On 16/01/2023 21:57, David Woodhouse wrote:
From: David Woodhouse <d...@amazon.co.uk>
The kvm_xen_inject_vcpu_callback_vector() function will either deliver
the per-vCPU local APIC vector (as an MSI), or just kick the vCPU out
of the kernel to trigger KVM's automatic delivery of the global vector.
Support for asserting the GSI/PCI_INTX callbacks will come later.
Also add kvm_xen_get_vcpu_info_hva() which returns the vcpu_info of
a given vCPU.
Signed-off-by: David Woodhouse <d...@amazon.co.uk>
---
include/sysemu/kvm_xen.h | 2 +
target/i386/cpu.h | 2 +
target/i386/kvm/xen-emu.c | 86 ++++++++++++++++++++++++++++++++++++---
3 files changed, 84 insertions(+), 6 deletions(-)
diff --git a/include/sysemu/kvm_xen.h b/include/sysemu/kvm_xen.h
index 3e43cd7843..ee53294deb 100644
--- a/include/sysemu/kvm_xen.h
+++ b/include/sysemu/kvm_xen.h
@@ -17,6 +17,8 @@
#define INVALID_GFN UINT64_MAX
uint32_t kvm_xen_get_caps(void);
+void *kvm_xen_get_vcpu_info_hva(uint32_t vcpu_id);
+void kvm_xen_inject_vcpu_callback_vector(uint32_t vcpu_id, int type);
#define kvm_xen_has_cap(cap) (!!(kvm_xen_get_caps() & \
KVM_XEN_HVM_CONFIG_ ## cap))
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 938a1b9c8b..c9b12e7476 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1788,6 +1788,8 @@ typedef struct CPUArchState {
#endif
#if defined(CONFIG_KVM)
struct kvm_nested_state *nested_state;
+ MemoryRegion *xen_vcpu_info_mr;
+ void *xen_vcpu_info_hva;
uint64_t xen_vcpu_info_gpa;
uint64_t xen_vcpu_info_default_gpa;
uint64_t xen_vcpu_time_info_gpa;
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index b0e7620b16..d04d858912 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -20,6 +20,8 @@
#include "trace.h"
#include "sysemu/runstate.h"
+#include "hw/pci/msi.h"
+#include "hw/i386/apic-msidef.h"
#include "hw/i386/kvm/xen_overlay.h"
#include "hw/i386/kvm/xen_evtchn.h"
@@ -247,6 +249,35 @@ static void do_set_vcpu_callback_vector(CPUState *cs, run_on_cpu_data data)
}
}
+static int set_vcpu_info(CPUState *cs, uint64_t gpa)
+{
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+ MemoryRegionSection mrs;
+ int ret;
+
+ ret = kvm_xen_set_vcpu_attr(cs, KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO, gpa);
+ if (ret || gpa == INVALID_GPA) {
+ fail:
Ick. Do we really want cross-block gotos? For me it would look a lot
nicer if you did a forward jump here and later and put the label+code
after the `return 0`.
+ if (env->xen_vcpu_info_mr) {
+ memory_region_unref(env->xen_vcpu_info_mr);
+ env->xen_vcpu_info_mr = NULL;
+ }
+ env->xen_vcpu_info_hva = NULL;
+ return ret;
+ }
+
+ mrs = memory_region_find(get_system_memory(), gpa, sizeof(struct
vcpu_info));
+ if (!mrs.mr || !mrs.mr->ram_block || mrs.size < sizeof(struct vcpu_info) ||
+ !(env->xen_vcpu_info_hva = qemu_map_ram_ptr(mrs.mr->ram_block,
+
mrs.offset_within_region))) {
+ ret = -EINVAL;
+ goto fail;
+ }
+ env->xen_vcpu_info_mr = mrs.mr;
+ return 0;
+}