diff --git a/include/arch/riscv/arch/model/statedata.h b/include/arch/riscv/arch/model/statedata.h index 82f754aba..d350435d1 100644 --- a/include/arch/riscv/arch/model/statedata.h +++ b/include/arch/riscv/arch/model/statedata.h @@ -31,5 +31,6 @@ extern pte_t kernel_root_pageTable[BIT(PT_INDEX_BITS)] VISIBLE; * page entry to avoid PMP exception. */ #if __riscv_xlen != 32 extern pte_t kernel_image_level2_pt[BIT(PT_INDEX_BITS)]; +extern pte_t kernel_image_level2_dev_pt[BIT(PT_INDEX_BITS)]; #endif diff --git a/include/drivers/irq/riscv_plic0.h b/include/drivers/irq/riscv_plic0.h index 00811b38c..9d5f37aef 100644 --- a/include/drivers/irq/riscv_plic0.h +++ b/include/drivers/irq/riscv_plic0.h @@ -16,7 +16,7 @@ * https://static.dev.sifive.com/U54-MC-RVCoreIP.pdf */ -#define PLIC_PPTR_BASE (PLIC_PPTR + 0x0C000000) +#define PLIC_PPTR_BASE PLIC_PPTR #define PLIC_HART_ID (CONFIG_FIRST_HART_ID) diff --git a/src/arch/riscv/kernel/vspace.c b/src/arch/riscv/kernel/vspace.c index d852c44d6..64de4dff4 100644 --- a/src/arch/riscv/kernel/vspace.c +++ b/src/arch/riscv/kernel/vspace.c @@ -85,9 +85,22 @@ static pte_t pte_next(word_t phys_addr, bool_t is_leaf) BOOT_CODE void map_kernel_frame(paddr_t paddr, pptr_t vaddr, vm_rights_t vm_rights) { +#if __riscv_xlen == 32 paddr = ROUND_DOWN(paddr, RISCV_GET_LVL_PGSIZE_BITS(0)); assert((paddr % RISCV_GET_LVL_PGSIZE(0)) == 0); kernel_root_pageTable[RISCV_GET_PT_INDEX(vaddr, 0)] = pte_next(paddr, true); +#else + if (vaddr >= KDEV_BASE) { + /* Map devices in 2nd-level page table */ + paddr = ROUND_DOWN(paddr, RISCV_GET_LVL_PGSIZE_BITS(1)); + assert((paddr % RISCV_GET_LVL_PGSIZE(1)) == 0); + kernel_image_level2_dev_pt[RISCV_GET_PT_INDEX(vaddr, 1)] = pte_next(paddr, true); + } else { + paddr = ROUND_DOWN(paddr, RISCV_GET_LVL_PGSIZE_BITS(0)); + assert((paddr % RISCV_GET_LVL_PGSIZE(0)) == 0); + kernel_root_pageTable[RISCV_GET_PT_INDEX(vaddr, 0)] = pte_next(paddr, true); + } +#endif } BOOT_CODE VISIBLE void map_kernel_window(void) @@ -133,6 +146,10 @@ BOOT_CODE VISIBLE void map_kernel_window(void) pptr += RISCV_GET_LVL_PGSIZE(1); paddr += RISCV_GET_LVL_PGSIZE(1); } + + /* Map kernel device page table */ + kernel_root_pageTable[RISCV_GET_PT_INDEX(KDEV_BASE, 0)] = + pte_next(kpptr_to_paddr(kernel_image_level2_dev_pt), false); #endif /* There should be 1GiB free where we put device mapping */ diff --git a/src/arch/riscv/machine/hardware.c b/src/arch/riscv/machine/hardware.c index 06a66d883..1357ce07b 100644 --- a/src/arch/riscv/machine/hardware.c +++ b/src/arch/riscv/machine/hardware.c @@ -55,12 +55,12 @@ BOOT_CODE void map_kernel_devices(void) } for (int i = 0; i < (sizeof(kernel_devices) / sizeof(kernel_frame_t)); i++) { - map_kernel_frame(kernel_devices[i].paddr, KDEV_BASE, + map_kernel_frame(kernel_devices[i].paddr, kernel_devices[i].pptr, VMKernelOnly); if (!kernel_devices[i].userAvailable) { p_region_t reg = { .start = kernel_devices[i].paddr, - .end = kernel_devices[i].paddr + (1 << PAGE_BITS), + .end = kernel_devices[i].paddr + (1 << seL4_LargePageBits), }; reserve_region(reg); } diff --git a/src/arch/riscv/model/statedata.c b/src/arch/riscv/model/statedata.c index 2352797a6..66534c711 100644 --- a/src/arch/riscv/model/statedata.c +++ b/src/arch/riscv/model/statedata.c @@ -22,6 +22,7 @@ pte_t kernel_root_pageTable[BIT(PT_INDEX_BITS)] ALIGN_BSS(BIT(seL4_PageTableBits #if __riscv_xlen != 32 pte_t kernel_image_level2_pt[BIT(PT_INDEX_BITS)] ALIGN_BSS(BIT(seL4_PageTableBits)); +pte_t kernel_image_level2_dev_pt[BIT(PT_INDEX_BITS)] ALIGN_BSS(BIT(seL4_PageTableBits)); #endif SMP_STATE_DEFINE(core_map_t, coreMap); diff --git a/tools/hardware.yml b/tools/hardware.yml index fcfdc831f..9092950d3 100644 --- a/tools/hardware.yml +++ b/tools/hardware.yml @@ -245,6 +245,7 @@ devices: regions: - index: 0 kernel: PLIC_PPTR + kernel_size: 0x04000000 # elfloader rules - compatible: diff --git a/tools/hardware/config.py b/tools/hardware/config.py index bec1802f5..c2bc5cf22 100644 --- a/tools/hardware/config.py +++ b/tools/hardware/config.py @@ -25,6 +25,10 @@ class Config: ''' Get page size in bits for this arch ''' return 12 # 4096-byte pages + def get_device_page_bits(self) -> int: + ''' Get page size in bits for mapping devices for this arch ''' + return self.get_page_bits() + class ARMConfig(Config): ''' Config class for ARM ''' @@ -46,6 +50,15 @@ class RISCVConfig(Config): of physical memory. Mark it as unavailable. ''' return self.MEGA_PAGE_SIZE + def get_device_page_bits(self) -> int: + ''' Get page size in bits for mapping devices for this arch ''' + if self.addrspace_max > (1 << 32): + # rv39 and rv48 use 2MiB device pages + return 21 + else: + # rv32 uses 4MiB device pages + return 22 + def get_arch_config(arch: str, addrspace_max: int) -> Config: ''' Return an appropriate Config object for the given architecture ''' diff --git a/tools/hardware/utils/rule.py b/tools/hardware/utils/rule.py index ef86e2719..9fa857acc 100644 --- a/tools/hardware/utils/rule.py +++ b/tools/hardware/utils/rule.py @@ -168,14 +168,14 @@ class DeviceRule: kernel_name = rule['kernel'] user = rule.get('user', False) macro = rule.get('macro', None) - max_size = 1 << self.config.get_page_bits() + max_size = 1 << self.config.get_device_page_bits() if 'kernel_size' in rule: max_size = rule['kernel_size'] elif max_size < reg.size: logging.warning( "Only mapping {}/{} bytes from node {}, region {}. Set kernel_size in YAML to silence.".format(max_size, reg.size, node.path, i)) ret.append(KernelRegionGroup(reg, kernel_name, - self.config.get_page_bits(), max_size, macro, user)) + self.config.get_device_page_bits(), max_size, macro, user)) return ret