RISC-V: reserve memory for SBI in device tree

Instead of special handling for the SBI region in the kernel, which can
be platform specific, treat it as a reserved memory region in the device
tree which is sufficient to prevent the kernel from turning the reserved
region into kernel untyped caps.

Signed-off-by: Kent McLeod <kent@kry10.com>
This commit is contained in:
Kent McLeod
2022-02-01 15:07:08 +11:00
committed by Gerwin Klein
parent 6e7e37af06
commit b657e50b66
14 changed files with 195 additions and 64 deletions

View File

@@ -19,11 +19,6 @@ class Config:
''' Used to align the base of physical memory. Returns alignment size in bits. '''
return 0
def get_bootloader_reserve(self) -> int:
''' Used to reserve a fixed amount of memory for the bootloader. Offsets
the kernel load address by the amount returned in bytes. '''
return 0
def get_page_bits(self) -> int:
''' Get page size in bits for this arch '''
return 12 # 4096-byte pages
@@ -35,15 +30,6 @@ class Config:
''' Get page size in bits for mapping devices for this arch '''
return self.get_page_bits()
def align_memory(self, regions: Set[Region]) -> List[Region]:
''' Given a set of regions, sort them and align the first so that the
ELF loader will be able to load the kernel into it. Will return the
aligned memory region list, a set of any regions of memory that were
aligned out and the physBase value that the kernel will use. memory
region list, a set of any regions of memory that were aligned out and
the physBase value that the kernel will use. '''
pass
class ARMConfig(Config):
''' Config class for ARM '''
@@ -57,20 +43,6 @@ class ARMConfig(Config):
''' On AArch32 the kernel requires at least super section alignment for physBase. '''
return self.SUPERSECTION_BITS
def align_memory(self, regions: Set[Region]) -> List[Region]:
''' Arm wants physBase to be the physical load address of the kernel. '''
ret = sorted(regions)
extra_reserved = set()
new = ret[0].align_base(self.get_kernel_phys_align())
resv = Region(ret[0].base, new.base - ret[0].base)
extra_reserved.add(resv)
ret[0] = new
physBase = ret[0].base
return ret, extra_reserved, physBase
class RISCVConfig(Config):
''' Config class for RISCV '''
@@ -79,28 +51,6 @@ class RISCVConfig(Config):
MEGAPAGE_BITS_RV64 = 21 # 2^21 = 2 MiByte
MEGA_PAGE_SIZE_RV64 = 2**MEGAPAGE_BITS_RV64
def get_bootloader_reserve(self) -> int:
''' OpenSBI reserved the first 2 MiByte of physical memory on rv64,
which is exactly a megapage. For rv32 we use the same value for now, as
this seems to work nicely - even if this is just half of the 4 MiByte
magepages that exist there. '''
return self.MEGA_PAGE_SIZE_RV64
def align_memory(self, regions: Set[Region]) -> List[Region]:
''' Currently the RISC-V port expects physBase to be the address that the
bootloader is loaded at. To be generalised in the future. '''
ret = sorted(regions)
extra_reserved = set()
physBase = ret[0].base
resv = Region(ret[0].base, self.get_bootloader_reserve())
extra_reserved.add(resv)
ret[0].base += self.get_bootloader_reserve()
ret[0].size -= self.get_bootloader_reserve()
return ret, extra_reserved, physBase
def get_device_page_bits(self) -> int:
''' Get page size in bits for mapping devices for this arch '''
if (self.sel4arch == 'riscv32'):

View File

@@ -83,12 +83,31 @@ def reserve_regions(regions: Set[Region], reserved: Set[Region]) -> Set[Region]:
return ret
def align_memory(regions: Set[Region], config: Config) -> List[Region]:
''' Given a set of regions, sort them and align the first so that the
ELF loader will be able to load the kernel into it. Will return the
aligned memory region list, a set of any regions of memory that were
aligned out and the physBase value that the kernel will use. '''
ret = sorted(regions)
extra_reserved = set()
if config.get_kernel_phys_align() != 0:
new = ret[0].align_base(config.get_kernel_phys_align())
resv = Region(ret[0].base, new.base - ret[0].base)
extra_reserved.add(resv)
ret[0] = new
physBase = ret[0].base
return ret, extra_reserved, physBase
def get_physical_memory(tree: FdtParser, config: Config) -> List[Region]:
''' returns a list of regions representing physical memory as used by the kernel '''
regions = merge_memory_regions(get_memory_regions(tree))
reserved = parse_reserved_regions(tree.get_path('/reserved-memory'))
regions = reserve_regions(regions, reserved)
regions, extra_reserved, physBase = config.align_memory(regions)
regions, extra_reserved, physBase = align_memory(regions, config)
return regions, reserved.union(extra_reserved), physBase