1#
2# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3#
4# SPDX-License-Identifier: GPL-2.0-only
5#
6
7
8class Config:
9    ''' Abstract config class '''
10    arch = 'unknown'
11
12    def __init__(self, addrspace_max):
13        self.addrspace_max = addrspace_max
14
15    def get_kernel_phys_align(self) -> int:
16        ''' Used to align the base of physical memory. Returns alignment size in bits. '''
17        return 0
18
19    def get_bootloader_reserve(self) -> int:
20        ''' Used to reserve a fixed amount of memory for the bootloader. Offsets
21            the kernel load address by the amount returned in bytes. '''
22        return 0
23
24    def get_page_bits(self) -> int:
25        ''' Get page size in bits for this arch '''
26        return 12  # 4096-byte pages
27
28    def get_device_page_bits(self) -> int:
29        ''' Get page size in bits for mapping devices for this arch '''
30        return self.get_page_bits()
31
32
33class ARMConfig(Config):
34    ''' Config class for ARM '''
35    SUPERSECTION_BITS = 24
36    arch = 'arm'
37
38    def get_kernel_phys_align(self) -> int:
39        ''' on ARM the ELF loader expects to be able to map a supersection page to load the kernel. '''
40        return self.SUPERSECTION_BITS
41
42
43class RISCVConfig(Config):
44    ''' Config class for RISCV '''
45    MEGA_PAGE_SIZE = 0x200000
46    arch = 'riscv'
47
48    def get_bootloader_reserve(self) -> int:
49        ''' on RISC-V the BBL is loaded at the start
50        of physical memory. Mark it as unavailable. '''
51        return self.MEGA_PAGE_SIZE
52
53    def get_device_page_bits(self) -> int:
54        ''' Get page size in bits for mapping devices for this arch '''
55        if self.addrspace_max > (1 << 32):
56            # rv39 and rv48 use 2MiB device pages
57            return 21
58        else:
59            # rv32 uses 4MiB device pages
60            return 22
61
62
63def get_arch_config(arch: str, addrspace_max: int) -> Config:
64    ''' Return an appropriate Config object for the given architecture '''
65    if arch == 'arm':
66        return ARMConfig(addrspace_max)
67    elif arch == 'riscv':
68        return RISCVConfig(addrspace_max)
69    raise ValueError('Unsupported arch specified.')
70