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 --- arch/arm64/kernel/early_printk.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'arch/arm64/kernel') diff --git a/arch/arm64/kernel/early_printk.c b/arch/arm64/kernel/early_printk.c index 7e320a2edb9b..0bb7436c57dc 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 v1.2.1 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 --- arch/arm64/kernel/early_printk.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'arch/arm64/kernel') diff --git a/arch/arm64/kernel/early_printk.c b/arch/arm64/kernel/early_printk.c index 0bb7436c57dc..ac974f48a7a2 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 v1.2.1 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 --- arch/arm64/kernel/setup.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch/arm64/kernel') diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 113db863f832..9c023d714f44 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 v1.2.1 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 --- arch/arm64/kernel/smp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch/arm64/kernel') diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index bdd34597254b..a57a373d305f 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 v1.2.1 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 --- arch/arm64/kernel/setup.c | 4 +++ arch/arm64/kernel/smp.c | 92 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 89 insertions(+), 7 deletions(-) (limited to 'arch/arm64/kernel') diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 9c023d714f44..6a9a53292590 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 a57a373d305f..d4dcc6515253 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 v1.2.1 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 --- arch/arm64/kernel/head.S | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/arm64/kernel') diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 0a0a49756826..53dcae49e729 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 v1.2.1 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 --- arch/arm64/kernel/arm64ksyms.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch/arm64/kernel') diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c index aa3e948f7885..d7f7b17c414e 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); -- cgit v1.2.1 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 --- arch/arm64/kernel/arm64ksyms.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/arm64/kernel') diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c index d7f7b17c414e..a5d0d4643109 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); -- cgit v1.2.1 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 --- arch/arm64/kernel/arm64ksyms.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'arch/arm64/kernel') diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c index a5d0d4643109..7df1aad29b67 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); -- cgit v1.2.1 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 --- arch/arm64/kernel/smp_psci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/arm64/kernel') diff --git a/arch/arm64/kernel/smp_psci.c b/arch/arm64/kernel/smp_psci.c index 112091684c22..0c533301be77 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 v1.2.1 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 --- arch/arm64/kernel/irq.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'arch/arm64/kernel') diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c index 0373c6609eaf..ecb3354292ed 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 v1.2.1 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 --- arch/arm64/kernel/entry.S | 53 ++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 26 deletions(-) (limited to 'arch/arm64/kernel') diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 514d6098dbee..c7e047049f2c 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 v1.2.1 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 --- arch/arm64/kernel/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm64/kernel') diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index 0337cdb0667b..c2cc2493481b 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 v1.2.1 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 --- arch/arm64/kernel/smp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch/arm64/kernel') diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index d4dcc6515253..a886194e58fd 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 v1.2.1 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 --- arch/arm64/kernel/process.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch/arm64/kernel') diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index c2cc2493481b..116a60abe86f 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 v1.2.1 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 --- arch/arm64/kernel/smp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/arm64/kernel') diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index a886194e58fd..1e22ff9ae153 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 v1.2.1