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