[PATCH 6/8] kvm tools: Add PPC64 PCI Host Bridge

2011-12-05 Thread Matt Evans
This provides the PCI bridge, definitions for the address layout of the windows
and wires in IRQs.  Once PCI devices are all registered, they are enumerated and
DT nodes generated for each.

Signed-off-by: Matt Evans m...@ozlabs.org
---
 tools/kvm/powerpc/include/kvm/kvm-arch.h |3 +
 tools/kvm/powerpc/irq.c  |   17 +-
 tools/kvm/powerpc/kvm.c  |   11 +
 tools/kvm/powerpc/spapr.h|8 +
 tools/kvm/powerpc/spapr_pci.c|  429 ++
 tools/kvm/powerpc/spapr_pci.h|   38 +++
 6 files changed, 504 insertions(+), 2 deletions(-)
 create mode 100644 tools/kvm/powerpc/spapr_pci.c
 create mode 100644 tools/kvm/powerpc/spapr_pci.h

diff --git a/tools/kvm/powerpc/include/kvm/kvm-arch.h 
b/tools/kvm/powerpc/include/kvm/kvm-arch.h
index ae811e9..ba374f5 100644
--- a/tools/kvm/powerpc/include/kvm/kvm-arch.h
+++ b/tools/kvm/powerpc/include/kvm/kvm-arch.h
@@ -40,6 +40,8 @@
  */
 #define KVM_PCI_MMIO_AREA  0x100
 
+struct spapr_phb;
+
 struct kvm {
int sys_fd; /* For system ioctls(), i.e. 
/dev/kvm */
int vm_fd;  /* For VM ioctls() */
@@ -66,6 +68,7 @@ struct kvm {
unsigned long   initrd_size;
const char  *name;
struct icp_state*icp;
+   struct spapr_phb*phb;
 };
 
 #endif /* KVM__KVM_ARCH_H */
diff --git a/tools/kvm/powerpc/irq.c b/tools/kvm/powerpc/irq.c
index 80c972a..134db8f 100644
--- a/tools/kvm/powerpc/irq.c
+++ b/tools/kvm/powerpc/irq.c
@@ -21,14 +21,27 @@
 #include stddef.h
 #include stdlib.h
 
+#include kvm/pci.h
+
 #include xics.h
+#include spapr_pci.h
 
 #define XICS_IRQS   1024
 
+static int pci_devs = 0;
+
 int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line)
 {
-   fprintf(stderr, irq__register_device(%d, [%d], [%d], [%d]\n,
-   dev, *num, *pin, *line);
+   if (pci_devs = PCI_MAX_DEVICES)
+   die(Hit PCI device limit!\n);
+
+   *num = pci_devs++;
+
+   *pin = 1;
+   /* Have I said how nasty I find this?  Line should be dontcare... PHB
+* should determine which CPU/XICS IRQ to fire.
+*/
+   *line = xics_alloc_irqnum();
return 0;
 }
 
diff --git a/tools/kvm/powerpc/kvm.c b/tools/kvm/powerpc/kvm.c
index bfd7c3a..353c667 100644
--- a/tools/kvm/powerpc/kvm.c
+++ b/tools/kvm/powerpc/kvm.c
@@ -16,6 +16,7 @@
 
 #include spapr.h
 #include spapr_hvcons.h
+#include spapr_pci.h
 
 #include linux/kvm.h
 
@@ -166,6 +167,11 @@ void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, 
const char *hugetlbfs_
register_core_rtas();
/* Now that hypercalls are initialised, register a couple for the 
console: */
spapr_hvcons_init();
+   spapr_create_phb(kvm, pci, SPAPR_PCI_BUID,
+SPAPR_PCI_MEM_WIN_ADDR,
+SPAPR_PCI_MEM_WIN_SIZE,
+SPAPR_PCI_IO_WIN_ADDR,
+SPAPR_PCI_IO_WIN_SIZE);
 }
 
 void kvm__irq_trigger(struct kvm *kvm, int irq)
@@ -420,6 +426,11 @@ static void setup_fdt(struct kvm *kvm)
_FDT(fdt_finish(fdt));
 
_FDT(fdt_open_into(fdt, fdt_dest, FDT_MAX_SIZE));
+
+   /* PCI */
+   if (spapr_populate_pci_devices(kvm, PHANDLE_XICP, fdt_dest))
+   die(Fail populating PCI device nodes);
+
_FDT(fdt_add_mem_rsv(fdt_dest, kvm-rtas_gra, kvm-rtas_size));
_FDT(fdt_pack(fdt_dest));
 }
diff --git a/tools/kvm/powerpc/spapr.h b/tools/kvm/powerpc/spapr.h
index 4e5d7bd..902496d 100644
--- a/tools/kvm/powerpc/spapr.h
+++ b/tools/kvm/powerpc/spapr.h
@@ -305,4 +305,12 @@ target_ulong spapr_rtas_call(struct kvm_cpu *vcpu,
  uint32_t token, uint32_t nargs, target_ulong args,
  uint32_t nret, target_ulong rets);
 
+#define SPAPR_PCI_BUID  0x8002001ULL
+#define SPAPR_PCI_MEM_WIN_ADDR  (KVM_MMIO_START + 0xA000)
+#define SPAPR_PCI_MEM_WIN_SIZE  0x2000
+#define SPAPR_PCI_IO_WIN_ADDR   (KVM_MMIO_START + 0x8000)
+/* This, to me, is odd... 32MB of I/O?  Some PHBs are set up like this.
+ * Anything ever use  64K? :P */
+#define SPAPR_PCI_IO_WIN_SIZE  0x200
+
 #endif /* !defined (__HW_SPAPR_H__) */
diff --git a/tools/kvm/powerpc/spapr_pci.c b/tools/kvm/powerpc/spapr_pci.c
new file mode 100644
index 000..233c42c
--- /dev/null
+++ b/tools/kvm/powerpc/spapr_pci.c
@@ -0,0 +1,429 @@
+/*
+ * SPAPR PHB emulation, RTAS interface to PCI config space, device tree nodes
+ * for enumerated devices.
+ *
+ * Borrowed heavily from QEMU's spapr_pci.c,
+ * Copyright (c) 2011 Alexey Kardashevskiy, IBM Corporation.
+ * Copyright (c) 2011 David Gibson, IBM Corporation.
+ *
+ * Modifications copyright 2011 Matt Evans m...@ozlabs.org, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public 

[PATCH 6/8] kvm tools: Add PPC64 PCI Host Bridge

2011-12-05 Thread Matt Evans
This provides the PCI bridge, definitions for the address layout of the windows
and wires in IRQs.  Once PCI devices are all registered, they are enumerated and
DT nodes generated for each.

Signed-off-by: Matt Evans m...@ozlabs.org
---
 tools/kvm/powerpc/include/kvm/kvm-arch.h |3 +
 tools/kvm/powerpc/irq.c  |   17 +-
 tools/kvm/powerpc/kvm.c  |   11 +
 tools/kvm/powerpc/spapr.h|8 +
 tools/kvm/powerpc/spapr_pci.c|  429 ++
 tools/kvm/powerpc/spapr_pci.h|   38 +++
 6 files changed, 504 insertions(+), 2 deletions(-)
 create mode 100644 tools/kvm/powerpc/spapr_pci.c
 create mode 100644 tools/kvm/powerpc/spapr_pci.h

diff --git a/tools/kvm/powerpc/include/kvm/kvm-arch.h 
b/tools/kvm/powerpc/include/kvm/kvm-arch.h
index ae811e9..ba374f5 100644
--- a/tools/kvm/powerpc/include/kvm/kvm-arch.h
+++ b/tools/kvm/powerpc/include/kvm/kvm-arch.h
@@ -40,6 +40,8 @@
  */
 #define KVM_PCI_MMIO_AREA  0x100
 
+struct spapr_phb;
+
 struct kvm {
int sys_fd; /* For system ioctls(), i.e. 
/dev/kvm */
int vm_fd;  /* For VM ioctls() */
@@ -66,6 +68,7 @@ struct kvm {
unsigned long   initrd_size;
const char  *name;
struct icp_state*icp;
+   struct spapr_phb*phb;
 };
 
 #endif /* KVM__KVM_ARCH_H */
diff --git a/tools/kvm/powerpc/irq.c b/tools/kvm/powerpc/irq.c
index 80c972a..134db8f 100644
--- a/tools/kvm/powerpc/irq.c
+++ b/tools/kvm/powerpc/irq.c
@@ -21,14 +21,27 @@
 #include stddef.h
 #include stdlib.h
 
+#include kvm/pci.h
+
 #include xics.h
+#include spapr_pci.h
 
 #define XICS_IRQS   1024
 
+static int pci_devs = 0;
+
 int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line)
 {
-   fprintf(stderr, irq__register_device(%d, [%d], [%d], [%d]\n,
-   dev, *num, *pin, *line);
+   if (pci_devs = PCI_MAX_DEVICES)
+   die(Hit PCI device limit!\n);
+
+   *num = pci_devs++;
+
+   *pin = 1;
+   /* Have I said how nasty I find this?  Line should be dontcare... PHB
+* should determine which CPU/XICS IRQ to fire.
+*/
+   *line = xics_alloc_irqnum();
return 0;
 }
 
diff --git a/tools/kvm/powerpc/kvm.c b/tools/kvm/powerpc/kvm.c
index bfd7c3a..353c667 100644
--- a/tools/kvm/powerpc/kvm.c
+++ b/tools/kvm/powerpc/kvm.c
@@ -16,6 +16,7 @@
 
 #include spapr.h
 #include spapr_hvcons.h
+#include spapr_pci.h
 
 #include linux/kvm.h
 
@@ -166,6 +167,11 @@ void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, 
const char *hugetlbfs_
register_core_rtas();
/* Now that hypercalls are initialised, register a couple for the 
console: */
spapr_hvcons_init();
+   spapr_create_phb(kvm, pci, SPAPR_PCI_BUID,
+SPAPR_PCI_MEM_WIN_ADDR,
+SPAPR_PCI_MEM_WIN_SIZE,
+SPAPR_PCI_IO_WIN_ADDR,
+SPAPR_PCI_IO_WIN_SIZE);
 }
 
 void kvm__irq_trigger(struct kvm *kvm, int irq)
@@ -420,6 +426,11 @@ static void setup_fdt(struct kvm *kvm)
_FDT(fdt_finish(fdt));
 
_FDT(fdt_open_into(fdt, fdt_dest, FDT_MAX_SIZE));
+
+   /* PCI */
+   if (spapr_populate_pci_devices(kvm, PHANDLE_XICP, fdt_dest))
+   die(Fail populating PCI device nodes);
+
_FDT(fdt_add_mem_rsv(fdt_dest, kvm-rtas_gra, kvm-rtas_size));
_FDT(fdt_pack(fdt_dest));
 }
diff --git a/tools/kvm/powerpc/spapr.h b/tools/kvm/powerpc/spapr.h
index 4e5d7bd..902496d 100644
--- a/tools/kvm/powerpc/spapr.h
+++ b/tools/kvm/powerpc/spapr.h
@@ -305,4 +305,12 @@ target_ulong spapr_rtas_call(struct kvm_cpu *vcpu,
  uint32_t token, uint32_t nargs, target_ulong args,
  uint32_t nret, target_ulong rets);
 
+#define SPAPR_PCI_BUID  0x8002001ULL
+#define SPAPR_PCI_MEM_WIN_ADDR  (KVM_MMIO_START + 0xA000)
+#define SPAPR_PCI_MEM_WIN_SIZE  0x2000
+#define SPAPR_PCI_IO_WIN_ADDR   (KVM_MMIO_START + 0x8000)
+/* This, to me, is odd... 32MB of I/O?  Some PHBs are set up like this.
+ * Anything ever use  64K? :P */
+#define SPAPR_PCI_IO_WIN_SIZE  0x200
+
 #endif /* !defined (__HW_SPAPR_H__) */
diff --git a/tools/kvm/powerpc/spapr_pci.c b/tools/kvm/powerpc/spapr_pci.c
new file mode 100644
index 000..233c42c
--- /dev/null
+++ b/tools/kvm/powerpc/spapr_pci.c
@@ -0,0 +1,429 @@
+/*
+ * SPAPR PHB emulation, RTAS interface to PCI config space, device tree nodes
+ * for enumerated devices.
+ *
+ * Borrowed heavily from QEMU's spapr_pci.c,
+ * Copyright (c) 2011 Alexey Kardashevskiy, IBM Corporation.
+ * Copyright (c) 2011 David Gibson, IBM Corporation.
+ *
+ * Modifications copyright 2011 Matt Evans m...@ozlabs.org, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public