* 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.
This commit is contained in:
Doug Rabson 2001-09-13 12:39:15 +00:00
parent ed1e8460bd
commit 0b02d706db
7 changed files with 300 additions and 74 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -386,17 +386,24 @@ 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.
*/

View File

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