From nobody Fri Oct 23 14:30:37 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=cdac.in ARC-Seal: i=1; a=rsa-sha256; t=1792138204; cv=none; d=zohomail.com; s=zohoarc; b=esFtY/l3nlCcnuO7TddjPUo9jtW9aKH9+8GDPvy9FsorPmE8Ar9WTK4Krf2vA1Mdd6iSVXpTVKLJJ638dGqtSc2aXCEYJrOdVLxzS5aIMI80GnxyzpT4zz2VZlkL8ZD3nCMxYjk4SbgeRyE6Vdnb422/fpQXtqn4gf5XLkhAFXc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792138204; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Cchf6L/xWsO/4eF++LBRe1rUWbyM6s8D7PefONWKShs=; b=MyFNiSjrsODnuaDIJLL/QaiTozE6Dt7fkdHE8c48ZRJHTJg/ePRNSwaTM+kthY9dNbELfznzpRbJNaWy8sCMSTkZOgHJqi5LbbePwe/a5IL1Hf0zWbUs0NFi8pbzPcWFFFBmLU7MZPVAfW/oUwG6ZsyQcJpztiRmD0UvM+thCf8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792138201029510.04818688127625; Fri, 16 Oct 2026 01:10:01 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xHczb-0003ry-SW; Fri, 16 Oct 2026 04:08:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xHczG-0003o9-CH; Fri, 16 Oct 2026 04:08:24 -0400 Received: from mailsender.cdac.in ([196.1.113.117] helo=mailsender-core1.pune.cdac.in) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xHczA-0005w6-MU; Fri, 16 Oct 2026 04:08:21 -0400 Received: from mscr-int2.pune.cdac.in (mscr-int2.pune.cdac.in [10.208.193.12]) by mailsender.cdac.in (8.15.2/8.15.2/Debian-22ubuntu3) with ESMTP id 69G87vhZ3825194; Fri, 16 Oct 2026 13:37:58 +0530 Received: from mailgw-cip.pune.cdac.in (mscr-haproxy.pune.cdac.in [10.208.193.46]) by mscr-int2.pune.cdac.in (Postfix) with ESMTP id 79AFF10014455; Fri, 16 Oct 2026 13:37:46 +0530 (IST) Received: from hdg164.tvm.cdac.in (hd_hdg164.tvm.cdac.in [10.176.18.107]) (Authenticated sender: karthika.b@cdac.in) by mailgw-cip.pune.cdac.in (Postfix) with ESMTPSA id 3E31A14E17D2; Fri, 16 Oct 2026 13:37:46 +0530 (IST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cdac.in; s=default; t=1792138078; bh=fhREqVjIOaSR1eiA6lBky1Aw8am+YPwicWDTrG5TP9A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bSN+dHDkGmG+SMb+/wZxeOwP8ZTAEUkgiOg6NxbKoIcH33av6QQFiv4T+f/Pp4DsU r/bUvH7nrzO2rA07pVNrUQUC1WbXbJ5MrMEUviHsCej2KN25x2j0WXHVlQeg19HwQK KSWR2uaqrZWBPPcZyRP5OCOG76nuBYvvspl6b054= X-Auth: karthika.b@cdac.in From: Karthika B To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, sreenadh@cdac.in, raokk@cdac.in, Karthika B , Paolo Bonzini Subject: [PATCH 1/7] hw/intc: Add CDAC VEGA PLIC device model Date: Fri, 16 Oct 2026 13:37:01 +0530 Message-ID: <20261016080709.17331-2-karthika.b@cdac.in> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20261016080709.17331-1-karthika.b@cdac.in> References: <385625713.441366.1761727810206@webmail2.cdac.in> <20261016080709.17331-1-karthika.b@cdac.in> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CDAC-PUNE-MailScanner-Information: Please contact the ISP for more information X-CDAC-PUNE-MailScanner-ID: 79AFF10014455.A03F8 X-CDAC-PUNE-MailScanner: Found to be clean X-CDAC-PUNE-MailScanner-SpamCheck: not spam, SpamAssassin (not cached, score=-0.999, required 6, ALL_TRUSTED -1.00, URIBL_BLOCKED 0.00) X-CDAC-PUNE-MailScanner-From: karthika.b@cdac.in 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=lists1p.gnu.org; Received-SPF: pass client-ip=196.1.113.117; envelope-from=karthika.b@cdac.in; helo=mailsender-core1.pune.cdac.in X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @cdac.in) X-ZM-MESSAGEID: 1792138206625158500 Content-Type: text/plain; charset="utf-8" Signed-off-by: Karthika B --- hw/intc/Kconfig | 7 + hw/intc/meson.build | 2 + hw/intc/vega_plic.c | 517 ++++++++++++++++++++++++++++++++++++ include/hw/intc/vega_plic.h | 87 ++++++ 4 files changed, 613 insertions(+) create mode 100644 hw/intc/vega_plic.c create mode 100644 include/hw/intc/vega_plic.h diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig index 636d00b7e8..942ec4d0e5 100644 --- a/hw/intc/Kconfig +++ b/hw/intc/Kconfig @@ -117,3 +117,10 @@ config LOONGARCH_EXTIOI =20 config LOONGARCH_DINTC bool + +config VEGA_ACLINT + bool + +config VEGA_PLIC + bool + select MSI_NONBROKEN diff --git a/hw/intc/meson.build b/hw/intc/meson.build index fac2d228f9..4c9eb0e9c4 100644 --- a/hw/intc/meson.build +++ b/hw/intc/meson.build @@ -68,6 +68,8 @@ specific_ss.add(when: 'CONFIG_RISCV_APLIC', if_true: file= s('riscv_aplic.c')) specific_ss.add(when: 'CONFIG_RISCV_IMSIC', if_true: files('riscv_imsic.c'= )) specific_ss.add(when: 'CONFIG_SIFIVE_PLIC', if_true: files('sifive_plic.c'= )) specific_ss.add(when: 'CONFIG_XICS', if_true: files('xics.c', 'xive2.c')) +specific_ss.add(when: 'CONFIG_VEGA_ACLINT', if_true: files('vega_aclint.c'= )) +specific_ss.add(when: 'CONFIG_VEGA_PLIC', if_true: files('vega_plic.c')) specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XICS'], if_true: files('xics_kvm.c')) specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('xics_spapr.c', 'sp= apr_xive.c')) diff --git a/hw/intc/vega_plic.c b/hw/intc/vega_plic.c new file mode 100644 index 0000000000..7ad58b0023 --- /dev/null +++ b/hw/intc/vega_plic.c @@ -0,0 +1,517 @@ +/* + * VEGA PLIC (Platform-Level Interrupt Controller) emulation + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2025 C-DAC (Centre for Development of Advanced Computing) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/error-report.h" +#include "hw/core/sysbus.h" +#include "hw/core/qdev-properties.h" +#include "hw/intc/vega_plic.h" +#include "target/riscv/cpu.h" +#include "migration/vmstate.h" +#include "hw/core/irq.h" +#include "system/kvm.h" + +static bool addr_between(uint32_t addr, uint32_t base, uint32_t num) +{ + return addr >=3D base && addr - base < num; +} + +static PLICMode char_to_mode(char c) +{ + switch (c) { + case 'U': return PLICMode_U; + case 'S': return PLICMode_S; + case 'M': return PLICMode_M; + default: + error_report("plic: invalid mode '%c'", c); + exit(1); + } +} + +static uint32_t atomic_set_masked(uint32_t *a, uint32_t mask, uint32_t val= ue) +{ + uint32_t old, new, cmp =3D qatomic_read(a); + + do { + old =3D cmp; + new =3D (old & ~mask) | (value & mask); + cmp =3D qatomic_cmpxchg(a, old, new); + } while (old !=3D cmp); + + return old; +} + +static void vega_plic_set_pending(VegaPLICState *plic, int irq, bool level) +{ + atomic_set_masked(&plic->pending[irq >> 5], 1 << (irq & 31), -!!level); +} + +static void vega_plic_set_claimed(VegaPLICState *plic, int irq, bool level) +{ + atomic_set_masked(&plic->claimed[irq >> 5], 1 << (irq & 31), -!!level); +} + +static uint32_t vega_plic_claimed(VegaPLICState *plic, uint32_t addrid) +{ + uint32_t max_irq =3D 0; + uint32_t max_prio =3D plic->target_priority[addrid]; + int i, j; + int num_irq_in_word =3D 32; + + for (i =3D 0; i < plic->bitfield_words; i++) { + uint32_t pending_enabled_not_claimed =3D + (plic->pending[i] & ~plic->claimed[i]) & + plic->enable[addrid * plic->bitfield_words + i= ]; + + if (!pending_enabled_not_claimed) { + continue; + } + + if (i =3D=3D (plic->bitfield_words - 1)) { + /* + * If plic->num_sources is not multiple of 32, num-of-irq in l= ast + * word is not 32. Compute the num-of-irq of last word to avoid + * out-of-bound access of source_priority array. + */ + num_irq_in_word =3D plic->num_sources - ((plic->bitfield_words= - 1) << 5); + } + + for (j =3D 0; j < num_irq_in_word; j++) { + int irq =3D (i << 5) + j; + uint32_t prio =3D plic->source_priority[irq]; + int enabled =3D pending_enabled_not_claimed & (1 << j); + + if (enabled && prio > max_prio) { + max_irq =3D irq; + max_prio =3D prio; + } + } + } + + return max_irq; +} + +static void vega_plic_update(VegaPLICState *plic) +{ + int addrid; + + /* raise irq on harts where this irq is enabled */ + for (addrid =3D 0; addrid < plic->num_addrs; addrid++) { + uint32_t hartid =3D plic->addr_config[addrid].hartid; + PLICMode mode =3D plic->addr_config[addrid].mode; + bool level =3D !!vega_plic_claimed(plic, addrid); + + switch (mode) { + case PLICMode_M: + qemu_set_irq(plic->m_external_irqs[hartid - plic->hartid_base]= , level); + break; + case PLICMode_S: + qemu_set_irq(plic->s_external_irqs[hartid - plic->hartid_base]= , level); + break; + default: + break; + } + } +} + +static const uint32_t vega_priority_regs =3D 0x10; +static const uint32_t vega_pending_regs =3D 0x4; +static const uint32_t vega_enable_reg_size =3D 0x100; + +static uint64_t vega_plic_read(void *opaque, hwaddr addr, unsigned size) +{ + VegaPLICState *plic =3D opaque; + + if (addr_between(addr, plic->priority_base, vega_priority_regs << 2)) { + /* Between 0x00 and 0x40 (Write only) */ + uint32_t irq =3D (addr >> 2) * 8; + uint32_t result =3D 0; + + for (uint32_t i =3D 0; i < 8; i++) { + if (irq !=3D 0) { + result |=3D (plic->source_priority[irq] & 0xf) << (i * 4); + } + irq++; + } + return result; + } else if (addr_between(addr, plic->pending_base, + vega_pending_regs << 2)) { + /* Between 0x80 and 0x90 (Read only) */ + uint32_t word =3D (addr - plic->pending_base) >> 2; + + return plic->pending[word]; + } else if (addr_between(addr, plic->enable_base, vega_enable_reg_size)= ) { + /* Between 0x100 and 0x200 */ + uint32_t addrid =3D (addr - plic->enable_base) / plic->enable_stri= de; + uint32_t wordid =3D (addr - plic->enable_base - + (addrid * plic->enable_stride)) >> 2; + + if (wordid < plic->bitfield_words) { + return plic->enable[addrid * plic->bitfield_words + wordid]; + } + } else if (addr_between(addr, plic->context_base, + plic->num_addrs * plic->context_stride)) { + uint32_t addrid =3D (addr - plic->context_base) / plic->context_st= ride; + uint32_t contextid =3D (addr & (plic->context_stride - 1)); + + if (contextid =3D=3D 0) { + return plic->target_priority[addrid]; + } else if (contextid =3D=3D 4) { + uint32_t max_irq =3D vega_plic_claimed(plic, addrid); + + if (max_irq) { + vega_plic_set_pending(plic, max_irq, false); + vega_plic_set_claimed(plic, max_irq, true); + } + + vega_plic_update(plic); + return max_irq; + } + } + + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Invalid register read 0x%" HWADDR_PRIx "\n", + __func__, addr); + return 0; +} + +static void vega_plic_write(void *opaque, hwaddr addr, uint64_t value, + unsigned size) +{ + VegaPLICState *plic =3D opaque; + + if (addr_between(addr, plic->priority_base, vega_priority_regs << 2)) { + /* Between 0x00 and 0x40 (Write only) */ + uint32_t irq =3D (addr >> 2) * 8; + + for (uint32_t i =3D 0; i < 8; i++) { + if (irq !=3D 0) { + plic->source_priority[irq] =3D (value >> (i * 4)) & 0xff; + vega_plic_update(plic); + } + irq++; + } + } else if (addr_between(addr, plic->pending_base, + vega_pending_regs << 2)) { + /* Between 0x80 and 0x90 (Read only) */ + qemu_log_mask(LOG_GUEST_ERROR, + "%s: invalid pending write: 0x%" HWADDR_PRIx "", + __func__, addr); + } else if (addr_between(addr, plic->enable_base, vega_enable_reg_size)= ) { + /* Between 0x100 and 0x200 */ + uint32_t addrid =3D (addr - plic->enable_base) / plic->enable_stri= de; + uint32_t wordid =3D (addr - plic->enable_base - + (addrid * plic->enable_stride)) >> 2; + + if (wordid < plic->bitfield_words) { + plic->enable[addrid * plic->bitfield_words + wordid] =3D value; + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Invalid enable write 0x%" HWADDR_PRIx "\n", + __func__, addr); + } + } else if (addr_between(addr, plic->context_base, + plic->num_addrs * plic->context_stride)) { + uint32_t addrid =3D (addr - plic->context_base) / plic->context_st= ride; + uint32_t contextid =3D (addr & (plic->context_stride - 1)); + + if (contextid =3D=3D 0) { + if (value <=3D plic->num_priorities) { + plic->target_priority[addrid] =3D value; + vega_plic_update(plic); + } + } else if (contextid =3D=3D 4) { + if (value < plic->num_sources) { + vega_plic_set_claimed(plic, value, false); + vega_plic_update(plic); + } + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Invalid context write 0x%" HWADDR_PRIx "\n", + __func__, addr); + } + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: Invalid register write 0x%" HWADDR_PRIx "\n", + __func__, addr); + } +} + +static const MemoryRegionOps vega_plic_ops =3D { + .read =3D vega_plic_read, + .write =3D vega_plic_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 4 + } +}; + +static void vega_plic_reset(DeviceState *dev) +{ + VegaPLICState *s =3D VEGA_PLIC(dev); + int i; + + memset(s->source_priority, 0, sizeof(uint32_t) * s->num_sources); + memset(s->target_priority, 0, sizeof(uint32_t) * s->num_addrs); + memset(s->pending, 0, sizeof(uint32_t) * s->bitfield_words); + memset(s->claimed, 0, sizeof(uint32_t) * s->bitfield_words); + memset(s->enable, 0, sizeof(uint32_t) * s->num_enables); + + for (i =3D 0; i < s->num_harts; i++) { + qemu_set_irq(s->m_external_irqs[i], 0); + qemu_set_irq(s->s_external_irqs[i], 0); + } +} + +/* + * parse PLIC hart/mode address offset config + * + * "M" 1 hart with M mode + * "MS,MS" 2 harts, 0-1 with M and S mode + * "M,MS,MS,MS,MS" 5 harts, 0 with M mode, 1-5 with M and S mode + */ +static void parse_hart_config(VegaPLICState *plic) +{ + int addrid, hartid, modes, m; + const char *p; + char c; + + /* count and validate hart/mode combinations */ + addrid =3D 0, hartid =3D 0, modes =3D 0; + p =3D plic->hart_config; + while ((c =3D *p++)) { + if (c =3D=3D ',') { + if (modes) { + addrid +=3D ctpop8(modes); + hartid++; + modes =3D 0; + } + } else { + m =3D 1 << char_to_mode(c); + if (modes =3D=3D (modes | m)) { + error_report("plic: duplicate mode '%c' in config: %s", + c, plic->hart_config); + exit(1); + } + modes |=3D m; + } + } + if (modes) { + addrid +=3D ctpop8(modes); + hartid++; + modes =3D 0; + } + + plic->num_addrs =3D addrid; + plic->num_harts =3D hartid; + + /* store hart/mode combinations */ + plic->addr_config =3D g_new(PLICAddr, plic->num_addrs); + addrid =3D 0, hartid =3D plic->hartid_base; + p =3D plic->hart_config; + while ((c =3D *p++)) { + if (c =3D=3D ',') { + if (modes) { + hartid++; + modes =3D 0; + } + } else { + m =3D char_to_mode(c); + plic->addr_config[addrid].addrid =3D addrid; + plic->addr_config[addrid].hartid =3D hartid; + plic->addr_config[addrid].mode =3D m; + modes |=3D (1 << m); + addrid++; + } + } +} + +static void vega_plic_irq_request(void *opaque, int irq, int level) +{ + VegaPLICState *s =3D opaque; + + if (level > 0) { + vega_plic_set_pending(s, irq, true); + vega_plic_update(s); + } +} + +static void vega_plic_realize(DeviceState *dev, Error **errp) +{ + VegaPLICState *s =3D VEGA_PLIC(dev); + int i; + + memory_region_init_io(&s->mmio, OBJECT(dev), &vega_plic_ops, s, + TYPE_VEGA_PLIC, s->aperture_size); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); + + parse_hart_config(s); + + if (!s->num_sources) { + error_setg(errp, "plic: invalid number of interrupt sources"); + return; + } + + s->bitfield_words =3D (s->num_sources + 31) >> 5; + s->num_enables =3D s->bitfield_words * s->num_addrs; + s->source_priority =3D g_new0(uint32_t, s->num_sources); + s->target_priority =3D g_new0(uint32_t, s->num_addrs); + s->pending =3D g_new0(uint32_t, s->bitfield_words); + s->claimed =3D g_new0(uint32_t, s->bitfield_words); + s->enable =3D g_new0(uint32_t, s->num_enables); + + qdev_init_gpio_in(dev, vega_plic_irq_request, s->num_sources); + + s->s_external_irqs =3D g_malloc(sizeof(qemu_irq) * s->num_harts); + qdev_init_gpio_out(dev, s->s_external_irqs, s->num_harts); + + s->m_external_irqs =3D g_malloc(sizeof(qemu_irq) * s->num_harts); + qdev_init_gpio_out(dev, s->m_external_irqs, s->num_harts); + + /* + * We can't allow the supervisor to control SEIP as this would allow t= he + * supervisor to clear a pending external interrupt which will result = in + * lost a interrupt in the case a PLIC is attached. The SEIP bit must = be + * hardware controlled when a PLIC is attached. + */ + for (i =3D 0; i < s->num_harts; i++) { + RISCVCPU *cpu =3D RISCV_CPU(qemu_get_cpu(s->hartid_base + i)); + if (riscv_cpu_claim_interrupts(cpu, MIP_SEIP) < 0) { + error_setg(errp, "SEIP already claimed"); + return; + } + } + +} + +static const VMStateDescription vmstate_vega_plic =3D { + .name =3D "riscv_vega_plic", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (const VMStateField[]) { + VMSTATE_VARRAY_UINT32(source_priority, VegaPLICState, + num_sources, 0, + vmstate_info_uint32, uint32_t), + VMSTATE_VARRAY_UINT32(target_priority, VegaPLICState, + num_addrs, 0, + vmstate_info_uint32, uint32_t), + VMSTATE_VARRAY_UINT32(pending, VegaPLICState, bitfield_words, = 0, + vmstate_info_uint32, uint32_t), + VMSTATE_VARRAY_UINT32(claimed, VegaPLICState, bitfield_words, = 0, + vmstate_info_uint32, uint32_t), + VMSTATE_VARRAY_UINT32(enable, VegaPLICState, num_enables, 0, + vmstate_info_uint32, uint32_t), + VMSTATE_END_OF_LIST() + } +}; + +static const Property vega_plic_properties[] =3D { + DEFINE_PROP_STRING("hart-config", VegaPLICState, hart_config), + DEFINE_PROP_UINT32("hartid-base", VegaPLICState, hartid_base, 0), + /* number of interrupt sources including interrupt source 0 */ + DEFINE_PROP_UINT32("num-sources", VegaPLICState, num_sources, 1), + DEFINE_PROP_UINT32("num-priorities", VegaPLICState, num_priorities, 0), + /* interrupt priority register base starting from source 0 */ + DEFINE_PROP_UINT32("priority-base", VegaPLICState, priority_base, 0), + DEFINE_PROP_UINT32("pending-base", VegaPLICState, pending_base, 0), + DEFINE_PROP_UINT32("enable-base", VegaPLICState, enable_base, 0), + DEFINE_PROP_UINT32("enable-stride", VegaPLICState, enable_stride, 0), + DEFINE_PROP_UINT32("context-base", VegaPLICState, context_base, 0), + DEFINE_PROP_UINT32("context-stride", VegaPLICState, context_stride, 0), + DEFINE_PROP_UINT32("aperture-size", VegaPLICState, aperture_size, 0), +}; + +static void vega_plic_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + device_class_set_legacy_reset(dc, vega_plic_reset); + device_class_set_props(dc, vega_plic_properties); + dc->realize =3D vega_plic_realize; + dc->vmsd =3D &vmstate_vega_plic; +} + +static const TypeInfo vega_plic_info =3D { + .name =3D TYPE_VEGA_PLIC, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(VegaPLICState), + .class_init =3D vega_plic_class_init, +}; + +static void vega_plic_register_types(void) +{ + type_register_static(&vega_plic_info); +} + +type_init(vega_plic_register_types) + +/* + * Create PLIC device. + */ +DeviceState *vega_plic_create(hwaddr addr, char *hart_config, + uint32_t num_harts, + uint32_t hartid_base, uint32_t num_sources, + uint32_t num_priorities, uint32_t priority_base, + uint32_t pending_base, uint32_t enable_base, + uint32_t enable_stride, uint32_t context_base, + uint32_t context_stride, uint32_t aperture_size) +{ + DeviceState *dev =3D qdev_new(TYPE_VEGA_PLIC); + int i; + VegaPLICState *plic; + + assert(enable_stride =3D=3D (enable_stride & -enable_stride)); + assert(context_stride =3D=3D (context_stride & -context_stride)); + qdev_prop_set_string(dev, "hart-config", hart_config); + qdev_prop_set_uint32(dev, "hartid-base", hartid_base); + qdev_prop_set_uint32(dev, "num-sources", num_sources); + qdev_prop_set_uint32(dev, "num-priorities", num_priorities); + qdev_prop_set_uint32(dev, "priority-base", priority_base); + qdev_prop_set_uint32(dev, "pending-base", pending_base); + qdev_prop_set_uint32(dev, "enable-base", enable_base); + qdev_prop_set_uint32(dev, "enable-stride", enable_stride); + qdev_prop_set_uint32(dev, "context-base", context_base); + qdev_prop_set_uint32(dev, "context-stride", context_stride); + qdev_prop_set_uint32(dev, "aperture-size", aperture_size); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); + + plic =3D VEGA_PLIC(dev); + + for (i =3D 0; i < plic->num_addrs; i++) { + int cpu_num =3D plic->addr_config[i].hartid; + CPUState *cpu =3D qemu_get_cpu(cpu_num); + + if (plic->addr_config[i].mode =3D=3D PLICMode_M) { + qdev_connect_gpio_out(dev, cpu_num - hartid_base + num_harts, + qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT)= ); + } + if (plic->addr_config[i].mode =3D=3D PLICMode_S) { + qdev_connect_gpio_out(dev, cpu_num - hartid_base, + qdev_get_gpio_in(DEVICE(cpu), IRQ_S_EXT)= ); + } + } + + return dev; +} diff --git a/include/hw/intc/vega_plic.h b/include/hw/intc/vega_plic.h new file mode 100644 index 0000000000..f26d91a2a3 --- /dev/null +++ b/include/hw/intc/vega_plic.h @@ -0,0 +1,87 @@ +/* + * VEGA PLIC (Platform-Level Interrupt Controller) interface + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2025 C-DAC (Centre for Development of Advanced Computing) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + */ + +#ifndef HW_VEGA_PLIC_H +#define HW_VEGA_PLIC_H + +#include "hw/core/sysbus.h" +#include "qom/object.h" + +#define TYPE_VEGA_PLIC "riscv.vega.plic" + +typedef struct VegaPLICState VegaPLICState; +DECLARE_INSTANCE_CHECKER(VegaPLICState, VEGA_PLIC, + TYPE_VEGA_PLIC) + +typedef enum PLICMode { + PLICMode_U, + PLICMode_S, + PLICMode_M +} PLICMode; + +typedef struct PLICAddr { + uint32_t addrid; + uint32_t hartid; + PLICMode mode; +} PLICAddr; + +struct VegaPLICState { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + MemoryRegion mmio; + uint32_t num_addrs; + uint32_t num_harts; + uint32_t bitfield_words; + uint32_t num_enables; + PLICAddr *addr_config; + uint32_t *source_priority; + uint32_t *target_priority; + uint32_t *pending; + uint32_t *claimed; + uint32_t *enable; + + /* config */ + char *hart_config; + uint32_t hartid_base; + uint32_t num_sources; + uint32_t num_priorities; + uint32_t priority_base; + uint32_t pending_base; + uint32_t enable_base; + uint32_t enable_stride; + uint32_t context_base; + uint32_t context_stride; + uint32_t aperture_size; + + qemu_irq *m_external_irqs; + qemu_irq *s_external_irqs; +}; + +DeviceState *vega_plic_create(hwaddr addr, char *hart_config, + uint32_t num_harts, + uint32_t hartid_base, uint32_t num_sources, + uint32_t num_priorities, uint32_t priority_base, + uint32_t pending_base, uint32_t enable_base, + uint32_t enable_stride, uint32_t context_base, + uint32_t context_stride, uint32_t aperture_size); + +#endif --=20 2.43.0 ---------------------------------------------------------------------------= --------------------------------- [ C-DAC is on Social-Media too. Kindly follow us at: Facebook: https://www.facebook.com/CDACINDIA & Twitter: @cdacindia ] This e-mail is for the sole use of the intended recipient(s) and may contain confidential and privileged information. If you are not the intended recipient, please contact the sender by reply e-mail and destroy all copies and the original message. Any unauthorized review, use, disclosure, dissemination, forwarding, printing or copying of this email is strictly prohibited and appropriate legal action will be taken. ---------------------------------------------------------------------------= --------------------------------- From nobody Fri Oct 23 14:30:37 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=cdac.in ARC-Seal: i=1; a=rsa-sha256; t=1792138202; cv=none; d=zohomail.com; s=zohoarc; b=E4E7st5/0wSfSyX/xwfyPiJ3/pwvb0y29oRby9rQID5xUSlO7z2bW7Byl709CepogtqkVaexsp5B8lrpIUA0ba/ATBWoL9djfMtE0AX0aeYy27ZGqm2JUxeU3TG33yTosJ687pg8mZ2F3pnMu61U9xKPx4KREc9SQdbvafEUb3k= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792138202; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=CjVlhc5qJzfQOGuT6RFh8gG5U63wP6Jok5/UhMgD7d8=; b=QT4Ko/JnIh7gfjHHuem0KaFTvQCS4b4XOZRbFhk59AIZnsu3PNm/Zq9cvuIthcdzimgFq8w9PKvK50QeesK2ubN2TvV7X9nh4LdJp6lQvu/q5w32cszfuZSeqL6KIdgyEpmL/XfK3Mgj2m1FtMAYDfFsbvkWNbvpQzch+BMNV8E= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792138201332459.3918221970047; Fri, 16 Oct 2026 01:10:01 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xHczb-0003rx-Rz; Fri, 16 Oct 2026 04:08:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xHczG-0003oA-Cu; Fri, 16 Oct 2026 04:08:24 -0400 Received: from mailsender.cdac.in ([196.1.113.117] helo=mailsender-core1.pune.cdac.in) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xHczA-0005wZ-Np; Fri, 16 Oct 2026 04:08:21 -0400 Received: from mscr-int.pune.cdac.in (mscr-int.pune.cdac.in [10.208.193.2]) by mailsender.cdac.in (8.15.2/8.15.2/Debian-22ubuntu3) with ESMTP id 69G888PO3825296; Fri, 16 Oct 2026 13:38:09 +0530 Received: from mailgw-cip.pune.cdac.in (mscr-haproxy.pune.cdac.in [10.208.193.46]) by mscr-int.pune.cdac.in (Postfix) with ESMTP id A7AD81000701F; Fri, 16 Oct 2026 13:37:47 +0530 (IST) Received: from hdg164.tvm.cdac.in (hd_hdg164.tvm.cdac.in [10.176.18.107]) (Authenticated sender: karthika.b@cdac.in) by mailgw-cip.pune.cdac.in (Postfix) with ESMTPSA id 6D99114E17D2; Fri, 16 Oct 2026 13:37:47 +0530 (IST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cdac.in; s=default; t=1792138089; bh=d7C0HqV9r3bcJ9cU7H6GV06qqkPVxW+XZtwdXyCLWks=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JAWRnCUONCmtdTQrx2JbwOVPRmtNofEZKI23maqsAA8SbzvbRcevzrcpYe43rdfR7 Ox3BIS9td/UH4q+mGdj2t6Y6lMa9Lv1LgxNwrpnnv49GCTpNxMr0UuYFdYX++b8Fbo XJOJYztjDrD3zhVvdkNVaeUx2vC+sa36DSiLiBJw= X-Auth: karthika.b@cdac.in From: Karthika B To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, sreenadh@cdac.in, raokk@cdac.in, Karthika B Subject: [PATCH 2/7] hw/intc: Add CDAC VEGA ACLINT device model Date: Fri, 16 Oct 2026 13:37:02 +0530 Message-ID: <20261016080709.17331-3-karthika.b@cdac.in> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20261016080709.17331-1-karthika.b@cdac.in> References: <385625713.441366.1761727810206@webmail2.cdac.in> <20261016080709.17331-1-karthika.b@cdac.in> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-CDAC-PUNE-MailScanner-Information: Please contact the ISP for more information X-CDAC-PUNE-MailScanner-ID: A7AD81000701F.AF7A2 X-CDAC-PUNE-MailScanner: Found to be clean X-CDAC-PUNE-MailScanner-SpamCheck: not spam, SpamAssassin (not cached, score=-2.9, required 6, autolearn=not spam, ALL_TRUSTED -1.00, BAYES_00 -1.90) X-CDAC-PUNE-MailScanner-From: karthika.b@cdac.in 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=lists1p.gnu.org; Received-SPF: pass client-ip=196.1.113.117; envelope-from=karthika.b@cdac.in; helo=mailsender-core1.pune.cdac.in X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @cdac.in) X-ZM-MESSAGEID: 1792138204666158500 Signed-off-by: Karthika B --- hw/intc/vega_aclint.c | 668 ++++++++++++++++++++++++++++++++++ include/hw/intc/vega_aclint.h | 84 +++++ 2 files changed, 752 insertions(+) create mode 100644 hw/intc/vega_aclint.c create mode 100644 include/hw/intc/vega_aclint.h diff --git a/hw/intc/vega_aclint.c b/hw/intc/vega_aclint.c new file mode 100644 index 0000000000..2583813a7c --- /dev/null +++ b/hw/intc/vega_aclint.c @@ -0,0 +1,668 @@ +/* + * VEGA ACLINT (Advanced Core Local Interruptor) emulation + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2025 C-DAC (Centre for Development of Advanced Computing) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "hw/core/sysbus.h" +#include "target/riscv/cpu.h" +#include "target/riscv/time_helper.h" +#include "hw/core/qdev-properties.h" +#include "hw/intc/vega_aclint.h" +#include "qemu/timer.h" +#include "hw/core/irq.h" +#include "migration/vmstate.h" + +typedef struct vega_aclint_mtimer_callback { + VEGAAclintMTimerState *s; + int num; +} vega_aclint_mtimer_callback; + +static uint64_t cpu_vega_read_rtc_raw(uint32_t timebase_freq) +{ + return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), + timebase_freq, NANOSECONDS_PER_SECOND); +} + +static uint64_t cpu_vega_read_rtc(void *opaque) +{ + VEGAAclintMTimerState *mtimer =3D opaque; + return cpu_vega_read_rtc_raw(mtimer->timebase_freq) + mtimer->time_del= ta; +} + +/* + * Called when timecmp is written to update the QEMU timer or immediately + * trigger timer interrupt if mtimecmp <=3D current timer value. + */ +static void vega_aclint_mtimer_write_timecmp(VEGAAclintMTimerState *mtimer, + RISCVCPU *cpu, + int hartid, + uint64_t value) +{ + uint32_t timebase_freq =3D mtimer->timebase_freq; + uint64_t next; + uint64_t diff; + + uint64_t rtc =3D cpu_vega_read_rtc(mtimer); + + /* Compute the relative hartid w.r.t the socket */ + hartid =3D hartid - mtimer->hartid_base; + + mtimer->timecmp[hartid] =3D value; + if (mtimer->timecmp[hartid] <=3D rtc) { + /* + * If we're setting an MTIMECMP value in the "past", + * immediately raise the timer interrupt + */ + qemu_irq_raise(mtimer->timer_irqs[hartid]); + return; + } + + /* otherwise, set up the future timer interrupt */ + qemu_irq_lower(mtimer->timer_irqs[hartid]); + diff =3D mtimer->timecmp[hartid] - rtc; + /* back to ns (note args switched in muldiv64) */ + uint64_t ns_diff =3D muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_f= req); + + /* + * check if ns_diff overflowed and check if the addition would potenti= ally + * overflow + */ + if ((NANOSECONDS_PER_SECOND > timebase_freq && ns_diff < diff) || + ns_diff > INT64_MAX) { + next =3D INT64_MAX; + } else { + /* + * as it is very unlikely qemu_clock_get_ns will return a value + * greater than INT64_MAX, no additional check is needed for an + * unsigned integer overflow. + */ + next =3D qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns_diff; + /* + * if ns_diff is INT64_MAX next may still be outside the range + * of a signed integer. + */ + next =3D MIN(next, INT64_MAX); + } + + timer_mod(mtimer->timers[hartid], next); +} + +/* + * Callback used when the timer set using timer_mod expires. + * Should raise the timer interrupt line + */ +static void vega_aclint_mtimer_cb(void *opaque) +{ + vega_aclint_mtimer_callback *state =3D opaque; + + qemu_irq_raise(state->s->timer_irqs[state->num]); +} + +/* CPU read MTIMER register */ +static uint64_t vega_aclint_mtimer_read(void *opaque, hwaddr addr, + unsigned size) +{ + VEGAAclintMTimerState *mtimer =3D opaque; + + /* STIMECMP[h] =3D timecmp_base + 0x10 + h*0x20 =E2=80=94 stored in up= per timecmp[] */ + if (addr >=3D (mtimer->timecmp_base + 0x10) && + addr < (mtimer->timecmp_base + 0x10 + (mtimer->num_harts << 5)) && + ((addr - (mtimer->timecmp_base + 0x10)) % 0x20) < 8) { + size_t hartid =3D mtimer->hartid_base + + ((addr - (mtimer->timecmp_base + 0x10)) >> 5); + if (hartid < mtimer->hartid_base + mtimer->num_harts) { + uint64_t stimecmp =3D mtimer->timecmp[hartid + mtimer->num_har= ts]; + return (size =3D=3D 4) ? (stimecmp & 0xFFFFFFFF) : stimecmp; + } + return 0; + } + if (addr >=3D mtimer->timecmp_base && + addr < (mtimer->timecmp_base + (mtimer->num_harts << 5)) && + ((addr - mtimer->timecmp_base) % 0x20) < 8) { + size_t hartid =3D mtimer->hartid_base + + ((addr - mtimer->timecmp_base) >> 5); + CPUState *cpu =3D cpu_by_arch_id(hartid); + CPURISCVState *env =3D cpu ? cpu_env(cpu) : NULL; + if (!env) { + qemu_log_mask(LOG_GUEST_ERROR, + "aclint-mtimer: invalid hartid: %zu", hartid); + } else if ((addr & 0x7) =3D=3D 0) { + /* timecmp_lo for RV32/RV64 or timecmp for RV64 */ + uint64_t timecmp =3D mtimer->timecmp[hartid]; + return (size =3D=3D 4) ? (timecmp & 0xFFFFFFFF) : timecmp; + } else if ((addr & 0x7) =3D=3D 4) { + /* timecmp_hi */ + uint64_t timecmp =3D mtimer->timecmp[hartid]; + return (timecmp >> 32) & 0xFFFFFFFF; + } else { + qemu_log_mask(LOG_UNIMP, + "aclint-mtimer: invalid read: %08x", (uint32_t)a= ddr); + return 0; + } + } else if (addr =3D=3D mtimer->time_base) { + /* time_lo for RV32/RV64 or timecmp for RV64 */ + uint64_t rtc =3D cpu_vega_read_rtc(mtimer); + return (size =3D=3D 4) ? (rtc & 0xFFFFFFFF) : rtc; + } else if (addr =3D=3D mtimer->time_base + 4) { + /* time_hi */ + return (cpu_vega_read_rtc(mtimer) >> 32) & 0xFFFFFFFF; + } + + qemu_log_mask(LOG_UNIMP, + "aclint-mtimer: invalid read: %08x", (uint32_t)addr); + return 0; +} + +/* CPU write MTIMER register */ +static void vega_aclint_mtimer_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + VEGAAclintMTimerState *mtimer =3D opaque; + int i; + + /* + * STIMECMP[h] =3D timecmp_base + 0x10 + h*0x20. + * BBL's fdt.c VEGA_CLINT uses hls->timecmp =3D STIMECMP for sbi_set_t= imer. + * Writing STIMECMP must schedule a timer so MTIME>=3DSTIMECMP fires M= IP.STIP. + */ + if (addr >=3D (mtimer->timecmp_base + 0x10) && + addr < (mtimer->timecmp_base + 0x10 + (mtimer->num_harts << 5)) && + ((addr - (mtimer->timecmp_base + 0x10)) % 0x20) < 8) { + size_t hartid =3D mtimer->hartid_base + + ((addr - (mtimer->timecmp_base + 0x10)) >> 5); + if (hartid < mtimer->hartid_base + mtimer->num_harts) { + uint64_t stimecmp =3D value; + uint32_t hart_idx =3D (uint32_t)(hartid - mtimer->hartid_base); + mtimer->timecmp[hartid + mtimer->num_harts] =3D stimecmp; + /* Schedule (or cancel) the STIP timer exactly like MTIMECMP */ + RISCVCPU *cpu =3D RISCV_CPU(cpu_by_arch_id(hartid)); + uint64_t rtc =3D cpu_vega_read_rtc(mtimer); + if (stimecmp <=3D rtc) { + riscv_cpu_update_mip(&cpu->env, MIP_STIP, BOOL_TO_MASK(1)); + } else { + riscv_cpu_update_mip(&cpu->env, MIP_STIP, BOOL_TO_MASK(0)); + uint64_t diff =3D stimecmp - rtc; + uint64_t ns_diff =3D muldiv64(diff, NANOSECONDS_PER_SECOND, + mtimer->timebase_freq); + uint64_t next; + if ((NANOSECONDS_PER_SECOND > mtimer->timebase_freq && + ns_diff < diff) || ns_diff > INT64_MAX) { + next =3D INT64_MAX; + } else { + next =3D MIN(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n= s_diff, + (uint64_t)INT64_MAX); + } + timer_mod(mtimer->stimecmp_timers[hart_idx], next); + } + } + return; + } + if (addr >=3D mtimer->timecmp_base && + addr < (mtimer->timecmp_base + (mtimer->num_harts << 5)) && + ((addr - mtimer->timecmp_base) % 0x20) < 8) { + size_t hartid =3D mtimer->hartid_base + + ((addr - mtimer->timecmp_base) >> 5); + + CPUState *cpu =3D cpu_by_arch_id(hartid); + CPURISCVState *env =3D cpu ? cpu_env(cpu) : NULL; + if (!env) { + qemu_log_mask(LOG_GUEST_ERROR, + "aclint-mtimer: invalid hartid: %zu", hartid); + } else if ((addr & 0x7) =3D=3D 0) { + if (size =3D=3D 4) { + /* timecmp_lo for RV32/RV64 */ + uint64_t timecmp_hi =3D mtimer->timecmp[hartid] >> 32; + vega_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), h= artid, + timecmp_hi << 32 | (value & 0xFFFFFFFF)); + } else { + /* timecmp for RV64 */ + vega_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), h= artid, + value); + } + } else if ((addr & 0x7) =3D=3D 4) { + if (size =3D=3D 4) { + /* timecmp_hi for RV32/RV64 */ + uint64_t timecmp_lo =3D mtimer->timecmp[hartid]; + vega_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), h= artid, + value << 32 | (timecmp_lo & 0xFFFFFFFF)); + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "aclint-mtimer: invalid timecmp_hi write: %0= 8x", + (uint32_t)addr); + } + } else { + qemu_log_mask(LOG_UNIMP, + "aclint-mtimer: invalid timecmp write: %08x", + (uint32_t)addr); + } + return; + } else if (addr =3D=3D mtimer->time_base || addr =3D=3D mtimer->time_b= ase + 4) { + uint64_t rtc_r =3D cpu_vega_read_rtc_raw(mtimer->timebase_freq); + uint64_t rtc =3D cpu_vega_read_rtc(mtimer); + + if (addr =3D=3D mtimer->time_base) { + if (size =3D=3D 4) { + /* time_lo for RV32/RV64 */ + mtimer->time_delta =3D ((rtc & ~0xFFFFFFFFULL) | value) - = rtc_r; + } else { + /* time for RV64 */ + mtimer->time_delta =3D value - rtc_r; + } + } else { + if (size =3D=3D 4) { + /* time_hi for RV32/RV64 */ + mtimer->time_delta =3D (value << 32 | (rtc & 0xFFFFFFFF)) = - rtc_r; + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "aclint-mtimer: invalid time_hi write: %08x", + (uint32_t)addr); + return; + } + } + + /* Check if timer interrupt is triggered for each hart. */ + for (i =3D 0; i < mtimer->num_harts; i++) { + CPUState *cpu =3D cpu_by_arch_id(mtimer->hartid_base + i); + CPURISCVState *env =3D cpu ? cpu_env(cpu) : NULL; + if (!env) { + continue; + } + vega_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), + mtimer->hartid_base + i, + mtimer->timecmp[i]); + riscv_timer_write_timecmp(env, env->stimer, env->stimecmp, 0, = MIP_STIP); + riscv_timer_write_timecmp(env, env->vstimer, env->vstimecmp, + env->htimedelta, MIP_VSTIP); + + } + return; + } + + qemu_log_mask(LOG_UNIMP, + "aclint-mtimer: invalid write: %08x", (uint32_t)addr); +} + +static const MemoryRegionOps vega_aclint_mtimer_ops =3D { + .read =3D vega_aclint_mtimer_read, + .write =3D vega_aclint_mtimer_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 8 + }, + .impl =3D { + .min_access_size =3D 4, + .max_access_size =3D 8, + } +}; + +static const Property vega_aclint_mtimer_properties[] =3D { + DEFINE_PROP_UINT32("hartid-base", VEGAAclintMTimerState, + hartid_base, 0), + DEFINE_PROP_UINT32("num-harts", VEGAAclintMTimerState, num_harts, 1), + DEFINE_PROP_UINT32("timecmp-base", VEGAAclintMTimerState, + timecmp_base, VEGA_ACLINT_DEFAULT_MTIMECMP), + DEFINE_PROP_UINT32("time-base", VEGAAclintMTimerState, + time_base, VEGA_ACLINT_DEFAULT_MTIME), + DEFINE_PROP_UINT32("aperture-size", VEGAAclintMTimerState, + aperture_size, VEGA_ACLINT_DEFAULT_MTIMER_SIZE), + DEFINE_PROP_UINT32("timebase-freq", VEGAAclintMTimerState, + timebase_freq, 0), +}; + +/* + * Callback when STIMECMP timer fires: set MIP.STIP. + * Reuses the existing vega_aclint_mtimer_callback struct: + * .s =3D pointer to VEGAAclintMTimerState + * .num =3D hart index (relative to hartid_base) + */ +static void vega_aclint_stimecmp_cb(void *opaque) +{ + vega_aclint_mtimer_callback *cb =3D opaque; + VEGAAclintMTimerState *mtimer =3D cb->s; + int hart_idx =3D cb->num; + size_t hartid =3D mtimer->hartid_base + hart_idx; + + RISCVCPU *cpu =3D RISCV_CPU(cpu_by_arch_id(hartid)); + uint64_t rtc =3D cpu_vega_read_rtc(mtimer); + uint64_t stimecmp =3D mtimer->timecmp[hartid + mtimer->num_harts]; + + if (rtc >=3D stimecmp) { + riscv_cpu_update_mip(&cpu->env, MIP_STIP, BOOL_TO_MASK(1)); + } + /* else: spurious wakeup, leave STIP cleared */ +} + +static void vega_aclint_mtimer_realize(DeviceState *dev, Error **errp) +{ + VEGAAclintMTimerState *s =3D VEGA_ACLINT_MTIMER(dev); + int i; + + memory_region_init_io(&s->mmio, OBJECT(dev), &vega_aclint_mtimer_ops, + s, TYPE_VEGA_ACLINT_MTIMER, s->aperture_size); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); + + s->timer_irqs =3D g_new(qemu_irq, s->num_harts); + qdev_init_gpio_out(dev, s->timer_irqs, s->num_harts); + + s->timers =3D g_new0(QEMUTimer *, s->num_harts); + /* Allocate 2=C3=97num_harts: lower half =3D MTIMECMP, upper half =3D = STIMECMP */ + /* + * Initialise all MTIMECMP and STIMECMP slots to UINT64_MAX so the + * timer interrupt does not fire before software explicitly arms it. + * With the default g_new0 (value 0), MTIME >=3D MTIMECMP is true the + * instant the clock starts, causing a continuous timer interrupt storm + * that prevents Linux from completing early initialisation. + */ + s->timecmp =3D g_new(uint64_t, s->num_harts * 2); + for (int _i =3D 0; _i < s->num_harts * 2; _i++) { + s->timecmp[_i] =3D UINT64_MAX; + } + /* Claim MTIP and STIP on each hart, create STIMECMP timers */ + s->stimecmp_timers =3D g_new(QEMUTimer *, s->num_harts); + for (i =3D 0; i < s->num_harts; i++) { + RISCVCPU *cpu =3D RISCV_CPU(cpu_by_arch_id(s->hartid_base + i)); + if (riscv_cpu_claim_interrupts(cpu, MIP_MTIP) < 0) { + error_report("MTIP already claimed"); + exit(1); + } + if (riscv_cpu_claim_interrupts(cpu, MIP_STIP) < 0) { + error_report("STIP already claimed"); + exit(1); + } + vega_aclint_mtimer_callback *scb =3D g_new(vega_aclint_mtimer_call= back, 1); + scb->s =3D s; + scb->num =3D i; + s->stimecmp_timers[i] =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, + vega_aclint_stimecmp_cb, scb= ); + timer_mod(s->stimecmp_timers[i], INT64_MAX); + } +} + +static void vega_aclint_mtimer_reset_enter(Object *obj, ResetType type) +{ + /* + * According to RISC-V ACLINT spec: + * - On MTIMER device reset, the MTIME register is cleared to zero. + * - On MTIMER device reset, the MTIMECMP registers are in unknown s= tate. + */ + VEGAAclintMTimerState *mtimer =3D VEGA_ACLINT_MTIMER(obj); + + /* + * Clear mtime register by writing to 0 it. + * Pending mtime interrupts will also be cleared at the same time. + */ + vega_aclint_mtimer_write(mtimer, mtimer->time_base, 0, 8); +} + +static const VMStateDescription vmstate_vega_mtimer =3D { + .name =3D "vega_mtimer", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (const VMStateField[]) { + VMSTATE_VARRAY_UINT32(timecmp, VEGAAclintMTimerState, + num_harts, 0, + vmstate_info_uint64, uint64_t), + VMSTATE_END_OF_LIST() + } +}; + +static void vega_aclint_mtimer_class_init(ObjectClass *klass, const void *= data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + dc->realize =3D vega_aclint_mtimer_realize; + device_class_set_props(dc, vega_aclint_mtimer_properties); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + rc->phases.enter =3D vega_aclint_mtimer_reset_enter; + dc->vmsd =3D &vmstate_vega_mtimer; +} + +static const TypeInfo vega_aclint_mtimer_info =3D { + .name =3D TYPE_VEGA_ACLINT_MTIMER, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(VEGAAclintMTimerState), + .class_init =3D vega_aclint_mtimer_class_init, +}; + +/* + * Create ACLINT MTIMER device. + */ +DeviceState *vega_aclint_mtimer_create(hwaddr addr, hwaddr size, + uint32_t hartid_base, uint32_t num_harts, + uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq, + bool provide_rdtime) +{ + int i; + DeviceState *dev =3D qdev_new(TYPE_VEGA_ACLINT_MTIMER); + VEGAAclintMTimerState *s =3D VEGA_ACLINT_MTIMER(dev); + + assert(num_harts <=3D VEGA_ACLINT_MAX_HARTS); + assert(!(addr & 0x7)); + assert(!(timecmp_base & 0x7)); + assert(!(time_base & 0x7)); + + qdev_prop_set_uint32(dev, "hartid-base", hartid_base); + qdev_prop_set_uint32(dev, "num-harts", num_harts); + qdev_prop_set_uint32(dev, "timecmp-base", timecmp_base); + qdev_prop_set_uint32(dev, "time-base", time_base); + qdev_prop_set_uint32(dev, "aperture-size", size); + qdev_prop_set_uint32(dev, "timebase-freq", timebase_freq); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); + + for (i =3D 0; i < num_harts; i++) { + CPUState *cpu =3D cpu_by_arch_id(hartid_base + i); + RISCVCPU *rvcpu =3D RISCV_CPU(cpu); + CPURISCVState *env =3D cpu ? cpu_env(cpu) : NULL; + vega_aclint_mtimer_callback *cb =3D + g_new0(vega_aclint_mtimer_callback, 1); + + if (!env) { + g_free(cb); + continue; + } + if (provide_rdtime) { + riscv_cpu_set_rdtime_fn(env, cpu_vega_read_rtc, dev); + } + + cb->s =3D s; + cb->num =3D i; + s->timers[i] =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, + &vega_aclint_mtimer_cb, cb); + /* + * MTIMECMP initialized to UINT64_MAX in realize(); do NOT reset t= o 0 + * here =E2=80=94 doing so causes M-mode timer to fire immediately= once BBL + * enables MTIE after the first sbi_set_timer call. + */ + + qdev_connect_gpio_out(dev, i, + qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_TIMER)= ); + } + + return dev; +} + +/* CPU read [M|S]SWI register */ +static uint64_t vega_aclint_swi_read(void *opaque, hwaddr addr, + unsigned size) +{ + VEGAAclintSwiState *swi =3D opaque; + + if (addr < (swi->num_harts << 4)) { + size_t hartid =3D swi->hartid_base + (addr >> 4); + CPUState *cpu =3D cpu_by_arch_id(hartid); + CPURISCVState *env =3D cpu ? cpu_env(cpu) : NULL; + if (!env) { + qemu_log_mask(LOG_GUEST_ERROR, + "aclint-swi: invalid hartid: %zu", hartid); + } else if ((addr & 0x3) =3D=3D 0) { + return (swi->sswi) ? 0 : ((env->mip & MIP_MSIP) > 0); + } + } + + qemu_log_mask(LOG_UNIMP, + "aclint-swi: invalid read: %08x", (uint32_t)addr); + return 0; +} + +/* CPU write [M|S]SWI register */ +static void vega_aclint_swi_write(void *opaque, hwaddr addr, uint64_t valu= e, + unsigned size) +{ + VEGAAclintSwiState *swi =3D opaque; + + if (addr < (swi->num_harts << 4)) { + size_t hartid =3D swi->hartid_base + (addr >> 4); + + CPUState *cpu =3D cpu_by_arch_id(hartid); + CPURISCVState *env =3D cpu ? cpu_env(cpu) : NULL; + if (!env) { + qemu_log_mask(LOG_GUEST_ERROR, + "aclint-swi: invalid hartid: %zu", hartid); + } else if ((addr & 0x3) =3D=3D 0) { + if (value & 0x1) { + qemu_irq_raise(swi->soft_irqs[hartid - swi->hartid_base]); + } else { + if (!swi->sswi) { + qemu_irq_lower(swi->soft_irqs[hartid - swi->hartid_bas= e]); + } + } + return; + } + } + + qemu_log_mask(LOG_UNIMP, + "aclint-swi: invalid write: %08x", (uint32_t)addr); +} + +static const MemoryRegionOps vega_aclint_swi_ops =3D { + .read =3D vega_aclint_swi_read, + .write =3D vega_aclint_swi_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 4 + } +}; + +static const Property vega_aclint_swi_properties[] =3D { + DEFINE_PROP_UINT32("hartid-base", VEGAAclintSwiState, hartid_base, 0), + DEFINE_PROP_UINT32("num-harts", VEGAAclintSwiState, num_harts, 1), + DEFINE_PROP_UINT32("sswi", VEGAAclintSwiState, sswi, false), +}; + +static void vega_aclint_swi_realize(DeviceState *dev, Error **errp) +{ + VEGAAclintSwiState *swi =3D VEGA_ACLINT_SWI(dev); + int i; + + memory_region_init_io(&swi->mmio, OBJECT(dev), &vega_aclint_swi_ops, s= wi, + TYPE_VEGA_ACLINT_SWI, VEGA_ACLINT_SWI_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &swi->mmio); + + swi->soft_irqs =3D g_new(qemu_irq, swi->num_harts); + qdev_init_gpio_out(dev, swi->soft_irqs, swi->num_harts); + + /* Claim software interrupt bits */ + for (i =3D 0; i < swi->num_harts; i++) { + RISCVCPU *cpu =3D RISCV_CPU(qemu_get_cpu(swi->hartid_base + i)); + /* We don't claim mip.SSIP because it is writable by software */ + if (riscv_cpu_claim_interrupts(cpu, swi->sswi ? 0 : MIP_MSIP) < 0)= { + error_report("MSIP already claimed"); + exit(1); + } + } +} + +static void vega_aclint_swi_reset_enter(Object *obj, ResetType type) +{ + /* + * According to RISC-V ACLINT spec: + * - On MSWI device reset, each MSIP register is cleared to zero. + * + * p.s. SSWI device reset does nothing since SETSIP register always re= ads 0. + */ + VEGAAclintSwiState *swi =3D VEGA_ACLINT_SWI(obj); + int i; + + if (!swi->sswi) { + for (i =3D 0; i < swi->num_harts; i++) { + /* Clear MSIP registers by lowering software interrupts. */ + qemu_irq_lower(swi->soft_irqs[i]); + } + } +} + +static void vega_aclint_swi_class_init(ObjectClass *klass, const void *dat= a) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + dc->realize =3D vega_aclint_swi_realize; + device_class_set_props(dc, vega_aclint_swi_properties); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + rc->phases.enter =3D vega_aclint_swi_reset_enter; +} + +static const TypeInfo vega_aclint_swi_info =3D { + .name =3D TYPE_VEGA_ACLINT_SWI, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(VEGAAclintSwiState), + .class_init =3D vega_aclint_swi_class_init, +}; + +/* + * Create ACLINT [M|S]SWI device. + */ +DeviceState *vega_aclint_swi_create(hwaddr addr, uint32_t hartid_base, + uint32_t num_harts, bool sswi) +{ + int i; + DeviceState *dev =3D qdev_new(TYPE_VEGA_ACLINT_SWI); + + assert(num_harts <=3D VEGA_ACLINT_MAX_HARTS); + assert(!(addr & 0x3)); + + qdev_prop_set_uint32(dev, "hartid-base", hartid_base); + qdev_prop_set_uint32(dev, "num-harts", num_harts); + qdev_prop_set_uint32(dev, "sswi", sswi ? true : false); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); + + for (i =3D 0; i < num_harts; i++) { + CPUState *cpu =3D cpu_by_arch_id(hartid_base + i); + RISCVCPU *rvcpu =3D RISCV_CPU(cpu); + + qdev_connect_gpio_out(dev, i, + qdev_get_gpio_in(DEVICE(rvcpu), + (sswi) ? IRQ_S_SOFT : IRQ_M_SOFT)); + } + + return dev; +} + +static void vega_aclint_register_types(void) +{ + type_register_static(&vega_aclint_mtimer_info); + type_register_static(&vega_aclint_swi_info); +} + +type_init(vega_aclint_register_types) diff --git a/include/hw/intc/vega_aclint.h b/include/hw/intc/vega_aclint.h new file mode 100644 index 0000000000..21bc157ee1 --- /dev/null +++ b/include/hw/intc/vega_aclint.h @@ -0,0 +1,84 @@ +/* + * VEGA ACLINT (Advanced Core Local Interruptor) interface + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2025 C-DAC (Centre for Development of Advanced Computing) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + */ + +#ifndef HW_VEGA_ACLINT_H +#define HW_VEGA_ACLINT_H + +#include "hw/core/sysbus.h" + +#define TYPE_VEGA_ACLINT_MTIMER "vega.aclint.mtimer" + +#define VEGA_ACLINT_MTIMER(obj) \ + OBJECT_CHECK(VEGAAclintMTimerState, (obj), TYPE_VEGA_ACLINT_MTIMER) + +typedef struct VEGAAclintMTimerState { + /*< private >*/ + SysBusDevice parent_obj; + uint64_t time_delta; + uint64_t *timecmp; + QEMUTimer **timers; + QEMUTimer **stimecmp_timers; + + /*< public >*/ + MemoryRegion mmio; + uint32_t hartid_base; + uint32_t num_harts; + uint32_t timecmp_base; + uint32_t time_base; + uint32_t aperture_size; + uint32_t timebase_freq; + qemu_irq *timer_irqs; +} VEGAAclintMTimerState; + +DeviceState *vega_aclint_mtimer_create(hwaddr addr, hwaddr size, + uint32_t hartid_base, uint32_t num_harts, + uint32_t timecmp_base, uint32_t time_base, uint32_t timebase_freq, + bool provide_rdtime); + +#define TYPE_VEGA_ACLINT_SWI "vega.aclint.swi" + +#define VEGA_ACLINT_SWI(obj) \ + OBJECT_CHECK(VEGAAclintSwiState, (obj), TYPE_VEGA_ACLINT_SWI) + +typedef struct VEGAAclintSwiState { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + MemoryRegion mmio; + uint32_t hartid_base; + uint32_t num_harts; + uint32_t sswi; + qemu_irq *soft_irqs; +} VEGAAclintSwiState; + +DeviceState *vega_aclint_swi_create(hwaddr addr, uint32_t hartid_base, + uint32_t num_harts, bool sswi); + +enum { + VEGA_ACLINT_DEFAULT_MTIMECMP =3D 0x0, + VEGA_ACLINT_DEFAULT_MTIME =3D 0x100, + VEGA_ACLINT_DEFAULT_MTIMER_SIZE =3D 0x8000, + VEGA_ACLINT_DEFAULT_TIMEBASE_FREQ =3D 10000000, + VEGA_ACLINT_MAX_HARTS =3D 4095, + VEGA_ACLINT_SWI_SIZE =3D 0x480 +}; + +#endif --=20 2.43.0 ---------------------------------------------------------------------------= --------------------------------- [ C-DAC is on Social-Media too. Kindly follow us at: Facebook: https://www.facebook.com/CDACINDIA & Twitter: @cdacindia ] This e-mail is for the sole use of the intended recipient(s) and may contain confidential and privileged information. If you are not the intended recipient, please contact the sender by reply e-mail and destroy all copies and the original message. Any unauthorized review, use, disclosure, dissemination, forwarding, printing or copying of this email is strictly prohibited and appropriate legal action will be taken. ---------------------------------------------------------------------------= --------------------------------- From nobody Fri Oct 23 14:30:37 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=cdac.in ARC-Seal: i=1; a=rsa-sha256; t=1792138172; cv=none; d=zohomail.com; s=zohoarc; b=dk7C37P/W27zBXpnkuASDdBMR2Pc7yAcFn/cmq9MrXUer8UdyfG+geQjBSwrguPZlS5PIZ4aALEYLnJ8ZeI4M9qS2iEFd5RI5ODvNka53YwE1i2wargeMPTNJv1z/nMSiBiaaAiinj514nlrjhQ12OxWXTT79qKoRWhmYQLSiZ8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792138172; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=tHIkpkteURo1Z6wwo8qnOinuNOkehDohgY7yN5oVosA=; b=LtZXsZkpES7BXyt6qPLwMqqzzBnAYks3Ams8SX9iYtdtYAe0HDIRh3yyo93J4FoERl0QjpbUyL9NgWjFmCSNpjmeomX9GZ+jT9CY+G1DR9knh5JcX9uKOAU2xVoUNb95UKwMb76hLH4xw8Rx8Ely1CQL+r4HEkCLC7ghikkSYNg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792138171762467.81943219855646; Fri, 16 Oct 2026 01:09:31 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xHczg-0003tx-Mb; Fri, 16 Oct 2026 04:08:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xHczK-0003od-IB; Fri, 16 Oct 2026 04:08:29 -0400 Received: from mailsender.cdac.in ([196.1.113.117] helo=mailsender-core1.pune.cdac.in) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xHczG-0005xB-DO; Fri, 16 Oct 2026 04:08:25 -0400 Received: from mscr-int.pune.cdac.in (mscr-int.pune.cdac.in [10.208.193.2]) by mailsender.cdac.in (8.15.2/8.15.2/Debian-22ubuntu3) with ESMTP id 69G888B43825298; Fri, 16 Oct 2026 13:38:09 +0530 Received: from mailgw-cip.pune.cdac.in (mscr-haproxy.pune.cdac.in [10.208.193.46]) by mscr-int.pune.cdac.in (Postfix) with ESMTP id E1D811000723A; Fri, 16 Oct 2026 13:37:48 +0530 (IST) Received: from hdg164.tvm.cdac.in (hd_hdg164.tvm.cdac.in [10.176.18.107]) (Authenticated sender: karthika.b@cdac.in) by mailgw-cip.pune.cdac.in (Postfix) with ESMTPSA id 864BE14E17D2; Fri, 16 Oct 2026 13:37:48 +0530 (IST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cdac.in; s=default; t=1792138089; bh=5nWtAO4eDgun5El3ax95KIS+TUrX8uE5A3LV2dn1u1M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aA7kcTjIERazQmnREpGLsYiYaMHXQYVtns74fEqssq15U0uBZCxQ7lC3UdmAEwaDN kT2bYeFhri72Jn7Ndo0ZBWVjbz0W3JVFWL7jf8gTGuUJ01lm5cdobAQbXAnTWQ5oZk EsXIVdanrqb1AFGYB+d2oYgR46tNqbqJSrMGqBFg= X-Auth: karthika.b@cdac.in From: Karthika B To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, sreenadh@cdac.in, raokk@cdac.in, Karthika B , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu Subject: [PATCH 3/7] target/riscv: Add VEGA32 and VEGA64 CPU types Date: Fri, 16 Oct 2026 13:37:03 +0530 Message-ID: <20261016080709.17331-4-karthika.b@cdac.in> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20261016080709.17331-1-karthika.b@cdac.in> References: <385625713.441366.1761727810206@webmail2.cdac.in> <20261016080709.17331-1-karthika.b@cdac.in> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CDAC-PUNE-MailScanner-Information: Please contact the ISP for more information X-CDAC-PUNE-MailScanner-ID: E1D811000723A.AEE86 X-CDAC-PUNE-MailScanner: Found to be clean X-CDAC-PUNE-MailScanner-SpamCheck: not spam, SpamAssassin (not cached, score=-2.9, required 6, autolearn=not spam, ALL_TRUSTED -1.00, BAYES_00 -1.90) X-CDAC-PUNE-MailScanner-From: karthika.b@cdac.in 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=lists1p.gnu.org; Received-SPF: pass client-ip=196.1.113.117; envelope-from=karthika.b@cdac.in; helo=mailsender-core1.pune.cdac.in X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @cdac.in) X-ZM-MESSAGEID: 1792138174054158500 Content-Type: text/plain; charset="utf-8" Signed-off-by: Karthika B --- target/riscv/cpu-qom.h | 2 ++ target/riscv/cpu.c | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index 30dcdcfaae..58abfef048 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -58,6 +58,8 @@ #define TYPE_RISCV_CPU_XIANGSHAN_KMH RISCV_CPU_TYPE_NAME("xiangshan-kun= minghu") #define TYPE_RISCV_CPU_MIPS_P8700 RISCV_CPU_TYPE_NAME("mips-p8700") #define TYPE_RISCV_CPU_HOST RISCV_CPU_TYPE_NAME("host") +#define TYPE_RISCV_CPU_VEGA32 RISCV_CPU_TYPE_NAME("vega32") +#define TYPE_RISCV_CPU_VEGA64 RISCV_CPU_TYPE_NAME("vega64") =20 OBJECT_DECLARE_CPU_TYPE(RISCVCPU, RISCVCPUClass, RISCV_CPU) =20 diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 5903df9954..7b96b7b670 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -2987,6 +2987,20 @@ static const TypeInfo riscv_cpu_type_infos[] =3D { ), #endif =20 + +#if defined(TARGET_RISCV32) + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_VEGA32, TYPE_RISCV_CPU_SIFIVE_U, + .misa_mxl_max =3D MXL_RV32, + .misa_ext =3D RVI | RVM | RVA | RVS | RVU, + .priv_spec =3D PRIV_VERSION_LATEST, + + .cfg.max_satp_mode =3D VM_1_10_SV32, + .cfg.ext_zicsr =3D true, + .cfg.ext_zifencei =3D true, + .cfg.pmp =3D false, + ), +#endif + #if (defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY)) DEFINE_RISCV_CPU(TYPE_RISCV_CPU_MAX32, TYPE_RISCV_DYNAMIC_CPU, .cfg.max_satp_mode =3D VM_1_10_SV32, @@ -3032,6 +3046,17 @@ static const TypeInfo riscv_cpu_type_infos[] =3D { .misa_mxl_max =3D MXL_RV64, ), =20 + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_VEGA64, TYPE_RISCV_CPU_SIFIVE_U, + .misa_mxl_max =3D MXL_RV64, + .misa_ext =3D RVI | RVM | RVA | RVS | RVU, + .priv_spec =3D PRIV_VERSION_LATEST, + + .cfg.max_satp_mode =3D VM_1_10_SV39, + .cfg.ext_zicsr =3D true, + .cfg.ext_zifencei =3D true, + .cfg.pmp =3D false, + ), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_THEAD_C906, TYPE_RISCV_VENDOR_CPU, .misa_mxl_max =3D MXL_RV64, .misa_ext =3D RVG | RVC | RVS | RVU, --=20 2.43.0 ---------------------------------------------------------------------------= --------------------------------- [ C-DAC is on Social-Media too. Kindly follow us at: Facebook: https://www.facebook.com/CDACINDIA & Twitter: @cdacindia ] This e-mail is for the sole use of the intended recipient(s) and may contain confidential and privileged information. If you are not the intended recipient, please contact the sender by reply e-mail and destroy all copies and the original message. Any unauthorized review, use, disclosure, dissemination, forwarding, printing or copying of this email is strictly prohibited and appropriate legal action will be taken. ---------------------------------------------------------------------------= --------------------------------- From nobody Fri Oct 23 14:30:37 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=cdac.in ARC-Seal: i=1; a=rsa-sha256; t=1792138157; cv=none; d=zohomail.com; s=zohoarc; b=Lo2ZEY+qsxzwHdWnQIcjcPIAytoTAS3rOeGZwPvd6Ie00A2bcMS6JVvXHrc9VgdIpTLUJc97eaEmHYaRW29cw9XqvuIze/ZfpkOImzwgn2j4APW+n2eBScxdJgANCeCYJqJLSL0+awuGSVwX8emGcyVaDgxm14OqQRDuV+13Urc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792138157; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=CYSGlme0+Vdt8Vp6p8J8RIo7AWcmPiCBAHzobMlG7IE=; b=GO2i5HzSjlEtgOKEjygXqJS4Y2d58U+VMdGqC1H0vbBtJBkwhwSMLwppjuG9VdquP7HxFMsPotlJfKPLlu79ZwS+BlLFz6sl+EpurCAUhtXNFe+BlYuj9EapjrPNXvRtq/29a5U8f8Y9MlyvBNG/27GlTqZpWlOnGEim5fX3t8k= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792138153127340.46124345354326; Fri, 16 Oct 2026 01:09:13 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xHcze-0003sz-KX; Fri, 16 Oct 2026 04:08:46 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xHczP-0003pJ-SI; Fri, 16 Oct 2026 04:08:33 -0400 Received: from mailsender.cdac.in ([196.1.113.117] helo=mailsender-core1.pune.cdac.in) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xHczK-0005xf-Ki; Fri, 16 Oct 2026 04:08:30 -0400 Received: from mscr-int2.pune.cdac.in (mscr-int2.pune.cdac.in [10.208.193.12]) by mailsender.cdac.in (8.15.2/8.15.2/Debian-22ubuntu3) with ESMTP id 69G880pH3825216; Fri, 16 Oct 2026 13:38:01 +0530 Received: from mailgw-cip.pune.cdac.in (mscr-haproxy.pune.cdac.in [10.208.193.46]) by mscr-int2.pune.cdac.in (Postfix) with ESMTP id 4D45B100234DA; Fri, 16 Oct 2026 13:37:50 +0530 (IST) Received: from hdg164.tvm.cdac.in (hd_hdg164.tvm.cdac.in [10.176.18.107]) (Authenticated sender: karthika.b@cdac.in) by mailgw-cip.pune.cdac.in (Postfix) with ESMTPSA id C3E9414E17D2; Fri, 16 Oct 2026 13:37:49 +0530 (IST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cdac.in; s=default; t=1792138086; bh=KiWcE4WCJ1a/zJGVsIfItYxBqmqXpYzt76ubD+KXQ7s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hIY/rGWS6KZpSOuhsigZfMOToXO10xCc8IcotWB18mQhXO65R/29RhX90ppsXcCF+ xKYvtzBKL6KUFRfcBFz6rlpSrhXf41pwD9imiz/JYIQMahlHFS43pEW0OrdAykTQab kIRucfDMTJSikDAmqPpZVYHjdwmEgK9PqCgmHSm0= X-Auth: karthika.b@cdac.in From: Karthika B To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, sreenadh@cdac.in, raokk@cdac.in, Karthika B , Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu Subject: [PATCH 4/7] hw/riscv: Add CDAC VEGA machine model Date: Fri, 16 Oct 2026 13:37:04 +0530 Message-ID: <20261016080709.17331-5-karthika.b@cdac.in> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20261016080709.17331-1-karthika.b@cdac.in> References: <385625713.441366.1761727810206@webmail2.cdac.in> <20261016080709.17331-1-karthika.b@cdac.in> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-CDAC-PUNE-MailScanner-Information: Please contact the ISP for more information X-CDAC-PUNE-MailScanner-ID: 4D45B100234DA.A259C X-CDAC-PUNE-MailScanner: Found to be clean X-CDAC-PUNE-MailScanner-SpamCheck: not spam, SpamAssassin (not cached, score=-0.999, required 6, ALL_TRUSTED -1.00, URIBL_BLOCKED 0.00) X-CDAC-PUNE-MailScanner-From: karthika.b@cdac.in 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=lists1p.gnu.org; Received-SPF: pass client-ip=196.1.113.117; envelope-from=karthika.b@cdac.in; helo=mailsender-core1.pune.cdac.in X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @cdac.in) X-ZM-MESSAGEID: 1792138159711158500 Signed-off-by: Karthika B --- configs/devices/riscv64-softmmu/default.mak | 1 + hw/riscv/Kconfig | 11 + hw/riscv/meson.build | 1 + hw/riscv/vega.c | 502 ++++++++++++++++++++ include/hw/riscv/vega.h | 136 ++++++ 5 files changed, 651 insertions(+) create mode 100644 hw/riscv/vega.c create mode 100644 include/hw/riscv/vega.h diff --git a/configs/devices/riscv64-softmmu/default.mak b/configs/devices/= riscv64-softmmu/default.mak index a8e4d0ab33..5454fded22 100644 --- a/configs/devices/riscv64-softmmu/default.mak +++ b/configs/devices/riscv64-softmmu/default.mak @@ -11,5 +11,6 @@ # CONFIG_RISCV_VIRT=3Dn # CONFIG_MICROCHIP_PFSOC=3Dn # CONFIG_SHAKTI_C=3Dn +# CONFIG_VEGA=3Dn # CONFIG_XIANGSHAN_KUNMINGHU=3Dn # CONFIG_MIPS_BOSTON_AIA=3Dn diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 2518b04175..dc95cad9d8 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -120,6 +120,17 @@ config SPIKE select RISCV_ACLINT select SIFIVE_PLIC =20 +config VEGA + bool + default y + depends on RISCV32 || RISCV64 + select DEVICE_TREE + select RISCV_NUMA + select SERIAL_MM + select VEGA_ACLINT + select VEGA_PLIC + select VIRTIO_MMIO + config XIANGSHAN_KUNMINGHU bool default y diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index 533472e22a..74bea26bef 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -13,6 +13,7 @@ riscv_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-ac= pi-build.c')) riscv_ss.add(when: 'CONFIG_RISCV_IOMMU', if_true: files( 'riscv-iommu.c', 'riscv-iommu-pci.c', 'riscv-iommu-sys.c', 'riscv-iommu-h= pm.c')) riscv_ss.add(when: 'CONFIG_MICROBLAZE_V', if_true: files('microblaze-v-gen= eric.c')) +riscv_ss.add(when: 'CONFIG_VEGA', if_true: files('vega.c')) riscv_ss.add(when: 'CONFIG_XIANGSHAN_KUNMINGHU', if_true: files('xiangshan= _kmh.c')) =20 riscv_ss.add(when: 'CONFIG_RISCV_MIPS_CPS', if_true: files('cps.c')) diff --git a/hw/riscv/vega.c b/hw/riscv/vega.c new file mode 100644 index 0000000000..835c90571a --- /dev/null +++ b/hw/riscv/vega.c @@ -0,0 +1,502 @@ +/* + * QEMU RISC-V VEGA SoC machine emulation + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2025 C-DAC (Centre for Development of Advanced Computing) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/guest-random.h" +#include "qapi/error.h" +#include "hw/core/boards.h" +#include "hw/core/sysbus.h" +#include "hw/core/qdev-properties.h" +#include "hw/char/serial-mm.h" +#include "target/riscv/cpu.h" +#include "target/riscv/pmu.h" +#include "hw/riscv/riscv_hart.h" +#include "hw/riscv/vega.h" +#include "hw/riscv/machines-qom.h" +#include "hw/riscv/boot.h" +#include "hw/riscv/numa.h" +#include "kvm/kvm_riscv.h" +#include "hw/intc/vega_aclint.h" +#include "hw/intc/vega_plic.h" +#include "hw/misc/sifive_test.h" +#include "chardev/char.h" +#include "system/device_tree.h" +#include "system/system.h" +#include "system/tcg.h" +#include "system/kvm.h" +#include "system/qtest.h" +#include "hw/misc/unimp.h" + +static bool vega_aclint_allowed(void) +{ + return tcg_enabled() || qtest_enabled(); +} + +/* + * Memory map =E2=80=94 entries match the enum in vega.h exactly, same ord= er. + * DRAM size is filled in from machine->ram_size during vega_machine_init. + */ +static MemMapEntry vega_memmap[] =3D { + [VEGA_DEBUG] =3D { 0x0, 0x100 }, + [VEGA_MROM] =3D { 0x1000, 0xf000 }, + [VEGA_TEST] =3D { 0x100000, 0x1000 }, + [VEGA_CLINT] =3D { 0x20010000, 0x10000 }, + [VEGA_ACLINT_SSWI] =3D { 0x3F00000, 0x4000 }, + [VEGA_PLIC_ID] =3D { 0x20010000, 0x400 }, + [VEGA_UART0] =3D { 0x10000100, 0x100 }, +#if defined(TARGET_RISCV32) + [VEGA_DRAM] =3D { 0x200000, 0x0 }, +#else + [VEGA_DRAM] =3D { 0x400000000, 0x0 }, +#endif + [VEGA_SRAM] =3D { 0x20000, 0x10000 }, + [VEGA_UART1] =3D { 0x10000200, 0x100 }, + [VEGA_UART2] =3D { 0x10000300, 0x100 }, + [VEGA_UART3] =3D { 0x10000400, 0x100 }, + [VEGA_UART4] =3D { 0x10000500, 0x100 }, + [VEGA_SPI0] =3D { 0x10000600, 0x100 }, + [VEGA_SPI1] =3D { 0x10000700, 0x100 }, + [VEGA_IIC0] =3D { 0x10000800, 0x100 }, + [VEGA_IIC1] =3D { 0x10000900, 0x100 }, + [VEGA_SDHCI] =3D { 0x20040000, 0x1000 }, + [VEGA_VIRTIO] =3D { 0x10002000, 0x100 }, +}; + +/* + * UART init + * + * Baremetal (no DTB / no-fdt=3Don): + * Always use shift=3D2 / io-width=3D4. The CDAC UART places every 16550 + * register at a 4-byte boundary on a 32-bit bus. + * + * Linux (-dtb supplied): + * Read reg-shift and reg-io-width from the /soc/serial node in the DTB. + * If absent, the baremetal defaults are kept. + */ + +static void vega_uart_init(RISCVVegaState *s, MachineState *machine, + MemoryRegion *system_memory, + DeviceState *mmio_irqchip) +{ + int reg_shift =3D VEGA_UART_DEFAULT_REGSHIFT; + + /* + * Linux boot path: -kernel bbl -dtb riscv.dtb + * machine->dtb is set =E2=86=92 read reg-shift from the DTB uart no= de. + * + * Baremetal path: -bios baremetal.elf + * machine->firmware is set, machine->dtb is NULL =E2=86=92 + * use the hardware default (shift=3D2, 4-byte stride). + */ + /* + * machine->dtb is set when the user passes -dtb . + * machine->fdt is only non-NULL after load_device_tree() has run. + * Both must be checked: dtb may be set but fdt not yet loaded when + * vega_uart_init is called early in vega_machine_init. + */ + if (machine->dtb && machine->fdt) { + char uart_path[64]; + int val =3D 0; + snprintf(uart_path, sizeof(uart_path), "/soc/serial@%lx", + (unsigned long)s->memmap[VEGA_UART0].base); + if (qemu_fdt_getprop_cell(machine->fdt, uart_path, + "reg-shift", &val, NULL) =3D=3D 0) + reg_shift =3D val; + } + + serial_mm_init(system_memory, + s->memmap[VEGA_UART0].base, + reg_shift, + qdev_get_gpio_in(mmio_irqchip, UART0_IRQ), + 399193, + serial_hd(0), + DEVICE_LITTLE_ENDIAN); +} + +/* + * VIRTIO-MMIO: QEMU-side device realization + * + * Instantiates the actual virtio-mmio transport slots so that -device + * virtio-*-device has a virtio-bus to attach to. VEGA does not generate + * its own FDT (see vega_machine_init below) =E2=80=94 the caller is respo= nsible + * for supplying a -dtb whose virtio_mmio nodes match these addresses and + * IRQs exactly. + */ +static void vega_virtio_init(RISCVVegaState *s, DeviceState *mmio_irqchip) +{ + int i; + + for (i =3D 0; i < VEGA_VIRTIO_COUNT; i++) { + hwaddr addr =3D s->memmap[VEGA_VIRTIO].base + + i * s->memmap[VEGA_VIRTIO].size; + + sysbus_create_simple("virtio-mmio", addr, + qdev_get_gpio_in(mmio_irqchip, + VEGA_VIRTIO_IRQ + i)); + } +} + +/* PLIC creation */ + +static DeviceState *vega_create_plic(const MemMapEntry *memmap, int socket, + int base_hartid, int hart_count) +{ + g_autofree char *plic_hart_config =3D + riscv_plic_hart_config_string(hart_count); + + return vega_plic_create( + memmap[VEGA_PLIC_ID].base + socket * memmap[VEGA_PLIC_ID].siz= e, + plic_hart_config, hart_count, base_hartid, + VEGA_IRQCHIP_NUM_SOURCES, + ((1U << VEGA_IRQCHIP_NUM_PRIO_BITS) - 1), + VEGA_PLIC_PRIORITY_BASE, VEGA_PLIC_PENDING_BASE, + VEGA_PLIC_ENABLE_BASE, VEGA_PLIC_ENABLE_STRIDE, + VEGA_PLIC_CONTEXT_BASE, VEGA_PLIC_CONTEXT_STRIDE, + memmap[VEGA_PLIC_ID].size); +} + +/* Machine done notifier */ + +static void vega_machine_done(Notifier *notifier, void *data) +{ + RISCVVegaState *s =3D container_of(notifier, RISCVVegaState, machine_d= one); + MachineState *machine =3D MACHINE(s); + hwaddr start_addr =3D s->memmap[VEGA_DRAM].base; + target_ulong firmware_end_addr, kernel_start_addr; + const char *firmware_name =3D riscv_default_firmware_name(&s->soc[0]); + uint64_t fdt_load_addr =3D 0; + uint64_t kernel_entry =3D 0; + RISCVBootInfo boot_info; + + /* + * Baremetal path (-bios baremetal.elf, no -dtb): + * machine->firmware is set and machine->dtb is NULL. + * Load the ELF via the firmware slot, set the reset vector to the + * ELF entry point, and return =E2=80=94 no DTB is generated or load= ed. + */ + if (machine->firmware && strcmp(machine->firmware, "none") !=3D 0 + && !machine->dtb) { + firmware_end_addr =3D riscv_find_and_load_firmware(machine, firmwa= re_name, + &start_addr, NULL= ); + (void)firmware_end_addr; + riscv_boot_info_init(&boot_info, &s->soc[0]); + riscv_setup_rom_reset_vec(machine, &s->soc[0], + s->memmap[VEGA_DRAM].base, + s->memmap[VEGA_MROM].base, + s->memmap[VEGA_MROM].size, + 0, 0); + return; + } + + /* + * Nothing to boot at all: no -kernel, no -dtb, no real -bios firmware. + * This is a valid, inert machine state (e.g. qtest's generic qom/hmp + * smoke tests just instantiate "-M vega" with nothing to run). The + * rest of this function assumes machine->fdt exists in order to + * compute an FDT load address and place a kernel, so it must not run + * in this case. + */ + if (!machine->kernel_filename && !machine->dtb + && (!machine->firmware || !strcmp(machine->firmware, "none")))= { + return; + } + + if (kvm_enabled()) { + if (machine->firmware) { + if (strcmp(machine->firmware, "none")) { + error_report("Machine mode firmware is not supported with = KVM."); + exit(1); + } + } else { + machine->firmware =3D g_strdup("none"); + } + } + + firmware_end_addr =3D riscv_find_and_load_firmware(machine, firmware_n= ame, + &start_addr, NULL); + riscv_boot_info_init(&boot_info, &s->soc[0]); + + if (machine->kernel_filename && !kernel_entry) { + kernel_start_addr =3D riscv_calc_kernel_start_addr(&boot_info, + firmware_end_addr= ); + riscv_load_kernel(machine, &boot_info, kernel_start_addr, true, NU= LL); + kernel_entry =3D boot_info.image_low_addr; + } + + /* + * Use machine->ram_size (not s->memmap[VEGA_DRAM].size) so that the D= TB + * is placed at the top of actual RAM. DRAM size is set in the memmap= for + * MMIO range registration but ram_size is the authoritative value for + * address-space arithmetic here. + */ + fdt_load_addr =3D riscv_compute_fdt_addr(s->memmap[VEGA_DRAM].base, + machine->ram_size, + machine, &boot_info); + riscv_load_fdt(fdt_load_addr, machine->fdt); + riscv_setup_rom_reset_vec(machine, &s->soc[0], start_addr, + s->memmap[VEGA_MROM].base, + s->memmap[VEGA_MROM].size, + kernel_entry, fdt_load_addr); + if (kvm_enabled()) { + riscv_setup_direct_kernel(kernel_entry, fdt_load_addr); + } +} + +/* Machine init */ + +static void vega_machine_init(MachineState *machine) +{ + RISCVVegaState *s =3D RISCV_VEGA_MACHINE(machine); + MemoryRegion *system_memory =3D get_system_memory(); + MemoryRegion *mask_rom =3D g_new(MemoryRegion, 1); + DeviceState *mmio_irqchip =3D NULL; + int i, base_hartid, hart_count; + int socket_count =3D riscv_socket_count(machine); + + s->memmap =3D vega_memmap; + + if (VEGA_SOCKETS_MAX < socket_count) { + error_report("number of sockets/nodes should be less than %d", + VEGA_SOCKETS_MAX); + exit(1); + } + if (!vega_aclint_allowed() && s->have_aclint) { + error_report("'aclint' is only available with TCG acceleration"); + exit(1); + } + + for (i =3D 0; i < socket_count; i++) { + g_autofree char *soc_name =3D g_strdup_printf("soc%d", i); + + if (!riscv_socket_check_hartids(machine, i)) { + error_report("discontinuous hartids in socket%d", i); exit(1); + } + base_hartid =3D riscv_socket_first_hartid(machine, i); + if (base_hartid < 0) { + error_report("can't find hartid base for socket%d", i); exit(1= ); + } + hart_count =3D riscv_socket_hart_count(machine, i); + if (hart_count < 0) { + error_report("can't find hart count for socket%d", i); exit(1); + } + + object_initialize_child(OBJECT(machine), soc_name, &s->soc[i], + TYPE_RISCV_HART_ARRAY); + object_property_set_str(OBJECT(&s->soc[i]), "cpu-type", + machine->cpu_type, &error_abort); + object_property_set_int(OBJECT(&s->soc[i]), "hartid-base", + base_hartid, &error_abort); + object_property_set_int(OBJECT(&s->soc[i]), "num-harts", + hart_count, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->soc[i]), &error_fatal); + + /* Timer */ + if (vega_aclint_allowed() && s->have_aclint) { + vega_aclint_swi_create( + s->memmap[VEGA_CLINT].base + i * s->memmap[VEGA_CLINT].siz= e, + base_hartid, hart_count, false); + vega_aclint_mtimer_create( + s->memmap[VEGA_CLINT].base + i * s->memmap[VEGA_CLINT].siz= e + + VEGA_ACLINT_SWI_SIZE, + VEGA_ACLINT_DEFAULT_MTIMER_SIZE, base_hartid, hart_count, + VEGA_ACLINT_DEFAULT_MTIMECMP, VEGA_ACLINT_DEFAULT_MTIME, + VEGA_ACLINT_DEFAULT_TIMEBASE_FREQ, true); + vega_aclint_swi_create( + s->memmap[VEGA_ACLINT_SSWI].base + + i * s->memmap[VEGA_ACLINT_SSWI].size, + base_hartid, hart_count, true); + } else if (tcg_enabled()) { + vega_aclint_swi_create( + s->memmap[VEGA_CLINT].base + i * s->memmap[VEGA_CLINT].siz= e + + VEGA_CLINT_MSWI_OFFSET, + base_hartid, hart_count, false); + vega_aclint_mtimer_create( + s->memmap[VEGA_CLINT].base + i * s->memmap[VEGA_CLINT].siz= e + + VEGA_ACLINT_SWI_SIZE, + VEGA_ACLINT_DEFAULT_MTIMER_SIZE, base_hartid, hart_count, + VEGA_ACLINT_DEFAULT_MTIMECMP, VEGA_ACLINT_DEFAULT_MTIME, + VEGA_ACLINT_DEFAULT_TIMEBASE_FREQ, true); + } + + s->irqchip[i] =3D vega_create_plic(s->memmap, i, + base_hartid, hart_count); + + if (i =3D=3D 0) { + mmio_irqchip =3D s->irqchip[i]; + } + } + + /* DRAM =E2=80=94 set base and size before any FDT address computation= */ + if (!s->dram_base) { + s->dram_base =3D vega_memmap[VEGA_DRAM].base; + warn_report("dram-base not specified, using default 0x%"PRIx64, + s->dram_base); + } else { + vega_memmap[VEGA_DRAM].base =3D s->dram_base; + } + vega_memmap[VEGA_DRAM].size =3D machine->ram_size; + + memory_region_add_subregion(system_memory, s->memmap[VEGA_DRAM].base, + machine->ram); + + /* SRAM */ + { + MemoryRegion *sram =3D g_new(MemoryRegion, 1); + memory_region_init_ram(sram, NULL, "riscv_vega_board.sram", + s->memmap[VEGA_SRAM].size, &error_fatal); + memory_region_add_subregion(system_memory, + s->memmap[VEGA_SRAM].base, sram); + } + + /* Boot ROM */ + memory_region_init_rom(mask_rom, NULL, "riscv_vega_board.mrom", + s->memmap[VEGA_MROM].size, &error_fatal); + memory_region_add_subregion(system_memory, + s->memmap[VEGA_MROM].base, mask_rom); + + /* SiFive Test device =E2=80=94 reboot / poweroff */ + sifive_test_create(s->memmap[VEGA_TEST].base); + + /* UART0 =E2=80=94 shift/width from DTB (Linux) or hardcoded defaults = (baremetal) */ + vega_uart_init(s, machine, system_memory, mmio_irqchip); + + /* + * VIRTIO-MMIO =E2=80=94 must match whatever the user's -dtb describes. + * VEGA does not generate its own FDT (see below); the caller is + * responsible for supplying a DTB whose virtio_mmio nodes match + * these addresses/IRQs exactly. + */ + vega_virtio_init(s, mmio_irqchip); + + /* Peripheral address stubs */ + create_unimplemented_device("vega.uart1", + s->memmap[VEGA_UART1].base, s->memmap[VEGA_UART1].size); + create_unimplemented_device("vega.uart2", + s->memmap[VEGA_UART2].base, s->memmap[VEGA_UART2].size); + create_unimplemented_device("vega.uart3", + s->memmap[VEGA_UART3].base, s->memmap[VEGA_UART3].size); + create_unimplemented_device("vega.uart4", + s->memmap[VEGA_UART4].base, s->memmap[VEGA_UART4].size); + create_unimplemented_device("vega.spi0", + s->memmap[VEGA_SPI0].base, s->memmap[VEGA_SPI0].size); + create_unimplemented_device("vega.spi1", + s->memmap[VEGA_SPI1].base, s->memmap[VEGA_SPI1].size); + create_unimplemented_device("vega.i2c0", + s->memmap[VEGA_IIC0].base, s->memmap[VEGA_IIC0].size); + create_unimplemented_device("vega.i2c1", + s->memmap[VEGA_IIC1].base, s->memmap[VEGA_IIC1].size); + create_unimplemented_device("vega.sdhci", + s->memmap[VEGA_SDHCI].base, s->memmap[VEGA_SDHCI].size); + + /* VIRTIO_MMIO */ + for (i =3D 0; i < VEGA_VIRTIO_COUNT; i++) { + sysbus_create_simple("virtio-mmio", + s->memmap[VEGA_VIRTIO].base + i * s->memmap[VEGA_VIRTIO].size, + qdev_get_gpio_in(mmio_irqchip, VEGA_VIRTIO_IRQ + i)); + } + + /* + * Device tree: + * Linux (-kernel + -dtb): load the user-supplied DTB. + * Baremetal (-bios): skip entirely =E2=80=94 no DTB needed. + * Linux without -dtb is not currently supported. + */ + if (machine->dtb) { + machine->fdt =3D load_device_tree(machine->dtb, &s->fdt_size); + if (!machine->fdt) { + error_report("load_device_tree() failed"); + exit(1); + } + } else if (machine->firmware && strcmp(machine->firmware, "none") !=3D= 0) { + /* baremetal: no DTB needed, handled entirely in vega_machine_done= */ + } else if (machine->kernel_filename) { + /* + * Only a -kernel boot actually needs a DTB. A bare machine + * instantiation with neither -kernel nor -bios (e.g. qtest's + * generic qom/hmp smoke tests, or a user just probing -M vega) + * is a valid, inert state and must not be treated as an error. + */ + error_report("VEGA requires -dtb when booting with -kernel; " + "internal device-tree generation is not yet supported= "); + exit(1); + } + + s->machine_done.notify =3D vega_machine_done; + qemu_add_machine_init_done_notifier(&s->machine_done); +} + +/* Instance init */ + +static void vega_machine_instance_init(Object *obj) +{ + RISCVVegaState *s =3D RISCV_VEGA_MACHINE(obj); + + object_property_add_uint64_ptr(obj, "dram-base", &s->dram_base, + OBJ_PROP_FLAG_WRITE); + object_property_set_description(obj, "dram-base", + "Base address of DRAM"); +} + +static bool vega_get_aclint(Object *obj, Error **errp) +{ + return RISCV_VEGA_MACHINE(obj)->have_aclint; +} + +static void vega_set_aclint(Object *obj, bool value, Error **errp) +{ + RISCV_VEGA_MACHINE(obj)->have_aclint =3D value; +} + +/* Class init */ + +static void vega_machine_class_init(ObjectClass *oc, const void *data) +{ + MachineClass *mc =3D MACHINE_CLASS(oc); + + mc->desc =3D "CDAC VEGA series RISC-V SoC"; + mc->init =3D vega_machine_init; + mc->max_cpus =3D VEGA_CPUS_MAX; + mc->default_cpu_type =3D VEGA_CPU; + mc->default_ram_id =3D "riscv_vega_board.ram"; + + object_class_property_add_bool(oc, "aclint", + vega_get_aclint, vega_set_aclint); + object_class_property_set_description(oc, "aclint", + "(TCG only) Enable ACLINT devices"); +} + +/* Type registration */ + +static const TypeInfo vega_machine_typeinfo =3D { + .name =3D MACHINE_TYPE_NAME("vega"), + .parent =3D TYPE_MACHINE, + .class_init =3D vega_machine_class_init, + .instance_init =3D vega_machine_instance_init, + .instance_size =3D sizeof(RISCVVegaState), + .interfaces =3D riscv32_64_machine_interfaces, +}; + +static void vega_machine_init_register_types(void) +{ + type_register_static(&vega_machine_typeinfo); +} + +type_init(vega_machine_init_register_types) diff --git a/include/hw/riscv/vega.h b/include/hw/riscv/vega.h new file mode 100644 index 0000000000..85993fd77c --- /dev/null +++ b/include/hw/riscv/vega.h @@ -0,0 +1,136 @@ +/* + * QEMU RISC-V VEGA machine interface + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2025 C-DAC (Centre for Development of Advanced Computing) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + */ + +#ifndef HW_RISCV_VEGA_H +#define HW_RISCV_VEGA_H + +#include "hw/core/boards.h" +#include "hw/riscv/riscv_hart.h" +#include "hw/core/sysbus.h" + +#if defined(TARGET_RISCV32) +#define VEGA_CPU TYPE_RISCV_CPU_VEGA32 +#elif defined(TARGET_RISCV64) +#define VEGA_CPU TYPE_RISCV_CPU_VEGA64 +#else +#error "Unknown RISCV target" +#endif + +#define VEGA_CPUS_MAX_BITS 2 +#define VEGA_CPUS_MAX (1 << VEGA_CPUS_MAX_BITS) /* 4 */ +#define VEGA_SOCKETS_MAX_BITS 1 +#define VEGA_SOCKETS_MAX (1 << VEGA_SOCKETS_MAX_BITS) /* 2 */ +#define VEGA_VIRTIO_COUNT 4 +#define VEGA_VIRTIO_IRQ 1 + +#define TYPE_RISCV_VEGA_MACHINE MACHINE_TYPE_NAME("vega") +typedef struct RISCVVegaState RISCVVegaState; +DECLARE_INSTANCE_CHECKER(RISCVVegaState, RISCV_VEGA_MACHINE, + TYPE_RISCV_VEGA_MACHINE) + + +struct RISCVVegaState { + /*< private >*/ + MachineState parent; + + /*< public >*/ + Notifier machine_done; + RISCVHartArrayState soc[VEGA_SOCKETS_MAX]; + DeviceState *irqchip[VEGA_SOCKETS_MAX]; + + int fdt_size; + bool have_aclint; + const MemMapEntry *memmap; + + uint64_t dram_base; /* configurable DRAM base address */ + +}; + +/* + * Memory-map index enum. + * Entries are tightly packed =E2=80=94 the array in vega.c must follow th= e same order. + */ +enum { + VEGA_DEBUG, + VEGA_MROM, + VEGA_TEST, + VEGA_CLINT, + VEGA_ACLINT_SSWI, + VEGA_PLIC_ID, + VEGA_UART0, + VEGA_DRAM, + VEGA_SRAM, + VEGA_UART1, + VEGA_UART2, + VEGA_UART3, + VEGA_UART4, + VEGA_SPI0, + VEGA_SPI1, + VEGA_IIC0, + VEGA_IIC1, + VEGA_SDHCI, + VEGA_VIRTIO, +}; + +/* IRQ numbers */ +enum { + UART0_IRQ =3D 10, + UART1_IRQ =3D 10, + UART2_IRQ =3D 10, + UART3_IRQ =3D 10, + UART4_IRQ =3D 10, +}; + +/* + * UART defaults for baremetal (-bios mode, no DTB). + * When booting Linux (-kernel + -dtb), reg-shift is read from + * the /soc/serial node in the DTB at runtime. + * Baremetal is detected by machine->firmware being set. + */ +#define VEGA_UART_DEFAULT_REGSHIFT 2 /* 4-byte stride */ +#define VEGA_UART_DEFAULT_IOWIDTH 4 /* 32-bit bus access */ + +/* CLINT layout (TCG default path) */ +#define VEGA_CLINT_MSWI_OFFSET 0x400 + +/* Interrupt controller sizing */ +#define VEGA_IRQCHIP_NUM_SOURCES 128 /* IRQ 0 (none) + IRQ 1-127 =3D 1= 28 entries */ +#define VEGA_IRQCHIP_NUM_PRIO_BITS 4 +#define VEGA_IRQCHIP_MAX_GUESTS_BITS 3 +#define VEGA_IRQCHIP_MAX_GUESTS ((1U << VEGA_IRQCHIP_MAX_GUESTS_BITS) = - 1U) + +/* PLIC register layout */ +#define VEGA_PLIC_PRIORITY_BASE 0x00 +#define VEGA_PLIC_PENDING_BASE 0x80 +#define VEGA_PLIC_ENABLE_BASE 0x100 /* M-mode enables start at 0x100 */ +#define VEGA_PLIC_ENABLE_STRIDE 0x20 /* stride between M and S contexts= */ +#define VEGA_PLIC_CONTEXT_BASE 0x300 /* M-mode context starts at 0x300 = */ +#define VEGA_PLIC_CONTEXT_STRIDE 0x10 + +#define VEGA_PLIC_SIZE(__num_context) \ + (VEGA_PLIC_CONTEXT_BASE + (__num_context) * VEGA_PLIC_CONTEXT_STRIDE) + +/* FDT cell-size constants */ +#define FDT_PLIC_ADDR_CELLS 0 +#define FDT_PLIC_INT_CELLS 1 +#define FDT_APLIC_INT_CELLS 2 +#define FDT_APLIC_ADDR_CELLS 0 + +#endif /* HW_RISCV_VEGA_H */ --=20 2.43.0 ---------------------------------------------------------------------------= --------------------------------- [ C-DAC is on Social-Media too. Kindly follow us at: Facebook: https://www.facebook.com/CDACINDIA & Twitter: @cdacindia ] This e-mail is for the sole use of the intended recipient(s) and may contain confidential and privileged information. If you are not the intended recipient, please contact the sender by reply e-mail and destroy all copies and the original message. Any unauthorized review, use, disclosure, dissemination, forwarding, printing or copying of this email is strictly prohibited and appropriate legal action will be taken. ---------------------------------------------------------------------------= --------------------------------- From nobody Fri Oct 23 14:30:37 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=cdac.in ARC-Seal: i=1; a=rsa-sha256; t=1792138153; cv=none; d=zohomail.com; s=zohoarc; b=QjaQ8PwF8o2lQbUmSoFsP4vJFcrZaY5eO1a5yTVh4vfJVZdyLRcL/6fjU6WhiE+sSRmWWBBbG8aYDgkOwOaeBl4kFis7uVoI9WkfZDpFf2IHFHxZ2H9ZpHiwAj/Qr4LGTQxRVSVrFd3evnXKGf0wear/qc8cq3c8Lqbjw98Rfc0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792138153; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=O0M8WvGJF2gSWv/JaecqQIOBkc+oOosdI94Qe0lc35s=; b=kh2WZxP+ZCftjbWruBK6KJcJZ9zASp0GSTa3YZHR0+dMKw83okGbktQpyNoFoR2gWARS6s9T0QYqng0TiGciP4i7rSziqfRjdVNHfoYN0ABo8KdjuRbayRsZG3kkSuI9eTPvF5HWFHEBjtd1gPBfkOw91Ic7OH0eyWAseDn+R2U= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792138153126107.3570606761242; Fri, 16 Oct 2026 01:09:13 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xHcza-0003rO-LK; Fri, 16 Oct 2026 04:08:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xHczK-0003oc-II; Fri, 16 Oct 2026 04:08:29 -0400 Received: from mailsender.cdac.in ([196.1.113.117] helo=mailsender-core1.pune.cdac.in) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xHczG-0005xE-Pm; Fri, 16 Oct 2026 04:08:26 -0400 Received: from mscr-int2.pune.cdac.in (mscr-int2.pune.cdac.in [10.208.193.12]) by mailsender.cdac.in (8.15.2/8.15.2/Debian-22ubuntu3) with ESMTP id 69G885BH3825273; Fri, 16 Oct 2026 13:38:06 +0530 Received: from mailgw-cip.pune.cdac.in (mscr-haproxy.pune.cdac.in [10.208.193.46]) by mscr-int2.pune.cdac.in (Postfix) with ESMTP id B7E4F100234DC; Fri, 16 Oct 2026 13:37:55 +0530 (IST) Received: from hdg164.tvm.cdac.in (hd_hdg164.tvm.cdac.in [10.176.18.107]) (Authenticated sender: karthika.b@cdac.in) by mailgw-cip.pune.cdac.in (Postfix) with ESMTPSA id 5684914E17D2; Fri, 16 Oct 2026 13:37:55 +0530 (IST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cdac.in; s=default; t=1792138086; bh=gk3HZKAxOpyO5yJT8ekYuu2NFizbkjOTQwvrWEecYeo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VNQPxLT/5aqhQVBgwYAhx6iW7N9MaTLXt+hWw67L44lOWr1qFkXnzvhvTSqh/ppGN PYOdFyReZkOb2ZnGGSvDg4NCjAQ/dAxFy8UQo1M0bFr8s0diF8+xD9JuEF1tyLhQHH +gORC2DXF3eB03V6nKjJOCtO16OPmUcIYPT7CJSA= X-Auth: karthika.b@cdac.in From: Karthika B To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, sreenadh@cdac.in, raokk@cdac.in, Karthika B , Pierrick Bouvier , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu Subject: [PATCH 5/7] docs/system/riscv: Add VEGA machine documentation Date: Fri, 16 Oct 2026 13:37:05 +0530 Message-ID: <20261016080709.17331-6-karthika.b@cdac.in> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20261016080709.17331-1-karthika.b@cdac.in> References: <385625713.441366.1761727810206@webmail2.cdac.in> <20261016080709.17331-1-karthika.b@cdac.in> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-CDAC-PUNE-MailScanner-Information: Please contact the ISP for more information X-CDAC-PUNE-MailScanner-ID: B7E4F100234DC.A27E0 X-CDAC-PUNE-MailScanner: Found to be clean X-CDAC-PUNE-MailScanner-SpamCheck: not spam, SpamAssassin (not cached, score=-0.999, required 6, ALL_TRUSTED -1.00, URIBL_BLOCKED 0.00) X-CDAC-PUNE-MailScanner-From: karthika.b@cdac.in 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=lists1p.gnu.org; Received-SPF: pass client-ip=196.1.113.117; envelope-from=karthika.b@cdac.in; helo=mailsender-core1.pune.cdac.in X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @cdac.in) X-ZM-MESSAGEID: 1792138159144158500 Signed-off-by: Karthika B --- docs/system/riscv/vega.rst | 219 +++++++++++++++++++++++++++++++++++ docs/system/target-riscv.rst | 1 + 2 files changed, 220 insertions(+) create mode 100644 docs/system/riscv/vega.rst diff --git a/docs/system/riscv/vega.rst b/docs/system/riscv/vega.rst new file mode 100644 index 0000000000..78656682d0 --- /dev/null +++ b/docs/system/riscv/vega.rst @@ -0,0 +1,219 @@ +CDAC VEGA series RISC-V SoC (``vega``) +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +VEGA is a series of 32-bit and 64-bit processors based on the RISC-V ISA, = developed by C-DAC (Centre for Development of Advanced Computing, India) un= der the DIR-V program. The vega QEMU machine model supports both the 32-bit= and 64-bit VEGA variants. + +As with other QEMU RISC-V machine models, vega provides functional emulati= on of the VEGA SoC=E2=80=99s memory map, interrupt controllers, and periphe= rals. + +For more details on the VEGA processor series, please see: +https://vegaprocessors.in/ + +For VEGA documentation, please see: +https://cdac-vega.gitlab.io/ + +Supported devices +------------------ + +The ``vega`` machine supports the following devices: + + * Up to 4 RISC-V cores, RV32 or RV64 + * Platform-Level Interrupt Controller (PLIC) + * Core Level Interruptor (CLINT) + * 1 UART + * 4 virtio-mmio transports + +Boot options +------------ + +The ``vega`` machine supports two boot modes. + +Bare-metal +~~~~~~~~~~ + +Bare-metal payloads are loaded via ``-bios`` (not ``-kernel``). No +device tree is generated or loaded in this mode; the UART is always +accessed with a fixed 4-byte register stride (shift=3D2, io-width=3D4). + +.. code-block:: bash + + $ qemu-system-riscv64 -M vega,dram-base=3D0x80000000 \ + -smp 1 -m 2G \ + -display none -serial stdio \ + -bios path/to/baremetal.elf + +VEGA SDK +^^^^^^^^ + +VEGA SDK can be used to build baremetal example applications, such as +a "hello world" UART program, for both the Thejas32 (``vega32``, RV32) +and Thejas64 (``vega64``, RV64) SoCs. + +Install VEGA tools +'''''''''''''''''' + +For Thejas32 SoC (Aries boards): + +.. code-block:: bash + + $ git clone https://gitlab.com/cdac-vega/vega-tools-rv32.git + $ cd vega-tools-rv32 + $ ./setup-env.sh + $ cd .. + +For Thejas64 SoC: + +.. code-block:: bash + + $ git clone https://gitlab.com/cdac-vega/vega-tools-rv64.git + $ cd vega-tools-rv64 + $ ./setup-env.sh + $ cd .. + +Install VEGA SDK +'''''''''''''''' + +For Thejas32 SoC (Aries boards): + +.. code-block:: bash + + $ git clone https://gitlab.com/cdac-vega/vega-sdk.git + $ cd vega-sdk + $ git checkout aries + $ ./setup.sh + +For Thejas64 SoC: + +.. code-block:: bash + + $ git clone https://gitlab.com/cdac-vega/vega-sdk.git + $ cd vega-sdk + $ ./setup-thejas64.sh + +Build and run the hello world example +'''''''''''''''''''''''''''''''''''''' +.. code-block:: bash + + $ cd vega-sdk + $ cd examples/uart/hello_world + $ make + + +.. note:: + + The ``dram-base`` value must match the address the payload was + actually linked for; it is not a fixed VEGA default. The examples + below use ``dram-base=3D0x20000``, matching this SDK's hello-world + build for both Thejas32 and Thejas64 -- other payloads (e.g. a + Linux boot via BBL) are linked for a different address and need + their own matching ``dram-base`` value. + +.. code-block:: bash + + $ qemu-system-riscv32 -M vega,dram-base=3D0x20000 \ + -smp 1 -m 2G \ + -display none -serial stdio \ + -bios hello.elf + +.. code-block:: bash + + $ qemu-system-riscv64 -M vega,dram-base=3D0x20000 \ + -smp 1 -m 2G \ + -display none -serial stdio \ + -bios hello.elf + +Both should print:: + + Hello World + + +Linux / BBL +~~~~~~~~~~~ + +Linux boot requires a user-supplied device tree via ``-dtb``. The +``vega`` machine does not generate a device tree internally; passing +``-kernel`` without ``-dtb`` (and without ``-bios``) is a +configuration error and QEMU will refuse to start. + +.. code-block:: bash + + $ qemu-system-riscv64 -M vega,dram-base=3D0x400000000 \ + -smp 4 -m 2G \ + -display none -serial stdio -bios none \ + -kernel bbl -dtb vega.dtb -initrd rootfs.cpio + +Networking (virtio-net) can be attached the same way as on other +virtio-mmio boards: + +.. code-block:: bash + + $ qemu-system-riscv64 -M vega,dram-base=3D0x400000000 \ + -smp 4 -m 2G \ + -display none -serial stdio -bios none \ + -kernel bbl -dtb vega.dtb -initrd rootfs.cpio \ + -netdev tap,id=3Dnet0,ifname=3Dtap0,script=3Dno,downscript=3Dno \ + -device virtio-net-device,netdev=3Dnet0 + +.. note:: + + VEGA's PLIC uses the ``cdac,plic-1.0.0`` compatible string, + recognized by CDAC's own PLIC driver bundled in CDAC's + Buildroot-based BBL/Linux builds. The CLINT is addressed as a + standard ``riscv,clint0``, which CDAC's firmware uses directly + without a vendor-specific driver; all CDAC-produced VEGA firmware + variants use this generic CLINT compatible string. + +CPU defaults +------------ + +The ``vega`` machine supports both RV32 and RV64 harts, matching the +VEGA processor series. The CPU type defaults automatically to the +correct width for the binary in use (``qemu-system-riscv32`` selects +``vega32``, ``qemu-system-riscv64`` selects ``vega64``) and bakes in +VEGA's fixed baseline: I, M, A, S and U, Zicsr, and Zifencei, with the +current RISC-V privileged architecture specification and SV32/SV39 +paging respectively. No ``-cpu`` argument is required to boot. +Additional extensions (e.g. F/D/C) can still be enabled explicitly if +needed: + +.. code-block:: bash + + $ qemu-system-riscv64 -M vega -cpu vega64,f=3Dtrue,d=3Dtrue,c=3Dtrue ... + $ qemu-system-riscv32 -M vega -cpu vega32,f=3Dtrue,d=3Dtrue,c=3Dtrue ... + +.. note:: + + ``TYPE_RISCV_CPU_VEGA32``/``TYPE_RISCV_CPU_VEGA64`` are parented on + ``TYPE_RISCV_CPU_SIFIVE_U`` rather than the generic base CPU type, + since the generic type's default ISA extensions cannot be fully + narrowed for VEGA's actual silicon (QEMU's CPU-class extension + merge is additive only). One consequence worth documenting: SiFive + U's default privileged specification version (1.10.0) is explicitly + overridden back to the current version in both VEGA CPU types, + since firmware built against the modern privileged spec can hang + early in boot (in CLINT/timer setup) against the older version. If + you build a custom CPU subtype from a similar parent, do not assume + privileged spec version propagates the way ISA extension bits + might. + +dram-base option +----------------- + +VEGA silicon can be configured with DRAM at different base addresses. +This is exposed as a machine property: + +.. code-block:: bash + + $ qemu-system-riscv64 -M vega,dram-base=3D0x400000000 ... + +If ``dram-base`` is not specified, QEMU falls back to a default +address and prints a warning. + +PLIC and CLINT address overlap +------------------------------- + +On real VEGA silicon, the PLIC and CLINT are mapped at the same base +address but are distinguished by non-overlapping register offset +ranges, decoded internally by the SoC's interconnect. This is a +genuine hardware characteristic, not a QEMU modelling error; compiling +a VEGA device tree will produce a ``dtc`` ``unique_unit_address`` +warning for this reason, which is expected and can be ignored. diff --git a/docs/system/target-riscv.rst b/docs/system/target-riscv.rst index 3ad5d1ddaf..cf056011d5 100644 --- a/docs/system/target-riscv.rst +++ b/docs/system/target-riscv.rst @@ -71,6 +71,7 @@ undocumented; you can get a complete list by running riscv/mips riscv/shakti-c riscv/sifive_u + riscv/vega riscv/virt riscv/xiangshan-kunminghu =20 --=20 2.43.0 ---------------------------------------------------------------------------= --------------------------------- [ C-DAC is on Social-Media too. Kindly follow us at: Facebook: https://www.facebook.com/CDACINDIA & Twitter: @cdacindia ] This e-mail is for the sole use of the intended recipient(s) and may contain confidential and privileged information. If you are not the intended recipient, please contact the sender by reply e-mail and destroy all copies and the original message. Any unauthorized review, use, disclosure, dissemination, forwarding, printing or copying of this email is strictly prohibited and appropriate legal action will be taken. ---------------------------------------------------------------------------= --------------------------------- From nobody Fri Oct 23 14:30:37 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=cdac.in ARC-Seal: i=1; a=rsa-sha256; t=1792138193; cv=none; d=zohomail.com; s=zohoarc; b=aPVsbUqkzjXPeqc/ObFz6ab+NLyzccLP2kuOLtqTD+Y0dZBV7etXJsIn6LgsBbnrtW0gCSWTJLYTKcKQV8Ooa11EB/bYoqYmF3fxpm105tr86CVb9nF4S+cQ8E0RuuUDSyUu7gLFa9OzZA9OHEUcOlh2CiiLCVTeRhVN+3750Y8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792138193; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=zqFBmBVLYbxq+ynhMR9hCNmT/ufpAaBQBwoQK9WANrg=; b=f2ukfx6N2aZydlfoTG2pO0Ri0eG+oUB/sdEWY41lGfdGwKUYF9sk/svMfUIM6DRkbAsnjgqBuVMdKpXj7LQx3AuELrFWWNEnRzqrmzaiQGmdeSvoBqa9opHTopjb+viOKfsqqkWL4N+EYWTKqrWqLs+fFP8gieLAmn64kidbyms= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792138193633466.67528684553554; Fri, 16 Oct 2026 01:09:53 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xHczY-0003qt-Og; Fri, 16 Oct 2026 04:08:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xHczI-0003oH-EA; Fri, 16 Oct 2026 04:08:26 -0400 Received: from mailsender.cdac.in ([196.1.113.117] helo=mailsender-core1.pune.cdac.in) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xHczE-0005x9-Sf; Fri, 16 Oct 2026 04:08:23 -0400 Received: from mscr-int.pune.cdac.in (mscr-int.pune.cdac.in [10.208.193.2]) by mailsender.cdac.in (8.15.2/8.15.2/Debian-22ubuntu3) with ESMTP id 69G887Qr3825284; Fri, 16 Oct 2026 13:38:07 +0530 Received: from mailgw-cip.pune.cdac.in (mscr-haproxy.pune.cdac.in [10.208.193.46]) by mscr-int.pune.cdac.in (Postfix) with ESMTP id EEB9C1000722E; Fri, 16 Oct 2026 13:37:56 +0530 (IST) Received: from hdg164.tvm.cdac.in (hd_hdg164.tvm.cdac.in [10.176.18.107]) (Authenticated sender: karthika.b@cdac.in) by mailgw-cip.pune.cdac.in (Postfix) with ESMTPSA id 9404F14E17D2; Fri, 16 Oct 2026 13:37:56 +0530 (IST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cdac.in; s=default; t=1792138088; bh=8fyoY2xY8ynDtIuX0ixrw2Ej49Klu1ZQgQ2zy0isoH8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=W+4ngDsTfUqGEzIRM9d4hI5vsASaZbxpU8XzbExN46jEQ3ZLB91fcCEPLZe5145ZA CGt8fJarAkJRhTv0oaFHDWqTyJlQLz7V41kE4YITBII50S0qwvHgT3KCWTkv7uoGp1 dT+FV45xok/1y2VvaVXP4QQGg9t2GtUxIaj5MvuA= X-Auth: karthika.b@cdac.in From: Karthika B To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, sreenadh@cdac.in, raokk@cdac.in, Karthika B , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu Subject: [PATCH 6/7] tests/functional: Add VEGA machine functional tests Date: Fri, 16 Oct 2026 13:37:06 +0530 Message-ID: <20261016080709.17331-7-karthika.b@cdac.in> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20261016080709.17331-1-karthika.b@cdac.in> References: <385625713.441366.1761727810206@webmail2.cdac.in> <20261016080709.17331-1-karthika.b@cdac.in> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CDAC-PUNE-MailScanner-Information: Please contact the ISP for more information X-CDAC-PUNE-MailScanner-ID: EEB9C1000722E.A070C X-CDAC-PUNE-MailScanner: Found to be clean X-CDAC-PUNE-MailScanner-SpamCheck: not spam, SpamAssassin (not cached, score=-2.899, required 6, autolearn=not spam, ALL_TRUSTED -1.00, BAYES_00 -1.90, URIBL_BLOCKED 0.00) X-CDAC-PUNE-MailScanner-From: karthika.b@cdac.in 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=lists1p.gnu.org; Received-SPF: pass client-ip=196.1.113.117; envelope-from=karthika.b@cdac.in; helo=mailsender-core1.pune.cdac.in X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @cdac.in) X-ZM-MESSAGEID: 1792138194367158500 Content-Type: text/plain; charset="utf-8" Signed-off-by: Karthika B --- tests/functional/riscv32/meson.build | 1 + tests/functional/riscv32/test_vega.py | 32 ++++++++++++++ tests/functional/riscv64/meson.build | 1 + tests/functional/riscv64/test_vega.py | 63 +++++++++++++++++++++++++++ 4 files changed, 97 insertions(+) create mode 100644 tests/functional/riscv32/test_vega.py create mode 100644 tests/functional/riscv64/test_vega.py diff --git a/tests/functional/riscv32/meson.build b/tests/functional/riscv3= 2/meson.build index f3ebbb8db5..b02c26c186 100644 --- a/tests/functional/riscv32/meson.build +++ b/tests/functional/riscv32/meson.build @@ -7,4 +7,5 @@ tests_riscv32_system_quick =3D [ =20 tests_riscv32_system_thorough =3D [ 'tuxrun', + 'vega', ] diff --git a/tests/functional/riscv32/test_vega.py b/tests/functional/riscv= 32/test_vega.py new file mode 100644 index 0000000000..932819501c --- /dev/null +++ b/tests/functional/riscv32/test_vega.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# +# Functional test that boots a bare-metal hello-world program on the +# VEGA machine (RV32, Thejas32) and checks the console output. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset, QemuSystemTest +from qemu_test.cmd import wait_for_console_pattern + + +class Vega(QemuSystemTest): + + ASSET_HELLO32 =3D Asset( + 'https://gitlab.com/riscv-vega/vega_qemu_test_images/-/raw/v1.0/ba= remetal/hello32.elf', + '77d3449a495b78ff4d7aa93024682d3e8efa10e64a82c6c0029144ddd3b4c638') + + def test_riscv32_vega_hello(self): + self.set_machine('vega') + hello_path =3D self.ASSET_HELLO32.fetch() + + self.vm.set_console() + self.vm.add_args('-bios', hello_path, + '-M', 'vega,dram-base=3D0x20000', + '-no-reboot') + + self.vm.launch() + wait_for_console_pattern(self, 'Hello World') + + +if __name__ =3D=3D '__main__': + QemuSystemTest.main() diff --git a/tests/functional/riscv64/meson.build b/tests/functional/riscv6= 4/meson.build index b996c89d7d..932447144d 100644 --- a/tests/functional/riscv64/meson.build +++ b/tests/functional/riscv64/meson.build @@ -14,4 +14,5 @@ tests_riscv64_system_thorough =3D [ 'boston', 'sifive_u', 'tuxrun', + 'vega', ] diff --git a/tests/functional/riscv64/test_vega.py b/tests/functional/riscv= 64/test_vega.py new file mode 100644 index 0000000000..b71daa7bbb --- /dev/null +++ b/tests/functional/riscv64/test_vega.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +# +# Functional test that boots bare-metal and Linux payloads on the +# VEGA machine (RV64, Thejas64) and checks the console output. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from qemu_test import Asset, LinuxKernelTest, QemuSystemTest +from qemu_test.cmd import wait_for_console_pattern + + +class VegaBaremetal(QemuSystemTest): + + ASSET_HELLO64 =3D Asset( + 'https://gitlab.com/riscv-vega/vega_qemu_test_images/-/raw/v1.0/ba= remetal/hello64.elf', + 'cd2f3b04d8d6cd0ee75e3eeef58988cc02ed783f6f5b3b1d3a95195441fc7f1d') + + def test_riscv64_vega_hello(self): + self.set_machine('vega') + hello_path =3D self.ASSET_HELLO64.fetch() + + self.vm.set_console() + self.vm.add_args('-bios', hello_path, + '-M', 'vega,dram-base=3D0x20000', + '-no-reboot') + + self.vm.launch() + wait_for_console_pattern(self, 'Hello World') + + +class VegaLinux(LinuxKernelTest): + + ASSET_BBL =3D Asset( + 'https://gitlab.com/riscv-vega/vega_qemu_test_images/-/raw/v1.0/li= nux/bbl', + '018fa3e96ec715d4c915c3a85212da6c300c412e56c6c73a16f965526ca8d858') + ASSET_DTB =3D Asset( + 'https://gitlab.com/riscv-vega/vega_qemu_test_images/-/raw/v1.0/li= nux/vega.dtb', + '0b8261051c88e690d6508cb1c774fd3cab97d50570ff668fdfabd0bf52c52414') + ASSET_ROOTFS =3D Asset( + 'https://gitlab.com/riscv-vega/vega_qemu_test_images/-/raw/v1.0/li= nux/rootfs.cpio', + '389a5b9883b14c2a5614ece120abc4ee60543d1110a03a9de35d80405e18c063') + + def test_riscv64_vega_linux(self): + self.set_machine('vega') + bbl_path =3D self.ASSET_BBL.fetch() + dtb_path =3D self.ASSET_DTB.fetch() + rootfs_path =3D self.ASSET_ROOTFS.fetch() + + self.vm.set_console() + self.vm.add_args('-M', 'vega,dram-base=3D0x400000000', + '-m', '2G', + '-bios', 'none', + '-kernel', bbl_path, + '-dtb', dtb_path, + '-initrd', rootfs_path, + '-no-reboot') + + self.vm.launch() + self.wait_for_console_pattern('cdac login:') + + +if __name__ =3D=3D '__main__': + QemuSystemTest.main() --=20 2.43.0 ---------------------------------------------------------------------------= --------------------------------- [ C-DAC is on Social-Media too. Kindly follow us at: Facebook: https://www.facebook.com/CDACINDIA & Twitter: @cdacindia ] This e-mail is for the sole use of the intended recipient(s) and may contain confidential and privileged information. If you are not the intended recipient, please contact the sender by reply e-mail and destroy all copies and the original message. Any unauthorized review, use, disclosure, dissemination, forwarding, printing or copying of this email is strictly prohibited and appropriate legal action will be taken. ---------------------------------------------------------------------------= --------------------------------- From nobody Fri Oct 23 14:30:37 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=cdac.in ARC-Seal: i=1; a=rsa-sha256; t=1792138174; cv=none; d=zohomail.com; s=zohoarc; b=mBS1Od+8u5j9wR5ytv8ITVHbgirCh6bBtoH2mpIvlL2fX6Ubb+lwhqg0f5/8PycEICQgR5cPRn0M9lRHTcFmNQ3wu2T2UD4lD499/lV/j9p1dOaYjcK1iOd80OcBVb/UMdJJiAvUD7AF33CalSU+HSg9xnk9IzADs8sCn8hi/b4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792138174; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=tKGpnTraypuwzjdrAMaO6xADNko8viUQ+avbRlA5vvc=; b=bIp+89SyRrkoR9S6BTN9NkqYUsyggFt/74PV6fT7Ngrki92OuLKRiWJYAKnriOukGWomrz5jQbSt/5lsBgrZSFzE6t+lKBgeI7/vUpPUAiHIJ+stF993brCPCbk2hhD7A4zyxE9+r0zr83F1rVil3N+UdTUo4uqj39PgHXLBXNk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792138174384641.9353365449919; Fri, 16 Oct 2026 01:09:34 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xHczm-0003wA-BZ; Fri, 16 Oct 2026 04:08:54 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xHcza-0003rR-Pa; Fri, 16 Oct 2026 04:08:43 -0400 Received: from mailsender.cdac.in ([196.1.113.117] helo=mailsender-core1.pune.cdac.in) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1xHczW-0005yY-P3; Fri, 16 Oct 2026 04:08:41 -0400 Received: from mscr-int.pune.cdac.in (mscr-int.pune.cdac.in [10.208.193.2]) by mailsender.cdac.in (8.15.2/8.15.2/Debian-22ubuntu3) with ESMTP id 69G88BIF3825318; Fri, 16 Oct 2026 13:38:11 +0530 Received: from mailgw-cip.pune.cdac.in (mscr-haproxy.pune.cdac.in [10.208.193.46]) by mscr-int.pune.cdac.in (Postfix) with ESMTP id D5B9710007297; Fri, 16 Oct 2026 13:38:01 +0530 (IST) Received: from hdg164.tvm.cdac.in (hd_hdg164.tvm.cdac.in [10.176.18.107]) (Authenticated sender: karthika.b@cdac.in) by mailgw-cip.pune.cdac.in (Postfix) with ESMTPSA id 80B6814E17D2; Fri, 16 Oct 2026 13:38:01 +0530 (IST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=cdac.in; s=default; t=1792138093; bh=ctZgAjNW/jTbpIBcY7W8+yJg8zzvQ9YcMD2822CbeH8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dw5V3Lhd3Qmmwx4gKUJPqFZ5dHwAutwsyzb4BxDi/lfn3oP006L0Sub5E5muSNZCs pH9EpJ5rcAiou1rtNmCFqFU+AVVURbG6IFdx97lkmf+6UoRzNkGjFUXyUemPKPL39k 6xEyWslxGb/5jXdPFVXiItBCBiNgBc4Jh7BgBIgY= X-Auth: karthika.b@cdac.in From: Karthika B To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, sreenadh@cdac.in, raokk@cdac.in, Karthika B , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Peter Maydell , Markus Armbruster , Pierrick Bouvier , Thomas Huth Subject: [PATCH 7/7] MAINTAINERS: Add entry for VEGA machine Date: Fri, 16 Oct 2026 13:37:07 +0530 Message-ID: <20261016080709.17331-8-karthika.b@cdac.in> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20261016080709.17331-1-karthika.b@cdac.in> References: <385625713.441366.1761727810206@webmail2.cdac.in> <20261016080709.17331-1-karthika.b@cdac.in> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CDAC-PUNE-MailScanner-Information: Please contact the ISP for more information X-CDAC-PUNE-MailScanner-ID: D5B9710007297.AE1DF X-CDAC-PUNE-MailScanner: Found to be clean X-CDAC-PUNE-MailScanner-SpamCheck: not spam, SpamAssassin (not cached, score=-2.9, required 6, autolearn=not spam, ALL_TRUSTED -1.00, BAYES_00 -1.90) X-CDAC-PUNE-MailScanner-From: karthika.b@cdac.in 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=lists1p.gnu.org; Received-SPF: pass client-ip=196.1.113.117; envelope-from=karthika.b@cdac.in; helo=mailsender-core1.pune.cdac.in X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @cdac.in) X-ZM-MESSAGEID: 1792138176000158500 Content-Type: text/plain; charset="utf-8" Signed-off-by: Karthika B --- MAINTAINERS | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 2b5b581e17..ece538b4f9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1786,6 +1786,20 @@ F: docs/system/riscv/xiangshan-kunminghu.rst F: hw/riscv/xiangshan_kmh.c F: include/hw/riscv/xiangshan_kmh.h =20 +VEGA +M: Karthika B +L: qemu-riscv@nongnu.org +S: Odd Fixes +F: hw/riscv/vega.c +F: hw/intc/vega_plic.c +F: hw/intc/vega_aclint.c +F: include/hw/riscv/vega.h +F: include/hw/intc/vega_plic.h +F: include/hw/intc/vega_aclint.h +F: docs/system/riscv/vega.rst +F: tests/functional/riscv32/test_vega.py +F: tests/functional/riscv64/test_vega.py + RX Machines ----------- rx-gdbsim --=20 2.43.0 ---------------------------------------------------------------------------= --------------------------------- [ C-DAC is on Social-Media too. Kindly follow us at: Facebook: https://www.facebook.com/CDACINDIA & Twitter: @cdacindia ] This e-mail is for the sole use of the intended recipient(s) and may contain confidential and privileged information. If you are not the intended recipient, please contact the sender by reply e-mail and destroy all copies and the original message. Any unauthorized review, use, disclosure, dissemination, forwarding, printing or copying of this email is strictly prohibited and appropriate legal action will be taken. ---------------------------------------------------------------------------= ---------------------------------