aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlauber de Oliveira Costa <gcosta@redhat.com>2008-01-07 08:05:27 -0500
committerRusty Russell <rusty@rustcorp.com.au>2008-01-30 06:50:08 -0500
commit73044f05a4ac65f2df42753e9566444b9d2a660f (patch)
tree80a3e1d1bda31a769554a8c51f8c189ccec0b9f8
parent7ea07a1500f05e06ebf0136763c781244f77a2a1 (diff)
lguest: make hypercalls use the vcpu struct
this patch changes do_hcall() and do_async_hcall() interfaces (and obviously their callers) to get a vcpu struct. Again, a vcpu services the hypercall, not the whole guest Signed-off-by: Glauber de Oliveira Costa <gcosta@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--drivers/lguest/core.c6
-rw-r--r--drivers/lguest/hypercalls.c42
-rw-r--r--drivers/lguest/lg.h16
-rw-r--r--drivers/lguest/x86/core.c16
4 files changed, 44 insertions, 36 deletions
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c
index 75b38f2c778a..0ea67cb0cc0b 100644
--- a/drivers/lguest/core.c
+++ b/drivers/lguest/core.c
@@ -181,8 +181,8 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
181 /* We stop running once the Guest is dead. */ 181 /* We stop running once the Guest is dead. */
182 while (!lg->dead) { 182 while (!lg->dead) {
183 /* First we run any hypercalls the Guest wants done. */ 183 /* First we run any hypercalls the Guest wants done. */
184 if (lg->hcall) 184 if (cpu->hcall)
185 do_hypercalls(lg); 185 do_hypercalls(cpu);
186 186
187 /* It's possible the Guest did a NOTIFY hypercall to the 187 /* It's possible the Guest did a NOTIFY hypercall to the
188 * Launcher, in which case we return from the read() now. */ 188 * Launcher, in which case we return from the read() now. */
@@ -234,7 +234,7 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user)
234 local_irq_enable(); 234 local_irq_enable();
235 235
236 /* Now we deal with whatever happened to the Guest. */ 236 /* Now we deal with whatever happened to the Guest. */
237 lguest_arch_handle_trap(lg); 237 lguest_arch_handle_trap(cpu);
238 } 238 }
239 239
240 if (lg->dead == ERR_PTR(-ERESTART)) 240 if (lg->dead == ERR_PTR(-ERESTART))
diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c
index 05fad6fa8049..7827671b2234 100644
--- a/drivers/lguest/hypercalls.c
+++ b/drivers/lguest/hypercalls.c
@@ -29,8 +29,10 @@
29 29
30/*H:120 This is the core hypercall routine: where the Guest gets what it wants. 30/*H:120 This is the core hypercall routine: where the Guest gets what it wants.
31 * Or gets killed. Or, in the case of LHCALL_CRASH, both. */ 31 * Or gets killed. Or, in the case of LHCALL_CRASH, both. */
32static void do_hcall(struct lguest *lg, struct hcall_args *args) 32static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
33{ 33{
34 struct lguest *lg = cpu->lg;
35
34 switch (args->arg0) { 36 switch (args->arg0) {
35 case LHCALL_FLUSH_ASYNC: 37 case LHCALL_FLUSH_ASYNC:
36 /* This call does nothing, except by breaking out of the Guest 38 /* This call does nothing, except by breaking out of the Guest
@@ -93,7 +95,7 @@ static void do_hcall(struct lguest *lg, struct hcall_args *args)
93 break; 95 break;
94 default: 96 default:
95 /* It should be an architecture-specific hypercall. */ 97 /* It should be an architecture-specific hypercall. */
96 if (lguest_arch_do_hcall(lg, args)) 98 if (lguest_arch_do_hcall(cpu, args))
97 kill_guest(lg, "Bad hypercall %li\n", args->arg0); 99 kill_guest(lg, "Bad hypercall %li\n", args->arg0);
98 } 100 }
99} 101}
@@ -106,10 +108,11 @@ static void do_hcall(struct lguest *lg, struct hcall_args *args)
106 * Guest put them in the ring, but we also promise the Guest that they will 108 * Guest put them in the ring, but we also promise the Guest that they will
107 * happen before any normal hypercall (which is why we check this before 109 * happen before any normal hypercall (which is why we check this before
108 * checking for a normal hcall). */ 110 * checking for a normal hcall). */
109static void do_async_hcalls(struct lguest *lg) 111static void do_async_hcalls(struct lg_cpu *cpu)
110{ 112{
111 unsigned int i; 113 unsigned int i;
112 u8 st[LHCALL_RING_SIZE]; 114 u8 st[LHCALL_RING_SIZE];
115 struct lguest *lg = cpu->lg;
113 116
114 /* For simplicity, we copy the entire call status array in at once. */ 117 /* For simplicity, we copy the entire call status array in at once. */
115 if (copy_from_user(&st, &lg->lguest_data->hcall_status, sizeof(st))) 118 if (copy_from_user(&st, &lg->lguest_data->hcall_status, sizeof(st)))
@@ -121,7 +124,7 @@ static void do_async_hcalls(struct lguest *lg)
121 /* We remember where we were up to from last time. This makes 124 /* We remember where we were up to from last time. This makes
122 * sure that the hypercalls are done in the order the Guest 125 * sure that the hypercalls are done in the order the Guest
123 * places them in the ring. */ 126 * places them in the ring. */
124 unsigned int n = lg->next_hcall; 127 unsigned int n = cpu->next_hcall;
125 128
126 /* 0xFF means there's no call here (yet). */ 129 /* 0xFF means there's no call here (yet). */
127 if (st[n] == 0xFF) 130 if (st[n] == 0xFF)
@@ -129,8 +132,8 @@ static void do_async_hcalls(struct lguest *lg)
129 132
130 /* OK, we have hypercall. Increment the "next_hcall" cursor, 133 /* OK, we have hypercall. Increment the "next_hcall" cursor,
131 * and wrap back to 0 if we reach the end. */ 134 * and wrap back to 0 if we reach the end. */
132 if (++lg->next_hcall == LHCALL_RING_SIZE) 135 if (++cpu->next_hcall == LHCALL_RING_SIZE)
133 lg->next_hcall = 0; 136 cpu->next_hcall = 0;
134 137
135 /* Copy the hypercall arguments into a local copy of 138 /* Copy the hypercall arguments into a local copy of
136 * the hcall_args struct. */ 139 * the hcall_args struct. */
@@ -141,7 +144,7 @@ static void do_async_hcalls(struct lguest *lg)
141 } 144 }
142 145
143 /* Do the hypercall, same as a normal one. */ 146 /* Do the hypercall, same as a normal one. */
144 do_hcall(lg, &args); 147 do_hcall(cpu, &args);
145 148
146 /* Mark the hypercall done. */ 149 /* Mark the hypercall done. */
147 if (put_user(0xFF, &lg->lguest_data->hcall_status[n])) { 150 if (put_user(0xFF, &lg->lguest_data->hcall_status[n])) {
@@ -158,16 +161,17 @@ static void do_async_hcalls(struct lguest *lg)
158 161
159/* Last of all, we look at what happens first of all. The very first time the 162/* Last of all, we look at what happens first of all. The very first time the
160 * Guest makes a hypercall, we end up here to set things up: */ 163 * Guest makes a hypercall, we end up here to set things up: */
161static void initialize(struct lguest *lg) 164static void initialize(struct lg_cpu *cpu)
162{ 165{
166 struct lguest *lg = cpu->lg;
163 /* You can't do anything until you're initialized. The Guest knows the 167 /* You can't do anything until you're initialized. The Guest knows the
164 * rules, so we're unforgiving here. */ 168 * rules, so we're unforgiving here. */
165 if (lg->hcall->arg0 != LHCALL_LGUEST_INIT) { 169 if (cpu->hcall->arg0 != LHCALL_LGUEST_INIT) {
166 kill_guest(lg, "hypercall %li before INIT", lg->hcall->arg0); 170 kill_guest(lg, "hypercall %li before INIT", cpu->hcall->arg0);
167 return; 171 return;
168 } 172 }
169 173
170 if (lguest_arch_init_hypercalls(lg)) 174 if (lguest_arch_init_hypercalls(cpu))
171 kill_guest(lg, "bad guest page %p", lg->lguest_data); 175 kill_guest(lg, "bad guest page %p", lg->lguest_data);
172 176
173 /* The Guest tells us where we're not to deliver interrupts by putting 177 /* The Guest tells us where we're not to deliver interrupts by putting
@@ -196,27 +200,27 @@ static void initialize(struct lguest *lg)
196 * Remember from the Guest, hypercalls come in two flavors: normal and 200 * Remember from the Guest, hypercalls come in two flavors: normal and
197 * asynchronous. This file handles both of types. 201 * asynchronous. This file handles both of types.
198 */ 202 */
199void do_hypercalls(struct lguest *lg) 203void do_hypercalls(struct lg_cpu *cpu)
200{ 204{
201 /* Not initialized yet? This hypercall must do it. */ 205 /* Not initialized yet? This hypercall must do it. */
202 if (unlikely(!lg->lguest_data)) { 206 if (unlikely(!cpu->lg->lguest_data)) {
203 /* Set up the "struct lguest_data" */ 207 /* Set up the "struct lguest_data" */
204 initialize(lg); 208 initialize(cpu);
205 /* Hcall is done. */ 209 /* Hcall is done. */
206 lg->hcall = NULL; 210 cpu->hcall = NULL;
207 return; 211 return;
208 } 212 }
209 213
210 /* The Guest has initialized. 214 /* The Guest has initialized.
211 * 215 *
212 * Look in the hypercall ring for the async hypercalls: */ 216 * Look in the hypercall ring for the async hypercalls: */
213 do_async_hcalls(lg); 217 do_async_hcalls(cpu);
214 218
215 /* If we stopped reading the hypercall ring because the Guest did a 219 /* If we stopped reading the hypercall ring because the Guest did a
216 * NOTIFY to the Launcher, we want to return now. Otherwise we do 220 * NOTIFY to the Launcher, we want to return now. Otherwise we do
217 * the hypercall. */ 221 * the hypercall. */
218 if (!lg->pending_notify) { 222 if (!cpu->lg->pending_notify) {
219 do_hcall(lg, lg->hcall); 223 do_hcall(cpu, cpu->hcall);
220 /* Tricky point: we reset the hcall pointer to mark the 224 /* Tricky point: we reset the hcall pointer to mark the
221 * hypercall as "done". We use the hcall pointer rather than 225 * hypercall as "done". We use the hcall pointer rather than
222 * the trap number to indicate a hypercall is pending. 226 * the trap number to indicate a hypercall is pending.
@@ -227,7 +231,7 @@ void do_hypercalls(struct lguest *lg)
227 * Launcher, the run_guest() loop will exit without running the 231 * Launcher, the run_guest() loop will exit without running the
228 * Guest. When it comes back it would try to re-run the 232 * Guest. When it comes back it would try to re-run the
229 * hypercall. */ 233 * hypercall. */
230 lg->hcall = NULL; 234 cpu->hcall = NULL;
231 } 235 }
232} 236}
233 237
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h
index bfca2716ad11..a4ebd415fa27 100644
--- a/drivers/lguest/lg.h
+++ b/drivers/lguest/lg.h
@@ -43,6 +43,10 @@ struct lguest;
43struct lg_cpu { 43struct lg_cpu {
44 unsigned int id; 44 unsigned int id;
45 struct lguest *lg; 45 struct lguest *lg;
46
47 /* If a hypercall was asked for, this points to the arguments. */
48 struct hcall_args *hcall;
49 u32 next_hcall;
46}; 50};
47 51
48/* The private info the thread maintains about the guest. */ 52/* The private info the thread maintains about the guest. */
@@ -65,13 +69,9 @@ struct lguest
65 u32 cr2; 69 u32 cr2;
66 int halted; 70 int halted;
67 int ts; 71 int ts;
68 u32 next_hcall;
69 u32 esp1; 72 u32 esp1;
70 u8 ss1; 73 u8 ss1;
71 74
72 /* If a hypercall was asked for, this points to the arguments. */
73 struct hcall_args *hcall;
74
75 /* Do we need to stop what we're doing and return to userspace? */ 75 /* Do we need to stop what we're doing and return to userspace? */
76 int break_out; 76 int break_out;
77 wait_queue_head_t break_wq; 77 wait_queue_head_t break_wq;
@@ -178,9 +178,9 @@ void page_table_guest_data_init(struct lguest *lg);
178void lguest_arch_host_init(void); 178void lguest_arch_host_init(void);
179void lguest_arch_host_fini(void); 179void lguest_arch_host_fini(void);
180void lguest_arch_run_guest(struct lg_cpu *cpu); 180void lguest_arch_run_guest(struct lg_cpu *cpu);
181void lguest_arch_handle_trap(struct lguest *lg); 181void lguest_arch_handle_trap(struct lg_cpu *cpu);
182int lguest_arch_init_hypercalls(struct lguest *lg); 182int lguest_arch_init_hypercalls(struct lg_cpu *cpu);
183int lguest_arch_do_hcall(struct lguest *lg, struct hcall_args *args); 183int lguest_arch_do_hcall(struct lg_cpu *cpu, struct hcall_args *args);
184void lguest_arch_setup_regs(struct lguest *lg, unsigned long start); 184void lguest_arch_setup_regs(struct lguest *lg, unsigned long start);
185 185
186/* <arch>/switcher.S: */ 186/* <arch>/switcher.S: */
@@ -191,7 +191,7 @@ int lguest_device_init(void);
191void lguest_device_remove(void); 191void lguest_device_remove(void);
192 192
193/* hypercalls.c: */ 193/* hypercalls.c: */
194void do_hypercalls(struct lguest *lg); 194void do_hypercalls(struct lg_cpu *cpu);
195void write_timestamp(struct lguest *lg); 195void write_timestamp(struct lguest *lg);
196 196
197/*L:035 197/*L:035
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c
index 3d2131e169fd..5962160aff3d 100644
--- a/drivers/lguest/x86/core.c
+++ b/drivers/lguest/x86/core.c
@@ -283,8 +283,9 @@ static int emulate_insn(struct lguest *lg)
283} 283}
284 284
285/*H:050 Once we've re-enabled interrupts, we look at why the Guest exited. */ 285/*H:050 Once we've re-enabled interrupts, we look at why the Guest exited. */
286void lguest_arch_handle_trap(struct lguest *lg) 286void lguest_arch_handle_trap(struct lg_cpu *cpu)
287{ 287{
288 struct lguest *lg = cpu->lg;
288 switch (lg->regs->trapnum) { 289 switch (lg->regs->trapnum) {
289 case 13: /* We've intercepted a General Protection Fault. */ 290 case 13: /* We've intercepted a General Protection Fault. */
290 /* Check if this was one of those annoying IN or OUT 291 /* Check if this was one of those annoying IN or OUT
@@ -336,7 +337,7 @@ void lguest_arch_handle_trap(struct lguest *lg)
336 case LGUEST_TRAP_ENTRY: 337 case LGUEST_TRAP_ENTRY:
337 /* Our 'struct hcall_args' maps directly over our regs: we set 338 /* Our 'struct hcall_args' maps directly over our regs: we set
338 * up the pointer now to indicate a hypercall is pending. */ 339 * up the pointer now to indicate a hypercall is pending. */
339 lg->hcall = (struct hcall_args *)lg->regs; 340 cpu->hcall = (struct hcall_args *)lg->regs;
340 return; 341 return;
341 } 342 }
342 343
@@ -491,8 +492,10 @@ void __exit lguest_arch_host_fini(void)
491 492
492 493
493/*H:122 The i386-specific hypercalls simply farm out to the right functions. */ 494/*H:122 The i386-specific hypercalls simply farm out to the right functions. */
494int lguest_arch_do_hcall(struct lguest *lg, struct hcall_args *args) 495int lguest_arch_do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
495{ 496{
497 struct lguest *lg = cpu->lg;
498
496 switch (args->arg0) { 499 switch (args->arg0) {
497 case LHCALL_LOAD_GDT: 500 case LHCALL_LOAD_GDT:
498 load_guest_gdt(lg, args->arg1, args->arg2); 501 load_guest_gdt(lg, args->arg1, args->arg2);
@@ -511,13 +514,14 @@ int lguest_arch_do_hcall(struct lguest *lg, struct hcall_args *args)
511} 514}
512 515
513/*H:126 i386-specific hypercall initialization: */ 516/*H:126 i386-specific hypercall initialization: */
514int lguest_arch_init_hypercalls(struct lguest *lg) 517int lguest_arch_init_hypercalls(struct lg_cpu *cpu)
515{ 518{
516 u32 tsc_speed; 519 u32 tsc_speed;
520 struct lguest *lg = cpu->lg;
517 521
518 /* The pointer to the Guest's "struct lguest_data" is the only 522 /* The pointer to the Guest's "struct lguest_data" is the only
519 * argument. We check that address now. */ 523 * argument. We check that address now. */
520 if (!lguest_address_ok(lg, lg->hcall->arg1, sizeof(*lg->lguest_data))) 524 if (!lguest_address_ok(lg, cpu->hcall->arg1, sizeof(*lg->lguest_data)))
521 return -EFAULT; 525 return -EFAULT;
522 526
523 /* Having checked it, we simply set lg->lguest_data to point straight 527 /* Having checked it, we simply set lg->lguest_data to point straight
@@ -525,7 +529,7 @@ int lguest_arch_init_hypercalls(struct lguest *lg)
525 * copy_to_user/from_user from now on, instead of lgread/write. I put 529 * copy_to_user/from_user from now on, instead of lgread/write. I put
526 * this in to show that I'm not immune to writing stupid 530 * this in to show that I'm not immune to writing stupid
527 * optimizations. */ 531 * optimizations. */
528 lg->lguest_data = lg->mem_base + lg->hcall->arg1; 532 lg->lguest_data = lg->mem_base + cpu->hcall->arg1;
529 533
530 /* We insist that the Time Stamp Counter exist and doesn't change with 534 /* We insist that the Time Stamp Counter exist and doesn't change with
531 * cpu frequency. Some devious chip manufacturers decided that TSC 535 * cpu frequency. Some devious chip manufacturers decided that TSC