From patchwork Wed Sep 7 08:03:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alistair Francis X-Patchwork-Id: 12968714 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4BF1CECAAD3 for ; Wed, 7 Sep 2022 09:27:16 +0000 (UTC) Received: from localhost ([::1]:52696 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oVrL1-0007ui-B7 for qemu-devel@archiver.kernel.org; Wed, 07 Sep 2022 05:27:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:48560) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oVq5C-0004xZ-8o for qemu-devel@nongnu.org; Wed, 07 Sep 2022 04:06:51 -0400 Received: from esa5.hgst.iphmx.com ([216.71.153.144]:1923) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oVq5A-0004Ud-0K for qemu-devel@nongnu.org; Wed, 07 Sep 2022 04:06:50 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1662538006; x=1694074006; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=mJseNOyurbSTqGWYzSNF8TtaRhTeuh4Q+s+WdbPkyzc=; b=C3JUAvua9p9iMgjvk7MW/XiGhhJw2CGeX5YsuQM9Q9JGSb92IwhL2IkX otazDzd49K+7AdY3eH/tXRz4v/PoWVutYfrvF7H7yqdRK4gzmpcCPHOij P+7E2X6kO2Rj+1DtBBpcyai+1f4HtC7jSKJayOkIXj89S7yTlRYdDRbXV 32Z/+TS/S0UZF6iolwhrcM0KI0QZSmC8gzfJ6DCQnvcN3p+ctInxAm9TF uppJu75SclqlozAdDVZS/1FnQwylVnTP/sjOX9L40vgbyB9QxG+N7y3iD +8TgyUQwlif5BCDuqsrC8uYb/BLblFV+FJy9ccqFfWUORGdokJBSs/vj4 A==; X-IronPort-AV: E=Sophos;i="5.93,296,1654531200"; d="scan'208";a="210715126" Received: from uls-op-cesaip02.wdc.com (HELO uls-op-cesaep02.wdc.com) ([199.255.45.15]) by ob1.hgst.iphmx.com with ESMTP; 07 Sep 2022 16:05:26 +0800 IronPort-SDR: 1p3+k5QcgTnYk5Xq33cN/VlDz/kduQLasrMecx8z/NFv892K48f6VRKQa0ShOkgFikrBv4j5Jl JirMDDyXUbonG4McXpZHH9I4tGDlMvmTZ3xnwNYkXWeuI1vAfesLf8pMEEBNN+E53Ha4xltnsi 4ciR/5Q5k4ZXoD+obKiuwYUH2KVp0QDLKtl13c15j6an9vlwOFHwtx6VbA8tgWdnC6MzWKftcA oUrYd9tK0yeb/LyhPe/nBROGyUhCrzXUoKfF3ibsNT8/6RwDJNUiWde5qITJyFOBPB7GSWLyNx 8jqhjgpDSmIUJbFt/VNwJa7Y Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep02.wdc.com with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 07 Sep 2022 00:20:24 -0700 IronPort-SDR: fPFdnTIxbYnDAOH1RFVCybvenk9T2ewmbjHFP3rU3sR3fv1qhYlLJ0+WyyyfHa3uVPFSltSQDK JK5h8Qh7Sw2PMetob87iosjRfIiFaF0YQaQeCkxoF3BLajNx+a9CnbFoo0wPjE02R3cWxNHGuh xh5LmlHWGPKAtb1TyE4HnPIIhvL4OPiV5wo2gHFSHtUbwWaxms5JBiuimZ6mEIUx+vKx8Hw+B5 eTP5P9rNgmYnFStbwZixEtqViVFt/PK4lpQAId9nJ961glOrCy8HcEKUAAYvbglEL7Ip/nZej3 EcU= WDCIronportException: Internal Received: from unknown (HELO toolbox.wdc.com) ([10.225.167.94]) by uls-op-cesaip01.wdc.com with ESMTP; 07 Sep 2022 01:05:26 -0700 To: qemu-devel@nongnu.org, peter.maydell@linaro.org Cc: alistair23@gmail.com, Atish Patra , Alistair Francis Subject: [PULL 39/44] target/riscv: Add vstimecmp support Date: Wed, 7 Sep 2022 10:03:48 +0200 Message-Id: <20220907080353.111926-40-alistair.francis@wdc.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20220907080353.111926-1-alistair.francis@wdc.com> References: <20220907080353.111926-1-alistair.francis@wdc.com> MIME-Version: 1.0 Received-SPF: pass client-ip=216.71.153.144; envelope-from=prvs=242877ce7=alistair.francis@wdc.com; helo=esa5.hgst.iphmx.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham 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+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Reply-to: Alistair Francis X-Patchwork-Original-From: Alistair Francis via From: Alistair Francis From: Atish Patra 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 Message-Id: <20220824221357.41070-4-atishp@rivosinc.com> Signed-off-by: Alistair Francis --- 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 d2529b757a..d895a0af2c 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -311,6 +311,8 @@ struct CPUArchState { /* Sstc CSRs */ uint64_t stimecmp; + uint64_t vstimecmp; + /* physical memory protection */ pmp_table_t pmp_state; target_ulong mseccfg; @@ -365,6 +367,8 @@ struct CPUArchState { /* 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; hwaddr kernel_addr; hwaddr fdt_addr; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index ac17cf1515..095dab19f5 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 +/* Sstc virtual CSRs */ +#define CSR_VSTIMECMP 0x24D +#define CSR_VSTIMECMPH 0x25D + #define CSR_MTINST 0x34a #define CSR_MTVAL2 0x34b diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 05c0c8d777..719c5d5d02 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -346,8 +346,9 @@ uint64_t riscv_cpu_all_pending(CPURISCVState *env) { uint32_t gein = get_field(env->hstatus, HSTATUS_VGEIN); uint64_t vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0; + uint64_t vstip = (env->vstime_irq) ? MIP_VSTIP : 0; - return (env->mip | vsgein) & env->mie; + return (env->mip | vsgein | vstip) & env->mie; } int riscv_cpu_mirq_pending(CPURISCVState *env) @@ -606,7 +607,7 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, uint64_t value) { CPURISCVState *env = &cpu->env; CPUState *cs = CPU(cpu); - uint64_t gein, vsgein = 0, old = env->mip; + uint64_t gein, vsgein = 0, vstip = 0, old = env->mip; bool locked = false; if (riscv_cpu_virt_enabled(env)) { @@ -614,6 +615,10 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, uint64_t value) vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0; } + /* No need to update mip for VSTIP */ + mask = ((mask == MIP_VSTIP) && env->vstime_irq) ? 0 : mask; + vstip = env->vstime_irq ? MIP_VSTIP : 0; + if (!qemu_mutex_iothread_locked()) { locked = true; qemu_mutex_lock_iothread(); @@ -621,7 +626,7 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, uint64_t value) env->mip = (env->mip & ~mask) | (value & mask); - 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 04b06a2389..1a35ac48cc 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -820,6 +820,7 @@ static RISCVException sstc(CPURISCVState *env, int csrno) { CPUState *cs = env_cpu(env); RISCVCPU *cpu = RISCV_CPU(cs); + bool hmode_check = false; if (!cpu->cfg.ext_sstc || !env->rdtime_fn) { return RISCV_EXCP_ILLEGAL_INST; @@ -838,7 +839,18 @@ static RISCVException sstc(CPURISCVState *env, int csrno) return RISCV_EXCP_ILLEGAL_INST; } - 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 == CSR_VSTIMECMP) || (csrno == CSR_VSTIMECMPH)) { + hmode_check = true; + } + + return hmode_check ? hmode(env, csrno) : smode(env, csrno); } static RISCVException sstc_32(CPURISCVState *env, int csrno) @@ -850,17 +862,72 @@ static RISCVException sstc_32(CPURISCVState *env, int csrno) return sstc(env, csrno); } +static RISCVException read_vstimecmp(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = env->vstimecmp; + + return RISCV_EXCP_NONE; +} + +static RISCVException read_vstimecmph(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = env->vstimecmp >> 32; + + return RISCV_EXCP_NONE; +} + +static RISCVException write_vstimecmp(CPURISCVState *env, int csrno, + target_ulong val) +{ + RISCVCPU *cpu = env_archcpu(env); + + if (riscv_cpu_mxl(env) == MXL_RV32) { + env->vstimecmp = deposit64(env->vstimecmp, 0, 32, (uint64_t)val); + } else { + env->vstimecmp = 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 = env_archcpu(env); + + env->vstimecmp = 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 = env->stimecmp; + if (riscv_cpu_virt_enabled(env)) { + *val = env->vstimecmp; + } else { + *val = env->stimecmp; + } + return RISCV_EXCP_NONE; } static RISCVException read_stimecmph(CPURISCVState *env, int csrno, target_ulong *val) { - *val = env->stimecmp >> 32; + if (riscv_cpu_virt_enabled(env)) { + *val = env->vstimecmp >> 32; + } else { + *val = env->stimecmp >> 32; + } + return RISCV_EXCP_NONE; } @@ -869,6 +936,10 @@ static RISCVException write_stimecmp(CPURISCVState *env, int csrno, { RISCVCPU *cpu = env_archcpu(env); + if (riscv_cpu_virt_enabled(env)) { + return write_vstimecmp(env, csrno, val); + } + if (riscv_cpu_mxl(env) == MXL_RV32) { env->stimecmp = deposit64(env->stimecmp, 0, 32, (uint64_t)val); } else { @@ -885,6 +956,10 @@ static RISCVException write_stimecmph(CPURISCVState *env, int csrno, { RISCVCPU *cpu = env_archcpu(env); + if (riscv_cpu_virt_enabled(env)) { + return write_vstimecmph(env, csrno, val); + } + env->stimecmp = deposit64(env->stimecmp, 32, 32, (uint64_t)val); riscv_timer_write_timecmp(cpu, env->stimer, env->stimecmp, 0, MIP_STIP); @@ -1814,6 +1889,7 @@ static RISCVException rmw_mip64(CPURISCVState *env, int csrno, if (csrno != CSR_HVIP) { gin = get_field(env->hstatus, HSTATUS_VGEIN); old_mip |= (env->hgeip & ((target_ulong)1 << gin)) ? MIP_VSEIP : 0; + old_mip |= env->vstime_irq ? MIP_VSTIP : 0; } if (ret_val) { @@ -3680,6 +3756,12 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_STIMECMPH] = { "stimecmph", sstc_32, read_stimecmph, write_stimecmph, .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSTIMECMP] = { "vstimecmp", sstc, read_vstimecmp, + write_vstimecmp, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSTIMECMPH] = { "vstimecmph", sstc_32, read_vstimecmph, + write_vstimecmph, + .min_priv_ver = PRIV_VERSION_1_12_0 }, /* Supervisor Protection and Translation */ [CSR_SATP] = { "satp", smode, read_satp, write_satp }, diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 622fface48..4ba55705d1 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -92,6 +92,7 @@ static const VMStateDescription vmstate_hyper = { VMSTATE_UINTTL(env.hgeie, RISCVCPU), VMSTATE_UINTTL(env.hgeip, RISCVCPU), VMSTATE_UINT64(env.htimedelta, RISCVCPU), + VMSTATE_UINT64(env.vstimecmp, RISCVCPU), 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 f3fb5eac7b..8cce667dfd 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" +static void riscv_vstimer_cb(void *opaque) +{ + RISCVCPU *cpu = opaque; + CPURISCVState *env = &cpu->env; + env->vstime_irq = 1; + riscv_cpu_update_mip(cpu, MIP_VSTIP, BOOL_TO_MASK(1)); +} + static void riscv_stimer_cb(void *opaque) { RISCVCPU *cpu = 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 == MIP_VSTIP) { + env->vstime_irq = 1; + } riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(1)); return; } + if (timer_irq == MIP_VSTIP) { + env->vstime_irq = 0; + } /* Clear the [V]STIP bit in mip */ riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(0)); @@ -95,4 +109,6 @@ void riscv_timer_init(RISCVCPU *cpu) env->stimer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &riscv_stimer_cb, cpu); env->stimecmp = 0; + env->vstimer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &riscv_vstimer_cb, cpu); + env->vstimecmp = 0; }