Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp5566993imm; Wed, 12 Sep 2018 07:53:46 -0700 (PDT) X-Google-Smtp-Source: ANB0VdZey1IiPEKlcHBL9uB5KZB1Q9YmUKioQUR6Z8ee1u/Hisd+BkJz2gCY1Vjmxj+PQOHOtzwk X-Received: by 2002:a63:4c02:: with SMTP id z2-v6mr2832404pga.312.1536764025974; Wed, 12 Sep 2018 07:53:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1536764025; cv=none; d=google.com; s=arc-20160816; b=RuUTg6u/bBNFgva+7mc5e+U64C1M+WYGNd+FPbRU7iAVnnTx3K7LJsHylfq/UJupKv fGVN6X0riwL4dfw92g5Ite8tgCovgmXbtUQHH90f4w6Vz9oWGI/BOr9rCNwU+m6kDuRy +VcNUj3c5Zx64HR2QoYoQFvCFHx8YF+gE4MopGb0HtifmAE3gd3ydvlWSJTt6Q+sg12G qt3Opis8sbjV1VOr8ixL/C+qgO8oIsys2RpeZDaXrBhLn5B+GOntpcydHRkbrhaRNfQT L8+rJGQgCd6I7Fi0LmB2heCH8Cv2RtQ8FLHikrheOFlsVxNnuTaB7ohWUT4AgZ7Dl8W0 XFQQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from; bh=hBQLLJRXO/dqOWF2Z7LNF4ts7t6aAjs6sGYUVB2Ta0A=; b=E9KcbhY9cSuaSv8eH8I/RskBe23d5t6v5Km4xJU4LflHUpWLQva8ev4LuSGSabT/+g xCTlAq5rjWnuCoEttqGoQ3CS6brDuNS+exmUOlx/5fEPIleymucA1CyXiQnzE3cSScB5 //LFIoslG4g5CyqUggt13t+j8NzKyLyj3ZdKLwSRzKONytHVPSyASlJT+3SFptkTbIzL gjdm5Pf6TtyylkVTmSsv2sLgQMoi36JNOzKTqVQ7+A57OeVBsOE26YkKM+dU5chIZGWP tJtZ6eQOn2GPx5enZ5Iey0wkKw7ge45AdtTXtIET8CDzqXInPar2wVMqKiT/8z9w+DsY WNbQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a8-v6si1487884pgm.201.2018.09.12.07.53.18; Wed, 12 Sep 2018 07:53:45 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728199AbeILT5y (ORCPT + 99 others); Wed, 12 Sep 2018 15:57:54 -0400 Received: from smtp2200-217.mail.aliyun.com ([121.197.200.217]:46740 "EHLO smtp2200-217.mail.aliyun.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727623AbeILT5y (ORCPT ); Wed, 12 Sep 2018 15:57:54 -0400 X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07437672|-1;CH=blue;FP=509572069294087794|2|2|12|0|-1|-1|-1;HT=e02c03299;MF=ren_guo@c-sky.com;NM=1;PH=DS;RN=15;RT=15;SR=0;TI=SMTPD_---.CpxEHWh_1536763968; Received: from localhost(mailfrom:ren_guo@c-sky.com fp:SMTPD_---.CpxEHWh_1536763968) by smtp.aliyun-inc.com(10.147.41.137); Wed, 12 Sep 2018 22:52:48 +0800 From: Guo Ren To: linux-arch@vger.kernel.org, linux-kernel@vger.kernel.org, tglx@linutronix.de, daniel.lezcano@linaro.org, jason@lakedaemon.net, arnd@arndb.de, devicetree@vger.kernel.org, andrea.parri@amarulasolutions.com, peterz@infradead.org Cc: c-sky_gcc_upstream@c-sky.com, gnu-csky@mentor.com, thomas.petazzoni@bootlin.com, wbx@uclibc-ng.org, ren_guo@c-sky.com, green.hu@gmail.com Subject: [PATCH V4 12/27] csky: ELF and module probe Date: Wed, 12 Sep 2018 22:51:54 +0800 Message-Id: <302a170bc63665c7bdf71033233222d83e1298fb.1536758961.git.ren_guo@c-sky.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <93e8b592e429c156ad4d4ca5d85ef48fd0ab8b70.1536758961.git.ren_guo@c-sky.com> References: <93e8b592e429c156ad4d4ca5d85ef48fd0ab8b70.1536758961.git.ren_guo@c-sky.com> In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Signed-off-by: Guo Ren --- arch/csky/include/asm/elf.h | 149 ++++++++++++++++++++++++++++++++++++++++++++ arch/csky/kernel/module.c | 82 ++++++++++++++++++++++++ 2 files changed, 231 insertions(+) create mode 100644 arch/csky/include/asm/elf.h create mode 100644 arch/csky/kernel/module.c diff --git a/arch/csky/include/asm/elf.h b/arch/csky/include/asm/elf.h new file mode 100644 index 0000000..9eef4a1 --- /dev/null +++ b/arch/csky/include/asm/elf.h @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. +#ifndef __ASMCSKY_ELF_H +#define __ASMCSKY_ELF_H + +/* + * ELF register definitions.. + */ + +#include +#include + +#define ELF_ARCH 252 + +/* CSKY Relocations */ +#define R_CSKY_NONE 0 +#define R_CSKY_32 1 +#define R_CSKY_PCIMM8BY4 2 +#define R_CSKY_PCIMM11BY2 3 +#define R_CSKY_PCIMM4BY2 4 +#define R_CSKY_PC32 5 +#define R_CSKY_PCRELJSR_IMM11BY2 6 +#define R_CSKY_GNU_VTINHERIT 7 +#define R_CSKY_GNU_VTENTRY 8 +#define R_CSKY_RELATIVE 9 +#define R_CSKY_COPY 10 +#define R_CSKY_GLOB_DAT 11 +#define R_CSKY_JUMP_SLOT 12 +#define R_CSKY_ADDR_HI16 24 +#define R_CSKY_ADDR_LO16 25 +#define R_CSKY_PCRELJSR_IMM26BY2 40 + +typedef unsigned long elf_greg_t; + +typedef struct user_fp elf_fpregset_t; + +#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t)) + +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(x) ((x)->e_machine == ELF_ARCH) + +/* + * These are used to set parameters in the core dumps. + */ +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 4096 +#define ELF_CLASS ELFCLASS32 +#define ELF_PLAT_INIT(_r, load_addr) _r->a0 = 0 + +#ifdef __cskyBE__ +#define ELF_DATA ELFDATA2MSB +#else +#define ELF_DATA ELFDATA2LSB +#endif + +/* This is the location that an ET_DYN program is loaded if exec'ed. Typical + use of this is to invoke "./ld.so someprog" to test out a new version of + the loader. We need to make sure that it is out of the way of the program + that it will "exec", and that there is sufficient room for the brk. */ + +#define ELF_ET_DYN_BASE 0x0UL + +/* The member sort in array pr_reg[x] is pc, r1, r0, psr, r2, r3,r4, + r5, r6...... Because GDB difine */ +#if defined(__CSKYABIV2__) + #define ELF_CORE_COPY_REGS(pr_reg, regs) \ + pr_reg[0] = regs->pc; \ + pr_reg[1] = regs->a1; \ + pr_reg[2] = regs->a0; \ + pr_reg[3] = regs->sr; \ + pr_reg[4] = regs->a2; \ + pr_reg[5] = regs->a3; \ + pr_reg[6] = regs->regs[0]; \ + pr_reg[7] = regs->regs[1]; \ + pr_reg[8] = regs->regs[2]; \ + pr_reg[9] = regs->regs[3]; \ + pr_reg[10] = regs->regs[4]; \ + pr_reg[11] = regs->regs[5]; \ + pr_reg[12] = regs->regs[6]; \ + pr_reg[13] = regs->regs[7]; \ + pr_reg[14] = regs->regs[8]; \ + pr_reg[15] = regs->regs[9]; \ + pr_reg[16] = regs->usp; \ + pr_reg[17] = regs->lr; \ + pr_reg[18] = regs->exregs[0]; \ + pr_reg[19] = regs->exregs[1]; \ + pr_reg[20] = regs->exregs[2]; \ + pr_reg[21] = regs->exregs[3]; \ + pr_reg[22] = regs->exregs[4]; \ + pr_reg[23] = regs->exregs[5]; \ + pr_reg[24] = regs->exregs[6]; \ + pr_reg[25] = regs->exregs[7]; \ + pr_reg[26] = regs->exregs[8]; \ + pr_reg[27] = regs->exregs[9]; \ + pr_reg[28] = regs->exregs[10]; \ + pr_reg[29] = regs->exregs[11]; \ + pr_reg[30] = regs->exregs[12]; \ + pr_reg[31] = regs->exregs[13]; \ + pr_reg[32] = regs->exregs[14]; \ + pr_reg[33] = regs->tls; +#else + #define ELF_CORE_COPY_REGS(pr_reg, regs) \ + pr_reg[0] = regs->pc; \ + pr_reg[1] = regs->regs[9]; \ + pr_reg[2] = regs->usp; \ + pr_reg[3] = regs->sr; \ + pr_reg[4] = regs->a0; \ + pr_reg[5] = regs->a1; \ + pr_reg[6] = regs->a2; \ + pr_reg[7] = regs->a3; \ + pr_reg[8] = regs->regs[0]; \ + pr_reg[9] = regs->regs[1]; \ + pr_reg[10] = regs->regs[2]; \ + pr_reg[11] = regs->regs[3]; \ + pr_reg[12] = regs->regs[4]; \ + pr_reg[13] = regs->regs[5]; \ + pr_reg[14] = regs->regs[6]; \ + pr_reg[15] = regs->regs[7]; \ + pr_reg[16] = regs->regs[8]; \ + pr_reg[17] = regs->lr; +#endif + +/* Similar, but for a thread other than current. */ +struct task_struct; +extern int dump_task_regs(struct task_struct *, elf_gregset_t *); +#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs) + +/* This yields a mask that user programs can use to figure out what + instruction set this cpu supports. */ + +#define ELF_HWCAP (0) + +/* This yields a string that ld.so will use to load implementation + specific libraries for optimization. This is more specific in + intent than poking at uname or /proc/cpuinfo. */ + +#define ELF_PLATFORM (NULL) +#define SET_PERSONALITY(ex) set_personality(PER_LINUX) +#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 +struct linux_binprm; +extern int arch_setup_additional_pages( + struct linux_binprm *bprm, + int uses_interp); + +#endif diff --git a/arch/csky/kernel/module.c b/arch/csky/kernel/module.c new file mode 100644 index 0000000..a8816e1 --- /dev/null +++ b/arch/csky/kernel/module.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IS_BSR32(hi16, lo16) (((hi16) & 0xFC00) == 0xE000) +#define IS_JSRI32(hi16, lo16) ((hi16) == 0xEAE0) +#define CHANGE_JSRI_TO_LRW(addr) *(uint16_t *)(addr) = (*(uint16_t *)(addr) & 0xFF9F) | 0x001a; \ + *((uint16_t *)(addr) + 1) = *((uint16_t *)(addr) + 1) & 0xFFFF +#define SET_JSR32_R26(addr) *(uint16_t *)(addr) = 0xE8Fa; \ + *((uint16_t *)(addr) + 1) = 0x0000; + +int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, + unsigned int symindex, unsigned int relsec, struct module *me) +{ + unsigned int i; + Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; + Elf32_Sym *sym; + uint32_t *location; + short * temp; +#ifdef CONFIG_CPU_CSKYV2 + uint16_t *location_tmp; +#endif + + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + + rel[i].r_offset; + /* This is the symbol it is referring to. Note that all + undefined symbols have been resolved. */ + sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + + ELF32_R_SYM(rel[i].r_info); + + switch (ELF32_R_TYPE(rel[i].r_info)) { + case R_CSKY_32: + /* We add the value into the location given */ + *location = rel[i].r_addend + sym->st_value; + break; + case R_CSKY_PC32: + /* Add the value, subtract its postition */ + *location = rel[i].r_addend + sym->st_value + - (uint32_t)location; + break; + case R_CSKY_PCRELJSR_IMM11BY2: + break; + case R_CSKY_PCRELJSR_IMM26BY2: +#ifdef CONFIG_CPU_CSKYV2 + location_tmp = (uint16_t *)location; + if (IS_BSR32(*location_tmp, *(location_tmp + 1))) + break; + else if (IS_JSRI32(*location_tmp, *(location_tmp + 1))) { + /* jsri 0x... --> lrw r26, 0x... */ + CHANGE_JSRI_TO_LRW(location); + /* lsli r0, r0 --> jsr r26 */ + SET_JSR32_R26(location + 1); + } +#endif + break; + case R_CSKY_ADDR_HI16: + temp = ((short *)location) + 1; + *temp = (short)((rel[i].r_addend + sym->st_value) >> 16); + break; + case R_CSKY_ADDR_LO16: + temp = ((short *)location) + 1; + *temp = (short)((rel[i].r_addend + sym->st_value) & 0xffff); + break; + default: + pr_err("module %s: Unknown relocation: %u\n", + me->name, ELF32_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} -- 2.7.4