Miscellaneous nommu fixes
Subsystems (3)
cover Miscellaneous nommu fixes
Hello,
This set of patches is a series of fixes for kernels built without CONFIG_MMU selected. It seems that this isn't a particularly popular choice amongst users of mainline kernels, but I was feeling brave and gave it a go.
The first patch is already in the patch system as 7337/1 but is unlikely to be merged unless it can be shown to work correctly. I tried the latest Codesourcery / Mentor uclinux GDB but that doesn't appear to issue the relevant ptrace requests:
http://lists.infradead.org/pipermail/linux-arm-kernel/2012-February/086219.html
If anybody has a working uclinux environment, it would *make my day* if they could take GDB for a spin.
The second patch has been picked up by Andrew Morton from the kexec list.
The remaining patches are largely straightforward with the exception of the CPU suspend changes. I actually managed to test this with a rather weird and wonderful configuration, although this was using software models which tend to hide some of the issues you may experience with real hardware.
All feedback welcome.
Will
Jonathan Austin (1):
ARM: nommu: Use VECTORS_BASE for vector copying with !MMU
Will Deacon (5):
ARM: ptrace: fix ptrace_read_user for !CONFIG_MMU platforms
kexec: crash: don't save swapper_pg_dir for !CONFIG_MMU
configurations
ARM: nommu: fix typo in mm/Kconfig
ARM: suspend: fix CPU suspend code for !CONFIG_MMU configurations
ARM: mm: truncate memory banks to fit in 4GB space for classic MMU
arch/arm/kernel/ptrace.c | 4 ++- arch/arm/kernel/setup.c | 11 ++++++++- arch/arm/kernel/suspend.c | 52 ++++++++++++++++++++++++++------------------- arch/arm/kernel/traps.c | 2 +- arch/arm/mm/Kconfig | 2 +- arch/arm/mm/proc-v6.S | 6 ++++- arch/arm/mm/proc-v7.S | 14 +++++++---- kernel/kexec.c | 2 + 8 files changed, 61 insertions(+), 32 deletions(-)
Signature · 1 line
1.7.4.1
PATCH 1/6 ARM: ptrace: fix ptrace_read_user for !CONFIG_MMU platforms
Commit 68b7f715 ("nommu: ptrace support") added definitions for PT_TEXT_ADDR and friends, as well as adding ptrace support for reading from these magic offsets.
Unfortunately, this has probably never worked, since ptrace_read_user predicates reading on off < sizeof(struct user), returning -EIO otherwise.
This patch moves the offset size check until after we have tried to match it against either a magic value or an offset into pt_regs.
--- arch/arm/kernel/ptrace.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
arch/arm/kernel/ptrace.c +3 -1
@@ -257,7 +257,7 @@ static int ptrace_read_user(struct task_struct *tsk, unsigned long off, {unsigned long tmp; -if (off &3 || off >=sizeof (struct user )) +if (off &3 )return -EIO ; tmp =0 ;
@@ -269,6 +269,8 @@ static int ptrace_read_user(struct task_struct *tsk, unsigned long off, tmp = tsk->mm->end_code; else if (off < sizeof(struct pt_regs)) tmp =get_user_reg (tsk, off >>2 ); + else if (off >= sizeof(struct user)) +return -EIO ;return put_user (tmp, ret); }
Signature · 1 line
1.7.4.1
PATCH 2/6 kexec: crash: don't save swapper_pg_dir for !CONFIG_MMU configurations
In reply to Will Deaconnommu platforms don't have very interesting swapper_pg_dir pointers and usually just #define them to NULL, meaning that we can't include them in the vmcoreinfo on the kexec crash path.
This patch only saves the swapper_pg_dir if we have an MMU.
--- kernel/kexec.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
kernel/kexec.c +2 -0
@@ -1462,7 +1462,9 @@ static int __init crash_save_vmcoreinfo_init(void)VMCOREINFO_SYMBOL (init_uts_ns);VMCOREINFO_SYMBOL (node_online_map); +#ifdef CONFIG_MMU VMCOREINFO_SYMBOL (swapper_pg_dir); +#endif VMCOREINFO_SYMBOL (_stext);VMCOREINFO_SYMBOL (vmlist);
Signature · 1 line
1.7.4.1
PATCH 3/6 ARM: nommu: fix typo in mm/Kconfig
In reply to Will DeaconThe description for the CPU_HIGH_VECTOR Kconfig option for nommu builds doesn't make any sense.
This patch fixes up the trivial grammatical error.
--- arch/arm/mm/Kconfig | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/arm/mm/Kconfig +1 -1
@@ -723,7 +723,7 @@ config CPU_HIGH_VECTOR bool "Select the High exception vector" help Say Y here to select high exception vector(0xFFFF0000~). - The exception vector can be vary depending on the platform + The exception vector can vary depending on the platform design in nommu mode. If your platform needs to select high exception vector, say Y. Otherwise or if you are unsure, say N, and the low exception
Signature · 1 line
1.7.4.1
PATCH 4/6 ARM: suspend: fix CPU suspend code for !CONFIG_MMU configurations
In reply to Will DeaconThe ARM CPU suspend code can be selected even for a !CONFIG_MMU configuration. The resulting kernel will not compile and, even if it did, would access undefined co-processor registers when executing.
This patch fixes the v6 and v7 CPU suspend code for the nommu case.
--- arch/arm/kernel/suspend.c | 52 ++++++++++++++++++++++++++------------------- arch/arm/mm/proc-v6.S | 6 ++++- arch/arm/mm/proc-v7.S | 14 +++++++---- 3 files changed, 44 insertions(+), 28 deletions(-)
arch/arm/kernel/suspend.c +30 -22
@@ -10,28 +10,7 @@extern int __cpu_suspend (unsigned long ,int (*)(unsigned long ));extern void cpu_resume_mmu (void ); -/* -* This is called by __cpu_suspend() to save the state, and do whatever -* flushing is required to ensure that when the CPU goes to sleep we have -* the necessary data available when the caches are not searched. -*/ -void __cpu_suspend_save (u32 *ptr,u32 ptrsz,u32 sp,u32 *save_ptr) -{ - *save_ptr =virt_to_phys (ptr); - -/* This must correspond to the LDM in cpu_resume() assembly */ - *ptr++ =virt_to_phys (idmap_pgd); - *ptr++ = sp; - *ptr++ =virt_to_phys (cpu_do_resume); - -cpu_do_suspend (ptr); - -flush_cache_all (); -outer_clean_range (*save_ptr, *save_ptr + ptrsz); -outer_clean_range (virt_to_phys (save_ptr), -virt_to_phys (save_ptr) +sizeof (*save_ptr)); -} - +#ifdef CONFIG_MMU /* * Hide the first two arguments to __cpu_suspend - these are an implementation * detail which platform code shouldn't have to know about.
@@ -58,3 +37,32 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))return ret; } +#else +int cpu_suspend (unsigned long arg,int (*fn)(unsigned long )) +{ +return __cpu_suspend (arg, fn); +} +#define idmap_pgd NULL +#endif + +/* +* This is called by __cpu_suspend() to save the state, and do whatever +* flushing is required to ensure that when the CPU goes to sleep we have +* the necessary data available when the caches are not searched. +*/ +void __cpu_suspend_save (u32 *ptr,u32 ptrsz,u32 sp,u32 *save_ptr) +{ + *save_ptr =virt_to_phys (ptr); + +/* This must correspond to the LDM in cpu_resume() assembly */ + *ptr++ =virt_to_phys (idmap_pgd); + *ptr++ = sp; + *ptr++ =virt_to_phys (cpu_do_resume); + +cpu_do_suspend (ptr); + +flush_cache_all (); +outer_clean_range (*save_ptr, *save_ptr + ptrsz); +outer_clean_range (virt_to_phys (save_ptr), +virt_to_phys (save_ptr) +sizeof (*save_ptr)); +}
arch/arm/mm/proc-v6.S +5 -1
@@ -136,8 +136,10 @@ ENTRY(cpu_v6_set_pte_ext) ENTRY(cpu_v6_do_suspend) stmfd sp!, {r4 - r9, lr} mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID +#ifdef CONFIG_MMU mrc p15, 0, r5, c3, c0, 0 @ Domain ID mrc p15, 0, r6, c2, c0, 1 @ Translation table base 1 +#endif mrc p15, 0, r7, c1, c0, 1 @ auxiliary control register mrc p15, 0, r8, c1, c0, 2 @ co-processor access control mrc p15, 0, r9, c1, c0, 0 @ control register
@@ -154,14 +156,16 @@ ENTRY(cpu_v6_do_resume) mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID ldmia r0, {r4 - r9} mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID +#ifdef CONFIG_MMU mcr p15, 0, r5, c3, c0, 0 @ Domain ID ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP) ALT_UP(orr r1, r1, #TTB_FLAGS_UP) mcr p15, 0, r1, c2, c0, 0 @ Translation table base 0 mcr p15, 0, r6, c2, c0, 1 @ Translation table base 1 + mcr p15, 0, ip, c2, c0, 2 @ TTB control register +#endif mcr p15, 0, r7, c1, c0, 1 @ auxiliary control register mcr p15, 0, r8, c1, c0, 2 @ co-processor access control - mcr p15, 0, ip, c2, c0, 2 @ TTB control register mcr p15, 0, ip, c7, c5, 4 @ ISB mov r0, r9 @ control register b cpu_resume_mmu
arch/arm/mm/proc-v7.S +9 -5
@@ -98,9 +98,11 @@ ENTRY(cpu_v7_do_suspend) mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID mrc p15, 0, r5, c13, c0, 3 @ User r/o thread ID stmia r0!, {r4 - r5} +#ifdef CONFIG_MMU mrc p15, 0, r6, c3, c0, 0 @ Domain ID mrc p15, 0, r7, c2, c0, 1 @ TTB 1 mrc p15, 0, r11, c2, c0, 2 @ TTB control register +#endif mrc p15, 0, r8, c1, c0, 0 @ Control register mrc p15, 0, r9, c1, c0, 1 @ Auxiliary control register mrc p15, 0, r10, c1, c0, 2 @ Co-processor access control
@@ -110,13 +112,14 @@ ENDPROC(cpu_v7_do_suspend) ENTRY(cpu_v7_do_resume) mov ip, #0 - mcr p15, 0, ip, c8, c7, 0 @ invalidate TLBs mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache mcr p15, 0, ip, c13, c0, 1 @ set reserved context ID ldmia r0!, {r4 - r5} mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID mcr p15, 0, r5, c13, c0, 3 @ User r/o thread ID ldmia r0, {r6 - r11} +#ifdef CONFIG_MMU + mcr p15, 0, ip, c8, c7, 0 @ invalidate TLBs mcr p15, 0, r6, c3, c0, 0 @ Domain ID #ifndef CONFIG_ARM_LPAE ALT_SMP(orr r1, r1, #TTB_FLAGS_SMP)
@@ -125,14 +128,15 @@ ENTRY(cpu_v7_do_resume) mcr p15, 0, r1, c2, c0, 0 @ TTB 0 mcr p15, 0, r7, c2, c0, 1 @ TTB 1 mcr p15, 0, r11, c2, c0, 2 @ TTB control register - mrc p15, 0, r4, c1, c0, 1 @ Read Auxiliary control register - teq r4, r9 @ Is it already set? - mcrne p15, 0, r9, c1, c0, 1 @ No, so write it - mcr p15, 0, r10, c1, c0, 2 @ Co-processor access control ldr r4, =PRRR @ PRRR ldr r5, =NMRR @ NMRR mcr p15, 0, r4, c10, c2, 0 @ write PRRR mcr p15, 0, r5, c10, c2, 1 @ write NMRR +#endif /* CONFIG_MMU */ + mrc p15, 0, r4, c1, c0, 1 @ Read Auxiliary control register + teq r4, r9 @ Is it already set? + mcrne p15, 0, r9, c1, c0, 1 @ No, so write it + mcr p15, 0, r10, c1, c0, 2 @ Co-processor access control isb dsb mov r0, r8 @ control register
Signature · 1 line
1.7.4.1
PATCH 5/6 ARM: nommu: Use VECTORS_BASE for vector copying with !MMU
In reply to Will DeaconFrom: Jonathan Austin <[email protected]>
When compiling with !CONFIG_MMU the vectors_page pointer does not get initialised. In the high vectors case, this results in copying to the wrong address (0x0) and hence a failure to boot.
This patch instead uses CONFIG_VECTORS_BASE as the destination address when !CONFIG_MMU.
--- arch/arm/kernel/traps.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/arm/kernel/traps.c +1 -1
@@ -786,7 +786,7 @@ static void __init kuser_get_tls_init(unsigned long vectors)void __init early_trap_init (void ) { -#if defined(CONFIG_CPU_USE_DOMAINS ) +#if defined(CONFIG_CPU_USE_DOMAINS ) || !defined(CONFIG_MMU )unsigned long vectors =CONFIG_VECTORS_BASE ;#else unsigned long vectors = (unsigned long )vectors_page;
Signature · 1 line
1.7.4.1
PATCH 6/6 ARM: mm: truncate memory banks to fit in 4GB space for classic MMU
In reply to Will DeaconIf a bank of memory spanning the 4GB boundary is added on a !CONFIG_LPAE kernel then we will hang early during boot since the memory bank will have wrapped around to zero.
This patch truncates memory banks for !LPAE configurations when the end address is not representable in 32 bits.
--- arch/arm/kernel/setup.c | 11 ++++++++++- 1 files changed, 10 insertions(+), 1 deletions(-)
arch/arm/kernel/setup.c +10 -1
@@ -521,7 +521,16 @@ int __init arm_add_memory(phys_addr_t start, unsigned long size)*/ size -= start & ~PAGE_MASK ; bank->start =PAGE_ALIGN (start); - bank->size = size &PAGE_MASK ; + +#ifndef CONFIG_LPAE +if (bank->start + size < bank->start) { +printk (KERN_CRIT "Truncating memory at 0x%08llx to fit in " +"32-bit physical address space\n" , (long long )start); + size =ULONG_MAX - bank->start; + } +#endif + + bank->size = size &PAGE_MASK ;/* * Check whether this memory region has non-zero size or
Signature · 1 line
1.7.4.1
PATCH 6/6 ARM: mm: truncate memory banks to fit in 4GB space for classic MMU
Hello.
Quoted 17 lines · Will Deacon
If a bank of memory spanning the 4GB boundary is added on a !CONFIG_LPAE kernel then we will hang early during boot since the memory bank will have wrapped around to zero.
This patch truncates memory banks for !LPAE configurations when the end address is not representable in 32 bits.
Signed-off-by Will Deacon<[email protected]>--- arch/arm/kernel/setup.c | 11 ++++++++++- 1 files changed, 10 insertions(+), 1 deletions(-)arch/arm/kernel/setup.c +0
-0
arch/arm/kernel/setup.c int __init arm_add_memory(phys_addr_t start, unsigned long size) · line 529
Quoted 10 lines
arch/arm/kernel/setup.c +6
-1@@ -521,7 +521,16 @@ int __init arm_add_memory(phys_addr_t start, unsigned long size)*/ size -= start& ~PAGE_MASK ; bank->start =PAGE_ALIGN (start); - bank->size = size&PAGE_MASK ; + +#ifndef CONFIG_LPAE +if (bank->start + size< bank->start) { +printk (KERN_CRIT "Truncating memory at 0x%08llx to fit in " +"32-bit physical address space\n" , (long long )start); + size =ULONG_MAX - bank->start;
I think you forgot to add one here.
WBR, Sergei
PATCH 6/6 ARM: mm: truncate memory banks to fit in 4GB space for classic MMU
Quoted 1 line · Sergei Shtylyov
Hello.
Hi Sergei,
Quoted 23 lines · Will Deacon
Quoted 22 lines
If a bank of memory spanning the 4GB boundary is added on a !CONFIG_LPAE kernel then we will hang early during boot since the memory bank will have wrapped around to zero.
This patch truncates memory banks for !LPAE configurations when the end address is not representable in 32 bits.
Signed-off-by Will Deacon<[email protected]>--- arch/arm/kernel/setup.c | 11 ++++++++++- 1 files changed, 10 insertions(+), 1 deletions(-)arch/arm/kernel/setup.c +0
-1@@ -521,7 +521,16 @@ int __init arm_add_memory(phys_addr_t start, unsigned long size)*/ size -= start& ~PAGE_MASK ; bank->start =PAGE_ALIGN (start); - bank->size = size&PAGE_MASK ;
Quoted 8 lines
arch/arm/kernel/setup.c int __init arm_add_memory(phys_addr_t start, unsigned long size) · line 529
Quoted 6 lines
arch/arm/kernel/setup.c +6
-0+ +#ifndef CONFIG_LPAE +if (bank->start + size< bank->start) { +printk (KERN_CRIT "Truncating memory at 0x%08llx to fit in " +"32-bit physical address space\n" , (long long )start); + size =ULONG_MAX - bank->start;I think you forgot to add one here.
No, I deliberately omit the last page because otherwise we end up with the end address of the bank being calculated as 0, which leads to boot failure.
Will
PATCH 6/6 ARM: mm: truncate memory banks to fit in 4GB space for classic MMU
Quoted 37 lines · Will Deacon
Quoted 1 line · Sergei Shtylyov
Hello.
Hi Sergei,
Quoted 23 lines · Will Deacon
Quoted 22 lines
If a bank of memory spanning the 4GB boundary is added on a !CONFIG_LPAE kernel then we will hang early during boot since the memory bank will have wrapped around to zero.
This patch truncates memory banks for !LPAE configurations when the end address is not representable in 32 bits.
Signed-off-by Will Deacon<[email protected]>--- arch/arm/kernel/setup.c | 11 ++++++++++- 1 files changed, 10 insertions(+), 1 deletions(-)arch/arm/kernel/setup.c +0
-1@@ -521,7 +521,16 @@ int __init arm_add_memory(phys_addr_t start, unsigned long size)*/ size -= start& ~PAGE_MASK ; bank->start =PAGE_ALIGN (start); - bank->size = size&PAGE_MASK ;Quoted 8 lines
arch/arm/kernel/setup.c int __init arm_add_memory(phys_addr_t start, unsigned long size) · line 529
Quoted 6 lines
arch/arm/kernel/setup.c +6
-0+ +#ifndef CONFIG_LPAE +if (bank->start + size< bank->start) { +printk (KERN_CRIT "Truncating memory at 0x%08llx to fit in " +"32-bit physical address space\n" , (long long )start); + size =ULONG_MAX - bank->start;I think you forgot to add one here.
Quoted 2 lines
No, I deliberately omit the last page because otherwise we end up with the end address of the bank being calculated as 0, which leads to boot failure.
What this mentioned in the code, or at least in the patch log?
Nicolas
PATCH 6/6 ARM: mm: truncate memory banks to fit in 4GB space for classic MMU
Hi Nicolas,
Quoted 12 lines · Nicolas Pitre
Quoted 11 lines · Will Deacon
Quoted 9 lines · Sergei Shtylyov
arch/arm/kernel/setup.c int __init arm_add_memory(phys_addr_t start, unsigned long size) · line 529
Quoted 5 lines · Will Deacon
arch/arm/kernel/setup.c +5
-0+#ifndef CONFIG_LPAE +if (bank->start + size< bank->start) { +printk (KERN_CRIT "Truncating memory at 0x%08llx to fit in " +"32-bit physical address space\n" , (long long )start); + size =ULONG_MAX - bank->start;I think you forgot to add one here.
Quoted 4 lines
Quoted 2 lines
No, I deliberately omit the last page because otherwise we end up with the end address of the bank being calculated as 0, which leads to boot failure.
What this mentioned in the code, or at least in the patch log?
Good idea - I'll add a comment to the code when we assign size.
Will