Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.2/patches/2235169/?format=api
{ "id": 2235169, "url": "http://patchwork.ozlabs.org/api/1.2/patches/2235169/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260508183717.193630-6-tdave@nvidia.com/", "project": { "id": 14, "url": "http://patchwork.ozlabs.org/api/1.2/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": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260508183717.193630-6-tdave@nvidia.com>", "list_archive_url": null, "date": "2026-05-08T18:37:14", "name": "[RFC,5/8] hw/pci: allocate remaining BARs for buses without fixed BARs", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "01ce1245571d4fab7cd31ea6598a165410742786", "submitter": { "id": 89928, "url": "http://patchwork.ozlabs.org/api/1.2/people/89928/?format=api", "name": "Tushar Dave", "email": "tdave@nvidia.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260508183717.193630-6-tdave@nvidia.com/mbox/", "series": [ { "id": 503429, "url": "http://patchwork.ozlabs.org/api/1.2/series/503429/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=503429", "date": "2026-05-08T18:37:09", "name": "hw/arm/virt, hw/pci: PCI pre-enumeration and fixed BAR allocation", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/503429/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2235169/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2235169/checks/", "tags": {}, "related": [], "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=Nvidia.com header.i=@Nvidia.com header.a=rsa-sha256\n header.s=selector2 header.b=VCuso00T;\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)", "dkim=none (message not signed)\n header.d=none;dmarc=none action=none header.from=nvidia.com;" ], "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 4gByZJ6gpxz1yCg\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 09 May 2026 04:39:04 +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 1wLQ5Y-0006hq-BA; Fri, 08 May 2026 14:38:16 -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 <tdave@nvidia.com>)\n id 1wLQ5O-0006gQ-Iq; Fri, 08 May 2026 14:38:06 -0400", "from\n mail-northcentralusazlp170100001.outbound.protection.outlook.com\n ([2a01:111:f403:c105::1] helo=CH1PR05CU001.outbound.protection.outlook.com)\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <tdave@nvidia.com>)\n id 1wLQ5M-0002b2-3S; Fri, 08 May 2026 14:38:06 -0400", "from BY5PR12MB4179.namprd12.prod.outlook.com (2603:10b6:a03:211::8)\n by DM4PR12MB6205.namprd12.prod.outlook.com (2603:10b6:8:a8::19) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9891.15; Fri, 8 May\n 2026 18:37:51 +0000", "from BY5PR12MB4179.namprd12.prod.outlook.com\n ([fe80::2036:e8b:9b3:f325]) by BY5PR12MB4179.namprd12.prod.outlook.com\n ([fe80::2036:e8b:9b3:f325%4]) with mapi id 15.20.9891.019; Fri, 8 May 2026\n 18:37:51 +0000" ], "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;\n b=v8FtgfQspDt8XpIK1nXypmybTNcMbCPBIefl2mNoR4KCb1wyg2cGD1xnLvkqL2EuipfQhjLLMSJ3hMsdtWjAG5YExkha02xtXLdNfjHv+jFUtmgN/E5lp9j8m4omzjeMR0cbaNS3IXCePZDnF4PQxwXz/QVygxcs4eFLihjvsvmv3HRCw+DGIfJk8qy5Lu324TbX2IzdZEfK6CvPoq2i1oaVpiHwk8L9JnPWzLIyT4njErh15VIN1IF8fHnnp0c17CIJBUMyLh7SUnXIyhc+R3X4fFf7KSau2mHnXDjGCVP5GHt4NxjD7dLsrrJZRO0hSbgW6Ih8hKQOXxOCPrrA6g==", "ARC-Message-Signature": "i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n s=arcselector10001;\n 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;\n bh=cxDvV4LZ4ek8q78zLfgg06hLW8aN2srFmLdvM6m92Gc=;\n b=lN0MUQiOULMoNqBKgOjYgnKgndS5fmHnKczx3pc+tUYfxmQv8ooVdnlkOE5Y1fO4qvxO+inhllDxraIFK2X5N4W9qFJ5cxQ+hIyOVKMy6jZNrG/dmNfUp3KFZyXCIcudXEzsSXdFtb23EoYi/dxvx/4jB25rJmvQI3ihTFA68qADgQTyciPxshQKUnaV3x12x9s1Gx9Ipcdfk6uU41cpfUSUxiW+JFxDcAyJBQkzbhf1OHjnmORIOdmPSbd1WGfQHAwSUyRYYl6h62VXc+gGNyykJzcEz2+vjH5yYmD3H6L/Coc1B9V3KXlxd6VILosROOJ4IVRqnGjp5ntFET2Qdg==", "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=pass\n smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com;\n dkim=pass header.d=nvidia.com; arc=none", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com;\n s=selector2;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=cxDvV4LZ4ek8q78zLfgg06hLW8aN2srFmLdvM6m92Gc=;\n b=VCuso00Tww8StwdHPE59Lp4G59sNgi27cxczFr4sd8zidx2DcPSdyklEfTDv2Qqa0p+1DB5H4gQ7jzgovaOTPNWXc6ST1LPLWnJLdFbSS/y+tvWm3Unvl6n9Vv8DUZ/jQ/62vP55YtJrMGF2Z3+e8Ydwe7Z6SVwVI2nOb+GbBRZxbAn+PudsrgXOnTY2uvup9hzL5Zq4aG7nm8hWawrbJMWa+mFFp6aes2V3m47IU2ZjIglOzoBPo4Otl4FY4gaBEr+W7/6x07StJGrfTQ9XP3z/iSDWMi7ZMq7tM0zRIUKpCnk7QacVTfnPUav5it669DUFOeUQFG5WQF1Hl0Xnzw==", "From": "Tushar Dave <tdave@nvidia.com>", "To": "qemu-devel@nongnu.org", "Cc": "alwilliamson@nvidia.com, jgg@nvidia.com, skolothumtho@nvidia.com,\n qemu-arm@nongnu.org, peter.maydell@linaro.org, mst@redhat.com,\n marcel.apfelbaum@gmail.com, devel@edk2.groups.io", "Subject": "[RFC PATCH 5/8] hw/pci: allocate remaining BARs for buses without\n fixed BARs", "Date": "Fri, 8 May 2026 13:37:14 -0500", "Message-Id": "<20260508183717.193630-6-tdave@nvidia.com>", "X-Mailer": "git-send-email 2.34.1", "In-Reply-To": "<20260508183717.193630-1-tdave@nvidia.com>", "References": "<20260508183717.193630-1-tdave@nvidia.com>", "Content-Transfer-Encoding": "8bit", "Content-Type": "text/plain", "X-ClientProxiedBy": "MN0P221CA0021.NAMP221.PROD.OUTLOOK.COM\n (2603:10b6:208:52a::25) To BY5PR12MB4179.namprd12.prod.outlook.com\n (2603:10b6:a03:211::8)", "MIME-Version": "1.0", "X-MS-PublicTrafficType": "Email", "X-MS-TrafficTypeDiagnostic": "BY5PR12MB4179:EE_|DM4PR12MB6205:EE_", "X-MS-Office365-Filtering-Correlation-Id": "b889e638-85a6-49e0-485a-08dead30e8f2", "X-MS-Exchange-SenderADCheck": "1", "X-MS-Exchange-AntiSpam-Relay": "0", "X-Microsoft-Antispam": "BCL:0;\n ARA:13230040|366016|1800799024|376014|22082099003|18002099003|56012099003;", "X-Microsoft-Antispam-Message-Info": "\n bAWKxHOpxI6m06hDAtwA7J3P1wk+6yDcVzKG9/BvJzJDja5YmZ3QpQ7noNdZO+GRKgeN2B9DaPCIz9362iBjWNy9Cdg/Non/keRg/uVBrggZCZPVyvDbcCNEuFsY4+AuPv+E+TmnEn/OR3g9eLQV70bdV81bqK6PbggYZCwhmns4zWTIy7hn5YpA2Yb2au4hPeZW9abv1CDh4ULW1dATdKbnEqgWJuBeskklTamPG4kFuzw8kGomhD+2IXW6OK9oo1rNK2/03trFWLPKtxZxOCALR9sJJdvtcrBvi06cfIuZbMSmBSkjcUj7qVrCRF9x9AT7XXw0sQlPSMshRkEbloxybZzMacRTMewyLIe925L7fk6ChfjakZkwecIOf4bbvxd/YperIgraoxrjYqeRGiFSQEN1u0LAlbVS6xyhFSBKU69bpjP8ttfE4yTJrnGvcvXgzWk3OfvWL0T8RbvQmOjqMF67YTGXP2RKpk4ot7p2IvVxxO5zWKVs00Z9XBH1XflzBFv5k3oJLnb9dPOhwV2cQnQgUMQn7hMZcWIi9tj1xhFVzoJjufGns+oQ6xCsvbM5e00DmYgb2JmwctyjS+rd3lJQYn6dyb/N6dAQlUMEtBVJTD79D2Mz4TwZkcDkJNyBu9CMmjEOTEk0x/t8ipKd/v7swfoyX6VDasvLzFIcIzHds866MpQbK4V4ED+f", "X-Forefront-Antispam-Report": "CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:;\n IPV:NLI; SFV:NSPM; H:BY5PR12MB4179.namprd12.prod.outlook.com; PTR:; CAT:NONE;\n SFS:(13230040)(366016)(1800799024)(376014)(22082099003)(18002099003)(56012099003);\n DIR:OUT; SFP:1101;", "X-MS-Exchange-AntiSpam-MessageData-ChunkCount": "1", "X-MS-Exchange-AntiSpam-MessageData-0": "\n rKNPOJvSY/g2FGYvckGMRzXy3nAT03LUHbK7zqTelcDw9Tay5di8HsJPojunb59yrdj+HIcN9pb6qsbIoXRV2pbM20NP6yyS0CXumbGNsR7cCvriqAtUIbcR/GJIvSpLvhTgxVfBuWStQoxB6pce04ppeqxWfzrtRB27TjKFMaM3nOHtvwna5IQPzSbGoeaCZq4Y6Pbim9wITi2Ujn+vebbFEVW3VpCsfIaRmAzwyLUZr4RkCoJ5wGM3RNxZ2he1Fp0lgegNnpyfyMqS4+u+iSzWuZLBC3W/IGxzWoQv/djKbfWcm30fomjqxC3n7bo3AtyxbDsLhrv6LrrOJdR9STcTmV1k5wajh6mfKmqmeP2MNEAw7y5qYIhOdwvS/OlpkGRbtpQXZNXerQvZus3lN7kZkvAwBxz+Q7JyyZeCohg+o/vtSP/HSPzdY7bwpEDrKlhDFdQlvVSnR+/5uR+n8oOc24bXAWxSZn5i+Ke/yEZ7quZOszP8jYUh/fQj+JtFTRcEc5P9Q/9EWraHlIKJZoYvb0p1ulB88rTt25uWYC9FnYVHWnQ/+FM6lqO3OhwYvby0yC+HDn3i3BumbCizAedmAp0XXKm+GeAG6RFs//U/yb/W3EdYx7LduJ0TrbauchmkknHcz+c6Q9oi+cUY63lAqye3kmvlmYyztciXvkQVvT39VPRI87QVjXzyVijAhBzYjqQtnnh+DEjZSNGQEMX3XCynasg7w8pIAYV3kBSongzH6iaFyXFUQScYYZAhAYem+hwcJJ2ojQrTNzFaSftPi20grPP8SbW/w14B+nJdHKInZGpsvP6OBqLnHWtO17BRfFsvRCR9lV2e9s7jRwI9LFdglCNKs69TPje5bIJHrDEm7oS7jvQkQL6F7irbRUc1WZHpPwDVrVRwB4xDI340k74gBxYCkt17inPjorNCr6KFEE/HtuXitVlYX6+CJWBlPn03a640DufvUBjuA5thesWDyciOq/Z6lmeSo4uo08nk/mGvZ1Sa4qwW1q7EM00m17fv/n13O2EK6MBCxQ2YrU9QSG0NunT+Zuh/biqJ3sWzR2JFNPrOw4LEF9F9DvSyXRqyr6zsILN9t9a3j90Oht950J3CtgykKhDoRYuavH74XM5hXkdYiM/nroH6GVzVZBYUnO5LABH3DuGDdRtrIud2gLbxEaDOz6nn0P/zBsWKTiHb4HQ7rFIBiv4iUY7sNKObSruSDozWRau8g/dnDghDX5xtr6bvLM2S8nriMOEajsFRBg6YAGZUZkgH1BhivV4Esp/UKN2SWOhu6VVQ3amCYGoJ7ACcgBue7fD8oVsCn8SBnkdcLiib5jF4NGc5+YdyW3H4n3ssIj5gdxs7Z/xzTfB4rd5tIE5mUsaqavsQVSpfsVBSzO1bbWidXwOLyhg+u6jJb7lXWfkSICLf609fn/mkBidXnWNWpCESqV34CQd4NxDvHEq+s9ivpwhFP/kqbKvU9/E1xl+Cbq/zHkwMEnQPiBU3INVb0Wl+pCdXFyHSXXpS3ce2ZemaOqRoCMj1Fc4jo1K5PTOH4reps6j/tHU/trphJWYKLwle6AuuZvN4c+WR7+ufMwGb+VFGehrII9dTC8AOjdyWLvjCwYAAgHfNJYVcdFADQ+pO09jLeDTTn46+3N2gUkSeZxEyf8rtLM2UHtDU0dlWR/8RK4zapTmtUgQV1E3PELxi4pTzATziRvfjjihiBTopHPCuiPlJjvk5zDTzhN9Fmg==", "X-OriginatorOrg": "Nvidia.com", "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n b889e638-85a6-49e0-485a-08dead30e8f2", "X-MS-Exchange-CrossTenant-AuthSource": "BY5PR12MB4179.namprd12.prod.outlook.com", "X-MS-Exchange-CrossTenant-AuthAs": "Internal", "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "08 May 2026 18:37:51.2581 (UTC)", "X-MS-Exchange-CrossTenant-FromEntityHeader": "Hosted", "X-MS-Exchange-CrossTenant-Id": "43083d15-7273-40c1-b7db-39efd9ccc17a", "X-MS-Exchange-CrossTenant-MailboxType": "HOSTED", "X-MS-Exchange-CrossTenant-UserPrincipalName": "\n i63nodeRj54rYsPGA9Vvv1O1MysuFV7F28/j7mlsGAwa3QRHLiJzcgWurNMlzB1iyEh/IlmOSY1Tfb594Wh55Q==", "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "DM4PR12MB6205", "Received-SPF": "permerror client-ip=2a01:111:f403:c105::1;\n envelope-from=tdave@nvidia.com;\n helo=CH1PR05CU001.outbound.protection.outlook.com", "X-Spam_score_int": "-14", "X-Spam_score": "-1.5", "X-Spam_bar": "-", "X-Spam_report": "(-1.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.44,\n DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n FORGED_SPF_HELO=1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-0.001,\n SPF_NONE=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": "This phase performs PCI BAR allocation for buses without fixed BAR\nassignments. It respects existing allocations and does not disturb\nalready programmed BARs or bridge windows.\n\nIt computes remaining MMIO64 requirements, assigns BARs, and extends\nbridge prefetch windows if required.\n\nSigned-off-by: Tushar Dave <tdave@nvidia.com>\n---\n hw/pci/pci-resource.c | 355 +++++++++++++++++++++++++++++++++++++++++-\n 1 file changed, 354 insertions(+), 1 deletion(-)", "diff": "diff --git a/hw/pci/pci-resource.c b/hw/pci/pci-resource.c\nindex de98924aa6..e2d2adc7de 100644\n--- a/hw/pci/pci-resource.c\n+++ b/hw/pci/pci-resource.c\n@@ -371,6 +371,358 @@ static void finalize_bridge_window(PCIBus *bus, uint64_t min_addr, uint64_t max_\n }\n }\n \n+/* Returns true if this 64-bit pref BAR is already assigned */\n+static bool bar_is_assigned(PCIDevice *dev, int bar_idx, GHashTable *had_fixed)\n+{\n+ PCIIORegion *r = &dev->io_regions[bar_idx];\n+ uint32_t lo;\n+ uint32_t hi;\n+\n+ if (!is_64bit_pref_bar(r)) {\n+ return false;\n+ }\n+ if (dev->fixed_bar_addrs &&\n+ dev->fixed_bar_addrs[bar_idx] != PCI_BAR_UNMAPPED) {\n+ return true;\n+ }\n+ if (bar_idx >= PCI_ROM_SLOT - 1) {\n+ return false; /* 64-bit BAR uses two slots */\n+ }\n+ lo = pci_get_long(dev->config + PCI_BASE_ADDRESS_0 + bar_idx * 4);\n+ if (!(lo & PCI_BASE_ADDRESS_MEM_TYPE_64)) {\n+ return (lo & PCI_BASE_ADDRESS_MEM_MASK) != 0;\n+ }\n+ hi = pci_get_long(dev->config + PCI_BASE_ADDRESS_0 + bar_idx * 4 + 4);\n+ return (((uint64_t)hi << 32) | (lo & PCI_BASE_ADDRESS_MEM_MASK)) != 0;\n+}\n+\n+/* Return BAR address from config, or 0 if unassigned. */\n+static uint64_t get_bar_addr_from_config(PCIDevice *dev, int bar_idx)\n+{\n+ PCIIORegion *r = &dev->io_regions[bar_idx];\n+ uint32_t lo;\n+ uint32_t hi;\n+\n+ if (!r->size || bar_idx >= PCI_ROM_SLOT - 1) {\n+ return 0;\n+ }\n+ lo = pci_get_long(dev->config + PCI_BASE_ADDRESS_0 + bar_idx * 4);\n+ if (lo & PCI_BASE_ADDRESS_MEM_TYPE_64) {\n+ hi = pci_get_long(dev->config + PCI_BASE_ADDRESS_0 + bar_idx * 4 + 4);\n+ return ((uint64_t)hi << 32) | (lo & PCI_BASE_ADDRESS_MEM_MASK);\n+ }\n+ return lo & PCI_BASE_ADDRESS_MEM_MASK;\n+}\n+\n+/* Total size of unassigned 64-bit pref BARs in this bus and its subtree. */\n+static uint64_t size_entire_subtree(PCIBus *bus, GHashTable *had_fixed)\n+{\n+ uint64_t total = 0;\n+\n+ for (int devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {\n+ PCIDevice *d = bus->devices[devfn];\n+ if (!d) {\n+ continue;\n+ }\n+ for (int i = 0; i < PCI_ROM_SLOT; i++) {\n+ PCIIORegion *r = &d->io_regions[i];\n+ if (!is_64bit_pref_bar(r)) {\n+ continue;\n+ }\n+ if (bar_is_assigned(d, i, had_fixed)) {\n+ continue;\n+ }\n+ total += r->size;\n+ }\n+ if (IS_PCI_BRIDGE(d)) {\n+ total += size_entire_subtree(pci_bridge_get_sec_bus(PCI_BRIDGE(d)), had_fixed);\n+ }\n+ }\n+ return total;\n+}\n+\n+/* Highest end address of any assigned BAR or bridge window in this bus and subtree. */\n+static uint64_t find_highest_assigned_in_bus(PCIBus *bus)\n+{\n+ uint64_t highest = 0;\n+ uint64_t base;\n+ uint64_t limit;\n+ uint64_t addr;\n+\n+ for (int devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {\n+ PCIDevice *d = bus->devices[devfn];\n+ if (!d) {\n+ continue;\n+ }\n+ if (IS_PCI_BRIDGE(d)) {\n+ PCIBus *sec = pci_bridge_get_sec_bus(PCI_BRIDGE(d));\n+ PCIDevice *bridge_dev = pci_bridge_get_device(sec);\n+ if (bridge_dev) {\n+ base = pci_bridge_get_base(bridge_dev, PCI_BASE_ADDRESS_MEM_PREFETCH);\n+ limit = pci_bridge_get_limit(bridge_dev, PCI_BASE_ADDRESS_MEM_PREFETCH);\n+ if (limit > base) {\n+ highest = MAX(highest, limit);\n+ }\n+ highest = MAX(highest, find_highest_assigned_in_bus(sec));\n+ }\n+ continue;\n+ }\n+ for (int i = 0; i < PCI_ROM_SLOT; i++) {\n+ PCIIORegion *r = &d->io_regions[i];\n+ if (!is_64bit_pref_bar(r)) {\n+ continue;\n+ }\n+ addr = 0;\n+ if (d->fixed_bar_addrs &&\n+ d->fixed_bar_addrs[i] != PCI_BAR_UNMAPPED) {\n+ addr = d->fixed_bar_addrs[i];\n+ } else {\n+ addr = get_bar_addr_from_config(d, i);\n+ }\n+ if (addr != 0 && r->size) {\n+ highest = MAX(highest, addr + r->size - 1);\n+ }\n+ }\n+ }\n+ return highest;\n+}\n+\n+/* Next free address in root MMIO64. */\n+static uint64_t next_free_from_root(hwaddr mmio64_base, hwaddr mmio64_size)\n+{\n+ uint64_t mmio_start = mmio64_base;\n+ uint64_t mmio_end = mmio64_base + mmio64_size - 1;\n+ uint64_t highest;\n+\n+ highest = mmio_start - 1;\n+ if (fixed_claim_regions) {\n+ for (guint i = 0; i < fixed_claim_regions->len; i++) {\n+ FixedClaim *c = &g_array_index(fixed_claim_regions, FixedClaim, i);\n+ if (c->end >= mmio_start && c->start <= mmio_end) {\n+ highest = MAX(highest, c->end);\n+ }\n+ }\n+ }\n+ return ROUND_UP(highest + 1, 0x1000); /* 4K align for new window */\n+}\n+\n+static bool\n+pci_bus_phase3_ensure_parent_prefetch_window(PCIBus *bus, PciProgramCtx *pctx,\n+ PCIDevice *parent_bridge, uint64_t mmio_end)\n+{\n+ PCIBus *parent_bus;\n+ PCIDevice *grandparent;\n+ uint64_t parent_win_base, parent_win_limit, next_in_subtree;\n+ uint64_t required, window_base, window_limit;\n+ bool window_not_programmed;\n+ bool parent_in_mmio64;\n+\n+ window_base = pci_bridge_get_base(parent_bridge, PCI_BASE_ADDRESS_MEM_PREFETCH);\n+ window_limit = pci_bridge_get_limit(parent_bridge, PCI_BASE_ADDRESS_MEM_PREFETCH);\n+ window_not_programmed = (window_base >= window_limit) ||\n+ (window_base < pctx->mmio64_base) || (window_limit > mmio_end);\n+ if (!window_not_programmed) {\n+ return true;\n+ }\n+\n+ required = size_entire_subtree(bus, pctx->had_fixed);\n+ if (required == 0) {\n+ return false;\n+ }\n+ required = ROUND_UP(required, 0x1000);\n+\n+ parent_bus = pci_get_bus(parent_bridge);\n+ grandparent = parent_bus ? pci_bridge_get_device(parent_bus) : NULL;\n+ if (!grandparent) {\n+ window_base = next_free_from_root(pctx->mmio64_base, pctx->mmio64_size);\n+ window_limit = window_base + required - 1;\n+ if (window_limit > mmio_end) {\n+ error_report(\"bus [%02x] out of root MMIO64 space\", pci_bus_num(bus));\n+ exit(1);\n+ }\n+ } else {\n+ parent_win_base = pci_bridge_get_base(grandparent, PCI_BASE_ADDRESS_MEM_PREFETCH);\n+ parent_win_limit = pci_bridge_get_limit(grandparent, PCI_BASE_ADDRESS_MEM_PREFETCH);\n+ parent_in_mmio64 = (parent_win_limit > parent_win_base) &&\n+ (parent_win_base >= pctx->mmio64_base) && (parent_win_limit <= mmio_end);\n+ if (!parent_in_mmio64) {\n+ window_base = next_free_from_root(pctx->mmio64_base, pctx->mmio64_size);\n+ window_limit = window_base + required - 1;\n+ if (window_limit > mmio_end) {\n+ error_report(\"bus [%02x] out of root MMIO64 space\", pci_bus_num(bus));\n+ exit(1);\n+ }\n+ } else {\n+ next_in_subtree = ROUND_UP(\n+ find_highest_assigned_in_bus(parent_bus) + 1, 0x1000);\n+ window_base = MAX(parent_win_base, next_in_subtree);\n+ window_limit = window_base + required - 1;\n+ if (window_limit > parent_win_limit) {\n+ error_report(\"bus [%02x] no room in parent bridge window\", pci_bus_num(bus));\n+ exit(1);\n+ }\n+ }\n+ }\n+ finalize_bridge_window(bus, window_base, window_limit);\n+ return true;\n+}\n+\n+static GArray *pci_bus_phase3_collect_unassigned_bars(PCIBus *bus, PciProgramCtx *pctx,\n+ uint64_t *out_total_size)\n+{\n+ PCIDevice *d;\n+ PCIIORegion *r;\n+ GArray *bars;\n+ uint64_t required;\n+ int devfn, i;\n+\n+ required = 0;\n+ bars = g_array_new(false, false, sizeof(BarEntry));\n+ for (devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {\n+ d = bus->devices[devfn];\n+ if (!d) {\n+ continue;\n+ }\n+ for (i = 0; i < PCI_ROM_SLOT; i++) {\n+ r = &d->io_regions[i];\n+ if (!is_64bit_pref_bar(r) || bar_is_assigned(d, i, pctx->had_fixed)) {\n+ continue;\n+ }\n+ required += r->size;\n+ g_array_append_val(\n+ bars, ((BarEntry){ .dev = d, .bar_idx = i, .size = r->size }));\n+ }\n+ }\n+ *out_total_size = required;\n+ return bars;\n+}\n+\n+static void\n+pci_bus_phase3_extend_window_for_bars(PCIBus *bus, PciProgramCtx *pctx,\n+ PCIDevice *parent_bridge, uint64_t mmio_end,\n+ uint64_t current, uint64_t required,\n+ uint64_t window_base, uint64_t *window_limit,\n+ GArray *bars_this_bus)\n+{\n+ uint64_t parent_limit, gp_base, gp_limit, new_limit;\n+ PCIBus *parent_bus;\n+ PCIDevice *grandparent;\n+\n+ if (current + required <= *window_limit) {\n+ return;\n+ }\n+\n+ parent_bus = pci_get_bus(parent_bridge);\n+ grandparent = parent_bus ? pci_bridge_get_device(parent_bus) : NULL;\n+ parent_limit = mmio_end;\n+ if (grandparent) {\n+ gp_base = pci_bridge_get_base(grandparent, PCI_BASE_ADDRESS_MEM_PREFETCH);\n+ gp_limit = pci_bridge_get_limit(grandparent, PCI_BASE_ADDRESS_MEM_PREFETCH);\n+ if (gp_limit > gp_base && gp_base >= pctx->mmio64_base) {\n+ parent_limit = gp_limit;\n+ }\n+ }\n+ new_limit = current + required - 1;\n+ if (new_limit > parent_limit) {\n+ error_report(\"bus [%02x] out of MMIO space (required 0x%\" PRIx64 \")\", pci_bus_num(bus),\n+ required);\n+ g_array_free(bars_this_bus, true);\n+ exit(1);\n+ }\n+ if (new_limit > *window_limit) {\n+ pci_update_prefetch_window(bus, window_base, new_limit);\n+ fixed_claim_regions_add(*window_limit + 1, new_limit, parent_bridge, -1);\n+ *window_limit = new_limit;\n+ }\n+}\n+\n+static void\n+pci_bus_phase3_program_bars_and_update_bridge(PCIBus *bus, PCIDevice *parent_bridge,\n+ uint64_t window_base, uint64_t window_limit,\n+ uint64_t start_addr, GArray *bars)\n+{\n+ guint b;\n+ BarEntry *be;\n+ PCIIORegion *r;\n+ uint64_t addr, bar_end, high;\n+ PhysBAR pbars_array[PCI_ROM_SLOT];\n+\n+ g_array_sort(bars, compare_bar_size_desc);\n+ addr = start_addr;\n+ for (b = 0; b < bars->len; b++) {\n+ be = &g_array_index(bars, BarEntry, b);\n+ r = &be->dev->io_regions[be->bar_idx];\n+ addr = ROUND_UP(addr, r->size);\n+ bar_end = addr + r->size - 1;\n+ memset(pbars_array, 0, sizeof(pbars_array));\n+ pbars_array[be->bar_idx].addr = addr;\n+ pbars_array[be->bar_idx].end = bar_end;\n+ pbars_array[be->bar_idx].flags = IORESOURCE_PREFETCH;\n+ pci_program_prefetch_bars(be->dev, pbars_array);\n+ addr = bar_end + 1;\n+ }\n+ high = find_highest_assigned_in_bus(bus);\n+ if (high > window_limit) {\n+ pci_update_prefetch_window(bus, window_base, high);\n+ fixed_claim_regions_add(window_limit + 1, high, parent_bridge, -1);\n+ }\n+ g_array_free(bars, true);\n+}\n+\n+/* Allocate and program 64-bit pref BARs for a bus with no fixed-BAR devices. */\n+static void pci_bus_phase3_allocate_bars(PCIBus *bus, PciProgramCtx *pctx)\n+{\n+ uint64_t mmio_end, window_base, window_limit, current, required;\n+ PCIDevice *parent_bridge;\n+ GArray *bars;\n+\n+ parent_bridge = pci_bridge_get_device(bus);\n+ if (!parent_bridge) {\n+ return; /* Root bus has no bridge; skip */\n+ }\n+\n+ mmio_end = pctx->mmio64_base + pctx->mmio64_size - 1;\n+ if (!pci_bus_phase3_ensure_parent_prefetch_window(bus, pctx, parent_bridge, mmio_end)) {\n+ return;\n+ }\n+ window_base = pci_bridge_get_base(parent_bridge, PCI_BASE_ADDRESS_MEM_PREFETCH);\n+ window_limit = pci_bridge_get_limit(parent_bridge, PCI_BASE_ADDRESS_MEM_PREFETCH);\n+ current = ROUND_UP(find_highest_assigned_in_bus(bus) + 1, 0x1000);\n+ if (current < window_base) {\n+ current = window_base;\n+ }\n+\n+ bars = pci_bus_phase3_collect_unassigned_bars(bus, pctx, &required);\n+ if (bars->len == 0) {\n+ g_array_free(bars, true);\n+ return;\n+ }\n+ pci_bus_phase3_extend_window_for_bars(bus, pctx, parent_bridge, mmio_end, current,\n+ required, window_base, &window_limit, bars);\n+ pci_bus_phase3_program_bars_and_update_bridge(\n+ bus, parent_bridge, window_base, window_limit, current, bars);\n+}\n+\n+/* Run once per bus; act only when the bus has no fixed-BAR devices. */\n+static void pci_bus_phase3_allocate_no_fixed_bars(PCIBus *bus, void *opaque)\n+{\n+ PciProgramCtx *pctx = (PciProgramCtx *)opaque;\n+ bool bus_has_fixed = false;\n+\n+ for (int devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {\n+ PCIDevice *d = bus->devices[devfn];\n+ if (d && g_hash_table_contains(pctx->had_fixed, d)) {\n+ bus_has_fixed = true;\n+ break;\n+ }\n+ }\n+\n+ if (bus_has_fixed) {\n+ return;\n+ }\n+ pci_bus_phase3_allocate_bars(bus, pctx);\n+}\n+\n static bool pci_bus_phase2_fill_bar_lists(PCIBus *bus, PciProgramCtx *pctx,\n GArray *fixed_bars, GArray *remaining_bars)\n {\n@@ -649,7 +1001,8 @@ void pci_fixed_bar_allocator(PCIBus *root, const PciFixedBarMmioParams *mmio)\n /* Phase 2: pack remaining 64-bit prefetchable BARs and size parent bridge window */\n pci_for_each_bus(bus, pci_bus_phase2_pack_remaining_bars, &pctx);\n \n- /* Phase 3: buses with no fixed-BAR devices; final bridge pass: follow-up */\n+ /* Phase 3: allocate BARs for buses that have no fixed-BAR devices */\n+ pci_for_each_bus(bus, pci_bus_phase3_allocate_no_fixed_bars, &pctx);\n \n /* Cleanup */\n g_hash_table_destroy(pctx.had_fixed);\n", "prefixes": [ "RFC", "5/8" ] }