mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000
@ 2023-05-22  5:28 Ahmad Fatoum
  2023-05-22  5:28 ` [PATCH 01/11] treewide: use remap_range instead of arch_remap_range Ahmad Fatoum
                   ` (11 more replies)
  0 siblings, 12 replies; 16+ messages in thread
From: Ahmad Fatoum @ 2023-05-22  5:28 UTC (permalink / raw)
  To: barebox; +Cc: lst, rcz

When MMU is enabled, barebox maintains a single address space with
1:1 physical to virtual mapping by default. Furthermore, the zero
page is marked inaccessible to trap NULL pointer dereferences.

This is problematic on the Qemu ARM Virt platform, because the
cfi-flash is memory mapped starting with address zero, so users need
to decide whether they want the cfi-flash or the MMU. The decision
so far, was to disable CONFIG_MMU in the Qemu Virt configs, but this
holds us back from removing these configs in favor of the new
multi_v7_defconfig/multi_v8_defconfig.

Make everyone happy by shifting the virtual cfi-flash mapping by 4K:

    virt   ->    phys

    0x0000 ->    0x0000 [faulting]
    0x1000 ->    0x0000 [(uncached) alias]
    0x2000 ->    0x1000
           .
           .
           .
 0x7fff000 -> 0x7ffe000
 0x8000000 -> 0x7fff000

This eats one page into the memory region starting at 0x8000000.
That's ok though, because that's where the GIC is located on both
ARM32 and ARM64 and we don't do interrupts in barebox.

This applies on top of Sascha's MMU rempping rework in next and
has been tested on both 32-bit and 64-bit QEMU ARM.

Ahmad Fatoum (11):
  treewide: use remap_range instead of arch_remap_range
  mmu: add physical address parameter to arch_remap_range
  ARM: mmu32: support non-1:1 mappings in arch_remap_range
  ARM: mmu64: support non-1:1 mappings in arch_remap_range
  of: platform: remap memory when encountering virtual-reg property
  common: boards: qemu-virt: remap cfi-flash from 0 to 0x1000
  ARM: prepare extending mmuinfo beyond ARMv7
  ARM64: mmu: implement ARMv8 mmuinfo command
  common: memtest: prepare for reuse in self test
  test: self: add MMU remapping self test
  ARM: mmuinfo: add options for enabling/disabling zero page trapping

 .../bindings/barebox/virtual-reg.rst          |  29 +++
 arch/arm/configs/multi_v8_defconfig           |   1 +
 arch/arm/cpu/Makefile                         |   2 +-
 arch/arm/cpu/mmu-common.c                     |   8 +-
 arch/arm/cpu/mmu_32.c                         |  54 ++--
 arch/arm/cpu/mmu_64.c                         |  18 +-
 arch/arm/cpu/mmuinfo.c                        | 128 +++++-----
 arch/arm/cpu/mmuinfo_32.c                     |  80 ++++++
 arch/arm/cpu/mmuinfo_64.c                     | 215 ++++++++++++++++
 arch/arm/include/asm/mmu.h                    |   2 +-
 arch/arm/include/asm/mmuinfo.h                |   9 +
 arch/arm/include/asm/sysreg.h                 |  76 ++++++
 arch/powerpc/cpu-85xx/mmu.c                   |   7 +-
 arch/powerpc/include/asm/mmu.h                |   2 +-
 commands/Kconfig                              |   8 +-
 commands/memtest.c                            |   5 +-
 common/Kconfig                                |   6 +
 common/Makefile                               |   2 +-
 common/boards/qemu-virt/Makefile              |   3 +
 common/boards/qemu-virt/overlay-of-flash.dts  |   5 +-
 common/memtest.c                              |  44 ++--
 drivers/hab/habv4.c                           |   2 +-
 drivers/mtd/nor/cfi_flash.c                   |   5 +-
 drivers/of/platform.c                         |  20 ++
 include/memtest.h                             |   7 +-
 include/mmu.h                                 |  19 +-
 include/zero_page.h                           |  12 +
 test/self/Kconfig                             |   6 +
 test/self/Makefile                            |   1 +
 test/self/mmu.c                               | 233 ++++++++++++++++++
 30 files changed, 865 insertions(+), 144 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/barebox/virtual-reg.rst
 create mode 100644 arch/arm/cpu/mmuinfo_32.c
 create mode 100644 arch/arm/cpu/mmuinfo_64.c
 create mode 100644 arch/arm/include/asm/mmuinfo.h
 create mode 100644 arch/arm/include/asm/sysreg.h
 create mode 100644 test/self/mmu.c

-- 
2.39.2




^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 01/11] treewide: use remap_range instead of arch_remap_range
  2023-05-22  5:28 [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000 Ahmad Fatoum
@ 2023-05-22  5:28 ` Ahmad Fatoum
  2023-05-22  5:28 ` [PATCH 02/11] mmu: add physical address parameter to arch_remap_range Ahmad Fatoum
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Ahmad Fatoum @ 2023-05-22  5:28 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum, lst, rcz

The remapping in arch_remap_range is currently limited to attributes. In
a later commit, we'll start supporting non-1:1 remappings. We'll keep
remap_range as is for 1:1, so as preparation, let's switch all
arch_remap_range users that want 1:1 remappings to remap_range.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/cpu/mmu-common.c |  8 ++++----
 arch/arm/cpu/mmu_32.c     | 10 +++++-----
 arch/arm/cpu/mmu_64.c     | 10 +++++-----
 drivers/hab/habv4.c       |  2 +-
 4 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/arch/arm/cpu/mmu-common.c b/arch/arm/cpu/mmu-common.c
index 02f512c2c6bd..5208db21ec90 100644
--- a/arch/arm/cpu/mmu-common.c
+++ b/arch/arm/cpu/mmu-common.c
@@ -36,7 +36,7 @@ void *dma_alloc_map(size_t size, dma_addr_t *dma_handle, unsigned flags)
 	memset(ret, 0, size);
 	dma_flush_range(ret, size);
 
-	arch_remap_range(ret, size, flags);
+	remap_range(ret, size, flags);
 
 	return ret;
 }
@@ -53,19 +53,19 @@ void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle)
 void dma_free_coherent(void *mem, dma_addr_t dma_handle, size_t size)
 {
 	size = PAGE_ALIGN(size);
-	arch_remap_range(mem, size, MAP_CACHED);
+	remap_range(mem, size, MAP_CACHED);
 
 	free(mem);
 }
 
 void zero_page_access(void)
 {
-	arch_remap_range(0x0, PAGE_SIZE, MAP_CACHED);
+	remap_range(0x0, PAGE_SIZE, MAP_CACHED);
 }
 
 void zero_page_faulting(void)
 {
-	arch_remap_range(0x0, PAGE_SIZE, MAP_FAULT);
+	remap_range(0x0, PAGE_SIZE, MAP_FAULT);
 }
 
 static int mmu_init(void)
diff --git a/arch/arm/cpu/mmu_32.c b/arch/arm/cpu/mmu_32.c
index 852c5626dedd..e4607d99fd2a 100644
--- a/arch/arm/cpu/mmu_32.c
+++ b/arch/arm/cpu/mmu_32.c
@@ -534,11 +534,11 @@ void __mmu_init(bool mmu_on)
 		pos = bank->start;
 
 		for_each_reserved_region(bank, rsv) {
-			arch_remap_range((void *)pos, rsv->start - pos, MAP_CACHED);
+			remap_range((void *)pos, rsv->start - pos, MAP_CACHED);
 			pos = rsv->end + 1;
 		}
 
-		arch_remap_range((void *)pos, bank->start + bank->size - pos, MAP_CACHED);
+		remap_range((void *)pos, bank->start + bank->size - pos, MAP_CACHED);
 	}
 }
 
@@ -581,9 +581,9 @@ void mmu_early_enable(unsigned long membase, unsigned long memsize)
 	create_flat_mapping();
 
 	/* maps main memory as cachable */
-	arch_remap_range((void *)membase, memsize - OPTEE_SIZE, MAP_CACHED);
-	arch_remap_range((void *)membase + memsize - OPTEE_SIZE, OPTEE_SIZE, MAP_UNCACHED);
-	arch_remap_range((void *)PAGE_ALIGN_DOWN((uintptr_t)_stext), PAGE_ALIGN(_etext - _stext), MAP_CACHED);
+	remap_range((void *)membase, memsize - OPTEE_SIZE, MAP_CACHED);
+	remap_range((void *)membase + memsize - OPTEE_SIZE, OPTEE_SIZE, MAP_UNCACHED);
+	remap_range((void *)PAGE_ALIGN_DOWN((uintptr_t)_stext), PAGE_ALIGN(_etext - _stext), MAP_CACHED);
 
 	__mmu_cache_on();
 }
diff --git a/arch/arm/cpu/mmu_64.c b/arch/arm/cpu/mmu_64.c
index 3f9b52bbdb7b..478222cd991f 100644
--- a/arch/arm/cpu/mmu_64.c
+++ b/arch/arm/cpu/mmu_64.c
@@ -203,11 +203,11 @@ void __mmu_init(bool mmu_on)
 		pos = bank->start;
 
 		for_each_reserved_region(bank, rsv) {
-			arch_remap_range((void *)pos, rsv->start - pos, MAP_CACHED);
+			remap_range((void *)pos, rsv->start - pos, MAP_CACHED);
 			pos = rsv->end + 1;
 		}
 
-		arch_remap_range((void *)pos, bank->start + bank->size - pos, MAP_CACHED);
+		remap_range((void *)pos, bank->start + bank->size - pos, MAP_CACHED);
 	}
 
 	/* Make zero page faulting to catch NULL pointer derefs */
@@ -257,9 +257,9 @@ void mmu_early_enable(unsigned long membase, unsigned long memsize)
 
 	memset((void *)ttb, 0, GRANULE_SIZE);
 
-	arch_remap_range(0, 1UL << (BITS_PER_VA - 1), MAP_UNCACHED);
-	arch_remap_range((void *)membase, memsize - OPTEE_SIZE, MAP_CACHED);
-	arch_remap_range((void *)membase + memsize - OPTEE_SIZE, OPTEE_SIZE, MAP_FAULT);
+	remap_range(0, 1UL << (BITS_PER_VA - 1), MAP_UNCACHED);
+	remap_range((void *)membase, memsize - OPTEE_SIZE, MAP_CACHED);
+	remap_range((void *)membase + memsize - OPTEE_SIZE, OPTEE_SIZE, MAP_FAULT);
 
 	mmu_enable();
 }
diff --git a/drivers/hab/habv4.c b/drivers/hab/habv4.c
index d2494db11486..a8745e8339e5 100644
--- a/drivers/hab/habv4.c
+++ b/drivers/hab/habv4.c
@@ -616,7 +616,7 @@ static int init_imx6_hab_get_status(void)
 		/* can happen in multi-image builds and is not an error */
 		return 0;
 
-	arch_remap_range(0x0, SZ_1M, MAP_CACHED);
+	remap_range(0x0, SZ_1M, MAP_CACHED);
 
 	/*
 	 * Nobody will check the return value if there were HAB errors, but the
-- 
2.39.2




^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 02/11] mmu: add physical address parameter to arch_remap_range
  2023-05-22  5:28 [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000 Ahmad Fatoum
  2023-05-22  5:28 ` [PATCH 01/11] treewide: use remap_range instead of arch_remap_range Ahmad Fatoum
@ 2023-05-22  5:28 ` Ahmad Fatoum
  2023-05-23  7:17   ` Sascha Hauer
  2023-05-22  5:28 ` [PATCH 03/11] ARM: mmu32: support non-1:1 mappings in arch_remap_range Ahmad Fatoum
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 16+ messages in thread
From: Ahmad Fatoum @ 2023-05-22  5:28 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum, lst, rcz

ARM32 has map_io_sections for non-1:1 remapping, but it's limited to 1M
sections.  arch_remap_range has newly gained support for 4K granularity
remapping, but supports only changing attributes and no non-1:1
remapping yet. In preparation for adding this missing feature, adjust
the prototype.

No functional change.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/cpu/mmu_32.c          | 25 ++++++++++++++-----------
 arch/arm/cpu/mmu_64.c          |  8 +++++---
 arch/arm/include/asm/mmu.h     |  2 +-
 arch/powerpc/cpu-85xx/mmu.c    |  7 +++++--
 arch/powerpc/include/asm/mmu.h |  2 +-
 include/mmu.h                  |  9 ++++++---
 6 files changed, 32 insertions(+), 21 deletions(-)

diff --git a/arch/arm/cpu/mmu_32.c b/arch/arm/cpu/mmu_32.c
index e4607d99fd2a..68336fc68be0 100644
--- a/arch/arm/cpu/mmu_32.c
+++ b/arch/arm/cpu/mmu_32.c
@@ -253,20 +253,23 @@ static uint32_t get_pmd_flags(int map_type)
 	return pte_flags_to_pmd(get_pte_flags(map_type));
 }
 
-int arch_remap_range(void *start, size_t size, unsigned map_type)
+int arch_remap_range(void *_virt_addr, phys_addr_t phys_addr, size_t size, unsigned map_type)
 {
-	u32 addr = (u32)start;
+	u32 virt_addr = (u32)_virt_addr;
 	u32 pte_flags, pmd_flags;
 	uint32_t *ttb = get_ttb();
 
-	BUG_ON(!IS_ALIGNED(addr, PAGE_SIZE));
+	if (phys_addr != virt_to_phys(virt_addr))
+		return -ENOSYS;
+
+	BUG_ON(!IS_ALIGNED(virt_addr, PAGE_SIZE));
 
 	pte_flags = get_pte_flags(map_type);
 	pmd_flags = pte_flags_to_pmd(pte_flags);
 
 	while (size) {
-		const bool pgdir_size_aligned = IS_ALIGNED(addr, PGDIR_SIZE);
-		u32 *pgd = (u32 *)&ttb[pgd_index(addr)];
+		const bool pgdir_size_aligned = IS_ALIGNED(virt_addr, PGDIR_SIZE);
+		u32 *pgd = (u32 *)&ttb[pgd_index(virt_addr)];
 		size_t chunk;
 
 		if (size >= PGDIR_SIZE && pgdir_size_aligned &&
@@ -276,7 +279,7 @@ int arch_remap_range(void *start, size_t size, unsigned map_type)
 			 * replace it with a section
 			 */
 			chunk = PGDIR_SIZE;
-			*pgd = addr | pmd_flags | PMD_TYPE_SECT;
+			*pgd = virt_addr | pmd_flags | PMD_TYPE_SECT;
 			dma_flush_range(pgd, sizeof(*pgd));
 		} else {
 			unsigned int num_ptes;
@@ -291,7 +294,7 @@ int arch_remap_range(void *start, size_t size, unsigned map_type)
 			 * was not aligned on PGDIR_SIZE boundary)
 			 */
 			chunk = pgdir_size_aligned ?
-				PGDIR_SIZE : ALIGN(addr, PGDIR_SIZE) - addr;
+				PGDIR_SIZE : ALIGN(virt_addr, PGDIR_SIZE) - virt_addr;
 			/*
 			 * At the same time we want to make sure that
 			 * we don't go on remapping past requested
@@ -301,15 +304,15 @@ int arch_remap_range(void *start, size_t size, unsigned map_type)
 			chunk = min(chunk, size);
 			num_ptes = chunk / PAGE_SIZE;
 
-			pte = find_pte(addr);
+			pte = find_pte(virt_addr);
 			if (!pte) {
 				/*
 				 * If PTE is not found it means that
 				 * we needs to split this section and
 				 * create a new page table for it
 				 */
-				table = arm_create_pte(addr, pmd_flags_to_pte(*pgd));
-				pte = find_pte(addr);
+				table = arm_create_pte(virt_addr, pmd_flags_to_pte(*pgd));
+				pte = find_pte(virt_addr);
 				BUG_ON(!pte);
 			}
 
@@ -321,7 +324,7 @@ int arch_remap_range(void *start, size_t size, unsigned map_type)
 			dma_flush_range(pte, num_ptes * sizeof(u32));
 		}
 
-		addr += chunk;
+		virt_addr += chunk;
 		size -= chunk;
 	}
 
diff --git a/arch/arm/cpu/mmu_64.c b/arch/arm/cpu/mmu_64.c
index 478222cd991f..7228b5d3fd12 100644
--- a/arch/arm/cpu/mmu_64.c
+++ b/arch/arm/cpu/mmu_64.c
@@ -158,10 +158,13 @@ static void create_sections(uint64_t virt, uint64_t phys, uint64_t size,
 	tlb_invalidate();
 }
 
-int arch_remap_range(void *_start, size_t size, unsigned flags)
+int arch_remap_range(void *virt_addr, phys_addr_t phys_addr, size_t size, unsigned flags)
 {
 	unsigned long attrs;
 
+	if (phys_addr != virt_to_phys(virt_addr))
+		return -ENOSYS;
+
 	switch (flags) {
 	case MAP_CACHED:
 		attrs = CACHED_MEM;
@@ -176,8 +179,7 @@ int arch_remap_range(void *_start, size_t size, unsigned flags)
 		return -EINVAL;
 	}
 
-	create_sections((uint64_t)_start, (uint64_t)_start, (uint64_t)size,
-			attrs);
+	create_sections((uint64_t)virt_addr, (uint64_t)virt_addr, (uint64_t)size, attrs);
 	return 0;
 }
 
diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h
index 9d2fdcf3657b..f819f582d5bd 100644
--- a/arch/arm/include/asm/mmu.h
+++ b/arch/arm/include/asm/mmu.h
@@ -23,7 +23,7 @@ static inline void setup_dma_coherent(unsigned long offset)
 #ifdef CONFIG_MMU
 #define ARCH_HAS_REMAP
 #define MAP_ARCH_DEFAULT MAP_CACHED
-int arch_remap_range(void *_start, size_t size, unsigned flags);
+int arch_remap_range(void *virt_addr, phys_addr_t phys_addr, size_t size, unsigned flags);
 void *map_io_sections(unsigned long physaddr, void *start, size_t size);
 #else
 #define MAP_ARCH_DEFAULT MAP_UNCACHED
diff --git a/arch/powerpc/cpu-85xx/mmu.c b/arch/powerpc/cpu-85xx/mmu.c
index 6b93c3e8db9a..b484acbf8043 100644
--- a/arch/powerpc/cpu-85xx/mmu.c
+++ b/arch/powerpc/cpu-85xx/mmu.c
@@ -17,13 +17,16 @@
 #include <mmu.h>
 #include <mach/mmu.h>
 
-int arch_remap_range(void *_start, size_t size, unsigned flags)
+int arch_remap_range(void *virt_addr, phys_addr_t phys_addr, size_t size, unsigned flags)
 {
 	uint32_t ptr, start, tsize, valid, wimge, pte_flags;
 	unsigned long epn;
 	phys_addr_t rpn = 0;
 	int esel = 0;
 
+	if (phys_addr != virt_to_phys(virt_addr))
+		return -ENOSYS;
+
 	switch (flags) {
 	case MAP_UNCACHED:
 		pte_flags = MAS2_I;
@@ -35,7 +38,7 @@ int arch_remap_range(void *_start, size_t size, unsigned flags)
 		return -EINVAL;
 	}
 
-	ptr = start = (uint32_t)_start;
+	ptr = start = (uint32_t)virt_addr;
 	wimge = pte_flags | MAS2_M;
 
 	while (ptr < (start + size)) {
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
index 81a5d7d55f93..10b15a47b9aa 100644
--- a/arch/powerpc/include/asm/mmu.h
+++ b/arch/powerpc/include/asm/mmu.h
@@ -563,7 +563,7 @@ extern int write_bat(ppc_bat_t bat, unsigned long upper, unsigned long lower);
 
 #ifdef CONFIG_MMU
 #define ARCH_HAS_REMAP
-int arch_remap_range(void *_start, size_t size, unsigned flags);
+int arch_remap_range(void *virt_addr, phys_addr_t phys_addr, size_t size, unsigned flags);
 #endif
 
 #endif
diff --git a/include/mmu.h b/include/mmu.h
index 2326cb215afb..fd6dbc51ac03 100644
--- a/include/mmu.h
+++ b/include/mmu.h
@@ -2,6 +2,8 @@
 #ifndef __MMU_H
 #define __MMU_H
 
+#include <linux/types.h>
+
 #define MAP_UNCACHED	0
 #define MAP_CACHED	1
 #define MAP_FAULT	2
@@ -16,9 +18,10 @@
 #include <asm/mmu.h>
 
 #ifndef ARCH_HAS_REMAP
-static inline int arch_remap_range(void *start, size_t size, unsigned flags)
+static inline int arch_remap_range(void *virt_addr, phys_addr_t phys_addr,
+				   size_t size, unsigned flags)
 {
-	if (flags == MAP_ARCH_DEFAULT)
+	if (flags == MAP_ARCH_DEFAULT && phys_addr == virt_to_phys(virt_addr))
 		return 0;
 
 	return -EINVAL;
@@ -37,7 +40,7 @@ static inline bool arch_can_remap(void)
 
 static inline int remap_range(void *start, size_t size, unsigned flags)
 {
-	return arch_remap_range(start, size, flags);
+	return arch_remap_range(start, virt_to_phys(start), size, flags);
 }
 
 #endif
-- 
2.39.2




^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 03/11] ARM: mmu32: support non-1:1 mappings in arch_remap_range
  2023-05-22  5:28 [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000 Ahmad Fatoum
  2023-05-22  5:28 ` [PATCH 01/11] treewide: use remap_range instead of arch_remap_range Ahmad Fatoum
  2023-05-22  5:28 ` [PATCH 02/11] mmu: add physical address parameter to arch_remap_range Ahmad Fatoum
@ 2023-05-22  5:28 ` Ahmad Fatoum
  2023-05-22  5:28 ` [PATCH 04/11] ARM: mmu64: " Ahmad Fatoum
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Ahmad Fatoum @ 2023-05-22  5:28 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum, lst, rcz

This makes the function usable as alternative to map_io_sections, but at
4K granularity.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/cpu/mmu_32.c | 29 +++++++++++++----------------
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/arch/arm/cpu/mmu_32.c b/arch/arm/cpu/mmu_32.c
index 68336fc68be0..4168125274f4 100644
--- a/arch/arm/cpu/mmu_32.c
+++ b/arch/arm/cpu/mmu_32.c
@@ -63,13 +63,6 @@ static inline void tlb_invalidate(void)
 			 PMD_SECT_BUFFERABLE | PMD_SECT_XN)
 #define PGD_FLAGS_UNCACHED_V7 (PMD_SECT_DEF_UNCACHED | PMD_SECT_XN)
 
-/*
- * PTE flags to set cached and uncached areas.
- * This will be determined at runtime.
- */
-
-#define PTE_MASK ((1 << 12) - 1)
-
 static bool pgd_type_table(u32 pgd)
 {
 	return (pgd & PMD_TYPE_MASK) == PMD_TYPE_TABLE;
@@ -140,21 +133,24 @@ void dma_inv_range(void *ptr, size_t size)
  * We initially create a flat uncached mapping on it.
  * Not yet exported, but may be later if someone finds use for it.
  */
-static u32 *arm_create_pte(unsigned long virt, uint32_t flags)
+static u32 *arm_create_pte(unsigned long virt, unsigned long phys,
+			   uint32_t flags)
 {
 	uint32_t *ttb = get_ttb();
 	u32 *table;
 	int i, ttb_idx;
 
 	virt = ALIGN_DOWN(virt, PGDIR_SIZE);
+	phys = ALIGN_DOWN(phys, PGDIR_SIZE);
 
 	table = alloc_pte();
 
 	ttb_idx = pgd_index(virt);
 
 	for (i = 0; i < PTRS_PER_PTE; i++) {
-		table[i] = virt | PTE_TYPE_SMALL | flags;
+		table[i] = phys | PTE_TYPE_SMALL | flags;
 		virt += PAGE_SIZE;
+		phys += PAGE_SIZE;
 	}
 	dma_flush_range(table, PTRS_PER_PTE * sizeof(u32));
 
@@ -259,10 +255,8 @@ int arch_remap_range(void *_virt_addr, phys_addr_t phys_addr, size_t size, unsig
 	u32 pte_flags, pmd_flags;
 	uint32_t *ttb = get_ttb();
 
-	if (phys_addr != virt_to_phys(virt_addr))
-		return -ENOSYS;
-
 	BUG_ON(!IS_ALIGNED(virt_addr, PAGE_SIZE));
+	BUG_ON(!IS_ALIGNED(phys_addr, PAGE_SIZE));
 
 	pte_flags = get_pte_flags(map_type);
 	pmd_flags = pte_flags_to_pmd(pte_flags);
@@ -273,13 +267,14 @@ int arch_remap_range(void *_virt_addr, phys_addr_t phys_addr, size_t size, unsig
 		size_t chunk;
 
 		if (size >= PGDIR_SIZE && pgdir_size_aligned &&
+		    IS_ALIGNED(phys_addr, PGDIR_SIZE) &&
 		    !pgd_type_table(*pgd)) {
 			/*
 			 * TODO: Add code to discard a page table and
 			 * replace it with a section
 			 */
 			chunk = PGDIR_SIZE;
-			*pgd = virt_addr | pmd_flags | PMD_TYPE_SECT;
+			*pgd = phys_addr | pmd_flags | PMD_TYPE_SECT;
 			dma_flush_range(pgd, sizeof(*pgd));
 		} else {
 			unsigned int num_ptes;
@@ -311,13 +306,14 @@ int arch_remap_range(void *_virt_addr, phys_addr_t phys_addr, size_t size, unsig
 				 * we needs to split this section and
 				 * create a new page table for it
 				 */
-				table = arm_create_pte(virt_addr, pmd_flags_to_pte(*pgd));
+				table = arm_create_pte(virt_addr, phys_addr,
+						       pmd_flags_to_pte(*pgd));
 				pte = find_pte(virt_addr);
 				BUG_ON(!pte);
 			}
 
 			for (i = 0; i < num_ptes; i++) {
-				pte[i] &= ~PTE_MASK;
+				pte[i] = phys_addr + i * PAGE_SIZE;
 				pte[i] |= pte_flags | PTE_TYPE_SMALL;
 			}
 
@@ -325,6 +321,7 @@ int arch_remap_range(void *_virt_addr, phys_addr_t phys_addr, size_t size, unsig
 		}
 
 		virt_addr += chunk;
+		phys_addr += chunk;
 		size -= chunk;
 	}
 
@@ -399,7 +396,7 @@ static void create_vector_table(unsigned long adr)
 		vectors = xmemalign(PAGE_SIZE, PAGE_SIZE);
 		pr_debug("Creating vector table, virt = 0x%p, phys = 0x%08lx\n",
 			 vectors, adr);
-		arm_create_pte(adr, get_pte_flags(MAP_UNCACHED));
+		arm_create_pte(adr, adr, get_pte_flags(MAP_UNCACHED));
 		pte = find_pte(adr);
 		*pte = (u32)vectors | PTE_TYPE_SMALL | get_pte_flags(MAP_CACHED);
 	}
-- 
2.39.2




^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 04/11] ARM: mmu64: support non-1:1 mappings in arch_remap_range
  2023-05-22  5:28 [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000 Ahmad Fatoum
                   ` (2 preceding siblings ...)
  2023-05-22  5:28 ` [PATCH 03/11] ARM: mmu32: support non-1:1 mappings in arch_remap_range Ahmad Fatoum
@ 2023-05-22  5:28 ` Ahmad Fatoum
  2023-05-22  5:28 ` [PATCH 05/11] of: platform: remap memory when encountering virtual-reg property Ahmad Fatoum
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Ahmad Fatoum @ 2023-05-22  5:28 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum, lst, rcz

This provides an alternative to ARM32's map_io_sections with the added
benefit of supporting 4K granularity.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/cpu/mmu_64.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/arch/arm/cpu/mmu_64.c b/arch/arm/cpu/mmu_64.c
index 7228b5d3fd12..5afb2b56d551 100644
--- a/arch/arm/cpu/mmu_64.c
+++ b/arch/arm/cpu/mmu_64.c
@@ -138,7 +138,8 @@ static void create_sections(uint64_t virt, uint64_t phys, uint64_t size,
 
 			pte = table + idx;
 
-			if (size >= block_size && IS_ALIGNED(addr, block_size)) {
+			if (size >= block_size && IS_ALIGNED(addr, block_size) &&
+			    IS_ALIGNED(phys, block_size)) {
 				type = (level == 3) ?
 					PTE_TYPE_PAGE : PTE_TYPE_BLOCK;
 				*pte = phys | attr | type;
@@ -162,9 +163,6 @@ int arch_remap_range(void *virt_addr, phys_addr_t phys_addr, size_t size, unsign
 {
 	unsigned long attrs;
 
-	if (phys_addr != virt_to_phys(virt_addr))
-		return -ENOSYS;
-
 	switch (flags) {
 	case MAP_CACHED:
 		attrs = CACHED_MEM;
@@ -179,7 +177,7 @@ int arch_remap_range(void *virt_addr, phys_addr_t phys_addr, size_t size, unsign
 		return -EINVAL;
 	}
 
-	create_sections((uint64_t)virt_addr, (uint64_t)virt_addr, (uint64_t)size, attrs);
+	create_sections((uint64_t)virt_addr, phys_addr, (uint64_t)size, attrs);
 	return 0;
 }
 
-- 
2.39.2




^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 05/11] of: platform: remap memory when encountering virtual-reg property
  2023-05-22  5:28 [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000 Ahmad Fatoum
                   ` (3 preceding siblings ...)
  2023-05-22  5:28 ` [PATCH 04/11] ARM: mmu64: " Ahmad Fatoum
@ 2023-05-22  5:28 ` Ahmad Fatoum
  2023-05-22  5:28 ` [PATCH 06/11] common: boards: qemu-virt: remap cfi-flash from 0 to 0x1000 Ahmad Fatoum
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Ahmad Fatoum @ 2023-05-22  5:28 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum, lst, rcz

Quoting the Device Tree specification v0.4-rc1[1]:

  The virtual-reg property specifies an effective address that maps to the
  first physical address specified in the reg property of the device node.
  This property enables boot programs to provide client programs with virtual-
  to-physical mappings that have been set up.

The only upstream use of this device tree property are some PowerPC
device trees that use it to find the virtual address of the early UART.

Let's start handling this property in barebox as well by remapping the
device to start at virtual-reg.

[1]: https://github.com/devicetree-org/devicetree-specification/releases/tag/v0.4-rc1

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 .../bindings/barebox/virtual-reg.rst          | 29 +++++++++++++++++++
 drivers/mtd/nor/cfi_flash.c                   |  5 +++-
 drivers/of/platform.c                         | 20 +++++++++++++
 3 files changed, 53 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/barebox/virtual-reg.rst

diff --git a/Documentation/devicetree/bindings/barebox/virtual-reg.rst b/Documentation/devicetree/bindings/barebox/virtual-reg.rst
new file mode 100644
index 000000000000..7d576d0cef6f
--- /dev/null
+++ b/Documentation/devicetree/bindings/barebox/virtual-reg.rst
@@ -0,0 +1,29 @@
+virtual-reg property
+====================
+
+The ``virtual-reg`` property provides a hint on the 32-bit virtual
+address mapping the first physical base address in the ``reg`` property.
+This is meant to allow the OS to use the boot firmware's virtual memory
+mapping to access device resources early in the kernel boot process.
+
+When barebox is compiled with ``CONFIG_MMU`` support and the
+implementation supports remapping, devices with ``virtual_reg`` will have
+all their resources remapped at the physical/virtual address offset calculated
+by subtracting ``virtual-reg`` from the first address in ``reg``.
+
+This is normally used to map I/O memory away from the zero page, so it
+can be used again to trap null pointer dereferences, while allowing
+full access to the device memory::
+
+.. code-block:: none
+
+   &{/soc} {
+   	#address-cells = <1>;
+   	#size-cells = <1>;
+
+        flash@0 {
+             reg = <0 0x10000>;
+             virtual-reg = <0x1000>;
+	     /* => memory region remapped from [0x1000, 0x11000] to [0x0000, 0x10000] */
+        };
+  };
diff --git a/drivers/mtd/nor/cfi_flash.c b/drivers/mtd/nor/cfi_flash.c
index b7499c93aee4..10542c710118 100644
--- a/drivers/mtd/nor/cfi_flash.c
+++ b/drivers/mtd/nor/cfi_flash.c
@@ -973,7 +973,10 @@ static int cfi_probe_one(struct flash_info *info, int num)
 		return PTR_ERR(iores);
 	info->base = IOMEM(iores->start);
 
-	/* TODO: either remap memory region or disable NULL pointer page */
+	/*
+	 * Platforms hitting this should remap memory region, e.g. via virtual-reg
+	 * device tree property or disable MMU.
+	 */
 	if (IS_ENABLED(CONFIG_MMU) && iores->start == 0)
 		return -EPERM;
 
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 23b8fa79348b..ab737629325a 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -12,6 +12,7 @@
 #include <of.h>
 #include <of_address.h>
 #include <linux/amba/bus.h>
+#include <mmu.h>
 
 /**
  * of_find_device_by_node - Find the platform_device associated with a node
@@ -145,6 +146,7 @@ struct device *of_platform_device_create(struct device_node *np,
 	struct resource *res = NULL, temp_res;
 	resource_size_t resinval;
 	int i, ret, num_reg = 0;
+	u32 virt;
 
 	if (!of_device_is_available(np))
 		return NULL;
@@ -186,6 +188,24 @@ struct device *of_platform_device_create(struct device_node *np,
 
 	of_dma_configure(dev, np);
 
+	if (num_reg && !of_property_read_u32(np, "virtual-reg", &virt)) {
+		resource_size_t remap_offset = virt - res[0].start;
+
+		for (i = 0; i < num_reg; i++) {
+			void *new_virt = (void *)res[i].start + remap_offset;
+			resource_size_t size = resource_size(&res[i]);
+
+			ret = arch_remap_range(new_virt, res[i].start, size, MAP_UNCACHED);
+			if (!ret) {
+				debug("%s: remap device %s resource %d: %pa -> 0x%p\n",
+				      __func__, dev_name(dev), i, &res[i].start, new_virt);
+
+				res[i].start = (resource_size_t)new_virt;
+				res[i].end = res[i].start + size - 1;
+			}
+		}
+	}
+
 	resinval = (-1);
 
 	debug("%s: register device %s, io=%pa\n",
-- 
2.39.2




^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 06/11] common: boards: qemu-virt: remap cfi-flash from 0 to 0x1000
  2023-05-22  5:28 [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000 Ahmad Fatoum
                   ` (4 preceding siblings ...)
  2023-05-22  5:28 ` [PATCH 05/11] of: platform: remap memory when encountering virtual-reg property Ahmad Fatoum
@ 2023-05-22  5:28 ` Ahmad Fatoum
  2023-05-22  5:28 ` [PATCH 07/11] ARM: prepare extending mmuinfo beyond ARMv7 Ahmad Fatoum
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Ahmad Fatoum @ 2023-05-22  5:28 UTC (permalink / raw)
  To: barebox; +Cc: Rouven Czerwinski, lst, Ahmad Fatoum, rcz

When MMU is enabled, barebox maintains a single address space with
1:1 physical to virtual mapping by default. Furthermore, the zero
page is marked inaccessible to trap NULL pointer dereferences.

This is problematic on the Qemu ARM Virt platform, because the
cfi-flash is memory mapped starting with address zero, so users need
to decide whether they want the cfi-flash or the MMU.

Make everyone happy by shifting the virtual cfi-flash mapping by 4K:

    virt   ->    phys

    0x0000 ->    0x0000 [faulting]
    0x1000 ->    0x0000 [(uncached) alias]
    0x2000 ->    0x1000
           .
           .
           .
 0x7fff000 -> 0x7ffe000
 0x8000000 -> 0x7fff000

This eats one page into the memory region starting at 0x8000000.
That's ok though, because that's where the GIC is located on both
ARM32 and ARM64 and we don't do interrupts in barebox.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
Cc: Rouven Czerwinski <r.czerwinski@pengutronix.de>
Cc: Lucas Stach <l.stach@pengutronix.de>
---
 common/boards/qemu-virt/Makefile             | 3 +++
 common/boards/qemu-virt/overlay-of-flash.dts | 5 ++++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/common/boards/qemu-virt/Makefile b/common/boards/qemu-virt/Makefile
index 8cacfafee734..c16727751550 100644
--- a/common/boards/qemu-virt/Makefile
+++ b/common/boards/qemu-virt/Makefile
@@ -5,6 +5,9 @@ obj-y += overlay-of-flash.dtb.o
 ifeq ($(CONFIG_RISCV),y)
 DTC_CPP_FLAGS_overlay-of-flash.dtb := -DRISCV_VIRT=1
 endif
+ifeq ($(CONFIG_ARM),y)
+DTC_CPP_FLAGS_overlay-of-flash.dtb := -DARM_VIRT=1
+endif
 
 clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts *.dtb.z
 clean-files += *.dtbo *.dtbo.S .*.dtso
diff --git a/common/boards/qemu-virt/overlay-of-flash.dts b/common/boards/qemu-virt/overlay-of-flash.dts
index 15c8cc450d49..16b1c7923d58 100644
--- a/common/boards/qemu-virt/overlay-of-flash.dts
+++ b/common/boards/qemu-virt/overlay-of-flash.dts
@@ -6,12 +6,15 @@
 #ifdef RISCV_VIRT
 #define PARTS_TARGET_PATH	/flash@20000000
 #define ENV_DEVICE_PATH		"/flash@20000000/partitions/partition@3c00000"
-#else
+#elif defined ARM_VIRT
 #define PARTS_TARGET_PATH	/flash@0
 #define ENV_DEVICE_PATH		"/flash@0/partitions/partition@3c00000"
 #endif
 
 &{PARTS_TARGET_PATH} {
+#ifdef ARM_VIRT
+	virtual-reg = <0x1000>;
+#endif
 	partitions {
 		compatible = "fixed-partitions";
 		#address-cells = <1>;
-- 
2.39.2




^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 07/11] ARM: prepare extending mmuinfo beyond ARMv7
  2023-05-22  5:28 [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000 Ahmad Fatoum
                   ` (5 preceding siblings ...)
  2023-05-22  5:28 ` [PATCH 06/11] common: boards: qemu-virt: remap cfi-flash from 0 to 0x1000 Ahmad Fatoum
@ 2023-05-22  5:28 ` Ahmad Fatoum
  2023-05-22  5:28 ` [PATCH 08/11] ARM64: mmu: implement ARMv8 mmuinfo command Ahmad Fatoum
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Ahmad Fatoum @ 2023-05-22  5:28 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum, lst, rcz

There's no reason to restrict mmuinfo to ARMv7 or ARM at all for that
matter. Prepare extending it for ARMv8 support by splitting off the
32-bit parts.

While at it, make the output available for debuggin by exporting a
mmuinfo() function.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/cpu/Makefile          |  2 +-
 arch/arm/cpu/mmuinfo.c         | 79 ++++++---------------------------
 arch/arm/cpu/mmuinfo_32.c      | 80 ++++++++++++++++++++++++++++++++++
 arch/arm/include/asm/mmuinfo.h |  8 ++++
 commands/Kconfig               |  1 +
 common/Kconfig                 |  3 ++
 include/mmu.h                  | 10 +++++
 7 files changed, 117 insertions(+), 66 deletions(-)
 create mode 100644 arch/arm/cpu/mmuinfo_32.c
 create mode 100644 arch/arm/include/asm/mmuinfo.h

diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile
index 0e4fa69229a6..a271de2c1f38 100644
--- a/arch/arm/cpu/Makefile
+++ b/arch/arm/cpu/Makefile
@@ -27,7 +27,7 @@ obj-$(CONFIG_ARM_PSCI_CLIENT) += psci-client.o
 # Any variants can be called as start-armxyz.S
 #
 obj-$(CONFIG_CMD_ARM_CPUINFO) += cpuinfo.o
-obj-$(CONFIG_CMD_ARM_MMUINFO) += mmuinfo.o
+obj-$(CONFIG_MMUINFO) += mmuinfo.o mmuinfo_32.o
 obj-$(CONFIG_OFDEVICE) += dtb.o
 
 ifeq ($(CONFIG_MMU),)
diff --git a/arch/arm/cpu/mmuinfo.c b/arch/arm/cpu/mmuinfo.c
index 1147c0a305b3..49e393149b69 100644
--- a/arch/arm/cpu/mmuinfo.c
+++ b/arch/arm/cpu/mmuinfo.c
@@ -1,91 +1,40 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // SPDX-FileCopyrightText: 2012 Jan Luebbe <j.luebbe@pengutronix.de>, Pengutronix
 /*
- * mmuinfo.c - Show MMU/cache information from cp15 registers
+ * mmuinfo.c - Show MMU/cache information
  */
 
 #include <common.h>
 #include <command.h>
+#include <asm/mmuinfo.h>
+#include <asm/system_info.h>
+#include <mmu.h>
 
-static char *inner_attr[] = {
-	"0b000 Non-cacheable",
-	"0b001 Strongly-ordered",
-	"0b010 (reserved)",
-	"0b011 Device",
-	"0b100 (reserved)",
-	"0b101 Write-Back, Write-Allocate",
-	"0b110 Write-Through",
-	"0b111 Write-Back, no Write-Allocate",
-};
-
-static char *outer_attr[] = {
-	"0b00 Non-cacheable",
-	"0b01 Write-Back, Write-Allocate",
-	"0b10 Write-Through, no Write-Allocate",
-	"0b11 Write-Back, no Write-Allocate",
-};
-
-static void decode_par(unsigned long par)
+int mmuinfo(void *addr)
 {
-	printf("  Physical Address [31:12]: 0x%08lx\n", par & 0xFFFFF000);
-	printf("  Reserved [11]:            0x%lx\n", (par >> 11) & 0x1);
-	printf("  Not Outer Shareable [10]: 0x%lx\n", (par >> 10) & 0x1);
-	printf("  Non-Secure [9]:           0x%lx\n", (par >> 9) & 0x1);
-	printf("  Impl. def. [8]:           0x%lx\n", (par >> 8) & 0x1);
-	printf("  Shareable [7]:            0x%lx\n", (par >> 7) & 0x1);
-	printf("  Inner mem. attr. [6:4]:   0x%lx (%s)\n", (par >> 4) & 0x7,
-		inner_attr[(par >> 4) & 0x7]);
-	printf("  Outer mem. attr. [3:2]:   0x%lx (%s)\n", (par >> 2) & 0x3,
-		outer_attr[(par >> 2) & 0x3]);
-	printf("  SuperSection [1]:         0x%lx\n", (par >> 1) & 0x1);
-	printf("  Failure [0]:              0x%lx\n", (par >> 0) & 0x1);
+	if (IS_ENABLED(CONFIG_CPU_V7) && cpu_architecture() == CPU_ARCH_ARMv7)
+		return mmuinfo_v7(addr);
+
+	return -ENOSYS;
 }
 
-static int do_mmuinfo(int argc, char *argv[])
+static __maybe_unused int do_mmuinfo(int argc, char *argv[])
 {
-	unsigned long addr = 0, priv_read, priv_write;
+	unsigned long addr;
 
 	if (argc < 2)
 		return COMMAND_ERROR_USAGE;
 
 	addr = strtoul_suffix(argv[1], NULL, 0);
 
-	__asm__ __volatile__(
-		"mcr    p15, 0, %0, c7, c8, 0   @ write VA to PA translation (priv read)\n"
-		:
-		: "r" (addr)
-		: "memory");
-
-	__asm__ __volatile__(
-		"mrc    p15, 0, %0, c7, c4, 0   @ read PAR\n"
-		: "=r" (priv_read)
-		:
-		: "memory");
-
-	__asm__ __volatile__(
-		"mcr    p15, 0, %0, c7, c8, 1   @ write VA to PA translation (priv write)\n"
-		:
-		: "r" (addr)
-		: "memory");
-
-	__asm__ __volatile__(
-		"mrc    p15, 0, %0, c7, c4, 0   @ read PAR\n"
-		: "=r" (priv_write)
-		:
-		: "memory");
-
-	printf("PAR result for 0x%08lx: \n", addr);
-	printf(" privileged read: 0x%08lx\n", priv_read);
-	decode_par(priv_read);
-	printf(" privileged write: 0x%08lx\n", priv_write);
-	decode_par(priv_write);
-
-	return 0;
+	return mmuinfo((void *)addr);
 }
 
+#ifdef CONFIG_COMMAND_SUPPORT
 BAREBOX_CMD_START(mmuinfo)
 	.cmd            = do_mmuinfo,
 	BAREBOX_CMD_DESC("show MMU/cache information of an address")
 	BAREBOX_CMD_OPTS("ADDRESS")
 	BAREBOX_CMD_GROUP(CMD_GRP_INFO)
 BAREBOX_CMD_END
+#endif
diff --git a/arch/arm/cpu/mmuinfo_32.c b/arch/arm/cpu/mmuinfo_32.c
new file mode 100644
index 000000000000..e26dabc9b3d9
--- /dev/null
+++ b/arch/arm/cpu/mmuinfo_32.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2012 Jan Luebbe <j.luebbe@pengutronix.de>, Pengutronix
+/*
+ * mmuinfo_32.c - Show MMU/cache information from cp15 registers
+ */
+
+#include <common.h>
+#include <asm/mmuinfo.h>
+
+static char *inner_attr[] = {
+	"0b000 Non-cacheable",
+	"0b001 Strongly-ordered",
+	"0b010 (reserved)",
+	"0b011 Device",
+	"0b100 (reserved)",
+	"0b101 Write-Back, Write-Allocate",
+	"0b110 Write-Through",
+	"0b111 Write-Back, no Write-Allocate",
+};
+
+static char *outer_attr[] = {
+	"0b00 Non-cacheable",
+	"0b01 Write-Back, Write-Allocate",
+	"0b10 Write-Through, no Write-Allocate",
+	"0b11 Write-Back, no Write-Allocate",
+};
+
+static void decode_par(unsigned long par)
+{
+	printf("  Physical Address [31:12]: 0x%08lx\n", par & 0xFFFFF000);
+	printf("  Reserved [11]:            0x%lx\n", (par >> 11) & 0x1);
+	printf("  Not Outer Shareable [10]: 0x%lx\n", (par >> 10) & 0x1);
+	printf("  Non-Secure [9]:           0x%lx\n", (par >> 9) & 0x1);
+	printf("  Impl. def. [8]:           0x%lx\n", (par >> 8) & 0x1);
+	printf("  Shareable [7]:            0x%lx\n", (par >> 7) & 0x1);
+	printf("  Inner mem. attr. [6:4]:   0x%lx (%s)\n", (par >> 4) & 0x7,
+		inner_attr[(par >> 4) & 0x7]);
+	printf("  Outer mem. attr. [3:2]:   0x%lx (%s)\n", (par >> 2) & 0x3,
+		outer_attr[(par >> 2) & 0x3]);
+	printf("  SuperSection [1]:         0x%lx\n", (par >> 1) & 0x1);
+	printf("  Failure [0]:              0x%lx\n", (par >> 0) & 0x1);
+}
+
+int mmuinfo_v7(void *_addr)
+{
+	unsigned long addr = (unsigned long)_addr;
+	unsigned long priv_read, priv_write;
+
+	__asm__ __volatile__(
+		"mcr    p15, 0, %0, c7, c8, 0   @ write VA to PA translation (priv read)\n"
+		:
+		: "r" (addr)
+		: "memory");
+
+	__asm__ __volatile__(
+		"mrc    p15, 0, %0, c7, c4, 0   @ read PAR\n"
+		: "=r" (priv_read)
+		:
+		: "memory");
+
+	__asm__ __volatile__(
+		"mcr    p15, 0, %0, c7, c8, 1   @ write VA to PA translation (priv write)\n"
+		:
+		: "r" (addr)
+		: "memory");
+
+	__asm__ __volatile__(
+		"mrc    p15, 0, %0, c7, c4, 0   @ read PAR\n"
+		: "=r" (priv_write)
+		:
+		: "memory");
+
+	printf("PAR result for 0x%08lx: \n", addr);
+	printf(" privileged read: 0x%08lx\n", priv_read);
+	decode_par(priv_read);
+	printf(" privileged write: 0x%08lx\n", priv_write);
+	decode_par(priv_write);
+
+	return 0;
+}
diff --git a/arch/arm/include/asm/mmuinfo.h b/arch/arm/include/asm/mmuinfo.h
new file mode 100644
index 000000000000..bc17bf8982ab
--- /dev/null
+++ b/arch/arm/include/asm/mmuinfo.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ARM_ASM_MMUINFO_H__
+#define __ARM_ASM_MMUINFO_H__
+
+int mmuinfo_v7(void *addr);
+
+#endif
diff --git a/commands/Kconfig b/commands/Kconfig
index c72c2b7758a2..bc697d52b730 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -202,6 +202,7 @@ config CMD_MEMINFO
 config CMD_ARM_MMUINFO
 	bool "mmuinfo command"
 	depends on CPU_V7
+	select MMUINFO
 	help
 	  Say yes here to get a mmuinfo command to show some
 	  MMU and cache information using the cp15 registers.
diff --git a/common/Kconfig b/common/Kconfig
index b9e175045608..bd1df889e69a 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -185,6 +185,9 @@ config MMU
 	  to enable the data cache which depends on the MMU. See Documentation/mmu.txt
 	  for further information.
 
+config MMUINFO
+	bool
+
 config HAVE_CONFIGURABLE_TEXT_BASE
 	bool
 
diff --git a/include/mmu.h b/include/mmu.h
index fd6dbc51ac03..84ec6c5efb3e 100644
--- a/include/mmu.h
+++ b/include/mmu.h
@@ -3,6 +3,7 @@
 #define __MMU_H
 
 #include <linux/types.h>
+#include <errno.h>
 
 #define MAP_UNCACHED	0
 #define MAP_CACHED	1
@@ -43,4 +44,13 @@ static inline int remap_range(void *start, size_t size, unsigned flags)
 	return arch_remap_range(start, virt_to_phys(start), size, flags);
 }
 
+#ifdef CONFIG_MMUINFO
+int mmuinfo(void *addr);
+#else
+static inline int mmuinfo(void *addr)
+{
+	return -ENOSYS;
+}
+#endif
+
 #endif
-- 
2.39.2




^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 08/11] ARM64: mmu: implement ARMv8 mmuinfo command
  2023-05-22  5:28 [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000 Ahmad Fatoum
                   ` (6 preceding siblings ...)
  2023-05-22  5:28 ` [PATCH 07/11] ARM: prepare extending mmuinfo beyond ARMv7 Ahmad Fatoum
@ 2023-05-22  5:28 ` Ahmad Fatoum
  2023-05-22  5:28 ` [PATCH 09/11] common: memtest: prepare for reuse in self test Ahmad Fatoum
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Ahmad Fatoum @ 2023-05-22  5:28 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum, lst, rcz

To aid with debugging of MMU code, let's implement mmuinfo for ARMv8,
like we already support for ARMv7.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/configs/multi_v8_defconfig |   1 +
 arch/arm/cpu/Makefile               |   2 +-
 arch/arm/cpu/mmuinfo.c              |   2 +
 arch/arm/cpu/mmuinfo_64.c           | 215 ++++++++++++++++++++++++++++
 arch/arm/include/asm/mmuinfo.h      |   1 +
 arch/arm/include/asm/sysreg.h       |  76 ++++++++++
 commands/Kconfig                    |   6 +-
 7 files changed, 299 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm/cpu/mmuinfo_64.c
 create mode 100644 arch/arm/include/asm/sysreg.h

diff --git a/arch/arm/configs/multi_v8_defconfig b/arch/arm/configs/multi_v8_defconfig
index 62afe3829350..d30158d7f880 100644
--- a/arch/arm/configs/multi_v8_defconfig
+++ b/arch/arm/configs/multi_v8_defconfig
@@ -57,6 +57,7 @@ CONFIG_LONGHELP=y
 CONFIG_CMD_IOMEM=y
 CONFIG_CMD_IMD=y
 CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_ARM_MMUINFO=y
 CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_MMC_EXTCSD=y
 CONFIG_CMD_POLLER=y
diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile
index a271de2c1f38..5baff2fad087 100644
--- a/arch/arm/cpu/Makefile
+++ b/arch/arm/cpu/Makefile
@@ -27,7 +27,7 @@ obj-$(CONFIG_ARM_PSCI_CLIENT) += psci-client.o
 # Any variants can be called as start-armxyz.S
 #
 obj-$(CONFIG_CMD_ARM_CPUINFO) += cpuinfo.o
-obj-$(CONFIG_MMUINFO) += mmuinfo.o mmuinfo_32.o
+obj-$(CONFIG_MMUINFO) += mmuinfo.o mmuinfo_$(S64_32).o
 obj-$(CONFIG_OFDEVICE) += dtb.o
 
 ifeq ($(CONFIG_MMU),)
diff --git a/arch/arm/cpu/mmuinfo.c b/arch/arm/cpu/mmuinfo.c
index 49e393149b69..413f2f337e95 100644
--- a/arch/arm/cpu/mmuinfo.c
+++ b/arch/arm/cpu/mmuinfo.c
@@ -12,6 +12,8 @@
 
 int mmuinfo(void *addr)
 {
+	if (IS_ENABLED(CONFIG_CPU_V8))
+		return mmuinfo_v8(addr);
 	if (IS_ENABLED(CONFIG_CPU_V7) && cpu_architecture() == CPU_ARCH_ARMv7)
 		return mmuinfo_v7(addr);
 
diff --git a/arch/arm/cpu/mmuinfo_64.c b/arch/arm/cpu/mmuinfo_64.c
new file mode 100644
index 000000000000..de4945f43e8e
--- /dev/null
+++ b/arch/arm/cpu/mmuinfo_64.c
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2023 Ahmad Fatoum <a.fatoum@pengutronix.de>, Pengutronix
+/*
+ * mmuinfo_64.c - Show MMU/cache information via AT instruction
+ */
+
+#include <common.h>
+#include <asm/mmuinfo.h>
+#include <asm/system.h>
+#include <asm/sysreg.h>
+#include <linux/bitfield.h>
+
+#define at_par(reg, addr) ({ \
+		asm volatile("at " reg ", %0\n" :: "r" (addr)); \
+		isb(); \
+		read_sysreg_par(); \
+})
+
+#define BITS(from, to, val) FIELD_GET(GENMASK(from, to), val)
+
+static const char *decode_devmem_attr(u8 attr)
+{
+	switch (attr & ~0x1) {
+	case 0b00000000:
+		return "0b0000 Device-nGnRnE memory";
+	case 0b00000100:
+		return "0b0100 Device-nGnRE memory";
+	case 0b00001000:
+		return "0b1000 Device-nGRE memory";
+	case 0b00001100:
+		return "0b1100 Device-GRE memory";
+	default:
+		return "unknown";
+	};
+}
+
+static char *cache_attr[] = {
+	"0b0000 Wrongly decoded",
+	"0b0001 Write-Through Transient, Write-Allocate, no Read-Allocate",
+	"0b0010 Write-Through Transient, no Write-Allocate",
+	"0b0011 Write-Through Transient, Write-Allocate",
+	"0b0100 Non-Cacheable",
+	"0b0101 Write-Back Transient, Write-Allocate, no Read-Allocate",
+	"0b0110 Write-Back Transient, no Write-Allocate",
+	"0b0111 Write-Back Transient, Write-Allocate",
+	"0b1000 Write-Through Non-transient, no Write-Allocate no Read-Allocate",
+	"0b1001 Write-Through Non-transient, Write-Allocate no Read-Allocate",
+	"0b1010 Write-Through Non-transient, no Write-Allocate",
+	"0b1011 Write-Through Non-transient, Write-Allocate",
+	"0b1100 Write-Back Non-transient, no Write-Allocate no Read-Allocate",
+	"0b1101 Write-Back Non-transient, Write-Allocate no Read-Allocate",
+	"0b1110 Write-Back Non-transient, no Write-Allocate",
+	"0b1111 Write-Back Non-transient, Write-Allocate",
+};
+
+static char *share_attr[] = {
+	"0b00 Non-Shareable",
+	"0b01 Reserved",
+	"0b10 Outer Shareable",
+	"0b11 Inner Shareable",
+};
+
+static char *stage_fault[] = {
+	"stage 1 translation",
+	"stage 2 translation",
+};
+
+static char *fault_status_leveled[] = {
+	"Address size fault",  /* of translation or translation table base register */
+	"Translation fault",
+	"Access flag fault",
+	"Permission fault",
+	"Synchronous External abort", /* level -1 */
+	"Synchronous External abort", /* on translation table walk or hardware update of translation table */
+	"Synchronous parity or ECC error", /* level -1 */
+	"Synchronous parity or ECC error", /* on memory access on translation table walk or hardware update of translation table */
+};
+
+static const char *decode_fault_status_level(u8 fst)
+{
+	if (!(fst & BIT(5)))
+		return "";
+
+	switch (BITS(5, 0, fst)) {
+	case 0b010011:
+	case 0b011011:
+		return ", level -1";
+	}
+
+	switch (BITS(1, 0, fst)) {
+	case 0b00:
+		return ", level 0";
+	case 0b01:
+		return ", level 1";
+	case 0b10:
+		return ", level 2";
+	case 0b11:
+		return ", level 3";
+	}
+
+	BUG();
+}
+
+static const char *decode_fault_status(u8 fst)
+{
+
+	switch (BITS(5, 0, fst)) {
+	case 0b101001: /* When FEAT_LPA2 is implemented */
+		return "Address size fault, level -1";
+	case 0b101011: /* When FEAT_LPA2 is implemented */
+		return "Translation fault, level -1";
+	case 0b110000:
+		return "TLB conflict abort";
+	case 0b110001: /* When FEAT_HAFDBS is implemented */
+		return "Unsupported atomic hardware update fault";
+	case 0b111101: /* When EL1 is capable of using AArch32 */
+		return "Section Domain fault, from an AArch32 stage 1 EL1&0 "
+			"translation regime using Short-descriptor translation "
+			"table format";
+	case 0b111110: /* When EL1 is capable of using AArch32 */
+		return "Page Domain fault, from an AArch32 stage 1 EL1&0 "
+			"translation regime using Short-descriptor translation "
+			"table format";
+	default:
+		if (fst & BIT(5))
+			return fault_status_leveled[BITS(4, 2, fst)];
+
+		return "Reserved";
+	}
+};
+
+static void decode_par(unsigned long par)
+{
+	u8 devmem_attr = BITS(63, 56, par);
+
+	if (par & 1) {
+		printf("  Translation aborted [9:8]: because of a fault in the %s%s\n",
+		       stage_fault[BITS(9, 9, par)],
+		       BITS(8, 8, par) ? " during a stage 1 translation table walk" : "");
+		printf("  Fault Status Code [6:1]:   0x%02lx (%s%s)\n", BITS(6, 1, par),
+		       decode_fault_status(BITS(6, 1, par)),
+		       decode_fault_status_level(BITS(6, 1, par)));
+		printf("  Failure [0]:                0x1\n");
+	} else {
+		if ((devmem_attr & 0xf0) && (devmem_attr & 0x0f)) {
+			printf("  Outer mem. attr. [63:60]:   0x%02lx (%s)\n", BITS(63, 60, par),
+			       cache_attr[BITS(63, 60, par)]);
+			printf("  Inner mem. attr. [59:56]:   0x%02lx (%s)\n", BITS(59, 56, par),
+			       cache_attr[BITS(59, 56, par)]);
+		} else if ((devmem_attr & 0b11110010) == 0) {
+			printf("  Memory attr. [63:56]:     0x%02x (%s)\n",
+			       devmem_attr, decode_devmem_attr(devmem_attr));
+			if (devmem_attr & 1)
+				printf("  (XS == 0 if FEAT_XS implemented)\n");
+		} else if (devmem_attr == 0b01000000) {
+			printf("  Outer mem. attr. [63:56]:   0x%02lx (%s)\n", BITS(63, 56, par),
+			       "Non-Cacheable");
+			printf("  Inner mem. attr. [63:56]:   0x%02lx (%s)\n", BITS(63, 56, par),
+			       "Non-Cacheable");
+			printf("  (XS == 0 if FEAT_XS implemented)\n");
+		} else if (devmem_attr == 0b10100000) {
+			printf("  Outer mem. attr. [63:56]:   0x%02lx (%s)\n", BITS(63, 56, par),
+			       "Write-Through, No Write-Allocate");
+			printf("  Inner mem. attr. [63:56]:   0x%02lx (%s)\n", BITS(63, 56, par),
+			       "Write-Through");
+			printf("  (XS == 0 if FEAT_XS implemented)\n");
+		} else if (devmem_attr == 0b11110000) {
+			printf("  Outer mem. attr. [63:56]:   0x%02lx (%s)\n", BITS(63, 56, par),
+			       "Write-Back");
+			printf("  Inner mem. attr. [63:56]:   0x%02lx (%s)\n", BITS(63, 56, par),
+			       "Write-Back, Write-Allocate, Non-transient");
+			printf("  (if FEAT_MTE2 implemented)\n");
+		}
+		printf("  Physical Address [51:12]: 0x%08lx\n", par & GENMASK(51, 12));
+		printf("  Non-Secure [9]:           0x%lx\n", BITS(9, 9, par));
+		printf("  Shareability attr. [8:7]: 0x%02lx (%s)\n", BITS(8, 7, par),
+			share_attr[BITS(8, 7, par)]);
+		printf("  Failure [0]:              0x0\n");
+	}
+}
+
+int mmuinfo_v8(void *_addr)
+{
+	unsigned long addr = (unsigned long)_addr;
+	unsigned long priv_read, priv_write;
+
+	switch (current_el()) {
+	case 3:
+		priv_read  = at_par("s1e3r", addr);
+		priv_write = at_par("s1e3w", addr);
+		break;
+	case 2:
+		priv_read  = at_par("s1e2r", addr);
+		priv_write = at_par("s1e2w", addr);
+		break;
+	case 1:
+		priv_read  = at_par("s1e1r", addr);
+		priv_write = at_par("s1e1w", addr);
+		break;
+	case 0:
+		priv_read  = at_par("s1e0r", addr);
+		priv_write = at_par("s1e0w", addr);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	printf("PAR result for 0x%08lx: \n", addr);
+	printf(" privileged read: 0x%08lx\n", priv_read);
+	decode_par(priv_read);
+	printf(" privileged write: 0x%08lx\n", priv_write);
+	decode_par(priv_write);
+
+	return 0;
+}
diff --git a/arch/arm/include/asm/mmuinfo.h b/arch/arm/include/asm/mmuinfo.h
index bc17bf8982ab..3005c388b967 100644
--- a/arch/arm/include/asm/mmuinfo.h
+++ b/arch/arm/include/asm/mmuinfo.h
@@ -4,5 +4,6 @@
 #define __ARM_ASM_MMUINFO_H__
 
 int mmuinfo_v7(void *addr);
+int mmuinfo_v8(void *addr);
 
 #endif
diff --git a/arch/arm/include/asm/sysreg.h b/arch/arm/include/asm/sysreg.h
new file mode 100644
index 000000000000..7d567e08d8b7
--- /dev/null
+++ b/arch/arm/include/asm/sysreg.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Macros for accessing system registers with older binutils.
+ *
+ * Copyright (C) 2014 ARM Ltd.
+ * Author: Catalin Marinas <catalin.marinas@arm.com>
+ */
+
+#ifndef __ASM_SYSREG_H
+#define __ASM_SYSREG_H
+
+#include <asm/system.h>
+#include <linux/stringify.h>
+
+/*
+ * Unlike read_cpuid, calls to read_sysreg are never expected to be
+ * optimized away or replaced with synthetic values.
+ */
+#define read_sysreg(r) ({					\
+	u64 __val;						\
+	asm volatile("mrs %0, " __stringify(r) : "=r" (__val));	\
+	__val;							\
+})
+
+/*
+ * The "Z" constraint normally means a zero immediate, but when combined with
+ * the "%x0" template means XZR.
+ */
+#define write_sysreg(v, r) do {					\
+	u64 __val = (u64)(v);					\
+	asm volatile("msr " __stringify(r) ", %x0"		\
+		     : : "rZ" (__val));				\
+} while (0)
+
+/*
+ * For registers without architectural names, or simply unsupported by
+ * GAS.
+ */
+#define read_sysreg_s(r) ({						\
+	u64 __val;							\
+	asm volatile(__mrs_s("%0", r) : "=r" (__val));			\
+	__val;								\
+})
+
+#define write_sysreg_s(v, r) do {					\
+	u64 __val = (u64)(v);						\
+	asm volatile(__msr_s(r, "%x0") : : "rZ" (__val));		\
+} while (0)
+
+/*
+ * Modify bits in a sysreg. Bits in the clear mask are zeroed, then bits in the
+ * set mask are set. Other bits are left as-is.
+ */
+#define sysreg_clear_set(sysreg, clear, set) do {			\
+	u64 __scs_val = read_sysreg(sysreg);				\
+	u64 __scs_new = (__scs_val & ~(u64)(clear)) | (set);		\
+	if (__scs_new != __scs_val)					\
+		write_sysreg(__scs_new, sysreg);			\
+} while (0)
+
+#define sysreg_clear_set_s(sysreg, clear, set) do {			\
+	u64 __scs_val = read_sysreg_s(sysreg);				\
+	u64 __scs_new = (__scs_val & ~(u64)(clear)) | (set);		\
+	if (__scs_new != __scs_val)					\
+		write_sysreg_s(__scs_new, sysreg);			\
+} while (0)
+
+#define read_sysreg_par() ({						\
+	u64 par;							\
+	asm("dmb sy");							\
+	par = read_sysreg(par_el1);					\
+	asm("dmb sy");							\
+	par;								\
+})
+
+#endif	/* __ASM_SYSREG_H */
diff --git a/commands/Kconfig b/commands/Kconfig
index bc697d52b730..3a43682b2b2c 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -201,13 +201,13 @@ config CMD_MEMINFO
 
 config CMD_ARM_MMUINFO
 	bool "mmuinfo command"
-	depends on CPU_V7
+	depends on CPU_V7 || CPU_V8
 	select MMUINFO
 	help
 	  Say yes here to get a mmuinfo command to show some
-	  MMU and cache information using the cp15 registers.
+	  MMU and cache information using the cp15/model-specific registers.
 
-	  Example:
+	  Example for ARMv7:
 
 	  PAR result for 0x00110000:
 	  privileged read: 0x00110090
-- 
2.39.2




^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 09/11] common: memtest: prepare for reuse in self test
  2023-05-22  5:28 [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000 Ahmad Fatoum
                   ` (7 preceding siblings ...)
  2023-05-22  5:28 ` [PATCH 08/11] ARM64: mmu: implement ARMv8 mmuinfo command Ahmad Fatoum
@ 2023-05-22  5:28 ` Ahmad Fatoum
  2023-05-22  5:28 ` [PATCH 10/11] test: self: add MMU remapping " Ahmad Fatoum
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 16+ messages in thread
From: Ahmad Fatoum @ 2023-05-22  5:28 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum, lst, rcz

memtest is quite talkative: it narrates status and advances a progress
bar. For non-interactive use, e.g. for selftest, this is a bit much,
so hide that behidnd a new MEMTEST_VERBOSE flag.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 commands/Kconfig   |  1 +
 commands/memtest.c |  5 +++--
 common/Kconfig     |  3 +++
 common/Makefile    |  2 +-
 common/memtest.c   | 44 ++++++++++++++++++++++++++------------------
 include/memtest.h  |  7 +++++--
 6 files changed, 39 insertions(+), 23 deletions(-)

diff --git a/commands/Kconfig b/commands/Kconfig
index 3a43682b2b2c..4d3ff631a8bf 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -1708,6 +1708,7 @@ config CMD_MEMSET
 
 config CMD_MEMTEST
 	tristate
+	select MEMTEST
 	prompt "memtest"
 	help
 	  The memtest command can test the registered barebox memory.
diff --git a/commands/memtest.c b/commands/memtest.c
index 864947fa94f9..9fa148b3aa41 100644
--- a/commands/memtest.c
+++ b/commands/memtest.c
@@ -15,6 +15,7 @@
 static int do_test_one_area(struct mem_test_resource *r, int bus_only,
 		unsigned cache_flag)
 {
+	unsigned flags = MEMTEST_VERBOSE;
 	int ret;
 
 	printf("Testing memory space: %pa -> %pa:\n",
@@ -22,14 +23,14 @@ static int do_test_one_area(struct mem_test_resource *r, int bus_only,
 
 	remap_range((void *)r->r->start, resource_size(r->r), cache_flag);
 
-	ret = mem_test_bus_integrity(r->r->start, r->r->end);
+	ret = mem_test_bus_integrity(r->r->start, r->r->end, flags);
 	if (ret < 0)
 		return ret;
 
 	if (bus_only)
 		return 0;
 
-	ret = mem_test_moving_inversions(r->r->start, r->r->end);
+	ret = mem_test_moving_inversions(r->r->start, r->r->end, flags);
 	if (ret < 0)
 		return ret;
 	printf("done.\n\n");
diff --git a/common/Kconfig b/common/Kconfig
index bd1df889e69a..ce94718c848a 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -144,6 +144,9 @@ config MEMINFO
 	bool "display memory info"
 	default y
 
+config MEMTEST
+	bool
+
 config ENVIRONMENT_VARIABLES
 	bool "environment variables support"
 
diff --git a/common/Makefile b/common/Makefile
index 8dc475f3244c..7fb864f61480 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -27,7 +27,7 @@ obj-$(CONFIG_BLOCK)		+= block.o
 obj-$(CONFIG_BLSPEC)		+= blspec.o
 obj-$(CONFIG_BOOTM)		+= bootm.o booti.o
 obj-$(CONFIG_CMD_LOADS)		+= s_record.o
-obj-$(CONFIG_CMD_MEMTEST)	+= memtest.o
+obj-$(CONFIG_MEMTEST)		+= memtest.o
 obj-$(CONFIG_COMMAND_SUPPORT)	+= command.o
 obj-$(CONFIG_CONSOLE_FULL)	+= console.o
 obj-$(CONFIG_CONSOLE_SIMPLE)	+= console_simple.o
diff --git a/common/memtest.c b/common/memtest.c
index d47e4a672ed9..aa16d94eeda0 100644
--- a/common/memtest.c
+++ b/common/memtest.c
@@ -160,7 +160,7 @@ static void mem_test_report_failure(const char *failure_description,
 }
 
 int mem_test_bus_integrity(resource_size_t _start,
-			   resource_size_t _end)
+			   resource_size_t _end, unsigned int flags)
 {
 	static const uint64_t bitpattern[] = {
 		0x0000000000000001ULL,	/* single bit */
@@ -190,7 +190,8 @@ int mem_test_bus_integrity(resource_size_t _start,
 	dummy = start + 1;
 	num_words = (_end - _start + 1)/sizeof(resource_size_t);
 
-	printf("Starting data line test.\n");
+	if (flags & MEMTEST_VERBOSE)
+		printf("Starting data line test.\n");
 
 	/*
 	 * Data line test: write a pattern to the first
@@ -294,7 +295,8 @@ int mem_test_bus_integrity(resource_size_t _start,
 	 */
 	start[0] = anti_pattern;
 
-	printf("Check for address bits stuck high.\n");
+	if (flags & MEMTEST_VERBOSE)
+		printf("Check for address bits stuck high.\n");
 
 	/*
 	 * Check for address bits stuck high.
@@ -313,8 +315,8 @@ int mem_test_bus_integrity(resource_size_t _start,
 	 */
 	start[0] = pattern;
 
-	printf("Check for address bits stuck "
-			"low or shorted.\n");
+	if (flags & MEMTEST_VERBOSE)
+		printf("Check for address bits stuck low or shorted.\n");
 
 	/*
 	 * Check for address bits stuck low or shorted.
@@ -340,7 +342,7 @@ int mem_test_bus_integrity(resource_size_t _start,
 	return 0;
 }
 
-static int update_progress(resource_size_t offset)
+static int update_progress(resource_size_t offset, unsigned flags)
 {
 	/* Only check every 4k to reduce overhead */
 	if (offset & (SZ_4K - 1))
@@ -349,12 +351,14 @@ static int update_progress(resource_size_t offset)
 	if (ctrlc())
 		return -EINTR;
 
-	show_progress(offset);
+	if (flags & MEMTEST_VERBOSE)
+		show_progress(offset);
 
 	return 0;
 }
 
-int mem_test_moving_inversions(resource_size_t _start, resource_size_t _end)
+int mem_test_moving_inversions(resource_size_t _start, resource_size_t _end,
+			       unsigned flags)
 {
 	volatile resource_size_t *start, num_words, offset, temp, anti_pattern;
 	int ret;
@@ -368,8 +372,12 @@ int mem_test_moving_inversions(resource_size_t _start, resource_size_t _end)
 	start = (resource_size_t *)_start;
 	num_words = (_end - _start + 1)/sizeof(resource_size_t);
 
-	printf("Starting moving inversions test of RAM:\n"
-	       "Fill with address, compare, fill with inverted address, compare again\n");
+	if (flags & MEMTEST_VERBOSE) {
+		printf("Starting moving inversions test of RAM:\n"
+		       "Fill with address, compare, fill with inverted address, compare again\n");
+
+		init_progression_bar(3 * num_words);
+	}
 
 	/*
 	 * Description: Test the integrity of a physical
@@ -382,11 +390,9 @@ int mem_test_moving_inversions(resource_size_t _start, resource_size_t _end)
 	 *		selected by the caller.
 	 */
 
-	init_progression_bar(3 * num_words);
-
 	/* Fill memory with a known pattern */
 	for (offset = 0; offset < num_words; offset++) {
-		ret = update_progress(offset);
+		ret = update_progress(offset, flags);
 		if (ret)
 			return ret;
 		start[offset] = offset + 1;
@@ -394,7 +400,7 @@ int mem_test_moving_inversions(resource_size_t _start, resource_size_t _end)
 
 	/* Check each location and invert it for the second pass */
 	for (offset = 0; offset < num_words; offset++) {
-		ret = update_progress(num_words + offset);
+		ret = update_progress(num_words + offset, flags);
 		if (ret)
 			return ret;
 
@@ -413,7 +419,7 @@ int mem_test_moving_inversions(resource_size_t _start, resource_size_t _end)
 
 	/* Check each location for the inverted pattern and zero it */
 	for (offset = 0; offset < num_words; offset++) {
-		ret = update_progress(2 * num_words + offset);
+		ret = update_progress(2 * num_words + offset, flags);
 		if (ret)
 			return ret;
 
@@ -430,10 +436,12 @@ int mem_test_moving_inversions(resource_size_t _start, resource_size_t _end)
 
 		start[offset] = 0;
 	}
-	show_progress(3 * num_words);
+	if (flags & MEMTEST_VERBOSE) {
+		show_progress(3 * num_words);
 
-	/* end of progressbar */
-	printf("\n");
+		/* end of progressbar */
+		printf("\n");
+	}
 
 	return 0;
 }
diff --git a/include/memtest.h b/include/memtest.h
index df0a391cc3c2..3de30631ae24 100644
--- a/include/memtest.h
+++ b/include/memtest.h
@@ -3,6 +3,7 @@
 #define __MEMTEST_H
 
 #include <linux/ioport.h>
+#include <linux/bitops.h>
 
 struct mem_test_resource {
 	struct resource *r;
@@ -13,7 +14,9 @@ int mem_test_request_regions(struct list_head *list);
 void mem_test_release_regions(struct list_head *list);
 struct mem_test_resource *mem_test_biggest_region(struct list_head *list);
 
-int mem_test_bus_integrity(resource_size_t _start, resource_size_t _end);
-int mem_test_moving_inversions(resource_size_t _start, resource_size_t _end);
+#define MEMTEST_VERBOSE		BIT(0)
+
+int mem_test_bus_integrity(resource_size_t _start, resource_size_t _end, unsigned flags);
+int mem_test_moving_inversions(resource_size_t _start, resource_size_t _end, unsigned flags);
 
 #endif /* __MEMTEST_H */
-- 
2.39.2




^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 10/11] test: self: add MMU remapping self test
  2023-05-22  5:28 [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000 Ahmad Fatoum
                   ` (8 preceding siblings ...)
  2023-05-22  5:28 ` [PATCH 09/11] common: memtest: prepare for reuse in self test Ahmad Fatoum
@ 2023-05-22  5:28 ` Ahmad Fatoum
  2023-05-22  5:28 ` [PATCH 11/11] ARM: mmuinfo: add options for enabling/disabling zero page trapping Ahmad Fatoum
  2023-05-23  7:21 ` [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000 Sascha Hauer
  11 siblings, 0 replies; 16+ messages in thread
From: Ahmad Fatoum @ 2023-05-22  5:28 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum, lst, rcz

ARM mmu code in barebox has recently seen some changes to enhance
remapping. Add a self test that exercises this a bit.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 test/self/Kconfig  |   6 ++
 test/self/Makefile |   1 +
 test/self/mmu.c    | 233 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 240 insertions(+)
 create mode 100644 test/self/mmu.c

diff --git a/test/self/Kconfig b/test/self/Kconfig
index ce5048c70ec9..c130209748aa 100644
--- a/test/self/Kconfig
+++ b/test/self/Kconfig
@@ -36,6 +36,7 @@ config SELFTEST_ENABLE_ALL
 	imply SELFTEST_FS_RAMFS
 	imply SELFTEST_TFTP
 	imply SELFTEST_JSON
+	imply SELFTEST_MMU
 	help
 	  Selects all self-tests compatible with current configuration
 
@@ -69,4 +70,9 @@ config SELFTEST_JSON
 	bool "JSON selftest"
 	depends on JSMN
 
+config SELFTEST_MMU
+	bool "MMU remapping selftest"
+	select MEMTEST
+	depends on MMU
+
 endif
diff --git a/test/self/Makefile b/test/self/Makefile
index 98ebd1fd66c1..8c816c4299f6 100644
--- a/test/self/Makefile
+++ b/test/self/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_SELFTEST_OF_MANIPULATION) += of_manipulation.o of_manipulation.dtb.
 obj-$(CONFIG_SELFTEST_ENVIRONMENT_VARIABLES) += envvar.o
 obj-$(CONFIG_SELFTEST_FS_RAMFS) += ramfs.o
 obj-$(CONFIG_SELFTEST_JSON) += json.o
+obj-$(CONFIG_SELFTEST_MMU) += mmu.o
 
 clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts *.dtb.z
 clean-files += *.dtbo *.dtbo.S .*.dtso
diff --git a/test/self/mmu.c b/test/self/mmu.c
new file mode 100644
index 000000000000..ee6c1cd45e7e
--- /dev/null
+++ b/test/self/mmu.c
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-2.0-onl
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <common.h>
+#include <bselftest.h>
+#include <mmu.h>
+#include <memtest.h>
+#include <abort.h>
+#include <zero_page.h>
+#include <linux/sizes.h>
+
+BSELFTEST_GLOBALS();
+
+#define __expect(ret, cond, fmt, ...) do { \
+	bool __cond = (cond); \
+	int __ret = (ret); \
+	total_tests++; \
+	\
+	if (!__cond) { \
+		failed_tests++; \
+		printf("%s:%d error %pe: " fmt "\n", \
+		       __func__, __LINE__, ERR_PTR(__ret), ##__VA_ARGS__); \
+	} \
+} while (0)
+
+#define expect_success(ret, ...) __expect((ret), ((ret) >= 0), __VA_ARGS__)
+
+static void memtest(void __iomem *start, size_t size, const char *desc)
+{
+	int ret;
+
+	ret = mem_test_bus_integrity((resource_size_t)start,
+				     (resource_size_t)start + size - 1, 0);
+	expect_success(ret, "%s bus test", desc);
+
+	ret = mem_test_moving_inversions((resource_size_t)start,
+					 (resource_size_t)start + size - 1, 0);
+	expect_success(ret, "%s moving inverstions test", desc);
+}
+
+static inline int __check_mirroring(void __iomem *a, void __iomem *b, bool is_mirror,
+				    const char *func, int line)
+{
+	if ((readl(a) == readl(b)) == (is_mirror))
+		return 0;
+
+	printf("%s:%d: mirroring unexpectedly %s: (*%p = 0x%x) %s (*%p = 0x%x)\n", func, line,
+	       is_mirror ? "failed" : "succeeded",
+	       a, readl(a), is_mirror ? "!=" : "==", b, readl(b));
+
+	mmuinfo(a);
+	mmuinfo(b);
+
+	return -EILSEQ;
+}
+
+#define check_mirroring(a, b, is_mirror) \
+	__check_mirroring((a), (b), (is_mirror), __func__, __LINE__)
+
+static void test_remap(void)
+{
+	u8 __iomem *buffer = NULL, *mirror = NULL;
+	phys_addr_t buffer_phys;
+	int i, ret;
+
+	buffer = memalign(SZ_2M, SZ_8M);
+	if (WARN_ON(!buffer))
+		goto out;
+
+	buffer_phys = virt_to_phys(buffer);
+
+	mirror = memalign(SZ_2M, SZ_8M);
+	if (WARN_ON(!mirror))
+		goto out;
+
+	pr_debug("allocated buffer = 0x%p, mirror = 0x%p\n", buffer, mirror);
+
+	memtest(buffer, SZ_8M, "cached buffer");
+	memtest(mirror, SZ_8M, "cached mirror");
+
+	if (__is_defined(ARCH_HAS_REMAP)) {
+		skipped_tests += 10;
+		goto out;
+	}
+
+	ret = remap_range(buffer, SZ_8M, MAP_UNCACHED);
+	memtest(buffer, SZ_8M, "uncached buffer");
+
+	ret = remap_range(mirror, SZ_8M, MAP_UNCACHED);
+	memtest(mirror, SZ_8M, "uncached mirror");
+
+	for (i = 0; i < SZ_8M; i += sizeof(u32)) {
+		int m = i, b = i;
+		writel(0xDEADBEEF, &mirror[m]);
+		writel(i, &buffer[b]);
+		ret = check_mirroring(&mirror[m], &buffer[b], false);
+		if (ret)
+			break;
+	}
+
+	expect_success(ret, "asserting no mirror before remap");
+
+	ret = arch_remap_range(mirror, buffer_phys, SZ_8M, MAP_UNCACHED);
+	expect_success(ret, "remapping with mirroring");
+
+	for (i = 0; i < SZ_8M; i += sizeof(u32)) {
+		int m = i, b = i;
+		writel(0xDEADBEEF, &mirror[m]);
+		writel(i, &buffer[b]);
+		ret = check_mirroring(&mirror[m], &buffer[b], true);
+		if (ret)
+			break;
+	}
+
+	expect_success(ret, "asserting mirroring after remap");
+
+	ret = arch_remap_range(mirror, buffer_phys + SZ_4K, SZ_4M, MAP_UNCACHED);
+	expect_success(ret, "remapping with mirroring (phys += 4K)");
+
+	for (i = 0; i < SZ_4M; i += sizeof(u32)) {
+		int m = i, b = i + SZ_4K;
+		writel(0xDEADBEEF, &mirror[m]);
+		writel(i, &buffer[b]);
+		ret = check_mirroring(&mirror[m], &buffer[b], true);
+		if (ret)
+			break;
+	}
+
+	expect_success(ret, "asserting mirroring after remap (phys += 4K)");
+
+	ret = arch_remap_range(mirror + SZ_4K, buffer_phys, SZ_4M, MAP_UNCACHED);
+	expect_success(ret, "remapping with mirroring (virt += 4K)");
+
+	for (i = 0; i < SZ_4M; i += sizeof(u32)) {
+		int m = i + SZ_4K, b = i;
+		writel(0xDEADBEEF, &mirror[m]);
+		writel(i, &buffer[b]);
+		ret = check_mirroring(&mirror[m], &buffer[b], true);
+		if (ret)
+			break;
+	}
+
+	expect_success(ret, "asserting mirroring after remap (virt += 4K)");
+	return;
+
+	ret = remap_range(buffer, SZ_8M, MAP_DEFAULT);
+	expect_success(ret, "remapping buffer with default attrs");
+	memtest(buffer, SZ_8M, "newly cached buffer");
+
+	ret = remap_range(mirror, SZ_8M, MAP_DEFAULT);
+	expect_success(ret, "remapping mirror with default attrs");
+	memtest(mirror, SZ_8M, "newly cached mirror");
+
+	for (i = 0; i < SZ_8M; i += sizeof(u32)) {
+		int m = i, b = i;
+		writel(0xDEADBEEF, &mirror[m]);
+		writel(i, &buffer[b]);
+		ret = check_mirroring(&mirror[m], &buffer[b], false);
+		if (ret)
+			break;
+	}
+
+	expect_success(ret, "asserting no mirror after remap restore");
+out:
+	free(buffer);
+	free(mirror);
+}
+
+static void test_zero_page(void)
+{
+	void __iomem *null = NULL;
+
+	total_tests += 3;
+
+	if (!IS_ENABLED(CONFIG_ARCH_HAS_DATA_ABORT_MASK)) {
+		pr_info("skipping %s because %s=n\n",
+			"CONFIG_ARCH_HAS_DATA_ABORT_MASK", __func__);
+		skipped_tests += 3;
+		return;
+	}
+
+	OPTIMIZER_HIDE_VAR(null);
+
+	/* Check if *NULL traps and data_abort_mask works */
+
+	data_abort_mask();
+
+	(void)readl(null);
+
+	if (!data_abort_unmask()) {
+		printf("%s: NULL pointer access did not trap\n", __func__);
+		failed_tests++;
+	}
+
+	if (!IS_ENABLED(CONFIG_ARCH_HAS_ZERO_PAGE)) {
+		pr_info("skipping %s because %s=n\n",
+			"CONFIG_ARCH_HAS_ZERO_PAGE", __func__);
+		skipped_tests += 2;
+		return;
+	}
+
+	/* Check if zero_page_access() works */
+
+	data_abort_mask();
+
+	zero_page_access();
+	(void)readl(null);
+	zero_page_faulting();
+
+	if (data_abort_unmask()) {
+		printf("%s: unexpected fault on zero page access\n", __func__);
+		failed_tests++;
+	}
+
+	/* Check if zero_page_faulting() works */
+
+	data_abort_mask();
+
+	(void)readl(null);
+
+	if (!data_abort_unmask()) {
+		printf("%s NULL pointer access did not trap\n", __func__);
+		failed_tests++;
+	}
+}
+
+static void test_mmu(void)
+{
+	test_zero_page();
+	test_remap();
+}
+bselftest(core, test_mmu);
-- 
2.39.2




^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 11/11] ARM: mmuinfo: add options for enabling/disabling zero page trapping
  2023-05-22  5:28 [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000 Ahmad Fatoum
                   ` (9 preceding siblings ...)
  2023-05-22  5:28 ` [PATCH 10/11] test: self: add MMU remapping " Ahmad Fatoum
@ 2023-05-22  5:28 ` Ahmad Fatoum
  2023-05-23  7:21 ` [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000 Sascha Hauer
  11 siblings, 0 replies; 16+ messages in thread
From: Ahmad Fatoum @ 2023-05-22  5:28 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum, lst, rcz

mmuinfo 0 will most likely trigger a translation fault. To allow
decoding the zero page or to allow reading BootROM code at address 0,
teach mmuinfo -z to disable trapping of the zero page and mmuinfo -Z to
reinstate the faulting zero page.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/cpu/mmuinfo.c | 47 ++++++++++++++++++++++++++++++++++++++++--
 include/zero_page.h    | 12 +++++++++++
 2 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/arch/arm/cpu/mmuinfo.c b/arch/arm/cpu/mmuinfo.c
index 413f2f337e95..44d6980a7569 100644
--- a/arch/arm/cpu/mmuinfo.c
+++ b/arch/arm/cpu/mmuinfo.c
@@ -6,8 +6,10 @@
 
 #include <common.h>
 #include <command.h>
+#include <getopt.h>
 #include <asm/mmuinfo.h>
 #include <asm/system_info.h>
+#include <zero_page.h>
 #include <mmu.h>
 
 int mmuinfo(void *addr)
@@ -23,8 +25,40 @@ int mmuinfo(void *addr)
 static __maybe_unused int do_mmuinfo(int argc, char *argv[])
 {
 	unsigned long addr;
+	int access_zero_page = -1;
+	int opt;
 
-	if (argc < 2)
+	while ((opt = getopt(argc, argv, "zZ")) > 0) {
+		switch (opt) {
+		case 'z':
+			access_zero_page = true;
+			break;
+		case 'Z':
+			access_zero_page = false;
+			break;
+		default:
+			return COMMAND_ERROR_USAGE;
+		}
+	}
+
+	if (access_zero_page >= 0) {
+		if (argc - optind != 0)
+			return COMMAND_ERROR_USAGE;
+
+		if (!zero_page_remappable()) {
+			pr_warn("No architecture support for zero page remap\n");
+			return -ENOSYS;
+		}
+
+		if (access_zero_page)
+			zero_page_access();
+		else
+			zero_page_faulting();
+
+		return 0;
+	}
+
+	if (argc - optind != 1)
 		return COMMAND_ERROR_USAGE;
 
 	addr = strtoul_suffix(argv[1], NULL, 0);
@@ -32,11 +66,20 @@ static __maybe_unused int do_mmuinfo(int argc, char *argv[])
 	return mmuinfo((void *)addr);
 }
 
+BAREBOX_CMD_HELP_START(mmuinfo)
+BAREBOX_CMD_HELP_TEXT("Show MMU/cache information using the cp15/model-specific registers.")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-z",  "enable access to zero page")
+BAREBOX_CMD_HELP_OPT ("-Z",  "disable access to zero page")
+BAREBOX_CMD_HELP_END
+
 #ifdef CONFIG_COMMAND_SUPPORT
 BAREBOX_CMD_START(mmuinfo)
 	.cmd            = do_mmuinfo,
 	BAREBOX_CMD_DESC("show MMU/cache information of an address")
-	BAREBOX_CMD_OPTS("ADDRESS")
+	BAREBOX_CMD_OPTS("[-zZ | ADDRESS]")
 	BAREBOX_CMD_GROUP(CMD_GRP_INFO)
+	BAREBOX_CMD_HELP(cmd_mmuinfo_help)
 BAREBOX_CMD_END
 #endif
diff --git a/include/zero_page.h b/include/zero_page.h
index a71c0e0b8733..79e0f22c7b5b 100644
--- a/include/zero_page.h
+++ b/include/zero_page.h
@@ -20,6 +20,13 @@ void zero_page_faulting(void);
  */
 void zero_page_access(void);
 
+void zero_page_access(void);
+
+static inline bool zero_page_remappable(void)
+{
+	return true;
+}
+
 #else
 
 static inline void zero_page_faulting(void)
@@ -30,6 +37,11 @@ static inline void zero_page_access(void)
 {
 }
 
+static inline bool zero_page_remappable(void)
+{
+	return false;
+}
+
 #endif
 
 static inline bool zero_page_contains(unsigned long addr)
-- 
2.39.2




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 02/11] mmu: add physical address parameter to arch_remap_range
  2023-05-22  5:28 ` [PATCH 02/11] mmu: add physical address parameter to arch_remap_range Ahmad Fatoum
@ 2023-05-23  7:17   ` Sascha Hauer
  2023-05-23  7:21     ` Ahmad Fatoum
  0 siblings, 1 reply; 16+ messages in thread
From: Sascha Hauer @ 2023-05-23  7:17 UTC (permalink / raw)
  To: Ahmad Fatoum; +Cc: barebox, lst, rcz

On Mon, May 22, 2023 at 07:28:26AM +0200, Ahmad Fatoum wrote:
> ARM32 has map_io_sections for non-1:1 remapping, but it's limited to 1M
> sections.  arch_remap_range has newly gained support for 4K granularity
> remapping, but supports only changing attributes and no non-1:1
> remapping yet. In preparation for adding this missing feature, adjust
> the prototype.
> 
> No functional change.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> ---
>  arch/arm/cpu/mmu_32.c          | 25 ++++++++++++++-----------
>  arch/arm/cpu/mmu_64.c          |  8 +++++---
>  arch/arm/include/asm/mmu.h     |  2 +-
>  arch/powerpc/cpu-85xx/mmu.c    |  7 +++++--
>  arch/powerpc/include/asm/mmu.h |  2 +-
>  include/mmu.h                  |  9 ++++++---
>  6 files changed, 32 insertions(+), 21 deletions(-)
> 
> diff --git a/arch/arm/cpu/mmu_32.c b/arch/arm/cpu/mmu_32.c
> index e4607d99fd2a..68336fc68be0 100644
> --- a/arch/arm/cpu/mmu_32.c
> +++ b/arch/arm/cpu/mmu_32.c
> @@ -253,20 +253,23 @@ static uint32_t get_pmd_flags(int map_type)
>  	return pte_flags_to_pmd(get_pte_flags(map_type));
>  }
>  
> -int arch_remap_range(void *start, size_t size, unsigned map_type)
> +int arch_remap_range(void *_virt_addr, phys_addr_t phys_addr, size_t size, unsigned map_type)

The prototype is changed here, but not its caller in the same file.
Fixed that up.

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 02/11] mmu: add physical address parameter to arch_remap_range
  2023-05-23  7:17   ` Sascha Hauer
@ 2023-05-23  7:21     ` Ahmad Fatoum
  2023-05-23  7:27       ` Sascha Hauer
  0 siblings, 1 reply; 16+ messages in thread
From: Ahmad Fatoum @ 2023-05-23  7:21 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox, lst, rcz

On 23.05.23 09:17, Sascha Hauer wrote:
> On Mon, May 22, 2023 at 07:28:26AM +0200, Ahmad Fatoum wrote:
>> ARM32 has map_io_sections for non-1:1 remapping, but it's limited to 1M
>> sections.  arch_remap_range has newly gained support for 4K granularity
>> remapping, but supports only changing attributes and no non-1:1
>> remapping yet. In preparation for adding this missing feature, adjust
>> the prototype.
>>
>> No functional change.
>>
>> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
>> ---
>>  arch/arm/cpu/mmu_32.c          | 25 ++++++++++++++-----------
>>  arch/arm/cpu/mmu_64.c          |  8 +++++---
>>  arch/arm/include/asm/mmu.h     |  2 +-
>>  arch/powerpc/cpu-85xx/mmu.c    |  7 +++++--
>>  arch/powerpc/include/asm/mmu.h |  2 +-
>>  include/mmu.h                  |  9 ++++++---
>>  6 files changed, 32 insertions(+), 21 deletions(-)
>>
>> diff --git a/arch/arm/cpu/mmu_32.c b/arch/arm/cpu/mmu_32.c
>> index e4607d99fd2a..68336fc68be0 100644
>> --- a/arch/arm/cpu/mmu_32.c
>> +++ b/arch/arm/cpu/mmu_32.c
>> @@ -253,20 +253,23 @@ static uint32_t get_pmd_flags(int map_type)
>>  	return pte_flags_to_pmd(get_pte_flags(map_type));
>>  }
>>  
>> -int arch_remap_range(void *start, size_t size, unsigned map_type)
>> +int arch_remap_range(void *_virt_addr, phys_addr_t phys_addr, size_t size, unsigned map_type)
> 
> The prototype is changed here, but not its caller in the same file.
> Fixed that up.

I don't have a caller in the same file. Everything should have been switched
to remap_range by now, except for remap_range's implementation itself.

If you added another arch_remap_range callsite in your MMU patches, please
change it on the previous commit.

> 
> Sascha
> 
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000
  2023-05-22  5:28 [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000 Ahmad Fatoum
                   ` (10 preceding siblings ...)
  2023-05-22  5:28 ` [PATCH 11/11] ARM: mmuinfo: add options for enabling/disabling zero page trapping Ahmad Fatoum
@ 2023-05-23  7:21 ` Sascha Hauer
  11 siblings, 0 replies; 16+ messages in thread
From: Sascha Hauer @ 2023-05-23  7:21 UTC (permalink / raw)
  To: Ahmad Fatoum; +Cc: barebox, lst, rcz

On Mon, May 22, 2023 at 07:28:24AM +0200, Ahmad Fatoum wrote:
> When MMU is enabled, barebox maintains a single address space with
> 1:1 physical to virtual mapping by default. Furthermore, the zero
> page is marked inaccessible to trap NULL pointer dereferences.
> 
> This is problematic on the Qemu ARM Virt platform, because the
> cfi-flash is memory mapped starting with address zero, so users need
> to decide whether they want the cfi-flash or the MMU. The decision
> so far, was to disable CONFIG_MMU in the Qemu Virt configs, but this
> holds us back from removing these configs in favor of the new
> multi_v7_defconfig/multi_v8_defconfig.
> 
> Make everyone happy by shifting the virtual cfi-flash mapping by 4K:
> 
>     virt   ->    phys
> 
>     0x0000 ->    0x0000 [faulting]
>     0x1000 ->    0x0000 [(uncached) alias]
>     0x2000 ->    0x1000
>            .
>            .
>            .
>  0x7fff000 -> 0x7ffe000
>  0x8000000 -> 0x7fff000
> 
> This eats one page into the memory region starting at 0x8000000.
> That's ok though, because that's where the GIC is located on both
> ARM32 and ARM64 and we don't do interrupts in barebox.
> 
> This applies on top of Sascha's MMU rempping rework in next and
> has been tested on both 32-bit and 64-bit QEMU ARM.

Applied, thanks

Sascha

> 
> Ahmad Fatoum (11):
>   treewide: use remap_range instead of arch_remap_range
>   mmu: add physical address parameter to arch_remap_range
>   ARM: mmu32: support non-1:1 mappings in arch_remap_range
>   ARM: mmu64: support non-1:1 mappings in arch_remap_range
>   of: platform: remap memory when encountering virtual-reg property
>   common: boards: qemu-virt: remap cfi-flash from 0 to 0x1000
>   ARM: prepare extending mmuinfo beyond ARMv7
>   ARM64: mmu: implement ARMv8 mmuinfo command
>   common: memtest: prepare for reuse in self test
>   test: self: add MMU remapping self test
>   ARM: mmuinfo: add options for enabling/disabling zero page trapping
> 
>  .../bindings/barebox/virtual-reg.rst          |  29 +++
>  arch/arm/configs/multi_v8_defconfig           |   1 +
>  arch/arm/cpu/Makefile                         |   2 +-
>  arch/arm/cpu/mmu-common.c                     |   8 +-
>  arch/arm/cpu/mmu_32.c                         |  54 ++--
>  arch/arm/cpu/mmu_64.c                         |  18 +-
>  arch/arm/cpu/mmuinfo.c                        | 128 +++++-----
>  arch/arm/cpu/mmuinfo_32.c                     |  80 ++++++
>  arch/arm/cpu/mmuinfo_64.c                     | 215 ++++++++++++++++
>  arch/arm/include/asm/mmu.h                    |   2 +-
>  arch/arm/include/asm/mmuinfo.h                |   9 +
>  arch/arm/include/asm/sysreg.h                 |  76 ++++++
>  arch/powerpc/cpu-85xx/mmu.c                   |   7 +-
>  arch/powerpc/include/asm/mmu.h                |   2 +-
>  commands/Kconfig                              |   8 +-
>  commands/memtest.c                            |   5 +-
>  common/Kconfig                                |   6 +
>  common/Makefile                               |   2 +-
>  common/boards/qemu-virt/Makefile              |   3 +
>  common/boards/qemu-virt/overlay-of-flash.dts  |   5 +-
>  common/memtest.c                              |  44 ++--
>  drivers/hab/habv4.c                           |   2 +-
>  drivers/mtd/nor/cfi_flash.c                   |   5 +-
>  drivers/of/platform.c                         |  20 ++
>  include/memtest.h                             |   7 +-
>  include/mmu.h                                 |  19 +-
>  include/zero_page.h                           |  12 +
>  test/self/Kconfig                             |   6 +
>  test/self/Makefile                            |   1 +
>  test/self/mmu.c                               | 233 ++++++++++++++++++
>  30 files changed, 865 insertions(+), 144 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/barebox/virtual-reg.rst
>  create mode 100644 arch/arm/cpu/mmuinfo_32.c
>  create mode 100644 arch/arm/cpu/mmuinfo_64.c
>  create mode 100644 arch/arm/include/asm/mmuinfo.h
>  create mode 100644 arch/arm/include/asm/sysreg.h
>  create mode 100644 test/self/mmu.c
> 
> -- 
> 2.39.2
> 
> 
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 02/11] mmu: add physical address parameter to arch_remap_range
  2023-05-23  7:21     ` Ahmad Fatoum
@ 2023-05-23  7:27       ` Sascha Hauer
  0 siblings, 0 replies; 16+ messages in thread
From: Sascha Hauer @ 2023-05-23  7:27 UTC (permalink / raw)
  To: Ahmad Fatoum; +Cc: barebox, lst, rcz

On Tue, May 23, 2023 at 09:21:03AM +0200, Ahmad Fatoum wrote:
> On 23.05.23 09:17, Sascha Hauer wrote:
> > On Mon, May 22, 2023 at 07:28:26AM +0200, Ahmad Fatoum wrote:
> >> ARM32 has map_io_sections for non-1:1 remapping, but it's limited to 1M
> >> sections.  arch_remap_range has newly gained support for 4K granularity
> >> remapping, but supports only changing attributes and no non-1:1
> >> remapping yet. In preparation for adding this missing feature, adjust
> >> the prototype.
> >>
> >> No functional change.
> >>
> >> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> >> ---
> >>  arch/arm/cpu/mmu_32.c          | 25 ++++++++++++++-----------
> >>  arch/arm/cpu/mmu_64.c          |  8 +++++---
> >>  arch/arm/include/asm/mmu.h     |  2 +-
> >>  arch/powerpc/cpu-85xx/mmu.c    |  7 +++++--
> >>  arch/powerpc/include/asm/mmu.h |  2 +-
> >>  include/mmu.h                  |  9 ++++++---
> >>  6 files changed, 32 insertions(+), 21 deletions(-)
> >>
> >> diff --git a/arch/arm/cpu/mmu_32.c b/arch/arm/cpu/mmu_32.c
> >> index e4607d99fd2a..68336fc68be0 100644
> >> --- a/arch/arm/cpu/mmu_32.c
> >> +++ b/arch/arm/cpu/mmu_32.c
> >> @@ -253,20 +253,23 @@ static uint32_t get_pmd_flags(int map_type)
> >>  	return pte_flags_to_pmd(get_pte_flags(map_type));
> >>  }
> >>  
> >> -int arch_remap_range(void *start, size_t size, unsigned map_type)
> >> +int arch_remap_range(void *_virt_addr, phys_addr_t phys_addr, size_t size, unsigned map_type)
> > 
> > The prototype is changed here, but not its caller in the same file.
> > Fixed that up.
> 
> I don't have a caller in the same file. Everything should have been switched
> to remap_range by now, except for remap_range's implementation itself.
> 
> If you added another arch_remap_range callsite in your MMU patches, please
> change it on the previous commit.

Yes, right. I changed that.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2023-05-23  7:28 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-22  5:28 [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000 Ahmad Fatoum
2023-05-22  5:28 ` [PATCH 01/11] treewide: use remap_range instead of arch_remap_range Ahmad Fatoum
2023-05-22  5:28 ` [PATCH 02/11] mmu: add physical address parameter to arch_remap_range Ahmad Fatoum
2023-05-23  7:17   ` Sascha Hauer
2023-05-23  7:21     ` Ahmad Fatoum
2023-05-23  7:27       ` Sascha Hauer
2023-05-22  5:28 ` [PATCH 03/11] ARM: mmu32: support non-1:1 mappings in arch_remap_range Ahmad Fatoum
2023-05-22  5:28 ` [PATCH 04/11] ARM: mmu64: " Ahmad Fatoum
2023-05-22  5:28 ` [PATCH 05/11] of: platform: remap memory when encountering virtual-reg property Ahmad Fatoum
2023-05-22  5:28 ` [PATCH 06/11] common: boards: qemu-virt: remap cfi-flash from 0 to 0x1000 Ahmad Fatoum
2023-05-22  5:28 ` [PATCH 07/11] ARM: prepare extending mmuinfo beyond ARMv7 Ahmad Fatoum
2023-05-22  5:28 ` [PATCH 08/11] ARM64: mmu: implement ARMv8 mmuinfo command Ahmad Fatoum
2023-05-22  5:28 ` [PATCH 09/11] common: memtest: prepare for reuse in self test Ahmad Fatoum
2023-05-22  5:28 ` [PATCH 10/11] test: self: add MMU remapping " Ahmad Fatoum
2023-05-22  5:28 ` [PATCH 11/11] ARM: mmuinfo: add options for enabling/disabling zero page trapping Ahmad Fatoum
2023-05-23  7:21 ` [PATCH 00/11] ARM: qemu-virt: remap cfi-flash from 0 to 0x1000 Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox