Re: [Qemu-devel] [PATCH V2 02/10] Introduce HostPCIDevice to access a pci device on the host.

2011-10-24 Thread Anthony PERARD
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.

2011-10-20 Thread Stefano Stabellini
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.

2011-10-19 Thread Anthony PERARD
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);