Ejemplo n.º 1
0
int
sysarch(struct thread *td, struct sysarch_args *uap)
{
	int error;
	void *tlsbase;

	switch (uap->op) {
	case MIPS_SET_TLS:
		td->td_md.md_tls = uap->parms;

		/*
		 * If there is an user local register implementation (ULRI)
		 * update it as well.  Add the TLS and TCB offsets so the
		 * value in this register is adjusted like in the case of the
		 * rdhwr trap() instruction handler.
		 */
		if (cpuinfo.userlocal_reg == true) {
#if defined(__mips_n64) && defined(COMPAT_FREEBSD32)
			mips_wr_userlocal((unsigned long)(uap->parms +
			    TLS_TP_OFFSET + TLS_TCB_SIZE32));
#else
			mips_wr_userlocal((unsigned long)(uap->parms +
			    TLS_TP_OFFSET + TLS_TCB_SIZE));
#endif
		}
		return (0);
	case MIPS_GET_TLS: 
		tlsbase = td->td_md.md_tls;
		error = copyout(&tlsbase, uap->parms, sizeof(tlsbase));
		return (error);
	default:
		break;
	}
	return (EINVAL);
}
Ejemplo n.º 2
0
int
sysarch(struct thread *td, struct sysarch_args *uap)
{
	int error;
	void *tlsbase;

	switch (uap->op) {
	case MIPS_SET_TLS:
		td->td_md.md_tls = uap->parms;

		/*
		 * If there is an user local register implementation (ULRI)
		 * update it as well.  Add the TLS and TCB offsets so the
		 * value in this register is adjusted like in the case of the
		 * rdhwr trap() instruction handler.
		 *
		 * XXXSS For more information why this offset is required see:
		 * 	'git show c6be4f4d2d1b71c04de5d3bbb6933ce2dbcdb317'
		 */
		if (cpuinfo.userlocal_reg == true) {
#if defined(__mips_n64) && defined(COMPAT_FREEBSD32)
			mips_wr_userlocal((unsigned long)(uap->parms +
			    TLS_TP_OFFSET + TLS_TCB_SIZE32));
#else
			mips_wr_userlocal((unsigned long)(uap->parms +
			    TLS_TP_OFFSET + TLS_TCB_SIZE));
#endif
		}
		return (0);

	case MIPS_GET_TLS:
		tlsbase = td->td_md.md_tls;
		error = copyout(&tlsbase, uap->parms, sizeof(tlsbase));
		return (error);

	case MIPS_GET_COUNT:
		td->td_retval[0] = mips_rd_count();
		return (0);

	default:
		break;
	}
	return (EINVAL);
}
Ejemplo n.º 3
0
int
cpu_set_user_tls(struct thread *td, void *tls_base)
{

#if defined(__mips_n64) && defined(COMPAT_FREEBSD32)
	if (td->td_proc && SV_PROC_FLAG(td->td_proc, SV_ILP32))
		td->td_md.md_tls_tcb_offset = TLS_TP_OFFSET + TLS_TCB_SIZE32;
	else
#endif
	td->td_md.md_tls_tcb_offset = TLS_TP_OFFSET + TLS_TCB_SIZE;
	td->td_md.md_tls = (char*)tls_base;
	if (td == curthread && cpuinfo.userlocal_reg == true) {
		mips_wr_userlocal((unsigned long)tls_base +
		    td->td_md.md_tls_tcb_offset);
	}

	return (0);
}
Ejemplo n.º 4
0
int
cheriabi_set_user_tls(struct thread *td, struct chericap *tls_base)
{
	int error;
	/* XXX-AR: add a TLS alignment check here */

	td->td_md.md_tls_tcb_offset = TLS_TP_OFFSET + TLS_TCB_SIZE_C;
	/*
	 * Don't require any particular permissions or size and allow NULL.
	 * If the caller passes nonsense, they just get nonsense results.
	 */
	error = cheriabi_cap_to_ptr((caddr_t *)&td->td_md.md_tls, tls_base,
	    0, 0, 1);
	if (error)
		return (error);
	cheri_capability_copy(&td->td_md.md_tls_cap, tls_base);
	/* XXX: should support a crdhwr version */
	if (curthread == td && cpuinfo.userlocal_reg == true) {
		/*
		 * If there is an user local register implementation
		 * (ULRI) update it as well.  Add the TLS and TCB
		 * offsets so the value in this register is
		 * adjusted like in the case of the rdhwr trap()
		 * instruction handler.
		 *
		 * The user local register needs the TLS and TCB
		 * offsets because the compiler simply generates a
		 * 'rdhwr reg, $29' instruction to access thread local
		 * storage (i.e., variables with the '_thread'
		 * attribute).
		 */
		mips_wr_userlocal((unsigned long)((caddr_t)td->td_md.md_tls +
		    td->td_md.md_tls_tcb_offset));
	}

	return (0);
}