From: David Woodhouse <d...@amazon.co.uk> Signed-off-by: David Woodhouse <d...@amazon.co.uk> --- hw/i386/kvm/xen_gnttab.c | 31 ++++++++++++++++++++ hw/i386/kvm/xen_gnttab.h | 5 ++++ target/i386/kvm/xen-emu.c | 60 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+)
diff --git a/hw/i386/kvm/xen_gnttab.c b/hw/i386/kvm/xen_gnttab.c index 4341030151..7a63225aca 100644 --- a/hw/i386/kvm/xen_gnttab.c +++ b/hw/i386/kvm/xen_gnttab.c @@ -180,3 +180,34 @@ int xen_gnttab_map_page(uint64_t idx, uint64_t gfn) return 0; } +int xen_gnttab_set_version_op(struct gnttab_set_version *set) +{ + int ret; + + switch (set->version) { + case 1: + ret = 0; + break; + + case 2: + /* Behave as before set_version was introduced. */ + ret = -ENOSYS; + break; + + default: + ret = -EINVAL; + } + + set->version = 1; + return ret; +} + +int xen_gnttab_get_version_op(struct gnttab_get_version *get) +{ + if (get->dom != DOMID_SELF && get->dom != xen_domid) { + return -ESRCH; + } + + get->version = 1; + return 0; +} diff --git a/hw/i386/kvm/xen_gnttab.h b/hw/i386/kvm/xen_gnttab.h index a7caa94c83..79579677ba 100644 --- a/hw/i386/kvm/xen_gnttab.h +++ b/hw/i386/kvm/xen_gnttab.h @@ -15,4 +15,9 @@ void xen_gnttab_create(void); int xen_gnttab_map_page(uint64_t idx, uint64_t gfn); +struct gnttab_set_version; +struct gnttab_get_version; +int xen_gnttab_set_version_op(struct gnttab_set_version *set); +int xen_gnttab_get_version_op(struct gnttab_get_version *get); + #endif /* QEMU_XEN_GNTTAB_H */ diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c index 14f401fed7..a0803f93ee 100644 --- a/target/i386/kvm/xen-emu.c +++ b/target/i386/kvm/xen-emu.c @@ -34,6 +34,7 @@ #include "standard-headers/xen/hvm/params.h" #include "standard-headers/xen/vcpu.h" #include "standard-headers/xen/event_channel.h" +#include "standard-headers/xen/grant_table.h" #include "xen-compat.h" @@ -1159,6 +1160,61 @@ static bool kvm_xen_hcall_sched_op(struct kvm_xen_exit *exit, X86CPU *cpu, return true; } +static bool kvm_xen_hcall_gnttab_op(struct kvm_xen_exit *exit, X86CPU *cpu, + int cmd, uint64_t arg, int count) +{ + CPUState *cs = CPU(cpu); + int err; + + switch (cmd) { + case GNTTABOP_set_version: { + struct gnttab_set_version set; + + qemu_build_assert(sizeof(set) == 4); + if (kvm_copy_from_gva(cs, arg, &set, sizeof(set))) { + err = -EFAULT; + break; + } + + err = xen_gnttab_set_version_op(&set); + if (!err && kvm_copy_to_gva(cs, arg, &set, sizeof(set))) { + err = -EFAULT; + } + break; + } + case GNTTABOP_get_version: { + struct gnttab_get_version get; + + qemu_build_assert(sizeof(get) == 8); + if (kvm_copy_from_gva(cs, arg, &get, sizeof(get))) { + err = -EFAULT; + break; + } + + err = xen_gnttab_get_version_op(&get); + if (!err && kvm_copy_to_gva(cs, arg, &get, sizeof(get))) { + err = -EFAULT; + } + break; + } + case GNTTABOP_query_size: + case GNTTABOP_setup_table: + case GNTTABOP_copy: + case GNTTABOP_map_grant_ref: + case GNTTABOP_unmap_grant_ref: + case GNTTABOP_swap_grant_ref: + return false; + + default: + /* Xen explicitly returns -ENOSYS to HVM guests for all others */ + err = -ENOSYS; + break; + } + + exit->u.hcall.result = err; + return true; +} + static bool do_kvm_xen_handle_exit(X86CPU *cpu, struct kvm_xen_exit *exit) { uint16_t code = exit->u.hcall.input; @@ -1169,6 +1225,10 @@ static bool do_kvm_xen_handle_exit(X86CPU *cpu, struct kvm_xen_exit *exit) } switch (code) { + case __HYPERVISOR_grant_table_op: + return kvm_xen_hcall_gnttab_op(exit, cpu, exit->u.hcall.params[0], + exit->u.hcall.params[1], + exit->u.hcall.params[2]); case __HYPERVISOR_sched_op: return kvm_xen_hcall_sched_op(exit, cpu, exit->u.hcall.params[0], exit->u.hcall.params[1]); -- 2.39.0