Skip to contentSkip to conversation

ARM: P2V: introduce phys_to_virt/virt_to_phys runtime patching

RFC In review Russell King - ARM Linux 2 participants 5 messages Jan 18, 2011 – Feb 7, 2011

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

RFC 4/5 ARM: P2V: introduce phys_to_virt/virt_to_phys runtime patching

A warning for OMAP.

Your use of the __virt_to_phys() in assembly code for the debug stuff will break with this patch... please ensure that it is resolved by the next merge window.

----- Forwarded message from Russell King - ARM Linux <[email protected]> -----

Date: Tue, 04 Jan 2011 20:23:18 +0000
From: Russell King - ARM Linux <[email protected]>
To: Nicolas Pitre <[email protected]>
Cc: [email protected]
Subject: [RFC 4/5] ARM: P2V: introduce phys_to_virt/virt_to_phys runtime
patching

This idea came from Nicolas, Eric Miao produced an initial version, which was then rewritten into this.

Patch the physical to virtual translations at runtime. As we modify the code, this makes it incompatible with XIP kernels, but on allows is to achieve this with minimal loss of performance.

As many translations are of the form:

physical = virtual + (PHYS_OFFSET - PAGE_OFFSET) virtual = physical - (PHYS_OFFSET - PAGE_OFFSET)

we generate an 'add' instruction for __virt_to_phys(), and a 'sub' instruction for __phys_to_virt(). We calculate at run time (PHYS_OFFSET
- PAGE_OFFSET) by comparing the address prior to MMU initialization with where it should be once the MMU has been initialized, and place this constant into the above add/sub instructions.

Once we have (PHYS_OFFSET - PAGE_OFFSET), we can calcuate the real PHYS_OFFSET as PAGE_OFFSET is a build-time constant, and save this for the C-mode PHYS_OFFSET variable definition to use.

At present, we are unable to support Realview with Sparsemem enabled as this uses a complex mapping function, and MSM as this requires a constant which will not fit in our math instruction.

---
 arch/arm/Kconfig              |   14 +++++++++
 arch/arm/include/asm/memory.h |   55 ++++++++++++++++++++++++++++--------
 arch/arm/kernel/head.S        |   63 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/kernel/module.c      |   23 ++++++++++++++-
 arch/arm/kernel/setup.c       |    2 +-
 arch/arm/kernel/vmlinux.lds.S |    4 ++
 6 files changed, 147 insertions(+), 14 deletions(-)
arch/arm/Kconfig +14 -0
index 7b155b0..801192b 100644
@@ -196,6 +196,19 @@ config VECTORS_BASE
 	help
 	  The base address of exception vectors.
 
+config ARM_PATCH_PHYS_VIRT
+	bool "Patch physical to virtual translations at runtime (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	depends on !XIP_KERNEL && !THUMB2_KERNEL && MMU
+	depends on !ARCH_MSM
+	depends on !ARCH_REALVIEW || !SPARSEMEM
+	help
+	  Patch phys-to-virt translation functions at runtime according to
+	  the position of the kernel in system memory.
+
+	  This can only be used with non-XIP, non-Thumb2, MMU kernels where
+	  the base of physical memory is at a 16MB boundary.
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
@@ -608,6 +621,7 @@ config ARCH_PXA
 	select TICK_ONESHOT
 	select PLAT_PXA
 	select SPARSE_IRQ
+	select ARM_PATCH_PHYS_VIRT
 	help
 	  Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
 
arch/arm/include/asm/memory.h +43 -12

73 lines not on this page · raw message

arch/arm/kernel/head.S +63 -0

73 lines not on this page · raw message

arch/arm/kernel/module.c +22 -1
index 0c1bb68..6a42e17 100644
@@ -276,12 +276,28 @@ struct mod_unwind_map {
 	const Elf_Shdr *txt_sec;
 };
 
+static const Elf_Shdr *find_mod_section(const Elf32_Ehdr *hdr,
+	const Elf_Shdr *sechdrs, const char *name)
+{
+	const Elf_Shdr *s, *se;
+	const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+	for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++)
+		if (strcmp(name, secstrs + s->sh_name) == 0)
+			return s;
+
+	return NULL;
+}
+
+extern void fixup_pv_table(const void *, unsigned long);
+
 int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
 		    struct module *mod)
 {
+	const Elf_Shdr *s = NULL;
 #ifdef CONFIG_ARM_UNWIND
 	const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
-	const Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
+	const Elf_Shdr *sechdrs_end = sechdrs + hdr->e_shnum;
 	struct mod_unwind_map maps[ARM_SEC_MAX];
 	int i;
 
@@ -323,6 +339,11 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
 					         maps[i].txt_sec->sh_addr,
 					         maps[i].txt_sec->sh_size);
 #endif
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
+	s = find_mod_section(hdr, sechdrs, ".pv_table");
+	if (s)
+		fixup_pv_table((void *)s->sh_addr, s->sh_size);
+#endif
 	return 0;
 }
 
arch/arm/kernel/setup.c +1 -1
index f67e682..7c5499d 100644
@@ -804,7 +804,7 @@ void __init setup_arch(char **cmdline_p)
 	struct machine_desc *mdesc;
 	char *from = default_command_line;
 
-	tags->mem.start = PHYS_OFFSET;
+	init_tags.mem.start = PHYS_OFFSET;
 
 	unwind_init();
 
arch/arm/kernel/vmlinux.lds.S +4 -0
index 86b66f3..45b5651 100644
@@ -57,6 +57,10 @@ SECTIONS
 		__smpalt_end = .;
 #endif
 
+		__pv_table_begin = .;
+			*(.pv_table)
+		__pv_table_end = .;
+
 		INIT_SETUP(16)
 
 		INIT_CALLS
Signature · 1 line
1.6.2.5
maintainer
#1 lore raw
Quoted 5 lines · Russell King - ARM Linux

A warning for OMAP.

Your use of the __virt_to_phys() in assembly code for the debug stuff will break with this patch... please ensure that it is resolved by the next merge window.

Sure thanks. I'm aware of this series, will take care of it.

Tony

maintainer
#2 lore raw

PATCH 1/1 omap: Fix DEBUG_LL code for p2v changes (Re: Fwd: [RFC 4/5] ARM: P2V: introduce phys_to_virt/virt_to_phys runtime patching)

Quoted 8 lines · Tony Lindgren
Quoted 5 lines · Russell King - ARM Linux

A warning for OMAP.

Your use of the __virt_to_phys() in assembly code for the debug stuff will break with this patch... please ensure that it is resolved by the next merge window.

Sure thanks. I'm aware of this series, will take care of it.

Here's a minimal fix for your p2v branch. Will send more DEBUG_LL related patches in a separate series.

Regards,

Tony

From: Tony Lindgren <[email protected]>
Date: Thu, 3 Feb 2011 15:17:44 -0800
Subject: [PATCH] omap: Fix DEBUG_LL code for p2v changes

These are needed for CONFIG_ARM_PATCH_PHYS_VIRT to work.

arch/arm/mach-omap1/include/mach/debug-macro.S +6 -3
@@ -17,6 +17,9 @@
 
 #include <plat/serial.h>
 
+#define omap_uart_v2p(x)	((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET)
+#define omap_uart_p2v(x)	((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET)
+
 		.pushsection .data
 omap_uart_phys:	.word	0x0
 omap_uart_virt:	.word	0x0
@@ -33,7 +36,7 @@ omap_uart_virt:	.word	0x0
 		/* Use omap_uart_phys/virt if already configured */
 9:		mrc	p15, 0, \rp, c1, c0
 		tst	\rp, #1			@ MMU enabled?
-		ldreq	\rp, =__virt_to_phys(omap_uart_phys)	@ MMU not enabled
+		ldreq	\rp, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
 		ldrne	\rp, =omap_uart_phys	@ MMU enabled
 		add	\rv, \rp, #4		@ omap_uart_virt
 		ldr	\rp, [\rp, #0]
@@ -46,7 +49,7 @@ omap_uart_virt:	.word	0x0
 		mrc	p15, 0, \rp, c1, c0
 		tst	\rp, #1			@ MMU enabled?
 		ldreq	\rp, =OMAP_UART_INFO	@ MMU not enabled
-		ldrne	\rp, =__phys_to_virt(OMAP_UART_INFO)	@ MMU enabled
+		ldrne	\rp, =omap_uart_p2v(OMAP_UART_INFO)	@ MMU enabled
 		ldr	\rp, [\rp, #0]
 
 		/* Select the UART to use based on the UART1 scratchpad value */
@@ -73,7 +76,7 @@ omap_uart_virt:	.word	0x0
 98:		add	\rp, \rp, #0xff000000	@ phys base
 		mrc	p15, 0, \rv, c1, c0
 		tst	\rv, #1			@ MMU enabled?
-		ldreq	\rv, =__virt_to_phys(omap_uart_phys)	@ MMU not enabled
+		ldreq	\rv, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
 		ldrne	\rv, =omap_uart_phys	@ MMU enabled
 		str	\rp, [\rv, #0]
 		sub	\rp, \rp, #0xff000000	@ phys base
arch/arm/mach-omap2/include/mach/debug-macro.S +8 -5
@@ -19,6 +19,9 @@
 
 #define UART_OFFSET(addr)	((addr) & 0x00ffffff)
 
+#define omap_uart_v2p(x)	((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET)
+#define omap_uart_p2v(x)	((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET)
+
 		.pushsection .data
 omap_uart_phys:	.word	0
 omap_uart_virt:	.word	0
@@ -36,7 +39,7 @@ omap_uart_lsr:	.word	0
 		/* Use omap_uart_phys/virt if already configured */
 10:		mrc	p15, 0, \rp, c1, c0
 		tst	\rp, #1			@ MMU enabled?
-		ldreq	\rp, =__virt_to_phys(omap_uart_phys)	@ MMU not enabled
+		ldreq	\rp, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
 		ldrne	\rp, =omap_uart_phys	@ MMU enabled
 		add	\rv, \rp, #4		@ omap_uart_virt
 		ldr	\rp, [\rp, #0]
@@ -49,7 +52,7 @@ omap_uart_lsr:	.word	0
 		mrc	p15, 0, \rp, c1, c0
 		tst	\rp, #1			@ MMU enabled?
 		ldreq	\rp, =OMAP_UART_INFO	@ MMU not enabled
-		ldrne	\rp, =__phys_to_virt(OMAP_UART_INFO)	@ MMU enabled
+		ldrne	\rp, =omap_uart_p2v(OMAP_UART_INFO)	@ MMU enabled
 		ldr	\rp, [\rp, #0]
 
 		/* Select the UART to use based on the UART1 scratchpad value */
@@ -94,7 +97,7 @@ omap_uart_lsr:	.word	0
 95:		ldr	\rp, =ZOOM_UART_BASE
 		mrc	p15, 0, \rv, c1, c0
 		tst	\rv, #1			@ MMU enabled?
-		ldreq	\rv, =__virt_to_phys(omap_uart_phys)	@ MMU not enabled
+		ldreq	\rv, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
 		ldrne	\rv, =omap_uart_phys	@ MMU enabled
 		str	\rp, [\rv, #0]
 		ldr	\rp, =ZOOM_UART_VIRT
@@ -109,7 +112,7 @@ omap_uart_lsr:	.word	0
 98:		add	\rp, \rp, #0x48000000	@ phys base
 		mrc	p15, 0, \rv, c1, c0
 		tst	\rv, #1			@ MMU enabled?
-		ldreq	\rv, =__virt_to_phys(omap_uart_phys)	@ MMU not enabled
+		ldreq	\rv, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
 		ldrne	\rv, =omap_uart_phys	@ MMU enabled
 		str	\rp, [\rv, #0]
 		sub	\rp, \rp, #0x48000000	@ phys base
@@ -131,7 +134,7 @@ omap_uart_lsr:	.word	0
 		.macro	busyuart,rd,rx
 1001:		mrc	p15, 0, \rd, c1, c0
 		tst	\rd, #1			@ MMU enabled?
-		ldreq	\rd, =__virt_to_phys(omap_uart_lsr)	@ MMU not enabled
+		ldreq	\rd, =omap_uart_v2p(omap_uart_lsr)	@ MMU disabled
 		ldrne	\rd, =omap_uart_lsr	@ MMU enabled
 		ldr	\rd, [\rd, #0]
 		ldrb	\rd, [\rx, \rd]
#3 lore raw

Re: [PATCH] omap: Fix DEBUG_LL code for p2v changes (Re: Fwd: [RFC 4/5] ARM: P2V: introduce phys_to_virt/virt_to_phys runtime patching)

Quoted 4 lines · Tony Lindgren
Quoted 3 lines · Tony Lindgren
Quoted 2 lines · Russell King - ARM Linux

A warning for OMAP.

Quoted 8 lines
Quoted 5 lines
Quoted 3 lines

Your use of the __virt_to_phys() in assembly code for the debug stuff will break with this patch... please ensure that it is resolved by the next merge window.

Sure thanks. I'm aware of this series, will take care of it.

Here's a minimal fix for your p2v branch. Will send more DEBUG_LL related patches in a separate series.

Could you please provide some acks/tested bys for the p2v stuff?

Thanks.

maintainer
#4 lore raw

Re: [PATCH] omap: Fix DEBUG_LL code for p2v changes (Re: Fwd: [RFC 4/5] ARM: P2V: introduce phys_to_virt/virt_to_phys runtime patching)

Quoted 9 lines · Russell King - ARM Linux
Quoted 8 lines · Tony Lindgren
Quoted 7 lines · Tony Lindgren
Quoted 5 lines · Russell King - ARM Linux

A warning for OMAP.

Your use of the __virt_to_phys() in assembly code for the debug stuff will break with this patch... please ensure that it is resolved by the next merge window.

Quoted 6 lines
Quoted 4 lines
Quoted 1 line

Sure thanks. I'm aware of this series, will take care of it.

Here's a minimal fix for your p2v branch. Will send more DEBUG_LL related patches in a separate series.

Could you please provide some acks/tested bys for the p2v stuff?

Sorry was out of town for the weekend, will reply with acks.

Tony