From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM11-CO1-obe.outbound.protection.outlook.com (NAM11-CO1-obe.outbound.protection.outlook.com [40.107.220.110]) by mx.groups.io with SMTP id smtpd.web08.4052.1607505866843263792 for ; Wed, 09 Dec 2020 01:24:27 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@os.amperecomputing.com header.s=selector2 header.b=VCGS8tpl; spf=pass (domain: os.amperecomputing.com, ip: 40.107.220.110, mailfrom: nhi@os.amperecomputing.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=COb4PgF0tJtpw7FAyG5GpbIaJOGwBe0BgbV2JjxHaU4TW9iPpk+V1iAZ96dCWXI8OxMXcoKCB/zVSp6urFCW2sKbbOBdTbD6oOMGLqOVy+FgLE9newycoyHTEyZWSrZo4PHcT7ZhZQ4Ozd2CZKMHhzN9zYCsXOvmfgNT17eCUWOeXT+JYqgFyC+c5EqNMc8hMvBb/qGZlC/U1TZhQbe4Oedz8jdXT6qnDRHQwDWDrG3mpdF7JaUl/n/0d8WLOwqDECuD9qKK8JHzw7lWyyG89unyJ4VstknKsRzGdBvQOuIBS5e3j8SuNKLjJW2SKoSr5uNkzdcguAs4t+PWJvRTfQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=MJ7eG/g1Paq7WIxV6ZacWXnU1hTRVE4Chmth4m2lqCk=; b=NkAZQXHEQF0J6pHwNmbKjaB84XprxLEEeeY00ic8aQmNlwvYfYJENRy48qcAMHtcO0JKNqccUcanH2c6TO0T9SQOSithK45hnuQ3qI7nMhT0tvfkfP5bUuUs8Gi0a1eu3eGWorfuB9J3oRRowaM7V/+KFOdXgH4HEBBmok+OgjIP2CP0pOJFVcQQ/xf5ANDkgMuVN2hAQg10MvuTWU4RkTFdF+GNQs5ZttyuRw9SNNsygbSIH1XTYhz6lmJ6roXVCgy45AFryw2qN7yViTbQS/RRj118AA/ogfAk1ZRAMx4oPfbUZ8kXFjo45Rm0whbZmIzn/YkiWU8VOu1cuQ4e2w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=os.amperecomputing.com; dmarc=pass action=none header.from=os.amperecomputing.com; dkim=pass header.d=os.amperecomputing.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=os.amperecomputing.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=MJ7eG/g1Paq7WIxV6ZacWXnU1hTRVE4Chmth4m2lqCk=; b=VCGS8tplAaF5AfAc+48QjzuKYKJhESXS7TKmAnv+dCjnDT1GL24ZNYX3IX+PC0cAVuJo67eLjF5C5cTfgffx9qGFPcGOJdKPmKbsjtoXMlKwizRHfqB3scQSrldxVG+yI/92IyI5j1LhhyGoIfVXwlT+wHH+MkbK7uFtHUJYKs0= Authentication-Results: edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=none action=none header.from=os.amperecomputing.com; Received: from DM6PR01MB5849.prod.exchangelabs.com (2603:10b6:5:205::20) by DM6PR01MB5609.prod.exchangelabs.com (2603:10b6:5:157::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3632.21; Wed, 9 Dec 2020 09:24:24 +0000 Received: from DM6PR01MB5849.prod.exchangelabs.com ([fe80::c814:9a08:5c2e:4076]) by DM6PR01MB5849.prod.exchangelabs.com ([fe80::c814:9a08:5c2e:4076%5]) with mapi id 15.20.3632.023; Wed, 9 Dec 2020 09:24:24 +0000 From: "Nhi Pham" To: devel@edk2.groups.io Cc: Nhi Pham Subject: [edk2-platforms][PATCH 09/34] JadePkg: Install some ACPI tables at runtime Date: Wed, 9 Dec 2020 16:25:06 +0700 Message-Id: <20201209092531.30867-10-nhi@os.amperecomputing.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201209092531.30867-1-nhi@os.amperecomputing.com> References: <20201209092531.30867-1-nhi@os.amperecomputing.com> X-Originating-IP: [118.69.219.201] X-ClientProxiedBy: HK0PR01CA0054.apcprd01.prod.exchangelabs.com (2603:1096:203:a6::18) To DM6PR01MB5849.prod.exchangelabs.com (2603:10b6:5:205::20) Return-Path: nhi@os.amperecomputing.com MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from sw004.amperecomputing.com (118.69.219.201) by HK0PR01CA0054.apcprd01.prod.exchangelabs.com (2603:1096:203:a6::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3654.12 via Frontend Transport; Wed, 9 Dec 2020 09:24:23 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 1638da46-cf3f-4c49-e3e9-08d89c243822 X-MS-TrafficTypeDiagnostic: DM6PR01MB5609: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:5516; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: qwO9NrnwqJX+cJCx8jpkg1yghzFjSlFvBV3SYhF3ctMt7gJdRJgBPjkv2sPj5hSxOwGp6fHIC70zKVrHg7Kr1WiPoDIMBEEtPcU6OKvSSg46x0qxHWJAatTo0dlcsBPt9X50s2vZRiSopg1mZj4y06Rvge2We19CWAQjgnoou58RRPSa5ioGvmcVkTP61UdnjgZh6YvLnNUUDX9nUC8L6fVQupjmGLt6geJXxZxqMiDtCQxPqPMZDRp3PHydKFHvjQmiatC6gYBwWSJZpfktpmz347D0gkT+peRYml6fhdQnSscH2Atx1KlA2E+sNxO9DlHJXzdOhl1dYw7zoxMoMgahWjNFqNvCQvK6pQuViByGCZp9GtO+ReD52TqzFdXg54wl2L09hQXVQnlJqMNbPA== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DM6PR01MB5849.prod.exchangelabs.com;PTR:;CAT:NONE;SFS:(4636009)(376002)(136003)(346002)(366004)(5660300002)(956004)(508600001)(52116002)(30864003)(66946007)(6916009)(2616005)(1076003)(19627235002)(86362001)(6512007)(66476007)(26005)(8936002)(16526019)(107886003)(6666004)(186003)(6486002)(8676002)(6506007)(83380400001)(2906002)(34490700003)(66556008)(4326008)(559001)(579004)(44824005);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData: =?us-ascii?Q?QaPtPt26UZeAdP42S1SZViyYKOqs5FUEcE1tmz2/Gm7cCaT8+6NaFI5T1hnv?= =?us-ascii?Q?2kqs+xZ/pGaDlLTEHJdJumw2SRILdqgOkw4rpyEt07um3aVPx+B9fDA0mXjS?= =?us-ascii?Q?wGfLT8FfJisrOwpzaI0iEFb9NZmnYV/mHxRuh6uyCGca13h8YYapzjp1xnRY?= =?us-ascii?Q?Q8fOKpJTn6IyHfdiSaEioNBSaCpPAoBafXzrO+0GlLHHWEYXmxyc0EOGChV/?= =?us-ascii?Q?4nnZkgF3YKWVlDYsH2WSr28P09Fg5MV0dPw84F+7BBTIH+/etqYol4BGJBV6?= =?us-ascii?Q?iq7h15NCJ832nB0tCeqiDE4V8jfFSnkR7xRfWL0eW1G3L4QJKJTCfydb/hLN?= =?us-ascii?Q?zluJYDA3ukT/cBtBF6Wod9UPD9TrsQ8Bdwr2jcFXVkddQ40OJJt5QnUAKfR/?= =?us-ascii?Q?V5EPkIFXIT3s9RyqSRfuIVeXXoPaff6lLvyMUbgTHfJZwaeTvPVhiAjeuGKm?= =?us-ascii?Q?Qt5iclWED6HUAoh2Jy2nUb3yW4BVjx1fAMzAnws+GlqkNwd+b1DI9ptVNBAI?= =?us-ascii?Q?hMEUyAW+i7d2bNiW8bQRbAuWWZPmPPGJE3wW+pOhAvRVL6EXN544dPS8dz1F?= =?us-ascii?Q?FSFXh2vVhkIuwL4JygVuyoduPC5+a+Y+1QWwz5pi1rKYrl+19mc8zh3KRi6T?= =?us-ascii?Q?1g+Jn0w8PJ6IrlgDsIthrOG1kUXlqgw2KW/f/zq6JgxhkwsX9vvil2/7uQgk?= =?us-ascii?Q?2vEf82de0jx9YwfDl4lNh7DykOuJLRgZemvkog/ocvIZAf7lFr5EzDkhCVjL?= =?us-ascii?Q?BQ2IIN3A5q4KpQYBTrsjEtx5gnzCLjBxadGYbjhqcFlYu/nrPVEnkd9F2Lu3?= =?us-ascii?Q?GIjie80ZWRLJ6IjsrsZoB+znK926PoD8tycSPwE/0wLx4vsMapQS/zqpCQSF?= =?us-ascii?Q?oyzu9qdBaikLVC3Gp1N2Z04YYjTaWT9bd9d+MqPFZarkCEo3Pubea08dk2lH?= =?us-ascii?Q?akpv0CUq0B4Ph0YE4EpVVM5boUHbUO4+Gp2LWRMJoFcKBPy2M9tKH9OWWzPn?= =?us-ascii?Q?d+Ej?= X-OriginatorOrg: os.amperecomputing.com X-MS-Exchange-CrossTenant-AuthSource: DM6PR01MB5849.prod.exchangelabs.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Dec 2020 09:24:24.6512 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3bc2b170-fd94-476d-b0ce-4229bdc904a7 X-MS-Exchange-CrossTenant-Network-Message-Id: 1638da46-cf3f-4c49-e3e9-08d89c243822 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 8bj3VRctzEMmhd2mxMo6NuI8fPM7oLi/WWPfZvUJzWjZTbRhFpDLMdAipdMqpBxjKtvYtHBe3HNW0a9g5lsRHojm1taNHuRdsMidKhXHN7Q= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR01MB5609 Content-Type: text/plain This supports to create MADT, PPTT, PCCT, SLIT, SRAT, NFIT tables at runtime. It also updates DSDT table based on the system information. Signed-off-by: Nhi Pham --- Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf | 22 ++ Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatform.h | 48 +++ Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiDsdt.c | 221 ++++++++++++ Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiMADT.c | 372 ++++++++++++++++++++ Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiNfit.c | 268 ++++++++++++++ Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPCCT.c | 264 ++++++++++++++ Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPPTT.c | 338 ++++++++++++++++++ Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c | 84 +++++ Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSLIT.c | 85 +++++ Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSRAT.c | 268 ++++++++++++++ 10 files changed, 1970 insertions(+) diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf index 1ec8602aede5..d9caca9438de 100644 --- a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf +++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf @@ -15,6 +15,13 @@ [Defines] ENTRY_POINT = AcpiPlatformDxeInitialize [Sources.common] + AcpiDsdt.c + AcpiMADT.c + AcpiNfit.c + AcpiPCCT.c + AcpiPPTT.c + AcpiSLIT.c + AcpiSRAT.c AcpiPlatform.h AcpiPlatformDxe.c @@ -35,10 +42,25 @@ [LibraryClasses] BaseLib UefiLib AcpiLib + AcpiPccLib + AcpiHelperLib + AmpereCpuLib + +[Pcd] + gArmPlatformTokenSpaceGuid.PcdCoreCount + gArmPlatformTokenSpaceGuid.PcdClusterCount + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision + gAmpereTokenSpaceGuid.PcdPmproDbBaseReg + gAmpereTokenSpaceGuid.PcdSmproDbBaseReg [Guids] gArmMpCoreInfoGuid gEfiAcpiTableGuid + gEfiEventReadyToBootGuid [Protocols] gEfiAcpiTableProtocolGuid ## ALWAYS_CONSUMED diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatform.h b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatform.h index 60b2ed22d05b..ba5d704a3fc0 100644 --- a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatform.h +++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatform.h @@ -22,5 +22,53 @@ #include #include #include +#include +#include + +#include +#include +#include +#include +#include + +EFI_STATUS +AcpiPatchDsdtTable ( + VOID + ); + +EFI_STATUS +AcpiInstallMadtTable ( + VOID + ); + +EFI_STATUS +AcpiInstallNfitTable ( + VOID + ); + +EFI_STATUS +AcpiPcctInit ( + VOID + ); + +EFI_STATUS +AcpiInstallPcctTable ( + VOID + ); + +EFI_STATUS +AcpiInstallPpttTable ( + VOID + ); + +EFI_STATUS +AcpiInstallSlitTable ( + VOID + ); + +EFI_STATUS +AcpiInstallSratTable ( + VOID + ); #endif /* _ACPI_PLATFORM_H_ */ diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiDsdt.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiDsdt.c new file mode 100755 index 000000000000..7d4501311a9f --- /dev/null +++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiDsdt.c @@ -0,0 +1,221 @@ +/** @file + + Copyright (c) 2020, Ampere Computing LLC. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "AcpiPlatform.h" + +#define SUBNUMA_MODE_MONOLITHIC 0 +#define SUBNUMA_MODE_HEMISPHERE 1 +#define SUBNUMA_MODE_QUADRANT 2 + +STATIC VOID +AcpiPatchCmn600 (VOID) +{ + CHAR8 NodePath[MAX_ACPI_NODE_PATH]; + UINTN Index; + + for (Index = 0; Index < GetNumberSupportedSockets (); Index++) { + AsciiSPrint (NodePath, sizeof (NodePath), "\\_SB.CMN%1X._STA", Index); + if (GetNumberActiveCPMsPerSocket (Index)) { + AcpiDSDTSetNodeStatusValue (NodePath, 0xf); + } else { + AcpiDSDTSetNodeStatusValue (NodePath, 0x0); + } + } +} + +STATIC VOID +AcpiPatchDmc620 (VOID) +{ + CHAR8 NodePath[MAX_ACPI_NODE_PATH]; + UINTN Index, Index1; + EFI_GUID PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2; + PlatformInfoHob_V2 *PlatformHob; + UINT32 McuMask; + VOID *Hob; + + Hob = GetFirstGuidHob (&PlatformHobGuid); + if (Hob == NULL) { + return; + } + + PlatformHob = (PlatformInfoHob_V2 *) GET_GUID_HOB_DATA (Hob); + + for (Index = 0; Index < GetNumberSupportedSockets (); Index++) { + McuMask = PlatformHob->DramInfo.McuMask[Index]; + for (Index1 = 0; Index1 < sizeof (McuMask) * 8; Index1++) { + AsciiSPrint (NodePath, sizeof (NodePath), "\\_SB.MC%1X%1X._STA", Index, Index1); + if (McuMask & (0x1 << Index1)) { + AcpiDSDTSetNodeStatusValue (NodePath, 0xf); + } else { + AcpiDSDTSetNodeStatusValue (NodePath, 0x0); + } + } + } +} + +STATIC VOID +AcpiPatchNvdimm (VOID) +{ + CHAR8 NodePath[MAX_ACPI_NODE_PATH]; + UINTN NvdRegionNum, Count; + EFI_GUID PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2; + PlatformInfoHob_V2 *PlatformHob; + VOID *Hob; + + Hob = GetFirstGuidHob (&PlatformHobGuid); + if (Hob == NULL) { + return; + } + + PlatformHob = (PlatformInfoHob_V2 *) GET_GUID_HOB_DATA (Hob); + + NvdRegionNum = 0; + for (Count = 0; Count < PlatformHob->DramInfo.NumRegion; Count++) { + if (PlatformHob->DramInfo.NvdRegion[Count]) { + NvdRegionNum += 1; + } + } + + if (NvdRegionNum == PLATFORM_MAX_NUM_NVDIMM_DEVICE) { + return; + } + + /* Disable NVDIMM Root Device */ + if (NvdRegionNum == 0) { + AsciiSPrint (NodePath, sizeof (NodePath), "\\_SB.NVDR._STA"); + AcpiDSDTSetNodeStatusValue (NodePath, 0x0); + } + + /* Disable NVDIMM Device which is not available */ + Count = NvdRegionNum + 1; + while (Count <= PLATFORM_MAX_NUM_NVDIMM_DEVICE) { + AsciiSPrint (NodePath, sizeof (NodePath), "\\_SB.NVDR.NVD%1X._STA", Count); + AcpiDSDTSetNodeStatusValue (NodePath, 0x0); + Count++; + } +} + +STATIC VOID +AcpiPatchHwmon (VOID) +{ + CHAR8 NodePath[MAX_ACPI_NODE_PATH]; + UINTN Index; + + // PCC Hardware Monitor Devices + for (Index = 0; Index < GetNumberSupportedSockets (); Index++) { + AsciiSPrint (NodePath, sizeof (NodePath), "\\_SB.HM0%1X._STA", Index); + if (GetNumberActiveCPMsPerSocket (Index)) { + AcpiDSDTSetNodeStatusValue (NodePath, 0xf); + } else { + AcpiDSDTSetNodeStatusValue (NodePath, 0x0); + } + } + + // Ampere Altra SoC Hardware Monitor Devices + for (Index = 0; Index < GetNumberSupportedSockets (); Index++) { + AsciiSPrint (NodePath, sizeof (NodePath), "\\_SB.HM0%1X._STA", Index + 2); + if (GetNumberActiveCPMsPerSocket (Index)) { + AcpiDSDTSetNodeStatusValue (NodePath, 0xf); + } else { + AcpiDSDTSetNodeStatusValue (NodePath, 0x0); + } + } +} + +STATIC VOID +AcpiPatchDsu (VOID) +{ + CHAR8 NodePath[MAX_ACPI_NODE_PATH]; + UINTN Index; + + for (Index = 0; Index < PLATFORM_CPU_MAX_NUM_CORES; Index += PLATFORM_CPU_NUM_CORES_PER_CPM) { + AsciiSPrint (NodePath, sizeof(NodePath), "\\_SB.DU%2X._STA", Index / PLATFORM_CPU_NUM_CORES_PER_CPM); + if (IsCpuEnabled (Index)) { + AcpiDSDTSetNodeStatusValue (NodePath, 0xf); + } else { + AcpiDSDTSetNodeStatusValue (NodePath, 0x0); + } + } +} + +STATIC UINT8 +PcieGetSubNumaMode ( + VOID + ) +{ + EFI_GUID PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2; + PlatformInfoHob_V2 *PlatformHob; + VOID *Hob; + + /* Get the Platform HOB */ + Hob = GetFirstGuidHob (&PlatformHobGuid); + if (Hob == NULL) { + return SUBNUMA_MODE_MONOLITHIC; + } + PlatformHob = (PlatformInfoHob_V2 *) GET_GUID_HOB_DATA (Hob); + + return PlatformHob->SubNumaMode[0]; +} + +VOID +AcpiPatchPcieNuma ( + VOID + ) +{ + CHAR8 NodePath[MAX_ACPI_NODE_PATH]; + UINTN Index; + UINTN NumaIdx; + UINTN NumPciePort; + UINTN NumaAssignment[3][16] = { + { 0, 0, 0, 0, 0, 0, 0, 0, // Monolitic Node 0 (S0) + 1, 1, 1, 1, 1, 1, 1, 1 }, // Monolitic Node 1 (S1) + { 0, 1, 0, 1, 0, 0, 1, 1, // Hemisphere Node 0, 1 (S0) + 2, 3, 2, 3, 2, 2, 3, 3 }, // Hemisphere Node 2, 3 (S1) + { 0, 2, 1, 3, 1, 1, 3, 3, // Quadrant Node 0, 1, 2, 3 (S0) + 4, 6, 5, 7, 5, 5, 7, 7 }, // Quadrant Node 4, 5, 6, 7 (S1) + }; + + switch (PcieGetSubNumaMode ()) { + case SUBNUMA_MODE_MONOLITHIC: + NumaIdx = 0; + break; + case SUBNUMA_MODE_HEMISPHERE: + NumaIdx = 1; + break; + case SUBNUMA_MODE_QUADRANT: + NumaIdx = 2; + break; + default: + NumaIdx = 0; + break; + } + + if (GetNumberActiveSockets () > 1) { + NumPciePort = 16; // 16 ports total (8 per socket) + } else { + NumPciePort = 8; // 8 ports total + } + + for (Index = 0; Index < NumPciePort; Index++) { + AsciiSPrint (NodePath, sizeof (NodePath), "\\_SB.PCI%X._PXM", Index); + AcpiDSDTSetNodeStatusValue (NodePath, NumaAssignment[NumaIdx][Index]); + } +} + +EFI_STATUS +AcpiPatchDsdtTable (VOID) +{ + AcpiPatchCmn600 (); + AcpiPatchDmc620 (); + AcpiPatchDsu (); + AcpiPatchHwmon (); + AcpiPatchNvdimm (); + AcpiPatchPcieNuma (); + + return EFI_SUCCESS; +} diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiMADT.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiMADT.c new file mode 100755 index 000000000000..fc34801fa340 --- /dev/null +++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiMADT.c @@ -0,0 +1,372 @@ +/** @file + + Copyright (c) 2020, Ampere Computing LLC. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "AcpiPlatform.h" + +EFI_ACPI_6_3_GIC_ITS_STRUCTURE GicItsTemplate = { + EFI_ACPI_6_3_GIC_ITS, + sizeof (EFI_ACPI_6_3_GIC_ITS_STRUCTURE), + EFI_ACPI_RESERVED_WORD, + 0, /* GicItsId */ + 0, /* PhysicalBaseAddress */ + 0, /* Reserved2 */ +}; + +EFI_ACPI_6_3_GICR_STRUCTURE GicRTemplate = { + EFI_ACPI_6_3_GICR, + sizeof (EFI_ACPI_6_3_GICR_STRUCTURE), + EFI_ACPI_RESERVED_WORD, + GICR_MASTER_BASE_REG, /* DiscoveryRangeBaseAddress */ + 0x1000000, /* DiscoveryRangeLength */ +}; + +EFI_ACPI_6_3_GIC_DISTRIBUTOR_STRUCTURE GicDTemplate = { + EFI_ACPI_6_3_GICD, + sizeof (EFI_ACPI_6_3_GIC_DISTRIBUTOR_STRUCTURE), + EFI_ACPI_RESERVED_WORD, + 0, /* GicDistHwId */ + GICD_BASE_REG, /* GicDistBase */ + 0, /* GicDistVector */ + 0x3, /* GicVersion */ + {EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE} +}; + +EFI_ACPI_6_3_GIC_STRUCTURE GiccTemplate = { + EFI_ACPI_6_3_GIC, + sizeof (EFI_ACPI_6_3_GIC_STRUCTURE), + EFI_ACPI_RESERVED_WORD, + 0, /* GicId */ + 0, /* AcpiCpuUid */ + 0, /* Flags */ + 0, + 23, /* PmuIrq */ + 0, + 0, + 0, + 0, + 25, /* GsivId */ + 0, /* GicRBase */ + 0, /* Mpidr */ + 0, /* ProcessorPowerEfficiencyClass */ + 0, /* Reserved2 */ + 21, /* SPE irq */ +}; + +EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER MADTTableHeaderTemplate = { + __ACPI_HEADER ( + EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE, + 0, /* need fill in */ + EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION + ), +}; + +UINT32 Ac01CoreOrderMonolithic[PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_NUM_CORES_PER_CPM] = { + 36, 52, 40, 56, 32, 48, 44, 60, + 20, 68, 24, 72, 16, 64, 28, 76, + 4, 8, 0, 12, 38, 54, 42, 58, + 34, 50, 46, 62, 22, 70, 26, 74, + 18, 66, 30, 78, 6, 10, 2, 14, + 37, 53, 41, 57, 33, 49, 45, 61, + 21, 69, 25, 73, 17, 65, 29, 77, + 5, 9, 1, 13, 39, 55, 43, 59, + 35, 51, 47, 63, 23, 71, 27, 75, + 19, 67, 31, 79, 7, 11, 3, 15, +}; + +UINT32 Ac01CoreOrderHemisphere[PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_NUM_CORES_PER_CPM] = { + 32, 48, 16, 64, 36, 52, 0, 20, + 68, 4, 34, 50, 18, 66, 38, 54, + 2, 22, 70, 6, 33, 49, 17, 65, + 37, 53, 1, 21, 69, 5, 35, 51, + 19, 67, 39, 55, 3, 23, 71, 7, + 44, 60, 28, 76, 40, 56, 12, 24, + 72, 8, 46, 62, 30, 78, 42, 58, + 14, 26, 74, 10, 45, 61, 29, 77, + 41, 57, 13, 25, 73, 9, 47, 63, + 31, 79, 43, 59, 15, 27, 75, 11, +}; + +UINT32 Ac01CoreOrderQuadrant[PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_NUM_CORES_PER_CPM] = { + 16, 32, 0, 20, 4, 18, 34, 2, + 22, 6, 17, 33, 1, 21, 5, 19, + 35, 3, 23, 7, 48, 64, 52, 68, + 36, 50, 66, 54, 70, 38, 49, 65, + 53, 69, 37, 51, 67, 55, 71, 39, + 28, 44, 12, 24, 8, 30, 46, 14, + 26, 10, 29, 45, 13, 25, 9, 31, + 47, 15, 27, 11, 60, 76, 56, 72, + 40, 62, 78, 58, 74, 42, 61, 77, + 57, 73, 41, 63, 79, 59, 75, 43, +}; + +EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *MadtTablePointer; + +STATIC UINT32 * +CPUGetCoreOrder (VOID) +{ + EFI_GUID PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2; + PlatformInfoHob_V2 *PlatformHob; + VOID *Hob; + UINT32 SubNumaMode; + UINT8 Ac01Chip = 1; + + /* Get the Platform HOB */ + Hob = GetFirstGuidHob (&PlatformHobGuid); + if (Hob == NULL) { + return SUBNUMA_MODE_MONOLITHIC; + } + PlatformHob = (PlatformInfoHob_V2 *) GET_GUID_HOB_DATA (Hob); + Ac01Chip = ((PlatformHob->ScuProductId[0] & 0xFF) == 0x1) ? 1 : 0; + + SubNumaMode = CPUGetSubNumaMode(); + switch (SubNumaMode) { + case SUBNUMA_MODE_MONOLITHIC: + if (Ac01Chip != 0) { + return (UINT32 *) &Ac01CoreOrderMonolithic; + } + case SUBNUMA_MODE_HEMISPHERE: + if (Ac01Chip != 0) { + return (UINT32 *) &Ac01CoreOrderHemisphere; + } + return (UINT32 *) &Ac01CoreOrderHemisphere; + case SUBNUMA_MODE_QUADRANT: + if (Ac01Chip != 0) { + return (UINT32 *) &Ac01CoreOrderQuadrant; + } + } + + if (Ac01Chip != 0) { + return (UINT32 *) &Ac01CoreOrderMonolithic; + } + + return NULL; +} + +STATIC UINT32 +AcpiInstallMadtProcessorNode ( + VOID *EntryPointer, + UINT32 CpuId + ) +{ + EFI_ACPI_6_3_GIC_STRUCTURE *MadtProcessorEntryPointer = EntryPointer; + UINT32 SocketId; + UINT32 ClusterId; + UINTN Size; + + Size = sizeof (GiccTemplate); + CopyMem (MadtProcessorEntryPointer, &GiccTemplate, Size); + + SocketId = CpuId / (PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_NUM_CORES_PER_CPM); + ClusterId = CpuId / PLATFORM_CPU_NUM_CORES_PER_CPM; + if (SocketId == 1) { + ClusterId -= PLATFORM_CPU_MAX_CPM; + } + + MadtProcessorEntryPointer->CPUInterfaceNumber = CpuId; + MadtProcessorEntryPointer->AcpiProcessorUid = + (SocketId << PLATFORM_SOCKET_UID_BIT_OFFSET) + + (ClusterId << 8) + (CpuId % PLATFORM_CPU_NUM_CORES_PER_CPM); + MadtProcessorEntryPointer->Flags = 1; + MadtProcessorEntryPointer->MPIDR = + (((ClusterId << 8) + (CpuId % PLATFORM_CPU_NUM_CORES_PER_CPM)) << 8) ; + MadtProcessorEntryPointer->MPIDR += (((UINT64) SocketId) << 32); + + return Size; +} + +STATIC UINT32 +AcpiInstallMadtGicD ( + VOID *EntryPointer + ) +{ + EFI_ACPI_6_3_GIC_DISTRIBUTOR_STRUCTURE *GicDEntryPointer = EntryPointer; + UINTN Size; + + Size = sizeof (GicDTemplate); + CopyMem (GicDEntryPointer, &GicDTemplate, Size); + + return Size; +} + +STATIC UINT32 +AcpiInstallMadtGicR ( + VOID *EntryPointer, + UINT32 SocketId + ) +{ + EFI_ACPI_6_3_GICR_STRUCTURE *GicREntryPointer = EntryPointer; + UINTN Size; + + /* + * If the Slave socket is not present, discard the Slave socket + * GIC redistributor region + */ + if ((SocketId == 1) && (GetNumberActiveCPMsPerSocket (SocketId) == 0)) { + return 0; + } + + Size = sizeof (GicRTemplate); + CopyMem (GicREntryPointer, &GicRTemplate, Size); + + if (SocketId == 1) { + GicREntryPointer->DiscoveryRangeBaseAddress = GICR_SLAVE_BASE_REG; + } + + return Size; +} + +STATIC UINT32 +AcpiInstallMadtGicIts ( + VOID *EntryPointer, + UINT32 Index + ) +{ + EFI_ACPI_6_3_GIC_ITS_STRUCTURE *GicItsEntryPointer = EntryPointer; + UINTN Size, Offset; + UINT64 GicBase = GICD_BASE_REG; + UINT32 ItsId = Index; + + if (Index > SOCKET0_LAST_RC) { /* Socket 1, Index: 8-15 */ + GicBase = GICD_SLAVE_BASE_REG; + Index -= (SOCKET0_LAST_RC + 1); /* Socket 1, Index:8 -> RCA0 */ + } + Size = sizeof(GicItsTemplate); + CopyMem (GicItsEntryPointer, &GicItsTemplate, Size); + Offset = 0x40000 + Index * 0x20000; + GicItsEntryPointer->GicItsId = ItsId; + GicItsEntryPointer->PhysicalBaseAddress = Offset + GicBase; + + return Size; +} + +/* + * Install MADT table. + */ +EFI_STATUS +AcpiInstallMadtTable (VOID) +{ + EFI_ACPI_6_3_GIC_STRUCTURE *GiccEntryPointer = NULL; + EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol; + UINTN MadtTableKey = 0; + INTN Count, Index; + EFI_STATUS Status; + UINTN Size; + UINT32 *CoreOrder; + UINT32 SktMaxCoreNum; + + if (IsAcpiInstalled (EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE)) { + DEBUG ((DEBUG_INFO, "APIC table is already installed. Skipping...\n")); + return EFI_ABORTED; + } + + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, + NULL, (VOID **) &AcpiTableProtocol); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Count = 0; Count < gST->NumberOfTableEntries; Count++) { + if (CompareGuid (&gArmMpCoreInfoGuid, &(gST->ConfigurationTable[Count].VendorGuid))) { + Size = sizeof(MADTTableHeaderTemplate) + + (PLATFORM_CPU_MAX_NUM_CORES * sizeof (GiccTemplate)) + + sizeof (GicDTemplate) + + (PLATFORM_CPU_MAX_SOCKET * sizeof (GicRTemplate)) + + ((SOCKET0_LAST_RC - SOCKET0_FIRST_RC + 1) * sizeof (GicItsTemplate)); + if (GetNumberActiveSockets () > 1) { + Size += ((SOCKET1_LAST_RC - SOCKET1_FIRST_RC + 1) * sizeof (GicItsTemplate)); + } else if (!PlatSlaveSocketPresent ()) { + Size += 2 * sizeof(GicItsTemplate); /* RCA0/1 */ + } + + MadtTablePointer = + (EFI_ACPI_6_3_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *) AllocateZeroPool(Size); + if (MadtTablePointer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + GiccEntryPointer = + (EFI_ACPI_6_3_GIC_STRUCTURE *) ((UINT64) MadtTablePointer + + sizeof (MADTTableHeaderTemplate)); + + /* Install Gic interface for each processor */ + Size = 0; + CoreOrder = CPUGetCoreOrder (); + ASSERT (CoreOrder != NULL); + SktMaxCoreNum = PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_NUM_CORES_PER_CPM; + for (Index = 0; Index < SktMaxCoreNum; Index++) { + if (IsCpuEnabled (CoreOrder[Index])) { + Size += AcpiInstallMadtProcessorNode ((VOID *) ((UINT64) GiccEntryPointer + Size), CoreOrder[Index]); + } + } + + for (Index = 0; Index < SktMaxCoreNum; Index++) { + if (IsCpuEnabled (CoreOrder[Index] + SktMaxCoreNum)) { + Size += AcpiInstallMadtProcessorNode ((VOID *) ((UINT64) GiccEntryPointer + Size), CoreOrder[Index] + SktMaxCoreNum); + } + } + + /* Install Gic Distributor */ + Size += AcpiInstallMadtGicD ((VOID *) ((UINT64) GiccEntryPointer + Size)); + + /* Install Gic Redistributor */ + for (Index = 0; Index < PLATFORM_CPU_MAX_SOCKET; Index++) { + Size += AcpiInstallMadtGicR ((VOID *) ((UINT64) GiccEntryPointer + Size), Index); + } + + /* Install Gic ITS */ + if (!PlatSlaveSocketPresent ()) { + for (Index = 0; Index <= 1; Index++) { /* RCA0/1 */ + Size += AcpiInstallMadtGicIts ((VOID *) ((UINT64) GiccEntryPointer + Size), Index); + } + } + for (Index = SOCKET0_FIRST_RC; Index <= SOCKET0_LAST_RC; Index++) { + Size += AcpiInstallMadtGicIts ((VOID *) ((UINT64) GiccEntryPointer + Size), Index); + } + if (GetNumberActiveSockets () > 1) { + for (Index = SOCKET1_FIRST_RC; Index <= SOCKET1_LAST_RC; Index++) { + Size += AcpiInstallMadtGicIts ((VOID *) ((UINT64) GiccEntryPointer + Size), Index); + } + } + CopyMem (MadtTablePointer, &MADTTableHeaderTemplate, + sizeof (MADTTableHeaderTemplate)); + + Size += sizeof (MADTTableHeaderTemplate); + MadtTablePointer->Header.Length = Size; + CopyMem ( + MadtTablePointer->Header.OemId, + PcdGetPtr (PcdAcpiDefaultOemId), + sizeof (MadtTablePointer->Header.OemId) + ); + MadtTablePointer->Header.OemTableId = EFI_ACPI_OEM_TABLE_ID; + MadtTablePointer->Header.OemRevision = 3; + MadtTablePointer->Header.CreatorId = EFI_ACPI_CREATOR_ID; + MadtTablePointer->Header.CreatorRevision = EFI_ACPI_CREATOR_REVISION; + + AcpiTableChecksum ((UINT8 *) MadtTablePointer, + MadtTablePointer->Header.Length); + + Status = AcpiTableProtocol->InstallAcpiTable ( + AcpiTableProtocol, + (VOID *) MadtTablePointer, + MadtTablePointer->Header.Length, + &MadtTableKey + ); + FreePool ((VOID *) MadtTablePointer); + if (EFI_ERROR (Status)) { + return Status; + } + break; + } + } + + if (Count == gST->NumberOfTableEntries) { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiNfit.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiNfit.c new file mode 100644 index 000000000000..fb22deef0aec --- /dev/null +++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiNfit.c @@ -0,0 +1,268 @@ +/** @file + + Copyright (c) 2020, Ampere Computing LLC. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "AcpiPlatform.h" + +EFI_ACPI_6_3_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE NfitSPATemplate = { + EFI_ACPI_6_3_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE_TYPE, + sizeof (EFI_ACPI_6_3_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE), + 0, // The uniue index - need to be filled. + 0, // The flags - need to be filled. + 0, // Reserved. + 0, // Proximity domain - need to be filled. + EFI_ACPI_6_3_NFIT_GUID_BYTE_ADDRESSABLE_PERSISTENT_MEMORY_REGION, // PM range type. + 0, // Start address - need to be filled. + 0, // Size - need to be filled. + EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB | EFI_MEMORY_WP | EFI_MEMORY_UCE, // attribute - need to be filled. +}; + +EFI_ACPI_6_3_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE NvdimmControlRegionTemplate = { + EFI_ACPI_6_3_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE_TYPE, + sizeof (EFI_ACPI_6_3_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE), + 0, // The unique index - need to be filled. + 0x1122, // The vendor id - dummy value. + 0x3344, // The device id - dummy value. + 0, // The revision - dummy value. + 0x5566, // The subsystem nvdimm id - dummy value. + 0x7788, // The subsystem nvdimm device id - dummy value. + 0x0, // The subsystem revision - dummy value. + 0, // The valid field. + 0, // The manufacturing location - not valid. + 0, // The manufacturing date - not valid. + {0}, // Reserved. + 0xaabbccdd, // The serial number - dummy value. + 0, // The region format interface code - dummy value. + 0, // The number of block control windows. + 0, // The size of block control windows. + 0, // The Command Register Offset in Block Control Window. + 0, // The Size of Command Register in Block Control Windows. + 0, // The Status Register Offset in Block Control Window. + 0, // Size of Status Register in Block Control Windows. + 0, // The NVDIMM Control Region Flag. + {0}, // Reserved. +}; + +EFI_ACPI_6_3_NFIT_NVDIMM_REGION_MAPPING_STRUCTURE NvdimmRegionMappingTemplate = { + EFI_ACPI_6_3_NFIT_NVDIMM_REGION_MAPPING_STRUCTURE_TYPE, + sizeof (EFI_ACPI_6_3_NFIT_NVDIMM_REGION_MAPPING_STRUCTURE), + {0}, // _ADR of the NVDIMM device - need to be filled. + 0, // Dimm smbios handle index - need to be filled. + 0, // The unique region index - need to be filled. + 0, // The SPA range index - need to be filled. + 0, // The control region index - need to be filled. + 0, // The region size - need to be filled. + 0, // The region offset - need to be filled. + 0, // The region base - need to be filled. + 0, // The interleave structure index - need to be filled. + 0, // The interleave ways - need to be filled. + 0, // NVDIMM flags - need to be filled. + 0, // Reserved. +}; + +EFI_ACPI_6_3_NVDIMM_FIRMWARE_INTERFACE_TABLE NFITTableHeaderTemplate = { + __ACPI_HEADER ( + EFI_ACPI_6_3_NVDIMM_FIRMWARE_INTERFACE_TABLE_STRUCTURE_SIGNATURE, + 0, /* need fill in */ + EFI_ACPI_6_3_NVDIMM_FIRMWARE_INTERFACE_TABLE_REVISION + ), + 0x00000000, // Reserved +}; + +/* + * Count NVDIMM Region + */ +EFI_STATUS +AcpiGetNvdRegionNumber ( + IN OUT UINTN *NvdRegionNum + ) +{ + CONST EFI_GUID PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2; + PlatformInfoHob_V2 *PlatformHob; + UINTN Count; + VOID *Hob; + + /* Get the Platform HOB */ + Hob = GetFirstGuidHob (&PlatformHobGuid); + if (Hob == NULL) { + return EFI_INVALID_PARAMETER; + } + PlatformHob = (PlatformInfoHob_V2 *) GET_GUID_HOB_DATA (Hob); + + *NvdRegionNum = 0; + for (Count = 0; Count < PlatformHob->DramInfo.NumRegion; Count++) { + if (PlatformHob->DramInfo.NvdRegion[Count]) { + *NvdRegionNum += 1; + } + } + + if (*NvdRegionNum == 0) { + DEBUG ((DEBUG_INFO, "No NVDIMM Region\n")); + return EFI_INVALID_PARAMETER; /* No NVDIMM Region */ + } + + return EFI_SUCCESS; +} + +/* + * Fill in SPA strucutre + */ +VOID +AcpiNfitFillSPA ( + IN OUT EFI_ACPI_6_3_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE *NfitSpaPointer, + IN UINTN NvdRegionIndex, + IN UINT64 NvdRegionBase, + IN UINT64 NvdRegionSize + ) +{ + NfitSpaPointer->Flags = 0; + NfitSpaPointer->SPARangeStructureIndex = NvdRegionIndex; + NfitSpaPointer->SystemPhysicalAddressRangeBase = NvdRegionBase; + NfitSpaPointer->SystemPhysicalAddressRangeLength = NvdRegionSize; +} + +VOID +NfitFillControlRegion ( + IN OUT EFI_ACPI_6_3_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE *NfitControlRegionPointer, + IN UINTN NvdRegionIndex + ) +{ + NfitControlRegionPointer->NVDIMMControlRegionStructureIndex = NvdRegionIndex; +} + +VOID +NfitFillRegionMapping ( + IN OUT EFI_ACPI_6_3_NFIT_NVDIMM_REGION_MAPPING_STRUCTURE *NfitRegionMappingPointer, + IN EFI_ACPI_6_3_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE *NfitControlRegionPointer, + IN EFI_ACPI_6_3_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE *NfitSpaPointer + ) +{ + NfitRegionMappingPointer->NVDIMMControlRegionStructureIndex = NfitControlRegionPointer->NVDIMMControlRegionStructureIndex; + NfitRegionMappingPointer->SPARangeStructureIndex = NfitSpaPointer->SPARangeStructureIndex; + NfitRegionMappingPointer->NVDIMMPhysicalAddressRegionBase = NfitSpaPointer->SystemPhysicalAddressRangeBase; + NfitRegionMappingPointer->NVDIMMRegionSize = NfitSpaPointer->SystemPhysicalAddressRangeLength; + NfitRegionMappingPointer->NFITDeviceHandle.DIMMNumber = 1; // Hardcoded for now. + NfitRegionMappingPointer->NFITDeviceHandle.MemoryChannelNumber = 0; // Hardcoded for now. + NfitRegionMappingPointer->NFITDeviceHandle.MemoryControllerID = 0; // Hardcoded for now. + NfitRegionMappingPointer->NFITDeviceHandle.NodeControllerID = 0; // Hardcoded for now. + NfitRegionMappingPointer->NFITDeviceHandle.SocketID = 0; // Hardcoded for now. + NfitRegionMappingPointer->RegionOffset = 0; // Hardcoded for now. +} + +EFI_STATUS +AcpiNfitFillTable ( + IN EFI_ACPI_6_3_NVDIMM_FIRMWARE_INTERFACE_TABLE *NfitTablePointer + ) +{ + EFI_ACPI_6_3_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE *NfitSpaPointer; + EFI_ACPI_6_3_NFIT_NVDIMM_REGION_MAPPING_STRUCTURE *NfitRegionMappingPointer; + EFI_ACPI_6_3_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE *NfitControlRegionPointer; + CONST EFI_GUID PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2; + PlatformInfoHob_V2 *PlatformHob; + UINTN Count; + VOID *Hob; + UINTN NvdRegionIndex; + UINT64 NvdRegionBase; + UINT64 NvdRegionSize; + + /* Get the Platform HOB */ + Hob = GetFirstGuidHob (&PlatformHobGuid); + if (Hob == NULL) { + return EFI_INVALID_PARAMETER; + } + PlatformHob = (PlatformInfoHob_V2 *) GET_GUID_HOB_DATA (Hob); + + NfitSpaPointer = (EFI_ACPI_6_3_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE *) + (NfitTablePointer + 1); + NvdRegionIndex = 0; + for (Count = 0; Count < PlatformHob->DramInfo.NumRegion; Count++) { + if (PlatformHob->DramInfo.NvdRegion[Count] != 0) { + NvdRegionIndex++; + NvdRegionBase = PlatformHob->DramInfo.Base[Count]; + NvdRegionSize = PlatformHob->DramInfo.Size[Count]; + + CopyMem ((VOID *) NfitSpaPointer, (VOID *) &NfitSPATemplate, sizeof (NfitSPATemplate)); + AcpiNfitFillSPA (NfitSpaPointer, NvdRegionIndex, NvdRegionBase, NvdRegionSize); + + NfitControlRegionPointer = (EFI_ACPI_6_3_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE *) + (NfitSpaPointer + 1); + CopyMem ((VOID *) NfitControlRegionPointer, + (VOID *) &NvdimmControlRegionTemplate, + sizeof (NvdimmControlRegionTemplate)); + NfitFillControlRegion (NfitControlRegionPointer, NvdRegionIndex); + + NfitRegionMappingPointer = (EFI_ACPI_6_3_NFIT_NVDIMM_REGION_MAPPING_STRUCTURE *) + (NfitControlRegionPointer + 1); + CopyMem ((VOID *) NfitRegionMappingPointer, + (VOID *) &NvdimmRegionMappingTemplate, + sizeof (NvdimmRegionMappingTemplate)); + NfitFillRegionMapping (NfitRegionMappingPointer, + NfitControlRegionPointer, + NfitSpaPointer); + /* Next Region */ + NfitSpaPointer = (EFI_ACPI_6_3_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE *) + (NfitRegionMappingPointer + 1); + } + } + + return EFI_SUCCESS; +} + +/* + * Install NFIT table. + */ +EFI_STATUS +AcpiInstallNfitTable (VOID) +{ + EFI_ACPI_6_3_NVDIMM_FIRMWARE_INTERFACE_TABLE *NfitTablePointer; + EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol; + UINTN NfitTableKey = 0; + EFI_STATUS Status; + UINTN Size; + UINTN NvdRegionNum; + + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, + NULL, (VOID **) &AcpiTableProtocol); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = AcpiGetNvdRegionNumber (&NvdRegionNum); + if (EFI_ERROR (Status)) { + return Status; + } + + Size = sizeof (EFI_ACPI_6_3_NVDIMM_FIRMWARE_INTERFACE_TABLE) + + ((sizeof (EFI_ACPI_6_3_NFIT_SYSTEM_PHYSICAL_ADDRESS_RANGE_STRUCTURE) + + sizeof (EFI_ACPI_6_3_NFIT_NVDIMM_REGION_MAPPING_STRUCTURE) + + sizeof (EFI_ACPI_6_3_NFIT_NVDIMM_CONTROL_REGION_STRUCTURE)) * NvdRegionNum); + NfitTablePointer = (EFI_ACPI_6_3_NVDIMM_FIRMWARE_INTERFACE_TABLE *) AllocateZeroPool (Size); + if (NfitTablePointer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem ((VOID *) NfitTablePointer, + (VOID *) &NFITTableHeaderTemplate, + sizeof (NFITTableHeaderTemplate)); + NfitTablePointer->Header.Length = Size; + + Status = AcpiNfitFillTable (NfitTablePointer); + if (EFI_ERROR (Status)) { + FreePool ((VOID *) NfitTablePointer); + return Status; + } + + AcpiTableChecksum ((UINT8 *)NfitTablePointer, NfitTablePointer->Header.Length); + Status = AcpiTableProtocol->InstallAcpiTable (AcpiTableProtocol, + (VOID *) NfitTablePointer, + NfitTablePointer->Header.Length, + &NfitTableKey); + if (EFI_ERROR (Status)) { + FreePool ((VOID *) NfitTablePointer); + } + + return Status; +} diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPCCT.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPCCT.c new file mode 100644 index 000000000000..c27e91f06375 --- /dev/null +++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPCCT.c @@ -0,0 +1,264 @@ +/** @file + + Copyright (c) 2020, Ampere Computing LLC. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include "AcpiPlatform.h" + +EFI_ACPI_6_3_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS PCCTSubspaceTemplate = { + 2, /* HW-Reduced Communication Subspace Type 2 */ + sizeof(EFI_ACPI_6_3_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS), + 0, /* DoorbellInterrupt: need fill in */ + 0, + 0, + 0, /* BaseAddress: need fill in */ + 0x100, + {0, 0x20, 0, 0x3, 0x0}, /* DoorbellRegister: need fill in */ + 0, + 0x53000040, + 1, + 1, + 1, + {0, 0x20, 0, 0x3, 0x0}, /* DoorbellAckRegister: need fill in */ + 0, + 0x10001, +}; + +EFI_ACPI_6_3_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER PCCTTableHeaderTemplate = { + { + EFI_ACPI_6_3_PLATFORM_COMMUNICATIONS_CHANNEL_TABLE_SIGNATURE, + 0, /* need fill in */ + EFI_ACPI_6_3_PLATFORM_COMMUNICATION_CHANNEL_TABLE_REVISION, // Revision + 0x00, // Checksum will be updated at runtime + // + // It is expected that these values will be updated at EntryPoint. + // + {0}, // OEM ID is a 6 bytes long field + 0, // OEM Table ID(8 bytes long) + 0, // OEM Revision + 0, // Creator ID + 0, // Creator Revision + }, + EFI_ACPI_6_3_PCCT_FLAGS_PLATFORM_INTERRUPT, +}; + +STATIC BOOLEAN +AcpiPcctIsV2 (VOID) +{ + CONST EFI_GUID PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2; + VOID *Hob; + + /* Get the Platform HOB */ + Hob = GetFirstGuidHob (&PlatformHobGuid); + if (Hob == NULL) { + return FALSE; + } + + return TRUE; +} + +STATIC UINT32 +AcpiPcctGetNumOfSocket (VOID) +{ + UINTN NumberSockets, NumberActiveSockets, Count, Index, Index1; + CONST EFI_GUID PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2; + PlatformInfoHob_V2 *PlatformHob; + PlatformClusterEn *Socket; + VOID *Hob; + + /* Get the Platform HOB */ + Hob = GetFirstGuidHob (&PlatformHobGuid); + if (Hob == NULL) { + return 1; + } + PlatformHob = (PlatformInfoHob_V2 *) GET_GUID_HOB_DATA (Hob); + + NumberSockets = sizeof (PlatformHob->ClusterEn) / sizeof (PlatformClusterEn); + NumberActiveSockets = 0; + + for (Index = 0; Index < NumberSockets; Index++) { + Socket = &PlatformHob->ClusterEn[Index]; + Count = sizeof (Socket->EnableMask) / sizeof (Socket->EnableMask[0]); + for (Index1 = 0; Index1 < Count; Index1++) { + if (Socket->EnableMask[Index1] != 0) { + NumberActiveSockets++; + break; + } + } + } + + return NumberActiveSockets; +} + +EFI_STATUS +AcpiPcctInit (VOID) +{ + INTN NumOfSocket = AcpiPcctGetNumOfSocket (); + INTN Subspace; + INTN Socket; + + for (Socket = 0; Socket < NumOfSocket; Socket++) { + for (Subspace = 0; Subspace < PCC_MAX_SUBSPACES_PER_SOCKET; Subspace++ ) { + if (AcpiPcctIsV2 ()) { + AcpiPccSharedMemInitV2 (Socket, Subspace); + } else { + AcpiPccSharedMemInit (Socket, Subspace); + } + AcpiPccSyncSharedMemAddr (Socket, Subspace); + AcpiPccUnmaskInt (Socket, Subspace); + } + } + + return EFI_SUCCESS; +} + +/* + * Install PCCT table. + * + * Each socket has 16 PCC subspaces + * 0 - 7 : PMPro subspaces + * 8 - 15 : SMPro subspaces + */ +EFI_STATUS +AcpiInstallPcctTable (VOID) +{ + EFI_ACPI_6_3_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER *PcctTablePointer = NULL; + EFI_ACPI_6_3_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS *PcctEntryPointer = NULL; + INTN NumOfSocket = AcpiPcctGetNumOfSocket (); + UINT64 PccSharedMemPointer = 0; + EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol; + UINTN PcctTableKey = 0; + INTN Count, Subspace; + INTN SubspaceIdx; + INTN NumOfSubspace; + INTN IntNum = 0; + EFI_STATUS Status; + UINTN Size; + INTN Socket; + + if (IsAcpiInstalled (EFI_ACPI_6_3_PLATFORM_COMMUNICATIONS_CHANNEL_TABLE_SIGNATURE)) { + DEBUG ((DEBUG_INFO, "PCCT table is already installed. Skipping...\n")); + return EFI_ABORTED; + } + + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, + NULL, (VOID **) &AcpiTableProtocol); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Count = 0; Count < gST->NumberOfTableEntries; Count++) { + if (CompareGuid (&gArmMpCoreInfoGuid, &(gST->ConfigurationTable[Count].VendorGuid))) { + NumOfSubspace = PCC_MAX_SUBSPACES_PER_SOCKET * NumOfSocket; + + Size = sizeof(EFI_ACPI_6_3_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER) + + NumOfSubspace * sizeof(EFI_ACPI_6_3_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS); + + PcctTablePointer = (EFI_ACPI_6_3_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER *)AllocateZeroPool(Size); + if (PcctTablePointer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + /* Allocation PCC shared memory */ + AcpiPccAllocSharedMemory (&PccSharedMemPointer, NumOfSubspace); + if (PccSharedMemPointer == 0) { + FreePool ((VOID *)PcctTablePointer); + return EFI_OUT_OF_RESOURCES; + } + + PcctEntryPointer = (EFI_ACPI_6_3_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS *) ((UINT64) PcctTablePointer + + sizeof (EFI_ACPI_6_3_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER)); + + for (Socket = 0; Socket < NumOfSocket; Socket++) { + for (Subspace = 0; Subspace < PCC_MAX_SUBSPACES_PER_SOCKET; Subspace++ ) { + SubspaceIdx = Subspace + PCC_MAX_SUBSPACES_PER_SOCKET * Socket; + + CopyMem (&PcctEntryPointer[SubspaceIdx], &PCCTSubspaceTemplate, + sizeof(EFI_ACPI_6_3_PCCT_SUBSPACE_2_HW_REDUCED_COMMUNICATIONS)); + + PcctEntryPointer[SubspaceIdx].BaseAddress = PccSharedMemPointer + + PCC_SUBSPACE_SHARED_MEM_SIZE * SubspaceIdx; + PcctEntryPointer[SubspaceIdx].AddressLength = PCC_SUBSPACE_SHARED_MEM_SIZE; + + IntNum = 0; + if (Socket > 0) { + IntNum = Socket * PLATFORM_SLAVE_SOCKET_SPI_INTERRUPT_START - 32; + } + if (Subspace < PMPRO_MAX_DB) { + IntNum += PMPRO_DB0_IRQ_NUM + Subspace; + /* PCC subspaces for 8 PMpro Doorbells */ + PcctEntryPointer[SubspaceIdx].DoorbellRegister.Address = PMPRO_DBx_REG (Socket, Subspace, DB_OUT); + PcctEntryPointer[SubspaceIdx].PlatformInterrupt = IntNum; + PcctEntryPointer[SubspaceIdx].PlatformInterruptAckRegister.Address = PMPRO_DBx_REG (Socket, Subspace, DB_STATUS); + } else { + IntNum += SMPRO_DB0_IRQ_NUM + Subspace - PMPRO_MAX_DB; + /* PCC subspaces for 8 SMpro Doorbells */ + PcctEntryPointer[SubspaceIdx].DoorbellRegister.Address = SMPRO_DBx_REG (Socket,Subspace - PMPRO_MAX_DB, DB_OUT); + PcctEntryPointer[SubspaceIdx].PlatformInterrupt = IntNum; + PcctEntryPointer[SubspaceIdx].PlatformInterruptAckRegister.Address = SMPRO_DBx_REG (Socket, Subspace - PMPRO_MAX_DB, DB_STATUS); + } + + /* Timing */ + PcctEntryPointer[SubspaceIdx].NominalLatency = PCC_NOMINAL_LATENCY; + PcctEntryPointer[SubspaceIdx].MaximumPeriodicAccessRate = PCC_MAX_PERIOD_ACCESS; + PcctEntryPointer[SubspaceIdx].MinimumRequestTurnaroundTime = PCC_MIN_REQ_TURNAROUND_TIME; + + /* Initialize subspace used for CPPC queries */ + if (Subspace == PCC_CPPC_SUBSPACE) { + /* Configure CPPC control byte for CPPC : 0x100 */ + PcctEntryPointer[SubspaceIdx].DoorbellWrite = PCC_MSG | PCC_CPPC_URG_MSG | PCC_CPPC_MSG; + PcctEntryPointer[SubspaceIdx].NominalLatency = PCC_CPPC_NOMINAL_LATENCY; + PcctEntryPointer[SubspaceIdx].MinimumRequestTurnaroundTime = PCC_CPPC_MIN_REQ_TURNAROUND_TIME; + } else { + PcctEntryPointer[SubspaceIdx].DoorbellWrite = PCC_MSG; + } + if (!AcpiPcctIsV2 ()) { + /* Store the upper address (Bit 40-43) of PCC shared memory */ + PcctEntryPointer[SubspaceIdx].DoorbellWrite |= + (PcctEntryPointer[SubspaceIdx].BaseAddress >> 40) & PCP_MSG_UPPER_ADDR_MASK; + } + } + } + + CopyMem (PcctTablePointer, &PCCTTableHeaderTemplate, + sizeof (EFI_ACPI_6_3_PLATFORM_COMMUNICATION_CHANNEL_TABLE_HEADER)); + + PcctTablePointer->Header.Length = Size; + CopyMem ( + PcctTablePointer->Header.OemId, + PcdGetPtr (PcdAcpiDefaultOemId), + sizeof (PcctTablePointer->Header.OemId) + ); + PcctTablePointer->Header.OemTableId = EFI_ACPI_OEM_TABLE_ID; + PcctTablePointer->Header.OemRevision = 3; + PcctTablePointer->Header.CreatorId = EFI_ACPI_CREATOR_ID; + PcctTablePointer->Header.CreatorRevision = EFI_ACPI_CREATOR_REVISION; + + AcpiTableChecksum ((UINT8 *) PcctTablePointer, + PcctTablePointer->Header.Length); + + Status = AcpiTableProtocol->InstallAcpiTable ( + AcpiTableProtocol, + (VOID *) PcctTablePointer, + PcctTablePointer->Header.Length, + &PcctTableKey + ); + if (EFI_ERROR (Status)) { + AcpiPccFreeSharedMemory (&PccSharedMemPointer, NumOfSubspace); + FreePool ((VOID *) PcctTablePointer); + return Status; + } + break; + } + } + + if (Count == gST->NumberOfTableEntries) { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPPTT.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPPTT.c new file mode 100755 index 000000000000..59a8701aa2e7 --- /dev/null +++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPPTT.c @@ -0,0 +1,338 @@ +/** @file + + Copyright (c) 2020, Ampere Computing LLC. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "AcpiPlatform.h" + +EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR PPTTProcessorTemplate = { + EFI_ACPI_6_3_PPTT_TYPE_PROCESSOR, + sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR), + { EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE }, + {0}, /* Flags */ + 0, /* Parent */ + 0, /* AcpiProcessorId */ + 0 /* NumberOfPrivateResources */ +}; + +EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE PPTTCacheTemplate = { + EFI_ACPI_6_3_PPTT_TYPE_CACHE, + sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE), + { EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE }, + {0}, /* Flags */ + 0, /* NextLevelOfCache */ + 0, /* Size */ + 0, /* NumberOfSets */ + 0, /* Associativity */ + {0}, /* Attributes */ + 0 +}; + +EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER PPTTTableHeaderTemplate = { + __ACPI_HEADER ( + EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_STRUCTURE_SIGNATURE, + 0, /* need fill in */ + EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_REVISION + ), +}; + +STATIC EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER *PpttTablePointer; +STATIC UINT32 PpttCoreOffset[PLATFORM_CPU_MAX_NUM_CORES]; +STATIC UINT32 PpttClusterOffset[PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_MAX_SOCKET]; +STATIC UINT32 PpttSocketOffset[PLATFORM_CPU_MAX_SOCKET]; +STATIC UINT32 PpttRootOffset; +STATIC UINT32 PpttL1DataCacheOffset[PLATFORM_CPU_MAX_NUM_CORES]; +STATIC UINT32 PpttL1InstructionCacheOffset[PLATFORM_CPU_MAX_NUM_CORES]; +STATIC UINT32 PpttL2CacheOffset[PLATFORM_CPU_MAX_NUM_CORES]; + +STATIC UINT32 +AcpiPpttProcessorThreadNode ( + VOID *EntryPointer, + UINT32 CpuId + ) +{ + EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *PpttProcessorEntryPointer = EntryPointer; + UINT32 *ResPointer; + UINTN ClusterIdPerSocket, CoreIdPerCpm, SocketId; + + CopyMem (PpttProcessorEntryPointer, &PPTTProcessorTemplate, + sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR)); + + ClusterIdPerSocket = (CpuId / PLATFORM_CPU_NUM_CORES_PER_CPM) % PLATFORM_CPU_MAX_CPM; + SocketId = (CpuId / PLATFORM_CPU_NUM_CORES_PER_CPM) / PLATFORM_CPU_MAX_CPM; + CoreIdPerCpm = CpuId % PLATFORM_CPU_NUM_CORES_PER_CPM; + PpttProcessorEntryPointer->Flags.AcpiProcessorIdValid = 1; + PpttProcessorEntryPointer->Flags.NodeIsALeaf = 1; + PpttProcessorEntryPointer->Flags.IdenticalImplementation = 1; + PpttProcessorEntryPointer->AcpiProcessorId = (SocketId << PLATFORM_SOCKET_UID_BIT_OFFSET) | (ClusterIdPerSocket << 8) | CoreIdPerCpm; + PpttProcessorEntryPointer->Parent = (UINT32) PpttCoreOffset[CpuId]; + PpttProcessorEntryPointer->NumberOfPrivateResources = 2; /* L1I + L1D */ + + ResPointer = (UINT32 *) ((UINT64) EntryPointer + + sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR)); + ResPointer[0] = PpttL1InstructionCacheOffset[CpuId]; + ResPointer[1] = PpttL1DataCacheOffset[CpuId]; + + PpttProcessorEntryPointer->Length = sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR) + 2 * sizeof (UINT32); + + return PpttProcessorEntryPointer->Length; +} + +STATIC UINT32 +AcpiPpttProcessorCoreNode ( + VOID *EntryPointer, + UINT32 CpuId + ) +{ + EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *PpttProcessorEntryPointer = EntryPointer; + + PpttCoreOffset[CpuId] = (UINT64) EntryPointer - (UINT64) PpttTablePointer; + + CopyMem (PpttProcessorEntryPointer, &PPTTProcessorTemplate, + sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR)); + + PpttProcessorEntryPointer->Parent = (UINT32) PpttClusterOffset[CpuId / PLATFORM_CPU_NUM_CORES_PER_CPM]; + PpttProcessorEntryPointer->Flags.IdenticalImplementation = 1; + + return PpttProcessorEntryPointer->Length; +} + +STATIC UINT32 +AcpiPpttClusterNode ( + VOID *EntryPointer, + UINT32 ClusterId + ) +{ + EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *PpttProcessorEntryPointer = EntryPointer; + + PpttClusterOffset[ClusterId] = (UINT64) EntryPointer - (UINT64) PpttTablePointer; + + CopyMem (PpttProcessorEntryPointer, &PPTTProcessorTemplate, + sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR)); + + PpttProcessorEntryPointer->Parent = (UINT32) PpttSocketOffset[ClusterId / PLATFORM_CPU_MAX_CPM]; + PpttProcessorEntryPointer->Flags.IdenticalImplementation = 1; + + return PpttProcessorEntryPointer->Length; +} + +STATIC UINT32 +AcpiPpttSocketNode ( + VOID *EntryPointer, + UINT32 SocketId + ) +{ + EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *PpttProcessorEntryPointer = EntryPointer; + + PpttSocketOffset[SocketId] = (UINT64) EntryPointer - (UINT64) PpttTablePointer; + + CopyMem (PpttProcessorEntryPointer, &PPTTProcessorTemplate, + sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR)); + + PpttProcessorEntryPointer->Flags.PhysicalPackage = 1; + PpttProcessorEntryPointer->Flags.IdenticalImplementation = 1; + PpttProcessorEntryPointer->Parent = (UINT32) PpttRootOffset; + + return PpttProcessorEntryPointer->Length; +} + +STATIC UINT32 +AcpiPpttRootNode ( + VOID *EntryPointer + ) +{ + EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *PpttProcessorEntryPointer = EntryPointer; + + PpttRootOffset = (UINT64) EntryPointer - (UINT64) PpttTablePointer; + + CopyMem (PpttProcessorEntryPointer, &PPTTProcessorTemplate, + sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR)); + + PpttProcessorEntryPointer->Flags.IdenticalImplementation = 1; + + return PpttProcessorEntryPointer->Length; +} + +STATIC VOID +AcpiPpttFillCacheSizeInfo ( + EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE *Node, + UINT32 Level + ) +{ + UINT64 CacheCCSIDR = AArch64ReadCCSIDRReg (Level); + UINT32 CacheLineSize; + UINT32 Count; + + CacheLineSize = 1; + Count = CCSIDR_LINE_SIZE (CacheCCSIDR) + 4; + while (Count-- > 0) { + CacheLineSize *= 2; + } + + Node->Flags.LineSizeValid = 1; + Node->Flags.NumberOfSetsValid = 1; + Node->Flags.AssociativityValid = 1; + Node->Flags.SizePropertyValid = 1; + Node->Flags.CacheTypeValid = 1; + Node->NumberOfSets = CCSIDR_NUMSETS (CacheCCSIDR) + 1; + Node->Associativity = CCSIDR_ASSOCIATIVITY (CacheCCSIDR) + 1; + Node->LineSize = CacheLineSize; + Node->Size = Node->NumberOfSets * + Node->Associativity * + Node->LineSize; +} + +STATIC UINT32 +AcpiPpttL1DataCacheNode ( + VOID *EntryPointer, + UINT32 CpuId + ) +{ + EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE *PpttCacheEntryPointer = EntryPointer; + + PpttL1DataCacheOffset[CpuId] = (UINT64) EntryPointer - (UINT64) PpttTablePointer; + CopyMem (PpttCacheEntryPointer, &PPTTCacheTemplate, + sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE)); + + AcpiPpttFillCacheSizeInfo (PpttCacheEntryPointer, 1); + PpttCacheEntryPointer->Attributes.CacheType = 0x0; /* Data Cache */ + PpttCacheEntryPointer->NextLevelOfCache = PpttL2CacheOffset[CpuId]; + + return PpttCacheEntryPointer->Length; +} + +STATIC UINT32 +AcpiPpttL1InstructionCacheNode ( + VOID *EntryPointer, + UINT32 CpuId + ) +{ + EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE *PpttCacheEntryPointer = EntryPointer; + + PpttL1InstructionCacheOffset[CpuId] = (UINT64) EntryPointer - (UINT64)PpttTablePointer; + CopyMem (PpttCacheEntryPointer, &PPTTCacheTemplate, + sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE)); + + AcpiPpttFillCacheSizeInfo (PpttCacheEntryPointer, 1); + PpttCacheEntryPointer->Attributes.CacheType = 0x1; /* Instruction Cache */ + PpttCacheEntryPointer->NextLevelOfCache = PpttL2CacheOffset[CpuId]; + + return PpttCacheEntryPointer->Length; +} + +STATIC UINT32 +AcpiPpttL2CacheNode ( + VOID *EntryPointer, + UINT32 CpuId + ) +{ + EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE *PpttCacheEntryPointer = EntryPointer; + + PpttL2CacheOffset[CpuId] = (UINT64) EntryPointer - (UINT64) PpttTablePointer; + CopyMem (PpttCacheEntryPointer, &PPTTCacheTemplate, + sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE)); + + AcpiPpttFillCacheSizeInfo (PpttCacheEntryPointer, 2); + PpttCacheEntryPointer->Attributes.CacheType = 0x3; /* Unified Cache */ + PpttCacheEntryPointer->NextLevelOfCache = 0; + + return PpttCacheEntryPointer->Length; +} + +/* + * Install PPTT table. + */ +EFI_STATUS +AcpiInstallPpttTable (VOID) +{ + EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *PpttProcessorEntryPointer = NULL; + EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol; + UINTN PpttTableKey = 0; + INTN Count, Count1; + EFI_STATUS Status; + UINTN Size; + + if (IsAcpiInstalled (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_STRUCTURE_SIGNATURE)) { + DEBUG ((DEBUG_INFO, "PPTT table is already installed. Skipping...\n")); + return EFI_ABORTED; + } + + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, + NULL, (VOID **) &AcpiTableProtocol); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Count = 0; Count < gST->NumberOfTableEntries; Count++) { + if (CompareGuid (&gArmMpCoreInfoGuid, &(gST->ConfigurationTable[Count].VendorGuid))) { + Size = sizeof (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER) + + sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR) + /* Root node */ + (PLATFORM_CPU_MAX_SOCKET * sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR)) + /* Socket node */ + (PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_MAX_SOCKET * sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR)) + /* Cluster node */ + (PLATFORM_CPU_MAX_NUM_CORES * sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR)) + /* Core node */ + (PLATFORM_CPU_MAX_NUM_CORES * (sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR) + 2 * sizeof (UINT32))) + /* Thread node */ + (PLATFORM_CPU_MAX_NUM_CORES * sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE)) + /* L1I node */ + (PLATFORM_CPU_MAX_NUM_CORES * sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE)) + /* L1D node */ + (PLATFORM_CPU_MAX_NUM_CORES * sizeof (EFI_ACPI_6_3_PPTT_STRUCTURE_CACHE)); /* L2 node */ + + PpttTablePointer = + (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER *) AllocateZeroPool (Size); + if (PpttTablePointer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + PpttProcessorEntryPointer = + (EFI_ACPI_6_3_PPTT_STRUCTURE_PROCESSOR *) ((UINT64) PpttTablePointer + + sizeof (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER)); + + Size = 0; + Size += AcpiPpttRootNode ((VOID *)((UINT64) PpttProcessorEntryPointer + Size)); + + for (Count1 = 0; Count1 < PLATFORM_CPU_MAX_SOCKET; Count1++) { + Size += AcpiPpttSocketNode ((VOID *)((UINT64) PpttProcessorEntryPointer + Size), Count1); + } + + for (Count1 = 0; Count1 < PLATFORM_CPU_MAX_CPM * PLATFORM_CPU_MAX_SOCKET; Count1++) { + Size += AcpiPpttClusterNode ((VOID *)((UINT64) PpttProcessorEntryPointer + Size), Count1); + } + + for (Count1 = 0; Count1 < PLATFORM_CPU_MAX_NUM_CORES; Count1++) { + Size += AcpiPpttL2CacheNode ((VOID *)((UINT64) PpttProcessorEntryPointer + Size), Count1); + Size += AcpiPpttL1InstructionCacheNode ((VOID *) ((UINT64) PpttProcessorEntryPointer + Size), Count1); + Size += AcpiPpttL1DataCacheNode ((VOID *)((UINT64) PpttProcessorEntryPointer + Size), Count1); + Size += AcpiPpttProcessorCoreNode ((VOID *)((UINT64) PpttProcessorEntryPointer + Size), Count1); + Size += AcpiPpttProcessorThreadNode ((VOID *)((UINT64) PpttProcessorEntryPointer + Size), Count1); + } + + CopyMem (PpttTablePointer, &PPTTTableHeaderTemplate, + sizeof (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER)); + + Size += sizeof (EFI_ACPI_6_3_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_HEADER); + PpttTablePointer->Header.Length = Size; + + AcpiTableChecksum ((UINT8 *) PpttTablePointer, + PpttTablePointer->Header.Length); + + Status = AcpiTableProtocol->InstallAcpiTable ( + AcpiTableProtocol, + (VOID *)PpttTablePointer, + PpttTablePointer->Header.Length, + &PpttTableKey + ); + FreePool ((VOID *)PpttTablePointer); + if (EFI_ERROR (Status)) { + return Status; + } + break; + } + } + + if (Count == gST->NumberOfTableEntries) { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c index 346f23cbe5fb..31b635db2b7b 100644 --- a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c +++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c @@ -47,6 +47,67 @@ AcpiNotificationEvent ( } } +VOID +EFIAPI +InstallAcpiOnReadyToBoot ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + + Status = AcpiInstallMadtTable (); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Installed MADT table\n")); + } + + Status = AcpiInstallPpttTable (); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Installed PPTT table\n")); + } + + Status = AcpiInstallSlitTable (); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Installed SLIT table\n")); + } + + Status = AcpiInstallSratTable (); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Installed SRAT table\n")); + } + + Status = AcpiInstallPcctTable (); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Installed PCCT table\n")); + } + + Status = AcpiInstallNfitTable (); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Installed NFIT table\n")); + } +} + +VOID +EFIAPI +UpdateAcpiOnExitBootServices( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + + Status = AcpiPatchDsdtTable (); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "DSDT Table updated!\n")); + } + + // Configure PCC mailbox base address and unmask interrupt + Status = AcpiPcctInit(); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "PCCT Table updated!\n")); + } +} + EFI_STATUS EFIAPI AcpiPlatformDxeInitialize ( @@ -54,6 +115,10 @@ AcpiPlatformDxeInitialize ( IN EFI_SYSTEM_TABLE *SystemTable ) { + EFI_EVENT ReadyToBootEvent; + EFI_EVENT ExitBootServicesEvent; + EFI_STATUS Status; + EfiCreateProtocolNotifyEvent ( &gEfiAcpiTableProtocolGuid, TPL_CALLBACK, @@ -62,5 +127,24 @@ AcpiPlatformDxeInitialize ( &mAcpiRegistration ); + Status = gBS->CreateEvent ( + EVT_SIGNAL_EXIT_BOOT_SERVICES, + TPL_CALLBACK, + UpdateAcpiOnExitBootServices, + NULL, + &ExitBootServicesEvent + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + InstallAcpiOnReadyToBoot, + NULL, + &gEfiEventReadyToBootGuid, + &ReadyToBootEvent + ); + ASSERT_EFI_ERROR(Status); + return EFI_SUCCESS; } diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSLIT.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSLIT.c new file mode 100755 index 000000000000..1b69abf9693b --- /dev/null +++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSLIT.c @@ -0,0 +1,85 @@ +/** @file + + Copyright (c) 2020, Ampere Computing LLC. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "AcpiPlatform.h" + +#define SELF_DISTANCE 10 +#define REMOTE_DISTANCE 20 + +EFI_ACPI_6_3_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_HEADER SLITTableHeaderTemplate = { + __ACPI_HEADER ( + EFI_ACPI_6_3_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE, + 0, /* need fill in */ + EFI_ACPI_6_3_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_REVISION + ), + 0, +}; + +EFI_STATUS +AcpiInstallSlitTable (VOID) +{ + EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol; + EFI_STATUS Status; + UINTN NumDomain, Count, Count1; + EFI_ACPI_6_3_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_HEADER *SlitTablePointer; + UINT8 *TmpPtr; + UINTN SlitTableKey; + UINTN NumDomainPerSocket; + + if (IsAcpiInstalled (EFI_ACPI_6_3_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE)) { + DEBUG ((DEBUG_INFO, "SLIT table is already installed. Skipping...\n")); + return EFI_ABORTED; + } + + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, + NULL, (VOID **) &AcpiTableProtocol); + if (EFI_ERROR (Status)) { + return Status; + } + + NumDomainPerSocket = CPUGetNumOfSubNuma (); + NumDomain = NumDomainPerSocket * GetNumberActiveSockets (); + + SlitTablePointer = (EFI_ACPI_6_3_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_HEADER *) + AllocateZeroPool (sizeof (SLITTableHeaderTemplate) + NumDomain * NumDomain); + if (SlitTablePointer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem ((VOID *) SlitTablePointer, (VOID *) &SLITTableHeaderTemplate, sizeof (SLITTableHeaderTemplate)); + SlitTablePointer->NumberOfSystemLocalities = NumDomain; + TmpPtr = (UINT8 *) SlitTablePointer + sizeof (SLITTableHeaderTemplate); + for (Count = 0; Count < NumDomain; Count++) { + for (Count1 = 0; Count1 < NumDomain; Count1++, TmpPtr++) { + if (Count == Count1) { + *TmpPtr = (UINT8) SELF_DISTANCE; + continue; + } + if ((Count1 / NumDomainPerSocket) == (Count / NumDomainPerSocket)) { + *TmpPtr = (UINT8) (SELF_DISTANCE + 1); + } else { + *TmpPtr = (UINT8) (REMOTE_DISTANCE); + } + } + } + + SlitTablePointer->Header.Length = sizeof (SLITTableHeaderTemplate) + NumDomain * NumDomain; + + AcpiTableChecksum ((UINT8 *) SlitTablePointer, + SlitTablePointer->Header.Length); + + Status = AcpiTableProtocol->InstallAcpiTable ( + AcpiTableProtocol, + (VOID *) SlitTablePointer, + SlitTablePointer->Header.Length, + &SlitTableKey + ); + FreePool ((VOID *) SlitTablePointer); + + return Status; +} + diff --git a/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSRAT.c b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSRAT.c new file mode 100755 index 000000000000..39b6936f6ed0 --- /dev/null +++ b/Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSRAT.c @@ -0,0 +1,268 @@ +/** @file + + Copyright (c) 2020, Ampere Computing LLC. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include "AcpiPlatform.h" + +EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER SRATTableHeaderTemplate = { + __ACPI_HEADER ( + EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE, + 0, /* need fill in */ + EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION + ), + 0x00000001, + 0x0000000000000000, +}; + +EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE GicItsAffinityTemplate = { + .Type = EFI_ACPI_6_3_GIC_ITS_AFFINITY, + sizeof (EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE), + .ProximityDomain = 0, /* ProximityDomain */ + { EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE }, + .ItsId = 0, +}; + +STATIC +UINTN +SratCalculateNumMemoryRegion (VOID) +{ + EFI_GUID PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2; + PlatformInfoHob_V2 *PlatformHob; + UINTN Count; + UINT64 TmpVal; + VOID *Hob; + UINTN Result; + + /* Get the Platform HOB */ + Hob = GetFirstGuidHob (&PlatformHobGuid); + if (Hob == NULL) { + return 0; + } + PlatformHob = (PlatformInfoHob_V2 *) GET_GUID_HOB_DATA (Hob); + + Result = 0; + for (Count = 0; Count < PlatformHob->DramInfo.NumRegion; Count++) { + TmpVal = PlatformHob->DramInfo.Size[Count]; + if (TmpVal > 0) { + Result++; + } + } + + return Result; +} + +STATIC +EFI_STATUS +SratAddMemAffinity ( + EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE *SratMemAffinity + ) +{ + EFI_GUID PlatformHobGuid = PLATFORM_INFO_HOB_GUID_V2; + PlatformInfoHob_V2 *PlatformHob; + UINTN Count, NumRegion; + UINT64 RegionSize, RegionBase; + VOID *Hob; + UINTN ProximityDomain; + + /* Get the Platform HOB */ + Hob = GetFirstGuidHob (&PlatformHobGuid); + if (Hob == NULL) { + return EFI_INVALID_PARAMETER; + } + PlatformHob = (PlatformInfoHob_V2 *) GET_GUID_HOB_DATA (Hob); + + NumRegion = 0; + + for (Count = 0; Count < PlatformHob->DramInfo.NumRegion; Count++) { + RegionSize = PlatformHob->DramInfo.Size[Count]; + RegionBase = PlatformHob->DramInfo.Base[Count]; + ProximityDomain = PlatformHob->DramInfo.Node[Count]; + if (RegionSize > 0) { + ZeroMem ((VOID *) &SratMemAffinity[NumRegion], sizeof (SratMemAffinity[NumRegion])); + SratMemAffinity[NumRegion].Flags = 1; + SratMemAffinity[NumRegion].LengthLow = + (UINT32) (RegionSize & 0xFFFFFFFF); + SratMemAffinity[NumRegion].LengthHigh = + (UINT32) ((RegionSize & 0xFFFFFFFF00000000ULL) >> 32); + SratMemAffinity[NumRegion].AddressBaseLow = + (UINT32) (RegionBase & 0xFFFFFFFF); + SratMemAffinity[NumRegion].AddressBaseHigh = + (UINT32) ((RegionBase & 0xFFFFFFFF00000000ULL) >> 32); + SratMemAffinity[NumRegion].ProximityDomain = (UINT32) (ProximityDomain); + SratMemAffinity[NumRegion].Type = EFI_ACPI_6_3_MEMORY_AFFINITY; + SratMemAffinity[NumRegion].Length = sizeof (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE); + NumRegion++; + } + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SratAddGiccAffinity ( + EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE *SratGiccAffinity + ) +{ + ARM_PROCESSOR_TABLE *ArmProcessorTable; + ARM_CORE_INFO *ArmCoreInfoTable; + UINTN Count, NumNode, Idx; + UINT32 AcpiProcessorUid; + UINT8 Socket; + UINT8 Cpm; + + for (Idx = 0; Idx < gST->NumberOfTableEntries; Idx++) { + if (CompareGuid (&gArmMpCoreInfoGuid, &(gST->ConfigurationTable[Idx].VendorGuid))) { + ArmProcessorTable = (ARM_PROCESSOR_TABLE *) gST->ConfigurationTable[Idx].VendorTable; + ArmCoreInfoTable = ArmProcessorTable->ArmCpus; + break; + } + } + + if (Idx == gST->NumberOfTableEntries) { + return EFI_INVALID_PARAMETER; + } + + Count = 0; + NumNode = 0; + while (Count != ArmProcessorTable->NumberOfEntries) { + for (Idx = 0; Idx < ArmProcessorTable->NumberOfEntries; Idx++ ) { + Socket = ArmCoreInfoTable[Idx].ClusterId; + Cpm = (ArmCoreInfoTable[Idx].CoreId >> PLATFORM_CPM_UID_BIT_OFFSET); + if (CPUGetSubNumNode (Socket, Cpm) != NumNode) { + /* We add nodes based on ProximityDomain order */ + continue; + } + AcpiProcessorUid = (ArmCoreInfoTable[Idx].ClusterId << PLATFORM_SOCKET_UID_BIT_OFFSET) + + ArmCoreInfoTable[Idx].CoreId; + ZeroMem ((VOID *) &SratGiccAffinity[Count], sizeof (SratGiccAffinity[Count])); + SratGiccAffinity[Count].AcpiProcessorUid = AcpiProcessorUid; + SratGiccAffinity[Count].Flags = 1; + SratGiccAffinity[Count].Length = sizeof (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE); + SratGiccAffinity[Count].Type = EFI_ACPI_6_3_GICC_AFFINITY; + SratGiccAffinity[Count].ProximityDomain = CPUGetSubNumNode (Socket, Cpm); + Count++; + } + NumNode++; + } + + return EFI_SUCCESS; +} + +STATIC UINT32 +InstallGicItsAffinity ( + VOID *EntryPointer, + UINT32 Index + ) +{ + EFI_ACPI_6_3_GIC_ITS_AFFINITY_STRUCTURE *ItsAffinityEntryPointer = EntryPointer; + UINTN Size; + + Size = sizeof (GicItsAffinityTemplate); + CopyMem (ItsAffinityEntryPointer, &GicItsAffinityTemplate, Size); + return Size; +} + +STATIC +EFI_STATUS +SratAddGicItsAffinity ( + VOID *TmpPtr + ) +{ + UINTN Size = 0; + UINTN Index; + + /* Install Gic ITSAffinity */ + if (!PlatSlaveSocketPresent ()) { + for (Index = 0; Index <= 1; Index++) { /* RCA0/1 */ + GicItsAffinityTemplate.ItsId = Index; + GicItsAffinityTemplate.ProximityDomain = 0; + Size += InstallGicItsAffinity ((VOID *) ((UINT64) TmpPtr + Size), Index); + } + } + + for (Index = SOCKET0_FIRST_RC; Index <= SOCKET0_LAST_RC; Index++) { + GicItsAffinityTemplate.ItsId = Index; + GicItsAffinityTemplate.ProximityDomain = 0; + Size += InstallGicItsAffinity ((VOID *) ((UINT64) TmpPtr + Size), Index); + } + + if (GetNumberActiveSockets () > 1) { + for (Index = SOCKET1_FIRST_RC; Index <= SOCKET1_LAST_RC; Index++) { + GicItsAffinityTemplate.ItsId = Index; + GicItsAffinityTemplate.ProximityDomain = 1; + Size += InstallGicItsAffinity ((VOID *) ((UINT64) TmpPtr + Size), Index); + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AcpiInstallSratTable (VOID) +{ + EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol; + EFI_STATUS Status; + EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *SratTablePointer; + UINT8 *TmpPtr; + UINTN SratTableKey; + UINTN Size; + + if (IsAcpiInstalled (EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE)) { + DEBUG ((DEBUG_INFO, "SRAT table is already installed. Skipping...\n")); + return EFI_ABORTED; + } + + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, + NULL, (VOID **) &AcpiTableProtocol); + if (EFI_ERROR (Status)) { + return Status; + } + + Size = sizeof (SRATTableHeaderTemplate) + + SratCalculateNumMemoryRegion () * sizeof (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE) + + GetNumberActiveCores () * sizeof (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE) + + ((SOCKET0_LAST_RC - SOCKET0_FIRST_RC + 1) * sizeof (GicItsAffinityTemplate)); + if (GetNumberActiveSockets () > 1) { + Size += (SOCKET1_LAST_RC - SOCKET1_FIRST_RC + 1) * sizeof (GicItsAffinityTemplate); + } else if (!PlatSlaveSocketPresent ()){ + Size += 2 * sizeof(GicItsAffinityTemplate); /* RCA0/1 */ + } + + SratTablePointer = (EFI_ACPI_6_3_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER *) AllocateZeroPool (Size); + if (SratTablePointer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem ((VOID *) SratTablePointer, (VOID *) &SRATTableHeaderTemplate, sizeof (SRATTableHeaderTemplate)); + + TmpPtr = (UINT8 *) SratTablePointer + sizeof (SRATTableHeaderTemplate); + Status = SratAddMemAffinity ((EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE *) TmpPtr); + ASSERT_EFI_ERROR (Status); + + TmpPtr += SratCalculateNumMemoryRegion () * sizeof (EFI_ACPI_6_3_MEMORY_AFFINITY_STRUCTURE); + Status = SratAddGiccAffinity ((EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE *) TmpPtr); + ASSERT_EFI_ERROR (Status); + + TmpPtr += GetNumberActiveCores () * sizeof (EFI_ACPI_6_3_GICC_AFFINITY_STRUCTURE); + SratAddGicItsAffinity ((VOID*) (UINT64) TmpPtr); + SratTablePointer->Header.Length = Size; + + AcpiTableChecksum ((UINT8 *) SratTablePointer, + SratTablePointer->Header.Length); + + Status = AcpiTableProtocol->InstallAcpiTable ( + AcpiTableProtocol, + (VOID *) SratTablePointer, + SratTablePointer->Header.Length, + &SratTableKey + ); + FreePool ((VOID *) SratTablePointer); + + return Status; +} + -- 2.17.1