Fix vm86 initialization, part 1 of 2 and a half.

vm86 uses the tss, but r273995 moved tss initialization to after where
it may be first used, just because tss_esp0 now depends on later
initializations and/or amd64 does it later.

vm86 is first used for memory sizing in cases where the loader can't
figure out the size or is not used.  Its initialization is placed
immediately before memory sizing to support this, and the tss was
initialized a little earlier.

Move everything in the tss initialization except for tss_esp0 back to
almost where it was, immediately before vm86 initialization (the
combined move is from before dblflt_tss initialization to after).  Add
only early initialization of tss_esp0, later reloading of the tss, and
comments.  The initial tss_esp0 no longer has space for the pcb since
initially the size of the pcb is not known and no pcb is needed.
(Later changes broke debugging at this point, so the nonexistent pcb
cannot be used by debuggers, and at the time of 273995 when ddb was
almost able to debug this problem it didn't need the pcb.)  The
iniitial tss_esp0 still has a magic 16 bytes reserved for vm86
although I think this is unused too.
This commit is contained in:
Bruce Evans 2016-08-28 14:03:25 +00:00
parent 787650cde6
commit 441ead70cd

View File

@ -2636,6 +2636,16 @@ init386(first)
dblfault_tss.tss_cs = GSEL(GCODE_SEL, SEL_KPL);
dblfault_tss.tss_ldt = GSEL(GLDT_SEL, SEL_KPL);
/* 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);
vm86_initialize();
getmemsize(first);
init_param2(physmem);
@ -2701,14 +2711,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 */