]> Zhao Yanbai Git Server - minix.git/commitdiff
kernel: fix for vm_init that triggered assert(ptproc == newptproc)
authorBen Gras <ben@minix3.org>
Mon, 7 Jun 2010 22:21:45 +0000 (22:21 +0000)
committerBen Gras <ben@minix3.org>
Mon, 7 Jun 2010 22:21:45 +0000 (22:21 +0000)
 - zero cr3 in vm_init() to avoid switch_address_space() not doing anything.

 - add vm_stop() to disable paging on shutdown.

kernel/arch/i386/arch_system.c
kernel/arch/i386/klib.S
kernel/arch/i386/memory.c
kernel/arch/i386/proto.h
kernel/proto.h

index 6894c244017d01e09bd6a3a3570f18eee5a8ca31..e98888786707dc973e4feed770374cb9bce5fcfc 100644 (file)
@@ -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);
 
index 98d7171b275591855573da6bf230a02cf03e6290..4d99dd782595ef288076a7c2ed7c37398da3a03f 100644 (file)
@@ -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                                    */
 /*===========================================================================*/
index e3bc551beee5750fadcd3809d6664d4ab739e4ab..ca93a298d5b8c8bd582152b26b40112e3d17cded 100644 (file)
@@ -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;
index 3acb7c42c91fa50b4c06b02aa40729539cede17b..cdc40ab8264be389e7a1beb8eef5832013a42381 100644 (file)
@@ -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)  );
index ac6e95a1796ee8e588d17d0486f812298b1f700e..727d987c98dad6a6a02cb0de212ec4060d24d796 100644 (file)
@@ -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,