1230557Sjimharris/*
2230557Sjimharris * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3230557Sjimharris *
4230557Sjimharris * SPDX-License-Identifier: GPL-2.0-only
5230557Sjimharris */
6230557Sjimharris
7230557Sjimharris#include <autoconf.h>
8230557Sjimharris#include <elfloader/gen_config.h>
9230557Sjimharris#include <types.h>
10230557Sjimharris#include <elfloader.h>
11230557Sjimharris#include <mode/structures.h>
12230557Sjimharris#include <printf.h>
13230557Sjimharris#include <abort.h>
14230557Sjimharris
15230557Sjimharris/*
16230557Sjimharris* Create a "boot" page table, which contains a 1:1 mapping below
17230557Sjimharris* the kernel's first vaddr, and a virtual-to-physical mapping above the
18230557Sjimharris* kernel's first vaddr.
19230557Sjimharris*/
20230557Sjimharrisvoid init_boot_vspace(struct image_info *kernel_info)
21230557Sjimharris{
22230557Sjimharris    word_t i;
23230557Sjimharris
24230557Sjimharris    vaddr_t first_vaddr = kernel_info->virt_region_start;
25230557Sjimharris    vaddr_t last_vaddr = kernel_info->virt_region_end;
26230557Sjimharris    paddr_t first_paddr = kernel_info->phys_region_start;
27230557Sjimharris
28230557Sjimharris    _boot_pgd_down[0] = ((uintptr_t)_boot_pud_down) | BIT(1) | BIT(0); /* its a page table */
29230557Sjimharris
30230557Sjimharris    for (i = 0; i < BIT(PUD_BITS); i++) {
31230557Sjimharris        _boot_pud_down[i] = (i << ARM_1GB_BLOCK_BITS)
32230557Sjimharris                            | BIT(10) /* access flag */
33230557Sjimharris                            | (0 << 2) /* strongly ordered memory */
34230557Sjimharris                            | BIT(0); /* 1G block */
35230557Sjimharris    }
36230557Sjimharris
37230557Sjimharris    _boot_pgd_up[GET_PGD_INDEX(first_vaddr)]
38230557Sjimharris        = ((uintptr_t)_boot_pud_up) | BIT(1) | BIT(0); /* its a page table */
39230557Sjimharris
40230557Sjimharris    _boot_pud_up[GET_PUD_INDEX(first_vaddr)]
41230557Sjimharris        = ((uintptr_t)_boot_pmd_up) | BIT(1) | BIT(0); /* its a page table */
42230557Sjimharris
43230557Sjimharris    /* We only map in 1 GiB, so check that the kernel doesn't cross 1GiB boundary. */
44230557Sjimharris    if ((first_vaddr & ~MASK(ARM_1GB_BLOCK_BITS)) != (last_vaddr & ~MASK(ARM_1GB_BLOCK_BITS))) {
45230557Sjimharris        printf("We only map 1GiB, but kernel vaddr range covers multiple GiB.\n");
46230557Sjimharris        abort();
47230557Sjimharris    }
48230557Sjimharris    for (i = GET_PMD_INDEX(first_vaddr); i < BIT(PMD_BITS); i++) {
49230557Sjimharris        _boot_pmd_up[i] = first_paddr
50230557Sjimharris                          | BIT(10) /* access flag */
51230557Sjimharris#if CONFIG_MAX_NUM_NODES > 1
52230557Sjimharris                          | (3 << 8) /* make sure the shareability is the same as the kernel's */
53230557Sjimharris#endif
54230557Sjimharris                          | (4 << 2) /* MT_NORMAL memory */
55230557Sjimharris                          | BIT(0); /* 2M block */
56230557Sjimharris        first_paddr += BIT(ARM_2MB_BLOCK_BITS);
57230557Sjimharris    }
58230557Sjimharris}
59230557Sjimharris
60230557Sjimharrisvoid init_hyp_boot_vspace(struct image_info *kernel_info)
61230557Sjimharris{
62230557Sjimharris    word_t i;
63230557Sjimharris    word_t pmd_index;
64230557Sjimharris    vaddr_t first_vaddr = kernel_info->virt_region_start;
65230557Sjimharris    paddr_t first_paddr = kernel_info->phys_region_start;
66230557Sjimharris    _boot_pgd_down[0] = ((uintptr_t)_boot_pud_down) | BIT(1) | BIT(0);
67230557Sjimharris
68230557Sjimharris    for (i = 0; i < BIT(PUD_BITS); i++) {
69230557Sjimharris        _boot_pud_down[i] = (i << ARM_1GB_BLOCK_BITS)
70230557Sjimharris                            | BIT(10) /* access flag */
71230557Sjimharris                            | (0 << 2) /* strongly ordered memory */
72230557Sjimharris                            | BIT(0); /* 1G block */
73230557Sjimharris    }
74230557Sjimharris
75230557Sjimharris    _boot_pgd_down[GET_PGD_INDEX(first_vaddr)]
76230557Sjimharris        = ((uintptr_t)_boot_pud_up) | BIT(1) | BIT(0); /* its a page table */
77230557Sjimharris
78230557Sjimharris    _boot_pud_up[GET_PUD_INDEX(first_vaddr)]
79230557Sjimharris        = ((uintptr_t)_boot_pmd_up) | BIT(1) | BIT(0); /* its a page table */
80230557Sjimharris
81230557Sjimharris    pmd_index = GET_PMD_INDEX(first_vaddr);
82230557Sjimharris    for (i = pmd_index; i < BIT(PMD_BITS); i++) {
83230557Sjimharris        _boot_pmd_up[i] = (((i - pmd_index) << ARM_2MB_BLOCK_BITS) + first_paddr)
84230557Sjimharris                          | BIT(10) /* access flag */
85230557Sjimharris#if CONFIG_MAX_NUM_NODES > 1
86230557Sjimharris                          | (3 << 8)
87230557Sjimharris#endif
88230557Sjimharris                          | (4 << 2) /* MT_NORMAL memory */
89230557Sjimharris                          | BIT(0); /* 2M block */
90230557Sjimharris    }
91230557Sjimharris}
92230557Sjimharris