seL4/tools/hardware/utils/memory.py
Gerwin Klein 7f562e1633 tools: consolidate RISC-V + Arm memory base logic
Co-authored-by: Oliver Scott <Oliver.Scott@data61.csiro.au>
Co-authored-by: Axel Heider <axel-h@users.noreply.github.com>
Signed-off-by: Gerwin Klein <gerwin.klein@proofcraft.systems>
2021-08-24 18:04:43 +10:00

82 lines
2.5 KiB
Python

#
# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
#
# SPDX-License-Identifier: GPL-2.0-only
#
from typing import List, Set
import hardware.utils as utils
from hardware.config import Config
from hardware.device import WrappedNode
from hardware.fdt import FdtParser
from hardware.memory import Region
from hardware.utils.rule import KernelRegionGroup
def get_memory_regions(tree: FdtParser):
''' Get all regions with device_type = memory in the tree '''
regions = set()
def visitor(node: WrappedNode):
if node.has_prop('device_type') and node.get_prop('device_type').strings[0] == 'memory':
regions.update(node.get_regions())
tree.visit(visitor)
return regions
def parse_reserved_regions(node: WrappedNode) -> Set[Region]:
''' Parse a reserved-memory node, looking for regions that are
unusable by OS (e.g. reserved for firmware/bootloader) '''
if node is None:
return set()
ret = set()
for child in node:
if child.has_prop('reg') and child.has_prop('no-map'):
ret.update(child.get_regions())
return ret
def reserve_regions(regions: Set[Region], reserved: Set[Region]) -> Set[Region]:
''' Given a set of regions, and a set of reserved regions,
return a new set that is the first set of regions minus the second set. '''
ret = set(regions)
while len(reserved) > 0:
reserve = reserved.pop()
new_ret = set()
for el in ret:
r = el.reserve(reserve)
new_ret.update(r)
ret = new_ret
return ret
def get_physical_memory(tree: FdtParser, config: Config) -> List[Region]:
''' returns a list of regions representing physical memory as used by the kernel '''
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)
return regions, reserved.union(extra_reserved), physBase
def get_addrspace_exclude(regions: List[Region], config: Config):
''' Returns a list of regions that represents the inverse of the given region list. '''
ret = set()
as_max = utils.align_down(config.addrspace_max, config.get_page_bits())
ret.add(Region(0, as_max, None))
for reg in regions:
if type(reg) == KernelRegionGroup:
if reg.user_ok:
continue
new_ret = set()
for el in ret:
new_ret.update(el.reserve(reg))
ret = new_ret
return sorted(ret, key=lambda a: a.base)