diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2015-02-10 23:45:09 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2015-02-11 01:17:30 -0500 |
commit | 69a09dc1742ffbb3b02f3a1e03da4801e96452e9 (patch) | |
tree | c9887c6b6150810ba103b76cf9d4376af3edd5e5 /drivers/lguest | |
parent | 18c137371b2ea86d263b75665a4904a0b8872990 (diff) |
lguest: write more information to userspace about pending traps.
This is preparation for userspace handling MMIO and ioport accesses.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/lguest')
-rw-r--r-- | drivers/lguest/core.c | 7 | ||||
-rw-r--r-- | drivers/lguest/hypercalls.c | 7 | ||||
-rw-r--r-- | drivers/lguest/lg.h | 3 | ||||
-rw-r--r-- | drivers/lguest/lguest_user.c | 14 |
4 files changed, 19 insertions, 12 deletions
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c index cdb2f9aa5860..9159dbc583f6 100644 --- a/drivers/lguest/core.c +++ b/drivers/lguest/core.c | |||
@@ -229,16 +229,17 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user) | |||
229 | * It's possible the Guest did a NOTIFY hypercall to the | 229 | * It's possible the Guest did a NOTIFY hypercall to the |
230 | * Launcher. | 230 | * Launcher. |
231 | */ | 231 | */ |
232 | if (cpu->pending_notify) { | 232 | if (cpu->pending.trap) { |
233 | /* | 233 | /* |
234 | * Does it just needs to write to a registered | 234 | * Does it just needs to write to a registered |
235 | * eventfd (ie. the appropriate virtqueue thread)? | 235 | * eventfd (ie. the appropriate virtqueue thread)? |
236 | */ | 236 | */ |
237 | if (!send_notify_to_eventfd(cpu)) { | 237 | if (!send_notify_to_eventfd(cpu)) { |
238 | /* OK, we tell the main Launcher. */ | 238 | /* OK, we tell the main Launcher. */ |
239 | if (put_user(cpu->pending_notify, user)) | 239 | if (copy_to_user(user, &cpu->pending, |
240 | sizeof(cpu->pending))) | ||
240 | return -EFAULT; | 241 | return -EFAULT; |
241 | return sizeof(cpu->pending_notify); | 242 | return sizeof(cpu->pending); |
242 | } | 243 | } |
243 | } | 244 | } |
244 | 245 | ||
diff --git a/drivers/lguest/hypercalls.c b/drivers/lguest/hypercalls.c index 83511eb0923d..5dd1fb8a6610 100644 --- a/drivers/lguest/hypercalls.c +++ b/drivers/lguest/hypercalls.c | |||
@@ -118,7 +118,8 @@ static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args) | |||
118 | cpu->halted = 1; | 118 | cpu->halted = 1; |
119 | break; | 119 | break; |
120 | case LHCALL_NOTIFY: | 120 | case LHCALL_NOTIFY: |
121 | cpu->pending_notify = args->arg1; | 121 | cpu->pending.trap = LGUEST_TRAP_ENTRY; |
122 | cpu->pending.addr = args->arg1; | ||
122 | break; | 123 | break; |
123 | default: | 124 | default: |
124 | /* It should be an architecture-specific hypercall. */ | 125 | /* It should be an architecture-specific hypercall. */ |
@@ -189,7 +190,7 @@ static void do_async_hcalls(struct lg_cpu *cpu) | |||
189 | * Stop doing hypercalls if they want to notify the Launcher: | 190 | * Stop doing hypercalls if they want to notify the Launcher: |
190 | * it needs to service this first. | 191 | * it needs to service this first. |
191 | */ | 192 | */ |
192 | if (cpu->pending_notify) | 193 | if (cpu->pending.trap) |
193 | break; | 194 | break; |
194 | } | 195 | } |
195 | } | 196 | } |
@@ -280,7 +281,7 @@ void do_hypercalls(struct lg_cpu *cpu) | |||
280 | * NOTIFY to the Launcher, we want to return now. Otherwise we do | 281 | * NOTIFY to the Launcher, we want to return now. Otherwise we do |
281 | * the hypercall. | 282 | * the hypercall. |
282 | */ | 283 | */ |
283 | if (!cpu->pending_notify) { | 284 | if (!cpu->pending.trap) { |
284 | do_hcall(cpu, cpu->hcall); | 285 | do_hcall(cpu, cpu->hcall); |
285 | /* | 286 | /* |
286 | * Tricky point: we reset the hcall pointer to mark the | 287 | * Tricky point: we reset the hcall pointer to mark the |
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h index 1c98bf74fd68..020fec5bb072 100644 --- a/drivers/lguest/lg.h +++ b/drivers/lguest/lg.h | |||
@@ -50,7 +50,8 @@ struct lg_cpu { | |||
50 | /* Bitmap of what has changed: see CHANGED_* above. */ | 50 | /* Bitmap of what has changed: see CHANGED_* above. */ |
51 | int changed; | 51 | int changed; |
52 | 52 | ||
53 | unsigned long pending_notify; /* pfn from LHCALL_NOTIFY */ | 53 | /* Pending operation. */ |
54 | struct lguest_pending pending; | ||
54 | 55 | ||
55 | unsigned long *reg_read; /* register from LHREQ_GETREG */ | 56 | unsigned long *reg_read; /* register from LHREQ_GETREG */ |
56 | 57 | ||
diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c index 7f14c152dd23..dcf9efd94cf4 100644 --- a/drivers/lguest/lguest_user.c +++ b/drivers/lguest/lguest_user.c | |||
@@ -29,6 +29,10 @@ bool send_notify_to_eventfd(struct lg_cpu *cpu) | |||
29 | unsigned int i; | 29 | unsigned int i; |
30 | struct lg_eventfd_map *map; | 30 | struct lg_eventfd_map *map; |
31 | 31 | ||
32 | /* We only connect LHCALL_NOTIFY to event fds, not other traps. */ | ||
33 | if (cpu->pending.trap != LGUEST_TRAP_ENTRY) | ||
34 | return false; | ||
35 | |||
32 | /* | 36 | /* |
33 | * This "rcu_read_lock()" helps track when someone is still looking at | 37 | * This "rcu_read_lock()" helps track when someone is still looking at |
34 | * the (RCU-using) eventfds array. It's not actually a lock at all; | 38 | * the (RCU-using) eventfds array. It's not actually a lock at all; |
@@ -52,9 +56,9 @@ bool send_notify_to_eventfd(struct lg_cpu *cpu) | |||
52 | * we'll continue to use the old array and just won't see the new one. | 56 | * we'll continue to use the old array and just won't see the new one. |
53 | */ | 57 | */ |
54 | for (i = 0; i < map->num; i++) { | 58 | for (i = 0; i < map->num; i++) { |
55 | if (map->map[i].addr == cpu->pending_notify) { | 59 | if (map->map[i].addr == cpu->pending.addr) { |
56 | eventfd_signal(map->map[i].event, 1); | 60 | eventfd_signal(map->map[i].event, 1); |
57 | cpu->pending_notify = 0; | 61 | cpu->pending.trap = 0; |
58 | break; | 62 | break; |
59 | } | 63 | } |
60 | } | 64 | } |
@@ -62,7 +66,7 @@ bool send_notify_to_eventfd(struct lg_cpu *cpu) | |||
62 | rcu_read_unlock(); | 66 | rcu_read_unlock(); |
63 | 67 | ||
64 | /* If we cleared the notification, it's because we found a match. */ | 68 | /* If we cleared the notification, it's because we found a match. */ |
65 | return cpu->pending_notify == 0; | 69 | return cpu->pending.trap == 0; |
66 | } | 70 | } |
67 | 71 | ||
68 | /*L:055 | 72 | /*L:055 |
@@ -282,8 +286,8 @@ static ssize_t read(struct file *file, char __user *user, size_t size,loff_t*o) | |||
282 | * If we returned from read() last time because the Guest sent I/O, | 286 | * If we returned from read() last time because the Guest sent I/O, |
283 | * clear the flag. | 287 | * clear the flag. |
284 | */ | 288 | */ |
285 | if (cpu->pending_notify) | 289 | if (cpu->pending.trap) |
286 | cpu->pending_notify = 0; | 290 | cpu->pending.trap = 0; |
287 | 291 | ||
288 | /* Run the Guest until something interesting happens. */ | 292 | /* Run the Guest until something interesting happens. */ |
289 | return run_guest(cpu, (unsigned long __user *)user); | 293 | return run_guest(cpu, (unsigned long __user *)user); |