diff options
author | Glauber de Oliveira Costa <gcosta@redhat.com> | 2008-01-07 08:05:27 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-01-30 06:50:08 -0500 |
commit | 73044f05a4ac65f2df42753e9566444b9d2a660f (patch) | |
tree | 80a3e1d1bda31a769554a8c51f8c189ccec0b9f8 /drivers/lguest | |
parent | 7ea07a1500f05e06ebf0136763c781244f77a2a1 (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>
Diffstat (limited to 'drivers/lguest')
-rw-r--r-- | drivers/lguest/core.c | 6 | ||||
-rw-r--r-- | drivers/lguest/hypercalls.c | 42 | ||||
-rw-r--r-- | drivers/lguest/lg.h | 16 | ||||
-rw-r--r-- | drivers/lguest/x86/core.c | 16 |
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. */ |
32 | static void do_hcall(struct lguest *lg, struct hcall_args *args) | 32 | static 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). */ |
109 | static void do_async_hcalls(struct lguest *lg) | 111 | static 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: */ |
161 | static void initialize(struct lguest *lg) | 164 | static 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 | */ |
199 | void do_hypercalls(struct lguest *lg) | 203 | void 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; | |||
43 | struct lg_cpu { | 43 | struct 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); | |||
178 | void lguest_arch_host_init(void); | 178 | void lguest_arch_host_init(void); |
179 | void lguest_arch_host_fini(void); | 179 | void lguest_arch_host_fini(void); |
180 | void lguest_arch_run_guest(struct lg_cpu *cpu); | 180 | void lguest_arch_run_guest(struct lg_cpu *cpu); |
181 | void lguest_arch_handle_trap(struct lguest *lg); | 181 | void lguest_arch_handle_trap(struct lg_cpu *cpu); |
182 | int lguest_arch_init_hypercalls(struct lguest *lg); | 182 | int lguest_arch_init_hypercalls(struct lg_cpu *cpu); |
183 | int lguest_arch_do_hcall(struct lguest *lg, struct hcall_args *args); | 183 | int lguest_arch_do_hcall(struct lg_cpu *cpu, struct hcall_args *args); |
184 | void lguest_arch_setup_regs(struct lguest *lg, unsigned long start); | 184 | void 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); | |||
191 | void lguest_device_remove(void); | 191 | void lguest_device_remove(void); |
192 | 192 | ||
193 | /* hypercalls.c: */ | 193 | /* hypercalls.c: */ |
194 | void do_hypercalls(struct lguest *lg); | 194 | void do_hypercalls(struct lg_cpu *cpu); |
195 | void write_timestamp(struct lguest *lg); | 195 | void 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. */ |
286 | void lguest_arch_handle_trap(struct lguest *lg) | 286 | void 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. */ |
494 | int lguest_arch_do_hcall(struct lguest *lg, struct hcall_args *args) | 495 | int 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: */ |
514 | int lguest_arch_init_hypercalls(struct lguest *lg) | 517 | int 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 |