|
19 | 19 | #include <h2_common_linear.h> |
20 | 20 | #include <h2_prof.h> |
21 | 21 | #include <angel.h> |
| 22 | +#include <boot.h> |
| 23 | +#include <bootvm_entry.h> |
| 24 | +#include <symbols.h> |
22 | 25 |
|
23 | 26 | #include <fcntl.h> |
24 | 27 | #include <unistd.h> |
|
92 | 95 | #define GUESS_HEAP_SIZE 0x4000000 /* 64MB */ |
93 | 96 | #define GUESS_STACK_SIZE 0x100000 /* 1MB */ |
94 | 97 |
|
| 98 | +#define GUEST_WINDOW_PAGES 5 /* number of 16M pages reserved for the guest image */ |
| 99 | + |
95 | 100 | #define FENCE_HI_MAX 0xfffff000 |
96 | 101 |
|
97 | 102 | #define WAKE_TIMER 0x1 |
@@ -541,6 +546,81 @@ void dcclean_range(unsigned long start, long range) { |
541 | 546 | } while (range >= 0); |
542 | 547 | } |
543 | 548 |
|
| 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 | + |
544 | 624 | void set_cmdline(unsigned int idx, long offset) { |
545 | 625 |
|
546 | 626 | int i; |
@@ -2406,6 +2486,8 @@ int main(int argc, char **argv) |
2406 | 2486 | clade_base = h2_info(INFO_CLADE_BASE); |
2407 | 2487 | guest_base = H2K_GUEST_START; |
2408 | 2488 |
|
| 2489 | + booter_self_map(); |
| 2490 | + |
2409 | 2491 | h2_galloc_init(&tcm_alloc, (unsigned int)tcm_base, (unsigned int)tcm_size, NULL); |
2410 | 2492 |
|
2411 | 2493 | h2_vmtrap_setvec(bootvm_vectors); |
|
0 commit comments