summaryrefslogtreecommitdiff
path: root/vm.c
diff options
context:
space:
mode:
authorPeter Froehlich <[email protected]>2016-12-22 20:26:37 -0500
committerFrans Kaashoek <[email protected]>2017-01-30 19:31:24 -0500
commit8d1f99637af48e28c0b4ebbe044e47abcefb5a5c (patch)
tree999310b49358018182cb249cb95125ec6b7f4535 /vm.c
parente916d668f7b184c41ee3d912ccda8cc7ca4aa765 (diff)
downloadxv6-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.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/vm.c b/vm.c
index 764512c..9db8b67 100644
--- a/vm.c
+++ b/vm.c
@@ -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();
}