All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yu Zhang <yu.c.zhang@linux.intel.com>
To: kvm@vger.kernel.org
Cc: pbonzini@redhat.com
Subject: [kvm-unit-tests] x86: access: Add test for 5 level paging mode
Date: Fri, 25 Aug 2017 19:57:31 +0800	[thread overview]
Message-ID: <1503662251-13895-1-git-send-email-yu.c.zhang@linux.intel.com> (raw)

Provide paging mode switching logic to run access test in 5
level paging mode if LA57 is detected. Qemu parameter +la57
should be used to expose this feature, for example:
./x86-run ./x86/access.flat -cpu qemu64,+la57

Signed-off-by: Yu Zhang <yu.c.zhang@linux.intel.com>
---
 x86/access.c   | 17 +++++++++++++++--
 x86/cstart64.S | 43 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/x86/access.c b/x86/access.c
index 0546dbb..56d17a1 100644
--- a/x86/access.c
+++ b/x86/access.c
@@ -15,6 +15,7 @@ typedef unsigned long pt_element_t;
 static int cpuid_7_ebx;
 static int cpuid_7_ecx;
 static int invalid_mask;
+static int page_table_levels;
 
 #define PT_BASE_ADDR_MASK ((pt_element_t)((((pt_element_t)1 << 40) - 1) & PAGE_MASK))
 #define PT_PSE_BASE_ADDR_MASK (PT_BASE_ADDR_MASK & ~(1ull << 21))
@@ -107,6 +108,8 @@ enum {
 #define AC_CPU_CR4_SMEP_MASK  (1 << AC_CPU_CR4_SMEP_BIT)
 #define AC_CPU_CR4_PKE_MASK   (1 << AC_CPU_CR4_PKE_BIT)
 
+extern void setup_5level_page_table();
+
 const char *ac_names[] = {
     [AC_PTE_PRESENT_BIT] = "pte.p",
     [AC_PTE_ACCESSED_BIT] = "pte.a",
@@ -467,11 +470,12 @@ void __ac_setup_specific_pages(ac_test_t *at, ac_pool_t *pool, u64 pd_page,
 	ac_test_reset_pt_pool(pool);
 
     at->ptep = 0;
-    for (int i = 4; i >= 1 && (i >= 2 || !F(AC_PDE_PSE)); --i) {
+    for (int i = page_table_levels; i >= 1 && (i >= 2 || !F(AC_PDE_PSE)); --i) {
 	pt_element_t *vroot = va(root & PT_BASE_ADDR_MASK);
 	unsigned index = PT_INDEX((unsigned long)at->virt, i);
 	pt_element_t pte = 0;
 	switch (i) {
+	case 5:
 	case 4:
 	case 3:
 	    pte = pd_page ? pd_page : ac_test_alloc_pt(pool);
@@ -552,7 +556,7 @@ static void dump_mapping(ac_test_t *at)
 	int i;
 
 	printf("Dump mapping: address: %p\n", at->virt);
-	for (i = 4; i >= 1 && (i >= 2 || !F(AC_PDE_PSE)); --i) {
+	for (i = page_table_levels ; i >= 1 && (i >= 2 || !F(AC_PDE_PSE)); --i) {
 		pt_element_t *vroot = va(root & PT_BASE_ADDR_MASK);
 		unsigned index = PT_INDEX((unsigned long)at->virt, i);
 		pt_element_t pte = vroot[index];
@@ -986,6 +990,15 @@ int main()
     cpuid_7_ecx = cpuid(7).c;
 
     printf("starting test\n\n");
+    page_table_levels = 4;
     r = ac_test_run();
+
+    if (cpuid_7_ecx & (1 << 16)) {
+        page_table_levels = 5;
+        setup_5level_page_table();
+        printf("starting 5-level paging test.\n\n");
+        r = ac_test_run();
+    }
+
     return r ? 0 : 1;
 }
diff --git a/x86/cstart64.S b/x86/cstart64.S
index 4c26fb2..8e4a1f3 100644
--- a/x86/cstart64.S
+++ b/x86/cstart64.S
@@ -45,6 +45,10 @@ ptl4:
 	.quad ptl3 + 7
 
 .align 4096
+ptl5:
+	.quad ptl4 + 7
+
+.align 4096
 
 gdt64_desc:
 	.word gdt64_end - gdt64 - 1
@@ -91,6 +95,8 @@ tss_end:
 
 mb_boot_info:	.quad 0
 
+pt_root:	.quad ptl4
+
 .section .init
 
 .code32
@@ -119,14 +125,36 @@ start:
 	call prepare_64
 	jmpl $8, $start64
 
+switch_to_5level:
+	/* Disable CR4.PCIDE */
+	mov %cr4, %eax
+	btr $17, %eax
+	mov %eax, %cr4
+
+	mov %cr0, %eax
+	btr $31, %eax
+	mov %eax, %cr0
+
+	mov $ptl5, %eax
+	mov %eax, pt_root
+
+	/* Enable CR4.LA57 */
+	mov %cr4, %eax
+	bts $12, %eax
+	mov %eax, %cr4
+
+	call enter_long_mode
+	jmpl $8, $lvl5
+
 prepare_64:
 	lgdt gdt64_desc
 
+enter_long_mode:
 	mov %cr4, %eax
 	bts $5, %eax  // pae
 	mov %eax, %cr4
 
-	mov $ptl4, %eax
+	mov pt_root, %eax
 	mov %eax, %cr3
 
 efer = 0xc0000080
@@ -211,6 +239,19 @@ start64:
 	mov %eax, %edi
 	call exit
 
+.globl setup_5level_page_table
+setup_5level_page_table:
+	/* Check if 5-level paging has already enabled */
+	mov %cr4, %rax
+	test $12, %eax
+	jnz lvl5
+
+	pushq $32
+	pushq $switch_to_5level
+	lretq
+lvl5:
+	retq
+
 idt_descr:
 	.word 16 * 256 - 1
 	.quad boot_idt
-- 
2.5.0

             reply	other threads:[~2017-08-25 12:20 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-25 11:57 Yu Zhang [this message]
2017-09-12 12:16 ` [kvm-unit-tests] x86: access: Add test for 5 level paging mode Paolo Bonzini
2017-09-12 13:39   ` Radim Krčmář
2017-09-12 13:42     ` Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1503662251-13895-1-git-send-email-yu.c.zhang@linux.intel.com \
    --to=yu.c.zhang@linux.intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.