From nobody Sat Nov 15 17:22:38 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=htecgroup.com); dmarc=pass(p=reject dis=none) header.from=htecgroup.com ARC-Seal: i=2; a=rsa-sha256; t=1750861217; cv=pass; d=zohomail.com; s=zohoarc; b=dHC6qm+sM9R0cISYGvMinuQpvUuvT9q4YJ9pDjp3oUHdJf7ZTVA44ahrdGvR2Qf3mVv22P67uFPuRZNMMhm21j55uMVh+2tLZNMtnVyNPtSEDc4sdRIJXZT+CdHixBUjzSgqlXs3c39s5t1v9WniNTH8bD9vZF5+owULg1z7iZE= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1750861217; 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:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=qxEP4FWeYg6iKNwewBZzX2R7q/0k3R83EvUmxAQP82Y=; b=CxpqXp/M49cleAQyp6DHq1b0hQZ1wjrDSwhkfT+yjb1Xd/l9r3QoQD3+OsEZ5OyK5Jv0C809FUFyPsyKStV4RAEt6QtX4m5aoJ03uG8brDSIcg9+qrMRMTTz3d9kXvWO2YEVZsDb8Uv4oYruPzdhe1bcbLSdhfGJuoje6vfeXE0= ARC-Authentication-Results: i=2; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=htecgroup.com); dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1750861217506596.75656188212; Wed, 25 Jun 2025 07:20:17 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uUQxd-00077F-1R; Wed, 25 Jun 2025 10:18:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uUQxb-000773-8k; Wed, 25 Jun 2025 10:18:47 -0400 Received: from mail-westeuropeazlp170120005.outbound.protection.outlook.com ([2a01:111:f403:c201::5] helo=AS8PR03CU001.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uUQxX-00048J-Rq; Wed, 25 Jun 2025 10:18:47 -0400 Received: from AS4PR09MB6518.eurprd09.prod.outlook.com (2603:10a6:20b:4fb::5) by AM0PR09MB3665.eurprd09.prod.outlook.com (2603:10a6:208:182::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8857.28; Wed, 25 Jun 2025 14:18:21 +0000 Received: from AS4PR09MB6518.eurprd09.prod.outlook.com ([fe80::ad50:891a:847c:580a]) by AS4PR09MB6518.eurprd09.prod.outlook.com ([fe80::ad50:891a:847c:580a%3]) with mapi id 15.20.8857.026; Wed, 25 Jun 2025 14:18:21 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=wd/KzY1Mm7j1YEkwSZuc1pcmJuqLkVUH0y3ZwdHWrYETqXbStFjsXqKlayqGPBnXSk9jQ2ATrzsKz5qhMyHia1oRtyg84YeWx/WLEowFsLjzrgc5dMO+IUuaa3XshL5+rhk3j9KC5TO5uqKnFOeVbm7COyJtOAC9eyR4KDnpr/LUKpCvaNulXz4VBGxXoHcqDicKHZySHJ7SG/NFwxj/h6Deuf1GrTwWMJIDv3AZtBKsyk9NFzuxXMLXv/+DL8whCOvxvIhG8OC4i3hEFe4YWL+05+CGQo74/OmMd84yjjyySmIOXI3HS+BFhUpXNytbCrvkMorzUWvfLupPvHkBMg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=qxEP4FWeYg6iKNwewBZzX2R7q/0k3R83EvUmxAQP82Y=; b=vJ5Xd8MHLruoAOGWI7gt+WGVrgJoFQEVTQCKhYwZ8H5LkKDtNrlYfXSv0H2u+zFiCVS+ri2eaVxuqtbuRxBqVVL0K1O5i9ViIK55/2nVCOXBF+v/zdqLdXyO5NWZOa4MN7yBOXAgKCugzOl0QwH8dE6jh4OuGVz/EjH036/f9MkyqCVjS5jY2X6pamt72O2q8AexUAppbTvL+S+lHW7JqE835W7jklWwf+eis//tL50ozEgGGQqEDTaL1y6oKuJYpJf5fp1pZTo3JB1rOjB9c+uJhYAlrinARqB51Uv0LmUPQL2BTm4Bk1vi9+UouNNax8o24WYUDUEOSQmSiHtIBQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=htecgroup.com; dmarc=pass action=none header.from=htecgroup.com; dkim=pass header.d=htecgroup.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=htecgroup.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=qxEP4FWeYg6iKNwewBZzX2R7q/0k3R83EvUmxAQP82Y=; b=RXncB4vJl/v0PS3QIBHtCSjTaMMmlp4he04bvxGUtPItjpaFnsWqjpBNPKwffE70k6OLUwpBjK3PoWpg7xMBw2v/b9YrPG0egS9vHR3Lg80fSYUgXSCSskHX5y2U1aon51uFmZq7775XmWc1xubg4dIf9ZuYzLWPJl3rf1QEoExew4Iot61YL1UqGLVxf4OfEmuxi72lCbJAEaSNsT6BEb6ImK4DxajfPqPKuOoO1/60gJmzltxiTqPaL5+5IrbSSgFD6fJ4Rfjfrqm5giRakPksANrLxzWNMoS/8egFDQp9/hlIHndiKkIshNZvnUwMEbukCxB5YLiFBs6XozO2mQ== From: Djordje Todorovic To: "qemu-devel@nongnu.org" CC: "qemu-riscv@nongnu.org" , "cfu@mips.com" , "mst@redhat.com" , "marcel.apfelbaum@gmail.com" , "dbarboza@ventanamicro.com" , Djordje Todorovic Subject: [PATCH v4 09/11] hw/riscv: Add support for MIPS Boston-aia board model Thread-Topic: [PATCH v4 09/11] hw/riscv: Add support for MIPS Boston-aia board model Thread-Index: AQHb5dwBdlUl/VldSkSIkY5okC3PEQ== Date: Wed, 25 Jun 2025 14:18:21 +0000 Message-ID: <20250625141732.59084-10-djordje.todorovic@htecgroup.com> References: <20250625141732.59084-1-djordje.todorovic@htecgroup.com> In-Reply-To: <20250625141732.59084-1-djordje.todorovic@htecgroup.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=htecgroup.com; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: AS4PR09MB6518:EE_|AM0PR09MB3665:EE_ x-ms-office365-filtering-correlation-id: 4ca72a46-3b46-468d-0d47-08ddb3f323fa x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; ARA:13230040|1800799024|376014|366016|13003099007|38070700018; x-microsoft-antispam-message-info: =?iso-8859-1?Q?fL2O8+tJY2KObljJ90hygdQJ6vxQRyJXtVa1sPHWZrRC0qmARyKAkEMHqn?= =?iso-8859-1?Q?TGsGSfIKZihecbrPnUyBBWABBU/YIaDBUCz/TqRXHT6wvOMygo/dIj2q9A?= =?iso-8859-1?Q?+TCpKyBp/8Fcfs02VZYaduvcPlfVpQtANsJ4ZrvoimjLu1MHlDzwVFn41V?= =?iso-8859-1?Q?2BwfUbI62wg+ROjVI3hE6tJmxiK5Yvcqd09+uVyQllOpvaRdgN2j4ZQeTx?= =?iso-8859-1?Q?9Yy7doWuwF6fP/lYEn1SJT2+n1v4fZHCdhHt9eamZSZ4r293KPZWYOnvxh?= =?iso-8859-1?Q?UKHrcbv+6s1zgPhJlKMouhGkSktcsiv0iKAVKyhgUqxwJpKDeEEZJdu700?= =?iso-8859-1?Q?8W+gybF+E2bhfNUSDn6nudfsdo7XJ3+v77zDR1wgtcVHWTzh84EJHrqbBV?= =?iso-8859-1?Q?2mesfm9oq0ZojVPImmu+yUMAJoeWSSTT7e/9O0wW6c0d31TSdnknnyhx4F?= =?iso-8859-1?Q?lRgVB8Rt/QstGIBnr6sv9RltBxeOQ1jfqfE0Y3wWVXRl3g5AwdNUxIh5yg?= =?iso-8859-1?Q?+r61QL4lxF16CK3vB3B9bXehk+Uatp85EG7SW8vz3iMldZXwxi7EehdNFN?= =?iso-8859-1?Q?Z0D4CA4Mhl+DYpTwAnU/fmYJdED53OW87Y4w9+dirYiypvZcznHENdEVS6?= =?iso-8859-1?Q?0Jl267N9Apky78ivJnYouJnIT6B1skunJoFdoJ3ZtF6z9dxAoCFlWL/za3?= =?iso-8859-1?Q?Qkb0dH7b5V5xYK9ywYoJt5JbLF4UJGcaSg1+bEW0e3j6bfI0+AeXgIJoME?= =?iso-8859-1?Q?YJqpwr7QShm/Qa4NVRDow3OJ7tFcyEIWwYjJ9Oy29J6AJmCUHXULWSaxFI?= =?iso-8859-1?Q?3GL66ryLN3+dx5gG06RXHdR2aY45qGKhBrPYIJpZGVmfMyrt/Ewsie+6Y4?= =?iso-8859-1?Q?1OEUVd6fGWcYPw8yvWavodG3yn7OnnFsfHWFy2GSuWa8wiR4lQAhSIigQr?= =?iso-8859-1?Q?yMIIscU209w+Vw//CPOGmdx3VwnkcDoSZTT3lymZQTEwIfgs21a3UmQPQy?= =?iso-8859-1?Q?l8lTnD6Lm68gLjQA17HWLOQcR2cj/wWxENN7VrmfsUIQeXmJKwGcP+kxOY?= =?iso-8859-1?Q?8ERSTC635KGr4xiqjIjanbZI878a8D8Q2fVPSkaQNx/rmsGzlOGN+Km0nz?= =?iso-8859-1?Q?jqY4qx9oUe4LsXRCkGwyl8j4FFb6CF8RNHXZ9+zL01gqz+Iosd2Odj4gyj?= =?iso-8859-1?Q?9JB8ugRG+lLY/1wWPNBk2vv9yrtFXUdGWbpCMQbcqIicMuDLP/2RfY62U6?= =?iso-8859-1?Q?mrPH0nCbnw/Gss0IaFOBK5Y1UtIGCjtScSYTJROjAH/lIGcYpyEQhlv42V?= =?iso-8859-1?Q?XVsoybg504wUirekPv2sce75ufLr10docnTAUS4Cc4v2Hc5kEHAFf2b3Yi?= =?iso-8859-1?Q?EMUIbwwM5TXRPI2WlJFL80a34CB+i6/MHwql9tZOvxXVVpkCBD6PN+XfQF?= =?iso-8859-1?Q?/NL64n7cdQ73SHgYUBCVQLRb+htZnmmU0gfhhe838Kf+NnOogK7t86Z31N?= =?iso-8859-1?Q?Eadoi9GkQp0CLhk/0FerWsOafbwIPYzIPzsvll3eVvf1NyN1dChyo9eBSK?= =?iso-8859-1?Q?DUnPPIM=3D?= x-forefront-antispam-report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:AS4PR09MB6518.eurprd09.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230040)(1800799024)(376014)(366016)(13003099007)(38070700018); DIR:OUT; SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?iso-8859-1?Q?774bL2nGa7dtVhp3s9oOkIDl8B0naAVrYLb4nPkpnewSFrgF/qKkzWA+Ui?= =?iso-8859-1?Q?wEc5FqVnVehNULZAhAznlytE3q8/+3gingePwE5Dj0gwBOQCe+s0LK9ELQ?= =?iso-8859-1?Q?AG8+b1m+yxIh8gc9qF6Oon+mZrUQAjN6di9GdtrA6Z+pa03gBudzJPbdmR?= =?iso-8859-1?Q?NUZKGbtbdSkp0byDhWffFt4FGMMnz1xB3r822i+EWe08eMME7sM8UdLOfP?= =?iso-8859-1?Q?+2cw4mWB3q9X8dzaEH2tDaWwsxHvhWa1liqwM0MebNN4/xBpTy1PmftaGt?= =?iso-8859-1?Q?tjuFZksrdJyvByZFW+qAEkfSCq2Vr1UtUfcQQ08bwE0SCT/gv6WzESXlse?= =?iso-8859-1?Q?alSslcoKeTkax2Eojv9I/FZxmJCgccULEUgHMI8HbkD0PB9EkW/APsJnQi?= =?iso-8859-1?Q?g97O7PUnIoEGni4NXimXRMQfF+aacLDSUbkNaP+lWGMU7U8c0EC1SXLNAp?= =?iso-8859-1?Q?npIpljSznsLPhdfGAvbXgfQwhQ5OWlYeO97jLxCbcP1SoucgkKWl98hdgN?= =?iso-8859-1?Q?Y6OXlsaAj1UwMB8p8k46XYvtfLZWnvZl6sgMvV/jOmi0PwfIFd6rpDnmeV?= =?iso-8859-1?Q?pnUhtuXMHzTqOygbs9kbZT7r+NsZRHwAx4UC+6P66RUy7lONPA76sJ09Nl?= =?iso-8859-1?Q?+x6zdHFpa1ph2q5aeAoaBtRyQB82zbvY10jbi+5roVSIGbduHEyBhb3N0A?= =?iso-8859-1?Q?9rpjjQg+/JSt16CyVg+zUKoCQzN5eT2taiYrE1YfqD1AqzfRxQkL8L1U6I?= =?iso-8859-1?Q?Jg0V5z3ivKKxdtGgC0OA9eTERczX4RvH+8AbokVCioUOhhhuzoVi/amcDo?= =?iso-8859-1?Q?2K6zUpYwC0SZ3Ndv5zS3DR23GjRLW4uoRtiTQyMJ6C8uVPkpSdkQO75BoD?= =?iso-8859-1?Q?+p3heEJ34UstDh5RLCoup18tzz0u61kdM/zL7Lm9V7atq0A58R+M+GiZq5?= =?iso-8859-1?Q?DADmAX5GJPi482RrpydE0ez2kLr82T6EBHx+m1aC9smzxVZNTqaVgR5lu6?= =?iso-8859-1?Q?8uPO8bJktVXHa3eh8fGBawx3p7d8t3hQrTHT+VqRy1q2TsNtHs9znUhK+v?= =?iso-8859-1?Q?MNVZWSs/2/PZurC18q2pyRJQAFtyWV7zVDOQ68GE1aowoEYvYJ/UfDwAzk?= =?iso-8859-1?Q?jzJtesywwwYje2gjj4zcdf7bJ6ToXhHy4kYZ+83Nyz6GDQVRC0osPnl2PB?= =?iso-8859-1?Q?G+A9lGsUp7Cju67K8VNEjmnfnSLwfbJbAiFquzLRnyfAgBMyfGOGW0qzVo?= =?iso-8859-1?Q?atHadMXOozst06rBgNqhOOQGeG6g7G1ABnHSdkm+/wAir/ookMb9bt3ymD?= =?iso-8859-1?Q?M2AQa0vX4Uvx4K6kRISD+0l6VvRPBE9ThvKXqrHtiYUgCGlOr7nyuVkole?= =?iso-8859-1?Q?blBSL2Z3ovefruSrg/ZbWjSGcOmCzyurc9qSlwimOwRJbfzc9msiFh9Gwn?= =?iso-8859-1?Q?phIRBPPOeU1TFIy9bPyFIqUQYbofBJMtRHAc/IAkOzT6RGFG12FA8vpohO?= =?iso-8859-1?Q?LgzKUZLKp4eqwBa441eZzObwAy3AK1hiy6hikJ5SVxJdMMsRHX8X3pfc5n?= =?iso-8859-1?Q?XCHXR2aNNVwwNgbrSlQkV6Mo6B3XX0eKxRlq8qKGDzILJerkRX8cDuxh7u?= =?iso-8859-1?Q?9LRARg4vEU/DOi4Wy+kSjad59xW1og3TO5vcsjtXRgyskysku0HcmLKMNw?= =?iso-8859-1?Q?5jd8bsj5QS7a04RHO+w=3D?= Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-OriginatorOrg: htecgroup.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: AS4PR09MB6518.eurprd09.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 4ca72a46-3b46-468d-0d47-08ddb3f323fa X-MS-Exchange-CrossTenant-originalarrivaltime: 25 Jun 2025 14:18:21.7981 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 9f85665b-7efd-4776-9dfe-b6bfda2565ee X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: k4ITfxQOpZyrfSyaJN0yJMxT2e01tTRqR0gk1Nmq7HJ0O9006WDEN7i7xNmfo3i4D73kX0fwGVfvaMbIaAIWVIISlWbG8ULu07jfj2kdfdg= X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM0PR09MB3665 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a01:111:f403:c201::5; envelope-from=Djordje.Todorovic@htecgroup.com; helo=AS8PR03CU001.outbound.protection.outlook.com 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_PASS=-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: 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 @htecgroup.com) X-ZM-MESSAGEID: 1750861218713116600 Content-Type: text/plain; charset="utf-8" Ex: Use 4 cores and 2 threads with each core to have 8 smp cpus as follows. qemu-system-riscv64 -cpu mips-p8700 \ -m 2G -M boston-aia \ -smp 8,cores=3D4,threads=3D2 -kernel fw_payload.bin \ -drive file=3Drootfs.ext2,format=3Draw -serial stdio Signed-off-by: Chao-ying Fu Signed-off-by: Djordje Todorovic Acked-by: Daniel Henrique Barboza --- configs/devices/riscv64-softmmu/default.mak | 1 + docs/system/riscv/mips.rst | 25 + docs/system/target-riscv.rst | 1 + hw/riscv/Kconfig | 6 + hw/riscv/boston-aia.c | 484 ++++++++++++++++++++ hw/riscv/cps.c | 187 ++++++++ hw/riscv/meson.build | 1 + include/hw/riscv/cps.h | 75 +++ 8 files changed, 780 insertions(+) create mode 100644 docs/system/riscv/mips.rst create mode 100644 hw/riscv/boston-aia.c create mode 100644 hw/riscv/cps.c create mode 100644 include/hw/riscv/cps.h diff --git a/configs/devices/riscv64-softmmu/default.mak b/configs/devices/= riscv64-softmmu/default.mak index 39ed3a0061..2f4f92b978 100644 --- a/configs/devices/riscv64-softmmu/default.mak +++ b/configs/devices/riscv64-softmmu/default.mak @@ -11,3 +11,4 @@ # CONFIG_RISCV_VIRT=3Dn # CONFIG_MICROCHIP_PFSOC=3Dn # CONFIG_SHAKTI_C=3Dn +# CONFIG_MIPS_BOSTON_AIA=3Dn diff --git a/docs/system/riscv/mips.rst b/docs/system/riscv/mips.rst new file mode 100644 index 0000000000..c05c6f19d6 --- /dev/null +++ b/docs/system/riscv/mips.rst @@ -0,0 +1,25 @@ +Boards for RISC-V Processors by MIPS +=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 + +RISC-V processors developed by MIPS support Boston-aia board model. The bo= ard +model supports up to 64 harts with MIPS CPS, MIPS GCR, MIPS CPC, AIA plic, +and AIA clint devices. The model can create boot code, if there is no +```-bios``` parameter. Also, we can specify ```-smp x,cores=3Dy,thread=3Dz= ```. + +Enable Boston-aia +----------------- + +To build qemu with support for ``Boston-aia`` set ```CONFIG_MIPS_BOSTON_AI= A=3Dy``. + +Running Linux kernel +-------------------- + +For example, to use 4 cores and 2 threads with each core to have 8 smp cpu= s, +that runs on the ```mips-p8700``` CPU, run qemu as follows: + +.. code-block:: bash + + qemu-system-riscv64 -cpu mips-p8700 \ + -m 2G -M boston-aia \ + -smp 8,cores=3D4,threads=3D2 -kernel fw_payload.bin \ + -drive file=3Drootfs.ext2,format=3Draw -serial stdio diff --git a/docs/system/target-riscv.rst b/docs/system/target-riscv.rst index 95457af130..9e11bb25c9 100644 --- a/docs/system/target-riscv.rst +++ b/docs/system/target-riscv.rst @@ -68,6 +68,7 @@ undocumented; you can get a complete list by running =20 riscv/microblaze-v-generic riscv/microchip-icicle-kit + riscv/mips riscv/shakti-c riscv/sifive_u riscv/virt diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index e6a0ac1fa1..047c6d8ae7 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -119,3 +119,9 @@ config SPIKE select HTIF select RISCV_ACLINT select SIFIVE_PLIC + +config MIPS_BOSTON_AIA + bool + default y + select PCI_EXPRESS + select PCI_EXPRESS_XILINX diff --git a/hw/riscv/boston-aia.c b/hw/riscv/boston-aia.c new file mode 100644 index 0000000000..6ed5c636cc --- /dev/null +++ b/hw/riscv/boston-aia.c @@ -0,0 +1,484 @@ +/* + * MIPS Boston-aia development board emulation. + * + * Copyright (c) 2016 Imagination Technologies + * + * Copyright (c) 2025 MIPS + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * SPDX-License-Identifier: GPL-2.0-or-later + * +*/ + +#include "qemu/osdep.h" +#include "qemu/units.h" + +#include "hw/boards.h" +#include "hw/char/serial-mm.h" +#include "hw/ide/pci.h" +#include "hw/ide/ahci-pci.h" +#include "hw/loader.h" +#include "hw/riscv/cps.h" +#include "hw/pci-host/xilinx-pcie.h" +#include "hw/qdev-properties.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "chardev/char.h" +#include "system/address-spaces.h" +#include "system/device_tree.h" +#include "system/system.h" +#include "system/qtest.h" +#include "system/runstate.h" + +#include +#include "qom/object.h" + +#define TYPE_MIPS_BOSTON_AIA "mips-boston-aia" +typedef struct BostonState BostonState; +DECLARE_INSTANCE_CHECKER(BostonState, BOSTON, + TYPE_MIPS_BOSTON_AIA) + +enum { + BOSTON_PCIE2, + BOSTON_PCIE2_MMIO, + BOSTON_PLATREG, + BOSTON_UART, + BOSTON_LCD, + BOSTON_FLASH, + BOSTON_HIGHDDR, +}; + +static const MemMapEntry boston_memmap[] =3D { + [BOSTON_PCIE2] =3D { 0x14000000, 0x2000000 }, + [BOSTON_PCIE2_MMIO] =3D { 0x16000000, 0x100000 }, + [BOSTON_PLATREG] =3D { 0x17ffd000, 0x1000 }, + [BOSTON_UART] =3D { 0x17ffe000, 0x20 }, + [BOSTON_LCD] =3D { 0x17fff000, 0x8 }, + [BOSTON_FLASH] =3D { 0x18000000, 0x8000000 }, + [BOSTON_HIGHDDR] =3D { 0x80000000, 0x0 }, +}; + +/* Interrupt numbers for APLIC. */ +#define UART_INT 4 +#define PCIE2_INT 7 + +struct BostonState { + SysBusDevice parent_obj; + + MachineState *mach; + RISCVCPSState cps; + SerialMM *uart; + + CharBackend lcd_display; + char lcd_content[8]; + bool lcd_inited; +}; + +enum boston_plat_reg { + PLAT_FPGA_BUILD =3D 0x00, + PLAT_CORE_CL =3D 0x04, + PLAT_WRAPPER_CL =3D 0x08, + PLAT_SYSCLK_STATUS =3D 0x0c, + PLAT_SOFTRST_CTL =3D 0x10, +#define PLAT_SOFTRST_CTL_SYSRESET (1 << 4) + PLAT_DDR3_STATUS =3D 0x14, +#define PLAT_DDR3_STATUS_LOCKED (1 << 0) +#define PLAT_DDR3_STATUS_CALIBRATED (1 << 2) +#define PLAT_DDR3_INTERFACE_RESET (1 << 3) + PLAT_PCIE_STATUS =3D 0x18, +#define PLAT_PCIE_STATUS_PCIE0_LOCKED (1 << 0) +#define PLAT_PCIE_STATUS_PCIE1_LOCKED (1 << 8) +#define PLAT_PCIE_STATUS_PCIE2_LOCKED (1 << 16) + PLAT_FLASH_CTL =3D 0x1c, + PLAT_SPARE0 =3D 0x20, + PLAT_SPARE1 =3D 0x24, + PLAT_SPARE2 =3D 0x28, + PLAT_SPARE3 =3D 0x2c, + PLAT_MMCM_DIV =3D 0x30, +#define PLAT_MMCM_DIV_CLK0DIV_SHIFT 0 +#define PLAT_MMCM_DIV_INPUT_SHIFT 8 +#define PLAT_MMCM_DIV_MUL_SHIFT 16 +#define PLAT_MMCM_DIV_CLK1DIV_SHIFT 24 + PLAT_BUILD_CFG =3D 0x34, +#define PLAT_BUILD_CFG_IOCU_EN (1 << 0) +#define PLAT_BUILD_CFG_PCIE0_EN (1 << 1) +#define PLAT_BUILD_CFG_PCIE1_EN (1 << 2) +#define PLAT_BUILD_CFG_PCIE2_EN (1 << 3) + PLAT_DDR_CFG =3D 0x38, +#define PLAT_DDR_CFG_SIZE (0xf << 0) +#define PLAT_DDR_CFG_MHZ (0xfff << 4) + PLAT_NOC_PCIE0_ADDR =3D 0x3c, + PLAT_NOC_PCIE1_ADDR =3D 0x40, + PLAT_NOC_PCIE2_ADDR =3D 0x44, + PLAT_SYS_CTL =3D 0x48, +}; + +static void boston_lcd_event(void *opaque, QEMUChrEvent event) +{ + BostonState *s =3D opaque; + if (event =3D=3D CHR_EVENT_OPENED && !s->lcd_inited) { + qemu_chr_fe_printf(&s->lcd_display, " "); + s->lcd_inited =3D true; + } +} + +static uint64_t boston_lcd_read(void *opaque, hwaddr addr, + unsigned size) +{ + BostonState *s =3D opaque; + uint64_t val =3D 0; + + switch (size) { + case 8: + val |=3D (uint64_t)s->lcd_content[(addr + 7) & 0x7] << 56; + val |=3D (uint64_t)s->lcd_content[(addr + 6) & 0x7] << 48; + val |=3D (uint64_t)s->lcd_content[(addr + 5) & 0x7] << 40; + val |=3D (uint64_t)s->lcd_content[(addr + 4) & 0x7] << 32; + /* fall through */ + case 4: + val |=3D (uint64_t)s->lcd_content[(addr + 3) & 0x7] << 24; + val |=3D (uint64_t)s->lcd_content[(addr + 2) & 0x7] << 16; + /* fall through */ + case 2: + val |=3D (uint64_t)s->lcd_content[(addr + 1) & 0x7] << 8; + /* fall through */ + case 1: + val |=3D (uint64_t)s->lcd_content[(addr + 0) & 0x7]; + break; + } + + return val; +} + +static void boston_lcd_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + BostonState *s =3D opaque; + + switch (size) { + case 8: + s->lcd_content[(addr + 7) & 0x7] =3D val >> 56; + s->lcd_content[(addr + 6) & 0x7] =3D val >> 48; + s->lcd_content[(addr + 5) & 0x7] =3D val >> 40; + s->lcd_content[(addr + 4) & 0x7] =3D val >> 32; + /* fall through */ + case 4: + s->lcd_content[(addr + 3) & 0x7] =3D val >> 24; + s->lcd_content[(addr + 2) & 0x7] =3D val >> 16; + /* fall through */ + case 2: + s->lcd_content[(addr + 1) & 0x7] =3D val >> 8; + /* fall through */ + case 1: + s->lcd_content[(addr + 0) & 0x7] =3D val; + break; + } + + qemu_chr_fe_printf(&s->lcd_display, + "\r%-8.8s", s->lcd_content); +} + +static const MemoryRegionOps boston_lcd_ops =3D { + .read =3D boston_lcd_read, + .write =3D boston_lcd_write, + .endianness =3D DEVICE_NATIVE_ENDIAN, +}; + +static uint64_t boston_platreg_read(void *opaque, hwaddr addr, + unsigned size) +{ + BostonState *s =3D opaque; + uint32_t gic_freq, val; + + if (size !=3D 4) { + qemu_log_mask(LOG_UNIMP, "%uB platform register read\n", size); + return 0; + } + + switch (addr & 0xffff) { + case PLAT_FPGA_BUILD: + case PLAT_CORE_CL: + case PLAT_WRAPPER_CL: + return 0; + case PLAT_DDR3_STATUS: + return PLAT_DDR3_STATUS_LOCKED | PLAT_DDR3_STATUS_CALIBRATED + | PLAT_DDR3_INTERFACE_RESET; + case PLAT_MMCM_DIV: + gic_freq =3D 25000000 / 1000000; + val =3D gic_freq << PLAT_MMCM_DIV_INPUT_SHIFT; + val |=3D 1 << PLAT_MMCM_DIV_MUL_SHIFT; + val |=3D 1 << PLAT_MMCM_DIV_CLK0DIV_SHIFT; + val |=3D 1 << PLAT_MMCM_DIV_CLK1DIV_SHIFT; + return val; + case PLAT_BUILD_CFG: + val =3D PLAT_BUILD_CFG_PCIE0_EN; + val |=3D PLAT_BUILD_CFG_PCIE1_EN; + val |=3D PLAT_BUILD_CFG_PCIE2_EN; + return val; + case PLAT_DDR_CFG: + val =3D s->mach->ram_size / GiB; + assert(!(val & ~PLAT_DDR_CFG_SIZE)); + val |=3D PLAT_DDR_CFG_MHZ; + return val; + default: + qemu_log_mask(LOG_UNIMP, "Read platform register 0x%" HWADDR_PRIx = "\n", + addr & 0xffff); + return 0; + } +} + +static void boston_platreg_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + if (size !=3D 4) { + qemu_log_mask(LOG_UNIMP, "%uB platform register write\n", size); + return; + } + + switch (addr & 0xffff) { + case PLAT_FPGA_BUILD: + case PLAT_CORE_CL: + case PLAT_WRAPPER_CL: + case PLAT_DDR3_STATUS: + case PLAT_PCIE_STATUS: + case PLAT_MMCM_DIV: + case PLAT_BUILD_CFG: + case PLAT_DDR_CFG: + /* read only */ + break; + case PLAT_SOFTRST_CTL: + if (val & PLAT_SOFTRST_CTL_SYSRESET) { + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + } + break; + default: + qemu_log_mask(LOG_UNIMP, "Write platform register 0x%" HWADDR_PRIx + " =3D 0x%" PRIx64 "\n", addr & 0xffff, val); + break; + } +} + +static const MemoryRegionOps boston_platreg_ops =3D { + .read =3D boston_platreg_read, + .write =3D boston_platreg_write, + .endianness =3D DEVICE_NATIVE_ENDIAN, +}; + +static const TypeInfo boston_device =3D { + .name =3D TYPE_MIPS_BOSTON_AIA, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(BostonState), +}; + +static void boston_register_types(void) +{ + type_register_static(&boston_device); +} +type_init(boston_register_types) + +#define NUM_INSNS 6 +static void gen_firmware(uint32_t *p) +{ + int i; + uint32_t reset_vec[NUM_INSNS] =3D { + /* CM relocate */ + 0x1fb802b7, /* li t0,0x1fb80000 */ + 0x16100337, /* li t1,0x16100000 */ + 0x0062b423, /* sd t1,8(t0) */ + /* Jump to 0x80000000 */ + 0x00100293, /* li t0,1 */ + 0x01f29293, /* slli t0,t0,1f */ + 0x00028067 /* jr t0 */ + }; + + for (i =3D 0; i < NUM_INSNS; i++) { + *p++ =3D reset_vec[i]; + } +} + +static inline XilinxPCIEHost * +xilinx_pcie_init(MemoryRegion *sys_mem, uint32_t bus_nr, + hwaddr cfg_base, uint64_t cfg_size, + hwaddr mmio_base, uint64_t mmio_size, + qemu_irq irq) +{ + DeviceState *dev; + MemoryRegion *cfg, *mmio; + + dev =3D qdev_new(TYPE_XILINX_PCIE_HOST); + + qdev_prop_set_uint32(dev, "bus_nr", bus_nr); + qdev_prop_set_uint64(dev, "cfg_base", cfg_base); + qdev_prop_set_uint64(dev, "cfg_size", cfg_size); + qdev_prop_set_uint64(dev, "mmio_base", mmio_base); + qdev_prop_set_uint64(dev, "mmio_size", mmio_size); + + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + cfg =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); + memory_region_add_subregion_overlap(sys_mem, cfg_base, cfg, 0); + + mmio =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1); + memory_region_add_subregion_overlap(sys_mem, 0, mmio, 0); + + qdev_connect_gpio_out_named(dev, "interrupt_out", 0, irq); + + return XILINX_PCIE_HOST(dev); +} + +static void boston_mach_init(MachineState *machine) +{ + DeviceState *dev; + BostonState *s; + MemoryRegion *flash, *ddr_low_alias, *lcd, *platreg; + MemoryRegion *sys_mem =3D get_system_memory(); + XilinxPCIEHost *pcie2; + PCIDevice *pdev; + AHCIPCIState *ich9; + DriveInfo *hd[6]; + Chardev *chr; + int fw_size; + + if ((machine->ram_size % GiB) || + (machine->ram_size > (4 * GiB))) { + error_report("Memory size must be 1GB, 2GB, 3GB, or 4GB"); + exit(1); + } + + if (machine->smp.cpus / machine->smp.cores / machine->smp.threads > 1)= { + error_report("Invalid -smp x,cores=3Dy,threads=3Dz. The max number= of clusters " + "supported is 1"); + exit(1); + } + + dev =3D qdev_new(TYPE_MIPS_BOSTON_AIA); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + s =3D BOSTON(dev); + s->mach =3D machine; + + object_initialize_child(OBJECT(machine), "cps", &s->cps, TYPE_RISCV_CP= S); + object_property_set_str(OBJECT(&s->cps), "cpu-type", machine->cpu_type, + &error_fatal); + object_property_set_uint(OBJECT(&s->cps), "num-vp", machine->smp.cpus, + &error_fatal); + object_property_set_uint(OBJECT(&s->cps), "num-hart", machine->smp.thr= eads, + &error_fatal); + object_property_set_uint(OBJECT(&s->cps), "num-core", machine->smp.cor= es, + &error_fatal); + object_property_set_uint(OBJECT(&s->cps), "gcr-base", GCR_BASE_ADDR, + &error_fatal); + sysbus_realize(SYS_BUS_DEVICE(&s->cps), &error_fatal); + + sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->cps), 0, 0, 1); + + flash =3D g_new(MemoryRegion, 1); + memory_region_init_rom(flash, NULL, "boston.flash", + boston_memmap[BOSTON_FLASH].size, &error_fatal); + memory_region_add_subregion_overlap(sys_mem, + boston_memmap[BOSTON_FLASH].base, + flash, 0); + + memory_region_add_subregion_overlap(sys_mem, + boston_memmap[BOSTON_HIGHDDR].base, + machine->ram, 0); + + ddr_low_alias =3D g_new(MemoryRegion, 1); + memory_region_init_alias(ddr_low_alias, NULL, "boston_low.ddr", + machine->ram, 0, + MIN(machine->ram_size, (256 * MiB))); + memory_region_add_subregion_overlap(sys_mem, 0, ddr_low_alias, 0); + + pcie2 =3D xilinx_pcie_init(sys_mem, 2, + boston_memmap[BOSTON_PCIE2].base, + boston_memmap[BOSTON_PCIE2].size, + boston_memmap[BOSTON_PCIE2_MMIO].base, + boston_memmap[BOSTON_PCIE2_MMIO].size, + qdev_get_gpio_in(s->cps.aplic, PCIE2_INT)); + + platreg =3D g_new(MemoryRegion, 1); + memory_region_init_io(platreg, NULL, &boston_platreg_ops, s, + "boston-platregs", + boston_memmap[BOSTON_PLATREG].size); + memory_region_add_subregion_overlap(sys_mem, + boston_memmap[BOSTON_PLATREG].base, platreg, 0); + + s->uart =3D serial_mm_init(sys_mem, boston_memmap[BOSTON_UART].base, 2, + qdev_get_gpio_in(s->cps.aplic, UART_INT), 100= 00000, + serial_hd(0), DEVICE_NATIVE_ENDIAN); + + lcd =3D g_new(MemoryRegion, 1); + memory_region_init_io(lcd, NULL, &boston_lcd_ops, s, "boston-lcd", 0x8= ); + memory_region_add_subregion_overlap(sys_mem, + boston_memmap[BOSTON_LCD].base, lc= d, 0); + + chr =3D qemu_chr_new("lcd", "vc:320x240", NULL); + qemu_chr_fe_init(&s->lcd_display, chr, NULL); + qemu_chr_fe_set_handlers(&s->lcd_display, NULL, NULL, + boston_lcd_event, NULL, s, NULL, true); + + pdev =3D pci_create_simple_multifunction(&PCI_BRIDGE(&pcie2->root)->se= c_bus, + PCI_DEVFN(0, 0), TYPE_ICH9_AHCI= ); + ich9 =3D ICH9_AHCI(pdev); + g_assert(ARRAY_SIZE(hd) =3D=3D ich9->ahci.ports); + ide_drive_get(hd, ich9->ahci.ports); + ahci_ide_create_devs(&ich9->ahci, hd); + + if (machine->firmware) { + fw_size =3D load_image_targphys(machine->firmware, + 0x1fc00000, 4 * MiB); + if (fw_size =3D=3D -1) { + error_report("unable to load firmware image '%s'", + machine->firmware); + exit(1); + } + if (machine->kernel_filename) { + fw_size =3D load_image_targphys(machine->kernel_filename, + 0x80000000, 64 * MiB); + if (fw_size =3D=3D -1) { + error_report("unable to load kernel image '%s'", + machine->kernel_filename); + exit(1); + } + } + } else if (machine->kernel_filename) { + fw_size =3D load_image_targphys(machine->kernel_filename, + 0x80000000, 64 * MiB); + if (fw_size =3D=3D -1) { + error_report("unable to load kernel image '%s'", + machine->kernel_filename); + exit(1); + } + + gen_firmware(memory_region_get_ram_ptr(flash) + 0x7c00000); + } else if (!qtest_enabled()) { + error_report("Please provide either a -kernel or -bios argument"); + exit(1); + } +} + +static void boston_mach_class_init(MachineClass *mc) +{ + mc->desc =3D "MIPS Boston-aia"; + mc->init =3D boston_mach_init; + mc->block_default_type =3D IF_IDE; + mc->default_ram_size =3D 2 * GiB; + mc->default_ram_id =3D "boston.ddr"; + mc->max_cpus =3D MAX_HARTS; + mc->default_cpu_type =3D TYPE_RISCV_CPU_MIPS_P8700; +} + +DEFINE_MACHINE("boston-aia", boston_mach_class_init) diff --git a/hw/riscv/cps.c b/hw/riscv/cps.c new file mode 100644 index 0000000000..ab4c27c7ee --- /dev/null +++ b/hw/riscv/cps.c @@ -0,0 +1,187 @@ +/* + * Coherent Processing System emulation. + * + * Copyright (c) 2016 Imagination Technologies + * + * Copyright (c) 2025 MIPS + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/module.h" +#include "hw/riscv/cps.h" +#include "hw/qdev-properties.h" +#include "system/reset.h" +#include "hw/intc/riscv_aclint.h" +#include "hw/intc/riscv_aplic.h" +#include "hw/intc/riscv_imsic.h" +#include "hw/pci/msi.h" + +static void riscv_cps_init(Object *obj) +{ + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + RISCVCPSState *s =3D RISCV_CPS(obj); + + /* + * Cover entire address space as there do not seem to be any + * constraints for the base address of CPC . + */ + memory_region_init(&s->container, obj, "mips-cps-container", UINT64_MA= X); + sysbus_init_mmio(sbd, &s->container); +} + +static void main_cpu_reset(void *opaque) +{ + RISCVCPU *cpu =3D opaque; + CPUState *cs =3D CPU(cpu); + + cpu_reset(cs); +} + +static void riscv_cps_realize(DeviceState *dev, Error **errp) +{ + RISCVCPSState *s =3D RISCV_CPS(dev); + RISCVCPU *cpu; + int i; + + /* Set up cpu_index and mhartid for avaiable CPUs. */ + int harts_in_cluster =3D s->num_hart * s->num_core; + int num_of_clusters =3D s->num_vp / harts_in_cluster; + for (i =3D 0; i < s->num_vp; i++) { + cpu =3D RISCV_CPU(object_new(s->cpu_type)); + + /* All VPs are halted on reset. Leave powering up to CPC. */ + object_property_set_bool(OBJECT(cpu), "start-powered-off", true, + &error_abort); + + if (!qdev_realize_and_unref(DEVICE(cpu), NULL, errp)) { + return; + } + + /* Set up mhartid */ + int cluster_id =3D i / harts_in_cluster; + int hart_id =3D (i % harts_in_cluster) % s->num_hart; + int core_id =3D (i % harts_in_cluster) / s->num_hart; + int mhartid =3D (cluster_id << MHARTID_CLUSTER_SHIFT) + + (core_id << MHARTID_CORE_SHIFT) + + (hart_id << MHARTID_HART_SHIFT); + cpu->env.mhartid =3D mhartid; + qemu_register_reset(main_cpu_reset, cpu); + } + + /* Cluster Power Controller */ + object_initialize_child(OBJECT(dev), "cpc", &s->cpc, TYPE_RISCV_CPC); + object_property_set_uint(OBJECT(&s->cpc), "cluster-id", 0, + &error_abort); + object_property_set_uint(OBJECT(&s->cpc), "num-vp", s->num_vp, + &error_abort); + object_property_set_uint(OBJECT(&s->cpc), "num-hart", s->num_hart, + &error_abort); + object_property_set_uint(OBJECT(&s->cpc), "num-core", s->num_core, + &error_abort); + object_property_set_int(OBJECT(&s->cpc), "vp-start-running", 1, + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpc), errp)) { + return; + } + + memory_region_add_subregion(&s->container, 0, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpc)= , 0)); + + /* Global Configuration Registers */ + object_initialize_child(OBJECT(dev), "gcr", &s->gcr, TYPE_RISCV_GCR); + object_property_set_uint(OBJECT(&s->gcr), "cluster-id", 0, + &error_abort); + object_property_set_uint(OBJECT(&s->gcr), "num-vp", s->num_vp, + &error_abort); + object_property_set_int(OBJECT(&s->gcr), "gcr-rev", 0xa00, + &error_abort); + object_property_set_int(OBJECT(&s->gcr), "gcr-base", s->gcr_base, + &error_abort); + object_property_set_link(OBJECT(&s->gcr), "cpc", OBJECT(&s->cpc.mr), + &error_abort); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->gcr), errp)) { + return; + } + + memory_region_add_subregion(&s->container, s->gcr_base, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gcr)= , 0)); + + for (i =3D 0; i < num_of_clusters; i++) { + uint64_t cm_base =3D GLOBAL_CM_BASE + (CM_SIZE * i); + uint32_t hartid_base =3D i << MHARTID_CLUSTER_SHIFT; + s->aplic =3D riscv_aplic_create(cm_base + AIA_PLIC_M_OFFSET, + AIA_PLIC_M_SIZE, + hartid_base, /* hartid_base */ + MAX_HARTS, /* num_harts */ + APLIC_NUM_SOURCES, + APLIC_NUM_PRIO_BITS, + false, true, NULL); + riscv_aplic_create(cm_base + AIA_PLIC_S_OFFSET, + AIA_PLIC_S_SIZE, + hartid_base, /* hartid_base */ + MAX_HARTS, /* num_harts */ + APLIC_NUM_SOURCES, + APLIC_NUM_PRIO_BITS, + false, false, s->aplic); + /* PLIC changes msi_nonbroken to ture. We revert the change. */ + msi_nonbroken =3D false; + riscv_aclint_swi_create(cm_base + AIA_CLINT_OFFSET, + hartid_base, MAX_HARTS, false); + riscv_aclint_mtimer_create(cm_base + AIA_CLINT_OFFSET + + RISCV_ACLINT_SWI_SIZE, + RISCV_ACLINT_DEFAULT_MTIMER_SIZE, + hartid_base, + MAX_HARTS, + RISCV_ACLINT_DEFAULT_MTIMECMP, + RISCV_ACLINT_DEFAULT_MTIME, + RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, fal= se); + } +} + +static const Property riscv_cps_properties[] =3D { + DEFINE_PROP_UINT32("num-vp", RISCVCPSState, num_vp, 1), + DEFINE_PROP_UINT32("num-hart", RISCVCPSState, num_hart, 1), + DEFINE_PROP_UINT32("num-core", RISCVCPSState, num_core, 1), + DEFINE_PROP_UINT64("gcr-base", RISCVCPSState, gcr_base, GCR_BASE_ADDR), + DEFINE_PROP_STRING("cpu-type", RISCVCPSState, cpu_type), +}; + +static void riscv_cps_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->realize =3D riscv_cps_realize; + device_class_set_props(dc, riscv_cps_properties); +} + +static const TypeInfo riscv_cps_info =3D { + .name =3D TYPE_RISCV_CPS, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(RISCVCPSState), + .instance_init =3D riscv_cps_init, + .class_init =3D riscv_cps_class_init, +}; + +static void riscv_cps_register_types(void) +{ + type_register_static(&riscv_cps_info); +} + +type_init(riscv_cps_register_types) diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index c22f3a7216..76a038f60e 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -13,5 +13,6 @@ 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_MIPS_BOSTON_AIA', if_true: files('boston-aia.c'= , 'cps.c')) =20 hw_arch +=3D {'riscv': riscv_ss} diff --git a/include/hw/riscv/cps.h b/include/hw/riscv/cps.h new file mode 100644 index 0000000000..dfc45f5797 --- /dev/null +++ b/include/hw/riscv/cps.h @@ -0,0 +1,75 @@ +/* + * Coherent Processing System emulation. + * + * Copyright (c) 2016 Imagination Technologies + * + * Copyright (c) 2025 MIPS + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + */ + +#ifndef RISCV_CPS_H +#define RISCV_CPS_H + +#include "hw/sysbus.h" +#include "hw/misc/riscv_cmgcr.h" +#include "hw/misc/riscv_cpc.h" +#include "target/riscv/cpu.h" +#include "qom/object.h" + +#define TYPE_RISCV_CPS "riscv-cps" +OBJECT_DECLARE_SIMPLE_TYPE(RISCVCPSState, RISCV_CPS) + +/* The model supports up to 64 harts. */ +#define MAX_HARTS 64 + +/* The global CM base for the boston-aia model. */ +#define GLOBAL_CM_BASE 0x16100000 +/* The CM block is 512 KiB. */ +#define CM_SIZE (1 << 19) + +/* The mhartid bits has cluster at bit 16, core at bit 4, and hart at + bit 0. */ +#define MHARTID_CLUSTER_SHIFT 16 +#define MHARTID_CORE_SHIFT 4 +#define MHARTID_HART_SHIFT 0 + +#define APLIC_NUM_SOURCES 0x35 /* Arbitray maximum number of interrupts. */ +#define APLIC_NUM_PRIO_BITS 3 +#define AIA_PLIC_M_OFFSET 0x40000 +#define AIA_PLIC_M_SIZE 0x8000 +#define AIA_PLIC_S_OFFSET 0x60000 +#define AIA_PLIC_S_SIZE 0x8000 +#define AIA_CLINT_OFFSET 0x50000 + +typedef struct RISCVCPSState { + SysBusDevice parent_obj; + + uint32_t num_vp; + uint32_t num_hart; + uint32_t num_core; + uint64_t gcr_base; + char *cpu_type; + + MemoryRegion container; + RISCVGCRState gcr; + RISCVCPCState cpc; + + DeviceState *aplic; +} RISCVCPSState; + +#endif --=20 2.34.1