1#
2# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3#
4# SPDX-License-Identifier: GPL-2.0-only
5#
6from typing import List, Set
7from hardware.memory import Region
8
9
10class Config:
11    ''' Abstract config class '''
12    arch = 'unknown'
13
14    def __init__(self, addrspace_max):
15        self.addrspace_max = addrspace_max
16
17    def get_kernel_phys_align(self) -> int:
18        ''' Used to align the base of physical memory. Returns alignment size in bits. '''
19        return 0
20
21    def get_bootloader_reserve(self) -> int:
22        ''' Used to reserve a fixed amount of memory for the bootloader. Offsets
23            the kernel load address by the amount returned in bytes. '''
24        return 0
25
26    def get_page_bits(self) -> int:
27        ''' Get page size in bits for this arch '''
28        return 12  # 4096-byte pages
29
30    def get_smallest_kernel_object_alignment(self) -> int:
31        return 4  # seL4_MinUntypedBits is 4 for all configurations
32
33    def get_device_page_bits(self) -> int:
34        ''' Get page size in bits for mapping devices for this arch '''
35        return self.get_page_bits()
36
37    def align_memory(self, regions: Set[Region]) -> List[Region]:
38        ''' Given a set of regions, sort them and align the first so that the
39        ELF loader will be able to load the kernel into it. Will return the
40        aligned memory region list, a set of any regions of memory that were
41        aligned out and the physBase value that the kernel will use. memory
42        region list, a set of any regions of memory that were aligned out and
43        the physBase value that the kernel will use. '''
44        pass
45
46
47class ARMConfig(Config):
48    ''' Config class for ARM '''
49    SUPERSECTION_BITS = 24
50    arch = 'arm'
51
52    def get_kernel_phys_align(self) -> int:
53        ''' on ARM the ELF loader expects to be able to map a supersection page to load the kernel. '''
54        return self.SUPERSECTION_BITS
55
56    def align_memory(self, regions: Set[Region]) -> List[Region]:
57        ''' Arm wants physBase to be the physical load address of the kernel. '''
58        ret = sorted(regions)
59        extra_reserved = set()
60
61        new = ret[0].align_base(self.get_kernel_phys_align())
62        resv = Region(ret[0].base, new.base - ret[0].base)
63        extra_reserved.add(resv)
64        ret[0] = new
65
66        physBase = ret[0].base
67
68        return ret, extra_reserved, physBase
69
70
71class RISCVConfig(Config):
72    ''' Config class for RISCV '''
73    MEGA_PAGE_SIZE = 0x200000
74    arch = 'riscv'
75
76    def get_bootloader_reserve(self) -> int:
77        ''' on RISC-V OpenSBI is loaded at the start
78        of physical memory. Mark it as unavailable. '''
79        return self.MEGA_PAGE_SIZE
80
81    def align_memory(self, regions: Set[Region]) -> List[Region]:
82        ''' Currently the RISC-V port expects physBase to be the address that the
83        bootloader is loaded at. To be generalised in the future. '''
84        ret = sorted(regions)
85        extra_reserved = set()
86
87        physBase = ret[0].base
88
89        resv = Region(ret[0].base, self.get_bootloader_reserve())
90        extra_reserved.add(resv)
91        ret[0].base += self.get_bootloader_reserve()
92        ret[0].size -= self.get_bootloader_reserve()
93
94        return ret, extra_reserved, physBase
95
96    def get_device_page_bits(self) -> int:
97        ''' Get page size in bits for mapping devices for this arch '''
98        if self.addrspace_max > (1 << 32):
99            # rv39 and rv48 use 2MiB device pages
100            return 21
101        else:
102            # rv32 uses 4MiB device pages
103            return 22
104
105
106def get_arch_config(arch: str, addrspace_max: int) -> Config:
107    ''' Return an appropriate Config object for the given architecture '''
108    if arch == 'arm':
109        return ARMConfig(addrspace_max)
110    elif arch == 'riscv':
111        return RISCVConfig(addrspace_max)
112    raise ValueError('Unsupported arch specified.')
113