Unverified Commit 3faacfa7 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!12858 intel: backport GNR and SRF intel_idle fix for 5.10

Merge Pull Request from: @jiayingbao 
 
description:
Backport AMX intel_idle support patch and dependency
Backport GNR intel_idle support 
Backport GNR and SRF intel_idle fix patch

Test:
intel_idle function can be enabled and disabled on GNR/SRF platform
 
 
Link:https://gitee.com/openeuler/kernel/pulls/12858

 

Reviewed-by: default avatarJason Zeng <jason.zeng@intel.com>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
parents 323d2842 cec77925
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -144,4 +144,6 @@ static inline bool fpstate_is_confidential(struct fpu_guest *gfpu)
struct task_struct;
extern long fpu_xstate_prctl(struct task_struct *tsk, int option, unsigned long arg2);

extern void fpu_idle_fpregs(void);

#endif /* _ASM_X86_FPU_API_H */
+9 −0
Original line number Diff line number Diff line
@@ -294,6 +294,15 @@ static inline int enqcmds(void __iomem *dst, const void *src)
	return 0;
}

static inline void tile_release(void)
{
	/*
	 * Instruction opcode for TILERELEASE; supported in binutils
	 * version >= 2.36.
	 */
	asm volatile(".byte 0xc4, 0xe2, 0x78, 0x49, 0xc0");
}

#endif /* __KERNEL__ */

#endif /* _ASM_X86_SPECIAL_INSNS_H */
+14 −0
Original line number Diff line number Diff line
@@ -828,3 +828,17 @@ int fpu__exception_code(struct fpu *fpu, int trap_nr)
	 */
	return 0;
}

/*
 * Initialize register state that may prevent from entering low-power idle.
 * This function will be invoked from the cpuidle driver only when needed.
 */
void fpu_idle_fpregs(void)
{
	/* Note: AMX_TILE being enabled implies XGETBV1 support */
	if (cpu_feature_enabled(X86_FEATURE_AMX_TILE) &&
	    (xfeatures_in_use() & XFEATURE_MASK_XTILE)) {
		tile_release();
		fpregs_deactivate(&current->thread.fpu);
	}
}
+121 −16
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@
#include <asm/nospec-branch.h>
#include <asm/mwait.h>
#include <asm/msr.h>
#include <asm/fpu/api.h>

#define INTEL_IDLE_VERSION "0.5.1"

@@ -113,6 +114,17 @@ static unsigned int mwait_substates __initdata;
 */
#define CPUIDLE_FLAG_IBRS		BIT(16)

/*
 * Initialize large xstate for the C6-state entrance.
 */
#define CPUIDLE_FLAG_INIT_XSTATE	BIT(17)

/*
 * Ignore the sub-state when matching mwait hints between the ACPI _CST and
 * custom tables.
 */
#define CPUIDLE_FLAG_PARTIAL_HINT_MATCH	BIT(18)

/*
 * MWAIT takes an 8-bit "hint" in EAX "suggesting"
 * the C-state (top nibble) and sub-state (bottom nibble)
@@ -123,6 +135,18 @@ static unsigned int mwait_substates __initdata;
#define flg2MWAIT(flags) (((flags) >> 24) & 0xFF)
#define MWAIT2flg(eax) ((eax & 0xFF) << 24)

static __always_inline int __intel_idle(struct cpuidle_device *dev,
					struct cpuidle_driver *drv, int index)
{
	struct cpuidle_state *state = &drv->states[index];
	unsigned long eax = flg2MWAIT(state->flags);
	unsigned long ecx = 1; /* break on interrupt flag */

	mwait_idle_with_hints(eax, ecx);

	return index;
}

/**
 * intel_idle - Ask the processor to enter the given idle state.
 * @dev: cpuidle device of the target CPU.
@@ -140,18 +164,20 @@ static unsigned int mwait_substates __initdata;
static __cpuidle int intel_idle(struct cpuidle_device *dev,
				struct cpuidle_driver *drv, int index)
{
	struct cpuidle_state *state = &drv->states[index];
	unsigned long eax = flg2MWAIT(state->flags);
	unsigned long ecx = 1; /* break on interrupt flag */
	return __intel_idle(dev, drv, index);
}

	if (state->flags & CPUIDLE_FLAG_IRQ_ENABLE)
		local_irq_enable();
static __cpuidle int intel_idle_irq(struct cpuidle_device *dev,
					struct cpuidle_driver *drv, int index)
{
	int ret;
	raw_local_irq_enable();
	ret = __intel_idle(dev, drv, index);

	mwait_idle_with_hints(eax, ecx);
	raw_local_irq_disable();

	return index;
	return ret;
}

static __cpuidle int intel_idle_ibrs(struct cpuidle_device *dev,
				     struct cpuidle_driver *drv, int index)
{
@@ -170,6 +196,13 @@ static __cpuidle int intel_idle_ibrs(struct cpuidle_device *dev,
	return ret;
}

static __cpuidle int intel_idle_xstate(struct cpuidle_device *dev,
				       struct cpuidle_driver *drv, int index)
{
	fpu_idle_fpregs();
	return __intel_idle(dev, drv, index);
}

/**
 * intel_idle_s2idle - Ask the processor to enter the given idle state.
 * @dev: cpuidle device of the target CPU.
@@ -185,8 +218,12 @@ static __cpuidle int intel_idle_ibrs(struct cpuidle_device *dev,
static __cpuidle int intel_idle_s2idle(struct cpuidle_device *dev,
				       struct cpuidle_driver *drv, int index)
{
	unsigned long eax = flg2MWAIT(drv->states[index].flags);
	unsigned long ecx = 1; /* break on interrupt flag */
	struct cpuidle_state *state = &drv->states[index];
	unsigned long eax = flg2MWAIT(state->flags);

	if (state->flags & CPUIDLE_FLAG_INIT_XSTATE)
		fpu_idle_fpregs();

	mwait_idle_with_hints(eax, ecx);

@@ -810,7 +847,8 @@ static struct cpuidle_state spr_cstates[] __initdata = {
	{
		.name = "C6",
		.desc = "MWAIT 0x20",
		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED |
					   CPUIDLE_FLAG_INIT_XSTATE,
		.exit_latency = 290,
		.target_residency = 800,
		.enter = &intel_idle,
@@ -819,6 +857,47 @@ static struct cpuidle_state spr_cstates[] __initdata = {
		.enter = NULL }
};

static struct cpuidle_state gnr_cstates[] __initdata = {
	{
		.name = "C1",
		.desc = "MWAIT 0x00",
		.flags = MWAIT2flg(0x00),
		.exit_latency = 1,
		.target_residency = 1,
		.enter = &intel_idle,
		.enter_s2idle = intel_idle_s2idle, },
	{
		.name = "C1E",
		.desc = "MWAIT 0x01",
		.flags = MWAIT2flg(0x01) | CPUIDLE_FLAG_ALWAYS_ENABLE,
		.exit_latency = 4,
		.target_residency = 4,
		.enter = &intel_idle,
		.enter_s2idle = intel_idle_s2idle, },
	{
		.name = "C6",
		.desc = "MWAIT 0x20",
		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED |
					   CPUIDLE_FLAG_INIT_XSTATE |
					   CPUIDLE_FLAG_PARTIAL_HINT_MATCH,
		.exit_latency = 170,
		.target_residency = 650,
		.enter = &intel_idle,
		.enter_s2idle = intel_idle_s2idle, },
	{
		.name = "C6P",
		.desc = "MWAIT 0x21",
		.flags = MWAIT2flg(0x21) | CPUIDLE_FLAG_TLB_FLUSHED |
					   CPUIDLE_FLAG_INIT_XSTATE |
					   CPUIDLE_FLAG_PARTIAL_HINT_MATCH,
		.exit_latency = 210,
		.target_residency = 1000,
		.enter = &intel_idle,
		.enter_s2idle = intel_idle_s2idle, },
	{
		.enter = NULL }
};

static struct cpuidle_state atom_cstates[] __initdata = {
	{
		.name = "C1E",
@@ -1083,7 +1162,8 @@ static struct cpuidle_state srf_cstates[] __initdata = {
	{
		.name = "C6S",
		.desc = "MWAIT 0x22",
		.flags = MWAIT2flg(0x22) | CPUIDLE_FLAG_TLB_FLUSHED,
		.flags = MWAIT2flg(0x22) | CPUIDLE_FLAG_TLB_FLUSHED |
					   CPUIDLE_FLAG_PARTIAL_HINT_MATCH,
		.exit_latency = 270,
		.target_residency = 700,
		.enter = &intel_idle,
@@ -1091,7 +1171,8 @@ static struct cpuidle_state srf_cstates[] __initdata = {
	{
		.name = "C6SP",
		.desc = "MWAIT 0x23",
		.flags = MWAIT2flg(0x23) | CPUIDLE_FLAG_TLB_FLUSHED,
		.flags = MWAIT2flg(0x23) | CPUIDLE_FLAG_TLB_FLUSHED |
					   CPUIDLE_FLAG_PARTIAL_HINT_MATCH,
		.exit_latency = 310,
		.target_residency = 900,
		.enter = &intel_idle,
@@ -1205,6 +1286,12 @@ static const struct idle_cpu idle_cpu_spr __initconst = {
	.use_acpi = true,
};

static const struct idle_cpu idle_cpu_gnr __initconst = {
	.state_table = gnr_cstates,
	.disable_promotion_to_c1e = true,
	.use_acpi = true,
};

static const struct idle_cpu idle_cpu_avn __initconst = {
	.state_table = avn_cstates,
	.disable_promotion_to_c1e = true,
@@ -1275,6 +1362,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
	X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D,		&idle_cpu_icx),
	X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X,	&idle_cpu_spr),
	X86_MATCH_INTEL_FAM6_MODEL(EMERALDRAPIDS_X,	&idle_cpu_spr),
	X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_X,	&idle_cpu_gnr),
	X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL,	&idle_cpu_knl),
	X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM,	&idle_cpu_knl),
	X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT,	&idle_cpu_bxt),
@@ -1433,7 +1521,7 @@ static void __init intel_idle_init_cstates_acpi(struct cpuidle_driver *drv)
	}
}

static bool __init intel_idle_off_by_default(u32 mwait_hint)
static bool __init intel_idle_off_by_default(unsigned int flags, u32 mwait_hint)
{
	int cstate, limit;

@@ -1450,7 +1538,15 @@ static bool __init intel_idle_off_by_default(u32 mwait_hint)
	 * the interesting states are ACPI_CSTATE_FFH.
	 */
	for (cstate = 1; cstate < limit; cstate++) {
		if (acpi_state_table.states[cstate].address == mwait_hint)
		u32 acpi_hint = acpi_state_table.states[cstate].address;
		u32 table_hint = mwait_hint;

		if (flags & CPUIDLE_FLAG_PARTIAL_HINT_MATCH) {
			acpi_hint &= ~MWAIT_SUBSTATE_MASK;
			table_hint &= ~MWAIT_SUBSTATE_MASK;
		}

		if (acpi_hint == table_hint)
			return false;
	}
	return true;
@@ -1460,7 +1556,10 @@ static bool __init intel_idle_off_by_default(u32 mwait_hint)

static inline bool intel_idle_acpi_cst_extract(void) { return false; }
static inline void intel_idle_init_cstates_acpi(struct cpuidle_driver *drv) { }
static inline bool intel_idle_off_by_default(u32 mwait_hint) { return false; }
static inline bool intel_idle_off_by_default(unsigned int flags, u32 mwait_hint)
{
	return false;
}
#endif /* !CONFIG_ACPI_PROCESSOR_CSTATE */

/**
@@ -1718,14 +1817,20 @@ static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
		/* Structure copy. */
		drv->states[drv->state_count] = cpuidle_state_table[cstate];

		if (cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_IRQ_ENABLE)
			drv->states[drv->state_count].enter = intel_idle_irq;

		if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS) &&
		    cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_IBRS) {
			drv->states[drv->state_count].enter = intel_idle_ibrs;
		}

		if (cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_INIT_XSTATE)
			drv->states[drv->state_count].enter = intel_idle_xstate;

		if ((disabled_states_mask & BIT(drv->state_count)) ||
		    ((icpu->use_acpi || force_use_acpi) &&
		     intel_idle_off_by_default(mwait_hint) &&
		     intel_idle_off_by_default(drv->states[drv->state_count].flags, mwait_hint) &&
		     !(cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_ALWAYS_ENABLE)))
			drv->states[drv->state_count].flags |= CPUIDLE_FLAG_OFF;