diff options
-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); |