[metal] Reclaim base memory pages for later app use

This commit is contained in:
tkchia 2022-11-07 14:10:32 +00:00
parent e4b5fb76e4
commit 6da7709fb8
5 changed files with 60 additions and 21 deletions

View file

@ -1504,7 +1504,6 @@ long: movabs $BANE+PHYSICAL(0f),%rax
xor %r15d,%r15d
xor %ebx,%ebx
xor %ebp,%ebp
push %rbp
mov $mm,%rdi
mov %cr3,%rsi
mov $IMAGE_BASE_PHYSICAL,%edx
@ -1594,6 +1593,10 @@ kernel: movabs $ape_stack_vaddr,%rsp
.byte 0x0f,0x1f,0207 # nop rdi binbase
.long (IMAGE_BASE_VIRTUAL-IMAGE_BASE_REAL)/512
#endif
movabs $BANE+mm,%rdi
mov $0x79000,%esi
mov $0x7f000,%edx
call __reclaim_boot_pages
push $_HOSTMETAL # sets __hostos in crt.S
pop %rcx
pushq .Lenv0(%rip) # envp[0][0]

View file

@ -33,6 +33,7 @@
αcτµαlly pδrταblε εxεcµταblε § no-frills virtual memory management
*/
#include "ape/relocations.h"
#include "libc/assert.h"
#include "libc/elf/def.h"
#include "libc/elf/struct/phdr.h"
#include "libc/macros.internal.h"
@ -44,13 +45,25 @@
#define INVERT(x) (BANE + PHYSICAL(x))
struct ReclaimedPage {
uint64_t next;
};
/**
* Allocates new page of physical memory.
*/
noasan texthead uint64_t __new_page(struct mman *mm) {
uint64_t p;
uint64_t p = mm->frp;
if (p) {
uint64_t q;
struct ReclaimedPage *rp = (struct ReclaimedPage *)(BANE + p);
_unassert(p == (p & PAGE_TA));
q = rp->next;
_unassert(q == (q & PAGE_TA));
mm->frp = q;
return p;
}
if (mm->pdpi == mm->e820n) {
/* TODO: reclaim free pages */
return 0;
}
while (mm->pdp >= mm->e820[mm->pdpi].addr + mm->e820[mm->pdpi].size) {
@ -113,6 +126,7 @@ static noasan textreal void __normalize_e820(struct mman *mm, uint64_t top) {
mm->pdp = MAX(top, mm->e820[0].addr);
mm->pdpi = 0;
mm->e820n = n;
mm->frp = 0;
}
/**
@ -210,3 +224,21 @@ noasan textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b,
}
mm->pdp = MAX(mm->pdp, m);
}
/**
* Reclaim memory pages which were used at boot time but which can now be
* made available for the application.
*/
noasan textreal void __reclaim_boot_pages(struct mman *mm, uint64_t skip_start,
uint64_t skip_end) {
uint64_t p = mm->frp, q = IMAGE_BASE_REAL, e;
e = mm->e820[0].addr + mm->e820[0].size;
while (q != e) {
struct ReclaimedPage *rp = (struct ReclaimedPage *)(BANE + q);
rp->next = p;
p = q;
q += 4096;
if (q == skip_start) q = skip_end;
}
mm->frp = p;
}

View file

@ -136,6 +136,7 @@ __msabi noasan EFI_STATUS EfiMain(EFI_HANDLE ImageHandle,
pml4t[0] = (intptr_t)pdpt1 + PAGE_V + PAGE_RW;
pml4t[256] = (intptr_t)pdpt2 + PAGE_V + PAGE_RW;
__map_phdrs(mm, pml4t, 1024 * 1024, 1024 * 1024 + (_end - _base));
__reclaim_boot_pages(mm, 0x79000, 0x7f000);
/*
* Asks UEFI to handover control?

View file

@ -8,31 +8,33 @@ struct mman {
int64_t pdp; /* 0x0500 */
int32_t pdpi; /* 0x0508 */
int32_t e820n; /* 0x050c */
struct SmapEntry e820[256]; /* 0x0510 */
struct SmapEntry e820_end[0]; /* 0x1d10 */
char pc_drive_base_table[11]; /* 0x1d10 */
unsigned char pc_drive_type; /* 0x1d1b */
unsigned char pc_drive_last_sector; /* 0x1d1c */
unsigned short pc_drive_last_cylinder; /* 0x1d1e */
unsigned char pc_drives_attached; /* 0x1d20 */
unsigned char pc_drive_last_head; /* 0x1d21 */
unsigned char pc_drive; /* 0x1d22 */
char bad_idt[6]; /* 0x1d23 */
unsigned char pc_video_type; /* 0x1d29 */
unsigned short pc_video_stride; /* 0x1d2a — line width, including any
uint64_t frp; /* 0x0510 — free list of reclaimed,
previously used pages */
struct SmapEntry e820[256]; /* 0x0518 */
struct SmapEntry e820_end[0]; /* 0x1d18 */
char pc_drive_base_table[11]; /* 0x1d18 */
unsigned char pc_drive_type; /* 0x1d23 */
unsigned char pc_drive_last_sector; /* 0x1d24 */
unsigned short pc_drive_last_cylinder; /* 0x1d26 */
unsigned char pc_drives_attached; /* 0x1d28 */
unsigned char pc_drive_last_head; /* 0x1d29 */
unsigned char pc_drive; /* 0x1d2a */
char bad_idt[6]; /* 0x1d2b */
unsigned char pc_video_type; /* 0x1d31 */
unsigned short pc_video_stride; /* 0x1d32 — line width, including any
invisible "pixels" in
bytes (NOTE) */
unsigned short pc_video_width; /* 0x1d2c — width in chars. (text)
unsigned short pc_video_width; /* 0x1d34 — width in chars. (text)
or pixels (graphics) */
unsigned short pc_video_height; /* 0x1d2e — height in chars. (text)
unsigned short pc_video_height; /* 0x1d36 — height in chars. (text)
or pixels (graphics) */
uint64_t pc_video_framebuffer; /* 0x1d30 — physical address of
uint64_t pc_video_framebuffer; /* 0x1d38 — physical address of
video frame buffer */
uint64_t pc_video_framebuffer_size; /* 0x1d38 */
struct { /* 0x1d40 — starting cursor pos. */
uint64_t pc_video_framebuffer_size; /* 0x1d40 */
struct { /* 0x1d48 — starting cursor pos. */
unsigned short y, x;
} pc_video_curs_info;
unsigned short pc_video_char_height; /* 0x1d44 — character height (useful
unsigned short pc_video_char_height; /* 0x1d4c — character height (useful
for setting cursor shape
in text mode) */
};

View file

@ -189,6 +189,7 @@ uint64_t __new_page(struct mman *);
void __invert_memory_area(struct mman *, uint64_t *, uint64_t, uint64_t,
uint64_t);
void __map_phdrs(struct mman *, uint64_t *, uint64_t, uint64_t);
void __reclaim_boot_pages(struct mman *, uint64_t, uint64_t);
forceinline unsigned char inb(unsigned short port) {
unsigned char al;