Commit 58989dc3 authored by Andy Lutomirski's avatar Andy Lutomirski Committed by Greg Kroah-Hartman

selftests/x86/fsgsbase: Test selectors 1, 2, and 3

commit 23d98c20 upstream.

Those are funny cases.  Make sure they work.

(Something is screwy with signal handling if a selector is 1, 2, or 3.
Anyone who wants to dive into that rabbit hole is welcome to do so.)
Signed-off-by: default avatarAndy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Borislav Petkov <bpetkov@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Chang Seok <chang.seok.bae@intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 9ed3dc1c
...@@ -285,9 +285,12 @@ static void *threadproc(void *ctx) ...@@ -285,9 +285,12 @@ static void *threadproc(void *ctx)
} }
} }
static void set_gs_and_switch_to(unsigned long local, unsigned long remote) static void set_gs_and_switch_to(unsigned long local,
unsigned short force_sel,
unsigned long remote)
{ {
unsigned long base; unsigned long base;
unsigned short sel_pre_sched, sel_post_sched;
bool hard_zero = false; bool hard_zero = false;
if (local == HARD_ZERO) { if (local == HARD_ZERO) {
...@@ -297,6 +300,8 @@ static void set_gs_and_switch_to(unsigned long local, unsigned long remote) ...@@ -297,6 +300,8 @@ static void set_gs_and_switch_to(unsigned long local, unsigned long remote)
printf("[RUN]\tARCH_SET_GS(0x%lx)%s, then schedule to 0x%lx\n", printf("[RUN]\tARCH_SET_GS(0x%lx)%s, then schedule to 0x%lx\n",
local, hard_zero ? " and clear gs" : "", remote); local, hard_zero ? " and clear gs" : "", remote);
if (force_sel)
printf("\tBefore schedule, set selector to 0x%hx\n", force_sel);
if (syscall(SYS_arch_prctl, ARCH_SET_GS, local) != 0) if (syscall(SYS_arch_prctl, ARCH_SET_GS, local) != 0)
err(1, "ARCH_SET_GS"); err(1, "ARCH_SET_GS");
if (hard_zero) if (hard_zero)
...@@ -307,18 +312,35 @@ static void set_gs_and_switch_to(unsigned long local, unsigned long remote) ...@@ -307,18 +312,35 @@ static void set_gs_and_switch_to(unsigned long local, unsigned long remote)
printf("[FAIL]\tGSBASE wasn't set as expected\n"); printf("[FAIL]\tGSBASE wasn't set as expected\n");
} }
if (force_sel) {
asm volatile ("mov %0, %%gs" : : "rm" (force_sel));
sel_pre_sched = force_sel;
local = read_base(GS);
/*
* Signal delivery seems to mess up weird selectors. Put it
* back.
*/
asm volatile ("mov %0, %%gs" : : "rm" (force_sel));
} else {
asm volatile ("mov %%gs, %0" : "=rm" (sel_pre_sched));
}
remote_base = remote; remote_base = remote;
ftx = 1; ftx = 1;
syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0); syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
while (ftx != 0) while (ftx != 0)
syscall(SYS_futex, &ftx, FUTEX_WAIT, 1, NULL, NULL, 0); syscall(SYS_futex, &ftx, FUTEX_WAIT, 1, NULL, NULL, 0);
asm volatile ("mov %%gs, %0" : "=rm" (sel_post_sched));
base = read_base(GS); base = read_base(GS);
if (base == local) { if (base == local && sel_pre_sched == sel_post_sched) {
printf("[OK]\tGSBASE remained 0x%lx\n", local); printf("[OK]\tGS/BASE remained 0x%hx/0x%lx\n",
sel_pre_sched, local);
} else { } else {
nerrs++; nerrs++;
printf("[FAIL]\tGSBASE changed to 0x%lx\n", base); printf("[FAIL]\tGS/BASE changed from 0x%hx/0x%lx to 0x%hx/0x%lx\n",
sel_pre_sched, local, sel_post_sched, base);
} }
} }
...@@ -381,10 +403,17 @@ int main() ...@@ -381,10 +403,17 @@ int main()
for (int local = 0; local < 4; local++) { for (int local = 0; local < 4; local++) {
for (int remote = 0; remote < 4; remote++) { for (int remote = 0; remote < 4; remote++) {
set_gs_and_switch_to(bases_with_hard_zero[local], for (unsigned short s = 0; s < 5; s++) {
unsigned short sel = s;
if (s == 4)
asm ("mov %%ss, %0" : "=rm" (sel));
set_gs_and_switch_to(
bases_with_hard_zero[local],
sel,
bases_with_hard_zero[remote]); bases_with_hard_zero[remote]);
} }
} }
}
test_unexpected_base(); test_unexpected_base();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment