Example #1
0
int do_cpuvar(struct proc *caller_ptr, message *m_ptr){

char *p_pi_ptr = m_ptr->m1_p1;
int i;
struct proc **queueHeadPtr = NULL;
struct proc qh_send[NR_SCHED_QUEUES];
struct proc nullProc;

queueHeadPtr = get_cpu_var(0,run_q_head);

nullProc.p_priority = -1;

for(i=0; i<NR_SCHED_QUEUES; i++){
	qh_send[i] = nullProc;
}
for(i=0; i<NR_SCHED_QUEUES; i++){
	if(queueHeadPtr[i]){
		qh_send[i] = *queueHeadPtr[i];
	}
}

data_copy_vmcheck(caller_ptr, KERNEL,(vir_bytes) &qh_send, caller_ptr->p_endpoint,(vir_bytes) p_pi_ptr, sizeof(struct proc)*NR_SCHED_QUEUES);

return(OK);
}
Example #2
0
/*===========================================================================*
 *			        do_sysctl				     *
 *===========================================================================*/
PUBLIC int do_sysctl(struct proc * caller, message * m_ptr)
{
  vir_bytes len, buf;
  static char mybuf[DIAG_BUFSIZE];
  int s, i, proc_nr;

  switch (m_ptr->SYSCTL_CODE) {
    case SYSCTL_CODE_DIAG:
        buf = (vir_bytes) m_ptr->SYSCTL_ARG1;
        len = (vir_bytes) m_ptr->SYSCTL_ARG2;
	if(len < 1 || len > DIAG_BUFSIZE) {
		printf("do_sysctl: diag for %d: len %d out of range\n",
			caller->p_endpoint, len);
		return EINVAL;
	}
	if((s=data_copy_vmcheck(caller, caller->p_endpoint, buf, KERNEL,
					(vir_bytes) mybuf, len)) != OK) {
		printf("do_sysctl: diag for %d: len %d: copy failed: %d\n",
			caller->p_endpoint, len, s);
		return s;
	}
	for(i = 0; i < len; i++)
		kputc(mybuf[i]);
	kputc(END_OF_KMESS);
	return OK;
    case SYSCTL_CODE_STACKTRACE:
	if(!isokendpt(m_ptr->SYSCTL_ARG2, &proc_nr))
		return EINVAL;
	proc_stacktrace(proc_addr(proc_nr));
	proc_dump_regs(proc_addr(proc_nr));
	return OK;
    default:
	printf("do_sysctl: invalid request %d\n", m_ptr->SYSCTL_CODE);
        return(EINVAL);
  }

  panic("do_sysctl: can't happen");

  return(OK);
}
Example #3
0
/*===========================================================================*
 *			        do_getinfo				     *
 *===========================================================================*/
int do_getinfo(struct proc * caller, message * m_ptr)
{
/* Request system information to be copied to caller's address space. This
 * call simply copies entire data structures to the caller.
 */
  size_t length;
  vir_bytes src_vir; 
  int nr_e, nr, r;
  int wipe_rnd_bin = -1;
  struct proc *p;

  /* Set source address and length based on request type. */
  switch (m_ptr->I_REQUEST) {
    case GET_MACHINE: {
        length = sizeof(struct machine);
        src_vir = (vir_bytes) &machine;
        break;
    }
    case GET_KINFO: {
        length = sizeof(struct kinfo);
        src_vir = (vir_bytes) &kinfo;
        break;
    }
    case GET_LOADINFO: {
        length = sizeof(struct loadinfo);
        src_vir = (vir_bytes) &kloadinfo;
        break;
    }
    case GET_CPUINFO: {
        length = sizeof(cpu_info);
        src_vir = (vir_bytes) &cpu_info;
        break;
    }
    case GET_HZ: {
        length = sizeof(system_hz);
        src_vir = (vir_bytes) &system_hz;
        break;
    }
    case GET_IMAGE: {
        length = sizeof(struct boot_image) * NR_BOOT_PROCS;
        src_vir = (vir_bytes) image;
        break;
    }
    case GET_IRQHOOKS: {
        length = sizeof(struct irq_hook) * NR_IRQ_HOOKS;
        src_vir = (vir_bytes) irq_hooks;
        break;
    }
    case GET_PROCTAB: {
	update_idle_time();
        length = sizeof(struct proc) * (NR_PROCS + NR_TASKS);
        src_vir = (vir_bytes) proc;
        break;
    }
    case GET_PRIVTAB: {
        length = sizeof(struct priv) * (NR_SYS_PROCS);
        src_vir = (vir_bytes) priv;
        break;
    }
    case GET_PROC: {
        nr_e = (m_ptr->I_VAL_LEN2_E == SELF) ?
		caller->p_endpoint : m_ptr->I_VAL_LEN2_E;
	if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
        length = sizeof(struct proc);
        src_vir = (vir_bytes) proc_addr(nr);
        break;
    }
    case GET_PRIV: {
        nr_e = (m_ptr->I_VAL_LEN2_E == SELF) ?
            caller->p_endpoint : m_ptr->I_VAL_LEN2_E;
        if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
        length = sizeof(struct priv);
        src_vir = (vir_bytes) priv_addr(nr_to_id(nr));
        break;
    }
    case GET_REGS: {
        nr_e = (m_ptr->I_VAL_LEN2_E == SELF) ?
            caller->p_endpoint : m_ptr->I_VAL_LEN2_E;
        if(!isokendpt(nr_e, &nr)) return EINVAL; /* validate request */
        p = proc_addr(nr);
        length = sizeof(p->p_reg);
        src_vir = (vir_bytes) &p->p_reg;
        break;
    }
    case GET_WHOAMI: {
	int len;
	/* GET_WHOAMI uses m3 and only uses the message contents for info. */
	m_ptr->GIWHO_EP = caller->p_endpoint;
	len = MIN(sizeof(m_ptr->GIWHO_NAME), sizeof(caller->p_name))-1;
	strncpy(m_ptr->GIWHO_NAME, caller->p_name, len);
	m_ptr->GIWHO_NAME[len] = '\0';
	m_ptr->GIWHO_PRIVFLAGS = priv(caller)->s_flags;
	return OK;
    }
    case GET_MONPARAMS: {
        src_vir = (vir_bytes) params_buffer;
	length = sizeof(params_buffer);
        break;
    }
    case GET_RANDOMNESS: {		
        static struct k_randomness copy;	/* copy to keep counters */
	int i;

        copy = krandom;
        for (i= 0; i<RANDOM_SOURCES; i++) {
  		krandom.bin[i].r_size = 0;	/* invalidate random data */
  		krandom.bin[i].r_next = 0;
	}
    	length = sizeof(copy);
    	src_vir = (vir_bytes) &copy;
    	break;
    }
    case GET_RANDOMNESS_BIN: {		
	int bin = m_ptr->I_VAL_LEN2_E;

	if(bin < 0 || bin >= RANDOM_SOURCES) {
		printf("SYSTEM: GET_RANDOMNESS_BIN: %d out of range\n", bin);
		return EINVAL;
	}

	if(krandom.bin[bin].r_size < RANDOM_ELEMENTS)
		return ENOENT;

    	length = sizeof(krandom.bin[bin]);
    	src_vir = (vir_bytes) &krandom.bin[bin];

	wipe_rnd_bin = bin;

    	break;
    }
    case GET_KMESSAGES: {
        length = sizeof(struct kmessages);
        src_vir = (vir_bytes) &kmess;
        break;
    }
    case GET_IRQACTIDS: {
        length = sizeof(irq_actids);
        src_vir = (vir_bytes) irq_actids;
        break;
    }
    case GET_IDLETSC: {
	struct proc * idl;
	update_idle_time();
	idl = proc_addr(IDLE);
        length = sizeof(idl->p_cycles);
        src_vir = (vir_bytes) &idl->p_cycles;
        break;
    }
    default:
	printf("do_getinfo: invalid request %d\n", m_ptr->I_REQUEST);
        return(EINVAL);
  }

  /* Try to make the actual copy for the requested data. */
  if (m_ptr->I_VAL_LEN > 0 && length > m_ptr->I_VAL_LEN) return (E2BIG);
  r = data_copy_vmcheck(caller, KERNEL, src_vir, caller->p_endpoint,
	(vir_bytes) m_ptr->I_VAL_PTR, length);

  if(r != OK) return r;

	if(wipe_rnd_bin >= 0 && wipe_rnd_bin < RANDOM_SOURCES) {
		krandom.bin[wipe_rnd_bin].r_size = 0;
		krandom.bin[wipe_rnd_bin].r_next = 0;
	}

  return(OK);
}
Example #4
0
/*===========================================================================*
 *				do_vumap				     *
 *===========================================================================*/
int do_vumap(struct proc *caller, message *m_ptr)
{
/* Map a vector of grants or local virtual addresses to physical addresses.
 * Designed to be used by drivers to perform an efficient lookup of physical
 * addresses for the purpose of direct DMA from/to a remote process.
 */
  endpoint_t endpt, source, granter;
  struct proc *procp;
  struct vumap_vir vvec[MAPVEC_NR];
  struct vumap_phys pvec[MAPVEC_NR];
  vir_bytes vaddr, paddr, vir_addr;
  phys_bytes phys_addr;
  int i, r, proc_nr, vcount, pcount, pmax, access;
  size_t size, chunk, offset;

  endpt = caller->p_endpoint;

  /* Retrieve and check input parameters. */
  source = m_ptr->VUMAP_ENDPT;
  vaddr = (vir_bytes) m_ptr->VUMAP_VADDR;
  vcount = m_ptr->VUMAP_VCOUNT;
  offset = m_ptr->VUMAP_OFFSET;
  access = m_ptr->VUMAP_ACCESS;
  paddr = (vir_bytes) m_ptr->VUMAP_PADDR;
  pmax = m_ptr->VUMAP_PMAX;

  if (vcount <= 0 || pmax <= 0)
	return EINVAL;

  if (vcount > MAPVEC_NR) vcount = MAPVEC_NR;
  if (pmax > MAPVEC_NR) pmax = MAPVEC_NR;

  /* Convert access to safecopy access flags. */
  switch (access) {
  case VUA_READ:		access = CPF_READ; break;
  case VUA_WRITE:		access = CPF_WRITE; break;
  case VUA_READ|VUA_WRITE:	access = CPF_READ|CPF_WRITE; break;
  default:			return EINVAL;
  }

  /* Copy in the vector of virtual addresses. */
  size = vcount * sizeof(vvec[0]);

  if (data_copy(endpt, vaddr, KERNEL, (vir_bytes) vvec, size) != OK)
	return EFAULT;

  pcount = 0;

  /* Go through the input entries, one at a time. Stop early in case the output
   * vector has filled up.
   */
  for (i = 0; i < vcount && pcount < pmax; i++) {
	size = vvec[i].vv_size;
	if (size <= offset)
		return EINVAL;
	size -= offset;

	if (source != SELF) {
		r = verify_grant(source, endpt, vvec[i].vv_grant, size, access,
			offset, &vir_addr, &granter);
		if (r != OK)
			return r;
	} else {
		vir_addr = vvec[i].vv_addr + offset;
		granter = endpt;
	}

	okendpt(granter, &proc_nr);
	procp = proc_addr(proc_nr);

	/* Each virtual range is made up of one or more physical ranges. */
	while (size > 0 && pcount < pmax) {
		chunk = vm_lookup_range(procp, vir_addr, &phys_addr, size);

		if (!chunk) {
			/* Try to get the memory allocated, unless the memory
			 * is supposed to be there to be read from.
			 */
			if (access & CPF_READ)
				return EFAULT;

			/* This call may suspend the current call, or return an
			 * error for a previous invocation.
			 */
			return vm_check_range(caller, procp, vir_addr, size);
		}

		pvec[pcount].vp_addr = phys_addr;
		pvec[pcount].vp_size = chunk;
		pcount++;

		vir_addr += chunk;
		size -= chunk;
	}

	offset = 0;
  }

  /* Copy out the resulting vector of physical addresses. */
  assert(pcount > 0);

  size = pcount * sizeof(pvec[0]);

  r = data_copy_vmcheck(caller, KERNEL, (vir_bytes) pvec, endpt, paddr, size);

  if (r == OK)
	m_ptr->VUMAP_PCOUNT = pcount;

  return r;
}
Example #5
0
/*===========================================================================*
 *			      do_sigsend				     *
 *===========================================================================*/
int do_sigsend(struct proc * caller, message * m_ptr)
{
/* Handle sys_sigsend, POSIX-style signal handling. */

  struct sigmsg smsg;
  register struct proc *rp;
  struct sigcontext sc, *scp;
  struct sigframe fr, *frp;
  int proc_nr, r;

  if (!isokendpt(m_ptr->SIG_ENDPT, &proc_nr)) return(EINVAL);
  if (iskerneln(proc_nr)) return(EPERM);
  rp = proc_addr(proc_nr);

  /* Get the sigmsg structure into our address space.  */
  if((r=data_copy_vmcheck(caller, caller->p_endpoint,
		(vir_bytes) m_ptr->SIG_CTXT_PTR, KERNEL, (vir_bytes) &smsg,
		(phys_bytes) sizeof(struct sigmsg))) != OK)
	return r;

  /* Compute the user stack pointer where sigcontext will be stored. */
  smsg.sm_stkptr = arch_get_sp(rp);
  scp = (struct sigcontext *) smsg.sm_stkptr - 1;

  /* Copy the registers to the sigcontext structure. */
  memcpy(&sc.sc_regs, (char *) &rp->p_reg, sizeof(sigregs));

#if defined(__i386__)
  sc.trap_style = rp->p_seg.p_kern_trap_style;

  if(sc.trap_style == KTS_NONE) {
  	printf("do_sigsend: sigsend an unsaved process\n");
	return EINVAL;
  }

    if(proc_used_fpu(rp)) {
	    /* save the FPU context before saving it to the sig context */
	    save_fpu(rp);
	    memcpy(&sc.sc_fpu_state, rp->p_seg.fpu_state, FPU_XFP_SIZE);
    }
#endif

  /* Finish the sigcontext initialization. */
  sc.sc_mask = smsg.sm_mask;
  sc.sc_flags = rp->p_misc_flags & MF_FPU_INITIALIZED;

  /* Copy the sigcontext structure to the user's stack. */
  if((r=data_copy_vmcheck(caller, KERNEL, (vir_bytes) &sc, m_ptr->SIG_ENDPT,
	(vir_bytes) scp, (vir_bytes) sizeof(struct sigcontext))) != OK)
      return r;

  /* Initialize the sigframe structure. */
  frp = (struct sigframe *) scp - 1;
  fr.sf_scpcopy = scp;
  fr.sf_retadr2= (void (*)()) rp->p_reg.pc;
  fr.sf_fp = rp->p_reg.fp;
  rp->p_reg.fp = (reg_t) &frp->sf_fp;
  fr.sf_scp = scp;

  fpu_sigcontext(rp, &fr, &sc);

  fr.sf_signo = smsg.sm_signo;
  fr.sf_retadr = (void (*)()) smsg.sm_sigreturn;

#if defined(__arm__)
  /* use the ARM link register to set the return address from the signal
   * handler
   */
  rp->p_reg.lr = (reg_t) fr.sf_retadr;
  if(rp->p_reg.lr & 1) { printf("sigsend: LSB LR makes no sense.\n"); }

  /* pass signal handler parameters in registers */
  rp->p_reg.retreg = (reg_t) fr.sf_signo;
  rp->p_reg.r1 = (reg_t) fr.sf_code;
  rp->p_reg.r2 = (reg_t) fr.sf_scp;
  rp->p_misc_flags |= MF_CONTEXT_SET;
#endif

  /* Copy the sigframe structure to the user's stack. */
  if((r=data_copy_vmcheck(caller, KERNEL, (vir_bytes) &fr,
	m_ptr->SIG_ENDPT, (vir_bytes) frp, 
      (vir_bytes) sizeof(struct sigframe))) != OK)
      return r;

  /* Reset user registers to execute the signal handler. */
  rp->p_reg.sp = (reg_t) frp;
  rp->p_reg.pc = (reg_t) smsg.sm_sighandler;

  /* Signal handler should get clean FPU. */
  rp->p_misc_flags &= ~MF_FPU_INITIALIZED;

  if(!RTS_ISSET(rp, RTS_PROC_STOP)) {
	printf("system: warning: sigsend a running process\n");
	printf("caller stack: ");
	proc_stacktrace(caller);
  }

  return(OK);
}
Example #6
0
/*===========================================================================*
 *			      do_sigsend				     *
 *===========================================================================*/
PUBLIC int do_sigsend(struct proc * caller, message * m_ptr)
{
/* Handle sys_sigsend, POSIX-style signal handling. */

  struct sigmsg smsg;
  register struct proc *rp;
  struct sigcontext sc, *scp;
  struct sigframe fr, *frp;
  int proc_nr, r;

  if (!isokendpt(m_ptr->SIG_ENDPT, &proc_nr)) return(EINVAL);
  if (iskerneln(proc_nr)) return(EPERM);
  rp = proc_addr(proc_nr);

  /* Get the sigmsg structure into our address space.  */
  if((r=data_copy_vmcheck(caller, caller->p_endpoint,
		(vir_bytes) m_ptr->SIG_CTXT_PTR, KERNEL, (vir_bytes) &smsg,
		(phys_bytes) sizeof(struct sigmsg))) != OK)
	return r;

  /* Compute the user stack pointer where sigcontext will be stored. */
  scp = (struct sigcontext *) smsg.sm_stkptr - 1;

  /* Copy the registers to the sigcontext structure. */
  memcpy(&sc.sc_regs, (char *) &rp->p_reg, sizeof(sigregs));
  #if (_MINIX_CHIP == _CHIP_INTEL)
    if(proc_used_fpu(rp)) {
	    /* save the FPU context before saving it to the sig context */
	    save_fpu(rp);
	    memcpy(&sc.sc_fpu_state, rp->p_fpu_state.fpu_save_area_p,
	   	 FPU_XFP_SIZE);
    }
  #endif

  /* Finish the sigcontext initialization. */
  sc.sc_mask = smsg.sm_mask;
  sc.sc_flags = rp->p_misc_flags & MF_FPU_INITIALIZED;

  /* Copy the sigcontext structure to the user's stack. */
  if((r=data_copy_vmcheck(caller, KERNEL, (vir_bytes) &sc, m_ptr->SIG_ENDPT,
	(vir_bytes) scp, (vir_bytes) sizeof(struct sigcontext))) != OK)
      return r;

  /* Initialize the sigframe structure. */
  frp = (struct sigframe *) scp - 1;
  fr.sf_scpcopy = scp;
  fr.sf_retadr2= (void (*)()) rp->p_reg.pc;
  fr.sf_fp = rp->p_reg.fp;
  rp->p_reg.fp = (reg_t) &frp->sf_fp;
  fr.sf_scp = scp;

  fpu_sigcontext(rp, &fr, &sc);

  fr.sf_signo = smsg.sm_signo;
  fr.sf_retadr = (void (*)()) smsg.sm_sigreturn;

  /* Copy the sigframe structure to the user's stack. */
  if((r=data_copy_vmcheck(caller, KERNEL, (vir_bytes) &fr,
	m_ptr->SIG_ENDPT, (vir_bytes) frp, 
      (vir_bytes) sizeof(struct sigframe))) != OK)
      return r;

  /* Reset user registers to execute the signal handler. */
  rp->p_reg.sp = (reg_t) frp;
  rp->p_reg.pc = (reg_t) smsg.sm_sighandler;

  /* Signal handler should get clean FPU. */
  rp->p_misc_flags &= ~MF_FPU_INITIALIZED;

  if(!RTS_ISSET(rp, RTS_PROC_STOP)) {
	printf("system: warning: sigsend a running process\n");
	printf("caller stack: ");
	proc_stacktrace(caller);
  }

  return(OK);
}