Received: by 10.213.65.68 with SMTP id h4csp1061378imn; Sun, 18 Mar 2018 13:00:03 -0700 (PDT) X-Google-Smtp-Source: AG47ELuBspptEBGSbDHtoBFKVAauN/RRA0JtSDzH7A2T3o2Nn2HJUGs38VUoOtHW6L7sX0+3bqGK X-Received: by 2002:a17:902:6b48:: with SMTP id g8-v6mr2684199plt.273.1521403203865; Sun, 18 Mar 2018 13:00:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521403203; cv=none; d=google.com; s=arc-20160816; b=FE63VU5hJpksw2C45FF+AMe9yNKGM+wG73yPilKqnsJ1d6ud+Uo7Yfuqfv4EHXcyvI cpLFVylJ6wpi0qfWnjlNGfvgYPC48BFvERJkyV1CSfCPiH6+6vEaC3jzbu1uNjOZ+lgV JFvpcqeW0TU10xLl4ZxR+gXycogtzKmCyB6a2bGJJC5m676EBEUbsd9dcM8lV6OSrsUn mDoDot3mbmOR2kpIjFbY5QOFsutdvt2vdovqqg0Przd7uOeQJAIDyr2ZkN9SA8nLt7xh 3tSl7dGTgTBCYwBOnn0fc68Yxz/arv2XBHaovUhVBCL9rgUjq2nthqpp7I9H9VQWXI+P bH7Q== 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 :arc-authentication-results; bh=Un0xCzpj6WOKY/i5JxIYzq/rYpyMuI5EfMC8l/FaNsI=; b=J0hZ4DwF9MRsyeCLtQCayCDRY7xKYcssSHmcqr9E8FtYUxKt4WC6AC3E+UeDB7b4P0 mBrBo2SdNyLvS5gfOjBpbZz1Kqj7J3qe503dDDIzXSqJhhYvNo3AWnA7TLiqSt+mwz44 ves/vh5E02BR9GpI1PW1FnPHp0syVbwYWYO8OkHkbFQJeYSoGzvMye06D9XMWHcFWmlo 5RZrf+M/tlqFx9wwXosjGyv5+1icNUGLT1DxmgtCcFwmVbCh4KFQkYJZilSfN98m1kB1 cAHSGDtVW5/ntjXCBIFaTUpKV4L1lV+DgqbTrPWdJhEroZsaIkvvtLOoLEONVwUKrzP0 C2QA== 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 91-v6si10557539pla.473.2018.03.18.12.59.49; Sun, 18 Mar 2018 13:00:03 -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 S1754539AbeCRTwf (ORCPT + 99 others); Sun, 18 Mar 2018 15:52:35 -0400 Received: from mail139-37.mail.alibaba.com ([198.11.139.37]:14439 "EHLO mail139-37.mail.alibaba.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754454AbeCRTw2 (ORCPT ); Sun, 18 Mar 2018 15:52:28 -0400 X-Alimail-AntiSpam: AC=CONTINUE;BC=0.02444197|-1;CH=green;FP=0|0|0|0|0|-1|-1|-1;HT=e01l07447;MF=ren_guo@c-sky.com;NM=1;PH=DS;RN=11;RT=11;SR=0;TI=SMTPD_---.BMC5Edc_1521402719; Received: from localhost(mailfrom:ren_guo@c-sky.com fp:183.159.50.56) by smtp.aliyun-inc.com(10.147.40.2); Mon, 19 Mar 2018 03:51:59 +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 Cc: c-sky_gcc_upstream@c-sky.com, gnu-csky@mentor.com, thomas.petazzoni@bootlin.com, wbx@uclibc-ng.org, Guo Ren Subject: [PATCH 08/19] csky: ELF and module probe Date: Mon, 19 Mar 2018 03:51:30 +0800 Message-Id: <9cff9d50d77972e9a4952eefd26bb372b2325d83.1521399976.git.ren_guo@c-sky.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: References: 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 | 151 ++++++++++++++++++++++++++++++++++++++++++++ arch/csky/kernel/module.c | 130 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 281 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..f63a45d --- /dev/null +++ b/arch/csky/include/asm/elf.h @@ -0,0 +1,151 @@ +// 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 +#include + +#define ELF_ARCH 39 + +/* 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; + + +#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t)) + +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef struct user_cskyfp_struct elf_fpregset_t; + +/* + * 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] = rdusp(); \ + pr_reg[17] = regs->r15; \ + 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->exregs[15]; +#else + #define ELF_CORE_COPY_REGS(pr_reg, regs) \ + pr_reg[0] = regs->pc; \ + pr_reg[1] = regs->regs[9]; \ + pr_reg[2] = rdusp(); \ + 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->r15; +#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..ca68315 --- /dev/null +++ b/arch/csky/kernel/module.c @@ -0,0 +1,130 @@ +// 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) | 0x0019; \ + *((uint16_t *)(addr) + 1) = *((uint16_t *)(addr) + 1) & 0xFFFF +#define SET_JSR32_R25(addr) *(uint16_t *)(addr) = 0xE8F9; \ + *((uint16_t *)(addr) + 1) = 0x0000; + +int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, unsigned int symindex, + unsigned int relsec, struct module *me) +{ + unsigned int i; + Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; + Elf32_Sym *sym; + uint32_t *location; + short * temp; + + 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_NONE: + case R_CSKY_PCRELJSR_IMM11BY2: + case R_CSKY_PCRELJSR_IMM26BY2: + /* ignore */ + break; + case R_CSKY_32: + /* We add the value into the location given */ + *location += sym->st_value; + break; + case R_CSKY_PC32: + /* Add the value, subtract its postition */ + *location += sym->st_value - (uint32_t)location; + break; + case R_CSKY_ADDR_HI16: + temp = ((short *)location) + 1; + *temp = (short)((sym->st_value) >> 16); + break; + case R_CSKY_ADDR_LO16: + temp = ((short *)location) + 1; + *temp = (short)((sym->st_value) & 0xffff); + break; + default: + printk(KERN_ERR "module %s: Unknown relocation: %u\n", + me->name, ELF32_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} + +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 r25, 0x... */ + CHANGE_JSRI_TO_LRW(location); + /* lsli r0, r0 --> jsr r25 */ + SET_JSR32_R25(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: + printk(KERN_ERR "module %s: Unknown relocation: %u\n", + me->name, ELF32_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} -- 2.7.4