blob: f17930f0a592eb69c10aeb84d24e1d5806a08e55 [file] [log] [blame]
Kevin O'Connore7cc7642009-10-04 10:05:16 -04001// Paravirtualization support.
2//
3// Copyright (C) 2009 Red Hat Inc.
4//
5// Authors:
6// Gleb Natapov <gnatapov@redhat.com>
7//
8// This file may be distributed under the terms of the GNU LGPLv3 license.
9
Kevin O'Connor897fb112013-02-07 23:32:48 -050010#include "config.h" // CONFIG_QEMU
Kevin O'Connorb3064592012-08-14 21:20:10 -040011#include "util.h" // dprintf
12#include "byteorder.h" // be32_to_cpu
Kevin O'Connor01a85202009-10-18 09:49:59 -040013#include "ioport.h" // outw
Kevin O'Connord83c87b2013-01-21 01:14:12 -050014#include "paravirt.h" // qemu_cfg_preinit
Kevin O'Connor01a85202009-10-18 09:49:59 -040015#include "smbios.h" // struct smbios_structure_header
Kevin O'Connor8ed2e532013-01-21 02:32:48 -050016#include "memmap.h" // add_e820
17#include "cmos.h" // CMOS_*
18#include "acpi.h" // acpi_setup
19#include "mptable.h" // mptable_setup
20#include "pci.h" // create_pirtable
Kevin O'Connore7cc7642009-10-04 10:05:16 -040021
Kevin O'Connor4edda082013-02-09 13:21:08 -050022struct e820_reservation {
23 u64 address;
24 u64 length;
25 u32 type;
26};
Kevin O'Connore7cc7642009-10-04 10:05:16 -040027
Kevin O'Connor7b5bc502013-02-09 13:07:23 -050028/* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx. It
29 * should be used to determine that a VM is running under KVM.
30 */
31#define KVM_CPUID_SIGNATURE 0x40000000
32
33static void kvm_preinit(void)
34{
35 if (!CONFIG_QEMU)
36 return;
37 unsigned int eax, ebx, ecx, edx;
38 char signature[13];
39
40 cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx);
41 memcpy(signature + 0, &ebx, 4);
42 memcpy(signature + 4, &ecx, 4);
43 memcpy(signature + 8, &edx, 4);
44 signature[12] = 0;
45
46 if (strcmp(signature, "KVMKVMKVM") == 0) {
47 dprintf(1, "Running on KVM\n");
48 PlatformRunningOn |= PF_KVM;
49 }
50}
51
Kevin O'Connor8ed2e532013-01-21 02:32:48 -050052void
53qemu_ramsize_preinit(void)
54{
Kevin O'Connor02313b22013-02-07 22:42:25 -050055 if (!CONFIG_QEMU)
56 return;
57
58 PlatformRunningOn = PF_QEMU;
Kevin O'Connor7b5bc502013-02-09 13:07:23 -050059 kvm_preinit();
Kevin O'Connor02313b22013-02-07 22:42:25 -050060
Kevin O'Connor8ed2e532013-01-21 02:32:48 -050061 // On emulators, get memory size from nvram.
62 u32 rs = ((inb_cmos(CMOS_MEM_EXTMEM2_LOW) << 16)
63 | (inb_cmos(CMOS_MEM_EXTMEM2_HIGH) << 24));
64 if (rs)
65 rs += 16 * 1024 * 1024;
66 else
67 rs = (((inb_cmos(CMOS_MEM_EXTMEM_LOW) << 10)
68 | (inb_cmos(CMOS_MEM_EXTMEM_HIGH) << 18))
69 + 1 * 1024 * 1024);
70 RamSize = rs;
71 add_e820(0, rs, E820_RAM);
72
73 // Check for memory over 4Gig
74 u64 high = ((inb_cmos(CMOS_MEM_HIGHMEM_LOW) << 16)
75 | ((u32)inb_cmos(CMOS_MEM_HIGHMEM_MID) << 24)
76 | ((u64)inb_cmos(CMOS_MEM_HIGHMEM_HIGH) << 32));
77 RamSizeOver4G = high;
78 add_e820(0x100000000ull, high, E820_RAM);
79
80 /* reserve 256KB BIOS area at the end of 4 GB */
81 add_e820(0xfffc0000, 256*1024, E820_RESERVED);
82
83 u32 count = qemu_cfg_e820_entries();
84 if (count) {
85 struct e820_reservation entry;
86 int i;
87
88 for (i = 0; i < count; i++) {
89 qemu_cfg_e820_load_next(&entry);
90 add_e820(entry.address, entry.length, entry.type);
91 }
Kevin O'Connor7b5bc502013-02-09 13:07:23 -050092 } else if (runningOnKVM()) {
Kevin O'Connor8ed2e532013-01-21 02:32:48 -050093 // Backwards compatibility - provide hard coded range.
94 // 4 pages before the bios, 3 pages for vmx tss pages, the
95 // other page for EPT real mode pagetable
96 add_e820(0xfffbc000, 4*4096, E820_RESERVED);
97 }
98}
99
100void
101qemu_biostable_setup(void)
102{
103 pirtable_setup();
104 mptable_setup();
105 smbios_setup();
106 acpi_setup();
107}
108
Kevin O'Connor4edda082013-02-09 13:21:08 -0500109
110/****************************************************************
111 * QEMU firmware config (fw_cfg) interface
112 ****************************************************************/
113
114int qemu_cfg_present;
115
116#define QEMU_CFG_SIGNATURE 0x00
117#define QEMU_CFG_ID 0x01
118#define QEMU_CFG_UUID 0x02
119#define QEMU_CFG_NUMA 0x0d
120#define QEMU_CFG_BOOT_MENU 0x0e
121#define QEMU_CFG_MAX_CPUS 0x0f
122#define QEMU_CFG_FILE_DIR 0x19
123#define QEMU_CFG_ARCH_LOCAL 0x8000
124#define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0)
125#define QEMU_CFG_SMBIOS_ENTRIES (QEMU_CFG_ARCH_LOCAL + 1)
126#define QEMU_CFG_IRQ0_OVERRIDE (QEMU_CFG_ARCH_LOCAL + 2)
127#define QEMU_CFG_E820_TABLE (QEMU_CFG_ARCH_LOCAL + 3)
128
Kevin O'Connore7cc7642009-10-04 10:05:16 -0400129static void
130qemu_cfg_select(u16 f)
131{
132 outw(f, PORT_QEMU_CFG_CTL);
133}
134
135static void
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -0500136qemu_cfg_read(void *buf, int len)
Kevin O'Connore7cc7642009-10-04 10:05:16 -0400137{
Kevin O'Connor6039fc52010-08-25 21:43:19 -0400138 insb(PORT_QEMU_CFG_DATA, buf, len);
Kevin O'Connore7cc7642009-10-04 10:05:16 -0400139}
140
141static void
Kevin O'Connor4e4b4102009-10-08 21:21:59 -0400142qemu_cfg_skip(int len)
143{
144 while (len--)
145 inb(PORT_QEMU_CFG_DATA);
146}
147
148static void
Kevin O'Connore7cc7642009-10-04 10:05:16 -0400149qemu_cfg_read_entry(void *buf, int e, int len)
150{
151 qemu_cfg_select(e);
152 qemu_cfg_read(buf, len);
153}
154
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500155void qemu_cfg_preinit(void)
Kevin O'Connore7cc7642009-10-04 10:05:16 -0400156{
157 char *sig = "QEMU";
158 int i;
159
Kevin O'Connor897fb112013-02-07 23:32:48 -0500160 if (!CONFIG_QEMU)
Kevin O'Connore7cc7642009-10-04 10:05:16 -0400161 return;
162
163 qemu_cfg_present = 1;
164
165 qemu_cfg_select(QEMU_CFG_SIGNATURE);
166
167 for (i = 0; i < 4; i++)
168 if (inb(PORT_QEMU_CFG_DATA) != sig[i]) {
169 qemu_cfg_present = 0;
170 break;
171 }
172 dprintf(4, "qemu_cfg_present=%d\n", qemu_cfg_present);
173}
174
175void qemu_cfg_get_uuid(u8 *uuid)
176{
177 if (!qemu_cfg_present)
178 return;
179
180 qemu_cfg_read_entry(uuid, QEMU_CFG_UUID, 16);
181}
182
183int qemu_cfg_show_boot_menu(void)
184{
185 u16 v;
186 if (!qemu_cfg_present)
187 return 1;
188
189 qemu_cfg_read_entry(&v, QEMU_CFG_BOOT_MENU, sizeof(v));
190
191 return v;
192}
193
Kevin O'Connor4d2b6192009-10-08 21:37:21 -0400194int qemu_cfg_irq0_override(void)
195{
196 u8 v;
197
198 if (!qemu_cfg_present)
199 return 0;
200
201 qemu_cfg_read_entry(&v, QEMU_CFG_IRQ0_OVERRIDE, sizeof(v));
202
203 return v;
204}
205
Kevin O'Connor4e4b4102009-10-08 21:21:59 -0400206u16 qemu_cfg_smbios_entries(void)
207{
208 u16 cnt;
209
210 if (!qemu_cfg_present)
211 return 0;
212
213 qemu_cfg_read_entry(&cnt, QEMU_CFG_SMBIOS_ENTRIES, sizeof(cnt));
214
215 return cnt;
216}
217
Jes Sorensen0360e8e2010-02-16 09:46:08 +0100218u32 qemu_cfg_e820_entries(void)
219{
220 u32 cnt;
221
222 if (!qemu_cfg_present)
223 return 0;
224
225 qemu_cfg_read_entry(&cnt, QEMU_CFG_E820_TABLE, sizeof(cnt));
226 return cnt;
227}
228
229void* qemu_cfg_e820_load_next(void *addr)
230{
231 qemu_cfg_read(addr, sizeof(struct e820_reservation));
232 return addr;
233}
234
Kevin O'Connor4e4b4102009-10-08 21:21:59 -0400235struct smbios_header {
236 u16 length;
237 u8 type;
238} PACKED;
239
240struct smbios_field {
241 struct smbios_header header;
242 u8 type;
243 u16 offset;
244 u8 data[];
245} PACKED;
246
247struct smbios_table {
248 struct smbios_header header;
249 u8 data[];
250} PACKED;
251
252#define SMBIOS_FIELD_ENTRY 0
253#define SMBIOS_TABLE_ENTRY 1
254
255size_t qemu_cfg_smbios_load_field(int type, size_t offset, void *addr)
256{
257 int i;
258
259 for (i = qemu_cfg_smbios_entries(); i > 0; i--) {
260 struct smbios_field field;
261
262 qemu_cfg_read((u8 *)&field, sizeof(struct smbios_header));
263 field.header.length -= sizeof(struct smbios_header);
264
265 if (field.header.type != SMBIOS_FIELD_ENTRY) {
266 qemu_cfg_skip(field.header.length);
267 continue;
268 }
269
270 qemu_cfg_read((u8 *)&field.type,
271 sizeof(field) - sizeof(struct smbios_header));
272 field.header.length -= sizeof(field) - sizeof(struct smbios_header);
273
274 if (field.type != type || field.offset != offset) {
275 qemu_cfg_skip(field.header.length);
276 continue;
277 }
278
279 qemu_cfg_read(addr, field.header.length);
280 return (size_t)field.header.length;
281 }
282 return 0;
283}
284
Kevin O'Connor4e4b4102009-10-08 21:21:59 -0400285int qemu_cfg_smbios_load_external(int type, char **p, unsigned *nr_structs,
286 unsigned *max_struct_size, char *end)
287{
288 static u64 used_bitmap[4] = { 0 };
289 char *start = *p;
290 int i;
291
292 /* Check if we've already reported these tables */
293 if (used_bitmap[(type >> 6) & 0x3] & (1ULL << (type & 0x3f)))
294 return 1;
295
296 /* Don't introduce spurious end markers */
297 if (type == 127)
298 return 0;
299
300 for (i = qemu_cfg_smbios_entries(); i > 0; i--) {
301 struct smbios_table table;
302 struct smbios_structure_header *header = (void *)*p;
303 int string;
304
305 qemu_cfg_read((u8 *)&table, sizeof(struct smbios_header));
306 table.header.length -= sizeof(struct smbios_header);
307
308 if (table.header.type != SMBIOS_TABLE_ENTRY) {
309 qemu_cfg_skip(table.header.length);
310 continue;
311 }
312
313 if (end - *p < sizeof(struct smbios_structure_header)) {
Kevin O'Connorcfdc13f2010-02-14 13:07:54 -0500314 warn_noalloc();
Kevin O'Connor4e4b4102009-10-08 21:21:59 -0400315 break;
316 }
317
318 qemu_cfg_read((u8 *)*p, sizeof(struct smbios_structure_header));
319 table.header.length -= sizeof(struct smbios_structure_header);
320
321 if (header->type != type) {
322 qemu_cfg_skip(table.header.length);
323 continue;
324 }
325
326 *p += sizeof(struct smbios_structure_header);
327
328 /* Entries end with a double NULL char, if there's a string at
329 * the end (length is greater than formatted length), the string
330 * terminator provides the first NULL. */
331 string = header->length < table.header.length +
332 sizeof(struct smbios_structure_header);
333
334 /* Read the rest and terminate the entry */
335 if (end - *p < table.header.length) {
Kevin O'Connorcfdc13f2010-02-14 13:07:54 -0500336 warn_noalloc();
Kevin O'Connor4e4b4102009-10-08 21:21:59 -0400337 *p -= sizeof(struct smbios_structure_header);
338 continue;
339 }
340 qemu_cfg_read((u8 *)*p, table.header.length);
341 *p += table.header.length;
342 *((u8*)*p) = 0;
343 (*p)++;
344 if (!string) {
345 *((u8*)*p) = 0;
346 (*p)++;
347 }
348
349 (*nr_structs)++;
350 if (*p - (char *)header > *max_struct_size)
351 *max_struct_size = *p - (char *)header;
352 }
353
354 if (start != *p) {
355 /* Mark that we've reported on this type */
356 used_bitmap[(type >> 6) & 0x3] |= (1ULL << (type & 0x3f));
357 return 1;
358 }
359
360 return 0;
361}
362
Kevin O'Connor590e5542009-10-08 22:09:02 -0400363int qemu_cfg_get_numa_nodes(void)
364{
365 u64 cnt;
366
367 qemu_cfg_read_entry(&cnt, QEMU_CFG_NUMA, sizeof(cnt));
368
369 return (int)cnt;
370}
371
372void qemu_cfg_get_numa_data(u64 *data, int n)
373{
374 int i;
375
376 for (i = 0; i < n; i++)
377 qemu_cfg_read((u8*)(data + i), sizeof(u64));
378}
Kevin O'Connor84705852009-10-08 22:13:15 -0400379
380u16 qemu_cfg_get_max_cpus(void)
381{
382 u16 cnt;
383
384 if (!qemu_cfg_present)
385 return 0;
386
387 qemu_cfg_read_entry(&cnt, QEMU_CFG_MAX_CPUS, sizeof(cnt));
388
389 return cnt;
390}
Gerd Hoffmannc4c9fae2009-12-18 12:16:04 +0100391
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -0500392static int
393qemu_cfg_read_file(struct romfile_s *file, void *dst, u32 maxlen)
Gerd Hoffmannc4c9fae2009-12-18 12:16:04 +0100394{
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400395 if (file->size > maxlen)
396 return -1;
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -0500397 qemu_cfg_select(file->id);
398 qemu_cfg_skip(file->rawsize);
399 qemu_cfg_read(dst, file->size);
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400400 return file->size;
401}
402
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -0500403static void
404qemu_romfile_add(char *name, int select, int skip, int size)
405{
406 struct romfile_s *file = malloc_tmp(sizeof(*file));
407 if (!file) {
408 warn_noalloc();
409 return;
410 }
411 memset(file, 0, sizeof(*file));
412 strtcpy(file->name, name, sizeof(file->name));
413 file->id = select;
414 file->rawsize = skip; // Use rawsize to indicate skip length.
415 file->size = size;
416 file->copy = qemu_cfg_read_file;
417 romfile_add(file);
418}
419
Kevin O'Connor188d9942013-02-09 15:24:08 -0500420// Populate romfile entries for legacy fw_cfg ports (that predate the
421// "file" interface).
422static void
423qemu_cfg_legacy(void)
424{
425 // ACPI tables
426 char name[128];
427 u16 cnt;
428 qemu_cfg_read_entry(&cnt, QEMU_CFG_ACPI_TABLES, sizeof(cnt));
429 int i, offset = sizeof(cnt);
430 for (i = 0; i < cnt; i++) {
431 u16 len;
432 qemu_cfg_read(&len, sizeof(len));
433 offset += sizeof(len);
434 snprintf(name, sizeof(name), "acpi/table%d", i);
435 qemu_romfile_add(name, QEMU_CFG_ACPI_TABLES, offset, len);
436 qemu_cfg_skip(len);
437 offset += len;
438 }
439}
440
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400441struct QemuCfgFile {
442 u32 size; /* file size */
443 u16 select; /* write this to 0x510 to read it */
444 u16 reserved;
445 char name[56];
446};
447
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500448void qemu_romfile_init(void)
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400449{
Kevin O'Connor897fb112013-02-07 23:32:48 -0500450 if (!CONFIG_QEMU || !qemu_cfg_present)
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400451 return;
Gerd Hoffmannc4c9fae2009-12-18 12:16:04 +0100452
Kevin O'Connor188d9942013-02-09 15:24:08 -0500453 // Populate romfiles for legacy fw_cfg entries
454 qemu_cfg_legacy();
455
456 // Load files found in the fw_cfg file directory
Kevin O'Connore2304262010-06-13 16:05:17 -0400457 u32 count;
Gerd Hoffmannc4c9fae2009-12-18 12:16:04 +0100458 qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count));
Kevin O'Connorb3064592012-08-14 21:20:10 -0400459 count = be32_to_cpu(count);
Kevin O'Connore2304262010-06-13 16:05:17 -0400460 u32 e;
461 for (e = 0; e < count; e++) {
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400462 struct QemuCfgFile qfile;
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -0500463 qemu_cfg_read(&qfile, sizeof(qfile));
464 qemu_romfile_add(qfile.name, be16_to_cpu(qfile.select)
465 , 0, be32_to_cpu(qfile.size));
Gerd Hoffmannc4c9fae2009-12-18 12:16:04 +0100466 }
Kevin O'Connor8b565782011-07-05 20:32:44 -0400467}