[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v6 13/23] target/riscv: Implement AIA mtopi, stopi, and vstop
From: |
Anup Patel |
Subject: |
Re: [PATCH v6 13/23] target/riscv: Implement AIA mtopi, stopi, and vstopi CSRs |
Date: |
Thu, 13 Jan 2022 16:18:09 +0530 |
On Wed, Jan 12, 2022 at 5:46 PM Frank Chang <frank.chang@sifive.com> wrote:
>
> Anup Patel <anup@brainfault.org> 於 2021年12月30日 週四 下午8:47寫道:
>>
>> From: Anup Patel <anup.patel@wdc.com>
>>
>> The AIA specification introduces new [m|s|vs]topi CSRs for
>> reporting pending local IRQ number and associated IRQ priority.
>>
>> Signed-off-by: Anup Patel <anup.patel@wdc.com>
>> Signed-off-by: Anup Patel <anup@brainfault.org>
>> ---
>> target/riscv/csr.c | 156 +++++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 156 insertions(+)
>>
>> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
>> index 55e747fbf7..5a27c3bfbb 100644
>> --- a/target/riscv/csr.c
>> +++ b/target/riscv/csr.c
>> @@ -190,6 +190,15 @@ static int smode32(CPURISCVState *env, int csrno)
>> return smode(env, csrno);
>> }
>>
>> +static int aia_smode(CPURISCVState *env, int csrno)
>> +{
>> + if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
>> + return RISCV_EXCP_ILLEGAL_INST;
>> + }
>> +
>> + return smode(env, csrno);
>> +}
>> +
>> static int aia_smode32(CPURISCVState *env, int csrno)
>> {
>> if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
>> @@ -502,6 +511,8 @@ static RISCVException read_timeh(CPURISCVState *env, int
>> csrno,
>> #define VS_MODE_INTERRUPTS ((uint64_t)(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP))
>> #define HS_MODE_INTERRUPTS ((uint64_t)(MIP_SGEIP | VS_MODE_INTERRUPTS))
>>
>> +#define VSTOPI_NUM_SRCS 5
>
>
> Nit:
> VSTOPI_NUM_SRCS can be reduced to 2 as AIA spec says:
> The list of candidate interrupts can be reduced to two finalists relatively.
> But it's fine to keep it to 5 if you think it has better readability.
Let's keep is 5 for now. This is little high to ensure that
we don't run out space in the candidate array.
Regards,
Anup
>
>>
>> +
>> static const uint64_t delegable_ints = S_MODE_INTERRUPTS |
>> VS_MODE_INTERRUPTS;
>> static const uint64_t vs_delegable_ints = VS_MODE_INTERRUPTS;
>> @@ -862,6 +873,28 @@ static RISCVException rmw_mieh(CPURISCVState *env, int
>> csrno,
>> return ret;
>> }
>>
>> +static int read_mtopi(CPURISCVState *env, int csrno, target_ulong *val)
>> +{
>> + int irq;
>> + uint8_t iprio;
>> +
>> + irq = riscv_cpu_mirq_pending(env);
>> + if (irq <= 0 || irq > 63) {
>> + *val = 0;
>> + } else {
>> + iprio = env->miprio[irq];
>> + if (!iprio) {
>> + if (riscv_cpu_default_priority(irq) > IPRIO_DEFAULT_M) {
>> + iprio = IPRIO_MMAXIPRIO;
>> + }
>> + }
>> + *val = (irq & TOPI_IID_MASK) << TOPI_IID_SHIFT;
>> + *val |= iprio;
>> + }
>> +
>> + return RISCV_EXCP_NONE;
>> +}
>> +
>> static RISCVException read_mtvec(CPURISCVState *env, int csrno,
>> target_ulong *val)
>> {
>> @@ -1391,6 +1424,120 @@ static RISCVException write_satp(CPURISCVState *env,
>> int csrno,
>> return RISCV_EXCP_NONE;
>> }
>>
>> +static int read_vstopi(CPURISCVState *env, int csrno, target_ulong *val)
>> +{
>> + int irq, ret;
>> + target_ulong topei;
>> + uint64_t vseip, vsgein;
>> + uint32_t iid, iprio, hviid, hviprio, gein;
>> + uint32_t s, scount = 0, siid[VSTOPI_NUM_SRCS], siprio[VSTOPI_NUM_SRCS];
>> +
>> + gein = get_field(env->hstatus, HSTATUS_VGEIN);
>> + hviid = get_field(env->hvictl, HVICTL_IID);
>> + hviprio = get_field(env->hvictl, HVICTL_IPRIO);
>> +
>> + if (gein) {
>> + vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
>> + vseip = env->mie & (env->mip | vsgein) & MIP_VSEIP;
>> + if (gein <= env->geilen && vseip) {
>> + siid[scount] = IRQ_S_EXT;
>> + siprio[scount] = IPRIO_MMAXIPRIO + 1;
>> + if (env->aia_ireg_rmw_fn[PRV_S]) {
>> + /*
>> + * Call machine specific IMSIC register emulation for
>> + * reading TOPEI.
>> + */
>> + ret = env->aia_ireg_rmw_fn[PRV_S](
>> + env->aia_ireg_rmw_fn_arg[PRV_S],
>> + AIA_MAKE_IREG(ISELECT_IMSIC_TOPEI, PRV_S, true,
>> gein,
>> + riscv_cpu_mxl_bits(env)),
>> + &topei, 0, 0);
>> + if (!ret && topei) {
>> + siprio[scount] = topei & IMSIC_TOPEI_IPRIO_MASK;
>> + }
>> + }
>> + scount++;
>> + }
>> + } else {
>> + if (hviid == IRQ_S_EXT && hviprio) {
>> + siid[scount] = IRQ_S_EXT;
>> + siprio[scount] = hviprio;
>> + scount++;
>> + }
>> + }
>> +
>> + if (env->hvictl & HVICTL_VTI) {
>> + if (hviid != IRQ_S_EXT) {
>> + siid[scount] = hviid;
>> + siprio[scount] = hviprio;
>> + scount++;
>> + }
>> + } else {
>> + irq = riscv_cpu_vsirq_pending(env);
>> + if (irq != IRQ_S_EXT && 0 < irq && irq <= 63) {
>> + siid[scount] = irq;
>> + siprio[scount] = env->hviprio[irq];
>> + scount++;
>> + }
>> + }
>> +
>> + iid = 0;
>> + iprio = UINT_MAX;
>> + for (s = 0; s < scount; s++) {
>> + if (siprio[s] < iprio) {
>> + iid = siid[s];
>> + iprio = siprio[s];
>> + }
>> + }
>> +
>> + if (iid) {
>> + if (env->hvictl & HVICTL_IPRIOM) {
>> + if (iprio > IPRIO_MMAXIPRIO) {
>> + iprio = IPRIO_MMAXIPRIO;
>> + }
>> + if (!iprio) {
>> + if (riscv_cpu_default_priority(iid) > IPRIO_DEFAULT_S) {
>> + iprio = IPRIO_MMAXIPRIO;
>> + }
>> + }
>> + } else {
>> + iprio = 1;
>> + }
>> + } else {
>> + iprio = 0;
>> + }
>> +
>> + *val = (iid & TOPI_IID_MASK) << TOPI_IID_SHIFT;
>> + *val |= iprio;
>> + return RISCV_EXCP_NONE;
>> +}
>> +
>> +static int read_stopi(CPURISCVState *env, int csrno, target_ulong *val)
>> +{
>> + int irq;
>> + uint8_t iprio;
>> +
>> + if (riscv_cpu_virt_enabled(env)) {
>> + return read_vstopi(env, CSR_VSTOPI, val);
>> + }
>> +
>> + irq = riscv_cpu_sirq_pending(env);
>> + if (irq <= 0 || irq > 63) {
>> + *val = 0;
>> + } else {
>> + iprio = env->siprio[irq];
>> + if (!iprio) {
>> + if (riscv_cpu_default_priority(irq) > IPRIO_DEFAULT_S) {
>> + iprio = IPRIO_MMAXIPRIO;
>> + }
>> + }
>> + *val = (irq & TOPI_IID_MASK) << TOPI_IID_SHIFT;
>> + *val |= iprio;
>> + }
>> +
>> + return RISCV_EXCP_NONE;
>> +}
>> +
>> /* Hypervisor Extensions */
>> static RISCVException read_hstatus(CPURISCVState *env, int csrno,
>> target_ulong *val)
>> @@ -2389,6 +2536,9 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
>> [CSR_MTVAL] = { "mtval", any, read_mtval, write_mtval },
>> [CSR_MIP] = { "mip", any, NULL, NULL, rmw_mip },
>>
>> + /* Machine-Level Interrupts (AIA) */
>> + [CSR_MTOPI] = { "mtopi", aia_any, read_mtopi },
>> +
>> /* Virtual Interrupts for Supervisor Level (AIA) */
>> [CSR_MVIEN] = { "mvien", aia_any, read_zero, write_ignore },
>> [CSR_MVIP] = { "mvip", aia_any, read_zero, write_ignore },
>> @@ -2416,6 +2566,9 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
>> /* Supervisor Protection and Translation */
>> [CSR_SATP] = { "satp", smode, read_satp, write_satp },
>>
>> + /* Supervisor-Level Interrupts (AIA) */
>> + [CSR_STOPI] = { "stopi", aia_smode, read_stopi },
>> +
>> /* Supervisor-Level High-Half CSRs (AIA) */
>> [CSR_SIEH] = { "sieh", aia_smode32, NULL, NULL, rmw_sieh },
>> [CSR_SIPH] = { "siph", aia_smode32, NULL, NULL, rmw_siph },
>> @@ -2454,6 +2607,9 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
>> [CSR_HVIPRIO1] = { "hviprio1", aia_hmode, read_hviprio1,
>> write_hviprio1 },
>> [CSR_HVIPRIO2] = { "hviprio2", aia_hmode, read_hviprio2,
>> write_hviprio2 },
>>
>> + /* VS-Level Interrupts (H-extension with AIA) */
>> + [CSR_VSTOPI] = { "vstopi", aia_hmode, read_vstopi },
>> +
>> /* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */
>> [CSR_HIDELEGH] = { "hidelegh", aia_hmode32, NULL, NULL,
>> rmw_hidelegh },
>> [CSR_HVIENH] = { "hvienh", aia_hmode32, read_zero,
>> write_ignore },
>> --
>> 2.25.1
>>
>>
>
> Reviewed-by: Frank Chang <frank.chang@sifive.com>