RE: [PATCH] x86/mce: Fix set_mce_nospec() to avoid #GP fault

2018-09-10 Thread David Laight
From: Linus Torvalds
> ...
> You could literally do something like
> 
> /* Make it canonical in case we flipped the high bit */
> addr = (long)(addr<<1)>>1;

Isn't it safer to use a mask and let the compiler decide if two
shifts are a good implementation?

addr &= ~HIGH_MAGIC_BIT;

ISTR fixing a bug in gld where it had (foo << 16) >> 16 instead
of foo & 0x. Didn't work well on 64bit.

(I may need to recompile that old gcc/gld again.
Failed miserably last time I tried.)

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, 
UK
Registration No: 1397386 (Wales)


RE: [PATCH] x86/mce: Fix set_mce_nospec() to avoid #GP fault

2018-09-10 Thread David Laight
From: Linus Torvalds
> ...
> You could literally do something like
> 
> /* Make it canonical in case we flipped the high bit */
> addr = (long)(addr<<1)>>1;

Isn't it safer to use a mask and let the compiler decide if two
shifts are a good implementation?

addr &= ~HIGH_MAGIC_BIT;

ISTR fixing a bug in gld where it had (foo << 16) >> 16 instead
of foo & 0x. Didn't work well on 64bit.

(I may need to recompile that old gcc/gld again.
Failed miserably last time I tried.)

David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, 
UK
Registration No: 1397386 (Wales)


Re: [PATCH] x86/mce: Fix set_mce_nospec() to avoid #GP fault

2018-08-31 Thread Thomas Gleixner
On Thu, 30 Aug 2018, Linus Torvalds wrote:
> On Thu, Aug 30, 2018 at 6:49 PM Tony Luck  wrote:
> >
> > Just checking "do we have a non-canonical address" at the bottom of that
> > call stack and flipping bit 63 back on again seems like a bad idea.
> 
> You could literally do something like
> 
> /* Make it canonical in case we flipped the high bit */
> addr = (long)(addr<<1)>>1;
> 
> in the call to clflush and it magically does the right thing.
> 
> Pretty? No. But with a big comment about what is going on and why it's
> done, I think it's prettier than your much bigger patch.
> 
> I dunno. It does strike me as a bit hacky, but I'd rather have a
> *small*  one-liner hack that generates two instructions, than add a
> complex hack that modifies the page tables three times and has a
> serializing instruction in it.
> 
> Both are subtle fixes for a subtle issue, but one seems pretty
> harmless in comparison.
> 
> Hmm?
> 
> But I'll bow to the x86 maintainers.

The above is fugly, but it has the charm of simplicity and I assume it's
going to be useful for other places as well. With a big fat comment WHY we
are doing it it's not that horrible. We have all the other L1TF places
where we fiddle with bits in non-obvious ways, so having another instance
of magic bit fiddling is not that big of a problem.

Thanks,

tglx


Re: [PATCH] x86/mce: Fix set_mce_nospec() to avoid #GP fault

2018-08-31 Thread Thomas Gleixner
On Thu, 30 Aug 2018, Linus Torvalds wrote:
> On Thu, Aug 30, 2018 at 6:49 PM Tony Luck  wrote:
> >
> > Just checking "do we have a non-canonical address" at the bottom of that
> > call stack and flipping bit 63 back on again seems like a bad idea.
> 
> You could literally do something like
> 
> /* Make it canonical in case we flipped the high bit */
> addr = (long)(addr<<1)>>1;
> 
> in the call to clflush and it magically does the right thing.
> 
> Pretty? No. But with a big comment about what is going on and why it's
> done, I think it's prettier than your much bigger patch.
> 
> I dunno. It does strike me as a bit hacky, but I'd rather have a
> *small*  one-liner hack that generates two instructions, than add a
> complex hack that modifies the page tables three times and has a
> serializing instruction in it.
> 
> Both are subtle fixes for a subtle issue, but one seems pretty
> harmless in comparison.
> 
> Hmm?
> 
> But I'll bow to the x86 maintainers.

The above is fugly, but it has the charm of simplicity and I assume it's
going to be useful for other places as well. With a big fat comment WHY we
are doing it it's not that horrible. We have all the other L1TF places
where we fiddle with bits in non-obvious ways, so having another instance
of magic bit fiddling is not that big of a problem.

Thanks,

tglx


Re: [PATCH] x86/mce: Fix set_mce_nospec() to avoid #GP fault

2018-08-30 Thread Linus Torvalds
On Thu, Aug 30, 2018 at 6:49 PM Tony Luck  wrote:
>
> Just checking "do we have a non-canonical address" at the bottom of that
> call stack and flipping bit 63 back on again seems like a bad idea.

You could literally do something like

/* Make it canonical in case we flipped the high bit */
addr = (long)(addr<<1)>>1;

in the call to clflush and it magically does the right thing.

Pretty? No. But with a big comment about what is going on and why it's
done, I think it's prettier than your much bigger patch.

I dunno. It does strike me as a bit hacky, but I'd rather have a
*small*  one-liner hack that generates two instructions, than add a
complex hack that modifies the page tables three times and has a
serializing instruction in it.

Both are subtle fixes for a subtle issue, but one seems pretty
harmless in comparison.

Hmm?

But I'll bow to the x86 maintainers.

 Linus


Re: [PATCH] x86/mce: Fix set_mce_nospec() to avoid #GP fault

2018-08-30 Thread Linus Torvalds
On Thu, Aug 30, 2018 at 6:49 PM Tony Luck  wrote:
>
> Just checking "do we have a non-canonical address" at the bottom of that
> call stack and flipping bit 63 back on again seems like a bad idea.

You could literally do something like

/* Make it canonical in case we flipped the high bit */
addr = (long)(addr<<1)>>1;

in the call to clflush and it magically does the right thing.

Pretty? No. But with a big comment about what is going on and why it's
done, I think it's prettier than your much bigger patch.

I dunno. It does strike me as a bit hacky, but I'd rather have a
*small*  one-liner hack that generates two instructions, than add a
complex hack that modifies the page tables three times and has a
serializing instruction in it.

Both are subtle fixes for a subtle issue, but one seems pretty
harmless in comparison.

Hmm?

But I'll bow to the x86 maintainers.

 Linus


Re: [PATCH] x86/mce: Fix set_mce_nospec() to avoid #GP fault

2018-08-30 Thread Tony Luck
On Thu, Aug 30, 2018 at 6:30 PM Linus Torvalds
 wrote:
>
> On Thu, Aug 30, 2018 at 2:45 PM Tony Luck  wrote:
> >
> > Fix is to move one step at a time. First mark the page not present
> > (using the decoy address). Then it is safe to use the actual address
> > of the 1:1 mapping to mark it "uc", and finally as present.
>
> Can't we do it in one step, but make sure that he clflush gets the real 
> address?
>

I'd like to, but I'd need to have a way to mark the address as needing fixing as
it gets passed from set_memory_uc() to _set_memory_uc() to
change_page_attr_set()
to change_page_attr_set_clear()

Just checking "do we have a non-canonical address" at the bottom of that
call stack and flipping bit 63 back on again seems like a bad idea. But adding
extra flag arguments is majorly ugly too.

-Tony


Re: [PATCH] x86/mce: Fix set_mce_nospec() to avoid #GP fault

2018-08-30 Thread Tony Luck
On Thu, Aug 30, 2018 at 6:30 PM Linus Torvalds
 wrote:
>
> On Thu, Aug 30, 2018 at 2:45 PM Tony Luck  wrote:
> >
> > Fix is to move one step at a time. First mark the page not present
> > (using the decoy address). Then it is safe to use the actual address
> > of the 1:1 mapping to mark it "uc", and finally as present.
>
> Can't we do it in one step, but make sure that he clflush gets the real 
> address?
>

I'd like to, but I'd need to have a way to mark the address as needing fixing as
it gets passed from set_memory_uc() to _set_memory_uc() to
change_page_attr_set()
to change_page_attr_set_clear()

Just checking "do we have a non-canonical address" at the bottom of that
call stack and flipping bit 63 back on again seems like a bad idea. But adding
extra flag arguments is majorly ugly too.

-Tony


Re: [PATCH] x86/mce: Fix set_mce_nospec() to avoid #GP fault

2018-08-30 Thread Linus Torvalds
On Thu, Aug 30, 2018 at 2:45 PM Tony Luck  wrote:
>
> Fix is to move one step at a time. First mark the page not present
> (using the decoy address). Then it is safe to use the actual address
> of the 1:1 mapping to mark it "uc", and finally as present.

Can't we do it in one step, but make sure that he clflush gets the real address?

  Linus


Re: [PATCH] x86/mce: Fix set_mce_nospec() to avoid #GP fault

2018-08-30 Thread Linus Torvalds
On Thu, Aug 30, 2018 at 2:45 PM Tony Luck  wrote:
>
> Fix is to move one step at a time. First mark the page not present
> (using the decoy address). Then it is safe to use the actual address
> of the 1:1 mapping to mark it "uc", and finally as present.

Can't we do it in one step, but make sure that he clflush gets the real address?

  Linus


[PATCH] x86/mce: Fix set_mce_nospec() to avoid #GP fault

2018-08-30 Thread Tony Luck
The trick with flipping bit 63 to avoid loading the address of the
1:1 mapping of the poisoned page while we update the 1:1 map used
to work when we wanted to unmap the page. But it falls down horribly
when we try to directly set the page as uncacheable.

The problem is that when we change the cache mode to uncachable we
try to flush the page from the cache. But the decoy address is
non-canonical, and the CLFLUSH instruction throws a #GP fault.

Fix is to move one step at a time. First mark the page not present
(using the decoy address). Then it is safe to use the actual address
of the 1:1 mapping to mark it "uc", and finally as present.

Fixes: 284ce4011ba6 ("x86/memory_failure: Introduce {set, clear}_mce_nospec()")
Signed-off-by: Tony Luck 
---

Maybe this is horrible. Other suggestions gratefully received.

 arch/x86/include/asm/set_memory.h | 23 +--
 arch/x86/mm/pageattr.c|  5 +
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/set_memory.h 
b/arch/x86/include/asm/set_memory.h
index 07a25753e85c..e876860988bf 100644
--- a/arch/x86/include/asm/set_memory.h
+++ b/arch/x86/include/asm/set_memory.h
@@ -43,6 +43,7 @@ int set_memory_wc(unsigned long addr, int numpages);
 int set_memory_wt(unsigned long addr, int numpages);
 int set_memory_wb(unsigned long addr, int numpages);
 int set_memory_np(unsigned long addr, int numpages);
+int set_memory_p(unsigned long addr, int numpages);
 int set_memory_4k(unsigned long addr, int numpages);
 int set_memory_encrypted(unsigned long addr, int numpages);
 int set_memory_decrypted(unsigned long addr, int numpages);
@@ -111,9 +112,27 @@ static inline int set_mce_nospec(unsigned long pfn)
 */
decoy_addr = (pfn << PAGE_SHIFT) + (PAGE_OFFSET ^ BIT(63));
 
-   rc = set_memory_uc(decoy_addr, 1);
-   if (rc)
+   rc = set_memory_np(decoy_addr, 1);
+   if (rc) {
pr_warn("Could not invalidate pfn=0x%lx from 1:1 map\n", pfn);
+   return rc;
+   }
+
+   native_cpuid_eax(0);
+
+   /* Now safe to use the virtual address in the 1:1 map */
+   rc = set_memory_uc((unsigned long)pfn_to_kaddr(pfn), 1);
+   if (rc) {
+   pr_warn("Could not set pfn=0x%lx uncacheable in 1:1 map\n", 
pfn);
+   return rc;
+   }
+
+   rc = set_memory_p((unsigned long)pfn_to_kaddr(pfn), 1);
+   if (rc) {
+   pr_warn("Could not remap pfn=0x%lx uncacheable in 1:1 map\n", 
pfn);
+   return rc;
+   }
+
return rc;
 }
 #define set_mce_nospec set_mce_nospec
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 8d6c34fe49be..87400351c5a0 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -1776,6 +1776,11 @@ int set_memory_np(unsigned long addr, int numpages)
return change_page_attr_clear(, numpages, __pgprot(_PAGE_PRESENT), 
0);
 }
 
+int set_memory_p(unsigned long addr, int numpages)
+{
+   return change_page_attr_set(, numpages, __pgprot(_PAGE_PRESENT), 
0);
+}
+
 int set_memory_np_noalias(unsigned long addr, int numpages)
 {
int cpa_flags = CPA_NO_CHECK_ALIAS;
-- 
2.17.1



[PATCH] x86/mce: Fix set_mce_nospec() to avoid #GP fault

2018-08-30 Thread Tony Luck
The trick with flipping bit 63 to avoid loading the address of the
1:1 mapping of the poisoned page while we update the 1:1 map used
to work when we wanted to unmap the page. But it falls down horribly
when we try to directly set the page as uncacheable.

The problem is that when we change the cache mode to uncachable we
try to flush the page from the cache. But the decoy address is
non-canonical, and the CLFLUSH instruction throws a #GP fault.

Fix is to move one step at a time. First mark the page not present
(using the decoy address). Then it is safe to use the actual address
of the 1:1 mapping to mark it "uc", and finally as present.

Fixes: 284ce4011ba6 ("x86/memory_failure: Introduce {set, clear}_mce_nospec()")
Signed-off-by: Tony Luck 
---

Maybe this is horrible. Other suggestions gratefully received.

 arch/x86/include/asm/set_memory.h | 23 +--
 arch/x86/mm/pageattr.c|  5 +
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/set_memory.h 
b/arch/x86/include/asm/set_memory.h
index 07a25753e85c..e876860988bf 100644
--- a/arch/x86/include/asm/set_memory.h
+++ b/arch/x86/include/asm/set_memory.h
@@ -43,6 +43,7 @@ int set_memory_wc(unsigned long addr, int numpages);
 int set_memory_wt(unsigned long addr, int numpages);
 int set_memory_wb(unsigned long addr, int numpages);
 int set_memory_np(unsigned long addr, int numpages);
+int set_memory_p(unsigned long addr, int numpages);
 int set_memory_4k(unsigned long addr, int numpages);
 int set_memory_encrypted(unsigned long addr, int numpages);
 int set_memory_decrypted(unsigned long addr, int numpages);
@@ -111,9 +112,27 @@ static inline int set_mce_nospec(unsigned long pfn)
 */
decoy_addr = (pfn << PAGE_SHIFT) + (PAGE_OFFSET ^ BIT(63));
 
-   rc = set_memory_uc(decoy_addr, 1);
-   if (rc)
+   rc = set_memory_np(decoy_addr, 1);
+   if (rc) {
pr_warn("Could not invalidate pfn=0x%lx from 1:1 map\n", pfn);
+   return rc;
+   }
+
+   native_cpuid_eax(0);
+
+   /* Now safe to use the virtual address in the 1:1 map */
+   rc = set_memory_uc((unsigned long)pfn_to_kaddr(pfn), 1);
+   if (rc) {
+   pr_warn("Could not set pfn=0x%lx uncacheable in 1:1 map\n", 
pfn);
+   return rc;
+   }
+
+   rc = set_memory_p((unsigned long)pfn_to_kaddr(pfn), 1);
+   if (rc) {
+   pr_warn("Could not remap pfn=0x%lx uncacheable in 1:1 map\n", 
pfn);
+   return rc;
+   }
+
return rc;
 }
 #define set_mce_nospec set_mce_nospec
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 8d6c34fe49be..87400351c5a0 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -1776,6 +1776,11 @@ int set_memory_np(unsigned long addr, int numpages)
return change_page_attr_clear(, numpages, __pgprot(_PAGE_PRESENT), 
0);
 }
 
+int set_memory_p(unsigned long addr, int numpages)
+{
+   return change_page_attr_set(, numpages, __pgprot(_PAGE_PRESENT), 
0);
+}
+
 int set_memory_np_noalias(unsigned long addr, int numpages)
 {
int cpa_flags = CPA_NO_CHECK_ALIAS;
-- 
2.17.1