summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2010-02-18 05:49:52 +0000
committerneel <neel@FreeBSD.org>2010-02-18 05:49:52 +0000
commitaa07cd309152c701760f95950436f1dac1e00016 (patch)
tree56e117e71722a097ba68b1b876cb693097f96568
parentffb08c6fd3e283de1c77c3ac7c8834a367b7f6c7 (diff)
downloadFreeBSD-src-aa07cd309152c701760f95950436f1dac1e00016.zip
FreeBSD-src-aa07cd309152c701760f95950436f1dac1e00016.tar.gz
Kernel module support for mips.
Reviewed by: gonzo Tested by: Alexandr Rybalko (ray@dlink.ua)
-rw-r--r--share/mk/bsd.cpu.mk2
-rw-r--r--sys/conf/files.mips2
-rw-r--r--sys/conf/kmod.mk11
-rw-r--r--sys/kern/link_elf_obj.c4
-rw-r--r--sys/mips/mips/elf_machdep.c158
5 files changed, 74 insertions, 103 deletions
diff --git a/share/mk/bsd.cpu.mk b/share/mk/bsd.cpu.mk
index 8278d47..61872ff 100644
--- a/share/mk/bsd.cpu.mk
+++ b/share/mk/bsd.cpu.mk
@@ -203,11 +203,9 @@ LD += -EB
.if ${MACHINE_ARCH} == "mips"
. if defined(TARGET_BIG_ENDIAN)
CFLAGS += -EB
-LDFLAGS += -Wl,-EB
LD += -EB
. else
CFLAGS += -EL
-LDFLAGS += -Wl,-EL
LD += -EL
. endif
CFLAGS += -msoft-float -G0 -mno-dsp -mabicalls
diff --git a/sys/conf/files.mips b/sys/conf/files.mips
index 6b2ece4..63d93ef 100644
--- a/sys/conf/files.mips
+++ b/sys/conf/files.mips
@@ -89,6 +89,8 @@ libkern/umoddi3.c optional isa_mips32
#libkern/mips/strcmp.S standard
#libkern/mips/strncmp.S standard
+kern/link_elf_obj.c standard
+
dev/cfe/cfe_api.c optional cfe
dev/cfe/cfe_console.c optional cfe_console
dev/cfe/cfe_env.c optional cfe_env
diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk
index 1c788a3..6d543e4 100644
--- a/sys/conf/kmod.mk
+++ b/sys/conf/kmod.mk
@@ -128,6 +128,10 @@ CFLAGS+= -fno-omit-frame-pointer
CFLAGS+= -mlongcall -fno-omit-frame-pointer
.endif
+.if ${MACHINE_ARCH} == "mips"
+CFLAGS+= -G0 -fno-pic -mno-abicalls -mlong-calls
+.endif
+
.if defined(FIRMWS)
.if !exists(@)
${KMOD:S/$/.c/}: @
@@ -174,7 +178,7 @@ ${PROG}.symbols: ${FULLPROG}
${OBJCOPY} --only-keep-debug ${FULLPROG} ${.TARGET}
.endif
-.if ${MACHINE_ARCH} != amd64
+.if ${MACHINE_ARCH} != amd64 && ${MACHINE_ARCH} != mips
${FULLPROG}: ${KMOD}.kld
${LD} -Bshareable ${LDFLAGS} -o ${.TARGET} ${KMOD}.kld
.if !defined(DEBUG_FLAGS)
@@ -187,7 +191,7 @@ EXPORT_SYMS?= NO
CLEANFILES+= export_syms
.endif
-.if ${MACHINE_ARCH} != amd64
+.if ${MACHINE_ARCH} != amd64 && ${MACHINE_ARCH} != mips
${KMOD}.kld: ${OBJS}
.else
${FULLPROG}: ${OBJS}
@@ -206,7 +210,8 @@ ${FULLPROG}: ${OBJS}
export_syms | xargs -J% ${OBJCOPY} % ${.TARGET}
.endif
.endif
-.if !defined(DEBUG_FLAGS) && ${MACHINE_ARCH} == amd64
+.if !defined(DEBUG_FLAGS) && \
+ (${MACHINE_ARCH} == amd64 || ${MACHINE_ARCH} == mips)
${OBJCOPY} --strip-debug ${.TARGET}
.endif
diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
index 68c60d8..a337fd0 100644
--- a/sys/kern/link_elf_obj.c
+++ b/sys/kern/link_elf_obj.c
@@ -853,8 +853,8 @@ link_elf_load_file(linker_class_t cls, const char *filename,
panic("lost relatab");
if (mapbase != (vm_offset_t)ef->address + mapsize)
panic("mapbase 0x%lx != address %p + mapsize 0x%lx (0x%lx)\n",
- mapbase, ef->address, mapsize,
- (vm_offset_t)ef->address + mapsize);
+ (u_long)mapbase, ef->address, (u_long)mapsize,
+ (u_long)(vm_offset_t)ef->address + mapsize);
/* Local intra-module relocations */
link_elf_reloc_local(lf);
diff --git a/sys/mips/mips/elf_machdep.c b/sys/mips/mips/elf_machdep.c
index 54c31e5..90e3dac 100644
--- a/sys/mips/mips/elf_machdep.c
+++ b/sys/mips/mips/elf_machdep.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <machine/elf.h>
#include <machine/md_var.h>
+#include <machine/cache.h>
#ifdef __mips_n64
struct sysentvec elf64_freebsd_sysvec = {
@@ -163,7 +164,12 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
Elf_Addr addend = (Elf_Addr)0;
Elf_Word rtype = (Elf_Word)0, symidx;
const Elf_Rel *rel;
- const Elf_Rela *rela;
+
+ /*
+ * Stash R_MIPS_HI16 info so we can use it when processing R_MIPS_LO16
+ */
+ static Elf_Addr ahl;
+ static Elf_Addr *where_hi16;
switch (type) {
case ELF_RELOC_REL:
@@ -173,108 +179,63 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
rtype = ELF_R_TYPE(rel->r_info);
symidx = ELF_R_SYM(rel->r_info);
break;
- case ELF_RELOC_RELA:
- rela = (const Elf_Rela *)data;
- where = (Elf_Addr *) (relocbase + rela->r_offset);
- addend = rela->r_addend;
- rtype = ELF_R_TYPE(rela->r_info);
- symidx = ELF_R_SYM(rela->r_info);
- break;
default:
panic("unknown reloc type %d\n", type);
}
- if (local) {
-#if 0 /* TBD */
- if (rtype == R_386_RELATIVE) { /* A + B */
- addr = elf_relocaddr(lf, relocbase + addend);
- if (*where != addr)
- *where = addr;
- }
- return (0);
-#endif
- }
-
switch (rtype) {
+ case R_MIPS_NONE: /* none */
+ break;
- case R_MIPS_NONE: /* none */
- break;
-
- case R_MIPS_16: /* S + sign-extend(A) */
- /*
- * There shouldn't be R_MIPS_16 relocs in kernel objects.
- */
- printf("kldload: unexpected R_MIPS_16 relocation\n");
- return -1;
- break;
-
- case R_MIPS_32: /* S + A - P */
- addr = lookup(lf, symidx, 1);
- if (addr == 0)
- return -1;
- addr += addend;
- if (*where != addr)
- *where = addr;
- break;
-
- case R_MIPS_REL32: /* A - EA + S */
- /*
- * There shouldn't be R_MIPS_REL32 relocs in kernel objects?
- */
- printf("kldload: unexpected R_MIPS_REL32 relocation\n");
- return -1;
- break;
-
- case R_MIPS_26: /* ((A << 2) | (P & 0xf0000000) + S) >> 2 */
- break;
-
- case R_MIPS_HI16:
- /* extern/local: ((AHL + S) - ((short)(AHL + S)) >> 16 */
- /* _gp_disp: ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16 */
- break;
-
- case R_MIPS_LO16:
- /* extern/local: AHL + S */
- /* _gp_disp: AHL + GP - P + 4 */
- break;
-
- case R_MIPS_GPREL16:
- /* extern/local: ((AHL + S) - ((short)(AHL + S)) >> 16 */
- /* _gp_disp: ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16 */
- break;
-
- case R_MIPS_LITERAL: /* sign-extend(A) + L */
- break;
-
- case R_MIPS_GOT16: /* external: G */
- /* local: tbd */
- break;
-
- case R_MIPS_PC16: /* sign-extend(A) + S - P */
- break;
-
- case R_MIPS_CALL16: /* G */
- break;
-
- case R_MIPS_GPREL32: /* A + S + GP0 - GP */
- break;
-
- case R_MIPS_GOTHI16: /* (G - (short)G) >> 16 + A */
- break;
-
- case R_MIPS_GOTLO16: /* G & 0xffff */
- break;
-
- case R_MIPS_CALLHI16: /* (G - (short)G) >> 16 + A */
- break;
-
- case R_MIPS_CALLLO16: /* G & 0xffff */
- break;
-
- default:
- printf("kldload: unexpected relocation type %d\n",
- rtype);
+ case R_MIPS_32: /* S + A */
+ addr = lookup(lf, symidx, 1);
+ if (addr == 0)
return (-1);
+ addr += addend;
+ if (*where != addr)
+ *where = addr;
+ break;
+
+ case R_MIPS_26: /* ((A << 2) | (P & 0xf0000000) + S) >> 2 */
+ addr = lookup(lf, symidx, 1);
+ if (addr == 0)
+ return (-1);
+
+ addend &= 0x03ffffff;
+ addend <<= 2;
+
+ addr += ((Elf_Addr)where & 0xf0000000) | addend;
+ addr >>= 2;
+
+ *where &= ~0x03ffffff;
+ *where |= addr & 0x03ffffff;
+ break;
+
+ case R_MIPS_HI16: /* ((AHL + S) - ((short)(AHL + S)) >> 16 */
+ ahl = addend << 16;
+ where_hi16 = where;
+ break;
+
+ case R_MIPS_LO16: /* AHL + S */
+ ahl += (int16_t)addend;
+ addr = lookup(lf, symidx, 1);
+ if (addr == 0)
+ return (-1);
+
+ addend &= 0xffff0000;
+ addend |= (uint16_t)(ahl + addr);
+ *where = addend;
+
+ addend = *where_hi16;
+ addend &= 0xffff0000;
+ addend |= ((ahl + addr) - (int16_t)(ahl + addr)) >> 16;
+ *where_hi16 = addend;
+ break;
+
+ default:
+ printf("kldload: unexpected relocation type %d\n",
+ rtype);
+ return (-1);
}
return(0);
}
@@ -299,6 +260,11 @@ int
elf_cpu_load_file(linker_file_t lf __unused)
{
+ /*
+ * Sync the I and D caches to make sure our relocations are visible.
+ */
+ mips_icache_sync_all();
+
return (0);
}
OpenPOWER on IntegriCloud