Re: [PATCH v2 7/9] KVM: arm64: Allocate hyp vectors statically

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Linux KVM]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux