| 106 | } |
| 107 | |
| 108 | int |
| 109 | ia32_fetch_syscall_args(struct thread *td) |
| 110 | { |
| 111 | struct proc *p; |
| 112 | struct trapframe *frame; |
| 113 | struct syscall_args *sa; |
| 114 | caddr_t params; |
| 115 | u_int32_t args[8], tmp; |
| 116 | int error, i; |
| 117 | #ifdef COMPAT_43 |
| 118 | u_int32_t eip; |
| 119 | int cs; |
| 120 | #endif |
| 121 | |
| 122 | p = td->td_proc; |
| 123 | frame = td->td_frame; |
| 124 | sa = &td->td_sa; |
| 125 | |
| 126 | #ifdef COMPAT_43 |
| 127 | if (__predict_false(frame->tf_cs == 7 && frame->tf_rip == 2)) { |
| 128 | /* |
| 129 | * In lcall $7,$0 after int $0x80. Convert the user |
| 130 | * frame to what it would be for a direct int 0x80 instead |
| 131 | * of lcall $7,$0, by popping the lcall return address. |
| 132 | */ |
| 133 | error = fueword32((void *)frame->tf_rsp, &eip); |
| 134 | if (error == -1) |
| 135 | return (EFAULT); |
| 136 | cs = fuword16((void *)(frame->tf_rsp + sizeof(u_int32_t))); |
| 137 | if (cs == -1) |
| 138 | return (EFAULT); |
| 139 | |
| 140 | /* |
| 141 | * Unwind in-kernel frame after all stack frame pieces |
| 142 | * were successfully read. |
| 143 | */ |
| 144 | frame->tf_rip = eip; |
| 145 | frame->tf_cs = cs; |
| 146 | frame->tf_rsp += 2 * sizeof(u_int32_t); |
| 147 | frame->tf_err = 7; /* size of lcall $7,$0 */ |
| 148 | } |
| 149 | #endif |
| 150 | |
| 151 | params = (caddr_t)frame->tf_rsp + sizeof(u_int32_t); |
| 152 | sa->code = frame->tf_rax; |
| 153 | |
| 154 | /* |
| 155 | * Need to check if this is a 32 bit or 64 bit syscall. |
| 156 | */ |
| 157 | if (sa->code == SYS_syscall) { |
| 158 | /* |
| 159 | * Code is first argument, followed by actual args. |
| 160 | */ |
| 161 | error = fueword32(params, &tmp); |
| 162 | if (error == -1) |
| 163 | return (EFAULT); |
| 164 | sa->code = tmp; |
| 165 | params += sizeof(int); |