mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 04:31:50 +00:00
Merge branch kvm-arm64/apple-vgic-mi into kvmarm/next
* kvm-arm64/apple-vgic-mi: : VGIC maintenance interrupt support for the AIC, courtesy of Marc Zyngier. : : The AIC provides a non-maskable VGIC maintenance interrupt, which until : now was not supported by KVM. This series (1) allows the registration of : a non-maskable maintenance interrupt and (2) wires in support for this : with the AIC driver. irqchip/apple-aic: Correctly map the vgic maintenance interrupt irqchip/apple-aic: Register vgic maintenance interrupt with KVM KVM: arm64: vgic: Allow registration of a non-maskable maintenance interrupt Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
This commit is contained in:
commit
e4f7417e96
@ -570,7 +570,7 @@ int kvm_vgic_hyp_init(void)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!has_mask)
|
||||
if (!has_mask && !kvm_vgic_global_state.maint_irq)
|
||||
return 0;
|
||||
|
||||
ret = request_percpu_irq(kvm_vgic_global_state.maint_irq,
|
||||
|
@ -210,7 +210,6 @@
|
||||
FIELD_PREP(AIC_EVENT_NUM, x))
|
||||
#define AIC_HWIRQ_IRQ(x) FIELD_GET(AIC_EVENT_NUM, x)
|
||||
#define AIC_HWIRQ_DIE(x) FIELD_GET(AIC_EVENT_DIE, x)
|
||||
#define AIC_NR_FIQ 6
|
||||
#define AIC_NR_SWIPI 32
|
||||
|
||||
/*
|
||||
@ -222,11 +221,18 @@
|
||||
* running at EL2 (with VHE). When the kernel is running at EL1, the
|
||||
* mapping differs and aic_irq_domain_translate() performs the remapping.
|
||||
*/
|
||||
|
||||
#define AIC_TMR_EL0_PHYS AIC_TMR_HV_PHYS
|
||||
#define AIC_TMR_EL0_VIRT AIC_TMR_HV_VIRT
|
||||
#define AIC_TMR_EL02_PHYS AIC_TMR_GUEST_PHYS
|
||||
#define AIC_TMR_EL02_VIRT AIC_TMR_GUEST_VIRT
|
||||
enum fiq_hwirq {
|
||||
/* Must be ordered as in apple-aic.h */
|
||||
AIC_TMR_EL0_PHYS = AIC_TMR_HV_PHYS,
|
||||
AIC_TMR_EL0_VIRT = AIC_TMR_HV_VIRT,
|
||||
AIC_TMR_EL02_PHYS = AIC_TMR_GUEST_PHYS,
|
||||
AIC_TMR_EL02_VIRT = AIC_TMR_GUEST_VIRT,
|
||||
AIC_CPU_PMU_Effi = AIC_CPU_PMU_E,
|
||||
AIC_CPU_PMU_Perf = AIC_CPU_PMU_P,
|
||||
/* No need for this to be discovered from DT */
|
||||
AIC_VGIC_MI,
|
||||
AIC_NR_FIQ
|
||||
};
|
||||
|
||||
static DEFINE_STATIC_KEY_TRUE(use_fast_ipi);
|
||||
|
||||
@ -384,14 +390,20 @@ static void __exception_irq_entry aic_handle_irq(struct pt_regs *regs)
|
||||
|
||||
/*
|
||||
* vGIC maintenance interrupts end up here too, so we need to check
|
||||
* for them separately. This should never trigger if KVM is working
|
||||
* properly, because it will have already taken care of clearing it
|
||||
* on guest exit before this handler runs.
|
||||
* for them separately. It should however only trigger when NV is
|
||||
* in use, and be cleared when coming back from the handler.
|
||||
*/
|
||||
if (is_kernel_in_hyp_mode() && (read_sysreg_s(SYS_ICH_HCR_EL2) & ICH_HCR_EN) &&
|
||||
read_sysreg_s(SYS_ICH_MISR_EL2) != 0) {
|
||||
pr_err_ratelimited("vGIC IRQ fired and not handled by KVM, disabling.\n");
|
||||
sysreg_clear_set_s(SYS_ICH_HCR_EL2, ICH_HCR_EN, 0);
|
||||
if (is_kernel_in_hyp_mode() &&
|
||||
(read_sysreg_s(SYS_ICH_HCR_EL2) & ICH_HCR_EN) &&
|
||||
read_sysreg_s(SYS_ICH_MISR_EL2) != 0) {
|
||||
generic_handle_domain_irq(aic_irqc->hw_domain,
|
||||
AIC_FIQ_HWIRQ(AIC_VGIC_MI));
|
||||
|
||||
if (unlikely((read_sysreg_s(SYS_ICH_HCR_EL2) & ICH_HCR_EN) &&
|
||||
read_sysreg_s(SYS_ICH_MISR_EL2))) {
|
||||
pr_err_ratelimited("vGIC IRQ fired and not handled by KVM, disabling.\n");
|
||||
sysreg_clear_set_s(SYS_ICH_HCR_EL2, ICH_HCR_EN, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1178,6 +1190,21 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p
|
||||
"irqchip/apple-aic/ipi:starting",
|
||||
aic_init_cpu, NULL);
|
||||
|
||||
if (is_kernel_in_hyp_mode()) {
|
||||
struct irq_fwspec mi = {
|
||||
.fwnode = of_node_to_fwnode(node),
|
||||
.param_count = 3,
|
||||
.param = {
|
||||
[0] = AIC_FIQ, /* This is a lie */
|
||||
[1] = AIC_VGIC_MI,
|
||||
[2] = IRQ_TYPE_LEVEL_HIGH,
|
||||
},
|
||||
};
|
||||
|
||||
vgic_info.maint_irq = irq_create_fwspec_mapping(&mi);
|
||||
WARN_ON(!vgic_info.maint_irq);
|
||||
}
|
||||
|
||||
vgic_set_kvm_info(&vgic_info);
|
||||
|
||||
pr_info("Initialized with %d/%d IRQs * %d/%d die(s), %d FIQs, %d vIPIs",
|
||||
|
Loading…
Reference in New Issue
Block a user