Skip to contentSkip to conversation

mtrr/x86/drivers: bury MTRR

PATCH In review Luis R. Rodriguez 34 participants 485 messages Mar 20, 2015 – Aug 1, 2015 Page 3 of 4

Subsystems (34)
lore
Share & tools
lore
maintainer
#226 lore raw

Re: [PATCH v4 7/7] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

In reply to Toshi Kani
Quoted 25 lines · Toshi Kani

This patch adds an additional argument, 'uniform', to mtrr_type_lookup(), which returns 1 when a given range is covered uniformly by MTRRs, i.e. the range is fully covered by a single MTRR entry or the default type.

pud_set_huge() and pmd_set_huge() are changed to check the new 'uniform' flag to see if it is safe to create a huge page mapping to the range. This allows them to create a huge page mapping to a range covered by a single MTRR entry of any memory type. It also detects a non-optimal request properly. They continue to check with the WB type since the WB type has no effect even if a request spans multiple MTRR entries.

pmd_set_huge() logs a warning message to a non-optimal request so that driver writers will be aware of such a case. Drivers should make a mapping request aligned to a single MTRR entry when the range is covered by MTRRs.

---
 arch/x86/include/asm/mtrr.h        |    5 +++--
 arch/x86/kernel/cpu/mtrr/generic.c |   35 +++++++++++++++++++++++++++--------
 arch/x86/mm/pat.c                  |    4 ++--
 arch/x86/mm/pgtable.c              |   25 +++++++++++++++----------
 4 files changed, 47 insertions(+), 22 deletions(-)

...

arch/x86/kernel/cpu/mtrr/generic.c static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end, · line 246

Quoted 8 lines
arch/x86/kernel/cpu/mtrr/generic.c +4 -0
@@ -235,13 +240,19 @@ static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
  * Return Values:
  * MTRR_TYPE_(type)  - The effective MTRR type for the region
  * MTRR_TYPE_INVALID - MTRR is disabled
+ *
+ * Output Argument:
+ * uniform - Set to 1 when MTRR covers the region uniformly, i.e. the region
+ *	     is fully covered by a single MTRR entry or the default type.

I'd call this "single_mtrr". "uniform" could also mean that the resulting type is uniform, i.e. of the same type but spanning multiple MTRRs.

arch/x86/kernel/cpu/mtrr/generic.c static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end, · line 255

Quoted 11 lines
arch/x86/kernel/cpu/mtrr/generic.c +4 -2
  */
-u8 mtrr_type_lookup(u64 start, u64 end)
+u8 mtrr_type_lookup(u64 start, u64 end, u8 *uniform)
 {
-	u8 type, prev_type;
+	u8 type, prev_type, is_uniform, dummy;
 	int repeat;
 	u64 partial_end;
 
+	*uniform = 1;
+

You're setting it here...

arch/x86/kernel/cpu/mtrr/generic.c static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end, · line 257

Quoted 2 lines
arch/x86/kernel/cpu/mtrr/generic.c +0 -0
 	if (!mtrr_state_set)
 		return MTRR_TYPE_INVALID;

... but if you return here, you would've changed the thing uniform points to needlessly as you're returning an error.

Quoted 21 lines
arch/x86/kernel/cpu/mtrr/generic.c +5 -2
@@ -253,14 +264,17 @@ u8 mtrr_type_lookup(u64 start, u64 end)
 	 * the variable ranges.
 	 */
 	type = mtrr_type_lookup_fixed(start, end);
-	if (type != MTRR_TYPE_INVALID)
+	if (type != MTRR_TYPE_INVALID) {
+		*uniform = 0;
 		return type;
+	}
 
 	/*
 	 * Look up the variable ranges.  Look of multiple ranges matching
 	 * this address and pick type as per MTRR precedence.
 	 */
-	type = mtrr_type_lookup_variable(start, end, &partial_end, &repeat);
+	type = mtrr_type_lookup_variable(start, end, &partial_end,
+					 &repeat, &is_uniform);
 
 	/*
 	 * Common path is with repeat = 0.

arch/x86/kernel/cpu/mtrr/generic.c u8 mtrr_type_lookup(u64 start, u64 end) · line 288

Quoted 4 lines
arch/x86/kernel/cpu/mtrr/generic.c +1 -0
@@ -271,16 +285,21 @@ u8 mtrr_type_lookup(u64 start, u64 end)
 	while (repeat) {
 		prev_type = type;
 		start = partial_end;
+		is_uniform = 0;

So I think it would be better if you added an out: label where you do exit from the function and set return values there.

So something like that, I'm pasting the whole function here so that you can follow better:

u8 mtrr_type_lookup(u64 start, u64 end, u8 *uniform)

{
        u8 type, prev_type, is_uniform = 1, dummy;
        int repeat;
        u64 partial_end;

        if (!mtrr_state_set)
                return MTRR_TYPE_INVALID;

        if (!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED))
                return MTRR_TYPE_INVALID;

        /*
         * Look up the fixed ranges first, which take priority over
         * the variable ranges.
         */
        type = mtrr_type_lookup_fixed(start, end);
        if (type != MTRR_TYPE_INVALID) {
                is_uniform = 0;
                goto out;
        }

        /*
         * Look up the variable ranges.  Look of multiple ranges matching
         * this address and pick type as per MTRR precedence.
         */
        type = mtrr_type_lookup_variable(start, end, &partial_end,
                                         &repeat, &is_uniform);

        /*
         * Common path is with repeat = 0.
         * However, we can have cases where [start:end] spans across some
         * MTRR ranges and/or the default type.  Do repeated lookups for
         * that case here.
         */
        while (repeat) {
                prev_type = type;
                start = partial_end;
                is_uniform = 0;

                type = mtrr_type_lookup_variable(start, end, &partial_end,
                                                 &repeat, &dummy);

                if (check_type_overlap(&prev_type, &type))
                        goto out;

        }

        if (mtrr_tom2 && (start >= (1ULL<<32)) && (end < mtrr_tom2))
                type = MTRR_TYPE_WRBACK;

out:

        *uniform = is_uniform;
        return type;
}

---

This way you're setting the uniform pointer in a single location and you're working with the local variable inside the function.

Much easier to follow.

Quoted 77 lines
arch/x86/kernel/cpu/mtrr/generic.c +6 -2
+
 		type = mtrr_type_lookup_variable(start, end, &partial_end,
-						 &repeat);
+						 &repeat, &dummy);
 
-		if (check_type_overlap(&prev_type, &type))
+		if (check_type_overlap(&prev_type, &type)) {
+			*uniform = 0;
 			return type;
+		}
 	}
 
 	if (mtrr_tom2 && (start >= (1ULL<<32)) && (end < mtrr_tom2))
 		return MTRR_TYPE_WRBACK;
 
+	*uniform = is_uniform;
 	return type;
 }
 
arch/x86/mm/pat.c +2 -2
index 35af677..372ad42 100644
@@ -267,9 +267,9 @@ static unsigned long pat_x_mtrr_type(u64 start, u64 end,
 	 * request is for WB.
 	 */
 	if (req_type == _PAGE_CACHE_MODE_WB) {
-		u8 mtrr_type;
+		u8 mtrr_type, uniform;
 
-		mtrr_type = mtrr_type_lookup(start, end);
+		mtrr_type = mtrr_type_lookup(start, end, &uniform);
 		if (mtrr_type != MTRR_TYPE_WRBACK)
 			return _PAGE_CACHE_MODE_UC_MINUS;
 
arch/x86/mm/pgtable.c +9 -7
index cfca4cf..3d6edea 100644
@@ -567,17 +567,18 @@ void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys,
  * pud_set_huge - setup kernel PUD mapping
  *
  * MTRR can override PAT memory types with 4KB granularity.  Therefore,
- * it does not set up a huge page when the range is covered by a non-WB
- * type of MTRR.  MTRR_TYPE_INVALID indicates that MTRR are disabled.
+ * it only sets up a huge page when the range is mapped uniformly by MTRR
+ * (i.e. the range is fully covered by a single MTRR entry or the default
+ * type) or the MTRR memory type is WB.
  *
  * Return 1 on success, and 0 when no PUD was set.
  */
 int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot)
 {
-	u8 mtrr;
+	u8 mtrr, uniform;
 
-	mtrr = mtrr_type_lookup(addr, addr + PUD_SIZE);
-	if ((mtrr != MTRR_TYPE_WRBACK) && (mtrr != MTRR_TYPE_INVALID))
+	mtrr = mtrr_type_lookup(addr, addr + PUD_SIZE, &uniform);
+	if ((!uniform) && (mtrr != MTRR_TYPE_WRBACK))
 		return 0;
 
 	prot = pgprot_4k_2_large(prot);
@@ -593,18 +594,22 @@ int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot)
  * pmd_set_huge - setup kernel PMD mapping
  *
  * MTRR can override PAT memory types with 4KB granularity.  Therefore,
- * it does not set up a huge page when the range is covered by a non-WB
- * type of MTRR.  MTRR_TYPE_INVALID indicates that MTRR are disabled.
+ * it only sets up a huge page when the range is mapped uniformly by MTRR
+ * (i.e. the range is fully covered by a single MTRR entry or the default
+ * type) or the MTRR memory type is WB.
  *
  * Return 1 on success, and 0 when no PMD was set.
  */
 int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot)
 {

arch/x86/mm/pgtable.c int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot) · line 611

Quoted 10 lines
arch/x86/mm/pgtable.c +5 -3
-	u8 mtrr;
+	u8 mtrr, uniform;
 
-	mtrr = mtrr_type_lookup(addr, addr + PMD_SIZE);
-	if ((mtrr != MTRR_TYPE_WRBACK) && (mtrr != MTRR_TYPE_INVALID))
+	mtrr = mtrr_type_lookup(addr, addr + PMD_SIZE, &uniform);
+	if ((!uniform) && (mtrr != MTRR_TYPE_WRBACK)) {
+		pr_warn("pmd_set_huge: requesting [mem %#010llx-%#010llx], which spans more than a single MTRR entry\n",
+				addr, addr + PMD_SIZE);
 		return 0;

So this returns 0, i.e. failure already. Why do we even have to warn? Caller already knows it failed.

And this warning would flood dmesg needlessly.

Signature · 11 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#227 lore raw

Re: [PATCH v4 7/7] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 1 line · Borislav Petkov

On Tue, Mar 24, 2015 at 04:08:41PM -0600, Toshi Kani wrote:

:

Quoted 11 lines

arch/x86/kernel/cpu/mtrr/generic.c static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end, · line 246

Quoted 8 lines
arch/x86/kernel/cpu/mtrr/generic.c +4 -0
@@ -235,13 +240,19 @@ static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
  * Return Values:
  * MTRR_TYPE_(type)  - The effective MTRR type for the region
  * MTRR_TYPE_INVALID - MTRR is disabled
+ *
+ * Output Argument:
+ * uniform - Set to 1 when MTRR covers the region uniformly, i.e. the region
+ *	     is fully covered by a single MTRR entry or the default type.

I'd call this "single_mtrr". "uniform" could also mean that the resulting type is uniform, i.e. of the same type but spanning multiple MTRRs.

Actually, that is the intend of "uniform" and the same type but spanning multiple MTRRs should set "uniform" to 1. The patch does not check such case for simplicity since we do not need to maximize the performance with MTRRs for every corner case since they are legacy and their use is expected to be phased out. It makes sure that a type conflict with MTRRs is detected so that huge page mappings are made safely.

Also, in most of the cases, "uniform" is set to 1 because there is no MTRR entry that covers the range, i.e. the default type.

Quoted 14 lines

arch/x86/kernel/cpu/mtrr/generic.c static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end, · line 255

Quoted 11 lines
arch/x86/kernel/cpu/mtrr/generic.c +4 -2
  */
-u8 mtrr_type_lookup(u64 start, u64 end)
+u8 mtrr_type_lookup(u64 start, u64 end, u8 *uniform)
 {
-	u8 type, prev_type;
+	u8 type, prev_type, is_uniform, dummy;
 	int repeat;
 	u64 partial_end;
 
+	*uniform = 1;
+

You're setting it here...

Quoted 5 lines

arch/x86/kernel/cpu/mtrr/generic.c static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end, · line 257

Quoted 2 lines
arch/x86/kernel/cpu/mtrr/generic.c +0 -0
 	if (!mtrr_state_set)
 		return MTRR_TYPE_INVALID;

... but if you return here, you would've changed the thing uniform points to needlessly as you're returning an error.

We need to set "uniform" to 1 when MTRRs are disabled since there is no type conflict with MTRRs.

Quoted 29 lines
Quoted 21 lines
arch/x86/kernel/cpu/mtrr/generic.c +5 -2
@@ -253,14 +264,17 @@ u8 mtrr_type_lookup(u64 start, u64 end)
 	 * the variable ranges.
 	 */
 	type = mtrr_type_lookup_fixed(start, end);
-	if (type != MTRR_TYPE_INVALID)
+	if (type != MTRR_TYPE_INVALID) {
+		*uniform = 0;
 		return type;
+	}
 
 	/*
 	 * Look up the variable ranges.  Look of multiple ranges matching
 	 * this address and pick type as per MTRR precedence.
 	 */
-	type = mtrr_type_lookup_variable(start, end, &partial_end, &repeat);
+	type = mtrr_type_lookup_variable(start, end, &partial_end,
+					 &repeat, &is_uniform);
 
 	/*
 	 * Common path is with repeat = 0.

arch/x86/kernel/cpu/mtrr/generic.c u8 mtrr_type_lookup(u64 start, u64 end) · line 288

Quoted 4 lines
arch/x86/kernel/cpu/mtrr/generic.c +1 -0
@@ -271,16 +285,21 @@ u8 mtrr_type_lookup(u64 start, u64 end)
 	while (repeat) {
 		prev_type = type;
 		start = partial_end;
+		is_uniform = 0;

So I think it would be better if you added an out: label where you do exit from the function and set return values there.

Quoted 2 lines

So something like that, I'm pasting the whole function here so that you can follow better:

:

Quoted 5 lines

This way you're setting the uniform pointer in a single location and you're working with the local variable inside the function.

Much easier to follow.

With the label, the above check will be:

        if (!mtrr_state_set) {
		is_uniform = 1;
                type = MTRR_TYPE_INVALID;
		goto out;
	}

I can follow your suggestion of using the label if you still prefer using it.

Quoted 17 lines

arch/x86/mm/pgtable.c int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot) · line 611

Quoted 13 lines
arch/x86/mm/pgtable.c +5 -3
  */
 int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot)
 {
-	u8 mtrr;
+	u8 mtrr, uniform;
 
-	mtrr = mtrr_type_lookup(addr, addr + PMD_SIZE);
-	if ((mtrr != MTRR_TYPE_WRBACK) && (mtrr != MTRR_TYPE_INVALID))
+	mtrr = mtrr_type_lookup(addr, addr + PMD_SIZE, &uniform);
+	if ((!uniform) && (mtrr != MTRR_TYPE_WRBACK)) {
+		pr_warn("pmd_set_huge: requesting [mem %#010llx-%#010llx], which spans more than a single MTRR entry\n",
+				addr, addr + PMD_SIZE);
 		return 0;

So this returns 0, i.e. failure already. Why do we even have to warn? Caller already knows it failed.

Quoted 1 line

And this warning would flood dmesg needlessly.

The warning was suggested by reviewers in the previous review so that driver writers will notice the issue. Returning 0 here will lead ioremap() to use 4KB mappings, but does not cause ioremap() to fail.

Thanks,
-Toshi

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#228 lore raw

Re: [PATCH v4 7/7] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 12 lines · Toshi Kani
Quoted 11 lines

arch/x86/kernel/cpu/mtrr/generic.c static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end, · line 246

Quoted 8 lines
arch/x86/kernel/cpu/mtrr/generic.c +4 -0
@@ -235,13 +240,19 @@ static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
  * Return Values:
  * MTRR_TYPE_(type)  - The effective MTRR type for the region
  * MTRR_TYPE_INVALID - MTRR is disabled
+ *
+ * Output Argument:
+ * uniform - Set to 1 when MTRR covers the region uniformly, i.e. the region
+ *	     is fully covered by a single MTRR entry or the default type.

I'd call this "single_mtrr". "uniform" could also mean that the resulting type is uniform, i.e. of the same type but spanning multiple MTRRs.

Quoted 2 lines

Actually, that is the intend of "uniform" and the same type but spanning multiple MTRRs should set "uniform" to 1. The patch does not check such

So why does it say "is fully covered by a single MTRR entry or the default type." - the stress being on *single*

You need to make up your mind.

Quoted 2 lines

We need to set "uniform" to 1 when MTRRs are disabled since there is no type conflict with MTRRs.

No, this is wrong.

When we return an *error*, "uniform" should be *undefined* because MTRRs are disabled and callers should be checking whether it returned an error first and only *then* look at uniform.

Quoted 2 lines

The warning was suggested by reviewers in the previous review so that driver writers will notice the issue.

No, we don't flood dmesg so that driver writers notice stuff. We better fix the callers.

Quoted 2 lines

Returning 0 here will lead
ioremap() to use 4KB mappings, but does not cause ioremap() to fail.

I guess a pr_warn_once() should be better then. Flooding dmesg with error messages for which the user can't really do anything about doesn't bring us anything.

Signature · 11 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#229 lore raw

Re: [PATCH v4 7/7] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 13 lines · Borislav Petkov
Quoted 12 lines · Toshi Kani
Quoted 11 lines

arch/x86/kernel/cpu/mtrr/generic.c static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end, · line 246

Quoted 8 lines
arch/x86/kernel/cpu/mtrr/generic.c +4 -0
@@ -235,13 +240,19 @@ static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
  * Return Values:
  * MTRR_TYPE_(type)  - The effective MTRR type for the region
  * MTRR_TYPE_INVALID - MTRR is disabled
+ *
+ * Output Argument:
+ * uniform - Set to 1 when MTRR covers the region uniformly, i.e. the region
+ *	     is fully covered by a single MTRR entry or the default type.

I'd call this "single_mtrr". "uniform" could also mean that the resulting type is uniform, i.e. of the same type but spanning multiple MTRRs.

Quoted 7 lines
Quoted 2 lines

Actually, that is the intend of "uniform" and the same type but spanning multiple MTRRs should set "uniform" to 1. The patch does not check such

So why does it say "is fully covered by a single MTRR entry or the default type." - the stress being on *single*

You need to make up your mind.

I will clarify the comment as follows.
===
uniform - Set to 1 when the region is not covered with multiple memory types by MTRRs. It is set for any return value.

NOTE: The current code sets 'uniform' to 1 when the region is fully covered by a single MTRR entry or fully uncovered. However, it does not detect a uniform case that the region is covered by the same type but spanning multiple MTRR entries for simplicity.
===

Quoted 8 lines
Quoted 2 lines

We need to set "uniform" to 1 when MTRRs are disabled since there is no type conflict with MTRRs.

No, this is wrong.

When we return an *error*, "uniform" should be *undefined* because MTRRs are disabled and callers should be checking whether it returned an error first and only *then* look at uniform.

MTRRs disabled is not an error case as it could be a normal configuration on some platforms / BIOS setups. I clarified it in the above comment that uniform is set for any return value.

Quoted 6 lines
Quoted 2 lines

The warning was suggested by reviewers in the previous review so that driver writers will notice the issue.

No, we don't flood dmesg so that driver writers notice stuff. We better fix the callers.

Quoted 6 lines
Quoted 2 lines

Returning 0 here will lead
ioremap() to use 4KB mappings, but does not cause ioremap() to fail.

I guess a pr_warn_once() should be better then. Flooding dmesg with error messages for which the user can't really do anything about doesn't bring us anything.

OK, I will change it to pr_warn_once().

Thanks,
-Toshi

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#230 lore raw

Re: [PATCH v4 7/7] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 2 lines · Toshi Kani

MTRRs disabled is not an error case as it could be a normal configuration on some platforms / BIOS setups.

Normal how? PAT-only systems? Examples please...

Quoted 2 lines

I clarified it in the above comment that uniform is set for any return value.

Hell no!

u8 mtrr_type_lookup(u64 start, u64 end, u8 *uniform) {

	...

        *uniform = 1;

        if (!mtrr_state_set)
                return MTRR_TYPE_INVALID;

        if (!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED))
                return MTRR_TYPE_INVALID;

This is wrong and the fact that I still need to persuade you about it says a lot.

If you want to be able to state that a type is uniform even if MTRRs are disabled, you need to define another retval which means exactly that.

Or add an inline function called mtrr_enabled() and call it in the mtrr_type_lookup() callers.

Or whatever.

I don't want any confusing states with two return types and people having to figure out what it exactly means and digging into the code and scratching heads WTF is that supposed to mean.

Signature · 11 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#231 lore raw

Re: [PATCH v4 7/7] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 5 lines · Borislav Petkov
Quoted 2 lines · Toshi Kani

MTRRs disabled is not an error case as it could be a normal configuration on some platforms / BIOS setups.

Normal how? PAT-only systems? Examples please...

BIOS initializes and enables MTRRs at POST. While the most (if not all) BIOSes do it today, I do not think the x86 arch requires BIOS to enable them.

Here is a quote from Intel SDM:
===
11.11.5 MTRR Initialization

On a hardware reset, the P6 and more recent processors clear the valid flags in variable-range MTRRs and clear the E flag in the IA32_MTRR_DEF_TYPE MSR to disable all MTRRs. All other bits in the MTRRs are undefined.

Prior to initializing the MTRRs, software (normally the system BIOS) must initialize all fixed-range and variablerange MTRR register fields to 0. Software can then initialize the MTRRs according to known types of memory, including memory on devices that it auto-configures. Initialization is expected to occur prior to booting the operating system.
===

Quoted 19 lines
Quoted 2 lines

I clarified it in the above comment that uniform is set for any return value.

Hell no!

u8 mtrr_type_lookup(u64 start, u64 end, u8 *uniform) {

	...

        *uniform = 1;

        if (!mtrr_state_set)
                return MTRR_TYPE_INVALID;

        if (!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED))
                return MTRR_TYPE_INVALID;
Quoted 5 lines

This is wrong and the fact that I still need to persuade you about it says a lot.

If you want to be able to state that a type is uniform even if MTRRs are disabled, you need to define another retval which means exactly that.

There may not be any type conflict with MTRR_TYPE_INVALID.

Quoted 8 lines

Or add an inline function called mtrr_enabled() and call it in the mtrr_type_lookup() callers.

Or whatever.

I don't want any confusing states with two return types and people having to figure out what it exactly means and digging into the code and scratching heads WTF is that supposed to mean.

I will change the caller to check MTRR_TYPE_INVALID, and treat it as a uniform case.

Thanks,
-Toshi

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#232 lore raw

Re: [PATCH v4 7/7] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 1 line · Toshi Kani

There may not be any type conflict with MTRR_TYPE_INVALID.

Because...?

Let me guess: you cannot change this function to return a signed value which is the type when positive and an error when negative?

Quoted 2 lines

I will change the caller to check MTRR_TYPE_INVALID, and treat it as a uniform case.

That would be, of course, also wrong.

Signature · 11 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#233 lore raw

Re: [PATCH v4 7/7] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 4 lines · Borislav Petkov
Quoted 1 line · Toshi Kani

There may not be any type conflict with MTRR_TYPE_INVALID.

Because...?

Because you cannot have a memory type conflict with MTRRs when MTRRs are disabled. mtrr_type_lookup() returns MTRR_TYPE_INVALID when MTRRs are disabled. This is stated in the comments of mtrr_type_lookup() and the MTRR_TYPE_INVALID definition itself.

BIOS can disable MTRRs, or VM may choose not to implement MTRRs. The OS needs to handle this case as a valid config, and this is not an error case.

Quoted 2 lines

Let me guess: you cannot change this function to return a signed value which is the type when positive and an error when negative?

No, that is not the reason.

Quoted 4 lines
Quoted 2 lines

I will change the caller to check MTRR_TYPE_INVALID, and treat it as a uniform case.

That would be, of course, also wrong.

I am confused... In your previous comments, you mentioned that:

| If you want to be able to state that a type is uniform even if MTRRs
| are disabled, you need to define another retval which means exactly
| that.

There may not be type conflict when MTRRs are disabled. There is no point of defining a new return value.

| Or add an inline function called mtrr_enabled() and call it in the | mtrr_type_lookup() callers.

MTRR_TYPE_INVALID means MTRRs disabled. So, the caller checking with this value is the same as checking with mtrr_enabled() you suggested.

Thanks,
-Toshi

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#234 lore raw

Re: [PATCH v4 7/7] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 2 lines · Toshi Kani

MTRR_TYPE_INVALID means MTRRs disabled. So, the caller checking with this value is the same as checking with mtrr_enabled() you suggested.

So then you don't have to set *uniform = 1 on entry to mtrr_type_lookup(). And change the retval test

	if ((!uniform) && (mtrr != MTRR_TYPE_WRBACK))

to

	if ((mtrr != MTRR_TYPE_INVALID) && (!uniform) && (mtrr != MTRR_TYPE_WRBACK))

You can put the MTRR_TYPE_INVALID first so that it shortcuts.

You need the distinction between MTRRs *disabled* and an MTRR region being {non-,}uniform.

If MTRRs are disabled, uniform doesn't *mean* *anything* because it is undefined. When MTRRs are disabled, the range is *not* covered by MTRRs because, well, them MTRRs are disabled.

And it might be fine for *your* use case to set *uniform even when MTRRs are disabled but it might matter in the future. So we better design it correct from the beginning.

Signature · 11 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#235 lore raw

Re: [PATCH v4 7/7] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 11 lines · Borislav Petkov
Quoted 2 lines · Toshi Kani

MTRR_TYPE_INVALID means MTRRs disabled. So, the caller checking with this value is the same as checking with mtrr_enabled() you suggested.

So then you don't have to set *uniform = 1 on entry to mtrr_type_lookup(). And change the retval test

	if ((!uniform) && (mtrr != MTRR_TYPE_WRBACK))

to

	if ((mtrr != MTRR_TYPE_INVALID) && (!uniform) && (mtrr != MTRR_TYPE_WRBACK))

Yes, that's what I was thinking as well. Will do.

Quoted 5 lines

You can put the MTRR_TYPE_INVALID first so that it shortcuts.

You need the distinction between MTRRs *disabled* and an MTRR region being {non-,}uniform.

Quoted 7 lines

If MTRRs are disabled, uniform doesn't *mean* *anything* because it is undefined. When MTRRs are disabled, the range is *not* covered by MTRRs because, well, them MTRRs are disabled.

And it might be fine for *your* use case to set *uniform even when MTRRs are disabled but it might matter in the future. So we better design it correct from the beginning.

I think it is a matter of how "uniform" is defined, but your point is taken and I will change it accordingly.

Thanks,
-Toshi

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#236 lore raw

Re: [PATCH v4 0/7] mtrr, mm, x86: Enhance MTRR checks for huge I/O mapping

In reply to Toshi Kani
Quoted 4 lines · On Tue, 24 Mar 2015 16:08:34 -0600 Toshi Kani <[email protected]> wrote:

This patchset enhances MTRR checks for the kernel huge I/O mapping, which was enabled by the patchset below:
https://lkml.org/lkml/2015/3/3/589

Quoted 8 lines

The following functional changes are made in patch 7/7.
- Allow pud_set_huge() and pmd_set_huge() to create a huge page mapping to a range covered by a single MTRR entry of any memory type.
- Log a pr_warn() message when a specified PMD map range spans more than a single MTRR entry. Drivers should make a mapping request aligned to a single MTRR entry when the range is covered by MTRRs.

OK, I grabbed these after barely looking at them, to get them a bit of runtime testing.

I'll await guidance from the x86 maintainers regarding next steps?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#237 lore raw

Re: [PATCH v4 0/7] mtrr, mm, x86: Enhance MTRR checks for huge I/O mapping

Quoted 15 lines · Andrew Morton
Quoted 4 lines · On Tue, 24 Mar 2015 16:08:34 -0600 Toshi Kani <[email protected]> wrote:

This patchset enhances MTRR checks for the kernel huge I/O mapping, which was enabled by the patchset below:
https://lkml.org/lkml/2015/3/3/589

Quoted 8 lines

The following functional changes are made in patch 7/7.
- Allow pud_set_huge() and pmd_set_huge() to create a huge page mapping to a range covered by a single MTRR entry of any memory type.
- Log a pr_warn() message when a specified PMD map range spans more than a single MTRR entry. Drivers should make a mapping request aligned to a single MTRR entry when the range is covered by MTRRs.

Quoted 4 lines

OK, I grabbed these after barely looking at them, to get them a bit of runtime testing.

I'll await guidance from the x86 maintainers regarding next steps?

Could you please send the current version of them over to us if your testing didn't find any problems?

I'd like to take a final look and have them cook in the x86 tree as well for a while and want to preserve your testing effort.

Thanks!

Ingo

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#238 lore raw

Re: [PATCH v4 0/7] mtrr, mm, x86: Enhance MTRR checks for huge I/O mapping

Quoted 20 lines · Ingo Molnar
Quoted 18 lines · Andrew Morton
Quoted 4 lines · On Tue, 24 Mar 2015 16:08:34 -0600 Toshi Kani <[email protected]> wrote:

This patchset enhances MTRR checks for the kernel huge I/O mapping, which was enabled by the patchset below:
https://lkml.org/lkml/2015/3/3/589

Quoted 8 lines

The following functional changes are made in patch 7/7.
- Allow pud_set_huge() and pmd_set_huge() to create a huge page mapping to a range covered by a single MTRR entry of any memory type.
- Log a pr_warn() message when a specified PMD map range spans more than a single MTRR entry. Drivers should make a mapping request aligned to a single MTRR entry when the range is covered by MTRRs.

OK, I grabbed these after barely looking at them, to get them a bit of runtime testing.

Quoted 7 lines
Quoted 1 line

I'll await guidance from the x86 maintainers regarding next steps?

Could you please send the current version of them over to us if your testing didn't find any problems?

I'd like to take a final look and have them cook in the x86 tree as well for a while and want to preserve your testing effort.

This patchset is on top of the following patches in the -mm tree. (Patches apply from the bottom to the top.)

2. Build error fixes and cleanups
http://ozlabs.org/~akpm/mmotm/broken-out/x86-mm-support-huge-kva-mappings-on-x86-fix.patch
http://ozlabs.org/~akpm/mmotm/broken-out/mm-change-vunmap-to-tear-down-huge-kva-mappings-fix.patch
http://ozlabs.org/~akpm/mmotm/broken-out/mm-change-ioremap-to-set-up-huge-i-o-mappings-fix.patch
http://ozlabs.org/~akpm/mmotm/broken-out/lib-add-huge-i-o-map-capability-interfaces-fix.patch

1. Kernel huge I/O mapping support
http://ozlabs.org/~akpm/mmotm/broken-out/x86-mm-support-huge-kva-mappings-on-x86.patch
http://ozlabs.org/~akpm/mmotm/broken-out/x86-mm-support-huge-i-o-mapping-capability-i-f.patch
http://ozlabs.org/~akpm/mmotm/broken-out/mm-change-vunmap-to-tear-down-huge-kva-mappings.patch
http://ozlabs.org/~akpm/mmotm/broken-out/mm-change-ioremap-to-set-up-huge-i-o-mappings.patch
http://ozlabs.org/~akpm/mmotm/broken-out/lib-add-huge-i-o-map-capability-interfaces.patch
http://ozlabs.org/~akpm/mmotm/broken-out/mm-change-__get_vm_area_node-to-use-fls_long.patch

Thanks,
-Toshi

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#239 lore raw

Re: [PATCH v4 0/7] mtrr, mm, x86: Enhance MTRR checks for huge I/O mapping

Quoted 23 lines · Toshi Kani
Quoted 22 lines · Ingo Molnar
Quoted 19 lines · Andrew Morton
Quoted 4 lines · On Tue, 24 Mar 2015 16:08:34 -0600 Toshi Kani <[email protected]> wrote:

This patchset enhances MTRR checks for the kernel huge I/O mapping, which was enabled by the patchset below:
https://lkml.org/lkml/2015/3/3/589

Quoted 8 lines

The following functional changes are made in patch 7/7.
- Allow pud_set_huge() and pmd_set_huge() to create a huge page mapping to a range covered by a single MTRR entry of any memory type.
- Log a pr_warn() message when a specified PMD map range spans more than a single MTRR entry. Drivers should make a mapping request aligned to a single MTRR entry when the range is covered by MTRRs.

OK, I grabbed these after barely looking at them, to get them a bit of runtime testing.

I'll await guidance from the x86 maintainers regarding next steps?

Quoted 8 lines
Quoted 5 lines

Could you please send the current version of them over to us if your testing didn't find any problems?

I'd like to take a final look and have them cook in the x86 tree as well for a while and want to preserve your testing effort.

This patchset is on top of the following patches in the -mm tree. (Patches apply from the bottom to the top.)

Ingo,

The following patches (2 got squashed to 1) went to 4.1-rc1, but this patch-set is still sitting in the -mm tree. I confirmed that the patch-set applies cleanly to 4.1-rc1. Please take a final look and let me know if you have any comment.

Thanks,
-Toshi

Quoted 14 lines

2. Build error fixes and cleanups
http://ozlabs.org/~akpm/mmotm/broken-out/x86-mm-support-huge-kva-mappings-on-x86-fix.patch
http://ozlabs.org/~akpm/mmotm/broken-out/mm-change-vunmap-to-tear-down-huge-kva-mappings-fix.patch
http://ozlabs.org/~akpm/mmotm/broken-out/mm-change-ioremap-to-set-up-huge-i-o-mappings-fix.patch
http://ozlabs.org/~akpm/mmotm/broken-out/lib-add-huge-i-o-map-capability-interfaces-fix.patch

1. Kernel huge I/O mapping support
http://ozlabs.org/~akpm/mmotm/broken-out/x86-mm-support-huge-kva-mappings-on-x86.patch
http://ozlabs.org/~akpm/mmotm/broken-out/x86-mm-support-huge-i-o-mapping-capability-i-f.patch
http://ozlabs.org/~akpm/mmotm/broken-out/mm-change-vunmap-to-tear-down-huge-kva-mappings.patch
http://ozlabs.org/~akpm/mmotm/broken-out/mm-change-ioremap-to-set-up-huge-i-o-mappings.patch
http://ozlabs.org/~akpm/mmotm/broken-out/lib-add-huge-i-o-map-capability-interfaces.patch
http://ozlabs.org/~akpm/mmotm/broken-out/mm-change-__get_vm_area_node-to-use-fls_long.patch

Quoted 3 lines

Thanks,
-Toshi

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#240 lore raw

PATCH 1/1 x86/kaslr: Fix typo in documentation

Documentation/x86/boot.txt labels the bit in boot_params.hdr.loadflags as ALSR_FLAG while it should be KASLR_FLAG.

---
 Documentation/x86/boot.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
Documentation/x86/boot.txt +1 -1
index 88b8589..69e1397 100644
@@ -406,7 +406,7 @@ Protocol:	2.00+
 	- If 0, the protected-mode code is loaded at 0x10000.
 	- If 1, the protected-mode code is loaded at 0x100000.
 
-  Bit 1 (kernel internal): ALSR_FLAG
+  Bit 1 (kernel internal): KASLR_FLAG
 	- Used internally by the compressed kernel to communicate
 	  KASLR status to kernel proper.
 	  If 1, KASLR enabled.
Signature · 1 line
2.1.4
#241 lore raw

Re: [PATCH] x86/kaslr: Fix typo in documentation

Quoted 13 lines · Miroslav Benes

Documentation/x86/boot.txt labels the bit in boot_params.hdr.loadflags as ALSR_FLAG while it should be KASLR_FLAG.

---
 Documentation/x86/boot.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
Documentation/x86/boot.txt +0 -0
index 88b8589..69e1397 100644

Documentation/x86/boot.txt Protocol: 2.00+ · line 412

Quoted 8 lines
Documentation/x86/boot.txt +1 -1
@@ -406,7 +406,7 @@ Protocol:	2.00+
 	- If 0, the protected-mode code is loaded at 0x10000.
 	- If 1, the protected-mode code is loaded at 0x100000.
 
-  Bit 1 (kernel internal): ALSR_FLAG
+  Bit 1 (kernel internal): KASLR_FLAG
 	- Used internally by the compressed kernel to communicate
 	  KASLR status to kernel proper.
 	  If 1, KASLR enabled.

Applied, thanks.

Signature · 5 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#242 lore raw

PATCH v4 1/1 mtrr: avoid ifdef'ery with phys_wc_to_mtrr_index()

From: "Luis R. Rodriguez" <[email protected]>

There is only one user but since we're going to bury MTRR next out of access to drivers expose this last piece of API to drivers in a general fashion only needing io.h for access to helpers.

Cc Toshi Kani <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Will Deacon <[email protected]>
Cc Thierry Reding <[email protected]>
Cc Andrew Morton <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Abhilash Kesavan <[email protected]>
Cc Matthias Brugger <[email protected]>
Cc Cristian Stoica <[email protected]>
Cc Suresh Siddha <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Antonino Daplas <[email protected]>
Cc Jean-Christophe Plagniol-Villard <[email protected]>
Cc Tomi Valkeinen <[email protected]>
Cc Ville Syrjälä <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Davidlohr Bueso <[email protected]>

---

This v4 adds a missing #endif.

 arch/x86/include/asm/io.h       |  3 +++
 arch/x86/include/asm/mtrr.h     |  5 -----
 arch/x86/kernel/cpu/mtrr/main.c |  6 +++---
 drivers/gpu/drm/drm_ioctl.c     | 14 +-------------
 include/linux/io.h              |  7 +++++++
 5 files changed, 14 insertions(+), 21 deletions(-)
arch/x86/include/asm/io.h +3 -0
index 4afc05f..a2b9740 100644
@@ -339,6 +339,9 @@ extern bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
 #define IO_SPACE_LIMIT 0xffff
 
 #ifdef CONFIG_MTRR
+extern int __must_check arch_phys_wc_index(int handle);
+#define arch_phys_wc_index arch_phys_wc_index
+
 extern int __must_check arch_phys_wc_add(unsigned long base,
 					 unsigned long size);
 extern void arch_phys_wc_del(int handle);
arch/x86/include/asm/mtrr.h +0 -5
index da8dff1..27e3dc0 100644
@@ -48,7 +48,6 @@ extern void mtrr_aps_init(void);
 extern void mtrr_bp_restore(void);
 extern int mtrr_trim_uncached_memory(unsigned long end_pfn);
 extern int amd_special_default_mtrr(void);
-extern int phys_wc_to_mtrr_index(int handle);
 #  else
 static inline u8 mtrr_type_lookup(u64 addr, u64 end, u8 *uniform)
 {
@@ -85,10 +84,6 @@ static inline int mtrr_trim_uncached_memory(unsigned long end_pfn)
 static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
 {
 }
-static inline int phys_wc_to_mtrr_index(int handle)
-{
-	return -1;
-}
 
 #define mtrr_ap_init() do {} while (0)
 #define mtrr_bp_init() do {} while (0)
arch/x86/kernel/cpu/mtrr/main.c +3 -3
index 12abdbe..d8c106c 100644
@@ -580,7 +580,7 @@ void arch_phys_wc_del(int handle)
 EXPORT_SYMBOL(arch_phys_wc_del);
 
 /*
- * phys_wc_to_mtrr_index - translates arch_phys_wc_add's return value
+ * arch_phys_wc_index - translates arch_phys_wc_add's return value
  * @handle: Return value from arch_phys_wc_add
  *
  * This will turn the return value from arch_phys_wc_add into an mtrr
@@ -590,14 +590,14 @@ EXPORT_SYMBOL(arch_phys_wc_del);
  * in printk line.  Alas there is an illegitimate use in some ancient
  * drm ioctls.
  */
-int phys_wc_to_mtrr_index(int handle)
+int arch_phys_wc_index(int handle)
 {
 	if (handle < MTRR_TO_PHYS_WC_OFFSET)
 		return -1;
 	else
 		return handle - MTRR_TO_PHYS_WC_OFFSET;
 }
-EXPORT_SYMBOL_GPL(phys_wc_to_mtrr_index);
+EXPORT_SYMBOL_GPL(arch_phys_wc_index);
 
 /*
  * HACK ALERT!
drivers/gpu/drm/drm_ioctl.c +1 -13
index 266dcd6..0a95782 100644
@@ -36,9 +36,6 @@
 
 #include <linux/pci.h>
 #include <linux/export.h>
-#ifdef CONFIG_X86
-#include <asm/mtrr.h>
-#endif
 
 static int drm_version(struct drm_device *dev, void *data,
 		       struct drm_file *file_priv);
@@ -197,16 +194,7 @@ static int drm_getmap(struct drm_device *dev, void *data,
 	map->type = r_list->map->type;
 	map->flags = r_list->map->flags;
 	map->handle = (void *)(unsigned long) r_list->user_token;
-
-#ifdef CONFIG_X86
-	/*
-	 * There appears to be exactly one user of the mtrr index: dritest.
-	 * It's easy enough to keep it working on non-PAT systems.
-	 */
-	map->mtrr = phys_wc_to_mtrr_index(r_list->map->mtrr);
-#else
-	map->mtrr = -1;
-#endif
+	map->mtrr = arch_phys_wc_index(r_list->map->mtrr);
 
 	mutex_unlock(&dev->struct_mutex);
 
include/linux/io.h +7 -0
index 986f2bf..04cce4d 100644
@@ -111,6 +111,13 @@ static inline void arch_phys_wc_del(int handle)
 }
 
 #define arch_phys_wc_add arch_phys_wc_add
+#ifndef arch_phys_wc_index
+static inline int arch_phys_wc_index(int handle)
+{
+	return -1;
+}
+#define arch_phys_wc_index arch_phys_wc_index
+#endif
 #endif
 
 #endif /* _LINUX_IO_H */
Signature · 1 line
2.3.2.209.gd67f9d5.dirty
#243 lore raw

PATCH 1/1 x86: improve algorithm in clflush_cache_range

The current algorithm used in clflush_cache_range() can cause the last cache line of the buffer to be flushed twice. Fix that algorithm so that each cache line will only be flushed once.

Cc H. Peter Anvin <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 arch/x86/mm/pageattr.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)
arch/x86/mm/pageattr.c +6 -7
index 89af288ec674..338e507f95b8 100644
@@ -129,16 +129,15 @@ within(unsigned long addr, unsigned long start, unsigned long end)
  */
 void clflush_cache_range(void *vaddr, unsigned int size)
 {
-	void *vend = vaddr + size - 1;
+	unsigned long clflush_mask = boot_cpu_data.x86_clflush_size - 1;
+	char *vend = (char *)vaddr + size;
+	char *p;
 
 	mb();
 
-	for (; vaddr < vend; vaddr += boot_cpu_data.x86_clflush_size)
-		clflushopt(vaddr);
-	/*
-	 * Flush any possible final partial cacheline:
-	 */
-	clflushopt(vend);
+	for (p = (char *)((unsigned long)vaddr & ~clflush_mask);
+	     p < vend; p += boot_cpu_data.x86_clflush_size)
+		clflushopt(p);
 
 	mb();
 }
Signature · 1 line
1.9.3
#244 lore raw

Re: [PATCH] x86: improve algorithm in clflush_cache_range

Quoted 11 lines · Ross Zwisler

The current algorithm used in clflush_cache_range() can cause the last cache line of the buffer to be flushed twice. Fix that algorithm so that each cache line will only be flushed once.

Cc H. Peter Anvin <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Borislav Petkov <[email protected]>
Quoted 3 lines
---
 arch/x86/mm/pageattr.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

Applied, thanks.

Signature · 5 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#245 lore raw

PATCH v2 1/1 x86: Add kerneldoc for pcommit_sfence()

Add kerneldoc comments for pcommit_sfence() describing the purpose of the pcommit instruction and demonstrating the usage of that instruction.

Cc H Peter Anvin <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Borislav Petkov <[email protected]>
---
 arch/x86/include/asm/special_insns.h | 37 ++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)
arch/x86/include/asm/special_insns.h +37 -0
index aeb4666e0c0a..c9f2ebec33ac 100644
@@ -215,6 +215,43 @@ static inline void clwb(volatile void *__p)
 		: [pax] "a" (p));
 }
 
+/**
+ * pcommit_sfence() - persistent commit and fence
+ *
+ * The PCOMMIT instruction ensures that data that has been flushed from the
+ * processor's cache hierarchy with CLWB, CLFLUSHOPT or CLFLUSH is accepted to
+ * memory and is durable on the DIMM.  The primary use case for this is
+ * persistent memory.
+ *
+ * This function shows how to properly use CLWB/CLFLUSHOPT/CLFLUSH and PCOMMIT
+ * with appropriate fencing:
+ *
+ * void flush_and_commit_buffer(void *vaddr, unsigned int size)
+ * {
+ *         unsigned long clflush_mask = boot_cpu_data.x86_clflush_size - 1;
+ *         void *vend = vaddr + size;
+ *         void *p;
+ *
+ *         for (p = (void *)((unsigned long)vaddr & ~clflush_mask);
+ *              p < vend; p += boot_cpu_data.x86_clflush_size)
+ *                 clwb(p);
+ *
+ *         // SFENCE to order CLWB/CLFLUSHOPT/CLFLUSH cache flushes
+ *         // MFENCE via mb() also works
+ *         wmb();
+ *
+ *         // PCOMMIT and the required SFENCE for ordering
+ *         pcommit_sfence();
+ * }
+ *
+ * After this function completes the data pointed to by 'vaddr' has been
+ * accepted to memory and will be durable if the 'vaddr' points to persistent
+ * memory.
+ *
+ * PCOMMIT must always be ordered by an MFENCE or SFENCE, so to help simplify
+ * things we include both the PCOMMIT and the required SFENCE in the
+ * alternatives generated by pcommit_sfence().
+ */
 static inline void pcommit_sfence(void)
 {
 	alternative(ASM_NOP7,
Signature · 1 line
1.9.3
maintainer Applied
#246 lore raw

Re: [PATCH v2] x86: Add kerneldoc for pcommit_sfence()

Quoted 9 lines · Ross Zwisler

Add kerneldoc comments for pcommit_sfence() describing the purpose of the pcommit instruction and demonstrating the usage of that instruction.

Cc H Peter Anvin <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Borislav Petkov <[email protected]>

---

Applied, thanks.

I added the "Example:" thing because apparently kernel-doc parses that, see below.

Doing

$ scripts/kernel-doc -html arch/x86/include/asm/special_insns.h > /tmp/doc.html

and then looking at doc.html doesn't make me go all full of joy and clap my hands but whatever, it is better than nothing.

---
From: Ross Zwisler <[email protected]>
Date: Tue, 28 Apr 2015 16:46:36 -0600
Subject: [PATCH] x86/mm: Add kerneldoc comments for pcommit_sfence()

Add kerneldoc comments for pcommit_sfence() describing the purpose of the PCOMMIT instruction and demonstrating its usage with an example.

---
 arch/x86/include/asm/special_insns.h | 38 ++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)
arch/x86/include/asm/special_insns.h +38 -0
index aeb4666e0c0a..2270e41b32fd 100644
@@ -215,6 +215,44 @@ static inline void clwb(volatile void *__p)
 		: [pax] "a" (p));
 }
 
+/**
+ * pcommit_sfence() - persistent commit and fence
+ *
+ * The PCOMMIT instruction ensures that data that has been flushed from the
+ * processor's cache hierarchy with CLWB, CLFLUSHOPT or CLFLUSH is accepted to
+ * memory and is durable on the DIMM.  The primary use case for this is
+ * persistent memory.
+ *
+ * This function shows how to properly use CLWB/CLFLUSHOPT/CLFLUSH and PCOMMIT
+ * with appropriate fencing.
+ *
+ * Example:
+ * void flush_and_commit_buffer(void *vaddr, unsigned int size)
+ * {
+ *         unsigned long clflush_mask = boot_cpu_data.x86_clflush_size - 1;
+ *         void *vend = vaddr + size;
+ *         void *p;
+ *
+ *         for (p = (void *)((unsigned long)vaddr & ~clflush_mask);
+ *              p < vend; p += boot_cpu_data.x86_clflush_size)
+ *                 clwb(p);
+ *
+ *         // SFENCE to order CLWB/CLFLUSHOPT/CLFLUSH cache flushes
+ *         // MFENCE via mb() also works
+ *         wmb();
+ *
+ *         // PCOMMIT and the required SFENCE for ordering
+ *         pcommit_sfence();
+ * }
+ *
+ * After this function completes the data pointed to by 'vaddr' has been
+ * accepted to memory and will be durable if the 'vaddr' points to persistent
+ * memory.
+ *
+ * PCOMMIT must always be ordered by an MFENCE or SFENCE, so to help simplify
+ * things we include both the PCOMMIT and the required SFENCE in the
+ * alternatives generated by pcommit_sfence().
+ */
 static inline void pcommit_sfence(void)
 {
 	alternative(ASM_NOP7,
Signature · 8 lines
2.3.5

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#247 lore raw

v4 cover x86: document and address MTRR corner cases

From: "Luis R. Rodriguez" <[email protected]>

This series addresses one commend fix on the table for mtrr_add() effect on the PAT case when UC- is used. Other than that it is the same as v4.

Luis R. Rodriguez (6):
x86: add ioremap_uc() - force strong UC, PCD=1, PWT=1
x86: document WC MTRR effects on PAT / non-PAT pages
video: fbdev: atyfb: move framebuffer length fudging to helper
video: fbdev: atyfb: clarify ioremap() base and length used
video: fbdev: atyfb: replace MTRR UC hole with strong UC
video: fbdev: atyfb: use arch_phys_wc_add() and ioremap_wc()

 Documentation/x86/mtrr.txt           | 18 +++++--
 Documentation/x86/pat.txt            | 40 ++++++++++++++-
 arch/x86/include/asm/io.h            |  1 +
 arch/x86/kernel/cpu/mtrr/main.c      |  3 ++
 arch/x86/mm/ioremap.c                | 36 ++++++++++++-
 arch/x86/mm/pageattr.c               |  3 ++
 drivers/video/fbdev/aty/atyfb.h      |  5 +-
 drivers/video/fbdev/aty/atyfb_base.c | 98 ++++++++++++++----------------------
 include/asm-generic/io.h             |  8 +++
 9 files changed, 143 insertions(+), 69 deletions(-)
Signature · 1 line
2.3.2.209.gd67f9d5.dirty
#248 lore raw

PATCH v4 1/6 x86: add ioremap_uc() - force strong UC, PCD=1, PWT=1

From: "Luis R. Rodriguez" <[email protected]>

ioremap_nocache() currently uses UC- by default. Our goal is to eventually make UC the default. Linux maps UC- to PCD=1, PWT=0 page attributes on non-PAT systems. Linux maps UC to PCD=1, PWT=1 page attributes on non-PAT systems. On non-PAT and PAT systems a WC MTRR has different effects on pages with either of these attributes. In order to help with a smooth transition its best to enable use of UC (PCD,1, PWT=1) on a region as that ensures a WC MTRR will have no effect on a region, this however requires us to have an way to declare a region as UC and we currently do not have a way to do this.

WC MTRR on non-PAT system with PCD=1, PWT=0 (UC-) yields WC. WC MTRR on non-PAT system with PCD=1, PWT=1 (UC) yields UC.

WC MTRR on PAT system with PCD=1, PWT=0 (UC-) yields WC. WC MTRR on PAT system with PCD=1, PWT=1 (UC) yields UC.

A flip of the default ioremap_nocache() behaviour from UC- to UC can therefore regress a memory region from effective memory type WC to UC if MTRRs are used. Use of MTRRs should be phased out and in the best case only arch_phys_wc_add() use will remain, even if this happens arch_phys_wc_add() will have an effect on non-PAT systems and changes to default ioremap_nocache() behaviour could regress drivers.

Now, ideally we'd use ioremap_nocache() on the regions in which we'd need uncachable memory types and avoid any MTRRs on those regions. There are however some restrictions on MTRRs use, such as the requirement of having the base and size of variable sized MTRRs to be powers of two, which could mean having to use a WC MTRR over a large area which includes a region in which write-combining effects are undesirable.

Add ioremap_uc() to help with the both phasing out of MTRR use and also provide a way to blacklist small WC undesirable regions in devices with mixed regions which are size-implicated to use large WC MTRRs. Use of ioremap_uc() helps phase out MTRR use by avoiding regressions with an eventual flip of default behaviour or ioremap_nocache() from UC- to UC.

Drivers working with WC MTRRs can use the below table to review and consider the use of ioremap*() and similar helpers to ensure appropriate behaviour long term even if default ioremap_nocache() behaviour changes from UC- to UC.

Although ioremap_uc() is being added we leave set_memory_uc() to use UC- as only initial memory type setup is required to be able to accomodate existing device drivers and phase out MTRR use. It should also be clarified that set_memory_uc() cannot be used with IO memory, even though its use will not return any errors, it really has no effect.

----------------------------------------------------------------------
MTRR Non-PAT PAT Linux ioremap value Effective memory type
----------------------------------------------------------------------

                                                  Non-PAT |  PAT
     PAT
     |PCD
     ||PWT
     |||
WC   000      WB      _PAGE_CACHE_MODE_WB            WC   |   WC
WC   001      WC      _PAGE_CACHE_MODE_WC            WC*  |   WC
WC   010      UC-     _PAGE_CACHE_MODE_UC_MINUS      WC*  |   WC
WC   011      UC      _PAGE_CACHE_MODE_UC            UC   |   UC

----------------------------------------------------------------------

Cc Toshi Kani <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Suresh Siddha <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Antonino Daplas <[email protected]>
Cc Jean-Christophe Plagniol-Villard <[email protected]>
Cc Tomi Valkeinen <[email protected]>
Cc Ville Syrjälä <[email protected]>
Cc Will Deacon <[email protected]>
Cc Thierry Reding <[email protected]>
Cc Mike Travis <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Davidlohr Bueso <[email protected]>
---
 arch/x86/include/asm/io.h |  1 +
 arch/x86/mm/ioremap.c     | 36 +++++++++++++++++++++++++++++++++++-
 arch/x86/mm/pageattr.c    |  3 +++
 include/asm-generic/io.h  |  8 ++++++++
 4 files changed, 47 insertions(+), 1 deletion(-)
arch/x86/include/asm/io.h +1 -0
index 34a5b93..4afc05f 100644
@@ -177,6 +177,7 @@ static inline unsigned int isa_virt_to_bus(volatile void *address)
  * look at pci_iomap().
  */
 extern void __iomem *ioremap_nocache(resource_size_t offset, unsigned long size);
+extern void __iomem *ioremap_uc(resource_size_t offset, unsigned long size);
 extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size);
 extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size,
 				unsigned long prot_val);
arch/x86/mm/ioremap.c +35 -1
index 70e7444..a493bb8 100644
@@ -237,7 +237,8 @@ void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
 	 *	pat_enabled ? _PAGE_CACHE_MODE_UC : _PAGE_CACHE_MODE_UC_MINUS;
 	 *
 	 * Till we fix all X drivers to use ioremap_wc(), we will use
-	 * UC MINUS.
+	 * UC MINUS. Drivers that are certain they need or can already
+	 * be converted over to strong UC can use ioremap_uc().
 	 */
 	enum page_cache_mode pcm = _PAGE_CACHE_MODE_UC_MINUS;
 
@@ -247,6 +248,39 @@ void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
 EXPORT_SYMBOL(ioremap_nocache);
 
 /**
+ * ioremap_uc     -   map bus memory into CPU space as strongly uncachable
+ * @phys_addr:    bus address of the memory
+ * @size:      size of the resource to map
+ *
+ * ioremap_uc performs a platform specific sequence of operations to
+ * make bus memory CPU accessible via the readb/readw/readl/writeb/
+ * writew/writel functions and the other mmio helpers. The returned
+ * address is not guaranteed to be usable directly as a virtual
+ * address.
+ *
+ * This version of ioremap ensures that the memory is marked with a strong
+ * preference as completely uncachable on the CPU when possible. For non-PAT
+ * systems this ends up setting page-attribute flags PCD=1, PWT=1. For PAT
+ * systems this will set the PAT entry for the pages as strong UC.  This call
+ * will honor existing caching rules from things like the PCI bus. Note that
+ * there are other caches and buffers on many busses. In particular driver
+ * authors should read up on PCI writes.
+ *
+ * It's useful if some control registers are in such an area and
+ * write combining or read caching is not desirable:
+ *
+ * Must be freed with iounmap.
+ */
+void __iomem *ioremap_uc(resource_size_t phys_addr, unsigned long size)
+{
+	enum page_cache_mode pcm = _PAGE_CACHE_MODE_UC;
+
+	return __ioremap_caller(phys_addr, size, pcm,
+				__builtin_return_address(0));
+}
+EXPORT_SYMBOL_GPL(ioremap_uc);
+
+/**
  * ioremap_wc	-	map memory into CPU space write combined
  * @phys_addr:	bus address of the memory
  * @size:	size of the resource to map
arch/x86/mm/pageattr.c +3 -0
index 89af288..49660c0 100644
@@ -1468,6 +1468,9 @@ int _set_memory_uc(unsigned long addr, int numpages)
 {
 	/*
 	 * for now UC MINUS. see comments in ioremap_nocache()
+	 * If you really need strong UC use ioremap_uc(), but note
+	 * that you cannot override IO areas with set_memory_*() as
+	 * these helpers cannot work with IO memory.
 	 */
 	return change_page_attr_set(&addr, numpages,
 				    cachemode2pgprot(_PAGE_CACHE_MODE_UC_MINUS),
include/asm-generic/io.h +8 -0
index 9db0423..90ccba7 100644
@@ -769,6 +769,14 @@ static inline void __iomem *ioremap_nocache(phys_addr_t offset, size_t size)
 }
 #endif
 
+#ifndef ioremap_uc
+#define ioremap_uc ioremap_uc
+static inline void __iomem *ioremap_uc(phys_addr_t offset, size_t size)
+{
+	return ioremap_nocache(offset, size);
+}
+#endif
+
 #ifndef ioremap_wc
 #define ioremap_wc ioremap_wc
 static inline void __iomem *ioremap_wc(phys_addr_t offset, size_t size)
Signature · 1 line
2.3.2.209.gd67f9d5.dirty
maintainer
#249 lore raw

Re: [PATCH v4 1/6] x86: add ioremap_uc() - force strong UC, PCD=1, PWT=1

Quoted 99 lines · Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

ioremap_nocache() currently uses UC- by default. Our goal is to eventually make UC the default. Linux maps UC- to PCD=1, PWT=0 page attributes on non-PAT systems. Linux maps UC to PCD=1, PWT=1 page attributes on non-PAT systems. On non-PAT and PAT systems a WC MTRR has different effects on pages with either of these attributes. In order to help with a smooth transition its best to enable use of UC (PCD,1, PWT=1) on a region as that ensures a WC MTRR will have no effect on a region, this however requires us to have an way to declare a region as UC and we currently do not have a way to do this.

WC MTRR on non-PAT system with PCD=1, PWT=0 (UC-) yields WC. WC MTRR on non-PAT system with PCD=1, PWT=1 (UC) yields UC.

WC MTRR on PAT system with PCD=1, PWT=0 (UC-) yields WC. WC MTRR on PAT system with PCD=1, PWT=1 (UC) yields UC.

A flip of the default ioremap_nocache() behaviour from UC- to UC can therefore regress a memory region from effective memory type WC to UC if MTRRs are used. Use of MTRRs should be phased out and in the best case only arch_phys_wc_add() use will remain, even if this happens arch_phys_wc_add() will have an effect on non-PAT systems and changes to default ioremap_nocache() behaviour could regress drivers.

Now, ideally we'd use ioremap_nocache() on the regions in which we'd need uncachable memory types and avoid any MTRRs on those regions. There are however some restrictions on MTRRs use, such as the requirement of having the base and size of variable sized MTRRs to be powers of two, which could mean having to use a WC MTRR over a large area which includes a region in which write-combining effects are undesirable.

Add ioremap_uc() to help with the both phasing out of MTRR use and also provide a way to blacklist small WC undesirable regions in devices with mixed regions which are size-implicated to use large WC MTRRs. Use of ioremap_uc() helps phase out MTRR use by avoiding regressions with an eventual flip of default behaviour or ioremap_nocache() from UC- to UC.

Drivers working with WC MTRRs can use the below table to review and consider the use of ioremap*() and similar helpers to ensure appropriate behaviour long term even if default ioremap_nocache() behaviour changes from UC- to UC.

Although ioremap_uc() is being added we leave set_memory_uc() to use UC- as only initial memory type setup is required to be able to accomodate existing device drivers and phase out MTRR use. It should also be clarified that set_memory_uc() cannot be used with IO memory, even though its use will not return any errors, it really has no effect.

----------------------------------------------------------------------
MTRR Non-PAT PAT Linux ioremap value Effective memory type
----------------------------------------------------------------------

                                                  Non-PAT |  PAT
     PAT
     |PCD
     ||PWT
     |||
WC   000      WB      _PAGE_CACHE_MODE_WB            WC   |   WC
WC   001      WC      _PAGE_CACHE_MODE_WC            WC*  |   WC
WC   010      UC-     _PAGE_CACHE_MODE_UC_MINUS      WC*  |   WC
WC   011      UC      _PAGE_CACHE_MODE_UC            UC   |   UC

----------------------------------------------------------------------

Cc Toshi Kani <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Suresh Siddha <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Antonino Daplas <[email protected]>
Cc Jean-Christophe Plagniol-Villard <[email protected]>
Cc Tomi Valkeinen <[email protected]>
Cc Ville Syrjälä <[email protected]>
Cc Will Deacon <[email protected]>
Cc Thierry Reding <[email protected]>
Cc Mike Travis <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Davidlohr Bueso <[email protected]>
Quoted 6 lines
---
 arch/x86/include/asm/io.h |  1 +
 arch/x86/mm/ioremap.c     | 36 +++++++++++++++++++++++++++++++++++-
 arch/x86/mm/pageattr.c    |  3 +++
 include/asm-generic/io.h  |  8 ++++++++
 4 files changed, 47 insertions(+), 1 deletion(-)

Looks ok to me. Applied, thanks.

Signature · 5 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#250 lore raw

PATCH v4 2/6 x86: document WC MTRR effects on PAT / non-PAT pages

In reply to Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

As part of the effort to phase out MTRR use document write-combining MTRR effects on pages with different non-PAT page attributes flags and different PAT entry values. Extend arch_phys_wc_add() documentation to clarify power of two sizes / boundary requirements as we phase out mtrr_add() use.

Lastly hint towards ioremap_uc() for corner cases on device drivers working with devices with mixed regions where MTRR size requirements would otherwise not enable write-combining effective memory types.

Cc Toshi Kani <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Suresh Siddha <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Antonino Daplas <[email protected]>
Cc Jean-Christophe Plagniol-Villard <[email protected]>
Cc Tomi Valkeinen <[email protected]>
Cc Ville Syrjälä <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Davidlohr Bueso <[email protected]>
---
 Documentation/x86/mtrr.txt      | 18 +++++++++++++++---
 Documentation/x86/pat.txt       | 40 +++++++++++++++++++++++++++++++++++++++-
 arch/x86/kernel/cpu/mtrr/main.c |  3 +++
 3 files changed, 57 insertions(+), 4 deletions(-)
Documentation/x86/mtrr.txt +14 -3
index cc071dc..a111a6c 100644
@@ -1,7 +1,19 @@
 MTRR (Memory Type Range Register) control
-3 Jun 1999
-Richard Gooch
-<[email protected]>
+
+Richard Gooch <[email protected]> - 3 Jun 1999
+Luis R. Rodriguez <[email protected]> - April 9, 2015
+
+=======================================+Phasing MTRR use
+
+MTRR use is replaced on modern x86 hardware with PAT. Over time the only type
+of effective MTRR that is expected to be supported will be for write-combining.
+As MTRR use is phased out device drivers should use arch_phys_wc_add() to make
+MTRR effective on non-PAT systems while a no-op on PAT enabled systems.
+
+For details refer to Documentation/x86/pat.txt.
+
+======================================= 
   On Intel P6 family processors (Pentium Pro, Pentium II and later)
   the Memory Type Range Registers (MTRRs) may be used to control
Documentation/x86/pat.txt +39 -1
index cf08c9f..7e183e3 100644
@@ -34,6 +34,8 @@ ioremap                |    --    |    UC-     |       UC-        |
                        |          |            |                  |
 ioremap_cache          |    --    |    WB      |       WB         |
                        |          |            |                  |
+ioremap_uc             |    --    |    UC      |       UC         |
+                       |          |            |                  |
 ioremap_nocache        |    --    |    UC-     |       UC-        |
                        |          |            |                  |
 ioremap_wc             |    --    |    --      |       WC         |
@@ -102,7 +104,43 @@ wants to export a RAM region, it has to do set_memory_uc() or set_memory_wc()
 as step 0 above and also track the usage of those pages and use set_memory_wb()
 before the page is freed to free pool.
 
-
+MTRR effects on PAT / non-PAT systems
+-------------------------------------
+
+The following table provides the effects of using write-combining MTRRs when
+using ioremap*() calls on x86 for both non-PAT and PAT systems. Ideally
+mtrr_add() usage will be phased in favor of arch_phys_wc_add() which will
+be a no-op on PAT enabled systems. The region over which a arch_phys_wc_add()
+is made should already have be ioremap'd with write-combining page attributes
+or PAT entries, this can be done by using ioremap_wc() / or respective helpers.
+Devices which combine areas of IO memory desired to remain uncachable with
+areas where write-combining is desirable and are restricted by the size
+requirements of MTRRs should consider splitting up their IO memory space
+cleanly with ioremap_uc() and ioremap_wc() followed by an arch_phys_wc_add()
+encompassing both regions. Such use is nevertheless heavily discouraged as
+the effective memory type is considered implementation defined. This strategy
+should only be used as last resort on devices with size-contrained regions
+where otherwise MTRR write-combining would not be effective.
+
+Note that you cannot use set_memory_wc() to override / whitelist IO remapped
+memory space mapped with ioremap*() calls, set_memory_wc() can only be used
+on RAM.
+
+----------------------------------------------------------------------
+MTRR Non-PAT   PAT    Linux ioremap value        Effective memory type
+----------------------------------------------------------------------
+                                                  Non-PAT |  PAT
+     PAT
+     |PCD
+     ||PWT
+     |||
+WC   000      WB      _PAGE_CACHE_MODE_WB            WC   |   WC
+WC   001      WC      _PAGE_CACHE_MODE_WC            WC*  |   WC
+WC   010      UC-     _PAGE_CACHE_MODE_UC_MINUS      WC*  |   WC
+WC   011      UC      _PAGE_CACHE_MODE_UC            UC   |   UC
+----------------------------------------------------------------------
+
+(*) denotes implementation defined and is discouraged
 
 Notes:
 
arch/x86/kernel/cpu/mtrr/main.c +3 -0
index ea5f363..12abdbe 100644
@@ -538,6 +538,9 @@ EXPORT_SYMBOL(mtrr_del);
  * attempts to add a WC MTRR covering size bytes starting at base and
  * logs an error if this fails.
  *
+ * The caller should expect to need to provide a power of two size on an
+ * equivalent power of two boundary.
+ *
  * Drivers must store the return value to pass to mtrr_del_wc_if_needed,
  * but drivers should not try to interpret that return value.
  */
Signature · 1 line
2.3.2.209.gd67f9d5.dirty
reviewer
#251 lore raw

Re: [PATCH v4 2/6] x86: document WC MTRR effects on PAT / non-PAT pages

Quoted 18 lines · Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

---
 Documentation/x86/mtrr.txt      | 18 +++++++++++++++---
 Documentation/x86/pat.txt       | 40 +++++++++++++++++++++++++++++++++++++++-
 arch/x86/kernel/cpu/mtrr/main.c |  3 +++
 3 files changed, 57 insertions(+), 4 deletions(-)
Documentation/x86/pat.txt +0 -1
index cf08c9f..7e183e3 100644
@@ -102,7 +104,43 @@ wants to export a RAM region, it has to do set_memory_uc() or set_memory_wc()
 as step 0 above and also track the usage of those pages and use set_memory_wb()
 before the page is freed to free pool.
 
-

Documentation/x86/pat.txt wants to export a RAM region, it has to do set_memory_uc() or set_memory_wc() · line 116

Quoted 10 lines
Documentation/x86/pat.txt +10 -0
+MTRR effects on PAT / non-PAT systems
+-------------------------------------
+
+The following table provides the effects of using write-combining MTRRs when
+using ioremap*() calls on x86 for both non-PAT and PAT systems. Ideally
+mtrr_add() usage will be phased in favor of arch_phys_wc_add() which will
+be a no-op on PAT enabled systems. The region over which a arch_phys_wc_add()
+is made should already have be ioremap'd with write-combining page attributes
+or PAT entries, this can be done by using ioremap_wc() / or respective helpers.
+Devices which combine areas of IO memory desired to remain uncachable with

I would spell it uncacheable. In kernel Documentation/, grep uncacheable finds 14 hits vs. 6 hits for uncachable. No big deal.

Documentation/x86/pat.txt wants to export a RAM region, it has to do set_memory_uc() or set_memory_wc() · line 122

Quoted 6 lines
Documentation/x86/pat.txt +6 -0
+areas where write-combining is desirable and are restricted by the size
+requirements of MTRRs should consider splitting up their IO memory space
+cleanly with ioremap_uc() and ioremap_wc() followed by an arch_phys_wc_add()
+encompassing both regions. Such use is nevertheless heavily discouraged as
+the effective memory type is considered implementation defined. This strategy
+should only be used as last resort on devices with size-contrained regions

size-constrained

Quoted 29 lines
Documentation/x86/pat.txt +21 -0
+where otherwise MTRR write-combining would not be effective.
+
+Note that you cannot use set_memory_wc() to override / whitelist IO remapped
+memory space mapped with ioremap*() calls, set_memory_wc() can only be used
+on RAM.
+
+----------------------------------------------------------------------
+MTRR Non-PAT   PAT    Linux ioremap value        Effective memory type
+----------------------------------------------------------------------
+                                                  Non-PAT |  PAT
+     PAT
+     |PCD
+     ||PWT
+     |||
+WC   000      WB      _PAGE_CACHE_MODE_WB            WC   |   WC
+WC   001      WC      _PAGE_CACHE_MODE_WC            WC*  |   WC
+WC   010      UC-     _PAGE_CACHE_MODE_UC_MINUS      WC*  |   WC
+WC   011      UC      _PAGE_CACHE_MODE_UC            UC   |   UC
+----------------------------------------------------------------------
+
+(*) denotes implementation defined and is discouraged
 
 Notes:
 
arch/x86/kernel/cpu/mtrr/main.c +0 -0
index ea5f363..12abdbe 100644

arch/x86/kernel/cpu/mtrr/main.c EXPORT_SYMBOL(mtrr_del); · line 541

Quoted 4 lines
arch/x86/kernel/cpu/mtrr/main.c +1 -0
@@ -538,6 +538,9 @@ EXPORT_SYMBOL(mtrr_del);
  * attempts to add a WC MTRR covering size bytes starting at base and
  * logs an error if this fails.
  *
+ * The caller should expect to need to provide a power of two size on an

* The called should provide a power of two size on an equivalent
* power of two boundary.

Quoted 6 lines
arch/x86/kernel/cpu/mtrr/main.c +2 -0
+ * equivalent power of two boundary.
+ *
  * Drivers must store the return value to pass to mtrr_del_wc_if_needed,
  * but drivers should not try to interpret that return value.
  */
Signature · 1 line
~Randy
#252 lore raw

Re: [PATCH v4 2/6] x86: document WC MTRR effects on PAT / non-PAT pages

Quoted 58 lines · Randy Dunlap
Quoted 10 lines · Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

Documentation/x86/pat.txt +0 -1
index cf08c9f..7e183e3 100644
@@ -102,7 +104,43 @@ wants to export a RAM region, it has to do set_memory_uc() or set_memory_wc()
 as step 0 above and also track the usage of those pages and use set_memory_wb()
 before the page is freed to free pool.
 
-

Documentation/x86/pat.txt wants to export a RAM region, it has to do set_memory_uc() or set_memory_wc() · line 116

Quoted 10 lines
Documentation/x86/pat.txt +10 -0
+MTRR effects on PAT / non-PAT systems
+-------------------------------------
+
+The following table provides the effects of using write-combining MTRRs when
+using ioremap*() calls on x86 for both non-PAT and PAT systems. Ideally
+mtrr_add() usage will be phased in favor of arch_phys_wc_add() which will
+be a no-op on PAT enabled systems. The region over which a arch_phys_wc_add()
+is made should already have be ioremap'd with write-combining page attributes
+or PAT entries, this can be done by using ioremap_wc() / or respective helpers.
+Devices which combine areas of IO memory desired to remain uncachable with

I would spell it uncacheable. In kernel Documentation/, grep uncacheable finds 14 hits vs. 6 hits for uncachable. No big deal.

Documentation/x86/pat.txt wants to export a RAM region, it has to do set_memory_uc() or set_memory_wc() · line 122

Quoted 6 lines
Documentation/x86/pat.txt +6 -0
+areas where write-combining is desirable and are restricted by the size
+requirements of MTRRs should consider splitting up their IO memory space
+cleanly with ioremap_uc() and ioremap_wc() followed by an arch_phys_wc_add()
+encompassing both regions. Such use is nevertheless heavily discouraged as
+the effective memory type is considered implementation defined. This strategy
+should only be used as last resort on devices with size-contrained regions

size-constrained

Quoted 24 lines
Documentation/x86/pat.txt +21 -0
+where otherwise MTRR write-combining would not be effective.
+
+Note that you cannot use set_memory_wc() to override / whitelist IO remapped
+memory space mapped with ioremap*() calls, set_memory_wc() can only be used
+on RAM.
+
+----------------------------------------------------------------------
+MTRR Non-PAT   PAT    Linux ioremap value        Effective memory type
+----------------------------------------------------------------------
+                                                  Non-PAT |  PAT
+     PAT
+     |PCD
+     ||PWT
+     |||
+WC   000      WB      _PAGE_CACHE_MODE_WB            WC   |   WC
+WC   001      WC      _PAGE_CACHE_MODE_WC            WC*  |   WC
+WC   010      UC-     _PAGE_CACHE_MODE_UC_MINUS      WC*  |   WC
+WC   011      UC      _PAGE_CACHE_MODE_UC            UC   |   UC
+----------------------------------------------------------------------
+
+(*) denotes implementation defined and is discouraged
 
 Notes:
 
Quoted 13 lines

arch/x86/kernel/cpu/mtrr/main.c EXPORT_SYMBOL(mtrr_del); · line 541

Quoted 9 lines
arch/x86/kernel/cpu/mtrr/main.c +1 -0
index ea5f363..12abdbe 100644
@@ -538,6 +538,9 @@ EXPORT_SYMBOL(mtrr_del);
  * attempts to add a WC MTRR covering size bytes starting at base and
  * logs an error if this fails.
  *
+ * The caller should expect to need to provide a power of two size on an

* The called should provide a power of two size on an equivalent
* power of two boundary.

Thanks since Boris took this already I'll let him amend unless he wishes for me to send a new version.

Luis

#253 lore raw

Re: [PATCH v4 2/6] x86: document WC MTRR effects on PAT / non-PAT pages

Quoted 2 lines · Luis R. Rodriguez

Thanks since Boris took this already I'll let him amend unless he wishes for me to send a new version.

Haven't. I'm waiting for v2.

Signature · 5 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#254 lore raw

Re: [PATCH v4 2/6] x86: document WC MTRR effects on PAT / non-PAT pages

Quoted 5 lines · Borislav Petkov
Quoted 2 lines · Luis R. Rodriguez

Thanks since Boris took this already I'll let him amend unless he wishes for me to send a new version.

Haven't. I'm waiting for v2.

OK thanks, it'll be a v5 actually. I am only resending the documentation patch.

Ville, are you OK with the other atyfb patches that follow up on top of this? If so since they depend on ioremap_uc() should it go through Boris as he's taking that in?

Luis

#255 lore raw

Re: [PATCH v4 2/6] x86: document WC MTRR effects on PAT / non-PAT pages

Quoted 2 lines · Luis R. Rodriguez

If so since they depend on ioremap_uc() should it go through Boris as he's taking that in?

Let's slow down a bit first, ok? First let's have all the x86 changes ready, in and tested. Drivers can convert to them in a following step.

Signature · 5 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#256 lore raw

Re: [PATCH v4 2/6] x86: document WC MTRR effects on PAT / non-PAT pages

In reply to Randy Dunlap
Quoted 18 lines · Randy Dunlap
Quoted 17 lines · Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

---
 Documentation/x86/mtrr.txt      | 18 +++++++++++++++---
 Documentation/x86/pat.txt       | 40 +++++++++++++++++++++++++++++++++++++++-
 arch/x86/kernel/cpu/mtrr/main.c |  3 +++
 3 files changed, 57 insertions(+), 4 deletions(-)
Documentation/x86/pat.txt +0 -0
index cf08c9f..7e183e3 100644
@@ -102,7 +104,43 @@ wants to export a RAM region, it has to do set_memory_uc() or set_memory_wc()
 as step 0 above and also track the usage of those pages and use set_memory_wb()
 before the page is freed to free pool.
 
Quoted 14 lines

Documentation/x86/pat.txt wants to export a RAM region, it has to do set_memory_uc() or set_memory_wc() · line 116

Quoted 11 lines
Documentation/x86/pat.txt +10 -1
-
+MTRR effects on PAT / non-PAT systems
+-------------------------------------
+
+The following table provides the effects of using write-combining MTRRs when
+using ioremap*() calls on x86 for both non-PAT and PAT systems. Ideally
+mtrr_add() usage will be phased in favor of arch_phys_wc_add() which will
+be a no-op on PAT enabled systems. The region over which a arch_phys_wc_add()
+is made should already have be ioremap'd with write-combining page attributes
+or PAT entries, this can be done by using ioremap_wc() / or respective helpers.
+Devices which combine areas of IO memory desired to remain uncachable with

I would spell it uncacheable. In kernel Documentation/, grep uncacheable finds 14 hits vs. 6 hits for uncachable. No big deal.

Fixed.

Quoted 8 lines

Documentation/x86/pat.txt wants to export a RAM region, it has to do set_memory_uc() or set_memory_wc() · line 122

Quoted 6 lines
Documentation/x86/pat.txt +6 -0
+areas where write-combining is desirable and are restricted by the size
+requirements of MTRRs should consider splitting up their IO memory space
+cleanly with ioremap_uc() and ioremap_wc() followed by an arch_phys_wc_add()
+encompassing both regions. Such use is nevertheless heavily discouraged as
+the effective memory type is considered implementation defined. This strategy
+should only be used as last resort on devices with size-contrained regions

size-constrained

Fixed.

Quoted 24 lines
Quoted 24 lines
Documentation/x86/pat.txt +21 -0
+where otherwise MTRR write-combining would not be effective.
+
+Note that you cannot use set_memory_wc() to override / whitelist IO remapped
+memory space mapped with ioremap*() calls, set_memory_wc() can only be used
+on RAM.
+
+----------------------------------------------------------------------
+MTRR Non-PAT   PAT    Linux ioremap value        Effective memory type
+----------------------------------------------------------------------
+                                                  Non-PAT |  PAT
+     PAT
+     |PCD
+     ||PWT
+     |||
+WC   000      WB      _PAGE_CACHE_MODE_WB            WC   |   WC
+WC   001      WC      _PAGE_CACHE_MODE_WC            WC*  |   WC
+WC   010      UC-     _PAGE_CACHE_MODE_UC_MINUS      WC*  |   WC
+WC   011      UC      _PAGE_CACHE_MODE_UC            UC   |   UC
+----------------------------------------------------------------------
+
+(*) denotes implementation defined and is discouraged
 
 Notes:
 
Quoted 12 lines

arch/x86/kernel/cpu/mtrr/main.c EXPORT_SYMBOL(mtrr_del); · line 541

Quoted 9 lines
arch/x86/kernel/cpu/mtrr/main.c +1 -0
index ea5f363..12abdbe 100644
@@ -538,6 +538,9 @@ EXPORT_SYMBOL(mtrr_del);
  * attempts to add a WC MTRR covering size bytes starting at base and
  * logs an error if this fails.
  *
+ * The caller should expect to need to provide a power of two size on an

* The called should provide a power of two size on an equivalent
* power of two boundary.

Fixed.

Luis

maintainer
#257 lore raw

Re: [PATCH v4 2/6] x86: document WC MTRR effects on PAT / non-PAT pages

In reply to Luis R. Rodriguez
Quoted 46 lines · Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

As part of the effort to phase out MTRR use document write-combining MTRR effects on pages with different non-PAT page attributes flags and different PAT entry values. Extend arch_phys_wc_add() documentation to clarify power of two sizes / boundary requirements as we phase out mtrr_add() use.

Lastly hint towards ioremap_uc() for corner cases on device drivers working with devices with mixed regions where MTRR size requirements would otherwise not enable write-combining effective memory types.

Cc Toshi Kani <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Suresh Siddha <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Antonino Daplas <[email protected]>
Cc Jean-Christophe Plagniol-Villard <[email protected]>
Cc Tomi Valkeinen <[email protected]>
Cc Ville Syrjälä <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Davidlohr Bueso <[email protected]>
---
 Documentation/x86/mtrr.txt      | 18 +++++++++++++++---
 Documentation/x86/pat.txt       | 40 +++++++++++++++++++++++++++++++++++++++-
 arch/x86/kernel/cpu/mtrr/main.c |  3 +++
 3 files changed, 57 insertions(+), 4 deletions(-)
Documentation/x86/mtrr.txt +0 -0
index cc071dc..a111a6c 100644

Documentation/x86/mtrr.txt line 6

Quoted 9 lines
Documentation/x86/mtrr.txt +5 -3
@@ -1,7 +1,19 @@
 MTRR (Memory Type Range Register) control
-3 Jun 1999
-Richard Gooch
-<[email protected]>
+
+Richard Gooch <[email protected]> - 3 Jun 1999
+Luis R. Rodriguez <[email protected]> - April 9, 2015
+
+=======================================> +Phasing MTRR use

"Phasing out...".

Quoted 25 lines
Documentation/x86/mtrr.txt +9 -0
+
+MTRR use is replaced on modern x86 hardware with PAT. Over time the only type
+of effective MTRR that is expected to be supported will be for write-combining.
+As MTRR use is phased out device drivers should use arch_phys_wc_add() to make
+MTRR effective on non-PAT systems while a no-op on PAT enabled systems.
+
+For details refer to Documentation/x86/pat.txt.
+
+=======================================>  
   On Intel P6 family processors (Pentium Pro, Pentium II and later)
   the Memory Type Range Registers (MTRRs) may be used to control
Documentation/x86/pat.txt +2 -0
index cf08c9f..7e183e3 100644
@@ -34,6 +34,8 @@ ioremap                |    --    |    UC-     |       UC-        |
                        |          |            |                  |
 ioremap_cache          |    --    |    WB      |       WB         |
                        |          |            |                  |
+ioremap_uc             |    --    |    UC      |       UC         |
+                       |          |            |                  |
 ioremap_nocache        |    --    |    UC-     |       UC-        |
                        |          |            |                  |
 ioremap_wc             |    --    |    --      |       WC         |

Documentation/x86/pat.txt wants to export a RAM region, it has to do set_memory_uc() or set_memory_wc() · line 112

Quoted 10 lines
Documentation/x86/pat.txt +6 -1
@@ -102,7 +104,43 @@ wants to export a RAM region, it has to do set_memory_uc() or set_memory_wc()
 as step 0 above and also track the usage of those pages and use set_memory_wb()
 before the page is freed to free pool.
 
-
+MTRR effects on PAT / non-PAT systems
+-------------------------------------
+
+The following table provides the effects of using write-combining MTRRs when
+using ioremap*() calls on x86 for both non-PAT and PAT systems. Ideally
+mtrr_add() usage will be phased in favor of arch_phys_wc_add() which will

out

Documentation/x86/pat.txt wants to export a RAM region, it has to do set_memory_uc() or set_memory_wc() · line 114

Quoted 2 lines
Documentation/x86/pat.txt +2 -0
+be a no-op on PAT enabled systems. The region over which a arch_phys_wc_add()
+is made should already have be ioremap'd with write-combining page attributes

, have been ioremapped with WC attributes...

Quoted 49 lines
Documentation/x86/pat.txt +29 -0
+or PAT entries, this can be done by using ioremap_wc() / or respective helpers.
+Devices which combine areas of IO memory desired to remain uncachable with
+areas where write-combining is desirable and are restricted by the size
+requirements of MTRRs should consider splitting up their IO memory space
+cleanly with ioremap_uc() and ioremap_wc() followed by an arch_phys_wc_add()
+encompassing both regions. Such use is nevertheless heavily discouraged as
+the effective memory type is considered implementation defined. This strategy
+should only be used as last resort on devices with size-contrained regions
+where otherwise MTRR write-combining would not be effective.
+
+Note that you cannot use set_memory_wc() to override / whitelist IO remapped
+memory space mapped with ioremap*() calls, set_memory_wc() can only be used
+on RAM.
+
+----------------------------------------------------------------------
+MTRR Non-PAT   PAT    Linux ioremap value        Effective memory type
+----------------------------------------------------------------------
+                                                  Non-PAT |  PAT
+     PAT
+     |PCD
+     ||PWT
+     |||
+WC   000      WB      _PAGE_CACHE_MODE_WB            WC   |   WC
+WC   001      WC      _PAGE_CACHE_MODE_WC            WC*  |   WC
+WC   010      UC-     _PAGE_CACHE_MODE_UC_MINUS      WC*  |   WC
+WC   011      UC      _PAGE_CACHE_MODE_UC            UC   |   UC
+----------------------------------------------------------------------
+
+(*) denotes implementation defined and is discouraged
 
 Notes:
 
arch/x86/kernel/cpu/mtrr/main.c +3 -0
index ea5f363..12abdbe 100644
@@ -538,6 +538,9 @@ EXPORT_SYMBOL(mtrr_del);
  * attempts to add a WC MTRR covering size bytes starting at base and
  * logs an error if this fails.
  *
+ * The caller should expect to need to provide a power of two size on an
+ * equivalent power of two boundary.
+ *
  * Drivers must store the return value to pass to mtrr_del_wc_if_needed,
  * but drivers should not try to interpret that return value.
  */
Signature · 1 line
2.3.2.209.gd67f9d5.dirty
Signature · 5 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#258 lore raw

Re: [PATCH v4 2/6] x86: document WC MTRR effects on PAT / non-PAT pages

Quoted 42 lines · Borislav Petkov
Quoted 41 lines · Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

As part of the effort to phase out MTRR use document write-combining MTRR effects on pages with different non-PAT page attributes flags and different PAT entry values. Extend arch_phys_wc_add() documentation to clarify power of two sizes / boundary requirements as we phase out mtrr_add() use.

Lastly hint towards ioremap_uc() for corner cases on device drivers working with devices with mixed regions where MTRR size requirements would otherwise not enable write-combining effective memory types.

Cc Toshi Kani <[email protected]>
Cc Jonathan Corbet <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Suresh Siddha <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Antonino Daplas <[email protected]>
Cc Jean-Christophe Plagniol-Villard <[email protected]>
Cc Tomi Valkeinen <[email protected]>
Cc Ville Syrjälä <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Davidlohr Bueso <[email protected]>
---
 Documentation/x86/mtrr.txt      | 18 +++++++++++++++---
 Documentation/x86/pat.txt       | 40 +++++++++++++++++++++++++++++++++++++++-
 arch/x86/kernel/cpu/mtrr/main.c |  3 +++
 3 files changed, 57 insertions(+), 4 deletions(-)
Quoted 16 lines
Quoted 5 lines
Documentation/x86/mtrr.txt +0 -0
index cc071dc..a111a6c 100644

Documentation/x86/mtrr.txt line 6

Quoted 9 lines
Documentation/x86/mtrr.txt +5 -3
@@ -1,7 +1,19 @@
 MTRR (Memory Type Range Register) control
-3 Jun 1999
-Richard Gooch
-<[email protected]>
+
+Richard Gooch <[email protected]> - 3 Jun 1999
+Luis R. Rodriguez <[email protected]> - April 9, 2015
+
+=======================================> > +Phasing MTRR use

"Phasing out...".

Fixed all, will send another version.

Luis

#259 lore raw

PATCH v4 3/6 video: fbdev: atyfb: move framebuffer length fudging to helper

In reply to Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

The size of the framebuffer to be used needs to be fudged to account for the different type of devices that are out there. This captures what is required to do well, we'll resuse this later.

This has no functional changes.

Cc Toshi Kani <[email protected]>
Cc Suresh Siddha <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Antonino Daplas <[email protected]>
Cc Jean-Christophe Plagniol-Villard <[email protected]>
Cc Tomi Valkeinen <[email protected]>
Cc Rob Clark <[email protected]>
Cc Mathias Krause <[email protected]>
Cc Andrzej Hajda <[email protected]>
Cc Ville Syrjälä <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Davidlohr Bueso <[email protected]>
---
 drivers/video/fbdev/aty/atyfb_base.c | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)
drivers/video/fbdev/aty/atyfb_base.c +15 -8
index 8789e48..16936bb 100644
@@ -427,6 +427,20 @@ static struct {
 #endif /* CONFIG_FB_ATY_CT */
 };
 
+/*
+ * Last page of 8 MB (4 MB on ISA) aperture is MMIO,
+ * unless the auxiliary register aperture is used.
+ */
+static void aty_fudge_framebuffer_len(struct fb_info *info)
+{
+	struct atyfb_par *par = (struct atyfb_par *) info->par;
+
+	if (!par->aux_start &&
+	    (info->fix.smem_len = 0x800000 ||
+	     (par->bus_type = ISA && info->fix.smem_len = 0x400000)))
+		info->fix.smem_len -= GUI_RESERVE;
+}
+
 static int correct_chipset(struct atyfb_par *par)
 {
 	u8 rev;
@@ -2603,14 +2617,7 @@ static int aty_init(struct fb_info *info)
 	if (par->pll_ops->resume_pll)
 		par->pll_ops->resume_pll(info, &par->pll);
 
-	/*
-	 * Last page of 8 MB (4 MB on ISA) aperture is MMIO,
-	 * unless the auxiliary register aperture is used.
-	 */
-	if (!par->aux_start &&
-	    (info->fix.smem_len = 0x800000 ||
-	     (par->bus_type = ISA && info->fix.smem_len = 0x400000)))
-		info->fix.smem_len -= GUI_RESERVE;
+	aty_fudge_framebuffer_len(info);
 
 	/*
 	 * Disable register access through the linear aperture
Signature · 1 line
2.3.2.209.gd67f9d5.dirty
#260 lore raw

PATCH v4 4/6 video: fbdev: atyfb: clarify ioremap() base and length used

In reply to Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

This has no functional changes, it just adjusts the ioremap() call for the framebuffer to use the same values we later use for the framebuffer, this will make it easier to review the next change.

The size of the framebuffer varies but since this is for PCI we *know* this defaults to 0x800000. atyfb_setup_generic() is *only* used on PCI probe.

Cc Toshi Kani <[email protected]>
Cc Suresh Siddha <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Antonino Daplas <[email protected]>
Cc Jean-Christophe Plagniol-Villard <[email protected]>
Cc Tomi Valkeinen <[email protected]>
Cc Ville Syrjälä <[email protected]>
Cc Rob Clark <[email protected]>
Cc Mathias Krause <[email protected]>
Cc Andrzej Hajda <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Davidlohr Bueso <[email protected]>
---
 drivers/video/fbdev/aty/atyfb_base.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/video/fbdev/aty/atyfb_base.c +3 -1
index 16936bb..8025624 100644
@@ -3489,7 +3489,9 @@ static int atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info,
 
 	/* Map in frame buffer */
 	info->fix.smem_start = addr;
-	info->screen_base = ioremap(addr, 0x800000);
+	info->fix.smem_len = 0x800000;
+
+	info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
 	if (info->screen_base = NULL) {
 		ret = -ENOMEM;
 		goto atyfb_setup_generic_fail;
Signature · 1 line
2.3.2.209.gd67f9d5.dirty
#261 lore raw

PATCH v4 5/6 video: fbdev: atyfb: replace MTRR UC hole with strong UC

In reply to Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

Replace a WC MTRR call followed by a UC MTRR "hole" call with a single WC MTRR call and use strong UC to protect the MMIO region and account for the device's architecture and MTRR size requirements.

The atyfb driver relies on two overlapping MTRRs. It does this to account for the fact that on some devices it has the MMIO region bundled together with the framebuffer on the same PCI BAR and the hardware requirement on MTRRs on both base and size to be powers of two. In the atyfb driver's case in the worst case the PCI BAR is of 16 MiB while the MMIO region is on the last 4 KiB of the same PCI BAR. If we use just one MTRR for WC we can only end up with an 8 MiB or 16 MiB framebuffer. Using a 16 MiB WC framebuffer area is unacceptable since we need the MMIO region to not be write-combined. An 8 MiB WC framebuffer option does not let use quite a bit of framebuffer space, it would reduce the resolution capability of the device considerably. An alternative is to use many MTRRs but on some systems that could mean not having not enough MTRRs to cover the framebuffer. The current driver solution is to issue a 16 MiB WC MTRR followed by a 4 KiB UC MTRR on the last 4 KiB. Its worth mentioning and documenting that the current ioremap*() strategy as well: the first ioremap() is used only for the MMIO region, a second ioremap() call is used for the framebuffer *and* the MMIO region, the MMIO region then ends up mmap'd twice. Two ioremap() calls are used since in some situations the framebuffer actually ends up on a separate auxiliary PCI BAR, but this is not always true, in the worst case the PCI BAR is shared for both MMIO and the framebuffer. By allowing overlapping ioremap() calls the driver enables two types of devices with one simple ioremap() strategy.

For non PAT systems:

As per Intel SDM "11.5.2.1 Selecting Memory Types for Pentium Pro and Pentium II Processors" [0] the effect of a WC MTRR for a region with page attribute settings set to PCD=1, PWT=1 (Linux _PAGE_CACHE_MODE_UC) will render the effective memory type to UC. A WC MTRR for a region with page attribute settings set to PCD=1, PWT=0 (Linux _PAGE_CACHE_MODE_UC_MINUS) will render the effective memory type to WC *but* yet this is considered implementation defined -- that is, "system designers are encouraged to avoid these implementation-defined combinations". A WC MTRR for a region with page attribute settings set to PCD=0, PWT=1 (Linux _PAGE_CACHE_MODE_WC) will render the effective memory type to WC *but* this is also implementation defined. Such is the case for non-PAT systems.

For PAT systems:

As per Intel SDM "11.5.2.2 Selecting Memory Types for Pentium III and More Recent Processor Families" the ffect of a WC MTRR for a region with a PAT entry value of UC will be UC. The effect of a WC MTRR on a region with a PAT entry UC- will be WC. The effect of a WC MTRR on a regoin with PAT entry WC is WC.

This can all be summarized in the following table:

----------------------------------------------------------------------
MTRR Non-PAT PAT Linux ioremap value Effective memory type
----------------------------------------------------------------------

                                                  Non-PAT |  PAT
     PAT
     |PCD
     ||PWT
     |||
WC   000      WB      _PAGE_CACHE_MODE_WB            WC   |   WC
WC   001      WC      _PAGE_CACHE_MODE_WC            WC*  |   WC
WC   010      UC-     _PAGE_CACHE_MODE_UC_MINUS      WC*  |   UC
WC   011      UC      _PAGE_CACHE_MODE_UC            UC   |   UC

----------------------------------------------------------------------

(*) denotes implementation defined

By default Linux today defaults both and ioremap_nocache() to use _PAGE_CACHE_MODE_UC_MINUS. On x86 ioremap() aliases ioremap_nocache(). The preferred value for Linux by may soon change however, the goal is to use _PAGE_CACHE_MODE_UC by default in the future.

We can use ioremap_uc() to set PCD=1, PWT=1 on non-PAT systems and use a PAT value of UC for PAT systems. This will ensure the same settings are in place regardless of what Linux decides to use by default later and to not regress our MTRR strategy since the effective memory type will differ depending on the value used. Using a WC MTRR on such an area will be nullified. This technique can be used to protect the MMIO region in this driver's case and address the restrictions of the device's architecture as well as restrictions set upon us by powers of 2 when using MTRRs.

This allows us to replace the two MTRR calls with a single 16 MiB WC MTRR and use page-attribute settings for non-PAT and PAT entry values for PAT systems to ensure the appropriate effective memory type won't have a write-combined effect on the MMIO region on both non-PAT and PAT systems. The framebuffer area will be sure to get the write-combined effective memory type by white-listing it with ioremap_wc().

We ensure the desired effective memory types are set by:

0) Using one ioremap_uc() for the MMIO region alone. This will set the page attribute settings for the MMIO region to PCD=1, PWT=1 for non-PAT systems while using a strong UC value on PAT systems.

1) Fixing the framebuffer ioremap'd area to exclude the MMIO region and using ioremap_wc() instead to whitelist the area we want for write-combining.

On both cases an implementation defined (as per above table) effective memory type of WC is used for the framebuffer for non-PAT systems.

[0] https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf

Cc Toshi Kani <[email protected]>
Cc Suresh Siddha <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Antonino Daplas <[email protected]>
Cc Jean-Christophe Plagniol-Villard <[email protected]>
Cc Tomi Valkeinen <[email protected]>
Cc Ville Syrjälä <[email protected]>
Cc Rob Clark <[email protected]>
Cc Mathias Krause <[email protected]>
Cc Andrzej Hajda <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Davidlohr Bueso <[email protected]>
---
 drivers/video/fbdev/aty/atyfb.h      |  1 -
 drivers/video/fbdev/aty/atyfb_base.c | 36 ++++++++++++++----------------------
 2 files changed, 14 insertions(+), 23 deletions(-)
drivers/video/fbdev/aty/atyfb.h +0 -1
index 1f39a62..89ec439 100644
@@ -184,7 +184,6 @@ struct atyfb_par {
 	spinlock_t int_lock;
 #ifdef CONFIG_MTRR
 	int mtrr_aper;
-	int mtrr_reg;
 #endif
 	u32 mem_cntl;
 	struct crtc saved_crtc;
drivers/video/fbdev/aty/atyfb_base.c +14 -22
index 8025624..546f5af 100644
@@ -2630,21 +2630,13 @@ static int aty_init(struct fb_info *info)
 
 #ifdef CONFIG_MTRR
 	par->mtrr_aper = -1;
-	par->mtrr_reg = -1;
 	if (!nomtrr) {
-		/* Cover the whole resource. */
+		/*
+		 * Only the ioremap_wc()'d area will get WC here
+		 * since ioremap_uc() was used on the entire PCI BAR.
+		 */
 		par->mtrr_aper = mtrr_add(par->res_start, par->res_size,
 					  MTRR_TYPE_WRCOMB, 1);
-		if (par->mtrr_aper >= 0 && !par->aux_start) {
-			/* Make a hole for mmio. */
-			par->mtrr_reg = mtrr_add(par->res_start + 0x800000 -
-						 GUI_RESERVE, GUI_RESERVE,
-						 MTRR_TYPE_UNCACHABLE, 1);
-			if (par->mtrr_reg < 0) {
-				mtrr_del(par->mtrr_aper, 0, 0);
-				par->mtrr_aper = -1;
-			}
-		}
 	}
 #endif
 
@@ -2776,10 +2768,6 @@ aty_init_exit:
 	par->pll_ops->set_pll(info, &par->saved_pll);
 
 #ifdef CONFIG_MTRR
-	if (par->mtrr_reg >= 0) {
-		mtrr_del(par->mtrr_reg, 0, 0);
-		par->mtrr_reg = -1;
-	}
 	if (par->mtrr_aper >= 0) {
 		mtrr_del(par->mtrr_aper, 0, 0);
 		par->mtrr_aper = -1;
@@ -3466,7 +3454,11 @@ static int atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info,
 	}
 
 	info->fix.mmio_start = raddr;
-	par->ati_regbase = ioremap(info->fix.mmio_start, 0x1000);
+	/*
+	 * By using strong UC we force the MTRR to never have an
+	 * effect on the MMIO region on both non-PAT and PAT systems.
+	 */
+	par->ati_regbase = ioremap_uc(info->fix.mmio_start, 0x1000);
 	if (par->ati_regbase = NULL)
 		return -ENOMEM;
 
@@ -3491,7 +3483,10 @@ static int atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info,
 	info->fix.smem_start = addr;
 	info->fix.smem_len = 0x800000;
 
-	info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+	aty_fudge_framebuffer_len(info);
+
+	info->screen_base = ioremap_wc(info->fix.smem_start,
+				       info->fix.smem_len);
 	if (info->screen_base = NULL) {
 		ret = -ENOMEM;
 		goto atyfb_setup_generic_fail;
@@ -3563,6 +3558,7 @@ static int atyfb_pci_probe(struct pci_dev *pdev,
 		return -ENOMEM;
 	}
 	par = info->par;
+	par->bus_type = PCI;
 	info->fix = atyfb_fix;
 	info->device = &pdev->dev;
 	par->pci_id = pdev->device;
@@ -3732,10 +3728,6 @@ static void atyfb_remove(struct fb_info *info)
 #endif
 
 #ifdef CONFIG_MTRR
-	if (par->mtrr_reg >= 0) {
-		mtrr_del(par->mtrr_reg, 0, 0);
-		par->mtrr_reg = -1;
-	}
 	if (par->mtrr_aper >= 0) {
 		mtrr_del(par->mtrr_aper, 0, 0);
 		par->mtrr_aper = -1;
Signature · 1 line
2.3.2.209.gd67f9d5.dirty
#262 lore raw

PATCH v4 6/6 video: fbdev: atyfb: use arch_phys_wc_add() and ioremap_wc()

In reply to Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

This driver uses strong UC for the MMIO region, and ioremap_wc() for the framebuffer to whitelist for the WC MTRR what can changed to WC. On PAT systems we don't need the MTRR call so just use arch_phys_wc_add() there, this lets us remove all those ifdefs. Lets also be consistent and use ioremap_wc() for ATARI as well.

There are a few motivations for this:

a) Take advantage of PAT when available

b) Help bury MTRR code away, MTRR is architecture specific and on x86 its replaced by PAT

c) Help with the goal of eventually using _PAGE_CACHE_UC over _PAGE_CACHE_UC_MINUS on x86 on ioremap_nocache() (see commit de33c442e titled "x86 PAT: fix performance drop for glx, use UC minus for ioremap(), ioremap_nocache() and pci_mmap_page_range()")

The conversion done is expressed by the following Coccinelle SmPL patch, it additionally required manual intervention to address all the #ifdery and removal of redundant things which arch_phys_wc_add() already addresses such as verbose message about when MTRR fails and doing nothing when we didn't get an MTRR.

@ mtrr_found @
expression index, base, size;
@@

-index = mtrr_add(base, size, MTRR_TYPE_WRCOMB, 1); +index = arch_phys_wc_add(base, size);

@ mtrr_rm depends on mtrr_found @
expression mtrr_found.index, mtrr_found.base, mtrr_found.size; @@

-mtrr_del(index, base, size);
+arch_phys_wc_del(index);

@ mtrr_rm_zero_arg depends on mtrr_found @
expression mtrr_found.index;
@@

-mtrr_del(index, 0, 0);
+arch_phys_wc_del(index);

@ mtrr_rm_fb_info depends on mtrr_found @
struct fb_info *info;
expression mtrr_found.index;
@@

-mtrr_del(index, info->fix.smem_start, info->fix.smem_len); +arch_phys_wc_del(index);

@ ioremap_replace_nocache depends on mtrr_found @
struct fb_info *info;
expression base, size;
@@

-info->screen_base = ioremap_nocache(base, size);
+info->screen_base = ioremap_wc(base, size);

@ ioremap_replace_default depends on mtrr_found @
struct fb_info *info;
expression base, size;
@@

-info->screen_base = ioremap(base, size);
+info->screen_base = ioremap_wc(base, size);

Generated-by Coccinelle SmPL
Cc Toshi Kani <[email protected]>
Cc Suresh Siddha <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Antonino Daplas <[email protected]>
Cc Jean-Christophe Plagniol-Villard <[email protected]>
Cc Tomi Valkeinen <[email protected]>
Cc Ville Syrjälä <[email protected]>
Cc Rob Clark <[email protected]>
Cc Mathias Krause <[email protected]>
Cc Andrzej Hajda <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Davidlohr Bueso <[email protected]>
---
 drivers/video/fbdev/aty/atyfb.h      |  4 +---
 drivers/video/fbdev/aty/atyfb_base.c | 37 +++++++-----------------------------
 2 files changed, 8 insertions(+), 33 deletions(-)
drivers/video/fbdev/aty/atyfb.h +1 -3
index 89ec439..63c4842 100644
@@ -182,9 +182,7 @@ struct atyfb_par {
 	unsigned long irq_flags;
 	unsigned int irq;
 	spinlock_t int_lock;
-#ifdef CONFIG_MTRR
-	int mtrr_aper;
-#endif
+	int wc_cookie;
 	u32 mem_cntl;
 	struct crtc saved_crtc;
 	union aty_pll saved_pll;
drivers/video/fbdev/aty/atyfb_base.c +7 -30
index 546f5af..b75c974 100644
@@ -98,9 +98,6 @@
 #ifdef CONFIG_PMAC_BACKLIGHT
 #include <asm/backlight.h>
 #endif
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
 
 /*
  * Debug flags.
@@ -303,9 +300,6 @@ static struct fb_ops atyfb_ops = {
 };
 
 static bool noaccel;
-#ifdef CONFIG_MTRR
-static bool nomtrr;
-#endif
 static int vram;
 static int pll;
 static int mclk;
@@ -2628,17 +2622,13 @@ static int aty_init(struct fb_info *info)
 		aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) |
 			    BUS_APER_REG_DIS, par);
 
-#ifdef CONFIG_MTRR
-	par->mtrr_aper = -1;
-	if (!nomtrr) {
+	if (!nomtrr)
 		/*
 		 * Only the ioremap_wc()'d area will get WC here
 		 * since ioremap_uc() was used on the entire PCI BAR.
 		 */
-		par->mtrr_aper = mtrr_add(par->res_start, par->res_size,
-					  MTRR_TYPE_WRCOMB, 1);
-	}
-#endif
+		par->wc_cookie = arch_phys_wc_add(par->res_start,
+						  par->res_size);
 
 	info->fbops = &atyfb_ops;
 	info->pseudo_palette = par->pseudo_palette;
@@ -2766,13 +2756,8 @@ aty_init_exit:
 	/* restore video mode */
 	aty_set_crtc(par, &par->saved_crtc);
 	par->pll_ops->set_pll(info, &par->saved_pll);
+	arch_phys_wc_del(par->wc_cookie);
 
-#ifdef CONFIG_MTRR
-	if (par->mtrr_aper >= 0) {
-		mtrr_del(par->mtrr_aper, 0, 0);
-		par->mtrr_aper = -1;
-	}
-#endif
 	return ret;
 }
 
@@ -3660,7 +3645,8 @@ static int __init atyfb_atari_probe(void)
 		 * Map the video memory (physical address given)
 		 * to somewhere in the kernel address space.
 		 */
-		info->screen_base = ioremap(phys_vmembase[m64_num], phys_size[m64_num]);
+		info->screen_base = ioremap_wc(phys_vmembase[m64_num],
+					       phys_size[m64_num]);
 		info->fix.smem_start = (unsigned long)info->screen_base; /* Fake! */
 		par->ati_regbase = ioremap(phys_guiregbase[m64_num], 0x10000) +
 						0xFC00ul;
@@ -3726,13 +3712,8 @@ static void atyfb_remove(struct fb_info *info)
 	if (M64_HAS(MOBIL_BUS))
 		aty_bl_exit(info->bl_dev);
 #endif
+	arch_phys_wc_del(par->wc_cookie);
 
-#ifdef CONFIG_MTRR
-	if (par->mtrr_aper >= 0) {
-		mtrr_del(par->mtrr_aper, 0, 0);
-		par->mtrr_aper = -1;
-	}
-#endif
 #ifndef __sparc__
 	if (par->ati_regbase)
 		iounmap(par->ati_regbase);
@@ -3848,10 +3829,8 @@ static int __init atyfb_setup(char *options)
 	while ((this_opt = strsep(&options, ",")) != NULL) {
 		if (!strncmp(this_opt, "noaccel", 7)) {
 			noaccel = 1;
-#ifdef CONFIG_MTRR
 		} else if (!strncmp(this_opt, "nomtrr", 6)) {
 			nomtrr = 1;
-#endif
 		} else if (!strncmp(this_opt, "vram:", 5))
 			vram = simple_strtoul(this_opt + 5, NULL, 0);
 		else if (!strncmp(this_opt, "pll:", 4))
@@ -4021,7 +4000,5 @@ module_param(comp_sync, int, 0);
 MODULE_PARM_DESC(comp_sync, "Set composite sync signal to low (0) or high (1)");
 module_param(mode, charp, 0);
 MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
-#ifdef CONFIG_MTRR
 module_param(nomtrr, bool, 0);
 MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers");
-#endif
Signature · 1 line
2.3.2.209.gd67f9d5.dirty
#263 lore raw

Re: [PATCH v4 6/6] video: fbdev: atyfb: use arch_phys_wc_add() and ioremap_wc()

Tomi,

the new required ioremap_uc() which was added in the initial patch set here is now merged on linux-next but I just noticed a small issue with this atyfb specific patch, I'll fix that and respin and send to you as v5.

Luis

#264 lore raw

Re: [PATCH v4 6/6] video: fbdev: atyfb: use arch_phys_wc_add() and ioremap_wc()

Quoted 5 lines · Luis R. Rodriguez

Tomi,

the new required ioremap_uc() which was added in the initial patch set here is now merged on linux-next but I just noticed a small issue with this atyfb specific patch, I'll fix that and respin and send to you as v5.

Actually since this series depends on ioremap_uc() and since I need to respin the last patch in this series for atyfb provided I get an Acked-by from you for the fbdev changes do you mind if this goes through the x86 tree as that already has the ioremap_uc() required call? Otherwise we will have one kernel release with that call available but not used, and we'll have to wait for 2 releases before these changes get merged.

Thoughts?

Luis

#265 lore raw

Re: [PATCH v4 0/6] x86: document and address MTRR corner cases

In reply to Luis R. Rodriguez
Quoted 6 lines · Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

This series addresses one commend fix on the table for mtrr_add() effect on the PAT case when UC- is used. Other than that it is the same as v4.

Quoted 7 lines

Luis R. Rodriguez (6):
x86: add ioremap_uc() - force strong UC, PCD=1, PWT=1
x86: document WC MTRR effects on PAT / non-PAT pages
video: fbdev: atyfb: move framebuffer length fudging to helper
video: fbdev: atyfb: clarify ioremap() base and length used
video: fbdev: atyfb: replace MTRR UC hole with strong UC
video: fbdev: atyfb: use arch_phys_wc_add() and ioremap_wc()

Ville,

the x86 patches are in and on their way to the next version of Linux. Can I trouble you for your review of the atyfb driver changes?

Luis

#266 lore raw

Re: [PATCH v4 0/6] x86: document and address MTRR corner cases

Quoted 4 lines · Luis R. Rodriguez

Ville,

the x86 patches are in and on their way to the next version of Linux. Can I trouble you for your review of the atyfb driver changes?

Hey Ville, just a friendly *poke*.

Luis

#267 lore raw

Re: [PATCH v4 0/6] x86: document and address MTRR corner cases

Quoted 7 lines · Luis R. Rodriguez
Quoted 4 lines · Luis R. Rodriguez

Ville,

the x86 patches are in and on their way to the next version of Linux. Can I trouble you for your review of the atyfb driver changes?

Hey Ville, just a friendly *poke*.

Hey, Ville, trying your Intel address, just in case. Full context of the entire series, in case it helps as this happens to be the more complex of the changes in the entire series:

http://lkml.kernel.org/r/CAB=NE6UgtdSoBsA=8+ueYRAZHDnWUSmQAoHhAaefqudBrSY7Zw at mail.gmail.com

Luis

#268 lore raw

Re: [PATCH v4 0/6] x86: document and address MTRR corner cases

Quoted 7 lines · Luis R. Rodriguez
Quoted 6 lines · Luis R. Rodriguez
Quoted 4 lines · Luis R. Rodriguez

Ville,

the x86 patches are in and on their way to the next version of Linux. Can I trouble you for your review of the atyfb driver changes?

Quoted 7 lines
Quoted 1 line

Hey Ville, just a friendly *poke*.

Hey, Ville, trying your Intel address, just in case. Full context of the entire series, in case it helps as this happens to be the more complex of the changes in the entire series:

http://lkml.kernel.org/r/CAB=NE6UgtdSoBsA=8+ueYRAZHDnWUSmQAoHhAaefqudBrSY7Zw@mail.gmail.com

Tomi, Dave, Andy,

Its' been one month now since posting the last unmodified version (other than commit log) of this series [0] and no word or follow up from Ville. The merge window is closing in and other than the PCI changes this would be the last pending series. Can I trouble one of you for your review ? I will note that this series depends on the ioremap_uc() which went in through Ingo's tree and visible on linux-next.

[0] http://lkml.kernel.org/r/[email protected]

Luis
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in Please read the FAQ at http://www.tux.org/lkml/

#269 lore raw

Re: [PATCH v4 0/6] x86: document and address MTRR corner cases

Quoted 11 lines · Luis R. Rodriguez

Tomi, Dave, Andy,

Its' been one month now since posting the last unmodified version (other than commit log) of this series [0] and no word or follow up from Ville. The merge window is closing in and other than the PCI changes this would be the last pending series. Can I trouble one of you for your review ? I will note that this series depends on the ioremap_uc() which went in through Ingo's tree and visible on linux-next.

[0] http://lkml.kernel.org/r/[email protected]

Alright, I'll poke to see if Andrew might take these then. I'll post a new clean series just to be crystal clear as this is a complex set, I admit and it may be worth re-iterating things.

Luis

#270 lore raw

Re: [PATCH v4 0/6] x86: document and address MTRR corner cases

Quoted 11 lines · Luis R. Rodriguez
Quoted 10 lines · Luis R. Rodriguez

Tomi, Dave, Andy,

Its' been one month now since posting the last unmodified version (other than commit log) of this series [0] and no word or follow up from Ville. The merge window is closing in and other than the PCI changes this would be the last pending series. Can I trouble one of you for your review ? I will note that this series depends on the ioremap_uc() which went in through Ingo's tree and visible on linux-next.

Quoted 5 lines
Quoted 1 line

[0] http://lkml.kernel.org/r/[email protected]

Alright, I'll poke to see if Andrew might take these then. I'll post a new clean series just to be crystal clear as this is a complex set, I admit and it may be worth re-iterating things.

No, please send it to us against -tip as the previous patches, I'd like all these changes that materially impact x86 to go through the x86 tree.

I can deal with the generic impact.

Thanks,

Ingo

#271 lore raw

Re: [PATCH v4 0/6] x86: document and address MTRR corner cases

Quoted 14 lines · Ingo Molnar
Quoted 11 lines · Luis R. Rodriguez
Quoted 10 lines · Luis R. Rodriguez

Tomi, Dave, Andy,

Its' been one month now since posting the last unmodified version (other than commit log) of this series [0] and no word or follow up from Ville. The merge window is closing in and other than the PCI changes this would be the last pending series. Can I trouble one of you for your review ? I will note that this series depends on the ioremap_uc() which went in through Ingo's tree and visible on linux-next.

Quoted 8 lines
Quoted 5 lines
Quoted 1 line

[0] http://lkml.kernel.org/r/[email protected]

Alright, I'll poke to see if Andrew might take these then. I'll post a new clean series just to be crystal clear as this is a complex set, I admit and it may be worth re-iterating things.

No, please send it to us against -tip as the previous patches, I'd like all these changes that materially impact x86 to go through the x86 tree.

Oh OK -- Andrew please ignore that atyfb series I sent yesterday to you then.

Quoted 1 line

I can deal with the generic impact.

Great, thanks.

Luis

#272 lore raw

v5 cover x86: address drivers that do not work with PAT

From: "Luis R. Rodriguez" <[email protected]>

This v5 drops the addition of new early_param_*() helpers and their use on pat_enabled as we are sticking with __read_mostly, and as per review this should be selectively used only on well established hot paths. pat_enabled turns out to be a common hot path, so we want to keep that. This v5 also changes the pr_info() patch slightly to address the feedback. The other patches do not change at all.

Luis R. Rodriguez (6):
x86/mm/pat: use pr_info() and friends x86/mm/pat: redefine pat_enabled arch/x86/mm/pat: export pat_enabled()
ivtv: use arch_phys_wc_add() and require PAT disabled IB/ipath: add counting for MTRR
IB/ipath: use arch_phys_wc_add() and require PAT disabled

 arch/x86/include/asm/pat.h                    |  7 +--
 arch/x86/kernel/cpu/mtrr/main.c               |  2 +-
 arch/x86/mm/iomap_32.c                        |  2 +-
 arch/x86/mm/ioremap.c                         |  4 +-
 arch/x86/mm/pageattr.c                        |  2 +-
 arch/x86/mm/pat.c                             | 75 +++++++++++++--------------
 arch/x86/mm/pat_internal.h                    |  2 +-
 arch/x86/mm/pat_rbtree.c                      |  5 +-
 arch/x86/pci/i386.c                           |  6 +--
 drivers/infiniband/hw/ipath/Kconfig           |  3 ++
 drivers/infiniband/hw/ipath/ipath_driver.c    | 18 +++++--
 drivers/infiniband/hw/ipath/ipath_kernel.h    |  4 +-
 drivers/infiniband/hw/ipath/ipath_wc_x86_64.c | 43 ++++-----------
 drivers/media/pci/ivtv/Kconfig                |  3 ++
 drivers/media/pci/ivtv/ivtvfb.c               | 58 ++++++++-------------
 15 files changed, 103 insertions(+), 131 deletions(-)
Signature · 1 line
2.3.2.209.gd67f9d5.dirty
#273 lore raw

PATCH v5 1/6 x86/mm/pat: use pr_info() and friends

From: "Luis R. Rodriguez" <[email protected]>

Use pr_info() instead of the old printk to prefix the component where things are coming from. With this readers will know exactly where the message is coming from. Since pr_fmt is already defined in this case we redefine it to "PAT: ".

We leave the users of dprintk() in place, this will print only when the debugpat kernel parameter is enabled. We want to leave those enabled as a debug feature, but also make them use the same prefix.

Cc Andy Walls <[email protected]>
Cc Doug Ledford <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Michael S. Tsirkin <[email protected]>
---
 arch/x86/mm/pat.c          | 41 +++++++++++++++++++++--------------------
 arch/x86/mm/pat_internal.h |  2 +-
 arch/x86/mm/pat_rbtree.c   |  5 ++++-
 3 files changed, 26 insertions(+), 22 deletions(-)
arch/x86/mm/pat.c +21 -20
index 372ad42..8f88c6a 100644
@@ -33,13 +33,16 @@
 #include "pat_internal.h"
 #include "mm_internal.h"
 
+#undef pr_fmt
+#define pr_fmt(fmt)	"PAT: " fmt
+
 #ifdef CONFIG_X86_PAT
 int __read_mostly pat_enabled = 1;
 
 static inline void pat_disable(const char *reason)
 {
 	pat_enabled = 0;
-	printk(KERN_INFO "%s\n", reason);
+	pr_info("%s\n", reason);
 }
 
 static int __init nopat(char *str)
@@ -211,8 +214,7 @@ void pat_init(void)
 			 * switched to PAT on the boot CPU. We have no way to
 			 * undo PAT.
 			 */
-			printk(KERN_ERR "PAT enabled, "
-			       "but not supported by secondary CPU\n");
+			pr_err("PAT enabled, but not supported by secondary CPU\n");
 			BUG();
 		}
 	}
@@ -451,9 +453,9 @@ int reserve_memtype(u64 start, u64 end, enum page_cache_mode req_type,
 
 	err = rbt_memtype_check_insert(new, new_type);
 	if (err) {
-		printk(KERN_INFO "reserve_memtype failed [mem %#010Lx-%#010Lx], track %s, req %s\n",
-		       start, end - 1,
-		       cattr_name(new->type), cattr_name(req_type));
+		pr_info("reserve_memtype failed [mem %#010Lx-%#010Lx], track %s, req %s\n",
+			start, end - 1,
+			cattr_name(new->type), cattr_name(req_type));
 		kfree(new);
 		spin_unlock(&memtype_lock);
 
@@ -497,8 +499,8 @@ int free_memtype(u64 start, u64 end)
 	spin_unlock(&memtype_lock);
 
 	if (!entry) {
-		printk(KERN_INFO "%s:%d freeing invalid memtype [mem %#010Lx-%#010Lx]\n",
-		       current->comm, current->pid, start, end - 1);
+		pr_info("%s:%d freeing invalid memtype [mem %#010Lx-%#010Lx]\n",
+			current->comm, current->pid, start, end - 1);
 		return -EINVAL;
 	}
 
@@ -628,8 +630,8 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
 
 	while (cursor < to) {
 		if (!devmem_is_allowed(pfn)) {
-			printk(KERN_INFO "Program %s tried to access /dev/mem between [mem %#010Lx-%#010Lx], PAT prevents it\n",
-			       current->comm, from, to - 1);
+			pr_info("Program %s tried to access /dev/mem between [mem %#010Lx-%#010Lx], PAT prevents it\n",
+				current->comm, from, to - 1);
 			return 0;
 		}
 		cursor += PAGE_SIZE;
@@ -698,8 +700,7 @@ int kernel_map_sync_memtype(u64 base, unsigned long size,
 				size;
 
 	if (ioremap_change_attr((unsigned long)__va(base), id_sz, pcm) < 0) {
-		printk(KERN_INFO "%s:%d ioremap_change_attr failed %s "
-			"for [mem %#010Lx-%#010Lx]\n",
+		pr_info("%s:%d ioremap_change_attr failed %s for [mem %#010Lx-%#010Lx]\n",
 			current->comm, current->pid,
 			cattr_name(pcm),
 			base, (unsigned long long)(base + size-1));
@@ -734,7 +735,7 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
 
 		pcm = lookup_memtype(paddr);
 		if (want_pcm != pcm) {
-			printk(KERN_WARNING "%s:%d map pfn RAM range req %s for [mem %#010Lx-%#010Lx], got %s\n",
+			pr_warn("%s:%d map pfn RAM range req %s for [mem %#010Lx-%#010Lx], got %s\n",
 				current->comm, current->pid,
 				cattr_name(want_pcm),
 				(unsigned long long)paddr,
@@ -755,13 +756,13 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
 		if (strict_prot ||
 		    !is_new_memtype_allowed(paddr, size, want_pcm, pcm)) {
 			free_memtype(paddr, paddr + size);
-			printk(KERN_ERR "%s:%d map pfn expected mapping type %s"
-				" for [mem %#010Lx-%#010Lx], got %s\n",
-				current->comm, current->pid,
-				cattr_name(want_pcm),
-				(unsigned long long)paddr,
-				(unsigned long long)(paddr + size - 1),
-				cattr_name(pcm));
+			pr_err("%s:%d map pfn expected mapping type %s"
+			       " for [mem %#010Lx-%#010Lx], got %s\n",
+			       current->comm, current->pid,
+			       cattr_name(want_pcm),
+			       (unsigned long long)paddr,
+			       (unsigned long long)(paddr + size - 1),
+			       cattr_name(pcm));
 			return -EINVAL;
 		}
 		/*
arch/x86/mm/pat_internal.h +1 -1
index f641162..ea7fbf0 100644
@@ -4,7 +4,7 @@
 extern int pat_debug_enable;
 
 #define dprintk(fmt, arg...) \
-	do { if (pat_debug_enable) printk(KERN_INFO fmt, ##arg); } while (0)
+	do { if (pat_debug_enable) pr_info(fmt, ##arg); } while (0)
 
 struct memtype {
 	u64			start;
arch/x86/mm/pat_rbtree.c +4 -1
index 6582adc..374539b 100644
@@ -21,6 +21,9 @@
 
 #include "pat_internal.h"
 
+#undef pr_fmt
+#define pr_fmt(fmt)	"PAT: " fmt
+
 /*
  * The memtype tree keeps track of memory type for specific
  * physical memory areas. Without proper tracking, conflicting memory
@@ -160,7 +163,7 @@ success:
 	return 0;
 
 failure:
-	printk(KERN_INFO "%s:%d conflicting memory types "
+	pr_info("%s:%d conflicting memory types "
 		"%Lx-%Lx %s<->%s\n", current->comm, current->pid, start,
 		end, cattr_name(found_type), cattr_name(match->type));
 	return -EBUSY;
Signature · 1 line
2.3.2.209.gd67f9d5.dirty
#274 lore raw

Re: [PATCH v5 1/6] x86/mm/pat: use pr_info() and friends

Quoted 39 lines · Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

Use pr_info() instead of the old printk to prefix the component where things are coming from. With this readers will know exactly where the message is coming from. Since pr_fmt is already defined in this case we redefine it to "PAT: ".

We leave the users of dprintk() in place, this will print only when the debugpat kernel parameter is enabled. We want to leave those enabled as a debug feature, but also make them use the same prefix.

Cc Andy Walls <[email protected]>
Cc Doug Ledford <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Michael S. Tsirkin <[email protected]>
---
 arch/x86/mm/pat.c          | 41 +++++++++++++++++++++--------------------
 arch/x86/mm/pat_internal.h |  2 +-
 arch/x86/mm/pat_rbtree.c   |  5 ++++-
 3 files changed, 26 insertions(+), 22 deletions(-)
arch/x86/mm/pat.c +0 -0
index 372ad42..8f88c6a 100644

arch/x86/mm/pat.c line 37

Quoted 5 lines
arch/x86/mm/pat.c +2 -0
@@ -33,13 +33,16 @@
 #include "pat_internal.h"
 #include "mm_internal.h"
 
+#undef pr_fmt
+#define pr_fmt(fmt)	"PAT: " fmt

Hmm, ok, so those pr_* helpers with the prefix actually make grepping for the error message not fun. So I take that back about the pr_fmt thing - it is a bad idea.

Instead, we should still use pr_* because they're shorter but simply add the prefix before each message so that you can grep for it.

I went and I did that, see below.

---
From: "Luis R. Rodriguez" <[email protected]>
Date: Thu, 30 Apr 2015 13:25:15 -0700
Subject: [PATCH] x86/mm/pat: Convert to pr_* usage

Use pr_info() instead of the old printk to prefix the component where things are coming from. With this readers will know exactly where the message is coming from. Since pr_fmt is already defined in this case we redefine it to "x86/PAT: ".

We leave the users of dprintk() in place, this will print only when the debugpat kernel parameter is enabled. We want to leave those enabled as a debug feature, but also make them use the same prefix.

Cc Andy Walls <[email protected]>
Cc Doug Ledford <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Michael S. Tsirkin <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc H. Peter Anvin <[email protected]>

Signed-off-by:

---
 arch/x86/mm/pat.c          | 41 +++++++++++++++++++----------------------
 arch/x86/mm/pat_internal.h |  2 +-
 arch/x86/mm/pat_rbtree.c   |  2 +-
 3 files changed, 21 insertions(+), 24 deletions(-)
arch/x86/mm/pat.c +19 -22
index 35af6771a95a..8269c784b61c 100644
@@ -39,7 +39,7 @@ int __read_mostly pat_enabled = 1;
 static inline void pat_disable(const char *reason)
 {
 	pat_enabled = 0;
-	printk(KERN_INFO "%s\n", reason);
+	pr_info("x86/PAT: %s\n", reason);
 }
 
 static int __init nopat(char *str)
@@ -188,7 +188,7 @@ void pat_init_cache_modes(void)
 					   pat_msg + 4 * i);
 		update_cache_mode_entry(i, cache);
 	}
-	pr_info("PAT configuration [0-7]: %s\n", pat_msg);
+	pr_info("x86/PAT: Configuration [0-7]: %s\n", pat_msg);
 }
 
 #define PAT(x, y)	((u64)PAT_ ## y << ((x)*8))
@@ -211,8 +211,7 @@ void pat_init(void)
 			 * switched to PAT on the boot CPU. We have no way to
 			 * undo PAT.
 			 */
-			printk(KERN_ERR "PAT enabled, "
-			       "but not supported by secondary CPU\n");
+			pr_err("x86/PAT: PAT enabled, but not supported by secondary CPU\n");
 			BUG();
 		}
 	}
@@ -347,7 +346,7 @@ static int reserve_ram_pages_type(u64 start, u64 end,
 		page = pfn_to_page(pfn);
 		type = get_page_memtype(page);
 		if (type != -1) {
-			pr_info("reserve_ram_pages_type failed [mem %#010Lx-%#010Lx], track 0x%x, req 0x%x\n",
+			pr_info("x86/PAT: reserve_ram_pages_type failed [mem %#010Lx-%#010Lx], track 0x%x, req 0x%x\n",
 				start, end - 1, type, req_type);
 			if (new_type)
 				*new_type = type;
@@ -451,9 +450,9 @@ int reserve_memtype(u64 start, u64 end, enum page_cache_mode req_type,
 
 	err = rbt_memtype_check_insert(new, new_type);
 	if (err) {
-		printk(KERN_INFO "reserve_memtype failed [mem %#010Lx-%#010Lx], track %s, req %s\n",
-		       start, end - 1,
-		       cattr_name(new->type), cattr_name(req_type));
+		pr_info("x86/PAT: reserve_memtype failed [mem %#010Lx-%#010Lx], track %s, req %s\n",
+			start, end - 1,
+			cattr_name(new->type), cattr_name(req_type));
 		kfree(new);
 		spin_unlock(&memtype_lock);
 
@@ -497,8 +496,8 @@ int free_memtype(u64 start, u64 end)
 	spin_unlock(&memtype_lock);
 
 	if (!entry) {
-		printk(KERN_INFO "%s:%d freeing invalid memtype [mem %#010Lx-%#010Lx]\n",
-		       current->comm, current->pid, start, end - 1);
+		pr_info("x86/PAT: %s:%d freeing invalid memtype [mem %#010Lx-%#010Lx]\n",
+			current->comm, current->pid, start, end - 1);
 		return -EINVAL;
 	}
 
@@ -628,8 +627,8 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
 
 	while (cursor < to) {
 		if (!devmem_is_allowed(pfn)) {
-			printk(KERN_INFO "Program %s tried to access /dev/mem between [mem %#010Lx-%#010Lx], PAT prevents it\n",
-			       current->comm, from, to - 1);
+			pr_info("x86/PAT: Program %s tried to access /dev/mem between [mem %#010Lx-%#010Lx], PAT prevents it\n",
+				current->comm, from, to - 1);
 			return 0;
 		}
 		cursor += PAGE_SIZE;
@@ -698,8 +697,7 @@ int kernel_map_sync_memtype(u64 base, unsigned long size,
 				size;
 
 	if (ioremap_change_attr((unsigned long)__va(base), id_sz, pcm) < 0) {
-		printk(KERN_INFO "%s:%d ioremap_change_attr failed %s "
-			"for [mem %#010Lx-%#010Lx]\n",
+		pr_info("x86/PAT: %s:%d ioremap_change_attr failed %s for [mem %#010Lx-%#010Lx]\n",
 			current->comm, current->pid,
 			cattr_name(pcm),
 			base, (unsigned long long)(base + size-1));
@@ -734,7 +732,7 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
 
 		pcm = lookup_memtype(paddr);
 		if (want_pcm != pcm) {
-			printk(KERN_WARNING "%s:%d map pfn RAM range req %s for [mem %#010Lx-%#010Lx], got %s\n",
+			pr_warn("x86/PAT: %s:%d map pfn RAM range req %s for [mem %#010Lx-%#010Lx], got %s\n",
 				current->comm, current->pid,
 				cattr_name(want_pcm),
 				(unsigned long long)paddr,
@@ -755,13 +753,12 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
 		if (strict_prot ||
 		    !is_new_memtype_allowed(paddr, size, want_pcm, pcm)) {
 			free_memtype(paddr, paddr + size);
-			printk(KERN_ERR "%s:%d map pfn expected mapping type %s"
-				" for [mem %#010Lx-%#010Lx], got %s\n",
-				current->comm, current->pid,
-				cattr_name(want_pcm),
-				(unsigned long long)paddr,
-				(unsigned long long)(paddr + size - 1),
-				cattr_name(pcm));
+			pr_err("x86/PAT: %s:%d map pfn expected mapping type %s for [mem %#010Lx-%#010Lx], got %s\n",
+			       current->comm, current->pid,
+			       cattr_name(want_pcm),
+			       (unsigned long long)paddr,
+			       (unsigned long long)(paddr + size - 1),
+			       cattr_name(pcm));
 			return -EINVAL;
 		}
 		/*
arch/x86/mm/pat_internal.h +1 -1
index f6411620305d..a739bfc40690 100644
@@ -4,7 +4,7 @@
 extern int pat_debug_enable;
 
 #define dprintk(fmt, arg...) \
-	do { if (pat_debug_enable) printk(KERN_INFO fmt, ##arg); } while (0)
+	do { if (pat_debug_enable) pr_info("x86/PAT: " fmt, ##arg); } while (0)
 
 struct memtype {
 	u64			start;
arch/x86/mm/pat_rbtree.c +1 -1
index 6582adcc8bd9..82b8c6aaf260 100644
@@ -160,7 +160,7 @@ success:
 	return 0;
 
 failure:
-	printk(KERN_INFO "%s:%d conflicting memory types "
+	pr_info("x86/PAT: %s:%d conflicting memory types "
 		"%Lx-%Lx %s<->%s\n", current->comm, current->pid, start,
 		end, cattr_name(found_type), cattr_name(match->type));
 	return -EBUSY;
Signature · 8 lines
2.3.5

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#275 lore raw

RE: [PATCH v5 1/6] x86/mm/pat: use pr_info() and friends

In reply to Luis R. Rodriguez
Quoted 5 lines

From: [email protected] [mailto:linux-kernel- [email protected]] On Behalf Of Luis R. Rodriguez
Sent: Thursday, April 30, 2015 3:25 PM
Subject: [PATCH v5 1/6] x86/mm/pat: use pr_info() and friends

...

arch/x86/mm/pat.c static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot, · line 760

Quoted 10 lines
(quoted diff) +0 -1
-			printk(KERN_ERR "%s:%d map pfn expected mapping

type %s"

arch/x86/mm/pat.c +2 -6
-				" for [mem %#010Lx-%#010Lx], got %s\n",
-				current->comm, current->pid,
-				cattr_name(want_pcm),
-				(unsigned long long)paddr,
-				(unsigned long long)(paddr + size - 1),
-				cattr_name(pcm));
+			pr_err("%s:%d map pfn expected mapping type %s"
+			       " for [mem %#010Lx-%#010Lx], got %s\n",

Since the patch joins some other print format strings split across lines (which checkpatch allows), you might want to join this one too.

...

Quoted 1 line
arch/x86/mm/pat_rbtree.c +0 -0

...

arch/x86/mm/pat_rbtree.c success: · line 168

Quoted 5 lines

failure:

arch/x86/mm/pat_rbtree.c +1 -1
-	printk(KERN_INFO "%s:%d conflicting memory types "
+	pr_info("%s:%d conflicting memory types "
 		"%Lx-%Lx %s<->%s\n", current->comm, current->pid, start,
 		end, cattr_name(found_type), cattr_name(match->type));

and that one.

#276 lore raw

Re: [PATCH v5 1/6] x86/mm/pat: use pr_info() and friends

Quoted 23 lines · Robert (Server Storage)
Quoted 5 lines

From: [email protected] [mailto:linux-kernel- [email protected]] On Behalf Of Luis R. Rodriguez
Sent: Thursday, April 30, 2015 3:25 PM
Subject: [PATCH v5 1/6] x86/mm/pat: use pr_info() and friends

...

arch/x86/mm/pat.c static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot, · line 760

Quoted 10 lines
(quoted diff) +0 -1
-			printk(KERN_ERR "%s:%d map pfn expected mapping

type %s"

arch/x86/mm/pat.c +2 -6
-				" for [mem %#010Lx-%#010Lx], got %s\n",
-				current->comm, current->pid,
-				cattr_name(want_pcm),
-				(unsigned long long)paddr,
-				(unsigned long long)(paddr + size - 1),
-				cattr_name(pcm));
+			pr_err("%s:%d map pfn expected mapping type %s"
+			       " for [mem %#010Lx-%#010Lx], got %s\n",

Since the patch joins some other print format strings split across lines (which checkpatch allows), you might want to join this one too.

...

Quoted 1 line
arch/x86/mm/pat_rbtree.c +0 -0

...

Quoted 7 lines

arch/x86/mm/pat_rbtree.c success: · line 168

Quoted 5 lines

failure:

arch/x86/mm/pat_rbtree.c +1 -1
-	printk(KERN_INFO "%s:%d conflicting memory types "
+	pr_info("%s:%d conflicting memory types "
 		"%Lx-%Lx %s<->%s\n", current->comm, current->pid, start,
 		end, cattr_name(found_type), cattr_name(match->type));

and that one.

I have adjusted this.

Boris, would you like a v6 re-spin on this series? Or just this patch, or anthing else? FWIW since I keep having to re-do patches / rebase after a while and the entire kill-mtrr series is large with tons of parts I've set out a tree with all pending mtrr changes. The kill-mtrr-v5-20150514 can be used:

https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux-next.git

When needed I'll just fetch linux-next and rebase --onto that day's origin/master.

Luis

#277 lore raw

PATCH v5 2/6 x86/mm/pat: redefine pat_enabled

In reply to Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

We use pat_enabled on x86 specific code to see if PAT is enabled or not, we however are granting full access to the variable even though readers do not need to set it. If for instance we granted access to it to modules later they then could override the variable setting... no bueno.

This renames pat_enabled under a new static variable __pat_enabled, to see if PAT is enabled / disabled folks can just use pat_enabled() now. Code that sets this can only be internal to pat.c. Apart from the early kernel parameter "nopat" to disable PAT we also have a few cases that disable it later and make use of a helper pat_disable(), this helper is wrapped under an ifdef but since that code cannot run unless PAT was enabled its not required to wrap it with ifdefs, unwrap that. Likewise since "nopat" doesn't really change non-PAT systems just remove that ifdef as well.

Although we could add and use an early_param_off() these helpers don't use __read_mostly and we want to keep __read_mostly for __pat_enabled as this is a hot path -- upon boot for instance a simple guest may see ~4k accesses to pat_enabled(). Since __read_mostly early boot params are not that common we don't add a helper for them just yet.

Cc Borislav Petkov <[email protected]>
Cc Christoph Lameter <[email protected]>
Cc Kyle McMartin <[email protected]>
Cc Andy Walls <[email protected]>
Cc Doug Ledford <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Michael S. Tsirkin <[email protected]>
---
 arch/x86/include/asm/pat.h      |  7 +------
 arch/x86/kernel/cpu/mtrr/main.c |  2 +-
 arch/x86/mm/iomap_32.c          |  2 +-
 arch/x86/mm/ioremap.c           |  4 ++--
 arch/x86/mm/pageattr.c          |  2 +-
 arch/x86/mm/pat.c               | 33 +++++++++++++++------------------
 arch/x86/pci/i386.c             |  6 +++---
 7 files changed, 24 insertions(+), 32 deletions(-)
arch/x86/include/asm/pat.h +1 -6
index 91bc4ba..cdcff7f 100644
@@ -4,12 +4,7 @@
 #include <linux/types.h>
 #include <asm/pgtable_types.h>
 
-#ifdef CONFIG_X86_PAT
-extern int pat_enabled;
-#else
-static const int pat_enabled;
-#endif
-
+bool pat_enabled(void);
 extern void pat_init(void);
 void pat_init_cache_modes(void);
 
arch/x86/kernel/cpu/mtrr/main.c +1 -1
index bfef424..f094d36 100644
@@ -556,7 +556,7 @@ int arch_phys_wc_add(unsigned long base, unsigned long size)
 {
 	int ret;
 
-	if (pat_enabled || !mtrr_enabled)
+	if (pat_enabled() || !mtrr_enabled)
 		return 0;  /* Success!  (We don't need to do anything.) */
 
 	ret = mtrr_add(base, size, MTRR_TYPE_WRCOMB, true);
arch/x86/mm/iomap_32.c +1 -1
index 9ca35fc..3a2ec87 100644
@@ -82,7 +82,7 @@ iomap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot)
 	 * MTRR is UC or WC.  UC_MINUS gets the real intention, of the
 	 * user, which is "WC if the MTRR is WC, UC if you can't do that."
 	 */
-	if (!pat_enabled && pgprot_val(prot) ==
+	if (!pat_enabled() && pgprot_val(prot) ==
 	    (__PAGE_KERNEL | cachemode2protval(_PAGE_CACHE_MODE_WC)))
 		prot = __pgprot(__PAGE_KERNEL |
 				cachemode2protval(_PAGE_CACHE_MODE_UC_MINUS));
arch/x86/mm/ioremap.c +2 -2
index a493bb8..82d63ed 100644
@@ -234,7 +234,7 @@ void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
 {
 	/*
 	 * Ideally, this should be:
-	 *	pat_enabled ? _PAGE_CACHE_MODE_UC : _PAGE_CACHE_MODE_UC_MINUS;
+	 *	pat_enabled() ? _PAGE_CACHE_MODE_UC : _PAGE_CACHE_MODE_UC_MINUS;
 	 *
 	 * Till we fix all X drivers to use ioremap_wc(), we will use
 	 * UC MINUS. Drivers that are certain they need or can already
@@ -292,7 +292,7 @@ EXPORT_SYMBOL_GPL(ioremap_uc);
  */
 void __iomem *ioremap_wc(resource_size_t phys_addr, unsigned long size)
 {
-	if (pat_enabled)
+	if (pat_enabled())
 		return __ioremap_caller(phys_addr, size, _PAGE_CACHE_MODE_WC,
 					__builtin_return_address(0));
 	else
arch/x86/mm/pageattr.c +1 -1
index 49660c0..0aa8dd8 100644
@@ -1574,7 +1574,7 @@ int set_memory_wc(unsigned long addr, int numpages)
 {
 	int ret;
 
-	if (!pat_enabled)
+	if (!pat_enabled())
 		return set_memory_uc(addr, numpages);
 
 	ret = reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
arch/x86/mm/pat.c +15 -18
index 8f88c6a..f64785e 100644
@@ -36,12 +36,11 @@
 #undef pr_fmt
 #define pr_fmt(fmt)	"PAT: " fmt
 
-#ifdef CONFIG_X86_PAT
-int __read_mostly pat_enabled = 1;
+static int __read_mostly __pat_enabled = IS_ENABLED(CONFIG_X86_PAT);
 
 static inline void pat_disable(const char *reason)
 {
-	pat_enabled = 0;
+	__pat_enabled = false;
 	pr_info("%s\n", reason);
 }
 
@@ -51,13 +50,11 @@ static int __init nopat(char *str)
 	return 0;
 }
 early_param("nopat", nopat);
-#else
-static inline void pat_disable(const char *reason)
+
+bool pat_enabled(void)
 {
-	(void)reason;
+	return !!__pat_enabled;
 }
-#endif
-
 
 int pat_debug_enable;
 
@@ -201,7 +198,7 @@ void pat_init(void)
 	u64 pat;
 	bool boot_cpu = !boot_pat_state;
 
-	if (!pat_enabled)
+	if (!pat_enabled())
 		return;
 
 	if (!cpu_has_pat) {
@@ -402,7 +399,7 @@ int reserve_memtype(u64 start, u64 end, enum page_cache_mode req_type,
 
 	BUG_ON(start >= end); /* end is exclusive */
 
-	if (!pat_enabled) {
+	if (!pat_enabled()) {
 		/* This is identical to page table setting without PAT */
 		if (new_type) {
 			if (req_type == _PAGE_CACHE_MODE_WC)
@@ -477,7 +474,7 @@ int free_memtype(u64 start, u64 end)
 	int is_range_ram;
 	struct memtype *entry;
 
-	if (!pat_enabled)
+	if (!pat_enabled())
 		return 0;
 
 	/* Low ISA region is always mapped WB. No need to track */
@@ -625,7 +622,7 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
 	u64 to = from + size;
 	u64 cursor = from;
 
-	if (!pat_enabled)
+	if (!pat_enabled())
 		return 1;
 
 	while (cursor < to) {
@@ -661,7 +658,7 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
 	 * caching for the high addresses through the KEN pin, but
 	 * we maintain the tradition of paranoia in this code.
 	 */
-	if (!pat_enabled &&
+	if (!pat_enabled() &&
 	    !(boot_cpu_has(X86_FEATURE_MTRR) ||
 	      boot_cpu_has(X86_FEATURE_K6_MTRR) ||
 	      boot_cpu_has(X86_FEATURE_CYRIX_ARR) ||
@@ -730,7 +727,7 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
 	 * the type requested matches the type of first page in the range.
 	 */
 	if (is_ram) {
-		if (!pat_enabled)
+		if (!pat_enabled())
 			return 0;
 
 		pcm = lookup_memtype(paddr);
@@ -845,7 +842,7 @@ int track_pfn_remap(struct vm_area_struct *vma, pgprot_t *prot,
 		return ret;
 	}
 
-	if (!pat_enabled)
+	if (!pat_enabled())
 		return 0;
 
 	/*
@@ -873,7 +870,7 @@ int track_pfn_insert(struct vm_area_struct *vma, pgprot_t *prot,
 {
 	enum page_cache_mode pcm;
 
-	if (!pat_enabled)
+	if (!pat_enabled())
 		return 0;
 
 	/* Set prot based on lookup */
@@ -914,7 +911,7 @@ void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn,
 
 pgprot_t pgprot_writecombine(pgprot_t prot)
 {
-	if (pat_enabled)
+	if (pat_enabled())
 		return __pgprot(pgprot_val(prot) |
 				cachemode2protval(_PAGE_CACHE_MODE_WC));
 	else
@@ -997,7 +994,7 @@ static const struct file_operations memtype_fops = {
 
 static int __init pat_memtype_list_init(void)
 {
-	if (pat_enabled) {
+	if (pat_enabled()) {
 		debugfs_create_file("pat_memtype_list", S_IRUSR,
 				    arch_debugfs_dir, NULL, &memtype_fops);
 	}
arch/x86/pci/i386.c +3 -3
index 349c0d3..0a9f2ca 100644
@@ -429,12 +429,12 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
  	 * Caller can followup with UC MINUS request and add a WC mtrr if there
  	 * is a free mtrr slot.
  	 */
-	if (!pat_enabled && write_combine)
+	if (!pat_enabled() && write_combine)
 		return -EINVAL;
 
-	if (pat_enabled && write_combine)
+	if (pat_enabled() && write_combine)
 		prot |= cachemode2protval(_PAGE_CACHE_MODE_WC);
-	else if (pat_enabled || boot_cpu_data.x86 > 3)
+	else if (pat_enabled() || boot_cpu_data.x86 > 3)
 		/*
 		 * ioremap() and ioremap_nocache() defaults to UC MINUS for now.
 		 * To avoid attribute conflicts, request UC MINUS here
Signature · 1 line
2.3.2.209.gd67f9d5.dirty
#278 lore raw

Re: [PATCH v5 2/6] x86/mm/pat: redefine pat_enabled

arch/x86/kernel/cpu/mtrr/main.c int arch_phys_wc_add(unsigned long base, unsigned long size) · line 559

Quoted 10 lines · Luis R. Rodriguez
arch/x86/kernel/cpu/mtrr/main.c +1 -1
index bfef424..f094d36 100644
@@ -556,7 +556,7 @@ int arch_phys_wc_add(unsigned long base, unsigned long size)
 {
 	int ret;
 
-	if (pat_enabled || !mtrr_enabled)
+	if (pat_enabled() || !mtrr_enabled)

What's going on here? I got a reject about mtrr_enabled which is nowhere to be found. Am I missing a patch?

Anyway, I applied that:

---
From: "Luis R. Rodriguez" <[email protected]>
Date: Thu, 30 Apr 2015 13:25:16 -0700
Subject: [PATCH] x86/mm/pat: Redefine pat_enabled

We use pat_enabled in x86 specific code to see if PAT is enabled or not, we however are granting full access to the variable even though readers do not need to set it. If for instance we granted access to it to modules later they then could override the variable setting... no bueno.

This renames pat_enabled to a new static variable __pat_enabled. To see if PAT is enabled / disabled folks can just use the nice accessor pat_enabled() now.

Code that sets this can only be internal to pat.c. Apart from the early kernel parameter "nopat" to disable PAT we also have a few cases that disable it later and make use of a helper pat_disable(), this helper is wrapped under an ifdef but since that code cannot run unless PAT was enabled its not required to wrap it with ifdefs, unwrap that. Likewise since "nopat" doesn't really change non-PAT systems just remove that ifdef as well.

Although we could add and use an early_param_off() these helpers don't use __read_mostly and we want to keep __read_mostly for __pat_enabled as this is a hot path -- upon boot for instance a simple guest may see ~4k accesses to pat_enabled(). Since __read_mostly early boot params are not that common we don't add a helper for them just yet.

Cc Christoph Lameter <[email protected]>
Cc Kyle McMartin <[email protected]>
Cc Andy Walls <[email protected]>
Cc Doug Ledford <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Michael S. Tsirkin <[email protected]>

Signed-off-by:

---
 arch/x86/include/asm/pat.h      |  7 +------
 arch/x86/kernel/cpu/mtrr/main.c |  2 +-
 arch/x86/mm/iomap_32.c          |  2 +-
 arch/x86/mm/ioremap.c           |  4 ++--
 arch/x86/mm/pageattr.c          |  2 +-
 arch/x86/mm/pat.c               | 33 +++++++++++++++------------------
 arch/x86/pci/i386.c             |  6 +++---
 7 files changed, 24 insertions(+), 32 deletions(-)
arch/x86/include/asm/pat.h +1 -6
index 91bc4ba95f91..cdcff7f7f694 100644
@@ -4,12 +4,7 @@
 #include <linux/types.h>
 #include <asm/pgtable_types.h>
 
-#ifdef CONFIG_X86_PAT
-extern int pat_enabled;
-#else
-static const int pat_enabled;
-#endif
-
+bool pat_enabled(void);
 extern void pat_init(void);
 void pat_init_cache_modes(void);
 
arch/x86/kernel/cpu/mtrr/main.c +1 -1
index ea5f363a1948..96fa7b38af5e 100644
@@ -545,7 +545,7 @@ int arch_phys_wc_add(unsigned long base, unsigned long size)
 {
 	int ret;
 
-	if (pat_enabled)
+	if (pat_enabled())
 		return 0;  /* Success!  (We don't need to do anything.) */
 
 	ret = mtrr_add(base, size, MTRR_TYPE_WRCOMB, true);
arch/x86/mm/iomap_32.c +1 -1
index 9ca35fc60cfe..3a2ec8790ca7 100644
@@ -82,7 +82,7 @@ iomap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot)
 	 * MTRR is UC or WC.  UC_MINUS gets the real intention, of the
 	 * user, which is "WC if the MTRR is WC, UC if you can't do that."
 	 */
-	if (!pat_enabled && pgprot_val(prot) ==
+	if (!pat_enabled() && pgprot_val(prot) ==
 	    (__PAGE_KERNEL | cachemode2protval(_PAGE_CACHE_MODE_WC)))
 		prot = __pgprot(__PAGE_KERNEL |
 				cachemode2protval(_PAGE_CACHE_MODE_UC_MINUS));
arch/x86/mm/ioremap.c +2 -2
index fc08431a387b..ea379c06cc4c 100644
@@ -234,7 +234,7 @@ void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
 {
 	/*
 	 * Ideally, this should be:
-	 *	pat_enabled ? _PAGE_CACHE_MODE_UC : _PAGE_CACHE_MODE_UC_MINUS;
+	 *	pat_enabled() ? _PAGE_CACHE_MODE_UC : _PAGE_CACHE_MODE_UC_MINUS;
 	 *
 	 * Till we fix all X drivers to use ioremap_wc(), we will use
 	 * UC MINUS. Drivers that are certain they need or can already
@@ -292,7 +292,7 @@ EXPORT_SYMBOL_GPL(ioremap_uc);
  */
 void __iomem *ioremap_wc(resource_size_t phys_addr, unsigned long size)
 {
-	if (pat_enabled)
+	if (pat_enabled())
 		return __ioremap_caller(phys_addr, size, _PAGE_CACHE_MODE_WC,
 					__builtin_return_address(0));
 	else
arch/x86/mm/pageattr.c +1 -1
index d35148acdc05..e07686633ce4 100644
@@ -1573,7 +1573,7 @@ int set_memory_wc(unsigned long addr, int numpages)
 {
 	int ret;
 
-	if (!pat_enabled)
+	if (!pat_enabled())
 		return set_memory_uc(addr, numpages);
 
 	ret = reserve_memtype(__pa(addr), __pa(addr) + numpages * PAGE_SIZE,
arch/x86/mm/pat.c +15 -18
index 8269c784b61c..6e05a071ffc8 100644
@@ -33,12 +33,11 @@
 #include "pat_internal.h"
 #include "mm_internal.h"
 
-#ifdef CONFIG_X86_PAT
-int __read_mostly pat_enabled = 1;
+static int __read_mostly __pat_enabled = IS_ENABLED(CONFIG_X86_PAT);
 
 static inline void pat_disable(const char *reason)
 {
-	pat_enabled = 0;
+	__pat_enabled = 0;
 	pr_info("x86/PAT: %s\n", reason);
 }
 
@@ -48,13 +47,11 @@ static int __init nopat(char *str)
 	return 0;
 }
 early_param("nopat", nopat);
-#else
-static inline void pat_disable(const char *reason)
+
+bool pat_enabled(void)
 {
-	(void)reason;
+	return !!__pat_enabled;
 }
-#endif
-
 
 int pat_debug_enable;
 
@@ -198,7 +195,7 @@ void pat_init(void)
 	u64 pat;
 	bool boot_cpu = !boot_pat_state;
 
-	if (!pat_enabled)
+	if (!pat_enabled())
 		return;
 
 	if (!cpu_has_pat) {
@@ -399,7 +396,7 @@ int reserve_memtype(u64 start, u64 end, enum page_cache_mode req_type,
 
 	BUG_ON(start >= end); /* end is exclusive */
 
-	if (!pat_enabled) {
+	if (!pat_enabled()) {
 		/* This is identical to page table setting without PAT */
 		if (new_type) {
 			if (req_type == _PAGE_CACHE_MODE_WC)
@@ -474,7 +471,7 @@ int free_memtype(u64 start, u64 end)
 	int is_range_ram;
 	struct memtype *entry;
 
-	if (!pat_enabled)
+	if (!pat_enabled())
 		return 0;
 
 	/* Low ISA region is always mapped WB. No need to track */
@@ -622,7 +619,7 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size)
 	u64 to = from + size;
 	u64 cursor = from;
 
-	if (!pat_enabled)
+	if (!pat_enabled())
 		return 1;
 
 	while (cursor < to) {
@@ -658,7 +655,7 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
 	 * caching for the high addresses through the KEN pin, but
 	 * we maintain the tradition of paranoia in this code.
 	 */
-	if (!pat_enabled &&
+	if (!pat_enabled() &&
 	    !(boot_cpu_has(X86_FEATURE_MTRR) ||
 	      boot_cpu_has(X86_FEATURE_K6_MTRR) ||
 	      boot_cpu_has(X86_FEATURE_CYRIX_ARR) ||
@@ -727,7 +724,7 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
 	 * the type requested matches the type of first page in the range.
 	 */
 	if (is_ram) {
-		if (!pat_enabled)
+		if (!pat_enabled())
 			return 0;
 
 		pcm = lookup_memtype(paddr);
@@ -841,7 +838,7 @@ int track_pfn_remap(struct vm_area_struct *vma, pgprot_t *prot,
 		return ret;
 	}
 
-	if (!pat_enabled)
+	if (!pat_enabled())
 		return 0;
 
 	/*
@@ -869,7 +866,7 @@ int track_pfn_insert(struct vm_area_struct *vma, pgprot_t *prot,
 {
 	enum page_cache_mode pcm;
 
-	if (!pat_enabled)
+	if (!pat_enabled())
 		return 0;
 
 	/* Set prot based on lookup */
@@ -910,7 +907,7 @@ void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn,
 
 pgprot_t pgprot_writecombine(pgprot_t prot)
 {
-	if (pat_enabled)
+	if (pat_enabled())
 		return __pgprot(pgprot_val(prot) |
 				cachemode2protval(_PAGE_CACHE_MODE_WC));
 	else
@@ -993,7 +990,7 @@ static const struct file_operations memtype_fops = {
 
 static int __init pat_memtype_list_init(void)
 {
-	if (pat_enabled) {
+	if (pat_enabled()) {
 		debugfs_create_file("pat_memtype_list", S_IRUSR,
 				    arch_debugfs_dir, NULL, &memtype_fops);
 	}
arch/x86/pci/i386.c +3 -3
index 349c0d32cc0b..0a9f2caf358f 100644
@@ -429,12 +429,12 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
  	 * Caller can followup with UC MINUS request and add a WC mtrr if there
  	 * is a free mtrr slot.
  	 */
-	if (!pat_enabled && write_combine)
+	if (!pat_enabled() && write_combine)
 		return -EINVAL;
 
-	if (pat_enabled && write_combine)
+	if (pat_enabled() && write_combine)
 		prot |= cachemode2protval(_PAGE_CACHE_MODE_WC);
-	else if (pat_enabled || boot_cpu_data.x86 > 3)
+	else if (pat_enabled() || boot_cpu_data.x86 > 3)
 		/*
 		 * ioremap() and ioremap_nocache() defaults to UC MINUS for now.
 		 * To avoid attribute conflicts, request UC MINUS here
Signature · 8 lines
2.3.5

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#279 lore raw

Re: [PATCH v5 2/6] x86/mm/pat: redefine pat_enabled

Quoted 9 lines · Borislav Petkov
Quoted 8 lines · Luis R. Rodriguez
arch/x86/kernel/cpu/mtrr/main.c +0 -0
index bfef424..f094d36 100644
@@ -556,7 +556,7 @@ int arch_phys_wc_add(unsigned long base, unsigned long size)
 {
 	int ret;
 
Quoted 5 lines

arch/x86/kernel/cpu/mtrr/main.c int arch_phys_wc_add(unsigned long base, unsigned long size) · line 559

Quoted 2 lines
arch/x86/kernel/cpu/mtrr/main.c +1 -1
-	if (pat_enabled || !mtrr_enabled)
+	if (pat_enabled() || !mtrr_enabled)

What's going on here? I got a reject about mtrr_enabled which is nowhere to be found. Am I missing a patch?

Yes, the patch titled, "x86: mtrr: generalize run time disabling of MTRR" should be applied first, or ammended to fit the new style. Let me know what you prefer.

Quoted 1 line

Anyway, I applied that:

Great, thanks, is there a tree I can use to rebase / fetch ?

Luis

#280 lore raw

PATCH v5 3/6 arch/x86/mm/pat: export pat_enabled()

In reply to Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

Two Linux device drivers cannot work with PAT and the work required to make them work is significant. There is not enough motivation to convert these drivers over to use PAT properly, the compromise reached is to let drivers that cannot be ported to PAT check if PAT was enabled and if so fail on probe with a recommendation to boot with the "nopat" kernel parameter.

Cc Andy Walls <[email protected]>
Cc Doug Ledford <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Michael S. Tsirkin <[email protected]>
---
 arch/x86/mm/pat.c | 1 +
 1 file changed, 1 insertion(+)
arch/x86/mm/pat.c +1 -0
index f64785e..3d60207 100644
@@ -55,6 +55,7 @@ bool pat_enabled(void)
 {
 	return !!__pat_enabled;
 }
+EXPORT_SYMBOL_GPL(pat_enabled);
 
 int pat_debug_enable;
 
Signature · 1 line
2.3.2.209.gd67f9d5.dirty
#281 lore raw

Re: [PATCH v5 3/6] arch/x86/mm/pat: export pat_enabled()

Quoted 24 lines · Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

Two Linux device drivers cannot work with PAT and the work required to make them work is significant. There is not enough motivation to convert these drivers over to use PAT properly, the compromise reached is to let drivers that cannot be ported to PAT check if PAT was enabled and if so fail on probe with a recommendation to boot with the "nopat" kernel parameter.

Cc Andy Walls <[email protected]>
Cc Doug Ledford <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Michael S. Tsirkin <[email protected]>
Quoted 3 lines
---
 arch/x86/mm/pat.c | 1 +
 1 file changed, 1 insertion(+)

Applied, thanks.

Signature · 5 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#282 lore raw

PATCH v5 4/6 ivtv: use arch_phys_wc_add() and require PAT disabled

In reply to Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

We are burrying direct access to MTRR code support on x86 in order to take advantage of PAT. In the future we also want to make the default behaviour of ioremap_nocache() to use strong UC, use of mtrr_add() on those systems would make write-combining void.

In order to help both enable us to later make strong UC default and in order to phase out direct MTRR access code port the driver over to arch_phys_wc_add() and annotate that the device driver requires systems to boot with PAT disabled, with the nopat kernel parameter.

This is a worthy comprmise given that the hardware is really rare these days, and perhaps only some lost souls in some third world country are expected to be using this feature of the device driver.

Cc Andy Walls <[email protected]>
Cc Doug Ledford <[email protected]>
Cc Mauro Carvalho Chehab <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Suresh Siddha <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Antonino Daplas <[email protected]>
Cc Jean-Christophe Plagniol-Villard <[email protected]>
Cc Tomi Valkeinen <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Arnd Bergmann <[email protected]>
Cc Michael S. Tsirkin <[email protected]>
Cc Stefan Bader <[email protected]>
Cc Ville Syrjälä <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Davidlohr Bueso <[email protected]>
Cc Roger Pau Monné <[email protected]>
---
 drivers/media/pci/ivtv/Kconfig  |  3 +++
 drivers/media/pci/ivtv/ivtvfb.c | 58 ++++++++++++++++-------------------------
 2 files changed, 26 insertions(+), 35 deletions(-)
drivers/media/pci/ivtv/Kconfig +3 -0
index dd6ee57e..b2a7f88 100644
@@ -57,5 +57,8 @@ config VIDEO_FB_IVTV
 	  This is used in the Hauppauge PVR-350 card. There is a driver
 	  homepage at <http://www.ivtvdriver.org>.
 
+	  If you have this hardware you will need to boot with PAT disabled
+	  on your x86 systems, use the nopat kernel parameter.
+
 	  To compile this driver as a module, choose M here: the
 	  module will be called ivtvfb.
drivers/media/pci/ivtv/ivtvfb.c +23 -35

98 lines not on this page · raw message

Signature · 1 line
2.3.2.209.gd67f9d5.dirty
#283 lore raw

PATCH v5 5/6 IB/ipath: add counting for MTRR

In reply to Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

There is no good reason not to, we eventually delete it as well.

Cc Toshi Kani <[email protected]>
Cc Roland Dreier <[email protected]>
Cc Sean Hefty <[email protected]>
Cc Hal Rosenstock <[email protected]>
Cc Suresh Siddha <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Antonino Daplas <[email protected]>
Cc Jean-Christophe Plagniol-Villard <[email protected]>
Cc Tomi Valkeinen <[email protected]>
---
 drivers/infiniband/hw/ipath/ipath_wc_x86_64.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/hw/ipath/ipath_wc_x86_64.c +1 -1
index 4ad0b93..70c1f3a 100644
@@ -127,7 +127,7 @@ int ipath_enable_wc(struct ipath_devdata *dd)
 			   "(addr %llx, len=0x%llx)\n",
 			   (unsigned long long) pioaddr,
 			   (unsigned long long) piolen);
-		cookie = mtrr_add(pioaddr, piolen, MTRR_TYPE_WRCOMB, 0);
+		cookie = mtrr_add(pioaddr, piolen, MTRR_TYPE_WRCOMB, 1);
 		if (cookie < 0) {
 			{
 				dev_info(&dd->pcidev->dev,
Signature · 1 line
2.3.2.209.gd67f9d5.dirty
#284 lore raw

PATCH v5 6/6 IB/ipath: use arch_phys_wc_add() and require PAT disabled

In reply to Luis R. Rodriguez

From: "Luis R. Rodriguez" <[email protected]>

We are burrying direct access to MTRR code support on x86 in order to take advantage of PAT. In the future we also want to make the default behaviour of ioremap_nocache() to use strong UC, use of mtrr_add() on those systems would make write-combining void.

In order to help both enable us to later make strong UC default and in order to phase out direct MTRR access code port the driver over to arch_phys_wc_add() and annotate that the device driver requires systems to boot with PAT disabled, with the nopat kernel parameter.

This is a worthy compromise given that the ipath device driver powers the old HTX bus cards that only work in AMD systems, while the newer IB/qib device driver powers all PCI-e cards. The ipath device driver is obsolete, hardware hard to find and because of this this its a reasonable compromise to make to require users of ipath to boot with nopat.

Cc Doug Ledford <[email protected]>
Cc Andy Walls <[email protected]>
Cc Hal Rosenstock <[email protected]>
Cc Sean Hefty <[email protected]>
Cc Suresh Siddha <[email protected]>
Cc Rickard Strandqvist <[email protected]>
Cc Mike Marciniszyn <[email protected]>
Cc Roland Dreier <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Antonino Daplas <[email protected]>
Cc Jean-Christophe Plagniol-Villard <[email protected]>
Cc Tomi Valkeinen <[email protected]>
Cc Ville Syrjälä <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Davidlohr Bueso <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Arnd Bergmann <[email protected]>
Cc Michael S. Tsirkin <[email protected]>
Cc Stefan Bader <[email protected]>
Cc Roger Pau Monné <[email protected]>
---
 drivers/infiniband/hw/ipath/Kconfig           |  3 ++
 drivers/infiniband/hw/ipath/ipath_driver.c    | 18 +++++++----
 drivers/infiniband/hw/ipath/ipath_kernel.h    |  4 +--
 drivers/infiniband/hw/ipath/ipath_wc_x86_64.c | 43 ++++++---------------------
 4 files changed, 26 insertions(+), 42 deletions(-)
drivers/infiniband/hw/ipath/Kconfig +3 -0
index 1d9bb11..8fe54ff 100644
@@ -9,3 +9,6 @@ config INFINIBAND_IPATH
 	as IP-over-InfiniBand as well as with userspace applications
 	(in conjunction with InfiniBand userspace access).
 	For QLogic PCIe QLE based cards, use the QIB driver instead.
+
+	If you have this hardware you will need to boot with PAT disabled
+	on your x86-64 systems, use the nopat kernel parameter.
drivers/infiniband/hw/ipath/ipath_driver.c +13 -5
index bd0caed..441cfe5 100644
@@ -42,6 +42,9 @@
 #include <linux/bitmap.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#ifdef CONFIG_X86_64
+#include <asm/pat.h>
+#endif
 
 #include "ipath_kernel.h"
 #include "ipath_verbs.h"
@@ -395,6 +398,14 @@ static int ipath_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	unsigned long long addr;
 	u32 bar0 = 0, bar1 = 0;
 
+#ifdef CONFIG_X86_64
+	if (WARN(pat_enabled(),
+		 "ipath needs PAT disabled, boot with nopat kernel parameter\n")) {
+		ret = EINVAL;
+		goto bail;
+	}
+#endif
+
 	dd = ipath_alloc_devdata(pdev);
 	if (IS_ERR(dd)) {
 		ret = PTR_ERR(dd);
@@ -542,6 +553,7 @@ static int ipath_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	dd->ipath_kregbase = __ioremap(addr, len,
 		(_PAGE_NO_CACHE|_PAGE_WRITETHRU));
 #else
+	/* XXX: split this properly to enable on PAT */
 	dd->ipath_kregbase = ioremap_nocache(addr, len);
 #endif
 
@@ -587,12 +599,8 @@ static int ipath_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	ret = ipath_enable_wc(dd);
 
-	if (ret) {
-		ipath_dev_err(dd, "Write combining not enabled "
-			      "(err %d): performance may be poor\n",
-			      -ret);
+	if (ret)
 		ret = 0;
-	}
 
 	ipath_verify_pioperf(dd);
 
drivers/infiniband/hw/ipath/ipath_kernel.h +1 -3
index e08db70..f0f9471 100644
@@ -463,9 +463,7 @@ struct ipath_devdata {
 	/* offset in HT config space of slave/primary interface block */
 	u8 ipath_ht_slave_off;
 	/* for write combining settings */
-	unsigned long ipath_wc_cookie;
-	unsigned long ipath_wc_base;
-	unsigned long ipath_wc_len;
+	int wc_cookie;
 	/* ref count for each pkey */
 	atomic_t ipath_pkeyrefs[4];
 	/* shadow copy of struct page *'s for exp tid pages */
drivers/infiniband/hw/ipath/ipath_wc_x86_64.c +9 -34

59 lines not on this page · raw message

Signature · 1 line
2.3.2.209.gd67f9d5.dirty
#285 lore raw

Re: tools: Consolidate types.h

Hi,

I can't build the kernel after "git pull",

	In file included from /usr/include/asm/types.h:4,
			 from ./tools/include/linux/types.h:9,
			 from ./include/uapi/linux/elf.h:4,
			 from arch/x86/vdso/vdso2c.c:66:
	./include/uapi/asm-generic/int-ll64.h:11:29: error: asm/bitsperlong.h: No such file or directory

I am not 100% sure but it seems that this was broken by d944c4eebcf4c0d5e5d9728fec110cbf0047ad7f "tools: Consolidate types.h"

Don't we need the patch below? Or should I finally update my (very old) distro which doesn't have /usr/include/asm/bitsperlong.h ?

Oleg.

arch/x86/vdso/Makefile +1 -1
index 275a3a8..e970320 100644
@@ -51,7 +51,7 @@ VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
 $(obj)/vdso64.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
 	$(call if_changed,vdso)
 
-HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi
+HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi -I$(srctree)/arch/x86/include/uapi
 hostprogs-y			+= vdso2c
 
 quiet_cmd_vdso2c = VDSO2C  $@
#286 lore raw

Re: tools: Consolidate types.h

Quoted 3 lines · Oleg Nesterov

Hi,

I can't build the kernel after "git pull",

You mean, you can't build perf tool...?

Quoted 21 lines
	In file included from /usr/include/asm/types.h:4,
			 from ./tools/include/linux/types.h:9,
			 from ./include/uapi/linux/elf.h:4,
			 from arch/x86/vdso/vdso2c.c:66:
	./include/uapi/asm-generic/int-ll64.h:11:29: error: asm/bitsperlong.h: No such file or directory

I am not 100% sure but it seems that this was broken by d944c4eebcf4c0d5e5d9728fec110cbf0047ad7f "tools: Consolidate types.h"

Don't we need the patch below? Or should I finally update my (very old) distro which doesn't have /usr/include/asm/bitsperlong.h ?

Oleg.

arch/x86/vdso/Makefile +0 -0
index 275a3a8..e970320 100644

arch/x86/vdso/Makefile VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \ · line 54

Quoted 5 lines
arch/x86/vdso/Makefile +1 -1
@@ -51,7 +51,7 @@ VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
 $(obj)/vdso64.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
 	$(call if_changed,vdso)
 
-HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi
+HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi -I$(srctree)/arch/x86/include/uapi

Do you have kernel-headers installed on your distro? That's basically those uapi headers packaged separately. There's also "make headers_install" which should probably do that (haven't tried it though).

Signature · 5 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#287 lore raw

Re: tools: Consolidate types.h

Quoted 7 lines · Borislav Petkov
Quoted 3 lines · Oleg Nesterov

Hi,

I can't build the kernel after "git pull",

You mean, you can't build perf tool...?

No, make bzImage fails, it can't compile arch/x86/vdso/vdso2c

Quoted 25 lines
Quoted 25 lines

	In file included from /usr/include/asm/types.h:4,
			 from ./tools/include/linux/types.h:9,
			 from ./include/uapi/linux/elf.h:4,
			 from arch/x86/vdso/vdso2c.c:66:
	./include/uapi/asm-generic/int-ll64.h:11:29: error: asm/bitsperlong.h: No such file or directory

I am not 100% sure but it seems that this was broken by d944c4eebcf4c0d5e5d9728fec110cbf0047ad7f "tools: Consolidate types.h"

Don't we need the patch below? Or should I finally update my (very old) distro which doesn't have /usr/include/asm/bitsperlong.h ?

Oleg.

arch/x86/vdso/Makefile +0 -0
index 275a3a8..e970320 100644
@@ -51,7 +51,7 @@ VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
 $(obj)/vdso64.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
 	$(call if_changed,vdso)
 
Quoted 4 lines

arch/x86/vdso/Makefile VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \ · line 54

Quoted 2 lines
arch/x86/vdso/Makefile +1 -1
-HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi
+HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi -I$(srctree)/arch/x86/include/uapi

Do you have kernel-headers installed on your distro?

I have no idea ;) but I guess they were installed. many years ago.

Quoted 4 lines

That's
basically those uapi headers packaged separately. There's also "make headers_install" which should probably do that (haven't tried it though).

Perhaps. but still, if HOST_EXTRACFLAGS has -I$(srctree)/include/uapi, why it doesn't add arch/x86/include/uapi? This doesn't look consistent in any case.

Oleg.

#288 lore raw

Re: tools: Consolidate types.h

Quoted 10 lines · Oleg Nesterov
Quoted 7 lines · Borislav Petkov
Quoted 3 lines · Oleg Nesterov

Hi,

I can't build the kernel after "git pull",

You mean, you can't build perf tool...?

No, make bzImage fails, it can't compile arch/x86/vdso/vdso2c

Wow, so this commit is a year old and this is the first time I see a it causing a failure. You must have a really ooold distro :-)

Quoted 15 lines
Quoted 8 lines
Quoted 8 lines
arch/x86/vdso/Makefile +0 -0
index 275a3a8..e970320 100644
@@ -51,7 +51,7 @@ VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
 $(obj)/vdso64.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
 	$(call if_changed,vdso)
 
Quoted 4 lines

arch/x86/vdso/Makefile VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \ · line 54

Quoted 2 lines
arch/x86/vdso/Makefile +1 -1
-HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi
+HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi -I$(srctree)/arch/x86/include/uapi

Do you have kernel-headers installed on your distro?

I have no idea ;) but I guess they were installed. many years ago.

Quoted 8 lines
Quoted 4 lines

That's
basically those uapi headers packaged separately. There's also "make headers_install" which should probably do that (haven't tried it though).

Perhaps. but still, if HOST_EXTRACFLAGS has -I$(srctree)/include/uapi, why it doesn't add arch/x86/include/uapi? This doesn't look consistent in any case.

Yeah, I guess it wouldn't hurt. Andy, see quoted hunk above ^^.

Signature · 5 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#289 lore raw

Re: tools: Consolidate types.h

Quoted 35 lines · Borislav Petkov
Quoted 10 lines · Oleg Nesterov
Quoted 7 lines · Borislav Petkov
Quoted 3 lines · Oleg Nesterov

Hi,

I can't build the kernel after "git pull",

You mean, you can't build perf tool...?

No, make bzImage fails, it can't compile arch/x86/vdso/vdso2c

Wow, so this commit is a year old and this is the first time I see a it causing a failure. You must have a really ooold distro :-)

Quoted 20 lines
Quoted 8 lines
Quoted 8 lines
arch/x86/vdso/Makefile +0 -0
index 275a3a8..e970320 100644
@@ -51,7 +51,7 @@ VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
 $(obj)/vdso64.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
  $(call if_changed,vdso)
 
Quoted 4 lines

arch/x86/vdso/Makefile VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \ · line 54

Quoted 2 lines
arch/x86/vdso/Makefile +1 -1
-HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi
+HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi -I$(srctree)/arch/x86/include/uapi

Do you have kernel-headers installed on your distro?

I have no idea ;) but I guess they were installed. many years ago.

Quoted 4 lines

That's
basically those uapi headers packaged separately. There's also "make headers_install" which should probably do that (haven't tried it though).

Quoted 5 lines
Quoted 3 lines

Perhaps. but still, if HOST_EXTRACFLAGS has -I$(srctree)/include/uapi, why it doesn't add arch/x86/include/uapi? This doesn't look consistent in any case.

Yeah, I guess it wouldn't hurt. Andy, see quoted hunk above ^^.

I'd be fine with adding the extra -I. Want to send a pach? I'll get to it eventually if you don't beat me to it.

--Andy

Quoted 7 lines

--
Regards/Gruss,
Boris.

ECO tip #101: Trim your mails when you reply.
--

Signature · 2 lines
Andy Lutomirski
AMA Capital Management, LLC
#290 lore raw

cover x86/vdso: add -Iarch/x86/include/uapi into HOST_EXTRACFLAGS

Quoted 3 lines · Andy Lutomirski

I'd be fine with adding the extra -I. Want to send a pach? I'll get to it eventually if you don't beat me to it.

Sure. But please feel free to ignore, this is really minor and I can add a couple of .h files in my /usr/include. That said, "looks more consistent" is true in any case imo, so please see the trivial 1/1.

Oleg.

#291 lore raw

PATCH 1/1 x86/vdso: add -Iarch/x86/include/uapi into HOST_EXTRACFLAGS

Change HOST_EXTRACFLAGS to include arch/x86/include/uapi along with include/uapi.

This looks more consistent, and this fixes "make bzImage" on my old distro which doesn't have asm/bitsperlong.h in /usr/include/.

---
 arch/x86/vdso/Makefile |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
arch/x86/vdso/Makefile +1 -1
index 275a3a8..e970320 100644
@@ -51,7 +51,7 @@ VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
 $(obj)/vdso64.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
 	$(call if_changed,vdso)
 
-HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi
+HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi -I$(srctree)/arch/x86/include/uapi
 hostprogs-y			+= vdso2c
 
 quiet_cmd_vdso2c = VDSO2C  $@
Signature · 1 line
1.5.5.1
Acked-by on v1 1/1
#292 lore raw

Re: [PATCH 1/1] x86/vdso: add -Iarch/x86/include/uapi into HOST_EXTRACFLAGS

Quoted 7 lines · Oleg Nesterov

Change HOST_EXTRACFLAGS to include arch/x86/include/uapi along with include/uapi.

This looks more consistent, and this fixes "make bzImage" on my old distro which doesn't have asm/bitsperlong.h in /usr/include/.

Fixed: 6f121e548f83 x86, vdso: Reimplement vdso.so preparation in build-time C

Ingo, despite Oleg's rather late discovery of this, it's a regression fix. If you think it's appropriate for x86/urgent, please apply it. Otherwise I'll queue it up.

--Andy

Quoted 21 lines
---
 arch/x86/vdso/Makefile |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
arch/x86/vdso/Makefile +1 -2
index 275a3a8..e970320 100644
@@ -51,7 +51,7 @@ VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
 $(obj)/vdso64.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
        $(call if_changed,vdso)
 
-HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi
+HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi -I$(srctree)/arch/x86/include/uapi
 hostprogs-y                    += vdso2c
 
 quiet_cmd_vdso2c = VDSO2C  $@
--

1.5.5.1

Signature · 2 lines
Andy Lutomirski
AMA Capital Management, LLC
#293 lore raw

Re: [PATCH 1/1] x86/vdso: add -Iarch/x86/include/uapi into HOST_EXTRACFLAGS

Quoted 7 lines · Andy Lutomirski
Quoted 6 lines · Oleg Nesterov

Change HOST_EXTRACFLAGS to include arch/x86/include/uapi along with include/uapi.

This looks more consistent, and this fixes "make bzImage" on my old distro which doesn't have asm/bitsperlong.h in /usr/include/.

Quoted 8 lines
Quoted 1 line

Fixed: 6f121e548f83 x86, vdso: Reimplement vdso.so preparation in build-time C

Ingo, despite Oleg's rather late discovery of this, it's a regression fix. If you think it's appropriate for x86/urgent, please apply it. Otherwise I'll queue it up.

I took it and tagged it for stable. It is a build fix after all.

Thanks.

Signature · 5 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#294 lore raw

[tip:x86/urgent] x86/vdso: Fix 'make bzImage' on older distros

In reply to Oleg Nesterov
x86/vdso: Fix 'make bzImage' on older distros
Commit-ID:  ef7254a595912b026d80a4116b8c4cd5b79d9c62
Gitweb:     http://git.kernel.org/tip/ef7254a595912b026d80a4116b8c4cd5b79d9c62
Author:     Oleg Nesterov <[email protected]>
AuthorDate: Mon, 11 May 2015 10:15:50 +0200
Committer:  Ingo Molnar <[email protected]>
CommitDate: Mon, 11 May 2015 10:25:02 +0200

x86/vdso: Fix 'make bzImage' on older distros

Change HOST_EXTRACFLAGS to include arch/x86/include/uapi along with include/uapi.

This looks more consistent, and this fixes "make bzImage" on my old distro which doesn't have asm/bitsperlong.h in /usr/include/.

Cc Andy Lutomirski <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Rusty Russell <[email protected]>
Cc Thomas Gleixner <[email protected]>
Fixes 6f121e548f83 ("x86, vdso: Reimplement vdso.so preparation in build-time C")
---
 arch/x86/vdso/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/vdso/Makefile +1 -1
index 275a3a8..e970320 100644
@@ -51,7 +51,7 @@ VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
 $(obj)/vdso64.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
 	$(call if_changed,vdso)
 
-HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi
+HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi -I$(srctree)/arch/x86/include/uapi
 hostprogs-y			+= vdso2c
 
 quiet_cmd_vdso2c = VDSO2C  $@
maintainer
#295 lore raw

cover tip queue 2015-05-11

From: Borislav Petkov <[email protected]>

Hi Ingo,

8 patches this time.

2015-05-11/

├── cleanups
│   └── 0001-x86-kaslr-Fix-typo-in-KASLR_FLAG-documentation.patch
├── cpu
│   └── 0001-x86-alternatives-Switch-AMD-F15h-and-later-to-the-P6.patch
├── microcode
│   └── 0001-x86-cpu-microcode-Zap-changelog.patch
├── mm
│   ├── 0001-x86-mm-Do-not-flush-last-cacheline-twice-in-clflush_.patch
│   ├── 0002-x86-mm-Add-kerneldoc-comments-for-pcommit_sfence.patch
│   ├── 0003-x86-MTRR-Remove-wrong-address-check-in-__mtrr_type_l.patch
│   └── 0004-x86-mm-Add-ioremap_uc-helper-to-map-memory-uncacheab.patch
└── urgent
    └── 0001-x86-vdso-Add-arch-x86-include-uapi-include-path-to-H.patch
maintainer
#296 lore raw

PATCH 1/1 x86/kaslr: Fix typo in KASLR_FLAG documentation

From: Miroslav Benes <[email protected]>

Documentation/x86/boot.txt labels the bit in boot_params.hdr.loadflags as ALSR_FLAG while it should be KASLR_FLAG.

---
 Documentation/x86/boot.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
Documentation/x86/boot.txt +1 -1
index 88b85899d309..69e139791868 100644
@@ -406,7 +406,7 @@ Protocol:	2.00+
 	- If 0, the protected-mode code is loaded at 0x10000.
 	- If 1, the protected-mode code is loaded at 0x100000.
 
-  Bit 1 (kernel internal): ALSR_FLAG
+  Bit 1 (kernel internal): KASLR_FLAG
 	- Used internally by the compressed kernel to communicate
 	  KASLR status to kernel proper.
 	  If 1, KASLR enabled.
Signature · 1 line
2.3.5
#297 lore raw

[tip:x86/boot] x86/kaslr: Fix typo in the KASLR_FLAG documentation

x86/kaslr: Fix typo in the KASLR_FLAG documentation
Commit-ID:  d4bd441532b81fe2be1706e7f9dbbe8b5a364bcf
Gitweb:     http://git.kernel.org/tip/d4bd441532b81fe2be1706e7f9dbbe8b5a364bcf
Author:     Miroslav Benes <[email protected]>
AuthorDate: Mon, 11 May 2015 10:15:48 +0200
Committer:  Ingo Molnar <[email protected]>
CommitDate: Mon, 11 May 2015 10:28:57 +0200

x86/kaslr: Fix typo in the KASLR_FLAG documentation

Documentation/x86/boot.txt labels the bit in boot_params.hdr.loadflags as ALSR_FLAG while it should be KASLR_FLAG.

---
 Documentation/x86/boot.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
Documentation/x86/boot.txt +1 -1
index 88b8589..69e1397 100644
@@ -406,7 +406,7 @@ Protocol:	2.00+
 	- If 0, the protected-mode code is loaded at 0x10000.
 	- If 1, the protected-mode code is loaded at 0x100000.
 
-  Bit 1 (kernel internal): ALSR_FLAG
+  Bit 1 (kernel internal): KASLR_FLAG
 	- Used internally by the compressed kernel to communicate
 	  KASLR status to kernel proper.
 	  If 1, KASLR enabled.
maintainer
#298 lore raw

PATCH 1/5 x86/mm: Do not flush last cacheline twice in clflush_cache_range()

In reply to Borislav Petkov

From: Ross Zwisler <[email protected]>

The current algorithm used in clflush_cache_range() can cause the last cache line of the buffer to be flushed twice. Fix that algorithm so that each cache line will only be flushed once.

---
 arch/x86/mm/pageattr.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)
arch/x86/mm/pageattr.c +6 -7
index 89af288ec674..338e507f95b8 100644
@@ -129,16 +129,15 @@ within(unsigned long addr, unsigned long start, unsigned long end)
  */
 void clflush_cache_range(void *vaddr, unsigned int size)
 {
-	void *vend = vaddr + size - 1;
+	unsigned long clflush_mask = boot_cpu_data.x86_clflush_size - 1;
+	char *vend = (char *)vaddr + size;
+	char *p;
 
 	mb();
 
-	for (; vaddr < vend; vaddr += boot_cpu_data.x86_clflush_size)
-		clflushopt(vaddr);
-	/*
-	 * Flush any possible final partial cacheline:
-	 */
-	clflushopt(vend);
+	for (p = (char *)((unsigned long)vaddr & ~clflush_mask);
+	     p < vend; p += boot_cpu_data.x86_clflush_size)
+		clflushopt(p);
 
 	mb();
 }
Signature · 1 line
2.3.5
#299 lore raw

[tip:x86/mm] x86/mm: Do not flush last cacheline twice in clflush_cache_range()

x86/mm: Do not flush last cacheline twice in clflush_cache_range()
Commit-ID:  6c434d6176c0cb42847c33245189667d645db7bf
Gitweb:     http://git.kernel.org/tip/6c434d6176c0cb42847c33245189667d645db7bf
Author:     Ross Zwisler <[email protected]>
AuthorDate: Mon, 11 May 2015 10:15:49 +0200
Committer:  Ingo Molnar <[email protected]>
CommitDate: Mon, 11 May 2015 10:38:44 +0200

x86/mm: Do not flush last cacheline twice in clflush_cache_range()

The current algorithm used in clflush_cache_range() can cause the last cache line of the buffer to be flushed twice. Fix that algorithm so that each cache line will only be flushed once.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Luis R. Rodriguez <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Toshi Kani <[email protected]>
[ Changed it to 'void *' to simplify the type conversions. ]
---
 arch/x86/mm/pageattr.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)
arch/x86/mm/pageattr.c +6 -7
index 89af288..5ddd900 100644
@@ -129,16 +129,15 @@ within(unsigned long addr, unsigned long start, unsigned long end)
  */
 void clflush_cache_range(void *vaddr, unsigned int size)
 {
-	void *vend = vaddr + size - 1;
+	unsigned long clflush_mask = boot_cpu_data.x86_clflush_size - 1;
+	void *vend = vaddr + size;
+	void *p;
 
 	mb();
 
-	for (; vaddr < vend; vaddr += boot_cpu_data.x86_clflush_size)
-		clflushopt(vaddr);
-	/*
-	 * Flush any possible final partial cacheline:
-	 */
-	clflushopt(vend);
+	for (p = (void *)((unsigned long)vaddr & ~clflush_mask);
+	     p < vend; p += boot_cpu_data.x86_clflush_size)
+		clflushopt(p);
 
 	mb();
 }
maintainer
#300 lore raw

PATCH 1/1 x86/cpu/microcode: Zap changelog

In reply to Borislav Petkov

From: Borislav Petkov <[email protected]>

It is useless at best and git history has it all detailed anyway. Update copyright while at it.

---
 arch/x86/kernel/cpu/microcode/core.c  | 76 +++++------------------------------
 arch/x86/kernel/cpu/microcode/intel.c | 75 ++++------------------------------
 2 files changed, 16 insertions(+), 135 deletions(-)
arch/x86/kernel/cpu/microcode/core.c +9 -67
index 36a83617eb21..6236a54a63f4 100644
@@ -1,74 +1,16 @@
 /*
- *	Intel CPU Microcode Update Driver for Linux
+ * CPU Microcode Update Driver for Linux
  *
- *	Copyright (C) 2000-2006 Tigran Aivazian <[email protected]>
- *		      2006	Shaohua Li <[email protected]>
+ * Copyright (C) 2000-2006 Tigran Aivazian <[email protected]>
+ *	      2006	Shaohua Li <[email protected]>
+ *	      2013-2015	Borislav Petkov <[email protected]>
  *
- *	This driver allows to upgrade microcode on Intel processors
- *	belonging to IA-32 family - PentiumPro, Pentium II,
- *	Pentium III, Xeon, Pentium 4, etc.
+ * This driver allows to upgrade microcode on x86 processors.
  *
- *	Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
- *	Software Developer's Manual
- *	Order Number 253668 or free download from:
- *
- *	http://developer.intel.com/Assets/PDF/manual/253668.pdf	
- *
- *	For more information, go to http://www.urbanmyth.org/microcode
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License
- *	as published by the Free Software Foundation; either version
- *	2 of the License, or (at your option) any later version.
- *
- *	1.0	16 Feb 2000, Tigran Aivazian <[email protected]>
- *		Initial release.
- *	1.01	18 Feb 2000, Tigran Aivazian <[email protected]>
- *		Added read() support + cleanups.
- *	1.02	21 Feb 2000, Tigran Aivazian <[email protected]>
- *		Added 'device trimming' support. open(O_WRONLY) zeroes
- *		and frees the saved copy of applied microcode.
- *	1.03	29 Feb 2000, Tigran Aivazian <[email protected]>
- *		Made to use devfs (/dev/cpu/microcode) + cleanups.
- *	1.04	06 Jun 2000, Simon Trimmer <[email protected]>
- *		Added misc device support (now uses both devfs and misc).
- *		Added MICROCODE_IOCFREE ioctl to clear memory.
- *	1.05	09 Jun 2000, Simon Trimmer <[email protected]>
- *		Messages for error cases (non Intel & no suitable microcode).
- *	1.06	03 Aug 2000, Tigran Aivazian <[email protected]>
- *		Removed ->release(). Removed exclusive open and status bitmap.
- *		Added microcode_rwsem to serialize read()/write()/ioctl().
- *		Removed global kernel lock usage.
- *	1.07	07 Sep 2000, Tigran Aivazian <[email protected]>
- *		Write 0 to 0x8B msr and then cpuid before reading revision,
- *		so that it works even if there were no update done by the
- *		BIOS. Otherwise, reading from 0x8B gives junk (which happened
- *		to be 0 on my machine which is why it worked even when I
- *		disabled update by the BIOS)
- *		Thanks to Eric W. Biederman <[email protected]> for the fix.
- *	1.08	11 Dec 2000, Richard Schaal <[email protected]> and
- *			     Tigran Aivazian <[email protected]>
- *		Intel Pentium 4 processor support and bugfixes.
- *	1.09	30 Oct 2001, Tigran Aivazian <[email protected]>
- *		Bugfix for HT (Hyper-Threading) enabled processors
- *		whereby processor resources are shared by all logical processors
- *		in a single CPU package.
- *	1.10	28 Feb 2002 Asit K Mallick <[email protected]> and
- *		Tigran Aivazian <[email protected]>,
- *		Serialize updates as required on HT processors due to
- *		speculative nature of implementation.
- *	1.11	22 Mar 2002 Tigran Aivazian <[email protected]>
- *		Fix the panic when writing zero-length microcode chunk.
- *	1.12	29 Sep 2003 Nitin Kamble <[email protected]>,
- *		Jun Nakajima <[email protected]>
- *		Support for the microcode updates in the new format.
- *	1.13	10 Oct 2003 Tigran Aivazian <[email protected]>
- *		Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl
- *		because we no longer hold a copy of applied microcode
- *		in kernel memory.
- *	1.14	25 Jun 2004 Tigran Aivazian <[email protected]>
- *		Fix sigmatch() macro to handle old CPUs with pf == 0.
- *		Thanks to Stuart Swales for pointing out this bug.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
arch/x86/kernel/cpu/microcode/intel.c +7 -68

81 lines not on this page · raw message

Signature · 1 line
2.3.5
#301 lore raw

[tip:x86/microcode] x86/cpu/microcode: Zap changelog

x86/cpu/microcode: Zap changelog
Commit-ID:  6b44e72a1c45d1a4e903af75611235a2d6ea25e3
Gitweb:     http://git.kernel.org/tip/6b44e72a1c45d1a4e903af75611235a2d6ea25e3
Author:     Borislav Petkov <[email protected]>
AuthorDate: Mon, 11 May 2015 10:15:47 +0200
Committer:  Ingo Molnar <[email protected]>
CommitDate: Mon, 11 May 2015 10:27:09 +0200

x86/cpu/microcode: Zap changelog

It is useless at best and git history has it all detailed anyway. Update copyright while at it.

Cc Andy Lutomirski <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/kernel/cpu/microcode/core.c  | 76 +++++------------------------------
 arch/x86/kernel/cpu/microcode/intel.c | 75 ++++------------------------------
 2 files changed, 16 insertions(+), 135 deletions(-)
arch/x86/kernel/cpu/microcode/core.c +9 -67
index 36a8361..6236a54 100644
@@ -1,74 +1,16 @@
 /*
- *	Intel CPU Microcode Update Driver for Linux
+ * CPU Microcode Update Driver for Linux
  *
- *	Copyright (C) 2000-2006 Tigran Aivazian <[email protected]>
- *		      2006	Shaohua Li <[email protected]>
+ * Copyright (C) 2000-2006 Tigran Aivazian <[email protected]>
+ *	      2006	Shaohua Li <[email protected]>
+ *	      2013-2015	Borislav Petkov <[email protected]>
  *
- *	This driver allows to upgrade microcode on Intel processors
- *	belonging to IA-32 family - PentiumPro, Pentium II,
- *	Pentium III, Xeon, Pentium 4, etc.
+ * This driver allows to upgrade microcode on x86 processors.
  *
- *	Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
- *	Software Developer's Manual
- *	Order Number 253668 or free download from:
- *
- *	http://developer.intel.com/Assets/PDF/manual/253668.pdf	
- *
- *	For more information, go to http://www.urbanmyth.org/microcode
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License
- *	as published by the Free Software Foundation; either version
- *	2 of the License, or (at your option) any later version.
- *
- *	1.0	16 Feb 2000, Tigran Aivazian <[email protected]>
- *		Initial release.
- *	1.01	18 Feb 2000, Tigran Aivazian <[email protected]>
- *		Added read() support + cleanups.
- *	1.02	21 Feb 2000, Tigran Aivazian <[email protected]>
- *		Added 'device trimming' support. open(O_WRONLY) zeroes
- *		and frees the saved copy of applied microcode.
- *	1.03	29 Feb 2000, Tigran Aivazian <[email protected]>
- *		Made to use devfs (/dev/cpu/microcode) + cleanups.
- *	1.04	06 Jun 2000, Simon Trimmer <[email protected]>
- *		Added misc device support (now uses both devfs and misc).
- *		Added MICROCODE_IOCFREE ioctl to clear memory.
- *	1.05	09 Jun 2000, Simon Trimmer <[email protected]>
- *		Messages for error cases (non Intel & no suitable microcode).
- *	1.06	03 Aug 2000, Tigran Aivazian <[email protected]>
- *		Removed ->release(). Removed exclusive open and status bitmap.
- *		Added microcode_rwsem to serialize read()/write()/ioctl().
- *		Removed global kernel lock usage.
- *	1.07	07 Sep 2000, Tigran Aivazian <[email protected]>
- *		Write 0 to 0x8B msr and then cpuid before reading revision,
- *		so that it works even if there were no update done by the
- *		BIOS. Otherwise, reading from 0x8B gives junk (which happened
- *		to be 0 on my machine which is why it worked even when I
- *		disabled update by the BIOS)
- *		Thanks to Eric W. Biederman <[email protected]> for the fix.
- *	1.08	11 Dec 2000, Richard Schaal <[email protected]> and
- *			     Tigran Aivazian <[email protected]>
- *		Intel Pentium 4 processor support and bugfixes.
- *	1.09	30 Oct 2001, Tigran Aivazian <[email protected]>
- *		Bugfix for HT (Hyper-Threading) enabled processors
- *		whereby processor resources are shared by all logical processors
- *		in a single CPU package.
- *	1.10	28 Feb 2002 Asit K Mallick <[email protected]> and
- *		Tigran Aivazian <[email protected]>,
- *		Serialize updates as required on HT processors due to
- *		speculative nature of implementation.
- *	1.11	22 Mar 2002 Tigran Aivazian <[email protected]>
- *		Fix the panic when writing zero-length microcode chunk.
- *	1.12	29 Sep 2003 Nitin Kamble <[email protected]>,
- *		Jun Nakajima <[email protected]>
- *		Support for the microcode updates in the new format.
- *	1.13	10 Oct 2003 Tigran Aivazian <[email protected]>
- *		Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl
- *		because we no longer hold a copy of applied microcode
- *		in kernel memory.
- *	1.14	25 Jun 2004 Tigran Aivazian <[email protected]>
- *		Fix sigmatch() macro to handle old CPUs with pf == 0.
- *		Thanks to Stuart Swales for pointing out this bug.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
arch/x86/kernel/cpu/microcode/intel.c +7 -68

81 lines not on this page · raw message

maintainer
#302 lore raw

PATCH 2/5 x86/mm: Add kerneldoc comments for pcommit_sfence()

In reply to Borislav Petkov

From: Ross Zwisler <[email protected]>

Add kerneldoc comments for pcommit_sfence() describing the purpose of the PCOMMIT instruction and demonstrating its usage with an example.

---
 arch/x86/include/asm/special_insns.h | 38 ++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)
arch/x86/include/asm/special_insns.h +38 -0
index aeb4666e0c0a..2270e41b32fd 100644
@@ -215,6 +215,44 @@ static inline void clwb(volatile void *__p)
 		: [pax] "a" (p));
 }
 
+/**
+ * pcommit_sfence() - persistent commit and fence
+ *
+ * The PCOMMIT instruction ensures that data that has been flushed from the
+ * processor's cache hierarchy with CLWB, CLFLUSHOPT or CLFLUSH is accepted to
+ * memory and is durable on the DIMM.  The primary use case for this is
+ * persistent memory.
+ *
+ * This function shows how to properly use CLWB/CLFLUSHOPT/CLFLUSH and PCOMMIT
+ * with appropriate fencing.
+ *
+ * Example:
+ * void flush_and_commit_buffer(void *vaddr, unsigned int size)
+ * {
+ *         unsigned long clflush_mask = boot_cpu_data.x86_clflush_size - 1;
+ *         void *vend = vaddr + size;
+ *         void *p;
+ *
+ *         for (p = (void *)((unsigned long)vaddr & ~clflush_mask);
+ *              p < vend; p += boot_cpu_data.x86_clflush_size)
+ *                 clwb(p);
+ *
+ *         // SFENCE to order CLWB/CLFLUSHOPT/CLFLUSH cache flushes
+ *         // MFENCE via mb() also works
+ *         wmb();
+ *
+ *         // PCOMMIT and the required SFENCE for ordering
+ *         pcommit_sfence();
+ * }
+ *
+ * After this function completes the data pointed to by 'vaddr' has been
+ * accepted to memory and will be durable if the 'vaddr' points to persistent
+ * memory.
+ *
+ * PCOMMIT must always be ordered by an MFENCE or SFENCE, so to help simplify
+ * things we include both the PCOMMIT and the required SFENCE in the
+ * alternatives generated by pcommit_sfence().
+ */
 static inline void pcommit_sfence(void)
 {
 	alternative(ASM_NOP7,
Signature · 1 line
2.3.5
#303 lore raw

[tip:x86/mm] x86/mm: Add kerneldoc comments for pcommit_sfence()

x86/mm: Add kerneldoc comments for pcommit_sfence()
Commit-ID:  ca7d9b795e6bc78c80a1771ada867994fabcfc01
Gitweb:     http://git.kernel.org/tip/ca7d9b795e6bc78c80a1771ada867994fabcfc01
Author:     Ross Zwisler <[email protected]>
AuthorDate: Mon, 11 May 2015 10:15:51 +0200
Committer:  Ingo Molnar <[email protected]>
CommitDate: Mon, 11 May 2015 10:38:44 +0200

x86/mm: Add kerneldoc comments for pcommit_sfence()

Add kerneldoc comments for pcommit_sfence() describing the purpose of the PCOMMIT instruction and demonstrating its usage with an example.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H Peter Anvin <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Luis R. Rodriguez <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Toshi Kani <[email protected]>
---
 arch/x86/include/asm/special_insns.h | 38 ++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)
arch/x86/include/asm/special_insns.h +38 -0
index aeb4666e..2270e41 100644
@@ -215,6 +215,44 @@ static inline void clwb(volatile void *__p)
 		: [pax] "a" (p));
 }
 
+/**
+ * pcommit_sfence() - persistent commit and fence
+ *
+ * The PCOMMIT instruction ensures that data that has been flushed from the
+ * processor's cache hierarchy with CLWB, CLFLUSHOPT or CLFLUSH is accepted to
+ * memory and is durable on the DIMM.  The primary use case for this is
+ * persistent memory.
+ *
+ * This function shows how to properly use CLWB/CLFLUSHOPT/CLFLUSH and PCOMMIT
+ * with appropriate fencing.
+ *
+ * Example:
+ * void flush_and_commit_buffer(void *vaddr, unsigned int size)
+ * {
+ *         unsigned long clflush_mask = boot_cpu_data.x86_clflush_size - 1;
+ *         void *vend = vaddr + size;
+ *         void *p;
+ *
+ *         for (p = (void *)((unsigned long)vaddr & ~clflush_mask);
+ *              p < vend; p += boot_cpu_data.x86_clflush_size)
+ *                 clwb(p);
+ *
+ *         // SFENCE to order CLWB/CLFLUSHOPT/CLFLUSH cache flushes
+ *         // MFENCE via mb() also works
+ *         wmb();
+ *
+ *         // PCOMMIT and the required SFENCE for ordering
+ *         pcommit_sfence();
+ * }
+ *
+ * After this function completes the data pointed to by 'vaddr' has been
+ * accepted to memory and will be durable if the 'vaddr' points to persistent
+ * memory.
+ *
+ * PCOMMIT must always be ordered by an MFENCE or SFENCE, so to help simplify
+ * things we include both the PCOMMIT and the required SFENCE in the
+ * alternatives generated by pcommit_sfence().
+ */
 static inline void pcommit_sfence(void)
 {
 	alternative(ASM_NOP7,
maintainer
#304 lore raw

PATCH 3/5 x86/MTRR: Remove wrong address check in __mtrr_type_lookup()

In reply to Borislav Petkov

From: Toshi Kani <[email protected]>

__mtrr_type_lookup() checks MTRR fixed ranges when mtrr_state.have_fixed is set and start is less than 0x100000. However, the 'else if (start < 0x1000000)' in the code checks with a wrong address as it has an extra-zero in the address. The code still runs correctly as this check is meaningless, though.

This patch replaces the wrong address check with 'else' with no condition.

---
 arch/x86/kernel/cpu/mtrr/generic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kernel/cpu/mtrr/generic.c +1 -1
index 7d74f7b3c6ba..5b239679cfc9 100644
@@ -137,7 +137,7 @@ static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
 			idx = 1 * 8;
 			idx += ((start - 0x80000) >> 14);
 			return mtrr_state.fixed_ranges[idx];
-		} else if (start < 0x1000000) {
+		} else {
 			idx = 3 * 8;
 			idx += ((start - 0xC0000) >> 12);
 			return mtrr_state.fixed_ranges[idx];
Signature · 1 line
2.3.5
#305 lore raw

[tip:x86/mm] x86/mm/mtrr: Remove incorrect address check in __mtrr_type_lookup()

x86/mm/mtrr: Remove incorrect address check in __mtrr_type_lookup()
Commit-ID:  cd2f6a5a4704a359635eb34919317052e6a96ba7
Gitweb:     http://git.kernel.org/tip/cd2f6a5a4704a359635eb34919317052e6a96ba7
Author:     Toshi Kani <[email protected]>
AuthorDate: Mon, 11 May 2015 10:15:52 +0200
Committer:  Ingo Molnar <[email protected]>
CommitDate: Mon, 11 May 2015 10:38:44 +0200

x86/mm/mtrr: Remove incorrect address check in __mtrr_type_lookup()

__mtrr_type_lookup() checks MTRR fixed ranges when mtrr_state.have_fixed is set and start is less than 0x100000.

However, the 'else if (start < 0x1000000)' in the code checks with an incorrect address as it has an extra-zero in the address.

The code still runs correctly as this check is meaningless, though.

This patch replaces the incorrect address check with 'else' with no condition.

---
 arch/x86/kernel/cpu/mtrr/generic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kernel/cpu/mtrr/generic.c +1 -1
index 7d74f7b..5b23967 100644
@@ -137,7 +137,7 @@ static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
 			idx = 1 * 8;
 			idx += ((start - 0x80000) >> 14);
 			return mtrr_state.fixed_ranges[idx];
-		} else if (start < 0x1000000) {
+		} else {
 			idx = 3 * 8;
 			idx += ((start - 0xC0000) >> 12);
 			return mtrr_state.fixed_ranges[idx];

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#306 lore raw

PATCH 1/1 x86/vdso: Add arch/x86/include/uapi include path to HOST_EXTRACFLAGS

In reply to Borislav Petkov

From: Oleg Nesterov <[email protected]>

Change HOST_EXTRACFLAGS to include arch/x86/include/uapi along with include/uapi.

This looks more consistent, and this fixes "make bzImage" on my old distro which doesn't have asm/bitsperlong.h in /usr/include/.

Cc Rusty Russell <[email protected]>
Cc Jiri Olsa <[email protected]>
Fixes 6f121e548f83 ("x86, vdso: Reimplement vdso.so preparation in build-time C")
---
 arch/x86/vdso/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/vdso/Makefile +1 -1
index 275a3a8b78af..e97032069f88 100644
@@ -51,7 +51,7 @@ VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
 $(obj)/vdso64.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
 	$(call if_changed,vdso)
 
-HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi
+HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi -I$(srctree)/arch/x86/include/uapi
 hostprogs-y			+= vdso2c
 
 quiet_cmd_vdso2c = VDSO2C  $@
Signature · 1 line
2.3.5
maintainer
#307 lore raw

PATCH 4/5 x86/mm: Add ioremap_uc() helper to map memory uncacheable (not UC-)

In reply to Borislav Petkov

From: "Luis R. Rodriguez" <[email protected]>

ioremap_nocache() currently uses UC- by default. Our goal is to eventually make UC the default. Linux maps UC- to PCD=1, PWT=0 page attributes on non-PAT systems. Linux maps UC to PCD=1, PWT=1 page attributes on non-PAT systems. On non-PAT and PAT systems a WC MTRR has different effects on pages with either of these attributes. In order to help with a smooth transition its best to enable use of UC (PCD,1, PWT=1) on a region as that ensures a WC MTRR will have no effect on a region, this however requires us to have an way to declare a region as UC and we currently do not have a way to do this.

WC MTRR on non-PAT system with PCD=1, PWT=0 (UC-) yields WC. WC MTRR on non-PAT system with PCD=1, PWT=1 (UC) yields UC.

WC MTRR on PAT system with PCD=1, PWT=0 (UC-) yields WC. WC MTRR on PAT system with PCD=1, PWT=1 (UC) yields UC.

A flip of the default ioremap_nocache() behaviour from UC- to UC can therefore regress a memory region from effective memory type WC to UC if MTRRs are used. Use of MTRRs should be phased out and in the best case only arch_phys_wc_add() use will remain, even if this happens arch_phys_wc_add() will have an effect on non-PAT systems and changes to default ioremap_nocache() behaviour could regress drivers.

Now, ideally we'd use ioremap_nocache() on the regions in which we'd need uncachable memory types and avoid any MTRRs on those regions. There are however some restrictions on MTRRs use, such as the requirement of having the base and size of variable sized MTRRs to be powers of two, which could mean having to use a WC MTRR over a large area which includes a region in which write-combining effects are undesirable.

Add ioremap_uc() to help with the both phasing out of MTRR use and also provide a way to blacklist small WC undesirable regions in devices with mixed regions which are size-implicated to use large WC MTRRs. Use of ioremap_uc() helps phase out MTRR use by avoiding regressions with an eventual flip of default behaviour or ioremap_nocache() from UC- to UC.

Drivers working with WC MTRRs can use the below table to review and consider the use of ioremap*() and similar helpers to ensure appropriate behaviour long term even if default ioremap_nocache() behaviour changes from UC- to UC.

Although ioremap_uc() is being added we leave set_memory_uc() to use UC- as only initial memory type setup is required to be able to accommodate existing device drivers and phase out MTRR use. It should also be clarified that set_memory_uc() cannot be used with IO memory, even though its use will not return any errors, it really has no effect.

----------------------------------------------------------------------
MTRR Non-PAT PAT Linux ioremap value Effective memory type
----------------------------------------------------------------------

                                                  Non-PAT |  PAT
     PAT
     |PCD
     ||PWT
     |||
WC   000      WB      _PAGE_CACHE_MODE_WB            WC   |   WC
WC   001      WC      _PAGE_CACHE_MODE_WC            WC*  |   WC
WC   010      UC-     _PAGE_CACHE_MODE_UC_MINUS      WC*  |   WC
WC   011      UC      _PAGE_CACHE_MODE_UC            UC   |   UC

----------------------------------------------------------------------

[ hpa: this requires communication with driver writers ]

Cc Toshi Kani <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Suresh Siddha <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Antonino Daplas <[email protected]>
Cc Jean-Christophe Plagniol-Villard <[email protected]>
Cc Tomi Valkeinen <[email protected]>
Cc Ville Syrjälä <[email protected]>
Cc Will Deacon <[email protected]>
Cc Thierry Reding <[email protected]>
Cc Mike Travis <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Davidlohr Bueso <[email protected]>
---
 arch/x86/include/asm/io.h |  1 +
 arch/x86/mm/ioremap.c     | 36 +++++++++++++++++++++++++++++++++++-
 arch/x86/mm/pageattr.c    |  3 +++
 include/asm-generic/io.h  |  8 ++++++++
 4 files changed, 47 insertions(+), 1 deletion(-)
arch/x86/include/asm/io.h +1 -0
index 34a5b93704d3..4afc05ffa566 100644
@@ -177,6 +177,7 @@ static inline unsigned int isa_virt_to_bus(volatile void *address)
  * look at pci_iomap().
  */
 extern void __iomem *ioremap_nocache(resource_size_t offset, unsigned long size);
+extern void __iomem *ioremap_uc(resource_size_t offset, unsigned long size);
 extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size);
 extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size,
 				unsigned long prot_val);
arch/x86/mm/ioremap.c +35 -1
index 5ead4d6cf3a7..fc08431a387b 100644
@@ -237,7 +237,8 @@ void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
 	 *	pat_enabled ? _PAGE_CACHE_MODE_UC : _PAGE_CACHE_MODE_UC_MINUS;
 	 *
 	 * Till we fix all X drivers to use ioremap_wc(), we will use
-	 * UC MINUS.
+	 * UC MINUS. Drivers that are certain they need or can already
+	 * be converted over to strong UC can use ioremap_uc().
 	 */
 	enum page_cache_mode pcm = _PAGE_CACHE_MODE_UC_MINUS;
 
@@ -247,6 +248,39 @@ void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
 EXPORT_SYMBOL(ioremap_nocache);
 
 /**
+ * ioremap_uc     -   map bus memory into CPU space as strongly uncachable
+ * @phys_addr:    bus address of the memory
+ * @size:      size of the resource to map
+ *
+ * ioremap_uc performs a platform specific sequence of operations to
+ * make bus memory CPU accessible via the readb/readw/readl/writeb/
+ * writew/writel functions and the other mmio helpers. The returned
+ * address is not guaranteed to be usable directly as a virtual
+ * address.
+ *
+ * This version of ioremap ensures that the memory is marked with a strong
+ * preference as completely uncachable on the CPU when possible. For non-PAT
+ * systems this ends up setting page-attribute flags PCD=1, PWT=1. For PAT
+ * systems this will set the PAT entry for the pages as strong UC.  This call
+ * will honor existing caching rules from things like the PCI bus. Note that
+ * there are other caches and buffers on many busses. In particular driver
+ * authors should read up on PCI writes.
+ *
+ * It's useful if some control registers are in such an area and
+ * write combining or read caching is not desirable:
+ *
+ * Must be freed with iounmap.
+ */
+void __iomem *ioremap_uc(resource_size_t phys_addr, unsigned long size)
+{
+	enum page_cache_mode pcm = _PAGE_CACHE_MODE_UC;
+
+	return __ioremap_caller(phys_addr, size, pcm,
+				__builtin_return_address(0));
+}
+EXPORT_SYMBOL_GPL(ioremap_uc);
+
+/**
  * ioremap_wc	-	map memory into CPU space write combined
  * @phys_addr:	bus address of the memory
  * @size:	size of the resource to map
arch/x86/mm/pageattr.c +3 -0
index 338e507f95b8..d35148acdc05 100644
@@ -1467,6 +1467,9 @@ int _set_memory_uc(unsigned long addr, int numpages)
 {
 	/*
 	 * for now UC MINUS. see comments in ioremap_nocache()
+	 * If you really need strong UC use ioremap_uc(), but note
+	 * that you cannot override IO areas with set_memory_*() as
+	 * these helpers cannot work with IO memory.
 	 */
 	return change_page_attr_set(&addr, numpages,
 				    cachemode2pgprot(_PAGE_CACHE_MODE_UC_MINUS),
include/asm-generic/io.h +8 -0
index 9db042304df3..90ccba7f9f9a 100644
@@ -769,6 +769,14 @@ static inline void __iomem *ioremap_nocache(phys_addr_t offset, size_t size)
 }
 #endif
 
+#ifndef ioremap_uc
+#define ioremap_uc ioremap_uc
+static inline void __iomem *ioremap_uc(phys_addr_t offset, size_t size)
+{
+	return ioremap_nocache(offset, size);
+}
+#endif
+
 #ifndef ioremap_wc
 #define ioremap_wc ioremap_wc
 static inline void __iomem *ioremap_wc(phys_addr_t offset, size_t size)
Signature · 1 line
2.3.5
#308 lore raw

[tip:x86/mm] x86/mm: Add ioremap_uc() helper to map memory uncacheable (not UC-)

x86/mm: Add ioremap_uc() helper to map memory uncacheable (not UC-)
Commit-ID:  e4b6be33c28923d8cde53023e0888b1c5d1a9027
Gitweb:     http://git.kernel.org/tip/e4b6be33c28923d8cde53023e0888b1c5d1a9027
Author:     Luis R. Rodriguez <[email protected]>
AuthorDate: Mon, 11 May 2015 10:15:53 +0200
Committer:  Ingo Molnar <[email protected]>
CommitDate: Mon, 11 May 2015 10:38:45 +0200

x86/mm: Add ioremap_uc() helper to map memory uncacheable (not UC-)

ioremap_nocache() currently uses UC- by default. Our goal is to eventually make UC the default. Linux maps UC- to PCD=1, PWT=0 page attributes on non-PAT systems. Linux maps UC to PCD=1, PWT=1 page attributes on non-PAT systems. On non-PAT and PAT systems a WC MTRR has different effects on pages with either of these attributes. In order to help with a smooth transition its best to enable use of UC (PCD,1, PWT=1) on a region as that ensures a WC MTRR will have no effect on a region, this however requires us to have an way to declare a region as UC and we currently do not have a way to do this.

WC MTRR on non-PAT system with PCD=1, PWT=0 (UC-) yields WC. WC MTRR on non-PAT system with PCD=1, PWT=1 (UC) yields UC.

WC MTRR on PAT system with PCD=1, PWT=0 (UC-) yields WC. WC MTRR on PAT system with PCD=1, PWT=1 (UC) yields UC.

A flip of the default ioremap_nocache() behaviour from UC- to UC can therefore regress a memory region from effective memory type WC to UC if MTRRs are used. Use of MTRRs should be phased out and in the best case only arch_phys_wc_add() use will remain, even if this happens arch_phys_wc_add() will have an effect on non-PAT systems and changes to default ioremap_nocache() behaviour could regress drivers.

Now, ideally we'd use ioremap_nocache() on the regions in which we'd need uncachable memory types and avoid any MTRRs on those regions. There are however some restrictions on MTRRs use, such as the requirement of having the base and size of variable sized MTRRs to be powers of two, which could mean having to use a WC MTRR over a large area which includes a region in which write-combining effects are undesirable.

Add ioremap_uc() to help with the both phasing out of MTRR use and also provide a way to blacklist small WC undesirable regions in devices with mixed regions which are size-implicated to use large WC MTRRs. Use of ioremap_uc() helps phase out MTRR use by avoiding regressions with an eventual flip of default behaviour or ioremap_nocache() from UC- to UC.

Drivers working with WC MTRRs can use the below table to review and consider the use of ioremap*() and similar helpers to ensure appropriate behaviour long term even if default ioremap_nocache() behaviour changes from UC- to UC.

Although ioremap_uc() is being added we leave set_memory_uc() to use UC- as only initial memory type setup is required to be able to accommodate existing device drivers and phase out MTRR use. It should also be clarified that set_memory_uc() cannot be used with IO memory, even though its use will not return any errors, it really has no effect.

----------------------------------------------------------------------
MTRR Non-PAT PAT Linux ioremap value Effective memory type
----------------------------------------------------------------------

                                                    Non-PAT |  PAT
       PAT
       |PCD
       ||PWT
       |||
  WC   000      WB      _PAGE_CACHE_MODE_WB            WC   |   WC
  WC   001      WC      _PAGE_CACHE_MODE_WC            WC*  |   WC
  WC   010      UC-     _PAGE_CACHE_MODE_UC_MINUS      WC*  |   WC
  WC   011      UC      _PAGE_CACHE_MODE_UC            UC   |   UC

----------------------------------------------------------------------

Cc Andy Lutomirski <[email protected]>
Cc Antonino Daplas <[email protected]>
Cc Bjorn Helgaas <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc Dave Airlie <[email protected]>
Cc Davidlohr Bueso <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc Jean-Christophe Plagniol-Villard <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Mel Gorman <[email protected]>
Cc Mike Travis <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Suresh Siddha <[email protected]>
Cc Thierry Reding <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Tomi Valkeinen <[email protected]>
Cc Toshi Kani <[email protected]>
Cc Ville Syrjälä <[email protected]>
Cc Vlastimil Babka <[email protected]>
Cc Will Deacon <[email protected]>
---
 arch/x86/include/asm/io.h |  1 +
 arch/x86/mm/ioremap.c     | 36 +++++++++++++++++++++++++++++++++++-
 arch/x86/mm/pageattr.c    |  3 +++
 include/asm-generic/io.h  |  8 ++++++++
 4 files changed, 47 insertions(+), 1 deletion(-)
arch/x86/include/asm/io.h +1 -0
index 34a5b93..4afc05f 100644
@@ -177,6 +177,7 @@ static inline unsigned int isa_virt_to_bus(volatile void *address)
  * look at pci_iomap().
  */
 extern void __iomem *ioremap_nocache(resource_size_t offset, unsigned long size);
+extern void __iomem *ioremap_uc(resource_size_t offset, unsigned long size);
 extern void __iomem *ioremap_cache(resource_size_t offset, unsigned long size);
 extern void __iomem *ioremap_prot(resource_size_t offset, unsigned long size,
 				unsigned long prot_val);
arch/x86/mm/ioremap.c +35 -1
index 70e7444..a493bb8 100644
@@ -237,7 +237,8 @@ void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
 	 *	pat_enabled ? _PAGE_CACHE_MODE_UC : _PAGE_CACHE_MODE_UC_MINUS;
 	 *
 	 * Till we fix all X drivers to use ioremap_wc(), we will use
-	 * UC MINUS.
+	 * UC MINUS. Drivers that are certain they need or can already
+	 * be converted over to strong UC can use ioremap_uc().
 	 */
 	enum page_cache_mode pcm = _PAGE_CACHE_MODE_UC_MINUS;
 
@@ -247,6 +248,39 @@ void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
 EXPORT_SYMBOL(ioremap_nocache);
 
 /**
+ * ioremap_uc     -   map bus memory into CPU space as strongly uncachable
+ * @phys_addr:    bus address of the memory
+ * @size:      size of the resource to map
+ *
+ * ioremap_uc performs a platform specific sequence of operations to
+ * make bus memory CPU accessible via the readb/readw/readl/writeb/
+ * writew/writel functions and the other mmio helpers. The returned
+ * address is not guaranteed to be usable directly as a virtual
+ * address.
+ *
+ * This version of ioremap ensures that the memory is marked with a strong
+ * preference as completely uncachable on the CPU when possible. For non-PAT
+ * systems this ends up setting page-attribute flags PCD=1, PWT=1. For PAT
+ * systems this will set the PAT entry for the pages as strong UC.  This call
+ * will honor existing caching rules from things like the PCI bus. Note that
+ * there are other caches and buffers on many busses. In particular driver
+ * authors should read up on PCI writes.
+ *
+ * It's useful if some control registers are in such an area and
+ * write combining or read caching is not desirable:
+ *
+ * Must be freed with iounmap.
+ */
+void __iomem *ioremap_uc(resource_size_t phys_addr, unsigned long size)
+{
+	enum page_cache_mode pcm = _PAGE_CACHE_MODE_UC;
+
+	return __ioremap_caller(phys_addr, size, pcm,
+				__builtin_return_address(0));
+}
+EXPORT_SYMBOL_GPL(ioremap_uc);
+
+/**
  * ioremap_wc	-	map memory into CPU space write combined
  * @phys_addr:	bus address of the memory
  * @size:	size of the resource to map
arch/x86/mm/pageattr.c +3 -0
index 5ddd900..c77abd7 100644
@@ -1467,6 +1467,9 @@ int _set_memory_uc(unsigned long addr, int numpages)
 {
 	/*
 	 * for now UC MINUS. see comments in ioremap_nocache()
+	 * If you really need strong UC use ioremap_uc(), but note
+	 * that you cannot override IO areas with set_memory_*() as
+	 * these helpers cannot work with IO memory.
 	 */
 	return change_page_attr_set(&addr, numpages,
 				    cachemode2pgprot(_PAGE_CACHE_MODE_UC_MINUS),
include/asm-generic/io.h +8 -0
index 9db0423..90ccba7 100644
@@ -769,6 +769,14 @@ static inline void __iomem *ioremap_nocache(phys_addr_t offset, size_t size)
 }
 #endif
 
+#ifndef ioremap_uc
+#define ioremap_uc ioremap_uc
+static inline void __iomem *ioremap_uc(phys_addr_t offset, size_t size)
+{
+	return ioremap_nocache(offset, size);
+}
+#endif
+
 #ifndef ioremap_wc
 #define ioremap_wc ioremap_wc
 static inline void __iomem *ioremap_wc(phys_addr_t offset, size_t size)
maintainer
#309 lore raw

PATCH 1/1 x86/alternatives: Switch AMD F15h and later to the P6 NOPs

In reply to Borislav Petkov

From: Borislav Petkov <[email protected]>

Software optimization guides for both F15h and F16h cite those NOPs as the optimal ones. A microbenchmark confirms that actually even older families are better with the single-insn NOPs so switch to them for the alternatives.

Cycles count below includes the loop overhead of the measurement but that overhead is the same with all runs.

F10h, revE:
-----------
Running NOP tests, 1000 NOPs x 1000000 repetitions

K8:

                      90     288.212282 cycles
                   66 90     288.220840 cycles
                66 66 90     288.219447 cycles
             66 66 66 90     288.223204 cycles
          66 66 90 66 90     571.393424 cycles
       66 66 90 66 66 90     571.374919 cycles
    66 66 66 90 66 66 90     572.249281 cycles
 66 66 66 90 66 66 66 90     571.388651 cycles

P6:

                      90     288.214193 cycles
                   66 90     288.225550 cycles
                0f 1f 00     288.224441 cycles
             0f 1f 40 00     288.225030 cycles
          0f 1f 44 00 00     288.233558 cycles
       66 0f 1f 44 00 00     324.792342 cycles
    0f 1f 80 00 00 00 00     325.657462 cycles
 0f 1f 84 00 00 00 00 00     430.246643 cycles

F14h:
----
Running NOP tests, 1000 NOPs x 1000000 repetitions

K8:

                      90     510.404890 cycles
                   66 90     510.432117 cycles
                66 66 90     510.561858 cycles
             66 66 66 90     510.541865 cycles
          66 66 90 66 90    1014.192782 cycles
       66 66 90 66 66 90    1014.226546 cycles
    66 66 66 90 66 66 90    1014.334299 cycles
 66 66 66 90 66 66 66 90    1014.381205 cycles

P6:

                      90     510.436710 cycles
                   66 90     510.448229 cycles
                0f 1f 00     510.545100 cycles
             0f 1f 40 00     510.502792 cycles
          0f 1f 44 00 00     510.589517 cycles
       66 0f 1f 44 00 00     510.611462 cycles
    0f 1f 80 00 00 00 00     511.166794 cycles
 0f 1f 84 00 00 00 00 00     511.651641 cycles

F15h:
-----
Running NOP tests, 1000 NOPs x 1000000 repetitions

K8:

                      90     243.128396 cycles
                   66 90     243.129883 cycles
                66 66 90     243.131631 cycles
             66 66 66 90     242.499324 cycles
          66 66 90 66 90     481.829083 cycles
       66 66 90 66 66 90     481.884413 cycles
    66 66 66 90 66 66 90     481.851446 cycles
 66 66 66 90 66 66 66 90     481.409220 cycles

P6:

                      90     243.127026 cycles
                   66 90     243.130711 cycles
                0f 1f 00     243.122747 cycles
             0f 1f 40 00     242.497617 cycles
          0f 1f 44 00 00     245.354461 cycles
       66 0f 1f 44 00 00     361.930417 cycles
    0f 1f 80 00 00 00 00     362.844944 cycles
 0f 1f 84 00 00 00 00 00     480.514948 cycles

F16h:
-----
Running NOP tests, 1000 NOPs x 1000000 repetitions

K8:

                      90     507.793298 cycles
                   66 90     507.789636 cycles
                66 66 90     507.826490 cycles
             66 66 66 90     507.859075 cycles
          66 66 90 66 90    1008.663129 cycles
       66 66 90 66 66 90    1008.696259 cycles
    66 66 66 90 66 66 90    1008.692517 cycles
 66 66 66 90 66 66 66 90    1008.755399 cycles

P6:

                      90     507.795232 cycles
                   66 90     507.794761 cycles
                0f 1f 00     507.834901 cycles
             0f 1f 40 00     507.822629 cycles
          0f 1f 44 00 00     507.838493 cycles
       66 0f 1f 44 00 00     507.908597 cycles
    0f 1f 80 00 00 00 00     507.946417 cycles
 0f 1f 84 00 00 00 00 00     507.954960 cycles
Cc Aravind Gopalakrishnan <[email protected]>
---
 arch/x86/kernel/alternative.c | 9 +++++++++
 1 file changed, 9 insertions(+)
arch/x86/kernel/alternative.c +9 -0
index aef653193160..b0932c4341b3 100644
@@ -227,6 +227,15 @@ void __init arch_init_ideal_nops(void)
 #endif
 		}
 		break;
+
+	case X86_VENDOR_AMD:
+		if (boot_cpu_data.x86 > 0xf) {
+			ideal_nops = p6_nops;
+			return;
+		}
+
+		/* fall through */
+
 	default:
 #ifdef CONFIG_X86_64
 		ideal_nops = k8_nops;
Signature · 1 line
2.3.5
#310 lore raw

[tip:x86/asm] x86/alternatives: Switch AMD F15h and later to the P6 NOPs

x86/alternatives: Switch AMD F15h and later to the P6 NOPs
Commit-ID:  f21262b8e092a770e39fbd405cc18a0247c3af68
Gitweb:     http://git.kernel.org/tip/f21262b8e092a770e39fbd405cc18a0247c3af68
Author:     Borislav Petkov <[email protected]>
AuthorDate: Mon, 11 May 2015 10:15:46 +0200
Committer:  Ingo Molnar <[email protected]>
CommitDate: Mon, 11 May 2015 10:26:05 +0200

x86/alternatives: Switch AMD F15h and later to the P6 NOPs

Software optimization guides for both F15h and F16h cite those NOPs as the optimal ones. A microbenchmark confirms that actually even older families are better with the single-insn NOPs so switch to them for the alternatives.

Cycles count below includes the loop overhead of the measurement but that overhead is the same with all runs.

	F10h, revE:
	-----------
	Running NOP tests, 1000 NOPs x 1000000 repetitions

	K8:
			      90     288.212282 cycles
			   66 90     288.220840 cycles
			66 66 90     288.219447 cycles
		     66 66 66 90     288.223204 cycles
		  66 66 90 66 90     571.393424 cycles
	       66 66 90 66 66 90     571.374919 cycles
	    66 66 66 90 66 66 90     572.249281 cycles
	 66 66 66 90 66 66 66 90     571.388651 cycles

	P6:
			      90     288.214193 cycles
			   66 90     288.225550 cycles
			0f 1f 00     288.224441 cycles
		     0f 1f 40 00     288.225030 cycles
		  0f 1f 44 00 00     288.233558 cycles
	       66 0f 1f 44 00 00     324.792342 cycles
	    0f 1f 80 00 00 00 00     325.657462 cycles
	 0f 1f 84 00 00 00 00 00     430.246643 cycles

	F14h:
	----
	Running NOP tests, 1000 NOPs x 1000000 repetitions

	K8:
			      90     510.404890 cycles
			   66 90     510.432117 cycles
			66 66 90     510.561858 cycles
		     66 66 66 90     510.541865 cycles
		  66 66 90 66 90    1014.192782 cycles
	       66 66 90 66 66 90    1014.226546 cycles
	    66 66 66 90 66 66 90    1014.334299 cycles
	 66 66 66 90 66 66 66 90    1014.381205 cycles

	P6:
			      90     510.436710 cycles
			   66 90     510.448229 cycles
			0f 1f 00     510.545100 cycles
		     0f 1f 40 00     510.502792 cycles
		  0f 1f 44 00 00     510.589517 cycles
	       66 0f 1f 44 00 00     510.611462 cycles
	    0f 1f 80 00 00 00 00     511.166794 cycles
	 0f 1f 84 00 00 00 00 00     511.651641 cycles

	F15h:
	-----
	Running NOP tests, 1000 NOPs x 1000000 repetitions

	K8:
			      90     243.128396 cycles
			   66 90     243.129883 cycles
			66 66 90     243.131631 cycles
		     66 66 66 90     242.499324 cycles
		  66 66 90 66 90     481.829083 cycles
	       66 66 90 66 66 90     481.884413 cycles
	    66 66 66 90 66 66 90     481.851446 cycles
	 66 66 66 90 66 66 66 90     481.409220 cycles

	P6:
			      90     243.127026 cycles
			   66 90     243.130711 cycles
			0f 1f 00     243.122747 cycles
		     0f 1f 40 00     242.497617 cycles
		  0f 1f 44 00 00     245.354461 cycles
	       66 0f 1f 44 00 00     361.930417 cycles
	    0f 1f 80 00 00 00 00     362.844944 cycles
	 0f 1f 84 00 00 00 00 00     480.514948 cycles

	F16h:
	-----
	Running NOP tests, 1000 NOPs x 1000000 repetitions

	K8:
			      90     507.793298 cycles
			   66 90     507.789636 cycles
			66 66 90     507.826490 cycles
		     66 66 66 90     507.859075 cycles
		  66 66 90 66 90    1008.663129 cycles
	       66 66 90 66 66 90    1008.696259 cycles
	    66 66 66 90 66 66 90    1008.692517 cycles
	 66 66 66 90 66 66 66 90    1008.755399 cycles

	P6:
			      90     507.795232 cycles
			   66 90     507.794761 cycles
			0f 1f 00     507.834901 cycles
		     0f 1f 40 00     507.822629 cycles
		  0f 1f 44 00 00     507.838493 cycles
	       66 0f 1f 44 00 00     507.908597 cycles
	    0f 1f 80 00 00 00 00     507.946417 cycles
	 0f 1f 84 00 00 00 00 00     507.954960 cycles
Cc Andy Lutomirski <[email protected]>
Cc Aravind Gopalakrishnan <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/kernel/alternative.c | 9 +++++++++
 1 file changed, 9 insertions(+)
arch/x86/kernel/alternative.c +9 -0
index aef6531..b0932c4 100644
@@ -227,6 +227,15 @@ void __init arch_init_ideal_nops(void)
 #endif
 		}
 		break;
+
+	case X86_VENDOR_AMD:
+		if (boot_cpu_data.x86 > 0xf) {
+			ideal_nops = p6_nops;
+			return;
+		}
+
+		/* fall through */
+
 	default:
 #ifdef CONFIG_X86_64
 		ideal_nops = k8_nops;
#311 lore raw

v5 cover mtrr, mm, x86: Enhance MTRR checks for huge I/O mapping

This patchset enhances MTRR checks for the kernel huge I/O mapping.

The following functional changes are made in patch 6/6.
- Allow pud_set_huge() and pmd_set_huge() to create a huge page mapping when the range is covered by a single MTRR entry of any memory type.
- Log a pr_warn_once() message when a specified PMD map range spans more than a single MTRR entry. Drivers should make a mapping request aligned to a single MTRR entry when the range is covered by MTRRs.

Patch 1/6 simplifies the condition of HAVE_ARCH_HUGE_VMAP in Kconfig. Patch 2/6 - 5/6 are bug fix and clean up to mtrr_type_lookup().

The patchset is based on the tip tree.
---
v5:
- Separate Kconfig change and reordered/squashed the patchset. (Borislav Petkov)
- Update logs, comments and functional structures. (Borislav Petkov)
- Move MTRR_STATE_MTRR_XXX definitions to kernel asm/mtrr.h. (Borislav Petkov)
- Change mtrr_type_lookup() not to set 'uniform' in case of MTRR_TYPE_INVALID. (Borislav Petkov)
- Remove a patch accepted in the tip free from the series.

v4:
- Update the change logs of patchset. (Ingo Molnar)
- Add patch 3/7 to make the wrong address fix as a separate patch. (Ingo Molnar)
- Add patch 5/7 to define MTRR_TYPE_INVALID. (Ingo Molnar)
- Update patch 6/7 to document MTRR fixed ranges. (Ingo Molnar)

v3:
- Add patch 3/5 to fix a bug in MTRR state checks.
- Update patch 4/5 to create separate functions for the fixed and variable entries. (Ingo Molnar)

v2:
- Update change logs and comments per review comments. (Ingo Molnar)
- Add patch 3/4 to clean up mtrr_type_lookup(). (Ingo Molnar)

---
Toshi Kani (6):
1/6 mm, x86: Simplify conditions of HAVE_ARCH_HUGE_VMAP 2/6 mtrr, x86: Fix MTRR lookup to handle inclusive entry 3/6 mtrr, x86: Fix MTRR state checks in mtrr_type_lookup() 4/6 mtrr, x86: Define MTRR_TYPE_INVALID for mtrr_type_lookup() 5/6 mtrr, x86: Clean up mtrr_type_lookup()
6/6 mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

---
 arch/x86/Kconfig                   |   2 +-
 arch/x86/include/asm/mtrr.h        |  10 +-
 arch/x86/include/uapi/asm/mtrr.h   |   8 +-
 arch/x86/kernel/cpu/mtrr/cleanup.c |   3 +-
 arch/x86/kernel/cpu/mtrr/generic.c | 200 ++++++++++++++++++++++++-------------
 arch/x86/mm/pat.c                  |   4 +-
 arch/x86/mm/pgtable.c              |  59 ++++++++---
 7 files changed, 194 insertions(+), 92 deletions(-)

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#312 lore raw

PATCH v5 1/6 mm, x86: Simplify conditions of HAVE_ARCH_HUGE_VMAP

Simplify the conditions to select HAVE_ARCH_HUGE_VMAP in arch/x86/Kconfig since X86_PAE depends on X86_32.

---
 arch/x86/Kconfig |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/Kconfig +1 -1
index 8fec044..73a4d03 100644
@@ -100,7 +100,7 @@ config X86
 	select IRQ_FORCED_THREADING
 	select HAVE_BPF_JIT if X86_64
 	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
-	select HAVE_ARCH_HUGE_VMAP if X86_64 || (X86_32 && X86_PAE)
+	select HAVE_ARCH_HUGE_VMAP if X86_64 || X86_PAE
 	select ARCH_HAS_SG_CHAIN
 	select CLKEVT_I8253
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer Applied
#313 lore raw

Re: [PATCH v5 1/6] mm, x86: Simplify conditions of HAVE_ARCH_HUGE_VMAP

Quoted 13 lines · Toshi Kani

Simplify the conditions to select HAVE_ARCH_HUGE_VMAP in arch/x86/Kconfig since X86_PAE depends on X86_32.

---
 arch/x86/Kconfig |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/Kconfig +0 -0
index 8fec044..73a4d03 100644

arch/x86/Kconfig config X86 · line 106

Quoted 8 lines
arch/x86/Kconfig +1 -1
@@ -100,7 +100,7 @@ config X86
 	select IRQ_FORCED_THREADING
 	select HAVE_BPF_JIT if X86_64
 	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
-	select HAVE_ARCH_HUGE_VMAP if X86_64 || (X86_32 && X86_PAE)
+	select HAVE_ARCH_HUGE_VMAP if X86_64 || X86_PAE
 	select ARCH_HAS_SG_CHAIN
 	select CLKEVT_I8253
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG

Applied, thanks.

Signature · 5 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#314 lore raw

PATCH v5 2/6 mtrr, x86: Fix MTRR lookup to handle inclusive entry

In reply to Toshi Kani

When an MTRR entry is inclusive to a requested range, i.e. the start and end of the request are not within the MTRR entry range but the range contains the MTRR entry entirely, __mtrr_type_lookup() ignores such a case because both start_state and end_state are set to zero.

This bug can cause the following issues:
1) reserve_memtype() tracks an effective memory type in case a request type is WB (ex. /dev/mem blindly uses WB). Missing to track with its effective type causes a subsequent request to map the same range with the effective type to fail.
2) pud_set_huge() and pmd_set_huge() check if a requested range has any overlap with MTRRs. Missing to detect an overlap may cause a performance penalty or undefined behavior.

This patch fixes the bug by adding a new flag, 'inclusive', to detect the inclusive case. This case is then handled in the same way as end_state:1 since the first region is the same. With this fix, __mtrr_type_lookup() handles the inclusive case properly.

---
 arch/x86/kernel/cpu/mtrr/generic.c |   28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)
arch/x86/kernel/cpu/mtrr/generic.c +18 -10
index 5b23967..e202d26 100644
@@ -154,7 +154,7 @@ static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
 
 	prev_match = 0xFF;
 	for (i = 0; i < num_var_ranges; ++i) {
-		unsigned short start_state, end_state;
+		unsigned short start_state, end_state, inclusive;
 
 		if (!(mtrr_state.var_ranges[i].mask_lo & (1 << 11)))
 			continue;
@@ -166,19 +166,27 @@ static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
 
 		start_state = ((start & mask) == (base & mask));
 		end_state = ((end & mask) == (base & mask));
+		inclusive = ((start < base) && (end > base));
 
-		if (start_state != end_state) {
+		if ((start_state != end_state) || inclusive) {
 			/*
 			 * We have start:end spanning across an MTRR.
-			 * We split the region into
-			 * either
-			 * (start:mtrr_end) (mtrr_end:end)
-			 * or
-			 * (start:mtrr_start) (mtrr_start:end)
+			 * We split the region into either
+			 *
+			 * - start_state:1
+			 * (start:mtrr_end)(mtrr_end:end)
+			 * - end_state:1
+			 * (start:mtrr_start)(mtrr_start:end)
+			 * - inclusive:1
+			 * (start:mtrr_start)(mtrr_start:mtrr_end)(mtrr_end:end)
+			 *
 			 * depending on kind of overlap.
-			 * Return the type for first region and a pointer to
-			 * the start of second region so that caller will
-			 * lookup again on the second region.
+			 *
+			 * Return the type of the first region and a pointer
+			 * to the start of next region so that caller will be
+			 * advised to lookup again after having adjusted start
+			 * and end.
+			 *
 			 * Note: This way we handle multiple overlaps as well.
 			 */
 			if (start_state)

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#315 lore raw

PATCH v5 3/6 mtrr, x86: Fix MTRR state checks in mtrr_type_lookup()

In reply to Toshi Kani

'mtrr_state.enabled' contains the FE (fixed MTRRs enabled) and E (MTRRs enabled) flags in MSR_MTRRdefType. Intel SDM, section 11.11.2.1, defines these flags as follows:
- All MTRRs are disabled when the E flag is clear. The FE flag has no affect when the E flag is clear.
- The default type is enabled when the E flag is set.
- MTRR variable ranges are enabled when the E flag is set.
- MTRR fixed ranges are enabled when both E and FE flags are set.

MTRR state checks in __mtrr_type_lookup() do not match with SDM. Hence, this patch makes the following changes:
- The current code detects MTRRs disabled when both E and FE flags are clear in mtrr_state.enabled. Fix to detect MTRRs disabled when the E flag is clear.
- The current code does not check if the FE bit is set in mtrr_state.enabled when looking into the fixed entries. Fix to check the FE flag.
- The current code returns the default type when the E flag is clear in mtrr_state.enabled. However, the default type is also disabled when the E flag is clear. Fix to remove the code as this case is handled as MTRR disabled with the 1st change.

In addition, this patch defines the E and FE flags in mtrr_state.enabled as follows.
- FE flag: MTRR_STATE_MTRR_FIXED_ENABLED
- E flag: MTRR_STATE_MTRR_ENABLED

print_mtrr_state() and x86_get_mtrr_mem_range() are also updated accordingly.

---
 arch/x86/include/asm/mtrr.h        |    4 ++++
 arch/x86/kernel/cpu/mtrr/cleanup.c |    3 ++-
 arch/x86/kernel/cpu/mtrr/generic.c |   15 ++++++++-------
 3 files changed, 14 insertions(+), 8 deletions(-)
arch/x86/include/asm/mtrr.h +4 -0
index f768f62..ef92794 100644
@@ -127,4 +127,8 @@ struct mtrr_gentry32 {
 				 _IOW(MTRR_IOCTL_BASE,  9, struct mtrr_sentry32)
 #endif /* CONFIG_COMPAT */
 
+/* Bit fields for enabled in struct mtrr_state_type */
+#define MTRR_STATE_MTRR_FIXED_ENABLED	0x01
+#define MTRR_STATE_MTRR_ENABLED		0x02
+
 #endif /* _ASM_X86_MTRR_H */
arch/x86/kernel/cpu/mtrr/cleanup.c +2 -1
index 5f90b85..70d7c93 100644
@@ -98,7 +98,8 @@ x86_get_mtrr_mem_range(struct range *range, int nr_range,
 			continue;
 		base = range_state[i].base_pfn;
 		if (base < (1<<(20-PAGE_SHIFT)) && mtrr_state.have_fixed &&
-		    (mtrr_state.enabled & 1)) {
+		    (mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED) &&
+		    (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) {
 			/* Var MTRR contains UC entry below 1M? Skip it: */
 			printk(BIOS_BUG_MSG, i);
 			if (base + size <= (1<<(20-PAGE_SHIFT)))
arch/x86/kernel/cpu/mtrr/generic.c +8 -7
index e202d26..b0599db 100644
@@ -119,14 +119,16 @@ static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
 	if (!mtrr_state_set)
 		return 0xFF;
 
-	if (!mtrr_state.enabled)
+	if (!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED))
 		return 0xFF;
 
 	/* Make end inclusive end, instead of exclusive */
 	end--;
 
 	/* Look in fixed ranges. Just return the type as per start */
-	if (mtrr_state.have_fixed && (start < 0x100000)) {
+	if ((start < 0x100000) &&
+	    (mtrr_state.have_fixed) &&
+	    (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) {
 		int idx;
 
 		if (start < 0x80000) {
@@ -149,9 +151,6 @@ static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
 	 * Look of multiple ranges matching this address and pick type
 	 * as per MTRR precedence
 	 */
-	if (!(mtrr_state.enabled & 2))
-		return mtrr_state.def_type;
-
 	prev_match = 0xFF;
 	for (i = 0; i < num_var_ranges; ++i) {
 		unsigned short start_state, end_state, inclusive;
@@ -355,7 +354,9 @@ static void __init print_mtrr_state(void)
 		 mtrr_attrib_to_str(mtrr_state.def_type));
 	if (mtrr_state.have_fixed) {
 		pr_debug("MTRR fixed ranges %sabled:\n",
-			 mtrr_state.enabled & 1 ? "en" : "dis");
+			((mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED) &&
+			 (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) ?
+			 "en" : "dis");
 		print_fixed(0x00000, 0x10000, mtrr_state.fixed_ranges + 0);
 		for (i = 0; i < 2; ++i)
 			print_fixed(0x80000 + i * 0x20000, 0x04000,
@@ -368,7 +369,7 @@ static void __init print_mtrr_state(void)
 		print_fixed_last();
 	}
 	pr_debug("MTRR variable ranges %sabled:\n",
-		 mtrr_state.enabled & 2 ? "en" : "dis");
+		 mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED ? "en" : "dis");
 	high_width = (__ffs64(size_or_mask) - (32 - PAGE_SHIFT) + 3) / 4;
 
 	for (i = 0; i < num_var_ranges; ++i) {

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#316 lore raw

PATCH v5 4/6 mtrr, x86: Define MTRR_TYPE_INVALID for mtrr_type_lookup()

In reply to Toshi Kani

mtrr_type_lookup() returns 0xFF when it cannot return a valid MTRR memory type since MTRRs are disabled. This patch defines MTRR_TYPE_INVALID to clarify the meaning of this value, and documents its usage.

Document the return values of Kernel Virtual Address mapping functions, pud_set_huge(), pmd_set_huge, pud_clear_huge() and pmd_clear_huge().

There is no functional change in this patch.

---
 arch/x86/include/asm/mtrr.h        |    2 +-
 arch/x86/include/uapi/asm/mtrr.h   |    8 ++++++-
 arch/x86/kernel/cpu/mtrr/generic.c |   14 ++++++------
 arch/x86/mm/pgtable.c              |   42 +++++++++++++++++++++++++++---------
 4 files changed, 47 insertions(+), 19 deletions(-)
arch/x86/include/asm/mtrr.h +1 -1
index ef92794..bb03a54 100644
@@ -55,7 +55,7 @@ static inline u8 mtrr_type_lookup(u64 addr, u64 end)
 	/*
 	 * Return no-MTRRs:
 	 */
-	return 0xff;
+	return MTRR_TYPE_INVALID;
 }
 #define mtrr_save_fixed_ranges(arg) do {} while (0)
 #define mtrr_save_state() do {} while (0)
arch/x86/include/uapi/asm/mtrr.h +7 -1
index d0acb65..7528dcf 100644
@@ -103,7 +103,7 @@ struct mtrr_state_type {
 #define MTRRIOC_GET_PAGE_ENTRY   _IOWR(MTRR_IOCTL_BASE, 8, struct mtrr_gentry)
 #define MTRRIOC_KILL_PAGE_ENTRY  _IOW(MTRR_IOCTL_BASE,  9, struct mtrr_sentry)
 
-/*  These are the region types  */
+/* MTRR memory types, which are defined in SDM */
 #define MTRR_TYPE_UNCACHABLE 0
 #define MTRR_TYPE_WRCOMB     1
 /*#define MTRR_TYPE_         2*/
@@ -113,5 +113,11 @@ struct mtrr_state_type {
 #define MTRR_TYPE_WRBACK     6
 #define MTRR_NUM_TYPES       7
 
+/*
+ * Invalid MTRR memory type.  mtrr_type_lookup() returns this value when
+ * MTRRs are disabled.  Note, this value is allocated from the reserved
+ * values (0x7-0xff) of the MTRR memory types.
+ */
+#define MTRR_TYPE_INVALID    0xff
 
 #endif /* _UAPI_ASM_X86_MTRR_H */
arch/x86/kernel/cpu/mtrr/generic.c +7 -7
index b0599db..7b1491c 100644
@@ -104,7 +104,7 @@ static int check_type_overlap(u8 *prev, u8 *curr)
 
 /*
  * Error/Semi-error returns:
- * 0xFF - when MTRR is not enabled
+ * MTRR_TYPE_INVALID - when MTRR is not enabled
  * *repeat == 1 implies [start:end] spanned across MTRR range and type returned
  *		corresponds only to [start:*partial_end].
  *		Caller has to lookup again for [*partial_end:end].
@@ -117,10 +117,10 @@ static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
 
 	*repeat = 0;
 	if (!mtrr_state_set)
-		return 0xFF;
+		return MTRR_TYPE_INVALID;
 
 	if (!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED))
-		return 0xFF;
+		return MTRR_TYPE_INVALID;
 
 	/* Make end inclusive end, instead of exclusive */
 	end--;
@@ -151,7 +151,7 @@ static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
 	 * Look of multiple ranges matching this address and pick type
 	 * as per MTRR precedence
 	 */
-	prev_match = 0xFF;
+	prev_match = MTRR_TYPE_INVALID;
 	for (i = 0; i < num_var_ranges; ++i) {
 		unsigned short start_state, end_state, inclusive;
 
@@ -206,7 +206,7 @@ static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
 			continue;
 
 		curr_match = mtrr_state.var_ranges[i].base_lo & 0xff;
-		if (prev_match == 0xFF) {
+		if (prev_match == MTRR_TYPE_INVALID) {
 			prev_match = curr_match;
 			continue;
 		}
@@ -220,7 +220,7 @@ static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
 			return MTRR_TYPE_WRBACK;
 	}
 
-	if (prev_match != 0xFF)
+	if (prev_match != MTRR_TYPE_INVALID)
 		return prev_match;
 
 	return mtrr_state.def_type;
@@ -229,7 +229,7 @@ static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
 /*
  * Returns the effective MTRR type for the region
  * Error return:
- * 0xFF - when MTRR is not enabled
+ * MTRR_TYPE_INVALID - when MTRR is not enabled
  */
 u8 mtrr_type_lookup(u64 start, u64 end)
 {
arch/x86/mm/pgtable.c +32 -10

76 lines not on this page · raw message

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#317 lore raw

PATCH v5 5/6 mtrr, x86: Clean up mtrr_type_lookup()

In reply to Toshi Kani

MTRRs contain fixed and variable entries. mtrr_type_lookup() may repeatedly call __mtrr_type_lookup() to handle a request that overlaps with variable entries. However, __mtrr_type_lookup() also handles the fixed entries, which do not have to be repeated. Therefore, this patch creates separate functions, mtrr_type_lookup_fixed() and mtrr_type_lookup_variable(), to handle the fixed and variable ranges respectively.

The patch also updates the function headers to clarify the return values and output argument. It updates comments to clarify that the repeating is necessary to handle overlaps with the default type, since overlaps with multiple entries alone can be handled without such repeating.

There is no functional change in this patch.

---
 arch/x86/kernel/cpu/mtrr/generic.c |  136 +++++++++++++++++++++++-------------
 1 file changed, 85 insertions(+), 51 deletions(-)
arch/x86/kernel/cpu/mtrr/generic.c +85 -51
index 7b1491c..c7d5245 100644
@@ -102,55 +102,67 @@ static int check_type_overlap(u8 *prev, u8 *curr)
 	return 0;
 }
 
-/*
- * Error/Semi-error returns:
- * MTRR_TYPE_INVALID - when MTRR is not enabled
- * *repeat == 1 implies [start:end] spanned across MTRR range and type returned
- *		corresponds only to [start:*partial_end].
- *		Caller has to lookup again for [*partial_end:end].
+/**
+ * mtrr_type_lookup_fixed - look up memory type in MTRR fixed entries
+ *
+ * Return the MTRR fixed memory type of 'start'.
+ *
+ * MTRR fixed entries are divided into the following ways:
+ *  0x00000 - 0x7FFFF : This range is divided into eight 64KB sub-ranges
+ *  0x80000 - 0xBFFFF : This range is divided into sixteen 16KB sub-ranges
+ *  0xC0000 - 0xFFFFF : This range is divided into sixty-four 4KB sub-ranges
+ *
+ * Return Values:
+ * MTRR_TYPE_(type)  - Matched memory type
+ * MTRR_TYPE_INVALID - Unmatched
  */
-static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
+static u8 mtrr_type_lookup_fixed(u64 start, u64 end)
+{
+	int idx;
+
+	if (start >= 0x100000)
+		return MTRR_TYPE_INVALID;
+
+	if (start < 0x80000) {		/* 0x0 - 0x7FFFF */
+		idx = 0;
+		idx += (start >> 16);
+		return mtrr_state.fixed_ranges[idx];
+
+	} else if (start < 0xC0000) {	/* 0x80000 - 0xBFFFF */
+		idx = 1 * 8;
+		idx += ((start - 0x80000) >> 14);
+		return mtrr_state.fixed_ranges[idx];
+	}
+
+	/* 0xC0000 - 0xFFFFF */
+	idx = 3 * 8;
+	idx += ((start - 0xC0000) >> 12);
+	return mtrr_state.fixed_ranges[idx];
+}
+
+/**
+ * mtrr_type_lookup_variable - look up memory type in MTRR variable entries
+ *
+ * Return Value:
+ * MTRR_TYPE_(type) - Matched memory type or default memory type (unmatched)
+ *
+ * Output Argument:
+ * repeat - Set to 1 when [start:end] spanned across MTRR range and type
+ *	    returned corresponds only to [start:*partial_end].  Caller has
+ *	    to lookup again for [*partial_end:end].
+ */
+static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
+				    int *repeat)
 {
 	int i;
 	u64 base, mask;
 	u8 prev_match, curr_match;
 
 	*repeat = 0;
-	if (!mtrr_state_set)
-		return MTRR_TYPE_INVALID;
-
-	if (!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED))
-		return MTRR_TYPE_INVALID;
 
 	/* Make end inclusive end, instead of exclusive */
 	end--;
 
-	/* Look in fixed ranges. Just return the type as per start */
-	if ((start < 0x100000) &&
-	    (mtrr_state.have_fixed) &&
-	    (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) {
-		int idx;
-
-		if (start < 0x80000) {
-			idx = 0;
-			idx += (start >> 16);
-			return mtrr_state.fixed_ranges[idx];
-		} else if (start < 0xC0000) {
-			idx = 1 * 8;
-			idx += ((start - 0x80000) >> 14);
-			return mtrr_state.fixed_ranges[idx];
-		} else {
-			idx = 3 * 8;
-			idx += ((start - 0xC0000) >> 12);
-			return mtrr_state.fixed_ranges[idx];
-		}
-	}
-
-	/*
-	 * Look in variable ranges
-	 * Look of multiple ranges matching this address and pick type
-	 * as per MTRR precedence
-	 */
 	prev_match = MTRR_TYPE_INVALID;
 	for (i = 0; i < num_var_ranges; ++i) {
 		unsigned short start_state, end_state, inclusive;
@@ -186,7 +198,8 @@ static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
 			 * advised to lookup again after having adjusted start
 			 * and end.
 			 *
-			 * Note: This way we handle multiple overlaps as well.
+			 * Note: This way we handle overlaps with multiple
+			 * entries and the default type properly.
 			 */
 			if (start_state)
 				*partial_end = base + get_mtrr_size(mask);
@@ -215,21 +228,18 @@ static u8 __mtrr_type_lookup(u64 start, u64 end, u64 *partial_end, int *repeat)
 			return curr_match;
 	}
 
-	if (mtrr_tom2) {
-		if (start >= (1ULL<<32) && (end < mtrr_tom2))
-			return MTRR_TYPE_WRBACK;
-	}
-
 	if (prev_match != MTRR_TYPE_INVALID)
 		return prev_match;
 
 	return mtrr_state.def_type;
 }
 
-/*
- * Returns the effective MTRR type for the region
- * Error return:
- * MTRR_TYPE_INVALID - when MTRR is not enabled
+/**
+ * mtrr_type_lookup - look up memory type in MTRR
+ *
+ * Return Values:
+ * MTRR_TYPE_(type)  - The effective MTRR type for the region
+ * MTRR_TYPE_INVALID - MTRR is disabled
  */
 u8 mtrr_type_lookup(u64 start, u64 end)
 {
@@ -237,22 +247,46 @@ u8 mtrr_type_lookup(u64 start, u64 end)
 	int repeat;
 	u64 partial_end;
 
-	type = __mtrr_type_lookup(start, end, &partial_end, &repeat);
+	if (!mtrr_state_set)
+		return MTRR_TYPE_INVALID;
+
+	if (!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED))
+		return MTRR_TYPE_INVALID;
+
+	/*
+	 * Look up the fixed ranges first, which take priority over
+	 * the variable ranges.
+	 */
+	if ((start < 0x100000) &&
+	    (mtrr_state.have_fixed) &&
+	    (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED))
+		return mtrr_type_lookup_fixed(start, end);
+
+	/*
+	 * Look up the variable ranges.  Look of multiple ranges matching
+	 * this address and pick type as per MTRR precedence.
+	 */
+	type = mtrr_type_lookup_variable(start, end, &partial_end, &repeat);
 
 	/*
 	 * Common path is with repeat = 0.
 	 * However, we can have cases where [start:end] spans across some
-	 * MTRR range. Do repeated lookups for that case here.
+	 * MTRR ranges and/or the default type.  Do repeated lookups for
+	 * that case here.
 	 */
 	while (repeat) {
 		prev_type = type;
 		start = partial_end;
-		type = __mtrr_type_lookup(start, end, &partial_end, &repeat);
+		type = mtrr_type_lookup_variable(start, end, &partial_end,
+						 &repeat);
 
 		if (check_type_overlap(&prev_type, &type))
 			return type;
 	}
 
+	if (mtrr_tom2 && (start >= (1ULL<<32)) && (end < mtrr_tom2))
+		return MTRR_TYPE_WRBACK;
+
 	return type;
 }
 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#318 lore raw

PATCH v5 6/6 mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

In reply to Toshi Kani

This patch adds an additional argument, 'uniform', to mtrr_type_lookup(), which returns 1 when a given range is covered uniformly by MTRRs, i.e. the range is fully covered by a single MTRR entry or the default type.

pud_set_huge() and pmd_set_huge() are changed to check the new 'uniform' flag to see if it is safe to create a huge page mapping to the range. This allows them to create a huge page mapping to a range covered by a single MTRR entry of any memory type. It also detects a non-optimal request properly. They continue to check with the WB type since the WB type has no effect even if a request spans multiple MTRR entries.

pmd_set_huge() logs a warning message to a non-optimal request so that driver writers will be aware of such a case. Drivers should make a mapping request aligned to a single MTRR entry when the range is covered by MTRRs.

---
 arch/x86/include/asm/mtrr.h        |    4 ++--
 arch/x86/kernel/cpu/mtrr/generic.c |   37 ++++++++++++++++++++++++++----------
 arch/x86/mm/pat.c                  |    4 ++--
 arch/x86/mm/pgtable.c              |   33 ++++++++++++++++++++------------
 4 files changed, 52 insertions(+), 26 deletions(-)
arch/x86/include/asm/mtrr.h +2 -2
index bb03a54..a31759e 100644
@@ -31,7 +31,7 @@
  * arch_phys_wc_add and arch_phys_wc_del.
  */
 # ifdef CONFIG_MTRR
-extern u8 mtrr_type_lookup(u64 addr, u64 end);
+extern u8 mtrr_type_lookup(u64 addr, u64 end, u8 *uniform);
 extern void mtrr_save_fixed_ranges(void *);
 extern void mtrr_save_state(void);
 extern int mtrr_add(unsigned long base, unsigned long size,
@@ -50,7 +50,7 @@ extern int mtrr_trim_uncached_memory(unsigned long end_pfn);
 extern int amd_special_default_mtrr(void);
 extern int phys_wc_to_mtrr_index(int handle);
 #  else
-static inline u8 mtrr_type_lookup(u64 addr, u64 end)
+static inline u8 mtrr_type_lookup(u64 addr, u64 end, u8 *uniform)
 {
 	/*
 	 * Return no-MTRRs:
arch/x86/kernel/cpu/mtrr/generic.c +27 -10
index c7d5245..7d347ac 100644
@@ -146,19 +146,22 @@ static u8 mtrr_type_lookup_fixed(u64 start, u64 end)
  * Return Value:
  * MTRR_TYPE_(type) - Matched memory type or default memory type (unmatched)
  *
- * Output Argument:
+ * Output Arguments:
  * repeat - Set to 1 when [start:end] spanned across MTRR range and type
  *	    returned corresponds only to [start:*partial_end].  Caller has
  *	    to lookup again for [*partial_end:end].
+ * uniform - Set to 1 when MTRR covers the region uniformly, i.e. the region
+ *	     is fully covered by a single MTRR entry or the default type.
  */
 static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
-				    int *repeat)
+				    int *repeat, u8 *uniform)
 {
 	int i;
 	u64 base, mask;
 	u8 prev_match, curr_match;
 
 	*repeat = 0;
+	*uniform = 1;
 
 	/* Make end inclusive end, instead of exclusive */
 	end--;
@@ -213,6 +216,7 @@ static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
 
 			end = *partial_end - 1; /* end is inclusive */
 			*repeat = 1;
+			*uniform = 0;
 		}
 
 		if ((start & mask) != (base & mask))
@@ -224,6 +228,7 @@ static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
 			continue;
 		}
 
+		*uniform = 0;
 		if (check_type_overlap(&prev_match, &curr_match))
 			return curr_match;
 	}
@@ -240,10 +245,14 @@ static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
  * Return Values:
  * MTRR_TYPE_(type)  - The effective MTRR type for the region
  * MTRR_TYPE_INVALID - MTRR is disabled
+ *
+ * Output Argument:
+ * uniform - Set to 1 when MTRR covers the region uniformly, i.e. the region
+ *	     is fully covered by a single MTRR entry or the default type.
  */
-u8 mtrr_type_lookup(u64 start, u64 end)
+u8 mtrr_type_lookup(u64 start, u64 end, u8 *uniform)
 {
-	u8 type, prev_type;
+	u8 type, prev_type, is_uniform = 1, dummy;
 	int repeat;
 	u64 partial_end;
 
@@ -259,14 +268,18 @@ u8 mtrr_type_lookup(u64 start, u64 end)
 	 */
 	if ((start < 0x100000) &&
 	    (mtrr_state.have_fixed) &&
-	    (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED))
-		return mtrr_type_lookup_fixed(start, end);
+	    (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) {
+		is_uniform = 0;
+		type = mtrr_type_lookup_fixed(start, end);
+		goto out;
+	}
 
 	/*
 	 * Look up the variable ranges.  Look of multiple ranges matching
 	 * this address and pick type as per MTRR precedence.
 	 */
-	type = mtrr_type_lookup_variable(start, end, &partial_end, &repeat);
+	type = mtrr_type_lookup_variable(start, end, &partial_end,
+					 &repeat, &is_uniform);
 
 	/*
 	 * Common path is with repeat = 0.
@@ -277,16 +290,20 @@ u8 mtrr_type_lookup(u64 start, u64 end)
 	while (repeat) {
 		prev_type = type;
 		start = partial_end;
+		is_uniform = 0;
+
 		type = mtrr_type_lookup_variable(start, end, &partial_end,
-						 &repeat);
+						 &repeat, &dummy);
 
 		if (check_type_overlap(&prev_type, &type))
-			return type;
+			goto out;
 	}
 
 	if (mtrr_tom2 && (start >= (1ULL<<32)) && (end < mtrr_tom2))
-		return MTRR_TYPE_WRBACK;
+		type = MTRR_TYPE_WRBACK;
 
+out:
+	*uniform = is_uniform;
 	return type;
 }
 
arch/x86/mm/pat.c +2 -2
index 35af677..372ad42 100644
@@ -267,9 +267,9 @@ static unsigned long pat_x_mtrr_type(u64 start, u64 end,
 	 * request is for WB.
 	 */
 	if (req_type == _PAGE_CACHE_MODE_WB) {
-		u8 mtrr_type;
+		u8 mtrr_type, uniform;
 
-		mtrr_type = mtrr_type_lookup(start, end);
+		mtrr_type = mtrr_type_lookup(start, end, &uniform);
 		if (mtrr_type != MTRR_TYPE_WRBACK)
 			return _PAGE_CACHE_MODE_UC_MINUS;
 
arch/x86/mm/pgtable.c +21 -12
index c30f981..3fa0eb9 100644
@@ -567,18 +567,21 @@ void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys,
  * pud_set_huge - setup kernel PUD mapping
  *
  * MTRR can override PAT memory types with 4KiB granularity.  Therefore,
- * this function does not set up a huge page when the range is covered
- * by a non-WB type of MTRR.  MTRR_TYPE_INVALID indicates that MTRR are
- * disabled.
+ * this function only sets up a huge page in the following conditions.
+ *  - MTRR is disabled.
+ *  - The range is mapped uniformly by MTRR, i.e. the range is fully covered
+ *    by a single MTRR entry or the default type.
+ *  - The MTRR memory type is WB.
  *
  * Returns 1 on success and 0 on failure.
  */
 int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot)
 {
-	u8 mtrr;
+	u8 mtrr, uniform;
 
-	mtrr = mtrr_type_lookup(addr, addr + PUD_SIZE);
-	if ((mtrr != MTRR_TYPE_WRBACK) && (mtrr != MTRR_TYPE_INVALID))
+	mtrr = mtrr_type_lookup(addr, addr + PUD_SIZE, &uniform);
+	if ((mtrr != MTRR_TYPE_INVALID) && (!uniform) &&
+	    (mtrr != MTRR_TYPE_WRBACK))
 		return 0;
 
 	prot = pgprot_4k_2_large(prot);
@@ -594,19 +597,25 @@ int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot)
  * pmd_set_huge - setup kernel PMD mapping
  *
  * MTRR can override PAT memory types with 4KiB granularity.  Therefore,
- * this function does not set up a huge page when the range is covered
- * by a non-WB type of MTRR.  MTRR_TYPE_INVALID indicates that MTRR are
- * disabled.
+ * this function only sets up a huge page in the following conditions.
+ *  - MTRR is disabled.
+ *  - The range is mapped uniformly by MTRR, i.e. the range is fully covered
+ *    by a single MTRR entry or the default type.
+ *  - The MTRR memory type is WB.
  *
  * Returns 1 on success and 0 on failure.
  */
 int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot)
 {
-	u8 mtrr;
+	u8 mtrr, uniform;
 
-	mtrr = mtrr_type_lookup(addr, addr + PMD_SIZE);
-	if ((mtrr != MTRR_TYPE_WRBACK) && (mtrr != MTRR_TYPE_INVALID))
+	mtrr = mtrr_type_lookup(addr, addr + PMD_SIZE, &uniform);
+	if ((mtrr != MTRR_TYPE_INVALID) && (!uniform) &&
+	    (mtrr != MTRR_TYPE_WRBACK)) {
+		pr_warn_once("pmd_set_huge: requesting [mem %#010llx-%#010llx], which spans more than a single MTRR entry\n",
+				addr, addr + PMD_SIZE);
 		return 0;
+	}
 
 	prot = pgprot_4k_2_large(prot);
 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#319 lore raw

Re: [PATCH v5 6/6] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 25 lines · Toshi Kani

This patch adds an additional argument, 'uniform', to mtrr_type_lookup(), which returns 1 when a given range is covered uniformly by MTRRs, i.e. the range is fully covered by a single MTRR entry or the default type.

pud_set_huge() and pmd_set_huge() are changed to check the new 'uniform' flag to see if it is safe to create a huge page mapping to the range. This allows them to create a huge page mapping to a range covered by a single MTRR entry of any memory type. It also detects a non-optimal request properly. They continue to check with the WB type since the WB type has no effect even if a request spans multiple MTRR entries.

pmd_set_huge() logs a warning message to a non-optimal request so that driver writers will be aware of such a case. Drivers should make a mapping request aligned to a single MTRR entry when the range is covered by MTRRs.

---
 arch/x86/include/asm/mtrr.h        |    4 ++--
 arch/x86/kernel/cpu/mtrr/generic.c |   37 ++++++++++++++++++++++++++----------
 arch/x86/mm/pat.c                  |    4 ++--
 arch/x86/mm/pgtable.c              |   33 ++++++++++++++++++++------------
 4 files changed, 52 insertions(+), 26 deletions(-)

...

Quoted 4 lines

int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot) {

(quoted diff) +1 -1
-	u8 mtrr;
+	u8 mtrr, uniform;

Review

Quoted 10 lines
(quoted diff) +6 -2
 
-	mtrr = mtrr_type_lookup(addr, addr + PMD_SIZE);
-	if ((mtrr != MTRR_TYPE_WRBACK) && (mtrr != MTRR_TYPE_INVALID))
+	mtrr = mtrr_type_lookup(addr, addr + PMD_SIZE, &uniform);
+	if ((mtrr != MTRR_TYPE_INVALID) && (!uniform) &&
+	    (mtrr != MTRR_TYPE_WRBACK)) {
+		pr_warn_once("pmd_set_huge: requesting [mem %#010llx-%#010llx], which spans more than a single MTRR entry\n",
+				addr, addr + PMD_SIZE);
 		return 0;
+	}

All applied, I reformatted the comments in this last one a bit and made the warning message hopefully a bit more descriptive:

---
From: Toshi Kani <[email protected]>
Date: Fri, 15 May 2015 12:23:57 -0600
Subject: [PATCH] x86/mm: Enhance MTRR checks in kernel mapping helpers

This patch adds the argument 'uniform' to mtrr_type_lookup(), which gets set to 1 when a given range is covered uniformly by MTRRs, i.e. the range is fully covered by a single MTRR entry or the default type.

Change pud_set_huge() and pmd_set_huge() to honor the 'uniform' flag to see if it is safe to create a huge page mapping in the range.

This allows them to create a huge page mapping in a range covered by a single MTRR entry of any memory type. It also detects a non-optimal request properly. They continue to check with the WB type since it does not effectively change the uniform mapping even if a request spans multiple MTRR entries.

pmd_set_huge() logs a warning message to a non-optimal request so that driver writers will be aware of such a case. Drivers should make a mapping request aligned to a single MTRR entry when the range is covered by MTRRs.

Cc Luis R. Rodriguez <[email protected]>
Cc Andrew Morton <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc linux-mm <[email protected]>
Cc x86-ml <[email protected]>
[ Realign comments, improve warning message. ]
---
 arch/x86/include/asm/mtrr.h        |  4 ++--
 arch/x86/kernel/cpu/mtrr/generic.c | 40 +++++++++++++++++++++++++++----------
 arch/x86/mm/pat.c                  |  4 ++--
 arch/x86/mm/pgtable.c              | 41 +++++++++++++++++++++++++-------------
 4 files changed, 61 insertions(+), 28 deletions(-)
arch/x86/include/asm/mtrr.h +2 -2
index bb03a547c1ab..a31759e1edd9 100644
@@ -31,7 +31,7 @@
  * arch_phys_wc_add and arch_phys_wc_del.
  */
 # ifdef CONFIG_MTRR
-extern u8 mtrr_type_lookup(u64 addr, u64 end);
+extern u8 mtrr_type_lookup(u64 addr, u64 end, u8 *uniform);
 extern void mtrr_save_fixed_ranges(void *);
 extern void mtrr_save_state(void);
 extern int mtrr_add(unsigned long base, unsigned long size,
@@ -50,7 +50,7 @@ extern int mtrr_trim_uncached_memory(unsigned long end_pfn);
 extern int amd_special_default_mtrr(void);
 extern int phys_wc_to_mtrr_index(int handle);
 #  else
-static inline u8 mtrr_type_lookup(u64 addr, u64 end)
+static inline u8 mtrr_type_lookup(u64 addr, u64 end, u8 *uniform)
 {
 	/*
 	 * Return no-MTRRs:
arch/x86/kernel/cpu/mtrr/generic.c +30 -10
index e51100c49eea..f782d9b62cb3 100644
@@ -147,19 +147,24 @@ static u8 mtrr_type_lookup_fixed(u64 start, u64 end)
  * Return Value:
  * MTRR_TYPE_(type) - Matched memory type or default memory type (unmatched)
  *
- * Output Argument:
+ * Output Arguments:
  * repeat - Set to 1 when [start:end] spanned across MTRR range and type
  *	    returned corresponds only to [start:*partial_end].  Caller has
  *	    to lookup again for [*partial_end:end].
+ *
+ * uniform - Set to 1 when an MTRR covers the region uniformly, i.e. the
+ *	     region is fully covered by a single MTRR entry or the default
+ *	     type.
  */
 static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
-				    int *repeat)
+				    int *repeat, u8 *uniform)
 {
 	int i;
 	u64 base, mask;
 	u8 prev_match, curr_match;
 
 	*repeat = 0;
+	*uniform = 1;
 
 	/* Make end inclusive instead of exclusive */
 	end--;
@@ -214,6 +219,7 @@ static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
 
 			end = *partial_end - 1; /* end is inclusive */
 			*repeat = 1;
+			*uniform = 0;
 		}
 
 		if ((start & mask) != (base & mask))
@@ -225,6 +231,7 @@ static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
 			continue;
 		}
 
+		*uniform = 0;
 		if (check_type_overlap(&prev_match, &curr_match))
 			return curr_match;
 	}
@@ -241,10 +248,15 @@ static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
  * Return Values:
  * MTRR_TYPE_(type)  - The effective MTRR type for the region
  * MTRR_TYPE_INVALID - MTRR is disabled
+ *
+ * Output Argument:
+ * uniform - Set to 1 when an MTRR covers the region uniformly, i.e. the
+ *	     region is fully covered by a single MTRR entry or the default
+ *	     type.
  */
-u8 mtrr_type_lookup(u64 start, u64 end)
+u8 mtrr_type_lookup(u64 start, u64 end, u8 *uniform)
 {
-	u8 type, prev_type;
+	u8 type, prev_type, is_uniform = 1, dummy;
 	int repeat;
 	u64 partial_end;
 
@@ -260,14 +272,18 @@ u8 mtrr_type_lookup(u64 start, u64 end)
 	 */
 	if ((start < 0x100000) &&
 	    (mtrr_state.have_fixed) &&
-	    (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED))
-		return mtrr_type_lookup_fixed(start, end);
+	    (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) {
+		is_uniform = 0;
+		type = mtrr_type_lookup_fixed(start, end);
+		goto out;
+	}
 
 	/*
 	 * Look up the variable ranges.  Look of multiple ranges matching
 	 * this address and pick type as per MTRR precedence.
 	 */
-	type = mtrr_type_lookup_variable(start, end, &partial_end, &repeat);
+	type = mtrr_type_lookup_variable(start, end, &partial_end,
+					 &repeat, &is_uniform);
 
 	/*
 	 * Common path is with repeat = 0.
@@ -278,15 +294,19 @@ u8 mtrr_type_lookup(u64 start, u64 end)
 	while (repeat) {
 		prev_type = type;
 		start = partial_end;
-		type = mtrr_type_lookup_variable(start, end, &partial_end, &repeat);
+		is_uniform = 0;
+		type = mtrr_type_lookup_variable(start, end, &partial_end,
+						 &repeat, &dummy);
 
 		if (check_type_overlap(&prev_type, &type))
-			return type;
+			goto out;
 	}
 
 	if (mtrr_tom2 && (start >= (1ULL<<32)) && (end < mtrr_tom2))
-		return MTRR_TYPE_WRBACK;
+		type = MTRR_TYPE_WRBACK;
 
+out:
+	*uniform = is_uniform;
 	return type;
 }
 
arch/x86/mm/pat.c +2 -2
index 35af6771a95a..372ad422c2c3 100644
@@ -267,9 +267,9 @@ static unsigned long pat_x_mtrr_type(u64 start, u64 end,
 	 * request is for WB.
 	 */
 	if (req_type == _PAGE_CACHE_MODE_WB) {
-		u8 mtrr_type;
+		u8 mtrr_type, uniform;
 
-		mtrr_type = mtrr_type_lookup(start, end);
+		mtrr_type = mtrr_type_lookup(start, end, &uniform);
 		if (mtrr_type != MTRR_TYPE_WRBACK)
 			return _PAGE_CACHE_MODE_UC_MINUS;
 
arch/x86/mm/pgtable.c +27 -14

66 lines not on this page · raw message

Signature · 8 lines
2.3.5

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#320 lore raw

Re: [PATCH v5 6/6] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 19 lines · Borislav Petkov
Quoted 18 lines · Toshi Kani

This patch adds an additional argument, 'uniform', to mtrr_type_lookup(), which returns 1 when a given range is covered uniformly by MTRRs, i.e. the range is fully covered by a single MTRR entry or the default type.

pud_set_huge() and pmd_set_huge() are changed to check the new 'uniform' flag to see if it is safe to create a huge page mapping to the range. This allows them to create a huge page mapping to a range covered by a single MTRR entry of any memory type. It also detects a non-optimal request properly. They continue to check with the WB type since the WB type has no effect even if a request spans multiple MTRR entries.

pmd_set_huge() logs a warning message to a non-optimal request so that driver writers will be aware of such a case. Drivers should make a mapping request aligned to a single MTRR entry when the range is covered by MTRRs.

Quoted 7 lines
Quoted 7 lines
---
 arch/x86/include/asm/mtrr.h        |    4 ++--
 arch/x86/kernel/cpu/mtrr/generic.c |   37 ++++++++++++++++++++++++++----------
 arch/x86/mm/pat.c                  |    4 ++--
 arch/x86/mm/pgtable.c              |   33 ++++++++++++++++++++------------
 4 files changed, 52 insertions(+), 26 deletions(-)

:

Quoted 2 lines

All applied,

Great!

Quoted 2 lines

I reformatted the comments in this last one a bit and made the warning message hopefully a bit more descriptive:

I have a few comments below.

Quoted 5 lines
arch/x86/mm/pgtable.c +0 -0
index c30f9819786b..f1894daa79ee 100644

arch/x86/mm/pgtable.c void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys, · line 571

Quoted 10 lines
arch/x86/mm/pgtable.c +3 -4
@@ -566,19 +566,24 @@ void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys,
 /**
  * pud_set_huge - setup kernel PUD mapping
  *
- * MTRR can override PAT memory types with 4KiB granularity.  Therefore,
- * this function does not set up a huge page when the range is covered
- * by a non-WB type of MTRR.  MTRR_TYPE_INVALID indicates that MTRR are
- * disabled.
+ * MTRRs can override PAT memory types with 4KiB granularity. Therefore,
+ * this function sets up a huge page only if all of the following
+ * conditions are met:

It should be "if any of the following condition is met". Or, does NOT setup if all of ...

Quoted 22 lines
arch/x86/mm/pgtable.c +9 -3
+ *
+ *  - MTRRs are disabled.
+ *  - The range is mapped uniformly by an MTRR, i.e. the range is
+ *    fully covered by a single MTRR entry or the default type.
+ *  - The MTRR memory type is WB.
  *
  * Returns 1 on success and 0 on failure.
  */
 int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot)
 {
-	u8 mtrr;
+	u8 mtrr, uniform;
 
-	mtrr = mtrr_type_lookup(addr, addr + PUD_SIZE);
-	if ((mtrr != MTRR_TYPE_WRBACK) && (mtrr != MTRR_TYPE_INVALID))
+	mtrr = mtrr_type_lookup(addr, addr + PUD_SIZE, &uniform);
+	if ((mtrr != MTRR_TYPE_INVALID) && (!uniform) &&
+	    (mtrr != MTRR_TYPE_WRBACK))
 		return 0;
 
 	prot = pgprot_4k_2_large(prot);

arch/x86/mm/pgtable.c int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot) · line 603

Quoted 10 lines
arch/x86/mm/pgtable.c +3 -4
@@ -593,20 +598,28 @@ int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot)
 /**
  * pmd_set_huge - setup kernel PMD mapping
  *
- * MTRR can override PAT memory types with 4KiB granularity.  Therefore,
- * this function does not set up a huge page when the range is covered
- * by a non-WB type of MTRR.  MTRR_TYPE_INVALID indicates that MTRR are
- * disabled.
+ * MTRRs can override PAT memory types with 4KiB granularity. Therefore,
+ * this function sets up a huge page only if all of the following
+ * conditions are met:

Ditto.

Quoted 10 lines
arch/x86/mm/pgtable.c +5 -0
+ *
+ *  - MTRR is disabled.
+ *  - The range is mapped uniformly by an MTRR, i.e. the range is
+ *    fully covered by a single MTRR entry or the default type.
+ *  - The MTRR memory type is WB.
  *
  * Returns 1 on success and 0 on failure.
  */
 int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot)
 {

arch/x86/mm/pgtable.c int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot) · line 620

Quoted 10 lines
arch/x86/mm/pgtable.c +6 -3
-	u8 mtrr;
+	u8 mtrr, uniform;
 
-	mtrr = mtrr_type_lookup(addr, addr + PMD_SIZE);
-	if ((mtrr != MTRR_TYPE_WRBACK) && (mtrr != MTRR_TYPE_INVALID))
+	mtrr = mtrr_type_lookup(addr, addr + PMD_SIZE, &uniform);
+	if ((mtrr != MTRR_TYPE_INVALID) && (!uniform) &&
+	    (mtrr != MTRR_TYPE_WRBACK)) {
+		pr_warn_once("%s: Cannot satisfy [mem %#010llx-%#010llx] with a huge-page mapping due to MTRR override.\n",
+			     __func__, addr, addr + PMD_SIZE);

This new message looks good.

Thanks,
-Toshi

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#321 lore raw

Re: [PATCH v5 6/6] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 10 lines · Toshi Kani
Quoted 10 lines
arch/x86/mm/pgtable.c +0 -2
index c30f9819786b..f1894daa79ee 100644
@@ -566,19 +566,24 @@ void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys,
 /**
  * pud_set_huge - setup kernel PUD mapping
  *
- * MTRR can override PAT memory types with 4KiB granularity.  Therefore,
- * this function does not set up a huge page when the range is covered
Quoted 14 lines

arch/x86/mm/pgtable.c void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys, · line 571

Quoted 5 lines
arch/x86/mm/pgtable.c +3 -2
- * by a non-WB type of MTRR.  MTRR_TYPE_INVALID indicates that MTRR are
- * disabled.
+ * MTRRs can override PAT memory types with 4KiB granularity. Therefore,
+ * this function sets up a huge page only if all of the following
+ * conditions are met:

It should be "if any of the following condition is met". Or, does NOT setup if all of ...

Quoted 5 lines
arch/x86/mm/pgtable.c +5 -0
+ *
+ *  - MTRRs are disabled.
+ *  - The range is mapped uniformly by an MTRR, i.e. the range is
+ *    fully covered by a single MTRR entry or the default type.
+ *  - The MTRR memory type is WB.

Hmm, ok, so this is kinda like "any" but they also depend on each other. So it is

If
- MTRRs are disabled

or

- MTRRs are enabled and the range is completely covered by a single MTRR

or

- MTRRs are enabled and the range is not completely covered by a single MTRR but the memory type of the range is WB, even if covered by multiple MTRRs.

Right?

So tell me this: why do we need to repeat that over those KVA helpers? It's not like the callers can do anything about it, can they?

So maybe that comment - expanded into more detail - should be over mtrr_type_lookup() only. That'll be better, methinks.

Hmm.

Signature · 5 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#322 lore raw

Re: [PATCH v5 6/6] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 36 lines · Borislav Petkov
Quoted 10 lines · Toshi Kani
Quoted 10 lines
arch/x86/mm/pgtable.c +0 -2
index c30f9819786b..f1894daa79ee 100644
@@ -566,19 +566,24 @@ void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys,
 /**
  * pud_set_huge - setup kernel PUD mapping
  *
- * MTRR can override PAT memory types with 4KiB granularity.  Therefore,
- * this function does not set up a huge page when the range is covered
Quoted 14 lines

arch/x86/mm/pgtable.c void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys, · line 571

Quoted 5 lines
arch/x86/mm/pgtable.c +3 -2
- * by a non-WB type of MTRR.  MTRR_TYPE_INVALID indicates that MTRR are
- * disabled.
+ * MTRRs can override PAT memory types with 4KiB granularity. Therefore,
+ * this function sets up a huge page only if all of the following
+ * conditions are met:

It should be "if any of the following condition is met". Or, does NOT setup if all of ...

Quoted 5 lines
arch/x86/mm/pgtable.c +5 -0
+ *
+ *  - MTRRs are disabled.
+ *  - The range is mapped uniformly by an MTRR, i.e. the range is
+ *    fully covered by a single MTRR entry or the default type.
+ *  - The MTRR memory type is WB.

Hmm, ok, so this is kinda like "any" but they also depend on each other. So it is

If
- MTRRs are disabled

or

- MTRRs are enabled and the range is completely covered by a single MTRR

Quoted 7 lines

or

- MTRRs are enabled and the range is not completely covered by a single MTRR but the memory type of the range is WB, even if covered by multiple MTRRs.

Right?

Well, #2 and #3 are independent. That is, uniform can be set regardless of a type value, and WB can be returned regardless of a uniform value.

#1 is a new condition added per your comment that uniform no longer covers the MTRR disabled case. Yes, #2 and #3 depend on #1 being false.

Quoted 5 lines

So tell me this: why do we need to repeat that over those KVA helpers? It's not like the callers can do anything about it, can they?

So maybe that comment - expanded into more detail - should be over mtrr_type_lookup() only. That'll be better, methinks.

The caller is responsible for verifying the conditions that are safe to create huge page. So, I think the comments are needed here to state such conditions.

Thanks,
-Toshi

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#323 lore raw

Re: [PATCH v5 6/6] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 1 line · Toshi Kani

Well, #2 and #3 are independent. That is, uniform can be set regardless

Not #2 and #3 above - the original #2 and #3 ones. I've written them out detailed to show what I mean.

Quoted 2 lines

The caller is responsible for verifying the conditions that are safe to create huge page.

How is the caller ever going to be able to do anything about it?

Regardless, I'd prefer to not duplicate comments and rather put a short sentence pointing the reader to the comments over mtrr_type_lookup() where this all is being explained in detail.

I'll fix it up.

Signature · 5 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#324 lore raw

Re: [PATCH v5 6/6] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 5 lines · Borislav Petkov
Quoted 1 line · Toshi Kani

Well, #2 and #3 are independent. That is, uniform can be set regardless

Not #2 and #3 above - the original #2 and #3 ones. I've written them out detailed to show what I mean.

The original #2 and #3 are set independently as well. They do not depend on each other condition being a specific value.

Quoted 4 lines
Quoted 2 lines

The caller is responsible for verifying the conditions that are safe to create huge page.

How is the caller ever going to be able to do anything about it?

The caller is the one who makes the condition checks necessary to create a huge page mapping. mtrr_type_look() only returns how the given range is related with MTRRs.

Quoted 5 lines

Regardless, I'd prefer to not duplicate comments and rather put a short sentence pointing the reader to the comments over mtrr_type_lookup() where this all is being explained in detail.

I'll fix it up.

I appreciate your help.

Thanks,
-Toshi

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#325 lore raw

Re: [PATCH v5 6/6] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 2 lines · Toshi Kani

The caller is the one who makes the condition checks necessary to create a huge page mapping.

How? It would go and change MTRRs configuration and ranges and their memory types so that a huge mapping succeeds?

Or go and try a different range?

Signature · 5 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#326 lore raw

Re: [PATCH v5 6/6] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 8 lines · Borislav Petkov
Quoted 2 lines · Toshi Kani

The caller is the one who makes the condition checks necessary to create a huge page mapping.

How? It would go and change MTRRs configuration and ranges and their memory types so that a huge mapping succeeds?

Or go and try a different range?

Try with a smaller page size.

The callers, pud_set_huge() and pmd_set_huge(), check if the given range is safe with MTRRs for creating a huge page mapping. If not, they fail the request, which leads their callers, ioremap_pud_range() and ioremap_pmd_range(), to retry with a smaller page size, i.e. 1GB -> 2MB -> 4KB. 4KB may not have overlap with MTRRs (hence no checking is necessary), which will succeed as before.

Thanks,
-Toshi

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#327 lore raw

Re: [PATCH v5 6/6] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 10 lines · Toshi Kani
Quoted 8 lines · Borislav Petkov
Quoted 2 lines · Toshi Kani

The caller is the one who makes the condition checks necessary to create a huge page mapping.

How? It would go and change MTRRs configuration and ranges and their memory types so that a huge mapping succeeds?

Or go and try a different range?

Quoted 8 lines

Try with a smaller page size.

The callers, pud_set_huge() and pmd_set_huge(), check if the given range is safe with MTRRs for creating a huge page mapping. If not, they fail the request, which leads their callers, ioremap_pud_range() and ioremap_pmd_range(), to retry with a smaller page size, i.e. 1GB -> 2MB -> 4KB. 4KB may not have overlap with MTRRs (hence no checking is necessary), which will succeed as before.

Ok, now *this* should be in the form of a comment over the KVA helpers, not the MTRR aspect. Callers of those functions would have to know that
- they shouldn't care about MTRR setup.

The MTRR aspect with the 3 conditions should be only over mtrr_type_lookup().

I'll integrate it into the patch.

Signature · 5 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
maintainer
#328 lore raw

Re: [PATCH v5 6/6] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 8 lines · Borislav Petkov
Quoted 8 lines

Try with a smaller page size.

The callers, pud_set_huge() and pmd_set_huge(), check if the given range is safe with MTRRs for creating a huge page mapping. If not, they fail the request, which leads their callers, ioremap_pud_range() and ioremap_pmd_range(), to retry with a smaller page size, i.e. 1GB -> 2MB -> 4KB. 4KB may not have overlap with MTRRs (hence no checking is necessary), which will succeed as before.

Scratch that, I think I have it now. And I even have a good feeling about it :-)

---
From: Toshi Kani <[email protected]>
Date: Fri, 15 May 2015 12:23:57 -0600
Subject: [PATCH] x86/mm: Enhance MTRR checks in kernel mapping helpers

This patch adds the argument 'uniform' to mtrr_type_lookup(), which gets set to 1 when a given range is covered uniformly by MTRRs, i.e. the range is fully covered by a single MTRR entry or the default type.

Change pud_set_huge() and pmd_set_huge() to honor the 'uniform' flag to see if it is safe to create a huge page mapping in the range.

This allows them to create a huge page mapping in a range covered by a single MTRR entry of any memory type. It also detects a non-optimal request properly. They continue to check with the WB type since it does not effectively change the uniform mapping even if a request spans multiple MTRR entries.

pmd_set_huge() logs a warning message to a non-optimal request so that driver writers will be aware of such a case. Drivers should make a mapping request aligned to a single MTRR entry when the range is covered by MTRRs.

Cc Luis R. Rodriguez <[email protected]>
Cc Andrew Morton <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc linux-mm <[email protected]>
Cc x86-ml <[email protected]>
[ Realign, flesh out comments, improve warning message. ]
---
 arch/x86/include/asm/mtrr.h        |  4 ++--
 arch/x86/kernel/cpu/mtrr/generic.c | 40 ++++++++++++++++++++++++++++----------
 arch/x86/mm/pat.c                  |  4 ++--
 arch/x86/mm/pgtable.c              | 38 +++++++++++++++++++++++-------------
 4 files changed, 58 insertions(+), 28 deletions(-)
arch/x86/include/asm/mtrr.h +2 -2
index bb03a547c1ab..a31759e1edd9 100644
@@ -31,7 +31,7 @@
  * arch_phys_wc_add and arch_phys_wc_del.
  */
 # ifdef CONFIG_MTRR
-extern u8 mtrr_type_lookup(u64 addr, u64 end);
+extern u8 mtrr_type_lookup(u64 addr, u64 end, u8 *uniform);
 extern void mtrr_save_fixed_ranges(void *);
 extern void mtrr_save_state(void);
 extern int mtrr_add(unsigned long base, unsigned long size,
@@ -50,7 +50,7 @@ extern int mtrr_trim_uncached_memory(unsigned long end_pfn);
 extern int amd_special_default_mtrr(void);
 extern int phys_wc_to_mtrr_index(int handle);
 #  else
-static inline u8 mtrr_type_lookup(u64 addr, u64 end)
+static inline u8 mtrr_type_lookup(u64 addr, u64 end, u8 *uniform)
 {
 	/*
 	 * Return no-MTRRs:
arch/x86/kernel/cpu/mtrr/generic.c +30 -10
index e51100c49eea..f782d9b62cb3 100644
@@ -147,19 +147,24 @@ static u8 mtrr_type_lookup_fixed(u64 start, u64 end)
  * Return Value:
  * MTRR_TYPE_(type) - Matched memory type or default memory type (unmatched)
  *
- * Output Argument:
+ * Output Arguments:
  * repeat - Set to 1 when [start:end] spanned across MTRR range and type
  *	    returned corresponds only to [start:*partial_end].  Caller has
  *	    to lookup again for [*partial_end:end].
+ *
+ * uniform - Set to 1 when an MTRR covers the region uniformly, i.e. the
+ *	     region is fully covered by a single MTRR entry or the default
+ *	     type.
  */
 static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
-				    int *repeat)
+				    int *repeat, u8 *uniform)
 {
 	int i;
 	u64 base, mask;
 	u8 prev_match, curr_match;
 
 	*repeat = 0;
+	*uniform = 1;
 
 	/* Make end inclusive instead of exclusive */
 	end--;
@@ -214,6 +219,7 @@ static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
 
 			end = *partial_end - 1; /* end is inclusive */
 			*repeat = 1;
+			*uniform = 0;
 		}
 
 		if ((start & mask) != (base & mask))
@@ -225,6 +231,7 @@ static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
 			continue;
 		}
 
+		*uniform = 0;
 		if (check_type_overlap(&prev_match, &curr_match))
 			return curr_match;
 	}
@@ -241,10 +248,15 @@ static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end,
  * Return Values:
  * MTRR_TYPE_(type)  - The effective MTRR type for the region
  * MTRR_TYPE_INVALID - MTRR is disabled
+ *
+ * Output Argument:
+ * uniform - Set to 1 when an MTRR covers the region uniformly, i.e. the
+ *	     region is fully covered by a single MTRR entry or the default
+ *	     type.
  */
-u8 mtrr_type_lookup(u64 start, u64 end)
+u8 mtrr_type_lookup(u64 start, u64 end, u8 *uniform)
 {
-	u8 type, prev_type;
+	u8 type, prev_type, is_uniform = 1, dummy;
 	int repeat;
 	u64 partial_end;
 
@@ -260,14 +272,18 @@ u8 mtrr_type_lookup(u64 start, u64 end)
 	 */
 	if ((start < 0x100000) &&
 	    (mtrr_state.have_fixed) &&
-	    (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED))
-		return mtrr_type_lookup_fixed(start, end);
+	    (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) {
+		is_uniform = 0;
+		type = mtrr_type_lookup_fixed(start, end);
+		goto out;
+	}
 
 	/*
 	 * Look up the variable ranges.  Look of multiple ranges matching
 	 * this address and pick type as per MTRR precedence.
 	 */
-	type = mtrr_type_lookup_variable(start, end, &partial_end, &repeat);
+	type = mtrr_type_lookup_variable(start, end, &partial_end,
+					 &repeat, &is_uniform);
 
 	/*
 	 * Common path is with repeat = 0.
@@ -278,15 +294,19 @@ u8 mtrr_type_lookup(u64 start, u64 end)
 	while (repeat) {
 		prev_type = type;
 		start = partial_end;
-		type = mtrr_type_lookup_variable(start, end, &partial_end, &repeat);
+		is_uniform = 0;
+		type = mtrr_type_lookup_variable(start, end, &partial_end,
+						 &repeat, &dummy);
 
 		if (check_type_overlap(&prev_type, &type))
-			return type;
+			goto out;
 	}
 
 	if (mtrr_tom2 && (start >= (1ULL<<32)) && (end < mtrr_tom2))
-		return MTRR_TYPE_WRBACK;
+		type = MTRR_TYPE_WRBACK;
 
+out:
+	*uniform = is_uniform;
 	return type;
 }
 
arch/x86/mm/pat.c +2 -2
index 35af6771a95a..372ad422c2c3 100644
@@ -267,9 +267,9 @@ static unsigned long pat_x_mtrr_type(u64 start, u64 end,
 	 * request is for WB.
 	 */
 	if (req_type == _PAGE_CACHE_MODE_WB) {
-		u8 mtrr_type;
+		u8 mtrr_type, uniform;
 
-		mtrr_type = mtrr_type_lookup(start, end);
+		mtrr_type = mtrr_type_lookup(start, end, &uniform);
 		if (mtrr_type != MTRR_TYPE_WRBACK)
 			return _PAGE_CACHE_MODE_UC_MINUS;
 
arch/x86/mm/pgtable.c +24 -14
index c30f9819786b..df2f8a587438 100644
@@ -566,19 +566,28 @@ void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys,
 /**
  * pud_set_huge - setup kernel PUD mapping
  *
- * MTRR can override PAT memory types with 4KiB granularity.  Therefore,
- * this function does not set up a huge page when the range is covered
- * by a non-WB type of MTRR.  MTRR_TYPE_INVALID indicates that MTRR are
- * disabled.
+ * MTRRs can override PAT memory types with 4KiB granularity. Therefore, this
+ * function sets up a huge page only if any of the following conditions are met:
+ *
+ * - MTRRs are disabled, or
+ *
+ * - MTRRs are enabled and the range is completely covered by a single MTRR, or
+ *
+ * - MTRRs are enabled and the range is not completely covered by a single MTRR
+ *   but the memory type of the range is WB, even if covered by multiple MTRRs.
+ *
+ * Callers should try to decrease page size (1GB -> 2MB -> 4K) if the bigger
+ * page mapping attempt fails.
  *
  * Returns 1 on success and 0 on failure.
  */
 int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot)
 {
-	u8 mtrr;
+	u8 mtrr, uniform;
 
-	mtrr = mtrr_type_lookup(addr, addr + PUD_SIZE);
-	if ((mtrr != MTRR_TYPE_WRBACK) && (mtrr != MTRR_TYPE_INVALID))
+	mtrr = mtrr_type_lookup(addr, addr + PUD_SIZE, &uniform);
+	if ((mtrr != MTRR_TYPE_INVALID) && (!uniform) &&
+	    (mtrr != MTRR_TYPE_WRBACK))
 		return 0;
 
 	prot = pgprot_4k_2_large(prot);
@@ -593,20 +602,21 @@ int pud_set_huge(pud_t *pud, phys_addr_t addr, pgprot_t prot)
 /**
  * pmd_set_huge - setup kernel PMD mapping
  *
- * MTRR can override PAT memory types with 4KiB granularity.  Therefore,
- * this function does not set up a huge page when the range is covered
- * by a non-WB type of MTRR.  MTRR_TYPE_INVALID indicates that MTRR are
- * disabled.
+ * See text over pud_set_huge() above.
  *
  * Returns 1 on success and 0 on failure.
  */
 int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot)
 {
-	u8 mtrr;
+	u8 mtrr, uniform;
 
-	mtrr = mtrr_type_lookup(addr, addr + PMD_SIZE);
-	if ((mtrr != MTRR_TYPE_WRBACK) && (mtrr != MTRR_TYPE_INVALID))
+	mtrr = mtrr_type_lookup(addr, addr + PMD_SIZE, &uniform);
+	if ((mtrr != MTRR_TYPE_INVALID) && (!uniform) &&
+	    (mtrr != MTRR_TYPE_WRBACK)) {
+		pr_warn_once("%s: Cannot satisfy [mem %#010llx-%#010llx] with a huge-page mapping due to MTRR override.\n",
+			     __func__, addr, addr + PMD_SIZE);
 		return 0;
+	}
 
 	prot = pgprot_4k_2_large(prot);
 
Signature · 8 lines
2.3.5

-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#329 lore raw

Re: [PATCH v5 6/6] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 10 lines · Borislav Petkov
Quoted 8 lines · Borislav Petkov
Quoted 8 lines

Try with a smaller page size.

The callers, pud_set_huge() and pmd_set_huge(), check if the given range is safe with MTRRs for creating a huge page mapping. If not, they fail the request, which leads their callers, ioremap_pud_range() and ioremap_pmd_range(), to retry with a smaller page size, i.e. 1GB -> 2MB -> 4KB. 4KB may not have overlap with MTRRs (hence no checking is necessary), which will succeed as before.

Quoted 2 lines

Scratch that, I think I have it now. And I even have a good feeling about it :-)

Looks good. Thanks for the update!
-Toshi

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#330 lore raw

Re: [PATCH v5 6/6] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

In reply to Borislav Petkov
Quoted 12 lines · Borislav Petkov
arch/x86/mm/pgtable.c +2 -4
@@ -566,19 +566,28 @@ void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys,
 /**
  * pud_set_huge - setup kernel PUD mapping
  *
- * MTRR can override PAT memory types with 4KiB granularity.  Therefore,
- * this function does not set up a huge page when the range is covered
- * by a non-WB type of MTRR.  MTRR_TYPE_INVALID indicates that MTRR are
- * disabled.
+ * MTRRs can override PAT memory types with 4KiB granularity. Therefore, this
+ * function sets up a huge page only if any of the following conditions are met:

arch/x86/mm/pgtable.c void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys, · line 580

Quoted 10 lines
arch/x86/mm/pgtable.c +10 -0
+ *
+ * - MTRRs are disabled, or
+ *
+ * - MTRRs are enabled and the range is completely covered by a single MTRR, or
+ *
+ * - MTRRs are enabled and the range is not completely covered by a single MTRR
+ *   but the memory type of the range is WB, even if covered by multiple MTRRs.
+ *
+ * Callers should try to decrease page size (1GB -> 2MB -> 4K) if the bigger
+ * page mapping attempt fails.

This comment should explain why it's ok in the WB case.

Also, the phrase 'the memory type of the range' is ambiguous: it might mean the partial MTRR's, or the memory type specified via PAT by the huge-pmd entry.

Thanks,

Ingo

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#331 lore raw

Re: [PATCH v5 6/6] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 27 lines · Ingo Molnar
Quoted 12 lines · Borislav Petkov
arch/x86/mm/pgtable.c +2 -4
@@ -566,19 +566,28 @@ void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys,
 /**
  * pud_set_huge - setup kernel PUD mapping
  *
- * MTRR can override PAT memory types with 4KiB granularity.  Therefore,
- * this function does not set up a huge page when the range is covered
- * by a non-WB type of MTRR.  MTRR_TYPE_INVALID indicates that MTRR are
- * disabled.
+ * MTRRs can override PAT memory types with 4KiB granularity. Therefore, this
+ * function sets up a huge page only if any of the following conditions are met:

arch/x86/mm/pgtable.c void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys, · line 580

Quoted 10 lines
arch/x86/mm/pgtable.c +10 -0
+ *
+ * - MTRRs are disabled, or
+ *
+ * - MTRRs are enabled and the range is completely covered by a single MTRR, or
+ *
+ * - MTRRs are enabled and the range is not completely covered by a single MTRR
+ *   but the memory type of the range is WB, even if covered by multiple MTRRs.
+ *
+ * Callers should try to decrease page size (1GB -> 2MB -> 4K) if the bigger
+ * page mapping attempt fails.

This comment should explain why it's ok in the WB case.

Quoted 3 lines

Also, the phrase 'the memory type of the range' is ambiguous: it might mean the partial MTRR's, or the memory type specified via PAT by the huge-pmd entry.

Agreed. How about this sentence?

- MTRRs are enabled and the corresponding MTRR memory type is WB, which
has no effect to the requested PAT memory type.

Thanks,
-Toshi

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#332 lore raw

Re: [PATCH v5 6/6] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 28 lines · Toshi Kani
Quoted 27 lines · Ingo Molnar
Quoted 12 lines · Borislav Petkov
arch/x86/mm/pgtable.c +2 -4
@@ -566,19 +566,28 @@ void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys,
 /**
  * pud_set_huge - setup kernel PUD mapping
  *
- * MTRR can override PAT memory types with 4KiB granularity.  Therefore,
- * this function does not set up a huge page when the range is covered
- * by a non-WB type of MTRR.  MTRR_TYPE_INVALID indicates that MTRR are
- * disabled.
+ * MTRRs can override PAT memory types with 4KiB granularity. Therefore, this
+ * function sets up a huge page only if any of the following conditions are met:

arch/x86/mm/pgtable.c void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys, · line 580

Quoted 10 lines
arch/x86/mm/pgtable.c +10 -0
+ *
+ * - MTRRs are disabled, or
+ *
+ * - MTRRs are enabled and the range is completely covered by a single MTRR, or
+ *
+ * - MTRRs are enabled and the range is not completely covered by a single MTRR
+ *   but the memory type of the range is WB, even if covered by multiple MTRRs.
+ *
+ * Callers should try to decrease page size (1GB -> 2MB -> 4K) if the bigger
+ * page mapping attempt fails.

This comment should explain why it's ok in the WB case.

Quoted 8 lines
Quoted 3 lines

Also, the phrase 'the memory type of the range' is ambiguous: it might mean the partial MTRR's, or the memory type specified via PAT by the huge-pmd entry.

Agreed. How about this sentence?

- MTRRs are enabled and the corresponding MTRR memory type is WB, which
has no effect to the requested PAT memory type.

s/effect to/effect on

sounds good otherwise!

Btw., if WB MTRR entries can never have an effect on Linux PAT specified attributes, why do we allow them to be created? I don't think we ever call into real mode for this to matter?

Thanks,

Ingo

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#333 lore raw

Re: [PATCH v5 6/6] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 34 lines · Ingo Molnar
Quoted 32 lines · Toshi Kani
Quoted 30 lines · Ingo Molnar
Quoted 12 lines · Borislav Petkov
arch/x86/mm/pgtable.c +2 -4
@@ -566,19 +566,28 @@ void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys,
 /**
  * pud_set_huge - setup kernel PUD mapping
  *
- * MTRR can override PAT memory types with 4KiB granularity.  Therefore,
- * this function does not set up a huge page when the range is covered
- * by a non-WB type of MTRR.  MTRR_TYPE_INVALID indicates that MTRR are
- * disabled.
+ * MTRRs can override PAT memory types with 4KiB granularity. Therefore, this
+ * function sets up a huge page only if any of the following conditions are met:

arch/x86/mm/pgtable.c void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys, · line 580

Quoted 10 lines
arch/x86/mm/pgtable.c +10 -0
+ *
+ * - MTRRs are disabled, or
+ *
+ * - MTRRs are enabled and the range is completely covered by a single MTRR, or
+ *
+ * - MTRRs are enabled and the range is not completely covered by a single MTRR
+ *   but the memory type of the range is WB, even if covered by multiple MTRRs.
+ *
+ * Callers should try to decrease page size (1GB -> 2MB -> 4K) if the bigger
+ * page mapping attempt fails.

This comment should explain why it's ok in the WB case.

Also, the phrase 'the memory type of the range' is ambiguous: it might mean the partial MTRR's, or the memory type specified via PAT by the huge-pmd entry.

Quoted 8 lines
Quoted 4 lines

Agreed. How about this sentence?

- MTRRs are enabled and the corresponding MTRR memory type is WB, which
has no effect to the requested PAT memory type.

s/effect to/effect on

sounds good otherwise!

Great!

Boris, can you update the patch, or do you want me to send you a patch for this update?

Quoted 3 lines

Btw., if WB MTRR entries can never have an effect on Linux PAT specified attributes, why do we allow them to be created? I don't think we ever call into real mode for this to matter?

MTRRs have the default memory type, which is used when the given range is not covered by any MTRR entries. There are two types of BIOS setup:

1) Default UC
- BIOS sets the default type to UC, and covers all WB accessible ranges
with MTRR entries of WB.

2) Default WB
- BIOS sets the default type to WB, and covers non-WB accessible range
with MTRR entries of other memory types, such as UC.

In both cases, WB type can be returned. In case of 1), the requested range may overlap with multiple MTRR entries of WB type, which is still safe.

Thanks,
-Toshi

Thanks,
-Toshi

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#334 lore raw

Re: [PATCH v5 6/6] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping

Quoted 1 line · Toshi Kani

Boris, can you update the patch,

Done.

Signature · 5 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#336 lore raw

v4 cover Compile-time stack frame pointer validation

In discussions around the live kernel patching consistency model RFC [1], Peter and Ingo correctly pointed out that stack traces aren't reliable. And as Ingo said, there's no "strong force" which ensures we can rely on them.

So I've been thinking about how to fix that. My goal is to eventually make stack traces reliable. Or at the very least, to be able to detect at runtime when a given stack trace *might* be unreliable. But improved stack traces would broadly benefit the entire kernel, regardless of the outcome of the live kernel patching consistency model discussions.

This patch set is just the first in a series of proposed stack trace reliability improvements. Future proposals will include runtime stack reliability checking, as well as compile-time and runtime DWARF validations.

As far as I can tell, there are two main obstacles which prevent frame pointer based stack traces from being reliable:

1) Missing frame pointer logic: currently, most assembly functions don't set up the frame pointer.

2) Interrupts: if a function is interrupted before it can save and set up the frame pointer, its caller won't show up in the stack trace.

This patch set aims to remove the first obstacle by enforcing that all asm functions honor CONFIG_FRAME_POINTER. This is done with a new stackvalidate host tool which is automatically run for every compiled .S file and which validates that every asm function does the proper frame pointer setup.

Also, to make sure somebody didn't forget to annotate their callable asm code as a function, flag an error for any return instructions which are hiding outside of a function. In almost all cases, return instructions are part of callable functions and should be annotated as such so that we can validate their frame pointer usage. A whitelist mechanism exists for those few return instructions which are not actually in callable code.

It currently only supports x86_64. It *almost* supports x86_32, but the stackvalidate code doesn't yet know how to deal with 32-bit REL relocations for the return whitelists. I tried to make the code generic so that support for other architectures can be plugged in pretty easily.

As a first step, all reported non-compliances result in warnings. Right now I'm seeing 200+ warnings. Once we get them all cleaned up, we can change the warnings to build errors so the asm code can stay clean.

The patches are based on linux-next. Patch 1 adds the stackvalidate host tool. Patch 2 is a cleanup which makes the push/pop CFI macros arch-independent, in preparation for patch 3. Patch 3 adds some helper macros for asm functions so that they can comply with stackvalidate.

[1] http://lkml.kernel.org/r/[email protected]

v4:
- Changed the default to CONFIG_STACK_VALIDATION=n, until all the asm code can get cleaned up.
- Fixed a stackvalidate error path exit code issue found by Michal Marek.

v3:
- Added a patch to make the push/pop CFI macros arch-independent, as suggested by H. Peter Anvin

v2:
- Fixed memory leaks reported by Petr Mladek

Josh Poimboeuf (3):
x86, stackvalidate: Compile-time stack frame pointer validation
x86: Make push/pop CFI macros arch-independent
x86, stackvalidate: Add asm frame pointer setup macros

 MAINTAINERS                           |   6 +
 arch/Kconfig                          |   3 +
 arch/x86/Kconfig                      |   1 +
 arch/x86/Makefile                     |   6 +-
 arch/x86/ia32/ia32entry.S             |  60 +++---
 arch/x86/include/asm/calling.h        |  28 +--
 arch/x86/include/asm/dwarf2.h         |  92 ++++-----
 arch/x86/include/asm/frame.h          |   4 +-
 arch/x86/include/asm/func.h           |  82 ++++++++
 arch/x86/kernel/entry_32.S            | 214 ++++++++++-----------
 arch/x86/kernel/entry_64.S            |  96 +++++-----
 arch/x86/lib/atomic64_386_32.S        |   4 +-
 arch/x86/lib/atomic64_cx8_32.S        |  40 ++--
 arch/x86/lib/checksum_32.S            |  42 ++--
 arch/x86/lib/cmpxchg16b_emu.S         |   6 +-
 arch/x86/lib/cmpxchg8b_emu.S          |   6 +-
 arch/x86/lib/msr-reg.S                |  34 ++--
 arch/x86/lib/rwsem.S                  |  40 ++--
 arch/x86/lib/thunk_32.S               |  12 +-
 arch/x86/lib/thunk_64.S               |  36 ++--
 lib/Kconfig.debug                     |  11 ++
 scripts/Makefile                      |   1 +
 scripts/Makefile.build                |  22 ++-
 scripts/stackvalidate/Makefile        |  17 ++
 scripts/stackvalidate/arch-x86.c      | 134 +++++++++++++
 scripts/stackvalidate/arch.h          |  10 +
 scripts/stackvalidate/elf.c           | 352 ++++++++++++++++++++++++++++++++++
 scripts/stackvalidate/elf.h           |  56 ++++++
 scripts/stackvalidate/list.h          | 217 +++++++++++++++++++++
 scripts/stackvalidate/stackvalidate.c | 226 ++++++++++++++++++++++
 30 files changed, 1484 insertions(+), 374 deletions(-)
 create mode 100644 arch/x86/include/asm/func.h
 create mode 100644 scripts/stackvalidate/Makefile
 create mode 100644 scripts/stackvalidate/arch-x86.c
 create mode 100644 scripts/stackvalidate/arch.h
 create mode 100644 scripts/stackvalidate/elf.c
 create mode 100644 scripts/stackvalidate/elf.h
 create mode 100644 scripts/stackvalidate/list.h
 create mode 100644 scripts/stackvalidate/stackvalidate.c
Signature · 1 line
2.1.0
#337 lore raw

PATCH v4 1/3 x86, stackvalidate: Compile-time stack frame pointer validation

Frame pointer based stack traces aren't always reliable. One big reason is that most asm functions don't set up the frame pointer.

Fix that by enforcing that all asm functions honor CONFIG_FRAME_POINTER. This is done with a new stackvalidate host tool which is automatically run for every compiled .S file and which validates that every asm function does the proper frame pointer setup.

Also, to make sure somebody didn't forget to annotate their callable asm code as a function, flag an error for any return instructions which are hiding outside of a function. In almost all cases, return instructions are part of callable functions and should be annotated as such so that we can validate their frame pointer usage. A whitelist mechanism exists for those few return instructions which are not actually in callable code.

It currently only supports x86_64. It *almost* supports x86_32, but the stackvalidate code doesn't yet know how to deal with 32-bit REL relocations for the return whitelists. I tried to make the code generic so that support for other architectures can be plugged in pretty easily.

As a first step, CONFIG_STACK_VALIDATION is disabled by default, and all reported non-compliances result in warnings. Right now I'm seeing 200+ warnings. Once we get them all cleaned up, we can change the default to CONFIG_STACK_VALIDATION=y and change the warnings to build errors so the asm code can stay clean.

---
 MAINTAINERS                           |   6 +
 arch/Kconfig                          |   3 +
 arch/x86/Kconfig                      |   1 +
 arch/x86/Makefile                     |   6 +-
 lib/Kconfig.debug                     |  11 ++
 scripts/Makefile                      |   1 +
 scripts/Makefile.build                |  22 ++-
 scripts/stackvalidate/Makefile        |  17 ++
 scripts/stackvalidate/arch-x86.c      | 134 +++++++++++++
 scripts/stackvalidate/arch.h          |  10 +
 scripts/stackvalidate/elf.c           | 352 ++++++++++++++++++++++++++++++++++
 scripts/stackvalidate/elf.h           |  56 ++++++
 scripts/stackvalidate/list.h          | 217 +++++++++++++++++++++
 scripts/stackvalidate/stackvalidate.c | 226 ++++++++++++++++++++++
 14 files changed, 1059 insertions(+), 3 deletions(-)
 create mode 100644 scripts/stackvalidate/Makefile
 create mode 100644 scripts/stackvalidate/arch-x86.c
 create mode 100644 scripts/stackvalidate/arch.h
 create mode 100644 scripts/stackvalidate/elf.c
 create mode 100644 scripts/stackvalidate/elf.h
 create mode 100644 scripts/stackvalidate/list.h
 create mode 100644 scripts/stackvalidate/stackvalidate.c
MAINTAINERS +6 -0
index 78ea7b6..6d700bf 100644
@@ -9451,6 +9451,12 @@ L:	[email protected]
 S:	Supported
 F:	Documentation/stable_kernel_rules.txt
 
+STACK VALIDATION
+M:	Josh Poimboeuf <[email protected]>
+S:	Supported
+F:	scripts/stackvalidate/
+F:	arch/x86/include/asm/func.h
+
 STAGING SUBSYSTEM
 M:	Greg Kroah-Hartman <[email protected]>
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
arch/Kconfig +3 -0
index bec6666..a5c3f50 100644
@@ -506,6 +506,9 @@ config HAVE_COPY_THREAD_TLS
 	  normal C parameter passing, rather than extracting the syscall
 	  argument from pt_regs.
 
+config HAVE_STACK_VALIDATION
+	bool
+
 #
 # ABI hall of shame
 #
arch/x86/Kconfig +1 -0
index c92fdcc..d60a2378a 100644
@@ -146,6 +146,7 @@ config X86
 	select ACPI_LEGACY_TABLES_LOOKUP if ACPI
 	select X86_FEATURE_NAMES if PROC_FS
 	select SRCU
+	select HAVE_STACK_VALIDATION if FRAME_POINTER && X86_64
 
 config INSTRUCTION_DECODER
 	def_bool y
arch/x86/Makefile +5 -1
index 57996ee..c5598a0 100644
@@ -180,9 +180,13 @@ KBUILD_CFLAGS += $(call cc-option,-mno-avx,)
 KBUILD_CFLAGS += $(mflags-y)
 KBUILD_AFLAGS += $(mflags-y)
 
-archscripts: scripts_basic
+archscripts: scripts_basic $(objtree)/arch/x86/lib/inat-tables.c
 	$(Q)$(MAKE) $(build)=arch/x86/tools relocs
 
+# this file is needed early by scripts/stackvalidate
+$(objtree)/arch/x86/lib/inat-tables.c:
+	$(Q)$(MAKE) $(build)=arch/x86/lib $@
+
 ###
 # Syscall table generation
 
lib/Kconfig.debug +11 -0
index eb3997b..7bfaf80 100644
@@ -332,6 +332,17 @@ config FRAME_POINTER
 	  larger and slower, but it gives very useful debugging information
 	  in case of kernel bugs. (precise oopses/stacktraces/warnings)
 
+
+config STACK_VALIDATION
+	bool "Enable kernel stack validation"
+	depends on HAVE_STACK_VALIDATION
+	default n
+	help
+	  Add compile-time validations which help make kernel stack traces more
+	  reliable.  This includes checks to ensure that assembly functions
+	  save, update and restore the frame pointer or the back chain pointer.
+
+
 config DEBUG_FORCE_WEAK_PER_CPU
 	bool "Force weak per-cpu definitions"
 	depends on DEBUG_KERNEL
scripts/Makefile +1 -0
index 2016a64..c882a91 100644
@@ -37,6 +37,7 @@ subdir-y                     += mod
 subdir-$(CONFIG_SECURITY_SELINUX) += selinux
 subdir-$(CONFIG_DTC)         += dtc
 subdir-$(CONFIG_GDB_SCRIPTS) += gdb
+subdir-$(CONFIG_STACK_VALIDATION) += stackvalidate
 
 # Let clean descend into subdirs
 subdir-	+= basic kconfig package
scripts/Makefile.build +20 -2
index 01df30a..3b05833 100644
@@ -253,6 +253,24 @@ define rule_cc_o_c
 	mv -f $(dot-target).tmp $(dot-target).cmd
 endef
 
+ifdef CONFIG_STACK_VALIDATION
+stackvalidate = $(objtree)/scripts/stackvalidate/stackvalidate
+cmd_stackvalidate =							  \
+	case $(@) in							  \
+		arch/x86/purgatory/*) ;;				  \
+		*) $(stackvalidate) "$(@)"; \
+	esac;
+endif
+
+define rule_as_o_S
+	$(call echo-cmd,as_o_S) $(cmd_as_o_S);				  \
+	$(cmd_stackvalidate)						  \
+	scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,as_o_S)' >    \
+	                                              $(dot-target).tmp;  \
+	rm -f $(depfile);						  \
+	mv -f $(dot-target).tmp $(dot-target).cmd
+endef
+
 # Built-in and composite module parts
 $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
 	$(call cmd,force_checksrc)
@@ -290,8 +308,8 @@ $(obj)/%.s: $(src)/%.S FORCE
 quiet_cmd_as_o_S = AS $(quiet_modtag)  $@
 cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
 
-$(obj)/%.o: $(src)/%.S FORCE
-	$(call if_changed_dep,as_o_S)
+$(obj)/%.o: $(src)/%.S $(stackvalidate) FORCE
+	$(call if_changed_rule,as_o_S)
 
 targets += $(real-objs-y) $(real-objs-m) $(lib-y)
 targets += $(extra-y) $(MAKECMDGOALS) $(always)
scripts/stackvalidate/Makefile new file +17 -0
new file mode 100644
index 0000000..6027ec4
@@ -0,0 +1,17 @@
+hostprogs-y := stackvalidate
+always := $(hostprogs-y)
+
+stackvalidate-objs := stackvalidate.o elf.o
+
+HOSTCFLAGS += -Werror
+HOSTLOADLIBES_stackvalidate := -lelf
+
+ifdef CONFIG_X86
+
+stackvalidate-objs += arch-x86.o
+
+HOSTCFLAGS_arch-x86.o := -I$(objtree)/arch/x86/lib/ -I$(srctree)/arch/x86/include/ -I$(srctree)/arch/x86/lib/
+
+$(obj)/arch-x86.o: $(srctree)/arch/x86/lib/insn.c $(srctree)/arch/x86/lib/inat.c $(srctree)/arch/x86/include/asm/inat_types.h $(srctree)/arch/x86/include/asm/inat.h $(srctree)/arch/x86/include/asm/insn.h $(objtree)/arch/x86/lib/inat-tables.c
+
+endif
scripts/stackvalidate/arch-x86.c new file +134 -0

134 lines not on this page · raw message

scripts/stackvalidate/arch.h new file +10 -0
new file mode 100644
index 0000000..3b91b1c
@@ -0,0 +1,10 @@
+#ifndef _ARCH_H_
+#define _ARCH_H_
+
+#include "elf.h"
+
+int arch_validate_function(struct elf *elf, struct symbol *func);
+int arch_is_return_insn(struct elf *elf, unsigned long addr,
+			unsigned int maxlen, unsigned int *len);
+
+#endif /* _ARCH_H_ */
scripts/stackvalidate/elf.c new file +352 -0

352 lines not on this page · raw message

scripts/stackvalidate/elf.h new file +56 -0

56 lines not on this page · raw message

scripts/stackvalidate/list.h new file +217 -0

217 lines not on this page · raw message

scripts/stackvalidate/stackvalidate.c new file +226 -0

226 lines not on this page · raw message

Signature · 1 line
2.1.0
#338 lore raw

PATCH v4 2/3 x86: Make push/pop CFI macros arch-independent

In reply to Josh Poimboeuf

The separate push{lq}_cfi and pop_{lq}_cfi macros aren't needed. Push and pop only come in one size per architecture, so the trailing 'q' or 'l' characters are redundant, and awkward to use in arch-independent code.

Replace the push/pop CFI macros with architecture-independent versions:
push_cfi, pop_cfi, etc.

This change is purely cosmetic, with no resulting object code changes.

---
 arch/x86/ia32/ia32entry.S      |  60 ++++++------
 arch/x86/include/asm/calling.h |  28 +++---
 arch/x86/include/asm/dwarf2.h  |  92 ++++++------------
 arch/x86/include/asm/frame.h   |   4 +-
 arch/x86/kernel/entry_32.S     | 214 ++++++++++++++++++++---------------------
 arch/x86/kernel/entry_64.S     |  96 +++++++++---------
 arch/x86/lib/atomic64_386_32.S |   4 +-
 arch/x86/lib/atomic64_cx8_32.S |  40 ++++----
 arch/x86/lib/checksum_32.S     |  42 ++++----
 arch/x86/lib/cmpxchg16b_emu.S  |   6 +-
 arch/x86/lib/cmpxchg8b_emu.S   |   6 +-
 arch/x86/lib/msr-reg.S         |  34 +++----
 arch/x86/lib/rwsem.S           |  40 ++++----
 arch/x86/lib/thunk_32.S        |  12 +--
 arch/x86/lib/thunk_64.S        |  36 +++----
 15 files changed, 343 insertions(+), 371 deletions(-)
arch/x86/ia32/ia32entry.S +30 -30
index 83e4ed2..7259bc9 100644
@@ -124,19 +124,19 @@ ENTRY(ia32_sysenter_target)
 	CFI_REGISTER rip,r10
 
 	/* Construct struct pt_regs on stack */
-	pushq_cfi	$__USER32_DS		/* pt_regs->ss */
-	pushq_cfi	%rbp			/* pt_regs->sp */
+	push_cfi	$__USER32_DS		/* pt_regs->ss */
+	push_cfi	%rbp			/* pt_regs->sp */
 	CFI_REL_OFFSET	rsp,0
-	pushfq_cfi				/* pt_regs->flags */
-	pushq_cfi	$__USER32_CS		/* pt_regs->cs */
-	pushq_cfi	%r10 /* pt_regs->ip = thread_info->sysenter_return */
+	pushf_cfi				/* pt_regs->flags */
+	push_cfi	$__USER32_CS		/* pt_regs->cs */
+	push_cfi	%r10 /* pt_regs->ip = thread_info->sysenter_return */
 	CFI_REL_OFFSET	rip,0
-	pushq_cfi_reg	rax			/* pt_regs->orig_ax */
-	pushq_cfi_reg	rdi			/* pt_regs->di */
-	pushq_cfi_reg	rsi			/* pt_regs->si */
-	pushq_cfi_reg	rdx			/* pt_regs->dx */
-	pushq_cfi_reg	rcx			/* pt_regs->cx */
-	pushq_cfi	$-ENOSYS		/* pt_regs->ax */
+	push_cfi_reg	rax			/* pt_regs->orig_ax */
+	push_cfi_reg	rdi			/* pt_regs->di */
+	push_cfi_reg	rsi			/* pt_regs->si */
+	push_cfi_reg	rdx			/* pt_regs->dx */
+	push_cfi_reg	rcx			/* pt_regs->cx */
+	push_cfi	$-ENOSYS		/* pt_regs->ax */
 	cld
 	sub	$(10*8),%rsp /* pt_regs->r8-11,bp,bx,r12-15 not saved */
 	CFI_ADJUST_CFA_OFFSET 10*8
@@ -282,8 +282,8 @@ sysexit_audit:
 #endif
 
 sysenter_fix_flags:
-	pushq_cfi $(X86_EFLAGS_IF|X86_EFLAGS_FIXED)
-	popfq_cfi
+	push_cfi $(X86_EFLAGS_IF|X86_EFLAGS_FIXED)
+	popf_cfi
 	jmp sysenter_flags_fixed
 
 sysenter_tracesys:
@@ -353,20 +353,20 @@ ENTRY(ia32_cstar_target)
 	movl	%eax,%eax
 
 	/* Construct struct pt_regs on stack */
-	pushq_cfi	$__USER32_DS		/* pt_regs->ss */
-	pushq_cfi	%r8			/* pt_regs->sp */
+	push_cfi	$__USER32_DS		/* pt_regs->ss */
+	push_cfi	%r8			/* pt_regs->sp */
 	CFI_REL_OFFSET rsp,0
-	pushq_cfi	%r11			/* pt_regs->flags */
-	pushq_cfi	$__USER32_CS		/* pt_regs->cs */
-	pushq_cfi	%rcx			/* pt_regs->ip */
+	push_cfi	%r11			/* pt_regs->flags */
+	push_cfi	$__USER32_CS		/* pt_regs->cs */
+	push_cfi	%rcx			/* pt_regs->ip */
 	CFI_REL_OFFSET rip,0
-	pushq_cfi_reg	rax			/* pt_regs->orig_ax */
-	pushq_cfi_reg	rdi			/* pt_regs->di */
-	pushq_cfi_reg	rsi			/* pt_regs->si */
-	pushq_cfi_reg	rdx			/* pt_regs->dx */
-	pushq_cfi_reg	rbp			/* pt_regs->cx */
+	push_cfi_reg	rax			/* pt_regs->orig_ax */
+	push_cfi_reg	rdi			/* pt_regs->di */
+	push_cfi_reg	rsi			/* pt_regs->si */
+	push_cfi_reg	rdx			/* pt_regs->dx */
+	push_cfi_reg	rbp			/* pt_regs->cx */
 	movl	%ebp,%ecx
-	pushq_cfi	$-ENOSYS		/* pt_regs->ax */
+	push_cfi	$-ENOSYS		/* pt_regs->ax */
 	sub	$(10*8),%rsp /* pt_regs->r8-11,bp,bx,r12-15 not saved */
 	CFI_ADJUST_CFA_OFFSET 10*8
 
@@ -506,12 +506,12 @@ ENTRY(ia32_syscall)
 	movl	%eax,%eax
 
 	/* Construct struct pt_regs on stack (iret frame is already on stack) */
-	pushq_cfi_reg	rax			/* pt_regs->orig_ax */
-	pushq_cfi_reg	rdi			/* pt_regs->di */
-	pushq_cfi_reg	rsi			/* pt_regs->si */
-	pushq_cfi_reg	rdx			/* pt_regs->dx */
-	pushq_cfi_reg	rcx			/* pt_regs->cx */
-	pushq_cfi	$-ENOSYS		/* pt_regs->ax */
+	push_cfi_reg	rax			/* pt_regs->orig_ax */
+	push_cfi_reg	rdi			/* pt_regs->di */
+	push_cfi_reg	rsi			/* pt_regs->si */
+	push_cfi_reg	rdx			/* pt_regs->dx */
+	push_cfi_reg	rcx			/* pt_regs->cx */
+	push_cfi	$-ENOSYS		/* pt_regs->ax */
 	cld
 	sub	$(10*8),%rsp /* pt_regs->r8-11,bp,bx,r12-15 not saved */
 	CFI_ADJUST_CFA_OFFSET 10*8
arch/x86/include/asm/calling.h +14 -14
index 1c8b50e..4abc60f 100644
@@ -224,23 +224,23 @@ For 32-bit we have the following conventions - kernel is built with
  */
 
 	.macro SAVE_ALL
-	pushl_cfi_reg eax
-	pushl_cfi_reg ebp
-	pushl_cfi_reg edi
-	pushl_cfi_reg esi
-	pushl_cfi_reg edx
-	pushl_cfi_reg ecx
-	pushl_cfi_reg ebx
+	push_cfi_reg eax
+	push_cfi_reg ebp
+	push_cfi_reg edi
+	push_cfi_reg esi
+	push_cfi_reg edx
+	push_cfi_reg ecx
+	push_cfi_reg ebx
 	.endm
 
 	.macro RESTORE_ALL
-	popl_cfi_reg ebx
-	popl_cfi_reg ecx
-	popl_cfi_reg edx
-	popl_cfi_reg esi
-	popl_cfi_reg edi
-	popl_cfi_reg ebp
-	popl_cfi_reg eax
+	pop_cfi_reg ebx
+	pop_cfi_reg ecx
+	pop_cfi_reg edx
+	pop_cfi_reg esi
+	pop_cfi_reg edi
+	pop_cfi_reg ebp
+	pop_cfi_reg eax
 	.endm
 
 #endif /* CONFIG_X86_64 */
arch/x86/include/asm/dwarf2.h +32 -60

124 lines not on this page · raw message

arch/x86/include/asm/frame.h +2 -2
index 3b629f4..325e4e8 100644
@@ -8,12 +8,12 @@
    frame pointer later */
 #ifdef CONFIG_FRAME_POINTER
 	.macro FRAME
-	__ASM_SIZE(push,_cfi)	%__ASM_REG(bp)
+	push_cfi		%__ASM_REG(bp)
 	CFI_REL_OFFSET		__ASM_REG(bp), 0
 	__ASM_SIZE(mov)		%__ASM_REG(sp), %__ASM_REG(bp)
 	.endm
 	.macro ENDFRAME
-	__ASM_SIZE(pop,_cfi)	%__ASM_REG(bp)
+	pop_cfi			%__ASM_REG(bp)
 	CFI_RESTORE		__ASM_REG(bp)
 	.endm
 #else
arch/x86/kernel/entry_32.S +107 -107

533 lines not on this page · raw message

arch/x86/kernel/entry_64.S +48 -48

242 lines not on this page · raw message

arch/x86/lib/atomic64_386_32.S +2 -2
index 00933d5..aa17c69 100644
@@ -15,12 +15,12 @@
 
 /* if you want SMP support, implement these with real spinlocks */
 .macro LOCK reg
-	pushfl_cfi
+	pushf_cfi
 	cli
 .endm
 
 .macro UNLOCK reg
-	popfl_cfi
+	popf_cfi
 .endm
 
 #define BEGIN(op) \
arch/x86/lib/atomic64_cx8_32.S +20 -20
index 082a851..c5dd086 100644
@@ -57,10 +57,10 @@ ENDPROC(atomic64_xchg_cx8)
 .macro addsub_return func ins insc
 ENTRY(atomic64_\func\()_return_cx8)
 	CFI_STARTPROC
-	pushl_cfi_reg ebp
-	pushl_cfi_reg ebx
-	pushl_cfi_reg esi
-	pushl_cfi_reg edi
+	push_cfi_reg ebp
+	push_cfi_reg ebx
+	push_cfi_reg esi
+	push_cfi_reg edi
 
 	movl %eax, %esi
 	movl %edx, %edi
@@ -79,10 +79,10 @@ ENTRY(atomic64_\func\()_return_cx8)
 10:
 	movl %ebx, %eax
 	movl %ecx, %edx
-	popl_cfi_reg edi
-	popl_cfi_reg esi
-	popl_cfi_reg ebx
-	popl_cfi_reg ebp
+	pop_cfi_reg edi
+	pop_cfi_reg esi
+	pop_cfi_reg ebx
+	pop_cfi_reg ebp
 	ret
 	CFI_ENDPROC
 ENDPROC(atomic64_\func\()_return_cx8)
@@ -94,7 +94,7 @@ addsub_return sub sub sbb
 .macro incdec_return func ins insc
 ENTRY(atomic64_\func\()_return_cx8)
 	CFI_STARTPROC
-	pushl_cfi_reg ebx
+	push_cfi_reg ebx
 
 	read64 %esi
 1:
@@ -109,7 +109,7 @@ ENTRY(atomic64_\func\()_return_cx8)
 10:
 	movl %ebx, %eax
 	movl %ecx, %edx
-	popl_cfi_reg ebx
+	pop_cfi_reg ebx
 	ret
 	CFI_ENDPROC
 ENDPROC(atomic64_\func\()_return_cx8)
@@ -120,7 +120,7 @@ incdec_return dec sub sbb
 
 ENTRY(atomic64_dec_if_positive_cx8)
 	CFI_STARTPROC
-	pushl_cfi_reg ebx
+	push_cfi_reg ebx
 
 	read64 %esi
 1:
@@ -136,18 +136,18 @@ ENTRY(atomic64_dec_if_positive_cx8)
 2:
 	movl %ebx, %eax
 	movl %ecx, %edx
-	popl_cfi_reg ebx
+	pop_cfi_reg ebx
 	ret
 	CFI_ENDPROC
 ENDPROC(atomic64_dec_if_positive_cx8)
 
 ENTRY(atomic64_add_unless_cx8)
 	CFI_STARTPROC
-	pushl_cfi_reg ebp
-	pushl_cfi_reg ebx
+	push_cfi_reg ebp
+	push_cfi_reg ebx
 /* these just push these two parameters on the stack */
-	pushl_cfi_reg edi
-	pushl_cfi_reg ecx
+	push_cfi_reg edi
+	push_cfi_reg ecx
 
 	movl %eax, %ebp
 	movl %edx, %edi
@@ -169,8 +169,8 @@ ENTRY(atomic64_add_unless_cx8)
 3:
 	addl $8, %esp
 	CFI_ADJUST_CFA_OFFSET -8
-	popl_cfi_reg ebx
-	popl_cfi_reg ebp
+	pop_cfi_reg ebx
+	pop_cfi_reg ebp
 	ret
 4:
 	cmpl %edx, 4(%esp)
@@ -182,7 +182,7 @@ ENDPROC(atomic64_add_unless_cx8)
 
 ENTRY(atomic64_inc_not_zero_cx8)
 	CFI_STARTPROC
-	pushl_cfi_reg ebx
+	push_cfi_reg ebx
 
 	read64 %esi
 1:
@@ -199,7 +199,7 @@ ENTRY(atomic64_inc_not_zero_cx8)
 
 	movl $1, %eax
 3:
-	popl_cfi_reg ebx
+	pop_cfi_reg ebx
 	ret
 	CFI_ENDPROC
 ENDPROC(atomic64_inc_not_zero_cx8)
arch/x86/lib/checksum_32.S +21 -21

90 lines not on this page · raw message

arch/x86/lib/cmpxchg16b_emu.S +3 -3
index 40a1725..b18f317 100644
@@ -32,7 +32,7 @@ CFI_STARTPROC
 # *atomic* on a single cpu (as provided by the this_cpu_xx class of
 # macros).
 #
-	pushfq_cfi
+	pushf_cfi
 	cli
 
 	cmpq PER_CPU_VAR((%rsi)), %rax
@@ -44,13 +44,13 @@ CFI_STARTPROC
 	movq %rcx, PER_CPU_VAR(8(%rsi))
 
 	CFI_REMEMBER_STATE
-	popfq_cfi
+	popf_cfi
 	mov $1, %al
 	ret
 
 	CFI_RESTORE_STATE
 .Lnot_same:
-	popfq_cfi
+	popf_cfi
 	xor %al,%al
 	ret
 
arch/x86/lib/cmpxchg8b_emu.S +3 -3
index b4807fce..a4862d0 100644
@@ -27,7 +27,7 @@ CFI_STARTPROC
 # set the whole ZF thing (caller will just compare
 # eax:edx with the expected value)
 #
-	pushfl_cfi
+	pushf_cfi
 	cli
 
 	cmpl  (%esi), %eax
@@ -39,7 +39,7 @@ CFI_STARTPROC
 	movl %ecx, 4(%esi)
 
 	CFI_REMEMBER_STATE
-	popfl_cfi
+	popf_cfi
 	ret
 
 	CFI_RESTORE_STATE
@@ -48,7 +48,7 @@ CFI_STARTPROC
 .Lhalf_same:
 	movl 4(%esi), %edx
 
-	popfl_cfi
+	popf_cfi
 	ret
 
 CFI_ENDPROC
arch/x86/lib/msr-reg.S +17 -17
index 3ca5218..046a560 100644
@@ -14,8 +14,8 @@
 .macro op_safe_regs op
 ENTRY(\op\()_safe_regs)
 	CFI_STARTPROC
-	pushq_cfi_reg rbx
-	pushq_cfi_reg rbp
+	push_cfi_reg rbx
+	push_cfi_reg rbp
 	movq	%rdi, %r10	/* Save pointer */
 	xorl	%r11d, %r11d	/* Return value */
 	movl    (%rdi), %eax
@@ -35,8 +35,8 @@ ENTRY(\op\()_safe_regs)
 	movl    %ebp, 20(%r10)
 	movl    %esi, 24(%r10)
 	movl    %edi, 28(%r10)
-	popq_cfi_reg rbp
-	popq_cfi_reg rbx
+	pop_cfi_reg rbp
+	pop_cfi_reg rbx
 	ret
 3:
 	CFI_RESTORE_STATE
@@ -53,12 +53,12 @@ ENDPROC(\op\()_safe_regs)
 .macro op_safe_regs op
 ENTRY(\op\()_safe_regs)
 	CFI_STARTPROC
-	pushl_cfi_reg ebx
-	pushl_cfi_reg ebp
-	pushl_cfi_reg esi
-	pushl_cfi_reg edi
-	pushl_cfi $0              /* Return value */
-	pushl_cfi %eax
+	push_cfi_reg ebx
+	push_cfi_reg ebp
+	push_cfi_reg esi
+	push_cfi_reg edi
+	push_cfi $0              /* Return value */
+	push_cfi %eax
 	movl    4(%eax), %ecx
 	movl    8(%eax), %edx
 	movl    12(%eax), %ebx
@@ -68,9 +68,9 @@ ENTRY(\op\()_safe_regs)
 	movl    (%eax), %eax
 	CFI_REMEMBER_STATE
 1:	\op
-2:	pushl_cfi %eax
+2:	push_cfi %eax
 	movl    4(%esp), %eax
-	popl_cfi (%eax)
+	pop_cfi (%eax)
 	addl    $4, %esp
 	CFI_ADJUST_CFA_OFFSET -4
 	movl    %ecx, 4(%eax)
@@ -79,11 +79,11 @@ ENTRY(\op\()_safe_regs)
 	movl    %ebp, 20(%eax)
 	movl    %esi, 24(%eax)
 	movl    %edi, 28(%eax)
-	popl_cfi %eax
-	popl_cfi_reg edi
-	popl_cfi_reg esi
-	popl_cfi_reg ebp
-	popl_cfi_reg ebx
+	pop_cfi %eax
+	pop_cfi_reg edi
+	pop_cfi_reg esi
+	pop_cfi_reg ebp
+	pop_cfi_reg ebx
 	ret
 3:
 	CFI_RESTORE_STATE
arch/x86/lib/rwsem.S +20 -20
index 2322abe..c630a80 100644
@@ -34,10 +34,10 @@
  */
 
 #define save_common_regs \
-	pushl_cfi_reg ecx
+	push_cfi_reg ecx
 
 #define restore_common_regs \
-	popl_cfi_reg ecx
+	pop_cfi_reg ecx
 
 	/* Avoid uglifying the argument copying x86-64 needs to do. */
 	.macro movq src, dst
@@ -64,22 +64,22 @@
  */
 
 #define save_common_regs \
-	pushq_cfi_reg rdi; \
-	pushq_cfi_reg rsi; \
-	pushq_cfi_reg rcx; \
-	pushq_cfi_reg r8;  \
-	pushq_cfi_reg r9;  \
-	pushq_cfi_reg r10; \
-	pushq_cfi_reg r11
+	push_cfi_reg rdi; \
+	push_cfi_reg rsi; \
+	push_cfi_reg rcx; \
+	push_cfi_reg r8;  \
+	push_cfi_reg r9;  \
+	push_cfi_reg r10; \
+	push_cfi_reg r11
 
 #define restore_common_regs \
-	popq_cfi_reg r11; \
-	popq_cfi_reg r10; \
-	popq_cfi_reg r9; \
-	popq_cfi_reg r8; \
-	popq_cfi_reg rcx; \
-	popq_cfi_reg rsi; \
-	popq_cfi_reg rdi
+	pop_cfi_reg r11; \
+	pop_cfi_reg r10; \
+	pop_cfi_reg r9; \
+	pop_cfi_reg r8; \
+	pop_cfi_reg rcx; \
+	pop_cfi_reg rsi; \
+	pop_cfi_reg rdi
 
 #endif
 
@@ -87,10 +87,10 @@
 ENTRY(call_rwsem_down_read_failed)
 	CFI_STARTPROC
 	save_common_regs
-	__ASM_SIZE(push,_cfi_reg) __ASM_REG(dx)
+	push_cfi_reg __ASM_REG(dx)
 	movq %rax,%rdi
 	call rwsem_down_read_failed
-	__ASM_SIZE(pop,_cfi_reg) __ASM_REG(dx)
+	pop_cfi_reg __ASM_REG(dx)
 	restore_common_regs
 	ret
 	CFI_ENDPROC
@@ -122,10 +122,10 @@ ENDPROC(call_rwsem_wake)
 ENTRY(call_rwsem_downgrade_wake)
 	CFI_STARTPROC
 	save_common_regs
-	__ASM_SIZE(push,_cfi_reg) __ASM_REG(dx)
+	push_cfi_reg __ASM_REG(dx)
 	movq %rax,%rdi
 	call rwsem_downgrade_wake
-	__ASM_SIZE(pop,_cfi_reg) __ASM_REG(dx)
+	pop_cfi_reg __ASM_REG(dx)
 	restore_common_regs
 	ret
 	CFI_ENDPROC
arch/x86/lib/thunk_32.S +6 -6
index 5eb7150..bb370de 100644
@@ -13,9 +13,9 @@
 	.globl \name
 \name:
 	CFI_STARTPROC
-	pushl_cfi_reg eax
-	pushl_cfi_reg ecx
-	pushl_cfi_reg edx
+	push_cfi_reg eax
+	push_cfi_reg ecx
+	push_cfi_reg edx
 
 	.if \put_ret_addr_in_eax
 	/* Place EIP in the arg1 */
@@ -23,9 +23,9 @@
 	.endif
 
 	call \func
-	popl_cfi_reg edx
-	popl_cfi_reg ecx
-	popl_cfi_reg eax
+	pop_cfi_reg edx
+	pop_cfi_reg ecx
+	pop_cfi_reg eax
 	ret
 	CFI_ENDPROC
 	_ASM_NOKPROBE(\name)
arch/x86/lib/thunk_64.S +18 -18
index f89ba4e9..39ad268 100644
@@ -17,15 +17,15 @@
 	CFI_STARTPROC
 
 	/* this one pushes 9 elems, the next one would be %rIP */
-	pushq_cfi_reg rdi
-	pushq_cfi_reg rsi
-	pushq_cfi_reg rdx
-	pushq_cfi_reg rcx
-	pushq_cfi_reg rax
-	pushq_cfi_reg r8
-	pushq_cfi_reg r9
-	pushq_cfi_reg r10
-	pushq_cfi_reg r11
+	push_cfi_reg rdi
+	push_cfi_reg rsi
+	push_cfi_reg rdx
+	push_cfi_reg rcx
+	push_cfi_reg rax
+	push_cfi_reg r8
+	push_cfi_reg r9
+	push_cfi_reg r10
+	push_cfi_reg r11
 
 	.if \put_ret_addr_in_rdi
 	/* 9*8(%rsp) is return addr on stack */
@@ -60,15 +60,15 @@
 	CFI_STARTPROC
 	CFI_ADJUST_CFA_OFFSET 9*8
 restore:
-	popq_cfi_reg r11
-	popq_cfi_reg r10
-	popq_cfi_reg r9
-	popq_cfi_reg r8
-	popq_cfi_reg rax
-	popq_cfi_reg rcx
-	popq_cfi_reg rdx
-	popq_cfi_reg rsi
-	popq_cfi_reg rdi
+	pop_cfi_reg r11
+	pop_cfi_reg r10
+	pop_cfi_reg r9
+	pop_cfi_reg r8
+	pop_cfi_reg rax
+	pop_cfi_reg rcx
+	pop_cfi_reg rdx
+	pop_cfi_reg rsi
+	pop_cfi_reg rdi
 	ret
 	CFI_ENDPROC
 	_ASM_NOKPROBE(restore)
Signature · 1 line
2.1.0
#339 lore raw

PATCH v4 3/3 x86, stackvalidate: Add asm frame pointer setup macros

In reply to Josh Poimboeuf

Add some helper macros for asm functions so that they can comply with stackvalidate.

The FUNC_ENTER and FUNC_RETURN macros help asm functions save, set up, and restore frame pointers.

The RET_NOVALIDATE and FILE_NOVALIDATE macros can be used to whitelist the few locations which need a return instruction outside of a callable function.

---
 arch/x86/include/asm/func.h | 82 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)
 create mode 100644 arch/x86/include/asm/func.h
arch/x86/include/asm/func.h new file +82 -0
new file mode 100644
index 0000000..cd27ad4
@@ -0,0 +1,82 @@
+#ifndef _ASM_X86_FUNC_H
+#define _ASM_X86_FUNC_H
+
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+#include <asm/asm.h>
+
+.macro FUNC_ENTER_NO_FP name
+	ENTRY(\name)
+	CFI_STARTPROC
+	CFI_DEF_CFA _ASM_SP, __ASM_SEL(4, 8)
+.endm
+
+.macro FUNC_RETURN_NO_FP name
+	CFI_DEF_CFA _ASM_SP, __ASM_SEL(4, 8)
+	ret
+	CFI_ENDPROC
+	ENDPROC(\name)
+.endm
+
+#ifdef CONFIG_FRAME_POINTER
+
+.macro FUNC_ENTER_FP name
+	FUNC_ENTER_NO_FP \name
+	push_cfi %_ASM_BP
+	CFI_REL_OFFSET _ASM_BP, 0
+	_ASM_MOV %_ASM_SP, %_ASM_BP
+	CFI_DEF_CFA_REGISTER _ASM_BP
+.endm
+
+.macro FUNC_RETURN_FP name
+	pop_cfi %_ASM_BP
+	CFI_RESTORE _ASM_BP
+	FUNC_RETURN_NO_FP \name
+.endm
+
+/*
+ * Every callable asm function should be bookended with FUNC_ENTER and
+ * FUNC_RETURN.  They do proper frame pointer and DWARF CFI setups in order to
+ * achieve more reliable stack traces.
+ *
+ * For the sake of simplicity and correct DWARF annotations, use of the macros
+ * requires that the return instruction comes at the end of the function.
+ */
+#define FUNC_ENTER(name) FUNC_ENTER_FP name
+#define FUNC_RETURN(name) FUNC_RETURN_FP name
+
+/*
+ * RET_NOVALIDATE tells the stack validation script to whitelist the return
+ * instruction immediately after the macro.  Only use it if you're completely
+ * sure you need a return instruction outside of a callable function.
+ * Otherwise, if the code can be called and you haven't annotated it with
+ * FUNC_ENTER/FUNC_RETURN, it will break stack trace reliability.
+ */
+.macro RET_NOVALIDATE
+	163:
+	.pushsection __stackvalidate_whitelist_ret, "ae"
+	_ASM_ALIGN
+	.long 163b - .
+	.popsection
+.endm
+
+/*
+ * FILE_NOVALIDATE is like RET_NOVALIDATE except it whitelists the entire file.
+ * Use with extreme caution or you will silently break stack traces.
+ */
+.macro FILE_NOVALIDATE
+	.pushsection __stackvalidate_whitelist_file, "ae"
+	.long 0
+	.popsection
+.endm
+
+#else /* !FRAME_POINTER */
+
+#define FUNC_ENTER(name) FUNC_ENTER_NO_FP name
+#define FUNC_RETURN(name) FUNC_RETURN_NO_FP name
+#define RET_NOVALIDATE
+#define FILE_NOVALIDATE
+
+#endif /* FRAME_POINTER */
+
+#endif /* _ASM_X86_FUNC_H */
Signature · 1 line
2.1.0
#340 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

In reply to Josh Poimboeuf
Quoted 16 lines · Josh Poimboeuf

In discussions around the live kernel patching consistency model RFC [1], Peter and Ingo correctly pointed out that stack traces aren't reliable. And as Ingo said, there's no "strong force" which ensures we can rely on them.

So I've been thinking about how to fix that. My goal is to eventually make stack traces reliable. Or at the very least, to be able to detect at runtime when a given stack trace *might* be unreliable. But improved stack traces would broadly benefit the entire kernel, regardless of the outcome of the live kernel patching consistency model discussions.

This patch set is just the first in a series of proposed stack trace reliability improvements. Future proposals will include runtime stack reliability checking, as well as compile-time and runtime DWARF validations.

Quoted 5 lines

As far as I can tell, there are two main obstacles which prevent frame pointer based stack traces from being reliable:

1) Missing frame pointer logic: currently, most assembly functions don't set up the frame pointer.

Could you please paste here the output of what the new checks print for x86/64 defconfig?

Quoted 4 lines

As a first step, all reported non-compliances result in warnings. Right now I'm seeing 200+ warnings. Once we get them all cleaned up, we can change the warnings to build errors so the asm code can stay clean.

That's quite a bit ...

Thanks,

Ingo

#341 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

Quoted 19 lines · Ingo Molnar
Quoted 16 lines · Josh Poimboeuf

In discussions around the live kernel patching consistency model RFC [1], Peter and Ingo correctly pointed out that stack traces aren't reliable. And as Ingo said, there's no "strong force" which ensures we can rely on them.

So I've been thinking about how to fix that. My goal is to eventually make stack traces reliable. Or at the very least, to be able to detect at runtime when a given stack trace *might* be unreliable. But improved stack traces would broadly benefit the entire kernel, regardless of the outcome of the live kernel patching consistency model discussions.

This patch set is just the first in a series of proposed stack trace reliability improvements. Future proposals will include runtime stack reliability checking, as well as compile-time and runtime DWARF validations.

Quoted 8 lines
Quoted 5 lines

As far as I can tell, there are two main obstacles which prevent frame pointer based stack traces from being reliable:

1) Missing frame pointer logic: currently, most assembly functions don't set up the frame pointer.

Could you please paste here the output of what the new checks print for x86/64 defconfig?

Here are all 89 warnings from defconfig:

arch/x86/ia32/ia32entry.o: ia32_sysenter_target() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/ia32/ia32entry.o: return instruction outside of a function at .entry.text+0x52e. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x359. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x19be. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x19e5. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x1c21. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x1ceb. Please use FUNC_ENTER. arch/x86/kernel/acpi/wakeup_64.o: wakeup_long64() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/kernel/acpi/wakeup_64.o: do_suspend_lowlevel() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/platform/efi/efi_stub_64.o: efi_call() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x6b. Please use FUNC_ENTER. arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0xc7. Please use FUNC_ENTER.

arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x110.  Please use FUNC_ENTER.
arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x145.  Please use FUNC_ENTER.
arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x1c4.  Please use FUNC_ENTER.
arch/x86/realmode/rm/trampoline_64.o: return instruction outside of a function at .text+0x170.  Please use FUNC_ENTER.
arch/x86/realmode/rm/trampoline_64.o: return instruction outside of a function at .text+0x176.  Please use FUNC_ENTER.

arch/x86/kernel/head_64.o: return instruction outside of a function at .head.text+0x1a2. Please use FUNC_ENTER. arch/x86/kernel/head_64.o: start_cpu0() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/kernel/head_64.o: early_idt_handler() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/reboot.o: return instruction outside of a function at .text+0x2a. Please use FUNC_ENTER. arch/x86/realmode/rm/copy.o: memcpy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/copy.o: memset() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/copy.o: copy_from_fs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/copy.o: copy_to_fs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/bioscall.o: intcall() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/int80.o: __kernel_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/int80.o: __kernel_rt_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/int80.o: __kernel_vsyscall() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/syscall.o: __kernel_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/syscall.o: __kernel_rt_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/syscall.o: __kernel_vsyscall() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/sysenter.o: __kernel_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/sysenter.o: __kernel_rt_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/power/hibernate_asm_64.o: return instruction outside of a function at .text+0x69. Please use FUNC_ENTER. arch/x86/power/hibernate_asm_64.o: return instruction outside of a function at .text+0x16d. Please use FUNC_ENTER. arch/x86/lib/msr-reg.o: rdmsr_safe_regs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/msr-reg.o: wrmsr_safe_regs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/iomap_copy_64.o: __iowrite32_copy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/clear_page_64.o: clear_page() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/clear_page_64.o: clear_page_orig() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/clear_page_64.o: clear_page_c_e() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/cmpxchg16b_emu.o: this_cpu_cmpxchg16b_emu() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_page_64.o: copy_page() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_page_64.o: copy_page_regs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: _copy_to_user() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: _copy_from_user() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: copy_user_generic_unrolled() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: copy_user_generic_string() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: copy_user_enhanced_fast_string() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: __copy_user_nocache() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: bad_from_user() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/csum-copy_64.o: csum_partial_copy_generic() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: __get_user_1() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: __get_user_2() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: __get_user_4() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: __get_user_8() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: return instruction outside of a function at .text+0xc5. Please use FUNC_ENTER. arch/x86/lib/memcpy_64.o: memcpy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memcpy_64.o: __memcpy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memcpy_64.o: memcpy_erms() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memcpy_64.o: memcpy_orig() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memmove_64.o: memmove() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memmove_64.o: __memmove() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memmove_64.o: return instruction outside of a function at .altinstr_replacement+0x5. Please use FUNC_ENTER. arch/x86/lib/memset_64.o: memset() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memset_64.o: __memset() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memset_64.o: memset_erms() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memset_64.o: memset_orig() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: __put_user_1() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: __put_user_2() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: __put_user_4() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: __put_user_8() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: return instruction outside of a function at .text+0xc1. Please use FUNC_ENTER. arch/x86/lib/rwsem.o: call_rwsem_down_read_failed() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/rwsem.o: call_rwsem_down_write_failed() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/rwsem.o: call_rwsem_wake() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/rwsem.o: call_rwsem_downgrade_wake() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/bioscall.o: intcall() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/copy.o: memcpy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/copy.o: memset() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/copy.o: copy_from_fs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/copy.o: copy_to_fs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/pmjump.o: protected_mode_jump() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/pmjump.o: in_pm32() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/compressed/head_64.o: return instruction outside of a function at .text+0x16e. Please use FUNC_ENTER. arch/x86/boot/compressed/head_64.o: return instruction outside of a function at .text+0x172. Please use FUNC_ENTER. arch/x86/boot/compressed/head_64.o: startup_32() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/header.o: die() is missing frame pointer logic. Please use FUNC_ENTER.

Quoted 6 lines
Quoted 4 lines

As a first step, all reported non-compliances result in warnings. Right now I'm seeing 200+ warnings. Once we get them all cleaned up, we can change the warnings to build errors so the asm code can stay clean.

That's quite a bit ...

Yeah, a Fedora-based config has over 200 warnings. Most of the differences between the above 89 warnings for defconfig and the 200+ for a Fedora config seem to be caused by xen, crypto and bpf.

Signature · 1 line
Josh
#342 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

Quoted 112 lines · Josh Poimboeuf
Quoted 19 lines · Ingo Molnar
Quoted 16 lines · Josh Poimboeuf

In discussions around the live kernel patching consistency model RFC [1], Peter and Ingo correctly pointed out that stack traces aren't reliable. And as Ingo said, there's no "strong force" which ensures we can rely on them.

So I've been thinking about how to fix that. My goal is to eventually make stack traces reliable. Or at the very least, to be able to detect at runtime when a given stack trace *might* be unreliable. But improved stack traces would broadly benefit the entire kernel, regardless of the outcome of the live kernel patching consistency model discussions.

This patch set is just the first in a series of proposed stack trace reliability improvements. Future proposals will include runtime stack reliability checking, as well as compile-time and runtime DWARF validations.

Quoted 8 lines
Quoted 5 lines

As far as I can tell, there are two main obstacles which prevent frame pointer based stack traces from being reliable:

1) Missing frame pointer logic: currently, most assembly functions don't set up the frame pointer.

Could you please paste here the output of what the new checks print for x86/64 defconfig?

Here are all 89 warnings from defconfig:

arch/x86/ia32/ia32entry.o: ia32_sysenter_target() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/ia32/ia32entry.o: return instruction outside of a function at .entry.text+0x52e. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x359. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x19be. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x19e5. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x1c21. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x1ceb. Please use FUNC_ENTER. arch/x86/kernel/acpi/wakeup_64.o: wakeup_long64() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/kernel/acpi/wakeup_64.o: do_suspend_lowlevel() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/platform/efi/efi_stub_64.o: efi_call() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x6b. Please use FUNC_ENTER. arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0xc7. Please use FUNC_ENTER.

arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x110.  Please use FUNC_ENTER.
arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x145.  Please use FUNC_ENTER.
arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x1c4.  Please use FUNC_ENTER.
arch/x86/realmode/rm/trampoline_64.o: return instruction outside of a function at .text+0x170.  Please use FUNC_ENTER.
arch/x86/realmode/rm/trampoline_64.o: return instruction outside of a function at .text+0x176.  Please use FUNC_ENTER.

arch/x86/kernel/head_64.o: return instruction outside of a function at .head.text+0x1a2. Please use FUNC_ENTER. arch/x86/kernel/head_64.o: start_cpu0() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/kernel/head_64.o: early_idt_handler() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/reboot.o: return instruction outside of a function at .text+0x2a. Please use FUNC_ENTER. arch/x86/realmode/rm/copy.o: memcpy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/copy.o: memset() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/copy.o: copy_from_fs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/copy.o: copy_to_fs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/bioscall.o: intcall() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/int80.o: __kernel_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/int80.o: __kernel_rt_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/int80.o: __kernel_vsyscall() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/syscall.o: __kernel_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/syscall.o: __kernel_rt_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/syscall.o: __kernel_vsyscall() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/sysenter.o: __kernel_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/sysenter.o: __kernel_rt_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/power/hibernate_asm_64.o: return instruction outside of a function at .text+0x69. Please use FUNC_ENTER. arch/x86/power/hibernate_asm_64.o: return instruction outside of a function at .text+0x16d. Please use FUNC_ENTER. arch/x86/lib/msr-reg.o: rdmsr_safe_regs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/msr-reg.o: wrmsr_safe_regs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/iomap_copy_64.o: __iowrite32_copy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/clear_page_64.o: clear_page() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/clear_page_64.o: clear_page_orig() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/clear_page_64.o: clear_page_c_e() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/cmpxchg16b_emu.o: this_cpu_cmpxchg16b_emu() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_page_64.o: copy_page() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_page_64.o: copy_page_regs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: _copy_to_user() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: _copy_from_user() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: copy_user_generic_unrolled() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: copy_user_generic_string() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: copy_user_enhanced_fast_string() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: __copy_user_nocache() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: bad_from_user() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/csum-copy_64.o: csum_partial_copy_generic() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: __get_user_1() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: __get_user_2() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: __get_user_4() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: __get_user_8() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: return instruction outside of a function at .text+0xc5. Please use FUNC_ENTER. arch/x86/lib/memcpy_64.o: memcpy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memcpy_64.o: __memcpy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memcpy_64.o: memcpy_erms() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memcpy_64.o: memcpy_orig() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memmove_64.o: memmove() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memmove_64.o: __memmove() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memmove_64.o: return instruction outside of a function at .altinstr_replacement+0x5. Please use FUNC_ENTER. arch/x86/lib/memset_64.o: memset() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memset_64.o: __memset() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memset_64.o: memset_erms() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memset_64.o: memset_orig() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: __put_user_1() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: __put_user_2() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: __put_user_4() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: __put_user_8() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: return instruction outside of a function at .text+0xc1. Please use FUNC_ENTER. arch/x86/lib/rwsem.o: call_rwsem_down_read_failed() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/rwsem.o: call_rwsem_down_write_failed() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/rwsem.o: call_rwsem_wake() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/rwsem.o: call_rwsem_downgrade_wake() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/bioscall.o: intcall() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/copy.o: memcpy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/copy.o: memset() is missing frame pointer logic. Please use FUNC_ENTER.

Quoted 8 lines

arch/x86/boot/copy.o: copy_from_fs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/copy.o: copy_to_fs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/pmjump.o: protected_mode_jump() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/pmjump.o: in_pm32() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/compressed/head_64.o: return instruction outside of a function at .text+0x16e. Please use FUNC_ENTER. arch/x86/boot/compressed/head_64.o: return instruction outside of a function at .text+0x172. Please use FUNC_ENTER. arch/x86/boot/compressed/head_64.o: startup_32() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/header.o: die() is missing frame pointer logic. Please use FUNC_ENTER.

Yeah, so many of these seem to be 'leaf only' functions: functions that don't ever call functions themselves.

So lets assume we always have CONFIG_FRAME_POINTERS=y.

If they don't set up a frame pointer then they in essence won't show up in the call chain - but normally they wouldn't because they call nothing.

If they trigger an exception/fault or if they get hit by an interrupt then I think we'll still correctly walk the stack - just those functions might be missing from the deterministic call chain, right? (it will still show up as a '?' entry.)

If they crash then we'll see them because the crashing RIP will be printed.

So I'm wondering what the x86 policy here should be: to create frame pointers in them or not. Cc:-ed a few more gents for thoughts.

Thanks,

Ingo

#343 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

Quoted 124 lines · Ingo Molnar
Quoted 112 lines · Josh Poimboeuf
Quoted 19 lines · Ingo Molnar
Quoted 16 lines · Josh Poimboeuf

In discussions around the live kernel patching consistency model RFC [1], Peter and Ingo correctly pointed out that stack traces aren't reliable. And as Ingo said, there's no "strong force" which ensures we can rely on them.

So I've been thinking about how to fix that. My goal is to eventually make stack traces reliable. Or at the very least, to be able to detect at runtime when a given stack trace *might* be unreliable. But improved stack traces would broadly benefit the entire kernel, regardless of the outcome of the live kernel patching consistency model discussions.

This patch set is just the first in a series of proposed stack trace reliability improvements. Future proposals will include runtime stack reliability checking, as well as compile-time and runtime DWARF validations.

Quoted 8 lines
Quoted 5 lines

As far as I can tell, there are two main obstacles which prevent frame pointer based stack traces from being reliable:

1) Missing frame pointer logic: currently, most assembly functions don't set up the frame pointer.

Could you please paste here the output of what the new checks print for x86/64 defconfig?

Here are all 89 warnings from defconfig:

arch/x86/ia32/ia32entry.o: ia32_sysenter_target() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/ia32/ia32entry.o: return instruction outside of a function at .entry.text+0x52e. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x359. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x19be. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x19e5. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x1c21. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x1ceb. Please use FUNC_ENTER. arch/x86/kernel/acpi/wakeup_64.o: wakeup_long64() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/kernel/acpi/wakeup_64.o: do_suspend_lowlevel() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/platform/efi/efi_stub_64.o: efi_call() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x6b. Please use FUNC_ENTER. arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0xc7. Please use FUNC_ENTER.

arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x110.  Please use FUNC_ENTER.
arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x145.  Please use FUNC_ENTER.
arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x1c4.  Please use FUNC_ENTER.
arch/x86/realmode/rm/trampoline_64.o: return instruction outside of a function at .text+0x170.  Please use FUNC_ENTER.
arch/x86/realmode/rm/trampoline_64.o: return instruction outside of a function at .text+0x176.  Please use FUNC_ENTER.

arch/x86/kernel/head_64.o: return instruction outside of a function at .head.text+0x1a2. Please use FUNC_ENTER. arch/x86/kernel/head_64.o: start_cpu0() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/kernel/head_64.o: early_idt_handler() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/reboot.o: return instruction outside of a function at .text+0x2a. Please use FUNC_ENTER. arch/x86/realmode/rm/copy.o: memcpy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/copy.o: memset() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/copy.o: copy_from_fs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/copy.o: copy_to_fs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/bioscall.o: intcall() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/int80.o: __kernel_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/int80.o: __kernel_rt_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/int80.o: __kernel_vsyscall() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/syscall.o: __kernel_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/syscall.o: __kernel_rt_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/syscall.o: __kernel_vsyscall() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/sysenter.o: __kernel_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/sysenter.o: __kernel_rt_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/power/hibernate_asm_64.o: return instruction outside of a function at .text+0x69. Please use FUNC_ENTER. arch/x86/power/hibernate_asm_64.o: return instruction outside of a function at .text+0x16d. Please use FUNC_ENTER. arch/x86/lib/msr-reg.o: rdmsr_safe_regs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/msr-reg.o: wrmsr_safe_regs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/iomap_copy_64.o: __iowrite32_copy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/clear_page_64.o: clear_page() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/clear_page_64.o: clear_page_orig() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/clear_page_64.o: clear_page_c_e() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/cmpxchg16b_emu.o: this_cpu_cmpxchg16b_emu() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_page_64.o: copy_page() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_page_64.o: copy_page_regs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: _copy_to_user() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: _copy_from_user() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: copy_user_generic_unrolled() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: copy_user_generic_string() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: copy_user_enhanced_fast_string() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: __copy_user_nocache() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: bad_from_user() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/csum-copy_64.o: csum_partial_copy_generic() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: __get_user_1() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: __get_user_2() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: __get_user_4() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: __get_user_8() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: return instruction outside of a function at .text+0xc5. Please use FUNC_ENTER. arch/x86/lib/memcpy_64.o: memcpy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memcpy_64.o: __memcpy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memcpy_64.o: memcpy_erms() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memcpy_64.o: memcpy_orig() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memmove_64.o: memmove() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memmove_64.o: __memmove() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memmove_64.o: return instruction outside of a function at .altinstr_replacement+0x5. Please use FUNC_ENTER. arch/x86/lib/memset_64.o: memset() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memset_64.o: __memset() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memset_64.o: memset_erms() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memset_64.o: memset_orig() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: __put_user_1() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: __put_user_2() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: __put_user_4() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: __put_user_8() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: return instruction outside of a function at .text+0xc1. Please use FUNC_ENTER. arch/x86/lib/rwsem.o: call_rwsem_down_read_failed() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/rwsem.o: call_rwsem_down_write_failed() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/rwsem.o: call_rwsem_wake() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/rwsem.o: call_rwsem_downgrade_wake() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/bioscall.o: intcall() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/copy.o: memcpy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/copy.o: memset() is missing frame pointer logic. Please use FUNC_ENTER.

Quoted 8 lines

arch/x86/boot/copy.o: copy_from_fs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/copy.o: copy_to_fs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/pmjump.o: protected_mode_jump() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/pmjump.o: in_pm32() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/compressed/head_64.o: return instruction outside of a function at .text+0x16e. Please use FUNC_ENTER. arch/x86/boot/compressed/head_64.o: return instruction outside of a function at .text+0x172. Please use FUNC_ENTER. arch/x86/boot/compressed/head_64.o: startup_32() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/header.o: die() is missing frame pointer logic. Please use FUNC_ENTER.

Quoted 2 lines

Yeah, so many of these seem to be 'leaf only' functions: functions that don't ever call functions themselves.

Yeah, good observation.

Quoted 4 lines

So lets assume we always have CONFIG_FRAME_POINTERS=y.

If they don't set up a frame pointer then they in essence won't show up in the call chain

It's actually the _caller_ of the asm function which gets skipped in the trace.

(Though it doesn't really matter -- either way it's unreliable.)

Quoted 6 lines

but normally they wouldn't because they call nothing.

If they trigger an exception/fault or if they get hit by an interrupt then I think we'll still correctly walk the stack - just those functions might be missing from the deterministic call chain, right? (it will still show up as a '?' entry.)

Right. This patch set takes the more conservative approach of requiring _all_ callable asm functions to have frame pointer logic. Which has the benefit of getting rid of some of the cases where we need the '?' stack entries.

Quoted 5 lines

If they crash then we'll see them because the crashing RIP will be printed.

So I'm wondering what the x86 policy here should be: to create frame pointers in them or not. Cc:-ed a few more gents for thoughts.

I agree that frame pointers aren't strictly necessary for leaf functions.

I could easily relax the stackvalidate restrictions to exclude the checking of leaf functions. In fact I think that would be more consistent with how gcc does it, so maybe that's a more reasonable approach.

Signature · 1 line
Josh
#344 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

Quoted 34 lines · Josh Poimboeuf
Quoted 2 lines · Ingo Molnar

Yeah, so many of these seem to be 'leaf only' functions: functions that don't ever call functions themselves.

Yeah, good observation.

Quoted 4 lines

So lets assume we always have CONFIG_FRAME_POINTERS=y.

If they don't set up a frame pointer then they in essence won't show up in the call chain

It's actually the _caller_ of the asm function which gets skipped in the trace.

(Though it doesn't really matter -- either way it's unreliable.)

Quoted 6 lines

but normally they wouldn't because they call nothing.

If they trigger an exception/fault or if they get hit by an interrupt then I think we'll still correctly walk the stack - just those functions might be missing from the deterministic call chain, right? (it will still show up as a '?' entry.)

Right. This patch set takes the more conservative approach of requiring _all_ callable asm functions to have frame pointer logic. Which has the benefit of getting rid of some of the cases where we need the '?' stack entries.

Quoted 5 lines

If they crash then we'll see them because the crashing RIP will be printed.

So I'm wondering what the x86 policy here should be: to create frame pointers in them or not. Cc:-ed a few more gents for thoughts.

Quoted 7 lines

I agree that frame pointers aren't strictly necessary for leaf functions.

I could easily relax the stackvalidate restrictions to exclude the checking of leaf functions. In fact I think that would be more consistent with how gcc does it, so maybe that's a more reasonable approach.

I remembered another reason why I went with the more conservative approach of requiring frame pointers in leaf functions.

It's often hard to pin down where an asm function begins and where it ends. For example, you might have something like:

ENTRY(callable_asm_func)
jmp label
ENDPROC(callable_asm_func)

label:
call some_c_function
ret

If we were to relax the stackvalidate restrictions then we'd miss that kind of (surprisingly common) situation, where a function jumps outside of its scope.

Then again, I guess it would be pretty easy to add checks for that.

Signature · 1 line
Josh
#345 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

In reply to Ingo Molnar
Quoted 129 lines · Ingo Molnar
Quoted 112 lines · Josh Poimboeuf
Quoted 19 lines · Ingo Molnar
Quoted 16 lines · Josh Poimboeuf

In discussions around the live kernel patching consistency model RFC [1], Peter and Ingo correctly pointed out that stack traces aren't reliable. And as Ingo said, there's no "strong force" which ensures we can rely on them.

So I've been thinking about how to fix that. My goal is to eventually make stack traces reliable. Or at the very least, to be able to detect at runtime when a given stack trace *might* be unreliable. But improved stack traces would broadly benefit the entire kernel, regardless of the outcome of the live kernel patching consistency model discussions.

This patch set is just the first in a series of proposed stack trace reliability improvements. Future proposals will include runtime stack reliability checking, as well as compile-time and runtime DWARF validations.

Quoted 8 lines
Quoted 5 lines

As far as I can tell, there are two main obstacles which prevent frame pointer based stack traces from being reliable:

1) Missing frame pointer logic: currently, most assembly functions don't set up the frame pointer.

Could you please paste here the output of what the new checks print for x86/64 defconfig?

Here are all 89 warnings from defconfig:

arch/x86/ia32/ia32entry.o: ia32_sysenter_target() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/ia32/ia32entry.o: return instruction outside of a function at .entry.text+0x52e. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x359. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x19be. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x19e5. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x1c21. Please use FUNC_ENTER. arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x1ceb. Please use FUNC_ENTER. arch/x86/kernel/acpi/wakeup_64.o: wakeup_long64() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/kernel/acpi/wakeup_64.o: do_suspend_lowlevel() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/platform/efi/efi_stub_64.o: efi_call() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x6b. Please use FUNC_ENTER. arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0xc7. Please use FUNC_ENTER.

arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x110.  Please use FUNC_ENTER.
arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x145.  Please use FUNC_ENTER.
arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x1c4.  Please use FUNC_ENTER.
arch/x86/realmode/rm/trampoline_64.o: return instruction outside of a function at .text+0x170.  Please use FUNC_ENTER.
arch/x86/realmode/rm/trampoline_64.o: return instruction outside of a function at .text+0x176.  Please use FUNC_ENTER.

arch/x86/kernel/head_64.o: return instruction outside of a function at .head.text+0x1a2. Please use FUNC_ENTER. arch/x86/kernel/head_64.o: start_cpu0() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/kernel/head_64.o: early_idt_handler() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/reboot.o: return instruction outside of a function at .text+0x2a. Please use FUNC_ENTER. arch/x86/realmode/rm/copy.o: memcpy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/copy.o: memset() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/copy.o: copy_from_fs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/copy.o: copy_to_fs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/realmode/rm/bioscall.o: intcall() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/int80.o: __kernel_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/int80.o: __kernel_rt_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/int80.o: __kernel_vsyscall() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/syscall.o: __kernel_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/syscall.o: __kernel_rt_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/syscall.o: __kernel_vsyscall() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/sysenter.o: __kernel_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/vdso/vdso32/sysenter.o: __kernel_rt_sigreturn() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/power/hibernate_asm_64.o: return instruction outside of a function at .text+0x69. Please use FUNC_ENTER. arch/x86/power/hibernate_asm_64.o: return instruction outside of a function at .text+0x16d. Please use FUNC_ENTER. arch/x86/lib/msr-reg.o: rdmsr_safe_regs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/msr-reg.o: wrmsr_safe_regs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/iomap_copy_64.o: __iowrite32_copy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/clear_page_64.o: clear_page() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/clear_page_64.o: clear_page_orig() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/clear_page_64.o: clear_page_c_e() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/cmpxchg16b_emu.o: this_cpu_cmpxchg16b_emu() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_page_64.o: copy_page() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_page_64.o: copy_page_regs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: _copy_to_user() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: _copy_from_user() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: copy_user_generic_unrolled() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: copy_user_generic_string() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: copy_user_enhanced_fast_string() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: __copy_user_nocache() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/copy_user_64.o: bad_from_user() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/csum-copy_64.o: csum_partial_copy_generic() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: __get_user_1() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: __get_user_2() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: __get_user_4() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: __get_user_8() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/getuser.o: return instruction outside of a function at .text+0xc5. Please use FUNC_ENTER. arch/x86/lib/memcpy_64.o: memcpy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memcpy_64.o: __memcpy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memcpy_64.o: memcpy_erms() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memcpy_64.o: memcpy_orig() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memmove_64.o: memmove() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memmove_64.o: __memmove() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memmove_64.o: return instruction outside of a function at .altinstr_replacement+0x5. Please use FUNC_ENTER. arch/x86/lib/memset_64.o: memset() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memset_64.o: __memset() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memset_64.o: memset_erms() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/memset_64.o: memset_orig() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: __put_user_1() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: __put_user_2() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: __put_user_4() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: __put_user_8() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/putuser.o: return instruction outside of a function at .text+0xc1. Please use FUNC_ENTER. arch/x86/lib/rwsem.o: call_rwsem_down_read_failed() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/rwsem.o: call_rwsem_down_write_failed() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/rwsem.o: call_rwsem_wake() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/lib/rwsem.o: call_rwsem_downgrade_wake() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/bioscall.o: intcall() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/copy.o: memcpy() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/copy.o: memset() is missing frame pointer logic. Please use FUNC_ENTER.

Quoted 8 lines

arch/x86/boot/copy.o: copy_from_fs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/copy.o: copy_to_fs() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/pmjump.o: protected_mode_jump() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/pmjump.o: in_pm32() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/compressed/head_64.o: return instruction outside of a function at .text+0x16e. Please use FUNC_ENTER. arch/x86/boot/compressed/head_64.o: return instruction outside of a function at .text+0x172. Please use FUNC_ENTER. arch/x86/boot/compressed/head_64.o: startup_32() is missing frame pointer logic. Please use FUNC_ENTER. arch/x86/boot/header.o: die() is missing frame pointer logic. Please use FUNC_ENTER.

Yeah, so many of these seem to be 'leaf only' functions: functions that don't ever call functions themselves.

So lets assume we always have CONFIG_FRAME_POINTERS=y.

Quoted 8 lines

If they don't set up a frame pointer then they in essence won't show up in the call chain - but normally they wouldn't because they call nothing.

If they trigger an exception/fault or if they get hit by an interrupt then I think we'll still correctly walk the stack - just those functions might be missing from the deterministic call chain, right? (it will still show up as a '?' entry.)

I've never quite understood what the '?' means.

Quoted 7 lines

If they crash then we'll see them because the crashing RIP will be printed.

So I'm wondering what the x86 policy here should be: to create frame pointers in them or not. Cc:-ed a few more gents for thoughts.

I think it would be nice to have full DWARF unwind support for everything at some point. Unfortunately, I don't see any easy path to getting there. It doesn't help that AFAIK no one has ever proposed a usable in-kernel DWARF unwinder.

It also doesn't help that writing correct CFI annotations in inline asm can be very complicated.

I think that ia64 manages to have complete unwind support. How did they manage it?

If we had an unwinder, it would be relatively straightforward to write something perf-based that would frequently check that we can unwind all the way out of an NMI back to userspace and warn if we couldn't.

--Andy

#346 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

Quoted 10 lines · Andy Lutomirski
Quoted 9 lines · Ingo Molnar

Yeah, so many of these seem to be 'leaf only' functions: functions that don't ever call functions themselves.

So lets assume we always have CONFIG_FRAME_POINTERS=y.

If they don't set up a frame pointer then they in essence won't show up in the call chain - but normally they wouldn't because they call nothing.

Quoted 6 lines
Quoted 4 lines

If they trigger an exception/fault or if they get hit by an interrupt then I think we'll still correctly walk the stack - just those functions might be missing from the deterministic call chain, right? (it will still show up as a '?' entry.)

I've never quite understood what the '?' means.

It basically means "here's a function address we found on the stack, which may or may not have been called." It's needed because stack walking isn't currently 100% reliable.

Quoted 15 lines
Quoted 6 lines

If they crash then we'll see them because the crashing RIP will be printed.

So I'm wondering what the x86 policy here should be: to create frame pointers in them or not. Cc:-ed a few more gents for thoughts.

I think it would be nice to have full DWARF unwind support for everything at some point. Unfortunately, I don't see any easy path to getting there. It doesn't help that AFAIK no one has ever proposed a usable in-kernel DWARF unwinder.

It also doesn't help that writing correct CFI annotations in inline asm can be very complicated.

Quoted 6 lines

I think that ia64 manages to have complete unwind support. How did they manage it?

If we had an unwinder, it would be relatively straightforward to write something perf-based that would frequently check that we can unwind all the way out of an NMI back to userspace and warn if we couldn't.

I agree that DWARF unwind support would be nice. I have some plans about how to achieve that in future patch sets. It includes several pieces:

- compile-time DWARF data validation (using some similar approaches to this patch set)

- run time DWARF data validation, including:
- a DWARF unwinder which doesn't blindly trust any of the DWARF data
- ensuring DWARF and frame pointer data are consistent with each other
- ensuring it can walk all the way to the bottom of the stack
- a DEBUG option which validates the stack periodically from an NMI and/or schedule()

Signature · 1 line
Josh
#347 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

Quoted 48 lines · Josh Poimboeuf
Quoted 10 lines · Andy Lutomirski
Quoted 9 lines · Ingo Molnar

Yeah, so many of these seem to be 'leaf only' functions: functions that don't ever call functions themselves.

So lets assume we always have CONFIG_FRAME_POINTERS=y.

If they don't set up a frame pointer then they in essence won't show up in the call chain - but normally they wouldn't because they call nothing.

Quoted 6 lines
Quoted 4 lines

If they trigger an exception/fault or if they get hit by an interrupt then I think we'll still correctly walk the stack - just those functions might be missing from the deterministic call chain, right? (it will still show up as a '?' entry.)

I've never quite understood what the '?' means.

It basically means "here's a function address we found on the stack, which may or may not have been called." It's needed because stack walking isn't currently 100% reliable.

Quoted 15 lines
Quoted 6 lines

If they crash then we'll see them because the crashing RIP will be printed.

So I'm wondering what the x86 policy here should be: to create frame pointers in them or not. Cc:-ed a few more gents for thoughts.

I think it would be nice to have full DWARF unwind support for everything at some point. Unfortunately, I don't see any easy path to getting there. It doesn't help that AFAIK no one has ever proposed a usable in-kernel DWARF unwinder.

It also doesn't help that writing correct CFI annotations in inline asm can be very complicated.

Quoted 6 lines

I think that ia64 manages to have complete unwind support. How did they manage it?

If we had an unwinder, it would be relatively straightforward to write something perf-based that would frequently check that we can unwind all the way out of an NMI back to userspace and warn if we couldn't.

I agree that DWARF unwind support would be nice. I have some plans about how to achieve that in future patch sets. It includes several pieces:

Quoted 5 lines

- compile-time DWARF data validation (using some similar approaches to this patch set)

- run time DWARF data validation, including:
- a DWARF unwinder which doesn't blindly trust any of the DWARF data

Fantastic!

Quoted 4 lines

- ensuring DWARF and frame pointer data are consistent with each other
- ensuring it can walk all the way to the bottom of the stack
- a DEBUG option which validates the stack periodically from an NMI and/or schedule()

We think alike :)

NMI will be much more interesting than schedule.

--Andy

maintainer
#348 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

In reply to Josh Poimboeuf
Quoted 5 lines · Josh Poimboeuf
Quoted 1 line

I've never quite understood what the '?' means.

It basically means "here's a function address we found on the stack, which may or may not have been called." It's needed because stack walking isn't currently 100% reliable.

Yeah, that was not that trivial to figure out at the time:

unsigned long
print_context_stack(struct thread_info *tinfo,

		...

                if (__kernel_text_address(addr)) {
                        if ((unsigned long) stack == bp + sizeof(long)) {
                                ops->address(data, addr, 1);
                                frame = frame->next_frame;
                                bp = (unsigned long) frame;
                        } else {
                                ops->address(data, addr, 0);
                        }

and that ops->address is

print_trace_address()
|-> printk_stack_address()

So if I'm understanding this correctly, if rBP+8 is equal to rSP, i.e. return address is on the stack, then this frame got called.

Otherwise -> "?".

I might be missing something though...

Signature · 5 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#349 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

Quoted 27 lines · Borislav Petkov
Quoted 5 lines · Josh Poimboeuf
Quoted 1 line

I've never quite understood what the '?' means.

It basically means "here's a function address we found on the stack, which may or may not have been called." It's needed because stack walking isn't currently 100% reliable.

Yeah, that was not that trivial to figure out at the time:

unsigned long
print_context_stack(struct thread_info *tinfo,

		...

                if (__kernel_text_address(addr)) {
                        if ((unsigned long) stack == bp + sizeof(long)) {
                                ops->address(data, addr, 1);
                                frame = frame->next_frame;
                                bp = (unsigned long) frame;
                        } else {
                                ops->address(data, addr, 0);
                        }

and that ops->address is

print_trace_address()
|-> printk_stack_address()

Quoted 6 lines

So if I'm understanding this correctly, if rBP+8 is equal to rSP, i.e. return address is on the stack, then this frame got called.

Otherwise -> "?".

I might be missing something though...

So this is how we are printing backtraces on x86:

We always scan the full kernel stack for return addresses stored on the kernel stack(s) [*], from stack top to stack bottom, and print out anything that 'looks like' a kernel text address.

If it fits into the frame pointer chain, we print it without a question mark, knowing that it's part of the real backtrace.

If the address does not fit into our expected frame pointer chain we still print it, but we print a '?'. It can mean two things:

- either the address is not part of the call chain: it's just stale values on the kernel stack, from earlier function calls. This is the common case.

- or it is part of the call chain, but the frame pointer was not set up properly within the function, so we don't recognize it. See the 200+ assembly functions that Josh's build time validation found.

This way we will always print out the real call chain (plus a few more entries), regardless of whether the frame pointer was set up correctly or not - but in most cases we'll get the call chain right as well. The entries printed are strictly in stack order, so you can deduce more information from that as well.

The most important property of this method is that we _never_ lose
information: we always strive to print _all_ addresses on the stack(s) that look like kernel text addresses, so if debug information is wrong, we still print out the real call chain as well - just with more question marks than ideal.

Thanks,

Ingo

[*] For things like IRQ stacks and ISTs we also scan those stacks, in
the right order, and try to cross from one stack into another reconstructing the call chain. This works most of the time.

maintainer
#350 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

Quoted 1 line · Ingo Molnar

So this is how we are printing backtraces on x86:

<snip useful info>

This is pretty useful info and the question about the '?' keeps popping up.

How about I moved Documentation/x86/x86_64/kernel-stacks to Documentation/x86/kernel-stacks and added that info to it?

Signature · 5 lines
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.
--
#351 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

Quoted 10 lines · Borislav Petkov
Quoted 1 line · Ingo Molnar

So this is how we are printing backtraces on x86:

<snip useful info>

This is pretty useful info and the question about the '?' keeps popping up.

How about I moved Documentation/x86/x86_64/kernel-stacks to Documentation/x86/kernel-stacks and added that info to it?

Yeah, please do!

Thanks,

Ingo

maintainer
#352 lore raw

PATCH 1/3 x86/documentation: Move kernel-stacks doc one level up

From: Borislav Petkov <[email protected]>

... to Documentation/x86/ as it is going to collect more and not only 64-bit specific info.

Cc Ingo Molnar <[email protected]>
Cc Josh Poimboeuf <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Michal Marek <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc X86 ML <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Andrew Morton <[email protected]>
---
 Documentation/x86/{x86_64 => }/kernel-stacks | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename Documentation/x86/{x86_64 => }/kernel-stacks (100%)
Documentation/x86/kernel-stacks renamed from Documentation/x86/x86_64/kernel-stacks +0 -0
similarity index 100%
rename from Documentation/x86/x86_64/kernel-stacks
rename to Documentation/x86/kernel-stacks
Signature · 1 line
2.3.5
maintainer
#353 lore raw

PATCH 2/3 x86/documentation: Remove STACKFAULT_STACK bulletpoint

From: Borislav Petkov <[email protected]>

Update the documentation after

6f442be2fb22 ("x86_64, traps: Stop using IST for #SS").

Cc Ingo Molnar <[email protected]>
Cc Josh Poimboeuf <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Michal Marek <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc X86 ML <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Andrew Morton <[email protected]>
---
 Documentation/x86/kernel-stacks | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)
Documentation/x86/kernel-stacks +3 -7
index e3c8a49d1a2f..c3c935b9d56e 100644
@@ -1,3 +1,6 @@
+Kernel stacks on x86-64 bit
+---------------------------
+
 Most of the text from Keith Owens, hacked by AK
 
 x86_64 page size (PAGE_SIZE) is 4K.
@@ -56,13 +59,6 @@ If that assumption is ever broken then the stacks will become corrupt.
 
 The currently assigned IST stacks are :-
 
-* STACKFAULT_STACK.  EXCEPTION_STKSZ (PAGE_SIZE).
-
-  Used for interrupt 12 - Stack Fault Exception (#SS).
-
-  This allows the CPU to recover from invalid stack segments. Rarely
-  happens.
-
 * DOUBLEFAULT_STACK.  EXCEPTION_STKSZ (PAGE_SIZE).
 
   Used for interrupt 8 - Double Fault Exception (#DF).
Signature · 1 line
2.3.5
maintainer
#354 lore raw

PATCH 3/3 x86/documentation: Adapt Ingo's explanation on printing backtraces

In reply to Borislav Petkov

From: Borislav Petkov <[email protected]>

Hold it down for future reference, as the question about the question mark in stack traces keeps popping up.

Cc Ingo Molnar <[email protected]>
Cc Josh Poimboeuf <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Michal Marek <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc X86 ML <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Andrew Morton <[email protected]>
---
 Documentation/x86/kernel-stacks | 44 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)
Documentation/x86/kernel-stacks +44 -0
index c3c935b9d56e..0f3a6c201943 100644
@@ -95,3 +95,47 @@ The currently assigned IST stacks are :-
   assumptions about the previous state of the kernel stack.
 
 For more details see the Intel IA32 or AMD AMD64 architecture manuals.
+
+
+Printing backtraces on x86
+--------------------------
+
+The question about the '?' preceding function names in an x86 stacktrace
+keeps popping up, here's an indepth explanation. It helps if the reader
+stares at print_context_stack() and the whole machinery in and around
+arch/x86/kernel/dumpstack.c.
+
+Adapted from Ingo's mail, Message-ID: <[email protected]>:
+
+We always scan the full kernel stack for return addresses stored on
+the kernel stack(s) [*], from stack top to stack bottom, and print out
+anything that 'looks like' a kernel text address.
+
+If it fits into the frame pointer chain, we print it without a question
+mark, knowing that it's part of the real backtrace.
+
+If the address does not fit into our expected frame pointer chain we
+still print it, but we print a '?'. It can mean two things:
+
+ - either the address is not part of the call chain: it's just stale
+   values on the kernel stack, from earlier function calls. This is
+   the common case.
+
+ - or it is part of the call chain, but the frame pointer was not set
+   up properly within the function, so we don't recognize it.
+
+This way we will always print out the real call chain (plus a few more
+entries), regardless of whether the frame pointer was set up correctly
+or not - but in most cases we'll get the call chain right as well. The
+entries printed are strictly in stack order, so you can deduce more
+information from that as well.
+
+The most important property of this method is that we _never_ lose
+information: we always strive to print _all_ addresses on the stack(s)
+that look like kernel text addresses, so if debug information is wrong,
+we still print out the real call chain as well - just with more question
+marks than ideal.
+
+[*] For things like IRQ and IST stacks, we also scan those stacks, in
+    the right order, and try to cross from one stack into another
+    reconstructing the call chain. This works most of the time.
Signature · 1 line
2.3.5
#355 lore raw

[tip:x86/debug] x86/Documentation: Adapt Ingo' s explanation on printing backtraces

In reply to Ingo Molnar
x86/Documentation: Adapt Ingo's explanation on printing backtraces
Commit-ID:  113b5e3720e79ad938374163c1b8e295521dc9cf
Gitweb:     http://git.kernel.org/tip/113b5e3720e79ad938374163c1b8e295521dc9cf
Author:     Borislav Petkov <[email protected]>
AuthorDate: Tue, 26 May 2015 10:28:20 +0200
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 27 May 2015 14:39:47 +0200

x86/Documentation: Adapt Ingo's explanation on printing backtraces

Hold it down for future reference, as the question about the question mark in stack traces keeps popping up.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Josh Poimboeuf <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 Documentation/x86/kernel-stacks | 44 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)
Documentation/x86/kernel-stacks +44 -0
index c3c935b..0f3a6c2 100644
@@ -95,3 +95,47 @@ The currently assigned IST stacks are :-
   assumptions about the previous state of the kernel stack.
 
 For more details see the Intel IA32 or AMD AMD64 architecture manuals.
+
+
+Printing backtraces on x86
+--------------------------
+
+The question about the '?' preceding function names in an x86 stacktrace
+keeps popping up, here's an indepth explanation. It helps if the reader
+stares at print_context_stack() and the whole machinery in and around
+arch/x86/kernel/dumpstack.c.
+
+Adapted from Ingo's mail, Message-ID: <[email protected]>:
+
+We always scan the full kernel stack for return addresses stored on
+the kernel stack(s) [*], from stack top to stack bottom, and print out
+anything that 'looks like' a kernel text address.
+
+If it fits into the frame pointer chain, we print it without a question
+mark, knowing that it's part of the real backtrace.
+
+If the address does not fit into our expected frame pointer chain we
+still print it, but we print a '?'. It can mean two things:
+
+ - either the address is not part of the call chain: it's just stale
+   values on the kernel stack, from earlier function calls. This is
+   the common case.
+
+ - or it is part of the call chain, but the frame pointer was not set
+   up properly within the function, so we don't recognize it.
+
+This way we will always print out the real call chain (plus a few more
+entries), regardless of whether the frame pointer was set up correctly
+or not - but in most cases we'll get the call chain right as well. The
+entries printed are strictly in stack order, so you can deduce more
+information from that as well.
+
+The most important property of this method is that we _never_ lose
+information: we always strive to print _all_ addresses on the stack(s)
+that look like kernel text addresses, so if debug information is wrong,
+we still print out the real call chain as well - just with more question
+marks than ideal.
+
+[*] For things like IRQ and IST stacks, we also scan those stacks, in
+    the right order, and try to cross from one stack into another
+    reconstructing the call chain. This works most of the time.
#356 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

In reply to Josh Poimboeuf
Quoted 7 lines · Josh Poimboeuf
Quoted 2 lines · Andy Lutomirski

I've never quite understood what the '?' means.

It basically means "here's a function address we found on the stack, which may or may not have been called." It's needed because stack walking isn't currently 100% reliable.

It is often quite interesting and helpful, because it shows stale data on the stack, giving clues about what happened just before.

Now, I'd like gcc to generally be better about not wasting so much stack frame, so in that sense I'd like to see fewer '?" entries just from a code quality standpoint, but when debugging those things, the downside of "noise" is often cancelled by the upside of "ahh, it happens after calling X".

So the "perfect stack frames" is actually not as great a thing as some people want to make it seem.

Linus

#357 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

Quoted 12 lines · Linus Torvalds
Quoted 7 lines · Josh Poimboeuf
Quoted 2 lines · Andy Lutomirski

I've never quite understood what the '?' means.

It basically means "here's a function address we found on the stack, which may or may not have been called." It's needed because stack walking isn't currently 100% reliable.

It is often quite interesting and helpful, because it shows stale data on the stack, giving clues about what happened just before.

Quoted 8 lines

Now, I'd like gcc to generally be better about not wasting so much stack frame, so in that sense I'd like to see fewer '?" entries just from a code quality standpoint, but when debugging those things, the downside of "noise" is often cancelled by the upside of "ahh, it happens after calling X".

So the "perfect stack frames" is actually not as great a thing as some people want to make it seem.

Ok, I can see how looking at stale stack data could be useful for some of the really tough problems.

But right now, the meaning of '?' is ambiguous. It could be stale data, or it could be part of a frame for the current stack which was skipped due to missing frame pointers or an exception.

If we can somehow make the stack unwinder reliable, then it would at least allow us to remove the ambiguity of the '?' entries. And it would reduce the "noise" for the majority of issues where we don't care about stale stack data, and can simply ignore it.

Signature · 1 line
Josh
#358 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

Quoted 19 lines · Josh Poimboeuf
Quoted 18 lines · Linus Torvalds
Quoted 7 lines · Josh Poimboeuf
Quoted 2 lines · Andy Lutomirski

I've never quite understood what the '?' means.

It basically means "here's a function address we found on the stack, which may or may not have been called." It's needed because stack walking isn't currently 100% reliable.

It is often quite interesting and helpful, because it shows stale data on the stack, giving clues about what happened just before.

Now, I'd like gcc to generally be better about not wasting so much stack frame, so in that sense I'd like to see fewer '?" entries just from a code quality standpoint, but when debugging those things, the downside of "noise" is often cancelled by the upside of "ahh, it happens after calling X".

Quoted 5 lines
Quoted 2 lines

So the "perfect stack frames" is actually not as great a thing as some people want to make it seem.

Ok, I can see how looking at stale stack data could be useful for some of the really tough problems.

And note that the tough problems are actually the ones where we need that information the most. So any stack backtrace printing method must be biased towards helping the difficult scenarios - not the trivial crashes. That is one of the reasons why we are always printing the question marks.

Quoted 3 lines

But right now, the meaning of '?' is ambiguous. It could be stale data, or it could be part of a frame for the current stack which was skipped due to missing frame pointers or an exception.

Yes, of course. That's not a big problem as the actual symbolic information will tell us a lot, which allows us to reconstruct the real call chain, plus allows us to see any 'recent execution activity' that might be on the stack as stale entries.

Quoted 4 lines

If we can somehow make the stack unwinder reliable, then it would at least allow us to remove the ambiguity of the '?' entries. And it would reduce the "noise" for the majority of issues where we don't care about stale stack data, and can simply ignore it.

Yes, but note the above consideration - the probability distribution of kernel bugs tends to have a _very_ long tail, with bugs that sometimes take years to trigger and fix. Kernel developers upstream and at distros tend to spend a disproportionately large amount of time staring at difficult to decode bugs.

For that reason it is far more important to still stay maintainable with those kinds of difficult bugs, than to make the resolution of trivial, unambiguous crashes a tiny bit easier by printing fewer 'distractions'...

Also, note that the '?' entries have another role: they cross-check the unwinder.

If you think we'll be able to do a perfect unwinder then think again:
debug info _will_ be messed up periodically, either by us or by tooling, because right now no kernel code or other functionality relies on perfect unwinding.

So this is not like C++ exception handling where broken unwinding will break the code. This is something that is literally only visible in kernel logs currently, as a slight anomaly.

So any x86 stack unwinder code must be fundamentally based on the idea and expectation that stack unwinding is always going to be somewhat imperfect and somewhat statistical.

Thanks,

Ingo

#359 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

In reply to Linus Torvalds
Quoted 11 lines · Linus Torvalds
Quoted 7 lines · Josh Poimboeuf
Quoted 2 lines · Andy Lutomirski

I've never quite understood what the '?' means.

It basically means "here's a function address we found on the stack, which may or may not have been called." It's needed because stack walking isn't currently 100% reliable.

It is often quite interesting and helpful, because it shows stale data on the stack, giving clues about what happened just before.

Yes, it's basically a zero-cost tracer: often showing a partial trace of events that happened before.

Quoted 8 lines

Now, I'd like gcc to generally be better about not wasting so much stack frame, so in that sense I'd like to see fewer '?" entries just from a code quality standpoint, but when debugging those things, the downside of "noise" is often cancelled by the upside of "ahh, it happens after calling X".

So the "perfect stack frames" is actually not as great a thing as some people want to make it seem.

We should definitely also print out the '?' entries, they are very useful especially when analyzing rare, difficult to reproduce, sporadic bugs - which are usually the hardest to fix bugs.

The biggest long term plus of 'perfect stack frames' would not be to skip the '?' entries (we don't want to skip them!), but to be able to eventually build the kernel without frame pointers.

Especially on modern x86 CPUs with stack engines (latest Intel and AMD CPUs) that keeps ESP updates out of the later stages of execution pipelines, going from RBP framepointers to direct ESP use is beneficial to performance and compresses I$ footprint as well:

text data bss dec hex filename
12150606 2565544 1634304 16350454 f97cf6 linux-CONFIG_FRAME_POINTERS=n/vmlinux
13282884 2571744 1617920 17472548 10a9c24 linux-CONFIG_FRAME_POINTERS=y/vmlinux

Here's the I$ cachemiss rate with the 'vfs-mix' workload that I used in the -falign-functions measuremenst gives this for CONFIG_FRAMEPOINTERS=y, on Intel Sandy Bridge (best of 9x10 runs):

#
# CONFIG_FRAMEPOINTERS=y
#
Performance counter stats for 'system wide' (10 runs):

       728,328,347      L1-icache-load-misses                                         ( +-  0.08% )  (100.00%)
    11,891,931,664      instructions                                                  ( +-  0.00% )
           300,023      context-switches                                              ( +-  0.00% )

7.324048170 seconds time elapsed ( +- 0.09% )

... and these are the I$ miss perf stats from running the same workload on a CONFIG_FRAMEPOINTERS=n kernel:

#
# CONFIG_FRAMEPOINTERS are not set
#
Performance counter stats for 'system wide' (10 runs):

       687,758,078      L1-icache-load-misses                                         ( +-  0.10% )  (100.00%)
    10,984,908,013      instructions                                                  ( +-  0.01% )
           300,021      context-switches                                              ( +-  0.00% )

7.120867260 seconds time elapsed ( +- 0.29% )

So if we disable frame pointers, then on this workload:

- the kernel text size is 9.3% smaller
- the number of instructions executed went down by about 8.2%
- the cachemiss rate went down by about 5.9%
- performance went up by about 2.8%.

The speedup is actually even better than 2.8%, if you look at average execution time:

linux-CONFIG_FRAME_POINTERS=y/res.txt:       7.324048170 seconds time elapsed                                          ( +-  0.09% )
linux-CONFIG_FRAME_POINTERS=y/res.txt:       7.470166715 seconds time elapsed                                          ( +-  1.01% )
linux-CONFIG_FRAME_POINTERS=y/res.txt:       7.365047474 seconds time elapsed                                          ( +-  0.25% )
linux-CONFIG_FRAME_POINTERS=y/res.txt:       7.828223324 seconds time elapsed                                          ( +-  2.04% )
linux-CONFIG_FRAME_POINTERS=y/res.txt:       7.427164489 seconds time elapsed                                          ( +-  0.70% )
linux-CONFIG_FRAME_POINTERS=y/res.txt:       7.385565350 seconds time elapsed                                          ( +-  0.35% )
linux-CONFIG_FRAME_POINTERS=y/res.txt:       7.560782318 seconds time elapsed                                          ( +-  1.68% )
linux-CONFIG_FRAME_POINTERS=y/res.txt:       7.399741309 seconds time elapsed                                          ( +-  0.74% )
linux-CONFIG_FRAME_POINTERS=y/res.txt:       7.303746766 seconds time elapsed                                          ( +-  0.04% )

avg = 7.451609

linux-CONFIG_FRAME_POINTERS=n/res.txt:       7.201498813 seconds time elapsed                                          ( +-  0.86% )
linux-CONFIG_FRAME_POINTERS=n/res.txt:       7.120867260 seconds time elapsed                                          ( +-  0.29% )
linux-CONFIG_FRAME_POINTERS=n/res.txt:       7.141642635 seconds time elapsed                                          ( +-  0.15% )
linux-CONFIG_FRAME_POINTERS=n/res.txt:       7.217213506 seconds time elapsed                                          ( +-  0.85% )
linux-CONFIG_FRAME_POINTERS=n/res.txt:       7.163046581 seconds time elapsed                                          ( +-  0.56% )
linux-CONFIG_FRAME_POINTERS=n/res.txt:       7.128939439 seconds time elapsed                                          ( +-  0.23% )
linux-CONFIG_FRAME_POINTERS=n/res.txt:       7.256172853 seconds time elapsed                                          ( +-  0.82% )
linux-CONFIG_FRAME_POINTERS=n/res.txt:       7.122946768 seconds time elapsed                                          ( +-  0.23% )
linux-CONFIG_FRAME_POINTERS=n/res.txt:       7.126018578 seconds time elapsed                                          ( +-  0.18% )

avg = 7.164260

Then with framepointers disabled this workload gets faster by 4.0% on average.

The average result is also pretty stable in the no-framepointers case, while it fluctuates more in the framepointers case. (and this is why the 'best runtime' favors the framepointers case - the average is closer to reality.)

So the performance advantages of not doing framepointers is not something we can ignore IMHO: but obviously performance isn't everything - so if stack unwinding is unrobust, then we need and want frame pointers.

Thanks,

Ingo

#360 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

Quoted 8 lines · Ingo Molnar

Especially on modern x86 CPUs with stack engines (latest Intel and AMD CPUs) that keeps ESP updates out of the later stages of execution pipelines, going from RBP framepointers to direct ESP use is beneficial to performance and compresses I$ footprint as well:

text data bss dec hex filename
12150606 2565544 1634304 16350454 f97cf6 linux-CONFIG_FRAME_POINTERS=n/vmlinux
13282884 2571744 1617920 17472548 10a9c24 linux-CONFIG_FRAME_POINTERS=y/vmlinux

Correction: I ran that with a 1-byte alignment patch still applied.

I reran all the numbers with the default 16-bytes alignment as well, and the gap between framepointers and no-framepointers become smaller, but the various trends and conclusions still hold.

Here are the updated numbers:

text data bss dec hex filename

 13548564        2571744 1617920 17738228        10ea9f4 linux-CONFIG_FRAME_POINTERS=n/vmlinux
 13797773        2571744 1617920 17987437        112776d linux-CONFIG_FRAME_POINTERS=y/vmlinux
Quoted 9 lines

Here's the I$ cachemiss rate with the 'vfs-mix' workload that I used in the -falign-functions measuremenst gives this for CONFIG_FRAMEPOINTERS=y, on Intel Sandy Bridge (best of 9x10 runs):

#
# CONFIG_FRAMEPOINTERS=y
#
Performance counter stats for 'system wide' (10 runs):

Quoted 5 lines
       728,328,347      L1-icache-load-misses                                         ( +-  0.08% )  (100.00%)
    11,891,931,664      instructions                                                  ( +-  0.00% )
           300,023      context-switches                                              ( +-  0.00% )

7.324048170 seconds time elapsed ( +- 0.09% )

Performance counter stats for 'system wide' (10 runs):

       701,525,006      L1-icache-load-misses                                         ( +-  0.06% )  (100.00%)
    11,891,793,196      instructions                                                  ( +-  0.01% )
           300,036      context-switches                                              ( +-  0.00% )

7.354372294 seconds time elapsed ( +- 0.82% )

Quoted 9 lines

... and these are the I$ miss perf stats from running the same workload on a CONFIG_FRAMEPOINTERS=n kernel:

#
# CONFIG_FRAMEPOINTERS are not set
#
Performance counter stats for 'system wide' (10 runs):

Quoted 5 lines
       687,758,078      L1-icache-load-misses                                         ( +-  0.10% )  (100.00%)
    10,984,908,013      instructions                                                  ( +-  0.01% )
           300,021      context-switches                                              ( +-  0.00% )

7.120867260 seconds time elapsed ( +- 0.29% )

Performance counter stats for 'system wide' (10 runs):

       685,107,089      L1-icache-load-misses                                         ( +-  0.08% )  (100.00%)
    10,983,861,590      instructions                                                  ( +-  0.01% )
           300,031      context-switches                                              ( +-  0.00% )

7.120738452 seconds time elapsed ( +- 0.35% )

Quoted 6 lines

So if we disable frame pointers, then on this workload:

- the kernel text size is 9.3% smaller
- the number of instructions executed went down by about 8.2%
- the cachemiss rate went down by about 5.9%
- performance went up by about 2.8%.

- the kernel text size is 1.8% smaller: with 16 bytes alignment there's quite some extra free space the frame pointer code can grow into, which reduces the size win.

- the number of instructions executed went down by about 8.2% (as expected this is invariant of alignment.)

- the cachemiss rate went down by about 2.7%: this is a smaller win again, partly because of the 'free space' 16-byte alignment gives us.

- the best 'time elapsed' numbers out of 10 runs show a speedup of 2.0% - close to the 2.8% with 1-byte alignment.

Quoted 13 lines

The speedup is actually even better than 2.8%, if you look at average execution time:

linux-CONFIG_FRAME_POINTERS=y/res.txt:       7.324048170 seconds time elapsed                                          ( +-  0.09% )
linux-CONFIG_FRAME_POINTERS=y/res.txt:       7.470166715 seconds time elapsed                                          ( +-  1.01% )
linux-CONFIG_FRAME_POINTERS=y/res.txt:       7.365047474 seconds time elapsed                                          ( +-  0.25% )
linux-CONFIG_FRAME_POINTERS=y/res.txt:       7.828223324 seconds time elapsed                                          ( +-  2.04% )
linux-CONFIG_FRAME_POINTERS=y/res.txt:       7.427164489 seconds time elapsed                                          ( +-  0.70% )
linux-CONFIG_FRAME_POINTERS=y/res.txt:       7.385565350 seconds time elapsed                                          ( +-  0.35% )
linux-CONFIG_FRAME_POINTERS=y/res.txt:       7.560782318 seconds time elapsed                                          ( +-  1.68% )
linux-CONFIG_FRAME_POINTERS=y/res.txt:       7.399741309 seconds time elapsed                                          ( +-  0.74% )
linux-CONFIG_FRAME_POINTERS=y/res.txt:       7.303746766 seconds time elapsed                                          ( +-  0.04% )
Quoted 1 line

avg = 7.451609

linux-CONFIG_FRAME_POINTERS=y/res2.txt:       7.300875812 seconds time elapsed                                          ( +-  0.17% )
linux-CONFIG_FRAME_POINTERS=y/res2.txt:       7.491652338 seconds time elapsed                                          ( +-  1.33% )
linux-CONFIG_FRAME_POINTERS=y/res2.txt:       7.307877300 seconds time elapsed                                          ( +-  0.20% )
linux-CONFIG_FRAME_POINTERS=y/res2.txt:       7.258946461 seconds time elapsed                                          ( +-  0.23% )
linux-CONFIG_FRAME_POINTERS=y/res2.txt:       7.295113779 seconds time elapsed                                          ( +-  0.30% )
linux-CONFIG_FRAME_POINTERS=y/res2.txt:       7.283375859 seconds time elapsed                                          ( +-  0.21% )
linux-CONFIG_FRAME_POINTERS=y/res2.txt:       7.319320205 seconds time elapsed                                          ( +-  0.38% )
linux-CONFIG_FRAME_POINTERS=y/res2.txt:       7.354372294 seconds time elapsed                                          ( +-  0.82% )
linux-CONFIG_FRAME_POINTERS=y/res2.txt:       7.308955558 seconds time elapsed                                          ( +-  0.26% )
linux-CONFIG_FRAME_POINTERS=y/res2.txt:       7.295267101 seconds time elapsed                                          ( +-  0.26% )

avg=7.32

Quoted 11 lines
linux-CONFIG_FRAME_POINTERS=n/res.txt:       7.201498813 seconds time elapsed                                          ( +-  0.86% )
linux-CONFIG_FRAME_POINTERS=n/res.txt:       7.120867260 seconds time elapsed                                          ( +-  0.29% )
linux-CONFIG_FRAME_POINTERS=n/res.txt:       7.141642635 seconds time elapsed                                          ( +-  0.15% )
linux-CONFIG_FRAME_POINTERS=n/res.txt:       7.217213506 seconds time elapsed                                          ( +-  0.85% )
linux-CONFIG_FRAME_POINTERS=n/res.txt:       7.163046581 seconds time elapsed                                          ( +-  0.56% )
linux-CONFIG_FRAME_POINTERS=n/res.txt:       7.128939439 seconds time elapsed                                          ( +-  0.23% )
linux-CONFIG_FRAME_POINTERS=n/res.txt:       7.256172853 seconds time elapsed                                          ( +-  0.82% )
linux-CONFIG_FRAME_POINTERS=n/res.txt:       7.122946768 seconds time elapsed                                          ( +-  0.23% )
linux-CONFIG_FRAME_POINTERS=n/res.txt:       7.126018578 seconds time elapsed                                          ( +-  0.18% )

avg = 7.164260

linux-CONFIG_FRAME_POINTERS=n/res2.txt:       7.135061084 seconds time elapsed                                          ( +-  0.39% )
linux-CONFIG_FRAME_POINTERS=n/res2.txt:       7.132738388 seconds time elapsed                                          ( +-  0.34% )
linux-CONFIG_FRAME_POINTERS=n/res2.txt:       7.174334895 seconds time elapsed                                          ( +-  0.32% )
linux-CONFIG_FRAME_POINTERS=n/res2.txt:       7.215143851 seconds time elapsed                                          ( +-  0.71% )
linux-CONFIG_FRAME_POINTERS=n/res2.txt:       7.131166029 seconds time elapsed                                          ( +-  0.19% )
linux-CONFIG_FRAME_POINTERS=n/res2.txt:       7.270427197 seconds time elapsed                                          ( +-  1.22% )
linux-CONFIG_FRAME_POINTERS=n/res2.txt:       7.120738452 seconds time elapsed                                          ( +-  0.35% )
linux-CONFIG_FRAME_POINTERS=n/res2.txt:       7.168856127 seconds time elapsed                                          ( +-  0.27% )
linux-CONFIG_FRAME_POINTERS=n/res2.txt:       7.268637173 seconds time elapsed                                          ( +-  1.28% )
linux-CONFIG_FRAME_POINTERS=n/res2.txt:       7.178431781 seconds time elapsed                                          ( +-  0.32% )

avg=7.18

Quoted 2 lines

Then with framepointers disabled this workload gets faster by 4.0% on average.

With 16-byte alignment the average gets faster by 2.8%.

The conclusions are unchanged:

Quoted 9 lines

The average result is also pretty stable in the no-framepointers case, while it fluctuates more in the framepointers case. (and this is why the 'best runtime' favors the framepointers case - the average is closer to reality.)

So the performance advantages of not doing framepointers is not something we can ignore IMHO: but obviously performance isn't everything - so if stack unwinding is unrobust, then we need and want frame pointers.

Thanks,

Ingo

#361 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

In reply to Ingo Molnar
Quoted 5 lines · Ingo Molnar

Especially on modern x86 CPUs with stack engines (latest Intel and AMD CPUs) that keeps ESP updates out of the later stages of execution pipelines, going from RBP framepointers to direct ESP use is beneficial to performance and compresses I$ footprint as well:

Note that Atom doesn't have this stack engine, so you'll likely see even more difference there.

Quoted 2 lines

So the performance advantages of not doing framepointers is not something we can ignore IMHO:

Agreed.

Quoted 3 lines

but obviously performance isn't
everything - so if stack unwinding is unrobust, then we need and want frame pointers.

It wasn't that bad in the old days with the approx stack traces. In fact I bet it would be possible to write an automated tool that weeds out many (most?) false positives automatically with a static compile-time callgraph.

It would be good to at least make it easier building without them again. Currently it's very difficult because a lot of subsystems force select frame pointers.

-Andi

Signature · 1 line
[email protected] -- Speaking for myself only
maintainer
#362 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

In reply to Andy Lutomirski
Quoted 4 lines · Andy Lutomirski

I think it would be nice to have full DWARF unwind support for everything at some point. Unfortunately, I don't see any easy path to getting there. It doesn't help that AFAIK no one has ever proposed a usable in-kernel DWARF unwinder.

There's a bit of history here; SuSE (iirc) actually has one, however:

https://lkml.org/lkml/2012/2/10/356

#363 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

Quoted 8 lines · Peter Zijlstra
Quoted 4 lines

I think it would be nice to have full DWARF unwind support for everything at some point. Unfortunately, I don't see any easy path to getting there. It doesn't help that AFAIK no one has ever proposed a usable in-kernel DWARF unwinder.

There's a bit of history here; SuSE (iirc) actually has one, however:

https://lkml.org/lkml/2012/2/10/356

Oh absolutely, there are stories behind this :)

Just for the sake of completness -- the current implementation can be found in our public GIT repository, for not-really-complete picture see
[1] [2] [3] [4].

It turned out to be rather useful on many ocasions when debugging customer reports, but I of course also understand what Linus is saying above. The bugs in unwinder can be *really* painful. Our experience so far has been that it did pay off at the end of the day (and of course analyzing stacktraces is our daily bread).

[1] http://kernel.suse.com/cgit/kernel-source/tree/patches.suse/stack-unwind?h=SLE12
[2] http://kernel.suse.com/cgit/kernel-source/tree/patches.suse/no-frame-pointer-select?h=SLE12
[3] http://kernel.suse.com/cgit/kernel-source/tree/patches.arch/stack-unwind-cfi_ignore-takes-more-arguments?h=SLE12
[4] http://kernel.suse.com/cgit/kernel-source/tree/patches.arch/x86_64-unwind-annotations?h=SLE12

Signature · 2 lines
Jiri Kosina
SUSE Labs
#364 lore raw

Re: [PATCH v4 0/3] Compile-time stack frame pointer validation

In reply to Ingo Molnar
Quoted 14 lines · Ingo Molnar

Yeah, so many of these seem to be 'leaf only' functions: functions that don't ever call functions themselves.

So lets assume we always have CONFIG_FRAME_POINTERS=y.

If they don't set up a frame pointer then they in essence won't show up in the call chain - but normally they wouldn't because they call nothing.

If they trigger an exception/fault or if they get hit by an interrupt then I think we'll still correctly walk the stack - just those functions might be missing from the deterministic call chain, right? (it will still show up as a '?' entry.)

Quoted 5 lines

If they crash then we'll see them because the crashing RIP will be printed.

So I'm wondering what the x86 policy here should be: to create frame pointers in them or not. Cc:-ed a few more gents for thoughts.

After removing the frame pointer checks for leaf functions, and adding a check for all functions which jump outside of their scope, the number of defconfig warnings dropped from 89 -> 47. The Fedora config warning count dropped from 207 -> 83.

Here are the remaining 47 warnings for defconfig:

stackvalidate: arch/x86/ia32/ia32entry.o: ia32_sysenter_target() is missing frame pointer logic
stackvalidate: arch/x86/ia32/ia32entry.o: return instruction outside of a function at .entry.text+0x52e
stackvalidate: arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x359
stackvalidate: arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x19be
stackvalidate: arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x19e5
stackvalidate: arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x1c21
stackvalidate: arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x1ceb
stackvalidate: arch/x86/kernel/acpi/wakeup_64.o: unsupported jump to outside of the function at wakeup_long64+0x15
stackvalidate: arch/x86/kernel/acpi/wakeup_64.o: do_suspend_lowlevel() is missing frame pointer logic
stackvalidate: arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x6b
stackvalidate: arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0xc7
stackvalidate: arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x110
stackvalidate: arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x145
stackvalidate: arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x1c4
stackvalidate: arch/x86/kernel/head_64.o: return instruction outside of a function at .head.text+0x1a2
stackvalidate: arch/x86/kernel/head_64.o: early_idt_handler() is missing frame pointer logic
stackvalidate: arch/x86/platform/efi/efi_stub_64.o: efi_call() is missing frame pointer logic
stackvalidate: arch/x86/realmode/rm/trampoline_64.o: return instruction outside of a function at .text+0x170
stackvalidate: arch/x86/realmode/rm/trampoline_64.o: return instruction outside of a function at .text+0x176
stackvalidate: arch/x86/realmode/rm/reboot.o: return instruction outside of a function at .text+0x2a
stackvalidate: arch/x86/realmode/rm/copy.o: copy_from_fs() is missing frame pointer logic
stackvalidate: arch/x86/realmode/rm/copy.o: copy_to_fs() is missing frame pointer logic
stackvalidate: arch/x86/power/hibernate_asm_64.o: return instruction outside of a function at .text+0x69
stackvalidate: arch/x86/power/hibernate_asm_64.o: return instruction outside of a function at .text+0x16d
stackvalidate: arch/x86/lib/copy_user_64.o: unsupported jump to outside of the function at _copy_to_user+0x25
stackvalidate: arch/x86/lib/copy_user_64.o: unsupported jump to outside of the function at _copy_from_user+0x25
stackvalidate: arch/x86/lib/getuser.o: unsupported jump to outside of the function at __get_user_1+0x14
stackvalidate: arch/x86/lib/getuser.o: unsupported jump to outside of the function at __get_user_2+0x4
stackvalidate: arch/x86/lib/getuser.o: unsupported jump to outside of the function at __get_user_4+0x4
stackvalidate: arch/x86/lib/getuser.o: unsupported jump to outside of the function at __get_user_8+0x4
stackvalidate: arch/x86/lib/getuser.o: return instruction outside of a function at .text+0xc5
stackvalidate: arch/x86/lib/memmove_64.o: return instruction outside of a function at .altinstr_replacement+0x5
stackvalidate: arch/x86/lib/putuser.o: unsupported jump to outside of the function at __put_user_1+0x14
stackvalidate: arch/x86/lib/putuser.o: unsupported jump to outside of the function at __put_user_2+0x1b
stackvalidate: arch/x86/lib/putuser.o: unsupported jump to outside of the function at __put_user_4+0x1b
stackvalidate: arch/x86/lib/putuser.o: unsupported jump to outside of the function at __put_user_8+0x1b
stackvalidate: arch/x86/lib/putuser.o: return instruction outside of a function at .text+0xc1
stackvalidate: arch/x86/lib/rwsem.o: call_rwsem_down_read_failed() is missing frame pointer logic
stackvalidate: arch/x86/lib/rwsem.o: call_rwsem_down_write_failed() is missing frame pointer logic
stackvalidate: arch/x86/lib/rwsem.o: call_rwsem_wake() is missing frame pointer logic
stackvalidate: arch/x86/lib/rwsem.o: call_rwsem_downgrade_wake() is missing frame pointer logic
stackvalidate: arch/x86/boot/copy.o: copy_from_fs() is missing frame pointer logic
stackvalidate: arch/x86/boot/copy.o: copy_to_fs() is missing frame pointer logic
stackvalidate: arch/x86/boot/compressed/head_64.o: return instruction outside of a function at .text+0x16e
stackvalidate: arch/x86/boot/compressed/head_64.o: return instruction outside of a function at .text+0x172
stackvalidate: arch/x86/boot/compressed/head_64.o: startup_32() is missing frame pointer logic
stackvalidate: arch/x86/boot/pmjump.o: unsupported jump to outside of the function at in_pm32+0x1c

Note that only 13 of the 47 warnings are actually due to missing frame pointer logic. The rest are ambiguous conditions which prevent stackvalidate from being able to make sense of things: returning from outside of a proper ELF function, or jumping from inside of a function to outside of its scope.

Similarly, in the Fedora config case, only 27 of the 83 warnings are for missing frame pointer logic.

If there are no objections, I'll go with this approach in the next version of the patch set.

Thanks!

Signature · 1 line
Josh