diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2009-08-01 11:45:37 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2009-08-01 11:45:37 -0400 |
commit | 0bf9270aa47777992914096d476c4aef99e30865 (patch) | |
tree | f2318aba7b724632088310ad3beb14a1ca450053 | |
parent | 69656657953bf9a65ef55a20c1626023ffefb41d (diff) | |
download | seabios-0bf9270aa47777992914096d476c4aef99e30865.tar.gz |
Add Post Memory Manager (PMM) support.
Complete the initial implementation of PMM.
Default new PMM code to be enabled.
Move malloc code from memmap.c to pmm.c.
Define new malloc zones for PMM (ZoneTmpLow and ZoneTmpHigh).
Change default READ/WRITE_SEG macros to use 32bit pointers (the 16bit
PMM code use "big real" mode and requires 32bit accesses).
Allow pmm allocations to occur during bcv executions also.
Add low-memory clearing before boot.
Also, align the default f-seg memory.
-rw-r--r-- | src/acpi.c | 1 | ||||
-rw-r--r-- | src/biosvar.h | 4 | ||||
-rw-r--r-- | src/config.h | 2 | ||||
-rw-r--r-- | src/coreboot.c | 1 | ||||
-rw-r--r-- | src/farptr.h | 17 | ||||
-rw-r--r-- | src/memmap.c | 90 | ||||
-rw-r--r-- | src/memmap.h | 5 | ||||
-rw-r--r-- | src/misc.c | 2 | ||||
-rw-r--r-- | src/mptable.c | 1 | ||||
-rw-r--r-- | src/pmm.c | 333 | ||||
-rw-r--r-- | src/post.c | 8 | ||||
-rw-r--r-- | src/smbios.c | 1 | ||||
-rw-r--r-- | src/types.h | 8 | ||||
-rw-r--r-- | src/util.h | 14 |
14 files changed, 359 insertions, 128 deletions
@@ -7,7 +7,6 @@ #include "acpi.h" // struct rsdp_descriptor #include "util.h" // memcpy -#include "memmap.h" // malloc_fseg #include "pci.h" // pci_find_device #include "biosvar.h" // GET_EBDA #include "pci_ids.h" // PCI_VENDOR_ID_INTEL diff --git a/src/biosvar.h b/src/biosvar.h index 821aa357..0d175efd 100644 --- a/src/biosvar.h +++ b/src/biosvar.h @@ -1,6 +1,6 @@ // Variable layouts of bios. // -// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net> +// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net> // // This file may be distributed under the terms of the GNU LGPLv3 license. #ifndef __BIOSVAR_H @@ -240,6 +240,8 @@ struct extended_bios_data_area_s { DIV_ROUND_UP(sizeof(struct extended_bios_data_area_s), 1024) #define EBDA_SEGMENT_START \ FLATPTR_TO_SEG((640 - EBDA_SIZE_START) * 1024) +#define EBDA_SEGMENT_MINIMUM \ + FLATPTR_TO_SEG((640 - 256) * 1024) // Accessor functions static inline u16 get_ebda_seg() { diff --git a/src/config.h b/src/config.h index 36f2a728..20e74c76 100644 --- a/src/config.h +++ b/src/config.h @@ -40,7 +40,7 @@ // Support PnP BIOS entry point. #define CONFIG_PNPBIOS 1 // Support Post Memory Manager (PMM) entry point. -#define CONFIG_PMM 0 +#define CONFIG_PMM 1 // Support int 19/18 system bootup support #define CONFIG_BOOT 1 // Support an interactive boot menu at end of post. diff --git a/src/coreboot.c b/src/coreboot.c index 4ab2a7a8..82c9f8a5 100644 --- a/src/coreboot.c +++ b/src/coreboot.c @@ -11,7 +11,6 @@ #include "mptable.h" // MPTABLE_SIGNATURE #include "biosvar.h" // GET_EBDA #include "lzmadecode.h" // LzmaDecode -#include "memmap.h" // malloc_fseg /**************************************************************** diff --git a/src/farptr.h b/src/farptr.h index a270f87a..1f3df9d2 100644 --- a/src/farptr.h +++ b/src/farptr.h @@ -1,6 +1,6 @@ // Code to access multiple segments within gcc. // -// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net> +// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net> // // This file may be distributed under the terms of the GNU LGPLv3 license. #ifndef __FARPTR_H @@ -15,13 +15,13 @@ extern u16 __segment_FS, __segment_GS; // Low level macros for reading/writing memory via a segment selector. #define READ8_SEG(SEG, value, var) \ - __asm__("movb %%" #SEG ":%1, %b0" : "=Qi"(value) \ + __asm__("addr32 movb %%" #SEG ":%1, %b0" : "=Qi"(value) \ : "m"(var), "m"(__segment_ ## SEG)) #define READ16_SEG(SEG, value, var) \ - __asm__("movw %%" #SEG ":%1, %w0" : "=ri"(value) \ + __asm__("addr32 movw %%" #SEG ":%1, %w0" : "=ri"(value) \ : "m"(var), "m"(__segment_ ## SEG)) #define READ32_SEG(SEG, value, var) \ - __asm__("movl %%" #SEG ":%1, %0" : "=ri"(value) \ + __asm__("addr32 movl %%" #SEG ":%1, %0" : "=ri"(value) \ : "m"(var), "m"(__segment_ ## SEG)) #define READ64_SEG(SEG, value, var) do { \ union u64_u32_u __value; \ @@ -31,18 +31,19 @@ extern u16 __segment_FS, __segment_GS; *(u64*)&(value) = __value.val; \ } while (0) #define WRITE8_SEG(SEG, var, value) \ - __asm__("movb %b1, %%" #SEG ":%0" : "=m"(var) \ + __asm__("addr32 movb %b1, %%" #SEG ":%0" : "=m"(var) \ : "Q"(value), "m"(__segment_ ## SEG)) #define WRITE16_SEG(SEG, var, value) \ - __asm__("movw %w1, %%" #SEG ":%0" : "=m"(var) \ + __asm__("addr32 movw %w1, %%" #SEG ":%0" : "=m"(var) \ : "r"(value), "m"(__segment_ ## SEG)) #define WRITE32_SEG(SEG, var, value) \ - __asm__("movl %1, %%" #SEG ":%0" : "=m"(var) \ + __asm__("addr32 movl %1, %%" #SEG ":%0" : "=m"(var) \ : "r"(value), "m"(__segment_ ## SEG)) #define WRITE64_SEG(SEG, var, value) do { \ union u64_u32_u __value; \ union u64_u32_u *__w64_ptr = (union u64_u32_u *)&(var); \ - __value.val = (value); \ + typeof(var) __value_tmp = (value); \ + __value.val = *(u64*)&__value_tmp; \ WRITE32_SEG(SEG, __w64_ptr->hi, __value.hi); \ WRITE32_SEG(SEG, __w64_ptr->lo, __value.lo); \ } while (0) diff --git a/src/memmap.c b/src/memmap.c index 9fc3626f..005c474c 100644 --- a/src/memmap.c +++ b/src/memmap.c @@ -132,93 +132,3 @@ memmap_finalize() { dump_map(); } - - -/**************************************************************** - * malloc - ****************************************************************/ - -#define MINALIGN 16 - -struct zone_s { - u32 top, bottom, cur; -}; - -static struct zone_s ZoneHigh, ZoneFSeg; - -static void * -__malloc(struct zone_s *zone, u32 size) -{ - u32 newpos = (zone->cur - size) / MINALIGN * MINALIGN; - if ((s32)(newpos - zone->bottom) < 0) - // No space - return NULL; - zone->cur = newpos; - return (void*)newpos; -} - -// Allocate memory at the top of 32bit ram. -void * -malloc_high(u32 size) -{ - return __malloc(&ZoneHigh, size); -} - -// Allocate memory in the 0xf0000-0x100000 area of ram. -void * -malloc_fseg(u32 size) -{ - return __malloc(&ZoneFSeg, size); -} - -void -malloc_setup() -{ - dprintf(3, "malloc setup\n"); - - // Memory in 0xf0000 area. - memset(BiosTableSpace, 0, CONFIG_MAX_BIOSTABLE); - ZoneFSeg.bottom = (u32)BiosTableSpace; - ZoneFSeg.top = ZoneFSeg.cur = ZoneFSeg.bottom + CONFIG_MAX_BIOSTABLE; - - // Find memory at the top of ram. - u32 top = 0; - int i; - for (i=e820_count-1; i>=0; i--) { - struct e820entry *e = &e820_list[i]; - u64 end = e->start + e->size; - if (e->type != E820_RAM || end > 0xffffffff - || e->size < CONFIG_MAX_HIGHTABLE) - continue; - top = end; - break; - } - if (top < 1024*1024 + CONFIG_MAX_HIGHTABLE) { - // No memory above 1Meg - memset(&ZoneHigh, 0, sizeof(ZoneHigh)); - return; - } - ZoneHigh.bottom = top - CONFIG_MAX_HIGHTABLE; - ZoneHigh.top = ZoneHigh.cur = ZoneHigh.bottom + CONFIG_MAX_HIGHTABLE; - add_e820(ZoneHigh.bottom, CONFIG_MAX_HIGHTABLE, E820_RESERVED); -} - -void -malloc_finalize() -{ - dprintf(3, "malloc finalize\n"); - - // Give back unused high ram. - u32 giveback = (ZoneHigh.cur - ZoneHigh.bottom) / 4096 * 4096; - add_e820(ZoneHigh.bottom, giveback, E820_RAM); - - // Report statistics - u32 used = ZoneFSeg.top - ZoneFSeg.cur; - u32 avail = ZoneFSeg.top - ZoneFSeg.bottom; - dprintf(1, "malloc_fseg used=%d (%d%%)\n" - , used, (100 * used) / avail); - used = ZoneHigh.top - ZoneHigh.cur; - avail = ZoneHigh.top - ZoneHigh.bottom; - dprintf(1, "malloc_high used=%d (%d%%) (returned %d)\n" - , used, (100 * used) / avail, giveback); -} diff --git a/src/memmap.h b/src/memmap.h index 8df9ed09..51471d69 100644 --- a/src/memmap.h +++ b/src/memmap.h @@ -20,11 +20,6 @@ void add_e820(u64 start, u64 size, u32 type); void memmap_setup(); void memmap_finalize(); -void *malloc_high(u32 size); -void *malloc_fseg(u32 size); -void malloc_setup(); -void malloc_finalize(); - // e820 map storage (defined in system.c) extern struct e820entry e820_list[]; extern int e820_count; @@ -15,7 +15,7 @@ u32 RamSize VAR16_32; // Amount of continuous ram >4Gig u64 RamSizeOver4G; // Space for bios tables built an run-time. -char BiosTableSpace[CONFIG_MAX_BIOSTABLE] VAR16_32; +char BiosTableSpace[CONFIG_MAX_BIOSTABLE] __aligned(MALLOC_MIN_ALIGN) VAR16_32; /**************************************************************** diff --git a/src/mptable.c b/src/mptable.c index 8f622fff..aeb1f94e 100644 --- a/src/mptable.c +++ b/src/mptable.c @@ -6,7 +6,6 @@ // This file may be distributed under the terms of the GNU LGPLv3 license. #include "util.h" // dprintf -#include "memmap.h" // malloc_fseg #include "config.h" // CONFIG_* #include "mptable.h" // MPTABLE_SIGNATURE @@ -6,6 +6,270 @@ #include "util.h" // checksum #include "config.h" // BUILD_BIOS_ADDR +#include "memmap.h" // e820_list +#include "farptr.h" // GET_FARVAR +#include "biosvar.h" // EBDA_SEGMENT_MINIMUM + + +/**************************************************************** + * malloc + ****************************************************************/ + +#if MODE16 +// The 16bit pmm entry points runs in "big real" mode, and can +// therefore read/write to the 32bit malloc variables. +#define GET_PMMVAR(var) GET_FARVAR(0, (var)) +#define SET_PMMVAR(var, val) SET_FARVAR(0, (var), (val)) +#else +#define GET_PMMVAR(var) (var) +#define SET_PMMVAR(var, val) do { (var) = (val); } while (0) +#endif + +// Zone definitions +struct zone_s { + u32 top, bottom, cur; +}; + +struct zone_s ZoneHigh VAR32VISIBLE, ZoneFSeg VAR32VISIBLE; +struct zone_s ZoneTmpLow VAR32VISIBLE, ZoneTmpHigh VAR32VISIBLE; + +struct zone_s *Zones[] VAR32VISIBLE = { + &ZoneTmpLow, &ZoneFSeg, &ZoneTmpHigh, &ZoneHigh +}; + +// Obtain memory from a given zone. +static void * +zone_malloc(struct zone_s *zone, u32 size, u32 align) +{ + u32 newpos = (GET_PMMVAR(zone->cur) - size) / align * align; + if ((s32)(newpos - GET_PMMVAR(zone->bottom)) < 0) + // No space + return NULL; + SET_PMMVAR(zone->cur, newpos); + return (void*)newpos; +} + +// Return memory to a zone (if it was the last to be allocated). +static void +zone_free(struct zone_s *zone, void *data, u32 olddata) +{ + if (! data || GET_PMMVAR(zone->cur) != (u32)data) + return; + SET_PMMVAR(zone->cur, olddata); +} + +// Find the zone that contains the given data block. +static struct zone_s * +zone_find(void *data) +{ + int i; + for (i=0; i<ARRAY_SIZE(Zones); i++) { + struct zone_s *zone = GET_PMMVAR(Zones[i]); + if ((u32)data >= GET_PMMVAR(zone->cur) + && (u32)data < GET_PMMVAR(zone->top)) + return zone; + } + return NULL; +} + +// Report the status of all the zones. +static void +dumpZones() +{ + int i; + for (i=0; i<ARRAY_SIZE(Zones); i++) { + struct zone_s *zone = Zones[i]; + u32 used = zone->top - zone->cur; + u32 avail = zone->top - zone->bottom; + dprintf(2, "zone %d: %08x-%08x used=%d (%d%%)\n" + , i, zone->bottom, zone->top, used, (100 * used) / avail); + } +} + +// Allocate memory at the top of 32bit ram. +void * +malloc_high(u32 size) +{ + return zone_malloc(&ZoneHigh, size, MALLOC_MIN_ALIGN); +} + +// Allocate memory in the 0xf0000-0x100000 area of ram. +void * +malloc_fseg(u32 size) +{ + return zone_malloc(&ZoneFSeg, size, MALLOC_MIN_ALIGN); +} + +void +malloc_setup() +{ + ASSERT32(); + dprintf(3, "malloc setup\n"); + + // Memory in 0xf0000 area. + memset(BiosTableSpace, 0, CONFIG_MAX_BIOSTABLE); + ZoneFSeg.bottom = (u32)BiosTableSpace; + ZoneFSeg.top = ZoneFSeg.cur = ZoneFSeg.bottom + CONFIG_MAX_BIOSTABLE; + + // Memory under 1Meg. + ZoneTmpLow.bottom = BUILD_STACK_ADDR; + ZoneTmpLow.top = ZoneTmpLow.cur = (u32)MAKE_FLATPTR(EBDA_SEGMENT_MINIMUM, 0); + + // Find memory at the top of ram. + u32 top = 0, bottom = 0; + int i; + for (i=e820_count-1; i>=0; i--) { + struct e820entry *e = &e820_list[i]; + u64 end = e->start + e->size; + if (e->type != E820_RAM || end > 0xffffffff + || e->size < CONFIG_MAX_HIGHTABLE) + continue; + top = end; + bottom = e->start; + break; + } + if (top < 1024*1024 + CONFIG_MAX_HIGHTABLE) { + // No memory above 1Meg + memset(&ZoneHigh, 0, sizeof(ZoneHigh)); + return; + } + + // Memory at top of ram. + ZoneHigh.bottom = top - CONFIG_MAX_HIGHTABLE; + ZoneHigh.top = ZoneHigh.cur = ZoneHigh.bottom + CONFIG_MAX_HIGHTABLE; + add_e820(ZoneHigh.bottom, CONFIG_MAX_HIGHTABLE, E820_RESERVED); + + // Memory above 1Meg + ZoneTmpHigh.bottom = bottom; + ZoneTmpHigh.top = ZoneTmpHigh.cur = ZoneHigh.bottom; +} + +void +malloc_finalize() +{ + dprintf(3, "malloc finalize\n"); + + dumpZones(); + + // Give back unused high ram. + u32 giveback = (ZoneHigh.cur - ZoneHigh.bottom) / 4096 * 4096; + add_e820(ZoneHigh.bottom, giveback, E820_RAM); + dprintf(1, "Returned %d bytes of ZoneHigh\n", giveback); + + // Clear low-memory allocations. + memset((void*)ZoneTmpLow.bottom, 0, ZoneTmpLow.top - ZoneTmpLow.bottom); +} + + +/**************************************************************** + * pmm allocation + ****************************************************************/ + +// Information on PMM tracked allocations +struct pmmalloc_s { + void *data; + u32 olddata; + u32 handle; + struct pmmalloc_s *next; +}; + +struct pmmalloc_s *PMMAllocs VAR32VISIBLE; + +#define PMMALLOCSIZE ALIGN(sizeof(struct pmmalloc_s), MALLOC_MIN_ALIGN) + +// Allocate memory from the given zone and track it as a PMM allocation +static void * +pmm_malloc(struct zone_s *zone, u32 handle, u32 size, u32 align) +{ + struct pmmalloc_s *info = zone_malloc(&ZoneTmpHigh, sizeof(*info) + , MALLOC_MIN_ALIGN); + if (!info) + return NULL; + u32 olddata = GET_PMMVAR(zone->cur); + void *data = zone_malloc(zone, size, align); + if (! data) { + zone_free(&ZoneTmpHigh, info, (u32)info + PMMALLOCSIZE); + return NULL; + } + dprintf(8, "pmm_malloc zone=%p handle=%x size=%d align=%x" + " ret=%p (info=%p)\n" + , zone, handle, size, align + , data, info); + SET_PMMVAR(info->data, data); + SET_PMMVAR(info->olddata, olddata); + SET_PMMVAR(info->handle, handle); + SET_PMMVAR(info->next, GET_PMMVAR(PMMAllocs)); + SET_PMMVAR(PMMAllocs, info); + return data; +} + +// Free a raw data block (either from a zone or from pmm alloc list). +static void +pmm_free_data(struct zone_s *zone, void *data, u32 olddata) +{ + if (GET_PMMVAR(zone->cur) == (u32)data) { + zone_free(zone, data, olddata); + return; + } + struct pmmalloc_s *info; + for (info=GET_PMMVAR(PMMAllocs); info; info = GET_PMMVAR(info->next)) + if (GET_PMMVAR(info->olddata) == (u32)data) { + SET_PMMVAR(info->olddata, olddata); + return; + } +} + +// Free a data block allocated with pmm_malloc +static int +pmm_free(void *data) +{ + struct zone_s *zone = zone_find(GET_PMMVAR(data)); + if (!zone) + return -1; + struct pmmalloc_s **pinfo = &PMMAllocs; + for (;;) { + struct pmmalloc_s *info = GET_PMMVAR(*pinfo); + if (!info) + return -1; + if (GET_PMMVAR(info->data) == data) { + SET_PMMVAR(*pinfo, GET_PMMVAR(info->next)); + u32 olddata = GET_PMMVAR(info->olddata); + pmm_free_data(zone, data, olddata); + pmm_free_data(&ZoneTmpHigh, info, (u32)info + PMMALLOCSIZE); + dprintf(8, "pmm_free data=%p zone=%p olddata=%p info=%p\n" + , data, zone, (void*)olddata, info); + return 0; + } + pinfo = &info->next; + } + return -1; +} + +// Find the amount of free space in a given zone. +static u32 +pmm_getspace(struct zone_s *zone) +{ + u32 space = GET_PMMVAR(zone->cur) - GET_PMMVAR(zone->bottom); + if (space <= PMMALLOCSIZE) + return 0; + return space - PMMALLOCSIZE; +} + +// Find the data block allocated with pmm_malloc with a given handle. +static void * +pmm_find(u32 handle) +{ + struct pmmalloc_s *info; + for (info=GET_PMMVAR(PMMAllocs); info; info = GET_PMMVAR(info->next)) + if (GET_PMMVAR(info->handle) == handle) + return GET_PMMVAR(info->data); + return NULL; +} + + +/**************************************************************** + * pmm interface + ****************************************************************/ struct pmmheader { u32 signature; @@ -29,7 +293,7 @@ struct pmmheader PMMHEADER __aligned(16) VAR16EXPORT = { }; #endif -#define FUNCTION_NOT_SUPPORTED 0xffffffff +#define PMM_FUNCTION_NOT_SUPPORTED 0xffffffff // PMM - allocate static u32 @@ -37,10 +301,51 @@ handle_pmm00(u16 *args) { u32 length = *(u32*)&args[1], handle = *(u32*)&args[3]; u16 flags = args[5]; - dprintf(1, "pmm00: length=%x handle=%x flags=%x\n" + dprintf(3, "pmm00: length=%x handle=%x flags=%x\n" , length, handle, flags); - // XXX - return 0; + if (!length) { + // Memory size request + switch (flags & 3) { + default: + case 0: + return 0; + case 1: + return pmm_getspace(&ZoneTmpLow); + case 2: + return pmm_getspace(&ZoneTmpHigh); + case 3: { + u32 spacelow = pmm_getspace(&ZoneTmpLow); + u32 spacehigh = pmm_getspace(&ZoneTmpHigh); + if (spacelow > spacehigh) + return spacelow; + return spacehigh; + } + } + } + u32 size = length * 16; + if ((s32)size <= 0) + return 0; + u32 align = MALLOC_MIN_ALIGN; + if (flags & 4) { + align = 1<<__ffs(size); + if (align < MALLOC_MIN_ALIGN) + align = MALLOC_MIN_ALIGN; + } + switch (flags & 3) { + default: + case 0: + return 0; + case 1: + return (u32)pmm_malloc(&ZoneTmpLow, handle, size, align); + case 2: + return (u32)pmm_malloc(&ZoneTmpHigh, handle, size, align); + case 3: { + void *data = pmm_malloc(&ZoneTmpLow, handle, size, align); + if (data) + return (u32)data; + return (u32)pmm_malloc(&ZoneTmpHigh, handle, size, align); + } + } } // PMM - find @@ -48,9 +353,10 @@ static u32 handle_pmm01(u16 *args) { u32 handle = *(u32*)&args[1]; - dprintf(1, "pmm01: handle=%x\n", handle); - // XXX - return 0; + dprintf(3, "pmm01: handle=%x\n", handle); + if (handle == 0xFFFFFFFF) + return 0; + return (u32)pmm_find(handle); } // PMM - deallocate @@ -58,22 +364,25 @@ static u32 handle_pmm02(u16 *args) { u32 buffer = *(u32*)&args[1]; - dprintf(1, "pmm02: buffer=%x\n", buffer); - // XXX + dprintf(3, "pmm02: buffer=%x\n", buffer); + int ret = pmm_free((void*)buffer); + if (ret) + // Error + return 1; return 0; } static u32 handle_pmmXX(u16 *args) { - return FUNCTION_NOT_SUPPORTED; + return PMM_FUNCTION_NOT_SUPPORTED; } u32 VISIBLE16 handle_pmm(u16 *args) { if (! CONFIG_PMM) - return FUNCTION_NOT_SUPPORTED; + return PMM_FUNCTION_NOT_SUPPORTED; u16 arg1 = args[0]; dprintf(DEBUG_HDL_pmm, "pmm call arg1=%x\n", arg1); @@ -112,6 +421,4 @@ pmm_finalize() PMMHEADER.signature = 0; PMMHEADER.entry_offset = 0; - - // XXX - zero low-memory allocations. } @@ -190,6 +190,9 @@ post() optionrom_setup(); + // Run BCVs + boot_prep(); + pmm_finalize(); malloc_finalize(); memmap_finalize(); @@ -210,13 +213,10 @@ _start() // Perform main setup code. post(); - // Run BCVs - boot_prep(); - // Setup bios checksum. BiosChecksum -= checksum((u8*)BUILD_BIOS_ADDR, BUILD_BIOS_SIZE); - // Prep for boot process. + // Write protect bios memory. make_bios_readonly(); // Invoke int 19 to start boot process. diff --git a/src/smbios.c b/src/smbios.c index fb036711..6fbddd98 100644 --- a/src/smbios.c +++ b/src/smbios.c @@ -6,7 +6,6 @@ // This file may be distributed under the terms of the GNU LGPLv3 license. #include "util.h" // dprintf -#include "memmap.h" // malloc_fseg #include "biosvar.h" // GET_EBDA diff --git a/src/types.h b/src/types.h index 9f93e0b2..bbb38bbb 100644 --- a/src/types.h +++ b/src/types.h @@ -1,6 +1,6 @@ // Basic type definitions for X86 cpus. // -// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net> +// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net> // // This file may be distributed under the terms of the GNU LGPLv3 license. #ifndef __TYPES_H @@ -48,6 +48,8 @@ union u64_u32_u { # define VAR16EXPORT __section(".data16.export." UNIQSEC) __VISIBLE // Designate a variable at a specific 16bit address # define VAR16FIXED(addr) __aligned(1) __VISIBLE __section(".fixedaddr." __stringify(addr)) +// Designate a 32bit variable also available in 16bit "big real" mode. +# define VAR32VISIBLE __section(".discard.var32." UNIQSEC) __VISIBLE __weak // Designate top-level assembler as 16bit only. # define ASM16(code) __ASM(code) // Designate top-level assembler as 32bit only. @@ -59,6 +61,7 @@ union u64_u32_u { # define VAR16_32 VAR16 __VISIBLE __weak # define VAR16EXPORT VAR16_32 # define VAR16FIXED(addr) VAR16_32 +# define VAR32VISIBLE __VISIBLE # define ASM16(code) # define ASM32(code) __ASM(code) #endif @@ -69,6 +72,9 @@ union u64_u32_u { #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) #define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1) #define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) #define NULL ((void *)0) @@ -80,6 +80,14 @@ static inline u64 rdtscll(void) return val; } +static inline u32 __ffs(u32 word) +{ + asm("bsf %1,%0" + : "=r" (word) + : "rm" (word)); + return word; +} + #define call16_simpint(nr, peax, pflags) do { \ ASSERT16(); \ asm volatile( \ @@ -232,8 +240,14 @@ u16 get_pnp_offset(); void pnp_setup(); // pmm.c +void *malloc_high(u32 size); +void *malloc_fseg(u32 size); +void malloc_setup(); +void malloc_finalize(); void pmm_setup(); void pmm_finalize(); +// Minimum alignment of malloc'd memory +#define MALLOC_MIN_ALIGN 16 // mtrr.c void mtrr_setup(void); |