From nobody Sun Apr 12 00:57:42 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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; dmarc=fail(p=none dis=none) header.from=git.sr.ht Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1771600157413725.1400313243219; Fri, 20 Feb 2026 07:09:17 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vtS7s-0005rX-70; Fri, 20 Feb 2026 10:09:04 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS26-00087w-10; Fri, 20 Feb 2026 10:03:07 -0500 Received: from mail-a.sr.ht ([46.23.81.152]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS24-0002Il-9k; Fri, 20 Feb 2026 10:03:05 -0500 Received: from git.sr.ht (unknown [46.23.81.155]) by mail-a.sr.ht (Postfix) with ESMTPSA id 5E38725016; Fri, 20 Feb 2026 15:02:55 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=KygNMSHDJRpYUUZFihrvfUizAP5Rz6A+N42Aif3Z9Ac=; c=simple/simple; d=git.sr.ht; h=From:Date:Subject:Reply-to:In-Reply-To:To:Cc; q=dns/txt; s=20240113; t=1771599775; v=1; b=nIRhPDRvDp5/0vDm2bbF6/J/6L+Yf180sFdNVFbw+hFk5KlWZmv3fz7ViG1KJHPe4mEDGLmw LJap8lnkv2csIKiqOcUUIU1lufxtj504/Jeb0Y8KuOYtyPfn00bpIgFBTzYsa/1PmAA5ddal7dR UXgGj0liQkVifF71H6Z8rjZS+qQq10AcUzjWMeBjJxo7tZm3aBFW3hnATsY+HPj6K8Cg5JPvBGi gDif9ZVGDggXW8APknX2BH82mVpH6Qt6CBc0orvGq7r717u0syW/lt4s9ve05CFHB484QAfUBVB OiRCyuTA5UcD2aGycjw7fSN9g+Qyb+2B5m+TEp2/0Q03A== From: ~lexbaileylowrisc Date: Thu, 27 Apr 2023 19:39:11 +0200 Subject: [PATCH qemu 01/11] [ot] target/riscv: rename ibex hart as lowrisc-ibex Message-ID: <177159976712.8279.7732381632410882915-1@git.sr.ht> X-Mailer: git.sr.ht In-Reply-To: <177159976712.8279.7732381632410882915-0@git.sr.ht> To: qemu-devel@nongnu.org Cc: Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , qemu-riscv@nongnu.org, Paolo Bonzini , =?utf-8?q?Marc-Andr=C3=A9?= Lureau , Alistair Francis , Pierrick Bouvier , "Dr. David Alan Gilbert" , Daniel =?utf-8?q?P=2E_Berrang=C3=A9?= , Philippe =?utf-8?q?Mathieu-Daud=C3=A9?= , lowRISC , nabihestefan@google.com, Amit Kumar-Hermosillo Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 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=46.23.81.152; envelope-from=outgoing@sr.ht; helo=mail-a.sr.ht X-Spam_score_int: 17 X-Spam_score: 1.7 X-Spam_bar: + X-Spam_report: (1.7 / 5.0 requ) BAYES_00=-1.9, DATE_IN_PAST_96_XX=3.405, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Fri, 20 Feb 2026 10:09:01 -0500 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: ~lexbaileylowrisc Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1771600158779154100 From: Emmanuel Blot Follow vendor-device syntax used with other RISCV cores Signed-off-by: Emmanuel Blot Reviewed-by: Alistair Francis --- hw/riscv/opentitan.c | 2 +- target/riscv/cpu-qom.h | 2 +- target/riscv/cpu.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c index 309125e854..19cb35b351 100644 --- a/hw/riscv/opentitan.c +++ b/hw/riscv/opentitan.c @@ -119,7 +119,7 @@ static void opentitan_machine_class_init(ObjectClass *o= c, const void *data) mc->desc =3D "RISC-V Board compatible with OpenTitan"; mc->init =3D opentitan_machine_init; mc->max_cpus =3D 1; - mc->default_cpu_type =3D TYPE_RISCV_CPU_IBEX; + mc->default_cpu_type =3D TYPE_RISCV_CPU_LOWRISC_IBEX; mc->default_ram_id =3D "riscv.lowrisc.ibex.ram"; mc->default_ram_size =3D ibex_memmap[IBEX_DEV_RAM].size; } diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index 30dcdcfaae..3a6394fd11 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -42,7 +42,7 @@ #define TYPE_RISCV_CPU_RVA22S64 RISCV_CPU_TYPE_NAME("rva22s64") #define TYPE_RISCV_CPU_RVA23U64 RISCV_CPU_TYPE_NAME("rva23u64") #define TYPE_RISCV_CPU_RVA23S64 RISCV_CPU_TYPE_NAME("rva23s64") -#define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex") +#define TYPE_RISCV_CPU_LOWRISC_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex") #define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c") #define TYPE_RISCV_CPU_SIFIVE_E RISCV_CPU_TYPE_NAME("sifive-e") #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31") diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index e56470a374..24a4c2fd3f 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -3043,7 +3043,7 @@ static const TypeInfo riscv_cpu_type_infos[] =3D { .misa_mxl_max =3D MXL_RV32, ), =20 - DEFINE_RISCV_CPU(TYPE_RISCV_CPU_IBEX, TYPE_RISCV_VENDOR_CPU, + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_LOWRISC_IBEX, TYPE_RISCV_VENDOR_CPU, .misa_mxl_max =3D MXL_RV32, .misa_ext =3D RVI | RVM | RVC | RVU, .priv_spec =3D PRIV_VERSION_1_12_0, --=20 2.49.1 From nobody Sun Apr 12 00:57:42 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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; dmarc=fail(p=none dis=none) header.from=git.sr.ht Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1771600187780862.1023920267216; Fri, 20 Feb 2026 07:09:47 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vtS7u-0005sC-6Z; Fri, 20 Feb 2026 10:09:06 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS26-00087z-5T; Fri, 20 Feb 2026 10:03:07 -0500 Received: from mail-a.sr.ht ([46.23.81.152]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS24-0002J4-8g; Fri, 20 Feb 2026 10:03:05 -0500 Received: from git.sr.ht (unknown [46.23.81.155]) by mail-a.sr.ht (Postfix) with ESMTPSA id BF9B725018; Fri, 20 Feb 2026 15:03:01 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=fYomp+aGUznWhaP+Te2FfkZ0k+Rqrbj8Q85aJKAFHgk=; c=simple/simple; d=git.sr.ht; h=From:Date:Subject:Reply-to:In-Reply-To:To:Cc; q=dns/txt; s=20240113; t=1771599781; v=1; b=NpZDTX4LEImvhDeBXxNMpLX5P105CsVfnwjFbuTQmK1ypI47wCAGfBDnMW0eg6QweOMpl4Qq dMph0k6cL2tkIu+VkT9BijBd7p4GREyQgswAM0KMgWMcAsvrYNfhXPDbLwit4CmbgQYLF9MQpcn rOdCqHrKqSygfdEEXWG6vySKyumPGejlyxzouQLb00+SmbPUV1YnxAH0G34yC4jhYFgREj5jPym jXKDNU5BLAILgG5s9wMtnH4Oz3PiKvC9MegOQbCi5IaDzf7nH3XxEUG6okSU6l5ki89RIy0ZqVK xqIMUysITOjjtZea9pJ7sgrYR0Na4jAC6+GM/7al6x77Q== From: ~lexbaileylowrisc Date: Mon, 30 Jan 2023 13:14:50 +0100 Subject: [PATCH qemu 02/11] [ot] hw/char, hw/timer, hw/ssi: fix device definitions Message-ID: <177159976712.8279.7732381632410882915-2@git.sr.ht> X-Mailer: git.sr.ht In-Reply-To: <177159976712.8279.7732381632410882915-0@git.sr.ht> To: qemu-devel@nongnu.org Cc: Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , qemu-riscv@nongnu.org, Paolo Bonzini , =?utf-8?q?Marc-Andr=C3=A9?= Lureau , Alistair Francis , Pierrick Bouvier , "Dr. David Alan Gilbert" , Daniel =?utf-8?q?P=2E_Berrang=C3=A9?= , Philippe =?utf-8?q?Mathieu-Daud=C3=A9?= , lowRISC , nabihestefan@google.com, Amit Kumar-Hermosillo Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 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=46.23.81.152; envelope-from=outgoing@sr.ht; helo=mail-a.sr.ht X-Spam_score_int: 17 X-Spam_score: 1.7 X-Spam_bar: + X-Spam_report: (1.7 / 5.0 requ) BAYES_00=-1.9, DATE_IN_PAST_96_XX=3.405, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Fri, 20 Feb 2026 10:09:01 -0500 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: ~lexbaileylowrisc Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1771600189971158500 From: Emmanuel Blot Use a separate Kconfig symbols for Ibex UART, Timer, and SPI devices: having an Ibex CPU does not imply usage of these specific implementations. Signed-off-by: Emmanuel Blot --- hw/char/Kconfig | 3 +++ hw/char/meson.build | 2 +- hw/riscv/Kconfig | 3 +++ hw/ssi/Kconfig | 4 ++++ hw/ssi/meson.build | 2 +- hw/timer/Kconfig | 3 +++ hw/timer/ibex_timer.c | 2 +- hw/timer/meson.build | 2 +- 8 files changed, 17 insertions(+), 4 deletions(-) diff --git a/hw/char/Kconfig b/hw/char/Kconfig index 020c0a84bb..0cbbaedb2f 100644 --- a/hw/char/Kconfig +++ b/hw/char/Kconfig @@ -95,3 +95,6 @@ config IP_OCTAL_232 bool default y depends on IPACK + +config IBEX_UART + bool diff --git a/hw/char/meson.build b/hw/char/meson.build index a9e1dc26c0..f47fa11bbe 100644 --- a/hw/char/meson.build +++ b/hw/char/meson.build @@ -2,7 +2,7 @@ system_ss.add(when: 'CONFIG_CADENCE', if_true: files('caden= ce_uart.c')) system_ss.add(when: 'CONFIG_CMSDK_APB_UART', if_true: files('cmsdk-apb-uar= t.c')) system_ss.add(when: 'CONFIG_ESCC', if_true: files('escc.c')) system_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_apbuart.c')) -system_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_uart.c')) +system_ss.add(when: 'CONFIG_IBEX_UART', if_true: files('ibex_uart.c')) system_ss.add(when: 'CONFIG_IMX', if_true: files('imx_serial.c')) system_ss.add(when: 'CONFIG_IP_OCTAL_232', if_true: files('ipoctal232.c')) system_ss.add(when: 'CONFIG_ISA_BUS', if_true: files('parallel-isa.c')) diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 0222c93f87..e6aa32ee8f 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -38,6 +38,9 @@ config OPENTITAN default y depends on RISCV32 select IBEX + select IBEX_SPI_HOST + select IBEX_TIMER + select IBEX_UART select SIFIVE_PLIC select UNIMP =20 diff --git a/hw/ssi/Kconfig b/hw/ssi/Kconfig index 1bd56463c1..c8d573eeb9 100644 --- a/hw/ssi/Kconfig +++ b/hw/ssi/Kconfig @@ -32,3 +32,7 @@ config PNV_SPI config ALLWINNER_A10_SPI bool select SSI + +config IBEX_SPI_HOST + bool + select SSI diff --git a/hw/ssi/meson.build b/hw/ssi/meson.build index 6afb1ea200..a3ba319280 100644 --- a/hw/ssi/meson.build +++ b/hw/ssi/meson.build @@ -10,6 +10,6 @@ system_ss.add(when: 'CONFIG_XILINX_SPI', if_true: files('= xilinx_spi.c')) system_ss.add(when: 'CONFIG_XILINX_SPIPS', if_true: files('xilinx_spips.c'= )) system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-ospi= .c')) system_ss.add(when: 'CONFIG_IMX', if_true: files('imx_spi.c')) -system_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_spi_host.c')) +system_ss.add(when: 'CONFIG_IBEX_SPI_HOST', if_true: files('ibex_spi_host.= c')) system_ss.add(when: 'CONFIG_BCM2835_SPI', if_true: files('bcm2835_spi.c')) system_ss.add(when: 'CONFIG_PNV_SPI', if_true: files('pnv_spi.c')) diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig index b3d823ce2c..2fdefd0d1f 100644 --- a/hw/timer/Kconfig +++ b/hw/timer/Kconfig @@ -65,3 +65,6 @@ config STELLARIS_GPTM =20 config AVR_TIMER16 bool + +config IBEX_TIMER + bool diff --git a/hw/timer/ibex_timer.c b/hw/timer/ibex_timer.c index ee18652189..858e1a67de 100644 --- a/hw/timer/ibex_timer.c +++ b/hw/timer/ibex_timer.c @@ -31,7 +31,7 @@ #include "hw/timer/ibex_timer.h" #include "hw/core/irq.h" #include "hw/core/qdev-properties.h" -#include "target/riscv/cpu.h" +#include "hw/core/registerfields.h" #include "migration/vmstate.h" =20 REG32(ALERT_TEST, 0x00) diff --git a/hw/timer/meson.build b/hw/timer/meson.build index 178321c029..cc02aa0dda 100644 --- a/hw/timer/meson.build +++ b/hw/timer/meson.build @@ -30,7 +30,7 @@ system_ss.add(when: 'CONFIG_SSE_TIMER', if_true: files('s= se-timer.c')) system_ss.add(when: 'CONFIG_STELLARIS_GPTM', if_true: files('stellaris-gpt= m.c')) system_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_ti= mer.c')) system_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c')) -specific_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_timer.c')) +system_ss.add(when: 'CONFIG_IBEX_TIMER', if_true: files('ibex_timer.c')) system_ss.add(when: 'CONFIG_SIFIVE_PWM', if_true: files('sifive_pwm.c')) =20 specific_ss.add(when: 'CONFIG_AVR_TIMER16', if_true: files('avr_timer16.c'= )) --=20 2.49.1 From nobody Sun Apr 12 00:57:42 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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; dmarc=fail(p=none dis=none) header.from=git.sr.ht Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1771600231125994.5979623820047; Fri, 20 Feb 2026 07:10:31 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vtS7t-0005ri-72; Fri, 20 Feb 2026 10:09:05 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS2C-0008Cn-1p; Fri, 20 Feb 2026 10:03:13 -0500 Received: from mail-a.sr.ht ([46.23.81.152]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS29-0002Kl-7Y; Fri, 20 Feb 2026 10:03:11 -0500 Received: from git.sr.ht (unknown [46.23.81.155]) by mail-a.sr.ht (Postfix) with ESMTPSA id D306625019; Fri, 20 Feb 2026 15:03:02 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=WWZhY35LLWHeJdCFFOr+e8kJW4fpE0wdAgDqorcI8cE=; c=simple/simple; d=git.sr.ht; h=From:Date:Subject:Reply-to:In-Reply-To:To:Cc; q=dns/txt; s=20240113; t=1771599782; v=1; b=E1ZCIiDdZvF6fSlCx5QSPrkzDlCGfCY1B6tSMNvOVGqUg8qhUEUlnSAKY9v/kLqJMxJ7l2SU Q0sORnKRzPEgHDlPSmGiC+a//H6noMza/UbugRBoUbxaAqv7fNyUXZookNlKeOYUxXY1mvUPq83 IopqKbcCEHdOzZwn3LH57xqU9O6AiYNJU55z/M1xvEDiysi98C/lfOkUyvLrZmsQqbnAZHHtOfi LseEjFSSHPPCh55PtPryf+LlnvY+qZTnXGkxsgarf5SHLYs0MQKSwBF8/ikRx9/1/CI5T8MGExw A+er3bW6tnvGLf8DZ7nfIYUzos724NlwonRRjuX2hmtiQ== From: ~lexbaileylowrisc Date: Mon, 05 Jun 2023 12:24:08 +0200 Subject: [PATCH qemu 03/11] [ot] hw/riscv: add helper for Ibex platforms Message-ID: <177159976712.8279.7732381632410882915-3@git.sr.ht> X-Mailer: git.sr.ht In-Reply-To: <177159976712.8279.7732381632410882915-0@git.sr.ht> To: qemu-devel@nongnu.org Cc: Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , qemu-riscv@nongnu.org, Paolo Bonzini , =?utf-8?q?Marc-Andr=C3=A9?= Lureau , Alistair Francis , Pierrick Bouvier , "Dr. David Alan Gilbert" , Daniel =?utf-8?q?P=2E_Berrang=C3=A9?= , Philippe =?utf-8?q?Mathieu-Daud=C3=A9?= , lowRISC , nabihestefan@google.com, Amit Kumar-Hermosillo Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 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=46.23.81.152; envelope-from=outgoing@sr.ht; helo=mail-a.sr.ht X-Spam_score_int: 17 X-Spam_score: 1.7 X-Spam_bar: + X-Spam_report: (1.7 / 5.0 requ) BAYES_00=-1.9, DATE_IN_PAST_96_XX=3.405, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Fri, 20 Feb 2026 10:09:01 -0500 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: ~lexbaileylowrisc Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1771600232167158500 From: Emmanuel Blot Signed-off-by: Lex Bailey --- MAINTAINERS | 14 +- hmp-commands-info.hx | 12 ++ hw/riscv/Kconfig | 3 + hw/riscv/ibex_common.c | 316 ++++++++++++++++++++++++++++++++ hw/riscv/meson.build | 1 + include/hw/riscv/ibex_common.h | 322 +++++++++++++++++++++++++++++++++ 6 files changed, 666 insertions(+), 2 deletions(-) create mode 100644 hw/riscv/ibex_common.c create mode 100644 include/hw/riscv/ibex_common.h diff --git a/MAINTAINERS b/MAINTAINERS index e0c481e212..8b8bb7b554 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1716,9 +1716,13 @@ M: Alistair Francis L: qemu-riscv@nongnu.org S: Supported F: hw/riscv/opentitan.c -F: hw/*/ibex_*.c +F: hw/ssi/ibex_spi_host.c +F: hw/timer/ibex_timer.c +F: hw/char/ibex_uart.c F: include/hw/riscv/opentitan.h -F: include/hw/*/ibex_*.h +F: include/hw/ssi/ibex_spi_host.h +F: include/hw/timer/ibex_timer.h +F: include/hw/char/ibex_uart.h =20 Microchip PolarFire SoC Icicle Kit L: qemu-riscv@nongnu.org @@ -4450,6 +4454,12 @@ F: docs/devel/ebpf_rss.rst F: ebpf/* F: tools/ebpf/* =20 +Ibex +M: lowRISC +S: Supported +F: hw/riscv/ibex_common.c +F: include/hw/riscv/ibex_common.h +F: include/hw/riscv/ibex_irq.h Build and test automation ------------------------- Build and test automation, general continuous integration diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index 74c741f80e..90f05f7599 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -1010,3 +1010,15 @@ SRST ``info firmware-log`` Show the firmware (ovmf) debug log. ERST + + { + .name =3D "ibex", + .args_type =3D "", + .params =3D "", + .help =3D "Show Ibex vCPU info", + }, + +SRST + ``info ibex`` + Show Ibex vCPU information. +ERST diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index e6aa32ee8f..7877f0615c 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -7,6 +7,9 @@ config RISCV_NUMA config IBEX bool =20 +config IBEX_COMMON + bool + # RISC-V machines in alphabetical order =20 config MICROCHIP_PFSOC diff --git a/hw/riscv/ibex_common.c b/hw/riscv/ibex_common.c new file mode 100644 index 0000000000..c6056767c7 --- /dev/null +++ b/hw/riscv/ibex_common.c @@ -0,0 +1,316 @@ +/* + * QEMU RISC-V Helpers for LowRISC Ibex Demo System & OpenTitan EarlGrey + * + * Copyright (c) 2022-2023 Rivos, Inc. + * + * Author(s): + * Emmanuel Blot + * Lo=C3=AFc Lefort + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "cpu.h" +#include "disas/disas.h" +#include "elf.h" +#include "exec/hwaddr.h" +#include "hw/boards.h" +#include "hw/loader.h" +#include "hw/misc/unimp.h" +#include "hw/qdev-core.h" +#include "hw/qdev-properties.h" +#include "hw/riscv/ibex_common.h" +#include "hw/sysbus.h" +#include "monitor/monitor.h" + + +static void ibex_mmio_map_device(SysBusDevice *dev, MemoryRegion *mr, + unsigned nr, hwaddr addr) +{ + assert(nr < dev->num_mmio); + assert(dev->mmio[nr].addr =3D=3D (hwaddr)-1); + dev->mmio[nr].addr =3D addr; + memory_region_add_subregion(mr, addr, dev->mmio[nr].memory); +} + +DeviceState **ibex_create_devices(const IbexDeviceDef *defs, unsigned coun= t, + DeviceState *parent) +{ + DeviceState **devices =3D g_new0(DeviceState *, count); + unsigned unimp_count =3D 0; + for (unsigned idx =3D 0; idx < count; idx++) { + const IbexDeviceDef *def =3D &defs[idx]; + assert(def->type); + devices[idx] =3D qdev_new(def->type); + + char *name; + if (!strcmp(def->type, TYPE_UNIMPLEMENTED_DEVICE)) { + if (def->name) { + name =3D g_strdup_printf("%s[%u]", def->name, def->instanc= e); + } else { + name =3D g_strdup_printf(TYPE_UNIMPLEMENTED_DEVICE "[%u]", + unimp_count); + } + unimp_count +=3D 1u; + } else { + name =3D g_strdup_printf("%s[%u]", def->type, def->instance); + } + object_property_add_child(OBJECT(parent), name, OBJECT(devices[idx= ])); + g_free(name); + } + return devices; +} + +void ibex_link_devices(DeviceState **devices, const IbexDeviceDef *defs, + unsigned count) +{ + /* Link devices */ + for (unsigned idx =3D 0; idx < count; idx++) { + DeviceState *dev =3D devices[idx]; + const IbexDeviceLinkDef *link =3D defs[idx].link; + if (link) { + while (link->propname) { + DeviceState *target =3D devices[link->index]; + (void)object_property_set_link(OBJECT(dev), link->propname, + OBJECT(target), &error_fata= l); + link++; + } + } + } +} + +void ibex_define_device_props(DeviceState **devices, const IbexDeviceDef *= defs, + unsigned count) +{ + for (unsigned idx =3D 0; idx < count; idx++) { + DeviceState *dev =3D devices[idx]; + const IbexDevicePropDef *prop =3D defs[idx].prop; + if (prop) { + while (prop->propname) { + switch (prop->type) { + case IBEX_PROP_TYPE_BOOL: + object_property_set_bool(OBJECT(dev), prop->propname, + prop->b, &error_fatal); + break; + case IBEX_PROP_TYPE_INT: + object_property_set_int(OBJECT(dev), prop->propname, + prop->i, &error_fatal); + break; + case IBEX_PROP_TYPE_UINT: + object_property_set_int(OBJECT(dev), prop->propname, + prop->u, &error_fatal); + break; + case IBEX_PROP_TYPE_STR: + object_property_set_str(OBJECT(dev), prop->propname, + prop->s, &error_fatal); + break; + default: + g_assert_not_reached(); + break; + } + prop++; + } + } + } +} + +void ibex_realize_system_devices(DeviceState **devices, + const IbexDeviceDef *defs, unsigned count) +{ + BusState *bus =3D sysbus_get_default(); + + ibex_realize_devices(devices, bus, defs, count); + + MemoryRegion *mrs[] =3D { get_system_memory(), NULL, NULL, NULL }; + + ibex_map_devices(devices, mrs, defs, count); +} + +void ibex_realize_devices(DeviceState **devices, BusState *bus, + const IbexDeviceDef *defs, unsigned count) +{ + /* Realize devices */ + for (unsigned idx =3D 0; idx < count; idx++) { + DeviceState *dev =3D devices[idx]; + const IbexDeviceDef *def =3D &defs[idx]; + + if (def->cfg) { + def->cfg(dev, def, DEVICE(OBJECT(dev)->parent)); + } + + if (def->memmap) { + SysBusDevice *busdev =3D + (SysBusDevice *)object_dynamic_cast(OBJECT(dev), + TYPE_SYS_BUS_DEVICE); + if (!busdev) { + /* non-sysbus devices are not supported for now */ + g_assert_not_reached(); + } + + qdev_realize_and_unref(DEVICE(busdev), bus, &error_fatal); + } else { + /* device is not connected to a bus */ + qdev_realize_and_unref(dev, NULL, &error_fatal); + } + } +} + +void ibex_map_devices(DeviceState **devices, MemoryRegion **mrs, + const IbexDeviceDef *defs, unsigned count) +{ + for (unsigned idx =3D 0; idx < count; idx++) { + DeviceState *dev =3D devices[idx]; + const IbexDeviceDef *def =3D &defs[idx]; + + if (def->memmap) { + SysBusDevice *busdev =3D + (SysBusDevice *)object_dynamic_cast(OBJECT(dev), + TYPE_SYS_BUS_DEVICE); + if (busdev) { + const MemMapEntry *memmap =3D def->memmap; + unsigned mem =3D 0; + while (memmap->size) { + unsigned region =3D IBEX_MEMMAP_GET_REGIDX(memmap->bas= e); + MemoryRegion *mr =3D mrs[region]; + if (mr) { + ibex_mmio_map_device(busdev, mr, mem, + IBEX_MEMMAP_GET_ADDRESS( + memmap->base)); + } + mem++; + memmap++; + } + } + } + } +} + +void ibex_connect_devices(DeviceState **devices, const IbexDeviceDef *defs, + unsigned count) +{ + /* Connect GPIOs (in particular, IRQs) */ + for (unsigned idx =3D 0; idx < count; idx++) { + DeviceState *dev =3D devices[idx]; + const IbexDeviceDef *def =3D &defs[idx]; + + if (def->gpio) { + const IbexGpioConnDef *conn =3D def->gpio; + while (conn->out.num >=3D 0 && conn->in.num >=3D 0) { + qemu_irq in_gpio =3D + qdev_get_gpio_in_named(devices[conn->in.index], + conn->in.name, conn->in.num); + + qdev_connect_gpio_out_named(dev, conn->out.name, conn->out= .num, + in_gpio); + conn++; + } + } + } +} + +void ibex_configure_devices(DeviceState **devices, BusState *bus, + const IbexDeviceDef *defs, unsigned count) +{ + ibex_link_devices(devices, defs, count); + ibex_define_device_props(devices, defs, count); + ibex_realize_devices(devices, bus, defs, count); + ibex_connect_devices(devices, defs, count); +} + +void ibex_unimp_configure(DeviceState *dev, const IbexDeviceDef *def, + DeviceState *parent) +{ + if (def->name) { + qdev_prop_set_string(dev, "name", def->name); + } + assert(def->memmap !=3D NULL); + assert(def->memmap->size !=3D 0); + qdev_prop_set_uint64(dev, "size", def->memmap->size); +} + +void ibex_load_kernel(AddressSpace *as) +{ + MachineState *ms =3D MACHINE(qdev_get_machine()); + + /* load kernel if provided */ + if (ms->kernel_filename) { + uint64_t kernel_entry; + if (load_elf_ram_sym(ms->kernel_filename, NULL, NULL, NULL, + &kernel_entry, NULL, NULL, NULL, 0, EM_RISCV,= 1, 0, + as, true, NULL) <=3D 0) { + error_report("Cannot load ELF kernel %s", ms->kernel_filename); + exit(EXIT_FAILURE); + } + + CPUState *cpu; + CPU_FOREACH(cpu) { + if (!as || cpu->as =3D=3D as) { + CPURISCVState *env =3D &RISCV_CPU(cpu)->env; + env->resetvec =3D (target_ulong)kernel_entry; + } + } + } +} + +uint64_t ibex_get_current_pc(void) +{ + CPUState *cs =3D current_cpu; + + return cs && cs->cc->get_pc ? cs->cc->get_pc(cs) : 0u; +} + +/* x0 is replaced with PC */ +static const char ibex_ireg_names[32u][4u] =3D { + "pc", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", + "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", + "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", +}; + +void ibex_log_vcpu_registers(uint64_t regbm) +{ + CPURISCVState *env =3D &RISCV_CPU(current_cpu)->env; + qemu_log_mask(CPU_LOG_TB_IN_ASM, "\n....\n"); + if (regbm & 0x1u) { + qemu_log_mask(CPU_LOG_TB_IN_ASM, "%4s: 0x" TARGET_FMT_lx "\n", + ibex_ireg_names[0], env->pc); + } + for (unsigned gix =3D 1u; gix < 32u; gix++) { + uint64_t mask =3D 1u << gix; + if (regbm & mask) { + qemu_log_mask(CPU_LOG_TB_IN_ASM, "%4s: 0x" TARGET_FMT_lx "\n", + ibex_ireg_names[gix], env->gpr[gix]); + } + } +} + +/* + * Note: this is not specific to Ibex, and might apply to any vCPU. + */ +static void hmp_info_ibex(Monitor *mon, const QDict *qdict) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + vaddr pc; + const char *symbol; + if (cpu->cc->get_pc) { + pc =3D cpu->cc->get_pc(cpu); + symbol =3D lookup_symbol(pc); + } else { + pc =3D -1; + symbol =3D "?"; + } + monitor_printf(mon, "* CPU #%d: 0x%" PRIx64 " in '%s'\n", + cpu->cpu_index, (uint64_t)pc, symbol); + } +} + +static void ibex_register_types(void) +{ + monitor_register_hmp("ibex", true, &hmp_info_ibex); +} + +type_init(ibex_register_types) diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index 533472e22a..70d63f56b5 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -3,6 +3,7 @@ riscv_ss.add(files('boot.c')) riscv_ss.add(when: 'CONFIG_RISCV_NUMA', if_true: files('numa.c')) riscv_ss.add(files('riscv_hart.c')) riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c')) +riscv_ss.add(when: 'CONFIG_IBEX_COMMON', if_true: files('ibex_common.c')) riscv_ss.add(when: 'CONFIG_RISCV_VIRT', if_true: files('virt.c')) riscv_ss.add(when: 'CONFIG_SHAKTI_C', if_true: files('shakti_c.c')) riscv_ss.add(when: 'CONFIG_SIFIVE_E', if_true: files('sifive_e.c')) diff --git a/include/hw/riscv/ibex_common.h b/include/hw/riscv/ibex_common.h new file mode 100644 index 0000000000..6c7dae5cbe --- /dev/null +++ b/include/hw/riscv/ibex_common.h @@ -0,0 +1,322 @@ +/* + * QEMU RISC-V Helpers for LowRISC OpenTitan EarlGrey and related systems + * + * Copyright (c) 2022-2023 Rivos, Inc. + * + * Author(s): + * Emmanuel Blot + * Lo=C3=AFc Lefort + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_RISCV_IBEX_COMMON_H +#define HW_RISCV_IBEX_COMMON_H + +#include "qemu/osdep.h" +#include "qom/object.h" +#include "exec/hwaddr.h" +#include "hw/qdev-core.h" + + +/* -----------------------------------------------------------------------= - */ +/* Devices & GPIOs */ +/* -----------------------------------------------------------------------= - */ + +#define IBEX_MAX_MMIO_ENTRIES 4u +#define IBEX_MAX_GPIO_ENTRIES 16u + +typedef struct IbexDeviceDef IbexDeviceDef; + +typedef void (*ibex_dev_cfg_fn)(DeviceState *dev, const IbexDeviceDef *def, + DeviceState *parent); + +/** + * Structure defining a GPIO connection (in particular, IRQs) from the cur= rent + * device to a target device + */ +typedef struct { + /** Source GPIO */ + struct { + /** Name of source GPIO array or NULL for unnamed */ + const char *name; + /** Index of source output GPIO */ + int num; + } out; + + /** Target GPIO */ + struct { + /** Target device index */ + int index; + /** Name of target input GPIO array or NULL for unnamed */ + const char *name; + /** Index of target input GPIO */ + int num; + } in; +} IbexGpioConnDef; + +typedef struct { + /** Name of the property to assign the linked device to */ + const char *propname; + /** Linked device index */ + int index; +} IbexDeviceLinkDef; + +/** Type of device property */ +typedef enum { + IBEX_PROP_TYPE_BOOL, + IBEX_PROP_TYPE_INT, + IBEX_PROP_TYPE_UINT, + IBEX_PROP_TYPE_STR, +} IbexPropertyType; + +typedef struct { + /** Name of the property */ + const char *propname; + /** Type of property */ + IbexPropertyType type; + /** Value */ + union { + bool b; + int64_t i; + uint64_t u; + const char *s; + }; +} IbexDevicePropDef; + +struct IbexDeviceDef { + /** Registered type of the device */ + const char *type; + /** Optional name, may be NULL */ + const char *name; + /** Instance number, default to 0 */ + int instance; + /** Optional configuration function */ + ibex_dev_cfg_fn cfg; + /** Array of memory map */ + const MemMapEntry *memmap; + /** Array of GPIO connections */ + const IbexGpioConnDef *gpio; + /** Array of linked devices */ + const IbexDeviceLinkDef *link; + /** Array of properties */ + const IbexDevicePropDef *prop; +}; + +/* + * Special memory address marked to flag a special MemMapEntry. + * Flagged MemMapEntry are used to select a memory region while mem mapping + * devices. There could be up to 4 different regions. + */ +#define IBEX_MEMMAP_REGIDX_COUNT 4u +#define IBEX_MEMMAP_REGIDX_MASK \ + ((IBEX_MEMMAP_REGIDX_COUNT) - 1u) /* address are always word-aligned */ +#define IBEX_MEMMAP_MAKE_REG(_addr_, _flag_) \ + ((_addr_) | ((_flag_) & IBEX_MEMMAP_REGIDX_MASK)) +#define IBEX_MEMMAP_GET_REGIDX(_addr_) ((_addr_) & IBEX_MEMMAP_REGIDX_MASK) +#define IBEX_MEMMAP_GET_ADDRESS(_addr_) ((_addr_) & ~IBEX_MEMMAP_REGIDX_MA= SK) + +/** + * Create memory map entries, each arg is MemMapEntry definition + */ +#define MEMMAPENTRIES(...) \ + (const MemMapEntry[]) \ + { \ + __VA_ARGS__, \ + { \ + .size =3D 0u \ + } \ + } + +/** + * Create GPIO connection entries, each arg is IbexGpioConnDef definition + */ +#define IBEXGPIOCONNDEFS(...) \ + (const IbexGpioConnDef[]) \ + { \ + __VA_ARGS__, \ + { \ + .out =3D {.num =3D -1 } \ + } \ + } + +/** + * Create device link entries, each arg is IbexDeviceLinkDef definition + */ +#define IBEXDEVICELINKDEFS(...) \ + (const IbexDeviceLinkDef[]) \ + { \ + __VA_ARGS__, \ + { \ + .propname =3D NULL \ + } \ + } + +/** + * Create device property entries, each arg is IbexDevicePropDef definition + */ +#define IBEXDEVICEPROPDEFS(...) \ + (const IbexDevicePropDef[]) \ + { \ + __VA_ARGS__, \ + { \ + .propname =3D NULL \ + } \ + } + +/** + * Create a IbexGpioConnDef to connect two unnamed GPIOs + */ +#define IBEX_GPIO(_irq_, _in_idx_, _num_) \ + { \ + .out =3D { \ + .num =3D (_irq_), \ + }, \ + .in =3D { \ + .index =3D (_in_idx_), \ + .num =3D (_num_), \ + } \ + } + +/** + * Create a IbexGpioConnDef to connect a SysBus IRQ to an unnamed GPIO + */ +#define IBEX_GPIO_SYSBUS_IRQ(_irq_, _in_idx_, _num_) \ + { \ + .out =3D { \ + .name =3D SYSBUS_DEVICE_GPIO_IRQ, \ + .num =3D (_irq_), \ + }, \ + .in =3D { \ + .index =3D (_in_idx_), \ + .num =3D (_num_), \ + } \ + } + +/** + * Create a IbexLinkDeviceDef to link one device to another + */ +#define IBEX_DEVLINK(_pname_, _idx_) \ + { \ + .propname =3D (_pname_), .index =3D (_idx_), \ + } + +/** + * Create a boolean device property + */ +#define IBEX_DEV_BOOL_PROP(_pname_, _b_) \ + { \ + .propname =3D (_pname_), .type =3D IBEX_PROP_TYPE_BOOL, .b =3D (_b= _), \ + } + +/** + * Create a signed integer device property + */ +#define IBEX_DEV_INT_PROP(_pname_, _i_) \ + { \ + .propname =3D (_pname_), .type =3D IBEX_PROP_TYPE_INT, .i =3D (_i_= ), \ + } + +/** + * Create an unsigned integer device property + */ +#define IBEX_DEV_UINT_PROP(_pname_, _u_) \ + { \ + .propname =3D (_pname_), .type =3D IBEX_PROP_TYPE_UINT, .u =3D (_u= _), \ + } + +/** + * Create a string device property + */ +#define IBEX_DEV_STRING_PROP(_pname_, _s_) \ + { \ + .propname =3D (_pname_), .type =3D IBEX_PROP_TYPE_STR, .s =3D (_s_= ), \ + } + +DeviceState **ibex_create_devices(const IbexDeviceDef *defs, unsigned coun= t, + DeviceState *parent); +void ibex_link_devices(DeviceState **devices, const IbexDeviceDef *defs, + unsigned count); +void ibex_define_device_props(DeviceState **devices, const IbexDeviceDef *= defs, + unsigned count); +void ibex_realize_system_devices(DeviceState **devices, + const IbexDeviceDef *defs, unsigned count= ); +void ibex_realize_devices(DeviceState **devices, BusState *bus, + const IbexDeviceDef *defs, unsigned count); +void ibex_connect_devices(DeviceState **devices, const IbexDeviceDef *defs, + unsigned count); +void ibex_map_devices(DeviceState **devices, MemoryRegion **mrs, + const IbexDeviceDef *defs, unsigned count); +void ibex_configure_devices(DeviceState **devices, BusState *bus, + const IbexDeviceDef *defs, unsigned count); + +/** + * Utility function to configure unimplemented device. + * The Ibex device definition should have one defined memory entry, and an + * optional name. + */ +void ibex_unimp_configure(DeviceState *dev, const IbexDeviceDef *def, + DeviceState *parent); + +/* -----------------------------------------------------------------------= - */ +/* CPU */ +/* -----------------------------------------------------------------------= - */ + +/** + * Load an ELF application into a CPU address space. + * @as the address space to load the application into, maybe NULL to use t= he + * default address space + */ +void ibex_load_kernel(AddressSpace *as); + +/** + * Helper for device debugging: report the current guest PC, if any. + * + * If a HW access is performed from another device but the CPU, reported PC + * is 0. + */ +uint64_t ibex_get_current_pc(void); + +enum { + RV_GPR_PC =3D (1u << 0u), + RV_GPR_RA =3D (1u << 1u), + RV_GPR_SP =3D (1u << 2u), + RV_GPR_GP =3D (1u << 3u), + RV_GPR_TP =3D (1u << 4u), + RV_GPR_T0 =3D (1u << 5u), + RV_GPR_T1 =3D (1u << 6u), + RV_GPR_T2 =3D (1u << 7u), + RV_GPR_S0 =3D (1u << 8u), + RV_GPR_S1 =3D (1u << 9u), + RV_GPR_A0 =3D (1u << 10u), + RV_GPR_A1 =3D (1u << 11u), + RV_GPR_A2 =3D (1u << 12u), + RV_GPR_A3 =3D (1u << 13u), + RV_GPR_A4 =3D (1u << 14u), + RV_GPR_A5 =3D (1u << 15u), + RV_GPR_A6 =3D (1u << 16u), + RV_GPR_A7 =3D (1u << 17u), + RV_GPR_S2 =3D (1u << 18u), + RV_GPR_S3 =3D (1u << 19u), + RV_GPR_S4 =3D (1u << 20u), + RV_GPR_S5 =3D (1u << 21u), + RV_GPR_S6 =3D (1u << 22u), + RV_GPR_S7 =3D (1u << 23u), + RV_GPR_S8 =3D (1u << 24u), + RV_GPR_S9 =3D (1u << 25u), + RV_GPR_S10 =3D (1u << 26u), + RV_GPR_S11 =3D (1u << 27u), + RV_GPR_T3 =3D (1u << 28u), + RV_GPR_T4 =3D (1u << 29u), + RV_GPR_T5 =3D (1u << 30u), + RV_GPR_T6 =3D (1u << 31u), +}; + +/** + * Log current vCPU registers. + * + * @regbm is a bitmap of registers to be dumped [x1..t6], pc replace x0 + */ +void ibex_log_vcpu_registers(uint64_t regbm); + +#endif /* HW_RISCV_IBEX_COMMON_H */ --=20 2.49.1 From nobody Sun Apr 12 00:57:42 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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; dmarc=fail(p=none dis=none) header.from=git.sr.ht Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1771600189702809.2782157791714; Fri, 20 Feb 2026 07:09:49 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vtS7s-0005rf-O1; Fri, 20 Feb 2026 10:09:04 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS2B-0008CR-1t; Fri, 20 Feb 2026 10:03:12 -0500 Received: from mail-a.sr.ht ([46.23.81.152]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS29-0002Kp-C0; Fri, 20 Feb 2026 10:03:10 -0500 Received: from git.sr.ht (unknown [46.23.81.155]) by mail-a.sr.ht (Postfix) with ESMTPSA id EA4552501C; Fri, 20 Feb 2026 15:03:07 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=y3mnVFRBz48Yw2IzjiSIHXssFaZ5U7MLuEMtGzsSPsc=; c=simple/simple; d=git.sr.ht; h=From:Date:Subject:Reply-to:In-Reply-To:To:Cc; q=dns/txt; s=20240113; t=1771599788; v=1; b=oWxUtkgku9BWFCUpjeFwgablpsBkq6mt2Sx0G5UnGB2BJ/xwWv9J3+f2Ua4lkfOH06rwl0Af lL3kV8nD9fTVjxOjvvnMvKJDsq5exY+bWaIImzmKS/kOY//u3x+yR/NI/nDt26muVvaRGmV46hy Zmjnncqr/ridAYFG8ndMyQhGllMsZiDJhLFP0h/+LTdluh4z2CZkNr+yYM80GGV86Dc4KHJwjjP vlwfWuhRj5Dlw0dGOcyTr/u84PgjptogtrPtrqnFWczAyHbtipDc9tWMyuFM9XF9ZI7iW6tlwXR KwkLXqFaMDsG4THRE3U0UepObfbBn519ephrf7YX2SsDg== From: ~lexbaileylowrisc Date: Tue, 07 Feb 2023 16:59:35 +0100 Subject: [PATCH qemu 04/11] [ot] target/riscv: implement custom LowRisc Ibex CSRs Message-ID: <177159976712.8279.7732381632410882915-4@git.sr.ht> X-Mailer: git.sr.ht In-Reply-To: <177159976712.8279.7732381632410882915-0@git.sr.ht> To: qemu-devel@nongnu.org Cc: Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , qemu-riscv@nongnu.org, Paolo Bonzini , =?utf-8?q?Marc-Andr=C3=A9?= Lureau , Alistair Francis , Pierrick Bouvier , "Dr. David Alan Gilbert" , Daniel =?utf-8?q?P=2E_Berrang=C3=A9?= , Philippe =?utf-8?q?Mathieu-Daud=C3=A9?= , lowRISC , nabihestefan@google.com, Amit Kumar-Hermosillo Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 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=46.23.81.152; envelope-from=outgoing@sr.ht; helo=mail-a.sr.ht X-Spam_score_int: 17 X-Spam_score: 1.7 X-Spam_bar: + X-Spam_report: (1.7 / 5.0 requ) BAYES_00=-1.9, DATE_IN_PAST_96_XX=3.405, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Fri, 20 Feb 2026 10:09:01 -0500 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: ~lexbaileylowrisc Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1771600191853158500 From: Emmanuel Blot Signed-off-by: Emmanuel Blot Includes existing MIT licenced code (already published elsewhere) --- target/riscv/cpu.c | 2 +- target/riscv/cpu.h | 7 ++++ target/riscv/ibex_csr.c | 85 ++++++++++++++++++++++++++++++++++++++++ target/riscv/meson.build | 1 + 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 target/riscv/ibex_csr.c diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 24a4c2fd3f..dd30b21dd2 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -3056,7 +3056,7 @@ static const TypeInfo riscv_cpu_type_infos[] =3D { .cfg.ext_zba =3D true, .cfg.ext_zbb =3D true, .cfg.ext_zbc =3D true, - .cfg.ext_zbs =3D true + .cfg.ext_zbs =3D true, ), =20 DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_E31, TYPE_RISCV_CPU_SIFIVE_E, diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 35d1f6362c..faf55e8b5e 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -481,6 +481,10 @@ struct CPUArchState { uint64_t hstateen[SMSTATEEN_MAX_COUNT]; uint64_t sstateen[SMSTATEEN_MAX_COUNT]; uint64_t henvcfg; + + /* Ibex custom CSRs */ + target_ulong cpuctrlsts; + target_ulong secureseed; #endif =20 /* Fields from here on are preserved across CPU reset. */ @@ -988,5 +992,8 @@ extern const RISCVCSR th_csr_list[]; /* Implemented in mips_csr.c */ extern const RISCVCSR mips_csr_list[]; =20 +/* Implemented in ibex_csr.c */ +extern const RISCVCSR ibex_csr_list[]; + const char *priv_spec_to_str(int priv_version); #endif /* RISCV_CPU_H */ diff --git a/target/riscv/ibex_csr.c b/target/riscv/ibex_csr.c new file mode 100644 index 0000000000..d62638bbfb --- /dev/null +++ b/target/riscv/ibex_csr.c @@ -0,0 +1,85 @@ +/* + * QEMU LowRisc Ibex core features + * + * Copyright (c) 2023 Rivos, Inc. + * + * SPDX-License-Identifier: MIT + * + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "cpu.h" + +/* Custom CSRs */ +#define CSR_CPUCTRLSTS 0x7c0 +#define CSR_SECURESEED 0x7c1 + +#define CPUCTRLSTS_ICACHE_ENABLE 0x000 +#define CPUCTRLSTS_DATA_IND_TIMING 0x001 +#define CPUCTRLSTS_DUMMY_INSTR_EN 0x002 +#define CPUCTRLSTS_DUMMY_INSTR_MASK 0x038 +#define CPUCTRLSTS_SYNC_EXC_SEEN 0x040 +#define CPUCTRLSTS_DOUBLE_FAULT_SEEN 0x080 +#define CPUCTRLSTS_IC_SCR_KEY_VALID 0x100 + +#if !defined(CONFIG_USER_ONLY) + +static RISCVException read_cpuctrlsts(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val =3D CPUCTRLSTS_IC_SCR_KEY_VALID | env->cpuctrlsts; + return RISCV_EXCP_NONE; +} + +static RISCVException write_cpuctrlsts(CPURISCVState *env, int csrno, + target_ulong val, uintptr_t a) +{ + /* b7 can only be cleared */ + env->cpuctrlsts &=3D ~0xbf; + /* b6 should be cleared on mret */ + env->cpuctrlsts |=3D val & 0x3f; + return RISCV_EXCP_NONE; +} + +static RISCVException read_secureseed(CPURISCVState *env, int csrno, + target_ulong *val) +{ + /* + * "Seed values are not actually stored in a register and so reads to = this + * register will always return zero." + */ + *val =3D 0; + return RISCV_EXCP_NONE; +} + +static RISCVException write_secureseed(CPURISCVState *env, int csrno, + target_ulong val, uintptr_t a) +{ + (void)val; + return RISCV_EXCP_NONE; +} + +static RISCVException any(CPURISCVState *env, int csrno) +{ + /* + * unfortunately, this predicate is not public, so duplicate the stan= dard + * implementation + */ + return RISCV_EXCP_NONE; +} + +const RISCVCSR ibex_csr_list[] =3D { + { + .csrno =3D CSR_CPUCTRLSTS, + .csr_ops =3D { "cpuctrlsts", any, &read_cpuctrlsts, &write_cpuctrl= sts }, + }, + { + .csrno =3D CSR_SECURESEED, + .csr_ops =3D { "secureseed", any, &read_secureseed, &write_secures= eed }, + }, + {} +}; + +#endif /* !defined(CONFIG_USER_ONLY) */ + diff --git a/target/riscv/meson.build b/target/riscv/meson.build index 3842c7c1a8..5a174a6feb 100644 --- a/target/riscv/meson.build +++ b/target/riscv/meson.build @@ -17,6 +17,7 @@ riscv_ss.add(files( 'cpu.c', 'cpu_helper.c', 'csr.c', + 'ibex_csr.c', 'fpu_helper.c', 'gdbstub.c', 'op_helper.c', --=20 2.49.1 From nobody Sun Apr 12 00:57:42 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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; dmarc=fail(p=none dis=none) header.from=git.sr.ht Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1771600236039850.058919673606; Fri, 20 Feb 2026 07:10:36 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vtS7t-0005rm-NM; Fri, 20 Feb 2026 10:09:05 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS2C-0008D0-6P; Fri, 20 Feb 2026 10:03:13 -0500 Received: from mail-a.sr.ht ([46.23.81.152]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS29-0002Kr-F4; Fri, 20 Feb 2026 10:03:11 -0500 Received: from git.sr.ht (unknown [46.23.81.155]) by mail-a.sr.ht (Postfix) with ESMTPSA id 0EFA12501D; Fri, 20 Feb 2026 15:03:08 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=l6zKq+H7M6nbmk+wPFI6JyTis646VpV4edPZH5Wq97I=; c=simple/simple; d=git.sr.ht; h=From:Date:Subject:Reply-to:In-Reply-To:To:Cc; q=dns/txt; s=20240113; t=1771599788; v=1; b=Q+k+Fx/ZLLukMuaEksjQAQYnJamwm2l74t4fyoexuw9o2O3u9+79O5GZdEJuLV4upt9kDZRc hKfj1c2G/+8x+M2Kl/rXR1eYr3xaUFF8z2YuKMzutRkUn++CFV53XBLWkLC4GqBgZsXh+t76gL4 0SvWM5rpX/5b6tnji4K8taxkePDLkrFHw7P8eSdCazfoq5Jkk2DZajprB2s8q/StU4s1r5LyXf2 tfPzCIpxVDt/e04LaXNfQZJZjIPJ2v2boD+53+dW2vClfMzPAIxhh8xTVKGRhMU9H4CnmpAqnz5 H39E0N7IRUKgvjMii5/lyRqLx9wgWgK70yQ0Ft5jMgYzw== From: ~lexbaileylowrisc Date: Wed, 29 Mar 2023 19:16:44 +0200 Subject: [PATCH qemu 05/11] [ot] target/riscv: add custom mtvec CSR management Message-ID: <177159976712.8279.7732381632410882915-5@git.sr.ht> X-Mailer: git.sr.ht In-Reply-To: <177159976712.8279.7732381632410882915-0@git.sr.ht> To: qemu-devel@nongnu.org Cc: Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , qemu-riscv@nongnu.org, Paolo Bonzini , =?utf-8?q?Marc-Andr=C3=A9?= Lureau , Alistair Francis , Pierrick Bouvier , "Dr. David Alan Gilbert" , Daniel =?utf-8?q?P=2E_Berrang=C3=A9?= , Philippe =?utf-8?q?Mathieu-Daud=C3=A9?= , lowRISC , nabihestefan@google.com, Amit Kumar-Hermosillo Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 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=46.23.81.152; envelope-from=outgoing@sr.ht; helo=mail-a.sr.ht X-Spam_score_int: 17 X-Spam_score: 1.7 X-Spam_bar: + X-Spam_report: (1.7 / 5.0 requ) BAYES_00=-1.9, DATE_IN_PAST_96_XX=3.405, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Fri, 20 Feb 2026 10:09:01 -0500 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: ~lexbaileylowrisc Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1771600237806154100 From: Emmanuel Blot Signed-off-by: Emmanuel Blot --- target/riscv/ibex_csr.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/target/riscv/ibex_csr.c b/target/riscv/ibex_csr.c index d62638bbfb..a6e815e782 100644 --- a/target/riscv/ibex_csr.c +++ b/target/riscv/ibex_csr.c @@ -69,7 +69,37 @@ static RISCVException any(CPURISCVState *env, int csrno) return RISCV_EXCP_NONE; } =20 +static RISCVException read_mtvec(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val =3D env->mtvec; + + return RISCV_EXCP_NONE; +} + +static RISCVException write_mtvec(CPURISCVState *env, int csrno, + target_ulong val, uintptr_t a) +{ + /* bits [1:0] encode mode; Ibex only supports 1 =3D vectored */ + if ((val & 3u) !=3D 1u) { + qemu_log_mask(LOG_UNIMP, + "CSR_MTVEC: reserved mode not supported 0x" TARGET_FMT_lx "\n", + val); + /* WARL */ + return RISCV_EXCP_NONE; + } + + /* bits [7:2] are always 0, address should be aligned in 256 bytes */ + env->mtvec =3D val & ~0xFCu; + + return RISCV_EXCP_NONE; +} + const RISCVCSR ibex_csr_list[] =3D { + { + .csrno =3D CSR_MTVEC, + .csr_ops =3D { "mtvec", any, &read_mtvec, &write_mtvec }, + }, { .csrno =3D CSR_CPUCTRLSTS, .csr_ops =3D { "cpuctrlsts", any, &read_cpuctrlsts, &write_cpuctrl= sts }, --=20 2.49.1 From nobody Sun Apr 12 00:57:42 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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; dmarc=fail(p=none dis=none) header.from=git.sr.ht Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1771600191949731.6289648262499; Fri, 20 Feb 2026 07:09:51 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vtS7s-0005rb-D0; Fri, 20 Feb 2026 10:09:04 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS2F-0008Ec-IM; Fri, 20 Feb 2026 10:03:19 -0500 Received: from mail-a.sr.ht ([46.23.81.152]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS2B-0002LQ-J6; Fri, 20 Feb 2026 10:03:14 -0500 Received: from git.sr.ht (unknown [46.23.81.155]) by mail-a.sr.ht (Postfix) with ESMTPSA id 246432501E; Fri, 20 Feb 2026 15:03:08 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=y8/iG1x91AvcU0JSYGvA1Y86G6kqZ/bl4CFKG6Hl2wI=; c=simple/simple; d=git.sr.ht; h=From:Date:Subject:Reply-to:In-Reply-To:To:Cc; q=dns/txt; s=20240113; t=1771599788; v=1; b=arWagb+yHOWbYMDlxyvJ9qJzHpv2yjAarLqMTQNV0uinbHU1vw3DW0j5ep9m1q7opzgt2jdu Q9Lkg0FHdgQTA6OnCZacua01c4//F8IffH2XZohgGqHPH0GoHp6FLqY+Wf0hyXFG6VsdeleusbF Cd0eeF+8a7I8zyFj8pBURBE+p26mhTTU+7sKNhfOyoZM6IRw13EjqGU5wFlVOUoS/2LWA1wt3Uf GD1mi1RtxP2UY1le0c0Q22Q/VEMenoPLxS+Q5bO7PRcL7KOhZ8Oq7lfSdErTe7l69TYLTg6JuIi 9gfQ1B70SIFr8yUhtvy8jX95vFYgExJnGvWH5lhA0/H4Q== From: ~lexbaileylowrisc Date: Thu, 27 Apr 2023 19:45:37 +0200 Subject: [PATCH qemu 06/11] [ot] target/riscv, hw/riscv: add basic OpenTitan EarlGrey machine MIME-Version: 1.0 Message-ID: <177159976712.8279.7732381632410882915-6@git.sr.ht> X-Mailer: git.sr.ht In-Reply-To: <177159976712.8279.7732381632410882915-0@git.sr.ht> To: qemu-devel@nongnu.org Cc: Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , qemu-riscv@nongnu.org, Paolo Bonzini , =?utf-8?q?Marc-Andr=C3=A9?= Lureau , Alistair Francis , Pierrick Bouvier , "Dr. David Alan Gilbert" , Daniel =?utf-8?q?P=2E_Berrang=C3=A9?= , Philippe =?utf-8?q?Mathieu-Daud=C3=A9?= , lowRISC , nabihestefan@google.com, Amit Kumar-Hermosillo Content-Type: text/plain; charset="utf-8" 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=46.23.81.152; envelope-from=outgoing@sr.ht; helo=mail-a.sr.ht X-Spam_score_int: 17 X-Spam_score: 1.7 X-Spam_bar: + X-Spam_report: (1.7 / 5.0 requ) BAYES_00=-1.9, DATE_IN_PAST_96_XX=3.405, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Fri, 20 Feb 2026 10:09:01 -0500 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: ~lexbaileylowrisc Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1771600194156158500 From: Emmanuel Blot 1. Define a generic version of lowrisc-ibex core that can be used in severa= l machines: - leave MISA empty so that generic properties can be defined for this core - remove all arbitrary default properties but ISA I,C,U which are mandator= y for ibex - define default mtvec which is only support vectored mode - update privilege version (1.12) according to the Ibex documentation - define ibex architecture identifier - remove hart array (mostly useless, its definition is incoherent and prevent from applying properties to CPU cores) 2. Add an EarlGrey machine that uses this new definition Signed-off-by: Lo=C3=AFc Lefort Signed-off-by: Emmanuel Blot Signed-off-by: Lex Bailey --- MAINTAINERS | 7 + hw/Kconfig | 3 + hw/meson.build | 1 + hw/opentitan/Kconfig | 2 + hw/opentitan/meson.build | 2 + hw/opentitan/trace-events | 1 + hw/opentitan/trace.h | 2 + hw/riscv/Kconfig | 7 + hw/riscv/ibex_common.c | 10 +- hw/riscv/meson.build | 1 + hw/riscv/opentitan.c | 30 +- hw/riscv/ot_earlgrey.c | 734 +++++++++++++++++++++++++++++++++ include/hw/riscv/ibex_common.h | 2 +- include/hw/riscv/opentitan.h | 4 +- include/hw/riscv/ot_earlgrey.h | 27 ++ meson.build | 1 + target/riscv/cpu-qom.h | 2 + target/riscv/cpu.c | 14 +- 18 files changed, 829 insertions(+), 21 deletions(-) create mode 100644 hw/opentitan/Kconfig create mode 100644 hw/opentitan/meson.build create mode 100644 hw/opentitan/trace-events create mode 100644 hw/opentitan/trace.h create mode 100644 hw/riscv/ot_earlgrey.c create mode 100644 include/hw/riscv/ot_earlgrey.h diff --git a/MAINTAINERS b/MAINTAINERS index 8b8bb7b554..c7f98e4b61 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4460,6 +4460,13 @@ S: Supported F: hw/riscv/ibex_common.c F: include/hw/riscv/ibex_common.h F: include/hw/riscv/ibex_irq.h + +OpenTitan +M: lowRISC +S: Supported +F: hw/opentitan/* +F: include/hw/opentitan/* + Build and test automation ------------------------- Build and test automation, general continuous integration diff --git a/hw/Kconfig b/hw/Kconfig index f8f92b5d03..5215240092 100644 --- a/hw/Kconfig +++ b/hw/Kconfig @@ -69,6 +69,9 @@ source sparc64/Kconfig source tricore/Kconfig source xtensa/Kconfig =20 +# OpenTitan devices +source opentitan/Kconfig + # Symbols used by multiple targets config TEST_DEVICES bool diff --git a/hw/meson.build b/hw/meson.build index 66e46b8090..f00346854e 100644 --- a/hw/meson.build +++ b/hw/meson.build @@ -20,6 +20,7 @@ subdir('sparc') subdir('sparc64') subdir('tricore') subdir('xtensa') +subdir('opentitan') =20 subdir('9pfs') subdir('acpi') diff --git a/hw/opentitan/Kconfig b/hw/opentitan/Kconfig new file mode 100644 index 0000000000..6bd1855a84 --- /dev/null +++ b/hw/opentitan/Kconfig @@ -0,0 +1,2 @@ +# OpenTitan devices + diff --git a/hw/opentitan/meson.build b/hw/opentitan/meson.build new file mode 100644 index 0000000000..6bd1855a84 --- /dev/null +++ b/hw/opentitan/meson.build @@ -0,0 +1,2 @@ +# OpenTitan devices + diff --git a/hw/opentitan/trace-events b/hw/opentitan/trace-events new file mode 100644 index 0000000000..695debd380 --- /dev/null +++ b/hw/opentitan/trace-events @@ -0,0 +1 @@ +# OpenTitan EarlGrey Trace Events diff --git a/hw/opentitan/trace.h b/hw/opentitan/trace.h new file mode 100644 index 0000000000..17c1fd28ed --- /dev/null +++ b/hw/opentitan/trace.h @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include "trace/trace-hw_opentitan.h" diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 7877f0615c..76588c43ae 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -12,6 +12,13 @@ config IBEX_COMMON =20 # RISC-V machines in alphabetical order =20 +config OT_EARLGREY + bool + default y + select IBEX + select IBEX_COMMON + select SIFIVE_PLIC + config MICROCHIP_PFSOC bool default y diff --git a/hw/riscv/ibex_common.c b/hw/riscv/ibex_common.c index c6056767c7..6b53662a5b 100644 --- a/hw/riscv/ibex_common.c +++ b/hw/riscv/ibex_common.c @@ -17,13 +17,13 @@ #include "disas/disas.h" #include "elf.h" #include "exec/hwaddr.h" -#include "hw/boards.h" -#include "hw/loader.h" +#include "hw/core/boards.h" +#include "hw/core/loader.h" #include "hw/misc/unimp.h" -#include "hw/qdev-core.h" -#include "hw/qdev-properties.h" +#include "hw/core/qdev.h" +#include "hw/core/qdev-properties.h" #include "hw/riscv/ibex_common.h" -#include "hw/sysbus.h" +#include "hw/core/sysbus.h" #include "monitor/monitor.h" =20 =20 diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index 70d63f56b5..76dc93147a 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -4,6 +4,7 @@ riscv_ss.add(when: 'CONFIG_RISCV_NUMA', if_true: files('num= a.c')) riscv_ss.add(files('riscv_hart.c')) riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c')) riscv_ss.add(when: 'CONFIG_IBEX_COMMON', if_true: files('ibex_common.c')) +riscv_ss.add(when: 'CONFIG_OT_EARLGREY', if_true: files('ot_earlgrey.c')) riscv_ss.add(when: 'CONFIG_RISCV_VIRT', if_true: files('virt.c')) riscv_ss.add(when: 'CONFIG_SHAKTI_C', if_true: files('shakti_c.c')) riscv_ss.add(when: 'CONFIG_SIFIVE_E', if_true: files('sifive_e.c')) diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c index 19cb35b351..22f8b20f42 100644 --- a/hw/riscv/opentitan.c +++ b/hw/riscv/opentitan.c @@ -104,7 +104,9 @@ static void opentitan_machine_init(MachineState *machin= e) riscv_load_firmware(machine->firmware, &firmware_load_addr, NULL); } =20 - riscv_boot_info_init(&boot_info, &s->soc.cpus); + boot_info.kernel_size =3D 0; + boot_info.is_32bit =3D 1; + if (machine->kernel_filename) { riscv_load_kernel(machine, &boot_info, memmap[IBEX_DEV_RAM].base, @@ -119,7 +121,7 @@ static void opentitan_machine_class_init(ObjectClass *o= c, const void *data) mc->desc =3D "RISC-V Board compatible with OpenTitan"; mc->init =3D opentitan_machine_init; mc->max_cpus =3D 1; - mc->default_cpu_type =3D TYPE_RISCV_CPU_LOWRISC_IBEX; + mc->default_cpu_type =3D TYPE_RISCV_CPU_LOWRISC_OPENTITAN; mc->default_ram_id =3D "riscv.lowrisc.ibex.ram"; mc->default_ram_size =3D ibex_memmap[IBEX_DEV_RAM].size; } @@ -128,7 +130,7 @@ static void lowrisc_ibex_soc_init(Object *obj) { LowRISCIbexSoCState *s =3D RISCV_IBEX_SOC(obj); =20 - object_initialize_child(obj, "cpus", &s->cpus, TYPE_RISCV_HART_ARRAY); + object_initialize_child(obj, "cpu", &s->cpu, TYPE_RISCV_CPU_LOWRISC_OP= ENTITAN); =20 object_initialize_child(obj, "plic", &s->plic, TYPE_SIFIVE_PLIC); =20 @@ -152,13 +154,17 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev= _soc, Error **errp) MemoryRegion *sys_mem =3D get_system_memory(); int i; =20 - object_property_set_str(OBJECT(&s->cpus), "cpu-type", ms->cpu_type, - &error_abort); - object_property_set_int(OBJECT(&s->cpus), "num-harts", ms->smp.cpus, - &error_abort); - object_property_set_int(OBJECT(&s->cpus), "resetvec", s->resetvec, - &error_abort); - sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_fatal); + Object *cpu =3D OBJECT(&s->cpu); + object_property_set_int(cpu, "resetvec", s->resetvec, + &error_fatal); + object_property_set_bool(cpu, "m", true, &error_fatal); + object_property_set_bool(cpu, "pmp", true, &error_fatal); + object_property_set_bool(cpu, "zba", true, &error_fatal); + object_property_set_bool(cpu, "zbb", true, &error_fatal); + object_property_set_bool(cpu, "zbc", true, &error_fatal); + object_property_set_bool(cpu, "zbs", true, &error_fatal); + object_property_set_bool(cpu, "smepmp", true, &error_fatal); + qdev_realize(DEVICE(&s->cpu), NULL, &error_fatal); =20 /* Boot ROM */ memory_region_init_rom(&s->rom, OBJECT(dev_soc), "riscv.lowrisc.ibex.r= om", @@ -194,10 +200,10 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev= _soc, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(&s->plic), 0, memmap[IBEX_DEV_PLIC].bas= e); =20 for (i =3D 0; i < ms->smp.cpus; i++) { - CPUState *cpu =3D qemu_get_cpu(i); + CPUState *cpu_i =3D qemu_get_cpu(i); =20 qdev_connect_gpio_out(DEVICE(&s->plic), ms->smp.cpus + i, - qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT)); + qdev_get_gpio_in(DEVICE(cpu_i), IRQ_M_EXT)); } =20 /* UART */ diff --git a/hw/riscv/ot_earlgrey.c b/hw/riscv/ot_earlgrey.c new file mode 100644 index 0000000000..760a8d2c2e --- /dev/null +++ b/hw/riscv/ot_earlgrey.c @@ -0,0 +1,734 @@ +/* + * QEMU RISC-V Board Compatible with OpenTitan EarlGrey FPGA platform + * + * Copyright (c) 2022-2023 Rivos, Inc. + * + * Author(s): + * Emmanuel Blot + * Lo=C3=AFc Lefort + * + * This implementation is based on OpenTitan RTL version: + * + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + */ + +#include "qemu/osdep.h" +#include "qemu/cutils.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "cpu.h" +#include "system/address-spaces.h" +#include "hw/core/boards.h" +#include "hw/intc/sifive_plic.h" +#include "hw/misc/unimp.h" +#include "hw/core/qdev-properties.h" +#include "hw/riscv/ibex_common.h" +#include "hw/riscv/ot_earlgrey.h" +#include "system/system.h" + +/* -----------------------------------------------------------------------= - */ +/* Constants */ +/* -----------------------------------------------------------------------= - */ + +#define OT_EARLGREY_PERIPHERAL_CLK_HZ 2500000u + +enum OtEarlgreySocMemory { + OT_EARLGREY_SOC_MEM_ROM, + OT_EARLGREY_SOC_MEM_RAM, + OT_EARLGREY_SOC_MEM_FLASH, +}; + +static const MemMapEntry ot_earlgrey_soc_memories[] =3D { + [OT_EARLGREY_SOC_MEM_ROM] =3D { 0x00008000u, 0x8000u }, + [OT_EARLGREY_SOC_MEM_RAM] =3D { 0x10000000u, 0x20000u }, + [OT_EARLGREY_SOC_MEM_FLASH] =3D { 0x20000000u, 0x100000u }, +}; + +enum OtEarlgreySocDevice { + OT_EARLGREY_SOC_DEV_ADC_CTRL, + OT_EARLGREY_SOC_DEV_AES, + OT_EARLGREY_SOC_DEV_ALERT_HANDLER, + OT_EARLGREY_SOC_DEV_AON_TIMER, + OT_EARLGREY_SOC_DEV_AST, + OT_EARLGREY_SOC_DEV_CLKMGR, + OT_EARLGREY_SOC_DEV_CSRNG, + OT_EARLGREY_SOC_DEV_EDN0, + OT_EARLGREY_SOC_DEV_EDN1, + OT_EARLGREY_SOC_DEV_ENTROPY_SRC, + OT_EARLGREY_SOC_DEV_FLASH_CTRL, + OT_EARLGREY_SOC_DEV_FLASH_CTRL_PRIM, + OT_EARLGREY_SOC_DEV_GPIO, + OT_EARLGREY_SOC_DEV_HART, + OT_EARLGREY_SOC_DEV_HMAC, + OT_EARLGREY_SOC_DEV_I2C0, + OT_EARLGREY_SOC_DEV_I2C1, + OT_EARLGREY_SOC_DEV_I2C2, + OT_EARLGREY_SOC_DEV_IBEX_WRAPPER, + OT_EARLGREY_SOC_DEV_KEYMGR, + OT_EARLGREY_SOC_DEV_KMAC, + OT_EARLGREY_SOC_DEV_LC_CTRL, + OT_EARLGREY_SOC_DEV_OTBN, + OT_EARLGREY_SOC_DEV_OTP_CTRL, + OT_EARLGREY_SOC_DEV_OTP_CTRL_PRIM, + OT_EARLGREY_SOC_DEV_PATTGEN, + OT_EARLGREY_SOC_DEV_PINMUX, + OT_EARLGREY_SOC_DEV_PLIC, + OT_EARLGREY_SOC_DEV_PWM, + OT_EARLGREY_SOC_DEV_PWRMGR, + OT_EARLGREY_SOC_DEV_RAM_RET, + OT_EARLGREY_SOC_DEV_ROM_CTRL, + OT_EARLGREY_SOC_DEV_RSTMGR, + OT_EARLGREY_SOC_DEV_RV_DM, + OT_EARLGREY_SOC_DEV_RV_DM_MEM, + OT_EARLGREY_SOC_DEV_SENSOR_CTRL, + OT_EARLGREY_SOC_DEV_SPI_DEVICE, + OT_EARLGREY_SOC_DEV_SPI_HOST0, + OT_EARLGREY_SOC_DEV_SPI_HOST1, + OT_EARLGREY_SOC_DEV_SRAM_CTRL, + OT_EARLGREY_SOC_DEV_SRAM_CTRL_MAIN, + OT_EARLGREY_SOC_DEV_SYSRST_CTRL, + OT_EARLGREY_SOC_DEV_TIMER, + OT_EARLGREY_SOC_DEV_UART0, + OT_EARLGREY_SOC_DEV_UART1, + OT_EARLGREY_SOC_DEV_UART2, + OT_EARLGREY_SOC_DEV_UART3, + OT_EARLGREY_SOC_DEV_USBDEV, +}; + +#define OT_EARLGREY_SOC_GPIO(_irq_, _target_, _num_) \ + IBEX_GPIO(_irq_, OT_EARLGREY_SOC_DEV_##_target_, _num_) + +#define OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(_irq_, _target_, _num_) \ + IBEX_GPIO_SYSBUS_IRQ(_irq_, OT_EARLGREY_SOC_DEV_##_target_, _num_) + +#define OT_EARLGREY_SOC_DEVLINK(_pname_, _target_) \ + IBEX_DEVLINK(_pname_, OT_EARLGREY_SOC_DEV_##_target_) + +/* + * MMIO/interrupt mapping as per: + * lowRISC/opentitan: hw/top_earlgrey/sw/autogen/top_earlgrey_memory.h + * and + * lowRISC/opentitan: hw/top_earlgrey/sw/autogen/top_earlgrey.h + */ +static const IbexDeviceDef ot_earlgrey_soc_devices[] =3D { + /* clang-format off */ + [OT_EARLGREY_SOC_DEV_HART] =3D { + .type =3D TYPE_RISCV_CPU_LOWRISC_OPENTITAN, + .prop =3D IBEXDEVICEPROPDEFS( + IBEX_DEV_BOOL_PROP("zba", true), + IBEX_DEV_BOOL_PROP("zbb", true), + IBEX_DEV_BOOL_PROP("zbc", true), + IBEX_DEV_BOOL_PROP("zbs", true), + IBEX_DEV_BOOL_PROP("smepmp", true) + ), + }, + [OT_EARLGREY_SOC_DEV_RV_DM_MEM] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-rv_dm_mem", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x00010000u, 0x1000u } + ), + }, + [OT_EARLGREY_SOC_DEV_UART0] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-uart", + .cfg =3D &ibex_unimp_configure, + .instance =3D 0, + .memmap =3D MEMMAPENTRIES( + { 0x40000000u, 0x40u } + ), + }, + [OT_EARLGREY_SOC_DEV_UART1] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-uart", + .cfg =3D &ibex_unimp_configure, + .instance =3D 1, + .memmap =3D MEMMAPENTRIES( + { 0x40010000u, 0x40u } + ), + }, + [OT_EARLGREY_SOC_DEV_UART2] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-uart", + .cfg =3D &ibex_unimp_configure, + .instance =3D 2, + .memmap =3D MEMMAPENTRIES( + { 0x40020000u, 0x40u } + ), + }, + [OT_EARLGREY_SOC_DEV_UART3] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-uart", + .cfg =3D &ibex_unimp_configure, + .instance =3D 3, + .memmap =3D MEMMAPENTRIES( + { 0x40030000u, 0x1000u } + ), + }, + [OT_EARLGREY_SOC_DEV_GPIO] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-gpio", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40040000u, 0x40u } + ), + }, + [OT_EARLGREY_SOC_DEV_SPI_DEVICE] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-spi_device", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40050000u, 0x2000u } + ), + }, + [OT_EARLGREY_SOC_DEV_I2C0] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-i2c", + .cfg =3D &ibex_unimp_configure, + .instance =3D 0, + .memmap =3D MEMMAPENTRIES( + { 0x40080000u, 0x80u } + ), + }, + [OT_EARLGREY_SOC_DEV_I2C1] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-i2c", + .cfg =3D &ibex_unimp_configure, + .instance =3D 1, + .memmap =3D MEMMAPENTRIES( + { 0x40090000u, 0x80u } + ), + }, + [OT_EARLGREY_SOC_DEV_I2C2] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-i2c", + .cfg =3D &ibex_unimp_configure, + .instance =3D 2, + .memmap =3D MEMMAPENTRIES( + { 0x400a0000u, 0x80u } + ), + }, + [OT_EARLGREY_SOC_DEV_PATTGEN] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-pattgen", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x400e0000u, 0x40u } + ), + }, + [OT_EARLGREY_SOC_DEV_TIMER] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-timer", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40100000u, 0x200u } + ), + }, + [OT_EARLGREY_SOC_DEV_OTP_CTRL] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-otp_ctrl", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40130000u, 0x2000u } + ), + }, + [OT_EARLGREY_SOC_DEV_OTP_CTRL_PRIM] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-ot_ctrl_prim", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40132000u, 0x20u } + ), + }, + [OT_EARLGREY_SOC_DEV_LC_CTRL] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-lc_ctrl", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40140000u, 0x100u } + ), + }, + [OT_EARLGREY_SOC_DEV_ALERT_HANDLER] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-alert_handler", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40150000u, 0x800u } + ), + }, + [OT_EARLGREY_SOC_DEV_SPI_HOST0] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-spi_host", + .cfg =3D &ibex_unimp_configure, + .instance =3D 0, + .memmap =3D MEMMAPENTRIES( + { 0x40300000u, 0x40u } + ), + }, + [OT_EARLGREY_SOC_DEV_SPI_HOST1] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-spi_host", + .cfg =3D &ibex_unimp_configure, + .instance =3D 1, + .memmap =3D MEMMAPENTRIES( + { 0x40310000u, 0x40u } + ), + }, + [OT_EARLGREY_SOC_DEV_USBDEV] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-usbdev", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40320000u, 0x1000u } + ), + }, + [OT_EARLGREY_SOC_DEV_PWRMGR] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-pwrmgr", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40400000u, 0x80u } + ), + }, + [OT_EARLGREY_SOC_DEV_RSTMGR] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-rstmgr", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40410000u, 0x80u } + ), + }, + [OT_EARLGREY_SOC_DEV_CLKMGR] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-clkmgr", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40420000u, 0x80u } + ), + }, + [OT_EARLGREY_SOC_DEV_SYSRST_CTRL] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-sysrst_ctrl", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40430000u, 0x100u } + ), + }, + [OT_EARLGREY_SOC_DEV_ADC_CTRL] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-adc_ctrl", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40440000u, 0x80u } + ), + }, + [OT_EARLGREY_SOC_DEV_PWM] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-pwm", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40450000u, 0x80u } + ), + }, + [OT_EARLGREY_SOC_DEV_PINMUX] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-pinmux", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40460000u, 0x1000u } + ), + }, + [OT_EARLGREY_SOC_DEV_AON_TIMER] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-aon_timer", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40470000u, 0x40u } + ), + }, + [OT_EARLGREY_SOC_DEV_AST] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-ast", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40480000u, 0x400u } + ), + }, + [OT_EARLGREY_SOC_DEV_SENSOR_CTRL] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-sensor_ctrl", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40490000u, 0x40u } + ), + }, + [OT_EARLGREY_SOC_DEV_SRAM_CTRL] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-sram_ctrl", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40500000u, 0x20u } + ), + }, + [OT_EARLGREY_SOC_DEV_RAM_RET] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-ram_ret", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x40600000u, 0x1000u } + ), + }, + [OT_EARLGREY_SOC_DEV_FLASH_CTRL] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-flash_ctrl", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x41000000u, 0x200u } + ), + }, + [OT_EARLGREY_SOC_DEV_FLASH_CTRL_PRIM] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-flash_ctrl_prim", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x41008000u, 0x80u } + ), + }, + [OT_EARLGREY_SOC_DEV_AES] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-aes", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x41100000u, 0x100u } + ), + }, + [OT_EARLGREY_SOC_DEV_HMAC] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-hmac", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x41110000u, 0x1000u } + ), + }, + [OT_EARLGREY_SOC_DEV_KMAC] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-kmac", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x41120000u, 0x1000u } + ), + }, + [OT_EARLGREY_SOC_DEV_OTBN] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-otbn", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x41130000u, 0x10000u } + ), + }, + [OT_EARLGREY_SOC_DEV_KEYMGR] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-keymgr", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x41140000u, 0x100u } + ), + }, + [OT_EARLGREY_SOC_DEV_CSRNG] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-csrng", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x41150000u, 0x80u } + ), + }, + [OT_EARLGREY_SOC_DEV_ENTROPY_SRC] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-entropy_src", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x41160000u, 0x100u } + ), + }, + [OT_EARLGREY_SOC_DEV_EDN0] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-edn", + .cfg =3D &ibex_unimp_configure, + .instance =3D 0, + .memmap =3D MEMMAPENTRIES( + { 0x41170000u, 0x80u } + ), + }, + [OT_EARLGREY_SOC_DEV_EDN1] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-edn", + .cfg =3D &ibex_unimp_configure, + .instance =3D 1, + .memmap =3D MEMMAPENTRIES( + { 0x41180000u, 0x80u } + ), + }, + [OT_EARLGREY_SOC_DEV_SRAM_CTRL_MAIN] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-sram_ctrl_main", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x411c0000u, 0x20u } + ), + }, + [OT_EARLGREY_SOC_DEV_ROM_CTRL] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-rom_ctrl", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x411e0000u, 0x80u } + ), + }, + [OT_EARLGREY_SOC_DEV_IBEX_WRAPPER] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-ibex_wrapper", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x411f0000u, 0x100u } + ), + }, + [OT_EARLGREY_SOC_DEV_RV_DM] =3D { + .type =3D TYPE_UNIMPLEMENTED_DEVICE, + .name =3D "ot-rv_dm", + .cfg =3D &ibex_unimp_configure, + .memmap =3D MEMMAPENTRIES( + { 0x41200000u, 0x4u } + ), + }, + [OT_EARLGREY_SOC_DEV_PLIC] =3D { + .type =3D TYPE_SIFIVE_PLIC, + .memmap =3D MEMMAPENTRIES( + { 0x48000000u, 0x8000000u } + ), + .gpio =3D IBEXGPIOCONNDEFS( + OT_EARLGREY_SOC_GPIO(1, HART, IRQ_M_EXT) + ), + .prop =3D IBEXDEVICEPROPDEFS( + IBEX_DEV_STRING_PROP("hart-config", "M"), + IBEX_DEV_UINT_PROP("hartid-base", 0u), + /* note: should always be max_irq + 1 */ + IBEX_DEV_UINT_PROP("num-sources", 185u), + IBEX_DEV_UINT_PROP("num-priorities", 3u), + IBEX_DEV_UINT_PROP("priority-base", 0x0u), + IBEX_DEV_UINT_PROP("pending-base", 0x1000u), + IBEX_DEV_UINT_PROP("enable-base", 0x2000u), + IBEX_DEV_UINT_PROP("enable-stride", 32u), + IBEX_DEV_UINT_PROP("context-base", 0x200000u), + IBEX_DEV_UINT_PROP("context-stride", 8u), + IBEX_DEV_UINT_PROP("aperture-size", 0x8000000u) + ), + }, + /* clang-format on */ +}; + +enum OtEarlgreyBoardDevice { + OT_EARLGREY_BOARD_DEV_SOC, + _OT_EARLGREY_BOARD_DEV_COUNT, +}; + +/* -----------------------------------------------------------------------= - */ +/* Type definitions */ +/* -----------------------------------------------------------------------= - */ + +struct OtEarlGreySoCState { + SysBusDevice parent_obj; + + DeviceState **devices; + MemoryRegion *memories; +}; + +struct OtEarlGreyBoardState { + DeviceState parent_obj; + + DeviceState **devices; +}; + +struct OtEarlGreyMachineState { + MachineState parent_obj; +}; + +/* -----------------------------------------------------------------------= - */ +/* SoC */ +/* -----------------------------------------------------------------------= - */ + +static void ot_earlgrey_soc_reset(DeviceState *dev) +{ + OtEarlGreySoCState *s =3D RISCV_OT_EARLGREY_SOC(dev); + + cpu_reset(CPU(s->devices[OT_EARLGREY_SOC_DEV_HART])); +} + +static void ot_earlgrey_soc_realize(DeviceState *dev, Error **errp) +{ + OtEarlGreySoCState *s =3D RISCV_OT_EARLGREY_SOC(dev); + const MemMapEntry *memmap =3D &ot_earlgrey_soc_memories[0]; + + MachineState *ms =3D MACHINE(qdev_get_machine()); + MemoryRegion *sys_mem =3D get_system_memory(); + + /* RAM */ + memory_region_add_subregion(sys_mem, memmap[OT_EARLGREY_SOC_MEM_RAM].b= ase, + ms->ram); + + /* Boot ROM */ + memory_region_init_rom(&s->memories[OT_EARLGREY_SOC_MEM_ROM], OBJECT(d= ev), + "ot-rom", memmap[OT_EARLGREY_SOC_MEM_ROM].size, + &error_fatal); + memory_region_add_subregion(sys_mem, memmap[OT_EARLGREY_SOC_MEM_ROM].b= ase, + &s->memories[OT_EARLGREY_SOC_MEM_ROM]); + + /* Flash memory */ + memory_region_init_rom(&s->memories[OT_EARLGREY_SOC_MEM_FLASH], OBJECT= (dev), + "ot-flash", memmap[OT_EARLGREY_SOC_MEM_FLASH].s= ize, + &error_fatal); + memory_region_add_subregion(sys_mem, memmap[OT_EARLGREY_SOC_MEM_FLASH]= .base, + &s->memories[OT_EARLGREY_SOC_MEM_FLASH]); + + /* Link, define properties and realize devices, then connect GPIOs */ + ibex_link_devices(s->devices, ot_earlgrey_soc_devices, + ARRAY_SIZE(ot_earlgrey_soc_devices)); + ibex_define_device_props(s->devices, ot_earlgrey_soc_devices, + ARRAY_SIZE(ot_earlgrey_soc_devices)); + ibex_realize_system_devices(s->devices, ot_earlgrey_soc_devices, + ARRAY_SIZE(ot_earlgrey_soc_devices)); + ibex_connect_devices(s->devices, ot_earlgrey_soc_devices, + ARRAY_SIZE(ot_earlgrey_soc_devices)); + + /* load kernel if provided */ + ibex_load_kernel(NULL); +} + +static void ot_earlgrey_soc_init(Object *obj) +{ + OtEarlGreySoCState *s =3D RISCV_OT_EARLGREY_SOC(obj); + + s->devices =3D + ibex_create_devices(ot_earlgrey_soc_devices, + ARRAY_SIZE(ot_earlgrey_soc_devices), DEVICE(s)= ); + s->memories =3D g_new0(MemoryRegion, ARRAY_SIZE(ot_earlgrey_soc_memori= es)); +} + +static void ot_earlgrey_soc_class_init(ObjectClass *oc, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(oc); + + dc->legacy_reset =3D &ot_earlgrey_soc_reset; + dc->realize =3D &ot_earlgrey_soc_realize; + dc->user_creatable =3D false; +} + +static const TypeInfo ot_earlgrey_soc_type_info =3D { + .name =3D TYPE_RISCV_OT_EARLGREY_SOC, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(OtEarlGreySoCState), + .instance_init =3D &ot_earlgrey_soc_init, + .class_init =3D &ot_earlgrey_soc_class_init, +}; + +static void ot_earlgrey_soc_register_types(void) +{ + type_register_static(&ot_earlgrey_soc_type_info); +} + +type_init(ot_earlgrey_soc_register_types); + +/* -----------------------------------------------------------------------= - */ +/* Board */ +/* -----------------------------------------------------------------------= - */ + +static void ot_earlgrey_board_realize(DeviceState *dev, Error **errp) +{ + OtEarlGreyBoardState *board =3D RISCV_OT_EARLGREY_BOARD(dev); + + DeviceState *soc =3D board->devices[OT_EARLGREY_BOARD_DEV_SOC]; + object_property_add_child(OBJECT(board), "soc", OBJECT(soc)); + sysbus_realize_and_unref(SYS_BUS_DEVICE(soc), &error_fatal); +} + +static void ot_earlgrey_board_init(Object *obj) +{ + OtEarlGreyBoardState *s =3D RISCV_OT_EARLGREY_BOARD(obj); + + s->devices =3D g_new0(DeviceState *, _OT_EARLGREY_BOARD_DEV_COUNT); + s->devices[OT_EARLGREY_BOARD_DEV_SOC] =3D + qdev_new(TYPE_RISCV_OT_EARLGREY_SOC); +} + +static void ot_earlgrey_board_class_init(ObjectClass *oc, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(oc); + + dc->realize =3D &ot_earlgrey_board_realize; +} + +static const TypeInfo ot_earlgrey_board_type_info =3D { + .name =3D TYPE_RISCV_OT_EARLGREY_BOARD, + .parent =3D TYPE_DEVICE, + .instance_size =3D sizeof(OtEarlGreyBoardState), + .instance_init =3D &ot_earlgrey_board_init, + .class_init =3D &ot_earlgrey_board_class_init, +}; + +static void ot_earlgrey_board_register_types(void) +{ + type_register_static(&ot_earlgrey_board_type_info); +} + +type_init(ot_earlgrey_board_register_types); + +/* -----------------------------------------------------------------------= - */ +/* Machine */ +/* -----------------------------------------------------------------------= - */ + +static void ot_earlgrey_machine_instance_init(Object *obj) +{ + OtEarlGreyMachineState *s =3D RISCV_OT_EARLGREY_MACHINE(obj); + + /* nothing here */ + (void)s; +} + +static void ot_earlgrey_machine_init(MachineState *state) +{ + DeviceState *dev =3D qdev_new(TYPE_RISCV_OT_EARLGREY_BOARD); + + object_property_add_child(OBJECT(state), "board", OBJECT(dev)); + qdev_realize(dev, NULL, &error_fatal); +} + +static void ot_earlgrey_machine_class_init(ObjectClass *oc, const void *da= ta) +{ + MachineClass *mc =3D MACHINE_CLASS(oc); + + mc->desc =3D "RISC-V Board compatible with OpenTitan EarlGrey FPGA pla= tform"; + mc->init =3D ot_earlgrey_machine_init; + mc->max_cpus =3D 1u; + mc->default_cpu_type =3D + ot_earlgrey_soc_devices[OT_EARLGREY_SOC_DEV_HART].type; + mc->default_ram_id =3D "ot-ram"; + mc->default_ram_size =3D + ot_earlgrey_soc_memories[OT_EARLGREY_SOC_MEM_RAM].size; +} + +static const TypeInfo ot_earlgrey_machine_type_info =3D { + .name =3D TYPE_RISCV_OT_EARLGREY_MACHINE, + .parent =3D TYPE_MACHINE, + .instance_size =3D sizeof(OtEarlGreyMachineState), + .instance_init =3D &ot_earlgrey_machine_instance_init, + .class_init =3D &ot_earlgrey_machine_class_init, +}; + +static void ot_earlgrey_machine_register_types(void) +{ + type_register_static(&ot_earlgrey_machine_type_info); +} + +type_init(ot_earlgrey_machine_register_types); diff --git a/include/hw/riscv/ibex_common.h b/include/hw/riscv/ibex_common.h index 6c7dae5cbe..963ab1fa78 100644 --- a/include/hw/riscv/ibex_common.h +++ b/include/hw/riscv/ibex_common.h @@ -16,7 +16,7 @@ #include "qemu/osdep.h" #include "qom/object.h" #include "exec/hwaddr.h" -#include "hw/qdev-core.h" +#include "hw/core/qdev.h" =20 =20 /* -----------------------------------------------------------------------= - */ diff --git a/include/hw/riscv/opentitan.h b/include/hw/riscv/opentitan.h index 5b9016e1d8..0da19c671f 100644 --- a/include/hw/riscv/opentitan.h +++ b/include/hw/riscv/opentitan.h @@ -19,13 +19,13 @@ #ifndef HW_OPENTITAN_H #define HW_OPENTITAN_H =20 -#include "hw/riscv/riscv_hart.h" #include "hw/intc/sifive_plic.h" #include "hw/char/ibex_uart.h" #include "hw/timer/ibex_timer.h" #include "hw/ssi/ibex_spi_host.h" #include "hw/core/boards.h" #include "qom/object.h" +#include "target/riscv/cpu.h" =20 #define TYPE_RISCV_IBEX_SOC "riscv.lowrisc.ibex.soc" OBJECT_DECLARE_SIMPLE_TYPE(LowRISCIbexSoCState, RISCV_IBEX_SOC) @@ -41,7 +41,7 @@ struct LowRISCIbexSoCState { SysBusDevice parent_obj; =20 /*< public >*/ - RISCVHartArrayState cpus; + RISCVCPU cpu; SiFivePLICState plic; IbexUartState uart; IbexTimerState timer; diff --git a/include/hw/riscv/ot_earlgrey.h b/include/hw/riscv/ot_earlgrey.h new file mode 100644 index 0000000000..650f53a9dd --- /dev/null +++ b/include/hw/riscv/ot_earlgrey.h @@ -0,0 +1,27 @@ +/* + * QEMU RISC-V Board Compatible with OpenTitan EarlGrey FPGA platform + * + * Copyright (c) 2022-2023 Rivos, Inc. + * + * Author(s): + * Lo=C3=AFc Lefort + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + */ + +#ifndef HW_RISCV_OT_EARLGREY_H +#define HW_RISCV_OT_EARLGREY_H + +#include "qom/object.h" + +#define TYPE_RISCV_OT_EARLGREY_MACHINE MACHINE_TYPE_NAME("ot-earlgrey") +OBJECT_DECLARE_SIMPLE_TYPE(OtEarlGreyMachineState, RISCV_OT_EARLGREY_MACHI= NE) + +#define TYPE_RISCV_OT_EARLGREY_BOARD "riscv.ot_earlgrey.board" +OBJECT_DECLARE_SIMPLE_TYPE(OtEarlGreyBoardState, RISCV_OT_EARLGREY_BOARD) + +#define TYPE_RISCV_OT_EARLGREY_SOC "riscv.ot_earlgrey.soc" +OBJECT_DECLARE_SIMPLE_TYPE(OtEarlGreySoCState, RISCV_OT_EARLGREY_SOC) + +#endif /* HW_RISCV_OT_EARLGREY_H */ diff --git a/meson.build b/meson.build index 4af32c3e1f..55a85ec895 100644 --- a/meson.build +++ b/meson.build @@ -3626,6 +3626,7 @@ if have_system 'hw/nubus', 'hw/nvme', 'hw/nvram', + 'hw/opentitan', 'hw/pci', 'hw/pci-host', 'hw/ppc', diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index 3a6394fd11..418b56d69e 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -43,6 +43,8 @@ #define TYPE_RISCV_CPU_RVA23U64 RISCV_CPU_TYPE_NAME("rva23u64") #define TYPE_RISCV_CPU_RVA23S64 RISCV_CPU_TYPE_NAME("rva23s64") #define TYPE_RISCV_CPU_LOWRISC_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex") +#define TYPE_RISCV_CPU_LOWRISC_OPENTITAN \ + RISCV_CPU_TYPE_NAME("lowrisc-opentitan") #define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c") #define TYPE_RISCV_CPU_SIFIVE_E RISCV_CPU_TYPE_NAME("sifive-e") #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31") diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index dd30b21dd2..507061e8e9 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -3043,13 +3043,25 @@ static const TypeInfo riscv_cpu_type_infos[] =3D { .misa_mxl_max =3D MXL_RV32, ), =20 - DEFINE_RISCV_CPU(TYPE_RISCV_CPU_LOWRISC_IBEX, TYPE_RISCV_VENDOR_CPU, + + DEFINE_ABSTRACT_RISCV_CPU(TYPE_RISCV_CPU_LOWRISC_IBEX, + TYPE_RISCV_VENDOR_CPU, .misa_mxl_max =3D MXL_RV32, .misa_ext =3D RVI | RVM | RVC | RVU, .priv_spec =3D PRIV_VERSION_1_12_0, .cfg.max_satp_mode =3D VM_1_10_MBARE, .cfg.ext_zifencei =3D true, .cfg.ext_zicsr =3D true, + + .cfg.marchid =3D 0x16u, + +#ifndef CONFIG_USER_ONLY + .custom_csrs =3D ibex_csr_list, +#endif + ), + + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_LOWRISC_OPENTITAN, + TYPE_RISCV_CPU_LOWRISC_IBEX, .cfg.pmp =3D true, .cfg.ext_smepmp =3D true, =20 --=20 2.49.1 From nobody Sun Apr 12 00:57:42 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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; dmarc=fail(p=none dis=none) header.from=git.sr.ht Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 177160020215126.60061338917933; Fri, 20 Feb 2026 07:10:02 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vtS7u-0005su-Lm; Fri, 20 Feb 2026 10:09:06 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS2D-0008Dc-FQ; Fri, 20 Feb 2026 10:03:17 -0500 Received: from mail-a.sr.ht ([46.23.81.152]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS2B-0002LT-PF; Fri, 20 Feb 2026 10:03:13 -0500 Received: from git.sr.ht (unknown [46.23.81.155]) by mail-a.sr.ht (Postfix) with ESMTPSA id 3A0B02501F; Fri, 20 Feb 2026 15:03:10 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=WKnV4L7hUXk8QTYKS6WtDPUEwgGmDE9P4skYagYcYNs=; c=simple/simple; d=git.sr.ht; h=From:Date:Subject:Reply-to:In-Reply-To:To:Cc; q=dns/txt; s=20240113; t=1771599790; v=1; b=i+L5vdOuOPsfiqcDqkyD2xWQT2jrfYmRyQWPKoFuafSG+V0HJp8g0XNjoVpBHS+D7Tu9zQUO MiwSD3V807NbJfqPeZv+F/2uFu64/8b/5ElcmJZi3+Twio8huxohIc63Zbz4wf9x466g5n/ZD+A 3meW5mJLZR/X89fFM6OXaLeKmhK3n7bfnMnDQ5ivOJXmXhl2A6toNbwxuC3hYxQH1WeKkrYUJ+w x+rKtGLYew05Kmp9THOxOGeuClvoZlm1wwDnIrVk4/MRTOIgNwA1PMXmUVVupBGr+uWKJHiXMHL Pqt7Wvf5X521KlvyRPT6fnrjLd+BBJrEbhO7Pf49OldLQ== From: ~lexbaileylowrisc Date: Wed, 15 Feb 2023 18:17:31 +0100 Subject: [PATCH qemu 07/11] [ot] target/riscv: add support for impl-defined initial PMP config Message-ID: <177159976712.8279.7732381632410882915-7@git.sr.ht> X-Mailer: git.sr.ht In-Reply-To: <177159976712.8279.7732381632410882915-0@git.sr.ht> To: qemu-devel@nongnu.org Cc: Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , qemu-riscv@nongnu.org, Paolo Bonzini , =?utf-8?q?Marc-Andr=C3=A9?= Lureau , Alistair Francis , Pierrick Bouvier , "Dr. David Alan Gilbert" , Daniel =?utf-8?q?P=2E_Berrang=C3=A9?= , Philippe =?utf-8?q?Mathieu-Daud=C3=A9?= , lowRISC , nabihestefan@google.com, Amit Kumar-Hermosillo Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 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=46.23.81.152; envelope-from=outgoing@sr.ht; helo=mail-a.sr.ht X-Spam_score_int: 17 X-Spam_score: 1.7 X-Spam_bar: + X-Spam_report: (1.7 / 5.0 requ) BAYES_00=-1.9, DATE_IN_PAST_96_XX=3.405, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Fri, 20 Feb 2026 10:09:01 -0500 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: ~lexbaileylowrisc Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1771600203914158500 From: Emmanuel Blot Signed-off-by: Emmanuel Blot --- target/riscv/cpu.c | 24 ++++++++++++++++++++++++ target/riscv/cpu_cfg_fields.h.inc | 7 +++++++ 2 files changed, 31 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 507061e8e9..73aae7fd14 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -792,6 +792,25 @@ static void riscv_cpu_reset_hold(Object *obj, ResetTyp= e type) if (kvm_enabled()) { kvm_riscv_reset_vcpu(cpu); } + + /* default physical memory protection configuration */ + const RISCVCPUConfig *cfg =3D &cpu->cfg; + g_assert(cfg->pmp_cfg_count <=3D MAX_RISCV_PMPS); + g_assert(cfg->pmp_addr_count <=3D MAX_RISCV_PMPS); + for (i =3D 0; i < MAX_RISCV_PMPS; i++) { + env->pmp_state.pmp[i].cfg_reg =3D + i < cfg->pmp_cfg_count ? cfg->pmp_cfg[i] : 0; + } + for (i =3D 0; i < MAX_RISCV_PMPS; i++) { + env->pmp_state.pmp[i].addr_reg =3D + i < cfg->pmp_addr_count ? (target_ulong)cfg->pmp_addr[i] : 0; + } + for (i =3D 0; i < MAX_RISCV_PMPS; i++) { + pmp_update_rule_addr(env, i); + } + pmp_update_rule_nums(env); + + env->mseccfg =3D (target_ulong)cfg->mseccfg; #endif } =20 @@ -2670,6 +2689,11 @@ static const Property riscv_cpu_properties[] =3D { DEFAULT_RNMI_IRQVEC), DEFINE_PROP_UINT64("rnmi-exception-vector", RISCVCPU, env.rnmi_excpvec, DEFAULT_RNMI_EXCPVEC), + DEFINE_PROP_UINT64("mseccfg", RISCVCPU, cfg.mseccfg, 0u), + DEFINE_PROP_ARRAY("pmp_cfg", RISCVCPU, cfg.pmp_cfg_count, cfg.pmp_cfg, + qdev_prop_uint8, uint8_t), + DEFINE_PROP_ARRAY("pmp_addr", RISCVCPU, cfg.pmp_addr_count, cfg.pmp_ad= dr, + qdev_prop_uint64, uint64_t), #endif =20 DEFINE_PROP_BOOL("short-isa-string", RISCVCPU, cfg.short_isa_string, f= alse), diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_field= s.h.inc index 70ec650abf..39ca957aa6 100644 --- a/target/riscv/cpu_cfg_fields.h.inc +++ b/target/riscv/cpu_cfg_fields.h.inc @@ -176,5 +176,12 @@ TYPED_FIELD(uint32_t, pmp_granularity, 0) =20 TYPED_FIELD(int8_t, max_satp_mode, -1) =20 +/* physical memory protection HW configuration */ +TYPED_FIELD(uint8_t *, pmp_cfg, 0) +TYPED_FIELD(uint32_t, pmp_cfg_count, 0) +TYPED_FIELD(uint64_t *, pmp_addr, 0) +TYPED_FIELD(uint32_t, pmp_addr_count, 0) +TYPED_FIELD(uint64_t, mseccfg, 0) + #undef BOOL_FIELD #undef TYPED_FIELD --=20 2.49.1 From nobody Sun Apr 12 00:57:42 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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; dmarc=fail(p=none dis=none) header.from=git.sr.ht Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1771600238184445.8270759995927; Fri, 20 Feb 2026 07:10:38 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vtS7t-0005rj-C4; Fri, 20 Feb 2026 10:09:05 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS2E-0008Dn-8e; Fri, 20 Feb 2026 10:03:17 -0500 Received: from mail-a.sr.ht ([46.23.81.152]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS2C-0002Lf-9e; Fri, 20 Feb 2026 10:03:13 -0500 Received: from git.sr.ht (unknown [46.23.81.155]) by mail-a.sr.ht (Postfix) with ESMTPSA id 516F525020; Fri, 20 Feb 2026 15:03:10 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=nA/pvhoKhGArAZpnZD0U0/Br7wO+8lIKMpEBB8d6hnc=; c=simple/simple; d=git.sr.ht; h=From:Date:Subject:Reply-to:In-Reply-To:To:Cc; q=dns/txt; s=20240113; t=1771599790; v=1; b=bJsCkyWjpjtN6M8tEuFr3Qi2rXfVg5rajx/nLmyLN/xh9ZXU5ZsMi9TE4TB4uMHnl+0eDIpV ihBFJMIri3cTmjImaimylZSLOTDHFsxmAvyHvtUMOripY+Wz2xVF6iUs/kr/5Vc+OzhWWEo+X9t lvlD2NOsMPmtHDYWw1TiiIbPCtanT3i3MeXxD6BlcAy6X7wuGqOo4jdDW/BxbeBCh7FiHc0+AyO LWXKaQnNhWBc//W3aCq1LESk2MtjRfDWQEgBibFzJwsxLcfyPixOMLBO8w0bAZu5Jme+AtAP0D6 jBic2flmJYzvbhNRD7DLSAzGs9LRyF/mf1RtUw0ncOWfA== From: ~lexbaileylowrisc Date: Wed, 15 Feb 2023 18:18:54 +0100 Subject: [PATCH qemu 08/11] [ot] hw/riscv: ot_earlgrey: add HW PMP configuration MIME-Version: 1.0 Message-ID: <177159976712.8279.7732381632410882915-8@git.sr.ht> X-Mailer: git.sr.ht In-Reply-To: <177159976712.8279.7732381632410882915-0@git.sr.ht> To: qemu-devel@nongnu.org Cc: Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , qemu-riscv@nongnu.org, Paolo Bonzini , =?utf-8?q?Marc-Andr=C3=A9?= Lureau , Alistair Francis , Pierrick Bouvier , "Dr. David Alan Gilbert" , Daniel =?utf-8?q?P=2E_Berrang=C3=A9?= , Philippe =?utf-8?q?Mathieu-Daud=C3=A9?= , lowRISC , nabihestefan@google.com, Amit Kumar-Hermosillo Content-Type: text/plain; charset="utf-8" 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=46.23.81.152; envelope-from=outgoing@sr.ht; helo=mail-a.sr.ht X-Spam_score_int: 17 X-Spam_score: 1.7 X-Spam_bar: + X-Spam_report: (1.7 / 5.0 requ) BAYES_00=-1.9, DATE_IN_PAST_96_XX=3.405, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Fri, 20 Feb 2026 10:09:01 -0500 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: ~lexbaileylowrisc Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1771600240172158500 From: Emmanuel Blot also adds property no_epmp_cfg on EarlGrey machine to disable default ePMP configuration. Usage: qemu-system-riscv32 -M ot-earlgrey,no-epmp-cfg=3Dtrue [...] Signed-off-by: Emmanuel Blot Signed-off-by: Lo=C3=AFc Lefort --- hw/riscv/ot_earlgrey.c | 116 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 2 deletions(-) diff --git a/hw/riscv/ot_earlgrey.c b/hw/riscv/ot_earlgrey.c index 760a8d2c2e..77fb1b207c 100644 --- a/hw/riscv/ot_earlgrey.c +++ b/hw/riscv/ot_earlgrey.c @@ -18,6 +18,7 @@ #include "qemu/cutils.h" #include "qemu/units.h" #include "qapi/error.h" +#include "qobject/qlist.h" #include "cpu.h" #include "system/address-spaces.h" #include "hw/core/boards.h" @@ -28,6 +29,13 @@ #include "hw/riscv/ot_earlgrey.h" #include "system/system.h" =20 +/* -----------------------------------------------------------------------= - */ +/* Forward Declarations */ +/* -----------------------------------------------------------------------= - */ + +static void ot_earlgrey_soc_hart_configure( + DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent); + /* -----------------------------------------------------------------------= - */ /* Constants */ /* -----------------------------------------------------------------------= - */ @@ -116,6 +124,7 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = =3D { /* clang-format off */ [OT_EARLGREY_SOC_DEV_HART] =3D { .type =3D TYPE_RISCV_CPU_LOWRISC_OPENTITAN, + .cfg =3D &ot_earlgrey_soc_hart_configure, .prop =3D IBEXDEVICEPROPDEFS( IBEX_DEV_BOOL_PROP("zba", true), IBEX_DEV_BOOL_PROP("zbb", true), @@ -529,6 +538,60 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = =3D { /* clang-format on */ }; =20 +#define PMP_CFG(_l_, _a_, _x_, _w_, _r_) \ + ((uint8_t)(((_l_) << 7u) | ((_a_) << 3u) | ((_x_) << 2u) | ((_w_) << 1= u) | \ + ((_r_)))) +#define PMP_ADDR(_a_) ((_a_) >> 2u) + +#define MSECCFG(_rlb_, _mmwp_, _mml_) \ + (((_rlb_) << 2u) | ((_mmwp_) << 1u) | ((_mml_))) + +enum { PMP_MODE_OFF, PMP_MODE_TOR, PMP_MODE_NA4, PMP_MODE_NAPOT }; + +static const uint8_t ot_earlgrey_pmp_cfgs[] =3D { + /* clang-format off */ + PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0), + PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0), + PMP_CFG(1, PMP_MODE_NAPOT, 1, 0, 1), /* rgn 2 [ROM: LRX] */ + PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0), + PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0), + PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0), + PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0), + PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0), + PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0), + PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0), + PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0), + PMP_CFG(1, PMP_MODE_TOR, 0, 1, 1), /* rgn 11 [MMIO: LRW] */ + PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0), + PMP_CFG(1, PMP_MODE_NAPOT, 1, 1, 1), /* rgn 13 [DV_ROM: LRWX] */ + PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0), + PMP_CFG(0, PMP_MODE_OFF, 0, 0, 0) + /* clang-format on */ +}; + +static const uint32_t ot_earlgrey_pmp_addrs[] =3D { + /* clang-format off */ + PMP_ADDR(0x00000000), + PMP_ADDR(0x00000000), + PMP_ADDR(0x000083fc), /* rgn 2 [ROM: base=3D0x0000_8000 size (2KiB)] = */ + PMP_ADDR(0x00000000), + PMP_ADDR(0x00000000), + PMP_ADDR(0x00000000), + PMP_ADDR(0x00000000), + PMP_ADDR(0x00000000), + PMP_ADDR(0x00000000), + PMP_ADDR(0x00000000), + PMP_ADDR(0x40000000), /* rgn 10 [MMIO: lo=3D0x4000_0000] = */ + PMP_ADDR(0x42010000), /* rgn 11 [MMIO: hi=3D0x4201_0000] = */ + PMP_ADDR(0x00000000), + PMP_ADDR(0x000107fc), /* rgn 13 [DV_ROM: base=3D0x0001_0000 size (4KiB= )] */ + PMP_ADDR(0x00000000), + PMP_ADDR(0x00000000) + /* clang-format on */ +}; + +#define OT_EARLGREY_MSECCFG MSECCFG(1, 1, 0) + enum OtEarlgreyBoardDevice { OT_EARLGREY_BOARD_DEV_SOC, _OT_EARLGREY_BOARD_DEV_COUNT, @@ -553,8 +616,38 @@ struct OtEarlGreyBoardState { =20 struct OtEarlGreyMachineState { MachineState parent_obj; + + bool no_epmp_cfg; }; =20 +/* -----------------------------------------------------------------------= - */ +/* Device Configuration */ +/* -----------------------------------------------------------------------= - */ + +static void ot_earlgrey_soc_hart_configure( + DeviceState *dev, const IbexDeviceDef *def, DeviceState *parent) +{ + OtEarlGreyMachineState *ms =3D RISCV_OT_EARLGREY_MACHINE(qdev_get_mach= ine()); + if (ms->no_epmp_cfg) { + /* skip default PMP config */ + return; + } + + QList *pmp_cfgs =3D qlist_new(); + QList *pmp_addrs =3D qlist_new(); + + for (unsigned ix =3D 0; ix < ARRAY_SIZE(ot_earlgrey_pmp_cfgs); ix++) { + qlist_append_int(pmp_cfgs, (uint64_t)ot_earlgrey_pmp_cfgs[ix]); + } + for (unsigned ix =3D 0; ix < ARRAY_SIZE(ot_earlgrey_pmp_addrs); ix++) { + qlist_append_int(pmp_addrs, (uint64_t)ot_earlgrey_pmp_addrs[ix]); + } + + qdev_prop_set_array(dev, "pmp_cfg", pmp_cfgs); + qdev_prop_set_array(dev, "pmp_addr", pmp_addrs); + qdev_prop_set_uint64(dev, "mseccfg", (uint64_t)OT_EARLGREY_MSECCFG); +} + /* -----------------------------------------------------------------------= - */ /* SoC */ /* -----------------------------------------------------------------------= - */ @@ -688,12 +781,31 @@ type_init(ot_earlgrey_board_register_types); /* Machine */ /* -----------------------------------------------------------------------= - */ =20 +static bool ot_earlgrey_machine_get_no_epmp_cfg(Object *obj, Error **errp) +{ + OtEarlGreyMachineState *s =3D RISCV_OT_EARLGREY_MACHINE(obj); + + return s->no_epmp_cfg; +} + +static void +ot_earlgrey_machine_set_no_epmp_cfg(Object *obj, bool value, Error **errp) +{ + OtEarlGreyMachineState *s =3D RISCV_OT_EARLGREY_MACHINE(obj); + + s->no_epmp_cfg =3D value; +} + static void ot_earlgrey_machine_instance_init(Object *obj) { OtEarlGreyMachineState *s =3D RISCV_OT_EARLGREY_MACHINE(obj); =20 - /* nothing here */ - (void)s; + s->no_epmp_cfg =3D false; + object_property_add_bool(obj, "no-epmp-cfg", + &ot_earlgrey_machine_get_no_epmp_cfg, + &ot_earlgrey_machine_set_no_epmp_cfg); + object_property_set_description(obj, "no-epmp-cfg", + "Skip default ePMP configuration"); } =20 static void ot_earlgrey_machine_init(MachineState *state) --=20 2.49.1 From nobody Sun Apr 12 00:57:42 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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; dmarc=fail(p=none dis=none) header.from=git.sr.ht Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1771600178999297.2297866869201; Fri, 20 Feb 2026 07:09:38 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vtS7s-0005rY-7G; Fri, 20 Feb 2026 10:09:04 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS2F-0008EZ-Gn; Fri, 20 Feb 2026 10:03:17 -0500 Received: from mail-a.sr.ht ([46.23.81.152]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS2D-0002MO-FL; Fri, 20 Feb 2026 10:03:14 -0500 Received: from git.sr.ht (unknown [46.23.81.155]) by mail-a.sr.ht (Postfix) with ESMTPSA id 6A6D025021; Fri, 20 Feb 2026 15:03:10 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=ly5RtxzJn0F2WP0BkUcyjhxWSvK+uULsMgUEDOP8Xb0=; c=simple/simple; d=git.sr.ht; h=From:Date:Subject:Reply-to:In-Reply-To:To:Cc; q=dns/txt; s=20240113; t=1771599790; v=1; b=RxsXJdy+BJ8bSbC2/bjwxjL3mbZSSSKqveBgOouLkAp55UoX9WY9tHsq3Fv7wRmi6MH65foD e6feFAFLuaZxVkgR+zWyfoIZNhHPU5oug3cdAvqq6mq7F5zV4ADejLEU2JI6f4/Hno65oskAZ1D DuLZPmZGM68TP+avC74xPy9dH9JcU9+AgVajaT8+/uQVn3hAGQiLBs2KM7aQKNszK+amdpnhXrm bWEaHGXxc0jeNTHgJAKDpO7uzhzbKaKzlh+/GNLQ+Jbai6dSkvKqKI6A/hlvb1M/tn01H9kxcE2 LFRmdJGTBivD4SMtaZytaRdiuV15IDfS9axqsqBbhzdlA== From: ~lexbaileylowrisc Date: Fri, 17 Feb 2023 16:10:15 +0100 Subject: [PATCH qemu 09/11] [ot] hw/opentitan: add OpenTitan shadow register helpers MIME-Version: 1.0 Message-ID: <177159976712.8279.7732381632410882915-9@git.sr.ht> X-Mailer: git.sr.ht In-Reply-To: <177159976712.8279.7732381632410882915-0@git.sr.ht> To: qemu-devel@nongnu.org Cc: Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , qemu-riscv@nongnu.org, Paolo Bonzini , =?utf-8?q?Marc-Andr=C3=A9?= Lureau , Alistair Francis , Pierrick Bouvier , "Dr. David Alan Gilbert" , Daniel =?utf-8?q?P=2E_Berrang=C3=A9?= , Philippe =?utf-8?q?Mathieu-Daud=C3=A9?= , lowRISC , nabihestefan@google.com, Amit Kumar-Hermosillo Content-Type: text/plain; charset="utf-8" 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=46.23.81.152; envelope-from=outgoing@sr.ht; helo=mail-a.sr.ht X-Spam_score_int: 17 X-Spam_score: 1.7 X-Spam_bar: + X-Spam_report: (1.7 / 5.0 requ) BAYES_00=-1.9, DATE_IN_PAST_96_XX=3.405, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Fri, 20 Feb 2026 10:09:01 -0500 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: ~lexbaileylowrisc Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1771600181914158500 From: Lo=C3=AFc Lefort Signed-off-by: Lo=C3=AFc Lefort --- include/hw/opentitan/ot_common.h | 93 ++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 include/hw/opentitan/ot_common.h diff --git a/include/hw/opentitan/ot_common.h b/include/hw/opentitan/ot_com= mon.h new file mode 100644 index 0000000000..546a7d88a8 --- /dev/null +++ b/include/hw/opentitan/ot_common.h @@ -0,0 +1,93 @@ +/* + * QEMU RISC-V Helpers for OpenTitan EarlGrey + * + * Copyright (c) 2023 Rivos, Inc. + * + * Author(s): + * Emmanuel Blot + * Lo=C3=AFc Lefort + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_RISCV_OT_COMMON_H +#define HW_RISCV_OT_COMMON_H + +#include "qemu/osdep.h" + +/* -----------------------------------------------------------------------= - */ +/* Shadow Registers */ +/* -----------------------------------------------------------------------= - */ + +/* + * Shadow register, concept documented at: + * https://docs.opentitan.org/doc/rm/register_tool/#shadow-registers + */ +typedef struct OtShadowReg { + /* committed register value */ + uint32_t committed; + /* staged register value */ + uint32_t staged; + /* true if 'staged' holds a value */ + bool staged_p; +} OtShadowReg; + +enum { + OT_SHADOW_REG_ERROR =3D -1, + OT_SHADOW_REG_COMMITTED =3D 0, + OT_SHADOW_REG_STAGED =3D 1, +}; + +/** + * Initialize a shadow register with a committed value and no staged value + */ +static inline void ot_shadow_reg_init(OtShadowReg *sreg, uint32_t value) +{ + sreg->committed =3D value; + sreg->staged_p =3D false; +} + +/** + * Write a new value to a shadow register. + * If no value was previously staged, the new value is only staged for next + * write and the function returns OT_SHADOW_REG_STAGED. + * If a value was previously staged and the new value is different, the fu= nction + * returns OT_SHADOW_REG_ERROR and the new value is ignored. Otherwise the= value + * is committed, the staged value is discarded and the function returns + * OT_SHADOW_REG_COMMITTED. + */ +static inline int ot_shadow_reg_write(OtShadowReg *sreg, uint32_t value) +{ + if (sreg->staged_p) { + if (value !=3D sreg->staged) { + /* second write is different, return error status */ + return OT_SHADOW_REG_ERROR; + } + sreg->committed =3D value; + sreg->staged_p =3D false; + return OT_SHADOW_REG_COMMITTED; + } else { + sreg->staged =3D value; + sreg->staged_p =3D true; + return OT_SHADOW_REG_STAGED; + } +} + +/** + * Return the current committed register value + */ +static inline uint32_t ot_shadow_reg_peek(const OtShadowReg *sreg) +{ + return sreg->committed; +} + +/** + * Discard the staged value and return the current committed register value + */ +static inline uint32_t ot_shadow_reg_read(OtShadowReg *sreg) +{ + sreg->staged_p =3D false; + return sreg->committed; +} + +#endif /* HW_RISCV_OT_COMMON_H */ --=20 2.49.1 From nobody Sun Apr 12 00:57:42 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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; dmarc=fail(p=none dis=none) header.from=git.sr.ht Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1771600155349809.7482140105602; Fri, 20 Feb 2026 07:09:15 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vtS7s-0005re-O3; Fri, 20 Feb 2026 10:09:04 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS2Z-0008PE-95; Fri, 20 Feb 2026 10:03:35 -0500 Received: from mail-a.sr.ht ([46.23.81.152]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS2X-0002MU-LR; Fri, 20 Feb 2026 10:03:34 -0500 Received: from git.sr.ht (unknown [46.23.81.155]) by mail-a.sr.ht (Postfix) with ESMTPSA id 3249E25025; Fri, 20 Feb 2026 15:03:12 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=AHBKd/E7gyHUH8J6ORF6Q6SY/jbV6XihNGC5nYAYW8Y=; c=simple/simple; d=git.sr.ht; h=From:Date:Subject:Reply-to:In-Reply-To:To:Cc; q=dns/txt; s=20240113; t=1771599792; v=1; b=E7ZA/Ga9knyjjFTJb/IJKleVXgIabmEzGst8yeGmrBGD67nCLlcTT5ahiJIvpTsZScpVb7+L NBfyJ2uwxQ6ZKhd4bsqncE0U/45X2FcqNLBsZy3fnm6brPCjB44DhpLy4GICRkEKnLAyVCFWVtB 4yGxq8Os6LsjX+qpxX5A8aZ1QshKBs+jD//eid7jmrE88kFgd+jm24xvMITNH3xVdRpnuLxmk4a rB3xJ/G4pn+XiMQN0CH8HSYFdPBmFtZBkDJm3s7ZzOfxwZNth9SaktaNUJoiKziigLoA/X5yo/k GxqKQqU+qeXVpOHFVaq5EZfg/fhVwFlbpCGtNsz1/3LVQ== From: ~lexbaileylowrisc Date: Tue, 31 Jan 2023 14:52:45 +0100 Subject: [PATCH qemu 10/11] [ot] hw/riscv: add an IRQ wrapper Message-ID: <177159976712.8279.7732381632410882915-10@git.sr.ht> X-Mailer: git.sr.ht In-Reply-To: <177159976712.8279.7732381632410882915-0@git.sr.ht> To: qemu-devel@nongnu.org Cc: Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , qemu-riscv@nongnu.org, Paolo Bonzini , =?utf-8?q?Marc-Andr=C3=A9?= Lureau , Alistair Francis , Pierrick Bouvier , "Dr. David Alan Gilbert" , Daniel =?utf-8?q?P=2E_Berrang=C3=A9?= , Philippe =?utf-8?q?Mathieu-Daud=C3=A9?= , lowRISC , nabihestefan@google.com, Amit Kumar-Hermosillo Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 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=46.23.81.152; envelope-from=outgoing@sr.ht; helo=mail-a.sr.ht X-Spam_score_int: 17 X-Spam_score: 1.7 X-Spam_bar: + X-Spam_report: (1.7 / 5.0 requ) BAYES_00=-1.9, DATE_IN_PAST_96_XX=3.405, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Fri, 20 Feb 2026 10:09:01 -0500 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: ~lexbaileylowrisc Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1771600157077154100 From: Emmanuel Blot Signed-off-by: Emmanuel Blot Includes existing MIT licenced code (already published elsewhere) --- include/hw/riscv/ibex_irq.h | 69 +++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 include/hw/riscv/ibex_irq.h diff --git a/include/hw/riscv/ibex_irq.h b/include/hw/riscv/ibex_irq.h new file mode 100644 index 0000000000..22ccff6d5e --- /dev/null +++ b/include/hw/riscv/ibex_irq.h @@ -0,0 +1,69 @@ +/* + * QEMU lowRISC Ibex IRQ wrapper + * + * Copyright (c) 2022-2023 Rivos, Inc. + * + * SPDX-License-Identifier: MIT + * + */ + +#ifndef HW_RISCV_IBEX_IRQ_H +#define HW_RISCV_IBEX_IRQ_H + +#include "qemu/osdep.h" +#include "qom/object.h" +#include "hw/irq.h" +#include "hw/qdev-core.h" +#include "hw/sysbus.h" + + +/** Simple IRQ wrapper to limit propagation of no-change calls */ +typedef struct { + qemu_irq irq; + int level; +} IbexIRQ; + +static inline bool ibex_irq_set(IbexIRQ *ibex_irq, int level) +{ + if (level !=3D ibex_irq->level) { + ibex_irq->level =3D level; + qemu_set_irq(ibex_irq->irq, level); + return true; + } + + return false; +} + +static inline bool ibex_irq_raise(IbexIRQ *irq) +{ + return ibex_irq_set(irq, 1); +} + +static inline bool ibex_irq_lower(IbexIRQ *irq) +{ + return ibex_irq_set(irq, 0); +} + +static inline void ibex_qdev_init_irq(Object *obj, IbexIRQ *irq, + const char *name) +{ + irq->level =3D 0; + qdev_init_gpio_out_named(DEVICE(obj), &irq->irq, name, 1); +} + +static inline void ibex_qdev_init_irqs(Object *obj, IbexIRQ *irqs, + const char *name, unsigned count) +{ + for (unsigned ix =3D 0; ix < count; ix++) { + irqs[ix].level =3D 0; + qdev_init_gpio_out_named(DEVICE(obj), &irqs[ix].irq, name, 1); + } +} + +static inline void ibex_sysbus_init_irq(Object *obj, IbexIRQ *irq) +{ + irq->level =3D 0; + sysbus_init_irq(SYS_BUS_DEVICE(obj), &irq->irq); +} + +#endif /* HW_RISCV_IBEX_IRQ_H */ --=20 2.49.1 From nobody Sun Apr 12 00:57:42 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; 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; dmarc=fail(p=none dis=none) header.from=git.sr.ht Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1771600229530204.88374137915514; Fri, 20 Feb 2026 07:10:29 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vtS7s-0005rg-Ux; Fri, 20 Feb 2026 10:09:04 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS2b-0008Su-LC; Fri, 20 Feb 2026 10:03:37 -0500 Received: from mail-a.sr.ht ([46.23.81.152]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1vtS2X-0002MY-NM; Fri, 20 Feb 2026 10:03:36 -0500 Received: from git.sr.ht (unknown [46.23.81.155]) by mail-a.sr.ht (Postfix) with ESMTPSA id 4A9AF25026; Fri, 20 Feb 2026 15:03:12 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=rBS2TnP2vkOrMgY4ViNjdaynesZqm+FvW1XBTRD4iP8=; c=simple/simple; d=git.sr.ht; h=From:Date:Subject:Reply-to:In-Reply-To:To:Cc; q=dns/txt; s=20240113; t=1771599792; v=1; b=oHlR8Dpfn5QNDn8gFtZinQQoBDvBgcmkTVj14/cC6oRIbFilDxFg+8pjSFOxGdg1zg/bGAXw bD60U26bvzrDRsa+X0gzVw5icKo6n6eioIZ+KX/4YaC2h4iTH7DIDW4J667baCTXG3zp5XOD3A5 4PwqO4WTsIR7Y3k4Dz43oXAXzad+DAL9qyGauBfoaaZ46IbXz/v49F/NX8JfVcT3CNnBSkzh18u 1o5EuriFxUFcJly7Kwd7n9wwOpHAkLOGnSClpDNFe+Yx8iZilFKWXAC+eSiklzOrCM83KonDk33 uKo0SUF0dHwmVq6VKX5sd1fQBddtl7SU0teWkLo6E5AXw== From: ~lexbaileylowrisc Date: Thu, 16 Feb 2023 17:11:22 +0100 Subject: [PATCH qemu 11/11] [ot] hw/riscv, hw/opentitan: add Opentitan Alert handler device Message-ID: <177159976712.8279.7732381632410882915-11@git.sr.ht> X-Mailer: git.sr.ht In-Reply-To: <177159976712.8279.7732381632410882915-0@git.sr.ht> To: qemu-devel@nongnu.org Cc: Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , qemu-riscv@nongnu.org, Paolo Bonzini , =?utf-8?q?Marc-Andr=C3=A9?= Lureau , Alistair Francis , Pierrick Bouvier , "Dr. David Alan Gilbert" , Daniel =?utf-8?q?P=2E_Berrang=C3=A9?= , Philippe =?utf-8?q?Mathieu-Daud=C3=A9?= , lowRISC , nabihestefan@google.com, Amit Kumar-Hermosillo Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 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=46.23.81.152; envelope-from=outgoing@sr.ht; helo=mail-a.sr.ht X-Spam_score_int: 17 X-Spam_score: 1.7 X-Spam_bar: + X-Spam_report: (1.7 / 5.0 requ) BAYES_00=-1.9, DATE_IN_PAST_96_XX=3.405, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, UPPERCASE_50_75=0.008 autolearn=no autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Fri, 20 Feb 2026 10:09:01 -0500 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: ~lexbaileylowrisc Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1771600232154154100 From: Emmanuel Blot Signed-off-by: Lex Bailey Includes existing MIT licenced code (already published elsewhere) --- hw/opentitan/Kconfig | 2 + hw/opentitan/meson.build | 1 + hw/opentitan/ot_alert.c | 668 ++++++++++++++++++++++++++++++++ hw/opentitan/trace-events | 5 + hw/riscv/Kconfig | 1 + hw/riscv/ibex_common.c | 2 +- hw/riscv/ot_earlgrey.c | 11 +- include/hw/opentitan/ot_alert.h | 23 ++ include/hw/riscv/ibex_irq.h | 6 +- 9 files changed, 712 insertions(+), 7 deletions(-) create mode 100644 hw/opentitan/ot_alert.c create mode 100644 include/hw/opentitan/ot_alert.h diff --git a/hw/opentitan/Kconfig b/hw/opentitan/Kconfig index 6bd1855a84..6e9aa833b4 100644 --- a/hw/opentitan/Kconfig +++ b/hw/opentitan/Kconfig @@ -1,2 +1,4 @@ # OpenTitan devices =20 +config OT_ALERT + bool diff --git a/hw/opentitan/meson.build b/hw/opentitan/meson.build index 6bd1855a84..d24aae88fd 100644 --- a/hw/opentitan/meson.build +++ b/hw/opentitan/meson.build @@ -1,2 +1,3 @@ # OpenTitan devices =20 +system_ss.add(when: 'CONFIG_OT_ALERT', if_true: files('ot_alert.c')) diff --git a/hw/opentitan/ot_alert.c b/hw/opentitan/ot_alert.c new file mode 100644 index 0000000000..b864fda0fa --- /dev/null +++ b/hw/opentitan/ot_alert.c @@ -0,0 +1,668 @@ +/* + * QEMU OpenTitan Alert handler device + * + * Copyright (c) 2023-2025 Rivos, Inc. + * + * Author(s): + * Emmanuel Blot + * + * SPDX-License-Identifier: MIT + * + */ + +#include "qemu/osdep.h" +#include "qemu/guest-random.h" +#include "qemu/log.h" +#include "qemu/main-loop.h" +#include "qemu/timer.h" +#include "qemu/typedefs.h" +#include "qapi/error.h" +#include "hw/opentitan/ot_alert.h" +#include "hw/core/qdev-properties-system.h" +#include "hw/core/qdev-properties.h" +#include "hw/core/registerfields.h" +#include "hw/riscv/ibex_common.h" +#include "hw/riscv/ibex_irq.h" +#include "hw/core/sysbus.h" +#include "trace.h" + +#define PARAM_N_ALERTS 65u +#define PARAM_N_LPG 24u +#define PARAM_N_LPG_WIDTH 5u +#define PARAM_ESC_CNT_DW 32u +#define PARAM_ACCU_CNT_DW 16u +#define PARAM_N_CLASSES 4u +#define PARAM_N_ESC_SEV 4u +#define PARAM_N_PHASES 4u +#define PARAM_N_LOC_ALERT 7u +#define PARAM_PING_CNT_DW 16u +#define PARAM_PHASE_DW 2u +#define PARAM_CLASS_DW 2u + +/* clang-format off */ +REG32(INTR_STATE, 0x0u) + SHARED_FIELD(INTR_STATE_CLASSA, 0u, 1u) + SHARED_FIELD(INTR_STATE_CLASSB, 1u, 1u) + SHARED_FIELD(INTR_STATE_CLASSC, 2u, 1u) + SHARED_FIELD(INTR_STATE_CLASSD, 3u, 1u) +REG32(INTR_ENABLE, 0x4u) +REG32(INTR_TEST, 0x8u) +REG32(PING_TIMER_REGWEN, 0xcu) + FIELD(PING_TIMER_REGWEN, EN, 0u, 1u) +REG32(PING_TIMEOUT_CYC_SHADOWED, 0x10u) + FIELD(PING_TIMEOUT_CYC_SHADOWED, VAL, 0u, 16u) +REG32(PING_TIMER_EN_SHADOWED, 0x14u) + FIELD(PING_TIMER_EN_SHADOWED, EN, 0u, 1u) +REG32(ALERT_REGWEN, 0x18u) + SHARED_FIELD(ALERT_REGWEN_EN, 0u, 1u) +REG32(ALERT_EN_SHADOWED, 0x11cu) + SHARED_FIELD(ALERT_EN_SHADOWED_EN, 0u, 1u) +REG32(ALERT_CLASS_SHADOWED, 0x220u) + SHARED_FIELD(ALERT_CLASS_SHADOWED_EN, 0u, 2u) +REG32(ALERT_CAUSE, 0x324u) + SHARED_FIELD(ALERT_CAUSE_EN, 0u, 1u) +REG32(LOC_ALERT_REGWEN, 0x428u) + SHARED_FIELD(LOC_ALERT_REGWEN_EN, 0u, 1u) +REG32(LOC_ALERT_EN_SHADOWED, 0x444u) + SHARED_FIELD(LOC_ALERT_EN_SHADOWED_EN, 0u, 1u) +REG32(LOC_ALERT_CLASS_SHADOWED, 0x460u) + SHARED_FIELD(LOC_ALERT_CLASS_SHADOWED_EN, 0u, 2u) +REG32(LOC_ALERT_CAUSE, 0x47cu) + SHARED_FIELD(LOC_ALERT_CAUSE_EN, 0u, 1u) +REG32(CLASS_REGWEN, 0x498u) + FIELD(CLASS_REGWEN, EN, 0u, 1u) +REG32(CLASS_CTRL_SHADOWED, 0x49cu) + SHARED_FIELD(CLASS_CTRL_SHADOWED_EN, 0u, 1u) + SHARED_FIELD(CLASS_CTRL_SHADOWED_LOCK, 1u, 1u) + SHARED_FIELD(CLASS_CTRL_SHADOWED_EN_E0, 2u, 1u) + SHARED_FIELD(CLASS_CTRL_SHADOWED_EN_E1, 3u, 1u) + SHARED_FIELD(CLASS_CTRL_SHADOWED_EN_E2, 4u, 1u) + SHARED_FIELD(CLASS_CTRL_SHADOWED_EN_E3, 5u, 1u) + SHARED_FIELD(CLASS_CTRL_SHADOWED_MAP_E0, 6u, 2u) + SHARED_FIELD(CLASS_CTRL_SHADOWED_MAP_E1, 8u, 2u) + SHARED_FIELD(CLASS_CTRL_SHADOWED_MAP_E2, 10u, 2u) + SHARED_FIELD(CLASS_CTRL_SHADOWED_MAP_E3, 12u, 2u) +REG32(CLASS_CLR_REGWEN, 0x4a0u) + SHARED_FIELD(CLASS_CLR_REGWEN_EN, 0u, 1u) +REG32(CLASS_CLR_SHADOWED, 0x4a4u) + SHARED_FIELD(CLASS_CLR_SHADOWED_EN, 0u, 1u) +REG32(CLASS_ACCUM_CNT, 0x4a8u) + SHARED_FIELD(CLASS_ACCUM_CNT, 0u, 16u) +REG32(CLASS_ACCUM_THRESH_SHADOWED, 0x4acu) + SHARED_FIELD(CLASS_ACCUM_THRESH_SHADOWED, 0u, 16u) +REG32(CLASS_TIMEOUT_CYC_SHADOWED, 0x4b0u) +REG32(CLASS_CRASHDUMP_TRIGGER_SHADOWED, 0x4b4u) + SHARED_FIELD(CLASS_CRASHDUMP_TRIGGER_SHADOWED, 0u, 2u) +REG32(CLASS_PHASE0_CYC_SHADOWED, 0x4b8u) +REG32(CLASS_PHASE1_CYC_SHADOWED, 0x4bcu) +REG32(CLASS_PHASE2_CYC_SHADOWED, 0x4c0u) +REG32(CLASS_PHASE3_CYC_SHADOWED, 0x4c4u) +REG32(CLASS_ESC_CNT, 0x4c8u) +REG32(CLASS_STATE, 0x4ccu) + FIELD(CLASS_STATE, VAL, 0u, 3u) +/* clang-format on */ + +enum { + ALERT_ID_ALERT_PINGFAIL, + ALERT_ID_ESC_PINGFAIL, + ALERT_ID_ALERT_INTEGFAIL, + ALERT_ID_ESC_INTEGFAIL, + ALERT_ID_BUS_INTEGFAIL, + ALERT_ID_SHADOW_REG_UPDATE_ERROR, + ALERT_ID_SHADOW_REG_STORAGE_ERROR, +}; + +enum { + ALERT_CLASSA, + ALERT_CLASSB, + ALERT_CLASSC, + ALERT_CLASSD, +}; + +enum { + STATE_IDLE, + STATE_TIMEOUT, + STATE_FSMERROR, + STATE_TERMINAL, + STATE_PHASE0, + STATE_PHASE1, + STATE_PHASE2, + STATE_PHASE3, +}; + +#define INTR_MASK ((1u << PARAM_N_CLASSES) - 1u) +#define CLASS_CTRL_SHADOWED_MASK \ + (CLASS_CTRL_SHADOWED_EN_MASK | CLASS_CTRL_SHADOWED_LOCK_MASK | \ + CLASS_CTRL_SHADOWED_EN_E0_MASK | CLASS_CTRL_SHADOWED_EN_E1_MASK | \ + CLASS_CTRL_SHADOWED_EN_E2_MASK | CLASS_CTRL_SHADOWED_EN_E3_MASK | \ + CLASS_CTRL_SHADOWED_MAP_E0_MASK | CLASS_CTRL_SHADOWED_MAP_E1_MASK | \ + CLASS_CTRL_SHADOWED_MAP_E2_MASK | CLASS_CTRL_SHADOWED_MAP_E3_MASK) + +#define R32_OFF(_r_) ((_r_) / sizeof(uint32_t)) + +#define R_LAST_REG R32_OFF(0x574u) +#define REGS_COUNT (R_LAST_REG + 1u) +#define REGS_SIZE (REGS_COUNT * sizeof(uint32_t)) + +#define ALERT_SLOT_SIZE R32_OFF(sizeof(struct alerts)) +#define LOC_ALERT_SLOT_SIZE R32_OFF(sizeof(struct loc_alerts)) +#define CLASS_SLOT_SIZE R32_OFF(sizeof(struct classes)) +#define CASE_RANGE(_reg_, _cnt_) (_reg_)...((_reg_) + (_cnt_) - (1u)) +#define CASE_STRIDE(_reg_, _cls_) ((_reg_) + (_cls_) * (CLASS_SLOT_SIZE)) +#define SLOT_OFFSET(_reg_, _base_, _kind_) \ + (((_reg_) - (_base_)) / _kind_##_SLOT_SIZE) +#define ALERT_SLOT(_reg_) SLOT_OFFSET(_reg_, R_ALERT_REGWEN, ALERT) +#define LOC_ALERT_SLOT(_reg_) SLOT_OFFSET(_reg_, R_LOC_ALERT_REGWEN, LOC_A= LERT) +#define CLASS_SLOT(_reg_) SLOT_OFFSET(_reg_, R_CLASS_REGWEN, CLASS) + +#define CHECK_REGWEN(_reg_, _cond_) \ + ot_alert_check_regwen(__func__, (_reg_), (_cond_)) + +struct intr { + uint32_t state; + uint32_t enable; + uint32_t test; +}; + +struct ping { + uint32_t timer_regwen; + uint32_t timeout_cyc_shadowed; + uint32_t timer_en_shadowed; +}; + +struct alerts { + uint32_t regwen; + uint32_t en_shadowed; + uint32_t class_shadowed; + uint32_t cause; +}; + +struct loc_alerts { + uint32_t regwen; + uint32_t en_shadowed; + uint32_t class_shadowed; + uint32_t cause; +}; + +struct classes { + uint32_t regwen; + uint32_t ctrl_shadowed; + uint32_t clr_regwen; + uint32_t clr_shadowed; + uint32_t accum_cnt; + uint32_t accum_thresh_shadowed; + uint32_t timeout_cyc_shadowed; + uint32_t crashdump_trigger_shadowed; + uint32_t phase0_cyc_shadowed; + uint32_t phase1_cyc_shadowed; + uint32_t phase2_cyc_shadowed; + uint32_t phase3_cyc_shadowed; + uint32_t esc_cnt; + uint32_t state; +}; + +typedef struct OtAlertRegs { + struct intr intr; + struct ping ping; + struct alerts alerts[PARAM_N_ALERTS]; + struct loc_alerts loc_alerts[PARAM_N_LOC_ALERT]; + struct classes classes[PARAM_N_CLASSES]; +} OtAlertRegs; + +struct OtAlertState { + SysBusDevice parent_obj; + + MemoryRegion mmio; + IbexIRQ irqs[PARAM_N_CLASSES]; + + OtAlertRegs *regs; +}; + +struct OtAlertClass { + SysBusDeviceClass parent_class; + ResettablePhases parent_phases; +}; + +static inline bool +ot_alert_check_regwen(const char *func, unsigned reg, bool cond) +{ + if (!cond) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: reg 0x%04x is write-protected\= n", + func, (unsigned)(reg * sizeof(uint32_t))); + return false; + } + return true; +} + +static void ot_alert_update_irqs(OtAlertState *s) +{ + uint32_t level =3D s->regs->intr.state & s->regs->intr.enable; + + for (unsigned ix =3D 0; ix < ARRAY_SIZE(s->irqs); ix++) { + ibex_irq_set(&s->irqs[ix], (int)((level >> ix) & 0x1)); + } +} + +static uint64_t ot_alert_regs_read(void *opaque, hwaddr addr, unsigned siz= e) +{ + OtAlertState *s =3D opaque; + OtAlertRegs *regs =3D s->regs; + uint32_t val32; + + hwaddr reg =3D R32_OFF(addr); + + switch (reg) { + case R_INTR_STATE: + val32 =3D regs->intr.state; + break; + case R_INTR_ENABLE: + val32 =3D regs->intr.enable; + break; + case R_PING_TIMER_REGWEN: + val32 =3D regs->ping.timer_regwen; + break; + case R_PING_TIMEOUT_CYC_SHADOWED: + val32 =3D regs->ping.timeout_cyc_shadowed; + break; + case R_PING_TIMER_EN_SHADOWED: + val32 =3D regs->ping.timer_en_shadowed; + break; + case R_INTR_TEST: + qemu_log_mask(LOG_GUEST_ERROR, "W/O register 0x02%" HWADDR_PRIx "\= n", + addr); + val32 =3D 0; + break; + case CASE_RANGE(R_ALERT_REGWEN, PARAM_N_ALERTS): + val32 =3D regs->alerts[ALERT_SLOT(reg)].regwen; + break; + case CASE_RANGE(R_ALERT_EN_SHADOWED, PARAM_N_ALERTS): + val32 =3D regs->alerts[ALERT_SLOT(reg)].en_shadowed; + break; + case CASE_RANGE(R_ALERT_CLASS_SHADOWED, PARAM_N_ALERTS): + val32 =3D regs->alerts[ALERT_SLOT(reg)].class_shadowed; + break; + case CASE_RANGE(R_ALERT_CAUSE, PARAM_N_ALERTS): + val32 =3D regs->alerts[ALERT_SLOT(reg)].cause; + break; + case CASE_RANGE(R_LOC_ALERT_REGWEN, PARAM_N_LOC_ALERT): + val32 =3D regs->loc_alerts[LOC_ALERT_SLOT(reg)].regwen; + break; + case CASE_RANGE(R_LOC_ALERT_EN_SHADOWED, PARAM_N_LOC_ALERT): + val32 =3D regs->loc_alerts[LOC_ALERT_SLOT(reg)].en_shadowed; + break; + case CASE_RANGE(R_LOC_ALERT_CLASS_SHADOWED, PARAM_N_LOC_ALERT): + val32 =3D regs->loc_alerts[LOC_ALERT_SLOT(reg)].class_shadowed; + break; + case CASE_RANGE(R_LOC_ALERT_CAUSE, PARAM_N_LOC_ALERT): + val32 =3D regs->loc_alerts[LOC_ALERT_SLOT(reg)].cause; + break; + case CASE_STRIDE(R_CLASS_REGWEN, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_REGWEN, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_REGWEN, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_REGWEN, ALERT_CLASSD): + val32 =3D regs->classes[CLASS_SLOT(reg)].regwen; + break; + case CASE_STRIDE(R_CLASS_CTRL_SHADOWED, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_CTRL_SHADOWED, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_CTRL_SHADOWED, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_CTRL_SHADOWED, ALERT_CLASSD): + val32 =3D regs->classes[CLASS_SLOT(reg)].ctrl_shadowed; + break; + case CASE_STRIDE(R_CLASS_CLR_REGWEN, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_CLR_REGWEN, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_CLR_REGWEN, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_CLR_REGWEN, ALERT_CLASSD): + val32 =3D regs->classes[CLASS_SLOT(reg)].clr_regwen; + break; + case CASE_STRIDE(R_CLASS_CLR_SHADOWED, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_CLR_SHADOWED, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_CLR_SHADOWED, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_CLR_SHADOWED, ALERT_CLASSD): + val32 =3D regs->classes[CLASS_SLOT(reg)].clr_shadowed; + break; + case CASE_STRIDE(R_CLASS_ACCUM_CNT, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_ACCUM_CNT, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_ACCUM_CNT, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_ACCUM_CNT, ALERT_CLASSD): + val32 =3D regs->classes[CLASS_SLOT(reg)].accum_cnt; + break; + case CASE_STRIDE(R_CLASS_ACCUM_THRESH_SHADOWED, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_ACCUM_THRESH_SHADOWED, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_ACCUM_THRESH_SHADOWED, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_ACCUM_THRESH_SHADOWED, ALERT_CLASSD): + val32 =3D regs->classes[CLASS_SLOT(reg)].accum_thresh_shadowed; + break; + case CASE_STRIDE(R_CLASS_TIMEOUT_CYC_SHADOWED, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_TIMEOUT_CYC_SHADOWED, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_TIMEOUT_CYC_SHADOWED, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_TIMEOUT_CYC_SHADOWED, ALERT_CLASSD): + val32 =3D regs->classes[CLASS_SLOT(reg)].timeout_cyc_shadowed; + break; + case CASE_STRIDE(R_CLASS_CRASHDUMP_TRIGGER_SHADOWED, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_CRASHDUMP_TRIGGER_SHADOWED, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_CRASHDUMP_TRIGGER_SHADOWED, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_CRASHDUMP_TRIGGER_SHADOWED, ALERT_CLASSD): + val32 =3D regs->classes[CLASS_SLOT(reg)].crashdump_trigger_shadowe= d; + break; + case CASE_STRIDE(R_CLASS_PHASE0_CYC_SHADOWED, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_PHASE0_CYC_SHADOWED, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_PHASE0_CYC_SHADOWED, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_PHASE0_CYC_SHADOWED, ALERT_CLASSD): + val32 =3D regs->classes[CLASS_SLOT(reg)].phase0_cyc_shadowed; + break; + case CASE_STRIDE(R_CLASS_PHASE1_CYC_SHADOWED, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_PHASE1_CYC_SHADOWED, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_PHASE1_CYC_SHADOWED, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_PHASE1_CYC_SHADOWED, ALERT_CLASSD): + val32 =3D regs->classes[CLASS_SLOT(reg)].phase1_cyc_shadowed; + break; + case CASE_STRIDE(R_CLASS_PHASE2_CYC_SHADOWED, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_PHASE2_CYC_SHADOWED, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_PHASE2_CYC_SHADOWED, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_PHASE2_CYC_SHADOWED, ALERT_CLASSD): + val32 =3D regs->classes[CLASS_SLOT(reg)].phase2_cyc_shadowed; + break; + case CASE_STRIDE(R_CLASS_PHASE3_CYC_SHADOWED, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_PHASE3_CYC_SHADOWED, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_PHASE3_CYC_SHADOWED, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_PHASE3_CYC_SHADOWED, ALERT_CLASSD): + val32 =3D regs->classes[CLASS_SLOT(reg)].phase3_cyc_shadowed; + break; + case CASE_STRIDE(R_CLASS_ESC_CNT, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_ESC_CNT, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_ESC_CNT, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_ESC_CNT, ALERT_CLASSD): + val32 =3D regs->classes[CLASS_SLOT(reg)].esc_cnt; + break; + case CASE_STRIDE(R_CLASS_STATE, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_STATE, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_STATE, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_STATE, ALERT_CLASSD): + val32 =3D + regs->classes[reg - CASE_STRIDE(R_CLASS_STATE, ALERT_CLASSA)].= state; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\= n", + __func__, addr); + val32 =3D 0; + break; + } + + uint64_t pc =3D ibex_get_current_pc(); + trace_ot_alert_io_read_out((unsigned)addr, (uint64_t)val32, pc); + + return (uint64_t)val32; +}; + +static void ot_alert_regs_write(void *opaque, hwaddr addr, uint64_t val64, + unsigned size) +{ + OtAlertState *s =3D opaque; + OtAlertRegs *regs =3D s->regs; + uint32_t val32 =3D (uint32_t)val64; + + hwaddr reg =3D R32_OFF(addr); + + uint64_t pc =3D ibex_get_current_pc(); + trace_ot_alert_io_write((unsigned)addr, val64, pc); + + switch (reg) { + case R_INTR_STATE: + val32 &=3D INTR_MASK; + regs->intr.state &=3D ~val32; /* RW1C */ + ot_alert_update_irqs(s); + break; + case R_INTR_ENABLE: + val32 &=3D INTR_MASK; + regs->intr.enable =3D val32; + ot_alert_update_irqs(s); + break; + case R_INTR_TEST: + val32 &=3D INTR_MASK; + regs->intr.state |=3D val32; + ot_alert_update_irqs(s); + break; + case R_PING_TIMER_REGWEN: + val32 &=3D R_PING_TIMER_REGWEN_EN_MASK; + regs->ping.timer_regwen &=3D ~val32; /* RW1C */ + break; + case R_PING_TIMEOUT_CYC_SHADOWED: + val32 &=3D R_PING_TIMEOUT_CYC_SHADOWED_VAL_MASK; + regs->ping.timeout_cyc_shadowed =3D val32; + break; + case R_PING_TIMER_EN_SHADOWED: + val32 =3D R_PING_TIMER_EN_SHADOWED_EN_MASK; /* RW1S */ + regs->ping.timer_en_shadowed |=3D val32; + break; + case CASE_RANGE(R_ALERT_REGWEN, PARAM_N_ALERTS): + val32 &=3D ALERT_REGWEN_EN_MASK; + regs->alerts[ALERT_SLOT(reg)].regwen &=3D val32; /* RW0C */ + break; + case CASE_RANGE(R_ALERT_EN_SHADOWED, PARAM_N_ALERTS): + if (CHECK_REGWEN(reg, regs->alerts[reg - R_ALERT_EN_SHADOWED].regw= en)) { + val32 &=3D ALERT_EN_SHADOWED_EN_MASK; + regs->alerts[ALERT_SLOT(reg)].en_shadowed =3D val32; + } + break; + case CASE_RANGE(R_ALERT_CLASS_SHADOWED, PARAM_N_ALERTS): + if (CHECK_REGWEN(reg, + regs->alerts[reg - R_ALERT_CLASS_SHADOWED].regwen= )) { + val32 &=3D ALERT_CLASS_SHADOWED_EN_MASK; + regs->alerts[ALERT_SLOT(reg)].en_shadowed =3D val32; + } + break; + case CASE_RANGE(R_ALERT_CAUSE, PARAM_N_ALERTS): + val32 =3D ALERT_CAUSE_EN_MASK; + regs->alerts[ALERT_SLOT(reg)].cause &=3D ~val32; /* RW1C */ + break; + case CASE_RANGE(R_LOC_ALERT_REGWEN, PARAM_N_LOC_ALERT): + val32 &=3D LOC_ALERT_REGWEN_EN_MASK; + regs->loc_alerts[LOC_ALERT_SLOT(reg)].regwen &=3D val32; /* RW0C */ + break; + case CASE_RANGE(R_LOC_ALERT_EN_SHADOWED, PARAM_N_LOC_ALERT): + if (CHECK_REGWEN(reg, regs->loc_alerts[LOC_ALERT_SLOT(reg)].regwen= )) { + val32 &=3D LOC_ALERT_EN_SHADOWED_EN_MASK; + regs->loc_alerts[LOC_ALERT_SLOT(reg)].en_shadowed =3D val32; + } + break; + case CASE_RANGE(R_LOC_ALERT_CLASS_SHADOWED, PARAM_N_LOC_ALERT): + if (CHECK_REGWEN(reg, regs->loc_alerts[LOC_ALERT_SLOT(reg)].regwen= )) { + val32 &=3D LOC_ALERT_CLASS_SHADOWED_EN_MASK; + regs->loc_alerts[LOC_ALERT_SLOT(reg)].en_shadowed =3D val32; + } + break; + case CASE_RANGE(R_LOC_ALERT_CAUSE, PARAM_N_LOC_ALERT): + val32 =3D LOC_ALERT_CAUSE_EN_MASK; + regs->loc_alerts[LOC_ALERT_SLOT(reg)].cause &=3D ~val32; /* RW1C */ + break; + case CASE_STRIDE(R_CLASS_REGWEN, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_REGWEN, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_REGWEN, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_REGWEN, ALERT_CLASSD): + val32 =3D R_CLASS_REGWEN_EN_MASK; + regs->classes[CLASS_SLOT(reg)].regwen &=3D val32; /* RW0C */ + break; + case CASE_STRIDE(R_CLASS_CTRL_SHADOWED, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_CTRL_SHADOWED, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_CTRL_SHADOWED, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_CTRL_SHADOWED, ALERT_CLASSD): + if (CHECK_REGWEN(reg, regs->classes[CLASS_SLOT(reg)].regwen)) { + val32 &=3D CLASS_CTRL_SHADOWED_MASK; + regs->classes[CLASS_SLOT(reg)].ctrl_shadowed =3D val32; + } + break; + case CASE_STRIDE(R_CLASS_CLR_REGWEN, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_CLR_REGWEN, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_CLR_REGWEN, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_CLR_REGWEN, ALERT_CLASSD): + val32 &=3D CLASS_CLR_REGWEN_EN_MASK; + regs->classes[CLASS_SLOT(reg)].clr_regwen &=3D val32; /* RW0C */ + break; + case CASE_STRIDE(R_CLASS_CLR_SHADOWED, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_CLR_SHADOWED, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_CLR_SHADOWED, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_CLR_SHADOWED, ALERT_CLASSD): + if (CHECK_REGWEN(reg, regs->classes[CLASS_SLOT(reg)].clr_regwen)) { + val32 &=3D CLASS_CLR_SHADOWED_EN_MASK; + regs->classes[CLASS_SLOT(reg)].clr_shadowed =3D val32; + } + break; + case CASE_STRIDE(R_CLASS_ACCUM_THRESH_SHADOWED, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_ACCUM_THRESH_SHADOWED, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_ACCUM_THRESH_SHADOWED, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_ACCUM_THRESH_SHADOWED, ALERT_CLASSD): + if (CHECK_REGWEN(reg, regs->classes[CLASS_SLOT(reg)].regwen)) { + val32 &=3D CLASS_ACCUM_THRESH_SHADOWED_MASK; + regs->classes[CLASS_SLOT(reg)].accum_thresh_shadowed =3D val32; + } + break; + case CASE_STRIDE(R_CLASS_TIMEOUT_CYC_SHADOWED, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_TIMEOUT_CYC_SHADOWED, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_TIMEOUT_CYC_SHADOWED, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_TIMEOUT_CYC_SHADOWED, ALERT_CLASSD): + if (CHECK_REGWEN(reg, regs->classes[CLASS_SLOT(reg)].regwen)) { + regs->classes[CLASS_SLOT(reg)].timeout_cyc_shadowed =3D val32; + } + break; + case CASE_STRIDE(R_CLASS_CRASHDUMP_TRIGGER_SHADOWED, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_CRASHDUMP_TRIGGER_SHADOWED, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_CRASHDUMP_TRIGGER_SHADOWED, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_CRASHDUMP_TRIGGER_SHADOWED, ALERT_CLASSD): + if (CHECK_REGWEN(reg, regs->classes[CLASS_SLOT(reg)].regwen)) { + val32 &=3D CLASS_CRASHDUMP_TRIGGER_SHADOWED_MASK; + regs->classes[CLASS_SLOT(reg)].crashdump_trigger_shadowed =3D = val32; + } + break; + case CASE_STRIDE(R_CLASS_PHASE0_CYC_SHADOWED, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_PHASE0_CYC_SHADOWED, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_PHASE0_CYC_SHADOWED, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_PHASE0_CYC_SHADOWED, ALERT_CLASSD): + if (CHECK_REGWEN(reg, regs->classes[CLASS_SLOT(reg)].regwen)) { + regs->classes[CLASS_SLOT(reg)].phase0_cyc_shadowed =3D val32; + } + break; + case CASE_STRIDE(R_CLASS_PHASE1_CYC_SHADOWED, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_PHASE1_CYC_SHADOWED, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_PHASE1_CYC_SHADOWED, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_PHASE1_CYC_SHADOWED, ALERT_CLASSD): + if (CHECK_REGWEN(reg, regs->classes[CLASS_SLOT(reg)].regwen)) { + regs->classes[CLASS_SLOT(reg)].phase1_cyc_shadowed =3D val32; + } + break; + case CASE_STRIDE(R_CLASS_PHASE2_CYC_SHADOWED, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_PHASE2_CYC_SHADOWED, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_PHASE2_CYC_SHADOWED, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_PHASE2_CYC_SHADOWED, ALERT_CLASSD): + if (CHECK_REGWEN(reg, regs->classes[CLASS_SLOT(reg)].regwen)) { + regs->classes[CLASS_SLOT(reg)].phase2_cyc_shadowed =3D val32; + } + break; + case CASE_STRIDE(R_CLASS_PHASE3_CYC_SHADOWED, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_PHASE3_CYC_SHADOWED, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_PHASE3_CYC_SHADOWED, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_PHASE3_CYC_SHADOWED, ALERT_CLASSD): + if (CHECK_REGWEN(reg, regs->classes[CLASS_SLOT(reg)].regwen)) { + regs->classes[CLASS_SLOT(reg)].phase3_cyc_shadowed =3D val32; + } + break; + case CASE_STRIDE(R_CLASS_ACCUM_CNT, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_ACCUM_CNT, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_ACCUM_CNT, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_ACCUM_CNT, ALERT_CLASSD): + case CASE_STRIDE(R_CLASS_ESC_CNT, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_ESC_CNT, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_ESC_CNT, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_ESC_CNT, ALERT_CLASSD): + case CASE_STRIDE(R_CLASS_STATE, ALERT_CLASSA): + case CASE_STRIDE(R_CLASS_STATE, ALERT_CLASSB): + case CASE_STRIDE(R_CLASS_STATE, ALERT_CLASSC): + case CASE_STRIDE(R_CLASS_STATE, ALERT_CLASSD): + qemu_log_mask(LOG_GUEST_ERROR, "R/O register 0x02%" HWADDR_PRIx "\= n", + addr); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\= n", + __func__, addr); + break; + } +}; + +static const MemoryRegionOps ot_alert_regs_ops =3D { + .read =3D &ot_alert_regs_read, + .write =3D &ot_alert_regs_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .impl.min_access_size =3D 4u, + .impl.max_access_size =3D 4u, +}; + +static void ot_alert_reset_enter(Object *obj, ResetType type) +{ + OtAlertClass *c =3D OT_ALERT_GET_CLASS(obj); + OtAlertState *s =3D OT_ALERT(obj); + + if (c->parent_phases.enter) { + c->parent_phases.enter(obj, type); + } + + OtAlertRegs *regs =3D s->regs; + memset(regs, 0, sizeof(*regs)); + + regs->ping.timer_regwen =3D 0x1u; + regs->ping.timeout_cyc_shadowed =3D 0x100u; + for (unsigned ix =3D 0; ix < PARAM_N_ALERTS; ix++) { + regs->alerts[ix].regwen =3D 0x1u; + } + for (unsigned ix =3D 0; ix < PARAM_N_LOC_ALERT; ix++) { + regs->loc_alerts[ix].regwen =3D 0x1u; + } + for (unsigned ix =3D 0; ix < PARAM_N_CLASSES; ix++) { + regs->classes[ix].regwen =3D 0x1u; + regs->classes[ix].ctrl_shadowed =3D 0x393cu; + regs->classes[ix].clr_regwen =3D 0x1u; + } + + ot_alert_update_irqs(s); +} + +static void ot_alert_init(Object *obj) +{ + OtAlertState *s =3D OT_ALERT(obj); + + memory_region_init_io(&s->mmio, obj, &ot_alert_regs_ops, s, TYPE_OT_AL= ERT, + REGS_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->mmio); + + s->regs =3D g_new0(OtAlertRegs, 1); + + for (unsigned ix =3D 0; ix < ARRAY_SIZE(s->irqs); ix++) { + ibex_sysbus_init_irq(obj, &s->irqs[ix]); + } +} + +static void ot_alert_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + OtAlertClass *ac =3D OT_ALERT_CLASS(klass); + resettable_class_set_parent_phases(rc, &ot_alert_reset_enter, NULL, NU= LL, + &ac->parent_phases); +} + +static const TypeInfo ot_alert_info =3D { + .name =3D TYPE_OT_ALERT, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(OtAlertState), + .instance_init =3D &ot_alert_init, + .class_size =3D sizeof(OtAlertClass), + .class_init =3D &ot_alert_class_init, +}; + +static void ot_alert_register_types(void) +{ + type_register_static(&ot_alert_info); +} + +type_init(ot_alert_register_types) diff --git a/hw/opentitan/trace-events b/hw/opentitan/trace-events index 695debd380..39dea92d2b 100644 --- a/hw/opentitan/trace-events +++ b/hw/opentitan/trace-events @@ -1 +1,6 @@ # OpenTitan EarlGrey Trace Events + +# ot_alert.c + +ot_alert_io_read_out(unsigned int addr, uint64_t val, uint64_t pc) "addr= =3D0x%02x, val=3D0x%" PRIx64 ", pc=3D0x%" PRIx64 +ot_alert_io_write(unsigned int addr, uint64_t val, uint64_t pc) "addr=3D0x= %02x, val=3D0x%" PRIx64 ", pc=3D0x%" PRIx64 diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 76588c43ae..8fdb048ea7 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -17,6 +17,7 @@ config OT_EARLGREY default y select IBEX select IBEX_COMMON + select OT_ALERT select SIFIVE_PLIC =20 config MICROCHIP_PFSOC diff --git a/hw/riscv/ibex_common.c b/hw/riscv/ibex_common.c index 6b53662a5b..dc0ae79777 100644 --- a/hw/riscv/ibex_common.c +++ b/hw/riscv/ibex_common.c @@ -1,5 +1,5 @@ /* - * QEMU RISC-V Helpers for LowRISC Ibex Demo System & OpenTitan EarlGrey + * QEMU RISC-V Helpers for LowRISC OpenTitan EarlGrey and related systems * * Copyright (c) 2022-2023 Rivos, Inc. * diff --git a/hw/riscv/ot_earlgrey.c b/hw/riscv/ot_earlgrey.c index 77fb1b207c..ccb9ad0e7e 100644 --- a/hw/riscv/ot_earlgrey.c +++ b/hw/riscv/ot_earlgrey.c @@ -24,6 +24,7 @@ #include "hw/core/boards.h" #include "hw/intc/sifive_plic.h" #include "hw/misc/unimp.h" +#include "hw/opentitan/ot_alert.h" #include "hw/core/qdev-properties.h" #include "hw/riscv/ibex_common.h" #include "hw/riscv/ot_earlgrey.h" @@ -261,12 +262,16 @@ static const IbexDeviceDef ot_earlgrey_soc_devices[] = =3D { ), }, [OT_EARLGREY_SOC_DEV_ALERT_HANDLER] =3D { - .type =3D TYPE_UNIMPLEMENTED_DEVICE, - .name =3D "ot-alert_handler", - .cfg =3D &ibex_unimp_configure, + .type =3D TYPE_OT_ALERT, .memmap =3D MEMMAPENTRIES( { 0x40150000u, 0x800u } ), + .gpio =3D IBEXGPIOCONNDEFS( + OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 127), + OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 128), + OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(0, PLIC, 129), + OT_EARLGREY_SOC_GPIO_SYSBUS_IRQ(1, PLIC, 130) + ), }, [OT_EARLGREY_SOC_DEV_SPI_HOST0] =3D { .type =3D TYPE_UNIMPLEMENTED_DEVICE, diff --git a/include/hw/opentitan/ot_alert.h b/include/hw/opentitan/ot_aler= t.h new file mode 100644 index 0000000000..d68f4c9e6e --- /dev/null +++ b/include/hw/opentitan/ot_alert.h @@ -0,0 +1,23 @@ +/* + * QEMU OpenTitan Alert handler device + * + * Copyright (c) 2022-2025 Rivos, Inc. + * + * Author(s): + * Emmanuel Blot + * Lo=C3=AFc Lefort + * + * SPDX-License-Identifier: MIT + */ + +#ifndef HW_OPENTITAN_OT_ALERT +#define HW_OPENTITAN_OT_ALERT + +#include "qom/object.h" + +#define OPENTITAN_DEVICE_ALERT "ot-alert" + +#define TYPE_OT_ALERT "ot-alert" +OBJECT_DECLARE_TYPE(OtAlertState, OtAlertClass, OT_ALERT) + +#endif /* HW_OPENTITAN_OT_ALERT */ diff --git a/include/hw/riscv/ibex_irq.h b/include/hw/riscv/ibex_irq.h index 22ccff6d5e..c1e11e20f6 100644 --- a/include/hw/riscv/ibex_irq.h +++ b/include/hw/riscv/ibex_irq.h @@ -12,9 +12,9 @@ =20 #include "qemu/osdep.h" #include "qom/object.h" -#include "hw/irq.h" -#include "hw/qdev-core.h" -#include "hw/sysbus.h" +#include "hw/core/irq.h" +#include "hw/core/qdev.h" +#include "hw/core/sysbus.h" =20 =20 /** Simple IRQ wrapper to limit propagation of no-change calls */ --=20 2.49.1