void syscall_linux(void) { assert(current != NULL); struct trapframe *tf = current->tf; uint32_t arg[6]; int num = tf->tf_regs.reg_r[MIPS_REG_V0] - 4000; if (num >= 0 && num < 1000) { if (linux_syscall_table[num] != NULL) { arg[0] = tf->tf_regs.reg_r[MIPS_REG_A0]; arg[1] = tf->tf_regs.reg_r[MIPS_REG_A1]; arg[2] = tf->tf_regs.reg_r[MIPS_REG_A2]; arg[3] = tf->tf_regs.reg_r[MIPS_REG_A3]; uint32_t* stack_pointor = tf->tf_regs.reg_r[MIPS_REG_SP]; arg[4] = stack_pointor[4]; arg[5] = stack_pointor[5]; //kprintf("MIPS_sys $%d $%d\n", current->pid, num); //TODO: 0 indicates that syscall always suceeded, not reasonable but seems //It works. Need to be set before syscall because fork won't return. if(num == __NR_pipe) { int fd[2]; if(file_pipe(fd) != 0) { tf->tf_regs.reg_r[MIPS_REG_A3] = 1; } else { tf->tf_regs.reg_r[MIPS_REG_A3] = 0; tf->tf_regs.reg_r[MIPS_REG_V0] = fd[0]; tf->tf_regs.reg_r[MIPS_REG_V1] = fd[1]; kprintf("pipe %d %d\n", fd[0], fd[1]); } } else { tf->tf_regs.reg_r[MIPS_REG_A3] = 0; tf->tf_regs.reg_r[MIPS_REG_V0] = linux_syscall_table[num] (arg); } /*if(num == __NR_read || num == __NR_write) { if(((int)tf->tf_regs.reg_r[MIPS_REG_V0]) < 0) { tf->tf_regs.reg_r[MIPS_REG_A3] = 1; } }*/ return; } } print_trapframe(tf); panic("Undefined Linux OABI syscall %d, pid = %d, name = %s.\n", num, current->pid, current->name); }
int sysfile_pipe(int *fd_store) { struct mm_struct *mm = current->mm; int ret, fd[2]; if (!user_mem_check(mm, (uintptr_t)fd_store, sizeof(fd), 1)) { return -E_INVAL; } if ((ret = file_pipe(fd)) == 0) { lock_mm(mm); { if (!copy_to_user(mm, fd_store, fd, sizeof(fd))) { ret = -E_INVAL; } } unlock_mm(mm); if (ret != 0) { file_close(fd[0]), file_close(fd[1]); } } return ret; }