Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/lguest/hypercalls.c
15109 views
1
/*P:500
2
* Just as userspace programs request kernel operations through a system
3
* call, the Guest requests Host operations through a "hypercall". You might
4
* notice this nomenclature doesn't really follow any logic, but the name has
5
* been around for long enough that we're stuck with it. As you'd expect, this
6
* code is basically a one big switch statement.
7
:*/
8
9
/* Copyright (C) 2006 Rusty Russell IBM Corporation
10
11
This program is free software; you can redistribute it and/or modify
12
it under the terms of the GNU General Public License as published by
13
the Free Software Foundation; either version 2 of the License, or
14
(at your option) any later version.
15
16
This program is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
GNU General Public License for more details.
20
21
You should have received a copy of the GNU General Public License
22
along with this program; if not, write to the Free Software
23
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
*/
25
#include <linux/uaccess.h>
26
#include <linux/syscalls.h>
27
#include <linux/mm.h>
28
#include <linux/ktime.h>
29
#include <asm/page.h>
30
#include <asm/pgtable.h>
31
#include "lg.h"
32
33
/*H:120
34
* This is the core hypercall routine: where the Guest gets what it wants.
35
* Or gets killed. Or, in the case of LHCALL_SHUTDOWN, both.
36
*/
37
static void do_hcall(struct lg_cpu *cpu, struct hcall_args *args)
38
{
39
switch (args->arg0) {
40
case LHCALL_FLUSH_ASYNC:
41
/*
42
* This call does nothing, except by breaking out of the Guest
43
* it makes us process all the asynchronous hypercalls.
44
*/
45
break;
46
case LHCALL_SEND_INTERRUPTS:
47
/*
48
* This call does nothing too, but by breaking out of the Guest
49
* it makes us process any pending interrupts.
50
*/
51
break;
52
case LHCALL_LGUEST_INIT:
53
/*
54
* You can't get here unless you're already initialized. Don't
55
* do that.
56
*/
57
kill_guest(cpu, "already have lguest_data");
58
break;
59
case LHCALL_SHUTDOWN: {
60
char msg[128];
61
/*
62
* Shutdown is such a trivial hypercall that we do it in five
63
* lines right here.
64
*
65
* If the lgread fails, it will call kill_guest() itself; the
66
* kill_guest() with the message will be ignored.
67
*/
68
__lgread(cpu, msg, args->arg1, sizeof(msg));
69
msg[sizeof(msg)-1] = '\0';
70
kill_guest(cpu, "CRASH: %s", msg);
71
if (args->arg2 == LGUEST_SHUTDOWN_RESTART)
72
cpu->lg->dead = ERR_PTR(-ERESTART);
73
break;
74
}
75
case LHCALL_FLUSH_TLB:
76
/* FLUSH_TLB comes in two flavors, depending on the argument: */
77
if (args->arg1)
78
guest_pagetable_clear_all(cpu);
79
else
80
guest_pagetable_flush_user(cpu);
81
break;
82
83
/*
84
* All these calls simply pass the arguments through to the right
85
* routines.
86
*/
87
case LHCALL_NEW_PGTABLE:
88
guest_new_pagetable(cpu, args->arg1);
89
break;
90
case LHCALL_SET_STACK:
91
guest_set_stack(cpu, args->arg1, args->arg2, args->arg3);
92
break;
93
case LHCALL_SET_PTE:
94
#ifdef CONFIG_X86_PAE
95
guest_set_pte(cpu, args->arg1, args->arg2,
96
__pte(args->arg3 | (u64)args->arg4 << 32));
97
#else
98
guest_set_pte(cpu, args->arg1, args->arg2, __pte(args->arg3));
99
#endif
100
break;
101
case LHCALL_SET_PGD:
102
guest_set_pgd(cpu->lg, args->arg1, args->arg2);
103
break;
104
#ifdef CONFIG_X86_PAE
105
case LHCALL_SET_PMD:
106
guest_set_pmd(cpu->lg, args->arg1, args->arg2);
107
break;
108
#endif
109
case LHCALL_SET_CLOCKEVENT:
110
guest_set_clockevent(cpu, args->arg1);
111
break;
112
case LHCALL_TS:
113
/* This sets the TS flag, as we saw used in run_guest(). */
114
cpu->ts = args->arg1;
115
break;
116
case LHCALL_HALT:
117
/* Similarly, this sets the halted flag for run_guest(). */
118
cpu->halted = 1;
119
break;
120
case LHCALL_NOTIFY:
121
cpu->pending_notify = args->arg1;
122
break;
123
default:
124
/* It should be an architecture-specific hypercall. */
125
if (lguest_arch_do_hcall(cpu, args))
126
kill_guest(cpu, "Bad hypercall %li\n", args->arg0);
127
}
128
}
129
130
/*H:124
131
* Asynchronous hypercalls are easy: we just look in the array in the
132
* Guest's "struct lguest_data" to see if any new ones are marked "ready".
133
*
134
* We are careful to do these in order: obviously we respect the order the
135
* Guest put them in the ring, but we also promise the Guest that they will
136
* happen before any normal hypercall (which is why we check this before
137
* checking for a normal hcall).
138
*/
139
static void do_async_hcalls(struct lg_cpu *cpu)
140
{
141
unsigned int i;
142
u8 st[LHCALL_RING_SIZE];
143
144
/* For simplicity, we copy the entire call status array in at once. */
145
if (copy_from_user(&st, &cpu->lg->lguest_data->hcall_status, sizeof(st)))
146
return;
147
148
/* We process "struct lguest_data"s hcalls[] ring once. */
149
for (i = 0; i < ARRAY_SIZE(st); i++) {
150
struct hcall_args args;
151
/*
152
* We remember where we were up to from last time. This makes
153
* sure that the hypercalls are done in the order the Guest
154
* places them in the ring.
155
*/
156
unsigned int n = cpu->next_hcall;
157
158
/* 0xFF means there's no call here (yet). */
159
if (st[n] == 0xFF)
160
break;
161
162
/*
163
* OK, we have hypercall. Increment the "next_hcall" cursor,
164
* and wrap back to 0 if we reach the end.
165
*/
166
if (++cpu->next_hcall == LHCALL_RING_SIZE)
167
cpu->next_hcall = 0;
168
169
/*
170
* Copy the hypercall arguments into a local copy of the
171
* hcall_args struct.
172
*/
173
if (copy_from_user(&args, &cpu->lg->lguest_data->hcalls[n],
174
sizeof(struct hcall_args))) {
175
kill_guest(cpu, "Fetching async hypercalls");
176
break;
177
}
178
179
/* Do the hypercall, same as a normal one. */
180
do_hcall(cpu, &args);
181
182
/* Mark the hypercall done. */
183
if (put_user(0xFF, &cpu->lg->lguest_data->hcall_status[n])) {
184
kill_guest(cpu, "Writing result for async hypercall");
185
break;
186
}
187
188
/*
189
* Stop doing hypercalls if they want to notify the Launcher:
190
* it needs to service this first.
191
*/
192
if (cpu->pending_notify)
193
break;
194
}
195
}
196
197
/*
198
* Last of all, we look at what happens first of all. The very first time the
199
* Guest makes a hypercall, we end up here to set things up:
200
*/
201
static void initialize(struct lg_cpu *cpu)
202
{
203
/*
204
* You can't do anything until you're initialized. The Guest knows the
205
* rules, so we're unforgiving here.
206
*/
207
if (cpu->hcall->arg0 != LHCALL_LGUEST_INIT) {
208
kill_guest(cpu, "hypercall %li before INIT", cpu->hcall->arg0);
209
return;
210
}
211
212
if (lguest_arch_init_hypercalls(cpu))
213
kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
214
215
/*
216
* The Guest tells us where we're not to deliver interrupts by putting
217
* the range of addresses into "struct lguest_data".
218
*/
219
if (get_user(cpu->lg->noirq_start, &cpu->lg->lguest_data->noirq_start)
220
|| get_user(cpu->lg->noirq_end, &cpu->lg->lguest_data->noirq_end))
221
kill_guest(cpu, "bad guest page %p", cpu->lg->lguest_data);
222
223
/*
224
* We write the current time into the Guest's data page once so it can
225
* set its clock.
226
*/
227
write_timestamp(cpu);
228
229
/* page_tables.c will also do some setup. */
230
page_table_guest_data_init(cpu);
231
232
/*
233
* This is the one case where the above accesses might have been the
234
* first write to a Guest page. This may have caused a copy-on-write
235
* fault, but the old page might be (read-only) in the Guest
236
* pagetable.
237
*/
238
guest_pagetable_clear_all(cpu);
239
}
240
/*:*/
241
242
/*M:013
243
* If a Guest reads from a page (so creates a mapping) that it has never
244
* written to, and then the Launcher writes to it (ie. the output of a virtual
245
* device), the Guest will still see the old page. In practice, this never
246
* happens: why would the Guest read a page which it has never written to? But
247
* a similar scenario might one day bite us, so it's worth mentioning.
248
*
249
* Note that if we used a shared anonymous mapping in the Launcher instead of
250
* mapping /dev/zero private, we wouldn't worry about cop-on-write. And we
251
* need that to switch the Launcher to processes (away from threads) anyway.
252
:*/
253
254
/*H:100
255
* Hypercalls
256
*
257
* Remember from the Guest, hypercalls come in two flavors: normal and
258
* asynchronous. This file handles both of types.
259
*/
260
void do_hypercalls(struct lg_cpu *cpu)
261
{
262
/* Not initialized yet? This hypercall must do it. */
263
if (unlikely(!cpu->lg->lguest_data)) {
264
/* Set up the "struct lguest_data" */
265
initialize(cpu);
266
/* Hcall is done. */
267
cpu->hcall = NULL;
268
return;
269
}
270
271
/*
272
* The Guest has initialized.
273
*
274
* Look in the hypercall ring for the async hypercalls:
275
*/
276
do_async_hcalls(cpu);
277
278
/*
279
* If we stopped reading the hypercall ring because the Guest did a
280
* NOTIFY to the Launcher, we want to return now. Otherwise we do
281
* the hypercall.
282
*/
283
if (!cpu->pending_notify) {
284
do_hcall(cpu, cpu->hcall);
285
/*
286
* Tricky point: we reset the hcall pointer to mark the
287
* hypercall as "done". We use the hcall pointer rather than
288
* the trap number to indicate a hypercall is pending.
289
* Normally it doesn't matter: the Guest will run again and
290
* update the trap number before we come back here.
291
*
292
* However, if we are signalled or the Guest sends I/O to the
293
* Launcher, the run_guest() loop will exit without running the
294
* Guest. When it comes back it would try to re-run the
295
* hypercall. Finding that bug sucked.
296
*/
297
cpu->hcall = NULL;
298
}
299
}
300
301
/*
302
* This routine supplies the Guest with time: it's used for wallclock time at
303
* initial boot and as a rough time source if the TSC isn't available.
304
*/
305
void write_timestamp(struct lg_cpu *cpu)
306
{
307
struct timespec now;
308
ktime_get_real_ts(&now);
309
if (copy_to_user(&cpu->lg->lguest_data->time,
310
&now, sizeof(struct timespec)))
311
kill_guest(cpu, "Writing timestamp");
312
}
313
314