|
Interestingly, the processor will indeed go into user mode, functioning just fine until a trap, interrupt, or system call occurs. Most other processors have dedicated register sets to locate the kernel stack in these cases. But the 386 designers conceptualized ring crossings (user <-> kernel mode) like that of task switches. Thus, we include the supervisor "entry into ring" stack pointer in the TSS. Listing 10:
/* [excerpted from i386.c] */
...
init386(){
...
/* make a initial tss so 386 can get interrupt stack on syscall! */
tss[0].tss_esp0 = (int) &x - 4096;
tss[0].tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
tss[0].tss_cr3 = (int) cr3;
printf("ltr "); getchar();
ltr(GSEL(GPROC0_SEL, SEL_KPL));
printf("resume() "); getchar();
/* set busy type to avail */
gdt[GPROC0_SEL].sd.sd_type = SDT_SYS386TSS;
/* jump to self to fill out tss, like BSD resume() */
jmptss(GSEL(GPROC0_SEL, SEL_KPL));
...
# excerpted from srt.s
...
/* jmptss(sel)-- Jump to TSS so that we can load/unload context */
.globl _jmptss /* similar to BSD swtch()/resume() */
_jmptss:
ljmp 0(%esp) /* ljmp tss */
/* saved pc points here */
ret
|