Skip to content

Commit 1fe2ef5

Browse files
committed
aarch64: implement signal delivery
NOTE: For aarch64 vdso is required for sigreturn to work. WIP/TODOs: - save/restore FP state - restart syscalls (and set orig_x0) when necessary - handle multiple signal frames Signed-off-by: Tianhao Wang <[email protected]>
1 parent db660fa commit 1fe2ef5

File tree

4 files changed

+135
-28
lines changed

4 files changed

+135
-28
lines changed

qkernel/src/syscalls/sys_signal.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ pub fn SysRtSigaction(task: &mut Task, args: &SyscallArguments) -> Result<i64> {
8787
let sigAction1 = task.CopyInObj::<SigAct>(sigAction)?;
8888
//info!("signum is {} the signaction is {:?}, ", signum, sigAction1);
8989
newactptr = Some(sigAction1);
90+
debug!("sys_rt_sigaction: received SigAct: {:#?}", sigAction1);
9091
}
9192

9293
let t = task.Thread();

qlib/kernel/SignalDef.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,9 @@ impl UContext {
410410
}
411411
}
412412

413+
// HACK. TODO Refactor this as soon as we have proper VDSO perser.
414+
#[cfg(target_arch = "aarch64")]
415+
pub const VDSO_OFFSET_SIGRETURN: u64 = 0x1120;
413416

414417
// https://elixir.bootlin.com/linux/latest/source/arch/x86/include/uapi/asm/sigcontext.h#L284
415418
#[cfg(target_arch = "x86_64")]
@@ -460,6 +463,7 @@ pub struct SigContext {
460463
pub sp: u64,
461464
pub pc: u64,
462465
pub pstate: u64,
466+
pub oldmask: u64, /* should we do it here? */
463467
/* 4K reserved for FP/SIMD state and future expansion */
464468
pub __reserved: [u8; 4096],
465469
}
@@ -504,8 +508,13 @@ impl SigContext {
504508
impl Default for SigContext {
505509
fn default() -> Self {
506510
Self {
511+
fault_address: 0,
512+
regs: [0u64; 31],
513+
sp: 0,
514+
pc: 0,
515+
pstate: 0,
516+
oldmask: 0,
507517
__reserved: [0u8;4096],
508-
..Default::default()
509518
}
510519
}
511520
}
@@ -523,16 +532,17 @@ impl fmt::Debug for SigContext {
523532
}
524533
}
525534

526-
//TODO how to set sigcontext
535+
//TODO support fpstate
527536
#[cfg(target_arch = "aarch64")]
528537
impl SigContext {
529-
pub fn New(ptRegs: &PtRegs, oldMask: u64, cr2: u64, fpstate: u64) -> Self {
538+
pub fn New(ptRegs: &PtRegs, oldMask: u64, cr2: u64, _fpstate: u64) -> Self {
530539
return Self {
531-
fault_address: 0,
540+
fault_address: cr2,
532541
regs: ptRegs.regs.clone(),
533542
pc: ptRegs.pc,
534543
sp: ptRegs.sp,
535544
pstate: ptRegs.pstate,
545+
oldmask: oldMask,
536546
..Default::default()
537547
};
538548
}
@@ -606,13 +616,13 @@ impl fmt::Debug for SigAct {
606616
f,
607617
"SigAction {{ \n\
608618
handler: {:x}, \n\
609-
flag : {:x}, \n \
610-
flags::HasRestorer: {}, \n \
611-
flags::IsOnStack: {}, \n \
612-
flags::IsRestart: {}, \n \
613-
flags::IsResetHandler: {}, \n \
614-
flags::IsNoDefer: {}, \n \
615-
flags::IsSigInfo: {}, \n \
619+
flag : {:x}, \n\
620+
flags::HasRestorer: {}, \n\
621+
flags::IsOnStack: {}, \n\
622+
flags::IsRestart: {}, \n\
623+
flags::IsResetHandler: {}, \n\
624+
flags::IsNoDefer: {}, \n\
625+
flags::IsSigInfo: {}, \n\
616626
restorer : {:x}, \n\
617627
mask: {:x}, \n}}",
618628
self.handler,

qlib/kernel/arch/aarch64/arch_def.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,11 @@ impl Aarch64Context {
203203
return self.ready.load(Ordering::Acquire);
204204
}
205205
}
206+
//
207+
//
208+
// #[derive(Debug)]
209+
// #[repr(C)]
210+
// pub struct ExceptionContext {
211+
//
212+
// }
213+

qlib/kernel/threadmgr/task_signals.rs

Lines changed: 105 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,6 +1023,7 @@ impl Task {
10231023
// deliverSignal delivers the given signal and returns the following run state.
10241024
pub fn ThreadDeliverSignal(&mut self, info: &SignalInfo, act: &SigAct) -> TaskRunState {
10251025
let sigact = ComputeAction(Signal(info.Signo), act);
1026+
debug!("task_signals: thread deliver signal {:#?}", act);
10261027

10271028
if self.haveSyscallReturn {
10281029
let ret = self.Return();
@@ -1125,12 +1126,12 @@ impl Task {
11251126
// xsave features that are always enabled in signal frame fpstate.
11261127
pub const XFEATURE_MASK_FPSSE: u64 = 0x3;
11271128

1129+
#[cfg(target_arch="x86")]
11281130
pub fn deliverSignalToHandler(&mut self, info: &SignalInfo, sigAct: &SigAct) -> Result<()> {
1129-
#[cfg(target_arch="aarch64")]
1130-
todo!("deliverSignalToHandler not implemented for aarch64");
11311131
let pt = self.GetPtRegs();
11321132
let mut userStack = Stack::New(pt.get_stack_pointer() - 128); // red zone
11331133

1134+
11341135
if sigAct.flags.IsOnStack() && self.signalStack.IsEnable() {
11351136
self.signalStack.SetOnStack();
11361137
if !self.signalStack.Contains(pt.get_stack_pointer()) {
@@ -1202,25 +1203,23 @@ impl Task {
12021203
let currTask = Task::Current();
12031204
let regs = currTask.GetPtRegs();
12041205
*regs = PtRegs::default();
1205-
#[cfg(target_arch = "x86_64")]
1206-
{
1207-
regs.rsp = rsp;
1208-
regs.rcx = sigAct.handler;
1209-
regs.r11 = 0x2;
1210-
regs.rdi = signo;
1211-
regs.rsi = sigInfoAddr;
1212-
regs.rdx = sigCtxAddr;
1213-
regs.rax = 0;
1214-
regs.rip = regs.rcx;
1215-
regs.eflags = regs.r11;
1216-
}
1217-
1206+
regs.rsp = rsp;
1207+
regs.rcx = sigAct.handler; // x86 return address
1208+
regs.r11 = 0x2; // x86 rflags
1209+
regs.rdi = signo; // paras to handler
1210+
regs.rsi = sigInfoAddr;
1211+
regs.rdx = sigCtxAddr;
1212+
regs.rax = 0;
1213+
regs.rip = regs.rcx;
1214+
regs.eflags = regs.r11;
12181215

12191216
return Ok(());
12201217
}
12211218

12221219
#[cfg(target_arch = "x86_64")]
12231220
pub fn SignalReturn(&mut self, _rt: bool) -> Result<i64> {
1221+
// sigret from user signal handler
1222+
// sys_sigreturn
12241223
let pt = self.GetPtRegs();
12251224

12261225
let mut userStack = Stack::New(pt.get_stack_pointer());
@@ -1239,6 +1238,7 @@ impl Task {
12391238
self.savefpsate = true;
12401239
}
12411240

1241+
// restore user stack?
12421242
let alt = uc.Stack;
12431243

12441244
self.SetSignalStack(alt);
@@ -1263,9 +1263,97 @@ impl Task {
12631263
return Err(Error::SysCallRetCtrl(TaskRunState::RunSyscallRet));
12641264
}
12651265

1266-
// TODO has to define a SignalRestore for each arch
1266+
1267+
#[cfg(target_arch = "aarch64")]
1268+
pub fn deliverSignalToHandler(&mut self, info: &SignalInfo, sigAct: &SigAct) -> Result<()> {
1269+
let pt = self.GetPtRegs();
1270+
let mut userStack = Stack::New(pt.get_stack_pointer() - 128); // red zone
1271+
1272+
// if user specifies their own stack
1273+
if sigAct.flags.IsOnStack() && self.signalStack.IsEnable() {
1274+
self.signalStack.SetOnStack();
1275+
if !self.signalStack.Contains(pt.get_stack_pointer()) {
1276+
userStack = Stack::New(self.signalStack.Top());
1277+
}
1278+
}
1279+
let t = self.Thread();
1280+
let mut mask = t.lock().signalMask;
1281+
let haveSavedSignalMask = t.lock().haveSavedSignalMask;
1282+
if haveSavedSignalMask {
1283+
mask = t.lock().savedSignalMask;
1284+
t.lock().haveSavedSignalMask = false;
1285+
}
1286+
1287+
let mut newMask = t.lock().signalMask;
1288+
newMask.0 |= sigAct.mask;
1289+
if !sigAct.flags.IsNoDefer() {
1290+
newMask.0 |= SignalSet::New(Signal(info.Signo)).0;
1291+
}
1292+
t.SetSignalMask(newMask);
1293+
1294+
let mut fault_addr = 0;
1295+
if info.Signo == Signal::SIGBUS || info.Signo == Signal::SIGSEGV {
1296+
fault_addr = info.SigFault().addr;
1297+
}
1298+
1299+
// set up signal frame
1300+
1301+
// let's forget about the fp units for the moment
1302+
let mut uc = UContext::New(pt, mask.0, fault_addr, 0, &self.signalStack);
1303+
// TODO if SA_SIGINFO is not requested, the handler takes the form
1304+
// void handler(int signo)
1305+
// we should push the siginfo and sigctx conditionally
1306+
let sigInfoAddr = userStack.PushType::<SignalInfo>(self, info)?;
1307+
let sigCtxAddr = userStack.PushType::<UContext>(self, &uc)?;
1308+
let signo = info.Signo as u64;
1309+
let currTask = Task::Current();
1310+
let regs = currTask.GetPtRegs();
1311+
*regs = PtRegs::default();
1312+
regs.sp = sigCtxAddr;
1313+
regs.pc = sigAct.handler;
1314+
regs.pstate = 0x0;
1315+
1316+
// parameters to the handler
1317+
// handler(int signo, siginfo_t *info, void *context)
1318+
regs.regs[0] = signo;
1319+
regs.regs[1] = sigInfoAddr;
1320+
regs.regs[2] = sigCtxAddr;
1321+
// TODO set frame pointer regs[29] if there are other sig frames
1322+
if sigAct.flags.HasRestorer() {
1323+
regs.regs[30] = sigAct.restorer;
1324+
} else {
1325+
let vdsoAddr = Task::Current().mm.GetUserVDSOBase();
1326+
assert!(vdsoAddr != 0);
1327+
regs.regs[30] = vdsoAddr + VDSO_OFFSET_SIGRETURN;
1328+
}
1329+
return Ok(());
1330+
}
1331+
12671332
#[cfg(target_arch = "aarch64")]
12681333
pub fn SignalReturn(&mut self, _rt: bool) -> Result<i64> {
1269-
todo!("task_signals: SignalReturn not implemented for aarch64");
1334+
let pt = self.GetPtRegs();
1335+
// pop the signal frame
1336+
let mut userStack = Stack::New(pt.get_stack_pointer());
1337+
let mut uc = UContext::default();
1338+
userStack.PopType::<UContext>(self, &mut uc)?;
1339+
let mut sigInfo = SignalInfo::default();
1340+
userStack.PopType::<SignalInfo>(self, &mut sigInfo)?;
1341+
1342+
let alt = uc.Stack;
1343+
self.SetSignalStack(alt);
1344+
// restore user context
1345+
// ignore restoring fpstate for now.
1346+
pt.Set(&uc.MContext);
1347+
1348+
let oldMask = uc.MContext.oldmask & !(UNBLOCKED_SIGNALS.0);
1349+
let t = self.Thread();
1350+
t.SetSignalMask(SignalSet(oldMask));
1351+
// TODO restart syscall if needed
1352+
if t.lock().HasSignal() {
1353+
t.lock().interruptSelf();
1354+
}
1355+
1356+
// TODO Segfault if badframe
1357+
return Err(Error::SysCallRetCtrl(TaskRunState::RunSyscallRet));
12701358
}
12711359
}

0 commit comments

Comments
 (0)