mtrr/x86/drivers: bury MTRR
Subsystems (34)
Borislav Petkov
maintainerRe: [PATCH v4 7/7] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping
In reply to Toshi KaniQuoted 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()andpmd_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.Signed-off-by Toshi Kani <[email protected]>--- 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
-0if (!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@@ -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@@ -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>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
-0if (!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>
Borislav Petkov
maintainerRe: [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 causeioremap()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>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 causeioremap()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>
Borislav Petkov
maintainerRe: [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>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 themtrr_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>
Borislav Petkov
maintainerRe: [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>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>
Borislav Petkov
maintainerRe: [PATCH v4 7/7] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping
Quoted 2 lines · Toshi Kani
MTRR_TYPE_INVALIDmeans MTRRs disabled. So, the caller checking with this value is the same as checking withmtrr_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>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_INVALIDmeans MTRRs disabled. So, the caller checking with this value is the same as checking withmtrr_enabled()you suggested.So then you don't have to set *uniform = 1 on entry to
mtrr_type_lookup(). And change the retval testif ((!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_INVALIDfirst 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>
Andrew Morton
maintainerRe: [PATCH v4 0/7] mtrr, mm, x86: Enhance MTRR checks for huge I/O mapping
In reply to Toshi KaniQuoted 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.
- Allowpud_set_huge()andpmd_set_huge()to create a huge page mapping to a range covered by a single MTRR entry of any memory type.
- Log apr_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>
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/589Quoted 8 lines
The following functional changes are made in patch 7/7.
- Allowpud_set_huge()andpmd_set_huge()to create a huge page mapping to a range covered by a single MTRR entry of any memory type.
- Log apr_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>
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/589Quoted 8 lines
The following functional changes are made in patch 7/7.
- Allowpud_set_huge()andpmd_set_huge()to create a huge page mapping to a range covered by a single MTRR entry of any memory type.
- Log apr_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>
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/589Quoted 8 lines
The following functional changes are made in patch 7/7.
- Allowpud_set_huge()andpmd_set_huge()to create a huge page mapping to a range covered by a single MTRR entry of any memory type.
- Log apr_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.patch1. 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>
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
@@ -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
Borislav Petkov
AppliedRe: [PATCH] x86/kaslr: Fix typo in documentation
Quoted 13 lines · Miroslav Benes
Documentation/x86/boot.txtlabels the bit in boot_params.hdr.loadflags asALSR_FLAGwhile it should beKASLR_FLAG.Signed-off-by Miroslav Benes <[email protected]>--- Documentation/x86/boot.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)Documentation/x86/boot.txt +0
-0
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.
--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.
---
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
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.
--- arch/x86/mm/pageattr.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
arch/x86/mm/pageattr.c +6 -7
@@ -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
Borislav Petkov
AppliedRe: [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.Signed-off-by Ross Zwisler <[email protected]>Reported-by H. Peter Anvin <[email protected]>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.
--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.
--- arch/x86/include/asm/special_insns.h | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)
arch/x86/include/asm/special_insns.h +37 -0
@@ -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
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.Signed-off-by Ross Zwisler <[email protected]>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
@@ -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.
--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
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----------------------------------------------------------------------
--- 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
@@ -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
@@ -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
@@ -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
@@ -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_wcstatic inline void __iomem *ioremap_wc (phys_addr_t offset,size_t size)
Signature · 1 line
2.3.2.209.gd67f9d5.dirty
Borislav Petkov
maintainerRe: [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 onlyarch_phys_wc_add()use will remain, even if this happensarch_phys_wc_add()will have an effect on non-PAT systems and changes to defaultioremap_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 ofioremap_uc()helps phase out MTRR use by avoiding regressions with an eventual flip of default behaviour orioremap_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 leaveset_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 thatset_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]>Signed-off-by Luis R. Rodriguez <[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.
--PATCH v4 2/6 x86: document WC MTRR effects on PAT / non-PAT pages
In reply to Luis R. RodriguezFrom: "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.
--- 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
@@ -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
@@ -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
@@ -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
Randy Dunlap
reviewerRe: [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@@ -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
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
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@@ -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 withI 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 regionssize-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@@ -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
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.
--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
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.
--Re: [PATCH v4 2/6] x86: document WC MTRR effects on PAT / non-PAT pages
In reply to Randy DunlapQuoted 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@@ -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 withI 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 regionssize-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@@ -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
Borislav Petkov
maintainerRe: [PATCH v4 2/6] x86: document WC MTRR effects on PAT / non-PAT pages
In reply to Luis R. RodriguezQuoted 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 outmtrr_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]>Signed-off-by 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/mtrr.txt +0
-0
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 controlDocumentation/x86/pat.txt +2
-0@@ -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@@ -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.
--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 outmtrr_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]>Signed-off-by 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(-)
Quoted 16 lines
Quoted 5 lines
Documentation/x86/mtrr.txt +0
-0Documentation/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
PATCH v4 3/6 video: fbdev: atyfb: move framebuffer length fudging to helper
In reply to Luis R. RodriguezFrom: "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.
--- drivers/video/fbdev/aty/atyfb_base.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-)
drivers/video/fbdev/aty/atyfb_base.c +15 -8
@@ -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
PATCH v4 4/6 video: fbdev: atyfb: clarify ioremap() base and length used
In reply to Luis R. RodriguezFrom: "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.
--- drivers/video/fbdev/aty/atyfb_base.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/video/fbdev/aty/atyfb_base.c +3 -1
@@ -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
PATCH v4 5/6 video: fbdev: atyfb: replace MTRR UC hole with strong UC
In reply to Luis R. RodriguezFrom: "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.
--- 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
@@ -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
@@ -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
PATCH v4 6/6 video: fbdev: atyfb: use arch_phys_wc_add() and ioremap_wc()
In reply to Luis R. RodriguezFrom: "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);
--- 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
@@ -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
@@ -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
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
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
Re: [PATCH v4 0/6] x86: document and address MTRR corner cases
In reply to Luis R. RodriguezQuoted 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: addioremap_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: clarifyioremap()base and length used
video: fbdev: atyfb: replace MTRR UC hole with strong UC
video: fbdev: atyfb: usearch_phys_wc_add()andioremap_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
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
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
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/
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.
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
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
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
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
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
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
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.
--- 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
@@ -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
@@ -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
@@ -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
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. Sincepr_fmtis 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]>Signed-off-by Luis R. Rodriguez <[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
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.
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
@@ -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
@@ -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
@@ -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.
--RE: [PATCH v5 1/6] x86/mm/pat: use pr_info() and friends
In reply to Luis R. RodriguezQuoted 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: usepr_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 mappingtype %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.
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: usepr_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 mappingtype %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
PATCH v5 2/6 x86/mm/pat: redefine pat_enabled
In reply to Luis R. RodriguezFrom: "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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
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@@ -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.
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
--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@@ -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_enabledwhich 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
PATCH v5 3/6 arch/x86/mm/pat: export pat_enabled()
In reply to Luis R. RodriguezFrom: "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.
--- arch/x86/mm/pat.c | 1 + 1 file changed, 1 insertion(+)
arch/x86/mm/pat.c +1 -0
@@ -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
Borislav Petkov
AppliedRe: [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]>Signed-off-by Luis R. Rodriguez <[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.
--PATCH v5 4/6 ivtv: use arch_phys_wc_add() and require PAT disabled
In reply to Luis R. RodriguezFrom: "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.
--- 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
@@ -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
PATCH v5 5/6 IB/ipath: add counting for MTRR
In reply to Luis R. RodriguezFrom: "Luis R. Rodriguez" <[email protected]>
There is no good reason not to, we eventually delete it as well.
--- 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
@@ -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
PATCH v5 6/6 IB/ipath: use arch_phys_wc_add() and require PAT disabled
In reply to Luis R. RodriguezFrom: "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.
--- 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
@@ -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
@@ -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
@@ -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
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
@@ -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 $@
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 directoryI am not 100% sure but it seems that this was broken by
d944c4eebcf4c0d5e5d9728fec110cbf0047ad7f"tools: Consolidatetypes.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
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.
--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 directoryI am not 100% sure but it seems that this was broken by
d944c4eebcf4c0d5e5d9728fec110cbf0047ad7f"tools: Consolidatetypes.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@@ -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/uapiDo 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 "makeheaders_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.
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@@ -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/uapiDo 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 "makeheaders_install" which should probably do that (haven't tried it though).Perhaps. but still, if
HOST_EXTRACFLAGShas -I$(srctree)/include/uapi, why it doesn't addarch/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.
--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/vdso2cWow, 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@@ -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/uapiDo 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 "makeheaders_install" which should probably do that (haven't tried it though).
Quoted 5 lines
Quoted 3 lines
Perhaps. but still, if
HOST_EXTRACFLAGShas -I$(srctree)/include/uapi, why it doesn't addarch/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
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.
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
@@ -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
Re: [PATCH 1/1] x86/vdso: add -Iarch/x86/include/uapi into HOST_EXTRACFLAGS
Quoted 7 lines · Oleg Nesterov
Change
HOST_EXTRACFLAGSto includearch/x86/include/uapialong withinclude/uapi.This looks more consistent, and this fixes "make bzImage" on my old distro which doesn't have
asm/bitsperlong.hin/usr/include/.Signed-off-by Oleg Nesterov <[email protected]>
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@@ -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
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_EXTRACFLAGSto includearch/x86/include/uapialong withinclude/uapi.This looks more consistent, and this fixes "make bzImage" on my old distro which doesn't have
asm/bitsperlong.hin/usr/include/.
Quoted 8 lines
Quoted 1 line
Signed-off-by Oleg Nesterov <[email protected]>Fixed:
6f121e548f83x86, vdso: Reimplement vdso.so preparation in build-time CAcked-by Andy Lutomirski <[email protected]>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.
--tip-bot for Oleg Nesterov
merge bot[tip:x86/urgent] x86/vdso: Fix 'make bzImage' on older distros
In reply to Oleg Nesterovx86/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/.
--- arch/x86/vdso/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
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 hostprogs-y += vdso2c quiet_cmd_vdso2c = VDSO2C $@
Borislav Petkov
maintainercover 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.patchBorislav Petkov
maintainerPATCH 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
@@ -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
tip-bot for Miroslav Benes
merge bot[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
@@ -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.
Borislav Petkov
maintainerPATCH 1/5 x86/mm: Do not flush last cacheline twice in clflush_cache_range()
In reply to Borislav PetkovFrom: 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
@@ -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
tip-bot for Ross Zwisler
merge bot[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.
--- arch/x86/mm/pageattr.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
arch/x86/mm/pageattr.c +6 -7
@@ -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 (); }
Borislav Petkov
maintainerPATCH 1/1 x86/cpu/microcode: Zap changelog
In reply to Borislav PetkovFrom: 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
@@ -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
tip-bot for Borislav Petkov
merge bot[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.
--- 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
@@ -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
Borislav Petkov
maintainerPATCH 2/5 x86/mm: Add kerneldoc comments for pcommit_sfence()
In reply to Borislav PetkovFrom: 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
@@ -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
tip-bot for Ross Zwisler
merge bot[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.
--- arch/x86/include/asm/special_insns.h | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)
arch/x86/include/asm/special_insns.h +38 -0
@@ -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,
Borislav Petkov
maintainerPATCH 3/5 x86/MTRR: Remove wrong address check in __mtrr_type_lookup()
In reply to Borislav PetkovFrom: 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
@@ -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
tip-bot for Toshi Kani
merge bot[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
@@ -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>
Borislav Petkov
maintainerPATCH 1/1 x86/vdso: Add arch/x86/include/uapi include path to HOST_EXTRACFLAGS
In reply to Borislav PetkovFrom: 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/.
--- arch/x86/vdso/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
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 hostprogs-y += vdso2c quiet_cmd_vdso2c = VDSO2C $@
Signature · 1 line
2.3.5
Borislav Petkov
maintainerPATCH 4/5 x86/mm: Add ioremap_uc() helper to map memory uncacheable (not UC-)
In reply to Borislav PetkovFrom: "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 ]
--- 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
@@ -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
@@ -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
@@ -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
@@ -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_wcstatic inline void __iomem *ioremap_wc (phys_addr_t offset,size_t size)
Signature · 1 line
2.3.5
tip-bot for Luis R. Rodriguez
merge bot[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----------------------------------------------------------------------
--- 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
@@ -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
@@ -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
@@ -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
@@ -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_wcstatic inline void __iomem *ioremap_wc (phys_addr_t offset,size_t size)
Borislav Petkov
maintainerPATCH 1/1 x86/alternatives: Switch AMD F15h and later to the P6 NOPs
In reply to Borislav PetkovFrom: 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 cyclesP6:
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 cyclesF14h:
----
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 cyclesP6:
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 cyclesF15h:
-----
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 cyclesP6:
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 cyclesF16h:
-----
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 cyclesP6:
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--- arch/x86/kernel/alternative.c | 9 +++++++++ 1 file changed, 9 insertions(+)
arch/x86/kernel/alternative.c +9 -0
@@ -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
tip-bot for Borislav Petkov
merge bot[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
--- arch/x86/kernel/alternative.c | 9 +++++++++ 1 file changed, 9 insertions(+)
arch/x86/kernel/alternative.c +9 -0
@@ -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;
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>
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
@@ -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>
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_VMAPinarch/x86/KconfigsinceX86_PAEdepends onX86_32.Signed-off-by Toshi Kani <[email protected]>--- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)arch/x86/Kconfig +0
-0
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.
--PATCH v5 2/6 mtrr, x86: Fix MTRR lookup to handle inclusive entry
In reply to Toshi KaniWhen 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
@@ -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>
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
@@ -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
@@ -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
@@ -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>
PATCH v5 4/6 mtrr, x86: Define MTRR_TYPE_INVALID for mtrr_type_lookup()
In reply to Toshi Kanimtrr_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
@@ -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
@@ -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
@@ -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>
PATCH v5 5/6 mtrr, x86: Clean up mtrr_type_lookup()
In reply to Toshi KaniMTRRs 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
@@ -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>
PATCH v5 6/6 mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping
In reply to Toshi KaniThis 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
@@ -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
@@ -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
@@ -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
@@ -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>
Borislav Petkov
maintainerRe: [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()andpmd_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.Signed-off-by Toshi Kani <[email protected]>--- 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.
--- 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
@@ -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
@@ -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
@@ -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.
--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()andpmd_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
Signed-off-by Toshi Kani <[email protected]>--- 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
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>
Borislav Petkov
maintainerRe: [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@@ -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.
--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@@ -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 disabledor
- 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>
Borislav Petkov
maintainerRe: [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.
--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>
Borislav Petkov
maintainerRe: [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.
--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>
Borislav Petkov
maintainerRe: [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()andpmd_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()andioremap_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.
--Borislav Petkov
maintainerRe: [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()andpmd_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()andioremap_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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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.
--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()andpmd_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()andioremap_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>
Re: [PATCH v5 6/6] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping
In reply to Borislav PetkovQuoted 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>
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>
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>
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>
Borislav Petkov
maintainerRe: [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.
--Re: [PATCH v5 6/6] mtrr, mm, x86: Enhance MTRR checks for KVA huge page mapping
Quoted 4 lines · Borislav Petkov
Quoted 1 line · Toshi Kani
Boris, can you update the patch,
Done.
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>
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
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v4 2/3 x86: Make push/pop CFI macros arch-independent
In reply to Josh PoimboeufThe 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v4 3/3 x86, stackvalidate: Add asm frame pointer setup macros
In reply to Josh PoimboeufAdd 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
@@ -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
Re: [PATCH v4 0/3] Compile-time stack frame pointer validation
In reply to Josh PoimboeufQuoted 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
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
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 useFUNC_ENTER.arch/x86/ia32/ia32entry.o: return instruction outside of a function at .entry.text+0x52e. Please useFUNC_ENTER.arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x359. Please useFUNC_ENTER.arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x19be. Please useFUNC_ENTER.arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x19e5. Please useFUNC_ENTER.arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x1c21. Please useFUNC_ENTER.arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x1ceb. Please useFUNC_ENTER.arch/x86/kernel/acpi/wakeup_64.o:wakeup_long64()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/kernel/acpi/wakeup_64.o:do_suspend_lowlevel()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/platform/efi/efi_stub_64.o:efi_call()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x6b. Please useFUNC_ENTER.arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0xc7. Please useFUNC_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 useFUNC_ENTER.arch/x86/kernel/head_64.o:start_cpu0()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/kernel/head_64.o:early_idt_handler()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/realmode/rm/reboot.o: return instruction outside of a function at .text+0x2a. Please useFUNC_ENTER.arch/x86/realmode/rm/copy.o:memcpy()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/realmode/rm/copy.o:memset()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/realmode/rm/copy.o:copy_from_fs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/realmode/rm/copy.o:copy_to_fs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/realmode/rm/bioscall.o:intcall()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/int80.o:__kernel_sigreturn()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/int80.o:__kernel_rt_sigreturn()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/int80.o:__kernel_vsyscall()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/syscall.o:__kernel_sigreturn()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/syscall.o:__kernel_rt_sigreturn()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/syscall.o:__kernel_vsyscall()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/sysenter.o:__kernel_sigreturn()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/sysenter.o:__kernel_rt_sigreturn()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/power/hibernate_asm_64.o: return instruction outside of a function at .text+0x69. Please useFUNC_ENTER.arch/x86/power/hibernate_asm_64.o: return instruction outside of a function at .text+0x16d. Please useFUNC_ENTER.arch/x86/lib/msr-reg.o:rdmsr_safe_regs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/msr-reg.o:wrmsr_safe_regs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/iomap_copy_64.o:__iowrite32_copy()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/clear_page_64.o:clear_page()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/clear_page_64.o:clear_page_orig()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/clear_page_64.o:clear_page_c_e()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/cmpxchg16b_emu.o:this_cpu_cmpxchg16b_emu()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_page_64.o:copy_page()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_page_64.o:copy_page_regs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:_copy_to_user()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:_copy_from_user()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:copy_user_generic_unrolled()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:copy_user_generic_string()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:copy_user_enhanced_fast_string()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:__copy_user_nocache()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:bad_from_user()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/csum-copy_64.o:csum_partial_copy_generic()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/getuser.o:__get_user_1()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/getuser.o:__get_user_2()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/getuser.o:__get_user_4()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/getuser.o:__get_user_8()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/getuser.o: return instruction outside of a function at .text+0xc5. Please useFUNC_ENTER.arch/x86/lib/memcpy_64.o:memcpy()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memcpy_64.o:__memcpy()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memcpy_64.o:memcpy_erms()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memcpy_64.o:memcpy_orig()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memmove_64.o:memmove()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memmove_64.o:__memmove()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memmove_64.o: return instruction outside of a function at .altinstr_replacement+0x5. Please useFUNC_ENTER.arch/x86/lib/memset_64.o:memset()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memset_64.o:__memset()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memset_64.o:memset_erms()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memset_64.o:memset_orig()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/putuser.o:__put_user_1()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/putuser.o:__put_user_2()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/putuser.o:__put_user_4()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/putuser.o:__put_user_8()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/putuser.o: return instruction outside of a function at .text+0xc1. Please useFUNC_ENTER.arch/x86/lib/rwsem.o:call_rwsem_down_read_failed()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/rwsem.o:call_rwsem_down_write_failed()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/rwsem.o:call_rwsem_wake()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/rwsem.o:call_rwsem_downgrade_wake()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/bioscall.o:intcall()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/copy.o:memcpy()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/copy.o:memset()is missing frame pointer logic. Please useFUNC_ENTER.
Quoted 8 lines
arch/x86/boot/copy.o:copy_from_fs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/copy.o:copy_to_fs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/pmjump.o:protected_mode_jump()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/pmjump.o:in_pm32()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/compressed/head_64.o: return instruction outside of a function at .text+0x16e. Please useFUNC_ENTER.arch/x86/boot/compressed/head_64.o: return instruction outside of a function at .text+0x172. Please useFUNC_ENTER.arch/x86/boot/compressed/head_64.o:startup_32()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/header.o:die()is missing frame pointer logic. Please useFUNC_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
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 useFUNC_ENTER.arch/x86/ia32/ia32entry.o: return instruction outside of a function at .entry.text+0x52e. Please useFUNC_ENTER.arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x359. Please useFUNC_ENTER.arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x19be. Please useFUNC_ENTER.arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x19e5. Please useFUNC_ENTER.arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x1c21. Please useFUNC_ENTER.arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x1ceb. Please useFUNC_ENTER.arch/x86/kernel/acpi/wakeup_64.o:wakeup_long64()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/kernel/acpi/wakeup_64.o:do_suspend_lowlevel()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/platform/efi/efi_stub_64.o:efi_call()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x6b. Please useFUNC_ENTER.arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0xc7. Please useFUNC_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 useFUNC_ENTER.arch/x86/kernel/head_64.o:start_cpu0()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/kernel/head_64.o:early_idt_handler()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/realmode/rm/reboot.o: return instruction outside of a function at .text+0x2a. Please useFUNC_ENTER.arch/x86/realmode/rm/copy.o:memcpy()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/realmode/rm/copy.o:memset()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/realmode/rm/copy.o:copy_from_fs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/realmode/rm/copy.o:copy_to_fs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/realmode/rm/bioscall.o:intcall()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/int80.o:__kernel_sigreturn()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/int80.o:__kernel_rt_sigreturn()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/int80.o:__kernel_vsyscall()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/syscall.o:__kernel_sigreturn()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/syscall.o:__kernel_rt_sigreturn()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/syscall.o:__kernel_vsyscall()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/sysenter.o:__kernel_sigreturn()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/sysenter.o:__kernel_rt_sigreturn()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/power/hibernate_asm_64.o: return instruction outside of a function at .text+0x69. Please useFUNC_ENTER.arch/x86/power/hibernate_asm_64.o: return instruction outside of a function at .text+0x16d. Please useFUNC_ENTER.arch/x86/lib/msr-reg.o:rdmsr_safe_regs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/msr-reg.o:wrmsr_safe_regs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/iomap_copy_64.o:__iowrite32_copy()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/clear_page_64.o:clear_page()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/clear_page_64.o:clear_page_orig()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/clear_page_64.o:clear_page_c_e()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/cmpxchg16b_emu.o:this_cpu_cmpxchg16b_emu()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_page_64.o:copy_page()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_page_64.o:copy_page_regs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:_copy_to_user()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:_copy_from_user()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:copy_user_generic_unrolled()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:copy_user_generic_string()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:copy_user_enhanced_fast_string()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:__copy_user_nocache()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:bad_from_user()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/csum-copy_64.o:csum_partial_copy_generic()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/getuser.o:__get_user_1()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/getuser.o:__get_user_2()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/getuser.o:__get_user_4()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/getuser.o:__get_user_8()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/getuser.o: return instruction outside of a function at .text+0xc5. Please useFUNC_ENTER.arch/x86/lib/memcpy_64.o:memcpy()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memcpy_64.o:__memcpy()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memcpy_64.o:memcpy_erms()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memcpy_64.o:memcpy_orig()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memmove_64.o:memmove()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memmove_64.o:__memmove()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memmove_64.o: return instruction outside of a function at .altinstr_replacement+0x5. Please useFUNC_ENTER.arch/x86/lib/memset_64.o:memset()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memset_64.o:__memset()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memset_64.o:memset_erms()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memset_64.o:memset_orig()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/putuser.o:__put_user_1()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/putuser.o:__put_user_2()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/putuser.o:__put_user_4()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/putuser.o:__put_user_8()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/putuser.o: return instruction outside of a function at .text+0xc1. Please useFUNC_ENTER.arch/x86/lib/rwsem.o:call_rwsem_down_read_failed()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/rwsem.o:call_rwsem_down_write_failed()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/rwsem.o:call_rwsem_wake()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/rwsem.o:call_rwsem_downgrade_wake()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/bioscall.o:intcall()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/copy.o:memcpy()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/copy.o:memset()is missing frame pointer logic. Please useFUNC_ENTER.Quoted 8 lines
arch/x86/boot/copy.o:copy_from_fs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/copy.o:copy_to_fs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/pmjump.o:protected_mode_jump()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/pmjump.o:in_pm32()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/compressed/head_64.o: return instruction outside of a function at .text+0x16e. Please useFUNC_ENTER.arch/x86/boot/compressed/head_64.o: return instruction outside of a function at .text+0x172. Please useFUNC_ENTER.arch/x86/boot/compressed/head_64.o:startup_32()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/header.o:die()is missing frame pointer logic. Please useFUNC_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
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 labelENDPROC(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
Re: [PATCH v4 0/3] Compile-time stack frame pointer validation
In reply to Ingo MolnarQuoted 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 useFUNC_ENTER.arch/x86/ia32/ia32entry.o: return instruction outside of a function at .entry.text+0x52e. Please useFUNC_ENTER.arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x359. Please useFUNC_ENTER.arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x19be. Please useFUNC_ENTER.arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x19e5. Please useFUNC_ENTER.arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x1c21. Please useFUNC_ENTER.arch/x86/kernel/entry_64.o: return instruction outside of a function at .entry.text+0x1ceb. Please useFUNC_ENTER.arch/x86/kernel/acpi/wakeup_64.o:wakeup_long64()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/kernel/acpi/wakeup_64.o:do_suspend_lowlevel()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/platform/efi/efi_stub_64.o:efi_call()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0x6b. Please useFUNC_ENTER.arch/x86/kernel/relocate_kernel_64.o: return instruction outside of a function at .text+0xc7. Please useFUNC_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 useFUNC_ENTER.arch/x86/kernel/head_64.o:start_cpu0()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/kernel/head_64.o:early_idt_handler()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/realmode/rm/reboot.o: return instruction outside of a function at .text+0x2a. Please useFUNC_ENTER.arch/x86/realmode/rm/copy.o:memcpy()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/realmode/rm/copy.o:memset()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/realmode/rm/copy.o:copy_from_fs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/realmode/rm/copy.o:copy_to_fs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/realmode/rm/bioscall.o:intcall()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/int80.o:__kernel_sigreturn()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/int80.o:__kernel_rt_sigreturn()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/int80.o:__kernel_vsyscall()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/syscall.o:__kernel_sigreturn()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/syscall.o:__kernel_rt_sigreturn()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/syscall.o:__kernel_vsyscall()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/sysenter.o:__kernel_sigreturn()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/vdso/vdso32/sysenter.o:__kernel_rt_sigreturn()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/power/hibernate_asm_64.o: return instruction outside of a function at .text+0x69. Please useFUNC_ENTER.arch/x86/power/hibernate_asm_64.o: return instruction outside of a function at .text+0x16d. Please useFUNC_ENTER.arch/x86/lib/msr-reg.o:rdmsr_safe_regs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/msr-reg.o:wrmsr_safe_regs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/iomap_copy_64.o:__iowrite32_copy()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/clear_page_64.o:clear_page()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/clear_page_64.o:clear_page_orig()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/clear_page_64.o:clear_page_c_e()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/cmpxchg16b_emu.o:this_cpu_cmpxchg16b_emu()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_page_64.o:copy_page()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_page_64.o:copy_page_regs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:_copy_to_user()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:_copy_from_user()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:copy_user_generic_unrolled()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:copy_user_generic_string()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:copy_user_enhanced_fast_string()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:__copy_user_nocache()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/copy_user_64.o:bad_from_user()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/csum-copy_64.o:csum_partial_copy_generic()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/getuser.o:__get_user_1()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/getuser.o:__get_user_2()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/getuser.o:__get_user_4()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/getuser.o:__get_user_8()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/getuser.o: return instruction outside of a function at .text+0xc5. Please useFUNC_ENTER.arch/x86/lib/memcpy_64.o:memcpy()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memcpy_64.o:__memcpy()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memcpy_64.o:memcpy_erms()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memcpy_64.o:memcpy_orig()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memmove_64.o:memmove()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memmove_64.o:__memmove()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memmove_64.o: return instruction outside of a function at .altinstr_replacement+0x5. Please useFUNC_ENTER.arch/x86/lib/memset_64.o:memset()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memset_64.o:__memset()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memset_64.o:memset_erms()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/memset_64.o:memset_orig()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/putuser.o:__put_user_1()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/putuser.o:__put_user_2()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/putuser.o:__put_user_4()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/putuser.o:__put_user_8()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/putuser.o: return instruction outside of a function at .text+0xc1. Please useFUNC_ENTER.arch/x86/lib/rwsem.o:call_rwsem_down_read_failed()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/rwsem.o:call_rwsem_down_write_failed()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/rwsem.o:call_rwsem_wake()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/lib/rwsem.o:call_rwsem_downgrade_wake()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/bioscall.o:intcall()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/copy.o:memcpy()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/copy.o:memset()is missing frame pointer logic. Please useFUNC_ENTER.Quoted 8 lines
arch/x86/boot/copy.o:copy_from_fs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/copy.o:copy_to_fs()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/pmjump.o:protected_mode_jump()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/pmjump.o:in_pm32()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/compressed/head_64.o: return instruction outside of a function at .text+0x16e. Please useFUNC_ENTER.arch/x86/boot/compressed/head_64.o: return instruction outside of a function at .text+0x172. Please useFUNC_ENTER.arch/x86/boot/compressed/head_64.o:startup_32()is missing frame pointer logic. Please useFUNC_ENTER.arch/x86/boot/header.o:die()is missing frame pointer logic. Please useFUNC_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
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
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/orschedule()
We think alike :)
NMI will be much more interesting than schedule.
--Andy
Borislav Petkov
maintainerRe: [PATCH v4 0/3] Compile-time stack frame pointer validation
In reply to Josh PoimboeufQuoted 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.
--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(structthread_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->addressis
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.
Borislav Petkov
maintainerRe: [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.
--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-stackstoDocumentation/x86/kernel-stacksand added that info to it?
Yeah, please do!
Thanks,
Ingo
Borislav Petkov
maintainerPATCH 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.
---
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
Signature · 1 line
2.3.5
Borislav Petkov
maintainerPATCH 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").
--- Documentation/x86/kernel-stacks | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
Documentation/x86/kernel-stacks +3 -7
@@ -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
Borislav Petkov
maintainerPATCH 3/3 x86/documentation: Adapt Ingo's explanation on printing backtraces
In reply to Borislav PetkovFrom: Borislav Petkov <[email protected]>
Hold it down for future reference, as the question about the question mark in stack traces keeps popping up.
--- Documentation/x86/kernel-stacks | 44 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
Documentation/x86/kernel-stacks +44 -0
@@ -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
tip-bot for Borislav Petkov
merge bot[tip:x86/debug] x86/Documentation: Adapt Ingo' s explanation on printing backtraces
In reply to Ingo Molnarx86/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.
--- Documentation/x86/kernel-stacks | 44 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
Documentation/x86/kernel-stacks +44 -0
@@ -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.
Re: [PATCH v4 0/3] Compile-time stack frame pointer validation
In reply to Josh PoimboeufQuoted 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
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
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
Re: [PATCH v4 0/3] Compile-time stack frame pointer validation
In reply to Linus TorvaldsQuoted 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
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=nkernel:#
#CONFIG_FRAMEPOINTERSare 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
Re: [PATCH v4 0/3] Compile-time stack frame pointer validation
In reply to Ingo MolnarQuoted 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
Peter Zijlstra
maintainerRe: [PATCH v4 0/3] Compile-time stack frame pointer validation
In reply to Andy LutomirskiQuoted 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:
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:
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
Re: [PATCH v4 0/3] Compile-time stack frame pointer validation
In reply to Ingo MolnarQuoted 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