@@ -6,6 +6,7 @@
* This work is licensed under the terms of the GNU LGPL, version 2.
*/
#define __ASSEMBLY__
+#include <auxinfo.h>
#include <asm/thread_info.h>
#include <asm/asm-offsets.h>
#include <asm/ptrace.h>
@@ -57,7 +58,12 @@ start:
/* complete setup */
pop {r0-r1}
bl setup
+ bl get_mmu_off
+ cmp r0, #0
+ bne 1f
+ bl setup_vm
+1:
/* run the test */
ldr r0, =__argc
ldr r0, [r0]
@@ -96,14 +102,25 @@ exceptions_init:
.text
+.global get_mmu_off
+get_mmu_off:
+ ldr r0, =auxinfo
+ ldr r0, [r0, #4]
+ and r0, #AUXINFO_MMU_OFF
+ mov pc, lr
+
.global secondary_entry
secondary_entry:
- /* enable the MMU */
+ /* enable the MMU unless requested off */
+ bl get_mmu_off
+ cmp r0, #0
+ bne 1f
mov r1, #0
ldr r0, =mmu_idmap
ldr r0, [r0]
bl asm_mmu_enable
+1:
/*
* Set the stack, and set up vector table
* and exception stacks. Exception stacks
@@ -6,6 +6,7 @@
* This work is licensed under the terms of the GNU GPL, version 2.
*/
#define __ASSEMBLY__
+#include <auxinfo.h>
#include <asm/asm-offsets.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
@@ -38,7 +39,11 @@ start:
/* complete setup */
ldp x0, x1, [sp], #16
bl setup
+ bl get_mmu_off
+ cbnz x0, 1f
+ bl setup_vm
+1:
/* run the test */
adrp x0, __argc
ldr x0, [x0, :lo12:__argc]
@@ -59,6 +64,13 @@ exceptions_init:
.text
+.globl get_mmu_off
+get_mmu_off:
+ adrp x0, auxinfo
+ ldr x0, [x0, :lo12:auxinfo + 8]
+ and x0, x0, #AUXINFO_MMU_OFF
+ ret
+
.globl secondary_entry
secondary_entry:
/* Enable FP/ASIMD */
@@ -68,11 +80,14 @@ secondary_entry:
/* set up exception handling */
bl exceptions_init
- /* enable the MMU */
+ /* enable the MMU unless requested off */
+ bl get_mmu_off
+ cbnz x0, 1f
adrp x0, mmu_idmap
ldr x0, [x0, :lo12:mmu_idmap]
bl asm_mmu_enable
+1:
/* set the stack */
adrp x0, secondary_data
ldr x0, [x0, :lo12:secondary_data]
@@ -15,11 +15,11 @@
#include <devicetree.h>
#include <alloc.h>
#include <alloc_phys.h>
+#include <alloc_page.h>
#include <argv.h>
#include <asm/thread_info.h>
#include <asm/setup.h>
#include <asm/page.h>
-#include <asm/mmu.h>
#include <asm/smp.h>
extern unsigned long stacktop;
@@ -70,6 +70,7 @@ static void mem_init(phys_addr_t freemem_start)
struct mem_region primary, mem = {
.start = (phys_addr_t)-1,
};
+ phys_addr_t base, top;
int nr_regs, i;
nr_regs = dt_get_memory_params(regs, NR_MEM_REGIONS);
@@ -108,7 +109,14 @@ static void mem_init(phys_addr_t freemem_start)
phys_alloc_init(freemem_start, primary.end - freemem_start);
phys_alloc_set_minimum_alignment(SMP_CACHE_BYTES);
- setup_vm();
+ phys_alloc_get_unused(&base, &top);
+ base = PAGE_ALIGN(base);
+ top = top & PAGE_MASK;
+ assert(sizeof(long) == 8 || !(base >> 32));
+ if (sizeof(long) != 8 && (top >> 32) != 0)
+ top = ((uint64_t)1 << 32);
+ free_pages((void *)(unsigned long)base, top - base);
+ page_alloc_ops_enable();
}
void setup(const void *fdt)
@@ -156,14 +164,12 @@ void setup(const void *fdt)
}
/* call init functions */
+ mem_init(PAGE_ALIGN((unsigned long)freemem));
cpu_init();
/* cpu_init must be called before thread_info_init */
thread_info_init(current_thread_info(), 0);
- /* thread_info_init must be called before mem_init */
- mem_init(PAGE_ALIGN((unsigned long)freemem));
-
/* mem_init must be called before io_init */
io_init();
@@ -6,6 +6,7 @@
* This work is licensed under the terms of the GNU LGPL, version 2.
*/
#include <libcflat.h>
+#include <auxinfo.h>
#include <asm/thread_info.h>
#include <asm/spinlock.h>
#include <asm/cpumask.h>
@@ -33,8 +34,11 @@ secondary_entry_fn secondary_cinit(void)
secondary_entry_fn entry;
thread_info_init(ti, 0);
- ti->pgtable = mmu_idmap;
- mmu_mark_enabled(ti->cpu);
+
+ if (!(auxinfo.flags & AUXINFO_MMU_OFF)) {
+ ti->pgtable = mmu_idmap;
+ mmu_mark_enabled(ti->cpu);
+ }
/*
* Save secondary_data.entry locally to avoid opening a race
@@ -4,6 +4,10 @@
*/
#ifndef _AUXINFO_H_
#define _AUXINFO_H_
+
+#define AUXINFO_MMU_OFF (1 << 0)
+
+#ifndef __ASSEMBLY__
struct auxinfo {
const char *progname;
unsigned long flags;
@@ -12,3 +16,4 @@ struct auxinfo {
/* No extern! Define a common symbol. */
struct auxinfo auxinfo;
#endif
+#endif
Determine whether or not to enable the MMU during setup with an auxinfo flag. This gives unit tests that need to start cpu0 at main() with the MMU off, and no page tables constructed, the option to do so. The physical page allocator is now used as the basis for alloc_ops, allowing both malloc() and page_alloc() to work without a setup_vm() call. The unit test can still call setup_vm() itself later. Secondaries will also start in their entry points with the MMU off. If page tables have already been constructed by another CPU, and are pointed to by e.g. 'pgtable', then the secondary can easily enable the MMU with mmu_enable(pgtable). Naturally unit tests that start multiple CPUs with the MMU off need to keep track of each CPU's MMU enable status and which set of ops are pointed to by alloc_ops. Also note, spinlocks may not work as expected with the MMU off. IOW, this option gives a unit test plenty of rope to shoot itself with. Signed-off-by: Andrew Jones <drjones@redhat.com> --- arm/cstart.S | 19 ++++++++++++++++++- arm/cstart64.S | 17 ++++++++++++++++- lib/arm/setup.c | 16 +++++++++++----- lib/arm/smp.c | 8 ++++++-- lib/auxinfo.h | 5 +++++ 5 files changed, 56 insertions(+), 9 deletions(-)