blob: 58973a2b105982b4d300df018bbe61438e518075 [file] [log] [blame]
Kevin O'Connore7cc7642009-10-04 10:05:16 -04001// Paravirtualization support.
2//
Kevin O'Connorb840ba92013-02-09 20:09:22 -05003// Copyright (C) 2013 Kevin O'Connor <kevin@koconnor.net>
Kevin O'Connore7cc7642009-10-04 10:05:16 -04004// Copyright (C) 2009 Red Hat Inc.
5//
6// Authors:
7// Gleb Natapov <gnatapov@redhat.com>
8//
9// This file may be distributed under the terms of the GNU LGPLv3 license.
10
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040011#include "byteorder.h" // be32_to_cpu
12#include "config.h" // CONFIG_QEMU
Kevin O'Connor5d369d82013-09-02 20:48:46 -040013#include "hw/pci.h" // create_pirtable
Gerd Hoffmannebfece82013-09-03 11:41:01 +020014#include "hw/pci_regs.h" // PCI_DEVICE_ID
Kevin O'Connor8b7861c2013-09-15 02:29:06 -040015#include "hw/rtc.h" // CMOS_*
Kevin O'Connor9dea5902013-09-14 20:23:54 -040016#include "malloc.h" // malloc_tmp
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040017#include "memmap.h" // add_e820
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040018#include "output.h" // dprintf
19#include "paravirt.h" // qemu_cfg_preinit
Kevin O'Connor41639f82013-09-14 19:37:36 -040020#include "romfile.h" // romfile_loadint
Kevin O'Connorfa9c66a2013-09-14 19:10:40 -040021#include "string.h" // memset
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040022#include "util.h" // pci_setup
Kevin O'Connorb9c6a962013-09-14 13:01:30 -040023#include "x86.h" // cpuid
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040024#include "xen.h" // xen_biostable_setup
Kevin O'Connore7cc7642009-10-04 10:05:16 -040025
Kevin O'Connorf85e4bc2013-02-19 01:33:45 -050026// Amount of continuous ram under 4Gig
27u32 RamSize;
28// Amount of continuous ram >4Gig
29u64 RamSizeOver4G;
Kevin O'Connor89a2f962013-02-18 23:36:03 -050030// Type of emulator platform.
31int PlatformRunningOn VARFSEG;
32
Kevin O'Connor7b5bc502013-02-09 13:07:23 -050033/* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx. It
34 * should be used to determine that a VM is running under KVM.
35 */
36#define KVM_CPUID_SIGNATURE 0x40000000
37
Gerd Hoffmannebfece82013-09-03 11:41:01 +020038static void kvm_detect(void)
Kevin O'Connor7b5bc502013-02-09 13:07:23 -050039{
Kevin O'Connor7b5bc502013-02-09 13:07:23 -050040 unsigned int eax, ebx, ecx, edx;
41 char signature[13];
42
43 cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx);
44 memcpy(signature + 0, &ebx, 4);
45 memcpy(signature + 4, &ecx, 4);
46 memcpy(signature + 8, &edx, 4);
47 signature[12] = 0;
48
49 if (strcmp(signature, "KVMKVMKVM") == 0) {
50 dprintf(1, "Running on KVM\n");
51 PlatformRunningOn |= PF_KVM;
52 }
53}
54
Gerd Hoffmannebfece82013-09-03 11:41:01 +020055static void qemu_detect(void)
56{
57 if (!CONFIG_QEMU_HARDWARE)
58 return;
59
60 // check northbridge @ 00:00.0
61 u16 v = pci_config_readw(0, PCI_VENDOR_ID);
62 if (v == 0x0000 || v == 0xffff)
63 return;
64 u16 d = pci_config_readw(0, PCI_DEVICE_ID);
65 u16 sv = pci_config_readw(0, PCI_SUBSYSTEM_VENDOR_ID);
66 u16 sd = pci_config_readw(0, PCI_SUBSYSTEM_ID);
67
68 if (sv != 0x1af4 || /* Red Hat, Inc */
69 sd != 0x1100) /* Qemu virtual machine */
70 return;
71
72 PlatformRunningOn |= PF_QEMU;
73 switch (d) {
74 case 0x1237:
75 dprintf(1, "Running on QEMU (i440fx)\n");
76 break;
77 case 0x29c0:
78 dprintf(1, "Running on QEMU (q35)\n");
79 break;
80 default:
81 dprintf(1, "Running on QEMU (unknown nb: %04x:%04x)\n", v, d);
82 break;
83 }
84 kvm_detect();
85}
86
Kevin O'Connor8ed2e532013-01-21 02:32:48 -050087void
Kevin O'Connora2a86e22013-02-13 19:35:12 -050088qemu_preinit(void)
Kevin O'Connor8ed2e532013-01-21 02:32:48 -050089{
Gerd Hoffmannebfece82013-09-03 11:41:01 +020090 qemu_detect();
91
Kevin O'Connor02313b22013-02-07 22:42:25 -050092 if (!CONFIG_QEMU)
93 return;
94
Kevin O'Connora2a86e22013-02-13 19:35:12 -050095 if (runningOnXen()) {
96 xen_ramsize_preinit();
97 return;
98 }
99
Gerd Hoffmannebfece82013-09-03 11:41:01 +0200100 if (!runningOnQEMU()) {
101 dprintf(1, "Warning: No QEMU Northbridge found (isapc?)\n");
102 PlatformRunningOn |= PF_QEMU;
103 kvm_detect();
104 }
Kevin O'Connor02313b22013-02-07 22:42:25 -0500105
Kevin O'Connor8ed2e532013-01-21 02:32:48 -0500106 // On emulators, get memory size from nvram.
Kevin O'Connor8b7861c2013-09-15 02:29:06 -0400107 u32 rs = ((rtc_read(CMOS_MEM_EXTMEM2_LOW) << 16)
108 | (rtc_read(CMOS_MEM_EXTMEM2_HIGH) << 24));
Kevin O'Connor8ed2e532013-01-21 02:32:48 -0500109 if (rs)
110 rs += 16 * 1024 * 1024;
111 else
Kevin O'Connor8b7861c2013-09-15 02:29:06 -0400112 rs = (((rtc_read(CMOS_MEM_EXTMEM_LOW) << 10)
113 | (rtc_read(CMOS_MEM_EXTMEM_HIGH) << 18))
Kevin O'Connor8ed2e532013-01-21 02:32:48 -0500114 + 1 * 1024 * 1024);
115 RamSize = rs;
116 add_e820(0, rs, E820_RAM);
117
Kevin O'Connor8ed2e532013-01-21 02:32:48 -0500118 /* reserve 256KB BIOS area at the end of 4 GB */
119 add_e820(0xfffc0000, 256*1024, E820_RESERVED);
Kevin O'Connorf85e4bc2013-02-19 01:33:45 -0500120
Gerd Hoffmann6e1b0822013-10-18 12:18:19 +0200121 dprintf(1, "RamSize: 0x%08x [cmos]\n", RamSize);
Kevin O'Connor8ed2e532013-01-21 02:32:48 -0500122}
123
124void
Kevin O'Connora2a86e22013-02-13 19:35:12 -0500125qemu_platform_setup(void)
Kevin O'Connor8ed2e532013-01-21 02:32:48 -0500126{
Kevin O'Connora2a86e22013-02-13 19:35:12 -0500127 if (!CONFIG_QEMU)
128 return;
129
130 if (runningOnXen()) {
131 pci_probe_devices();
132 xen_hypercall_setup();
133 xen_biostable_setup();
134 return;
135 }
136
137 // Initialize pci
138 pci_setup();
Kevin O'Connorcdbac7f2013-03-08 19:33:39 -0500139 smm_device_setup();
Kevin O'Connora2a86e22013-02-13 19:35:12 -0500140 smm_setup();
141
142 // Initialize mtrr and smp
143 mtrr_setup();
144 smp_setup();
145
146 // Create bios tables
Kevin O'Connor8ed2e532013-01-21 02:32:48 -0500147 pirtable_setup();
148 mptable_setup();
149 smbios_setup();
150 acpi_setup();
151}
152
Kevin O'Connor4edda082013-02-09 13:21:08 -0500153
154/****************************************************************
155 * QEMU firmware config (fw_cfg) interface
156 ****************************************************************/
157
Kevin O'Connorb840ba92013-02-09 20:09:22 -0500158// List of QEMU fw_cfg entries. DO NOT ADD MORE. (All new content
159// should be passed via the fw_cfg "file" interface.)
Kevin O'Connor4edda082013-02-09 13:21:08 -0500160#define QEMU_CFG_SIGNATURE 0x00
161#define QEMU_CFG_ID 0x01
162#define QEMU_CFG_UUID 0x02
163#define QEMU_CFG_NUMA 0x0d
164#define QEMU_CFG_BOOT_MENU 0x0e
165#define QEMU_CFG_MAX_CPUS 0x0f
166#define QEMU_CFG_FILE_DIR 0x19
167#define QEMU_CFG_ARCH_LOCAL 0x8000
168#define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0)
169#define QEMU_CFG_SMBIOS_ENTRIES (QEMU_CFG_ARCH_LOCAL + 1)
170#define QEMU_CFG_IRQ0_OVERRIDE (QEMU_CFG_ARCH_LOCAL + 2)
171#define QEMU_CFG_E820_TABLE (QEMU_CFG_ARCH_LOCAL + 3)
172
Kevin O'Connore7cc7642009-10-04 10:05:16 -0400173static void
174qemu_cfg_select(u16 f)
175{
176 outw(f, PORT_QEMU_CFG_CTL);
177}
178
179static void
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -0500180qemu_cfg_read(void *buf, int len)
Kevin O'Connore7cc7642009-10-04 10:05:16 -0400181{
Kevin O'Connor6039fc52010-08-25 21:43:19 -0400182 insb(PORT_QEMU_CFG_DATA, buf, len);
Kevin O'Connore7cc7642009-10-04 10:05:16 -0400183}
184
185static void
Kevin O'Connor4e4b4102009-10-08 21:21:59 -0400186qemu_cfg_skip(int len)
187{
188 while (len--)
189 inb(PORT_QEMU_CFG_DATA);
190}
191
192static void
Kevin O'Connore7cc7642009-10-04 10:05:16 -0400193qemu_cfg_read_entry(void *buf, int e, int len)
194{
195 qemu_cfg_select(e);
196 qemu_cfg_read(buf, len);
197}
198
Kevin O'Connor4158c8c2013-03-30 09:12:11 -0400199struct qemu_romfile_s {
200 struct romfile_s file;
201 int select, skip;
202};
203
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -0500204static int
205qemu_cfg_read_file(struct romfile_s *file, void *dst, u32 maxlen)
Gerd Hoffmannc4c9fae2009-12-18 12:16:04 +0100206{
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400207 if (file->size > maxlen)
208 return -1;
Kevin O'Connor4158c8c2013-03-30 09:12:11 -0400209 struct qemu_romfile_s *qfile;
210 qfile = container_of(file, struct qemu_romfile_s, file);
211 qemu_cfg_select(qfile->select);
212 qemu_cfg_skip(qfile->skip);
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -0500213 qemu_cfg_read(dst, file->size);
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400214 return file->size;
215}
216
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -0500217static void
218qemu_romfile_add(char *name, int select, int skip, int size)
219{
Kevin O'Connor4158c8c2013-03-30 09:12:11 -0400220 struct qemu_romfile_s *qfile = malloc_tmp(sizeof(*qfile));
221 if (!qfile) {
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -0500222 warn_noalloc();
223 return;
224 }
Kevin O'Connor4158c8c2013-03-30 09:12:11 -0400225 memset(qfile, 0, sizeof(*qfile));
226 strtcpy(qfile->file.name, name, sizeof(qfile->file.name));
227 qfile->file.size = size;
228 qfile->select = select;
229 qfile->skip = skip;
230 qfile->file.copy = qemu_cfg_read_file;
231 romfile_add(&qfile->file);
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -0500232}
233
Kevin O'Connorfe090302013-02-09 20:00:06 -0500234struct e820_reservation {
235 u64 address;
236 u64 length;
237 u32 type;
238};
239
Kevin O'Connorde9e7052013-02-09 19:09:20 -0500240#define SMBIOS_FIELD_ENTRY 0
241#define SMBIOS_TABLE_ENTRY 1
242
243struct qemu_smbios_header {
244 u16 length;
245 u8 headertype;
246 u8 tabletype;
247 u16 fieldoffset;
248} PACKED;
249
Gerd Hoffmann6e1b0822013-10-18 12:18:19 +0200250static void
251qemu_cfg_e820(void)
252{
253 // QEMU_CFG_E820_TABLE has reservations only
254 u32 count32;
255 qemu_cfg_read_entry(&count32, QEMU_CFG_E820_TABLE, sizeof(count32));
256 if (count32) {
257 struct e820_reservation entry;
258 int i;
259 for (i = 0; i < count32; i++) {
260 qemu_cfg_read(&entry, sizeof(entry));
261 add_e820(entry.address, entry.length, entry.type);
262 }
263 } else if (runningOnKVM()) {
264 // Backwards compatibility - provide hard coded range.
265 // 4 pages before the bios, 3 pages for vmx tss pages, the
266 // other page for EPT real mode pagetable
267 add_e820(0xfffbc000, 4*4096, E820_RESERVED);
268 }
269
270 // Check for memory over 4Gig in cmos
271 u64 high = ((rtc_read(CMOS_MEM_HIGHMEM_LOW) << 16)
272 | ((u32)rtc_read(CMOS_MEM_HIGHMEM_MID) << 24)
273 | ((u64)rtc_read(CMOS_MEM_HIGHMEM_HIGH) << 32));
274 RamSizeOver4G = high;
275 add_e820(0x100000000ull, high, E820_RAM);
276 dprintf(1, "RamSizeOver4G: 0x%016llx [cmos]\n", RamSizeOver4G);
277}
278
Kevin O'Connor188d9942013-02-09 15:24:08 -0500279// Populate romfile entries for legacy fw_cfg ports (that predate the
280// "file" interface).
281static void
282qemu_cfg_legacy(void)
283{
Kevin O'Connor7507ce22013-06-13 20:04:31 -0400284 if (!CONFIG_QEMU)
285 return;
286
Kevin O'Connor56c50892013-02-09 19:25:51 -0500287 // Misc config items.
288 qemu_romfile_add("etc/show-boot-menu", QEMU_CFG_BOOT_MENU, 0, 2);
289 qemu_romfile_add("etc/irq0-override", QEMU_CFG_IRQ0_OVERRIDE, 0, 1);
290 qemu_romfile_add("etc/max-cpus", QEMU_CFG_MAX_CPUS, 0, 2);
291
Kevin O'Connorf9e4e372013-02-09 19:45:45 -0500292 // NUMA data
293 u64 numacount;
294 qemu_cfg_read_entry(&numacount, QEMU_CFG_NUMA, sizeof(numacount));
Kevin O'Connorfb76cff2013-03-23 11:38:45 -0400295 int max_cpu = romfile_loadint("etc/max-cpus", 0);
296 qemu_romfile_add("etc/numa-cpu-map", QEMU_CFG_NUMA, sizeof(numacount)
297 , max_cpu*sizeof(u64));
298 qemu_romfile_add("etc/numa-nodes", QEMU_CFG_NUMA
299 , sizeof(numacount) + max_cpu*sizeof(u64)
Kevin O'Connorf9e4e372013-02-09 19:45:45 -0500300 , numacount*sizeof(u64));
301
Kevin O'Connor188d9942013-02-09 15:24:08 -0500302 // ACPI tables
303 char name[128];
304 u16 cnt;
305 qemu_cfg_read_entry(&cnt, QEMU_CFG_ACPI_TABLES, sizeof(cnt));
306 int i, offset = sizeof(cnt);
307 for (i = 0; i < cnt; i++) {
308 u16 len;
309 qemu_cfg_read(&len, sizeof(len));
310 offset += sizeof(len);
311 snprintf(name, sizeof(name), "acpi/table%d", i);
312 qemu_romfile_add(name, QEMU_CFG_ACPI_TABLES, offset, len);
313 qemu_cfg_skip(len);
314 offset += len;
315 }
Kevin O'Connorde9e7052013-02-09 19:09:20 -0500316
317 // SMBIOS info
318 qemu_cfg_read_entry(&cnt, QEMU_CFG_SMBIOS_ENTRIES, sizeof(cnt));
319 offset = sizeof(cnt);
320 for (i = 0; i < cnt; i++) {
321 struct qemu_smbios_header header;
322 qemu_cfg_read(&header, sizeof(header));
323 if (header.headertype == SMBIOS_FIELD_ENTRY) {
324 snprintf(name, sizeof(name), "smbios/field%d-%d"
325 , header.tabletype, header.fieldoffset);
326 qemu_romfile_add(name, QEMU_CFG_SMBIOS_ENTRIES
327 , offset + sizeof(header)
328 , header.length - sizeof(header));
329 } else {
330 snprintf(name, sizeof(name), "smbios/table%d-%d"
331 , header.tabletype, i);
332 qemu_romfile_add(name, QEMU_CFG_SMBIOS_ENTRIES
333 , offset + 3, header.length - 3);
334 }
335 qemu_cfg_skip(header.length - sizeof(header));
336 offset += header.length;
337 }
Kevin O'Connor188d9942013-02-09 15:24:08 -0500338}
339
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400340struct QemuCfgFile {
341 u32 size; /* file size */
342 u16 select; /* write this to 0x510 to read it */
343 u16 reserved;
344 char name[56];
345};
346
Kevin O'Connorb840ba92013-02-09 20:09:22 -0500347void qemu_cfg_init(void)
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400348{
Kevin O'Connor7507ce22013-06-13 20:04:31 -0400349 if (!runningOnQEMU())
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400350 return;
Gerd Hoffmannc4c9fae2009-12-18 12:16:04 +0100351
Kevin O'Connorb840ba92013-02-09 20:09:22 -0500352 // Detect fw_cfg interface.
353 qemu_cfg_select(QEMU_CFG_SIGNATURE);
354 char *sig = "QEMU";
355 int i;
356 for (i = 0; i < 4; i++)
357 if (inb(PORT_QEMU_CFG_DATA) != sig[i])
358 return;
359 dprintf(1, "Found QEMU fw_cfg\n");
360
Kevin O'Connor188d9942013-02-09 15:24:08 -0500361 // Populate romfiles for legacy fw_cfg entries
362 qemu_cfg_legacy();
363
364 // Load files found in the fw_cfg file directory
Kevin O'Connore2304262010-06-13 16:05:17 -0400365 u32 count;
Gerd Hoffmannc4c9fae2009-12-18 12:16:04 +0100366 qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count));
Kevin O'Connorb3064592012-08-14 21:20:10 -0400367 count = be32_to_cpu(count);
Kevin O'Connore2304262010-06-13 16:05:17 -0400368 u32 e;
369 for (e = 0; e < count; e++) {
Kevin O'Connor59d6ca52012-05-31 00:20:55 -0400370 struct QemuCfgFile qfile;
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -0500371 qemu_cfg_read(&qfile, sizeof(qfile));
372 qemu_romfile_add(qfile.name, be16_to_cpu(qfile.select)
373 , 0, be32_to_cpu(qfile.size));
Gerd Hoffmannc4c9fae2009-12-18 12:16:04 +0100374 }
Gerd Hoffmann6e1b0822013-10-18 12:18:19 +0200375
376 qemu_cfg_e820();
Kevin O'Connor8b565782011-07-05 20:32:44 -0400377}