Kernel module support for mips.

Reviewed by: gonzo

Tested by: Alexandr Rybalko (ray@dlink.ua)
This commit is contained in:
Neel Natu 2010-02-18 05:49:52 +00:00
parent 35873dcedb
commit 6f3c632700
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=204031
5 changed files with 74 additions and 103 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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);
}