From nobody Tue Feb 10 10:54:49 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org ARC-Seal: i=1; a=rsa-sha256; t=1660157779; cv=none; d=zohomail.com; s=zohoarc; b=EZZlgZ3BbvWDJ9Us30ama3tQLtIKOpuhN1KyBPZfwwiDvKZqeF33nTiCvC6BNZ2Y3srj9OvUOUUUeeerWnkXCHrUGveEBfFlUzbsRN1Tw+kBIsDwox8S6wzy4b3zEOf+fzdPzBj3gv+nuERDzOpkALCs1Z3nah/CA1UX3E/k+4g= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1660157779; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=kKO5nq7SFLCs2QcNZwvlmy9QPHHSTSZrvaBBDp1Oedo=; b=ZYsuQxlQTTz1jaRKrO990oaTkMODRV/ogfNbsZeFJjVFdvxIJ225Nnaap46IUV41mc5/0XiY9CX65+aRV1xXOLSbcEknxedwq1KQ1AaK/ndUwjeAolqY173IKp36HLC9U/Z/6J6r+Em8XX+SVJFCrejZv/IOnL5DhsJhA+tOIrs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1660157779277987.9920855668456; Wed, 10 Aug 2022 11:56:19 -0700 (PDT) Received: from localhost ([::1]:59118 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oLqsM-0003V4-3f for importer@patchew.org; Wed, 10 Aug 2022 14:56:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43046) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oLqiX-0005Yi-CQ for qemu-devel@nongnu.org; Wed, 10 Aug 2022 14:46:12 -0400 Received: from mail-pj1-x102a.google.com ([2607:f8b0:4864:20::102a]:36646) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1oLqiT-0007ET-FD for qemu-devel@nongnu.org; Wed, 10 Aug 2022 14:46:09 -0400 Received: by mail-pj1-x102a.google.com with SMTP id 15-20020a17090a098f00b001f305b453feso3072317pjo.1 for ; Wed, 10 Aug 2022 11:46:04 -0700 (PDT) Received: from atishp.ba.rivosinc.com ([66.220.2.162]) by smtp.gmail.com with ESMTPSA id b13-20020a170903228d00b00162529828aesm13270142plh.109.2022.08.10.11.46.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 Aug 2022 11:46:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rivosinc-com.20210112.gappssmtp.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc; bh=kKO5nq7SFLCs2QcNZwvlmy9QPHHSTSZrvaBBDp1Oedo=; b=rTkRtiN1xxqTLR09203DjblQrISrrNpR9v7IYqDmJWPe9niLRSR8EwMInyseLFgw21 V+SyRl8PTcZqGJ5spnoaG6Nqc3yKKwSx+d3SB2S+EcvmbdGuNYyTqzWQJj/Fs44ynJDN 5NP9BTy6H/IbEX3CgvJjLt9tEJm13lznjifWVLLhwrBZWQV5gpqz1tpxP/59+oZLlbSg G5ruWx+kSNwMRn4c2hcMTzvKOKM1NRIsencqltBT6aX30lQ+TuaGZiEW86nDtw9XAdNM mvs+Bug4rqSeFs2HaS5MckzK8urvG+ms1QepQYjgQPtROs4tJc4nuFFhaSePZZuQCQz8 uSiA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=kKO5nq7SFLCs2QcNZwvlmy9QPHHSTSZrvaBBDp1Oedo=; b=pkRIntsRkamweNSfeVcTtv8oqEr3zux6SWHml0uqVZ57E1AQ6iRVLXTogXLOJlZmko rpmyniYXpIOz5TO46ENN8GjEl3dPfTrIrrtjGYNvfB8byYErI9Ni5grurSK2J1eRCFT2 AtjrrIEM8PmCWrMDpAPqmNmLOxIecU1yCSKzTOFyAID9iNeKHWcJAhfirQ/3LnOPHTjP BjkzPrK/2MICRKSlNn4BylV0xlh0ZdWZnRkMd0arykYxLOTor6Aa6NagG+wcqLO2wOyq IlYV3XkBsBAzIhz58pNnKWKAaAyv4FxDmCiS4KrZ/3X2DoIN7JC9eb+JHpOm4feJBkOq MNdQ== X-Gm-Message-State: ACgBeo1H7tZTkmhWbrYUoa4snmOQqZxRF/PQCweHY/ssLAjVwPcvxxJY wwIraG4U3tLqskiH+EOXldI6+NVjOTkAqw== X-Google-Smtp-Source: AA6agR6mQxdSJKSeXhJWhRi1lNcj/Ki/13LtUdNToguhjdLVSY7KfuaQj1SaC7KRtuq8qmhq26OROA== X-Received: by 2002:a17:90a:f002:b0:1f3:251:c48 with SMTP id bt2-20020a17090af00200b001f302510c48mr4977718pjb.22.1660157163302; Wed, 10 Aug 2022 11:46:03 -0700 (PDT) From: Atish Patra To: qemu-devel@nongnu.org Cc: Atish Patra , Alistair Francis , Alistair Francis , Bin Meng , Palmer Dabbelt , qemu-riscv@nongnu.org Subject: [PATCH v9 3/3] target/riscv: Add vstimecmp support Date: Wed, 10 Aug 2022 11:45:48 -0700 Message-Id: <20220810184548.3620153-4-atishp@rivosinc.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220810184548.3620153-1-atishp@rivosinc.com> References: <20220810184548.3620153-1-atishp@rivosinc.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::102a; envelope-from=atishp@rivosinc.com; helo=mail-pj1-x102a.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @rivosinc-com.20210112.gappssmtp.com) X-ZM-MESSAGEID: 1660157781530100001 Content-Type: text/plain; charset="utf-8" vstimecmp CSR allows the guest OS or to program the next guest timer interrupt directly. Thus, hypervisor no longer need to inject the timer interrupt to the guest if vstimecmp is used. This was ratified as a part of the Sstc extension. Reviewed-by: Alistair Francis Signed-off-by: Atish Patra Reviewed-by: Weiwei Li --- target/riscv/cpu.h | 4 ++ target/riscv/cpu_bits.h | 4 ++ target/riscv/cpu_helper.c | 11 +++-- target/riscv/csr.c | 88 ++++++++++++++++++++++++++++++++++++-- target/riscv/machine.c | 1 + target/riscv/time_helper.c | 16 +++++++ 6 files changed, 118 insertions(+), 6 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 4cda2905661e..1fd382b2717f 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -312,6 +312,8 @@ struct CPUArchState { /* Sstc CSRs */ uint64_t stimecmp; =20 + uint64_t vstimecmp; + /* physical memory protection */ pmp_table_t pmp_state; target_ulong mseccfg; @@ -366,6 +368,8 @@ struct CPUArchState { =20 /* Fields from here on are preserved across CPU reset. */ QEMUTimer *stimer; /* Internal timer for S-mode interrupt */ + QEMUTimer *vstimer; /* Internal timer for VS-mode interrupt */ + bool vstime_irq; =20 hwaddr kernel_addr; hwaddr fdt_addr; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index ac17cf1515c0..095dab19f512 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -257,6 +257,10 @@ #define CSR_VSIP 0x244 #define CSR_VSATP 0x280 =20 +/* Sstc virtual CSRs */ +#define CSR_VSTIMECMP 0x24D +#define CSR_VSTIMECMPH 0x25D + #define CSR_MTINST 0x34a #define CSR_MTVAL2 0x34b =20 diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 650574accf0a..1e4faa84e839 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -345,8 +345,9 @@ uint64_t riscv_cpu_all_pending(CPURISCVState *env) { uint32_t gein =3D get_field(env->hstatus, HSTATUS_VGEIN); uint64_t vsgein =3D (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0; + uint64_t vstip =3D (env->vstime_irq) ? MIP_VSTIP : 0; =20 - return (env->mip | vsgein) & env->mie; + return (env->mip | vsgein | vstip) & env->mie; } =20 int riscv_cpu_mirq_pending(CPURISCVState *env) @@ -605,7 +606,7 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t m= ask, uint64_t value) { CPURISCVState *env =3D &cpu->env; CPUState *cs =3D CPU(cpu); - uint64_t gein, vsgein =3D 0, old =3D env->mip; + uint64_t gein, vsgein =3D 0, vstip =3D 0, old =3D env->mip; bool locked =3D false; =20 if (riscv_cpu_virt_enabled(env)) { @@ -613,6 +614,10 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t = mask, uint64_t value) vsgein =3D (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0; } =20 + /* No need to update mip for VSTIP */ + mask =3D ((mask =3D=3D MIP_VSTIP) && env->vstime_irq) ? 0 : mask; + vstip =3D env->vstime_irq ? MIP_VSTIP : 0; + if (!qemu_mutex_iothread_locked()) { locked =3D true; qemu_mutex_lock_iothread(); @@ -620,7 +625,7 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t m= ask, uint64_t value) =20 env->mip =3D (env->mip & ~mask) | (value & mask); =20 - if (env->mip | vsgein) { + if (env->mip | vsgein | vstip) { cpu_interrupt(cs, CPU_INTERRUPT_HARD); } else { cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 9079d988ba08..38bb46db8f99 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -808,6 +808,7 @@ static RISCVException sstc(CPURISCVState *env, int csrn= o) { CPUState *cs =3D env_cpu(env); RISCVCPU *cpu =3D RISCV_CPU(cs); + bool hmode_check =3D false; =20 if (!cpu->cfg.ext_sstc || !env->rdtime_fn) { return RISCV_EXCP_ILLEGAL_INST; @@ -826,7 +827,18 @@ static RISCVException sstc(CPURISCVState *env, int csr= no) return RISCV_EXCP_ILLEGAL_INST; } =20 - return smode(env, csrno); + if (riscv_cpu_virt_enabled(env)) { + if (!(get_field(env->hcounteren, COUNTEREN_TM) & + get_field(env->henvcfg, HENVCFG_STCE))) { + return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; + } + } + + if ((csrno =3D=3D CSR_VSTIMECMP) || (csrno =3D=3D CSR_VSTIMECMPH)) { + hmode_check =3D true; + } + + return hmode_check ? hmode(env, csrno) : smode(env, csrno); } =20 static RISCVException sstc_32(CPURISCVState *env, int csrno) @@ -838,17 +850,72 @@ static RISCVException sstc_32(CPURISCVState *env, int= csrno) return sstc(env, csrno); } =20 +static RISCVException read_vstimecmp(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val =3D env->vstimecmp; + + return RISCV_EXCP_NONE; +} + +static RISCVException read_vstimecmph(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val =3D env->vstimecmp >> 32; + + return RISCV_EXCP_NONE; +} + +static RISCVException write_vstimecmp(CPURISCVState *env, int csrno, + target_ulong val) +{ + RISCVCPU *cpu =3D env_archcpu(env); + + if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { + env->vstimecmp =3D deposit64(env->vstimecmp, 0, 32, (uint64_t)val); + } else { + env->vstimecmp =3D val; + } + + riscv_timer_write_timecmp(cpu, env->vstimer, env->vstimecmp, + env->htimedelta, MIP_VSTIP); + + return RISCV_EXCP_NONE; +} + +static RISCVException write_vstimecmph(CPURISCVState *env, int csrno, + target_ulong val) +{ + RISCVCPU *cpu =3D env_archcpu(env); + + env->vstimecmp =3D deposit64(env->vstimecmp, 32, 32, (uint64_t)val); + riscv_timer_write_timecmp(cpu, env->vstimer, env->vstimecmp, + env->htimedelta, MIP_VSTIP); + + return RISCV_EXCP_NONE; +} + static RISCVException read_stimecmp(CPURISCVState *env, int csrno, target_ulong *val) { - *val =3D env->stimecmp; + if (riscv_cpu_virt_enabled(env)) { + *val =3D env->vstimecmp; + } else { + *val =3D env->stimecmp; + } + return RISCV_EXCP_NONE; } =20 static RISCVException read_stimecmph(CPURISCVState *env, int csrno, target_ulong *val) { - *val =3D env->stimecmp >> 32; + if (riscv_cpu_virt_enabled(env)) { + *val =3D env->vstimecmp >> 32; + } else { + *val =3D env->stimecmp >> 32; + } + return RISCV_EXCP_NONE; } =20 @@ -857,6 +924,10 @@ static RISCVException write_stimecmp(CPURISCVState *en= v, int csrno, { RISCVCPU *cpu =3D env_archcpu(env); =20 + if (riscv_cpu_virt_enabled(env)) { + return write_vstimecmp(env, csrno, val); + } + if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { env->stimecmp =3D deposit64(env->stimecmp, 0, 32, (uint64_t)val); } else { @@ -873,6 +944,10 @@ static RISCVException write_stimecmph(CPURISCVState *e= nv, int csrno, { RISCVCPU *cpu =3D env_archcpu(env); =20 + if (riscv_cpu_virt_enabled(env)) { + return write_vstimecmph(env, csrno, val); + } + env->stimecmp =3D deposit64(env->stimecmp, 32, 32, (uint64_t)val); riscv_timer_write_timecmp(cpu, env->stimer, env->stimecmp, 0, MIP_STIP= ); =20 @@ -1810,6 +1885,7 @@ static RISCVException rmw_mip64(CPURISCVState *env, i= nt csrno, if (csrno !=3D CSR_HVIP) { gin =3D get_field(env->hstatus, HSTATUS_VGEIN); old_mip |=3D (env->hgeip & ((target_ulong)1 << gin)) ? MIP_VSEIP := 0; + old_mip |=3D env->vstime_irq ? MIP_VSTIP : 0; } =20 if (ret_val) { @@ -3670,6 +3746,12 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] =3D { .min_priv_ver =3D PRIV_VERSION_1_12_0 }, [CSR_STIMECMPH] =3D { "stimecmph", sstc_32, read_stimecmph, write_stim= ecmph, .min_priv_ver =3D PRIV_VERSION_1_12_0 }, + [CSR_VSTIMECMP] =3D { "vstimecmp", sstc, read_vstimecmp, + write_vstimecmp, + .min_priv_ver =3D PRIV_VERSION_1_12_0 }, + [CSR_VSTIMECMPH] =3D { "vstimecmph", sstc_32, read_vstimecmph, + write_vstimecmph, + .min_priv_ver =3D PRIV_VERSION_1_12_0 }, =20 /* Supervisor Protection and Translation */ [CSR_SATP] =3D { "satp", smode, read_satp, write_satp = }, diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 622fface484e..4ba55705d147 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -92,6 +92,7 @@ static const VMStateDescription vmstate_hyper =3D { VMSTATE_UINTTL(env.hgeie, RISCVCPU), VMSTATE_UINTTL(env.hgeip, RISCVCPU), VMSTATE_UINT64(env.htimedelta, RISCVCPU), + VMSTATE_UINT64(env.vstimecmp, RISCVCPU), =20 VMSTATE_UINTTL(env.hvictl, RISCVCPU), VMSTATE_UINT8_ARRAY(env.hviprio, RISCVCPU, 64), diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c index f3fb5eac7b7b..8cce667dfd47 100644 --- a/target/riscv/time_helper.c +++ b/target/riscv/time_helper.c @@ -22,6 +22,14 @@ #include "time_helper.h" #include "hw/intc/riscv_aclint.h" =20 +static void riscv_vstimer_cb(void *opaque) +{ + RISCVCPU *cpu =3D opaque; + CPURISCVState *env =3D &cpu->env; + env->vstime_irq =3D 1; + riscv_cpu_update_mip(cpu, MIP_VSTIP, BOOL_TO_MASK(1)); +} + static void riscv_stimer_cb(void *opaque) { RISCVCPU *cpu =3D opaque; @@ -47,10 +55,16 @@ void riscv_timer_write_timecmp(RISCVCPU *cpu, QEMUTimer= *timer, * If we're setting an stimecmp value in the "past", * immediately raise the timer interrupt */ + if (timer_irq =3D=3D MIP_VSTIP) { + env->vstime_irq =3D 1; + } riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(1)); return; } =20 + if (timer_irq =3D=3D MIP_VSTIP) { + env->vstime_irq =3D 0; + } /* Clear the [V]STIP bit in mip */ riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(0)); =20 @@ -95,4 +109,6 @@ void riscv_timer_init(RISCVCPU *cpu) env->stimer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, &riscv_stimer_cb, cpu= ); env->stimecmp =3D 0; =20 + env->vstimer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, &riscv_vstimer_cb, c= pu); + env->vstimecmp =3D 0; } --=20 2.25.1