Skip to content

Commit

Permalink
fix(intr, aia): update xtopi and use xtopi to update intr deleg
Browse files Browse the repository at this point in the history
* NEMU could get xtopei csr register to update xtopi by difftest
* add m/s/vsiprio struct and add init iprio method
* add update xtopi method to update interrupt deleg when intr raise
* add xtopei, xtopi, xireg csr registers read/write
  • Loading branch information
sinceforYy committed Nov 13, 2024
1 parent fe45f57 commit 3d3534a
Show file tree
Hide file tree
Showing 9 changed files with 497 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/cpu/cpu-exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <generated/autoconf.h>
#include <profiling/profiling_control.h>
#include "../local-include/trigger.h"
#include "../local-include/aia.h"

/* The assembly code of instructions executed is only output to the screen
* when the number of instructions executed is less than this value.
Expand Down
6 changes: 6 additions & 0 deletions src/cpu/difftest/ref.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,12 @@ void difftest_get_store_event_other_info(void *info) {



void difftest_aia_xtopei(void *xtopei) {
#ifdef CONFIG_RV_IMSIC
memcpy(&cpu.xtopei, xtopei, sizeof(struct Xtopei));
#endif
}

void difftest_enable_debug() {
#ifdef CONFIG_SHARE
dynamic_config.debug_difftest = true;
Expand Down
18 changes: 18 additions & 0 deletions src/isa/riscv64/include/isa-def.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ struct NonRegInterruptPending {
bool lcofi_req;
};

struct Xtopei {
uint64_t mtopei;
uint64_t stopei;
uint64_t vstopei;
};

struct DebugInfo {
uint64_t current_pc;
};
Expand All @@ -73,6 +79,8 @@ struct MemEventQueryResult {
#endif

typedef struct TriggerModule TriggerModule;
typedef struct IpriosModule IpriosModule;
typedef struct IpriosSort IpriosSort;

typedef struct {
// Below will be synced by regcpy when run difftest, DO NOT TOUCH
Expand Down Expand Up @@ -149,6 +157,8 @@ typedef struct {

struct NonRegInterruptPending non_reg_interrupt_pending;

struct Xtopei xtopei;

// User defined debug info
struct DebugInfo debug;
#ifdef CONFIG_QUERY_REF
Expand All @@ -174,6 +184,14 @@ typedef struct {

trap_info_t trapInfo;

#ifdef CONFIG_RV_IMSIC
IpriosModule* MIprios;
IpriosModule* SIprios;
IpriosSort* MIpriosSort;
IpriosSort* SIpriosSort;
IpriosSort* VSIpriosSort;
#endif

} riscv64_CPU_state;

// decode
Expand Down
7 changes: 7 additions & 0 deletions src/isa/riscv64/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ void init_csr();
#ifdef CONFIG_RV_SDTRIG
void init_trigger();
#endif // CONFIG_RV_SDTRIG
#ifdef CONFIG_RV_AIA
void init_iprio();
#endif

#if !defined(CONFIG_SHARE) || defined(CONFIG_LIGHTQS)
void init_clint();
Expand Down Expand Up @@ -202,6 +205,10 @@ void init_isa() {
init_trigger();
#endif // CONFIG_RV_SDTRIG

#ifdef CONFIG_RV_IMSIC
init_iprio();
#endif

#define MSTATEEN0_RESET 0xdc00000000000001ULL
#define HSTATEEN0_RESET 0xdc00000000000001ULL
#define SSTATEEN0_RESET 0x0000000000000001ULL
Expand Down
38 changes: 38 additions & 0 deletions src/isa/riscv64/local-include/aia.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#ifdef CONFIG_RV_IMSIC

#ifndef __AIA_H__
#define __AIA_H__

#include "common.h"
#include "csr.h"
#include "intr.h"

#define IPRIO_ENABLE_NUM (CONFIG_INTR_NUM - 3)

typedef struct {
word_t val;
} Iprio;

typedef struct IpriosModule {
Iprio iprios[CONFIG_IPRIO_NUM];
} IpriosModule;

typedef struct {
bool enable;
uint8_t priority;
} IpriosEnable;

typedef struct IpriosSort {
IpriosEnable ipriosEnable[IPRIO_ENABLE_NUM];
} IpriosSort;

bool iprio_is_zero(IpriosModule* iprios);
void set_iprios_sort(uint64_t topi_gather, IpriosSort* iprios_sort, IpriosModule* iprios);
void set_viprios_sort(uint64_t topi_gather);
uint8_t high_iprio(IpriosSort* ipriosSort, uint8_t xei);
uint8_t get_prio_idx_in_group(uint8_t irq);

extern int interrupt_default_prio[IPRIO_ENABLE_NUM];

#endif // __AIA_H__
#endif // CONFIG_RV_IMSIC
11 changes: 11 additions & 0 deletions src/isa/riscv64/local-include/csr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1248,6 +1248,14 @@ CSR_STRUCT_START(hvictl)
CSR_STRUCT_END(hvictl)

CSR_STRUCT_START(hviprio1)
uint64_t intr0 : 8; // [7 : 0] reserved
uint64_t ssi : 8; // [16: 8]
uint64_t intr4 : 8; // [23:16] reserved
uint64_t sti : 8; // [31:24]
uint64_t intr8 : 8; // [39:32] reserved
uint64_t coi : 8; // [47:40]
uint64_t intr14 : 8; // [55:48]
uint64_t intr15 : 8; // [63:56]
CSR_STRUCT_END(hviprio1)

CSR_STRUCT_START(hviprio2)
Expand Down Expand Up @@ -1529,6 +1537,9 @@ void csr_prepare();

word_t gen_status_sd(word_t status);
word_t get_mip();
void update_mtopi();
void update_stopi();
void update_vstopi();

word_t csrid_read(uint32_t csrid);

Expand Down
138 changes: 138 additions & 0 deletions src/isa/riscv64/system/aia.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#include "isa.h"
#include "cpu/cpu.h"
#include "../local-include/aia.h"

#ifdef CONFIG_RV_IMSIC

int interrupt_default_prio[IPRIO_ENABLE_NUM] = {
// custom highest group
63, 31, 62,
61, 30, 60,
// local high group
47, 23, 46,
45, 22, 44,
43, 21, 42,
41, 20, 40,
// custom middle high group
59, 29, 58,
57, 28, 56,
// priv arch group
IRQ_MEIP, IRQ_MSIP, IRQ_MTIP,
IRQ_SEIP, IRQ_SSIP, IRQ_STIP,
IRQ_SGEI,
IRQ_VSEIP, IRQ_VSSIP, IRQ_VSTIP,
IRQ_LCOFI, 14, 15,
// custom middle low group
55, 27, 54,
53, 26, 52,
// local low group
39, 19, 38,
37, 18, 36,
35, 17, 34,
33, 16, 32,
// custom lowest group
51, 25, 50,
49, 24, 48
};

bool iprio_is_zero(IpriosModule* iprios) {
bool is_zero = true;
for (int i = 0; i < CONFIG_IPRIO_NUM; i++) {
is_zero &= iprios->iprios[i].val == 0;
}
return is_zero;
}

uint8_t get_prio_idx_in_group(uint8_t irq) {
uint8_t idx = 0;
for (int i = 0; i < IPRIO_ENABLE_NUM; i++) {
if (irq == interrupt_default_prio[i]) {
idx = i;
}
}
return idx;
}

void set_iprios_sort(uint64_t topi_gather, IpriosSort* iprios_sort, IpriosModule* iprios) {
for (int i = 0; i < IPRIO_ENABLE_NUM; i++) {
if ((topi_gather >> interrupt_default_prio[i]) & 0x1) {
iprios_sort->ipriosEnable[i].enable = true;
iprios_sort->ipriosEnable[i].priority = (iprios->iprios[interrupt_default_prio[i]/8].val >> (8 * (interrupt_default_prio[i]%8))) & 0xff;
} else {
iprios_sort->ipriosEnable[i].enable = false;
iprios_sort->ipriosEnable[i].priority = 0;
}
}
}

void set_viprios_sort(uint64_t topi_gather) {
// supervisor software interrupt
word_t idx = 0;
if ((topi_gather >> IRQ_SSIP) & 0x1) {
idx = get_prio_idx_in_group(IRQ_SSIP);
cpu.VSIpriosSort->ipriosEnable[idx].enable = true;
cpu.VSIpriosSort->ipriosEnable[idx].priority = hviprio1->ssi;
}
// supervisor timer interrupt
if ((topi_gather >> IRQ_STIP) & 0x1) {
idx = get_prio_idx_in_group(IRQ_STIP);
cpu.VSIpriosSort->ipriosEnable[idx].enable = true;
cpu.VSIpriosSort->ipriosEnable[idx].priority = hviprio1->sti;
}
// counter overflow interrupt
if ((topi_gather >> IRQ_LCOFI) & 0x1) {
idx = get_prio_idx_in_group(IRQ_LCOFI);
cpu.VSIpriosSort->ipriosEnable[idx].enable = true;
cpu.VSIpriosSort->ipriosEnable[idx].priority = hviprio1->coi;
}
for (int i = 0; i <= 1; i++) {
if ((topi_gather >> (i+14)) & 0x1) {
idx = get_prio_idx_in_group(i+14);
cpu.VSIpriosSort->ipriosEnable[idx].enable = true;
cpu.VSIpriosSort->ipriosEnable[idx].priority = hviprio1->val & (0xf << 8*(i+6));
}
}
for (int i = 0; i <= 7; i++) {
if ((topi_gather >> (i+16)) & 0x1) {
idx = get_prio_idx_in_group(i+16);
cpu.VSIpriosSort->ipriosEnable[idx].enable = true;
cpu.VSIpriosSort->ipriosEnable[idx].priority = hviprio2->val & (0xf << 8*i);
}
}
}

uint8_t high_iprio(IpriosSort* ipriosSort, uint8_t xei) {
uint8_t high_prio_idx = 0;
for (int i = 0; i < IPRIO_ENABLE_NUM; i++) {
if (ipriosSort->ipriosEnable[i].enable && !ipriosSort->ipriosEnable[i+1].enable) {
high_prio_idx = i;
} else if (!ipriosSort->ipriosEnable[i].enable && ipriosSort->ipriosEnable[i+1].enable) {
high_prio_idx = i + 1;
} else if (ipriosSort->ipriosEnable[i].enable && ipriosSort->ipriosEnable[i+1].enable) {
if ((ipriosSort->ipriosEnable[i].priority == 0) && (ipriosSort->ipriosEnable[i+1].priority == 0)) {
high_prio_idx = i;
} else if ((ipriosSort->ipriosEnable[i].priority == 0) && (ipriosSort->ipriosEnable[i+1].priority != 0)) {
if (i <= get_prio_idx_in_group(xei)) {
high_prio_idx = i;
} else {
high_prio_idx = i + 1;
}
} else if ((ipriosSort->ipriosEnable[i].priority != 0) && (ipriosSort->ipriosEnable[i+1].priority == 0)) {
if (i + 1 <= get_prio_idx_in_group(xei)) {
high_prio_idx = i + 1;
} else {
high_prio_idx = i;
}
} else if ((ipriosSort->ipriosEnable[i].priority != 0) && (ipriosSort->ipriosEnable[i+1].priority != 0)) {
if (ipriosSort->ipriosEnable[i].priority <= ipriosSort->ipriosEnable[i+1].priority) {
high_prio_idx = i;
} else {
high_prio_idx = i + 1;
}
}
}
}
return high_prio_idx;
}

#endif
22 changes: 21 additions & 1 deletion src/isa/riscv64/system/intr.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,31 @@ void update_mmu_state();
#ifdef CONFIG_RVH
bool intr_deleg_S(word_t exceptionNO) {
bool isNMI = MUXDEF(CONFIG_RV_SMRNMI, cpu.hasNMI && (exceptionNO & INTR_BIT), false);
word_t deleg = (exceptionNO & INTR_BIT ? mideleg->val : medeleg->val);
#ifdef CONFIG_RV_AIA
word_t deleg = (exceptionNO & INTR_BIT ?
(((mtopi->iid == 0) && (stopi->iid != 0)) ? (1 << stopi->iid) : 0)
: medeleg->val);
#else
word_t deleg = (exceptionNO & INTR_BIT) ? mideleg->val : medeleg->val;
#endif
bool delegS = ((deleg & (1 << (exceptionNO & 0xff))) != 0) && (cpu.mode < MODE_M) && !isNMI;
return delegS;
}
bool intr_deleg_VS(word_t exceptionNO){
bool isNMI = MUXDEF(CONFIG_RV_SMRNMI, cpu.hasNMI && (exceptionNO & INTR_BIT), false);
bool delegS = intr_deleg_S(exceptionNO);
#ifdef CONFIG_RV_AIA
word_t intrCode = (vstopi->iid == IRQ_SSIP) || (vstopi->iid == IRQ_STIP) || (vstopi->iid == IRQ_SEIP) ? (vstopi->iid + 1) : vstopi->iid;
word_t deleg = (exceptionNO & INTR_BIT ?
(((mtopi->iid == 0) && (stopi->iid == 0) && (vstopi->iid != 0)) ? (1 << intrCode) : 0)
: hedeleg->val);
bool delegVS = cpu.v && ((deleg & (1 << (exceptionNO & 0xff))) != 0) && (cpu.mode < MODE_M) && !isNMI;
return exceptionNO & INTR_BIT ? delegVS : delegS && delegVS;
#else
word_t deleg = (exceptionNO & INTR_BIT ? hideleg->val : hedeleg->val);
bool delegVS = cpu.v && ((deleg & (1 << (exceptionNO & 0xff))) != 0) && (cpu.mode < MODE_M) && !isNMI;
return delegS && delegVS;
#endif
}

#else
Expand Down Expand Up @@ -117,6 +132,11 @@ word_t raise_intr(word_t NO, vaddr_t epc) {
return 0;
}
#endif // CONFIG_RV_SMRNMI
#ifdef CONFIG_RV_IMSIC
update_mtopi();
update_stopi();
update_vstopi();
#endif // CONFIG_RV_IMSIC
bool isNMI = MUXDEF(CONFIG_RV_SMRNMI, cpu.hasNMI && (NO & INTR_BIT), false);
bool delegS = intr_deleg_S(NO);
bool delegM = !delegS && !isNMI;
Expand Down
Loading

0 comments on commit 3d3534a

Please sign in to comment.