pde cache check works

no more silly vm checkranges
This commit is contained in:
Ben Gras
2009-06-07 15:55:44 +00:00
parent 4dae6c4bbc
commit 0702c826a2
17 changed files with 98 additions and 230 deletions

View File

@@ -160,8 +160,6 @@ struct proc *t;
/* Save proc_ptr, because it may be changed by debug statements. */
saved_proc = proc_ptr;
CHECK_RUNQUEUES;
ep = &ex_data[vec_nr];
if (vec_nr == 2) { /* spurious NMI on some machines */

View File

@@ -23,7 +23,7 @@ PRIVATE int psok = 0;
int verifyrange = 0;
extern u32_t newpde, overwritepde, linlincopies,
physzero, invlpgs, vmcheckranges, straightpdes;
physzero, invlpgs, straightpdes;
#define PROCPDEPTR(pr, pi) ((u32_t *) ((u8_t *) vm_pagedirs +\
I386_PAGE_SIZE * pr->p_nr + \
@@ -36,7 +36,7 @@ u8_t *vm_pagedirs = NULL;
u32_t i386_invlpg_addr = 0;
#define WANT_FREEPDES 4
#define WANT_FREEPDES 100
#define NOPDE -1
#define PDEMASK(n) (1L << (n))
PRIVATE int nfreepdes = 0, freepdes[WANT_FREEPDES], inusepde = NOPDE;
@@ -448,8 +448,6 @@ PUBLIC int vm_contiguous(struct proc *targetproc, u32_t vir_buf, size_t bytes)
return 1;
}
int vm_checkrange_verbose = 0;
extern u32_t vmreqs;
/*===========================================================================*
@@ -531,81 +529,6 @@ int delivermsg(struct proc *rp)
NOREC_RETURN(deliver, r);
}
/*===========================================================================*
* vm_checkrange *
*===========================================================================*/
PUBLIC int vm_checkrange(struct proc *caller, struct proc *target,
vir_bytes vir, vir_bytes bytes, int wrfl, int checkonly)
{
u32_t flags, po, v;
int r;
NOREC_ENTER(vmcheckrange);
vmcheckranges++;
if(!HASPT(target))
NOREC_RETURN(vmcheckrange, OK);
/* If caller has had a reply to this request, return it. */
if(!verifyrange && RTS_ISSET(caller, VMREQUEST)) {
if(caller->p_vmrequest.who == target->p_endpoint) {
vmassert(caller->p_vmrequest.vmresult != VMSUSPEND);
RTS_LOCK_UNSET(caller, VMREQUEST);
#if 1
kprintf("SYSTEM: vm_checkrange: returning vmresult %d\n",
caller->p_vmrequest.vmresult);
#endif
NOREC_RETURN(vmcheckrange, caller->p_vmrequest.vmresult);
} else {
#if 1
kprintf("SYSTEM: vm_checkrange: caller has a request for %d, "
"but our target is %d\n",
caller->p_vmrequest.who, target->p_endpoint);
#endif
}
}
po = vir % I386_PAGE_SIZE;
if(po > 0) {
vir -= po;
bytes += po;
}
vmassert(target);
vmassert(bytes > 0);
for(v = vir; v < vir + bytes; v+= I386_PAGE_SIZE) {
u32_t phys;
int r;
/* If page exists and it's writable if desired, we're OK
* for this page.
*/
if((r=vm_lookup(target, v, &phys, &flags)) == OK &&
!(wrfl && !(flags & I386_VM_WRITE))) {
continue;
}
if(verifyrange) {
int wrok;
wrok = !(wrfl && !(flags & I386_VM_WRITE));
printf("checkrange failed; lookup: %d; write ok: %d\n",
r, wrok);
}
if(!checkonly) {
vmassert(k_reenter == -1);
vm_suspend(caller, target, vir, bytes, wrfl,
VMSTYPE_KERNELCALL);
}
NOREC_RETURN(vmcheckrange, VMSUSPEND);
}
NOREC_RETURN(vmcheckrange, OK);
}
char *flagstr(u32_t e, int dir)
{
static char str[80];
@@ -692,16 +615,14 @@ void invlpg_range(u32_t lin, u32_t bytes)
o = lin % I386_PAGE_SIZE;
lin -= o;
limit = (limit + o) & I386_VM_ADDR_MASK;
#if 0
#if 1
for(i386_invlpg_addr = lin; i386_invlpg_addr <= limit;
i386_invlpg_addr += I386_PAGE_SIZE) {
invlpgs++;
level0(i386_invlpg_level0);
}
#else
vm_cr3= ptproc->p_seg.p_cr3;
vmassert(vm_cr3);
level0(set_cr3);
level0(reload_cr3);
#endif
}
@@ -726,15 +647,15 @@ u32_t read_cr3(void)
* address space), SEG (hardware segment), VIRT (in-datasegment
* address if known).
*/
#define CREATEPDE(PROC, PTR, LINADDR, REMAIN, BYTES) { \
#define CREATEPDE(PROC, PTR, LINADDR, REMAIN, BYTES, PDE) { \
int proc_pde_index; \
FIXME("CREATEPDE: check if invlpg is necessary"); \
proc_pde_index = I386_VM_PDE(LINADDR); \
PDE = NOPDE; \
if((PROC) && (((PROC) == ptproc) || iskernelp(PROC))) { \
PTR = LINADDR; \
straightpdes++; \
} else { \
int use_pde = NOPDE; \
int fp; \
int mustinvl; \
u32_t pdeval, *pdevalptr, mask; \
@@ -756,34 +677,41 @@ u32_t read_cr3(void)
int k = freepdes[fp]; \
if(inusepde == k) \
continue; \
use_pde = k; \
PDE = k; \
mask = PDEMASK(k); \
vmassert(mask); \
if(dirtypde & mask) \
continue; \
break; \
} \
vmassert(use_pde != NOPDE); \
vmassert(PDE != NOPDE); \
vmassert(mask); \
if(dirtypde & mask) { \
mustinvl = 1; \
overwritepde++; \
} else { \
mustinvl = 0; \
dirtypde |= mask; \
newpde++; \
} \
inusepde = use_pde; \
*PROCPDEPTR(ptproc, use_pde) = pdeval; \
inusepde = PDE; \
*PROCPDEPTR(ptproc, PDE) = pdeval; \
offset = LINADDR & I386_VM_OFFSET_MASK_4MB; \
PTR = I386_BIG_PAGE_SIZE*use_pde + offset; \
PTR = I386_BIG_PAGE_SIZE*PDE + offset; \
REMAIN = MIN(REMAIN, I386_BIG_PAGE_SIZE - offset); \
if(1 || mustinvl) { \
if(mustinvl) { \
invlpg_range(PTR, REMAIN); \
} \
} \
}
#define DONEPDE(PDE) { \
if(PDE != NOPDE) { \
dirtypde |= PDEMASK(PDE); \
*PROCPDEPTR(ptproc, PDE) = 0; \
} \
}
/*===========================================================================*
* lin_lin_copy *
@@ -813,11 +741,12 @@ int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr,
while(bytes > 0) {
phys_bytes srcptr, dstptr;
vir_bytes chunk = bytes;
int srcpde, dstpde;
/* Set up 4MB ranges. */
inusepde = NOPDE;
CREATEPDE(srcproc, srcptr, srclinaddr, chunk, bytes);
CREATEPDE(dstproc, dstptr, dstlinaddr, chunk, bytes);
CREATEPDE(srcproc, srcptr, srclinaddr, chunk, bytes, srcpde);
CREATEPDE(dstproc, dstptr, dstlinaddr, chunk, bytes, dstpde);
/* Copy pages. */
vmassert(intr_disabled());
@@ -828,6 +757,9 @@ int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr,
vmassert(catch_pagefaults);
catch_pagefaults = 0;
DONEPDE(srcpde);
DONEPDE(dstpde);
if(addr) {
if(addr >= srcptr && addr < (srcptr + chunk)) {
NOREC_RETURN(linlincopy, EFAULT_SRC);
@@ -872,14 +804,16 @@ int vm_phys_memset(phys_bytes ph, u8_t c, phys_bytes bytes)
* We can do this 4MB at a time.
*/
while(bytes > 0) {
int pde;
vir_bytes chunk = bytes;
phys_bytes ptr;
inusepde = NOPDE;
CREATEPDE(((struct proc *) NULL), ptr, ph, chunk, bytes);
CREATEPDE(((struct proc *) NULL), ptr, ph, chunk, bytes, pde);
/* We can memset as many bytes as we have remaining,
* or as many as remain in the 4MB chunk we mapped in.
*/
phys_memset(ptr, p, chunk);
DONEPDE(pde);
bytes -= chunk;
ph += chunk;
}
@@ -1077,6 +1011,25 @@ PUBLIC int data_copy(
return virtual_copy(&src, &dst, bytes);
}
/*===========================================================================*
* data_copy_vmcheck *
*===========================================================================*/
PUBLIC int data_copy_vmcheck(
endpoint_t from_proc, vir_bytes from_addr,
endpoint_t to_proc, vir_bytes to_addr,
size_t bytes)
{
struct vir_addr src, dst;
src.segment = dst.segment = D;
src.offset = from_addr;
dst.offset = to_addr;
src.proc_nr_e = from_proc;
dst.proc_nr_e = to_proc;
return virtual_copy_vmcheck(&src, &dst, bytes);
}
/*===========================================================================*
* arch_pre_exec *
*===========================================================================*/

View File

@@ -76,6 +76,7 @@ begbss:
.define _pagefault_count
.define _cr3_test
.define _cr3_reload
.define _reload_cr3
.define _write_cr3 ! write cr3
.define errexception
@@ -419,7 +420,7 @@ _restart:
mov (loadedcr3), eax
mov eax, (_proc_ptr)
mov (_ptproc), eax
! mov (_dirtypde), 0
mov (_dirtypde), 0
0:
lea eax, P_STACKTOP(esp) ! arrange for next interrupt
mov (_tss+TSS3_S_SP0), eax ! to save state in process table
@@ -566,16 +567,30 @@ _write_cr3:
mov ebp, esp
mov eax, 8(ebp)
inc (_cr3_test)
! cmp eax, (loadedcr3)
! jz 0f
cmp eax, (loadedcr3)
jz 0f
inc (_cr3_reload)
mov cr3, eax
mov (loadedcr3), eax
! mov (_dirtypde), 0
mov (_dirtypde), 0
0:
pop ebp
ret
!*===========================================================================*
!* reload_cr3 *
!*===========================================================================*
! PUBLIC void reload_cr3(void);
_reload_cr3:
push ebp
mov ebp, esp
inc (_cr3_reload)
mov (_dirtypde), 0
mov eax, cr3
mov cr3, eax
pop ebp
ret
!*===========================================================================*
!* level0_call *
!*===========================================================================*

View File

@@ -79,6 +79,7 @@ _PROTOTYPE( void i386_invlpg_level0, (void) );
_PROTOTYPE( int _memcpy_k, (void *dst, void *src, size_t n) );
_PROTOTYPE( int _memcpy_k_fault, (void) );
_PROTOTYPE( u32_t read_cr3, (void) );
_PROTOTYPE( void reload_cr3, (void) );
/* protect.c */
_PROTOTYPE( void prot_init, (void) );

View File

@@ -153,6 +153,7 @@ PRIVATE void ser_debug(int c)
case '2':
ser_dump_queues();
break;
#if DEBUG_TRACE
#define TOGGLECASE(ch, flag) \
case ch: { \
if(verboseflags & flag) { \
@@ -166,6 +167,7 @@ PRIVATE void ser_debug(int c)
}
TOGGLECASE('8', VF_SCHEDULING)
TOGGLECASE('9', VF_PICKPROC)
#endif
}
do_serial_debug--;
if(u) { unlock; }
@@ -182,22 +184,13 @@ PRIVATE void printslot(struct proc *pp, int level)
return;
}
if(pp->p_ready && pp->p_rts_flags) {
printf("HUH? p_ready but rts flags!\n");
}
if(!pp->p_ready && !pp->p_rts_flags) {
printf("HUH? not p_ready but no rts flags!\n");
}
COL
kprintf("%d: %s %d prio %d/%d time %d/%d cr3 0x%lx rts %s misc %s ready %d",
kprintf("%d: %s %d prio %d/%d time %d/%d cr3 0x%lx rts %s misc %s",
proc_nr(pp), pp->p_name, pp->p_endpoint,
pp->p_priority, pp->p_max_priority, pp->p_user_time,
pp->p_sys_time, pp->p_seg.p_cr3,
rtsflagstr(pp->p_rts_flags), miscflagstr(pp->p_misc_flags),
pp->p_ready);
rtsflagstr(pp->p_rts_flags), miscflagstr(pp->p_misc_flags));
if(pp->p_rts_flags & SENDING) {
dep = pp->p_sendto_e;
@@ -231,11 +224,6 @@ PRIVATE void printslot(struct proc *pp, int level)
COL
proc_stacktrace(pp);
if(pp->p_rts_flags & VMREQUEST) {
COL
printf("vmrequest set with: %s\n", pp->p_vmrequest.stacktrace);
}
if(depproc)
printslot(depproc, level+1);
}
@@ -259,8 +247,6 @@ PUBLIC void ser_dump_proc()
{
struct proc *pp;
CHECK_RUNQUEUES;
for (pp= BEG_PROC_ADDR; pp < END_PROC_ADDR; pp++)
{
if (pp->p_rts_flags & SLOT_FREE)