xref: /kvmtool/pci.c (revision 4f045c573234f6d7275f481c7604ae51a1e98218)
1 #include "kvm/pci.h"
2 #include "kvm/ioport.h"
3 #include "kvm/util.h"
4 #include "kvm/kvm.h"
5 
6 #include <assert.h>
7 
8 #define PCI_MAX_DEVICES			256
9 #define PCI_IO_SIZE			0x100
10 #define PCI_BAR_OFFSET(b)		(offsetof(struct pci_device_header, bar[b]))
11 
12 static struct pci_device_header		*pci_devices[PCI_MAX_DEVICES];
13 
14 static struct pci_config_address	pci_config_address;
15 
16 /* This is within our PCI gap - in an unused area */
17 static u32 io_space_blocks		= KVM_32BIT_GAP_START + 0x1000000;
18 
19 u32 pci_get_io_space_block(void)
20 {
21 	u32 block = io_space_blocks;
22 	io_space_blocks += PCI_IO_SIZE;
23 
24 	return block;
25 }
26 
27 static void *pci_config_address_ptr(u16 port)
28 {
29 	unsigned long offset;
30 	void *base;
31 
32 	offset		= port - PCI_CONFIG_ADDRESS;
33 	base		= &pci_config_address;
34 
35 	return base + offset;
36 }
37 
38 static bool pci_config_address_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
39 {
40 	void *p = pci_config_address_ptr(port);
41 
42 	memcpy(p, data, size);
43 
44 	return true;
45 }
46 
47 static bool pci_config_address_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
48 {
49 	void *p = pci_config_address_ptr(port);
50 
51 	memcpy(data, p, size);
52 
53 	return true;
54 }
55 
56 static struct ioport_operations pci_config_address_ops = {
57 	.io_in		= pci_config_address_in,
58 	.io_out		= pci_config_address_out,
59 };
60 
61 static bool pci_device_exists(u8 bus_number, u8 device_number, u8 function_number)
62 {
63 	struct pci_device_header *dev;
64 
65 	if (pci_config_address.bus_number != bus_number)
66 		return false;
67 
68 	if (pci_config_address.function_number != function_number)
69 		return false;
70 
71 	if (device_number >= PCI_MAX_DEVICES)
72 		return false;
73 
74 	dev		= pci_devices[device_number];
75 
76 	return dev != NULL;
77 }
78 
79 static bool pci_config_data_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
80 {
81 	unsigned long start;
82 	u8 dev_num;
83 
84 	/*
85 	 * If someone accesses PCI configuration space offsets that are not
86 	 * aligned to 4 bytes, it uses ioports to signify that.
87 	 */
88 	start = port - PCI_CONFIG_DATA;
89 
90 	dev_num		= pci_config_address.device_number;
91 
92 	if (pci_device_exists(0, dev_num, 0)) {
93 		unsigned long offset;
94 
95 		offset = start + (pci_config_address.register_number << 2);
96 		if (offset < sizeof(struct pci_device_header)) {
97 			void *p = pci_devices[dev_num];
98 			u8 bar = offset - PCI_BAR_OFFSET(0) / (sizeof(u32));
99 			u32 sz = PCI_IO_SIZE;
100 
101 			if (bar < 6 && pci_devices[dev_num]->bar_size[bar])
102 				sz = pci_devices[dev_num]->bar_size[bar];
103 
104 			/*
105 			 * If the kernel masks the BAR it would expect to find the
106 			 * size of the BAR there next time it reads from it.
107 			 * When the kernel got the size it would write the address
108 			 * back.
109 			 */
110 			if (ioport__read32(p + offset)) {
111 				/* See if kernel tries to mask one of the BARs */
112 				if ((offset >= PCI_BAR_OFFSET(0)) &&
113 				    (offset <= PCI_BAR_OFFSET(6)) &&
114 				    (ioport__read32(data)  == 0xFFFFFFFF))
115 					memcpy(p + offset, &sz, sizeof(sz));
116 				    else
117 					memcpy(p + offset, data, size);
118 			}
119 		}
120 	}
121 
122 	return true;
123 }
124 
125 static bool pci_config_data_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size, u32 count)
126 {
127 	unsigned long start;
128 	u8 dev_num;
129 
130 	/*
131 	 * If someone accesses PCI configuration space offsets that are not
132 	 * aligned to 4 bytes, it uses ioports to signify that.
133 	 */
134 	start = port - PCI_CONFIG_DATA;
135 
136 	dev_num		= pci_config_address.device_number;
137 
138 	if (pci_device_exists(0, dev_num, 0)) {
139 		unsigned long offset;
140 
141 		offset = start + (pci_config_address.register_number << 2);
142 		if (offset < sizeof(struct pci_device_header)) {
143 			void *p = pci_devices[dev_num];
144 
145 			memcpy(data, p + offset, size);
146 		} else
147 			memset(data, 0x00, size);
148 	} else
149 		memset(data, 0xff, size);
150 
151 	return true;
152 }
153 
154 static struct ioport_operations pci_config_data_ops = {
155 	.io_in		= pci_config_data_in,
156 	.io_out		= pci_config_data_out,
157 };
158 
159 void pci__register(struct pci_device_header *dev, u8 dev_num)
160 {
161 	assert(dev_num < PCI_MAX_DEVICES);
162 
163 	pci_devices[dev_num]	= dev;
164 }
165 
166 void pci__init(void)
167 {
168 	ioport__register(PCI_CONFIG_DATA + 0, &pci_config_data_ops, 4, NULL);
169 	ioport__register(PCI_CONFIG_ADDRESS + 0, &pci_config_address_ops, 4, NULL);
170 }
171