add malloc Allocate the e820 map in the E-segment. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
diff --git a/Makefile b/Makefile index 39a63bd..6db2104 100644 --- a/Makefile +++ b/Makefile
@@ -1,5 +1,5 @@ obj-y = code16.o entry.o main.o string.o printf.o cstart.o fw_cfg.o -obj-y += linuxboot.o +obj-y += linuxboot.o malloc.o all-y = bios.bin all: $(all-y)
diff --git a/code16.c b/code16.c index d8861de..f933915 100644 --- a/code16.c +++ b/code16.c
@@ -1,4 +1,5 @@ asm(".code16gcc"); +#include <stddef.h> #include "bios.h" #include "segment.h" #include "ioport.h" @@ -23,32 +24,40 @@ { uint32_t v; - asm volatile("addr32 movl %%fs:%1,%0" : "=q" (v) : "m" (*(uint32_t *)addr)); + asm volatile("addr32 movl %%fs:%1,%0" : "=r" (v) : "m" (*(uint32_t *)addr)); return v; } -struct e820map e820; +static inline uint16_t rdcs16(void *p) +{ + uint32_t addr = ((uintptr_t) p) & 65535; + uint16_t v; + + asm volatile("addr32 movw %%cs:%1,%0" : "=r" (v) : "m" (*(uint32_t *)addr)); + + return v; +} + +uint16_t e820_seg; bioscall void e820_query_map(struct biosregs *regs) { uint32_t map_size; - uint16_t fs_seg; uint32_t ndx; - fs_seg = flat_to_seg16((uintptr_t) &e820); - set_fs(fs_seg); + set_fs(rdcs16(&e820_seg)); ndx = regs->ebx; - map_size = rdfs32(flat_to_off16((uintptr_t) &e820.nr_map)); + map_size = rdfs32(offsetof(struct e820map, nr_map)); if (ndx < map_size) { uint32_t start; unsigned int i; uint8_t *p; - start = flat_to_off16((uintptr_t)&e820.map[ndx]); + start = flat_to_off16(offsetof(struct e820map, map[ndx])); p = (void *) regs->edi;
diff --git a/flat.lds b/flat.lds index d12b835..be84ec3 100644 --- a/flat.lds +++ b/flat.lds
@@ -3,14 +3,16 @@ SECTIONS { . = 1024K - 64K; + stext = .; .text : { *(.text.startup) *(.text) *(.text.*) } - . = ALIGN(4K); + . = ALIGN(16); .data : { *(.data) } . = ALIGN(16); .rodata : { *(.rodata) } . = ALIGN(16); .bss : { *(.bss) } - . = ALIGN(4K); + . = ALIGN(16); + edata = .; . = 1024K - 128; .init : { *(.init);
diff --git a/include/bios.h b/include/bios.h index 93c4c96..d3f9a22 100644 --- a/include/bios.h +++ b/include/bios.h
@@ -38,7 +38,7 @@ extern void boot_from_fwcfg(void); -extern struct e820map e820; +extern uint16_t e820_seg; #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
diff --git a/include/e820.h b/include/e820.h index 1dfd18f..085df6a 100644 --- a/include/e820.h +++ b/include/e820.h
@@ -2,30 +2,6 @@ #define _UAPI_ASM_X86_E820_H #define SMAP 0x534d4150 /* ASCII "SMAP" */ -#define E820MAP 0x2d0 /* our map */ -#define E820MAX 128 /* number of entries in E820MAP */ - -/* - * Legacy E820 BIOS limits us to 128 (E820MAX) nodes due to the - * constrained space in the zeropage. If we have more nodes than - * that, and if we've booted off EFI firmware, then the EFI tables - * passed us from the EFI firmware can list more nodes. Size our - * internal memory map tables to have room for these additional - * nodes, based on up to three entries per node for which the - * kernel was built: MAX_NUMNODES == (1 << CONFIG_NODES_SHIFT), - * plus E820MAX, allowing space for the possible duplicate E820 - * entries that might need room in the same arrays, prior to the - * call to sanitize_e820_map() to remove duplicates. The allowance - * of three memory map entries per node is "enough" entries for - * the initial hardware platform motivating this mechanism to make - * use of additional EFI map entries. Future platforms may want - * to allow more than three entries per node or otherwise refine - * this size. - */ - -#define E820_X_MAX E820MAX - -#define E820NR 0x1e8 /* # entries in E820MAP */ #define E820_RAM 1 #define E820_RESERVED 2 @@ -50,7 +26,7 @@ struct e820map { uint32_t nr_map; - struct e820entry map[E820_X_MAX]; + struct e820entry map[]; }; #define ISA_START_ADDRESS 0xa0000
diff --git a/include/string.h b/include/string.h index 962b07e..9b0b8af 100644 --- a/include/string.h +++ b/include/string.h
@@ -15,4 +15,7 @@ void *memmove(void *dest, const void *src, size_t n); void *memchr(const void *s, int c, size_t n); +void *malloc(int n); +void *malloc_fseg(int n); + #endif
diff --git a/main.c b/main.c index 8b61caf..74c4057 100644 --- a/main.c +++ b/main.c
@@ -1,4 +1,5 @@ #include "bios.h" +#include "stdio.h" #include "e820.h" #include "pci.h" #include "string.h" @@ -83,24 +84,31 @@ { int id = fw_cfg_file_id("etc/e820"); uint32_t size; + int nr_map; + struct e820map *e820; if (id == -1) panic(); size = fw_cfg_file_size(id); - e820.nr_map = size / sizeof(e820.map[0]) + 4; + nr_map = size / sizeof(e820->map[0]) + 4; fw_cfg_file_select(id); - e820.map[0] = (struct e820entry) + + e820 = malloc(offsetof(struct e820map, map[nr_map])); + e820->nr_map = nr_map; + e820->map[0] = (struct e820entry) { .addr = 0, .size = 639 * 1024, .type = E820_RAM }; /* low RAM */ - e820.map[1] = (struct e820entry) + e820->map[1] = (struct e820entry) { .addr = 639 * 1024, .size = 1024, .type = E820_RESERVED }; /* EBDA */ - e820.map[2] = (struct e820entry) + e820->map[2] = (struct e820entry) { .addr = 0xe0000, .size = 64 * 1024, .type = E820_NVS }; /* ACPI tables */ - e820.map[3] = (struct e820entry) + e820->map[3] = (struct e820entry) { .addr = 0xf0000, .size = 64 * 1024, .type = E820_RESERVED }; /* firmware */ - fw_cfg_read(&e820.map[4], size); - e820.map[4].addr = 1024 * 1024; - e820.map[4].size -= 1024 * 1024; + fw_cfg_read(&e820->map[4], size); + e820->map[4].addr = 1024 * 1024; + e820->map[4].size -= 1024 * 1024; + + e820_seg = ((uintptr_t) e820) >> 4; } int main(void)
diff --git a/malloc.c b/malloc.c new file mode 100644 index 0000000..3ab95ed --- /dev/null +++ b/malloc.c
@@ -0,0 +1,21 @@ +#include <inttypes.h> +#include "string.h" + +extern uint8_t edata; +static uint8_t *fseg_base = &edata; + +extern uint8_t stext; +static uint8_t *malloc_top = &stext; + +void *malloc(int n) +{ + malloc_top -= (n + 15) & -16; + return malloc_top; +} + +void *malloc_fseg(int n) +{ + void *p = fseg_base; + fseg_base += (n + 15) & -16; + return p; +}