Bare metal: tweaks pertaining to physical memory handling

- Factor __invert_memory() into two routines, to make it
  easier for other libc routines to create their own negative
  address mappings
- Tweak __invert_memory() to map only the usable memory as
  given in the 0xe820 memory map, and no more
- Arrange for VGA console initialization to map video memory
  separately into virtual memory (in case needed)
- Rename libc/vga/vga-init.S to libc/vga/rlinit-vga.S, to
  reduce confusion as to the module's purpose
This commit is contained in:
tkchia 2022-09-22 18:28:44 +00:00
parent 87708c5d6e
commit 8089876c51
4 changed files with 28 additions and 7 deletions

View file

@ -112,19 +112,34 @@ static noasan textreal void __normalize_e820(struct mman *mm) {
mm->e820n = n;
}
/**
* Identity maps an area of physical memory to its negative address.
*/
noasan textreal void __invert_memory_area(struct mman *mm, uint64_t *pml4t,
uint64_t ps, uint64_t size,
uint64_t pte_flags) {
uint64_t pe = ps + size, p, *m;
ps = ROUNDDOWN(ps, 4096);
pe = ROUNDUP(pe, 4096);
for (p = ps; p != pe; p += 4096) {
m = __get_virtual(mm, pml4t, BANE + p, true);
if (m && !(*m & PAGE_V)) {
*m = p | PAGE_V | pte_flags;
}
}
}
/**
* Identity maps all usable physical memory to its negative address.
*/
static noasan textreal void __invert_memory(struct mman *mm, uint64_t *pml4t) {
uint64_t i, j, *m, p, pe;
for (i = 0; i < mm->e820n; ++i) {
for (p = mm->e820[i].addr, pe = mm->e820[i].addr + mm->e820[i].size;
p != pe + 0x200000; p += 4096) {
m = __get_virtual(mm, pml4t, BANE + p, true);
if (m && !(*m & PAGE_V)) {
*m = p | PAGE_V | PAGE_RW;
}
}
uint64_t ps = mm->e820[i].addr, size = mm->e820[i].size;
/* ape/ape.S has already mapped the first 2 MiB of physical memory. */
if (ps < 0x200000 && ps + size <= 0x200000)
continue;
__invert_memory_area(mm, pml4t, ps, size, PAGE_RW);
}
}

View file

@ -185,6 +185,8 @@ struct IdtDescriptor {
uint64_t *__get_virtual(struct mman *, uint64_t *, int64_t, bool);
uint64_t __clear_page(uint64_t);
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);
forceinline unsigned char inb(unsigned short port) {

View file

@ -60,6 +60,7 @@ ssize_t sys_writev_vga(struct Fd *fd, const struct iovec *iov, int iovlen) {
__attribute__((__constructor__)) static textstartup void _vga_init(void) {
if (IsMetal()) {
struct mman *mm = (struct mman *)(BANE + 0x0500);
void * const vid_buf = (void *)(BANE + 0xb8000ull);
/*
* Get the initial cursor position from the BIOS data area. Also get
@ -74,6 +75,9 @@ __attribute__((__constructor__)) static textstartup void _vga_init(void) {
chr_ht_hi = *(uint8_t *)(BANE + 0x0486ull);
if (chr_ht_hi != 0 || chr_ht > 32)
chr_ht = 32;
/* Make sure the video buffer is mapped into virtual memory. */
__invert_memory_area(mm, __get_pml4t(), (uint64_t)vid_buf,
2 * VGA_TTY_HEIGHT * VGA_TTY_WIDTH, PAGE_RW);
/*
* Initialize our tty structure from the current screen contents,
* current cursor position, & character height.