mirror of
https://github.com/memtest86plus/memtest86plus.git
synced 2024-11-27 01:50:20 -06:00
Switch to an array of heaps in the heap manager, and heap IDs in the allocation functions.
This commit is contained in:
parent
13d9569041
commit
408fdb8db6
@ -515,11 +515,11 @@ bool ehci_init(int bus, int dev, int func, uintptr_t base_addr, usb_hcd_t *hcd)
|
||||
if (!reset_host_controller(op_regs)) return false;
|
||||
|
||||
// Record the heap state to allow us to free memory.
|
||||
uintptr_t initial_heap_mark = lm_heap_mark();
|
||||
uintptr_t initial_heap_mark = heap_mark(HEAP_TYPE_LM_1);
|
||||
|
||||
// Allocate and initialise a periodic frame list. This needs to be aligned on a 4K page boundary. Some controllers
|
||||
// don't support a programmable list length, so we just use the default length.
|
||||
uintptr_t pfl_addr = lm_heap_alloc(EHCI_MAX_PFL_LENGTH * sizeof(uint32_t), PAGE_SIZE);
|
||||
uintptr_t pfl_addr = heap_alloc(HEAP_TYPE_LM_1, EHCI_MAX_PFL_LENGTH * sizeof(uint32_t), PAGE_SIZE);
|
||||
if (pfl_addr == 0) {
|
||||
goto no_keyboards_found;
|
||||
}
|
||||
@ -530,7 +530,7 @@ bool ehci_init(int bus, int dev, int func, uintptr_t base_addr, usb_hcd_t *hcd)
|
||||
}
|
||||
|
||||
// Allocate and initialise a workspace for this controller. This needs to be permanently mapped into virtual memory.
|
||||
uintptr_t workspace_addr = lm_heap_alloc(sizeof(workspace_t), PAGE_SIZE);
|
||||
uintptr_t workspace_addr = heap_alloc(HEAP_TYPE_LM_1, sizeof(workspace_t), PAGE_SIZE);
|
||||
if (workspace_addr == 0) {
|
||||
goto no_keyboards_found;
|
||||
}
|
||||
@ -684,6 +684,6 @@ bool ehci_init(int bus, int dev, int func, uintptr_t base_addr, usb_hcd_t *hcd)
|
||||
return true;
|
||||
|
||||
no_keyboards_found:
|
||||
lm_heap_rewind(initial_heap_mark);
|
||||
heap_rewind(HEAP_TYPE_LM_1, initial_heap_mark);
|
||||
return false;
|
||||
}
|
||||
|
@ -24,8 +24,10 @@ typedef struct {
|
||||
// Private Variables
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static heap_t lm_heap = { .segment = -1, .start = 0, .end = 0 };
|
||||
static heap_t hm_heap = { .segment = -1, .start = 0, .end = 0 };
|
||||
static heap_t heaps[HEAP_TYPE_LAST] = {
|
||||
{ .segment = -1, .start = 0, .end = 0 },
|
||||
{ .segment = -1, .start = 0, .end = 0 }
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private Functions
|
||||
@ -36,8 +38,9 @@ static size_t num_pages(size_t size)
|
||||
return (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
||||
}
|
||||
|
||||
static uintptr_t heap_alloc(const heap_t *heap, size_t size, uintptr_t alignment)
|
||||
uintptr_t heap_alloc(heap_type_t heap_id, size_t size, uintptr_t alignment)
|
||||
{
|
||||
const heap_t * heap = &heaps[heap_id];
|
||||
if (heap->segment < 0) {
|
||||
return 0;
|
||||
}
|
||||
@ -50,16 +53,18 @@ static uintptr_t heap_alloc(const heap_t *heap, size_t size, uintptr_t alignment
|
||||
return addr << PAGE_SHIFT;
|
||||
}
|
||||
|
||||
static uintptr_t heap_mark(const heap_t *heap)
|
||||
uintptr_t heap_mark(heap_type_t heap_id)
|
||||
{
|
||||
const heap_t * heap = &heaps[heap_id];
|
||||
if (heap->segment < 0) {
|
||||
return 0;
|
||||
}
|
||||
return pm_map[heap->segment].end;
|
||||
}
|
||||
|
||||
static void heap_rewind(const heap_t *heap, uintptr_t mark)
|
||||
void heap_rewind(heap_type_t heap_id, uintptr_t mark)
|
||||
{
|
||||
const heap_t * heap = &heaps[heap_id];
|
||||
if (heap->segment >= 0 && mark > pm_map[heap->segment].end && mark <= heap->end) {
|
||||
pm_map[heap->segment].end = mark;
|
||||
}
|
||||
@ -86,43 +91,13 @@ void heap_init(void)
|
||||
if (segment_size >= max_segment_size) {
|
||||
max_segment_size = segment_size;
|
||||
if (try_heap_end <= PAGE_C(1,MB)) {
|
||||
lm_heap.segment = i;
|
||||
lm_heap.start = try_heap_start;
|
||||
lm_heap.end = try_heap_end;
|
||||
heaps[HEAP_TYPE_LM_1].segment = i;
|
||||
heaps[HEAP_TYPE_LM_1].start = try_heap_start;
|
||||
heaps[HEAP_TYPE_LM_1].end = try_heap_end;
|
||||
}
|
||||
hm_heap.segment = i;
|
||||
hm_heap.start = try_heap_start;
|
||||
hm_heap.end = try_heap_end;
|
||||
heaps[HEAP_TYPE_HM_1].segment = i;
|
||||
heaps[HEAP_TYPE_HM_1].start = try_heap_start;
|
||||
heaps[HEAP_TYPE_HM_1].end = try_heap_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t lm_heap_alloc(size_t size, uintptr_t alignment)
|
||||
{
|
||||
return heap_alloc(&lm_heap, size, alignment);
|
||||
}
|
||||
|
||||
uintptr_t lm_heap_mark(void)
|
||||
{
|
||||
return heap_mark(&lm_heap);
|
||||
}
|
||||
|
||||
void lm_heap_rewind(uintptr_t mark)
|
||||
{
|
||||
heap_rewind(&lm_heap, mark);
|
||||
}
|
||||
|
||||
uintptr_t hm_heap_alloc(size_t size, uintptr_t alignment)
|
||||
{
|
||||
return heap_alloc(&hm_heap, size, alignment);
|
||||
}
|
||||
|
||||
uintptr_t hm_heap_mark(void)
|
||||
{
|
||||
return heap_mark(&hm_heap);
|
||||
}
|
||||
|
||||
void hm_heap_rewind(uintptr_t mark)
|
||||
{
|
||||
heap_rewind(&hm_heap, mark);
|
||||
}
|
||||
|
@ -16,71 +16,48 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum {
|
||||
HEAP_TYPE_LM_1,
|
||||
HEAP_TYPE_HM_1,
|
||||
HEAP_TYPE_LAST
|
||||
} heap_type_t;
|
||||
|
||||
/**
|
||||
* Initialises the heaps.
|
||||
*/
|
||||
void heap_init(void);
|
||||
|
||||
/**
|
||||
* Allocates a chunk of physical memory below 1MB. The allocated region will
|
||||
* be at least the requested size with the requested alignment. This memory
|
||||
* is always mapped to the identical address in virtual memory.
|
||||
* Allocates a chunk of physical memory in the given heap. The allocated
|
||||
* region will be at least the requested size with the requested alignment.
|
||||
* This memory is always mapped to the identical address in virtual memory.
|
||||
*
|
||||
* \param size - the requested size in bytes.
|
||||
* \param alignment - the requested byte alignment (must be a power of 2).
|
||||
* \param size - the requested size in bytes.
|
||||
* \param alignment - the requested byte alignment (must be a power of 2).
|
||||
* \param heap - the heap on which this allocation shall be performed.
|
||||
*
|
||||
* \returns
|
||||
* On success, the allocated address in physical memory. On failure, 0.
|
||||
*/
|
||||
uintptr_t lm_heap_alloc(size_t size, uintptr_t alignment);
|
||||
uintptr_t heap_alloc(heap_type_t heap_id, size_t size, uintptr_t alignment);
|
||||
|
||||
/**
|
||||
* Returns a value indicating the current allocation state of the low-memory
|
||||
* heap. This value may be passed to lm_heap_rewind() to free any low memory
|
||||
* allocated after this call.
|
||||
* Returns a value indicating the current allocation state of the given
|
||||
* memory heap. This value may be passed to heap_rewind() to free any
|
||||
* memory from that heap allocated after this call.
|
||||
*
|
||||
* \returns
|
||||
* An opaque value indicating the current allocation state.
|
||||
*/
|
||||
uintptr_t lm_heap_mark(void);
|
||||
uintptr_t heap_mark(heap_type_t heap_id);
|
||||
|
||||
/**
|
||||
* Frees any low memory allocated since the specified mark was obtained from
|
||||
* a call to lm_heap_mark().
|
||||
* Frees any memory allocated in the given heap since the specified mark was
|
||||
* obtained from a call to heap_mark().
|
||||
*
|
||||
* \param mark - the mark that indicates how much memory to free.
|
||||
* \param mark - the mark that indicates how much memory to free.
|
||||
* \param heap - the heap on which this rewind shall be performed.
|
||||
*/
|
||||
void lm_heap_rewind(uintptr_t mark);
|
||||
|
||||
/**
|
||||
* Allocates a chunk of physical memory below 4GB. The allocated region will
|
||||
* be at least the requested size with the requested alignment. The caller is
|
||||
* responsible for mapping it into virtual memory if required.
|
||||
*
|
||||
* \param size - the requested size in bytes.
|
||||
* \param alignment - the requested byte alignment (must be a power of 2).
|
||||
*
|
||||
* \returns
|
||||
* On success, the allocated address in physical memory. On failure, 0.
|
||||
*/
|
||||
uintptr_t hm_heap_alloc(size_t size, uintptr_t alignment);
|
||||
|
||||
/**
|
||||
* Returns a value indicating the current allocation state of the high-memory
|
||||
* heap. This value may be passed to hm_heap_rewind() to free any high memory
|
||||
* allocated after this call.
|
||||
*
|
||||
* \returns
|
||||
* An opaque value indicating the current allocation state.
|
||||
*/
|
||||
uintptr_t hm_heap_mark(void);
|
||||
|
||||
/**
|
||||
* Frees any high memory allocated since the specified mark was obtained from
|
||||
* a call to hm_heap_mark().
|
||||
*
|
||||
* \param mark - the mark that indicates how much memory to free.
|
||||
*/
|
||||
void hm_heap_rewind(uintptr_t mark);
|
||||
void heap_rewind(heap_type_t heap_id, uintptr_t mark);
|
||||
|
||||
#endif // HEAP_H
|
||||
|
@ -457,10 +457,10 @@ bool ohci_init(uintptr_t base_addr, usb_hcd_t *hcd)
|
||||
}
|
||||
|
||||
// Record the heap state to allow us to free memory.
|
||||
uintptr_t initial_heap_mark = lm_heap_mark();
|
||||
uintptr_t initial_heap_mark = heap_mark(HEAP_TYPE_LM_1);
|
||||
|
||||
// Allocate and initialise a workspace for this controller. This needs to be permanently mapped into virtual memory.
|
||||
uintptr_t workspace_addr = lm_heap_alloc(sizeof(workspace_t), PAGE_SIZE);
|
||||
uintptr_t workspace_addr = heap_alloc(HEAP_TYPE_LM_1, sizeof(workspace_t), PAGE_SIZE);
|
||||
if (workspace_addr == 0) {
|
||||
goto no_keyboards_found;
|
||||
}
|
||||
@ -608,6 +608,6 @@ bool ohci_init(uintptr_t base_addr, usb_hcd_t *hcd)
|
||||
return true;
|
||||
|
||||
no_keyboards_found:
|
||||
lm_heap_rewind(initial_heap_mark);
|
||||
heap_rewind(HEAP_TYPE_LM_1, initial_heap_mark);
|
||||
return false;
|
||||
}
|
||||
|
@ -550,7 +550,7 @@ void smp_init(bool smp_enable)
|
||||
|
||||
// Allocate a page of low memory for AP trampoline and sync objects.
|
||||
// These need to remain pinned in place during relocation.
|
||||
smp_heap_page = lm_heap_alloc(PAGE_SIZE, PAGE_SIZE) >> PAGE_SHIFT;
|
||||
smp_heap_page = heap_alloc(HEAP_TYPE_LM_1, PAGE_SIZE, PAGE_SIZE) >> PAGE_SHIFT;
|
||||
|
||||
ap_startup_addr = (uintptr_t)startup;
|
||||
|
||||
|
@ -430,17 +430,17 @@ bool uhci_init(int bus, int dev, int func, uint16_t io_base, usb_hcd_t *hcd)
|
||||
if (!reset_host_controller(io_base)) return false;
|
||||
|
||||
// Record the heap state to allow us to free memory.
|
||||
uintptr_t initial_heap_mark = lm_heap_mark();
|
||||
uintptr_t initial_heap_mark = heap_mark(HEAP_TYPE_LM_1);
|
||||
|
||||
// Allocate the frame list. This needs to be aligned on a 4K page boundary.
|
||||
uintptr_t fl_addr = lm_heap_alloc(UHCI_FL_LENGTH * sizeof(uint32_t), PAGE_SIZE);
|
||||
uintptr_t fl_addr = heap_alloc(HEAP_TYPE_LM_1, UHCI_FL_LENGTH * sizeof(uint32_t), PAGE_SIZE);
|
||||
if (fl_addr == 0) {
|
||||
goto no_keyboards_found;
|
||||
}
|
||||
uint32_t *fl = (uint32_t *)fl_addr;
|
||||
|
||||
// Allocate and initialise a workspace for this controller. This needs to be permanently mapped into virtual memory.
|
||||
uintptr_t workspace_addr = lm_heap_alloc(sizeof(workspace_t), PAGE_SIZE);
|
||||
uintptr_t workspace_addr = heap_alloc(HEAP_TYPE_LM_1, sizeof(workspace_t), PAGE_SIZE);
|
||||
if (workspace_addr == 0) {
|
||||
goto no_keyboards_found;
|
||||
}
|
||||
@ -574,6 +574,6 @@ bool uhci_init(int bus, int dev, int func, uint16_t io_base, usb_hcd_t *hcd)
|
||||
return true;
|
||||
|
||||
no_keyboards_found:
|
||||
lm_heap_rewind(initial_heap_mark);
|
||||
heap_rewind(HEAP_TYPE_LM_1, initial_heap_mark);
|
||||
return false;
|
||||
}
|
||||
|
@ -645,10 +645,10 @@ static int allocate_slot(const usb_hcd_t *hcd)
|
||||
xhci_trb_t event;
|
||||
|
||||
// Record the heap state to allow us to free memory.
|
||||
ws->initial_heap_mark = lm_heap_mark();
|
||||
ws->initial_heap_mark = heap_mark(HEAP_TYPE_LM_1);
|
||||
|
||||
// Allocate and initialise a private workspace for this device.
|
||||
uintptr_t device_workspace_addr = lm_heap_alloc(DEVICE_WS_SIZE, PAGE_SIZE);
|
||||
uintptr_t device_workspace_addr = heap_alloc(HEAP_TYPE_LM_1, DEVICE_WS_SIZE, PAGE_SIZE);
|
||||
if (device_workspace_addr == 0) {
|
||||
goto free_memory;
|
||||
}
|
||||
@ -672,7 +672,7 @@ static int allocate_slot(const usb_hcd_t *hcd)
|
||||
return slot_id;
|
||||
|
||||
free_memory:
|
||||
lm_heap_rewind(ws->initial_heap_mark);
|
||||
heap_rewind(HEAP_TYPE_LM_1, ws->initial_heap_mark);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -690,7 +690,7 @@ static bool release_slot(const usb_hcd_t *hcd, int slot_id)
|
||||
|
||||
write64(&ws->device_context_index[slot_id], 0);
|
||||
|
||||
lm_heap_rewind(ws->initial_heap_mark);
|
||||
heap_rewind(HEAP_TYPE_LM_1, ws->initial_heap_mark);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -987,8 +987,8 @@ bool xhci_init(uintptr_t base_addr, usb_hcd_t *hcd)
|
||||
if (!reset_host_controller(op_regs)) return false;
|
||||
|
||||
// Record the heap states to allow us to free memory.
|
||||
uintptr_t initial_lm_heap_mark = lm_heap_mark();
|
||||
uintptr_t initial_hm_heap_mark = hm_heap_mark();
|
||||
uintptr_t initial_lm_heap_mark = heap_mark(HEAP_TYPE_LM_1);
|
||||
uintptr_t initial_hm_heap_mark = heap_mark(HEAP_TYPE_HM_1);
|
||||
|
||||
// Record the controller page size.
|
||||
uintptr_t xhci_page_size = (read32(&op_regs->page_size) & 0xffff) << 12;
|
||||
@ -1002,7 +1002,7 @@ bool xhci_init(uintptr_t base_addr, usb_hcd_t *hcd)
|
||||
|
||||
// Allocate and clear the scratchpad memory on the heap. This must be aligned to the controller page size.
|
||||
uintptr_t scratchpad_size = num_scratchpad_buffers * xhci_page_size;
|
||||
uintptr_t scratchpad_paddr = hm_heap_alloc(scratchpad_size, xhci_page_size);
|
||||
uintptr_t scratchpad_paddr = heap_alloc(HEAP_TYPE_HM_1, scratchpad_size, xhci_page_size);
|
||||
if (scratchpad_paddr == 0) {
|
||||
goto no_keyboards_found;
|
||||
}
|
||||
@ -1018,7 +1018,7 @@ bool xhci_init(uintptr_t base_addr, usb_hcd_t *hcd)
|
||||
uintptr_t device_context_index_size = (1 + max_slots) * sizeof(uint64_t);
|
||||
uintptr_t scratchpad_buffer_index_offs = round_up(device_context_index_size, 64);
|
||||
uintptr_t scratchpad_buffer_index_size = num_scratchpad_buffers * sizeof(uint64_t);
|
||||
uintptr_t device_context_index_paddr = hm_heap_alloc(scratchpad_buffer_index_offs + scratchpad_buffer_index_size, 64);
|
||||
uintptr_t device_context_index_paddr = heap_alloc(HEAP_TYPE_HM_1, scratchpad_buffer_index_offs + scratchpad_buffer_index_size, 64);
|
||||
if (device_context_index_paddr == 0) {
|
||||
goto no_keyboards_found;
|
||||
}
|
||||
@ -1041,7 +1041,7 @@ bool xhci_init(uintptr_t base_addr, usb_hcd_t *hcd)
|
||||
}
|
||||
|
||||
// Allocate and initialise a workspace for this controller. This needs to be permanently mapped into virtual memory.
|
||||
uintptr_t workspace_addr = lm_heap_alloc(sizeof(workspace_t), PAGE_SIZE);
|
||||
uintptr_t workspace_addr = heap_alloc(HEAP_TYPE_LM_1, sizeof(workspace_t), PAGE_SIZE);
|
||||
if (workspace_addr == 0) {
|
||||
goto no_keyboards_found;
|
||||
}
|
||||
@ -1061,7 +1061,7 @@ bool xhci_init(uintptr_t base_addr, usb_hcd_t *hcd)
|
||||
ws->er_dequeue_state = WS_ER_SIZE; // cycle = 1, index = 0
|
||||
|
||||
// Allocate and initialise the input context data structure. This needs to be contained within a single page.
|
||||
ws->input_context_addr = lm_heap_alloc(XHCI_MAX_IP_CONTEXT_SIZE, PAGE_SIZE);
|
||||
ws->input_context_addr = heap_alloc(HEAP_TYPE_LM_1, XHCI_MAX_IP_CONTEXT_SIZE, PAGE_SIZE);
|
||||
if (ws->input_context_addr == 0) {
|
||||
goto no_keyboards_found;
|
||||
}
|
||||
@ -1167,7 +1167,7 @@ bool xhci_init(uintptr_t base_addr, usb_hcd_t *hcd)
|
||||
return true;
|
||||
|
||||
no_keyboards_found:
|
||||
lm_heap_rewind(initial_lm_heap_mark);
|
||||
hm_heap_rewind(initial_hm_heap_mark);
|
||||
heap_rewind(HEAP_TYPE_LM_1, initial_lm_heap_mark);
|
||||
heap_rewind(HEAP_TYPE_HM_1, initial_hm_heap_mark);
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user