Nico Huber has uploaded this change for review. ( https://review.coreboot.org/28441
Change subject: mb/emulation/qemu x86: Use scratchpad for RAM size ......................................................................
mb/emulation/qemu x86: Use scratchpad for RAM size
Qemu communicates its RAM size through some bytes in CMOS. This works fine as long as we don't try to use CMOS for configuration. If we do, i.e. with CONFIG_USE_OPTION_TABLE enabled, these bytes would be erased on boot (because of a checksum mismatch) even if we'd reserve them in `cmos.layout`.
Instead of patching our option table implementation, we work around the issue in Qemu's mainboard code: Before the option table is initialized, we copy the RAM size to a scratchpad in the northbridge's PCI device.
Note: The scratchpad used is actually only for i440fx, but as there is no real emulation of the northbridge, this works for q35 too.
Change-Id: I5d4a238feb252561ad2dac06c44b9398bf908105 Signed-off-by: Nico Huber nico.huber@secunet.com --- M src/mainboard/emulation/qemu-i440fx/Kconfig M src/mainboard/emulation/qemu-i440fx/Makefile.inc A src/mainboard/emulation/qemu-i440fx/bootblock.c M src/mainboard/emulation/qemu-i440fx/memory.c A src/mainboard/emulation/qemu-i440fx/memory.h M src/mainboard/emulation/qemu-i440fx/northbridge.c M src/mainboard/emulation/qemu-i440fx/romstage.c M src/mainboard/emulation/qemu-q35/Makefile.inc M src/mainboard/emulation/qemu-q35/bootblock.c M src/mainboard/emulation/qemu-q35/romstage.c 10 files changed, 126 insertions(+), 35 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/41/28441/1
diff --git a/src/mainboard/emulation/qemu-i440fx/Kconfig b/src/mainboard/emulation/qemu-i440fx/Kconfig index fc56ab6..b779bbf 100644 --- a/src/mainboard/emulation/qemu-i440fx/Kconfig +++ b/src/mainboard/emulation/qemu-i440fx/Kconfig @@ -21,6 +21,10 @@ string default "QEMU x86 i440fx/piix4"
+config BOOTBLOCK_NORTHBRIDGE_INIT + string + default "mainboard/emulation/qemu-i440fx/bootblock.c" + config IRQ_SLOT_COUNT int default 6 diff --git a/src/mainboard/emulation/qemu-i440fx/Makefile.inc b/src/mainboard/emulation/qemu-i440fx/Makefile.inc index f9cf252..525b4c2 100644 --- a/src/mainboard/emulation/qemu-i440fx/Makefile.inc +++ b/src/mainboard/emulation/qemu-i440fx/Makefile.inc @@ -1,3 +1,5 @@ cpu_incs-y += $(src)/mainboard/emulation/qemu-i440fx/cache_as_ram.inc +romstage-y += memory.c +ramstage-y += memory.c ramstage-y += northbridge.c ramstage-y += fw_cfg.c diff --git a/src/mainboard/emulation/qemu-i440fx/bootblock.c b/src/mainboard/emulation/qemu-i440fx/bootblock.c new file mode 100644 index 0000000..e409cb3 --- /dev/null +++ b/src/mainboard/emulation/qemu-i440fx/bootblock.c @@ -0,0 +1,37 @@ +/* + * This file is part of the coreboot project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/io.h> +#include <pc80/mc146818rtc.h> +#include "memory.h" + +void bootblock_northbridge_init(void) +{ + /* + * We have to cache Qemu's RAM size (from CMOS) for the case + * that USE_OPTION_TABLE is enabled. We use a scratchpad in + * D0F0 for this. + */ + + unsigned long tomk; + tomk = (unsigned long)cmos_read(HIGH_RAM_ADDR) << 14; + tomk |= (unsigned long)cmos_read(LOW_RAM_ADDR) << 6; + tomk += 16 * 1024; + pci_write_config32(PCI_DEV(0, 0x00, 0), QEMU_D0F0_SCRATCHPAD, tomk); + + unsigned long high; + high = (unsigned long)cmos_read(HIGH_HIGHRAM_ADDR) << 22; + high |= (unsigned long)cmos_read(MID_HIGHRAM_ADDR) << 14; + high |= (unsigned long)cmos_read(LOW_HIGHRAM_ADDR) << 6; + pci_write_config32(PCI_DEV(0, 0x00, 0), QEMU_D0F0_SCRATCHPAD + 4, high); +} diff --git a/src/mainboard/emulation/qemu-i440fx/memory.c b/src/mainboard/emulation/qemu-i440fx/memory.c index b8109e5..12d9a96 100644 --- a/src/mainboard/emulation/qemu-i440fx/memory.c +++ b/src/mainboard/emulation/qemu-i440fx/memory.c @@ -13,27 +13,34 @@ * GNU General Public License for more details. */
+#include <arch/io.h> +#include <device/device.h> +#include <device/pci.h> #include <cbmem.h> +#include "memory.h"
-#define CMOS_ADDR_PORT 0x70 -#define CMOS_DATA_PORT 0x71 - -#define HIGH_RAM_ADDR 0x35 -#define LOW_RAM_ADDR 0x34 - -#define HIGH_HIGHRAM_ADDR 0x5d -#define MID_HIGHRAM_ADDR 0x5c -#define LOW_HIGHRAM_ADDR 0x5b - -static unsigned long qemu_get_memory_size(void) +unsigned long qemu_get_memory_size(void) { - unsigned long tomk; - outb (HIGH_RAM_ADDR, CMOS_ADDR_PORT); - tomk = ((unsigned long) inb(CMOS_DATA_PORT)) << 14; - outb (LOW_RAM_ADDR, CMOS_ADDR_PORT); - tomk |= ((unsigned long) inb(CMOS_DATA_PORT)) << 6; - tomk += 16 * 1024; - return tomk; +#ifdef __SIMPLE_DEVICE__ + const device_t d0f0 = PCI_DEV(0, 0x00, 0); +#else + struct device *const d0f0 = dev_find_slot(0, PCI_DEVFN(0x00, 0)); + if (!d0f0) + return 16 * 1024; +#endif + return pci_read_config32(d0f0, QEMU_D0F0_SCRATCHPAD); +} + +unsigned long qemu_get_high_memory_size(void) +{ +#ifdef __SIMPLE_DEVICE__ + const device_t d0f0 = PCI_DEV(0, 0x00, 0); +#else + struct device *const d0f0 = dev_find_slot(0, PCI_DEVFN(0x00, 0)); + if (!d0f0) + return 16 * 1024; +#endif + return pci_read_config32(d0f0, QEMU_D0F0_SCRATCHPAD + 4); }
void *cbmem_top(void) diff --git a/src/mainboard/emulation/qemu-i440fx/memory.h b/src/mainboard/emulation/qemu-i440fx/memory.h new file mode 100644 index 0000000..753ef63 --- /dev/null +++ b/src/mainboard/emulation/qemu-i440fx/memory.h @@ -0,0 +1,29 @@ +/* + * This file is part of the coreboot project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef MAINBOARD_EMULATION_QEMU_I440FX_MEMORY_H +#define MAINBOARD_EMULATION_QEMU_I440FX_MEMORY_H 1 + +#define HIGH_RAM_ADDR 0x35 +#define LOW_RAM_ADDR 0x34 + +#define HIGH_HIGHRAM_ADDR 0x5d +#define MID_HIGHRAM_ADDR 0x5c +#define LOW_HIGHRAM_ADDR 0x5b + +#define QEMU_D0F0_SCRATCHPAD 0xd0 + +unsigned long qemu_get_memory_size(void); +unsigned long qemu_get_high_memory_size(void); + +#endif diff --git a/src/mainboard/emulation/qemu-i440fx/northbridge.c b/src/mainboard/emulation/qemu-i440fx/northbridge.c index aa309de..5711e72 100644 --- a/src/mainboard/emulation/qemu-i440fx/northbridge.c +++ b/src/mainboard/emulation/qemu-i440fx/northbridge.c @@ -28,21 +28,9 @@ #include "fw_cfg.h" #include "fw_cfg_if.h"
-#include "memory.c" +#include "memory.h" #include "acpi.h"
-static unsigned long qemu_get_high_memory_size(void) -{ - unsigned long high; - outb (HIGH_HIGHRAM_ADDR, CMOS_ADDR_PORT); - high = ((unsigned long) inb(CMOS_DATA_PORT)) << 22; - outb (MID_HIGHRAM_ADDR, CMOS_ADDR_PORT); - high |= ((unsigned long) inb(CMOS_DATA_PORT)) << 14; - outb (LOW_HIGHRAM_ADDR, CMOS_ADDR_PORT); - high |= ((unsigned long) inb(CMOS_DATA_PORT)) << 6; - return high; -} - static void qemu_reserve_ports(struct device *dev, unsigned int idx, unsigned int base, unsigned int size, const char *name) diff --git a/src/mainboard/emulation/qemu-i440fx/romstage.c b/src/mainboard/emulation/qemu-i440fx/romstage.c index ce12a8b..decd85f 100644 --- a/src/mainboard/emulation/qemu-i440fx/romstage.c +++ b/src/mainboard/emulation/qemu-i440fx/romstage.c @@ -24,8 +24,7 @@ #include <timestamp.h> #include <delay.h> #include <cpu/x86/lapic.h> - -#include "memory.c" +#include <cbmem.h>
void *asmlinkage romstage_main(unsigned long bist) { diff --git a/src/mainboard/emulation/qemu-q35/Makefile.inc b/src/mainboard/emulation/qemu-q35/Makefile.inc index fc4374c..cb85def 100644 --- a/src/mainboard/emulation/qemu-q35/Makefile.inc +++ b/src/mainboard/emulation/qemu-q35/Makefile.inc @@ -1,3 +1,5 @@ cpu_incs-y += $(src)/mainboard/emulation/qemu-i440fx/cache_as_ram.inc +romstage-y += ../qemu-i440fx/memory.c +ramstage-y += ../qemu-i440fx/memory.c ramstage-y += ../qemu-i440fx/northbridge.c ramstage-y += ../qemu-i440fx/fw_cfg.c diff --git a/src/mainboard/emulation/qemu-q35/bootblock.c b/src/mainboard/emulation/qemu-q35/bootblock.c index 3625cf9..b190cfc 100644 --- a/src/mainboard/emulation/qemu-q35/bootblock.c +++ b/src/mainboard/emulation/qemu-q35/bootblock.c @@ -12,6 +12,8 @@ */
#include <arch/io.h> +#include <pc80/mc146818rtc.h> +#include "../qemu-i440fx/memory.h"
/* Just define these here, there is no gm35.h file to include. */ #define D0F0_PCIEXBAR_LO 0x60 @@ -37,6 +39,28 @@ pci_io_write_config32(PCI_DEV(0,0,0), D0F0_PCIEXBAR_HI, reg); reg = CONFIG_MMCONF_BASE_ADDRESS | 1; /* 256MiB - 0-255 buses. */ pci_io_write_config32(PCI_DEV(0,0,0), D0F0_PCIEXBAR_LO, reg); + + /* + * We have to cache Qemu's RAM size (from CMOS) for the case + * that USE_OPTION_TABLE is enabled. We use a scratchpad in + * D0F0 for this. + * Warning: This is actually a scratchpad address for I440FX, + * but it is not used in Qemu's emulated Q35. Although unlikely, + * this may break in the future. We could use an actual scratch- + * pad register (0xdc) but this is already used for timestamps + * in ICH9. + */ + unsigned long tomk; + tomk = (unsigned long)cmos_read(HIGH_RAM_ADDR) << 14; + tomk |= (unsigned long)cmos_read(LOW_RAM_ADDR) << 6; + tomk += 16 * 1024; + pci_write_config32(PCI_DEV(0, 0x00, 0), QEMU_D0F0_SCRATCHPAD, tomk); + + unsigned long high; + high = (unsigned long)cmos_read(HIGH_HIGHRAM_ADDR) << 22; + high |= (unsigned long)cmos_read(MID_HIGHRAM_ADDR) << 14; + high |= (unsigned long)cmos_read(LOW_HIGHRAM_ADDR) << 6; + pci_write_config32(PCI_DEV(0, 0x00, 0), QEMU_D0F0_SCRATCHPAD + 4, high); }
static void bootblock_mainboard_init(void) diff --git a/src/mainboard/emulation/qemu-q35/romstage.c b/src/mainboard/emulation/qemu-q35/romstage.c index 870dd07..8f6a479 100644 --- a/src/mainboard/emulation/qemu-q35/romstage.c +++ b/src/mainboard/emulation/qemu-q35/romstage.c @@ -26,8 +26,7 @@ #include <timestamp.h> #include <delay.h> #include <cpu/x86/lapic.h> - -#include "../qemu-i440fx/memory.c" +#include <cbmem.h>
void * asmlinkage romstage_main(unsigned long bist) {