Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d4ce2d7 authored by Pawan Gupta's avatar Pawan Gupta Committed by Greg Kroah-Hartman
Browse files

x86/speculation: Add spectre_v2=ibrs option to support Kernel IBRS



commit 7c693f54c873691a4b7da05c7e0f74e67745d144 upstream.

Extend spectre_v2= boot option with Kernel IBRS.

  [jpoimboe: no STIBP with IBRS]

Signed-off-by: default avatarPawan Gupta <pawan.kumar.gupta@linux.intel.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Reviewed-by: default avatarJosh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Signed-off-by: default avatarThadeu Lima de Souza Cascardo <cascardo@canonical.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e2d793a3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -4553,6 +4553,7 @@
			eibrs		  - enhanced IBRS
			eibrs,retpoline   - enhanced IBRS + Retpolines
			eibrs,lfence      - enhanced IBRS + LFENCE
			ibrs		  - use IBRS to protect kernel

			Not specifying this option is equivalent to
			spectre_v2=auto.
+1 −0
Original line number Diff line number Diff line
@@ -234,6 +234,7 @@ enum spectre_v2_mitigation {
	SPECTRE_V2_EIBRS,
	SPECTRE_V2_EIBRS_RETPOLINE,
	SPECTRE_V2_EIBRS_LFENCE,
	SPECTRE_V2_IBRS,
};

/* The indirect branch speculation control variants */
+52 −14
Original line number Diff line number Diff line
@@ -877,6 +877,7 @@ enum spectre_v2_mitigation_cmd {
	SPECTRE_V2_CMD_EIBRS,
	SPECTRE_V2_CMD_EIBRS_RETPOLINE,
	SPECTRE_V2_CMD_EIBRS_LFENCE,
	SPECTRE_V2_CMD_IBRS,
};

enum spectre_v2_user_cmd {
@@ -949,11 +950,12 @@ spectre_v2_parse_user_cmdline(enum spectre_v2_mitigation_cmd v2_cmd)
	return SPECTRE_V2_USER_CMD_AUTO;
}

static inline bool spectre_v2_in_eibrs_mode(enum spectre_v2_mitigation mode)
static inline bool spectre_v2_in_ibrs_mode(enum spectre_v2_mitigation mode)
{
	return (mode == SPECTRE_V2_EIBRS ||
	return mode == SPECTRE_V2_IBRS ||
	       mode == SPECTRE_V2_EIBRS ||
	       mode == SPECTRE_V2_EIBRS_RETPOLINE ||
		mode == SPECTRE_V2_EIBRS_LFENCE);
	       mode == SPECTRE_V2_EIBRS_LFENCE;
}

static void __init
@@ -1018,12 +1020,12 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
	}

	/*
	 * If no STIBP, enhanced IBRS is enabled or SMT impossible, STIBP is not
	 * required.
	 * If no STIBP, IBRS or enhanced IBRS is enabled, or SMT impossible,
	 * STIBP is not required.
	 */
	if (!boot_cpu_has(X86_FEATURE_STIBP) ||
	    !smt_possible ||
	    spectre_v2_in_eibrs_mode(spectre_v2_enabled))
	    spectre_v2_in_ibrs_mode(spectre_v2_enabled))
		return;

	/*
@@ -1048,6 +1050,7 @@ static const char * const spectre_v2_strings[] = {
	[SPECTRE_V2_EIBRS]			= "Mitigation: Enhanced IBRS",
	[SPECTRE_V2_EIBRS_LFENCE]		= "Mitigation: Enhanced IBRS + LFENCE",
	[SPECTRE_V2_EIBRS_RETPOLINE]		= "Mitigation: Enhanced IBRS + Retpolines",
	[SPECTRE_V2_IBRS]			= "Mitigation: IBRS",
};

static const struct {
@@ -1065,6 +1068,7 @@ static const struct {
	{ "eibrs,lfence",	SPECTRE_V2_CMD_EIBRS_LFENCE,	  false },
	{ "eibrs,retpoline",	SPECTRE_V2_CMD_EIBRS_RETPOLINE,	  false },
	{ "auto",		SPECTRE_V2_CMD_AUTO,		  false },
	{ "ibrs",		SPECTRE_V2_CMD_IBRS,              false },
};

static void __init spec_v2_print_cond(const char *reason, bool secure)
@@ -1127,6 +1131,24 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
		return SPECTRE_V2_CMD_AUTO;
	}

	if (cmd == SPECTRE_V2_CMD_IBRS && boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) {
		pr_err("%s selected but not Intel CPU. Switching to AUTO select\n",
		       mitigation_options[i].option);
		return SPECTRE_V2_CMD_AUTO;
	}

	if (cmd == SPECTRE_V2_CMD_IBRS && !boot_cpu_has(X86_FEATURE_IBRS)) {
		pr_err("%s selected but CPU doesn't have IBRS. Switching to AUTO select\n",
		       mitigation_options[i].option);
		return SPECTRE_V2_CMD_AUTO;
	}

	if (cmd == SPECTRE_V2_CMD_IBRS && boot_cpu_has(X86_FEATURE_XENPV)) {
		pr_err("%s selected but running as XenPV guest. Switching to AUTO select\n",
		       mitigation_options[i].option);
		return SPECTRE_V2_CMD_AUTO;
	}

	spec_v2_print_cond(mitigation_options[i].option,
			   mitigation_options[i].secure);
	return cmd;
@@ -1166,6 +1188,14 @@ static void __init spectre_v2_select_mitigation(void)
			break;
		}

		if (boot_cpu_has_bug(X86_BUG_RETBLEED) &&
		    retbleed_cmd != RETBLEED_CMD_OFF &&
		    boot_cpu_has(X86_FEATURE_IBRS) &&
		    boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
			mode = SPECTRE_V2_IBRS;
			break;
		}

		mode = spectre_v2_select_retpoline();
		break;

@@ -1182,6 +1212,10 @@ static void __init spectre_v2_select_mitigation(void)
		mode = spectre_v2_select_retpoline();
		break;

	case SPECTRE_V2_CMD_IBRS:
		mode = SPECTRE_V2_IBRS;
		break;

	case SPECTRE_V2_CMD_EIBRS:
		mode = SPECTRE_V2_EIBRS;
		break;
@@ -1198,7 +1232,7 @@ static void __init spectre_v2_select_mitigation(void)
	if (mode == SPECTRE_V2_EIBRS && unprivileged_ebpf_enabled())
		pr_err(SPECTRE_V2_EIBRS_EBPF_MSG);

	if (spectre_v2_in_eibrs_mode(mode)) {
	if (spectre_v2_in_ibrs_mode(mode)) {
		/* Force it so VMEXIT will restore correctly */
		x86_spec_ctrl_base |= SPEC_CTRL_IBRS;
		write_spec_ctrl_current(x86_spec_ctrl_base, true);
@@ -1209,6 +1243,10 @@ static void __init spectre_v2_select_mitigation(void)
	case SPECTRE_V2_EIBRS:
		break;

	case SPECTRE_V2_IBRS:
		setup_force_cpu_cap(X86_FEATURE_KERNEL_IBRS);
		break;

	case SPECTRE_V2_LFENCE:
	case SPECTRE_V2_EIBRS_LFENCE:
		setup_force_cpu_cap(X86_FEATURE_RETPOLINE_LFENCE);
@@ -1235,17 +1273,17 @@ static void __init spectre_v2_select_mitigation(void)
	pr_info("Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch\n");

	/*
	 * Retpoline means the kernel is safe because it has no indirect
	 * branches. Enhanced IBRS protects firmware too, so, enable restricted
	 * speculation around firmware calls only when Enhanced IBRS isn't
	 * supported.
	 * Retpoline protects the kernel, but doesn't protect firmware.  IBRS
	 * and Enhanced IBRS protect firmware too, so enable IBRS around
	 * firmware calls only when IBRS / Enhanced IBRS aren't otherwise
	 * enabled.
	 *
	 * Use "mode" to check Enhanced IBRS instead of boot_cpu_has(), because
	 * the user might select retpoline on the kernel command line and if
	 * the CPU supports Enhanced IBRS, kernel might un-intentionally not
	 * enable IBRS around firmware calls.
	 */
	if (boot_cpu_has(X86_FEATURE_IBRS) && !spectre_v2_in_eibrs_mode(mode)) {
	if (boot_cpu_has(X86_FEATURE_IBRS) && !spectre_v2_in_ibrs_mode(mode)) {
		setup_force_cpu_cap(X86_FEATURE_USE_IBRS_FW);
		pr_info("Enabling Restricted Speculation for firmware calls\n");
	}
@@ -1951,7 +1989,7 @@ static ssize_t mmio_stale_data_show_state(char *buf)

static char *stibp_state(void)
{
	if (spectre_v2_in_eibrs_mode(spectre_v2_enabled))
	if (spectre_v2_in_ibrs_mode(spectre_v2_enabled))
		return "";

	switch (spectre_v2_user_stibp) {