mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 17:13:52 +02:00
KVM/arm64 fixes for 7.0, take #3
- Correctly handle deeactivation of out-of-LRs interrupts by starting the EOIcount deactivation walk *after* the last irq that made it into an LR. This avoids deactivating irqs that are in the LRs and that the vcpu hasn't deactivated yet. - Avoid calling into the stubs to probe for ICH_VTR_EL2.TDS when pKVM is already enabled -- not only thhis isn't possible (pKVM will reject the call), but it is also useless: this can only happen for a CPU that has already booted once, and the capability will not change. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEn9UcU+C1Yxj9lZw9I9DQutE9ekMFAmmxpzgACgkQI9DQutE9 ekNFIRAAuJ4wuvElcp8bcgQna59ao7Anjm2pGOXCQ1dJqxfXWyYDnKtaVYko9vZ+ Hp/GewtIyMlf+TNeVse0B8Ys3Y41L/gdedEJdK1jj0T4QOfGKeKXhMc5LYlmWRRv TdYjDu1jQE0vPjFOI0z6fFy37c0huofi3pODkVWh1S4A8bL0/gdycvdmJ41bcDR2 pRP/b31opytXLArW1tUkLyr7JET2Q9PnQISie6ES1pvVoDl4sUcOt1poA3MVNVLA 2X+Tyc8xI9eSDPM4p5ckRtF6Y0+lJUZQN2EAEejIJr9c3NYtomwOhlA2Xv6zFCaZ guA8XFCT5kWwLrcWJmV6WjZeUnVWfJJBI82l5Ft7HEYVSqMIvzWXMTBxt9mPPjXD asUf9rFmGV16Wk63ijagvu58cz16ppukOjPdaUeZfuqG/xzacmIjrZwgYy1QlRKv 5u6+4JrVzRcehC6jEDoQjUK5d98EA0ddl7kaDydjz+oFIpYKVl4MY4bpYyo/JIlI OxoyyhKV4iK+Es+5K9yYeP5C4qHoc6S9IyqnDa9Dgft9NHXNx9pajKgNNLMb3VlR QadWnwVikxqEuUVZqTdwKvT9LOTysz65JmLTdREKlYHlJjYueotIwjVse9voiSkb Eo23Vt2/xnWQoOjTN2UuxA1ZITBAUsRDwMV94y6KMZT1HAwBM3Y= =U7Y3 -----END PGP SIGNATURE----- Merge tag 'kvmarm-fixes-7.0-3' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD KVM/arm64 fixes for 7.0, take #3 - Correctly handle deeactivation of out-of-LRs interrupts by starting the EOIcount deactivation walk *after* the last irq that made it into an LR. This avoids deactivating irqs that are in the LRs and that the vcpu hasn't deactivated yet. - Avoid calling into the stubs to probe for ICH_VTR_EL2.TDS when pKVM is already enabled -- not only thhis isn't possible (pKVM will reject the call), but it is also useless: this can only happen for a CPU that has already booted once, and the capability will not change.
This commit is contained in:
commit
6e827fa2c5
|
|
@ -784,6 +784,9 @@ struct kvm_host_data {
|
|||
/* Number of debug breakpoints/watchpoints for this CPU (minus 1) */
|
||||
unsigned int debug_brps;
|
||||
unsigned int debug_wrps;
|
||||
|
||||
/* Last vgic_irq part of the AP list recorded in an LR */
|
||||
struct vgic_irq *last_lr_irq;
|
||||
};
|
||||
|
||||
struct kvm_host_psci_config {
|
||||
|
|
|
|||
|
|
@ -2345,6 +2345,15 @@ static bool can_trap_icv_dir_el1(const struct arm64_cpu_capabilities *entry,
|
|||
!is_midr_in_range_list(has_vgic_v3))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* pKVM prevents late onlining of CPUs. This means that whatever
|
||||
* state the capability is in after deprivilege cannot be affected
|
||||
* by a new CPU booting -- this is garanteed to be a CPU we have
|
||||
* already seen, and the cap is therefore unchanged.
|
||||
*/
|
||||
if (system_capabilities_finalized() && is_protected_kvm_enabled())
|
||||
return cpus_have_final_cap(ARM64_HAS_ICH_HCR_EL2_TDIR);
|
||||
|
||||
if (is_kernel_in_hyp_mode())
|
||||
res.a1 = read_sysreg_s(SYS_ICH_VTR_EL2);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
|
|||
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
|
||||
struct vgic_v2_cpu_if *cpuif = &vgic_cpu->vgic_v2;
|
||||
u32 eoicount = FIELD_GET(GICH_HCR_EOICOUNT, cpuif->vgic_hcr);
|
||||
struct vgic_irq *irq;
|
||||
struct vgic_irq *irq = *host_data_ptr(last_lr_irq);
|
||||
|
||||
DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());
|
||||
|
||||
|
|
@ -123,7 +123,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
|
|||
vgic_v2_fold_lr(vcpu, cpuif->vgic_lr[lr]);
|
||||
|
||||
/* See the GICv3 equivalent for the EOIcount handling rationale */
|
||||
list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
|
||||
list_for_each_entry_continue(irq, &vgic_cpu->ap_list_head, ap_list) {
|
||||
u32 lr;
|
||||
|
||||
if (!eoicount) {
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
|
|||
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
|
||||
struct vgic_v3_cpu_if *cpuif = &vgic_cpu->vgic_v3;
|
||||
u32 eoicount = FIELD_GET(ICH_HCR_EL2_EOIcount, cpuif->vgic_hcr);
|
||||
struct vgic_irq *irq;
|
||||
struct vgic_irq *irq = *host_data_ptr(last_lr_irq);
|
||||
|
||||
DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());
|
||||
|
||||
|
|
@ -158,12 +158,12 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
|
|||
/*
|
||||
* EOIMode=0: use EOIcount to emulate deactivation. We are
|
||||
* guaranteed to deactivate in reverse order of the activation, so
|
||||
* just pick one active interrupt after the other in the ap_list,
|
||||
* and replay the deactivation as if the CPU was doing it. We also
|
||||
* rely on priority drop to have taken place, and the list to be
|
||||
* sorted by priority.
|
||||
* just pick one active interrupt after the other in the tail part
|
||||
* of the ap_list, past the LRs, and replay the deactivation as if
|
||||
* the CPU was doing it. We also rely on priority drop to have taken
|
||||
* place, and the list to be sorted by priority.
|
||||
*/
|
||||
list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
|
||||
list_for_each_entry_continue(irq, &vgic_cpu->ap_list_head, ap_list) {
|
||||
u64 lr;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -814,6 +814,9 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
|
|||
|
||||
static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (!*host_data_ptr(last_lr_irq))
|
||||
return;
|
||||
|
||||
if (kvm_vgic_global_state.type == VGIC_V2)
|
||||
vgic_v2_fold_lr_state(vcpu);
|
||||
else
|
||||
|
|
@ -960,10 +963,13 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
|
|||
if (irqs_outside_lrs(&als))
|
||||
vgic_sort_ap_list(vcpu);
|
||||
|
||||
*host_data_ptr(last_lr_irq) = NULL;
|
||||
|
||||
list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
|
||||
scoped_guard(raw_spinlock, &irq->irq_lock) {
|
||||
if (likely(vgic_target_oracle(irq) == vcpu)) {
|
||||
vgic_populate_lr(vcpu, irq, count++);
|
||||
*host_data_ptr(last_lr_irq) = irq;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user