InOsEmuPkg: Implement gIdleLoopEventGuid.

Added a CpuSleep () API to the Emulator Thunk. We needed to do this as the Stall() works hard to not get broken by the timer tic (POSIX signal). nanosleep() gets interrupted by the timer signal so it is a good emulator of a CpuSleep(); I was also able to remove some stalls in the X11 keyboard and mouse checking events, now that the gIdleLoopEventGuid was added.

Signed-off-by: andrewfish



git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11846 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
andrewfish 2011-06-17 18:21:16 +00:00
parent d8387fa4af
commit 57c7d70ff9
8 changed files with 104 additions and 42 deletions

View File

@ -305,6 +305,27 @@ CpuUpdateSmbios (
FreePool (SmbiosRecord); FreePool (SmbiosRecord);
} }
/**
Callback function for idle events.
@param Event Event whose notification function is being invoked.
@param Context The pointer to the notification function's context,
which is implementation-dependent.
**/
VOID
EFIAPI
IdleLoopEventCallback (
IN EFI_EVENT Event,
IN VOID *Context
)
{
gEmuThunk->CpuSleep ();
}
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
InitializeCpu ( InitializeCpu (
@ -314,6 +335,7 @@ InitializeCpu (
{ {
EFI_STATUS Status; EFI_STATUS Status;
UINT64 Frequency; UINT64 Frequency;
EFI_EVENT IdleLoopEvent;
// //
// Retrieve the frequency of the performance counter in Hz. // Retrieve the frequency of the performance counter in Hz.
@ -329,6 +351,17 @@ InitializeCpu (
CpuMpServicesInit (); CpuMpServicesInit ();
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
IdleLoopEventCallback,
NULL,
&gIdleLoopEventGuid,
&IdleLoopEvent
);
ASSERT_EFI_ERROR (Status);
Status = gBS->InstallMultipleProtocolInterfaces ( Status = gBS->InstallMultipleProtocolInterfaces (
&mCpuTemplate.Handle, &mCpuTemplate.Handle,
&gEfiCpuArchProtocolGuid, &mCpuTemplate.Cpu, &gEfiCpuArchProtocolGuid, &mCpuTemplate.Cpu,

View File

@ -66,6 +66,9 @@
gEmuThreadThunkProtocolGuid gEmuThreadThunkProtocolGuid
gEfiMpServiceProtocolGuid gEfiMpServiceProtocolGuid
[Guids]
gIdleLoopEventGuid ## CONSUMES ## GUID
[Pcd] [Pcd]
gInOsEmuPkgTokenSpaceGuid.PcdEmuMpServicesPollingInterval gInOsEmuPkgTokenSpaceGuid.PcdEmuMpServicesPollingInterval

View File

@ -28,6 +28,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/CpuIo2.h> #include <Protocol/CpuIo2.h>
#include <Guid/DataHubRecords.h> #include <Guid/DataHubRecords.h>
#include <Guid/IdleLoopEvent.h>
#include <Library/BaseLib.h> #include <Library/BaseLib.h>
#include <Library/DebugLib.h> #include <Library/DebugLib.h>

View File

@ -128,6 +128,12 @@ VOID
IN UINT64 Milliseconds IN UINT64 Milliseconds
); );
typedef
VOID
(EFIAPI *EMU_CPU_SLEEP) (
VOID
);
typedef typedef
VOID VOID
(EFIAPI *EMU_EXIT) ( (EFIAPI *EMU_EXIT) (
@ -215,6 +221,7 @@ struct _EMU_THUNK_PROTOCOL {
EMU_QUERY_PERFORMANCE_COUNTER QueryPerformanceCounter; EMU_QUERY_PERFORMANCE_COUNTER QueryPerformanceCounter;
EMU_SLEEP Sleep; EMU_SLEEP Sleep;
EMU_CPU_SLEEP CpuSleep;
EMU_EXIT Exit; EMU_EXIT Exit;
EMU_GET_TIME GetTime; EMU_GET_TIME GetTime;
EMU_SET_TIME SetTime; EMU_SET_TIME SetTime;

View File

@ -286,6 +286,22 @@ SecSleep (
} }
} }
VOID
SecCpuSleep (
VOID
)
{
struct timespec rq, rm;
// nanosleep gets interrupted by the timer tic
rq.tv_sec = 1;
rq.tv_nsec = 0;
nanosleep (&rq, &rm);
}
VOID VOID
SecExit ( SecExit (
UINTN Status UINTN Status
@ -362,6 +378,7 @@ EMU_THUNK_PROTOCOL gEmuThunkProtocol = {
GasketQueryPerformanceFrequency, GasketQueryPerformanceFrequency,
GasketQueryPerformanceCounter, GasketQueryPerformanceCounter,
GasketSecSleep, GasketSecSleep,
GasketSecCpuSleep,
GasketSecExit, GasketSecExit,
GasketSecGetTime, GasketSecGetTime,
GasketSecSetTime, GasketSecSetTime,

View File

@ -108,6 +108,12 @@ VOID
EFIAPI EFIAPI
GasketSecSleep ( GasketSecSleep (
IN UINT64 Milliseconds IN UINT64 Milliseconds
);
VOID
EFIAPI
GasketSecCpuSleep (
VOID
); );
VOID VOID

View File

@ -624,24 +624,6 @@ X11ColorToPixel (
return Pixel; return Pixel;
} }
EFI_STATUS
CheckKeyInternal (
IN GRAPHICS_IO_PRIVATE *Drv,
IN BOOLEAN delay
)
{
HandleEvents (Drv);
if (Drv->key_count != 0) {
return EFI_SUCCESS;
}
if (delay) {
// EFI is polling. Be CPU-friendly.
SecSleep (20);
}
return EFI_NOT_READY;
}
EFI_STATUS EFI_STATUS
X11CheckKey ( X11CheckKey (
@ -652,7 +634,13 @@ X11CheckKey (
Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo; Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;
return CheckKeyInternal (Drv, TRUE); HandleEvents (Drv);
if (Drv->key_count != 0) {
return EFI_SUCCESS;
}
return EFI_NOT_READY;
} }
EFI_STATUS EFI_STATUS
@ -667,7 +655,7 @@ X11GetKey (
Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo; Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;
EfiStatus = CheckKeyInternal (Drv, FALSE); EfiStatus = X11CheckKey (GraphicsIo);
if (EFI_ERROR (EfiStatus)) { if (EFI_ERROR (EfiStatus)) {
return EfiStatus; return EfiStatus;
} }
@ -879,24 +867,6 @@ X11Blt (
return EFI_SUCCESS; return EFI_SUCCESS;
} }
EFI_STATUS
CheckPointerInternal (
IN GRAPHICS_IO_PRIVATE *Drv,
IN BOOLEAN delay
)
{
HandleEvents (Drv);
if (Drv->pointer_state_changed != 0) {
return EFI_SUCCESS;
}
if ( delay ) {
// EFI is polling. Be CPU-friendly.
SecSleep (20);
}
return EFI_NOT_READY;
}
EFI_STATUS EFI_STATUS
X11CheckPointer ( X11CheckPointer (
@ -907,23 +877,32 @@ X11CheckPointer (
Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo; Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;
return CheckPointerInternal (Drv, TRUE); HandleEvents (Drv);
if (Drv->pointer_state_changed != 0) {
return EFI_SUCCESS;
} }
return EFI_NOT_READY;
}
EFI_STATUS EFI_STATUS
X11GetPointerState (EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo, EFI_SIMPLE_POINTER_STATE *state) X11GetPointerState (
IN EMU_GRAPHICS_WINDOW_PROTOCOL *GraphicsIo,
IN EFI_SIMPLE_POINTER_STATE *State
)
{ {
EFI_STATUS EfiStatus; EFI_STATUS EfiStatus;
GRAPHICS_IO_PRIVATE *Drv; GRAPHICS_IO_PRIVATE *Drv;
Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo; Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo;
EfiStatus = CheckPointerInternal (Drv, FALSE); EfiStatus = X11CheckPointer (GraphicsIo);
if (EfiStatus != EFI_SUCCESS) { if (EfiStatus != EFI_SUCCESS) {
return EfiStatus; return EfiStatus;
} }
memcpy (state, &Drv->pointer_state, sizeof (EFI_SIMPLE_POINTER_STATE)); memcpy (State, &Drv->pointer_state, sizeof (EFI_SIMPLE_POINTER_STATE));
Drv->pointer_state.RelativeMovementX = 0; Drv->pointer_state.RelativeMovementX = 0;
Drv->pointer_state.RelativeMovementY = 0; Drv->pointer_state.RelativeMovementY = 0;

View File

@ -227,6 +227,22 @@ ASM_PFX(GasketSecSleep):
ret ret
ASM_GLOBAL ASM_PFX(GasketSecCpuSleep)
ASM_PFX(GasketSecCpuSleep):
pushq %rbp // stack frame is for the debugger
movq %rsp, %rbp
pushq %rsi // %rsi & %rdi are volatile in Unix and callee-save in EFI ABI
pushq %rdi
call ASM_PFX(SecCpuSleep)
popq %rdi // restore state
popq %rsi
popq %rbp
ret
ASM_GLOBAL ASM_PFX(GasketSecExit) ASM_GLOBAL ASM_PFX(GasketSecExit)
ASM_PFX(GasketSecExit): ASM_PFX(GasketSecExit):
pushq %rbp // stack frame is for the debugger pushq %rbp // stack frame is for the debugger