summaryrefslogtreecommitdiff
path: root/kern/hvcall.c
diff options
context:
space:
mode:
Diffstat (limited to 'kern/hvcall.c')
-rw-r--r--kern/hvcall.c40
1 files changed, 35 insertions, 5 deletions
diff --git a/kern/hvcall.c b/kern/hvcall.c
index 1513942..d8dfeed 100644
--- a/kern/hvcall.c
+++ b/kern/hvcall.c
@@ -36,6 +36,7 @@
#define HV_REFPD_OP HV_RESERVED_0
#define HV_UNREFPD_OP HV_RESERVED_1
+#define HV_LOADPD_OP HV_RESERVED_2
static void hvcall_exit(stack_frame_t* f);
static void hvcall_iret(stack_frame_t* f);
@@ -49,6 +50,7 @@ static void hvcall_get_cursor(stack_frame_t* f);
static void hvcall_print_at(stack_frame_t* f);
static void hvcall_refpd(int ref);
+static void hvcall_loadpd(stack_frame_t* f);
// 0: not pv, 1: processed
int handle_pv_syscall(stack_frame_t* f, int index) {
@@ -114,6 +116,9 @@ void sys_hvcall_real(stack_frame_t* f) {
case HV_UNREFPD_OP:
hvcall_refpd(0);
break;
+ case HV_LOADPD_OP:
+ hvcall_loadpd(f);
+ break;
default:
pv_die("Bad hvcall number");
break;
@@ -223,7 +228,7 @@ static void hvcall_setpd(stack_frame_t* f) {
goto alloc_pd_fail;
}
queue_insert_head(&pv->shadow_pds, &pv_pd->pv_link);
- select_pv_pd(t->process, pv_pd);
+ pv_select_pd(t->process, pv_pd);
return;
alloc_pd_fail:
@@ -662,13 +667,38 @@ read_arg_fail:
}
static void hvcall_refpd(int ref) {
- pv_t* pv = get_current()->process->pv;
+ pv_pd_t* pv_pd = get_current()->process->pv->active_shadow_pd;
if (ref == 1) {
- pv->active_shadow_pd->refcount++;
+ pv_pd->refcount++;
} else {
- pv->active_shadow_pd->refcount--;
- if (pv->active_shadow_pd->refcount <= 0) {
+ pv_pd->refcount--;
+ if (pv_pd->refcount <= 0) {
pv_die("Page table destroyed by kerenl");
}
}
}
+
+static void hvcall_loadpd(stack_frame_t* f) {
+ reg_t esp = f->esp;
+ pa_t pd;
+ if (copy_from_user(esp, sizeof(pa_t), &pd) != 0) {
+ goto read_arg_fail;
+ }
+ process_t* p = get_current()->process;
+ pv_t* pv = p->pv;
+ queue_t* node = pv->shadow_pds;
+ queue_t* end = node;
+ do {
+ pv_pd_t* pv_pd = queue_data(node, pv_pd_t, pv_link);
+ if (pv_pd->guest_pd == pd + USER_MEM_START) {
+ pv_select_pd(p, pv_pd);
+ return;
+ }
+ node = node->next;
+ sfree(pv_pd, sizeof(pv_pd_t));
+ } while (node != end);
+ pv_die("Loading a nonexist page table");
+
+read_arg_fail:
+ pv_die("Bad argument address");
+}