vm: clear map cache after kernel requests

. fixes a dirty tlb situation (i.e. random crashes)
	  on some hardware, seemingly new intel architectures
	  (e.g. my desktop i7 machine)
This commit is contained in:
Ben Gras 2012-01-02 18:20:02 +01:00
parent 0bb4bb9d51
commit 7cd4002083
3 changed files with 26 additions and 4 deletions

View 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);

View file

@ -36,6 +36,10 @@
#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. */

View 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();
}
/*===========================================================================*