diff options
Diffstat (limited to 'arch/arc')
43 files changed, 461 insertions, 548 deletions
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 9063ae6553cc..9596b0ab108d 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -57,7 +57,7 @@ config ARCH_FLATMEM_ENABLE config MMU def_bool y -config NO_IOPORT +config NO_IOPORT_MAP def_bool y config GENERIC_CALIBRATE_DELAY @@ -128,8 +128,8 @@ config SMP default n help This enables support for systems with more than one CPU. If you have - a system with only one CPU, like most personal computers, say N. If - you have a system with more than one CPU, say Y. + a system with only one CPU, say N. If you have a system with more + than one CPU, say Y. if SMP @@ -356,7 +356,6 @@ config ARC_CURR_IN_REG config ARC_MISALIGN_ACCESS bool "Emulate unaligned memory access (userspace only)" - default N select SYSCTL_ARCH_UNALIGN_NO_WARN select SYSCTL_ARCH_UNALIGN_ALLOW help @@ -409,17 +408,6 @@ config ARC_DBG_TLB_MISS_COUNT Counts number of I and D TLB Misses and exports them via Debugfs The counters can be cleared via Debugfs as well -config CMDLINE_UBOOT - bool "Support U-boot kernel command line passing" - default n - help - If you are using U-boot (www.denx.de) and wish to pass the kernel - command line from the U-boot environment to the Linux kernel then - switch this option on. - ARC U-boot will setup the cmdline in RAM/flash and set r2 to point - to it. kernel startup code will append this to DeviceTree - /bootargs provided cmdline args. - config ARC_BUILTIN_DTB_NAME string "Built in DTB" help diff --git a/arch/arc/boot/.gitignore b/arch/arc/boot/.gitignore index 5d65b54bf17a..5246969a20c5 100644 --- a/arch/arc/boot/.gitignore +++ b/arch/arc/boot/.gitignore @@ -1 +1,2 @@ *.dtb* +uImage diff --git a/arch/arc/boot/dts/angel4.dts b/arch/arc/boot/dts/angel4.dts index bcf662d21a57..5bb2fdaca02f 100644 --- a/arch/arc/boot/dts/angel4.dts +++ b/arch/arc/boot/dts/angel4.dts @@ -17,7 +17,7 @@ interrupt-parent = <&intc>; chosen { - bootargs = "console=ttyARC0,115200n8"; + bootargs = "console=ttyARC0,115200n8 earlyprintk=ttyARC0"; }; aliases { diff --git a/arch/arc/boot/dts/nsimosci.dts b/arch/arc/boot/dts/nsimosci.dts index ea16d782af58..4f31b2eb5cdf 100644 --- a/arch/arc/boot/dts/nsimosci.dts +++ b/arch/arc/boot/dts/nsimosci.dts @@ -11,13 +11,16 @@ / { compatible = "snps,nsimosci"; - clock-frequency = <80000000>; /* 80 MHZ */ + clock-frequency = <20000000>; /* 20 MHZ */ #address-cells = <1>; #size-cells = <1>; interrupt-parent = <&intc>; chosen { - bootargs = "console=tty0 consoleblank=0"; + /* this is for console on PGU */ + /* bootargs = "console=tty0 consoleblank=0"; */ + /* this is for console on serial */ + bootargs = "earlycon=uart8250,mmio32,0xc0000000,115200n8 console=ttyS0,115200n8 consoleblank=0 debug"; }; aliases { @@ -44,15 +47,14 @@ }; uart0: serial@c0000000 { - compatible = "snps,dw-apb-uart"; + compatible = "ns8250"; reg = <0xc0000000 0x2000>; interrupts = <11>; - #clock-frequency = <80000000>; clock-frequency = <3686400>; baud = <115200>; reg-shift = <2>; reg-io-width = <4>; - status = "okay"; + no-loopback-test = <1>; }; pgu0: pgu@c9000000 { diff --git a/arch/arc/boot/dts/skeleton.dts b/arch/arc/boot/dts/skeleton.dts deleted file mode 100644 index 25a84fb5b3dc..000000000000 --- a/arch/arc/boot/dts/skeleton.dts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com) - * - * 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. - */ -/dts-v1/; - -/include/ "skeleton.dtsi" diff --git a/arch/arc/configs/nsimosci_defconfig b/arch/arc/configs/nsimosci_defconfig index 451af30914f6..c01ba35a4eff 100644 --- a/arch/arc/configs/nsimosci_defconfig +++ b/arch/arc/configs/nsimosci_defconfig @@ -54,6 +54,7 @@ CONFIG_SERIO_ARC_PS2=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_OF_PLATFORM=y CONFIG_SERIAL_ARC=y CONFIG_SERIAL_ARC_CONSOLE=y # CONFIG_HW_RANDOM is not set diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild index 5943f7f9d325..e76fd79f32b0 100644 --- a/arch/arc/include/asm/Kbuild +++ b/arch/arc/include/asm/Kbuild @@ -1,16 +1,18 @@ generic-y += auxvec.h -generic-y += bugs.h +generic-y += barrier.h generic-y += bitsperlong.h +generic-y += bugs.h generic-y += clkdev.h generic-y += cputime.h generic-y += device.h generic-y += div64.h generic-y += emergency-restart.h generic-y += errno.h -generic-y += fcntl.h generic-y += fb.h +generic-y += fcntl.h generic-y += ftrace.h generic-y += hardirq.h +generic-y += hash.h generic-y += hw_irq.h generic-y += ioctl.h generic-y += ioctls.h @@ -20,6 +22,7 @@ generic-y += kmap_types.h generic-y += kvm_para.h generic-y += local.h generic-y += local64.h +generic-y += mcs_spinlock.h generic-y += mman.h generic-y += msgbuf.h generic-y += param.h @@ -28,6 +31,7 @@ generic-y += pci.h generic-y += percpu.h generic-y += poll.h generic-y += posix_types.h +generic-y += preempt.h generic-y += resource.h generic-y += scatterlist.h generic-y += sembuf.h @@ -46,4 +50,3 @@ generic-y += ucontext.h generic-y += user.h generic-y += vga.h generic-y += xor.h -generic-y += preempt.h diff --git a/arch/arc/include/asm/barrier.h b/arch/arc/include/asm/barrier.h deleted file mode 100644 index f6cb7c4ffb35..000000000000 --- a/arch/arc/include/asm/barrier.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) - * - * 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. - */ - -#ifndef __ASM_BARRIER_H -#define __ASM_BARRIER_H - -#ifndef __ASSEMBLY__ - -/* TODO-vineetg: Need to see what this does, don't we need sync anywhere */ -#define mb() __asm__ __volatile__ ("" : : : "memory") -#define rmb() mb() -#define wmb() mb() -#define set_mb(var, value) do { var = value; mb(); } while (0) -#define set_wmb(var, value) do { var = value; wmb(); } while (0) -#define read_barrier_depends() mb() - -/* TODO-vineetg verify the correctness of macros here */ -#ifdef CONFIG_SMP -#define smp_mb() mb() -#define smp_rmb() rmb() -#define smp_wmb() wmb() -#else -#define smp_mb() barrier() -#define smp_rmb() barrier() -#define smp_wmb() barrier() -#endif - -#define smp_mb__before_atomic_dec() barrier() -#define smp_mb__after_atomic_dec() barrier() -#define smp_mb__before_atomic_inc() barrier() -#define smp_mb__after_atomic_inc() barrier() - -#define smp_read_barrier_depends() do { } while (0) - -#endif - -#endif diff --git a/arch/arc/include/asm/bitops.h b/arch/arc/include/asm/bitops.h index 647a83a8e756..ebc0cf3164dc 100644 --- a/arch/arc/include/asm/bitops.h +++ b/arch/arc/include/asm/bitops.h @@ -19,6 +19,7 @@ #include <linux/types.h> #include <linux/compiler.h> +#include <asm/barrier.h> /* * Hardware assisted read-modify-write using ARC700 LLOCK/SCOND insns. @@ -496,10 +497,6 @@ static inline __attribute__ ((const)) int __ffs(unsigned long word) */ #define ffz(x) __ffs(~(x)) -/* TODO does this affect uni-processor code */ -#define smp_mb__before_clear_bit() barrier() -#define smp_mb__after_clear_bit() barrier() - #include <asm-generic/bitops/hweight.h> #include <asm-generic/bitops/fls64.h> #include <asm-generic/bitops/sched.h> diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h index 2fd3162ec4df..b3c750979aa1 100644 --- a/arch/arc/include/asm/cache.h +++ b/arch/arc/include/asm/cache.h @@ -55,4 +55,31 @@ extern void read_decode_cache_bcr(void); #endif /* !__ASSEMBLY__ */ +/* Instruction cache related Auxiliary registers */ +#define ARC_REG_IC_BCR 0x77 /* Build Config reg */ +#define ARC_REG_IC_IVIC 0x10 +#define ARC_REG_IC_CTRL 0x11 +#define ARC_REG_IC_IVIL 0x19 +#if defined(CONFIG_ARC_MMU_V3) +#define ARC_REG_IC_PTAG 0x1E +#endif + +/* Bit val in IC_CTRL */ +#define IC_CTRL_CACHE_DISABLE 0x1 + +/* Data cache related Auxiliary registers */ +#define ARC_REG_DC_BCR 0x72 /* Build Config reg */ +#define ARC_REG_DC_IVDC 0x47 +#define ARC_REG_DC_CTRL 0x48 +#define ARC_REG_DC_IVDL 0x4A +#define ARC_REG_DC_FLSH 0x4B +#define ARC_REG_DC_FLDL 0x4C +#if defined(CONFIG_ARC_MMU_V3) +#define ARC_REG_DC_PTAG 0x5C +#endif + +/* Bit val in DC_CTRL */ +#define DC_CTRL_INV_MODE_FLUSH 0x40 +#define DC_CTRL_FLUSH_STATUS 0x100 + #endif /* _ASM_CACHE_H */ diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h index 291a70db68b8..fb4efb648971 100644 --- a/arch/arc/include/asm/irq.h +++ b/arch/arc/include/asm/irq.h @@ -19,8 +19,6 @@ #include <asm-generic/irq.h> extern void arc_init_IRQ(void); -extern int get_hw_config_num_irq(void); - -void arc_local_timer_setup(unsigned int cpu); +void arc_local_timer_setup(void); #endif diff --git a/arch/arc/include/asm/linkage.h b/arch/arc/include/asm/linkage.h index 0283e9e44e0d..5faad17118b4 100644 --- a/arch/arc/include/asm/linkage.h +++ b/arch/arc/include/asm/linkage.h @@ -11,19 +11,7 @@ #ifdef __ASSEMBLY__ -/* Can't use the ENTRY macro in linux/linkage.h - * gas considers ';' as comment vs. newline - */ -.macro ARC_ENTRY name - .global \name - .align 4 - \name: -.endm - -.macro ARC_EXIT name -#define ASM_PREV_SYM_ADDR(name) .-##name - .size \ name, ASM_PREV_SYM_ADDR(\name) -.endm +#define ASM_NL ` /* use '`' to mark new line in macro */ /* annotation for data we want in DCCM - if enabled in .config */ .macro ARCFP_DATA nm diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h index 15334ab66b56..d99f9b37cd15 100644 --- a/arch/arc/include/asm/processor.h +++ b/arch/arc/include/asm/processor.h @@ -18,7 +18,6 @@ #ifndef __ASSEMBLY__ -#include <asm/arcregs.h> /* for STATUS_E1_MASK et all */ #include <asm/ptrace.h> /* Arch specific stuff which needs to be saved per task. @@ -41,15 +40,13 @@ struct thread_struct { /* Forward declaration, a strange C thing */ struct task_struct; -/* - * Return saved PC of a blocked thread. - */ +/* Return saved PC of a blocked thread */ unsigned long thread_saved_pc(struct task_struct *t); #define task_pt_regs(p) \ ((struct pt_regs *)(THREAD_SIZE + (void *)task_stack_page(p)) - 1) -/* Free all resources held by a thread. */ +/* Free all resources held by a thread */ #define release_thread(thread) do { } while (0) /* Prepare to copy thread state - unlazy all lazy status */ @@ -82,26 +79,8 @@ unsigned long thread_saved_pc(struct task_struct *t); #define KSTK_BLINK(tsk) KSTK_REG(tsk, 4) #define KSTK_FP(tsk) KSTK_REG(tsk, 0) -/* - * Do necessary setup to start up a newly executed thread. - * - * E1,E2 so that Interrupts are enabled in user mode - * L set, so Loop inhibited to begin with - * lp_start and lp_end seeded with bogus non-zero values so to easily catch - * the ARC700 sr to lp_start hardware bug - */ -#define start_thread(_regs, _pc, _usp) \ -do { \ - set_fs(USER_DS); /* reads from user space */ \ - (_regs)->ret = (_pc); \ - /* Interrupts enabled in User Mode */ \ - (_regs)->status32 = STATUS_U_MASK | STATUS_L_MASK \ - | STATUS_E1_MASK | STATUS_E2_MASK; \ - (_regs)->sp = (_usp); \ - /* bogus seed values for debugging */ \ - (_regs)->lp_start = 0x10; \ - (_regs)->lp_end = 0x80; \ -} while (0) +extern void start_thread(struct pt_regs * regs, unsigned long pc, + unsigned long usp); extern unsigned int get_wchan(struct task_struct *p); diff --git a/arch/arc/include/asm/sections.h b/arch/arc/include/asm/sections.h index 764f1e3ba752..09db952e14bd 100644 --- a/arch/arc/include/asm/sections.h +++ b/arch/arc/include/asm/sections.h @@ -12,6 +12,5 @@ #include <asm-generic/sections.h> extern char __arc_dccm_base[]; -extern char __dtb_start[]; #endif diff --git a/arch/arc/include/asm/smp.h b/arch/arc/include/asm/smp.h index eefc29f08cdb..5d06eee43ea9 100644 --- a/arch/arc/include/asm/smp.h +++ b/arch/arc/include/asm/smp.h @@ -46,14 +46,14 @@ extern int smp_ipi_irq_setup(int cpu, int irq); * * @info: SoC SMP specific info for /proc/cpuinfo etc * @cpu_kick: For Master to kickstart a cpu (optionally at a PC) - * @ipi_send: To send IPI to a @cpumask - * @ips_clear: To clear IPI received by @cpu at @irq + * @ipi_send: To send IPI to a @cpu + * @ips_clear: To clear IPI received at @irq */ struct plat_smp_ops { const char *info; void (*cpu_kick)(int cpu, unsigned long pc); - void (*ipi_send)(void *callmap); - void (*ipi_clear)(int cpu, int irq); + void (*ipi_send)(int cpu); + void (*ipi_clear)(int irq); }; /* TBD: stop exporting it for direct population by platform */ diff --git a/arch/arc/include/uapi/asm/Kbuild b/arch/arc/include/uapi/asm/Kbuild index 18fefaea73fd..f50d02df78d5 100644 --- a/arch/arc/include/uapi/asm/Kbuild +++ b/arch/arc/include/uapi/asm/Kbuild @@ -2,11 +2,4 @@ include include/uapi/asm-generic/Kbuild.asm header-y += elf.h header-y += page.h -header-y += setup.h -header-y += byteorder.h header-y += cachectl.h -header-y += ptrace.h -header-y += sigcontext.h -header-y += signal.h -header-y += swab.h -header-y += unistd.h diff --git a/arch/arc/include/uapi/asm/ptrace.h b/arch/arc/include/uapi/asm/ptrace.h index 2618cc13ba75..76a7739aab1c 100644 --- a/arch/arc/include/uapi/asm/ptrace.h +++ b/arch/arc/include/uapi/asm/ptrace.h @@ -11,6 +11,7 @@ #ifndef _UAPI__ASM_ARC_PTRACE_H #define _UAPI__ASM_ARC_PTRACE_H +#define PTRACE_GET_THREAD_AREA 25 #ifndef __ASSEMBLY__ /* diff --git a/arch/arc/kernel/ctx_sw_asm.S b/arch/arc/kernel/ctx_sw_asm.S index 65690e7fcc8c..e248594097e7 100644 --- a/arch/arc/kernel/ctx_sw_asm.S +++ b/arch/arc/kernel/ctx_sw_asm.S @@ -10,9 +10,9 @@ * -This is the more "natural" hand written assembler */ +#include <linux/linkage.h> #include <asm/entry.h> /* For the SAVE_* macros */ #include <asm/asm-offsets.h> -#include <asm/linkage.h> #define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4) @@ -62,4 +62,4 @@ __switch_to: ld.ab blink, [sp, 4] j [blink] -ARC_EXIT __switch_to +END(__switch_to) diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c index b6dc4e21fd32..fffdb5e41b20 100644 --- a/arch/arc/kernel/devtree.c +++ b/arch/arc/kernel/devtree.c @@ -41,8 +41,8 @@ const struct machine_desc * __init setup_machine_fdt(void *dt) { const struct machine_desc *mdesc; unsigned long dt_root; - void *clk; - unsigned long len; + const void *clk; + int len; if (!early_init_dt_scan(dt)) return NULL; diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index 47d09d07f093..83a046a7cd06 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S @@ -141,7 +141,7 @@ VECTOR EV_Extension ; 0x130, Extn Intruction Excp (0x26) VECTOR reserved ; Reserved Exceptions .endr -#include <linux/linkage.h> /* ARC_{EXTRY,EXIT} */ +#include <linux/linkage.h> /* {EXTRY,EXIT} */ #include <asm/entry.h> /* SAVE_ALL_{INT1,INT2,SYS...} */ #include <asm/errno.h> #include <asm/arcregs.h> @@ -156,7 +156,7 @@ ARCFP_DATA int1_saved_reg int1_saved_reg: .zero 4 -/* Each Interrupt level needs it's own scratch */ +/* Each Interrupt level needs its own scratch */ #ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS ARCFP_DATA int2_saved_reg @@ -184,7 +184,7 @@ reserved: ; processor restart ; --------------------------------------------- ; Level 2 ISR: Can interrupt a Level 1 ISR ; --------------------------------------------- -ARC_ENTRY handle_interrupt_level2 +ENTRY(handle_interrupt_level2) ; TODO-vineetg for SMP this wont work ; free up r9 as scratchpad @@ -225,14 +225,14 @@ ARC_ENTRY handle_interrupt_level2 b ret_from_exception -ARC_EXIT handle_interrupt_level2 +END(handle_interrupt_level2) #endif ; --------------------------------------------- ; Level 1 ISR ; --------------------------------------------- -ARC_ENTRY handle_interrupt_level1 +ENTRY(handle_interrupt_level1) /* free up r9 as scratchpad */ #ifdef CONFIG_SMP @@ -265,7 +265,7 @@ ARC_ENTRY handle_interrupt_level1 sr r8, [AUX_IRQ_LV12] ; clear bit in Sticky Status Reg b ret_from_exception -ARC_EXIT handle_interrupt_level1 +END(handle_interrupt_level1) ;################### Non TLB Exception Handling ############################# @@ -273,7 +273,7 @@ ARC_EXIT handle_interrupt_level1 ; Instruction Error Exception Handler ; --------------------------------------------- -ARC_ENTRY instr_service +ENTRY(instr_service) EXCEPTION_PROLOGUE @@ -284,13 +284,13 @@ ARC_ENTRY instr_service bl do_insterror_or_kprobe b ret_from_exception -ARC_EXIT instr_service +END(instr_service) ; --------------------------------------------- ; Memory Error Exception Handler ; --------------------------------------------- -ARC_ENTRY mem_service +ENTRY(mem_service) EXCEPTION_PROLOGUE @@ -301,13 +301,13 @@ ARC_ENTRY mem_service bl do_memory_error b ret_from_exception -ARC_EXIT mem_service +END(mem_service) ; --------------------------------------------- ; Machine Check Exception Handler ; --------------------------------------------- -ARC_ENTRY EV_MachineCheck +ENTRY(EV_MachineCheck) EXCEPTION_PROLOGUE @@ -331,13 +331,13 @@ ARC_ENTRY EV_MachineCheck j do_machine_check_fault -ARC_EXIT EV_MachineCheck +END(EV_MachineCheck) ; --------------------------------------------- ; Protection Violation Exception Handler ; --------------------------------------------- -ARC_ENTRY EV_TLBProtV +ENTRY(EV_TLBProtV) EXCEPTION_PROLOGUE @@ -385,12 +385,12 @@ ARC_ENTRY EV_TLBProtV b ret_from_exception -ARC_EXIT EV_TLBProtV +END(EV_TLBProtV) ; --------------------------------------------- ; Privilege Violation Exception Handler ; --------------------------------------------- -ARC_ENTRY EV_PrivilegeV +ENTRY(EV_PrivilegeV) EXCEPTION_PROLOGUE @@ -401,12 +401,12 @@ ARC_ENTRY EV_PrivilegeV bl do_privilege_fault b ret_from_exception -ARC_EXIT EV_PrivilegeV +END(EV_PrivilegeV) ; --------------------------------------------- ; Extension Instruction Exception Handler ; --------------------------------------------- -ARC_ENTRY EV_Extension +ENTRY(EV_Extension) EXCEPTION_PROLOGUE @@ -417,7 +417,7 @@ ARC_ENTRY EV_Extension bl do_extension_fault b ret_from_exception -ARC_EXIT EV_Extension +END(EV_Extension) ;######################### System Call Tracing ######################### @@ -473,7 +473,7 @@ trap_with_param: lr r0, [efa] mov r1, sp - ; Now that we have read EFA, its safe to do "fake" rtie + ; Now that we have read EFA, it is safe to do "fake" rtie ; and get out of CPU exception mode FAKE_RET_FROM_EXCPN r11 @@ -504,7 +504,7 @@ trap_with_param: ; (2) Break Points ;------------------------------------------------------------------ -ARC_ENTRY EV_Trap +ENTRY(EV_Trap) EXCEPTION_PROLOGUE @@ -534,9 +534,9 @@ ARC_ENTRY EV_Trap jl [r9] ; Entry into Sys Call Handler ; fall through to ret_from_system_call -ARC_EXIT EV_Trap +END(EV_Trap) -ARC_ENTRY ret_from_system_call +ENTRY(ret_from_system_call) st r0, [sp, PT_r0] ; sys call return value in pt_regs @@ -546,7 +546,7 @@ ARC_ENTRY ret_from_system_call ; ; If ret to user mode do we need to handle signals, schedule() et al. -ARC_ENTRY ret_from_exception +ENTRY(ret_from_exception) ; Pre-{IRQ,Trap,Exception} K/U mode from pt_regs->status32 ld r8, [sp, PT_status32] ; returning to User/Kernel Mode @@ -614,11 +614,13 @@ resume_user_mode_begin: resume_kernel_mode: -#ifdef CONFIG_PREEMPT - - ; This is a must for preempt_schedule_irq() + ; Disable Interrupts from this point on + ; CONFIG_PREEMPT: This is a must for preempt_schedule_irq() + ; !CONFIG_PREEMPT: To ensure restore_regs is intr safe IRQ_DISABLE r9 +#ifdef CONFIG_PREEMPT + ; Can't preempt if preemption disabled GET_CURR_THR_INFO_FROM_SP r10 ld r8, [r10, THREAD_INFO_PREEMPT_COUNT] @@ -676,9 +678,9 @@ not_exception: brne r9, event_IRQ2, 149f ;------------------------------------------------------------------ - ; if L2 IRQ interrupted a L1 ISR, we'd disbaled preemption earlier - ; so that sched doesnt move to new task, causing L1 to be delayed - ; undeterministically. Now that we've achieved that, lets reset + ; if L2 IRQ interrupted an L1 ISR, we'd disabled preemption earlier + ; so that sched doesn't move to new task, causing L1 to be delayed + ; undeterministically. Now that we've achieved that, let's reset ; things to what they were, before returning from L2 context ;---------------------------------------------------------------- @@ -726,15 +728,15 @@ not_level1_interrupt: debug_marker_syscall: rtie -ARC_EXIT ret_from_exception +END(ret_from_exception) -ARC_ENTRY ret_from_fork +ENTRY(ret_from_fork) ; when the forked child comes here from the __switch_to function ; r0 has the last task pointer. ; put last task in scheduler queue bl @schedule_tail - ; If kernel thread, jump to it's entry-point + ; If kernel thread, jump to its entry-point ld r9, [sp, PT_status32] brne r9, 0, 1f @@ -745,11 +747,11 @@ ARC_ENTRY ret_from_fork ; special case of kernel_thread entry point returning back due to ; kernel_execve() - pretend return from syscall to ret to userland b ret_from_exception -ARC_EXIT ret_from_fork +END(ret_from_fork) ;################### Special Sys Call Wrappers ########################## -ARC_ENTRY sys_clone_wrapper +ENTRY(sys_clone_wrapper) SAVE_CALLEE_SAVED_USER bl @sys_clone DISCARD_CALLEE_SAVED_USER @@ -759,7 +761,7 @@ ARC_ENTRY sys_clone_wrapper bnz tracesys_exit b ret_from_system_call -ARC_EXIT sys_clone_wrapper +END(sys_clone_wrapper) #ifdef CONFIG_ARC_DW2_UNWIND ; Workaround for bug 94179 (STAR ): diff --git a/arch/arc/kernel/head.S b/arch/arc/kernel/head.S index 2c878e964a64..4d2481bd8b98 100644 --- a/arch/arc/kernel/head.S +++ b/arch/arc/kernel/head.S @@ -12,10 +12,42 @@ * to skip certain things during boot on simulator */ +#include <linux/linkage.h> #include <asm/asm-offsets.h> #include <asm/entry.h> -#include <linux/linkage.h> #include <asm/arcregs.h> +#include <asm/cache.h> + +.macro CPU_EARLY_SETUP + + ; Setting up Vectror Table (in case exception happens in early boot + sr @_int_vec_base_lds, [AUX_INTR_VEC_BASE] + + ; Disable I-cache/D-cache if kernel so configured + lr r5, [ARC_REG_IC_BCR] + breq r5, 0, 1f ; I$ doesn't exist + lr r5, [ARC_REG_IC_CTRL] +#ifdef CONFIG_ARC_HAS_ICACHE + bclr r5, r5, 0 ; 0 - Enable, 1 is Disable +#else + bset r5, r5, 0 ; I$ exists, but is not used +#endif + sr r5, [ARC_REG_IC_CTRL] + +1: + lr r5, [ARC_REG_DC_BCR] + breq r5, 0, 1f ; D$ doesn't exist + lr r5, [ARC_REG_DC_CTRL] + bclr r5, r5, 6 ; Invalidate (discard w/o wback) +#ifdef CONFIG_ARC_HAS_DCACHE + bclr r5, r5, 0 ; Enable (+Inv) +#else + bset r5, r5, 0 ; Disable (+Inv) +#endif + sr r5, [ARC_REG_DC_CTRL] + +1: +.endm .cpu A7 @@ -24,13 +56,13 @@ .globl stext stext: ;------------------------------------------------------------------- - ; Don't clobber r0-r4 yet. It might have bootloader provided info + ; Don't clobber r0-r2 yet. It might have bootloader provided info ;------------------------------------------------------------------- - sr @_int_vec_base_lds, [AUX_INTR_VEC_BASE] + CPU_EARLY_SETUP #ifdef CONFIG_SMP - ; Only Boot (Master) proceeds. Others wait in platform dependent way + ; Ensure Boot (Master) proceeds. Others wait in platform dependent way ; IDENTITY Reg [ 3 2 1 0 ] ; (cpu-id) ^^^ => Zero for UP ARC700 ; => #Core-ID if SMP (Master 0) @@ -39,35 +71,25 @@ stext: ; need to make sure only boot cpu takes this path. GET_CPU_ID r5 cmp r5, 0 - jnz arc_platform_smp_wait_to_boot + mov.ne r0, r5 + jne arc_platform_smp_wait_to_boot #endif ; Clear BSS before updating any globals ; XXX: use ZOL here mov r5, __bss_start - mov r6, __bss_stop + sub r6, __bss_stop, r5 + lsr.f lp_count, r6, 2 + lpnz 1f + st.ab 0, [r5, 4] 1: - st.ab 0, [r5,4] - brlt r5, r6, 1b -#ifdef CONFIG_CMDLINE_UBOOT - ; support for bootloader provided cmdline - ; If cmdline passed by u-boot, then - ; r0 = 1 (because ATAGS parsing, now retired, used to use 0) - ; r1 = magic number (board identity) - ; r2 = addr of cmdline string (somewhere in memory/flash) - - brne r0, 1, .Lother_bootup_chores ; u-boot didn't pass cmdline - breq r2, 0, .Lother_bootup_chores ; or cmdline is NULL - - mov r5, @command_line -1: - ldb.ab r6, [r2, 1] - breq r6, 0, .Lother_bootup_chores - b.d 1b - stb.ab r6, [r5, 1] -#endif - -.Lother_bootup_chores: + ; Uboot - kernel ABI + ; r0 = [0] No uboot interaction, [1] cmdline in r2, [2] DTB in r2 + ; r1 = magic number (board identity, unused as of now + ; r2 = pointer to uboot provided cmdline or external DTB in mem + ; These are handled later in setup_arch() + st r0, [@uboot_tag] + st r2, [@uboot_arg] ; Identify if running on ISS vs Silicon ; IDENTITY Reg [ 3 2 1 0 ] @@ -101,7 +123,7 @@ stext: first_lines_of_secondary: - sr @_int_vec_base_lds, [AUX_INTR_VEC_BASE] + CPU_EARLY_SETUP ; setup per-cpu idle task as "current" on this CPU ld r0, [@secondary_idle_tsk] diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c index a4b141ee9a6a..7d653c0d0773 100644 --- a/arch/arc/kernel/irq.c +++ b/arch/arc/kernel/irq.c @@ -150,24 +150,6 @@ void arch_do_IRQ(unsigned int irq, struct pt_regs *regs) set_irq_regs(old_regs); } -int get_hw_config_num_irq(void) -{ - uint32_t val = read_aux_reg(ARC_REG_VECBASE_BCR); - - switch (val & 0x03) { - case 0: - return 16; - case 1: - return 32; - case 2: - return 8; - default: - return 0; - } - - return 0; -} - /* * arch_local_irq_enable - Enable interrupts. * diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c index 07a3a968fe49..fdd89715d2d3 100644 --- a/arch/arc/kernel/process.c +++ b/arch/arc/kernel/process.c @@ -151,6 +151,29 @@ int copy_thread(unsigned long clone_flags, } /* + * Do necessary setup to start up a new user task + */ +void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long usp) +{ + set_fs(USER_DS); /* user space */ + + regs->sp = usp; + regs->ret = pc; + + /* + * [U]ser Mode bit set + * [L] ZOL loop inhibited to begin with - cleared by a LP insn + * Interrupts enabled + */ + regs->status32 = STATUS_U_MASK | STATUS_L_MASK | + STATUS_E1_MASK | STATUS_E2_MASK; + + /* bogus seed values for debugging */ + regs->lp_start = 0x10; + regs->lp_end = 0x80; +} + +/* * Some archs flush debug and FPU info here */ void flush_thread(void) diff --git a/arch/arc/kernel/ptrace.c b/arch/arc/kernel/ptrace.c index 5d76706139dd..13b3ffb27a38 100644 --- a/arch/arc/kernel/ptrace.c +++ b/arch/arc/kernel/ptrace.c @@ -146,6 +146,10 @@ long arch_ptrace(struct task_struct *child, long request, pr_debug("REQ=%ld: ADDR =0x%lx, DATA=0x%lx)\n", request, addr, data); switch (request) { + case PTRACE_GET_THREAD_AREA: + ret = put_user(task_thread_info(child)->thr_ptr, + (unsigned long __user *)data); + break; default: ret = ptrace_request(child, request, addr, data); break; diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 643eae4436e0..119dddb752b2 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -29,7 +29,10 @@ int running_on_hw = 1; /* vs. on ISS */ -char __initdata command_line[COMMAND_LINE_SIZE]; +/* Part of U-boot ABI: see head.S */ +int __initdata uboot_tag; +char __initdata *uboot_arg; + const struct machine_desc *machine_desc; struct task_struct *_current_task[NR_CPUS]; /* For stack switching */ @@ -311,19 +314,40 @@ void setup_processor(void) arc_chk_fpu(); } +static inline int is_kernel(unsigned long addr) +{ + if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end) + return 1; + return 0; +} + void __init setup_arch(char **cmdline_p) { - /* This also populates @boot_command_line from /bootargs */ - machine_desc = setup_machine_fdt(__dtb_start); - if (!machine_desc) - panic("Embedded DT invalid\n"); - - /* Append any u-boot provided cmdline */ -#ifdef CONFIG_CMDLINE_UBOOT - /* Add a whitespace seperator between the 2 cmdlines */ - strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); - strlcat(boot_command_line, command_line, COMMAND_LINE_SIZE); -#endif + /* make sure that uboot passed pointer to cmdline/dtb is valid */ + if (uboot_tag && is_kernel((unsigned long)uboot_arg)) + panic("Invalid uboot arg\n"); + + /* See if u-boot passed an external Device Tree blob */ + machine_desc = setup_machine_fdt(uboot_arg); /* uboot_tag == 2 */ + if (!machine_desc) { + /* No, so try the embedded one */ + machine_desc = setup_machine_fdt(__dtb_start); + if (!machine_desc) + panic("Embedded DT invalid\n"); + + /* + * If we are here, it is established that @uboot_arg didn't + * point to DT blob. Instead if u-boot says it is cmdline, + * Appent to embedded DT cmdline. + * setup_machine_fdt() would have populated @boot_command_line + */ + if (uboot_tag == 1) { + /* Ensure a whitespace between the 2 cmdlines */ + strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); + strlcat(boot_command_line, uboot_arg, + COMMAND_LINE_SIZE); + } + } /* Save unparsed command line copy for /proc/cmdline */ *cmdline_p = boot_command_line; diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c index c2f9ebbc38f6..c802bb500602 100644 --- a/arch/arc/kernel/smp.c +++ b/arch/arc/kernel/smp.c @@ -138,7 +138,7 @@ void start_kernel_secondary(void) if (machine_desc->init_smp) machine_desc->init_smp(smp_processor_id()); - arc_local_timer_setup(cpu); + arc_local_timer_setup(); local_irq_enable(); preempt_disable(); @@ -197,51 +197,65 @@ int __init setup_profiling_timer(unsigned int multiplier) /* Inter Processor Interrupt Handling */ /*****************************************************************************/ -/* - * structures for inter-processor calls - * A Collection of single bit ipi messages - * - */ - -/* - * TODO_rajesh investigate tlb message types. - * IPI Timer not needed because each ARC has an individual Interrupting Timer - */ enum ipi_msg_type { - IPI_NOP = 0, + IPI_EMPTY = 0, IPI_RESCHEDULE = 1, IPI_CALL_FUNC, - IPI_CPU_STOP + IPI_CPU_STOP, }; -struct ipi_data { - unsigned long bits; -}; +/* + * In arches with IRQ for each msg type (above), receiver can use IRQ-id to + * figure out what msg was sent. For those which don't (ARC has dedicated IPI + * IRQ), the msg-type needs to be conveyed via per-cpu data + */ -static DEFINE_PER_CPU(struct ipi_data, ipi_data); +static DEFINE_PER_CPU(unsigned long, ipi_data); -static void ipi_send_msg(const struct cpumask *callmap, enum ipi_msg_type msg) +static void ipi_send_msg_one(int cpu, enum ipi_msg_type msg) { + unsigned long __percpu *ipi_data_ptr = per_cpu_ptr(&ipi_data, cpu); + unsigned long old, new; unsigned long flags; - unsigned int cpu; + + pr_debug("%d Sending msg [%d] to %d\n", smp_processor_id(), msg, cpu); local_irq_save(flags); - for_each_cpu(cpu, callmap) { - struct ipi_data *ipi = &per_cpu(ipi_data, cpu); - set_bit(msg, &ipi->bits); - } + /* + * Atomically write new msg bit (in case others are writing too), + * and read back old value + */ + do { + new = old = *ipi_data_ptr; + new |= 1U << msg; + } while (cmpxchg(ipi_data_ptr, old, new) != old); - /* Call the platform specific cross-CPU call function */ - if (plat_smp_ops.ipi_send) - plat_smp_ops.ipi_send((void *)callmap); + /* + * Call the platform specific IPI kick function, but avoid if possible: + * Only do so if there's no pending msg from other concurrent sender(s). + * Otherwise, recevier will see this msg as well when it takes the + * IPI corresponding to that msg. This is true, even if it is already in + * IPI handler, because !@old means it has not yet dequeued the msg(s) + * so @new msg can be a free-loader + */ + if (plat_smp_ops.ipi_send && !old) + plat_smp_ops.ipi_send(cpu); local_irq_restore(flags); } +static void ipi_send_msg(const struct cpumask *callmap, enum ipi_msg_type msg) +{ + unsigned int cpu; + + for_each_cpu(cpu, callmap) + ipi_send_msg_one(cpu, msg); +} + void smp_send_reschedule(int cpu) { - ipi_send_msg(cpumask_of(cpu), IPI_RESCHEDULE); + ipi_send_msg_one(cpu, IPI_RESCHEDULE); } void smp_send_stop(void) @@ -254,7 +268,7 @@ void smp_send_stop(void) void arch_send_call_function_single_ipi(int cpu) { - ipi_send_msg(cpumask_of(cpu), IPI_CALL_FUNC); + ipi_send_msg_one(cpu, IPI_CALL_FUNC); } void arch_send_call_function_ipi_mask(const struct cpumask *mask) @@ -265,33 +279,29 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask) /* * ipi_cpu_stop - handle IPI from smp_send_stop() */ -static void ipi_cpu_stop(unsigned int cpu) +static void ipi_cpu_stop(void) { machine_halt(); } -static inline void __do_IPI(unsigned long *ops, struct ipi_data *ipi, int cpu) +static inline void __do_IPI(unsigned long msg) { - unsigned long msg = 0; - - do { - msg = find_next_bit(ops, BITS_PER_LONG, msg+1); + switch (msg) { + case IPI_RESCHEDULE: + scheduler_ipi(); + break; - switch (msg) { - case IPI_RESCHEDULE: - scheduler_ipi(); - break; + case IPI_CALL_FUNC: + generic_smp_call_function_interrupt(); + break; - case IPI_CALL_FUNC: - generic_smp_call_function_interrupt(); - break; - - case IPI_CPU_STOP: - ipi_cpu_stop(cpu); - break; - } - } while (msg < BITS_PER_LONG); + case IPI_CPU_STOP: + ipi_cpu_stop(); + break; + default: + pr_warn("IPI with unexpected msg %ld\n", msg); + } } /* @@ -300,19 +310,25 @@ static inline void __do_IPI(unsigned long *ops, struct ipi_data *ipi, int cpu) */ irqreturn_t do_IPI(int irq, void *dev_id) { - int cpu = smp_processor_id(); - struct ipi_data *ipi = &per_cpu(ipi_data, cpu); - unsigned long ops; + unsigned long pending; + + pr_debug("IPI [%ld] received on cpu %d\n", + *this_cpu_ptr(&ipi_data), smp_processor_id()); if (plat_smp_ops.ipi_clear) - plat_smp_ops.ipi_clear(cpu, irq); + plat_smp_ops.ipi_clear(irq); /* - * XXX: is this loop really needed - * And do we need to move ipi_clean inside + * "dequeue" the msg corresponding to this IPI (and possibly other + * piggybacked msg from elided IPIs: see ipi_send_msg_one() above) */ - while ((ops = xchg(&ipi->bits, 0)) != 0) - __do_IPI(&ops, ipi, cpu); + pending = xchg(this_cpu_ptr(&ipi_data), 0); + + do { + unsigned long msg = __ffs(pending); + __do_IPI(msg); + pending &= ~(1U << msg); + } while (pending); return IRQ_HANDLED; } @@ -321,8 +337,19 @@ irqreturn_t do_IPI(int irq, void *dev_id) * API called by platform code to hookup arch-common ISR to their IPI IRQ */ static DEFINE_PER_CPU(int, ipi_dev); + +static struct irqaction arc_ipi_irq = { + .name = "IPI Interrupt", + .flags = IRQF_PERCPU, + .handler = do_IPI, +}; + int smp_ipi_irq_setup(int cpu, int irq) { - int *dev_id = &per_cpu(ipi_dev, smp_processor_id()); - return request_percpu_irq(irq, do_IPI, "IPI Interrupt", dev_id); + if (!cpu) + return setup_irq(irq, &arc_ipi_irq); + else + arch_unmask_irq(irq); + + return 0; } diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c index e5f3a837fb35..36c2aa99436f 100644 --- a/arch/arc/kernel/time.c +++ b/arch/arc/kernel/time.c @@ -155,22 +155,6 @@ static void arc_timer_event_setup(unsigned int limit) write_aux_reg(ARC_REG_TIMER0_CTRL, TIMER_CTRL_IE | TIMER_CTRL_NH); } -/* - * Acknowledge the interrupt (oneshot) and optionally re-arm it (periodic) - * -Any write to CTRL Reg will ack the intr (NH bit: Count when not halted) - * -Rearming is done by setting the IE bit - * - * Small optimisation: Normal code would have been - * if (irq_reenable) - * CTRL_REG = (IE | NH); - * else - * CTRL_REG = NH; - * However since IE is BIT0 we can fold the branch - */ -static void arc_timer_event_ack(unsigned int irq_reenable) -{ - write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH); -} static int arc_clkevent_set_next_event(unsigned long delta, struct clock_event_device *dev) @@ -207,10 +191,22 @@ static DEFINE_PER_CPU(struct clock_event_device, arc_clockevent_device) = { static irqreturn_t timer_irq_handler(int irq, void *dev_id) { - struct clock_event_device *clk = this_cpu_ptr(&arc_clockevent_device); + /* + * Note that generic IRQ core could have passed @evt for @dev_id if + * irq_set_chip_and_handler() asked for handle_percpu_devid_irq() + */ + struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device); + int irq_reenable = evt->mode == CLOCK_EVT_MODE_PERIODIC; + + /* + * Any write to CTRL reg ACks the interrupt, we rewrite the + * Count when [N]ot [H]alted bit. + * And re-arm it if perioid by [I]nterrupt [E]nable bit + */ + write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH); + + evt->event_handler(evt); - arc_timer_event_ack(clk->mode == CLOCK_EVT_MODE_PERIODIC); - clk->event_handler(clk); return IRQ_HANDLED; } @@ -222,14 +218,14 @@ static struct irqaction arc_timer_irq = { /* * Setup the local event timer for @cpu - * N.B. weak so that some exotic ARC SoCs can completely override it */ -void __weak arc_local_timer_setup(unsigned int cpu) +void arc_local_timer_setup() { - struct clock_event_device *clk = &per_cpu(arc_clockevent_device, cpu); + struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device); + int cpu = smp_processor_id(); - clk->cpumask = cpumask_of(cpu); - clockevents_config_and_register(clk, arc_get_core_freq(), + evt->cpumask = cpumask_of(cpu); + clockevents_config_and_register(evt, arc_get_core_freq(), 0, ARC_TIMER_MAX); /* @@ -266,7 +262,7 @@ void __init time_init(void) clocksource_register_hz(&arc_counter, arc_get_core_freq()); /* sets up the periodic event timer */ - arc_local_timer_setup(smp_processor_id()); + arc_local_timer_setup(); if (machine_desc->init_time) machine_desc->init_time(); diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c index 73a7450ee622..1badf9b84b51 100644 --- a/arch/arc/kernel/troubleshoot.c +++ b/arch/arc/kernel/troubleshoot.c @@ -86,12 +86,13 @@ static void show_faulting_vma(unsigned long address, char *buf) unsigned long ino = 0; dev_t dev = 0; char *nm = buf; + struct mm_struct *active_mm = current->active_mm; /* can't use print_vma_addr() yet as it doesn't check for * non-inclusive vma */ - - vma = find_vma(current->active_mm, address); + down_read(&active_mm->mmap_sem); + vma = find_vma(active_mm, address); /* check against the find_vma( ) behaviour which returns the next VMA * if the container VMA is not found @@ -110,9 +111,10 @@ static void show_faulting_vma(unsigned long address, char *buf) vma->vm_start < TASK_UNMAPPED_BASE ? address : address - vma->vm_start, nm, vma->vm_start, vma->vm_end); - } else { + } else pr_info(" @No matching VMA found\n"); - } + + up_read(&active_mm->mmap_sem); } static void show_ecr_verbose(struct pt_regs *regs) diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S index 2555f5886af6..dd35bde39f69 100644 --- a/arch/arc/kernel/vmlinux.lds.S +++ b/arch/arc/kernel/vmlinux.lds.S @@ -116,7 +116,7 @@ SECTIONS _edata = .; - BSS_SECTION(0, 0, 0) + BSS_SECTION(4, 4, 4) #ifdef CONFIG_ARC_DW2_UNWIND . = ALIGN(PAGE_SIZE); diff --git a/arch/arc/lib/memcmp.S b/arch/arc/lib/memcmp.S index bc813d55b6c3..978bf8314dfb 100644 --- a/arch/arc/lib/memcmp.S +++ b/arch/arc/lib/memcmp.S @@ -6,7 +6,7 @@ * published by the Free Software Foundation. */ -#include <asm/linkage.h> +#include <linux/linkage.h> #ifdef __LITTLE_ENDIAN__ #define WORD2 r2 @@ -16,7 +16,7 @@ #define SHIFT r2 #endif -ARC_ENTRY memcmp +ENTRY(memcmp) or r12,r0,r1 asl_s r12,r12,30 sub r3,r2,1 @@ -121,4 +121,4 @@ ARC_ENTRY memcmp .Lnil: j_s.d [blink] mov r0,0 -ARC_EXIT memcmp +END(memcmp) diff --git a/arch/arc/lib/memcpy-700.S b/arch/arc/lib/memcpy-700.S index b64cc10ac918..3222573e50de 100644 --- a/arch/arc/lib/memcpy-700.S +++ b/arch/arc/lib/memcpy-700.S @@ -6,9 +6,9 @@ * published by the Free Software Foundation. */ -#include <asm/linkage.h> +#include <linux/linkage.h> -ARC_ENTRY memcpy +ENTRY(memcpy) or r3,r0,r1 asl_s r3,r3,30 mov_s r5,r0 @@ -63,4 +63,4 @@ ARC_ENTRY memcpy .Lendbloop: j_s.d [blink] stb r12,[r5,0] -ARC_EXIT memcpy +END(memcpy) diff --git a/arch/arc/lib/memset.S b/arch/arc/lib/memset.S index 9b2d88d2e141..d36bd43fc98d 100644 --- a/arch/arc/lib/memset.S +++ b/arch/arc/lib/memset.S @@ -6,11 +6,11 @@ * published by the Free Software Foundation. */ -#include <asm/linkage.h> +#include <linux/linkage.h> #define SMALL 7 /* Must be at least 6 to deal with alignment/loop issues. */ -ARC_ENTRY memset +ENTRY(memset) mov_s r4,r0 or r12,r0,r2 bmsk.f r12,r12,1 @@ -46,14 +46,14 @@ ARC_ENTRY memset stb.ab r1,[r4,1] .Ltiny_end: j_s [blink] -ARC_EXIT memset +END(memset) ; memzero: @r0 = mem, @r1 = size_t ; memset: @r0 = mem, @r1 = char, @r2 = size_t -ARC_ENTRY memzero +ENTRY(memzero) ; adjust bzero args to memset args mov r2, r1 mov r1, 0 b memset ;tail call so need to tinker with blink -ARC_EXIT memzero +END(memzero) diff --git a/arch/arc/lib/strchr-700.S b/arch/arc/lib/strchr-700.S index 9c548c7cf001..b725d5862107 100644 --- a/arch/arc/lib/strchr-700.S +++ b/arch/arc/lib/strchr-700.S @@ -11,9 +11,9 @@ presence of the norm instruction makes it easier to operate on whole words branch-free. */ -#include <asm/linkage.h> +#include <linux/linkage.h> -ARC_ENTRY strchr +ENTRY(strchr) extb_s r1,r1 asl r5,r1,8 bmsk r2,r0,1 @@ -130,4 +130,4 @@ ARC_ENTRY strchr j_s.d [blink] mov.mi r0,0 #endif /* ENDIAN */ -ARC_EXIT strchr +END(strchr) diff --git a/arch/arc/lib/strcmp.S b/arch/arc/lib/strcmp.S index 5dc802b45cf3..3544600fefe6 100644 --- a/arch/arc/lib/strcmp.S +++ b/arch/arc/lib/strcmp.S @@ -13,9 +13,9 @@ source 1; however, that would increase the overhead for loop setup / finish, and strcmp might often terminate early. */ -#include <asm/linkage.h> +#include <linux/linkage.h> -ARC_ENTRY strcmp +ENTRY(strcmp) or r2,r0,r1 bmsk_s r2,r2,1 brne r2,0,.Lcharloop @@ -93,4 +93,4 @@ ARC_ENTRY strcmp .Lcmpend: j_s.d [blink] sub r0,r2,r3 -ARC_EXIT strcmp +END(strcmp) diff --git a/arch/arc/lib/strcpy-700.S b/arch/arc/lib/strcpy-700.S index b7ca4ae81d88..8422f38e1218 100644 --- a/arch/arc/lib/strcpy-700.S +++ b/arch/arc/lib/strcpy-700.S @@ -16,9 +16,9 @@ there, but the it is not likely to be taken often, and it would also be likey to cost an unaligned mispredict at the next call. */ -#include <asm/linkage.h> +#include <linux/linkage.h> -ARC_ENTRY strcpy +ENTRY(strcpy) or r2,r0,r1 bmsk_s r2,r2,1 brne.d r2,0,charloop @@ -67,4 +67,4 @@ charloop: brne.d r3,0,charloop stb.ab r3,[r10,1] j [blink] -ARC_EXIT strcpy +END(strcpy) diff --git a/arch/arc/lib/strlen.S b/arch/arc/lib/strlen.S index 39759e099696..53cfd5685a5f 100644 --- a/arch/arc/lib/strlen.S +++ b/arch/arc/lib/strlen.S @@ -6,9 +6,9 @@ * published by the Free Software Foundation. */ -#include <asm/linkage.h> +#include <linux/linkage.h> -ARC_ENTRY strlen +ENTRY(strlen) or r3,r0,7 ld r2,[r3,-7] ld.a r6,[r3,-3] @@ -80,4 +80,4 @@ ARC_ENTRY strlen .Learly_end: b.d .Lend sub_s.ne r1,r1,r1 -ARC_EXIT strlen +END(strlen) diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c index 6b58c1de7577..353b202c37c9 100644 --- a/arch/arc/mm/cache_arc700.c +++ b/arch/arc/mm/cache_arc700.c @@ -73,37 +73,9 @@ #include <asm/cachectl.h> #include <asm/setup.h> -/* Instruction cache related Auxiliary registers */ -#define ARC_REG_IC_BCR 0x77 /* Build Config reg */ -#define ARC_REG_IC_IVIC 0x10 -#define ARC_REG_IC_CTRL 0x11 -#define ARC_REG_IC_IVIL 0x19 -#if (CONFIG_ARC_MMU_VER > 2) -#define ARC_REG_IC_PTAG 0x1E -#endif - -/* Bit val in IC_CTRL */ -#define IC_CTRL_CACHE_DISABLE 0x1 - -/* Data cache related Auxiliary registers */ -#define ARC_REG_DC_BCR 0x72 /* Build Config reg */ -#define ARC_REG_DC_IVDC 0x47 -#define ARC_REG_DC_CTRL 0x48 -#define ARC_REG_DC_IVDL 0x4A -#define ARC_REG_DC_FLSH 0x4B -#define ARC_REG_DC_FLDL 0x4C -#if (CONFIG_ARC_MMU_VER > 2) -#define ARC_REG_DC_PTAG 0x5C -#endif - -/* Bit val in DC_CTRL */ -#define DC_CTRL_INV_MODE_FLUSH 0x40 -#define DC_CTRL_FLUSH_STATUS 0x100 - -char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len) +char *arc_cache_mumbojumbo(int c, char *buf, int len) { int n = 0; - unsigned int c = smp_processor_id(); #define PR_CACHE(p, enb, str) \ { \ @@ -169,72 +141,43 @@ void read_decode_cache_bcr(void) */ void arc_cache_init(void) { - unsigned int cpu = smp_processor_id(); - struct cpuinfo_arc_cache *ic = &cpuinfo_arc700[cpu].icache; - struct cpuinfo_arc_cache *dc = &cpuinfo_arc700[cpu].dcache; - unsigned int dcache_does_alias, temp; + unsigned int __maybe_unused cpu = smp_processor_id(); + struct cpuinfo_arc_cache __maybe_unused *ic, __maybe_unused *dc; char str[256]; printk(arc_cache_mumbojumbo(0, str, sizeof(str))); - if (!ic->ver) - goto chk_dc; - #ifdef CONFIG_ARC_HAS_ICACHE - /* 1. Confirm some of I-cache params which Linux assumes */ - if (ic->line_len != L1_CACHE_BYTES) - panic("Cache H/W doesn't match kernel Config"); - - if (ic->ver != CONFIG_ARC_MMU_VER) - panic("Cache ver doesn't match MMU ver\n"); -#endif - - /* Enable/disable I-Cache */ - temp = read_aux_reg(ARC_REG_IC_CTRL); - -#ifdef CONFIG_ARC_HAS_ICACHE - temp &= ~IC_CTRL_CACHE_DISABLE; -#else - temp |= IC_CTRL_CACHE_DISABLE; + ic = &cpuinfo_arc700[cpu].icache; + if (ic->ver) { + if (ic->line_len != L1_CACHE_BYTES) + panic("ICache line [%d] != kernel Config [%d]", + ic->line_len, L1_CACHE_BYTES); + + if (ic->ver != CONFIG_ARC_MMU_VER) + panic("Cache ver [%d] doesn't match MMU ver [%d]\n", + ic->ver, CONFIG_ARC_MMU_VER); + } #endif - write_aux_reg(ARC_REG_IC_CTRL, temp); - -chk_dc: - if (!dc->ver) - return; - #ifdef CONFIG_ARC_HAS_DCACHE - if (dc->line_len != L1_CACHE_BYTES) - panic("Cache H/W doesn't match kernel Config"); + dc = &cpuinfo_arc700[cpu].dcache; + if (dc->ver) { + unsigned int dcache_does_alias; - /* check for D-Cache aliasing */ - dcache_does_alias = (dc->sz / dc->assoc) > PAGE_SIZE; + if (dc->line_len != L1_CACHE_BYTES) + panic("DCache line [%d] != kernel Config [%d]", + dc->line_len, L1_CACHE_BYTES); - if (dcache_does_alias && !cache_is_vipt_aliasing()) - panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n"); - else if (!dcache_does_alias && cache_is_vipt_aliasing()) - panic("Don't need CONFIG_ARC_CACHE_VIPT_ALIASING\n"); -#endif - - /* Set the default Invalidate Mode to "simpy discard dirty lines" - * as this is more frequent then flush before invalidate - * Ofcourse we toggle this default behviour when desired - */ - temp = read_aux_reg(ARC_REG_DC_CTRL); - temp &= ~DC_CTRL_INV_MODE_FLUSH; + /* check for D-Cache aliasing */ + dcache_does_alias = (dc->sz / dc->assoc) > PAGE_SIZE; -#ifdef CONFIG_ARC_HAS_DCACHE - /* Enable D-Cache: Clear Bit 0 */ - write_aux_reg(ARC_REG_DC_CTRL, temp & ~IC_CTRL_CACHE_DISABLE); -#else - /* Flush D cache */ - write_aux_reg(ARC_REG_DC_FLSH, 0x1); - /* Disable D cache */ - write_aux_reg(ARC_REG_DC_CTRL, temp | IC_CTRL_CACHE_DISABLE); + if (dcache_does_alias && !cache_is_vipt_aliasing()) + panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n"); + else if (!dcache_does_alias && cache_is_vipt_aliasing()) + panic("Don't need CONFIG_ARC_CACHE_VIPT_ALIASING\n"); + } #endif - - return; } #define OP_INV 0x1 @@ -254,12 +197,16 @@ static inline void __cache_line_loop(unsigned long paddr, unsigned long vaddr, if (cacheop == OP_INV_IC) { aux_cmd = ARC_REG_IC_IVIL; +#if (CONFIG_ARC_MMU_VER > 2) aux_tag = ARC_REG_IC_PTAG; +#endif } else { /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */ aux_cmd = cacheop & OP_INV ? ARC_REG_DC_IVDL : ARC_REG_DC_FLDL; +#if (CONFIG_ARC_MMU_VER > 2) aux_tag = ARC_REG_DC_PTAG; +#endif } /* Ensure we properly floor/ceil the non-line aligned/sized requests @@ -282,7 +229,7 @@ static inline void __cache_line_loop(unsigned long paddr, unsigned long vaddr, #else /* if V-P const for loop, PTAG can be written once outside loop */ if (full_page_op) - write_aux_reg(ARC_REG_DC_PTAG, paddr); + write_aux_reg(aux_tag, paddr); #endif while (num_lines-- > 0) { @@ -296,7 +243,7 @@ static inline void __cache_line_loop(unsigned long paddr, unsigned long vaddr, write_aux_reg(aux_cmd, vaddr); vaddr += L1_CACHE_BYTES; #else - write_aux_reg(aux, paddr); + write_aux_reg(aux_cmd, paddr); paddr += L1_CACHE_BYTES; #endif } @@ -442,7 +389,7 @@ static inline void __dc_line_op(unsigned long paddr, unsigned long vaddr, /*********************************************************** * Machine specific helper for per line I-Cache invalidate. */ -static void __ic_line_inv_vaddr(unsigned long paddr, unsigned long vaddr, +static void __ic_line_inv_vaddr_local(unsigned long paddr, unsigned long vaddr, unsigned long sz) { unsigned long flags; @@ -458,6 +405,23 @@ static inline void __ic_entire_inv(void) read_aux_reg(ARC_REG_IC_CTRL); /* blocks */ } +struct ic_line_inv_vaddr_ipi { + unsigned long paddr, vaddr; + int sz; +}; + +static void __ic_line_inv_vaddr_helper(void *info) +{ + struct ic_line_inv_vaddr_ipi *ic_inv = (struct ic_line_inv_vaddr_ipi*) info; + __ic_line_inv_vaddr_local(ic_inv->paddr, ic_inv->vaddr, ic_inv->sz); +} + +static void __ic_line_inv_vaddr(unsigned long paddr, unsigned long vaddr, + unsigned long sz) +{ + struct ic_line_inv_vaddr_ipi ic_inv = { paddr, vaddr , sz}; + on_each_cpu(__ic_line_inv_vaddr_helper, &ic_inv, 1); +} #else #define __ic_entire_inv() @@ -606,12 +570,8 @@ void flush_icache_range(unsigned long kstart, unsigned long kend) */ void __sync_icache_dcache(unsigned long paddr, unsigned long vaddr, int len) { - unsigned long flags; - - local_irq_save(flags); - __ic_line_inv_vaddr(paddr, vaddr, len); __dc_line_op(paddr, vaddr, len, OP_FLUSH_N_INV); - local_irq_restore(flags); + __ic_line_inv_vaddr(paddr, vaddr, len); } /* wrapper to compile time eliminate alignment checks in flush loop */ diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c index 55e0a85bea78..523412369f70 100644 --- a/arch/arc/mm/init.c +++ b/arch/arc/mm/init.c @@ -10,6 +10,9 @@ #include <linux/mm.h> #include <linux/bootmem.h> #include <linux/memblock.h> +#ifdef CONFIG_BLK_DEV_INITRD +#include <linux/initrd.h> +#endif #include <linux/swap.h> #include <linux/module.h> #include <asm/page.h> @@ -42,6 +45,24 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) pr_info("Memory size set via devicetree %ldM\n", TO_MB(arc_mem_sz)); } +#ifdef CONFIG_BLK_DEV_INITRD +static int __init early_initrd(char *p) +{ + unsigned long start, size; + char *endp; + + start = memparse(p, &endp); + if (*endp == ',') { + size = memparse(endp + 1, NULL); + + initrd_start = (unsigned long)__va(start); + initrd_end = (unsigned long)__va(start + size); + } + return 0; +} +early_param("initrd", early_initrd); +#endif + /* * First memory setup routine called from setup_arch() * 1. setup swapper's mm @init_mm @@ -80,6 +101,12 @@ void __init setup_arch_memory(void) memblock_reserve(CONFIG_LINUX_LINK_BASE, __pa(_end) - CONFIG_LINUX_LINK_BASE); +#ifdef CONFIG_BLK_DEV_INITRD + /*------------- reserve initrd image -----------------------*/ + if (initrd_start) + memblock_reserve(__pa(initrd_start), initrd_end - initrd_start); +#endif + memblock_dump_all(); /*-------------- node setup --------------------------------*/ diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S index 3fcfdb38d242..79bfc81358c9 100644 --- a/arch/arc/mm/tlbex.S +++ b/arch/arc/mm/tlbex.S @@ -260,7 +260,7 @@ ARCFP_CODE ;Fast Path Code, candidate for ICCM ; I-TLB Miss Exception Handler ;----------------------------------------------------------------------------- -ARC_ENTRY EV_TLBMissI +ENTRY(EV_TLBMissI) TLBMISS_FREEUP_REGS @@ -293,13 +293,13 @@ ARC_ENTRY EV_TLBMissI TLBMISS_RESTORE_REGS rtie -ARC_EXIT EV_TLBMissI +END(EV_TLBMissI) ;----------------------------------------------------------------------------- ; D-TLB Miss Exception Handler ;----------------------------------------------------------------------------- -ARC_ENTRY EV_TLBMissD +ENTRY(EV_TLBMissD) TLBMISS_FREEUP_REGS @@ -381,6 +381,4 @@ do_slow_path_pf: bl do_page_fault b ret_from_exception -ARC_EXIT EV_TLBMissD - -ARC_ENTRY EV_TLBMissB ; Bogus entry to measure sz of DTLBMiss hdlr +END(EV_TLBMissD) diff --git a/arch/arc/plat-arcfpga/Kconfig b/arch/arc/plat-arcfpga/Kconfig index 295cefeb25d3..e27bb5cc3c1e 100644 --- a/arch/arc/plat-arcfpga/Kconfig +++ b/arch/arc/plat-arcfpga/Kconfig @@ -33,7 +33,6 @@ config ISS_SMP_EXTN bool "ARC SMP Extensions (ISS Models only)" default n depends on SMP - select ARC_HAS_COH_RTSC help SMP Extensions to ARC700, in a "simulation only" Model, supported in ARC ISS (Instruction Set Simulator). @@ -49,36 +48,4 @@ config ARC_SERIAL_BAUD help Baud rate for the ARC UART -menuconfig ARC_HAS_BVCI_LAT_UNIT - bool "BVCI Bus Latency Unit" - depends on ARC_BOARD_ML509 || ARC_BOARD_ANGEL4 - help - IP to add artificial latency to BVCI Bus Based FPGA builds. - The default latency (even worst case) for FPGA is non-realistic - (~10 SDRAM, ~5 SSRAM). - -config BVCI_LAT_UNITS - hex "Latency Unit(s) Bitmap" - default "0x0" - depends on ARC_HAS_BVCI_LAT_UNIT - help - There are multiple Latency Units corresponding to the many - interfaces of the system bus arbiter (both CPU side as well as - the peripheral side). - To add latency to ALL memory transaction, choose Unit 0, otherwise - for finer grainer - interface wise latency, specify a bitmap (1 bit - per unit) of all units. e.g. 1,2,12 will be 0x1003 - - Unit 0 - System Arb and Mem Controller - Unit 1 - I$ and System Bus - Unit 2 - D$ and System Bus - .. - Unit 12 - IDE Disk controller and System Bus - -config BVCI_LAT_CYCLES - int "Latency Value in cycles" - range 0 63 - default "30" - depends on ARC_HAS_BVCI_LAT_UNIT - endif diff --git a/arch/arc/plat-arcfpga/Makefile b/arch/arc/plat-arcfpga/Makefile index a44e22ebc1b7..4d1bddc34b5b 100644 --- a/arch/arc/plat-arcfpga/Makefile +++ b/arch/arc/plat-arcfpga/Makefile @@ -9,4 +9,4 @@ KBUILD_CFLAGS += -Iarch/arc/plat-arcfpga/include obj-y := platform.o irq.o -obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_ISS_SMP_EXTN) += smp.o diff --git a/arch/arc/plat-arcfpga/platform.c b/arch/arc/plat-arcfpga/platform.c index d71f3c3bcf24..61c7e5997387 100644 --- a/arch/arc/plat-arcfpga/platform.c +++ b/arch/arc/plat-arcfpga/platform.c @@ -22,59 +22,6 @@ #include <plat/smp.h> #include <plat/irq.h> -/*-----------------------BVCI Latency Unit -----------------------------*/ - -#ifdef CONFIG_ARC_HAS_BVCI_LAT_UNIT - -int lat_cycles = CONFIG_BVCI_LAT_CYCLES; - -/* BVCI Bus Profiler: Latency Unit */ -static void __init setup_bvci_lat_unit(void) -{ -#define MAX_BVCI_UNITS 12 - - unsigned int i; - unsigned int *base = (unsigned int *)BVCI_LAT_UNIT_BASE; - const unsigned long units_req = CONFIG_BVCI_LAT_UNITS; - const unsigned int REG_UNIT = 21; - const unsigned int REG_VAL = 22; - - /* - * There are multiple Latency Units corresponding to the many - * interfaces of the system bus arbiter (both CPU side as well as - * the peripheral side). - * - * Unit 0 - System Arb and Mem Controller - adds latency to all - * memory trasactions - * Unit 1 - I$ and System Bus - * Unit 2 - D$ and System Bus - * .. - * Unit 12 - IDE Disk controller and System Bus - * - * The programmers model requires writing to lat_unit reg first - * and then the latency value (cycles) to lat_value reg - */ - - if (CONFIG_BVCI_LAT_UNITS == 0) { - writel(0, base + REG_UNIT); - writel(lat_cycles, base + REG_VAL); - pr_info("BVCI Latency for all Memory Transactions %d cycles\n", - lat_cycles); - } else { - for_each_set_bit(i, &units_req, MAX_BVCI_UNITS) { - writel(i + 1, base + REG_UNIT); /* loop is 0 based */ - writel(lat_cycles, base + REG_VAL); - pr_info("BVCI Latency for Unit[%d] = %d cycles\n", - (i + 1), lat_cycles); - } - } -} -#else -static void __init setup_bvci_lat_unit(void) -{ -} -#endif - /*----------------------- Platform Devices -----------------------------*/ #if IS_ENABLED(CONFIG_SERIAL_ARC) @@ -132,16 +79,11 @@ static void arc_fpga_serial_init(void) ARRAY_SIZE(fpga_early_devs)); /* - * ARC console driver registers itself as an early platform driver - * of class "earlyprintk". - * Install it here, followed by probe of devices. - * The installation here doesn't require earlyprintk in command line - * To do so however, replace the lines below with - * parse_early_param(); - * early_platform_driver_probe("earlyprintk", 1, 1); - * ^^ + * ARC console driver registers (build time) as an early platform driver + * of class "earlyprintk". However it needs explicit cmdline toggle + * "earlyprintk=ttyARC0" to be successfuly runtime registered. + * Otherwise the early probe below fails to find the driver */ - early_platform_driver_register_all("earlyprintk"); early_platform_driver_probe("earlyprintk", 1, 0); /* @@ -165,11 +107,9 @@ static void __init plat_fpga_early_init(void) { pr_info("[plat-arcfpga]: registering early dev resources\n"); - setup_bvci_lat_unit(); - arc_fpga_serial_init(); -#ifdef CONFIG_SMP +#ifdef CONFIG_ISS_SMP_EXTN iss_model_init_early_smp(); #endif } @@ -201,7 +141,7 @@ static void __init plat_fpga_populate_dev(void) * callback set, by matching the DT compatible name. */ -static const char *aa4_compat[] __initdata = { +static const char *aa4_compat[] __initconst = { "snps,arc-angel4", NULL, }; @@ -211,12 +151,12 @@ MACHINE_START(ANGEL4, "angel4") .init_early = plat_fpga_early_init, .init_machine = plat_fpga_populate_dev, .init_irq = plat_fpga_init_IRQ, -#ifdef CONFIG_SMP +#ifdef CONFIG_ISS_SMP_EXTN .init_smp = iss_model_init_smp, #endif MACHINE_END -static const char *ml509_compat[] __initdata = { +static const char *ml509_compat[] __initconst = { "snps,arc-ml509", NULL, }; @@ -231,7 +171,7 @@ MACHINE_START(ML509, "ml509") #endif MACHINE_END -static const char *nsimosci_compat[] __initdata = { +static const char *nsimosci_compat[] __initconst = { "snps,nsimosci", NULL, }; diff --git a/arch/arc/plat-arcfpga/smp.c b/arch/arc/plat-arcfpga/smp.c index 91b55349a5f8..92bad9122077 100644 --- a/arch/arc/plat-arcfpga/smp.c +++ b/arch/arc/plat-arcfpga/smp.c @@ -42,6 +42,24 @@ static void iss_model_smp_wakeup_cpu(int cpu, unsigned long pc) } +static inline int get_hw_config_num_irq(void) +{ + uint32_t val = read_aux_reg(ARC_REG_VECBASE_BCR); + + switch (val & 0x03) { + case 0: + return 16; + case 1: + return 32; + case 2: + return 8; + default: + return 0; + } + + return 0; +} + /* * Any SMP specific init any CPU does when it comes up. * Here we setup the CPU to enable Inter-Processor-Interrupts @@ -88,18 +106,14 @@ void iss_model_init_smp(unsigned int cpu) smp_ipi_irq_setup(cpu, IDU_INTERRUPT_0 + cpu); } -static void iss_model_ipi_send(void *arg) +static void iss_model_ipi_send(int cpu) { - struct cpumask *callmap = arg; - unsigned int cpu; - - for_each_cpu(cpu, callmap) - idu_irq_assert(cpu); + idu_irq_assert(cpu); } -static void iss_model_ipi_clear(int cpu, int irq) +static void iss_model_ipi_clear(int irq) { - idu_irq_clear(IDU_INTERRUPT_0 + cpu); + idu_irq_clear(IDU_INTERRUPT_0 + smp_processor_id()); } void iss_model_init_early_smp(void) |