From d9c1951f400942bbdb41e75a73d151e4a9d5469e Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 27 Feb 2013 18:05:59 +0000 Subject: arm64: add read_cpuid_{implementor,part_number,mpidr} In order to preserve some kind of source compatibility between arm and arm64, introduce read_cpuid_{implementor,part_number,mpidr} which are used on KVM to find out which CPU we're running on. Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index ef54125..7a31702 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -17,6 +17,7 @@ #define __ASM_CPUTYPE_H #define ID_MIDR_EL1 "midr_el1" +#define ID_MPIDR_EL1 "mpidr_el1" #define ID_CTR_EL0 "ctr_el0" #define ID_AA64PFR0_EL1 "id_aa64pfr0_el1" @@ -31,6 +32,12 @@ __val; \ }) +#define ARM_CPU_IMP_ARM 0x41 + +#define ARM_CPU_PART_AEM_V8 0xD0F0 +#define ARM_CPU_PART_FOUNDATION 0xD000 +#define ARM_CPU_PART_CORTEX_A57 0xD070 + /* * The CPU ID never changes at run time, so we might as well tell the * compiler that it's constant. Use this function to read the CPU ID @@ -41,6 +48,21 @@ static inline u32 __attribute_const__ read_cpuid_id(void) return read_cpuid(ID_MIDR_EL1); } +static inline u64 __attribute_const__ read_cpuid_mpidr(void) +{ + return read_cpuid(ID_MPIDR_EL1); +} + +static inline unsigned int __attribute_const__ read_cpuid_implementor(void) +{ + return (read_cpuid_id() & 0xFF000000) >> 24; +} + +static inline unsigned int __attribute_const__ read_cpuid_part_number(void) +{ + return (read_cpuid_id() & 0xFFF0); +} + static inline u32 __attribute_const__ read_cpuid_cachetype(void) { return read_cpuid(ID_CTR_EL0); -- cgit v0.10.2 From 0492f72508184d451101564e235b0c32edf9acd3 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 27 Feb 2013 18:06:00 +0000 Subject: arm64: early_printk: add support for FastModel console output Enable early_printk to use the FastModel semihosting to output the early kernel messages. Works both for host and guest kernels. To use this feature, pass "early_printk=smh" to the kernel. Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas diff --git a/arch/arm64/kernel/early_printk.c b/arch/arm64/kernel/early_printk.c index 7e320a2..0bb7436 100644 --- a/arch/arm64/kernel/early_printk.c +++ b/arch/arm64/kernel/early_printk.c @@ -40,6 +40,17 @@ static void pl011_printch(char ch) ; } +/* + * Semihosting-based debug console + */ +static void smh_printch(char ch) +{ + asm volatile("mov x1, %0\n" + "mov x0, #3\n" + "hlt 0xf000\n" + : : "r" (&ch) : "x0", "x1", "memory"); +} + struct earlycon_match { const char *name; void (*printch)(char ch); @@ -47,6 +58,7 @@ struct earlycon_match { static const struct earlycon_match earlycon_match[] __initconst = { { .name = "pl011", .printch = pl011_printch, }, + { .name = "smh", .printch = smh_printch, }, {} }; -- cgit v0.10.2 From e53f2f4b570d85c7208dfc97de54db1296b88207 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Fri, 1 Mar 2013 08:41:47 +0000 Subject: arm64: add support for 8250/16550 earlyprintk This patch adds support for using earlyprintk with 8250/16550 UART ports. The 8250/16550 UART can either have 8-bit or 32-bit aligned registers which is HW vendor dependent. Kernel args for 8-bit aligned regs: earlyprintk=uart8250-8bit, Kernel args for 32-bit aligned regs: earlyprintk=uart8250-32bit, Signed-off-by: Anup Patel Reviewed-by: Marc Zyngier Signed-off-by: Catalin Marinas diff --git a/arch/arm64/kernel/early_printk.c b/arch/arm64/kernel/early_printk.c index 0bb7436..ac974f4 100644 --- a/arch/arm64/kernel/early_printk.c +++ b/arch/arm64/kernel/early_printk.c @@ -24,6 +24,7 @@ #include #include +#include static void __iomem *early_base; static void (*printch)(char ch); @@ -51,6 +52,26 @@ static void smh_printch(char ch) : : "r" (&ch) : "x0", "x1", "memory"); } +/* + * 8250/16550 (8-bit aligned registers) single character TX. + */ +static void uart8250_8bit_printch(char ch) +{ + while (!(readb_relaxed(early_base + UART_LSR) & UART_LSR_THRE)) + ; + writeb_relaxed(ch, early_base + UART_TX); +} + +/* + * 8250/16550 (32-bit aligned registers) single character TX. + */ +static void uart8250_32bit_printch(char ch) +{ + while (!(readl_relaxed(early_base + (UART_LSR << 2)) & UART_LSR_THRE)) + ; + writel_relaxed(ch, early_base + (UART_TX << 2)); +} + struct earlycon_match { const char *name; void (*printch)(char ch); @@ -59,6 +80,8 @@ struct earlycon_match { static const struct earlycon_match earlycon_match[] __initconst = { { .name = "pl011", .printch = pl011_printch, }, { .name = "smh", .printch = smh_printch, }, + { .name = "uart8250-8bit", .printch = uart8250_8bit_printch, }, + { .name = "uart8250-32bit", .printch = uart8250_32bit_printch, }, {} }; -- cgit v0.10.2 From de79a64d61ed3f7ccec9f9661fab2f3e97256243 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Fri, 8 Feb 2013 12:18:15 +0000 Subject: arm64: Initialise the clocks described via DT This patch adds an arch_initcall() for the of_clk_init() clock initialisation. Signed-off-by: Catalin Marinas diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 113db86..9c023d7 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -277,6 +278,13 @@ void __init setup_arch(char **cmdline_p) #endif } +static int __init arm64_of_clk_init(void) +{ + of_clk_init(NULL); + return 0; +} +arch_initcall(arm64_of_clk_init); + static DEFINE_PER_CPU(struct cpu, cpu_data); static int __init topology_init(void) -- cgit v0.10.2 From 3e98fdacc59bbbdbb659be1a144ccc48ed4860fa Mon Sep 17 00:00:00 2001 From: Javi Merino Date: Thu, 31 Jan 2013 20:09:04 +0000 Subject: arm64: kernel: make the pen of the secondary a 64-bit unsigned value Change the prototype of write_pen_release() accordingly and clarify that's holding the hardware id of the secondary that's going to boot. This is in preparation of getting HWIDs parsed from the DT. Signed-off-by: Javi Merino Signed-off-by: Catalin Marinas diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index 7a31702..9397a17 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -26,6 +26,8 @@ #define ID_AA64ISAR0_EL1 "id_aa64isar0_el1" #define ID_AA64MMFR0_EL1 "id_aa64mmfr0_el1" +#define INVALID_HWID ULONG_MAX + #define read_cpuid(reg) ({ \ u64 __val; \ asm("mrs %0, " reg : "=r" (__val)); \ diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index bdd3459..a57a373 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -53,7 +53,7 @@ * where to place its SVC stack */ struct secondary_data secondary_data; -volatile unsigned long secondary_holding_pen_release = -1; +volatile unsigned long secondary_holding_pen_release = INVALID_HWID; enum ipi_msg_type { IPI_RESCHEDULE, @@ -70,7 +70,7 @@ static DEFINE_RAW_SPINLOCK(boot_lock); * in coherency or not. This is necessary for the hotplug code to work * reliably. */ -static void __cpuinit write_pen_release(int val) +static void __cpuinit write_pen_release(u64 val) { void *start = (void *)&secondary_holding_pen_release; unsigned long size = sizeof(secondary_holding_pen_release); @@ -105,7 +105,7 @@ static int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { - if (secondary_holding_pen_release == -1UL) + if (secondary_holding_pen_release == INVALID_HWID) break; udelay(10); } @@ -116,7 +116,7 @@ static int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) */ raw_spin_unlock(&boot_lock); - return secondary_holding_pen_release != -1 ? -ENOSYS : 0; + return secondary_holding_pen_release != INVALID_HWID ? -ENOSYS : 0; } static DECLARE_COMPLETION(cpu_running); @@ -190,7 +190,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) * Let the primary processor know we're out of the * pen, then head off into the C entry point */ - write_pen_release(-1); + write_pen_release(INVALID_HWID); /* * Synchronise with the boot thread. -- cgit v0.10.2 From 4c7aa0021356ee91b96cea51b8b7fadebaba489e Mon Sep 17 00:00:00 2001 From: Javi Merino Date: Wed, 29 Aug 2012 09:47:19 +0100 Subject: arm64: kernel: initialise cpu_logical_map from the DT When booting the kernel, the cpu logical id map must be initialised using device tree data passed by FW or through an embedded blob. This patch parses the reg property in device tree "cpu" nodes, retrieves the corresponding CPUs hardware identifiers (MPIDR) and initialises the cpu logical map accordingly. The device tree HW identifiers are considered valid if all CPU nodes contain a "reg" property, there are no duplicate "reg" entries and the DT defines a CPU node whose "reg" property defines affinity levels that matches those of the boot CPU. The primary CPU is assigned cpu logical number 0 to keep the current convention valid. Based on a0ae02405076ac32bd17ece976e914b5b6075bb0 (ARM: kernel: add device tree init map function). Signed-off-by: Javi Merino Signed-off-by: Catalin Marinas diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index 9397a17..3780b2e 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -28,6 +28,8 @@ #define INVALID_HWID ULONG_MAX +#define MPIDR_HWID_BITMASK 0xff00ffffff + #define read_cpuid(reg) ({ \ u64 __val; \ asm("mrs %0, " reg : "=r" (__val)); \ diff --git a/arch/arm64/include/asm/smp_plat.h b/arch/arm64/include/asm/smp_plat.h new file mode 100644 index 0000000..ed43a0d --- /dev/null +++ b/arch/arm64/include/asm/smp_plat.h @@ -0,0 +1,30 @@ +/* + * Definitions specific to SMP platforms. + * + * Copyright (C) 2013 ARM Ltd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __ASM_SMP_PLAT_H +#define __ASM_SMP_PLAT_H + +#include + +/* + * Logical CPU mapping. + */ +extern u64 __cpu_logical_map[NR_CPUS]; +#define cpu_logical_map(cpu) __cpu_logical_map[cpu] + +#endif /* __ASM_SMP_PLAT_H */ diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 9c023d7..6a9a532 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -241,6 +242,8 @@ static void __init request_standard_resources(void) } } +u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID }; + void __init setup_arch(char **cmdline_p) { setup_processor(); @@ -265,6 +268,7 @@ void __init setup_arch(char **cmdline_p) psci_init(); + cpu_logical_map(0) = read_cpuid_mpidr() & MPIDR_HWID_BITMASK; #ifdef CONFIG_SMP smp_init_cpus(); #endif diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index a57a373..d4dcc65 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -96,7 +97,7 @@ static int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) /* * Update the pen release flag. */ - write_pen_release(cpu); + write_pen_release(cpu_logical_map(cpu)); /* * Send an event, causing the secondaries to read pen_release. @@ -257,15 +258,77 @@ static const struct smp_enable_ops * __init smp_get_enable_ops(const char *name) } /* - * Enumerate the possible CPU set from the device tree. + * Enumerate the possible CPU set from the device tree and build the + * cpu logical map array containing MPIDR values related to logical + * cpus. Assumes that cpu_logical_map(0) has already been initialized. */ void __init smp_init_cpus(void) { const char *enable_method; struct device_node *dn = NULL; - int cpu = 0; + int i, cpu = 1; + bool bootcpu_valid = false; while ((dn = of_find_node_by_type(dn, "cpu"))) { + u64 hwid; + + /* + * A cpu node with missing "reg" property is + * considered invalid to build a cpu_logical_map + * entry. + */ + if (of_property_read_u64(dn, "reg", &hwid)) { + pr_err("%s: missing reg property\n", dn->full_name); + goto next; + } + + /* + * Non affinity bits must be set to 0 in the DT + */ + if (hwid & ~MPIDR_HWID_BITMASK) { + pr_err("%s: invalid reg property\n", dn->full_name); + goto next; + } + + /* + * Duplicate MPIDRs are a recipe for disaster. Scan + * all initialized entries and check for + * duplicates. If any is found just ignore the cpu. + * cpu_logical_map was initialized to INVALID_HWID to + * avoid matching valid MPIDR values. + */ + for (i = 1; (i < cpu) && (i < NR_CPUS); i++) { + if (cpu_logical_map(i) == hwid) { + pr_err("%s: duplicate cpu reg properties in the DT\n", + dn->full_name); + goto next; + } + } + + /* + * The numbering scheme requires that the boot CPU + * must be assigned logical id 0. Record it so that + * the logical map built from DT is validated and can + * be used. + */ + if (hwid == cpu_logical_map(0)) { + if (bootcpu_valid) { + pr_err("%s: duplicate boot cpu reg property in DT\n", + dn->full_name); + goto next; + } + + bootcpu_valid = true; + + /* + * cpu_logical_map has already been + * initialized and the boot cpu doesn't need + * the enable-method so continue without + * incrementing cpu. + */ + continue; + } + if (cpu >= NR_CPUS) goto next; @@ -274,22 +337,24 @@ void __init smp_init_cpus(void) */ enable_method = of_get_property(dn, "enable-method", NULL); if (!enable_method) { - pr_err("CPU %d: missing enable-method property\n", cpu); + pr_err("%s: missing enable-method property\n", + dn->full_name); goto next; } smp_enable_ops[cpu] = smp_get_enable_ops(enable_method); if (!smp_enable_ops[cpu]) { - pr_err("CPU %d: invalid enable-method property: %s\n", - cpu, enable_method); + pr_err("%s: invalid enable-method property: %s\n", + dn->full_name, enable_method); goto next; } if (smp_enable_ops[cpu]->init_cpu(dn, cpu)) goto next; - set_cpu_possible(cpu, true); + pr_debug("cpu logical map 0x%llx\n", hwid); + cpu_logical_map(cpu) = hwid; next: cpu++; } @@ -298,6 +363,19 @@ next: if (cpu > NR_CPUS) pr_warning("no. of cores (%d) greater than configured maximum of %d - clipping\n", cpu, NR_CPUS); + + if (!bootcpu_valid) { + pr_err("DT missing boot CPU MPIDR, not enabling secondaries\n"); + return; + } + + /* + * All the cpus that made it to the cpu_logical_map have been + * validated so set them as possible cpus. + */ + for (i = 0; i < NR_CPUS; i++) + if (cpu_logical_map(i) != INVALID_HWID) + set_cpu_possible(i, true); } void __init smp_prepare_cpus(unsigned int max_cpus) -- cgit v0.10.2 From 0359b0e2d0bbd28289c38ebe779b5f1c61f8ccc8 Mon Sep 17 00:00:00 2001 From: Javi Merino Date: Wed, 29 Aug 2012 18:32:18 +0100 Subject: arm64: head: match all affinity levels in the pen of the secondaries The reg property of the cpu nodes in the DT now contains all the affinity levels in (MPIDR[39:32] and MPIDR[23:0]) and that's what boot_secondary() writes in the pen, so increase the mask in secondary_holding_pen accordingly. Signed-off-by: Javi Merino Signed-off-by: Catalin Marinas diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index 3780b2e..cf27494 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -42,6 +42,8 @@ #define ARM_CPU_PART_FOUNDATION 0xD000 #define ARM_CPU_PART_CORTEX_A57 0xD070 +#ifndef __ASSEMBLY__ + /* * The CPU ID never changes at run time, so we might as well tell the * compiler that it's constant. Use this function to read the CPU ID @@ -72,4 +74,6 @@ static inline u32 __attribute_const__ read_cpuid_cachetype(void) return read_cpuid(ID_CTR_EL0); } +#endif /* __ASSEMBLY__ */ + #endif diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 0a0a497..53dcae4 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -229,7 +230,8 @@ ENTRY(secondary_holding_pen) bl __calc_phys_offset // x24=phys offset bl el2_setup // Drop to EL1 mrs x0, mpidr_el1 - and x0, x0, #15 // CPU number + ldr x1, =MPIDR_HWID_BITMASK + and x0, x0, x1 adr x1, 1b ldp x2, x3, [x1] sub x1, x1, x2 -- cgit v0.10.2 From 4a8992271c843cb5bcd3321bf6a02eb251280b1d Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Thu, 21 Mar 2013 16:16:43 +0000 Subject: arm64: klib: Optimised memory functions This patch introduces AArch64-specific memory functions (memcpy, memmove, memchr, memset). These functions are not optimised for any CPU implementation but can be used as a starting point once hardware is available. Signed-off-by: Catalin Marinas diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild index e5fe4f9..a13a4a4 100644 --- a/arch/arm64/include/asm/Kbuild +++ b/arch/arm64/include/asm/Kbuild @@ -39,7 +39,6 @@ generic-y += shmbuf.h generic-y += sizes.h generic-y += socket.h generic-y += sockios.h -generic-y += string.h generic-y += switch_to.h generic-y += swab.h generic-y += termbits.h diff --git a/arch/arm64/include/asm/string.h b/arch/arm64/include/asm/string.h new file mode 100644 index 0000000..be8a644 --- /dev/null +++ b/arch/arm64/include/asm/string.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2013 ARM Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef __ASM_STRING_H +#define __ASM_STRING_H + +#define __HAVE_ARCH_MEMCPY +extern void *memcpy(void *, const void *, __kernel_size_t); + +#define __HAVE_ARCH_MEMMOVE +extern void *memmove(void *, const void *, __kernel_size_t); + +#define __HAVE_ARCH_MEMCHR +extern void *memchr(const void *, int, __kernel_size_t); + +#define __HAVE_ARCH_MEMSET +extern void *memset(void *, int, __kernel_size_t); + +#endif diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c index aa3e948..d7f7b17 100644 --- a/arch/arm64/kernel/arm64ksyms.c +++ b/arch/arm64/kernel/arm64ksyms.c @@ -46,3 +46,9 @@ EXPORT_SYMBOL(__atomic_hash); /* physical memory */ EXPORT_SYMBOL(memstart_addr); + + /* string / mem functions */ +EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memmove); +EXPORT_SYMBOL(memchr); diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile index 2fb7f60..2fce139 100644 --- a/arch/arm64/lib/Makefile +++ b/arch/arm64/lib/Makefile @@ -1,4 +1,5 @@ lib-y := bitops.o delay.o \ strncpy_from_user.o strnlen_user.o clear_user.o \ copy_from_user.o copy_to_user.o copy_in_user.o \ - copy_page.o clear_page.o + copy_page.o clear_page.o \ + memchr.o memcpy.o memmove.o memset.o diff --git a/arch/arm64/lib/memchr.S b/arch/arm64/lib/memchr.S new file mode 100644 index 0000000..8636b75 --- /dev/null +++ b/arch/arm64/lib/memchr.S @@ -0,0 +1,44 @@ +/* + * Based on arch/arm/lib/memchr.S + * + * Copyright (C) 1995-2000 Russell King + * Copyright (C) 2013 ARM Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +/* + * Find a character in an area of memory. + * + * Parameters: + * x0 - buf + * x1 - c + * x2 - n + * Returns: + * x0 - address of first occurrence of 'c' or 0 + */ +ENTRY(memchr) + and w1, w1, #0xff +1: subs x2, x2, #1 + b.mi 2f + ldrb w3, [x0], #1 + cmp w3, w1 + b.ne 1b + sub x0, x0, #1 + ret +2: mov x0, #0 + ret +ENDPROC(memchr) diff --git a/arch/arm64/lib/memcpy.S b/arch/arm64/lib/memcpy.S new file mode 100644 index 0000000..27b5003 --- /dev/null +++ b/arch/arm64/lib/memcpy.S @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2013 ARM Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +/* + * Copy a buffer from src to dest (alignment handled by the hardware) + * + * Parameters: + * x0 - dest + * x1 - src + * x2 - n + * Returns: + * x0 - dest + */ +ENTRY(memcpy) + mov x4, x0 + subs x2, x2, #8 + b.mi 2f +1: ldr x3, [x1], #8 + subs x2, x2, #8 + str x3, [x4], #8 + b.pl 1b +2: adds x2, x2, #4 + b.mi 3f + ldr w3, [x1], #4 + sub x2, x2, #4 + str w3, [x4], #4 +3: adds x2, x2, #2 + b.mi 4f + ldrh w3, [x1], #2 + sub x2, x2, #2 + strh w3, [x4], #2 +4: adds x2, x2, #1 + b.mi 5f + ldrb w3, [x1] + strb w3, [x4] +5: ret +ENDPROC(memcpy) diff --git a/arch/arm64/lib/memmove.S b/arch/arm64/lib/memmove.S new file mode 100644 index 0000000..b79fdfa --- /dev/null +++ b/arch/arm64/lib/memmove.S @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2013 ARM Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +/* + * Move a buffer from src to test (alignment handled by the hardware). + * If dest <= src, call memcpy, otherwise copy in reverse order. + * + * Parameters: + * x0 - dest + * x1 - src + * x2 - n + * Returns: + * x0 - dest + */ +ENTRY(memmove) + cmp x0, x1 + b.ls memcpy + add x4, x0, x2 + add x1, x1, x2 + subs x2, x2, #8 + b.mi 2f +1: ldr x3, [x1, #-8]! + subs x2, x2, #8 + str x3, [x4, #-8]! + b.pl 1b +2: adds x2, x2, #4 + b.mi 3f + ldr w3, [x1, #-4]! + sub x2, x2, #4 + str w3, [x4, #-4]! +3: adds x2, x2, #2 + b.mi 4f + ldrh w3, [x1, #-2]! + sub x2, x2, #2 + strh w3, [x4, #-2]! +4: adds x2, x2, #1 + b.mi 5f + ldrb w3, [x1, #-1] + strb w3, [x4, #-1] +5: ret +ENDPROC(memmove) diff --git a/arch/arm64/lib/memset.S b/arch/arm64/lib/memset.S new file mode 100644 index 0000000..87e4a68 --- /dev/null +++ b/arch/arm64/lib/memset.S @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2013 ARM Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +/* + * Fill in the buffer with character c (alignment handled by the hardware) + * + * Parameters: + * x0 - buf + * x1 - c + * x2 - n + * Returns: + * x0 - buf + */ +ENTRY(memset) + mov x4, x0 + and w1, w1, #0xff + orr w1, w1, w1, lsl #8 + orr w1, w1, w1, lsl #16 + orr x1, x1, x1, lsl #32 + subs x2, x2, #8 + b.mi 2f +1: str x1, [x4], #8 + subs x2, x2, #8 + b.pl 1b +2: adds x2, x2, #4 + b.mi 3f + sub x2, x2, #4 + str w1, [x4], #4 +3: adds x2, x2, #2 + b.mi 4f + sub x2, x2, #2 + strh w1, [x4], #2 +4: adds x2, x2, #1 + b.mi 5f + strb w1, [x4] +5: ret +ENDPROC(memset) -- cgit v0.10.2 From 2b8cac814cd5a0a305d62dcd1d589faccb705a4d Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Thu, 21 Mar 2013 16:23:43 +0000 Subject: arm64: klib: Optimised string functions This patch introduces AArch64-specific string functions (strchr, strrchr). Signed-off-by: Catalin Marinas diff --git a/arch/arm64/include/asm/string.h b/arch/arm64/include/asm/string.h index be8a644..3ee8b30 100644 --- a/arch/arm64/include/asm/string.h +++ b/arch/arm64/include/asm/string.h @@ -16,6 +16,12 @@ #ifndef __ASM_STRING_H #define __ASM_STRING_H +#define __HAVE_ARCH_STRRCHR +extern char *strrchr(const char *, int c); + +#define __HAVE_ARCH_STRCHR +extern char *strchr(const char *, int c); + #define __HAVE_ARCH_MEMCPY extern void *memcpy(void *, const void *, __kernel_size_t); diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c index d7f7b17..a5d0d46 100644 --- a/arch/arm64/kernel/arm64ksyms.c +++ b/arch/arm64/kernel/arm64ksyms.c @@ -48,6 +48,8 @@ EXPORT_SYMBOL(__atomic_hash); EXPORT_SYMBOL(memstart_addr); /* string / mem functions */ +EXPORT_SYMBOL(strchr); +EXPORT_SYMBOL(strrchr); EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memmove); diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile index 2fce139..59acc0e 100644 --- a/arch/arm64/lib/Makefile +++ b/arch/arm64/lib/Makefile @@ -2,4 +2,5 @@ lib-y := bitops.o delay.o \ strncpy_from_user.o strnlen_user.o clear_user.o \ copy_from_user.o copy_to_user.o copy_in_user.o \ copy_page.o clear_page.o \ - memchr.o memcpy.o memmove.o memset.o + memchr.o memcpy.o memmove.o memset.o \ + strchr.o strrchr.o diff --git a/arch/arm64/lib/strchr.S b/arch/arm64/lib/strchr.S new file mode 100644 index 0000000..dae0cf5 --- /dev/null +++ b/arch/arm64/lib/strchr.S @@ -0,0 +1,42 @@ +/* + * Based on arch/arm/lib/strchr.S + * + * Copyright (C) 1995-2000 Russell King + * Copyright (C) 2013 ARM Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +/* + * Find the first occurrence of a character in a string. + * + * Parameters: + * x0 - str + * x1 - c + * Returns: + * x0 - address of first occurrence of 'c' or 0 + */ +ENTRY(strchr) + and w1, w1, #0xff +1: ldrb w2, [x0], #1 + cmp w2, w1 + ccmp w2, wzr, #4, ne + b.ne 1b + sub x0, x0, #1 + cmp w2, w1 + csel x0, x0, xzr, eq + ret +ENDPROC(strchr) diff --git a/arch/arm64/lib/strrchr.S b/arch/arm64/lib/strrchr.S new file mode 100644 index 0000000..61eabd9 --- /dev/null +++ b/arch/arm64/lib/strrchr.S @@ -0,0 +1,43 @@ +/* + * Based on arch/arm/lib/strrchr.S + * + * Copyright (C) 1995-2000 Russell King + * Copyright (C) 2013 ARM Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +/* + * Find the last occurrence of a character in a string. + * + * Parameters: + * x0 - str + * x1 - c + * Returns: + * x0 - address of last occurrence of 'c' or 0 + */ +ENTRY(strrchr) + mov x3, #0 + and w1, w1, #0xff +1: ldrb w2, [x0], #1 + cbz w2, 2f + cmp w2, w1 + b.ne 1b + sub x3, x0, #1 + b 1b +2: mov x0, x3 + ret +ENDPROC(strrchr) -- cgit v0.10.2 From 62479586532715b6da4777374a6f53b32453385e Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Thu, 21 Mar 2013 16:28:47 +0000 Subject: arm64: klib: Optimised atomic bitops This patch implements the AArch64-specific atomic bitops functions using exclusive memory accesses to avoid locking. Signed-off-by: Catalin Marinas diff --git a/arch/arm64/include/asm/bitops.h b/arch/arm64/include/asm/bitops.h index 5e69307..aa5b59d 100644 --- a/arch/arm64/include/asm/bitops.h +++ b/arch/arm64/include/asm/bitops.h @@ -32,6 +32,16 @@ #error only can be included directly #endif +/* + * Little endian assembly atomic bitops. + */ +extern void set_bit(int nr, volatile unsigned long *p); +extern void clear_bit(int nr, volatile unsigned long *p); +extern void change_bit(int nr, volatile unsigned long *p); +extern int test_and_set_bit(int nr, volatile unsigned long *p); +extern int test_and_clear_bit(int nr, volatile unsigned long *p); +extern int test_and_change_bit(int nr, volatile unsigned long *p); + #include #include #include @@ -45,9 +55,13 @@ #include #include -#include #include #include -#include + +/* + * Ext2 is defined to use little-endian byte ordering. + */ +#define ext2_set_bit_atomic(lock, nr, p) test_and_set_bit_le(nr, p) +#define ext2_clear_bit_atomic(lock, nr, p) test_and_clear_bit_le(nr, p) #endif /* __ASM_BITOPS_H */ diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c index a5d0d46..7df1aad 100644 --- a/arch/arm64/kernel/arm64ksyms.c +++ b/arch/arm64/kernel/arm64ksyms.c @@ -39,11 +39,6 @@ EXPORT_SYMBOL(__copy_from_user); EXPORT_SYMBOL(__copy_to_user); EXPORT_SYMBOL(__clear_user); - /* bitops */ -#ifdef CONFIG_SMP -EXPORT_SYMBOL(__atomic_hash); -#endif - /* physical memory */ EXPORT_SYMBOL(memstart_addr); @@ -54,3 +49,11 @@ EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(memchr); + + /* atomic bitops */ +EXPORT_SYMBOL(set_bit); +EXPORT_SYMBOL(test_and_set_bit); +EXPORT_SYMBOL(clear_bit); +EXPORT_SYMBOL(test_and_clear_bit); +EXPORT_SYMBOL(change_bit); +EXPORT_SYMBOL(test_and_change_bit); diff --git a/arch/arm64/lib/bitops.S b/arch/arm64/lib/bitops.S new file mode 100644 index 0000000..fd1e801 --- /dev/null +++ b/arch/arm64/lib/bitops.S @@ -0,0 +1,70 @@ +/* + * Based on arch/arm/lib/bitops.h + * + * Copyright (C) 2013 ARM Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +/* + * x0: bits 5:0 bit offset + * bits 63:6 word offset + * x1: address + */ + .macro bitop, name, instr +ENTRY( \name ) + and x3, x0, #63 // Get bit offset + eor x0, x0, x3 // Clear low bits + mov x2, #1 + add x1, x1, x0, lsr #3 // Get word offset + lsl x3, x2, x3 // Create mask +1: ldxr x2, [x1] + \instr x2, x2, x3 + stxr w0, x2, [x1] + cbnz w0, 1b + ret +ENDPROC(\name ) + .endm + + .macro testop, name, instr +ENTRY( \name ) + and x3, x0, #63 // Get bit offset + eor x0, x0, x3 // Clear low bits + mov x2, #1 + add x1, x1, x0, lsr #3 // Get word offset + lsl x4, x2, x3 // Create mask + smp_dmb ish +1: ldxr x2, [x1] + lsr x0, x2, x3 // Save old value of bit + \instr x2, x2, x4 // toggle bit + stxr w2, x2, [x1] + cbnz w2, 1b + smp_dmb ish + and x0, x0, #1 +3: ret +ENDPROC(\name ) + .endm + +/* + * Atomic bit operations. + */ + bitop change_bit, eor + bitop clear_bit, bic + bitop set_bit, orr + + testop test_and_change_bit, eor + testop test_and_clear_bit, bic + testop test_and_set_bit, orr diff --git a/arch/arm64/lib/bitops.c b/arch/arm64/lib/bitops.c deleted file mode 100644 index aa4965e..0000000 --- a/arch/arm64/lib/bitops.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2012 ARM Limited - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include - -#ifdef CONFIG_SMP -arch_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = { - [0 ... (ATOMIC_HASH_SIZE-1)] = __ARCH_SPIN_LOCK_UNLOCKED -}; -#endif -- cgit v0.10.2 From a9a193ffe51d036a7c2d30d7fbdb66498c688237 Mon Sep 17 00:00:00 2001 From: Liviu Dudau Date: Tue, 26 Mar 2013 11:02:51 +0000 Subject: arm64: psci: Use the MPIDR values from cpu_logical_map for cpu ids. With the (re)introduction of cpu_logical_map in arm64 we switch to the use of MPIDR values to identify CPUs. Update the psci code to do that. Signed-off-by: Liviu Dudau Signed-off-by: Catalin Marinas diff --git a/arch/arm64/kernel/smp_psci.c b/arch/arm64/kernel/smp_psci.c index 1120916..0c53330 100644 --- a/arch/arm64/kernel/smp_psci.c +++ b/arch/arm64/kernel/smp_psci.c @@ -21,6 +21,7 @@ #include #include +#include static int __init smp_psci_init_cpu(struct device_node *dn, int cpu) { @@ -36,7 +37,7 @@ static int __init smp_psci_prepare_cpu(int cpu) return -ENODEV; } - err = psci_ops.cpu_on(cpu, __pa(secondary_holding_pen)); + err = psci_ops.cpu_on(cpu_logical_map(cpu), __pa(secondary_holding_pen)); if (err) { pr_err("psci: failed to boot CPU%d (%d)\n", cpu, err); return err; @@ -47,6 +48,6 @@ static int __init smp_psci_prepare_cpu(int cpu) const struct smp_enable_ops smp_psci_ops __initconst = { .name = "psci", - .init_cpu = smp_psci_init_cpu, + .init_cpu = smp_psci_init_cpu, .prepare_cpu = smp_psci_prepare_cpu, }; -- cgit v0.10.2 From e851b58cb77b47a5c14267723bd6b76655d21840 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 14 Jan 2013 12:39:31 +0000 Subject: arm64: Use irqchip_init() for interrupt controller initialisation This patch uses the generic irqchip_init() function for initialising the interrupt controller on arm64. It also adds several definitions required by the ARM GIC irqchip driver but does not enable ARM_GIC yet. Signed-off-by: Catalin Marinas diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h index ac63519..0303705 100644 --- a/arch/arm64/include/asm/exception.h +++ b/arch/arm64/include/asm/exception.h @@ -19,5 +19,6 @@ #define __ASM_EXCEPTION_H #define __exception __attribute__((section(".exception.text"))) +#define __exception_irq_entry __exception #endif /* __ASM_EXCEPTION_H */ diff --git a/arch/arm64/include/asm/hardirq.h b/arch/arm64/include/asm/hardirq.h index 5075463..990c051 100644 --- a/arch/arm64/include/asm/hardirq.h +++ b/arch/arm64/include/asm/hardirq.h @@ -49,4 +49,9 @@ static inline void ack_bad_irq(unsigned int irq) extern void handle_IRQ(unsigned int, struct pt_regs *); +/* + * No arch-specific IRQ flags. + */ +#define set_irq_flags(irq, flags) + #endif /* __ASM_HARDIRQ_H */ diff --git a/arch/arm64/include/asm/irq.h b/arch/arm64/include/asm/irq.h index a4e1cad..0332fc0 100644 --- a/arch/arm64/include/asm/irq.h +++ b/arch/arm64/include/asm/irq.h @@ -4,5 +4,6 @@ #include extern void (*handle_arch_irq)(struct pt_regs *); +extern void set_handle_irq(void (*handle_irq)(struct pt_regs *)); #endif diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c index 0373c66..ecb3354 100644 --- a/arch/arm64/kernel/irq.c +++ b/arch/arm64/kernel/irq.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include @@ -67,18 +67,17 @@ void handle_IRQ(unsigned int irq, struct pt_regs *regs) set_irq_regs(old_regs); } -/* - * Interrupt controllers supported by the kernel. - */ -static const struct of_device_id intctrl_of_match[] __initconst = { - /* IRQ controllers { .compatible, .data } info to go here */ - {} -}; +void __init set_handle_irq(void (*handle_irq)(struct pt_regs *)) +{ + if (handle_arch_irq) + return; + + handle_arch_irq = handle_irq; +} void __init init_IRQ(void) { - of_irq_init(intctrl_of_match); - + irqchip_init(); if (!handle_arch_irq) panic("No interrupt controller found."); } -- cgit v0.10.2 From 5c1ce6f7c2aae5329f667fb079b3198266d9a3fa Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 8 Apr 2013 17:17:03 +0100 Subject: arm64: add explicit symbols to ESR_EL1 decoding The ESR_EL1 decoding process is a bit cryptic, and KVM has also a need for the same constants. Add a new esr.h file containing the appropriate exception classes constants, and change entry.S to use it. Fix a small bug in the EL1 breakpoint check while we're at it. Signed-off-by: Marc Zyngier Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h new file mode 100644 index 0000000..7883412 --- /dev/null +++ b/arch/arm64/include/asm/esr.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2013 - ARM Ltd + * Author: Marc Zyngier + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __ASM_ESR_H +#define __ASM_ESR_H + +#define ESR_EL1_EC_SHIFT (26) +#define ESR_EL1_IL (1U << 25) + +#define ESR_EL1_EC_UNKNOWN (0x00) +#define ESR_EL1_EC_WFI (0x01) +#define ESR_EL1_EC_CP15_32 (0x03) +#define ESR_EL1_EC_CP15_64 (0x04) +#define ESR_EL1_EC_CP14_MR (0x05) +#define ESR_EL1_EC_CP14_LS (0x06) +#define ESR_EL1_EC_FP_ASIMD (0x07) +#define ESR_EL1_EC_CP10_ID (0x08) +#define ESR_EL1_EC_CP14_64 (0x0C) +#define ESR_EL1_EC_ILL_ISS (0x0E) +#define ESR_EL1_EC_SVC32 (0x11) +#define ESR_EL1_EC_SVC64 (0x15) +#define ESR_EL1_EC_SYS64 (0x18) +#define ESR_EL1_EC_IABT_EL0 (0x20) +#define ESR_EL1_EC_IABT_EL1 (0x21) +#define ESR_EL1_EC_PC_ALIGN (0x22) +#define ESR_EL1_EC_DABT_EL0 (0x24) +#define ESR_EL1_EC_DABT_EL1 (0x25) +#define ESR_EL1_EC_SP_ALIGN (0x26) +#define ESR_EL1_EC_FP_EXC32 (0x28) +#define ESR_EL1_EC_FP_EXC64 (0x2C) +#define ESR_EL1_EC_SERRROR (0x2F) +#define ESR_EL1_EC_BREAKPT_EL0 (0x30) +#define ESR_EL1_EC_BREAKPT_EL1 (0x31) +#define ESR_EL1_EC_SOFTSTP_EL0 (0x32) +#define ESR_EL1_EC_SOFTSTP_EL1 (0x33) +#define ESR_EL1_EC_WATCHPT_EL0 (0x34) +#define ESR_EL1_EC_WATCHPT_EL1 (0x35) +#define ESR_EL1_EC_BKPT32 (0x38) +#define ESR_EL1_EC_BRK64 (0x3C) + +#endif /* __ASM_ESR_H */ diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 514d609..c7e0470 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -239,18 +240,18 @@ ENDPROC(el1_error_invalid) el1_sync: kernel_entry 1 mrs x1, esr_el1 // read the syndrome register - lsr x24, x1, #26 // exception class - cmp x24, #0x25 // data abort in EL1 + lsr x24, x1, #ESR_EL1_EC_SHIFT // exception class + cmp x24, #ESR_EL1_EC_DABT_EL1 // data abort in EL1 b.eq el1_da - cmp x24, #0x18 // configurable trap + cmp x24, #ESR_EL1_EC_SYS64 // configurable trap b.eq el1_undef - cmp x24, #0x26 // stack alignment exception + cmp x24, #ESR_EL1_EC_SP_ALIGN // stack alignment exception b.eq el1_sp_pc - cmp x24, #0x22 // pc alignment exception + cmp x24, #ESR_EL1_EC_PC_ALIGN // pc alignment exception b.eq el1_sp_pc - cmp x24, #0x00 // unknown exception in EL1 + cmp x24, #ESR_EL1_EC_UNKNOWN // unknown exception in EL1 b.eq el1_undef - cmp x24, #0x30 // debug exception in EL1 + cmp x24, #ESR_EL1_EC_BREAKPT_EL1 // debug exception in EL1 b.ge el1_dbg b el1_inv el1_da: @@ -346,27 +347,27 @@ el1_preempt: el0_sync: kernel_entry 0 mrs x25, esr_el1 // read the syndrome register - lsr x24, x25, #26 // exception class - cmp x24, #0x15 // SVC in 64-bit state + lsr x24, x25, #ESR_EL1_EC_SHIFT // exception class + cmp x24, #ESR_EL1_EC_SVC64 // SVC in 64-bit state b.eq el0_svc adr lr, ret_from_exception - cmp x24, #0x24 // data abort in EL0 + cmp x24, #ESR_EL1_EC_DABT_EL0 // data abort in EL0 b.eq el0_da - cmp x24, #0x20 // instruction abort in EL0 + cmp x24, #ESR_EL1_EC_IABT_EL0 // instruction abort in EL0 b.eq el0_ia - cmp x24, #0x07 // FP/ASIMD access + cmp x24, #ESR_EL1_EC_FP_ASIMD // FP/ASIMD access b.eq el0_fpsimd_acc - cmp x24, #0x2c // FP/ASIMD exception + cmp x24, #ESR_EL1_EC_FP_EXC64 // FP/ASIMD exception b.eq el0_fpsimd_exc - cmp x24, #0x18 // configurable trap + cmp x24, #ESR_EL1_EC_SYS64 // configurable trap b.eq el0_undef - cmp x24, #0x26 // stack alignment exception + cmp x24, #ESR_EL1_EC_SP_ALIGN // stack alignment exception b.eq el0_sp_pc - cmp x24, #0x22 // pc alignment exception + cmp x24, #ESR_EL1_EC_PC_ALIGN // pc alignment exception b.eq el0_sp_pc - cmp x24, #0x00 // unknown exception in EL0 + cmp x24, #ESR_EL1_EC_UNKNOWN // unknown exception in EL0 b.eq el0_undef - cmp x24, #0x30 // debug exception in EL0 + cmp x24, #ESR_EL1_EC_BREAKPT_EL0 // debug exception in EL0 b.ge el0_dbg b el0_inv @@ -375,21 +376,21 @@ el0_sync: el0_sync_compat: kernel_entry 0, 32 mrs x25, esr_el1 // read the syndrome register - lsr x24, x25, #26 // exception class - cmp x24, #0x11 // SVC in 32-bit state + lsr x24, x25, #ESR_EL1_EC_SHIFT // exception class + cmp x24, #ESR_EL1_EC_SVC32 // SVC in 32-bit state b.eq el0_svc_compat adr lr, ret_from_exception - cmp x24, #0x24 // data abort in EL0 + cmp x24, #ESR_EL1_EC_DABT_EL0 // data abort in EL0 b.eq el0_da - cmp x24, #0x20 // instruction abort in EL0 + cmp x24, #ESR_EL1_EC_IABT_EL0 // instruction abort in EL0 b.eq el0_ia - cmp x24, #0x07 // FP/ASIMD access + cmp x24, #ESR_EL1_EC_FP_ASIMD // FP/ASIMD access b.eq el0_fpsimd_acc - cmp x24, #0x28 // FP/ASIMD exception + cmp x24, #ESR_EL1_EC_FP_EXC32 // FP/ASIMD exception b.eq el0_fpsimd_exc - cmp x24, #0x00 // unknown exception in EL0 + cmp x24, #ESR_EL1_EC_UNKNOWN // unknown exception in EL0 b.eq el0_undef - cmp x24, #0x30 // debug exception in EL0 + cmp x24, #ESR_EL1_EC_BREAKPT_EL0 // debug exception in EL0 b.ge el0_dbg b el0_inv el0_svc_compat: -- cgit v0.10.2 From 3325732f3b223812e54ac67dbb0a8ea7c99cf519 Mon Sep 17 00:00:00 2001 From: Christopher Covington Date: Wed, 3 Apr 2013 19:01:01 +0100 Subject: arm64: Fix task tracing For accurate accounting call contextidr_thread_switch before a task is scheduled, rather than after, when the 'next' variable has a different meaning since we switched the stacks. Signed-off-by: Christopher Covington Signed-off-by: Catalin Marinas diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 0337cdb..c2cc249 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -311,11 +311,11 @@ struct task_struct *__switch_to(struct task_struct *prev, fpsimd_thread_switch(next); tls_thread_switch(next); hw_breakpoint_thread_switch(next); + contextidr_thread_switch(next); /* the actual thread switch */ last = cpu_switch_to(prev, next); - contextidr_thread_switch(next); return last; } -- cgit v0.10.2 From 12f883989cf91afa8509c547feebbc3acbc04497 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Fri, 19 Apr 2013 12:24:37 +0100 Subject: arm64: Define readq and writeq for driver module using when compiling with allmodconfig, CONFIG_64BIT=y the file drivers/base/regmap/regmap-mmio.c will use readq and writeq so we need implement these functions. Signed-off-by: Chen Gang Acked-by: Arnd Bergmann Signed-off-by: Catalin Marinas diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h index 57f12c9..2e12258 100644 --- a/arch/arm64/include/asm/io.h +++ b/arch/arm64/include/asm/io.h @@ -92,10 +92,12 @@ static inline u64 __raw_readq(const volatile void __iomem *addr) #define readb_relaxed(c) ({ u8 __v = __raw_readb(c); __v; }) #define readw_relaxed(c) ({ u16 __v = le16_to_cpu((__force __le16)__raw_readw(c)); __v; }) #define readl_relaxed(c) ({ u32 __v = le32_to_cpu((__force __le32)__raw_readl(c)); __v; }) +#define readq_relaxed(c) ({ u64 __v = le64_to_cpu((__force __le64)__raw_readq(c)); __v; }) #define writeb_relaxed(v,c) ((void)__raw_writeb((v),(c))) #define writew_relaxed(v,c) ((void)__raw_writew((__force u16)cpu_to_le16(v),(c))) #define writel_relaxed(v,c) ((void)__raw_writel((__force u32)cpu_to_le32(v),(c))) +#define writeq_relaxed(v,c) ((void)__raw_writeq((__force u64)cpu_to_le64(v),(c))) /* * I/O memory access primitives. Reads are ordered relative to any @@ -105,10 +107,12 @@ static inline u64 __raw_readq(const volatile void __iomem *addr) #define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; }) #define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; }) #define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; }) +#define readq(c) ({ u64 __v = readq_relaxed(c); __iormb(); __v; }) #define writeb(v,c) ({ __iowmb(); writeb_relaxed((v),(c)); }) #define writew(v,c) ({ __iowmb(); writew_relaxed((v),(c)); }) #define writel(v,c) ({ __iowmb(); writel_relaxed((v),(c)); }) +#define writeq(v,c) ({ __iowmb(); writeq_relaxed((v),(c)); }) /* * I/O port access primitives. -- cgit v0.10.2 From a84b086b874e0c03ca456c1748df7031a8cdf957 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Mon, 22 Apr 2013 06:08:41 +0100 Subject: arm64: Define cmpxchg64 and cmpxchg64_local for outside use Drivers use cmpxchg64, cmpxchg64_local to perform 64-bit operation, so they can cross 32-bit and 64-bit platforms (it is a standard way). Signed-off-by: Chen Gang Signed-off-by: Catalin Marinas diff --git a/arch/arm64/include/asm/cmpxchg.h b/arch/arm64/include/asm/cmpxchg.h index 968b5cb..8a8ce0e 100644 --- a/arch/arm64/include/asm/cmpxchg.h +++ b/arch/arm64/include/asm/cmpxchg.h @@ -170,4 +170,7 @@ static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old, (unsigned long)(n), \ sizeof(*(ptr)))) +#define cmpxchg64(ptr,o,n) cmpxchg((ptr),(o),(n)) +#define cmpxchg64_local(ptr,o,n) cmpxchg_local((ptr),(o),(n)) + #endif /* __ASM_CMPXCHG_H */ -- cgit v0.10.2 From 72aea393a2e7c53a951bc581f18a79315f47036b Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 22 Apr 2013 18:28:55 +0100 Subject: arm64: smp: honour #address-size when parsing CPU reg property For systems where the top 32-bits of the MPIDR are all zero, we should allow the device-tree to specify an #address-size of 0x1 for the CPU reg property and then zero extend the value there. Without this patch, kvmtool breaks with the recent mpidr parsing code introduced in 4c7aa0021356 ("arm64: kernel: initialise cpu_logical_map from the DT"). Acked-by: Javi Merino Acked-by: Lorenzo Pieralisi Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index d4dcc65..a886194 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -270,6 +270,7 @@ void __init smp_init_cpus(void) bool bootcpu_valid = false; while ((dn = of_find_node_by_type(dn, "cpu"))) { + const u32 *cell; u64 hwid; /* @@ -277,10 +278,12 @@ void __init smp_init_cpus(void) * considered invalid to build a cpu_logical_map * entry. */ - if (of_property_read_u64(dn, "reg", &hwid)) { + cell = of_get_property(dn, "reg", NULL); + if (!cell) { pr_err("%s: missing reg property\n", dn->full_name); goto next; } + hwid = of_read_number(cell, of_n_addr_cells(dn)); /* * Non affinity bits must be set to 0 in the DT -- cgit v0.10.2 From 4b3ea2e04d2b8b37c5bc472f710d706b42e4fa06 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Wed, 24 Apr 2013 11:58:24 +0100 Subject: arm64: compiling issue, need add include/asm/vga.h file For compiling with allmodconfig, need vga.h file, so generate it which just only include the asm-generic one. It is firstly used by drivers/gpu/drm/drm_irq.c. The related error: include/video/vga.h:22:21: fatal error: asm/vga.h: No such file or directory Signed-off-by: Chen Gang Signed-off-by: Catalin Marinas diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild index a13a4a4..79a642d 100644 --- a/arch/arm64/include/asm/Kbuild +++ b/arch/arm64/include/asm/Kbuild @@ -48,4 +48,5 @@ generic-y += trace_clock.h generic-y += types.h generic-y += unaligned.h generic-y += user.h +generic-y += vga.h generic-y += xor.h -- cgit v0.10.2 From 5108c67c376b3ee59cc7fbe46eaba481eb3419aa Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Wed, 24 Apr 2013 14:47:02 +0100 Subject: arm64: Execute DSB during thread switching for TLB/cache maintenance The DSB following TLB or cache maintenance ops must be run on the same CPU. With kernel preemption enabled or for user-space cache maintenance this may not be the case. This patch adds an explicit DSB in the __switch_to() function. Signed-off-by: Catalin Marinas diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index c2cc249..116a60a 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -313,6 +313,12 @@ struct task_struct *__switch_to(struct task_struct *prev, hw_breakpoint_thread_switch(next); contextidr_thread_switch(next); + /* + * Complete any pending TLB or cache maintenance on this CPU in case + * the thread migrates to a different CPU. + */ + dsb(); + /* the actual thread switch */ last = cpu_switch_to(prev, next); -- cgit v0.10.2 From f15a2a12d01573fcf9d2beb657f308845d55fc66 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Thu, 25 Apr 2013 11:23:41 +0100 Subject: arm64: Fix compat types affecting struct compat_stat The compat_stat structure doesn't match the arch/arm/ struct stat definition. This patch fixes the compat types and struct compat_stat definition accordingly. Signed-off-by: Catalin Marinas Acked-by: Will Deacon diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h index 618b450..899af80 100644 --- a/arch/arm64/include/asm/compat.h +++ b/arch/arm64/include/asm/compat.h @@ -35,14 +35,16 @@ typedef s32 compat_clock_t; typedef s32 compat_pid_t; typedef u32 __compat_uid_t; typedef u32 __compat_gid_t; +typedef u16 __compat_uid16_t; +typedef u16 __compat_gid16_t; typedef u32 __compat_uid32_t; typedef u32 __compat_gid32_t; -typedef u32 compat_mode_t; +typedef u16 compat_mode_t; typedef u32 compat_ino_t; typedef u32 compat_dev_t; typedef s32 compat_off_t; typedef s64 compat_loff_t; -typedef s16 compat_nlink_t; +typedef s32 compat_nlink_t; typedef u16 compat_ipc_pid_t; typedef s32 compat_daddr_t; typedef u32 compat_caddr_t; @@ -50,9 +52,11 @@ typedef __kernel_fsid_t compat_fsid_t; typedef s32 compat_key_t; typedef s32 compat_timer_t; +typedef s16 compat_short_t; typedef s32 compat_int_t; typedef s32 compat_long_t; typedef s64 compat_s64; +typedef u16 compat_ushort_t; typedef u32 compat_uint_t; typedef u32 compat_ulong_t; typedef u64 compat_u64; @@ -72,20 +76,20 @@ struct compat_stat { compat_dev_t st_dev; compat_ino_t st_ino; compat_mode_t st_mode; - compat_nlink_t st_nlink; - __compat_uid32_t st_uid; - __compat_gid32_t st_gid; + compat_ushort_t st_nlink; + __compat_uid16_t st_uid; + __compat_gid16_t st_gid; compat_dev_t st_rdev; compat_off_t st_size; compat_off_t st_blksize; compat_off_t st_blocks; compat_time_t st_atime; - u32 st_atime_nsec; + compat_ulong_t st_atime_nsec; compat_time_t st_mtime; - u32 st_mtime_nsec; + compat_ulong_t st_mtime_nsec; compat_time_t st_ctime; - u32 st_ctime_nsec; - u32 __unused4[2]; + compat_ulong_t st_ctime_nsec; + compat_ulong_t __unused4[2]; }; struct compat_flock { -- cgit v0.10.2 From 4339e3f389081ea90e230a785bdbe10eccd02b71 Mon Sep 17 00:00:00 2001 From: Steve Capper Date: Fri, 19 Apr 2013 15:49:31 +0100 Subject: arm64: mm: Correct show_pte behaviour show_pte makes use of the *_none_or_clear_bad style functions. If a pgd, pud or pmd is identified as being bad, it will then be cleared. As show_pte appears to be called from either the user or kernel fault handlers this side effect can lead to unpredictable behaviour; especially as TLB entries are not invalidated. This patch removes the page table sanitisation from show_pte. If a bad pgd, pud or pmd is encountered it is left unmodified. Signed-off-by: Steve Capper Signed-off-by: Catalin Marinas diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index afadae6..5263817 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -57,16 +57,16 @@ void show_pte(struct mm_struct *mm, unsigned long addr) pmd_t *pmd; pte_t *pte; - if (pgd_none_or_clear_bad(pgd)) + if (pgd_none(*pgd) || pgd_bad(*pgd)) break; pud = pud_offset(pgd, addr); - if (pud_none_or_clear_bad(pud)) + if (pud_none(*pud) || pud_bad(*pud)) break; pmd = pmd_offset(pud, addr); printk(", *pmd=%016llx", pmd_val(*pmd)); - if (pmd_none_or_clear_bad(pmd)) + if (pmd_none(*pmd) || pmd_bad(*pmd)) break; pte = pte_offset_map(pmd, addr); -- cgit v0.10.2 From 39a90ca639db5fcd33064ddf754793ec85764239 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Tue, 23 Apr 2013 17:22:49 +0100 Subject: arm64: Survive invalid cpu enable-methods Currently, if you pass the kernel a dtb where a cpu node has an unsupported enable-method property (e.g. "not-psci"), it'll explode horribly, as it iterates over the enable_ops array incorrectly. It increments the pointer *at* the current element, rather than incrementing the pointer *to* the current element. As the first two elements pointed to structures that were contiguous in memory, this happened to be equivalent. However the third element is NULL, so when the list is exhausted, smp_get_enable_ops generates the wrong pointer, and dereferences an arbitrary portion of memory, which currently happens to contain zero. This patch fixes this by indirecting the pointer one level, so we iterate over the array elements correctly, avoiding the below panic: Signed-off-by: Mark Rutland Signed-off-by: Catalin Marinas diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index a886194..1e22ff9 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -245,11 +245,11 @@ static const struct smp_enable_ops *smp_enable_ops[NR_CPUS]; static const struct smp_enable_ops * __init smp_get_enable_ops(const char *name) { - const struct smp_enable_ops *ops = enable_ops[0]; + const struct smp_enable_ops **ops = enable_ops; - while (ops) { - if (!strcmp(name, ops->name)) - return ops; + while (*ops) { + if (!strcmp(name, (*ops)->name)) + return *ops; ops++; } -- cgit v0.10.2 From 90556ca1ebdd01fbedaf9e56a826d4ce84346466 Mon Sep 17 00:00:00 2001 From: Pawel Moll Date: Wed, 21 Nov 2012 11:44:28 +0000 Subject: arm64: vexpress: Add dts files for the ARMv8 RTSM models This patch adds the DTS files for the ARMv8 RTSM and Foundation models. Signed-off-by: Pawel Moll Signed-off-by: Catalin Marinas Acked-by: Arnd Bergmann diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile index 32ac0ae..68457e9 100644 --- a/arch/arm64/boot/dts/Makefile +++ b/arch/arm64/boot/dts/Makefile @@ -1,3 +1,5 @@ +dtb-$(CONFIG_ARCH_VEXPRESS) += rtsm_ve-aemv8a.dtb foundation-v8.dtb + targets += dtbs targets += $(dtb-y) diff --git a/arch/arm64/boot/dts/foundation-v8.dts b/arch/arm64/boot/dts/foundation-v8.dts new file mode 100644 index 0000000..198682b --- /dev/null +++ b/arch/arm64/boot/dts/foundation-v8.dts @@ -0,0 +1,230 @@ +/* + * ARM Ltd. + * + * ARMv8 Foundation model DTS + */ + +/dts-v1/; + +/ { + model = "Foundation-v8A"; + compatible = "arm,foundation-aarch64", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x0>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x8000fff8>; + }; + cpu@1 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x1>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x8000fff8>; + }; + cpu@2 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x2>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x8000fff8>; + }; + cpu@3 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x3>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x8000fff8>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0 0x80000000>, + <0x00000008 0x80000000 0 0x80000000>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x0 0x2c001000 0 0x1000>, + <0x0 0x2c002000 0 0x1000>, + <0x0 0x2c004000 0 0x2000>, + <0x0 0x2c006000 0 0x2000>; + interrupts = <1 9 0xf04>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <1 13 0xff01>, + <1 14 0xff01>, + <1 11 0xff01>, + <1 10 0xff01>; + clock-frequency = <100000000>; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <0 60 4>, + <0 61 4>, + <0 62 4>, + <0 63 4>; + }; + + smb { + compatible = "arm,vexpress,v2m-p1", "simple-bus"; + arm,v2m-memory-map = "rs1"; + #address-cells = <2>; /* SMB chipselect number and offset */ + #size-cells = <1>; + + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 63>; + interrupt-map = <0 0 0 &gic 0 0 4>, + <0 0 1 &gic 0 1 4>, + <0 0 2 &gic 0 2 4>, + <0 0 3 &gic 0 3 4>, + <0 0 4 &gic 0 4 4>, + <0 0 5 &gic 0 5 4>, + <0 0 6 &gic 0 6 4>, + <0 0 7 &gic 0 7 4>, + <0 0 8 &gic 0 8 4>, + <0 0 9 &gic 0 9 4>, + <0 0 10 &gic 0 10 4>, + <0 0 11 &gic 0 11 4>, + <0 0 12 &gic 0 12 4>, + <0 0 13 &gic 0 13 4>, + <0 0 14 &gic 0 14 4>, + <0 0 15 &gic 0 15 4>, + <0 0 16 &gic 0 16 4>, + <0 0 17 &gic 0 17 4>, + <0 0 18 &gic 0 18 4>, + <0 0 19 &gic 0 19 4>, + <0 0 20 &gic 0 20 4>, + <0 0 21 &gic 0 21 4>, + <0 0 22 &gic 0 22 4>, + <0 0 23 &gic 0 23 4>, + <0 0 24 &gic 0 24 4>, + <0 0 25 &gic 0 25 4>, + <0 0 26 &gic 0 26 4>, + <0 0 27 &gic 0 27 4>, + <0 0 28 &gic 0 28 4>, + <0 0 29 &gic 0 29 4>, + <0 0 30 &gic 0 30 4>, + <0 0 31 &gic 0 31 4>, + <0 0 32 &gic 0 32 4>, + <0 0 33 &gic 0 33 4>, + <0 0 34 &gic 0 34 4>, + <0 0 35 &gic 0 35 4>, + <0 0 36 &gic 0 36 4>, + <0 0 37 &gic 0 37 4>, + <0 0 38 &gic 0 38 4>, + <0 0 39 &gic 0 39 4>, + <0 0 40 &gic 0 40 4>, + <0 0 41 &gic 0 41 4>, + <0 0 42 &gic 0 42 4>; + + ethernet@2,02000000 { + compatible = "smsc,lan91c111"; + reg = <2 0x02000000 0x10000>; + interrupts = <15>; + }; + + v2m_clk24mhz: clk24mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "v2m:clk24mhz"; + }; + + v2m_refclk1mhz: refclk1mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <1000000>; + clock-output-names = "v2m:refclk1mhz"; + }; + + v2m_refclk32khz: refclk32khz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "v2m:refclk32khz"; + }; + + iofpga@3,00000000 { + compatible = "arm,amba-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 3 0 0x200000>; + + v2m_sysreg: sysreg@010000 { + compatible = "arm,vexpress-sysreg"; + reg = <0x010000 0x1000>; + }; + + v2m_serial0: uart@090000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x090000 0x1000>; + interrupts = <5>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial1: uart@0a0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0a0000 0x1000>; + interrupts = <6>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial2: uart@0b0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0b0000 0x1000>; + interrupts = <7>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial3: uart@0c0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0c0000 0x1000>; + interrupts = <8>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + virtio_block@0130000 { + compatible = "virtio,mmio"; + reg = <0x130000 0x1000>; + interrupts = <42>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts new file mode 100644 index 0000000..572005e --- /dev/null +++ b/arch/arm64/boot/dts/rtsm_ve-aemv8a.dts @@ -0,0 +1,159 @@ +/* + * ARM Ltd. Fast Models + * + * Architecture Envelope Model (AEM) ARMv8-A + * ARMAEMv8AMPCT + * + * RTSM_VE_AEMv8A.lisa + */ + +/dts-v1/; + +/memreserve/ 0x80000000 0x00010000; + +/ { + model = "RTSM_VE_AEMv8A"; + compatible = "arm,rtsm_ve,aemv8a", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x0>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x8000fff8>; + }; + cpu@1 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x1>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x8000fff8>; + }; + cpu@2 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x2>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x8000fff8>; + }; + cpu@3 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0 0x3>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0x8000fff8>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0 0x80000000>, + <0x00000008 0x80000000 0 0x80000000>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x0 0x2c001000 0 0x1000>, + <0x0 0x2c002000 0 0x1000>, + <0x0 0x2c004000 0 0x2000>, + <0x0 0x2c006000 0 0x2000>; + interrupts = <1 9 0xf04>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <1 13 0xff01>, + <1 14 0xff01>, + <1 11 0xff01>, + <1 10 0xff01>; + clock-frequency = <100000000>; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <0 60 4>, + <0 61 4>, + <0 62 4>, + <0 63 4>; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 63>; + interrupt-map = <0 0 0 &gic 0 0 4>, + <0 0 1 &gic 0 1 4>, + <0 0 2 &gic 0 2 4>, + <0 0 3 &gic 0 3 4>, + <0 0 4 &gic 0 4 4>, + <0 0 5 &gic 0 5 4>, + <0 0 6 &gic 0 6 4>, + <0 0 7 &gic 0 7 4>, + <0 0 8 &gic 0 8 4>, + <0 0 9 &gic 0 9 4>, + <0 0 10 &gic 0 10 4>, + <0 0 11 &gic 0 11 4>, + <0 0 12 &gic 0 12 4>, + <0 0 13 &gic 0 13 4>, + <0 0 14 &gic 0 14 4>, + <0 0 15 &gic 0 15 4>, + <0 0 16 &gic 0 16 4>, + <0 0 17 &gic 0 17 4>, + <0 0 18 &gic 0 18 4>, + <0 0 19 &gic 0 19 4>, + <0 0 20 &gic 0 20 4>, + <0 0 21 &gic 0 21 4>, + <0 0 22 &gic 0 22 4>, + <0 0 23 &gic 0 23 4>, + <0 0 24 &gic 0 24 4>, + <0 0 25 &gic 0 25 4>, + <0 0 26 &gic 0 26 4>, + <0 0 27 &gic 0 27 4>, + <0 0 28 &gic 0 28 4>, + <0 0 29 &gic 0 29 4>, + <0 0 30 &gic 0 30 4>, + <0 0 31 &gic 0 31 4>, + <0 0 32 &gic 0 32 4>, + <0 0 33 &gic 0 33 4>, + <0 0 34 &gic 0 34 4>, + <0 0 35 &gic 0 35 4>, + <0 0 36 &gic 0 36 4>, + <0 0 37 &gic 0 37 4>, + <0 0 38 &gic 0 38 4>, + <0 0 39 &gic 0 39 4>, + <0 0 40 &gic 0 40 4>, + <0 0 41 &gic 0 41 4>, + <0 0 42 &gic 0 42 4>; + + /include/ "rtsm_ve-motherboard.dtsi" + }; +}; diff --git a/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi b/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi new file mode 100644 index 0000000..b45e5f3 --- /dev/null +++ b/arch/arm64/boot/dts/rtsm_ve-motherboard.dtsi @@ -0,0 +1,234 @@ +/* + * ARM Ltd. Fast Models + * + * Versatile Express (VE) system model + * Motherboard component + * + * VEMotherBoard.lisa + */ + + motherboard { + arm,v2m-memory-map = "rs1"; + compatible = "arm,vexpress,v2m-p1", "simple-bus"; + #address-cells = <2>; /* SMB chipselect number and offset */ + #size-cells = <1>; + #interrupt-cells = <1>; + ranges; + + flash@0,00000000 { + compatible = "arm,vexpress-flash", "cfi-flash"; + reg = <0 0x00000000 0x04000000>, + <4 0x00000000 0x04000000>; + bank-width = <4>; + }; + + vram@2,00000000 { + compatible = "arm,vexpress-vram"; + reg = <2 0x00000000 0x00800000>; + }; + + ethernet@2,02000000 { + compatible = "smsc,lan91c111"; + reg = <2 0x02000000 0x10000>; + interrupts = <15>; + }; + + v2m_clk24mhz: clk24mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "v2m:clk24mhz"; + }; + + v2m_refclk1mhz: refclk1mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <1000000>; + clock-output-names = "v2m:refclk1mhz"; + }; + + v2m_refclk32khz: refclk32khz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "v2m:refclk32khz"; + }; + + iofpga@3,00000000 { + compatible = "arm,amba-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 3 0 0x200000>; + + v2m_sysreg: sysreg@010000 { + compatible = "arm,vexpress-sysreg"; + reg = <0x010000 0x1000>; + gpio-controller; + #gpio-cells = <2>; + }; + + v2m_sysctl: sysctl@020000 { + compatible = "arm,sp810", "arm,primecell"; + reg = <0x020000 0x1000>; + clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>; + clock-names = "refclk", "timclk", "apb_pclk"; + #clock-cells = <1>; + clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3"; + }; + + aaci@040000 { + compatible = "arm,pl041", "arm,primecell"; + reg = <0x040000 0x1000>; + interrupts = <11>; + clocks = <&v2m_clk24mhz>; + clock-names = "apb_pclk"; + }; + + mmci@050000 { + compatible = "arm,pl180", "arm,primecell"; + reg = <0x050000 0x1000>; + interrupts = <9 10>; + cd-gpios = <&v2m_sysreg 0 0>; + wp-gpios = <&v2m_sysreg 1 0>; + max-frequency = <12000000>; + vmmc-supply = <&v2m_fixed_3v3>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "mclk", "apb_pclk"; + }; + + kmi@060000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x060000 0x1000>; + interrupts = <12>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + kmi@070000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x070000 0x1000>; + interrupts = <13>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + v2m_serial0: uart@090000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x090000 0x1000>; + interrupts = <5>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial1: uart@0a0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0a0000 0x1000>; + interrupts = <6>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial2: uart@0b0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0b0000 0x1000>; + interrupts = <7>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial3: uart@0c0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0c0000 0x1000>; + interrupts = <8>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + wdt@0f0000 { + compatible = "arm,sp805", "arm,primecell"; + reg = <0x0f0000 0x1000>; + interrupts = <0>; + clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>; + clock-names = "wdogclk", "apb_pclk"; + }; + + v2m_timer01: timer@110000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x110000 0x1000>; + interrupts = <2>; + clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>; + clock-names = "timclken1", "timclken2", "apb_pclk"; + }; + + v2m_timer23: timer@120000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x120000 0x1000>; + interrupts = <3>; + clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>; + clock-names = "timclken1", "timclken2", "apb_pclk"; + }; + + rtc@170000 { + compatible = "arm,pl031", "arm,primecell"; + reg = <0x170000 0x1000>; + interrupts = <4>; + clocks = <&v2m_clk24mhz>; + clock-names = "apb_pclk"; + }; + + clcd@1f0000 { + compatible = "arm,pl111", "arm,primecell"; + reg = <0x1f0000 0x1000>; + interrupts = <14>; + clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>; + clock-names = "clcdclk", "apb_pclk"; + }; + }; + + v2m_fixed_3v3: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + mcc { + compatible = "arm,vexpress,config-bus", "simple-bus"; + arm,vexpress,config-bridge = <&v2m_sysreg>; + + v2m_oscclk1: osc@1 { + /* CLCD clock */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 1>; + freq-range = <23750000 63500000>; + #clock-cells = <0>; + clock-output-names = "v2m:oscclk1"; + }; + + reset@0 { + compatible = "arm,vexpress-reset"; + arm,vexpress-sysreg,func = <5 0>; + }; + + muxfpga@0 { + compatible = "arm,vexpress-muxfpga"; + arm,vexpress-sysreg,func = <7 0>; + }; + + shutdown@0 { + compatible = "arm,vexpress-shutdown"; + arm,vexpress-sysreg,func = <8 0>; + }; + + reboot@0 { + compatible = "arm,vexpress-reboot"; + arm,vexpress-sysreg,func = <9 0>; + }; + + dvimode@0 { + compatible = "arm,vexpress-dvimode"; + arm,vexpress-sysreg,func = <11 0>; + }; + }; + }; diff --git a/arch/arm64/boot/dts/skeleton.dtsi b/arch/arm64/boot/dts/skeleton.dtsi new file mode 100644 index 0000000..38ead82 --- /dev/null +++ b/arch/arm64/boot/dts/skeleton.dtsi @@ -0,0 +1,13 @@ +/* + * Skeleton device tree; the bare minimum needed to boot; just include and + * add a compatible value. The bootloader will typically populate the memory + * node. + */ + +/ { + #address-cells = <2>; + #size-cells = <1>; + chosen { }; + aliases { }; + memory { device_type = "memory"; reg = <0 0 0>; }; +}; -- cgit v0.10.2 From 1ae90e79051318c34d5a75c2ef5b9a55bd22f2ed Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Wed, 5 Sep 2012 17:47:44 +0100 Subject: arm64: vexpress: Enable ARMv8 RTSM model (SoC) support This patch adds the necessary Kconfig entries to enable support for the ARMv8 software model (Versatile Express platform) together with the defconfig update. Signed-off-by: Catalin Marinas Acked-by: Arnd Bergmann diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 9b6d19f..73b6e76 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -99,7 +99,16 @@ source "init/Kconfig" source "kernel/Kconfig.freezer" -menu "System Type" +menu "Platform selection" + +config ARCH_VEXPRESS + bool "ARMv8 software model (Versatile Express)" + select ARCH_REQUIRE_GPIOLIB + select COMMON_CLK_VERSATILE + select VEXPRESS_CONFIG + help + This enables support for the ARMv8 software model (Versatile + Express). endmenu diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 09bef29..8d9696ad 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -23,6 +23,7 @@ CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_IOSCHED_DEADLINE is not set +CONFIG_ARCH_VEXPRESS=y CONFIG_SMP=y CONFIG_PREEMPT_VOLUNTARY=y CONFIG_CMDLINE="console=ttyAMA0" @@ -47,11 +48,14 @@ CONFIG_BLK_DEV_SD=y # CONFIG_SCSI_LOWLEVEL is not set CONFIG_NETDEVICES=y CONFIG_MII=y +CONFIG_SMC91X=y # CONFIG_WLAN is not set CONFIG_INPUT_EVDEV=y # CONFIG_SERIO_I8042 is not set # CONFIG_SERIO_SERPORT is not set CONFIG_LEGACY_PTY_COUNT=16 +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y # CONFIG_HW_RANDOM is not set # CONFIG_HWMON is not set CONFIG_FB=y diff --git a/drivers/net/ethernet/smsc/Kconfig b/drivers/net/ethernet/smsc/Kconfig index 5a689af..bb4c167 100644 --- a/drivers/net/ethernet/smsc/Kconfig +++ b/drivers/net/ethernet/smsc/Kconfig @@ -5,7 +5,7 @@ config NET_VENDOR_SMSC bool "SMC (SMSC)/Western Digital devices" default y - depends on ARM || ISA || MAC || ARM || MIPS || M32R || SUPERH || \ + depends on ARM || ISA || MAC || ARM64 || MIPS || M32R || SUPERH || \ BLACKFIN || MN10300 || COLDFIRE || PCI || PCMCIA ---help--- If you have a network (Ethernet) card belonging to this class, say Y @@ -40,7 +40,7 @@ config SMC91X select NET_CORE select MII depends on (ARM || M32R || SUPERH || MIPS || BLACKFIN || \ - MN10300 || COLDFIRE) + MN10300 || COLDFIRE || ARM64) ---help--- This is a driver for SMC's 91x series of Ethernet chipsets, including the SMC91C94 and the SMC91C111. Say Y if you want it -- cgit v0.10.2 From c47d6a04e6ed22ccc5d89aaf2a136bf4971de310 Mon Sep 17 00:00:00 2001 From: Mark Rutland Date: Tue, 30 Apr 2013 11:11:15 +0100 Subject: arm64: klib: bitops: fix unpredictable stxr usage We're currently relying on unpredictable behaviour in our testops (test_and_*_bit), as stxr is unpredictable when the status register and the source register are the same This patch changes reallocates the status register so as to bring us back into the realm of predictable behaviour. Boot tested on an AEMv8 model. Signed-off-by: Mark Rutland Signed-off-by: Catalin Marinas diff --git a/arch/arm64/lib/bitops.S b/arch/arm64/lib/bitops.S index fd1e801..eaed8bb 100644 --- a/arch/arm64/lib/bitops.S +++ b/arch/arm64/lib/bitops.S @@ -50,8 +50,8 @@ ENTRY( \name ) 1: ldxr x2, [x1] lsr x0, x2, x3 // Save old value of bit \instr x2, x2, x4 // toggle bit - stxr w2, x2, [x1] - cbnz w2, 1b + stxr w5, x2, [x1] + cbnz w5, 1b smp_dmb ish and x0, x0, #1 3: ret -- cgit v0.10.2 From 16c85a1fd73eade2ae290d759924c09b4595f504 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Tue, 30 Apr 2013 15:58:37 +0100 Subject: arm64: Use acquire/release semantics instead of explicit DMB This patch changes the test_and_*_bit functions to use the load-acquire/store-release instructions instead of explicit DMB. Signed-off-by: Catalin Marinas diff --git a/arch/arm64/lib/bitops.S b/arch/arm64/lib/bitops.S index eaed8bb..36216d3 100644 --- a/arch/arm64/lib/bitops.S +++ b/arch/arm64/lib/bitops.S @@ -46,13 +46,11 @@ ENTRY( \name ) mov x2, #1 add x1, x1, x0, lsr #3 // Get word offset lsl x4, x2, x3 // Create mask - smp_dmb ish -1: ldxr x2, [x1] +1: ldaxr x2, [x1] lsr x0, x2, x3 // Save old value of bit \instr x2, x2, x4 // toggle bit - stxr w5, x2, [x1] + stlxr w5, x2, [x1] cbnz w5, 1b - smp_dmb ish and x0, x0, #1 3: ret ENDPROC(\name ) -- cgit v0.10.2