From patchwork Wed Jul 16 08:47:38 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Jones X-Patchwork-Id: 4565611 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 2F6289F1D6 for ; Wed, 16 Jul 2014 08:49:05 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8758A2018E for ; Wed, 16 Jul 2014 08:49:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A625A201CD for ; Wed, 16 Jul 2014 08:49:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933640AbaGPIs5 (ORCPT ); Wed, 16 Jul 2014 04:48:57 -0400 Received: from mx1.redhat.com ([209.132.183.28]:36605 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1759212AbaGPIsF (ORCPT ); Wed, 16 Jul 2014 04:48:05 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s6G8m30o002122 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 16 Jul 2014 04:48:03 -0400 Received: from hawk.usersys.redhat.com (dhcp-1-116.brq.redhat.com [10.34.1.116]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s6G8llvm029735; Wed, 16 Jul 2014 04:48:01 -0400 From: Andrew Jones To: kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org Cc: christoffer.dall@linaro.org, pbonzini@redhat.com Subject: [PATCH v7 09/14] arm: initial drop Date: Wed, 16 Jul 2014 10:47:38 +0200 Message-Id: <1405500463-20713-10-git-send-email-drjones@redhat.com> In-Reply-To: <1405500463-20713-1-git-send-email-drjones@redhat.com> References: <1405500463-20713-1-git-send-email-drjones@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This is the initial drop of the arm test framework and a first test that just checks that setup completed (a selftest). kvm isn't needed to run this test unless testing with smp > 1. Try it out with yum install gcc-arm-linux-gnu export QEMU=[qemu with mach-virt and chr-testdev] ./configure --cross-prefix=arm-linux-gnu- --arch=arm make ./run_tests.sh Signed-off-by: Andrew Jones Reviewed-by: Christoffer Dall --- v7: - remove memregions (reworked them as phys_alloc in lib/alloc) - selftest: non-functional change: s/argv[i]/var/ - lib/argv:setup_args don't dereference NULL v6: - fixed setup.c comment [Christoffer Dall] - changed arm/run to use chr-testdev instead of virtio-testdev - add align parameter to memregion_new, setup alloc_ops v5: - memregions: check freemem_start is in bounds and document - selftest: rename testnam => testname and properly init it - io.c: use writeb instead of writel in puts() and use ioremap - arm/run script update for new qemu ('-device ?' now requires -machine) - couple other minor changes to setup.c and io.c [Christoffer Dall] v4: - moved fdt to just after stacktop (it was in the middle of free memory) - switched from using heap to memregions - get nr_cpus and added smp= test - added barrier.h - use new report()/report_summary() - config/config-arm.mak cleanup --- arm/cstart.S | 35 ++++++++++++++++++++ arm/flat.lds | 18 +++++++++++ arm/run | 46 +++++++++++++++++++++++++++ arm/selftest.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++ arm/unittests.cfg | 18 +++++++++++ config/config-arm.mak | 74 +++++++++++++++++++++++++++++++++++++++++++ configure | 12 +++++-- lib/argv.c | 9 ++++++ lib/arm/asm/barrier.h | 18 +++++++++++ lib/arm/asm/io.h | 24 ++++++++++++++ lib/arm/asm/page.h | 1 + lib/arm/asm/setup.h | 27 ++++++++++++++++ lib/arm/asm/spinlock.h | 16 ++++++++++ lib/arm/eabi_compat.c | 20 ++++++++++++ lib/arm/io.c | 65 ++++++++++++++++++++++++++++++++++++++ lib/arm/setup.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++ 16 files changed, 549 insertions(+), 2 deletions(-) create mode 100644 arm/cstart.S create mode 100644 arm/flat.lds create mode 100755 arm/run create mode 100644 arm/selftest.c create mode 100644 arm/unittests.cfg create mode 100644 config/config-arm.mak create mode 100644 lib/arm/asm/barrier.h create mode 100644 lib/arm/asm/io.h create mode 100644 lib/arm/asm/page.h create mode 100644 lib/arm/asm/setup.h create mode 100644 lib/arm/asm/spinlock.h create mode 100644 lib/arm/eabi_compat.c create mode 100644 lib/arm/io.c create mode 100644 lib/arm/setup.c diff --git a/arm/cstart.S b/arm/cstart.S new file mode 100644 index 0000000000000..e28251db2950d --- /dev/null +++ b/arm/cstart.S @@ -0,0 +1,35 @@ +/* + * Boot entry point and assembler functions for armv7 tests. + * + * Copyright (C) 2014, Red Hat Inc, Andrew Jones + * + * This work is licensed under the terms of the GNU LGPL, version 2. + */ + +.arm + +.section .init + +.globl start +start: + /* + * bootloader params are in r0-r2 + * See the kernel doc Documentation/arm/Booting + */ + ldr sp, =stacktop + bl setup + + /* run the test */ + ldr r0, =__argc + ldr r0, [r0] + ldr r1, =__argv + bl main + bl exit + b halt + +.text + +.globl halt +halt: +1: wfi + b 1b diff --git a/arm/flat.lds b/arm/flat.lds new file mode 100644 index 0000000000000..3e5d72e24989b --- /dev/null +++ b/arm/flat.lds @@ -0,0 +1,18 @@ + +SECTIONS +{ + .text : { *(.init) *(.text) *(.text.*) } + . = ALIGN(4K); + .data : { *(.data) } + . = ALIGN(16); + .rodata : { *(.rodata) } + . = ALIGN(16); + .bss : { *(.bss) } + . = ALIGN(4K); + edata = .; + . += 8K; + . = ALIGN(4K); + stacktop = .; +} + +ENTRY(start) diff --git a/arm/run b/arm/run new file mode 100755 index 0000000000000..a714350225597 --- /dev/null +++ b/arm/run @@ -0,0 +1,46 @@ +#!/bin/bash + +if [ ! -f config.mak ]; then + echo run ./configure first. See ./configure -h + exit 2 +fi +source config.mak + +qemu="${QEMU:-qemu-system-arm}" +qpath=$(which $qemu 2>/dev/null) + +if [ -z "$qpath" ]; then + echo $qemu not found. + exit 2 +fi + +if ! $qemu -machine '?' 2>&1 | grep 'ARM Virtual Machine' > /dev/null; then + echo "$qpath doesn't support mach-virt ('-machine virt'). Exiting." + exit 2 +fi + +M='-machine virt' + +if ! $qemu $M -device '?' 2>&1 | grep virtconsole > /dev/null; then + echo "$qpath doesn't support virtio-console for chr-testdev. Exiting." + exit 2 +fi + +if $qemu $M -chardev testdev,id=id -kernel . 2>&1 \ + | grep backend > /dev/null; then + echo "$qpath doesn't support chr-testdev. Exiting." + exit 2 +fi + +M='-machine virt,accel=kvm:tcg' +chr_testdev='-device virtio-serial-device' +chr_testdev+=' -device virtconsole,chardev=ctd -chardev testdev,id=ctd' + +command="$qemu $M -cpu $PROCESSOR $chr_testdev" +command+=" -display none -serial stdio -kernel" + +echo $command "$@" +$command "$@" +ret=$? +echo Return value from qemu: $ret +exit $ret diff --git a/arm/selftest.c b/arm/selftest.c new file mode 100644 index 0000000000000..e674103379956 --- /dev/null +++ b/arm/selftest.c @@ -0,0 +1,86 @@ +/* + * Test the framework itself. These tests confirm that setup works. + * + * Copyright (C) 2014, Red Hat Inc, Andrew Jones + * + * This work is licensed under the terms of the GNU LGPL, version 2. + */ +#include "libcflat.h" +#include "asm/setup.h" + +#define TESTGRP "selftest" + +static char testname[64]; + +static void testname_set(const char *subtest) +{ + strcpy(testname, TESTGRP); + if (subtest) { + strcat(testname, "::"); + strcat(testname, subtest); + } +} + +static void assert_args(int num_args, int needed_args) +{ + if (num_args < needed_args) { + printf("%s: not enough arguments\n", testname); + abort(); + } +} + +static char *split_var(char *s, long *val) +{ + char *p; + + p = strchr(s, '='); + if (!p) + return NULL; + + *val = atol(p+1); + *p = '\0'; + + return s; +} + +static void check_setup(int argc, char **argv) +{ + int nr_tests = 0, i; + char *var; + long val; + + for (i = 0; i < argc; ++i) { + + var = split_var(argv[i], &val); + if (!var) + continue; + + if (strcmp(var, "mem") == 0) { + + phys_addr_t memsize = PHYS_END - PHYS_OFFSET; + phys_addr_t expected = ((phys_addr_t)val)*1024*1024; + + report("%s[%s]", memsize == expected, testname, "mem"); + ++nr_tests; + + } else if (strcmp(var, "smp") == 0) { + + report("%s[%s]", nr_cpus == (int)val, testname, "smp"); + ++nr_tests; + } + } + + assert_args(nr_tests, 2); +} + +int main(int argc, char **argv) +{ + testname_set(NULL); + assert_args(argc, 1); + testname_set(argv[0]); + + if (strcmp(argv[0], "setup") == 0) + check_setup(argc-1, &argv[1]); + + return report_summary(); +} diff --git a/arm/unittests.cfg b/arm/unittests.cfg new file mode 100644 index 0000000000000..da9dfd7b1f118 --- /dev/null +++ b/arm/unittests.cfg @@ -0,0 +1,18 @@ +# Define your new unittest following the convention: +# [unittest_name] +# file = foo.flat # Name of the flat file to be used +# smp = 2 # Number of processors the VM will use during this test +# extra_params = -append # Additional parameters used +# arch = arm/arm64 # Only if test case is specific to one +# groups = group1 group2 # Used to identify test cases with run_tests -g ... + +# +# Test that the configured number of processors (smp = ), and +# that the configured amount of memory (-m ) are correctly setup +# by the framework. +# +[selftest::setup] +file = selftest.flat +smp = 1 +extra_params = -m 256 -append 'setup smp=1 mem=256' +groups = selftest diff --git a/config/config-arm.mak b/config/config-arm.mak new file mode 100644 index 0000000000000..ff965428e0e5b --- /dev/null +++ b/config/config-arm.mak @@ -0,0 +1,74 @@ +# +# arm makefile +# +# Authors: Andrew Jones +# + +tests-common = \ + $(TEST_DIR)/selftest.flat + +tests = + +all: test_cases + +################################################################## +bits = 32 +ldarch = elf32-littlearm + +ifeq ($(LOADADDR),) + LOADADDR = 0x40000000 +endif +phys_base = $(LOADADDR) +kernel_offset = 0x10000 + +CFLAGS += -D__arm__ +CFLAGS += -marm +CFLAGS += -mcpu=$(PROCESSOR) +CFLAGS += -std=gnu99 +CFLAGS += -ffreestanding +CFLAGS += -Wextra +CFLAGS += -O2 +CFLAGS += -I lib -I lib/libfdt + +cflatobjs += \ + lib/alloc.o \ + lib/devicetree.o \ + lib/virtio.o \ + lib/virtio-mmio.o \ + lib/chr-testdev.o \ + lib/arm/io.o \ + lib/arm/setup.o + +libeabi = lib/arm/libeabi.a +eabiobjs = lib/arm/eabi_compat.o + +libgcc := $(shell $(CC) -m$(ARCH) --print-libgcc-file-name) +start_addr := $(shell printf "%x\n" $$(( $(phys_base) + $(kernel_offset) ))) + +FLATLIBS = $(libcflat) $(LIBFDT_archive) $(libgcc) $(libeabi) +%.elf: LDFLAGS = $(CFLAGS) -nostdlib +%.elf: %.o $(FLATLIBS) arm/flat.lds + $(CC) $(LDFLAGS) -o $@ \ + -Wl,-T,arm/flat.lds,--build-id=none,-Ttext=$(start_addr) \ + $(filter %.o, $^) $(FLATLIBS) + +%.flat: %.elf + $(OBJCOPY) -O binary $^ $@ + +$(libeabi): $(eabiobjs) + $(AR) rcs $@ $^ + +arch_clean: libfdt_clean + $(RM) $(TEST_DIR)/*.{o,flat,elf} $(libeabi) $(eabiobjs) \ + $(TEST_DIR)/.*.d lib/arm/.*.d + +################################################################## + +tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg + +cstart.o = $(TEST_DIR)/cstart.o + +test_cases: $(tests-common) $(tests) + +$(TEST_DIR)/selftest.elf: $(cstart.o) $(TEST_DIR)/selftest.o + diff --git a/configure b/configure index aaa1b50ab1b98..afdd62800f56e 100755 --- a/configure +++ b/configure @@ -6,8 +6,7 @@ cc=gcc ld=ld objcopy=objcopy ar=ar -arch=`uname -m | sed -e s/i.86/i386/` -processor="$arch" +arch=`uname -m | sed -e s/i.86/i386/ | sed -e 's/arm.*/arm/'` cross_prefix= usage() { @@ -16,6 +15,7 @@ usage() { Options include: --arch=ARCH architecture to compile for ($arch) + --processor=PROCESSOR processor to compile for ($arch) --cross-prefix=PREFIX cross compiler prefix --cc=CC c compiler to use ($cc) --ld=LD ld linker to use ($ld) @@ -62,6 +62,12 @@ while [[ "$1" = -* ]]; do ;; esac done +[ -z "$processor" ] && processor="$arch" + +if [ "$processor" = "arm" ]; then + processor="cortex-a15" +fi + if [ "$arch" = "i386" ] || [ "$arch" = "x86_64" ]; then testdir=x86 else @@ -76,6 +82,7 @@ if [ -f $testdir/run ]; then fi # check for dependent 32 bit libraries +if [ "$arch" != "arm" ]; then cat << EOF > lib_test.c #include #include @@ -90,6 +97,7 @@ if [ $exit -eq 0 ]; then api=true fi rm -f lib_test.c +fi # link lib/asm for the architecture rm -f lib/asm diff --git a/lib/argv.c b/lib/argv.c index 4ee54a6eeac3e..62dd1fd4cf980 100644 --- a/lib/argv.c +++ b/lib/argv.c @@ -31,3 +31,12 @@ void __setup_args(void) } __argc = argv - __argv; } + +void setup_args(char *args) +{ + if (!args) + return; + + __args = args; + __setup_args(); +} diff --git a/lib/arm/asm/barrier.h b/lib/arm/asm/barrier.h new file mode 100644 index 0000000000000..acaeab5123431 --- /dev/null +++ b/lib/arm/asm/barrier.h @@ -0,0 +1,18 @@ +#ifndef _ASMARM_BARRIER_H_ +#define _ASMARM_BARRIER_H_ +/* + * Adapted form arch/arm/include/asm/barrier.h + */ + +#define isb(option) __asm__ __volatile__ ("isb " #option : : : "memory") +#define dsb(option) __asm__ __volatile__ ("dsb " #option : : : "memory") +#define dmb(option) __asm__ __volatile__ ("dmb " #option : : : "memory") + +#define mb() dsb() +#define rmb() dsb() +#define wmb() dsb(st) +#define smp_mb() dmb(ish) +#define smp_rmb() smp_mb() +#define smp_wmb() dmb(ishst) + +#endif /* _ASMARM_BARRIER_H_ */ diff --git a/lib/arm/asm/io.h b/lib/arm/asm/io.h new file mode 100644 index 0000000000000..51ec6e9aa2e99 --- /dev/null +++ b/lib/arm/asm/io.h @@ -0,0 +1,24 @@ +#ifndef _ASMARM_IO_H_ +#define _ASMARM_IO_H_ +#include "libcflat.h" +#include "asm/barrier.h" + +#define __bswap16 bswap16 +static inline u16 bswap16(u16 val) +{ + u16 ret; + asm volatile("rev16 %0, %1" : "=r" (ret) : "r" (val)); + return ret; +} + +#define __bswap32 bswap32 +static inline u32 bswap32(u32 val) +{ + u32 ret; + asm volatile("rev %0, %1" : "=r" (ret) : "r" (val)); + return ret; +} + +#include "asm-generic/io.h" + +#endif /* _ASMARM_IO_H_ */ diff --git a/lib/arm/asm/page.h b/lib/arm/asm/page.h new file mode 100644 index 0000000000000..91a4bc3b7f86e --- /dev/null +++ b/lib/arm/asm/page.h @@ -0,0 +1 @@ +#include "asm-generic/page.h" diff --git a/lib/arm/asm/setup.h b/lib/arm/asm/setup.h new file mode 100644 index 0000000000000..21445ef2085fc --- /dev/null +++ b/lib/arm/asm/setup.h @@ -0,0 +1,27 @@ +#ifndef _ASMARM_SETUP_H_ +#define _ASMARM_SETUP_H_ +/* + * Copyright (C) 2014, Red Hat Inc, Andrew Jones + * + * This work is licensed under the terms of the GNU LGPL, version 2. + */ +#include "libcflat.h" +#include "alloc.h" + +#define NR_CPUS 8 +extern u32 cpus[NR_CPUS]; +extern int nr_cpus; + +extern phys_addr_t __phys_offset, __phys_end; + +#define PHYS_OFFSET (__phys_offset) +#define PHYS_END (__phys_end) +#define PHYS_SHIFT 40 +#define PHYS_SIZE (1ULL << PHYS_SHIFT) +#define PHYS_MASK (PHYS_SIZE - 1ULL) + +#define L1_CACHE_SHIFT 6 +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) +#define SMP_CACHE_BYTES L1_CACHE_BYTES + +#endif /* _ASMARM_SETUP_H_ */ diff --git a/lib/arm/asm/spinlock.h b/lib/arm/asm/spinlock.h new file mode 100644 index 0000000000000..04f5a1a5538e2 --- /dev/null +++ b/lib/arm/asm/spinlock.h @@ -0,0 +1,16 @@ +#ifndef _ASMARM_SPINLOCK_H_ +#define _ASMARM_SPINLOCK_H_ + +struct spinlock { + int v; +}; + +//TODO +static inline void spin_lock(struct spinlock *lock __unused) +{ +} +static inline void spin_unlock(struct spinlock *lock __unused) +{ +} + +#endif /* _ASMARM_SPINLOCK_H_ */ diff --git a/lib/arm/eabi_compat.c b/lib/arm/eabi_compat.c new file mode 100644 index 0000000000000..59d624dcd9277 --- /dev/null +++ b/lib/arm/eabi_compat.c @@ -0,0 +1,20 @@ +/* + * Adapted from u-boot's arch/arm/lib/eabi_compat.c + */ +#include "libcflat.h" + +int raise(int signum __unused) +{ + printf("Divide by zero!\n"); + abort(); + return 0; +} + +/* Dummy functions to avoid linker complaints */ +void __aeabi_unwind_cpp_pr0(void) +{ +} + +void __aeabi_unwind_cpp_pr1(void) +{ +} diff --git a/lib/arm/io.c b/lib/arm/io.c new file mode 100644 index 0000000000000..60c0fdba2bff6 --- /dev/null +++ b/lib/arm/io.c @@ -0,0 +1,65 @@ +/* + * Each architecture must implement puts() and exit() with the I/O + * devices exposed from QEMU, e.g. pl011 and chr-testdev. That's + * what's done here, along with initialization functions for those + * devices. + * + * Copyright (C) 2014, Red Hat Inc, Andrew Jones + * + * This work is licensed under the terms of the GNU LGPL, version 2. + */ +#include "libcflat.h" +#include "devicetree.h" +#include "chr-testdev.h" +#include "asm/spinlock.h" +#include "asm/io.h" + +extern void halt(int code); + +/* + * Use this guess for the pl011 base in order to make an attempt at + * having earlier printf support. We'll overwrite it with the real + * base address that we read from the device tree later. + */ +#define QEMU_MACH_VIRT_PL011_BASE 0x09000000UL + +static struct spinlock uart_lock; +static volatile u8 *uart0_base = (u8 *)QEMU_MACH_VIRT_PL011_BASE; + +static void uart0_init(void) +{ + const char *compatible = "arm,pl011"; + struct dt_pbus_reg base; + int ret; + + ret = dt_pbus_get_base_compatible(compatible, &base); + assert(ret == 0 || ret == -FDT_ERR_NOTFOUND); + + if (ret) { + printf("%s: %s not found in the device tree, aborting...\n", + __func__, compatible); + abort(); + } + + uart0_base = ioremap(base.addr, base.size); +} + +void io_init(void) +{ + uart0_init(); + chr_testdev_init(); +} + +void puts(const char *s) +{ + spin_lock(&uart_lock); + while (*s) + writeb(*s++, uart0_base); + spin_unlock(&uart_lock); +} + +void exit(int code) +{ + chr_testdev_exit(code); + halt(code); +} diff --git a/lib/arm/setup.c b/lib/arm/setup.c new file mode 100644 index 0000000000000..3941c9757dcb2 --- /dev/null +++ b/lib/arm/setup.c @@ -0,0 +1,82 @@ +/* + * Initialize machine setup information and I/O. + * + * After running setup() unit tests may query how many cpus they have + * (nr_cpus), how much memory they have (PHYS_END - PHYS_OFFSET), may + * use dynamic memory allocation (malloc, etc.), printf, and exit. + * Finally, argc and argv are also ready to be passed to main(). + * + * Copyright (C) 2014, Red Hat Inc, Andrew Jones + * + * This work is licensed under the terms of the GNU LGPL, version 2. + */ +#include "libcflat.h" +#include "libfdt/libfdt.h" +#include "devicetree.h" +#include "alloc.h" +#include "asm/setup.h" +#include "asm/page.h" + +extern unsigned long stacktop; +extern void io_init(void); +extern void setup_args(const char *args); + +u32 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0UL) }; +int nr_cpus; + +phys_addr_t __phys_offset, __phys_end; + +static void cpu_set(int fdtnode __unused, u32 regval, void *info __unused) +{ + assert(nr_cpus < NR_CPUS); + cpus[nr_cpus++] = regval; +} + +static void cpu_init(void) +{ + nr_cpus = 0; + assert(dt_for_each_cpu_node(cpu_set, NULL) == 0); +} + +static void mem_init(phys_addr_t freemem_start) +{ + /* we only expect one membank to be defined in the DT */ + struct dt_pbus_reg regs[1]; + phys_addr_t mem_start, mem_end; + + assert(dt_get_memory_params(regs, 1)); + + mem_start = regs[0].addr; + mem_end = mem_start + regs[0].size; + + assert(!(mem_start & ~PHYS_MASK) && !((mem_end-1) & ~PHYS_MASK)); + assert(freemem_start >= mem_start && freemem_start < mem_end); + + __phys_offset = mem_start; /* PHYS_OFFSET */ + __phys_end = mem_end; /* PHYS_END */ + + phys_alloc_init(freemem_start, mem_end - freemem_start); + phys_alloc_set_minimum_alignment(SMP_CACHE_BYTES); +} + +void setup(unsigned long arg __unused, unsigned long id __unused, + const void *fdt) +{ + const char *bootargs; + u32 fdt_size; + + /* + * Move the fdt to just above the stack. The free memory + * then starts just after the fdt. + */ + fdt_size = fdt_totalsize(fdt); + assert(fdt_move(fdt, &stacktop, fdt_size) == 0); + assert(dt_init(&stacktop) == 0); + + mem_init(PAGE_ALIGN((unsigned long)&stacktop + fdt_size)); + io_init(); + cpu_init(); + + assert(dt_get_bootargs(&bootargs) == 0); + setup_args(bootargs); +}