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:
Tomas Hruby
2010-04-26 23:21:26 +00:00
parent a131085a5b
commit f51eea4b32
13 changed files with 104 additions and 178 deletions

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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 */