I was curious to see if SeaBIOS could run in memory above 4GB. This series demonstrates that it is possible. At the end of this experimental patch series, SeaBIOS can relocate itself to physical ram above 4GB and it can also run its internal threads above 4GB.
I've tested this with QEMU running FreeDOS on an ATA drive - other configs are likely to break as most drivers have not been updated to use ioremap().
The series is also available at: https://github.com/KevinOConnor/seabios/tree/testing
The first 7 patches are cleanup patches and should probably be committed even without the others. The remaining patches become more specific to PAE and become increasingly more experimental. The final patch is mostly a hack, but it does verify that SeaBIOS could use PAE to make full use of any RAM in the system.
Patch 14 implements PAE paging support with a simple ioremap() hash scheme. The first 2MB uses an identity map, and no other memory is accessible without first calling ioremap() (or the similar memremap() ). That scheme is probably a bit too aggressive - it would likely be simpler to not require memremap() to access regular ram below 4GB.
-Kevin
Kevin O'Connor (15): e820: Introduce e820_remove() and avoid exporting E820_HOLE e820: Rename memmap.c to e820map.c and use consistent "e820_" prefix e820: Update debugging messages to report 64bit values virtio: Simplify vring alignment code virtio: Move standard definitions from virtio-ring.h to standard headers malloc: Use consistent naming for internal low-level "alloc" functions malloc: Introduce common helper alloc_new_detail() malloc: Don't mix virtual and physical addresses memmap: Move GDT declarations from misc.c to new file memmap.c optionroms: Use ioremap() on PCI rom bars to map them to memory smp: Use ioremap() on APIC memory tpm: Temporary ioremap() hack for tpm_drivers Implement protected mode exception handlers Experimental support for PAE paging Experiment with SeaBIOS internal memory above 4GB
Makefile | 4 +- src/Kconfig | 7 ++ src/{memmap.c => e820map.c} | 18 ++- src/{memmap.h => e820map.h} | 9 +- src/fw/coreboot.c | 8 +- src/fw/csm.c | 14 +-- src/fw/paravirt.c | 22 ++-- src/fw/pciinit.c | 6 +- src/fw/smp.c | 23 ++-- src/fw/xen.c | 9 +- src/hw/pvscsi.c | 2 +- src/hw/ramdisk.c | 5 +- src/hw/tpm_drivers.c | 6 +- src/hw/virtio-ring.h | 36 ++---- src/list.h | 10 ++ src/malloc.c | 296 ++++++++++++++++++++++++-------------------- src/malloc.h | 22 ++-- src/memmap.c | 282 +++++++++++++++++++++++++---------------- src/memmap.h | 48 +++---- src/misc.c | 45 ------- src/optionroms.c | 5 +- src/pmm.c | 16 +-- src/post.c | 6 +- src/romlayout.S | 54 ++++++-- src/stacks.c | 17 ++- src/system.c | 2 +- src/x86.h | 53 +++++++- 27 files changed, 606 insertions(+), 419 deletions(-) copy src/{memmap.c => e820map.c} (90%) copy src/{memmap.h => e820map.h} (66%)
The E820_HOLE definition is used internally in the e820 manipulation code to remove entries from the e820 map. Introduce the e820_remove() function so that the E820_HOLE definition does not need to be exported from the memmap.c code.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/malloc.c | 2 +- src/memmap.c | 10 +++++++++- src/memmap.h | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/src/malloc.c b/src/malloc.c index c4cb171..5c05a8a 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -396,7 +396,7 @@ malloc_preinit(void) dprintf(3, "malloc preinit\n");
// Don't declare any memory between 0xa0000 and 0x100000 - add_e820(BUILD_LOWRAM_END, BUILD_BIOS_ADDR-BUILD_LOWRAM_END, E820_HOLE); + e820_remove(BUILD_LOWRAM_END, BUILD_BIOS_ADDR-BUILD_LOWRAM_END);
// Mark known areas as reserved. add_e820(BUILD_BIOS_ADDR, BUILD_BIOS_SIZE, E820_RESERVED); diff --git a/src/memmap.c b/src/memmap.c index e03f8d0..8c0c38d 100644 --- a/src/memmap.c +++ b/src/memmap.c @@ -54,7 +54,6 @@ e820_type_name(u32 type) case E820_ACPI: return "ACPI"; case E820_NVS: return "NVS"; case E820_UNUSABLE: return "UNUSABLE"; - case E820_HOLE: return "HOLE"; default: return "UNKNOWN"; } } @@ -73,6 +72,8 @@ dump_map(void) } }
+#define E820_HOLE ((u32)-1) // Used internally to remove entries + // Add a new entry to the list. This scans for overlaps and keeps the // list sorted. void @@ -136,6 +137,13 @@ add_e820(u64 start, u64 size, u32 type) //dump_map(); }
+// Remove any definitions in a memory range (make a memory hole). +void +e820_remove(u64 start, u64 size) +{ + add_e820(start, size, E820_HOLE); +} + // Report on final memory locations. void memmap_prepboot(void) diff --git a/src/memmap.h b/src/memmap.h index 7bda56e..e7d94ee 100644 --- a/src/memmap.h +++ b/src/memmap.h @@ -8,7 +8,6 @@ #define E820_ACPI 3 #define E820_NVS 4 #define E820_UNUSABLE 5 -#define E820_HOLE ((u32)-1) // Useful for removing entries
struct e820entry { u64 start; @@ -17,6 +16,7 @@ struct e820entry { };
void add_e820(u64 start, u64 size, u32 type); +void e820_remove(u64 start, u64 size); void memmap_prepboot(void);
// A typical OS page size
Rename memmap.c to e820map.c as the code in that file only deals with maintaining the e820 map. Move all the e820 definitions to new file e820map.h and use a consistent "e820_" prefix on all exported functions.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- Makefile | 2 +- src/{memmap.c => e820map.c} | 8 ++++---- src/{memmap.h => e820map.h} | 7 ++----- src/fw/coreboot.c | 8 ++++---- src/fw/csm.c | 14 +++++++------- src/fw/paravirt.c | 14 +++++++------- src/fw/pciinit.c | 6 +++--- src/fw/xen.c | 9 +++++---- src/hw/ramdisk.c | 5 +++-- src/malloc.c | 11 ++++++----- src/memmap.h | 28 +++------------------------- src/post.c | 6 +++--- src/system.c | 2 +- 13 files changed, 49 insertions(+), 71 deletions(-) rename src/{memmap.c => e820map.c} (96%) copy src/{memmap.h => e820map.h} (77%)
diff --git a/Makefile b/Makefile index 3a0d2e8..e5f28d4 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,7 @@ SRCBOTH=misc.c stacks.c output.c string.c block.c cdrom.c disk.c mouse.c kbd.c \ hw/blockcmd.c hw/floppy.c hw/ata.c hw/ramdisk.c \ hw/lsi-scsi.c hw/esp-scsi.c hw/megasas.c SRC16=$(SRCBOTH) -SRC32FLAT=$(SRCBOTH) post.c memmap.c malloc.c romfile.c x86.c optionroms.c \ +SRC32FLAT=$(SRCBOTH) post.c e820map.c malloc.c romfile.c x86.c optionroms.c \ pmm.c font.c boot.c bootsplash.c jpeg.c bmp.c tcgbios.c sha1.c \ hw/ahci.c hw/pvscsi.c hw/usb-xhci.c hw/usb-hub.c hw/sdcard.c \ fw/coreboot.c fw/lzmadecode.c fw/multiboot.c fw/csm.c fw/biostables.c \ diff --git a/src/memmap.c b/src/e820map.c similarity index 96% rename from src/memmap.c rename to src/e820map.c index 8c0c38d..901ccdf 100644 --- a/src/memmap.c +++ b/src/e820map.c @@ -5,7 +5,7 @@ // This file may be distributed under the terms of the GNU LGPLv3 license.
#include "config.h" // BUILD_MAX_E820 -#include "memmap.h" // struct e820entry +#include "e820map.h" // struct e820entry #include "output.h" // dprintf #include "string.h" // memmove
@@ -77,7 +77,7 @@ dump_map(void) // Add a new entry to the list. This scans for overlaps and keeps the // list sorted. void -add_e820(u64 start, u64 size, u32 type) +e820_add(u64 start, u64 size, u32 type) { dprintf(8, "Add to e820 map: %08x %08x %d\n", (u32)start, (u32)size, type);
@@ -141,12 +141,12 @@ add_e820(u64 start, u64 size, u32 type) void e820_remove(u64 start, u64 size) { - add_e820(start, size, E820_HOLE); + e820_add(start, size, E820_HOLE); }
// Report on final memory locations. void -memmap_prepboot(void) +e820_prepboot(void) { dump_map(); } diff --git a/src/memmap.h b/src/e820map.h similarity index 77% copy from src/memmap.h copy to src/e820map.h index e7d94ee..de8b523 100644 --- a/src/memmap.h +++ b/src/e820map.h @@ -15,12 +15,9 @@ struct e820entry { u32 type; };
-void add_e820(u64 start, u64 size, u32 type); +void e820_add(u64 start, u64 size, u32 type); void e820_remove(u64 start, u64 size); -void memmap_prepboot(void); - -// A typical OS page size -#define PAGE_SIZE 4096 +void e820_prepboot(void);
// e820 map storage extern struct e820entry e820_list[]; diff --git a/src/fw/coreboot.c b/src/fw/coreboot.c index b077fe1..a47f524 100644 --- a/src/fw/coreboot.c +++ b/src/fw/coreboot.c @@ -7,10 +7,10 @@ #include "block.h" // MAXDESCSIZE #include "byteorder.h" // be32_to_cpu #include "config.h" // CONFIG_* +#include "e820map.h" // e820_add #include "hw/pci.h" // pci_probe_devices #include "lzmadecode.h" // LzmaDecode #include "malloc.h" // free -#include "memmap.h" // add_e820 #include "output.h" // dprintf #include "paravirt.h" // PlatformRunningOn #include "romfile.h" // romfile_findprefix @@ -184,12 +184,12 @@ coreboot_preinit(void) u32 type = m->type; if (type == CB_MEM_TABLE) type = E820_RESERVED; - add_e820(m->start, m->size, type); + e820_add(m->start, m->size, type); }
// Ughh - coreboot likes to set a map at 0x0000-0x1000, but this // confuses grub. So, override it. - add_e820(0, 16*1024, E820_RAM); + e820_add(0, 16*1024, E820_RAM);
struct cb_cbmem_ref *cbref = find_cb_subtable(cbh, CB_TAG_CBMEM_CONSOLE); if (cbref) { @@ -210,7 +210,7 @@ coreboot_preinit(void) fail: // No table found.. Use 16Megs as a dummy value. dprintf(1, "Unable to find coreboot table!\n"); - add_e820(0, 16*1024*1024, E820_RAM); + e820_add(0, 16*1024*1024, E820_RAM); return; }
diff --git a/src/fw/csm.c b/src/fw/csm.c index aee2f90..0467560 100644 --- a/src/fw/csm.c +++ b/src/fw/csm.c @@ -4,20 +4,20 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license.
-#include "bregs.h" +#include "bregs.h" // struct bregs #include "config.h" // CONFIG_* +#include "e820map.h" // e820_add #include "farptr.h" // MAKE_FLATPTR -#include "hw/pci.h" -#include "hw/pic.h" +#include "hw/pci.h" // pci_probe_devices +#include "hw/pic.h" // pic_irqmask_read #include "malloc.h" // csm_malloc_preinit -#include "memmap.h" #include "output.h" // dprintf +#include "paravirt.h" // qemu_preinit #include "stacks.h" // wait_threads #include "std/acpi.h" // RSDP_SIGNATURE #include "std/bda.h" // struct bios_data_area_s #include "std/optionrom.h" // struct rom_header #include "util.h" // copy_smbios -#include "paravirt.h" // qemu_preinit
#define UINT8 u8 #define UINT16 u16 @@ -147,11 +147,11 @@ handle_csm_0002(struct bregs *regs) struct e820entry *p = (void *)csm_compat_table.E820Pointer; int i; for (i=0; i < csm_compat_table.E820Length / sizeof(struct e820entry); i++) - add_e820(p[i].start, p[i].size, p[i].type); + e820_add(p[i].start, p[i].size, p[i].type);
if (csm_init_table->HiPmmMemorySizeInBytes > BUILD_MAX_HIGHTABLE) { u32 hi_pmm_end = csm_init_table->HiPmmMemory + csm_init_table->HiPmmMemorySizeInBytes; - add_e820(hi_pmm_end - BUILD_MAX_HIGHTABLE, BUILD_MAX_HIGHTABLE, E820_RESERVED); + e820_add(hi_pmm_end - BUILD_MAX_HIGHTABLE, BUILD_MAX_HIGHTABLE, E820_RESERVED); }
// For PCIBIOS 1ab10e diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c index db22ae8..acb44b9 100644 --- a/src/fw/paravirt.c +++ b/src/fw/paravirt.c @@ -10,11 +10,11 @@
#include "byteorder.h" // be32_to_cpu #include "config.h" // CONFIG_QEMU +#include "e820map.h" // e820_add #include "hw/pci.h" // create_pirtable #include "hw/pci_regs.h" // PCI_DEVICE_ID #include "hw/rtc.h" // CMOS_* #include "malloc.h" // malloc_tmp -#include "memmap.h" // add_e820 #include "output.h" // dprintf #include "paravirt.h" // qemu_cfg_preinit #include "romfile.h" // romfile_loadint @@ -114,10 +114,10 @@ qemu_preinit(void) | (rtc_read(CMOS_MEM_EXTMEM_HIGH) << 18)) + 1 * 1024 * 1024); RamSize = rs; - add_e820(0, rs, E820_RAM); + e820_add(0, rs, E820_RAM);
/* reserve 256KB BIOS area at the end of 4 GB */ - add_e820(0xfffc0000, 256*1024, E820_RESERVED); + e820_add(0xfffc0000, 256*1024, E820_RESERVED);
dprintf(1, "RamSize: 0x%08x [cmos]\n", RamSize); } @@ -302,7 +302,7 @@ qemu_cfg_e820(void) } /* fall through */ case E820_RESERVED: - add_e820(table[i].address, table[i].length, table[i].type); + e820_add(table[i].address, table[i].length, table[i].type); break; default: /* @@ -324,13 +324,13 @@ qemu_cfg_e820(void) int i; for (i = 0; i < count32; i++) { qemu_cfg_read(&entry, sizeof(entry)); - add_e820(entry.address, entry.length, entry.type); + e820_add(entry.address, entry.length, entry.type); } } else if (runningOnKVM()) { // Backwards compatibility - provide hard coded range. // 4 pages before the bios, 3 pages for vmx tss pages, the // other page for EPT real mode pagetable - add_e820(0xfffbc000, 4*4096, E820_RESERVED); + e820_add(0xfffbc000, 4*4096, E820_RESERVED); }
// Check for memory over 4Gig in cmos @@ -338,7 +338,7 @@ qemu_cfg_e820(void) | ((u32)rtc_read(CMOS_MEM_HIGHMEM_MID) << 24) | ((u64)rtc_read(CMOS_MEM_HIGHMEM_HIGH) << 32)); RamSizeOver4G = high; - add_e820(0x100000000ull, high, E820_RAM); + e820_add(0x100000000ull, high, E820_RAM); dprintf(1, "RamSizeOver4G: 0x%016llx [cmos]\n", RamSizeOver4G); }
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c index 3ad84ba..7b8aab7 100644 --- a/src/fw/pciinit.c +++ b/src/fw/pciinit.c @@ -9,13 +9,13 @@ #include "config.h" // CONFIG_* #include "dev-q35.h" // Q35_HOST_BRIDGE_PCIEXBAR_ADDR #include "dev-piix.h" // PIIX_* +#include "e820map.h" // e820_add #include "hw/ata.h" // PORT_ATA1_CMD_BASE #include "hw/pci.h" // pci_config_readl #include "hw/pci_ids.h" // PCI_VENDOR_ID_INTEL #include "hw/pci_regs.h" // PCI_COMMAND #include "list.h" // struct hlist_node #include "malloc.h" // free -#include "memmap.h" // add_e820 #include "output.h" // dprintf #include "paravirt.h" // RamSize #include "romfile.h" // romfile_loadint @@ -186,7 +186,7 @@ static void mch_isa_bridge_setup(struct pci_device *dev, void *arg) /* set root complex register block BAR */ pci_config_writel(bdf, ICH9_LPC_RCBA, ICH9_LPC_RCBA_ADDR | ICH9_LPC_RCBA_EN); - add_e820(ICH9_LPC_RCBA_ADDR, 16*1024, E820_RESERVED); + e820_add(ICH9_LPC_RCBA_ADDR, 16*1024, E820_RESERVED);
acpi_pm1a_cnt = acpi_pm_base + 0x04; pmtimer_setup(acpi_pm_base + 0x08); @@ -400,7 +400,7 @@ static void mch_mem_addr_setup(struct pci_device *dev, void *arg) pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, 0); pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR + 4, upper); pci_config_writel(bdf, Q35_HOST_BRIDGE_PCIEXBAR, lower); - add_e820(addr, size, E820_RESERVED); + e820_add(addr, size, E820_RESERVED);
/* setup pci i/o window (above mmconfig) */ pcimem_start = addr + size; diff --git a/src/fw/xen.c b/src/fw/xen.c index dd8e8af..3f19ef2 100644 --- a/src/fw/xen.c +++ b/src/fw/xen.c @@ -4,16 +4,17 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license.
-#include "config.h" +#include "config.h" // CONFIG_XEN +#include "e820map.h" // e820_add #include "hw/serialio.h" // DebugOutputPort #include "malloc.h" // memalign_high -#include "memmap.h" // add_e820 +#include "memmap.h" // PAGE_SIZE #include "output.h" // dprintf #include "paravirt.h" // PlatformRunningOn #include "string.h" // memcpy #include "util.h" // copy_acpi_rsdp #include "x86.h" // cpuid -#include "xen.h" +#include "xen.h" // xen_extraversion_t
#define INFO_PHYSICAL_ADDRESS 0x00001000
@@ -142,6 +143,6 @@ void xen_ramsize_preinit(void)
for (i = 0; i < info->e820_nr; i++) { struct e820entry *e = &e820[i]; - add_e820(e->start, e->size, e->type); + e820_add(e->start, e->size, e->type); } } diff --git a/src/hw/ramdisk.c b/src/hw/ramdisk.c index 4cdf95f..adec1d1 100644 --- a/src/hw/ramdisk.c +++ b/src/hw/ramdisk.c @@ -7,8 +7,9 @@ #include "biosvar.h" // GET_GLOBALFLAT #include "block.h" // struct drive_s #include "bregs.h" // struct bregs +#include "e820map.h" // e820_add #include "malloc.h" // memalign_tmphigh -#include "memmap.h" // add_e820 +#include "memmap.h" // PAGE_SIZE #include "output.h" // dprintf #include "romfile.h" // romfile_findprefix #include "stacks.h" // call16_int @@ -41,7 +42,7 @@ ramdisk_setup(void) warn_noalloc(); return; } - add_e820((u32)pos, size, E820_RESERVED); + e820_add((u32)pos, size, E820_RESERVED);
// Copy image into ram. int ret = file->copy(file, pos, size); diff --git a/src/malloc.c b/src/malloc.c index 5c05a8a..efd09b3 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -6,9 +6,10 @@
#include "biosvar.h" // GET_BDA #include "config.h" // BUILD_BIOS_ADDR +#include "e820map.h" // struct e820entry #include "list.h" // hlist_node #include "malloc.h" // _malloc -#include "memmap.h" // struct e820entry +#include "memmap.h" // PAGE_SIZE #include "output.h" // dprintf #include "stacks.h" // wait_preempt #include "std/optionrom.h" // OPTION_ROM_ALIGN @@ -399,7 +400,7 @@ malloc_preinit(void) e820_remove(BUILD_LOWRAM_END, BUILD_BIOS_ADDR-BUILD_LOWRAM_END);
// Mark known areas as reserved. - add_e820(BUILD_BIOS_ADDR, BUILD_BIOS_SIZE, E820_RESERVED); + e820_add(BUILD_BIOS_ADDR, BUILD_BIOS_SIZE, E820_RESERVED);
// Populate temp high ram u32 highram = 0; @@ -427,7 +428,7 @@ malloc_preinit(void) if (highram) { addSpace(&ZoneHigh, (void*)highram , (void*)highram + BUILD_MAX_HIGHTABLE); - add_e820(highram, BUILD_MAX_HIGHTABLE, E820_RESERVED); + e820_add(highram, BUILD_MAX_HIGHTABLE, E820_RESERVED); } }
@@ -521,7 +522,7 @@ malloc_prepboot(void)
// Reserve more low-mem if needed. u32 endlow = GET_BDA(mem_size_kb)*1024; - add_e820(endlow, BUILD_LOWRAM_END-endlow, E820_RESERVED); + e820_add(endlow, BUILD_LOWRAM_END-endlow, E820_RESERVED);
// Clear unused f-seg ram. struct allocinfo_s *info = findLast(&ZoneFSeg); @@ -533,7 +534,7 @@ malloc_prepboot(void) info = findLast(&ZoneHigh); if (info) { u32 giveback = ALIGN_DOWN(info->allocend - info->dataend, PAGE_SIZE); - add_e820((u32)info->dataend, giveback, E820_RAM); + e820_add((u32)info->dataend, giveback, E820_RAM); dprintf(1, "Returned %d bytes of ZoneHigh\n", giveback); }
diff --git a/src/memmap.h b/src/memmap.h index e7d94ee..c439982 100644 --- a/src/memmap.h +++ b/src/memmap.h @@ -1,29 +1,7 @@ -#ifndef __E820MAP_H -#define __E820MAP_H - -#include "types.h" // u64 - -#define E820_RAM 1 -#define E820_RESERVED 2 -#define E820_ACPI 3 -#define E820_NVS 4 -#define E820_UNUSABLE 5 - -struct e820entry { - u64 start; - u64 size; - u32 type; -}; - -void add_e820(u64 start, u64 size, u32 type); -void e820_remove(u64 start, u64 size); -void memmap_prepboot(void); +#ifndef __MEMMAP_H +#define __MEMMAP_H
// A typical OS page size #define PAGE_SIZE 4096
-// e820 map storage -extern struct e820entry e820_list[]; -extern int e820_count; - -#endif // e820map.h +#endif // memmap.h diff --git a/src/post.c b/src/post.c index e19b06c..89e6eff 100644 --- a/src/post.c +++ b/src/post.c @@ -8,6 +8,7 @@ #include "biosvar.h" // SET_BDA #include "bregs.h" // struct bregs #include "config.h" // CONFIG_* +#include "e820map.h" // e820_add #include "fw/paravirt.h" // qemu_cfg_preinit #include "fw/xen.h" // xen_preinit #include "hw/ahci.h" // ahci_setup @@ -24,7 +25,6 @@ #include "hw/virtio-blk.h" // virtio_blk_setup #include "hw/virtio-scsi.h" // virtio_scsi_setup #include "malloc.h" // malloc_init -#include "memmap.h" // add_e820 #include "output.h" // dprintf #include "string.h" // memset #include "util.h" // kbd_init @@ -102,7 +102,7 @@ bda_init(void) memset(ebda, 0, sizeof(*ebda)); ebda->size = esize;
- add_e820((u32)ebda, BUILD_LOWRAM_END-(u32)ebda, E820_RESERVED); + e820_add((u32)ebda, BUILD_LOWRAM_END-(u32)ebda, E820_RESERVED);
// Init extra stack StackPos = (void*)(&ExtraStack[BUILD_EXTRA_STACK_SIZE] - zonelow_base); @@ -191,7 +191,7 @@ prepareboot(void) cdrom_prepboot(); pmm_prepboot(); malloc_prepboot(); - memmap_prepboot(); + e820_prepboot();
HaveRunPost = 2;
diff --git a/src/system.c b/src/system.c index 60a6fce..438e60e 100644 --- a/src/system.c +++ b/src/system.c @@ -7,9 +7,9 @@
#include "biosvar.h" // GET_GLOBAL #include "bregs.h" // struct bregs +#include "e820map.h" // E820_RAM #include "hw/pic.h" // pic_reset #include "malloc.h" // LegacyRamSize -#include "memmap.h" // E820_RAM #include "output.h" // debug_enter #include "string.h" // memcpy_far #include "util.h" // handle_1553
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/e820map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/e820map.c b/src/e820map.c index 901ccdf..39445cf 100644 --- a/src/e820map.c +++ b/src/e820map.c @@ -79,7 +79,7 @@ dump_map(void) void e820_add(u64 start, u64 size, u32 type) { - dprintf(8, "Add to e820 map: %08x %08x %d\n", (u32)start, (u32)size, type); + dprintf(8, "Add to e820 map: %08llx %08llx %d\n", start, size, type);
if (! size) // Huh? Nothing to do.
Don't do phys_to_virt(virt_to_phys(vaddr)) for page alignment - page alignment can be determined directly from the virtual address.
Use the ALIGN() macro to make the code more readable.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/hw/virtio-ring.h | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-)
diff --git a/src/hw/virtio-ring.h b/src/hw/virtio-ring.h index 7df9004..e8f3b82 100644 --- a/src/hw/virtio-ring.h +++ b/src/hw/virtio-ring.h @@ -5,10 +5,8 @@ #include "memmap.h" // PAGE_SIZE
#define PAGE_SHIFT 12 -#define PAGE_MASK (PAGE_SIZE-1)
#define virt_to_phys(v) (unsigned long)(v) -#define phys_to_virt(p) (void*)(p) /* Compiler barrier is enough as an x86 CPU does not reorder reads or writes */ #define smp_rmb() barrier() #define smp_wmb() barrier() @@ -73,10 +71,9 @@ struct vring { };
#define vring_size(num) \ - (((((sizeof(struct vring_desc) * num) + \ - (sizeof(struct vring_avail) + sizeof(u16) * num)) \ - + PAGE_MASK) & ~PAGE_MASK) + \ - (sizeof(struct vring_used) + sizeof(struct vring_used_elem) * num)) + (ALIGN(sizeof(struct vring_desc) * num + sizeof(struct vring_avail) \ + + sizeof(u16) * num, PAGE_SIZE) \ + + sizeof(struct vring_used) + sizeof(struct vring_used_elem) * num)
typedef unsigned char virtio_queue_t[vring_size(MAX_QUEUE_NUM)];
@@ -96,33 +93,25 @@ struct vring_list { unsigned int length; };
-static inline void vring_init(struct vring *vr, - unsigned int num, unsigned char *queue) +static inline void +vring_init(struct vring *vr, unsigned int num, unsigned char *queue) { - unsigned int i; - unsigned long pa; - ASSERT32FLAT(); vr->num = num;
/* physical address of desc must be page aligned */ - - pa = virt_to_phys(queue); - pa = (pa + PAGE_MASK) & ~PAGE_MASK; - vr->desc = phys_to_virt(pa); + vr->desc = (void*)ALIGN((u32)queue, PAGE_SIZE);
vr->avail = (struct vring_avail *)&vr->desc[num]; /* disable interrupts */ vr->avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
/* physical address of used must be page aligned */ + vr->used = (void*)ALIGN((u32)&vr->avail->ring[num], PAGE_SIZE);
- pa = virt_to_phys(&vr->avail->ring[num]); - pa = (pa + PAGE_MASK) & ~PAGE_MASK; - vr->used = phys_to_virt(pa); - + int i; for (i = 0; i < num - 1; i++) - vr->desc[i].next = i + 1; + vr->desc[i].next = i + 1; vr->desc[i].next = 0; }
Move PAGE_SHIFT / virt_to_phys() to memmap.h and smp_[rw]mb() to x86.h.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/hw/pvscsi.c | 2 +- src/hw/virtio-ring.h | 7 ------- src/memmap.h | 7 +++++++ src/x86.h | 8 ++++++++ 4 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/src/hw/pvscsi.c b/src/hw/pvscsi.c index a462522..fa20efe 100644 --- a/src/hw/pvscsi.c +++ b/src/hw/pvscsi.c @@ -11,6 +11,7 @@ #include "blockcmd.h" // scsi_drive_setup #include "config.h" // CONFIG_* #include "malloc.h" // free +#include "memmap.h" // PAGE_SHIFT, virt_to_phys #include "output.h" // dprintf #include "pci.h" // foreachpci #include "pci_ids.h" // PCI_DEVICE_ID_VMWARE_PVSCSI @@ -19,7 +20,6 @@ #include "std/disk.h" // DISK_RET_SUCCESS #include "string.h" // memset #include "util.h" // usleep -#include "virtio-ring.h" // PAGE_SHIFT, virt_to_phys #include "x86.h" // writel
#define MASK(n) ((1 << (n)) - 1) diff --git a/src/hw/virtio-ring.h b/src/hw/virtio-ring.h index e8f3b82..7665fd5 100644 --- a/src/hw/virtio-ring.h +++ b/src/hw/virtio-ring.h @@ -4,13 +4,6 @@ #include "types.h" // u64 #include "memmap.h" // PAGE_SIZE
-#define PAGE_SHIFT 12 - -#define virt_to_phys(v) (unsigned long)(v) -/* Compiler barrier is enough as an x86 CPU does not reorder reads or writes */ -#define smp_rmb() barrier() -#define smp_wmb() barrier() - /* Status byte for guest to report progress, and synchronize features. */ /* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ #define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 diff --git a/src/memmap.h b/src/memmap.h index c439982..9a59024 100644 --- a/src/memmap.h +++ b/src/memmap.h @@ -1,7 +1,14 @@ #ifndef __MEMMAP_H #define __MEMMAP_H
+#include "types.h" // u32 + // A typical OS page size #define PAGE_SIZE 4096 +#define PAGE_SHIFT 12 + +static inline u32 virt_to_phys(void *v) { + return (u32)v; +}
#endif // memmap.h diff --git a/src/x86.h b/src/x86.h index 19d404f..53378e9 100644 --- a/src/x86.h +++ b/src/x86.h @@ -190,6 +190,14 @@ static inline void outsl(u16 port, u32 *data, u32 count) { : "+c"(count), "+S"(data) : "d"(port) : "memory"); }
+/* Compiler barrier is enough as an x86 CPU does not reorder reads or writes */ +static inline void smp_rmb(void) { + barrier(); +} +static inline void smp_wmb(void) { + barrier(); +} + static inline void writel(void *addr, u32 val) { barrier(); *(volatile u32 *)addr = val;
Use the "alloc_" prefix for all the low-level allocation functions and avoid camelCase naming.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/malloc.c | 102 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 51 insertions(+), 51 deletions(-)
diff --git a/src/malloc.c b/src/malloc.c index efd09b3..3aed014 100644 --- a/src/malloc.c +++ b/src/malloc.c @@ -48,7 +48,7 @@ static struct zone_s *Zones[] VARVERIFY32INIT = {
// Find and reserve space from a given zone static void * -allocSpace(struct zone_s *zone, u32 size, u32 align, struct allocinfo_s *fill) +alloc_new(struct zone_s *zone, u32 size, u32 align, struct allocinfo_s *fill) { struct allocinfo_s *info; hlist_for_each_entry(info, &zone->head, node) { @@ -71,20 +71,9 @@ allocSpace(struct zone_s *zone, u32 size, u32 align, struct allocinfo_s *fill) return NULL; }
-// Release space allocated with allocSpace() -static void -freeSpace(struct allocinfo_s *info) -{ - struct allocinfo_s *next = container_of_or_null( - info->node.next, struct allocinfo_s, node); - if (next && next->allocend == info->data) - next->allocend = info->allocend; - hlist_del(&info->node); -} - // Add new memory to a zone static void -addSpace(struct zone_s *zone, void *start, void *end) +alloc_add(struct zone_s *zone, void *start, void *end) { // Find position to add space struct allocinfo_s *info; @@ -101,11 +90,11 @@ addSpace(struct zone_s *zone, void *start, void *end) hlist_add(&tempdetail.datainfo.node, pprev);
// Allocate final allocation info. - struct allocdetail_s *detail = allocSpace( + struct allocdetail_s *detail = alloc_new( &ZoneTmpHigh, sizeof(*detail), MALLOC_MIN_ALIGN, NULL); if (!detail) { - detail = allocSpace(&ZoneTmpLow, sizeof(*detail) - , MALLOC_MIN_ALIGN, NULL); + detail = alloc_new(&ZoneTmpLow, sizeof(*detail) + , MALLOC_MIN_ALIGN, NULL); if (!detail) { hlist_del(&tempdetail.datainfo.node); warn_noalloc(); @@ -121,9 +110,20 @@ addSpace(struct zone_s *zone, void *start, void *end) hlist_add(&detail->datainfo.node, pprev); }
-// Search all zones for an allocation obtained from allocSpace() +// Release space allocated with alloc_new() +static void +alloc_free(struct allocinfo_s *info) +{ + struct allocinfo_s *next = container_of_or_null( + info->node.next, struct allocinfo_s, node); + if (next && next->allocend == info->data) + next->allocend = info->allocend; + hlist_del(&info->node); +} + +// Search all zones for an allocation obtained from alloc_new() static struct allocinfo_s * -findAlloc(void *data) +alloc_find(void *data) { int i; for (i=0; i<ARRAY_SIZE(Zones); i++) { @@ -136,9 +136,9 @@ findAlloc(void *data) return NULL; }
-// Return the last sentinal node of a zone +// Return the sentinel node of a zone (stores lowest contiguous free space) static struct allocinfo_s * -findLast(struct zone_s *zone) +alloc_get_sentinel(struct zone_s *zone) { struct allocinfo_s *info, *last = NULL; hlist_for_each_entry(info, &zone->head, node) { @@ -177,12 +177,12 @@ zonelow_expand(u32 size, u32 align, struct allocinfo_s *fill) { // Make sure to not move ebda while an optionrom is running. if (unlikely(wait_preempt())) { - void *data = allocSpace(&ZoneLow, size, align, fill); + void *data = alloc_new(&ZoneLow, size, align, fill); if (data) return data; }
- struct allocinfo_s *info = findLast(&ZoneLow); + struct allocinfo_s *info = alloc_get_sentinel(&ZoneLow); if (!info) return NULL; u32 oldpos = (u32)info->allocend; @@ -190,7 +190,7 @@ zonelow_expand(u32 size, u32 align, struct allocinfo_s *fill) u32 bottom = (u32)info->dataend; if (newpos >= bottom && newpos <= oldpos) // Space already present. - return allocSpace(&ZoneLow, size, align, fill); + return alloc_new(&ZoneLow, size, align, fill); u16 ebda_seg = get_ebda_seg(); u32 ebda_pos = (u32)MAKE_FLATPTR(ebda_seg, 0); u8 ebda_size = GET_EBDA(ebda_seg, size); @@ -214,9 +214,9 @@ zonelow_expand(u32 size, u32 align, struct allocinfo_s *fill) info->data = (void*)newbottom; info->dataend = (void*)newbottom; } else - addSpace(&ZoneLow, (void*)newbottom, (void*)ebda_end); + alloc_add(&ZoneLow, (void*)newbottom, (void*)ebda_end);
- return allocSpace(&ZoneLow, size, align, fill); + return alloc_new(&ZoneLow, size, align, fill); }
@@ -233,22 +233,22 @@ _malloc(struct zone_s *zone, u32 size, u32 align) return NULL;
// Find and reserve space for bookkeeping. - struct allocdetail_s *detail = allocSpace( + struct allocdetail_s *detail = alloc_new( &ZoneTmpHigh, sizeof(*detail), MALLOC_MIN_ALIGN, NULL); if (!detail) { - detail = allocSpace(&ZoneTmpLow, sizeof(*detail) - , MALLOC_MIN_ALIGN, NULL); + detail = alloc_new(&ZoneTmpLow, sizeof(*detail) + , MALLOC_MIN_ALIGN, NULL); if (!detail) return NULL; } detail->handle = MALLOC_DEFAULT_HANDLE;
// Find and reserve space for main allocation - void *data = allocSpace(zone, size, align, &detail->datainfo); + void *data = alloc_new(zone, size, align, &detail->datainfo); if (!CONFIG_MALLOC_UPPERMEMORY && !data && zone == &ZoneLow) data = zonelow_expand(size, align, &detail->datainfo); if (!data) { - freeSpace(&detail->detailinfo); + alloc_free(&detail->detailinfo); return NULL; }
@@ -263,14 +263,14 @@ int _free(void *data) { ASSERT32FLAT(); - struct allocinfo_s *info = findAlloc(data); + struct allocinfo_s *info = alloc_find(data); if (!info || data == (void*)info || data == info->dataend) return -1; struct allocdetail_s *detail = container_of( info, struct allocdetail_s, datainfo); dprintf(8, "_free %p (detail=%p)\n", data, detail); - freeSpace(info); - freeSpace(&detail->detailinfo); + alloc_free(info); + alloc_free(&detail->detailinfo); return 0; }
@@ -302,7 +302,7 @@ void malloc_sethandle(void *data, u32 handle) { ASSERT32FLAT(); - struct allocinfo_s *info = findAlloc(data); + struct allocinfo_s *info = alloc_find(data); if (!info || data == (void*)info || data == info->dataend) return; struct allocdetail_s *detail = container_of( @@ -420,14 +420,14 @@ malloc_preinit(void) e = newe; } } - addSpace(&ZoneTmpHigh, (void*)s, (void*)e); + alloc_add(&ZoneTmpHigh, (void*)s, (void*)e); }
// Populate regions - addSpace(&ZoneTmpLow, (void*)BUILD_STACK_ADDR, (void*)BUILD_EBDA_MINIMUM); + alloc_add(&ZoneTmpLow, (void*)BUILD_STACK_ADDR, (void*)BUILD_EBDA_MINIMUM); if (highram) { - addSpace(&ZoneHigh, (void*)highram - , (void*)highram + BUILD_MAX_HIGHTABLE); + alloc_add(&ZoneHigh, (void*)highram + , (void*)highram + BUILD_MAX_HIGHTABLE); e820_add(highram, BUILD_MAX_HIGHTABLE, E820_RESERVED); } } @@ -438,13 +438,13 @@ csm_malloc_preinit(u32 low_pmm, u32 low_pmm_size, u32 hi_pmm, u32 hi_pmm_size) ASSERT32FLAT();
if (hi_pmm_size > BUILD_MAX_HIGHTABLE) { - void *hi_pmm_end = (void *)hi_pmm + hi_pmm_size; - addSpace(&ZoneTmpHigh, (void *)hi_pmm, hi_pmm_end - BUILD_MAX_HIGHTABLE); - addSpace(&ZoneHigh, hi_pmm_end - BUILD_MAX_HIGHTABLE, hi_pmm_end); + void *hi_pmm_end = (void*)hi_pmm + hi_pmm_size; + alloc_add(&ZoneTmpHigh, (void*)hi_pmm, hi_pmm_end - BUILD_MAX_HIGHTABLE); + alloc_add(&ZoneHigh, hi_pmm_end - BUILD_MAX_HIGHTABLE, hi_pmm_end); } else { - addSpace(&ZoneTmpHigh, (void *)hi_pmm, (void *)hi_pmm + hi_pmm_size); + alloc_add(&ZoneTmpHigh, (void*)hi_pmm, (void*)hi_pmm + hi_pmm_size); } - addSpace(&ZoneTmpLow, (void *)low_pmm, (void *)low_pmm + low_pmm_size); + alloc_add(&ZoneTmpLow, (void*)low_pmm, (void*)low_pmm + low_pmm_size); }
u32 LegacyRamSize VARFSEG; @@ -488,18 +488,18 @@ malloc_init(void) extern u8 varlow_start[], varlow_end[], final_varlow_start[]; memmove(final_varlow_start, varlow_start, varlow_end - varlow_start); if (CONFIG_MALLOC_UPPERMEMORY) { - addSpace(&ZoneLow, zonelow_base + OPROM_HEADER_RESERVE - , final_varlow_start); - RomBase = findLast(&ZoneLow); + alloc_add(&ZoneLow, zonelow_base + OPROM_HEADER_RESERVE + , final_varlow_start); + RomBase = alloc_get_sentinel(&ZoneLow); } else { - addSpace(&ZoneLow, (void*)ALIGN_DOWN((u32)final_varlow_start, 1024) - , final_varlow_start); + alloc_add(&ZoneLow, (void*)ALIGN_DOWN((u32)final_varlow_start, 1024) + , final_varlow_start); }
// Add space available in f-segment to ZoneFSeg extern u8 zonefseg_start[], zonefseg_end[]; memset(zonefseg_start, 0, zonefseg_end - zonefseg_start); - addSpace(&ZoneFSeg, zonefseg_start, zonefseg_end); + alloc_add(&ZoneFSeg, zonefseg_start, zonefseg_end);
calcRamSize(); } @@ -525,13 +525,13 @@ malloc_prepboot(void) e820_add(endlow, BUILD_LOWRAM_END-endlow, E820_RESERVED);
// Clear unused f-seg ram. - struct allocinfo_s *info = findLast(&ZoneFSeg); + struct allocinfo_s *info = alloc_get_sentinel(&ZoneFSeg); memset(info->dataend, 0, info->allocend - info->dataend); dprintf(1, "Space available for UMB: %x-%x, %x-%x\n" , RomEnd, base, (u32)info->dataend, (u32)info->allocend);
// Give back unused high ram. - info = findLast(&ZoneHigh); + info = alloc_get_sentinel(&ZoneHigh); if (info) { u32 giveback = ALIGN_DOWN(info->allocend - info->dataend, PAGE_SIZE); e820_add((u32)info->dataend, giveback, E820_RAM);