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 uint64_t qpci_spapr_pio_readq(QPCIBus
*bus
, uint32_t addr
)
83 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
84 return bswap64(readq(s
->pio_cpu_base
+ addr
));
87 static void qpci_spapr_pio_writeq(QPCIBus
*bus
, uint32_t addr
, uint64_t val
)
89 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
90 writeq(s
->pio_cpu_base
+ addr
, bswap64(val
));
93 static void qpci_spapr_memread(QPCIBus
*bus
, uint32_t addr
,
94 void *buf
, size_t len
)
96 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
97 memread(s
->mmio32_cpu_base
+ addr
, buf
, len
);
100 static void qpci_spapr_memwrite(QPCIBus
*bus
, uint32_t addr
,
101 const void *buf
, size_t len
)
103 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
104 memwrite(s
->mmio32_cpu_base
+ addr
, buf
, len
);
107 static uint8_t qpci_spapr_config_readb(QPCIBus
*bus
, int devfn
, uint8_t offset
)
109 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
110 uint32_t config_addr
= (devfn
<< 8) | offset
;
111 return qrtas_ibm_read_pci_config(bus
->qts
, s
->alloc
, s
->buid
,
115 static uint16_t qpci_spapr_config_readw(QPCIBus
*bus
, int devfn
, uint8_t offset
)
117 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
118 uint32_t config_addr
= (devfn
<< 8) | offset
;
119 return qrtas_ibm_read_pci_config(bus
->qts
, s
->alloc
, s
->buid
,
123 static uint32_t qpci_spapr_config_readl(QPCIBus
*bus
, int devfn
, uint8_t offset
)
125 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
126 uint32_t config_addr
= (devfn
<< 8) | offset
;
127 return qrtas_ibm_read_pci_config(bus
->qts
, s
->alloc
, s
->buid
,
131 static void qpci_spapr_config_writeb(QPCIBus
*bus
, int devfn
, uint8_t offset
,
134 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
135 uint32_t config_addr
= (devfn
<< 8) | offset
;
136 qrtas_ibm_write_pci_config(bus
->qts
, s
->alloc
, s
->buid
,
137 config_addr
, 1, value
);
140 static void qpci_spapr_config_writew(QPCIBus
*bus
, int devfn
, uint8_t offset
,
143 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
144 uint32_t config_addr
= (devfn
<< 8) | offset
;
145 qrtas_ibm_write_pci_config(bus
->qts
, s
->alloc
, s
->buid
,
146 config_addr
, 2, value
);
149 static void qpci_spapr_config_writel(QPCIBus
*bus
, int devfn
, uint8_t offset
,
152 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
153 uint32_t config_addr
= (devfn
<< 8) | offset
;
154 qrtas_ibm_write_pci_config(bus
->qts
, s
->alloc
, s
->buid
,
155 config_addr
, 4, value
);
158 #define SPAPR_PCI_BASE (1ULL << 45)
160 #define SPAPR_PCI_MMIO32_WIN_SIZE 0x80000000 /* 2 GiB */
161 #define SPAPR_PCI_IO_WIN_SIZE 0x10000
163 QPCIBus
*qpci_init_spapr(QTestState
*qts
, QGuestAllocator
*alloc
)
165 QPCIBusSPAPR
*ret
= g_new0(QPCIBusSPAPR
, 1);
171 ret
->bus
.pio_readb
= qpci_spapr_pio_readb
;
172 ret
->bus
.pio_readw
= qpci_spapr_pio_readw
;
173 ret
->bus
.pio_readl
= qpci_spapr_pio_readl
;
174 ret
->bus
.pio_readq
= qpci_spapr_pio_readq
;
176 ret
->bus
.pio_writeb
= qpci_spapr_pio_writeb
;
177 ret
->bus
.pio_writew
= qpci_spapr_pio_writew
;
178 ret
->bus
.pio_writel
= qpci_spapr_pio_writel
;
179 ret
->bus
.pio_writeq
= qpci_spapr_pio_writeq
;
181 ret
->bus
.memread
= qpci_spapr_memread
;
182 ret
->bus
.memwrite
= qpci_spapr_memwrite
;
184 ret
->bus
.config_readb
= qpci_spapr_config_readb
;
185 ret
->bus
.config_readw
= qpci_spapr_config_readw
;
186 ret
->bus
.config_readl
= qpci_spapr_config_readl
;
188 ret
->bus
.config_writeb
= qpci_spapr_config_writeb
;
189 ret
->bus
.config_writew
= qpci_spapr_config_writew
;
190 ret
->bus
.config_writel
= qpci_spapr_config_writel
;
192 /* FIXME: We assume the default location of the PHB for now.
193 * Ideally we'd parse the device tree deposited in the guest to
194 * get the window locations */
195 ret
->buid
= 0x800000020000000ULL
;
197 ret
->pio_cpu_base
= SPAPR_PCI_BASE
;
198 ret
->pio
.pci_base
= 0;
199 ret
->pio
.size
= SPAPR_PCI_IO_WIN_SIZE
;
201 /* 32-bit portion of the MMIO window is at PCI address 2..4 GiB */
202 ret
->mmio32_cpu_base
= SPAPR_PCI_BASE
;
203 ret
->mmio32
.pci_base
= SPAPR_PCI_MMIO32_WIN_SIZE
;
204 ret
->mmio32
.size
= SPAPR_PCI_MMIO32_WIN_SIZE
;
207 ret
->bus
.pio_alloc_ptr
= 0xc000;
208 ret
->bus
.mmio_alloc_ptr
= ret
->mmio32
.pci_base
;
209 ret
->bus
.mmio_limit
= ret
->mmio32
.pci_base
+ ret
->mmio32
.size
;
214 void qpci_free_spapr(QPCIBus
*bus
)
216 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);