mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-09 03:10:27 +00:00
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:
parent
87708c5d6e
commit
8089876c51
4 changed files with 28 additions and 7 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue