Move qemu fw_cfg detection to separate function. No functional change.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/fw/paravirt.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c index 119280c574fd..b21f1aef1c7f 100644 --- a/src/fw/paravirt.c +++ b/src/fw/paravirt.c @@ -614,10 +614,10 @@ struct QemuCfgFile { char name[56]; };
-void qemu_cfg_init(void) +static int qemu_cfg_detect(void) { - if (!runningOnQEMU()) - return; + if (cfg_enabled) + return 1;
// Detect fw_cfg interface. qemu_cfg_select(QEMU_CFG_SIGNATURE); @@ -625,7 +625,7 @@ void qemu_cfg_init(void) int i; for (i = 0; i < 4; i++) if (inb(PORT_QEMU_CFG_DATA) != sig[i]) - return; + return 0;
dprintf(1, "Found QEMU fw_cfg\n"); cfg_enabled = 1; @@ -638,6 +638,16 @@ void qemu_cfg_init(void) dprintf(1, "QEMU fw_cfg DMA interface supported\n"); cfg_dma_enabled = 1; } + return 1; +} + +void qemu_cfg_init(void) +{ + if (!runningOnQEMU()) + return; + + if (!qemu_cfg_detect()) + return;
// Populate romfiles for legacy fw_cfg entries qemu_cfg_legacy();
Read e820 table from fw_cfg early. This avoids reading the cmos for ram detection on modern qemu. It also simplifies the ram detection logic. We stop doing ram detecion in two steps, so we don't have to worry about the second step overwriting the setup done by the first step.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/fw/paravirt.c | 133 ++++++++++++++++++++++++++++------------------ 1 file changed, 82 insertions(+), 51 deletions(-)
diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c index b21f1aef1c7f..3465f97ec0b0 100644 --- a/src/fw/paravirt.c +++ b/src/fw/paravirt.c @@ -151,6 +151,8 @@ static void qemu_detect(void) } }
+static int qemu_early_e820(void); + void qemu_preinit(void) { @@ -165,22 +167,24 @@ qemu_preinit(void) return; }
- // On emulators, get memory size from nvram. - u32 rs = ((rtc_read(CMOS_MEM_EXTMEM2_LOW) << 16) - | (rtc_read(CMOS_MEM_EXTMEM2_HIGH) << 24)); - if (rs) - rs += 16 * 1024 * 1024; - else - rs = (((rtc_read(CMOS_MEM_EXTMEM_LOW) << 10) - | (rtc_read(CMOS_MEM_EXTMEM_HIGH) << 18)) - + 1 * 1024 * 1024); - RamSize = rs; - e820_add(0, rs, E820_RAM); + // try read e820 table first + if (!qemu_early_e820()) { + // when it fails get memory size from nvram. + u32 rs = ((rtc_read(CMOS_MEM_EXTMEM2_LOW) << 16) + | (rtc_read(CMOS_MEM_EXTMEM2_HIGH) << 24)); + if (rs) + rs += 16 * 1024 * 1024; + else + rs = (((rtc_read(CMOS_MEM_EXTMEM_LOW) << 10) + | (rtc_read(CMOS_MEM_EXTMEM_HIGH) << 18)) + + 1 * 1024 * 1024); + RamSize = rs; + e820_add(0, rs, E820_RAM); + dprintf(1, "RamSize: 0x%08x [cmos]\n", RamSize); + }
/* reserve 256KB BIOS area at the end of 4 GB */ e820_add(0xfffc0000, 256*1024, E820_RESERVED); - - dprintf(1, "RamSize: 0x%08x [cmos]\n", RamSize); }
#define MSR_IA32_FEATURE_CONTROL 0x0000003a @@ -476,47 +480,11 @@ struct qemu_smbios_header { static void qemu_cfg_e820(void) { - struct e820_reservation *table; - int i, size; - if (!CONFIG_QEMU) return;
- // "etc/e820" has both ram and reservations - table = romfile_loadfile("etc/e820", &size); - if (table) { - for (i = 0; i < size / sizeof(struct e820_reservation); i++) { - switch (table[i].type) { - case E820_RAM: - dprintf(1, "RamBlock: addr 0x%016llx len 0x%016llx [e820]\n", - table[i].address, table[i].length); - if (table[i].address < RamSize) - // ignore, preinit got it from cmos already and - // adding this again would ruin any reservations - // done so far - continue; - if (table[i].address < 0x100000000LL) { - // below 4g -- adjust RamSize to mark highest lowram addr - if (RamSize < table[i].address + table[i].length) - RamSize = table[i].address + table[i].length; - } else { - // above 4g -- adjust RamSizeOver4G to mark highest ram addr - if (0x100000000LL + RamSizeOver4G < table[i].address + table[i].length) - RamSizeOver4G = table[i].address + table[i].length - 0x100000000LL; - } - /* fall through */ - case E820_RESERVED: - e820_add(table[i].address, table[i].length, table[i].type); - break; - default: - /* - * Qemu 1.7 uses RAM + RESERVED only. Ignore - * everything else, so we have the option to - * extend this in the future without breakage. - */ - break; - } - } + if (romfile_find("etc/e820")) { + // qemu_early_e820() has handled everything return; }
@@ -678,3 +646,66 @@ void qemu_cfg_init(void) && !romfile_find("vgaroms/sgabios.bin")) const_romfile_add_int("etc/sercon-port", PORT_SERIAL1); } + +/* + * This runs before malloc and romfile are ready, so we have to work + * with stack allocations and read from fw_cfg in chunks. + */ +static int qemu_early_e820(void) +{ + struct e820_reservation table; + struct QemuCfgFile qfile; + u32 select = 0, size = 0; + u32 count, i; + + if (!qemu_cfg_detect()) + return 0; + + // find e820 table + qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count)); + count = be32_to_cpu(count); + for (i = 0; i < count; i++) { + qemu_cfg_read(&qfile, sizeof(qfile)); + if (memcmp(qfile.name, "etc/e820", 9) != 0) + continue; + select = be16_to_cpu(qfile.select); + size = be32_to_cpu(qfile.size); + break; + } + if (select == 0) { + // may happen on old qemu + dprintf(1, "qemu/e820: fw_cfg file etc/e820 not found\n"); + return 0; + } + + // walk e820 table + qemu_cfg_select(select); + count = size/sizeof(table); + for (i = 0, select = 0; i < count; i++) { + qemu_cfg_read(&table, sizeof(table)); + switch (table.type) { + case E820_RESERVED: + e820_add(table.address, table.length, table.type); + dprintf(3, "qemu/e820: addr 0x%016llx len 0x%016llx [reserved]\n", + table.address, table.length); + break; + case E820_RAM: + e820_add(table.address, table.length, table.type); + dprintf(1, "qemu/e820: addr 0x%016llx len 0x%016llx [RAM]\n", + table.address, table.length); + if (table.address < 0x100000000LL) { + // below 4g + if (RamSize < table.address + table.length) + RamSize = table.address + table.length; + } else { + // above 4g + if (RamSizeOver4G < table.address + table.length - 0x100000000LL) + RamSizeOver4G = table.address + table.length - 0x100000000LL; + } + } + } + + dprintf(3, "qemu/e820: RamSize: 0x%08x\n", RamSize); + dprintf(3, "qemu/e820: RamSizeOver4G: 0x%016llx\n", RamSizeOver4G); + return 1; +}
Read month register which should never have a value larger than 12. In case the read returns 0xff assume the rtc isn't there. Don't try to read the cpu count from cmos without rtc.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- src/fw/paravirt.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c index 3465f97ec0b0..e76fa65d87a0 100644 --- a/src/fw/paravirt.c +++ b/src/fw/paravirt.c @@ -447,6 +447,11 @@ qemu_get_romfile_key(struct romfile_s *file) return qfile->select; }
+static int rtc_present(void) +{ + return rtc_read(CMOS_RTC_MONTH) != 0xff; +} + u16 qemu_get_present_cpus_count(void) { @@ -454,9 +459,11 @@ qemu_get_present_cpus_count(void) if (qemu_cfg_enabled()) { qemu_cfg_read_entry(&smp_count, QEMU_CFG_NB_CPUS, sizeof(smp_count)); } - u16 cmos_cpu_count = rtc_read(CMOS_BIOS_SMP_COUNT) + 1; - if (smp_count < cmos_cpu_count) { - smp_count = cmos_cpu_count; + if (rtc_present()) { + u16 cmos_cpu_count = rtc_read(CMOS_BIOS_SMP_COUNT) + 1; + if (smp_count < cmos_cpu_count) { + smp_count = cmos_cpu_count; + } } return smp_count; }
On 5/8/20 1:37 PM, Gerd Hoffmann wrote:
Read month register which should never have a value larger than 12. In case the read returns 0xff assume the rtc isn't there. Don't try to read the cpu count from cmos without rtc.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com
Reviewed-by: Philippe Mathieu-Daudé philmd@redhat.com
src/fw/paravirt.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c index 3465f97ec0b0..e76fa65d87a0 100644 --- a/src/fw/paravirt.c +++ b/src/fw/paravirt.c @@ -447,6 +447,11 @@ qemu_get_romfile_key(struct romfile_s *file) return qfile->select; }
+static int rtc_present(void) +{
- return rtc_read(CMOS_RTC_MONTH) != 0xff;
+}
- u16 qemu_get_present_cpus_count(void) {
@@ -454,9 +459,11 @@ qemu_get_present_cpus_count(void) if (qemu_cfg_enabled()) { qemu_cfg_read_entry(&smp_count, QEMU_CFG_NB_CPUS, sizeof(smp_count)); }
- u16 cmos_cpu_count = rtc_read(CMOS_BIOS_SMP_COUNT) + 1;
- if (smp_count < cmos_cpu_count) {
smp_count = cmos_cpu_count;
- if (rtc_present()) {
u16 cmos_cpu_count = rtc_read(CMOS_BIOS_SMP_COUNT) + 1;
if (smp_count < cmos_cpu_count) {
smp_count = cmos_cpu_count;
}} } return smp_count;
On Fri, May 08, 2020 at 01:37:17PM +0200, Gerd Hoffmann wrote:
Read month register which should never have a value larger than 12. In case the read returns 0xff assume the rtc isn't there. Don't try to read the cpu count from cmos without rtc.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com
FYI, the series looks fine to me.
-Kevin
On Thu, May 14, 2020 at 10:11:28PM -0400, Kevin O'Connor wrote:
On Fri, May 08, 2020 at 01:37:17PM +0200, Gerd Hoffmann wrote:
Read month register which should never have a value larger than 12. In case the read returns 0xff assume the rtc isn't there. Don't try to read the cpu count from cmos without rtc.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com
FYI, the series looks fine to me.
Committed series.
take care, Gerd