\r
#include "SnpPageStateChange.h"\r
\r
+//\r
+// The variable used for the VMPL check.\r
+//\r
+STATIC UINT8 gVmpl0Data[4096];\r
+\r
+/**\r
+ The function checks whether SEV-SNP guest is booted under VMPL0.\r
+\r
+ @retval TRUE The guest is booted under VMPL0\r
+ @retval FALSE The guest is not booted under VMPL0\r
+ **/\r
+STATIC\r
+BOOLEAN\r
+SevSnpIsVmpl0 (\r
+ VOID\r
+ )\r
+{\r
+ UINT64 Rdx;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // There is no straightforward way to query the current VMPL level.\r
+ // The simplest method is to use the RMPADJUST instruction to change\r
+ // a page permission to a VMPL level-1, and if the guest kernel is\r
+ // launched at a level <= 1, then RMPADJUST instruction will return\r
+ // an error.\r
+ //\r
+ Rdx = 1;\r
+\r
+ Status = AsmRmpAdjust ((UINT64)gVmpl0Data, 0, Rdx);\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
/**\r
Pre-validate the system RAM when SEV-SNP is enabled in the guest VM.\r
\r
return;\r
}\r
\r
+ //\r
+ // The page state change uses the PVALIDATE instruction. The instruction\r
+ // can be run on VMPL-0 only. If its not VMPL-0 guest then terminate\r
+ // the boot.\r
+ //\r
+ if (!SevSnpIsVmpl0 ()) {\r
+ SnpPageStateFailureTerminate ();\r
+ }\r
+\r
InternalSetPageState (BaseAddress, NumPages, SevSnpPagePrivate, TRUE);\r
}\r