提交 8a6b8708 编写于 作者: A Anthony Liguori

Merge remote-tracking branch 'sstabellini/for_anthony' into staging

* sstabellini/for_anthony:
  xen: introduce an event channel for buffered io event notifications
  xen-mapcache: don't unmap locked entry during mapcache invalidation
  Xen, mapcache: Fix the compute of the size of bucket.
  xen: handle backend deletion from xenstore
  Xen: Add xen-apic support and hook it up.
  Xen: basic HVM MSI injection support.
...@@ -239,7 +239,7 @@ QEMU_CFLAGS += $(VNC_PNG_CFLAGS) ...@@ -239,7 +239,7 @@ QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
obj-$(CONFIG_XEN) += xen-all.o xen_machine_pv.o xen_domainbuild.o xen-mapcache.o obj-$(CONFIG_XEN) += xen-all.o xen_machine_pv.o xen_domainbuild.o xen-mapcache.o
obj-$(CONFIG_NO_XEN) += xen-stub.o obj-$(CONFIG_NO_XEN) += xen-stub.o
obj-i386-$(CONFIG_XEN) += xen_platform.o obj-i386-$(CONFIG_XEN) += xen_platform.o xen_apic.o
# Inter-VM PCI shared memory # Inter-VM PCI shared memory
CONFIG_IVSHMEM = CONFIG_IVSHMEM =
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "sysbus.h" #include "sysbus.h"
#include "sysemu.h" #include "sysemu.h"
#include "kvm.h" #include "kvm.h"
#include "xen.h"
#include "blockdev.h" #include "blockdev.h"
#include "ui/qemu-spice.h" #include "ui/qemu-spice.h"
#include "memory.h" #include "memory.h"
...@@ -891,9 +892,12 @@ static DeviceState *apic_init(void *env, uint8_t apic_id) ...@@ -891,9 +892,12 @@ static DeviceState *apic_init(void *env, uint8_t apic_id)
if (kvm_irqchip_in_kernel()) { if (kvm_irqchip_in_kernel()) {
dev = qdev_create(NULL, "kvm-apic"); dev = qdev_create(NULL, "kvm-apic");
} else if (xen_enabled()) {
dev = qdev_create(NULL, "xen-apic");
} else { } else {
dev = qdev_create(NULL, "apic"); dev = qdev_create(NULL, "apic");
} }
qdev_prop_set_uint8(dev, "id", apic_id); qdev_prop_set_uint8(dev, "id", apic_id);
qdev_prop_set_ptr(dev, "cpu_env", env); qdev_prop_set_ptr(dev, "cpu_env", env);
qdev_init_nofail(dev); qdev_init_nofail(dev);
...@@ -912,6 +916,10 @@ static DeviceState *apic_init(void *env, uint8_t apic_id) ...@@ -912,6 +916,10 @@ static DeviceState *apic_init(void *env, uint8_t apic_id)
msi_supported = true; msi_supported = true;
} }
if (xen_enabled()) {
msi_supported = true;
}
return dev; return dev;
} }
......
...@@ -34,6 +34,7 @@ static inline int xen_enabled(void) ...@@ -34,6 +34,7 @@ static inline int xen_enabled(void)
int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num); int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num);
void xen_piix3_set_irq(void *opaque, int irq_num, int level); void xen_piix3_set_irq(void *opaque, int irq_num, int level);
void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len); void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len);
void xen_hvm_inject_msi(uint64_t addr, uint32_t data);
void xen_cmos_set_s3_resume(void *opaque, int irq, int level); void xen_cmos_set_s3_resume(void *opaque, int irq, int level);
qemu_irq *xen_interrupt_controller_init(void); qemu_irq *xen_interrupt_controller_init(void);
......
/*
* Xen basic APIC support
*
* Copyright (c) 2012 Citrix
*
* Authors:
* Wei Liu <wei.liu2@citrix.com>
*
* 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 "hw/apic_internal.h"
#include "hw/msi.h"
#include "xen.h"
static uint64_t xen_apic_mem_read(void *opaque, target_phys_addr_t addr,
unsigned size)
{
return ~(uint64_t)0;
}
static void xen_apic_mem_write(void *opaque, target_phys_addr_t addr,
uint64_t data, unsigned size)
{
if (size != sizeof(uint32_t)) {
fprintf(stderr, "Xen: APIC write data size = %d, invalid\n", size);
return;
}
xen_hvm_inject_msi(addr, data);
}
static const MemoryRegionOps xen_apic_io_ops = {
.read = xen_apic_mem_read,
.write = xen_apic_mem_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};
static void xen_apic_init(APICCommonState *s)
{
memory_region_init_io(&s->io_memory, &xen_apic_io_ops, s, "xen-apic-msi",
MSI_SPACE_SIZE);
}
static void xen_apic_set_base(APICCommonState *s, uint64_t val)
{
}
static void xen_apic_set_tpr(APICCommonState *s, uint8_t val)
{
}
static uint8_t xen_apic_get_tpr(APICCommonState *s)
{
return 0;
}
static void xen_apic_vapic_base_update(APICCommonState *s)
{
}
static void xen_apic_external_nmi(APICCommonState *s)
{
}
static void xen_apic_class_init(ObjectClass *klass, void *data)
{
APICCommonClass *k = APIC_COMMON_CLASS(klass);
k->init = xen_apic_init;
k->set_base = xen_apic_set_base;
k->set_tpr = xen_apic_set_tpr;
k->get_tpr = xen_apic_get_tpr;
k->vapic_base_update = xen_apic_vapic_base_update;
k->external_nmi = xen_apic_external_nmi;
}
static TypeInfo xen_apic_info = {
.name = "xen-apic",
.parent = TYPE_APIC_COMMON,
.instance_size = sizeof(APICCommonState),
.class_init = xen_apic_class_init,
};
static void xen_apic_register_types(void)
{
type_register_static(&xen_apic_info);
}
type_init(xen_apic_register_types)
...@@ -592,7 +592,7 @@ static void xenstore_update_be(char *watch, char *type, int dom, ...@@ -592,7 +592,7 @@ static void xenstore_update_be(char *watch, char *type, int dom,
struct XenDevOps *ops) struct XenDevOps *ops)
{ {
struct XenDevice *xendev; struct XenDevice *xendev;
char path[XEN_BUFSIZE], *dom0; char path[XEN_BUFSIZE], *dom0, *bepath;
unsigned int len, dev; unsigned int len, dev;
dom0 = xs_get_domain_path(xenstore, 0); dom0 = xs_get_domain_path(xenstore, 0);
...@@ -611,15 +611,16 @@ static void xenstore_update_be(char *watch, char *type, int dom, ...@@ -611,15 +611,16 @@ static void xenstore_update_be(char *watch, char *type, int dom,
return; return;
} }
if (0) {
/* FIXME: detect devices being deleted from xenstore ... */
xen_be_del_xendev(dom, dev);
}
xendev = xen_be_get_xendev(type, dom, dev, ops); xendev = xen_be_get_xendev(type, dom, dev, ops);
if (xendev != NULL) { if (xendev != NULL) {
xen_be_backend_changed(xendev, path); bepath = xs_read(xenstore, 0, xendev->be, &len);
xen_be_check_state(xendev); if (bepath == NULL) {
xen_be_del_xendev(dom, dev);
} else {
free(bepath);
xen_be_backend_changed(xendev, path);
xen_be_check_state(xendev);
}
} }
} }
......
...@@ -745,6 +745,10 @@ static int blk_free(struct XenDevice *xendev) ...@@ -745,6 +745,10 @@ static int blk_free(struct XenDevice *xendev)
struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
struct ioreq *ioreq; struct ioreq *ioreq;
if (blkdev->bs || blkdev->sring) {
blk_disconnect(xendev);
}
while (!QLIST_EMPTY(&blkdev->freelist)) { while (!QLIST_EMPTY(&blkdev->freelist)) {
ioreq = QLIST_FIRST(&blkdev->freelist); ioreq = QLIST_FIRST(&blkdev->freelist);
QLIST_REMOVE(ioreq, list); QLIST_REMOVE(ioreq, list);
......
...@@ -59,6 +59,9 @@ static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu) ...@@ -59,6 +59,9 @@ static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
} }
# define FMT_ioreq_size "u" # define FMT_ioreq_size "u"
#endif #endif
#ifndef HVM_PARAM_BUFIOREQ_EVTCHN
#define HVM_PARAM_BUFIOREQ_EVTCHN 26
#endif
#define BUFFER_IO_MAX_DELAY 100 #define BUFFER_IO_MAX_DELAY 100
...@@ -77,6 +80,8 @@ typedef struct XenIOState { ...@@ -77,6 +80,8 @@ typedef struct XenIOState {
QEMUTimer *buffered_io_timer; QEMUTimer *buffered_io_timer;
/* the evtchn port for polling the notification, */ /* the evtchn port for polling the notification, */
evtchn_port_t *ioreq_local_port; evtchn_port_t *ioreq_local_port;
/* evtchn local port for buffered io */
evtchn_port_t bufioreq_local_port;
/* the evtchn fd for polling */ /* the evtchn fd for polling */
XenEvtchn xce_handle; XenEvtchn xce_handle;
/* which vcpu we are serving */ /* which vcpu we are serving */
...@@ -122,6 +127,11 @@ void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len) ...@@ -122,6 +127,11 @@ void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
} }
} }
void xen_hvm_inject_msi(uint64_t addr, uint32_t data)
{
xc_hvm_inject_msi(xen_xc, xen_domid, addr, data);
}
static void xen_suspend_notifier(Notifier *notifier, void *data) static void xen_suspend_notifier(Notifier *notifier, void *data)
{ {
xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 3); xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 3);
...@@ -624,6 +634,12 @@ static ioreq_t *cpu_get_ioreq(XenIOState *state) ...@@ -624,6 +634,12 @@ static ioreq_t *cpu_get_ioreq(XenIOState *state)
evtchn_port_t port; evtchn_port_t port;
port = xc_evtchn_pending(state->xce_handle); port = xc_evtchn_pending(state->xce_handle);
if (port == state->bufioreq_local_port) {
qemu_mod_timer(state->buffered_io_timer,
BUFFER_IO_MAX_DELAY + qemu_get_clock_ms(rt_clock));
return NULL;
}
if (port != -1) { if (port != -1) {
for (i = 0; i < smp_cpus; i++) { for (i = 0; i < smp_cpus; i++) {
if (state->ioreq_local_port[i] == port) { if (state->ioreq_local_port[i] == port) {
...@@ -772,16 +788,18 @@ static void handle_ioreq(ioreq_t *req) ...@@ -772,16 +788,18 @@ static void handle_ioreq(ioreq_t *req)
} }
} }
static void handle_buffered_iopage(XenIOState *state) static int handle_buffered_iopage(XenIOState *state)
{ {
buf_ioreq_t *buf_req = NULL; buf_ioreq_t *buf_req = NULL;
ioreq_t req; ioreq_t req;
int qw; int qw;
if (!state->buffered_io_page) { if (!state->buffered_io_page) {
return; return 0;
} }
memset(&req, 0x00, sizeof(req));
while (state->buffered_io_page->read_pointer != state->buffered_io_page->write_pointer) { while (state->buffered_io_page->read_pointer != state->buffered_io_page->write_pointer) {
buf_req = &state->buffered_io_page->buf_ioreq[ buf_req = &state->buffered_io_page->buf_ioreq[
state->buffered_io_page->read_pointer % IOREQ_BUFFER_SLOT_NUM]; state->buffered_io_page->read_pointer % IOREQ_BUFFER_SLOT_NUM];
...@@ -806,15 +824,21 @@ static void handle_buffered_iopage(XenIOState *state) ...@@ -806,15 +824,21 @@ static void handle_buffered_iopage(XenIOState *state)
xen_mb(); xen_mb();
state->buffered_io_page->read_pointer += qw ? 2 : 1; state->buffered_io_page->read_pointer += qw ? 2 : 1;
} }
return req.count;
} }
static void handle_buffered_io(void *opaque) static void handle_buffered_io(void *opaque)
{ {
XenIOState *state = opaque; XenIOState *state = opaque;
handle_buffered_iopage(state); if (handle_buffered_iopage(state)) {
qemu_mod_timer(state->buffered_io_timer, qemu_mod_timer(state->buffered_io_timer,
BUFFER_IO_MAX_DELAY + qemu_get_clock_ms(rt_clock)); BUFFER_IO_MAX_DELAY + qemu_get_clock_ms(rt_clock));
} else {
qemu_del_timer(state->buffered_io_timer);
xc_evtchn_unmask(state->xce_handle, state->bufioreq_local_port);
}
} }
static void cpu_handle_ioreq(void *opaque) static void cpu_handle_ioreq(void *opaque)
...@@ -944,7 +968,6 @@ static void xen_main_loop_prepare(XenIOState *state) ...@@ -944,7 +968,6 @@ static void xen_main_loop_prepare(XenIOState *state)
state->buffered_io_timer = qemu_new_timer_ms(rt_clock, handle_buffered_io, state->buffered_io_timer = qemu_new_timer_ms(rt_clock, handle_buffered_io,
state); state);
qemu_mod_timer(state->buffered_io_timer, qemu_get_clock_ms(rt_clock));
if (evtchn_fd != -1) { if (evtchn_fd != -1) {
qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, state); qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, state);
...@@ -1045,6 +1068,7 @@ int xen_hvm_init(void) ...@@ -1045,6 +1068,7 @@ int xen_hvm_init(void)
{ {
int i, rc; int i, rc;
unsigned long ioreq_pfn; unsigned long ioreq_pfn;
unsigned long bufioreq_evtchn;
XenIOState *state; XenIOState *state;
state = g_malloc0(sizeof (XenIOState)); state = g_malloc0(sizeof (XenIOState));
...@@ -1097,6 +1121,20 @@ int xen_hvm_init(void) ...@@ -1097,6 +1121,20 @@ int xen_hvm_init(void)
state->ioreq_local_port[i] = rc; state->ioreq_local_port[i] = rc;
} }
rc = xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_EVTCHN,
&bufioreq_evtchn);
if (rc < 0) {
fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN\n");
return -1;
}
rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
(uint32_t)bufioreq_evtchn);
if (rc == -1) {
fprintf(stderr, "bind interdomain ioctl error %d\n", errno);
return -1;
}
state->bufioreq_local_port = rc;
/* Init RAM management */ /* Init RAM management */
xen_map_cache_init(xen_phys_offset_to_gaddr, state); xen_map_cache_init(xen_phys_offset_to_gaddr, state);
xen_ram_init(ram_size); xen_ram_init(ram_size);
......
...@@ -216,12 +216,14 @@ tryagain: ...@@ -216,12 +216,14 @@ tryagain:
} }
/* size is always a multiple of MCACHE_BUCKET_SIZE */ /* size is always a multiple of MCACHE_BUCKET_SIZE */
if ((address_offset + (__size % MCACHE_BUCKET_SIZE)) > MCACHE_BUCKET_SIZE) if (size) {
__size += MCACHE_BUCKET_SIZE; __size = size + address_offset;
if (__size % MCACHE_BUCKET_SIZE) if (__size % MCACHE_BUCKET_SIZE) {
__size += MCACHE_BUCKET_SIZE - (__size % MCACHE_BUCKET_SIZE); __size += MCACHE_BUCKET_SIZE - (__size % MCACHE_BUCKET_SIZE);
if (!__size) }
} else {
__size = MCACHE_BUCKET_SIZE; __size = MCACHE_BUCKET_SIZE;
}
entry = &mapcache->entry[address_index % mapcache->nr_buckets]; entry = &mapcache->entry[address_index % mapcache->nr_buckets];
...@@ -385,6 +387,9 @@ void xen_invalidate_map_cache(void) ...@@ -385,6 +387,9 @@ void xen_invalidate_map_cache(void)
if (entry->vaddr_base == NULL) { if (entry->vaddr_base == NULL) {
continue; continue;
} }
if (entry->lock > 0) {
continue;
}
if (munmap(entry->vaddr_base, entry->size) != 0) { if (munmap(entry->vaddr_base, entry->size) != 0) {
perror("unmap fails"); perror("unmap fails");
......
...@@ -29,6 +29,10 @@ void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len) ...@@ -29,6 +29,10 @@ void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int len)
{ {
} }
void xen_hvm_inject_msi(uint64_t addr, uint32_t data)
{
}
void xen_cmos_set_s3_resume(void *opaque, int irq, int level) void xen_cmos_set_s3_resume(void *opaque, int irq, int level)
{ {
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册