* swap                                .11..ttttt.0
  * prot-none, clean, old       .11.xx0000.1
  * prot-none, clean, young     .11.xx0001.1
- * prot-none, dirty, old       .10.xx0010.1
- * prot-none, dirty, young     .10.xx0011.1
+ * prot-none, dirty, old       .11.xx0010.1
+ * prot-none, dirty, young     .11.xx0011.1
  * read-only, clean, old       .11.xx0100.1
  * read-only, clean, young     .01.xx0101.1
  * read-only, dirty, old       .11.xx0110.1
 #define _SEGMENT_ENTRY_DIRTY   0x2000  /* SW segment dirty bit */
 #define _SEGMENT_ENTRY_YOUNG   0x1000  /* SW segment young bit */
 #define _SEGMENT_ENTRY_LARGE   0x0400  /* STE-format control, large page */
-#define _SEGMENT_ENTRY_READ    0x0002  /* SW segment read bit */
-#define _SEGMENT_ENTRY_WRITE   0x0001  /* SW segment write bit */
+#define _SEGMENT_ENTRY_WRITE   0x0002  /* SW segment write bit */
+#define _SEGMENT_ENTRY_READ    0x0001  /* SW segment read bit */
 
 #ifdef CONFIG_MEM_SOFT_DIRTY
 #define _SEGMENT_ENTRY_SOFT_DIRTY 0x4000 /* SW segment soft dirty bit */
 /*
  * Segment table and region3 table entry encoding
  * (R = read-only, I = invalid, y = young bit):
- *                             dy..R...I...rw
+ *                             dy..R...I...wr
  * prot-none, clean, old       00..1...1...00
  * prot-none, clean, young     01..1...1...00
  * prot-none, dirty, old       10..1...1...00
  * prot-none, dirty, young     11..1...1...00
- * read-only, clean, old       00..1...1...10
- * read-only, clean, young     01..1...0...10
- * read-only, dirty, old       10..1...1...10
- * read-only, dirty, young     11..1...0...10
+ * read-only, clean, old       00..1...1...01
+ * read-only, clean, young     01..1...0...01
+ * read-only, dirty, old       10..1...1...01
+ * read-only, dirty, young     11..1...0...01
  * read-write, clean, old      00..1...1...11
  * read-write, clean, young    01..1...0...11
  * read-write, dirty, old      10..0...1...11
 /*
  * Page protection definitions.
  */
-#define PAGE_NONE      __pgprot(_PAGE_PRESENT | _PAGE_INVALID)
+#define PAGE_NONE      __pgprot(_PAGE_PRESENT | _PAGE_INVALID | _PAGE_PROTECT)
 #define PAGE_READ      __pgprot(_PAGE_PRESENT | _PAGE_READ | \
                                 _PAGE_INVALID | _PAGE_PROTECT)
 #define PAGE_WRITE     __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
 
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
 
+/*
+ * If the bit selected by single-bit bitmask "a" is set within "x", move
+ * it to the position indicated by single-bit bitmask "b".
+ */
+#define move_set_bit(x, a, b)  (((x) & (a)) >> ilog2(a) << ilog2(b))
+
 static inline unsigned long __pte_to_rste(pte_t pte)
 {
        unsigned long rste;
         */
        if (pte_present(pte)) {
                rste = pte_val(pte) & PAGE_MASK;
-               rste |= (pte_val(pte) & _PAGE_READ) >> 4;
-               rste |= (pte_val(pte) & _PAGE_WRITE) >> 4;
-               rste |= (pte_val(pte) & _PAGE_INVALID) >> 5;
-               rste |= (pte_val(pte) & _PAGE_PROTECT);
-               rste |= (pte_val(pte) & _PAGE_DIRTY) << 10;
-               rste |= (pte_val(pte) & _PAGE_YOUNG) << 10;
-               rste |= (pte_val(pte) & _PAGE_SOFT_DIRTY) << 13;
+               rste |= move_set_bit(pte_val(pte), _PAGE_READ,
+                                    _SEGMENT_ENTRY_READ);
+               rste |= move_set_bit(pte_val(pte), _PAGE_WRITE,
+                                    _SEGMENT_ENTRY_WRITE);
+               rste |= move_set_bit(pte_val(pte), _PAGE_INVALID,
+                                    _SEGMENT_ENTRY_INVALID);
+               rste |= move_set_bit(pte_val(pte), _PAGE_PROTECT,
+                                    _SEGMENT_ENTRY_PROTECT);
+               rste |= move_set_bit(pte_val(pte), _PAGE_DIRTY,
+                                    _SEGMENT_ENTRY_DIRTY);
+               rste |= move_set_bit(pte_val(pte), _PAGE_YOUNG,
+                                    _SEGMENT_ENTRY_YOUNG);
+#ifdef CONFIG_MEM_SOFT_DIRTY
+               rste |= move_set_bit(pte_val(pte), _PAGE_SOFT_DIRTY,
+                                    _SEGMENT_ENTRY_SOFT_DIRTY);
+#endif
        } else
                rste = _SEGMENT_ENTRY_INVALID;
        return rste;
        if (present) {
                pte_val(pte) = rste & _SEGMENT_ENTRY_ORIGIN_LARGE;
                pte_val(pte) |= _PAGE_LARGE | _PAGE_PRESENT;
-               pte_val(pte) |= (rste & _SEGMENT_ENTRY_READ) << 4;
-               pte_val(pte) |= (rste & _SEGMENT_ENTRY_WRITE) << 4;
-               pte_val(pte) |= (rste & _SEGMENT_ENTRY_INVALID) << 5;
-               pte_val(pte) |= (rste & _SEGMENT_ENTRY_PROTECT);
-               pte_val(pte) |= (rste & _SEGMENT_ENTRY_DIRTY) >> 10;
-               pte_val(pte) |= (rste & _SEGMENT_ENTRY_YOUNG) >> 10;
-               pte_val(pte) |= (rste & _SEGMENT_ENTRY_SOFT_DIRTY) >> 13;
+               pte_val(pte) |= move_set_bit(rste, _SEGMENT_ENTRY_READ,
+                                            _PAGE_READ);
+               pte_val(pte) |= move_set_bit(rste, _SEGMENT_ENTRY_WRITE,
+                                            _PAGE_WRITE);
+               pte_val(pte) |= move_set_bit(rste, _SEGMENT_ENTRY_INVALID,
+                                            _PAGE_INVALID);
+               pte_val(pte) |= move_set_bit(rste, _SEGMENT_ENTRY_PROTECT,
+                                            _PAGE_PROTECT);
+               pte_val(pte) |= move_set_bit(rste, _SEGMENT_ENTRY_DIRTY,
+                                            _PAGE_DIRTY);
+               pte_val(pte) |= move_set_bit(rste, _SEGMENT_ENTRY_YOUNG,
+                                            _PAGE_YOUNG);
+#ifdef CONFIG_MEM_SOFT_DIRTY
+               pte_val(pte) |= move_set_bit(rste, _SEGMENT_ENTRY_SOFT_DIRTY,
+                                            _PAGE_DIRTY);
+#endif
        } else
                pte_val(pte) = _PAGE_INVALID;
        return pte;