diff options
author | kib <kib@FreeBSD.org> | 2016-12-28 04:48:30 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2016-12-28 04:48:30 +0000 |
commit | c500fe201f75cd47504133e46fa0c60a43ec6973 (patch) | |
tree | 921f70b9fa0bf557047d9bb853c1ba019e19cb97 | |
parent | c7359d9413c3c0507304ec9530281a7954b3b877 (diff) | |
download | FreeBSD-src-c500fe201f75cd47504133e46fa0c60a43ec6973.zip FreeBSD-src-c500fe201f75cd47504133e46fa0c60a43ec6973.tar.gz |
MFC r304957, r304958, r306310 (by bde):
Fix vm86 initialization.
MFC r310050:
Improve very early trap handling on amd64.
-rw-r--r-- | sys/amd64/amd64/machdep.c | 48 | ||||
-rw-r--r-- | sys/i386/i386/machdep.c | 83 |
2 files changed, 95 insertions, 36 deletions
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 5664b3d..18484e6 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -1506,6 +1506,16 @@ native_parse_preload_data(u_int64_t modulep) return (kmdp); } +static void +amd64_kdb_init(void) +{ + kdb_init(); +#ifdef KDB + if (boothowto & RB_KDB) + kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); +#endif +} + u_int64_t hammer_time(u_int64_t modulep, u_int64_t physfree) { @@ -1517,6 +1527,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) u_int64_t msr; char *env; size_t kstack0_sz; + int late_console; /* * This may be done better later if it gets more high level @@ -1561,6 +1572,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) physfree += DPCPU_SIZE; PCPU_SET(prvspace, pc); PCPU_SET(curthread, &thread0); + /* Non-late cninit() and printf() can be moved up to here. */ PCPU_SET(tssp, &common_tss[0]); PCPU_SET(commontssp, &common_tss[0]); PCPU_SET(tss, (struct system_segment_descriptor *)&gdt[GPROC0_SEL]); @@ -1660,12 +1672,36 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) wrmsr(MSR_STAR, msr); wrmsr(MSR_SF_MASK, PSL_NT|PSL_T|PSL_I|PSL_C|PSL_D); + /* + * Temporary forge some valid pointer to PCB, for exception + * handlers. It is reinitialized properly below after FPU is + * set up. Also set up td_critnest to short-cut the page + * fault handler. + */ + cpu_max_ext_state_size = sizeof(struct savefpu); + thread0.td_pcb = get_pcb_td(&thread0); + thread0.td_critnest = 1; + + /* + * The console and kdb should be initialized even earlier than here, + * but some console drivers don't work until after getmemsize(). + * Default to late console initialization to support these drivers. + * This loses mainly printf()s in getmemsize() and early debugging. + */ + late_console = 1; + TUNABLE_INT_FETCH("debug.late_console", &late_console); + if (!late_console) { + cninit(); + amd64_kdb_init(); + } + getmemsize(kmdp, physfree); init_param2(physmem); /* now running on new page tables, configured,and u/iom is accessible */ - cninit(); + if (late_console) + cninit(); #ifdef DEV_ISA #ifdef DEV_ATPIC @@ -1686,13 +1722,8 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) #error "have you forgotten the isa device?"; #endif - kdb_init(); - -#ifdef KDB - if (boothowto & RB_KDB) - kdb_enter(KDB_WHY_BOOTFLAGS, - "Boot flags requested debugger"); -#endif + if (late_console) + amd64_kdb_init(); msgbufinit(msgbufp, msgbufsize); fpuinit(); @@ -1741,6 +1772,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) #ifdef FDT x86_init_fdt(); #endif + thread0.td_critnest = 0; /* Location of kernel stack for locore */ return ((u_int64_t)thread0.td_pcb); diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 89e67a5..9200d00 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -2089,7 +2089,6 @@ getmemsize(int first) * use that and do not make any VM86 calls. */ physmap_idx = 0; - smapbase = NULL; kmdp = preload_search_by_type("elf kernel"); if (kmdp == NULL) kmdp = preload_search_by_type("elf32 kernel"); @@ -2223,6 +2222,9 @@ physmap_done: * highest page of the physical address space. It should be * called something like "Maxphyspage". We may adjust this * based on ``hw.physmem'' and the results of the memory test. + * + * This is especially confusing when it is much larger than the + * memory size and is displayed as "realmem". */ Maxmem = atop(physmap[physmap_idx + 1]); @@ -2428,6 +2430,19 @@ do_next: } #endif /* PC98 */ +static void +i386_kdb_init(void) +{ +#ifdef DDB + db_fetch_ksymtab(bootinfo.bi_symtab, bootinfo.bi_esymtab); +#endif + kdb_init(); +#ifdef KDB + if (boothowto & RB_KDB) + kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); +#endif +} + register_t init386(first) int first; @@ -2438,6 +2453,7 @@ init386(first) #ifdef CPU_ENABLE_SSE struct xstate_hdr *xhdr; #endif + int late_console; thread0.td_kstack = proc0kstack; thread0.td_kstack_pages = TD0_KSTACK_PAGES; @@ -2502,6 +2518,7 @@ init386(first) first += DPCPU_SIZE; PCPU_SET(prvspace, pc); PCPU_SET(curthread, &thread0); + /* Non-late cninit() and printf() can be moved up to here. */ /* * Initialize mutexes. @@ -2636,20 +2653,17 @@ init386(first) dblfault_tss.tss_cs = GSEL(GCODE_SEL, SEL_KPL); dblfault_tss.tss_ldt = GSEL(GLDT_SEL, SEL_KPL); - vm86_initialize(); - getmemsize(first); - init_param2(physmem); - - /* now running on new page tables, configured,and u/iom is accessible */ - - /* - * Initialize the console before we print anything out. - */ - cninit(); - - if (metadata_missing) - printf("WARNING: loader(8) metadata is missing!\n"); + /* Initialize the tss (except for the final esp0) early for vm86. */ + PCPU_SET(common_tss.tss_esp0, thread0.td_kstack + + thread0.td_kstack_pages * PAGE_SIZE - 16); + PCPU_SET(common_tss.tss_ss0, GSEL(GDATA_SEL, SEL_KPL)); + gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); + PCPU_SET(tss_gdt, &gdt[GPROC0_SEL].sd); + PCPU_SET(common_tssd, *PCPU_GET(tss_gdt)); + PCPU_SET(common_tss.tss_ioopt, (sizeof (struct i386tss)) << 16); + ltr(gsel_tss); + /* Initialize the PIC early for vm86 calls. */ #ifdef DEV_ISA #ifdef DEV_ATPIC #ifndef PC98 @@ -2671,16 +2685,33 @@ init386(first) #endif #endif -#ifdef DDB - db_fetch_ksymtab(bootinfo.bi_symtab, bootinfo.bi_esymtab); -#endif + /* + * The console and kdb should be initialized even earlier than here, + * but some console drivers don't work until after getmemsize(). + * Default to late console initialization to support these drivers. + * This loses mainly printf()s in getmemsize() and early debugging. + */ + late_console = 1; + TUNABLE_INT_FETCH("debug.late_console", &late_console); + if (!late_console) { + cninit(); + i386_kdb_init(); + } - kdb_init(); + vm86_initialize(); + getmemsize(first); + init_param2(physmem); -#ifdef KDB - if (boothowto & RB_KDB) - kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); -#endif + /* now running on new page tables, configured,and u/iom is accessible */ + + if (late_console) + cninit(); + + if (metadata_missing) + printf("WARNING: loader(8) metadata is missing!\n"); + + if (late_console) + i386_kdb_init(); msgbufinit(msgbufp, msgbufsize); #ifdef DEV_NPX @@ -2701,14 +2732,10 @@ init386(first) } #endif PCPU_SET(curpcb, thread0.td_pcb); - /* make an initial tss so cpu can get interrupt stack on syscall! */ + /* Move esp0 in the tss to its final place. */ /* Note: -16 is so we can grow the trapframe if we came from vm86 */ PCPU_SET(common_tss.tss_esp0, (vm_offset_t)thread0.td_pcb - 16); - PCPU_SET(common_tss.tss_ss0, GSEL(GDATA_SEL, SEL_KPL)); - gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); - PCPU_SET(tss_gdt, &gdt[GPROC0_SEL].sd); - PCPU_SET(common_tssd, *PCPU_GET(tss_gdt)); - PCPU_SET(common_tss.tss_ioopt, (sizeof (struct i386tss)) << 16); + gdt[GPROC0_SEL].sd.sd_type = SDT_SYS386TSS; /* clear busy bit */ ltr(gsel_tss); /* make a call gate to reenter kernel with */ |