FROMLIST: KVM: arm64: Initialize kvm_nvhe_init_params early
Move the initialization of kvm_nvhe_init_params in a dedicated function that is run early, and only once during KVM init, rather than every time the KVM vectors are set and reset. This also opens the opportunity for the hypervisor to change the init structs during boot, hence simplifying the replacement of host-provided page-table by the one the hypervisor will create for itself. Acked-by: Will Deacon <will@kernel.org> Signed-off-by: Quentin Perret <qperret@google.com> Link: https://lore.kernel.org/r/20210315143536.214621-5-qperret@google.com Bug: 178098380 Change-Id: I83ee2ac4889ce39f8d02da1d9682f813713a1540
This commit is contained in:
@@ -1397,22 +1397,18 @@ static int kvm_init_vector_slots(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpu_init_hyp_mode(void)
|
static void cpu_prepare_hyp_mode(int cpu)
|
||||||
{
|
{
|
||||||
struct kvm_nvhe_init_params *params = this_cpu_ptr_nvhe_sym(kvm_init_params);
|
struct kvm_nvhe_init_params *params = per_cpu_ptr_nvhe_sym(kvm_init_params, cpu);
|
||||||
struct arm_smccc_res res;
|
|
||||||
unsigned long tcr;
|
unsigned long tcr;
|
||||||
|
|
||||||
/* Switch from the HYP stub to our own HYP init vector */
|
|
||||||
__hyp_set_vectors(kvm_get_idmap_vector());
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate the raw per-cpu offset without a translation from the
|
* Calculate the raw per-cpu offset without a translation from the
|
||||||
* kernel's mapping to the linear mapping, and store it in tpidr_el2
|
* kernel's mapping to the linear mapping, and store it in tpidr_el2
|
||||||
* so that we can use adr_l to access per-cpu variables in EL2.
|
* so that we can use adr_l to access per-cpu variables in EL2.
|
||||||
* Also drop the KASAN tag which gets in the way...
|
* Also drop the KASAN tag which gets in the way...
|
||||||
*/
|
*/
|
||||||
params->tpidr_el2 = (unsigned long)kasan_reset_tag(this_cpu_ptr_nvhe_sym(__per_cpu_start)) -
|
params->tpidr_el2 = (unsigned long)kasan_reset_tag(per_cpu_ptr_nvhe_sym(__per_cpu_start, cpu)) -
|
||||||
(unsigned long)kvm_ksym_ref(CHOOSE_NVHE_SYM(__per_cpu_start));
|
(unsigned long)kvm_ksym_ref(CHOOSE_NVHE_SYM(__per_cpu_start));
|
||||||
|
|
||||||
params->mair_el2 = read_sysreg(mair_el1);
|
params->mair_el2 = read_sysreg(mair_el1);
|
||||||
@@ -1436,7 +1432,7 @@ static void cpu_init_hyp_mode(void)
|
|||||||
tcr |= (idmap_t0sz & GENMASK(TCR_TxSZ_WIDTH - 1, 0)) << TCR_T0SZ_OFFSET;
|
tcr |= (idmap_t0sz & GENMASK(TCR_TxSZ_WIDTH - 1, 0)) << TCR_T0SZ_OFFSET;
|
||||||
params->tcr_el2 = tcr;
|
params->tcr_el2 = tcr;
|
||||||
|
|
||||||
params->stack_hyp_va = kern_hyp_va(__this_cpu_read(kvm_arm_hyp_stack_page) + PAGE_SIZE);
|
params->stack_hyp_va = kern_hyp_va(per_cpu(kvm_arm_hyp_stack_page, cpu) + PAGE_SIZE);
|
||||||
params->pgd_pa = kvm_mmu_get_httbr();
|
params->pgd_pa = kvm_mmu_get_httbr();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1444,6 +1440,15 @@ static void cpu_init_hyp_mode(void)
|
|||||||
* be read while the MMU is off.
|
* be read while the MMU is off.
|
||||||
*/
|
*/
|
||||||
kvm_flush_dcache_to_poc(params, sizeof(*params));
|
kvm_flush_dcache_to_poc(params, sizeof(*params));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cpu_init_hyp_mode(void)
|
||||||
|
{
|
||||||
|
struct kvm_nvhe_init_params *params;
|
||||||
|
struct arm_smccc_res res;
|
||||||
|
|
||||||
|
/* Switch from the HYP stub to our own HYP init vector */
|
||||||
|
__hyp_set_vectors(kvm_get_idmap_vector());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call initialization code, and switch to the full blown HYP code.
|
* Call initialization code, and switch to the full blown HYP code.
|
||||||
@@ -1452,6 +1457,7 @@ static void cpu_init_hyp_mode(void)
|
|||||||
* cpus_have_const_cap() wrapper.
|
* cpus_have_const_cap() wrapper.
|
||||||
*/
|
*/
|
||||||
BUG_ON(!system_capabilities_finalized());
|
BUG_ON(!system_capabilities_finalized());
|
||||||
|
params = this_cpu_ptr_nvhe_sym(kvm_init_params);
|
||||||
arm_smccc_1_1_hvc(KVM_HOST_SMCCC_FUNC(__kvm_hyp_init), virt_to_phys(params), &res);
|
arm_smccc_1_1_hvc(KVM_HOST_SMCCC_FUNC(__kvm_hyp_init), virt_to_phys(params), &res);
|
||||||
WARN_ON(res.a0 != SMCCC_RET_SUCCESS);
|
WARN_ON(res.a0 != SMCCC_RET_SUCCESS);
|
||||||
|
|
||||||
@@ -1799,19 +1805,19 @@ static int init_hyp_mode(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Map Hyp percpu pages
|
|
||||||
*/
|
|
||||||
for_each_possible_cpu(cpu) {
|
for_each_possible_cpu(cpu) {
|
||||||
char *percpu_begin = (char *)kvm_arm_hyp_percpu_base[cpu];
|
char *percpu_begin = (char *)kvm_arm_hyp_percpu_base[cpu];
|
||||||
char *percpu_end = percpu_begin + nvhe_percpu_size();
|
char *percpu_end = percpu_begin + nvhe_percpu_size();
|
||||||
|
|
||||||
|
/* Map Hyp percpu pages */
|
||||||
err = create_hyp_mappings(percpu_begin, percpu_end, PAGE_HYP);
|
err = create_hyp_mappings(percpu_begin, percpu_end, PAGE_HYP);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
kvm_err("Cannot map hyp percpu region\n");
|
kvm_err("Cannot map hyp percpu region\n");
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prepare the CPU initialization parameters */
|
||||||
|
cpu_prepare_hyp_mode(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_protected_kvm_enabled()) {
|
if (is_protected_kvm_enabled()) {
|
||||||
|
Reference in New Issue
Block a user