Refactor some Blinkenlights code

This commit is contained in:
Justine Tunney 2021-03-03 13:09:06 -08:00
parent 8af91bcbe7
commit e3ee3c78e9
4 changed files with 46 additions and 40 deletions

View file

@ -56,7 +56,7 @@ struct Machine {
}; };
struct MachineTlb { struct MachineTlb {
int64_t virt; int64_t virt;
uint8_t *host; uint64_t entry;
} tlb[16]; } tlb[16];
struct MachineReal { struct MachineReal {
size_t i, n; size_t i, n;

View file

@ -21,6 +21,7 @@
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/runtime/pc.internal.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/x/x.h" #include "libc/x/x.h"
#include "tool/build/lib/endian.h" #include "tool/build/lib/endian.h"
@ -44,50 +45,54 @@ void SetWriteAddr(struct Machine *m, int64_t addr, uint32_t size) {
} }
} }
long HandlePageFault(struct Machine *m, uint64_t entry, uint64_t table, uint64_t HandlePageFault(struct Machine *m, uint64_t entry, uint64_t table,
unsigned index) { unsigned index) {
long page; long page;
if ((page = AllocateLinearPage(m)) != -1) { if ((page = AllocateLinearPage(m)) != -1) {
--m->memstat.reserved; --m->memstat.reserved;
*(uint64_t *)(m->real.p + table + index * 8) = return (*(uint64_t *)(m->real.p + table + index * 8) =
page | entry & ~0x7ffffffffe00; page | entry & ~0x7ffffffffe00);
} else {
return 0;
} }
return page; }
uint64_t FindPage(struct Machine *m, int64_t virt) {
uint64_t table, entry;
unsigned level, index, i;
virt &= -0x1000;
for (i = 0; i < ARRAYLEN(m->tlb); ++i) {
if (m->tlb[i].virt == virt && (m->tlb[i].entry & 1)) {
return m->tlb[i].entry;
}
}
level = 39;
entry = m->cr3;
do {
table = entry & PAGE_TA;
CHECK_LT(table, m->real.n);
index = (virt >> level) & 511;
entry = *(uint64_t *)(m->real.p + table + index * 8);
if (!(entry & 1)) return 0;
} while ((level -= 9) >= 12);
if ((entry & 0x0e00) &&
(entry = HandlePageFault(m, entry, table, index)) == -1) {
return 0;
}
m->tlbindex = (m->tlbindex + 1) & (ARRAYLEN(m->tlb) - 1);
m->tlb[m->tlbindex] = m->tlb[0];
m->tlb[0].virt = virt;
m->tlb[0].entry = entry;
return entry;
} }
void *FindReal(struct Machine *m, int64_t virt) { void *FindReal(struct Machine *m, int64_t virt) {
long page; uint64_t table, entry, page;
uint64_t table, entry;
unsigned skew, level, index, i; unsigned skew, level, index, i;
if ((m->mode & 3) != XED_MODE_REAL) { if ((m->mode & 3) != XED_MODE_REAL) {
if (-0x800000000000 <= virt && virt < 0x800000000000) { if (-0x800000000000 <= virt && virt < 0x800000000000) {
skew = virt & 0xfff; if (!(entry = FindPage(m, virt))) return NULL;
virt &= -0x1000; return m->real.p + (entry & PAGE_TA) + (virt & 0xfff);
for (i = 0; i < ARRAYLEN(m->tlb); ++i) {
if (m->tlb[i].virt == virt && m->tlb[i].host) {
return m->tlb[i].host + skew;
}
}
level = 39;
entry = m->cr3;
do {
table = entry & 0x7ffffffff000;
CHECK_LT(table, m->real.n);
index = (virt >> level) & 511;
entry = *(uint64_t *)(m->real.p + table + index * 8);
if (!(entry & 1)) return NULL;
} while ((level -= 9) >= 12);
if (!(entry & 0x0e00)) {
page = entry & 0x7ffffffff000;
CHECK_LT(page, m->real.n);
} else if ((page = HandlePageFault(m, entry, table, index)) == -1) {
return NULL;
}
m->tlbindex = (m->tlbindex + 1) & (ARRAYLEN(m->tlb) - 1);
m->tlb[m->tlbindex] = m->tlb[0];
m->tlb[0].virt = virt;
m->tlb[0].host = m->real.p + page;
return m->real.p + page + skew;
} else { } else {
return NULL; return NULL;
} }

View file

@ -5,6 +5,7 @@
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
int RegisterMemory(struct Machine *, int64_t, void *, size_t); int RegisterMemory(struct Machine *, int64_t, void *, size_t);
uint64_t FindPage(struct Machine *, int64_t);
void *AccessRam(struct Machine *, int64_t, size_t, void *[2], uint8_t *, bool); void *AccessRam(struct Machine *, int64_t, size_t, void *[2], uint8_t *, bool);
void *BeginLoadStore(struct Machine *, int64_t, size_t, void *[2], uint8_t *); void *BeginLoadStore(struct Machine *, int64_t, size_t, void *[2], uint8_t *);
void *BeginStore(struct Machine *, int64_t, size_t, void *[2], uint8_t *); void *BeginStore(struct Machine *, int64_t, size_t, void *[2], uint8_t *);
@ -14,19 +15,19 @@ void *Load(struct Machine *, int64_t, size_t, uint8_t *);
void *LoadBuf(struct Machine *, int64_t, size_t); void *LoadBuf(struct Machine *, int64_t, size_t);
void *LoadStr(struct Machine *, int64_t); void *LoadStr(struct Machine *, int64_t);
void *MallocPage(void); void *MallocPage(void);
void *RealAddress(struct Machine *, int64_t);
void *ReserveAddress(struct Machine *, int64_t, size_t); void *ReserveAddress(struct Machine *, int64_t, size_t);
void *ResolveAddress(struct Machine *, int64_t); void *ResolveAddress(struct Machine *, int64_t);
void *VirtualSend(struct Machine *, void *, int64_t, uint64_t);
void EndStore(struct Machine *, int64_t, size_t, void *[2], uint8_t *); void EndStore(struct Machine *, int64_t, size_t, void *[2], uint8_t *);
void EndStoreNp(struct Machine *, int64_t, size_t, void *[2], uint8_t *); void EndStoreNp(struct Machine *, int64_t, size_t, void *[2], uint8_t *);
void ResetRam(struct Machine *); void ResetRam(struct Machine *);
void SetReadAddr(struct Machine *, int64_t, uint32_t); void SetReadAddr(struct Machine *, int64_t, uint32_t);
void SetWriteAddr(struct Machine *, int64_t, uint32_t); void SetWriteAddr(struct Machine *, int64_t, uint32_t);
void VirtualRecv(struct Machine *, int64_t, void *, uint64_t); void VirtualRecv(struct Machine *, int64_t, void *, uint64_t);
void *VirtualSend(struct Machine *, void *, int64_t, uint64_t);
void VirtualSet(struct Machine *, int64_t, char, uint64_t);
void *RealAddress(struct Machine *, int64_t);
void VirtualSendRead(struct Machine *, void *, int64_t, uint64_t);
void VirtualRecvWrite(struct Machine *, int64_t, void *, uint64_t); void VirtualRecvWrite(struct Machine *, int64_t, void *, uint64_t);
void VirtualSendRead(struct Machine *, void *, int64_t, uint64_t);
void VirtualSet(struct Machine *, int64_t, char, uint64_t);
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -92,5 +92,5 @@ void ResetTlb(struct Machine *m) {
m->tlbindex = 0; m->tlbindex = 0;
memset(m->tlb, 0, sizeof(m->tlb)); memset(m->tlb, 0, sizeof(m->tlb));
m->codevirt = 0; m->codevirt = 0;
m->codehost = NULL; m->codehost = 0;
} }