diff options
author | dfr <dfr@FreeBSD.org> | 2001-09-13 12:39:15 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 2001-09-13 12:39:15 +0000 |
commit | 7b40715e824711834ec0f89ba4f0881f57b4d53a (patch) | |
tree | ab02773c4b2a2195943d3ed2c2e6e839872dab3b /sys | |
parent | 5903e1d51b427659e37c7d4e10c090e5783f52da (diff) | |
download | FreeBSD-src-7b40715e824711834ec0f89ba4f0881f57b4d53a.zip FreeBSD-src-7b40715e824711834ec0f89ba4f0881f57b4d53a.tar.gz |
* Enable dynamically linked kernel. This involves adding a self-relocator
to locore to process the @fptr relocations in the dynamic executable.
* Don't initialise the timer until *after* we install the timecounter to
avoid a race between timecounter initialisation and hardclock.
* Tidy up bootinfo somewhat including adding sanity checks for when the
kernel is loaded without a recognisable bootinfo.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/conf/Makefile.ia64 | 2 | ||||
-rw-r--r-- | sys/ia64/ia64/clock.c | 5 | ||||
-rw-r--r-- | sys/ia64/ia64/genassym.c | 12 | ||||
-rw-r--r-- | sys/ia64/ia64/locore.S | 132 | ||||
-rw-r--r-- | sys/ia64/ia64/locore.s | 132 | ||||
-rw-r--r-- | sys/ia64/ia64/machdep.c | 85 | ||||
-rw-r--r-- | sys/ia64/include/bootinfo.h | 6 |
7 files changed, 300 insertions, 74 deletions
diff --git a/sys/conf/Makefile.ia64 b/sys/conf/Makefile.ia64 index 431ed93..30e4c6e 100644 --- a/sys/conf/Makefile.ia64 +++ b/sys/conf/Makefile.ia64 @@ -105,7 +105,7 @@ SYSTEM_CFILES= vnode_if.c hints.c env.c config.c SYSTEM_SFILES= $S/$M/$M/locore.s SYSTEM_DEP= Makefile ${SYSTEM_OBJS} SYSTEM_OBJS= locore.o vnode_if.o ${OBJS} hints.o env.o config.o \ - # hack.So ski can't cope with dynamic relocs + hack.So SYSTEM_LD= @${LD} ${FMT} -Bdynamic -T $S/conf/ldscript.$M \ -export-dynamic -dynamic-linker /red/herring \ -o ${.TARGET} -X ${SYSTEM_OBJS} vers.o diff --git a/sys/ia64/ia64/clock.c b/sys/ia64/ia64/clock.c index 0d686c5..fc3ad07 100644 --- a/sys/ia64/ia64/clock.c +++ b/sys/ia64/ia64/clock.c @@ -180,8 +180,6 @@ cpu_initclocks() * XXX we should call SAL_FREQ_BASE_INTERVAL_TIMER here. */ cycles_per_sec = 70000000; - ia64_set_itm(ia64_get_itc() + (cycles_per_sec + hz/2) / hz); - ia64_set_itv(240); /* highest priority class */ freq = cycles_per_sec; last_time = ia64_get_itc(); @@ -191,6 +189,9 @@ cpu_initclocks() ia64_timecounter.tc_frequency = freq; tc_init(&ia64_timecounter); + ia64_set_itm(ia64_get_itc() + (cycles_per_sec + hz/2) / hz); + ia64_set_itv(240); /* highest priority class */ + stathz = 128; } diff --git a/sys/ia64/ia64/genassym.c b/sys/ia64/ia64/genassym.c index 0984c87..e8084bf 100644 --- a/sys/ia64/ia64/genassym.c +++ b/sys/ia64/ia64/genassym.c @@ -52,6 +52,7 @@ #include <sys/ucontext.h> #include <machine/frame.h> #include <machine/mutex.h> +#include <machine/elf.h> #include <sys/vmmeter.h> #include <vm/vm.h> #include <vm/vm_param.h> @@ -139,3 +140,14 @@ ASSYM(KSTACK_PAGES, KSTACK_PAGES); ASSYM(SIZEOF_TRAPFRAME, sizeof(struct trapframe)); ASSYM(SIZEOF_PCB, sizeof(struct pcb)); + +ASSYM(DT_NULL, DT_NULL); +ASSYM(DT_RELA, DT_RELA); +ASSYM(DT_RELASZ, DT_RELASZ); +ASSYM(DT_SYMTAB, DT_SYMTAB); +ASSYM(DT_SYMENT, DT_SYMENT); +ASSYM(DT_RELAENT, DT_RELAENT); +ASSYM(R_IA64_NONE, R_IA64_NONE); +ASSYM(R_IA64_DIR64LSB, R_IA64_DIR64LSB); +ASSYM(R_IA64_FPTR64LSB, R_IA64_FPTR64LSB); +ASSYM(R_IA64_REL64LSB, R_IA64_REL64LSB); diff --git a/sys/ia64/ia64/locore.S b/sys/ia64/ia64/locore.S index 55c0816..aaeb184 100644 --- a/sys/ia64/ia64/locore.S +++ b/sys/ia64/ia64/locore.S @@ -98,6 +98,12 @@ ENTRY(__start, 1) ;; mov ar.rsc=3 // turn rse back on ;; + alloc r16=ar.pfs,0,0,1,0 + ;; + movl out0=0 // we are linked at the right address + ;; // we just need to process fptrs + br.call.sptk.many rp=_reloc + ;; br.call.sptk.many rp=ia64_init /* @@ -219,3 +225,129 @@ EXPORT(intrcnt) .fill INTRCNT_COUNT + 1, 8, 0 EXPORT(eintrcnt) .text + + // in0: image base +STATIC_ENTRY(_reloc, 1) + alloc loc0=ar.pfs,1,2,0,0 + mov loc1=rp + ;; + movl r15=@gprel(_DYNAMIC) // find _DYNAMIC etc. + movl r2=@gprel(fptr_storage) + movl r3=@gprel(fptr_storage_end) + ;; + add r15=r15,gp // relocate _DYNAMIC etc. + add r2=r2,gp + add r3=r3,gp + ;; +1: ld8 r16=[r15],8 // read r15->d_tag + ;; + ld8 r17=[r15],8 // and r15->d_val + ;; + cmp.eq p6,p0=DT_NULL,r16 // done? +(p6) br.cond.dpnt.few 2f + ;; + cmp.eq p6,p0=DT_RELA,r16 + ;; +(p6) add r18=r17,in0 // found rela section + ;; + cmp.eq p6,p0=DT_RELASZ,r16 + ;; +(p6) mov r19=r17 // found rela size + ;; + cmp.eq p6,p0=DT_SYMTAB,r16 + ;; +(p6) add r20=r17,in0 // found symbol table + ;; +(p6) setf.sig f8=r20 + ;; + cmp.eq p6,p0=DT_SYMENT,r16 + ;; +(p6) setf.sig f9=r17 // found symbol entry size + ;; + cmp.eq p6,p0=DT_RELAENT,r16 + ;; +(p6) mov r22=r17 // found rela entry size + ;; + br.sptk.few 1b + +2: + ld8 r15=[r18],8 // read r_offset + ;; + ld8 r16=[r18],8 // read r_info + add r15=r15,in0 // relocate r_offset + ;; + ld8 r17=[r18],8 // read r_addend + sub r19=r19,r22 // update relasz + + extr.u r23=r16,0,32 // ELF64_R_TYPE(r16) + ;; + cmp.eq p6,p0=R_IA64_NONE,r23 +(p6) br.cond.dpnt.few 3f + ;; + cmp.eq p6,p0=R_IA64_DIR64LSB,r23 + ;; +(p6) br.cond.dptk.few 4f + ;; + cmp.eq p6,p0=R_IA64_FPTR64LSB,r23 + ;; +(p6) br.cond.dptk.few 5f + ;; + cmp.eq p6,p0=R_IA64_REL64LSB,r23 + ;; +(p6) br.cond.dptk.few 4f + ;; + +3: cmp.ltu p6,p0=0,r19 // more? +(p6) br.cond.dptk.few 2b // loop + + mov r8=0 // success return value + ;; + br.cond.sptk.few 9f // done + +4: + ld8 r16=[r15] // read value + ;; + add r16=r16,in0 // relocate it + ;; + st8 [r15]=r16 // and store it back + br.cond.sptk.few 3b + +5: + extr.u r23=r16,32,32 // ELF64_R_SYM(r16) + ;; + setf.sig f10=r23 // so we can multiply + ;; + xma.lu f10=f10,f9,f8 // f10=symtab + r_sym*syment + ;; + getf.sig r16=f10 + mov r8=1 // failure return value + ;; + cmp.geu p6,p0=r2,r3 // space left? +(p6) br.cond.dpnt.few 9f // bail out + + st8 [r15]=r2 // install fptr + add r16=8,r16 // address of st_value + ;; + ld8 r16=[r16] // read symbol value + ;; + add r16=r16,in0 // relocate symbol value + ;; + st8 [r2]=r16,8 // write fptr address + ;; + st8 [r2]=gp,8 // write fptr gp + br.cond.sptk.few 3b + +9: + mov ar.pfs=loc0 + mov rp=loc1 + ;; + br.ret.sptk.few rp + +END(_reloc) + + .data + .align 16 + +fptr_storage: + .space 4096*16 // XXX +fptr_storage_end: diff --git a/sys/ia64/ia64/locore.s b/sys/ia64/ia64/locore.s index 55c0816..aaeb184 100644 --- a/sys/ia64/ia64/locore.s +++ b/sys/ia64/ia64/locore.s @@ -98,6 +98,12 @@ ENTRY(__start, 1) ;; mov ar.rsc=3 // turn rse back on ;; + alloc r16=ar.pfs,0,0,1,0 + ;; + movl out0=0 // we are linked at the right address + ;; // we just need to process fptrs + br.call.sptk.many rp=_reloc + ;; br.call.sptk.many rp=ia64_init /* @@ -219,3 +225,129 @@ EXPORT(intrcnt) .fill INTRCNT_COUNT + 1, 8, 0 EXPORT(eintrcnt) .text + + // in0: image base +STATIC_ENTRY(_reloc, 1) + alloc loc0=ar.pfs,1,2,0,0 + mov loc1=rp + ;; + movl r15=@gprel(_DYNAMIC) // find _DYNAMIC etc. + movl r2=@gprel(fptr_storage) + movl r3=@gprel(fptr_storage_end) + ;; + add r15=r15,gp // relocate _DYNAMIC etc. + add r2=r2,gp + add r3=r3,gp + ;; +1: ld8 r16=[r15],8 // read r15->d_tag + ;; + ld8 r17=[r15],8 // and r15->d_val + ;; + cmp.eq p6,p0=DT_NULL,r16 // done? +(p6) br.cond.dpnt.few 2f + ;; + cmp.eq p6,p0=DT_RELA,r16 + ;; +(p6) add r18=r17,in0 // found rela section + ;; + cmp.eq p6,p0=DT_RELASZ,r16 + ;; +(p6) mov r19=r17 // found rela size + ;; + cmp.eq p6,p0=DT_SYMTAB,r16 + ;; +(p6) add r20=r17,in0 // found symbol table + ;; +(p6) setf.sig f8=r20 + ;; + cmp.eq p6,p0=DT_SYMENT,r16 + ;; +(p6) setf.sig f9=r17 // found symbol entry size + ;; + cmp.eq p6,p0=DT_RELAENT,r16 + ;; +(p6) mov r22=r17 // found rela entry size + ;; + br.sptk.few 1b + +2: + ld8 r15=[r18],8 // read r_offset + ;; + ld8 r16=[r18],8 // read r_info + add r15=r15,in0 // relocate r_offset + ;; + ld8 r17=[r18],8 // read r_addend + sub r19=r19,r22 // update relasz + + extr.u r23=r16,0,32 // ELF64_R_TYPE(r16) + ;; + cmp.eq p6,p0=R_IA64_NONE,r23 +(p6) br.cond.dpnt.few 3f + ;; + cmp.eq p6,p0=R_IA64_DIR64LSB,r23 + ;; +(p6) br.cond.dptk.few 4f + ;; + cmp.eq p6,p0=R_IA64_FPTR64LSB,r23 + ;; +(p6) br.cond.dptk.few 5f + ;; + cmp.eq p6,p0=R_IA64_REL64LSB,r23 + ;; +(p6) br.cond.dptk.few 4f + ;; + +3: cmp.ltu p6,p0=0,r19 // more? +(p6) br.cond.dptk.few 2b // loop + + mov r8=0 // success return value + ;; + br.cond.sptk.few 9f // done + +4: + ld8 r16=[r15] // read value + ;; + add r16=r16,in0 // relocate it + ;; + st8 [r15]=r16 // and store it back + br.cond.sptk.few 3b + +5: + extr.u r23=r16,32,32 // ELF64_R_SYM(r16) + ;; + setf.sig f10=r23 // so we can multiply + ;; + xma.lu f10=f10,f9,f8 // f10=symtab + r_sym*syment + ;; + getf.sig r16=f10 + mov r8=1 // failure return value + ;; + cmp.geu p6,p0=r2,r3 // space left? +(p6) br.cond.dpnt.few 9f // bail out + + st8 [r15]=r2 // install fptr + add r16=8,r16 // address of st_value + ;; + ld8 r16=[r16] // read symbol value + ;; + add r16=r16,in0 // relocate symbol value + ;; + st8 [r2]=r16,8 // write fptr address + ;; + st8 [r2]=gp,8 // write fptr gp + br.cond.sptk.few 3b + +9: + mov ar.pfs=loc0 + mov rp=loc1 + ;; + br.ret.sptk.few rp + +END(_reloc) + + .data + .align 16 + +fptr_storage: + .space 4096*16 // XXX +fptr_storage_end: diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index e5af476..a956acf 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -387,16 +387,23 @@ ia64_init() /* OUTPUT NOW ALLOWED */ /* + * Gross and disgusting hack. The bootinfo is written into + * memory at a fixed address. + */ + bootinfo = *(struct bootinfo *) 0xe000000000508000; + if (bootinfo.bi_magic != BOOTINFO_MAGIC + || bootinfo.bi_version != 1) { + bzero(&bootinfo, sizeof(bootinfo)); + bootinfo.bi_kernend = (vm_offset_t) round_page(_end); + } + + /* * Find the beginning and end of the kernel. */ kernstart = trunc_page(kernel_text); -#ifdef DDBxx ksym_start = (void *)bootinfo.bi_symtab; ksym_end = (void *)bootinfo.bi_esymtab; kernend = (vm_offset_t)round_page(ksym_end); -#else - kernend = (vm_offset_t)round_page(_end); -#endif /* But if the bootstrap tells us otherwise, believe it! */ if (bootinfo.bi_kernend) kernend = round_page(bootinfo.bi_kernend); @@ -606,74 +613,10 @@ ia64_init() /* * Look at arguments passed to us and compute boothowto. */ - boothowto = 0; + boothowto = bootinfo.bi_boothowto; #ifdef KADB boothowto |= RB_KDB; #endif -/* boothowto |= RB_KDB | RB_GDB; */ - for (p = bootinfo.bi_flags; p && *p != '\0'; p++) { - /* - * Note that we'd really like to differentiate case here, - * but the Ia64 AXP Architecture Reference Manual - * says that we shouldn't. - */ - switch (*p) { - case 'a': /* autoboot */ - case 'A': - boothowto &= ~RB_SINGLE; - break; - -#ifdef DEBUG - case 'c': /* crash dump immediately after autoconfig */ - case 'C': - boothowto |= RB_DUMP; - break; -#endif - -#if defined(DDB) - case 'd': /* break into the kernel debugger ASAP */ - case 'D': - boothowto |= RB_KDB; - break; - case 'g': /* use kernel gdb */ - case 'G': - boothowto |= RB_GDB; - break; -#endif - - case 'h': /* always halt, never reboot */ - case 'H': - boothowto |= RB_HALT; - break; - -#if 0 - case 'm': /* mini root present in memory */ - case 'M': - boothowto |= RB_MINIROOT; - break; -#endif - - case 'n': /* askname */ - case 'N': - boothowto |= RB_ASKNAME; - break; - - case 's': /* single-user (default, supported for sanity) */ - case 'S': - boothowto |= RB_SINGLE; - break; - - case 'v': - case 'V': - boothowto |= RB_VERBOSE; - bootverbose = 1; - break; - - default: - printf("Unrecognized boot flag '%c'.\n", *p); - break; - } - } /* * Catch case of boot_verbose set in environment. @@ -681,10 +624,12 @@ ia64_init() if ((p = getenv("boot_verbose")) != NULL) { if (strcmp(p, "yes") == 0 || strcmp(p, "YES") == 0) { boothowto |= RB_VERBOSE; - bootverbose = 1; } } + if (boothowto & RB_VERBOSE) + bootverbose = 1; + /* * Force single-user for a while. */ diff --git a/sys/ia64/include/bootinfo.h b/sys/ia64/include/bootinfo.h index c148120..d5914f8 100644 --- a/sys/ia64/include/bootinfo.h +++ b/sys/ia64/include/bootinfo.h @@ -41,9 +41,13 @@ * (u_long), then the bootinfo */ +#define BOOTINFO_MAGIC 0xdeadbeeffeedface + struct bootinfo { - char bi_flags[64]; /* boot flags */ + u_int64_t bi_magic; /* BOOTINFO_MAGIC */ + u_int64_t bi_version; /* version 1 */ char bi_kernel[64]; /* name of booted kernel */ + u_int64_t bi_boothowto; /* value for boothowto */ u_int64_t bi_systab; /* pa of EFI system table */ u_int64_t bi_memmap; /* pa of EFI memory map */ u_int64_t bi_memmap_size; /* size of EFI memory map */ |