get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.1/patches/2228144/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2228144,
    "url": "http://patchwork.ozlabs.org/api/1.1/patches/2228144/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260425131721.932250-10-joel@jms.id.au/",
    "project": {
        "id": 14,
        "url": "http://patchwork.ozlabs.org/api/1.1/projects/14/?format=api",
        "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": "<20260425131721.932250-10-joel@jms.id.au>",
    "date": "2026-04-25T13:17:15",
    "name": "[v4,09/13] hw/riscv: Add Tenstorrent Atlantis machine",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "de54ee227f11d366d3e0deb191a3ef1329f1155b",
    "submitter": {
        "id": 48628,
        "url": "http://patchwork.ozlabs.org/api/1.1/people/48628/?format=api",
        "name": "Joel Stanley",
        "email": "joel@jms.id.au"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260425131721.932250-10-joel@jms.id.au/mbox/",
    "series": [
        {
            "id": 501439,
            "url": "http://patchwork.ozlabs.org/api/1.1/series/501439/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=501439",
            "date": "2026-04-25T13:17:08",
            "name": "hw/riscv: Add the Tenstorrent Atlantis machine",
            "version": 4,
            "mbox": "http://patchwork.ozlabs.org/series/501439/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2228144/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2228144/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=fail reason=\"signature verification failed\" (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=k57YKe5H;\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=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"
        ],
        "Received": [
            "from lists1p.gnu.org (lists1p.gnu.org [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 4g2r5b1XKrz1xvV\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 25 Apr 2026 23:19:31 +1000 (AEST)",
            "from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wGcuR-0007R4-7M; Sat, 25 Apr 2026 09:18:59 -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 <joel.stan@gmail.com>)\n id 1wGcuM-0007Hi-WE\n for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:56 -0400",
            "from mail-pf1-x42b.google.com ([2607:f8b0:4864:20::42b])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)\n (Exim 4.90_1) (envelope-from <joel.stan@gmail.com>)\n id 1wGcuI-0000Gz-RE\n for qemu-devel@nongnu.org; Sat, 25 Apr 2026 09:18:54 -0400",
            "by mail-pf1-x42b.google.com with SMTP id\n d2e1a72fcca58-82f1bfc9b8fso3999423b3a.1\n for <qemu-devel@nongnu.org>; Sat, 25 Apr 2026 06:18:50 -0700 (PDT)",
            "from donnager-debian.. ([45.124.203.19])\n by smtp.gmail.com with ESMTPSA id\n d2e1a72fcca58-82f8e9f7735sm26898866b3a.21.2026.04.25.06.18.40\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Sat, 25 Apr 2026 06:18:48 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1777123129; x=1777727929; darn=nongnu.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:sender:from:to:cc:subject:date\n :message-id:reply-to;\n bh=C5hVR0szfLa1Sd9HchfmovkD60pPov32aK2HjckAgro=;\n b=k57YKe5HwPiJp8pgXowrW0lbE2MSpif9AG6iEC3/+yH/MY2o+tApdMOhEEUG9vtEvT\n eMbXEwTMcjLFunT/X7DQoa+30OsHo/dU/4Tir1EY9X2fBfEKqQ17qDRhM38vsOBsd6nI\n xV99IuKJBy7KRM+zqzBGZs+ZcLfjefJsRYXLEIuiDrVQhM96BoLF+zN2vrEw7OC7ruAu\n CcQGJVMF3Y/gJIrYFYC6lhbTF2hd884jLJSsRv0Blf8KLvsE+SdxdIuwVBgSf1qEoA78\n PthJ2dW+87zdRO05zAiGUlfAP+XovMpfZsMUUu1qVFhvFsyR/KvxeJ9Gx+hFNCXEEQ0I\n 92iQ==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777123129; x=1777727929;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:sender:x-gm-gg\n :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to;\n bh=C5hVR0szfLa1Sd9HchfmovkD60pPov32aK2HjckAgro=;\n b=enyiAyzDaElUpIRhLShVuG66TTLgCRL92HyQnGXWXmZBSasgJUcas+hihiHuxp3BC2\n iRyb78N5cHPL7YiH2zynCVtKEo5wRZDYPbStH0+VmFPrCgJUVg3eIoE8v4pyuhf5V5vD\n F2qV/B0IYxejWW24q4nAyUArGgBlJlCUBJ/bIheimeRyk3yLxUBf1NFesVQmDqAd05cn\n 44+ZCy7tF105NTlJcWu3OwOqhqJ08Zjfc3nZkegYrMr+ZEnfmfHgKEDBUNbdnxaF7FrX\n bSOQEpPkATc4DwsC42kdbpZvFiTpyfQRckMDJaOkZRqR+U+bl1/o/OWc0inBDKP4j237\n 3AKA==",
        "X-Forwarded-Encrypted": "i=1;\n AFNElJ9/9oQFOOQTLPwh9NvGLnSOVUI6DU090Xx/WxhfHoH95CFVw0GlAMmdyxcTb09cU4+YbnVXTMDkrIKg@nongnu.org",
        "X-Gm-Message-State": "AOJu0YwmY1g9K5z1K9jj7J0fRqWHdnudXMzBYoQkPXxmXkNMDwKQZe9v\n 4J1e27NAwHKALJA3tzkObcnYQGh3H7eC0DmFZLkzHFMIx7FyJqtBL0hn",
        "X-Gm-Gg": "AeBDiesb5WYmvkqXh1NvJC916wV2Y4uk6dttS/xZ2LuazOl9rRVQND1/sQrKjmymjje\n 9znTcE/1RDjwFhSbDdZG9N4QMzgusqe0VffSdFtY0h5MoPnmP9qC2P+XSSmz7GfaNxh78Qht84A\n Q0SVpH7s6xzgG/w7026MpGfdhT/8dXjwY31ho/K5/ktE54+Xgv84glVZhZ9Ots88cItp5e8iwhC\n uLKdktbRaR82pnxWjtqm/Q+3/8x1v2jaIXSBNNZ+gCPtvum/lBdVkrfwqwMSL2HmcEM45ZgIz5d\n +Z53glwsOndcsumCliDAg9sGVwFwdMofYA3X8W4GCMlYbc4paKj9iaABlj7UoQyVdeVIKTPF0xm\n m0L3xs04M0PmYhY4NUb77d6wEQELvxxbnLl03DTo00qYZCxXjNErpD4Lu+Ab0TWzgubl3yiXowS\n EAMNqIPsi8GOP91turRh0TMWiNE8lTdHjr9DVQ6gUrWndiQ/WvdQLDGOP4Acqav936IGFxE8fNi\n BmCzhHczQfRtUdxPto5veNsRBJFWRWi",
        "X-Received": "by 2002:a05:6a00:14c2:b0:82f:8332:4933 with SMTP id\n d2e1a72fcca58-82f8c7dd158mr35501433b3a.3.1777123129353;\n Sat, 25 Apr 2026 06:18:49 -0700 (PDT)",
        "From": "Joel Stanley <joel@jms.id.au>",
        "To": "Alistair Francis <alistair.francis@wdc.com>,\n Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>",
        "Cc": "Chao Liu <chao.liu.zevorn@gmail.com>, Michael Ellerman <mpe@kernel.org>,\n Nicholas Piggin <npiggin@gmail.com>, Joel Stanley <jms@oss.tenstorrent.com>,\n Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com>,\n Portia Stephens <portias@oss.tenstorrent.com>, qemu-riscv@nongnu.org,\n qemu-devel@nongnu.org,\n =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= <philmd@linaro.org>",
        "Subject": "[PATCH v4 09/13] hw/riscv: Add Tenstorrent Atlantis machine",
        "Date": "Sat, 25 Apr 2026 23:17:15 +1000",
        "Message-ID": "<20260425131721.932250-10-joel@jms.id.au>",
        "X-Mailer": "git-send-email 2.47.3",
        "In-Reply-To": "<20260425131721.932250-1-joel@jms.id.au>",
        "References": "<20260425131721.932250-1-joel@jms.id.au>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=UTF-8",
        "Content-Transfer-Encoding": "8bit",
        "Received-SPF": "pass client-ip=2607:f8b0:4864:20::42b;\n envelope-from=joel.stan@gmail.com; helo=mail-pf1-x42b.google.com",
        "X-Spam_score_int": "-16",
        "X-Spam_score": "-1.7",
        "X-Spam_bar": "-",
        "X-Spam_report": "(-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FORGED_FROMDOMAIN=0.001,\n FREEMAIL_FROM=0.001, HEADER_FROM_DIFFERENT_DOMAINS=0.25,\n RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001,\n SPF_PASS=-0.001 autolearn=no 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": "The Tenstorrent Atlantis platform is a collaboration between Tenstorrent\nand CoreLab Technology. It is based on the Atlantis SoC, which includes\nthe Ascalon-X CPU and other IP from Tenstorrent and CoreLab Technology.\n\nThe Tenstorrent Ascalon-X is a high performance 64-bit RVA23 compliant\nRISC-V CPU.\n\nThis adds the machine containing serial console, interrupt controllers\nand device tree support.\n\n  qemu-system-riscv64 -M tt-atlantis -m 512M \\\n   -kernel Image -initrd rootfs.cpio -nographic\n\nIf there is no kernel provided the simple payload is loaded to avoid\nOpenSBI hanging with no messages.\n\nCo-Developed-by: Nicholas Piggin <npiggin@gmail.com>\nReviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>\nReviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>\nSigned-off-by: Joel Stanley <joel@jms.id.au>\n---\nv4:\n - Clean up unused PCIe defines\nv3:\n  - Merge simple payload change into this patch\n  - Fix fw_cfg_init_mem_dma API change\n  - Clean up irqchip #defines\n  - Add Michael and Nick as reviewers\n  - create_fdt_pmu was copying RISCVCPU by value\n  - Remove unused platform_bus\n\nremove unused defines\n\nSigned-off-by: Joel Stanley <joel@jms.id.au>\n---\n MAINTAINERS                       |  11 +\n docs/system/riscv/tt_atlantis.rst |  38 ++\n docs/system/target-riscv.rst      |   1 +\n include/hw/riscv/tt_atlantis.h    |  61 +++\n hw/riscv/tt_atlantis.c            | 632 ++++++++++++++++++++++++++++++\n hw/riscv/Kconfig                  |  15 +\n hw/riscv/meson.build              |   1 +\n 7 files changed, 759 insertions(+)\n create mode 100644 docs/system/riscv/tt_atlantis.rst\n create mode 100644 include/hw/riscv/tt_atlantis.h\n create mode 100644 hw/riscv/tt_atlantis.c",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex e1942a86eba5..635a380945fd 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -1760,6 +1760,17 @@ F: hw/*/*sifive*.c\n F: include/hw/*/*sifive*.h\n F: tests/functional/test_riscv64_sifive_u.py\n \n+Tenstorrent Machines\n+M: Joel Stanley <joel@jms.id.au>\n+R: Nicholas Piggin <npiggin@gmail.com>\n+R: Michael Ellerman <mpe@kernel.org>\n+L: qemu-riscv@nongnu.org\n+S: Supported\n+F: docs/system/riscv/tt_*.rst\n+F: hw/riscv/tt_*.c\n+F: hw/riscv/aia.[ch]\n+F: include/hw/riscv/tt_*.h\n+\n AMD Microblaze-V Generic Board\n M: Sai Pavan Boddu <sai.pavan.boddu@amd.com>\n S: Maintained\ndiff --git a/docs/system/riscv/tt_atlantis.rst b/docs/system/riscv/tt_atlantis.rst\nnew file mode 100644\nindex 000000000000..640cabf7b046\n--- /dev/null\n+++ b/docs/system/riscv/tt_atlantis.rst\n@@ -0,0 +1,38 @@\n+Tenstorrent Atlantis (``tt-atlantis``)\n+======================================\n+\n+The Tenstorrent Atlantis platform is a collaboration between Tenstorrent\n+and CoreLab Technology. It is based on the Atlantis SoC, which includes\n+the Ascalon-X CPU and other IP from Tenstorrent and CoreLab Technology.\n+\n+The Tenstorrent Ascalon-X is a high performance 64-bit RVA23 compliant\n+RISC-V CPU.\n+\n+Features\n+--------\n+\n+* 8-core Ascalon-X CPU Cluster\n+* Dual x32 LPDDR5 @ 6400 MT/s\n+* RISC-V compliant Advanced Interrupt Architecture\n+* PCIe Gen4\n+* RISC-V compliant IOMMU\n+* GPU and Video subsystem\n+* 2x USB3.1 & 2x USB2.0\n+* 2x 1GbE Ethernet\n+* 2x eMMC5.1/SDIO3.0 storage\n+* Extensive connectivity (SPI, I2C, UART, GPIO, CANFD)\n+\n+Note: the QEMU tt-atlantis machine does not model the platform\n+exactly or all devices, but it is undergoing improvement.\n+\n+Supported software\n+------------------\n+\n+The Tenstorrent Ascalon CPUs avoid proprietary or non-standard\n+extensions, so compatibility with existing software is generally\n+good. The QEMU tt-atlantis machine works with upstream OpenSBI\n+and Linux with default configurations.\n+\n+The development board hardware will require some implementation\n+specific setup in firmware which is being developed and may\n+become a requirement or option for the tt-atlantis machine.\ndiff --git a/docs/system/target-riscv.rst b/docs/system/target-riscv.rst\nindex 3ad5d1ddafbb..a8e6b3342186 100644\n--- a/docs/system/target-riscv.rst\n+++ b/docs/system/target-riscv.rst\n@@ -71,6 +71,7 @@ undocumented; you can get a complete list by running\n    riscv/mips\n    riscv/shakti-c\n    riscv/sifive_u\n+   riscv/tt_atlantis\n    riscv/virt\n    riscv/xiangshan-kunminghu\n \ndiff --git a/include/hw/riscv/tt_atlantis.h b/include/hw/riscv/tt_atlantis.h\nnew file mode 100644\nindex 000000000000..9fe50d9c9040\n--- /dev/null\n+++ b/include/hw/riscv/tt_atlantis.h\n@@ -0,0 +1,61 @@\n+/*\n+ * Tenstorrent Atlantis RISC-V System on Chip\n+ *\n+ * SPDX-License-Identifier: GPL-2.0-or-later\n+ *\n+ * Copyright 2025 Tenstorrent, Joel Stanley <joel@jms.id.au>\n+ */\n+\n+#ifndef HW_RISCV_TT_ATLANTIS_H\n+#define HW_RISCV_TT_ATLANTIS_H\n+\n+#include \"hw/core/boards.h\"\n+#include \"hw/core/sysbus.h\"\n+#include \"hw/intc/riscv_imsic.h\"\n+#include \"hw/riscv/riscv_hart.h\"\n+\n+#define TYPE_TT_ATLANTIS_MACHINE MACHINE_TYPE_NAME(\"tt-atlantis\")\n+OBJECT_DECLARE_SIMPLE_TYPE(TTAtlantisState, TT_ATLANTIS_MACHINE)\n+\n+struct TTAtlantisState {\n+    /*< private >*/\n+    MachineState parent;\n+\n+    /*< public >*/\n+    Notifier machine_done;\n+    FWCfgState *fw_cfg;\n+    const MemMapEntry *memmap;\n+\n+    RISCVHartArrayState soc;\n+    DeviceState *irqchip;\n+\n+    int fdt_size;\n+};\n+\n+enum {\n+    TT_ATL_SYSCON_IRQ = 10,\n+    TT_ATL_UART0_IRQ = 38,\n+    TT_ATL_UART1_IRQ = 39,\n+    TT_ATL_UART2_IRQ = 40,\n+    TT_ATL_UART3_IRQ = 41,\n+    TT_ATL_UART4_IRQ = 42,\n+};\n+\n+enum {\n+    TT_ATL_ACLINT,\n+    TT_ATL_BOOTROM,\n+    TT_ATL_DDR_LO,\n+    TT_ATL_DDR_HI,\n+    TT_ATL_FW_CFG,\n+    TT_ATL_I2C0,\n+    TT_ATL_MAPLIC,\n+    TT_ATL_MIMSIC,\n+    TT_ATL_SAPLIC,\n+    TT_ATL_SIMSIC,\n+    TT_ATL_SYSCON,\n+    TT_ATL_TIMER,\n+    TT_ATL_UART0,\n+    TT_ATL_WDT0,\n+};\n+\n+#endif\ndiff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c\nnew file mode 100644\nindex 000000000000..5b66d7e95bb9\n--- /dev/null\n+++ b/hw/riscv/tt_atlantis.c\n@@ -0,0 +1,632 @@\n+/*\n+ * Tenstorrent Atlantis RISC-V System on Chip\n+ *\n+ * SPDX-License-Identifier: GPL-2.0-or-later\n+ *\n+ * Copyright 2025 Tenstorrent, Joel Stanley <joel@jms.id.au>\n+ */\n+\n+#include \"qemu/osdep.h\"\n+#include \"qemu/cutils.h\"\n+#include \"qemu/error-report.h\"\n+#include \"qemu/guest-random.h\"\n+#include \"qemu/units.h\"\n+\n+#include \"hw/core/boards.h\"\n+#include \"hw/core/loader.h\"\n+#include \"hw/core/sysbus.h\"\n+\n+#include \"target/riscv/cpu.h\"\n+#include \"target/riscv/pmu.h\"\n+\n+#include \"hw/riscv/boot.h\"\n+#include \"hw/riscv/numa.h\"\n+#include \"hw/riscv/riscv_hart.h\"\n+\n+#include \"hw/char/serial-mm.h\"\n+#include \"hw/intc/riscv_aclint.h\"\n+#include \"hw/intc/riscv_aplic.h\"\n+#include \"hw/misc/pvpanic.h\"\n+\n+#include \"system/system.h\"\n+#include \"system/device_tree.h\"\n+\n+#include \"hw/riscv/tt_atlantis.h\"\n+\n+#include \"aia.h\"\n+\n+#define TT_IRQCHIP_NUM_MSIS       255\n+#define TT_IRQCHIP_NUM_SOURCES    128\n+#define TT_IRQCHIP_NUM_PRIO_BITS  3\n+#define TT_IRQCHIP_GUESTS         7 /* aia_guests */\n+\n+#define FDT_PCI_ADDR_CELLS    3\n+#define FDT_PCI_INT_CELLS     1\n+#define FDT_MAX_INT_CELLS     2\n+#define FDT_MAX_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + \\\n+                                 1 + FDT_MAX_INT_CELLS)\n+\n+#define TT_ACLINT_MTIME_SIZE    0x8050\n+#define TT_ACLINT_MTIME         0x0\n+#define TT_ACLINT_MTIMECMP      0x8000\n+#define TT_ACLINT_TIMEBASE_FREQ 1000000000\n+\n+static const MemMapEntry tt_atlantis_memmap[] = {\n+    /* Keep sorted with :'<,'>!sort -g -k 4 */\n+    [TT_ATL_DDR_LO] =           { 0x00000000,    0x80000000 },\n+    [TT_ATL_BOOTROM] =          { 0x80000000,        0x2000 },\n+    [TT_ATL_FW_CFG] =           { 0x80002000,          0xff }, /* qemu only */\n+    [TT_ATL_SYSCON] =           { 0x80004000,        0x1000 }, /* qemu only */\n+    [TT_ATL_MIMSIC] =           { 0xa0000000,      0x200000 },\n+    [TT_ATL_ACLINT] =           { 0xa2180000,       0x10000 },\n+    [TT_ATL_SIMSIC] =           { 0xa4000000,      0x200000 },\n+    [TT_ATL_TIMER] =            { 0xa8020000,       0x10000 },\n+    [TT_ATL_WDT0] =             { 0xa8030000,       0x10000 },\n+    [TT_ATL_UART0] =            { 0xb0100000,       0x10000 },\n+    [TT_ATL_MAPLIC] =           { 0xcc000000,     0x4000000 },\n+    [TT_ATL_SAPLIC] =           { 0xe8000000,     0x4000000 },\n+    [TT_ATL_DDR_HI] =          { 0x100000000,  0x1000000000 },\n+};\n+\n+static uint32_t next_phandle(void)\n+{\n+    static uint32_t phandle = 1;\n+    return phandle++;\n+}\n+\n+static void create_fdt_cpus(TTAtlantisState *s, uint32_t *intc_phandles)\n+{\n+    uint32_t cpu_phandle;\n+    void *fdt = MACHINE(s)->fdt;\n+\n+    for (int cpu = s->soc.num_harts - 1; cpu >= 0; cpu--) {\n+        RISCVCPU *cpu_ptr = &s->soc.harts[cpu];\n+        g_autofree char *cpu_name = NULL;\n+        g_autofree char *intc_name = NULL;\n+\n+        cpu_phandle = next_phandle();\n+\n+        cpu_name = g_strdup_printf(\"/cpus/cpu@%d\", s->soc.hartid_base + cpu);\n+        qemu_fdt_add_subnode(fdt, cpu_name);\n+\n+        qemu_fdt_setprop_string(fdt, cpu_name, \"mmu-type\", \"riscv,sv57\");\n+\n+        riscv_isa_write_fdt(cpu_ptr, fdt, cpu_name);\n+\n+        qemu_fdt_setprop_cell(fdt, cpu_name, \"riscv,cbom-block-size\",\n+                cpu_ptr->cfg.cbom_blocksize);\n+\n+        qemu_fdt_setprop_cell(fdt, cpu_name, \"riscv,cboz-block-size\",\n+                cpu_ptr->cfg.cboz_blocksize);\n+\n+        qemu_fdt_setprop_cell(fdt, cpu_name, \"riscv,cbop-block-size\",\n+                cpu_ptr->cfg.cbop_blocksize);\n+\n+        qemu_fdt_setprop_string(fdt, cpu_name, \"compatible\", \"riscv\");\n+        qemu_fdt_setprop_string(fdt, cpu_name, \"status\", \"okay\");\n+        qemu_fdt_setprop_cell(fdt, cpu_name, \"reg\", s->soc.hartid_base + cpu);\n+        qemu_fdt_setprop_string(fdt, cpu_name, \"device_type\", \"cpu\");\n+        qemu_fdt_setprop_cell(fdt, cpu_name, \"phandle\", cpu_phandle);\n+\n+        intc_phandles[cpu] = next_phandle();\n+\n+        intc_name = g_strdup_printf(\"%s/interrupt-controller\", cpu_name);\n+        qemu_fdt_add_subnode(fdt, intc_name);\n+        qemu_fdt_setprop_cell(fdt, intc_name, \"phandle\",\n+                              intc_phandles[cpu]);\n+        qemu_fdt_setprop_string(fdt, intc_name, \"compatible\",\n+                                \"riscv,cpu-intc\");\n+        qemu_fdt_setprop(fdt, intc_name, \"interrupt-controller\", NULL, 0);\n+        qemu_fdt_setprop_cell(fdt, intc_name, \"#interrupt-cells\", 1);\n+    }\n+}\n+\n+static void create_fdt_memory_node(TTAtlantisState *s,\n+                                   hwaddr addr, hwaddr size)\n+{\n+    void *fdt = MACHINE(s)->fdt;\n+    g_autofree char *name = g_strdup_printf(\"/memory@%\"HWADDR_PRIX, addr);\n+    qemu_fdt_add_subnode(fdt, name);\n+    qemu_fdt_setprop_sized_cells(fdt, name, \"reg\", 2, addr, 2, size);\n+    qemu_fdt_setprop_string(fdt, name, \"device_type\", \"memory\");\n+}\n+\n+static void create_fdt_memory(TTAtlantisState *s)\n+{\n+    hwaddr size_lo = MACHINE(s)->ram_size;\n+    hwaddr size_hi = 0;\n+\n+    if (size_lo > s->memmap[TT_ATL_DDR_LO].size) {\n+        size_lo = s->memmap[TT_ATL_DDR_LO].size;\n+        size_hi = MACHINE(s)->ram_size - size_lo;\n+    }\n+\n+    create_fdt_memory_node(s, s->memmap[TT_ATL_DDR_LO].base, size_lo);\n+    if (size_hi) {\n+        /*\n+         * The first part of the HI address is aliased at the LO address\n+         * so do not include that as usable memory. Is there any way\n+         * (or good reason) to describe that aliasing 2GB with DT?\n+         */\n+        create_fdt_memory_node(s, s->memmap[TT_ATL_DDR_HI].base + size_lo,\n+                               size_hi);\n+    }\n+}\n+\n+static void create_fdt_aclint(TTAtlantisState *s, uint32_t *intc_phandles)\n+{\n+    void *fdt = MACHINE(s)->fdt;\n+    g_autofree char *name = NULL;\n+    g_autofree uint32_t *aclint_mtimer_cells = NULL;\n+    uint32_t aclint_cells_size;\n+    hwaddr addr;\n+\n+    aclint_mtimer_cells = g_new0(uint32_t, s->soc.num_harts * 2);\n+\n+    for (int cpu = 0; cpu < s->soc.num_harts; cpu++) {\n+        aclint_mtimer_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);\n+        aclint_mtimer_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_M_TIMER);\n+    }\n+    aclint_cells_size = s->soc.num_harts * sizeof(uint32_t) * 2;\n+\n+    addr = s->memmap[TT_ATL_ACLINT].base;\n+\n+    name = g_strdup_printf(\"/soc/mtimer@%\"HWADDR_PRIX, addr);\n+    qemu_fdt_add_subnode(fdt, name);\n+    qemu_fdt_setprop_string(fdt, name, \"compatible\", \"riscv,aclint-mtimer\");\n+    qemu_fdt_setprop_sized_cells(fdt, name, \"reg\",\n+                                 2, addr + TT_ACLINT_MTIME,\n+                                 2, 0x1000,\n+                                 2, addr + TT_ACLINT_MTIMECMP,\n+                                 2, 0x1000);\n+    qemu_fdt_setprop(fdt, name, \"interrupts-extended\",\n+                     aclint_mtimer_cells, aclint_cells_size);\n+}\n+\n+static void create_fdt_one_imsic(void *fdt, const MemMapEntry *mem, int cpus,\n+                                 uint32_t *intc_phandles, uint32_t msi_phandle,\n+                                 int irq_line, uint32_t imsic_guest_bits)\n+{\n+    g_autofree char *name = NULL;\n+    g_autofree uint32_t *imsic_cells = g_new0(uint32_t, cpus * 2);\n+\n+    for (int cpu = 0; cpu < cpus; cpu++) {\n+        imsic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);\n+        imsic_cells[cpu * 2 + 1] = cpu_to_be32(irq_line);\n+    }\n+\n+    name = g_strdup_printf(\"/soc/interrupt-controller@%\"HWADDR_PRIX, mem->base);\n+    qemu_fdt_add_subnode(fdt, name);\n+    qemu_fdt_setprop_string(fdt, name, \"compatible\", \"riscv,imsics\");\n+\n+    qemu_fdt_setprop_cell(fdt, name, \"#interrupt-cells\", 0);\n+    qemu_fdt_setprop(fdt, name, \"interrupt-controller\", NULL, 0);\n+    qemu_fdt_setprop(fdt, name, \"msi-controller\", NULL, 0);\n+    qemu_fdt_setprop(fdt, name, \"interrupts-extended\",\n+                     imsic_cells, sizeof(uint32_t) * cpus * 2);\n+    qemu_fdt_setprop_sized_cells(fdt, name, \"reg\", 2, mem->base, 2, mem->size);\n+    qemu_fdt_setprop_cell(fdt, name, \"riscv,num-ids\", TT_IRQCHIP_NUM_MSIS);\n+\n+    if (imsic_guest_bits) {\n+        qemu_fdt_setprop_cell(fdt, name, \"riscv,guest-index-bits\",\n+                              imsic_guest_bits);\n+    }\n+    qemu_fdt_setprop_cell(fdt, name, \"phandle\", msi_phandle);\n+}\n+\n+static void create_fdt_one_aplic(void *fdt,\n+                                 const MemMapEntry *mem,\n+                                 uint32_t msi_phandle,\n+                                 uint32_t *intc_phandles,\n+                                 uint32_t aplic_phandle,\n+                                 uint32_t aplic_child_phandle,\n+                                 int irq_line, int num_harts)\n+{\n+    g_autofree char *name =\n+        g_strdup_printf(\"/soc/interrupt-controller@%\"HWADDR_PRIX, mem->base);\n+    g_autofree uint32_t *aplic_cells = g_new0(uint32_t, num_harts * 2);\n+\n+    for (int cpu = 0; cpu < num_harts; cpu++) {\n+        aplic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);\n+        aplic_cells[cpu * 2 + 1] = cpu_to_be32(irq_line);\n+    }\n+\n+    qemu_fdt_add_subnode(fdt, name);\n+    qemu_fdt_setprop_string(fdt, name, \"compatible\", \"riscv,aplic\");\n+    qemu_fdt_setprop_cell(fdt, name, \"#address-cells\", 0);\n+    qemu_fdt_setprop_cell(fdt, name, \"#interrupt-cells\", 2);\n+    qemu_fdt_setprop(fdt, name, \"interrupt-controller\", NULL, 0);\n+\n+    qemu_fdt_setprop(fdt, name, \"interrupts-extended\",\n+                     aplic_cells, num_harts * sizeof(uint32_t) * 2);\n+    qemu_fdt_setprop_cell(fdt, name, \"msi-parent\", msi_phandle);\n+\n+    qemu_fdt_setprop_sized_cells(fdt, name, \"reg\", 2, mem->base, 2, mem->size);\n+    qemu_fdt_setprop_cell(fdt, name, \"riscv,num-sources\",\n+                          TT_IRQCHIP_NUM_SOURCES);\n+\n+    if (aplic_child_phandle) {\n+        qemu_fdt_setprop_cell(fdt, name, \"riscv,children\",\n+                              aplic_child_phandle);\n+        qemu_fdt_setprop_cells(fdt, name, \"riscv,delegation\",\n+                               aplic_child_phandle, 1, TT_IRQCHIP_NUM_SOURCES);\n+    }\n+\n+    qemu_fdt_setprop_cell(fdt, name, \"phandle\", aplic_phandle);\n+}\n+\n+static void create_fdt_pmu(TTAtlantisState *s)\n+{\n+    g_autofree char *pmu_name = g_strdup_printf(\"/pmu\");\n+    void *fdt = MACHINE(s)->fdt;\n+    RISCVCPU *hart = &s->soc.harts[0];\n+\n+    qemu_fdt_add_subnode(fdt, pmu_name);\n+    qemu_fdt_setprop_string(fdt, pmu_name, \"compatible\", \"riscv,pmu\");\n+    riscv_pmu_generate_fdt_node(fdt, hart->pmu_avail_ctrs, pmu_name);\n+}\n+\n+static void create_fdt_cpu(TTAtlantisState *s, const MemMapEntry *memmap,\n+                           uint32_t aplic_s_phandle,\n+                           uint32_t imsic_s_phandle)\n+{\n+    MachineState *ms = MACHINE(s);\n+    void *fdt = MACHINE(s)->fdt;\n+    g_autofree uint32_t *intc_phandles = NULL;\n+\n+    qemu_fdt_add_subnode(fdt, \"/cpus\");\n+    qemu_fdt_setprop_cell(fdt, \"/cpus\", \"timebase-frequency\",\n+                          TT_ACLINT_TIMEBASE_FREQ);\n+    qemu_fdt_setprop_cell(fdt, \"/cpus\", \"#size-cells\", 0x0);\n+    qemu_fdt_setprop_cell(fdt, \"/cpus\", \"#address-cells\", 0x1);\n+\n+    intc_phandles = g_new0(uint32_t, ms->smp.cpus);\n+\n+    create_fdt_cpus(s, intc_phandles);\n+\n+    create_fdt_memory(s);\n+\n+    create_fdt_aclint(s, intc_phandles);\n+\n+    /* M-level IMSIC node */\n+    uint32_t msi_m_phandle = next_phandle();\n+    create_fdt_one_imsic(fdt, &s->memmap[TT_ATL_MIMSIC], ms->smp.cpus,\n+                         intc_phandles, msi_m_phandle,\n+                         IRQ_M_EXT, 0);\n+\n+    /* S-level IMSIC node */\n+    create_fdt_one_imsic(fdt, &s->memmap[TT_ATL_SIMSIC], ms->smp.cpus,\n+                         intc_phandles, imsic_s_phandle,\n+                         IRQ_S_EXT, imsic_num_bits(TT_IRQCHIP_GUESTS + 1));\n+\n+    uint32_t aplic_m_phandle = next_phandle();\n+\n+    /* M-level APLIC node */\n+    create_fdt_one_aplic(fdt, &s->memmap[TT_ATL_MAPLIC],\n+                         msi_m_phandle, intc_phandles,\n+                         aplic_m_phandle, aplic_s_phandle,\n+                         IRQ_M_EXT, s->soc.num_harts);\n+\n+    /* S-level APLIC node */\n+    create_fdt_one_aplic(fdt, &s->memmap[TT_ATL_SAPLIC],\n+                         imsic_s_phandle, intc_phandles,\n+                         aplic_s_phandle, 0,\n+                         IRQ_S_EXT, s->soc.num_harts);\n+}\n+\n+static void create_fdt_reset(void *fdt, const MemMapEntry *mem)\n+{\n+    uint32_t syscon_phandle = next_phandle();\n+    char *name;\n+\n+    name = g_strdup_printf(\"/soc/syscon@%\"HWADDR_PRIX, mem->base);\n+    qemu_fdt_add_subnode(fdt, name);\n+    qemu_fdt_setprop_string(fdt, name, \"compatible\", \"syscon\");\n+    qemu_fdt_setprop_sized_cells(fdt, name, \"reg\", 2, mem->base, 2, mem->size);\n+    qemu_fdt_setprop_cell(fdt, name, \"phandle\", syscon_phandle);\n+    g_free(name);\n+\n+    name = g_strdup_printf(\"/poweroff\");\n+    qemu_fdt_add_subnode(fdt, name);\n+    qemu_fdt_setprop_string(fdt, name, \"compatible\", \"syscon-poweroff\");\n+    qemu_fdt_setprop_cell(fdt, name, \"regmap\", syscon_phandle);\n+    qemu_fdt_setprop_cell(fdt, name, \"offset\", 0x0);\n+    qemu_fdt_setprop_cell(fdt, name, \"value\", PVPANIC_SHUTDOWN);\n+    g_free(name);\n+}\n+\n+static void create_fdt_uart(void *fdt, const MemMapEntry *mem, int irq,\n+                            int irqchip_phandle)\n+{\n+    g_autofree char *name = g_strdup_printf(\"/soc/serial@%\"HWADDR_PRIX,\n+                                            mem->base);\n+\n+    qemu_fdt_add_subnode(fdt, name);\n+    qemu_fdt_setprop_string(fdt, name, \"compatible\", \"ns16550a\");\n+    qemu_fdt_setprop_sized_cells(fdt, name, \"reg\", 2, mem->base, 2, mem->size);\n+    qemu_fdt_setprop_cell(fdt, name, \"reg-shift\", 2);\n+    qemu_fdt_setprop_cell(fdt, name, \"reg-io-width\", 4);\n+    qemu_fdt_setprop_cell(fdt, name, \"clock-frequency\", 3686400);\n+    qemu_fdt_setprop_cell(fdt, name, \"interrupt-parent\", irqchip_phandle);\n+    qemu_fdt_setprop_cells(fdt, name, \"interrupts\", irq, 0x4);\n+\n+    qemu_fdt_setprop_string(fdt, \"/chosen\", \"stdout-path\", name);\n+    qemu_fdt_setprop_string(fdt, \"/aliases\", \"serial0\", name);\n+}\n+\n+static void create_fdt_fw_cfg(void *fdt, const MemMapEntry *mem)\n+{\n+    g_autofree char *name = g_strdup_printf(\"/fw-cfg@%\"HWADDR_PRIX, mem->base);\n+\n+    qemu_fdt_add_subnode(fdt, name);\n+    qemu_fdt_setprop_string(fdt, name, \"compatible\", \"qemu,fw-cfg-mmio\");\n+    qemu_fdt_setprop_sized_cells(fdt, name, \"reg\", 2, mem->base, 2, mem->size);\n+    qemu_fdt_setprop(fdt, name, \"dma-coherent\", NULL, 0);\n+}\n+\n+static void finalize_fdt(TTAtlantisState *s)\n+{\n+    uint32_t aplic_s_phandle = next_phandle();\n+    uint32_t imsic_s_phandle = next_phandle();\n+    void *fdt = MACHINE(s)->fdt;\n+\n+    create_fdt_cpu(s, s->memmap, aplic_s_phandle, imsic_s_phandle);\n+\n+    /*\n+     * We want to do this, but the Linux aplic driver was broken before v6.16\n+     *\n+     * qemu_fdt_setprop_cell(MACHINE(s)->fdt, \"/soc\", \"interrupt-parent\",\n+     *                       aplic_s_phandle);\n+     */\n+\n+    create_fdt_reset(fdt, &s->memmap[TT_ATL_SYSCON]);\n+\n+    create_fdt_uart(fdt, &s->memmap[TT_ATL_UART0], TT_ATL_UART0_IRQ,\n+                    aplic_s_phandle);\n+}\n+\n+static void create_fdt(TTAtlantisState *s)\n+{\n+    MachineState *ms = MACHINE(s);\n+    uint8_t rng_seed[32];\n+    g_autofree char *name = NULL;\n+    void *fdt;\n+\n+    fdt = create_device_tree(&s->fdt_size);\n+    if (!fdt) {\n+        error_report(\"create_device_tree() failed\");\n+        exit(1);\n+    }\n+    ms->fdt = fdt;\n+\n+    qemu_fdt_setprop_string(fdt, \"/\", \"model\",\n+                            \"Tenstorrent Atlantis RISC-V Machine\");\n+    qemu_fdt_setprop_string(fdt, \"/\", \"compatible\", \"tenstorrent,atlantis\");\n+    qemu_fdt_setprop_cell(fdt, \"/\", \"#size-cells\", 0x2);\n+    qemu_fdt_setprop_cell(fdt, \"/\", \"#address-cells\", 0x2);\n+\n+    qemu_fdt_add_subnode(fdt, \"/soc\");\n+    qemu_fdt_setprop(fdt, \"/soc\", \"ranges\", NULL, 0);\n+    qemu_fdt_setprop_string(fdt, \"/soc\", \"compatible\", \"simple-bus\");\n+    qemu_fdt_setprop_cell(fdt, \"/soc\", \"#size-cells\", 0x2);\n+    qemu_fdt_setprop_cell(fdt, \"/soc\", \"#address-cells\", 0x2);\n+\n+    qemu_fdt_add_subnode(fdt, \"/chosen\");\n+\n+    /* Pass seed to RNG */\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+    qemu_fdt_add_subnode(fdt, \"/aliases\");\n+\n+    create_fdt_fw_cfg(fdt, &s->memmap[TT_ATL_FW_CFG]);\n+    create_fdt_pmu(s);\n+}\n+\n+static DeviceState *create_reboot_device(const MemMapEntry *mem)\n+{\n+    DeviceState *dev = qdev_new(TYPE_PVPANIC_MMIO_DEVICE);\n+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);\n+\n+    qdev_prop_set_uint32(dev, \"events\", PVPANIC_SHUTDOWN | PVPANIC_PANICKED);\n+\n+    sysbus_realize_and_unref(sbd, &error_fatal);\n+    sysbus_mmio_map(sbd, 0, mem->base);\n+\n+    return dev;\n+}\n+\n+static FWCfgState *create_fw_cfg(const MemMapEntry *mem, int num_cpus)\n+{\n+    FWCfgState *fw_cfg;\n+    hwaddr base = mem->base;\n+\n+    fw_cfg = fw_cfg_init_mem_dma(base + 8, base, 8, base + 16,\n+                                 &address_space_memory);\n+    fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, num_cpus);\n+\n+    return fw_cfg;\n+}\n+\n+static void tt_atlantis_machine_done(Notifier *notifier, void *data)\n+{\n+    TTAtlantisState *s = container_of(notifier, TTAtlantisState, machine_done);\n+    MachineState *machine = MACHINE(s);\n+    hwaddr start_addr = s->memmap[TT_ATL_DDR_LO].base;\n+    hwaddr mem_size;\n+    target_ulong firmware_end_addr, kernel_start_addr;\n+    const char *firmware_name = riscv_default_firmware_name(&s->soc);\n+    uint64_t fdt_load_addr;\n+    uint64_t kernel_entry;\n+    RISCVBootInfo boot_info;\n+\n+    /*\n+     * A user provided dtb must include everything, including\n+     * dynamic sysbus devices. Our FDT needs to be finalized.\n+     */\n+    if (machine->dtb == NULL) {\n+        finalize_fdt(s);\n+    }\n+\n+    mem_size = machine->ram_size;\n+    if (mem_size > s->memmap[TT_ATL_DDR_LO].size) {\n+        mem_size = s->memmap[TT_ATL_DDR_LO].size;\n+    }\n+    riscv_boot_info_init_discontig_mem(&boot_info, &s->soc,\n+                                       s->memmap[TT_ATL_DDR_LO].base,\n+                                       mem_size);\n+\n+    firmware_end_addr = riscv_find_and_load_firmware(machine, &boot_info,\n+                                                     firmware_name,\n+                                                     &start_addr, NULL);\n+\n+    kernel_start_addr = riscv_calc_kernel_start_addr(&boot_info,\n+                                                     firmware_end_addr);\n+    if (machine->kernel_filename) {\n+        riscv_load_kernel(machine, &boot_info, kernel_start_addr,\n+                          true, NULL);\n+    } else {\n+        riscv_setup_halting_payload(&boot_info, kernel_start_addr);\n+    }\n+    kernel_entry = boot_info.image_low_addr;\n+\n+    fdt_load_addr = riscv_compute_fdt_addr(s->memmap[TT_ATL_DDR_LO].base,\n+                                           s->memmap[TT_ATL_DDR_LO].size,\n+                                           machine, &boot_info);\n+    riscv_load_fdt(fdt_load_addr, machine->fdt);\n+\n+    /* load the reset vector */\n+    riscv_setup_rom_reset_vec(machine, &s->soc, start_addr,\n+                              s->memmap[TT_ATL_BOOTROM].base,\n+                              s->memmap[TT_ATL_BOOTROM].size,\n+                              kernel_entry,\n+                              fdt_load_addr);\n+\n+}\n+\n+static void tt_atlantis_machine_init(MachineState *machine)\n+{\n+    TTAtlantisState *s = TT_ATLANTIS_MACHINE(machine);\n+\n+    MemoryRegion *system_memory = get_system_memory();\n+    MemoryRegion *ram_hi = g_new(MemoryRegion, 1);\n+    MemoryRegion *ram_lo = g_new(MemoryRegion, 1);\n+    MemoryRegion *bootrom = g_new(MemoryRegion, 1);\n+    ram_addr_t lo_ram_size, hi_ram_size;\n+    int hart_count = machine->smp.cpus;\n+    int base_hartid = 0;\n+\n+    s->memmap = tt_atlantis_memmap;\n+\n+    object_initialize_child(OBJECT(machine), \"soc\", &s->soc,\n+                            TYPE_RISCV_HART_ARRAY);\n+    object_property_set_str(OBJECT(&s->soc), \"cpu-type\", machine->cpu_type,\n+                            &error_abort);\n+    object_property_set_int(OBJECT(&s->soc), \"hartid-base\", base_hartid,\n+                            &error_abort);\n+    object_property_set_int(OBJECT(&s->soc), \"num-harts\", hart_count,\n+                            &error_abort);\n+    object_property_set_int(OBJECT(&s->soc), \"resetvec\",\n+                            s->memmap[TT_ATL_BOOTROM].base,\n+                            &error_abort);\n+    sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_fatal);\n+\n+    s->irqchip = riscv_create_aia(true, TT_IRQCHIP_GUESTS,\n+                                  TT_IRQCHIP_NUM_SOURCES,\n+                                  &s->memmap[TT_ATL_MAPLIC],\n+                                  &s->memmap[TT_ATL_SAPLIC],\n+                                  &s->memmap[TT_ATL_MIMSIC],\n+                                  &s->memmap[TT_ATL_SIMSIC],\n+                                  0, base_hartid, hart_count,\n+                                  TT_IRQCHIP_NUM_MSIS,\n+                                  TT_IRQCHIP_NUM_PRIO_BITS);\n+\n+    riscv_aclint_mtimer_create(s->memmap[TT_ATL_ACLINT].base,\n+            TT_ACLINT_MTIME_SIZE,\n+            base_hartid, hart_count,\n+            TT_ACLINT_MTIMECMP,\n+            TT_ACLINT_MTIME,\n+            TT_ACLINT_TIMEBASE_FREQ, true);\n+\n+    /* DDR */\n+\n+    /* The high address covers all of RAM, the low address just the first 2GB */\n+    lo_ram_size = s->memmap[TT_ATL_DDR_LO].size;\n+    hi_ram_size = s->memmap[TT_ATL_DDR_HI].size;\n+    if (machine->ram_size > hi_ram_size) {\n+        char *sz = size_to_str(hi_ram_size);\n+        error_report(\"RAM size is too large, maximum is %s\", sz);\n+        g_free(sz);\n+        exit(EXIT_FAILURE);\n+    }\n+\n+    memory_region_init_alias(ram_lo, OBJECT(machine), \"ram.low\", machine->ram,\n+                             0, lo_ram_size);\n+    memory_region_init_alias(ram_hi, OBJECT(machine), \"ram.high\", machine->ram,\n+                             0, hi_ram_size);\n+    memory_region_add_subregion(system_memory,\n+                                s->memmap[TT_ATL_DDR_LO].base, ram_lo);\n+    memory_region_add_subregion(system_memory,\n+                                s->memmap[TT_ATL_DDR_HI].base, ram_hi);\n+\n+    /* Boot ROM */\n+    memory_region_init_rom(bootrom, NULL, \"tt-atlantis.bootrom\",\n+                           s->memmap[TT_ATL_BOOTROM].size, &error_fatal);\n+    memory_region_add_subregion(system_memory, s->memmap[TT_ATL_BOOTROM].base,\n+                                bootrom);\n+\n+    /*\n+     * Init fw_cfg. Must be done before riscv_load_fdt, otherwise the\n+     * device tree cannot be altered and we get FDT_ERR_NOSPACE.\n+     */\n+    s->fw_cfg = create_fw_cfg(&s->memmap[TT_ATL_FW_CFG], machine->smp.cpus);\n+    rom_set_fw(s->fw_cfg);\n+\n+    /* Reboot and exit */\n+    create_reboot_device(&s->memmap[TT_ATL_SYSCON]);\n+\n+    /* UART */\n+    serial_mm_init(system_memory, s->memmap[TT_ATL_UART0].base, 2,\n+                   qdev_get_gpio_in(s->irqchip, TT_ATL_UART0_IRQ),\n+                   115200, serial_hd(0), DEVICE_LITTLE_ENDIAN);\n+\n+    /* Load or create device tree */\n+    if (machine->dtb) {\n+        machine->fdt = load_device_tree(machine->dtb, &s->fdt_size);\n+        if (!machine->fdt) {\n+            error_report(\"load_device_tree() failed\");\n+            exit(1);\n+        }\n+    } else {\n+        create_fdt(s);\n+    }\n+\n+    s->machine_done.notify = tt_atlantis_machine_done;\n+    qemu_add_machine_init_done_notifier(&s->machine_done);\n+}\n+\n+static void tt_atlantis_machine_class_init(ObjectClass *oc, const void *data)\n+{\n+    MachineClass *mc = MACHINE_CLASS(oc);\n+\n+    mc->desc = \"Tenstorrent Atlantis RISC-V SoC\";\n+    mc->init = tt_atlantis_machine_init;\n+    mc->max_cpus = 8;\n+    mc->default_cpus = 8;\n+    mc->default_ram_size = 2 * GiB;\n+    mc->default_cpu_type = TYPE_RISCV_CPU_TT_ASCALON;\n+    mc->block_default_type = IF_VIRTIO;\n+    mc->no_cdrom = 1;\n+    mc->default_ram_id = \"tt_atlantis.ram\";\n+}\n+\n+static const TypeInfo tt_atlantis_types[] = {\n+    {\n+        .name       = MACHINE_TYPE_NAME(\"tt-atlantis\"),\n+        .parent     = TYPE_MACHINE,\n+        .class_init = tt_atlantis_machine_class_init,\n+        .instance_size = sizeof(TTAtlantisState),\n+    },\n+};\n+\n+DEFINE_TYPES(tt_atlantis_types)\ndiff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig\nindex 0222c93f878b..0601ae1a7494 100644\n--- a/hw/riscv/Kconfig\n+++ b/hw/riscv/Kconfig\n@@ -120,6 +120,21 @@ config SPIKE\n     select RISCV_ACLINT\n     select SIFIVE_PLIC\n \n+config TENSTORRENT\n+    bool\n+    default y\n+    depends on RISCV64\n+    imply PCI_DEVICES\n+    imply TEST_DEVICES\n+    select DEVICE_TREE\n+    select RISCV_NUMA\n+    select PVPANIC_MMIO\n+    select SERIAL_MM\n+    select RISCV_ACLINT\n+    select RISCV_APLIC\n+    select RISCV_IMSIC\n+    select FW_CFG_DMA\n+\n config XIANGSHAN_KUNMINGHU\n     bool\n     default y\ndiff --git a/hw/riscv/meson.build b/hw/riscv/meson.build\nindex e53c180d0d10..026e79591f4b 100644\n--- a/hw/riscv/meson.build\n+++ b/hw/riscv/meson.build\n@@ -9,6 +9,7 @@ riscv_ss.add(when: 'CONFIG_SIFIVE_E', if_true: files('sifive_e.c'))\n riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sifive_u.c'))\n riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c'))\n riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: files('microchip_pfsoc.c'))\n+riscv_ss.add(when: 'CONFIG_TENSTORRENT', if_true: files('tt_atlantis.c'))\n riscv_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c'))\n riscv_ss.add(when: 'CONFIG_RISCV_IOMMU', if_true: files(\n \t'riscv-iommu.c', 'riscv-iommu-pci.c', 'riscv-iommu-sys.c', 'riscv-iommu-hpm.c'))\n",
    "prefixes": [
        "v4",
        "09/13"
    ]
}