1b44d84daSMao, Junjie /* Basic PCID & INVPCID functionality test */ 2b44d84daSMao, Junjie 3b44d84daSMao, Junjie #include "libcflat.h" 4b44d84daSMao, Junjie #include "processor.h" 5b44d84daSMao, Junjie #include "desc.h" 6b44d84daSMao, Junjie 7b44d84daSMao, Junjie struct invpcid_desc { 8*fb0e760aSZhenzhong Duan u64 pcid : 12; 9*fb0e760aSZhenzhong Duan u64 rsv : 52; 10*fb0e760aSZhenzhong Duan u64 addr : 64; 11b44d84daSMao, Junjie }; 12b44d84daSMao, Junjie 13db4898e8SThomas Huth static int write_cr0_checking(unsigned long val) 14b44d84daSMao, Junjie { 15b44d84daSMao, Junjie asm volatile(ASM_TRY("1f") 16b44d84daSMao, Junjie "mov %0, %%cr0\n\t" 17b44d84daSMao, Junjie "1:": : "r" (val)); 18b44d84daSMao, Junjie return exception_vector(); 19b44d84daSMao, Junjie } 20b44d84daSMao, Junjie 21db4898e8SThomas Huth static int invpcid_checking(unsigned long type, void *desc) 22b44d84daSMao, Junjie { 23b44d84daSMao, Junjie asm volatile (ASM_TRY("1f") 24b44d84daSMao, Junjie ".byte 0x66,0x0f,0x38,0x82,0x18 \n\t" /* invpcid (%rax), %rbx */ 25b44d84daSMao, Junjie "1:" : : "a" (desc), "b" (type)); 26b44d84daSMao, Junjie return exception_vector(); 27b44d84daSMao, Junjie } 28b44d84daSMao, Junjie 29db4898e8SThomas Huth static void test_pcid_enabled(void) 30b44d84daSMao, Junjie { 31b44d84daSMao, Junjie int passed = 0; 32b44d84daSMao, Junjie ulong cr0 = read_cr0(), cr3 = read_cr3(), cr4 = read_cr4(); 33b44d84daSMao, Junjie 34b44d84daSMao, Junjie /* try setting CR4.PCIDE, no exception expected */ 35b44d84daSMao, Junjie if (write_cr4_checking(cr4 | X86_CR4_PCIDE) != 0) 36b44d84daSMao, Junjie goto report; 37b44d84daSMao, Junjie 38b44d84daSMao, Junjie /* try clearing CR0.PG when CR4.PCIDE=1, #GP expected */ 39a1a39c97SPaolo Bonzini if (write_cr0_checking(cr0 & ~X86_CR0_PG) != GP_VECTOR) 40b44d84daSMao, Junjie goto report; 41b44d84daSMao, Junjie 42b44d84daSMao, Junjie write_cr4(cr4); 43b44d84daSMao, Junjie 44b44d84daSMao, Junjie /* try setting CR4.PCIDE when CR3[11:0] != 0 , #GP expected */ 45b44d84daSMao, Junjie write_cr3(cr3 | 0x001); 46b44d84daSMao, Junjie if (write_cr4_checking(cr4 | X86_CR4_PCIDE) != GP_VECTOR) 47b44d84daSMao, Junjie goto report; 486c8ef44fSMao, Junjie write_cr3(cr3); 49b44d84daSMao, Junjie 50b44d84daSMao, Junjie passed = 1; 51b44d84daSMao, Junjie 52b44d84daSMao, Junjie report: 53a299895bSThomas Huth report(passed, "Test on PCID when enabled"); 54b44d84daSMao, Junjie } 55b44d84daSMao, Junjie 56db4898e8SThomas Huth static void test_pcid_disabled(void) 57b44d84daSMao, Junjie { 58b44d84daSMao, Junjie int passed = 0; 59b44d84daSMao, Junjie ulong cr4 = read_cr4(); 60b44d84daSMao, Junjie 61b44d84daSMao, Junjie /* try setting CR4.PCIDE, #GP expected */ 62b44d84daSMao, Junjie if (write_cr4_checking(cr4 | X86_CR4_PCIDE) != GP_VECTOR) 63b44d84daSMao, Junjie goto report; 64b44d84daSMao, Junjie 65b44d84daSMao, Junjie passed = 1; 66b44d84daSMao, Junjie 67b44d84daSMao, Junjie report: 68a299895bSThomas Huth report(passed, "Test on PCID when disabled"); 69b44d84daSMao, Junjie } 70b44d84daSMao, Junjie 716e058ea6SSean Christopherson static void test_invpcid_enabled(int pcid_enabled) 72b44d84daSMao, Junjie { 73477ae7deSSean Christopherson int passed = 0, i; 74b44d84daSMao, Junjie ulong cr4 = read_cr4(); 75b44d84daSMao, Junjie struct invpcid_desc desc; 76*fb0e760aSZhenzhong Duan 77*fb0e760aSZhenzhong Duan memset(&desc, 0, sizeof(desc)); 78b44d84daSMao, Junjie 79477ae7deSSean Christopherson /* try executing invpcid when CR4.PCIDE=0, desc.pcid=0 and type=0..3 80b44d84daSMao, Junjie * no exception expected 81b44d84daSMao, Junjie */ 82477ae7deSSean Christopherson for (i = 0; i < 4; i++) { 83477ae7deSSean Christopherson if (invpcid_checking(i, &desc) != 0) 84b44d84daSMao, Junjie goto report; 85477ae7deSSean Christopherson } 86b44d84daSMao, Junjie 87477ae7deSSean Christopherson /* try executing invpcid when CR4.PCIDE=0, desc.pcid=1 and type=0..1 88b44d84daSMao, Junjie * #GP expected 89b44d84daSMao, Junjie */ 90b44d84daSMao, Junjie desc.pcid = 1; 91477ae7deSSean Christopherson for (i = 0; i < 2; i++) { 92477ae7deSSean Christopherson if (invpcid_checking(i, &desc) != GP_VECTOR) 93b44d84daSMao, Junjie goto report; 94477ae7deSSean Christopherson } 95b44d84daSMao, Junjie 966e058ea6SSean Christopherson /* Skip tests that require the PCIDE=1 if PCID isn't supported. */ 976e058ea6SSean Christopherson if (!pcid_enabled) 986e058ea6SSean Christopherson goto success; 996e058ea6SSean Christopherson 100b44d84daSMao, Junjie if (write_cr4_checking(cr4 | X86_CR4_PCIDE) != 0) 101b44d84daSMao, Junjie goto report; 102b44d84daSMao, Junjie 103b44d84daSMao, Junjie /* try executing invpcid when CR4.PCIDE=1 104b44d84daSMao, Junjie * no exception expected 105b44d84daSMao, Junjie */ 106b44d84daSMao, Junjie desc.pcid = 10; 107b44d84daSMao, Junjie if (invpcid_checking(2, &desc) != 0) 108b44d84daSMao, Junjie goto report; 109b44d84daSMao, Junjie 1106e058ea6SSean Christopherson success: 111b44d84daSMao, Junjie passed = 1; 112b44d84daSMao, Junjie 113b44d84daSMao, Junjie report: 114a299895bSThomas Huth report(passed, "Test on INVPCID when enabled"); 115b44d84daSMao, Junjie } 116b44d84daSMao, Junjie 117db4898e8SThomas Huth static void test_invpcid_disabled(void) 118b44d84daSMao, Junjie { 119b44d84daSMao, Junjie int passed = 0; 120b44d84daSMao, Junjie struct invpcid_desc desc; 121b44d84daSMao, Junjie 122b44d84daSMao, Junjie /* try executing invpcid, #UD expected */ 123b44d84daSMao, Junjie if (invpcid_checking(2, &desc) != UD_VECTOR) 124b44d84daSMao, Junjie goto report; 125b44d84daSMao, Junjie 126b44d84daSMao, Junjie passed = 1; 127b44d84daSMao, Junjie 128b44d84daSMao, Junjie report: 129a299895bSThomas Huth report(passed, "Test on INVPCID when disabled"); 130b44d84daSMao, Junjie } 131b44d84daSMao, Junjie 132b44d84daSMao, Junjie int main(int ac, char **av) 133b44d84daSMao, Junjie { 134b44d84daSMao, Junjie int pcid_enabled = 0, invpcid_enabled = 0; 135b44d84daSMao, Junjie 136badc98caSKrish Sadhukhan if (this_cpu_has(X86_FEATURE_PCID)) 137b44d84daSMao, Junjie pcid_enabled = 1; 138badc98caSKrish Sadhukhan if (this_cpu_has(X86_FEATURE_INVPCID)) 139b44d84daSMao, Junjie invpcid_enabled = 1; 140b44d84daSMao, Junjie 141b44d84daSMao, Junjie if (pcid_enabled) 142b44d84daSMao, Junjie test_pcid_enabled(); 143b44d84daSMao, Junjie else 144b44d84daSMao, Junjie test_pcid_disabled(); 145b44d84daSMao, Junjie 146b44d84daSMao, Junjie if (invpcid_enabled) 1476e058ea6SSean Christopherson test_invpcid_enabled(pcid_enabled); 148b44d84daSMao, Junjie else 149b44d84daSMao, Junjie test_invpcid_disabled(); 150b44d84daSMao, Junjie 151f3cdd159SJan Kiszka return report_summary(); 152b44d84daSMao, Junjie } 153