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 { 8b44d84daSMao, Junjie unsigned long pcid : 12; 9b44d84daSMao, Junjie unsigned long rsv : 52; 10b44d84daSMao, Junjie unsigned long 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 71db4898e8SThomas Huth static void test_invpcid_enabled(void) 72b44d84daSMao, Junjie { 73*477ae7deSSean Christopherson int passed = 0, i; 74b44d84daSMao, Junjie ulong cr4 = read_cr4(); 75b44d84daSMao, Junjie struct invpcid_desc desc; 76b44d84daSMao, Junjie desc.rsv = 0; 77b44d84daSMao, Junjie 78*477ae7deSSean Christopherson /* try executing invpcid when CR4.PCIDE=0, desc.pcid=0 and type=0..3 79b44d84daSMao, Junjie * no exception expected 80b44d84daSMao, Junjie */ 81b44d84daSMao, Junjie desc.pcid = 0; 82*477ae7deSSean Christopherson for (i = 0; i < 4; i++) { 83*477ae7deSSean Christopherson if (invpcid_checking(i, &desc) != 0) 84b44d84daSMao, Junjie goto report; 85*477ae7deSSean Christopherson } 86b44d84daSMao, Junjie 87*477ae7deSSean 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; 91*477ae7deSSean Christopherson for (i = 0; i < 2; i++) { 92*477ae7deSSean Christopherson if (invpcid_checking(i, &desc) != GP_VECTOR) 93b44d84daSMao, Junjie goto report; 94*477ae7deSSean Christopherson } 95b44d84daSMao, Junjie 96b44d84daSMao, Junjie if (write_cr4_checking(cr4 | X86_CR4_PCIDE) != 0) 97b44d84daSMao, Junjie goto report; 98b44d84daSMao, Junjie 99b44d84daSMao, Junjie /* try executing invpcid when CR4.PCIDE=1 100b44d84daSMao, Junjie * no exception expected 101b44d84daSMao, Junjie */ 102b44d84daSMao, Junjie desc.pcid = 10; 103b44d84daSMao, Junjie if (invpcid_checking(2, &desc) != 0) 104b44d84daSMao, Junjie goto report; 105b44d84daSMao, Junjie 106b44d84daSMao, Junjie passed = 1; 107b44d84daSMao, Junjie 108b44d84daSMao, Junjie report: 109a299895bSThomas Huth report(passed, "Test on INVPCID when enabled"); 110b44d84daSMao, Junjie } 111b44d84daSMao, Junjie 112db4898e8SThomas Huth static void test_invpcid_disabled(void) 113b44d84daSMao, Junjie { 114b44d84daSMao, Junjie int passed = 0; 115b44d84daSMao, Junjie struct invpcid_desc desc; 116b44d84daSMao, Junjie 117b44d84daSMao, Junjie /* try executing invpcid, #UD expected */ 118b44d84daSMao, Junjie if (invpcid_checking(2, &desc) != UD_VECTOR) 119b44d84daSMao, Junjie goto report; 120b44d84daSMao, Junjie 121b44d84daSMao, Junjie passed = 1; 122b44d84daSMao, Junjie 123b44d84daSMao, Junjie report: 124a299895bSThomas Huth report(passed, "Test on INVPCID when disabled"); 125b44d84daSMao, Junjie } 126b44d84daSMao, Junjie 127b44d84daSMao, Junjie int main(int ac, char **av) 128b44d84daSMao, Junjie { 129b44d84daSMao, Junjie int pcid_enabled = 0, invpcid_enabled = 0; 130b44d84daSMao, Junjie 131badc98caSKrish Sadhukhan if (this_cpu_has(X86_FEATURE_PCID)) 132b44d84daSMao, Junjie pcid_enabled = 1; 133badc98caSKrish Sadhukhan if (this_cpu_has(X86_FEATURE_INVPCID)) 134b44d84daSMao, Junjie invpcid_enabled = 1; 135b44d84daSMao, Junjie 136b44d84daSMao, Junjie if (pcid_enabled) 137b44d84daSMao, Junjie test_pcid_enabled(); 138b44d84daSMao, Junjie else 139b44d84daSMao, Junjie test_pcid_disabled(); 140b44d84daSMao, Junjie 141b44d84daSMao, Junjie if (invpcid_enabled) 142b44d84daSMao, Junjie test_invpcid_enabled(); 143b44d84daSMao, Junjie else 144b44d84daSMao, Junjie test_invpcid_disabled(); 145b44d84daSMao, Junjie 146f3cdd159SJan Kiszka return report_summary(); 147b44d84daSMao, Junjie } 148