bootloader/bios_ia32: Allocate physical memory from the kernel separate from the bootloader.
Just start the kernel allocations after the end of the identity map (i.e. the first 8 MB of RAM.) This way, we can avoid putting the bootloader heap and page table memory into the kernel ranges at all, which avoids leaking it.
This commit is contained in:
@@ -73,7 +73,7 @@ segment_descriptor gBootGDT[BOOT_GDT_SEGMENT_COUNT];
|
|||||||
|
|
||||||
static const uint32 kDefaultPageTableFlags = 0x07; // present, user, R/W
|
static const uint32 kDefaultPageTableFlags = 0x07; // present, user, R/W
|
||||||
static const size_t kMaxKernelSize = 0x1000000; // 16 MB for the kernel
|
static const size_t kMaxKernelSize = 0x1000000; // 16 MB for the kernel
|
||||||
static const size_t kIdentityMapEnd = (8 * 1024 * 1024);
|
static const size_t kIdentityMapEnd = 0x0800000; // 8 MB
|
||||||
|
|
||||||
// working page directory and page table
|
// working page directory and page table
|
||||||
static uint32 *sPageDirectory = 0;
|
static uint32 *sPageDirectory = 0;
|
||||||
@@ -81,6 +81,7 @@ static uint32 *sPageDirectory = 0;
|
|||||||
#ifdef _PXE_ENV
|
#ifdef _PXE_ENV
|
||||||
|
|
||||||
static addr_t sNextPhysicalAddress = 0x112000;
|
static addr_t sNextPhysicalAddress = 0x112000;
|
||||||
|
static addr_t sNextPhysicalKernelAddress = kIdentityMapEnd;
|
||||||
static addr_t sNextVirtualAddress = KERNEL_LOAD_BASE + kMaxKernelSize;
|
static addr_t sNextVirtualAddress = KERNEL_LOAD_BASE + kMaxKernelSize;
|
||||||
|
|
||||||
static addr_t sNextPageTableAddress = 0x7d000;
|
static addr_t sNextPageTableAddress = 0x7d000;
|
||||||
@@ -90,6 +91,7 @@ static const uint32 kPageTableRegionEnd = 0x8b000;
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
static addr_t sNextPhysicalAddress = 0x100000;
|
static addr_t sNextPhysicalAddress = 0x100000;
|
||||||
|
static addr_t sNextPhysicalKernelAddress = kIdentityMapEnd;
|
||||||
static addr_t sNextVirtualAddress = KERNEL_LOAD_BASE + kMaxKernelSize;
|
static addr_t sNextVirtualAddress = KERNEL_LOAD_BASE + kMaxKernelSize;
|
||||||
|
|
||||||
static addr_t sNextPageTableAddress = 0x90000;
|
static addr_t sNextPageTableAddress = 0x90000;
|
||||||
@@ -100,7 +102,7 @@ static const uint32 kPageTableRegionEnd = 0x9e000;
|
|||||||
|
|
||||||
|
|
||||||
static addr_t
|
static addr_t
|
||||||
get_next_virtual_address(size_t size)
|
allocate_virtual(size_t size)
|
||||||
{
|
{
|
||||||
addr_t address = sNextVirtualAddress;
|
addr_t address = sNextVirtualAddress;
|
||||||
sNextVirtualAddress += size;
|
sNextVirtualAddress += size;
|
||||||
@@ -110,18 +112,29 @@ get_next_virtual_address(size_t size)
|
|||||||
|
|
||||||
|
|
||||||
static addr_t
|
static addr_t
|
||||||
get_next_physical_address(size_t size)
|
allocate_physical(size_t size, bool forKernel)
|
||||||
{
|
{
|
||||||
uint64 base;
|
uint64 base;
|
||||||
|
if (!forKernel) {
|
||||||
|
base = sNextPhysicalAddress;
|
||||||
|
if ((base + size) > kIdentityMapEnd) {
|
||||||
|
panic("Out of identity-map physical memory!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sNextPhysicalAddress += size;
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
if (!get_free_address_range(gKernelArgs.physical_allocated_range,
|
if (!get_free_address_range(gKernelArgs.physical_allocated_range,
|
||||||
gKernelArgs.num_physical_allocated_ranges, sNextPhysicalAddress,
|
gKernelArgs.num_physical_allocated_ranges, sNextPhysicalKernelAddress,
|
||||||
size, &base)) {
|
size, &base)) {
|
||||||
panic("Out of physical memory!");
|
panic("Out of physical memory!");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
insert_physical_allocated_range(base, size);
|
insert_physical_allocated_range(base, size);
|
||||||
sNextPhysicalAddress = base + size;
|
sNextPhysicalKernelAddress = base + size;
|
||||||
// TODO: Can overflow theoretically.
|
// TODO: Can overflow theoretically.
|
||||||
|
|
||||||
return base;
|
return base;
|
||||||
@@ -131,14 +144,14 @@ get_next_physical_address(size_t size)
|
|||||||
static addr_t
|
static addr_t
|
||||||
get_next_virtual_page()
|
get_next_virtual_page()
|
||||||
{
|
{
|
||||||
return get_next_virtual_address(B_PAGE_SIZE);
|
return allocate_virtual(B_PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static addr_t
|
static addr_t
|
||||||
get_next_physical_page()
|
get_next_physical_page()
|
||||||
{
|
{
|
||||||
return get_next_physical_address(B_PAGE_SIZE);
|
return allocate_physical(B_PAGE_SIZE, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -151,7 +164,7 @@ get_next_page_table()
|
|||||||
|
|
||||||
addr_t address = sNextPageTableAddress;
|
addr_t address = sNextPageTableAddress;
|
||||||
if (address >= kPageTableRegionEnd)
|
if (address >= kPageTableRegionEnd)
|
||||||
return (uint32 *)get_next_physical_page();
|
return (uint32 *)allocate_physical(B_PAGE_SIZE, false);
|
||||||
|
|
||||||
sNextPageTableAddress += B_PAGE_SIZE;
|
sNextPageTableAddress += B_PAGE_SIZE;
|
||||||
return (uint32 *)address;
|
return (uint32 *)address;
|
||||||
@@ -321,7 +334,7 @@ init_page_directory(void)
|
|||||||
TRACE("init_page_directory\n");
|
TRACE("init_page_directory\n");
|
||||||
|
|
||||||
// allocate a new pgdir
|
// allocate a new pgdir
|
||||||
sPageDirectory = (uint32 *)get_next_physical_page();
|
sPageDirectory = (uint32 *)allocate_physical(B_PAGE_SIZE, false);
|
||||||
gKernelArgs.arch_args.phys_pgdir = (uint32)sPageDirectory;
|
gKernelArgs.arch_args.phys_pgdir = (uint32)sPageDirectory;
|
||||||
|
|
||||||
// clear out the pgdir
|
// clear out the pgdir
|
||||||
@@ -630,7 +643,7 @@ mmu_init(void)
|
|||||||
|
|
||||||
gKernelArgs.arch_args.virtual_end = KERNEL_LOAD_BASE;
|
gKernelArgs.arch_args.virtual_end = KERNEL_LOAD_BASE;
|
||||||
|
|
||||||
gKernelArgs.physical_allocated_range[0].start = sNextPhysicalAddress;
|
gKernelArgs.physical_allocated_range[0].start = sNextPhysicalKernelAddress;
|
||||||
gKernelArgs.physical_allocated_range[0].size = 0;
|
gKernelArgs.physical_allocated_range[0].size = 0;
|
||||||
gKernelArgs.num_physical_allocated_ranges = 1;
|
gKernelArgs.num_physical_allocated_ranges = 1;
|
||||||
// remember the start of the allocated physical pages
|
// remember the start of the allocated physical pages
|
||||||
@@ -813,13 +826,10 @@ platform_free_region(void *address, size_t size)
|
|||||||
ssize_t
|
ssize_t
|
||||||
platform_allocate_heap_region(size_t size, void **_base)
|
platform_allocate_heap_region(size_t size, void **_base)
|
||||||
{
|
{
|
||||||
addr_t base = get_next_physical_address(size);
|
addr_t base = allocate_physical(size, false);
|
||||||
if (base == 0)
|
if (base == 0)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
if ((base + size) > kIdentityMapEnd)
|
|
||||||
panic("platform_allocate_heap_region: region end is beyond identity map");
|
|
||||||
|
|
||||||
*_base = (void*)base;
|
*_base = (void*)base;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@@ -829,7 +839,6 @@ void
|
|||||||
platform_free_heap_region(void *_base, size_t size)
|
platform_free_heap_region(void *_base, size_t size)
|
||||||
{
|
{
|
||||||
addr_t base = (addr_t)_base;
|
addr_t base = (addr_t)_base;
|
||||||
remove_physical_allocated_range(base, size);
|
|
||||||
if (sNextPhysicalAddress == (base + size))
|
if (sNextPhysicalAddress == (base + size))
|
||||||
sNextPhysicalAddress -= size;
|
sNextPhysicalAddress -= size;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user