@@ -218,290 +218,45 @@ static int kvm_eiointc_read(struct kvm_vcpu *vcpu,
218
218
return 0 ;
219
219
}
220
220
221
- static int loongarch_eiointc_writeb (struct kvm_vcpu * vcpu ,
221
+ static int loongarch_eiointc_write (struct kvm_vcpu * vcpu ,
222
222
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 )
388
224
{
389
225
int i , index , irq , bits , ret = 0 ;
390
226
u8 cpu ;
391
- u32 data , old_data ;
392
- u32 coreisr , old_coreisr ;
227
+ u64 data , old , mask ;
393
228
gpa_t offset ;
394
229
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 );
397
233
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 ;
481
235
offset = addr - EIOINTC_BASE ;
482
236
483
237
switch (offset ) {
484
238
case EIOINTC_NODETYPE_START ... EIOINTC_NODETYPE_END :
485
239
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 ;
487
242
break ;
488
243
case EIOINTC_IPMAP_START ... EIOINTC_IPMAP_END :
489
244
/*
490
245
* ipmap cannot be set at runtime, can be set only at the beginning
491
246
* of irqchip driver, need not update upper irq level
492
247
*/
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 ;
495
250
break ;
496
251
case EIOINTC_ENABLE_START ... EIOINTC_ENABLE_END :
497
252
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 ;
500
255
/*
501
256
* 1: enable irq.
502
257
* update irq when isr is set.
503
258
*/
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 ];
505
260
for (i = 0 ; i < sizeof (data ); i ++ ) {
506
261
u8 mask = (data >> (i * 8 )) & 0xff ;
507
262
eiointc_enable_irq (vcpu , s , index * 8 + i , mask , 1 );
@@ -510,7 +265,7 @@ static int loongarch_eiointc_writeq(struct kvm_vcpu *vcpu,
510
265
* 0: disable irq.
511
266
* update irq when isr is set.
512
267
*/
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 ];
514
269
for (i = 0 ; i < sizeof (data ); i ++ ) {
515
270
u8 mask = (data >> (i * 8 )) & 0xff ;
516
271
eiointc_enable_irq (vcpu , s , index * 8 + i , mask , 0 );
@@ -519,30 +274,31 @@ static int loongarch_eiointc_writeq(struct kvm_vcpu *vcpu,
519
274
case EIOINTC_BOUNCE_START ... EIOINTC_BOUNCE_END :
520
275
/* do not emulate hw bounced irq routing */
521
276
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 ;
523
279
break ;
524
280
case EIOINTC_COREISR_START ... EIOINTC_COREISR_END :
525
281
index = (offset - EIOINTC_COREISR_START ) >> 3 ;
526
282
/* use attrs to get current cpu index */
527
283
cpu = vcpu -> vcpu_id ;
528
- coreisr = data ;
529
- old_coreisr = s -> coreisr .reg_u64 [cpu ][index ];
284
+ old = s -> coreisr .reg_u64 [cpu ][index ];
530
285
/* 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 ;
533
288
bits = sizeof (data ) * 8 ;
534
- irq = find_first_bit ((void * )& coreisr , bits );
289
+ irq = find_first_bit ((void * )& data , bits );
535
290
while (irq < bits ) {
536
291
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 );
539
294
}
540
295
break ;
541
296
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);
546
302
break ;
547
303
default :
548
304
ret = - EINVAL ;
@@ -557,7 +313,7 @@ static int kvm_eiointc_write(struct kvm_vcpu *vcpu,
557
313
gpa_t addr , int len , const void * val )
558
314
{
559
315
int ret = - EINVAL ;
560
- unsigned long flags ;
316
+ unsigned long flags , value ;
561
317
struct loongarch_eiointc * eiointc = vcpu -> kvm -> arch .eiointc ;
562
318
563
319
if (!eiointc ) {
@@ -574,16 +330,20 @@ static int kvm_eiointc_write(struct kvm_vcpu *vcpu,
574
330
spin_lock_irqsave (& eiointc -> lock , flags );
575
331
switch (len ) {
576
332
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 );
578
335
break ;
579
336
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 );
581
339
break ;
582
340
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 );
584
343
break ;
585
344
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 );
587
347
break ;
588
348
}
589
349
spin_unlock_irqrestore (& eiointc -> lock , flags );
0 commit comments