From nobody Sat May 4 06:35:15 2024 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=1660157978; cv=none; d=zohomail.com; s=zohoarc; b=YwO4B85upYEMsXMlzl+BO2jk43BFd5kQTpNrFwUfPwFYc4zms5Xi60X5Nm4MMKiSyWY38d4EWcRS/NaZMjvvTPII2Ptn0bZBljW+w8k6A4iGW7zMP1Bxc38Z+W5HjvaMHJ4kiLTQUndTjbAXoMX0zrDaOG7XW+N3JwldfBwhhmY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1660157978; 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=yqFL3XWjqlrMAYFofhsb+vhYAWbOFm6JfDPSQsN8zoE=; b=mVOim8ervmJfFHkS1gVMLqELPS5AlOteToyn9f866I5XJWKNaOGFnQnwthYzhQYH9o5SUHz7pEtaZkwiEWNcfgKJjDsVP73l+6ukYe4dEPJsSsW+7GKKOqm7qSueKjEr/Sj8Y1Rg/2Kv7py5WerlitaYR9yyH13PK21y3rQe6FA= 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 1660157978355218.85482253840496; Wed, 10 Aug 2022 11:59:38 -0700 (PDT) Received: from localhost ([::1]:37978 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oLqvY-0008Sj-1X for importer@patchew.org; Wed, 10 Aug 2022 14:59:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43044) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oLqiX-0005Yh-73 for qemu-devel@nongnu.org; Wed, 10 Aug 2022 14:46:12 -0400 Received: from mail-pl1-x62d.google.com ([2607:f8b0:4864:20::62d]:35512) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1oLqiR-0007Dt-59 for qemu-devel@nongnu.org; Wed, 10 Aug 2022 14:46:07 -0400 Received: by mail-pl1-x62d.google.com with SMTP id y1so9384030plb.2 for ; Wed, 10 Aug 2022 11:46:02 -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.45.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 Aug 2022 11:46:00 -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=yqFL3XWjqlrMAYFofhsb+vhYAWbOFm6JfDPSQsN8zoE=; b=K1yAT3dyTcmFpJ3Aumq6oo3PXzRyajtZn/C7BFlkTE4Cxljj9dZXFjiKxeGzlYaPtX admmgEzN6zRPOhui6nUO6ODJVt/JHfVssDYnkA5zKfii6vgurtJN6w2nXwamOhaaINi0 HaI+fpjSiI60tuLa+ugM25FyMo9qdeSaWLR+gKFEaRl6bmLzvg5xcueIizX5nXtCyDHD 8eYXPhQbXBIa8oGTAYhtHLKzHvWmAmdcCBhwlBxBfU1Y4OmNHA0+x0KPaoCeenGFMOeW vN/pJrP+5a4EyAB4j4EnctIE9FhMVqfcAIUIKipzyGJLzTz0ipehSjy5s4AOduF3PD/8 16cw== 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=yqFL3XWjqlrMAYFofhsb+vhYAWbOFm6JfDPSQsN8zoE=; b=MpO0dXwtnjslsR3yIpk4//oaH4Fh14ECy8Q84XwmWv3ec6RFsNjOhh0albePLlq8+b x/L/8Yc6dm1q5qUNtuEF9xw2B65X/8xIANvfLuu7j8H8FRacZMAbIeSrPfVm9lSR/lEa zXyFbnoJNbPHklI3hmP8OMKYhRYg7b81XX5aYOmeE6xYmIjCTWLg9rhU/dUMX6ipS+U+ lGm+KqZkHZeiLQwmI5C1XTG5BSttfNPrRszGodakaQ9PAia5Fr+aYJRr0JdX0xOOXWEi FG3dxsitn3TqmlIcd5lSkuzqfkWjTZEU/KvTElCPgt76BAtPp2ctKKMwSUAd3hOQCzI5 pzwA== X-Gm-Message-State: ACgBeo2njfdV/QSQwFPF4Ya85+pm8Z8p0AQ/gVeWVLoFEWr074LYST6W t0c3zQisnl2Y9s5xEz6+AHXEysYApNP+0w== X-Google-Smtp-Source: AA6agR6gftxAp3uiROHxkUxUH3XLMYrHIIE133/oTHlZs56Wn/JspboU2PbEoeiuSy0bkbQHHnByVA== X-Received: by 2002:a17:90a:4805:b0:1f5:39ab:29a9 with SMTP id a5-20020a17090a480500b001f539ab29a9mr4986099pjh.202.1660157160668; Wed, 10 Aug 2022 11:46:00 -0700 (PDT) From: Atish Patra To: qemu-devel@nongnu.org Cc: Atish Patra , Anup Patel , Alistair Francis , Andrew Jones , Alistair Francis , Bin Meng , Palmer Dabbelt , qemu-riscv@nongnu.org Subject: [PATCH v9 1/3] hw/intc: Move mtimer/mtimecmp to aclint Date: Wed, 10 Aug 2022 11:45:46 -0700 Message-Id: <20220810184548.3620153-2-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::62d; envelope-from=atishp@rivosinc.com; helo=mail-pl1-x62d.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: 1660157980114100001 Content-Type: text/plain; charset="utf-8" Historically, The mtime/mtimecmp has been part of the CPU because they are per hart entities. However, they actually belong to aclint which is a MMIO device. Move them to the ACLINT device. This also emulates the real hardware more closely. Reviewed-by: Anup Patel Reviewed-by: Alistair Francis Reviewed-by: Andrew Jones Signed-off-by: Atish Patra --- hw/intc/riscv_aclint.c | 41 ++++++++++++++++++++++++---------- hw/timer/ibex_timer.c | 18 ++++++--------- include/hw/intc/riscv_aclint.h | 2 ++ include/hw/timer/ibex_timer.h | 2 ++ target/riscv/cpu.h | 2 -- target/riscv/machine.c | 5 ++--- 6 files changed, 42 insertions(+), 28 deletions(-) diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c index e7942c4e5a32..a125c73d535c 100644 --- a/hw/intc/riscv_aclint.c +++ b/hw/intc/riscv_aclint.c @@ -32,6 +32,7 @@ #include "hw/intc/riscv_aclint.h" #include "qemu/timer.h" #include "hw/irq.h" +#include "migration/vmstate.h" =20 typedef struct riscv_aclint_mtimer_callback { RISCVAclintMTimerState *s; @@ -65,8 +66,8 @@ static void riscv_aclint_mtimer_write_timecmp(RISCVAclint= MTimerState *mtimer, =20 uint64_t rtc_r =3D cpu_riscv_read_rtc(mtimer); =20 - cpu->env.timecmp =3D value; - if (cpu->env.timecmp <=3D rtc_r) { + mtimer->timecmp[hartid] =3D value; + if (mtimer->timecmp[hartid] <=3D rtc_r) { /* * If we're setting an MTIMECMP value in the "past", * immediately raise the timer interrupt @@ -77,7 +78,7 @@ static void riscv_aclint_mtimer_write_timecmp(RISCVAclint= MTimerState *mtimer, =20 /* otherwise, set up the future timer interrupt */ qemu_irq_lower(mtimer->timer_irqs[hartid - mtimer->hartid_base]); - diff =3D cpu->env.timecmp - rtc_r; + diff =3D mtimer->timecmp[hartid] - rtc_r; /* back to ns (note args switched in muldiv64) */ uint64_t ns_diff =3D muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_f= req); =20 @@ -102,7 +103,7 @@ static void riscv_aclint_mtimer_write_timecmp(RISCVAcli= ntMTimerState *mtimer, next =3D MIN(next, INT64_MAX); } =20 - timer_mod(cpu->env.timer, next); + timer_mod(mtimer->timers[hartid], next); } =20 /* @@ -133,11 +134,11 @@ static uint64_t riscv_aclint_mtimer_read(void *opaque= , hwaddr addr, "aclint-mtimer: invalid hartid: %zu", hartid); } else if ((addr & 0x7) =3D=3D 0) { /* timecmp_lo for RV32/RV64 or timecmp for RV64 */ - uint64_t timecmp =3D env->timecmp; + uint64_t timecmp =3D mtimer->timecmp[hartid]; return (size =3D=3D 4) ? (timecmp & 0xFFFFFFFF) : timecmp; } else if ((addr & 0x7) =3D=3D 4) { /* timecmp_hi */ - uint64_t timecmp =3D env->timecmp; + uint64_t timecmp =3D mtimer->timecmp[hartid]; return (timecmp >> 32) & 0xFFFFFFFF; } else { qemu_log_mask(LOG_UNIMP, @@ -177,7 +178,7 @@ static void riscv_aclint_mtimer_write(void *opaque, hwa= ddr addr, } else if ((addr & 0x7) =3D=3D 0) { if (size =3D=3D 4) { /* timecmp_lo for RV32/RV64 */ - uint64_t timecmp_hi =3D env->timecmp >> 32; + uint64_t timecmp_hi =3D mtimer->timecmp[hartid] >> 32; riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), = hartid, timecmp_hi << 32 | (value & 0xFFFFFFFF)); } else { @@ -188,7 +189,7 @@ static void riscv_aclint_mtimer_write(void *opaque, hwa= ddr addr, } else if ((addr & 0x7) =3D=3D 4) { if (size =3D=3D 4) { /* timecmp_hi for RV32/RV64 */ - uint64_t timecmp_lo =3D env->timecmp; + uint64_t timecmp_lo =3D mtimer->timecmp[hartid]; riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), = hartid, value << 32 | (timecmp_lo & 0xFFFFFFFF)); } else { @@ -234,7 +235,7 @@ static void riscv_aclint_mtimer_write(void *opaque, hwa= ddr addr, } riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), mtimer->hartid_base + i, - env->timecmp); + mtimer->timecmp[i]); } return; } @@ -284,6 +285,8 @@ static void riscv_aclint_mtimer_realize(DeviceState *de= v, Error **errp) s->timer_irqs =3D g_new(qemu_irq, s->num_harts); qdev_init_gpio_out(dev, s->timer_irqs, s->num_harts); =20 + s->timers =3D g_new0(QEMUTimer *, s->num_harts); + s->timecmp =3D g_new0(uint64_t, s->num_harts); /* Claim timer interrupt bits */ for (i =3D 0; i < s->num_harts; i++) { RISCVCPU *cpu =3D RISCV_CPU(qemu_get_cpu(s->hartid_base + i)); @@ -310,6 +313,18 @@ static void riscv_aclint_mtimer_reset_enter(Object *ob= j, ResetType type) riscv_aclint_mtimer_write(mtimer, mtimer->time_base, 0, 8); } =20 +static const VMStateDescription vmstate_riscv_mtimer =3D { + .name =3D "riscv_mtimer", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_VARRAY_UINT32(timecmp, RISCVAclintMTimerState, + num_harts, 0, + vmstate_info_uint64, uint64_t), + VMSTATE_END_OF_LIST() + } +}; + static void riscv_aclint_mtimer_class_init(ObjectClass *klass, void *data) { DeviceClass *dc =3D DEVICE_CLASS(klass); @@ -317,6 +332,7 @@ static void riscv_aclint_mtimer_class_init(ObjectClass = *klass, void *data) device_class_set_props(dc, riscv_aclint_mtimer_properties); ResettableClass *rc =3D RESETTABLE_CLASS(klass); rc->phases.enter =3D riscv_aclint_mtimer_reset_enter; + dc->vmsd =3D &vmstate_riscv_mtimer; } =20 static const TypeInfo riscv_aclint_mtimer_info =3D { @@ -336,6 +352,7 @@ DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hw= addr size, { int i; DeviceState *dev =3D qdev_new(TYPE_RISCV_ACLINT_MTIMER); + RISCVAclintMTimerState *s =3D RISCV_ACLINT_MTIMER(dev); =20 assert(num_harts <=3D RISCV_ACLINT_MAX_HARTS); assert(!(addr & 0x7)); @@ -366,11 +383,11 @@ DeviceState *riscv_aclint_mtimer_create(hwaddr addr, = hwaddr size, riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, dev); } =20 - cb->s =3D RISCV_ACLINT_MTIMER(dev); + cb->s =3D s; cb->num =3D i; - env->timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, + s->timers[i] =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, &riscv_aclint_mtimer_cb, cb); - env->timecmp =3D 0; + s->timecmp[i] =3D 0; =20 qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_TIMER)= ); diff --git a/hw/timer/ibex_timer.c b/hw/timer/ibex_timer.c index 8c2ca364daab..d8b8e4e1f602 100644 --- a/hw/timer/ibex_timer.c +++ b/hw/timer/ibex_timer.c @@ -60,8 +60,6 @@ static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq) =20 static void ibex_timer_update_irqs(IbexTimerState *s) { - CPUState *cs =3D qemu_get_cpu(0); - RISCVCPU *cpu =3D RISCV_CPU(cs); uint64_t value =3D s->timer_compare_lower0 | ((uint64_t)s->timer_compare_upper0 << 32); uint64_t next, diff; @@ -73,9 +71,9 @@ static void ibex_timer_update_irqs(IbexTimerState *s) } =20 /* Update the CPUs mtimecmp */ - cpu->env.timecmp =3D value; + s->mtimecmp =3D value; =20 - if (cpu->env.timecmp <=3D now) { + if (s->mtimecmp <=3D now) { /* * If the mtimecmp was in the past raise the interrupt now. */ @@ -91,7 +89,7 @@ static void ibex_timer_update_irqs(IbexTimerState *s) qemu_irq_lower(s->m_timer_irq); qemu_set_irq(s->irq, false); =20 - diff =3D cpu->env.timecmp - now; + diff =3D s->mtimecmp - now; next =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + muldiv64(diff, NANOSECONDS_PER_SECOND, @@ -99,9 +97,9 @@ static void ibex_timer_update_irqs(IbexTimerState *s) =20 if (next < qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) { /* We overflowed the timer, just set it as large as we can */ - timer_mod(cpu->env.timer, 0x7FFFFFFFFFFFFFFF); + timer_mod(s->mtimer, 0x7FFFFFFFFFFFFFFF); } else { - timer_mod(cpu->env.timer, next); + timer_mod(s->mtimer, next); } } =20 @@ -120,11 +118,9 @@ static void ibex_timer_reset(DeviceState *dev) { IbexTimerState *s =3D IBEX_TIMER(dev); =20 - CPUState *cpu =3D qemu_get_cpu(0); - CPURISCVState *env =3D cpu->env_ptr; - env->timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, + s->mtimer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, &ibex_timer_cb, s); - env->timecmp =3D 0; + s->mtimecmp =3D 0; =20 s->timer_ctrl =3D 0x00000000; s->timer_cfg0 =3D 0x00010000; diff --git a/include/hw/intc/riscv_aclint.h b/include/hw/intc/riscv_aclint.h index 26d4048687fb..693415eb6def 100644 --- a/include/hw/intc/riscv_aclint.h +++ b/include/hw/intc/riscv_aclint.h @@ -32,6 +32,8 @@ typedef struct RISCVAclintMTimerState { /*< private >*/ SysBusDevice parent_obj; uint64_t time_delta; + uint64_t *timecmp; + QEMUTimer **timers; =20 /*< public >*/ MemoryRegion mmio; diff --git a/include/hw/timer/ibex_timer.h b/include/hw/timer/ibex_timer.h index 1a0a28d5fab5..41f5c82a920b 100644 --- a/include/hw/timer/ibex_timer.h +++ b/include/hw/timer/ibex_timer.h @@ -33,6 +33,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(IbexTimerState, IBEX_TIMER) struct IbexTimerState { /* */ SysBusDevice parent_obj; + uint64_t mtimecmp; + QEMUTimer *mtimer; /* Internal timer for M-mode interrupt */ =20 /* */ MemoryRegion mmio; diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 4be4b82a837d..0fae1569945c 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -308,7 +308,6 @@ struct CPUArchState { /* temporary htif regs */ uint64_t mfromhost; uint64_t mtohost; - uint64_t timecmp; =20 /* physical memory protection */ pmp_table_t pmp_state; @@ -363,7 +362,6 @@ struct CPUArchState { float_status fp_status; =20 /* Fields from here on are preserved across CPU reset. */ - QEMUTimer *timer; /* Internal timer */ =20 hwaddr kernel_addr; hwaddr fdt_addr; diff --git a/target/riscv/machine.c b/target/riscv/machine.c index dc182ca81119..b508b042cb73 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -307,8 +307,8 @@ static const VMStateDescription vmstate_pmu_ctr_state = =3D { =20 const VMStateDescription vmstate_riscv_cpu =3D { .name =3D "cpu", - .version_id =3D 3, - .minimum_version_id =3D 3, + .version_id =3D 4, + .minimum_version_id =3D 4, .post_load =3D riscv_cpu_post_load, .fields =3D (VMStateField[]) { VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32), @@ -359,7 +359,6 @@ const VMStateDescription vmstate_riscv_cpu =3D { VMSTATE_UINTTL(env.mscratch, RISCVCPU), VMSTATE_UINT64(env.mfromhost, RISCVCPU), VMSTATE_UINT64(env.mtohost, RISCVCPU), - VMSTATE_UINT64(env.timecmp, RISCVCPU), =20 VMSTATE_END_OF_LIST() }, --=20 2.25.1 From nobody Sat May 4 06:35:15 2024 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=1660158155; cv=none; d=zohomail.com; s=zohoarc; b=cNiqwMeSDHHrL3cIX8d/SXVXvwARePlUA9cTOh3HR4DzaE4skQfpSu8sUcPWAKM6kTg7JvOWpzOYDB4NLoDSJkExOIeOIT4XNcANz+2CM6xgm1oNr4fKWQ5pqoxZzqxAySsEm19txM3BQ/29LtkIX3OBOABhEFHhBjxHHXH8oqE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1660158155; 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=WQG35qX5tJ6WiRkcyGfDdPtizg2y+1PZIHoEGmfeOHc=; b=mvnCzdJpJz02KYosCmQj2V5jldE0oa8rOXOw3fqZted93ZwFwmUs+VTU5bxi0QaLLgH8q8yJkwvrGqEYZSQHqymIu0jYDpqoOz4rZDuNLcXYtprf1qJTnFPBQIVqp9WvExwwuL6rrfI3UCqD326USTWi9xoJTzMeev3olDZnluo= 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 1660158155185811.0970298451907; Wed, 10 Aug 2022 12:02:35 -0700 (PDT) Received: from localhost ([::1]:41518 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oLqyP-0002aZ-0r for importer@patchew.org; Wed, 10 Aug 2022 15:02:33 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43050) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oLqib-0005aF-EM for qemu-devel@nongnu.org; Wed, 10 Aug 2022 14:46:13 -0400 Received: from mail-pl1-x631.google.com ([2607:f8b0:4864:20::631]:42634) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1oLqiR-0007ED-Le for qemu-devel@nongnu.org; Wed, 10 Aug 2022 14:46:13 -0400 Received: by mail-pl1-x631.google.com with SMTP id w14so14987334plp.9 for ; Wed, 10 Aug 2022 11:46:03 -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.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 Aug 2022 11:46:01 -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=WQG35qX5tJ6WiRkcyGfDdPtizg2y+1PZIHoEGmfeOHc=; b=hxuTslPOgax2hOVoI3QTMxhtglvfHseJvozD6VSuudB0boZS1j6FKQIQDSU1XDkVnx sl08HGIOxRAV1awpy8Mv86ZeRz0M15GD+3yQx11k9bsDaPAA3aE2e7U9ZLcLCew6a4zm CsruIb5ezxxPhXAkGv1Wl4Bsy750mquzCW85FuUrediYIndtpOE3fMCMeY6gjVuWSiDY 9J9PC+m/O46Kr2vodgFYaqbOfkPuff5mtw7hJbyV/Ds1bu1i/OknAlkZ+U96/8eqahN2 FgdzOPHBy5lRC0kusimoKVmpF+J+3CyJa/tWfS+IH/R7HYwNds1MyxM+r76YN4SMK0SQ RU3A== 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=WQG35qX5tJ6WiRkcyGfDdPtizg2y+1PZIHoEGmfeOHc=; b=VmrQs5f9kI1vnlDL2rvZ/fK10D1BFmFZ6czwkQdXf47tTSNXJXGikn+yFdt2ahfbdq dNCTRdXC38n6hQUbW1yA0lbfERtJ2k2FKXKf8JGbzLWCDWK2BoaCie3QxF1GlJQLnW0H 23UUSy5bNLu630s/ZDSVfZ7q/S3YBirhtY+VqZ9pjUYPbdyFqe4Di96/v6qwYgx7cCKv 02+r7UKj8+77EG2S9ELQ0saM9NqTdgSXwz2ydGa+/GfBs3XYjQmywFQuAdDMNYBqjIUF oqIif9iUDXLvKY+t1JgDI8fwkRLXUC8HLULihiPIPwUWoPUlDGUS3m6Ss+FW0hnFu8d5 xAKg== X-Gm-Message-State: ACgBeo2FHT+y1u6U44zSVrrLvh5f1LNRezrIOabWKNUkSxVRBkFoxmtH cicQmS1SIKUDcCSOKo00QTT20hjMMyEUew== X-Google-Smtp-Source: AA6agR7hNCEMQYZw0u3Zas9kDh8gcazjVMtOK5th48c/s+zITIzS7eRQ7QW9iIQl4aZWYMJmQRofjQ== X-Received: by 2002:a17:903:110e:b0:171:3afa:e68c with SMTP id n14-20020a170903110e00b001713afae68cmr2963504plh.12.1660157162158; Wed, 10 Aug 2022 11:46:02 -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 2/3] target/riscv: Add stimecmp support Date: Wed, 10 Aug 2022 11:45:47 -0700 Message-Id: <20220810184548.3620153-3-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::631; envelope-from=atishp@rivosinc.com; helo=mail-pl1-x631.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=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+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @rivosinc-com.20210112.gappssmtp.com) X-ZM-MESSAGEID: 1660158157601100001 Content-Type: text/plain; charset="utf-8" stimecmp allows the supervisor mode to update stimecmp CSR directly to program the next timer interrupt. This CSR is part of the Sstc extension which was ratified recently. Reviewed-by: Alistair Francis Signed-off-by: Atish Patra --- target/riscv/cpu.c | 9 ++++ target/riscv/cpu.h | 5 ++ target/riscv/cpu_bits.h | 4 ++ target/riscv/csr.c | 86 +++++++++++++++++++++++++++++++++ target/riscv/machine.c | 1 + target/riscv/meson.build | 3 +- target/riscv/time_helper.c | 98 ++++++++++++++++++++++++++++++++++++++ target/riscv/time_helper.h | 30 ++++++++++++ 8 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 target/riscv/time_helper.c create mode 100644 target/riscv/time_helper.h diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index d4635c7df46b..2498b93105fd 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -23,6 +23,7 @@ #include "qemu/log.h" #include "cpu.h" #include "internals.h" +#include "time_helper.h" #include "exec/exec-all.h" #include "qapi/error.h" #include "qemu/error-report.h" @@ -99,6 +100,7 @@ static const struct isa_ext_data isa_edata_arr[] =3D { ISA_EXT_DATA_ENTRY(zve64f, true, PRIV_VERSION_1_12_0, ext_zve64f), ISA_EXT_DATA_ENTRY(zhinx, true, PRIV_VERSION_1_12_0, ext_zhinx), ISA_EXT_DATA_ENTRY(zhinxmin, true, PRIV_VERSION_1_12_0, ext_zhinxmin), + ISA_EXT_DATA_ENTRY(sstc, true, PRIV_VERSION_1_12_0, ext_sstc), ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval), ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot), ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt), @@ -675,6 +677,12 @@ static void riscv_cpu_realize(DeviceState *dev, Error = **errp) =20 set_resetvec(env, cpu->cfg.resetvec); =20 +#ifndef CONFIG_USER_ONLY + if (cpu->cfg.ext_sstc) { + riscv_timer_init(cpu); + } +#endif /* CONFIG_USER_ONLY */ + /* Validate that MISA_MXL is set properly. */ switch (env->misa_mxl_max) { #ifdef TARGET_RISCV64 @@ -995,6 +1003,7 @@ static Property riscv_cpu_extensions[] =3D { DEFINE_PROP_BOOL("Zve64f", RISCVCPU, cfg.ext_zve64f, false), DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true), DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true), + DEFINE_PROP_BOOL("sstc", RISCVCPU, cfg.ext_sstc, true), =20 DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec), DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 0fae1569945c..4cda2905661e 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -309,6 +309,9 @@ struct CPUArchState { uint64_t mfromhost; uint64_t mtohost; =20 + /* Sstc CSRs */ + uint64_t stimecmp; + /* physical memory protection */ pmp_table_t pmp_state; target_ulong mseccfg; @@ -362,6 +365,7 @@ struct CPUArchState { float_status fp_status; =20 /* Fields from here on are preserved across CPU reset. */ + QEMUTimer *stimer; /* Internal timer for S-mode interrupt */ =20 hwaddr kernel_addr; hwaddr fdt_addr; @@ -425,6 +429,7 @@ struct RISCVCPUConfig { bool ext_ifencei; bool ext_icsr; bool ext_zihintpause; + bool ext_sstc; bool ext_svinval; bool ext_svnapot; bool ext_svpbmt; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 6be5a9e9f046..ac17cf1515c0 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -206,6 +206,10 @@ #define CSR_STVAL 0x143 #define CSR_SIP 0x144 =20 +/* Sstc supervisor CSRs */ +#define CSR_STIMECMP 0x14D +#define CSR_STIMECMPH 0x15D + /* Supervisor Protection and Translation */ #define CSR_SPTBR 0x180 #define CSR_SATP 0x180 diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 0fb042b2fd0f..9079d988ba08 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -22,6 +22,7 @@ #include "qemu/timer.h" #include "cpu.h" #include "pmu.h" +#include "time_helper.h" #include "qemu/main-loop.h" #include "exec/exec-all.h" #include "sysemu/cpu-timers.h" @@ -803,6 +804,81 @@ static RISCVException read_timeh(CPURISCVState *env, i= nt csrno, return RISCV_EXCP_NONE; } =20 +static RISCVException sstc(CPURISCVState *env, int csrno) +{ + CPUState *cs =3D env_cpu(env); + RISCVCPU *cpu =3D RISCV_CPU(cs); + + if (!cpu->cfg.ext_sstc || !env->rdtime_fn) { + return RISCV_EXCP_ILLEGAL_INST; + } + + if (env->priv =3D=3D PRV_M) { + return RISCV_EXCP_NONE; + } + + /* + * No need of separate function for rv32 as menvcfg stores both menvcfg + * menvcfgh for RV32. + */ + if (!(get_field(env->mcounteren, COUNTEREN_TM) && + get_field(env->menvcfg, MENVCFG_STCE))) { + return RISCV_EXCP_ILLEGAL_INST; + } + + return smode(env, csrno); +} + +static RISCVException sstc_32(CPURISCVState *env, int csrno) +{ + if (riscv_cpu_mxl(env) !=3D MXL_RV32) { + return RISCV_EXCP_ILLEGAL_INST; + } + + return sstc(env, csrno); +} + +static RISCVException read_stimecmp(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val =3D env->stimecmp; + return RISCV_EXCP_NONE; +} + +static RISCVException read_stimecmph(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val =3D env->stimecmp >> 32; + return RISCV_EXCP_NONE; +} + +static RISCVException write_stimecmp(CPURISCVState *env, int csrno, + target_ulong val) +{ + RISCVCPU *cpu =3D env_archcpu(env); + + if (riscv_cpu_mxl(env) =3D=3D MXL_RV32) { + env->stimecmp =3D deposit64(env->stimecmp, 0, 32, (uint64_t)val); + } else { + env->stimecmp =3D val; + } + + riscv_timer_write_timecmp(cpu, env->stimer, env->stimecmp, 0, MIP_STIP= ); + + return RISCV_EXCP_NONE; +} + +static RISCVException write_stimecmph(CPURISCVState *env, int csrno, + target_ulong val) +{ + RISCVCPU *cpu =3D env_archcpu(env); + + env->stimecmp =3D deposit64(env->stimecmp, 32, 32, (uint64_t)val); + riscv_timer_write_timecmp(cpu, env->stimer, env->stimecmp, 0, MIP_STIP= ); + + return RISCV_EXCP_NONE; +} + /* Machine constants */ =20 #define M_MODE_INTERRUPTS ((uint64_t)(MIP_MSIP | MIP_MTIP | MIP_MEIP)) @@ -1719,6 +1795,12 @@ static RISCVException rmw_mip64(CPURISCVState *env, = int csrno, new_val |=3D env->external_seip * MIP_SEIP; } =20 + if (cpu->cfg.ext_sstc && (env->priv =3D=3D PRV_M) && + get_field(env->menvcfg, MENVCFG_STCE)) { + /* sstc extension forbids STIP & VSTIP to be writeable in mip */ + mask =3D mask & ~(MIP_STIP | MIP_VSTIP); + } + if (mask) { old_mip =3D riscv_cpu_update_mip(cpu, mask, (new_val & mask)); } else { @@ -3584,6 +3666,10 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] =3D { [CSR_SCAUSE] =3D { "scause", smode, read_scause, write_scause = }, [CSR_STVAL] =3D { "stval", smode, read_stval, write_stval = }, [CSR_SIP] =3D { "sip", smode, NULL, NULL, rmw_sip = }, + [CSR_STIMECMP] =3D { "stimecmp", sstc, read_stimecmp, write_stimecmp, + .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 }, =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 b508b042cb73..622fface484e 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -359,6 +359,7 @@ const VMStateDescription vmstate_riscv_cpu =3D { VMSTATE_UINTTL(env.mscratch, RISCVCPU), VMSTATE_UINT64(env.mfromhost, RISCVCPU), VMSTATE_UINT64(env.mtohost, RISCVCPU), + VMSTATE_UINT64(env.stimecmp, RISCVCPU), =20 VMSTATE_END_OF_LIST() }, diff --git a/target/riscv/meson.build b/target/riscv/meson.build index 2c1975e72c4e..24893c614ee4 100644 --- a/target/riscv/meson.build +++ b/target/riscv/meson.build @@ -31,7 +31,8 @@ riscv_softmmu_ss.add(files( 'debug.c', 'monitor.c', 'machine.c', - 'pmu.c' + 'pmu.c', + 'time_helper.c' )) =20 target_arch +=3D {'riscv': riscv_ss} diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c new file mode 100644 index 000000000000..f3fb5eac7b7b --- /dev/null +++ b/target/riscv/time_helper.c @@ -0,0 +1,98 @@ +/* + * RISC-V timer helper implementation. + * + * Copyright (c) 2022 Rivos Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "cpu_bits.h" +#include "time_helper.h" +#include "hw/intc/riscv_aclint.h" + +static void riscv_stimer_cb(void *opaque) +{ + RISCVCPU *cpu =3D opaque; + riscv_cpu_update_mip(cpu, MIP_STIP, BOOL_TO_MASK(1)); +} + +/* + * Called when timecmp is written to update the QEMU timer or immediately + * trigger timer interrupt if mtimecmp <=3D current timer value. + */ +void riscv_timer_write_timecmp(RISCVCPU *cpu, QEMUTimer *timer, + uint64_t timecmp, uint64_t delta, + uint32_t timer_irq) +{ + uint64_t diff, ns_diff, next; + CPURISCVState *env =3D &cpu->env; + RISCVAclintMTimerState *mtimer =3D env->rdtime_fn_arg; + uint32_t timebase_freq =3D mtimer->timebase_freq; + uint64_t rtc_r =3D env->rdtime_fn(env->rdtime_fn_arg) + delta; + + if (timecmp <=3D rtc_r) { + /* + * If we're setting an stimecmp value in the "past", + * immediately raise the timer interrupt + */ + riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(1)); + return; + } + + /* Clear the [V]STIP bit in mip */ + riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(0)); + + /* otherwise, set up the future timer interrupt */ + diff =3D timecmp - rtc_r; + /* back to ns (note args switched in muldiv64) */ + ns_diff =3D muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq); + + /* + * check if ns_diff overflowed and check if the addition would potenti= ally + * overflow + */ + if ((NANOSECONDS_PER_SECOND > timebase_freq && ns_diff < diff) || + ns_diff > INT64_MAX) { + next =3D INT64_MAX; + } else { + /* + * as it is very unlikely qemu_clock_get_ns will return a value + * greater than INT64_MAX, no additional check is needed for an + * unsigned integer overflow. + */ + next =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns_diff; + /* + * if ns_diff is INT64_MAX next may still be outside the range + * of a signed integer. + */ + next =3D MIN(next, INT64_MAX); + } + + timer_mod(timer, next); +} + +void riscv_timer_init(RISCVCPU *cpu) +{ + CPURISCVState *env; + + if (!cpu) { + return; + } + + env =3D &cpu->env; + env->stimer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, &riscv_stimer_cb, cpu= ); + env->stimecmp =3D 0; + +} diff --git a/target/riscv/time_helper.h b/target/riscv/time_helper.h new file mode 100644 index 000000000000..7b3cdcc35020 --- /dev/null +++ b/target/riscv/time_helper.h @@ -0,0 +1,30 @@ +/* + * RISC-V timer header file. + * + * Copyright (c) 2022 Rivos Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + */ + +#ifndef RISCV_TIME_HELPER_H +#define RISCV_TIME_HELPER_H + +#include "cpu.h" +#include "qemu/timer.h" + +void riscv_timer_write_timecmp(RISCVCPU *cpu, QEMUTimer *timer, + uint64_t timecmp, uint64_t delta, + uint32_t timer_irq); +void riscv_timer_init(RISCVCPU *cpu); + +#endif --=20 2.25.1 From nobody Sat May 4 06:35:15 2024 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