mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Clear DF
flag during signal handling to conform to x86-64 calling convention
This commit is contained in:
parent
9e5075dab7
commit
05ff441577
@ -218,6 +218,15 @@ pub fn handle_user_signal(
|
||||
} else {
|
||||
user_ctx.set_arguments(sig_num, 0, 0);
|
||||
}
|
||||
// CPU architecture-dependent logic
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_arch = "x86_64")] {
|
||||
// Clear `DF` flag for C function entry to conform to x86-64 calling convention.
|
||||
// Bit 10 is the DF flag.
|
||||
const X86_RFLAGS_DF: usize = 1 << 10;
|
||||
user_ctx.general_regs_mut().rflags &= !X86_RFLAGS_DF;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -2,4 +2,6 @@
|
||||
|
||||
include ../test_common.mk
|
||||
|
||||
EXTRA_C_FLAGS := -static
|
||||
# Removed `-static` to enable dynamic linking.
|
||||
# Refer to "signal_rflags_df.c" for details on how dynamic linking affects DF flag testing.
|
||||
EXTRA_C_FLAGS :=
|
||||
|
60
test/apps/signal_c/signal_rflags_df.c
Normal file
60
test/apps/signal_c/signal_rflags_df.c
Normal file
@ -0,0 +1,60 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdatomic.h>
|
||||
#include <assert.h>
|
||||
|
||||
volatile sig_atomic_t signaled = 0; // Volatile to avoid optimization issues
|
||||
|
||||
void read_df_flag_and_assert(int expect)
|
||||
{
|
||||
unsigned long rflags;
|
||||
asm volatile("pushfq\n\t" // Push the RFLAGS register onto the stack
|
||||
"popq %0\n\t" // Pop it into a variable
|
||||
: "=r"(rflags)); // Output constraint
|
||||
int df = (rflags >> 10) & 1; // The DF flag is the 10th bit of RFLAGS
|
||||
assert(df == expect);
|
||||
}
|
||||
|
||||
void sigint_handler(int signum)
|
||||
{
|
||||
read_df_flag_and_assert(0);
|
||||
signaled = 1; // Update volatile variable to notify main
|
||||
}
|
||||
|
||||
// A regression test for the DF flag bug fixed in https://github.com/asterinas/asterinas/pull/1638.
|
||||
// Also checks PR #1637 when dynamically linked. If calling a function from a shared library mapped
|
||||
// via mmap triggers a page fault and #1637 is not fixed, it may cause kernel panic.
|
||||
int main()
|
||||
{
|
||||
// Check DF flag in main before setting it
|
||||
read_df_flag_and_assert(0);
|
||||
asm volatile("std"); // Set DF flag
|
||||
read_df_flag_and_assert(1);
|
||||
|
||||
// Set up the SIGINT signal handler
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = sigint_handler;
|
||||
sa.sa_flags = 0;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
|
||||
// Send SIGINT to itself
|
||||
if (kill(getpid(), SIGINT) != 0) {
|
||||
perror("kill");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Wait for the signal handler to update the variable
|
||||
while (!signaled) {
|
||||
// Spin until the signal is handled
|
||||
}
|
||||
|
||||
// Check DF flag in main after signal handling
|
||||
read_df_flag_and_assert(1);
|
||||
|
||||
_exit(0); // Exit immediately without cleanup because DF is set
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user