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