From: Leif Lindholm <leif.lindholm@linaro.org>
To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: edk2-devel@lists.01.org, marc.zyngier@arm.com
Subject: Re: [PATCH] ArmPkg/Gic: force GIC driver to run before CPU arch protocol driver
Date: Tue, 6 Feb 2018 13:01:16 +0000 [thread overview]
Message-ID: <20180206130116.ejxc3f2djg6y3dtm@bivouac.eciton.net> (raw)
In-Reply-To: <20180206120416.17462-1-ard.biesheuvel@linaro.org>
On Tue, Feb 06, 2018 at 12:04:16PM +0000, Ard Biesheuvel wrote:
> Currently, the GIC driver has a static dependency on the CPU arch protocol
> driver, so it can register its IRQ handler at init time. This means there
> is a window between dispatch of the CPU driver and dispatch of the GIC
> driver where any unexpected GIC state may trigger an interrupt which we
> are not set up to handle yet. Note that this is even the case if we enter
> UEFI with interrupts disabled at the CPU, given that any TPL manipulation
> involving TPL_HIGH_LEVEL will unconditionally enable IRQs at the CPU side
> regardless of whether they were enabled to begin with (but only as soon as
> the CPU arch protocol is actually installed)
>
> So let's reorder the GIC driver with the CPU driver, and let it run its
> initialization that puts the GIC into a known state before enabling
> interrupts. Move its installation of its IRQ handler to a protocol notify
> callback on the CPU arch protocol so that it runs as soon as it becomes
> available.
>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
> ---
>
> This fixes an issue observed with GICv3 guests running under KVM.
>
> ArmPkg/ArmPkg.dec | 2 +
> ArmPkg/Drivers/ArmGic/ArmGicCommonDxe.c | 69 +++++++++++++-------
> ArmPkg/Drivers/ArmGic/ArmGicDxe.h | 1 +
> ArmPkg/Drivers/ArmGic/ArmGicDxe.inf | 5 +-
> ArmPkg/Drivers/CpuDxe/CpuDxe.inf | 2 +-
> 5 files changed, 54 insertions(+), 25 deletions(-)
>
> diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec
> index 5dbd019e2966..a55b6268ff85 100644
> --- a/ArmPkg/ArmPkg.dec
> +++ b/ArmPkg/ArmPkg.dec
> @@ -48,6 +48,8 @@ [Guids.common]
> # Include/Guid/ArmMpCoreInfo.h
> gArmMpCoreInfoGuid = { 0xa4ee0728, 0xe5d7, 0x4ac5, {0xb2, 0x1e, 0x65, 0x8e, 0xd8, 0x57, 0xe8, 0x34} }
>
> + gArmGicDxeFileGuid = { 0xde371f7c, 0xdec4, 0x4d21, { 0xad, 0xf1, 0x59, 0x3a, 0xbc, 0xc1, 0x58, 0x82 } }
> +
> [Ppis]
> ## Include/Ppi/ArmMpCoreInfo.h
> gArmMpCoreInfoPpiGuid = { 0x6847cc74, 0xe9ec, 0x4f8f, {0xa2, 0x9d, 0xab, 0x44, 0xe7, 0x54, 0xa8, 0xfc} }
> diff --git a/ArmPkg/Drivers/ArmGic/ArmGicCommonDxe.c b/ArmPkg/Drivers/ArmGic/ArmGicCommonDxe.c
> index bff8d983cf02..e1adcd3bc6d3 100644
> --- a/ArmPkg/Drivers/ArmGic/ArmGicCommonDxe.c
> +++ b/ArmPkg/Drivers/ArmGic/ArmGicCommonDxe.c
> @@ -121,6 +121,44 @@ RegisterInterruptSource (
> }
> }
>
> +STATIC VOID *mCpuArchProtocolNotifyEventRegistration;
> +
> +STATIC
> +VOID
> +EFIAPI
> +CpuArchEventProtocolNotify (
> + IN EFI_EVENT Event,
> + IN VOID *Context
> + )
> +{
> + EFI_CPU_ARCH_PROTOCOL *Cpu;
> + EFI_STATUS Status;
> +
> + // Get the CPU protocol that this driver requires.
> + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
> + if (EFI_ERROR (Status)) {
> + return;
> + }
> +
> + // Unregister the default exception handler.
> + Status = Cpu->RegisterInterruptHandler (Cpu, ARM_ARCH_EXCEPTION_IRQ, NULL);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "%a: Cpu->RegisterInterruptHandler() - %r\n",
> + __FUNCTION__, Status));
> + return;
> + }
> +
> + // Register to receive interrupts
> + Status = Cpu->RegisterInterruptHandler (Cpu, ARM_ARCH_EXCEPTION_IRQ,
> + Context);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "%a: Cpu->RegisterInterruptHandler() - %r\n",
> + __FUNCTION__, Status));
> + }
> +
> + gBS->CloseEvent (Event);
> +}
> +
> EFI_STATUS
> InstallAndRegisterInterruptService (
> IN EFI_HARDWARE_INTERRUPT_PROTOCOL *InterruptProtocol,
> @@ -130,7 +168,6 @@ InstallAndRegisterInterruptService (
> )
> {
> EFI_STATUS Status;
> - EFI_CPU_ARCH_PROTOCOL *Cpu;
> CONST UINTN RihArraySize =
> (sizeof(HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts);
>
> @@ -152,27 +189,15 @@ InstallAndRegisterInterruptService (
> return Status;
> }
>
> - // Get the CPU protocol that this driver requires.
> - Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
> - if (EFI_ERROR (Status)) {
> - return Status;
> - }
> -
> - // Unregister the default exception handler.
> - Status = Cpu->RegisterInterruptHandler (Cpu, ARM_ARCH_EXCEPTION_IRQ, NULL);
> - if (EFI_ERROR (Status)) {
> - return Status;
> - }
> -
> - // Register to receive interrupts
> - Status = Cpu->RegisterInterruptHandler (
> - Cpu,
> - ARM_ARCH_EXCEPTION_IRQ,
> - InterruptHandler
> - );
> - if (EFI_ERROR (Status)) {
> - return Status;
> - }
> + //
> + // Install the interrupt handler as soon as the CPU arch protocol appears.
> + //
> + EfiCreateProtocolNotifyEvent (
> + &gEfiCpuArchProtocolGuid,
> + TPL_CALLBACK,
> + CpuArchEventProtocolNotify,
> + InterruptHandler,
> + &mCpuArchProtocolNotifyEventRegistration);
>
> // Register for an ExitBootServicesEvent
> Status = gBS->CreateEvent (
> diff --git a/ArmPkg/Drivers/ArmGic/ArmGicDxe.h b/ArmPkg/Drivers/ArmGic/ArmGicDxe.h
> index 610ffacc7eb0..f6b75d729601 100644
> --- a/ArmPkg/Drivers/ArmGic/ArmGicDxe.h
> +++ b/ArmPkg/Drivers/ArmGic/ArmGicDxe.h
> @@ -21,6 +21,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> #include <Library/IoLib.h>
> #include <Library/MemoryAllocationLib.h>
> #include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiLib.h>
>
> #include <Protocol/Cpu.h>
> #include <Protocol/HardwareInterrupt.h>
> diff --git a/ArmPkg/Drivers/ArmGic/ArmGicDxe.inf b/ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
> index d5921533fb68..24b02ef30e83 100644
> --- a/ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
> +++ b/ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
> @@ -16,7 +16,7 @@
> [Defines]
> INF_VERSION = 0x00010005
> BASE_NAME = ArmGicDxe
> - FILE_GUID = DE371F7C-DEC4-4D21-ADF1-593ABCC15882
> + FILE_GUID = DE371F7C-DEC4-4D21-ADF1-593ABCC15882 # gArmGicDxeFileGuid
> MODULE_TYPE = DXE_DRIVER
> VERSION_STRING = 1.0
>
> @@ -45,6 +45,7 @@ [LibraryClasses]
> UefiDriverEntryPoint
> IoLib
> PcdLib
> + UefiLib
>
> [Protocols]
> gHardwareInterruptProtocolGuid
> @@ -58,4 +59,4 @@ [Pcd.common]
> gArmTokenSpaceGuid.PcdArmGicV3WithV2Legacy
>
> [Depex]
> - gEfiCpuArchProtocolGuid
> + TRUE
> diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf
> index d068e06803ed..cda549922e9c 100644
> --- a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf
> +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf
> @@ -76,4 +76,4 @@ [FeaturePcd.common]
> gArmTokenSpaceGuid.PcdDebuggerExceptionSupport
>
> [Depex]
> - TRUE
> + AFTER gArmGicDxeFileGuid
> --
> 2.11.0
>
next prev parent reply other threads:[~2018-02-06 12:55 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-02-06 12:04 [PATCH] ArmPkg/Gic: force GIC driver to run before CPU arch protocol driver Ard Biesheuvel
2018-02-06 13:01 ` Leif Lindholm [this message]
2018-02-06 14:55 ` Marc Zyngier
2018-02-06 19:01 ` Ard Biesheuvel
2018-03-21 13:15 ` Shannon Zhao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180206130116.ejxc3f2djg6y3dtm@bivouac.eciton.net \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox