@@ -383,6 +383,21 @@ static RISCVException aia_smode32(CPURISCVState *env, int csrno)
383
383
return smode32 (env , csrno );
384
384
}
385
385
386
+ static RISCVException scountinhibit_pred (CPURISCVState * env , int csrno )
387
+ {
388
+ RISCVCPU * cpu = env_archcpu (env );
389
+
390
+ if (!cpu -> cfg .ext_ssccfg || !cpu -> cfg .ext_smcdeleg ) {
391
+ return RISCV_EXCP_ILLEGAL_INST ;
392
+ }
393
+
394
+ if (env -> virt_enabled ) {
395
+ return RISCV_EXCP_VIRT_INSTRUCTION_FAULT ;
396
+ }
397
+
398
+ return smode (env , csrno );
399
+ }
400
+
386
401
static bool csrind_extensions_present (CPURISCVState * env )
387
402
{
388
403
return riscv_cpu_cfg (env )-> ext_smcsrind || riscv_cpu_cfg (env )-> ext_sscsrind ;
@@ -1224,10 +1239,9 @@ static target_ulong riscv_pmu_ctr_get_fixed_counters_val(CPURISCVState *env,
1224
1239
return result ;
1225
1240
}
1226
1241
1227
- static RISCVException write_mhpmcounter (CPURISCVState * env , int csrno ,
1228
- target_ulong val )
1242
+ static RISCVException riscv_pmu_write_ctr (CPURISCVState * env , target_ulong val ,
1243
+ uint32_t ctr_idx )
1229
1244
{
1230
- int ctr_idx = csrno - CSR_MCYCLE ;
1231
1245
PMUCTRState * counter = & env -> pmu_ctrs [ctr_idx ];
1232
1246
uint64_t mhpmctr_val = val ;
1233
1247
@@ -1252,10 +1266,9 @@ static RISCVException write_mhpmcounter(CPURISCVState *env, int csrno,
1252
1266
return RISCV_EXCP_NONE ;
1253
1267
}
1254
1268
1255
- static RISCVException write_mhpmcounterh (CPURISCVState * env , int csrno ,
1256
- target_ulong val )
1269
+ static RISCVException riscv_pmu_write_ctrh (CPURISCVState * env , target_ulong val ,
1270
+ uint32_t ctr_idx )
1257
1271
{
1258
- int ctr_idx = csrno - CSR_MCYCLEH ;
1259
1272
PMUCTRState * counter = & env -> pmu_ctrs [ctr_idx ];
1260
1273
uint64_t mhpmctr_val = counter -> mhpmcounter_val ;
1261
1274
uint64_t mhpmctrh_val = val ;
@@ -1277,6 +1290,20 @@ static RISCVException write_mhpmcounterh(CPURISCVState *env, int csrno,
1277
1290
return RISCV_EXCP_NONE ;
1278
1291
}
1279
1292
1293
+ static int write_mhpmcounter (CPURISCVState * env , int csrno , target_ulong val )
1294
+ {
1295
+ int ctr_idx = csrno - CSR_MCYCLE ;
1296
+
1297
+ return riscv_pmu_write_ctr (env , val , ctr_idx );
1298
+ }
1299
+
1300
+ static int write_mhpmcounterh (CPURISCVState * env , int csrno , target_ulong val )
1301
+ {
1302
+ int ctr_idx = csrno - CSR_MCYCLEH ;
1303
+
1304
+ return riscv_pmu_write_ctrh (env , val , ctr_idx );
1305
+ }
1306
+
1280
1307
RISCVException riscv_pmu_read_ctr (CPURISCVState * env , target_ulong * val ,
1281
1308
bool upper_half , uint32_t ctr_idx )
1282
1309
{
@@ -1342,6 +1369,167 @@ static RISCVException read_hpmcounterh(CPURISCVState *env, int csrno,
1342
1369
return riscv_pmu_read_ctr (env , val , true, ctr_index );
1343
1370
}
1344
1371
1372
+ static int rmw_cd_mhpmcounter (CPURISCVState * env , int ctr_idx ,
1373
+ target_ulong * val , target_ulong new_val ,
1374
+ target_ulong wr_mask )
1375
+ {
1376
+ if (wr_mask != 0 && wr_mask != -1 ) {
1377
+ return - EINVAL ;
1378
+ }
1379
+
1380
+ if (!wr_mask && val ) {
1381
+ riscv_pmu_read_ctr (env , val , false, ctr_idx );
1382
+ } else if (wr_mask ) {
1383
+ riscv_pmu_write_ctr (env , new_val , ctr_idx );
1384
+ } else {
1385
+ return - EINVAL ;
1386
+ }
1387
+
1388
+ return 0 ;
1389
+ }
1390
+
1391
+ static int rmw_cd_mhpmcounterh (CPURISCVState * env , int ctr_idx ,
1392
+ target_ulong * val , target_ulong new_val ,
1393
+ target_ulong wr_mask )
1394
+ {
1395
+ if (wr_mask != 0 && wr_mask != -1 ) {
1396
+ return - EINVAL ;
1397
+ }
1398
+
1399
+ if (!wr_mask && val ) {
1400
+ riscv_pmu_read_ctr (env , val , true, ctr_idx );
1401
+ } else if (wr_mask ) {
1402
+ riscv_pmu_write_ctrh (env , new_val , ctr_idx );
1403
+ } else {
1404
+ return - EINVAL ;
1405
+ }
1406
+
1407
+ return 0 ;
1408
+ }
1409
+
1410
+ static int rmw_cd_mhpmevent (CPURISCVState * env , int evt_index ,
1411
+ target_ulong * val , target_ulong new_val ,
1412
+ target_ulong wr_mask )
1413
+ {
1414
+ uint64_t mhpmevt_val = new_val ;
1415
+
1416
+ if (wr_mask != 0 && wr_mask != -1 ) {
1417
+ return - EINVAL ;
1418
+ }
1419
+
1420
+ if (!wr_mask && val ) {
1421
+ * val = env -> mhpmevent_val [evt_index ];
1422
+ if (riscv_cpu_cfg (env )-> ext_sscofpmf ) {
1423
+ * val &= ~MHPMEVENT_BIT_MINH ;
1424
+ }
1425
+ } else if (wr_mask ) {
1426
+ wr_mask &= ~MHPMEVENT_BIT_MINH ;
1427
+ mhpmevt_val = (new_val & wr_mask ) |
1428
+ (env -> mhpmevent_val [evt_index ] & ~wr_mask );
1429
+ if (riscv_cpu_mxl (env ) == MXL_RV32 ) {
1430
+ mhpmevt_val = mhpmevt_val |
1431
+ ((uint64_t )env -> mhpmeventh_val [evt_index ] << 32 );
1432
+ }
1433
+ env -> mhpmevent_val [evt_index ] = mhpmevt_val ;
1434
+ riscv_pmu_update_event_map (env , mhpmevt_val , evt_index );
1435
+ } else {
1436
+ return - EINVAL ;
1437
+ }
1438
+
1439
+ return 0 ;
1440
+ }
1441
+
1442
+ static int rmw_cd_mhpmeventh (CPURISCVState * env , int evt_index ,
1443
+ target_ulong * val , target_ulong new_val ,
1444
+ target_ulong wr_mask )
1445
+ {
1446
+ uint64_t mhpmevth_val ;
1447
+ uint64_t mhpmevt_val = env -> mhpmevent_val [evt_index ];
1448
+
1449
+ if (wr_mask != 0 && wr_mask != -1 ) {
1450
+ return - EINVAL ;
1451
+ }
1452
+
1453
+ if (!wr_mask && val ) {
1454
+ * val = env -> mhpmeventh_val [evt_index ];
1455
+ if (riscv_cpu_cfg (env )-> ext_sscofpmf ) {
1456
+ * val &= ~MHPMEVENTH_BIT_MINH ;
1457
+ }
1458
+ } else if (wr_mask ) {
1459
+ wr_mask &= ~MHPMEVENTH_BIT_MINH ;
1460
+ env -> mhpmeventh_val [evt_index ] =
1461
+ (new_val & wr_mask ) | (env -> mhpmeventh_val [evt_index ] & ~wr_mask );
1462
+ mhpmevth_val = env -> mhpmeventh_val [evt_index ];
1463
+ mhpmevt_val = mhpmevt_val | (mhpmevth_val << 32 );
1464
+ riscv_pmu_update_event_map (env , mhpmevt_val , evt_index );
1465
+ } else {
1466
+ return - EINVAL ;
1467
+ }
1468
+
1469
+ return 0 ;
1470
+ }
1471
+
1472
+ static int rmw_cd_ctr_cfg (CPURISCVState * env , int cfg_index , target_ulong * val ,
1473
+ target_ulong new_val , target_ulong wr_mask )
1474
+ {
1475
+ switch (cfg_index ) {
1476
+ case 0 : /* CYCLECFG */
1477
+ if (wr_mask ) {
1478
+ wr_mask &= ~MCYCLECFG_BIT_MINH ;
1479
+ env -> mcyclecfg = (new_val & wr_mask ) | (env -> mcyclecfg & ~wr_mask );
1480
+ } else {
1481
+ * val = env -> mcyclecfg &= ~MHPMEVENTH_BIT_MINH ;
1482
+ }
1483
+ break ;
1484
+ case 2 : /* INSTRETCFG */
1485
+ if (wr_mask ) {
1486
+ wr_mask &= ~MINSTRETCFG_BIT_MINH ;
1487
+ env -> minstretcfg = (new_val & wr_mask ) |
1488
+ (env -> minstretcfg & ~wr_mask );
1489
+ } else {
1490
+ * val = env -> minstretcfg &= ~MHPMEVENTH_BIT_MINH ;
1491
+ }
1492
+ break ;
1493
+ default :
1494
+ return - EINVAL ;
1495
+ }
1496
+ return 0 ;
1497
+ }
1498
+
1499
+ static int rmw_cd_ctr_cfgh (CPURISCVState * env , int cfg_index , target_ulong * val ,
1500
+ target_ulong new_val , target_ulong wr_mask )
1501
+ {
1502
+
1503
+ if (riscv_cpu_mxl (env ) != MXL_RV32 ) {
1504
+ return RISCV_EXCP_ILLEGAL_INST ;
1505
+ }
1506
+
1507
+ switch (cfg_index ) {
1508
+ case 0 : /* CYCLECFGH */
1509
+ if (wr_mask ) {
1510
+ wr_mask &= ~MCYCLECFGH_BIT_MINH ;
1511
+ env -> mcyclecfgh = (new_val & wr_mask ) |
1512
+ (env -> mcyclecfgh & ~wr_mask );
1513
+ } else {
1514
+ * val = env -> mcyclecfgh ;
1515
+ }
1516
+ break ;
1517
+ case 2 : /* INSTRETCFGH */
1518
+ if (wr_mask ) {
1519
+ wr_mask &= ~MINSTRETCFGH_BIT_MINH ;
1520
+ env -> minstretcfgh = (new_val & wr_mask ) |
1521
+ (env -> minstretcfgh & ~wr_mask );
1522
+ } else {
1523
+ * val = env -> minstretcfgh ;
1524
+ }
1525
+ break ;
1526
+ default :
1527
+ return - EINVAL ;
1528
+ }
1529
+ return 0 ;
1530
+ }
1531
+
1532
+
1345
1533
static RISCVException read_scountovf (CPURISCVState * env , int csrno ,
1346
1534
target_ulong * val )
1347
1535
{
@@ -1351,6 +1539,14 @@ static RISCVException read_scountovf(CPURISCVState *env, int csrno,
1351
1539
target_ulong * mhpm_evt_val ;
1352
1540
uint64_t of_bit_mask ;
1353
1541
1542
+ /* Virtualize scountovf for counter delegation */
1543
+ if (riscv_cpu_cfg (env )-> ext_sscofpmf &&
1544
+ riscv_cpu_cfg (env )-> ext_ssccfg &&
1545
+ get_field (env -> menvcfg , MENVCFG_CDE ) &&
1546
+ env -> virt_enabled ) {
1547
+ return RISCV_EXCP_VIRT_INSTRUCTION_FAULT ;
1548
+ }
1549
+
1354
1550
if (riscv_cpu_mxl (env ) == MXL_RV32 ) {
1355
1551
mhpm_evt_val = env -> mhpmeventh_val ;
1356
1552
of_bit_mask = MHPMEVENTH_BIT_OF ;
@@ -2293,11 +2489,72 @@ static int rmw_xireg_cd(CPURISCVState *env, int csrno,
2293
2489
target_ulong isel , target_ulong * val ,
2294
2490
target_ulong new_val , target_ulong wr_mask )
2295
2491
{
2296
- if (!riscv_cpu_cfg (env )-> ext_smcdeleg ) {
2297
- return RISCV_EXCP_ILLEGAL_INST ;
2492
+ int ret = - EINVAL ;
2493
+ int ctr_index = isel - ISELECT_CD_FIRST ;
2494
+ int isel_hpm_start = ISELECT_CD_FIRST + 3 ;
2495
+
2496
+ if (!riscv_cpu_cfg (env )-> ext_smcdeleg || !riscv_cpu_cfg (env )-> ext_ssccfg ) {
2497
+ ret = RISCV_EXCP_ILLEGAL_INST ;
2498
+ goto done ;
2298
2499
}
2299
- /* TODO: Implement the functionality later */
2300
- return RISCV_EXCP_NONE ;
2500
+
2501
+ /* Invalid siselect value for reserved */
2502
+ if (ctr_index == 1 ) {
2503
+ goto done ;
2504
+ }
2505
+
2506
+ /* sireg4 and sireg5 provides access RV32 only CSRs */
2507
+ if (((csrno == CSR_SIREG5 ) || (csrno == CSR_SIREG4 )) &&
2508
+ (riscv_cpu_mxl (env ) != MXL_RV32 )) {
2509
+ ret = RISCV_EXCP_ILLEGAL_INST ;
2510
+ goto done ;
2511
+ }
2512
+
2513
+ /* Check Sscofpmf dependancy */
2514
+ if (!riscv_cpu_cfg (env )-> ext_sscofpmf && csrno == CSR_SIREG5 &&
2515
+ (isel_hpm_start <= isel && isel <= ISELECT_CD_LAST )) {
2516
+ goto done ;
2517
+ }
2518
+
2519
+ /* Check smcntrpmf dependancy */
2520
+ if (!riscv_cpu_cfg (env )-> ext_smcntrpmf &&
2521
+ (csrno == CSR_SIREG2 || csrno == CSR_SIREG5 ) &&
2522
+ (ISELECT_CD_FIRST <= isel && isel < isel_hpm_start )) {
2523
+ goto done ;
2524
+ }
2525
+
2526
+ if (!get_field (env -> mcounteren , BIT (ctr_index )) ||
2527
+ !get_field (env -> menvcfg , MENVCFG_CDE )) {
2528
+ goto done ;
2529
+ }
2530
+
2531
+ switch (csrno ) {
2532
+ case CSR_SIREG :
2533
+ ret = rmw_cd_mhpmcounter (env , ctr_index , val , new_val , wr_mask );
2534
+ break ;
2535
+ case CSR_SIREG4 :
2536
+ ret = rmw_cd_mhpmcounterh (env , ctr_index , val , new_val , wr_mask );
2537
+ break ;
2538
+ case CSR_SIREG2 :
2539
+ if (ctr_index <= 2 ) {
2540
+ ret = rmw_cd_ctr_cfg (env , ctr_index , val , new_val , wr_mask );
2541
+ } else {
2542
+ ret = rmw_cd_mhpmevent (env , ctr_index , val , new_val , wr_mask );
2543
+ }
2544
+ break ;
2545
+ case CSR_SIREG5 :
2546
+ if (ctr_index <= 2 ) {
2547
+ ret = rmw_cd_ctr_cfgh (env , ctr_index , val , new_val , wr_mask );
2548
+ } else {
2549
+ ret = rmw_cd_mhpmeventh (env , ctr_index , val , new_val , wr_mask );
2550
+ }
2551
+ break ;
2552
+ default :
2553
+ goto done ;
2554
+ }
2555
+
2556
+ done :
2557
+ return ret ;
2301
2558
}
2302
2559
2303
2560
/*
@@ -2576,6 +2833,21 @@ static RISCVException write_mcountinhibit(CPURISCVState *env, int csrno,
2576
2833
return RISCV_EXCP_NONE ;
2577
2834
}
2578
2835
2836
+ static RISCVException read_scountinhibit (CPURISCVState * env , int csrno ,
2837
+ target_ulong * val )
2838
+ {
2839
+ /* S-mode can only access the bits delegated by M-mode */
2840
+ * val = env -> mcountinhibit & env -> mcounteren ;
2841
+ return RISCV_EXCP_NONE ;
2842
+ }
2843
+
2844
+ static RISCVException write_scountinhibit (CPURISCVState * env , int csrno ,
2845
+ target_ulong val )
2846
+ {
2847
+ write_mcountinhibit (env , csrno , val & env -> mcounteren );
2848
+ return RISCV_EXCP_NONE ;
2849
+ }
2850
+
2579
2851
static RISCVException read_mcounteren (CPURISCVState * env , int csrno ,
2580
2852
target_ulong * val )
2581
2853
{
@@ -2678,11 +2950,13 @@ static RISCVException write_menvcfg(CPURISCVState *env, int csrno,
2678
2950
target_ulong val )
2679
2951
{
2680
2952
const RISCVCPUConfig * cfg = riscv_cpu_cfg (env );
2681
- uint64_t mask = MENVCFG_FIOM | MENVCFG_CBIE | MENVCFG_CBCFE | MENVCFG_CBZE ;
2953
+ uint64_t mask = MENVCFG_FIOM | MENVCFG_CBIE | MENVCFG_CBCFE |
2954
+ MENVCFG_CBZE | MENVCFG_CDE ;
2682
2955
2683
2956
if (riscv_cpu_mxl (env ) == MXL_RV64 ) {
2684
2957
mask |= (cfg -> ext_svpbmt ? MENVCFG_PBMTE : 0 ) |
2685
2958
(cfg -> ext_sstc ? MENVCFG_STCE : 0 ) |
2959
+ (cfg -> ext_smcdeleg ? MENVCFG_CDE : 0 ) |
2686
2960
(cfg -> ext_svadu ? MENVCFG_ADUE : 0 );
2687
2961
2688
2962
if (env_archcpu (env )-> cfg .ext_zicfilp ) {
@@ -2717,7 +2991,8 @@ static RISCVException write_menvcfgh(CPURISCVState *env, int csrno,
2717
2991
const RISCVCPUConfig * cfg = riscv_cpu_cfg (env );
2718
2992
uint64_t mask = (cfg -> ext_svpbmt ? MENVCFG_PBMTE : 0 ) |
2719
2993
(cfg -> ext_sstc ? MENVCFG_STCE : 0 ) |
2720
- (cfg -> ext_svadu ? MENVCFG_ADUE : 0 );
2994
+ (cfg -> ext_svadu ? MENVCFG_ADUE : 0 ) |
2995
+ (cfg -> ext_smcdeleg ? MENVCFG_CDE : 0 );
2721
2996
uint64_t valh = (uint64_t )val << 32 ;
2722
2997
2723
2998
env -> menvcfg = (env -> menvcfg & ~mask ) | (valh & mask );
@@ -5304,6 +5579,11 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
5304
5579
[CSR_MNSTATUS ] = { "mnstatus" , rnmi , read_mnstatus , write_mnstatus ,
5305
5580
.min_priv_ver = PRIV_VERSION_1_12_0 },
5306
5581
5582
+ /* Supervisor Counter Delegation */
5583
+ [CSR_SCOUNTINHIBIT ] = {"scountinhibit" , scountinhibit_pred ,
5584
+ read_scountinhibit , write_scountinhibit ,
5585
+ .min_priv_ver = PRIV_VERSION_1_12_0 },
5586
+
5307
5587
/* Supervisor Trap Setup */
5308
5588
[CSR_SSTATUS ] = { "sstatus" , smode , read_sstatus , write_sstatus ,
5309
5589
NULL , read_sstatus_i128 },
0 commit comments