diff options
| author | Rodrigo Vivi <[email protected]> | 2018-07-23 09:13:12 -0700 | 
|---|---|---|
| committer | Rodrigo Vivi <[email protected]> | 2018-07-23 09:13:12 -0700 | 
| commit | c74a7469f97c0f40b46e82ee979f9fb1bb6e847c (patch) | |
| tree | f2690a1a916b73ef94657fbf0e0141ae57701825 /arch/arm64/kernel/ssbd.c | |
| parent | 6f15a7de86c8cf2dc09fc9e6d07047efa40ef809 (diff) | |
| parent | 500775074f88d9cf5416bed2ca19592812d62c41 (diff) | |
Merge drm/drm-next into drm-intel-next-queued
We need a backmerge to get DP_DPCD_REV_14 before we push other
i915 changes to dinq that could break compilation.
Signed-off-by: Rodrigo Vivi <[email protected]>
Diffstat (limited to 'arch/arm64/kernel/ssbd.c')
| -rw-r--r-- | arch/arm64/kernel/ssbd.c | 110 | 
1 files changed, 110 insertions, 0 deletions
| diff --git a/arch/arm64/kernel/ssbd.c b/arch/arm64/kernel/ssbd.c new file mode 100644 index 000000000000..3432e5ef9f41 --- /dev/null +++ b/arch/arm64/kernel/ssbd.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 ARM Ltd, All Rights Reserved. + */ + +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/thread_info.h> + +#include <asm/cpufeature.h> + +/* + * prctl interface for SSBD + * FIXME: Drop the below ifdefery once merged in 4.18. + */ +#ifdef PR_SPEC_STORE_BYPASS +static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl) +{ +	int state = arm64_get_ssbd_state(); + +	/* Unsupported */ +	if (state == ARM64_SSBD_UNKNOWN) +		return -EINVAL; + +	/* Treat the unaffected/mitigated state separately */ +	if (state == ARM64_SSBD_MITIGATED) { +		switch (ctrl) { +		case PR_SPEC_ENABLE: +			return -EPERM; +		case PR_SPEC_DISABLE: +		case PR_SPEC_FORCE_DISABLE: +			return 0; +		} +	} + +	/* +	 * Things are a bit backward here: the arm64 internal API +	 * *enables the mitigation* when the userspace API *disables +	 * speculation*. So much fun. +	 */ +	switch (ctrl) { +	case PR_SPEC_ENABLE: +		/* If speculation is force disabled, enable is not allowed */ +		if (state == ARM64_SSBD_FORCE_ENABLE || +		    task_spec_ssb_force_disable(task)) +			return -EPERM; +		task_clear_spec_ssb_disable(task); +		clear_tsk_thread_flag(task, TIF_SSBD); +		break; +	case PR_SPEC_DISABLE: +		if (state == ARM64_SSBD_FORCE_DISABLE) +			return -EPERM; +		task_set_spec_ssb_disable(task); +		set_tsk_thread_flag(task, TIF_SSBD); +		break; +	case PR_SPEC_FORCE_DISABLE: +		if (state == ARM64_SSBD_FORCE_DISABLE) +			return -EPERM; +		task_set_spec_ssb_disable(task); +		task_set_spec_ssb_force_disable(task); +		set_tsk_thread_flag(task, TIF_SSBD); +		break; +	default: +		return -ERANGE; +	} + +	return 0; +} + +int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which, +			     unsigned long ctrl) +{ +	switch (which) { +	case PR_SPEC_STORE_BYPASS: +		return ssbd_prctl_set(task, ctrl); +	default: +		return -ENODEV; +	} +} + +static int ssbd_prctl_get(struct task_struct *task) +{ +	switch (arm64_get_ssbd_state()) { +	case ARM64_SSBD_UNKNOWN: +		return -EINVAL; +	case ARM64_SSBD_FORCE_ENABLE: +		return PR_SPEC_DISABLE; +	case ARM64_SSBD_KERNEL: +		if (task_spec_ssb_force_disable(task)) +			return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE; +		if (task_spec_ssb_disable(task)) +			return PR_SPEC_PRCTL | PR_SPEC_DISABLE; +		return PR_SPEC_PRCTL | PR_SPEC_ENABLE; +	case ARM64_SSBD_FORCE_DISABLE: +		return PR_SPEC_ENABLE; +	default: +		return PR_SPEC_NOT_AFFECTED; +	} +} + +int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which) +{ +	switch (which) { +	case PR_SPEC_STORE_BYPASS: +		return ssbd_prctl_get(task); +	default: +		return -ENODEV; +	} +} +#endif	/* PR_SPEC_STORE_BYPASS */ |