Re: [Qemu-devel] [PATCH V2 02/10] Introduce HostPCIDevice to access a pci device on the host.
On Thu, Oct 20, 2011 at 11:57, Stefano Stabellini stefano.stabell...@eu.citrix.com wrote: On Wed, 19 Oct 2011, Anthony PERARD wrote: Signed-off-by: Anthony PERARD anthony.per...@citrix.com --- Makefile.target | 1 + hw/host-pci-device.c | 245 ++ hw/host-pci-device.h | 75 +++ 3 files changed, 321 insertions(+), 0 deletions(-) create mode 100644 hw/host-pci-device.c create mode 100644 hw/host-pci-device.h diff --git a/Makefile.target b/Makefile.target index c518103..ca3420d 100644 --- a/Makefile.target +++ b/Makefile.target @@ -209,6 +209,7 @@ obj-$(CONFIG_NO_XEN) += xen-stub.o obj-i386-$(CONFIG_XEN) += xen_platform.o # Xen PCI Passthrough +obj-i386-$(CONFIG_XEN_PCI_PASSTHROUGH) += host-pci-device.o # Inter-VM PCI shared memory CONFIG_IVSHMEM = diff --git a/hw/host-pci-device.c b/hw/host-pci-device.c new file mode 100644 index 000..0f25fcf --- /dev/null +++ b/hw/host-pci-device.c @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2011 Citrix Ltd. + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include qemu-common.h +#include host-pci-device.h + +static int path_to(const HostPCIDevice *d, + const char *name, char *buf, ssize_t size) +{ + return snprintf(buf, size, /sys/bus/pci/devices/%04x:%02x:%02x.%x/%s, + d-domain, d-bus, d-dev, d-func, name); +} + +static int get_resource(HostPCIDevice *d) +{ + int i, rc = 0; + FILE *f; + char path[PATH_MAX]; + unsigned long long start, end, flags, size; + + path_to(d, resource, path, sizeof (path)); + f = fopen(path, r); + if (!f) { + fprintf(stderr, Error: Can't open %s: %s\n, path, strerror(errno)); + return -1; it would be better to return a proper error code, rather than just -1 probably -errno will do it. + } + + for (i = 0; i PCI_NUM_REGIONS; i++) { + if (fscanf(f, %llx %llx %llx, start, end, flags) != 3) { + fprintf(stderr, Error: Syntax error in %s\n, path); + rc = -1; Ditto probably 1 with a define on the top of the file. + break; + } + if (start) { + size = end - start + 1; + } else { + size = 0; + } + + if (i PCI_ROM_SLOT) { + d-io_regions[i].base_addr = start; + d-io_regions[i].size = size; + d-io_regions[i].flags = flags; + } else { + d-rom.base_addr = start; + d-rom.size = size; + d-rom.flags = flags; + } + } + + fclose(f); + return rc; +} [...] + +uint32_t host_pci_find_ext_cap_offset(HostPCIDevice *d, uint32_t cap) +{ + uint32_t header = 0; + int max_cap = 480; + int pos = 0x100; could you used some defined constants here? Yes, I will. + do { + header = host_pci_get_long(d, pos); + /* + * If we have no capabilities, this is indicated by cap ID, + * cap version and next pointer all being 0. + */ + if (header == 0) { + break; + } + + if (PCI_EXT_CAP_ID(header) == cap) { + return pos; + } + + pos = PCI_EXT_CAP_NEXT(header); + if (pos 0x100) { + break; + } + + max_cap--; + } while (max_cap 0); + + return 0; +} -- Anthony PERARD
Re: [Qemu-devel] [PATCH V2 02/10] Introduce HostPCIDevice to access a pci device on the host.
On Wed, 19 Oct 2011, Anthony PERARD wrote: Signed-off-by: Anthony PERARD anthony.per...@citrix.com --- Makefile.target |1 + hw/host-pci-device.c | 245 ++ hw/host-pci-device.h | 75 +++ 3 files changed, 321 insertions(+), 0 deletions(-) create mode 100644 hw/host-pci-device.c create mode 100644 hw/host-pci-device.h diff --git a/Makefile.target b/Makefile.target index c518103..ca3420d 100644 --- a/Makefile.target +++ b/Makefile.target @@ -209,6 +209,7 @@ obj-$(CONFIG_NO_XEN) += xen-stub.o obj-i386-$(CONFIG_XEN) += xen_platform.o # Xen PCI Passthrough +obj-i386-$(CONFIG_XEN_PCI_PASSTHROUGH) += host-pci-device.o # Inter-VM PCI shared memory CONFIG_IVSHMEM = diff --git a/hw/host-pci-device.c b/hw/host-pci-device.c new file mode 100644 index 000..0f25fcf --- /dev/null +++ b/hw/host-pci-device.c @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2011 Citrix Ltd. + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include qemu-common.h +#include host-pci-device.h + +static int path_to(const HostPCIDevice *d, + const char *name, char *buf, ssize_t size) +{ +return snprintf(buf, size, /sys/bus/pci/devices/%04x:%02x:%02x.%x/%s, +d-domain, d-bus, d-dev, d-func, name); +} + +static int get_resource(HostPCIDevice *d) +{ +int i, rc = 0; +FILE *f; +char path[PATH_MAX]; +unsigned long long start, end, flags, size; + +path_to(d, resource, path, sizeof (path)); +f = fopen(path, r); +if (!f) { +fprintf(stderr, Error: Can't open %s: %s\n, path, strerror(errno)); +return -1; it would be better to return a proper error code, rather than just -1 +} + +for (i = 0; i PCI_NUM_REGIONS; i++) { +if (fscanf(f, %llx %llx %llx, start, end, flags) != 3) { +fprintf(stderr, Error: Syntax error in %s\n, path); +rc = -1; Ditto +break; +} +if (start) { +size = end - start + 1; +} else { +size = 0; +} + +if (i PCI_ROM_SLOT) { +d-io_regions[i].base_addr = start; +d-io_regions[i].size = size; +d-io_regions[i].flags = flags; +} else { +d-rom.base_addr = start; +d-rom.size = size; +d-rom.flags = flags; +} +} + +fclose(f); +return rc; +} + +static unsigned long get_value(HostPCIDevice *d, const char *name) +{ +char path[PATH_MAX]; +FILE *f; +unsigned long value; + +path_to(d, name, path, sizeof (path)); +f = fopen(path, r); +if (!f) { +fprintf(stderr, Error: Can't open %s: %s\n, path, strerror(errno)); +return -1; +} +if (fscanf(f, %lx\n, value) != 1) { +fprintf(stderr, Error: Syntax error in %s\n, path); +value = -1; +} +fclose(f); +return value; +} + +static int pci_dev_is_virtfn(HostPCIDevice *d) +{ +int rc; +char path[PATH_MAX]; +struct stat buf; + +path_to(d, physfn, path, sizeof (path)); +rc = !stat(path, buf); + +return rc; +} + +static int host_pci_config_fd(HostPCIDevice *d) +{ +char path[PATH_MAX]; + +if (d-config_fd 0) { +path_to(d, config, path, sizeof (path)); +d-config_fd = open(path, O_RDWR); +if (d-config_fd 0) { +fprintf(stderr, HostPCIDevice: Can not open '%s': %s\n, +path, strerror(errno)); +} +} +return d-config_fd; +} +static int host_pci_config_read(HostPCIDevice *d, int pos, void *buf, int len) +{ +int fd = host_pci_config_fd(d); +int res = 0; + +res = pread(fd, buf, len, pos); +if (res 0) { +fprintf(stderr, host_pci_config: read failed: %s (fd: %i)\n, +strerror(errno), fd); +return -1; +} +return res; +} +static int host_pci_config_write(HostPCIDevice *d, + int pos, const void *buf, int len) +{ +int fd = host_pci_config_fd(d); +int res = 0; + +res = pwrite(fd, buf, len, pos); +if (res 0) { +fprintf(stderr, host_pci_config: write failed: %s\n, +strerror(errno)); +return -1; +} +return res; +} + +uint8_t host_pci_get_byte(HostPCIDevice *d, int pos) +{ + uint8_t buf; + host_pci_config_read(d, pos, buf, 1); + return buf; +} +uint16_t host_pci_get_word(HostPCIDevice *d, int pos) +{ + uint16_t buf; + host_pci_config_read(d, pos, buf, 2); + return le16_to_cpu(buf); +} +uint32_t host_pci_get_long(HostPCIDevice *d, int pos) +{ + uint32_t buf; + host_pci_config_read(d, pos, buf, 4); + return le32_to_cpu(buf); +} +int host_pci_get_block(HostPCIDevice *d,
[Qemu-devel] [PATCH V2 02/10] Introduce HostPCIDevice to access a pci device on the host.
Signed-off-by: Anthony PERARD anthony.per...@citrix.com --- Makefile.target |1 + hw/host-pci-device.c | 245 ++ hw/host-pci-device.h | 75 +++ 3 files changed, 321 insertions(+), 0 deletions(-) create mode 100644 hw/host-pci-device.c create mode 100644 hw/host-pci-device.h diff --git a/Makefile.target b/Makefile.target index c518103..ca3420d 100644 --- a/Makefile.target +++ b/Makefile.target @@ -209,6 +209,7 @@ obj-$(CONFIG_NO_XEN) += xen-stub.o obj-i386-$(CONFIG_XEN) += xen_platform.o # Xen PCI Passthrough +obj-i386-$(CONFIG_XEN_PCI_PASSTHROUGH) += host-pci-device.o # Inter-VM PCI shared memory CONFIG_IVSHMEM = diff --git a/hw/host-pci-device.c b/hw/host-pci-device.c new file mode 100644 index 000..0f25fcf --- /dev/null +++ b/hw/host-pci-device.c @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2011 Citrix Ltd. + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include qemu-common.h +#include host-pci-device.h + +static int path_to(const HostPCIDevice *d, + const char *name, char *buf, ssize_t size) +{ +return snprintf(buf, size, /sys/bus/pci/devices/%04x:%02x:%02x.%x/%s, +d-domain, d-bus, d-dev, d-func, name); +} + +static int get_resource(HostPCIDevice *d) +{ +int i, rc = 0; +FILE *f; +char path[PATH_MAX]; +unsigned long long start, end, flags, size; + +path_to(d, resource, path, sizeof (path)); +f = fopen(path, r); +if (!f) { +fprintf(stderr, Error: Can't open %s: %s\n, path, strerror(errno)); +return -1; +} + +for (i = 0; i PCI_NUM_REGIONS; i++) { +if (fscanf(f, %llx %llx %llx, start, end, flags) != 3) { +fprintf(stderr, Error: Syntax error in %s\n, path); +rc = -1; +break; +} +if (start) { +size = end - start + 1; +} else { +size = 0; +} + +if (i PCI_ROM_SLOT) { +d-io_regions[i].base_addr = start; +d-io_regions[i].size = size; +d-io_regions[i].flags = flags; +} else { +d-rom.base_addr = start; +d-rom.size = size; +d-rom.flags = flags; +} +} + +fclose(f); +return rc; +} + +static unsigned long get_value(HostPCIDevice *d, const char *name) +{ +char path[PATH_MAX]; +FILE *f; +unsigned long value; + +path_to(d, name, path, sizeof (path)); +f = fopen(path, r); +if (!f) { +fprintf(stderr, Error: Can't open %s: %s\n, path, strerror(errno)); +return -1; +} +if (fscanf(f, %lx\n, value) != 1) { +fprintf(stderr, Error: Syntax error in %s\n, path); +value = -1; +} +fclose(f); +return value; +} + +static int pci_dev_is_virtfn(HostPCIDevice *d) +{ +int rc; +char path[PATH_MAX]; +struct stat buf; + +path_to(d, physfn, path, sizeof (path)); +rc = !stat(path, buf); + +return rc; +} + +static int host_pci_config_fd(HostPCIDevice *d) +{ +char path[PATH_MAX]; + +if (d-config_fd 0) { +path_to(d, config, path, sizeof (path)); +d-config_fd = open(path, O_RDWR); +if (d-config_fd 0) { +fprintf(stderr, HostPCIDevice: Can not open '%s': %s\n, +path, strerror(errno)); +} +} +return d-config_fd; +} +static int host_pci_config_read(HostPCIDevice *d, int pos, void *buf, int len) +{ +int fd = host_pci_config_fd(d); +int res = 0; + +res = pread(fd, buf, len, pos); +if (res 0) { +fprintf(stderr, host_pci_config: read failed: %s (fd: %i)\n, +strerror(errno), fd); +return -1; +} +return res; +} +static int host_pci_config_write(HostPCIDevice *d, + int pos, const void *buf, int len) +{ +int fd = host_pci_config_fd(d); +int res = 0; + +res = pwrite(fd, buf, len, pos); +if (res 0) { +fprintf(stderr, host_pci_config: write failed: %s\n, +strerror(errno)); +return -1; +} +return res; +} + +uint8_t host_pci_get_byte(HostPCIDevice *d, int pos) +{ + uint8_t buf; + host_pci_config_read(d, pos, buf, 1); + return buf; +} +uint16_t host_pci_get_word(HostPCIDevice *d, int pos) +{ + uint16_t buf; + host_pci_config_read(d, pos, buf, 2); + return le16_to_cpu(buf); +} +uint32_t host_pci_get_long(HostPCIDevice *d, int pos) +{ + uint32_t buf; + host_pci_config_read(d, pos, buf, 4); + return le32_to_cpu(buf); +} +int host_pci_get_block(HostPCIDevice *d, int pos, uint8_t *buf, int len) +{ + return host_pci_config_read(d, pos, buf, len); +} + +int host_pci_set_byte(HostPCIDevice *d, int pos, uint8_t data) +{ + return host_pci_config_write(d, pos, data, 1); +} +int host_pci_set_word(HostPCIDevice *d, int pos, uint16_t data) +{ + data = cpu_to_le16(data);