diff options
-rw-r--r-- | InOsEmuPkg/CpuRuntimeDxe/Cpu.c | 33 | ||||
-rw-r--r-- | InOsEmuPkg/CpuRuntimeDxe/Cpu.inf | 3 | ||||
-rw-r--r-- | InOsEmuPkg/CpuRuntimeDxe/CpuDriver.h | 1 | ||||
-rw-r--r-- | InOsEmuPkg/Include/Protocol/EmuThunk.h | 7 | ||||
-rw-r--r-- | InOsEmuPkg/Unix/Sec/EmuThunk.c | 17 | ||||
-rw-r--r-- | InOsEmuPkg/Unix/Sec/Gasket.h | 6 | ||||
-rw-r--r-- | InOsEmuPkg/Unix/Sec/X11GraphicsWindow.c | 63 | ||||
-rw-r--r-- | InOsEmuPkg/Unix/Sec/X64/Gasket.S | 16 |
8 files changed, 104 insertions, 42 deletions
diff --git a/InOsEmuPkg/CpuRuntimeDxe/Cpu.c b/InOsEmuPkg/CpuRuntimeDxe/Cpu.c index 472b1c3b73..5ec315bea2 100644 --- a/InOsEmuPkg/CpuRuntimeDxe/Cpu.c +++ b/InOsEmuPkg/CpuRuntimeDxe/Cpu.c @@ -305,6 +305,27 @@ CpuUpdateSmbios ( 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
EFIAPI
InitializeCpu (
@@ -314,6 +335,7 @@ InitializeCpu ( {
EFI_STATUS Status;
UINT64 Frequency;
+ EFI_EVENT IdleLoopEvent;
//
// Retrieve the frequency of the performance counter in Hz.
@@ -328,6 +350,17 @@ InitializeCpu ( CpuUpdateSmbios ();
CpuMpServicesInit ();
+
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ IdleLoopEventCallback,
+ NULL,
+ &gIdleLoopEventGuid,
+ &IdleLoopEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
Status = gBS->InstallMultipleProtocolInterfaces (
&mCpuTemplate.Handle,
diff --git a/InOsEmuPkg/CpuRuntimeDxe/Cpu.inf b/InOsEmuPkg/CpuRuntimeDxe/Cpu.inf index 6fc240c907..d548c8a41a 100644 --- a/InOsEmuPkg/CpuRuntimeDxe/Cpu.inf +++ b/InOsEmuPkg/CpuRuntimeDxe/Cpu.inf @@ -66,6 +66,9 @@ gEmuThreadThunkProtocolGuid
gEfiMpServiceProtocolGuid
+[Guids]
+ gIdleLoopEventGuid ## CONSUMES ## GUID
+
[Pcd]
gInOsEmuPkgTokenSpaceGuid.PcdEmuMpServicesPollingInterval
diff --git a/InOsEmuPkg/CpuRuntimeDxe/CpuDriver.h b/InOsEmuPkg/CpuRuntimeDxe/CpuDriver.h index 3ef251101f..69505ff0e4 100644 --- a/InOsEmuPkg/CpuRuntimeDxe/CpuDriver.h +++ b/InOsEmuPkg/CpuRuntimeDxe/CpuDriver.h @@ -28,6 +28,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include <Protocol/CpuIo2.h>
#include <Guid/DataHubRecords.h>
+#include <Guid/IdleLoopEvent.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
diff --git a/InOsEmuPkg/Include/Protocol/EmuThunk.h b/InOsEmuPkg/Include/Protocol/EmuThunk.h index 3e2718ed66..ed4df3a942 100644 --- a/InOsEmuPkg/Include/Protocol/EmuThunk.h +++ b/InOsEmuPkg/Include/Protocol/EmuThunk.h @@ -130,6 +130,12 @@ VOID typedef
VOID
+(EFIAPI *EMU_CPU_SLEEP) (
+ VOID
+ );
+
+typedef
+VOID
(EFIAPI *EMU_EXIT) (
IN UINTN Status
);
@@ -215,6 +221,7 @@ struct _EMU_THUNK_PROTOCOL { EMU_QUERY_PERFORMANCE_COUNTER QueryPerformanceCounter;
EMU_SLEEP Sleep;
+ EMU_CPU_SLEEP CpuSleep;
EMU_EXIT Exit;
EMU_GET_TIME GetTime;
EMU_SET_TIME SetTime;
diff --git a/InOsEmuPkg/Unix/Sec/EmuThunk.c b/InOsEmuPkg/Unix/Sec/EmuThunk.c index 579f67fa1a..ca8be55a0f 100644 --- a/InOsEmuPkg/Unix/Sec/EmuThunk.c +++ b/InOsEmuPkg/Unix/Sec/EmuThunk.c @@ -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 SecExit ( UINTN Status @@ -362,6 +378,7 @@ EMU_THUNK_PROTOCOL gEmuThunkProtocol = { GasketQueryPerformanceFrequency, GasketQueryPerformanceCounter, GasketSecSleep, + GasketSecCpuSleep, GasketSecExit, GasketSecGetTime, GasketSecSetTime, diff --git a/InOsEmuPkg/Unix/Sec/Gasket.h b/InOsEmuPkg/Unix/Sec/Gasket.h index 2234bbe8c6..0862b2c9ac 100644 --- a/InOsEmuPkg/Unix/Sec/Gasket.h +++ b/InOsEmuPkg/Unix/Sec/Gasket.h @@ -108,6 +108,12 @@ VOID EFIAPI
GasketSecSleep (
IN UINT64 Milliseconds
+
+ );
+VOID
+EFIAPI
+GasketSecCpuSleep (
+ VOID
);
VOID
diff --git a/InOsEmuPkg/Unix/Sec/X11GraphicsWindow.c b/InOsEmuPkg/Unix/Sec/X11GraphicsWindow.c index 72c4544ce5..10c591d403 100644 --- a/InOsEmuPkg/Unix/Sec/X11GraphicsWindow.c +++ b/InOsEmuPkg/Unix/Sec/X11GraphicsWindow.c @@ -624,24 +624,6 @@ X11ColorToPixel ( 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 X11CheckKey ( @@ -652,7 +634,13 @@ X11CheckKey ( 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 @@ -667,7 +655,7 @@ X11GetKey ( Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo; - EfiStatus = CheckKeyInternal (Drv, FALSE); + EfiStatus = X11CheckKey (GraphicsIo); if (EFI_ERROR (EfiStatus)) { return EfiStatus; } @@ -879,24 +867,6 @@ X11Blt ( 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 X11CheckPointer ( @@ -907,23 +877,32 @@ X11CheckPointer ( 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 -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; GRAPHICS_IO_PRIVATE *Drv; Drv = (GRAPHICS_IO_PRIVATE *)GraphicsIo; - EfiStatus = CheckPointerInternal (Drv, FALSE); + EfiStatus = X11CheckPointer (GraphicsIo); if (EfiStatus != EFI_SUCCESS) { 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.RelativeMovementY = 0; diff --git a/InOsEmuPkg/Unix/Sec/X64/Gasket.S b/InOsEmuPkg/Unix/Sec/X64/Gasket.S index a51807ab47..d30aed617b 100644 --- a/InOsEmuPkg/Unix/Sec/X64/Gasket.S +++ b/InOsEmuPkg/Unix/Sec/X64/Gasket.S @@ -227,6 +227,22 @@ ASM_PFX(GasketSecSleep): 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_PFX(GasketSecExit): pushq %rbp // stack frame is for the debugger |