blob: 5de25edba385d9de2a2cd20512006409b7fd6ebe [file]
/*
* Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: GPL-2.0-only
*/
#include <types.h>
#include <elfloader.h>
#include <mode/structures.h>
#define ARM_VECTOR_TABLE 0xffff0000
extern char arm_vector_table[1];
/*
* Create a "boot" page directory, which contains a 1:1 mapping below
* the kernel's first vaddr, and a virtual-to-physical mapping above the
* kernel's first vaddr.
*/
void init_boot_vspace(struct image_info *kernel_info)
{
uint32_t i;
vaddr_t first_vaddr = kernel_info->virt_region_start;
paddr_t first_paddr = kernel_info->phys_region_start;
/* identity mapping below kernel window */
for (i = 0; i < (first_vaddr >> ARM_SECTION_BITS); i++) {
_boot_pd[i] = (i << ARM_SECTION_BITS)
| BIT(10) /* kernel-only access */
| BIT(1); /* 1M section */
}
/* mapping of kernel window, except last 1M*/
for (i = 0; i < ((-first_vaddr) >> ARM_SECTION_BITS) - 1; i++) {
_boot_pd[i + (first_vaddr >> ARM_SECTION_BITS)]
= ((i << ARM_SECTION_BITS) + first_paddr)
| BIT(10) /* kernel-only access */
| BIT(1); /* 1M section */
}
/* map page table covering last 1M of virtual address space to page directory */
_boot_pd[i + (first_vaddr >> ARM_SECTION_BITS)]
= ((uintptr_t)_boot_pt)
| BIT(9)
| BIT(0); /* page table */
/* map vector table */
_boot_pt[GET_PT_INDEX(ARM_VECTOR_TABLE)]
= ((uintptr_t)arm_vector_table)
| BIT(4) /* kernel-only access */
| BIT(1); /* 4K page */
}
/**
* Performs the same operation as init_boot_pd, but initialises
* the LPAE page table. In this case, 3 L2 tables are concatenated.
* PGD entries point to the appropriate L2 table.
*/
void init_hyp_boot_vspace(struct image_info *kernel_info)
{
uint32_t i, k;
vaddr_t first_vaddr = kernel_info->virt_region_start;
paddr_t first_paddr = kernel_info->phys_region_start;
/* Map in L2 page tables */
for (i = 0; i < 4; i++) {
_lpae_boot_pgd[i] = ((uintptr_t)_lpae_boot_pmd + (i << PAGE_BITS))
| BIT(1) /* Page table */
| BIT(0); /* Valid */
}
/* identity mapping below kernel window */
for (i = 0; i < (first_vaddr >> ARM_2MB_BLOCK_BITS); i++) {
_lpae_boot_pmd[i] = (i << ARM_2MB_BLOCK_BITS)
| BIT(10) /* AF - Not always HW managed */
| BIT(0); /* Valid */
}
/* mapping of kernel window */
for (k = 0; k < ((-first_vaddr) >> ARM_2MB_BLOCK_BITS); k++) {
_lpae_boot_pmd[i + k] = ((k << ARM_2MB_BLOCK_BITS) + first_paddr)
| BIT(10) /* AF - Not always HW managed */
| BIT(0); /* Valid */
}
}