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>
82 lines
2.5 KiB
Python
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)
|