Skip to content

Commit 2ef6dea

Browse files
committed
booter: build a self-owned LINEAR TLB for the bootvm ASID
Replace the kernel's OFFSET translation with a LINEAR table the booter builds and installs itself via h2_vmtrap_newmap(), covering its own footprint (image + heap + stack) sized from BOOT_TLB_PGSIZE and PAGE_BITS. Add a GUEST_WINDOW_PAGES-sized (16M-page) window starting at H2K_GUEST_START, since load_vm() accesses guest physical memory directly through the booter's own map and needs coverage beyond the booter's footprint entries. Signed-off-by: Tzahi Sabo <stzahi@qti.qualcomm.com>
1 parent 43c0b68 commit 2ef6dea

1 file changed

Lines changed: 82 additions & 0 deletions

File tree

booter/booter.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
#include <h2_common_linear.h>
2020
#include <h2_prof.h>
2121
#include <angel.h>
22+
#include <boot.h>
23+
#include <bootvm_entry.h>
24+
#include <symbols.h>
2225

2326
#include <fcntl.h>
2427
#include <unistd.h>
@@ -92,6 +95,8 @@ enum {
9295
#define GUESS_HEAP_SIZE 0x4000000 /* 64MB */
9396
#define GUESS_STACK_SIZE 0x100000 /* 1MB */
9497

98+
#define GUEST_WINDOW_PAGES 5 /* number of 16M pages reserved for the guest image */
99+
95100
#define FENCE_HI_MAX 0xfffff000
96101

97102
#define WAKE_TIMER 0x1
@@ -541,6 +546,81 @@ void dcclean_range(unsigned long start, long range) {
541546
} while (range >= 0);
542547
}
543548

549+
void booter_self_map(void) {
550+
551+
H2K_linear_fmt_t *table;
552+
unsigned long page_size;
553+
unsigned long image_base;
554+
unsigned long heap_size;
555+
unsigned long stack_size;
556+
unsigned long footprint;
557+
unsigned long npages;
558+
unsigned long guest_npages;
559+
unsigned long va;
560+
unsigned long long pa;
561+
unsigned long i;
562+
563+
page_size = 1UL << (PAGE_BITS + BOOT_TLB_PGSIZE * 2); // size in bytes of one booter TLB page (BOOT_TLB_PGSIZE encodes size as a power-of-4 step above the minimum page)
564+
image_base = (unsigned long)__bootvm_entry_point & -page_size; // round entry point down to a page boundary so the mapping starts on an aligned page
565+
566+
heap_size = ((unsigned long)&HEAP_SIZE == 0) ? GUESS_HEAP_SIZE : (unsigned long)&HEAP_SIZE;
567+
stack_size = ((unsigned long)&STACK_SIZE == 0) ? GUESS_STACK_SIZE : (unsigned long)&STACK_SIZE;
568+
569+
// Total footprint: image (from the aligned base up to the linker's "end" symbol) + heap + stack,
570+
// rounded up to a whole number of pages so every byte the booter itself uses is covered.
571+
footprint = H2_ALIGN_UP(((unsigned long)&end - image_base) + heap_size + stack_size, page_size);
572+
npages = footprint / page_size;
573+
574+
/* Separate entries covering the guest image address range, since load_vm()
575+
* accesses guest physical memory directly through the booter's own map. */
576+
guest_npages = GUEST_WINDOW_PAGES; // fixed-size window of 16M pages; typical guest images are well under this
577+
578+
// +1 for the booter's own footprint entries, +guest_npages for the guest window, +1 for the null (end-marker) entry
579+
if (NULL == (table = (H2K_linear_fmt_t *)malloc(sizeof(H2K_linear_fmt_t) * (npages + guest_npages + 1)))) {
580+
error("malloc booter_self_map table", NULL);
581+
}
582+
583+
va = image_base >> PAGE_BITS; // table entries store page numbers, not byte addresses
584+
pa = ((unsigned long long)image_base + __boot_net_phys_offset__) >> PAGE_BITS; // matching PA: same offset the old OFFSET translation used
585+
586+
for (i = 0; i < npages; i++) {
587+
table[i].raw = 0ULL;
588+
table[i].ppn = pa;
589+
table[i].cccc = BOOT_CACHE_ATTR;
590+
table[i].xwru = URWX;
591+
table[i].vpn = va;
592+
table[i].size = BOOT_TLB_PGSIZE;
593+
594+
va += 1 << (BOOT_TLB_PGSIZE * 2); // advance by one page's worth of page-numbers (size field is a log4 step, hence *2)
595+
pa += 1 << (BOOT_TLB_PGSIZE * 2);
596+
}
597+
598+
// Guest window: maps H2K_GUEST_START upward in 16M pages so the booter can read/write guest
599+
// physical memory directly (memcpy/read/memset in load_vm()) the same way OFFSET translation
600+
// allowed before this table replaced it.
601+
va = H2K_GUEST_START >> PAGE_BITS;
602+
pa = ((unsigned long long)H2K_GUEST_START + __boot_net_phys_offset__) >> PAGE_BITS;
603+
604+
for (i = 0; i < guest_npages; i++) {
605+
table[npages + i].raw = 0ULL;
606+
table[npages + i].ppn = pa;
607+
table[npages + i].cccc = BOOT_CACHE_ATTR;
608+
table[npages + i].xwru = URWX;
609+
table[npages + i].vpn = va;
610+
table[npages + i].size = SIZE_16M;
611+
612+
va += 1 << (SIZE_16M * 2); // advance by one 16M page's worth of page-numbers
613+
pa += 1 << (SIZE_16M * 2);
614+
}
615+
table[npages + guest_npages].raw = 0ULL; // end marker (zero raw entry terminates the table)
616+
617+
dcclean_range((unsigned long)table, sizeof(H2K_linear_fmt_t) * (npages + guest_npages + 1));
618+
619+
if (h2_vmtrap_newmap(table, H2K_ASID_TRANS_TYPE_LINEAR, H2K_ASID_TLB_INVALIDATE_TRUE) < 0) {
620+
FAIL("booter_self_map: h2_vmtrap_newmap", "");
621+
}
622+
}
623+
544624
void set_cmdline(unsigned int idx, long offset) {
545625

546626
int i;
@@ -2406,6 +2486,8 @@ int main(int argc, char **argv)
24062486
clade_base = h2_info(INFO_CLADE_BASE);
24072487
guest_base = H2K_GUEST_START;
24082488

2489+
booter_self_map();
2490+
24092491
h2_galloc_init(&tcm_alloc, (unsigned int)tcm_base, (unsigned int)tcm_size, NULL);
24102492

24112493
h2_vmtrap_setvec(bootvm_vectors);

0 commit comments

Comments
 (0)