2020年5月13日 星期三

Sleep State Flow

先了解一下OSPM, _PTS, _WAK之間的flow。

Transitioning from the Working to the Sleeping State

  1. OSPM決定要進入sleeping state(S1, S2, S3, S4),這邊可以是你自己按的也可以是一些電源選項達成。
  2. OSPM會去call ACPI裡面的_TTS(Transition to State)看是要進到哪個sleeping state。
  3. 接著OSPM會去call device的_PRW(Power Resources to Wake)去確認有哪些device可以叫醒系統。
  4. OSPM要把所有device放進相對的sleeping state,可以wake的device就進到Dx state,反之進D3。
  5. OSPM call _PTS(Prepare to Sleep),_PTS在做什麼根據platform不同就會有所差異,主要就是傳遞現在要進哪個state,有些platform會在這邊把wake的enable起來還有把status清乾淨。
  6. OSPM會把其他processor的data存進memory。
  7. OSPM把waking vector放進FACS table裡。
  8. Clear WAK_STS in PM1a_STS(bit15),準備之後可以正常wake。
  9. 這時候才把local processor的data存進memory裡,如果是S1, S2, S3的話就會把caches清掉。
  10. OSPM會把GPE 或是其他可以wake的中斷enable起來。
  11. 如果是S4的話,OSPM會把S4BIOS_REQ寫進SMI_CMD port。
  12. 不是的話,OSPM會去填PM1a_CNT裡面的SLP_TYPx和SLP_EN。
  13. SLP_EN設起來以後就是HW的事情了。

Transitioning from the Working to the Soft Off State

  1. OSPM call _PTS傳遞即將進入S5。
  2. OSPM把所有的device關掉
  3. OSPM填SLP_TYP和SLP_EN設起來就進S5了。

接下來是wake起來後的flow

上面兩張圖是wake起來以後走的路線,現在總算知道S3起來以後會走到Waking Vector,Waking Vector是什麼呢?
Waking Vector是在系統要睡下去的時候,OSPM會寫進FACS(Firmware ACPI Control Structure)裡面的Byte Offset=12的位置。
--------------------------------------------------------------------------------------------------------------------
Field        | Byte Length | Byte Offset | Description                                                                          
--------------------------------------------------------------------------------------------------------------------
Firmware | 4                  | 12                | Before transitioning the system into a global sleeping 
Waking    |                     |                     | state, OSPM fills this field with the physical memory 
Vector      |                     |                     | address of an OS-specific wake function. If this is
                 |                    |                     |  non-zero, transfers control to the specified address.
---------------------------------------------------------------------------------------------------------------------
從code來看的話,當POST跑到最後一個PEIM也就是DxeLoadCore的時候
/**
   Main entry point to last PEIM.

   This function finds DXE Core in the firmware volume and transfer the control to
   DXE core.

**/
EFI_STATUS
EFIAPI
DxeLoadCore (
  IN CONST EFI_DXE_IPL_PPI *This,
  IN EFI_PEI_SERVICES      **PeiServices,
  IN EFI_PEI_HOB_POINTERS  HobList
  )
這裡面會去看BootMode是不是S3, Recovery Mode, Capsule Update,如果是S3的話就走S3的路,
最後會走到
      //
      // IA32 protected mode waking vector (Page disabled)
      //
      DEBUG ((DEBUG_INFO, "Transfer to 32bit OS waking vector - %x\r\n", (UINTN)Facs->XFirmwareWakingVector));
      SwitchStack (
        (SWITCH_STACK_ENTRY_POINT) (UINTN) Facs->XFirmwareWakingVector,
        NULL,
        NULL,
        (VOID *)(UINTN)TempStackTop
        );
這個SwitchStack的功能就是轉交控制權。
回到OS以後才要call _WAK(System Wake),其實就是做跟_PTS相反的事情,然後還要把剛剛睡下去的device叫醒,
  Case (43) { // interrupt 43
            Store(One, ISTS) // clear interrupt status register at device X
            // which is mapped via an operation region
            Notify (\_SB.DEVX0x2// wake event
            } 
Notify的第一個param是device,第二個是要notify什麼,這邊0x2是Device Wake. 
Device Wake : Used to notify that the device has signaled its wake event,and that OSPM needs to notify OSPM native device for the device.
This is only used for devices that support _PRW.
Notify完了以後,OS應該就會去把device和driver串起來了。

沒有留言:

張貼留言