| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| /* | ||
| * QEMU Xen emulation: Event channel support | ||
| * | ||
| * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| * | ||
| * Authors: David Woodhouse <dwmw2@infradead.org> | ||
| * | ||
| * 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 QEMU_XEN_EVTCHN_H | ||
| #define QEMU_XEN_EVTCHN_H | ||
|
|
||
| #include "hw/sysbus.h" | ||
|
|
||
| typedef uint32_t evtchn_port_t; | ||
|
|
||
| void xen_evtchn_create(void); | ||
| int xen_evtchn_soft_reset(void); | ||
| int xen_evtchn_set_callback_param(uint64_t param); | ||
| void xen_evtchn_connect_gsis(qemu_irq *system_gsis); | ||
| void xen_evtchn_set_callback_level(int level); | ||
|
|
||
| int xen_evtchn_set_port(uint16_t port); | ||
|
|
||
| bool xen_evtchn_set_gsi(int gsi, int level); | ||
| void xen_evtchn_snoop_msi(PCIDevice *dev, bool is_msix, unsigned int vector, | ||
| uint64_t addr, uint32_t data, bool is_masked); | ||
| void xen_evtchn_remove_pci_device(PCIDevice *dev); | ||
| struct kvm_irq_routing_entry; | ||
| int xen_evtchn_translate_pirq_msi(struct kvm_irq_routing_entry *route, | ||
| uint64_t address, uint32_t data); | ||
| bool xen_evtchn_deliver_pirq_msi(uint64_t address, uint32_t data); | ||
|
|
||
|
|
||
| /* | ||
| * These functions mirror the libxenevtchn library API, providing the QEMU | ||
| * backend side of "interdomain" event channels. | ||
| */ | ||
| struct xenevtchn_handle; | ||
| struct xenevtchn_handle *xen_be_evtchn_open(void); | ||
| int xen_be_evtchn_bind_interdomain(struct xenevtchn_handle *xc, uint32_t domid, | ||
| evtchn_port_t guest_port); | ||
| int xen_be_evtchn_unbind(struct xenevtchn_handle *xc, evtchn_port_t port); | ||
| int xen_be_evtchn_close(struct xenevtchn_handle *xc); | ||
| int xen_be_evtchn_fd(struct xenevtchn_handle *xc); | ||
| int xen_be_evtchn_notify(struct xenevtchn_handle *xc, evtchn_port_t port); | ||
| int xen_be_evtchn_unmask(struct xenevtchn_handle *xc, evtchn_port_t port); | ||
| int xen_be_evtchn_pending(struct xenevtchn_handle *xc); | ||
| /* Apart from this which is a local addition */ | ||
| int xen_be_evtchn_get_guest_port(struct xenevtchn_handle *xc); | ||
|
|
||
| struct evtchn_status; | ||
| struct evtchn_close; | ||
| struct evtchn_unmask; | ||
| struct evtchn_bind_virq; | ||
| struct evtchn_bind_pirq; | ||
| struct evtchn_bind_ipi; | ||
| struct evtchn_send; | ||
| struct evtchn_alloc_unbound; | ||
| struct evtchn_bind_interdomain; | ||
| struct evtchn_bind_vcpu; | ||
| struct evtchn_reset; | ||
| int xen_evtchn_status_op(struct evtchn_status *status); | ||
| int xen_evtchn_close_op(struct evtchn_close *close); | ||
| int xen_evtchn_unmask_op(struct evtchn_unmask *unmask); | ||
| int xen_evtchn_bind_virq_op(struct evtchn_bind_virq *virq); | ||
| int xen_evtchn_bind_pirq_op(struct evtchn_bind_pirq *pirq); | ||
| int xen_evtchn_bind_ipi_op(struct evtchn_bind_ipi *ipi); | ||
| int xen_evtchn_send_op(struct evtchn_send *send); | ||
| int xen_evtchn_alloc_unbound_op(struct evtchn_alloc_unbound *alloc); | ||
| int xen_evtchn_bind_interdomain_op(struct evtchn_bind_interdomain *interdomain); | ||
| int xen_evtchn_bind_vcpu_op(struct evtchn_bind_vcpu *vcpu); | ||
| int xen_evtchn_reset_op(struct evtchn_reset *reset); | ||
|
|
||
| struct physdev_map_pirq; | ||
| struct physdev_unmap_pirq; | ||
| struct physdev_eoi; | ||
| struct physdev_irq_status_query; | ||
| struct physdev_get_free_pirq; | ||
| int xen_physdev_map_pirq(struct physdev_map_pirq *map); | ||
| int xen_physdev_unmap_pirq(struct physdev_unmap_pirq *unmap); | ||
| int xen_physdev_eoi_pirq(struct physdev_eoi *eoi); | ||
| int xen_physdev_query_pirq(struct physdev_irq_status_query *query); | ||
| int xen_physdev_get_free_pirq(struct physdev_get_free_pirq *get); | ||
|
|
||
| #endif /* QEMU_XEN_EVTCHN_H */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,232 @@ | ||
| /* | ||
| * QEMU Xen emulation: Grant table support | ||
| * | ||
| * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| * | ||
| * Authors: David Woodhouse <dwmw2@infradead.org> | ||
| * | ||
| * This work is licensed under the terms of the GNU GPL, version 2 or later. | ||
| * See the COPYING file in the top-level directory. | ||
| */ | ||
|
|
||
| #include "qemu/osdep.h" | ||
| #include "qemu/host-utils.h" | ||
| #include "qemu/module.h" | ||
| #include "qemu/lockable.h" | ||
| #include "qemu/main-loop.h" | ||
| #include "qapi/error.h" | ||
| #include "qom/object.h" | ||
| #include "exec/target_page.h" | ||
| #include "exec/address-spaces.h" | ||
| #include "migration/vmstate.h" | ||
|
|
||
| #include "hw/sysbus.h" | ||
| #include "hw/xen/xen.h" | ||
| #include "xen_overlay.h" | ||
| #include "xen_gnttab.h" | ||
|
|
||
| #include "sysemu/kvm.h" | ||
| #include "sysemu/kvm_xen.h" | ||
|
|
||
| #include "hw/xen/interface/memory.h" | ||
| #include "hw/xen/interface/grant_table.h" | ||
|
|
||
| #define TYPE_XEN_GNTTAB "xen-gnttab" | ||
| OBJECT_DECLARE_SIMPLE_TYPE(XenGnttabState, XEN_GNTTAB) | ||
|
|
||
| #define XEN_PAGE_SHIFT 12 | ||
| #define XEN_PAGE_SIZE (1ULL << XEN_PAGE_SHIFT) | ||
|
|
||
| #define ENTRIES_PER_FRAME_V1 (XEN_PAGE_SIZE / sizeof(grant_entry_v1_t)) | ||
|
|
||
| struct XenGnttabState { | ||
| /*< private >*/ | ||
| SysBusDevice busdev; | ||
| /*< public >*/ | ||
|
|
||
| QemuMutex gnt_lock; | ||
|
|
||
| uint32_t nr_frames; | ||
| uint32_t max_frames; | ||
|
|
||
| union { | ||
| grant_entry_v1_t *v1; | ||
| /* Theoretically, v2 support could be added here. */ | ||
| } entries; | ||
|
|
||
| MemoryRegion gnt_frames; | ||
| MemoryRegion *gnt_aliases; | ||
| uint64_t *gnt_frame_gpas; | ||
| }; | ||
|
|
||
| struct XenGnttabState *xen_gnttab_singleton; | ||
|
|
||
| static void xen_gnttab_realize(DeviceState *dev, Error **errp) | ||
| { | ||
| XenGnttabState *s = XEN_GNTTAB(dev); | ||
| int i; | ||
|
|
||
| if (xen_mode != XEN_EMULATE) { | ||
| error_setg(errp, "Xen grant table support is for Xen emulation"); | ||
| return; | ||
| } | ||
| s->nr_frames = 0; | ||
| s->max_frames = kvm_xen_get_gnttab_max_frames(); | ||
| memory_region_init_ram(&s->gnt_frames, OBJECT(dev), "xen:grant_table", | ||
| XEN_PAGE_SIZE * s->max_frames, &error_abort); | ||
| memory_region_set_enabled(&s->gnt_frames, true); | ||
| s->entries.v1 = memory_region_get_ram_ptr(&s->gnt_frames); | ||
| memset(s->entries.v1, 0, XEN_PAGE_SIZE * s->max_frames); | ||
|
|
||
| /* Create individual page-sizes aliases for overlays */ | ||
| s->gnt_aliases = (void *)g_new0(MemoryRegion, s->max_frames); | ||
| s->gnt_frame_gpas = (void *)g_new(uint64_t, s->max_frames); | ||
| for (i = 0; i < s->max_frames; i++) { | ||
| memory_region_init_alias(&s->gnt_aliases[i], OBJECT(dev), | ||
| NULL, &s->gnt_frames, | ||
| i * XEN_PAGE_SIZE, XEN_PAGE_SIZE); | ||
| s->gnt_frame_gpas[i] = INVALID_GPA; | ||
| } | ||
|
|
||
| qemu_mutex_init(&s->gnt_lock); | ||
|
|
||
| xen_gnttab_singleton = s; | ||
| } | ||
|
|
||
| static int xen_gnttab_post_load(void *opaque, int version_id) | ||
| { | ||
| XenGnttabState *s = XEN_GNTTAB(opaque); | ||
| uint32_t i; | ||
|
|
||
| for (i = 0; i < s->nr_frames; i++) { | ||
| if (s->gnt_frame_gpas[i] != INVALID_GPA) { | ||
| xen_overlay_do_map_page(&s->gnt_aliases[i], s->gnt_frame_gpas[i]); | ||
| } | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| static bool xen_gnttab_is_needed(void *opaque) | ||
| { | ||
| return xen_mode == XEN_EMULATE; | ||
| } | ||
|
|
||
| static const VMStateDescription xen_gnttab_vmstate = { | ||
| .name = "xen_gnttab", | ||
| .version_id = 1, | ||
| .minimum_version_id = 1, | ||
| .needed = xen_gnttab_is_needed, | ||
| .post_load = xen_gnttab_post_load, | ||
| .fields = (VMStateField[]) { | ||
| VMSTATE_UINT32(nr_frames, XenGnttabState), | ||
| VMSTATE_VARRAY_UINT32(gnt_frame_gpas, XenGnttabState, nr_frames, 0, | ||
| vmstate_info_uint64, uint64_t), | ||
| VMSTATE_END_OF_LIST() | ||
| } | ||
| }; | ||
|
|
||
| static void xen_gnttab_class_init(ObjectClass *klass, void *data) | ||
| { | ||
| DeviceClass *dc = DEVICE_CLASS(klass); | ||
|
|
||
| dc->realize = xen_gnttab_realize; | ||
| dc->vmsd = &xen_gnttab_vmstate; | ||
| } | ||
|
|
||
| static const TypeInfo xen_gnttab_info = { | ||
| .name = TYPE_XEN_GNTTAB, | ||
| .parent = TYPE_SYS_BUS_DEVICE, | ||
| .instance_size = sizeof(XenGnttabState), | ||
| .class_init = xen_gnttab_class_init, | ||
| }; | ||
|
|
||
| void xen_gnttab_create(void) | ||
| { | ||
| xen_gnttab_singleton = XEN_GNTTAB(sysbus_create_simple(TYPE_XEN_GNTTAB, | ||
| -1, NULL)); | ||
| } | ||
|
|
||
| static void xen_gnttab_register_types(void) | ||
| { | ||
| type_register_static(&xen_gnttab_info); | ||
| } | ||
|
|
||
| type_init(xen_gnttab_register_types) | ||
|
|
||
| int xen_gnttab_map_page(uint64_t idx, uint64_t gfn) | ||
| { | ||
| XenGnttabState *s = xen_gnttab_singleton; | ||
| uint64_t gpa = gfn << XEN_PAGE_SHIFT; | ||
|
|
||
| if (!s) { | ||
| return -ENOTSUP; | ||
| } | ||
|
|
||
| if (idx >= s->max_frames) { | ||
| return -EINVAL; | ||
| } | ||
|
|
||
| QEMU_IOTHREAD_LOCK_GUARD(); | ||
| QEMU_LOCK_GUARD(&s->gnt_lock); | ||
|
|
||
| xen_overlay_do_map_page(&s->gnt_aliases[idx], gpa); | ||
|
|
||
| s->gnt_frame_gpas[idx] = gpa; | ||
|
|
||
| if (s->nr_frames <= idx) { | ||
| s->nr_frames = idx + 1; | ||
| } | ||
|
|
||
| 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; | ||
| } | ||
|
|
||
| int xen_gnttab_query_size_op(struct gnttab_query_size *size) | ||
| { | ||
| XenGnttabState *s = xen_gnttab_singleton; | ||
|
|
||
| if (!s) { | ||
| return -ENOTSUP; | ||
| } | ||
|
|
||
| if (size->dom != DOMID_SELF && size->dom != xen_domid) { | ||
| size->status = GNTST_bad_domain; | ||
| return 0; | ||
| } | ||
|
|
||
| size->status = GNTST_okay; | ||
| size->nr_frames = s->nr_frames; | ||
| size->max_nr_frames = s->max_frames; | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| /* | ||
| * QEMU Xen emulation: Grant table support | ||
| * | ||
| * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| * | ||
| * Authors: David Woodhouse <dwmw2@infradead.org> | ||
| * | ||
| * 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 QEMU_XEN_GNTTAB_H | ||
| #define QEMU_XEN_GNTTAB_H | ||
|
|
||
| void xen_gnttab_create(void); | ||
| int xen_gnttab_map_page(uint64_t idx, uint64_t gfn); | ||
|
|
||
| struct gnttab_set_version; | ||
| struct gnttab_get_version; | ||
| struct gnttab_query_size; | ||
| int xen_gnttab_set_version_op(struct gnttab_set_version *set); | ||
| int xen_gnttab_get_version_op(struct gnttab_get_version *get); | ||
| int xen_gnttab_query_size_op(struct gnttab_query_size *size); | ||
|
|
||
| #endif /* QEMU_XEN_GNTTAB_H */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,272 @@ | ||
| /* | ||
| * QEMU Xen emulation: Shared/overlay pages support | ||
| * | ||
| * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| * | ||
| * Authors: David Woodhouse <dwmw2@infradead.org> | ||
| * | ||
| * This work is licensed under the terms of the GNU GPL, version 2 or later. | ||
| * See the COPYING file in the top-level directory. | ||
| */ | ||
|
|
||
| #include "qemu/osdep.h" | ||
| #include "qemu/host-utils.h" | ||
| #include "qemu/module.h" | ||
| #include "qemu/main-loop.h" | ||
| #include "qapi/error.h" | ||
| #include "qom/object.h" | ||
| #include "exec/target_page.h" | ||
| #include "exec/address-spaces.h" | ||
| #include "migration/vmstate.h" | ||
|
|
||
| #include "hw/sysbus.h" | ||
| #include "hw/xen/xen.h" | ||
| #include "xen_overlay.h" | ||
|
|
||
| #include "sysemu/kvm.h" | ||
| #include "sysemu/kvm_xen.h" | ||
| #include <linux/kvm.h> | ||
|
|
||
| #include "hw/xen/interface/memory.h" | ||
|
|
||
|
|
||
| #define TYPE_XEN_OVERLAY "xen-overlay" | ||
| OBJECT_DECLARE_SIMPLE_TYPE(XenOverlayState, XEN_OVERLAY) | ||
|
|
||
| #define XEN_PAGE_SHIFT 12 | ||
| #define XEN_PAGE_SIZE (1ULL << XEN_PAGE_SHIFT) | ||
|
|
||
| struct XenOverlayState { | ||
| /*< private >*/ | ||
| SysBusDevice busdev; | ||
| /*< public >*/ | ||
|
|
||
| MemoryRegion shinfo_mem; | ||
| void *shinfo_ptr; | ||
| uint64_t shinfo_gpa; | ||
| bool long_mode; | ||
| }; | ||
|
|
||
| struct XenOverlayState *xen_overlay_singleton; | ||
|
|
||
| void xen_overlay_do_map_page(MemoryRegion *page, uint64_t gpa) | ||
| { | ||
| /* | ||
| * Xen allows guests to map the same page as many times as it likes | ||
| * into guest physical frames. We don't, because it would be hard | ||
| * to track and restore them all. One mapping of each page is | ||
| * perfectly sufficient for all known guests... and we've tested | ||
| * that theory on a few now in other implementations. dwmw2. | ||
| */ | ||
| if (memory_region_is_mapped(page)) { | ||
| if (gpa == INVALID_GPA) { | ||
| memory_region_del_subregion(get_system_memory(), page); | ||
| } else { | ||
| /* Just move it */ | ||
| memory_region_set_address(page, gpa); | ||
| } | ||
| } else if (gpa != INVALID_GPA) { | ||
| memory_region_add_subregion_overlap(get_system_memory(), gpa, page, 0); | ||
| } | ||
| } | ||
|
|
||
| /* KVM is the only existing back end for now. Let's not overengineer it yet. */ | ||
| static int xen_overlay_set_be_shinfo(uint64_t gfn) | ||
| { | ||
| struct kvm_xen_hvm_attr xa = { | ||
| .type = KVM_XEN_ATTR_TYPE_SHARED_INFO, | ||
| .u.shared_info.gfn = gfn, | ||
| }; | ||
|
|
||
| return kvm_vm_ioctl(kvm_state, KVM_XEN_HVM_SET_ATTR, &xa); | ||
| } | ||
|
|
||
|
|
||
| static void xen_overlay_realize(DeviceState *dev, Error **errp) | ||
| { | ||
| XenOverlayState *s = XEN_OVERLAY(dev); | ||
|
|
||
| if (xen_mode != XEN_EMULATE) { | ||
| error_setg(errp, "Xen overlay page support is for Xen emulation"); | ||
| return; | ||
| } | ||
|
|
||
| memory_region_init_ram(&s->shinfo_mem, OBJECT(dev), "xen:shared_info", | ||
| XEN_PAGE_SIZE, &error_abort); | ||
| memory_region_set_enabled(&s->shinfo_mem, true); | ||
|
|
||
| s->shinfo_ptr = memory_region_get_ram_ptr(&s->shinfo_mem); | ||
| s->shinfo_gpa = INVALID_GPA; | ||
| s->long_mode = false; | ||
| memset(s->shinfo_ptr, 0, XEN_PAGE_SIZE); | ||
| } | ||
|
|
||
| static int xen_overlay_pre_save(void *opaque) | ||
| { | ||
| /* | ||
| * Fetch the kernel's idea of long_mode to avoid the race condition | ||
| * where the guest has set the hypercall page up in 64-bit mode but | ||
| * not yet made a hypercall by the time migration happens, so qemu | ||
| * hasn't yet noticed. | ||
| */ | ||
| return xen_sync_long_mode(); | ||
| } | ||
|
|
||
| static int xen_overlay_post_load(void *opaque, int version_id) | ||
| { | ||
| XenOverlayState *s = opaque; | ||
|
|
||
| if (s->shinfo_gpa != INVALID_GPA) { | ||
| xen_overlay_do_map_page(&s->shinfo_mem, s->shinfo_gpa); | ||
| xen_overlay_set_be_shinfo(s->shinfo_gpa >> XEN_PAGE_SHIFT); | ||
| } | ||
| if (s->long_mode) { | ||
| xen_set_long_mode(true); | ||
| } | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| static bool xen_overlay_is_needed(void *opaque) | ||
| { | ||
| return xen_mode == XEN_EMULATE; | ||
| } | ||
|
|
||
| static const VMStateDescription xen_overlay_vmstate = { | ||
| .name = "xen_overlay", | ||
| .version_id = 1, | ||
| .minimum_version_id = 1, | ||
| .needed = xen_overlay_is_needed, | ||
| .pre_save = xen_overlay_pre_save, | ||
| .post_load = xen_overlay_post_load, | ||
| .fields = (VMStateField[]) { | ||
| VMSTATE_UINT64(shinfo_gpa, XenOverlayState), | ||
| VMSTATE_BOOL(long_mode, XenOverlayState), | ||
| VMSTATE_END_OF_LIST() | ||
| } | ||
| }; | ||
|
|
||
| static void xen_overlay_reset(DeviceState *dev) | ||
| { | ||
| kvm_xen_soft_reset(); | ||
| } | ||
|
|
||
| static void xen_overlay_class_init(ObjectClass *klass, void *data) | ||
| { | ||
| DeviceClass *dc = DEVICE_CLASS(klass); | ||
|
|
||
| dc->reset = xen_overlay_reset; | ||
| dc->realize = xen_overlay_realize; | ||
| dc->vmsd = &xen_overlay_vmstate; | ||
| } | ||
|
|
||
| static const TypeInfo xen_overlay_info = { | ||
| .name = TYPE_XEN_OVERLAY, | ||
| .parent = TYPE_SYS_BUS_DEVICE, | ||
| .instance_size = sizeof(XenOverlayState), | ||
| .class_init = xen_overlay_class_init, | ||
| }; | ||
|
|
||
| void xen_overlay_create(void) | ||
| { | ||
| xen_overlay_singleton = XEN_OVERLAY(sysbus_create_simple(TYPE_XEN_OVERLAY, | ||
| -1, NULL)); | ||
|
|
||
| /* If xen_domid wasn't explicitly set, at least make sure it isn't zero. */ | ||
| if (xen_domid == DOMID_QEMU) { | ||
| xen_domid = 1; | ||
| }; | ||
| } | ||
|
|
||
| static void xen_overlay_register_types(void) | ||
| { | ||
| type_register_static(&xen_overlay_info); | ||
| } | ||
|
|
||
| type_init(xen_overlay_register_types) | ||
|
|
||
| int xen_overlay_map_shinfo_page(uint64_t gpa) | ||
| { | ||
| XenOverlayState *s = xen_overlay_singleton; | ||
| int ret; | ||
|
|
||
| if (!s) { | ||
| return -ENOENT; | ||
| } | ||
|
|
||
| assert(qemu_mutex_iothread_locked()); | ||
|
|
||
| if (s->shinfo_gpa) { | ||
| /* If removing shinfo page, turn the kernel magic off first */ | ||
| ret = xen_overlay_set_be_shinfo(INVALID_GFN); | ||
| if (ret) { | ||
| return ret; | ||
| } | ||
| } | ||
|
|
||
| xen_overlay_do_map_page(&s->shinfo_mem, gpa); | ||
| if (gpa != INVALID_GPA) { | ||
| ret = xen_overlay_set_be_shinfo(gpa >> XEN_PAGE_SHIFT); | ||
| if (ret) { | ||
| return ret; | ||
| } | ||
| } | ||
| s->shinfo_gpa = gpa; | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| void *xen_overlay_get_shinfo_ptr(void) | ||
| { | ||
| XenOverlayState *s = xen_overlay_singleton; | ||
|
|
||
| if (!s) { | ||
| return NULL; | ||
| } | ||
|
|
||
| return s->shinfo_ptr; | ||
| } | ||
|
|
||
| int xen_sync_long_mode(void) | ||
| { | ||
| int ret; | ||
| struct kvm_xen_hvm_attr xa = { | ||
| .type = KVM_XEN_ATTR_TYPE_LONG_MODE, | ||
| }; | ||
|
|
||
| if (!xen_overlay_singleton) { | ||
| return -ENOENT; | ||
| } | ||
|
|
||
| ret = kvm_vm_ioctl(kvm_state, KVM_XEN_HVM_GET_ATTR, &xa); | ||
| if (!ret) { | ||
| xen_overlay_singleton->long_mode = xa.u.long_mode; | ||
| } | ||
|
|
||
| return ret; | ||
| } | ||
|
|
||
| int xen_set_long_mode(bool long_mode) | ||
| { | ||
| int ret; | ||
| struct kvm_xen_hvm_attr xa = { | ||
| .type = KVM_XEN_ATTR_TYPE_LONG_MODE, | ||
| .u.long_mode = long_mode, | ||
| }; | ||
|
|
||
| if (!xen_overlay_singleton) { | ||
| return -ENOENT; | ||
| } | ||
|
|
||
| ret = kvm_vm_ioctl(kvm_state, KVM_XEN_HVM_SET_ATTR, &xa); | ||
| if (!ret) { | ||
| xen_overlay_singleton->long_mode = xa.u.long_mode; | ||
| } | ||
|
|
||
| return ret; | ||
| } | ||
|
|
||
| bool xen_is_long_mode(void) | ||
| { | ||
| return xen_overlay_singleton && xen_overlay_singleton->long_mode; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| /* | ||
| * QEMU Xen emulation: Shared/overlay pages support | ||
| * | ||
| * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| * | ||
| * Authors: David Woodhouse <dwmw2@infradead.org> | ||
| * | ||
| * 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 QEMU_XEN_OVERLAY_H | ||
| #define QEMU_XEN_OVERLAY_H | ||
|
|
||
| void xen_overlay_create(void); | ||
|
|
||
| int xen_overlay_map_shinfo_page(uint64_t gpa); | ||
| void *xen_overlay_get_shinfo_ptr(void); | ||
|
|
||
| int xen_sync_long_mode(void); | ||
| int xen_set_long_mode(bool long_mode); | ||
| bool xen_is_long_mode(void); | ||
|
|
||
| void xen_overlay_do_map_page(MemoryRegion *page, uint64_t gpa); | ||
|
|
||
| #endif /* QEMU_XEN_OVERLAY_H */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| /* | ||
| * QEMU Xen emulation: Xenstore emulation | ||
| * | ||
| * Copyright © 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| * | ||
| * Authors: David Woodhouse <dwmw2@infradead.org> | ||
| * | ||
| * 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 QEMU_XEN_XENSTORE_H | ||
| #define QEMU_XEN_XENSTORE_H | ||
|
|
||
| void xen_xenstore_create(void); | ||
| int xen_xenstore_reset(void); | ||
|
|
||
| uint16_t xen_xenstore_get_port(void); | ||
|
|
||
| #endif /* QEMU_XEN_XENSTORE_H */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| config XEN_BUS | ||
| bool | ||
| default y if (XEN || XEN_EMU) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| /****************************************************************************** | ||
| * arch-x86/cpuid.h | ||
| * | ||
| * CPUID interface to Xen. | ||
| * | ||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| * of this software and associated documentation files (the "Software"), to | ||
| * deal in the Software without restriction, including without limitation the | ||
| * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| * sell copies of the Software, and to permit persons to whom the Software is | ||
| * furnished to do so, subject to the following conditions: | ||
| * | ||
| * The above copyright notice and this permission notice shall be included in | ||
| * all copies or substantial portions of the Software. | ||
| * | ||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| * DEALINGS IN THE SOFTWARE. | ||
| * | ||
| * Copyright (c) 2007 Citrix Systems, Inc. | ||
| * | ||
| * Authors: | ||
| * Keir Fraser <keir@xen.org> | ||
| */ | ||
|
|
||
| #ifndef __XEN_PUBLIC_ARCH_X86_CPUID_H__ | ||
| #define __XEN_PUBLIC_ARCH_X86_CPUID_H__ | ||
|
|
||
| /* | ||
| * For compatibility with other hypervisor interfaces, the Xen cpuid leaves | ||
| * can be found at the first otherwise unused 0x100 aligned boundary starting | ||
| * from 0x40000000. | ||
| * | ||
| * e.g If viridian extensions are enabled for an HVM domain, the Xen cpuid | ||
| * leaves will start at 0x40000100 | ||
| */ | ||
|
|
||
| #define XEN_CPUID_FIRST_LEAF 0x40000000 | ||
| #define XEN_CPUID_LEAF(i) (XEN_CPUID_FIRST_LEAF + (i)) | ||
|
|
||
| /* | ||
| * Leaf 1 (0x40000x00) | ||
| * EAX: Largest Xen-information leaf. All leaves up to an including @EAX | ||
| * are supported by the Xen host. | ||
| * EBX-EDX: "XenVMMXenVMM" signature, allowing positive identification | ||
| * of a Xen host. | ||
| */ | ||
| #define XEN_CPUID_SIGNATURE_EBX 0x566e6558 /* "XenV" */ | ||
| #define XEN_CPUID_SIGNATURE_ECX 0x65584d4d /* "MMXe" */ | ||
| #define XEN_CPUID_SIGNATURE_EDX 0x4d4d566e /* "nVMM" */ | ||
|
|
||
| /* | ||
| * Leaf 2 (0x40000x01) | ||
| * EAX[31:16]: Xen major version. | ||
| * EAX[15: 0]: Xen minor version. | ||
| * EBX-EDX: Reserved (currently all zeroes). | ||
| */ | ||
|
|
||
| /* | ||
| * Leaf 3 (0x40000x02) | ||
| * EAX: Number of hypercall transfer pages. This register is always guaranteed | ||
| * to specify one hypercall page. | ||
| * EBX: Base address of Xen-specific MSRs. | ||
| * ECX: Features 1. Unused bits are set to zero. | ||
| * EDX: Features 2. Unused bits are set to zero. | ||
| */ | ||
|
|
||
| /* Does the host support MMU_PT_UPDATE_PRESERVE_AD for this guest? */ | ||
| #define _XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD 0 | ||
| #define XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD (1u<<0) | ||
|
|
||
| /* | ||
| * Leaf 4 (0x40000x03) | ||
| * Sub-leaf 0: EAX: bit 0: emulated tsc | ||
| * bit 1: host tsc is known to be reliable | ||
| * bit 2: RDTSCP instruction available | ||
| * EBX: tsc_mode: 0=default (emulate if necessary), 1=emulate, | ||
| * 2=no emulation, 3=no emulation + TSC_AUX support | ||
| * ECX: guest tsc frequency in kHz | ||
| * EDX: guest tsc incarnation (migration count) | ||
| * Sub-leaf 1: EAX: tsc offset low part | ||
| * EBX: tsc offset high part | ||
| * ECX: multiplicator for tsc->ns conversion | ||
| * EDX: shift amount for tsc->ns conversion | ||
| * Sub-leaf 2: EAX: host tsc frequency in kHz | ||
| */ | ||
|
|
||
| /* | ||
| * Leaf 5 (0x40000x04) | ||
| * HVM-specific features | ||
| * Sub-leaf 0: EAX: Features | ||
| * Sub-leaf 0: EBX: vcpu id (iff EAX has XEN_HVM_CPUID_VCPU_ID_PRESENT flag) | ||
| * Sub-leaf 0: ECX: domain id (iff EAX has XEN_HVM_CPUID_DOMID_PRESENT flag) | ||
| */ | ||
| #define XEN_HVM_CPUID_APIC_ACCESS_VIRT (1u << 0) /* Virtualized APIC registers */ | ||
| #define XEN_HVM_CPUID_X2APIC_VIRT (1u << 1) /* Virtualized x2APIC accesses */ | ||
| /* Memory mapped from other domains has valid IOMMU entries */ | ||
| #define XEN_HVM_CPUID_IOMMU_MAPPINGS (1u << 2) | ||
| #define XEN_HVM_CPUID_VCPU_ID_PRESENT (1u << 3) /* vcpu id is present in EBX */ | ||
| #define XEN_HVM_CPUID_DOMID_PRESENT (1u << 4) /* domid is present in ECX */ | ||
|
|
||
| /* | ||
| * Leaf 6 (0x40000x05) | ||
| * PV-specific parameters | ||
| * Sub-leaf 0: EAX: max available sub-leaf | ||
| * Sub-leaf 0: EBX: bits 0-7: max machine address width | ||
| */ | ||
|
|
||
| /* Max. address width in bits taking memory hotplug into account. */ | ||
| #define XEN_CPUID_MACHINE_ADDRESS_WIDTH_MASK (0xffu << 0) | ||
|
|
||
| #define XEN_CPUID_MAX_NUM_LEAVES 5 | ||
|
|
||
| #endif /* __XEN_PUBLIC_ARCH_X86_CPUID_H__ */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,194 @@ | ||
| /****************************************************************************** | ||
| * xen-x86_32.h | ||
| * | ||
| * Guest OS interface to x86 32-bit Xen. | ||
| * | ||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| * of this software and associated documentation files (the "Software"), to | ||
| * deal in the Software without restriction, including without limitation the | ||
| * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| * sell copies of the Software, and to permit persons to whom the Software is | ||
| * furnished to do so, subject to the following conditions: | ||
| * | ||
| * The above copyright notice and this permission notice shall be included in | ||
| * all copies or substantial portions of the Software. | ||
| * | ||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| * DEALINGS IN THE SOFTWARE. | ||
| * | ||
| * Copyright (c) 2004-2007, K A Fraser | ||
| */ | ||
|
|
||
| #ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__ | ||
| #define __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__ | ||
|
|
||
| /* | ||
| * Hypercall interface: | ||
| * Input: %ebx, %ecx, %edx, %esi, %edi, %ebp (arguments 1-6) | ||
| * Output: %eax | ||
| * Access is via hypercall page (set up by guest loader or via a Xen MSR): | ||
| * call hypercall_page + hypercall-number * 32 | ||
| * Clobbered: Argument registers (e.g., 2-arg hypercall clobbers %ebx,%ecx) | ||
| */ | ||
|
|
||
| /* | ||
| * These flat segments are in the Xen-private section of every GDT. Since these | ||
| * are also present in the initial GDT, many OSes will be able to avoid | ||
| * installing their own GDT. | ||
| */ | ||
| #define FLAT_RING1_CS 0xe019 /* GDT index 259 */ | ||
| #define FLAT_RING1_DS 0xe021 /* GDT index 260 */ | ||
| #define FLAT_RING1_SS 0xe021 /* GDT index 260 */ | ||
| #define FLAT_RING3_CS 0xe02b /* GDT index 261 */ | ||
| #define FLAT_RING3_DS 0xe033 /* GDT index 262 */ | ||
| #define FLAT_RING3_SS 0xe033 /* GDT index 262 */ | ||
|
|
||
| #define FLAT_KERNEL_CS FLAT_RING1_CS | ||
| #define FLAT_KERNEL_DS FLAT_RING1_DS | ||
| #define FLAT_KERNEL_SS FLAT_RING1_SS | ||
| #define FLAT_USER_CS FLAT_RING3_CS | ||
| #define FLAT_USER_DS FLAT_RING3_DS | ||
| #define FLAT_USER_SS FLAT_RING3_SS | ||
|
|
||
| #define __HYPERVISOR_VIRT_START_PAE 0xF5800000 | ||
| #define __MACH2PHYS_VIRT_START_PAE 0xF5800000 | ||
| #define __MACH2PHYS_VIRT_END_PAE 0xF6800000 | ||
| #define HYPERVISOR_VIRT_START_PAE xen_mk_ulong(__HYPERVISOR_VIRT_START_PAE) | ||
| #define MACH2PHYS_VIRT_START_PAE xen_mk_ulong(__MACH2PHYS_VIRT_START_PAE) | ||
| #define MACH2PHYS_VIRT_END_PAE xen_mk_ulong(__MACH2PHYS_VIRT_END_PAE) | ||
|
|
||
| /* Non-PAE bounds are obsolete. */ | ||
| #define __HYPERVISOR_VIRT_START_NONPAE 0xFC000000 | ||
| #define __MACH2PHYS_VIRT_START_NONPAE 0xFC000000 | ||
| #define __MACH2PHYS_VIRT_END_NONPAE 0xFC400000 | ||
| #define HYPERVISOR_VIRT_START_NONPAE \ | ||
| xen_mk_ulong(__HYPERVISOR_VIRT_START_NONPAE) | ||
| #define MACH2PHYS_VIRT_START_NONPAE \ | ||
| xen_mk_ulong(__MACH2PHYS_VIRT_START_NONPAE) | ||
| #define MACH2PHYS_VIRT_END_NONPAE \ | ||
| xen_mk_ulong(__MACH2PHYS_VIRT_END_NONPAE) | ||
|
|
||
| #define __HYPERVISOR_VIRT_START __HYPERVISOR_VIRT_START_PAE | ||
| #define __MACH2PHYS_VIRT_START __MACH2PHYS_VIRT_START_PAE | ||
| #define __MACH2PHYS_VIRT_END __MACH2PHYS_VIRT_END_PAE | ||
|
|
||
| #ifndef HYPERVISOR_VIRT_START | ||
| #define HYPERVISOR_VIRT_START xen_mk_ulong(__HYPERVISOR_VIRT_START) | ||
| #endif | ||
|
|
||
| #define MACH2PHYS_VIRT_START xen_mk_ulong(__MACH2PHYS_VIRT_START) | ||
| #define MACH2PHYS_VIRT_END xen_mk_ulong(__MACH2PHYS_VIRT_END) | ||
| #define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>2) | ||
| #ifndef machine_to_phys_mapping | ||
| #define machine_to_phys_mapping ((unsigned long *)MACH2PHYS_VIRT_START) | ||
| #endif | ||
|
|
||
| /* 32-/64-bit invariability for control interfaces (domctl/sysctl). */ | ||
| #if defined(__XEN__) || defined(__XEN_TOOLS__) | ||
| #undef ___DEFINE_XEN_GUEST_HANDLE | ||
| #define ___DEFINE_XEN_GUEST_HANDLE(name, type) \ | ||
| typedef struct { type *p; } \ | ||
| __guest_handle_ ## name; \ | ||
| typedef struct { union { type *p; uint64_aligned_t q; }; } \ | ||
| __guest_handle_64_ ## name | ||
| #undef set_xen_guest_handle_raw | ||
| #define set_xen_guest_handle_raw(hnd, val) \ | ||
| do { if ( sizeof(hnd) == 8 ) *(uint64_t *)&(hnd) = 0; \ | ||
| (hnd).p = val; \ | ||
| } while ( 0 ) | ||
| #define int64_aligned_t int64_t __attribute__((aligned(8))) | ||
| #define uint64_aligned_t uint64_t __attribute__((aligned(8))) | ||
| #define __XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name | ||
| #define XEN_GUEST_HANDLE_64(name) __XEN_GUEST_HANDLE_64(name) | ||
| #endif | ||
|
|
||
| #ifndef __ASSEMBLY__ | ||
|
|
||
| #if defined(XEN_GENERATING_COMPAT_HEADERS) | ||
| /* nothing */ | ||
| #elif defined(__XEN__) || defined(__XEN_TOOLS__) | ||
| /* Anonymous unions include all permissible names (e.g., al/ah/ax/eax). */ | ||
| #define __DECL_REG_LO8(which) union { \ | ||
| uint32_t e ## which ## x; \ | ||
| uint16_t which ## x; \ | ||
| struct { \ | ||
| uint8_t which ## l; \ | ||
| uint8_t which ## h; \ | ||
| }; \ | ||
| } | ||
| #define __DECL_REG_LO16(name) union { \ | ||
| uint32_t e ## name, _e ## name; \ | ||
| uint16_t name; \ | ||
| } | ||
| #else | ||
| /* Other sources must always use the proper 32-bit name (e.g., eax). */ | ||
| #define __DECL_REG_LO8(which) uint32_t e ## which ## x | ||
| #define __DECL_REG_LO16(name) uint32_t e ## name | ||
| #endif | ||
|
|
||
| struct cpu_user_regs { | ||
| __DECL_REG_LO8(b); | ||
| __DECL_REG_LO8(c); | ||
| __DECL_REG_LO8(d); | ||
| __DECL_REG_LO16(si); | ||
| __DECL_REG_LO16(di); | ||
| __DECL_REG_LO16(bp); | ||
| __DECL_REG_LO8(a); | ||
| uint16_t error_code; /* private */ | ||
| uint16_t entry_vector; /* private */ | ||
| __DECL_REG_LO16(ip); | ||
| uint16_t cs; | ||
| uint8_t saved_upcall_mask; | ||
| uint8_t _pad0; | ||
| __DECL_REG_LO16(flags); /* eflags.IF == !saved_upcall_mask */ | ||
| __DECL_REG_LO16(sp); | ||
| uint16_t ss, _pad1; | ||
| uint16_t es, _pad2; | ||
| uint16_t ds, _pad3; | ||
| uint16_t fs, _pad4; | ||
| uint16_t gs, _pad5; | ||
| }; | ||
| typedef struct cpu_user_regs cpu_user_regs_t; | ||
| DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t); | ||
|
|
||
| #undef __DECL_REG_LO8 | ||
| #undef __DECL_REG_LO16 | ||
|
|
||
| /* | ||
| * Page-directory addresses above 4GB do not fit into architectural %cr3. | ||
| * When accessing %cr3, or equivalent field in vcpu_guest_context, guests | ||
| * must use the following accessor macros to pack/unpack valid MFNs. | ||
| */ | ||
| #define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20)) | ||
| #define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20)) | ||
|
|
||
| struct arch_vcpu_info { | ||
| unsigned long cr2; | ||
| unsigned long pad[5]; /* sizeof(vcpu_info_t) == 64 */ | ||
| }; | ||
| typedef struct arch_vcpu_info arch_vcpu_info_t; | ||
|
|
||
| struct xen_callback { | ||
| unsigned long cs; | ||
| unsigned long eip; | ||
| }; | ||
| typedef struct xen_callback xen_callback_t; | ||
|
|
||
| #endif /* !__ASSEMBLY__ */ | ||
|
|
||
| #endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__ */ | ||
|
|
||
| /* | ||
| * Local variables: | ||
| * mode: C | ||
| * c-file-style: "BSD" | ||
| * c-basic-offset: 4 | ||
| * tab-width: 4 | ||
| * indent-tabs-mode: nil | ||
| * End: | ||
| */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,241 @@ | ||
| /****************************************************************************** | ||
| * xen-x86_64.h | ||
| * | ||
| * Guest OS interface to x86 64-bit Xen. | ||
| * | ||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| * of this software and associated documentation files (the "Software"), to | ||
| * deal in the Software without restriction, including without limitation the | ||
| * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| * sell copies of the Software, and to permit persons to whom the Software is | ||
| * furnished to do so, subject to the following conditions: | ||
| * | ||
| * The above copyright notice and this permission notice shall be included in | ||
| * all copies or substantial portions of the Software. | ||
| * | ||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| * DEALINGS IN THE SOFTWARE. | ||
| * | ||
| * Copyright (c) 2004-2006, K A Fraser | ||
| */ | ||
|
|
||
| #ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ | ||
| #define __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ | ||
|
|
||
| /* | ||
| * Hypercall interface: | ||
| * Input: %rdi, %rsi, %rdx, %r10, %r8, %r9 (arguments 1-6) | ||
| * Output: %rax | ||
| * Access is via hypercall page (set up by guest loader or via a Xen MSR): | ||
| * call hypercall_page + hypercall-number * 32 | ||
| * Clobbered: argument registers (e.g., 2-arg hypercall clobbers %rdi,%rsi) | ||
| */ | ||
|
|
||
| /* | ||
| * 64-bit segment selectors | ||
| * These flat segments are in the Xen-private section of every GDT. Since these | ||
| * are also present in the initial GDT, many OSes will be able to avoid | ||
| * installing their own GDT. | ||
| */ | ||
|
|
||
| #define FLAT_RING3_CS32 0xe023 /* GDT index 260 */ | ||
| #define FLAT_RING3_CS64 0xe033 /* GDT index 262 */ | ||
| #define FLAT_RING3_DS32 0xe02b /* GDT index 261 */ | ||
| #define FLAT_RING3_DS64 0x0000 /* NULL selector */ | ||
| #define FLAT_RING3_SS32 0xe02b /* GDT index 261 */ | ||
| #define FLAT_RING3_SS64 0xe02b /* GDT index 261 */ | ||
|
|
||
| #define FLAT_KERNEL_DS64 FLAT_RING3_DS64 | ||
| #define FLAT_KERNEL_DS32 FLAT_RING3_DS32 | ||
| #define FLAT_KERNEL_DS FLAT_KERNEL_DS64 | ||
| #define FLAT_KERNEL_CS64 FLAT_RING3_CS64 | ||
| #define FLAT_KERNEL_CS32 FLAT_RING3_CS32 | ||
| #define FLAT_KERNEL_CS FLAT_KERNEL_CS64 | ||
| #define FLAT_KERNEL_SS64 FLAT_RING3_SS64 | ||
| #define FLAT_KERNEL_SS32 FLAT_RING3_SS32 | ||
| #define FLAT_KERNEL_SS FLAT_KERNEL_SS64 | ||
|
|
||
| #define FLAT_USER_DS64 FLAT_RING3_DS64 | ||
| #define FLAT_USER_DS32 FLAT_RING3_DS32 | ||
| #define FLAT_USER_DS FLAT_USER_DS64 | ||
| #define FLAT_USER_CS64 FLAT_RING3_CS64 | ||
| #define FLAT_USER_CS32 FLAT_RING3_CS32 | ||
| #define FLAT_USER_CS FLAT_USER_CS64 | ||
| #define FLAT_USER_SS64 FLAT_RING3_SS64 | ||
| #define FLAT_USER_SS32 FLAT_RING3_SS32 | ||
| #define FLAT_USER_SS FLAT_USER_SS64 | ||
|
|
||
| #define __HYPERVISOR_VIRT_START 0xFFFF800000000000 | ||
| #define __HYPERVISOR_VIRT_END 0xFFFF880000000000 | ||
| #define __MACH2PHYS_VIRT_START 0xFFFF800000000000 | ||
| #define __MACH2PHYS_VIRT_END 0xFFFF804000000000 | ||
|
|
||
| #ifndef HYPERVISOR_VIRT_START | ||
| #define HYPERVISOR_VIRT_START xen_mk_ulong(__HYPERVISOR_VIRT_START) | ||
| #define HYPERVISOR_VIRT_END xen_mk_ulong(__HYPERVISOR_VIRT_END) | ||
| #endif | ||
|
|
||
| #define MACH2PHYS_VIRT_START xen_mk_ulong(__MACH2PHYS_VIRT_START) | ||
| #define MACH2PHYS_VIRT_END xen_mk_ulong(__MACH2PHYS_VIRT_END) | ||
| #define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>3) | ||
| #ifndef machine_to_phys_mapping | ||
| #define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START) | ||
| #endif | ||
|
|
||
| /* | ||
| * int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base) | ||
| * @which == SEGBASE_* ; @base == 64-bit base address | ||
| * Returns 0 on success. | ||
| */ | ||
| #define SEGBASE_FS 0 | ||
| #define SEGBASE_GS_USER 1 | ||
| #define SEGBASE_GS_KERNEL 2 | ||
| #define SEGBASE_GS_USER_SEL 3 /* Set user %gs specified in base[15:0] */ | ||
|
|
||
| /* | ||
| * int HYPERVISOR_iret(void) | ||
| * All arguments are on the kernel stack, in the following format. | ||
| * Never returns if successful. Current kernel context is lost. | ||
| * The saved CS is mapped as follows: | ||
| * RING0 -> RING3 kernel mode. | ||
| * RING1 -> RING3 kernel mode. | ||
| * RING2 -> RING3 kernel mode. | ||
| * RING3 -> RING3 user mode. | ||
| * However RING0 indicates that the guest kernel should return to iteself | ||
| * directly with | ||
| * orb $3,1*8(%rsp) | ||
| * iretq | ||
| * If flags contains VGCF_in_syscall: | ||
| * Restore RAX, RIP, RFLAGS, RSP. | ||
| * Discard R11, RCX, CS, SS. | ||
| * Otherwise: | ||
| * Restore RAX, R11, RCX, CS:RIP, RFLAGS, SS:RSP. | ||
| * All other registers are saved on hypercall entry and restored to user. | ||
| */ | ||
| /* Guest exited in SYSCALL context? Return to guest with SYSRET? */ | ||
| #define _VGCF_in_syscall 8 | ||
| #define VGCF_in_syscall (1<<_VGCF_in_syscall) | ||
| #define VGCF_IN_SYSCALL VGCF_in_syscall | ||
|
|
||
| #ifndef __ASSEMBLY__ | ||
|
|
||
| struct iret_context { | ||
| /* Top of stack (%rsp at point of hypercall). */ | ||
| uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss; | ||
| /* Bottom of iret stack frame. */ | ||
| }; | ||
|
|
||
| #if defined(__XEN__) || defined(__XEN_TOOLS__) | ||
| /* Anonymous unions include all permissible names (e.g., al/ah/ax/eax/rax). */ | ||
| #define __DECL_REG_LOHI(which) union { \ | ||
| uint64_t r ## which ## x; \ | ||
| uint32_t e ## which ## x; \ | ||
| uint16_t which ## x; \ | ||
| struct { \ | ||
| uint8_t which ## l; \ | ||
| uint8_t which ## h; \ | ||
| }; \ | ||
| } | ||
| #define __DECL_REG_LO8(name) union { \ | ||
| uint64_t r ## name; \ | ||
| uint32_t e ## name; \ | ||
| uint16_t name; \ | ||
| uint8_t name ## l; \ | ||
| } | ||
| #define __DECL_REG_LO16(name) union { \ | ||
| uint64_t r ## name; \ | ||
| uint32_t e ## name; \ | ||
| uint16_t name; \ | ||
| } | ||
| #define __DECL_REG_HI(num) union { \ | ||
| uint64_t r ## num; \ | ||
| uint32_t r ## num ## d; \ | ||
| uint16_t r ## num ## w; \ | ||
| uint8_t r ## num ## b; \ | ||
| } | ||
| #elif defined(__GNUC__) && !defined(__STRICT_ANSI__) | ||
| /* Anonymous union includes both 32- and 64-bit names (e.g., eax/rax). */ | ||
| #define __DECL_REG(name) union { \ | ||
| uint64_t r ## name, e ## name; \ | ||
| uint32_t _e ## name; \ | ||
| } | ||
| #else | ||
| /* Non-gcc sources must always use the proper 64-bit name (e.g., rax). */ | ||
| #define __DECL_REG(name) uint64_t r ## name | ||
| #endif | ||
|
|
||
| #ifndef __DECL_REG_LOHI | ||
| #define __DECL_REG_LOHI(name) __DECL_REG(name ## x) | ||
| #define __DECL_REG_LO8 __DECL_REG | ||
| #define __DECL_REG_LO16 __DECL_REG | ||
| #define __DECL_REG_HI(num) uint64_t r ## num | ||
| #endif | ||
|
|
||
| struct cpu_user_regs { | ||
| __DECL_REG_HI(15); | ||
| __DECL_REG_HI(14); | ||
| __DECL_REG_HI(13); | ||
| __DECL_REG_HI(12); | ||
| __DECL_REG_LO8(bp); | ||
| __DECL_REG_LOHI(b); | ||
| __DECL_REG_HI(11); | ||
| __DECL_REG_HI(10); | ||
| __DECL_REG_HI(9); | ||
| __DECL_REG_HI(8); | ||
| __DECL_REG_LOHI(a); | ||
| __DECL_REG_LOHI(c); | ||
| __DECL_REG_LOHI(d); | ||
| __DECL_REG_LO8(si); | ||
| __DECL_REG_LO8(di); | ||
| uint32_t error_code; /* private */ | ||
| uint32_t entry_vector; /* private */ | ||
| __DECL_REG_LO16(ip); | ||
| uint16_t cs, _pad0[1]; | ||
| uint8_t saved_upcall_mask; | ||
| uint8_t _pad1[3]; | ||
| __DECL_REG_LO16(flags); /* rflags.IF == !saved_upcall_mask */ | ||
| __DECL_REG_LO8(sp); | ||
| uint16_t ss, _pad2[3]; | ||
| uint16_t es, _pad3[3]; | ||
| uint16_t ds, _pad4[3]; | ||
| uint16_t fs, _pad5[3]; | ||
| uint16_t gs, _pad6[3]; | ||
| }; | ||
| typedef struct cpu_user_regs cpu_user_regs_t; | ||
| DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t); | ||
|
|
||
| #undef __DECL_REG | ||
| #undef __DECL_REG_LOHI | ||
| #undef __DECL_REG_LO8 | ||
| #undef __DECL_REG_LO16 | ||
| #undef __DECL_REG_HI | ||
|
|
||
| #define xen_pfn_to_cr3(pfn) ((unsigned long)(pfn) << 12) | ||
| #define xen_cr3_to_pfn(cr3) ((unsigned long)(cr3) >> 12) | ||
|
|
||
| struct arch_vcpu_info { | ||
| unsigned long cr2; | ||
| unsigned long pad; /* sizeof(vcpu_info_t) == 64 */ | ||
| }; | ||
| typedef struct arch_vcpu_info arch_vcpu_info_t; | ||
|
|
||
| typedef unsigned long xen_callback_t; | ||
|
|
||
| #endif /* !__ASSEMBLY__ */ | ||
|
|
||
| #endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ */ | ||
|
|
||
| /* | ||
| * Local variables: | ||
| * mode: C | ||
| * c-file-style: "BSD" | ||
| * c-basic-offset: 4 | ||
| * tab-width: 4 | ||
| * indent-tabs-mode: nil | ||
| * End: | ||
| */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,398 @@ | ||
| /****************************************************************************** | ||
| * arch-x86/xen.h | ||
| * | ||
| * Guest OS interface to x86 Xen. | ||
| * | ||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| * of this software and associated documentation files (the "Software"), to | ||
| * deal in the Software without restriction, including without limitation the | ||
| * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| * sell copies of the Software, and to permit persons to whom the Software is | ||
| * furnished to do so, subject to the following conditions: | ||
| * | ||
| * The above copyright notice and this permission notice shall be included in | ||
| * all copies or substantial portions of the Software. | ||
| * | ||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| * DEALINGS IN THE SOFTWARE. | ||
| * | ||
| * Copyright (c) 2004-2006, K A Fraser | ||
| */ | ||
|
|
||
| #include "../xen.h" | ||
|
|
||
| #ifndef __XEN_PUBLIC_ARCH_X86_XEN_H__ | ||
| #define __XEN_PUBLIC_ARCH_X86_XEN_H__ | ||
|
|
||
| /* Structural guest handles introduced in 0x00030201. */ | ||
| #if __XEN_INTERFACE_VERSION__ >= 0x00030201 | ||
| #define ___DEFINE_XEN_GUEST_HANDLE(name, type) \ | ||
| typedef struct { type *p; } __guest_handle_ ## name | ||
| #else | ||
| #define ___DEFINE_XEN_GUEST_HANDLE(name, type) \ | ||
| typedef type * __guest_handle_ ## name | ||
| #endif | ||
|
|
||
| /* | ||
| * XEN_GUEST_HANDLE represents a guest pointer, when passed as a field | ||
| * in a struct in memory. | ||
| * XEN_GUEST_HANDLE_PARAM represent a guest pointer, when passed as an | ||
| * hypercall argument. | ||
| * XEN_GUEST_HANDLE_PARAM and XEN_GUEST_HANDLE are the same on X86 but | ||
| * they might not be on other architectures. | ||
| */ | ||
| #define __DEFINE_XEN_GUEST_HANDLE(name, type) \ | ||
| ___DEFINE_XEN_GUEST_HANDLE(name, type); \ | ||
| ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type) | ||
| #define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name) | ||
| #define __XEN_GUEST_HANDLE(name) __guest_handle_ ## name | ||
| #define XEN_GUEST_HANDLE(name) __XEN_GUEST_HANDLE(name) | ||
| #define XEN_GUEST_HANDLE_PARAM(name) XEN_GUEST_HANDLE(name) | ||
| #define set_xen_guest_handle_raw(hnd, val) do { (hnd).p = val; } while (0) | ||
| #define set_xen_guest_handle(hnd, val) set_xen_guest_handle_raw(hnd, val) | ||
|
|
||
| #if defined(__i386__) | ||
| # ifdef __XEN__ | ||
| __DeFiNe__ __DECL_REG_LO8(which) uint32_t e ## which ## x | ||
| __DeFiNe__ __DECL_REG_LO16(name) union { uint32_t e ## name; } | ||
| # endif | ||
| #include "xen-x86_32.h" | ||
| # ifdef __XEN__ | ||
| __UnDeF__ __DECL_REG_LO8 | ||
| __UnDeF__ __DECL_REG_LO16 | ||
| __DeFiNe__ __DECL_REG_LO8(which) e ## which ## x | ||
| __DeFiNe__ __DECL_REG_LO16(name) e ## name | ||
| # endif | ||
| #elif defined(__x86_64__) | ||
| #include "xen-x86_64.h" | ||
| #endif | ||
|
|
||
| #ifndef __ASSEMBLY__ | ||
| typedef unsigned long xen_pfn_t; | ||
| #define PRI_xen_pfn "lx" | ||
| #define PRIu_xen_pfn "lu" | ||
| #endif | ||
|
|
||
| #define XEN_HAVE_PV_GUEST_ENTRY 1 | ||
|
|
||
| #define XEN_HAVE_PV_UPCALL_MASK 1 | ||
|
|
||
| /* | ||
| * `incontents 200 segdesc Segment Descriptor Tables | ||
| */ | ||
| /* | ||
| * ` enum neg_errnoval | ||
| * ` HYPERVISOR_set_gdt(const xen_pfn_t frames[], unsigned int entries); | ||
| * ` | ||
| */ | ||
| /* | ||
| * A number of GDT entries are reserved by Xen. These are not situated at the | ||
| * start of the GDT because some stupid OSes export hard-coded selector values | ||
| * in their ABI. These hard-coded values are always near the start of the GDT, | ||
| * so Xen places itself out of the way, at the far end of the GDT. | ||
| * | ||
| * NB The LDT is set using the MMUEXT_SET_LDT op of HYPERVISOR_mmuext_op | ||
| */ | ||
| #define FIRST_RESERVED_GDT_PAGE 14 | ||
| #define FIRST_RESERVED_GDT_BYTE (FIRST_RESERVED_GDT_PAGE * 4096) | ||
| #define FIRST_RESERVED_GDT_ENTRY (FIRST_RESERVED_GDT_BYTE / 8) | ||
|
|
||
|
|
||
| /* | ||
| * ` enum neg_errnoval | ||
| * ` HYPERVISOR_update_descriptor(u64 pa, u64 desc); | ||
| * ` | ||
| * ` @pa The machine physical address of the descriptor to | ||
| * ` update. Must be either a descriptor page or writable. | ||
| * ` @desc The descriptor value to update, in the same format as a | ||
| * ` native descriptor table entry. | ||
| */ | ||
|
|
||
| /* Maximum number of virtual CPUs in legacy multi-processor guests. */ | ||
| #define XEN_LEGACY_MAX_VCPUS 32 | ||
|
|
||
| #ifndef __ASSEMBLY__ | ||
|
|
||
| typedef unsigned long xen_ulong_t; | ||
| #define PRI_xen_ulong "lx" | ||
|
|
||
| /* | ||
| * ` enum neg_errnoval | ||
| * ` HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp); | ||
| * ` | ||
| * Sets the stack segment and pointer for the current vcpu. | ||
| */ | ||
|
|
||
| /* | ||
| * ` enum neg_errnoval | ||
| * ` HYPERVISOR_set_trap_table(const struct trap_info traps[]); | ||
| * ` | ||
| */ | ||
| /* | ||
| * Send an array of these to HYPERVISOR_set_trap_table(). | ||
| * Terminate the array with a sentinel entry, with traps[].address==0. | ||
| * The privilege level specifies which modes may enter a trap via a software | ||
| * interrupt. On x86/64, since rings 1 and 2 are unavailable, we allocate | ||
| * privilege levels as follows: | ||
| * Level == 0: Noone may enter | ||
| * Level == 1: Kernel may enter | ||
| * Level == 2: Kernel may enter | ||
| * Level == 3: Everyone may enter | ||
| * | ||
| * Note: For compatibility with kernels not setting up exception handlers | ||
| * early enough, Xen will avoid trying to inject #GP (and hence crash | ||
| * the domain) when an RDMSR would require this, but no handler was | ||
| * set yet. The precise conditions are implementation specific, and | ||
| * new code may not rely on such behavior anyway. | ||
| */ | ||
| #define TI_GET_DPL(_ti) ((_ti)->flags & 3) | ||
| #define TI_GET_IF(_ti) ((_ti)->flags & 4) | ||
| #define TI_SET_DPL(_ti,_dpl) ((_ti)->flags |= (_dpl)) | ||
| #define TI_SET_IF(_ti,_if) ((_ti)->flags |= ((!!(_if))<<2)) | ||
| struct trap_info { | ||
| uint8_t vector; /* exception vector */ | ||
| uint8_t flags; /* 0-3: privilege level; 4: clear event enable? */ | ||
| uint16_t cs; /* code selector */ | ||
| unsigned long address; /* code offset */ | ||
| }; | ||
| typedef struct trap_info trap_info_t; | ||
| DEFINE_XEN_GUEST_HANDLE(trap_info_t); | ||
|
|
||
| typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */ | ||
|
|
||
| /* | ||
| * The following is all CPU context. Note that the fpu_ctxt block is filled | ||
| * in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used. | ||
| * | ||
| * Also note that when calling DOMCTL_setvcpucontext for HVM guests, not all | ||
| * information in this structure is updated, the fields read include: fpu_ctxt | ||
| * (if VGCT_I387_VALID is set), flags, user_regs and debugreg[*]. | ||
| * | ||
| * Note: VCPUOP_initialise for HVM guests is non-symetric with | ||
| * DOMCTL_setvcpucontext, and uses struct vcpu_hvm_context from hvm/hvm_vcpu.h | ||
| */ | ||
| struct vcpu_guest_context { | ||
| /* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */ | ||
| struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */ | ||
| #define VGCF_I387_VALID (1<<0) | ||
| #define VGCF_IN_KERNEL (1<<2) | ||
| #define _VGCF_i387_valid 0 | ||
| #define VGCF_i387_valid (1<<_VGCF_i387_valid) | ||
| #define _VGCF_in_kernel 2 | ||
| #define VGCF_in_kernel (1<<_VGCF_in_kernel) | ||
| #define _VGCF_failsafe_disables_events 3 | ||
| #define VGCF_failsafe_disables_events (1<<_VGCF_failsafe_disables_events) | ||
| #define _VGCF_syscall_disables_events 4 | ||
| #define VGCF_syscall_disables_events (1<<_VGCF_syscall_disables_events) | ||
| #define _VGCF_online 5 | ||
| #define VGCF_online (1<<_VGCF_online) | ||
| unsigned long flags; /* VGCF_* flags */ | ||
| struct cpu_user_regs user_regs; /* User-level CPU registers */ | ||
| struct trap_info trap_ctxt[256]; /* Virtual IDT */ | ||
| unsigned long ldt_base, ldt_ents; /* LDT (linear address, # ents) */ | ||
| unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */ | ||
| unsigned long kernel_ss, kernel_sp; /* Virtual TSS (only SS1/SP1) */ | ||
| /* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */ | ||
| unsigned long ctrlreg[8]; /* CR0-CR7 (control registers) */ | ||
| unsigned long debugreg[8]; /* DB0-DB7 (debug registers) */ | ||
| #ifdef __i386__ | ||
| unsigned long event_callback_cs; /* CS:EIP of event callback */ | ||
| unsigned long event_callback_eip; | ||
| unsigned long failsafe_callback_cs; /* CS:EIP of failsafe callback */ | ||
| unsigned long failsafe_callback_eip; | ||
| #else | ||
| unsigned long event_callback_eip; | ||
| unsigned long failsafe_callback_eip; | ||
| #ifdef __XEN__ | ||
| union { | ||
| unsigned long syscall_callback_eip; | ||
| struct { | ||
| unsigned int event_callback_cs; /* compat CS of event cb */ | ||
| unsigned int failsafe_callback_cs; /* compat CS of failsafe cb */ | ||
| }; | ||
| }; | ||
| #else | ||
| unsigned long syscall_callback_eip; | ||
| #endif | ||
| #endif | ||
| unsigned long vm_assist; /* VMASST_TYPE_* bitmap */ | ||
| #ifdef __x86_64__ | ||
| /* Segment base addresses. */ | ||
| uint64_t fs_base; | ||
| uint64_t gs_base_kernel; | ||
| uint64_t gs_base_user; | ||
| #endif | ||
| }; | ||
| typedef struct vcpu_guest_context vcpu_guest_context_t; | ||
| DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); | ||
|
|
||
| struct arch_shared_info { | ||
| /* | ||
| * Number of valid entries in the p2m table(s) anchored at | ||
| * pfn_to_mfn_frame_list_list and/or p2m_vaddr. | ||
| */ | ||
| unsigned long max_pfn; | ||
| /* | ||
| * Frame containing list of mfns containing list of mfns containing p2m. | ||
| * A value of 0 indicates it has not yet been set up, ~0 indicates it has | ||
| * been set to invalid e.g. due to the p2m being too large for the 3-level | ||
| * p2m tree. In this case the linear mapper p2m list anchored at p2m_vaddr | ||
| * is to be used. | ||
| */ | ||
| xen_pfn_t pfn_to_mfn_frame_list_list; | ||
| unsigned long nmi_reason; | ||
| /* | ||
| * Following three fields are valid if p2m_cr3 contains a value different | ||
| * from 0. | ||
| * p2m_cr3 is the root of the address space where p2m_vaddr is valid. | ||
| * p2m_cr3 is in the same format as a cr3 value in the vcpu register state | ||
| * and holds the folded machine frame number (via xen_pfn_to_cr3) of a | ||
| * L3 or L4 page table. | ||
| * p2m_vaddr holds the virtual address of the linear p2m list. All entries | ||
| * in the range [0...max_pfn[ are accessible via this pointer. | ||
| * p2m_generation will be incremented by the guest before and after each | ||
| * change of the mappings of the p2m list. p2m_generation starts at 0 and | ||
| * a value with the least significant bit set indicates that a mapping | ||
| * update is in progress. This allows guest external software (e.g. in Dom0) | ||
| * to verify that read mappings are consistent and whether they have changed | ||
| * since the last check. | ||
| * Modifying a p2m element in the linear p2m list is allowed via an atomic | ||
| * write only. | ||
| */ | ||
| unsigned long p2m_cr3; /* cr3 value of the p2m address space */ | ||
| unsigned long p2m_vaddr; /* virtual address of the p2m list */ | ||
| unsigned long p2m_generation; /* generation count of p2m mapping */ | ||
| #ifdef __i386__ | ||
| /* There's no room for this field in the generic structure. */ | ||
| uint32_t wc_sec_hi; | ||
| #endif | ||
| }; | ||
| typedef struct arch_shared_info arch_shared_info_t; | ||
|
|
||
| #if defined(__XEN__) || defined(__XEN_TOOLS__) | ||
| /* | ||
| * struct xen_arch_domainconfig's ABI is covered by | ||
| * XEN_DOMCTL_INTERFACE_VERSION. | ||
| */ | ||
| struct xen_arch_domainconfig { | ||
| #define _XEN_X86_EMU_LAPIC 0 | ||
| #define XEN_X86_EMU_LAPIC (1U<<_XEN_X86_EMU_LAPIC) | ||
| #define _XEN_X86_EMU_HPET 1 | ||
| #define XEN_X86_EMU_HPET (1U<<_XEN_X86_EMU_HPET) | ||
| #define _XEN_X86_EMU_PM 2 | ||
| #define XEN_X86_EMU_PM (1U<<_XEN_X86_EMU_PM) | ||
| #define _XEN_X86_EMU_RTC 3 | ||
| #define XEN_X86_EMU_RTC (1U<<_XEN_X86_EMU_RTC) | ||
| #define _XEN_X86_EMU_IOAPIC 4 | ||
| #define XEN_X86_EMU_IOAPIC (1U<<_XEN_X86_EMU_IOAPIC) | ||
| #define _XEN_X86_EMU_PIC 5 | ||
| #define XEN_X86_EMU_PIC (1U<<_XEN_X86_EMU_PIC) | ||
| #define _XEN_X86_EMU_VGA 6 | ||
| #define XEN_X86_EMU_VGA (1U<<_XEN_X86_EMU_VGA) | ||
| #define _XEN_X86_EMU_IOMMU 7 | ||
| #define XEN_X86_EMU_IOMMU (1U<<_XEN_X86_EMU_IOMMU) | ||
| #define _XEN_X86_EMU_PIT 8 | ||
| #define XEN_X86_EMU_PIT (1U<<_XEN_X86_EMU_PIT) | ||
| #define _XEN_X86_EMU_USE_PIRQ 9 | ||
| #define XEN_X86_EMU_USE_PIRQ (1U<<_XEN_X86_EMU_USE_PIRQ) | ||
| #define _XEN_X86_EMU_VPCI 10 | ||
| #define XEN_X86_EMU_VPCI (1U<<_XEN_X86_EMU_VPCI) | ||
|
|
||
| #define XEN_X86_EMU_ALL (XEN_X86_EMU_LAPIC | XEN_X86_EMU_HPET | \ | ||
| XEN_X86_EMU_PM | XEN_X86_EMU_RTC | \ | ||
| XEN_X86_EMU_IOAPIC | XEN_X86_EMU_PIC | \ | ||
| XEN_X86_EMU_VGA | XEN_X86_EMU_IOMMU | \ | ||
| XEN_X86_EMU_PIT | XEN_X86_EMU_USE_PIRQ |\ | ||
| XEN_X86_EMU_VPCI) | ||
| uint32_t emulation_flags; | ||
|
|
||
| /* | ||
| * Select whether to use a relaxed behavior for accesses to MSRs not explicitly | ||
| * handled by Xen instead of injecting a #GP to the guest. Note this option | ||
| * doesn't allow the guest to read or write to the underlying MSR. | ||
| */ | ||
| #define XEN_X86_MSR_RELAXED (1u << 0) | ||
| uint32_t misc_flags; | ||
| }; | ||
|
|
||
| /* Location of online VCPU bitmap. */ | ||
| #define XEN_ACPI_CPU_MAP 0xaf00 | ||
| #define XEN_ACPI_CPU_MAP_LEN ((HVM_MAX_VCPUS + 7) / 8) | ||
|
|
||
| /* GPE0 bit set during CPU hotplug */ | ||
| #define XEN_ACPI_GPE0_CPUHP_BIT 2 | ||
| #endif | ||
|
|
||
| /* | ||
| * Representations of architectural CPUID and MSR information. Used as the | ||
| * serialised version of Xen's internal representation. | ||
| */ | ||
| typedef struct xen_cpuid_leaf { | ||
| #define XEN_CPUID_NO_SUBLEAF 0xffffffffu | ||
| uint32_t leaf, subleaf; | ||
| uint32_t a, b, c, d; | ||
| } xen_cpuid_leaf_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_cpuid_leaf_t); | ||
|
|
||
| typedef struct xen_msr_entry { | ||
| uint32_t idx; | ||
| uint32_t flags; /* Reserved MBZ. */ | ||
| uint64_t val; | ||
| } xen_msr_entry_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_msr_entry_t); | ||
|
|
||
| #endif /* !__ASSEMBLY__ */ | ||
|
|
||
| /* | ||
| * ` enum neg_errnoval | ||
| * ` HYPERVISOR_fpu_taskswitch(int set); | ||
| * ` | ||
| * Sets (if set!=0) or clears (if set==0) CR0.TS. | ||
| */ | ||
|
|
||
| /* | ||
| * ` enum neg_errnoval | ||
| * ` HYPERVISOR_set_debugreg(int regno, unsigned long value); | ||
| * | ||
| * ` unsigned long | ||
| * ` HYPERVISOR_get_debugreg(int regno); | ||
| * For 0<=reg<=7, returns the debug register value. | ||
| * For other values of reg, returns ((unsigned long)-EINVAL). | ||
| * (Unfortunately, this interface is defective.) | ||
| */ | ||
|
|
||
| /* | ||
| * Prefix forces emulation of some non-trapping instructions. | ||
| * Currently only CPUID. | ||
| */ | ||
| #ifdef __ASSEMBLY__ | ||
| #define XEN_EMULATE_PREFIX .byte 0x0f,0x0b,0x78,0x65,0x6e ; | ||
| #define XEN_CPUID XEN_EMULATE_PREFIX cpuid | ||
| #else | ||
| #define XEN_EMULATE_PREFIX ".byte 0x0f,0x0b,0x78,0x65,0x6e ; " | ||
| #define XEN_CPUID XEN_EMULATE_PREFIX "cpuid" | ||
| #endif | ||
|
|
||
| /* | ||
| * Debug console IO port, also called "port E9 hack". Each character written | ||
| * to this IO port will be printed on the hypervisor console, subject to log | ||
| * level restrictions. | ||
| */ | ||
| #define XEN_HVM_DEBUGCONS_IOPORT 0xe9 | ||
|
|
||
| #endif /* __XEN_PUBLIC_ARCH_X86_XEN_H__ */ | ||
|
|
||
| /* | ||
| * Local variables: | ||
| * mode: C | ||
| * c-file-style: "BSD" | ||
| * c-basic-offset: 4 | ||
| * tab-width: 4 | ||
| * indent-tabs-mode: nil | ||
| * End: | ||
| */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,388 @@ | ||
| /****************************************************************************** | ||
| * event_channel.h | ||
| * | ||
| * Event channels between domains. | ||
| * | ||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| * of this software and associated documentation files (the "Software"), to | ||
| * deal in the Software without restriction, including without limitation the | ||
| * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| * sell copies of the Software, and to permit persons to whom the Software is | ||
| * furnished to do so, subject to the following conditions: | ||
| * | ||
| * The above copyright notice and this permission notice shall be included in | ||
| * all copies or substantial portions of the Software. | ||
| * | ||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| * DEALINGS IN THE SOFTWARE. | ||
| * | ||
| * Copyright (c) 2003-2004, K A Fraser. | ||
| */ | ||
|
|
||
| #ifndef __XEN_PUBLIC_EVENT_CHANNEL_H__ | ||
| #define __XEN_PUBLIC_EVENT_CHANNEL_H__ | ||
|
|
||
| #include "xen.h" | ||
|
|
||
| /* | ||
| * `incontents 150 evtchn Event Channels | ||
| * | ||
| * Event channels are the basic primitive provided by Xen for event | ||
| * notifications. An event is the Xen equivalent of a hardware | ||
| * interrupt. They essentially store one bit of information, the event | ||
| * of interest is signalled by transitioning this bit from 0 to 1. | ||
| * | ||
| * Notifications are received by a guest via an upcall from Xen, | ||
| * indicating when an event arrives (setting the bit). Further | ||
| * notifications are masked until the bit is cleared again (therefore, | ||
| * guests must check the value of the bit after re-enabling event | ||
| * delivery to ensure no missed notifications). | ||
| * | ||
| * Event notifications can be masked by setting a flag; this is | ||
| * equivalent to disabling interrupts and can be used to ensure | ||
| * atomicity of certain operations in the guest kernel. | ||
| * | ||
| * Event channels are represented by the evtchn_* fields in | ||
| * struct shared_info and struct vcpu_info. | ||
| */ | ||
|
|
||
| /* | ||
| * ` enum neg_errnoval | ||
| * ` HYPERVISOR_event_channel_op(enum event_channel_op cmd, void *args) | ||
| * ` | ||
| * @cmd == EVTCHNOP_* (event-channel operation). | ||
| * @args == struct evtchn_* Operation-specific extra arguments (NULL if none). | ||
| */ | ||
|
|
||
| /* ` enum event_channel_op { // EVTCHNOP_* => struct evtchn_* */ | ||
| #define EVTCHNOP_bind_interdomain 0 | ||
| #define EVTCHNOP_bind_virq 1 | ||
| #define EVTCHNOP_bind_pirq 2 | ||
| #define EVTCHNOP_close 3 | ||
| #define EVTCHNOP_send 4 | ||
| #define EVTCHNOP_status 5 | ||
| #define EVTCHNOP_alloc_unbound 6 | ||
| #define EVTCHNOP_bind_ipi 7 | ||
| #define EVTCHNOP_bind_vcpu 8 | ||
| #define EVTCHNOP_unmask 9 | ||
| #define EVTCHNOP_reset 10 | ||
| #define EVTCHNOP_init_control 11 | ||
| #define EVTCHNOP_expand_array 12 | ||
| #define EVTCHNOP_set_priority 13 | ||
| #ifdef __XEN__ | ||
| #define EVTCHNOP_reset_cont 14 | ||
| #endif | ||
| /* ` } */ | ||
|
|
||
| typedef uint32_t evtchn_port_t; | ||
| DEFINE_XEN_GUEST_HANDLE(evtchn_port_t); | ||
|
|
||
| /* | ||
| * EVTCHNOP_alloc_unbound: Allocate a port in domain <dom> and mark as | ||
| * accepting interdomain bindings from domain <remote_dom>. A fresh port | ||
| * is allocated in <dom> and returned as <port>. | ||
| * NOTES: | ||
| * 1. If the caller is unprivileged then <dom> must be DOMID_SELF. | ||
| * 2. <remote_dom> may be DOMID_SELF, allowing loopback connections. | ||
| */ | ||
| struct evtchn_alloc_unbound { | ||
| /* IN parameters */ | ||
| domid_t dom, remote_dom; | ||
| /* OUT parameters */ | ||
| evtchn_port_t port; | ||
| }; | ||
| typedef struct evtchn_alloc_unbound evtchn_alloc_unbound_t; | ||
|
|
||
| /* | ||
| * EVTCHNOP_bind_interdomain: Construct an interdomain event channel between | ||
| * the calling domain and <remote_dom>. <remote_dom,remote_port> must identify | ||
| * a port that is unbound and marked as accepting bindings from the calling | ||
| * domain. A fresh port is allocated in the calling domain and returned as | ||
| * <local_port>. | ||
| * | ||
| * In case the peer domain has already tried to set our event channel | ||
| * pending, before it was bound, EVTCHNOP_bind_interdomain always sets | ||
| * the local event channel pending. | ||
| * | ||
| * The usual pattern of use, in the guest's upcall (or subsequent | ||
| * handler) is as follows: (Re-enable the event channel for subsequent | ||
| * signalling and then) check for the existence of whatever condition | ||
| * is being waited for by other means, and take whatever action is | ||
| * needed (if any). | ||
| * | ||
| * NOTES: | ||
| * 1. <remote_dom> may be DOMID_SELF, allowing loopback connections. | ||
| */ | ||
| struct evtchn_bind_interdomain { | ||
| /* IN parameters. */ | ||
| domid_t remote_dom; | ||
| evtchn_port_t remote_port; | ||
| /* OUT parameters. */ | ||
| evtchn_port_t local_port; | ||
| }; | ||
| typedef struct evtchn_bind_interdomain evtchn_bind_interdomain_t; | ||
|
|
||
| /* | ||
| * EVTCHNOP_bind_virq: Bind a local event channel to VIRQ <irq> on specified | ||
| * vcpu. | ||
| * NOTES: | ||
| * 1. Virtual IRQs are classified as per-vcpu or global. See the VIRQ list | ||
| * in xen.h for the classification of each VIRQ. | ||
| * 2. Global VIRQs must be allocated on VCPU0 but can subsequently be | ||
| * re-bound via EVTCHNOP_bind_vcpu. | ||
| * 3. Per-vcpu VIRQs may be bound to at most one event channel per vcpu. | ||
| * The allocated event channel is bound to the specified vcpu and the | ||
| * binding cannot be changed. | ||
| */ | ||
| struct evtchn_bind_virq { | ||
| /* IN parameters. */ | ||
| uint32_t virq; /* enum virq */ | ||
| uint32_t vcpu; | ||
| /* OUT parameters. */ | ||
| evtchn_port_t port; | ||
| }; | ||
| typedef struct evtchn_bind_virq evtchn_bind_virq_t; | ||
|
|
||
| /* | ||
| * EVTCHNOP_bind_pirq: Bind a local event channel to a real IRQ (PIRQ <irq>). | ||
| * NOTES: | ||
| * 1. A physical IRQ may be bound to at most one event channel per domain. | ||
| * 2. Only a sufficiently-privileged domain may bind to a physical IRQ. | ||
| */ | ||
| struct evtchn_bind_pirq { | ||
| /* IN parameters. */ | ||
| uint32_t pirq; | ||
| #define BIND_PIRQ__WILL_SHARE 1 | ||
| uint32_t flags; /* BIND_PIRQ__* */ | ||
| /* OUT parameters. */ | ||
| evtchn_port_t port; | ||
| }; | ||
| typedef struct evtchn_bind_pirq evtchn_bind_pirq_t; | ||
|
|
||
| /* | ||
| * EVTCHNOP_bind_ipi: Bind a local event channel to receive events. | ||
| * NOTES: | ||
| * 1. The allocated event channel is bound to the specified vcpu. The binding | ||
| * may not be changed. | ||
| */ | ||
| struct evtchn_bind_ipi { | ||
| uint32_t vcpu; | ||
| /* OUT parameters. */ | ||
| evtchn_port_t port; | ||
| }; | ||
| typedef struct evtchn_bind_ipi evtchn_bind_ipi_t; | ||
|
|
||
| /* | ||
| * EVTCHNOP_close: Close a local event channel <port>. If the channel is | ||
| * interdomain then the remote end is placed in the unbound state | ||
| * (EVTCHNSTAT_unbound), awaiting a new connection. | ||
| */ | ||
| struct evtchn_close { | ||
| /* IN parameters. */ | ||
| evtchn_port_t port; | ||
| }; | ||
| typedef struct evtchn_close evtchn_close_t; | ||
|
|
||
| /* | ||
| * EVTCHNOP_send: Send an event to the remote end of the channel whose local | ||
| * endpoint is <port>. | ||
| */ | ||
| struct evtchn_send { | ||
| /* IN parameters. */ | ||
| evtchn_port_t port; | ||
| }; | ||
| typedef struct evtchn_send evtchn_send_t; | ||
|
|
||
| /* | ||
| * EVTCHNOP_status: Get the current status of the communication channel which | ||
| * has an endpoint at <dom, port>. | ||
| * NOTES: | ||
| * 1. <dom> may be specified as DOMID_SELF. | ||
| * 2. Only a sufficiently-privileged domain may obtain the status of an event | ||
| * channel for which <dom> is not DOMID_SELF. | ||
| */ | ||
| struct evtchn_status { | ||
| /* IN parameters */ | ||
| domid_t dom; | ||
| evtchn_port_t port; | ||
| /* OUT parameters */ | ||
| #define EVTCHNSTAT_closed 0 /* Channel is not in use. */ | ||
| #define EVTCHNSTAT_unbound 1 /* Channel is waiting interdom connection.*/ | ||
| #define EVTCHNSTAT_interdomain 2 /* Channel is connected to remote domain. */ | ||
| #define EVTCHNSTAT_pirq 3 /* Channel is bound to a phys IRQ line. */ | ||
| #define EVTCHNSTAT_virq 4 /* Channel is bound to a virtual IRQ line */ | ||
| #define EVTCHNSTAT_ipi 5 /* Channel is bound to a virtual IPI line */ | ||
| uint32_t status; | ||
| uint32_t vcpu; /* VCPU to which this channel is bound. */ | ||
| union { | ||
| struct { | ||
| domid_t dom; | ||
| } unbound; /* EVTCHNSTAT_unbound */ | ||
| struct { | ||
| domid_t dom; | ||
| evtchn_port_t port; | ||
| } interdomain; /* EVTCHNSTAT_interdomain */ | ||
| uint32_t pirq; /* EVTCHNSTAT_pirq */ | ||
| uint32_t virq; /* EVTCHNSTAT_virq */ | ||
| } u; | ||
| }; | ||
| typedef struct evtchn_status evtchn_status_t; | ||
|
|
||
| /* | ||
| * EVTCHNOP_bind_vcpu: Specify which vcpu a channel should notify when an | ||
| * event is pending. | ||
| * NOTES: | ||
| * 1. IPI-bound channels always notify the vcpu specified at bind time. | ||
| * This binding cannot be changed. | ||
| * 2. Per-VCPU VIRQ channels always notify the vcpu specified at bind time. | ||
| * This binding cannot be changed. | ||
| * 3. All other channels notify vcpu0 by default. This default is set when | ||
| * the channel is allocated (a port that is freed and subsequently reused | ||
| * has its binding reset to vcpu0). | ||
| */ | ||
| struct evtchn_bind_vcpu { | ||
| /* IN parameters. */ | ||
| evtchn_port_t port; | ||
| uint32_t vcpu; | ||
| }; | ||
| typedef struct evtchn_bind_vcpu evtchn_bind_vcpu_t; | ||
|
|
||
| /* | ||
| * EVTCHNOP_unmask: Unmask the specified local event-channel port and deliver | ||
| * a notification to the appropriate VCPU if an event is pending. | ||
| */ | ||
| struct evtchn_unmask { | ||
| /* IN parameters. */ | ||
| evtchn_port_t port; | ||
| }; | ||
| typedef struct evtchn_unmask evtchn_unmask_t; | ||
|
|
||
| /* | ||
| * EVTCHNOP_reset: Close all event channels associated with specified domain. | ||
| * NOTES: | ||
| * 1. <dom> may be specified as DOMID_SELF. | ||
| * 2. Only a sufficiently-privileged domain may specify other than DOMID_SELF. | ||
| * 3. Destroys all control blocks and event array, resets event channel | ||
| * operations to 2-level ABI if called with <dom> == DOMID_SELF and FIFO | ||
| * ABI was used. Guests should not bind events during EVTCHNOP_reset call | ||
| * as these events are likely to be lost. | ||
| */ | ||
| struct evtchn_reset { | ||
| /* IN parameters. */ | ||
| domid_t dom; | ||
| }; | ||
| typedef struct evtchn_reset evtchn_reset_t; | ||
|
|
||
| /* | ||
| * EVTCHNOP_init_control: initialize the control block for the FIFO ABI. | ||
| * | ||
| * Note: any events that are currently pending will not be resent and | ||
| * will be lost. Guests should call this before binding any event to | ||
| * avoid losing any events. | ||
| */ | ||
| struct evtchn_init_control { | ||
| /* IN parameters. */ | ||
| uint64_t control_gfn; | ||
| uint32_t offset; | ||
| uint32_t vcpu; | ||
| /* OUT parameters. */ | ||
| uint8_t link_bits; | ||
| uint8_t _pad[7]; | ||
| }; | ||
| typedef struct evtchn_init_control evtchn_init_control_t; | ||
|
|
||
| /* | ||
| * EVTCHNOP_expand_array: add an additional page to the event array. | ||
| */ | ||
| struct evtchn_expand_array { | ||
| /* IN parameters. */ | ||
| uint64_t array_gfn; | ||
| }; | ||
| typedef struct evtchn_expand_array evtchn_expand_array_t; | ||
|
|
||
| /* | ||
| * EVTCHNOP_set_priority: set the priority for an event channel. | ||
| */ | ||
| struct evtchn_set_priority { | ||
| /* IN parameters. */ | ||
| evtchn_port_t port; | ||
| uint32_t priority; | ||
| }; | ||
| typedef struct evtchn_set_priority evtchn_set_priority_t; | ||
|
|
||
| /* | ||
| * ` enum neg_errnoval | ||
| * ` HYPERVISOR_event_channel_op_compat(struct evtchn_op *op) | ||
| * ` | ||
| * Superceded by new event_channel_op() hypercall since 0x00030202. | ||
| */ | ||
| struct evtchn_op { | ||
| uint32_t cmd; /* enum event_channel_op */ | ||
| union { | ||
| evtchn_alloc_unbound_t alloc_unbound; | ||
| evtchn_bind_interdomain_t bind_interdomain; | ||
| evtchn_bind_virq_t bind_virq; | ||
| evtchn_bind_pirq_t bind_pirq; | ||
| evtchn_bind_ipi_t bind_ipi; | ||
| evtchn_close_t close; | ||
| evtchn_send_t send; | ||
| evtchn_status_t status; | ||
| evtchn_bind_vcpu_t bind_vcpu; | ||
| evtchn_unmask_t unmask; | ||
| } u; | ||
| }; | ||
| typedef struct evtchn_op evtchn_op_t; | ||
| DEFINE_XEN_GUEST_HANDLE(evtchn_op_t); | ||
|
|
||
| /* | ||
| * 2-level ABI | ||
| */ | ||
|
|
||
| #define EVTCHN_2L_NR_CHANNELS (sizeof(xen_ulong_t) * sizeof(xen_ulong_t) * 64) | ||
|
|
||
| /* | ||
| * FIFO ABI | ||
| */ | ||
|
|
||
| /* Events may have priorities from 0 (highest) to 15 (lowest). */ | ||
| #define EVTCHN_FIFO_PRIORITY_MAX 0 | ||
| #define EVTCHN_FIFO_PRIORITY_DEFAULT 7 | ||
| #define EVTCHN_FIFO_PRIORITY_MIN 15 | ||
|
|
||
| #define EVTCHN_FIFO_MAX_QUEUES (EVTCHN_FIFO_PRIORITY_MIN + 1) | ||
|
|
||
| typedef uint32_t event_word_t; | ||
|
|
||
| #define EVTCHN_FIFO_PENDING 31 | ||
| #define EVTCHN_FIFO_MASKED 30 | ||
| #define EVTCHN_FIFO_LINKED 29 | ||
| #define EVTCHN_FIFO_BUSY 28 | ||
|
|
||
| #define EVTCHN_FIFO_LINK_BITS 17 | ||
| #define EVTCHN_FIFO_LINK_MASK ((1 << EVTCHN_FIFO_LINK_BITS) - 1) | ||
|
|
||
| #define EVTCHN_FIFO_NR_CHANNELS (1 << EVTCHN_FIFO_LINK_BITS) | ||
|
|
||
| struct evtchn_fifo_control_block { | ||
| uint32_t ready; | ||
| uint32_t _rsvd; | ||
| uint32_t head[EVTCHN_FIFO_MAX_QUEUES]; | ||
| }; | ||
| typedef struct evtchn_fifo_control_block evtchn_fifo_control_block_t; | ||
|
|
||
| #endif /* __XEN_PUBLIC_EVENT_CHANNEL_H__ */ | ||
|
|
||
| /* | ||
| * Local variables: | ||
| * mode: C | ||
| * c-file-style: "BSD" | ||
| * c-basic-offset: 4 | ||
| * tab-width: 4 | ||
| * indent-tabs-mode: nil | ||
| * End: | ||
| */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,143 @@ | ||
| /****************************************************************************** | ||
| * features.h | ||
| * | ||
| * Feature flags, reported by XENVER_get_features. | ||
| * | ||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| * of this software and associated documentation files (the "Software"), to | ||
| * deal in the Software without restriction, including without limitation the | ||
| * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| * sell copies of the Software, and to permit persons to whom the Software is | ||
| * furnished to do so, subject to the following conditions: | ||
| * | ||
| * The above copyright notice and this permission notice shall be included in | ||
| * all copies or substantial portions of the Software. | ||
| * | ||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| * DEALINGS IN THE SOFTWARE. | ||
| * | ||
| * Copyright (c) 2006, Keir Fraser <keir@xensource.com> | ||
| */ | ||
|
|
||
| #ifndef __XEN_PUBLIC_FEATURES_H__ | ||
| #define __XEN_PUBLIC_FEATURES_H__ | ||
|
|
||
| /* | ||
| * `incontents 200 elfnotes_features XEN_ELFNOTE_FEATURES | ||
| * | ||
| * The list of all the features the guest supports. They are set by | ||
| * parsing the XEN_ELFNOTE_FEATURES and XEN_ELFNOTE_SUPPORTED_FEATURES | ||
| * string. The format is the feature names (as given here without the | ||
| * "XENFEAT_" prefix) separated by '|' characters. | ||
| * If a feature is required for the kernel to function then the feature name | ||
| * must be preceded by a '!' character. | ||
| * | ||
| * Note that if XEN_ELFNOTE_SUPPORTED_FEATURES is used, then in the | ||
| * XENFEAT_dom0 MUST be set if the guest is to be booted as dom0, | ||
| */ | ||
|
|
||
| /* | ||
| * If set, the guest does not need to write-protect its pagetables, and can | ||
| * update them via direct writes. | ||
| */ | ||
| #define XENFEAT_writable_page_tables 0 | ||
|
|
||
| /* | ||
| * If set, the guest does not need to write-protect its segment descriptor | ||
| * tables, and can update them via direct writes. | ||
| */ | ||
| #define XENFEAT_writable_descriptor_tables 1 | ||
|
|
||
| /* | ||
| * If set, translation between the guest's 'pseudo-physical' address space | ||
| * and the host's machine address space are handled by the hypervisor. In this | ||
| * mode the guest does not need to perform phys-to/from-machine translations | ||
| * when performing page table operations. | ||
| */ | ||
| #define XENFEAT_auto_translated_physmap 2 | ||
|
|
||
| /* If set, the guest is running in supervisor mode (e.g., x86 ring 0). */ | ||
| #define XENFEAT_supervisor_mode_kernel 3 | ||
|
|
||
| /* | ||
| * If set, the guest does not need to allocate x86 PAE page directories | ||
| * below 4GB. This flag is usually implied by auto_translated_physmap. | ||
| */ | ||
| #define XENFEAT_pae_pgdir_above_4gb 4 | ||
|
|
||
| /* x86: Does this Xen host support the MMU_PT_UPDATE_PRESERVE_AD hypercall? */ | ||
| #define XENFEAT_mmu_pt_update_preserve_ad 5 | ||
|
|
||
| /* x86: Does this Xen host support the MMU_{CLEAR,COPY}_PAGE hypercall? */ | ||
| #define XENFEAT_highmem_assist 6 | ||
|
|
||
| /* | ||
| * If set, GNTTABOP_map_grant_ref honors flags to be placed into guest kernel | ||
| * available pte bits. | ||
| */ | ||
| #define XENFEAT_gnttab_map_avail_bits 7 | ||
|
|
||
| /* x86: Does this Xen host support the HVM callback vector type? */ | ||
| #define XENFEAT_hvm_callback_vector 8 | ||
|
|
||
| /* x86: pvclock algorithm is safe to use on HVM */ | ||
| #define XENFEAT_hvm_safe_pvclock 9 | ||
|
|
||
| /* x86: pirq can be used by HVM guests */ | ||
| #define XENFEAT_hvm_pirqs 10 | ||
|
|
||
| /* operation as Dom0 is supported */ | ||
| #define XENFEAT_dom0 11 | ||
|
|
||
| /* Xen also maps grant references at pfn = mfn. | ||
| * This feature flag is deprecated and should not be used. | ||
| #define XENFEAT_grant_map_identity 12 | ||
| */ | ||
|
|
||
| /* Guest can use XENMEMF_vnode to specify virtual node for memory op. */ | ||
| #define XENFEAT_memory_op_vnode_supported 13 | ||
|
|
||
| /* arm: Hypervisor supports ARM SMC calling convention. */ | ||
| #define XENFEAT_ARM_SMCCC_supported 14 | ||
|
|
||
| /* | ||
| * x86/PVH: If set, ACPI RSDP can be placed at any address. Otherwise RSDP | ||
| * must be located in lower 1MB, as required by ACPI Specification for IA-PC | ||
| * systems. | ||
| * This feature flag is only consulted if XEN_ELFNOTE_GUEST_OS contains | ||
| * the "linux" string. | ||
| */ | ||
| #define XENFEAT_linux_rsdp_unrestricted 15 | ||
|
|
||
| /* | ||
| * A direct-mapped (or 1:1 mapped) domain is a domain for which its | ||
| * local pages have gfn == mfn. If a domain is direct-mapped, | ||
| * XENFEAT_direct_mapped is set; otherwise XENFEAT_not_direct_mapped | ||
| * is set. | ||
| * | ||
| * If neither flag is set (e.g. older Xen releases) the assumptions are: | ||
| * - not auto_translated domains (x86 only) are always direct-mapped | ||
| * - on x86, auto_translated domains are not direct-mapped | ||
| * - on ARM, Dom0 is direct-mapped, DomUs are not | ||
| */ | ||
| #define XENFEAT_not_direct_mapped 16 | ||
| #define XENFEAT_direct_mapped 17 | ||
|
|
||
| #define XENFEAT_NR_SUBMAPS 1 | ||
|
|
||
| #endif /* __XEN_PUBLIC_FEATURES_H__ */ | ||
|
|
||
| /* | ||
| * Local variables: | ||
| * mode: C | ||
| * c-file-style: "BSD" | ||
| * c-basic-offset: 4 | ||
| * tab-width: 4 | ||
| * indent-tabs-mode: nil | ||
| * End: | ||
| */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,395 @@ | ||
| /* | ||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| * of this software and associated documentation files (the "Software"), to | ||
| * deal in the Software without restriction, including without limitation the | ||
| * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
| * sell copies of the Software, and to permit persons to whom the Software is | ||
| * furnished to do so, subject to the following conditions: | ||
| * | ||
| * The above copyright notice and this permission notice shall be included in | ||
| * all copies or substantial portions of the Software. | ||
| * | ||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| * DEALINGS IN THE SOFTWARE. | ||
| * | ||
| * Copyright (c) 2007, Keir Fraser | ||
| */ | ||
|
|
||
| #ifndef __XEN_PUBLIC_HVM_HVM_OP_H__ | ||
| #define __XEN_PUBLIC_HVM_HVM_OP_H__ | ||
|
|
||
| #include "../xen.h" | ||
| #include "../trace.h" | ||
| #include "../event_channel.h" | ||
|
|
||
| /* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */ | ||
| #define HVMOP_set_param 0 | ||
| #define HVMOP_get_param 1 | ||
| struct xen_hvm_param { | ||
| domid_t domid; /* IN */ | ||
| uint16_t pad; | ||
| uint32_t index; /* IN */ | ||
| uint64_t value; /* IN/OUT */ | ||
| }; | ||
| typedef struct xen_hvm_param xen_hvm_param_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_hvm_param_t); | ||
|
|
||
| struct xen_hvm_altp2m_suppress_ve { | ||
| uint16_t view; | ||
| uint8_t suppress_ve; /* Boolean type. */ | ||
| uint8_t pad1; | ||
| uint32_t pad2; | ||
| uint64_t gfn; | ||
| }; | ||
|
|
||
| struct xen_hvm_altp2m_suppress_ve_multi { | ||
| uint16_t view; | ||
| uint8_t suppress_ve; /* Boolean type. */ | ||
| uint8_t pad1; | ||
| int32_t first_error; /* Should be set to 0. */ | ||
| uint64_t first_gfn; /* Value may be updated. */ | ||
| uint64_t last_gfn; | ||
| uint64_t first_error_gfn; /* Gfn of the first error. */ | ||
| }; | ||
|
|
||
| #if __XEN_INTERFACE_VERSION__ < 0x00040900 | ||
|
|
||
| /* Set the logical level of one of a domain's PCI INTx wires. */ | ||
| #define HVMOP_set_pci_intx_level 2 | ||
| struct xen_hvm_set_pci_intx_level { | ||
| /* Domain to be updated. */ | ||
| domid_t domid; | ||
| /* PCI INTx identification in PCI topology (domain:bus:device:intx). */ | ||
| uint8_t domain, bus, device, intx; | ||
| /* Assertion level (0 = unasserted, 1 = asserted). */ | ||
| uint8_t level; | ||
| }; | ||
| typedef struct xen_hvm_set_pci_intx_level xen_hvm_set_pci_intx_level_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_intx_level_t); | ||
|
|
||
| /* Set the logical level of one of a domain's ISA IRQ wires. */ | ||
| #define HVMOP_set_isa_irq_level 3 | ||
| struct xen_hvm_set_isa_irq_level { | ||
| /* Domain to be updated. */ | ||
| domid_t domid; | ||
| /* ISA device identification, by ISA IRQ (0-15). */ | ||
| uint8_t isa_irq; | ||
| /* Assertion level (0 = unasserted, 1 = asserted). */ | ||
| uint8_t level; | ||
| }; | ||
| typedef struct xen_hvm_set_isa_irq_level xen_hvm_set_isa_irq_level_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_isa_irq_level_t); | ||
|
|
||
| #define HVMOP_set_pci_link_route 4 | ||
| struct xen_hvm_set_pci_link_route { | ||
| /* Domain to be updated. */ | ||
| domid_t domid; | ||
| /* PCI link identifier (0-3). */ | ||
| uint8_t link; | ||
| /* ISA IRQ (1-15), or 0 (disable link). */ | ||
| uint8_t isa_irq; | ||
| }; | ||
| typedef struct xen_hvm_set_pci_link_route xen_hvm_set_pci_link_route_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_link_route_t); | ||
|
|
||
| #endif /* __XEN_INTERFACE_VERSION__ < 0x00040900 */ | ||
|
|
||
| /* Flushes all VCPU TLBs: @arg must be NULL. */ | ||
| #define HVMOP_flush_tlbs 5 | ||
|
|
||
| /* | ||
| * hvmmem_type_t should not be defined when generating the corresponding | ||
| * compat header. This will ensure that the improperly named HVMMEM_(*) | ||
| * values are defined only once. | ||
| */ | ||
| #ifndef XEN_GENERATING_COMPAT_HEADERS | ||
|
|
||
| typedef enum { | ||
| HVMMEM_ram_rw, /* Normal read/write guest RAM */ | ||
| HVMMEM_ram_ro, /* Read-only; writes are discarded */ | ||
| HVMMEM_mmio_dm, /* Reads and write go to the device model */ | ||
| #if __XEN_INTERFACE_VERSION__ < 0x00040700 | ||
| HVMMEM_mmio_write_dm, /* Read-only; writes go to the device model */ | ||
| #else | ||
| HVMMEM_unused, /* Placeholder; setting memory to this type | ||
| will fail for code after 4.7.0 */ | ||
| #endif | ||
| HVMMEM_ioreq_server /* Memory type claimed by an ioreq server; type | ||
| changes to this value are only allowed after | ||
| an ioreq server has claimed its ownership. | ||
| Only pages with HVMMEM_ram_rw are allowed to | ||
| change to this type; conversely, pages with | ||
| this type are only allowed to be changed back | ||
| to HVMMEM_ram_rw. */ | ||
| } hvmmem_type_t; | ||
|
|
||
| #endif /* XEN_GENERATING_COMPAT_HEADERS */ | ||
|
|
||
| /* Hint from PV drivers for pagetable destruction. */ | ||
| #define HVMOP_pagetable_dying 9 | ||
| struct xen_hvm_pagetable_dying { | ||
| /* Domain with a pagetable about to be destroyed. */ | ||
| domid_t domid; | ||
| uint16_t pad[3]; /* align next field on 8-byte boundary */ | ||
| /* guest physical address of the toplevel pagetable dying */ | ||
| uint64_t gpa; | ||
| }; | ||
| typedef struct xen_hvm_pagetable_dying xen_hvm_pagetable_dying_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_hvm_pagetable_dying_t); | ||
|
|
||
| /* Get the current Xen time, in nanoseconds since system boot. */ | ||
| #define HVMOP_get_time 10 | ||
| struct xen_hvm_get_time { | ||
| uint64_t now; /* OUT */ | ||
| }; | ||
| typedef struct xen_hvm_get_time xen_hvm_get_time_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_time_t); | ||
|
|
||
| #define HVMOP_xentrace 11 | ||
| struct xen_hvm_xentrace { | ||
| uint16_t event, extra_bytes; | ||
| uint8_t extra[TRACE_EXTRA_MAX * sizeof(uint32_t)]; | ||
| }; | ||
| typedef struct xen_hvm_xentrace xen_hvm_xentrace_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_hvm_xentrace_t); | ||
|
|
||
| /* Following tools-only interfaces may change in future. */ | ||
| #if defined(__XEN__) || defined(__XEN_TOOLS__) | ||
|
|
||
| /* Deprecated by XENMEM_access_op_set_access */ | ||
| #define HVMOP_set_mem_access 12 | ||
|
|
||
| /* Deprecated by XENMEM_access_op_get_access */ | ||
| #define HVMOP_get_mem_access 13 | ||
|
|
||
| #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */ | ||
|
|
||
| #define HVMOP_get_mem_type 15 | ||
| /* Return hvmmem_type_t for the specified pfn. */ | ||
| struct xen_hvm_get_mem_type { | ||
| /* Domain to be queried. */ | ||
| domid_t domid; | ||
| /* OUT variable. */ | ||
| uint16_t mem_type; | ||
| uint16_t pad[2]; /* align next field on 8-byte boundary */ | ||
| /* IN variable. */ | ||
| uint64_t pfn; | ||
| }; | ||
| typedef struct xen_hvm_get_mem_type xen_hvm_get_mem_type_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_mem_type_t); | ||
|
|
||
| /* Following tools-only interfaces may change in future. */ | ||
| #if defined(__XEN__) || defined(__XEN_TOOLS__) | ||
|
|
||
| /* | ||
| * Definitions relating to DMOP_create_ioreq_server. (Defined here for | ||
| * backwards compatibility). | ||
| */ | ||
|
|
||
| #define HVM_IOREQSRV_BUFIOREQ_OFF 0 | ||
| #define HVM_IOREQSRV_BUFIOREQ_LEGACY 1 | ||
| /* | ||
| * Use this when read_pointer gets updated atomically and | ||
| * the pointer pair gets read atomically: | ||
| */ | ||
| #define HVM_IOREQSRV_BUFIOREQ_ATOMIC 2 | ||
|
|
||
| #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */ | ||
|
|
||
| #if defined(__i386__) || defined(__x86_64__) | ||
|
|
||
| /* | ||
| * HVMOP_set_evtchn_upcall_vector: Set a <vector> that should be used for event | ||
| * channel upcalls on the specified <vcpu>. If set, | ||
| * this vector will be used in preference to the | ||
| * domain global callback via (see | ||
| * HVM_PARAM_CALLBACK_IRQ). | ||
| */ | ||
| #define HVMOP_set_evtchn_upcall_vector 23 | ||
| struct xen_hvm_evtchn_upcall_vector { | ||
| uint32_t vcpu; | ||
| uint8_t vector; | ||
| }; | ||
| typedef struct xen_hvm_evtchn_upcall_vector xen_hvm_evtchn_upcall_vector_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_hvm_evtchn_upcall_vector_t); | ||
|
|
||
| #endif /* defined(__i386__) || defined(__x86_64__) */ | ||
|
|
||
| #define HVMOP_guest_request_vm_event 24 | ||
|
|
||
| /* HVMOP_altp2m: perform altp2m state operations */ | ||
| #define HVMOP_altp2m 25 | ||
|
|
||
| #define HVMOP_ALTP2M_INTERFACE_VERSION 0x00000001 | ||
|
|
||
| struct xen_hvm_altp2m_domain_state { | ||
| /* IN or OUT variable on/off */ | ||
| uint8_t state; | ||
| }; | ||
| typedef struct xen_hvm_altp2m_domain_state xen_hvm_altp2m_domain_state_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_hvm_altp2m_domain_state_t); | ||
|
|
||
| struct xen_hvm_altp2m_vcpu_enable_notify { | ||
| uint32_t vcpu_id; | ||
| uint32_t pad; | ||
| /* #VE info area gfn */ | ||
| uint64_t gfn; | ||
| }; | ||
| typedef struct xen_hvm_altp2m_vcpu_enable_notify xen_hvm_altp2m_vcpu_enable_notify_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_hvm_altp2m_vcpu_enable_notify_t); | ||
|
|
||
| struct xen_hvm_altp2m_vcpu_disable_notify { | ||
| uint32_t vcpu_id; | ||
| }; | ||
| typedef struct xen_hvm_altp2m_vcpu_disable_notify xen_hvm_altp2m_vcpu_disable_notify_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_hvm_altp2m_vcpu_disable_notify_t); | ||
|
|
||
| struct xen_hvm_altp2m_view { | ||
| /* IN/OUT variable */ | ||
| uint16_t view; | ||
| uint16_t hvmmem_default_access; /* xenmem_access_t */ | ||
| }; | ||
| typedef struct xen_hvm_altp2m_view xen_hvm_altp2m_view_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_hvm_altp2m_view_t); | ||
|
|
||
| #if __XEN_INTERFACE_VERSION__ < 0x00040a00 | ||
| struct xen_hvm_altp2m_set_mem_access { | ||
| /* view */ | ||
| uint16_t view; | ||
| /* Memory type */ | ||
| uint16_t access; /* xenmem_access_t */ | ||
| uint32_t pad; | ||
| /* gfn */ | ||
| uint64_t gfn; | ||
| }; | ||
| typedef struct xen_hvm_altp2m_set_mem_access xen_hvm_altp2m_set_mem_access_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_hvm_altp2m_set_mem_access_t); | ||
| #endif /* __XEN_INTERFACE_VERSION__ < 0x00040a00 */ | ||
|
|
||
| struct xen_hvm_altp2m_mem_access { | ||
| /* view */ | ||
| uint16_t view; | ||
| /* Memory type */ | ||
| uint16_t access; /* xenmem_access_t */ | ||
| uint32_t pad; | ||
| /* gfn */ | ||
| uint64_t gfn; | ||
| }; | ||
| typedef struct xen_hvm_altp2m_mem_access xen_hvm_altp2m_mem_access_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_hvm_altp2m_mem_access_t); | ||
|
|
||
| struct xen_hvm_altp2m_set_mem_access_multi { | ||
| /* view */ | ||
| uint16_t view; | ||
| uint16_t pad; | ||
| /* Number of pages */ | ||
| uint32_t nr; | ||
| /* | ||
| * Used for continuation purposes. | ||
| * Must be set to zero upon initial invocation. | ||
| */ | ||
| uint64_t opaque; | ||
| /* List of pfns to set access for */ | ||
| XEN_GUEST_HANDLE(const_uint64) pfn_list; | ||
| /* Corresponding list of access settings for pfn_list */ | ||
| XEN_GUEST_HANDLE(const_uint8) access_list; | ||
| }; | ||
|
|
||
| struct xen_hvm_altp2m_change_gfn { | ||
| /* view */ | ||
| uint16_t view; | ||
| uint16_t pad1; | ||
| uint32_t pad2; | ||
| /* old gfn */ | ||
| uint64_t old_gfn; | ||
| /* new gfn, INVALID_GFN (~0UL) means revert */ | ||
| uint64_t new_gfn; | ||
| }; | ||
| typedef struct xen_hvm_altp2m_change_gfn xen_hvm_altp2m_change_gfn_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_hvm_altp2m_change_gfn_t); | ||
|
|
||
| struct xen_hvm_altp2m_get_vcpu_p2m_idx { | ||
| uint32_t vcpu_id; | ||
| uint16_t altp2m_idx; | ||
| }; | ||
|
|
||
| struct xen_hvm_altp2m_set_visibility { | ||
| uint16_t altp2m_idx; | ||
| uint8_t visible; | ||
| uint8_t pad; | ||
| }; | ||
|
|
||
| struct xen_hvm_altp2m_op { | ||
| uint32_t version; /* HVMOP_ALTP2M_INTERFACE_VERSION */ | ||
| uint32_t cmd; | ||
| /* Get/set the altp2m state for a domain */ | ||
| #define HVMOP_altp2m_get_domain_state 1 | ||
| #define HVMOP_altp2m_set_domain_state 2 | ||
| /* Set a given VCPU to receive altp2m event notifications */ | ||
| #define HVMOP_altp2m_vcpu_enable_notify 3 | ||
| /* Create a new view */ | ||
| #define HVMOP_altp2m_create_p2m 4 | ||
| /* Destroy a view */ | ||
| #define HVMOP_altp2m_destroy_p2m 5 | ||
| /* Switch view for an entire domain */ | ||
| #define HVMOP_altp2m_switch_p2m 6 | ||
| /* Notify that a page of memory is to have specific access types */ | ||
| #define HVMOP_altp2m_set_mem_access 7 | ||
| /* Change a p2m entry to have a different gfn->mfn mapping */ | ||
| #define HVMOP_altp2m_change_gfn 8 | ||
| /* Set access for an array of pages */ | ||
| #define HVMOP_altp2m_set_mem_access_multi 9 | ||
| /* Set the "Suppress #VE" bit on a page */ | ||
| #define HVMOP_altp2m_set_suppress_ve 10 | ||
| /* Get the "Suppress #VE" bit of a page */ | ||
| #define HVMOP_altp2m_get_suppress_ve 11 | ||
| /* Get the access of a page of memory from a certain view */ | ||
| #define HVMOP_altp2m_get_mem_access 12 | ||
| /* Disable altp2m event notifications for a given VCPU */ | ||
| #define HVMOP_altp2m_vcpu_disable_notify 13 | ||
| /* Get the active vcpu p2m index */ | ||
| #define HVMOP_altp2m_get_p2m_idx 14 | ||
| /* Set the "Supress #VE" bit for a range of pages */ | ||
| #define HVMOP_altp2m_set_suppress_ve_multi 15 | ||
| /* Set visibility for a given altp2m view */ | ||
| #define HVMOP_altp2m_set_visibility 16 | ||
| domid_t domain; | ||
| uint16_t pad1; | ||
| uint32_t pad2; | ||
| union { | ||
| struct xen_hvm_altp2m_domain_state domain_state; | ||
| struct xen_hvm_altp2m_vcpu_enable_notify enable_notify; | ||
| struct xen_hvm_altp2m_view view; | ||
| #if __XEN_INTERFACE_VERSION__ < 0x00040a00 | ||
| struct xen_hvm_altp2m_set_mem_access set_mem_access; | ||
| #endif /* __XEN_INTERFACE_VERSION__ < 0x00040a00 */ | ||
| struct xen_hvm_altp2m_mem_access mem_access; | ||
| struct xen_hvm_altp2m_change_gfn change_gfn; | ||
| struct xen_hvm_altp2m_set_mem_access_multi set_mem_access_multi; | ||
| struct xen_hvm_altp2m_suppress_ve suppress_ve; | ||
| struct xen_hvm_altp2m_suppress_ve_multi suppress_ve_multi; | ||
| struct xen_hvm_altp2m_vcpu_disable_notify disable_notify; | ||
| struct xen_hvm_altp2m_get_vcpu_p2m_idx get_vcpu_p2m_idx; | ||
| struct xen_hvm_altp2m_set_visibility set_visibility; | ||
| uint8_t pad[64]; | ||
| } u; | ||
| }; | ||
| typedef struct xen_hvm_altp2m_op xen_hvm_altp2m_op_t; | ||
| DEFINE_XEN_GUEST_HANDLE(xen_hvm_altp2m_op_t); | ||
|
|
||
| #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */ | ||
|
|
||
| /* | ||
| * Local variables: | ||
| * mode: C | ||
| * c-file-style: "BSD" | ||
| * c-basic-offset: 4 | ||
| * tab-width: 4 | ||
| * indent-tabs-mode: nil | ||
| * End: | ||
| */ |