Blob Blame History Raw
From: Janosch Frank <frankja@linux.ibm.com>
Subject: s390/mm: Add gmap pmd linking
Patch-mainline: v4.19-rc1
Git-commit: 58b7e200d2f1f9af9ef69a401a877791837a1c87
References: FATE#326372, LTC#169184, bsc#1113484

Summary:     kernel: Introduce huge page KVM backing support
Description: This adds the KVM support for libhugetlbfs backings of
             s390 KVM guests.

Upstream-Description:

             s390/mm: Add gmap pmd linking

             Let's allow pmds to be linked into gmap for the upcoming s390 KVM huge
             page support.

             Before this patch we copied the full userspace pmd entry. This is not
             correct, as it contains SW defined bits that might be interpreted
             differently in the GMAP context. Now we only copy over all hardware
             relevant information leaving out the software bits.

             Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
             Reviewed-by: David Hildenbrand <david@redhat.com>

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 arch/s390/include/asm/pgtable.h |    6 ++++--
 arch/s390/mm/gmap.c             |   13 +++++++++----
 2 files changed, 13 insertions(+), 6 deletions(-)

--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -312,8 +312,10 @@ static inline int is_module_addr(void *a
 #define _REGION_ENTRY_BITS_LARGE 0xffffffff8000fe27UL
 
 /* Bits in the segment table entry */
-#define _SEGMENT_ENTRY_BITS	0xfffffffffffffe33UL
-#define _SEGMENT_ENTRY_BITS_LARGE 0xfffffffffff0ff33UL
+#define _SEGMENT_ENTRY_BITS			0xfffffffffffffe33UL
+#define _SEGMENT_ENTRY_BITS_LARGE		0xfffffffffff0ff33UL
+#define _SEGMENT_ENTRY_HARDWARE_BITS		0xfffffffffffffe30UL
+#define _SEGMENT_ENTRY_HARDWARE_BITS_LARGE	0xfffffffffff00730UL
 #define _SEGMENT_ENTRY_ORIGIN_LARGE ~0xfffffUL /* large page address	    */
 #define _SEGMENT_ENTRY_ORIGIN	~0x7ffUL/* segment table origin		    */
 #define _SEGMENT_ENTRY_PROTECT	0x200	/* page protection bit		    */
--- a/arch/s390/mm/gmap.c
+++ b/arch/s390/mm/gmap.c
@@ -592,10 +592,15 @@ int __gmap_link(struct gmap *gmap, unsig
 	if (*table == _SEGMENT_ENTRY_EMPTY) {
 		rc = radix_tree_insert(&gmap->host_to_guest,
 				       vmaddr >> PMD_SHIFT, table);
-		if (!rc)
-			*table = pmd_val(*pmd);
-	} else
-		rc = 0;
+		if (!rc) {
+			if (pmd_large(*pmd)) {
+				*table = pmd_val(*pmd) &
+					_SEGMENT_ENTRY_HARDWARE_BITS_LARGE;
+			} else
+				*table = pmd_val(*pmd) &
+					_SEGMENT_ENTRY_HARDWARE_BITS;
+		}
+	}
 	spin_unlock(&gmap->guest_table_lock);
 	spin_unlock(ptl);
 	radix_tree_preload_end();