Changeset View
Changeset View
Standalone View
Standalone View
sys/arm64/arm64/locore.S
Show First 20 Lines • Show All 231 Lines • ▼ Show 20 Lines | mp_virtdone: | ||||
tlbi vmalle1 | tlbi vmalle1 | ||||
dsb sy | dsb sy | ||||
isb | isb | ||||
b init_secondary | b init_secondary | ||||
END(mpentry) | END(mpentry) | ||||
#endif | #endif | ||||
.align 3 | |||||
.globl _C_LABEL(hypmode_enabled) | |||||
_C_LABEL(hypmode_enabled): | |||||
.zero 8 | |||||
/* | /* | ||||
* If we are started in EL2, configure the required hypervisor | * If we are started in EL2, configure the required hypervisor | ||||
* registers and drop to EL1. | * registers and drop to EL1. | ||||
*/ | */ | ||||
drop_to_el1: | drop_to_el1: | ||||
mrs x23, CurrentEL | mrs x23, CurrentEL | ||||
lsr x23, x23, #2 | lsr x23, x23, #2 | ||||
cmp x23, #0x2 | cmp x23, #0x2 | ||||
b.eq 1f | b.eq 1f | ||||
/* We didn't start in EL2, hypmode will remain disabled */ | |||||
ret | ret | ||||
1: | 1: | ||||
/* Configure the Hypervisor */ | /* | ||||
mov x2, #(HCR_RW) | * If the MMU is active, then it is using a page table where VA == PA. | ||||
* But the page table won't have entries for the hypervisor EL2 | |||||
* initialization code which is loaded into memory with the vmm module. | |||||
* | |||||
* So we disable the MMU in EL2 to make the vmm hypervisor code run | |||||
* successfully. | |||||
*/ | |||||
dsb sy | |||||
mrs x2, sctlr_el2 | |||||
bic x2, x2, SCTLR_M | |||||
msr sctlr_el2, x2 | |||||
isb | |||||
/* Enable the HVC Instruction and Make EL1 aarch64 */ | |||||
ldr x2, hcr | |||||
msr hcr_el2, x2 | msr hcr_el2, x2 | ||||
/* Load the Virtualization Process ID Register */ | /* Load the Virtualization Process ID Register */ | ||||
mrs x2, midr_el1 | mrs x2, midr_el1 | ||||
msr vpidr_el2, x2 | msr vpidr_el2, x2 | ||||
/* Load the Virtualization Multiprocess ID Register */ | /* Load the Virtualization Multiprocess ID Register */ | ||||
mrs x2, mpidr_el1 | mrs x2, mpidr_el1 | ||||
Show All 13 Lines | 1: | ||||
/* Enable access to the physical timers at EL1 */ | /* Enable access to the physical timers at EL1 */ | ||||
mrs x2, cnthctl_el2 | mrs x2, cnthctl_el2 | ||||
orr x2, x2, #(CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN) | orr x2, x2, #(CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN) | ||||
msr cnthctl_el2, x2 | msr cnthctl_el2, x2 | ||||
/* Set the counter offset to a known value */ | /* Set the counter offset to a known value */ | ||||
msr cntvoff_el2, xzr | msr cntvoff_el2, xzr | ||||
/* Hypervisor trap functions */ | /* Install hypervisor trap functions */ | ||||
adr x2, hyp_vectors | adrp x2, hyp_stub_vectors | ||||
msr vbar_el2, x2 | msr vbar_el2, x2 | ||||
/* Use the host VTTBR_EL2 to tell the host and the guests apart */ | |||||
mov x2, #VTTBR_HOST | |||||
msr vttbr_el2, x2 | |||||
/* Mark hypervisor mode as enabled */ | |||||
mov x1, #1 | |||||
adr x2, hypmode_enabled | |||||
str x1, [x2] | |||||
mov x2, #(PSR_F | PSR_I | PSR_A | PSR_D | PSR_M_EL1h) | mov x2, #(PSR_F | PSR_I | PSR_A | PSR_D | PSR_M_EL1h) | ||||
msr spsr_el2, x2 | msr spsr_el2, x2 | ||||
/* Configure GICv3 CPU interface */ | /* Configure GICv3 CPU interface */ | ||||
mrs x2, id_aa64pfr0_el1 | mrs x2, id_aa64pfr0_el1 | ||||
/* Extract GIC bits from the register */ | /* Extract GIC bits from the register */ | ||||
ubfx x2, x2, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_BITS | ubfx x2, x2, #ID_AA64PFR0_GIC_SHIFT, #ID_AA64PFR0_GIC_BITS | ||||
/* GIC[3:0] == 0001 - GIC CPU interface via special regs. supported */ | /* GIC[3:0] == 0001 - GIC CPU interface via special regs. supported */ | ||||
cmp x2, #(ID_AA64PFR0_GIC_CPUIF_EN >> ID_AA64PFR0_GIC_SHIFT) | cmp x2, #(ID_AA64PFR0_GIC_CPUIF_EN >> ID_AA64PFR0_GIC_SHIFT) | ||||
b.ne 2f | b.ne 2f | ||||
mrs x2, icc_sre_el2 | mrs x2, icc_sre_el2 | ||||
orr x2, x2, #ICC_SRE_EL2_EN /* Enable access from insecure EL1 */ | orr x2, x2, #ICC_SRE_EL2_EN /* Enable access from insecure EL1 */ | ||||
orr x2, x2, #ICC_SRE_EL2_SRE /* Enable system registers */ | orr x2, x2, #ICC_SRE_EL2_SRE /* Enable system registers */ | ||||
msr icc_sre_el2, x2 | msr icc_sre_el2, x2 | ||||
2: | 2: | ||||
/* Set the address to return to our return address */ | /* Set the address to return to our return address */ | ||||
msr elr_el2, x30 | msr elr_el2, x30 | ||||
isb | isb | ||||
eret | eret | ||||
.align 3 | .align 3 | ||||
.Lsctlr_res1: | .Lsctlr_res1: | ||||
.quad SCTLR_RES1 | .quad SCTLR_RES1 | ||||
#define VECT_EMPTY \ | hcr: | ||||
.align 7; \ | /* Make sure the HVC instruction is not disabled */ | ||||
1: b 1b | .quad (HCR_RW & ~HCR_HCD) | ||||
.align 11 | |||||
hyp_vectors: | |||||
VECT_EMPTY /* Synchronous EL2t */ | |||||
VECT_EMPTY /* IRQ EL2t */ | |||||
VECT_EMPTY /* FIQ EL2t */ | |||||
VECT_EMPTY /* Error EL2t */ | |||||
VECT_EMPTY /* Synchronous EL2h */ | |||||
VECT_EMPTY /* IRQ EL2h */ | |||||
VECT_EMPTY /* FIQ EL2h */ | |||||
VECT_EMPTY /* Error EL2h */ | |||||
VECT_EMPTY /* Synchronous 64-bit EL1 */ | |||||
VECT_EMPTY /* IRQ 64-bit EL1 */ | |||||
VECT_EMPTY /* FIQ 64-bit EL1 */ | |||||
VECT_EMPTY /* Error 64-bit EL1 */ | |||||
VECT_EMPTY /* Synchronous 32-bit EL1 */ | |||||
VECT_EMPTY /* IRQ 32-bit EL1 */ | |||||
VECT_EMPTY /* FIQ 32-bit EL1 */ | |||||
VECT_EMPTY /* Error 32-bit EL1 */ | |||||
/* | /* | ||||
* Get the delta between the physical address we were loaded to and the | * Get the delta between the physical address we were loaded to and the | ||||
* virtual address we expect to run from. This is used when building the | * virtual address we expect to run from. This is used when building the | ||||
* initial page table. | * initial page table. | ||||
*/ | */ | ||||
get_virt_delta: | get_virt_delta: | ||||
/* Load the physical address of virt_map */ | /* Load the physical address of virt_map */ | ||||
▲ Show 20 Lines • Show All 507 Lines • Show Last 20 Lines |