aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/entry/entry_64_compat.S8
-rw-r--r--tools/testing/selftests/x86/test_syscall_vdso.c35
2 files changed, 25 insertions, 18 deletions
diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
index 9af927e59d49..9de7f1e1dede 100644
--- a/arch/x86/entry/entry_64_compat.S
+++ b/arch/x86/entry/entry_64_compat.S
@@ -84,13 +84,13 @@ ENTRY(entry_SYSENTER_compat)
84 pushq %rdx /* pt_regs->dx */ 84 pushq %rdx /* pt_regs->dx */
85 pushq %rcx /* pt_regs->cx */ 85 pushq %rcx /* pt_regs->cx */
86 pushq $-ENOSYS /* pt_regs->ax */ 86 pushq $-ENOSYS /* pt_regs->ax */
87 pushq $0 /* pt_regs->r8 = 0 */ 87 pushq %r8 /* pt_regs->r8 */
88 xorl %r8d, %r8d /* nospec r8 */ 88 xorl %r8d, %r8d /* nospec r8 */
89 pushq $0 /* pt_regs->r9 = 0 */ 89 pushq %r9 /* pt_regs->r9 */
90 xorl %r9d, %r9d /* nospec r9 */ 90 xorl %r9d, %r9d /* nospec r9 */
91 pushq $0 /* pt_regs->r10 = 0 */ 91 pushq %r10 /* pt_regs->r10 */
92 xorl %r10d, %r10d /* nospec r10 */ 92 xorl %r10d, %r10d /* nospec r10 */
93 pushq $0 /* pt_regs->r11 = 0 */ 93 pushq %r11 /* pt_regs->r11 */
94 xorl %r11d, %r11d /* nospec r11 */ 94 xorl %r11d, %r11d /* nospec r11 */
95 pushq %rbx /* pt_regs->rbx */ 95 pushq %rbx /* pt_regs->rbx */
96 xorl %ebx, %ebx /* nospec rbx */ 96 xorl %ebx, %ebx /* nospec rbx */
diff --git a/tools/testing/selftests/x86/test_syscall_vdso.c b/tools/testing/selftests/x86/test_syscall_vdso.c
index 40370354d4c1..c9c3281077bc 100644
--- a/tools/testing/selftests/x86/test_syscall_vdso.c
+++ b/tools/testing/selftests/x86/test_syscall_vdso.c
@@ -100,12 +100,19 @@ asm (
100 " shl $32, %r8\n" 100 " shl $32, %r8\n"
101 " orq $0x7f7f7f7f, %r8\n" 101 " orq $0x7f7f7f7f, %r8\n"
102 " movq %r8, %r9\n" 102 " movq %r8, %r9\n"
103 " movq %r8, %r10\n" 103 " incq %r9\n"
104 " movq %r8, %r11\n" 104 " movq %r9, %r10\n"
105 " movq %r8, %r12\n" 105 " incq %r10\n"
106 " movq %r8, %r13\n" 106 " movq %r10, %r11\n"
107 " movq %r8, %r14\n" 107 " incq %r11\n"
108 " movq %r8, %r15\n" 108 " movq %r11, %r12\n"
109 " incq %r12\n"
110 " movq %r12, %r13\n"
111 " incq %r13\n"
112 " movq %r13, %r14\n"
113 " incq %r14\n"
114 " movq %r14, %r15\n"
115 " incq %r15\n"
109 " ret\n" 116 " ret\n"
110 " .code32\n" 117 " .code32\n"
111 " .popsection\n" 118 " .popsection\n"
@@ -128,12 +135,13 @@ int check_regs64(void)
128 int err = 0; 135 int err = 0;
129 int num = 8; 136 int num = 8;
130 uint64_t *r64 = &regs64.r8; 137 uint64_t *r64 = &regs64.r8;
138 uint64_t expected = 0x7f7f7f7f7f7f7f7fULL;
131 139
132 if (!kernel_is_64bit) 140 if (!kernel_is_64bit)
133 return 0; 141 return 0;
134 142
135 do { 143 do {
136 if (*r64 == 0x7f7f7f7f7f7f7f7fULL) 144 if (*r64 == expected++)
137 continue; /* register did not change */ 145 continue; /* register did not change */
138 if (syscall_addr != (long)&int80) { 146 if (syscall_addr != (long)&int80) {
139 /* 147 /*
@@ -147,18 +155,17 @@ int check_regs64(void)
147 continue; 155 continue;
148 } 156 }
149 } else { 157 } else {
150 /* INT80 syscall entrypoint can be used by 158 /*
159 * INT80 syscall entrypoint can be used by
151 * 64-bit programs too, unlike SYSCALL/SYSENTER. 160 * 64-bit programs too, unlike SYSCALL/SYSENTER.
152 * Therefore it must preserve R12+ 161 * Therefore it must preserve R12+
153 * (they are callee-saved registers in 64-bit C ABI). 162 * (they are callee-saved registers in 64-bit C ABI).
154 * 163 *
155 * This was probably historically not intended, 164 * Starting in Linux 4.17 (and any kernel that
156 * but R8..11 are clobbered (cleared to 0). 165 * backports the change), R8..11 are preserved.
157 * IOW: they are the only registers which aren't 166 * Historically (and probably unintentionally), they
158 * preserved across INT80 syscall. 167 * were clobbered or zeroed.
159 */ 168 */
160 if (*r64 == 0 && num <= 11)
161 continue;
162 } 169 }
163 printf("[FAIL]\tR%d has changed:%016llx\n", num, *r64); 170 printf("[FAIL]\tR%d has changed:%016llx\n", num, *r64);
164 err++; 171 err++;