This series is a refreshed subset of the Keystone platform patches posted
earlier (see [1] and [2]). In this series, we've dropped the Keystone
sub-architecture patches, which have remained largely unchanged from before,
and were being provided only for reference. The focus with this series is
to get these LPAE related changes queued up.
These patches have been rebased and verified against linux-next-20120910.
These patches are also available in git:
git://git.kernel.org/pub/scm/linux/kernel/git/cchemparathy/linux-keystone.git upstream/keystone-lpae-v3
[1] http://comments.gmane.org/gmane.linux.kernel/1341497
[2] http://comments.gmane.org/gmane.linux.kernel/1332069
Series changelog:
(01/22) ARM: add mechanism for late code patching
(v3) ability to patch multiple sequential instructions with the IMM8 patch
type
(v3) error handling at module patch time
(v3) reuse __patch_text() from kprobes code
(v2) pulled runtime patching code into separate source files
(v2) reordered arguments to patch macros for consistency with assembly
"Rd, Rt, imm" ordering
(v2) added support for mov immediate patching
(v2) cache flush patched instructions instead of entire kernel code
(v2) pack patch table to reduce table volume
(v2) add to module vermagic to reflect abi change
(v2) misc. cleanups in naming and structure
(02/22) ARM: add self test for runtime patch mechanism
(v3) added tests for both even and odd shifts of immediate values
(v2) added init-time tests to verify instruction encoding
(03/22) ARM: use late patch framework for phys-virt patching
(v3) fixed commit description for unconditional init of __pv_* symbols
(v2) move __pv_offset and __pv_phys_offset to C code
(v2) restore conditional init of __pv_offset and __pv_phys_offset
(04/22) ARM: LPAE: use phys_addr_t on virt <--> phys conversion
(v3) unchanged from v2
(v2) fix patched __phys_to_virt() to use 32-bit operand
(v2) convert non-patch __phys_to_virt and __virt_to_phys to inlines to retain
type checking
(05/22) ARM: LPAE: support 64-bit virt_to_phys patching
(v3) added explicit patch stub for 64-bit to clean up compiler generated
code, both 64-bit and 32-bit cases generate optimal code with this
(v2) use phys_addr_t instead of split high/low phys_offsets
(v2) use mov immediate instead of add to zero when patching in high order
physical address bits
(v2) fix __pv_phys_offset handling for big-endian
(v2) remove set_phys_offset()
(06/22) ARM: LPAE: use signed arithmetic for mask definitions
(07/22) ARM: LPAE: use phys_addr_t in alloc_init_pud()
(08/22) ARM: LPAE: use phys_addr_t in free_memmap()
(v3) unchanged from v2
(v2) unchanged from v1
(09/22) ARM: LPAE: use phys_addr_t for initrd location and size
(v3) unchanged from v2
(v2) revert to unsigned long for initrd size
(10/22) ARM: LPAE: use phys_addr_t in switch_mm()
(v3) remove unnecessary handling for !LPAE in proc-v7-3level
(v2) use phys_addr_t instead of u64 in switch_mm()
(v2) revert on changes to v6 and v7-2level
(v2) fix register mapping for big-endian in v7-3level
(11/22) ARM: LPAE: use 64-bit accessors for TTBR registers
(v3) remove unnecessary condition code clobber
(v2) restore comment in cpu_set_reserved_ttbr0()
(12/22) ARM: LPAE: define ARCH_LOW_ADDRESS_LIMIT for bootmem
(13/22) ARM: LPAE: factor out T1SZ and TTBR1 computations
(v3) unchanged from v2
(v2) unchanged from v1
(14/22) ARM: LPAE: accomodate >32-bit addresses for page table base
(v3) unchanged from v2
(v2) apply arch_pgd_shift only on lpae
(v2) move arch_pgd_shift definition to asm/memory.h
(v2) revert on changes to non-lpae procs
(v2) add check to ensure that the pgd physical address is aligned at an
ARCH_PGD_SHIFT boundary
(15/22) ARM: mm: use physical addresses in highmem sanity checks
(16/22) ARM: mm: cleanup checks for membank overlap with vmalloc area
(17/22) ARM: mm: clean up membank size limit checks
(v3) unchanged from v2
(v2) unchanged from v1
Cyril Chemparathy (14):
ARM: add mechanism for late code patching
ARM: add self test for runtime patch mechanism
ARM: use late patch framework for phys-virt patching
ARM: LPAE: use phys_addr_t on virt <--> phys conversion
ARM: LPAE: support 64-bit virt_to_phys patching
ARM: LPAE: use signed arithmetic for mask definitions
ARM: LPAE: use phys_addr_t in switch_mm()
ARM: LPAE: use 64-bit accessors for TTBR registers
ARM: LPAE: define ARCH_LOW_ADDRESS_LIMIT for bootmem
ARM: LPAE: factor out T1SZ and TTBR1 computations
ARM: LPAE: accomodate >32-bit addresses for page table base
ARM: mm: use physical addresses in highmem sanity checks
ARM: mm: cleanup checks for membank overlap with vmalloc area
ARM: mm: clean up membank size limit checks
Vitaly Andrianov (3):
ARM: LPAE: use phys_addr_t in alloc_init_pud()
ARM: LPAE: use phys_addr_t in free_memmap()
ARM: LPAE: use phys_addr_t for initrd location and size
arch/arm/Kconfig | 16 ++
arch/arm/include/asm/memory.h | 101 +++++++---
arch/arm/include/asm/module.h | 7 +
arch/arm/include/asm/page.h | 2 +-
arch/arm/include/asm/pgtable-3level-hwdef.h | 10 +
arch/arm/include/asm/pgtable-3level.h | 6 +-
arch/arm/include/asm/proc-fns.h | 28 ++-
arch/arm/include/asm/runtime-patch.h | 208 +++++++++++++++++++++
arch/arm/kernel/Makefile | 1 +
arch/arm/kernel/armksyms.c | 4 -
arch/arm/kernel/head.S | 107 +++--------
arch/arm/kernel/module.c | 14 +-
arch/arm/kernel/runtime-patch.c | 268 +++++++++++++++++++++++++++
arch/arm/kernel/setup.c | 15 ++
arch/arm/kernel/smp.c | 11 +-
arch/arm/kernel/vmlinux.lds.S | 13 +-
arch/arm/mm/context.c | 9 +-
arch/arm/mm/init.c | 19 +-
arch/arm/mm/mmu.c | 49 ++---
arch/arm/mm/proc-v7-3level.S | 41 ++--
20 files changed, 728 insertions(+), 201 deletions(-)
create mode 100644 arch/arm/include/asm/runtime-patch.h
create mode 100644 arch/arm/kernel/runtime-patch.c
--
1.7.9.5
This patch adds an architecture defined override for ARCH_LOW_ADDRESS_LIMIT.
On PAE systems, the absence of this override causes bootmem to incorrectly
limit itself to 32-bit addressable physical memory.
Signed-off-by: Cyril Chemparathy <redacted>
Signed-off-by: Vitaly Andrianov <redacted>
---
arch/arm/include/asm/memory.h | 2 ++
1 file changed, 2 insertions(+)
This patch adds TTBR accessor macros, and modifies cpu_get_pgd() and
the LPAE version of cpu_set_reserved_ttbr0() to use these instead.
In the process, we also fix these functions to correctly handle cases
where the physical address lies beyond the 4G limit of 32-bit addressing.
Signed-off-by: Cyril Chemparathy <redacted>
Signed-off-by: Vitaly Andrianov <redacted>
Acked-by: Nicolas Pitre <redacted>
---
arch/arm/include/asm/proc-fns.h | 24 +++++++++++++++++++-----
arch/arm/mm/context.c | 9 ++-------
2 files changed, 21 insertions(+), 12 deletions(-)
From: Vitaly Andrianov <redacted>
The free_memmap() was mistakenly using unsigned long type to represent
physical addresses. This breaks on PAE systems where memory could be placed
above the 32-bit addressible limit.
This patch fixes this function to properly use phys_addr_t instead.
Signed-off-by: Vitaly Andrianov <redacted>
Signed-off-by: Cyril Chemparathy <redacted>
Acked-by: Nicolas Pitre <redacted>
---
arch/arm/mm/init.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
@@ -469,8 +469,8 @@ free_memmap(unsigned long start_pfn, unsigned long end_pfn)*Converttophysicaladdresses,and*roundstartupwardsandenddownwards.*/-pg=(unsignedlong)PAGE_ALIGN(__pa(start_pg));-pgend=(unsignedlong)__pa(end_pg)&PAGE_MASK;+pg=PAGE_ALIGN(__pa(start_pg));+pgend=__pa(end_pg)&PAGE_MASK;/**Iftherearefreepagesbetweenthese,
This patch fixes up the types used when converting back and forth between
physical and virtual addresses.
Signed-off-by: Vitaly Andrianov <redacted>
Signed-off-by: Cyril Chemparathy <redacted>
Reviewed-by: Nicolas Pitre <redacted>
---
arch/arm/include/asm/memory.h | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
From: Vitaly Andrianov <redacted>
This patch fixes the initrd setup code to use phys_addr_t instead of assuming
32-bit addressing. Without this we cannot boot on systems where initrd is
located above the 4G physical address limit.
Signed-off-by: Vitaly Andrianov <redacted>
Signed-off-by: Cyril Chemparathy <redacted>
Acked-by: Nicolas Pitre <redacted>
---
arch/arm/mm/init.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
@@ -347,14 +348,14 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)#ifdef CONFIG_BLK_DEV_INITRDif(phys_initrd_size&&!memblock_is_region_memory(phys_initrd_start,phys_initrd_size)){-pr_err("INITRD: 0x%08lx+0x%08lx is not a memory region - disabling initrd\n",-phys_initrd_start,phys_initrd_size);+pr_err("INITRD: 0x%08llx+0x%08lx is not a memory region - disabling initrd\n",+(u64)phys_initrd_start,phys_initrd_size);phys_initrd_start=phys_initrd_size=0;}if(phys_initrd_size&&memblock_is_region_reserved(phys_initrd_start,phys_initrd_size)){-pr_err("INITRD: 0x%08lx+0x%08lx overlaps in-use memory region - disabling initrd\n",-phys_initrd_start,phys_initrd_size);+pr_err("INITRD: 0x%08llx+0x%08lx overlaps in-use memory region - disabling initrd\n",+(u64)phys_initrd_start,phys_initrd_size);phys_initrd_start=phys_initrd_size=0;}if(phys_initrd_size){
On Keystone platforms, physical memory is entirely outside the 32-bit
addressible range. Therefore, the (bank->start > ULONG_MAX) check below marks
the entire system memory as highmem, and this causes unpleasentness all over.
This patch eliminates the extra bank start check (against ULONG_MAX) by
checking bank->start against the physical address corresponding to vmalloc_min
instead.
In the process, this patch also cleans up parts of the highmem sanity check
code by removing what has now become a redundant check for banks that entirely
overlap with the vmalloc range.
Signed-off-by: Cyril Chemparathy <redacted>
Signed-off-by: Vitaly Andrianov <redacted>
Acked-by: Nicolas Pitre <redacted>
---
arch/arm/mm/mmu.c | 19 +------------------
1 file changed, 1 insertion(+), 18 deletions(-)
This patch adds basic sanity tests to ensure that the instruction patching
results in valid instruction encodings. This is done by verifying the output
of the patch process against a vector of assembler generated instructions at
init time.
Signed-off-by: Cyril Chemparathy <redacted>
---
arch/arm/Kconfig | 12 +++++++
arch/arm/kernel/runtime-patch.c | 75 +++++++++++++++++++++++++++++++++++++++
2 files changed, 87 insertions(+)
From: Vitaly Andrianov <redacted>
This patch fixes the alloc_init_pud() function to use phys_addr_t instead of
unsigned long when passing in the phys argument.
This is an extension to commit 97092e0c56830457af0639f6bd904537a150ea4a (ARM:
pgtable: use phys_addr_t for physical addresses), which applied similar changes
elsewhere in the ARM memory management code.
Signed-off-by: Vitaly Andrianov <redacted>
Signed-off-by: Cyril Chemparathy <redacted>
Acked-by: Nicolas Pitre <redacted>
---
arch/arm/mm/mmu.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
The original phys_to_virt/virt_to_phys patching implementation relied on early
patching prior to MMU initialization. On PAE systems running out of >4G
address space, this would have entailed an additional round of patching after
switching over to the high address space.
The approach implemented here conceptually extends the original PHYS_OFFSET
patching implementation with the introduction of "early" patch stubs. Early
patch code is required to be functional out of the box, even before the patch
is applied. This is implemented by inserting functional (but inefficient)
load code into the .runtime.patch.code init section. Having functional code
out of the box then allows us to defer the init time patch application until
later in the init sequence.
In addition to fitting better with our need for physical address-space
switch-over, this implementation should be somewhat more extensible by virtue
of its more readable (and hackable) C implementation. This should prove
useful for other similar init time specialization needs, especially in light
of our multi-platform kernel initiative.
This code has been boot tested in both ARM and Thumb-2 modes on an ARMv7
(Cortex-A8) device.
Note: the obtuse use of stringified symbols in patch_stub() and
early_patch_stub() is intentional. Theoretically this should have been
accomplished with formal operands passed into the asm block, but this requires
the use of the 'c' modifier for instantiating the long (e.g. .long %c0).
However, the 'c' modifier has been found to ICE certain versions of GCC, and
therefore we resort to stringified symbols here.
Signed-off-by: Cyril Chemparathy <redacted>
Reviewed-by: Nicolas Pitre <redacted>
---
arch/arm/Kconfig | 3 +
arch/arm/include/asm/module.h | 7 ++
arch/arm/include/asm/runtime-patch.h | 208 ++++++++++++++++++++++++++++++++++
arch/arm/kernel/Makefile | 1 +
arch/arm/kernel/module.c | 9 +-
arch/arm/kernel/runtime-patch.c | 193 +++++++++++++++++++++++++++++++
arch/arm/kernel/setup.c | 3 +
arch/arm/kernel/vmlinux.lds.S | 10 ++
8 files changed, 433 insertions(+), 1 deletion(-)
create mode 100644 arch/arm/include/asm/runtime-patch.h
create mode 100644 arch/arm/kernel/runtime-patch.c
@@ -511,92 +511,29 @@ ENDPROC(fixup_smp)#ifdef CONFIG_ARM_PATCH_PHYS_VIRT-/*__fixup_pv_table-patchthestubinstructionswiththedeltabetween-*PHYS_OFFSETandPAGE_OFFSET,whichisassumedtobe16MiBalignedand-*canbeexpressedbyanimmediateshifteroperand.Thestubinstruction-*hasaformof'(add|sub) rd, rn, #imm'.+/*+*__fixup_pv_offsets-update__pv_offsetand__pv_phys_offsetbasedonthe+*runtimelocationofthekernel.*/__HEAD-__fixup_pv_table:+__fixup_pv_offsets:adrr0,1f-ldmiar0,{r3-r5,r7}+ldmiar0,{r3-r6}subr3,r0,r3@PHYS_OFFSET-PAGE_OFFSET-addr4,r4,r3@adjusttablestartaddress-addr5,r5,r3@adjusttableendaddress-addr7,r7,r3@adjust__pv_phys_offsetaddress-strr8,[r7]@savecomputedPHYS_OFFSETto__pv_phys_offset-movr6,r3,lsr#24 @ constant for add/sub instructions-teqr3,r6,lsl#24 @ must be 16MiB aligned-THUMB(itne@crosssectionbranch)-bne__error-strr6,[r7,#4] @ save to __pv_offset-b__fixup_a_pv_table-ENDPROC(__fixup_pv_table)+addr4,r4,r3@virt_to_phys(__pv_phys_offset)+addr5,r5,r3@virt_to_phys(__pv_offset)+addr6,r6,r3@virt_to_phys(PAGE_OFFSET)=PHYS_OFFSET+strr6,[r4]@save__pv_phys_offset+strr3,[r5]@save__pv_offset+movpc,lr+ENDPROC(__fixup_pv_offsets).align1:.long.-.long__pv_table_begin-.long__pv_table_end-2:.long__pv_phys_offset--.text-__fixup_a_pv_table:-#ifdef CONFIG_THUMB2_KERNEL-lslsr6,#24-beq2f-clzr7,r6-lsrr6,#24-lslr6,r7-bicr6,#0x0080-lsrsr7,#1-orrcsr6,#0x0080-orrr6,r6,r7,lsl#12-orrr6,#0x4000-b2f-1:addr7,r3-ldrhip,[r7,#2]-andip,0x8f00-orrip,r6@maskinoffsetbits31-24-strhip,[r7,#2]-2:cmpr4,r5-ldrccr7,[r4],#4 @ use branch for delay slot-bcc1b-bxlr-#else-b2f-1:ldrip,[r7,r3]-bicip,ip,#0x000000ff-orrip,ip,r6@maskinoffsetbits31-24-strip,[r7,r3]-2:cmpr4,r5-ldrccr7,[r4],#4 @ use branch for delay slot-bcc1b-movpc,lr+.long__pv_phys_offset+.long__pv_offset+.longPAGE_OFFSET#endif-ENDPROC(__fixup_a_pv_table)--ENTRY(fixup_pv_table)-stmfdsp!,{r4-r7,lr}-ldrr2,2f@getaddressof__pv_phys_offset-movr3,#0 @ no offset-movr4,r0@r0=tablestart-addr5,r0,r1@r1=tablesize-ldrr6,[r2,#4] @ get __pv_offset-bl__fixup_a_pv_table-ldmfdsp!,{r4-r7,pc}-ENDPROC(fixup_pv_table)-.align-2:.long__pv_phys_offset--.data-.globl__pv_phys_offset-.type__pv_phys_offset,%object-__pv_phys_offset:-.long0-.size__pv_phys_offset,.-__pv_phys_offset-__pv_offset:-.long0-#endif#include "head-common.S"
This patch modifies the highmem sanity checking code to use physical addresses
instead. This change eliminates the wrap-around problems associated with the
original virtual address based checks, and this simplifies the code a bit.
The one constraint imposed here is that low physical memory must be mapped in
a monotonically increasing fashion if there are multiple banks of memory,
i.e., x < y must => pa(x) < pa(y).
Signed-off-by: Cyril Chemparathy <redacted>
Signed-off-by: Vitaly Andrianov <redacted>
Acked-by: Nicolas Pitre <redacted>
---
arch/arm/mm/mmu.c | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)
This patch redefines the early boot time use of the R4 register to steal a few
low order bits (ARCH_PGD_SHIFT bits) on LPAE systems. This allows for up to
38-bit physical addresses.
Signed-off-by: Cyril Chemparathy <redacted>
Signed-off-by: Vitaly Andrianov <redacted>
---
arch/arm/include/asm/memory.h | 15 +++++++++++++++
arch/arm/kernel/head.S | 10 ++++------
arch/arm/kernel/smp.c | 11 +++++++++--
arch/arm/mm/proc-v7-3level.S | 8 ++++++++
4 files changed, 36 insertions(+), 8 deletions(-)
@@ -306,6 +306,7 @@ __create_page_tables:#endif#ifdef CONFIG_ARM_LPAEsubr4,r4,#0x1000 @ point to the PGD table+movr4,r4,lsr#ARCH_PGD_SHIFT#endifmovpc,lrENDPROC(__create_page_tables)
@@ -379,7 +380,7 @@ __secondary_data:*r0=cp#15 control register*r1=machineID*r2=atagsordtbpointer-*r4=pagetablepointer+*r4=pagetable (seeARCH_PGD_SHIFTinasm/memory.h)*r9=processorID*r13=*virtual*addresstojumptouponcompletion*/
This patch adds support for 64-bit physical addresses in virt_to_phys()
patching. This does not do real 64-bit add/sub, but instead patches in the
upper 32-bits of the phys_offset directly into the output of virt_to_phys.
There is no corresponding change on the phys_to_virt() side, because
computations on the upper 32-bits would be discarded anyway.
Signed-off-by: Cyril Chemparathy <redacted>
---
arch/arm/include/asm/memory.h | 38 ++++++++++++++++++++++++++++++++++++--
arch/arm/kernel/head.S | 4 ++++
arch/arm/kernel/setup.c | 2 +-
3 files changed, 41 insertions(+), 3 deletions(-)
This patch modifies the switch_mm() processor functions to use phys_addr_t.
On LPAE systems, we now honor the upper 32-bits of the physical address that
is being passed in, and program these into TTBR as expected.
Signed-off-by: Cyril Chemparathy <redacted>
Signed-off-by: Vitaly Andrianov <redacted>
---
arch/arm/include/asm/proc-fns.h | 4 ++--
arch/arm/mm/proc-v7-3level.S | 17 +++++++++++++----
2 files changed, 15 insertions(+), 6 deletions(-)
This patch moves the TTBR1 offset calculation and the T1SZ calculation out
of the TTB setup assembly code. This should not affect functionality in
any way, but improves code readability as well as readability of subsequent
patches in this series.
Signed-off-by: Cyril Chemparathy <redacted>
Signed-off-by: Vitaly Andrianov <redacted>
Acked-by: Nicolas Pitre <redacted>
---
arch/arm/include/asm/pgtable-3level-hwdef.h | 10 ++++++++++
arch/arm/mm/proc-v7-3level.S | 16 ++++------------
2 files changed, 14 insertions(+), 12 deletions(-)
This patch cleans up the highmem sanity check code by simplifying the range
checks with a pre-calculated size_limit. This patch should otherwise have no
functional impact on behavior.
This patch also removes a redundant (bank->start < vmalloc_limit) check, since
this is already covered by the !highmem condition.
Signed-off-by: Cyril Chemparathy <redacted>
Signed-off-by: Vitaly Andrianov <redacted>
---
arch/arm/mm/mmu.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
This patch applies to PAGE_MASK, PMD_MASK, and PGDIR_MASK, where forcing
unsigned long math truncates the mask at the 32-bits. This clearly does bad
things on PAE systems.
This patch fixes this problem by defining these masks as signed quantities.
We then rely on sign extension to do the right thing.
Signed-off-by: Cyril Chemparathy <redacted>
Signed-off-by: Vitaly Andrianov <redacted>
Reviewed-by: Nicolas Pitre <redacted>
---
arch/arm/include/asm/page.h | 2 +-
arch/arm/include/asm/pgtable-3level.h | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
From: Nicolas Pitre <hidden> Date: 2012-09-21 17:40:26
On Tue, 11 Sep 2012, Cyril Chemparathy wrote:
quoted hunk
This patch adds basic sanity tests to ensure that the instruction patching
results in valid instruction encodings. This is done by verifying the output
of the patch process against a vector of assembler generated instructions at
init time.
Signed-off-by: Cyril Chemparathy <redacted>
---
arch/arm/Kconfig | 12 +++++++
arch/arm/kernel/runtime-patch.c | 75 +++++++++++++++++++++++++++++++++++++++
2 files changed, 87 insertions(+)
@@ -207,6 +207,18 @@ config ARM_PATCH_PHYS_VIRTthisfeature(eg,buildingakernelforasinglemachine)andyouneedtoshrinkthekerneltotheminimalsize.+configARM_RUNTIME_PATCH_TEST+bool"Self test runtime patching mechanism"ifARM_RUNTIME_PATCH+defaulty
Here you probably want this instead:
bool "Self test runtime patching mechanism"
default y
depends on ARM_RUNTIME_PATCH
Otherwise ARM_RUNTIME_PATCH_TEST will be forced to y whenever
ARM_RUNTIME_PATCH is unset. That doesn't currently affect the build
since the containing .c file is only compiled when ARM_RUNTIME_PATCH is
set but that is still not strictly right.
[...]
I think you shoulld have runtime_patch_test() return a possible error
code and use BUG_ON() with it as well.
With those minor changes you can add...
Reviewed-by: Nicolas Pitre <redacted>
Nicolas
From: Nicolas Pitre <hidden> Date: 2012-09-21 18:09:44
On Tue, 11 Sep 2012, Cyril Chemparathy wrote:
The original phys_to_virt/virt_to_phys patching implementation relied on early
patching prior to MMU initialization. On PAE systems running out of >4G
address space, this would have entailed an additional round of patching after
switching over to the high address space.
The approach implemented here conceptually extends the original PHYS_OFFSET
patching implementation with the introduction of "early" patch stubs. Early
patch code is required to be functional out of the box, even before the patch
is applied. This is implemented by inserting functional (but inefficient)
load code into the .runtime.patch.code init section. Having functional code
out of the box then allows us to defer the init time patch application until
later in the init sequence.
In addition to fitting better with our need for physical address-space
switch-over, this implementation should be somewhat more extensible by virtue
of its more readable (and hackable) C implementation. This should prove
useful for other similar init time specialization needs, especially in light
of our multi-platform kernel initiative.
This code has been boot tested in both ARM and Thumb-2 modes on an ARMv7
(Cortex-A8) device.
Note: the obtuse use of stringified symbols in patch_stub() and
early_patch_stub() is intentional. Theoretically this should have been
accomplished with formal operands passed into the asm block, but this requires
the use of the 'c' modifier for instantiating the long (e.g. .long %c0).
However, the 'c' modifier has been found to ICE certain versions of GCC, and
therefore we resort to stringified symbols here.
Signed-off-by: Cyril Chemparathy <redacted>
Reviewed-by: Nicolas Pitre <redacted>
I know I provided review before, but here's another nit I'd like fixed:
This is wrong. If runtime_patch() is ever called when
CONFIG_ARM_RUNTIME_PATCH is not set, then i'd better return an error and
not pretend it performed the requested action. Returning -ENOSYS would
be appropriate.
This is especially important in the following context:
Despite the vermagic check, If ever a .runtime.patch.table section is
found in a module to be loaded in a kernel with no support for it then
it is best to return an error than see the kernel crashing later on when
the fallback stubs have been discarded.
Nicolas
From: Nicolas Pitre <hidden> Date: 2012-09-21 18:15:22
On Tue, 11 Sep 2012, Cyril Chemparathy wrote:
This patch replaces the original physical offset patching implementation
with one that uses the newly added patching framework.
Signed-off-by: Cyril Chemparathy <redacted>
Please also remove the MODULE_ARCH_VERMAGIC_P2V entirely from module.h
in this patch. This corresponds to the old patch table format which is
no longer supported once this patch is applied. The new mechanism is
covered by MODULE_ARCH_VERMAGIC_RT_PATCH already.
Once that is done, you may add...
Reviewed-by: Nicolas Pitre <redacted>
Nicolas
From: Nicolas Pitre <hidden> Date: 2012-09-21 18:30:44
On Tue, 11 Sep 2012, Cyril Chemparathy wrote:
From: Vitaly Andrianov <redacted>
This patch fixes the initrd setup code to use phys_addr_t instead of assuming
32-bit addressing. Without this we cannot boot on systems where initrd is
located above the 4G physical address limit.
Signed-off-by: Vitaly Andrianov <redacted>
Signed-off-by: Cyril Chemparathy <redacted>
Acked-by: Nicolas Pitre <redacted>
Nit: please adjust the patch title. No need for phys_addr_t on the size.
@@ -347,14 +348,14 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)#ifdef CONFIG_BLK_DEV_INITRDif(phys_initrd_size&&!memblock_is_region_memory(phys_initrd_start,phys_initrd_size)){-pr_err("INITRD: 0x%08lx+0x%08lx is not a memory region - disabling initrd\n",-phys_initrd_start,phys_initrd_size);+pr_err("INITRD: 0x%08llx+0x%08lx is not a memory region - disabling initrd\n",+(u64)phys_initrd_start,phys_initrd_size);phys_initrd_start=phys_initrd_size=0;}if(phys_initrd_size&&memblock_is_region_reserved(phys_initrd_start,phys_initrd_size)){-pr_err("INITRD: 0x%08lx+0x%08lx overlaps in-use memory region - disabling initrd\n",-phys_initrd_start,phys_initrd_size);+pr_err("INITRD: 0x%08llx+0x%08lx overlaps in-use memory region - disabling initrd\n",+(u64)phys_initrd_start,phys_initrd_size);phys_initrd_start=phys_initrd_size=0;}if(phys_initrd_size){
From: Nicolas Pitre <hidden> Date: 2012-09-21 18:33:48
On Tue, 11 Sep 2012, Cyril Chemparathy wrote:
This patch modifies the switch_mm() processor functions to use phys_addr_t.
On LPAE systems, we now honor the upper 32-bits of the physical address that
is being passed in, and program these into TTBR as expected.
Signed-off-by: Cyril Chemparathy <redacted>
Signed-off-by: Vitaly Andrianov <redacted>
From: Russell King - ARM Linux <hidden> Date: 2012-09-21 18:41:56
On Fri, Sep 21, 2012 at 02:33:43PM -0400, Nicolas Pitre wrote:
On Tue, 11 Sep 2012, Cyril Chemparathy wrote:
quoted
This patch modifies the switch_mm() processor functions to use phys_addr_t.
On LPAE systems, we now honor the upper 32-bits of the physical address that
is being passed in, and program these into TTBR as expected.
Signed-off-by: Cyril Chemparathy <redacted>
Signed-off-by: Vitaly Andrianov <redacted>
Reviewed-by: Nicolas Pitre <redacted>
Err... you may have reviewed it but did you read it?
phys_addr_t can be either 64-bit or 32-bit. Which it ends up depends on
a configuration option. If it's 32-bit, then mm is in r1, otherwise it
is in r2...
which breaks this when phys_addr_t is 32-bit.
Doing it this way means we have to have similar conditionals in other
files which make use of the 'mm' argument.
Moving the 'mm' argument into arg0 would mean that stays as r0, but
then the pgd_phys argument is passed in either r1 when 32-bit, or
r2,r3 when 64-bit on EABI and r1,r2 on OABI. That's hardly desirable
behaviour either, because it all too easily allows bugs to creap in.
The easiest solution would be to just change pgd_phys to be uint64_t
and be done with it. Then you always know in assembly what registers
values are going to be passed in (except for the LE/BE issue with r0/r1).
From: Nicolas Pitre <hidden> Date: 2012-09-21 18:42:16
On Tue, 11 Sep 2012, Cyril Chemparathy wrote:
This patch cleans up the highmem sanity check code by simplifying the range
checks with a pre-calculated size_limit. This patch should otherwise have no
functional impact on behavior.
This patch also removes a redundant (bank->start < vmalloc_limit) check, since
this is already covered by the !highmem condition.
Signed-off-by: Cyril Chemparathy <redacted>
Signed-off-by: Vitaly Andrianov <redacted>
From: Nicolas Pitre <hidden> Date: 2012-09-21 18:53:25
On Fri, 21 Sep 2012, Russell King - ARM Linux wrote:
On Fri, Sep 21, 2012 at 02:33:43PM -0400, Nicolas Pitre wrote:
quoted
On Tue, 11 Sep 2012, Cyril Chemparathy wrote:
quoted
This patch modifies the switch_mm() processor functions to use phys_addr_t.
On LPAE systems, we now honor the upper 32-bits of the physical address that
is being passed in, and program these into TTBR as expected.
Signed-off-by: Cyril Chemparathy <redacted>
Signed-off-by: Vitaly Andrianov <redacted>
Reviewed-by: Nicolas Pitre <redacted>
Err... you may have reviewed it but did you read it?
phys_addr_t can be either 64-bit or 32-bit. Which it ends up depends on
a configuration option. If it's 32-bit, then mm is in r1, otherwise it
is in r2...
Right. And that configuration option is CONFIG_ARM_LPAE.
This patch adds basic sanity tests to ensure that the instruction patching
results in valid instruction encodings. This is done by verifying the output
of the patch process against a vector of assembler generated instructions at
init time.
Signed-off-by: Cyril Chemparathy <redacted>
---
arch/arm/Kconfig | 12 +++++++
arch/arm/kernel/runtime-patch.c | 75 +++++++++++++++++++++++++++++++++++++++
2 files changed, 87 insertions(+)
@@ -207,6 +207,18 @@ config ARM_PATCH_PHYS_VIRTthisfeature(eg,buildingakernelforasinglemachine)andyouneedtoshrinkthekerneltotheminimalsize.+configARM_RUNTIME_PATCH_TEST+bool"Self test runtime patching mechanism"ifARM_RUNTIME_PATCH+defaulty
Here you probably want this instead:
bool "Self test runtime patching mechanism"
default y
depends on ARM_RUNTIME_PATCH
Otherwise ARM_RUNTIME_PATCH_TEST will be forced to y whenever
ARM_RUNTIME_PATCH is unset. That doesn't currently affect the build
since the containing .c file is only compiled when ARM_RUNTIME_PATCH is
set but that is still not strictly right.
The original phys_to_virt/virt_to_phys patching implementation relied on early
patching prior to MMU initialization. On PAE systems running out of >4G
address space, this would have entailed an additional round of patching after
switching over to the high address space.
The approach implemented here conceptually extends the original PHYS_OFFSET
patching implementation with the introduction of "early" patch stubs. Early
patch code is required to be functional out of the box, even before the patch
is applied. This is implemented by inserting functional (but inefficient)
load code into the .runtime.patch.code init section. Having functional code
out of the box then allows us to defer the init time patch application until
later in the init sequence.
In addition to fitting better with our need for physical address-space
switch-over, this implementation should be somewhat more extensible by virtue
of its more readable (and hackable) C implementation. This should prove
useful for other similar init time specialization needs, especially in light
of our multi-platform kernel initiative.
This code has been boot tested in both ARM and Thumb-2 modes on an ARMv7
(Cortex-A8) device.
Note: the obtuse use of stringified symbols in patch_stub() and
early_patch_stub() is intentional. Theoretically this should have been
accomplished with formal operands passed into the asm block, but this requires
the use of the 'c' modifier for instantiating the long (e.g. .long %c0).
However, the 'c' modifier has been found to ICE certain versions of GCC, and
therefore we resort to stringified symbols here.
Signed-off-by: Cyril Chemparathy <redacted>
Reviewed-by: Nicolas Pitre <redacted>
I know I provided review before, but here's another nit I'd like fixed:
This is wrong. If runtime_patch() is ever called when
CONFIG_ARM_RUNTIME_PATCH is not set, then i'd better return an error and
not pretend it performed the requested action. Returning -ENOSYS would
be appropriate.
This is especially important in the following context:
Despite the vermagic check, If ever a .runtime.patch.table section is
found in a module to be loaded in a kernel with no support for it then
it is best to return an error than see the kernel crashing later on when
the fallback stubs have been discarded.
Nicolas
This patch cleans up the highmem sanity check code by simplifying the range
checks with a pre-calculated size_limit. This patch should otherwise have no
functional impact on behavior.
This patch also removes a redundant (bank->start < vmalloc_limit) check, since
this is already covered by the !highmem condition.
Signed-off-by: Cyril Chemparathy <redacted>
Signed-off-by: Vitaly Andrianov <redacted>
Acked-by: Nicolas Pitre <redacted>
Thanks, Nico.
Could you please take another peek at patch 05/17 (support 64-bit
virt_to_phys patching)? You had reviewed it in an earlier posting, but
I've had to tweak the code to optimize the compiler generated inline
expansion code.
Patch 14/17 (accomodate >32-bit addresses for page table base) could use
some attention as well. The same goes with 12/17 (define
ARCH_LOW_ADDRESS_LIMIT for bootmem), if you could.
--
Thanks
- Cyril