qemu: load e820 from fw_cfg
qemu 1.7+ provides a fw_cfg file named "etc/e820" with e820-like entries for reservations and ram regions. Use it for ram detection if present, otherwise fallback to the traditional cmos method. Change-Id: Icac6c99d2a053e59dfdd28e48d1ceb3d56a61bdc Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-on: http://review.coreboot.org/4030 Tested-by: build bot (Jenkins)
This commit is contained in:
parent
289b45fdff
commit
baa782020e
|
@ -51,3 +51,9 @@ typedef struct FWCfgFiles {
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
FWCfgFile f[];
|
FWCfgFile f[];
|
||||||
} FWCfgFiles;
|
} FWCfgFiles;
|
||||||
|
|
||||||
|
typedef struct FwCfgE820Entry {
|
||||||
|
uint64_t address;
|
||||||
|
uint64_t length;
|
||||||
|
uint32_t type;
|
||||||
|
} FwCfgE820Entry __attribute((__aligned__(4)));
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <cbmem.h>
|
#include <cbmem.h>
|
||||||
|
|
||||||
#include "fw_cfg.h"
|
#include "fw_cfg.h"
|
||||||
|
#include "fw_cfg_if.h"
|
||||||
|
|
||||||
#include "memory.c"
|
#include "memory.c"
|
||||||
|
|
||||||
|
@ -58,20 +59,62 @@ static void cpu_pci_domain_read_resources(struct device *dev)
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
unsigned long tomk = 0, high;
|
unsigned long tomk = 0, high;
|
||||||
int idx = 10;
|
int idx = 10;
|
||||||
|
int size;
|
||||||
|
|
||||||
pci_domain_read_resources(dev);
|
pci_domain_read_resources(dev);
|
||||||
|
|
||||||
tomk = qemu_get_memory_size();
|
size = fw_cfg_check_file("etc/e820");
|
||||||
high = qemu_get_high_memory_size();
|
if (size > 0) {
|
||||||
printk(BIOS_DEBUG, "Detected %lu MiB RAM below 4G.\n", tomk / 1024);
|
/* supported by qemu 1.7+ */
|
||||||
printk(BIOS_DEBUG, "Detected %lu MiB RAM above 4G.\n", high / 1024);
|
FwCfgE820Entry *list = malloc(size);
|
||||||
|
int i;
|
||||||
|
fw_cfg_load_file("etc/e820", list);
|
||||||
|
for (i = 0; i < size/sizeof(*list); i++) {
|
||||||
|
switch (list[i].type) {
|
||||||
|
case 1: /* ram */
|
||||||
|
printk(BIOS_DEBUG, "QEMU: e820/ram: 0x%08llx +0x%08llx\n",
|
||||||
|
list[i].address, list[i].length);
|
||||||
|
if (list[i].address == 0) {
|
||||||
|
tomk = list[i].length / 1024;
|
||||||
|
ram_resource(dev, idx++, 0, 640);
|
||||||
|
ram_resource(dev, idx++, 768, tomk - 768);
|
||||||
|
} else {
|
||||||
|
ram_resource(dev, idx++,
|
||||||
|
list[i].address / 1024,
|
||||||
|
list[i].length / 1024);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: /* reserved */
|
||||||
|
printk(BIOS_DEBUG, "QEMU: e820/res: 0x%08llx +0x%08llx\n",
|
||||||
|
list[i].address, list[i].length);
|
||||||
|
res = new_resource(dev, idx++);
|
||||||
|
res->base = list[i].address;
|
||||||
|
res->size = list[i].length;
|
||||||
|
res->limit = 0xffffffff;
|
||||||
|
res->flags = IORESOURCE_MEM | IORESOURCE_FIXED |
|
||||||
|
IORESOURCE_STORED | IORESOURCE_ASSIGNED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* skip unknown */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(list);
|
||||||
|
}
|
||||||
|
|
||||||
/* Report the memory regions. */
|
if (!tomk) {
|
||||||
idx = 10;
|
/* qemu older than 1.7, or reading etc/e820 failed. Fallback to cmos. */
|
||||||
ram_resource(dev, idx++, 0, 640);
|
tomk = qemu_get_memory_size();
|
||||||
ram_resource(dev, idx++, 768, tomk - 768);
|
high = qemu_get_high_memory_size();
|
||||||
if (high)
|
printk(BIOS_DEBUG, "QEMU: cmos: %lu MiB RAM below 4G.\n", tomk / 1024);
|
||||||
ram_resource(dev, idx++, 4 * 1024 * 1024, high);
|
printk(BIOS_DEBUG, "QEMU: cmos: %lu MiB RAM above 4G.\n", high / 1024);
|
||||||
|
|
||||||
|
/* Report the memory regions. */
|
||||||
|
ram_resource(dev, idx++, 0, 640);
|
||||||
|
ram_resource(dev, idx++, 768, tomk - 768);
|
||||||
|
if (high)
|
||||||
|
ram_resource(dev, idx++, 4 * 1024 * 1024, high);
|
||||||
|
}
|
||||||
|
|
||||||
/* Reserve I/O ports used by QEMU */
|
/* Reserve I/O ports used by QEMU */
|
||||||
qemu_reserve_ports(dev, idx++, 0x0510, 0x02, "firmware-config");
|
qemu_reserve_ports(dev, idx++, 0x0510, 0x02, "firmware-config");
|
||||||
|
|
Loading…
Reference in New Issue