diff --git a/common/inc/s3k/syscall.h b/common/inc/s3k/syscall.h index 18db2340..0a6da378 100644 --- a/common/inc/s3k/syscall.h +++ b/common/inc/s3k/syscall.h @@ -23,6 +23,7 @@ typedef enum { // Monitor calls S3K_SYS_MON_SUSPEND, S3K_SYS_MON_RESUME, + S3K_SYS_MON_YIELD, S3K_SYS_MON_REG_READ, S3K_SYS_MON_REG_WRITE, S3K_SYS_MON_CAP_READ, @@ -109,6 +110,7 @@ s3k_err_t s3k_pmp_load(s3k_cidx_t pmp_idx, s3k_pmp_slot_t pmp_slot); s3k_err_t s3k_pmp_unload(s3k_cidx_t pmp_idx); s3k_err_t s3k_mon_suspend(s3k_cidx_t mon_idx, s3k_pid_t pid); s3k_err_t s3k_mon_resume(s3k_cidx_t mon_idx, s3k_pid_t pid); +s3k_err_t s3k_mon_yield(s3k_cidx_t mon_idx, s3k_pid_t pid); s3k_err_t s3k_mon_reg_read(s3k_cidx_t mon_idx, s3k_pid_t pid, s3k_reg_t reg, uint64_t *val); s3k_err_t s3k_mon_reg_write(s3k_cidx_t mon_idx, s3k_pid_t pid, s3k_reg_t reg, @@ -133,6 +135,7 @@ s3k_err_t s3k_try_pmp_load(s3k_cidx_t pmp_idx, s3k_pmp_slot_t pmp_slot); s3k_err_t s3k_try_pmp_unload(s3k_cidx_t pmp_idx); s3k_err_t s3k_try_mon_suspend(s3k_cidx_t mon_idx, s3k_pid_t pid); s3k_err_t s3k_try_mon_resume(s3k_cidx_t mon_idx, s3k_pid_t pid); +s3k_err_t s3k_try_mon_yield(s3k_cidx_t mon_idx, s3k_pid_t pid); s3k_err_t s3k_try_mon_reg_read(s3k_cidx_t mon_idx, s3k_pid_t pid, s3k_reg_t reg, uint64_t *val); s3k_err_t s3k_try_mon_reg_write(s3k_cidx_t mon_idx, s3k_pid_t pid, diff --git a/common/src/s3k/s3k.c b/common/src/s3k/s3k.c index dcee3ff3..78118bf6 100644 --- a/common/src/s3k/s3k.c +++ b/common/src/s3k/s3k.c @@ -484,6 +484,15 @@ s3k_err_t s3k_mon_resume(s3k_cidx_t mon_idx, s3k_pid_t pid) return err; } +s3k_err_t s3k_mon_yield(s3k_cidx_t mon_idx, s3k_pid_t pid) +{ + s3k_err_t err; + do { + err = s3k_try_mon_yield(mon_idx, pid); + } while (err == S3K_ERR_PREEMPTED); + return err; +} + s3k_err_t s3k_mon_reg_read(s3k_cidx_t mon_idx, s3k_pid_t pid, s3k_reg_t reg, uint64_t *val) { @@ -622,6 +631,14 @@ s3k_err_t s3k_try_mon_resume(s3k_cidx_t mon, s3k_pid_t pid) return do_ecall(S3K_SYS_MON_RESUME, args).err; } +s3k_err_t s3k_try_mon_yield(s3k_cidx_t mon, s3k_pid_t pid) +{ + sys_args_t args = { + .mon_state = {mon, pid} + }; + return do_ecall(S3K_SYS_MON_YIELD, args).err; +} + s3k_err_t s3k_try_mon_reg_read(s3k_cidx_t mon, s3k_pid_t pid, s3k_reg_t reg, uint64_t *val) { diff --git a/kernel/inc/cap_monitor.h b/kernel/inc/cap_monitor.h index 7ee0eca1..9957aa29 100644 --- a/kernel/inc/cap_monitor.h +++ b/kernel/inc/cap_monitor.h @@ -65,6 +65,18 @@ err_t cap_monitor_suspend(cte_t mon, pid_t pid); */ err_t cap_monitor_resume(cte_t mon, pid_t pid); +/** + * Yield remaining execution time to specified ready process. + * + * @param mon The CTE of the monitor capability. + * @param pid The ID of the process to be run. + * @return SUCCESS if the process is resumed. + * ERR_EMPTY if the CTE is empty. + * ERR_INVALID_MONITOR if the CTE has the wrong capability type or is + * unauthorized. ERR_INVALID_STATE if the process is not ready. + */ +err_t cap_monitor_yield(cte_t mon, pid_t pid, proc_t **next); + /** * Reads a register value from a specified suspended process. * diff --git a/kernel/inc/syscall.h b/kernel/inc/syscall.h index 26461618..1884a8f9 100644 --- a/kernel/inc/syscall.h +++ b/kernel/inc/syscall.h @@ -26,6 +26,7 @@ typedef enum { // Monitor SYS_MON_SUSPEND, SYS_MON_RESUME, + SYS_MON_YIELD, SYS_MON_REG_READ, SYS_MON_REG_WRITE, SYS_MON_CAP_READ, diff --git a/kernel/src/cap_monitor.c b/kernel/src/cap_monitor.c index 136a5b4a..82fc012d 100644 --- a/kernel/src/cap_monitor.c +++ b/kernel/src/cap_monitor.c @@ -44,6 +44,22 @@ err_t cap_monitor_resume(cte_t mon, pid_t pid) return err; } +err_t cap_monitor_yield(cte_t mon, pid_t pid, proc_t **next) +{ + err_t err = check_monitor(mon, pid, false); + if (!err) { + proc_t *proc = proc_get(pid); + proc_t *curr = proc_get(cte_pid(mon)); + if (proc_acquire(proc)) { + curr->regs[REG_T0] = SUCCESS; + *next = proc; + return YIELD; + } + curr->regs[REG_T0] = ERR_INVALID_STATE; + } + return err; +} + err_t cap_monitor_reg_read(cte_t mon, pid_t pid, reg_t reg, uint64_t *val) { err_t err = check_monitor(mon, pid, true); diff --git a/kernel/src/syscall.c b/kernel/src/syscall.c index 54b07d07..e7eef9e0 100644 --- a/kernel/src/syscall.c +++ b/kernel/src/syscall.c @@ -35,6 +35,7 @@ static err_t sys_pmp_load(proc_t *p, const sys_args_t *args, uint64_t *ret); static err_t sys_pmp_unload(proc_t *p, const sys_args_t *args, uint64_t *ret); static err_t sys_mon_suspend(proc_t *p, const sys_args_t *args, uint64_t *ret); static err_t sys_mon_resume(proc_t *p, const sys_args_t *args, uint64_t *ret); +static err_t sys_mon_yield(proc_t *p, const sys_args_t *args, uint64_t *ret); static err_t sys_mon_reg_read(proc_t *p, const sys_args_t *args, uint64_t *ret); static err_t sys_mon_reg_write(proc_t *p, const sys_args_t *args, uint64_t *ret); @@ -50,12 +51,12 @@ static err_t sys_sock_sendrecv(proc_t *p, const sys_args_t *args, typedef err_t (*sys_handler_t)(proc_t *, const sys_args_t *, uint64_t *); sys_handler_t handlers[] = { - sys_get_info, sys_reg_read, sys_reg_write, sys_sync, - sys_cap_read, sys_cap_move, sys_cap_delete, sys_cap_revoke, - sys_cap_derive, sys_pmp_load, sys_pmp_unload, sys_mon_suspend, - sys_mon_resume, sys_mon_reg_read, sys_mon_reg_write, sys_mon_cap_read, - sys_mon_cap_move, sys_mon_pmp_load, sys_mon_pmp_unload, sys_sock_send, - sys_sock_sendrecv, + sys_get_info, sys_reg_read, sys_reg_write, sys_sync, + sys_cap_read, sys_cap_move, sys_cap_delete, sys_cap_revoke, + sys_cap_derive, sys_pmp_load, sys_pmp_unload, sys_mon_suspend, + sys_mon_resume, sys_mon_yield, sys_mon_reg_read, sys_mon_reg_write, + sys_mon_cap_read, sys_mon_cap_move, sys_mon_pmp_load, sys_mon_pmp_unload, + sys_sock_send, sys_sock_sendrecv, }; void handle_syscall(proc_t *p) @@ -201,6 +202,7 @@ err_t validate_arguments(uint64_t call, const sys_args_t *args) case SYS_MON_SUSPEND: case SYS_MON_RESUME: + case SYS_MON_YIELD: if (!valid_idx(args->mon_state.mon_idx)) return ERR_INVALID_INDEX; if (!valid_pid(args->mon_state.pid)) @@ -390,6 +392,12 @@ err_t sys_mon_resume(proc_t *p, const sys_args_t *args, uint64_t *ret) return cap_monitor_resume(mon, args->mon_state.pid); } +err_t sys_mon_yield(proc_t *p, const sys_args_t *args, uint64_t *ret) +{ + cte_t mon = ctable_get(p->pid, args->mon_state.mon_idx); + return cap_monitor_yield(mon, args->mon_state.pid, (proc_t **)ret); +} + err_t sys_mon_reg_read(proc_t *p, const sys_args_t *args, uint64_t *ret) { cte_t mon = ctable_get(p->pid, args->mon_reg.mon_idx);