my state.
trying to get some memory optimisation (less pagetable reloading, less tlb purging) features working smoothly. to be documented when committing to trunk :)
This commit is contained in:
@@ -77,7 +77,7 @@ register message *m_ptr; /* pointer to request message */
|
||||
return EPERM;
|
||||
}
|
||||
/* Get and check physical address. */
|
||||
if ((phys_buf = umap_virtual(proc_addr(proc_nr), D,
|
||||
if ((phys_buf = umap_local(proc_addr(proc_nr), D,
|
||||
(vir_bytes) m_ptr->DIO_VEC_ADDR, count)) == 0)
|
||||
return(EFAULT);
|
||||
}
|
||||
|
||||
@@ -11,53 +11,67 @@
|
||||
#include <minix/sysutil.h>
|
||||
#include "../../proc.h"
|
||||
#include "../../proto.h"
|
||||
#include "../../vm.h"
|
||||
|
||||
extern int vm_copy_in_progress, catch_pagefaults;
|
||||
extern struct proc *vm_copy_from, *vm_copy_to;
|
||||
extern u32_t npagefaults;
|
||||
|
||||
u32_t pagefault_cr2, pagefault_count = 0;
|
||||
vir_bytes *old_eip_ptr = NULL, *old_eax_ptr = NULL;
|
||||
PUBLIC u32_t pagefault_count = 0;
|
||||
|
||||
void pagefault(vir_bytes old_eip, struct proc *pr, int trap_errno)
|
||||
void pagefault(vir_bytes old_eip, struct proc *pr, int trap_errno,
|
||||
u32_t *old_eipptr, u32_t *old_eaxptr, u32_t pagefaultcr2)
|
||||
{
|
||||
int s;
|
||||
vir_bytes ph;
|
||||
u32_t pte;
|
||||
int procok = 0, pcok = 0, rangeok = 0;
|
||||
int in_memcpy = 0, in_physcopy = 0;
|
||||
int in_physcopy = 0;
|
||||
vir_bytes test_eip;
|
||||
|
||||
vmassert(old_eip_ptr);
|
||||
vmassert(old_eax_ptr);
|
||||
vmassert(old_eipptr);
|
||||
vmassert(old_eaxptr);
|
||||
|
||||
vmassert(*old_eip_ptr == old_eip);
|
||||
vmassert(old_eip_ptr != &old_eip);
|
||||
vmassert(*old_eipptr == old_eip);
|
||||
vmassert(old_eipptr != &old_eip);
|
||||
|
||||
vmassert(pagefault_count == 1);
|
||||
|
||||
if(catch_pagefaults) {
|
||||
vir_bytes test_eip;
|
||||
test_eip = k_reenter ? old_eip : pr->p_reg.pc;
|
||||
in_memcpy = (test_eip > (vir_bytes) _memcpy_k) &&
|
||||
(test_eip < (vir_bytes) _memcpy_k_fault);
|
||||
in_physcopy = (test_eip > (vir_bytes) phys_copy) &&
|
||||
(test_eip < (vir_bytes) phys_copy_fault);
|
||||
if((pcok = in_memcpy || in_physcopy)) {
|
||||
pagefault_count = 0;
|
||||
#if 0
|
||||
printf("kernel: pagefault in pr %d, addr 0x%lx, his cr3 0x%lx, actual cr3 0x%lx\n",
|
||||
pr->p_endpoint, pagefaultcr2, pr->p_seg.p_cr3, read_cr3());
|
||||
#endif
|
||||
|
||||
if(in_memcpy) {
|
||||
vmassert(!in_physcopy);
|
||||
*old_eip_ptr = _memcpy_k_fault;
|
||||
}
|
||||
if(in_physcopy) {
|
||||
vmassert(!in_memcpy);
|
||||
*old_eip_ptr = phys_copy_fault;
|
||||
}
|
||||
*old_eax_ptr = pagefault_cr2;
|
||||
|
||||
return;
|
||||
}
|
||||
if(pr->p_seg.p_cr3) {
|
||||
#if 0
|
||||
vm_print(pr->p_seg.p_cr3);
|
||||
#endif
|
||||
vmassert(pr->p_seg.p_cr3 == read_cr3());
|
||||
} else {
|
||||
vmassert(ptproc);
|
||||
vmassert(ptproc->p_seg.p_cr3 == read_cr3());
|
||||
}
|
||||
|
||||
test_eip = k_reenter ? old_eip : pr->p_reg.pc;
|
||||
|
||||
in_physcopy = (test_eip > (vir_bytes) phys_copy) &&
|
||||
(test_eip < (vir_bytes) phys_copy_fault);
|
||||
|
||||
if((k_reenter || iskernelp(pr)) &&
|
||||
catch_pagefaults && in_physcopy) {
|
||||
#if 0
|
||||
printf("pf caught! addr 0x%lx\n", pagefaultcr2);
|
||||
#endif
|
||||
*old_eipptr = phys_copy_fault;
|
||||
*old_eaxptr = pagefaultcr2;
|
||||
|
||||
pagefault_count = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
npagefaults++;
|
||||
|
||||
/* System processes that don't have their own page table can't
|
||||
* have page faults. VM does have its own page table but also
|
||||
* can't have page faults (because VM has to handle them).
|
||||
@@ -67,9 +81,9 @@ void pagefault(vir_bytes old_eip, struct proc *pr, int trap_errno)
|
||||
/* Page fault we can't / don't want to
|
||||
* handle.
|
||||
*/
|
||||
kprintf("pagefault for process %d ('%s'), pc = 0x%x, addr = 0x%x, flags = 0x%x\n",
|
||||
kprintf("pagefault for process %d ('%s'), pc = 0x%x, addr = 0x%x, flags = 0x%x, k_reenter %d\n",
|
||||
pr->p_endpoint, pr->p_name, pr->p_reg.pc,
|
||||
pagefault_cr2, trap_errno);
|
||||
pagefaultcr2, trap_errno, k_reenter);
|
||||
proc_stacktrace(pr);
|
||||
minix_panic("page fault in system process", pr->p_endpoint);
|
||||
|
||||
@@ -86,12 +100,12 @@ void pagefault(vir_bytes old_eip, struct proc *pr, int trap_errno)
|
||||
* and tell VM there is a pagefault to be
|
||||
* handled.
|
||||
*/
|
||||
pr->p_pagefault.pf_virtual = pagefault_cr2;
|
||||
pr->p_pagefault.pf_virtual = pagefaultcr2;
|
||||
pr->p_pagefault.pf_flags = trap_errno;
|
||||
pr->p_nextpagefault = pagefaults;
|
||||
pagefaults = pr;
|
||||
|
||||
lock_notify(SYSTEM, VM_PROC_NR);
|
||||
lock_notify(HARDWARE, VM_PROC_NR);
|
||||
|
||||
pagefault_count = 0;
|
||||
|
||||
@@ -101,12 +115,16 @@ void pagefault(vir_bytes old_eip, struct proc *pr, int trap_errno)
|
||||
/*===========================================================================*
|
||||
* exception *
|
||||
*===========================================================================*/
|
||||
PUBLIC void exception(vec_nr, trap_errno, old_eip, old_cs, old_eflags)
|
||||
PUBLIC void exception(vec_nr, trap_errno, old_eip, old_cs, old_eflags,
|
||||
old_eipptr, old_eaxptr, pagefaultcr2)
|
||||
unsigned vec_nr;
|
||||
u32_t trap_errno;
|
||||
u32_t old_eip;
|
||||
U16_t old_cs;
|
||||
u32_t old_eflags;
|
||||
u32_t *old_eipptr;
|
||||
u32_t *old_eaxptr;
|
||||
u32_t pagefaultcr2;
|
||||
{
|
||||
/* An exception or unexpected interrupt has occurred. */
|
||||
|
||||
@@ -141,6 +159,8 @@ 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];
|
||||
|
||||
@@ -150,8 +170,9 @@ struct proc *t;
|
||||
}
|
||||
|
||||
if(vec_nr == PAGE_FAULT_VECTOR) {
|
||||
pagefault(old_eip, saved_proc, trap_errno);
|
||||
return;
|
||||
pagefault(old_eip, saved_proc, trap_errno,
|
||||
old_eipptr, old_eaxptr, pagefaultcr2);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If an exception occurs while running a process, the k_reenter variable
|
||||
@@ -222,7 +243,7 @@ PUBLIC void proc_stacktrace(struct proc *proc)
|
||||
break;
|
||||
}
|
||||
if(PRCOPY(proc, v_bp + sizeof(v_pc), &v_pc, sizeof(v_pc)) != OK) {
|
||||
kprintf("(v_pc 0x%lx ?)", v_pc);
|
||||
kprintf("(v_pc 0x%lx ?)", v_bp + sizeof(v_pc));
|
||||
break;
|
||||
}
|
||||
kprintf("0x%lx ", (unsigned long) v_pc);
|
||||
|
||||
@@ -383,8 +383,6 @@ _phys_copy:
|
||||
mov edi, PC_ARGS+4(esp)
|
||||
mov eax, PC_ARGS+4+4(esp)
|
||||
|
||||
mov (_catch_pagefaults), 1
|
||||
|
||||
cmp eax, 10 ! avoid align overhead for small counts
|
||||
jb pc_small
|
||||
mov ecx, esi ! align source, hope target is too
|
||||
@@ -403,12 +401,11 @@ pc_small:
|
||||
rep
|
||||
eseg movsb
|
||||
|
||||
mov eax, 0 ! 0 means: no fault
|
||||
_phys_copy_fault: ! kernel can send us here
|
||||
pop es
|
||||
pop edi
|
||||
pop esi
|
||||
mov eax, 0 ! 0 means: no fault
|
||||
_phys_copy_fault: ! kernel can send us here
|
||||
mov (_catch_pagefaults), 0
|
||||
ret
|
||||
|
||||
!*===========================================================================*
|
||||
@@ -439,7 +436,7 @@ fill_start:
|
||||
jnz fill_start
|
||||
! Any remaining bytes?
|
||||
mov eax, 16(ebp)
|
||||
! and eax, 3
|
||||
and eax, 3
|
||||
remain_fill:
|
||||
cmp eax, 0
|
||||
jz fill_done
|
||||
|
||||
@@ -9,21 +9,21 @@
|
||||
#include <minix/cpufeature.h>
|
||||
#include <string.h>
|
||||
|
||||
#define FREEPDE_SRC 0
|
||||
#define FREEPDE_DST 1
|
||||
#define FREEPDE_MEMSET 2
|
||||
|
||||
#include <sys/vm_i386.h>
|
||||
|
||||
#include <minix/portio.h>
|
||||
|
||||
#include "proto.h"
|
||||
#include "../../proto.h"
|
||||
#include "../../proto.h"
|
||||
#include "../../debug.h"
|
||||
|
||||
PRIVATE int psok = 0;
|
||||
|
||||
extern u32_t createpde, linlincopies, physzero;
|
||||
int verifyrange = 0;
|
||||
|
||||
extern u32_t newpde, overwritepde, linlincopies,
|
||||
physzero, invlpgs, vmcheckranges, straightpdes;
|
||||
|
||||
#define PROCPDEPTR(pr, pi) ((u32_t *) ((u8_t *) vm_pagedirs +\
|
||||
I386_PAGE_SIZE * pr->p_nr + \
|
||||
@@ -37,12 +37,15 @@ u8_t *vm_pagedirs = NULL;
|
||||
u32_t i386_invlpg_addr = 0;
|
||||
|
||||
#define WANT_FREEPDES 4
|
||||
PRIVATE int nfreepdes = 0, freepdes[WANT_FREEPDES];
|
||||
#define NOPDE -1
|
||||
#define PDEMASK(n) (1L << (n))
|
||||
PRIVATE int nfreepdes = 0, freepdes[WANT_FREEPDES], inusepde = NOPDE;
|
||||
PUBLIC u32_t dirtypde;
|
||||
|
||||
#define HASPT(procptr) ((procptr)->p_seg.p_cr3 != 0)
|
||||
|
||||
FORWARD _PROTOTYPE( u32_t phys_get32, (vir_bytes v) );
|
||||
FORWARD _PROTOTYPE( void vm_set_cr3, (u32_t value) );
|
||||
FORWARD _PROTOTYPE( void vm_set_cr3, (struct proc *pr) );
|
||||
FORWARD _PROTOTYPE( void set_cr3, (void) );
|
||||
FORWARD _PROTOTYPE( void vm_enable_paging, (void) );
|
||||
|
||||
@@ -50,34 +53,13 @@ FORWARD _PROTOTYPE( void vm_enable_paging, (void) );
|
||||
|
||||
PUBLIC void vm_init(struct proc *newptproc)
|
||||
{
|
||||
u32_t newcr3;
|
||||
|
||||
int i;
|
||||
if(vm_running)
|
||||
minix_panic("vm_init: vm_running", NO_NUM);
|
||||
|
||||
ptproc = newptproc;
|
||||
newcr3 = ptproc->p_seg.p_cr3;
|
||||
kprintf("vm_init: ptproc: %s / %d, cr3 0x%lx\n",
|
||||
ptproc->p_name, ptproc->p_endpoint,
|
||||
ptproc->p_seg.p_cr3);
|
||||
vmassert(newcr3);
|
||||
|
||||
/* Set this cr3 now (not active until paging enabled). */
|
||||
vm_set_cr3(newcr3);
|
||||
|
||||
kprintf("vm_init: writing cr3 0x%lx done; cr3: 0x%lx\n",
|
||||
newcr3, read_cr3());
|
||||
|
||||
kprintf("vm_init: enabling\n");
|
||||
/* Actually enable paging (activating cr3 load above). */
|
||||
vm_set_cr3(newptproc);
|
||||
level0(vm_enable_paging);
|
||||
|
||||
kprintf("vm_init: enabled\n");
|
||||
|
||||
/* Don't do this init in the future. */
|
||||
vm_running = 1;
|
||||
|
||||
kprintf("vm_init done\n");
|
||||
}
|
||||
|
||||
PRIVATE u32_t phys_get32(addr)
|
||||
@@ -91,9 +73,8 @@ phys_bytes addr;
|
||||
return v;
|
||||
}
|
||||
|
||||
if((r=lin_lin_copy(NULL, addr, NULL, D,
|
||||
proc_addr(SYSTEM), &v, &v, D,
|
||||
sizeof(v))) != OK) {
|
||||
if((r=lin_lin_copy(NULL, addr,
|
||||
proc_addr(SYSTEM), vir2phys(&v), sizeof(v))) != OK) {
|
||||
minix_panic("lin_lin_copy for phys_get32 failed", r);
|
||||
}
|
||||
|
||||
@@ -102,11 +83,16 @@ phys_bytes addr;
|
||||
|
||||
PRIVATE u32_t vm_cr3; /* temp arg to level0() func */
|
||||
|
||||
PRIVATE void vm_set_cr3(value)
|
||||
u32_t value;
|
||||
PRIVATE void vm_set_cr3(struct proc *newptproc)
|
||||
{
|
||||
vm_cr3= value;
|
||||
level0(set_cr3);
|
||||
int u = 0;
|
||||
if(!intr_disabled()) { lock; u = 1; }
|
||||
vm_cr3= newptproc->p_seg.p_cr3;
|
||||
if(vm_cr3) {
|
||||
level0(set_cr3);
|
||||
ptproc = newptproc;
|
||||
}
|
||||
if(u) { unlock; }
|
||||
}
|
||||
|
||||
PRIVATE void set_cr3()
|
||||
@@ -343,11 +329,13 @@ PUBLIC int vm_lookup(struct proc *proc, vir_bytes virtual, vir_bytes *physical,
|
||||
pde_v = phys_get32((u32_t) (root + pde));
|
||||
|
||||
if(!(pde_v & I386_VM_PRESENT)) {
|
||||
#if 0
|
||||
#if 1
|
||||
if(verifyrange) {
|
||||
kprintf("vm_lookup: %d:%s:0x%lx: cr3 0x%lx: pde %d not present\n",
|
||||
proc->p_endpoint, proc->p_name, virtual, root, pde);
|
||||
kprintf("kernel stack: ");
|
||||
util_stacktrace();
|
||||
}
|
||||
#endif
|
||||
NOREC_RETURN(vmlookup, EFAULT);
|
||||
}
|
||||
@@ -365,6 +353,14 @@ PUBLIC int vm_lookup(struct proc *proc, vir_bytes virtual, vir_bytes *physical,
|
||||
vmassert(pte >= 0 && pte < I386_VM_PT_ENTRIES);
|
||||
pte_v = phys_get32((u32_t) (pt + pte));
|
||||
if(!(pte_v & I386_VM_PRESENT)) {
|
||||
#if 1
|
||||
if(verifyrange) {
|
||||
kprintf("vm_lookup: %d:%s:0x%lx: cr3 0x%lx: pte %d not present\n",
|
||||
proc->p_endpoint, proc->p_name, virtual, root, pte);
|
||||
kprintf("kernel stack: ");
|
||||
util_stacktrace();
|
||||
}
|
||||
#endif
|
||||
NOREC_RETURN(vmlookup, EFAULT);
|
||||
}
|
||||
|
||||
@@ -449,35 +445,90 @@ PUBLIC int vm_contiguous(struct proc *targetproc, u32_t vir_buf, size_t bytes)
|
||||
boundaries++;
|
||||
}
|
||||
|
||||
if(verbose_vm)
|
||||
kprintf("vm_contiguous: yes (%d boundaries tested)\n",
|
||||
boundaries);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int vm_checkrange_verbose = 0;
|
||||
|
||||
extern u32_t vmreqs;
|
||||
|
||||
/*===========================================================================*
|
||||
* vm_suspend *
|
||||
*===========================================================================*/
|
||||
PUBLIC int vm_suspend(struct proc *caller, struct proc *target)
|
||||
PUBLIC int vm_suspend(struct proc *caller, struct proc *target,
|
||||
vir_bytes linaddr, vir_bytes len, int wrflag, int type)
|
||||
{
|
||||
/* This range is not OK for this process. Set parameters
|
||||
* of the request and notify VM about the pending request.
|
||||
*/
|
||||
if(RTS_ISSET(caller, VMREQUEST))
|
||||
minix_panic("VMREQUEST already set", caller->p_endpoint);
|
||||
RTS_LOCK_SET(caller, VMREQUEST);
|
||||
vmassert(!RTS_ISSET(caller, VMREQUEST));
|
||||
vmassert(!RTS_ISSET(caller, VMREQTARGET));
|
||||
vmassert(!RTS_ISSET(target, VMREQUEST));
|
||||
vmassert(!RTS_ISSET(target, VMREQTARGET));
|
||||
|
||||
RTS_LOCK_SET(caller, VMREQUEST);
|
||||
RTS_LOCK_SET(target, VMREQTARGET);
|
||||
|
||||
#if DEBUG_VMASSERT
|
||||
caller->p_vmrequest.stacktrace[0] = '\0';
|
||||
util_stacktrace_strcat(caller->p_vmrequest.stacktrace);
|
||||
#endif
|
||||
|
||||
vmreqs++;
|
||||
|
||||
/* Set caller in target. */
|
||||
target->p_vmrequest.requestor = caller;
|
||||
caller->p_vmrequest.writeflag = 1;
|
||||
caller->p_vmrequest.start = linaddr;
|
||||
caller->p_vmrequest.length = len;
|
||||
caller->p_vmrequest.who = target->p_endpoint;
|
||||
caller->p_vmrequest.type = type;
|
||||
|
||||
/* Connect caller on vmrequest wait queue. */
|
||||
caller->p_vmrequest.nextrequestor = vmrequest;
|
||||
vmrequest = caller;
|
||||
if(!caller->p_vmrequest.nextrequestor)
|
||||
if(!(caller->p_vmrequest.nextrequestor = vmrequest))
|
||||
lock_notify(SYSTEM, VM_PROC_NR);
|
||||
vmrequest = caller;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* delivermsg *
|
||||
*===========================================================================*/
|
||||
int delivermsg(struct proc *rp)
|
||||
{
|
||||
phys_bytes addr;
|
||||
int r;
|
||||
NOREC_ENTER(deliver);
|
||||
|
||||
vmassert(rp->p_misc_flags & MF_DELIVERMSG);
|
||||
vmassert(rp->p_delivermsg.m_source != NONE);
|
||||
|
||||
vmassert(rp->p_delivermsg_lin);
|
||||
vmassert(rp->p_delivermsg_lin ==
|
||||
umap_local(rp, D, rp->p_delivermsg_vir, sizeof(message)));
|
||||
|
||||
vm_set_cr3(rp);
|
||||
|
||||
vmassert(intr_disabled());
|
||||
vmassert(!catch_pagefaults);
|
||||
catch_pagefaults = 1;
|
||||
addr = phys_copy(vir2phys(&rp->p_delivermsg),
|
||||
rp->p_delivermsg_lin, sizeof(message));
|
||||
vmassert(catch_pagefaults);
|
||||
catch_pagefaults = 0;
|
||||
|
||||
if(addr) {
|
||||
printf("phys_copy failed - addr 0x%lx\n", addr);
|
||||
vm_suspend(rp, rp, rp->p_delivermsg_lin, sizeof(message), 1,
|
||||
VMSTYPE_DELIVERMSG);
|
||||
r = VMSUSPEND;
|
||||
} else {
|
||||
#if DEBUG_VMASSERT
|
||||
rp->p_delivermsg.m_source = NONE;
|
||||
rp->p_delivermsg_lin = 0;
|
||||
#endif
|
||||
rp->p_misc_flags &= ~MF_DELIVERMSG;
|
||||
r = OK;
|
||||
}
|
||||
|
||||
NOREC_RETURN(deliver, r);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
@@ -491,22 +542,23 @@ PUBLIC int vm_checkrange(struct proc *caller, struct proc *target,
|
||||
|
||||
NOREC_ENTER(vmcheckrange);
|
||||
|
||||
vmcheckranges++;
|
||||
|
||||
if(!HASPT(target))
|
||||
NOREC_RETURN(vmcheckrange, OK);
|
||||
|
||||
/* If caller has had a reply to this request, return it. */
|
||||
if(RTS_ISSET(caller, VMREQUEST)) {
|
||||
if(!verifyrange && RTS_ISSET(caller, VMREQUEST)) {
|
||||
if(caller->p_vmrequest.who == target->p_endpoint) {
|
||||
if(caller->p_vmrequest.vmresult == VMSUSPEND)
|
||||
minix_panic("check sees VMSUSPEND?", NO_NUM);
|
||||
vmassert(caller->p_vmrequest.vmresult != VMSUSPEND);
|
||||
RTS_LOCK_UNSET(caller, VMREQUEST);
|
||||
#if 0
|
||||
#if 1
|
||||
kprintf("SYSTEM: vm_checkrange: returning vmresult %d\n",
|
||||
caller->p_vmrequest.vmresult);
|
||||
#endif
|
||||
NOREC_RETURN(vmcheckrange, caller->p_vmrequest.vmresult);
|
||||
} else {
|
||||
#if 0
|
||||
#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);
|
||||
@@ -525,25 +577,29 @@ PUBLIC int vm_checkrange(struct proc *caller, struct proc *target,
|
||||
|
||||
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(vm_lookup(target, v, &phys, &flags) == OK &&
|
||||
if((r=vm_lookup(target, v, &phys, &flags)) == OK &&
|
||||
!(wrfl && !(flags & I386_VM_WRITE))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!checkonly) {
|
||||
/* Set parameters in caller. */
|
||||
vm_suspend(caller, target);
|
||||
caller->p_vmrequest.writeflag = wrfl;
|
||||
caller->p_vmrequest.start = vir;
|
||||
caller->p_vmrequest.length = bytes;
|
||||
caller->p_vmrequest.who = target->p_endpoint;
|
||||
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);
|
||||
}
|
||||
|
||||
/* SYSTEM loop will fill in VMSTYPE_SYS_MESSAGE. */
|
||||
NOREC_RETURN(vmcheckrange, VMSUSPEND);
|
||||
}
|
||||
|
||||
@@ -636,9 +692,17 @@ 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
|
||||
for(i386_invlpg_addr = lin; i386_invlpg_addr <= limit;
|
||||
i386_invlpg_addr += I386_PAGE_SIZE)
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
u32_t thecr3;
|
||||
@@ -662,79 +726,77 @@ u32_t read_cr3(void)
|
||||
* address space), SEG (hardware segment), VIRT (in-datasegment
|
||||
* address if known).
|
||||
*/
|
||||
#define CREATEPDE(PROC, PTR, LINADDR, OFFSET, FREEPDE, VIRT, SEG, REMAIN, BYTES) { \
|
||||
#define CREATEPDE(PROC, PTR, LINADDR, REMAIN, BYTES) { \
|
||||
int proc_pde_index; \
|
||||
FIXME("CREATEPDE: check if invlpg is necessary"); \
|
||||
if(PROC == ptproc) { \
|
||||
FIXME("CREATEPDE: use in-memory process"); \
|
||||
} \
|
||||
if((PROC) && iskernelp(PROC) && SEG == D) { \
|
||||
PTR = VIRT; \
|
||||
OFFSET = 0; \
|
||||
proc_pde_index = I386_VM_PDE(LINADDR); \
|
||||
if((PROC) && (((PROC) == ptproc) || iskernelp(PROC))) { \
|
||||
PTR = LINADDR; \
|
||||
straightpdes++; \
|
||||
} else { \
|
||||
u32_t pdeval, *pdevalptr, newlin; \
|
||||
int pde_index; \
|
||||
int use_pde = NOPDE; \
|
||||
int fp; \
|
||||
int mustinvl; \
|
||||
u32_t pdeval, *pdevalptr, mask; \
|
||||
phys_bytes offset; \
|
||||
vmassert(psok); \
|
||||
pde_index = I386_VM_PDE(LINADDR); \
|
||||
vmassert(!iskernelp(PROC)); \
|
||||
createpde++; \
|
||||
if(PROC) { \
|
||||
u32_t *pdeptr; \
|
||||
u32_t *pdeptr; \
|
||||
vmassert(!iskernelp(PROC)); \
|
||||
vmassert(HASPT(PROC)); \
|
||||
pdeptr = PROCPDEPTR(PROC, pde_index); \
|
||||
pdeval = *pdeptr; \
|
||||
} else { \
|
||||
pdeptr = PROCPDEPTR(PROC, proc_pde_index); \
|
||||
pdeval = *pdeptr; \
|
||||
} else { \
|
||||
vmassert(!iskernelp(PROC)); \
|
||||
pdeval = (LINADDR & I386_VM_ADDR_MASK_4MB) | \
|
||||
I386_VM_BIGPAGE | I386_VM_PRESENT | \
|
||||
I386_VM_WRITE | I386_VM_USER; \
|
||||
} \
|
||||
*PROCPDEPTR(ptproc, FREEPDE) = pdeval; \
|
||||
newlin = I386_BIG_PAGE_SIZE*FREEPDE; \
|
||||
PTR = (u8_t *) phys2vir(newlin); \
|
||||
OFFSET = LINADDR & I386_VM_OFFSET_MASK_4MB; \
|
||||
REMAIN = MIN(REMAIN, I386_BIG_PAGE_SIZE - OFFSET); \
|
||||
invlpg_range(newlin + OFFSET, REMAIN); \
|
||||
for(fp = 0; fp < nfreepdes; fp++) { \
|
||||
int k = freepdes[fp]; \
|
||||
if(inusepde == k) \
|
||||
continue; \
|
||||
use_pde = k; \
|
||||
mask = PDEMASK(k); \
|
||||
vmassert(mask); \
|
||||
if(dirtypde & mask) \
|
||||
continue; \
|
||||
break; \
|
||||
} \
|
||||
vmassert(use_pde != NOPDE); \
|
||||
vmassert(mask); \
|
||||
if(dirtypde & mask) { \
|
||||
mustinvl = 1; \
|
||||
overwritepde++; \
|
||||
} else { \
|
||||
mustinvl = 0; \
|
||||
dirtypde |= mask; \
|
||||
newpde++; \
|
||||
} \
|
||||
inusepde = use_pde; \
|
||||
*PROCPDEPTR(ptproc, use_pde) = pdeval; \
|
||||
offset = LINADDR & I386_VM_OFFSET_MASK_4MB; \
|
||||
PTR = I386_BIG_PAGE_SIZE*use_pde + offset; \
|
||||
REMAIN = MIN(REMAIN, I386_BIG_PAGE_SIZE - offset); \
|
||||
if(1 || mustinvl) { \
|
||||
invlpg_range(PTR, REMAIN); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* arch_switch_copymsg *
|
||||
*===========================================================================*/
|
||||
phys_bytes arch_switch_copymsg(struct proc *rp, message *m, phys_bytes lin)
|
||||
{
|
||||
phys_bytes r;
|
||||
int u = 0;
|
||||
if(!intr_disabled()) { lock; u = 1; }
|
||||
if(rp->p_seg.p_cr3 && ptproc != rp) {
|
||||
vm_set_cr3(rp->p_seg.p_cr3);
|
||||
ptproc = rp;
|
||||
}
|
||||
r = phys_copy(vir2phys(m), lin, sizeof(message));
|
||||
if(u) { unlock; }
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* lin_lin_copy *
|
||||
*===========================================================================*/
|
||||
int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, u8_t *vsrc,
|
||||
int srcseg,
|
||||
struct proc *dstproc, vir_bytes dstlinaddr, u8_t *vdst,
|
||||
int dstseg,
|
||||
vir_bytes bytes)
|
||||
int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr,
|
||||
struct proc *dstproc, vir_bytes dstlinaddr, vir_bytes bytes)
|
||||
{
|
||||
u32_t addr;
|
||||
int procslot;
|
||||
u32_t catchrange_dst, catchrange_lo, catchrange_hi;
|
||||
NOREC_ENTER(linlincopy);
|
||||
|
||||
linlincopies++;
|
||||
|
||||
if(srcproc && dstproc && iskernelp(srcproc) && iskernelp(dstproc)) {
|
||||
memcpy(vdst, vsrc, bytes);
|
||||
NOREC_RETURN(linlincopy, OK);
|
||||
}
|
||||
|
||||
FIXME("lin_lin_copy requires big pages");
|
||||
vmassert(vm_running);
|
||||
vmassert(!catch_pagefaults);
|
||||
@@ -747,37 +809,30 @@ int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, u8_t *vsrc,
|
||||
procslot = ptproc->p_nr;
|
||||
|
||||
vmassert(procslot >= 0 && procslot < I386_VM_DIR_ENTRIES);
|
||||
vmassert(freepdes[FREEPDE_SRC] < freepdes[FREEPDE_DST]);
|
||||
|
||||
catchrange_lo = I386_BIG_PAGE_SIZE*freepdes[FREEPDE_SRC];
|
||||
catchrange_dst = I386_BIG_PAGE_SIZE*freepdes[FREEPDE_DST];
|
||||
catchrange_hi = I386_BIG_PAGE_SIZE*(freepdes[FREEPDE_DST]+1);
|
||||
|
||||
while(bytes > 0) {
|
||||
u8_t *srcptr, *dstptr;
|
||||
vir_bytes srcoffset, dstoffset;
|
||||
phys_bytes srcptr, dstptr;
|
||||
vir_bytes chunk = bytes;
|
||||
|
||||
/* Set up 4MB ranges. */
|
||||
CREATEPDE(srcproc, srcptr, srclinaddr, srcoffset,
|
||||
freepdes[FREEPDE_SRC], vsrc, srcseg, chunk, bytes);
|
||||
CREATEPDE(dstproc, dstptr, dstlinaddr, dstoffset,
|
||||
freepdes[FREEPDE_DST], vdst, dstseg, chunk, bytes);
|
||||
inusepde = NOPDE;
|
||||
CREATEPDE(srcproc, srcptr, srclinaddr, chunk, bytes);
|
||||
CREATEPDE(dstproc, dstptr, dstlinaddr, chunk, bytes);
|
||||
|
||||
/* Copy pages. */
|
||||
vmassert(intr_disabled());
|
||||
vmassert(!catch_pagefaults);
|
||||
catch_pagefaults = 1;
|
||||
addr=_memcpy_k(dstptr + dstoffset, srcptr + srcoffset, chunk);
|
||||
addr=phys_copy(srcptr, dstptr, chunk);
|
||||
vmassert(intr_disabled());
|
||||
vmassert(catch_pagefaults);
|
||||
catch_pagefaults = 0;
|
||||
|
||||
if(addr) {
|
||||
if(addr >= catchrange_lo && addr < catchrange_dst) {
|
||||
if(addr >= srcptr && addr < (srcptr + chunk)) {
|
||||
NOREC_RETURN(linlincopy, EFAULT_SRC);
|
||||
}
|
||||
if(addr >= catchrange_dst && addr < catchrange_hi) {
|
||||
if(addr >= dstptr && addr < (dstptr + chunk)) {
|
||||
NOREC_RETURN(linlincopy, EFAULT_DST);
|
||||
}
|
||||
minix_panic("lin_lin_copy fault out of range", NO_NUM);
|
||||
@@ -785,15 +840,11 @@ int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, u8_t *vsrc,
|
||||
/* Not reached. */
|
||||
NOREC_RETURN(linlincopy, EFAULT);
|
||||
}
|
||||
|
||||
vmassert(memcmp(dstptr + dstoffset, srcptr + srcoffset, chunk) == 0);
|
||||
|
||||
/* Update counter and addresses for next iteration, if any. */
|
||||
bytes -= chunk;
|
||||
srclinaddr += chunk;
|
||||
dstlinaddr += chunk;
|
||||
vsrc += chunk;
|
||||
vdst += chunk;
|
||||
}
|
||||
|
||||
NOREC_RETURN(linlincopy, OK);
|
||||
@@ -805,12 +856,12 @@ int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, u8_t *vsrc,
|
||||
int vm_phys_memset(phys_bytes ph, u8_t c, phys_bytes bytes)
|
||||
{
|
||||
char *v;
|
||||
u32_t p;
|
||||
p = c | (c << 8) | (c << 16) | (c << 24);
|
||||
|
||||
physzero++;
|
||||
|
||||
if(!vm_running) {
|
||||
u32_t p;
|
||||
p = c | (c << 8) | (c << 16) | (c << 24);
|
||||
phys_memset(ph, p, bytes);
|
||||
return OK;
|
||||
}
|
||||
@@ -822,14 +873,13 @@ int vm_phys_memset(phys_bytes ph, u8_t c, phys_bytes bytes)
|
||||
*/
|
||||
while(bytes > 0) {
|
||||
vir_bytes chunk = bytes;
|
||||
u8_t *ptr;
|
||||
u32_t offset;
|
||||
CREATEPDE(((struct proc *) NULL), ptr, ph,
|
||||
offset, freepdes[FREEPDE_MEMSET], 0, 0, chunk, bytes);
|
||||
phys_bytes ptr;
|
||||
inusepde = NOPDE;
|
||||
CREATEPDE(((struct proc *) NULL), ptr, ph, chunk, bytes);
|
||||
/* We can memset as many bytes as we have remaining,
|
||||
* or as many as remain in the 4MB chunk we mapped in.
|
||||
*/
|
||||
memset(ptr + offset, c, chunk);
|
||||
phys_memset(ptr, p, chunk);
|
||||
bytes -= chunk;
|
||||
ph += chunk;
|
||||
}
|
||||
@@ -930,30 +980,43 @@ int vmcheck; /* if nonzero, can return VMSUSPEND */
|
||||
|
||||
if(vm_running) {
|
||||
int r;
|
||||
struct proc *target, *caller;
|
||||
struct proc *caller;
|
||||
|
||||
caller = proc_addr(who_p);
|
||||
|
||||
if(RTS_ISSET(caller, VMREQUEST)) {
|
||||
struct proc *target;
|
||||
int pn;
|
||||
vmassert(caller->p_vmrequest.vmresult != VMSUSPEND);
|
||||
RTS_LOCK_UNSET(caller, VMREQUEST);
|
||||
if(caller->p_vmrequest.vmresult != OK) {
|
||||
printf("virtual_copy: returning VM error %d\n",
|
||||
caller->p_vmrequest.vmresult);
|
||||
NOREC_RETURN(virtualcopy, caller->p_vmrequest.vmresult);
|
||||
}
|
||||
}
|
||||
|
||||
if((r=lin_lin_copy(procs[_SRC_], phys_addr[_SRC_],
|
||||
(u8_t *) src_addr->offset, src_addr->segment,
|
||||
procs[_DST_], phys_addr[_DST_], (u8_t *) dst_addr->offset,
|
||||
dst_addr->segment, bytes)) != OK) {
|
||||
procs[_DST_], phys_addr[_DST_], bytes)) != OK) {
|
||||
struct proc *target;
|
||||
int wr;
|
||||
phys_bytes lin;
|
||||
if(r != EFAULT_SRC && r != EFAULT_DST)
|
||||
minix_panic("lin_lin_copy failed", r);
|
||||
if(!vmcheck) {
|
||||
NOREC_RETURN(virtualcopy, r);
|
||||
}
|
||||
|
||||
caller = proc_addr(who_p);
|
||||
|
||||
vmassert(procs[_SRC_] && procs[_DST_]);
|
||||
|
||||
if(r == EFAULT_SRC) {
|
||||
caller->p_vmrequest.start = phys_addr[_SRC_];
|
||||
lin = phys_addr[_SRC_];
|
||||
target = procs[_SRC_];
|
||||
caller->p_vmrequest.writeflag = 0;
|
||||
wr = 0;
|
||||
} else if(r == EFAULT_DST) {
|
||||
caller->p_vmrequest.start = phys_addr[_DST_];
|
||||
lin = phys_addr[_DST_];
|
||||
target = procs[_DST_];
|
||||
caller->p_vmrequest.writeflag = 1;
|
||||
wr = 1;
|
||||
} else {
|
||||
minix_panic("r strange", r);
|
||||
}
|
||||
@@ -964,10 +1027,9 @@ int vmcheck; /* if nonzero, can return VMSUSPEND */
|
||||
target->p_endpoint, target->p_name);
|
||||
#endif
|
||||
|
||||
caller->p_vmrequest.length = bytes;
|
||||
caller->p_vmrequest.who = target->p_endpoint;
|
||||
|
||||
vm_suspend(caller, target);
|
||||
vmassert(k_reenter == -1);
|
||||
vmassert(proc_ptr->p_endpoint == SYSTEM);
|
||||
vm_suspend(caller, target, lin, bytes, wr, VMSTYPE_KERNELCALL);
|
||||
|
||||
NOREC_RETURN(virtualcopy, VMSUSPEND);
|
||||
}
|
||||
@@ -990,7 +1052,8 @@ int vmcheck; /* if nonzero, can return VMSUSPEND */
|
||||
}
|
||||
|
||||
/* Now copy bytes between physical addresseses. */
|
||||
phys_copy(phys_addr[_SRC_], phys_addr[_DST_], (phys_bytes) bytes);
|
||||
if(phys_copy(phys_addr[_SRC_], phys_addr[_DST_], (phys_bytes) bytes))
|
||||
NOREC_RETURN(virtualcopy, EFAULT);
|
||||
|
||||
NOREC_RETURN(virtualcopy, OK);
|
||||
}
|
||||
|
||||
@@ -73,10 +73,7 @@ begbss:
|
||||
|
||||
.define _restart
|
||||
.define save
|
||||
.define _pagefault_cr2
|
||||
.define _pagefault_count
|
||||
.define _old_eip_ptr
|
||||
.define _old_eax_ptr
|
||||
.define _cr3_test
|
||||
.define _cr3_reload
|
||||
.define _write_cr3 ! write cr3
|
||||
@@ -104,6 +101,8 @@ begbss:
|
||||
.define _params_size
|
||||
.define _params_offset
|
||||
.define _mon_ds
|
||||
.define _schedcheck
|
||||
.define _dirtypde
|
||||
|
||||
.define _hwint00 ! handlers for hardware interrupts
|
||||
.define _hwint01
|
||||
@@ -395,7 +394,7 @@ _p_s_call:
|
||||
|
||||
call _sys_call ! sys_call(call_nr, src_dst, m_ptr, bit_map)
|
||||
! caller is now explicitly in proc_ptr
|
||||
mov AXREG(esi), eax ! sys_call MUST PRESERVE si
|
||||
mov AXREG(esi), eax
|
||||
|
||||
! Fall into code to restart proc/task running.
|
||||
|
||||
@@ -406,25 +405,22 @@ _restart:
|
||||
|
||||
! Restart the current process or the next process if it is set.
|
||||
|
||||
cmp (_next_ptr), 0 ! see if another process is scheduled
|
||||
jz 0f
|
||||
mov eax, (_next_ptr)
|
||||
mov (_proc_ptr), eax ! schedule new process
|
||||
mov (_next_ptr), 0
|
||||
0: mov esp, (_proc_ptr) ! will assume P_STACKBASE == 0
|
||||
call _schedcheck ! ask C function who we're running
|
||||
mov esp, (_proc_ptr) ! will assume P_STACKBASE == 0
|
||||
lldt P_LDT_SEL(esp) ! enable process' segment descriptors
|
||||
inc (_cr3_test)
|
||||
cmp P_CR3(esp), 0 ! process does not have its own PT
|
||||
jz noload
|
||||
jz 0f
|
||||
mov eax, P_CR3(esp)
|
||||
cmp eax, (loadedcr3)
|
||||
jz noload
|
||||
jz 0f
|
||||
inc (_cr3_reload)
|
||||
mov cr3, eax
|
||||
mov (loadedcr3), eax
|
||||
mov eax, (_proc_ptr)
|
||||
mov (_ptproc), eax
|
||||
noload:
|
||||
! 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
|
||||
restart1:
|
||||
@@ -500,7 +496,7 @@ _page_fault:
|
||||
push PAGE_FAULT_VECTOR
|
||||
push eax
|
||||
mov eax, cr2
|
||||
sseg mov (_pagefault_cr2), eax
|
||||
sseg mov (pagefaultcr2), eax
|
||||
sseg inc (_pagefault_count)
|
||||
pop eax
|
||||
jmp errexception
|
||||
@@ -530,8 +526,8 @@ errexception:
|
||||
sseg pop (ex_number)
|
||||
sseg pop (trap_errno)
|
||||
exception1: ! Common for all exceptions.
|
||||
sseg mov (_old_eax_ptr), esp ! where will eax be saved?
|
||||
sseg sub (_old_eax_ptr), PCREG-AXREG ! here
|
||||
sseg mov (old_eax_ptr), esp ! where will eax be saved?
|
||||
sseg sub (old_eax_ptr), PCREG-AXREG ! here
|
||||
|
||||
push eax ! eax is scratch register
|
||||
|
||||
@@ -539,7 +535,7 @@ exception1: ! Common for all exceptions.
|
||||
sseg mov (old_eip), eax
|
||||
mov eax, esp
|
||||
add eax, 4
|
||||
sseg mov (_old_eip_ptr), eax
|
||||
sseg mov (old_eip_ptr), eax
|
||||
movzx eax, 4+4(esp) ! old cs
|
||||
sseg mov (old_cs), eax
|
||||
mov eax, 8+4(esp) ! old eflags
|
||||
@@ -547,6 +543,9 @@ exception1: ! Common for all exceptions.
|
||||
|
||||
pop eax
|
||||
call save
|
||||
push (pagefaultcr2)
|
||||
push (old_eax_ptr)
|
||||
push (old_eip_ptr)
|
||||
push (old_eflags)
|
||||
push (old_cs)
|
||||
push (old_eip)
|
||||
@@ -554,7 +553,7 @@ exception1: ! Common for all exceptions.
|
||||
push (ex_number)
|
||||
call _exception ! (ex_number, trap_errno, old_eip,
|
||||
! old_cs, old_eflags)
|
||||
add esp, 5*4
|
||||
add esp, 8*4
|
||||
ret
|
||||
|
||||
|
||||
@@ -566,8 +565,14 @@ _write_cr3:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
mov eax, 8(ebp)
|
||||
inc (_cr3_test)
|
||||
! cmp eax, (loadedcr3)
|
||||
! jz 0f
|
||||
inc (_cr3_reload)
|
||||
mov cr3, eax
|
||||
mov (loadedcr3), eax
|
||||
! mov (_dirtypde), 0
|
||||
0:
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
@@ -591,8 +596,11 @@ k_stack:
|
||||
k_stktop: ! top of kernel stack
|
||||
.comm ex_number, 4
|
||||
.comm trap_errno, 4
|
||||
.comm old_eip_ptr, 4
|
||||
.comm old_eax_ptr, 4
|
||||
.comm old_eip, 4
|
||||
.comm old_cs, 4
|
||||
.comm old_eflags, 4
|
||||
.comm pagefaultcr2, 4
|
||||
.comm loadedcr3, 4
|
||||
|
||||
|
||||
@@ -52,11 +52,13 @@ _PROTOTYPE( void vir_outsw, (u16_t port, struct proc *proc, u32_t vir, size_t co
|
||||
_PROTOTYPE( void i386_updatepde, (int pde, u32_t val));
|
||||
_PROTOTYPE( void i386_freepde, (int pde));
|
||||
_PROTOTYPE( void getcr3val, (void));
|
||||
_PROTOTYPE( void switchedcr3, (void));
|
||||
|
||||
|
||||
/* exception.c */
|
||||
_PROTOTYPE( void exception, (unsigned vec_nr, u32_t trap_errno,
|
||||
u32_t old_eip, U16_t old_cs, u32_t old_eflags) );
|
||||
u32_t old_eip, U16_t old_cs, u32_t old_eflags,
|
||||
u32_t *old_eip_ptr, u32_t *old_eax_ptr, u32_t pagefaultcr2) );
|
||||
|
||||
/* klib386.s */
|
||||
_PROTOTYPE( void level0, (void (*func)(void)) );
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
|
||||
#include "proto.h"
|
||||
#include "../../proc.h"
|
||||
#include "../../debug.h"
|
||||
|
||||
#define CR0_EM 0x0004 /* set to enable trap on any FP instruction */
|
||||
|
||||
FORWARD _PROTOTYPE( void ser_debug, (int c));
|
||||
FORWARD _PROTOTYPE( void ser_dump_stats, (void));
|
||||
|
||||
PUBLIC void arch_shutdown(int how)
|
||||
{
|
||||
@@ -139,39 +139,65 @@ PUBLIC void do_ser_debug()
|
||||
|
||||
PRIVATE void ser_debug(int c)
|
||||
{
|
||||
int u = 0;
|
||||
|
||||
do_serial_debug++;
|
||||
kprintf("ser_debug: %d\n", c);
|
||||
/* Disable interrupts so that we get a consistent state. */
|
||||
if(!intr_disabled()) { lock; u = 1; };
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case '1':
|
||||
ser_dump_proc();
|
||||
break;
|
||||
case '2':
|
||||
ser_dump_stats();
|
||||
ser_dump_queues();
|
||||
break;
|
||||
#define TOGGLECASE(ch, flag) \
|
||||
case ch: { \
|
||||
if(verboseflags & flag) { \
|
||||
verboseflags &= ~flag; \
|
||||
printf("%s disabled\n", #flag); \
|
||||
} else { \
|
||||
verboseflags |= flag; \
|
||||
printf("%s enabled\n", #flag); \
|
||||
} \
|
||||
break; \
|
||||
}
|
||||
TOGGLECASE('8', VF_SCHEDULING)
|
||||
TOGGLECASE('9', VF_PICKPROC)
|
||||
}
|
||||
do_serial_debug--;
|
||||
if(u) { unlock; }
|
||||
}
|
||||
|
||||
PRIVATE void printslot(struct proc *pp)
|
||||
PRIVATE void printslot(struct proc *pp, int level)
|
||||
{
|
||||
static int level = 0;
|
||||
struct proc *depproc = NULL;
|
||||
int dep = NONE;
|
||||
#define COL { int i; for(i = 0; i < level; i++) printf("> "); }
|
||||
|
||||
if(level >= NR_PROCS) {
|
||||
kprintf("loop??\n");
|
||||
return;
|
||||
}
|
||||
|
||||
level++;
|
||||
if(pp->p_ready && pp->p_rts_flags) {
|
||||
printf("HUH? p_ready but rts flags!\n");
|
||||
}
|
||||
|
||||
kprintf("%*s %d: %s %d prio %d/%d time %d/%d cr3 0x%lx rts %s misc %s ",
|
||||
level, "",
|
||||
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",
|
||||
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));
|
||||
rtsflagstr(pp->p_rts_flags), miscflagstr(pp->p_misc_flags),
|
||||
pp->p_ready);
|
||||
|
||||
if(pp->p_rts_flags & SENDING) {
|
||||
dep = pp->p_sendto_e;
|
||||
@@ -201,65 +227,46 @@ PRIVATE void printslot(struct proc *pp)
|
||||
} else {
|
||||
kprintf("\n");
|
||||
}
|
||||
kprintf("%*s ", 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--;
|
||||
printslot(depproc, level+1);
|
||||
}
|
||||
|
||||
PUBLIC void ser_dump_queues()
|
||||
{
|
||||
int q;
|
||||
for(q = 0; q < NR_SCHED_QUEUES; q++) {
|
||||
struct proc *p;
|
||||
if(rdy_head[q])
|
||||
printf("%2d: ", q);
|
||||
for(p = rdy_head[q]; p; p = p->p_nextready) {
|
||||
printf("%s / %d ", p->p_name, p->p_endpoint);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PUBLIC void ser_dump_proc()
|
||||
{
|
||||
struct proc *pp;
|
||||
int u = 0;
|
||||
|
||||
/* Disable interrupts so that we get a consistent state. */
|
||||
if(!intr_disabled()) { lock; u = 1; };
|
||||
CHECK_RUNQUEUES;
|
||||
|
||||
for (pp= BEG_PROC_ADDR; pp < END_PROC_ADDR; pp++)
|
||||
{
|
||||
if (pp->p_rts_flags & SLOT_FREE)
|
||||
continue;
|
||||
printslot(pp);
|
||||
printslot(pp, 0);
|
||||
}
|
||||
|
||||
if(u) { unlock; }
|
||||
}
|
||||
|
||||
PRIVATE void ser_dump_stats()
|
||||
{
|
||||
kprintf("ipc_stats:\n");
|
||||
kprintf("deadproc: %d\n", ipc_stats.deadproc);
|
||||
kprintf("bad_endpoint: %d\n", ipc_stats.bad_endpoint);
|
||||
kprintf("dst_not_allowed: %d\n", ipc_stats.dst_not_allowed);
|
||||
kprintf("bad_call: %d\n", ipc_stats.bad_call);
|
||||
kprintf("call_not_allowed: %d\n", ipc_stats.call_not_allowed);
|
||||
kprintf("bad_buffer: %d\n", ipc_stats.bad_buffer);
|
||||
kprintf("deadlock: %d\n", ipc_stats.deadlock);
|
||||
kprintf("not_ready: %d\n", ipc_stats.not_ready);
|
||||
kprintf("src_died: %d\n", ipc_stats.src_died);
|
||||
kprintf("dst_died: %d\n", ipc_stats.dst_died);
|
||||
kprintf("no_priv: %d\n", ipc_stats.no_priv);
|
||||
kprintf("bad_size: %d\n", ipc_stats.bad_size);
|
||||
kprintf("bad_senda: %d\n", ipc_stats.bad_senda);
|
||||
if (ex64hi(ipc_stats.total))
|
||||
{
|
||||
kprintf("total: %x:%08x\n", ex64hi(ipc_stats.total),
|
||||
ex64lo(ipc_stats.total));
|
||||
}
|
||||
else
|
||||
kprintf("total: %u\n", ex64lo(ipc_stats.total));
|
||||
|
||||
kprintf("sys_stats:\n");
|
||||
kprintf("bad_req: %d\n", sys_stats.bad_req);
|
||||
kprintf("not_allowed: %d\n", sys_stats.not_allowed);
|
||||
if (ex64hi(sys_stats.total))
|
||||
{
|
||||
kprintf("total: %x:%08x\n", ex64hi(sys_stats.total),
|
||||
ex64lo(sys_stats.total));
|
||||
}
|
||||
else
|
||||
kprintf("total: %u\n", ex64lo(sys_stats.total));
|
||||
}
|
||||
|
||||
#if SPROFILE
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
|
||||
.define _last_cr3
|
||||
|
||||
#define LOADCR3WITHEAX(type, newcr3, ptproc) ;\
|
||||
sseg inc (_cr3switch) ;\
|
||||
sseg mov eax, newcr3 ;\
|
||||
sseg cmp (_last_cr3), eax ;\
|
||||
jz 8f ;\
|
||||
mov cr3, eax ;\
|
||||
sseg inc (_cr3reload) ;\
|
||||
sseg mov (_last_cr3), eax ;\
|
||||
sseg mov eax, (ptproc) ;\
|
||||
sseg mov (_ptproc), eax ;\
|
||||
8:
|
||||
|
||||
Reference in New Issue
Block a user