Author: stepan Date: Mon May 3 18:21:52 2010 New Revision: 5521 URL: https://tracker.coreboot.org/trac/coreboot/changeset/5521
Log: Qemu, despite "emulating" an intel chipset, uses the CMOS to tell the BIOS how much RAM the virtual machine has available. This patch fixes the detection.
Signed-off-by: Valdimir Serbinenko phcoder@gmail.com Acked-by: Stefan Reinauer stepan@coresystems.de
Modified: trunk/src/mainboard/emulation/qemu-x86/northbridge.c
Modified: trunk/src/mainboard/emulation/qemu-x86/northbridge.c ============================================================================== --- trunk/src/mainboard/emulation/qemu-x86/northbridge.c Fri Apr 30 22:44:30 2010 (r5520) +++ trunk/src/mainboard/emulation/qemu-x86/northbridge.c Mon May 3 18:21:52 2010 (r5521) @@ -53,60 +53,44 @@ extern uint64_t high_tables_base, high_tables_size; #endif
+#define CMOS_ADDR_PORT 0x70 +#define CMOS_DATA_PORT 0x71 +#define HIGH_RAM_ADDR 0x35 +#define LOW_RAM_ADDR 0x34 + static void cpu_pci_domain_set_resources(device_t dev) { - static const uint8_t ramregs[] = { - 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x56, 0x57 - }; - device_t mc_dev; - uint32_t pci_tolm; - - pci_tolm = find_pci_tolm(&dev->link[0]); - mc_dev = dev->link[0].children; - if (mc_dev) { - unsigned long tomk, tolmk; - unsigned char rambits; - int i, idx; - - for(rambits = 0, i = 0; i < ARRAY_SIZE(ramregs); i++) { - unsigned char reg; - reg = pci_read_config8(mc_dev, ramregs[i]); - /* these are ENDING addresses, not sizes. - * if there is memory in this slot, then reg will be > rambits. - * So we just take the max, that gives us total. - * We take the highest one to cover for once and future coreboot - * bugs. We warn about bugs. - */ - if (reg > rambits) - rambits = reg; - if (reg < rambits) - printk(BIOS_ERR, "ERROR! register 0x%x is not set!\n", - ramregs[i]); - } - if (rambits == 0) { - printk(BIOS_ERR, "RAM size config registers are empty; defaulting to 64 MBytes\n"); - rambits = 8; - } - printk(BIOS_DEBUG, "I would set ram size to 0x%x Kbytes\n", (rambits)*8*1024); - tomk = rambits*8*1024; - /* Compute the top of Low memory */ - tolmk = pci_tolm >> 10; - if (tolmk >= tomk) { - /* The PCI hole does not overlap the memory. */ - tolmk = tomk; - } - - /* Report the memory regions. */ - idx = 10; - ram_resource(dev, idx++, 0, 640); - ram_resource(dev, idx++, 768, tolmk - 768); + u32 pci_tolm = find_pci_tolm(&dev->link[0]); + unsigned long tomk = 0, tolmk; + int idx; + + 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; + + printk(BIOS_DEBUG, "Detected %lu Kbytes (%lu MiB) RAM.\n", + tomk, tomk / 1024); + + /* Compute the top of Low memory */ + tolmk = pci_tolm >> 10; + if (tolmk >= tomk) { + /* The PCI hole does not overlap the memory. */ + tolmk = tomk; + } + + /* Report the memory regions. */ + idx = 10; + ram_resource(dev, idx++, 0, 640); + ram_resource(dev, idx++, 768, tolmk - 768);
#if CONFIG_WRITE_HIGH_TABLES==1 - /* Leave some space for ACPI, PIRQ and MP tables */ - high_tables_base = (tomk - HIGH_TABLES_SIZE) * 1024; - high_tables_size = HIGH_TABLES_SIZE * 1024; + /* Leave some space for ACPI, PIRQ and MP tables */ + high_tables_base = (tomk - HIGH_TABLES_SIZE) * 1024; + high_tables_size = HIGH_TABLES_SIZE * 1024; #endif - } + assign_resources(&dev->link[0]); }