Skip to content

Commit 8040280

Browse files
committed
Merge tag 'loongarch-kvm-6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson into HEAD
LoongArch KVM changes for v6.19 1. Get VM PMU capability from HW GCFG register. 2. Add AVEC basic support. 3. Use 64-bit register definition for EIOINTC. 4. Add KVM timer test cases for tools/selftests.
2 parents 679fcce + 0f90fa6 commit 8040280

File tree

15 files changed

+534
-107
lines changed

15 files changed

+534
-107
lines changed

arch/loongarch/include/asm/kvm_eiointc.h

Lines changed: 8 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@
1010

1111
#define EIOINTC_IRQS 256
1212
#define EIOINTC_ROUTE_MAX_VCPUS 256
13-
#define EIOINTC_IRQS_U8_NUMS (EIOINTC_IRQS / 8)
14-
#define EIOINTC_IRQS_U16_NUMS (EIOINTC_IRQS_U8_NUMS / 2)
15-
#define EIOINTC_IRQS_U32_NUMS (EIOINTC_IRQS_U8_NUMS / 4)
16-
#define EIOINTC_IRQS_U64_NUMS (EIOINTC_IRQS_U8_NUMS / 8)
13+
#define EIOINTC_IRQS_U64_NUMS (EIOINTC_IRQS / 64)
1714
/* map to ipnum per 32 irqs */
1815
#define EIOINTC_IRQS_NODETYPE_COUNT 16
1916

@@ -64,54 +61,18 @@ struct loongarch_eiointc {
6461
uint32_t status;
6562

6663
/* hardware state */
67-
union nodetype {
68-
u64 reg_u64[EIOINTC_IRQS_NODETYPE_COUNT / 4];
69-
u32 reg_u32[EIOINTC_IRQS_NODETYPE_COUNT / 2];
70-
u16 reg_u16[EIOINTC_IRQS_NODETYPE_COUNT];
71-
u8 reg_u8[EIOINTC_IRQS_NODETYPE_COUNT * 2];
72-
} nodetype;
64+
u64 nodetype[EIOINTC_IRQS_NODETYPE_COUNT / 4];
7365

7466
/* one bit shows the state of one irq */
75-
union bounce {
76-
u64 reg_u64[EIOINTC_IRQS_U64_NUMS];
77-
u32 reg_u32[EIOINTC_IRQS_U32_NUMS];
78-
u16 reg_u16[EIOINTC_IRQS_U16_NUMS];
79-
u8 reg_u8[EIOINTC_IRQS_U8_NUMS];
80-
} bounce;
81-
82-
union isr {
83-
u64 reg_u64[EIOINTC_IRQS_U64_NUMS];
84-
u32 reg_u32[EIOINTC_IRQS_U32_NUMS];
85-
u16 reg_u16[EIOINTC_IRQS_U16_NUMS];
86-
u8 reg_u8[EIOINTC_IRQS_U8_NUMS];
87-
} isr;
88-
union coreisr {
89-
u64 reg_u64[EIOINTC_ROUTE_MAX_VCPUS][EIOINTC_IRQS_U64_NUMS];
90-
u32 reg_u32[EIOINTC_ROUTE_MAX_VCPUS][EIOINTC_IRQS_U32_NUMS];
91-
u16 reg_u16[EIOINTC_ROUTE_MAX_VCPUS][EIOINTC_IRQS_U16_NUMS];
92-
u8 reg_u8[EIOINTC_ROUTE_MAX_VCPUS][EIOINTC_IRQS_U8_NUMS];
93-
} coreisr;
94-
union enable {
95-
u64 reg_u64[EIOINTC_IRQS_U64_NUMS];
96-
u32 reg_u32[EIOINTC_IRQS_U32_NUMS];
97-
u16 reg_u16[EIOINTC_IRQS_U16_NUMS];
98-
u8 reg_u8[EIOINTC_IRQS_U8_NUMS];
99-
} enable;
67+
u64 bounce[EIOINTC_IRQS_U64_NUMS];
68+
u64 isr[EIOINTC_IRQS_U64_NUMS];
69+
u64 coreisr[EIOINTC_ROUTE_MAX_VCPUS][EIOINTC_IRQS_U64_NUMS];
70+
u64 enable[EIOINTC_IRQS_U64_NUMS];
10071

10172
/* use one byte to config ipmap for 32 irqs at once */
102-
union ipmap {
103-
u64 reg_u64;
104-
u32 reg_u32[EIOINTC_IRQS_U32_NUMS / 4];
105-
u16 reg_u16[EIOINTC_IRQS_U16_NUMS / 4];
106-
u8 reg_u8[EIOINTC_IRQS_U8_NUMS / 4];
107-
} ipmap;
73+
u64 ipmap;
10874
/* use one byte to config coremap for one irq */
109-
union coremap {
110-
u64 reg_u64[EIOINTC_IRQS / 8];
111-
u32 reg_u32[EIOINTC_IRQS / 4];
112-
u16 reg_u16[EIOINTC_IRQS / 2];
113-
u8 reg_u8[EIOINTC_IRQS];
114-
} coremap;
75+
u64 coremap[EIOINTC_IRQS / 8];
11576

11677
DECLARE_BITMAP(sw_coreisr[EIOINTC_ROUTE_MAX_VCPUS][LOONGSON_IP_NUM], EIOINTC_IRQS);
11778
uint8_t sw_coremap[EIOINTC_IRQS];

arch/loongarch/include/asm/kvm_host.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ struct kvm_arch {
126126
struct kvm_phyid_map *phyid_map;
127127
/* Enabled PV features */
128128
unsigned long pv_features;
129+
/* Supported KVM features */
130+
unsigned long kvm_features;
129131

130132
s64 time_offset;
131133
struct kvm_context __percpu *vmcs;
@@ -293,6 +295,12 @@ static inline int kvm_get_pmu_num(struct kvm_vcpu_arch *arch)
293295
return (arch->cpucfg[6] & CPUCFG6_PMNUM) >> CPUCFG6_PMNUM_SHIFT;
294296
}
295297

298+
/* Check whether KVM support this feature (VMM may disable it) */
299+
static inline bool kvm_vm_support(struct kvm_arch *arch, int feature)
300+
{
301+
return !!(arch->kvm_features & BIT_ULL(feature));
302+
}
303+
296304
bool kvm_arch_pmi_in_guest(struct kvm_vcpu *vcpu);
297305

298306
/* Debug: dump vcpu state */

arch/loongarch/include/asm/kvm_vcpu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define CPU_PMU (_ULCAST_(1) << 10)
1616
#define CPU_TIMER (_ULCAST_(1) << 11)
1717
#define CPU_IPI (_ULCAST_(1) << 12)
18+
#define CPU_AVEC (_ULCAST_(1) << 14)
1819

1920
/* Controlled by 0x52 guest exception VIP aligned to estat bit 5~12 */
2021
#define CPU_IP0 (_ULCAST_(1))

arch/loongarch/include/asm/loongarch.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,8 @@
511511
#define CSR_GCFG_GPERF_SHIFT 24
512512
#define CSR_GCFG_GPERF_WIDTH 3
513513
#define CSR_GCFG_GPERF (_ULCAST_(0x7) << CSR_GCFG_GPERF_SHIFT)
514+
#define CSR_GCFG_GPMP_SHIFT 23
515+
#define CSR_GCFG_GPMP (_ULCAST_(0x1) << CSR_GCFG_GPMP_SHIFT)
514516
#define CSR_GCFG_GCI_SHIFT 20
515517
#define CSR_GCFG_GCI_WIDTH 2
516518
#define CSR_GCFG_GCI (_ULCAST_(0x3) << CSR_GCFG_GCI_SHIFT)

arch/loongarch/include/uapi/asm/kvm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ struct kvm_fpu {
104104
#define KVM_LOONGARCH_VM_FEAT_PV_IPI 6
105105
#define KVM_LOONGARCH_VM_FEAT_PV_STEALTIME 7
106106
#define KVM_LOONGARCH_VM_FEAT_PTW 8
107+
#define KVM_LOONGARCH_VM_FEAT_MSGINT 9
107108

108109
/* Device Control API on vcpu fd */
109110
#define KVM_LOONGARCH_VCPU_CPUCFG 0

arch/loongarch/kvm/intc/eiointc.c

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,19 @@ static void eiointc_set_sw_coreisr(struct loongarch_eiointc *s)
1313
struct kvm_vcpu *vcpu;
1414

1515
for (irq = 0; irq < EIOINTC_IRQS; irq++) {
16-
ipnum = s->ipmap.reg_u8[irq / 32];
16+
ipnum = (s->ipmap >> (irq / 32 * 8)) & 0xff;
1717
if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) {
1818
ipnum = count_trailing_zeros(ipnum);
1919
ipnum = (ipnum >= 0 && ipnum < 4) ? ipnum : 0;
2020
}
2121

22-
cpuid = s->coremap.reg_u8[irq];
22+
cpuid = ((u8 *)s->coremap)[irq];
2323
vcpu = kvm_get_vcpu_by_cpuid(s->kvm, cpuid);
2424
if (!vcpu)
2525
continue;
2626

2727
cpu = vcpu->vcpu_id;
28-
if (test_bit(irq, (unsigned long *)s->coreisr.reg_u32[cpu]))
28+
if (test_bit(irq, (unsigned long *)s->coreisr[cpu]))
2929
__set_bit(irq, s->sw_coreisr[cpu][ipnum]);
3030
else
3131
__clear_bit(irq, s->sw_coreisr[cpu][ipnum]);
@@ -38,7 +38,7 @@ static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level)
3838
struct kvm_vcpu *vcpu;
3939
struct kvm_interrupt vcpu_irq;
4040

41-
ipnum = s->ipmap.reg_u8[irq / 32];
41+
ipnum = (s->ipmap >> (irq / 32 * 8)) & 0xff;
4242
if (!(s->status & BIT(EIOINTC_ENABLE_INT_ENCODE))) {
4343
ipnum = count_trailing_zeros(ipnum);
4444
ipnum = (ipnum >= 0 && ipnum < 4) ? ipnum : 0;
@@ -53,13 +53,13 @@ static void eiointc_update_irq(struct loongarch_eiointc *s, int irq, int level)
5353

5454
if (level) {
5555
/* if not enable return false */
56-
if (!test_bit(irq, (unsigned long *)s->enable.reg_u32))
56+
if (!test_bit(irq, (unsigned long *)s->enable))
5757
return;
58-
__set_bit(irq, (unsigned long *)s->coreisr.reg_u32[cpu]);
58+
__set_bit(irq, (unsigned long *)s->coreisr[cpu]);
5959
found = find_first_bit(s->sw_coreisr[cpu][ipnum], EIOINTC_IRQS);
6060
__set_bit(irq, s->sw_coreisr[cpu][ipnum]);
6161
} else {
62-
__clear_bit(irq, (unsigned long *)s->coreisr.reg_u32[cpu]);
62+
__clear_bit(irq, (unsigned long *)s->coreisr[cpu]);
6363
__clear_bit(irq, s->sw_coreisr[cpu][ipnum]);
6464
found = find_first_bit(s->sw_coreisr[cpu][ipnum], EIOINTC_IRQS);
6565
}
@@ -94,7 +94,7 @@ static inline void eiointc_update_sw_coremap(struct loongarch_eiointc *s,
9494
if (s->sw_coremap[irq + i] == cpu)
9595
continue;
9696

97-
if (notify && test_bit(irq + i, (unsigned long *)s->isr.reg_u8)) {
97+
if (notify && test_bit(irq + i, (unsigned long *)s->isr)) {
9898
/* lower irq at old cpu and raise irq at new cpu */
9999
eiointc_update_irq(s, irq + i, 0);
100100
s->sw_coremap[irq + i] = cpu;
@@ -108,7 +108,7 @@ static inline void eiointc_update_sw_coremap(struct loongarch_eiointc *s,
108108
void eiointc_set_irq(struct loongarch_eiointc *s, int irq, int level)
109109
{
110110
unsigned long flags;
111-
unsigned long *isr = (unsigned long *)s->isr.reg_u8;
111+
unsigned long *isr = (unsigned long *)s->isr;
112112

113113
spin_lock_irqsave(&s->lock, flags);
114114
level ? __set_bit(irq, isr) : __clear_bit(irq, isr);
@@ -127,27 +127,27 @@ static int loongarch_eiointc_read(struct kvm_vcpu *vcpu, struct loongarch_eioint
127127
switch (offset) {
128128
case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
129129
index = (offset - EIOINTC_NODETYPE_START) >> 3;
130-
data = s->nodetype.reg_u64[index];
130+
data = s->nodetype[index];
131131
break;
132132
case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
133133
index = (offset - EIOINTC_IPMAP_START) >> 3;
134-
data = s->ipmap.reg_u64;
134+
data = s->ipmap;
135135
break;
136136
case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
137137
index = (offset - EIOINTC_ENABLE_START) >> 3;
138-
data = s->enable.reg_u64[index];
138+
data = s->enable[index];
139139
break;
140140
case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
141141
index = (offset - EIOINTC_BOUNCE_START) >> 3;
142-
data = s->bounce.reg_u64[index];
142+
data = s->bounce[index];
143143
break;
144144
case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
145145
index = (offset - EIOINTC_COREISR_START) >> 3;
146-
data = s->coreisr.reg_u64[vcpu->vcpu_id][index];
146+
data = s->coreisr[vcpu->vcpu_id][index];
147147
break;
148148
case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
149149
index = (offset - EIOINTC_COREMAP_START) >> 3;
150-
data = s->coremap.reg_u64[index];
150+
data = s->coremap[index];
151151
break;
152152
default:
153153
ret = -EINVAL;
@@ -223,26 +223,26 @@ static int loongarch_eiointc_write(struct kvm_vcpu *vcpu,
223223
switch (offset) {
224224
case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
225225
index = (offset - EIOINTC_NODETYPE_START) >> 3;
226-
old = s->nodetype.reg_u64[index];
227-
s->nodetype.reg_u64[index] = (old & ~mask) | data;
226+
old = s->nodetype[index];
227+
s->nodetype[index] = (old & ~mask) | data;
228228
break;
229229
case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
230230
/*
231231
* ipmap cannot be set at runtime, can be set only at the beginning
232232
* of irqchip driver, need not update upper irq level
233233
*/
234-
old = s->ipmap.reg_u64;
235-
s->ipmap.reg_u64 = (old & ~mask) | data;
234+
old = s->ipmap;
235+
s->ipmap = (old & ~mask) | data;
236236
break;
237237
case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
238238
index = (offset - EIOINTC_ENABLE_START) >> 3;
239-
old = s->enable.reg_u64[index];
240-
s->enable.reg_u64[index] = (old & ~mask) | data;
239+
old = s->enable[index];
240+
s->enable[index] = (old & ~mask) | data;
241241
/*
242242
* 1: enable irq.
243243
* update irq when isr is set.
244244
*/
245-
data = s->enable.reg_u64[index] & ~old & s->isr.reg_u64[index];
245+
data = s->enable[index] & ~old & s->isr[index];
246246
while (data) {
247247
irq = __ffs(data);
248248
eiointc_update_irq(s, irq + index * 64, 1);
@@ -252,7 +252,7 @@ static int loongarch_eiointc_write(struct kvm_vcpu *vcpu,
252252
* 0: disable irq.
253253
* update irq when isr is set.
254254
*/
255-
data = ~s->enable.reg_u64[index] & old & s->isr.reg_u64[index];
255+
data = ~s->enable[index] & old & s->isr[index];
256256
while (data) {
257257
irq = __ffs(data);
258258
eiointc_update_irq(s, irq + index * 64, 0);
@@ -262,16 +262,16 @@ static int loongarch_eiointc_write(struct kvm_vcpu *vcpu,
262262
case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
263263
/* do not emulate hw bounced irq routing */
264264
index = (offset - EIOINTC_BOUNCE_START) >> 3;
265-
old = s->bounce.reg_u64[index];
266-
s->bounce.reg_u64[index] = (old & ~mask) | data;
265+
old = s->bounce[index];
266+
s->bounce[index] = (old & ~mask) | data;
267267
break;
268268
case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
269269
index = (offset - EIOINTC_COREISR_START) >> 3;
270270
/* use attrs to get current cpu index */
271271
cpu = vcpu->vcpu_id;
272-
old = s->coreisr.reg_u64[cpu][index];
272+
old = s->coreisr[cpu][index];
273273
/* write 1 to clear interrupt */
274-
s->coreisr.reg_u64[cpu][index] = old & ~data;
274+
s->coreisr[cpu][index] = old & ~data;
275275
data &= old;
276276
while (data) {
277277
irq = __ffs(data);
@@ -281,9 +281,9 @@ static int loongarch_eiointc_write(struct kvm_vcpu *vcpu,
281281
break;
282282
case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
283283
index = (offset - EIOINTC_COREMAP_START) >> 3;
284-
old = s->coremap.reg_u64[index];
285-
s->coremap.reg_u64[index] = (old & ~mask) | data;
286-
data = s->coremap.reg_u64[index];
284+
old = s->coremap[index];
285+
s->coremap[index] = (old & ~mask) | data;
286+
data = s->coremap[index];
287287
eiointc_update_sw_coremap(s, index * 8, data, sizeof(data), true);
288288
break;
289289
default:
@@ -451,10 +451,10 @@ static int kvm_eiointc_ctrl_access(struct kvm_device *dev,
451451
break;
452452
case KVM_DEV_LOONGARCH_EXTIOI_CTRL_LOAD_FINISHED:
453453
eiointc_set_sw_coreisr(s);
454-
for (i = 0; i < (EIOINTC_IRQS / 4); i++) {
455-
start_irq = i * 4;
454+
for (i = 0; i < (EIOINTC_IRQS / 8); i++) {
455+
start_irq = i * 8;
456456
eiointc_update_sw_coremap(s, start_irq,
457-
s->coremap.reg_u32[i], sizeof(u32), false);
457+
s->coremap[i], sizeof(u64), false);
458458
}
459459
break;
460460
default:
@@ -481,34 +481,34 @@ static int kvm_eiointc_regs_access(struct kvm_device *dev,
481481
switch (addr) {
482482
case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
483483
offset = (addr - EIOINTC_NODETYPE_START) / 4;
484-
p = &s->nodetype.reg_u32[offset];
484+
p = s->nodetype + offset * 4;
485485
break;
486486
case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
487487
offset = (addr - EIOINTC_IPMAP_START) / 4;
488-
p = &s->ipmap.reg_u32[offset];
488+
p = &s->ipmap + offset * 4;
489489
break;
490490
case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
491491
offset = (addr - EIOINTC_ENABLE_START) / 4;
492-
p = &s->enable.reg_u32[offset];
492+
p = s->enable + offset * 4;
493493
break;
494494
case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
495495
offset = (addr - EIOINTC_BOUNCE_START) / 4;
496-
p = &s->bounce.reg_u32[offset];
496+
p = s->bounce + offset * 4;
497497
break;
498498
case EIOINTC_ISR_START ... EIOINTC_ISR_END:
499499
offset = (addr - EIOINTC_ISR_START) / 4;
500-
p = &s->isr.reg_u32[offset];
500+
p = s->isr + offset * 4;
501501
break;
502502
case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
503503
if (cpu >= s->num_cpu)
504504
return -EINVAL;
505505

506506
offset = (addr - EIOINTC_COREISR_START) / 4;
507-
p = &s->coreisr.reg_u32[cpu][offset];
507+
p = s->coreisr[cpu] + offset * 4;
508508
break;
509509
case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
510510
offset = (addr - EIOINTC_COREMAP_START) / 4;
511-
p = &s->coremap.reg_u32[offset];
511+
p = s->coremap + offset * 4;
512512
break;
513513
default:
514514
kvm_err("%s: unknown eiointc register, addr = %d\n", __func__, addr);

arch/loongarch/kvm/interrupt.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ static unsigned int priority_to_irq[EXCCODE_INT_NUM] = {
2121
[INT_HWI5] = CPU_IP5,
2222
[INT_HWI6] = CPU_IP6,
2323
[INT_HWI7] = CPU_IP7,
24+
[INT_AVEC] = CPU_AVEC,
2425
};
2526

2627
static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
@@ -31,6 +32,11 @@ static int kvm_irq_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
3132
if (priority < EXCCODE_INT_NUM)
3233
irq = priority_to_irq[priority];
3334

35+
if (cpu_has_msgint && (priority == INT_AVEC)) {
36+
set_gcsr_estat(irq);
37+
return 1;
38+
}
39+
3440
switch (priority) {
3541
case INT_TI:
3642
case INT_IPI:
@@ -58,6 +64,11 @@ static int kvm_irq_clear(struct kvm_vcpu *vcpu, unsigned int priority)
5864
if (priority < EXCCODE_INT_NUM)
5965
irq = priority_to_irq[priority];
6066

67+
if (cpu_has_msgint && (priority == INT_AVEC)) {
68+
clear_gcsr_estat(irq);
69+
return 1;
70+
}
71+
6172
switch (priority) {
6273
case INT_TI:
6374
case INT_IPI:
@@ -83,10 +94,10 @@ void kvm_deliver_intr(struct kvm_vcpu *vcpu)
8394
unsigned long *pending = &vcpu->arch.irq_pending;
8495
unsigned long *pending_clr = &vcpu->arch.irq_clear;
8596

86-
for_each_set_bit(priority, pending_clr, INT_IPI + 1)
97+
for_each_set_bit(priority, pending_clr, EXCCODE_INT_NUM)
8798
kvm_irq_clear(vcpu, priority);
8899

89-
for_each_set_bit(priority, pending, INT_IPI + 1)
100+
for_each_set_bit(priority, pending, EXCCODE_INT_NUM)
90101
kvm_irq_deliver(vcpu, priority);
91102
}
92103

0 commit comments

Comments
 (0)