@@ -1316,6 +1316,28 @@ vlapic_icrlo_write_handler(struct acrn_vlapic *vlapic)
1316
1316
return ret ; /* handled completely in the kernel */
1317
1317
}
1318
1318
1319
+ static inline uint32_t vlapic_find_highest_irr (const struct acrn_vlapic * vlapic )
1320
+ {
1321
+ const struct lapic_regs * lapic = & (vlapic -> apic_page );
1322
+ uint32_t i , val , bitpos , vec = 0U ;
1323
+ const struct lapic_reg * irrptr ;
1324
+
1325
+ irrptr = & lapic -> irr [0 ];
1326
+
1327
+ /* i ranges effectively from 7 to 1 */
1328
+ for (i = 8U ; i > 1U ; ) {
1329
+ i -- ;
1330
+ val = atomic_load32 (& irrptr [i ].v );
1331
+ if (val != 0U ) {
1332
+ bitpos = (uint32_t )fls32 (val );
1333
+ vec = (i * 32U ) + bitpos ;
1334
+ break ;
1335
+ }
1336
+ }
1337
+
1338
+ return vec ;
1339
+ }
1340
+
1319
1341
/**
1320
1342
* @brief Find a deliverable virtual interrupts for vLAPIC in irr.
1321
1343
*
@@ -1330,32 +1352,20 @@ vlapic_icrlo_write_handler(struct acrn_vlapic *vlapic)
1330
1352
* result of calling this function.
1331
1353
* This function is only for case that APICv/VID is NOT supported.
1332
1354
*/
1333
- bool
1334
- vlapic_find_deliverable_intr (const struct acrn_vlapic * vlapic , uint32_t * vecptr )
1355
+ bool vlapic_find_deliverable_intr (const struct acrn_vlapic * vlapic , uint32_t * vecptr )
1335
1356
{
1336
1357
const struct lapic_regs * lapic = & (vlapic -> apic_page );
1337
- uint32_t i , vector , val , bitpos ;
1338
- const struct lapic_reg * irrptr ;
1358
+ uint32_t vec ;
1339
1359
bool ret = false;
1340
1360
1341
- irrptr = & lapic -> irr [0 ];
1342
-
1343
- /* i ranges effectively from 7 to 0 */
1344
- for (i = 8U ; i > 0U ; ) {
1345
- i -- ;
1346
- val = atomic_load32 (& irrptr [i ].v );
1347
- bitpos = (uint32_t )fls32 (val );
1348
- if (bitpos != INVALID_BIT_INDEX ) {
1349
- vector = (i * 32U ) + bitpos ;
1350
- if (prio (vector ) > prio (lapic -> ppr .v )) {
1351
- if (vecptr != NULL ) {
1352
- * vecptr = vector ;
1353
- }
1354
- ret = true;
1355
- }
1356
- break ;
1361
+ vec = vlapic_find_highest_irr (vlapic );
1362
+ if (prio (vec ) > prio (lapic -> ppr .v )) {
1363
+ ret = true;
1364
+ if (vecptr != NULL ) {
1365
+ * vecptr = vec ;
1357
1366
}
1358
1367
}
1368
+
1359
1369
return ret ;
1360
1370
}
1361
1371
@@ -2419,8 +2429,35 @@ int32_t apic_write_vmexit_handler(struct acrn_vcpu *vcpu)
2419
2429
return err ;
2420
2430
}
2421
2431
2422
- int32_t tpr_below_threshold_vmexit_handler (__unused struct acrn_vcpu * vcpu )
2432
+ /*
2433
+ * TPR threshold (32 bits). Bits 3:0 of this field determine the threshold
2434
+ * below which bits 7:4 of VTPR (see Section 29.1.1) cannot fall.
2435
+ */
2436
+ void vlapic_update_tpr_threshold (const struct acrn_vlapic * vlapic )
2423
2437
{
2424
- pr_err ("Unhandled %s." , __func__ );
2438
+ uint32_t irr , tpr , threshold ;
2439
+
2440
+ tpr = vlapic -> apic_page .tpr .v ;
2441
+ tpr = ((tpr & 0xf0U ) >> 4U );
2442
+ irr = vlapic_find_highest_irr (vlapic );
2443
+ irr >>= 4U ;
2444
+ threshold = (irr > tpr ) ? 0U : irr ;
2445
+
2446
+ exec_vmwrite32 (VMX_TPR_THRESHOLD , threshold );
2447
+ }
2448
+
2449
+ int32_t tpr_below_threshold_vmexit_handler (struct acrn_vcpu * vcpu )
2450
+ {
2451
+ struct acrn_vlapic * vlapic = vcpu_vlapic (vcpu );
2452
+
2453
+ vlapic_update_ppr (vlapic );
2454
+ /*
2455
+ * Once we come here, the vTPR must small than IRR.
2456
+ * set TPR threshold to 0 to bypass VM-Execution Control Fields check
2457
+ * since vcpu_inject_vlapic_int will update TPR threshold aright.
2458
+ */
2459
+ exec_vmwrite32 (VMX_TPR_THRESHOLD , 0U );
2460
+ vcpu_make_request (vcpu , ACRN_REQUEST_EVENT );
2461
+
2425
2462
return 0 ;
2426
2463
}
0 commit comments