UEFI non-blocking StartupThisAP for EFI_MP_SERVICES_PROTOCOL
Posted: Wed Nov 24, 2021 4:33 am
I am building a UEFI application that needs to execute instructions on two parallel cores concurrently.
I am using StartupThisAP in EFI_MP_SERVICES_PROTOCOL to wake up the second core to execute a given function.
Per my understanding of UEFI specification (https://uefi.org/sites/default/files/re ... ec_1_6.pdf page 485) the WaitEvent parameter of StartupThisAP in EFI_MP_SERVICES_PROTOCOL should set the execution of the Procedure to the non-blocking mode when set to not null:
However, I always observe the two cores executing sequentially, with the BSP core waiting for the termination of the AP. Am I using the API wrong?
I attach the code of the minimized UEFI application. It is launched from the UEFI shell, by simply executing it.
Am I not allowed to use EFI_MP_SERVICES_PROTOCOL in such a setup?
I am using gnu-efi to build the application, and I'm using a custom header to provide definitions for EFI_MP_SERVICES_PROTOCOL, which I did not find among the ones provided by gnu-efi.
The example function that is run in the AP is calling BootServices and issuing prints, I know in theory it is not MP safe, but this is an easy way to show if they are executing in parallel or not.
What I observe is always all the prints from the AP core being issued before the ones from BSP, never interleaved. I also print the core ID to be sure that the function is actually executed from the second core.
The platform is an x86-64 Intel CPU with two cores, two threads, with no hyperthreading support.
I also tried to use atomic variables to block the AP core on a polling loop until the BSP signals it to start, but this just breaks into a deadlock since the BSP is blocked until the AP finishes.
I am using StartupThisAP in EFI_MP_SERVICES_PROTOCOL to wake up the second core to execute a given function.
Per my understanding of UEFI specification (https://uefi.org/sites/default/files/re ... ec_1_6.pdf page 485) the WaitEvent parameter of StartupThisAP in EFI_MP_SERVICES_PROTOCOL should set the execution of the Procedure to the non-blocking mode when set to not null:
Code: Select all
EFI_EVENT Event = 0;
status = uefi_call_wrapper(BS->CreateEvent, 5, 0, TPL_NOTIFY, NULL, NULL, &Event);
if(EFI_ERROR(status) || !Event) {
Print(L"[-] Failed to create event\n");
return EFI_SUCCESS;
}
status = uefi_call_wrapper(mp->StartupThisAP, 7, mp, SMP_function, CORE1, Event, 0, (VOID*) NULL, NULL);
if(EFI_ERROR(status)) {
Print(L"[-] Failed to spawn SMP\n");
return EFI_SUCCESS;
}
I attach the code of the minimized UEFI application. It is launched from the UEFI shell, by simply executing it.
Am I not allowed to use EFI_MP_SERVICES_PROTOCOL in such a setup?
I am using gnu-efi to build the application, and I'm using a custom header to provide definitions for EFI_MP_SERVICES_PROTOCOL, which I did not find among the ones provided by gnu-efi.
The example function that is run in the AP is calling BootServices and issuing prints, I know in theory it is not MP safe, but this is an easy way to show if they are executing in parallel or not.
What I observe is always all the prints from the AP core being issued before the ones from BSP, never interleaved. I also print the core ID to be sure that the function is actually executed from the second core.
Code: Select all
Hello from SMP: 1
Hello from SMP: 1
Hello from SMP: 1
[...]
Hello from SMP: 1
Hello from BSP: 0
Hello from BSP: 0
[...]
Hello from BSP: 0
I also tried to use atomic variables to block the AP core on a polling loop until the BSP signals it to start, but this just breaks into a deadlock since the BSP is blocked until the AP finishes.