]> rtime.felk.cvut.cz Git - jailhouse.git/commitdiff
x86: Make vcpu_handle_hypercall() generic
authorValentine Sinitsyn <valentine.sinitsyn@gmail.com>
Fri, 15 Aug 2014 19:07:55 +0000 (01:07 +0600)
committerJan Kiszka <jan.kiszka@siemens.com>
Fri, 10 Oct 2014 11:47:37 +0000 (13:47 +0200)
Hypercall handling code can now be used for any vendor.
This implies implementing accessor to EFER, RFLAGS, CS and RIP,
(commonly referred to as "execution state") and also making
vcpu_deactivate_vmm() non-static.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
hypervisor/arch/x86/include/asm/vcpu.h
hypervisor/arch/x86/vcpu.c
hypervisor/arch/x86/vmx.c

index 4e0d9b55a9305e91cc7e3da6065b41f0a8c716ce..ea574946ca720c9e82876ee7c31426ad48be9805 100644 (file)
@@ -26,6 +26,13 @@ struct vcpu_io_bitmap {
        u32 size;
 };
 
+struct vcpu_execution_state {
+       u64 efer;
+       u64 rflags;
+       u16 cs;
+       u64 rip;
+};
+
 int vcpu_vendor_init(void);
 
 int vcpu_cell_init(struct cell *cell);
@@ -42,6 +49,9 @@ int vcpu_init(struct per_cpu *cpu_data);
 void vcpu_exit(struct per_cpu *cpu_data);
 
 void __attribute__((noreturn)) vcpu_activate_vmm(struct per_cpu *cpu_data);
+void __attribute__((noreturn))
+vcpu_deactivate_vmm(struct registers *guest_regs);
+
 void vcpu_handle_exit(struct registers *guest_regs, struct per_cpu *cpu_data);
 
 void vcpu_park(struct per_cpu *cpu_data);
@@ -72,6 +82,11 @@ void vcpu_skip_emulated_instruction(unsigned int inst_len);
 void vcpu_vendor_get_cell_io_bitmap(struct cell *cell,
                                    struct vcpu_io_bitmap *out);
 
+void vcpu_vendor_get_execution_state(struct vcpu_execution_state *x_state);
+
+void vcpu_handle_hypercall(struct registers *guest_regs,
+                          struct vcpu_execution_state *x_state);
+
 bool vcpu_get_guest_paging_structs(struct guest_paging_structures *pg_structs);
 
 #endif
index 35462c1ba09505ff7fb44294d2f3f940bf3fb2c6..d202f0f28ec9283fd2c2f52e287065c8812d9d26 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <jailhouse/control.h>
 #include <jailhouse/paging.h>
+#include <jailhouse/printk.h>
 #include <jailhouse/string.h>
 #include <jailhouse/types.h>
 #include <asm/i8042.h>
@@ -126,3 +127,30 @@ void vcpu_cell_exit(struct cell *cell)
 
        vcpu_vendor_cell_exit(cell);
 }
+
+void vcpu_handle_hypercall(struct registers *guest_regs,
+                          struct vcpu_execution_state *x_state)
+{
+       bool long_mode = !!(x_state->efer & EFER_LMA);
+       unsigned long arg_mask = long_mode ? (u64)-1 : (u32)-1;
+       struct per_cpu *cpu_data = this_cpu_data();
+       unsigned long code = guest_regs->rax;
+
+       vcpu_skip_emulated_instruction(X86_INST_LEN_VMCALL);
+
+       if ((!long_mode && (x_state->rflags & X86_RFLAGS_VM)) ||
+           (x_state->cs & 3) != 0) {
+               guest_regs->rax = -EPERM;
+               return;
+       }
+
+       guest_regs->rax = hypercall(code, guest_regs->rdi & arg_mask,
+                                   guest_regs->rsi & arg_mask);
+       if (guest_regs->rax == -ENOSYS)
+               printk("CPU %d: Unknown vmcall %d, RIP: %p\n",
+                      cpu_data->cpu_id, code,
+                      x_state->rip - X86_INST_LEN_VMCALL);
+
+       if (code == JAILHOUSE_HC_DISABLE && guest_regs->rax == 0)
+               vcpu_deactivate_vmm(guest_regs);
+}
index 794792c50b5ac218eb9f2c10ccb381cc42fecf46..d7d164d0c9bcece5d129afba01f8615c98ba3a27 100644 (file)
@@ -622,8 +622,8 @@ void vcpu_activate_vmm(struct per_cpu *cpu_data)
        panic_stop();
 }
 
-static void __attribute__((noreturn))
-vmx_cpu_deactivate_vmm(struct registers *guest_regs)
+void __attribute__((noreturn))
+vcpu_deactivate_vmm(struct registers *guest_regs)
 {
        unsigned long *stack = (unsigned long *)vmcs_read64(GUEST_RSP);
        unsigned long linux_ip = vmcs_read64(GUEST_RIP);
@@ -816,30 +816,6 @@ static void update_efer(void)
                     vmcs_read32(VM_ENTRY_CONTROLS) | VM_ENTRY_IA32E_MODE);
 }
 
-static void vcpu_handle_hypercall(struct registers *guest_regs)
-{
-       bool ia32e_mode = !!(vmcs_read64(GUEST_IA32_EFER) & EFER_LMA);
-       unsigned long arg_mask = ia32e_mode ? (u64)-1 : (u32)-1;
-       unsigned long code = guest_regs->rax;
-
-       vcpu_skip_emulated_instruction(X86_INST_LEN_VMCALL);
-
-       if ((!ia32e_mode && vmcs_read64(GUEST_RFLAGS) & X86_RFLAGS_VM) ||
-           (vmcs_read16(GUEST_CS_SELECTOR) & 3) != 0) {
-               guest_regs->rax = -EPERM;
-               return;
-       }
-
-       guest_regs->rax = hypercall(code, guest_regs->rdi & arg_mask,
-                                   guest_regs->rsi & arg_mask);
-       if (guest_regs->rax == -ENOSYS)
-               printk("CPU %d: Unknown vmcall %d, RIP: %p\n", this_cpu_id(),
-                      code, vmcs_read64(GUEST_RIP) - X86_INST_LEN_VMCALL);
-
-       if (code == JAILHOUSE_HC_DISABLE && guest_regs->rax == 0)
-               vmx_cpu_deactivate_vmm(guest_regs);
-}
-
 static bool vmx_handle_cr(struct registers *guest_regs,
                          struct per_cpu *cpu_data)
 {
@@ -1043,6 +1019,7 @@ invalid_access:
 void vcpu_handle_exit(struct registers *guest_regs, struct per_cpu *cpu_data)
 {
        u32 reason = vmcs_read32(VM_EXIT_REASON);
+       struct vcpu_execution_state x_state;
        int sipi_vector;
 
        cpu_data->stats[JAILHOUSE_CPU_STAT_VMEXITS_TOTAL]++;
@@ -1073,7 +1050,8 @@ void vcpu_handle_exit(struct registers *guest_regs, struct per_cpu *cpu_data)
                        (u32 *)&guest_regs->rcx, (u32 *)&guest_regs->rdx);
                return;
        case EXIT_REASON_VMCALL:
-               vcpu_handle_hypercall(guest_regs);
+               vcpu_vendor_get_execution_state(&x_state);
+               vcpu_handle_hypercall(guest_regs, &x_state);
                return;
        case EXIT_REASON_CR_ACCESS:
                cpu_data->stats[JAILHOUSE_CPU_STAT_VMEXITS_CR]++;
@@ -1159,3 +1137,11 @@ void vcpu_vendor_get_cell_io_bitmap(struct cell *cell,
        iobm->data = cell->vmx.io_bitmap;
        iobm->size = sizeof(cell->vmx.io_bitmap);
 }
+
+void vcpu_vendor_get_execution_state(struct vcpu_execution_state *x_state)
+{
+       x_state->efer = vmcs_read64(GUEST_IA32_EFER);
+       x_state->rflags = vmcs_read64(GUEST_RFLAGS);
+       x_state->cs = vmcs_read16(GUEST_CS_SELECTOR);
+       x_state->rip = vmcs_read64(GUEST_RIP);
+}