xref: /kvmtool/x86/mptable.c (revision d4d6f1538966e211913db5d522e67ed65d73625d)
1 #include "kvm/kvm.h"
2 #include "kvm/bios.h"
3 #include "kvm/apic.h"
4 #include "kvm/mptable.h"
5 #include "kvm/util.h"
6 #include "kvm/devices.h"
7 #include "kvm/pci.h"
8 
9 #include <linux/kernel.h>
10 #include <string.h>
11 
12 #include <asm/mpspec_def.h>
13 #include <linux/types.h>
14 
15 /*
16  * FIXME: please make sure the addresses borrowed
17  * for apic/ioapic never overlaped! We need a global
18  * tracker of system resources (including io, mmio,
19  * and friends).
20  */
21 
mpf_checksum(unsigned char * mp,int len)22 static unsigned int mpf_checksum(unsigned char *mp, int len)
23 {
24 	unsigned int sum = 0;
25 
26 	while (len--)
27 		sum += *mp++;
28 
29 	return sum & 0xFF;
30 }
31 
gen_cpu_flag(unsigned int cpu,unsigned int ncpu)32 static unsigned int gen_cpu_flag(unsigned int cpu, unsigned int ncpu)
33 {
34 	/* sets enabled/disabled | BSP/AP processor */
35 	return ( (cpu < ncpu) ? CPU_ENABLED       : 0) |
36 		((cpu == 0)   ? CPU_BOOTPROCESSOR : 0x00);
37 }
38 
39 #define MPTABLE_SIG_FLOATING	"_MP_"
40 #define MPTABLE_OEM		"KVMCPU00"
41 #define MPTABLE_PRODUCTID	"0.1         "
42 #define MPTABLE_PCIBUSTYPE	"PCI   "
43 #define MPTABLE_ISABUSTYPE	"ISA   "
44 
45 #define MPTABLE_STRNCPY(d, s)	memcpy(d, s, sizeof(d))
46 
47 /* It should be more than enough */
48 #define MPTABLE_MAX_SIZE	(32 << 20)
49 
50 /*
51  * Too many cpus will require x2apic mode
52  * and rather ACPI support so we limit it
53  * here for a while.
54  */
55 #define MPTABLE_MAX_CPUS	255
56 
mptable_add_irq_src(struct mpc_intsrc * mpc_intsrc,u16 srcbusid,u16 srcbusirq,u16 dstapic,u16 dstirq)57 static void mptable_add_irq_src(struct mpc_intsrc *mpc_intsrc,
58 				u16 srcbusid,	u16 srcbusirq,
59 				u16 dstapic,	u16 dstirq)
60 {
61 	*mpc_intsrc = (struct mpc_intsrc) {
62 		.type		= MP_INTSRC,
63 		.irqtype	= mp_INT,
64 		.irqflag	= MP_IRQDIR_DEFAULT,
65 		.srcbus		= srcbusid,
66 		.srcbusirq	= srcbusirq,
67 		.dstapic	= dstapic,
68 		.dstirq		= dstirq
69 	};
70 }
71 
72 /**
73  * mptable_setup - create mptable and fill guest memory with it
74  */
mptable__init(struct kvm * kvm)75 int mptable__init(struct kvm *kvm)
76 {
77 	unsigned long real_mpc_table, real_mpf_intel, size;
78 	struct mpf_intel *mpf_intel;
79 	struct mpc_table *mpc_table;
80 	struct mpc_cpu *mpc_cpu;
81 	struct mpc_bus *mpc_bus;
82 	struct mpc_ioapic *mpc_ioapic;
83 	struct mpc_intsrc *mpc_intsrc;
84 	struct device_header *dev_hdr;
85 
86 	const int pcibusid = 0;
87 	const int isabusid = 1;
88 
89 	unsigned int i, nentries = 0, ncpus = kvm->nrcpus;
90 	unsigned int ioapicid;
91 	void *last_addr;
92 
93 	/* That is where MP table will be in guest memory */
94 	real_mpc_table = ALIGN(MB_BIOS_BEGIN + bios_rom_size, 16);
95 
96 	if (ncpus > MPTABLE_MAX_CPUS) {
97 		pr_warning("Too many cpus: %d limited to %d",
98 			ncpus, MPTABLE_MAX_CPUS);
99 		ncpus = MPTABLE_MAX_CPUS;
100 	}
101 
102 	mpc_table = calloc(1, MPTABLE_MAX_SIZE);
103 	if (!mpc_table)
104 		return -ENOMEM;
105 
106 	MPTABLE_STRNCPY(mpc_table->signature,	MPC_SIGNATURE);
107 	MPTABLE_STRNCPY(mpc_table->oem,		MPTABLE_OEM);
108 	MPTABLE_STRNCPY(mpc_table->productid,	MPTABLE_PRODUCTID);
109 
110 	mpc_table->spec		= 4;
111 	mpc_table->lapic	= APIC_ADDR(0);
112 	mpc_table->oemcount	= ncpus; /* will be updated again at end */
113 
114 	/*
115 	 * CPUs enumeration. Technically speaking we should
116 	 * ask either host or HV for apic version supported
117 	 * but for a while we simply put some random value
118 	 * here.
119 	 */
120 	mpc_cpu = (void *)&mpc_table[1];
121 	for (i = 0; i < ncpus; i++) {
122 		mpc_cpu->type		= MP_PROCESSOR;
123 		mpc_cpu->apicid		= i;
124 		mpc_cpu->apicver	= KVM_APIC_VERSION;
125 		mpc_cpu->cpuflag	= gen_cpu_flag(i, ncpus);
126 		mpc_cpu->cpufeature	= 0x600; /* some default value */
127 		mpc_cpu->featureflag	= 0x201; /* some default value */
128 		mpc_cpu++;
129 	}
130 
131 	last_addr = (void *)mpc_cpu;
132 	nentries += ncpus;
133 
134 	/*
135 	 * PCI buses.
136 	 * FIXME: Some callback here to obtain real number
137 	 * of PCI buses present in system.
138 	 */
139 	mpc_bus		= last_addr;
140 	mpc_bus->type	= MP_BUS;
141 	mpc_bus->busid	= pcibusid;
142 	MPTABLE_STRNCPY(mpc_bus->bustype, MPTABLE_PCIBUSTYPE);
143 
144 	last_addr = (void *)&mpc_bus[1];
145 	nentries++;
146 
147 	/*
148 	 * ISA bus.
149 	 * FIXME: Same issue as for PCI bus.
150 	 */
151 	mpc_bus		= last_addr;
152 	mpc_bus->type	= MP_BUS;
153 	mpc_bus->busid	= isabusid;
154 	MPTABLE_STRNCPY(mpc_bus->bustype, MPTABLE_ISABUSTYPE);
155 
156 	last_addr = (void *)&mpc_bus[1];
157 	nentries++;
158 
159 	/*
160 	 * IO-APIC chip.
161 	 */
162 	ioapicid		= ncpus + 1;
163 	mpc_ioapic		= last_addr;
164 	mpc_ioapic->type	= MP_IOAPIC;
165 	mpc_ioapic->apicid	= ioapicid;
166 	mpc_ioapic->apicver	= KVM_APIC_VERSION;
167 	mpc_ioapic->flags	= MPC_APIC_USABLE;
168 	mpc_ioapic->apicaddr	= IOAPIC_ADDR(0);
169 
170 	last_addr = (void *)&mpc_ioapic[1];
171 	nentries++;
172 
173 	/*
174 	 * IRQ sources.
175 	 * Also note we use PCI irqs here, no for ISA bus yet.
176 	 */
177 
178 	dev_hdr = device__first_dev(DEVICE_BUS_PCI);
179 	while (dev_hdr) {
180 		unsigned char srcbusirq;
181 		struct pci_device_header *pci_hdr = dev_hdr->data;
182 
183 		srcbusirq = (pci_hdr->subsys_id << 2) | (pci_hdr->irq_pin - 1);
184 		mpc_intsrc = last_addr;
185 		mptable_add_irq_src(mpc_intsrc, pcibusid, srcbusirq, ioapicid, pci_hdr->irq_line);
186 
187 		last_addr = (void *)&mpc_intsrc[1];
188 		nentries++;
189 		dev_hdr = device__next_dev(dev_hdr);
190 	}
191 
192 	/*
193 	 * Local IRQs assignment (LINT0, LINT1)
194 	 */
195 	mpc_intsrc		= last_addr;
196 	mpc_intsrc->type	= MP_LINTSRC;
197 	mpc_intsrc->irqtype	= mp_ExtINT;
198 	mpc_intsrc->irqtype	= mp_INT;
199 	mpc_intsrc->irqflag	= MP_IRQDIR_DEFAULT;
200 	mpc_intsrc->srcbus	= isabusid;
201 	mpc_intsrc->srcbusirq	= 0;
202 	mpc_intsrc->dstapic	= 0; /* FIXME: BSP apic */
203 	mpc_intsrc->dstirq	= 0; /* LINT0 */
204 
205 	last_addr = (void *)&mpc_intsrc[1];
206 	nentries++;
207 
208 	mpc_intsrc		= last_addr;
209 	mpc_intsrc->type	= MP_LINTSRC;
210 	mpc_intsrc->irqtype	= mp_NMI;
211 	mpc_intsrc->irqflag	= MP_IRQDIR_DEFAULT;
212 	mpc_intsrc->srcbus	= isabusid;
213 	mpc_intsrc->srcbusirq	= 0;
214 	mpc_intsrc->dstapic	= 0; /* FIXME: BSP apic */
215 	mpc_intsrc->dstirq	= 1; /* LINT1 */
216 
217 	last_addr = (void *)&mpc_intsrc[1];
218 	nentries++;
219 
220 	/*
221 	 * Floating MP table finally.
222 	 */
223 	real_mpf_intel	= ALIGN((unsigned long)last_addr - (unsigned long)mpc_table, 16);
224 	mpf_intel	= (void *)((unsigned long)mpc_table + real_mpf_intel);
225 
226 	MPTABLE_STRNCPY(mpf_intel->signature, MPTABLE_SIG_FLOATING);
227 	mpf_intel->length	= 1;
228 	mpf_intel->specification= 4;
229 	mpf_intel->physptr	= (unsigned int)real_mpc_table;
230 	mpf_intel->checksum	= -mpf_checksum((unsigned char *)mpf_intel, sizeof(*mpf_intel));
231 
232 	/*
233 	 * No last_addr inclrement here please, we need last
234 	 * active position here to compute table size.
235 	 */
236 
237 	/*
238 	 * Don't forget to update header in fixed table.
239 	*/
240 	mpc_table->oemcount	= nentries;
241 	mpc_table->length	= last_addr - (void *)mpc_table;
242 	mpc_table->checksum	= -mpf_checksum((unsigned char *)mpc_table, mpc_table->length);
243 
244 
245 	/*
246 	 * We will copy the whole table, no need to separate
247 	 * floating structure and table itkvm.
248 	 */
249 	size = (unsigned long)mpf_intel + sizeof(*mpf_intel) - (unsigned long)mpc_table;
250 
251 	/*
252 	 * The finial check -- never get out of system bios
253 	 * area. Lets also check for allocated memory overrun,
254 	 * in real it's late but still usefull.
255 	 */
256 
257 	if (size > (unsigned long)(MB_BIOS_END - bios_rom_size) ||
258 	    size > MPTABLE_MAX_SIZE) {
259 		free(mpc_table);
260 		pr_err("MP table is too big");
261 
262 		return -E2BIG;
263 	}
264 
265 	/*
266 	 * OK, it is time to move it to guest memory.
267 	 */
268 	memcpy(guest_flat_to_host(kvm, real_mpc_table), mpc_table, size);
269 
270 	free(mpc_table);
271 
272 	return 0;
273 }
274 firmware_init(mptable__init);
275 
mptable__exit(struct kvm * kvm)276 int mptable__exit(struct kvm *kvm)
277 {
278 	return 0;
279 }
280 firmware_exit(mptable__exit);
281