RISCV: Change 64 bit kernel window mapping to avoid PMP exception.

The SBI memory was mapped outside the kernel window. This would trigger
an instruction access fault on some hardware, when the bootloader has set
up PMP to protect the SBI memory. Instead of protecting a particular memory
region, the PMP locks the entire page table entry that covers the region.

The PADDR_LOAD and kernel base are adjusted to have the SBI memory
included in the kernel window. So that the SBI memory can be mapped as
part of the kernel image to a separate page table entry. This also
avoids the kernel to allocate untyped memory from the SBI region.
This commit is contained in:
Siwei Zhuang 2019-04-02 15:36:33 +11:00
parent cde3934f09
commit 897aaf5b13
6 changed files with 22 additions and 15 deletions

View file

@ -40,10 +40,9 @@ extern asid_pool_t *riscvKSASIDTable[BIT(asidHighBits)];
/* Kernel Page Tables */
extern pte_t kernel_root_pageTable[BIT(PT_INDEX_BITS)] VISIBLE;
/* If our PADDR_LOAD is not 1GiB aligned then we need to introduce a level2 pagetable
* in order to map in our kernel image at KERNEL_BASE */
#if CONFIG_PT_LEVELS == 3 && !IS_ALIGNED(PADDR_LOAD, RISCV_GET_LVL_PGSIZE_BITS(1))
#define RISCV_KERNEL_WINDOW_LEVEL2_PT
/* We need to introduce a level2 pagetable in order to map the BBL to a separate
* page entry to avoid PMP exception. */
#if __riscv_xlen != 32
extern pte_t kernel_image_level2_pt[BIT(PT_INDEX_BITS)];
#endif
#endif

View file

@ -26,7 +26,7 @@
/* This is the base of the kernel window, which is directly mapped to PADDR_BASE */
#define PPTR_BASE 0xFFFFFFC000000000lu
/* This is the mapping of the kernel (mapped above the kernel window currently) */
#define KERNEL_BASE 0xFFFFFFFF80000000lu
#define KERNEL_BASE 0xFFFFFFFF84000000lu
#else
#error Only PT_LEVELS == 3 is supported
#endif

View file

@ -38,7 +38,7 @@
/* This represents the physical address that the kernel image will be linked to. This needs to
* be on a 1gb boundary as we currently require being able to creating a mapping to this address
* as the largest frame size */
#define PADDR_LOAD 0xC0000000lu
#define PADDR_LOAD 0x84000000lu
#endif
/* The highest valid physical address that can be indexed in the kernel window */

View file

@ -38,6 +38,7 @@
#include <arch/machine.h>
#include <plat/machine/hardware.h>
#include <kernel/stack.h>
#include <util.h>
struct resolve_ret {
paddr_t frameBase;
@ -107,7 +108,7 @@ BOOT_CODE VISIBLE void map_kernel_window(void)
/* first we map in memory from PADDR_BASE */
word_t paddr = PADDR_BASE;
while (pptr < KERNEL_BASE) {
while (pptr < ROUND_DOWN(KERNEL_BASE, RISCV_GET_LVL_PGSIZE_BITS(1))) {
assert(IS_ALIGNED(pptr, RISCV_GET_LVL_PGSIZE_BITS(1)));
assert(IS_ALIGNED(paddr, RISCV_GET_LVL_PGSIZE_BITS(1)));
@ -116,19 +117,25 @@ BOOT_CODE VISIBLE void map_kernel_window(void)
pptr += RISCV_GET_LVL_PGSIZE(1);
paddr += RISCV_GET_LVL_PGSIZE(1);
}
/* now we should be mapping the 1GiB kernel base, starting again from PADDR_LOAD */
assert(pptr == KERNEL_BASE);
paddr = PADDR_LOAD;
/* now we should be mapping the 1GiB kernel base */
assert(pptr == ROUND_DOWN(KERNEL_BASE, RISCV_GET_LVL_PGSIZE_BITS(1)));
paddr = ROUND_DOWN(PADDR_LOAD, RISCV_GET_LVL_PGSIZE_BITS(1));
#ifndef RISCV_KERNEL_WINDOW_LEVEL2_PT
#if __riscv_xlen == 32
kernel_root_pageTable[RISCV_GET_PT_INDEX(pptr, 1)] = pte_next(paddr, true);
pptr += RISCV_GET_LVL_PGSIZE(1);
paddr += RISCV_GET_LVL_PGSIZE(1);
#else
word_t index = 0;
/* The kernel image are mapped twice, locating the two indexes in the
* root page table, pointing them to the same second level page table.
*/
kernel_root_pageTable[RISCV_GET_PT_INDEX(PADDR_LOAD + BASE_OFFSET, 1)] =
pte_next(kpptr_to_paddr(kernel_image_level2_pt), false);
kernel_root_pageTable[RISCV_GET_PT_INDEX(pptr, 1)] =
pte_next(kpptr_to_paddr(kernel_image_level2_pt), false);
while (pptr < KERNEL_BASE + RISCV_GET_LVL_PGSIZE(1)) {
while (pptr < ROUND_DOWN(KERNEL_BASE, RISCV_GET_LVL_PGSIZE_BITS(1)) +
RISCV_GET_LVL_PGSIZE(1)) {
kernel_image_level2_pt[index] = pte_next(paddr, true);
index++;
pptr += RISCV_GET_LVL_PGSIZE(2);

View file

@ -31,6 +31,7 @@ asid_pool_t *riscvKSASIDTable[BIT(asidHighBits)];
/* Kernel Page Tables */
pte_t kernel_root_pageTable[BIT(PT_INDEX_BITS)] ALIGN_BSS(BIT(seL4_PageTableBits));
#ifdef RISCV_KERNEL_WINDOW_LEVEL2_PT
#if __riscv_xlen != 32
pte_t kernel_image_level2_pt[BIT(PT_INDEX_BITS)] ALIGN_BSS(BIT(seL4_PageTableBits));
#endif

View file

@ -24,7 +24,7 @@ ENTRY(_start)
#if CONFIG_PT_LEVELS == 2
KERNEL_BASE = 0xFF800000;
#elif CONFIG_PT_LEVELS == 3
KERNEL_BASE = 0xFFFFFFFF80000000;
KERNEL_BASE = 0xFFFFFFFF84000000;
#elif CONFIG_PT_LEVELS == 4
#error PT_LEVELS == 4 is not supported yet
#endif
@ -33,7 +33,7 @@ KERNEL_BASE = 0xFFFFFFFF80000000;
#ifdef CONFIG_BUILD_ROCKET_CHIP_ZEDBOARD
PADDR_LOAD = 0x0000000088000000;
#else
PADDR_LOAD = 0x00000000C0000000;
PADDR_LOAD = 0x0000000084000000;
#endif
KERNEL_OFFSET = KERNEL_BASE - PADDR_LOAD;