On Thu, Nov 12, 2020 at 11:07:55AM +0000, Marc Zyngier wrote: > On 2020-11-09 21:47, Will Deacon wrote: > > The EL2 vectors installed when a guest is running point at one of the > > following configurations for a given CPU: > > > > - Straight at __kvm_hyp_vector > > - A trampoline containing an SMC sequence to mitigate Spectre-v2 and > > then a direct branch to __kvm_hyp_vector > > - A dynamically-allocated trampoline which has an indirect branch to > > __kvm_hyp_vector > > - A dynamically-allocated trampoline containing an SMC sequence to > > mitigate Spectre-v2 and then an indirect branch to __kvm_hyp_vector > > > > The indirect branches mean that VA randomization at EL2 isn't trivially > > bypassable using Spectre-v3a (where the vector base is readable by the > > guest). > > > > Rather than populate these vectors dynamically, configure everything > > statically and use an enumerated type to identify the vector "slot" > > corresponding to one of the configurations above. This both simplifies > > the code, but also makes it much easier to implement at EL2 later on. > > This series terminally breaks VHE (the host locks up on the first guest > run, CPU is nowhere to be seen again). Whoops, sorry about that. I'll look into it. > I have a hunch about what is happening, see below. > > [...] > > > @@ -1406,24 +1401,9 @@ static void cpu_hyp_reset(void) > > static void cpu_set_hyp_vector(void) > > { > > struct bp_hardening_data *data = this_cpu_ptr(&bp_hardening_data); > > - void *vect = kern_hyp_va(kvm_ksym_ref(__kvm_hyp_vector)); > > - int slot = -1; > > - > > - if (cpus_have_const_cap(ARM64_SPECTRE_V2) && data->fn) { > > - vect = kern_hyp_va(kvm_ksym_ref(__bp_harden_hyp_vecs)); > > - slot = data->hyp_vectors_slot; > > - } > > - > > - if (this_cpu_has_cap(ARM64_HARDEN_EL2_VECTORS) && !has_vhe()) { > > - vect = __kvm_bp_vect_base; > > - if (slot == -1) > > - slot = __kvm_harden_el2_vector_slot; > > - } > > - > > - if (slot != -1) > > - vect += slot * SZ_2K; > > + void *vector = hyp_spectre_vector_selector[data->slot]; > > > > - *this_cpu_ptr_hyp_sym(kvm_hyp_vector) = (unsigned long)vect; > > + *this_cpu_ptr_hyp_sym(kvm_hyp_vector) = (unsigned long)vector; > > } > > > > static void cpu_hyp_reinit(void) > > @@ -1661,9 +1641,9 @@ static int init_hyp_mode(void) > > goto out_err; > > } > > > > - err = kvm_map_vectors(); > > + err = kvm_init_vector_slots(); > > Here, you have turned the mapping of the vectors into the full > init+map. The mapping makes no sense on VHE, but the initialization > does matter! init_hyp_mode() being only called on non-VHE, the HYP > vectors are never initialized. Too bad. Yeah, that certainly smells bad. I'll hack at it now and post a v3 when it comes back to life. Cheers, Will _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/mailman/listinfo/kvmarm