* [PATCH 0/2] Fix swap and page migration for LPAE
@ 2012-07-26 16:01 Will Deacon
2012-07-26 16:01 ` [PATCH 1/2] ARM: mm: avoid setting nG bit for user mappings that aren't present Will Deacon
2012-07-26 16:01 ` [PATCH 2/2] ARM: mm: use 5 bits for swapfile type encoding Will Deacon
0 siblings, 2 replies; 5+ messages in thread
From: Will Deacon @ 2012-07-26 16:01 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
These two patches fix swapping and page migration for LPAE-enabled
kernels. Without these changes, we corrupt the offset stored in the file
pte when updating the page tables and may truncate the pfn when storing
it into a swp_entry_t.
I'll CC stable on the final patches.
All feedback welcome,
Will
Will Deacon (2):
ARM: mm: avoid setting nG bit for user mappings that aren't present
ARM: mm: use 5 bits for swapfile type encoding
arch/arm/include/asm/pgtable.h | 40 +++++++++++++++++++++-------------------
arch/arm/mm/flush.c | 2 --
2 files changed, 21 insertions(+), 21 deletions(-)
--
1.7.4.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] ARM: mm: avoid setting nG bit for user mappings that aren't present
2012-07-26 16:01 [PATCH 0/2] Fix swap and page migration for LPAE Will Deacon
@ 2012-07-26 16:01 ` Will Deacon
2012-07-26 16:49 ` Catalin Marinas
2012-07-26 16:01 ` [PATCH 2/2] ARM: mm: use 5 bits for swapfile type encoding Will Deacon
1 sibling, 1 reply; 5+ messages in thread
From: Will Deacon @ 2012-07-26 16:01 UTC (permalink / raw)
To: linux-arm-kernel
Swap entries are encoding in ptes such that !pte_present(pte) and
pte_file(pte). The remaining bits of the descriptor are used to identify
the swapfile and offset within it to the swap entry.
When writing such a pte for a user virtual address, set_pte_at
unconditionally sets the nG bit, which (in the case of LPAE) will
corrupt the swapfile offset and lead to a BUG:
[ 140.494067] swap_free: Unused swap offset entry 000763b4
[ 140.509989] BUG: Bad page map in process rs:main Q:Reg pte:0ec76800 pmd:8f92e003
This patch fixes the problem by only setting the nG bit for user
mappings that are actually present.
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
arch/arm/include/asm/pgtable.h | 34 ++++++++++++++++++----------------
arch/arm/mm/flush.c | 2 --
2 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index f66626d..d88f9f0 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -195,6 +195,18 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd)
#define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0)
+#define pte_none(pte) (!pte_val(pte))
+#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT)
+#define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY))
+#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY)
+#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG)
+#define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN))
+#define pte_special(pte) (0)
+
+#define pte_present_user(pte) \
+ ((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \
+ (L_PTE_PRESENT | L_PTE_USER))
+
#if __LINUX_ARM_ARCH__ < 6
static inline void __sync_icache_dcache(pte_t pteval)
{
@@ -206,25 +218,15 @@ extern void __sync_icache_dcache(pte_t pteval);
static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pteval)
{
- if (addr >= TASK_SIZE)
- set_pte_ext(ptep, pteval, 0);
- else {
+ unsigned long ext = 0;
+
+ if (addr < TASK_SIZE && pte_present_user(pteval)) {
__sync_icache_dcache(pteval);
- set_pte_ext(ptep, pteval, PTE_EXT_NG);
+ ext |= PTE_EXT_NG;
}
-}
-#define pte_none(pte) (!pte_val(pte))
-#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT)
-#define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY))
-#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY)
-#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG)
-#define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN))
-#define pte_special(pte) (0)
-
-#define pte_present_user(pte) \
- ((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \
- (L_PTE_PRESENT | L_PTE_USER))
+ set_pte_ext(ptep, pteval, ext);
+}
#define PTE_BIT_FUNC(fn,op) \
static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 7745854..40ca11e 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -231,8 +231,6 @@ void __sync_icache_dcache(pte_t pteval)
struct page *page;
struct address_space *mapping;
- if (!pte_present_user(pteval))
- return;
if (cache_is_vipt_nonaliasing() && !pte_exec(pteval))
/* only flush non-aliasing VIPT caches for exec mappings */
return;
--
1.7.4.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] ARM: mm: use 5 bits for swapfile type encoding
2012-07-26 16:01 [PATCH 0/2] Fix swap and page migration for LPAE Will Deacon
2012-07-26 16:01 ` [PATCH 1/2] ARM: mm: avoid setting nG bit for user mappings that aren't present Will Deacon
@ 2012-07-26 16:01 ` Will Deacon
2012-07-26 16:49 ` Catalin Marinas
1 sibling, 1 reply; 5+ messages in thread
From: Will Deacon @ 2012-07-26 16:01 UTC (permalink / raw)
To: linux-arm-kernel
Page migration encodes the pfn in the offset field of a swp_entry_t.
For LPAE, we support physical addresses of up to 36 bits (due to
sparsemem limitations with the size of page flags), requiring 24 bits
to represent a pfn. A further 3 bits are used to encode a swp_entry into
a pte, leaving 5 bits for the type field. Furthermore, the core code
defines MAX_SWAPFILES_SHIFT as 5, so the additional type bit does not
get used.
This patch reduces the width of the type field to 5 bits, allowing us
to create up to 31 swapfiles of 64GB each.
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
arch/arm/include/asm/pgtable.h | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index d88f9f0..41dc31f 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -253,13 +253,13 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
*
* 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * <--------------- offset --------------------> <- type --> 0 0 0
+ * <--------------- offset ----------------------> < type -> 0 0 0
*
- * This gives us up to 63 swap files and 32GB per swap file. Note that
+ * This gives us up to 31 swap files and 64GB per swap file. Note that
* the offset field is always non-zero.
*/
#define __SWP_TYPE_SHIFT 3
-#define __SWP_TYPE_BITS 6
+#define __SWP_TYPE_BITS 5
#define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1)
#define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT)
--
1.7.4.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 1/2] ARM: mm: avoid setting nG bit for user mappings that aren't present
2012-07-26 16:01 ` [PATCH 1/2] ARM: mm: avoid setting nG bit for user mappings that aren't present Will Deacon
@ 2012-07-26 16:49 ` Catalin Marinas
0 siblings, 0 replies; 5+ messages in thread
From: Catalin Marinas @ 2012-07-26 16:49 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Jul 26, 2012 at 05:01:07PM +0100, Will Deacon wrote:
> Swap entries are encoding in ptes such that !pte_present(pte) and
> pte_file(pte). The remaining bits of the descriptor are used to identify
> the swapfile and offset within it to the swap entry.
>
> When writing such a pte for a user virtual address, set_pte_at
> unconditionally sets the nG bit, which (in the case of LPAE) will
> corrupt the swapfile offset and lead to a BUG:
>
> [ 140.494067] swap_free: Unused swap offset entry 000763b4
> [ 140.509989] BUG: Bad page map in process rs:main Q:Reg pte:0ec76800 pmd:8f92e003
>
> This patch fixes the problem by only setting the nG bit for user
> mappings that are actually present.
>
> Signed-off-by: Will Deacon <will.deacon@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/2] ARM: mm: use 5 bits for swapfile type encoding
2012-07-26 16:01 ` [PATCH 2/2] ARM: mm: use 5 bits for swapfile type encoding Will Deacon
@ 2012-07-26 16:49 ` Catalin Marinas
0 siblings, 0 replies; 5+ messages in thread
From: Catalin Marinas @ 2012-07-26 16:49 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Jul 26, 2012 at 05:01:08PM +0100, Will Deacon wrote:
> Page migration encodes the pfn in the offset field of a swp_entry_t.
> For LPAE, we support physical addresses of up to 36 bits (due to
> sparsemem limitations with the size of page flags), requiring 24 bits
> to represent a pfn. A further 3 bits are used to encode a swp_entry into
> a pte, leaving 5 bits for the type field. Furthermore, the core code
> defines MAX_SWAPFILES_SHIFT as 5, so the additional type bit does not
> get used.
>
> This patch reduces the width of the type field to 5 bits, allowing us
> to create up to 31 swapfiles of 64GB each.
>
> Signed-off-by: Will Deacon <will.deacon@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-07-26 16:49 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-26 16:01 [PATCH 0/2] Fix swap and page migration for LPAE Will Deacon
2012-07-26 16:01 ` [PATCH 1/2] ARM: mm: avoid setting nG bit for user mappings that aren't present Will Deacon
2012-07-26 16:49 ` Catalin Marinas
2012-07-26 16:01 ` [PATCH 2/2] ARM: mm: use 5 bits for swapfile type encoding Will Deacon
2012-07-26 16:49 ` Catalin Marinas
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).