diff options
author | Peter Froehlich <[email protected]> | 2016-12-22 20:26:37 -0500 |
---|---|---|
committer | Frans Kaashoek <[email protected]> | 2017-01-30 19:31:24 -0500 |
commit | 8d1f99637af48e28c0b4ebbe044e47abcefb5a5c (patch) | |
tree | 999310b49358018182cb249cb95125ec6b7f4535 /vm.c | |
parent | e916d668f7b184c41ee3d912ccda8cc7ca4aa765 (diff) | |
download | xv6-labs-8d1f99637af48e28c0b4ebbe044e47abcefb5a5c.tar.gz xv6-labs-8d1f99637af48e28c0b4ebbe044e47abcefb5a5c.tar.bz2 xv6-labs-8d1f99637af48e28c0b4ebbe044e47abcefb5a5c.zip |
Fix long-standing switchuvm() inconsistency.
switchuvm() is supposed to switch the TSS and page table to the
process p it is passed. Alas, instead of using p to access the
kstack field, it used the global proc. This worked fine because
(a) most uses of switchuvm() pass proc anyway and (b) because in
the schedule, where we call switchuvm with the newly scheduled
process, we actually set the global proc before the call. But I
think it's still a bug, even if it never broke a test case. :-)
Diffstat (limited to 'vm.c')
-rw-r--r-- | vm.c | 11 |
1 files changed, 8 insertions, 3 deletions
@@ -163,17 +163,22 @@ switchkvm(void) void switchuvm(struct proc *p) { + if(p == 0) + panic("switchuvm: no process"); + if(p->kstack == 0) + panic("switchuvm: no kstack"); + if(p->pgdir == 0) + panic("switchuvm: no pgdir"); + pushcli(); cpu->gdt[SEG_TSS] = SEG16(STS_T32A, &cpu->ts, sizeof(cpu->ts)-1, 0); cpu->gdt[SEG_TSS].s = 0; cpu->ts.ss0 = SEG_KDATA << 3; - cpu->ts.esp0 = (uint)proc->kstack + KSTACKSIZE; + cpu->ts.esp0 = (uint)p->kstack + KSTACKSIZE; // setting IOPL=0 in eflags *and* iomb beyond the tss segment limit // forbids I/O instructions (e.g., inb and outb) from user space cpu->ts.iomb = (ushort) 0xFFFF; ltr(SEG_TSS << 3); - if(p->pgdir == 0) - panic("switchuvm: no pgdir"); lcr3(V2P(p->pgdir)); // switch to process's address space popcli(); } |