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.arch == 'riscv': # RISC-V is special: it expects physBase to be # the address that the bootloader is loaded at. physBase = ret[0].base if config.get_bootloader_reserve() > 0: resv = Region(ret[0].base, config.get_bootloader_reserve(), None) extra_reserved.add(resv) ret[0].base += config.get_bootloader_reserve() ret[0].size -= config.get_bootloader_reserve() 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, None) extra_reserved.add(resv) ret[0] = new if config.arch != 'riscv': # ARM (and presumably other architectures) # want physBase to be the physical load address of the kernel. physBase = ret[0].base return ret, extra_reserved, physBase
def __init__(self, region: Region, kernel_name: str, page_bits: int, max_size: int, condition_macro: str = None, user_ok: bool = False): self.macro = condition_macro self.desc = region.owner.path if region.owner else 'dynamically generated region' self.kernel_offset = -1 self.page_bits = page_bits self.labels = {} # dict of label => offset within region. self.user_ok = user_ok region.size = min(max_size, region.size) aligned = region.align_size(page_bits) self.size = aligned.size self.base = aligned.base self.regions = aligned.make_chunks(1 << page_bits) self.labels[kernel_name] = region.base - aligned.base
def merge_memory_regions(regions: Set[Region]) -> Set[Region]: ''' Check all region and merge adjacent ones ''' all_regions = [ dict(idx=idx, region=region, right_adj=None, left_adj=None) for (idx, region) in enumerate(regions) ] # Find all right contiguous regions for dreg in all_regions: for dnreg in all_regions[dreg['idx'] + 1:]: if dreg['region'].owner == dnreg['region'].owner: if dnreg['region'].base == dreg['region'].base + dreg[ 'region'].size: dreg['right_adj'] = dnreg dnreg['left_adj'] = dreg elif dreg['region'].base == dnreg['region'].base + dnreg[ 'region'].size: dnreg['right_adj'] = dreg dreg['left_adj'] = dnreg # Find all the left-most contiguous regions contiguous_regions = set() for reg in all_regions: if reg['left_adj'] is None: size = reg['region'].size r_adj = reg['right_adj'] while r_adj is not None: size += r_adj['region'].size r_adj = r_adj['right_adj'] contiguous_regions.add( Region(reg['region'].base, size, reg['region'].owner)) return contiguous_regions
def get_regions(self) -> List[Region]: if 'reg' not in self.props: return [] reg = [] prop = list(self.props['reg'].words) sizes = (self.parent.get_addr_cells(), self.parent.get_size_cells()) for r in Utils.intarray_iter(prop, sizes): reg.append( Region(self.parent._translate_child_address(r[0]), r[1], self)) return reg
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
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_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)
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() # We can't create untypeds that exceed the addrspace_max, so we round down to the smallest # untyped size alignment so that the kernel will be able to turn the entire range into untypeds. as_max = hardware.utils.align_down( config.addrspace_max, config.get_smallest_kernel_object_alignment()) ret.add(Region(0, as_max)) 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)