/* Ensure all threads in this mm have the same pointer masking mode. */ if (IS_ENABLED(CONFIG_RISCV_ISA_SUPM) && p->mm && (clone_flags & CLONE_VM))
set_bit(MM_CONTEXT_LOCK_PMLEN, &p->mm->context.flags);
memset(&p->thread.s, 0, sizeof(p->thread.s));
/* p->thread holds context to be restored by __switch_to() */ if (unlikely(args->fn)) { /* Kernel thread */
memset(childregs, 0, sizeof(struct pt_regs)); /* Supervisor/Machine, irqs on: */
childregs->status = SR_PP | SR_PIE;
p->thread.s[0] = (unsignedlong)args->fn;
p->thread.s[1] = (unsignedlong)args->fn_arg;
p->thread.ra = (unsignedlong)ret_from_fork_kernel_asm;
} else {
*childregs = *(current_pt_regs()); /* Turn off status.VS */
riscv_v_vstate_off(childregs); if (usp) /* User fork */
childregs->sp = usp; if (clone_flags & CLONE_SETTLS)
childregs->tp = tls;
childregs->a0 = 0; /* Return value of fork() */
p->thread.ra = (unsignedlong)ret_from_fork_user_asm;
}
p->thread.riscv_v_flags = 0; if (has_vector() || has_xtheadvector())
riscv_v_thread_alloc(p);
p->thread.sp = (unsignedlong)childregs; /* kernel sp */ return 0;
}
if (!riscv_has_extension_unlikely(RISCV_ISA_EXT_SUPM)) return -EINVAL;
if (is_compat_thread(ti)) return -EINVAL;
if (arg & ~valid_mask) return -EINVAL;
/* * Prefer the smallest PMLEN that satisfies the user's request, * in case choosing a larger PMLEN has a performance impact.
*/
pmlen = FIELD_GET(PR_PMLEN_MASK, arg); if (pmlen == PMLEN_0) {
pmm = ENVCFG_PMM_PMLEN_0;
} elseif (pmlen <= PMLEN_7 && have_user_pmlen_7) {
pmlen = PMLEN_7;
pmm = ENVCFG_PMM_PMLEN_7;
} elseif (pmlen <= PMLEN_16 && have_user_pmlen_16) {
pmlen = PMLEN_16;
pmm = ENVCFG_PMM_PMLEN_16;
} else { return -EINVAL;
}
/* * Do not allow the enabling of the tagged address ABI if globally * disabled via sysctl abi.tagged_addr_disabled, if pointer masking * is disabled for userspace.
*/ if (arg & PR_TAGGED_ADDR_ENABLE && (tagged_addr_disabled || !pmlen)) return -EINVAL;
if (!(arg & PR_TAGGED_ADDR_ENABLE))
pmlen = PMLEN_0;
long get_tagged_addr_ctrl(struct task_struct *task)
{ struct thread_info *ti = task_thread_info(task); long ret = 0;
if (!riscv_has_extension_unlikely(RISCV_ISA_EXT_SUPM)) return -EINVAL;
if (is_compat_thread(ti)) return -EINVAL;
/* * The mm context's pmlen is set only when the tagged address ABI is * enabled, so the effective PMLEN must be extracted from envcfg.PMM.
*/ switch (task->thread.envcfg & ENVCFG_PMM) { case ENVCFG_PMM_PMLEN_7:
ret = FIELD_PREP(PR_PMLEN_MASK, PMLEN_7); break; case ENVCFG_PMM_PMLEN_16:
ret = FIELD_PREP(PR_PMLEN_MASK, PMLEN_16); break;
}
if (task->mm->context.pmlen)
ret |= PR_TAGGED_ADDR_ENABLE;
/* * Global sysctl to disable the tagged user addresses support. This control * only prevents the tagged address ABI enabling via prctl() and does not * disable it for tasks that already opted in to the relaxed ABI.
*/
staticint __init tagged_addr_init(void)
{ if (!riscv_has_extension_unlikely(RISCV_ISA_EXT_SUPM)) return 0;
/* * envcfg.PMM is a WARL field. Detect which values are supported. * Assume the supported PMLEN values are the same on all harts.
*/
csr_clear(CSR_ENVCFG, ENVCFG_PMM);
have_user_pmlen_7 = try_to_set_pmm(ENVCFG_PMM_PMLEN_7);
have_user_pmlen_16 = try_to_set_pmm(ENVCFG_PMM_PMLEN_16);
if (!register_sysctl("abi", tagged_addr_sysctl_table)) return -EINVAL;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.