mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
x86 fixes:
- Reject the loading of a potentially problematic microcode version
on Intel Granite Rapids systems (Chang S. Bae)
- On FRED, reconstruct the proper #GP context for rejected INT
instructions, to fix a signal ABI regression (Matthew Schwartz)
- Add a test for this signal ABI regression the x86
self-test suite (Matthew Schwartz)
- Don't emit the new and not yet properly supported EGPR instructions
(%r16-%r31) on CONFIG_X86_NATIVE_CPU=y builds (Chang S. Bae)
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-----BEGIN PGP SIGNATURE-----
iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAmqvrhgRHG1pbmdvQGtl
cm5lbC5vcmcACgkQEnMQ0APhK1inbQ/9G4Q0h9esQ945n0uYRYvVLuj2P8DvE3XN
9d5IJ5pIYdhJCvlv8yXyv1u3sq59QYNmUgpBMghHJonhqobtnchvBSiznoAMgi8L
yjRlcaFBPX9qjFQV1W9WJQuUHhW/12QFy9Bo9n1uXEv6pYspYVDwodCaS+rEvkTF
0wK3TjETv90TravGjFscYTt2VLAiy+cd/FxkUA0sBaMLjhFpUyAPHGJe/vcf8vT3
rEXkY8EeSjv5F6eKMTDVacrSZu2c9wco1bJIsSFEcxZGFzhDbuCOGiDCkwmB3uuD
ReKbEUC0KmF8qd4Ubf0dMGpbHT9LDu9Ggex619cHFOHMupPubP+yym7aCpm3v7Sb
gZe6eV6VrSREJ+oBVKsqMrWXsg1YDj6uJhC/5K3S78xBeRq64kKsmBbC93Zp20TC
QpSAxKIFqp8C+tfKzpBmcSbcipRUfATJxLjp94QaQDp467jjJCvpDJdc12mV7WR9
0gMtFjxUaIe8BGX7s2PuWPgZ8+CIH0hZQuttxUU4QWvM2RGU+QrDaMwTeAY7wme4
xomc0wpXQb5enrjmFu8betlD0xfjgt7k6eW0njezRpWSk3wyHDd5w/6Vfn8pA6Fx
AQV4UuszXzQmG+W2pdIjLhnjmsjEeWMpmwgzn0rkcqujWHeh8XOSvQIjULFrFtFv
srSbum6vEfk=
=MP1H
-----END PGP SIGNATURE-----
Merge tag 'x86-urgent-2026-09-20' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Ingo Molnar:
- Reject the loading of a potentially problematic microcode version
on Intel Granite Rapids systems (Chang S. Bae)
- On FRED, reconstruct the proper #GP context for rejected INT
instructions, to fix a signal ABI regression (Matthew Schwartz)
- Add a test for this signal ABI regression the x86
self-test suite (Matthew Schwartz)
- Don't emit the new and not yet properly supported EGPR instructions
(%r16-%r31) on CONFIG_X86_NATIVE_CPU=y builds (Chang S. Bae)
* tag 'x86-urgent-2026-09-20' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/build/64: Prevent native builds from generating EGPR use
selftests/x86: Check signal state for rejected software interrupts
x86/fred: Reconstruct the #GP context for rejected INT instructions
x86/microcode/intel: Reject problematic loading on Granite Rapids systems
This commit is contained in:
commit
156fa7417f
|
|
@ -204,10 +204,21 @@ config CC_HAS_MARCH_NATIVE
|
|||
# usage warnings that only appear wth '-march=native'.
|
||||
depends on CC_IS_GCC || CLANG_VERSION >= 190100
|
||||
|
||||
config RUSTC_HAS_APXF
|
||||
# The kernel isn't ready for in-kernel APX instructions. Without
|
||||
# explicit frontend gating of APX, the backend may emit those
|
||||
# instructions in native builds.
|
||||
#
|
||||
# Rust 1.88 added the `apxf` feature option, but versions before 1.93
|
||||
# emit an `apxf` target attribute that only LLVM 23+ can interpret.
|
||||
def_bool (RUSTC_VERSION >= 108800 && RUSTC_LLVM_MAJOR_VERSION >= 23) || \
|
||||
RUSTC_VERSION >= 109300
|
||||
|
||||
config X86_NATIVE_CPU
|
||||
bool "Build and optimize for local/native CPU"
|
||||
depends on X86_64
|
||||
depends on CC_HAS_MARCH_NATIVE
|
||||
depends on !RUST || RUSTC_HAS_APXF
|
||||
help
|
||||
Optimize for the current CPU used to compile the kernel.
|
||||
Use this option if you intend to build the kernel for your
|
||||
|
|
|
|||
|
|
@ -161,6 +161,11 @@ else
|
|||
|
||||
ifdef CONFIG_X86_NATIVE_CPU
|
||||
KBUILD_CFLAGS += -march=native
|
||||
# Prevent the compiler from generating EGPR use. The kernel is
|
||||
# not yet prepared for general in-kernel use.
|
||||
KBUILD_CFLAGS += $(call cc-option,-mno-apx-features=egpr)
|
||||
|
||||
# generate_rust_target.rs handles Rust APX gating.
|
||||
KBUILD_RUSTFLAGS += -Ctarget-cpu=native
|
||||
else
|
||||
KBUILD_CFLAGS += -march=x86-64 -mtune=generic
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <asm/desc.h>
|
||||
#include <asm/fred.h>
|
||||
#include <asm/idtentry.h>
|
||||
#include <asm/processor-flags.h>
|
||||
#include <asm/syscall.h>
|
||||
#include <asm/trapnr.h>
|
||||
#include <asm/traps.h>
|
||||
|
|
@ -71,7 +72,15 @@ static noinstr void fred_intx(struct pt_regs *regs)
|
|||
#endif
|
||||
|
||||
default:
|
||||
return exc_general_protection(regs, 0);
|
||||
/*
|
||||
* Reconstruct the #GP fault state that IDT delivery would produce.
|
||||
* Clear the software event flag so ERETU with TF set does not trap
|
||||
* before the resumed instruction. See prevent_single_step_upon_eretu().
|
||||
*/
|
||||
regs->ip -= regs->fred_ss.insnlen;
|
||||
regs->flags |= X86_EFLAGS_RF;
|
||||
regs->fred_ss.swevent = 0;
|
||||
return exc_general_protection(regs, (regs->fred_ss.vector << 3) | 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -309,6 +309,26 @@ static void save_microcode_patch(struct microcode_intel *patch)
|
|||
pr_err("Unable to allocate microcode memory size: %u\n", size);
|
||||
}
|
||||
|
||||
static bool revision_is_safe(struct cpu_signature *sig, u32 rev)
|
||||
{
|
||||
u32 vfm = IFM(x86_family(sig->sig), x86_model(sig->sig));
|
||||
|
||||
/*
|
||||
* Erratum GNR98 can cause #MCs if "jumping over" revision 0x1000405.
|
||||
* Avoid the jumps.
|
||||
*/
|
||||
if (vfm == INTEL_GRANITERAPIDS_X &&
|
||||
x86_stepping(sig->sig) == 1 &&
|
||||
sig->pf & 0x95 &&
|
||||
sig->rev < 0x1000405 &&
|
||||
rev > 0x1000405) {
|
||||
pr_err_once("Erratum GNR98: skipping revision 0x%x.\n", rev);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Scan blob for microcode matching the boot CPUs family, model, stepping */
|
||||
static __init struct microcode_intel *scan_microcode(void *data, size_t size,
|
||||
struct ucode_cpu_info *uci,
|
||||
|
|
@ -330,6 +350,9 @@ static __init struct microcode_intel *scan_microcode(void *data, size_t size,
|
|||
if (!intel_find_matching_signature(data, &uci->cpu_sig))
|
||||
continue;
|
||||
|
||||
if (!revision_is_safe(&uci->cpu_sig, mc_header->rev))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* For saving the early microcode, find the matching revision which
|
||||
* was loaded on the BSP.
|
||||
|
|
@ -878,6 +901,9 @@ static enum ucode_state parse_microcode_blobs(int cpu, struct iov_iter *iter)
|
|||
if (!intel_find_matching_signature(mc, &uci->cpu_sig))
|
||||
continue;
|
||||
|
||||
if (!revision_is_safe(&uci->cpu_sig, mc_header.rev))
|
||||
continue;
|
||||
|
||||
is_safe = ucode_validate_minrev(&mc_header);
|
||||
if (force_minrev && !is_safe)
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -224,6 +224,11 @@ fn main() {
|
|||
features += ",+harden-sls-ijmp";
|
||||
features += ",+harden-sls-ret";
|
||||
}
|
||||
if cfg.has("X86_NATIVE_CPU") {
|
||||
// Prevent the backend from generating APX instructions. The kernel is not yet prepared
|
||||
// for general in-kernel EGPR use.
|
||||
features += ",-apxf";
|
||||
}
|
||||
ts.push("features", features);
|
||||
ts.push("llvm-target", "x86_64-linux-gnu");
|
||||
ts.push("supported-sanitizers", ["kcfi", "kernel-address"]);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ CAN_BUILD_WITH_NOPIE := $(shell ./check_cc.sh "$(CC)" trivial_program.c -no-pie)
|
|||
TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt test_mremap_vdso \
|
||||
check_initial_reg_state sigreturn iopl ioperm \
|
||||
test_vsyscall mov_ss_trap sigtrap_loop \
|
||||
syscall_arg_fault fsgsbase_restore sigaltstack
|
||||
syscall_arg_fault fsgsbase_restore sigaltstack int_signal
|
||||
TARGETS_C_BOTHBITS += nx_stack
|
||||
TARGETS_C_32BIT_ONLY := entry_from_vm86 test_syscall_vdso unwind_vdso \
|
||||
test_FCMOV test_FCOMI test_FISTTP \
|
||||
|
|
|
|||
311
tools/testing/selftests/x86/int_signal.c
Normal file
311
tools/testing/selftests/x86/int_signal.c
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Check the signal context for INT instructions with IDT and FRED entry. */
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <cpuid.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
#ifdef __x86_64__
|
||||
#define REG_IP REG_RIP
|
||||
#define USER_IP rip
|
||||
#define STACK_PTR "%rsp"
|
||||
#else
|
||||
#define REG_IP REG_EIP
|
||||
#define USER_IP eip
|
||||
#define STACK_PTR "%esp"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Each instruction has normal and single-step entry points. Resume at the
|
||||
* NOP after handling its signal, then expect a trace trap after that NOP
|
||||
* when TF is set. Explicit labels avoid assuming the kernel's saved IP.
|
||||
*/
|
||||
#define PROBE(name, insn) \
|
||||
extern void name(void); \
|
||||
extern void name##_tf(void); \
|
||||
extern const char name##_end[], name##_step[]; \
|
||||
asm(".pushsection .text\n" \
|
||||
".globl " #name "_tf\n" \
|
||||
".type " #name "_tf, @function\n" \
|
||||
#name "_tf:\n" \
|
||||
"pushf\n" \
|
||||
"orl $0x100, (" STACK_PTR ")\n" \
|
||||
"popf\n" \
|
||||
".globl " #name "\n" \
|
||||
".type " #name ", @function\n" \
|
||||
#name ":\n" insn "\n" \
|
||||
".globl " #name "_end\n" \
|
||||
#name "_end:\nnop\n" \
|
||||
".globl " #name "_step\n" \
|
||||
#name "_step:\nret\n" \
|
||||
".size " #name ", .-" #name "\n" \
|
||||
".size " #name "_tf, .-" #name "_tf\n" \
|
||||
".popsection\n")
|
||||
|
||||
PROBE(int1, ".byte 0xcd, 0x01");
|
||||
PROBE(int29, ".byte 0xcd, 0x29");
|
||||
PROBE(int2c, ".byte 0xcd, 0x2c");
|
||||
PROBE(int2d, ".byte 0xcd, 0x2d");
|
||||
PROBE(prefixed_int2d, ".byte 0x66, 0xcd, 0x2d");
|
||||
PROBE(long_int2d, ".fill 13, 1, 0x2e\n.byte 0xcd, 0x2d");
|
||||
PROBE(int81, ".byte 0xcd, 0x81");
|
||||
PROBE(intff, ".byte 0xcd, 0xff");
|
||||
PROBE(short_int3, ".byte 0xcc");
|
||||
PROBE(long_int3, ".byte 0xcd, 0x03");
|
||||
PROBE(int4, ".byte 0xcd, 0x04");
|
||||
PROBE(ud2, ".byte 0x0f, 0x0b");
|
||||
PROBE(hlt, ".byte 0xf4");
|
||||
|
||||
struct test {
|
||||
const char *name;
|
||||
void (*run)(void);
|
||||
void (*run_tf)(void);
|
||||
const char *end, *step;
|
||||
int signo, trap, error, ip_offset, flags, code;
|
||||
};
|
||||
|
||||
#define TEST(name, sig, trap, error, offset, flags, code) \
|
||||
{ #name, name, name##_tf, name##_end, name##_step, \
|
||||
sig, trap, error, offset, flags, code }
|
||||
|
||||
#define GP(name, error) \
|
||||
TEST(name, SIGSEGV, 13, error, 0, X86_EFLAGS_RF, SI_KERNEL)
|
||||
|
||||
static const struct test tests[] = {
|
||||
GP(int1, 0x00a),
|
||||
GP(int29, 0x14a),
|
||||
GP(int2c, 0x162),
|
||||
GP(int2d, 0x16a),
|
||||
GP(prefixed_int2d, 0x16a),
|
||||
GP(long_int2d, 0x16a),
|
||||
GP(int81, 0x40a),
|
||||
GP(intff, 0x7fa),
|
||||
GP(hlt, 0),
|
||||
TEST(short_int3, SIGTRAP, 3, 0, 1, 0, SI_KERNEL),
|
||||
TEST(long_int3, SIGTRAP, 3, 0, 2, 0, SI_KERNEL),
|
||||
TEST(int4, SIGSEGV, 4, 0, 2, 0, SI_KERNEL),
|
||||
TEST(ud2, SIGILL, 6, 0, 0, X86_EFLAGS_RF, ILL_ILLOPN),
|
||||
};
|
||||
|
||||
static const struct test *active;
|
||||
static volatile sig_atomic_t seen, signo, trap, error, ip_offset, flags;
|
||||
static volatile sig_atomic_t code, addr_ok, single_step, stepped, step_ok;
|
||||
|
||||
static void handler(int sig, siginfo_t *info, void *context)
|
||||
{
|
||||
ucontext_t *uc = context;
|
||||
uintptr_t ip = uc->uc_mcontext.gregs[REG_IP];
|
||||
uintptr_t start = (uintptr_t)active->run;
|
||||
uintptr_t end = (uintptr_t)active->end;
|
||||
|
||||
if (seen && single_step && sig == SIGTRAP) {
|
||||
if (stepped++) {
|
||||
ksft_print_msg("%s: second trace trap at %#lx\n",
|
||||
active->name, (unsigned long)ip);
|
||||
_exit(KSFT_FAIL);
|
||||
}
|
||||
step_ok = ip == (uintptr_t)active->step &&
|
||||
uc->uc_mcontext.gregs[REG_TRAPNO] == 1 &&
|
||||
info->si_code == TRAP_TRACE;
|
||||
uc->uc_mcontext.gregs[REG_EFL] &= ~X86_EFLAGS_TF;
|
||||
return;
|
||||
}
|
||||
|
||||
if (seen || ip < start || ip > end) {
|
||||
ksft_print_msg("%s: unexpected signal %d at %#lx\n",
|
||||
active->name, sig, (unsigned long)ip);
|
||||
_exit(KSFT_FAIL);
|
||||
}
|
||||
|
||||
signo = sig;
|
||||
trap = uc->uc_mcontext.gregs[REG_TRAPNO];
|
||||
error = uc->uc_mcontext.gregs[REG_ERR];
|
||||
ip_offset = ip - start;
|
||||
flags = uc->uc_mcontext.gregs[REG_EFL] & (X86_EFLAGS_RF | X86_EFLAGS_TF);
|
||||
code = info->si_code;
|
||||
/* force_sig() reports no address, force_sig_fault() reports the IP. */
|
||||
addr_ok = info->si_addr == (code == SI_KERNEL ? NULL : (void *)ip);
|
||||
seen = 1;
|
||||
uc->uc_mcontext.gregs[REG_IP] = end;
|
||||
}
|
||||
|
||||
static void wait_for_child(pid_t child, int *status)
|
||||
{
|
||||
pid_t ret;
|
||||
|
||||
do {
|
||||
ret = waitpid(child, status, 0);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
if (ret != child)
|
||||
ksft_exit_fail_perror("waitpid");
|
||||
}
|
||||
|
||||
/* Resume the tracee and check where the next stop lands. */
|
||||
static bool resume_to(pid_t child, int *status, int request, int sig,
|
||||
const void *ip, const char *what)
|
||||
{
|
||||
struct user_regs_struct regs;
|
||||
|
||||
if (ptrace(request, child, 0, 0))
|
||||
return false;
|
||||
wait_for_child(child, status);
|
||||
if (!WIFSTOPPED(*status)) {
|
||||
ksft_print_msg("%s: tracee did not stop\n", what);
|
||||
return false;
|
||||
}
|
||||
if (WSTOPSIG(*status) != sig) {
|
||||
ksft_print_msg("%s: stopped with signal %d, expected %d\n",
|
||||
what, WSTOPSIG(*status), sig);
|
||||
return false;
|
||||
}
|
||||
if (ptrace(PTRACE_GETREGS, child, 0, ®s))
|
||||
return false;
|
||||
if ((unsigned long)regs.USER_IP != (unsigned long)ip) {
|
||||
ksft_print_msg("%s: stopped at %#lx, expected %#lx\n", what,
|
||||
(unsigned long)regs.USER_IP, (unsigned long)ip);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool set_ip(pid_t child, const void *ip, bool tf)
|
||||
{
|
||||
struct user_regs_struct regs;
|
||||
|
||||
if (ptrace(PTRACE_GETREGS, child, 0, ®s))
|
||||
return false;
|
||||
regs.USER_IP = (unsigned long)ip;
|
||||
if (tf)
|
||||
regs.eflags |= X86_EFLAGS_TF;
|
||||
return !ptrace(PTRACE_SETREGS, child, 0, ®s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Exercise the tracer paths that resume through the fault frame rather than
|
||||
* sigreturn. A stale FRED software event flag on that frame traps before the
|
||||
* NOP executes instead of after it.
|
||||
*/
|
||||
static void test_ptrace(void)
|
||||
{
|
||||
bool into = false, step = false, cont = false;
|
||||
pid_t child;
|
||||
int status;
|
||||
|
||||
child = fork();
|
||||
if (child < 0)
|
||||
ksft_exit_fail_perror("fork");
|
||||
if (!child) {
|
||||
if (ptrace(PTRACE_TRACEME, 0, 0, 0))
|
||||
_exit(KSFT_FAIL);
|
||||
/* Start from a breakpoint frame, not the syscall frame of raise(). */
|
||||
asm volatile("int3");
|
||||
_exit(KSFT_FAIL);
|
||||
}
|
||||
|
||||
wait_for_child(child, &status);
|
||||
if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGTRAP)
|
||||
goto out;
|
||||
if (ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_EXITKILL))
|
||||
goto out;
|
||||
|
||||
/* Single-step into the INT. The fault must report the INT's address. */
|
||||
if (!set_ip(child, int2d, false))
|
||||
goto out;
|
||||
into = resume_to(child, &status, PTRACE_SINGLESTEP, SIGSEGV, int2d,
|
||||
"single-step into INT");
|
||||
if (!into)
|
||||
goto out;
|
||||
|
||||
/* Suppress SIGSEGV and single-step the NOP. */
|
||||
if (!set_ip(child, int2d_end, false))
|
||||
goto out;
|
||||
step = resume_to(child, &status, PTRACE_SINGLESTEP, SIGTRAP, int2d_step,
|
||||
"single-step after INT");
|
||||
if (!step)
|
||||
goto out;
|
||||
|
||||
/* Fault again, then suppress SIGSEGV and continue with TF set. */
|
||||
if (!set_ip(child, int2d, false))
|
||||
goto out;
|
||||
if (!resume_to(child, &status, PTRACE_CONT, SIGSEGV, int2d,
|
||||
"continue to INT"))
|
||||
goto out;
|
||||
if (!set_ip(child, int2d_end, true))
|
||||
goto out;
|
||||
cont = resume_to(child, &status, PTRACE_CONT, SIGTRAP, int2d_step,
|
||||
"continue with TF after INT");
|
||||
out:
|
||||
if (WIFSTOPPED(status)) {
|
||||
kill(child, SIGKILL);
|
||||
wait_for_child(child, &status);
|
||||
}
|
||||
ksft_test_result(into, "ptrace single-step into INT faults at the INT\n");
|
||||
ksft_test_result(step, "ptrace single-step after suppressing SIGSEGV\n");
|
||||
ksft_test_result(cont, "ptrace continue with TF after suppressing SIGSEGV\n");
|
||||
}
|
||||
|
||||
static bool cpu_has_fred(void)
|
||||
{
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
|
||||
if (__get_cpuid_max(0, NULL) < 7)
|
||||
return false;
|
||||
__cpuid_count(7, 1, eax, ebx, ecx, edx);
|
||||
return eax & (1 << 17);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
unsigned int i, tf;
|
||||
int expected_flags, ok;
|
||||
|
||||
ksft_print_header();
|
||||
ksft_set_plan(2 * ARRAY_SIZE(tests) + 3);
|
||||
ksft_print_msg("CPU %s FRED\n", cpu_has_fred() ? "supports" : "lacks");
|
||||
sethandler(SIGSEGV, handler, 0);
|
||||
sethandler(SIGTRAP, handler, 0);
|
||||
sethandler(SIGILL, handler, 0);
|
||||
|
||||
for (tf = 0; tf < 2; tf++) {
|
||||
for (i = 0; i < ARRAY_SIZE(tests); i++) {
|
||||
active = &tests[i];
|
||||
single_step = tf;
|
||||
seen = signo = trap = error = ip_offset = flags = 0;
|
||||
code = addr_ok = stepped = step_ok = 0;
|
||||
expected_flags = active->flags | (tf ? X86_EFLAGS_TF : 0);
|
||||
if (tf)
|
||||
active->run_tf();
|
||||
else
|
||||
active->run();
|
||||
|
||||
ok = seen && signo == active->signo && trap == active->trap &&
|
||||
error == active->error && ip_offset == active->ip_offset &&
|
||||
flags == expected_flags && code == active->code && addr_ok &&
|
||||
(!tf || (stepped && step_ok));
|
||||
ksft_test_result(ok, "%s%s\n", active->name, tf ? " with TF" : "");
|
||||
if (!ok) {
|
||||
ksft_print_msg("got signal=%d trap=%d error=%#x ip=%d\n",
|
||||
signo, trap, error, ip_offset);
|
||||
ksft_print_msg("got flags=%#x code=%d addr_ok=%d step_ok=%d\n",
|
||||
flags, code, addr_ok, step_ok);
|
||||
ksft_print_msg("expected signal=%d trap=%d error=%#x ip=%d\n",
|
||||
active->signo, active->trap, active->error,
|
||||
active->ip_offset);
|
||||
ksft_print_msg("expected flags=%#x code=%d\n",
|
||||
expected_flags, active->code);
|
||||
}
|
||||
}
|
||||
}
|
||||
test_ptrace();
|
||||
ksft_finished();
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user