{"id":2221053,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2221053/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/patch/20260408042149.1902796-9-brian.cain@oss.qualcomm.com/","project":{"id":14,"url":"http://patchwork.ozlabs.org/api/1.1/projects/14/?format=json","name":"QEMU Development","link_name":"qemu-devel","list_id":"qemu-devel.nongnu.org","list_email":"qemu-devel@nongnu.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20260408042149.1902796-9-brian.cain@oss.qualcomm.com>","date":"2026-04-08T04:21:47","name":"[v4,8/9] hw/hexagon: Define hexagon \"virt\" machine","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"0bbc7d01b5c1c7d0c76079392f90bb7cf5e41635","submitter":{"id":89839,"url":"http://patchwork.ozlabs.org/api/1.1/people/89839/?format=json","name":"Brian Cain","email":"brian.cain@oss.qualcomm.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/qemu-devel/patch/20260408042149.1902796-9-brian.cain@oss.qualcomm.com/mbox/","series":[{"id":499184,"url":"http://patchwork.ozlabs.org/api/1.1/series/499184/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/list/?series=499184","date":"2026-04-08T04:21:47","name":"Hexagon system emulation - Part 3/3","version":4,"mbox":"http://patchwork.ozlabs.org/series/499184/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2221053/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2221053/checks/","tags":{},"headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=qualcomm.com header.i=@qualcomm.com header.a=rsa-sha256\n header.s=qcppdkim1 header.b=mfSpapuU;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com\n header.a=rsa-sha256 header.s=google header.b=UJWNSSCk;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from lists.gnu.org (unknown [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4frX1142Y0z1xv0\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 09 Apr 2026 04:39:49 +1000 (AEST)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wAXoU-000693-7U; Wed, 08 Apr 2026 14:39:42 -0400","from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <brian.cain@oss.qualcomm.com>)\n id 1wAXno-0005ea-Ei\n for qemu-devel@nongnu.org; Wed, 08 Apr 2026 14:39:06 -0400","from mx0b-0031df01.pphosted.com ([205.220.180.131])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <brian.cain@oss.qualcomm.com>)\n id 1wAKQe-0005jR-Jm\n for qemu-devel@nongnu.org; Wed, 08 Apr 2026 00:22:14 -0400","from pps.filterd (m0279872.ppops.net [127.0.0.1])\n by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id\n 637M3ILZ1619592\n for <qemu-devel@nongnu.org>; Wed, 8 Apr 2026 04:22:01 GMT","from mail-dl1-f70.google.com (mail-dl1-f70.google.com\n [74.125.82.70])\n by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ddacrgxpe-1\n (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT)\n for <qemu-devel@nongnu.org>; Wed, 08 Apr 2026 04:22:01 +0000 (GMT)","by mail-dl1-f70.google.com with SMTP id\n a92af1059eb24-12737f276a2so9128498c88.1\n for <qemu-devel@nongnu.org>; Tue, 07 Apr 2026 21:22:01 -0700 (PDT)","from hu-bcain-lv.qualcomm.com (Global_NAT1.qualcomm.com.\n [129.46.96.20]) by smtp.gmail.com with ESMTPSA id\n a92af1059eb24-12bed93f861sm23474816c88.0.2026.04.07.21.21.58\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 07 Apr 2026 21:21:58 -0700 (PDT)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h=\n cc:content-transfer-encoding:content-type:date:from:in-reply-to\n :message-id:mime-version:references:subject:to; s=qcppdkim1; bh=\n Z3/J1BwyXrlk5FAojCmce8KYkpwJi520mHJIgo87T6M=; b=mfSpapuUCY5t7Yfg\n jiglEYzekT9yDRk6FuIm+u96ucciFDFVNbc+JXfLgoDOvq2QF5IsGpP5vjQrtiUA\n cnhk7oEVWi2fzbrjXXG7qgEXk+vyw6rZc/d8Uh29dtw7oS/qr4P1UYL9bU3o9gO1\n 06yT/RcdgfIWBoeE1xWNpjO5KXoRHFV4n7nf9RyhB7EBGo4K7L681rOP25PmbGP2\n Jl8CuaaidsWF52q4RwvQhsx8GN72xImH33vgSSeFOfuKKsxWwYSP6RxMOLkq1DqN\n W4gAQrnUNB9j1PGfyXJHGnRS30r++W5CLj14eI1r8kJruPoPchJWl/Ldk1B8rLcF\n vg2xFA==","v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=oss.qualcomm.com; s=google; t=1775622120; x=1776226920; darn=nongnu.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=Z3/J1BwyXrlk5FAojCmce8KYkpwJi520mHJIgo87T6M=;\n b=UJWNSSCkEdTf5MpMkZQxSTmZrwPVgXDplQVzr0n2DQYGnhyUejjEJN3cYR3wrUl9BM\n 7zoZFz0izPr5mHQ8VSML9uzsQ2Fz7xlQrOoEtOgkRzt37zBuOPXNh3lTtL0oUJ2naYX4\n 1Hgnqbc2nglEaRYrT/EkRtQheGqUAr4Hd4kB30JZ3ofhu2ZlfejUPguUstxgSKCApseS\n chWQZJ4tvSn/h4W+wNB1hdJ5V9tYbPLhpAG1h7+34l7K8xVhvv6nWTCbz7GOaXxL5EoG\n 4TZYaI9fa9IHUPDVTJBwG3vf7EzTDt5B0ebMDGCOQkC/56EON1Ix8dWkJD2R5N7g0Gub\n xZRA=="],"X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1775622120; x=1776226920;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=Z3/J1BwyXrlk5FAojCmce8KYkpwJi520mHJIgo87T6M=;\n b=Ljg/UkvOtam+/B4vI5UebsdbubxUwUCJ4cnzMDsK73w8QyFAesupQ/fXVSYKjUEG8w\n DrOQjbv/YtA5av3VTrgnHqPvYmuCRJ1xb4afXS9eNBHzHZstn1BjGlc70LnDH75O7ufX\n INE3Rj5+ewR/mOz97G6s14069qaVmeqfjUktE0RZBQjCEhYP44XzbkSvN1wb7yv9Hzjf\n y9YtrcVa/sCdxgMGsZLYOpjwO4/PaK49NfFI1TkXZd+nk5RO2jqd1nmMV9PcdkNlWtp2\n OpCa8O+MOcOcUUIrUr+ABC4dHRy5xgY/bvR0U1fhnFAsIZcRMjTU1PuE7PVwkUttUBDK\n ufAg==","X-Gm-Message-State":"AOJu0YwYom5RVGrj33S4xduqtZRyQ9/PbrjlOq19g5qWKTQu6C/nMNko\n faZ2jm2UUT5KzpH4khLMKprCMpPTyE7lrMOMOUKmDXu/ZafoEU//qFP+2OaXnp1Hzv/8WesaeE7\n 0rlr37MDxSoXuUcaKdsLMkm4dNPJkg3hTkReC6cy+TGF5icX1xxvRTtpvfj61jg9JwQ==","X-Gm-Gg":"AeBDiet8nPwpv4wdlLMAJeO0RueSBz3EflPeQ6k/B6xWsTW5ofaWiz3rytTblmVO9r8\n IFPxV2pKRvBTesTR0qakvRXd1aplx2tg9qyqolUtJQJAEMK4/T155On2nP6K8aGnYYbQW/MofHz\n p7bPzPn01hCw9mfze6wQ1yucJosi2FdFBphvc1gqK7nO7xk6Uk6YnJxIUhTvf4Bs8sWRc5fR7zT\n vxw3kRSPNtrAlYQpTLxYP2vLdnNsm9gS3PmHo706HDSMMK4cu47txJjgHJV7h3f++Y6uTSayD3y\n kygVWdrFNn4fEGQs8RYvPYFX8rGuAUNy8jr+RPGcD0QhPoZMtHL81vseZM5dXe5j6rYzDuE5hlS\n UR0rtf48Ljenyn8DfumUadZUGA87KamXgubqkTzsKux19S8Lmbv2VMpQx13i22ojvHuB3cA==","X-Received":["by 2002:a05:7022:52b:b0:127:15cd:9f52 with SMTP id\n a92af1059eb24-12bfb6ee075mr9617922c88.5.1775622120008;\n Tue, 07 Apr 2026 21:22:00 -0700 (PDT)","by 2002:a05:7022:52b:b0:127:15cd:9f52 with SMTP id\n a92af1059eb24-12bfb6ee075mr9617907c88.5.1775622119287;\n Tue, 07 Apr 2026 21:21:59 -0700 (PDT)"],"From":"Brian Cain <brian.cain@oss.qualcomm.com>","To":"qemu-devel@nongnu.org","Cc":"brian.cain@oss.qualcomm.com, philmd@linaro.org, ltaylorsimpson@gmail.com,\n matheus.bernardino@oss.qualcomm.com, marco.liebel@oss.qualcomm.com,\n quic_mburton@quicinc.com, sid.manning@oss.qualcomm.com, ale@rev.ng,\n anjo@rev.ng, Brian Cain <bcain@quicinc.com>,\n Paolo Bonzini <pbonzini@redhat.com>, Kevin Wolf <kwolf@redhat.com>,\n Hanna Reitz <hreitz@redhat.com>,\n qemu-block@nongnu.org (open list:Block layer core)","Subject":"[PATCH v4 8/9] hw/hexagon: Define hexagon \"virt\" machine","Date":"Tue,  7 Apr 2026 21:21:47 -0700","Message-Id":"<20260408042149.1902796-9-brian.cain@oss.qualcomm.com>","X-Mailer":"git-send-email 2.34.1","In-Reply-To":"<20260408042149.1902796-1-brian.cain@oss.qualcomm.com>","References":"<20260408042149.1902796-1-brian.cain@oss.qualcomm.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"base64","X-Proofpoint-ORIG-GUID":"E3QoKzUkJRDF0tcP3D6xN5MLUVnf2Shs","X-Proofpoint-GUID":"E3QoKzUkJRDF0tcP3D6xN5MLUVnf2Shs","X-Authority-Analysis":"v=2.4 cv=WZs8rUhX c=1 sm=1 tr=0 ts=69d5d7e9 cx=c_pps\n a=SvEPeNj+VMjHSW//kvnxuw==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17\n a=IkcTkHD0fZMA:10 a=A5OVakUREuEA:10 a=s4-Qcg_JpJYA:10\n a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=yx91gb_oNiZeI1HMLzn7:22\n a=COk6AnOGAAAA:8 a=EUspDBNiAAAA:8 a=NKwyhsPI2JXA-XLkMRkA:9 a=QEXdDO2ut3YA:10\n a=Kq8ClHjjuc5pcCNDwlU0:22 a=TjNXssC_j7lpFel5tvFf:22","X-Proofpoint-Spam-Details-Enc":"AW1haW4tMjYwNDA4MDAzNiBTYWx0ZWRfX4CUkT1ds3CD5\n xwQ8RRRpM84baSiiYoNuZOpTLURm7jVlsemvNVp6FlcY9l+Z4aSwtrdihbISxGMbuus2Rvb/Lk4\n GLKkuJ8Dql+lTI8kKb+9sXQ7UtxRRx7DB/grJ1FI0FgWa7k/wqzVEDoYu2u3Wd1olRgUyXBOAum\n NSSAiEC3O69ZwC9xme9h7KbHGpWz9xR0/uZ22WcXP7rgnvUPqk7JkRy/Q/VEIQQ/e7QhDqC+ujw\n fzdTaYDPvBfjLGPMrH4CJHT49B/URy89v4r9U3N0CYZdI25iMRrK1zD/+YMYcY3AiKL7jizySZh\n mO2x2y1WKKxq5YgVM3uzdLyu12F8fXrPEzHdqpkZ4K05vvADP7+it3lXios/GRKQXXEMb8Q3mmJ\n Hc98U54XOTHyhTDtffqR2evXgVUgPfDw95KHBGnJanXzgIF2Q4F16ORlK1ahT4jc0zkwy9oG9hz\n EqbbLcNNv9pG3Et19iw==","X-Proofpoint-Virus-Version":"vendor=baseguard\n engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.51,FMLib:17.12.100.49\n definitions=2026-04-08_02,2026-04-07_05,2025-10-01_01","X-Proofpoint-Spam-Details":"rule=outbound_notspam policy=outbound score=0\n suspectscore=0 malwarescore=0 adultscore=0 phishscore=0 clxscore=1015\n bulkscore=0 lowpriorityscore=0 spamscore=0 priorityscore=1501 impostorscore=0\n classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0\n reason=mlx scancount=1 engine=8.22.0-2604010000 definitions=main-2604080036","Received-SPF":"pass client-ip=205.220.180.131;\n envelope-from=brian.cain@oss.qualcomm.com; helo=mx0b-0031df01.pphosted.com","X-Spam_score_int":"-27","X-Spam_score":"-2.8","X-Spam_bar":"--","X-Spam_report":"(-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001,\n RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001,\n SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no","X-Spam_action":"no action","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"qemu development <qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"},"content":"From: Brian Cain <bcain@quicinc.com>\n\nSigned-off-by: Brian Cain <brian.cain@oss.qualcomm.com>\n---\n configs/devices/hexagon-softmmu/default.mak |   1 +\n configs/targets/hexagon-softmmu.mak         |   1 +\n include/hw/hexagon/virt.h                   |  43 ++\n hw/hexagon/virt.c                           | 456 ++++++++++++++++++++\n target/hexagon/cpu.c                        |   2 +\n hw/hexagon/Kconfig                          |  10 +\n hw/hexagon/meson.build                      |   2 +\n tests/qemu-iotests/testenv.py               |   1 +\n 8 files changed, 516 insertions(+)\n create mode 100644 include/hw/hexagon/virt.h\n create mode 100644 hw/hexagon/virt.c","diff":"diff --git a/configs/devices/hexagon-softmmu/default.mak b/configs/devices/hexagon-softmmu/default.mak\nindex 08e709aea72..37b4f9f3237 100644\n--- a/configs/devices/hexagon-softmmu/default.mak\n+++ b/configs/devices/hexagon-softmmu/default.mak\n@@ -3,5 +3,6 @@\n # Uncomment the following lines to disable these optional devices:\n \n # Boards are selected by default, uncomment to keep out of the build.\n+# CONFIG_HEX_VIRT=y\n # CONFIG_HEX_DSP=y\n # CONFIG_L2VIC=y\ndiff --git a/configs/targets/hexagon-softmmu.mak b/configs/targets/hexagon-softmmu.mak\nindex fdfa29b4f39..a77c100f0c5 100644\n--- a/configs/targets/hexagon-softmmu.mak\n+++ b/configs/targets/hexagon-softmmu.mak\n@@ -5,3 +5,4 @@ TARGET_XML_FILES=hexagon-core.xml hexagon-hvx.xml\n TARGET_LONG_BITS=32\n TARGET_NOT_USING_LEGACY_LDST_PHYS_API=y\n TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API=y\n+TARGET_NEED_FDT=y\ndiff --git a/include/hw/hexagon/virt.h b/include/hw/hexagon/virt.h\nnew file mode 100644\nindex 00000000000..a54eac5cf00\n--- /dev/null\n+++ b/include/hw/hexagon/virt.h\n@@ -0,0 +1,43 @@\n+/*\n+ * Definitions for hexagon virt board.\n+ *\n+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.\n+ * SPDX-License-Identifier: GPL-2.0-or-later\n+ */\n+\n+#ifndef HW_HEXAGONVIRT_H\n+#define HW_HEXAGONVIRT_H\n+\n+#include \"hw/core/boards.h\"\n+#include \"target/hexagon/cpu.h\"\n+\n+struct HexagonVirtMachineState {\n+    /*< private >*/\n+    MachineState parent_obj;\n+\n+    int fdt_size;\n+    MemoryRegion *sys;\n+    MemoryRegion cfgtable;\n+    MemoryRegion ram;\n+    MemoryRegion tcm;\n+    MemoryRegion vtcm;\n+    MemoryRegion bios;\n+    DeviceState *l2vic;\n+    Clock *apb_clk;\n+};\n+\n+void hexagon_load_fdt(const struct HexagonVirtMachineState *vms);\n+\n+enum {\n+    VIRT_UART0,\n+    VIRT_QTMR0,\n+    VIRT_QTMR1,\n+    VIRT_GPT,\n+    VIRT_MMIO,\n+    VIRT_FDT,\n+};\n+\n+#define TYPE_HEXAGON_VIRT_MACHINE MACHINE_TYPE_NAME(\"virt\")\n+OBJECT_DECLARE_SIMPLE_TYPE(HexagonVirtMachineState, HEXAGON_VIRT_MACHINE)\n+\n+#endif /* HW_HEXAGONVIRT_H */\ndiff --git a/hw/hexagon/virt.c b/hw/hexagon/virt.c\nnew file mode 100644\nindex 00000000000..49ee1aad2fe\n--- /dev/null\n+++ b/hw/hexagon/virt.c\n@@ -0,0 +1,456 @@\n+/*\n+ * Hexagon virt emulation\n+ *\n+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.\n+ * SPDX-License-Identifier: GPL-2.0-or-later\n+ */\n+\n+#include \"qemu/osdep.h\"\n+#include \"qapi/error.h\"\n+#include \"hw/hexagon/virt.h\"\n+#include \"elf.h\"\n+#include \"hw/char/pl011.h\"\n+#include \"hw/core/clock.h\"\n+#include \"hw/core/sysbus-fdt.h\"\n+#include \"hw/hexagon/hexagon.h\"\n+#include \"hw/hexagon/hexagon_globalreg.h\"\n+#include \"hw/hexagon/hexagon_tlb.h\"\n+#include \"hw/core/loader.h\"\n+#include \"hw/core/qdev-properties.h\"\n+#include \"hw/core/qdev-clock.h\"\n+#include \"hw/core/register.h\"\n+#include \"qemu/error-report.h\"\n+#include \"qemu/guest-random.h\"\n+#include \"qemu/units.h\"\n+#include \"elf.h\"\n+#include \"machine_cfg_v68n_1024.h.inc\"\n+#include \"system/address-spaces.h\"\n+#include \"system/device_tree.h\"\n+#include \"system/reset.h\"\n+#include \"system/system.h\"\n+#include <libfdt.h>\n+\n+static const int VIRTIO_DEV_COUNT = 8;\n+\n+static const MemMapEntry base_memmap[] = {\n+    [VIRT_UART0] = { 0x10000000, 0x00000200 },\n+    [VIRT_MMIO] = { 0x11000000, 0x1000000, },\n+    [VIRT_GPT] = { 0xab000000, 0x00001000 },\n+    [VIRT_FDT] = { 0x99800000, 0x00400000 },\n+};\n+\n+static const int irqmap[] = {\n+    [VIRT_MMIO] = 18, /* ...to 18 + VIRTIO_DEV_COUNT - 1 */\n+    [VIRT_GPT] = 12,\n+    [VIRT_UART0] = 15,\n+    [VIRT_QTMR0] = 2,\n+    [VIRT_QTMR1] = 4,\n+};\n+\n+\n+static void create_fdt(HexagonVirtMachineState *vms)\n+{\n+    MachineState *ms = MACHINE(vms);\n+    void *fdt = create_device_tree(&vms->fdt_size);\n+    uint8_t rng_seed[32];\n+\n+    if (!fdt) {\n+        error_report(\"create_device_tree() failed\");\n+        exit(1);\n+    }\n+\n+    ms->fdt = fdt;\n+\n+    qemu_fdt_setprop_cell(fdt, \"/\", \"#address-cells\", 0x2);\n+    qemu_fdt_setprop_cell(fdt, \"/\", \"#size-cells\", 0x1);\n+    qemu_fdt_setprop_string(fdt, \"/\", \"model\", \"hexagon-virt,qemu\");\n+    qemu_fdt_setprop_string(fdt, \"/\", \"compatible\", \"qcom,sm8150\");\n+\n+    qemu_fdt_add_subnode(fdt, \"/soc\");\n+    qemu_fdt_setprop_cell(fdt, \"/soc\", \"#address-cells\", 0x2);\n+    qemu_fdt_setprop_cell(fdt, \"/soc\", \"#size-cells\", 0x1);\n+    qemu_fdt_setprop(fdt, \"/soc\", \"ranges\", NULL, 0);\n+\n+    qemu_fdt_add_subnode(fdt, \"/chosen\");\n+    qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));\n+    qemu_fdt_setprop(fdt, \"/chosen\", \"rng-seed\", rng_seed, sizeof(rng_seed));\n+}\n+\n+static void fdt_add_hvx(HexagonVirtMachineState *vms,\n+                        const struct hexagon_machine_config *m_cfg,\n+                        Error **errp)\n+{\n+    const MachineState *ms = MACHINE(vms);\n+    uint32_t vtcm_size_bytes = m_cfg->cfgtable.vtcm_size_kb * 1024;\n+    if (vtcm_size_bytes > 0) {\n+        memory_region_init_ram(&vms->vtcm, NULL, \"vtcm.ram\", vtcm_size_bytes,\n+                               errp);\n+        memory_region_add_subregion(vms->sys, m_cfg->cfgtable.vtcm_base << 16,\n+                                    &vms->vtcm);\n+\n+        qemu_fdt_add_subnode(ms->fdt, \"/soc/vtcm\");\n+        qemu_fdt_setprop_string(ms->fdt, \"/soc/vtcm\", \"compatible\",\n+                                \"qcom,hexagon_vtcm\");\n+\n+        assert(sizeof(m_cfg->cfgtable.vtcm_base) == sizeof(uint32_t));\n+        qemu_fdt_setprop_cells(ms->fdt, \"/soc/vtcm\", \"reg\", 0,\n+                               m_cfg->cfgtable.vtcm_base << 16,\n+                               vtcm_size_bytes);\n+    }\n+\n+    if (m_cfg->cfgtable.ext_contexts > 0) {\n+        qemu_fdt_add_subnode(ms->fdt, \"/soc/hvx\");\n+        qemu_fdt_setprop_string(ms->fdt, \"/soc/hvx\", \"compatible\",\n+                                \"qcom,hexagon-hvx\");\n+        qemu_fdt_setprop_cells(ms->fdt, \"/soc/hvx\", \"qcom,hvx-max-ctxts\",\n+                               m_cfg->cfgtable.ext_contexts);\n+        qemu_fdt_setprop_cells(ms->fdt, \"/soc/hvx\", \"qcom,hvx-vlength\",\n+                               m_cfg->cfgtable.hvx_vec_log_length);\n+    }\n+}\n+\n+static int32_t irq_hvm_ic_phandle = -1;\n+static void fdt_add_hvm_pic_node(HexagonVirtMachineState *vms,\n+                                 const struct hexagon_machine_config *m_cfg)\n+{\n+    MachineState *ms = MACHINE(vms);\n+    irq_hvm_ic_phandle = qemu_fdt_alloc_phandle(ms->fdt);\n+\n+    qemu_fdt_setprop_cell(ms->fdt, \"/soc\", \"interrupt-parent\",\n+                          irq_hvm_ic_phandle);\n+\n+    qemu_fdt_add_subnode(ms->fdt, \"/soc/interrupt-controller\");\n+    qemu_fdt_setprop_cell(ms->fdt, \"/soc/interrupt-controller\",\n+                          \"#address-cells\", 2);\n+    qemu_fdt_setprop_cell(ms->fdt, \"/soc/interrupt-controller\",\n+                          \"#interrupt-cells\", 2);\n+    qemu_fdt_setprop_string(ms->fdt, \"/soc/interrupt-controller\", \"compatible\",\n+                            \"qcom,h2-pic,hvm-pic\");\n+    qemu_fdt_setprop(ms->fdt, \"/soc/interrupt-controller\",\n+                     \"interrupt-controller\", NULL, 0);\n+    qemu_fdt_setprop_cell(ms->fdt, \"/soc/interrupt-controller\", \"phandle\",\n+                          irq_hvm_ic_phandle);\n+\n+    sysbus_mmio_map(SYS_BUS_DEVICE(vms->l2vic), 1,\n+                    m_cfg->cfgtable.fastl2vic_base << 16);\n+}\n+\n+\n+static void fdt_add_gpt_node(HexagonVirtMachineState *vms)\n+{\n+    g_autofree char *name = NULL;\n+    MachineState *ms = MACHINE(vms);\n+\n+    name = g_strdup_printf(\"/soc/gpt@%\" PRIx64,\n+                           (int64_t)base_memmap[VIRT_GPT].base);\n+    qemu_fdt_add_subnode(ms->fdt, name);\n+    qemu_fdt_setprop_string(ms->fdt, name, \"compatible\",\n+                            \"qcom,h2-timer,hvm-timer\");\n+    qemu_fdt_setprop_cells(ms->fdt, name, \"interrupts\", irqmap[VIRT_GPT], 0);\n+    qemu_fdt_setprop_cells(ms->fdt, name, \"reg\", 0x0,\n+                           base_memmap[VIRT_GPT].base,\n+                           base_memmap[VIRT_GPT].size);\n+}\n+\n+static int32_t clock_phandle = -1;\n+static void fdt_add_clocks(const HexagonVirtMachineState *vms)\n+{\n+    MachineState *ms = MACHINE(vms);\n+    clock_phandle = qemu_fdt_alloc_phandle(ms->fdt);\n+    qemu_fdt_add_subnode(ms->fdt, \"/apb-pclk\");\n+    qemu_fdt_setprop_string(ms->fdt, \"/apb-pclk\", \"compatible\", \"fixed-clock\");\n+    qemu_fdt_setprop_cell(ms->fdt, \"/apb-pclk\", \"#clock-cells\", 0x0);\n+    qemu_fdt_setprop_cell(ms->fdt, \"/apb-pclk\", \"clock-frequency\", 24000000);\n+    qemu_fdt_setprop_string(ms->fdt, \"/apb-pclk\", \"clock-output-names\",\n+                            \"clk24mhz\");\n+    qemu_fdt_setprop_cell(ms->fdt, \"/apb-pclk\", \"phandle\", clock_phandle);\n+}\n+\n+static void fdt_add_uart(const HexagonVirtMachineState *vms, int uart)\n+{\n+    char *nodename;\n+    hwaddr base = base_memmap[uart].base;\n+    hwaddr size = base_memmap[uart].size;\n+    assert(uart == 0);\n+    int irq = irqmap[VIRT_UART0 + uart];\n+    const char compat[] = \"arm,pl011\\0arm,primecell\";\n+    const char clocknames[] = \"uartclk\\0apb_pclk\";\n+    MachineState *ms = MACHINE(vms);\n+    DeviceState *dev;\n+    SysBusDevice *s;\n+\n+    dev = qdev_new(TYPE_PL011);\n+    s = SYS_BUS_DEVICE(dev);\n+    qdev_prop_set_chr(dev, \"chardev\", serial_hd(0));\n+    qdev_connect_clock_in(dev, \"clk\", vms->apb_clk);\n+    sysbus_realize_and_unref(s, &error_fatal);\n+    sysbus_mmio_map(s, 0, base);\n+    if (vms->l2vic) {\n+        sysbus_connect_irq(s, 0, qdev_get_gpio_in(vms->l2vic, irq));\n+    }\n+\n+    nodename = g_strdup_printf(\"/pl011@%\" PRIx64, base);\n+    qemu_fdt_add_subnode(ms->fdt, nodename);\n+\n+    /* Note that we can't use setprop_string because of the embedded NUL */\n+    qemu_fdt_setprop(ms->fdt, nodename, \"compatible\", compat, sizeof(compat));\n+    qemu_fdt_setprop_cells(ms->fdt, nodename, \"reg\", 0, base, size);\n+    if (vms->l2vic) {\n+        qemu_fdt_setprop_cells(ms->fdt, nodename, \"interrupts\",\n+                               32 + irq, 0);\n+        qemu_fdt_setprop_cell(ms->fdt, nodename, \"interrupt-parent\",\n+                              irq_hvm_ic_phandle);\n+    }\n+    qemu_fdt_setprop_cells(ms->fdt, nodename, \"clocks\", clock_phandle,\n+                           clock_phandle);\n+    qemu_fdt_setprop(ms->fdt, nodename, \"clock-names\", clocknames,\n+                     sizeof(clocknames));\n+\n+    qemu_fdt_setprop_string(ms->fdt, \"/chosen\", \"stdout-path\", nodename);\n+    qemu_fdt_add_subnode(ms->fdt, \"/aliases\");\n+    qemu_fdt_setprop_string(ms->fdt, \"/aliases\", \"serial0\", nodename);\n+\n+    g_free(nodename);\n+}\n+\n+static void fdt_add_cpu_nodes(const HexagonVirtMachineState *vms)\n+{\n+    MachineState *ms = MACHINE(vms);\n+    qemu_fdt_add_subnode(ms->fdt, \"/cpus\");\n+    qemu_fdt_setprop_cell(ms->fdt, \"/cpus\", \"#address-cells\", 0x1);\n+    qemu_fdt_setprop_cell(ms->fdt, \"/cpus\", \"#size-cells\", 0x0);\n+\n+    /* cpu nodes */\n+    for (int num = ms->smp.cpus - 1; num >= 0; num--) {\n+        char *nodename = g_strdup_printf(\"/cpus/cpu@%d\", num);\n+        qemu_fdt_add_subnode(ms->fdt, nodename);\n+        qemu_fdt_setprop_string(ms->fdt, nodename, \"device_type\", \"cpu\");\n+        qemu_fdt_setprop_cell(ms->fdt, nodename, \"reg\", num);\n+        qemu_fdt_setprop_cell(ms->fdt, nodename, \"phandle\",\n+                              qemu_fdt_alloc_phandle(ms->fdt));\n+        g_free(nodename);\n+    }\n+}\n+\n+\n+static void fdt_add_virtio_devices(const HexagonVirtMachineState *vms)\n+{\n+    MachineState *ms = MACHINE(vms);\n+    /* VirtIO MMIO devices */\n+    for (int i = 0; i < VIRTIO_DEV_COUNT; i++) {\n+        char *nodename;\n+        int irq = irqmap[VIRT_MMIO] + i;\n+        size_t size = base_memmap[VIRT_MMIO].size;\n+        hwaddr base = base_memmap[VIRT_MMIO].base + i * size;\n+\n+        nodename = g_strdup_printf(\"/virtio_mmio@%\" PRIx64, base);\n+        qemu_fdt_add_subnode(ms->fdt, nodename);\n+        qemu_fdt_setprop_string(ms->fdt, nodename, \"compatible\", \"virtio,mmio\");\n+        qemu_fdt_setprop_sized_cells(ms->fdt, nodename, \"reg\", 2, base, 1,\n+                                     size);\n+        qemu_fdt_setprop_cells(ms->fdt, nodename, \"interrupts\", irq, 0);\n+        qemu_fdt_setprop_cell(ms->fdt, nodename, \"interrupt-parent\",\n+                              irq_hvm_ic_phandle);\n+\n+        sysbus_create_simple(\n+            \"virtio-mmio\", base,\n+            qdev_get_gpio_in(vms->l2vic, irqmap[VIRT_MMIO] + i));\n+\n+        g_free(nodename);\n+    }\n+}\n+\n+static void virt_instance_init(Object *obj)\n+{\n+    HexagonVirtMachineState *vms = HEXAGON_VIRT_MACHINE(obj);\n+\n+    create_fdt(vms);\n+}\n+\n+void hexagon_load_fdt(const HexagonVirtMachineState *vms)\n+{\n+    MachineState *ms = MACHINE(vms);\n+    hwaddr fdt_addr = base_memmap[VIRT_FDT].base;\n+    uint32_t fdtsize = vms->fdt_size;\n+\n+    g_assert(fdtsize <= base_memmap[VIRT_FDT].size);\n+    /* copy in the device tree */\n+    rom_add_blob_fixed_as(\"fdt\", ms->fdt, fdtsize, fdt_addr,\n+                          &address_space_memory);\n+    qemu_register_reset_nosnapshotload(\n+        qemu_fdt_randomize_seeds,\n+        rom_ptr_for_as(&address_space_memory, fdt_addr, fdtsize));\n+}\n+\n+static uint64_t load_kernel(const HexagonVirtMachineState *vms)\n+{\n+    MachineState *ms = MACHINE(vms);\n+    uint64_t entry = 0;\n+    if (load_elf_ram_sym(ms->kernel_filename, NULL, NULL, NULL, &entry, NULL,\n+                         NULL, NULL, 0, EM_HEXAGON, 0, 0, &address_space_memory,\n+                         false, NULL) > 0) {\n+        return entry;\n+    }\n+    error_report(\"error loading '%s'\", ms->kernel_filename);\n+    exit(1);\n+}\n+\n+static uint64_t load_bios(HexagonVirtMachineState *vms)\n+{\n+    MachineState *ms = MACHINE(vms);\n+    uint64_t bios_addr = 0x0;  /* Load BIOS at reset vector address 0x0 */\n+    int bios_size;\n+\n+    bios_size = load_image_targphys(ms->firmware ?: \"\",\n+                                    bios_addr, 64 * 1024, NULL);\n+    if (bios_size < 0) {\n+        error_report(\"Could not load BIOS '%s'\", ms->firmware ?: \"\");\n+        exit(1);\n+    }\n+\n+    return bios_addr;  /* Return entry point at address 0x0 */\n+}\n+\n+static void do_cpu_reset(void *opaque)\n+{\n+    HexagonCPU *cpu = opaque;\n+    CPUState *cs = CPU(cpu);\n+    cpu_reset(cs);\n+}\n+\n+static void virt_init(MachineState *ms)\n+{\n+    HexagonVirtMachineState *vms = HEXAGON_VIRT_MACHINE(ms);\n+    const struct hexagon_machine_config *m_cfg = &v68n_1024;\n+    const char *cpu_model;\n+    DeviceState *gsregs_dev;\n+    DeviceState *tlb_dev;\n+    HexagonCPU *cpu_0;\n+\n+    qemu_fdt_setprop_string(ms->fdt, \"/chosen\", \"bootargs\", ms->kernel_cmdline);\n+\n+    vms->sys = get_system_memory();\n+\n+    /* Create APB clock for peripherals */\n+    vms->apb_clk = clock_new(OBJECT(ms), \"apb-pclk\");\n+    clock_set_hz(vms->apb_clk, 24000000);\n+\n+    memory_region_init_ram(&vms->ram, NULL, \"ddr.ram\", ms->ram_size,\n+                           &error_fatal);\n+    memory_region_add_subregion(vms->sys, 0x0, &vms->ram);\n+\n+    if (m_cfg->l2tcm_size) {\n+        memory_region_init_ram(&vms->tcm, NULL, \"tcm.ram\", m_cfg->l2tcm_size,\n+                               &error_fatal);\n+        memory_region_add_subregion(vms->sys, m_cfg->cfgtable.l2tcm_base << 16,\n+                                    &vms->tcm);\n+    }\n+\n+    memory_region_init_rom(&vms->cfgtable, NULL, \"config_table.rom\",\n+                           sizeof(m_cfg->cfgtable), &error_fatal);\n+    memory_region_add_subregion(vms->sys, m_cfg->cfgbase, &vms->cfgtable);\n+    fdt_add_hvx(vms, m_cfg, &error_fatal);\n+    cpu_model = ms->cpu_type;\n+\n+    if (!cpu_model) {\n+        cpu_model = HEXAGON_CPU_TYPE_NAME(\"v73\");\n+    }\n+\n+    gsregs_dev = qdev_new(TYPE_HEXAGON_GLOBALREG);\n+    object_property_add_child(OBJECT(ms), \"global-regs\", OBJECT(gsregs_dev));\n+    qdev_prop_set_uint64(gsregs_dev, \"config-table-addr\", m_cfg->cfgbase);\n+    qdev_prop_set_uint32(gsregs_dev, \"dsp-rev\", v68_rev);\n+    sysbus_realize_and_unref(SYS_BUS_DEVICE(gsregs_dev), &error_fatal);\n+\n+    tlb_dev = qdev_new(TYPE_HEXAGON_TLB);\n+    object_property_add_child(OBJECT(ms), \"tlb\", OBJECT(tlb_dev));\n+    qdev_prop_set_uint32(tlb_dev, \"num-entries\",\n+                         m_cfg->cfgtable.jtlb_size_entries);\n+    sysbus_realize_and_unref(SYS_BUS_DEVICE(tlb_dev), &error_fatal);\n+\n+    cpu_0 = NULL;\n+    for (int i = 0; i < ms->smp.cpus; i++) {\n+        HexagonCPU *cpu = HEXAGON_CPU(object_new(ms->cpu_type));\n+        qemu_register_reset(do_cpu_reset, cpu);\n+\n+        if (i == 0) {\n+            cpu_0 = cpu;\n+            if (ms->kernel_filename) {\n+                uint64_t entry = load_kernel(vms);\n+                qdev_prop_set_uint32(DEVICE(cpu_0), \"exec-start-addr\", entry);\n+            } else if (ms->firmware) {\n+                uint64_t entry = load_bios(vms);\n+                qdev_prop_set_uint32(DEVICE(cpu_0), \"exec-start-addr\", entry);\n+            }\n+        }\n+        qdev_prop_set_uint32(DEVICE(cpu), \"htid\", i);\n+        qdev_prop_set_bit(DEVICE(cpu), \"start-powered-off\", (i != 0));\n+        object_property_set_link(OBJECT(cpu), \"global-regs\",\n+                                 OBJECT(gsregs_dev), &error_fatal);\n+        object_property_set_link(OBJECT(cpu), \"tlb\",\n+                                 OBJECT(tlb_dev), &error_fatal);\n+\n+        if (!qdev_realize_and_unref(DEVICE(cpu), NULL, &error_fatal)) {\n+            return;\n+        }\n+    }\n+    /* TODO: enable l2vic when l2vic device arrives */\n+    if (object_class_by_name(\"l2vic\")) {\n+        vms->l2vic = sysbus_create_varargs(\n+            \"l2vic\", m_cfg->l2vic_base,\n+            qdev_get_gpio_in(DEVICE(cpu_0), 0),\n+            qdev_get_gpio_in(DEVICE(cpu_0), 1),\n+            qdev_get_gpio_in(DEVICE(cpu_0), 2),\n+            qdev_get_gpio_in(DEVICE(cpu_0), 3),\n+            qdev_get_gpio_in(DEVICE(cpu_0), 4),\n+            qdev_get_gpio_in(DEVICE(cpu_0), 5),\n+            qdev_get_gpio_in(DEVICE(cpu_0), 6),\n+            qdev_get_gpio_in(DEVICE(cpu_0), 7), NULL);\n+\n+        fdt_add_hvm_pic_node(vms, m_cfg);\n+        fdt_add_virtio_devices(vms);\n+        fdt_add_gpt_node(vms);\n+    }\n+\n+    fdt_add_cpu_nodes(vms);\n+    fdt_add_clocks(vms);\n+    fdt_add_uart(vms, VIRT_UART0);\n+\n+    rom_add_blob_fixed_as(\"config_table.rom\", &m_cfg->cfgtable,\n+                          sizeof(m_cfg->cfgtable), m_cfg->cfgbase,\n+                          &address_space_memory);\n+\n+\n+    hexagon_load_fdt(vms);\n+}\n+\n+\n+static void virt_class_init(ObjectClass *oc, const void *data)\n+{\n+    MachineClass *mc = MACHINE_CLASS(oc);\n+\n+    mc->desc = \"Hexagon Virtual Machine\";\n+    mc->init = virt_init;\n+    mc->default_cpu_type = HEXAGON_CPU_TYPE_NAME(\"v73\");\n+    mc->default_ram_size = 4 * GiB;\n+    mc->max_cpus = 8;\n+    mc->default_cpus = 8;\n+    mc->is_default = false;\n+    mc->default_kernel_irqchip_split = false;\n+    mc->block_default_type = IF_VIRTIO;\n+    mc->default_boot_order = NULL;\n+    mc->no_cdrom = 1;\n+    mc->numa_mem_supported = false;\n+    mc->default_nic = \"virtio-mmio-bus\";\n+}\n+\n+\n+static const TypeInfo virt_machine_types[] = { {\n+    .name = TYPE_HEXAGON_VIRT_MACHINE,\n+    .parent = TYPE_MACHINE,\n+    .instance_size = sizeof(HexagonVirtMachineState),\n+    .class_init = virt_class_init,\n+    .instance_init = virt_instance_init,\n+} };\n+\n+DEFINE_TYPES(virt_machine_types)\ndiff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c\nindex 355abb4fd24..01781a76caf 100644\n--- a/target/hexagon/cpu.c\n+++ b/target/hexagon/cpu.c\n@@ -68,6 +68,8 @@ static ObjectClass *hexagon_cpu_class_by_name(const char *cpu_model)\n \n static const Property hexagon_cpu_properties[] = {\n #if !defined(CONFIG_USER_ONLY)\n+    DEFINE_PROP_LINK(\"tlb\", HexagonCPU, tlb, TYPE_HEXAGON_TLB,\n+                     HexagonTLBState *),\n     DEFINE_PROP_UINT32(\"exec-start-addr\", HexagonCPU, boot_addr, 0xffffffff),\n     DEFINE_PROP_LINK(\"global-regs\", HexagonCPU, globalregs,\n         TYPE_HEXAGON_GLOBALREG, HexagonGlobalRegState *),\ndiff --git a/hw/hexagon/Kconfig b/hw/hexagon/Kconfig\nindex 7b9577f68f7..dc74751d21e 100644\n--- a/hw/hexagon/Kconfig\n+++ b/hw/hexagon/Kconfig\n@@ -3,3 +3,13 @@ config HEX_DSP\n     default y\n     depends on HEXAGON && TCG\n     imply PTIMER\n+\n+config HEX_VIRT\n+    bool\n+    default y\n+    depends on HEX_DSP && FDT\n+    select DEVICE_TREE\n+    select VIRTIO_MMIO\n+    select PL011\n+    select VIRTIO_BLK\n+    select VIRTIO_SCSI\ndiff --git a/hw/hexagon/meson.build b/hw/hexagon/meson.build\nindex f528d2bc4ab..5b6a5e11a17 100644\n--- a/hw/hexagon/meson.build\n+++ b/hw/hexagon/meson.build\n@@ -4,3 +4,5 @@ hexagon_ss.add(files('hexagon_globalreg.c'))\n hexagon_ss.add(when: 'CONFIG_HEX_DSP', if_true: files('hexagon_dsp.c'))\n \n hw_arch += {'hexagon': hexagon_ss}\n+\n+hexagon_ss.add(when: 'CONFIG_HEX_VIRT', if_true: files('virt.c'))\ndiff --git a/tests/qemu-iotests/testenv.py b/tests/qemu-iotests/testenv.py\nindex c357e6ebf50..86bcdf7cfad 100644\n--- a/tests/qemu-iotests/testenv.py\n+++ b/tests/qemu-iotests/testenv.py\n@@ -259,6 +259,7 @@ def __init__(self, source_dir: str, build_dir: str,\n             ('arm', 'virt'),\n             ('aarch64', 'virt'),\n             ('avr', 'mega2560'),\n+            ('hexagon', 'virt'),\n             ('m68k', 'virt'),\n             ('or1k', 'virt'),\n             ('riscv32', 'virt'),\n","prefixes":["v4","8/9"]}