Page MenuHomeFreeBSD

D26406.id76927.diff
No OneTemporary

D26406.id76927.diff

Index: sys/amd64/linux/linux_sysvec.c
===================================================================
--- sys/amd64/linux/linux_sysvec.c
+++ sys/amd64/linux/linux_sysvec.c
@@ -207,19 +207,49 @@
static void
linux_set_syscall_retval(struct thread *td, int error)
{
- struct trapframe *frame = td->td_frame;
+ struct trapframe *frame;
+ frame = td->td_frame;
+
/*
* On Linux only %rcx and %r11 values are not preserved across
* the syscall. So, do not clobber %rdx and %r10.
*/
- td->td_retval[1] = frame->tf_rdx;
- if (error != EJUSTRETURN)
+
+ if (__predict_true(error == 0)) {
+ frame->tf_rax = td->td_retval[0];
frame->tf_r10 = frame->tf_rcx;
+ /* XXX: This shouldn't be needed. */
+ set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
+ return;
+ }
- cpu_set_syscall_retval(td, error);
+ switch (error) {
+ case ERESTART:
+ /*
+ * Reconstruct pc, we know that 'syscall' is 2 bytes,
+ * lcall $X,y is 7 bytes, int 0x80 is 2 bytes.
+ * We saved this in tf_err.
+ *
+ * Require full context restore to get the arguments
+ * in the registers reloaded at return to usermode.
+ */
+ frame->tf_rip -= frame->tf_err;
+ frame->tf_r10 = frame->tf_rcx;
+ set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
+ break;
- /* Restore all registers. */
+ case EJUSTRETURN:
+ break;
+
+ default:
+ frame->tf_rax = SV_ABI_ERRNO(td->td_proc, error);
+ frame->tf_r10 = frame->tf_rcx;
+ set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
+ break;
+ }
+
+ /* Restore all registers. XXX: This shouldn't be needed. */
set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
}

File Metadata

Mime Type
text/plain
Expires
Mon, Jul 6, 1:44 AM (7 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34731730
Default Alt Text
D26406.id76927.diff (1 KB)

Event Timeline