2 * libqos PCI bindings for SPAPR
4 * This work is licensed under the terms of the GNU GPL, version 2 or later.
5 * See the COPYING file in the top-level directory.
8 #include "qemu/osdep.h"
10 #include "libqos/pci-spapr.h"
11 #include "libqos/rtas.h"
13 #include "hw/pci/pci_regs.h"
15 #include "qemu-common.h"
16 #include "qemu/host-utils.h"
19 /* From include/hw/pci-host/spapr.h */
21 typedef struct QPCIWindow
{
22 uint64_t pci_base
; /* window address in PCI space */
23 uint64_t size
; /* window size */
26 typedef struct QPCIBusSPAPR
{
28 QGuestAllocator
*alloc
;
32 uint64_t pio_cpu_base
;
35 uint64_t mmio32_cpu_base
;
40 * PCI devices are always little-endian
41 * SPAPR by default is big-endian
42 * so PCI accessors need to swap data endianness
45 static uint8_t qpci_spapr_pio_readb(QPCIBus
*bus
, uint32_t addr
)
47 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
48 return readb(s
->pio_cpu_base
+ addr
);
51 static void qpci_spapr_pio_writeb(QPCIBus
*bus
, uint32_t addr
, uint8_t val
)
53 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
54 writeb(s
->pio_cpu_base
+ addr
, val
);
57 static uint16_t qpci_spapr_pio_readw(QPCIBus
*bus
, uint32_t addr
)
59 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
60 return bswap16(readw(s
->pio_cpu_base
+ addr
));
63 static void qpci_spapr_pio_writew(QPCIBus
*bus
, uint32_t addr
, uint16_t val
)
65 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
66 writew(s
->pio_cpu_base
+ addr
, bswap16(val
));
69 static uint32_t qpci_spapr_pio_readl(QPCIBus
*bus
, uint32_t addr
)
71 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
72 return bswap32(readl(s
->pio_cpu_base
+ addr
));
75 static void qpci_spapr_pio_writel(QPCIBus
*bus
, uint32_t addr
, uint32_t val
)
77 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
78 writel(s
->pio_cpu_base
+ addr
, bswap32(val
));
81 static void qpci_spapr_memread(QPCIBus
*bus
, uint32_t addr
,
82 void *buf
, size_t len
)
84 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
85 memread(s
->mmio32_cpu_base
+ addr
, buf
, len
);
88 static void qpci_spapr_memwrite(QPCIBus
*bus
, uint32_t addr
,
89 const void *buf
, size_t len
)
91 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
92 memwrite(s
->mmio32_cpu_base
+ addr
, buf
, len
);
95 static uint8_t qpci_spapr_config_readb(QPCIBus
*bus
, int devfn
, uint8_t offset
)
97 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
98 uint32_t config_addr
= (devfn
<< 8) | offset
;
99 return qrtas_ibm_read_pci_config(s
->alloc
, s
->buid
, config_addr
, 1);
102 static uint16_t qpci_spapr_config_readw(QPCIBus
*bus
, int devfn
, uint8_t offset
)
104 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
105 uint32_t config_addr
= (devfn
<< 8) | offset
;
106 return qrtas_ibm_read_pci_config(s
->alloc
, s
->buid
, config_addr
, 2);
109 static uint32_t qpci_spapr_config_readl(QPCIBus
*bus
, int devfn
, uint8_t offset
)
111 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
112 uint32_t config_addr
= (devfn
<< 8) | offset
;
113 return qrtas_ibm_read_pci_config(s
->alloc
, s
->buid
, config_addr
, 4);
116 static void qpci_spapr_config_writeb(QPCIBus
*bus
, int devfn
, uint8_t offset
,
119 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
120 uint32_t config_addr
= (devfn
<< 8) | offset
;
121 qrtas_ibm_write_pci_config(s
->alloc
, s
->buid
, config_addr
, 1, value
);
124 static void qpci_spapr_config_writew(QPCIBus
*bus
, int devfn
, uint8_t offset
,
127 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
128 uint32_t config_addr
= (devfn
<< 8) | offset
;
129 qrtas_ibm_write_pci_config(s
->alloc
, s
->buid
, config_addr
, 2, value
);
132 static void qpci_spapr_config_writel(QPCIBus
*bus
, int devfn
, uint8_t offset
,
135 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
136 uint32_t config_addr
= (devfn
<< 8) | offset
;
137 qrtas_ibm_write_pci_config(s
->alloc
, s
->buid
, config_addr
, 4, value
);
140 #define SPAPR_PCI_BASE (1ULL << 45)
142 #define SPAPR_PCI_MMIO32_WIN_SIZE 0x80000000 /* 2 GiB */
143 #define SPAPR_PCI_IO_WIN_SIZE 0x10000
145 QPCIBus
*qpci_init_spapr(QGuestAllocator
*alloc
)
149 ret
= g_malloc(sizeof(*ret
));
153 ret
->bus
.pio_readb
= qpci_spapr_pio_readb
;
154 ret
->bus
.pio_readw
= qpci_spapr_pio_readw
;
155 ret
->bus
.pio_readl
= qpci_spapr_pio_readl
;
157 ret
->bus
.pio_writeb
= qpci_spapr_pio_writeb
;
158 ret
->bus
.pio_writew
= qpci_spapr_pio_writew
;
159 ret
->bus
.pio_writel
= qpci_spapr_pio_writel
;
161 ret
->bus
.memread
= qpci_spapr_memread
;
162 ret
->bus
.memwrite
= qpci_spapr_memwrite
;
164 ret
->bus
.config_readb
= qpci_spapr_config_readb
;
165 ret
->bus
.config_readw
= qpci_spapr_config_readw
;
166 ret
->bus
.config_readl
= qpci_spapr_config_readl
;
168 ret
->bus
.config_writeb
= qpci_spapr_config_writeb
;
169 ret
->bus
.config_writew
= qpci_spapr_config_writew
;
170 ret
->bus
.config_writel
= qpci_spapr_config_writel
;
172 /* FIXME: We assume the default location of the PHB for now.
173 * Ideally we'd parse the device tree deposited in the guest to
174 * get the window locations */
175 ret
->buid
= 0x800000020000000ULL
;
177 ret
->pio_cpu_base
= SPAPR_PCI_BASE
;
178 ret
->pio
.pci_base
= 0;
179 ret
->pio
.size
= SPAPR_PCI_IO_WIN_SIZE
;
181 /* 32-bit portion of the MMIO window is at PCI address 2..4 GiB */
182 ret
->mmio32_cpu_base
= SPAPR_PCI_BASE
+ SPAPR_PCI_MMIO32_WIN_SIZE
;
183 ret
->mmio32
.pci_base
= 0x80000000; /* 2 GiB */
184 ret
->mmio32
.size
= SPAPR_PCI_MMIO32_WIN_SIZE
;
186 ret
->bus
.pio_alloc_ptr
= 0xc000;
187 ret
->bus
.mmio_alloc_ptr
= ret
->mmio32
.pci_base
;
188 ret
->bus
.mmio_limit
= ret
->mmio32
.pci_base
+ ret
->mmio32
.size
;
193 void qpci_free_spapr(QPCIBus
*bus
)
195 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);