Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1538675 > unrolled thread

[RFC, PATCHv1 15/28] x86: detect 5-level paging support

Started by"Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
First post2016-12-08 17:30 +0100
Last post2016-12-09 17:40 +0100
Articles 6 — 4 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [RFC, PATCHv1 15/28] x86: detect 5-level paging support "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2016-12-08 17:30 +0100
    Re: [RFC, PATCHv1 15/28] x86: detect 5-level paging support Borislav Petkov <bp@alien8.de> - 2016-12-08 21:10 +0100
      Re: [RFC, PATCHv1 15/28] x86: detect 5-level paging support Linus Torvalds <torvalds@linux-foundation.org> - 2016-12-08 21:10 +0100
        Re: [RFC, PATCHv1 15/28] x86: detect 5-level paging support Borislav Petkov <bp@alien8.de> - 2016-12-08 21:30 +0100
      Re: [RFC, PATCHv1 15/28] x86: detect 5-level paging support "Kirill A. Shutemov" <kirill@shutemov.name> - 2016-12-09 16:40 +0100
        Re: [RFC, PATCHv1 15/28] x86: detect 5-level paging support Borislav Petkov <bp@alien8.de> - 2016-12-09 17:40 +0100

#1538675 — [RFC, PATCHv1 15/28] x86: detect 5-level paging support

From"Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Date2016-12-08 17:30 +0100
Subject[RFC, PATCHv1 15/28] x86: detect 5-level paging support
Message-ID<sM9K2-8la-3@gated-at.bofh.it>
5-level paging support is required from hardware when compiled with
CONFIG_X86_5LEVEL=y. We may implement runtime switch support later.

Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
---
 arch/x86/boot/cpucheck.c                 |  9 +++++++++
 arch/x86/boot/cpuflags.c                 | 16 ++++++++++++++++
 arch/x86/include/asm/cpufeatures.h       |  1 +
 arch/x86/include/asm/disabled-features.h |  8 +++++++-
 arch/x86/include/asm/required-features.h |  8 +++++++-
 5 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c
index 4ad7d70e8739..8f0c4c9fc904 100644
--- a/arch/x86/boot/cpucheck.c
+++ b/arch/x86/boot/cpucheck.c
@@ -44,6 +44,15 @@ static const u32 req_flags[NCAPINTS] =
 	0, /* REQUIRED_MASK5 not implemented in this file */
 	REQUIRED_MASK6,
 	0, /* REQUIRED_MASK7 not implemented in this file */
+	0, /* REQUIRED_MASK8 not implemented in this file */
+	0, /* REQUIRED_MASK9 not implemented in this file */
+	0, /* REQUIRED_MASK10 not implemented in this file */
+	0, /* REQUIRED_MASK11 not implemented in this file */
+	0, /* REQUIRED_MASK12 not implemented in this file */
+	0, /* REQUIRED_MASK13 not implemented in this file */
+	0, /* REQUIRED_MASK14 not implemented in this file */
+	0, /* REQUIRED_MASK15 not implemented in this file */
+	REQUIRED_MASK16,
 };
 
 #define A32(a, b, c, d) (((d) << 24)+((c) << 16)+((b) << 8)+(a))
diff --git a/arch/x86/boot/cpuflags.c b/arch/x86/boot/cpuflags.c
index 6687ab953257..26e9a287805f 100644
--- a/arch/x86/boot/cpuflags.c
+++ b/arch/x86/boot/cpuflags.c
@@ -80,6 +80,17 @@ static inline void cpuid(u32 id, u32 *a, u32 *b, u32 *c, u32 *d)
 	);
 }
 
+static inline void cpuid_count(u32 id, u32 count,
+		u32 *a, u32 *b, u32 *c, u32 *d)
+{
+	asm volatile(".ifnc %%ebx,%3 ; movl  %%ebx,%3 ; .endif	\n\t"
+		     "cpuid					\n\t"
+		     ".ifnc %%ebx,%3 ; xchgl %%ebx,%3 ; .endif	\n\t"
+		    : "=a" (*a), "=c" (*c), "=d" (*d), EBX_REG (*b)
+		    : "a" (id), "c" (count)
+	);
+}
+
 void get_cpuflags(void)
 {
 	u32 max_intel_level, max_amd_level;
@@ -108,6 +119,11 @@ void get_cpuflags(void)
 				cpu.model += ((tfms >> 16) & 0xf) << 4;
 		}
 
+		if (max_intel_level >= 0x00000007) {
+			cpuid_count(0x00000007, 0, &ignored, &ignored,
+					&cpu.flags[16], &ignored);
+		}
+
 		cpuid(0x80000000, &max_amd_level, &ignored, &ignored,
 		      &ignored);
 
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 92a8308b96f6..388f1277880f 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -280,6 +280,7 @@
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */
 #define X86_FEATURE_PKU		(16*32+ 3) /* Protection Keys for Userspace */
 #define X86_FEATURE_OSPKE	(16*32+ 4) /* OS Protection Keys Enable */
+#define X86_FEATURE_LA57	(16*32+16) /* 5-level page tables */
 
 /* AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17 */
 #define X86_FEATURE_OVERFLOW_RECOV (17*32+0) /* MCA overflow recovery support */
diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h
index 85599ad4d024..fc0960236fc3 100644
--- a/arch/x86/include/asm/disabled-features.h
+++ b/arch/x86/include/asm/disabled-features.h
@@ -36,6 +36,12 @@
 # define DISABLE_OSPKE		(1<<(X86_FEATURE_OSPKE & 31))
 #endif /* CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS */
 
+#ifdef CONFIG_X86_5LEVEL
+#define DISABLE_LA57	0
+#else
+#define DISABLE_LA57	(1<<(X86_FEATURE_LA57 & 31))
+#endif
+
 /*
  * Make sure to add features to the correct mask
  */
@@ -55,7 +61,7 @@
 #define DISABLED_MASK13	0
 #define DISABLED_MASK14	0
 #define DISABLED_MASK15	0
-#define DISABLED_MASK16	(DISABLE_PKU|DISABLE_OSPKE)
+#define DISABLED_MASK16	(DISABLE_PKU|DISABLE_OSPKE|DISABLE_LA57)
 #define DISABLED_MASK17	0
 #define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
 
diff --git a/arch/x86/include/asm/required-features.h b/arch/x86/include/asm/required-features.h
index fac9a5c0abe9..d91ba04dd007 100644
--- a/arch/x86/include/asm/required-features.h
+++ b/arch/x86/include/asm/required-features.h
@@ -53,6 +53,12 @@
 # define NEED_MOVBE	0
 #endif
 
+#ifdef CONFIG_X86_5LEVEL
+# define NEED_LA57	(1<<(X86_FEATURE_LA57 & 31))
+#else
+# define NEED_LA57	0
+#endif
+
 #ifdef CONFIG_X86_64
 #ifdef CONFIG_PARAVIRT
 /* Paravirtualized systems may not have PSE or PGE available */
@@ -98,7 +104,7 @@
 #define REQUIRED_MASK13	0
 #define REQUIRED_MASK14	0
 #define REQUIRED_MASK15	0
-#define REQUIRED_MASK16	0
+#define REQUIRED_MASK16	(NEED_LA57)
 #define REQUIRED_MASK17	0
 #define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
 
-- 
2.10.2

[toc] | [next] | [standalone]


#1538847

FromBorislav Petkov <bp@alien8.de>
Date2016-12-08 21:10 +0100
Message-ID<sMdaV-254-15@gated-at.bofh.it>
In reply to#1538675
On Thu, Dec 08, 2016 at 07:21:37PM +0300, Kirill A. Shutemov wrote:
> 5-level paging support is required from hardware when compiled with
> CONFIG_X86_5LEVEL=y. We may implement runtime switch support later.
> 
> Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>

...

> diff --git a/arch/x86/boot/cpuflags.c b/arch/x86/boot/cpuflags.c
> index 6687ab953257..26e9a287805f 100644
> --- a/arch/x86/boot/cpuflags.c
> +++ b/arch/x86/boot/cpuflags.c
> @@ -80,6 +80,17 @@ static inline void cpuid(u32 id, u32 *a, u32 *b, u32 *c, u32 *d)
>  	);
>  }
>  
> +static inline void cpuid_count(u32 id, u32 count,
> +		u32 *a, u32 *b, u32 *c, u32 *d)
> +{
> +	asm volatile(".ifnc %%ebx,%3 ; movl  %%ebx,%3 ; .endif	\n\t"
> +		     "cpuid					\n\t"
> +		     ".ifnc %%ebx,%3 ; xchgl %%ebx,%3 ; .endif	\n\t"
> +		    : "=a" (*a), "=c" (*c), "=d" (*d), EBX_REG (*b)
> +		    : "a" (id), "c" (count)
> +	);
> +}

Pls make those like cpuid() and cpuid_count() in
arch/x86/include/asm/processor.h, which explicitly assign ecx and then
call the underlying helper.

The cpuid() in cpuflags.c doesn't zero ecx which, if we have to be
pedantic, it should do. It calls CPUID now with the ptr value of its 4th
on 64-bit and 3rd arg on 32-bit, respectively, IINM.

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

[toc] | [prev] | [next] | [standalone]


#1538848

FromLinus Torvalds <torvalds@linux-foundation.org>
Date2016-12-08 21:10 +0100
Message-ID<sMdaV-254-17@gated-at.bofh.it>
In reply to#1538847
On Thu, Dec 8, 2016 at 12:05 PM, Borislav Petkov <bp@alien8.de> wrote:
>
> The cpuid() in cpuflags.c doesn't zero ecx which, if we have to be
> pedantic, it should do. It calls CPUID now with the ptr value of its 4th
> on 64-bit and 3rd arg on 32-bit, respectively, IINM.

In fact, just do a single cpuid_count(), and then implement the
traditional cpuid() as just

   #define cpuid(x, a,b,c,d) cpuid_count(x, 0, a, b, c, d)

or something.

Especially since that's some of the ugliest inline asm ever due to the
nasty BX handling.

          Linus

[toc] | [prev] | [next] | [standalone]


#1538858

FromBorislav Petkov <bp@alien8.de>
Date2016-12-08 21:30 +0100
Message-ID<sMduh-2eY-5@gated-at.bofh.it>
In reply to#1538848
On Thu, Dec 08, 2016 at 12:08:53PM -0800, Linus Torvalds wrote:
> Especially since that's some of the ugliest inline asm ever due to the
> nasty BX handling.

Yeah, about that: why doesn't gcc handle that for us like it would
handle a clobbered register? I mean, it *should* know that BX is live
when building with -fPIC... The .ifnc thing looks really silly.

Hmmm.

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

[toc] | [prev] | [next] | [standalone]


#1539444

From"Kirill A. Shutemov" <kirill@shutemov.name>
Date2016-12-09 16:40 +0100
Message-ID<sMvrc-4YR-19@gated-at.bofh.it>
In reply to#1538847
On Thu, Dec 08, 2016 at 09:05:05PM +0100, Borislav Petkov wrote:
> On Thu, Dec 08, 2016 at 07:21:37PM +0300, Kirill A. Shutemov wrote:
> > 5-level paging support is required from hardware when compiled with
> > CONFIG_X86_5LEVEL=y. We may implement runtime switch support later.
> > 
> > Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
> 
> ...
> 
> > diff --git a/arch/x86/boot/cpuflags.c b/arch/x86/boot/cpuflags.c
> > index 6687ab953257..26e9a287805f 100644
> > --- a/arch/x86/boot/cpuflags.c
> > +++ b/arch/x86/boot/cpuflags.c
> > @@ -80,6 +80,17 @@ static inline void cpuid(u32 id, u32 *a, u32 *b, u32 *c, u32 *d)
> >  	);
> >  }
> >  
> > +static inline void cpuid_count(u32 id, u32 count,
> > +		u32 *a, u32 *b, u32 *c, u32 *d)
> > +{
> > +	asm volatile(".ifnc %%ebx,%3 ; movl  %%ebx,%3 ; .endif	\n\t"
> > +		     "cpuid					\n\t"
> > +		     ".ifnc %%ebx,%3 ; xchgl %%ebx,%3 ; .endif	\n\t"
> > +		    : "=a" (*a), "=c" (*c), "=d" (*d), EBX_REG (*b)
> > +		    : "a" (id), "c" (count)
> > +	);
> > +}
> 
> Pls make those like cpuid() and cpuid_count() in
> arch/x86/include/asm/processor.h, which explicitly assign ecx and then
> call the underlying helper.
> 
> The cpuid() in cpuflags.c doesn't zero ecx which, if we have to be
> pedantic, it should do. It calls CPUID now with the ptr value of its 4th
> on 64-bit and 3rd arg on 32-bit, respectively, IINM.

Something like this?

diff --git a/arch/x86/boot/cpuflags.c b/arch/x86/boot/cpuflags.c
index 6687ab953257..366aad972025 100644
--- a/arch/x86/boot/cpuflags.c
+++ b/arch/x86/boot/cpuflags.c
@@ -70,16 +70,22 @@ int has_eflag(unsigned long mask)
 # define EBX_REG "=b"
 #endif

-static inline void cpuid(u32 id, u32 *a, u32 *b, u32 *c, u32 *d)
+static inline void cpuid_count(u32 id, u32 count,
+               u32 *a, u32 *b, u32 *c, u32 *d)
 {
+       *a = id;
+       *c = count;
+
        asm volatile(".ifnc %%ebx,%3 ; movl  %%ebx,%3 ; .endif  \n\t"
                     "cpuid                                     \n\t"
                     ".ifnc %%ebx,%3 ; xchgl %%ebx,%3 ; .endif  \n\t"
                    : "=a" (*a), "=c" (*c), "=d" (*d), EBX_REG (*b)
-                   : "a" (id)
+                   : "a" (id), "c" (count)
        );
 }

+#define cpuid(id, a, b, c, d) cpuid_count(id, 0, a, b, c, d)
+
 void get_cpuflags(void)
 {
        u32 max_intel_level, max_amd_level;
-- 
 Kirill A. Shutemov

[toc] | [prev] | [next] | [standalone]


#1539545

FromBorislav Petkov <bp@alien8.de>
Date2016-12-09 17:40 +0100
Message-ID<sMwnh-5zi-109@gated-at.bofh.it>
In reply to#1539444
On Fri, Dec 09, 2016 at 06:32:33PM +0300, Kirill A. Shutemov wrote:
> Something like this?
> 
> diff --git a/arch/x86/boot/cpuflags.c b/arch/x86/boot/cpuflags.c
> index 6687ab953257..366aad972025 100644
> --- a/arch/x86/boot/cpuflags.c
> +++ b/arch/x86/boot/cpuflags.c
> @@ -70,16 +70,22 @@ int has_eflag(unsigned long mask)
>  # define EBX_REG "=b"
>  #endif
> 
> -static inline void cpuid(u32 id, u32 *a, u32 *b, u32 *c, u32 *d)
> +static inline void cpuid_count(u32 id, u32 count,
> +               u32 *a, u32 *b, u32 *c, u32 *d)
>  {
> +       *a = id;
> +       *c = count;
> +
>         asm volatile(".ifnc %%ebx,%3 ; movl  %%ebx,%3 ; .endif  \n\t"
>                      "cpuid                                     \n\t"
>                      ".ifnc %%ebx,%3 ; xchgl %%ebx,%3 ; .endif  \n\t"
>                     : "=a" (*a), "=c" (*c), "=d" (*d), EBX_REG (*b)
> -                   : "a" (id)
> +                   : "a" (id), "c" (count)
>         );
>  }
> 
> +#define cpuid(id, a, b, c, d) cpuid_count(id, 0, a, b, c, d)

LGTM.

Thanks.

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web