| 1011 | } |
| 1012 | |
| 1013 | int |
| 1014 | cpu_fetch_syscall_args(struct thread *td) |
| 1015 | { |
| 1016 | struct proc *p; |
| 1017 | struct trapframe *frame; |
| 1018 | struct syscall_args *sa; |
| 1019 | caddr_t params; |
| 1020 | long tmp; |
| 1021 | int error; |
| 1022 | #ifdef COMPAT_43 |
| 1023 | u_int32_t eip; |
| 1024 | int cs; |
| 1025 | #endif |
| 1026 | |
| 1027 | p = td->td_proc; |
| 1028 | frame = td->td_frame; |
| 1029 | sa = &td->td_sa; |
| 1030 | |
| 1031 | #ifdef COMPAT_43 |
| 1032 | if (__predict_false(frame->tf_cs == 7 && frame->tf_eip == 2)) { |
| 1033 | /* |
| 1034 | * In lcall $7,$0 after int $0x80. Convert the user |
| 1035 | * frame to what it would be for a direct int 0x80 instead |
| 1036 | * of lcall $7,$0, by popping the lcall return address. |
| 1037 | */ |
| 1038 | error = fueword32((void *)frame->tf_esp, &eip); |
| 1039 | if (error == -1) |
| 1040 | return (EFAULT); |
| 1041 | cs = fuword16((void *)(frame->tf_esp + sizeof(u_int32_t))); |
| 1042 | if (cs == -1) |
| 1043 | return (EFAULT); |
| 1044 | |
| 1045 | /* |
| 1046 | * Unwind in-kernel frame after all stack frame pieces |
| 1047 | * were successfully read. |
| 1048 | */ |
| 1049 | frame->tf_eip = eip; |
| 1050 | frame->tf_cs = cs; |
| 1051 | frame->tf_esp += 2 * sizeof(u_int32_t); |
| 1052 | frame->tf_err = 7; /* size of lcall $7,$0 */ |
| 1053 | } |
| 1054 | #endif |
| 1055 | |
| 1056 | sa->code = frame->tf_eax; |
| 1057 | params = (caddr_t)frame->tf_esp + sizeof(uint32_t); |
| 1058 | |
| 1059 | /* |
| 1060 | * Need to check if this is a 32 bit or 64 bit syscall. |
| 1061 | */ |
| 1062 | if (sa->code == SYS_syscall) { |
| 1063 | /* |
| 1064 | * Code is first argument, followed by actual args. |
| 1065 | */ |
| 1066 | error = fueword(params, &tmp); |
| 1067 | if (error == -1) |
| 1068 | return (EFAULT); |
| 1069 | sa->code = tmp; |
| 1070 | params += sizeof(uint32_t); |