Skip to content

Commit fa741a6

Browse files
bibo-maoKexyBiscuit
authored andcommitted
FROMGIT: LoongArch: KVM: Use generic function loongarch_eiointc_write()
With all eiointc iocsr register write operation with 1/2/4/8 bytes size, generic function loongarch_eiointc_write() is used here. And function loongarch_eiointc_writeb(), loongarch_eiointc_writew(), loongarch_eiointc_writel() are removed. Signed-off-by: Bibo Mao <[email protected]> Signed-off-by: Huacai Chen <[email protected]> (cherry picked from commit b0096e1 https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson.git loongarch-next) Signed-off-by: Kexy Biscuit <[email protected]>
1 parent 3097b8d commit fa741a6

File tree

1 file changed

+37
-277
lines changed

1 file changed

+37
-277
lines changed

arch/loongarch/kvm/intc/eiointc.c

Lines changed: 37 additions & 277 deletions
Original file line numberDiff line numberDiff line change
@@ -218,290 +218,45 @@ static int kvm_eiointc_read(struct kvm_vcpu *vcpu,
218218
return 0;
219219
}
220220

221-
static int loongarch_eiointc_writeb(struct kvm_vcpu *vcpu,
221+
static int loongarch_eiointc_write(struct kvm_vcpu *vcpu,
222222
struct loongarch_eiointc *s,
223-
gpa_t addr, const void *val)
224-
{
225-
int index, irq, bits, ret = 0;
226-
u8 cpu;
227-
u8 data, old_data;
228-
u8 coreisr, old_coreisr;
229-
gpa_t offset;
230-
231-
data = *(u8 *)val;
232-
offset = addr - EIOINTC_BASE;
233-
234-
switch (offset) {
235-
case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
236-
index = (offset - EIOINTC_NODETYPE_START);
237-
s->nodetype.reg_u8[index] = data;
238-
break;
239-
case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
240-
/*
241-
* ipmap cannot be set at runtime, can be set only at the beginning
242-
* of irqchip driver, need not update upper irq level
243-
*/
244-
index = (offset - EIOINTC_IPMAP_START);
245-
s->ipmap.reg_u8[index] = data;
246-
break;
247-
case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
248-
index = (offset - EIOINTC_ENABLE_START);
249-
old_data = s->enable.reg_u8[index];
250-
s->enable.reg_u8[index] = data;
251-
/*
252-
* 1: enable irq.
253-
* update irq when isr is set.
254-
*/
255-
data = s->enable.reg_u8[index] & ~old_data & s->isr.reg_u8[index];
256-
eiointc_enable_irq(vcpu, s, index, data, 1);
257-
/*
258-
* 0: disable irq.
259-
* update irq when isr is set.
260-
*/
261-
data = ~s->enable.reg_u8[index] & old_data & s->isr.reg_u8[index];
262-
eiointc_enable_irq(vcpu, s, index, data, 0);
263-
break;
264-
case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
265-
/* do not emulate hw bounced irq routing */
266-
index = offset - EIOINTC_BOUNCE_START;
267-
s->bounce.reg_u8[index] = data;
268-
break;
269-
case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
270-
index = (offset - EIOINTC_COREISR_START);
271-
/* use attrs to get current cpu index */
272-
cpu = vcpu->vcpu_id;
273-
coreisr = data;
274-
old_coreisr = s->coreisr.reg_u8[cpu][index];
275-
/* write 1 to clear interrupt */
276-
s->coreisr.reg_u8[cpu][index] = old_coreisr & ~coreisr;
277-
coreisr &= old_coreisr;
278-
bits = sizeof(data) * 8;
279-
irq = find_first_bit((void *)&coreisr, bits);
280-
while (irq < bits) {
281-
eiointc_update_irq(s, irq + index * bits, 0);
282-
bitmap_clear((void *)&coreisr, irq, 1);
283-
irq = find_first_bit((void *)&coreisr, bits);
284-
}
285-
break;
286-
case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
287-
irq = offset - EIOINTC_COREMAP_START;
288-
index = irq;
289-
s->coremap.reg_u8[index] = data;
290-
eiointc_update_sw_coremap(s, irq, data, sizeof(data), true);
291-
break;
292-
default:
293-
ret = -EINVAL;
294-
break;
295-
}
296-
297-
return ret;
298-
}
299-
300-
static int loongarch_eiointc_writew(struct kvm_vcpu *vcpu,
301-
struct loongarch_eiointc *s,
302-
gpa_t addr, const void *val)
303-
{
304-
int i, index, irq, bits, ret = 0;
305-
u8 cpu;
306-
u16 data, old_data;
307-
u16 coreisr, old_coreisr;
308-
gpa_t offset;
309-
310-
data = *(u16 *)val;
311-
offset = addr - EIOINTC_BASE;
312-
313-
switch (offset) {
314-
case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
315-
index = (offset - EIOINTC_NODETYPE_START) >> 1;
316-
s->nodetype.reg_u16[index] = data;
317-
break;
318-
case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
319-
/*
320-
* ipmap cannot be set at runtime, can be set only at the beginning
321-
* of irqchip driver, need not update upper irq level
322-
*/
323-
index = (offset - EIOINTC_IPMAP_START) >> 1;
324-
s->ipmap.reg_u16[index] = data;
325-
break;
326-
case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
327-
index = (offset - EIOINTC_ENABLE_START) >> 1;
328-
old_data = s->enable.reg_u16[index];
329-
s->enable.reg_u16[index] = data;
330-
/*
331-
* 1: enable irq.
332-
* update irq when isr is set.
333-
*/
334-
data = s->enable.reg_u16[index] & ~old_data & s->isr.reg_u16[index];
335-
for (i = 0; i < sizeof(data); i++) {
336-
u8 mask = (data >> (i * 8)) & 0xff;
337-
eiointc_enable_irq(vcpu, s, index * 2 + i, mask, 1);
338-
}
339-
/*
340-
* 0: disable irq.
341-
* update irq when isr is set.
342-
*/
343-
data = ~s->enable.reg_u16[index] & old_data & s->isr.reg_u16[index];
344-
for (i = 0; i < sizeof(data); i++) {
345-
u8 mask = (data >> (i * 8)) & 0xff;
346-
eiointc_enable_irq(vcpu, s, index * 2 + i, mask, 0);
347-
}
348-
break;
349-
case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
350-
/* do not emulate hw bounced irq routing */
351-
index = (offset - EIOINTC_BOUNCE_START) >> 1;
352-
s->bounce.reg_u16[index] = data;
353-
break;
354-
case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
355-
index = (offset - EIOINTC_COREISR_START) >> 1;
356-
/* use attrs to get current cpu index */
357-
cpu = vcpu->vcpu_id;
358-
coreisr = data;
359-
old_coreisr = s->coreisr.reg_u16[cpu][index];
360-
/* write 1 to clear interrupt */
361-
s->coreisr.reg_u16[cpu][index] = old_coreisr & ~coreisr;
362-
coreisr &= old_coreisr;
363-
bits = sizeof(data) * 8;
364-
irq = find_first_bit((void *)&coreisr, bits);
365-
while (irq < bits) {
366-
eiointc_update_irq(s, irq + index * bits, 0);
367-
bitmap_clear((void *)&coreisr, irq, 1);
368-
irq = find_first_bit((void *)&coreisr, bits);
369-
}
370-
break;
371-
case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
372-
irq = offset - EIOINTC_COREMAP_START;
373-
index = irq >> 1;
374-
s->coremap.reg_u16[index] = data;
375-
eiointc_update_sw_coremap(s, irq, data, sizeof(data), true);
376-
break;
377-
default:
378-
ret = -EINVAL;
379-
break;
380-
}
381-
382-
return ret;
383-
}
384-
385-
static int loongarch_eiointc_writel(struct kvm_vcpu *vcpu,
386-
struct loongarch_eiointc *s,
387-
gpa_t addr, const void *val)
223+
gpa_t addr, u64 value, u64 field_mask)
388224
{
389225
int i, index, irq, bits, ret = 0;
390226
u8 cpu;
391-
u32 data, old_data;
392-
u32 coreisr, old_coreisr;
227+
u64 data, old, mask;
393228
gpa_t offset;
394229

395-
data = *(u32 *)val;
396-
offset = addr - EIOINTC_BASE;
230+
offset = addr & 7;
231+
mask = field_mask << (offset * 8);
232+
data = (value & field_mask) << (offset * 8);
397233

398-
switch (offset) {
399-
case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
400-
index = (offset - EIOINTC_NODETYPE_START) >> 2;
401-
s->nodetype.reg_u32[index] = data;
402-
break;
403-
case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
404-
/*
405-
* ipmap cannot be set at runtime, can be set only at the beginning
406-
* of irqchip driver, need not update upper irq level
407-
*/
408-
index = (offset - EIOINTC_IPMAP_START) >> 2;
409-
s->ipmap.reg_u32[index] = data;
410-
break;
411-
case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
412-
index = (offset - EIOINTC_ENABLE_START) >> 2;
413-
old_data = s->enable.reg_u32[index];
414-
s->enable.reg_u32[index] = data;
415-
/*
416-
* 1: enable irq.
417-
* update irq when isr is set.
418-
*/
419-
data = s->enable.reg_u32[index] & ~old_data & s->isr.reg_u32[index];
420-
for (i = 0; i < sizeof(data); i++) {
421-
u8 mask = (data >> (i * 8)) & 0xff;
422-
eiointc_enable_irq(vcpu, s, index * 4 + i, mask, 1);
423-
}
424-
/*
425-
* 0: disable irq.
426-
* update irq when isr is set.
427-
*/
428-
data = ~s->enable.reg_u32[index] & old_data & s->isr.reg_u32[index];
429-
for (i = 0; i < sizeof(data); i++) {
430-
u8 mask = (data >> (i * 8)) & 0xff;
431-
eiointc_enable_irq(vcpu, s, index * 4 + i, mask, 0);
432-
}
433-
break;
434-
case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
435-
/* do not emulate hw bounced irq routing */
436-
index = (offset - EIOINTC_BOUNCE_START) >> 2;
437-
s->bounce.reg_u32[index] = data;
438-
break;
439-
case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
440-
index = (offset - EIOINTC_COREISR_START) >> 2;
441-
/* use attrs to get current cpu index */
442-
cpu = vcpu->vcpu_id;
443-
coreisr = data;
444-
old_coreisr = s->coreisr.reg_u32[cpu][index];
445-
/* write 1 to clear interrupt */
446-
s->coreisr.reg_u32[cpu][index] = old_coreisr & ~coreisr;
447-
coreisr &= old_coreisr;
448-
bits = sizeof(data) * 8;
449-
irq = find_first_bit((void *)&coreisr, bits);
450-
while (irq < bits) {
451-
eiointc_update_irq(s, irq + index * bits, 0);
452-
bitmap_clear((void *)&coreisr, irq, 1);
453-
irq = find_first_bit((void *)&coreisr, bits);
454-
}
455-
break;
456-
case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
457-
irq = offset - EIOINTC_COREMAP_START;
458-
index = irq >> 2;
459-
s->coremap.reg_u32[index] = data;
460-
eiointc_update_sw_coremap(s, irq, data, sizeof(data), true);
461-
break;
462-
default:
463-
ret = -EINVAL;
464-
break;
465-
}
466-
467-
return ret;
468-
}
469-
470-
static int loongarch_eiointc_writeq(struct kvm_vcpu *vcpu,
471-
struct loongarch_eiointc *s,
472-
gpa_t addr, const void *val)
473-
{
474-
int i, index, irq, bits, ret = 0;
475-
u8 cpu;
476-
u64 data, old_data;
477-
u64 coreisr, old_coreisr;
478-
gpa_t offset;
479-
480-
data = *(u64 *)val;
234+
addr -= offset;
481235
offset = addr - EIOINTC_BASE;
482236

483237
switch (offset) {
484238
case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END:
485239
index = (offset - EIOINTC_NODETYPE_START) >> 3;
486-
s->nodetype.reg_u64[index] = data;
240+
old = s->nodetype.reg_u64[index];
241+
s->nodetype.reg_u64[index] = (old & ~mask) | data;
487242
break;
488243
case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END:
489244
/*
490245
* ipmap cannot be set at runtime, can be set only at the beginning
491246
* of irqchip driver, need not update upper irq level
492247
*/
493-
index = (offset - EIOINTC_IPMAP_START) >> 3;
494-
s->ipmap.reg_u64 = data;
248+
old = s->ipmap.reg_u64;
249+
s->ipmap.reg_u64 = (old & ~mask) | data;
495250
break;
496251
case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END:
497252
index = (offset - EIOINTC_ENABLE_START) >> 3;
498-
old_data = s->enable.reg_u64[index];
499-
s->enable.reg_u64[index] = data;
253+
old = s->enable.reg_u64[index];
254+
s->enable.reg_u64[index] = (old & ~mask) | data;
500255
/*
501256
* 1: enable irq.
502257
* update irq when isr is set.
503258
*/
504-
data = s->enable.reg_u64[index] & ~old_data & s->isr.reg_u64[index];
259+
data = s->enable.reg_u64[index] & ~old & s->isr.reg_u64[index];
505260
for (i = 0; i < sizeof(data); i++) {
506261
u8 mask = (data >> (i * 8)) & 0xff;
507262
eiointc_enable_irq(vcpu, s, index * 8 + i, mask, 1);
@@ -510,7 +265,7 @@ static int loongarch_eiointc_writeq(struct kvm_vcpu *vcpu,
510265
* 0: disable irq.
511266
* update irq when isr is set.
512267
*/
513-
data = ~s->enable.reg_u64[index] & old_data & s->isr.reg_u64[index];
268+
data = ~s->enable.reg_u64[index] & old & s->isr.reg_u64[index];
514269
for (i = 0; i < sizeof(data); i++) {
515270
u8 mask = (data >> (i * 8)) & 0xff;
516271
eiointc_enable_irq(vcpu, s, index * 8 + i, mask, 0);
@@ -519,30 +274,31 @@ static int loongarch_eiointc_writeq(struct kvm_vcpu *vcpu,
519274
case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END:
520275
/* do not emulate hw bounced irq routing */
521276
index = (offset - EIOINTC_BOUNCE_START) >> 3;
522-
s->bounce.reg_u64[index] = data;
277+
old = s->bounce.reg_u64[index];
278+
s->bounce.reg_u64[index] = (old & ~mask) | data;
523279
break;
524280
case EIOINTC_COREISR_START ... EIOINTC_COREISR_END:
525281
index = (offset - EIOINTC_COREISR_START) >> 3;
526282
/* use attrs to get current cpu index */
527283
cpu = vcpu->vcpu_id;
528-
coreisr = data;
529-
old_coreisr = s->coreisr.reg_u64[cpu][index];
284+
old = s->coreisr.reg_u64[cpu][index];
530285
/* write 1 to clear interrupt */
531-
s->coreisr.reg_u64[cpu][index] = old_coreisr & ~coreisr;
532-
coreisr &= old_coreisr;
286+
s->coreisr.reg_u64[cpu][index] = old & ~data;
287+
data &= old;
533288
bits = sizeof(data) * 8;
534-
irq = find_first_bit((void *)&coreisr, bits);
289+
irq = find_first_bit((void *)&data, bits);
535290
while (irq < bits) {
536291
eiointc_update_irq(s, irq + index * bits, 0);
537-
bitmap_clear((void *)&coreisr, irq, 1);
538-
irq = find_first_bit((void *)&coreisr, bits);
292+
bitmap_clear((void *)&data, irq, 1);
293+
irq = find_first_bit((void *)&data, bits);
539294
}
540295
break;
541296
case EIOINTC_COREMAP_START ... EIOINTC_COREMAP_END:
542-
irq = offset - EIOINTC_COREMAP_START;
543-
index = irq >> 3;
544-
s->coremap.reg_u64[index] = data;
545-
eiointc_update_sw_coremap(s, irq, data, sizeof(data), true);
297+
index = (offset - EIOINTC_COREMAP_START) >> 3;
298+
old = s->coremap.reg_u64[index];
299+
s->coremap.reg_u64[index] = (old & ~mask) | data;
300+
data = s->coremap.reg_u64[index];
301+
eiointc_update_sw_coremap(s, index * 8, data, sizeof(data), true);
546302
break;
547303
default:
548304
ret = -EINVAL;
@@ -557,7 +313,7 @@ static int kvm_eiointc_write(struct kvm_vcpu *vcpu,
557313
gpa_t addr, int len, const void *val)
558314
{
559315
int ret = -EINVAL;
560-
unsigned long flags;
316+
unsigned long flags, value;
561317
struct loongarch_eiointc *eiointc = vcpu->kvm->arch.eiointc;
562318

563319
if (!eiointc) {
@@ -574,16 +330,20 @@ static int kvm_eiointc_write(struct kvm_vcpu *vcpu,
574330
spin_lock_irqsave(&eiointc->lock, flags);
575331
switch (len) {
576332
case 1:
577-
ret = loongarch_eiointc_writeb(vcpu, eiointc, addr, val);
333+
value = *(unsigned char *)val;
334+
ret = loongarch_eiointc_write(vcpu, eiointc, addr, value, 0xFF);
578335
break;
579336
case 2:
580-
ret = loongarch_eiointc_writew(vcpu, eiointc, addr, val);
337+
value = *(unsigned short *)val;
338+
ret = loongarch_eiointc_write(vcpu, eiointc, addr, value, USHRT_MAX);
581339
break;
582340
case 4:
583-
ret = loongarch_eiointc_writel(vcpu, eiointc, addr, val);
341+
value = *(unsigned int *)val;
342+
ret = loongarch_eiointc_write(vcpu, eiointc, addr, value, UINT_MAX);
584343
break;
585344
default:
586-
ret = loongarch_eiointc_writeq(vcpu, eiointc, addr, val);
345+
value = *(unsigned long *)val;
346+
ret = loongarch_eiointc_write(vcpu, eiointc, addr, value, ULONG_MAX);
587347
break;
588348
}
589349
spin_unlock_irqrestore(&eiointc->lock, flags);

0 commit comments

Comments
 (0)