Ejemplo n.º 1
0
/*
 * Finish a fork operation, with process p2 nearly set up.
 * Copy and update the pcb, set up the stack so that the child
 * ready to run and return to user mode.
 */
void
cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
{
	struct pcb *pcb2;
	struct trapframe *tf;

	if ((flags & RFPROC) == 0)
		return;

	if (td1 == curthread) {
		/*
		 * Save the tpidr_el0 and the vfp state, these normally happen
		 * in cpu_switch, but if userland changes these then forks
		 * this may not have happened.
		 */
		td1->td_pcb->pcb_tpidr_el0 = READ_SPECIALREG(tpidr_el0);
		td1->td_pcb->pcb_tpidrro_el0 = READ_SPECIALREG(tpidrro_el0);
#ifdef VFP
		if ((td1->td_pcb->pcb_fpflags & PCB_FP_STARTED) != 0)
			vfp_save_state(td1, td1->td_pcb);
#endif
	}

	pcb2 = (struct pcb *)(td2->td_kstack +
	    td2->td_kstack_pages * PAGE_SIZE) - 1;

	td2->td_pcb = pcb2;
	bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));

	td2->td_proc->p_md.md_l0addr =
	    vtophys(vmspace_pmap(td2->td_proc->p_vmspace)->pm_l0);

	tf = (struct trapframe *)STACKALIGN((struct trapframe *)pcb2 - 1);
	bcopy(td1->td_frame, tf, sizeof(*tf));
	tf->tf_x[0] = 0;
	tf->tf_x[1] = 0;
	tf->tf_spsr = td1->td_frame->tf_spsr & PSR_M_32;

	td2->td_frame = tf;

	/* Set the return value registers for fork() */
	td2->td_pcb->pcb_x[8] = (uintptr_t)fork_return;
	td2->td_pcb->pcb_x[9] = (uintptr_t)td2;
	td2->td_pcb->pcb_x[PCB_LR] = (uintptr_t)fork_trampoline;
	td2->td_pcb->pcb_sp = (uintptr_t)td2->td_frame;
	td2->td_pcb->pcb_fpusaved = &td2->td_pcb->pcb_fpustate;
	td2->td_pcb->pcb_vfpcpu = UINT_MAX;

	/* Setup to release spin count in fork_exit(). */
	td2->td_md.md_spinlock_count = 1;
	td2->td_md.md_saved_daif = td1->td_md.md_saved_daif & ~DAIF_I_MASKED;
}
Ejemplo n.º 2
0
/*
 * Performance Monitors Control Register
 */
static uint32_t
arm64_pmcr_read(void)
{
	uint32_t reg;

	reg = READ_SPECIALREG(PMCR_EL0);

	return (reg);
}
Ejemplo n.º 3
0
/*
 * Performance Count Register N
 */
static uint32_t
arm64_pmcn_read(unsigned int pmc)
{

	KASSERT(pmc < arm64_npmcs, ("%s: illegal PMC number %d", __func__, pmc));

	WRITE_SPECIALREG(PMSELR_EL0, pmc);

	isb();

	return (READ_SPECIALREG(PMXEVCNTR_EL0));
}
Ejemplo n.º 4
0
static int
arm64_intr(struct trapframe *tf)
{
	struct arm64_cpu *pc;
	int retval, ri;
	struct pmc *pm;
	int error;
	int reg, cpu;

	cpu = curcpu;
	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
	    ("[arm64,%d] CPU %d out of range", __LINE__, cpu));

	retval = 0;
	pc = arm64_pcpu[cpu];

	for (ri = 0; ri < arm64_npmcs; ri++) {
		pm = arm64_pcpu[cpu]->pc_arm64pmcs[ri].phw_pmc;
		if (pm == NULL)
			continue;
		if (!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
			continue;

		/* Check if counter is overflowed */
		reg = (1 << ri);
		if ((READ_SPECIALREG(PMOVSCLR_EL0) & reg) == 0)
			continue;
		/* Clear Overflow Flag */
		WRITE_SPECIALREG(PMOVSCLR_EL0, reg);

		isb();

		retval = 1; /* Found an interrupting PMC. */
		if (pm->pm_state != PMC_STATE_RUNNING)
			continue;

		error = pmc_process_interrupt(PMC_HR, pm, tf);
		if (error)
			arm64_stop_pmc(cpu, ri);

		/* Reload sampling count */
		arm64_write_pmc(cpu, ri, pm->pm_sc.pm_reloadcount);
	}

	return (retval);
}
Ejemplo n.º 5
0
static void
cache_setup(void)
{
	int dcache_line_shift, icache_line_shift;
	uint32_t ctr_el0;

	ctr_el0 = READ_SPECIALREG(ctr_el0);

	/* Read the log2 words in each D cache line */
	dcache_line_shift = CTR_DLINE_SIZE(ctr_el0);
	/* Get the D cache line size */
	dcache_line_size = sizeof(int) << dcache_line_shift;

	/* And the same for the I cache */
	icache_line_shift = CTR_ILINE_SIZE(ctr_el0);
	icache_line_size = sizeof(int) << icache_line_shift;

	idcache_line_size = MIN(dcache_line_size, icache_line_size);
}