1 // Paravirtualization support.
2 //
3 // Copyright (C) 2013 Kevin O'Connor <kevin@koconnor.net>
4 // 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
11 #include "byteorder.h" // be32_to_cpu
12 #include "config.h" // CONFIG_QEMU
13 #include "e820map.h" // e820_add
14 #include "hw/pci.h" // pci_config_readw
15 #include "hw/pcidevice.h" // pci_probe_devices
16 #include "hw/pci_regs.h" // PCI_DEVICE_ID
17 #include "hw/serialio.h" // PORT_SERIAL1
18 #include "hw/rtc.h" // CMOS_*
19 #include "hw/virtio-mmio.h" // virtio_mmio_acpi
20 #include "malloc.h" // malloc_tmp
21 #include "output.h" // dprintf
22 #include "paravirt.h" // qemu_cfg_preinit
23 #include "romfile.h" // romfile_loadint
24 #include "romfile_loader.h" // romfile_loader_execute
25 #include "string.h" // memset
26 #include "util.h" // pci_setup
27 #include "x86.h" // cpuid
28 #include "xen.h" // xen_biostable_setup
29 #include "stacks.h" // yield
30
31 // Amount of continuous ram under 4Gig
32 u32 RamSize;
33 // Amount of continuous ram >4Gig
34 u64 RamSizeOver4G;
35 // Type of emulator platform.
36 int PlatformRunningOn VARFSEG;
37 // cfg enabled
38 int cfg_enabled = 0;
39 // cfg_dma enabled
40 int cfg_dma_enabled = 0;
41
qemu_cfg_enabled(void)42 inline int qemu_cfg_enabled(void)
43 {
44 return cfg_enabled;
45 }
46
qemu_cfg_dma_enabled(void)47 inline int qemu_cfg_dma_enabled(void)
48 {
49 return cfg_dma_enabled;
50 }
51
52 /* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx. It
53 * should be used to determine that a VM is running under KVM.
54 */
55 #define KVM_CPUID_SIGNATURE 0x40000000
56
kvm_detect(void)57 static void kvm_detect(void)
58 {
59 unsigned int eax, ebx, ecx, edx;
60 char signature[13];
61
62 cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx);
63 memcpy(signature + 0, &ebx, 4);
64 memcpy(signature + 4, &ecx, 4);
65 memcpy(signature + 8, &edx, 4);
66 signature[12] = 0;
67
68 if (strcmp(signature, "KVMKVMKVM") == 0) {
69 dprintf(1, "Running on KVM\n");
70 PlatformRunningOn |= PF_KVM;
71 if (eax >= KVM_CPUID_SIGNATURE + 0x10) {
72 cpuid(KVM_CPUID_SIGNATURE + 0x10, &eax, &ebx, &ecx, &edx);
73 dprintf(1, "kvm: have invtsc, freq %u kHz\n", eax);
74 tsctimer_setfreq(eax, "invtsc");
75 }
76 }
77 }
78
79 #define KVM_FEATURE_CLOCKSOURCE 0
80 #define KVM_FEATURE_CLOCKSOURCE2 3
81
82 #define MSR_KVM_SYSTEM_TIME 0x12
83 #define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01
84
85 #define PVCLOCK_TSC_STABLE_BIT (1 << 0)
86
87 struct pvclock_vcpu_time_info *kvmclock;
88
kvmclock_init(void)89 static void kvmclock_init(void)
90 {
91 unsigned int eax, ebx, ecx, edx, msr;
92
93 if (!runningOnKVM())
94 return;
95
96 cpuid(KVM_CPUID_SIGNATURE + 0x01, &eax, &ebx, &ecx, &edx);
97 if (eax & (1 << KVM_FEATURE_CLOCKSOURCE2))
98 msr = MSR_KVM_SYSTEM_TIME_NEW;
99 else if (eax & (1 << KVM_FEATURE_CLOCKSOURCE))
100 msr = MSR_KVM_SYSTEM_TIME;
101 else
102 return;
103
104 kvmclock = memalign_low(sizeof(*kvmclock), 32);
105 memset(kvmclock, 0, sizeof(*kvmclock));
106 u32 value = (u32)(kvmclock);
107 dprintf(1, "kvmclock: at 0x%x (msr 0x%x)\n", value, msr);
108 wrmsr(msr, value | 0x01);
109
110 if (!(kvmclock->flags & PVCLOCK_TSC_STABLE_BIT))
111 return;
112 u32 MHz = (1000 << 16) / (kvmclock->tsc_to_system_mul >> 16);
113 if (kvmclock->tsc_shift < 0)
114 MHz <<= -kvmclock->tsc_shift;
115 else
116 MHz >>= kvmclock->tsc_shift;
117 dprintf(1, "kvmclock: stable tsc, %d MHz\n", MHz);
118 tsctimer_setfreq(MHz * 1000, "kvmclock");
119 }
120
qemu_detect(void)121 static void qemu_detect(void)
122 {
123 if (!CONFIG_QEMU_HARDWARE)
124 return;
125
126 // Setup QEMU debug output port
127 qemu_debug_preinit();
128
129 // check northbridge @ 00:00.0
130 u16 v = pci_config_readw(0, PCI_VENDOR_ID);
131 if (v == 0x0000 || v == 0xffff)
132 return;
133 u16 d = pci_config_readw(0, PCI_DEVICE_ID);
134 u16 sv = pci_config_readw(0, PCI_SUBSYSTEM_VENDOR_ID);
135 u16 sd = pci_config_readw(0, PCI_SUBSYSTEM_ID);
136
137 if (sv != 0x1af4 || /* Red Hat, Inc */
138 sd != 0x1100) /* Qemu virtual machine */
139 return;
140
141 PlatformRunningOn |= PF_QEMU;
142 switch (d) {
143 case 0x1237:
144 dprintf(1, "Running on QEMU (i440fx)\n");
145 break;
146 case 0x29c0:
147 dprintf(1, "Running on QEMU (q35)\n");
148 break;
149 default:
150 dprintf(1, "Running on QEMU (unknown nb: %04x:%04x)\n", v, d);
151 break;
152 }
153 }
154
155 static int qemu_early_e820(void);
156
157 void
qemu_preinit(void)158 qemu_preinit(void)
159 {
160 qemu_detect();
161 kvm_detect();
162
163 if (!CONFIG_QEMU)
164 return;
165
166 if (runningOnXen()) {
167 xen_ramsize_preinit();
168 return;
169 }
170
171 // try read e820 table first
172 if (!qemu_early_e820()) {
173 // when it fails get memory size from nvram.
174 u32 rs = ((rtc_read(CMOS_MEM_EXTMEM2_LOW) << 16)
175 | (rtc_read(CMOS_MEM_EXTMEM2_HIGH) << 24));
176 if (rs)
177 rs += 16 * 1024 * 1024;
178 else
179 rs = (((rtc_read(CMOS_MEM_EXTMEM_LOW) << 10)
180 | (rtc_read(CMOS_MEM_EXTMEM_HIGH) << 18))
181 + 1 * 1024 * 1024);
182 RamSize = rs;
183 e820_add(0, rs, E820_RAM);
184 dprintf(1, "RamSize: 0x%08x [cmos]\n", RamSize);
185 }
186
187 /* reserve 256KB BIOS area at the end of 4 GB */
188 e820_add(0xfffc0000, 256*1024, E820_RESERVED);
189 }
190
191 #define MSR_IA32_FEATURE_CONTROL 0x0000003a
192
msr_feature_control_setup(void)193 static void msr_feature_control_setup(void)
194 {
195 u64 feature_control_bits = romfile_loadint("etc/msr_feature_control", 0);
196 if (feature_control_bits)
197 wrmsr_smp(MSR_IA32_FEATURE_CONTROL, feature_control_bits);
198 }
199
200 void
qemu_platform_setup(void)201 qemu_platform_setup(void)
202 {
203 if (!CONFIG_QEMU)
204 return;
205
206 if (runningOnXen()) {
207 pci_probe_devices();
208 xen_hypercall_setup();
209 xen_biostable_setup();
210 return;
211 }
212
213 kvmclock_init();
214
215 // Initialize pci
216 pci_setup();
217 smm_device_setup();
218 smm_setup();
219
220 // Initialize mtrr, msr_feature_control and smp
221 mtrr_setup();
222 msr_feature_control_setup();
223 smp_setup();
224
225 // Create bios tables
226 if (MaxCountCPUs <= 255) {
227 pirtable_setup();
228 mptable_setup();
229 }
230 smbios_setup();
231
232 if (CONFIG_FW_ROMFILE_LOAD) {
233 int loader_err;
234
235 dprintf(3, "load ACPI tables\n");
236
237 loader_err = romfile_loader_execute("etc/table-loader");
238
239 RsdpAddr = find_acpi_rsdp();
240
241 if (RsdpAddr) {
242 acpi_dsdt_parse();
243 virtio_mmio_setup_acpi();
244 return;
245 }
246 /* If present, loader should have installed an RSDP.
247 * Not installed? We might still be able to continue
248 * using the builtin RSDP.
249 */
250 if (!loader_err)
251 warn_internalerror();
252 }
253
254 acpi_setup();
255 }
256
257
258 /****************************************************************
259 * QEMU firmware config (fw_cfg) interface
260 ****************************************************************/
261
262 // List of QEMU fw_cfg entries. DO NOT ADD MORE. (All new content
263 // should be passed via the fw_cfg "file" interface.)
264 #define QEMU_CFG_SIGNATURE 0x00
265 #define QEMU_CFG_ID 0x01
266 #define QEMU_CFG_UUID 0x02
267 #define QEMU_CFG_NOGRAPHIC 0x04
268 #define QEMU_CFG_NUMA 0x0d
269 #define QEMU_CFG_BOOT_MENU 0x0e
270 #define QEMU_CFG_NB_CPUS 0x05
271 #define QEMU_CFG_MAX_CPUS 0x0f
272 #define QEMU_CFG_FILE_DIR 0x19
273 #define QEMU_CFG_ARCH_LOCAL 0x8000
274 #define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0)
275 #define QEMU_CFG_SMBIOS_ENTRIES (QEMU_CFG_ARCH_LOCAL + 1)
276 #define QEMU_CFG_IRQ0_OVERRIDE (QEMU_CFG_ARCH_LOCAL + 2)
277 #define QEMU_CFG_E820_TABLE (QEMU_CFG_ARCH_LOCAL + 3)
278
279 static void
qemu_cfg_select(u16 f)280 qemu_cfg_select(u16 f)
281 {
282 outw(f, PORT_QEMU_CFG_CTL);
283 }
284
285 static void
qemu_cfg_dma_transfer(void * address,u32 length,u32 control)286 qemu_cfg_dma_transfer(void *address, u32 length, u32 control)
287 {
288 QemuCfgDmaAccess access;
289
290 access.address = cpu_to_be64((u64)(u32)address);
291 access.length = cpu_to_be32(length);
292 access.control = cpu_to_be32(control);
293
294 barrier();
295
296 outl(cpu_to_be32((u32)&access), PORT_QEMU_CFG_DMA_ADDR_LOW);
297
298 while(be32_to_cpu(access.control) & ~QEMU_CFG_DMA_CTL_ERROR) {
299 yield();
300 }
301 }
302
303 static void
qemu_cfg_read(void * buf,int len)304 qemu_cfg_read(void *buf, int len)
305 {
306 if (len == 0) {
307 return;
308 }
309
310 if (qemu_cfg_dma_enabled()) {
311 qemu_cfg_dma_transfer(buf, len, QEMU_CFG_DMA_CTL_READ);
312 } else {
313 insb(PORT_QEMU_CFG_DATA, buf, len);
314 }
315 }
316
317 static void
qemu_cfg_write(void * buf,int len)318 qemu_cfg_write(void *buf, int len)
319 {
320 if (len == 0) {
321 return;
322 }
323
324 if (qemu_cfg_dma_enabled()) {
325 qemu_cfg_dma_transfer(buf, len, QEMU_CFG_DMA_CTL_WRITE);
326 } else {
327 warn_internalerror();
328 }
329 }
330
331 static void
qemu_cfg_skip(int len)332 qemu_cfg_skip(int len)
333 {
334 if (len == 0) {
335 return;
336 }
337
338 if (qemu_cfg_dma_enabled()) {
339 qemu_cfg_dma_transfer(0, len, QEMU_CFG_DMA_CTL_SKIP);
340 } else {
341 while (len--)
342 inb(PORT_QEMU_CFG_DATA);
343 }
344 }
345
346 static void
qemu_cfg_read_entry(void * buf,int e,int len)347 qemu_cfg_read_entry(void *buf, int e, int len)
348 {
349 if (qemu_cfg_dma_enabled()) {
350 u32 control = (e << 16) | QEMU_CFG_DMA_CTL_SELECT
351 | QEMU_CFG_DMA_CTL_READ;
352 qemu_cfg_dma_transfer(buf, len, control);
353 } else {
354 qemu_cfg_select(e);
355 qemu_cfg_read(buf, len);
356 }
357 }
358
359 static void
qemu_cfg_write_entry(void * buf,int e,int len)360 qemu_cfg_write_entry(void *buf, int e, int len)
361 {
362 if (qemu_cfg_dma_enabled()) {
363 u32 control = (e << 16) | QEMU_CFG_DMA_CTL_SELECT
364 | QEMU_CFG_DMA_CTL_WRITE;
365 qemu_cfg_dma_transfer(buf, len, control);
366 } else {
367 warn_internalerror();
368 }
369 }
370
371 struct qemu_romfile_s {
372 struct romfile_s file;
373 int select, skip;
374 };
375
376 static int
qemu_cfg_read_file(struct romfile_s * file,void * dst,u32 maxlen)377 qemu_cfg_read_file(struct romfile_s *file, void *dst, u32 maxlen)
378 {
379 if (file->size > maxlen)
380 return -1;
381 struct qemu_romfile_s *qfile;
382 qfile = container_of(file, struct qemu_romfile_s, file);
383 if (qfile->skip == 0) {
384 /* Do it in one transfer */
385 qemu_cfg_read_entry(dst, qfile->select, file->size);
386 } else {
387 qemu_cfg_select(qfile->select);
388 qemu_cfg_skip(qfile->skip);
389 qemu_cfg_read(dst, file->size);
390 }
391 return file->size;
392 }
393
394 // Bare-bones function for writing a file knowing only its unique
395 // identifying key (select)
396 int
qemu_cfg_write_file_simple(void * src,u16 key,u32 offset,u32 len)397 qemu_cfg_write_file_simple(void *src, u16 key, u32 offset, u32 len)
398 {
399 if (offset == 0) {
400 /* Do it in one transfer */
401 qemu_cfg_write_entry(src, key, len);
402 } else {
403 qemu_cfg_select(key);
404 qemu_cfg_skip(offset);
405 qemu_cfg_write(src, len);
406 }
407 return len;
408 }
409
410 int
qemu_cfg_write_file(void * src,struct romfile_s * file,u32 offset,u32 len)411 qemu_cfg_write_file(void *src, struct romfile_s *file, u32 offset, u32 len)
412 {
413 if ((offset + len) > file->size)
414 return -1;
415
416 if (!qemu_cfg_dma_enabled() || (file->copy != qemu_cfg_read_file)) {
417 warn_internalerror();
418 return -1;
419 }
420 return qemu_cfg_write_file_simple(src, qemu_get_romfile_key(file),
421 offset, len);
422 }
423
424 static void
qemu_romfile_add(char * name,int select,int skip,int size)425 qemu_romfile_add(char *name, int select, int skip, int size)
426 {
427 struct qemu_romfile_s *qfile = malloc_tmp(sizeof(*qfile));
428 if (!qfile) {
429 warn_noalloc();
430 return;
431 }
432 memset(qfile, 0, sizeof(*qfile));
433 strtcpy(qfile->file.name, name, sizeof(qfile->file.name));
434 qfile->file.size = size;
435 qfile->select = select;
436 qfile->skip = skip;
437 qfile->file.copy = qemu_cfg_read_file;
438 romfile_add(&qfile->file);
439 }
440
441 u16
qemu_get_romfile_key(struct romfile_s * file)442 qemu_get_romfile_key(struct romfile_s *file)
443 {
444 struct qemu_romfile_s *qfile;
445 if (file->copy != qemu_cfg_read_file) {
446 warn_internalerror();
447 return 0;
448 }
449 qfile = container_of(file, struct qemu_romfile_s, file);
450 return qfile->select;
451 }
452
rtc_present(void)453 static int rtc_present(void)
454 {
455 return rtc_read(CMOS_RTC_MONTH) != 0xff;
456 }
457
458 u16
qemu_get_present_cpus_count(void)459 qemu_get_present_cpus_count(void)
460 {
461 u16 smp_count = 0;
462 if (qemu_cfg_enabled()) {
463 qemu_cfg_read_entry(&smp_count, QEMU_CFG_NB_CPUS, sizeof(smp_count));
464 }
465 if (rtc_present()) {
466 u16 cmos_cpu_count = rtc_read(CMOS_BIOS_SMP_COUNT) + 1;
467 if (smp_count < cmos_cpu_count) {
468 smp_count = cmos_cpu_count;
469 }
470 }
471 return smp_count;
472 }
473
474 struct e820_reservation {
475 u64 address;
476 u64 length;
477 u32 type;
478 };
479
480 #define SMBIOS_FIELD_ENTRY 0
481 #define SMBIOS_TABLE_ENTRY 1
482
483 struct qemu_smbios_header {
484 u16 length;
485 u8 headertype;
486 u8 tabletype;
487 u16 fieldoffset;
488 } PACKED;
489
490 static void
qemu_cfg_e820(void)491 qemu_cfg_e820(void)
492 {
493 if (!CONFIG_QEMU)
494 return;
495
496 if (romfile_find("etc/e820")) {
497 // qemu_early_e820() has handled everything
498 return;
499 }
500
501 // QEMU_CFG_E820_TABLE has reservations only
502 u32 count32;
503 qemu_cfg_read_entry(&count32, QEMU_CFG_E820_TABLE, sizeof(count32));
504 if (count32) {
505 struct e820_reservation entry;
506 int i;
507 for (i = 0; i < count32; i++) {
508 qemu_cfg_read(&entry, sizeof(entry));
509 e820_add(entry.address, entry.length, entry.type);
510 }
511 } else if (runningOnKVM()) {
512 // Backwards compatibility - provide hard coded range.
513 // 4 pages before the bios, 3 pages for vmx tss pages, the
514 // other page for EPT real mode pagetable
515 e820_add(0xfffbc000, 4*4096, E820_RESERVED);
516 }
517
518 // Check for memory over 4Gig in cmos
519 u64 high = ((rtc_read(CMOS_MEM_HIGHMEM_LOW) << 16)
520 | ((u32)rtc_read(CMOS_MEM_HIGHMEM_MID) << 24)
521 | ((u64)rtc_read(CMOS_MEM_HIGHMEM_HIGH) << 32));
522 RamSizeOver4G = high;
523 e820_add(0x100000000ull, high, E820_RAM);
524 dprintf(1, "RamSizeOver4G: 0x%016llx [cmos]\n", RamSizeOver4G);
525 }
526
527 // Populate romfile entries for legacy fw_cfg ports (that predate the
528 // "file" interface).
529 static void
qemu_cfg_legacy(void)530 qemu_cfg_legacy(void)
531 {
532 if (!CONFIG_QEMU)
533 return;
534
535 // Misc config items.
536 qemu_romfile_add("etc/show-boot-menu", QEMU_CFG_BOOT_MENU, 0, 2);
537 qemu_romfile_add("etc/irq0-override", QEMU_CFG_IRQ0_OVERRIDE, 0, 1);
538 qemu_romfile_add("etc/max-cpus", QEMU_CFG_MAX_CPUS, 0, 2);
539
540 // NUMA data
541 u64 numacount;
542 qemu_cfg_read_entry(&numacount, QEMU_CFG_NUMA, sizeof(numacount));
543 int max_cpu = romfile_loadint("etc/max-cpus", 0);
544 qemu_romfile_add("etc/numa-cpu-map", QEMU_CFG_NUMA, sizeof(numacount)
545 , max_cpu*sizeof(u64));
546 qemu_romfile_add("etc/numa-nodes", QEMU_CFG_NUMA
547 , sizeof(numacount) + max_cpu*sizeof(u64)
548 , numacount*sizeof(u64));
549
550 // ACPI tables
551 char name[128];
552 u16 cnt;
553 qemu_cfg_read_entry(&cnt, QEMU_CFG_ACPI_TABLES, sizeof(cnt));
554 int i, offset = sizeof(cnt);
555 for (i = 0; i < cnt; i++) {
556 u16 len;
557 qemu_cfg_read(&len, sizeof(len));
558 offset += sizeof(len);
559 snprintf(name, sizeof(name), "acpi/table%d", i);
560 qemu_romfile_add(name, QEMU_CFG_ACPI_TABLES, offset, len);
561 qemu_cfg_skip(len);
562 offset += len;
563 }
564
565 // SMBIOS info
566 qemu_cfg_read_entry(&cnt, QEMU_CFG_SMBIOS_ENTRIES, sizeof(cnt));
567 offset = sizeof(cnt);
568 for (i = 0; i < cnt; i++) {
569 struct qemu_smbios_header header;
570 qemu_cfg_read(&header, sizeof(header));
571 if (header.headertype == SMBIOS_FIELD_ENTRY) {
572 snprintf(name, sizeof(name), "smbios/field%d-%d"
573 , header.tabletype, header.fieldoffset);
574 qemu_romfile_add(name, QEMU_CFG_SMBIOS_ENTRIES
575 , offset + sizeof(header)
576 , header.length - sizeof(header));
577 } else {
578 snprintf(name, sizeof(name), "smbios/table%d-%d"
579 , header.tabletype, i);
580 qemu_romfile_add(name, QEMU_CFG_SMBIOS_ENTRIES
581 , offset + 3, header.length - 3);
582 }
583 qemu_cfg_skip(header.length - sizeof(header));
584 offset += header.length;
585 }
586 }
587
588 struct QemuCfgFile {
589 u32 size; /* file size */
590 u16 select; /* write this to 0x510 to read it */
591 u16 reserved;
592 char name[56];
593 };
594
qemu_cfg_detect(void)595 static int qemu_cfg_detect(void)
596 {
597 if (cfg_enabled)
598 return 1;
599
600 // Detect fw_cfg interface.
601 qemu_cfg_select(QEMU_CFG_SIGNATURE);
602 char *sig = "QEMU";
603 int i;
604 for (i = 0; i < 4; i++)
605 if (inb(PORT_QEMU_CFG_DATA) != sig[i])
606 return 0;
607
608 dprintf(1, "Found QEMU fw_cfg\n");
609 cfg_enabled = 1;
610
611 // Detect DMA interface.
612 u32 id;
613 qemu_cfg_read_entry(&id, QEMU_CFG_ID, sizeof(id));
614
615 if (id & QEMU_CFG_VERSION_DMA) {
616 dprintf(1, "QEMU fw_cfg DMA interface supported\n");
617 cfg_dma_enabled = 1;
618 }
619 return 1;
620 }
621
qemu_cfg_init(void)622 void qemu_cfg_init(void)
623 {
624 if (!runningOnQEMU())
625 return;
626
627 if (!qemu_cfg_detect())
628 return;
629
630 // Populate romfiles for legacy fw_cfg entries
631 qemu_cfg_legacy();
632
633 // Load files found in the fw_cfg file directory
634 u32 count;
635 qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count));
636 count = be32_to_cpu(count);
637 u32 e;
638 for (e = 0; e < count; e++) {
639 struct QemuCfgFile qfile;
640 qemu_cfg_read(&qfile, sizeof(qfile));
641 qemu_romfile_add(qfile.name, be16_to_cpu(qfile.select)
642 , 0, be32_to_cpu(qfile.size));
643 }
644
645 qemu_cfg_e820();
646
647 if (romfile_find("etc/table-loader")) {
648 acpi_pm_base = 0x0600;
649 dprintf(1, "Moving pm_base to 0x%x\n", acpi_pm_base);
650 }
651
652 // serial console
653 u16 nogfx = 0;
654 qemu_cfg_read_entry(&nogfx, QEMU_CFG_NOGRAPHIC, sizeof(nogfx));
655 if (nogfx && !romfile_find("etc/sercon-port")
656 && !romfile_find("vgaroms/sgabios.bin"))
657 const_romfile_add_int("etc/sercon-port", PORT_SERIAL1);
658 }
659
660 /*
661 * This runs before malloc and romfile are ready, so we have to work
662 * with stack allocations and read from fw_cfg in chunks.
663 */
qemu_early_e820(void)664 static int qemu_early_e820(void)
665 {
666 struct e820_reservation table;
667 struct QemuCfgFile qfile;
668 u32 select = 0, size = 0;
669 u32 count, i;
670
671 if (!qemu_cfg_detect())
672 return 0;
673
674 // find e820 table
675 qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count));
676 count = be32_to_cpu(count);
677 for (i = 0; i < count; i++) {
678 qemu_cfg_read(&qfile, sizeof(qfile));
679 if (memcmp(qfile.name, "etc/e820", 9) != 0)
680 continue;
681 select = be16_to_cpu(qfile.select);
682 size = be32_to_cpu(qfile.size);
683 break;
684 }
685 if (select == 0) {
686 // may happen on old qemu
687 dprintf(1, "qemu/e820: fw_cfg file etc/e820 not found\n");
688 return 0;
689 }
690
691 // walk e820 table
692 qemu_cfg_select(select);
693 count = size/sizeof(table);
694 for (i = 0, select = 0; i < count; i++) {
695 qemu_cfg_read(&table, sizeof(table));
696 switch (table.type) {
697 case E820_RESERVED:
698 e820_add(table.address, table.length, table.type);
699 dprintf(3, "qemu/e820: addr 0x%016llx len 0x%016llx [reserved]\n",
700 table.address, table.length);
701 break;
702 case E820_RAM:
703 e820_add(table.address, table.length, table.type);
704 dprintf(1, "qemu/e820: addr 0x%016llx len 0x%016llx [RAM]\n",
705 table.address, table.length);
706 if (table.address < 0x100000000LL) {
707 // below 4g
708 if (RamSize < table.address + table.length)
709 RamSize = table.address + table.length;
710 } else {
711 // above 4g
712 if (RamSizeOver4G < table.address + table.length - 0x100000000LL)
713 RamSizeOver4G = table.address + table.length - 0x100000000LL;
714 }
715 }
716 }
717
718 dprintf(3, "qemu/e820: RamSize: 0x%08x\n", RamSize);
719 dprintf(3, "qemu/e820: RamSizeOver4G: 0x%016llx\n", RamSizeOver4G);
720 return 1;
721 }
722