Commit 091ebf07a2408f9a56634caa0f86d9360e9af23b

Authored by Rusty Russell
1 parent 5094aeafbb

lguest: stop using KVM hypercall mechanism

This is a partial revert of 4cd8b5e2a159 "lguest: use KVM hypercalls";
we revert to using (just as questionable but more reliable) int $15 for
hypercalls.  I didn't revert the register mapping, so we still use the
same calling convention as kvm.

KVM in more recent incarnations stopped injecting a fault when a guest
tried to use the VMCALL instruction from ring 1, so lguest under kvm
fails to make hypercalls.  It was nice to share code with our KVM
cousins, but this was overreach.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Cc: Matias Zabaljauregui <zabaljauregui@gmail.com>
Cc: Avi Kivity <avi@redhat.com>

Showing 4 changed files with 56 additions and 40 deletions Side-by-side Diff

arch/x86/include/asm/lguest_hcall.h
... ... @@ -28,22 +28,39 @@
28 28  
29 29 #ifndef __ASSEMBLY__
30 30 #include <asm/hw_irq.h>
31   -#include <asm/kvm_para.h>
32 31  
33 32 /*G:030
34 33 * But first, how does our Guest contact the Host to ask for privileged
35 34 * operations? There are two ways: the direct way is to make a "hypercall",
36 35 * to make requests of the Host Itself.
37 36 *
38   - * We use the KVM hypercall mechanism, though completely different hypercall
39   - * numbers. Seventeen hypercalls are available: the hypercall number is put in
40   - * the %eax register, and the arguments (when required) are placed in %ebx,
41   - * %ecx, %edx and %esi. If a return value makes sense, it's returned in %eax.
  37 + * Our hypercall mechanism uses the highest unused trap code (traps 32 and
  38 + * above are used by real hardware interrupts). Seventeen hypercalls are
  39 + * available: the hypercall number is put in the %eax register, and the
  40 + * arguments (when required) are placed in %ebx, %ecx, %edx and %esi.
  41 + * If a return value makes sense, it's returned in %eax.
42 42 *
43 43 * Grossly invalid calls result in Sudden Death at the hands of the vengeful
44 44 * Host, rather than returning failure. This reflects Winston Churchill's
45 45 * definition of a gentleman: "someone who is only rude intentionally".
46   -:*/
  46 + */
  47 +static inline unsigned long
  48 +hcall(unsigned long call,
  49 + unsigned long arg1, unsigned long arg2, unsigned long arg3,
  50 + unsigned long arg4)
  51 +{
  52 + /* "int" is the Intel instruction to trigger a trap. */
  53 + asm volatile("int $" __stringify(LGUEST_TRAP_ENTRY)
  54 + /* The call in %eax (aka "a") might be overwritten */
  55 + : "=a"(call)
  56 + /* The arguments are in %eax, %ebx, %ecx, %edx & %esi */
  57 + : "a"(call), "b"(arg1), "c"(arg2), "d"(arg3), "S"(arg4)
  58 + /* "memory" means this might write somewhere in memory.
  59 + * This isn't true for all calls, but it's safe to tell
  60 + * gcc that it might happen so it doesn't get clever. */
  61 + : "memory");
  62 + return call;
  63 +}
47 64  
48 65 /* Can't use our min() macro here: needs to be a constant */
49 66 #define LGUEST_IRQS (NR_IRQS < 32 ? NR_IRQS: 32)
arch/x86/lguest/boot.c
... ... @@ -115,7 +115,7 @@
115 115 local_irq_save(flags);
116 116 if (lguest_data.hcall_status[next_call] != 0xFF) {
117 117 /* Table full, so do normal hcall which will flush table. */
118   - kvm_hypercall4(call, arg1, arg2, arg3, arg4);
  118 + hcall(call, arg1, arg2, arg3, arg4);
119 119 } else {
120 120 lguest_data.hcalls[next_call].arg0 = call;
121 121 lguest_data.hcalls[next_call].arg1 = arg1;
122 122  
123 123  
124 124  
125 125  
126 126  
127 127  
128 128  
... ... @@ -145,46 +145,45 @@
145 145 * So, when we're in lazy mode, we call async_hcall() to store the call for
146 146 * future processing:
147 147 */
148   -static void lazy_hcall1(unsigned long call,
149   - unsigned long arg1)
  148 +static void lazy_hcall1(unsigned long call, unsigned long arg1)
150 149 {
151 150 if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE)
152   - kvm_hypercall1(call, arg1);
  151 + hcall(call, arg1, 0, 0, 0);
153 152 else
154 153 async_hcall(call, arg1, 0, 0, 0);
155 154 }
156 155  
157 156 /* You can imagine what lazy_hcall2, 3 and 4 look like. :*/
158 157 static void lazy_hcall2(unsigned long call,
159   - unsigned long arg1,
160   - unsigned long arg2)
  158 + unsigned long arg1,
  159 + unsigned long arg2)
161 160 {
162 161 if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE)
163   - kvm_hypercall2(call, arg1, arg2);
  162 + hcall(call, arg1, arg2, 0, 0);
164 163 else
165 164 async_hcall(call, arg1, arg2, 0, 0);
166 165 }
167 166  
168 167 static void lazy_hcall3(unsigned long call,
169   - unsigned long arg1,
170   - unsigned long arg2,
171   - unsigned long arg3)
  168 + unsigned long arg1,
  169 + unsigned long arg2,
  170 + unsigned long arg3)
172 171 {
173 172 if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE)
174   - kvm_hypercall3(call, arg1, arg2, arg3);
  173 + hcall(call, arg1, arg2, arg3, 0);
175 174 else
176 175 async_hcall(call, arg1, arg2, arg3, 0);
177 176 }
178 177  
179 178 #ifdef CONFIG_X86_PAE
180 179 static void lazy_hcall4(unsigned long call,
181   - unsigned long arg1,
182   - unsigned long arg2,
183   - unsigned long arg3,
184   - unsigned long arg4)
  180 + unsigned long arg1,
  181 + unsigned long arg2,
  182 + unsigned long arg3,
  183 + unsigned long arg4)
185 184 {
186 185 if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE)
187   - kvm_hypercall4(call, arg1, arg2, arg3, arg4);
  186 + hcall(call, arg1, arg2, arg3, arg4);
188 187 else
189 188 async_hcall(call, arg1, arg2, arg3, arg4);
190 189 }
191 190  
... ... @@ -196,13 +195,13 @@
196 195 :*/
197 196 static void lguest_leave_lazy_mmu_mode(void)
198 197 {
199   - kvm_hypercall0(LHCALL_FLUSH_ASYNC);
  198 + hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0, 0);
200 199 paravirt_leave_lazy_mmu();
201 200 }
202 201  
203 202 static void lguest_end_context_switch(struct task_struct *next)
204 203 {
205   - kvm_hypercall0(LHCALL_FLUSH_ASYNC);
  204 + hcall(LHCALL_FLUSH_ASYNC, 0, 0, 0, 0);
206 205 paravirt_end_context_switch(next);
207 206 }
208 207  
... ... @@ -286,7 +285,7 @@
286 285 /* Keep the local copy up to date. */
287 286 native_write_idt_entry(dt, entrynum, g);
288 287 /* Tell Host about this new entry. */
289   - kvm_hypercall3(LHCALL_LOAD_IDT_ENTRY, entrynum, desc[0], desc[1]);
  288 + hcall(LHCALL_LOAD_IDT_ENTRY, entrynum, desc[0], desc[1], 0);
290 289 }
291 290  
292 291 /*
... ... @@ -300,7 +299,7 @@
300 299 struct desc_struct *idt = (void *)desc->address;
301 300  
302 301 for (i = 0; i < (desc->size+1)/8; i++)
303   - kvm_hypercall3(LHCALL_LOAD_IDT_ENTRY, i, idt[i].a, idt[i].b);
  302 + hcall(LHCALL_LOAD_IDT_ENTRY, i, idt[i].a, idt[i].b, 0);
304 303 }
305 304  
306 305 /*
... ... @@ -321,7 +320,7 @@
321 320 struct desc_struct *gdt = (void *)desc->address;
322 321  
323 322 for (i = 0; i < (desc->size+1)/8; i++)
324   - kvm_hypercall3(LHCALL_LOAD_GDT_ENTRY, i, gdt[i].a, gdt[i].b);
  323 + hcall(LHCALL_LOAD_GDT_ENTRY, i, gdt[i].a, gdt[i].b, 0);
325 324 }
326 325  
327 326 /*
... ... @@ -334,8 +333,8 @@
334 333 {
335 334 native_write_gdt_entry(dt, entrynum, desc, type);
336 335 /* Tell Host about this new entry. */
337   - kvm_hypercall3(LHCALL_LOAD_GDT_ENTRY, entrynum,
338   - dt[entrynum].a, dt[entrynum].b);
  336 + hcall(LHCALL_LOAD_GDT_ENTRY, entrynum,
  337 + dt[entrynum].a, dt[entrynum].b, 0);
339 338 }
340 339  
341 340 /*
... ... @@ -931,7 +930,7 @@
931 930 }
932 931  
933 932 /* Please wake us this far in the future. */
934   - kvm_hypercall1(LHCALL_SET_CLOCKEVENT, delta);
  933 + hcall(LHCALL_SET_CLOCKEVENT, delta, 0, 0, 0);
935 934 return 0;
936 935 }
937 936  
... ... @@ -942,7 +941,7 @@
942 941 case CLOCK_EVT_MODE_UNUSED:
943 942 case CLOCK_EVT_MODE_SHUTDOWN:
944 943 /* A 0 argument shuts the clock down. */
945   - kvm_hypercall0(LHCALL_SET_CLOCKEVENT);
  944 + hcall(LHCALL_SET_CLOCKEVENT, 0, 0, 0, 0);
946 945 break;
947 946 case CLOCK_EVT_MODE_ONESHOT:
948 947 /* This is what we expect. */
... ... @@ -1100,7 +1099,7 @@
1100 1099 /* STOP! Until an interrupt comes in. */
1101 1100 static void lguest_safe_halt(void)
1102 1101 {
1103   - kvm_hypercall0(LHCALL_HALT);
  1102 + hcall(LHCALL_HALT, 0, 0, 0, 0);
1104 1103 }
1105 1104  
1106 1105 /*
... ... @@ -1112,8 +1111,8 @@
1112 1111 */
1113 1112 static void lguest_power_off(void)
1114 1113 {
1115   - kvm_hypercall2(LHCALL_SHUTDOWN, __pa("Power down"),
1116   - LGUEST_SHUTDOWN_POWEROFF);
  1114 + hcall(LHCALL_SHUTDOWN, __pa("Power down"),
  1115 + LGUEST_SHUTDOWN_POWEROFF, 0, 0);
1117 1116 }
1118 1117  
1119 1118 /*
... ... @@ -1123,7 +1122,7 @@
1123 1122 */
1124 1123 static int lguest_panic(struct notifier_block *nb, unsigned long l, void *p)
1125 1124 {
1126   - kvm_hypercall2(LHCALL_SHUTDOWN, __pa(p), LGUEST_SHUTDOWN_POWEROFF);
  1125 + hcall(LHCALL_SHUTDOWN, __pa(p), LGUEST_SHUTDOWN_POWEROFF, 0, 0);
1127 1126 /* The hcall won't return, but to keep gcc happy, we're "done". */
1128 1127 return NOTIFY_DONE;
1129 1128 }
... ... @@ -1162,7 +1161,7 @@
1162 1161 len = sizeof(scratch) - 1;
1163 1162 scratch[len] = '\0';
1164 1163 memcpy(scratch, buf, len);
1165   - kvm_hypercall1(LHCALL_NOTIFY, __pa(scratch));
  1164 + hcall(LHCALL_NOTIFY, __pa(scratch), 0, 0, 0);
1166 1165  
1167 1166 /* This routine returns the number of bytes actually written. */
1168 1167 return len;
... ... @@ -1174,7 +1173,7 @@
1174 1173 */
1175 1174 static void lguest_restart(char *reason)
1176 1175 {
1177   - kvm_hypercall2(LHCALL_SHUTDOWN, __pa(reason), LGUEST_SHUTDOWN_RESTART);
  1176 + hcall(LHCALL_SHUTDOWN, __pa(reason), LGUEST_SHUTDOWN_RESTART, 0, 0);
1178 1177 }
1179 1178  
1180 1179 /*G:050
arch/x86/lguest/i386_head.S
... ... @@ -32,7 +32,7 @@
32 32 */
33 33 movl $LHCALL_LGUEST_INIT, %eax
34 34 movl $lguest_data - __PAGE_OFFSET, %ebx
35   - .byte 0x0f,0x01,0xc1 /* KVM_HYPERCALL */
  35 + int $LGUEST_TRAP_ENTRY
36 36  
37 37 /* Set up the initial stack so we can run C code. */
38 38 movl $(init_thread_union+THREAD_SIZE),%esp
drivers/lguest/lguest_device.c
... ... @@ -178,7 +178,7 @@
178 178  
179 179 /* We set the status. */
180 180 to_lgdev(vdev)->desc->status = status;
181   - kvm_hypercall1(LHCALL_NOTIFY, (max_pfn << PAGE_SHIFT) + offset);
  181 + hcall(LHCALL_NOTIFY, (max_pfn << PAGE_SHIFT) + offset, 0, 0, 0);
182 182 }
183 183  
184 184 static void lg_set_status(struct virtio_device *vdev, u8 status)
... ... @@ -229,7 +229,7 @@
229 229 */
230 230 struct lguest_vq_info *lvq = vq->priv;
231 231  
232   - kvm_hypercall1(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT);
  232 + hcall(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT, 0, 0, 0);
233 233 }
234 234  
235 235 /* An extern declaration inside a C file is bad form. Don't do it. */