Changed pagefault delivery to VM
this patch changes the way pagefaults are delivered to VM. It adopts the same model as the out-of-quantum messages sent by kernel to a scheduler. - everytime a userspace pagefault occurs, kernel creates a message which is sent to VM on behalf of the faulting process - the process is blocked on delivery to VM in the standard IPC code instead of waiting in a spacial in-kernel queue (stack) and is not runnable until VM tell kernel that the pagefault is resolved and is free to clear the RTS_PAGEFAULT flag. - VM does not need call kernel and poll the pagefault information which saves many (1/2?) calls and kernel calls that return "no more data" - VM notification by kernel does not need to use signals - each entry in proc table is by 12 bytes smaller (~3k save)
This commit is contained in:
@@ -41,19 +41,6 @@ struct proc *p;
|
||||
/* Increase process SP. */
|
||||
p->p_reg.sp += m_ptr->SVMCTL_VALUE;
|
||||
return OK;
|
||||
case VMCTL_GET_PAGEFAULT:
|
||||
{
|
||||
struct proc *rp;
|
||||
if(!(rp=pagefaults))
|
||||
return ESRCH;
|
||||
pagefaults = rp->p_nextpagefault;
|
||||
if(!RTS_ISSET(rp, RTS_PAGEFAULT))
|
||||
panic( "non-PAGEFAULT process on pagefault chain: %d", rp->p_endpoint);
|
||||
m_ptr->SVMCTL_PF_WHO = rp->p_endpoint;
|
||||
m_ptr->SVMCTL_PF_I386_CR2 = rp->p_pagefault.pf_virtual;
|
||||
m_ptr->SVMCTL_PF_I386_ERR = rp->p_pagefault.pf_flags;
|
||||
return OK;
|
||||
}
|
||||
case VMCTL_I386_KERNELLIMIT:
|
||||
{
|
||||
int r;
|
||||
|
||||
@@ -20,6 +20,8 @@ void pagefault( struct proc *pr,
|
||||
int in_physcopy = 0;
|
||||
|
||||
reg_t pagefaultcr2;
|
||||
message m_pagefault;
|
||||
int err;
|
||||
|
||||
assert(frame);
|
||||
|
||||
@@ -77,17 +79,16 @@ void pagefault( struct proc *pr,
|
||||
assert(!RTS_ISSET(pr, RTS_PAGEFAULT));
|
||||
RTS_SET(pr, RTS_PAGEFAULT);
|
||||
|
||||
/* Save pagefault details, suspend process,
|
||||
* add process to pagefault chain,
|
||||
* and tell VM there is a pagefault to be
|
||||
* handled.
|
||||
*/
|
||||
pr->p_pagefault.pf_virtual = pagefaultcr2;
|
||||
pr->p_pagefault.pf_flags = frame->errcode;
|
||||
pr->p_nextpagefault = pagefaults;
|
||||
pagefaults = pr;
|
||||
|
||||
send_sig(VM_PROC_NR, SIGKPF);
|
||||
/* tell Vm about the pagefault */
|
||||
m_pagefault.m_source = pr->p_endpoint;
|
||||
m_pagefault.m_type = VM_PAGEFAULT;
|
||||
m_pagefault.VPF_ADDR = pagefaultcr2;
|
||||
m_pagefault.VPF_FLAGS = frame->errcode;
|
||||
|
||||
if ((err = mini_send(pr, VM_PROC_NR,
|
||||
&m_pagefault, FROM_KERNEL))) {
|
||||
panic("WARNING: pagefault: mini_send returned %d\n", err);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ EXTERN struct loadinfo kloadinfo; /* status of load average */
|
||||
EXTERN struct proc *proc_ptr; /* pointer to currently running process */
|
||||
EXTERN struct proc *bill_ptr; /* process to bill for clock ticks */
|
||||
EXTERN struct proc *vmrequest; /* first process on vmrequest queue */
|
||||
EXTERN struct proc *pagefaults; /* first process on pagefault queue */
|
||||
EXTERN unsigned lost_ticks; /* clock ticks counted outside clock task */
|
||||
|
||||
|
||||
|
||||
@@ -31,8 +31,6 @@ struct proc {
|
||||
struct proc *p_scheduler; /* who should get out of quantum msg */
|
||||
|
||||
struct mem_map p_memmap[NR_LOCAL_SEGS]; /* memory map (T, D, S) */
|
||||
struct pagefault p_pagefault; /* valid if PAGEFAULT in p_rts_flags set */
|
||||
struct proc *p_nextpagefault; /* next on PAGEFAULT chain */
|
||||
|
||||
clock_t p_user_time; /* user time in ticks */
|
||||
clock_t p_sys_time; /* sys time in ticks */
|
||||
|
||||
Reference in New Issue
Block a user