xref: /kvmtool/virtio/pci-modern.c (revision b0d56e3c994a0feb3ffb519cecda5c1f6da8b1ab)
1*b0d56e3cSJean-Philippe Brucker #include "kvm/virtio-pci.h"
2*b0d56e3cSJean-Philippe Brucker 
3*b0d56e3cSJean-Philippe Brucker #include "kvm/ioport.h"
4*b0d56e3cSJean-Philippe Brucker #include "kvm/virtio.h"
5*b0d56e3cSJean-Philippe Brucker #include "kvm/virtio-pci-dev.h"
6*b0d56e3cSJean-Philippe Brucker 
7*b0d56e3cSJean-Philippe Brucker #include <linux/virtio_config.h>
8*b0d56e3cSJean-Philippe Brucker 
9*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_COMMON_SIZE	sizeof(struct virtio_pci_common_cfg)
10*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_COMMON_START	0
11*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_COMMON_END	(VPCI_CFG_COMMON_SIZE - 1)
12*b0d56e3cSJean-Philippe Brucker /*
13*b0d56e3cSJean-Philippe Brucker  * Use a naturally aligned 4-byte doorbell, in case we ever want to
14*b0d56e3cSJean-Philippe Brucker  * implement VIRTIO_F_NOTIFICATION_DATA
15*b0d56e3cSJean-Philippe Brucker  */
16*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_NOTIFY_SIZE	4
17*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_NOTIFY_START	(VPCI_CFG_COMMON_END + 1)
18*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_NOTIFY_END	(VPCI_CFG_COMMON_END + VPCI_CFG_NOTIFY_SIZE)
19*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_ISR_SIZE	4
20*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_ISR_START	(VPCI_CFG_NOTIFY_END + 1)
21*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_ISR_END	(VPCI_CFG_NOTIFY_END + VPCI_CFG_ISR_SIZE)
22*b0d56e3cSJean-Philippe Brucker /*
23*b0d56e3cSJean-Philippe Brucker  * We're at 64 bytes. Use the remaining 192 bytes in PCI_IO_SIZE for the
24*b0d56e3cSJean-Philippe Brucker  * device-specific config space. It's sufficient for the devices we
25*b0d56e3cSJean-Philippe Brucker  * currently implement (virtio_blk_config is 60 bytes) and, I think, all
26*b0d56e3cSJean-Philippe Brucker  * existing virtio 1.2 devices.
27*b0d56e3cSJean-Philippe Brucker  */
28*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_DEV_START	(VPCI_CFG_ISR_END + 1)
29*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_DEV_END	((PCI_IO_SIZE) - 1)
30*b0d56e3cSJean-Philippe Brucker #define VPCI_CFG_DEV_SIZE	(VPCI_CFG_DEV_END - VPCI_CFG_DEV_START + 1)
31*b0d56e3cSJean-Philippe Brucker 
32*b0d56e3cSJean-Philippe Brucker #define vpci_selected_vq(vpci) \
33*b0d56e3cSJean-Philippe Brucker 	vdev->ops->get_vq((vpci)->kvm, (vpci)->dev, (vpci)->queue_selector)
34*b0d56e3cSJean-Philippe Brucker 
35*b0d56e3cSJean-Philippe Brucker typedef bool (*access_handler_t)(struct virtio_device *, unsigned long, void *, int);
36*b0d56e3cSJean-Philippe Brucker 
37*b0d56e3cSJean-Philippe Brucker static bool virtio_pci__common_write(struct virtio_device *vdev,
38*b0d56e3cSJean-Philippe Brucker 				     unsigned long offset, void *data, int size)
39*b0d56e3cSJean-Philippe Brucker {
40*b0d56e3cSJean-Philippe Brucker 	u64 features;
41*b0d56e3cSJean-Philippe Brucker 	u32 val, gsi, vec;
42*b0d56e3cSJean-Philippe Brucker 	struct virtio_pci *vpci = vdev->virtio;
43*b0d56e3cSJean-Philippe Brucker 
44*b0d56e3cSJean-Philippe Brucker 	switch (offset - VPCI_CFG_COMMON_START) {
45*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_DFSELECT:
46*b0d56e3cSJean-Philippe Brucker 		vpci->device_features_sel = ioport__read32(data);
47*b0d56e3cSJean-Philippe Brucker 		break;
48*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_GFSELECT:
49*b0d56e3cSJean-Philippe Brucker 		vpci->driver_features_sel = ioport__read32(data);
50*b0d56e3cSJean-Philippe Brucker 		break;
51*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_GF:
52*b0d56e3cSJean-Philippe Brucker 		val = ioport__read32(data);
53*b0d56e3cSJean-Philippe Brucker 		if (vpci->driver_features_sel > 1)
54*b0d56e3cSJean-Philippe Brucker 			break;
55*b0d56e3cSJean-Philippe Brucker 
56*b0d56e3cSJean-Philippe Brucker 		features = (u64)val << (32 * vpci->driver_features_sel);
57*b0d56e3cSJean-Philippe Brucker 		virtio_set_guest_features(vpci->kvm, vdev, vpci->dev, features);
58*b0d56e3cSJean-Philippe Brucker 		break;
59*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_MSIX:
60*b0d56e3cSJean-Philippe Brucker 		vec = vpci->config_vector = ioport__read16(data);
61*b0d56e3cSJean-Philippe Brucker 		gsi = virtio_pci__add_msix_route(vpci, vec);
62*b0d56e3cSJean-Philippe Brucker 		if (gsi < 0)
63*b0d56e3cSJean-Philippe Brucker 			break;
64*b0d56e3cSJean-Philippe Brucker 
65*b0d56e3cSJean-Philippe Brucker 		vpci->config_gsi = gsi;
66*b0d56e3cSJean-Philippe Brucker 		break;
67*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_STATUS:
68*b0d56e3cSJean-Philippe Brucker 		vpci->status = ioport__read8(data);
69*b0d56e3cSJean-Philippe Brucker 		virtio_notify_status(vpci->kvm, vdev, vpci->dev, vpci->status);
70*b0d56e3cSJean-Philippe Brucker 		break;
71*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_SELECT:
72*b0d56e3cSJean-Philippe Brucker 		val = ioport__read16(data);
73*b0d56e3cSJean-Philippe Brucker 		if (val >= (u32)vdev->ops->get_vq_count(vpci->kvm, vpci->dev))
74*b0d56e3cSJean-Philippe Brucker 			pr_warning("invalid vq number %u", val);
75*b0d56e3cSJean-Philippe Brucker 		else
76*b0d56e3cSJean-Philippe Brucker 			vpci->queue_selector = val;
77*b0d56e3cSJean-Philippe Brucker 		break;
78*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_SIZE:
79*b0d56e3cSJean-Philippe Brucker 		vdev->ops->set_size_vq(vpci->kvm, vpci->dev,
80*b0d56e3cSJean-Philippe Brucker 				       vpci->queue_selector,
81*b0d56e3cSJean-Philippe Brucker 				       ioport__read16(data));
82*b0d56e3cSJean-Philippe Brucker 		break;
83*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_MSIX:
84*b0d56e3cSJean-Philippe Brucker 		vec = vpci->vq_vector[vpci->queue_selector] = ioport__read16(data);
85*b0d56e3cSJean-Philippe Brucker 
86*b0d56e3cSJean-Philippe Brucker 		gsi = virtio_pci__add_msix_route(vpci, vec);
87*b0d56e3cSJean-Philippe Brucker 		if (gsi < 0)
88*b0d56e3cSJean-Philippe Brucker 			break;
89*b0d56e3cSJean-Philippe Brucker 
90*b0d56e3cSJean-Philippe Brucker 		vpci->gsis[vpci->queue_selector] = gsi;
91*b0d56e3cSJean-Philippe Brucker 		if (vdev->ops->notify_vq_gsi)
92*b0d56e3cSJean-Philippe Brucker 			vdev->ops->notify_vq_gsi(vpci->kvm, vpci->dev,
93*b0d56e3cSJean-Philippe Brucker 						 vpci->queue_selector, gsi);
94*b0d56e3cSJean-Philippe Brucker 		break;
95*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_ENABLE:
96*b0d56e3cSJean-Philippe Brucker 		val = ioport__read16(data);
97*b0d56e3cSJean-Philippe Brucker 		if (val)
98*b0d56e3cSJean-Philippe Brucker 			virtio_pci_init_vq(vpci->kvm, vdev, vpci->queue_selector);
99*b0d56e3cSJean-Philippe Brucker 		else
100*b0d56e3cSJean-Philippe Brucker 			virtio_pci_exit_vq(vpci->kvm, vdev, vpci->queue_selector);
101*b0d56e3cSJean-Philippe Brucker 		break;
102*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_DESCLO:
103*b0d56e3cSJean-Philippe Brucker 		vpci_selected_vq(vpci)->vring_addr.desc_lo = ioport__read32(data);
104*b0d56e3cSJean-Philippe Brucker 		break;
105*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_DESCHI:
106*b0d56e3cSJean-Philippe Brucker 		vpci_selected_vq(vpci)->vring_addr.desc_hi = ioport__read32(data);
107*b0d56e3cSJean-Philippe Brucker 		break;
108*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_AVAILLO:
109*b0d56e3cSJean-Philippe Brucker 		vpci_selected_vq(vpci)->vring_addr.avail_lo = ioport__read32(data);
110*b0d56e3cSJean-Philippe Brucker 		break;
111*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_AVAILHI:
112*b0d56e3cSJean-Philippe Brucker 		vpci_selected_vq(vpci)->vring_addr.avail_hi = ioport__read32(data);
113*b0d56e3cSJean-Philippe Brucker 		break;
114*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_USEDLO:
115*b0d56e3cSJean-Philippe Brucker 		vpci_selected_vq(vpci)->vring_addr.used_lo = ioport__read32(data);
116*b0d56e3cSJean-Philippe Brucker 		break;
117*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_USEDHI:
118*b0d56e3cSJean-Philippe Brucker 		vpci_selected_vq(vpci)->vring_addr.used_hi = ioport__read32(data);
119*b0d56e3cSJean-Philippe Brucker 		break;
120*b0d56e3cSJean-Philippe Brucker 	}
121*b0d56e3cSJean-Philippe Brucker 
122*b0d56e3cSJean-Philippe Brucker 	return true;
123*b0d56e3cSJean-Philippe Brucker }
124*b0d56e3cSJean-Philippe Brucker 
125*b0d56e3cSJean-Philippe Brucker static bool virtio_pci__notify_write(struct virtio_device *vdev,
126*b0d56e3cSJean-Philippe Brucker 				     unsigned long offset, void *data, int size)
127*b0d56e3cSJean-Philippe Brucker {
128*b0d56e3cSJean-Philippe Brucker 	u16 vq = ioport__read16(data);
129*b0d56e3cSJean-Philippe Brucker 	struct virtio_pci *vpci = vdev->virtio;
130*b0d56e3cSJean-Philippe Brucker 
131*b0d56e3cSJean-Philippe Brucker 	vdev->ops->notify_vq(vpci->kvm, vpci->dev, vq);
132*b0d56e3cSJean-Philippe Brucker 
133*b0d56e3cSJean-Philippe Brucker 	return true;
134*b0d56e3cSJean-Philippe Brucker }
135*b0d56e3cSJean-Philippe Brucker 
136*b0d56e3cSJean-Philippe Brucker static bool virtio_pci__config_write(struct virtio_device *vdev,
137*b0d56e3cSJean-Philippe Brucker 				     unsigned long offset, void *data, int size)
138*b0d56e3cSJean-Philippe Brucker {
139*b0d56e3cSJean-Philippe Brucker 	struct virtio_pci *vpci = vdev->virtio;
140*b0d56e3cSJean-Philippe Brucker 
141*b0d56e3cSJean-Philippe Brucker 	return virtio_access_config(vpci->kvm, vdev, vpci->dev,
142*b0d56e3cSJean-Philippe Brucker 				    offset - VPCI_CFG_DEV_START, data, size,
143*b0d56e3cSJean-Philippe Brucker 				    true);
144*b0d56e3cSJean-Philippe Brucker }
145*b0d56e3cSJean-Philippe Brucker 
146*b0d56e3cSJean-Philippe Brucker static bool virtio_pci__common_read(struct virtio_device *vdev,
147*b0d56e3cSJean-Philippe Brucker 				    unsigned long offset, void *data, int size)
148*b0d56e3cSJean-Philippe Brucker {
149*b0d56e3cSJean-Philippe Brucker 	u32 val;
150*b0d56e3cSJean-Philippe Brucker 	struct virtio_pci *vpci = vdev->virtio;
151*b0d56e3cSJean-Philippe Brucker 	u64 features = 1ULL << VIRTIO_F_VERSION_1;
152*b0d56e3cSJean-Philippe Brucker 
153*b0d56e3cSJean-Philippe Brucker 	switch (offset - VPCI_CFG_COMMON_START) {
154*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_DFSELECT:
155*b0d56e3cSJean-Philippe Brucker 		val = vpci->device_features_sel;
156*b0d56e3cSJean-Philippe Brucker 		ioport__write32(data, val);
157*b0d56e3cSJean-Philippe Brucker 		break;
158*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_DF:
159*b0d56e3cSJean-Philippe Brucker 		if (vpci->device_features_sel > 1)
160*b0d56e3cSJean-Philippe Brucker 			break;
161*b0d56e3cSJean-Philippe Brucker 		features |= vdev->ops->get_host_features(vpci->kvm, vpci->dev);
162*b0d56e3cSJean-Philippe Brucker 		val = features >> (32 * vpci->device_features_sel);
163*b0d56e3cSJean-Philippe Brucker 		ioport__write32(data, val);
164*b0d56e3cSJean-Philippe Brucker 		break;
165*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_GFSELECT:
166*b0d56e3cSJean-Philippe Brucker 		val = vpci->driver_features_sel;
167*b0d56e3cSJean-Philippe Brucker 		ioport__write32(data, val);
168*b0d56e3cSJean-Philippe Brucker 		break;
169*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_MSIX:
170*b0d56e3cSJean-Philippe Brucker 		val = vpci->config_vector;
171*b0d56e3cSJean-Philippe Brucker 		ioport__write32(data, val);
172*b0d56e3cSJean-Philippe Brucker 		break;
173*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_NUMQ:
174*b0d56e3cSJean-Philippe Brucker 		val = vdev->ops->get_vq_count(vpci->kvm, vpci->dev);
175*b0d56e3cSJean-Philippe Brucker 		ioport__write32(data, val);
176*b0d56e3cSJean-Philippe Brucker 		break;
177*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_STATUS:
178*b0d56e3cSJean-Philippe Brucker 		ioport__write8(data, vpci->status);
179*b0d56e3cSJean-Philippe Brucker 		break;
180*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_CFGGENERATION:
181*b0d56e3cSJean-Philippe Brucker 		/*
182*b0d56e3cSJean-Philippe Brucker 		 * The config generation changes when the device updates a
183*b0d56e3cSJean-Philippe Brucker 		 * config field larger than 32 bits, that the driver may read
184*b0d56e3cSJean-Philippe Brucker 		 * using multiple accesses. Since kvmtool doesn't use any
185*b0d56e3cSJean-Philippe Brucker 		 * mutable config field larger than 32 bits, the generation is
186*b0d56e3cSJean-Philippe Brucker 		 * constant.
187*b0d56e3cSJean-Philippe Brucker 		 */
188*b0d56e3cSJean-Philippe Brucker 		ioport__write8(data, 0);
189*b0d56e3cSJean-Philippe Brucker 		break;
190*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_SELECT:
191*b0d56e3cSJean-Philippe Brucker 		ioport__write16(data, vpci->queue_selector);
192*b0d56e3cSJean-Philippe Brucker 		break;
193*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_SIZE:
194*b0d56e3cSJean-Philippe Brucker 		val = vdev->ops->get_size_vq(vpci->kvm, vpci->dev,
195*b0d56e3cSJean-Philippe Brucker 					     vpci->queue_selector);
196*b0d56e3cSJean-Philippe Brucker 		ioport__write16(data, val);
197*b0d56e3cSJean-Philippe Brucker 		break;
198*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_MSIX:
199*b0d56e3cSJean-Philippe Brucker 		val = vpci->vq_vector[vpci->queue_selector];
200*b0d56e3cSJean-Philippe Brucker 		ioport__write16(data, val);
201*b0d56e3cSJean-Philippe Brucker 		break;
202*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_ENABLE:
203*b0d56e3cSJean-Philippe Brucker 		val = vpci_selected_vq(vpci)->enabled;
204*b0d56e3cSJean-Philippe Brucker 		ioport__write16(data, val);
205*b0d56e3cSJean-Philippe Brucker 		break;
206*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_NOFF:
207*b0d56e3cSJean-Philippe Brucker 		val = vpci->queue_selector;
208*b0d56e3cSJean-Philippe Brucker 		ioport__write16(data, val);
209*b0d56e3cSJean-Philippe Brucker 		break;
210*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_DESCLO:
211*b0d56e3cSJean-Philippe Brucker 		val = vpci_selected_vq(vpci)->vring_addr.desc_lo;
212*b0d56e3cSJean-Philippe Brucker 		ioport__write32(data, val);
213*b0d56e3cSJean-Philippe Brucker 		break;
214*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_DESCHI:
215*b0d56e3cSJean-Philippe Brucker 		val = vpci_selected_vq(vpci)->vring_addr.desc_hi;
216*b0d56e3cSJean-Philippe Brucker 		ioport__write32(data, val);
217*b0d56e3cSJean-Philippe Brucker 		break;
218*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_AVAILLO:
219*b0d56e3cSJean-Philippe Brucker 		val = vpci_selected_vq(vpci)->vring_addr.avail_lo;
220*b0d56e3cSJean-Philippe Brucker 		ioport__write32(data, val);
221*b0d56e3cSJean-Philippe Brucker 		break;
222*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_AVAILHI:
223*b0d56e3cSJean-Philippe Brucker 		val = vpci_selected_vq(vpci)->vring_addr.avail_hi;
224*b0d56e3cSJean-Philippe Brucker 		ioport__write32(data, val);
225*b0d56e3cSJean-Philippe Brucker 		break;
226*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_USEDLO:
227*b0d56e3cSJean-Philippe Brucker 		val = vpci_selected_vq(vpci)->vring_addr.used_lo;
228*b0d56e3cSJean-Philippe Brucker 		ioport__write32(data, val);
229*b0d56e3cSJean-Philippe Brucker 		break;
230*b0d56e3cSJean-Philippe Brucker 	case VIRTIO_PCI_COMMON_Q_USEDHI:
231*b0d56e3cSJean-Philippe Brucker 		val = vpci_selected_vq(vpci)->vring_addr.used_hi;
232*b0d56e3cSJean-Philippe Brucker 		ioport__write32(data, val);
233*b0d56e3cSJean-Philippe Brucker 		break;
234*b0d56e3cSJean-Philippe Brucker 	};
235*b0d56e3cSJean-Philippe Brucker 
236*b0d56e3cSJean-Philippe Brucker 	return true;
237*b0d56e3cSJean-Philippe Brucker }
238*b0d56e3cSJean-Philippe Brucker 
239*b0d56e3cSJean-Philippe Brucker static bool virtio_pci__isr_read(struct virtio_device *vdev,
240*b0d56e3cSJean-Philippe Brucker 				 unsigned long offset, void *data, int size)
241*b0d56e3cSJean-Philippe Brucker {
242*b0d56e3cSJean-Philippe Brucker 	struct virtio_pci *vpci = vdev->virtio;
243*b0d56e3cSJean-Philippe Brucker 
244*b0d56e3cSJean-Philippe Brucker 	if (WARN_ON(offset - VPCI_CFG_ISR_START != 0))
245*b0d56e3cSJean-Philippe Brucker 		return false;
246*b0d56e3cSJean-Philippe Brucker 
247*b0d56e3cSJean-Philippe Brucker 	ioport__write8(data, vpci->isr);
248*b0d56e3cSJean-Philippe Brucker 	/*
249*b0d56e3cSJean-Philippe Brucker 	 * Interrupts are edge triggered (yes, going against the PCI and virtio
250*b0d56e3cSJean-Philippe Brucker 	 * specs), so no need to deassert the IRQ line.
251*b0d56e3cSJean-Philippe Brucker 	 */
252*b0d56e3cSJean-Philippe Brucker 	vpci->isr = 0;
253*b0d56e3cSJean-Philippe Brucker 
254*b0d56e3cSJean-Philippe Brucker 	return 0;
255*b0d56e3cSJean-Philippe Brucker }
256*b0d56e3cSJean-Philippe Brucker 
257*b0d56e3cSJean-Philippe Brucker static bool virtio_pci__config_read(struct virtio_device *vdev,
258*b0d56e3cSJean-Philippe Brucker 				    unsigned long offset, void *data, int size)
259*b0d56e3cSJean-Philippe Brucker {
260*b0d56e3cSJean-Philippe Brucker 	struct virtio_pci *vpci = vdev->virtio;
261*b0d56e3cSJean-Philippe Brucker 
262*b0d56e3cSJean-Philippe Brucker 	return virtio_access_config(vpci->kvm, vdev, vpci->dev,
263*b0d56e3cSJean-Philippe Brucker 				    offset - VPCI_CFG_DEV_START, data, size,
264*b0d56e3cSJean-Philippe Brucker 				    false);
265*b0d56e3cSJean-Philippe Brucker }
266*b0d56e3cSJean-Philippe Brucker 
267*b0d56e3cSJean-Philippe Brucker static bool virtio_pci_access(struct kvm_cpu *vcpu, struct virtio_device *vdev,
268*b0d56e3cSJean-Philippe Brucker 			      unsigned long offset, void *data, int size,
269*b0d56e3cSJean-Philippe Brucker 			      bool write)
270*b0d56e3cSJean-Philippe Brucker {
271*b0d56e3cSJean-Philippe Brucker 	access_handler_t handler = NULL;
272*b0d56e3cSJean-Philippe Brucker 
273*b0d56e3cSJean-Philippe Brucker 	switch (offset) {
274*b0d56e3cSJean-Philippe Brucker 	case VPCI_CFG_COMMON_START...VPCI_CFG_COMMON_END:
275*b0d56e3cSJean-Philippe Brucker 		if (write)
276*b0d56e3cSJean-Philippe Brucker 			handler = virtio_pci__common_write;
277*b0d56e3cSJean-Philippe Brucker 		else
278*b0d56e3cSJean-Philippe Brucker 			handler = virtio_pci__common_read;
279*b0d56e3cSJean-Philippe Brucker 		break;
280*b0d56e3cSJean-Philippe Brucker 	case VPCI_CFG_NOTIFY_START...VPCI_CFG_NOTIFY_END:
281*b0d56e3cSJean-Philippe Brucker 		if (write)
282*b0d56e3cSJean-Philippe Brucker 			handler = virtio_pci__notify_write;
283*b0d56e3cSJean-Philippe Brucker 		break;
284*b0d56e3cSJean-Philippe Brucker 	case VPCI_CFG_ISR_START...VPCI_CFG_ISR_END:
285*b0d56e3cSJean-Philippe Brucker 		if (!write)
286*b0d56e3cSJean-Philippe Brucker 			handler = virtio_pci__isr_read;
287*b0d56e3cSJean-Philippe Brucker 		break;
288*b0d56e3cSJean-Philippe Brucker 	case VPCI_CFG_DEV_START...VPCI_CFG_DEV_END:
289*b0d56e3cSJean-Philippe Brucker 		if (write)
290*b0d56e3cSJean-Philippe Brucker 			handler = virtio_pci__config_write;
291*b0d56e3cSJean-Philippe Brucker 		else
292*b0d56e3cSJean-Philippe Brucker 			handler = virtio_pci__config_read;
293*b0d56e3cSJean-Philippe Brucker 		break;
294*b0d56e3cSJean-Philippe Brucker 	}
295*b0d56e3cSJean-Philippe Brucker 
296*b0d56e3cSJean-Philippe Brucker 	if (!handler)
297*b0d56e3cSJean-Philippe Brucker 		return false;
298*b0d56e3cSJean-Philippe Brucker 
299*b0d56e3cSJean-Philippe Brucker 	return handler(vdev, offset, data, size);
300*b0d56e3cSJean-Philippe Brucker }
301*b0d56e3cSJean-Philippe Brucker 
302*b0d56e3cSJean-Philippe Brucker void virtio_pci_modern__io_mmio_callback(struct kvm_cpu *vcpu, u64 addr,
303*b0d56e3cSJean-Philippe Brucker 					 u8 *data, u32 len, u8 is_write,
304*b0d56e3cSJean-Philippe Brucker 					 void *ptr)
305*b0d56e3cSJean-Philippe Brucker {
306*b0d56e3cSJean-Philippe Brucker 	struct virtio_device *vdev = ptr;
307*b0d56e3cSJean-Philippe Brucker 	struct virtio_pci *vpci = vdev->virtio;
308*b0d56e3cSJean-Philippe Brucker 	u32 mmio_addr = virtio_pci__mmio_addr(vpci);
309*b0d56e3cSJean-Philippe Brucker 
310*b0d56e3cSJean-Philippe Brucker 	virtio_pci_access(vcpu, vdev, addr - mmio_addr, data, len, is_write);
311*b0d56e3cSJean-Philippe Brucker }
312*b0d56e3cSJean-Philippe Brucker 
313*b0d56e3cSJean-Philippe Brucker int virtio_pci_modern_init(struct virtio_device *vdev)
314*b0d56e3cSJean-Philippe Brucker {
315*b0d56e3cSJean-Philippe Brucker 	int subsys_id;
316*b0d56e3cSJean-Philippe Brucker 	struct virtio_pci *vpci = vdev->virtio;
317*b0d56e3cSJean-Philippe Brucker 	struct pci_device_header *hdr = &vpci->pci_hdr;
318*b0d56e3cSJean-Philippe Brucker 
319*b0d56e3cSJean-Philippe Brucker 	subsys_id = le16_to_cpu(hdr->subsys_id);
320*b0d56e3cSJean-Philippe Brucker 
321*b0d56e3cSJean-Philippe Brucker 	hdr->device_id = cpu_to_le16(PCI_DEVICE_ID_VIRTIO_BASE + subsys_id);
322*b0d56e3cSJean-Philippe Brucker 	hdr->subsys_id = cpu_to_le16(PCI_SUBSYS_ID_VIRTIO_BASE + subsys_id);
323*b0d56e3cSJean-Philippe Brucker 
324*b0d56e3cSJean-Philippe Brucker 	vpci->doorbell_offset = VPCI_CFG_NOTIFY_START;
325*b0d56e3cSJean-Philippe Brucker 	vdev->endian = VIRTIO_ENDIAN_LE;
326*b0d56e3cSJean-Philippe Brucker 
327*b0d56e3cSJean-Philippe Brucker 	hdr->msix.next = PCI_CAP_OFF(hdr, virtio);
328*b0d56e3cSJean-Philippe Brucker 
329*b0d56e3cSJean-Philippe Brucker 	hdr->virtio.common = (struct virtio_pci_cap) {
330*b0d56e3cSJean-Philippe Brucker 		.cap_vndr		= PCI_CAP_ID_VNDR,
331*b0d56e3cSJean-Philippe Brucker 		.cap_next		= PCI_CAP_OFF(hdr, virtio.notify),
332*b0d56e3cSJean-Philippe Brucker 		.cap_len		= sizeof(hdr->virtio.common),
333*b0d56e3cSJean-Philippe Brucker 		.cfg_type		= VIRTIO_PCI_CAP_COMMON_CFG,
334*b0d56e3cSJean-Philippe Brucker 		.bar			= 1,
335*b0d56e3cSJean-Philippe Brucker 		.offset			= cpu_to_le32(VPCI_CFG_COMMON_START),
336*b0d56e3cSJean-Philippe Brucker 		.length			= cpu_to_le32(VPCI_CFG_COMMON_SIZE),
337*b0d56e3cSJean-Philippe Brucker 	};
338*b0d56e3cSJean-Philippe Brucker 	BUILD_BUG_ON(VPCI_CFG_COMMON_START & 0x3);
339*b0d56e3cSJean-Philippe Brucker 
340*b0d56e3cSJean-Philippe Brucker 	hdr->virtio.notify = (struct virtio_pci_notify_cap) {
341*b0d56e3cSJean-Philippe Brucker 		.cap.cap_vndr		= PCI_CAP_ID_VNDR,
342*b0d56e3cSJean-Philippe Brucker 		.cap.cap_next		= PCI_CAP_OFF(hdr, virtio.isr),
343*b0d56e3cSJean-Philippe Brucker 		.cap.cap_len		= sizeof(hdr->virtio.notify),
344*b0d56e3cSJean-Philippe Brucker 		.cap.cfg_type		= VIRTIO_PCI_CAP_NOTIFY_CFG,
345*b0d56e3cSJean-Philippe Brucker 		.cap.bar		= 1,
346*b0d56e3cSJean-Philippe Brucker 		.cap.offset		= cpu_to_le32(VPCI_CFG_NOTIFY_START),
347*b0d56e3cSJean-Philippe Brucker 		.cap.length		= cpu_to_le32(VPCI_CFG_NOTIFY_SIZE),
348*b0d56e3cSJean-Philippe Brucker 		/*
349*b0d56e3cSJean-Philippe Brucker 		 * Notify multiplier is 0, meaning that notifications are all on
350*b0d56e3cSJean-Philippe Brucker 		 * the same register
351*b0d56e3cSJean-Philippe Brucker 		 */
352*b0d56e3cSJean-Philippe Brucker 	};
353*b0d56e3cSJean-Philippe Brucker 	BUILD_BUG_ON(VPCI_CFG_NOTIFY_START & 0x3);
354*b0d56e3cSJean-Philippe Brucker 
355*b0d56e3cSJean-Philippe Brucker 	hdr->virtio.isr = (struct virtio_pci_cap) {
356*b0d56e3cSJean-Philippe Brucker 		.cap_vndr		= PCI_CAP_ID_VNDR,
357*b0d56e3cSJean-Philippe Brucker 		.cap_next		= PCI_CAP_OFF(hdr, virtio.device),
358*b0d56e3cSJean-Philippe Brucker 		.cap_len		= sizeof(hdr->virtio.isr),
359*b0d56e3cSJean-Philippe Brucker 		.cfg_type		= VIRTIO_PCI_CAP_ISR_CFG,
360*b0d56e3cSJean-Philippe Brucker 		.bar			= 1,
361*b0d56e3cSJean-Philippe Brucker 		.offset			= cpu_to_le32(VPCI_CFG_ISR_START),
362*b0d56e3cSJean-Philippe Brucker 		.length			= cpu_to_le32(VPCI_CFG_ISR_SIZE),
363*b0d56e3cSJean-Philippe Brucker 	};
364*b0d56e3cSJean-Philippe Brucker 
365*b0d56e3cSJean-Philippe Brucker 	hdr->virtio.device = (struct virtio_pci_cap) {
366*b0d56e3cSJean-Philippe Brucker 		.cap_vndr		= PCI_CAP_ID_VNDR,
367*b0d56e3cSJean-Philippe Brucker 		.cap_next		= PCI_CAP_OFF(hdr, virtio.pci),
368*b0d56e3cSJean-Philippe Brucker 		.cap_len		= sizeof(hdr->virtio.device),
369*b0d56e3cSJean-Philippe Brucker 		.cfg_type		= VIRTIO_PCI_CAP_DEVICE_CFG,
370*b0d56e3cSJean-Philippe Brucker 		.bar			= 1,
371*b0d56e3cSJean-Philippe Brucker 		.offset			= cpu_to_le32(VPCI_CFG_DEV_START),
372*b0d56e3cSJean-Philippe Brucker 		.length			= cpu_to_le32(VPCI_CFG_DEV_SIZE),
373*b0d56e3cSJean-Philippe Brucker 	};
374*b0d56e3cSJean-Philippe Brucker 	BUILD_BUG_ON(VPCI_CFG_DEV_START & 0x3);
375*b0d56e3cSJean-Philippe Brucker 
376*b0d56e3cSJean-Philippe Brucker 	/*
377*b0d56e3cSJean-Philippe Brucker 	 * TODO: implement this weird proxy capability (it is a "MUST" in the
378*b0d56e3cSJean-Philippe Brucker 	 * spec, but I don't know if anyone actually uses it).
379*b0d56e3cSJean-Philippe Brucker 	 * It doesn't use any BAR space. Instead the driver writes .cap.offset
380*b0d56e3cSJean-Philippe Brucker 	 * and .cap.length to access a register in a BAR.
381*b0d56e3cSJean-Philippe Brucker 	 */
382*b0d56e3cSJean-Philippe Brucker 	hdr->virtio.pci = (struct virtio_pci_cfg_cap) {
383*b0d56e3cSJean-Philippe Brucker 		.cap.cap_vndr		= PCI_CAP_ID_VNDR,
384*b0d56e3cSJean-Philippe Brucker 		.cap.cap_next		= 0,
385*b0d56e3cSJean-Philippe Brucker 		.cap.cap_len		= sizeof(hdr->virtio.pci),
386*b0d56e3cSJean-Philippe Brucker 		.cap.cfg_type		= VIRTIO_PCI_CAP_PCI_CFG,
387*b0d56e3cSJean-Philippe Brucker 	};
388*b0d56e3cSJean-Philippe Brucker 
389*b0d56e3cSJean-Philippe Brucker 	return 0;
390*b0d56e3cSJean-Philippe Brucker }
391