minix/lib/libsys/sys_vmctl.c
Tomas Hruby 12ef495cac atomicity fix when enabling paging
- before enabling paging VM asks kernel to resize its segments. This
  may cause kernel to segfault if APIC is used and an interrupt
  happens between this and paging enabled. As these are 2 separate
  vmctl calls it is not atomic. This patch fixes this problem. VM does
  not ask kernel to resize the segments in a separate call anymore.
  The new segments limit is part of the "enable paging" call. It
  generalizes this call in such a way that more information can be
  passed as need be or the information may be completely different if
  another architecture requires this.
2010-03-22 07:42:52 +00:00

108 lines
2.1 KiB
C

#include "syslib.h"
PUBLIC int sys_vmctl(endpoint_t who, int param, u32_t value)
{
message m;
int r;
m.SVMCTL_WHO = who;
m.SVMCTL_PARAM = param;
m.SVMCTL_VALUE = value;
r = _kernel_call(SYS_VMCTL, &m);
return(r);
}
PUBLIC int sys_vmctl_get_pagefault_i386(endpoint_t *who, u32_t *cr2, u32_t *err)
{
message m;
int r;
m.SVMCTL_WHO = SELF;
m.SVMCTL_PARAM = VMCTL_GET_PAGEFAULT;
r = _kernel_call(SYS_VMCTL, &m);
if(r == OK) {
*who = m.SVMCTL_PF_WHO;
*cr2 = m.SVMCTL_PF_I386_CR2;
*err = m.SVMCTL_PF_I386_ERR;
}
return(r);
}
PUBLIC int sys_vmctl_get_cr3_i386(endpoint_t who, u32_t *cr3)
{
message m;
int r;
m.SVMCTL_WHO = who;
m.SVMCTL_PARAM = VMCTL_I386_GETCR3;
r = _kernel_call(SYS_VMCTL, &m);
if(r == OK) {
*cr3 = m.SVMCTL_VALUE;
}
return(r);
}
PUBLIC int sys_vmctl_get_memreq(endpoint_t *who, vir_bytes *mem,
vir_bytes *len, int *wrflag, endpoint_t *who_s, vir_bytes *mem_s,
endpoint_t *requestor)
{
message m;
int r;
m.SVMCTL_WHO = SELF;
m.SVMCTL_PARAM = VMCTL_MEMREQ_GET;
r = _kernel_call(SYS_VMCTL, &m);
if(r >= 0) {
*who = m.SVMCTL_MRG_TARGET;
*mem = m.SVMCTL_MRG_ADDR;
*len = m.SVMCTL_MRG_LENGTH;
*wrflag = m.SVMCTL_MRG_FLAG;
*who_s = m.SVMCTL_MRG_EP2;
*mem_s = m.SVMCTL_MRG_ADDR2;
*requestor = (endpoint_t) m.SVMCTL_MRG_REQUESTOR;
}
return r;
}
PUBLIC int sys_vmctl_enable_paging(void * data)
{
message m;
m.SVMCTL_WHO = SELF;
m.SVMCTL_PARAM = VMCTL_ENABLE_PAGING;
m.SVMCTL_VALUE = (u32_t) data;
return _kernel_call(SYS_VMCTL, &m);
}
PUBLIC int sys_vmctl_get_mapping(int index,
phys_bytes *addr, phys_bytes *len, int *flags)
{
int r;
message m;
m.SVMCTL_WHO = SELF;
m.SVMCTL_PARAM = VMCTL_KERN_PHYSMAP;
m.SVMCTL_VALUE = (int) index;
r = _kernel_call(SYS_VMCTL, &m);
if(r != OK)
return r;
*addr = m.SVMCTL_MAP_PHYS_ADDR;
*len = m.SVMCTL_MAP_PHYS_LEN;
*flags = m.SVMCTL_MAP_FLAGS;
return OK;
}
PUBLIC int sys_vmctl_reply_mapping(int index, vir_bytes addr)
{
message m;
m.SVMCTL_WHO = SELF;
m.SVMCTL_PARAM = VMCTL_KERN_MAP_REPLY;
m.SVMCTL_VALUE = index;
m.SVMCTL_MAP_VIR_ADDR = (char *) addr;
return _kernel_call(SYS_VMCTL, &m);
}