2,341 changes: 2,341 additions & 0 deletions hw/i386/kvm/xen_evtchn.c

Large diffs are not rendered by default.

88 changes: 88 additions & 0 deletions hw/i386/kvm/xen_evtchn.h
@@ -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 */
232 changes: 232 additions & 0 deletions hw/i386/kvm/xen_gnttab.c
@@ -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;
}
25 changes: 25 additions & 0 deletions hw/i386/kvm/xen_gnttab.h
@@ -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 */
272 changes: 272 additions & 0 deletions hw/i386/kvm/xen_overlay.c
@@ -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;
}
26 changes: 26 additions & 0 deletions hw/i386/kvm/xen_overlay.h
@@ -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 */
500 changes: 500 additions & 0 deletions hw/i386/kvm/xen_xenstore.c

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions hw/i386/kvm/xen_xenstore.h
@@ -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 */
26 changes: 26 additions & 0 deletions hw/i386/pc.c
Expand Up @@ -90,6 +90,10 @@
#include "hw/virtio/virtio-iommu.h"
#include "hw/virtio/virtio-pmem-pci.h"
#include "hw/virtio/virtio-mem-pci.h"
#include "hw/i386/kvm/xen_overlay.h"
#include "hw/i386/kvm/xen_evtchn.h"
#include "hw/i386/kvm/xen_gnttab.h"
#include "hw/i386/kvm/xen_xenstore.h"
#include "hw/mem/memory-device.h"
#include "sysemu/replay.h"
#include "target/i386/cpu.h"
Expand Down Expand Up @@ -1308,6 +1312,15 @@ void pc_basic_device_init(struct PCMachineState *pcms,
}
*rtc_state = ISA_DEVICE(mc146818_rtc_init(isa_bus, 2000, rtc_irq));

#ifdef CONFIG_XEN_EMU
if (xen_mode == XEN_EMULATE) {
xen_evtchn_connect_gsis(gsi);
if (pcms->bus) {
pci_create_simple(pcms->bus, -1, "xen-platform");
}
}
#endif

qemu_register_boot_set(pc_boot_set, *rtc_state);

if (!xen_enabled() &&
Expand Down Expand Up @@ -1846,6 +1859,19 @@ static void pc_machine_initfn(Object *obj)
cxl_machine_init(obj, &pcms->cxl_devices_state);
}

int pc_machine_kvm_type(MachineState *machine, const char *kvm_type)
{
#ifdef CONFIG_XEN_EMU
if (xen_mode == XEN_EMULATE) {
xen_overlay_create();
xen_evtchn_create();
xen_gnttab_create();
xen_xenstore_create();
}
#endif
return 0;
}

static void pc_machine_reset(MachineState *machine, ShutdownCause reason)
{
CPUState *cs;
Expand Down
16 changes: 16 additions & 0 deletions hw/i386/x86.c
Expand Up @@ -61,6 +61,11 @@
#include CONFIG_DEVICES
#include "kvm/kvm_i386.h"

#ifdef CONFIG_XEN_EMU
#include "hw/xen/xen.h"
#include "hw/i386/kvm/xen_evtchn.h"
#endif

/* Physical Address of PVH entry point read from kernel ELF NOTE */
static size_t pvh_start_addr;

Expand Down Expand Up @@ -610,6 +615,17 @@ void gsi_handler(void *opaque, int n, int level)
}
/* fall through */
case ISA_NUM_IRQS ... IOAPIC_NUM_PINS - 1:
#ifdef CONFIG_XEN_EMU
/*
* Xen delivers the GSI to the Legacy PIC (not that Legacy PIC
* routing actually works properly under Xen). And then to
* *either* the PIRQ handling or the I/OAPIC depending on
* whether the former wants it.
*/
if (xen_mode == XEN_EMULATE && xen_evtchn_set_gsi(n, level)) {
break;
}
#endif
qemu_set_irq(s->ioapic_irq[n], level);
break;
case IO_APIC_SECONDARY_IRQBASE
Expand Down
5 changes: 4 additions & 1 deletion hw/i386/xen/meson.build
Expand Up @@ -2,6 +2,9 @@ i386_ss.add(when: 'CONFIG_XEN', if_true: files(
'xen-hvm.c',
'xen-mapcache.c',
'xen_apic.c',
'xen_platform.c',
'xen_pvdevice.c',
))

i386_ss.add(when: 'CONFIG_XEN_BUS', if_true: files(
'xen_platform.c',
))
8 changes: 1 addition & 7 deletions hw/i386/xen/xen-hvm.c
Expand Up @@ -1502,13 +1502,7 @@ void xen_hvm_init_pc(PCMachineState *pcms, MemoryRegion **ram_memory)
device_listener_register(&state->device_listener);

xen_bus_init();

/* Initialize backend core & drivers */
if (xen_be_init() != 0) {
error_report("xen backend core setup failed");
goto err;
}
xen_be_register_common();
xen_be_init();

QLIST_INIT(&xen_physmap);
xen_read_physmap(state);
Expand Down
57 changes: 41 additions & 16 deletions hw/i386/xen/xen_platform.c
Expand Up @@ -27,16 +27,21 @@
#include "qapi/error.h"
#include "hw/ide/pci.h"
#include "hw/pci/pci.h"
#include "hw/xen/xen_common.h"
#include "migration/vmstate.h"
#include "hw/xen/xen-legacy-backend.h"
#include "hw/xen/xen.h"
#include "net/net.h"
#include "trace.h"
#include "sysemu/xen.h"
#include "sysemu/block-backend.h"
#include "qemu/error-report.h"
#include "qemu/module.h"
#include "qom/object.h"

#ifdef CONFIG_XEN
#include "hw/xen/xen_common.h"
#include "hw/xen/xen-legacy-backend.h"
#endif

//#define DEBUG_PLATFORM

#ifdef DEBUG_PLATFORM
Expand Down Expand Up @@ -108,12 +113,25 @@ static void log_writeb(PCIXenPlatformState *s, char val)
#define _UNPLUG_NVME_DISKS 3
#define UNPLUG_NVME_DISKS (1u << _UNPLUG_NVME_DISKS)

static bool pci_device_is_passthrough(PCIDevice *d)
{
if (!strcmp(d->name, "xen-pci-passthrough")) {
return true;
}

if (xen_mode == XEN_EMULATE && !strcmp(d->name, "vfio-pci")) {
return true;
}

return false;
}

static void unplug_nic(PCIBus *b, PCIDevice *d, void *o)
{
/* We have to ignore passthrough devices */
if (pci_get_word(d->config + PCI_CLASS_DEVICE) ==
PCI_CLASS_NETWORK_ETHERNET
&& strcmp(d->name, "xen-pci-passthrough") != 0) {
&& !pci_device_is_passthrough(d)) {
object_unparent(OBJECT(d));
}
}
Expand Down Expand Up @@ -186,9 +204,8 @@ static void unplug_disks(PCIBus *b, PCIDevice *d, void *opaque)
!(flags & UNPLUG_IDE_SCSI_DISKS);

/* We have to ignore passthrough devices */
if (!strcmp(d->name, "xen-pci-passthrough")) {
if (pci_device_is_passthrough(d))
return;
}

switch (pci_get_word(d->config + PCI_CLASS_DEVICE)) {
case PCI_CLASS_STORAGE_IDE:
Expand Down Expand Up @@ -267,18 +284,26 @@ static void platform_fixed_ioport_writeb(void *opaque, uint32_t addr, uint32_t v
PCIXenPlatformState *s = opaque;

switch (addr) {
case 0: /* Platform flags */ {
hvmmem_type_t mem_type = (val & PFFLAG_ROM_LOCK) ?
HVMMEM_ram_ro : HVMMEM_ram_rw;
if (xen_set_mem_type(xen_domid, mem_type, 0xc0, 0x40)) {
DPRINTF("unable to change ro/rw state of ROM memory area!\n");
} else {
case 0: /* Platform flags */
if (xen_mode == XEN_EMULATE) {
/* XX: Use i440gx/q35 PAM setup to do this? */
s->flags = val & PFFLAG_ROM_LOCK;
DPRINTF("changed ro/rw state of ROM memory area. now is %s state.\n",
(mem_type == HVMMEM_ram_ro ? "ro":"rw"));
#ifdef CONFIG_XEN
} else {
hvmmem_type_t mem_type = (val & PFFLAG_ROM_LOCK) ?
HVMMEM_ram_ro : HVMMEM_ram_rw;

if (xen_set_mem_type(xen_domid, mem_type, 0xc0, 0x40)) {
DPRINTF("unable to change ro/rw state of ROM memory area!\n");
} else {
s->flags = val & PFFLAG_ROM_LOCK;
DPRINTF("changed ro/rw state of ROM memory area. now is %s state.\n",
(mem_type == HVMMEM_ram_ro ? "ro" : "rw"));
}
#endif
}
break;
}

case 2:
log_writeb(s, val);
break;
Expand Down Expand Up @@ -496,8 +521,8 @@ static void xen_platform_realize(PCIDevice *dev, Error **errp)
uint8_t *pci_conf;

/* Device will crash on reset if xen is not initialized */
if (!xen_enabled()) {
error_setg(errp, "xen-platform device requires the Xen accelerator");
if (xen_mode == XEN_DISABLED) {
error_setg(errp, "xen-platform device requires a Xen guest");
return;
}

Expand Down
11 changes: 11 additions & 0 deletions hw/pci/msi.c
Expand Up @@ -24,6 +24,8 @@
#include "qemu/range.h"
#include "qapi/error.h"

#include "hw/i386/kvm/xen_evtchn.h"

/* PCI_MSI_ADDRESS_LO */
#define PCI_MSI_ADDRESS_LO_MASK (~0x3)

Expand Down Expand Up @@ -414,6 +416,15 @@ void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len)
fprintf(stderr, "\n");
#endif

if (xen_mode == XEN_EMULATE) {
for (vector = 0; vector < msi_nr_vectors(flags); vector++) {
MSIMessage msg = msi_prepare_message(dev, vector);

xen_evtchn_snoop_msi(dev, false, vector, msg.address, msg.data,
msi_is_masked(dev, vector));
}
}

if (!(flags & PCI_MSI_FLAGS_ENABLE)) {
return;
}
Expand Down
9 changes: 9 additions & 0 deletions hw/pci/msix.c
Expand Up @@ -26,6 +26,8 @@
#include "qapi/error.h"
#include "trace.h"

#include "hw/i386/kvm/xen_evtchn.h"

/* MSI enable bit and maskall bit are in byte 1 in FLAGS register */
#define MSIX_CONTROL_OFFSET (PCI_MSIX_FLAGS + 1)
#define MSIX_ENABLE_MASK (PCI_MSIX_FLAGS_ENABLE >> 8)
Expand Down Expand Up @@ -124,6 +126,13 @@ static void msix_handle_mask_update(PCIDevice *dev, int vector, bool was_masked)
{
bool is_masked = msix_is_masked(dev, vector);

if (xen_mode == XEN_EMULATE) {
MSIMessage msg = msix_prepare_message(dev, vector);

xen_evtchn_snoop_msi(dev, true, vector, msg.address, msg.data,
is_masked);
}

if (is_masked == was_masked) {
return;
}
Expand Down
17 changes: 17 additions & 0 deletions hw/pci/pci.c
Expand Up @@ -49,6 +49,9 @@
#include "qemu/cutils.h"
#include "pci-internal.h"

#include "hw/xen/xen.h"
#include "hw/i386/kvm/xen_evtchn.h"

//#define DEBUG_PCI
#ifdef DEBUG_PCI
# define PCI_DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
Expand Down Expand Up @@ -319,6 +322,17 @@ static void pci_msi_trigger(PCIDevice *dev, MSIMessage msg)
{
MemTxAttrs attrs = {};

/*
* Xen uses the high bits of the address to contain some of the bits
* of the PIRQ#. Therefore we can't just send the write cycle and
* trust that it's caught by the APIC at 0xfee00000 because the
* target of the write might be e.g. 0x0x1000fee46000 for PIRQ#4166.
* So we intercept the delivery here instead of in kvm_send_msi().
*/
if (xen_mode == XEN_EMULATE &&
xen_evtchn_deliver_pirq_msi(msg.address, msg.data)) {
return;
}
attrs.requester_id = pci_requester_id(dev);
address_space_stl_le(&dev->bus_master_as, msg.address, msg.data,
attrs, NULL);
Expand Down Expand Up @@ -988,6 +1002,9 @@ static void do_pci_unregister_device(PCIDevice *pci_dev)
pci_get_bus(pci_dev)->devices[pci_dev->devfn] = NULL;
pci_config_free(pci_dev);

if (xen_mode == XEN_EMULATE) {
xen_evtchn_remove_pci_device(pci_dev);
}
if (memory_region_is_mapped(&pci_dev->bus_master_enable_region)) {
memory_region_del_subregion(&pci_dev->bus_master_container_region,
&pci_dev->bus_master_enable_region);
Expand Down
3 changes: 3 additions & 0 deletions hw/xen/Kconfig
@@ -0,0 +1,3 @@
config XEN_BUS
bool
default y if (XEN || XEN_EMU)
56 changes: 22 additions & 34 deletions hw/xen/xen-legacy-backend.c
Expand Up @@ -676,21 +676,30 @@ void xenstore_update_fe(char *watch, struct XenLegacyDevice *xendev)
}
/* -------------------------------------------------------------------- */

int xen_be_init(void)
static void xen_set_dynamic_sysbus(void)
{
Object *machine = qdev_get_machine();
ObjectClass *oc = object_get_class(machine);
MachineClass *mc = MACHINE_CLASS(oc);

machine_class_allow_dynamic_sysbus_dev(mc, TYPE_XENSYSDEV);
}

void xen_be_init(void)
{
xengnttab_handle *gnttabdev;

xenstore = xs_daemon_open();
if (!xenstore) {
xen_pv_printf(NULL, 0, "can't connect to xenstored\n");
return -1;
exit(1);
}

qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL);

if (xen_xc == NULL || xen_fmem == NULL) {
/* Check if xen_init() have been called */
goto err;
xen_pv_printf(NULL, 0, "Xen operations not set up\n");
exit(1);
}

gnttabdev = xengnttab_open(NULL, 0);
Expand All @@ -706,23 +715,16 @@ int xen_be_init(void)
xen_sysbus = qbus_new(TYPE_XENSYSBUS, xen_sysdev, "xen-sysbus");
qbus_set_bus_hotplug_handler(xen_sysbus);

return 0;

err:
qemu_set_fd_handler(xs_fileno(xenstore), NULL, NULL, NULL);
xs_daemon_close(xenstore);
xenstore = NULL;

return -1;
}

static void xen_set_dynamic_sysbus(void)
{
Object *machine = qdev_get_machine();
ObjectClass *oc = object_get_class(machine);
MachineClass *mc = MACHINE_CLASS(oc);
xen_set_dynamic_sysbus();

machine_class_allow_dynamic_sysbus_dev(mc, TYPE_XENSYSDEV);
xen_be_register("console", &xen_console_ops);
xen_be_register("vkbd", &xen_kbdmouse_ops);
#ifdef CONFIG_VIRTFS
xen_be_register("9pfs", &xen_9pfs_ops);
#endif
#ifdef CONFIG_USB_LIBUSB
xen_be_register("qusb", &xen_usb_ops);
#endif
}

int xen_be_register(const char *type, struct XenDevOps *ops)
Expand All @@ -744,20 +746,6 @@ int xen_be_register(const char *type, struct XenDevOps *ops)
return xenstore_scan(type, xen_domid, ops);
}

void xen_be_register_common(void)
{
xen_set_dynamic_sysbus();

xen_be_register("console", &xen_console_ops);
xen_be_register("vkbd", &xen_kbdmouse_ops);
#ifdef CONFIG_VIRTFS
xen_be_register("9pfs", &xen_9pfs_ops);
#endif
#ifdef CONFIG_USB_LIBUSB
xen_be_register("qusb", &xen_usb_ops);
#endif
}

int xen_be_bind_evtchn(struct XenLegacyDevice *xendev)
{
if (xendev->local_port != -1) {
Expand Down
6 changes: 1 addition & 5 deletions hw/xenpv/xen_machine_pv.c
Expand Up @@ -36,10 +36,7 @@ static void xen_init_pv(MachineState *machine)
int i;

/* Initialize backend core & drivers */
if (xen_be_init() != 0) {
error_report("%s: xen backend core setup failed", __func__);
exit(1);
}
xen_be_init();

switch (xen_mode) {
case XEN_ATTACH:
Expand All @@ -55,7 +52,6 @@ static void xen_init_pv(MachineState *machine)
break;
}

xen_be_register_common();
xen_be_register("vfb", &xen_framebuffer_ops);
xen_be_register("qnic", &xen_netdev_ops);

Expand Down
3 changes: 3 additions & 0 deletions include/hw/i386/pc.h
Expand Up @@ -291,12 +291,15 @@ extern const size_t pc_compat_1_5_len;
extern GlobalProperty pc_compat_1_4[];
extern const size_t pc_compat_1_4_len;

int pc_machine_kvm_type(MachineState *machine, const char *vm_type);

#define DEFINE_PC_MACHINE(suffix, namestr, initfn, optsfn) \
static void pc_machine_##suffix##_class_init(ObjectClass *oc, void *data) \
{ \
MachineClass *mc = MACHINE_CLASS(oc); \
optsfn(mc); \
mc->init = initfn; \
mc->kvm_type = pc_machine_kvm_type; \
} \
static const TypeInfo pc_machine_type_##suffix = { \
.name = namestr TYPE_MACHINE_SUFFIX, \
Expand Down
1 change: 1 addition & 0 deletions include/hw/pci/msi.h
Expand Up @@ -33,6 +33,7 @@ extern bool msi_nonbroken;
void msi_set_message(PCIDevice *dev, MSIMessage msg);
MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector);
bool msi_enabled(const PCIDevice *dev);
void msi_set_enabled(PCIDevice *dev);
int msi_init(struct PCIDevice *dev, uint8_t offset,
unsigned int nr_vectors, bool msi64bit,
bool msi_per_vector_mask, Error **errp);
Expand Down
510 changes: 510 additions & 0 deletions include/hw/xen/interface/arch-arm.h

Large diffs are not rendered by default.

118 changes: 118 additions & 0 deletions include/hw/xen/interface/arch-x86/cpuid.h
@@ -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__ */
194 changes: 194 additions & 0 deletions include/hw/xen/interface/arch-x86/xen-x86_32.h
@@ -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:
*/
241 changes: 241 additions & 0 deletions include/hw/xen/interface/arch-x86/xen-x86_64.h
@@ -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:
*/
398 changes: 398 additions & 0 deletions include/hw/xen/interface/arch-x86/xen.h
@@ -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:
*/
388 changes: 388 additions & 0 deletions include/hw/xen/interface/event_channel.h
@@ -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:
*/
143 changes: 143 additions & 0 deletions include/hw/xen/interface/features.h
@@ -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:
*/
650 changes: 650 additions & 0 deletions include/hw/xen/interface/grant_table.h

Large diffs are not rendered by default.

395 changes: 395 additions & 0 deletions include/hw/xen/interface/hvm/hvm_op.h
@@ -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:
*/