s390/mm: Add gmap pmd linking
authorJanosch Frank <frankja@linux.ibm.com>
Fri, 13 Jul 2018 10:28:20 +0000 (11:28 +0100)
committerJanosch Frank <frankja@linux.ibm.com>
Mon, 30 Jul 2018 10:20:17 +0000 (11:20 +0100)
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>
arch/s390/include/asm/pgtable.h
arch/s390/mm/gmap.c

index 5ab636089c6052c51cb5ac15046ee0975bcfd026..fe36b3bb2afd5aeb2cb0f6f01e8667929311945c 100644 (file)
@@ -268,8 +268,10 @@ static inline int is_module_addr(void *addr)
 #define _REGION_ENTRY_BITS_LARGE 0xffffffff8000fe2fUL
 
 /* 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/* page table origin                */
 #define _SEGMENT_ENTRY_PROTECT 0x200   /* segment protection bit           */
index 0bada5e097cb2bd7787546f3496aa2ebcd937543..870e81fcb0cffa1be54967af70b3730875286308 100644 (file)
@@ -596,10 +596,15 @@ int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr)
        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();