Skip to content

Commit 32e92b7

Browse files
author
Marc Zyngier
committed
Merge branch kvm-arm64/m1 into kvmarm-master/next
Rework the KVM GIC and timer to cope with lesser HW such as the Apple M1 SoC. * kvm-arm64/m1: irqchip/apple-aic: Advertise some level of vGICv3 compatibility KVM: arm64: timer: Add support for SW-based deactivation KVM: arm64: timer: Refactor IRQ configuration KVM: arm64: vgic: Implement SW-driven deactivation KVM: arm64: vgic: move irq->get_input_level into an ops structure KVM: arm64: vgic: Let an interrupt controller advertise lack of HW deactivation KVM: arm64: vgic: Be tolerant to the lack of maintenance interrupt masking KVM: arm64: Handle physical FIQ as an IRQ while running a guest irqchip/gic: Split vGIC probing information from the GIC code
2 parents 8124c8a + b6ca556 commit 32e92b7

14 files changed

Lines changed: 299 additions & 104 deletions

File tree

arch/arm64/kvm/arch_timer.c

Lines changed: 136 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/kvm_host.h>
1010
#include <linux/interrupt.h>
1111
#include <linux/irq.h>
12+
#include <linux/irqdomain.h>
1213
#include <linux/uaccess.h>
1314

1415
#include <clocksource/arm_arch_timer.h>
@@ -973,36 +974,154 @@ static int kvm_timer_dying_cpu(unsigned int cpu)
973974
return 0;
974975
}
975976

976-
int kvm_timer_hyp_init(bool has_gic)
977+
static int timer_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
977978
{
978-
struct arch_timer_kvm_info *info;
979-
int err;
979+
if (vcpu)
980+
irqd_set_forwarded_to_vcpu(d);
981+
else
982+
irqd_clr_forwarded_to_vcpu(d);
980983

981-
info = arch_timer_get_kvm_info();
982-
timecounter = &info->timecounter;
984+
return 0;
985+
}
983986

984-
if (!timecounter->cc) {
985-
kvm_err("kvm_arch_timer: uninitialized timecounter\n");
986-
return -ENODEV;
987+
static int timer_irq_set_irqchip_state(struct irq_data *d,
988+
enum irqchip_irq_state which, bool val)
989+
{
990+
if (which != IRQCHIP_STATE_ACTIVE || !irqd_is_forwarded_to_vcpu(d))
991+
return irq_chip_set_parent_state(d, which, val);
992+
993+
if (val)
994+
irq_chip_mask_parent(d);
995+
else
996+
irq_chip_unmask_parent(d);
997+
998+
return 0;
999+
}
1000+
1001+
static void timer_irq_eoi(struct irq_data *d)
1002+
{
1003+
if (!irqd_is_forwarded_to_vcpu(d))
1004+
irq_chip_eoi_parent(d);
1005+
}
1006+
1007+
static void timer_irq_ack(struct irq_data *d)
1008+
{
1009+
d = d->parent_data;
1010+
if (d->chip->irq_ack)
1011+
d->chip->irq_ack(d);
1012+
}
1013+
1014+
static struct irq_chip timer_chip = {
1015+
.name = "KVM",
1016+
.irq_ack = timer_irq_ack,
1017+
.irq_mask = irq_chip_mask_parent,
1018+
.irq_unmask = irq_chip_unmask_parent,
1019+
.irq_eoi = timer_irq_eoi,
1020+
.irq_set_type = irq_chip_set_type_parent,
1021+
.irq_set_vcpu_affinity = timer_irq_set_vcpu_affinity,
1022+
.irq_set_irqchip_state = timer_irq_set_irqchip_state,
1023+
};
1024+
1025+
static int timer_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
1026+
unsigned int nr_irqs, void *arg)
1027+
{
1028+
irq_hw_number_t hwirq = (uintptr_t)arg;
1029+
1030+
return irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
1031+
&timer_chip, NULL);
1032+
}
1033+
1034+
static void timer_irq_domain_free(struct irq_domain *domain, unsigned int virq,
1035+
unsigned int nr_irqs)
1036+
{
1037+
}
1038+
1039+
static const struct irq_domain_ops timer_domain_ops = {
1040+
.alloc = timer_irq_domain_alloc,
1041+
.free = timer_irq_domain_free,
1042+
};
1043+
1044+
static struct irq_ops arch_timer_irq_ops = {
1045+
.get_input_level = kvm_arch_timer_get_input_level,
1046+
};
1047+
1048+
static void kvm_irq_fixup_flags(unsigned int virq, u32 *flags)
1049+
{
1050+
*flags = irq_get_trigger_type(virq);
1051+
if (*flags != IRQF_TRIGGER_HIGH && *flags != IRQF_TRIGGER_LOW) {
1052+
kvm_err("Invalid trigger for timer IRQ%d, assuming level low\n",
1053+
virq);
1054+
*flags = IRQF_TRIGGER_LOW;
9871055
}
1056+
}
9881057

989-
/* First, do the virtual EL1 timer irq */
1058+
static int kvm_irq_init(struct arch_timer_kvm_info *info)
1059+
{
1060+
struct irq_domain *domain = NULL;
9901061

9911062
if (info->virtual_irq <= 0) {
9921063
kvm_err("kvm_arch_timer: invalid virtual timer IRQ: %d\n",
9931064
info->virtual_irq);
9941065
return -ENODEV;
9951066
}
1067+
9961068
host_vtimer_irq = info->virtual_irq;
1069+
kvm_irq_fixup_flags(host_vtimer_irq, &host_vtimer_irq_flags);
1070+
1071+
if (kvm_vgic_global_state.no_hw_deactivation) {
1072+
struct fwnode_handle *fwnode;
1073+
struct irq_data *data;
1074+
1075+
fwnode = irq_domain_alloc_named_fwnode("kvm-timer");
1076+
if (!fwnode)
1077+
return -ENOMEM;
1078+
1079+
/* Assume both vtimer and ptimer in the same parent */
1080+
data = irq_get_irq_data(host_vtimer_irq);
1081+
domain = irq_domain_create_hierarchy(data->domain, 0,
1082+
NR_KVM_TIMERS, fwnode,
1083+
&timer_domain_ops, NULL);
1084+
if (!domain) {
1085+
irq_domain_free_fwnode(fwnode);
1086+
return -ENOMEM;
1087+
}
1088+
1089+
arch_timer_irq_ops.flags |= VGIC_IRQ_SW_RESAMPLE;
1090+
WARN_ON(irq_domain_push_irq(domain, host_vtimer_irq,
1091+
(void *)TIMER_VTIMER));
1092+
}
9971093

998-
host_vtimer_irq_flags = irq_get_trigger_type(host_vtimer_irq);
999-
if (host_vtimer_irq_flags != IRQF_TRIGGER_HIGH &&
1000-
host_vtimer_irq_flags != IRQF_TRIGGER_LOW) {
1001-
kvm_err("Invalid trigger for vtimer IRQ%d, assuming level low\n",
1002-
host_vtimer_irq);
1003-
host_vtimer_irq_flags = IRQF_TRIGGER_LOW;
1094+
if (info->physical_irq > 0) {
1095+
host_ptimer_irq = info->physical_irq;
1096+
kvm_irq_fixup_flags(host_ptimer_irq, &host_ptimer_irq_flags);
1097+
1098+
if (domain)
1099+
WARN_ON(irq_domain_push_irq(domain, host_ptimer_irq,
1100+
(void *)TIMER_PTIMER));
10041101
}
10051102

1103+
return 0;
1104+
}
1105+
1106+
int kvm_timer_hyp_init(bool has_gic)
1107+
{
1108+
struct arch_timer_kvm_info *info;
1109+
int err;
1110+
1111+
info = arch_timer_get_kvm_info();
1112+
timecounter = &info->timecounter;
1113+
1114+
if (!timecounter->cc) {
1115+
kvm_err("kvm_arch_timer: uninitialized timecounter\n");
1116+
return -ENODEV;
1117+
}
1118+
1119+
err = kvm_irq_init(info);
1120+
if (err)
1121+
return err;
1122+
1123+
/* First, do the virtual EL1 timer irq */
1124+
10061125
err = request_percpu_irq(host_vtimer_irq, kvm_arch_timer_handler,
10071126
"kvm guest vtimer", kvm_get_running_vcpus());
10081127
if (err) {
@@ -1027,15 +1146,6 @@ int kvm_timer_hyp_init(bool has_gic)
10271146
/* Now let's do the physical EL1 timer irq */
10281147

10291148
if (info->physical_irq > 0) {
1030-
host_ptimer_irq = info->physical_irq;
1031-
host_ptimer_irq_flags = irq_get_trigger_type(host_ptimer_irq);
1032-
if (host_ptimer_irq_flags != IRQF_TRIGGER_HIGH &&
1033-
host_ptimer_irq_flags != IRQF_TRIGGER_LOW) {
1034-
kvm_err("Invalid trigger for ptimer IRQ%d, assuming level low\n",
1035-
host_ptimer_irq);
1036-
host_ptimer_irq_flags = IRQF_TRIGGER_LOW;
1037-
}
1038-
10391149
err = request_percpu_irq(host_ptimer_irq, kvm_arch_timer_handler,
10401150
"kvm guest ptimer", kvm_get_running_vcpus());
10411151
if (err) {
@@ -1143,15 +1253,15 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
11431253
ret = kvm_vgic_map_phys_irq(vcpu,
11441254
map.direct_vtimer->host_timer_irq,
11451255
map.direct_vtimer->irq.irq,
1146-
kvm_arch_timer_get_input_level);
1256+
&arch_timer_irq_ops);
11471257
if (ret)
11481258
return ret;
11491259

11501260
if (map.direct_ptimer) {
11511261
ret = kvm_vgic_map_phys_irq(vcpu,
11521262
map.direct_ptimer->host_timer_irq,
11531263
map.direct_ptimer->irq.irq,
1154-
kvm_arch_timer_get_input_level);
1264+
&arch_timer_irq_ops);
11551265
}
11561266

11571267
if (ret)

arch/arm64/kvm/hyp/hyp-entry.S

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ el1_trap:
7676
b __guest_exit
7777

7878
el1_irq:
79+
el1_fiq:
7980
get_vcpu_ptr x1, x0
8081
mov x0, #ARM_EXCEPTION_IRQ
8182
b __guest_exit
@@ -131,7 +132,6 @@ SYM_CODE_END(\label)
131132
invalid_vector el2t_error_invalid
132133
invalid_vector el2h_irq_invalid
133134
invalid_vector el2h_fiq_invalid
134-
invalid_vector el1_fiq_invalid
135135

136136
.ltorg
137137

@@ -179,12 +179,12 @@ SYM_CODE_START(__kvm_hyp_vector)
179179

180180
valid_vect el1_sync // Synchronous 64-bit EL1
181181
valid_vect el1_irq // IRQ 64-bit EL1
182-
invalid_vect el1_fiq_invalid // FIQ 64-bit EL1
182+
valid_vect el1_fiq // FIQ 64-bit EL1
183183
valid_vect el1_error // Error 64-bit EL1
184184

185185
valid_vect el1_sync // Synchronous 32-bit EL1
186186
valid_vect el1_irq // IRQ 32-bit EL1
187-
invalid_vect el1_fiq_invalid // FIQ 32-bit EL1
187+
valid_vect el1_fiq // FIQ 32-bit EL1
188188
valid_vect el1_error // Error 32-bit EL1
189189
SYM_CODE_END(__kvm_hyp_vector)
190190

arch/arm64/kvm/vgic/vgic-init.c

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,16 @@ static irqreturn_t vgic_maintenance_handler(int irq, void *data)
482482
return IRQ_HANDLED;
483483
}
484484

485+
static struct gic_kvm_info *gic_kvm_info;
486+
487+
void __init vgic_set_kvm_info(const struct gic_kvm_info *info)
488+
{
489+
BUG_ON(gic_kvm_info != NULL);
490+
gic_kvm_info = kmalloc(sizeof(*info), GFP_KERNEL);
491+
if (gic_kvm_info)
492+
*gic_kvm_info = *info;
493+
}
494+
485495
/**
486496
* kvm_vgic_init_cpu_hardware - initialize the GIC VE hardware
487497
*
@@ -509,18 +519,29 @@ void kvm_vgic_init_cpu_hardware(void)
509519
*/
510520
int kvm_vgic_hyp_init(void)
511521
{
512-
const struct gic_kvm_info *gic_kvm_info;
522+
bool has_mask;
513523
int ret;
514524

515-
gic_kvm_info = gic_get_kvm_info();
516525
if (!gic_kvm_info)
517526
return -ENODEV;
518527

519-
if (!gic_kvm_info->maint_irq) {
528+
has_mask = !gic_kvm_info->no_maint_irq_mask;
529+
530+
if (has_mask && !gic_kvm_info->maint_irq) {
520531
kvm_err("No vgic maintenance irq\n");
521532
return -ENXIO;
522533
}
523534

535+
/*
536+
* If we get one of these oddball non-GICs, taint the kernel,
537+
* as we have no idea of how they *really* behave.
538+
*/
539+
if (gic_kvm_info->no_hw_deactivation) {
540+
kvm_info("Non-architectural vgic, tainting kernel\n");
541+
add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
542+
kvm_vgic_global_state.no_hw_deactivation = true;
543+
}
544+
524545
switch (gic_kvm_info->type) {
525546
case GIC_V2:
526547
ret = vgic_v2_probe(gic_kvm_info);
@@ -536,10 +557,17 @@ int kvm_vgic_hyp_init(void)
536557
ret = -ENODEV;
537558
}
538559

560+
kvm_vgic_global_state.maint_irq = gic_kvm_info->maint_irq;
561+
562+
kfree(gic_kvm_info);
563+
gic_kvm_info = NULL;
564+
539565
if (ret)
540566
return ret;
541567

542-
kvm_vgic_global_state.maint_irq = gic_kvm_info->maint_irq;
568+
if (!has_mask)
569+
return 0;
570+
543571
ret = request_percpu_irq(kvm_vgic_global_state.maint_irq,
544572
vgic_maintenance_handler,
545573
"vgic", kvm_get_running_vcpus());

arch/arm64/kvm/vgic/vgic-v2.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,22 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
108108
* If this causes us to lower the level, we have to also clear
109109
* the physical active state, since we will otherwise never be
110110
* told when the interrupt becomes asserted again.
111+
*
112+
* Another case is when the interrupt requires a helping hand
113+
* on deactivation (no HW deactivation, for example).
111114
*/
112-
if (vgic_irq_is_mapped_level(irq) && (val & GICH_LR_PENDING_BIT)) {
113-
irq->line_level = vgic_get_phys_line_level(irq);
115+
if (vgic_irq_is_mapped_level(irq)) {
116+
bool resample = false;
117+
118+
if (val & GICH_LR_PENDING_BIT) {
119+
irq->line_level = vgic_get_phys_line_level(irq);
120+
resample = !irq->line_level;
121+
} else if (vgic_irq_needs_resampling(irq) &&
122+
!(irq->active || irq->pending_latch)) {
123+
resample = true;
124+
}
114125

115-
if (!irq->line_level)
126+
if (resample)
116127
vgic_irq_set_phys_active(irq, false);
117128
}
118129

@@ -152,7 +163,7 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
152163
if (irq->group)
153164
val |= GICH_LR_GROUP1;
154165

155-
if (irq->hw) {
166+
if (irq->hw && !vgic_irq_needs_resampling(irq)) {
156167
val |= GICH_LR_HW;
157168
val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
158169
/*

arch/arm64/kvm/vgic/vgic-v3.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,22 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
101101
* If this causes us to lower the level, we have to also clear
102102
* the physical active state, since we will otherwise never be
103103
* told when the interrupt becomes asserted again.
104+
*
105+
* Another case is when the interrupt requires a helping hand
106+
* on deactivation (no HW deactivation, for example).
104107
*/
105-
if (vgic_irq_is_mapped_level(irq) && (val & ICH_LR_PENDING_BIT)) {
106-
irq->line_level = vgic_get_phys_line_level(irq);
108+
if (vgic_irq_is_mapped_level(irq)) {
109+
bool resample = false;
110+
111+
if (val & ICH_LR_PENDING_BIT) {
112+
irq->line_level = vgic_get_phys_line_level(irq);
113+
resample = !irq->line_level;
114+
} else if (vgic_irq_needs_resampling(irq) &&
115+
!(irq->active || irq->pending_latch)) {
116+
resample = true;
117+
}
107118

108-
if (!irq->line_level)
119+
if (resample)
109120
vgic_irq_set_phys_active(irq, false);
110121
}
111122

@@ -136,7 +147,7 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
136147
}
137148
}
138149

139-
if (irq->hw) {
150+
if (irq->hw && !vgic_irq_needs_resampling(irq)) {
140151
val |= ICH_LR_HW;
141152
val |= ((u64)irq->hwintid) << ICH_LR_PHYS_ID_SHIFT;
142153
/*

0 commit comments

Comments
 (0)