]> Zhao Yanbai Git Server - minix.git/commitdiff
vm: clear map cache after kernel requests
authorBen Gras <ben@minix3.org>
Mon, 2 Jan 2012 17:20:02 +0000 (18:20 +0100)
committerBen Gras <ben@minix3.org>
Wed, 11 Jan 2012 00:15:35 +0000 (01:15 +0100)
. fixes a dirty tlb situation (i.e. random crashes)
  on some hardware, seemingly new intel architectures
  (e.g. my desktop i7 machine)

kernel/arch/i386/memory.c
servers/vm/arch/i386/pagetable.c
servers/vm/main.c

index 8098355c5df8739f29ae0e2e59832df3f73b4c7b..d512f07bf8552a199f04f3db27f30ccc1e79a337 100644 (file)
@@ -31,7 +31,7 @@ PUBLIC int i386_paging_enabled = 0;
 
 PRIVATE int psok = 0;
 
-#define FREE_PDES_PER_CPU      3
+#define FREE_PDES_PER_CPU      2
 #define MAX_FREEPDES           (FREE_PDES_PER_CPU * CONFIG_MAX_CPUS)
 PRIVATE int nfreepdes = 0, freepdes[MAX_FREEPDES];
 
@@ -145,7 +145,7 @@ PRIVATE int lin_lin_copy(const struct proc *srcproc, vir_bytes srclinaddr,
        proc_nr_t procslot;
 
        assert(vm_running);
-       assert(nfreepdes >= 3);
+       assert(nfreepdes >= 2);
 
        assert(get_cpulocal_var(ptproc));
        assert(get_cpulocal_var(proc_ptr));
@@ -645,7 +645,7 @@ int vm_phys_memset(phys_bytes ph, const u8_t c, phys_bytes bytes)
                return OK;
        }
 
-       assert(nfreepdes >= 3);
+       assert(nfreepdes >= 2);
 
        assert(get_cpulocal_var(ptproc)->p_seg.p_cr3_v);
 
index bbd2183e98ead4fc784ff0446e09d75129c08aee..4c0ee2008274052e7ba68b71309871eb7ebf94be 100644 (file)
 
 #include "memory.h"
 
+/* Free PDE slots we tell kernel about */
+#define FREE_PDES      2
+PRIVATE int first_free_pde = -1;
+
 /* PDE used to map in kernel, kernel physical address. */
 PRIVATE int id_map_high_pde = -1, pagedir_pde = -1;
 PRIVATE u32_t global_bit = 0, pagedir_pde_val;
@@ -638,6 +642,18 @@ PUBLIC int pt_ptmap(struct vmproc *src_vmp, struct vmproc *dst_vmp)
        return OK;
 }
 
+PUBLIC int pt_clearmapcache(void)
+{
+       int f;
+       /* Make sure kernel will invalidate tlb when using current
+        * pagetable (i.e. vm's) to make new mappings before new cr3
+        * is loaded.
+        */
+       for(f = first_free_pde; f < first_free_pde+FREE_PDES; f++) {
+               vmprocess->vm_pt.pt_dir[f] = 0;
+       }
+}
+
 /*===========================================================================*
  *                             pt_writemap                                  *
  *===========================================================================*/
@@ -876,6 +892,7 @@ PUBLIC void pt_init(phys_bytes usedlimit)
        vir_bytes sparepages_mem;
        phys_bytes sparepages_ph;
        vir_bytes ptr;
+       int f = 0;
 
         /* Shorthand. */
         newpt = &vmprocess->vm_pt;
@@ -1030,10 +1047,12 @@ PUBLIC void pt_init(phys_bytes usedlimit)
                        I386_VM_PRESENT | I386_VM_USER | I386_VM_WRITE;
 
        /* Tell kernel about free pde's. */
-       while(free_pde*I386_BIG_PAGE_SIZE < VM_PROCSTART) {
+       first_free_pde = free_pde;
+       while(free_pde*I386_BIG_PAGE_SIZE < VM_PROCSTART && f < FREE_PDES) {
                if((r=sys_vmctl(SELF, VMCTL_I386_FREEPDE, free_pde++)) != OK) {
                        panic("VMCTL_I386_FREEPDE failed: %d", r);
                }
+               f++;
        }
 
        /* first pde in use by process. */
index 576522319e5f465e25512919c09d1919fdd7f53c..43a07b78d1a23e17c56f02fbea412205d4054501 100644 (file)
@@ -112,6 +112,7 @@ PUBLIC int main(void)
                                        "message!\n", msg.m_source);
                }
                do_pagefaults(&msg);
+               pt_clearmapcache();
                /*
                 * do not reply to this call, the caller is unblocked by
                 * a sys_vmctl() call in do_pagefaults if success. VM panics
@@ -419,6 +420,8 @@ PRIVATE void sef_cb_signal_handler(int signo)
        if(missing_spares > 0) {
                pt_cycle();     /* pagetable code wants to be called */
        }
+
+       pt_clearmapcache();
 }
 
 /*===========================================================================*