/*===========================================================================* * do_reboot * *===========================================================================*/ int do_reboot() { message m; /* Check permission to abort the system. */ if (mp->mp_effuid != SUPER_USER) return(EPERM); /* See how the system should be aborted. */ abort_flag = m_in.m_lc_pm_reboot.how; /* notify readclock (some arm systems power off via RTC alarms) */ if (abort_flag & RB_POWERDOWN) { endpoint_t readclock_ep; if (ds_retrieve_label_endpt("readclock.drv", &readclock_ep) == OK) { message m; /* no params to set, nothing we can do if it fails */ _taskcall(readclock_ep, RTCDEV_PWR_OFF, &m); } } /* Order matters here. When VFS is told to reboot, it exits all its * processes, and then would be confused if they're exited again by * SIGKILL. So first kill, then reboot. */ check_sig(-1, SIGKILL, FALSE /* ksig*/); /* kill all users except init */ sys_stop(INIT_PROC_NR); /* stop init, but keep it around */ /* Tell VFS to reboot */ memset(&m, 0, sizeof(m)); m.m_type = VFS_PM_REBOOT; tell_vfs(&mproc[VFS_PROC_NR], &m); return(SUSPEND); /* don't reply to caller */ }
int vm_cachecall(message *m, int call, void *addr, u32_t dev, u64_t dev_offset, u64_t ino, u64_t ino_offset, u32_t *flags, int blocksize) { if(blocksize % PAGE_SIZE) panic("blocksize %d should be a multiple of pagesize %d\n", blocksize, PAGE_SIZE); if(ino_offset % PAGE_SIZE) panic("inode offset %d should be a multiple of pagesize %d\n", ino_offset, PAGE_SIZE); if(dev_offset % PAGE_SIZE) panic("dev offset offset %d should be a multiple of pagesize %d\n", dev_offset, PAGE_SIZE); memset(m, 0, sizeof(*m)); assert(dev != NO_DEV); m->m_u.m_vmmcp.dev_offset_pages = dev_offset/PAGE_SIZE; m->m_u.m_vmmcp.ino_offset_pages = ino_offset/PAGE_SIZE; m->m_u.m_vmmcp.ino = ino; m->m_u.m_vmmcp.block = addr; m->m_u.m_vmmcp.flags_ptr = flags; m->m_u.m_vmmcp.dev = dev; m->m_u.m_vmmcp.pages = blocksize / PAGE_SIZE; m->m_u.m_vmmcp.flags = 0; return _taskcall(VM_PROC_NR, call, m); }
/*===========================================================================* * sched_inherit * *===========================================================================*/ PUBLIC int sched_inherit(endpoint_t scheduler_e, endpoint_t schedulee_e, endpoint_t parent_e, unsigned maxprio, endpoint_t *newscheduler_e) { int rv; message m; assert(_ENDPOINT_P(scheduler_e) >= 0); assert(_ENDPOINT_P(schedulee_e) >= 0); assert(_ENDPOINT_P(parent_e) >= 0); assert(maxprio >= 0); assert(maxprio < NR_SCHED_QUEUES); assert(newscheduler_e); m.SCHEDULING_ENDPOINT = schedulee_e; m.SCHEDULING_PARENT = parent_e; m.SCHEDULING_MAXPRIO = (int) maxprio; /* Send the request to the scheduler */ if ((rv = _taskcall(scheduler_e, SCHEDULING_INHERIT, &m))) { return rv; } /* Store the process' scheduler. Note that this might not be the * scheduler we sent the SCHEDULING_INHERIT message to. That scheduler * might have forwarded the scheduling message on to another scheduler * before returning the message. */ *newscheduler_e = m.SCHEDULING_SCHEDULER; return (OK); }
PRIVATE int do_invoke_ds(int type, const char *ds_name) { cp_grant_id_t g_key; size_t len_key; int access, r; if(type == DS_CHECK || type == DS_RETRIEVE_LABEL) { len_key = DS_MAX_KEYLEN; access = CPF_WRITE; } else { len_key = strlen(ds_name)+1; access = CPF_READ; } /* Grant for key. */ g_key = cpf_grant_direct(DS_PROC_NR, (vir_bytes) ds_name, len_key, access); if(!GRANT_VALID(g_key)) return errno; m.DS_KEY_GRANT = g_key; m.DS_KEY_LEN = len_key; r = _taskcall(DS_PROC_NR, type, &m); cpf_revoke(g_key); return r; }
PUBLIC int sys_setscheduler(int proc, int policy) { message m; m.m1_i1 = proc; m.m1_i2 = policy; return(_taskcall(SYSTASK, SYS_SETSCHEDULER, &m)); }
/*===========================================================================* * sys_nice * *===========================================================================*/ PUBLIC int sys_nice(int proc, int prio) { message m; m.m1_i1 = proc; m.m1_i2 = prio; return(_taskcall(SYSTASK, SYS_NICE, &m)); }
PUBLIC int sys_vmctl_enable_paging(struct mem_map *map) { message m; m.SVMCTL_WHO = SELF; m.SVMCTL_PARAM = VMCTL_ENABLE_PAGING; m.SVMCTL_VALUE = (int) map; return _taskcall(SYSTASK, SYS_VMCTL, &m); }
/*===========================================================================* * vm_brk * *===========================================================================*/ int vm_brk(endpoint_t ep, char *addr) { message m; m.VMB_ENDPOINT = ep; m.VMB_ADDR = (void *) addr; return _taskcall(VM_PROC_NR, VM_BRK, &m); }
/*===========================================================================* * vm_umap * *===========================================================================*/ PUBLIC int vm_ctl(int what, int param) { message m; int result; m.VCTL_WHAT = what; m.VCTL_PARAM = param; return _taskcall(VM_PROC_NR, VM_CTL, &m); }
/*===========================================================================* * do_gcov_flush * *===========================================================================*/ PUBLIC int do_gcov_flush() { /* A userland tool has requested the gcov data from another * process (possibly vfs itself). Grant the target process * access to the supplied buffer, and perform the call that * makes the target copy its buffer to the caller (incl vfs * itself). */ struct fproc *rfp; ssize_t size; cp_grant_id_t grantid; int r, n; pid_t target; message m; size = m_in.GCOV_BUFF_SZ; target = m_in.GCOV_PID; /* If the wrong process is sent to, the system hangs; so make this root-only. */ if (!super_user) return(EPERM); /* Find target gcov process. */ for(n = 0; n < NR_PROCS; n++) { if(fproc[n].fp_endpoint != NONE && fproc[n].fp_pid == target) break; } if(n >= NR_PROCS) { printf("VFS: gcov process %d not found\n", target); return(ESRCH); } rfp = &fproc[n]; /* Grant target process to requestor's buffer. */ if ((grantid = cpf_grant_magic(rfp->fp_endpoint, who_e, (vir_bytes) m_in.GCOV_BUFF_P, size, CPF_WRITE)) < 0) { printf("VFS: gcov_flush: grant failed\n"); return(ENOMEM); } if(rfp->fp_endpoint == VFS_PROC_NR) { /* Request is for VFS itself. */ r = gcov_flush(grantid, size); } else { /* Perform generic GCOV request. */ m.GCOV_GRANT = grantid; m.GCOV_BUFF_SZ = size; r = _taskcall(rfp->fp_endpoint, COMMON_REQ_GCOV_DATA, &m); } cpf_revoke(grantid); return(r); }
/*===========================================================================* * sys_runctl * *===========================================================================*/ PUBLIC int sys_runctl(endpoint_t proc_ep, int action, int flags) { message m; m.RC_ENDPT = proc_ep; m.RC_ACTION = action; m.RC_FLAGS = flags; return(_taskcall(SYSTASK, SYS_RUNCTL, &m)); }
int sys_klog_copy(int endpoint, void *data_ptr) { message m; /* message we use for the kernel call */ m.KLOG_ENDPT = endpoint; /* endpoint of user program */ m.KLOG_PTR = data_ptr; /* pointer to kernel log in user program */ /* do the kernel call and return the result */ return (_taskcall(SYSTASK, SYS_KLOG_COPY, &m)); }
int vm_update(endpoint_t src_e, endpoint_t dst_e) { message m; memset(&m, 0, sizeof(m)); m.m_lsys_vm_update.src = src_e; m.m_lsys_vm_update.dst = dst_e; return _taskcall(VM_PROC_NR, VM_RS_UPDATE, &m); }
int sys_privctl(int proc, int request, int i, void *p) { message m; m.CTL_ENDPT = proc; m.CTL_REQUEST = request; m.CTL_MM_PRIV = i; m.CTL_ARG_PTR = p; return _taskcall(SYSTASK, SYS_PRIVCTL, &m); }
PUBLIC int sys_vmctl(endpoint_t who, int param, u32_t value) { message m; int r; m.SVMCTL_WHO = who; m.SVMCTL_PARAM = param; m.SVMCTL_VALUE = value; r = _taskcall(SYSTASK, SYS_VMCTL, &m); return(r); }
PUBLIC int sys_vsafecopy(struct vscp_vec *vec, int els) { /* Vectored variant of sys_safecopy*. */ message copy_mess; copy_mess.VSCP_VEC_ADDR = (char *) vec; copy_mess.VSCP_VEC_SIZE = els; return(_taskcall(SYSTASK, SYS_VSAFECOPY, ©_mess)); }
/*===========================================================================* * vm_allocmem * *===========================================================================*/ PUBLIC int vm_allocmem(phys_clicks bytes, phys_clicks *retmembase) { message m; int result; m.VMAM_BYTES = (char *) bytes; result = _taskcall(VM_PROC_NR, VM_ALLOCMEM, &m); if(result == OK) *retmembase = m.VMAM_MEMBASE; return result; }
/*===========================================================================* * sched_start * *===========================================================================*/ PUBLIC int sched_start(endpoint_t scheduler_e, endpoint_t schedulee_e, endpoint_t parent_e, int maxprio, int quantum, int cpu, endpoint_t *newscheduler_e) { int rv; message m; /* No scheduler given? We are done. */ if(scheduler_e == NONE) { return OK; } assert(_ENDPOINT_P(schedulee_e) >= 0); assert(_ENDPOINT_P(parent_e) >= 0); assert(maxprio >= 0); assert(maxprio < NR_SCHED_QUEUES); assert(quantum > 0); assert(newscheduler_e); /* The KERNEL must schedule this process. */ if(scheduler_e == KERNEL) { if ((rv = sys_schedctl(SCHEDCTL_FLAG_KERNEL, schedulee_e, maxprio, quantum, cpu)) != OK) { return rv; } *newscheduler_e = scheduler_e; return OK; } /* A user-space scheduler must schedule this process. */ m.SCHEDULING_ENDPOINT = schedulee_e; m.SCHEDULING_PARENT = parent_e; m.SCHEDULING_MAXPRIO = (int) maxprio; m.SCHEDULING_QUANTUM = (int) quantum; /* Send the request to the scheduler */ if ((rv = _taskcall(scheduler_e, SCHEDULING_START, &m))) { return rv; } /* Store the process' scheduler. Note that this might not be the * scheduler we sent the SCHEDULING_START message to. That scheduler * might have forwarded the scheduling message on to another scheduler * before returning the message. */ *newscheduler_e = m.SCHEDULING_SCHEDULER; return (OK); }
/*===========================================================================* * vm_umap * *===========================================================================*/ int vm_umap(int seg, vir_bytes offset, vir_bytes len, phys_bytes *addr) { message m; int result; m.VMU_SEG = seg; m.VMU_OFFSET = (char *) offset; m.VMU_LENGTH = (char *) len; result = _taskcall(VM_PROC_NR, VM_UMAP, &m); *addr = (phys_bytes) m.VMU_RETADDR; return result; }
PUBLIC int sys_vmctl_get_cr3_i386(endpoint_t who, u32_t *cr3) { message m; int r; m.SVMCTL_WHO = who; m.SVMCTL_PARAM = VMCTL_I386_GETCR3; r = _taskcall(SYSTASK, SYS_VMCTL, &m); if(r == OK) { *cr3 = m.SVMCTL_VALUE; } return(r); }
PUBLIC int sys_vmctl_get_pagefault_i386(endpoint_t *who, u32_t *cr2, u32_t *err) { message m; int r; m.SVMCTL_WHO = SELF; m.SVMCTL_PARAM = VMCTL_GET_PAGEFAULT; r = _taskcall(SYSTASK, SYS_VMCTL, &m); if(r == OK) { *who = m.SVMCTL_PF_WHO; *cr2 = m.SVMCTL_PF_I386_CR2; *err = m.SVMCTL_PF_I386_ERR; } return(r); }
PUBLIC int sys_vmctl_get_memreq(endpoint_t *who, vir_bytes *mem, vir_bytes *len, int *wrflag, endpoint_t *requestor) { message m; int r; m.SVMCTL_WHO = SELF; m.SVMCTL_PARAM = VMCTL_MEMREQ_GET; r = _taskcall(SYSTASK, SYS_VMCTL, &m); if(r == OK) { *who = m.SVMCTL_MRG_EP; *mem = (vir_bytes) m.SVMCTL_MRG_ADDR; *len = m.SVMCTL_MRG_LEN; *wrflag = m.SVMCTL_MRG_WRITE; *requestor = (endpoint_t) m.SVMCTL_MRG_REQUESTOR; } return r; }
/*===========================================================================* * sched_nice * *===========================================================================*/ PUBLIC int sched_nice(struct mproc *rmp, int nice) { int rv; message m; /* If the kernel is the scheduler, we don't allow messing with the * priority. If you want to control process priority, assign the process * to a user-space scheduler */ if (rmp->mp_scheduler == KERNEL || rmp->mp_scheduler == NONE) return (EINVAL); m.SCHEDULING_ENDPOINT = rmp->mp_endpoint; m.SCHEDULING_NICE = nice; if ((rv = _taskcall(rmp->mp_scheduler, SCHEDULING_SET_NICE, &m))) { return rv; } return (OK); }
int mini_ds_retrieve_u32(char *ds_name, u32_t *value) { int r; message m; size_t len_key; len_key = strlen(ds_name)+1; m.DS_KEY_GRANT = ds_name; m.DS_KEY_LEN = len_key; m.DS_FLAGS = DS_TYPE_U32; r = _taskcall(DS_PROC_NR, DS_RETRIEVE_LIBC, &m); if(r == OK) { /* Assign u32 value. */ *value = m.DS_VAL; } return r; }
/*===========================================================================* * sched_stop * *===========================================================================*/ int sched_stop(endpoint_t scheduler_e, endpoint_t schedulee_e) { int rv; message m; /* If the kernel is the scheduler, it will implicitly stop scheduling * once another process takes over or the process terminates */ if (scheduler_e == KERNEL || scheduler_e == NONE) return(OK); /* User-scheduled, perform the call */ assert(_ENDPOINT_P(scheduler_e) >= 0); assert(_ENDPOINT_P(schedulee_e) >= 0); m.SCHEDULING_ENDPOINT = schedulee_e; if ((rv = _taskcall(scheduler_e, SCHEDULING_STOP, &m))) { return rv; } return (OK); }
int checkperms(endpoint_t endpt, char *path, size_t size) { cp_grant_id_t grant; message m; int r; if ((grant = cpf_grant_direct(VFS_PROC_NR, (vir_bytes) path, size, CPF_READ | CPF_WRITE)) == GRANT_INVALID) return ENOMEM; memset(&m, 0, sizeof(m)); m.m_lsys_vfs_checkperms.endpt = endpt; m.m_lsys_vfs_checkperms.grant = grant; m.m_lsys_vfs_checkperms.count = size; r = _taskcall(VFS_PROC_NR, VFS_CHECKPERMS, &m); cpf_revoke(grant); return r; }
/*===========================================================================* * sched_stop * *===========================================================================*/ PUBLIC int sched_stop(struct mproc *rmp) { int rv; message m; /* If the kernel is the scheduler, it will implicitly stop scheduling * once another process takes over or the process terminates */ if (rmp->mp_scheduler == KERNEL || rmp->mp_scheduler == NONE) return(OK); m.SCHEDULING_ENDPOINT = rmp->mp_endpoint; if ((rv = _taskcall(rmp->mp_scheduler, SCHEDULING_STOP, &m))) { return rv; } /* sched_stop is either called when the process is exiting or it is * being moved between schedulers. If it is being moved between * schedulers, we need to set the mp_scheduler to NONE so that PM * doesn't forward messages to the process' scheduler while being moved * (such as sched_nice). */ rmp->mp_scheduler = NONE; return (OK); }
/*===========================================================================* * sched_start * *===========================================================================*/ PUBLIC int sched_start(endpoint_t ep, struct mproc *rmp, int flags) { int rv; message m; /*printf("-------------------sched_start() of pm\n");*/ m.SCHEDULING_ENDPOINT = rmp->mp_endpoint; m.SCHEDULING_PARENT = mproc[rmp->mp_parent].mp_endpoint; m.SCHEDULING_NICE = rmp->mp_nice; /* Send the request to the scheduler */ if ((rv = _taskcall(ep, SCHEDULING_START, &m))) { return rv; } /* Store the process' scheduler. Note that this might not be the * scheduler we sent the SCHEDULING_START message to. That scheduler * might have forwarded the scheduling message on to another scheduler * before returning the message. */ rmp->mp_scheduler = m.SCHEDULING_SCHEDULER; return (OK); }