/* * The xstateregs_active() routine is the same as the regset_fpregs_active() routine, * as the "regset->n" for the xstate regset will be updated based on the feature * capabilities supported by the xsave.
*/ int regset_fpregs_active(struct task_struct *target, conststruct user_regset *regset)
{ return regset->n;
}
int regset_xregset_fpregs_active(struct task_struct *target, conststruct user_regset *regset)
{ if (boot_cpu_has(X86_FEATURE_FXSR)) return regset->n; else return 0;
}
/* * The regset get() functions are invoked from: * * - coredump to dump the current task's fpstate. If the current task * owns the FPU then the memory state has to be synchronized and the * FPU register state preserved. Otherwise fpstate is already in sync. * * - ptrace to dump fpstate of a stopped task, in which case the registers * have already been saved to fpstate on context switch.
*/ staticvoid sync_fpstate(struct fpu *fpu)
{ if (fpu == x86_task_fpu(current))
fpu_sync_fpstate(fpu);
}
/* * Invalidate cached FPU registers before modifying the stopped target * task's fpstate. * * This forces the target task on resume to restore the FPU registers from * modified fpstate. Otherwise the task might skip the restore and operate * with the cached FPU registers which discards the modifications.
*/ staticvoid fpu_force_restore(struct fpu *fpu)
{ /* * Only stopped child tasks can be used to modify the FPU * state in the fpstate buffer:
*/
WARN_ON_FPU(fpu == x86_task_fpu(current));
if (!cpu_feature_enabled(X86_FEATURE_USER_SHSTK) ||
!ssp_active(target, regset)) return -ENODEV;
sync_fpstate(fpu);
cetregs = get_xsave_addr(&fpu->fpstate->regs.xsave, XFEATURE_CET_USER); if (WARN_ON(!cetregs)) { /* * This shouldn't ever be NULL because shadow stack was * verified to be enabled above. This means * MSR_IA32_U_CET.CET_SHSTK_EN should be 1 and so * XFEATURE_CET_USER should not be in the init state.
*/ return -ENODEV;
}
if (!cpu_feature_enabled(X86_FEATURE_USER_SHSTK) ||
!ssp_active(target, regset)) return -ENODEV;
if (pos != 0 || count != sizeof(user_ssp)) return -EINVAL;
r = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &user_ssp, 0, -1); if (r) return r;
/* * Some kernel instructions (IRET, etc) can cause exceptions in the case * of disallowed CET register values. Just prevent invalid values.
*/ if (user_ssp >= TASK_SIZE_MAX || !IS_ALIGNED(user_ssp, 8)) return -EINVAL;
fpu_force_restore(fpu);
cetregs = get_xsave_addr(xsave, XFEATURE_CET_USER); if (WARN_ON(!cetregs)) { /* * This shouldn't ever be NULL because shadow stack was * verified to be enabled above. This means * MSR_IA32_U_CET.CET_SHSTK_EN should be 1 and so * XFEATURE_CET_USER should not be in the init state.
*/ return -ENODEV;
}
/* No funny business with partial or oversized writes is permitted. */ if (pos != 0 || count != sizeof(struct user_i387_ia32_struct)) return -EINVAL;
if (!cpu_feature_enabled(X86_FEATURE_FPU)) return fpregs_soft_set(target, regset, pos, count, kbuf, ubuf);
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &env, 0, -1); if (ret) return ret;
fpu_force_restore(fpu);
if (cpu_feature_enabled(X86_FEATURE_FXSR))
convert_to_fxsr(&fpu->fpstate->regs.fxsave, &env); else
memcpy(&fpu->fpstate->regs.fsave, &env, sizeof(env));
/* * Update the header bit in the xsave header, indicating the * presence of FP.
*/ if (cpu_feature_enabled(X86_FEATURE_XSAVE))
fpu->fpstate->regs.xsave.header.xfeatures |= XFEATURE_MASK_FP;
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.