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/hypercalls.c | |
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/hypercalls.c')
-rw-r--r-- | drivers/lguest/hypercalls.c | 42 |
1 files changed, 23 insertions, 19 deletions
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 | ||