]> www.infradead.org Git - users/dwmw2/qemu.git/commitdiff
i386/xen: set shared_info page
authorJoao Martins <joao.m.martins@oracle.com>
Mon, 18 Jun 2018 16:17:42 +0000 (12:17 -0400)
committerJoao Martins <joao.m.martins@oracle.com>
Tue, 19 Feb 2019 14:00:57 +0000 (09:00 -0500)
This is done by implementing HYPERVISOR_memory_op specifically
XENMEM_add_to_physmap with space XENMAPSPACE_shared_info. While
Xen removes the page with it's own, we instead use the gfn passed
by the guest.

Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
accel/kvm/kvm-all.c
include/qom/cpu.h
include/sysemu/kvm.h
linux-headers/linux/kvm.h
target/i386/cpu.h
target/i386/trace-events
target/i386/xen-proto.h [new file with mode: 0644]
target/i386/xen.c

index fd92b6f37547dda48c5edc0d8578adb5470a421c..e035a01f0cb78486b63c8f3ca74fae7e20f77004 100644 (file)
@@ -110,6 +110,9 @@ struct KVMState
     /* memory encryption */
     void *memcrypt_handle;
     int (*memcrypt_encrypt_data)(void *handle, uint8_t *ptr, uint64_t len);
+
+    /* xen guest state */
+    struct XenState xen;
 };
 
 KVMState *kvm_state;
@@ -138,6 +141,11 @@ static const KVMCapabilityInfo kvm_required_capabilites[] = {
     KVM_CAP_LAST_INFO
 };
 
+struct XenState *kvm_get_xen_state(KVMState *s)
+{
+    return &s->xen;
+}
+
 int kvm_get_max_memslots(void)
 {
     KVMState *s = KVM_STATE(current_machine->accelerator);
@@ -347,6 +355,7 @@ int kvm_init_vcpu(CPUState *cpu)
     cpu->kvm_fd = ret;
     cpu->kvm_state = s;
     cpu->vcpu_dirty = true;
+    cpu->xen_state = &s->xen;
 
     mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
     if (mmap_size < 0) {
index 1d6099e5d4be3c1afd349f8fde73fe0e6306bd49..b9d88f3594d873307c180f0ed014d25fe042482b 100644 (file)
@@ -452,6 +452,8 @@ struct CPUState {
 
     /* track IOMMUs whose translations we've cached in the TCG TLB */
     GArray *iommu_notifiers;
+
+    struct XenState *xen_state;
 };
 
 typedef QTAILQ_HEAD(CPUTailQ, CPUState) CPUTailQ;
index a6d1cd190fed62e07489a1b29050305e22dbc66c..2fe9bfcb4da9cbf36dacf249347f8f581854a4b6 100644 (file)
@@ -547,4 +547,5 @@ int kvm_set_one_reg(CPUState *cs, uint64_t id, void *source);
 int kvm_get_one_reg(CPUState *cs, uint64_t id, void *target);
 struct ppc_radix_page_info *kvm_get_radix_page_info(void);
 int kvm_get_max_memslots(void);
+struct XenState *kvm_get_xen_state(KVMState *s);
 #endif
index 6a7b0a4d98632b86c05e70cc2aa7204c39fb22c2..996689087f75157824361a3e243b93b83a6d919d 100644 (file)
@@ -1454,6 +1454,21 @@ struct kvm_enc_region {
 /* Available with KVM_CAP_HYPERV_CPUID */
 #define KVM_GET_SUPPORTED_HV_CPUID _IOWR(KVMIO, 0xc1, struct kvm_cpuid2)
 
+#define KVM_XEN_HVM_GET_ATTR        _IOWR(KVMIO,  0xc2, struct kvm_xen_hvm_attr)
+#define KVM_XEN_HVM_SET_ATTR        _IOW(KVMIO,  0xc3, struct kvm_xen_hvm_attr)
+
+struct kvm_xen_hvm_attr {
+       __u16 type;
+
+       union {
+               struct {
+                       __u64 gfn;
+               } shared_info;
+       } u;
+};
+
+#define KVM_XEN_ATTR_TYPE_SHARED_INFO       0x0
+
 /* Secure Encrypted Virtualization command */
 enum sev_cmd_id {
        /* Guest initialization commands */
index cef37a8a2b9c5096ec8107913e53667910342096..e3fc8ce131e21e4a25167fbc5dfe688decf4b11b 100644 (file)
@@ -24,6 +24,7 @@
 #include "qemu-common.h"
 #include "cpu-qom.h"
 #include "hyperv-proto.h"
+#include "xen-proto.h"
 
 #ifdef TARGET_X86_64
 #define TARGET_LONG_BITS 64
index aa7a5c6a5fb23cf6ff9564f230dfc8be3c378e2e..444e33d53b592d3dcfe85f8c7232faf952cf1a6d 100644 (file)
@@ -18,3 +18,4 @@ kvm_sev_launch_finish(void) ""
 
 # target/i386/xen.c
 kvm_xen_hypercall(int cpu, uint64_t input, uint64_t a0, uint64_t a1, uint64_t a2, uint64_t ret) "xen_hypercall: cpu %d input %" PRIu64 " a0 0x%" PRIx64 " a1 0x%" PRIx64 " a2 0x%" PRIx64" ret 0x%" PRIu64
+kvm_xen_set_shared_info(uint64_t gfn) "shared info at gfn 0x%" PRIx64
diff --git a/target/i386/xen-proto.h b/target/i386/xen-proto.h
new file mode 100644 (file)
index 0000000..c394909
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Definitions for Xen guest/hypervisor interaction - x86-specific part
+ *
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef TARGET_I386_XEN_PROTO_H
+#define TARGET_I386_XEN_PROTO_H
+
+typedef struct XenState {
+    struct shared_info *shared_info;
+} XenState;
+
+#endif
+
index 420a956d7749014099d057da829456226e9187f4..10bb40c417633e6a69a241c57a983baf175dae95 100644 (file)
 #include "qemu/log.h"
 #include "linux/kvm.h"
 #include "exec/address-spaces.h"
-#include "standard-headers/xen/version.h"
 #include "cpu.h"
 #include "xen.h"
-
 #include "trace.h"
 
+#include "standard-headers/xen/version.h"
+#include "standard-headers/xen/memory.h"
+
 #define PAGE_OFFSET    0xffffffff80000000UL
+#define PAGE_SHIFT     12
 
 /*
  * Unhandled hypercalls error:
@@ -138,11 +140,70 @@ static int kvm_xen_hcall_xen_version(struct kvm_xen_exit *exit, X86CPU *cpu,
     return err ? HCALL_ERR : 0;
 }
 
+static int xen_set_shared_info(CPUState *cs, struct shared_info *shi,
+                               uint64_t gfn)
+{
+    struct kvm_xen_hvm_attr xhsi;
+    XenState *xen = cs->xen_state;
+    KVMState *s = cs->kvm_state;
+    int err;
+
+    xhsi.type = KVM_XEN_ATTR_TYPE_SHARED_INFO;
+    xhsi.u.shared_info.gfn = gfn;
+    err = kvm_vm_ioctl(s, KVM_XEN_HVM_SET_ATTR, &xhsi);
+    trace_kvm_xen_set_shared_info(gfn);
+    xen->shared_info = shi;
+    return err;
+}
+
+static int kvm_xen_hcall_memory_op(struct kvm_xen_exit *exit,
+                                   int cmd, uint64_t arg, X86CPU *cpu)
+{
+    CPUState *cs = CPU(cpu);
+    int err = 0;
+
+    switch (cmd) {
+    case XENMEM_add_to_physmap: {
+            struct xen_add_to_physmap *xatp;
+            struct shared_info *shi;
+
+            xatp = gva_to_hva(cs, arg);
+            if (!xatp) {
+                err = -EFAULT;
+                break;
+            }
+
+            switch (xatp->space) {
+            case XENMAPSPACE_shared_info:
+                break;
+            default:
+                err = -ENOSYS;
+                break;
+            }
+
+            shi = gpa_to_hva(xatp->gpfn << PAGE_SHIFT);
+            if (!shi) {
+                err = -EFAULT;
+                break;
+            }
+
+            err = xen_set_shared_info(cs, shi, xatp->gpfn);
+            break;
+         }
+    }
+
+    exit->u.hcall.result = err;
+    return err ? HCALL_ERR : 0;
+}
+
 static int __kvm_xen_handle_exit(X86CPU *cpu, struct kvm_xen_exit *exit)
 {
     uint16_t code = exit->u.hcall.input;
 
     switch (code) {
+    case __HYPERVISOR_memory_op:
+        return kvm_xen_hcall_memory_op(exit, exit->u.hcall.params[0],
+                                       exit->u.hcall.params[1], cpu);
     case __HYPERVISOR_xen_version:
         return kvm_xen_hcall_xen_version(exit, cpu, exit->u.hcall.params[0],
                                          exit->u.hcall.params[1]);