All of lore.kernel.org
 help / color / mirror / Atom feed
From: k.khlebnikov@samsung.com (Konstantin Khlebnikov)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH RFC 3/3] ARM: reduce size of page table directory for short mode
Date: Tue, 18 Nov 2014 19:53:25 +0400	[thread overview]
Message-ID: <20141118165325.9958.84370.stgit@buzz> (raw)
In-Reply-To: <20141118165313.9958.1242.stgit@buzz>

Virtual memory above PAGE_OFFSET is covered by TTBR1 which always points
to swapper_pg_dir, thus size of the rest pgd tables might be reduced.
Of course idmap_pgd must be full 16k because it's used without split.
It seems nobody accesses pgd entries above PAGE_OFFSET via pgd_offset(),
all access is done via pgd_offset_k() which refers directly to init_mm.

This patch saves 8k per process for 2G/2G split (12k for 1G/3G split)
and kills source of frequent order-2 allocations. Unfortunately most
commonly used 3G/1G mode isn't supported, because first part must be
power of two. LPAE supports this mode, but it's pgd is already tiny.

Signed-off-by: Konstantin Khlebnikov <k.khlebnikov@samsung.com>
---
 arch/arm/mm/idmap.c |    6 ++++++
 arch/arm/mm/pgd.c   |   14 +++++++++-----
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c
index cc51b40..cea7ee1 100644
--- a/arch/arm/mm/idmap.c
+++ b/arch/arm/mm/idmap.c
@@ -100,7 +100,13 @@ extern char  __idmap_text_start[], __idmap_text_end[];
 
 static int __init init_static_idmap(void)
 {
+#ifdef CONFIG_ARM_LPAE
 	idmap_pgd = pgd_alloc(&init_mm);
+#else
+	idmap_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, 2);
+	if (idmap_pgd)
+		memcpy(idmap_pgd, swapper_pg_dir, PTRS_PER_PGD * sizeof(pgd_t));
+#endif
 	if (!idmap_pgd)
 		return -ENOMEM;
 
diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c
index 2493795..3fbcb5a 100644
--- a/arch/arm/mm/pgd.c
+++ b/arch/arm/mm/pgd.c
@@ -20,15 +20,19 @@
 #include "mm.h"
 
 #ifdef CONFIG_ARM_LPAE
+#define TTBR0_PTRS_PER_PGD	PTRS_PER_PGD
 #define __pgd_alloc()	kmalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL)
 #define __pgd_free(pgd)	kfree(pgd)
 #else
-#define __pgd_alloc()	(pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_REPEAT, 2)
-#define __pgd_free(pgd)	free_pages((unsigned long)pgd, 2)
+#define TTBR0_PTRS_PER_PGD	(PTRS_PER_PGD >> TTBR1_SIZE)
+#define __pgd_alloc()	(pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_REPEAT, \
+							2 - TTBR1_SIZE)
+#define __pgd_free(pgd)	free_pages((unsigned long)pgd, 2 - TTBR1_SIZE)
 #endif
 
 /*
- * need to get a 16k page for level 1
+ * We need 4k/8k/16k for pgd in short mode for CONFIG_VMSPLIT_1G/2G/3G
+ * or only 64 bytes if LPAE is enabled.
  */
 pgd_t *pgd_alloc(struct mm_struct *mm)
 {
@@ -48,9 +52,9 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
 	 */
 	init_pgd = pgd_offset_k(0);
 	memcpy(new_pgd + USER_PTRS_PER_PGD, init_pgd + USER_PTRS_PER_PGD,
-		       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+		(TTBR0_PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
 
-	clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
+	clean_dcache_area(new_pgd, TTBR0_PTRS_PER_PGD * sizeof(pgd_t));
 
 #ifdef CONFIG_ARM_LPAE
 	/*

WARNING: multiple messages have this Message-ID (diff)
From: Konstantin Khlebnikov <k.khlebnikov@samsung.com>
To: Russell King <linux@arm.linux.org.uk>,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
Subject: [PATCH RFC 3/3] ARM: reduce size of page table directory for short mode
Date: Tue, 18 Nov 2014 19:53:25 +0400	[thread overview]
Message-ID: <20141118165325.9958.84370.stgit@buzz> (raw)
In-Reply-To: <20141118165313.9958.1242.stgit@buzz>

Virtual memory above PAGE_OFFSET is covered by TTBR1 which always points
to swapper_pg_dir, thus size of the rest pgd tables might be reduced.
Of course idmap_pgd must be full 16k because it's used without split.
It seems nobody accesses pgd entries above PAGE_OFFSET via pgd_offset(),
all access is done via pgd_offset_k() which refers directly to init_mm.

This patch saves 8k per process for 2G/2G split (12k for 1G/3G split)
and kills source of frequent order-2 allocations. Unfortunately most
commonly used 3G/1G mode isn't supported, because first part must be
power of two. LPAE supports this mode, but it's pgd is already tiny.

Signed-off-by: Konstantin Khlebnikov <k.khlebnikov@samsung.com>
---
 arch/arm/mm/idmap.c |    6 ++++++
 arch/arm/mm/pgd.c   |   14 +++++++++-----
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c
index cc51b40..cea7ee1 100644
--- a/arch/arm/mm/idmap.c
+++ b/arch/arm/mm/idmap.c
@@ -100,7 +100,13 @@ extern char  __idmap_text_start[], __idmap_text_end[];
 
 static int __init init_static_idmap(void)
 {
+#ifdef CONFIG_ARM_LPAE
 	idmap_pgd = pgd_alloc(&init_mm);
+#else
+	idmap_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, 2);
+	if (idmap_pgd)
+		memcpy(idmap_pgd, swapper_pg_dir, PTRS_PER_PGD * sizeof(pgd_t));
+#endif
 	if (!idmap_pgd)
 		return -ENOMEM;
 
diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c
index 2493795..3fbcb5a 100644
--- a/arch/arm/mm/pgd.c
+++ b/arch/arm/mm/pgd.c
@@ -20,15 +20,19 @@
 #include "mm.h"
 
 #ifdef CONFIG_ARM_LPAE
+#define TTBR0_PTRS_PER_PGD	PTRS_PER_PGD
 #define __pgd_alloc()	kmalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL)
 #define __pgd_free(pgd)	kfree(pgd)
 #else
-#define __pgd_alloc()	(pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_REPEAT, 2)
-#define __pgd_free(pgd)	free_pages((unsigned long)pgd, 2)
+#define TTBR0_PTRS_PER_PGD	(PTRS_PER_PGD >> TTBR1_SIZE)
+#define __pgd_alloc()	(pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_REPEAT, \
+							2 - TTBR1_SIZE)
+#define __pgd_free(pgd)	free_pages((unsigned long)pgd, 2 - TTBR1_SIZE)
 #endif
 
 /*
- * need to get a 16k page for level 1
+ * We need 4k/8k/16k for pgd in short mode for CONFIG_VMSPLIT_1G/2G/3G
+ * or only 64 bytes if LPAE is enabled.
  */
 pgd_t *pgd_alloc(struct mm_struct *mm)
 {
@@ -48,9 +52,9 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
 	 */
 	init_pgd = pgd_offset_k(0);
 	memcpy(new_pgd + USER_PTRS_PER_PGD, init_pgd + USER_PTRS_PER_PGD,
-		       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+		(TTBR0_PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
 
-	clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
+	clean_dcache_area(new_pgd, TTBR0_PTRS_PER_PGD * sizeof(pgd_t));
 
 #ifdef CONFIG_ARM_LPAE
 	/*


  parent reply	other threads:[~2014-11-18 15:53 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-18 15:53 [PATCH RFC 1/3] ARM: LPAE: rework TTBR0/TTBR1 split Konstantin Khlebnikov
2014-11-18 15:53 ` Konstantin Khlebnikov
2014-11-18 15:53 ` [PATCH RFC 2/3] ARM: enable TTBR0/TTBR1 split in short mode Konstantin Khlebnikov
2014-11-18 15:53   ` Konstantin Khlebnikov
2014-11-18 18:04   ` Catalin Marinas
2014-11-18 18:04     ` Catalin Marinas
2014-11-18 15:53 ` Konstantin Khlebnikov [this message]
2014-11-18 15:53   ` [PATCH RFC 3/3] ARM: reduce size of page table directory for " Konstantin Khlebnikov
2014-11-18 18:14   ` Catalin Marinas
2014-11-18 18:14     ` Catalin Marinas
2014-11-18 19:11     ` Russell King - ARM Linux
2014-11-18 19:11       ` Russell King - ARM Linux
2014-11-18 23:02       ` Catalin Marinas
2014-11-18 23:02         ` Catalin Marinas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20141118165325.9958.84370.stgit@buzz \
    --to=k.khlebnikov@samsung.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.