memtest86plus/system/vmem.h
martinwhitaker 93c9c8ded5
Rework memory mapping to allow for larger program size (#54)
* Improve abstraction in vmem.h and limit memory benchmarking to first 2GB.

The third GB may get used for remapping memory regions that are only
accessed during startup, so it's not safe to use it for the memory
speed tests.

* Fix calculation of end limit for locating memory benchmark workspace.

* Document vmem.h.

* Use window number, not current start address, to detect first window.

* Increase the program low-load range from 1MB to 4MB and make more robust.

If the BIOS has reserved some parts of low memory, there may not be
enough contiguous space left to load the program there (issue #49).
So increase the low-load range to include the first 3MB of high
memory. Also guard against the program being initially loaded
straddling the new boundary.

Co-authored-by: Martin Whitaker <memtest@martin-whitaker.me.uk>
2022-04-28 23:04:01 +02:00

104 lines
3.3 KiB
C

// SPDX-License-Identifier: GPL-2.0
#ifndef VMEM_H
#define VMEM_H
/**
* \file
*
* Provides functions to handle physical memory page mapping into virtual
* memory.
*
* The startup code sets up the paging tables to give us a 4GB virtual address
* space, initially identity mapped to the first 4GB of physical memory. We
* leave the lower 2GB permanently mapped, and use the upper 2GB for mapping
* the remaining physical memory as required.
*
*//*
* Copyright (C) 2020-2022 Martin Whitaker.
*/
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "memsize.h"
/**
* The size of the physical memory region (in pages) that is permanently mapped
* into virtual memory, starting at virtual address 0.
*/
#define VM_PINNED_SIZE PAGE_C(2,GB)
/**
* The size of a physical memory region (in pages) that can be mapped into
* virtual memory by a call to map_window().
*/
#define VM_WINDOW_SIZE PAGE_C(1,GB)
/**
* Maps a physical memory region into the upper 2GB of virtual memory. The
* virtual address will have the same alignment within a page as the physical
* address.
*
* \param base_addr - the physical byte address of the region.
* \param size - the region size in bytes.
* \param only_for_startup - if true, the region will remain mapped until the
* first call to map_window(), otherwise it will be
* permanently mapped.
*
* \returns
* On success, the mapped address in virtual memory, On failure, 0.
*/
uintptr_t map_region(uintptr_t base_addr, size_t size, bool only_for_startup);
/**
* Maps a \ref VM_WINDOW_SIZE region of physical memory into the upper 2GB of
* virtual memory. The physical memory region must be aligned on a \ref
* VM_WINDOW_SIZE boundary. The virtual address will be similarly aligned.
* The region will remain mapped until the next call to map_window().
*
* \param start_page - the physical page number of the region.
*
* \returns
* On success, true. On failure, false.
*/
bool map_window(uintptr_t start_page);
/**
* Returns a virtual memory pointer to the first word of the specified physical
* memory page. Physical memory pages above \ref VM_PINNED_SIZE must have been
* mapped by a call to map_window() prior to calling this function.
*
* \param page - the physical page number.
*
* \returns
* A pointer to the first word of the page.
*/
void *first_word_mapping(uintptr_t page);
/**
* Returns a virtual memory pointer to the last word of the specified physical
* memory page. Physical memory pages above \ref VM_PINNED_SIZE must have been
* mapped by a call to map_window() prior to calling this function.
*
* \param page - the physical page number.
* \param word_size - the size of a word in bytes.
*
* \returns
* A pointer to the last word of the page.
*/
void *last_word_mapping(uintptr_t page, size_t word_size);
/**
* Returns the page number of the physical memory page containing the specified
* virtual memory address. The specified address must either be permanently
* mapped or mapped by a call to map_window() prior to calling this function.
*
* \param addr - the virtual memory address.
*
* \returns
* The corresponding physical page number.
*/
uintptr_t page_of(void *addr);
#endif // VMEM_H