Don't use the top 0.5GB of the 32-bit address space for device mapping.

This region is commonly used by the BIOS for mapping hardware devices,
so we can avoid a lot of remapping if we don't use it.
This commit is contained in:
Martin Whitaker 2022-02-21 13:12:06 +00:00
parent 6b570cd779
commit e4ad2dfa1b
1 changed files with 25 additions and 4 deletions

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2020-2021 Martin Whitaker.
// Copyright (C) 2020-2022 Martin Whitaker.
//
// Derived from memtest86+ vmem.c
//
@ -19,6 +19,23 @@
#include "vmem.h"
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
// The startup code sets up the paging tables to give us 4GB of virtual address
// space, using 2MB pages, initially identity mapped to the first 4GB of physical
// memory. We use the third GB to map the physical memory window we are currently
// testing, and the following 512MB to map the screen frame buffer and any hardware
// devices we need to access that are not in the permanently mapped regions.
#define MAX_DEVICE_PAGES 256 // VM pages
#define VM_WINDOW_START SIZE_C(2,GB)
#define VM_DEVICE_START (VM_WINDOW_START + SIZE_C(1,GB))
#define VM_DEVICE_END (VM_DEVICE_START + MAX_DEVICE_PAGES * VM_PAGE_SIZE - 1)
#define VM_SPACE_END 0xffffffff
//------------------------------------------------------------------------------
// Private Variables
//------------------------------------------------------------------------------
@ -58,18 +75,22 @@ static void load_pdbr()
uintptr_t map_device(uintptr_t base_addr, size_t size)
{
uintptr_t last_addr = base_addr + size - 1;
if (last_addr < VM_WINDOW_START || (base_addr > VM_DEVICE_END && last_addr <= VM_SPACE_END)) {
return base_addr;
}
uintptr_t first_virt_page = device_pages_used;
uintptr_t first_phys_page = base_addr >> VM_PAGE_SHIFT;
uintptr_t last_phys_page = (base_addr + size - 1) >> VM_PAGE_SHIFT;
uintptr_t last_phys_page = last_addr >> VM_PAGE_SHIFT;
// Compute the page table entries.
for (uintptr_t page = first_phys_page; page <= last_phys_page; page++) {
if (device_pages_used == 512) return 0;
if (device_pages_used == MAX_DEVICE_PAGES) return 0;
pd3[device_pages_used++] = (page << VM_PAGE_SHIFT) + 0x83;
}
// Reload the PDBR to flush any remnants of the old mapping.
load_pdbr();
// Return the mapped address.
return ADDR_C(3,GB) + first_virt_page * VM_PAGE_SIZE + base_addr % VM_PAGE_SIZE;
return VM_DEVICE_START + first_virt_page * VM_PAGE_SIZE + base_addr % VM_PAGE_SIZE;
}
bool map_window(uintptr_t start_page)