Xen 2016/01/21
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABAgAGBQJWoQ5KAAoJEIlPj0hw4a6QP6sP/01U66Fv7ZzqxnV6U/6hJkOG X11S6KUHVdNoLyMB4RCyOV/zsF16ODZ9A1PI+qeq/1Po4zNLASWYAdWR7OinCiis ad5QGmHY2JmzLm2x8ivWZR1ZqQ+PTRWFH7eEFEROaI/IEyG1wL4bTkMLB0L6Ih74 SMnMJg3Rkl8XhxdvVuE5JZ4f4ZTyPIk+0daMXIH9Q58XspblVNRjKAbotjte/zrj XmCIxVfu29NOIKD3F1n0Cw29OqCuyofbxWHk+SwT68fM8M8KcdnX1WGmfOXylXod JP0j2NRN07LgMfJv1K+QXPSNlFOZAMlzzXpOAnbb2AJceTTMMwTdkQb6aahFfMEL eyWabU+ZI8gemFePgWWdOipkrqtWlGvdyFLKLv42CR9jhVGNck8SBt01njLcOEsf TZjsuzPVxMmQvSYr7xcZgIFKwWkt3yUpOAKl6KS5PlerIezpJ1MtmB1ZmFF+Caui kGpC1tfIgdu3VHdlqASlc50BsAeqTdGzXI+KxTE/6raOnn+aUVIXrUzcdgV+Tgby 52Fd9y83X65RXIgasNIvNpUEX+jc7FYdrBaO2graSBzpCWAzituyypOk4WEpHxIn da64hN9Z3i4BzLDZtaC05B8A0iWpckLOwbVWK1zblsdiJJAaOFVAU9cNl2Plxm8j cy8WC0FdEqLZxXpU0deB =+hRh -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/sstabellini/tags/xen-20160121' into staging Xen 2016/01/21 # gpg: Signature made Thu 21 Jan 2016 16:58:50 GMT using RSA key ID 70E1AE90 # gpg: Good signature from "Stefano Stabellini <stefano.stabellini@eu.citrix.com>" * remotes/sstabellini/tags/xen-20160121: Xen PCI passthru: convert to realize() Add Error **errp for xen_pt_config_init() Add Error **errp for xen_pt_setup_vga() Add Error **errp for xen_host_pci_device_get() Xen: use qemu_strtoul instead of strtol Change xen_host_pci_sysfs_path() to return void xen-pvdevice: convert to realize() xen-hvm: Clean up xen_ram_alloc() error handling xen-hvm: Clean up xen_hvm_init() error handling xenfb.c: avoid expensive loops when prod <= out_cons MAINTAINERS: update Xen files Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
0b0571dd24
@ -273,9 +273,12 @@ F: */xen*
|
|||||||
F: hw/char/xen_console.c
|
F: hw/char/xen_console.c
|
||||||
F: hw/display/xenfb.c
|
F: hw/display/xenfb.c
|
||||||
F: hw/net/xen_nic.c
|
F: hw/net/xen_nic.c
|
||||||
|
F: hw/block/xen_*
|
||||||
F: hw/xen/
|
F: hw/xen/
|
||||||
F: hw/xenpv/
|
F: hw/xenpv/
|
||||||
|
F: hw/i386/xen/
|
||||||
F: include/hw/xen/
|
F: include/hw/xen/
|
||||||
|
F: include/sysemu/xen-mapcache.h
|
||||||
|
|
||||||
Hosts:
|
Hosts:
|
||||||
------
|
------
|
||||||
|
8
exec.c
8
exec.c
@ -1510,6 +1510,7 @@ static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp)
|
|||||||
RAMBlock *block;
|
RAMBlock *block;
|
||||||
RAMBlock *last_block = NULL;
|
RAMBlock *last_block = NULL;
|
||||||
ram_addr_t old_ram_size, new_ram_size;
|
ram_addr_t old_ram_size, new_ram_size;
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
old_ram_size = last_ram_offset() >> TARGET_PAGE_BITS;
|
old_ram_size = last_ram_offset() >> TARGET_PAGE_BITS;
|
||||||
|
|
||||||
@ -1519,7 +1520,12 @@ static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp)
|
|||||||
if (!new_block->host) {
|
if (!new_block->host) {
|
||||||
if (xen_enabled()) {
|
if (xen_enabled()) {
|
||||||
xen_ram_alloc(new_block->offset, new_block->max_length,
|
xen_ram_alloc(new_block->offset, new_block->max_length,
|
||||||
new_block->mr);
|
new_block->mr, &err);
|
||||||
|
if (err) {
|
||||||
|
error_propagate(errp, err);
|
||||||
|
qemu_mutex_unlock_ramlist();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
new_block->host = phys_mem_alloc(new_block->max_length,
|
new_block->host = phys_mem_alloc(new_block->max_length,
|
||||||
&new_block->mr->align);
|
&new_block->mr->align);
|
||||||
|
@ -789,8 +789,9 @@ static void xenfb_handle_events(struct XenFB *xenfb)
|
|||||||
|
|
||||||
prod = page->out_prod;
|
prod = page->out_prod;
|
||||||
out_cons = page->out_cons;
|
out_cons = page->out_cons;
|
||||||
if (prod == out_cons)
|
if (prod - out_cons >= XENFB_OUT_RING_LEN) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
xen_rmb(); /* ensure we see ring contents up to prod */
|
xen_rmb(); /* ensure we see ring contents up to prod */
|
||||||
for (cons = out_cons; cons != prod; cons++) {
|
for (cons = out_cons; cons != prod; cons++) {
|
||||||
union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
|
union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
|
||||||
|
@ -121,9 +121,8 @@ static void pc_init1(MachineState *machine,
|
|||||||
pcms->below_4g_mem_size = machine->ram_size;
|
pcms->below_4g_mem_size = machine->ram_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xen_enabled() && xen_hvm_init(pcms, &ram_memory) != 0) {
|
if (xen_enabled()) {
|
||||||
fprintf(stderr, "xen hardware virtual machine initialisation failed\n");
|
xen_hvm_init(pcms, &ram_memory);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pc_cpus_init(pcms);
|
pc_cpus_init(pcms);
|
||||||
|
@ -111,9 +111,8 @@ static void pc_q35_init(MachineState *machine)
|
|||||||
pcms->below_4g_mem_size = machine->ram_size;
|
pcms->below_4g_mem_size = machine->ram_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xen_enabled() && xen_hvm_init(pcms, &ram_memory) != 0) {
|
if (xen_enabled()) {
|
||||||
fprintf(stderr, "xen hardware virtual machine initialisation failed\n");
|
xen_hvm_init(pcms, &ram_memory);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pc_cpus_init(pcms);
|
pc_cpus_init(pcms);
|
||||||
|
@ -69,14 +69,16 @@ static const MemoryRegionOps xen_pv_mmio_ops = {
|
|||||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int xen_pv_init(PCIDevice *pci_dev)
|
static void xen_pv_realize(PCIDevice *pci_dev, Error **errp)
|
||||||
{
|
{
|
||||||
XenPVDevice *d = XEN_PV_DEVICE(pci_dev);
|
XenPVDevice *d = XEN_PV_DEVICE(pci_dev);
|
||||||
uint8_t *pci_conf;
|
uint8_t *pci_conf;
|
||||||
|
|
||||||
/* device-id property must always be supplied */
|
/* device-id property must always be supplied */
|
||||||
if (d->device_id == 0xffff)
|
if (d->device_id == 0xffff) {
|
||||||
return -1;
|
error_setg(errp, "Device ID invalid, it must always be supplied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pci_conf = pci_dev->config;
|
pci_conf = pci_dev->config;
|
||||||
|
|
||||||
@ -97,8 +99,6 @@ static int xen_pv_init(PCIDevice *pci_dev)
|
|||||||
|
|
||||||
pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
|
pci_register_bar(pci_dev, 1, PCI_BASE_ADDRESS_MEM_PREFETCH,
|
||||||
&d->mmio);
|
&d->mmio);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Property xen_pv_props[] = {
|
static Property xen_pv_props[] = {
|
||||||
@ -114,7 +114,7 @@ static void xen_pv_class_init(ObjectClass *klass, void *data)
|
|||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||||
|
|
||||||
k->init = xen_pv_init;
|
k->realize = xen_pv_realize;
|
||||||
k->class_id = PCI_CLASS_SYSTEM_OTHER;
|
k->class_id = PCI_CLASS_SYSTEM_OTHER;
|
||||||
dc->desc = "Xen PV Device";
|
dc->desc = "Xen PV Device";
|
||||||
dc->props = xen_pv_props;
|
dc->props = xen_pv_props;
|
||||||
|
@ -31,25 +31,20 @@
|
|||||||
#define IORESOURCE_PREFETCH 0x00001000 /* No side effects */
|
#define IORESOURCE_PREFETCH 0x00001000 /* No side effects */
|
||||||
#define IORESOURCE_MEM_64 0x00100000
|
#define IORESOURCE_MEM_64 0x00100000
|
||||||
|
|
||||||
static int xen_host_pci_sysfs_path(const XenHostPCIDevice *d,
|
static void xen_host_pci_sysfs_path(const XenHostPCIDevice *d,
|
||||||
const char *name, char *buf, ssize_t size)
|
const char *name, char *buf, ssize_t size)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = snprintf(buf, size, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/%s",
|
rc = snprintf(buf, size, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/%s",
|
||||||
d->domain, d->bus, d->dev, d->func, name);
|
d->domain, d->bus, d->dev, d->func, name);
|
||||||
|
assert(rc >= 0 && rc < size);
|
||||||
if (rc >= size || rc < 0) {
|
|
||||||
/* The output is truncated, or some other error was encountered */
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This size should be enough to read the first 7 lines of a resource file */
|
/* This size should be enough to read the first 7 lines of a resource file */
|
||||||
#define XEN_HOST_PCI_RESOURCE_BUFFER_SIZE 400
|
#define XEN_HOST_PCI_RESOURCE_BUFFER_SIZE 400
|
||||||
static int xen_host_pci_get_resource(XenHostPCIDevice *d)
|
static void xen_host_pci_get_resource(XenHostPCIDevice *d, Error **errp)
|
||||||
{
|
{
|
||||||
int i, rc, fd;
|
int i, rc, fd;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
@ -58,25 +53,22 @@ static int xen_host_pci_get_resource(XenHostPCIDevice *d)
|
|||||||
char *endptr, *s;
|
char *endptr, *s;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
|
|
||||||
rc = xen_host_pci_sysfs_path(d, "resource", path, sizeof (path));
|
xen_host_pci_sysfs_path(d, "resource", path, sizeof(path));
|
||||||
if (rc) {
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
fd = open(path, O_RDONLY);
|
fd = open(path, O_RDONLY);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
XEN_HOST_PCI_LOG("Error: Can't open %s: %s\n", path, strerror(errno));
|
error_setg_file_open(errp, errno, path);
|
||||||
return -errno;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
rc = read(fd, &buf, sizeof (buf) - 1);
|
rc = read(fd, &buf, sizeof(buf) - 1);
|
||||||
if (rc < 0 && errno != EINTR) {
|
if (rc < 0 && errno != EINTR) {
|
||||||
rc = -errno;
|
error_setg_errno(errp, errno, "read err");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} while (rc < 0);
|
} while (rc < 0);
|
||||||
buf[rc] = 0;
|
buf[rc] = 0;
|
||||||
rc = 0;
|
|
||||||
|
|
||||||
s = buf;
|
s = buf;
|
||||||
for (i = 0; i < PCI_NUM_REGIONS; i++) {
|
for (i = 0; i < PCI_NUM_REGIONS; i++) {
|
||||||
@ -129,70 +121,69 @@ static int xen_host_pci_get_resource(XenHostPCIDevice *d)
|
|||||||
d->rom.bus_flags = flags & IORESOURCE_BITS;
|
d->rom.bus_flags = flags & IORESOURCE_BITS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i != PCI_NUM_REGIONS) {
|
if (i != PCI_NUM_REGIONS) {
|
||||||
/* Invalid format or input to short */
|
error_setg(errp, "Invalid format or input too short: %s", buf);
|
||||||
rc = -ENODEV;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
close(fd);
|
close(fd);
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This size should be enough to read a long from a file */
|
/* This size should be enough to read a long from a file */
|
||||||
#define XEN_HOST_PCI_GET_VALUE_BUFFER_SIZE 22
|
#define XEN_HOST_PCI_GET_VALUE_BUFFER_SIZE 22
|
||||||
static int xen_host_pci_get_value(XenHostPCIDevice *d, const char *name,
|
static void xen_host_pci_get_value(XenHostPCIDevice *d, const char *name,
|
||||||
unsigned int *pvalue, int base)
|
unsigned int *pvalue, int base, Error **errp)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
char buf[XEN_HOST_PCI_GET_VALUE_BUFFER_SIZE];
|
char buf[XEN_HOST_PCI_GET_VALUE_BUFFER_SIZE];
|
||||||
int fd, rc;
|
int fd, rc;
|
||||||
unsigned long value;
|
unsigned long value;
|
||||||
char *endptr;
|
const char *endptr;
|
||||||
|
|
||||||
|
xen_host_pci_sysfs_path(d, name, path, sizeof(path));
|
||||||
|
|
||||||
rc = xen_host_pci_sysfs_path(d, name, path, sizeof (path));
|
|
||||||
if (rc) {
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
fd = open(path, O_RDONLY);
|
fd = open(path, O_RDONLY);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
XEN_HOST_PCI_LOG("Error: Can't open %s: %s\n", path, strerror(errno));
|
error_setg_file_open(errp, errno, path);
|
||||||
return -errno;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
rc = read(fd, &buf, sizeof (buf) - 1);
|
rc = read(fd, &buf, sizeof(buf) - 1);
|
||||||
if (rc < 0 && errno != EINTR) {
|
if (rc < 0 && errno != EINTR) {
|
||||||
rc = -errno;
|
error_setg_errno(errp, errno, "read err");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} while (rc < 0);
|
} while (rc < 0);
|
||||||
|
|
||||||
buf[rc] = 0;
|
buf[rc] = 0;
|
||||||
value = strtol(buf, &endptr, base);
|
rc = qemu_strtoul(buf, &endptr, base, &value);
|
||||||
if (endptr == buf || *endptr != '\n') {
|
if (!rc) {
|
||||||
rc = -1;
|
assert(value <= UINT_MAX);
|
||||||
} else if ((value == LONG_MIN || value == LONG_MAX) && errno == ERANGE) {
|
|
||||||
rc = -errno;
|
|
||||||
} else {
|
|
||||||
rc = 0;
|
|
||||||
*pvalue = value;
|
*pvalue = value;
|
||||||
|
} else {
|
||||||
|
error_setg_errno(errp, -rc, "failed to parse value '%s'", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
close(fd);
|
close(fd);
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int xen_host_pci_get_hex_value(XenHostPCIDevice *d,
|
static inline void xen_host_pci_get_hex_value(XenHostPCIDevice *d,
|
||||||
const char *name,
|
const char *name,
|
||||||
unsigned int *pvalue)
|
unsigned int *pvalue,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
return xen_host_pci_get_value(d, name, pvalue, 16);
|
xen_host_pci_get_value(d, name, pvalue, 16, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int xen_host_pci_get_dec_value(XenHostPCIDevice *d,
|
static inline void xen_host_pci_get_dec_value(XenHostPCIDevice *d,
|
||||||
const char *name,
|
const char *name,
|
||||||
unsigned int *pvalue)
|
unsigned int *pvalue,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
return xen_host_pci_get_value(d, name, pvalue, 10);
|
xen_host_pci_get_value(d, name, pvalue, 10, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool xen_host_pci_dev_is_virtfn(XenHostPCIDevice *d)
|
static bool xen_host_pci_dev_is_virtfn(XenHostPCIDevice *d)
|
||||||
@ -200,26 +191,21 @@ static bool xen_host_pci_dev_is_virtfn(XenHostPCIDevice *d)
|
|||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
|
|
||||||
if (xen_host_pci_sysfs_path(d, "physfn", path, sizeof (path))) {
|
xen_host_pci_sysfs_path(d, "physfn", path, sizeof(path));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !stat(path, &buf);
|
return !stat(path, &buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xen_host_pci_config_open(XenHostPCIDevice *d)
|
static void xen_host_pci_config_open(XenHostPCIDevice *d, Error **errp)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = xen_host_pci_sysfs_path(d, "config", path, sizeof (path));
|
xen_host_pci_sysfs_path(d, "config", path, sizeof(path));
|
||||||
if (rc) {
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
d->config_fd = open(path, O_RDWR);
|
d->config_fd = open(path, O_RDWR);
|
||||||
if (d->config_fd < 0) {
|
if (d->config_fd == -1) {
|
||||||
return -errno;
|
error_setg_file_open(errp, errno, path);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xen_host_pci_config_read(XenHostPCIDevice *d,
|
static int xen_host_pci_config_read(XenHostPCIDevice *d,
|
||||||
@ -341,11 +327,12 @@ int xen_host_pci_find_ext_cap_offset(XenHostPCIDevice *d, uint32_t cap)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int xen_host_pci_device_get(XenHostPCIDevice *d, uint16_t domain,
|
void xen_host_pci_device_get(XenHostPCIDevice *d, uint16_t domain,
|
||||||
uint8_t bus, uint8_t dev, uint8_t func)
|
uint8_t bus, uint8_t dev, uint8_t func,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
unsigned int v;
|
unsigned int v;
|
||||||
int rc = 0;
|
Error *err = NULL;
|
||||||
|
|
||||||
d->config_fd = -1;
|
d->config_fd = -1;
|
||||||
d->domain = domain;
|
d->domain = domain;
|
||||||
@ -353,43 +340,51 @@ int xen_host_pci_device_get(XenHostPCIDevice *d, uint16_t domain,
|
|||||||
d->dev = dev;
|
d->dev = dev;
|
||||||
d->func = func;
|
d->func = func;
|
||||||
|
|
||||||
rc = xen_host_pci_config_open(d);
|
xen_host_pci_config_open(d, &err);
|
||||||
if (rc) {
|
if (err) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
rc = xen_host_pci_get_resource(d);
|
|
||||||
if (rc) {
|
xen_host_pci_get_resource(d, &err);
|
||||||
|
if (err) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
rc = xen_host_pci_get_hex_value(d, "vendor", &v);
|
|
||||||
if (rc) {
|
xen_host_pci_get_hex_value(d, "vendor", &v, &err);
|
||||||
|
if (err) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
d->vendor_id = v;
|
d->vendor_id = v;
|
||||||
rc = xen_host_pci_get_hex_value(d, "device", &v);
|
|
||||||
if (rc) {
|
xen_host_pci_get_hex_value(d, "device", &v, &err);
|
||||||
|
if (err) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
d->device_id = v;
|
d->device_id = v;
|
||||||
rc = xen_host_pci_get_dec_value(d, "irq", &v);
|
|
||||||
if (rc) {
|
xen_host_pci_get_dec_value(d, "irq", &v, &err);
|
||||||
|
if (err) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
d->irq = v;
|
d->irq = v;
|
||||||
rc = xen_host_pci_get_hex_value(d, "class", &v);
|
|
||||||
if (rc) {
|
xen_host_pci_get_hex_value(d, "class", &v, &err);
|
||||||
|
if (err) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
d->class_code = v;
|
d->class_code = v;
|
||||||
|
|
||||||
d->is_virtfn = xen_host_pci_dev_is_virtfn(d);
|
d->is_virtfn = xen_host_pci_dev_is_virtfn(d);
|
||||||
|
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
error_propagate(errp, err);
|
||||||
|
|
||||||
if (d->config_fd >= 0) {
|
if (d->config_fd >= 0) {
|
||||||
close(d->config_fd);
|
close(d->config_fd);
|
||||||
d->config_fd = -1;
|
d->config_fd = -1;
|
||||||
}
|
}
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool xen_host_pci_device_closed(XenHostPCIDevice *d)
|
bool xen_host_pci_device_closed(XenHostPCIDevice *d)
|
||||||
|
@ -36,8 +36,9 @@ typedef struct XenHostPCIDevice {
|
|||||||
int config_fd;
|
int config_fd;
|
||||||
} XenHostPCIDevice;
|
} XenHostPCIDevice;
|
||||||
|
|
||||||
int xen_host_pci_device_get(XenHostPCIDevice *d, uint16_t domain,
|
void xen_host_pci_device_get(XenHostPCIDevice *d, uint16_t domain,
|
||||||
uint8_t bus, uint8_t dev, uint8_t func);
|
uint8_t bus, uint8_t dev, uint8_t func,
|
||||||
|
Error **errp);
|
||||||
void xen_host_pci_device_put(XenHostPCIDevice *pci_dev);
|
void xen_host_pci_device_put(XenHostPCIDevice *pci_dev);
|
||||||
bool xen_host_pci_device_closed(XenHostPCIDevice *d);
|
bool xen_host_pci_device_closed(XenHostPCIDevice *d);
|
||||||
|
|
||||||
|
@ -760,13 +760,14 @@ static void xen_pt_destroy(PCIDevice *d) {
|
|||||||
}
|
}
|
||||||
/* init */
|
/* init */
|
||||||
|
|
||||||
static int xen_pt_initfn(PCIDevice *d)
|
static void xen_pt_realize(PCIDevice *d, Error **errp)
|
||||||
{
|
{
|
||||||
XenPCIPassthroughState *s = XEN_PT_DEVICE(d);
|
XenPCIPassthroughState *s = XEN_PT_DEVICE(d);
|
||||||
int rc = 0;
|
int i, rc = 0;
|
||||||
uint8_t machine_irq = 0, scratch;
|
uint8_t machine_irq = 0, scratch;
|
||||||
uint16_t cmd = 0;
|
uint16_t cmd = 0;
|
||||||
int pirq = XEN_PT_UNASSIGNED_PIRQ;
|
int pirq = XEN_PT_UNASSIGNED_PIRQ;
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
/* register real device */
|
/* register real device */
|
||||||
XEN_PT_LOG(d, "Assigning real physical device %02x:%02x.%d"
|
XEN_PT_LOG(d, "Assigning real physical device %02x:%02x.%d"
|
||||||
@ -774,12 +775,14 @@ static int xen_pt_initfn(PCIDevice *d)
|
|||||||
s->hostaddr.bus, s->hostaddr.slot, s->hostaddr.function,
|
s->hostaddr.bus, s->hostaddr.slot, s->hostaddr.function,
|
||||||
s->dev.devfn);
|
s->dev.devfn);
|
||||||
|
|
||||||
rc = xen_host_pci_device_get(&s->real_device,
|
xen_host_pci_device_get(&s->real_device,
|
||||||
s->hostaddr.domain, s->hostaddr.bus,
|
s->hostaddr.domain, s->hostaddr.bus,
|
||||||
s->hostaddr.slot, s->hostaddr.function);
|
s->hostaddr.slot, s->hostaddr.function,
|
||||||
if (rc) {
|
&err);
|
||||||
XEN_PT_ERR(d, "Failed to \"open\" the real pci device. rc: %i\n", rc);
|
if (err) {
|
||||||
return -1;
|
error_append_hint(&err, "Failed to \"open\" the real pci device");
|
||||||
|
error_propagate(errp, err);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->is_virtfn = s->real_device.is_virtfn;
|
s->is_virtfn = s->real_device.is_virtfn;
|
||||||
@ -799,16 +802,19 @@ static int xen_pt_initfn(PCIDevice *d)
|
|||||||
if ((s->real_device.domain == 0) && (s->real_device.bus == 0) &&
|
if ((s->real_device.domain == 0) && (s->real_device.bus == 0) &&
|
||||||
(s->real_device.dev == 2) && (s->real_device.func == 0)) {
|
(s->real_device.dev == 2) && (s->real_device.func == 0)) {
|
||||||
if (!is_igd_vga_passthrough(&s->real_device)) {
|
if (!is_igd_vga_passthrough(&s->real_device)) {
|
||||||
XEN_PT_ERR(d, "Need to enable igd-passthru if you're trying"
|
error_setg(errp, "Need to enable igd-passthru if you're trying"
|
||||||
" to passthrough IGD GFX.\n");
|
" to passthrough IGD GFX");
|
||||||
xen_host_pci_device_put(&s->real_device);
|
xen_host_pci_device_put(&s->real_device);
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xen_pt_setup_vga(s, &s->real_device) < 0) {
|
xen_pt_setup_vga(s, &s->real_device, &err);
|
||||||
XEN_PT_ERR(d, "Setup VGA BIOS of passthrough GFX failed!\n");
|
if (err) {
|
||||||
|
error_append_hint(&err, "Setup VGA BIOS of passthrough"
|
||||||
|
" GFX failed");
|
||||||
|
error_propagate(errp, err);
|
||||||
xen_host_pci_device_put(&s->real_device);
|
xen_host_pci_device_put(&s->real_device);
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register ISA bridge for passthrough GFX. */
|
/* Register ISA bridge for passthrough GFX. */
|
||||||
@ -819,29 +825,30 @@ static int xen_pt_initfn(PCIDevice *d)
|
|||||||
xen_pt_register_regions(s, &cmd);
|
xen_pt_register_regions(s, &cmd);
|
||||||
|
|
||||||
/* reinitialize each config register to be emulated */
|
/* reinitialize each config register to be emulated */
|
||||||
rc = xen_pt_config_init(s);
|
xen_pt_config_init(s, &err);
|
||||||
if (rc) {
|
if (err) {
|
||||||
XEN_PT_ERR(d, "PCI Config space initialisation failed.\n");
|
error_append_hint(&err, "PCI Config space initialisation failed");
|
||||||
|
error_report_err(err);
|
||||||
|
rc = -1;
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bind interrupt */
|
/* Bind interrupt */
|
||||||
rc = xen_host_pci_get_byte(&s->real_device, PCI_INTERRUPT_PIN, &scratch);
|
rc = xen_host_pci_get_byte(&s->real_device, PCI_INTERRUPT_PIN, &scratch);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
XEN_PT_ERR(d, "Failed to read PCI_INTERRUPT_PIN! (rc:%d)\n", rc);
|
error_setg_errno(errp, errno, "Failed to read PCI_INTERRUPT_PIN");
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
if (!scratch) {
|
if (!scratch) {
|
||||||
XEN_PT_LOG(d, "no pin interrupt\n");
|
error_setg(errp, "no pin interrupt");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
machine_irq = s->real_device.irq;
|
machine_irq = s->real_device.irq;
|
||||||
rc = xc_physdev_map_pirq(xen_xc, xen_domid, machine_irq, &pirq);
|
rc = xc_physdev_map_pirq(xen_xc, xen_domid, machine_irq, &pirq);
|
||||||
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
XEN_PT_ERR(d, "Mapping machine irq %u to pirq %i failed, (err: %d)\n",
|
error_setg_errno(errp, errno, "Mapping machine irq %u to"
|
||||||
machine_irq, pirq, errno);
|
" pirq %i failed", machine_irq, pirq);
|
||||||
|
|
||||||
/* Disable PCI intx assertion (turn on bit10 of devctl) */
|
/* Disable PCI intx assertion (turn on bit10 of devctl) */
|
||||||
cmd |= PCI_COMMAND_INTX_DISABLE;
|
cmd |= PCI_COMMAND_INTX_DISABLE;
|
||||||
@ -862,8 +869,8 @@ static int xen_pt_initfn(PCIDevice *d)
|
|||||||
PCI_SLOT(d->devfn),
|
PCI_SLOT(d->devfn),
|
||||||
e_intx);
|
e_intx);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
XEN_PT_ERR(d, "Binding of interrupt %i failed! (err: %d)\n",
|
error_setg_errno(errp, errno, "Binding of interrupt %u failed",
|
||||||
e_intx, errno);
|
e_intx);
|
||||||
|
|
||||||
/* Disable PCI intx assertion (turn on bit10 of devctl) */
|
/* Disable PCI intx assertion (turn on bit10 of devctl) */
|
||||||
cmd |= PCI_COMMAND_INTX_DISABLE;
|
cmd |= PCI_COMMAND_INTX_DISABLE;
|
||||||
@ -871,8 +878,8 @@ static int xen_pt_initfn(PCIDevice *d)
|
|||||||
|
|
||||||
if (xen_pt_mapped_machine_irq[machine_irq] == 0) {
|
if (xen_pt_mapped_machine_irq[machine_irq] == 0) {
|
||||||
if (xc_physdev_unmap_pirq(xen_xc, xen_domid, machine_irq)) {
|
if (xc_physdev_unmap_pirq(xen_xc, xen_domid, machine_irq)) {
|
||||||
XEN_PT_ERR(d, "Unmapping of machine interrupt %i failed!"
|
error_setg_errno(errp, errno, "Unmapping of machine"
|
||||||
" (err: %d)\n", machine_irq, errno);
|
" interrupt %u failed", machine_irq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s->machine_irq = 0;
|
s->machine_irq = 0;
|
||||||
@ -885,14 +892,14 @@ out:
|
|||||||
|
|
||||||
rc = xen_host_pci_get_word(&s->real_device, PCI_COMMAND, &val);
|
rc = xen_host_pci_get_word(&s->real_device, PCI_COMMAND, &val);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
XEN_PT_ERR(d, "Failed to read PCI_COMMAND! (rc: %d)\n", rc);
|
error_setg_errno(errp, errno, "Failed to read PCI_COMMAND");
|
||||||
goto err_out;
|
goto err_out;
|
||||||
} else {
|
} else {
|
||||||
val |= cmd;
|
val |= cmd;
|
||||||
rc = xen_host_pci_set_word(&s->real_device, PCI_COMMAND, val);
|
rc = xen_host_pci_set_word(&s->real_device, PCI_COMMAND, val);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
XEN_PT_ERR(d, "Failed to write PCI_COMMAND val=0x%x!(rc: %d)\n",
|
error_setg_errno(errp, errno, "Failed to write PCI_COMMAND"
|
||||||
val, rc);
|
" val = 0x%x", val);
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -902,15 +909,19 @@ out:
|
|||||||
memory_listener_register(&s->io_listener, &address_space_io);
|
memory_listener_register(&s->io_listener, &address_space_io);
|
||||||
s->listener_set = true;
|
s->listener_set = true;
|
||||||
XEN_PT_LOG(d,
|
XEN_PT_LOG(d,
|
||||||
"Real physical device %02x:%02x.%d registered successfully!\n",
|
"Real physical device %02x:%02x.%d registered successfully\n",
|
||||||
s->hostaddr.bus, s->hostaddr.slot, s->hostaddr.function);
|
s->hostaddr.bus, s->hostaddr.slot, s->hostaddr.function);
|
||||||
|
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
err_out:
|
err_out:
|
||||||
|
for (i = 0; i < PCI_ROM_SLOT; i++) {
|
||||||
|
object_unparent(OBJECT(&s->bar[i]));
|
||||||
|
}
|
||||||
|
object_unparent(OBJECT(&s->rom));
|
||||||
|
|
||||||
xen_pt_destroy(d);
|
xen_pt_destroy(d);
|
||||||
assert(rc);
|
assert(rc);
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xen_pt_unregister_device(PCIDevice *d)
|
static void xen_pt_unregister_device(PCIDevice *d)
|
||||||
@ -929,7 +940,7 @@ static void xen_pci_passthrough_class_init(ObjectClass *klass, void *data)
|
|||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||||
|
|
||||||
k->init = xen_pt_initfn;
|
k->realize = xen_pt_realize;
|
||||||
k->exit = xen_pt_unregister_device;
|
k->exit = xen_pt_unregister_device;
|
||||||
k->config_read = xen_pt_pci_read_config;
|
k->config_read = xen_pt_pci_read_config;
|
||||||
k->config_write = xen_pt_pci_write_config;
|
k->config_write = xen_pt_pci_write_config;
|
||||||
|
@ -230,7 +230,7 @@ struct XenPCIPassthroughState {
|
|||||||
bool listener_set;
|
bool listener_set;
|
||||||
};
|
};
|
||||||
|
|
||||||
int xen_pt_config_init(XenPCIPassthroughState *s);
|
void xen_pt_config_init(XenPCIPassthroughState *s, Error **errp);
|
||||||
void xen_pt_config_delete(XenPCIPassthroughState *s);
|
void xen_pt_config_delete(XenPCIPassthroughState *s);
|
||||||
XenPTRegGroup *xen_pt_find_reg_grp(XenPCIPassthroughState *s, uint32_t address);
|
XenPTRegGroup *xen_pt_find_reg_grp(XenPCIPassthroughState *s, uint32_t address);
|
||||||
XenPTReg *xen_pt_find_reg(XenPTRegGroup *reg_grp, uint32_t address);
|
XenPTReg *xen_pt_find_reg(XenPTRegGroup *reg_grp, uint32_t address);
|
||||||
@ -330,5 +330,6 @@ static inline bool is_igd_vga_passthrough(XenHostPCIDevice *dev)
|
|||||||
}
|
}
|
||||||
int xen_pt_register_vga_regions(XenHostPCIDevice *dev);
|
int xen_pt_register_vga_regions(XenHostPCIDevice *dev);
|
||||||
int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev);
|
int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev);
|
||||||
int xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev);
|
void xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev,
|
||||||
|
Error **errp);
|
||||||
#endif /* !XEN_PT_H */
|
#endif /* !XEN_PT_H */
|
||||||
|
@ -1887,8 +1887,9 @@ static uint8_t find_cap_offset(XenPCIPassthroughState *s, uint8_t cap)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xen_pt_config_reg_init(XenPCIPassthroughState *s,
|
static void xen_pt_config_reg_init(XenPCIPassthroughState *s,
|
||||||
XenPTRegGroup *reg_grp, XenPTRegInfo *reg)
|
XenPTRegGroup *reg_grp, XenPTRegInfo *reg,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
XenPTReg *reg_entry;
|
XenPTReg *reg_entry;
|
||||||
uint32_t data = 0;
|
uint32_t data = 0;
|
||||||
@ -1907,12 +1908,13 @@ static int xen_pt_config_reg_init(XenPCIPassthroughState *s,
|
|||||||
reg_grp->base_offset + reg->offset, &data);
|
reg_grp->base_offset + reg->offset, &data);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
g_free(reg_entry);
|
g_free(reg_entry);
|
||||||
return rc;
|
error_setg(errp, "Init emulate register fail");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (data == XEN_PT_INVALID_REG) {
|
if (data == XEN_PT_INVALID_REG) {
|
||||||
/* free unused BAR register entry */
|
/* free unused BAR register entry */
|
||||||
g_free(reg_entry);
|
g_free(reg_entry);
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
/* Sync up the data to dev.config */
|
/* Sync up the data to dev.config */
|
||||||
offset = reg_grp->base_offset + reg->offset;
|
offset = reg_grp->base_offset + reg->offset;
|
||||||
@ -1930,7 +1932,8 @@ static int xen_pt_config_reg_init(XenPCIPassthroughState *s,
|
|||||||
if (rc) {
|
if (rc) {
|
||||||
/* Serious issues when we cannot read the host values! */
|
/* Serious issues when we cannot read the host values! */
|
||||||
g_free(reg_entry);
|
g_free(reg_entry);
|
||||||
return rc;
|
error_setg(errp, "Cannot read host values");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
/* Set bits in emu_mask are the ones we emulate. The dev.config shall
|
/* Set bits in emu_mask are the ones we emulate. The dev.config shall
|
||||||
* contain the emulated view of the guest - therefore we flip the mask
|
* contain the emulated view of the guest - therefore we flip the mask
|
||||||
@ -1955,10 +1958,10 @@ static int xen_pt_config_reg_init(XenPCIPassthroughState *s,
|
|||||||
val = data;
|
val = data;
|
||||||
|
|
||||||
if (val & ~size_mask) {
|
if (val & ~size_mask) {
|
||||||
XEN_PT_ERR(&s->dev,"Offset 0x%04x:0x%04x expands past register size(%d)!\n",
|
error_setg(errp, "Offset 0x%04x:0x%04x expands past"
|
||||||
offset, val, reg->size);
|
" register size (%d)", offset, val, reg->size);
|
||||||
g_free(reg_entry);
|
g_free(reg_entry);
|
||||||
return -ENXIO;
|
return;
|
||||||
}
|
}
|
||||||
/* This could be just pci_set_long as we don't modify the bits
|
/* This could be just pci_set_long as we don't modify the bits
|
||||||
* past reg->size, but in case this routine is run in parallel or the
|
* past reg->size, but in case this routine is run in parallel or the
|
||||||
@ -1978,13 +1981,12 @@ static int xen_pt_config_reg_init(XenPCIPassthroughState *s,
|
|||||||
}
|
}
|
||||||
/* list add register entry */
|
/* list add register entry */
|
||||||
QLIST_INSERT_HEAD(®_grp->reg_tbl_list, reg_entry, entries);
|
QLIST_INSERT_HEAD(®_grp->reg_tbl_list, reg_entry, entries);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int xen_pt_config_init(XenPCIPassthroughState *s)
|
void xen_pt_config_init(XenPCIPassthroughState *s, Error **errp)
|
||||||
{
|
{
|
||||||
int i, rc;
|
int i, rc;
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
QLIST_INIT(&s->reg_grps);
|
QLIST_INIT(&s->reg_grps);
|
||||||
|
|
||||||
@ -2027,11 +2029,12 @@ int xen_pt_config_init(XenPCIPassthroughState *s)
|
|||||||
reg_grp_offset,
|
reg_grp_offset,
|
||||||
®_grp_entry->size);
|
®_grp_entry->size);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
XEN_PT_LOG(&s->dev, "Failed to initialize %d/%ld, type=0x%x, rc:%d\n",
|
error_setg(&err, "Failed to initialize %d/%zu, type = 0x%x,"
|
||||||
i, ARRAY_SIZE(xen_pt_emu_reg_grps),
|
" rc: %d", i, ARRAY_SIZE(xen_pt_emu_reg_grps),
|
||||||
xen_pt_emu_reg_grps[i].grp_type, rc);
|
xen_pt_emu_reg_grps[i].grp_type, rc);
|
||||||
|
error_propagate(errp, err);
|
||||||
xen_pt_config_delete(s);
|
xen_pt_config_delete(s);
|
||||||
return rc;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2039,24 +2042,24 @@ int xen_pt_config_init(XenPCIPassthroughState *s)
|
|||||||
if (xen_pt_emu_reg_grps[i].emu_regs) {
|
if (xen_pt_emu_reg_grps[i].emu_regs) {
|
||||||
int j = 0;
|
int j = 0;
|
||||||
XenPTRegInfo *regs = xen_pt_emu_reg_grps[i].emu_regs;
|
XenPTRegInfo *regs = xen_pt_emu_reg_grps[i].emu_regs;
|
||||||
|
|
||||||
/* initialize capability register */
|
/* initialize capability register */
|
||||||
for (j = 0; regs->size != 0; j++, regs++) {
|
for (j = 0; regs->size != 0; j++, regs++) {
|
||||||
/* initialize capability register */
|
xen_pt_config_reg_init(s, reg_grp_entry, regs, &err);
|
||||||
rc = xen_pt_config_reg_init(s, reg_grp_entry, regs);
|
if (err) {
|
||||||
if (rc < 0) {
|
error_append_hint(&err, "Failed to initialize %d/%zu"
|
||||||
XEN_PT_LOG(&s->dev, "Failed to initialize %d/%ld reg 0x%x in grp_type=0x%x (%d/%ld), rc=%d\n",
|
" reg 0x%x in grp_type = 0x%x (%d/%zu)",
|
||||||
j, ARRAY_SIZE(xen_pt_emu_reg_grps[i].emu_regs),
|
j, ARRAY_SIZE(xen_pt_emu_reg_grps[i].emu_regs),
|
||||||
regs->offset, xen_pt_emu_reg_grps[i].grp_type,
|
regs->offset, xen_pt_emu_reg_grps[i].grp_type,
|
||||||
i, ARRAY_SIZE(xen_pt_emu_reg_grps), rc);
|
i, ARRAY_SIZE(xen_pt_emu_reg_grps));
|
||||||
|
error_propagate(errp, err);
|
||||||
xen_pt_config_delete(s);
|
xen_pt_config_delete(s);
|
||||||
return rc;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* delete all emulate register */
|
/* delete all emulate register */
|
||||||
|
@ -161,7 +161,8 @@ struct pci_data {
|
|||||||
uint16_t reserved;
|
uint16_t reserved;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
int xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev)
|
void xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
unsigned char *bios = NULL;
|
unsigned char *bios = NULL;
|
||||||
struct rom_header *rom;
|
struct rom_header *rom;
|
||||||
@ -172,13 +173,14 @@ int xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev)
|
|||||||
struct pci_data *pd = NULL;
|
struct pci_data *pd = NULL;
|
||||||
|
|
||||||
if (!is_igd_vga_passthrough(dev)) {
|
if (!is_igd_vga_passthrough(dev)) {
|
||||||
return -1;
|
error_setg(errp, "Need to enable igd-passthrough");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bios = get_vgabios(s, &bios_size, dev);
|
bios = get_vgabios(s, &bios_size, dev);
|
||||||
if (!bios) {
|
if (!bios) {
|
||||||
XEN_PT_ERR(&s->dev, "VGA: Can't getting VBIOS!\n");
|
error_setg(errp, "VGA: Can't get VBIOS");
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Currently we fixed this address as a primary. */
|
/* Currently we fixed this address as a primary. */
|
||||||
@ -203,7 +205,6 @@ int xen_pt_setup_vga(XenPCIPassthroughState *s, XenHostPCIDevice *dev)
|
|||||||
|
|
||||||
/* Currently we fixed this address as a primary for legacy BIOS. */
|
/* Currently we fixed this address as a primary for legacy BIOS. */
|
||||||
cpu_physical_memory_rw(0xc0000, bios, bios_size, 1);
|
cpu_physical_memory_rw(0xc0000, bios, bios_size, 1);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t igd_read_opregion(XenPCIPassthroughState *s)
|
uint32_t igd_read_opregion(XenPCIPassthroughState *s)
|
||||||
|
@ -39,9 +39,9 @@ qemu_irq *xen_interrupt_controller_init(void);
|
|||||||
void xenstore_store_pv_console_info(int i, struct CharDriverState *chr);
|
void xenstore_store_pv_console_info(int i, struct CharDriverState *chr);
|
||||||
|
|
||||||
#if defined(NEED_CPU_H) && !defined(CONFIG_USER_ONLY)
|
#if defined(NEED_CPU_H) && !defined(CONFIG_USER_ONLY)
|
||||||
int xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory);
|
void xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory);
|
||||||
void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size,
|
void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size,
|
||||||
struct MemoryRegion *mr);
|
struct MemoryRegion *mr, Error **errp);
|
||||||
void xen_modified_memory(ram_addr_t start, ram_addr_t length);
|
void xen_modified_memory(ram_addr_t start, ram_addr_t length);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -30,7 +30,8 @@ void xen_hvm_inject_msi(uint64_t addr, uint32_t data)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr)
|
void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,9 +48,8 @@ void xen_modified_memory(ram_addr_t start, ram_addr_t length)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory)
|
void xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory)
|
||||||
{
|
{
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
|
void qmp_xen_set_global_dirty_log(bool enable, Error **errp)
|
||||||
|
68
xen-hvm.c
68
xen-hvm.c
@ -17,6 +17,7 @@
|
|||||||
#include "qmp-commands.h"
|
#include "qmp-commands.h"
|
||||||
|
|
||||||
#include "sysemu/char.h"
|
#include "sysemu/char.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
#include "qemu/range.h"
|
#include "qemu/range.h"
|
||||||
#include "sysemu/xen-mapcache.h"
|
#include "sysemu/xen-mapcache.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
@ -238,9 +239,9 @@ static void xen_ram_init(PCMachineState *pcms,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr)
|
void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
/* FIXME caller ram_block_add() wants error_setg() on failure */
|
|
||||||
unsigned long nr_pfn;
|
unsigned long nr_pfn;
|
||||||
xen_pfn_t *pfn_list;
|
xen_pfn_t *pfn_list;
|
||||||
int i;
|
int i;
|
||||||
@ -267,7 +268,8 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (xc_domain_populate_physmap_exact(xen_xc, xen_domid, nr_pfn, 0, 0, pfn_list)) {
|
if (xc_domain_populate_physmap_exact(xen_xc, xen_domid, nr_pfn, 0, 0, pfn_list)) {
|
||||||
hw_error("xen: failed to populate ram at " RAM_ADDR_FMT, ram_addr);
|
error_setg(errp, "xen: failed to populate ram at " RAM_ADDR_FMT,
|
||||||
|
ram_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free(pfn_list);
|
g_free(pfn_list);
|
||||||
@ -1189,16 +1191,8 @@ static void xen_wakeup_notifier(Notifier *notifier, void *data)
|
|||||||
xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 0);
|
xc_set_hvm_param(xen_xc, xen_domid, HVM_PARAM_ACPI_S_STATE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return 0 means OK, or -1 means critical issue -- will exit(1) */
|
void xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory)
|
||||||
int xen_hvm_init(PCMachineState *pcms,
|
|
||||||
MemoryRegion **ram_memory)
|
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* FIXME Returns -1 without cleaning up on some errors (harmless
|
|
||||||
* as long as the caller exit()s on error), dies with hw_error()
|
|
||||||
* on others. hw_error() isn't approprate here. Should probably
|
|
||||||
* simply exit() on all errors.
|
|
||||||
*/
|
|
||||||
int i, rc;
|
int i, rc;
|
||||||
xen_pfn_t ioreq_pfn;
|
xen_pfn_t ioreq_pfn;
|
||||||
xen_pfn_t bufioreq_pfn;
|
xen_pfn_t bufioreq_pfn;
|
||||||
@ -1210,19 +1204,19 @@ int xen_hvm_init(PCMachineState *pcms,
|
|||||||
state->xce_handle = xen_xc_evtchn_open(NULL, 0);
|
state->xce_handle = xen_xc_evtchn_open(NULL, 0);
|
||||||
if (state->xce_handle == XC_HANDLER_INITIAL_VALUE) {
|
if (state->xce_handle == XC_HANDLER_INITIAL_VALUE) {
|
||||||
perror("xen: event channel open");
|
perror("xen: event channel open");
|
||||||
return -1;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->xenstore = xs_daemon_open();
|
state->xenstore = xs_daemon_open();
|
||||||
if (state->xenstore == NULL) {
|
if (state->xenstore == NULL) {
|
||||||
perror("xen: xenstore open");
|
perror("xen: xenstore open");
|
||||||
return -1;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = xen_create_ioreq_server(xen_xc, xen_domid, &state->ioservid);
|
rc = xen_create_ioreq_server(xen_xc, xen_domid, &state->ioservid);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
perror("xen: ioreq server create");
|
perror("xen: ioreq server create");
|
||||||
return -1;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->exit.notify = xen_exit_notifier;
|
state->exit.notify = xen_exit_notifier;
|
||||||
@ -1238,8 +1232,9 @@ int xen_hvm_init(PCMachineState *pcms,
|
|||||||
&ioreq_pfn, &bufioreq_pfn,
|
&ioreq_pfn, &bufioreq_pfn,
|
||||||
&bufioreq_evtchn);
|
&bufioreq_evtchn);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
hw_error("failed to get ioreq server info: error %d handle=" XC_INTERFACE_FMT,
|
error_report("failed to get ioreq server info: error %d handle=" XC_INTERFACE_FMT,
|
||||||
errno, xen_xc);
|
errno, xen_xc);
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF("shared page at pfn %lx\n", ioreq_pfn);
|
DPRINTF("shared page at pfn %lx\n", ioreq_pfn);
|
||||||
@ -1249,8 +1244,9 @@ int xen_hvm_init(PCMachineState *pcms,
|
|||||||
state->shared_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
|
state->shared_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
|
||||||
PROT_READ|PROT_WRITE, ioreq_pfn);
|
PROT_READ|PROT_WRITE, ioreq_pfn);
|
||||||
if (state->shared_page == NULL) {
|
if (state->shared_page == NULL) {
|
||||||
hw_error("map shared IO page returned error %d handle=" XC_INTERFACE_FMT,
|
error_report("map shared IO page returned error %d handle=" XC_INTERFACE_FMT,
|
||||||
errno, xen_xc);
|
errno, xen_xc);
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = xen_get_vmport_regs_pfn(xen_xc, xen_domid, &ioreq_pfn);
|
rc = xen_get_vmport_regs_pfn(xen_xc, xen_domid, &ioreq_pfn);
|
||||||
@ -1260,11 +1256,14 @@ int xen_hvm_init(PCMachineState *pcms,
|
|||||||
xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
|
xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE,
|
||||||
PROT_READ|PROT_WRITE, ioreq_pfn);
|
PROT_READ|PROT_WRITE, ioreq_pfn);
|
||||||
if (state->shared_vmport_page == NULL) {
|
if (state->shared_vmport_page == NULL) {
|
||||||
hw_error("map shared vmport IO page returned error %d handle="
|
error_report("map shared vmport IO page returned error %d handle="
|
||||||
XC_INTERFACE_FMT, errno, xen_xc);
|
XC_INTERFACE_FMT, errno, xen_xc);
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
} else if (rc != -ENOSYS) {
|
} else if (rc != -ENOSYS) {
|
||||||
hw_error("get vmport regs pfn returned error %d, rc=%d", errno, rc);
|
error_report("get vmport regs pfn returned error %d, rc=%d",
|
||||||
|
errno, rc);
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->buffered_io_page = xc_map_foreign_range(xen_xc, xen_domid,
|
state->buffered_io_page = xc_map_foreign_range(xen_xc, xen_domid,
|
||||||
@ -1272,7 +1271,8 @@ int xen_hvm_init(PCMachineState *pcms,
|
|||||||
PROT_READ|PROT_WRITE,
|
PROT_READ|PROT_WRITE,
|
||||||
bufioreq_pfn);
|
bufioreq_pfn);
|
||||||
if (state->buffered_io_page == NULL) {
|
if (state->buffered_io_page == NULL) {
|
||||||
hw_error("map buffered IO page returned error %d", errno);
|
error_report("map buffered IO page returned error %d", errno);
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: cpus is empty at this point in init */
|
/* Note: cpus is empty at this point in init */
|
||||||
@ -1280,8 +1280,9 @@ int xen_hvm_init(PCMachineState *pcms,
|
|||||||
|
|
||||||
rc = xen_set_ioreq_server_state(xen_xc, xen_domid, state->ioservid, true);
|
rc = xen_set_ioreq_server_state(xen_xc, xen_domid, state->ioservid, true);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
hw_error("failed to enable ioreq server info: error %d handle=" XC_INTERFACE_FMT,
|
error_report("failed to enable ioreq server info: error %d handle=" XC_INTERFACE_FMT,
|
||||||
errno, xen_xc);
|
errno, xen_xc);
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->ioreq_local_port = g_malloc0(max_cpus * sizeof (evtchn_port_t));
|
state->ioreq_local_port = g_malloc0(max_cpus * sizeof (evtchn_port_t));
|
||||||
@ -1291,8 +1292,8 @@ int xen_hvm_init(PCMachineState *pcms,
|
|||||||
rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
|
rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
|
||||||
xen_vcpu_eport(state->shared_page, i));
|
xen_vcpu_eport(state->shared_page, i));
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
fprintf(stderr, "shared evtchn %d bind error %d\n", i, errno);
|
error_report("shared evtchn %d bind error %d", i, errno);
|
||||||
return -1;
|
goto err;
|
||||||
}
|
}
|
||||||
state->ioreq_local_port[i] = rc;
|
state->ioreq_local_port[i] = rc;
|
||||||
}
|
}
|
||||||
@ -1300,8 +1301,8 @@ int xen_hvm_init(PCMachineState *pcms,
|
|||||||
rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
|
rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid,
|
||||||
bufioreq_evtchn);
|
bufioreq_evtchn);
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
fprintf(stderr, "buffered evtchn bind error %d\n", errno);
|
error_report("buffered evtchn bind error %d", errno);
|
||||||
return -1;
|
goto err;
|
||||||
}
|
}
|
||||||
state->bufioreq_local_port = rc;
|
state->bufioreq_local_port = rc;
|
||||||
|
|
||||||
@ -1324,15 +1325,18 @@ int xen_hvm_init(PCMachineState *pcms,
|
|||||||
|
|
||||||
/* Initialize backend core & drivers */
|
/* Initialize backend core & drivers */
|
||||||
if (xen_be_init() != 0) {
|
if (xen_be_init() != 0) {
|
||||||
fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__);
|
error_report("xen backend core setup failed");
|
||||||
return -1;
|
goto err;
|
||||||
}
|
}
|
||||||
xen_be_register("console", &xen_console_ops);
|
xen_be_register("console", &xen_console_ops);
|
||||||
xen_be_register("vkbd", &xen_kbdmouse_ops);
|
xen_be_register("vkbd", &xen_kbdmouse_ops);
|
||||||
xen_be_register("qdisk", &xen_blkdev_ops);
|
xen_be_register("qdisk", &xen_blkdev_ops);
|
||||||
xen_read_physmap(state);
|
xen_read_physmap(state);
|
||||||
|
return;
|
||||||
|
|
||||||
return 0;
|
err:
|
||||||
|
error_report("xen hardware virtual machine initialisation failed");
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy_hvm_domain(bool reboot)
|
void destroy_hvm_domain(bool reboot)
|
||||||
|
Loading…
Reference in New Issue
Block a user