Skip to contentSkip to conversation

s390x/mm: cleanup gmap_pte_op_walk()

PATCH Applied David Hildenbrand 3 participants 4 messages Nov 10, 2017 – Nov 15, 2017

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 s390x/mm: cleanup gmap_pte_op_walk()

gmap_mprotect_notify() refuses shadow gmaps. Turns out that
a) gmap_protect_range()
b) gmap_read_table()
c) gmap_pte_op_walk()

Are never called for gmap shadows. And never should be. This dates back to gmap shadow prototypes where we allowed to call mprotect_notify() on the gmap shadow (to get notified about the prefix pages getting removed). This is avoided by always getting notified about any change on the gmap shadow.

The only real function for walking page tables on shadow gmaps is gmap_table_walk().

So, essentially, these functions should never get called and gmap_pte_op_walk() can be cleaned up. Add some checks to callers of gmap_pte_op_walk().

---
 arch/s390/mm/gmap.c | 22 ++++++++--------------
 1 file changed, 8 insertions(+), 14 deletions(-)
arch/s390/mm/gmap.c +8 -14
index 2f66290c9b92..9630387e5f76 100644
@@ -814,27 +814,17 @@ static inline unsigned long *gmap_table_walk(struct gmap *gmap,
  * @ptl: pointer to the spinlock pointer
  *
  * Returns a pointer to the locked pte for a guest address, or NULL
- *
- * Note: Can also be called for shadow gmaps.
  */
 static pte_t *gmap_pte_op_walk(struct gmap *gmap, unsigned long gaddr,
 			       spinlock_t **ptl)
 {
 	unsigned long *table;
 
-	if (gmap_is_shadow(gmap))
-		spin_lock(&gmap->guest_table_lock);
+	BUG_ON(gmap_is_shadow(gmap));
 	/* Walk the gmap page table, lock and get pte pointer */
 	table = gmap_table_walk(gmap, gaddr, 1); /* get segment pointer */
-	if (!table || *table & _SEGMENT_ENTRY_INVALID) {
-		if (gmap_is_shadow(gmap))
-			spin_unlock(&gmap->guest_table_lock);
+	if (!table || *table & _SEGMENT_ENTRY_INVALID)
 		return NULL;
-	}
-	if (gmap_is_shadow(gmap)) {
-		*ptl = &gmap->guest_table_lock;
-		return pte_offset_map((pmd_t *) table, gaddr);
-	}
 	return pte_alloc_map_lock(gmap->mm, (pmd_t *) table, gaddr, ptl);
 }
 
@@ -889,7 +879,6 @@ static void gmap_pte_op_end(spinlock_t *ptl)
  *
  * Called with sg->mm->mmap_sem in read.
  *
- * Note: Can also be called for shadow gmaps.
  */
 static int gmap_protect_range(struct gmap *gmap, unsigned long gaddr,
 			      unsigned long len, int prot, unsigned long bits)
@@ -899,6 +888,7 @@ static int gmap_protect_range(struct gmap *gmap, unsigned long gaddr,
 	pte_t *ptep;
 	int rc;
 
+	BUG_ON(gmap_is_shadow(gmap));
 	while (len) {
 		rc = -EAGAIN;
 		ptep = gmap_pte_op_walk(gmap, gaddr, &ptl);
@@ -959,7 +949,8 @@ EXPORT_SYMBOL_GPL(gmap_mprotect_notify);
  * @val: pointer to the unsigned long value to return
  *
  * Returns 0 if the value was read, -ENOMEM if out of memory and -EFAULT
- * if reading using the virtual address failed.
+ * if reading using the virtual address failed. -EINVAL if called on a gmap
+ * shadow.
  *
  * Called with gmap->mm->mmap_sem in read.
  */
@@ -970,6 +961,9 @@ int gmap_read_table(struct gmap *gmap, unsigned long gaddr, unsigned long *val)
 	pte_t *ptep, pte;
 	int rc;
 
+	if (gmap_is_shadow(gmap))
+		return -EINVAL;
+
 	while (1) {
 		rc = -EAGAIN;
 		ptep = gmap_pte_op_walk(gmap, gaddr, &ptl);
Signature · 1 line
2.13.6
Reviewed-by on v1 1/1
#1 lore raw

This is KVM, not qemu, subject s/x//

Quoted 11 lines · David Hildenbrand

gmap_mprotect_notify() refuses shadow gmaps. Turns out that
a) gmap_protect_range()
b) gmap_read_table()
c) gmap_pte_op_walk()

Are never called for gmap shadows. And never should be. This dates back to gmap shadow prototypes where we allowed to call mprotect_notify() on the gmap shadow (to get notified about the prefix pages getting removed). This is avoided by always getting notified about any change on the gmap shadow.

Quoted 6 lines

The only real function for walking page tables on shadow gmaps is gmap_table_walk().

So, essentially, these functions should never get called and gmap_pte_op_walk() can be cleaned up. Add some checks to callers of gmap_pte_op_walk().

This already made sense when discussing, but I traced the callers anyhow to make sure we didn't accidentally forget one.

arch/s390/mm/gmap.c static void gmap_pte_op_end(spinlock_t *ptl) · line 892

Quoted 5 lines
arch/s390/mm/gmap.c +0 -1
@@ -889,7 +879,6 @@ static void gmap_pte_op_end(spinlock_t *ptl)
  *
  * Called with sg->mm->mmap_sem in read.
  *
- * Note: Can also be called for shadow gmaps.

How about also getting rid of the line above this one?

#2 lore raw
Quoted 18 lines · Janosch Frank

This is KVM, not qemu, subject s/x//

Quoted 14 lines · David Hildenbrand

gmap_mprotect_notify() refuses shadow gmaps. Turns out that
a) gmap_protect_range()
b) gmap_read_table()
c) gmap_pte_op_walk()

Are never called for gmap shadows. And never should be. This dates back to gmap shadow prototypes where we allowed to call mprotect_notify() on the gmap shadow (to get notified about the prefix pages getting removed). This is avoided by always getting notified about any change on the gmap shadow.

The only real function for walking page tables on shadow gmaps is gmap_table_walk().

Quoted 9 lines
Quoted 3 lines

So, essentially, these functions should never get called and gmap_pte_op_walk() can be cleaned up. Add some checks to callers of gmap_pte_op_walk().

This already made sense when discussing, but I traced the callers anyhow to make sure we didn't accidentally forget one.

Thanks!

Quoted 8 lines

arch/s390/mm/gmap.c static void gmap_pte_op_end(spinlock_t *ptl) · line 892

Quoted 5 lines
arch/s390/mm/gmap.c +0 -1
@@ -889,7 +879,6 @@ static void gmap_pte_op_end(spinlock_t *ptl)
  *
  * Called with sg->mm->mmap_sem in read.
  *
- * Note: Can also be called for shadow gmaps.

How about also getting rid of the line above this one?

Sure, can the person picking this up fix that one up?

Signature · 3 lines
Thanks,

David / dhildenb
#3 lore raw
Quoted 40 lines · David Hildenbrand
Quoted 18 lines · Janosch Frank

This is KVM, not qemu, subject s/x//

Quoted 14 lines · David Hildenbrand

gmap_mprotect_notify() refuses shadow gmaps. Turns out that
a) gmap_protect_range()
b) gmap_read_table()
c) gmap_pte_op_walk()

Are never called for gmap shadows. And never should be. This dates back to gmap shadow prototypes where we allowed to call mprotect_notify() on the gmap shadow (to get notified about the prefix pages getting removed). This is avoided by always getting notified about any change on the gmap shadow.

The only real function for walking page tables on shadow gmaps is gmap_table_walk().

Quoted 9 lines
Quoted 3 lines

So, essentially, these functions should never get called and gmap_pte_op_walk() can be cleaned up. Add some checks to callers of gmap_pte_op_walk().

This already made sense when discussing, but I traced the callers anyhow to make sure we didn't accidentally forget one.

Thanks!

Quoted 8 lines

arch/s390/mm/gmap.c static void gmap_pte_op_end(spinlock_t *ptl) · line 892

Quoted 5 lines
arch/s390/mm/gmap.c +0 -1
@@ -889,7 +879,6 @@ static void gmap_pte_op_end(spinlock_t *ptl)
  *
  * Called with sg->mm->mmap_sem in read.
  *
- * Note: Can also be called for shadow gmaps.

How about also getting rid of the line above this one?

Quoted 1 line

Sure, can the person picking this up fix that one up?

done.

applied.
Not sure yet if this goes via my tree or Martins tree, but the big mm things (e.g. hugetlbfs) will probably go via Martins tree.