From: Ben Gras Date: Mon, 7 Jun 2010 22:21:45 +0000 (+0000) Subject: kernel: fix for vm_init that triggered assert(ptproc == newptproc) X-Git-Tag: v3.1.8~493 X-Git-Url: http://zhaoyanbai.com/repos/%22/xml/v3/zones/static/man.host.html?a=commitdiff_plain;h=a09a8d4f3edbd5dc83ae89294585bdca08f66933;p=minix.git kernel: fix for vm_init that triggered assert(ptproc == newptproc) - zero cr3 in vm_init() to avoid switch_address_space() not doing anything. - add vm_stop() to disable paging on shutdown. --- diff --git a/kernel/arch/i386/arch_system.c b/kernel/arch/i386/arch_system.c index 6894c2440..e98888786 100644 --- a/kernel/arch/i386/arch_system.c +++ b/kernel/arch/i386/arch_system.c @@ -48,6 +48,8 @@ PUBLIC int cpu_has_tsc; PUBLIC void arch_shutdown(const int how) { + vm_stop(); + /* Mask all interrupts, including the clock. */ outb( INT_CTLMASK, ~0); diff --git a/kernel/arch/i386/klib.S b/kernel/arch/i386/klib.S index 98d7171b2..4d99dd782 100644 --- a/kernel/arch/i386/klib.S +++ b/kernel/arch/i386/klib.S @@ -38,6 +38,7 @@ .globl _getcr3val .globl _write_cr0 /* write a value in cr0 */ .globl _read_cr3 +.globl _write_cr3 .globl _read_cr4 .globl _write_cr4 @@ -788,6 +789,22 @@ _write_cr4: 0: pop %ebp ret + +/*===========================================================================*/ +/* write_cr3 */ +/*===========================================================================*/ +/* PUBLIC void write_cr3(unsigned long value); */ +_write_cr3: + push %ebp + mov %esp, %ebp + mov 8(%ebp), %eax + + /* DO NOT CHANGE THE OPERAND!!! gas2ack does not handle it yet */ + mov %eax, %cr3 + + pop %ebp + ret + /*===========================================================================*/ /* getcr3val */ /*===========================================================================*/ diff --git a/kernel/arch/i386/memory.c b/kernel/arch/i386/memory.c index e3bc551be..ca93a298d 100644 --- a/kernel/arch/i386/memory.c +++ b/kernel/arch/i386/memory.c @@ -45,11 +45,25 @@ PUBLIC void vm_init(struct proc *newptproc) { if(vm_running) panic("vm_init: vm_running"); + + /* switch_address_space() checks what is in cr3, and doesn't do + * anything if it's the same as the cr3 of its argument, newptproc. + * If MINIX was previously booted, this could very well be the case. + * + * The first time switch_address_space() is called, we want to + * force it to do something (load cr3 and set newptproc), so we + * zero cr3, and force paging off to make that a safe thing to do. + * + * After that, vm_enable_paging() enables paging with the page table + * of newptproc loaded. + */ + + vm_stop(); + write_cr3(0); switch_address_space(newptproc); assert(ptproc == newptproc); vm_enable_paging(); vm_running = 1; - } /* This function sets up a mapping from within the kernel's address @@ -254,6 +268,11 @@ PRIVATE char *cr4_str(u32_t e) return str; } +PUBLIC void vm_stop(void) +{ + write_cr0(read_cr0() & ~I386_CR0_PG); +} + PRIVATE void vm_enable_paging(void) { u32_t cr0, cr4; diff --git a/kernel/arch/i386/proto.h b/kernel/arch/i386/proto.h index 3acb7c42c..cdc40ab82 100644 --- a/kernel/arch/i386/proto.h +++ b/kernel/arch/i386/proto.h @@ -74,6 +74,7 @@ _PROTOTYPE( reg_t read_cr2, (void) ); _PROTOTYPE( void write_cr0, (unsigned long value) ); _PROTOTYPE( unsigned long read_cr4, (void) ); _PROTOTYPE( void write_cr4, (unsigned long value) ); +_PROTOTYPE( void write_cr3, (unsigned long value) ); _PROTOTYPE( unsigned long read_cpu_flags, (void) ); _PROTOTYPE( void phys_insb, (u16_t port, phys_bytes buf, size_t count) ); _PROTOTYPE( void phys_insw, (u16_t port, phys_bytes buf, size_t count) ); diff --git a/kernel/proto.h b/kernel/proto.h index ac6e95a17..727d987c9 100644 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -142,6 +142,7 @@ _PROTOTYPE( int data_copy_vmcheck, (struct proc *, endpoint_t to, vir_bytes to_addr, size_t bytes)); _PROTOTYPE( void alloc_segments, (struct proc *rp) ); _PROTOTYPE( void vm_init, (struct proc *first) ); +_PROTOTYPE( void vm_stop, (void) ); _PROTOTYPE( phys_bytes umap_local, (register struct proc *rp, int seg, vir_bytes vir_addr, vir_bytes bytes)); _PROTOTYPE( phys_bytes umap_remote, (const struct proc* rp, int seg,