linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1)
@ 2013-01-24 10:50 Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 01/71] ARC: Generic Headers Vineet Gupta
                   ` (25 more replies)
  0 siblings, 26 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta

This patchset based off-of 3.8-rc4, adds the Linux kernel port to ARC700
processor family (750D and 770D) from Synopsys. I would be greatful for
further review and feedback.

Salient points about v3 patchset
-------------------------------
* All of the feedback from v2 patchseries has been addressed.
* series sent in 2 parts, with other part containing patches not touched
  since v2.

About ARC Cores
----------------
ARC700 is highly configurable and power efficient 32-bit RISC core with MMU.
It is embedded in SoCs deployed in TV Set Top boxes, Digital Media Players,
all the way to Network-on-Chips.

More information is available @
 http://www.synopsys.com/IP/ProcessorIP/ARCProcessors/Pages/default.aspx

The GNU tool-chain, based off of gcc 4.4  + uClibc 0.9.30.3 is also available
from github. Please refer to Readme.md in "toolchain" repository also in same
hierarchy as kernel above.

---
v3:
=========================================================================

Review comments (with #<xx> patch in series addressing them)

#01 * Kbuild trace_clock.h inclusion - [split aggregate 3.8 patch]
#02 * Build system patch moved towards start of series
#02 * Dropped line continuation from Makefiles, Removed conditional HOTPLUG (Sam)
#02 * Removed empty vmlinux.lds.h (Sam)
#11 * _TIF_WORK_MASK needs to use the exact bits needed (Al Viro)
#17 * squashed generic clone patch into syscall patch (Al Viro)
#17 * split/squashed sys_execve removal bits into syscall patch (Al Viro)
#18 * split/squashed kernel_execve bits into process creation patch (Al Viro)
#18 * squashed switch-to-saner-execve into process creation patch (Al Viro)
#18 * squashed switch-to-generic-kernel-thread patch into process creation patch
#18 * cpu_idle() - fix a race between need_resched and sleep (Arnd)
#20 * task_pt_regs(current) => current_pt_regs()  (Al Viro)
#20 * altstack changes [split aggregate 3.8 patch] into signal handling (Al Viro)
#29 * include asm/cacheflush.h in io.h [split aggregate 3.8 patch]
#29 * Implemented __raw_{read,write}{b,w,l} for ARC with inline asm (Arnd)
#29 * early ioremap requiring MMU needs to bail out
#30 * switched from bootmem to memblock (Arnd)
#32 * dtb folder folded into dts to be consistent with other arches (Rob)
#32 * Using generic dtb build rule (Rob)
#33 * skeleton.dtsi no longer contains board references (Rob)
#34 * default DT is a board specific file (angel4) and not skeleton (Rob)
#42 * module helpers only defined when module unwinder really needs them (Arnd)
#44 * Removed CONFIG_ARC_HAS_IPI glue to enable SMP across platforms (Arnd)
#57 * hostlink driver converted/simplified using misc_register (Arnd)
#58 * UAPI - added a placeholder comment to empty setup.h (David)
#62 * struct machine_desc - arrange the callbacks in order of their call (Arnd)

Bug fixes (since v2)

#02 * ARC_SERIAL_BAUD depends on SERIAL_ARC_CONSOLE as well
#18 * RTSC fix in big-endian configuration (Noam Camus)
#21 * in_syscall() broken because checking of pt_regs->orig_r8 vs. pt_regs->event
#21 * syscall restarting infrastructure Big Endian safe
#22 * syscall restarting broken because not checking pt_regs->event
#23 * Changelog typo
#34 * cleanup static platform device for early arc-uart
#44 * Added CPU active notifier to secondary boot
#69 * Update defconfig for tmpfs, ext2, ....
    * make allyesconfig fixes
#06   * Missing ; in EXPORT_SYMBOL() in extable.c
#29   * Missing dma_sync_single_range_for_{cpu,device}
#29   * Missing dma_mmap_coherent/dma_get_sgtable
#48   * Missing regs_return_value() in ptrace.h for kprobes self-test
#70   * missing serial.h


v2:
=========================================================================
Changes for RFC v1 review:

* Reworked arc_local_irq_enable() with WARN_ONCE for buggy drivers (tglx)
* struct pt_regs wrapped under #ifdef __KERNEL__ (Jonas)
* returning to user mode (Al Viro)
  * re-enable interrupts before handling TIF_SIGPENDING/TIF_NOTIFY_RESUME
  * Don't discard callee-regs after handling signal
  * After TIF_NOTIFY_RESUME processing, loop back to start of TIF_* checks
* Reworked init_IRQ() to not use irq_modify_status() at all (tglx)
* Removed legacy syscalls (Arnd)
* cpu_idle to use schedule_preempt_disabled API (tglx)
* clocksource/clockevent code renamed/reworked (tglx)
* Removed possible live-lock in sched_clock() (tglx)
* Ensured that syscalls are not restarted multiple times (Al Viro)
* Support for DeviceTree based dynamic platform device registration (Arnd)
* clock-speed / mem-size extracted from Device Tree (Arnd)
* multi-platform-image - Non-exclusive platform selection in build (Arnd)
* multi-platform-image - Non-exclusive boards selection in build (Arnd)
* Fix the issue in switch to generic_execve (Al Viro)
* defconfigs need to be created using savedefconfig (Arnd)
* Remove support for legacy ptrace POKEUSR/PEEKUSR ABI (Arnd)
* module stubs need not be defined in Arch code (Arnd)
* Low Level Event Capture completely taken out (Arnd)
* Unaligned access runtime controlled using 2 sysctl knobs (Arnd)
* using io accessors for programming BVCI Latency Unit (Arnd)

Other fixes:

* 3.7 -> 3.8 upstream changes
  * Rebased off of 3.8-rc4
  * UAPI Disintegration using scripts provided David Howells
  * Generic clone/fork/vfork
  * switch to saner kernel_execve semantics (GENERIC_KERNEL_EXECVE)
  * Altstack consolidation tracking changes
  * trace_clock.h introduction, cacheflush.h inclusion removal from io.h
* bitops
  * test_and_clear_bit() was SETing the bit instead of CLEARing
  * test_and_*_bit() workaround a gas bug where a bitpos > 31 is not reported
    by doing __builtin_constant_p() check early
* uaccess
  * Added support for non-inline copy_{to,from}_user() for -Os
  * Optimised {get,put}_user() by overriding asm-generic versions
* Timers
  * split Process scheduling/Timers patch into two.
  * Add support for 64bit timestamp counter using RTSC instruction.
* Others
  * Move the incore intc chip handler out of platform code into common code
  * cpu_ide() to use the rcu_idle_* calls


patchset history
-----------------
[v2]	: https://lkml.org/lkml/2013/1/18/182

[RFC v1]: https://lkml.org/lkml/2012/11/7/114
          https://lkml.org/lkml/2012/11/12/121

Gilad Ben-Yossef (1):
  ARC: Add support for ioremap_prot API

Mischa Jonker (1):
  ARC: kgdb support

Vineet Gupta (69):
  ARC: Generic Headers
  ARC: Build system: Makefiles, Kconfig, Linker script
  ARC: irqflags - Interrupt enabling/disabling at in-core intc
  ARC: Atomic/bitops/cmpxchg/barriers
  asm-generic headers: uaccess.h to conditionally define segment_eq()
  ARC: uaccess friends
  asm-generic: uaccess: Allow arches to over-ride __{get,put}_user_fn()
  ARC: [optim] uaccess __{get,put}_user() optimised
  asm-generic headers: Allow yet more arch overrides in checksum.h
  ARC: Checksum/byteorder/swab routines
  ARC: Fundamental ARCH data-types/defines
  ARC: Spinlock/rwlock/mutex primitives
  ARC: String library
  ARC: Low level IRQ/Trap/Exception Handling
  ARC: Interrupt Handling
  ARC: Non-MMU Exception Handling
  ARC: Syscall support (no-legacy-syscall ABI)
  ARC: Process-creation/scheduling/idle-loop
  ARC: Timers/counters/delay management
  ARC: Signal handling
  ARC: [Review] Preparing to fix incorrect syscall restarts due to
    signals
  ARC: [Review] Prevent incorrect syscall restarts
  ARC: Cache Flush Management
  ARC: Page Table Management
  ARC: MMU Context Management
  ARC: MMU Exception Handling
  ARC: TLB flush Handling
  ARC: Page Fault handling
  ARC: I/O and DMA Mappings
  ARC: Boot #1: low-level, setup_arch(), /proc/cpuinfo, mem init
  ARC: [plat-arcfpga] Static platform device for CONFIG_SERIAL_ARC
  ARC: [DeviceTree] Basic support
  ARC: [DeviceTree] Convert some Kconfig items to runtime values
  ARC: [plat-arcfpga]: Enabling DeviceTree for Angel4 board
  ARC: Last bits (stubs) to get to a running kernel with UART
  ARC: [plat-arcfpga] defconfig
  ARC: [optim] Cache "current" in Register r25
  ARC: ptrace support
  ARC: Futex support
  ARC: OProfile support
  ARC: Support for high priority interrupts in the in-core intc
  ARC: Module support
  ARC: Diagnostics: show_regs() etc
  ARC: SMP support
  ARC: DWARF2 .debug_frame based stack unwinder
  ARC: stacktracing APIs based on dw2 unwinder
  ARC: disassembly (needed by kprobes/kgdb/unaligned-access-emul)
  ARC: kprobes support
  sysctl: Enable PARISC "unaligned-trap" to be used cross-arch
  ARC: Unaligned access emulation
  ARC: Boot #2: Verbose Boot reporting / feature verification
  ARC: [plat-arfpga] BVCI Latency Unit setup
  perf, ARC: Enable building perf tools for ARC
  ARC: perf support (software counters only)
  ARC: Support for single cycle Close Coupled Mem (CCM)
  ARC: Hostlink Pseudo-Driver for Metaware Debugger
  ARC: UAPI Disintegrate arch/arc/include/asm
  ARC: [Review] Multi-platform image #1: Kconfig enablement
  ARC: Fold boards sub-menu into platform/SoC menu
  ARC: [Review] Multi-platform image #2: Board callback Infrastructure
  ARC: [Review] Multi-platform image #3: switch to board callback
  ARC: [Review] Multi-platform image #4: Isolate platform headers
  ARC: [Review] Multi-platform image #5: NR_IRQS defined by ARC core
  ARC: [Review] Multi-platform image #6: cpu-to-dma-addr optional
  ARC: [Review] Multi-platform image #7: SMP common code to use
    callbacks
  ARC: [Review] Multi-platform image #8: platform registers SMP
    callbacks
  ARC: [plat-arcfpga] defconfig for fully loaded ARC Linux
  ARC: Provide a default serial.h for uart drivers needing BASE_BAUD
  ARC: Add self to MAINTAINERS

 .../devicetree/bindings/arc/interrupts.txt         |   24 +
 MAINTAINERS                                        |    6 +
 arch/arc/Kbuild                                    |    2 +
 arch/arc/Kconfig                                   |  456 +++++++
 arch/arc/Kconfig.debug                             |   34 +
 arch/arc/Makefile                                  |  126 ++
 arch/arc/boot/Makefile                             |   26 +
 arch/arc/boot/dts/Makefile                         |   14 +
 arch/arc/boot/dts/angel4.dts                       |   55 +
 arch/arc/boot/dts/skeleton.dts                     |   10 +
 arch/arc/boot/dts/skeleton.dtsi                    |   37 +
 arch/arc/configs/fpga_defconfig                    |   61 +
 arch/arc/include/asm/Kbuild                        |   49 +
 arch/arc/include/asm/arcregs.h                     |  433 +++++++
 arch/arc/include/asm/asm-offsets.h                 |    9 +
 arch/arc/include/asm/atomic.h                      |  232 ++++
 arch/arc/include/asm/barrier.h                     |   42 +
 arch/arc/include/asm/bitops.h                      |  516 ++++++++
 arch/arc/include/asm/bug.h                         |   37 +
 arch/arc/include/asm/cache.h                       |   75 ++
 arch/arc/include/asm/cacheflush.h                  |   67 +
 arch/arc/include/asm/checksum.h                    |  101 ++
 arch/arc/include/asm/clk.h                         |   22 +
 arch/arc/include/asm/cmpxchg.h                     |  143 +++
 arch/arc/include/asm/current.h                     |   32 +
 arch/arc/include/asm/defines.h                     |   56 +
 arch/arc/include/asm/delay.h                       |   68 +
 arch/arc/include/asm/disasm.h                      |  116 ++
 arch/arc/include/asm/dma-mapping.h                 |  221 ++++
 arch/arc/include/asm/dma.h                         |   14 +
 arch/arc/include/asm/elf.h                         |   97 ++
 arch/arc/include/asm/entry.h                       |  724 +++++++++++
 arch/arc/include/asm/exec.h                        |   15 +
 arch/arc/include/asm/futex.h                       |  151 +++
 arch/arc/include/asm/io.h                          |  105 ++
 arch/arc/include/asm/irq.h                         |   25 +
 arch/arc/include/asm/irqflags.h                    |  153 +++
 arch/arc/include/asm/kdebug.h                      |   19 +
 arch/arc/include/asm/kgdb.h                        |   61 +
 arch/arc/include/asm/kprobes.h                     |   62 +
 arch/arc/include/asm/linkage.h                     |   63 +
 arch/arc/include/asm/mach_desc.h                   |   85 ++
 arch/arc/include/asm/mmu.h                         |   23 +
 arch/arc/include/asm/mmu_context.h                 |  213 ++++
 arch/arc/include/asm/module.h                      |   28 +
 arch/arc/include/asm/mutex.h                       |   18 +
 arch/arc/include/asm/page.h                        |  109 ++
 arch/arc/include/asm/perf_event.h                  |   13 +
 arch/arc/include/asm/pgalloc.h                     |  134 ++
 arch/arc/include/asm/pgtable.h                     |  405 ++++++
 arch/arc/include/asm/processor.h                   |  151 +++
 arch/arc/include/asm/prom.h                        |   14 +
 arch/arc/include/asm/ptrace.h                      |  135 ++
 arch/arc/include/asm/sections.h                    |   18 +
 arch/arc/include/asm/segment.h                     |   24 +
 arch/arc/include/asm/serial.h                      |   25 +
 arch/arc/include/asm/setup.h                       |   37 +
 arch/arc/include/asm/smp.h                         |  130 ++
 arch/arc/include/asm/spinlock.h                    |  144 +++
 arch/arc/include/asm/spinlock_types.h              |   35 +
 arch/arc/include/asm/string.h                      |   40 +
 arch/arc/include/asm/switch_to.h                   |   41 +
 arch/arc/include/asm/syscall.h                     |   72 ++
 arch/arc/include/asm/syscalls.h                    |   29 +
 arch/arc/include/asm/thread_info.h                 |  121 ++
 arch/arc/include/asm/timex.h                       |   18 +
 arch/arc/include/asm/tlb-mmu1.h                    |  104 ++
 arch/arc/include/asm/tlb.h                         |   58 +
 arch/arc/include/asm/tlbflush.h                    |   28 +
 arch/arc/include/asm/uaccess.h                     |  751 +++++++++++
 arch/arc/include/asm/unaligned.h                   |   29 +
 arch/arc/include/asm/unwind.h                      |  163 +++
 arch/arc/include/uapi/asm/Kbuild                   |   11 +
 arch/arc/include/uapi/asm/byteorder.h              |   18 +
 arch/arc/include/uapi/asm/cachectl.h               |   28 +
 arch/arc/include/uapi/asm/page.h                   |   39 +
 arch/arc/include/uapi/asm/ptrace.h                 |   46 +
 arch/arc/include/uapi/asm/setup.h                  |    6 +
 arch/arc/include/uapi/asm/sigcontext.h             |   23 +
 arch/arc/include/uapi/asm/signal.h                 |   27 +
 arch/arc/include/uapi/asm/swab.h                   |   98 ++
 arch/arc/include/uapi/asm/unistd.h                 |   34 +
 arch/arc/kernel/Makefile                           |   33 +
 arch/arc/kernel/arc_hostlink.c                     |   58 +
 arch/arc/kernel/arcksyms.c                         |   56 +
 arch/arc/kernel/asm-offsets.c                      |   49 +
 arch/arc/kernel/clk.c                              |   21 +
 arch/arc/kernel/ctx_sw.c                           |  109 ++
 arch/arc/kernel/ctx_sw_asm.S                       |   58 +
 arch/arc/kernel/devtree.c                          |  113 ++
 arch/arc/kernel/disasm.c                           |  538 ++++++++
 arch/arc/kernel/entry.S                            |  839 ++++++++++++
 arch/arc/kernel/fpu.c                              |   55 +
 arch/arc/kernel/head.S                             |  111 ++
 arch/arc/kernel/irq.c                              |  273 ++++
 arch/arc/kernel/kgdb.c                             |  205 +++
 arch/arc/kernel/kprobes.c                          |  525 ++++++++
 arch/arc/kernel/module.c                           |  145 +++
 arch/arc/kernel/process.c                          |  235 ++++
 arch/arc/kernel/ptrace.c                           |  158 +++
 arch/arc/kernel/reset.c                            |   33 +
 arch/arc/kernel/setup.c                            |  471 +++++++
 arch/arc/kernel/signal.c                           |  363 ++++++
 arch/arc/kernel/smp.c                              |  332 +++++
 arch/arc/kernel/stacktrace.c                       |  254 ++++
 arch/arc/kernel/sys.c                              |   18 +
 arch/arc/kernel/time.c                             |  299 +++++
 arch/arc/kernel/traps.c                            |  170 +++
 arch/arc/kernel/troubleshoot.c                     |  322 +++++
 arch/arc/kernel/unaligned.c                        |  245 ++++
 arch/arc/kernel/unwind.c                           | 1329 ++++++++++++++++++++
 arch/arc/kernel/vmlinux.lds.S                      |  163 +++
 arch/arc/lib/Makefile                              |    9 +
 arch/arc/lib/memcmp.S                              |  124 ++
 arch/arc/lib/memcpy-700.S                          |   66 +
 arch/arc/lib/memset.S                              |   59 +
 arch/arc/lib/strchr-700.S                          |  123 ++
 arch/arc/lib/strcmp.S                              |   96 ++
 arch/arc/lib/strcpy-700.S                          |   70 +
 arch/arc/lib/strlen.S                              |   83 ++
 arch/arc/mm/Makefile                               |   10 +
 arch/arc/mm/cache_arc700.c                         |  771 ++++++++++++
 arch/arc/mm/dma.c                                  |   94 ++
 arch/arc/mm/extable.c                              |   63 +
 arch/arc/mm/fault.c                                |  228 ++++
 arch/arc/mm/init.c                                 |  187 +++
 arch/arc/mm/ioremap.c                              |   91 ++
 arch/arc/mm/tlb.c                                  |  645 ++++++++++
 arch/arc/mm/tlbex.S                                |  408 ++++++
 arch/arc/oprofile/Makefile                         |    9 +
 arch/arc/oprofile/common.c                         |   22 +
 arch/arc/plat-arcfpga/Kconfig                      |   84 ++
 arch/arc/plat-arcfpga/Makefile                     |   12 +
 arch/arc/plat-arcfpga/include/plat/irq.h           |   31 +
 arch/arc/plat-arcfpga/include/plat/memmap.h        |   31 +
 arch/arc/plat-arcfpga/include/plat/smp.h           |  118 ++
 arch/arc/plat-arcfpga/irq.c                        |   25 +
 arch/arc/plat-arcfpga/platform.c                   |  226 ++++
 arch/arc/plat-arcfpga/smp.c                        |  171 +++
 arch/parisc/Kconfig                                |    1 +
 include/asm-generic/checksum.h                     |    4 +
 include/asm-generic/uaccess.h                      |   14 +-
 init/Kconfig                                       |    8 +
 kernel/sysctl.c                                    |    5 +
 lib/checksum.c                                     |    2 +
 tools/perf/perf.h                                  |    6 +
 146 files changed, 19559 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arc/interrupts.txt
 create mode 100644 arch/arc/Kbuild
 create mode 100644 arch/arc/Kconfig
 create mode 100644 arch/arc/Kconfig.debug
 create mode 100644 arch/arc/Makefile
 create mode 100644 arch/arc/boot/Makefile
 create mode 100644 arch/arc/boot/dts/Makefile
 create mode 100644 arch/arc/boot/dts/angel4.dts
 create mode 100644 arch/arc/boot/dts/skeleton.dts
 create mode 100644 arch/arc/boot/dts/skeleton.dtsi
 create mode 100644 arch/arc/configs/fpga_defconfig
 create mode 100644 arch/arc/include/asm/Kbuild
 create mode 100644 arch/arc/include/asm/arcregs.h
 create mode 100644 arch/arc/include/asm/asm-offsets.h
 create mode 100644 arch/arc/include/asm/atomic.h
 create mode 100644 arch/arc/include/asm/barrier.h
 create mode 100644 arch/arc/include/asm/bitops.h
 create mode 100644 arch/arc/include/asm/bug.h
 create mode 100644 arch/arc/include/asm/cache.h
 create mode 100644 arch/arc/include/asm/cacheflush.h
 create mode 100644 arch/arc/include/asm/checksum.h
 create mode 100644 arch/arc/include/asm/clk.h
 create mode 100644 arch/arc/include/asm/cmpxchg.h
 create mode 100644 arch/arc/include/asm/current.h
 create mode 100644 arch/arc/include/asm/defines.h
 create mode 100644 arch/arc/include/asm/delay.h
 create mode 100644 arch/arc/include/asm/disasm.h
 create mode 100644 arch/arc/include/asm/dma-mapping.h
 create mode 100644 arch/arc/include/asm/dma.h
 create mode 100644 arch/arc/include/asm/elf.h
 create mode 100644 arch/arc/include/asm/entry.h
 create mode 100644 arch/arc/include/asm/exec.h
 create mode 100644 arch/arc/include/asm/futex.h
 create mode 100644 arch/arc/include/asm/io.h
 create mode 100644 arch/arc/include/asm/irq.h
 create mode 100644 arch/arc/include/asm/irqflags.h
 create mode 100644 arch/arc/include/asm/kdebug.h
 create mode 100644 arch/arc/include/asm/kgdb.h
 create mode 100644 arch/arc/include/asm/kprobes.h
 create mode 100644 arch/arc/include/asm/linkage.h
 create mode 100644 arch/arc/include/asm/mach_desc.h
 create mode 100644 arch/arc/include/asm/mmu.h
 create mode 100644 arch/arc/include/asm/mmu_context.h
 create mode 100644 arch/arc/include/asm/module.h
 create mode 100644 arch/arc/include/asm/mutex.h
 create mode 100644 arch/arc/include/asm/page.h
 create mode 100644 arch/arc/include/asm/perf_event.h
 create mode 100644 arch/arc/include/asm/pgalloc.h
 create mode 100644 arch/arc/include/asm/pgtable.h
 create mode 100644 arch/arc/include/asm/processor.h
 create mode 100644 arch/arc/include/asm/prom.h
 create mode 100644 arch/arc/include/asm/ptrace.h
 create mode 100644 arch/arc/include/asm/sections.h
 create mode 100644 arch/arc/include/asm/segment.h
 create mode 100644 arch/arc/include/asm/serial.h
 create mode 100644 arch/arc/include/asm/setup.h
 create mode 100644 arch/arc/include/asm/smp.h
 create mode 100644 arch/arc/include/asm/spinlock.h
 create mode 100644 arch/arc/include/asm/spinlock_types.h
 create mode 100644 arch/arc/include/asm/string.h
 create mode 100644 arch/arc/include/asm/switch_to.h
 create mode 100644 arch/arc/include/asm/syscall.h
 create mode 100644 arch/arc/include/asm/syscalls.h
 create mode 100644 arch/arc/include/asm/thread_info.h
 create mode 100644 arch/arc/include/asm/timex.h
 create mode 100644 arch/arc/include/asm/tlb-mmu1.h
 create mode 100644 arch/arc/include/asm/tlb.h
 create mode 100644 arch/arc/include/asm/tlbflush.h
 create mode 100644 arch/arc/include/asm/uaccess.h
 create mode 100644 arch/arc/include/asm/unaligned.h
 create mode 100644 arch/arc/include/asm/unwind.h
 create mode 100644 arch/arc/include/uapi/asm/Kbuild
 create mode 100644 arch/arc/include/uapi/asm/byteorder.h
 create mode 100644 arch/arc/include/uapi/asm/cachectl.h
 create mode 100644 arch/arc/include/uapi/asm/page.h
 create mode 100644 arch/arc/include/uapi/asm/ptrace.h
 create mode 100644 arch/arc/include/uapi/asm/setup.h
 create mode 100644 arch/arc/include/uapi/asm/sigcontext.h
 create mode 100644 arch/arc/include/uapi/asm/signal.h
 create mode 100644 arch/arc/include/uapi/asm/swab.h
 create mode 100644 arch/arc/include/uapi/asm/unistd.h
 create mode 100644 arch/arc/kernel/Makefile
 create mode 100644 arch/arc/kernel/arc_hostlink.c
 create mode 100644 arch/arc/kernel/arcksyms.c
 create mode 100644 arch/arc/kernel/asm-offsets.c
 create mode 100644 arch/arc/kernel/clk.c
 create mode 100644 arch/arc/kernel/ctx_sw.c
 create mode 100644 arch/arc/kernel/ctx_sw_asm.S
 create mode 100644 arch/arc/kernel/devtree.c
 create mode 100644 arch/arc/kernel/disasm.c
 create mode 100644 arch/arc/kernel/entry.S
 create mode 100644 arch/arc/kernel/fpu.c
 create mode 100644 arch/arc/kernel/head.S
 create mode 100644 arch/arc/kernel/irq.c
 create mode 100644 arch/arc/kernel/kgdb.c
 create mode 100644 arch/arc/kernel/kprobes.c
 create mode 100644 arch/arc/kernel/module.c
 create mode 100644 arch/arc/kernel/process.c
 create mode 100644 arch/arc/kernel/ptrace.c
 create mode 100644 arch/arc/kernel/reset.c
 create mode 100644 arch/arc/kernel/setup.c
 create mode 100644 arch/arc/kernel/signal.c
 create mode 100644 arch/arc/kernel/smp.c
 create mode 100644 arch/arc/kernel/stacktrace.c
 create mode 100644 arch/arc/kernel/sys.c
 create mode 100644 arch/arc/kernel/time.c
 create mode 100644 arch/arc/kernel/traps.c
 create mode 100644 arch/arc/kernel/troubleshoot.c
 create mode 100644 arch/arc/kernel/unaligned.c
 create mode 100644 arch/arc/kernel/unwind.c
 create mode 100644 arch/arc/kernel/vmlinux.lds.S
 create mode 100644 arch/arc/lib/Makefile
 create mode 100644 arch/arc/lib/memcmp.S
 create mode 100644 arch/arc/lib/memcpy-700.S
 create mode 100644 arch/arc/lib/memset.S
 create mode 100644 arch/arc/lib/strchr-700.S
 create mode 100644 arch/arc/lib/strcmp.S
 create mode 100644 arch/arc/lib/strcpy-700.S
 create mode 100644 arch/arc/lib/strlen.S
 create mode 100644 arch/arc/mm/Makefile
 create mode 100644 arch/arc/mm/cache_arc700.c
 create mode 100644 arch/arc/mm/dma.c
 create mode 100644 arch/arc/mm/extable.c
 create mode 100644 arch/arc/mm/fault.c
 create mode 100644 arch/arc/mm/init.c
 create mode 100644 arch/arc/mm/ioremap.c
 create mode 100644 arch/arc/mm/tlb.c
 create mode 100644 arch/arc/mm/tlbex.S
 create mode 100644 arch/arc/oprofile/Makefile
 create mode 100644 arch/arc/oprofile/common.c
 create mode 100644 arch/arc/plat-arcfpga/Kconfig
 create mode 100644 arch/arc/plat-arcfpga/Makefile
 create mode 100644 arch/arc/plat-arcfpga/include/plat/irq.h
 create mode 100644 arch/arc/plat-arcfpga/include/plat/memmap.h
 create mode 100644 arch/arc/plat-arcfpga/include/plat/smp.h
 create mode 100644 arch/arc/plat-arcfpga/irq.c
 create mode 100644 arch/arc/plat-arcfpga/platform.c
 create mode 100644 arch/arc/plat-arcfpga/smp.c

-- 
1.7.4.1


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [PATCH v3 01/71] ARC: Generic Headers
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 02/71] ARC: Build system: Makefiles, Kconfig, Linker script Vineet Gupta
                   ` (24 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/include/asm/Kbuild        |   58 ++++++++++++++++++++++++++++++++++++
 arch/arc/include/asm/asm-offsets.h |    9 +++++
 2 files changed, 67 insertions(+), 0 deletions(-)
 create mode 100644 arch/arc/include/asm/Kbuild
 create mode 100644 arch/arc/include/asm/asm-offsets.h

diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
new file mode 100644
index 0000000..a90a3c6
--- /dev/null
+++ b/arch/arc/include/asm/Kbuild
@@ -0,0 +1,58 @@
+include include/asm-generic/Kbuild.asm
+
+# 7-Oct-12: Jeremy Bennett <jeremy.bennett@embecosm.com>. Some of these
+# headers, beyond those specified in the generic set are needed by user code.
+
+header-y += page.h
+header-y += cachectl.h
+
+generic-y += auxvec.h
+generic-y += bugs.h
+generic-y += bitsperlong.h
+generic-y += clkdev.h
+generic-y += cputime.h
+generic-y += current.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 += ftrace.h
+generic-y += hardirq.h
+generic-y += hw_irq.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += ipcbuf.h
+generic-y += irq_regs.h
+generic-y += kmap_types.h
+generic-y += kvm_para.h
+generic-y += local.h
+generic-y += local64.h
+generic-y += mman.h
+generic-y += msgbuf.h
+generic-y += param.h
+generic-y += parport.h
+generic-y += percpu.h
+generic-y += poll.h
+generic-y += posix_types.h
+generic-y += resource.h
+generic-y += scatterlist.h
+generic-y += sembuf.h
+generic-y += shmbuf.h
+generic-y += shmparam.h
+generic-y += siginfo.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += stat.h
+generic-y += statfs.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += topology.h
+generic-y += trace_clock.h
+generic-y += types.h
+generic-y += ucontext.h
+generic-y += unaligned.h
+generic-y += user.h
+generic-y += vga.h
+generic-y += xor.h
diff --git a/arch/arc/include/asm/asm-offsets.h b/arch/arc/include/asm/asm-offsets.h
new file mode 100644
index 0000000..dad1876
--- /dev/null
+++ b/arch/arc/include/asm/asm-offsets.h
@@ -0,0 +1,9 @@
+/*
+ * 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.
+ */
+
+#include <generated/asm-offsets.h>
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 02/71] ARC: Build system: Makefiles, Kconfig, Linker script
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 01/71] ARC: Generic Headers Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-28  6:29   ` Vineet Gupta
  2013-02-11 11:29   ` James Hogan
  2013-01-24 10:50 ` [PATCH v3 06/71] ARC: uaccess friends Vineet Gupta
                   ` (23 subsequent siblings)
  25 siblings, 2 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta, Sam Ravnborg

Arnd in his review pointed out that arch Kconfig organisation has several
deficiencies:

* Build time entries for things which can be runtime extracted from DT
  (e.g. SDRAM size, core clk frequency..)
* Not multi-platform-image-build friendly (choice .. endchoice constructs)
* cpu variants support (750/770) is exclusive.

The first 2 have been fixed in subsequent patches.
Due to the nature of the 750 and 770, it is not possible to build for
both together, w/o special runtime glue code which would hurt
performance.

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Sam Ravnborg <sam@ravnborg.org>
---
 arch/arc/Kbuild                |    2 +
 arch/arc/Kconfig               |  328 ++++++++++++++++++++++++++++++++++++++++
 arch/arc/Kconfig.debug         |   34 ++++
 arch/arc/Makefile              |  115 ++++++++++++++
 arch/arc/boot/Makefile         |   26 +++
 arch/arc/include/asm/Kbuild    |    1 +
 arch/arc/kernel/Makefile       |   16 ++
 arch/arc/kernel/arcksyms.c     |   56 +++++++
 arch/arc/kernel/asm-offsets.c  |   46 ++++++
 arch/arc/kernel/vmlinux.lds.S  |  116 ++++++++++++++
 arch/arc/lib/Makefile          |    9 +
 arch/arc/mm/Makefile           |   10 ++
 arch/arc/plat-arcfpga/Kconfig  |   33 ++++
 arch/arc/plat-arcfpga/Makefile |    9 +
 14 files changed, 801 insertions(+), 0 deletions(-)
 create mode 100644 arch/arc/Kbuild
 create mode 100644 arch/arc/Kconfig
 create mode 100644 arch/arc/Kconfig.debug
 create mode 100644 arch/arc/Makefile
 create mode 100644 arch/arc/boot/Makefile
 create mode 100644 arch/arc/kernel/Makefile
 create mode 100644 arch/arc/kernel/arcksyms.c
 create mode 100644 arch/arc/kernel/asm-offsets.c
 create mode 100644 arch/arc/kernel/vmlinux.lds.S
 create mode 100644 arch/arc/lib/Makefile
 create mode 100644 arch/arc/mm/Makefile
 create mode 100644 arch/arc/plat-arcfpga/Kconfig
 create mode 100644 arch/arc/plat-arcfpga/Makefile

diff --git a/arch/arc/Kbuild b/arch/arc/Kbuild
new file mode 100644
index 0000000..082d329
--- /dev/null
+++ b/arch/arc/Kbuild
@@ -0,0 +1,2 @@
+obj-y += kernel/
+obj-y += mm/
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
new file mode 100644
index 0000000..b0b09ae
--- /dev/null
+++ b/arch/arc/Kconfig
@@ -0,0 +1,328 @@
+#
+# 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.
+#
+
+config ARC
+	def_bool y
+	select ARCH_NO_VIRT_TO_BUS
+	# ARC Busybox based initramfs absolutely relies on DEVTMPFS for /dev
+	select DEVTMPFS if !INITRAMFS_SOURCE=""
+	select GENERIC_ATOMIC64
+	select GENERIC_CLOCKEVENTS
+	select GENERIC_FIND_FIRST_BIT
+	# for now, we don't need GENERIC_IRQ_PROBE, CONFIG_GENERIC_IRQ_CHIP
+	select GENERIC_IRQ_SHOW
+	select GENERIC_PENDING_IRQ if SMP
+	select GENERIC_SMP_IDLE_THREAD
+	select HAVE_GENERIC_HARDIRQS
+	select MODULES_USE_ELF_RELA
+
+config SCHED_OMIT_FRAME_POINTER
+	def_bool y
+
+config GENERIC_CSUM
+	def_bool y
+
+config RWSEM_GENERIC_SPINLOCK
+	def_bool y
+
+config ARCH_FLATMEM_ENABLE
+	def_bool y
+
+config MMU
+	def_bool y
+
+config NO_IOPORT
+	def_bool y
+
+config GENERIC_CALIBRATE_DELAY
+	def_bool y
+
+config GENERIC_HWEIGHT
+	def_bool y
+
+config BINFMT_ELF
+	def_bool y
+
+config HAVE_LATENCYTOP_SUPPORT
+	def_bool y
+
+config NO_DMA
+	def_bool n
+
+source "init/Kconfig"
+source "kernel/Kconfig.freezer"
+
+menu "ARC Architecture Configuration"
+
+choice
+	prompt "ARC Platform"
+	default ARC_PLAT_FPGA_LEGACY
+
+config ARC_PLAT_FPGA_LEGACY
+	bool "\"Legacy\" ARC FPGA dev platform"
+	help
+	  Support for ARC development platforms, provided by Synopsys.
+	  These are based on FPGA or ISS. e.g.
+	  - ARCAngel4
+	  - ML509
+	  - MetaWare ISS
+
+#New platform adds here
+endchoice
+
+menu "ARC CPU Configuration"
+
+choice
+	prompt "ARC Core"
+	default ARC_CPU_770
+
+config ARC_CPU_750D
+	bool "ARC750D"
+	help
+	  Support for ARC750 core
+
+config ARC_CPU_770
+	bool "ARC770"
+	select ARC_CPU_REL_4_10
+	help
+	  Support for ARC770 core introduced with Rel 4.10 (Summer 2011)
+	  This core has a bunch of cool new features:
+	  -MMU-v3: Variable Page Sz (4k, 8k, 16k), bigger J-TLB (128x4)
+                   Shared Address Spaces (for sharing TLB entires in MMU)
+	  -Caches: New Prog Model, Region Flush
+	  -Insns: endian swap, load-locked/store-conditional, time-stamp-ctr
+
+endchoice
+
+config CPU_BIG_ENDIAN
+	bool "Enable Big Endian Mode"
+	default n
+	help
+	  Build kernel for Big Endian Mode of ARC CPU
+
+menuconfig ARC_CACHE
+	bool "Enable Cache Support"
+	default y
+
+if ARC_CACHE
+
+config ARC_CACHE_LINE_SHIFT
+	int "Cache Line Length (as power of 2)"
+	range 5 7
+	default "6"
+	help
+	  Starting with ARC700 4.9, Cache line length is configurable,
+	  This option specifies "N", with Line-len = 2 power N
+	  So line lengths of 32, 64, 128 are specified by 5,6,7, respectively
+	  Linux only supports same line lengths for I and D caches.
+
+config ARC_HAS_ICACHE
+	bool "Use Instruction Cache"
+	default y
+
+config ARC_HAS_DCACHE
+	bool "Use Data Cache"
+	default y
+
+config ARC_CACHE_PAGES
+	bool "Per Page Cache Control"
+	default y
+	depends on ARC_HAS_ICACHE || ARC_HAS_DCACHE
+	help
+	  This can be used to over-ride the global I/D Cache Enable on a
+	  per-page basis (but only for pages accessed via MMU such as
+	  Kernel Virtual address or User Virtual Address)
+	  TLB entries have a per-page Cache Enable Bit.
+	  Note that Global I/D ENABLE + Per Page DISABLE works but corollary
+	  Global DISABLE + Per Page ENABLE won't work
+
+endif	#ARC_CACHE
+
+config ARC_HAS_HW_MPY
+	bool "Use Hardware Multiplier (Normal or Faster XMAC)"
+	default y
+	help
+	  Influences how gcc generates code for MPY operations.
+	  If enabled, MPYxx insns are generated, provided by Standard/XMAC
+	  Multipler. Otherwise software multipy lib is used
+
+choice
+	prompt "ARC700 MMU Version"
+	default ARC_MMU_V3 if ARC_CPU_770
+	default ARC_MMU_V2 if ARC_CPU_750D
+
+config ARC_MMU_V1
+	bool "MMU v1"
+	help
+	  Orig ARC700 MMU
+
+config ARC_MMU_V2
+	bool "MMU v2"
+	help
+	  Fixed the deficiency of v1 - possible thrashing in memcpy sceanrio
+	  when 2 D-TLB and 1 I-TLB entries index into same 2way set.
+
+config ARC_MMU_V3
+	bool "MMU v3"
+	depends on ARC_CPU_770
+	help
+	  Introduced with ARC700 4.10: New Features
+	  Variable Page size (1k-16k), var JTLB size 128 x (2 or 4)
+	  Shared Address Spaces (SASID)
+
+endchoice
+
+
+choice
+	prompt "MMU Page Size"
+	default ARC_PAGE_SIZE_8K
+
+config ARC_PAGE_SIZE_8K
+	bool "8KB"
+	help
+	  Choose between 8k vs 16k
+
+config ARC_PAGE_SIZE_16K
+	bool "16KB"
+	depends on ARC_MMU_V3
+
+config ARC_PAGE_SIZE_4K
+	bool "4KB"
+	depends on ARC_MMU_V3
+
+endchoice
+
+config ARC_FPU_SAVE_RESTORE
+	bool "Enable FPU state persistence across context switch"
+	default n
+	help
+	  Double Precision Floating Point unit had dedictaed regs which
+	  need to be saved/restored across context-switch.
+	  Note that ARC FPU is overly simplistic, unlike say x86, which has
+	  hardware pieces to allow software to conditionally save/restore,
+	  based on actual usage of FPU by a task. Thus our implemn does
+	  this for all tasks in system.
+
+menuconfig ARC_CPU_REL_4_10
+	bool "Enable support for Rel 4.10 features"
+	default n
+	help
+	  -ARC770 (and dependent features) enabled
+	  -ARC750 also shares some of the new features with 770
+
+config ARC_HAS_LLSC
+	bool "Insn: LLOCK/SCOND (efficient atomic ops)"
+	default y
+	depends on ARC_CPU_770
+	# if SMP, enable LLSC ONLY if ARC implementation has coherent atomics
+	depends on !SMP || ARC_HAS_COH_LLSC
+
+config ARC_HAS_SWAPE
+	bool "Insn: SWAPE (endian-swap)"
+	default y
+	depends on ARC_CPU_REL_4_10
+
+config ARC_HAS_RTSC
+	bool "Insn: RTSC (64-bit r/o cycle counter)"
+	default y
+	depends on ARC_CPU_REL_4_10
+
+endmenu   # "ARC CPU Configuration"
+
+menu "Platform Board Configuration"
+
+source "arch/arc/plat-arcfpga/Kconfig"
+
+#New platform adds here
+
+config ARC_PLAT_CLK
+	int "Clk speed in Hz"
+	default "80000000"
+
+config LINUX_LINK_BASE
+	hex "Linux Link Address"
+	default "0x80000000"
+	help
+	  ARC700 divides the 32 bit phy address space into two equal halves
+	  -Lower 2G (0 - 0x7FFF_FFFF ) is user virtual, translated by MMU
+	  -Upper 2G (0x8000_0000 onwards) is untranslated, for kernel
+	  Typically Linux kernel is linked at the start of untransalted addr,
+	  hence the default value of 0x8zs.
+	  However some customers have peripherals mapped at this addr, so
+	  Linux needs to be scooted a bit.
+	  If you don't know what the above means, leave this setting alone.
+
+config ARC_PLAT_SDRAM_SIZE
+	hex "SD RAM Size"
+	default "0x10000000"
+	help
+	  Implies the amount of SDRAM/DRAM Linux is going to claim/own.
+	  The actual memory itself could be larger than this number. But for
+	  all software purposes, this is the amt of memory.
+
+endmenu # "Platform Board Configuration"
+
+config ARC_STACK_NONEXEC
+	bool "Make stack non-executable"
+	default n
+	help
+	  To disable the execute permissions of stack/heap of processes
+	  which are enabled by default.
+
+config HZ
+	int "Timer Frequency"
+	default 100
+
+menuconfig ARC_DBG
+	bool "ARC debugging"
+	default y
+
+config ARC_DBG_TLB_PARANOIA
+	bool "Paranoia Checks in Low Level TLB Handlers"
+	depends on ARC_DBG
+	default n
+
+config ARC_DBG_TLB_MISS_COUNT
+	bool "Profile TLB Misses"
+	default n
+	select DEBUG_FS
+	depends on ARC_DBG
+	help
+	  Counts number of I and D TLB Misses and exports them via Debugfs
+	  The counters can be cleared via Debugfs as well
+
+config CMDLINE
+	string "Kernel command line to built-in"
+	default "print-fatal-signals=1"
+	help
+	  The default command line which will be appended to the optional
+	  u-boot provided command line (see below)
+
+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 copy the string into cmdline buffer
+	  and also append CONFIG_CMDLINE.
+
+source "kernel/Kconfig.preempt"
+
+endmenu	 # "ARC Architecture Configuration"
+
+source "mm/Kconfig"
+source "net/Kconfig"
+source "drivers/Kconfig"
+source "fs/Kconfig"
+source "arch/arc/Kconfig.debug"
+source "security/Kconfig"
+source "crypto/Kconfig"
+source "lib/Kconfig"
diff --git a/arch/arc/Kconfig.debug b/arch/arc/Kconfig.debug
new file mode 100644
index 0000000..962c609
--- /dev/null
+++ b/arch/arc/Kconfig.debug
@@ -0,0 +1,34 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config EARLY_PRINTK
+	bool "Early printk" if EMBEDDED
+	default y
+	help
+	  Write kernel log output directly into the VGA buffer or to a serial
+	  port.
+
+	  This is useful for kernel debugging when your machine crashes very
+	  early before the console code is initialized. For normal operation
+	  it is not recommended because it looks ugly and doesn't cooperate
+	  with klogd/syslogd or the X server. You should normally N here,
+	  unless you want to debug such a crash.
+
+config DEBUG_STACKOVERFLOW
+	bool "Check for stack overflows"
+	depends on DEBUG_KERNEL
+	help
+	  This option will cause messages to be printed if free stack space
+	  drops below a certain limit.
+
+config 16KSTACKS
+	bool "Use 16Kb for kernel stacks instead of 8Kb"
+	help
+	  If you say Y here the kernel will use a  16Kb stacksize for the
+	  kernel stack attached to each process/thread. The default is 8K.
+	  This increases the resident kernel footprint and will cause less
+	  threads to run on the system and also increase the pressure
+	  on the VM subsystem for higher order allocations.
+
+endmenu
diff --git a/arch/arc/Makefile b/arch/arc/Makefile
new file mode 100644
index 0000000..4d52a3b
--- /dev/null
+++ b/arch/arc/Makefile
@@ -0,0 +1,115 @@
+#
+# 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.
+#
+
+UTS_MACHINE := arc
+
+KBUILD_DEFCONFIG := fpga_defconfig
+
+# For ARC FPGA Platforms
+platform-$(CONFIG_ARC_PLAT_FPGA_LEGACY)	:= arcfpga
+#New platform adds here
+
+PLATFORM := $(platform-y)
+export PLATFORM
+
+cflags-y	+= -Iarch/arc/plat-$(PLATFORM)/include
+cflags-y	+= -mA7 -fno-common -pipe -fno-builtin -D__linux__
+
+atleast_gcc44 :=  $(call cc-ifversion, -gt, 0402, y)
+cflags-$(atleast_gcc44)			+= -fsection-anchors
+
+cflags-$(CONFIG_ARC_HAS_LLSC)		+= -mlock
+cflags-$(CONFIG_ARC_HAS_SWAPE)		+= -mswape
+cflags-$(CONFIG_ARC_HAS_RTSC)		+= -mrtsc
+cflags-$(CONFIG_ARC_DW2_UNWIND)		+= -fasynchronous-unwind-tables
+
+ifndef CONFIG_CC_OPTIMIZE_FOR_SIZE
+# Generic build system uses -O2, we want -O3
+cflags-y  += -O3
+endif
+
+# small data is default for elf32 tool-chain. If not usable, disable it
+# This also allows repurposing GP as scratch reg to gcc reg allocator
+disable_small_data := y
+cflags-$(disable_small_data)		+= -mno-sdata -fcall-used-gp
+
+cflags-$(CONFIG_CPU_BIG_ENDIAN)		+= -mbig-endian
+ldflags-$(CONFIG_CPU_BIG_ENDIAN)	+= -EB
+
+# STAR 9000518362:
+# arc-linux-uclibc-ld (buildroot) or arceb-elf32-ld (EZChip) don't accept
+# --build-id w/o "-marclinux".
+# Default arc-elf32-ld is OK
+ldflags-y				+= -marclinux
+
+ARC_LIBGCC				:= -mA7
+cflags-$(CONFIG_ARC_HAS_HW_MPY)		+= -multcost=16
+
+ifndef CONFIG_ARC_HAS_HW_MPY
+	cflags-y	+= -mno-mpy
+
+# newlib for ARC700 assumes MPY to be always present, which is generally true
+# However, if someone really doesn't want MPY, we need to use the 600 ver
+# which coupled with -mno-mpy will use mpy emulation
+# With gcc 4.4.7, -mno-mpy is enough to make any other related adjustments,
+# e.g. increased cost of MPY. With gcc 4.2.1 this had to be explicitly hinted
+
+	ARC_LIBGCC		:= -marc600
+	ifneq ($(atleast_gcc44),y)
+		cflags-y	+= -multcost=30
+	endif
+endif
+
+LIBGCC	:= $(shell $(CC) $(ARC_LIBGCC) $(cflags-y) --print-libgcc-file-name)
+
+# Modules with short calls might break for calls into builtin-kernel
+KBUILD_CFLAGS_MODULE	+= -mlong-calls
+
+# Finally dump eveything into kernel build system
+KBUILD_CFLAGS	+= $(cflags-y)
+KBUILD_AFLAGS	+= $(KBUILD_CFLAGS)
+LDFLAGS		+= $(ldflags-y)
+
+# Needed for Linker script preprocessing
+KBUILD_CPPFLAGS	+= -Iarch/arc/plat-$(PLATFORM)/include
+
+head-y		:= arch/arc/kernel/head.o
+
+# See arch/arc/Kbuild for content of core part of the kernel
+core-y		+= arch/arc/
+
+# w/o this ifneq, make ARCH=arc clean was crapping out
+ifneq ($(platform-y),)
+core-y		+= arch/arc/plat-$(PLATFORM)/
+endif
+
+libs-y		+= arch/arc/lib/ $(LIBGCC)
+
+#default target for make without any arguements.
+KBUILD_IMAGE := bootpImage
+
+all:	$(KBUILD_IMAGE)
+boot	:= arch/arc/boot
+
+bootpImage: vmlinux
+
+uImage: vmlinux
+	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+archclean:
+	$(Q)$(MAKE) $(clean)=$(boot)
+
+# Hacks to enable final link due to absence of link-time branch relexation
+# and gcc choosing optimal(shorter) branches at -O3
+#
+# vineetg Feb 2010: -mlong-calls switched off for overall kernel build
+# However lib/decompress_inflate.o (.init.text) calls
+# zlib_inflate_workspacesize (.text) causing relocation errors.
+# Thus forcing all exten calls in this file to be long calls
+export CFLAGS_decompress_inflate.o = -mmedium-calls
+export CFLAGS_initramfs.o = -mmedium-calls
diff --git a/arch/arc/boot/Makefile b/arch/arc/boot/Makefile
new file mode 100644
index 0000000..7d514c2
--- /dev/null
+++ b/arch/arc/boot/Makefile
@@ -0,0 +1,26 @@
+targets := vmlinux.bin vmlinux.bin.gz uImage
+
+# uImage build relies on mkimage being availble on your host for ARC target
+# You will need to build u-boot for ARC, rename mkimage to arc-elf32-mkimage
+# and make sure it's reacable from your PATH
+MKIMAGE := $(srctree)/scripts/mkuboot.sh
+
+OBJCOPYFLAGS= -O binary -R .note -R .note.gnu.build-id -R .comment -S
+
+LINUX_START_TEXT = $$(readelf -h vmlinux | \
+			grep "Entry point address" | grep -o 0x.*)
+
+UIMAGE_LOADADDR    = $(CONFIG_LINUX_LINK_BASE)
+UIMAGE_ENTRYADDR   = $(LINUX_START_TEXT)
+UIMAGE_COMPRESSION = gzip
+
+$(obj)/vmlinux.bin: vmlinux FORCE
+	$(call if_changed,objcopy)
+
+$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
+	$(call if_changed,gzip)
+
+$(obj)/uImage: $(obj)/vmlinux.bin.gz FORCE
+	$(call if_changed,uimage)
+
+PHONY += FORCE
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index a90a3c6..105ec11 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -33,6 +33,7 @@ generic-y += mman.h
 generic-y += msgbuf.h
 generic-y += param.h
 generic-y += parport.h
+generic-y += pci.h
 generic-y += percpu.h
 generic-y += poll.h
 generic-y += posix_types.h
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
new file mode 100644
index 0000000..6d83431
--- /dev/null
+++ b/arch/arc/kernel/Makefile
@@ -0,0 +1,16 @@
+#
+# 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.
+
+obj-y	:= arcksyms.o setup.o irq.o time.o reset.o ptrace.o entry.o process.o
+obj-y	+= signal.o traps.o sys.o troubleshoot.o stacktrace.o clk.o
+
+obj-$(CONFIG_ARC_FPU_SAVE_RESTORE)	+= fpu.o
+CFLAGS_fpu.o   += -mdpfp
+
+obj-y += ctx_sw_asm.o
+
+extra-y := vmlinux.lds head.o
diff --git a/arch/arc/kernel/arcksyms.c b/arch/arc/kernel/arcksyms.c
new file mode 100644
index 0000000..4d9e777
--- /dev/null
+++ b/arch/arc/kernel/arcksyms.c
@@ -0,0 +1,56 @@
+/*
+ * arcksyms.c - Exporting symbols not exportable from their own sources
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+
+/* libgcc functions, not part of kernel sources */
+extern void __ashldi3(void);
+extern void __ashrdi3(void);
+extern void __divsi3(void);
+extern void __divsf3(void);
+extern void __lshrdi3(void);
+extern void __modsi3(void);
+extern void __muldi3(void);
+extern void __ucmpdi2(void);
+extern void __udivsi3(void);
+extern void __umodsi3(void);
+extern void __cmpdi2(void);
+extern void __fixunsdfsi(void);
+extern void __muldf3(void);
+extern void __divdf3(void);
+extern void __floatunsidf(void);
+extern void __floatunsisf(void);
+
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__divsf3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__ucmpdi2);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umodsi3);
+EXPORT_SYMBOL(__cmpdi2);
+EXPORT_SYMBOL(__fixunsdfsi);
+EXPORT_SYMBOL(__muldf3);
+EXPORT_SYMBOL(__divdf3);
+EXPORT_SYMBOL(__floatunsidf);
+EXPORT_SYMBOL(__floatunsisf);
+
+/* ARC optimised assembler routines */
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strcpy);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strlen);
diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c
new file mode 100644
index 0000000..7f3f611
--- /dev/null
+++ b/arch/arc/kernel/asm-offsets.c
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <asm/hardirq.h>
+#include <linux/thread_info.h>
+#include <asm/page.h>
+#include <linux/kbuild.h>
+
+int main(void)
+{
+	DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
+	DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
+
+	BLANK();
+
+	DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
+	DEFINE(THREAD_CALLEE_REG, offsetof(struct thread_struct, callee_reg));
+	DEFINE(THREAD_FAULT_ADDR,
+	       offsetof(struct thread_struct, fault_address));
+
+	BLANK();
+
+	DEFINE(THREAD_INFO_FLAGS, offsetof(struct thread_info, flags));
+	DEFINE(THREAD_INFO_PREEMPT_COUNT,
+	       offsetof(struct thread_info, preempt_count));
+
+	BLANK();
+
+	DEFINE(TASK_ACT_MM, offsetof(struct task_struct, active_mm));
+	DEFINE(TASK_TGID, offsetof(struct task_struct, tgid));
+
+	DEFINE(MM_CTXT, offsetof(struct mm_struct, context));
+	DEFINE(MM_PGD, offsetof(struct mm_struct, pgd));
+
+	DEFINE(MM_CTXT_ASID, offsetof(mm_context_t, asid));
+
+	return 0;
+}
diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
new file mode 100644
index 0000000..8c72bc3
--- /dev/null
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/cache.h>
+#include <asm/page.h>
+#include <asm/thread_info.h>
+#include <plat/memmap.h>
+
+OUTPUT_ARCH(arc)
+ENTRY(_stext)
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+jiffies = jiffies_64 + 4;
+#else
+jiffies = jiffies_64;
+#endif
+
+SECTIONS
+{
+	. = CONFIG_LINUX_LINK_BASE;
+
+	_int_vec_base_lds = .;
+	.vector : {
+		*(.vector)
+		. = ALIGN(PAGE_SIZE);
+	}
+
+	/*
+	 * The reason for having a seperate subsection .init.ramfs is to
+	 * prevent objump from including it in kernel dumps
+	 *
+	 * Reason for having .init.ramfs above .init is to make sure that the
+	 * binary blob is tucked away to one side, reducing the displacement
+	 * between .init.text and .text, avoiding any possible relocation
+	 * errors because of calls from .init.text to .text
+	 * Yes such calls do exist. e.g.
+	 *	decompress_inflate.c:gunzip( ) -> zlib_inflate_workspace( )
+	 */
+
+	__init_begin = .;
+
+	.init.ramfs : { INIT_RAM_FS }
+
+	. = ALIGN(PAGE_SIZE);
+	_stext = .;
+
+	HEAD_TEXT_SECTION
+	INIT_TEXT_SECTION(L1_CACHE_BYTES)
+
+	/* INIT_DATA_SECTION open-coded: special INIT_RAM_FS handling */
+	.init.data : {
+		INIT_DATA
+		INIT_SETUP(L1_CACHE_BYTES)
+		INIT_CALLS
+		CON_INITCALL
+		SECURITY_INITCALL
+	}
+
+	PERCPU_SECTION(L1_CACHE_BYTES)
+
+	/*
+	 * .exit.text is discard at runtime, not link time, to deal with
+	 * references from .debug_frame
+	 * It will be init freed, being inside [__init_start : __init_end]
+	 */
+	.exit.text : { EXIT_TEXT }
+	.exit.data : { EXIT_DATA }
+
+	. = ALIGN(PAGE_SIZE);
+	__init_end = .;
+
+	.text : {
+		_text = .;
+		TEXT_TEXT
+		SCHED_TEXT
+		LOCK_TEXT
+		KPROBES_TEXT
+		*(.fixup)
+		*(.gnu.warning)
+	}
+	EXCEPTION_TABLE(L1_CACHE_BYTES)
+	_etext = .;
+
+	_sdata = .;
+	RO_DATA_SECTION(PAGE_SIZE)
+
+	/*
+	 * 1. this is .data essentially
+	 * 2. THREAD_SIZE for init.task, must be kernel-stk sz aligned
+	 */
+	RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
+
+	_edata = .;
+
+	BSS_SECTION(0, 0, 0)
+
+	NOTES
+
+	. = ALIGN(PAGE_SIZE);
+	_end = . ;
+
+	STABS_DEBUG
+	DWARF_DEBUG
+	DISCARDS
+
+	.arcextmap 0 : {
+		*(.gnu.linkonce.arcextmap.*)
+		*(.arcextmap.*)
+	}
+}
diff --git a/arch/arc/lib/Makefile b/arch/arc/lib/Makefile
new file mode 100644
index 0000000..db46e20
--- /dev/null
+++ b/arch/arc/lib/Makefile
@@ -0,0 +1,9 @@
+#
+# 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.
+
+lib-y	:= strchr-700.o strcmp.o strcpy-700.o strlen.o
+lib-y	+= memcmp.o memcpy-700.o memset.o
diff --git a/arch/arc/mm/Makefile b/arch/arc/mm/Makefile
new file mode 100644
index 0000000..168dc14
--- /dev/null
+++ b/arch/arc/mm/Makefile
@@ -0,0 +1,10 @@
+#
+# 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.
+#
+
+obj-y	:= extable.o ioremap.o dma.o fault.o init.o
+obj-y	+= tlb.o tlbex.o cache_arc700.o
diff --git a/arch/arc/plat-arcfpga/Kconfig b/arch/arc/plat-arcfpga/Kconfig
new file mode 100644
index 0000000..7af3a4e
--- /dev/null
+++ b/arch/arc/plat-arcfpga/Kconfig
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 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.
+#
+
+if ARC_PLAT_FPGA_LEGACY
+
+choice
+	prompt "FPGA Board"
+
+config ARC_BOARD_ANGEL4
+	bool "ARC Angel4"
+	help
+	  ARC Angel4 FPGA Ref Platform (Xilinx Virtex Based)
+
+config ARC_BOARD_ML509
+	bool "ML509"
+	help
+	  ARC ML509 FPGA Ref Platform (Xilinx Virtex-5 Based)
+
+endchoice
+
+config ARC_SERIAL_BAUD
+	int "UART Baud rate"
+	default "115200"
+	depends on SERIAL_ARC || SERIAL_ARC_CONSOLE
+	help
+	  Baud rate for the ARC UART
+
+endif
diff --git a/arch/arc/plat-arcfpga/Makefile b/arch/arc/plat-arcfpga/Makefile
new file mode 100644
index 0000000..385eb9d
--- /dev/null
+++ b/arch/arc/plat-arcfpga/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright (C) 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.
+#
+
+obj-y := platform.o irq.o
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 06/71] ARC: uaccess friends
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 01/71] ARC: Generic Headers Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 02/71] ARC: Build system: Makefiles, Kconfig, Linker script Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 11/71] ARC: Fundamental ARCH data-types/defines Vineet Gupta
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/include/asm/segment.h |   24 ++
 arch/arc/include/asm/uaccess.h |  646 ++++++++++++++++++++++++++++++++++++++++
 arch/arc/mm/extable.c          |   63 ++++
 3 files changed, 733 insertions(+), 0 deletions(-)
 create mode 100644 arch/arc/include/asm/segment.h
 create mode 100644 arch/arc/include/asm/uaccess.h
 create mode 100644 arch/arc/mm/extable.c

diff --git a/arch/arc/include/asm/segment.h b/arch/arc/include/asm/segment.h
new file mode 100644
index 0000000..da2c459
--- /dev/null
+++ b/arch/arc/include/asm/segment.h
@@ -0,0 +1,24 @@
+/*
+ * 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 __ASMARC_SEGMENT_H
+#define __ASMARC_SEGMENT_H
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long mm_segment_t;
+
+#define MAKE_MM_SEG(s)	((mm_segment_t) { (s) })
+
+#define KERNEL_DS		MAKE_MM_SEG(0)
+#define USER_DS			MAKE_MM_SEG(TASK_SIZE)
+
+#define segment_eq(a, b)	((a) == (b))
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASMARC_SEGMENT_H */
diff --git a/arch/arc/include/asm/uaccess.h b/arch/arc/include/asm/uaccess.h
new file mode 100644
index 0000000..f13bca4
--- /dev/null
+++ b/arch/arc/include/asm/uaccess.h
@@ -0,0 +1,646 @@
+/*
+ * 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.
+ *
+ * vineetg: June 2010
+ *    -__clear_user( ) called multiple times during elf load was byte loop
+ *    converted to do as much word clear as possible.
+ *
+ * vineetg: Dec 2009
+ *    -Hand crafted constant propagation for "constant" copy sizes
+ *    -stock kernel shrunk by 33K at -O3
+ *
+ * vineetg: Sept 2009
+ *    -Added option to (UN)inline copy_(to|from)_user to reduce code sz
+ *    -kernel shrunk by 200K even at -O3 (gcc 4.2.1)
+ *    -Enabled when doing -Os
+ *
+ * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
+ */
+
+#ifndef _ASM_ARC_UACCESS_H
+#define _ASM_ARC_UACCESS_H
+
+#include <linux/sched.h>
+#include <asm/errno.h>
+#include <linux/string.h>	/* for generic string functions */
+
+
+#define __kernel_ok		(segment_eq(get_fs(), KERNEL_DS))
+
+/*
+ * Algorthmically, for __user_ok() we want do:
+ * 	(start < TASK_SIZE) && (start+len < TASK_SIZE)
+ * where TASK_SIZE could either be retrieved from thread_info->addr_limit or
+ * emitted directly in code.
+ *
+ * This can however be rewritten as follows:
+ *	(len <= TASK_SIZE) && (start+len < TASK_SIZE)
+ *
+ * Because it essentially checks if buffer end is within limit and @len is
+ * non-ngeative, which implies that buffer start will be within limit too.
+ *
+ * The reason for rewriting being, for majorit yof cases, @len is generally
+ * compile time constant, causing first sub-expression to be compile time
+ * subsumed.
+ *
+ * The second part would generate weird large LIMMs e.g. (0x6000_0000 - 0x10),
+ * so we check for TASK_SIZE using get_fs() since the addr_limit load from mem
+ * would already have been done at this call site for __kernel_ok()
+ *
+ */
+#define __user_ok(addr, sz)	(((sz) <= TASK_SIZE) && \
+				 (((addr)+(sz)) <= get_fs()))
+#define __access_ok(addr, sz)	(unlikely(__kernel_ok) || \
+				 likely(__user_ok((addr), (sz))))
+
+static inline unsigned long
+__arc_copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+	long res = 0;
+	char val;
+	unsigned long tmp1, tmp2, tmp3, tmp4;
+	unsigned long orig_n = n;
+
+	if (n == 0)
+		return 0;
+
+	/* unaligned */
+	if (((unsigned long)to & 0x3) || ((unsigned long)from & 0x3)) {
+
+		unsigned char tmp;
+
+		__asm__ __volatile__ (
+		"	mov.f   lp_count, %0		\n"
+		"	lpnz 2f				\n"
+		"1:	ldb.ab  %1, [%3, 1]		\n"
+		"	stb.ab  %1, [%2, 1]		\n"
+		"	sub     %0,%0,1			\n"
+		"2:	;nop				\n"
+		"	.section .fixup, \"ax\"		\n"
+		"	.align 4			\n"
+		"3:	j   2b				\n"
+		"	.previous			\n"
+		"	.section __ex_table, \"a\"	\n"
+		"	.align 4			\n"
+		"	.word   1b, 3b			\n"
+		"	.previous			\n"
+
+		: "+r" (n),
+		/*
+		 * Note as an '&' earlyclobber operand to make sure the
+		 * temporary register inside the loop is not the same as
+		 *  FROM or TO.
+		*/
+		  "=&r" (tmp), "+r" (to), "+r" (from)
+		:
+		: "lp_count", "lp_start", "lp_end", "memory");
+
+		return n;
+	}
+
+	/*
+	 * Hand-crafted constant propagation to reduce code sz of the
+	 * laddered copy 16x,8,4,2,1
+	 */
+	if (__builtin_constant_p(orig_n)) {
+		res = orig_n;
+
+		if (orig_n / 16) {
+			orig_n = orig_n % 16;
+
+			__asm__ __volatile__(
+			"	lsr   lp_count, %7,4		\n"
+			"	lp    3f			\n"
+			"1:	ld.ab   %3, [%2, 4]		\n"
+			"11:	ld.ab   %4, [%2, 4]		\n"
+			"12:	ld.ab   %5, [%2, 4]		\n"
+			"13:	ld.ab   %6, [%2, 4]		\n"
+			"	st.ab   %3, [%1, 4]		\n"
+			"	st.ab   %4, [%1, 4]		\n"
+			"	st.ab   %5, [%1, 4]		\n"
+			"	st.ab   %6, [%1, 4]		\n"
+			"	sub     %0,%0,16		\n"
+			"3:	;nop				\n"
+			"	.section .fixup, \"ax\"		\n"
+			"	.align 4			\n"
+			"4:	j   3b				\n"
+			"	.previous			\n"
+			"	.section __ex_table, \"a\"	\n"
+			"	.align 4			\n"
+			"	.word   1b, 4b			\n"
+			"	.word   11b,4b			\n"
+			"	.word   12b,4b			\n"
+			"	.word   13b,4b			\n"
+			"	.previous			\n"
+			: "+r" (res), "+r"(to), "+r"(from),
+			  "=r"(tmp1), "=r"(tmp2), "=r"(tmp3), "=r"(tmp4)
+			: "ir"(n)
+			: "lp_count", "memory");
+		}
+		if (orig_n / 8) {
+			orig_n = orig_n % 8;
+
+			__asm__ __volatile__(
+			"14:	ld.ab   %3, [%2,4]		\n"
+			"15:	ld.ab   %4, [%2,4]		\n"
+			"	st.ab   %3, [%1,4]		\n"
+			"	st.ab   %4, [%1,4]		\n"
+			"	sub     %0,%0,8			\n"
+			"31:	;nop				\n"
+			"	.section .fixup, \"ax\"		\n"
+			"	.align 4			\n"
+			"4:	j   31b				\n"
+			"	.previous			\n"
+			"	.section __ex_table, \"a\"	\n"
+			"	.align 4			\n"
+			"	.word   14b,4b			\n"
+			"	.word   15b,4b			\n"
+			"	.previous			\n"
+			: "+r" (res), "+r"(to), "+r"(from),
+			  "=r"(tmp1), "=r"(tmp2)
+			:
+			: "memory");
+		}
+		if (orig_n / 4) {
+			orig_n = orig_n % 4;
+
+			__asm__ __volatile__(
+			"16:	ld.ab   %3, [%2,4]		\n"
+			"	st.ab   %3, [%1,4]		\n"
+			"	sub     %0,%0,4			\n"
+			"32:	;nop				\n"
+			"	.section .fixup, \"ax\"		\n"
+			"	.align 4			\n"
+			"4:	j   32b				\n"
+			"	.previous			\n"
+			"	.section __ex_table, \"a\"	\n"
+			"	.align 4			\n"
+			"	.word   16b,4b			\n"
+			"	.previous			\n"
+			: "+r" (res), "+r"(to), "+r"(from), "=r"(tmp1)
+			:
+			: "memory");
+		}
+		if (orig_n / 2) {
+			orig_n = orig_n % 2;
+
+			__asm__ __volatile__(
+			"17:	ldw.ab   %3, [%2,2]		\n"
+			"	stw.ab   %3, [%1,2]		\n"
+			"	sub      %0,%0,2		\n"
+			"33:	;nop				\n"
+			"	.section .fixup, \"ax\"		\n"
+			"	.align 4			\n"
+			"4:	j   33b				\n"
+			"	.previous			\n"
+			"	.section __ex_table, \"a\"	\n"
+			"	.align 4			\n"
+			"	.word   17b,4b			\n"
+			"	.previous			\n"
+			: "+r" (res), "+r"(to), "+r"(from), "=r"(tmp1)
+			:
+			: "memory");
+		}
+		if (orig_n & 1) {
+			__asm__ __volatile__(
+			"18:	ldb.ab   %3, [%2,2]		\n"
+			"	stb.ab   %3, [%1,2]		\n"
+			"	sub      %0,%0,1		\n"
+			"34:	; nop				\n"
+			"	.section .fixup, \"ax\"		\n"
+			"	.align 4			\n"
+			"4:	j   34b				\n"
+			"	.previous			\n"
+			"	.section __ex_table, \"a\"	\n"
+			"	.align 4			\n"
+			"	.word   18b,4b			\n"
+			"	.previous			\n"
+			: "+r" (res), "+r"(to), "+r"(from), "=r"(tmp1)
+			:
+			: "memory");
+		}
+	} else {  /* n is NOT constant, so laddered copy of 16x,8,4,2,1  */
+
+		__asm__ __volatile__(
+		"	mov %0,%3			\n"
+		"	lsr.f   lp_count, %3,4		\n"  /* 16x bytes */
+		"	lpnz    3f			\n"
+		"1:	ld.ab   %5, [%2, 4]		\n"
+		"11:	ld.ab   %6, [%2, 4]		\n"
+		"12:	ld.ab   %7, [%2, 4]		\n"
+		"13:	ld.ab   %8, [%2, 4]		\n"
+		"	st.ab   %5, [%1, 4]		\n"
+		"	st.ab   %6, [%1, 4]		\n"
+		"	st.ab   %7, [%1, 4]		\n"
+		"	st.ab   %8, [%1, 4]		\n"
+		"	sub     %0,%0,16		\n"
+		"3:	and.f   %3,%3,0xf		\n"  /* stragglers */
+		"	bz      34f			\n"
+		"	bbit0   %3,3,31f		\n"  /* 8 bytes left */
+		"14:	ld.ab   %5, [%2,4]		\n"
+		"15:	ld.ab   %6, [%2,4]		\n"
+		"	st.ab   %5, [%1,4]		\n"
+		"	st.ab   %6, [%1,4]		\n"
+		"	sub.f   %0,%0,8			\n"
+		"31:	bbit0   %3,2,32f		\n"  /* 4 bytes left */
+		"16:	ld.ab   %5, [%2,4]		\n"
+		"	st.ab   %5, [%1,4]		\n"
+		"	sub.f   %0,%0,4			\n"
+		"32:	bbit0   %3,1,33f		\n"  /* 2 bytes left */
+		"17:	ldw.ab  %5, [%2,2]		\n"
+		"	stw.ab  %5, [%1,2]		\n"
+		"	sub.f   %0,%0,2			\n"
+		"33:	bbit0   %3,0,34f		\n"
+		"18:	ldb.ab  %5, [%2,1]		\n"  /* 1 byte left */
+		"	stb.ab  %5, [%1,1]		\n"
+		"	sub.f   %0,%0,1			\n"
+		"34:	;nop				\n"
+		"	.section .fixup, \"ax\"		\n"
+		"	.align 4			\n"
+		"4:	j   34b				\n"
+		"	.previous			\n"
+		"	.section __ex_table, \"a\"	\n"
+		"	.align 4			\n"
+		"	.word   1b, 4b			\n"
+		"	.word   11b,4b			\n"
+		"	.word   12b,4b			\n"
+		"	.word   13b,4b			\n"
+		"	.word   14b,4b			\n"
+		"	.word   15b,4b			\n"
+		"	.word   16b,4b			\n"
+		"	.word   17b,4b			\n"
+		"	.word   18b,4b			\n"
+		"	.previous			\n"
+		: "=r" (res), "+r"(to), "+r"(from), "+r"(n), "=r"(val),
+		  "=r"(tmp1), "=r"(tmp2), "=r"(tmp3), "=r"(tmp4)
+		:
+		: "lp_count", "memory");
+	}
+
+	return res;
+}
+
+extern unsigned long slowpath_copy_to_user(void __user *to, const void *from,
+					   unsigned long n);
+
+static inline unsigned long
+__arc_copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+	long res = 0;
+	char val;
+	unsigned long tmp1, tmp2, tmp3, tmp4;
+	unsigned long orig_n = n;
+
+	if (n == 0)
+		return 0;
+
+	/* unaligned */
+	if (((unsigned long)to & 0x3) || ((unsigned long)from & 0x3)) {
+
+		unsigned char tmp;
+
+		__asm__ __volatile__(
+		"	mov.f   lp_count, %0		\n"
+		"	lpnz 3f				\n"
+		"	ldb.ab  %1, [%3, 1]		\n"
+		"1:	stb.ab  %1, [%2, 1]		\n"
+		"	sub     %0, %0, 1		\n"
+		"3:	;nop				\n"
+		"	.section .fixup, \"ax\"		\n"
+		"	.align 4			\n"
+		"4:	j   3b				\n"
+		"	.previous			\n"
+		"	.section __ex_table, \"a\"	\n"
+		"	.align 4			\n"
+		"	.word   1b, 4b			\n"
+		"	.previous			\n"
+
+		: "+r" (n),
+		/* Note as an '&' earlyclobber operand to make sure the
+		 * temporary register inside the loop is not the same as
+		 * FROM or TO.
+		 */
+		  "=&r" (tmp), "+r" (to), "+r" (from)
+		:
+		: "lp_count", "lp_start", "lp_end", "memory");
+
+		return n;
+	}
+
+	if (__builtin_constant_p(orig_n)) {
+		res = orig_n;
+
+		if (orig_n / 16) {
+			orig_n = orig_n % 16;
+
+			__asm__ __volatile__(
+			"	lsr lp_count, %7,4		\n"
+			"	lp  3f				\n"
+			"	ld.ab %3, [%2, 4]		\n"
+			"	ld.ab %4, [%2, 4]		\n"
+			"	ld.ab %5, [%2, 4]		\n"
+			"	ld.ab %6, [%2, 4]		\n"
+			"1:	st.ab %3, [%1, 4]		\n"
+			"11:	st.ab %4, [%1, 4]		\n"
+			"12:	st.ab %5, [%1, 4]		\n"
+			"13:	st.ab %6, [%1, 4]		\n"
+			"	sub   %0, %0, 16		\n"
+			"3:;nop					\n"
+			"	.section .fixup, \"ax\"		\n"
+			"	.align 4			\n"
+			"4:	j   3b				\n"
+			"	.previous			\n"
+			"	.section __ex_table, \"a\"	\n"
+			"	.align 4			\n"
+			"	.word   1b, 4b			\n"
+			"	.word   11b,4b			\n"
+			"	.word   12b,4b			\n"
+			"	.word   13b,4b			\n"
+			"	.previous			\n"
+			: "+r" (res), "+r"(to), "+r"(from),
+			  "=r"(tmp1), "=r"(tmp2), "=r"(tmp3), "=r"(tmp4)
+			: "ir"(n)
+			: "lp_count", "memory");
+		}
+		if (orig_n / 8) {
+			orig_n = orig_n % 8;
+
+			__asm__ __volatile__(
+			"	ld.ab   %3, [%2,4]		\n"
+			"	ld.ab   %4, [%2,4]		\n"
+			"14:	st.ab   %3, [%1,4]		\n"
+			"15:	st.ab   %4, [%1,4]		\n"
+			"	sub     %0, %0, 8		\n"
+			"31:;nop				\n"
+			"	.section .fixup, \"ax\"		\n"
+			"	.align 4			\n"
+			"4:	j   31b				\n"
+			"	.previous			\n"
+			"	.section __ex_table, \"a\"	\n"
+			"	.align 4			\n"
+			"	.word   14b,4b			\n"
+			"	.word   15b,4b			\n"
+			"	.previous			\n"
+			: "+r" (res), "+r"(to), "+r"(from),
+			  "=r"(tmp1), "=r"(tmp2)
+			:
+			: "memory");
+		}
+		if (orig_n / 4) {
+			orig_n = orig_n % 4;
+
+			__asm__ __volatile__(
+			"	ld.ab   %3, [%2,4]		\n"
+			"16:	st.ab   %3, [%1,4]		\n"
+			"	sub     %0, %0, 4		\n"
+			"32:;nop				\n"
+			"	.section .fixup, \"ax\"		\n"
+			"	.align 4			\n"
+			"4:	j   32b				\n"
+			"	.previous			\n"
+			"	.section __ex_table, \"a\"	\n"
+			"	.align 4			\n"
+			"	.word   16b,4b			\n"
+			"	.previous			\n"
+			: "+r" (res), "+r"(to), "+r"(from), "=r"(tmp1)
+			:
+			: "memory");
+		}
+		if (orig_n / 2) {
+			orig_n = orig_n % 2;
+
+			__asm__ __volatile__(
+			"	ldw.ab    %3, [%2,2]		\n"
+			"17:	stw.ab    %3, [%1,2]		\n"
+			"	sub       %0, %0, 2		\n"
+			"33:;nop				\n"
+			"	.section .fixup, \"ax\"		\n"
+			"	.align 4			\n"
+			"4:	j   33b				\n"
+			"	.previous			\n"
+			"	.section __ex_table, \"a\"	\n"
+			"	.align 4			\n"
+			"	.word   17b,4b			\n"
+			"	.previous			\n"
+			: "+r" (res), "+r"(to), "+r"(from), "=r"(tmp1)
+			:
+			: "memory");
+		}
+		if (orig_n & 1) {
+			__asm__ __volatile__(
+			"	ldb.ab  %3, [%2,1]		\n"
+			"18:	stb.ab  %3, [%1,1]		\n"
+			"	sub     %0, %0, 1		\n"
+			"34:	;nop				\n"
+			"	.section .fixup, \"ax\"		\n"
+			"	.align 4			\n"
+			"4:	j   34b				\n"
+			"	.previous			\n"
+			"	.section __ex_table, \"a\"	\n"
+			"	.align 4			\n"
+			"	.word   18b,4b			\n"
+			"	.previous			\n"
+			: "+r" (res), "+r"(to), "+r"(from), "=r"(tmp1)
+			:
+			: "memory");
+		}
+	} else {  /* n is NOT constant, so laddered copy of 16x,8,4,2,1  */
+
+		__asm__ __volatile__(
+		"	mov   %0,%3			\n"
+		"	lsr.f lp_count, %3,4		\n"  /* 16x bytes */
+		"	lpnz  3f			\n"
+		"	ld.ab %5, [%2, 4]		\n"
+		"	ld.ab %6, [%2, 4]		\n"
+		"	ld.ab %7, [%2, 4]		\n"
+		"	ld.ab %8, [%2, 4]		\n"
+		"1:	st.ab %5, [%1, 4]		\n"
+		"11:	st.ab %6, [%1, 4]		\n"
+		"12:	st.ab %7, [%1, 4]		\n"
+		"13:	st.ab %8, [%1, 4]		\n"
+		"	sub   %0, %0, 16		\n"
+		"3:	and.f %3,%3,0xf			\n" /* stragglers */
+		"	bz 34f				\n"
+		"	bbit0   %3,3,31f		\n" /* 8 bytes left */
+		"	ld.ab   %5, [%2,4]		\n"
+		"	ld.ab   %6, [%2,4]		\n"
+		"14:	st.ab   %5, [%1,4]		\n"
+		"15:	st.ab   %6, [%1,4]		\n"
+		"	sub.f   %0, %0, 8		\n"
+		"31:	bbit0   %3,2,32f		\n"  /* 4 bytes left */
+		"	ld.ab   %5, [%2,4]		\n"
+		"16:	st.ab   %5, [%1,4]		\n"
+		"	sub.f   %0, %0, 4		\n"
+		"32:	bbit0 %3,1,33f			\n"  /* 2 bytes left */
+		"	ldw.ab    %5, [%2,2]		\n"
+		"17:	stw.ab    %5, [%1,2]		\n"
+		"	sub.f %0, %0, 2			\n"
+		"33:	bbit0 %3,0,34f			\n"
+		"	ldb.ab    %5, [%2,1]		\n"  /* 1 byte left */
+		"18:	stb.ab  %5, [%1,1]		\n"
+		"	sub.f %0, %0, 1			\n"
+		"34:	;nop				\n"
+		"	.section .fixup, \"ax\"		\n"
+		"	.align 4			\n"
+		"4:	j   34b				\n"
+		"	.previous			\n"
+		"	.section __ex_table, \"a\"	\n"
+		"	.align 4			\n"
+		"	.word   1b, 4b			\n"
+		"	.word   11b,4b			\n"
+		"	.word   12b,4b			\n"
+		"	.word   13b,4b			\n"
+		"	.word   14b,4b			\n"
+		"	.word   15b,4b			\n"
+		"	.word   16b,4b			\n"
+		"	.word   17b,4b			\n"
+		"	.word   18b,4b			\n"
+		"	.previous			\n"
+		: "=r" (res), "+r"(to), "+r"(from), "+r"(n), "=r"(val),
+		  "=r"(tmp1), "=r"(tmp2), "=r"(tmp3), "=r"(tmp4)
+		:
+		: "lp_count", "memory");
+	}
+
+	return res;
+}
+
+static inline unsigned long __arc_clear_user(void __user *to, unsigned long n)
+{
+	long res = n;
+	unsigned char *d_char = to;
+
+	__asm__ __volatile__(
+	"	bbit0   %0, 0, 1f		\n"
+	"75:	stb.ab  %2, [%0,1]		\n"
+	"	sub %1, %1, 1			\n"
+	"1:	bbit0   %0, 1, 2f		\n"
+	"76:	stw.ab  %2, [%0,2]		\n"
+	"	sub %1, %1, 2			\n"
+	"2:	asr.f   lp_count, %1, 2		\n"
+	"	lpnz    3f			\n"
+	"77:	st.ab   %2, [%0,4]		\n"
+	"	sub %1, %1, 4			\n"
+	"3:	bbit0   %1, 1, 4f		\n"
+	"78:	stw.ab  %2, [%0,2]		\n"
+	"	sub %1, %1, 2			\n"
+	"4:	bbit0   %1, 0, 5f		\n"
+	"79:	stb.ab  %2, [%0,1]		\n"
+	"	sub %1, %1, 1			\n"
+	"5:					\n"
+	"	.section .fixup, \"ax\"		\n"
+	"	.align 4			\n"
+	"3:	j   5b				\n"
+	"	.previous			\n"
+	"	.section __ex_table, \"a\"	\n"
+	"	.align 4			\n"
+	"	.word   75b, 3b			\n"
+	"	.word   76b, 3b			\n"
+	"	.word   77b, 3b			\n"
+	"	.word   78b, 3b			\n"
+	"	.word   79b, 3b			\n"
+	"	.previous			\n"
+	: "+r"(d_char), "+r"(res)
+	: "i"(0)
+	: "lp_count", "lp_start", "lp_end", "memory");
+
+	return res;
+}
+
+static inline long
+__arc_strncpy_from_user(char *dst, const char __user *src, long count)
+{
+	long res = count;
+	char val;
+	unsigned int hw_count;
+
+	if (count == 0)
+		return 0;
+
+	__asm__ __volatile__(
+	"	lp 2f		\n"
+	"1:	ldb.ab  %3, [%2, 1]		\n"
+	"	breq.d  %3, 0, 2f		\n"
+	"	stb.ab  %3, [%1, 1]		\n"
+	"2:	sub %0, %6, %4			\n"
+	"3:	;nop				\n"
+	"	.section .fixup, \"ax\"		\n"
+	"	.align 4			\n"
+	"4:	mov %0, %5			\n"
+	"	j   3b				\n"
+	"	.previous			\n"
+	"	.section __ex_table, \"a\"	\n"
+	"	.align 4			\n"
+	"	.word   1b, 4b			\n"
+	"	.previous			\n"
+	: "=r"(res), "+r"(dst), "+r"(src), "=&r"(val), "=l"(hw_count)
+	: "g"(-EFAULT), "ir"(count), "4"(count)	/* this "4" seeds lp_count */
+	: "memory");
+
+	return res;
+}
+
+static inline long __arc_strnlen_user(const char __user *s, long n)
+{
+	long res, tmp1, cnt;
+	char val;
+
+	__asm__ __volatile__(
+	"	mov %2, %1			\n"
+	"1:	ldb.ab  %3, [%0, 1]		\n"
+	"	breq.d  %3, 0, 2f		\n"
+	"	sub.f   %2, %2, 1		\n"
+	"	bnz 1b				\n"
+	"	sub %2, %2, 1			\n"
+	"2:	sub %0, %1, %2			\n"
+	"3:	;nop				\n"
+	"	.section .fixup, \"ax\"		\n"
+	"	.align 4			\n"
+	"4:	mov %0, 0			\n"
+	"	j   3b				\n"
+	"	.previous			\n"
+	"	.section __ex_table, \"a\"	\n"
+	"	.align 4			\n"
+	"	.word 1b, 4b			\n"
+	"	.previous			\n"
+	: "=r"(res), "=r"(tmp1), "=r"(cnt), "=r"(val)
+	: "0"(s), "1"(n)
+	: "memory");
+
+	return res;
+}
+
+#ifndef CONFIG_CC_OPTIMIZE_FOR_SIZE
+#define __copy_from_user(t, f, n)	__arc_copy_from_user(t, f, n)
+#define __copy_to_user(t, f, n)		__arc_copy_to_user(t, f, n)
+#define __clear_user(d, n)		__arc_clear_user(d, n)
+#define __strncpy_from_user(d, s, n)	__arc_strncpy_from_user(d, s, n)
+#define __strnlen_user(s, n)		__arc_strnlen_user(s, n)
+#else
+extern long arc_copy_from_user_noinline(void *to, const void __user * from,
+		unsigned long n);
+extern long arc_copy_to_user_noinline(void __user *to, const void *from,
+		unsigned long n);
+extern unsigned long arc_clear_user_noinline(void __user *to,
+		unsigned long n);
+extern long arc_strncpy_from_user_noinline (char *dst, const char __user *src,
+		long count);
+extern long arc_strnlen_user_noinline(const char __user *src, long n);
+
+#define __copy_from_user(t, f, n)	arc_copy_from_user_noinline(t, f, n)
+#define __copy_to_user(t, f, n)		arc_copy_to_user_noinline(t, f, n)
+#define __clear_user(d, n)		arc_clear_user_noinline(d, n)
+#define __strncpy_from_user(d, s, n)	arc_strncpy_from_user_noinline(d, s, n)
+#define __strnlen_user(s, n)		arc_strnlen_user_noinline(s, n)
+
+#endif
+
+#include <asm-generic/uaccess.h>
+
+extern int fixup_exception(struct pt_regs *regs);
+
+#endif
diff --git a/arch/arc/mm/extable.c b/arch/arc/mm/extable.c
new file mode 100644
index 0000000..014172b
--- /dev/null
+++ b/arch/arc/mm/extable.c
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ *
+ * Borrowed heavily from MIPS
+ */
+
+#include <linux/module.h>
+#include <linux/uaccess.h>
+
+int fixup_exception(struct pt_regs *regs)
+{
+	const struct exception_table_entry *fixup;
+
+	fixup = search_exception_tables(instruction_pointer(regs));
+	if (fixup) {
+		regs->ret = fixup->fixup;
+
+		return 1;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
+
+long arc_copy_from_user_noinline(void *to, const void __user * from,
+		unsigned long n)
+{
+	return __arc_copy_from_user(to, from, n);
+}
+EXPORT_SYMBOL(arc_copy_from_user_noinline);
+
+long arc_copy_to_user_noinline(void __user *to, const void *from,
+		unsigned long n)
+{
+	return __arc_copy_to_user(to, from, n);
+}
+EXPORT_SYMBOL(arc_copy_to_user_noinline);
+
+unsigned long arc_clear_user_noinline(void __user *to,
+		unsigned long n)
+{
+	return __arc_clear_user(to, n);
+}
+EXPORT_SYMBOL(arc_clear_user_noinline);
+
+long arc_strncpy_from_user_noinline (char *dst, const char __user *src,
+		long count)
+{
+	return __arc_strncpy_from_user(dst, src, count);
+}
+EXPORT_SYMBOL(arc_strncpy_from_user_noinline);
+
+long arc_strnlen_user_noinline(const char __user *src, long n)
+{
+	return __arc_strnlen_user(src, n);
+}
+EXPORT_SYMBOL(arc_strnlen_user_noinline);
+#endif
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 11/71] ARC: Fundamental ARCH data-types/defines
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (2 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 06/71] ARC: uaccess friends Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 17/71] ARC: Syscall support (no-legacy-syscall ABI) Vineet Gupta
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta, Jonas Bonn, Al Viro

* L1_CACHE_SHIFT
* PAGE_SIZE, PAGE_OFFSET
* struct pt_regs, struct user_regs_struct
* struct thread_struct, cpu_relax(), task_pt_regs(), start_thread(), ...
* struct thread_info, THREAD_SIZE, INIT_THREAD_INFO(), TIF_*, ...
* BUG()
* ELF_*
* Elf_*

To disallow user-space visibility into some of the core kernel data-types
such as struct pt_regs, #ifdef __KERNEL__ which also makes the UAPI header
spit (further patch in the series) to NOT export it to asm/uapi/ptrace.h

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Jonas Bonn <jonas.bonn@gmail.com>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
 arch/arc/include/asm/bug.h         |   37 +++++++++
 arch/arc/include/asm/cache.h       |   21 +++++
 arch/arc/include/asm/elf.h         |   97 ++++++++++++++++++++++++
 arch/arc/include/asm/exec.h        |   15 ++++
 arch/arc/include/asm/kdebug.h      |   19 +++++
 arch/arc/include/asm/linkage.h     |   30 ++++++++
 arch/arc/include/asm/module.h      |   17 ++++
 arch/arc/include/asm/page.h        |   42 +++++++++++
 arch/arc/include/asm/processor.h   |  143 ++++++++++++++++++++++++++++++++++++
 arch/arc/include/asm/ptrace.h      |  132 +++++++++++++++++++++++++++++++++
 arch/arc/include/asm/sections.h    |   17 ++++
 arch/arc/include/asm/thread_info.h |  121 ++++++++++++++++++++++++++++++
 12 files changed, 691 insertions(+), 0 deletions(-)
 create mode 100644 arch/arc/include/asm/bug.h
 create mode 100644 arch/arc/include/asm/cache.h
 create mode 100644 arch/arc/include/asm/elf.h
 create mode 100644 arch/arc/include/asm/exec.h
 create mode 100644 arch/arc/include/asm/kdebug.h
 create mode 100644 arch/arc/include/asm/linkage.h
 create mode 100644 arch/arc/include/asm/module.h
 create mode 100644 arch/arc/include/asm/page.h
 create mode 100644 arch/arc/include/asm/processor.h
 create mode 100644 arch/arc/include/asm/ptrace.h
 create mode 100644 arch/arc/include/asm/sections.h
 create mode 100644 arch/arc/include/asm/thread_info.h

diff --git a/arch/arc/include/asm/bug.h b/arch/arc/include/asm/bug.h
new file mode 100644
index 0000000..2ad8f9b
--- /dev/null
+++ b/arch/arc/include/asm/bug.h
@@ -0,0 +1,37 @@
+/*
+ * 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_ARC_BUG_H
+#define _ASM_ARC_BUG_H
+
+#ifndef __ASSEMBLY__
+
+#include <asm/ptrace.h>
+
+struct task_struct;
+
+void show_regs(struct pt_regs *regs);
+void show_stacktrace(struct task_struct *tsk, struct pt_regs *regs);
+void show_kernel_fault_diag(const char *str, struct pt_regs *regs,
+			    unsigned long address, unsigned long cause_reg);
+void die(const char *str, struct pt_regs *regs, unsigned long address,
+	 unsigned long cause_reg);
+
+#define BUG()	do {				\
+	dump_stack();					\
+	pr_warn("Kernel BUG in %s: %s: %d!\n",	\
+		__FILE__, __func__,  __LINE__);	\
+} while (0)
+
+#define HAVE_ARCH_BUG
+
+#include <asm-generic/bug.h>
+
+#endif	/* !__ASSEMBLY__ */
+
+#endif
diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h
new file mode 100644
index 0000000..30c72a4
--- /dev/null
+++ b/arch/arc/include/asm/cache.h
@@ -0,0 +1,21 @@
+/*
+ * 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 __ARC_ASM_CACHE_H
+#define __ARC_ASM_CACHE_H
+
+/* In case $$ not config, setup a dummy number for rest of kernel */
+#ifndef CONFIG_ARC_CACHE_LINE_SHIFT
+#define L1_CACHE_SHIFT		6
+#else
+#define L1_CACHE_SHIFT		CONFIG_ARC_CACHE_LINE_SHIFT
+#endif
+
+#define L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)
+
+#endif /* _ASM_CACHE_H */
diff --git a/arch/arc/include/asm/elf.h b/arch/arc/include/asm/elf.h
new file mode 100644
index 0000000..147284f
--- /dev/null
+++ b/arch/arc/include/asm/elf.h
@@ -0,0 +1,97 @@
+/*
+ * 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_ARC_ELF_H
+#define __ASM_ARC_ELF_H
+
+#include <asm/ptrace.h>
+
+#define EM_ARCOMPACT		93
+
+/* Machine specific ELF Hdr flags */
+#define EF_ARC_OSABI_MSK	0x00000f00
+#define EF_ARC_OSABI_ORIG	0x00000000   /* MUST be zero for back-compat */
+#define EF_ARC_OSABI_V2		0x00000200
+
+/* ARC Relocations (kernel Modules only) */
+#define  R_ARC_32		0x4
+#define  R_ARC_32_ME		0x1B
+#define  R_ARC_S25H_PCREL	0x10
+#define  R_ARC_S25W_PCREL	0x11
+
+typedef unsigned long elf_greg_t;
+typedef unsigned long elf_fpregset_t;
+
+
+/* core dump regs is in the order pt_regs, callee_regs, stop_pc (for gdb) */
+#define ELF_NGREG	((sizeof(struct pt_regs) + sizeof(struct callee_regs) \
+			  + sizeof(unsigned long)) / sizeof(elf_greg_t))
+
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/*
+ * To ensure that
+ *  -we don't load something for the wrong architecture.
+ *  -The userspace is using the correct syscall ABI
+ */
+struct elf32_hdr;
+extern int elf_check_arch(const struct elf32_hdr *);
+#define elf_check_arch	elf_check_arch
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_ARCH		EM_ARCOMPACT
+#define ELF_CLASS		ELFCLASS32
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define ELF_DATA		ELFDATA2MSB
+#else
+#define ELF_DATA		ELFDATA2LSB
+#endif
+
+#ifdef __KERNEL__
+
+#define CORE_DUMP_USE_REGSET
+
+#define ELF_EXEC_PAGESIZE	PAGE_SIZE
+
+/*
+ * This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+ * use of this is to invoke "./ld.so someprog" to test out a new version of
+ * the loader.  We need to make sure that it is out of the way of the program
+ * that it will "exec", and that there is sufficient room for the brk.
+ */
+#define ELF_ET_DYN_BASE		(2 * TASK_SIZE / 3)
+
+/*
+ * When the program starts, a1 contains a pointer to a function to be
+ * registered with atexit, as per the SVR4 ABI.  A value of 0 means we
+ * have no such handler.
+ */
+#define ELF_PLAT_INIT(_r, load_addr)	((_r)->r0 = 0)
+
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this cpu supports.
+ */
+#define ELF_HWCAP	(0)
+
+/*
+ * This yields a string that ld.so will use to load implementation
+ * specific libraries for optimization.  This is more specific in
+ * intent than poking at uname or /proc/cpuinfo.
+ */
+#define ELF_PLATFORM	(NULL)
+
+#define SET_PERSONALITY(ex) \
+	set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
+
+#endif  /* __KERNEL__ */
+
+#endif
diff --git a/arch/arc/include/asm/exec.h b/arch/arc/include/asm/exec.h
new file mode 100644
index 0000000..28abc69
--- /dev/null
+++ b/arch/arc/include/asm/exec.h
@@ -0,0 +1,15 @@
+/*
+ * 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_ARC_EXEC_H
+#define __ASM_ARC_EXEC_H
+
+/* Align to 16b */
+#define arch_align_stack(p) ((unsigned long)(p) & ~0xf)
+
+#endif
diff --git a/arch/arc/include/asm/kdebug.h b/arch/arc/include/asm/kdebug.h
new file mode 100644
index 0000000..3fbe6c4
--- /dev/null
+++ b/arch/arc/include/asm/kdebug.h
@@ -0,0 +1,19 @@
+/*
+ * 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_ARC_KDEBUG_H
+#define _ASM_ARC_KDEBUG_H
+
+enum die_val {
+	DIE_UNUSED,
+	DIE_TRAP,
+	DIE_IERR,
+	DIE_OOPS
+};
+
+#endif
diff --git a/arch/arc/include/asm/linkage.h b/arch/arc/include/asm/linkage.h
new file mode 100644
index 0000000..a45d1bb
--- /dev/null
+++ b/arch/arc/include/asm/linkage.h
@@ -0,0 +1,30 @@
+/*
+ * 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_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+#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
+
+#endif /* __ASSEMBLY__ */
+
+#endif
diff --git a/arch/arc/include/asm/module.h b/arch/arc/include/asm/module.h
new file mode 100644
index 0000000..165d768
--- /dev/null
+++ b/arch/arc/include/asm/module.h
@@ -0,0 +1,17 @@
+/*
+ * 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.
+ *
+ * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
+
+ */
+
+#ifndef _ASM_ARC_MODULE_H
+#define _ASM_ARC_MODULE_H
+
+#include <asm-generic/module.h>
+
+#endif /* _ASM_ARC_MODULE_H */
diff --git a/arch/arc/include/asm/page.h b/arch/arc/include/asm/page.h
new file mode 100644
index 0000000..7cd1224
--- /dev/null
+++ b/arch/arc/include/asm/page.h
@@ -0,0 +1,42 @@
+/*
+ * 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_ARC_PAGE_H
+#define __ASM_ARC_PAGE_H
+
+/* PAGE_SHIFT determines the page size */
+#if defined(CONFIG_ARC_PAGE_SIZE_16K)
+#define PAGE_SHIFT 14
+#elif defined(CONFIG_ARC_PAGE_SIZE_4K)
+#define PAGE_SHIFT 12
+#else
+/*
+ * Default 8k
+ * done this way (instead of under CONFIG_ARC_PAGE_SIZE_8K) because adhoc
+ * user code (busybox appletlib.h) expects PAGE_SHIFT to be defined w/o
+ * using the correct uClibc header and in their build our autoconf.h is
+ * not available
+ */
+#define PAGE_SHIFT 13
+#endif
+
+#ifdef __ASSEMBLY__
+#define PAGE_SIZE	(1 << PAGE_SHIFT)
+#define PAGE_OFFSET	(0x80000000)
+#else
+#define PAGE_SIZE	(1UL << PAGE_SHIFT)	/* Default 8K */
+#define PAGE_OFFSET	(0x80000000UL)	/* Kernel starts at 2G onwards */
+#endif
+
+#define PAGE_MASK	(~(PAGE_SIZE-1))
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h
new file mode 100644
index 0000000..bf88cfb
--- /dev/null
+++ b/arch/arc/include/asm/processor.h
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ *
+ * vineetg: March 2009
+ *  -Implemented task_pt_regs( )
+ *
+ * Amit Bhor, Sameer Dhavale, Ashwin Chaugule: Codito Technologies 2004
+ */
+
+#ifndef __ASM_ARC_PROCESSOR_H
+#define __ASM_ARC_PROCESSOR_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+#include <asm/arcregs.h>	/* for STATUS_E1_MASK et all */
+
+/* Arch specific stuff which needs to be saved per task.
+ * However these items are not so important so as to earn a place in
+ * struct thread_info
+ */
+struct thread_struct {
+	unsigned long ksp;	/* kernel mode stack pointer */
+	unsigned long callee_reg;	/* pointer to callee regs */
+	unsigned long fault_address;	/* dbls as brkpt holder as well */
+	unsigned long cause_code;	/* Exception Cause Code (ECR) */
+};
+
+#define INIT_THREAD  {                          \
+	.ksp = sizeof(init_stack) + (unsigned long) init_stack, \
+}
+
+/* Forward declaration, a strange C thing */
+struct task_struct;
+
+/*
+ * 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 - 4 + (void *)task_stack_page(p)) - 1)
+
+/* Free all resources held by a thread. */
+#define release_thread(thread) do { } while (0)
+
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)    do { } while (0)
+
+#define cpu_relax()	do { } while (0)
+
+/*
+ * Create a new kernel thread
+ */
+
+extern int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags);
+
+#define copy_segments(tsk, mm)      do { } while (0)
+#define release_segments(mm)        do { } while (0)
+
+#define KSTK_EIP(tsk)   (task_pt_regs(tsk)->ret)
+
+/*
+ * Where abouts of Task's sp, fp, blink when it was last seen in kernel mode.
+ * These can't be derived from pt_regs as that would give correp user-mode val
+ */
+#define KSTK_ESP(tsk)   (tsk->thread.ksp)
+#define KSTK_BLINK(tsk) (*((unsigned int *)((KSTK_ESP(tsk)) + (13+1+1)*4)))
+#define KSTK_FP(tsk)    (*((unsigned int *)((KSTK_ESP(tsk)) + (13+1)*4)))
+
+/*
+ * 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 unsigned int get_wchan(struct task_struct *p);
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ * Should the PC register be read instead ? This macro does not seem to
+ * be used in many places so this wont be all that bad.
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l; })
+
+#endif /* !__ASSEMBLY__ */
+
+/* Kernels Virtual memory area.
+ * Unlike other architectures(MIPS, sh, cris ) ARC 700 does not have a
+ * "kernel translated" region (like KSEG2 in MIPS). So we use a upper part
+ * of the translated bottom 2GB for kernel virtual memory and protect
+ * these pages from user accesses by disabling Ru, Eu and Wu.
+ */
+#define VMALLOC_SIZE	(0x10000000)	/* 256M */
+#define VMALLOC_START	(PAGE_OFFSET - VMALLOC_SIZE)
+#define VMALLOC_END	(PAGE_OFFSET)
+
+/* Most of the architectures seem to be keeping some kind of padding between
+ * userspace TASK_SIZE and PAGE_OFFSET. i.e TASK_SIZE != PAGE_OFFSET.
+ */
+#define USER_KERNEL_GUTTER    0x10000000
+
+/* User address space:
+ * On ARC700, CPU allows the entire lower half of 32 bit address space to be
+ * translated. Thus potentially 2G (0:0x7FFF_FFFF) could be User vaddr space.
+ * However we steal 256M for kernel addr (0x7000_0000:0x7FFF_FFFF) and another
+ * 256M (0x6000_0000:0x6FFF_FFFF) is gutter between user/kernel spaces
+ * Thus total User vaddr space is (0:0x5FFF_FFFF)
+ */
+#define TASK_SIZE	(PAGE_OFFSET - VMALLOC_SIZE - USER_KERNEL_GUTTER)
+
+#define STACK_TOP       TASK_SIZE
+#define STACK_TOP_MAX   STACK_TOP
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE      (TASK_SIZE / 3)
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_ARC_PROCESSOR_H */
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
new file mode 100644
index 0000000..561c7eb
--- /dev/null
+++ b/arch/arc/include/asm/ptrace.h
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ *
+ * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
+ */
+
+#ifndef __ASM_ARC_PTRACE_H
+#define __ASM_ARC_PTRACE_H
+
+/*
+ * XXX: ABI hack.
+ * The offset calc can be cleanly done in asm-offset.c, however gdb includes
+ * this header directly.
+ */
+#define PT_bta		4
+#define PT_lp_start	8
+#define PT_lp_end	12
+#define PT_lp_count	16
+#define PT_status32	20
+#define PT_ret		24
+#define PT_blink	28
+#define PT_fp		32
+#define PT_r26		36
+#define PT_r12		40
+#define PT_r11		44
+#define PT_r10		48
+#define PT_r9		52
+#define PT_r8		56
+#define PT_r7		60
+#define PT_r6		64
+#define PT_r5		68
+#define PT_r4		72
+#define PT_r3		76
+#define PT_r2		80
+#define PT_r1		84
+#define PT_r0		88
+#define PT_sp		92
+#define PT_orig_r0	96
+#define PT_orig_r8	100
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+/* THE pt_regs: Defines how regs are saved during entry into kernel */
+
+struct pt_regs {
+	/*
+	 * 1 word gutter after reg-file has been saved
+	 * Technically not needed, Since SP always points to a "full" location
+	 * (vs. "empty"). But pt_regs is shared with tools....
+	 */
+	long res;
+
+	/* Real registers */
+	long bta;	/* bta_l1, bta_l2, erbta */
+	long lp_start;
+	long lp_end;
+	long lp_count;
+	long status32;	/* status32_l1, status32_l2, erstatus */
+	long ret;	/* ilink1, ilink2 or eret */
+	long blink;
+	long fp;
+	long r26;	/* gp */
+	long r12;
+	long r11;
+	long r10;
+	long r9;
+	long r8;
+	long r7;
+	long r6;
+	long r5;
+	long r4;
+	long r3;
+	long r2;
+	long r1;
+	long r0;
+	long sp;	/* user/kernel sp depending on where we came from  */
+	long orig_r0;
+	long orig_r8;	/*to distinguish bet excp, sys call, int1 or int2 */
+};
+
+/* Callee saved registers - need to be saved only when you are scheduled out */
+
+struct callee_regs {
+	long res;	/* Again this is not needed */
+	long r25;
+	long r24;
+	long r23;
+	long r22;
+	long r21;
+	long r20;
+	long r19;
+	long r18;
+	long r17;
+	long r16;
+	long r15;
+	long r14;
+	long r13;
+};
+
+/* User mode registers, used for core dumps. */
+struct user_regs_struct {
+	struct pt_regs scratch;
+	struct callee_regs callee;
+	long efa;	/* break pt addr, for break points in delay slots */
+	long stop_pc;	/* give dbg stop_pc directly after checking orig_r8 */
+};
+
+#define instruction_pointer(regs)	((regs)->ret)
+#define profile_pc(regs)		instruction_pointer(regs)
+
+/* return 1 if user mode or 0 if kernel mode */
+#define user_mode(regs) (regs->status32 & STATUS_U_MASK)
+
+#define user_stack_pointer(regs)\
+({  unsigned int sp;		\
+	if (user_mode(regs))	\
+		sp = (regs)->sp;\
+	else			\
+		sp = -1;	\
+	sp;			\
+})
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_PTRACE_H */
diff --git a/arch/arc/include/asm/sections.h b/arch/arc/include/asm/sections.h
new file mode 100644
index 0000000..fc15f2e
--- /dev/null
+++ b/arch/arc/include/asm/sections.h
@@ -0,0 +1,17 @@
+/*
+ * 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_ARC_SECTIONS_H
+#define _ASM_ARC_SECTIONS_H
+
+#include <asm-generic/sections.h>
+
+extern char _int_vec_base_lds[];
+extern char __arc_dccm_base[];
+
+#endif
diff --git a/arch/arc/include/asm/thread_info.h b/arch/arc/include/asm/thread_info.h
new file mode 100644
index 0000000..2d50a4c
--- /dev/null
+++ b/arch/arc/include/asm/thread_info.h
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ *
+ * Vineetg: Oct 2009
+ *  No need for ARC specific thread_info allocator (kmalloc/free). This is
+ *  anyways one page allocation, thus slab alloc can be short-circuited and
+ *  the generic version (get_free_page) would be loads better.
+ *
+ * Sameer Dhavale: Codito Technologies 2004
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#include <asm/page.h>
+
+#ifdef CONFIG_16KSTACKS
+#define THREAD_SIZE_ORDER 1
+#else
+#define THREAD_SIZE_ORDER 0
+#endif
+
+#define THREAD_SIZE     (PAGE_SIZE << THREAD_SIZE_ORDER)
+
+#ifndef __ASSEMBLY__
+
+#include <linux/thread_info.h>
+#include <asm/segment.h>
+
+/*
+ * low level task data that entry.S needs immediate access to
+ * - this struct should fit entirely inside of one cache line
+ * - this struct shares the supervisor stack pages
+ * - if the contents of this structure are changed, the assembly constants
+ *   must also be changed
+ */
+struct thread_info {
+	unsigned long flags;		/* low level flags */
+	int preempt_count;		/* 0 => preemptable, <0 => BUG */
+	struct task_struct *task;	/* main task structure */
+	mm_segment_t addr_limit;	/* thread address space */
+	struct exec_domain *exec_domain;/* execution domain */
+	__u32 cpu;			/* current CPU */
+	unsigned long thr_ptr;		/* TLS ptr */
+	struct restart_block restart_block;
+};
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ *
+ * preempt_count needs to be 1 initially, until the scheduler is functional.
+ */
+#define INIT_THREAD_INFO(tsk)			\
+{						\
+	.task       = &tsk,			\
+	.exec_domain    = &default_exec_domain,	\
+	.flags      = 0,			\
+	.cpu        = 0,			\
+	.preempt_count  = INIT_PREEMPT_COUNT,	\
+	.addr_limit = KERNEL_DS,		\
+	.restart_block  = {			\
+		.fn = do_no_restart_syscall,	\
+	},					\
+}
+
+#define init_thread_info    (init_thread_union.thread_info)
+#define init_stack          (init_thread_union.stack)
+
+static inline __attribute_const__ struct thread_info *current_thread_info(void)
+{
+	register unsigned long sp asm("sp");
+	return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#define PREEMPT_ACTIVE      0x10000000
+
+/*
+ * thread information flags
+ * - these are process state flags that various assembly files may need to
+ *   access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+#define TIF_RESTORE_SIGMASK	0	/* restore sig mask in do_signal() */
+#define TIF_NOTIFY_RESUME	1	/* resumption notification requested */
+#define TIF_SIGPENDING		2	/* signal pending */
+#define TIF_NEED_RESCHED	3	/* rescheduling necessary */
+#define TIF_SYSCALL_AUDIT	4	/* syscall auditing active */
+#define TIF_SYSCALL_TRACE	15	/* syscall trace active */
+
+/* true if poll_idle() is polling TIF_NEED_RESCHED */
+#define TIF_MEMDIE		16
+
+#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
+#define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
+#define _TIF_MEMDIE		(1<<TIF_MEMDIE)
+
+/* work to do on interrupt/exception return */
+#define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
+				 _TIF_NOTIFY_RESUME)
+
+/*
+ * _TIF_ALLWORK_MASK includes SYSCALL_TRACE, but we don't need it.
+ * SYSCALL_TRACE is anways seperately/unconditionally tested right after a
+ * syscall, so all that reamins to be tested is _TIF_WORK_MASK
+ */
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_THREAD_INFO_H */
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 17/71] ARC: Syscall support (no-legacy-syscall ABI)
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (3 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 11/71] ARC: Fundamental ARCH data-types/defines Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 18/71] ARC: Process-creation/scheduling/idle-loop Vineet Gupta
                   ` (20 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta, Al Viro

This includes support for generic clone/for/vfork/execve

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
 arch/arc/Kconfig                |    1 +
 arch/arc/include/asm/ptrace.h   |    5 +++
 arch/arc/include/asm/syscall.h  |   72 +++++++++++++++++++++++++++++++++++++++
 arch/arc/include/asm/syscalls.h |   29 +++++++++++++++
 arch/arc/include/asm/unistd.h   |   34 ++++++++++++++++++
 arch/arc/kernel/entry.S         |   27 ++++++++++++++
 arch/arc/kernel/process.c       |   42 ++++++++++++++++++++++
 arch/arc/kernel/sys.c           |   18 ++++++++++
 8 files changed, 228 insertions(+), 0 deletions(-)
 create mode 100644 arch/arc/include/asm/syscall.h
 create mode 100644 arch/arc/include/asm/syscalls.h
 create mode 100644 arch/arc/include/asm/unistd.h
 create mode 100644 arch/arc/kernel/process.c
 create mode 100644 arch/arc/kernel/sys.c

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index b0b09ae..8789de1 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -9,6 +9,7 @@
 config ARC
 	def_bool y
 	select ARCH_NO_VIRT_TO_BUS
+	select CLONE_BACKWARDS
 	# ARC Busybox based initramfs absolutely relies on DEVTMPFS for /dev
 	select DEVTMPFS if !INITRAMFS_SOURCE=""
 	select GENERIC_ATOMIC64
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
index 561c7eb..9abbb7c 100644
--- a/arch/arc/include/asm/ptrace.h
+++ b/arch/arc/include/asm/ptrace.h
@@ -125,6 +125,11 @@ struct user_regs_struct {
 		sp = -1;	\
 	sp;			\
 })
+
+/* return 1 if in syscall, 0 if Intr or Exception */
+#define in_syscall(regs) (((regs->orig_r8) >= 0 && \
+			   (regs->orig_r8 <= NR_syscalls)) ? 1 : 0)
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
diff --git a/arch/arc/include/asm/syscall.h b/arch/arc/include/asm/syscall.h
new file mode 100644
index 0000000..33ab304
--- /dev/null
+++ b/arch/arc/include/asm/syscall.h
@@ -0,0 +1,72 @@
+/*
+ * 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_ARC_SYSCALL_H
+#define _ASM_ARC_SYSCALL_H  1
+
+#include <linux/err.h>
+#include <linux/sched.h>
+#include <asm/unistd.h>
+#include <asm/ptrace.h>		/* in_syscall() */
+
+static inline long
+syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
+{
+	if (user_mode(regs) && in_syscall(regs))
+		return regs->orig_r8;
+	else
+		return -1;
+}
+
+static inline void
+syscall_rollback(struct task_struct *task, struct pt_regs *regs)
+{
+	/* XXX: I can't fathom how pt_regs->r8 will be clobbered ? */
+	regs->r8 = regs->orig_r8;
+}
+
+static inline long
+syscall_get_error(struct task_struct *task, struct pt_regs *regs)
+{
+	/* 0 if syscall succeeded, otherwise -Errorcode */
+	return IS_ERR_VALUE(regs->r0) ? regs->r0 : 0;
+}
+
+static inline long
+syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
+{
+	return regs->r0;
+}
+
+static inline void
+syscall_set_return_value(struct task_struct *task, struct pt_regs *regs,
+			 int error, long val)
+{
+	regs->r0 = (long) error ?: val;
+}
+
+/*
+ * @i:      argument index [0,5]
+ * @n:      number of arguments; n+i must be [1,6].
+ */
+static inline void
+syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
+		      unsigned int i, unsigned int n, unsigned long *args)
+{
+	unsigned long *inside_ptregs = &(regs->r0);
+	inside_ptregs -= i;
+
+	BUG_ON((i + n) > 6);
+
+	while (n--) {
+		args[i++] = (*inside_ptregs);
+		inside_ptregs--;
+	}
+}
+
+#endif
diff --git a/arch/arc/include/asm/syscalls.h b/arch/arc/include/asm/syscalls.h
new file mode 100644
index 0000000..e53a534
--- /dev/null
+++ b/arch/arc/include/asm/syscalls.h
@@ -0,0 +1,29 @@
+/*
+ * 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_ARC_SYSCALLS_H
+#define _ASM_ARC_SYSCALLS_H  1
+
+#ifdef __KERNEL__
+
+#include <linux/compiler.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+
+int sys_clone_wrapper(int, int, int, int, int);
+int sys_fork_wrapper(void);
+int sys_vfork_wrapper(void);
+int sys_cacheflush(uint32_t, uint32_t uint32_t);
+int sys_arc_settls(void *);
+int sys_arc_gettls(void);
+
+#include <asm-generic/syscalls.h>
+
+#endif	/* __KERNEL__ */
+
+#endif
diff --git a/arch/arc/include/asm/unistd.h b/arch/arc/include/asm/unistd.h
new file mode 100644
index 0000000..6f30484
--- /dev/null
+++ b/arch/arc/include/asm/unistd.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+/******** no-legacy-syscalls-ABI *******/
+
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_VFORK
+#define __ARCH_WANT_SYS_FORK
+
+#define sys_mmap2 sys_mmap_pgoff
+
+#include <asm-generic/unistd.h>
+
+#define NR_syscalls	__NR_syscalls
+
+/* ARC specific syscall */
+#define __NR_cacheflush		(__NR_arch_specific_syscall + 0)
+#define __NR_arc_settls		(__NR_arch_specific_syscall + 1)
+#define __NR_arc_gettls		(__NR_arch_specific_syscall + 2)
+
+__SYSCALL(__NR_cacheflush, sys_cacheflush)
+__SYSCALL(__NR_arc_settls, sys_arc_settls)
+__SYSCALL(__NR_arc_gettls, sys_arc_gettls)
+
+
+/* Generic syscall (fs/filesystems.c - lost in asm-generic/unistd.h */
+#define __NR_sysfs		(__NR_arch_specific_syscall + 3)
+__SYSCALL(__NR_sysfs, sys_sysfs)
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index a4acc9e..0b0a190 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -569,3 +569,30 @@ ARC_ENTRY ret_from_fork
 	bl  @schedule_tail
 	b @ret_from_exception
 ARC_EXIT ret_from_fork
+
+;################### Special Sys Call Wrappers ##########################
+
+; TBD: call do_fork directly from here
+ARC_ENTRY sys_fork_wrapper
+	SAVE_CALLEE_SAVED_USER
+	bl  @sys_fork
+	DISCARD_CALLEE_SAVED_USER
+
+	b ret_from_system_call
+ARC_EXIT sys_fork_wrapper
+
+ARC_ENTRY sys_vfork_wrapper
+	SAVE_CALLEE_SAVED_USER
+	bl  @sys_vfork
+	DISCARD_CALLEE_SAVED_USER
+
+	b ret_from_system_call
+ARC_EXIT sys_vfork_wrapper
+
+ARC_ENTRY sys_clone_wrapper
+	SAVE_CALLEE_SAVED_USER
+	bl  @sys_clone
+	DISCARD_CALLEE_SAVED_USER
+
+	b ret_from_system_call
+ARC_EXIT sys_clone_wrapper
diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c
new file mode 100644
index 0000000..4d14e56
--- /dev/null
+++ b/arch/arc/kernel/process.c
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ *
+ * Amit Bhor, Kanika Nema: Codito Technologies 2004
+ */
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/elf.h>
+#include <linux/tick.h>
+
+SYSCALL_DEFINE1(arc_settls, void *, user_tls_data_ptr)
+{
+	task_thread_info(current)->thr_ptr = (unsigned int)user_tls_data_ptr;
+	return 0;
+}
+
+/*
+ * We return the user space TLS data ptr as sys-call return code
+ * Ideally it should be copy to user.
+ * However we can cheat by the fact that some sys-calls do return
+ * absurdly high values
+ * Since the tls dat aptr is not going to be in range of 0xFFFF_xxxx
+ * it won't be considered a sys-call error
+ * and it will be loads better than copy-to-user, which is a definite
+ * D-TLB Miss
+ */
+SYSCALL_DEFINE0(arc_gettls)
+{
+	return task_thread_info(current)->thr_ptr;
+}
diff --git a/arch/arc/kernel/sys.c b/arch/arc/kernel/sys.c
new file mode 100644
index 0000000..f6bdd07
--- /dev/null
+++ b/arch/arc/kernel/sys.c
@@ -0,0 +1,18 @@
+
+#include <linux/syscalls.h>
+#include <linux/signal.h>
+#include <linux/unistd.h>
+
+#include <asm/syscalls.h>
+
+#define sys_clone	sys_clone_wrapper
+#define sys_fork	sys_fork_wrapper
+#define sys_vfork	sys_vfork_wrapper
+
+#undef __SYSCALL
+#define __SYSCALL(nr, call) [nr] = (call),
+
+void *sys_call_table[NR_syscalls] = {
+	[0 ... NR_syscalls-1] = sys_ni_syscall,
+#include <asm/unistd.h>
+};
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 18/71] ARC: Process-creation/scheduling/idle-loop
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (4 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 17/71] ARC: Syscall support (no-legacy-syscall ABI) Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 19/71] ARC: Timers/counters/delay management Vineet Gupta
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta, Al Viro, Thomas Gleixner

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Thomas Gleixner <tglx@linutronix.de>
---
 arch/arc/Kconfig                 |    2 +
 arch/arc/include/asm/arcregs.h   |   20 ++++
 arch/arc/include/asm/processor.h |    9 +-
 arch/arc/include/asm/ptrace.h    |    8 ++
 arch/arc/include/asm/switch_to.h |   41 ++++++++
 arch/arc/kernel/ctx_sw.c         |   91 ++++++++++++++++++
 arch/arc/kernel/ctx_sw_asm.S     |   58 +++++++++++
 arch/arc/kernel/entry.S          |   15 +++-
 arch/arc/kernel/fpu.c            |   55 +++++++++++
 arch/arc/kernel/process.c        |  193 ++++++++++++++++++++++++++++++++++++++
 10 files changed, 484 insertions(+), 8 deletions(-)
 create mode 100644 arch/arc/include/asm/switch_to.h
 create mode 100644 arch/arc/kernel/ctx_sw.c
 create mode 100644 arch/arc/kernel/ctx_sw_asm.S
 create mode 100644 arch/arc/kernel/fpu.c

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 8789de1..a4e9806 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -17,6 +17,8 @@ config ARC
 	select GENERIC_FIND_FIRST_BIT
 	# for now, we don't need GENERIC_IRQ_PROBE, CONFIG_GENERIC_IRQ_CHIP
 	select GENERIC_IRQ_SHOW
+	select GENERIC_KERNEL_EXECVE
+	select GENERIC_KERNEL_THREAD
 	select GENERIC_PENDING_IRQ if SMP
 	select GENERIC_SMP_IDLE_THREAD
 	select HAVE_GENERIC_HARDIRQS
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index 3fccb04..d764118 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -47,6 +47,17 @@
 #define AUX_ITRIGGER		0x40d
 #define AUX_IPULSE		0x415
 
+/*
+ * Floating Pt Registers
+ * Status regs are read-only (build-time) so need not be saved/restored
+ */
+#define ARC_AUX_FP_STAT         0x300
+#define ARC_AUX_DPFP_1L         0x301
+#define ARC_AUX_DPFP_1H         0x302
+#define ARC_AUX_DPFP_2L         0x303
+#define ARC_AUX_DPFP_2H         0x304
+#define ARC_AUX_DPFP_STAT       0x305
+
 #ifndef __ASSEMBLY__
 
 /*
@@ -110,6 +121,15 @@
 
 #endif
 
+#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
+/* These DPFP regs need to be saved/restored across ctx-sw */
+struct arc_fpu {
+	struct {
+		unsigned int l, h;
+	} aux_dpfp[2];
+};
+#endif
+
 #endif /* __ASEMBLY__ */
 
 #endif /* __KERNEL__ */
diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h
index bf88cfb..860252e 100644
--- a/arch/arc/include/asm/processor.h
+++ b/arch/arc/include/asm/processor.h
@@ -29,6 +29,9 @@ struct thread_struct {
 	unsigned long callee_reg;	/* pointer to callee regs */
 	unsigned long fault_address;	/* dbls as brkpt holder as well */
 	unsigned long cause_code;	/* Exception Cause Code (ECR) */
+#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
+	struct arc_fpu fpu;
+#endif
 };
 
 #define INIT_THREAD  {                          \
@@ -54,12 +57,6 @@ unsigned long thread_saved_pc(struct task_struct *t);
 
 #define cpu_relax()	do { } while (0)
 
-/*
- * Create a new kernel thread
- */
-
-extern int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags);
-
 #define copy_segments(tsk, mm)      do { } while (0)
 #define release_segments(mm)        do { } while (0)
 
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
index 9abbb7c..72754a2 100644
--- a/arch/arc/include/asm/ptrace.h
+++ b/arch/arc/include/asm/ptrace.h
@@ -130,6 +130,14 @@ struct user_regs_struct {
 #define in_syscall(regs) (((regs->orig_r8) >= 0 && \
 			   (regs->orig_r8 <= NR_syscalls)) ? 1 : 0)
 
+#define current_pt_regs()					\
+({								\
+	/* open-coded current_thread_info() */			\
+	register unsigned long sp asm ("sp");			\
+	unsigned long pg_start = (sp & ~(THREAD_SIZE - 1));	\
+	(struct pt_regs *)(pg_start + THREAD_SIZE - 4) - 1;	\
+})
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
diff --git a/arch/arc/include/asm/switch_to.h b/arch/arc/include/asm/switch_to.h
new file mode 100644
index 0000000..1b171ab
--- /dev/null
+++ b/arch/arc/include/asm/switch_to.h
@@ -0,0 +1,41 @@
+/*
+ * 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_ARC_SWITCH_TO_H
+#define _ASM_ARC_SWITCH_TO_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/sched.h>
+
+#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
+
+extern void fpu_save_restore(struct task_struct *p, struct task_struct *n);
+#define ARC_FPU_PREV(p, n)	fpu_save_restore(p, n)
+#define ARC_FPU_NEXT(t)
+
+#else
+
+#define ARC_FPU_PREV(p, n)
+#define ARC_FPU_NEXT(n)
+
+#endif /* !CONFIG_ARC_FPU_SAVE_RESTORE */
+
+struct task_struct *__switch_to(struct task_struct *p, struct task_struct *n);
+
+#define switch_to(prev, next, last)	\
+do {					\
+	ARC_FPU_PREV(prev, next);	\
+	last = __switch_to(prev, next);\
+	ARC_FPU_NEXT(next);		\
+	mb();				\
+} while (0)
+
+#endif
+
+#endif
diff --git a/arch/arc/kernel/ctx_sw.c b/arch/arc/kernel/ctx_sw.c
new file mode 100644
index 0000000..647e37a
--- /dev/null
+++ b/arch/arc/kernel/ctx_sw.c
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ *
+ * Vineetg: Aug 2009
+ *  -"C" version of lowest level context switch asm macro called by schedular
+ *   gcc doesn't generate the dward CFI info for hand written asm, hence can't
+ *   backtrace out of it (e.g. tasks sleeping in kernel).
+ *   So we cheat a bit by writing almost similar code in inline-asm.
+ *  -This is a hacky way of doing things, but there is no other simple way.
+ *   I don't want/intend to extend unwinding code to understand raw asm
+ */
+
+#include <asm/asm-offsets.h>
+#include <linux/sched.h>
+
+struct task_struct *__sched
+__switch_to(struct task_struct *prev_task, struct task_struct *next_task)
+{
+	unsigned int tmp;
+	unsigned int prev = (unsigned int)prev_task;
+	unsigned int next = (unsigned int)next_task;
+	int num_words_to_skip = 1;
+
+	__asm__ __volatile__(
+		/* FP/BLINK save generated by gcc (standard function prologue */
+		"st.a    r13, [sp, -4]   \n\t"
+		"st.a    r14, [sp, -4]   \n\t"
+		"st.a    r15, [sp, -4]   \n\t"
+		"st.a    r16, [sp, -4]   \n\t"
+		"st.a    r17, [sp, -4]   \n\t"
+		"st.a    r18, [sp, -4]   \n\t"
+		"st.a    r19, [sp, -4]   \n\t"
+		"st.a    r20, [sp, -4]   \n\t"
+		"st.a    r21, [sp, -4]   \n\t"
+		"st.a    r22, [sp, -4]   \n\t"
+		"st.a    r23, [sp, -4]   \n\t"
+		"st.a    r24, [sp, -4]   \n\t"
+		"st.a    r25, [sp, -4]   \n\t"
+		"sub     sp, sp, %4      \n\t"	/* create gutter at top */
+
+		/* set ksp of outgoing task in tsk->thread.ksp */
+		"st.as   sp, [%3, %1]    \n\t"
+
+		"sync   \n\t"
+
+		/*
+		 * setup _current_task with incoming tsk.
+		 * optionally, set r25 to that as well
+		 * For SMP extra work to get to &_current_task[cpu]
+		 * (open coded SET_CURR_TASK_ON_CPU)
+		 */
+		"st  %2, [@_current_task]	\n\t"
+
+		/* get ksp of incoming task from tsk->thread.ksp */
+		"ld.as  sp, [%2, %1]   \n\t"
+
+		/* start loading it's CALLEE reg file */
+
+		"add    sp, sp, %4     \n\t"	/* skip gutter at top */
+
+		"ld.ab   r25, [sp, 4]   \n\t"
+		"ld.ab   r24, [sp, 4]   \n\t"
+		"ld.ab   r23, [sp, 4]   \n\t"
+		"ld.ab   r22, [sp, 4]   \n\t"
+		"ld.ab   r21, [sp, 4]   \n\t"
+		"ld.ab   r20, [sp, 4]   \n\t"
+		"ld.ab   r19, [sp, 4]   \n\t"
+		"ld.ab   r18, [sp, 4]   \n\t"
+		"ld.ab   r17, [sp, 4]   \n\t"
+		"ld.ab   r16, [sp, 4]   \n\t"
+		"ld.ab   r15, [sp, 4]   \n\t"
+		"ld.ab   r14, [sp, 4]   \n\t"
+		"ld.ab   r13, [sp, 4]   \n\t"
+
+		/* last (ret value) = prev : although for ARC it mov r0, r0 */
+		"mov     %0, %3        \n\t"
+
+		/* FP/BLINK restore generated by gcc (standard func epilogue */
+
+		: "=r"(tmp)
+		: "n"((TASK_THREAD + THREAD_KSP) / 4), "r"(next), "r"(prev),
+		  "n"(num_words_to_skip * 4)
+		: "blink"
+	);
+
+	return (struct task_struct *)tmp;
+}
diff --git a/arch/arc/kernel/ctx_sw_asm.S b/arch/arc/kernel/ctx_sw_asm.S
new file mode 100644
index 0000000..d897234
--- /dev/null
+++ b/arch/arc/kernel/ctx_sw_asm.S
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ *
+ * Vineetg: Aug 2009
+ *  -Moved core context switch macro out of entry.S into this file.
+ *  -This is the more "natural" hand written assembler
+ */
+
+#include <asm/entry.h>       /* For the SAVE_* macros */
+#include <asm/asm-offsets.h>
+#include <asm/linkage.h>
+
+;################### Low Level Context Switch ##########################
+
+	.section .sched.text,"ax",@progbits
+	.align 4
+	.global __switch_to
+	.type   __switch_to, @function
+__switch_to:
+
+	/* Save regs on kernel mode stack of task */
+	st.a    blink, [sp, -4]
+	st.a    fp, [sp, -4]
+	SAVE_CALLEE_SAVED_KERNEL
+
+	/* Save the now KSP in task->thread.ksp */
+	st.as  sp, [r0, (TASK_THREAD + THREAD_KSP)/4]
+
+	/*
+	* Return last task in r0 (return reg)
+	* On ARC, Return reg = First Arg reg = r0.
+	* Since we already have last task in r0,
+	* don't need to do anything special to return it
+	*/
+
+	/* hardware memory barrier */
+	sync
+
+	/*
+	 * switch to new task, contained in r1
+	 * Temp reg r3 is required to get the ptr to store val
+	 */
+	SET_CURR_TASK_ON_CPU  r1, r3
+
+	/* reload SP with kernel mode stack pointer in task->thread.ksp */
+	ld.as  sp, [r1, (TASK_THREAD + THREAD_KSP)/4]
+
+	/* restore the registers */
+	RESTORE_CALLEE_SAVED_KERNEL
+	ld.ab   fp, [sp, 4]
+	ld.ab   blink, [sp, 4]
+	j       [blink]
+
+ARC_EXIT __switch_to
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index 0b0a190..ed08ac1 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -566,8 +566,19 @@ ARC_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
-	b @ret_from_exception
+	bl   @schedule_tail
+
+	; If kernel thread, jump to it's entry-point
+	ld   r9, [sp, PT_status32]
+	brne r9, 0, 1f
+
+	jl.d [r14]
+	mov  r0, r13		; arg to payload
+
+1:
+	; 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
 
 ;################### Special Sys Call Wrappers ##########################
diff --git a/arch/arc/kernel/fpu.c b/arch/arc/kernel/fpu.c
new file mode 100644
index 0000000..f352e51
--- /dev/null
+++ b/arch/arc/kernel/fpu.c
@@ -0,0 +1,55 @@
+/*
+ * fpu.c - save/restore of Floating Point Unit Registers on task switch
+ *
+ * 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.
+ */
+
+#include <linux/sched.h>
+#include <asm/switch_to.h>
+
+/*
+ * To save/restore FPU regs, simplest scheme would use LR/SR insns.
+ * However since SR serializes the pipeline, an alternate "hack" can be used
+ * which uses the FPU Exchange insn (DEXCL) to r/w FPU regs.
+ *
+ * Store to 64bit dpfp1 reg from a pair of core regs:
+ *   dexcl1 0, r1, r0  ; where r1:r0 is the 64 bit val
+ *
+ * Read from dpfp1 into pair of core regs (w/o clobbering dpfp1)
+ *   mov_s    r3, 0
+ *   daddh11  r1, r3, r3   ; get "hi" into r1 (dpfp1 unchanged)
+ *   dexcl1   r0, r1, r3   ; get "low" into r0 (dpfp1 low clobbered)
+ *   dexcl1    0, r1, r0   ; restore dpfp1 to orig value
+ *
+ * However we can tweak the read, so that read-out of outgoing task's FPU regs
+ * and write of incoming task's regs happen in one shot. So all the work is
+ * done before context switch
+ */
+
+void fpu_save_restore(struct task_struct *prev, struct task_struct *next)
+{
+	unsigned int *saveto = &prev->thread.fpu.aux_dpfp[0].l;
+	unsigned int *readfrom = &next->thread.fpu.aux_dpfp[0].l;
+
+	const unsigned int zero = 0;
+
+	__asm__ __volatile__(
+		"daddh11  %0, %2, %2\n"
+		"dexcl1   %1, %3, %4\n"
+		: "=&r" (*(saveto + 1)), /* early clobber must here */
+		  "=&r" (*(saveto))
+		: "r" (zero), "r" (*(readfrom + 1)), "r" (*(readfrom))
+	);
+
+	__asm__ __volatile__(
+		"daddh22  %0, %2, %2\n"
+		"dexcl2   %1, %3, %4\n"
+		: "=&r"(*(saveto + 3)),	/* early clobber must here */
+		  "=&r"(*(saveto + 2))
+		: "r" (zero), "r" (*(readfrom + 3)), "r" (*(readfrom + 2))
+	);
+}
diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c
index 4d14e56..279e080 100644
--- a/arch/arc/kernel/process.c
+++ b/arch/arc/kernel/process.c
@@ -40,3 +40,196 @@ SYSCALL_DEFINE0(arc_gettls)
 {
 	return task_thread_info(current)->thr_ptr;
 }
+
+static inline void arch_idle(void)
+{
+	/* sleep, but enable all interrupts before committing */
+	__asm__("sleep 0x3");
+}
+
+void cpu_idle(void)
+{
+	/* Since we SLEEP in idle loop, TIF_POLLING_NRFLAG can't be set */
+
+	/* endless idle loop with no priority at all */
+	while (1) {
+		tick_nohz_idle_enter();
+		rcu_idle_enter();
+
+doze:
+		local_irq_disable();
+		if (!need_resched()) {
+			arch_idle();
+			goto doze;
+		} else {
+			local_irq_enable();
+		}
+
+		rcu_idle_exit();
+		tick_nohz_idle_exit();
+
+		schedule_preempt_disabled();
+	}
+}
+
+asmlinkage void ret_from_fork(void);
+
+/* Layout of Child kernel mode stack as setup at the end of this function is
+ *
+ * |     ...        |
+ * |     ...        |
+ * |    unused      |
+ * |                |
+ * ------------------  <==== top of Stack (thread.ksp)
+ * |   UNUSED 1 word|
+ * ------------------
+ * |     r25        |
+ * ~                ~
+ * |    --to--      |   (CALLEE Regs of user mode)
+ * |     r13        |
+ * ------------------
+ * |     fp         |
+ * |    blink       |   @ret_from_fork
+ * ------------------
+ * |                |
+ * ~                ~
+ * ~                ~
+ * |                |
+ * ------------------
+ * |     r12        |
+ * ~                ~
+ * |    --to--      |   (scratch Regs of user mode)
+ * |     r0         |
+ * ------------------
+ * |   UNUSED 1 word|
+ * ------------------  <===== END of PAGE
+ */
+int copy_thread(unsigned long clone_flags,
+		unsigned long usp, unsigned long arg,
+		struct task_struct *p)
+{
+	struct pt_regs *c_regs;        /* child's pt_regs */
+	unsigned long *childksp;       /* to unwind out of __switch_to() */
+	struct callee_regs *c_callee;  /* child's callee regs */
+	struct callee_regs *parent_callee;  /* paren't callee */
+	struct pt_regs *regs = current_pt_regs();
+
+	/* Mark the specific anchors to begin with (see pic above) */
+	c_regs = task_pt_regs(p);
+	childksp = (unsigned long *)c_regs - 2;  /* 2 words for FP/BLINK */
+	c_callee = ((struct callee_regs *)childksp) - 1;
+
+	/*
+	 * __switch_to() uses thread.ksp to start unwinding stack
+	 * For kernel threads we don't need to create callee regs, the
+	 * stack layout nevertheless needs to remain the same.
+	 * Also, since __switch_to anyways unwinds callee regs, we use
+	 * this to populate kernel thread entry-pt/args into callee regs,
+	 * so that ret_from_kernel_thread() becomes simpler.
+	 */
+	p->thread.ksp = (unsigned long)c_callee;	/* THREAD_KSP */
+
+	/* __switch_to expects FP(0), BLINK(return addr) at top */
+	childksp[0] = 0;			/* fp */
+	childksp[1] = (unsigned long)ret_from_fork; /* blink */
+
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		memset(c_regs, 0, sizeof(struct pt_regs));
+
+		c_callee->r13 = arg; /* argument to kernel thread */
+		c_callee->r14 = usp;  /* function */
+
+		return 0;
+	}
+
+	/*--------- User Task Only --------------*/
+
+	/* __switch_to expects FP(0), BLINK(return addr) at top of stack */
+	childksp[0] = 0;				/* for POP fp */
+	childksp[1] = (unsigned long)ret_from_fork;	/* for POP blink */
+
+	/* Copy parents pt regs on child's kernel mode stack */
+	*c_regs = *regs;
+
+	if (usp)
+		c_regs->sp = usp;
+
+	c_regs->r0 = 0;		/* fork returns 0 in child */
+
+	parent_callee = ((struct callee_regs *)regs) - 1;
+	*c_callee = *parent_callee;
+
+	if (unlikely(clone_flags & CLONE_SETTLS)) {
+		/*
+		 * set task's userland tls data ptr from 4th arg
+		 * clone C-lib call is difft from clone sys-call
+		 */
+		task_thread_info(p)->thr_ptr = regs->r3;
+	} else {
+		/* Normal fork case: set parent's TLS ptr in child */
+		task_thread_info(p)->thr_ptr =
+		task_thread_info(current)->thr_ptr;
+	}
+
+	return 0;
+}
+
+/*
+ * Some archs flush debug and FPU info here
+ */
+void flush_thread(void)
+{
+}
+
+/*
+ * Free any architecture-specific thread data structures, etc.
+ */
+void exit_thread(void)
+{
+}
+
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
+{
+	return 0;
+}
+
+/*
+ * API: expected by schedular Code: If thread is sleeping where is that.
+ * What is this good for? it will be always the scheduler or ret_from_fork.
+ * So we hard code that anyways.
+ */
+unsigned long thread_saved_pc(struct task_struct *t)
+{
+	struct pt_regs *regs = task_pt_regs(t);
+	unsigned long blink = 0;
+
+	/*
+	 * If the thread being queried for in not itself calling this, then it
+	 * implies it is not executing, which in turn implies it is sleeping,
+	 * which in turn implies it got switched OUT by the schedular.
+	 * In that case, it's kernel mode blink can reliably retrieved as per
+	 * the picture above (right above pt_regs).
+	 */
+	if (t != current && t->state != TASK_RUNNING)
+		blink = *((unsigned int *)regs - 1);
+
+	return blink;
+}
+
+int elf_check_arch(const struct elf32_hdr *x)
+{
+	unsigned int eflags;
+
+	if (x->e_machine != EM_ARCOMPACT)
+		return 0;
+
+	eflags = x->e_flags;
+	if ((eflags & EF_ARC_OSABI_MSK) < EF_ARC_OSABI_V2) {
+		pr_err("ABI mismatch - you need newer toolchain\n");
+		force_sigsegv(SIGSEGV, current);
+		return 0;
+	}
+
+	return 1;
+}
+EXPORT_SYMBOL(elf_check_arch);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 19/71] ARC: Timers/counters/delay management
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (5 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 18/71] ARC: Process-creation/scheduling/idle-loop Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 20/71] ARC: Signal handling Vineet Gupta
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta, Thomas Gleixner

ARC700 includes 2 in-core 32bit timers TIMER0 and TIMER1.
Both have exactly same capabilies.

* programmable to count from TIMER<n>_CNT to TIMER<n>_LIMIT
* for count 0 and LIMIT ~1, provides a free-running counter by
    auto-wrapping when limit is reached.
* optionally interrupt when LIMIT is reached (oneshot event semantics)
* rearming the interrupt provides periodic semantics
* run at CPU clk

ARC Linux uses TIMER0 for clockevent (periodic/oneshot) and TIMER1 for
clocksource (free-running clock).

Newer cores provide RTSC insn which gives a 64bit cpu clk snapshot hence
is more apt for clocksource when available.

SMP poses a bit of challenge for global timekeeping clocksource /
sched_clock() backend:
 -TIMER1 based local clocks are out-of-sync hence can't be used
  (thus we default to jiffies based cs as well as sched_clock() one/both
  of which platform can override with it's specific hardware assist)
 -RTSC is only allowed in SMP if it's cross-core-sync (Kconfig glue
  ensures that) and thus usable for both requirements.

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
---
 arch/arc/include/asm/arcregs.h |   11 ++
 arch/arc/include/asm/clk.h     |   20 +++
 arch/arc/include/asm/delay.h   |   68 +++++++++
 arch/arc/include/asm/irq.h     |    2 +
 arch/arc/include/asm/timex.h   |   18 +++
 arch/arc/kernel/clk.c          |   11 ++
 arch/arc/kernel/time.c         |  295 ++++++++++++++++++++++++++++++++++++++++
 7 files changed, 425 insertions(+), 0 deletions(-)
 create mode 100644 arch/arc/include/asm/clk.h
 create mode 100644 arch/arc/include/asm/delay.h
 create mode 100644 arch/arc/include/asm/timex.h
 create mode 100644 arch/arc/kernel/clk.c
 create mode 100644 arch/arc/kernel/time.c

diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index d764118..5131bb3 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -47,6 +47,17 @@
 #define AUX_ITRIGGER		0x40d
 #define AUX_IPULSE		0x415
 
+/* Timer related Aux registers */
+#define ARC_REG_TIMER0_LIMIT	0x23	/* timer 0 limit */
+#define ARC_REG_TIMER0_CTRL	0x22	/* timer 0 control */
+#define ARC_REG_TIMER0_CNT	0x21	/* timer 0 count */
+#define ARC_REG_TIMER1_LIMIT	0x102	/* timer 1 limit */
+#define ARC_REG_TIMER1_CTRL	0x101	/* timer 1 control */
+#define ARC_REG_TIMER1_CNT	0x100	/* timer 1 count */
+
+#define TIMER_CTRL_IE		(1 << 0) /* Interupt when Count reachs limit */
+#define TIMER_CTRL_NH		(1 << 1) /* Count only when CPU NOT halted */
+
 /*
  * Floating Pt Registers
  * Status regs are read-only (build-time) so need not be saved/restored
diff --git a/arch/arc/include/asm/clk.h b/arch/arc/include/asm/clk.h
new file mode 100644
index 0000000..6195643
--- /dev/null
+++ b/arch/arc/include/asm/clk.h
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_ARC_CLK_H
+#define _ASM_ARC_CLK_H
+
+/* Although we can't really hide core_freq, the accessor is still better way */
+extern unsigned long core_freq;
+
+static inline unsigned long arc_get_core_freq(void)
+{
+	return core_freq;
+}
+
+#endif
diff --git a/arch/arc/include/asm/delay.h b/arch/arc/include/asm/delay.h
new file mode 100644
index 0000000..442ce5d
--- /dev/null
+++ b/arch/arc/include/asm/delay.h
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ *
+ * Delay routines using pre computed loops_per_jiffy value.
+ *
+ * vineetg: Feb 2012
+ *  -Rewrote in "C" to avoid dealing with availability of H/w MPY
+ *  -Also reduced the num of MPY operations from 3 to 2
+ *
+ * Amit Bhor: Codito Technologies 2004
+ */
+
+#ifndef __ASM_ARC_UDELAY_H
+#define __ASM_ARC_UDELAY_H
+
+#include <asm/param.h>		/* HZ */
+
+static inline void __delay(unsigned long loops)
+{
+	__asm__ __volatile__(
+	"1:	sub.f %0, %0, 1	\n"
+	"	jpnz 1b		\n"
+	: "+r"(loops)
+	:
+	: "cc");
+}
+
+extern void __bad_udelay(void);
+
+/*
+ * Normal Math for computing loops in "N" usecs
+ *  -we have precomputed @loops_per_jiffy
+ *  -1 sec has HZ jiffies
+ * loops per "N" usecs = ((loops_per_jiffy * HZ / 1000000) * N)
+ *
+ * Approximate Division by multiplication:
+ *  -Mathematically if we multiply and divide a number by same value the
+ *   result remains unchanged:  In this case, we use 2^32
+ *  -> (loops_per_N_usec * 2^32 ) / 2^32
+ *  -> (((loops_per_jiffy * HZ / 1000000) * N) * 2^32) / 2^32
+ *  -> (loops_per_jiffy * HZ * N * 4295) / 2^32
+ *
+ *  -Divide by 2^32 is very simply right shift by 32
+ *  -We simply need to ensure that the multiply per above eqn happens in
+ *   64-bit precision (if CPU doesn't support it - gcc can emaulate it)
+ */
+
+static inline void __udelay(unsigned long usecs)
+{
+	unsigned long loops;
+
+	/* (long long) cast ensures 64 bit MPY - real or emulated
+	 * HZ * 4295 is pre-evaluated by gcc - hence only 2 mpy ops
+	 */
+	loops = ((long long)(usecs * 4295 * HZ) *
+		 (long long)(loops_per_jiffy)) >> 32;
+
+	__delay(loops);
+}
+
+#define udelay(n) (__builtin_constant_p(n) ? ((n) > 20000 ? __bad_udelay() \
+				: __udelay(n)) : __udelay(n))
+
+#endif /* __ASM_ARC_UDELAY_H */
diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h
index ca4aeba..514b302 100644
--- a/arch/arc/include/asm/irq.h
+++ b/arch/arc/include/asm/irq.h
@@ -19,4 +19,6 @@ extern void __init arc_init_IRQ(void);
 extern void __init plat_init_IRQ(void);
 extern int __init get_hw_config_num_irq(void);
 
+void __cpuinit arc_local_timer_setup(unsigned int cpu);
+
 #endif
diff --git a/arch/arc/include/asm/timex.h b/arch/arc/include/asm/timex.h
new file mode 100644
index 0000000..0a82960
--- /dev/null
+++ b/arch/arc/include/asm/timex.h
@@ -0,0 +1,18 @@
+/*
+ * 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_ARC_TIMEX_H
+#define _ASM_ARC_TIMEX_H
+
+#define CLOCK_TICK_RATE	80000000 /* slated to be removed */
+
+#include <asm-generic/timex.h>
+
+/* XXX: get_cycles() to be implemented with RTSC insn */
+
+#endif /* _ASM_ARC_TIMEX_H */
diff --git a/arch/arc/kernel/clk.c b/arch/arc/kernel/clk.c
new file mode 100644
index 0000000..64925db
--- /dev/null
+++ b/arch/arc/kernel/clk.c
@@ -0,0 +1,11 @@
+/*
+ * 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.
+ */
+
+#include <asm/clk.h>
+
+unsigned long core_freq = CONFIG_ARC_PLAT_CLK;
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
new file mode 100644
index 0000000..05dba11
--- /dev/null
+++ b/arch/arc/kernel/time.c
@@ -0,0 +1,295 @@
+/*
+ * 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.
+ *
+ * vineetg: Jan 1011
+ *  -sched_clock( ) no longer jiffies based. Uses the same clocksource
+ *   as gtod
+ *
+ * Rajeshwarr/Vineetg: Mar 2008
+ *  -Implemented CONFIG_GENERIC_TIME (rather deleted arch specific code)
+ *   for arch independent gettimeofday()
+ *  -Implemented CONFIG_GENERIC_CLOCKEVENTS as base for hrtimers
+ *
+ * Vineetg: Mar 2008: Forked off from time.c which now is time-jiff.c
+ */
+
+/* ARC700 has two 32bit independent prog Timers: TIMER0 and TIMER1
+ * Each can programmed to go from @count to @limit and optionally
+ * interrupt when that happens.
+ * A write to Control Register clears the Interrupt
+ *
+ * We've designated TIMER0 for events (clockevents)
+ * while TIMER1 for free running (clocksource)
+ *
+ * Newer ARC700 cores have 64bit clk fetching RTSC insn, preferred over TIMER1
+ */
+
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/timex.h>
+#include <linux/profile.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <asm/irq.h>
+#include <asm/arcregs.h>
+#include <asm/clk.h>
+
+#define ARC_TIMER_MAX	0xFFFFFFFF
+
+/********** Clock Source Device *********/
+
+#ifdef CONFIG_ARC_HAS_RTSC
+
+int __cpuinit arc_counter_setup(void)
+{
+	/* RTSC insn taps into cpu clk, needs no setup */
+
+	/* For SMP, only allowed if cross-core-sync, hence usable as cs */
+	return 1;
+}
+
+static cycle_t arc_counter_read(struct clocksource *cs)
+{
+	unsigned long flags;
+	union {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+		struct { u32 high, low; };
+#else
+		struct { u32 low, high; };
+#endif
+		cycle_t  full;
+	} stamp;
+
+	flags = arch_local_irq_save();
+
+	__asm__ __volatile(
+	"	.extCoreRegister tsch, 58,  r, cannot_shortcut	\n"
+	"	rtsc %0, 0	\n"
+	"	mov  %1, tsch	\n"	/* TSCH is extn core reg 58 */
+	: "=r" (stamp.low), "=r" (stamp.high));
+
+	arch_local_irq_restore(flags);
+
+	return stamp.full;
+}
+
+static struct clocksource arc_counter = {
+	.name   = "ARC RTSC",
+	.rating = 300,
+	.read   = arc_counter_read,
+	.mask   = CLOCKSOURCE_MASK(64),
+	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+#else /* !CONFIG_ARC_HAS_RTSC */
+
+static bool is_usable_as_clocksource(void)
+{
+#ifdef CONFIG_SMP
+	return 0;
+#else
+	return 1;
+#endif
+}
+
+/*
+ * set 32bit TIMER1 to keep counting monotonically and wraparound
+ */
+int __cpuinit arc_counter_setup(void)
+{
+	write_aux_reg(ARC_REG_TIMER1_LIMIT, ARC_TIMER_MAX);
+	write_aux_reg(ARC_REG_TIMER1_CNT, 0);
+	write_aux_reg(ARC_REG_TIMER1_CTRL, TIMER_CTRL_NH);
+
+	return is_usable_as_clocksource();
+}
+
+static cycle_t arc_counter_read(struct clocksource *cs)
+{
+	return (cycle_t) read_aux_reg(ARC_REG_TIMER1_CNT);
+}
+
+static struct clocksource arc_counter = {
+	.name   = "ARC Timer1",
+	.rating = 300,
+	.read   = arc_counter_read,
+	.mask   = CLOCKSOURCE_MASK(32),
+	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+#endif
+
+/********** Clock Event Device *********/
+
+/*
+ * Arm the timer to interrupt after @limit cycles
+ * The distinction for oneshot/periodic is done in arc_event_timer_ack() below
+ */
+static void arc_timer_event_setup(unsigned int limit)
+{
+	write_aux_reg(ARC_REG_TIMER0_LIMIT, limit);
+	write_aux_reg(ARC_REG_TIMER0_CNT, 0);	/* start from 0 */
+
+	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)
+{
+	arc_timer_event_setup(delta);
+	return 0;
+}
+
+static void arc_clkevent_set_mode(enum clock_event_mode mode,
+				  struct clock_event_device *dev)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		arc_timer_event_setup(arc_get_core_freq() / HZ);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		break;
+	default:
+		break;
+	}
+
+	return;
+}
+
+static DEFINE_PER_CPU(struct clock_event_device, arc_clockevent_device) = {
+	.name		= "ARC Timer0",
+	.features	= CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
+	.mode		= CLOCK_EVT_MODE_UNUSED,
+	.rating		= 300,
+	.irq		= TIMER0_IRQ,	/* hardwired, no need for resources */
+	.set_next_event = arc_clkevent_set_next_event,
+	.set_mode	= arc_clkevent_set_mode,
+};
+
+static irqreturn_t timer_irq_handler(int irq, void *dev_id)
+{
+	struct clock_event_device *clk = &__get_cpu_var(arc_clockevent_device);
+
+	arc_timer_event_ack(clk->mode == CLOCK_EVT_MODE_PERIODIC);
+	clk->event_handler(clk);
+	return IRQ_HANDLED;
+}
+
+static struct irqaction arc_timer_irq = {
+	.name    = "Timer0 (clock-evt-dev)",
+	.flags   = IRQF_TIMER | IRQF_PERCPU,
+	.handler = timer_irq_handler,
+};
+
+/*
+ * Setup the local event timer for @cpu
+ * N.B. weak so that some exotic ARC SoCs can completely override it
+ */
+void __attribute__((weak)) __cpuinit arc_local_timer_setup(unsigned int cpu)
+{
+	struct clock_event_device *clk = &per_cpu(arc_clockevent_device, cpu);
+
+	clockevents_calc_mult_shift(clk, arc_get_core_freq(), 5);
+
+	clk->max_delta_ns = clockevent_delta2ns(ARC_TIMER_MAX, clk);
+	clk->cpumask = cpumask_of(cpu);
+
+	clockevents_register_device(clk);
+
+	/*
+	 * setup the per-cpu timer IRQ handler - for all cpus
+	 * For non boot CPU explicitly unmask at intc
+	 * setup_irq() -> .. -> irq_startup() already does this on boot-cpu
+	 */
+	if (!cpu)
+		setup_irq(TIMER0_IRQ, &arc_timer_irq);
+	else
+		arch_unmask_irq(TIMER0_IRQ);
+}
+
+/*
+ * Called from start_kernel() - boot CPU only
+ *
+ * -Sets up h/w timers as applicable on boot cpu
+ * -Also sets up any global state needed for timer subsystem:
+ *    - for "counting" timer, registers a clocksource, usable across CPUs
+ *      (provided that underlying counter h/w is synchronized across cores)
+ *    - for "event" timer, sets up TIMER0 IRQ (as that is platform agnostic)
+ */
+void __init time_init(void)
+{
+	/*
+	 * sets up the timekeeping free-flowing counter which also returns
+	 * whether the counter is usable as clocksource
+	 */
+	if (arc_counter_setup())
+		/*
+		 * CLK upto 4.29 GHz can be safely represented in 32 bits
+		 * because Max 32 bit number is 4,294,967,295
+		 */
+		clocksource_register_hz(&arc_counter, arc_get_core_freq());
+
+	/* sets up the periodic event timer */
+	arc_local_timer_setup(smp_processor_id());
+}
+
+#ifdef CONFIG_ARC_HAS_RTSC
+/*
+ * sched_clock math assist
+ * ns = cycles * (ns_per_sec / cpu_freq_hz)
+ * ns = cycles * (10^6 / cpu_freq_khz)
+ * ns = cycles * (10^6 * 2^SF / cpu_freq_khz) / 2^SF
+ * ns = cycles * cyc2ns_scale >> SF
+ */
+#define CYC2NS_SF	10  /* 2^10, carefully chosen */
+#define CYC2NS_SCALE	((1000000 << CYC2NS_SF) / (arc_get_core_freq() / 1000))
+
+static unsigned long long cycles2ns(unsigned long long cyc)
+{
+	return (cyc * CYC2NS_SCALE ) >> CYC2NS_SF;
+}
+
+/*
+ * Scheduler clock - a monotonically increasing clock in nanosec units.
+ * It's return value must NOT wrap around.
+ *
+ * - Since 32bit TIMER1 will overflow almost immediately (53sec @ 80MHz), it
+ *   can't be used directly.
+ * - Using getrawmonotonic (TIMER1 based, but with state for last + current
+ *   snapshots), is no-good either because of seqlock deadlock possibilities
+ * - So only with native 64bit timer we do this, otherwise fallback to generic
+ *   jiffies based version - which despite not being fine grained gaurantees
+ *   the monotonically increasing semantics.
+ */
+unsigned long long sched_clock(void)
+{
+	return cycles2ns(arc_counter_read(NULL));
+}
+#endif
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 20/71] ARC: Signal handling
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (6 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 19/71] ARC: Timers/counters/delay management Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-02-11  7:26   ` pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling) Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 21/71] ARC: [Review] Preparing to fix incorrect syscall restarts due to signals Vineet Gupta
                   ` (17 subsequent siblings)
  25 siblings, 1 reply; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta, Al Viro

Includes following fixes courtesy review by Al-Viro

* Tracer poke to Callee-regs were lost

  Before going off into do_signal( ) we save the user-mode callee regs
  (as they are not saved by default as part of pt_regs). This is to make
  sure that that a Tracer (if tracing related signal) is able to do likes
  of PEEKUSR(callee-reg).

  However in return path we were simply discarding the user-mode callee
  regs, which would break a POKEUSR(callee-reg) from a tracer.

* Issue related to multiple syscall restarts are addressed in next patch

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
---
 arch/arc/Kconfig                  |    1 +
 arch/arc/include/asm/entry.h      |   35 ++++
 arch/arc/include/asm/sigcontext.h |   23 +++
 arch/arc/include/asm/signal.h     |   27 +++
 arch/arc/kernel/entry.S           |   11 +-
 arch/arc/kernel/signal.c          |  359 +++++++++++++++++++++++++++++++++++++
 6 files changed, 453 insertions(+), 3 deletions(-)
 create mode 100644 arch/arc/include/asm/sigcontext.h
 create mode 100644 arch/arc/include/asm/signal.h
 create mode 100644 arch/arc/kernel/signal.c

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index a4e9806..756beff 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -20,6 +20,7 @@ config ARC
 	select GENERIC_KERNEL_EXECVE
 	select GENERIC_KERNEL_THREAD
 	select GENERIC_PENDING_IRQ if SMP
+	select GENERIC_SIGALTSTACK
 	select GENERIC_SMP_IDLE_THREAD
 	select HAVE_GENERIC_HARDIRQS
 	select MODULES_USE_ELF_RELA
diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h
index 63705b1..6b42bf5 100644
--- a/arch/arc/include/asm/entry.h
+++ b/arch/arc/include/asm/entry.h
@@ -166,6 +166,41 @@
 .endm
 
 /*--------------------------------------------------------------
+ * RESTORE_CALLEE_SAVED_USER:
+ * This is called after do_signal where tracer might have changed callee regs
+ * thus we need to restore the reg file.
+ * Special case handling is required for r25 in case it is used by kernel
+ *  for caching task ptr. Ptrace would have modified on-kernel-stack value of
+ *  r25, which needs to be shoved back into task->thread.user_r25 where from
+ *  Low level exception/ISR return code will retrieve to populate with rest of
+ *  callee reg-file.
+ *-------------------------------------------------------------*/
+.macro RESTORE_CALLEE_SAVED_USER
+
+	add     sp, sp, 4   /* skip "callee_regs->stack_place_holder" */
+
+#ifdef CONFIG_ARC_CURR_IN_REG
+	ld.ab   r12, [sp, 4]
+	st      r12, [r25, TASK_THREAD + THREAD_USER_R25]
+#else
+	ld.ab   r25, [sp, 4]
+#endif
+
+	ld.ab   r24, [sp, 4]
+	ld.ab   r23, [sp, 4]
+	ld.ab   r22, [sp, 4]
+	ld.ab   r21, [sp, 4]
+	ld.ab   r20, [sp, 4]
+	ld.ab   r19, [sp, 4]
+	ld.ab   r18, [sp, 4]
+	ld.ab   r17, [sp, 4]
+	ld.ab   r16, [sp, 4]
+	ld.ab   r15, [sp, 4]
+	ld.ab   r14, [sp, 4]
+	ld.ab   r13, [sp, 4]
+.endm
+
+/*--------------------------------------------------------------
  * Super FAST Restore callee saved regs by simply re-adjusting SP
  *-------------------------------------------------------------*/
 .macro DISCARD_CALLEE_SAVED_USER
diff --git a/arch/arc/include/asm/sigcontext.h b/arch/arc/include/asm/sigcontext.h
new file mode 100644
index 0000000..f21b541
--- /dev/null
+++ b/arch/arc/include/asm/sigcontext.h
@@ -0,0 +1,23 @@
+/*
+ * 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_ARC_SIGCONTEXT_H
+#define _ASM_ARC_SIGCONTEXT_H
+
+#include <asm/ptrace.h>
+
+/*
+ * Signal context structure - contains all info to do with the state
+ * before the signal handler was invoked.  Note: only add new entries
+ * to the end of the structure.
+ */
+struct sigcontext {
+	struct pt_regs regs;
+};
+
+#endif /* _ASM_ARC_SIGCONTEXT_H */
diff --git a/arch/arc/include/asm/signal.h b/arch/arc/include/asm/signal.h
new file mode 100644
index 0000000..fad62f7
--- /dev/null
+++ b/arch/arc/include/asm/signal.h
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ *
+ * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
+ */
+
+#ifndef _ASM_ARC_SIGNAL_H
+#define _ASM_ARC_SIGNAL_H
+
+/*
+ * This is much needed for ARC sigreturn optimization.
+ * This allows uClibc to piggback the addr of a sigreturn stub in sigaction,
+ * which allows sigreturn based re-entry into kernel after handling signal.
+ * W/o this kernel needs to "synthesize" the sigreturn trampoline on user
+ * mode stack which in turn forces the following:
+ * -TLB Flush (after making the stack page executable)
+ * -Cache line Flush (to make I/D Cache lines coherent)
+ */
+#define SA_RESTORER	0x04000000
+
+#include <asm-generic/signal.h>
+
+#endif /* _ASM_ARC_SIGNAL_H */
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index ed08ac1..d625b77 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -470,7 +470,11 @@ resume_user_mode_begin:
 
 	bbit0  r9, TIF_SIGPENDING, .Lchk_notify_resume
 
-	; save CALLEE Regs.
+	; Normal Trap/IRQ entry only saves Scratch (caller-saved) regs
+	; in pt_reg since the "C" ABI (kernel code) will automatically
+	; save/restore callee-saved regs.
+	;
+	; However, here we need to explicitly save callee regs because
 	; (i)  If this signal causes coredump - full regfile needed
 	; (ii) If signal is SIGTRAP/SIGSTOP, task is being traced thus
 	;      tracer might call PEEKUSR(CALLEE reg)
@@ -484,8 +488,9 @@ resume_user_mode_begin:
 
 	bl  @do_signal
 
-	; unwind SP for cheap discard of Callee saved Regs
-	DISCARD_CALLEE_SAVED_USER
+	; Ideally we want to discard the Callee reg above, however if this was
+	; a tracing signal, tracer could have done a POKEUSR(CALLEE reg)
+	RESTORE_CALLEE_SAVED_USER
 
 	b      resume_user_mode_begin	; loop back to start of U mode ret
 
diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c
new file mode 100644
index 0000000..887a383
--- /dev/null
+++ b/arch/arc/kernel/signal.c
@@ -0,0 +1,359 @@
+/*
+ * Signal Handling for ARC
+ *
+ * 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.
+ *
+ * vineetg: Jan 2010 (Restarting of timer related syscalls)
+ *
+ * vineetg: Nov 2009 (Everything needed for TIF_RESTORE_SIGMASK)
+ *  -do_signal() supports TIF_RESTORE_SIGMASK
+ *  -do_signal() no loner needs oldset, required by OLD sys_sigsuspend
+ *  -sys_rt_sigsuspend() now comes from generic code, so discard arch implemen
+ *  -sys_sigsuspend() no longer needs to fudge ptregs, hence that arg removed
+ *  -sys_sigsuspend() no longer loops for do_signal(), sets TIF_xxx and leaves
+ *   the job to do_signal()
+ *
+ * vineetg: July 2009
+ *  -Modified Code to support the uClibc provided userland sigreturn stub
+ *   to avoid kernel synthesing it on user stack at runtime, costing TLB
+ *   probes and Cache line flushes.
+ *
+ * vineetg: July 2009
+ *  -In stash_usr_regs( ) and restore_usr_regs( ), save/restore of user regs
+ *   in done in block copy rather than one word at a time.
+ *   This saves around 2K of code and improves LMBench lat_sig <catch>
+ *
+ * rajeshwarr: Feb 2009
+ *  - Support for Realtime Signals
+ *
+ * vineetg: Aug 11th 2008: Bug #94183
+ *  -ViXS were still seeing crashes when using insmod to load drivers.
+ *   It turned out that the code to change Execute permssions for TLB entries
+ *   of user was not guarded for interrupts (mod_tlb_permission)
+ *   This was cauing TLB entries to be overwritten on unrelated indexes
+ *
+ * Vineetg: July 15th 2008: Bug #94183
+ *  -Exception happens in Delay slot of a JMP, and before user space resumes,
+ *   Signal is delivered (Ctrl + C) = >SIGINT.
+ *   setup_frame( ) sets up PC,SP,BLINK to enable user space signal handler
+ *   to run, but doesn't clear the Delay slot bit from status32. As a result,
+ *   on resuming user mode, signal handler branches off to BTA of orig JMP
+ *  -FIX: clear the DE bit from status32 in setup_frame( )
+ *
+ * Rahul Trivedi, Kanika Nema: Codito Technologies 2004
+ */
+
+#include <linux/signal.h>
+#include <linux/ptrace.h>
+#include <linux/personality.h>
+#include <linux/uaccess.h>
+#include <linux/syscalls.h>
+#include <linux/tracehook.h>
+#include <asm/ucontext.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+struct rt_sigframe {
+	struct siginfo info;
+	struct ucontext uc;
+#define MAGIC_SIGALTSTK		0x07302004
+	unsigned int sigret_magic;
+};
+
+static int
+stash_usr_regs(struct rt_sigframe __user *sf, struct pt_regs *regs,
+	       sigset_t *set)
+{
+	int err;
+	err = __copy_to_user(&(sf->uc.uc_mcontext.regs), regs, sizeof(*regs));
+	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(sigset_t));
+
+	return err;
+}
+
+static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf)
+{
+	sigset_t set;
+	int err;
+
+	err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
+	if (err == 0) {
+		sigdelsetmask(&set, ~_BLOCKABLE);
+		set_current_blocked(&set);
+	}
+
+	err |= __copy_from_user(regs, &(sf->uc.uc_mcontext.regs),
+				sizeof(*regs));
+
+	return err;
+}
+
+static inline int is_do_ss_needed(unsigned int magic)
+{
+	if (MAGIC_SIGALTSTK == magic)
+		return 1;
+	else
+		return 0;
+}
+
+SYSCALL_DEFINE0(rt_sigreturn)
+{
+	struct rt_sigframe __user *sf;
+	unsigned int magic;
+	int err;
+	struct pt_regs *regs = current_pt_regs();
+
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+	/* Since we stacked the signal on a word boundary,
+	 * then 'sp' should be word aligned here.  If it's
+	 * not, then the user is trying to mess with us.
+	 */
+	if (regs->sp & 3)
+		goto badframe;
+
+	sf = (struct rt_sigframe __force __user *)(regs->sp);
+
+	if (!access_ok(VERIFY_READ, sf, sizeof(*sf)))
+		goto badframe;
+
+	err = restore_usr_regs(regs, sf);
+	err |= __get_user(magic, &sf->sigret_magic);
+	if (err)
+		goto badframe;
+
+	if (unlikely(is_do_ss_needed(magic)))
+		if (restore_altstack(&sf->uc.uc_stack))
+			goto badframe;
+
+	return regs->r0;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+/*
+ * Determine which stack to use..
+ */
+static inline void __user *get_sigframe(struct k_sigaction *ka,
+					struct pt_regs *regs,
+					unsigned long framesize)
+{
+	unsigned long sp = regs->sp;
+	void __user *frame;
+
+	/* This is the X/Open sanctioned signal stack switching */
+	if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
+		sp = current->sas_ss_sp + current->sas_ss_size;
+
+	/* No matter what happens, 'sp' must be word
+	 * aligned otherwise nasty things could happen
+	 */
+
+	/* ATPCS B01 mandates 8-byte alignment */
+	frame = (void __user *)((sp - framesize) & ~7);
+
+	/* Check that we can actually write to the signal frame */
+	if (!access_ok(VERIFY_WRITE, frame, framesize))
+		frame = NULL;
+
+	return frame;
+}
+
+/*
+ * translate the signal
+ */
+static inline int map_sig(int sig)
+{
+	struct thread_info *thread = current_thread_info();
+	if (thread->exec_domain && thread->exec_domain->signal_invmap
+	    && sig < 32)
+		sig = thread->exec_domain->signal_invmap[sig];
+	return sig;
+}
+
+static int
+setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info,
+	       sigset_t *set, struct pt_regs *regs)
+{
+	struct rt_sigframe __user *sf;
+	unsigned int magic = 0;
+	int err = 0;
+
+	sf = get_sigframe(ka, regs, sizeof(struct rt_sigframe));
+	if (!sf)
+		return 1;
+
+	/*
+	 * SA_SIGINFO requires 3 args to signal handler:
+	 *  #1: sig-no (common to any handler)
+	 *  #2: struct siginfo
+	 *  #3: struct ucontext (completely populated)
+	 */
+	if (unlikely(ka->sa.sa_flags & SA_SIGINFO)) {
+		err |= copy_siginfo_to_user(&sf->info, info);
+		err |= __put_user(0, &sf->uc.uc_flags);
+		err |= __put_user(NULL, &sf->uc.uc_link);
+		err |= __save_altstack(&sf->uc.uc_stack, regs->sp);
+
+		/* setup args 2 and 3 fo ruse rmode handler */
+		regs->r1 = (unsigned long)&sf->info;
+		regs->r2 = (unsigned long)&sf->uc;
+
+		/*
+		 * small optim to avoid unconditonally calling do_sigaltstack
+		 * in sigreturn path, now that we only have rt_sigreturn
+		 */
+		magic = MAGIC_SIGALTSTK;
+	}
+
+	/*
+	 * w/o SA_SIGINFO, struct ucontext is partially populated (only
+	 * uc_mcontext/uc_sigmask) for kernel's normal user state preservation
+	 * during signal handler execution. This works for SA_SIGINFO as well
+	 * although the semantics are now overloaded (the same reg state can be
+	 * inspected by userland: but are they allowed to fiddle with it ?
+	 */
+	err |= stash_usr_regs(sf, regs, set);
+	err |= __put_user(magic, &sf->sigret_magic);
+	if (err)
+		return err;
+
+	/* #1 arg to the user Signal handler */
+	regs->r0 = map_sig(signo);
+
+	/* setup PC of user space signal handler */
+	regs->ret = (unsigned long)ka->sa.sa_handler;
+
+	/*
+	 * handler returns using sigreturn stub provided already by userpsace
+	 */
+	BUG_ON(!(ka->sa.sa_flags & SA_RESTORER));
+	regs->blink = (unsigned long)ka->sa.sa_restorer;
+
+	/* User Stack for signal handler will be above the frame just carved */
+	regs->sp = (unsigned long)sf;
+
+	/*
+	 * Bug 94183, Clear the DE bit, so that when signal handler
+	 * starts to run, it doesn't use BTA
+	 */
+	regs->status32 &= ~STATUS_DE_MASK;
+	regs->status32 |= STATUS_L_MASK;
+
+	return err;
+}
+
+static void arc_restart_syscall(struct k_sigaction *ka, struct pt_regs *regs)
+{
+	switch (regs->r0) {
+	case -ERESTART_RESTARTBLOCK:
+	case -ERESTARTNOHAND:
+		/*
+		 * ERESTARTNOHAND means that the syscall should
+		 * only be restarted if there was no handler for
+		 * the signal, and since we only get here if there
+		 * is a handler, we don't restart
+		 */
+		regs->r0 = -EINTR;   /* ERESTART_xxx is internal */
+		break;
+
+	case -ERESTARTSYS:
+		/*
+		 * ERESTARTSYS means to restart the syscall if
+		 * there is no handler or the handler was
+		 * registered with SA_RESTART
+		 */
+		if (!(ka->sa.sa_flags & SA_RESTART)) {
+			regs->r0 = -EINTR;
+			break;
+		}
+		/* fallthrough */
+
+	case -ERESTARTNOINTR:
+		/*
+		 * ERESTARTNOINTR means that the syscall should
+		 * be called again after the signal handler returns.
+		 * Setup reg state just as it was before doing the trap
+		 * r0 has been clobbered with sys call ret code thus it
+		 * needs to be reloaded with orig first arg to syscall
+		 * in orig_r0. Rest of relevant reg-file:
+		 * r8 (syscall num) and (r1 - r7) will be reset to
+		 * their orig user space value when we ret from kernel
+		 */
+		regs->r0 = regs->orig_r0;
+		regs->ret -= 4;
+		break;
+	}
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+static void
+handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
+	      struct pt_regs *regs)
+{
+	sigset_t *oldset = sigmask_to_save();
+	int ret;
+
+	/* Set up the stack frame */
+	ret = setup_rt_frame(sig, ka, info, oldset, regs);
+
+	if (ret)
+		force_sigsegv(sig, current);
+	else
+		signal_delivered(sig, info, ka, regs, 0);
+}
+
+void do_signal(struct pt_regs *regs)
+{
+	struct k_sigaction ka;
+	siginfo_t info;
+	int signr;
+	int restart_scall;
+
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+
+	/* Are we from a system call? */
+	restart_scall = in_syscall(regs);
+
+	if (signr > 0) {
+		if (restart_scall)
+			arc_restart_syscall(&ka, regs);
+
+		handle_signal(signr, &ka, &info, regs);
+		return;
+	}
+
+	if (restart_scall) {
+		/* No handler for syscall: restart it */
+		if (regs->r0 == -ERESTARTNOHAND ||
+		    regs->r0 == -ERESTARTSYS || regs->r0 == -ERESTARTNOINTR) {
+			regs->r0 = regs->orig_r0;
+			regs->ret -= 4;
+		} else if (regs->r0 == -ERESTART_RESTARTBLOCK) {
+			regs->r8 = __NR_restart_syscall;
+			regs->ret -= 4;
+		}
+	}
+
+	/* If there's no signal to deliver, restore the saved sigmask back */
+	restore_saved_sigmask();
+}
+
+void do_notify_resume(struct pt_regs *regs)
+{
+	/*
+	 * ASM glue gaurantees that this is only called when returning to
+	 * user mode
+	 */
+	if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME))
+		tracehook_notify_resume(regs);
+}
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 21/71] ARC: [Review] Preparing to fix incorrect syscall restarts due to signals
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (7 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 20/71] ARC: Signal handling Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 22/71] ARC: [Review] Prevent incorrect syscall restarts Vineet Gupta
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta, Al Viro

To avoid multiple syscall restarts (multiple signals) or no restart at
all (sigreturn), we need just an extra bit of state "literally 1 bit" in
struct pt_regs. orig_r8 is the best place to do this, however given the
way it is encoded currently, we can't add anything simplistically.

Current orig_r8:
* syscalls   -> 1 to NR_SYSCALLS
* Exceptions -> NR_SYSCALLS + 1
* Break-point-> NR_SYSCALLS + 2

In new scheme it is a bit-field
* lower short word contains the  exact event type (and a new bit to represent
   restart semantics : if syscall was already / can't be restarted)
* upper short word optionally containing the syscall num - needed by
  likes of tracehooks etc

This patch only changes how orig_r8 is organised and nothing should
change behaviourily.

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
---
 arch/arc/include/asm/entry.h  |   29 +++++++++++++++++------------
 arch/arc/include/asm/ptrace.h |   20 ++++++++++++++++----
 arch/arc/kernel/entry.S       |    4 ++--
 3 files changed, 35 insertions(+), 18 deletions(-)

diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h
index 6b42bf5..9eada5b 100644
--- a/arch/arc/include/asm/entry.h
+++ b/arch/arc/include/asm/entry.h
@@ -343,18 +343,12 @@
  *-------------------------------------------------------------*/
 .macro SAVE_ALL_EXCEPTION   marker
 
+	st      \marker, [sp, 8]
+	st      r0, [sp, 4]    /* orig_r0, needed only for sys calls */
+
 	/* Restore r9 used to code the early prologue */
 	EXCPN_PROLOG_RESTORE_REG  r9
 
-	/* Save the complete regfile now */
-
-	/* orig_r8 marker:
-	 * syscalls   -> 1 to NR_SYSCALLS
-	 * Exceptions -> NR_SYSCALLS + 1
-	 * Break-point-> NR_SYSCALLS + 2
-	 */
-	st      \marker, [sp, 8]
-	st      r0, [sp, 4]    /* orig_r0, needed only for sys calls */
 	SAVE_CALLER_SAVED
 	st.a    r26, [sp, -4]   /* gp */
 	st.a    fp, [sp, -4]
@@ -384,14 +378,25 @@
  * Save scratch regs for exceptions
  *-------------------------------------------------------------*/
 .macro SAVE_ALL_SYS
-	SAVE_ALL_EXCEPTION  (NR_syscalls + 1)
+	SAVE_ALL_EXCEPTION  orig_r8_IS_EXCPN
 .endm
 
 /*--------------------------------------------------------------
  * Save scratch regs for sys calls
  *-------------------------------------------------------------*/
 .macro SAVE_ALL_TRAP
-	SAVE_ALL_EXCEPTION  r8
+	/*
+	 * Setup pt_regs->orig_r8.
+	 * Encode syscall number (r8) in upper short word of event type (r9)
+	 * N.B. #1: This is already endian safe (see ptrace.h)
+	 *      #2: Only r9 can be used as scratch as it is already clobbered
+	 *          and it's contents are no longer needed by the latter part
+	 *          of exception prologue
+	 */
+	lsl  r9, r8, 16
+	or   r9, r9, orig_r8_IS_SCALL
+
+	SAVE_ALL_EXCEPTION  r9
 .endm
 
 /*--------------------------------------------------------------
@@ -442,7 +447,7 @@
 	ld  r9, [@int1_saved_reg]
 
 	/* now we are ready to save the remaining context :) */
-	st     -1, [sp, 8]    /* orig_r8, -1 for interuppt level one */
+	st      orig_r8_IS_IRQ1, [sp, 8]    /* Event Type */
 	st      0, [sp, 4]    /* orig_r0 , N/A for IRQ */
 	SAVE_CALLER_SAVED
 	st.a    r26, [sp, -4]   /* gp */
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
index 72754a2..1711d56 100644
--- a/arch/arc/include/asm/ptrace.h
+++ b/arch/arc/include/asm/ptrace.h
@@ -81,7 +81,13 @@ struct pt_regs {
 	long r0;
 	long sp;	/* user/kernel sp depending on where we came from  */
 	long orig_r0;
-	long orig_r8;	/*to distinguish bet excp, sys call, int1 or int2 */
+	/*to distinguish bet excp, syscall, irq */
+#ifdef CONFIG_CPU_BIG_ENDIAN
+	/* so that assembly code is same for LE/BE */
+	unsigned long orig_r8:16, event:16;
+#else
+	unsigned long event:16, orig_r8:16;
+#endif
 };
 
 /* Callee saved registers - need to be saved only when you are scheduled out */
@@ -126,9 +132,8 @@ struct user_regs_struct {
 	sp;			\
 })
 
-/* return 1 if in syscall, 0 if Intr or Exception */
-#define in_syscall(regs) (((regs->orig_r8) >= 0 && \
-			   (regs->orig_r8 <= NR_syscalls)) ? 1 : 0)
+#define in_syscall(regs)    (regs->event & orig_r8_IS_SCALL)
+#define in_brkpt_trap(regs) (regs->event & orig_r8_IS_BRKPT)
 
 #define current_pt_regs()					\
 ({								\
@@ -140,6 +145,13 @@ struct user_regs_struct {
 
 #endif /* !__ASSEMBLY__ */
 
+#define orig_r8_IS_SCALL		0x0001
+#define orig_r8_IS_SCALL_RESTARTED	0x0002
+#define orig_r8_IS_BRKPT		0x0004
+#define orig_r8_IS_EXCPN		0x0004
+#define orig_r8_IS_IRQ1			0x0010
+#define orig_r8_IS_IRQ2			0x0020
+
 #endif /* __KERNEL__ */
 
 #endif /* __ASM_PTRACE_H */
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index d625b77..ce8670d 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -350,8 +350,8 @@ ARC_EXIT EV_Extension
 
 trap_with_param:
 
-	;make sure orig_r8 is a positive value
-	st  NR_syscalls + 2, [sp, PT_orig_r8]
+	; stop_pc info by gdb needs this info
+	st  orig_r8_IS_BRKPT, [sp, PT_orig_r8]
 
 	mov r0, r12
 	lr  r1, [efa]
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 22/71] ARC: [Review] Prevent incorrect syscall restarts
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (8 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 21/71] ARC: [Review] Preparing to fix incorrect syscall restarts due to signals Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-28  7:42   ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 23/71] ARC: Cache Flush Management Vineet Gupta
                   ` (15 subsequent siblings)
  25 siblings, 1 reply; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta, Al Viro

Per Al Viro's "signals for dummies" https://lkml.org/lkml/2012/12/6/366
there are 3 golden rules for (not) restarting syscalls:

"	What we need to guarantee is
* restarts do not happen on signals caught in interrupts or exceptions
* restarts do not happen on signals caught in sigreturn()
* restart should happen only once, even if we get through do_signal()
  many times."

ARC Port already handled #1, this patch fixes #2 and #3.

We use the additional state in pt_regs->orig_r8 to ckh if restarting
has already been done once.

Thanks to Al Viro for spotting this.

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
---
 arch/arc/include/asm/ptrace.h |    3 +++
 arch/arc/kernel/signal.c      |   12 ++++++++----
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
index 1711d56..8bf7ff4 100644
--- a/arch/arc/include/asm/ptrace.h
+++ b/arch/arc/include/asm/ptrace.h
@@ -135,6 +135,9 @@ struct user_regs_struct {
 #define in_syscall(regs)    (regs->event & orig_r8_IS_SCALL)
 #define in_brkpt_trap(regs) (regs->event & orig_r8_IS_BRKPT)
 
+#define syscall_wont_restart(regs) (regs->event |= orig_r8_IS_SCALL_RESTARTED)
+#define syscall_restartable(regs) !(regs->event &  orig_r8_IS_SCALL_RESTARTED)
+
 #define current_pt_regs()					\
 ({								\
 	/* open-coded current_thread_info() */			\
diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c
index 887a383..9a1ea2b 100644
--- a/arch/arc/kernel/signal.c
+++ b/arch/arc/kernel/signal.c
@@ -131,6 +131,9 @@ SYSCALL_DEFINE0(rt_sigreturn)
 		if (restore_altstack(&sf->uc.uc_stack))
 			goto badframe;
 
+	/* Don't restart from sigreturn */
+	syscall_wont_restart(regs);
+
 	return regs->r0;
 
 badframe:
@@ -321,13 +324,13 @@ void do_signal(struct pt_regs *regs)
 
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
-	/* Are we from a system call? */
-	restart_scall = in_syscall(regs);
+	restart_scall = in_syscall(regs) && syscall_restartable(regs);
 
 	if (signr > 0) {
-		if (restart_scall)
+		if (restart_scall) {
 			arc_restart_syscall(&ka, regs);
-
+			syscall_wont_restart(regs);	/* No more restarts */
+		}
 		handle_signal(signr, &ka, &info, regs);
 		return;
 	}
@@ -342,6 +345,7 @@ void do_signal(struct pt_regs *regs)
 			regs->r8 = __NR_restart_syscall;
 			regs->ret -= 4;
 		}
+		syscall_wont_restart(regs);	/* No more restarts */
 	}
 
 	/* If there's no signal to deliver, restore the saved sigmask back */
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 23/71] ARC: Cache Flush Management
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (9 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 22/71] ARC: [Review] Prevent incorrect syscall restarts Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 29/71] ARC: I/O and DMA Mappings Vineet Gupta
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta

* ARC700 has VIPT L1 Caches
* Caches don't snoop and are not coherent
* Given the PAGE_SIZE and Cache associativity, we don't support aliasing
  D$ configurations (yet), but do allow aliasing I$ configs

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/include/asm/arcregs.h    |   80 ++++
 arch/arc/include/asm/cache.h      |   54 +++
 arch/arc/include/asm/cachectl.h   |   28 ++
 arch/arc/include/asm/cacheflush.h |   67 ++++
 arch/arc/mm/cache_arc700.c        |  725 +++++++++++++++++++++++++++++++++++++
 5 files changed, 954 insertions(+), 0 deletions(-)
 create mode 100644 arch/arc/include/asm/cachectl.h
 create mode 100644 arch/arc/include/asm/cacheflush.h
 create mode 100644 arch/arc/mm/cache_arc700.c

diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index 5131bb3..c6e2805 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -58,6 +58,33 @@
 #define TIMER_CTRL_IE		(1 << 0) /* Interupt when Count reachs limit */
 #define TIMER_CTRL_NH		(1 << 1) /* Count only when CPU NOT halted */
 
+/* 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
+#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
+
 /*
  * Floating Pt Registers
  * Status regs are read-only (build-time) so need not be saved/restored
@@ -132,6 +159,31 @@
 
 #endif
 
+#define READ_BCR(reg, into)				\
+{							\
+	unsigned int tmp;				\
+	tmp = read_aux_reg(reg);			\
+	if (sizeof(tmp) == sizeof(into)) {		\
+		into = *((typeof(into) *)&tmp);		\
+	} else {					\
+		extern void bogus_undefined(void);	\
+		bogus_undefined();			\
+	}						\
+}
+
+#define WRITE_BCR(reg, into)				\
+{							\
+	unsigned int tmp;				\
+	if (sizeof(tmp) == sizeof(into)) {		\
+		tmp = (*(unsigned int *)(into));	\
+		write_aux_reg(reg, tmp);		\
+	} else  {					\
+		extern void bogus_undefined(void);	\
+		bogus_undefined();			\
+	}						\
+}
+
+
 #ifdef CONFIG_ARC_FPU_SAVE_RESTORE
 /* These DPFP regs need to be saved/restored across ctx-sw */
 struct arc_fpu {
@@ -141,6 +193,34 @@ struct arc_fpu {
 };
 #endif
 
+/*
+ ***************************************************************
+ * Build Configuration Registers, with encoded hardware config
+ */
+
+struct bcr_cache {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+	unsigned int pad:12, line_len:4, sz:4, config:4, ver:8;
+#else
+	unsigned int ver:8, config:4, sz:4, line_len:4, pad:12;
+#endif
+};
+
+/*
+ *******************************************************************
+ * Generic structures to hold build configuration used at runtime
+ */
+
+struct cpuinfo_arc_cache {
+	unsigned int has_aliasing, sz, line_len, assoc, ver;
+};
+
+struct cpuinfo_arc {
+	struct cpuinfo_arc_cache icache, dcache;
+};
+
+extern struct cpuinfo_arc cpuinfo_arc700[];
+
 #endif /* __ASEMBLY__ */
 
 #endif /* __KERNEL__ */
diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h
index 30c72a4..6632273 100644
--- a/arch/arc/include/asm/cache.h
+++ b/arch/arc/include/asm/cache.h
@@ -18,4 +18,58 @@
 
 #define L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)
 
+#define ARC_ICACHE_WAYS	2
+#define ARC_DCACHE_WAYS	4
+
+/* Helpers */
+#define ARC_ICACHE_LINE_LEN	L1_CACHE_BYTES
+#define ARC_DCACHE_LINE_LEN	L1_CACHE_BYTES
+
+#define ICACHE_LINE_MASK	(~(ARC_ICACHE_LINE_LEN - 1))
+#define DCACHE_LINE_MASK	(~(ARC_DCACHE_LINE_LEN - 1))
+
+#if ARC_ICACHE_LINE_LEN != ARC_DCACHE_LINE_LEN
+#error "Need to fix some code as I/D cache lines not same"
+#else
+#define is_not_cache_aligned(p)	((unsigned long)p & (~DCACHE_LINE_MASK))
+#endif
+
+#ifndef __ASSEMBLY__
+
+/* Uncached access macros */
+#define arc_read_uncached_32(ptr)	\
+({					\
+	unsigned int __ret;		\
+	__asm__ __volatile__(		\
+	"	ld.di %0, [%1]	\n"	\
+	: "=r"(__ret)			\
+	: "r"(ptr));			\
+	__ret;				\
+})
+
+#define arc_write_uncached_32(ptr, data)\
+({					\
+	__asm__ __volatile__(		\
+	"	st.di %0, [%1]	\n"	\
+	:				\
+	: "r"(data), "r"(ptr));		\
+})
+
+/* used to give SHMLBA a value to avoid Cache Aliasing */
+extern unsigned int ARC_shmlba;
+
+#define ARCH_DMA_MINALIGN      L1_CACHE_BYTES
+
+/*
+ * ARC700 doesn't cache any access in top 256M.
+ * Ideal for wiring memory mapped peripherals as we don't need to do
+ * explicit uncached accesses (LD.di/ST.di) hence more portable drivers
+ */
+#define ARC_UNCACHED_ADDR_SPACE	0xc0000000
+
+extern void arc_cache_init(void);
+extern char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len);
+extern void __init read_decode_cache_bcr(void);
+#endif
+
 #endif /* _ASM_CACHE_H */
diff --git a/arch/arc/include/asm/cachectl.h b/arch/arc/include/asm/cachectl.h
new file mode 100644
index 0000000..51c73f0
--- /dev/null
+++ b/arch/arc/include/asm/cachectl.h
@@ -0,0 +1,28 @@
+/*
+ * 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 __ARC_ASM_CACHECTL_H
+#define __ARC_ASM_CACHECTL_H
+
+/*
+ * ARC ABI flags defined for Android's finegrained cacheflush requirements
+ */
+#define CF_I_INV	0x0002
+#define CF_D_FLUSH	0x0010
+#define CF_D_FLUSH_INV	0x0020
+
+#define CF_DEFAULT	(CF_I_INV | CF_D_FLUSH)
+
+/*
+ * Standard flags expected by cacheflush system call users
+ */
+#define ICACHE	CF_I_INV
+#define DCACHE	CF_D_FLUSH
+#define BCACHE	(CF_I_INV | CF_D_FLUSH)
+
+#endif
diff --git a/arch/arc/include/asm/cacheflush.h b/arch/arc/include/asm/cacheflush.h
new file mode 100644
index 0000000..97ee96f
--- /dev/null
+++ b/arch/arc/include/asm/cacheflush.h
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ *
+ *  vineetg: May 2011: for Non-aliasing VIPT D-cache following can be NOPs
+ *   -flush_cache_dup_mm (fork)
+ *   -likewise for flush_cache_mm (exit/execve)
+ *   -likewise for flush_cache_{range,page} (munmap, exit, COW-break)
+ *
+ *  vineetg: April 2008
+ *   -Added a critical CacheLine flush to copy_to_user_page( ) which
+ *     was causing gdbserver to not setup breakpoints consistently
+ */
+
+#ifndef _ASM_CACHEFLUSH_H
+#define _ASM_CACHEFLUSH_H
+
+#include <linux/mm.h>
+
+void flush_cache_all(void);
+
+void flush_icache_range(unsigned long start, unsigned long end);
+void flush_icache_page(struct vm_area_struct *vma, struct page *page);
+void flush_icache_range_vaddr(unsigned long paddr, unsigned long u_vaddr,
+				     int len);
+
+#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
+
+void flush_dcache_page(struct page *page);
+
+void dma_cache_wback_inv(unsigned long start, unsigned long sz);
+void dma_cache_inv(unsigned long start, unsigned long sz);
+void dma_cache_wback(unsigned long start, unsigned long sz);
+
+#define flush_dcache_mmap_lock(mapping)		do { } while (0)
+#define flush_dcache_mmap_unlock(mapping)	do { } while (0)
+
+/* TBD: optimize this */
+#define flush_cache_vmap(start, end)		flush_cache_all()
+#define flush_cache_vunmap(start, end)		flush_cache_all()
+
+/*
+ * VM callbacks when entire/range of user-space V-P mappings are
+ * torn-down/get-invalidated
+ *
+ * Currently we don't support D$ aliasing configs for our VIPT caches
+ * NOPS for VIPT Cache with non-aliasing D$ configurations only
+ */
+#define flush_cache_dup_mm(mm)			/* called on fork */
+#define flush_cache_mm(mm)			/* called on munmap/exit */
+#define flush_cache_range(mm, u_vstart, u_vend)
+#define flush_cache_page(vma, u_vaddr, pfn)	/* PF handling/COW-break */
+
+#define copy_to_user_page(vma, page, vaddr, dst, src, len)		\
+do {									\
+	memcpy(dst, src, len);						\
+	if (vma->vm_flags & VM_EXEC)					\
+		flush_icache_range_vaddr((unsigned long)(dst), vaddr, len);\
+} while (0)
+
+#define copy_from_user_page(vma, page, vaddr, dst, src, len)		\
+	memcpy(dst, src, len);						\
+
+#endif
diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c
new file mode 100644
index 0000000..670f65b
--- /dev/null
+++ b/arch/arc/mm/cache_arc700.c
@@ -0,0 +1,725 @@
+/*
+ * ARC700 VIPT Cache Management
+ *
+ * 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.
+ *
+ *  vineetg: May 2011: for Non-aliasing VIPT D-cache following can be NOPs
+ *   -flush_cache_dup_mm (fork)
+ *   -likewise for flush_cache_mm (exit/execve)
+ *   -likewise for flush_cache_range,flush_cache_page (munmap, exit, COW-break)
+ *
+ * vineetg: Apr 2011
+ *  -Now that MMU can support larger pg sz (16K), the determiniation of
+ *   aliasing shd not be based on assumption of 8k pg
+ *
+ * vineetg: Mar 2011
+ *  -optimised version of flush_icache_range( ) for making I/D coherent
+ *   when vaddr is available (agnostic of num of aliases)
+ *
+ * vineetg: Mar 2011
+ *  -Added documentation about I-cache aliasing on ARC700 and the way it
+ *   was handled up until MMU V2.
+ *  -Spotted a three year old bug when killing the 4 aliases, which needs
+ *   bottom 2 bits, so we need to do paddr | {0x00, 0x01, 0x02, 0x03}
+ *                        instead of paddr | {0x00, 0x01, 0x10, 0x11}
+ *   (Rajesh you owe me one now)
+ *
+ * vineetg: Dec 2010
+ *  -Off-by-one error when computing num_of_lines to flush
+ *   This broke signal handling with bionic which uses synthetic sigret stub
+ *
+ * vineetg: Mar 2010
+ *  -GCC can't generate ZOL for core cache flush loops.
+ *   Conv them into iterations based as opposed to while (start < end) types
+ *
+ * Vineetg: July 2009
+ *  -In I-cache flush routine we used to chk for aliasing for every line INV.
+ *   Instead now we setup routines per cache geometry and invoke them
+ *   via function pointers.
+ *
+ * Vineetg: Jan 2009
+ *  -Cache Line flush routines used to flush an extra line beyond end addr
+ *   because check was while (end >= start) instead of (end > start)
+ *     =Some call sites had to work around by doing -1, -4 etc to end param
+ *     =Some callers didnt care. This was spec bad in case of INV routines
+ *      which would discard valid data (cause of the horrible ext2 bug
+ *      in ARC IDE driver)
+ *
+ * vineetg: June 11th 2008: Fixed flush_icache_range( )
+ *  -Since ARC700 caches are not coherent (I$ doesnt snoop D$) both need
+ *   to be flushed, which it was not doing.
+ *  -load_module( ) passes vmalloc addr (Kernel Virtual Addr) to the API,
+ *   however ARC cache maintenance OPs require PHY addr. Thus need to do
+ *   vmalloc_to_phy.
+ *  -Also added optimisation there, that for range > PAGE SIZE we flush the
+ *   entire cache in one shot rather than line by line. For e.g. a module
+ *   with Code sz 600k, old code flushed 600k worth of cache (line-by-line),
+ *   while cache is only 16 or 32k.
+ */
+
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/cache.h>
+#include <linux/mmu_context.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+#include <asm/cacheflush.h>
+#include <asm/cachectl.h>
+#include <asm/setup.h>
+
+
+#ifdef CONFIG_ARC_HAS_ICACHE
+static void __ic_line_inv_no_alias(unsigned long, int);
+static void __ic_line_inv_2_alias(unsigned long, int);
+static void __ic_line_inv_4_alias(unsigned long, int);
+
+/* Holds the ptr to flush routine, dependign on size due to aliasing issues */
+static void (*___flush_icache_rtn) (unsigned long, int);
+#endif
+
+/*
+ * Read the Cache Build Confuration Registers, Decode them and save into
+ * the cpuinfo structure for later use.
+ * No Validation done here, simply read/convert the BCRs
+ */
+void __init read_decode_cache_bcr(void)
+{
+	struct bcr_cache ibcr, dbcr;
+	struct cpuinfo_arc_cache *p_ic, *p_dc;
+	unsigned int cpu = smp_processor_id();
+
+	p_ic = &cpuinfo_arc700[cpu].icache;
+	READ_BCR(ARC_REG_IC_BCR, ibcr);
+
+	if (ibcr.config == 0x3)
+		p_ic->assoc = 2;
+	p_ic->line_len = 8 << ibcr.line_len;
+	p_ic->sz = 0x200 << ibcr.sz;
+	p_ic->ver = ibcr.ver;
+
+	p_dc = &cpuinfo_arc700[cpu].dcache;
+	READ_BCR(ARC_REG_DC_BCR, dbcr);
+
+	if (dbcr.config == 0x2)
+		p_dc->assoc = 4;
+	p_dc->line_len = 16 << dbcr.line_len;
+	p_dc->sz = 0x200 << dbcr.sz;
+	p_dc->ver = dbcr.ver;
+}
+
+/*
+ * 1. Validate the Cache Geomtery (compile time config matches hardware)
+ * 2. If I-cache suffers from aliasing, setup work arounds (difft flush rtn)
+ *    (aliasing D-cache configurations are not supported YET)
+ * 3. Enable the Caches, setup default flush mode for D-Cache
+ * 3. Calculate the SHMLBA used by user space
+ */
+void __init arc_cache_init(void)
+{
+	unsigned int temp;
+#ifdef CONFIG_ARC_CACHE
+	unsigned int cpu = smp_processor_id();
+#endif
+#ifdef CONFIG_ARC_HAS_ICACHE
+	struct cpuinfo_arc_cache *ic;
+#endif
+#ifdef CONFIG_ARC_HAS_DCACHE
+	struct cpuinfo_arc_cache *dc;
+#endif
+	int way_pg_ratio = way_pg_ratio;
+
+#ifdef CONFIG_ARC_HAS_ICACHE
+	ic = &cpuinfo_arc700[cpu].icache;
+
+	/*
+	 * if Cache way size is <= page size then no aliasing exhibited
+	 * otherwise ratio determines num of aliases.
+	 * e.g. 32K I$, 2 way set assoc, 8k pg size
+	 *       way-sz = 32k/2 = 16k
+	 *       way-pg-ratio = 16k/8k = 2, so 2 aliases possible
+	 *       (meaning 1 line could be in 2 possible locations).
+	 */
+	way_pg_ratio = ic->sz / ARC_ICACHE_WAYS / PAGE_SIZE;
+	switch (way_pg_ratio) {
+	case 0:
+	case 1:
+		___flush_icache_rtn = __ic_line_inv_no_alias;
+		break;
+	case 2:
+		___flush_icache_rtn = __ic_line_inv_2_alias;
+		break;
+	case 4:
+		___flush_icache_rtn = __ic_line_inv_4_alias;
+		break;
+	default:
+		panic("Unsupported I-Cache Sz\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;
+#endif
+
+	write_aux_reg(ARC_REG_IC_CTRL, temp);
+
+#ifdef CONFIG_ARC_HAS_DCACHE
+	dc = &cpuinfo_arc700[cpu].dcache;
+
+	/* check for D-Cache aliasing */
+	if ((dc->sz / ARC_DCACHE_WAYS) > PAGE_SIZE)
+		panic("D$ aliasing not handled right now\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;
+
+#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);
+#endif
+
+	return;
+}
+
+#define OP_INV		0x1
+#define OP_FLUSH	0x2
+#define OP_FLUSH_N_INV	0x3
+
+#ifdef CONFIG_ARC_HAS_DCACHE
+
+/***************************************************************
+ * Machine specific helpers for Entire D-Cache or Per Line ops
+ */
+
+static inline void wait_for_flush(void)
+{
+	while (read_aux_reg(ARC_REG_DC_CTRL) & DC_CTRL_FLUSH_STATUS)
+		;
+}
+
+/*
+ * Operation on Entire D-Cache
+ * @cacheop = {OP_INV, OP_FLUSH, OP_FLUSH_N_INV}
+ * Note that constant propagation ensures all the checks are gone
+ * in generated code
+ */
+static inline void __dc_entire_op(const int cacheop)
+{
+	unsigned long flags, tmp = tmp;
+	int aux;
+
+	local_irq_save(flags);
+
+	if (cacheop == OP_FLUSH_N_INV) {
+		/* Dcache provides 2 cmd: FLUSH or INV
+		 * INV inturn has sub-modes: DISCARD or FLUSH-BEFORE
+		 * flush-n-inv is achieved by INV cmd but with IM=1
+		 * Default INV sub-mode is DISCARD, which needs to be toggled
+		 */
+		tmp = read_aux_reg(ARC_REG_DC_CTRL);
+		write_aux_reg(ARC_REG_DC_CTRL, tmp | DC_CTRL_INV_MODE_FLUSH);
+	}
+
+	if (cacheop & OP_INV)	/* Inv or flush-n-inv use same cmd reg */
+		aux = ARC_REG_DC_IVDC;
+	else
+		aux = ARC_REG_DC_FLSH;
+
+	write_aux_reg(aux, 0x1);
+
+	if (cacheop & OP_FLUSH)	/* flush / flush-n-inv both wait */
+		wait_for_flush();
+
+	/* Switch back the DISCARD ONLY Invalidate mode */
+	if (cacheop == OP_FLUSH_N_INV)
+		write_aux_reg(ARC_REG_DC_CTRL, tmp & ~DC_CTRL_INV_MODE_FLUSH);
+
+	local_irq_restore(flags);
+}
+
+/*
+ * Per Line Operation on D-Cache
+ * Doesn't deal with type-of-op/IRQ-disabling/waiting-for-flush-to-complete
+ * It's sole purpose is to help gcc generate ZOL
+ */
+static inline void __dc_line_loop(unsigned long start, unsigned long sz,
+					  int aux_reg)
+{
+	int num_lines, slack;
+
+	/* Ensure we properly floor/ceil the non-line aligned/sized requests
+	 * and have @start - aligned to cache line and integral @num_lines.
+	 * This however can be avoided for page sized since:
+	 *  -@start will be cache-line aligned already (being page aligned)
+	 *  -@sz will be integral multiple of line size (being page sized).
+	 */
+	if (!(__builtin_constant_p(sz) && sz == PAGE_SIZE)) {
+		slack = start & ~DCACHE_LINE_MASK;
+		sz += slack;
+		start -= slack;
+	}
+
+	num_lines = DIV_ROUND_UP(sz, ARC_DCACHE_LINE_LEN);
+
+	while (num_lines-- > 0) {
+#if (CONFIG_ARC_MMU_VER > 2)
+		/*
+		 * Just as for I$, in MMU v3, D$ ops also require
+		 * "tag" bits in DC_PTAG, "index" bits in FLDL,IVDL ops
+		 * But we pass phy addr for both. This works since Linux
+		 * doesn't support aliasing configs for D$, yet.
+		 * Thus paddr is enough to provide both tag and index.
+		 */
+		write_aux_reg(ARC_REG_DC_PTAG, start);
+#endif
+		write_aux_reg(aux_reg, start);
+		start += ARC_DCACHE_LINE_LEN;
+	}
+}
+
+/*
+ * D-Cache : Per Line INV (discard or wback+discard) or FLUSH (wback)
+ */
+static inline void __dc_line_op(unsigned long start, unsigned long sz,
+					const int cacheop)
+{
+	unsigned long flags, tmp = tmp;
+	int aux;
+
+	local_irq_save(flags);
+
+	if (cacheop == OP_FLUSH_N_INV) {
+		/*
+		 * Dcache provides 2 cmd: FLUSH or INV
+		 * INV inturn has sub-modes: DISCARD or FLUSH-BEFORE
+		 * flush-n-inv is achieved by INV cmd but with IM=1
+		 * Default INV sub-mode is DISCARD, which needs to be toggled
+		 */
+		tmp = read_aux_reg(ARC_REG_DC_CTRL);
+		write_aux_reg(ARC_REG_DC_CTRL, tmp | DC_CTRL_INV_MODE_FLUSH);
+	}
+
+	if (cacheop & OP_INV)	/* Inv / flush-n-inv use same cmd reg */
+		aux = ARC_REG_DC_IVDL;
+	else
+		aux = ARC_REG_DC_FLDL;
+
+	__dc_line_loop(start, sz, aux);
+
+	if (cacheop & OP_FLUSH)	/* flush / flush-n-inv both wait */
+		wait_for_flush();
+
+	/* Switch back the DISCARD ONLY Invalidate mode */
+	if (cacheop == OP_FLUSH_N_INV)
+		write_aux_reg(ARC_REG_DC_CTRL, tmp & ~DC_CTRL_INV_MODE_FLUSH);
+
+	local_irq_restore(flags);
+}
+
+#else
+
+#define __dc_entire_op(cacheop)
+#define __dc_line_op(start, sz, cacheop)
+
+#endif /* CONFIG_ARC_HAS_DCACHE */
+
+
+#ifdef CONFIG_ARC_HAS_ICACHE
+
+/*
+ *		I-Cache Aliasing in ARC700 VIPT caches
+ *
+ * For fetching code from I$, ARC700 uses vaddr (embedded in program code)
+ * to "index" into SET of cache-line and paddr from MMU to match the TAG
+ * in the WAYS of SET.
+ *
+ * However the CDU iterface (to flush/inv) lines from software, only takes
+ * paddr (to have simpler hardware interface). For simpler cases, using paddr
+ * alone suffices.
+ * e.g. 2-way-set-assoc, 16K I$ (8k MMU pg sz, 32b cache line size):
+ *      way_sz = cache_sz / num_ways = 16k/2 = 8k
+ *      num_sets = way_sz / line_sz = 8k/32 = 256 => 8 bits
+ *   Ignoring the bottom 5 bits corresp to the off within a 32b cacheline,
+ *   bits req for calc set-index = bits 12:5 (0 based). Since this range fits
+ *   inside the bottom 13 bits of paddr, which are same for vaddr and paddr
+ *   (with 8k pg sz), paddr alone can be safely used by CDU to unambigously
+ *   locate a cache-line.
+ *
+ * However for a difft sized cache, say 32k I$, above math yields need
+ * for 14 bits of vaddr to locate a cache line, which can't be provided by
+ * paddr, since the bit 13 (0 based) might differ between the two.
+ *
+ * This lack of extra bits needed for correct line addressing, defines the
+ * classical problem of Cache aliasing with VIPT architectures
+ * num_aliases = 1 << extra_bits
+ * e.g. 2-way-set-assoc, 32K I$ with 8k MMU pg sz => 2 aliases
+ *      2-way-set-assoc, 64K I$ with 8k MMU pg sz => 4 aliases
+ *      2-way-set-assoc, 16K I$ with 8k MMU pg sz => NO aliases
+ *
+ * ------------------
+ * MMU v1/v2 (Fixed Page Size 8k)
+ * ------------------
+ * The solution was to provide CDU with these additonal vaddr bits. These
+ * would be bits [x:13], x would depend on cache-geom.
+ * H/w folks chose [17:13] to be a future safe range, and moreso these 5 bits
+ * of vaddr could easily be "stuffed" in the paddr as bits [4:0] since the
+ * orig 5 bits of paddr were anyways ignored by CDU line ops, as they
+ * represent the offset within cache-line. The adv of using this "clumsy"
+ * interface for additional info was no new reg was needed in CDU.
+ *
+ * 17:13 represented the max num of bits passable, actual bits needed were
+ * fewer, based on the num-of-aliases possible.
+ * -for 2 alias possibility, only bit 13 needed (32K cache)
+ * -for 4 alias possibility, bits 14:13 needed (64K cache)
+ *
+ * Since vaddr was not available for all instances of I$ flush req by core
+ * kernel, the only safe way (non-optimal though) was to kill all possible
+ * lines which could represent an alias (even if they didnt represent one
+ * in execution).
+ * e.g. for 64K I$, 4 aliases possible, so we did
+ *      flush start
+ *      flush start | 0x01
+ *      flush start | 0x2
+ *      flush start | 0x3
+ *
+ * The penalty was invoking the operation itself, since tag match is anyways
+ * paddr based, a line which didn't represent an alias would not match the
+ * paddr, hence wont be killed
+ *
+ * Note that aliasing concerns are independent of line-sz for a given cache
+ * geometry (size + set_assoc) because the extra bits required by line-sz are
+ * reduced from the set calc.
+ * e.g. 2-way-set-assoc, 32K I$ with 8k MMU pg sz and using math above
+ *  32b line-sz: 9 bits set-index-calc, 5 bits offset-in-line => 1 extra bit
+ *  64b line-sz: 8 bits set-index-calc, 6 bits offset-in-line => 1 extra bit
+ *
+ * ------------------
+ * MMU v3
+ * ------------------
+ * This ver of MMU supports var page sizes (1k-16k) - Linux will support
+ * 8k (default), 16k and 4k.
+ * However from hardware perspective, smaller page sizes aggrevate aliasing
+ * meaning more vaddr bits needed to disambiguate the cache-line-op ;
+ * the existing scheme of piggybacking won't work for certain configurations.
+ * Two new registers IC_PTAG and DC_PTAG inttoduced.
+ * "tag" bits are provided in PTAG, index bits in existing IVIL/IVDL/FLDL regs
+ */
+
+/***********************************************************
+ * Machine specific helpers for per line I-Cache invalidate.
+ * 3 routines to accpunt for 1, 2, 4 aliases possible
+ */
+
+static void __ic_line_inv_no_alias(unsigned long start, int num_lines)
+{
+	while (num_lines-- > 0) {
+#if (CONFIG_ARC_MMU_VER > 2)
+		write_aux_reg(ARC_REG_IC_PTAG, start);
+#endif
+		write_aux_reg(ARC_REG_IC_IVIL, start);
+		start += ARC_ICACHE_LINE_LEN;
+	}
+}
+
+static void __ic_line_inv_2_alias(unsigned long start, int num_lines)
+{
+	while (num_lines-- > 0) {
+
+#if (CONFIG_ARC_MMU_VER > 2)
+		/*
+		 *  MMU v3, CDU prog model (for line ops) now uses a new IC_PTAG
+		 * reg to pass the "tag" bits and existing IVIL reg only looks
+		 * at bits relevant for "index" (details above)
+		 * Programming Notes:
+		 * -when writing tag to PTAG reg, bit chopping can be avoided,
+		 *  CDU ignores non-tag bits.
+		 * -Ideally "index" must be computed from vaddr, but it is not
+		 *  avail in these rtns. So to be safe, we kill the lines in all
+		 *  possible indexes corresp to num of aliases possible for
+		 *  given cache config.
+		 */
+		write_aux_reg(ARC_REG_IC_PTAG, start);
+		write_aux_reg(ARC_REG_IC_IVIL,
+				  start & ~(0x1 << PAGE_SHIFT));
+		write_aux_reg(ARC_REG_IC_IVIL, start | (0x1 << PAGE_SHIFT));
+#else
+		write_aux_reg(ARC_REG_IC_IVIL, start);
+		write_aux_reg(ARC_REG_IC_IVIL, start | 0x01);
+#endif
+		start += ARC_ICACHE_LINE_LEN;
+	}
+}
+
+static void __ic_line_inv_4_alias(unsigned long start, int num_lines)
+{
+	while (num_lines-- > 0) {
+
+#if (CONFIG_ARC_MMU_VER > 2)
+		write_aux_reg(ARC_REG_IC_PTAG, start);
+
+		write_aux_reg(ARC_REG_IC_IVIL,
+				  start & ~(0x3 << PAGE_SHIFT));
+		write_aux_reg(ARC_REG_IC_IVIL,
+				  start & ~(0x2 << PAGE_SHIFT));
+		write_aux_reg(ARC_REG_IC_IVIL,
+				  start & ~(0x1 << PAGE_SHIFT));
+		write_aux_reg(ARC_REG_IC_IVIL, start | (0x3 << PAGE_SHIFT));
+#else
+		write_aux_reg(ARC_REG_IC_IVIL, start);
+		write_aux_reg(ARC_REG_IC_IVIL, start | 0x01);
+		write_aux_reg(ARC_REG_IC_IVIL, start | 0x02);
+		write_aux_reg(ARC_REG_IC_IVIL, start | 0x03);
+#endif
+		start += ARC_ICACHE_LINE_LEN;
+	}
+}
+
+static void __ic_line_inv(unsigned long start, unsigned long sz)
+{
+	unsigned long flags;
+	int num_lines, slack;
+
+	/*
+	 * Ensure we properly floor/ceil the non-line aligned/sized requests
+	 * and have @start - aligned to cache line, and integral @num_lines
+	 * However page sized flushes can be compile time optimised.
+	 *  -@start will be cache-line aligned already (being page aligned)
+	 *  -@sz will be integral multiple of line size (being page sized).
+	 */
+	if (!(__builtin_constant_p(sz) && sz == PAGE_SIZE)) {
+		slack = start & ~ICACHE_LINE_MASK;
+		sz += slack;
+		start -= slack;
+	}
+
+	num_lines = DIV_ROUND_UP(sz, ARC_ICACHE_LINE_LEN);
+
+	local_irq_save(flags);
+	(*___flush_icache_rtn) (start, num_lines);
+	local_irq_restore(flags);
+}
+
+/* Unlike routines above, having vaddr for flush op (along with paddr),
+ * prevents the need to speculatively kill the lines in multiple sets
+ * based on ratio of way_sz : pg_sz
+ */
+static void __ic_line_inv_vaddr(unsigned long phy_start,
+					 unsigned long vaddr, unsigned long sz)
+{
+	unsigned long flags;
+	int num_lines, slack;
+	unsigned int addr;
+
+	slack = phy_start & ~ICACHE_LINE_MASK;
+	sz += slack;
+	phy_start -= slack;
+	num_lines = DIV_ROUND_UP(sz, ARC_ICACHE_LINE_LEN);
+
+#if (CONFIG_ARC_MMU_VER > 2)
+	vaddr &= ~ICACHE_LINE_MASK;
+	addr = phy_start;
+#else
+	/* bits 17:13 of vaddr go as bits 4:0 of paddr */
+	addr = phy_start | ((vaddr >> 13) & 0x1F);
+#endif
+
+	local_irq_save(flags);
+	while (num_lines-- > 0) {
+#if (CONFIG_ARC_MMU_VER > 2)
+		/* tag comes from phy addr */
+		write_aux_reg(ARC_REG_IC_PTAG, addr);
+
+		/* index bits come from vaddr */
+		write_aux_reg(ARC_REG_IC_IVIL, vaddr);
+		vaddr += ARC_ICACHE_LINE_LEN;
+#else
+		/* this paddr contains vaddrs bits as needed */
+		write_aux_reg(ARC_REG_IC_IVIL, addr);
+#endif
+		addr += ARC_ICACHE_LINE_LEN;
+	}
+	local_irq_restore(flags);
+}
+
+#else
+
+#define __ic_line_inv(start, sz)
+#define __ic_line_inv_vaddr(pstart, vstart, sz)
+
+#endif /* CONFIG_ARC_HAS_ICACHE */
+
+
+/***********************************************************
+ * Exported APIs
+ */
+
+/* TBD: use pg_arch_1 to optimize this */
+void flush_dcache_page(struct page *page)
+{
+	__dc_line_op((unsigned long)page_address(page), PAGE_SIZE, OP_FLUSH);
+}
+EXPORT_SYMBOL(flush_dcache_page);
+
+
+void dma_cache_wback_inv(unsigned long start, unsigned long sz)
+{
+	__dc_line_op(start, sz, OP_FLUSH_N_INV);
+}
+EXPORT_SYMBOL(dma_cache_wback_inv);
+
+void dma_cache_inv(unsigned long start, unsigned long sz)
+{
+	__dc_line_op(start, sz, OP_INV);
+}
+EXPORT_SYMBOL(dma_cache_inv);
+
+void dma_cache_wback(unsigned long start, unsigned long sz)
+{
+	__dc_line_op(start, sz, OP_FLUSH);
+}
+EXPORT_SYMBOL(dma_cache_wback);
+
+/*
+ * This is API for making I/D Caches consistent when modifying code
+ * (loadable modules, kprobes,  etc)
+ * This is called on insmod, with kernel virtual address for CODE of
+ * the module. ARC cache maintenance ops require PHY address thus we
+ * need to convert vmalloc addr to PHY addr
+ */
+void flush_icache_range(unsigned long kstart, unsigned long kend)
+{
+	unsigned int tot_sz, off, sz;
+	unsigned long phy, pfn;
+	unsigned long flags;
+
+	/* printk("Kernel Cache Cohenercy: %lx to %lx\n",kstart, kend); */
+
+	/* This is not the right API for user virtual address */
+	if (kstart < TASK_SIZE) {
+		BUG_ON("Flush icache range for user virtual addr space");
+		return;
+	}
+
+	/* Shortcut for bigger flush ranges.
+	 * Here we don't care if this was kernel virtual or phy addr
+	 */
+	tot_sz = kend - kstart;
+	if (tot_sz > PAGE_SIZE) {
+		flush_cache_all();
+		return;
+	}
+
+	/* Case: Kernel Phy addr (0x8000_0000 onwards) */
+	if (likely(kstart > PAGE_OFFSET)) {
+		__ic_line_inv(kstart, kend - kstart);
+		__dc_line_op(kstart, kend - kstart, OP_FLUSH);
+		return;
+	}
+
+	/*
+	 * Case: Kernel Vaddr (0x7000_0000 to 0x7fff_ffff)
+	 * (1) ARC Cache Maintenance ops only take Phy addr, hence special
+	 *     handling of kernel vaddr.
+	 *
+	 * (2) Despite @tot_sz being < PAGE_SIZE (bigger cases handled already),
+	 *     it still needs to handle  a 2 page scenario, where the range
+	 *     straddles across 2 virtual pages and hence need for loop
+	 */
+	while (tot_sz > 0) {
+		off = kstart % PAGE_SIZE;
+		pfn = vmalloc_to_pfn((void *)kstart);
+		phy = (pfn << PAGE_SHIFT) + off;
+		sz = min_t(unsigned int, tot_sz, PAGE_SIZE - off);
+		local_irq_save(flags);
+		__dc_line_op(phy, sz, OP_FLUSH);
+		__ic_line_inv(phy, sz);
+		local_irq_restore(flags);
+		kstart += sz;
+		tot_sz -= sz;
+	}
+}
+
+/*
+ * Optimised ver of flush_icache_range() with spec callers: ptrace/signals
+ * where vaddr is also available. This allows passing both vaddr and paddr
+ * bits to CDU for cache flush, short-circuting the current pessimistic algo
+ * which kills all possible aliases.
+ * An added adv of knowing that vaddr is user-vaddr avoids various checks
+ * and handling for k-vaddr, k-paddr as done in orig ver above
+ */
+void flush_icache_range_vaddr(unsigned long paddr, unsigned long u_vaddr,
+			      int len)
+{
+	__ic_line_inv_vaddr(paddr, u_vaddr, len);
+	__dc_line_op(paddr, len, OP_FLUSH);
+}
+
+/*
+ * XXX: This also needs to be optim using pg_arch_1
+ * This is called when a page-cache page is about to be mapped into a
+ * user process' address space.  It offers an opportunity for a
+ * port to ensure d-cache/i-cache coherency if necessary.
+ */
+void flush_icache_page(struct vm_area_struct *vma, struct page *page)
+{
+	if (!(vma->vm_flags & VM_EXEC))
+		return;
+
+	__ic_line_inv((unsigned long)page_address(page), PAGE_SIZE);
+}
+
+void flush_icache_all(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	write_aux_reg(ARC_REG_IC_IVIC, 1);
+
+	/* lr will not complete till the icache inv operation is not over */
+	read_aux_reg(ARC_REG_IC_CTRL);
+	local_irq_restore(flags);
+}
+
+noinline void flush_cache_all(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	flush_icache_all();
+	__dc_entire_op(OP_FLUSH_N_INV);
+
+	local_irq_restore(flags);
+
+}
+
+/**********************************************************************
+ * Explicit Cache flush request from user space via syscall
+ * Needed for JITs which generate code on the fly
+ */
+SYSCALL_DEFINE3(cacheflush, uint32_t, start, uint32_t, sz, uint32_t, flags)
+{
+	/* TBD: optimize this */
+	flush_cache_all();
+	return 0;
+}
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 29/71] ARC: I/O and DMA Mappings
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (10 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 23/71] ARC: Cache Flush Management Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 30/71] ARC: Boot #1: low-level, setup_arch(), /proc/cpuinfo, mem init Vineet Gupta
                   ` (13 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/include/asm/dma-mapping.h            |  205 +++++++++++++++++++++++++
 arch/arc/include/asm/dma.h                    |   14 ++
 arch/arc/include/asm/io.h                     |  103 +++++++++++++
 arch/arc/mm/dma.c                             |   94 +++++++++++
 arch/arc/mm/ioremap.c                         |   67 ++++++++
 arch/arc/plat-arcfpga/include/plat/dma_addr.h |   45 ++++++
 6 files changed, 528 insertions(+), 0 deletions(-)
 create mode 100644 arch/arc/include/asm/dma-mapping.h
 create mode 100644 arch/arc/include/asm/dma.h
 create mode 100644 arch/arc/include/asm/io.h
 create mode 100644 arch/arc/mm/dma.c
 create mode 100644 arch/arc/mm/ioremap.c
 create mode 100644 arch/arc/plat-arcfpga/include/plat/dma_addr.h

diff --git a/arch/arc/include/asm/dma-mapping.h b/arch/arc/include/asm/dma-mapping.h
new file mode 100644
index 0000000..7fd150e
--- /dev/null
+++ b/arch/arc/include/asm/dma-mapping.h
@@ -0,0 +1,205 @@
+/*
+ * DMA Mapping glue for ARC
+ *
+ * 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_ARC_DMA_MAPPING_H
+#define ASM_ARC_DMA_MAPPING_H
+
+#include <asm-generic/dma-coherent.h>
+#include <asm/cacheflush.h>
+#include <plat/dma_addr.h>
+
+void *dma_alloc_noncoherent(struct device *dev, size_t size,
+			    dma_addr_t *dma_handle, gfp_t gfp);
+
+void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
+			  dma_addr_t dma_handle);
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+			 dma_addr_t *dma_handle, gfp_t gfp);
+
+void dma_free_coherent(struct device *dev, size_t size, void *kvaddr,
+		       dma_addr_t dma_handle);
+
+/* drivers/base/dma-mapping.c */
+extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
+			   void *cpu_addr, dma_addr_t dma_addr, size_t size);
+extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
+				  void *cpu_addr, dma_addr_t dma_addr,
+				  size_t size);
+
+#define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s)
+#define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s)
+
+/*
+ * streaming DMA Mapping API...
+ * CPU accesses page via normal paddr, thus needs to explicitly made
+ * consistent before each use
+ */
+
+static inline void __inline_dma_cache_sync(unsigned long paddr, size_t size,
+					   enum dma_data_direction dir)
+{
+	switch (dir) {
+	case DMA_FROM_DEVICE:
+		dma_cache_inv(paddr, size);
+		break;
+	case DMA_TO_DEVICE:
+		dma_cache_wback(paddr, size);
+		break;
+	case DMA_BIDIRECTIONAL:
+		dma_cache_wback_inv(paddr, size);
+		break;
+	default:
+		pr_err("Invalid DMA dir [%d] for OP @ %lx\n", dir, paddr);
+	}
+}
+
+void __arc_dma_cache_sync(unsigned long paddr, size_t size,
+			  enum dma_data_direction dir);
+
+#define _dma_cache_sync(addr, sz, dir)			\
+do {							\
+	if (__builtin_constant_p(dir))			\
+		__inline_dma_cache_sync(addr, sz, dir);	\
+	else						\
+		__arc_dma_cache_sync(addr, sz, dir);	\
+}							\
+while (0);
+
+static inline dma_addr_t
+dma_map_single(struct device *dev, void *cpu_addr, size_t size,
+	       enum dma_data_direction dir)
+{
+	_dma_cache_sync((unsigned long)cpu_addr, size, dir);
+	return plat_kernel_addr_to_dma(dev, cpu_addr);
+}
+
+static inline void
+dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
+		 size_t size, enum dma_data_direction dir)
+{
+}
+
+static inline dma_addr_t
+dma_map_page(struct device *dev, struct page *page,
+	     unsigned long offset, size_t size,
+	     enum dma_data_direction dir)
+{
+	unsigned long paddr = page_to_phys(page) + offset;
+	return dma_map_single(dev, (void *)paddr, size, dir);
+}
+
+static inline void
+dma_unmap_page(struct device *dev, dma_addr_t dma_handle,
+	       size_t size, enum dma_data_direction dir)
+{
+}
+
+static inline int
+dma_map_sg(struct device *dev, struct scatterlist *sg,
+	   int nents, enum dma_data_direction dir)
+{
+	struct scatterlist *s;
+	int i;
+
+	for_each_sg(sg, s, nents, i)
+		sg->dma_address = dma_map_page(dev, sg_page(s), s->offset,
+					       s->length, dir);
+
+	return nents;
+}
+
+static inline void
+dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+	     int nents, enum dma_data_direction dir)
+{
+	struct scatterlist *s;
+	int i;
+
+	for_each_sg(sg, s, nents, i)
+		dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
+}
+
+static inline void
+dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
+			size_t size, enum dma_data_direction dir)
+{
+	_dma_cache_sync(plat_dma_addr_to_kernel(dev, dma_handle), size,
+			DMA_FROM_DEVICE);
+}
+
+static inline void
+dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
+			   size_t size, enum dma_data_direction dir)
+{
+	_dma_cache_sync(plat_dma_addr_to_kernel(dev, dma_handle), size,
+			DMA_TO_DEVICE);
+}
+
+static inline void
+dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
+			      unsigned long offset, size_t size,
+			      enum dma_data_direction direction)
+{
+	_dma_cache_sync(plat_dma_addr_to_kernel(dev, dma_handle) + offset,
+			size, DMA_FROM_DEVICE);
+}
+
+static inline void
+dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
+				 unsigned long offset, size_t size,
+				 enum dma_data_direction direction)
+{
+	_dma_cache_sync(plat_dma_addr_to_kernel(dev, dma_handle) + offset,
+			size, DMA_TO_DEVICE);
+}
+
+static inline void
+dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+		    enum dma_data_direction dir)
+{
+	int i;
+
+	for (i = 0; i < nelems; i++, sg++)
+		_dma_cache_sync((unsigned int)sg_virt(sg), sg->length, dir);
+}
+
+static inline void
+dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+		       enum dma_data_direction dir)
+{
+	int i;
+
+	for (i = 0; i < nelems; i++, sg++)
+		_dma_cache_sync((unsigned int)sg_virt(sg), sg->length, dir);
+}
+
+static inline int dma_supported(struct device *dev, u64 dma_mask)
+{
+	/* Support 32 bit DMA mask exclusively */
+	return dma_mask == DMA_BIT_MASK(32);
+}
+
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+	return 0;
+}
+
+static inline int dma_set_mask(struct device *dev, u64 dma_mask)
+{
+	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+		return -EIO;
+
+	*dev->dma_mask = dma_mask;
+
+	return 0;
+}
+
+#endif
diff --git a/arch/arc/include/asm/dma.h b/arch/arc/include/asm/dma.h
new file mode 100644
index 0000000..ca7c451
--- /dev/null
+++ b/arch/arc/include/asm/dma.h
@@ -0,0 +1,14 @@
+/*
+ * 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_ARC_DMA_H
+#define ASM_ARC_DMA_H
+
+#define MAX_DMA_ADDRESS 0xC0000000
+
+#endif
diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h
new file mode 100644
index 0000000..d20051b
--- /dev/null
+++ b/arch/arc/include/asm/io.h
@@ -0,0 +1,103 @@
+/*
+ * 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_ARC_IO_H
+#define _ASM_ARC_IO_H
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <asm/page.h>
+
+#define PCI_IOBASE ((void __iomem *)0)
+
+extern void __iomem *ioremap(unsigned long physaddr, unsigned long size);
+extern void iounmap(const void __iomem *addr);
+
+#define ioremap_nocache(phy, sz)	ioremap(phy, sz)
+#define ioremap_wc(phy, sz)		ioremap(phy, sz)
+
+/* Change struct page to physical address */
+#define page_to_phys(page)		(page_to_pfn(page) << PAGE_SHIFT)
+
+#define __raw_readb __raw_readb
+static inline u8 __raw_readb(const volatile void __iomem *addr)
+{
+	u8 b;
+
+	__asm__ __volatile__(
+	"	ldb%U1 %0, %1	\n"
+	: "=r" (b)
+	: "m" (*(volatile u8 __force *)addr)
+	: "memory");
+
+	return b;
+}
+
+#define __raw_readw __raw_readw
+static inline u16 __raw_readw(const volatile void __iomem *addr)
+{
+	u16 s;
+
+	__asm__ __volatile__(
+	"	ldw%U1 %0, %1	\n"
+	: "=r" (s)
+	: "m" (*(volatile u16 __force *)addr)
+	: "memory");
+
+	return s;
+}
+
+#define __raw_readl __raw_readl
+static inline u32 __raw_readl(const volatile void __iomem *addr)
+{
+	u32 w;
+
+	__asm__ __volatile__(
+	"	ld%U1 %0, %1	\n"
+	: "=r" (w)
+	: "m" (*(volatile u32 __force *)addr)
+	: "memory");
+
+	return w;
+}
+
+#define __raw_writeb __raw_writeb
+static inline void __raw_writeb(u8 b, volatile void __iomem *addr)
+{
+	__asm__ __volatile__(
+	"	stb%U1 %0, %1	\n"
+	:
+	: "r" (b), "m" (*(volatile u8 __force *)addr)
+	: "memory");
+}
+
+#define __raw_writew __raw_writew
+static inline void __raw_writew(u16 s, volatile void __iomem *addr)
+{
+	__asm__ __volatile__(
+	"	stw%U1 %0, %1	\n"
+	:
+	: "r" (s), "m" (*(volatile u16 __force *)addr)
+	: "memory");
+
+}
+
+#define __raw_writel __raw_writel
+static inline void __raw_writel(u32 w, volatile void __iomem *addr)
+{
+	__asm__ __volatile__(
+	"	st%U1 %0, %1	\n"
+	:
+	: "r" (w), "m" (*(volatile u32 __force *)addr)
+	: "memory");
+
+}
+
+#include <asm-generic/io.h>
+
+#endif /* _ASM_ARC_IO_H */
diff --git a/arch/arc/mm/dma.c b/arch/arc/mm/dma.c
new file mode 100644
index 0000000..12cc648
--- /dev/null
+++ b/arch/arc/mm/dma.c
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+/*
+ * DMA Coherent API Notes
+ *
+ * I/O is inherently non-coherent on ARC. So a coherent DMA buffer is
+ * implemented by accessintg it using a kernel virtual address, with
+ * Cache bit off in the TLB entry.
+ *
+ * The default DMA address == Phy address which is 0x8000_0000 based.
+ * A platform/device can make it zero based, by over-riding
+ * plat_{dma,kernel}_addr_to_{kernel,dma}
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/dma-debug.h>
+#include <linux/export.h>
+#include <asm/cacheflush.h>
+
+/*
+ * Helpers for Coherent DMA API.
+ */
+void *dma_alloc_noncoherent(struct device *dev, size_t size,
+			    dma_addr_t *dma_handle, gfp_t gfp)
+{
+	void *paddr;
+
+	/* This is linear addr (0x8000_0000 based) */
+	paddr = alloc_pages_exact(size, gfp);
+	if (!paddr)
+		return NULL;
+
+	/* This is bus address, platform dependent */
+	*dma_handle = plat_kernel_addr_to_dma(dev, paddr);
+
+	return paddr;
+}
+EXPORT_SYMBOL(dma_alloc_noncoherent);
+
+void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
+			  dma_addr_t dma_handle)
+{
+	free_pages_exact((void *)plat_dma_addr_to_kernel(dev, dma_handle),
+			 size);
+}
+EXPORT_SYMBOL(dma_free_noncoherent);
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+			 dma_addr_t *dma_handle, gfp_t gfp)
+{
+	void *paddr, *kvaddr;
+
+	/* This is linear addr (0x8000_0000 based) */
+	paddr = alloc_pages_exact(size, gfp);
+	if (!paddr)
+		return NULL;
+
+	/* This is kernel Virtual address (0x7000_0000 based) */
+	kvaddr = ioremap_nocache((unsigned long)paddr, size);
+	if (kvaddr != NULL)
+		memset(kvaddr, 0, size);
+
+	/* This is bus address, platform dependent */
+	*dma_handle = plat_kernel_addr_to_dma(dev, paddr);
+
+	return kvaddr;
+}
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_coherent(struct device *dev, size_t size, void *kvaddr,
+		       dma_addr_t dma_handle)
+{
+	iounmap((void __force __iomem *)kvaddr);
+
+	free_pages_exact((void *)plat_dma_addr_to_kernel(dev, dma_handle),
+			 size);
+}
+EXPORT_SYMBOL(dma_free_coherent);
+
+/*
+ * Helper for streaming DMA...
+ */
+void __arc_dma_cache_sync(unsigned long paddr, size_t size,
+			  enum dma_data_direction dir)
+{
+	__inline_dma_cache_sync(paddr, size, dir);
+}
+EXPORT_SYMBOL(__arc_dma_cache_sync);
diff --git a/arch/arc/mm/ioremap.c b/arch/arc/mm/ioremap.c
new file mode 100644
index 0000000..52518b6
--- /dev/null
+++ b/arch/arc/mm/ioremap.c
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/cache.h>
+
+void __iomem *ioremap(unsigned long paddr, unsigned long size)
+{
+	unsigned long vaddr;
+	struct vm_struct *area;
+	unsigned long off, end;
+	const pgprot_t prot = PAGE_KERNEL_NO_CACHE;
+
+	/* Don't allow wraparound or zero size */
+	end = paddr + size - 1;
+	if (!size || (end < paddr))
+		return NULL;
+
+	/* If the region is h/w uncached, nothing special needed */
+	if (paddr >= ARC_UNCACHED_ADDR_SPACE)
+		return (void __iomem *)paddr;
+
+	/* An early platform driver might end up here */
+	if (!slab_is_available())
+		return NULL;
+
+	/* Mappings have to be page-aligned, page-sized */
+	off = paddr & ~PAGE_MASK;
+	paddr &= PAGE_MASK;
+	size = PAGE_ALIGN(end + 1) - paddr;
+
+	/*
+	 * Ok, go for it..
+	 */
+	area = get_vm_area(size, VM_IOREMAP);
+	if (!area)
+		return NULL;
+
+	area->phys_addr = paddr;
+	vaddr = (unsigned long)area->addr;
+	if (ioremap_page_range(vaddr, vaddr + size, paddr, prot)) {
+		vfree(area->addr);
+		return NULL;
+	}
+
+	return (void __iomem *)(off + (char __iomem *)vaddr);
+}
+EXPORT_SYMBOL(ioremap);
+
+void iounmap(const void __iomem *addr)
+{
+	if (addr >= (void __force __iomem *)ARC_UNCACHED_ADDR_SPACE)
+		return;
+
+	vfree((void *)(PAGE_MASK & (unsigned long __force)addr));
+}
+EXPORT_SYMBOL(iounmap);
diff --git a/arch/arc/plat-arcfpga/include/plat/dma_addr.h b/arch/arc/plat-arcfpga/include/plat/dma_addr.h
new file mode 100644
index 0000000..0e96343
--- /dev/null
+++ b/arch/arc/plat-arcfpga/include/plat/dma_addr.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ *
+ * vineetg: Feb 2009
+ *  -For AA4 board, kernel to DMA address APIs
+ */
+
+/*
+ * kernel addresses are 0x800_000 based, while Bus addr are 0 based
+ */
+
+#ifndef __PLAT_DMA_ADDR_H
+#define __PLAT_DMA_ADDR_H
+
+#include <linux/device.h>
+
+static inline unsigned long plat_dma_addr_to_kernel(struct device *dev,
+						    dma_addr_t dma_addr)
+{
+	return dma_addr + PAGE_OFFSET;
+}
+
+static inline dma_addr_t plat_kernel_addr_to_dma(struct device *dev, void *ptr)
+{
+	unsigned long addr = (unsigned long)ptr;
+	/*
+	 * To Catch buggy drivers which can call DMA map API with kernel vaddr
+	 * i.e. for buffers alloc via vmalloc or ioremap which are not
+	 * gaurnateed to be PHY contiguous and hence unfit for DMA anyways.
+	 * On ARC kernel virtual address is 0x7000_0000 to 0x7FFF_FFFF, so
+	 * ideally we want to check this range here, but our implementation is
+	 * better as it checks for even worse user virtual address as well.
+	 */
+	if (likely(addr >= PAGE_OFFSET))
+		return addr - PAGE_OFFSET;
+
+	BUG();
+	return addr;
+}
+
+#endif
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 30/71] ARC: Boot #1: low-level, setup_arch(), /proc/cpuinfo, mem init
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (11 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 29/71] ARC: I/O and DMA Mappings Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 32/71] ARC: [DeviceTree] Basic support Vineet Gupta
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
 arch/arc/Kconfig                 |    2 +
 arch/arc/include/asm/arcregs.h   |    5 +
 arch/arc/include/asm/setup.h     |   22 +++++
 arch/arc/kernel/head.S           |   78 +++++++++++++++++
 arch/arc/kernel/reset.c          |   33 +++++++
 arch/arc/kernel/setup.c          |  166 ++++++++++++++++++++++++++++++++++++
 arch/arc/mm/init.c               |  171 ++++++++++++++++++++++++++++++++++++++
 arch/arc/plat-arcfpga/platform.c |   29 +++++++
 8 files changed, 506 insertions(+), 0 deletions(-)
 create mode 100644 arch/arc/include/asm/setup.h
 create mode 100644 arch/arc/kernel/head.S
 create mode 100644 arch/arc/kernel/reset.c
 create mode 100644 arch/arc/kernel/setup.c
 create mode 100644 arch/arc/mm/init.c
 create mode 100644 arch/arc/plat-arcfpga/platform.c

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 756beff..a353849 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -23,7 +23,9 @@ config ARC
 	select GENERIC_SIGALTSTACK
 	select GENERIC_SMP_IDLE_THREAD
 	select HAVE_GENERIC_HARDIRQS
+	select HAVE_MEMBLOCK
 	select MODULES_USE_ELF_RELA
+	select NO_BOOTMEM
 
 config SCHED_OMIT_FRAME_POINTER
 	def_bool y
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index 1c24485..9e42611 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -258,6 +258,11 @@
 	}						\
 }
 
+/* Helpers */
+#define TO_KB(bytes)		((bytes) >> 10)
+#define TO_MB(bytes)		(TO_KB(bytes) >> 10)
+#define PAGES_TO_KB(n_pages)	((n_pages) << (PAGE_SHIFT - 10))
+#define PAGES_TO_MB(n_pages)	(PAGES_TO_KB(n_pages) >> 10)
 
 #ifdef CONFIG_ARC_FPU_SAVE_RESTORE
 /* These DPFP regs need to be saved/restored across ctx-sw */
diff --git a/arch/arc/include/asm/setup.h b/arch/arc/include/asm/setup.h
new file mode 100644
index 0000000..ab427e6
--- /dev/null
+++ b/arch/arc/include/asm/setup.h
@@ -0,0 +1,22 @@
+/*
+ * 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 __ASMARC_SETUP_H
+#define __ASMARC_SETUP_H
+
+#include <linux/types.h>
+
+#define COMMAND_LINE_SIZE 256
+
+extern int root_mountflags, end_mem;
+extern int running_on_hw;
+
+void __init setup_processor(void);
+void __init setup_arch_memory(void);
+
+#endif /* __ASMARC_SETUP_H */
diff --git a/arch/arc/kernel/head.S b/arch/arc/kernel/head.S
new file mode 100644
index 0000000..e63f6a4
--- /dev/null
+++ b/arch/arc/kernel/head.S
@@ -0,0 +1,78 @@
+/*
+ * ARC CPU startup Code
+ *
+ * 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.
+ *
+ * Vineetg: Dec 2007
+ *  -Check if we are running on Simulator or on real hardware
+ *      to skip certain things during boot on simulator
+ */
+
+#include <asm/asm-offsets.h>
+#include <asm/entry.h>
+#include <linux/linkage.h>
+#include <asm/arcregs.h>
+
+	.cpu A7
+
+	.section .init.text, "ax",@progbits
+	.type stext, @function
+	.globl stext
+stext:
+	;-------------------------------------------------------------------
+	; Don't clobber r0-r4 yet. It might have bootloader provided info
+	;-------------------------------------------------------------------
+
+	; Clear BSS before updating any globals
+	; XXX: use ZOL here
+	mov	r5, __bss_start
+	mov	r6, __bss_stop
+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:
+
+	; Identify if running on ISS vs Silicon
+	; 	IDENTITY Reg [ 3  2  1  0 ]
+	;	(chip-id)      ^^^^^		==> 0xffff for ISS
+	lr	r0, [identity]
+	lsr	r3, r0, 16
+	cmp	r3, 0xffff
+	mov.z	r4, 0
+	mov.nz	r4, 1
+	st	r4, [@running_on_hw]
+
+	; setup "current" tsk and optionally cache it in dedicated r25
+	mov	r9, @init_task
+	SET_CURR_TASK_ON_CPU  r9, r0	; r9 = tsk, r0 = scratch
+
+	; setup stack (fp, sp)
+	mov	fp, 0
+
+	; tsk->thread_info is really a PAGE, whose bottom hoists stack
+	GET_TSK_STACK_BASE r9, sp	; r9 = tsk, sp = stack base(output)
+
+	j	start_kernel	; "C" entry point
diff --git a/arch/arc/kernel/reset.c b/arch/arc/kernel/reset.c
new file mode 100644
index 0000000..e227a2b
--- /dev/null
+++ b/arch/arc/kernel/reset.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/printk.h>
+#include <linux/reboot.h>
+#include <linux/pm.h>
+
+void machine_halt(void)
+{
+	/* Halt the processor */
+	__asm__ __volatile__("flag  1\n");
+}
+
+void machine_restart(char *__unused)
+{
+	/* Soft reset : jump to reset vector */
+	pr_info("Put your restart handler here\n");
+	machine_halt();
+}
+
+void machine_power_off(void)
+{
+	/* FIXME ::  power off ??? */
+	machine_halt();
+}
+
+void (*pm_power_off) (void) = NULL;
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
new file mode 100644
index 0000000..82ac206
--- /dev/null
+++ b/arch/arc/kernel/setup.c
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+
+#include <linux/seq_file.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/root_dev.h>
+#include <linux/console.h>
+#include <linux/module.h>
+#include <linux/cpu.h>
+#include <asm/arcregs.h>
+#include <asm/tlb.h>
+#include <asm/cache.h>
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <asm/irq.h>
+#include <asm/arcregs.h>
+
+#define FIX_PTR(x)  __asm__ __volatile__(";" : "+r"(x))
+
+int running_on_hw = 1;	/* vs. on ISS */
+
+char __initdata command_line[COMMAND_LINE_SIZE];
+
+struct task_struct *_current_task[NR_CPUS];	/* For stack switching */
+
+struct cpuinfo_arc cpuinfo_arc700[NR_CPUS];
+
+void __init read_arc_build_cfg_regs(void)
+{
+	read_decode_mmu_bcr();
+	read_decode_cache_bcr();
+}
+
+/*
+ * Initialize and setup the processor core
+ * This is called by all the CPUs thus should not do special case stuff
+ *    such as only for boot CPU etc
+ */
+
+void __init setup_processor(void)
+{
+	read_arc_build_cfg_regs();
+	arc_init_IRQ();
+	arc_mmu_init();
+	arc_cache_init();
+}
+
+void __init __attribute__((weak)) arc_platform_early_init(void)
+{
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+#ifdef CONFIG_CMDLINE_UBOOT
+	/* Make sure that a whitespace is inserted before */
+	strlcat(command_line, " ", sizeof(command_line));
+#endif
+	/*
+	 * Append .config cmdline to base command line, which might already
+	 * contain u-boot "bootargs" (handled by head.S, if so configured)
+	 */
+	strlcat(command_line, CONFIG_CMDLINE, sizeof(command_line));
+
+	/* Save unparsed command line copy for /proc/cmdline */
+	strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+	*cmdline_p = command_line;
+
+	/* To force early parsing of things like mem=xxx */
+	parse_early_param();
+
+	/* Platform/board specific: e.g. early console registration */
+	arc_platform_early_init();
+
+	setup_processor();
+
+	setup_arch_memory();
+
+	/* Can be issue if someone passes cmd line arg "ro"
+	 * But that is unlikely so keeping it as it is
+	 */
+	root_mountflags &= ~MS_RDONLY;
+
+	console_verbose();
+
+#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
+	conswitchp = &dummy_con;
+#endif
+
+}
+
+/*
+ *  Get CPU information for use by the procfs.
+ */
+
+#define cpu_to_ptr(c)	((void *)(0xFFFF0000 | (unsigned int)(c)))
+#define ptr_to_cpu(p)	(~0xFFFF0000UL & (unsigned int)(p))
+
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+	char *str;
+	int cpu_id = ptr_to_cpu(v);
+
+	str = (char *)__get_free_page(GFP_TEMPORARY);
+	if (!str)
+		goto done;
+
+	seq_printf(m, "ARC700 #%d\n", cpu_id);
+
+	seq_printf(m, "Bogo MIPS : \t%lu.%02lu\n",
+		   loops_per_jiffy / (500000 / HZ),
+		   (loops_per_jiffy / (5000 / HZ)) % 100);
+
+	free_page((unsigned long)str);
+done:
+	seq_printf(m, "\n\n");
+
+	return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	/*
+	 * Callback returns cpu-id to iterator for show routine, NULL to stop.
+	 * However since NULL is also a valid cpu-id (0), we use a round-about
+	 * way to pass it w/o having to kmalloc/free a 2 byte string.
+	 * Encode cpu-id as 0xFFcccc, which is decoded by show routine.
+	 */
+	return *pos < num_possible_cpus() ? cpu_to_ptr(*pos) : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	++*pos;
+	return c_start(m, pos);
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+const struct seq_operations cpuinfo_op = {
+	.start	= c_start,
+	.next	= c_next,
+	.stop	= c_stop,
+	.show	= show_cpuinfo
+};
+
+static DEFINE_PER_CPU(struct cpu, cpu_topology);
+
+static int __init topology_init(void)
+{
+	int cpu;
+
+	for_each_present_cpu(cpu)
+	    register_cpu(&per_cpu(cpu_topology, cpu), cpu);
+
+	return 0;
+}
+
+subsys_initcall(topology_init);
diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c
new file mode 100644
index 0000000..63da347
--- /dev/null
+++ b/arch/arc/mm/init.c
@@ -0,0 +1,171 @@
+/*
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/memblock.h>
+#ifdef CONFIG_BLOCK_DEV_RAM
+#include <linux/blk.h>
+#endif
+#include <linux/swap.h>
+#include <linux/module.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/sections.h>
+#include <asm/arcregs.h>
+
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __aligned(PAGE_SIZE);
+char empty_zero_page[PAGE_SIZE] __aligned(PAGE_SIZE);
+EXPORT_SYMBOL(empty_zero_page);
+
+/* Default tot mem from .config */
+static unsigned long arc_mem_sz = CONFIG_ARC_PLAT_SDRAM_SIZE;
+
+/* User can over-ride above with "mem=nnn[KkMm]" in cmdline */
+static int __init setup_mem_sz(char *str)
+{
+	arc_mem_sz = memparse(str, NULL) & PAGE_MASK;
+
+	/* early console might not be setup yet - it will show up later */
+	pr_info("\"mem=%s\": mem sz set to %ldM\n", str, TO_MB(arc_mem_sz));
+
+	return 0;
+}
+early_param("mem", setup_mem_sz);
+
+/*
+ * First memory setup routine called from setup_arch()
+ * 1. setup swapper's mm @init_mm
+ * 2. Count the pages we have and setup bootmem allocator
+ * 3. zone setup
+ */
+void __init setup_arch_memory(void)
+{
+	unsigned long zones_size[MAX_NR_ZONES] = { 0, 0 };
+	unsigned long end_mem = CONFIG_LINUX_LINK_BASE + arc_mem_sz;
+
+	init_mm.start_code = (unsigned long)_text;
+	init_mm.end_code = (unsigned long)_etext;
+	init_mm.end_data = (unsigned long)_edata;
+	init_mm.brk = (unsigned long)_end;
+
+	/*
+	 * We do it here, so that memory is correctly instantiated
+	 * even if "mem=xxx" cmline over-ride is not given
+	 */
+	memblock_add(CONFIG_LINUX_LINK_BASE, arc_mem_sz);
+
+	/*------------- externs in mm need setting up ---------------*/
+
+	/* first page of system - kernel .vector starts here */
+	min_low_pfn = PFN_DOWN(CONFIG_LINUX_LINK_BASE);
+
+	/* Last usable page of low mem (no HIGHMEM yet for ARC port) */
+	max_low_pfn = max_pfn = PFN_DOWN(end_mem);
+
+	max_mapnr = num_physpages = max_low_pfn - min_low_pfn;
+
+	/*------------- reserve kernel image -----------------------*/
+	memblock_reserve(CONFIG_LINUX_LINK_BASE,
+			 __pa(_end) - CONFIG_LINUX_LINK_BASE);
+
+	memblock_dump_all();
+
+	/*-------------- node setup --------------------------------*/
+	memset(zones_size, 0, sizeof(zones_size));
+	zones_size[ZONE_NORMAL] = num_physpages;
+
+	/*
+	 * We can't use the helper free_area_init(zones[]) because it uses
+	 * PAGE_OFFSET to compute the @min_low_pfn which would be wrong
+	 * when our kernel doesn't start at PAGE_OFFSET, i.e.
+	 * PAGE_OFFSET != CONFIG_LINUX_LINK_BASE
+	 */
+	free_area_init_node(0,			/* node-id */
+			    zones_size,		/* num pages per zone */
+			    min_low_pfn,	/* first pfn of node */
+			    NULL);		/* NO holes */
+}
+
+/*
+ * mem_init - initializes memory
+ *
+ * Frees up bootmem
+ * Calculates and displays memory available/used
+ */
+void __init mem_init(void)
+{
+	int codesize, datasize, initsize, reserved_pages, free_pages;
+	int tmp;
+
+	high_memory = (void *)(CONFIG_LINUX_LINK_BASE + arc_mem_sz);
+
+	totalram_pages = free_all_bootmem();
+
+	/* count all reserved pages [kernel code/data/mem_map..] */
+	reserved_pages = 0;
+	for (tmp = 0; tmp < max_mapnr; tmp++)
+		if (PageReserved(mem_map + tmp))
+			reserved_pages++;
+
+	/* XXX: nr_free_pages() is equivalent */
+	free_pages = max_mapnr - reserved_pages;
+
+	/*
+	 * For the purpose of display below, split the "reserve mem"
+	 * kernel code/data is already shown explicitly,
+	 * Show any other reservations (mem_map[ ] et al)
+	 */
+	reserved_pages -= (((unsigned int)_end - CONFIG_LINUX_LINK_BASE) >>
+								PAGE_SHIFT);
+
+	codesize = _etext - _text;
+	datasize = _end - _etext;
+	initsize = __init_end - __init_begin;
+
+	pr_info("Memory Available: %dM / %ldM (%dK code, %dK data, %dK init, %dK reserv)\n",
+		PAGES_TO_MB(free_pages),
+		TO_MB(arc_mem_sz),
+		TO_KB(codesize), TO_KB(datasize), TO_KB(initsize),
+		PAGES_TO_KB(reserved_pages));
+}
+
+static void __init free_init_pages(const char *what, unsigned long begin,
+				   unsigned long end)
+{
+	unsigned long addr;
+
+	pr_info("Freeing %s: %ldk [%lx] to [%lx]\n",
+		what, TO_KB(end - begin), begin, end);
+
+	/* need to check that the page we free is not a partial page */
+	for (addr = begin; addr + PAGE_SIZE <= end; addr += PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(addr));
+		init_page_count(virt_to_page(addr));
+		free_page(addr);
+		totalram_pages++;
+	}
+}
+
+/*
+ * free_initmem: Free all the __init memory.
+ */
+void __init_refok free_initmem(void)
+{
+	free_init_pages("unused kernel memory",
+			(unsigned long)__init_begin,
+			(unsigned long)__init_end);
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void __init free_initrd_mem(unsigned long start, unsigned long end)
+{
+	free_init_pages("initrd memory", start, end);
+}
+#endif
diff --git a/arch/arc/plat-arcfpga/platform.c b/arch/arc/plat-arcfpga/platform.c
new file mode 100644
index 0000000..7b5dcab
--- /dev/null
+++ b/arch/arc/plat-arcfpga/platform.c
@@ -0,0 +1,29 @@
+/*
+ * ARC FPGA Platform support code
+ *
+ * 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.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+/*
+ * Early Platform Initialization called from setup_arch()
+ */
+void __init arc_platform_early_init(void)
+{
+	pr_info("[plat-arcfpga]: registering early dev resources\n");
+}
+
+int __init fpga_plat_init(void)
+{
+	pr_info("[plat-arcfpga]: registering device resources\n");
+
+	return 0;
+}
+arch_initcall(fpga_plat_init);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 32/71] ARC: [DeviceTree] Basic support
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (12 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 30/71] ARC: Boot #1: low-level, setup_arch(), /proc/cpuinfo, mem init Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-28  7:40   ` Vineet Gupta
                     ` (2 more replies)
  2013-01-24 10:50 ` [PATCH v3 33/71] ARC: [DeviceTree] Convert some Kconfig items to runtime values Vineet Gupta
                   ` (11 subsequent siblings)
  25 siblings, 3 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel
  Cc: arnd, Vineet Gupta, Grant Likely, devicetree-discuss, Rob Herring

This is minimal infrastructure needed for devicetree work.
It uses an a sample "skeleton" devicetree - embedded in kernel image -
to print the board, manufacturer by parsing the top-level "compatible"
string.

As of now we don't need any additional "board" specific "machine_desc".

TODO: support interpreting the command line as boot-loader passed dtb

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: Rob Herring <rob.herring@calxeda.com>
---
 arch/arc/Kconfig                |    9 +++++
 arch/arc/Makefile               |    9 +++++
 arch/arc/boot/dts/Makefile      |   14 ++++++++
 arch/arc/boot/dts/skeleton.dts  |   10 ++++++
 arch/arc/boot/dts/skeleton.dtsi |   21 ++++++++++++
 arch/arc/include/asm/prom.h     |   15 ++++++++
 arch/arc/include/asm/sections.h |    1 +
 arch/arc/kernel/Makefile        |    2 +
 arch/arc/kernel/devtree.c       |   69 +++++++++++++++++++++++++++++++++++++++
 arch/arc/kernel/setup.c         |    9 +++++
 arch/arc/mm/init.c              |   13 +++++++
 11 files changed, 172 insertions(+), 0 deletions(-)
 create mode 100644 arch/arc/boot/dts/Makefile
 create mode 100644 arch/arc/boot/dts/skeleton.dts
 create mode 100644 arch/arc/boot/dts/skeleton.dtsi
 create mode 100644 arch/arc/include/asm/prom.h
 create mode 100644 arch/arc/kernel/devtree.c

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index a353849..7666857 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -24,8 +24,11 @@ config ARC
 	select GENERIC_SMP_IDLE_THREAD
 	select HAVE_GENERIC_HARDIRQS
 	select HAVE_MEMBLOCK
+	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
+	select OF
+	select OF_EARLY_FLATTREE
 
 config SCHED_OMIT_FRAME_POINTER
 	def_bool y
@@ -320,6 +323,12 @@ config CMDLINE_UBOOT
 	  to it. kernel startup code will copy the string into cmdline buffer
 	  and also append CONFIG_CMDLINE.
 
+config ARC_BUILTIN_DTB_NAME
+	string "Built in DTB"
+	help
+	  Set the name of the DTB to embed in the vmlinux binary
+	  Leaving it blank selects the minimal "skeleton" dtb
+
 source "kernel/Kconfig.preempt"
 
 endmenu	 # "ARC Architecture Configuration"
diff --git a/arch/arc/Makefile b/arch/arc/Makefile
index 4d52a3b..90570f9 100644
--- a/arch/arc/Makefile
+++ b/arch/arc/Makefile
@@ -83,6 +83,9 @@ head-y		:= arch/arc/kernel/head.o
 # See arch/arc/Kbuild for content of core part of the kernel
 core-y		+= arch/arc/
 
+# w/o this dtb won't embed into kernel binary
+core-y		+= arch/arc/boot/dts/
+
 # w/o this ifneq, make ARCH=arc clean was crapping out
 ifneq ($(platform-y),)
 core-y		+= arch/arc/plat-$(PLATFORM)/
@@ -101,6 +104,12 @@ bootpImage: vmlinux
 uImage: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
+%.dtb %.dtb.S %.dtb.o:
+	$(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@
+
+dtbs:
+	$(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@
+
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
 
diff --git a/arch/arc/boot/dts/Makefile b/arch/arc/boot/dts/Makefile
new file mode 100644
index 0000000..4a972a3
--- /dev/null
+++ b/arch/arc/boot/dts/Makefile
@@ -0,0 +1,14 @@
+ifeq ($(CONFIG_OF),y)
+
+# Built-in dtb
+builtindtb-y		:= skeleton
+
+ifneq ($(CONFIG_ARC_BUILTIN_DTB_NAME),"")
+	builtindtb-y	:= $(CONFIG_ARC_BUILTIN_DTB_NAME)
+endif
+
+obj-y	+= $(patsubst "%",%,$(builtindtb-y)).dtb.o
+
+clean-files := *.dtb
+
+endif
diff --git a/arch/arc/boot/dts/skeleton.dts b/arch/arc/boot/dts/skeleton.dts
new file mode 100644
index 0000000..25a84fb
--- /dev/null
+++ b/arch/arc/boot/dts/skeleton.dts
@@ -0,0 +1,10 @@
+/*
+ * 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/boot/dts/skeleton.dtsi b/arch/arc/boot/dts/skeleton.dtsi
new file mode 100644
index 0000000..9b357d8
--- /dev/null
+++ b/arch/arc/boot/dts/skeleton.dtsi
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+/*
+ * Skeleton device tree; the bare minimum needed to boot; just include and
+ * add a compatible value.
+ */
+
+/ {
+	compatible = "snps,arc";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	chosen { };
+	aliases { };
+	memory { device_type = "memory"; reg = <0 0>; };
+};
diff --git a/arch/arc/include/asm/prom.h b/arch/arc/include/asm/prom.h
new file mode 100644
index 0000000..f54489b
--- /dev/null
+++ b/arch/arc/include/asm/prom.h
@@ -0,0 +1,15 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_ARC_PROM_H_
+#define _ASM_ARC_PROM_H_
+
+#define HAVE_ARCH_DEVTREE_FIXUPS
+extern int __init setup_machine_fdt(void *dt);
+
+#endif
diff --git a/arch/arc/include/asm/sections.h b/arch/arc/include/asm/sections.h
index fc15f2e..6fc1159 100644
--- a/arch/arc/include/asm/sections.h
+++ b/arch/arc/include/asm/sections.h
@@ -13,5 +13,6 @@
 
 extern char _int_vec_base_lds[];
 extern char __arc_dccm_base[];
+extern char __dtb_start[];
 
 #endif
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
index 6d83431..8a55e99 100644
--- a/arch/arc/kernel/Makefile
+++ b/arch/arc/kernel/Makefile
@@ -8,6 +8,8 @@
 obj-y	:= arcksyms.o setup.o irq.o time.o reset.o ptrace.o entry.o process.o
 obj-y	+= signal.o traps.o sys.o troubleshoot.o stacktrace.o clk.o
 
+obj-$(CONFIG_OF)			+= devtree.o
+
 obj-$(CONFIG_ARC_FPU_SAVE_RESTORE)	+= fpu.o
 CFLAGS_fpu.o   += -mdpfp
 
diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c
new file mode 100644
index 0000000..229f78e
--- /dev/null
+++ b/arch/arc/kernel/devtree.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
+ *
+ * Based on highly stipped down version of METAG
+ *
+ * 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.
+ */
+
+
+#include <linux/init.h>
+#include <linux/export.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/reboot.h>
+#include <linux/memblock.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/prom.h>
+
+/* called from unflatten_device_tree() to bootstrap devicetree itself */
+void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
+{
+	return __va(memblock_alloc(size, align));
+}
+
+/**
+ * setup_machine_fdt - Machine setup when an dtb was passed to the kernel
+ * @dt:		virtual address pointer to dt blob
+ *
+ * If a dtb was passed to the kernel, then use it to choose the correct
+ * machine_desc and to setup the system.
+ */
+int __init setup_machine_fdt(void *dt)
+{
+	struct boot_param_header *devtree = dt;
+	unsigned long dt_root;
+	char *model, *compat;
+	char manufacturer[16];
+
+	/* check device tree validity */
+	if (be32_to_cpu(devtree->magic) != OF_DT_HEADER)
+		return 1;
+
+	/* Search the mdescs for the 'best' compatible value match */
+	initial_boot_params = devtree;
+	dt_root = of_get_flat_dt_root();
+
+	/* compat = "<manufacturer>,<model>" */
+	compat = of_get_flat_dt_prop(dt_root, "compatible", NULL);
+	if (!compat)
+		compat = "<unknown>";
+
+	model = strchr(compat, ',');
+	if (model)
+		model++;
+
+	strlcpy(manufacturer, compat, model ? model - compat : strlen(compat));
+
+	pr_info("Board \"%s\" from %s (Manufacturer)\n", model, manufacturer);
+
+	/* Retrieve various information from the /chosen node */
+	of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
+
+	return 0;
+}
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index 82ac206..27aebd6 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -13,6 +13,8 @@
 #include <linux/console.h>
 #include <linux/module.h>
 #include <linux/cpu.h>
+#include <linux/of_fdt.h>
+#include <asm/sections.h>
 #include <asm/arcregs.h>
 #include <asm/tlb.h>
 #include <asm/cache.h>
@@ -20,6 +22,7 @@
 #include <asm/page.h>
 #include <asm/irq.h>
 #include <asm/arcregs.h>
+#include <asm/prom.h>
 
 #define FIX_PTR(x)  __asm__ __volatile__(";" : "+r"(x))
 
@@ -57,6 +60,8 @@ void __init __attribute__((weak)) arc_platform_early_init(void)
 
 void __init setup_arch(char **cmdline_p)
 {
+	int rc;
+
 #ifdef CONFIG_CMDLINE_UBOOT
 	/* Make sure that a whitespace is inserted before */
 	strlcat(command_line, " ", sizeof(command_line));
@@ -71,6 +76,8 @@ void __init setup_arch(char **cmdline_p)
 	strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
 	*cmdline_p = command_line;
 
+	rc = setup_machine_fdt(__dtb_start);
+
 	/* To force early parsing of things like mem=xxx */
 	parse_early_param();
 
@@ -81,6 +88,8 @@ void __init setup_arch(char **cmdline_p)
 
 	setup_arch_memory();
 
+	unflatten_device_tree();
+
 	/* Can be issue if someone passes cmd line arg "ro"
 	 * But that is unlikely so keeping it as it is
 	 */
diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c
index 63da347..682cf57 100644
--- a/arch/arc/mm/init.c
+++ b/arch/arc/mm/init.c
@@ -39,6 +39,11 @@ static int __init setup_mem_sz(char *str)
 }
 early_param("mem", setup_mem_sz);
 
+void __init early_init_dt_add_memory_arch(u64 base, u64 size)
+{
+	pr_err("%s(%llx, %llx)\n", __func__, base, size);
+}
+
 /*
  * First memory setup routine called from setup_arch()
  * 1. setup swapper's mm @init_mm
@@ -169,3 +174,11 @@ void __init free_initrd_mem(unsigned long start, unsigned long end)
 	free_init_pages("initrd memory", start, end);
 }
 #endif
+
+#ifdef CONFIG_OF_FLATTREE
+void __init early_init_dt_setup_initrd_arch(unsigned long start,
+					    unsigned long end)
+{
+	pr_err("%s(%lx, %lx)\n", __func__, start, end);
+}
+#endif /* CONFIG_OF_FLATTREE */
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 33/71] ARC: [DeviceTree] Convert some Kconfig items to runtime values
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (13 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 32/71] ARC: [DeviceTree] Basic support Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 34/71] ARC: [plat-arcfpga]: Enabling DeviceTree for Angel4 board Vineet Gupta
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta, Grant Likely

* mem size now runtime configured (prev CONFIG_ARC_PLAT_SDRAM_SIZE)
* core cpu clk runtime configured (prev CONFIG_ARC_PLAT_CLK)

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Grant Likely <grant.likely@secretlab.ca>
---
 arch/arc/Kconfig                |   12 ------------
 arch/arc/boot/dts/skeleton.dtsi |    6 +++++-
 arch/arc/include/asm/clk.h      |    2 ++
 arch/arc/kernel/clk.c           |   12 +++++++++++-
 arch/arc/kernel/devtree.c       |   13 +++++++++++++
 arch/arc/mm/init.c              |    9 ++++++---
 6 files changed, 37 insertions(+), 17 deletions(-)

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 7666857..7db9785 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -249,10 +249,6 @@ source "arch/arc/plat-arcfpga/Kconfig"
 
 #New platform adds here
 
-config ARC_PLAT_CLK
-	int "Clk speed in Hz"
-	default "80000000"
-
 config LINUX_LINK_BASE
 	hex "Linux Link Address"
 	default "0x80000000"
@@ -266,14 +262,6 @@ config LINUX_LINK_BASE
 	  Linux needs to be scooted a bit.
 	  If you don't know what the above means, leave this setting alone.
 
-config ARC_PLAT_SDRAM_SIZE
-	hex "SD RAM Size"
-	default "0x10000000"
-	help
-	  Implies the amount of SDRAM/DRAM Linux is going to claim/own.
-	  The actual memory itself could be larger than this number. But for
-	  all software purposes, this is the amt of memory.
-
 endmenu # "Platform Board Configuration"
 
 config ARC_STACK_NONEXEC
diff --git a/arch/arc/boot/dts/skeleton.dtsi b/arch/arc/boot/dts/skeleton.dtsi
index 9b357d8..eb8b773 100644
--- a/arch/arc/boot/dts/skeleton.dtsi
+++ b/arch/arc/boot/dts/skeleton.dtsi
@@ -13,9 +13,13 @@
 
 / {
 	compatible = "snps,arc";
+	clock-frequency = <80000000>;	/* 80 MHZ */
 	#address-cells = <1>;
 	#size-cells = <1>;
 	chosen { };
 	aliases { };
-	memory { device_type = "memory"; reg = <0 0>; };
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>;	/* 256M */
+	};
 };
diff --git a/arch/arc/include/asm/clk.h b/arch/arc/include/asm/clk.h
index 6195643..bf9d29f 100644
--- a/arch/arc/include/asm/clk.h
+++ b/arch/arc/include/asm/clk.h
@@ -17,4 +17,6 @@ static inline unsigned long arc_get_core_freq(void)
 	return core_freq;
 }
 
+extern int arc_set_core_freq(unsigned long);
+
 #endif
diff --git a/arch/arc/kernel/clk.c b/arch/arc/kernel/clk.c
index 64925db..66ce0dc 100644
--- a/arch/arc/kernel/clk.c
+++ b/arch/arc/kernel/clk.c
@@ -8,4 +8,14 @@
 
 #include <asm/clk.h>
 
-unsigned long core_freq = CONFIG_ARC_PLAT_CLK;
+unsigned long core_freq = 800000000;
+
+/*
+ * As of now we default to device-tree provided clock
+ * In future we can determine this in early boot
+ */
+int arc_set_core_freq(unsigned long freq)
+{
+	core_freq = freq;
+	return 0;
+}
diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c
index 229f78e..d2a41be 100644
--- a/arch/arc/kernel/devtree.c
+++ b/arch/arc/kernel/devtree.c
@@ -20,6 +20,7 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <asm/prom.h>
+#include <asm/clk.h>
 
 /* called from unflatten_device_tree() to bootstrap devicetree itself */
 void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
@@ -39,7 +40,9 @@ int __init setup_machine_fdt(void *dt)
 	struct boot_param_header *devtree = dt;
 	unsigned long dt_root;
 	char *model, *compat;
+	void *clk;
 	char manufacturer[16];
+	unsigned long len;
 
 	/* check device tree validity */
 	if (be32_to_cpu(devtree->magic) != OF_DT_HEADER)
@@ -65,5 +68,15 @@ int __init setup_machine_fdt(void *dt)
 	/* Retrieve various information from the /chosen node */
 	of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
 
+	/* Initialize {size,address}-cells info */
+	of_scan_flat_dt(early_init_dt_scan_root, NULL);
+
+	/* Setup memory, calling early_init_dt_add_memory_arch */
+	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
+
+	clk = of_get_flat_dt_prop(dt_root, "clock-frequency", &len);
+	if (clk)
+		arc_set_core_freq(of_read_ulong(clk, len/4));
+
 	return 0;
 }
diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c
index 682cf57..caf797d 100644
--- a/arch/arc/mm/init.c
+++ b/arch/arc/mm/init.c
@@ -25,7 +25,7 @@ char empty_zero_page[PAGE_SIZE] __aligned(PAGE_SIZE);
 EXPORT_SYMBOL(empty_zero_page);
 
 /* Default tot mem from .config */
-static unsigned long arc_mem_sz = CONFIG_ARC_PLAT_SDRAM_SIZE;
+static unsigned long arc_mem_sz = 0x20000000;  /* some default */
 
 /* User can over-ride above with "mem=nnn[KkMm]" in cmdline */
 static int __init setup_mem_sz(char *str)
@@ -41,7 +41,8 @@ early_param("mem", setup_mem_sz);
 
 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
 {
-	pr_err("%s(%llx, %llx)\n", __func__, base, size);
+	arc_mem_sz = size & PAGE_MASK;
+	pr_info("Memory size set via devicetree %ldM\n", TO_MB(arc_mem_sz));
 }
 
 /*
@@ -62,7 +63,9 @@ void __init setup_arch_memory(void)
 
 	/*
 	 * We do it here, so that memory is correctly instantiated
-	 * even if "mem=xxx" cmline over-ride is not given
+	 * even if "mem=xxx" cmline over-ride is given and/or
+	 * DT has memory node. Each causes an update to @arc_mem_sz
+	 * and we finally add memory one here
 	 */
 	memblock_add(CONFIG_LINUX_LINK_BASE, arc_mem_sz);
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 34/71] ARC: [plat-arcfpga]: Enabling DeviceTree for Angel4 board
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (14 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 33/71] ARC: [DeviceTree] Convert some Kconfig items to runtime values Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 42/71] ARC: Module support Vineet Gupta
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta, Grant Likely

* arc-uart platform device now populated dynamically, using
  of_platform_populate() - applies to any other device whatsoever.

* uart in turn requires incore arc-intc to be also present in DT

* A irq-domain needs to be instantiated for IRQ requests by DT probed
  device (e.g. arc-uart)

TODO: switch over to linear irq domain once all devs have been
      transitioned to DT

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Arnd Bergmann <arnd@arndb.de>
---
 .../devicetree/bindings/arc/interrupts.txt         |   24 +++++
 arch/arc/boot/dts/Makefile                         |    2 +-
 arch/arc/boot/dts/angel4.dts                       |   55 +++++++++++
 arch/arc/boot/dts/skeleton.dtsi                    |   12 +++
 arch/arc/kernel/irq.c                              |   38 +++++++-
 arch/arc/plat-arcfpga/platform.c                   |   97 +++++++++----------
 6 files changed, 170 insertions(+), 58 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arc/interrupts.txt
 create mode 100644 arch/arc/boot/dts/angel4.dts

diff --git a/Documentation/devicetree/bindings/arc/interrupts.txt b/Documentation/devicetree/bindings/arc/interrupts.txt
new file mode 100644
index 0000000..9a5d562
--- /dev/null
+++ b/Documentation/devicetree/bindings/arc/interrupts.txt
@@ -0,0 +1,24 @@
+* ARC700 incore Interrupt Controller
+
+  The core interrupt controller provides 32 prioritised interrupts (2 levels)
+  to ARC700 core.
+
+Properties:
+
+- compatible: "snps,arc700-intc"
+- interrupt-controller: This is an interrupt controller.
+- #interrupt-cells: Must be <1>.
+
+  Single Cell "interrupts" property of a device specifies the IRQ number
+  between 0 to 31
+
+  intc accessed via the special ARC AUX register interface, hence "reg" property
+  is not specified.
+
+Example:
+
+	intc: interrupt-controller {
+		compatible = "snps,arc700-intc";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+	};
diff --git a/arch/arc/boot/dts/Makefile b/arch/arc/boot/dts/Makefile
index 4a972a3..dfda14e 100644
--- a/arch/arc/boot/dts/Makefile
+++ b/arch/arc/boot/dts/Makefile
@@ -1,7 +1,7 @@
 ifeq ($(CONFIG_OF),y)
 
 # Built-in dtb
-builtindtb-y		:= skeleton
+builtindtb-y		:= angel4
 
 ifneq ($(CONFIG_ARC_BUILTIN_DTB_NAME),"")
 	builtindtb-y	:= $(CONFIG_ARC_BUILTIN_DTB_NAME)
diff --git a/arch/arc/boot/dts/angel4.dts b/arch/arc/boot/dts/angel4.dts
new file mode 100644
index 0000000..4c188d5
--- /dev/null
+++ b/arch/arc/boot/dts/angel4.dts
@@ -0,0 +1,55 @@
+/*
+ * 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"
+
+/ {
+	compatible = "snps,arc-angel4";
+	clock-frequency = <80000000>;	/* 80 MHZ */
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&intc>;
+
+	chosen {
+		bootargs = "console=ttyARC0,115200n8";
+	};
+
+	aliases {
+		serial0 = &arcuart0;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>;	/* 256M */
+	};
+
+	fpga {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		/* child and parent address space 1:1 mapped */
+		ranges;
+
+		intc: interrupt-controller {
+			compatible = "snps,arc700-intc";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+
+		arcuart0: serial@c0fc1000 {
+			compatible = "snps,arc-uart";
+			reg = <0xc0fc1000 0x100>;
+			interrupts = <5>;
+			clock-frequency = <80000000>;
+			baud = <115200>;
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arc/boot/dts/skeleton.dtsi b/arch/arc/boot/dts/skeleton.dtsi
index eb8b773..a870bdd 100644
--- a/arch/arc/boot/dts/skeleton.dtsi
+++ b/arch/arc/boot/dts/skeleton.dtsi
@@ -18,6 +18,18 @@
 	#size-cells = <1>;
 	chosen { };
 	aliases { };
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "snps,arc770d";
+			reg = <0>;
+		};
+	};
+
 	memory {
 		device_type = "memory";
 		reg = <0x00000000 0x10000000>;	/* 256M */
diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
index 2f399eb..3c18e66 100644
--- a/arch/arc/kernel/irq.c
+++ b/arch/arc/kernel/irq.c
@@ -9,6 +9,8 @@
 
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/of.h>
+#include <linux/irqdomain.h>
 #include <asm/sections.h>
 #include <asm/irq.h>
 
@@ -59,16 +61,40 @@ static struct irq_chip onchip_intc = {
 	.irq_unmask	= arc_unmask_irq,
 };
 
+static int arc_intc_domain_map(struct irq_domain *d, unsigned int irq,
+				irq_hw_number_t hw)
+{
+	if (irq == TIMER0_IRQ)
+		irq_set_chip_and_handler(irq, &onchip_intc, handle_percpu_irq);
+	else
+		irq_set_chip_and_handler(irq, &onchip_intc, handle_level_irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops arc_intc_domain_ops = {
+	.xlate = irq_domain_xlate_onecell,
+	.map = arc_intc_domain_map,
+};
+
+static struct irq_domain *root_domain;
+
 void __init init_onchip_IRQ(void)
 {
-	int i;
+	struct device_node *intc = NULL;
+
+	intc = of_find_compatible_node(NULL, NULL, "snps,arc700-intc");
+	if(!intc)
+		panic("DeviceTree Missing incore intc\n");
+
+	root_domain = irq_domain_add_legacy(intc, NR_IRQS, 0, 0,
+					    &arc_intc_domain_ops, NULL);
 
-	for (i = 0; i < NR_IRQS; i++)
-		irq_set_chip_and_handler(i, &onchip_intc, handle_level_irq);
+	if (!root_domain)
+		panic("root irq domain not avail\n");
 
-#ifdef CONFIG_SMP
-	irq_set_chip_and_handler(TIMER0_IRQ, &onchip_intc, handle_percpu_irq);
-#endif
+	/* with this we don't need to export root_domain */
+	irq_set_default_host(root_domain);
 }
 
 /*
diff --git a/arch/arc/plat-arcfpga/platform.c b/arch/arc/plat-arcfpga/platform.c
index 5388b31..33bcac8 100644
--- a/arch/arc/plat-arcfpga/platform.c
+++ b/arch/arc/plat-arcfpga/platform.c
@@ -13,6 +13,7 @@
 #include <linux/device.h>
 #include <linux/platform_device.h>
 #include <linux/console.h>
+#include <linux/of_platform.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
 #include <asm/clk.h>
@@ -20,58 +21,56 @@
 
 /*----------------------- Platform Devices -----------------------------*/
 
-#if defined(CONFIG_SERIAL_ARC) || defined(CONFIG_SERIAL_ARC_MODULE)
-
 static unsigned long arc_uart_info[] = {
-	CONFIG_ARC_SERIAL_BAUD,	/* uart->baud */
-	-1,			/* uart->port.uartclk */
-	-1,			/* uart->is_emulated (runtime @running_on_hw) */
+	0,	/* uart->is_emulated (runtime @running_on_hw) */
+	0,	/* uart->port.uartclk */
+	0,	/* uart->baud */
 	0
 };
 
-#define ARC_UART_DEV(n)					\
-							\
-static struct resource arc_uart##n##_res[] = {		\
-	{						\
-		.start = UART##n##_BASE,			\
-		.end   = UART##n##_BASE + 0xFF,		\
-		.flags = IORESOURCE_MEM,		\
-	},						\
-	{						\
-		.start = UART##n##_IRQ,			\
-		.end   = UART##n##_IRQ,			\
-		.flags = IORESOURCE_IRQ,		\
-	},						\
-};							\
-							\
-static struct platform_device arc_uart##n##_dev = {	\
-	.name = "arc-uart",				\
-	.id = n,					\
-	.num_resources = ARRAY_SIZE(arc_uart##n##_res),	\
-	.resource = arc_uart##n##_res,			\
-	.dev = {					\
-		.platform_data = &arc_uart_info,	\
-	},						\
-}
+#if defined(CONFIG_SERIAL_ARC_CONSOLE)
+/*
+ * static platform data - but only for early serial
+ * TBD: derive this from a special DT node
+ */
+static struct resource arc_uart0_res[] = {
+	{
+		.start = UART0_BASE,
+		.end   = UART0_BASE + 0xFF,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = UART0_IRQ,
+		.end   = UART0_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
 
-ARC_UART_DEV(0);
-#if CONFIG_SERIAL_ARC_NR_PORTS > 1
-ARC_UART_DEV(1);
-#endif
+static struct platform_device arc_uart0_dev = {
+	.name = "arc-uart",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(arc_uart0_res),
+	.resource = arc_uart0_res,
+	.dev = {
+		.platform_data = &arc_uart_info,
+	},
+};
 
 static struct platform_device *fpga_early_devs[] __initdata = {
-#if defined(CONFIG_SERIAL_ARC_CONSOLE)
 	&arc_uart0_dev,
-#endif
 };
+#endif
 
 static void arc_fpga_serial_init(void)
 {
+	/* To let driver workaround ISS bug: baudh Reg can't be set to 0 */
+	arc_uart_info[0] = !running_on_hw;
+
 	arc_uart_info[1] = arc_get_core_freq();
 
-	/* To let driver workaround ISS bug: baudh Reg can't be set to 0 */
-	arc_uart_info[2] = !running_on_hw;
+	arc_uart_info[2] = CONFIG_ARC_SERIAL_BAUD;
 
+#if defined(CONFIG_SERIAL_ARC_CONSOLE)
 	early_platform_add_devices(fpga_early_devs,
 				   ARRAY_SIZE(fpga_early_devs));
 
@@ -97,16 +96,9 @@ static void arc_fpga_serial_init(void)
 	 * otherwise the early console never gets a chance to run.
 	 */
 	add_preferred_console("ttyARC", 0, "115200");
+#endif
 }
 
-#else
-
-static void arc_fpga_serial_init(void)
-{
-}
-
-#endif	/* CONFIG_SERIAL_ARC */
-
 /*
  * Early Platform Initialization called from setup_arch()
  */
@@ -117,20 +109,23 @@ void __init arc_platform_early_init(void)
 	arc_fpga_serial_init();
 }
 
-static struct platform_device *fpga_devs[] __initdata = {
+static struct of_dev_auxdata plat_auxdata_lookup[] __initdata = {
 #if defined(CONFIG_SERIAL_ARC) || defined(CONFIG_SERIAL_ARC_MODULE)
-	&arc_uart0_dev,
-#if CONFIG_SERIAL_ARC_NR_PORTS > 1
-	&arc_uart1_dev,
-#endif
+	OF_DEV_AUXDATA("snps,arc-uart", UART0_BASE, "arc-uart", arc_uart_info),
 #endif
+	{}
 };
 
 int __init fpga_plat_init(void)
 {
 	pr_info("[plat-arcfpga]: registering device resources\n");
 
-	platform_add_devices(fpga_devs, ARRAY_SIZE(fpga_devs));
+	/*
+	 * Traverses flattened DeviceTree - registering platform devices
+	 * complete with their resources
+	 */
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     plat_auxdata_lookup, NULL);
 
 	return 0;
 }
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 42/71] ARC: Module support
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (15 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 34/71] ARC: [plat-arcfpga]: Enabling DeviceTree for Angel4 board Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 44/71] ARC: SMP support Vineet Gupta
                   ` (8 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/include/asm/module.h |    4 ++
 arch/arc/kernel/Makefile      |    1 +
 arch/arc/kernel/module.c      |   87 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 92 insertions(+), 0 deletions(-)
 create mode 100644 arch/arc/kernel/module.c

diff --git a/arch/arc/include/asm/module.h b/arch/arc/include/asm/module.h
index 165d768..234b435 100644
--- a/arch/arc/include/asm/module.h
+++ b/arch/arc/include/asm/module.h
@@ -14,4 +14,8 @@
 
 #include <asm-generic/module.h>
 
+#define MODULE_PROC_FAMILY "ARC700"
+
+#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
+
 #endif /* _ASM_ARC_MODULE_H */
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
index 1f01d35..a24820f 100644
--- a/arch/arc/kernel/Makefile
+++ b/arch/arc/kernel/Makefile
@@ -12,6 +12,7 @@ obj-y	:= arcksyms.o setup.o irq.o time.o reset.o ptrace.o entry.o process.o
 obj-y	+= signal.o traps.o sys.o troubleshoot.o stacktrace.o clk.o
 
 obj-$(CONFIG_OF)			+= devtree.o
+obj-$(CONFIG_MODULES)			+= arcksyms.o module.o
 
 obj-$(CONFIG_ARC_FPU_SAVE_RESTORE)	+= fpu.o
 CFLAGS_fpu.o   += -mdpfp
diff --git a/arch/arc/kernel/module.c b/arch/arc/kernel/module.c
new file mode 100644
index 0000000..a1bb70d
--- /dev/null
+++ b/arch/arc/kernel/module.c
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleloader.h>
+#include <linux/kernel.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+
+static inline void arc_write_me(unsigned short *addr, unsigned long value)
+{
+	*addr = (value & 0xffff0000) >> 16;
+	*(addr + 1) = (value & 0xffff);
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+		       const char *strtab,
+		       unsigned int symindex,	/* sec index for sym tbl */
+		       unsigned int relsec,	/* sec index for relo sec */
+		       struct module *module)
+{
+	int i, n;
+	Elf32_Rela *rel_entry = (void *)sechdrs[relsec].sh_addr;
+	Elf32_Sym *sym_entry, *sym_sec;
+	Elf32_Addr relocation;
+	Elf32_Addr location;
+	Elf32_Addr sec_to_patch;
+	int relo_type;
+
+	sec_to_patch = sechdrs[sechdrs[relsec].sh_info].sh_addr;
+	sym_sec = (Elf32_Sym *) sechdrs[symindex].sh_addr;
+	n = sechdrs[relsec].sh_size / sizeof(*rel_entry);
+
+	pr_debug("\n========== Module Sym reloc ===========================\n");
+	pr_debug("Section to fixup %x\n", sec_to_patch);
+	pr_debug("=========================================================\n");
+	pr_debug("rela->r_off | rela->addend | sym->st_value | ADDR | VALUE\n");
+	pr_debug("=========================================================\n");
+
+	/* Loop thru entries in relocation section */
+	for (i = 0; i < n; i++) {
+
+		/* This is where to make the change */
+		location = sec_to_patch + rel_entry[i].r_offset;
+
+		/* This is the symbol it is referring to.  Note that all
+		   undefined symbols have been resolved.  */
+		sym_entry = sym_sec + ELF32_R_SYM(rel_entry[i].r_info);
+
+		relocation = sym_entry->st_value + rel_entry[i].r_addend;
+
+		pr_debug("\t%x\t\t%x\t\t%x  %x %x [%s]\n",
+			rel_entry[i].r_offset, rel_entry[i].r_addend,
+			sym_entry->st_value, location, relocation,
+			strtab + sym_entry->st_name);
+
+		/* This assumes modules are built with -mlong-calls
+		 * so any branches/jumps are absolute 32 bit jmps
+		 * global data access again is abs 32 bit.
+		 * Both of these are handled by same relocation type
+		 */
+		relo_type = ELF32_R_TYPE(rel_entry[i].r_info);
+
+		if (likely(R_ARC_32_ME == relo_type))
+			arc_write_me((unsigned short *)location, relocation);
+		else if (R_ARC_32 == relo_type)
+			*((Elf32_Addr *) location) = relocation;
+		else
+			goto relo_err;
+
+	}
+	return 0;
+
+relo_err:
+	pr_err("%s: unknown relocation: %u\n",
+		module->name, ELF32_R_TYPE(rel_entry[i].r_info));
+	return -ENOEXEC;
+
+}
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 44/71] ARC: SMP support
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (16 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 42/71] ARC: Module support Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 48/71] ARC: kprobes support Vineet Gupta
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel
  Cc: arnd, Vineet Gupta, Thomas Gleixner, Rajeshwar Ranga, Noam Camus,
	Gilad Ben-Yossef

ARC common code to enable a SMP system + ISS provided SMP extensions.

ARC700 natively lacks SMP support, hence some of the core features are
are only enabled if SoCs have the necessary h/w pixie-dust. This
includes:
-Inter Processor Interrupts (IPI)
-Cache coherency
-load-locked/store-conditional
...

The low level exception handling would be completely broken in SMP
because we don't have hardware assisted stack switching. Thus a fair bit
of this code is repurposing the MMU_SCRATCH reg for event handler
prologues to keep them re-entrant.

Many thanks to Rajeshwar Range for his initial "major" contributions to
SMP Port (back in 2008), and to Noam Camus and Gilad Ben-Yossef for help
with resurrecting that in 3.2 kernel (2012).

Note that this platform code is again singleton design pattern - so
multiple SMP platforms won't build at the moment - this deficiency is
addressed in subsequent patches within this series.

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Rajeshwar Ranga <rajeshwar.ranga@gmail.com>
Cc: Noam Camus <noamc@ezchip.com>
Cc: Gilad Ben-Yossef <gilad@benyossef.com>
---
 arch/arc/Kconfig                         |   39 ++++-
 arch/arc/Makefile                        |    3 +
 arch/arc/include/asm/entry.h             |   49 +++++
 arch/arc/include/asm/mmu_context.h       |    4 +
 arch/arc/include/asm/mutex.h             |    9 +
 arch/arc/include/asm/pgtable.h           |    4 +
 arch/arc/include/asm/processor.h         |    8 +
 arch/arc/include/asm/smp.h               |  107 ++++++++++
 arch/arc/kernel/Makefile                 |    1 +
 arch/arc/kernel/ctx_sw.c                 |   11 +
 arch/arc/kernel/entry.S                  |    4 +
 arch/arc/kernel/head.S                   |   33 +++
 arch/arc/kernel/irq.c                    |    5 +
 arch/arc/kernel/setup.c                  |    4 +
 arch/arc/kernel/smp.c                    |  320 ++++++++++++++++++++++++++++++
 arch/arc/mm/tlb.c                        |    6 +
 arch/arc/mm/tlbex.S                      |   38 ++++
 arch/arc/plat-arcfpga/Kconfig            |   14 ++
 arch/arc/plat-arcfpga/Makefile           |    1 +
 arch/arc/plat-arcfpga/include/plat/irq.h |   10 +-
 arch/arc/plat-arcfpga/include/plat/smp.h |  115 +++++++++++
 arch/arc/plat-arcfpga/irq.c              |   10 +
 arch/arc/plat-arcfpga/smp.c              |  167 ++++++++++++++++
 23 files changed, 960 insertions(+), 2 deletions(-)
 create mode 100644 arch/arc/kernel/smp.c
 create mode 100644 arch/arc/plat-arcfpga/include/plat/smp.h
 create mode 100644 arch/arc/plat-arcfpga/smp.c

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 68350aa..52f5c07 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -116,9 +116,42 @@ config CPU_BIG_ENDIAN
 	help
 	  Build kernel for Big Endian Mode of ARC CPU
 
+config SMP
+	bool "Symmetric Multi-Processing (Incomplete)"
+	default n
+	select USE_GENERIC_SMP_HELPERS
+	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.
+
+if SMP
+
+config ARC_HAS_COH_CACHES
+	def_bool n
+
+config ARC_HAS_COH_LLSC
+	def_bool n
+
+config ARC_HAS_COH_RTSC
+	def_bool n
+
+config ARC_HAS_REENTRANT_IRQ_LV2
+	def_bool n
+
+endif
+
+config NR_CPUS
+	int "Maximum number of CPUs (2-32)"
+	range 2 32
+	depends on SMP
+	default "2"
+
 menuconfig ARC_CACHE
 	bool "Enable Cache Support"
 	default y
+	# if SMP, cache enabled ONLY if ARC implementation has cache coherency
+	depends on !SMP || ARC_HAS_COH_CACHES
 
 if ARC_CACHE
 
@@ -213,6 +246,8 @@ config ARC_COMPACT_IRQ_LEVELS
 	default n
 	# Timer HAS to be high priority, for any other high priority config
 	select ARC_IRQ3_LV2
+	# if SMP, LV2 enabled ONLY if ARC implementation has LV2 re-entrancy
+	depends on !SMP || ARC_HAS_REENTRANT_IRQ_LV2
 
 if ARC_COMPACT_IRQ_LEVELS
 
@@ -261,6 +296,8 @@ config ARC_HAS_RTSC
 	bool "Insn: RTSC (64-bit r/o cycle counter)"
 	default y
 	depends on ARC_CPU_REL_4_10
+	# if SMP, enable RTSC only if counter is coherent across cores
+	depends on !SMP || ARC_HAS_COH_RTSC
 
 endmenu   # "ARC CPU Configuration"
 
@@ -309,7 +346,7 @@ menuconfig ARC_DBG
 
 config ARC_DBG_TLB_PARANOIA
 	bool "Paranoia Checks in Low Level TLB Handlers"
-	depends on ARC_DBG
+	depends on ARC_DBG && !SMP
 	default n
 
 config ARC_DBG_TLB_MISS_COUNT
diff --git a/arch/arc/Makefile b/arch/arc/Makefile
index 4f28f5b..ef54fed 100644
--- a/arch/arc/Makefile
+++ b/arch/arc/Makefile
@@ -133,3 +133,6 @@ archclean:
 # Thus forcing all exten calls in this file to be long calls
 export CFLAGS_decompress_inflate.o = -mmedium-calls
 export CFLAGS_initramfs.o = -mmedium-calls
+ifdef CONFIG_SMP
+export CFLAGS_core.o = -mmedium-calls
+endif
diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h
index 23ef2de..23daa32 100644
--- a/arch/arc/include/asm/entry.h
+++ b/arch/arc/include/asm/entry.h
@@ -389,11 +389,19 @@
  * to be saved again on kernel mode stack, as part of ptregs.
  *-------------------------------------------------------------*/
 .macro EXCPN_PROLOG_FREEUP_REG	reg
+#ifdef CONFIG_SMP
+	sr  \reg, [ARC_REG_SCRATCH_DATA0]
+#else
 	st  \reg, [@ex_saved_reg1]
+#endif
 .endm
 
 .macro EXCPN_PROLOG_RESTORE_REG	reg
+#ifdef CONFIG_SMP
+	lr  \reg, [ARC_REG_SCRATCH_DATA0]
+#else
 	ld  \reg, [@ex_saved_reg1]
+#endif
 .endm
 
 /*--------------------------------------------------------------
@@ -508,7 +516,11 @@
 	/* restore original r9 , saved in int1_saved_reg
 	* It will be saved on stack in macro: SAVE_CALLER_SAVED
 	*/
+#ifdef CONFIG_SMP
+	lr  r9, [ARC_REG_SCRATCH_DATA0]
+#else
 	ld  r9, [@int1_saved_reg]
+#endif
 
 	/* now we are ready to save the remaining context :) */
 	st      orig_r8_IS_IRQ1, [sp, 8]    /* Event Type */
@@ -639,6 +651,41 @@
 	bmsk \reg, \reg, 7
 .endm
 
+#ifdef CONFIG_SMP
+
+/*-------------------------------------------------
+ * Retrieve the current running task on this CPU
+ * 1. Determine curr CPU id.
+ * 2. Use it to index into _current_task[ ]
+ */
+.macro  GET_CURR_TASK_ON_CPU   reg
+	GET_CPU_ID  \reg
+	ld.as  \reg, [@_current_task, \reg]
+.endm
+
+/*-------------------------------------------------
+ * Save a new task as the "current" task on this CPU
+ * 1. Determine curr CPU id.
+ * 2. Use it to index into _current_task[ ]
+ *
+ * Coded differently than GET_CURR_TASK_ON_CPU (which uses LD.AS)
+ * because ST r0, [r1, offset] can ONLY have s9 @offset
+ * while   LD can take s9 (4 byte insn) or LIMM (8 byte insn)
+ */
+
+.macro  SET_CURR_TASK_ON_CPU    tsk, tmp
+	GET_CPU_ID  \tmp
+	add2 \tmp, @_current_task, \tmp
+	st   \tsk, [\tmp]
+#ifdef CONFIG_ARC_CURR_IN_REG
+	mov r25, \tsk
+#endif
+
+.endm
+
+
+#else   /* Uniprocessor implementation of macros */
+
 .macro  GET_CURR_TASK_ON_CPU    reg
 	ld  \reg, [@_current_task]
 .endm
@@ -650,6 +697,8 @@
 #endif
 .endm
 
+#endif /* SMP / UNI */
+
 /* ------------------------------------------------------------------
  * Get the ptr to some field of Current Task at @off in task struct
  *  -Uses r25 for Current task ptr if that is enabled
diff --git a/arch/arc/include/asm/mmu_context.h b/arch/arc/include/asm/mmu_context.h
index d12f3de..0d71fb1 100644
--- a/arch/arc/include/asm/mmu_context.h
+++ b/arch/arc/include/asm/mmu_context.h
@@ -147,8 +147,10 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 			     struct task_struct *tsk)
 {
+#ifndef CONFIG_SMP
 	/* PGD cached in MMU reg to avoid 3 mem lookups: task->mm->pgd */
 	write_aux_reg(ARC_REG_SCRATCH_DATA0, next->pgd);
+#endif
 
 	/*
 	 * Get a new ASID if task doesn't have a valid one. Possible when
@@ -197,7 +199,9 @@ static inline void destroy_context(struct mm_struct *mm)
 
 static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
 {
+#ifndef CONFIG_SMP
 	write_aux_reg(ARC_REG_SCRATCH_DATA0, next->pgd);
+#endif
 
 	/* Unconditionally get a new ASID */
 	get_new_mmu_context(next);
diff --git a/arch/arc/include/asm/mutex.h b/arch/arc/include/asm/mutex.h
index 3be5e64..a2f88ff 100644
--- a/arch/arc/include/asm/mutex.h
+++ b/arch/arc/include/asm/mutex.h
@@ -6,4 +6,13 @@
  * published by the Free Software Foundation.
  */
 
+/*
+ * xchg() based mutex fast path maintains a state of 0 or 1, as opposed to
+ * atomic dec based which can "count" any number of lock contenders.
+ * This ideally needs to be fixed in core, but for now switching to dec ver.
+ */
+#if defined(CONFIG_SMP) && (CONFIG_NR_CPUS > 2)
+#include <asm-generic/mutex-dec.h>
+#else
 #include <asm-generic/mutex-xchg.h>
+#endif
diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h
index dcb07015..b7e3668 100644
--- a/arch/arc/include/asm/pgtable.h
+++ b/arch/arc/include/asm/pgtable.h
@@ -354,11 +354,15 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
  * Thus use this macro only when you are certain that "current" is current
  * e.g. when dealing with signal frame setup code etc
  */
+#ifndef CONFIG_SMP
 #define pgd_offset_fast(mm, addr)	\
 ({					\
 	pgd_t *pgd_base = (pgd_t *) read_aux_reg(ARC_REG_SCRATCH_DATA0);  \
 	pgd_base + pgd_index(addr);	\
 })
+#else
+#define pgd_offset_fast(mm, addr)	pgd_offset(mm, addr)
+#endif
 
 extern void paging_init(void);
 extern pgd_t swapper_pg_dir[] __aligned(PAGE_SIZE);
diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h
index b7b1556..5f26b2c 100644
--- a/arch/arc/include/asm/processor.h
+++ b/arch/arc/include/asm/processor.h
@@ -58,7 +58,15 @@ unsigned long thread_saved_pc(struct task_struct *t);
 /* Prepare to copy thread state - unlazy all lazy status */
 #define prepare_to_copy(tsk)    do { } while (0)
 
+/*
+ * A lot of busy-wait loops in SMP are based off of non-volatile data otherwise
+ * get optimised away by gcc
+ */
+#ifdef CONFIG_SMP
+#define cpu_relax()	__asm__ __volatile__ ("" : : : "memory")
+#else
 #define cpu_relax()	do { } while (0)
+#endif
 
 #define copy_segments(tsk, mm)      do { } while (0)
 #define release_segments(mm)        do { } while (0)
diff --git a/arch/arc/include/asm/smp.h b/arch/arc/include/asm/smp.h
index 4341f3b..f91f194 100644
--- a/arch/arc/include/asm/smp.h
+++ b/arch/arc/include/asm/smp.h
@@ -9,6 +9,69 @@
 #ifndef __ASM_ARC_SMP_H
 #define __ASM_ARC_SMP_H
 
+#ifdef CONFIG_SMP
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/threads.h>
+
+#define raw_smp_processor_id() (current_thread_info()->cpu)
+
+/* including cpumask.h leads to cyclic deps hence this Forward declaration */
+struct cpumask;
+
+/*
+ * APIs provided by arch SMP code to generic code
+ */
+extern void arch_send_call_function_single_ipi(int cpu);
+extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
+
+/*
+ * APIs provided by arch SMP code to rest of arch code
+ */
+extern void __init smp_init_cpus(void);
+extern void __init first_lines_of_secondary(void);
+
+/*
+ * API expected BY platform smp code (FROM arch smp code)
+ *
+ * smp_ipi_irq_setup:
+ *	Takes @cpu and @irq to which the arch-common ISR is hooked up
+ */
+extern int smp_ipi_irq_setup(int cpu, int irq);
+
+/*
+ * APIs expected FROM platform smp code
+ *
+ * arc_platform_smp_cpuinfo:
+ *	returns a string containing info for /proc/cpuinfo
+ *
+ * arc_platform_smp_init_cpu:
+ *	Called from start_kernel_secondary to do any CPU local setup
+ *	such as starting a timer, setting up IPI etc
+ *
+ * arc_platform_smp_wait_to_boot:
+ *	Called from early bootup code for non-Master CPUs to "park" them
+ *
+ * arc_platform_smp_wakeup_cpu:
+ *	Called from __cpu_up (Master CPU) to kick start another one
+ *
+ * arc_platform_ipi_send:
+ *	Takes @cpumask to which IPI(s) would be sent.
+ *	The actual msg-id/buffer is manager in arch-common code
+ *
+ * arc_platform_ipi_clear:
+ *	Takes @cpu which got IPI at @irq to do any IPI clearing
+ */
+extern const char *arc_platform_smp_cpuinfo(void);
+extern void arc_platform_smp_init_cpu(void);
+extern void arc_platform_smp_wait_to_boot(int cpu);
+extern void arc_platform_smp_wakeup_cpu(int cpu, unsigned long pc);
+extern void arc_platform_ipi_send(const struct cpumask *callmap);
+extern void arc_platform_ipi_clear(int cpu, int irq);
+
+#endif  /* CONFIG_SMP */
+
 /*
  * ARC700 doesn't support atomic Read-Modify-Write ops.
  * Originally Interrupts had to be disabled around code to gaurantee atomicity.
@@ -18,10 +81,52 @@
  *
  * (1) These insn were introduced only in 4.10 release. So for older released
  *	support needed.
+ *
+ * (2) In a SMP setup, the LLOCK/SCOND atomiticity across CPUs needs to be
+ *	gaurantted by the platform (not something which core handles).
+ *	Assuming a platform won't, SMP Linux needs to use spinlocks + local IRQ
+ *	disabling for atomicity.
+ *
+ *	However exported spinlock API is not usable due to cyclic hdr deps
+ *	(even after system.h disintegration upstream)
+ *	asm/bitops.h -> linux/spinlock.h -> linux/preempt.h
+ *		-> linux/thread_info.h -> linux/bitops.h -> asm/bitops.h
+ *
+ *	So the workaround is to use the lowest level arch spinlock API.
+ *	The exported spinlock API is smart enough to be NOP for !CONFIG_SMP,
+ *	but same is not true for ARCH backend, hence the need for 2 variants
  */
 #ifndef CONFIG_ARC_HAS_LLSC
 
 #include <linux/irqflags.h>
+#ifdef CONFIG_SMP
+
+#include <asm/spinlock.h>
+
+extern arch_spinlock_t smp_atomic_ops_lock;
+extern arch_spinlock_t smp_bitops_lock;
+
+#define atomic_ops_lock(flags)	do {		\
+	local_irq_save(flags);			\
+	arch_spin_lock(&smp_atomic_ops_lock);	\
+} while (0)
+
+#define atomic_ops_unlock(flags) do {		\
+	arch_spin_unlock(&smp_atomic_ops_lock);	\
+	local_irq_restore(flags);		\
+} while (0)
+
+#define bitops_lock(flags)	do {		\
+	local_irq_save(flags);			\
+	arch_spin_lock(&smp_bitops_lock);	\
+} while (0)
+
+#define bitops_unlock(flags) do {		\
+	arch_spin_unlock(&smp_bitops_lock);	\
+	local_irq_restore(flags);		\
+} while (0)
+
+#else /* !CONFIG_SMP */
 
 #define atomic_ops_lock(flags)		local_irq_save(flags)
 #define atomic_ops_unlock(flags)	local_irq_restore(flags)
@@ -29,6 +134,8 @@
 #define bitops_lock(flags)		local_irq_save(flags)
 #define bitops_unlock(flags)		local_irq_restore(flags)
 
+#endif /* !CONFIG_SMP */
+
 #endif	/* !CONFIG_ARC_HAS_LLSC */
 
 #endif
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
index a24820f..cd2f882 100644
--- a/arch/arc/kernel/Makefile
+++ b/arch/arc/kernel/Makefile
@@ -13,6 +13,7 @@ obj-y	+= signal.o traps.o sys.o troubleshoot.o stacktrace.o clk.o
 
 obj-$(CONFIG_OF)			+= devtree.o
 obj-$(CONFIG_MODULES)			+= arcksyms.o module.o
+obj-$(CONFIG_SMP) 			+= smp.o
 
 obj-$(CONFIG_ARC_FPU_SAVE_RESTORE)	+= fpu.o
 CFLAGS_fpu.o   += -mdpfp
diff --git a/arch/arc/kernel/ctx_sw.c b/arch/arc/kernel/ctx_sw.c
index fbf739c..60844da 100644
--- a/arch/arc/kernel/ctx_sw.c
+++ b/arch/arc/kernel/ctx_sw.c
@@ -58,7 +58,18 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task)
 		 * For SMP extra work to get to &_current_task[cpu]
 		 * (open coded SET_CURR_TASK_ON_CPU)
 		 */
+#ifndef CONFIG_SMP
 		"st  %2, [@_current_task]	\n\t"
+#else
+		"lr   r24, [identity]		\n\t"
+		"lsr  r24, r24, 8		\n\t"
+		"bmsk r24, r24, 7		\n\t"
+		"add2 r24, @_current_task, r24	\n\t"
+		"st   %2,  [r24]		\n\t"
+#endif
+#ifdef CONFIG_ARC_CURR_IN_REG
+		"mov r25, %2   \n\t"
+#endif
 
 		/* get ksp of incoming task from tsk->thread.ksp */
 		"ld.as  sp, [%2, %1]   \n\t"
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index e33a0bf..3f6ce98 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -232,7 +232,11 @@ ARC_EXIT handle_interrupt_level2
 ARC_ENTRY handle_interrupt_level1
 
 	/* free up r9 as scratchpad */
+#ifdef CONFIG_SMP
+	sr  r9, [ARC_REG_SCRATCH_DATA0]
+#else
 	st   r9, [@int1_saved_reg]
+#endif
 
 	;Which mode (user/kernel) was the system in when intr occured
 	lr  r9, [status32_l1]
diff --git a/arch/arc/kernel/head.S b/arch/arc/kernel/head.S
index e63f6a4..006dec3 100644
--- a/arch/arc/kernel/head.S
+++ b/arch/arc/kernel/head.S
@@ -27,6 +27,15 @@ stext:
 	; Don't clobber r0-r4 yet. It might have bootloader provided info
 	;-------------------------------------------------------------------
 
+#ifdef CONFIG_SMP
+	; Only 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)
+	GET_CPU_ID  r5
+	cmp	r5, 0
+	jnz	arc_platform_smp_wait_to_boot
+#endif
 	; Clear BSS before updating any globals
 	; XXX: use ZOL here
 	mov	r5, __bss_start
@@ -76,3 +85,27 @@ stext:
 	GET_TSK_STACK_BASE r9, sp	; r9 = tsk, sp = stack base(output)
 
 	j	start_kernel	; "C" entry point
+
+#ifdef CONFIG_SMP
+;----------------------------------------------------------------
+;     First lines of code run by secondary before jumping to 'C'
+;----------------------------------------------------------------
+	.section .init.text, "ax",@progbits
+	.type first_lines_of_secondary, @function
+	.globl first_lines_of_secondary
+
+first_lines_of_secondary:
+
+	; setup per-cpu idle task as "current" on this CPU
+	ld	r0, [@secondary_idle_tsk]
+	SET_CURR_TASK_ON_CPU  r0, r1
+
+	; setup stack (fp, sp)
+	mov	fp, 0
+
+	; set it's stack base to tsk->thread_info bottom
+	GET_TSK_STACK_BASE r0, sp
+
+	j	start_kernel_secondary
+
+#endif
diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
index ca70894..df7da2b 100644
--- a/arch/arc/kernel/irq.c
+++ b/arch/arc/kernel/irq.c
@@ -124,6 +124,11 @@ void __init init_IRQ(void)
 {
 	init_onchip_IRQ();
 	plat_init_IRQ();
+
+#ifdef CONFIG_SMP
+	/* Master CPU can initialize it's side of IPI */
+	arc_platform_smp_init_cpu();
+#endif
 }
 
 /*
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index 27aebd6..4026b5a 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -86,6 +86,10 @@ void __init setup_arch(char **cmdline_p)
 
 	setup_processor();
 
+#ifdef CONFIG_SMP
+	smp_init_cpus();
+#endif
+
 	setup_arch_memory();
 
 	unflatten_device_tree();
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
new file mode 100644
index 0000000..1f762ad
--- /dev/null
+++ b/arch/arc/kernel/smp.c
@@ -0,0 +1,320 @@
+/*
+ * 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.
+ *
+ * RajeshwarR: Dec 11, 2007
+ *   -- Added support for Inter Processor Interrupts
+ *
+ * Vineetg: Nov 1st, 2007
+ *    -- Initial Write (Borrowed heavily from ARM)
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/profile.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/mm.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/atomic.h>
+#include <linux/percpu.h>
+#include <linux/cpumask.h>
+#include <linux/spinlock_types.h>
+#include <linux/reboot.h>
+#include <asm/processor.h>
+#include <asm/setup.h>
+
+arch_spinlock_t smp_atomic_ops_lock = __ARCH_SPIN_LOCK_UNLOCKED;
+arch_spinlock_t smp_bitops_lock = __ARCH_SPIN_LOCK_UNLOCKED;
+
+/* XXX: per cpu ? Only needed once in early seconday boot */
+struct task_struct *secondary_idle_tsk;
+
+/* Called from start_kernel */
+void __init smp_prepare_boot_cpu(void)
+{
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+void __init smp_init_cpus(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < NR_CPUS; i++)
+		set_cpu_possible(i, true);
+}
+
+/* called from init ( ) =>  process 1 */
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+	int i;
+
+	/*
+	 * Initialise the present map, which describes the set of CPUs
+	 * actually populated at the present time.
+	 */
+	for (i = 0; i < max_cpus; i++)
+		set_cpu_present(i, true);
+}
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
+
+}
+
+/*
+ * After power-up, a non Master CPU needs to wait for Master to kick start it
+ *
+ * The default implementation halts
+ *
+ * This relies on platform specific support allowing Master to directly set
+ * this CPU's PC (to be @first_lines_of_secondary() and kick start it.
+ *
+ * In lack of such h/w assist, platforms can override this function
+ *   - make this function busy-spin on a token, eventually set by Master
+ *     (from arc_platform_smp_wakeup_cpu())
+ *   - Once token is available, jump to @first_lines_of_secondary
+ *     (using inline asm).
+ *
+ * Alert: can NOT use stack here as it has not been determined/setup for CPU.
+ *        If it turns out to be elaborate, it's better to code it in assembly
+ *
+ */
+void __attribute__((weak)) arc_platform_smp_wait_to_boot(int cpu)
+{
+	/*
+	 * As a hack for debugging - since debugger will single-step over the
+	 * FLAG insn - wrap the halt itself it in a self loop
+	 */
+	__asm__ __volatile__(
+	"1:		\n"
+	"	flag 1	\n"
+	"	b 1b	\n");
+}
+
+/*
+ * The very first "C" code executed by secondary
+ * Called from asm stub in head.S
+ * "current"/R25 already setup by low level boot code
+ */
+void __cpuinit start_kernel_secondary(void)
+{
+	struct mm_struct *mm = &init_mm;
+	unsigned int cpu = smp_processor_id();
+
+	/* MMU, Caches, Vector Table, Interrupts etc */
+	setup_processor();
+
+	atomic_inc(&mm->mm_users);
+	atomic_inc(&mm->mm_count);
+	current->active_mm = mm;
+
+	notify_cpu_starting(cpu);
+	set_cpu_online(cpu, true);
+
+	pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu);
+
+	arc_platform_smp_init_cpu();
+
+	arc_local_timer_setup(cpu);
+
+	local_irq_enable();
+	preempt_disable();
+	cpu_idle();
+}
+
+/*
+ * Called from kernel_init( ) -> smp_init( ) - for each CPU
+ *
+ * At this point, Secondary Processor  is "HALT"ed:
+ *  -It booted, but was halted in head.S
+ *  -It was configured to halt-on-reset
+ *  So need to wake it up.
+ *
+ * Essential requirements being where to run from (PC) and stack (SP)
+*/
+int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
+{
+	unsigned long wait_till;
+
+	secondary_idle_tsk = idle;
+
+	pr_info("Idle Task [%d] %p", cpu, idle);
+	pr_info("Trying to bring up CPU%u ...\n", cpu);
+
+	arc_platform_smp_wakeup_cpu(cpu,
+				(unsigned long)first_lines_of_secondary);
+
+	/* wait for 1 sec after kicking the secondary */
+	wait_till = jiffies + HZ;
+	while (time_before(jiffies, wait_till)) {
+		if (cpu_online(cpu))
+			break;
+	}
+
+	if (!cpu_online(cpu)) {
+		pr_info("Timeout: CPU%u FAILED to comeup !!!\n", cpu);
+		return -1;
+	}
+
+	secondary_idle_tsk = NULL;
+
+	return 0;
+}
+
+/*
+ * not supported here
+ */
+int __init setup_profiling_timer(unsigned int multiplier)
+{
+	return -EINVAL;
+}
+
+/*****************************************************************************/
+/*              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_RESCHEDULE = 1,
+	IPI_CALL_FUNC,
+	IPI_CALL_FUNC_SINGLE,
+	IPI_CPU_STOP
+};
+
+struct ipi_data {
+	unsigned long bits;
+};
+
+static DEFINE_PER_CPU(struct ipi_data, ipi_data);
+
+static void ipi_send_msg(const struct cpumask *callmap, enum ipi_msg_type msg)
+{
+	unsigned long flags;
+	unsigned int cpu;
+
+	local_irq_save(flags);
+
+	for_each_cpu(cpu, callmap) {
+		struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
+		set_bit(msg, &ipi->bits);
+	}
+
+	/* Call the platform specific cross-CPU call function  */
+	arc_platform_ipi_send(callmap);
+
+	local_irq_restore(flags);
+}
+
+void smp_send_reschedule(int cpu)
+{
+	ipi_send_msg(cpumask_of(cpu), IPI_RESCHEDULE);
+}
+
+void smp_send_stop(void)
+{
+	struct cpumask targets;
+	cpumask_copy(&targets, cpu_online_mask);
+	cpumask_clear_cpu(smp_processor_id(), &targets);
+	ipi_send_msg(&targets, IPI_CPU_STOP);
+}
+
+void arch_send_call_function_single_ipi(int cpu)
+{
+	ipi_send_msg(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+}
+
+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
+{
+	ipi_send_msg(mask, IPI_CALL_FUNC);
+}
+
+/*
+ * ipi_cpu_stop - handle IPI from smp_send_stop()
+ */
+static void ipi_cpu_stop(unsigned int cpu)
+{
+	machine_halt();
+}
+
+static inline void __do_IPI(unsigned long *ops, struct ipi_data *ipi, int cpu)
+{
+	unsigned long msg = 0;
+
+	do {
+		msg = find_next_bit(ops, BITS_PER_LONG, msg+1);
+
+		switch (msg) {
+		case IPI_RESCHEDULE:
+			scheduler_ipi();
+			break;
+
+		case IPI_CALL_FUNC:
+			generic_smp_call_function_interrupt();
+			break;
+
+		case IPI_CALL_FUNC_SINGLE:
+			generic_smp_call_function_single_interrupt();
+			break;
+
+		case IPI_CPU_STOP:
+			ipi_cpu_stop(cpu);
+			break;
+		}
+	} while (msg < BITS_PER_LONG);
+
+}
+
+/*
+ * arch-common ISR to handle for inter-processor interrupts
+ * Has hooks for platform specific IPI
+ */
+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;
+
+	arc_platform_ipi_clear(cpu, irq);
+
+	/*
+	 * XXX: is this loop really needed
+	 * And do we need to move ipi_clean inside
+	 */
+	while ((ops = xchg(&ipi->bits, 0)) != 0)
+		__do_IPI(&ops, ipi, cpu);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * API called by platform code to hookup arch-common ISR to their IPI IRQ
+ */
+static DEFINE_PER_CPU(int, ipi_dev);
+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);
+}
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c
index 232a0ff..e96030c 100644
--- a/arch/arc/mm/tlb.c
+++ b/arch/arc/mm/tlb.c
@@ -474,6 +474,12 @@ void __init arc_mmu_init(void)
 
 	/* Enable the MMU */
 	write_aux_reg(ARC_REG_PID, MMU_ENABLE);
+
+	/* In smp we use this reg for interrupt 1 scratch */
+#ifndef CONFIG_SMP
+	/* swapper_pg_dir is the pgd for the kernel, used by vmalloc */
+	write_aux_reg(ARC_REG_SCRATCH_DATA0, swapper_pg_dir);
+#endif
 }
 
 /*
diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S
index 164b021..4b1ad2d 100644
--- a/arch/arc/mm/tlbex.S
+++ b/arch/arc/mm/tlbex.S
@@ -57,9 +57,15 @@
 	.global ex_saved_reg1
 	.align 1 << L1_CACHE_SHIFT	; IMP: Must be Cache Line aligned
 	.type   ex_saved_reg1, @object
+#ifdef CONFIG_SMP
+	.size   ex_saved_reg1, (CONFIG_NR_CPUS << L1_CACHE_SHIFT)
+ex_saved_reg1:
+	.zero (CONFIG_NR_CPUS << L1_CACHE_SHIFT)
+#else
 	.size   ex_saved_reg1, 16
 ex_saved_reg1:
 	.zero 16
+#endif
 
 ;============================================================================
 ;  Troubleshooting Stuff
@@ -116,7 +122,13 @@ ex_saved_reg1:
 
 	lr  r2, [efa]
 
+#ifndef CONFIG_SMP
 	lr  r1, [ARC_REG_SCRATCH_DATA0] ; current pgd
+#else
+	GET_CURR_TASK_ON_CPU  r1
+	ld  r1, [r1, TASK_ACT_MM]
+	ld  r1, [r1, MM_PGD]
+#endif
 
 	lsr     r0, r2, PGDIR_SHIFT     ; Bits for indexing into PGD
 	ld.as   r1, [r1, r0]            ; PGD entry corresp to faulting addr
@@ -192,12 +204,28 @@ ex_saved_reg1:
 ;	".size   ex_saved_reg1, 16"
 ; [All of this dance is to avoid stack switching for each TLB Miss, since we
 ; only need to save only a handful of regs, as opposed to complete reg file]
+;
+; For ARC700 SMP, the "global" obviously can't be used for free up the FIRST
+; core reg as it will not be SMP safe.
+; Thus scratch AUX reg is used (and no longer used to cache task PGD).
+; To save the rest of 3 regs - per cpu, the global is made "per-cpu".
+; Epilogue thus has to locate the "per-cpu" storage for regs.
+; To avoid cache line bouncing the per-cpu global is aligned/sized per
+; L1_CACHE_SHIFT, despite fundamentally needing to be 12 bytes only. Hence
+;	".size   ex_saved_reg1, (CONFIG_NR_CPUS << L1_CACHE_SHIFT)"
 
 ; As simple as that....
 
 .macro TLBMISS_FREEUP_REGS
+#ifdef CONFIG_SMP
+	sr  r0, [ARC_REG_SCRATCH_DATA0]	; freeup r0 to code with
+	GET_CPU_ID  r0			; get to per cpu scratch mem,
+	lsl r0, r0, L1_CACHE_SHIFT	; cache line wide per cpu
+	add r0, @ex_saved_reg1, r0
+#else
 	st    r0, [@ex_saved_reg1]
 	mov_s r0, @ex_saved_reg1
+#endif
 	st_s  r1, [r0, 4]
 	st_s  r2, [r0, 8]
 	st_s  r3, [r0, 12]
@@ -210,11 +238,21 @@ ex_saved_reg1:
 
 ;-----------------------------------------------------------------
 .macro TLBMISS_RESTORE_REGS
+#ifdef CONFIG_SMP
+	GET_CPU_ID  r0			; get to per cpu scratch mem
+	lsl r0, r0, L1_CACHE_SHIFT	; each is cache line wide
+	add r0, @ex_saved_reg1, r0
+	ld_s  r3, [r0,12]
+	ld_s  r2, [r0, 8]
+	ld_s  r1, [r0, 4]
+	lr    r0, [ARC_REG_SCRATCH_DATA0]
+#else
 	mov_s r0, @ex_saved_reg1
 	ld_s  r3, [r0,12]
 	ld_s  r2, [r0, 8]
 	ld_s  r1, [r0, 4]
 	ld_s  r0, [r0]
+#endif
 .endm
 
 .section .text, "ax",@progbits	;Fast Path Code, candidate for ICCM
diff --git a/arch/arc/plat-arcfpga/Kconfig b/arch/arc/plat-arcfpga/Kconfig
index 7af3a4e..38752bf 100644
--- a/arch/arc/plat-arcfpga/Kconfig
+++ b/arch/arc/plat-arcfpga/Kconfig
@@ -13,6 +13,7 @@ choice
 
 config ARC_BOARD_ANGEL4
 	bool "ARC Angel4"
+	select ISS_SMP_EXTN if SMP
 	help
 	  ARC Angel4 FPGA Ref Platform (Xilinx Virtex Based)
 
@@ -21,6 +22,19 @@ config ARC_BOARD_ML509
 	help
 	  ARC ML509 FPGA Ref Platform (Xilinx Virtex-5 Based)
 
+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).
+	  The SMP extensions include:
+	  -IDU (Interrupt Distribution Unit)
+	  -XTL (To enable CPU start/stop/set-PC for another CPU)
+	  It doesn't provide coherent Caches and/or Atomic Ops (LLOCK/SCOND)
+
 endchoice
 
 config ARC_SERIAL_BAUD
diff --git a/arch/arc/plat-arcfpga/Makefile b/arch/arc/plat-arcfpga/Makefile
index 385eb9d..2a828be 100644
--- a/arch/arc/plat-arcfpga/Makefile
+++ b/arch/arc/plat-arcfpga/Makefile
@@ -7,3 +7,4 @@
 #
 
 obj-y := platform.o irq.o
+obj-$(CONFIG_SMP)		+= smp.o
diff --git a/arch/arc/plat-arcfpga/include/plat/irq.h b/arch/arc/plat-arcfpga/include/plat/irq.h
index b34e087..255b90e 100644
--- a/arch/arc/plat-arcfpga/include/plat/irq.h
+++ b/arch/arc/plat-arcfpga/include/plat/irq.h
@@ -12,7 +12,11 @@
 #ifndef __PLAT_IRQ_H
 #define __PLAT_IRQ_H
 
-#define NR_IRQS		16
+#ifdef CONFIG_SMP
+#define NR_IRQS 32
+#else
+#define NR_IRQS 16
+#endif
 
 #define UART0_IRQ	5
 #define UART1_IRQ	10
@@ -24,4 +28,8 @@
 #define PCI_IRQ		14
 #define PS2_IRQ		15
 
+#ifdef CONFIG_SMP
+#define IDU_INTERRUPT_0 16
+#endif
+
 #endif
diff --git a/arch/arc/plat-arcfpga/include/plat/smp.h b/arch/arc/plat-arcfpga/include/plat/smp.h
new file mode 100644
index 0000000..8c5e46c
--- /dev/null
+++ b/arch/arc/plat-arcfpga/include/plat/smp.h
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ *
+ *  Rajeshwar Ranga: Interrupt Distribution Unit API's
+ */
+
+#ifndef __PLAT_ARCFPGA_SMP_H
+#define __PLAT_ARCFPGA_SMP_H
+
+#ifdef CONFIG_SMP
+
+#include <linux/types.h>
+#include <asm/arcregs.h>
+
+#define ARC_AUX_IDU_REG_CMD		0x2000
+#define ARC_AUX_IDU_REG_PARAM		0x2001
+
+#define ARC_AUX_XTL_REG_CMD		0x2002
+#define ARC_AUX_XTL_REG_PARAM		0x2003
+
+#define ARC_REG_MP_BCR			0x2021
+
+#define ARC_XTL_CMD_WRITE_PC		0x04
+#define ARC_XTL_CMD_CLEAR_HALT		0x02
+
+/*
+ * Build Configuration Register which identifies the sub-components
+ */
+struct bcr_mp {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+	unsigned int mp_arch:16, pad:5, sdu:1, idu:1, scu:1, ver:8;
+#else
+	unsigned int ver:8, scu:1, idu:1, sdu:1, pad:5, mp_arch:16;
+#endif
+};
+
+/* IDU supports 256 common interrupts */
+#define NR_IDU_IRQS			256
+
+/*
+ * The Aux Regs layout is same bit-by-bit in both BE/LE modes.
+ * However when casted as a bitfield encoded "C" struct, gcc treats it as
+ * memory, generating different code for BE/LE, requiring strcture adj (see
+ * include/asm/arcregs.h)
+ *
+ * However when manually "carving" the value for a Aux, no special handling
+ * of BE is needed because of the property discribed above
+ */
+#define IDU_SET_COMMAND(irq, cmd)			\
+do {							\
+	uint32_t __val;					\
+	__val = (((irq & 0xFF) << 8) | (cmd & 0xFF));	\
+	write_aux_reg(ARC_AUX_IDU_REG_CMD, __val);	\
+} while (0)
+
+#define IDU_SET_PARAM(par)  write_aux_reg(ARC_AUX_IDU_REG_PARAM, par)
+#define IDU_GET_PARAM()     read_aux_reg(ARC_AUX_IDU_REG_PARAM)
+
+/* IDU Commands */
+#define IDU_DISABLE			0x00
+#define IDU_ENABLE			0x01
+#define IDU_IRQ_CLEAR			0x02
+#define IDU_IRQ_ASSERT			0x03
+#define IDU_IRQ_WMODE			0x04
+#define IDU_IRQ_STATUS			0x05
+#define IDU_IRQ_ACK			0x06
+#define IDU_IRQ_PEND			0x07
+#define IDU_IRQ_RMODE			0x08
+#define IDU_IRQ_WBITMASK		0x09
+#define IDU_IRQ_RBITMASK		0x0A
+
+#define idu_enable()		IDU_SET_COMMAND(0, IDU_ENABLE)
+#define idu_disable()		IDU_SET_COMMAND(0, IDU_DISABLE)
+
+#define idu_irq_assert(irq)	IDU_SET_COMMAND((irq), IDU_IRQ_ASSERT)
+#define idu_irq_clear(irq)	IDU_SET_COMMAND((irq), IDU_IRQ_CLEAR)
+
+/* IDU Interrupt Mode - Destination Encoding */
+#define IDU_IRQ_MOD_DISABLE		0x00
+#define IDU_IRQ_MOD_ROUND_RECP		0x01
+#define IDU_IRQ_MOD_TCPU_FIRSTRECP	0x02
+#define IDU_IRQ_MOD_TCPU_ALLRECP	0x03
+
+/* IDU Interrupt Mode  - Triggering Mode */
+#define IDU_IRQ_MODE_LEVEL_TRIG		0x00
+#define IDU_IRQ_MODE_PULSE_TRIG		0x01
+
+#define IDU_IRQ_MODE_PARAM(dest_mode, trig_mode)   \
+	(((trig_mode & 0x01) << 15) | (dest_mode & 0xFF))
+
+struct idu_irq_config {
+	uint8_t irq;
+	uint8_t dest_mode;
+	uint8_t trig_mode;
+};
+
+struct idu_irq_status {
+	uint8_t irq;
+	bool enabled;
+	bool status;
+	bool ack;
+	bool pend;
+	uint8_t next_rr;
+};
+
+extern void idu_irq_set_tgtcpu(uint8_t irq, uint32_t mask);
+extern void idu_irq_set_mode(uint8_t irq, uint8_t dest_mode, uint8_t trig_mode);
+
+#endif	/* CONFIG_SMP */
+
+#endif
diff --git a/arch/arc/plat-arcfpga/irq.c b/arch/arc/plat-arcfpga/irq.c
index ed72636..590edd1 100644
--- a/arch/arc/plat-arcfpga/irq.c
+++ b/arch/arc/plat-arcfpga/irq.c
@@ -9,7 +9,17 @@
  */
 
 #include <linux/interrupt.h>
+#include <asm/irq.h>
 
 void __init plat_init_IRQ(void)
 {
+	/*
+	 * SMP Hack because UART IRQ hardwired to cpu0 (boot-cpu) but if the
+	 * request_irq() comes from any other CPU, the low level IRQ unamsking
+	 * essential for getting Interrupts won't be enabled on cpu0, locking
+	 * up the UART state machine.
+	 */
+#ifdef CONFIG_SMP
+	arch_unmask_irq(UART0_IRQ);
+#endif
 }
diff --git a/arch/arc/plat-arcfpga/smp.c b/arch/arc/plat-arcfpga/smp.c
new file mode 100644
index 0000000..a95fcdb
--- /dev/null
+++ b/arch/arc/plat-arcfpga/smp.c
@@ -0,0 +1,167 @@
+/*
+ * ARC700 Simulation-only Extensions for SMP
+ *
+ * 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.
+ *
+ *  Vineet Gupta    - 2012 : split off arch common and plat specific SMP
+ *  Rajeshwar Ranga - 2007 : Interrupt Distribution Unit API's
+ */
+
+#include <linux/smp.h>
+#include <asm/irq.h>
+#include <plat/smp.h>
+
+static char smp_cpuinfo_buf[128];
+
+/*
+ *-------------------------------------------------------------------
+ * Platform specific callbacks expected by arch SMP code
+ *-------------------------------------------------------------------
+ */
+
+const char *arc_platform_smp_cpuinfo(void)
+{
+#define IS_AVAIL1(var, str)    ((var) ? str : "")
+
+	struct bcr_mp mp;
+
+	READ_BCR(ARC_REG_MP_BCR, mp);
+
+	sprintf(smp_cpuinfo_buf, "Extn [700-SMP]: v%d, arch(%d) %s %s %s\n",
+		mp.ver, mp.mp_arch, IS_AVAIL1(mp.scu, "SCU"),
+		IS_AVAIL1(mp.idu, "IDU"), IS_AVAIL1(mp.sdu, "SDU"));
+
+	return smp_cpuinfo_buf;
+}
+
+/*
+ * Master kick starting another CPU
+ */
+void arc_platform_smp_wakeup_cpu(int cpu, unsigned long pc)
+{
+	/* setup the start PC */
+	write_aux_reg(ARC_AUX_XTL_REG_PARAM, pc);
+
+	/* Trigger WRITE_PC cmd for this cpu */
+	write_aux_reg(ARC_AUX_XTL_REG_CMD,
+			(ARC_XTL_CMD_WRITE_PC | (cpu << 8)));
+
+	/* Take the cpu out of Halt */
+	write_aux_reg(ARC_AUX_XTL_REG_CMD,
+			(ARC_XTL_CMD_CLEAR_HALT | (cpu << 8)));
+
+}
+
+/*
+ * Any SMP specific init any CPU does when it comes up.
+ * Here we setup the CPU to enable Inter-Processor-Interrupts
+ * Called for each CPU
+ * -Master      : init_IRQ()
+ * -Other(s)    : start_kernel_secondary()
+ */
+void arc_platform_smp_init_cpu(void)
+{
+	int cpu = smp_processor_id();
+
+	/* Check if CPU is configured for more than 16 interrupts */
+	if (NR_IRQS <= 16 || get_hw_config_num_irq() <= 16)
+		panic("[arcfpga] IRQ system can't support IDU IPI\n");
+
+	idu_disable();
+
+	/****************************************************************
+	 * IDU provides a set of Common IRQs, each of which can be dynamically
+	 * attached to (1|many|all) CPUs.
+	 * The Common IRQs [0-15] are mapped as CPU pvt [16-31]
+	 *
+	 * Here we use a simple 1:1 mapping:
+	 * A CPU 'x' is wired to Common IRQ 'x'.
+	 * So an IDU ASSERT on IRQ 'x' will trigger Interupt on CPU 'x', which
+	 * makes up for our simple IPI plumbing.
+	 *
+	 * TBD: Have a dedicated multicast IRQ for sending IPIs to all CPUs
+	 *      w/o having to do one-at-a-time
+	 ******************************************************************/
+
+	/*
+	 * Claim an IRQ which would trigger IPI on this CPU.
+	 * In IDU parlance it involves setting up a cpu bitmask for the IRQ
+	 * The bitmap here contains only 1 CPU (self).
+	 */
+	idu_irq_set_tgtcpu(cpu, 0x1 << cpu);
+
+	/* Set the IRQ destination to use the bitmask above */
+	idu_irq_set_mode(cpu, 7, /* XXX: IDU_IRQ_MOD_TCPU_ALLRECP: ISS bug */
+			 IDU_IRQ_MODE_PULSE_TRIG);
+
+	idu_enable();
+
+	/* Attach the arch-common IPI ISR to our IDU IRQ */
+	smp_ipi_irq_setup(cpu, IDU_INTERRUPT_0 + cpu);
+}
+
+void arc_platform_ipi_send(const struct cpumask *callmap)
+{
+	unsigned int cpu;
+
+	for_each_cpu(cpu, callmap)
+		idu_irq_assert(cpu);
+}
+
+void arc_platform_ipi_clear(int cpu, int irq)
+{
+	idu_irq_clear(IDU_INTERRUPT_0 + cpu);
+}
+
+/*
+ *-------------------------------------------------------------------
+ * Low level Platform IPI Providers
+ *-------------------------------------------------------------------
+ */
+
+/* Set the Mode for the Common IRQ */
+void idu_irq_set_mode(uint8_t irq, uint8_t dest_mode, uint8_t trig_mode)
+{
+	uint32_t par = IDU_IRQ_MODE_PARAM(dest_mode, trig_mode);
+
+	IDU_SET_PARAM(par);
+	IDU_SET_COMMAND(irq, IDU_IRQ_WMODE);
+}
+
+/* Set the target cpu Bitmask for Common IRQ */
+void idu_irq_set_tgtcpu(uint8_t irq, uint32_t mask)
+{
+	IDU_SET_PARAM(mask);
+	IDU_SET_COMMAND(irq, IDU_IRQ_WBITMASK);
+}
+
+/* Get the Interrupt Acknowledged status for IRQ (as CPU Bitmask) */
+bool idu_irq_get_ack(uint8_t irq)
+{
+	uint32_t val;
+
+	IDU_SET_COMMAND(irq, IDU_IRQ_ACK);
+	val = IDU_GET_PARAM();
+
+	return val & (1 << irq);
+}
+
+/*
+ * Get the Interrupt Pending status for IRQ (as CPU Bitmask)
+ * -Pending means CPU has not yet noticed the IRQ (e.g. disabled)
+ * -After Interrupt has been taken, the IPI expcitily needs to be
+ *  cleared, to be acknowledged.
+ */
+bool idu_irq_get_pend(uint8_t irq)
+{
+	uint32_t val;
+
+	IDU_SET_COMMAND(irq, IDU_IRQ_PEND);
+	val = IDU_GET_PARAM();
+
+	return val & (1 << irq);
+}
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 48/71] ARC: kprobes support
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (17 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 44/71] ARC: SMP support Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 57/71] ARC: Hostlink Pseudo-Driver for Metaware Debugger Vineet Gupta
                   ` (6 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta, Rajeshwar Ranga

Origin port done by Rajeshwar Ranga

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Rajeshwar Ranga <rajeshwar.ranga@gmail.com>
---
 arch/arc/Kconfig               |    2 +
 arch/arc/include/asm/kprobes.h |   62 +++++
 arch/arc/include/asm/ptrace.h  |    5 +
 arch/arc/kernel/Makefile       |    1 +
 arch/arc/kernel/disasm.c       |    5 +-
 arch/arc/kernel/kprobes.c      |  525 ++++++++++++++++++++++++++++++++++++++++
 arch/arc/kernel/traps.c        |   13 +
 7 files changed, 610 insertions(+), 3 deletions(-)
 create mode 100644 arch/arc/include/asm/kprobes.h
 create mode 100644 arch/arc/kernel/kprobes.c

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 84b23fa..cde8d3f 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -24,6 +24,8 @@ config ARC
 	select GENERIC_SMP_IDLE_THREAD
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_GENERIC_HARDIRQS
+	select HAVE_KPROBES
+	select HAVE_KRETPROBES
 	select HAVE_MEMBLOCK
 	select HAVE_MOD_ARCH_SPECIFIC if ARC_DW2_UNWIND
 	select HAVE_OPROFILE
diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h
new file mode 100644
index 0000000..4d9c211
--- /dev/null
+++ b/arch/arc/include/asm/kprobes.h
@@ -0,0 +1,62 @@
+/*
+ * 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 _ARC_KPROBES_H
+#define _ARC_KPROBES_H
+
+#ifdef CONFIG_KPROBES
+
+typedef u16 kprobe_opcode_t;
+
+#define UNIMP_S_INSTRUCTION 0x79e0
+#define TRAP_S_2_INSTRUCTION 0x785e
+
+#define MAX_INSN_SIZE   8
+#define MAX_STACK_SIZE  64
+
+struct arch_specific_insn {
+	int is_short;
+	kprobe_opcode_t *t1_addr, *t2_addr;
+	kprobe_opcode_t t1_opcode, t2_opcode;
+};
+
+#define flush_insn_slot(p)  do {  } while (0)
+
+#define kretprobe_blacklist_size    0
+
+struct kprobe;
+
+void arch_remove_kprobe(struct kprobe *p);
+
+int kprobe_exceptions_notify(struct notifier_block *self,
+			     unsigned long val, void *data);
+
+struct prev_kprobe {
+	struct kprobe *kp;
+	unsigned long status;
+};
+
+struct kprobe_ctlblk {
+	unsigned int kprobe_status;
+	struct pt_regs jprobe_saved_regs;
+	char jprobes_stack[MAX_STACK_SIZE];
+	struct prev_kprobe prev_kprobe;
+};
+
+int kprobe_fault_handler(struct pt_regs *regs, unsigned long cause);
+void kretprobe_trampoline(void);
+void trap_is_kprobe(unsigned long cause, unsigned long address,
+			   struct pt_regs *regs);
+#else
+static void trap_is_kprobe(unsigned long cause, unsigned long address,
+			   struct pt_regs *regs)
+{
+}
+#endif
+
+#endif
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
index 8bf7ff4..713f145 100644
--- a/arch/arc/include/asm/ptrace.h
+++ b/arch/arc/include/asm/ptrace.h
@@ -146,6 +146,11 @@ struct user_regs_struct {
 	(struct pt_regs *)(pg_start + THREAD_SIZE - 4) - 1;	\
 })
 
+static inline long regs_return_value(struct pt_regs *regs)
+{
+	return regs->r0;
+}
+
 #endif /* !__ASSEMBLY__ */
 
 #define orig_r8_IS_SCALL		0x0001
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
index 8906531..a64a604 100644
--- a/arch/arc/kernel/Makefile
+++ b/arch/arc/kernel/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_OF)			+= devtree.o
 obj-$(CONFIG_MODULES)			+= arcksyms.o module.o
 obj-$(CONFIG_SMP) 			+= smp.o
 obj-$(CONFIG_ARC_DW2_UNWIND)		+= unwind.o
+obj-$(CONFIG_KPROBES)      		+= kprobes.o
 
 obj-$(CONFIG_ARC_FPU_SAVE_RESTORE)	+= fpu.o
 CFLAGS_fpu.o   += -mdpfp
diff --git a/arch/arc/kernel/disasm.c b/arch/arc/kernel/disasm.c
index 254d11a..51bad8f 100644
--- a/arch/arc/kernel/disasm.c
+++ b/arch/arc/kernel/disasm.c
@@ -497,9 +497,8 @@ void __kprobes set_reg(int reg, long val, struct pt_regs *regs,
  * @pc +2/4/6 (ARCompact ISA allows free intermixing of 16/32 bit insns).
  *
  * If @pc is a branch
- * 	-@tgt_if_br is set to branch target.
- * 	-If branch has delay slot, @next_pc updated with actual next PC.
- *
+ *	-@tgt_if_br is set to branch target.
+ *	-If branch has delay slot, @next_pc updated with actual next PC.
  */
 int __kprobes disasm_next_pc(unsigned long pc, struct pt_regs *regs,
 			     struct callee_regs *cregs,
diff --git a/arch/arc/kernel/kprobes.c b/arch/arc/kernel/kprobes.c
new file mode 100644
index 0000000..47e42f2
--- /dev/null
+++ b/arch/arc/kernel/kprobes.c
@@ -0,0 +1,525 @@
+/*
+ * 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.
+ */
+
+#include <linux/types.h>
+#include <linux/kprobes.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kprobes.h>
+#include <linux/kdebug.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <asm/cacheflush.h>
+#include <asm/current.h>
+#include <asm/disasm.h>
+
+#define MIN_STACK_SIZE(addr)	min((unsigned long)MAX_STACK_SIZE, \
+		(unsigned long)current_thread_info() + THREAD_SIZE - (addr))
+
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
+{
+	/* Attempt to probe at unaligned address */
+	if ((unsigned long)p->addr & 0x01)
+		return -EINVAL;
+
+	/* Address should not be in exception handling code */
+
+	p->ainsn.is_short = is_short_instr((unsigned long)p->addr);
+	p->opcode = *p->addr;
+
+	return 0;
+}
+
+void __kprobes arch_arm_kprobe(struct kprobe *p)
+{
+	*p->addr = UNIMP_S_INSTRUCTION;
+
+	flush_icache_range((unsigned long)p->addr,
+			   (unsigned long)p->addr + sizeof(kprobe_opcode_t));
+}
+
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
+{
+	*p->addr = p->opcode;
+
+	flush_icache_range((unsigned long)p->addr,
+			   (unsigned long)p->addr + sizeof(kprobe_opcode_t));
+}
+
+void __kprobes arch_remove_kprobe(struct kprobe *p)
+{
+	arch_disarm_kprobe(p);
+
+	/* Can we remove the kprobe in the middle of kprobe handling? */
+	if (p->ainsn.t1_addr) {
+		*(p->ainsn.t1_addr) = p->ainsn.t1_opcode;
+
+		flush_icache_range((unsigned long)p->ainsn.t1_addr,
+				   (unsigned long)p->ainsn.t1_addr +
+				   sizeof(kprobe_opcode_t));
+
+		p->ainsn.t1_addr = NULL;
+	}
+
+	if (p->ainsn.t2_addr) {
+		*(p->ainsn.t2_addr) = p->ainsn.t2_opcode;
+
+		flush_icache_range((unsigned long)p->ainsn.t2_addr,
+				   (unsigned long)p->ainsn.t2_addr +
+				   sizeof(kprobe_opcode_t));
+
+		p->ainsn.t2_addr = NULL;
+	}
+}
+
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
+{
+	kcb->prev_kprobe.kp = kprobe_running();
+	kcb->prev_kprobe.status = kcb->kprobe_status;
+}
+
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+{
+	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+	kcb->kprobe_status = kcb->prev_kprobe.status;
+}
+
+static inline void __kprobes set_current_kprobe(struct kprobe *p)
+{
+	__get_cpu_var(current_kprobe) = p;
+}
+
+static void __kprobes resume_execution(struct kprobe *p, unsigned long addr,
+				       struct pt_regs *regs)
+{
+	/* Remove the trap instructions inserted for single step and
+	 * restore the original instructions
+	 */
+	if (p->ainsn.t1_addr) {
+		*(p->ainsn.t1_addr) = p->ainsn.t1_opcode;
+
+		flush_icache_range((unsigned long)p->ainsn.t1_addr,
+				   (unsigned long)p->ainsn.t1_addr +
+				   sizeof(kprobe_opcode_t));
+
+		p->ainsn.t1_addr = NULL;
+	}
+
+	if (p->ainsn.t2_addr) {
+		*(p->ainsn.t2_addr) = p->ainsn.t2_opcode;
+
+		flush_icache_range((unsigned long)p->ainsn.t2_addr,
+				   (unsigned long)p->ainsn.t2_addr +
+				   sizeof(kprobe_opcode_t));
+
+		p->ainsn.t2_addr = NULL;
+	}
+
+	return;
+}
+
+static void __kprobes setup_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+	unsigned long next_pc;
+	unsigned long tgt_if_br = 0;
+	int is_branch;
+	unsigned long bta;
+
+	/* Copy the opcode back to the kprobe location and execute the
+	 * instruction. Because of this we will not be able to get into the
+	 * same kprobe until this kprobe is done
+	 */
+	*(p->addr) = p->opcode;
+
+	flush_icache_range((unsigned long)p->addr,
+			   (unsigned long)p->addr + sizeof(kprobe_opcode_t));
+
+	/* Now we insert the trap at the next location after this instruction to
+	 * single step. If it is a branch we insert the trap at possible branch
+	 * targets
+	 */
+
+	bta = regs->bta;
+
+	if (regs->status32 & 0x40) {
+		/* We are in a delay slot with the branch taken */
+
+		next_pc = bta & ~0x01;
+
+		if (!p->ainsn.is_short) {
+			if (bta & 0x01)
+				regs->blink += 2;
+			else {
+				/* Branch not taken */
+				next_pc += 2;
+
+				/* next pc is taken from bta after executing the
+				 * delay slot instruction
+				 */
+				regs->bta += 2;
+			}
+		}
+
+		is_branch = 0;
+	} else
+		is_branch =
+		    disasm_next_pc((unsigned long)p->addr, regs,
+			(struct callee_regs *) current->thread.callee_reg,
+			&next_pc, &tgt_if_br);
+
+	p->ainsn.t1_addr = (kprobe_opcode_t *) next_pc;
+	p->ainsn.t1_opcode = *(p->ainsn.t1_addr);
+	*(p->ainsn.t1_addr) = TRAP_S_2_INSTRUCTION;
+
+	flush_icache_range((unsigned long)p->ainsn.t1_addr,
+			   (unsigned long)p->ainsn.t1_addr +
+			   sizeof(kprobe_opcode_t));
+
+	if (is_branch) {
+		p->ainsn.t2_addr = (kprobe_opcode_t *) tgt_if_br;
+		p->ainsn.t2_opcode = *(p->ainsn.t2_addr);
+		*(p->ainsn.t2_addr) = TRAP_S_2_INSTRUCTION;
+
+		flush_icache_range((unsigned long)p->ainsn.t2_addr,
+				   (unsigned long)p->ainsn.t2_addr +
+				   sizeof(kprobe_opcode_t));
+	}
+}
+
+int __kprobes arc_kprobe_handler(unsigned long addr, struct pt_regs *regs)
+{
+	struct kprobe *p;
+	struct kprobe_ctlblk *kcb;
+
+	preempt_disable();
+
+	kcb = get_kprobe_ctlblk();
+	p = get_kprobe((unsigned long *)addr);
+
+	if (p) {
+		/*
+		 * We have reentered the kprobe_handler, since another kprobe
+		 * was hit while within the handler, we save the original
+		 * kprobes and single step on the instruction of the new probe
+		 * without calling any user handlers to avoid recursive
+		 * kprobes.
+		 */
+		if (kprobe_running()) {
+			save_previous_kprobe(kcb);
+			set_current_kprobe(p);
+			kprobes_inc_nmissed_count(p);
+			setup_singlestep(p, regs);
+			kcb->kprobe_status = KPROBE_REENTER;
+			return 1;
+		}
+
+		set_current_kprobe(p);
+		kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+
+		/* If we have no pre-handler or it returned 0, we continue with
+		 * normal processing. If we have a pre-handler and it returned
+		 * non-zero - which is expected from setjmp_pre_handler for
+		 * jprobe, we return without single stepping and leave that to
+		 * the break-handler which is invoked by a kprobe from
+		 * jprobe_return
+		 */
+		if (!p->pre_handler || !p->pre_handler(p, regs)) {
+			setup_singlestep(p, regs);
+			kcb->kprobe_status = KPROBE_HIT_SS;
+		}
+
+		return 1;
+	} else if (kprobe_running()) {
+		p = __get_cpu_var(current_kprobe);
+		if (p->break_handler && p->break_handler(p, regs)) {
+			setup_singlestep(p, regs);
+			kcb->kprobe_status = KPROBE_HIT_SS;
+			return 1;
+		}
+	}
+
+	/* no_kprobe: */
+	preempt_enable_no_resched();
+	return 0;
+}
+
+static int __kprobes arc_post_kprobe_handler(unsigned long addr,
+					 struct pt_regs *regs)
+{
+	struct kprobe *cur = kprobe_running();
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+	if (!cur)
+		return 0;
+
+	resume_execution(cur, addr, regs);
+
+	/* Rearm the kprobe */
+	arch_arm_kprobe(cur);
+
+	/*
+	 * When we return from trap instruction we go to the next instruction
+	 * We restored the actual instruction in resume_exectuiont and we to
+	 * return to the same address and execute it
+	 */
+	regs->ret = addr;
+
+	if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+		kcb->kprobe_status = KPROBE_HIT_SSDONE;
+		cur->post_handler(cur, regs, 0);
+	}
+
+	if (kcb->kprobe_status == KPROBE_REENTER) {
+		restore_previous_kprobe(kcb);
+		goto out;
+	}
+
+	reset_current_kprobe();
+
+out:
+	preempt_enable_no_resched();
+	return 1;
+}
+
+/*
+ * Fault can be for the instruction being single stepped or for the
+ * pre/post handlers in the module.
+ * This is applicable for applications like user probes, where we have the
+ * probe in user space and the handlers in the kernel
+ */
+
+int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned long trapnr)
+{
+	struct kprobe *cur = kprobe_running();
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+	switch (kcb->kprobe_status) {
+	case KPROBE_HIT_SS:
+	case KPROBE_REENTER:
+		/*
+		 * We are here because the instruction being single stepped
+		 * caused the fault. We reset the current kprobe and allow the
+		 * exception handler as if it is regular exception. In our
+		 * case it doesn't matter because the system will be halted
+		 */
+		resume_execution(cur, (unsigned long)cur->addr, regs);
+
+		if (kcb->kprobe_status == KPROBE_REENTER)
+			restore_previous_kprobe(kcb);
+		else
+			reset_current_kprobe();
+
+		preempt_enable_no_resched();
+		break;
+
+	case KPROBE_HIT_ACTIVE:
+	case KPROBE_HIT_SSDONE:
+		/*
+		 * We are here because the instructions in the pre/post handler
+		 * caused the fault.
+		 */
+
+		/* We increment the nmissed count for accounting,
+		 * we can also use npre/npostfault count for accouting
+		 * these specific fault cases.
+		 */
+		kprobes_inc_nmissed_count(cur);
+
+		/*
+		 * We come here because instructions in the pre/post
+		 * handler caused the page_fault, this could happen
+		 * if handler tries to access user space by
+		 * copy_from_user(), get_user() etc. Let the
+		 * user-specified handler try to fix it first.
+		 */
+		if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
+			return 1;
+
+		/*
+		 * In case the user-specified fault handler returned zero,
+		 * try to fix up.
+		 */
+		if (fixup_exception(regs))
+			return 1;
+
+		/*
+		 * fixup_exception() could not handle it,
+		 * Let do_page_fault() fix it.
+		 */
+		break;
+
+	default:
+		break;
+	}
+	return 0;
+}
+
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+				       unsigned long val, void *data)
+{
+	struct die_args *args = data;
+	unsigned long addr = args->err;
+	int ret = NOTIFY_DONE;
+
+	switch (val) {
+	case DIE_IERR:
+		if (arc_kprobe_handler(addr, args->regs))
+			return NOTIFY_STOP;
+		break;
+
+	case DIE_TRAP:
+		if (arc_post_kprobe_handler(addr, args->regs))
+			return NOTIFY_STOP;
+		break;
+
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	struct jprobe *jp = container_of(p, struct jprobe, kp);
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+	unsigned long sp_addr = regs->sp;
+
+	kcb->jprobe_saved_regs = *regs;
+	memcpy(kcb->jprobes_stack, (void *)sp_addr, MIN_STACK_SIZE(sp_addr));
+	regs->ret = (unsigned long)(jp->entry);
+
+	return 1;
+}
+
+void __kprobes jprobe_return(void)
+{
+	__asm__ __volatile__("unimp_s");
+	return;
+}
+
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+	unsigned long sp_addr;
+
+	*regs = kcb->jprobe_saved_regs;
+	sp_addr = regs->sp;
+	memcpy((void *)sp_addr, kcb->jprobes_stack, MIN_STACK_SIZE(sp_addr));
+	preempt_enable_no_resched();
+
+	return 1;
+}
+
+static void __used kretprobe_trampoline_holder(void)
+{
+	__asm__ __volatile__(".global kretprobe_trampoline\n"
+			     "kretprobe_trampoline:\n" "nop\n");
+}
+
+void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
+				      struct pt_regs *regs)
+{
+
+	ri->ret_addr = (kprobe_opcode_t *) regs->blink;
+
+	/* Replace the return addr with trampoline addr */
+	regs->blink = (unsigned long)&kretprobe_trampoline;
+}
+
+static int __kprobes trampoline_probe_handler(struct kprobe *p,
+					      struct pt_regs *regs)
+{
+	struct kretprobe_instance *ri = NULL;
+	struct hlist_head *head, empty_rp;
+	struct hlist_node *node, *tmp;
+	unsigned long flags, orig_ret_address = 0;
+	unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
+
+	INIT_HLIST_HEAD(&empty_rp);
+	kretprobe_hash_lock(current, &head, &flags);
+
+	/*
+	 * It is possible to have multiple instances associated with a given
+	 * task either because an multiple functions in the call path
+	 * have a return probe installed on them, and/or more than one return
+	 * return probe was registered for a target function.
+	 *
+	 * We can handle this because:
+	 *     - instances are always inserted at the head of the list
+	 *     - when multiple return probes are registered for the same
+	 *       function, the first instance's ret_addr will point to the
+	 *       real return address, and all the rest will point to
+	 *       kretprobe_trampoline
+	 */
+	hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
+		if (ri->task != current)
+			/* another task is sharing our hash bucket */
+			continue;
+
+		if (ri->rp && ri->rp->handler)
+			ri->rp->handler(ri, regs);
+
+		orig_ret_address = (unsigned long)ri->ret_addr;
+		recycle_rp_inst(ri, &empty_rp);
+
+		if (orig_ret_address != trampoline_address) {
+			/*
+			 * This is the real return address. Any other
+			 * instances associated with this task are for
+			 * other calls deeper on the call stack
+			 */
+			break;
+		}
+	}
+
+	kretprobe_assert(ri, orig_ret_address, trampoline_address);
+	regs->ret = orig_ret_address;
+
+	reset_current_kprobe();
+	kretprobe_hash_unlock(current, &flags);
+	preempt_enable_no_resched();
+
+	hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
+		hlist_del(&ri->hlist);
+		kfree(ri);
+	}
+
+	/* By returning a non zero value, we are telling the kprobe handler
+	 * that we don't want the post_handler to run
+	 */
+	return 1;
+}
+
+static struct kprobe trampoline_p = {
+	.addr = (kprobe_opcode_t *) &kretprobe_trampoline,
+	.pre_handler = trampoline_probe_handler
+};
+
+int __init arch_init_kprobes(void)
+{
+	/* Registering the trampoline code for the kret probe */
+	return register_kprobe(&trampoline_p);
+}
+
+int __kprobes arch_trampoline_kprobe(struct kprobe *p)
+{
+	if (p->addr == (kprobe_opcode_t *) &kretprobe_trampoline)
+		return 1;
+
+	return 0;
+}
+
+void trap_is_kprobe(unsigned long cause, unsigned long address,
+		    struct pt_regs *regs)
+{
+	notify_die(DIE_TRAP, "kprobe_trap", regs, address, cause, SIGTRAP);
+}
diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c
index fd2457c..c6396b4 100644
--- a/arch/arc/kernel/traps.c
+++ b/arch/arc/kernel/traps.c
@@ -15,6 +15,7 @@
 #include <linux/uaccess.h>
 #include <asm/ptrace.h>
 #include <asm/setup.h>
+#include <asm/kprobes.h>
 
 void __init trap_init(void)
 {
@@ -90,6 +91,7 @@ void do_machine_check_fault(unsigned long cause, unsigned long address,
 	die("Machine Check Exception", regs, address, cause);
 }
 
+
 /*
  * Entry point for traps induced by ARCompact TRAP_S <n> insn
  * This is same family as TRAP0/SWI insn (use the same vector).
@@ -109,6 +111,10 @@ void do_non_swi_trap(unsigned long cause, unsigned long address,
 		trap_is_brkpt(cause, address, regs);
 		break;
 
+	case 2:
+		trap_is_kprobe(param, address, regs);
+		break;
+
 	default:
 		break;
 	}
@@ -116,10 +122,17 @@ void do_non_swi_trap(unsigned long cause, unsigned long address,
 
 /*
  * Entry point for Instruction Error Exception
+ *  -For a corner case, ARC kprobes implementation resorts to using
+ *   this exception, hence the check
  */
 void do_insterror_or_kprobe(unsigned long cause,
 				       unsigned long address,
 				       struct pt_regs *regs)
 {
+	/* Check if this exception is caused by kprobes */
+	if (notify_die(DIE_IERR, "kprobe_ierr", regs, address,
+		       cause, SIGILL) == NOTIFY_STOP)
+		return;
+
 	insterror_is_error(cause, address, regs);
 }
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 57/71] ARC: Hostlink Pseudo-Driver for Metaware Debugger
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (18 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 48/71] ARC: kprobes support Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 58/71] ARC: UAPI Disintegrate arch/arc/include/asm Vineet Gupta
                   ` (5 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta

This allows ARC Target to do I/O to host in absence of any peripherals
whatsoever, assisted by Metaware Hostlink facility.

Further we have a FUSE based filesystem which makes us mount/access host
filesystem on target and do fops.

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/Kconfig               |    9 ++++++
 arch/arc/kernel/Makefile       |    1 +
 arch/arc/kernel/arc_hostlink.c |   58 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 68 insertions(+), 0 deletions(-)
 create mode 100644 arch/arc/kernel/arc_hostlink.c

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 2611a60..cd4ad61 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -389,6 +389,15 @@ config HZ
 	int "Timer Frequency"
 	default 100
 
+config ARC_METAWARE_HLINK
+	bool "Support for Metaware debugger assisted Host access"
+	default n
+	help
+	  This options allows a Linux userland apps to directly access
+	  host file system (open/creat/read/write etc) with help from
+	  Metaware Debugger. This can come in handy for Linux-host communication
+	  when there is no real usable peripheral such as EMAC.
+
 menuconfig ARC_DBG
 	bool "ARC debugging"
 	default y
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
index 44975b6..b5cd328 100644
--- a/arch/arc/kernel/Makefile
+++ b/arch/arc/kernel/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_ARC_DW2_UNWIND)		+= unwind.o
 obj-$(CONFIG_KPROBES)      		+= kprobes.o
 obj-$(CONFIG_ARC_MISALIGN_ACCESS) 	+= unaligned.o
 obj-$(CONFIG_KGDB)			+= kgdb.o
+obj-$(CONFIG_ARC_METAWARE_HLINK)	+= arc_hostlink.o
 
 obj-$(CONFIG_ARC_FPU_SAVE_RESTORE)	+= fpu.o
 CFLAGS_fpu.o   += -mdpfp
diff --git a/arch/arc/kernel/arc_hostlink.c b/arch/arc/kernel/arc_hostlink.c
new file mode 100644
index 0000000..47b2a17
--- /dev/null
+++ b/arch/arc/kernel/arc_hostlink.c
@@ -0,0 +1,58 @@
+/*
+ * arc_hostlink.c: Pseudo-driver for Metaware provided "hostlink" facility
+ *
+ * Allows Linux userland access to host in absence of any peripherals.
+ *
+ * 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.
+ */
+
+#include <linux/fs.h>		/* file_operations */
+#include <linux/miscdevice.h>
+#include <linux/mm.h>		/* VM_IO */
+#include <linux/module.h>
+#include <linux/uaccess.h>
+
+static unsigned char __HOSTLINK__[4 * PAGE_SIZE] __aligned(PAGE_SIZE);
+
+static int arc_hl_mmap(struct file *fp, struct vm_area_struct *vma)
+{
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+			       vma->vm_end - vma->vm_start,
+			       vma->vm_page_prot)) {
+		pr_warn("Hostlink buffer mmap ERROR\n");
+		return -EAGAIN;
+	}
+	return 0;
+}
+
+static long arc_hl_ioctl(struct file *file, unsigned int cmd,
+			unsigned long arg)
+{
+	/* we only support, returning the physical addr to mmap in user space */
+	put_user((unsigned int)__HOSTLINK__, (int __user *)arg);
+	return 0;
+}
+
+static const struct file_operations arc_hl_fops = {
+	.unlocked_ioctl	= arc_hl_ioctl,
+	.mmap		= arc_hl_mmap,
+};
+
+static struct miscdevice arc_hl_dev = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "hostlink",
+	.fops	= &arc_hl_fops
+};
+
+static int __init arc_hl_init(void)
+{
+	pr_info("ARC Hostlink driver mmap at 0x%p\n", __HOSTLINK__);
+	return misc_register(&arc_hl_dev);
+}
+module_init(arc_hl_init);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 58/71] ARC: UAPI Disintegrate arch/arc/include/asm
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (19 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 57/71] ARC: Hostlink Pseudo-Driver for Metaware Debugger Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-28  7:36   ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 59/71] ARC: Add support for ioremap_prot API Vineet Gupta
                   ` (4 subsequent siblings)
  25 siblings, 1 reply; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta, David Howells

1. ./genfilelist.pl arch/arc/include/asm/

2. Create arch/arc/include/uapi/asm/Kbuild as follows

	+# UAPI Header export list
	+include include/uapi/asm-generic/Kbuild.asm

3. ./disintegrate-one.pl arch/arc/include/{,uapi/}asm/<above-list>

4. Edit arch/arc/include/asm/Kbuild to remove ref to
	asm-generic/Kbuild.asm

To work around empty uapi/asm/setup.h added a placholder comment.

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: David Howells <dhowells@redhat.com>
---
 arch/arc/include/asm/Kbuild            |    8 ---
 arch/arc/include/asm/byteorder.h       |   18 ------
 arch/arc/include/asm/cachectl.h        |   28 ---------
 arch/arc/include/asm/page.h            |   30 +---------
 arch/arc/include/asm/ptrace.h          |   37 +-----------
 arch/arc/include/asm/setup.h           |    3 +-
 arch/arc/include/asm/sigcontext.h      |   23 --------
 arch/arc/include/asm/signal.h          |   27 ---------
 arch/arc/include/asm/swab.h            |   98 --------------------------------
 arch/arc/include/asm/unistd.h          |   34 -----------
 arch/arc/include/uapi/asm/Kbuild       |   11 ++++
 arch/arc/include/uapi/asm/byteorder.h  |   18 ++++++
 arch/arc/include/uapi/asm/cachectl.h   |   28 +++++++++
 arch/arc/include/uapi/asm/page.h       |   39 +++++++++++++
 arch/arc/include/uapi/asm/ptrace.h     |   46 +++++++++++++++
 arch/arc/include/uapi/asm/setup.h      |    6 ++
 arch/arc/include/uapi/asm/sigcontext.h |   23 ++++++++
 arch/arc/include/uapi/asm/signal.h     |   27 +++++++++
 arch/arc/include/uapi/asm/swab.h       |   98 ++++++++++++++++++++++++++++++++
 arch/arc/include/uapi/asm/unistd.h     |   34 +++++++++++
 20 files changed, 335 insertions(+), 301 deletions(-)
 delete mode 100644 arch/arc/include/asm/byteorder.h
 delete mode 100644 arch/arc/include/asm/cachectl.h
 delete mode 100644 arch/arc/include/asm/sigcontext.h
 delete mode 100644 arch/arc/include/asm/signal.h
 delete mode 100644 arch/arc/include/asm/swab.h
 delete mode 100644 arch/arc/include/asm/unistd.h
 create mode 100644 arch/arc/include/uapi/asm/Kbuild
 create mode 100644 arch/arc/include/uapi/asm/byteorder.h
 create mode 100644 arch/arc/include/uapi/asm/cachectl.h
 create mode 100644 arch/arc/include/uapi/asm/page.h
 create mode 100644 arch/arc/include/uapi/asm/ptrace.h
 create mode 100644 arch/arc/include/uapi/asm/setup.h
 create mode 100644 arch/arc/include/uapi/asm/sigcontext.h
 create mode 100644 arch/arc/include/uapi/asm/signal.h
 create mode 100644 arch/arc/include/uapi/asm/swab.h
 create mode 100644 arch/arc/include/uapi/asm/unistd.h

diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index b24089c..48af742 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -1,11 +1,3 @@
-include include/asm-generic/Kbuild.asm
-
-# 7-Oct-12: Jeremy Bennett <jeremy.bennett@embecosm.com>. Some of these
-# headers, beyond those specified in the generic set are needed by user code.
-
-header-y += page.h
-header-y += cachectl.h
-
 generic-y += auxvec.h
 generic-y += bugs.h
 generic-y += bitsperlong.h
diff --git a/arch/arc/include/asm/byteorder.h b/arch/arc/include/asm/byteorder.h
deleted file mode 100644
index 9da71d4..0000000
--- a/arch/arc/include/asm/byteorder.h
+++ /dev/null
@@ -1,18 +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_ARC_BYTEORDER_H
-#define __ASM_ARC_BYTEORDER_H
-
-#ifdef CONFIG_CPU_BIG_ENDIAN
-#include <linux/byteorder/big_endian.h>
-#else
-#include <linux/byteorder/little_endian.h>
-#endif
-
-#endif /* ASM_ARC_BYTEORDER_H */
diff --git a/arch/arc/include/asm/cachectl.h b/arch/arc/include/asm/cachectl.h
deleted file mode 100644
index 51c73f0..0000000
--- a/arch/arc/include/asm/cachectl.h
+++ /dev/null
@@ -1,28 +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 __ARC_ASM_CACHECTL_H
-#define __ARC_ASM_CACHECTL_H
-
-/*
- * ARC ABI flags defined for Android's finegrained cacheflush requirements
- */
-#define CF_I_INV	0x0002
-#define CF_D_FLUSH	0x0010
-#define CF_D_FLUSH_INV	0x0020
-
-#define CF_DEFAULT	(CF_I_INV | CF_D_FLUSH)
-
-/*
- * Standard flags expected by cacheflush system call users
- */
-#define ICACHE	CF_I_INV
-#define DCACHE	CF_D_FLUSH
-#define BCACHE	(CF_I_INV | CF_D_FLUSH)
-
-#endif
diff --git a/arch/arc/include/asm/page.h b/arch/arc/include/asm/page.h
index d111d0c..dfe1f8a 100644
--- a/arch/arc/include/asm/page.h
+++ b/arch/arc/include/asm/page.h
@@ -5,37 +5,11 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
 #ifndef __ASM_ARC_PAGE_H
 #define __ASM_ARC_PAGE_H
 
-/* PAGE_SHIFT determines the page size */
-#if defined(CONFIG_ARC_PAGE_SIZE_16K)
-#define PAGE_SHIFT 14
-#elif defined(CONFIG_ARC_PAGE_SIZE_4K)
-#define PAGE_SHIFT 12
-#else
-/*
- * Default 8k
- * done this way (instead of under CONFIG_ARC_PAGE_SIZE_8K) because adhoc
- * user code (busybox appletlib.h) expects PAGE_SHIFT to be defined w/o
- * using the correct uClibc header and in their build our autoconf.h is
- * not available
- */
-#define PAGE_SHIFT 13
-#endif
-
-#ifdef __ASSEMBLY__
-#define PAGE_SIZE	(1 << PAGE_SHIFT)
-#define PAGE_OFFSET	(0x80000000)
-#else
-#define PAGE_SIZE	(1UL << PAGE_SHIFT)	/* Default 8K */
-#define PAGE_OFFSET	(0x80000000UL)	/* Kernel starts at 2G onwards */
-#endif
+#include <uapi/asm/page.h>
 
-#define PAGE_MASK	(~(PAGE_SIZE-1))
-
-#ifdef __KERNEL__
 
 #ifndef __ASSEMBLY__
 
@@ -129,6 +103,4 @@ typedef unsigned long pgtable_t;
 
 #endif /* !__ASSEMBLY__ */
 
-#endif /* __KERNEL__ */
-
 #endif
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
index 6ab65fa..95e633e 100644
--- a/arch/arc/include/asm/ptrace.h
+++ b/arch/arc/include/asm/ptrace.h
@@ -7,42 +7,11 @@
  *
  * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
  */
-
 #ifndef __ASM_ARC_PTRACE_H
 #define __ASM_ARC_PTRACE_H
 
-/*
- * XXX: ABI hack.
- * The offset calc can be cleanly done in asm-offset.c, however gdb includes
- * this header directly.
- */
-#define PT_bta		4
-#define PT_lp_start	8
-#define PT_lp_end	12
-#define PT_lp_count	16
-#define PT_status32	20
-#define PT_ret		24
-#define PT_blink	28
-#define PT_fp		32
-#define PT_r26		36
-#define PT_r12		40
-#define PT_r11		44
-#define PT_r10		48
-#define PT_r9		52
-#define PT_r8		56
-#define PT_r7		60
-#define PT_r6		64
-#define PT_r5		68
-#define PT_r4		72
-#define PT_r3		76
-#define PT_r2		80
-#define PT_r1		84
-#define PT_r0		88
-#define PT_sp		92
-#define PT_orig_r0	96
-#define PT_orig_r8	100
-
-#ifdef __KERNEL__
+#include <uapi/asm/ptrace.h>
+
 
 #ifndef __ASSEMBLY__
 
@@ -163,6 +132,4 @@ static inline long regs_return_value(struct pt_regs *regs)
 #define orig_r8_IS_IRQ1			0x0010
 #define orig_r8_IS_IRQ2			0x0020
 
-#endif /* __KERNEL__ */
-
 #endif /* __ASM_PTRACE_H */
diff --git a/arch/arc/include/asm/setup.h b/arch/arc/include/asm/setup.h
index fc97411..229e506 100644
--- a/arch/arc/include/asm/setup.h
+++ b/arch/arc/include/asm/setup.h
@@ -5,11 +5,12 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
 #ifndef __ASMARC_SETUP_H
 #define __ASMARC_SETUP_H
 
+
 #include <linux/types.h>
+#include <uapi/asm/setup.h>
 
 #define COMMAND_LINE_SIZE 256
 
diff --git a/arch/arc/include/asm/sigcontext.h b/arch/arc/include/asm/sigcontext.h
deleted file mode 100644
index f21b541..0000000
--- a/arch/arc/include/asm/sigcontext.h
+++ /dev/null
@@ -1,23 +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_ARC_SIGCONTEXT_H
-#define _ASM_ARC_SIGCONTEXT_H
-
-#include <asm/ptrace.h>
-
-/*
- * Signal context structure - contains all info to do with the state
- * before the signal handler was invoked.  Note: only add new entries
- * to the end of the structure.
- */
-struct sigcontext {
-	struct pt_regs regs;
-};
-
-#endif /* _ASM_ARC_SIGCONTEXT_H */
diff --git a/arch/arc/include/asm/signal.h b/arch/arc/include/asm/signal.h
deleted file mode 100644
index fad62f7..0000000
--- a/arch/arc/include/asm/signal.h
+++ /dev/null
@@ -1,27 +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.
- *
- * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
- */
-
-#ifndef _ASM_ARC_SIGNAL_H
-#define _ASM_ARC_SIGNAL_H
-
-/*
- * This is much needed for ARC sigreturn optimization.
- * This allows uClibc to piggback the addr of a sigreturn stub in sigaction,
- * which allows sigreturn based re-entry into kernel after handling signal.
- * W/o this kernel needs to "synthesize" the sigreturn trampoline on user
- * mode stack which in turn forces the following:
- * -TLB Flush (after making the stack page executable)
- * -Cache line Flush (to make I/D Cache lines coherent)
- */
-#define SA_RESTORER	0x04000000
-
-#include <asm-generic/signal.h>
-
-#endif /* _ASM_ARC_SIGNAL_H */
diff --git a/arch/arc/include/asm/swab.h b/arch/arc/include/asm/swab.h
deleted file mode 100644
index 095599a..0000000
--- a/arch/arc/include/asm/swab.h
+++ /dev/null
@@ -1,98 +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.
- *
- * vineetg: May 2011
- *  -Support single cycle endian-swap insn in ARC700 4.10
- *
- * vineetg: June 2009
- *  -Better htonl implementation (5 instead of 9 ALU instructions)
- *  -Hardware assisted single cycle bswap (Use Case of ARC custom instrn)
- */
-
-#ifndef __ASM_ARC_SWAB_H
-#define __ASM_ARC_SWAB_H
-
-#include <linux/types.h>
-
-/* Native single cycle endian swap insn */
-#ifdef CONFIG_ARC_HAS_SWAPE
-
-#define __arch_swab32(x)		\
-({					\
-	unsigned int tmp = x;		\
-	__asm__(			\
-	"	swape	%0, %1	\n"	\
-	: "=r" (tmp)			\
-	: "r" (tmp));			\
-	tmp;				\
-})
-
-#else
-
-/* Several ways of Endian-Swap Emulation for ARC
- * 0: kernel generic
- * 1: ARC optimised "C"
- * 2: ARC Custom instruction
- */
-#define ARC_BSWAP_TYPE	1
-
-#if (ARC_BSWAP_TYPE == 1)		/******* Software only ********/
-
-/* The kernel default implementation of htonl is
- *		return  x<<24 | x>>24 |
- *		 (x & (__u32)0x0000ff00UL)<<8 | (x & (__u32)0x00ff0000UL)>>8;
- *
- * This generates 9 instructions on ARC (excluding the ld/st)
- *
- * 8051fd8c:	ld     r3,[r7,20]	; Mem op : Get the value to be swapped
- * 8051fd98:	asl    r5,r3,24		; get  3rd Byte
- * 8051fd9c:	lsr    r2,r3,24		; get  0th Byte
- * 8051fda0:	and    r4,r3,0xff00
- * 8051fda8:	asl    r4,r4,8		; get 1st Byte
- * 8051fdac:	and    r3,r3,0x00ff0000
- * 8051fdb4:	or     r2,r2,r5		; combine 0th and 3rd Bytes
- * 8051fdb8:	lsr    r3,r3,8		; 2nd Byte at correct place in Dst Reg
- * 8051fdbc:	or     r2,r2,r4		; combine 0,3 Bytes with 1st Byte
- * 8051fdc0:	or     r2,r2,r3		; combine 0,3,1 Bytes with 2nd Byte
- * 8051fdc4:	st     r2,[r1,20]	; Mem op : save result back to mem
- *
- * Joern suggested a better "C" algorithm which is great since
- * (1) It is portable to any architecure
- * (2) At the same time it takes advantage of ARC ISA (rotate intrns)
- */
-
-#define __arch_swab32(x)					\
-({	unsigned long __in = (x), __tmp;			\
-	__tmp = __in << 8 | __in >> 24; /* ror tmp,in,24 */	\
-	__in = __in << 24 | __in >> 8; /* ror in,in,8 */	\
-	__tmp ^= __in;						\
-	__tmp &= 0xff00ff;					\
-	__tmp ^ __in;						\
-})
-
-#elif (ARC_BSWAP_TYPE == 2)	/* Custom single cycle bwap instruction */
-
-#define __arch_swab32(x)						\
-({									\
-	unsigned int tmp = x;						\
-	__asm__(							\
-	"	.extInstruction	bswap, 7, 0x00, SUFFIX_NONE, SYNTAX_2OP	\n"\
-	"	bswap  %0, %1						\n"\
-	: "=r" (tmp)							\
-	: "r" (tmp));							\
-	tmp;								\
-})
-
-#endif /* ARC_BSWAP_TYPE=zzz */
-
-#endif /* CONFIG_ARC_HAS_SWAPE */
-
-#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-#define __SWAB_64_THRU_32__
-#endif
-
-#endif
diff --git a/arch/arc/include/asm/unistd.h b/arch/arc/include/asm/unistd.h
deleted file mode 100644
index 6f30484..0000000
--- a/arch/arc/include/asm/unistd.h
+++ /dev/null
@@ -1,34 +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.
- */
-
-/******** no-legacy-syscalls-ABI *******/
-
-#define __ARCH_WANT_SYS_EXECVE
-#define __ARCH_WANT_SYS_CLONE
-#define __ARCH_WANT_SYS_VFORK
-#define __ARCH_WANT_SYS_FORK
-
-#define sys_mmap2 sys_mmap_pgoff
-
-#include <asm-generic/unistd.h>
-
-#define NR_syscalls	__NR_syscalls
-
-/* ARC specific syscall */
-#define __NR_cacheflush		(__NR_arch_specific_syscall + 0)
-#define __NR_arc_settls		(__NR_arch_specific_syscall + 1)
-#define __NR_arc_gettls		(__NR_arch_specific_syscall + 2)
-
-__SYSCALL(__NR_cacheflush, sys_cacheflush)
-__SYSCALL(__NR_arc_settls, sys_arc_settls)
-__SYSCALL(__NR_arc_gettls, sys_arc_gettls)
-
-
-/* Generic syscall (fs/filesystems.c - lost in asm-generic/unistd.h */
-#define __NR_sysfs		(__NR_arch_specific_syscall + 3)
-__SYSCALL(__NR_sysfs, sys_sysfs)
diff --git a/arch/arc/include/uapi/asm/Kbuild b/arch/arc/include/uapi/asm/Kbuild
new file mode 100644
index 0000000..2736244
--- /dev/null
+++ b/arch/arc/include/uapi/asm/Kbuild
@@ -0,0 +1,11 @@
+# UAPI Header export list
+include include/uapi/asm-generic/Kbuild.asm
+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/byteorder.h b/arch/arc/include/uapi/asm/byteorder.h
new file mode 100644
index 0000000..9da71d4
--- /dev/null
+++ b/arch/arc/include/uapi/asm/byteorder.h
@@ -0,0 +1,18 @@
+/*
+ * 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_ARC_BYTEORDER_H
+#define __ASM_ARC_BYTEORDER_H
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#include <linux/byteorder/big_endian.h>
+#else
+#include <linux/byteorder/little_endian.h>
+#endif
+
+#endif /* ASM_ARC_BYTEORDER_H */
diff --git a/arch/arc/include/uapi/asm/cachectl.h b/arch/arc/include/uapi/asm/cachectl.h
new file mode 100644
index 0000000..51c73f0
--- /dev/null
+++ b/arch/arc/include/uapi/asm/cachectl.h
@@ -0,0 +1,28 @@
+/*
+ * 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 __ARC_ASM_CACHECTL_H
+#define __ARC_ASM_CACHECTL_H
+
+/*
+ * ARC ABI flags defined for Android's finegrained cacheflush requirements
+ */
+#define CF_I_INV	0x0002
+#define CF_D_FLUSH	0x0010
+#define CF_D_FLUSH_INV	0x0020
+
+#define CF_DEFAULT	(CF_I_INV | CF_D_FLUSH)
+
+/*
+ * Standard flags expected by cacheflush system call users
+ */
+#define ICACHE	CF_I_INV
+#define DCACHE	CF_D_FLUSH
+#define BCACHE	(CF_I_INV | CF_D_FLUSH)
+
+#endif
diff --git a/arch/arc/include/uapi/asm/page.h b/arch/arc/include/uapi/asm/page.h
new file mode 100644
index 0000000..e5d41e0
--- /dev/null
+++ b/arch/arc/include/uapi/asm/page.h
@@ -0,0 +1,39 @@
+/*
+ * 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 _UAPI__ASM_ARC_PAGE_H
+#define _UAPI__ASM_ARC_PAGE_H
+
+/* PAGE_SHIFT determines the page size */
+#if defined(CONFIG_ARC_PAGE_SIZE_16K)
+#define PAGE_SHIFT 14
+#elif defined(CONFIG_ARC_PAGE_SIZE_4K)
+#define PAGE_SHIFT 12
+#else
+/*
+ * Default 8k
+ * done this way (instead of under CONFIG_ARC_PAGE_SIZE_8K) because adhoc
+ * user code (busybox appletlib.h) expects PAGE_SHIFT to be defined w/o
+ * using the correct uClibc header and in their build our autoconf.h is
+ * not available
+ */
+#define PAGE_SHIFT 13
+#endif
+
+#ifdef __ASSEMBLY__
+#define PAGE_SIZE	(1 << PAGE_SHIFT)
+#define PAGE_OFFSET	(0x80000000)
+#else
+#define PAGE_SIZE	(1UL << PAGE_SHIFT)	/* Default 8K */
+#define PAGE_OFFSET	(0x80000000UL)	/* Kernel starts at 2G onwards */
+#endif
+
+#define PAGE_MASK	(~(PAGE_SIZE-1))
+
+
+#endif /* _UAPI__ASM_ARC_PAGE_H */
diff --git a/arch/arc/include/uapi/asm/ptrace.h b/arch/arc/include/uapi/asm/ptrace.h
new file mode 100644
index 0000000..bccf4ab
--- /dev/null
+++ b/arch/arc/include/uapi/asm/ptrace.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ *
+ * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
+ */
+
+#ifndef _UAPI__ASM_ARC_PTRACE_H
+#define _UAPI__ASM_ARC_PTRACE_H
+
+/*
+ * XXX: ABI hack.
+ * The offset calc can be cleanly done in asm-offset.c, however gdb includes
+ * this header directly.
+ */
+#define PT_bta		4
+#define PT_lp_start	8
+#define PT_lp_end	12
+#define PT_lp_count	16
+#define PT_status32	20
+#define PT_ret		24
+#define PT_blink	28
+#define PT_fp		32
+#define PT_r26		36
+#define PT_r12		40
+#define PT_r11		44
+#define PT_r10		48
+#define PT_r9		52
+#define PT_r8		56
+#define PT_r7		60
+#define PT_r6		64
+#define PT_r5		68
+#define PT_r4		72
+#define PT_r3		76
+#define PT_r2		80
+#define PT_r1		84
+#define PT_r0		88
+#define PT_sp		92
+#define PT_orig_r0	96
+#define PT_orig_r8	100
+
+
+#endif /* _UAPI__ASM_ARC_PTRACE_H */
diff --git a/arch/arc/include/uapi/asm/setup.h b/arch/arc/include/uapi/asm/setup.h
new file mode 100644
index 0000000..a6d4e44
--- /dev/null
+++ b/arch/arc/include/uapi/asm/setup.h
@@ -0,0 +1,6 @@
+/*
+ * setup.h is part of userspace header ABI so UAPI scripts have to generate it
+ * even if there's nothing to export - causing empty <uapi/asm/setup.h>
+ * However to prevent "patch" from discarding it we add this placeholder
+ * comment
+ */
diff --git a/arch/arc/include/uapi/asm/sigcontext.h b/arch/arc/include/uapi/asm/sigcontext.h
new file mode 100644
index 0000000..f21b541
--- /dev/null
+++ b/arch/arc/include/uapi/asm/sigcontext.h
@@ -0,0 +1,23 @@
+/*
+ * 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_ARC_SIGCONTEXT_H
+#define _ASM_ARC_SIGCONTEXT_H
+
+#include <asm/ptrace.h>
+
+/*
+ * Signal context structure - contains all info to do with the state
+ * before the signal handler was invoked.  Note: only add new entries
+ * to the end of the structure.
+ */
+struct sigcontext {
+	struct pt_regs regs;
+};
+
+#endif /* _ASM_ARC_SIGCONTEXT_H */
diff --git a/arch/arc/include/uapi/asm/signal.h b/arch/arc/include/uapi/asm/signal.h
new file mode 100644
index 0000000..fad62f7
--- /dev/null
+++ b/arch/arc/include/uapi/asm/signal.h
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ *
+ * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
+ */
+
+#ifndef _ASM_ARC_SIGNAL_H
+#define _ASM_ARC_SIGNAL_H
+
+/*
+ * This is much needed for ARC sigreturn optimization.
+ * This allows uClibc to piggback the addr of a sigreturn stub in sigaction,
+ * which allows sigreturn based re-entry into kernel after handling signal.
+ * W/o this kernel needs to "synthesize" the sigreturn trampoline on user
+ * mode stack which in turn forces the following:
+ * -TLB Flush (after making the stack page executable)
+ * -Cache line Flush (to make I/D Cache lines coherent)
+ */
+#define SA_RESTORER	0x04000000
+
+#include <asm-generic/signal.h>
+
+#endif /* _ASM_ARC_SIGNAL_H */
diff --git a/arch/arc/include/uapi/asm/swab.h b/arch/arc/include/uapi/asm/swab.h
new file mode 100644
index 0000000..095599a
--- /dev/null
+++ b/arch/arc/include/uapi/asm/swab.h
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ *
+ * vineetg: May 2011
+ *  -Support single cycle endian-swap insn in ARC700 4.10
+ *
+ * vineetg: June 2009
+ *  -Better htonl implementation (5 instead of 9 ALU instructions)
+ *  -Hardware assisted single cycle bswap (Use Case of ARC custom instrn)
+ */
+
+#ifndef __ASM_ARC_SWAB_H
+#define __ASM_ARC_SWAB_H
+
+#include <linux/types.h>
+
+/* Native single cycle endian swap insn */
+#ifdef CONFIG_ARC_HAS_SWAPE
+
+#define __arch_swab32(x)		\
+({					\
+	unsigned int tmp = x;		\
+	__asm__(			\
+	"	swape	%0, %1	\n"	\
+	: "=r" (tmp)			\
+	: "r" (tmp));			\
+	tmp;				\
+})
+
+#else
+
+/* Several ways of Endian-Swap Emulation for ARC
+ * 0: kernel generic
+ * 1: ARC optimised "C"
+ * 2: ARC Custom instruction
+ */
+#define ARC_BSWAP_TYPE	1
+
+#if (ARC_BSWAP_TYPE == 1)		/******* Software only ********/
+
+/* The kernel default implementation of htonl is
+ *		return  x<<24 | x>>24 |
+ *		 (x & (__u32)0x0000ff00UL)<<8 | (x & (__u32)0x00ff0000UL)>>8;
+ *
+ * This generates 9 instructions on ARC (excluding the ld/st)
+ *
+ * 8051fd8c:	ld     r3,[r7,20]	; Mem op : Get the value to be swapped
+ * 8051fd98:	asl    r5,r3,24		; get  3rd Byte
+ * 8051fd9c:	lsr    r2,r3,24		; get  0th Byte
+ * 8051fda0:	and    r4,r3,0xff00
+ * 8051fda8:	asl    r4,r4,8		; get 1st Byte
+ * 8051fdac:	and    r3,r3,0x00ff0000
+ * 8051fdb4:	or     r2,r2,r5		; combine 0th and 3rd Bytes
+ * 8051fdb8:	lsr    r3,r3,8		; 2nd Byte at correct place in Dst Reg
+ * 8051fdbc:	or     r2,r2,r4		; combine 0,3 Bytes with 1st Byte
+ * 8051fdc0:	or     r2,r2,r3		; combine 0,3,1 Bytes with 2nd Byte
+ * 8051fdc4:	st     r2,[r1,20]	; Mem op : save result back to mem
+ *
+ * Joern suggested a better "C" algorithm which is great since
+ * (1) It is portable to any architecure
+ * (2) At the same time it takes advantage of ARC ISA (rotate intrns)
+ */
+
+#define __arch_swab32(x)					\
+({	unsigned long __in = (x), __tmp;			\
+	__tmp = __in << 8 | __in >> 24; /* ror tmp,in,24 */	\
+	__in = __in << 24 | __in >> 8; /* ror in,in,8 */	\
+	__tmp ^= __in;						\
+	__tmp &= 0xff00ff;					\
+	__tmp ^ __in;						\
+})
+
+#elif (ARC_BSWAP_TYPE == 2)	/* Custom single cycle bwap instruction */
+
+#define __arch_swab32(x)						\
+({									\
+	unsigned int tmp = x;						\
+	__asm__(							\
+	"	.extInstruction	bswap, 7, 0x00, SUFFIX_NONE, SYNTAX_2OP	\n"\
+	"	bswap  %0, %1						\n"\
+	: "=r" (tmp)							\
+	: "r" (tmp));							\
+	tmp;								\
+})
+
+#endif /* ARC_BSWAP_TYPE=zzz */
+
+#endif /* CONFIG_ARC_HAS_SWAPE */
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#define __SWAB_64_THRU_32__
+#endif
+
+#endif
diff --git a/arch/arc/include/uapi/asm/unistd.h b/arch/arc/include/uapi/asm/unistd.h
new file mode 100644
index 0000000..6f30484
--- /dev/null
+++ b/arch/arc/include/uapi/asm/unistd.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+/******** no-legacy-syscalls-ABI *******/
+
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_VFORK
+#define __ARCH_WANT_SYS_FORK
+
+#define sys_mmap2 sys_mmap_pgoff
+
+#include <asm-generic/unistd.h>
+
+#define NR_syscalls	__NR_syscalls
+
+/* ARC specific syscall */
+#define __NR_cacheflush		(__NR_arch_specific_syscall + 0)
+#define __NR_arc_settls		(__NR_arch_specific_syscall + 1)
+#define __NR_arc_gettls		(__NR_arch_specific_syscall + 2)
+
+__SYSCALL(__NR_cacheflush, sys_cacheflush)
+__SYSCALL(__NR_arc_settls, sys_arc_settls)
+__SYSCALL(__NR_arc_gettls, sys_arc_gettls)
+
+
+/* Generic syscall (fs/filesystems.c - lost in asm-generic/unistd.h */
+#define __NR_sysfs		(__NR_arch_specific_syscall + 3)
+__SYSCALL(__NR_sysfs, sys_sysfs)
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 59/71] ARC: Add support for ioremap_prot API
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (20 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 58/71] ARC: UAPI Disintegrate arch/arc/include/asm Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 62/71] ARC: [Review] Multi-platform image #2: Board callback Infrastructure Vineet Gupta
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel
  Cc: arnd, Gilad Ben-Yossef, Alexey Brodkin, Noam Camus, Vineet Gupta

From: Gilad Ben-Yossef <gilad@benyossef.com>

Implement ioremap_prot() to allow mapping IO memory with variable
protection
via TLB.

Implementing this allows the /dev/mem driver to use its generic access()
VMA callback, which in turn allows ptrace to examine data in memory
mapped regions mapped via /dev/mem, such as Arc DCCM.

The end result is that it is possible to examine values of variables
placed into DCCM in user space programs via GDB.

CC: Alexey Brodkin <Alexey.Brodkin@synopsys.com>
CC: Noam Camus <noamc@ezchip.com>
Acked-by: Vineet Gupta <vgupta@synopsys.com>
Signed-off-by: Gilad Ben-Yossef <gilad@benyossef.com>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/Kconfig            |    1 +
 arch/arc/include/asm/io.h   |    2 +
 arch/arc/include/asm/page.h |    3 ++
 arch/arc/mm/ioremap.c       |   48 ++++++++++++++++++++++++++++++++----------
 4 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index cd4ad61..2dab40d 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -25,6 +25,7 @@ config ARC
 	select HAVE_ARCH_KGDB
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_GENERIC_HARDIRQS
+	select HAVE_IOREMAP_PROT
 	select HAVE_IRQ_WORK
 	select HAVE_KPROBES
 	select HAVE_KRETPROBES
diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h
index d20051b..473424d 100644
--- a/arch/arc/include/asm/io.h
+++ b/arch/arc/include/asm/io.h
@@ -16,6 +16,8 @@
 #define PCI_IOBASE ((void __iomem *)0)
 
 extern void __iomem *ioremap(unsigned long physaddr, unsigned long size);
+extern void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
+				  unsigned long flags);
 extern void iounmap(const void __iomem *addr);
 
 #define ioremap_nocache(phy, sz)	ioremap(phy, sz)
diff --git a/arch/arc/include/asm/page.h b/arch/arc/include/asm/page.h
index dfe1f8a..bdf5461 100644
--- a/arch/arc/include/asm/page.h
+++ b/arch/arc/include/asm/page.h
@@ -48,6 +48,8 @@ typedef unsigned long pgtable_t;
 #define __pgd(x)        ((pgd_t) { (x) })
 #define __pgprot(x)     ((pgprot_t) { (x) })
 
+#define pte_pgprot(x) __pgprot(pte_val(x))
+
 #else /* !STRICT_MM_TYPECHECKS */
 
 typedef unsigned long pte_t;
@@ -60,6 +62,7 @@ typedef unsigned long pgtable_t;
 #define pgprot_val(x)	(x)
 #define __pte(x)	(x)
 #define __pgprot(x)	(x)
+#define pte_pgprot(x)	(x)
 
 #endif
 
diff --git a/arch/arc/mm/ioremap.c b/arch/arc/mm/ioremap.c
index 52518b6..3e5c92c 100644
--- a/arch/arc/mm/ioremap.c
+++ b/arch/arc/mm/ioremap.c
@@ -16,25 +16,49 @@
 
 void __iomem *ioremap(unsigned long paddr, unsigned long size)
 {
-	unsigned long vaddr;
-	struct vm_struct *area;
-	unsigned long off, end;
-	const pgprot_t prot = PAGE_KERNEL_NO_CACHE;
+	unsigned long end;
 
 	/* Don't allow wraparound or zero size */
 	end = paddr + size - 1;
 	if (!size || (end < paddr))
 		return NULL;
 
-	/* If the region is h/w uncached, nothing special needed */
+	/* If the region is h/w uncached, avoid MMU mappings */
 	if (paddr >= ARC_UNCACHED_ADDR_SPACE)
 		return (void __iomem *)paddr;
 
+	return ioremap_prot(paddr, size, PAGE_KERNEL_NO_CACHE);
+}
+EXPORT_SYMBOL(ioremap);
+
+/*
+ * ioremap with access flags
+ * Cache semantics wise it is same as ioremap - "forced" uncached.
+ * However unline vanilla ioremap which bypasses ARC MMU for addresses in
+ * ARC hardware uncached region, this one still goes thru the MMU as caller
+ * might need finer access control (R/W/X)
+ */
+void __iomem *ioremap_prot(phys_addr_t paddr, unsigned long size,
+			   unsigned long flags)
+{
+	void __iomem *vaddr;
+	struct vm_struct *area;
+	unsigned long off, end;
+	pgprot_t prot = __pgprot(flags);
+
+	/* Don't allow wraparound, zero size */
+	end = paddr + size - 1;
+	if ((!size) || (end < paddr))
+		return NULL;
+
 	/* An early platform driver might end up here */
 	if (!slab_is_available())
 		return NULL;
 
-	/* Mappings have to be page-aligned, page-sized */
+	/* force uncached */
+	prot = pgprot_noncached(prot);
+
+	/* Mappings have to be page-aligned */
 	off = paddr & ~PAGE_MASK;
 	paddr &= PAGE_MASK;
 	size = PAGE_ALIGN(end + 1) - paddr;
@@ -45,17 +69,17 @@ void __iomem *ioremap(unsigned long paddr, unsigned long size)
 	area = get_vm_area(size, VM_IOREMAP);
 	if (!area)
 		return NULL;
-
 	area->phys_addr = paddr;
-	vaddr = (unsigned long)area->addr;
-	if (ioremap_page_range(vaddr, vaddr + size, paddr, prot)) {
-		vfree(area->addr);
+	vaddr = (void __iomem *)area->addr;
+	if (ioremap_page_range((unsigned long)vaddr,
+			       (unsigned long)vaddr + size, paddr, prot)) {
+		vunmap((void __force *)vaddr);
 		return NULL;
 	}
-
 	return (void __iomem *)(off + (char __iomem *)vaddr);
 }
-EXPORT_SYMBOL(ioremap);
+EXPORT_SYMBOL(ioremap_prot);
+
 
 void iounmap(const void __iomem *addr)
 {
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 62/71] ARC: [Review] Multi-platform image #2: Board callback Infrastructure
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (21 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 59/71] ARC: Add support for ioremap_prot API Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 69/71] ARC: [plat-arcfpga] defconfig for fully loaded ARC Linux Vineet Gupta
                   ` (2 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta

The orig platform code orgnaization was singleton design pattern - only
one platform (and board thereof) would build at a time.

Thus any platform/board specific code (e.g. irq init, early init ...)
expected by ARC common code was exported as well defined set of APIs,
with only ONE instance building ever.

Now with multiple-platform build requirement, that design of code no
longer holds - multiple board specific calls need to build at the same
time - so ARC common code can't use the API approach, it needs a
callback based design where each board registers it's specific set of
functions, and at runtime, depending on board detection, the callbacks
are used from the registry.

This commit adds all the infrastructure, where board specific callbacks
are specified as a "machine description".

All the hooks are placed in right spots, no board callbacks registered
yet (with MACHINE_STARt/END constructs) so the hooks will not run.

Next commit will actually convert the platform to this infrastructure.

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
 arch/arc/include/asm/mach_desc.h |   85 ++++++++++++++++++++++++++++++++++++++
 arch/arc/include/asm/prom.h      |    1 -
 arch/arc/kernel/devtree.c        |   47 +++++++++++++++++----
 arch/arc/kernel/irq.c            |    7 +++
 arch/arc/kernel/setup.c          |   28 +++++++++++-
 arch/arc/kernel/smp.c            |    3 +
 arch/arc/kernel/time.c           |    4 ++
 arch/arc/kernel/vmlinux.lds.S    |    6 +++
 8 files changed, 169 insertions(+), 12 deletions(-)
 create mode 100644 arch/arc/include/asm/mach_desc.h

diff --git a/arch/arc/include/asm/mach_desc.h b/arch/arc/include/asm/mach_desc.h
new file mode 100644
index 0000000..eaebaf8
--- /dev/null
+++ b/arch/arc/include/asm/mach_desc.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
+ *
+ * based on METAG mach/arch.h (which in turn was based on ARM)
+ *
+ * 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_ARC_MACH_DESC_H_
+#define _ASM_ARC_MACH_DESC_H_
+
+/**
+ * struct machine_desc - Board specific callbacks, called from ARC common code
+ *	Provided by each ARC board using MACHINE_START()/MACHINE_END(), so
+ *	a multi-platform kernel builds with array of such descriptors.
+ *	We extend the early DT scan to also match the DT's "compatible" string
+ *	against the @dt_compat of all such descriptors, and one with highest
+ *	"DT score" is selected as global @machine_desc.
+ *
+ * @name:		Board/SoC name
+ * @dt_compat:		Array of device tree 'compatible' strings
+ * 			(XXX: although only 1st entry is looked at)
+ * @init_early:		Very early callback [called from setup_arch()]
+ * @init_irq:		setup external IRQ controllers [called from init_IRQ()]
+ * @init_smp:		for each CPU (e.g. setup IPI)
+ * 			[(M):init_IRQ(), (o):start_kernel_secondary()]
+ * @init_time:		platform specific clocksource/clockevent registration
+ * 			[called from time_init()]
+ * @init_machine:	arch initcall level callback (e.g. populate static
+ * 			platform devices or parse Devicetree)
+ * @init_late:		Late initcall level callback
+ *
+ */
+struct machine_desc {
+	const char		*name;
+	const char		**dt_compat;
+
+	void			(*init_early)(void);
+	void			(*init_irq)(void);
+#ifdef CONFIG_SMP
+	void			(*init_smp)(unsigned int);
+#endif
+	void			(*init_time)(void);
+	void			(*init_machine)(void);
+	void			(*init_late)(void);
+
+};
+
+/*
+ * Current machine - only accessible during boot.
+ */
+extern struct machine_desc *machine_desc;
+
+/*
+ * Machine type table - also only accessible during boot
+ */
+extern struct machine_desc __arch_info_begin[], __arch_info_end[];
+#define for_each_machine_desc(p)			\
+	for (p = __arch_info_begin; p < __arch_info_end; p++)
+
+static inline struct machine_desc *default_machine_desc(void)
+{
+	/* the default machine is the last one linked in */
+	if (__arch_info_end - 1 < __arch_info_begin)
+		return NULL;
+	return __arch_info_end - 1;
+}
+
+/*
+ * Set of macros to define architecture features.
+ * This is built into a table by the linker.
+ */
+#define MACHINE_START(_type, _name)			\
+static const struct machine_desc __mach_desc_##_type	\
+__used							\
+__attribute__((__section__(".arch.info.init"))) = {	\
+	.name		= _name,
+
+#define MACHINE_END				\
+};
+
+extern struct machine_desc *setup_machine_fdt(void *dt);
+#endif
diff --git a/arch/arc/include/asm/prom.h b/arch/arc/include/asm/prom.h
index f54489b..692d0d0 100644
--- a/arch/arc/include/asm/prom.h
+++ b/arch/arc/include/asm/prom.h
@@ -10,6 +10,5 @@
 #define _ASM_ARC_PROM_H_
 
 #define HAVE_ARCH_DEVTREE_FIXUPS
-extern int __init setup_machine_fdt(void *dt);
 
 #endif
diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c
index d2a41be..051ec8b 100644
--- a/arch/arc/kernel/devtree.c
+++ b/arch/arc/kernel/devtree.c
@@ -21,6 +21,7 @@
 #include <linux/of_platform.h>
 #include <asm/prom.h>
 #include <asm/clk.h>
+#include <asm/mach_desc.h>
 
 /* called from unflatten_device_tree() to bootstrap devicetree itself */
 void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
@@ -35,27 +36,57 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
  * If a dtb was passed to the kernel, then use it to choose the correct
  * machine_desc and to setup the system.
  */
-int __init setup_machine_fdt(void *dt)
+struct machine_desc * __init setup_machine_fdt(void *dt)
 {
 	struct boot_param_header *devtree = dt;
+	struct machine_desc *mdesc = NULL, *mdesc_best = NULL;
+	unsigned int score, mdesc_score = ~1;
 	unsigned long dt_root;
-	char *model, *compat;
+	const char *model, *compat;
 	void *clk;
 	char manufacturer[16];
 	unsigned long len;
 
 	/* check device tree validity */
 	if (be32_to_cpu(devtree->magic) != OF_DT_HEADER)
-		return 1;
+		return NULL;
 
-	/* Search the mdescs for the 'best' compatible value match */
 	initial_boot_params = devtree;
 	dt_root = of_get_flat_dt_root();
 
+	/*
+	 * The kernel could be multi-platform enabled, thus could have many
+	 * "baked-in" machine descriptors. Search thru all for the best
+	 * "compatible" string match.
+	 */
+	for_each_machine_desc(mdesc) {
+		score = of_flat_dt_match(dt_root, mdesc->dt_compat);
+		if (score > 0 && score < mdesc_score) {
+			mdesc_best = mdesc;
+			mdesc_score = score;
+		}
+	}
+	if (!mdesc_best) {
+		const char *prop;
+		long size;
+
+		pr_err("\n unrecognized device tree list:\n[ ");
+
+		prop = of_get_flat_dt_prop(dt_root, "compatible", &size);
+		if (prop) {
+			while (size > 0) {
+				printk("'%s' ", prop);
+				size -= strlen(prop) + 1;
+				prop += strlen(prop) + 1;
+			}
+		}
+		printk("]\n\n");
+
+		machine_halt();
+	}
+
 	/* compat = "<manufacturer>,<model>" */
-	compat = of_get_flat_dt_prop(dt_root, "compatible", NULL);
-	if (!compat)
-		compat = "<unknown>";
+	compat =  mdesc_best->dt_compat[0];
 
 	model = strchr(compat, ',');
 	if (model)
@@ -78,5 +109,5 @@ int __init setup_machine_fdt(void *dt)
 	if (clk)
 		arc_set_core_freq(of_read_ulong(clk, len/4));
 
-	return 0;
+	return mdesc_best;
 }
diff --git a/arch/arc/kernel/irq.c b/arch/arc/kernel/irq.c
index df7da2b..1198168 100644
--- a/arch/arc/kernel/irq.c
+++ b/arch/arc/kernel/irq.c
@@ -13,6 +13,7 @@
 #include <linux/irqdomain.h>
 #include <asm/sections.h>
 #include <asm/irq.h>
+#include <asm/mach_desc.h>
 
 /*
  * Early Hardware specific Interrupt setup
@@ -125,9 +126,15 @@ void __init init_IRQ(void)
 	init_onchip_IRQ();
 	plat_init_IRQ();
 
+	/* Any external intc can be setup here */
+	if (machine_desc->init_irq)
+		machine_desc->init_irq();
+
 #ifdef CONFIG_SMP
 	/* Master CPU can initialize it's side of IPI */
 	arc_platform_smp_init_cpu();
+	if (machine_desc->init_smp)
+		machine_desc->init_smp(smp_processor_id());
 #endif
 }
 
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index 6cc361c..20273b8 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -25,12 +25,14 @@
 #include <asm/prom.h>
 #include <asm/unwind.h>
 #include <asm/clk.h>
+#include <asm/mach_desc.h>
 
 #define FIX_PTR(x)  __asm__ __volatile__(";" : "+r"(x))
 
 int running_on_hw = 1;	/* vs. on ISS */
 
 char __initdata command_line[COMMAND_LINE_SIZE];
+struct machine_desc *machine_desc __initdata;
 
 struct task_struct *_current_task[NR_CPUS];	/* For stack switching */
 
@@ -323,8 +325,6 @@ void __init __attribute__((weak)) arc_platform_early_init(void)
 
 void __init setup_arch(char **cmdline_p)
 {
-	int rc;
-
 #ifdef CONFIG_CMDLINE_UBOOT
 	/* Make sure that a whitespace is inserted before */
 	strlcat(command_line, " ", sizeof(command_line));
@@ -339,13 +339,17 @@ void __init setup_arch(char **cmdline_p)
 	strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
 	*cmdline_p = command_line;
 
-	rc = setup_machine_fdt(__dtb_start);
+	machine_desc = setup_machine_fdt(__dtb_start);
+	if (!machine_desc)
+		panic("Embedded DT invalid\n");
 
 	/* To force early parsing of things like mem=xxx */
 	parse_early_param();
 
 	/* Platform/board specific: e.g. early console registration */
 	arc_platform_early_init();
+	if (machine_desc->init_early)
+		machine_desc->init_early();
 
 	setup_processor();
 
@@ -372,6 +376,24 @@ void __init setup_arch(char **cmdline_p)
 	arc_unwind_setup();
 }
 
+static int __init customize_machine(void)
+{
+	/* Add platform devices */
+	if (machine_desc->init_machine)
+		machine_desc->init_machine();
+
+	return 0;
+}
+arch_initcall(customize_machine);
+
+static int __init init_late_machine(void)
+{
+	if (machine_desc->init_late)
+		machine_desc->init_late();
+
+	return 0;
+}
+late_initcall(init_late_machine);
 /*
  *  Get CPU information for use by the procfs.
  */
diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c
index 1f762ad..ea15f07 100644
--- a/arch/arc/kernel/smp.c
+++ b/arch/arc/kernel/smp.c
@@ -32,6 +32,7 @@
 #include <linux/reboot.h>
 #include <asm/processor.h>
 #include <asm/setup.h>
+#include <asm/mach_desc.h>
 
 arch_spinlock_t smp_atomic_ops_lock = __ARCH_SPIN_LOCK_UNLOCKED;
 arch_spinlock_t smp_bitops_lock = __ARCH_SPIN_LOCK_UNLOCKED;
@@ -127,6 +128,8 @@ void __cpuinit start_kernel_secondary(void)
 	pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu);
 
 	arc_platform_smp_init_cpu();
+	if (machine_desc->init_smp)
+		machine_desc->init_smp(smp_processor_id());
 
 	arc_local_timer_setup(cpu);
 
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index 05dba11..0ce0e6f 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -43,6 +43,7 @@
 #include <asm/irq.h>
 #include <asm/arcregs.h>
 #include <asm/clk.h>
+#include <asm/mach_desc.h>
 
 #define ARC_TIMER_MAX	0xFFFFFFFF
 
@@ -258,6 +259,9 @@ void __init time_init(void)
 
 	/* sets up the periodic event timer */
 	arc_local_timer_setup(smp_processor_id());
+
+	if (machine_desc->init_time)
+		machine_desc->init_time();
 }
 
 #ifdef CONFIG_ARC_HAS_RTSC
diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
index 8d3b0d4..622d8b6 100644
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -75,6 +75,12 @@ SECTIONS
 		SECURITY_INITCALL
 	}
 
+	.init.arch.info : {
+		__arch_info_begin = .;
+		*(.arch.info.init)
+		__arch_info_end = .;
+	}
+
 	PERCPU_SECTION(L1_CACHE_BYTES)
 
 	/*
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 69/71] ARC: [plat-arcfpga] defconfig for fully loaded ARC Linux
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (22 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 62/71] ARC: [Review] Multi-platform image #2: Board callback Infrastructure Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 10:50 ` [PATCH v3 70/71] ARC: Provide a default serial.h for uart drivers needing BASE_BAUD Vineet Gupta
  2013-01-24 11:01 ` [PATCH v3 45/71] ARC: DWARF2 .debug_frame based stack unwinder Vineet Gupta
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/configs/fpga_defconfig |   23 +++++++++++++++++++----
 1 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/arch/arc/configs/fpga_defconfig b/arch/arc/configs/fpga_defconfig
index 8638e101f..b869806 100644
--- a/arch/arc/configs/fpga_defconfig
+++ b/arch/arc/configs/fpga_defconfig
@@ -10,16 +10,29 @@ CONFIG_NAMESPACES=y
 # CONFIG_PID_NS is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE="../arc_initramfs"
-CONFIG_EXPERT=y
-# CONFIG_FUTEX is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
 # CONFIG_COMPAT_BRK is not set
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARC_PLAT_FPGA_LEGACY=y
+CONFIG_ARC_BOARD_ML509=y
+# CONFIG_ARC_HAS_RTSC is not set
 CONFIG_ARC_BUILTIN_DTB_NAME="angel4"
 # CONFIG_COMPACTION is not set
 # CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IPV6 is not set
 # CONFIG_STANDALONE is not set
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 # CONFIG_FIRMWARE_IN_KERNEL is not set
@@ -38,9 +51,11 @@ CONFIG_SERIAL_ARC_CONSOLE=y
 # CONFIG_HID is not set
 # CONFIG_USB_SUPPORT is not set
 # CONFIG_IOMMU_SUPPORT is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_INOTIFY_USER is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_TMPFS=y
 # CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_XZ_DEC=y
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 70/71] ARC: Provide a default serial.h for uart drivers needing BASE_BAUD
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (23 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 69/71] ARC: [plat-arcfpga] defconfig for fully loaded ARC Linux Vineet Gupta
@ 2013-01-24 10:50 ` Vineet Gupta
  2013-01-24 11:01 ` [PATCH v3 45/71] ARC: DWARF2 .debug_frame based stack unwinder Vineet Gupta
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 10:50 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/include/asm/serial.h |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)
 create mode 100644 arch/arc/include/asm/serial.h

diff --git a/arch/arc/include/asm/serial.h b/arch/arc/include/asm/serial.h
new file mode 100644
index 0000000..4dff5a1
--- /dev/null
+++ b/arch/arc/include/asm/serial.h
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+#ifndef _ASM_ARC_SERIAL_H
+#define _ASM_ARC_SERIAL_H
+
+/*
+ * early-8250 requires BASE_BAUD to be defined and includes this header.
+ * We put in a typical value:
+ * 	(core clk / 16) - i.e. UART samples 16 times per sec.
+ * Athough in multi-platform-image this might not work, specially if the
+ * clk driving the UART is different.
+ * We can't use DeviceTree as this is typically for early serial.
+ */
+
+#include <asm/clk.h>
+
+#define BASE_BAUD	(arc_get_core_freq() / 16)
+
+#endif /* _ASM_ARC_SERIAL_H */
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v3 45/71] ARC: DWARF2 .debug_frame based stack unwinder
  2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
                   ` (24 preceding siblings ...)
  2013-01-24 10:50 ` [PATCH v3 70/71] ARC: Provide a default serial.h for uart drivers needing BASE_BAUD Vineet Gupta
@ 2013-01-24 11:01 ` Vineet Gupta
  25 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-24 11:01 UTC (permalink / raw)
  To: linux-arch, linux-kernel; +Cc: arnd, Vineet Gupta, Rajeshwar Ranga

-Originally contributed by Rajeshwar Range <rajeshwar.ranga@gmail.com>
-Derived off of generic unwinder in 2.6.19 and adapted to ARC

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Rajeshwar Ranga <rajeshwar.ranga@gmail.com>
---
 arch/arc/Kconfig              |   15 +
 arch/arc/include/asm/module.h |    7 +
 arch/arc/include/asm/unwind.h |  163 +++++
 arch/arc/kernel/Makefile      |    6 +
 arch/arc/kernel/entry.S       |    9 +
 arch/arc/kernel/module.c      |   58 ++
 arch/arc/kernel/setup.c       |    3 +
 arch/arc/kernel/unwind.c      | 1329 +++++++++++++++++++++++++++++++++++++++++
 arch/arc/kernel/vmlinux.lds.S |   23 +-
 9 files changed, 1612 insertions(+), 1 deletions(-)
 create mode 100644 arch/arc/include/asm/unwind.h
 create mode 100644 arch/arc/kernel/unwind.c

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 52f5c07..0979d8e 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -25,6 +25,7 @@ config ARC
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_GENERIC_HARDIRQS
 	select HAVE_MEMBLOCK
+	select HAVE_MOD_ARCH_SPECIFIC if ARC_DW2_UNWIND
 	select HAVE_OPROFILE
 	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
@@ -344,6 +345,20 @@ menuconfig ARC_DBG
 	bool "ARC debugging"
 	default y
 
+config ARC_DW2_UNWIND
+	bool "Enable DWARF specific kernel stack unwind"
+	depends on ARC_DBG
+	default y
+	select KALLSYMS
+	help
+	  Compiles the kernel with DWARF unwind information and can be used
+	  to get stack backtraces.
+
+	  If you say Y here the resulting kernel image will be slightly larger
+	  but not slower, and it will give very useful debugging information.
+	  If you don't debug the kernel, you can say N, but we may not be able
+	  to solve problems without frame unwind information
+
 config ARC_DBG_TLB_PARANOIA
 	bool "Paranoia Checks in Low Level TLB Handlers"
 	depends on ARC_DBG && !SMP
diff --git a/arch/arc/include/asm/module.h b/arch/arc/include/asm/module.h
index 234b435..518222b 100644
--- a/arch/arc/include/asm/module.h
+++ b/arch/arc/include/asm/module.h
@@ -14,6 +14,13 @@
 
 #include <asm-generic/module.h>
 
+#ifdef CONFIG_ARC_DW2_UNWIND
+struct mod_arch_specific {
+	void *unw_info;
+	int unw_sec_idx;
+};
+#endif
+
 #define MODULE_PROC_FAMILY "ARC700"
 
 #define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
diff --git a/arch/arc/include/asm/unwind.h b/arch/arc/include/asm/unwind.h
new file mode 100644
index 0000000..7ca628b
--- /dev/null
+++ b/arch/arc/include/asm/unwind.h
@@ -0,0 +1,163 @@
+/*
+ * 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_ARC_UNWIND_H
+#define _ASM_ARC_UNWIND_H
+
+#ifdef CONFIG_ARC_DW2_UNWIND
+
+#include <linux/sched.h>
+
+struct arc700_regs {
+	unsigned long r0;
+	unsigned long r1;
+	unsigned long r2;
+	unsigned long r3;
+	unsigned long r4;
+	unsigned long r5;
+	unsigned long r6;
+	unsigned long r7;
+	unsigned long r8;
+	unsigned long r9;
+	unsigned long r10;
+	unsigned long r11;
+	unsigned long r12;
+	unsigned long r13;
+	unsigned long r14;
+	unsigned long r15;
+	unsigned long r16;
+	unsigned long r17;
+	unsigned long r18;
+	unsigned long r19;
+	unsigned long r20;
+	unsigned long r21;
+	unsigned long r22;
+	unsigned long r23;
+	unsigned long r24;
+	unsigned long r25;
+	unsigned long r26;
+	unsigned long r27;	/* fp */
+	unsigned long r28;	/* sp */
+	unsigned long r29;
+	unsigned long r30;
+	unsigned long r31;	/* blink */
+	unsigned long r63;	/* pc */
+};
+
+struct unwind_frame_info {
+	struct arc700_regs regs;
+	struct task_struct *task;
+	unsigned call_frame:1;
+};
+
+#define UNW_PC(frame)		((frame)->regs.r63)
+#define UNW_SP(frame)		((frame)->regs.r28)
+#define UNW_BLINK(frame)	((frame)->regs.r31)
+
+/* Rajesh FIXME */
+#ifdef CONFIG_FRAME_POINTER
+#define UNW_FP(frame)		((frame)->regs.r27)
+#define FRAME_RETADDR_OFFSET	4
+#define FRAME_LINK_OFFSET	0
+#define STACK_BOTTOM_UNW(tsk)	STACK_LIMIT((tsk)->thread.ksp)
+#define STACK_TOP_UNW(tsk)	((tsk)->thread.ksp)
+#else
+#define UNW_FP(frame)		((void)(frame), 0)
+#endif
+
+#define STACK_LIMIT(ptr)	(((ptr) - 1) & ~(THREAD_SIZE - 1))
+
+#define UNW_REGISTER_INFO \
+	PTREGS_INFO(r0), \
+	PTREGS_INFO(r1), \
+	PTREGS_INFO(r2), \
+	PTREGS_INFO(r3), \
+	PTREGS_INFO(r4), \
+	PTREGS_INFO(r5), \
+	PTREGS_INFO(r6), \
+	PTREGS_INFO(r7), \
+	PTREGS_INFO(r8), \
+	PTREGS_INFO(r9), \
+	PTREGS_INFO(r10), \
+	PTREGS_INFO(r11), \
+	PTREGS_INFO(r12), \
+	PTREGS_INFO(r13), \
+	PTREGS_INFO(r14), \
+	PTREGS_INFO(r15), \
+	PTREGS_INFO(r16), \
+	PTREGS_INFO(r17), \
+	PTREGS_INFO(r18), \
+	PTREGS_INFO(r19), \
+	PTREGS_INFO(r20), \
+	PTREGS_INFO(r21), \
+	PTREGS_INFO(r22), \
+	PTREGS_INFO(r23), \
+	PTREGS_INFO(r24), \
+	PTREGS_INFO(r25), \
+	PTREGS_INFO(r26), \
+	PTREGS_INFO(r27), \
+	PTREGS_INFO(r28), \
+	PTREGS_INFO(r29), \
+	PTREGS_INFO(r30), \
+	PTREGS_INFO(r31), \
+	PTREGS_INFO(r63)
+
+#define UNW_DEFAULT_RA(raItem, dataAlign) \
+	((raItem).where == Memory && !((raItem).value * (dataAlign) + 4))
+
+extern int arc_unwind(struct unwind_frame_info *frame);
+extern void arc_unwind_init(void);
+extern void arc_unwind_setup(void);
+extern void *unwind_add_table(struct module *module, const void *table_start,
+			      unsigned long table_size);
+extern void unwind_remove_table(void *handle, int init_only);
+
+static inline int
+arch_unwind_init_running(struct unwind_frame_info *info,
+			 int (*callback) (struct unwind_frame_info *info,
+					  void *arg),
+			 void *arg)
+{
+	return 0;
+}
+
+static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
+{
+	return 0;
+}
+
+static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
+{
+	return;
+}
+
+static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
+					    struct pt_regs *regs)
+{
+	return;
+}
+
+#else
+
+#define UNW_PC(frame) ((void)(frame), 0)
+#define UNW_SP(frame) ((void)(frame), 0)
+#define UNW_FP(frame) ((void)(frame), 0)
+
+static inline void arc_unwind_init(void)
+{
+}
+
+static inline void arc_unwind_setup(void)
+{
+}
+#define unwind_add_table(a, b, c)
+#define unwind_remove_table(a, b)
+
+#endif /* CONFIG_ARC_DW2_UNWIND */
+
+#endif /* _ASM_ARC_UNWIND_H */
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
index cd2f882..d2a31ac 100644
--- a/arch/arc/kernel/Makefile
+++ b/arch/arc/kernel/Makefile
@@ -14,10 +14,16 @@ obj-y	+= signal.o traps.o sys.o troubleshoot.o stacktrace.o clk.o
 obj-$(CONFIG_OF)			+= devtree.o
 obj-$(CONFIG_MODULES)			+= arcksyms.o module.o
 obj-$(CONFIG_SMP) 			+= smp.o
+obj-$(CONFIG_ARC_DW2_UNWIND)		+= unwind.o
 
 obj-$(CONFIG_ARC_FPU_SAVE_RESTORE)	+= fpu.o
 CFLAGS_fpu.o   += -mdpfp
 
+ifdef CONFIG_ARC_DW2_UNWIND
+CFLAGS_ctx_sw.o += -fno-omit-frame-pointer
+obj-y += ctx_sw.o
+else
 obj-y += ctx_sw_asm.o
+endif
 
 extra-y := vmlinux.lds head.o
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index 3f6ce98..021cfa4 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -815,3 +815,12 @@ ARC_ENTRY sys_clone_wrapper
 
 	b ret_from_system_call
 ARC_EXIT sys_clone_wrapper
+
+#ifdef CONFIG_ARC_DW2_UNWIND
+; Workaround for bug 94179 (STAR ):
+; Despite -fasynchronous-unwind-tables, linker is not making dwarf2 unwinder
+; section (.debug_frame) as loadable. So we force it here.
+; This also fixes STAR 9000487933 where the prev-workaround (objcopy --setflag)
+; would not work after a clean build due to kernel build system dependencies.
+.section .debug_frame, "wa",@progbits
+#endif
diff --git a/arch/arc/kernel/module.c b/arch/arc/kernel/module.c
index a1bb70d..cdd3593 100644
--- a/arch/arc/kernel/module.c
+++ b/arch/arc/kernel/module.c
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/string.h>
+#include <asm/unwind.h>
 
 static inline void arc_write_me(unsigned short *addr, unsigned long value)
 {
@@ -21,6 +22,42 @@ static inline void arc_write_me(unsigned short *addr, unsigned long value)
 	*(addr + 1) = (value & 0xffff);
 }
 
+/* ARC specific section quirks - before relocation loop in generic loader
+ *
+ * For dwarf unwinding out of modules, this needs to
+ * 1. Ensure the .debug_frame is allocatable (ARC Linker bug: despite
+ *    -fasynchronous-unwind-tables it doesn't).
+ * 2. Since we are iterating thru sec hdr tbl anyways, make a note of
+ *    the exact section index, for later use.
+ */
+int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
+			      char *secstr, struct module *mod)
+{
+#ifdef CONFIG_ARC_DW2_UNWIND
+	int i;
+
+	mod->arch.unw_sec_idx = 0;
+	mod->arch.unw_info = NULL;
+
+	for (i = 1; i < hdr->e_shnum; i++) {
+		if (strcmp(secstr+sechdrs[i].sh_name, ".debug_frame") == 0) {
+			sechdrs[i].sh_flags |= SHF_ALLOC;
+			mod->arch.unw_sec_idx = i;
+			break;
+		}
+	}
+#endif
+    return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+#ifdef CONFIG_ARC_DW2_UNWIND
+	if (mod->arch.unw_info)
+		unwind_remove_table(mod->arch.unw_info, 0);
+#endif
+}
+
 int apply_relocate_add(Elf32_Shdr *sechdrs,
 		       const char *strtab,
 		       unsigned int symindex,	/* sec index for sym tbl */
@@ -85,3 +122,24 @@ relo_err:
 	return -ENOEXEC;
 
 }
+
+/* Just before lift off: After sections have been relocated, we add the
+ * dwarf section to unwinder table pool
+ * This couldn't be done in module_frob_arch_sections() because
+ * relocations had not been applied by then
+ */
+int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
+		    struct module *mod)
+{
+#ifdef CONFIG_ARC_DW2_UNWIND
+	void *unw;
+	int unwsec = mod->arch.unw_sec_idx;
+
+	if (unwsec) {
+		unw = unwind_add_table(mod, (void *)sechdrs[unwsec].sh_addr,
+				       sechdrs[unwsec].sh_size);
+		mod->arch.unw_info = unw;
+	}
+#endif
+    return 0;
+}
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index 4026b5a..6e3996c 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -23,6 +23,7 @@
 #include <asm/irq.h>
 #include <asm/arcregs.h>
 #include <asm/prom.h>
+#include <asm/unwind.h>
 
 #define FIX_PTR(x)  __asm__ __volatile__(";" : "+r"(x))
 
@@ -105,6 +106,8 @@ void __init setup_arch(char **cmdline_p)
 	conswitchp = &dummy_con;
 #endif
 
+	arc_unwind_init();
+	arc_unwind_setup();
 }
 
 /*
diff --git a/arch/arc/kernel/unwind.c b/arch/arc/kernel/unwind.c
new file mode 100644
index 0000000..a8d0222
--- /dev/null
+++ b/arch/arc/kernel/unwind.c
@@ -0,0 +1,1329 @@
+/*
+ * Copyright (C) 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
+ * Copyright (C) 2002-2006 Novell, Inc.
+ *	Jan Beulich <jbeulich@novell.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.
+ *
+ * A simple API for unwinding kernel stacks.  This is used for
+ * debugging and error reporting purposes.  The kernel doesn't need
+ * full-blown stack unwinding with all the bells and whistles, so there
+ * is not much point in implementing the full Dwarf2 unwind API.
+ */
+
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/bootmem.h>
+#include <linux/sort.h>
+#include <linux/slab.h>
+#include <linux/stop_machine.h>
+#include <linux/uaccess.h>
+#include <linux/ptrace.h>
+#include <asm/sections.h>
+#include <asm/unaligned.h>
+#include <asm/unwind.h>
+
+extern char __start_unwind[], __end_unwind[];
+/* extern const u8 __start_unwind_hdr[], __end_unwind_hdr[];*/
+
+/* #define UNWIND_DEBUG */
+
+#ifdef UNWIND_DEBUG
+int dbg_unw;
+#define unw_debug(fmt, ...)			\
+do {						\
+	if (dbg_unw)				\
+		pr_info(fmt, ##__VA_ARGS__);	\
+} while (0);
+#else
+#define unw_debug(fmt, ...)
+#endif
+
+#define MAX_STACK_DEPTH 8
+
+#define EXTRA_INFO(f) { \
+		BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \
+				% FIELD_SIZEOF(struct unwind_frame_info, f)) \
+				+ offsetof(struct unwind_frame_info, f) \
+				/ FIELD_SIZEOF(struct unwind_frame_info, f), \
+				FIELD_SIZEOF(struct unwind_frame_info, f) \
+	}
+#define PTREGS_INFO(f) EXTRA_INFO(regs.f)
+
+static const struct {
+	unsigned offs:BITS_PER_LONG / 2;
+	unsigned width:BITS_PER_LONG / 2;
+} reg_info[] = {
+UNW_REGISTER_INFO};
+
+#undef PTREGS_INFO
+#undef EXTRA_INFO
+
+#ifndef REG_INVALID
+#define REG_INVALID(r) (reg_info[r].width == 0)
+#endif
+
+#define DW_CFA_nop                          0x00
+#define DW_CFA_set_loc                      0x01
+#define DW_CFA_advance_loc1                 0x02
+#define DW_CFA_advance_loc2                 0x03
+#define DW_CFA_advance_loc4                 0x04
+#define DW_CFA_offset_extended              0x05
+#define DW_CFA_restore_extended             0x06
+#define DW_CFA_undefined                    0x07
+#define DW_CFA_same_value                   0x08
+#define DW_CFA_register                     0x09
+#define DW_CFA_remember_state               0x0a
+#define DW_CFA_restore_state                0x0b
+#define DW_CFA_def_cfa                      0x0c
+#define DW_CFA_def_cfa_register             0x0d
+#define DW_CFA_def_cfa_offset               0x0e
+#define DW_CFA_def_cfa_expression           0x0f
+#define DW_CFA_expression                   0x10
+#define DW_CFA_offset_extended_sf           0x11
+#define DW_CFA_def_cfa_sf                   0x12
+#define DW_CFA_def_cfa_offset_sf            0x13
+#define DW_CFA_val_offset                   0x14
+#define DW_CFA_val_offset_sf                0x15
+#define DW_CFA_val_expression               0x16
+#define DW_CFA_lo_user                      0x1c
+#define DW_CFA_GNU_window_save              0x2d
+#define DW_CFA_GNU_args_size                0x2e
+#define DW_CFA_GNU_negative_offset_extended 0x2f
+#define DW_CFA_hi_user                      0x3f
+
+#define DW_EH_PE_FORM     0x07
+#define DW_EH_PE_native   0x00
+#define DW_EH_PE_leb128   0x01
+#define DW_EH_PE_data2    0x02
+#define DW_EH_PE_data4    0x03
+#define DW_EH_PE_data8    0x04
+#define DW_EH_PE_signed   0x08
+#define DW_EH_PE_ADJUST   0x70
+#define DW_EH_PE_abs      0x00
+#define DW_EH_PE_pcrel    0x10
+#define DW_EH_PE_textrel  0x20
+#define DW_EH_PE_datarel  0x30
+#define DW_EH_PE_funcrel  0x40
+#define DW_EH_PE_aligned  0x50
+#define DW_EH_PE_indirect 0x80
+#define DW_EH_PE_omit     0xff
+
+typedef unsigned long uleb128_t;
+typedef signed long sleb128_t;
+
+static struct unwind_table {
+	struct {
+		unsigned long pc;
+		unsigned long range;
+	} core, init;
+	const void *address;
+	unsigned long size;
+	const unsigned char *header;
+	unsigned long hdrsz;
+	struct unwind_table *link;
+	const char *name;
+} root_table;
+
+struct unwind_item {
+	enum item_location {
+		Nowhere,
+		Memory,
+		Register,
+		Value
+	} where;
+	uleb128_t value;
+};
+
+struct unwind_state {
+	uleb128_t loc, org;
+	const u8 *cieStart, *cieEnd;
+	uleb128_t codeAlign;
+	sleb128_t dataAlign;
+	struct cfa {
+		uleb128_t reg, offs;
+	} cfa;
+	struct unwind_item regs[ARRAY_SIZE(reg_info)];
+	unsigned stackDepth:8;
+	unsigned version:8;
+	const u8 *label;
+	const u8 *stack[MAX_STACK_DEPTH];
+};
+
+static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
+
+static struct unwind_table *find_table(unsigned long pc)
+{
+	struct unwind_table *table;
+
+	for (table = &root_table; table; table = table->link)
+		if ((pc >= table->core.pc
+		     && pc < table->core.pc + table->core.range)
+		    || (pc >= table->init.pc
+			&& pc < table->init.pc + table->init.range))
+			break;
+
+	return table;
+}
+
+static unsigned long read_pointer(const u8 **pLoc,
+				  const void *end, signed ptrType);
+
+static void init_unwind_table(struct unwind_table *table, const char *name,
+			      const void *core_start, unsigned long core_size,
+			      const void *init_start, unsigned long init_size,
+			      const void *table_start, unsigned long table_size,
+			      const u8 *header_start, unsigned long header_size)
+{
+	const u8 *ptr = header_start + 4;
+	const u8 *end = header_start + header_size;
+
+	table->core.pc = (unsigned long)core_start;
+	table->core.range = core_size;
+	table->init.pc = (unsigned long)init_start;
+	table->init.range = init_size;
+	table->address = table_start;
+	table->size = table_size;
+
+	/* See if the linker provided table looks valid. */
+	if (header_size <= 4
+	    || header_start[0] != 1
+	    || (void *)read_pointer(&ptr, end, header_start[1]) != table_start
+	    || header_start[2] == DW_EH_PE_omit
+	    || read_pointer(&ptr, end, header_start[2]) <= 0
+	    || header_start[3] == DW_EH_PE_omit)
+		header_start = NULL;
+
+	table->hdrsz = header_size;
+	smp_wmb();
+	table->header = header_start;
+	table->link = NULL;
+	table->name = name;
+}
+
+void __init arc_unwind_init(void)
+{
+	init_unwind_table(&root_table, "kernel", _text, _end - _text, NULL, 0,
+			  __start_unwind, __end_unwind - __start_unwind,
+			  NULL, 0);
+	  /*__start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);*/
+}
+
+static const u32 bad_cie, not_fde;
+static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *);
+static signed fde_pointer_type(const u32 *cie);
+
+struct eh_frame_hdr_table_entry {
+	unsigned long start, fde;
+};
+
+static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2)
+{
+	const struct eh_frame_hdr_table_entry *e1 = p1;
+	const struct eh_frame_hdr_table_entry *e2 = p2;
+
+	return (e1->start > e2->start) - (e1->start < e2->start);
+}
+
+static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
+{
+	struct eh_frame_hdr_table_entry *e1 = p1;
+	struct eh_frame_hdr_table_entry *e2 = p2;
+	unsigned long v;
+
+	v = e1->start;
+	e1->start = e2->start;
+	e2->start = v;
+	v = e1->fde;
+	e1->fde = e2->fde;
+	e2->fde = v;
+}
+
+static void __init setup_unwind_table(struct unwind_table *table,
+				      void *(*alloc) (unsigned long))
+{
+	const u8 *ptr;
+	unsigned long tableSize = table->size, hdrSize;
+	unsigned n;
+	const u32 *fde;
+	struct {
+		u8 version;
+		u8 eh_frame_ptr_enc;
+		u8 fde_count_enc;
+		u8 table_enc;
+		unsigned long eh_frame_ptr;
+		unsigned int fde_count;
+		struct eh_frame_hdr_table_entry table[];
+	} __attribute__ ((__packed__)) *header;
+
+	if (table->header)
+		return;
+
+	if (table->hdrsz)
+		pr_warn(".eh_frame_hdr for '%s' present but unusable\n",
+			table->name);
+
+	if (tableSize & (sizeof(*fde) - 1))
+		return;
+
+	for (fde = table->address, n = 0;
+	     tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
+	     tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
+		const u32 *cie = cie_for_fde(fde, table);
+		signed ptrType;
+
+		if (cie == &not_fde)
+			continue;
+		if (cie == NULL || cie == &bad_cie)
+			return;
+		ptrType = fde_pointer_type(cie);
+		if (ptrType < 0)
+			return;
+
+		ptr = (const u8 *)(fde + 2);
+		if (!read_pointer(&ptr, (const u8 *)(fde + 1) + *fde,
+								ptrType)) {
+			/* FIXME_Rajesh We have 4 instances of null addresses
+			 * instead of the initial loc addr
+			 * return;
+			 */
+		}
+		++n;
+	}
+
+	if (tableSize || !n)
+		return;
+
+	hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
+	    + 2 * n * sizeof(unsigned long);
+	header = alloc(hdrSize);
+	if (!header)
+		return;
+	header->version = 1;
+	header->eh_frame_ptr_enc = DW_EH_PE_abs | DW_EH_PE_native;
+	header->fde_count_enc = DW_EH_PE_abs | DW_EH_PE_data4;
+	header->table_enc = DW_EH_PE_abs | DW_EH_PE_native;
+	put_unaligned((unsigned long)table->address, &header->eh_frame_ptr);
+	BUILD_BUG_ON(offsetof(typeof(*header), fde_count)
+		     % __alignof(typeof(header->fde_count)));
+	header->fde_count = n;
+
+	BUILD_BUG_ON(offsetof(typeof(*header), table)
+		     % __alignof(typeof(*header->table)));
+	for (fde = table->address, tableSize = table->size, n = 0;
+	     tableSize;
+	     tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
+		/* const u32 *cie = fde + 1 - fde[1] / sizeof(*fde); */
+		const u32 *cie = (const u32 *)(fde[1]);
+
+		if (fde[1] == 0xffffffff)
+			continue;	/* this is a CIE */
+		ptr = (const u8 *)(fde + 2);
+		header->table[n].start = read_pointer(&ptr,
+						      (const u8 *)(fde + 1) +
+						      *fde,
+						      fde_pointer_type(cie));
+		header->table[n].fde = (unsigned long)fde;
+		++n;
+	}
+	WARN_ON(n != header->fde_count);
+
+	sort(header->table,
+	     n,
+	     sizeof(*header->table),
+	     cmp_eh_frame_hdr_table_entries, swap_eh_frame_hdr_table_entries);
+
+	table->hdrsz = hdrSize;
+	smp_wmb();
+	table->header = (const void *)header;
+}
+
+static void *__init balloc(unsigned long sz)
+{
+	return __alloc_bootmem_nopanic(sz,
+				       sizeof(unsigned int),
+				       __pa(MAX_DMA_ADDRESS));
+}
+
+void __init arc_unwind_setup(void)
+{
+	setup_unwind_table(&root_table, balloc);
+}
+
+#ifdef CONFIG_MODULES
+
+static struct unwind_table *last_table;
+
+/* Must be called with module_mutex held. */
+void *unwind_add_table(struct module *module, const void *table_start,
+		       unsigned long table_size)
+{
+	struct unwind_table *table;
+
+	if (table_size <= 0)
+		return NULL;
+
+	table = kmalloc(sizeof(*table), GFP_KERNEL);
+	if (!table)
+		return NULL;
+
+	init_unwind_table(table, module->name,
+			  module->module_core, module->core_size,
+			  module->module_init, module->init_size,
+			  table_start, table_size,
+			  NULL, 0);
+
+#ifdef UNWIND_DEBUG
+	unw_debug("Table added for [%s] %lx %lx\n",
+		module->name, table->core.pc, table->core.range);
+#endif
+	if (last_table)
+		last_table->link = table;
+	else
+		root_table.link = table;
+	last_table = table;
+
+	return table;
+}
+
+struct unlink_table_info {
+	struct unwind_table *table;
+	int init_only;
+};
+
+static int unlink_table(void *arg)
+{
+	struct unlink_table_info *info = arg;
+	struct unwind_table *table = info->table, *prev;
+
+	for (prev = &root_table; prev->link && prev->link != table;
+	     prev = prev->link)
+		;
+
+	if (prev->link) {
+		if (info->init_only) {
+			table->init.pc = 0;
+			table->init.range = 0;
+			info->table = NULL;
+		} else {
+			prev->link = table->link;
+			if (!prev->link)
+				last_table = prev;
+		}
+	} else
+		info->table = NULL;
+
+	return 0;
+}
+
+/* Must be called with module_mutex held. */
+void unwind_remove_table(void *handle, int init_only)
+{
+	struct unwind_table *table = handle;
+	struct unlink_table_info info;
+
+	if (!table || table == &root_table)
+		return;
+
+	if (init_only && table == last_table) {
+		table->init.pc = 0;
+		table->init.range = 0;
+		return;
+	}
+
+	info.table = table;
+	info.init_only = init_only;
+
+	unlink_table(&info); /* XXX: SMP */
+	kfree(table);
+}
+
+#endif /* CONFIG_MODULES */
+
+static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
+{
+	const u8 *cur = *pcur;
+	uleb128_t value;
+	unsigned shift;
+
+	for (shift = 0, value = 0; cur < end; shift += 7) {
+		if (shift + 7 > 8 * sizeof(value)
+		    && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
+			cur = end + 1;
+			break;
+		}
+		value |= (uleb128_t) (*cur & 0x7f) << shift;
+		if (!(*cur++ & 0x80))
+			break;
+	}
+	*pcur = cur;
+
+	return value;
+}
+
+static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
+{
+	const u8 *cur = *pcur;
+	sleb128_t value;
+	unsigned shift;
+
+	for (shift = 0, value = 0; cur < end; shift += 7) {
+		if (shift + 7 > 8 * sizeof(value)
+		    && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
+			cur = end + 1;
+			break;
+		}
+		value |= (sleb128_t) (*cur & 0x7f) << shift;
+		if (!(*cur & 0x80)) {
+			value |= -(*cur++ & 0x40) << shift;
+			break;
+		}
+	}
+	*pcur = cur;
+
+	return value;
+}
+
+static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table)
+{
+	const u32 *cie;
+
+	if (!*fde || (*fde & (sizeof(*fde) - 1)))
+		return &bad_cie;
+
+	if (fde[1] == 0xffffffff)
+		return &not_fde;	/* this is a CIE */
+
+	if ((fde[1] & (sizeof(*fde) - 1)))
+/* || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address) */
+		return NULL;	/* this is not a valid FDE */
+
+	/* cie = fde + 1 - fde[1] / sizeof(*fde); */
+	cie = (u32 *) fde[1];
+
+	if (*cie <= sizeof(*cie) + 4 || *cie >= fde[1] - sizeof(*fde)
+	    || (*cie & (sizeof(*cie) - 1))
+	    || (cie[1] != 0xffffffff))
+		return NULL;	/* this is not a (valid) CIE */
+	return cie;
+}
+
+static unsigned long read_pointer(const u8 **pLoc, const void *end,
+				  signed ptrType)
+{
+	unsigned long value = 0;
+	union {
+		const u8 *p8;
+		const u16 *p16u;
+		const s16 *p16s;
+		const u32 *p32u;
+		const s32 *p32s;
+		const unsigned long *pul;
+	} ptr;
+
+	if (ptrType < 0 || ptrType == DW_EH_PE_omit)
+		return 0;
+	ptr.p8 = *pLoc;
+	switch (ptrType & DW_EH_PE_FORM) {
+	case DW_EH_PE_data2:
+		if (end < (const void *)(ptr.p16u + 1))
+			return 0;
+		if (ptrType & DW_EH_PE_signed)
+			value = get_unaligned((u16 *) ptr.p16s++);
+		else
+			value = get_unaligned((u16 *) ptr.p16u++);
+		break;
+	case DW_EH_PE_data4:
+#ifdef CONFIG_64BIT
+		if (end < (const void *)(ptr.p32u + 1))
+			return 0;
+		if (ptrType & DW_EH_PE_signed)
+			value = get_unaligned(ptr.p32s++);
+		else
+			value = get_unaligned(ptr.p32u++);
+		break;
+	case DW_EH_PE_data8:
+		BUILD_BUG_ON(sizeof(u64) != sizeof(value));
+#else
+		BUILD_BUG_ON(sizeof(u32) != sizeof(value));
+#endif
+	case DW_EH_PE_native:
+		if (end < (const void *)(ptr.pul + 1))
+			return 0;
+		value = get_unaligned((unsigned long *)ptr.pul++);
+		break;
+	case DW_EH_PE_leb128:
+		BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
+		value = ptrType & DW_EH_PE_signed ? get_sleb128(&ptr.p8, end)
+		    : get_uleb128(&ptr.p8, end);
+		if ((const void *)ptr.p8 > end)
+			return 0;
+		break;
+	default:
+		return 0;
+	}
+	switch (ptrType & DW_EH_PE_ADJUST) {
+	case DW_EH_PE_abs:
+		break;
+	case DW_EH_PE_pcrel:
+		value += (unsigned long)*pLoc;
+		break;
+	default:
+		return 0;
+	}
+	if ((ptrType & DW_EH_PE_indirect)
+	    && __get_user(value, (unsigned long __user *)value))
+		return 0;
+	*pLoc = ptr.p8;
+
+	return value;
+}
+
+static signed fde_pointer_type(const u32 *cie)
+{
+	const u8 *ptr = (const u8 *)(cie + 2);
+	unsigned version = *ptr;
+
+	if (version != 1)
+		return -1;	/* unsupported */
+
+	if (*++ptr) {
+		const char *aug;
+		const u8 *end = (const u8 *)(cie + 1) + *cie;
+		uleb128_t len;
+
+		/* check if augmentation size is first (and thus present) */
+		if (*ptr != 'z')
+			return -1;
+
+		/* check if augmentation string is nul-terminated */
+		aug = (const void *)ptr;
+		ptr = memchr(aug, 0, end - ptr);
+		if (ptr == NULL)
+			return -1;
+
+		++ptr;		/* skip terminator */
+		get_uleb128(&ptr, end);	/* skip code alignment */
+		get_sleb128(&ptr, end);	/* skip data alignment */
+		/* skip return address column */
+		version <= 1 ? (void) ++ptr : (void)get_uleb128(&ptr, end);
+		len = get_uleb128(&ptr, end);	/* augmentation length */
+
+		if (ptr + len < ptr || ptr + len > end)
+			return -1;
+
+		end = ptr + len;
+		while (*++aug) {
+			if (ptr >= end)
+				return -1;
+			switch (*aug) {
+			case 'L':
+				++ptr;
+				break;
+			case 'P':{
+					signed ptrType = *ptr++;
+
+					if (!read_pointer(&ptr, end, ptrType)
+					    || ptr > end)
+						return -1;
+				}
+				break;
+			case 'R':
+				return *ptr;
+			default:
+				return -1;
+			}
+		}
+	}
+	return DW_EH_PE_native | DW_EH_PE_abs;
+}
+
+static int advance_loc(unsigned long delta, struct unwind_state *state)
+{
+	state->loc += delta * state->codeAlign;
+
+	/* FIXME_Rajesh: Probably we are defining for the initial range as well;
+	   return delta > 0;
+	 */
+	unw_debug("delta %3lu => loc 0x%lx: ", delta, state->loc);
+	return 1;
+}
+
+static void set_rule(uleb128_t reg, enum item_location where, uleb128_t value,
+		     struct unwind_state *state)
+{
+	if (reg < ARRAY_SIZE(state->regs)) {
+		state->regs[reg].where = where;
+		state->regs[reg].value = value;
+
+#ifdef UNWIND_DEBUG
+		unw_debug("r%lu: ", reg);
+		switch (where) {
+		case Nowhere:
+			unw_debug("s ");
+			break;
+		case Memory:
+			unw_debug("c(%lu) ", value);
+			break;
+		case Register:
+			unw_debug("r(%lu) ", value);
+			break;
+		case Value:
+			unw_debug("v(%lu) ", value);
+			break;
+		default:
+			break;
+		}
+#endif
+	}
+}
+
+static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc,
+		      signed ptrType, struct unwind_state *state)
+{
+	union {
+		const u8 *p8;
+		const u16 *p16;
+		const u32 *p32;
+	} ptr;
+	int result = 1;
+	u8 opcode;
+
+	if (start != state->cieStart) {
+		state->loc = state->org;
+		result =
+		    processCFI(state->cieStart, state->cieEnd, 0, ptrType,
+			       state);
+		if (targetLoc == 0 && state->label == NULL)
+			return result;
+	}
+	for (ptr.p8 = start; result && ptr.p8 < end;) {
+		switch (*ptr.p8 >> 6) {
+			uleb128_t value;
+
+		case 0:
+			opcode = *ptr.p8++;
+
+			switch (opcode) {
+			case DW_CFA_nop:
+				unw_debug("cfa nop ");
+				break;
+			case DW_CFA_set_loc:
+				state->loc = read_pointer(&ptr.p8, end,
+							  ptrType);
+				if (state->loc == 0)
+					result = 0;
+				unw_debug("cfa_set_loc: 0x%lx ", state->loc);
+				break;
+			case DW_CFA_advance_loc1:
+				unw_debug("\ncfa advance loc1:");
+				result = ptr.p8 < end
+				    && advance_loc(*ptr.p8++, state);
+				break;
+			case DW_CFA_advance_loc2:
+				value = *ptr.p8++;
+				value += *ptr.p8++ << 8;
+				unw_debug("\ncfa advance loc2:");
+				result = ptr.p8 <= end + 2
+				    /* && advance_loc(*ptr.p16++, state); */
+				    && advance_loc(value, state);
+				break;
+			case DW_CFA_advance_loc4:
+				unw_debug("\ncfa advance loc4:");
+				result = ptr.p8 <= end + 4
+				    && advance_loc(*ptr.p32++, state);
+				break;
+			case DW_CFA_offset_extended:
+				value = get_uleb128(&ptr.p8, end);
+				unw_debug("cfa_offset_extended: ");
+				set_rule(value, Memory,
+					 get_uleb128(&ptr.p8, end), state);
+				break;
+			case DW_CFA_val_offset:
+				value = get_uleb128(&ptr.p8, end);
+				set_rule(value, Value,
+					 get_uleb128(&ptr.p8, end), state);
+				break;
+			case DW_CFA_offset_extended_sf:
+				value = get_uleb128(&ptr.p8, end);
+				set_rule(value, Memory,
+					 get_sleb128(&ptr.p8, end), state);
+				break;
+			case DW_CFA_val_offset_sf:
+				value = get_uleb128(&ptr.p8, end);
+				set_rule(value, Value,
+					 get_sleb128(&ptr.p8, end), state);
+				break;
+			case DW_CFA_restore_extended:
+				unw_debug("cfa_restore_extended: ");
+			case DW_CFA_undefined:
+				unw_debug("cfa_undefined: ");
+			case DW_CFA_same_value:
+				unw_debug("cfa_same_value: ");
+				set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0,
+					 state);
+				break;
+			case DW_CFA_register:
+				unw_debug("cfa_register: ");
+				value = get_uleb128(&ptr.p8, end);
+				set_rule(value,
+					 Register,
+					 get_uleb128(&ptr.p8, end), state);
+				break;
+			case DW_CFA_remember_state:
+				unw_debug("cfa_remember_state: ");
+				if (ptr.p8 == state->label) {
+					state->label = NULL;
+					return 1;
+				}
+				if (state->stackDepth >= MAX_STACK_DEPTH)
+					return 0;
+				state->stack[state->stackDepth++] = ptr.p8;
+				break;
+			case DW_CFA_restore_state:
+				unw_debug("cfa_restore_state: ");
+				if (state->stackDepth) {
+					const uleb128_t loc = state->loc;
+					const u8 *label = state->label;
+
+					state->label =
+					    state->stack[state->stackDepth - 1];
+					memcpy(&state->cfa, &badCFA,
+					       sizeof(state->cfa));
+					memset(state->regs, 0,
+					       sizeof(state->regs));
+					state->stackDepth = 0;
+					result =
+					    processCFI(start, end, 0, ptrType,
+						       state);
+					state->loc = loc;
+					state->label = label;
+				} else
+					return 0;
+				break;
+			case DW_CFA_def_cfa:
+				state->cfa.reg = get_uleb128(&ptr.p8, end);
+				unw_debug("cfa_def_cfa: r%lu ", state->cfa.reg);
+				/*nobreak*/
+			case DW_CFA_def_cfa_offset:
+				state->cfa.offs = get_uleb128(&ptr.p8, end);
+				unw_debug("cfa_def_cfa_offset: 0x%lx ",
+					  state->cfa.offs);
+				break;
+			case DW_CFA_def_cfa_sf:
+				state->cfa.reg = get_uleb128(&ptr.p8, end);
+				/*nobreak */
+			case DW_CFA_def_cfa_offset_sf:
+				state->cfa.offs = get_sleb128(&ptr.p8, end)
+				    * state->dataAlign;
+				break;
+			case DW_CFA_def_cfa_register:
+				unw_debug("cfa_def_cfa_regsiter: ");
+				state->cfa.reg = get_uleb128(&ptr.p8, end);
+				break;
+				/*todo case DW_CFA_def_cfa_expression: */
+				/*todo case DW_CFA_expression: */
+				/*todo case DW_CFA_val_expression: */
+			case DW_CFA_GNU_args_size:
+				get_uleb128(&ptr.p8, end);
+				break;
+			case DW_CFA_GNU_negative_offset_extended:
+				value = get_uleb128(&ptr.p8, end);
+				set_rule(value,
+					 Memory,
+					 (uleb128_t) 0 - get_uleb128(&ptr.p8,
+								     end),
+					 state);
+				break;
+			case DW_CFA_GNU_window_save:
+			default:
+				unw_debug("UNKNOW OPCODE 0x%x\n", opcode);
+				result = 0;
+				break;
+			}
+			break;
+		case 1:
+			unw_debug("\ncfa_adv_loc: ");
+			result = advance_loc(*ptr.p8++ & 0x3f, state);
+			break;
+		case 2:
+			unw_debug("cfa_offset: ");
+			value = *ptr.p8++ & 0x3f;
+			set_rule(value, Memory, get_uleb128(&ptr.p8, end),
+				 state);
+			break;
+		case 3:
+			unw_debug("cfa_restore: ");
+			set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
+			break;
+		}
+
+		if (ptr.p8 > end)
+			result = 0;
+		if (result && targetLoc != 0 && targetLoc < state->loc)
+			return 1;
+	}
+
+	return result && ptr.p8 == end && (targetLoc == 0 || (
+		/*todo While in theory this should apply, gcc in practice omits
+		  everything past the function prolog, and hence the location
+		  never reaches the end of the function.
+		targetLoc < state->loc && */  state->label == NULL));
+}
+
+/* Unwind to previous to frame.  Returns 0 if successful, negative
+ * number in case of an error. */
+int arc_unwind(struct unwind_frame_info *frame)
+{
+#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
+	const u32 *fde = NULL, *cie = NULL;
+	const u8 *ptr = NULL, *end = NULL;
+	unsigned long pc = UNW_PC(frame) - frame->call_frame;
+	unsigned long startLoc = 0, endLoc = 0, cfa;
+	unsigned i;
+	signed ptrType = -1;
+	uleb128_t retAddrReg = 0;
+	const struct unwind_table *table;
+	struct unwind_state state;
+	unsigned long *fptr;
+	unsigned long addr;
+
+	unw_debug("\n\nUNWIND FRAME:\n");
+	unw_debug("PC: 0x%lx BLINK: 0x%lx, SP: 0x%lx, FP: 0x%x\n",
+		  UNW_PC(frame), UNW_BLINK(frame), UNW_SP(frame),
+		  UNW_FP(frame));
+
+	if (UNW_PC(frame) == 0)
+		return -EINVAL;
+
+#ifdef UNWIND_DEBUG
+	{
+		unsigned long *sptr = (unsigned long *)UNW_SP(frame);
+		unw_debug("\nStack Dump:\n");
+		for (i = 0; i < 20; i++, sptr++)
+			unw_debug("0x%p:  0x%lx\n", sptr, *sptr);
+		unw_debug("\n");
+	}
+#endif
+
+	table = find_table(pc);
+	if (table != NULL
+	    && !(table->size & (sizeof(*fde) - 1))) {
+		const u8 *hdr = table->header;
+		unsigned long tableSize;
+
+		smp_rmb();
+		if (hdr && hdr[0] == 1) {
+			switch (hdr[3] & DW_EH_PE_FORM) {
+			case DW_EH_PE_native:
+				tableSize = sizeof(unsigned long);
+				break;
+			case DW_EH_PE_data2:
+				tableSize = 2;
+				break;
+			case DW_EH_PE_data4:
+				tableSize = 4;
+				break;
+			case DW_EH_PE_data8:
+				tableSize = 8;
+				break;
+			default:
+				tableSize = 0;
+				break;
+			}
+			ptr = hdr + 4;
+			end = hdr + table->hdrsz;
+			if (tableSize && read_pointer(&ptr, end, hdr[1])
+			    == (unsigned long)table->address
+			    && (i = read_pointer(&ptr, end, hdr[2])) > 0
+			    && i == (end - ptr) / (2 * tableSize)
+			    && !((end - ptr) % (2 * tableSize))) {
+				do {
+					const u8 *cur =
+					    ptr + (i / 2) * (2 * tableSize);
+
+					startLoc = read_pointer(&cur,
+								cur + tableSize,
+								hdr[3]);
+					if (pc < startLoc)
+						i /= 2;
+					else {
+						ptr = cur - tableSize;
+						i = (i + 1) / 2;
+					}
+				} while (startLoc && i > 1);
+				if (i == 1
+				    && (startLoc = read_pointer(&ptr,
+								ptr + tableSize,
+								hdr[3])) != 0
+				    && pc >= startLoc)
+					fde = (void *)read_pointer(&ptr,
+								   ptr +
+								   tableSize,
+								   hdr[3]);
+			}
+		}
+
+		if (fde != NULL) {
+			cie = cie_for_fde(fde, table);
+			ptr = (const u8 *)(fde + 2);
+			if (cie != NULL
+			    && cie != &bad_cie
+			    && cie != &not_fde
+			    && (ptrType = fde_pointer_type(cie)) >= 0
+			    && read_pointer(&ptr,
+					    (const u8 *)(fde + 1) + *fde,
+					    ptrType) == startLoc) {
+				if (!(ptrType & DW_EH_PE_indirect))
+					ptrType &=
+					    DW_EH_PE_FORM | DW_EH_PE_signed;
+				endLoc =
+				    startLoc + read_pointer(&ptr,
+							    (const u8 *)(fde +
+									 1) +
+							    *fde, ptrType);
+				if (pc >= endLoc)
+					fde = NULL;
+			} else
+				fde = NULL;
+		}
+		if (fde == NULL) {
+			for (fde = table->address, tableSize = table->size;
+			     cie = NULL, tableSize > sizeof(*fde)
+			     && tableSize - sizeof(*fde) >= *fde;
+			     tableSize -= sizeof(*fde) + *fde,
+			     fde += 1 + *fde / sizeof(*fde)) {
+				cie = cie_for_fde(fde, table);
+				if (cie == &bad_cie) {
+					cie = NULL;
+					break;
+				}
+				if (cie == NULL
+				    || cie == &not_fde
+				    || (ptrType = fde_pointer_type(cie)) < 0)
+					continue;
+				ptr = (const u8 *)(fde + 2);
+				startLoc = read_pointer(&ptr,
+							(const u8 *)(fde + 1) +
+							*fde, ptrType);
+				if (!startLoc)
+					continue;
+				if (!(ptrType & DW_EH_PE_indirect))
+					ptrType &=
+					    DW_EH_PE_FORM | DW_EH_PE_signed;
+				endLoc =
+				    startLoc + read_pointer(&ptr,
+							    (const u8 *)(fde +
+									 1) +
+							    *fde, ptrType);
+				if (pc >= startLoc && pc < endLoc)
+					break;
+			}
+		}
+	}
+	if (cie != NULL) {
+		memset(&state, 0, sizeof(state));
+		state.cieEnd = ptr;	/* keep here temporarily */
+		ptr = (const u8 *)(cie + 2);
+		end = (const u8 *)(cie + 1) + *cie;
+		frame->call_frame = 1;
+		if ((state.version = *ptr) != 1)
+			cie = NULL;	/* unsupported version */
+		else if (*++ptr) {
+			/* check if augmentation size is first (thus present) */
+			if (*ptr == 'z') {
+				while (++ptr < end && *ptr) {
+					switch (*ptr) {
+					/* chk for ignorable or already handled
+					 * nul-terminated augmentation string */
+					case 'L':
+					case 'P':
+					case 'R':
+						continue;
+					case 'S':
+						frame->call_frame = 0;
+						continue;
+					default:
+						break;
+					}
+					break;
+				}
+			}
+			if (ptr >= end || *ptr)
+				cie = NULL;
+		}
+		++ptr;
+	}
+	if (cie != NULL) {
+		/* get code aligment factor */
+		state.codeAlign = get_uleb128(&ptr, end);
+		/* get data aligment factor */
+		state.dataAlign = get_sleb128(&ptr, end);
+		if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
+			cie = NULL;
+		else {
+			retAddrReg =
+			    state.version <= 1 ? *ptr++ : get_uleb128(&ptr,
+								      end);
+			unw_debug("CIE Frame Info:\n");
+			unw_debug("return Address register 0x%lx\n",
+				  retAddrReg);
+			unw_debug("data Align: %ld\n", state.dataAlign);
+			unw_debug("code Align: %lu\n", state.codeAlign);
+			/* skip augmentation */
+			if (((const char *)(cie + 2))[1] == 'z') {
+				uleb128_t augSize = get_uleb128(&ptr, end);
+
+				ptr += augSize;
+			}
+			if (ptr > end || retAddrReg >= ARRAY_SIZE(reg_info)
+			    || REG_INVALID(retAddrReg)
+			    || reg_info[retAddrReg].width !=
+			    sizeof(unsigned long))
+				cie = NULL;
+		}
+	}
+	if (cie != NULL) {
+		state.cieStart = ptr;
+		ptr = state.cieEnd;
+		state.cieEnd = end;
+		end = (const u8 *)(fde + 1) + *fde;
+		/* skip augmentation */
+		if (((const char *)(cie + 2))[1] == 'z') {
+			uleb128_t augSize = get_uleb128(&ptr, end);
+
+			if ((ptr += augSize) > end)
+				fde = NULL;
+		}
+	}
+	if (cie == NULL || fde == NULL) {
+#ifdef CONFIG_FRAME_POINTER
+		unsigned long top, bottom;
+
+		top = STACK_TOP_UNW(frame->task);
+		bottom = STACK_BOTTOM_UNW(frame->task);
+#if FRAME_RETADDR_OFFSET < 0
+		if (UNW_SP(frame) < top && UNW_FP(frame) <= UNW_SP(frame)
+		    && bottom < UNW_FP(frame)
+#else
+		if (UNW_SP(frame) > top && UNW_FP(frame) >= UNW_SP(frame)
+		    && bottom > UNW_FP(frame)
+#endif
+		    && !((UNW_SP(frame) | UNW_FP(frame))
+			 & (sizeof(unsigned long) - 1))) {
+			unsigned long link;
+
+			if (!__get_user(link, (unsigned long *)
+					(UNW_FP(frame) + FRAME_LINK_OFFSET))
+#if FRAME_RETADDR_OFFSET < 0
+			    && link > bottom && link < UNW_FP(frame)
+#else
+			    && link > UNW_FP(frame) && link < bottom
+#endif
+			    && !(link & (sizeof(link) - 1))
+			    && !__get_user(UNW_PC(frame),
+					   (unsigned long *)(UNW_FP(frame)
+						+ FRAME_RETADDR_OFFSET)))
+			{
+				UNW_SP(frame) =
+				    UNW_FP(frame) + FRAME_RETADDR_OFFSET
+#if FRAME_RETADDR_OFFSET < 0
+				    -
+#else
+				    +
+#endif
+				    sizeof(UNW_PC(frame));
+				UNW_FP(frame) = link;
+				return 0;
+			}
+		}
+#endif
+		return -ENXIO;
+	}
+	state.org = startLoc;
+	memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
+
+	unw_debug("\nProcess instructions\n");
+
+	/* process instructions
+	 * For ARC, we optimize by having blink(retAddrReg) with
+	 * the sameValue in the leaf function, so we should not check
+	 * state.regs[retAddrReg].where == Nowhere
+	 */
+	if (!processCFI(ptr, end, pc, ptrType, &state)
+	    || state.loc > endLoc
+/*	   || state.regs[retAddrReg].where == Nowhere */
+	    || state.cfa.reg >= ARRAY_SIZE(reg_info)
+	    || reg_info[state.cfa.reg].width != sizeof(unsigned long)
+	    || state.cfa.offs % sizeof(unsigned long))
+		return -EIO;
+
+#ifdef UNWIND_DEBUG
+	unw_debug("\n");
+
+	unw_debug("\nRegister State Based on the rules parsed from FDE:\n");
+	for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
+
+		if (REG_INVALID(i))
+			continue;
+
+		switch (state.regs[i].where) {
+		case Nowhere:
+			break;
+		case Memory:
+			unw_debug(" r%d: c(%lu),", i, state.regs[i].value);
+			break;
+		case Register:
+			unw_debug(" r%d: r(%lu),", i, state.regs[i].value);
+			break;
+		case Value:
+			unw_debug(" r%d: v(%lu),", i, state.regs[i].value);
+			break;
+		}
+	}
+
+	unw_debug("\n");
+#endif
+
+	/* update frame */
+#ifndef CONFIG_AS_CFI_SIGNAL_FRAME
+	if (frame->call_frame
+	    && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign))
+		frame->call_frame = 0;
+#endif
+	cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
+	startLoc = min_t(unsigned long, UNW_SP(frame), cfa);
+	endLoc = max_t(unsigned long, UNW_SP(frame), cfa);
+	if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
+		startLoc = min(STACK_LIMIT(cfa), cfa);
+		endLoc = max(STACK_LIMIT(cfa), cfa);
+	}
+
+	unw_debug("\nCFA reg: 0x%lx, offset: 0x%lx =>  0x%lx\n",
+		  state.cfa.reg, state.cfa.offs, cfa);
+
+	for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
+		if (REG_INVALID(i)) {
+			if (state.regs[i].where == Nowhere)
+				continue;
+			return -EIO;
+		}
+		switch (state.regs[i].where) {
+		default:
+			break;
+		case Register:
+			if (state.regs[i].value >= ARRAY_SIZE(reg_info)
+			    || REG_INVALID(state.regs[i].value)
+			    || reg_info[i].width >
+			    reg_info[state.regs[i].value].width)
+				return -EIO;
+			switch (reg_info[state.regs[i].value].width) {
+			case sizeof(u8):
+				state.regs[i].value =
+				FRAME_REG(state.regs[i].value, const u8);
+				break;
+			case sizeof(u16):
+				state.regs[i].value =
+				FRAME_REG(state.regs[i].value, const u16);
+				break;
+			case sizeof(u32):
+				state.regs[i].value =
+				FRAME_REG(state.regs[i].value, const u32);
+				break;
+#ifdef CONFIG_64BIT
+			case sizeof(u64):
+				state.regs[i].value =
+				FRAME_REG(state.regs[i].value, const u64);
+				break;
+#endif
+			default:
+				return -EIO;
+			}
+			break;
+		}
+	}
+
+	unw_debug("\nRegister state after evaluation with realtime Stack:\n");
+	fptr = (unsigned long *)(&frame->regs);
+	for (i = 0; i < ARRAY_SIZE(state.regs); ++i, fptr++) {
+
+		if (REG_INVALID(i))
+			continue;
+		switch (state.regs[i].where) {
+		case Nowhere:
+			if (reg_info[i].width != sizeof(UNW_SP(frame))
+			    || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
+			    != &UNW_SP(frame))
+				continue;
+			UNW_SP(frame) = cfa;
+			break;
+		case Register:
+			switch (reg_info[i].width) {
+			case sizeof(u8):
+				FRAME_REG(i, u8) = state.regs[i].value;
+				break;
+			case sizeof(u16):
+				FRAME_REG(i, u16) = state.regs[i].value;
+				break;
+			case sizeof(u32):
+				FRAME_REG(i, u32) = state.regs[i].value;
+				break;
+#ifdef CONFIG_64BIT
+			case sizeof(u64):
+				FRAME_REG(i, u64) = state.regs[i].value;
+				break;
+#endif
+			default:
+				return -EIO;
+			}
+			break;
+		case Value:
+			if (reg_info[i].width != sizeof(unsigned long))
+				return -EIO;
+			FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
+			    * state.dataAlign;
+			break;
+		case Memory:
+			addr = cfa + state.regs[i].value * state.dataAlign;
+
+			if ((state.regs[i].value * state.dataAlign)
+			    % sizeof(unsigned long)
+			    || addr < startLoc
+			    || addr + sizeof(unsigned long) < addr
+			    || addr + sizeof(unsigned long) > endLoc)
+					return -EIO;
+
+			switch (reg_info[i].width) {
+			case sizeof(u8):
+				__get_user(FRAME_REG(i, u8),
+					   (u8 __user *)addr);
+				break;
+			case sizeof(u16):
+				__get_user(FRAME_REG(i, u16),
+					   (u16 __user *)addr);
+				break;
+			case sizeof(u32):
+				__get_user(FRAME_REG(i, u32),
+					   (u32 __user *)addr);
+				break;
+#ifdef CONFIG_64BIT
+			case sizeof(u64):
+				__get_user(FRAME_REG(i, u64),
+					   (u64 __user *)addr);
+				break;
+#endif
+			default:
+				return -EIO;
+			}
+
+			break;
+		}
+		unw_debug("r%d: 0x%lx ", i, *fptr);
+	}
+
+	return 0;
+#undef FRAME_REG
+}
+EXPORT_SYMBOL(arc_unwind);
diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
index 8c72bc3..303ea01 100644
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -100,17 +100,38 @@ SECTIONS
 
 	BSS_SECTION(0, 0, 0)
 
+#ifdef CONFIG_ARC_DW2_UNWIND
+	. = ALIGN(PAGE_SIZE);
+	.debug_frame  : {
+		__start_unwind = .;
+		*(.debug_frame)
+		__end_unwind = .;
+	}
+#else
+	/DISCARD/ : {	*(.debug_frame) }
+#endif
+
 	NOTES
 
 	. = ALIGN(PAGE_SIZE);
 	_end = . ;
 
 	STABS_DEBUG
-	DWARF_DEBUG
 	DISCARDS
 
 	.arcextmap 0 : {
 		*(.gnu.linkonce.arcextmap.*)
 		*(.arcextmap.*)
 	}
+
+	/* open-coded because we need .debug_frame seperately for unwinding */
+	.debug_aranges 0 : { *(.debug_aranges) }
+	.debug_pubnames 0 : { *(.debug_pubnames) }
+	.debug_info 0 : { *(.debug_info) }
+	.debug_abbrev 0 : { *(.debug_abbrev) }
+	.debug_line 0 : { *(.debug_line) }
+	.debug_str 0 : { *(.debug_str) }
+	.debug_loc 0 : { *(.debug_loc) }
+	.debug_macinfo 0 : { *(.debug_macinfo) }
+
 }
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCH v3 02/71] ARC: Build system: Makefiles, Kconfig, Linker script
  2013-01-24 10:50 ` [PATCH v3 02/71] ARC: Build system: Makefiles, Kconfig, Linker script Vineet Gupta
@ 2013-01-28  6:29   ` Vineet Gupta
  2013-01-28 18:44     ` Sam Ravnborg
  2013-02-11 11:29   ` James Hogan
  1 sibling, 1 reply; 57+ messages in thread
From: Vineet Gupta @ 2013-01-28  6:29 UTC (permalink / raw)
  To: Sam Ravnborg; +Cc: linux-arch, linux-kernel, arnd

Hi Sam,

On Thursday 24 January 2013 04:20 PM, Vineet Gupta wrote:
> Arnd in his review pointed out that arch Kconfig organisation has several
> deficiencies:
> 
> * Build time entries for things which can be runtime extracted from DT
>   (e.g. SDRAM size, core clk frequency..)
> * Not multi-platform-image-build friendly (choice .. endchoice constructs)
> * cpu variants support (750/770) is exclusive.
> 
> The first 2 have been fixed in subsequent patches.
> Due to the nature of the 750 and 770, it is not possible to build for
> both together, w/o special runtime glue code which would hurt
> performance.
> 
> Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Sam Ravnborg <sam@ravnborg.org>
> ---
>  arch/arc/Kbuild                |    2 +
>  arch/arc/Kconfig               |  328 ++++++++++++++++++++++++++++++++++++++++
>  arch/arc/Kconfig.debug         |   34 ++++
>  arch/arc/Makefile              |  115 ++++++++++++++
>  arch/arc/boot/Makefile         |   26 +++
>  arch/arc/include/asm/Kbuild    |    1 +
>  arch/arc/kernel/Makefile       |   16 ++
>  arch/arc/kernel/arcksyms.c     |   56 +++++++
>  arch/arc/kernel/asm-offsets.c  |   46 ++++++
>  arch/arc/kernel/vmlinux.lds.S  |  116 ++++++++++++++
>  arch/arc/lib/Makefile          |    9 +
>  arch/arc/mm/Makefile           |   10 ++
>  arch/arc/plat-arcfpga/Kconfig  |   33 ++++
>  arch/arc/plat-arcfpga/Makefile |    9 +
>  14 files changed, 801 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arc/Kbuild
>  create mode 100644 arch/arc/Kconfig
>  create mode 100644 arch/arc/Kconfig.debug
>  create mode 100644 arch/arc/Makefile
>  create mode 100644 arch/arc/boot/Makefile
>  create mode 100644 arch/arc/kernel/Makefile
>  create mode 100644 arch/arc/kernel/arcksyms.c
>  create mode 100644 arch/arc/kernel/asm-offsets.c
>  create mode 100644 arch/arc/kernel/vmlinux.lds.S
>  create mode 100644 arch/arc/lib/Makefile
>  create mode 100644 arch/arc/mm/Makefile
>  create mode 100644 arch/arc/plat-arcfpga/Kconfig
>  create mode 100644 arch/arc/plat-arcfpga/Makefile
> 
> diff --git a/arch/arc/Kbuild b/arch/arc/Kbuild
> new file mode 100644
> index 0000000..082d329
> --- /dev/null
> +++ b/arch/arc/Kbuild
> @@ -0,0 +1,2 @@
> +obj-y += kernel/
> +obj-y += mm/
> diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
> new file mode 100644
> index 0000000..b0b09ae
> --- /dev/null
> +++ b/arch/arc/Kconfig
> @@ -0,0 +1,328 @@
> +#
> +# 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.
> +#
> +
> +config ARC
> +	def_bool y
> +	select ARCH_NO_VIRT_TO_BUS
> +	# ARC Busybox based initramfs absolutely relies on DEVTMPFS for /dev
> +	select DEVTMPFS if !INITRAMFS_SOURCE=""
> +	select GENERIC_ATOMIC64
> +	select GENERIC_CLOCKEVENTS
> +	select GENERIC_FIND_FIRST_BIT
> +	# for now, we don't need GENERIC_IRQ_PROBE, CONFIG_GENERIC_IRQ_CHIP
> +	select GENERIC_IRQ_SHOW
> +	select GENERIC_PENDING_IRQ if SMP
> +	select GENERIC_SMP_IDLE_THREAD
> +	select HAVE_GENERIC_HARDIRQS
> +	select MODULES_USE_ELF_RELA
> +
> +config SCHED_OMIT_FRAME_POINTER
> +	def_bool y
> +
> +config GENERIC_CSUM
> +	def_bool y
> +
> +config RWSEM_GENERIC_SPINLOCK
> +	def_bool y
> +
> +config ARCH_FLATMEM_ENABLE
> +	def_bool y
> +
> +config MMU
> +	def_bool y
> +
> +config NO_IOPORT
> +	def_bool y
> +
> +config GENERIC_CALIBRATE_DELAY
> +	def_bool y
> +
> +config GENERIC_HWEIGHT
> +	def_bool y
> +
> +config BINFMT_ELF
> +	def_bool y
> +
> +config HAVE_LATENCYTOP_SUPPORT
> +	def_bool y
> +
> +config NO_DMA
> +	def_bool n
> +
> +source "init/Kconfig"
> +source "kernel/Kconfig.freezer"
> +
> +menu "ARC Architecture Configuration"
> +
> +choice
> +	prompt "ARC Platform"
> +	default ARC_PLAT_FPGA_LEGACY
> +
> +config ARC_PLAT_FPGA_LEGACY
> +	bool "\"Legacy\" ARC FPGA dev platform"
> +	help
> +	  Support for ARC development platforms, provided by Synopsys.
> +	  These are based on FPGA or ISS. e.g.
> +	  - ARCAngel4
> +	  - ML509
> +	  - MetaWare ISS
> +
> +#New platform adds here
> +endchoice
> +
> +menu "ARC CPU Configuration"
> +
> +choice
> +	prompt "ARC Core"
> +	default ARC_CPU_770
> +
> +config ARC_CPU_750D
> +	bool "ARC750D"
> +	help
> +	  Support for ARC750 core
> +
> +config ARC_CPU_770
> +	bool "ARC770"
> +	select ARC_CPU_REL_4_10
> +	help
> +	  Support for ARC770 core introduced with Rel 4.10 (Summer 2011)
> +	  This core has a bunch of cool new features:
> +	  -MMU-v3: Variable Page Sz (4k, 8k, 16k), bigger J-TLB (128x4)
> +                   Shared Address Spaces (for sharing TLB entires in MMU)
> +	  -Caches: New Prog Model, Region Flush
> +	  -Insns: endian swap, load-locked/store-conditional, time-stamp-ctr
> +
> +endchoice
> +
> +config CPU_BIG_ENDIAN
> +	bool "Enable Big Endian Mode"
> +	default n
> +	help
> +	  Build kernel for Big Endian Mode of ARC CPU
> +
> +menuconfig ARC_CACHE
> +	bool "Enable Cache Support"
> +	default y
> +
> +if ARC_CACHE
> +
> +config ARC_CACHE_LINE_SHIFT
> +	int "Cache Line Length (as power of 2)"
> +	range 5 7
> +	default "6"
> +	help
> +	  Starting with ARC700 4.9, Cache line length is configurable,
> +	  This option specifies "N", with Line-len = 2 power N
> +	  So line lengths of 32, 64, 128 are specified by 5,6,7, respectively
> +	  Linux only supports same line lengths for I and D caches.
> +
> +config ARC_HAS_ICACHE
> +	bool "Use Instruction Cache"
> +	default y
> +
> +config ARC_HAS_DCACHE
> +	bool "Use Data Cache"
> +	default y
> +
> +config ARC_CACHE_PAGES
> +	bool "Per Page Cache Control"
> +	default y
> +	depends on ARC_HAS_ICACHE || ARC_HAS_DCACHE
> +	help
> +	  This can be used to over-ride the global I/D Cache Enable on a
> +	  per-page basis (but only for pages accessed via MMU such as
> +	  Kernel Virtual address or User Virtual Address)
> +	  TLB entries have a per-page Cache Enable Bit.
> +	  Note that Global I/D ENABLE + Per Page DISABLE works but corollary
> +	  Global DISABLE + Per Page ENABLE won't work
> +
> +endif	#ARC_CACHE
> +
> +config ARC_HAS_HW_MPY
> +	bool "Use Hardware Multiplier (Normal or Faster XMAC)"
> +	default y
> +	help
> +	  Influences how gcc generates code for MPY operations.
> +	  If enabled, MPYxx insns are generated, provided by Standard/XMAC
> +	  Multipler. Otherwise software multipy lib is used
> +
> +choice
> +	prompt "ARC700 MMU Version"
> +	default ARC_MMU_V3 if ARC_CPU_770
> +	default ARC_MMU_V2 if ARC_CPU_750D
> +
> +config ARC_MMU_V1
> +	bool "MMU v1"
> +	help
> +	  Orig ARC700 MMU
> +
> +config ARC_MMU_V2
> +	bool "MMU v2"
> +	help
> +	  Fixed the deficiency of v1 - possible thrashing in memcpy sceanrio
> +	  when 2 D-TLB and 1 I-TLB entries index into same 2way set.
> +
> +config ARC_MMU_V3
> +	bool "MMU v3"
> +	depends on ARC_CPU_770
> +	help
> +	  Introduced with ARC700 4.10: New Features
> +	  Variable Page size (1k-16k), var JTLB size 128 x (2 or 4)
> +	  Shared Address Spaces (SASID)
> +
> +endchoice
> +
> +
> +choice
> +	prompt "MMU Page Size"
> +	default ARC_PAGE_SIZE_8K
> +
> +config ARC_PAGE_SIZE_8K
> +	bool "8KB"
> +	help
> +	  Choose between 8k vs 16k
> +
> +config ARC_PAGE_SIZE_16K
> +	bool "16KB"
> +	depends on ARC_MMU_V3
> +
> +config ARC_PAGE_SIZE_4K
> +	bool "4KB"
> +	depends on ARC_MMU_V3
> +
> +endchoice
> +
> +config ARC_FPU_SAVE_RESTORE
> +	bool "Enable FPU state persistence across context switch"
> +	default n
> +	help
> +	  Double Precision Floating Point unit had dedictaed regs which
> +	  need to be saved/restored across context-switch.
> +	  Note that ARC FPU is overly simplistic, unlike say x86, which has
> +	  hardware pieces to allow software to conditionally save/restore,
> +	  based on actual usage of FPU by a task. Thus our implemn does
> +	  this for all tasks in system.
> +
> +menuconfig ARC_CPU_REL_4_10
> +	bool "Enable support for Rel 4.10 features"
> +	default n
> +	help
> +	  -ARC770 (and dependent features) enabled
> +	  -ARC750 also shares some of the new features with 770
> +
> +config ARC_HAS_LLSC
> +	bool "Insn: LLOCK/SCOND (efficient atomic ops)"
> +	default y
> +	depends on ARC_CPU_770
> +	# if SMP, enable LLSC ONLY if ARC implementation has coherent atomics
> +	depends on !SMP || ARC_HAS_COH_LLSC
> +
> +config ARC_HAS_SWAPE
> +	bool "Insn: SWAPE (endian-swap)"
> +	default y
> +	depends on ARC_CPU_REL_4_10
> +
> +config ARC_HAS_RTSC
> +	bool "Insn: RTSC (64-bit r/o cycle counter)"
> +	default y
> +	depends on ARC_CPU_REL_4_10
> +
> +endmenu   # "ARC CPU Configuration"
> +
> +menu "Platform Board Configuration"
> +
> +source "arch/arc/plat-arcfpga/Kconfig"
> +
> +#New platform adds here
> +
> +config ARC_PLAT_CLK
> +	int "Clk speed in Hz"
> +	default "80000000"
> +
> +config LINUX_LINK_BASE
> +	hex "Linux Link Address"
> +	default "0x80000000"
> +	help
> +	  ARC700 divides the 32 bit phy address space into two equal halves
> +	  -Lower 2G (0 - 0x7FFF_FFFF ) is user virtual, translated by MMU
> +	  -Upper 2G (0x8000_0000 onwards) is untranslated, for kernel
> +	  Typically Linux kernel is linked at the start of untransalted addr,
> +	  hence the default value of 0x8zs.
> +	  However some customers have peripherals mapped at this addr, so
> +	  Linux needs to be scooted a bit.
> +	  If you don't know what the above means, leave this setting alone.
> +
> +config ARC_PLAT_SDRAM_SIZE
> +	hex "SD RAM Size"
> +	default "0x10000000"
> +	help
> +	  Implies the amount of SDRAM/DRAM Linux is going to claim/own.
> +	  The actual memory itself could be larger than this number. But for
> +	  all software purposes, this is the amt of memory.
> +
> +endmenu # "Platform Board Configuration"
> +
> +config ARC_STACK_NONEXEC
> +	bool "Make stack non-executable"
> +	default n
> +	help
> +	  To disable the execute permissions of stack/heap of processes
> +	  which are enabled by default.
> +
> +config HZ
> +	int "Timer Frequency"
> +	default 100
> +
> +menuconfig ARC_DBG
> +	bool "ARC debugging"
> +	default y
> +
> +config ARC_DBG_TLB_PARANOIA
> +	bool "Paranoia Checks in Low Level TLB Handlers"
> +	depends on ARC_DBG
> +	default n
> +
> +config ARC_DBG_TLB_MISS_COUNT
> +	bool "Profile TLB Misses"
> +	default n
> +	select DEBUG_FS
> +	depends on ARC_DBG
> +	help
> +	  Counts number of I and D TLB Misses and exports them via Debugfs
> +	  The counters can be cleared via Debugfs as well
> +
> +config CMDLINE
> +	string "Kernel command line to built-in"
> +	default "print-fatal-signals=1"
> +	help
> +	  The default command line which will be appended to the optional
> +	  u-boot provided command line (see below)
> +
> +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 copy the string into cmdline buffer
> +	  and also append CONFIG_CMDLINE.
> +
> +source "kernel/Kconfig.preempt"
> +
> +endmenu	 # "ARC Architecture Configuration"
> +
> +source "mm/Kconfig"
> +source "net/Kconfig"
> +source "drivers/Kconfig"
> +source "fs/Kconfig"
> +source "arch/arc/Kconfig.debug"
> +source "security/Kconfig"
> +source "crypto/Kconfig"
> +source "lib/Kconfig"
> diff --git a/arch/arc/Kconfig.debug b/arch/arc/Kconfig.debug
> new file mode 100644
> index 0000000..962c609
> --- /dev/null
> +++ b/arch/arc/Kconfig.debug
> @@ -0,0 +1,34 @@
> +menu "Kernel hacking"
> +
> +source "lib/Kconfig.debug"
> +
> +config EARLY_PRINTK
> +	bool "Early printk" if EMBEDDED
> +	default y
> +	help
> +	  Write kernel log output directly into the VGA buffer or to a serial
> +	  port.
> +
> +	  This is useful for kernel debugging when your machine crashes very
> +	  early before the console code is initialized. For normal operation
> +	  it is not recommended because it looks ugly and doesn't cooperate
> +	  with klogd/syslogd or the X server. You should normally N here,
> +	  unless you want to debug such a crash.
> +
> +config DEBUG_STACKOVERFLOW
> +	bool "Check for stack overflows"
> +	depends on DEBUG_KERNEL
> +	help
> +	  This option will cause messages to be printed if free stack space
> +	  drops below a certain limit.
> +
> +config 16KSTACKS
> +	bool "Use 16Kb for kernel stacks instead of 8Kb"
> +	help
> +	  If you say Y here the kernel will use a  16Kb stacksize for the
> +	  kernel stack attached to each process/thread. The default is 8K.
> +	  This increases the resident kernel footprint and will cause less
> +	  threads to run on the system and also increase the pressure
> +	  on the VM subsystem for higher order allocations.
> +
> +endmenu
> diff --git a/arch/arc/Makefile b/arch/arc/Makefile
> new file mode 100644
> index 0000000..4d52a3b
> --- /dev/null
> +++ b/arch/arc/Makefile
> @@ -0,0 +1,115 @@
> +#
> +# 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.
> +#
> +
> +UTS_MACHINE := arc
> +
> +KBUILD_DEFCONFIG := fpga_defconfig
> +
> +# For ARC FPGA Platforms
> +platform-$(CONFIG_ARC_PLAT_FPGA_LEGACY)	:= arcfpga
> +#New platform adds here
> +
> +PLATFORM := $(platform-y)
> +export PLATFORM
> +
> +cflags-y	+= -Iarch/arc/plat-$(PLATFORM)/include
> +cflags-y	+= -mA7 -fno-common -pipe -fno-builtin -D__linux__
> +
> +atleast_gcc44 :=  $(call cc-ifversion, -gt, 0402, y)
> +cflags-$(atleast_gcc44)			+= -fsection-anchors
> +
> +cflags-$(CONFIG_ARC_HAS_LLSC)		+= -mlock
> +cflags-$(CONFIG_ARC_HAS_SWAPE)		+= -mswape
> +cflags-$(CONFIG_ARC_HAS_RTSC)		+= -mrtsc
> +cflags-$(CONFIG_ARC_DW2_UNWIND)		+= -fasynchronous-unwind-tables
> +
> +ifndef CONFIG_CC_OPTIMIZE_FOR_SIZE
> +# Generic build system uses -O2, we want -O3
> +cflags-y  += -O3
> +endif
> +
> +# small data is default for elf32 tool-chain. If not usable, disable it
> +# This also allows repurposing GP as scratch reg to gcc reg allocator
> +disable_small_data := y
> +cflags-$(disable_small_data)		+= -mno-sdata -fcall-used-gp
> +
> +cflags-$(CONFIG_CPU_BIG_ENDIAN)		+= -mbig-endian
> +ldflags-$(CONFIG_CPU_BIG_ENDIAN)	+= -EB
> +
> +# STAR 9000518362:
> +# arc-linux-uclibc-ld (buildroot) or arceb-elf32-ld (EZChip) don't accept
> +# --build-id w/o "-marclinux".
> +# Default arc-elf32-ld is OK
> +ldflags-y				+= -marclinux
> +
> +ARC_LIBGCC				:= -mA7
> +cflags-$(CONFIG_ARC_HAS_HW_MPY)		+= -multcost=16
> +
> +ifndef CONFIG_ARC_HAS_HW_MPY
> +	cflags-y	+= -mno-mpy
> +
> +# newlib for ARC700 assumes MPY to be always present, which is generally true
> +# However, if someone really doesn't want MPY, we need to use the 600 ver
> +# which coupled with -mno-mpy will use mpy emulation
> +# With gcc 4.4.7, -mno-mpy is enough to make any other related adjustments,
> +# e.g. increased cost of MPY. With gcc 4.2.1 this had to be explicitly hinted
> +
> +	ARC_LIBGCC		:= -marc600
> +	ifneq ($(atleast_gcc44),y)
> +		cflags-y	+= -multcost=30
> +	endif
> +endif
> +
> +LIBGCC	:= $(shell $(CC) $(ARC_LIBGCC) $(cflags-y) --print-libgcc-file-name)
> +
> +# Modules with short calls might break for calls into builtin-kernel
> +KBUILD_CFLAGS_MODULE	+= -mlong-calls
> +
> +# Finally dump eveything into kernel build system
> +KBUILD_CFLAGS	+= $(cflags-y)
> +KBUILD_AFLAGS	+= $(KBUILD_CFLAGS)
> +LDFLAGS		+= $(ldflags-y)
> +
> +# Needed for Linker script preprocessing
> +KBUILD_CPPFLAGS	+= -Iarch/arc/plat-$(PLATFORM)/include
> +
> +head-y		:= arch/arc/kernel/head.o
> +
> +# See arch/arc/Kbuild for content of core part of the kernel
> +core-y		+= arch/arc/
> +
> +# w/o this ifneq, make ARCH=arc clean was crapping out
> +ifneq ($(platform-y),)
> +core-y		+= arch/arc/plat-$(PLATFORM)/
> +endif
> +
> +libs-y		+= arch/arc/lib/ $(LIBGCC)
> +
> +#default target for make without any arguements.
> +KBUILD_IMAGE := bootpImage
> +
> +all:	$(KBUILD_IMAGE)
> +boot	:= arch/arc/boot
> +
> +bootpImage: vmlinux
> +
> +uImage: vmlinux
> +	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
> +
> +archclean:
> +	$(Q)$(MAKE) $(clean)=$(boot)
> +
> +# Hacks to enable final link due to absence of link-time branch relexation
> +# and gcc choosing optimal(shorter) branches at -O3
> +#
> +# vineetg Feb 2010: -mlong-calls switched off for overall kernel build
> +# However lib/decompress_inflate.o (.init.text) calls
> +# zlib_inflate_workspacesize (.text) causing relocation errors.
> +# Thus forcing all exten calls in this file to be long calls
> +export CFLAGS_decompress_inflate.o = -mmedium-calls
> +export CFLAGS_initramfs.o = -mmedium-calls
> diff --git a/arch/arc/boot/Makefile b/arch/arc/boot/Makefile
> new file mode 100644
> index 0000000..7d514c2
> --- /dev/null
> +++ b/arch/arc/boot/Makefile
> @@ -0,0 +1,26 @@
> +targets := vmlinux.bin vmlinux.bin.gz uImage
> +
> +# uImage build relies on mkimage being availble on your host for ARC target
> +# You will need to build u-boot for ARC, rename mkimage to arc-elf32-mkimage
> +# and make sure it's reacable from your PATH
> +MKIMAGE := $(srctree)/scripts/mkuboot.sh
> +
> +OBJCOPYFLAGS= -O binary -R .note -R .note.gnu.build-id -R .comment -S
> +
> +LINUX_START_TEXT = $$(readelf -h vmlinux | \
> +			grep "Entry point address" | grep -o 0x.*)
> +
> +UIMAGE_LOADADDR    = $(CONFIG_LINUX_LINK_BASE)
> +UIMAGE_ENTRYADDR   = $(LINUX_START_TEXT)
> +UIMAGE_COMPRESSION = gzip
> +
> +$(obj)/vmlinux.bin: vmlinux FORCE
> +	$(call if_changed,objcopy)
> +
> +$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
> +	$(call if_changed,gzip)
> +
> +$(obj)/uImage: $(obj)/vmlinux.bin.gz FORCE
> +	$(call if_changed,uimage)
> +
> +PHONY += FORCE
> diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
> index a90a3c6..105ec11 100644
> --- a/arch/arc/include/asm/Kbuild
> +++ b/arch/arc/include/asm/Kbuild
> @@ -33,6 +33,7 @@ generic-y += mman.h
>  generic-y += msgbuf.h
>  generic-y += param.h
>  generic-y += parport.h
> +generic-y += pci.h
>  generic-y += percpu.h
>  generic-y += poll.h
>  generic-y += posix_types.h
> diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
> new file mode 100644
> index 0000000..6d83431
> --- /dev/null
> +++ b/arch/arc/kernel/Makefile
> @@ -0,0 +1,16 @@
> +#
> +# 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.
> +
> +obj-y	:= arcksyms.o setup.o irq.o time.o reset.o ptrace.o entry.o process.o
> +obj-y	+= signal.o traps.o sys.o troubleshoot.o stacktrace.o clk.o
> +
> +obj-$(CONFIG_ARC_FPU_SAVE_RESTORE)	+= fpu.o
> +CFLAGS_fpu.o   += -mdpfp
> +
> +obj-y += ctx_sw_asm.o
> +
> +extra-y := vmlinux.lds head.o
> diff --git a/arch/arc/kernel/arcksyms.c b/arch/arc/kernel/arcksyms.c
> new file mode 100644
> index 0000000..4d9e777
> --- /dev/null
> +++ b/arch/arc/kernel/arcksyms.c
> @@ -0,0 +1,56 @@
> +/*
> + * arcksyms.c - Exporting symbols not exportable from their own sources
> + *
> + * 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.
> + *
> + */
> +
> +#include <linux/module.h>
> +
> +/* libgcc functions, not part of kernel sources */
> +extern void __ashldi3(void);
> +extern void __ashrdi3(void);
> +extern void __divsi3(void);
> +extern void __divsf3(void);
> +extern void __lshrdi3(void);
> +extern void __modsi3(void);
> +extern void __muldi3(void);
> +extern void __ucmpdi2(void);
> +extern void __udivsi3(void);
> +extern void __umodsi3(void);
> +extern void __cmpdi2(void);
> +extern void __fixunsdfsi(void);
> +extern void __muldf3(void);
> +extern void __divdf3(void);
> +extern void __floatunsidf(void);
> +extern void __floatunsisf(void);
> +
> +EXPORT_SYMBOL(__ashldi3);
> +EXPORT_SYMBOL(__ashrdi3);
> +EXPORT_SYMBOL(__divsi3);
> +EXPORT_SYMBOL(__divsf3);
> +EXPORT_SYMBOL(__lshrdi3);
> +EXPORT_SYMBOL(__modsi3);
> +EXPORT_SYMBOL(__muldi3);
> +EXPORT_SYMBOL(__ucmpdi2);
> +EXPORT_SYMBOL(__udivsi3);
> +EXPORT_SYMBOL(__umodsi3);
> +EXPORT_SYMBOL(__cmpdi2);
> +EXPORT_SYMBOL(__fixunsdfsi);
> +EXPORT_SYMBOL(__muldf3);
> +EXPORT_SYMBOL(__divdf3);
> +EXPORT_SYMBOL(__floatunsidf);
> +EXPORT_SYMBOL(__floatunsisf);
> +
> +/* ARC optimised assembler routines */
> +EXPORT_SYMBOL(memset);
> +EXPORT_SYMBOL(memcpy);
> +EXPORT_SYMBOL(memcmp);
> +EXPORT_SYMBOL(strchr);
> +EXPORT_SYMBOL(strcpy);
> +EXPORT_SYMBOL(strcmp);
> +EXPORT_SYMBOL(strlen);
> diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c
> new file mode 100644
> index 0000000..7f3f611
> --- /dev/null
> +++ b/arch/arc/kernel/asm-offsets.c
> @@ -0,0 +1,46 @@
> +/*
> + * 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.
> + */
> +
> +#include <linux/sched.h>
> +#include <linux/mm.h>
> +#include <linux/interrupt.h>
> +#include <asm/hardirq.h>
> +#include <linux/thread_info.h>
> +#include <asm/page.h>
> +#include <linux/kbuild.h>
> +
> +int main(void)
> +{
> +	DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
> +	DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
> +
> +	BLANK();
> +
> +	DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
> +	DEFINE(THREAD_CALLEE_REG, offsetof(struct thread_struct, callee_reg));
> +	DEFINE(THREAD_FAULT_ADDR,
> +	       offsetof(struct thread_struct, fault_address));
> +
> +	BLANK();
> +
> +	DEFINE(THREAD_INFO_FLAGS, offsetof(struct thread_info, flags));
> +	DEFINE(THREAD_INFO_PREEMPT_COUNT,
> +	       offsetof(struct thread_info, preempt_count));
> +
> +	BLANK();
> +
> +	DEFINE(TASK_ACT_MM, offsetof(struct task_struct, active_mm));
> +	DEFINE(TASK_TGID, offsetof(struct task_struct, tgid));
> +
> +	DEFINE(MM_CTXT, offsetof(struct mm_struct, context));
> +	DEFINE(MM_PGD, offsetof(struct mm_struct, pgd));
> +
> +	DEFINE(MM_CTXT_ASID, offsetof(mm_context_t, asid));
> +
> +	return 0;
> +}
> diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
> new file mode 100644
> index 0000000..8c72bc3
> --- /dev/null
> +++ b/arch/arc/kernel/vmlinux.lds.S
> @@ -0,0 +1,116 @@
> +/*
> + * 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.
> + */
> +
> +#include <asm-generic/vmlinux.lds.h>
> +#include <asm/cache.h>
> +#include <asm/page.h>
> +#include <asm/thread_info.h>
> +#include <plat/memmap.h>
> +
> +OUTPUT_ARCH(arc)
> +ENTRY(_stext)
> +
> +#ifdef CONFIG_CPU_BIG_ENDIAN
> +jiffies = jiffies_64 + 4;
> +#else
> +jiffies = jiffies_64;
> +#endif
> +
> +SECTIONS
> +{
> +	. = CONFIG_LINUX_LINK_BASE;
> +
> +	_int_vec_base_lds = .;
> +	.vector : {
> +		*(.vector)
> +		. = ALIGN(PAGE_SIZE);
> +	}
> +
> +	/*
> +	 * The reason for having a seperate subsection .init.ramfs is to
> +	 * prevent objump from including it in kernel dumps
> +	 *
> +	 * Reason for having .init.ramfs above .init is to make sure that the
> +	 * binary blob is tucked away to one side, reducing the displacement
> +	 * between .init.text and .text, avoiding any possible relocation
> +	 * errors because of calls from .init.text to .text
> +	 * Yes such calls do exist. e.g.
> +	 *	decompress_inflate.c:gunzip( ) -> zlib_inflate_workspace( )
> +	 */
> +
> +	__init_begin = .;
> +
> +	.init.ramfs : { INIT_RAM_FS }
> +
> +	. = ALIGN(PAGE_SIZE);
> +	_stext = .;
> +
> +	HEAD_TEXT_SECTION
> +	INIT_TEXT_SECTION(L1_CACHE_BYTES)
> +
> +	/* INIT_DATA_SECTION open-coded: special INIT_RAM_FS handling */
> +	.init.data : {
> +		INIT_DATA
> +		INIT_SETUP(L1_CACHE_BYTES)
> +		INIT_CALLS
> +		CON_INITCALL
> +		SECURITY_INITCALL
> +	}
> +
> +	PERCPU_SECTION(L1_CACHE_BYTES)
> +
> +	/*
> +	 * .exit.text is discard at runtime, not link time, to deal with
> +	 * references from .debug_frame
> +	 * It will be init freed, being inside [__init_start : __init_end]
> +	 */
> +	.exit.text : { EXIT_TEXT }
> +	.exit.data : { EXIT_DATA }
> +
> +	. = ALIGN(PAGE_SIZE);
> +	__init_end = .;
> +
> +	.text : {
> +		_text = .;
> +		TEXT_TEXT
> +		SCHED_TEXT
> +		LOCK_TEXT
> +		KPROBES_TEXT
> +		*(.fixup)
> +		*(.gnu.warning)
> +	}
> +	EXCEPTION_TABLE(L1_CACHE_BYTES)
> +	_etext = .;
> +
> +	_sdata = .;
> +	RO_DATA_SECTION(PAGE_SIZE)
> +
> +	/*
> +	 * 1. this is .data essentially
> +	 * 2. THREAD_SIZE for init.task, must be kernel-stk sz aligned
> +	 */
> +	RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
> +
> +	_edata = .;
> +
> +	BSS_SECTION(0, 0, 0)
> +
> +	NOTES
> +
> +	. = ALIGN(PAGE_SIZE);
> +	_end = . ;
> +
> +	STABS_DEBUG
> +	DWARF_DEBUG
> +	DISCARDS
> +
> +	.arcextmap 0 : {
> +		*(.gnu.linkonce.arcextmap.*)
> +		*(.arcextmap.*)
> +	}
> +}
> diff --git a/arch/arc/lib/Makefile b/arch/arc/lib/Makefile
> new file mode 100644
> index 0000000..db46e20
> --- /dev/null
> +++ b/arch/arc/lib/Makefile
> @@ -0,0 +1,9 @@
> +#
> +# 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.
> +
> +lib-y	:= strchr-700.o strcmp.o strcpy-700.o strlen.o
> +lib-y	+= memcmp.o memcpy-700.o memset.o
> diff --git a/arch/arc/mm/Makefile b/arch/arc/mm/Makefile
> new file mode 100644
> index 0000000..168dc14
> --- /dev/null
> +++ b/arch/arc/mm/Makefile
> @@ -0,0 +1,10 @@
> +#
> +# 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.
> +#
> +
> +obj-y	:= extable.o ioremap.o dma.o fault.o init.o
> +obj-y	+= tlb.o tlbex.o cache_arc700.o
> diff --git a/arch/arc/plat-arcfpga/Kconfig b/arch/arc/plat-arcfpga/Kconfig
> new file mode 100644
> index 0000000..7af3a4e
> --- /dev/null
> +++ b/arch/arc/plat-arcfpga/Kconfig
> @@ -0,0 +1,33 @@
> +#
> +# Copyright (C) 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.
> +#
> +
> +if ARC_PLAT_FPGA_LEGACY
> +
> +choice
> +	prompt "FPGA Board"
> +
> +config ARC_BOARD_ANGEL4
> +	bool "ARC Angel4"
> +	help
> +	  ARC Angel4 FPGA Ref Platform (Xilinx Virtex Based)
> +
> +config ARC_BOARD_ML509
> +	bool "ML509"
> +	help
> +	  ARC ML509 FPGA Ref Platform (Xilinx Virtex-5 Based)
> +
> +endchoice
> +
> +config ARC_SERIAL_BAUD
> +	int "UART Baud rate"
> +	default "115200"
> +	depends on SERIAL_ARC || SERIAL_ARC_CONSOLE
> +	help
> +	  Baud rate for the ARC UART
> +
> +endif
> diff --git a/arch/arc/plat-arcfpga/Makefile b/arch/arc/plat-arcfpga/Makefile
> new file mode 100644
> index 0000000..385eb9d
> --- /dev/null
> +++ b/arch/arc/plat-arcfpga/Makefile
> @@ -0,0 +1,9 @@
> +#
> +# Copyright (C) 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.
> +#
> +
> +obj-y := platform.o irq.o
> 

If this patch looks OK - can you please respond with an ACK. If not, please let me
know what, if any, needs fixing/reworking.

Thx,
-Vineet

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v3 58/71] ARC: UAPI Disintegrate arch/arc/include/asm
  2013-01-24 10:50 ` [PATCH v3 58/71] ARC: UAPI Disintegrate arch/arc/include/asm Vineet Gupta
@ 2013-01-28  7:36   ` Vineet Gupta
  0 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-28  7:36 UTC (permalink / raw)
  To: David Howells; +Cc: linux-arch, linux-kernel, arnd

Hi David,

On Thursday 24 January 2013 04:20 PM, Vineet Gupta wrote:
> 1. ./genfilelist.pl arch/arc/include/asm/
> 
> 2. Create arch/arc/include/uapi/asm/Kbuild as follows
> 
> 	+# UAPI Header export list
> 	+include include/uapi/asm-generic/Kbuild.asm
> 
> 3. ./disintegrate-one.pl arch/arc/include/{,uapi/}asm/<above-list>
> 
> 4. Edit arch/arc/include/asm/Kbuild to remove ref to
> 	asm-generic/Kbuild.asm
> 
> To work around empty uapi/asm/setup.h added a placholder comment.
> 
> Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
> Cc: David Howells <dhowells@redhat.com>
> ---
>  arch/arc/include/asm/Kbuild            |    8 ---
>  arch/arc/include/asm/byteorder.h       |   18 ------
>  arch/arc/include/asm/cachectl.h        |   28 ---------
>  arch/arc/include/asm/page.h            |   30 +---------
>  arch/arc/include/asm/ptrace.h          |   37 +-----------
>  arch/arc/include/asm/setup.h           |    3 +-
>  arch/arc/include/asm/sigcontext.h      |   23 --------
>  arch/arc/include/asm/signal.h          |   27 ---------
>  arch/arc/include/asm/swab.h            |   98 --------------------------------
>  arch/arc/include/asm/unistd.h          |   34 -----------
>  arch/arc/include/uapi/asm/Kbuild       |   11 ++++
>  arch/arc/include/uapi/asm/byteorder.h  |   18 ++++++
>  arch/arc/include/uapi/asm/cachectl.h   |   28 +++++++++
>  arch/arc/include/uapi/asm/page.h       |   39 +++++++++++++
>  arch/arc/include/uapi/asm/ptrace.h     |   46 +++++++++++++++
>  arch/arc/include/uapi/asm/setup.h      |    6 ++
>  arch/arc/include/uapi/asm/sigcontext.h |   23 ++++++++
>  arch/arc/include/uapi/asm/signal.h     |   27 +++++++++
>  arch/arc/include/uapi/asm/swab.h       |   98 ++++++++++++++++++++++++++++++++
>  arch/arc/include/uapi/asm/unistd.h     |   34 +++++++++++
>  20 files changed, 335 insertions(+), 301 deletions(-)
>  delete mode 100644 arch/arc/include/asm/byteorder.h
>  delete mode 100644 arch/arc/include/asm/cachectl.h
>  delete mode 100644 arch/arc/include/asm/sigcontext.h
>  delete mode 100644 arch/arc/include/asm/signal.h
>  delete mode 100644 arch/arc/include/asm/swab.h
>  delete mode 100644 arch/arc/include/asm/unistd.h
>  create mode 100644 arch/arc/include/uapi/asm/Kbuild
>  create mode 100644 arch/arc/include/uapi/asm/byteorder.h
>  create mode 100644 arch/arc/include/uapi/asm/cachectl.h
>  create mode 100644 arch/arc/include/uapi/asm/page.h
>  create mode 100644 arch/arc/include/uapi/asm/ptrace.h
>  create mode 100644 arch/arc/include/uapi/asm/setup.h
>  create mode 100644 arch/arc/include/uapi/asm/sigcontext.h
>  create mode 100644 arch/arc/include/uapi/asm/signal.h
>  create mode 100644 arch/arc/include/uapi/asm/swab.h
>  create mode 100644 arch/arc/include/uapi/asm/unistd.h
> 
> diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
> index b24089c..48af742 100644
> --- a/arch/arc/include/asm/Kbuild
> +++ b/arch/arc/include/asm/Kbuild
> @@ -1,11 +1,3 @@
> -include include/asm-generic/Kbuild.asm
> -
> -# 7-Oct-12: Jeremy Bennett <jeremy.bennett@embecosm.com>. Some of these
> -# headers, beyond those specified in the generic set are needed by user code.
> -
> -header-y += page.h
> -header-y += cachectl.h
> -
>  generic-y += auxvec.h
>  generic-y += bugs.h
>  generic-y += bitsperlong.h
> diff --git a/arch/arc/include/asm/byteorder.h b/arch/arc/include/asm/byteorder.h
> deleted file mode 100644
> index 9da71d4..0000000
> --- a/arch/arc/include/asm/byteorder.h
> +++ /dev/null
> @@ -1,18 +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_ARC_BYTEORDER_H
> -#define __ASM_ARC_BYTEORDER_H
> -
> -#ifdef CONFIG_CPU_BIG_ENDIAN
> -#include <linux/byteorder/big_endian.h>
> -#else
> -#include <linux/byteorder/little_endian.h>
> -#endif
> -
> -#endif /* ASM_ARC_BYTEORDER_H */
> diff --git a/arch/arc/include/asm/cachectl.h b/arch/arc/include/asm/cachectl.h
> deleted file mode 100644
> index 51c73f0..0000000
> --- a/arch/arc/include/asm/cachectl.h
> +++ /dev/null
> @@ -1,28 +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 __ARC_ASM_CACHECTL_H
> -#define __ARC_ASM_CACHECTL_H
> -
> -/*
> - * ARC ABI flags defined for Android's finegrained cacheflush requirements
> - */
> -#define CF_I_INV	0x0002
> -#define CF_D_FLUSH	0x0010
> -#define CF_D_FLUSH_INV	0x0020
> -
> -#define CF_DEFAULT	(CF_I_INV | CF_D_FLUSH)
> -
> -/*
> - * Standard flags expected by cacheflush system call users
> - */
> -#define ICACHE	CF_I_INV
> -#define DCACHE	CF_D_FLUSH
> -#define BCACHE	(CF_I_INV | CF_D_FLUSH)
> -
> -#endif
> diff --git a/arch/arc/include/asm/page.h b/arch/arc/include/asm/page.h
> index d111d0c..dfe1f8a 100644
> --- a/arch/arc/include/asm/page.h
> +++ b/arch/arc/include/asm/page.h
> @@ -5,37 +5,11 @@
>   * it under the terms of the GNU General Public License version 2 as
>   * published by the Free Software Foundation.
>   */
> -
>  #ifndef __ASM_ARC_PAGE_H
>  #define __ASM_ARC_PAGE_H
>  
> -/* PAGE_SHIFT determines the page size */
> -#if defined(CONFIG_ARC_PAGE_SIZE_16K)
> -#define PAGE_SHIFT 14
> -#elif defined(CONFIG_ARC_PAGE_SIZE_4K)
> -#define PAGE_SHIFT 12
> -#else
> -/*
> - * Default 8k
> - * done this way (instead of under CONFIG_ARC_PAGE_SIZE_8K) because adhoc
> - * user code (busybox appletlib.h) expects PAGE_SHIFT to be defined w/o
> - * using the correct uClibc header and in their build our autoconf.h is
> - * not available
> - */
> -#define PAGE_SHIFT 13
> -#endif
> -
> -#ifdef __ASSEMBLY__
> -#define PAGE_SIZE	(1 << PAGE_SHIFT)
> -#define PAGE_OFFSET	(0x80000000)
> -#else
> -#define PAGE_SIZE	(1UL << PAGE_SHIFT)	/* Default 8K */
> -#define PAGE_OFFSET	(0x80000000UL)	/* Kernel starts at 2G onwards */
> -#endif
> +#include <uapi/asm/page.h>
>  
> -#define PAGE_MASK	(~(PAGE_SIZE-1))
> -
> -#ifdef __KERNEL__
>  
>  #ifndef __ASSEMBLY__
>  
> @@ -129,6 +103,4 @@ typedef unsigned long pgtable_t;
>  
>  #endif /* !__ASSEMBLY__ */
>  
> -#endif /* __KERNEL__ */
> -
>  #endif
> diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
> index 6ab65fa..95e633e 100644
> --- a/arch/arc/include/asm/ptrace.h
> +++ b/arch/arc/include/asm/ptrace.h
> @@ -7,42 +7,11 @@
>   *
>   * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
>   */
> -
>  #ifndef __ASM_ARC_PTRACE_H
>  #define __ASM_ARC_PTRACE_H
>  
> -/*
> - * XXX: ABI hack.
> - * The offset calc can be cleanly done in asm-offset.c, however gdb includes
> - * this header directly.
> - */
> -#define PT_bta		4
> -#define PT_lp_start	8
> -#define PT_lp_end	12
> -#define PT_lp_count	16
> -#define PT_status32	20
> -#define PT_ret		24
> -#define PT_blink	28
> -#define PT_fp		32
> -#define PT_r26		36
> -#define PT_r12		40
> -#define PT_r11		44
> -#define PT_r10		48
> -#define PT_r9		52
> -#define PT_r8		56
> -#define PT_r7		60
> -#define PT_r6		64
> -#define PT_r5		68
> -#define PT_r4		72
> -#define PT_r3		76
> -#define PT_r2		80
> -#define PT_r1		84
> -#define PT_r0		88
> -#define PT_sp		92
> -#define PT_orig_r0	96
> -#define PT_orig_r8	100
> -
> -#ifdef __KERNEL__
> +#include <uapi/asm/ptrace.h>
> +
>  
>  #ifndef __ASSEMBLY__
>  
> @@ -163,6 +132,4 @@ static inline long regs_return_value(struct pt_regs *regs)
>  #define orig_r8_IS_IRQ1			0x0010
>  #define orig_r8_IS_IRQ2			0x0020
>  
> -#endif /* __KERNEL__ */
> -
>  #endif /* __ASM_PTRACE_H */
> diff --git a/arch/arc/include/asm/setup.h b/arch/arc/include/asm/setup.h
> index fc97411..229e506 100644
> --- a/arch/arc/include/asm/setup.h
> +++ b/arch/arc/include/asm/setup.h
> @@ -5,11 +5,12 @@
>   * it under the terms of the GNU General Public License version 2 as
>   * published by the Free Software Foundation.
>   */
> -
>  #ifndef __ASMARC_SETUP_H
>  #define __ASMARC_SETUP_H
>  
> +
>  #include <linux/types.h>
> +#include <uapi/asm/setup.h>
>  
>  #define COMMAND_LINE_SIZE 256
>  
> diff --git a/arch/arc/include/asm/sigcontext.h b/arch/arc/include/asm/sigcontext.h
> deleted file mode 100644
> index f21b541..0000000
> --- a/arch/arc/include/asm/sigcontext.h
> +++ /dev/null
> @@ -1,23 +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_ARC_SIGCONTEXT_H
> -#define _ASM_ARC_SIGCONTEXT_H
> -
> -#include <asm/ptrace.h>
> -
> -/*
> - * Signal context structure - contains all info to do with the state
> - * before the signal handler was invoked.  Note: only add new entries
> - * to the end of the structure.
> - */
> -struct sigcontext {
> -	struct pt_regs regs;
> -};
> -
> -#endif /* _ASM_ARC_SIGCONTEXT_H */
> diff --git a/arch/arc/include/asm/signal.h b/arch/arc/include/asm/signal.h
> deleted file mode 100644
> index fad62f7..0000000
> --- a/arch/arc/include/asm/signal.h
> +++ /dev/null
> @@ -1,27 +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.
> - *
> - * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
> - */
> -
> -#ifndef _ASM_ARC_SIGNAL_H
> -#define _ASM_ARC_SIGNAL_H
> -
> -/*
> - * This is much needed for ARC sigreturn optimization.
> - * This allows uClibc to piggback the addr of a sigreturn stub in sigaction,
> - * which allows sigreturn based re-entry into kernel after handling signal.
> - * W/o this kernel needs to "synthesize" the sigreturn trampoline on user
> - * mode stack which in turn forces the following:
> - * -TLB Flush (after making the stack page executable)
> - * -Cache line Flush (to make I/D Cache lines coherent)
> - */
> -#define SA_RESTORER	0x04000000
> -
> -#include <asm-generic/signal.h>
> -
> -#endif /* _ASM_ARC_SIGNAL_H */
> diff --git a/arch/arc/include/asm/swab.h b/arch/arc/include/asm/swab.h
> deleted file mode 100644
> index 095599a..0000000
> --- a/arch/arc/include/asm/swab.h
> +++ /dev/null
> @@ -1,98 +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.
> - *
> - * vineetg: May 2011
> - *  -Support single cycle endian-swap insn in ARC700 4.10
> - *
> - * vineetg: June 2009
> - *  -Better htonl implementation (5 instead of 9 ALU instructions)
> - *  -Hardware assisted single cycle bswap (Use Case of ARC custom instrn)
> - */
> -
> -#ifndef __ASM_ARC_SWAB_H
> -#define __ASM_ARC_SWAB_H
> -
> -#include <linux/types.h>
> -
> -/* Native single cycle endian swap insn */
> -#ifdef CONFIG_ARC_HAS_SWAPE
> -
> -#define __arch_swab32(x)		\
> -({					\
> -	unsigned int tmp = x;		\
> -	__asm__(			\
> -	"	swape	%0, %1	\n"	\
> -	: "=r" (tmp)			\
> -	: "r" (tmp));			\
> -	tmp;				\
> -})
> -
> -#else
> -
> -/* Several ways of Endian-Swap Emulation for ARC
> - * 0: kernel generic
> - * 1: ARC optimised "C"
> - * 2: ARC Custom instruction
> - */
> -#define ARC_BSWAP_TYPE	1
> -
> -#if (ARC_BSWAP_TYPE == 1)		/******* Software only ********/
> -
> -/* The kernel default implementation of htonl is
> - *		return  x<<24 | x>>24 |
> - *		 (x & (__u32)0x0000ff00UL)<<8 | (x & (__u32)0x00ff0000UL)>>8;
> - *
> - * This generates 9 instructions on ARC (excluding the ld/st)
> - *
> - * 8051fd8c:	ld     r3,[r7,20]	; Mem op : Get the value to be swapped
> - * 8051fd98:	asl    r5,r3,24		; get  3rd Byte
> - * 8051fd9c:	lsr    r2,r3,24		; get  0th Byte
> - * 8051fda0:	and    r4,r3,0xff00
> - * 8051fda8:	asl    r4,r4,8		; get 1st Byte
> - * 8051fdac:	and    r3,r3,0x00ff0000
> - * 8051fdb4:	or     r2,r2,r5		; combine 0th and 3rd Bytes
> - * 8051fdb8:	lsr    r3,r3,8		; 2nd Byte at correct place in Dst Reg
> - * 8051fdbc:	or     r2,r2,r4		; combine 0,3 Bytes with 1st Byte
> - * 8051fdc0:	or     r2,r2,r3		; combine 0,3,1 Bytes with 2nd Byte
> - * 8051fdc4:	st     r2,[r1,20]	; Mem op : save result back to mem
> - *
> - * Joern suggested a better "C" algorithm which is great since
> - * (1) It is portable to any architecure
> - * (2) At the same time it takes advantage of ARC ISA (rotate intrns)
> - */
> -
> -#define __arch_swab32(x)					\
> -({	unsigned long __in = (x), __tmp;			\
> -	__tmp = __in << 8 | __in >> 24; /* ror tmp,in,24 */	\
> -	__in = __in << 24 | __in >> 8; /* ror in,in,8 */	\
> -	__tmp ^= __in;						\
> -	__tmp &= 0xff00ff;					\
> -	__tmp ^ __in;						\
> -})
> -
> -#elif (ARC_BSWAP_TYPE == 2)	/* Custom single cycle bwap instruction */
> -
> -#define __arch_swab32(x)						\
> -({									\
> -	unsigned int tmp = x;						\
> -	__asm__(							\
> -	"	.extInstruction	bswap, 7, 0x00, SUFFIX_NONE, SYNTAX_2OP	\n"\
> -	"	bswap  %0, %1						\n"\
> -	: "=r" (tmp)							\
> -	: "r" (tmp));							\
> -	tmp;								\
> -})
> -
> -#endif /* ARC_BSWAP_TYPE=zzz */
> -
> -#endif /* CONFIG_ARC_HAS_SWAPE */
> -
> -#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
> -#define __SWAB_64_THRU_32__
> -#endif
> -
> -#endif
> diff --git a/arch/arc/include/asm/unistd.h b/arch/arc/include/asm/unistd.h
> deleted file mode 100644
> index 6f30484..0000000
> --- a/arch/arc/include/asm/unistd.h
> +++ /dev/null
> @@ -1,34 +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.
> - */
> -
> -/******** no-legacy-syscalls-ABI *******/
> -
> -#define __ARCH_WANT_SYS_EXECVE
> -#define __ARCH_WANT_SYS_CLONE
> -#define __ARCH_WANT_SYS_VFORK
> -#define __ARCH_WANT_SYS_FORK
> -
> -#define sys_mmap2 sys_mmap_pgoff
> -
> -#include <asm-generic/unistd.h>
> -
> -#define NR_syscalls	__NR_syscalls
> -
> -/* ARC specific syscall */
> -#define __NR_cacheflush		(__NR_arch_specific_syscall + 0)
> -#define __NR_arc_settls		(__NR_arch_specific_syscall + 1)
> -#define __NR_arc_gettls		(__NR_arch_specific_syscall + 2)
> -
> -__SYSCALL(__NR_cacheflush, sys_cacheflush)
> -__SYSCALL(__NR_arc_settls, sys_arc_settls)
> -__SYSCALL(__NR_arc_gettls, sys_arc_gettls)
> -
> -
> -/* Generic syscall (fs/filesystems.c - lost in asm-generic/unistd.h */
> -#define __NR_sysfs		(__NR_arch_specific_syscall + 3)
> -__SYSCALL(__NR_sysfs, sys_sysfs)
> diff --git a/arch/arc/include/uapi/asm/Kbuild b/arch/arc/include/uapi/asm/Kbuild
> new file mode 100644
> index 0000000..2736244
> --- /dev/null
> +++ b/arch/arc/include/uapi/asm/Kbuild
> @@ -0,0 +1,11 @@
> +# UAPI Header export list
> +include include/uapi/asm-generic/Kbuild.asm
> +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/byteorder.h b/arch/arc/include/uapi/asm/byteorder.h
> new file mode 100644
> index 0000000..9da71d4
> --- /dev/null
> +++ b/arch/arc/include/uapi/asm/byteorder.h
> @@ -0,0 +1,18 @@
> +/*
> + * 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_ARC_BYTEORDER_H
> +#define __ASM_ARC_BYTEORDER_H
> +
> +#ifdef CONFIG_CPU_BIG_ENDIAN
> +#include <linux/byteorder/big_endian.h>
> +#else
> +#include <linux/byteorder/little_endian.h>
> +#endif
> +
> +#endif /* ASM_ARC_BYTEORDER_H */
> diff --git a/arch/arc/include/uapi/asm/cachectl.h b/arch/arc/include/uapi/asm/cachectl.h
> new file mode 100644
> index 0000000..51c73f0
> --- /dev/null
> +++ b/arch/arc/include/uapi/asm/cachectl.h
> @@ -0,0 +1,28 @@
> +/*
> + * 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 __ARC_ASM_CACHECTL_H
> +#define __ARC_ASM_CACHECTL_H
> +
> +/*
> + * ARC ABI flags defined for Android's finegrained cacheflush requirements
> + */
> +#define CF_I_INV	0x0002
> +#define CF_D_FLUSH	0x0010
> +#define CF_D_FLUSH_INV	0x0020
> +
> +#define CF_DEFAULT	(CF_I_INV | CF_D_FLUSH)
> +
> +/*
> + * Standard flags expected by cacheflush system call users
> + */
> +#define ICACHE	CF_I_INV
> +#define DCACHE	CF_D_FLUSH
> +#define BCACHE	(CF_I_INV | CF_D_FLUSH)
> +
> +#endif
> diff --git a/arch/arc/include/uapi/asm/page.h b/arch/arc/include/uapi/asm/page.h
> new file mode 100644
> index 0000000..e5d41e0
> --- /dev/null
> +++ b/arch/arc/include/uapi/asm/page.h
> @@ -0,0 +1,39 @@
> +/*
> + * 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 _UAPI__ASM_ARC_PAGE_H
> +#define _UAPI__ASM_ARC_PAGE_H
> +
> +/* PAGE_SHIFT determines the page size */
> +#if defined(CONFIG_ARC_PAGE_SIZE_16K)
> +#define PAGE_SHIFT 14
> +#elif defined(CONFIG_ARC_PAGE_SIZE_4K)
> +#define PAGE_SHIFT 12
> +#else
> +/*
> + * Default 8k
> + * done this way (instead of under CONFIG_ARC_PAGE_SIZE_8K) because adhoc
> + * user code (busybox appletlib.h) expects PAGE_SHIFT to be defined w/o
> + * using the correct uClibc header and in their build our autoconf.h is
> + * not available
> + */
> +#define PAGE_SHIFT 13
> +#endif
> +
> +#ifdef __ASSEMBLY__
> +#define PAGE_SIZE	(1 << PAGE_SHIFT)
> +#define PAGE_OFFSET	(0x80000000)
> +#else
> +#define PAGE_SIZE	(1UL << PAGE_SHIFT)	/* Default 8K */
> +#define PAGE_OFFSET	(0x80000000UL)	/* Kernel starts at 2G onwards */
> +#endif
> +
> +#define PAGE_MASK	(~(PAGE_SIZE-1))
> +
> +
> +#endif /* _UAPI__ASM_ARC_PAGE_H */
> diff --git a/arch/arc/include/uapi/asm/ptrace.h b/arch/arc/include/uapi/asm/ptrace.h
> new file mode 100644
> index 0000000..bccf4ab
> --- /dev/null
> +++ b/arch/arc/include/uapi/asm/ptrace.h
> @@ -0,0 +1,46 @@
> +/*
> + * 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.
> + *
> + * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
> + */
> +
> +#ifndef _UAPI__ASM_ARC_PTRACE_H
> +#define _UAPI__ASM_ARC_PTRACE_H
> +
> +/*
> + * XXX: ABI hack.
> + * The offset calc can be cleanly done in asm-offset.c, however gdb includes
> + * this header directly.
> + */
> +#define PT_bta		4
> +#define PT_lp_start	8
> +#define PT_lp_end	12
> +#define PT_lp_count	16
> +#define PT_status32	20
> +#define PT_ret		24
> +#define PT_blink	28
> +#define PT_fp		32
> +#define PT_r26		36
> +#define PT_r12		40
> +#define PT_r11		44
> +#define PT_r10		48
> +#define PT_r9		52
> +#define PT_r8		56
> +#define PT_r7		60
> +#define PT_r6		64
> +#define PT_r5		68
> +#define PT_r4		72
> +#define PT_r3		76
> +#define PT_r2		80
> +#define PT_r1		84
> +#define PT_r0		88
> +#define PT_sp		92
> +#define PT_orig_r0	96
> +#define PT_orig_r8	100
> +
> +
> +#endif /* _UAPI__ASM_ARC_PTRACE_H */
> diff --git a/arch/arc/include/uapi/asm/setup.h b/arch/arc/include/uapi/asm/setup.h
> new file mode 100644
> index 0000000..a6d4e44
> --- /dev/null
> +++ b/arch/arc/include/uapi/asm/setup.h
> @@ -0,0 +1,6 @@
> +/*
> + * setup.h is part of userspace header ABI so UAPI scripts have to generate it
> + * even if there's nothing to export - causing empty <uapi/asm/setup.h>
> + * However to prevent "patch" from discarding it we add this placeholder
> + * comment
> + */
> diff --git a/arch/arc/include/uapi/asm/sigcontext.h b/arch/arc/include/uapi/asm/sigcontext.h
> new file mode 100644
> index 0000000..f21b541
> --- /dev/null
> +++ b/arch/arc/include/uapi/asm/sigcontext.h
> @@ -0,0 +1,23 @@
> +/*
> + * 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_ARC_SIGCONTEXT_H
> +#define _ASM_ARC_SIGCONTEXT_H
> +
> +#include <asm/ptrace.h>
> +
> +/*
> + * Signal context structure - contains all info to do with the state
> + * before the signal handler was invoked.  Note: only add new entries
> + * to the end of the structure.
> + */
> +struct sigcontext {
> +	struct pt_regs regs;
> +};
> +
> +#endif /* _ASM_ARC_SIGCONTEXT_H */
> diff --git a/arch/arc/include/uapi/asm/signal.h b/arch/arc/include/uapi/asm/signal.h
> new file mode 100644
> index 0000000..fad62f7
> --- /dev/null
> +++ b/arch/arc/include/uapi/asm/signal.h
> @@ -0,0 +1,27 @@
> +/*
> + * 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.
> + *
> + * Amit Bhor, Sameer Dhavale: Codito Technologies 2004
> + */
> +
> +#ifndef _ASM_ARC_SIGNAL_H
> +#define _ASM_ARC_SIGNAL_H
> +
> +/*
> + * This is much needed for ARC sigreturn optimization.
> + * This allows uClibc to piggback the addr of a sigreturn stub in sigaction,
> + * which allows sigreturn based re-entry into kernel after handling signal.
> + * W/o this kernel needs to "synthesize" the sigreturn trampoline on user
> + * mode stack which in turn forces the following:
> + * -TLB Flush (after making the stack page executable)
> + * -Cache line Flush (to make I/D Cache lines coherent)
> + */
> +#define SA_RESTORER	0x04000000
> +
> +#include <asm-generic/signal.h>
> +
> +#endif /* _ASM_ARC_SIGNAL_H */
> diff --git a/arch/arc/include/uapi/asm/swab.h b/arch/arc/include/uapi/asm/swab.h
> new file mode 100644
> index 0000000..095599a
> --- /dev/null
> +++ b/arch/arc/include/uapi/asm/swab.h
> @@ -0,0 +1,98 @@
> +/*
> + * 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.
> + *
> + * vineetg: May 2011
> + *  -Support single cycle endian-swap insn in ARC700 4.10
> + *
> + * vineetg: June 2009
> + *  -Better htonl implementation (5 instead of 9 ALU instructions)
> + *  -Hardware assisted single cycle bswap (Use Case of ARC custom instrn)
> + */
> +
> +#ifndef __ASM_ARC_SWAB_H
> +#define __ASM_ARC_SWAB_H
> +
> +#include <linux/types.h>
> +
> +/* Native single cycle endian swap insn */
> +#ifdef CONFIG_ARC_HAS_SWAPE
> +
> +#define __arch_swab32(x)		\
> +({					\
> +	unsigned int tmp = x;		\
> +	__asm__(			\
> +	"	swape	%0, %1	\n"	\
> +	: "=r" (tmp)			\
> +	: "r" (tmp));			\
> +	tmp;				\
> +})
> +
> +#else
> +
> +/* Several ways of Endian-Swap Emulation for ARC
> + * 0: kernel generic
> + * 1: ARC optimised "C"
> + * 2: ARC Custom instruction
> + */
> +#define ARC_BSWAP_TYPE	1
> +
> +#if (ARC_BSWAP_TYPE == 1)		/******* Software only ********/
> +
> +/* The kernel default implementation of htonl is
> + *		return  x<<24 | x>>24 |
> + *		 (x & (__u32)0x0000ff00UL)<<8 | (x & (__u32)0x00ff0000UL)>>8;
> + *
> + * This generates 9 instructions on ARC (excluding the ld/st)
> + *
> + * 8051fd8c:	ld     r3,[r7,20]	; Mem op : Get the value to be swapped
> + * 8051fd98:	asl    r5,r3,24		; get  3rd Byte
> + * 8051fd9c:	lsr    r2,r3,24		; get  0th Byte
> + * 8051fda0:	and    r4,r3,0xff00
> + * 8051fda8:	asl    r4,r4,8		; get 1st Byte
> + * 8051fdac:	and    r3,r3,0x00ff0000
> + * 8051fdb4:	or     r2,r2,r5		; combine 0th and 3rd Bytes
> + * 8051fdb8:	lsr    r3,r3,8		; 2nd Byte at correct place in Dst Reg
> + * 8051fdbc:	or     r2,r2,r4		; combine 0,3 Bytes with 1st Byte
> + * 8051fdc0:	or     r2,r2,r3		; combine 0,3,1 Bytes with 2nd Byte
> + * 8051fdc4:	st     r2,[r1,20]	; Mem op : save result back to mem
> + *
> + * Joern suggested a better "C" algorithm which is great since
> + * (1) It is portable to any architecure
> + * (2) At the same time it takes advantage of ARC ISA (rotate intrns)
> + */
> +
> +#define __arch_swab32(x)					\
> +({	unsigned long __in = (x), __tmp;			\
> +	__tmp = __in << 8 | __in >> 24; /* ror tmp,in,24 */	\
> +	__in = __in << 24 | __in >> 8; /* ror in,in,8 */	\
> +	__tmp ^= __in;						\
> +	__tmp &= 0xff00ff;					\
> +	__tmp ^ __in;						\
> +})
> +
> +#elif (ARC_BSWAP_TYPE == 2)	/* Custom single cycle bwap instruction */
> +
> +#define __arch_swab32(x)						\
> +({									\
> +	unsigned int tmp = x;						\
> +	__asm__(							\
> +	"	.extInstruction	bswap, 7, 0x00, SUFFIX_NONE, SYNTAX_2OP	\n"\
> +	"	bswap  %0, %1						\n"\
> +	: "=r" (tmp)							\
> +	: "r" (tmp));							\
> +	tmp;								\
> +})
> +
> +#endif /* ARC_BSWAP_TYPE=zzz */
> +
> +#endif /* CONFIG_ARC_HAS_SWAPE */
> +
> +#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
> +#define __SWAB_64_THRU_32__
> +#endif
> +
> +#endif
> diff --git a/arch/arc/include/uapi/asm/unistd.h b/arch/arc/include/uapi/asm/unistd.h
> new file mode 100644
> index 0000000..6f30484
> --- /dev/null
> +++ b/arch/arc/include/uapi/asm/unistd.h
> @@ -0,0 +1,34 @@
> +/*
> + * 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.
> + */
> +
> +/******** no-legacy-syscalls-ABI *******/
> +
> +#define __ARCH_WANT_SYS_EXECVE
> +#define __ARCH_WANT_SYS_CLONE
> +#define __ARCH_WANT_SYS_VFORK
> +#define __ARCH_WANT_SYS_FORK
> +
> +#define sys_mmap2 sys_mmap_pgoff
> +
> +#include <asm-generic/unistd.h>
> +
> +#define NR_syscalls	__NR_syscalls
> +
> +/* ARC specific syscall */
> +#define __NR_cacheflush		(__NR_arch_specific_syscall + 0)
> +#define __NR_arc_settls		(__NR_arch_specific_syscall + 1)
> +#define __NR_arc_gettls		(__NR_arch_specific_syscall + 2)
> +
> +__SYSCALL(__NR_cacheflush, sys_cacheflush)
> +__SYSCALL(__NR_arc_settls, sys_arc_settls)
> +__SYSCALL(__NR_arc_gettls, sys_arc_gettls)
> +
> +
> +/* Generic syscall (fs/filesystems.c - lost in asm-generic/unistd.h */
> +#define __NR_sysfs		(__NR_arch_specific_syscall + 3)
> +__SYSCALL(__NR_sysfs, sys_sysfs)
> 

If this looks OK, can you please rubber-stamp it with your ACK.

Thx,
-Vineet

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v3 32/71] ARC: [DeviceTree] Basic support
  2013-01-24 10:50 ` [PATCH v3 32/71] ARC: [DeviceTree] Basic support Vineet Gupta
@ 2013-01-28  7:40   ` Vineet Gupta
  2013-01-28 10:21   ` James Hogan
  2013-01-29 13:25   ` Rob Herring
  2 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-28  7:40 UTC (permalink / raw)
  To: Rob Herring; +Cc: linux-arch, linux-kernel

Hi Rob,

On Thursday 24 January 2013 04:20 PM, Vineet Gupta wrote:
> This is minimal infrastructure needed for devicetree work.
> It uses an a sample "skeleton" devicetree - embedded in kernel image -
> to print the board, manufacturer by parsing the top-level "compatible"
> string.
> 
> As of now we don't need any additional "board" specific "machine_desc".
> 
> TODO: support interpreting the command line as boot-loader passed dtb
> 
> Signed-off-by: Vineet Gupta <vgupta-HKixBCOQz3hWk0Htik3J/w@public.gmane.org>
> Cc: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
> Cc: Grant Likely <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org>
> Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org
> Cc: Rob Herring <rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org>
> ---
>  arch/arc/Kconfig                |    9 +++++
>  arch/arc/Makefile               |    9 +++++
>  arch/arc/boot/dts/Makefile      |   14 ++++++++
>  arch/arc/boot/dts/skeleton.dts  |   10 ++++++
>  arch/arc/boot/dts/skeleton.dtsi |   21 ++++++++++++
>  arch/arc/include/asm/prom.h     |   15 ++++++++
>  arch/arc/include/asm/sections.h |    1 +
>  arch/arc/kernel/Makefile        |    2 +
>  arch/arc/kernel/devtree.c       |   69 +++++++++++++++++++++++++++++++++++++++
>  arch/arc/kernel/setup.c         |    9 +++++
>  arch/arc/mm/init.c              |   13 +++++++
>  11 files changed, 172 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arc/boot/dts/Makefile
>  create mode 100644 arch/arc/boot/dts/skeleton.dts
>  create mode 100644 arch/arc/boot/dts/skeleton.dtsi
>  create mode 100644 arch/arc/include/asm/prom.h
>  create mode 100644 arch/arc/kernel/devtree.c
> 
> diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
> index a353849..7666857 100644
> --- a/arch/arc/Kconfig
> +++ b/arch/arc/Kconfig
> @@ -24,8 +24,11 @@ config ARC
>  	select GENERIC_SMP_IDLE_THREAD
>  	select HAVE_GENERIC_HARDIRQS
>  	select HAVE_MEMBLOCK
> +	select IRQ_DOMAIN
>  	select MODULES_USE_ELF_RELA
>  	select NO_BOOTMEM
> +	select OF
> +	select OF_EARLY_FLATTREE
>  
>  config SCHED_OMIT_FRAME_POINTER
>  	def_bool y
> @@ -320,6 +323,12 @@ config CMDLINE_UBOOT
>  	  to it. kernel startup code will copy the string into cmdline buffer
>  	  and also append CONFIG_CMDLINE.
>  
> +config ARC_BUILTIN_DTB_NAME
> +	string "Built in DTB"
> +	help
> +	  Set the name of the DTB to embed in the vmlinux binary
> +	  Leaving it blank selects the minimal "skeleton" dtb
> +
>  source "kernel/Kconfig.preempt"
>  
>  endmenu	 # "ARC Architecture Configuration"
> diff --git a/arch/arc/Makefile b/arch/arc/Makefile
> index 4d52a3b..90570f9 100644
> --- a/arch/arc/Makefile
> +++ b/arch/arc/Makefile
> @@ -83,6 +83,9 @@ head-y		:= arch/arc/kernel/head.o
>  # See arch/arc/Kbuild for content of core part of the kernel
>  core-y		+= arch/arc/
>  
> +# w/o this dtb won't embed into kernel binary
> +core-y		+= arch/arc/boot/dts/
> +
>  # w/o this ifneq, make ARCH=arc clean was crapping out
>  ifneq ($(platform-y),)
>  core-y		+= arch/arc/plat-$(PLATFORM)/
> @@ -101,6 +104,12 @@ bootpImage: vmlinux
>  uImage: vmlinux
>  	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
>  
> +%.dtb %.dtb.S %.dtb.o:
> +	$(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@
> +
> +dtbs:
> +	$(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@
> +
>  archclean:
>  	$(Q)$(MAKE) $(clean)=$(boot)
>  
> diff --git a/arch/arc/boot/dts/Makefile b/arch/arc/boot/dts/Makefile
> new file mode 100644
> index 0000000..4a972a3
> --- /dev/null
> +++ b/arch/arc/boot/dts/Makefile
> @@ -0,0 +1,14 @@
> +ifeq ($(CONFIG_OF),y)
> +
> +# Built-in dtb
> +builtindtb-y		:= skeleton
> +
> +ifneq ($(CONFIG_ARC_BUILTIN_DTB_NAME),"")
> +	builtindtb-y	:= $(CONFIG_ARC_BUILTIN_DTB_NAME)
> +endif
> +
> +obj-y	+= $(patsubst "%",%,$(builtindtb-y)).dtb.o
> +
> +clean-files := *.dtb
> +
> +endif
> diff --git a/arch/arc/boot/dts/skeleton.dts b/arch/arc/boot/dts/skeleton.dts
> new file mode 100644
> index 0000000..25a84fb
> --- /dev/null
> +++ b/arch/arc/boot/dts/skeleton.dts
> @@ -0,0 +1,10 @@
> +/*
> + * 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/boot/dts/skeleton.dtsi b/arch/arc/boot/dts/skeleton.dtsi
> new file mode 100644
> index 0000000..9b357d8
> --- /dev/null
> +++ b/arch/arc/boot/dts/skeleton.dtsi
> @@ -0,0 +1,21 @@
> +/*
> + * 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.
> + */
> +
> +/*
> + * Skeleton device tree; the bare minimum needed to boot; just include and
> + * add a compatible value.
> + */
> +
> +/ {
> +	compatible = "snps,arc";
> +	#address-cells = <1>;
> +	#size-cells = <1>;
> +	chosen { };
> +	aliases { };
> +	memory { device_type = "memory"; reg = <0 0>; };
> +};
> diff --git a/arch/arc/include/asm/prom.h b/arch/arc/include/asm/prom.h
> new file mode 100644
> index 0000000..f54489b
> --- /dev/null
> +++ b/arch/arc/include/asm/prom.h
> @@ -0,0 +1,15 @@
> +/*
> + * 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.
> + */
> +
> +#ifndef _ASM_ARC_PROM_H_
> +#define _ASM_ARC_PROM_H_
> +
> +#define HAVE_ARCH_DEVTREE_FIXUPS
> +extern int __init setup_machine_fdt(void *dt);
> +
> +#endif
> diff --git a/arch/arc/include/asm/sections.h b/arch/arc/include/asm/sections.h
> index fc15f2e..6fc1159 100644
> --- a/arch/arc/include/asm/sections.h
> +++ b/arch/arc/include/asm/sections.h
> @@ -13,5 +13,6 @@
>  
>  extern char _int_vec_base_lds[];
>  extern char __arc_dccm_base[];
> +extern char __dtb_start[];
>  
>  #endif
> diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
> index 6d83431..8a55e99 100644
> --- a/arch/arc/kernel/Makefile
> +++ b/arch/arc/kernel/Makefile
> @@ -8,6 +8,8 @@
>  obj-y	:= arcksyms.o setup.o irq.o time.o reset.o ptrace.o entry.o process.o
>  obj-y	+= signal.o traps.o sys.o troubleshoot.o stacktrace.o clk.o
>  
> +obj-$(CONFIG_OF)			+= devtree.o
> +
>  obj-$(CONFIG_ARC_FPU_SAVE_RESTORE)	+= fpu.o
>  CFLAGS_fpu.o   += -mdpfp
>  
> diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c
> new file mode 100644
> index 0000000..229f78e
> --- /dev/null
> +++ b/arch/arc/kernel/devtree.c
> @@ -0,0 +1,69 @@
> +/*
> + * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
> + *
> + * Based on highly stipped down version of METAG
> + *
> + * 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.
> + */
> +
> +
> +#include <linux/init.h>
> +#include <linux/export.h>
> +#include <linux/errno.h>
> +#include <linux/types.h>
> +#include <linux/reboot.h>
> +#include <linux/memblock.h>
> +#include <linux/of.h>
> +#include <linux/of_fdt.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_platform.h>
> +#include <asm/prom.h>
> +
> +/* called from unflatten_device_tree() to bootstrap devicetree itself */
> +void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
> +{
> +	return __va(memblock_alloc(size, align));
> +}
> +
> +/**
> + * setup_machine_fdt - Machine setup when an dtb was passed to the kernel
> + * @dt:		virtual address pointer to dt blob
> + *
> + * If a dtb was passed to the kernel, then use it to choose the correct
> + * machine_desc and to setup the system.
> + */
> +int __init setup_machine_fdt(void *dt)
> +{
> +	struct boot_param_header *devtree = dt;
> +	unsigned long dt_root;
> +	char *model, *compat;
> +	char manufacturer[16];
> +
> +	/* check device tree validity */
> +	if (be32_to_cpu(devtree->magic) != OF_DT_HEADER)
> +		return 1;
> +
> +	/* Search the mdescs for the 'best' compatible value match */
> +	initial_boot_params = devtree;
> +	dt_root = of_get_flat_dt_root();
> +
> +	/* compat = "<manufacturer>,<model>" */
> +	compat = of_get_flat_dt_prop(dt_root, "compatible", NULL);
> +	if (!compat)
> +		compat = "<unknown>";
> +
> +	model = strchr(compat, ',');
> +	if (model)
> +		model++;
> +
> +	strlcpy(manufacturer, compat, model ? model - compat : strlen(compat));
> +
> +	pr_info("Board \"%s\" from %s (Manufacturer)\n", model, manufacturer);
> +
> +	/* Retrieve various information from the /chosen node */
> +	of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
> +
> +	return 0;
> +}
> diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
> index 82ac206..27aebd6 100644
> --- a/arch/arc/kernel/setup.c
> +++ b/arch/arc/kernel/setup.c
> @@ -13,6 +13,8 @@
>  #include <linux/console.h>
>  #include <linux/module.h>
>  #include <linux/cpu.h>
> +#include <linux/of_fdt.h>
> +#include <asm/sections.h>
>  #include <asm/arcregs.h>
>  #include <asm/tlb.h>
>  #include <asm/cache.h>
> @@ -20,6 +22,7 @@
>  #include <asm/page.h>
>  #include <asm/irq.h>
>  #include <asm/arcregs.h>
> +#include <asm/prom.h>
>  
>  #define FIX_PTR(x)  __asm__ __volatile__(";" : "+r"(x))
>  
> @@ -57,6 +60,8 @@ void __init __attribute__((weak)) arc_platform_early_init(void)
>  
>  void __init setup_arch(char **cmdline_p)
>  {
> +	int rc;
> +
>  #ifdef CONFIG_CMDLINE_UBOOT
>  	/* Make sure that a whitespace is inserted before */
>  	strlcat(command_line, " ", sizeof(command_line));
> @@ -71,6 +76,8 @@ void __init setup_arch(char **cmdline_p)
>  	strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
>  	*cmdline_p = command_line;
>  
> +	rc = setup_machine_fdt(__dtb_start);
> +
>  	/* To force early parsing of things like mem=xxx */
>  	parse_early_param();
>  
> @@ -81,6 +88,8 @@ void __init setup_arch(char **cmdline_p)
>  
>  	setup_arch_memory();
>  
> +	unflatten_device_tree();
> +
>  	/* Can be issue if someone passes cmd line arg "ro"
>  	 * But that is unlikely so keeping it as it is
>  	 */
> diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c
> index 63da347..682cf57 100644
> --- a/arch/arc/mm/init.c
> +++ b/arch/arc/mm/init.c
> @@ -39,6 +39,11 @@ static int __init setup_mem_sz(char *str)
>  }
>  early_param("mem", setup_mem_sz);
>  
> +void __init early_init_dt_add_memory_arch(u64 base, u64 size)
> +{
> +	pr_err("%s(%llx, %llx)\n", __func__, base, size);
> +}
> +
>  /*
>   * First memory setup routine called from setup_arch()
>   * 1. setup swapper's mm @init_mm
> @@ -169,3 +174,11 @@ void __init free_initrd_mem(unsigned long start, unsigned long end)
>  	free_init_pages("initrd memory", start, end);
>  }
>  #endif
> +
> +#ifdef CONFIG_OF_FLATTREE
> +void __init early_init_dt_setup_initrd_arch(unsigned long start,
> +					    unsigned long end)
> +{
> +	pr_err("%s(%lx, %lx)\n", __func__, start, end);
> +}
> +#endif /* CONFIG_OF_FLATTREE */
> 

Does the reworked patch look OK to you ? If so, can I get your ACK please.

Thx,
-Vineet

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v3 22/71] ARC: [Review] Prevent incorrect syscall restarts
  2013-01-24 10:50 ` [PATCH v3 22/71] ARC: [Review] Prevent incorrect syscall restarts Vineet Gupta
@ 2013-01-28  7:42   ` Vineet Gupta
  0 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-28  7:42 UTC (permalink / raw)
  To: Al Viro; +Cc: linux-arch, linux-kernel, arnd

Hi Al,

On Thursday 24 January 2013 04:20 PM, Vineet Gupta wrote:
> Per Al Viro's "signals for dummies" https://lkml.org/lkml/2012/12/6/366
> there are 3 golden rules for (not) restarting syscalls:
> 
> "	What we need to guarantee is
> * restarts do not happen on signals caught in interrupts or exceptions
> * restarts do not happen on signals caught in sigreturn()
> * restart should happen only once, even if we get through do_signal()
>   many times."
> 
> ARC Port already handled #1, this patch fixes #2 and #3.
> 
> We use the additional state in pt_regs->orig_r8 to ckh if restarting
> has already been done once.
> 
> Thanks to Al Viro for spotting this.
> 
> Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
> Cc: Al Viro <viro@ZenIV.linux.org.uk>
> ---
>  arch/arc/include/asm/ptrace.h |    3 +++
>  arch/arc/kernel/signal.c      |   12 ++++++++----
>  2 files changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
> index 1711d56..8bf7ff4 100644
> --- a/arch/arc/include/asm/ptrace.h
> +++ b/arch/arc/include/asm/ptrace.h
> @@ -135,6 +135,9 @@ struct user_regs_struct {
>  #define in_syscall(regs)    (regs->event & orig_r8_IS_SCALL)
>  #define in_brkpt_trap(regs) (regs->event & orig_r8_IS_BRKPT)
>  
> +#define syscall_wont_restart(regs) (regs->event |= orig_r8_IS_SCALL_RESTARTED)
> +#define syscall_restartable(regs) !(regs->event &  orig_r8_IS_SCALL_RESTARTED)
> +
>  #define current_pt_regs()					\
>  ({								\
>  	/* open-coded current_thread_info() */			\
> diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c
> index 887a383..9a1ea2b 100644
> --- a/arch/arc/kernel/signal.c
> +++ b/arch/arc/kernel/signal.c
> @@ -131,6 +131,9 @@ SYSCALL_DEFINE0(rt_sigreturn)
>  		if (restore_altstack(&sf->uc.uc_stack))
>  			goto badframe;
>  
> +	/* Don't restart from sigreturn */
> +	syscall_wont_restart(regs);
> +
>  	return regs->r0;
>  
>  badframe:
> @@ -321,13 +324,13 @@ void do_signal(struct pt_regs *regs)
>  
>  	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
>  
> -	/* Are we from a system call? */
> -	restart_scall = in_syscall(regs);
> +	restart_scall = in_syscall(regs) && syscall_restartable(regs);
>  
>  	if (signr > 0) {
> -		if (restart_scall)
> +		if (restart_scall) {
>  			arc_restart_syscall(&ka, regs);
> -
> +			syscall_wont_restart(regs);	/* No more restarts */
> +		}
>  		handle_signal(signr, &ka, &info, regs);
>  		return;
>  	}
> @@ -342,6 +345,7 @@ void do_signal(struct pt_regs *regs)
>  			regs->r8 = __NR_restart_syscall;
>  			regs->ret -= 4;
>  		}
> +		syscall_wont_restart(regs);	/* No more restarts */
>  	}
>  
>  	/* If there's no signal to deliver, restore the saved sigmask back */
> 

If this looks OK, can I get your ACK on this.

Thx,
-Vineet

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v3 32/71] ARC: [DeviceTree] Basic support
  2013-01-24 10:50 ` [PATCH v3 32/71] ARC: [DeviceTree] Basic support Vineet Gupta
  2013-01-28  7:40   ` Vineet Gupta
@ 2013-01-28 10:21   ` James Hogan
  2013-01-29  9:53     ` Vineet Gupta
  2013-01-29 13:25   ` Rob Herring
  2 siblings, 1 reply; 57+ messages in thread
From: James Hogan @ 2013-01-28 10:21 UTC (permalink / raw)
  To: Vineet Gupta
  Cc: linux-arch, linux-kernel, arnd, Grant Likely, devicetree-discuss,
	Rob Herring

Hi Vineet,

On 24/01/13 10:50, Vineet Gupta wrote:
> diff --git a/arch/arc/Makefile b/arch/arc/Makefile
> index 4d52a3b..90570f9 100644
> --- a/arch/arc/Makefile
> +++ b/arch/arc/Makefile
> @@ -83,6 +83,9 @@ head-y		:= arch/arc/kernel/head.o
>  # See arch/arc/Kbuild for content of core part of the kernel
>  core-y		+= arch/arc/
>  
> +# w/o this dtb won't embed into kernel binary
> +core-y		+= arch/arc/boot/dts/
> +
>  # w/o this ifneq, make ARCH=arc clean was crapping out
>  ifneq ($(platform-y),)
>  core-y		+= arch/arc/plat-$(PLATFORM)/
> @@ -101,6 +104,12 @@ bootpImage: vmlinux
>  uImage: vmlinux
>  	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
>  
> +%.dtb %.dtb.S %.dtb.o:
> +	$(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@

arm64 also depends on scripts here, presumably for a reason. I've copied
this in metag too.

> +
> +dtbs:
> +	$(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@

arm64 does this like below which I think is slightly nicer than how
metag did it:

dtbs: scripts
	$(Q)$(MAKE) $(build)=$(boot)/dts dtbs

> +
>  archclean:
>  	$(Q)$(MAKE) $(clean)=$(boot)
>  
> diff --git a/arch/arc/boot/dts/Makefile b/arch/arc/boot/dts/Makefile
> new file mode 100644
> index 0000000..4a972a3
> --- /dev/null
> +++ b/arch/arc/boot/dts/Makefile
> @@ -0,0 +1,14 @@
> +ifeq ($(CONFIG_OF),y)
> +
> +# Built-in dtb
> +builtindtb-y		:= skeleton
> +
> +ifneq ($(CONFIG_ARC_BUILTIN_DTB_NAME),"")
> +	builtindtb-y	:= $(CONFIG_ARC_BUILTIN_DTB_NAME)
> +endif
> +
> +obj-y	+= $(patsubst "%",%,$(builtindtb-y)).dtb.o
> +
> +clean-files := *.dtb

You don't seem to have a rule for dtbs, but still redirect it in the
main Makefile. I suppose dtbs may want adding to your archhelp if you
use it.

arm64 also adds dtbs and $(dtb-y) to targets (at least in linux-next). I
think this makes sure that they don't get rebuilt unless they've
actually changed. I've also copied this for metag.


> --- a/arch/arc/kernel/Makefile
> +++ b/arch/arc/kernel/Makefile
> @@ -8,6 +8,8 @@
>  obj-y	:= arcksyms.o setup.o irq.o time.o reset.o ptrace.o entry.o process.o
>  obj-y	+= signal.o traps.o sys.o troubleshoot.o stacktrace.o clk.o
>  
> +obj-$(CONFIG_OF)			+= devtree.o
> +

You always select CONFIG_OF, so this could be obj-y. I'm not sure this
particularly matters though.

Cheers
James


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v3 02/71] ARC: Build system: Makefiles, Kconfig, Linker script
  2013-01-28  6:29   ` Vineet Gupta
@ 2013-01-28 18:44     ` Sam Ravnborg
  2013-01-29 13:45       ` Vineet Gupta
  0 siblings, 1 reply; 57+ messages in thread
From: Sam Ravnborg @ 2013-01-28 18:44 UTC (permalink / raw)
  To: Vineet Gupta; +Cc: linux-arch, linux-kernel, arnd

On Mon, Jan 28, 2013 at 11:59:36AM +0530, Vineet Gupta wrote:
> Hi Sam,
> 
> On Thursday 24 January 2013 04:20 PM, Vineet Gupta wrote:
> > Arnd in his review pointed out that arch Kconfig organisation has several
> > deficiencies:
> > 
> > * Build time entries for things which can be runtime extracted from DT
> >   (e.g. SDRAM size, core clk frequency..)
> > * Not multi-platform-image-build friendly (choice .. endchoice constructs)
> > * cpu variants support (750/770) is exclusive.
> > 
> > The first 2 have been fixed in subsequent patches.
> > Due to the nature of the 750 and 770, it is not possible to build for
> > both together, w/o special runtime glue code which would hurt
> > performance.
> > 
> > Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
> > Cc: Arnd Bergmann <arnd@arndb.de>
> > Cc: Sam Ravnborg <sam@ravnborg.org>

Looks good - all former comments addressed, and nothing were jumping
into my eyes now.
Many existing architectures looks worse from the build stuff perspective...

Acked-by: Sam Ravnborg <sam@ravnborg.org>

	Sam

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v3 32/71] ARC: [DeviceTree] Basic support
  2013-01-28 10:21   ` James Hogan
@ 2013-01-29  9:53     ` Vineet Gupta
  2013-01-29 10:06       ` James Hogan
  0 siblings, 1 reply; 57+ messages in thread
From: Vineet Gupta @ 2013-01-29  9:53 UTC (permalink / raw)
  To: James Hogan
  Cc: linux-arch, linux-kernel, arnd, Grant Likely, devicetree-discuss,
	Rob Herring

Hi James,

On Monday 28 January 2013 03:51 PM, James Hogan wrote:
> Hi Vineet,
> 
> On 24/01/13 10:50, Vineet Gupta wrote:
>> diff --git a/arch/arc/Makefile b/arch/arc/Makefile
>> index 4d52a3b..90570f9 100644
>> --- a/arch/arc/Makefile
>> +++ b/arch/arc/Makefile
>> @@ -83,6 +83,9 @@ head-y		:= arch/arc/kernel/head.o
>>  # See arch/arc/Kbuild for content of core part of the kernel
>>  core-y		+= arch/arc/
>>  
>> +# w/o this dtb won't embed into kernel binary
>> +core-y		+= arch/arc/boot/dts/
>> +
>>  # w/o this ifneq, make ARCH=arc clean was crapping out
>>  ifneq ($(platform-y),)
>>  core-y		+= arch/arc/plat-$(PLATFORM)/
>> @@ -101,6 +104,12 @@ bootpImage: vmlinux
>>  uImage: vmlinux
>>  	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
>>  
>> +%.dtb %.dtb.S %.dtb.o:
>> +	$(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@
> 
> arm64 also depends on scripts here, presumably for a reason. I've copied
> this in metag too.

It probably has to do with forcing rebuild of DTs, in case scripts/dtc/dtc changes.

I'll add that as well.


>> +
>> +dtbs:
>> +	$(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@
> 
> arm64 does this like below which I think is slightly nicer than how
> metag did it:
> 
> dtbs: scripts
> 	$(Q)$(MAKE) $(build)=$(boot)/dts dtbs

OK !

>> +
>>  archclean:
>>  	$(Q)$(MAKE) $(clean)=$(boot)
>>  
>> diff --git a/arch/arc/boot/dts/Makefile b/arch/arc/boot/dts/Makefile
>> new file mode 100644
>> index 0000000..4a972a3
>> --- /dev/null
>> +++ b/arch/arc/boot/dts/Makefile
>> @@ -0,0 +1,14 @@
>> +ifeq ($(CONFIG_OF),y)
>> +
>> +# Built-in dtb
>> +builtindtb-y		:= skeleton
>> +
>> +ifneq ($(CONFIG_ARC_BUILTIN_DTB_NAME),"")
>> +	builtindtb-y	:= $(CONFIG_ARC_BUILTIN_DTB_NAME)
>> +endif
>> +
>> +obj-y	+= $(patsubst "%",%,$(builtindtb-y)).dtb.o
>> +
>> +clean-files := *.dtb
> 
> You don't seem to have a rule for dtbs, but still redirect it in the
> main Makefile. I suppose dtbs may want adding to your archhelp if you
> use it.

The dtbs rule doesn't seem to be working for me here. I'll need to investigate a bit.

> 
> arm64 also adds dtbs and $(dtb-y) to targets (at least in linux-next). I
> think this makes sure that they don't get rebuilt unless they've
> actually changed. I've also copied this for metag.

Did you verify that it makes a difference - at least at my end it's not - the
default dtb is getting rebuilt everytime. I need to debug this some more.


>> --- a/arch/arc/kernel/Makefile
>> +++ b/arch/arc/kernel/Makefile
>> @@ -8,6 +8,8 @@
>>  obj-y	:= arcksyms.o setup.o irq.o time.o reset.o ptrace.o entry.o process.o
>>  obj-y	+= signal.o traps.o sys.o troubleshoot.o stacktrace.o clk.o
>>  
>> +obj-$(CONFIG_OF)			+= devtree.o
>> +
> 
> You always select CONFIG_OF, so this could be obj-y. I'm not sure this
> particularly matters though.

Right, for consistency we might add this unconditionally.

Thanks for your review
-Vineet



^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v3 32/71] ARC: [DeviceTree] Basic support
  2013-01-29  9:53     ` Vineet Gupta
@ 2013-01-29 10:06       ` James Hogan
  0 siblings, 0 replies; 57+ messages in thread
From: James Hogan @ 2013-01-29 10:06 UTC (permalink / raw)
  To: Vineet Gupta
  Cc: linux-arch, linux-kernel, arnd, Grant Likely, devicetree-discuss,
	Rob Herring

Hi Vineet,

>> arm64 also adds dtbs and $(dtb-y) to targets (at least in linux-next). I
>> think this makes sure that they don't get rebuilt unless they've
>> actually changed. I've also copied this for metag.
> 
> Did you verify that it makes a difference - at least at my end it's not - the
> default dtb is getting rebuilt everytime. I need to debug this some more.

Yeh, for me it prevents the following build lines appearing every time:
DTC     arch/metag/boot/dts/tz1090_01sp.dtb

but it still does these every time:
DTB    arch/metag/boot/dts/tz1090_01sp.dtb.S
AS      arch/metag/boot/dts/tz1090_01sp.dtb.o

Adding dtbs o targets actually didn't seem to be necessary with $(dtb-y)
added.

Cheers
James


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v3 32/71] ARC: [DeviceTree] Basic support
  2013-01-24 10:50 ` [PATCH v3 32/71] ARC: [DeviceTree] Basic support Vineet Gupta
  2013-01-28  7:40   ` Vineet Gupta
  2013-01-28 10:21   ` James Hogan
@ 2013-01-29 13:25   ` Rob Herring
  2013-01-29 13:39     ` Vineet Gupta
  2 siblings, 1 reply; 57+ messages in thread
From: Rob Herring @ 2013-01-29 13:25 UTC (permalink / raw)
  To: Vineet Gupta
  Cc: linux-arch, linux-kernel, arnd, Grant Likely, devicetree-discuss

On 01/24/2013 04:50 AM, Vineet Gupta wrote:
> This is minimal infrastructure needed for devicetree work.
> It uses an a sample "skeleton" devicetree - embedded in kernel image -
> to print the board, manufacturer by parsing the top-level "compatible"
> string.
> 
> As of now we don't need any additional "board" specific "machine_desc".
> 
> TODO: support interpreting the command line as boot-loader passed dtb
> 
> Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: devicetree-discuss@lists.ozlabs.org
> Cc: Rob Herring <rob.herring@calxeda.com>

One minor thing below, otherwise:

Reviewed-by: Rob Herring <rob.herring@calxeda.com>


> diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c
> new file mode 100644
> index 0000000..229f78e
> --- /dev/null
> +++ b/arch/arc/kernel/devtree.c
> @@ -0,0 +1,69 @@
> +/*
> + * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
> + *
> + * Based on highly stipped down version of METAG
> + *
> + * 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.
> + */
> +
> +
> +#include <linux/init.h>
> +#include <linux/export.h>
> +#include <linux/errno.h>

Is this include needed?

> +#include <linux/types.h>
> +#include <linux/reboot.h>

And this?

> +#include <linux/memblock.h>
> +#include <linux/of.h>
> +#include <linux/of_fdt.h>
> +#include <linux/of_irq.h>

And this?

> +#include <linux/of_platform.h>

And this?

> +#include <asm/prom.h>
> +
> +/* called from unflatten_device_tree() to bootstrap devicetree itself */
> +void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
> +{
> +	return __va(memblock_alloc(size, align));
> +}
> +
> +/**
> + * setup_machine_fdt - Machine setup when an dtb was passed to the kernel
> + * @dt:		virtual address pointer to dt blob
> + *
> + * If a dtb was passed to the kernel, then use it to choose the correct
> + * machine_desc and to setup the system.
> + */
> +int __init setup_machine_fdt(void *dt)
> +{
> +	struct boot_param_header *devtree = dt;
> +	unsigned long dt_root;
> +	char *model, *compat;
> +	char manufacturer[16];
> +
> +	/* check device tree validity */
> +	if (be32_to_cpu(devtree->magic) != OF_DT_HEADER)
> +		return 1;
> +
> +	/* Search the mdescs for the 'best' compatible value match */
> +	initial_boot_params = devtree;
> +	dt_root = of_get_flat_dt_root();
> +
> +	/* compat = "<manufacturer>,<model>" */
> +	compat = of_get_flat_dt_prop(dt_root, "compatible", NULL);
> +	if (!compat)
> +		compat = "<unknown>";
> +
> +	model = strchr(compat, ',');
> +	if (model)
> +		model++;
> +
> +	strlcpy(manufacturer, compat, model ? model - compat : strlen(compat));
> +
> +	pr_info("Board \"%s\" from %s (Manufacturer)\n", model, manufacturer);
> +
> +	/* Retrieve various information from the /chosen node */
> +	of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
> +
> +	return 0;
> +}
> diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
> index 82ac206..27aebd6 100644
> --- a/arch/arc/kernel/setup.c
> +++ b/arch/arc/kernel/setup.c
> @@ -13,6 +13,8 @@
>  #include <linux/console.h>
>  #include <linux/module.h>
>  #include <linux/cpu.h>
> +#include <linux/of_fdt.h>
> +#include <asm/sections.h>
>  #include <asm/arcregs.h>
>  #include <asm/tlb.h>
>  #include <asm/cache.h>
> @@ -20,6 +22,7 @@
>  #include <asm/page.h>
>  #include <asm/irq.h>
>  #include <asm/arcregs.h>
> +#include <asm/prom.h>
>  
>  #define FIX_PTR(x)  __asm__ __volatile__(";" : "+r"(x))
>  
> @@ -57,6 +60,8 @@ void __init __attribute__((weak)) arc_platform_early_init(void)
>  
>  void __init setup_arch(char **cmdline_p)
>  {
> +	int rc;
> +
>  #ifdef CONFIG_CMDLINE_UBOOT
>  	/* Make sure that a whitespace is inserted before */
>  	strlcat(command_line, " ", sizeof(command_line));
> @@ -71,6 +76,8 @@ void __init setup_arch(char **cmdline_p)
>  	strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
>  	*cmdline_p = command_line;
>  
> +	rc = setup_machine_fdt(__dtb_start);
> +
>  	/* To force early parsing of things like mem=xxx */
>  	parse_early_param();
>  
> @@ -81,6 +88,8 @@ void __init setup_arch(char **cmdline_p)
>  
>  	setup_arch_memory();
>  
> +	unflatten_device_tree();
> +
>  	/* Can be issue if someone passes cmd line arg "ro"
>  	 * But that is unlikely so keeping it as it is
>  	 */
> diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c
> index 63da347..682cf57 100644
> --- a/arch/arc/mm/init.c
> +++ b/arch/arc/mm/init.c
> @@ -39,6 +39,11 @@ static int __init setup_mem_sz(char *str)
>  }
>  early_param("mem", setup_mem_sz);
>  
> +void __init early_init_dt_add_memory_arch(u64 base, u64 size)
> +{
> +	pr_err("%s(%llx, %llx)\n", __func__, base, size);
> +}
> +
>  /*
>   * First memory setup routine called from setup_arch()
>   * 1. setup swapper's mm @init_mm
> @@ -169,3 +174,11 @@ void __init free_initrd_mem(unsigned long start, unsigned long end)
>  	free_init_pages("initrd memory", start, end);
>  }
>  #endif
> +
> +#ifdef CONFIG_OF_FLATTREE
> +void __init early_init_dt_setup_initrd_arch(unsigned long start,
> +					    unsigned long end)
> +{
> +	pr_err("%s(%lx, %lx)\n", __func__, start, end);
> +}
> +#endif /* CONFIG_OF_FLATTREE */
> 

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v3 32/71] ARC: [DeviceTree] Basic support
  2013-01-29 13:25   ` Rob Herring
@ 2013-01-29 13:39     ` Vineet Gupta
  0 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-01-29 13:39 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-arch, linux-kernel, arnd, Grant Likely, devicetree-discuss

On Tuesday 29 January 2013 06:55 PM, Rob Herring wrote:
> On 01/24/2013 04:50 AM, Vineet Gupta wrote:
>> This is minimal infrastructure needed for devicetree work.
>> It uses an a sample "skeleton" devicetree - embedded in kernel image -
>> to print the board, manufacturer by parsing the top-level "compatible"
>> string.
>>
>> As of now we don't need any additional "board" specific "machine_desc".
>>
>> TODO: support interpreting the command line as boot-loader passed dtb
>>
>> Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
>> Cc: Arnd Bergmann <arnd@arndb.de>
>> Cc: Grant Likely <grant.likely@secretlab.ca>
>> Cc: devicetree-discuss@lists.ozlabs.org
>> Cc: Rob Herring <rob.herring@calxeda.com>
> One minor thing below, otherwise:
>
> Reviewed-by: Rob Herring <rob.herring@calxeda.com>
>
>
>> diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c
>> new file mode 100644
>> index 0000000..229f78e
>> --- /dev/null
>> +++ b/arch/arc/kernel/devtree.c
>> @@ -0,0 +1,69 @@
>> +/*
>> + * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
>> + *
>> + * Based on highly stipped down version of METAG
>> + *
>> + * 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.
>> + */
>> +
>> +
>> +#include <linux/init.h>
>> +#include <linux/export.h>
>> +#include <linux/errno.h>
> Is this include needed?

Nope - removed.

>
>> +#include <linux/types.h>
>> +#include <linux/reboot.h>
> And this?

reboot.h is needed for the machine_halt() prototype.

>
>> +#include <linux/memblock.h>
>> +#include <linux/of.h>
>> +#include <linux/of_fdt.h>
>> +#include <linux/of_irq.h>
> And this?
>
>> +#include <linux/of_platform.h>
> And this?

Both of the above removed.

I'll send a revised patch which also addresses James' review comments as well -
(namely broken dtbs rule, adding dependency on scripts ...)
See https://lkml.org/lkml/2013/1/28/138 for reference.


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v3 02/71] ARC: Build system: Makefiles, Kconfig, Linker script
  2013-01-28 18:44     ` Sam Ravnborg
@ 2013-01-29 13:45       ` Vineet Gupta
  2013-01-29 17:52         ` Sam Ravnborg
  0 siblings, 1 reply; 57+ messages in thread
From: Vineet Gupta @ 2013-01-29 13:45 UTC (permalink / raw)
  To: Sam Ravnborg; +Cc: linux-arch, linux-kernel, arnd

On Tuesday 29 January 2013 12:14 AM, Sam Ravnborg wrote:
> On Mon, Jan 28, 2013 at 11:59:36AM +0530, Vineet Gupta wrote:
>> Hi Sam,
>>
>> On Thursday 24 January 2013 04:20 PM, Vineet Gupta wrote:
>>> Arnd in his review pointed out that arch Kconfig organisation has several
>>> deficiencies:
>>>
>>> * Build time entries for things which can be runtime extracted from DT
>>>   (e.g. SDRAM size, core clk frequency..)
>>> * Not multi-platform-image-build friendly (choice .. endchoice constructs)
>>> * cpu variants support (750/770) is exclusive.
>>>
>>> The first 2 have been fixed in subsequent patches.
>>> Due to the nature of the 750 and 770, it is not possible to build for
>>> both together, w/o special runtime glue code which would hurt
>>> performance.
>>>
>>> Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
>>> Cc: Arnd Bergmann <arnd@arndb.de>
>>> Cc: Sam Ravnborg <sam@ravnborg.org>
> Looks good - all former comments addressed, and nothing were jumping
> into my eyes now.
> Many existing architectures looks worse from the build stuff perspective...
>
> Acked-by: Sam Ravnborg <sam@ravnborg.org>
>
> 	Sam

Thx Sam. I have a following one liner change to the version you reviewed. Will it
be OK to add your ACK despite that or do I need to send the updated patch for you
to take a look again.

-Vineet

------------------------->8-----------------------
diff --git a/arch/arc/plat-arcfpga/Kconfig b/arch/arc/plat-arcfpga/Kconfig
index 3fecd6f..b41e786 100644
--- a/arch/arc/plat-arcfpga/Kconfig
+++ b/arch/arc/plat-arcfpga/Kconfig
@@ -8,6 +8,7 @@
 
 menuconfig ARC_PLAT_FPGA_LEGACY
     bool "\"Legacy\" ARC FPGA dev Boards"
+    select ISS_SMP_EXTN if SMP
     help
       Support for ARC development boards, provided by Synopsys.
       These are based on FPGA or ISS. e.g.
@@ -19,7 +20,6 @@ if ARC_PLAT_FPGA_LEGACY
 
 config ARC_BOARD_ANGEL4
     bool "ARC Angel4"
-    select ISS_SMP_EXTN if SMP
     default y
     help
       ARC Angel4 FPGA Ref Platform (Xilinx Virtex Based)
------------------------->8-----------------------


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCH v3 02/71] ARC: Build system: Makefiles, Kconfig, Linker script
  2013-01-29 13:45       ` Vineet Gupta
@ 2013-01-29 17:52         ` Sam Ravnborg
  0 siblings, 0 replies; 57+ messages in thread
From: Sam Ravnborg @ 2013-01-29 17:52 UTC (permalink / raw)
  To: Vineet Gupta; +Cc: linux-arch, linux-kernel, arnd

On Tue, Jan 29, 2013 at 07:15:07PM +0530, Vineet Gupta wrote:
> On Tuesday 29 January 2013 12:14 AM, Sam Ravnborg wrote:
> > On Mon, Jan 28, 2013 at 11:59:36AM +0530, Vineet Gupta wrote:
> >> Hi Sam,
> >>
> >> On Thursday 24 January 2013 04:20 PM, Vineet Gupta wrote:
> >>> Arnd in his review pointed out that arch Kconfig organisation has several
> >>> deficiencies:
> >>>
> >>> * Build time entries for things which can be runtime extracted from DT
> >>>   (e.g. SDRAM size, core clk frequency..)
> >>> * Not multi-platform-image-build friendly (choice .. endchoice constructs)
> >>> * cpu variants support (750/770) is exclusive.
> >>>
> >>> The first 2 have been fixed in subsequent patches.
> >>> Due to the nature of the 750 and 770, it is not possible to build for
> >>> both together, w/o special runtime glue code which would hurt
> >>> performance.
> >>>
> >>> Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
> >>> Cc: Arnd Bergmann <arnd@arndb.de>
> >>> Cc: Sam Ravnborg <sam@ravnborg.org>
> > Looks good - all former comments addressed, and nothing were jumping
> > into my eyes now.
> > Many existing architectures looks worse from the build stuff perspective...
> >
> > Acked-by: Sam Ravnborg <sam@ravnborg.org>
> >
> > 	Sam
> 
> Thx Sam. I have a following one liner change to the version you reviewed. Will it
> be OK to add your ACK despite that or do I need to send the updated patch for you
> to take a look again.
OK

^ permalink raw reply	[flat|nested] 57+ messages in thread

* pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling)
  2013-01-24 10:50 ` [PATCH v3 20/71] ARC: Signal handling Vineet Gupta
@ 2013-02-11  7:26   ` Vineet Gupta
  2013-02-11  9:36     ` Jonas Bonn
  0 siblings, 1 reply; 57+ messages in thread
From: Vineet Gupta @ 2013-02-11  7:26 UTC (permalink / raw)
  To: arnd; +Cc: linux-arch, linux-kernel, Al Viro

Hi Arnd,

On Thursday 24 January 2013 04:20 PM, Vineet Gupta wrote:
> Includes following fixes courtesy review by Al-Viro
> 
> * Tracer poke to Callee-regs were lost
> 
>   Before going off into do_signal( ) we save the user-mode callee regs
>   (as they are not saved by default as part of pt_regs). This is to make
>   sure that that a Tracer (if tracing related signal) is able to do likes
>   of PEEKUSR(callee-reg).
> 
>   However in return path we were simply discarding the user-mode callee
>   regs, which would break a POKEUSR(callee-reg) from a tracer.
> 
> * Issue related to multiple syscall restarts are addressed in next patch
> 
> Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
> Cc: Al Viro <viro@ZenIV.linux.org.uk>

[snipped...]

> +#ifndef _ASM_ARC_SIGCONTEXT_H
> +#define _ASM_ARC_SIGCONTEXT_H
> +
> +#include <asm/ptrace.h>
> +
> +/*
> + * Signal context structure - contains all info to do with the state
> + * before the signal handler was invoked.  Note: only add new entries
> + * to the end of the structure.
> + */
> +struct sigcontext {
> +	struct pt_regs regs;
> +};

I ran into a pt_regs "leak" into userspace ABI - causing some apps build failures.
This prompted me to clean the slight mess in that area (patch inline below). The
"fundamental-ness" of this patch warrants a chop-n-dice-n-squash into orig series
(vs. a addon change) hence the reason for running this by you.

The fundamental change is following - with everything else being a adjustment for it.

 struct sigcontext {
-	struct pt_regs regs;
+	struct user_regs_struct regs;
 };

 struct user_regs_struct {
-	struct pt_regs scratch;
-	struct callee_regs callee;
+	struct scratch {
+		long pad;
+		long bta, lp_start, lp_end, lp_count;
+		long status32, ret, blink, fp, gp;
+		long r12, r11, r10, r9, r8, r7, r6, r5, r4, r3, r2, r1, r0;
+		long sp;
+	} scratch;
+	struct callee {
+		long pad;
+		long r25, r24, r23, r22, r21, r20;
+		long r19, r18, r17, r16, r15, r14, r13;
+	} callee;
	long efa;	/* break pt addr, for break points in delay slots */
	long stop_pc;	/* give dbg stop_pc directly after checking orig_r8 */
 };


The only downside of this patch is that userspace signal stack grows in size,
since signal frame only cares about scratch regs (pt_regs), but has to accommodate
unused placeholder for callee regs too by virtue of using user_regs_struct.

Please let me know if you OK with merge of this patch into linux-next, (obviously
after chop-n-dice-n-squash).

Thx,
-Vineet

--------------------->
From: Vineet Gupta <vgupta@synopsys.com>
Date: Mon, 11 Feb 2013 12:47:28 +0530
Subject: [PATCH] ARC RFC: Establish user_regs_struct for ABI

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/include/asm/entry.h           |    1 -
 arch/arc/include/asm/ptrace.h          |   17 ++++------
 arch/arc/include/uapi/asm/ptrace.h     |   56 ++++++++++++++++----------------
 arch/arc/include/uapi/asm/sigcontext.h |    5 +--
 arch/arc/kernel/asm-offsets.c          |   19 +++++++++--
 arch/arc/kernel/signal.c               |    5 ++-
 6 files changed, 56 insertions(+), 47 deletions(-)

diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h
index 23daa32..9f544fa 100644
--- a/arch/arc/include/asm/entry.h
+++ b/arch/arc/include/asm/entry.h
@@ -35,7 +35,6 @@
 #include <asm/unistd.h>		/* For NR_syscalls defination */
 #include <asm/asm-offsets.h>
 #include <asm/arcregs.h>
-#include <asm/ptrace.h>
 #include <asm/processor.h>	/* For VMALLOC_START */
 #include <asm/thread_info.h>	/* For THREAD_SIZE */

diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
index 95e633e..7d4cc32 100644
--- a/arch/arc/include/asm/ptrace.h
+++ b/arch/arc/include/asm/ptrace.h
@@ -50,13 +50,17 @@ struct pt_regs {
 	long r0;
 	long sp;	/* user/kernel sp depending on where we came from  */
 	long orig_r0;
+
 	/*to distinguish bet excp, syscall, irq */
+	union {
+		/* so that assembly code is same for LE/BE */
 #ifdef CONFIG_CPU_BIG_ENDIAN
-	/* so that assembly code is same for LE/BE */
-	unsigned long orig_r8:16, event:16;
+		unsigned long orig_r8:16, event:16;
 #else
-	unsigned long event:16, orig_r8:16;
+		unsigned long event:16, orig_r8:16;
 #endif
+		long orig_r8_word;
+	};
 };

 /* Callee saved registers - need to be saved only when you are scheduled out */
@@ -78,13 +82,6 @@ struct callee_regs {
 	long r13;
 };

-/* User mode registers, used for core dumps. */
-struct user_regs_struct {
-	struct pt_regs scratch;
-	struct callee_regs callee;
-	long efa;	/* break pt addr, for break points in delay slots */
-	long stop_pc;	/* give dbg stop_pc directly after checking orig_r8 */
-};

 #define instruction_pointer(regs)	((regs)->ret)
 #define profile_pc(regs)		instruction_pointer(regs)
diff --git a/arch/arc/include/uapi/asm/ptrace.h b/arch/arc/include/uapi/asm/ptrace.h
index bccf4ab..bacb411 100644
--- a/arch/arc/include/uapi/asm/ptrace.h
+++ b/arch/arc/include/uapi/asm/ptrace.h
@@ -12,35 +12,35 @@
 #define _UAPI__ASM_ARC_PTRACE_H

 /*
- * XXX: ABI hack.
- * The offset calc can be cleanly done in asm-offset.c, however gdb includes
- * this header directly.
+ * Userspace ABI: Register state needed by
+ *  -ptrace (gdbserver)
+ *  -sigcontext (SA_SIGNINFO signal frame)
+ *
+ * This is to decouple pt_regs from user-space ABI, to be able to change it
+ * w/o affecting the ABI.
+ * Although the layout (initial padding) is similar to pt_regs to have some
+ * optimizations when copying pt_regs to/from user_regs_struct.
+ *
+ * Also, sigcontext only care about the scratch regs as that is what we really
+ * save/restore for signal handling.
  */
-#define PT_bta		4
-#define PT_lp_start	8
-#define PT_lp_end	12
-#define PT_lp_count	16
-#define PT_status32	20
-#define PT_ret		24
-#define PT_blink	28
-#define PT_fp		32
-#define PT_r26		36
-#define PT_r12		40
-#define PT_r11		44
-#define PT_r10		48
-#define PT_r9		52
-#define PT_r8		56
-#define PT_r7		60
-#define PT_r6		64
-#define PT_r5		68
-#define PT_r4		72
-#define PT_r3		76
-#define PT_r2		80
-#define PT_r1		84
-#define PT_r0		88
-#define PT_sp		92
-#define PT_orig_r0	96
-#define PT_orig_r8	100
+struct user_regs_struct {
+
+	struct scratch {
+		long pad;
+		long bta, lp_start, lp_end, lp_count;
+		long status32, ret, blink, fp, gp;
+		long r12, r11, r10, r9, r8, r7, r6, r5, r4, r3, r2, r1, r0;
+		long sp;
+	} scratch;
+	struct callee {
+		long pad;
+		long r25, r24, r23, r22, r21, r20;
+		long r19, r18, r17, r16, r15, r14, r13;
+	} callee;
+	long efa;	/* break pt addr, for break points in delay slots */
+	long stop_pc;	/* give dbg stop_pc directly after checking orig_r8 */
+};


 #endif /* _UAPI__ASM_ARC_PTRACE_H */
diff --git a/arch/arc/include/uapi/asm/sigcontext.h
b/arch/arc/include/uapi/asm/sigcontext.h
index f21b541..9678a11 100644
--- a/arch/arc/include/uapi/asm/sigcontext.h
+++ b/arch/arc/include/uapi/asm/sigcontext.h
@@ -13,11 +13,10 @@

 /*
  * Signal context structure - contains all info to do with the state
- * before the signal handler was invoked.  Note: only add new entries
- * to the end of the structure.
+ * before the signal handler was invoked.
  */
 struct sigcontext {
-	struct pt_regs regs;
+	struct user_regs_struct regs;
 };

 #endif /* _ASM_ARC_SIGCONTEXT_H */
diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c
index 0c06b7a..b0197ad 100644
--- a/arch/arc/kernel/asm-offsets.c
+++ b/arch/arc/kernel/asm-offsets.c
@@ -9,11 +9,11 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
-#include <asm/hardirq.h>
 #include <linux/thread_info.h>
-#include <asm/page.h>
 #include <linux/kbuild.h>
-#include <asm/event-log.h>
+#include <asm/hardirq.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>

 int main(void)
 {
@@ -46,6 +46,19 @@ int main(void)

 	DEFINE(MM_CTXT_ASID, offsetof(mm_context_t, asid));

+	BLANK();
+
+	DEFINE(PT_status32, offsetof(struct pt_regs, status32));
+	DEFINE(PT_orig_r8, offsetof(struct pt_regs, orig_r8_word));
+	DEFINE(PT_r0, offsetof(struct pt_regs, r0));
+	DEFINE(PT_r1, offsetof(struct pt_regs, r1));
+	DEFINE(PT_r2, offsetof(struct pt_regs, r2));
+	DEFINE(PT_r3, offsetof(struct pt_regs, r3));
+	DEFINE(PT_r4, offsetof(struct pt_regs, r4));
+	DEFINE(PT_r5, offsetof(struct pt_regs, r5));
+	DEFINE(PT_r6, offsetof(struct pt_regs, r6));
+	DEFINE(PT_r7, offsetof(struct pt_regs, r7));
+
 #ifdef CONFIG_ARC_DBG_EVENT_TIMELINE
 	BLANK();
 	DEFINE(EVLOG_FIELD_EXTRA, offsetof(timeline_log_t, extra));
diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c
index d16740d..e56bb7d 100644
--- a/arch/arc/kernel/signal.c
+++ b/arch/arc/kernel/signal.c
@@ -70,7 +70,8 @@ stash_usr_regs(struct rt_sigframe __user *sf, struct pt_regs *regs,
 	       sigset_t *set)
 {
 	int err;
-	err = __copy_to_user(&(sf->uc.uc_mcontext.regs), regs, sizeof(*regs));
+	err = __copy_to_user(&(sf->uc.uc_mcontext.regs), regs,
+				sizeof(sf->uc.uc_mcontext.regs.scratch));
 	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(sigset_t));

 	return err;
@@ -88,7 +89,7 @@ static int restore_usr_regs(struct pt_regs *regs, struct
rt_sigframe __user *sf)
 	}

 	err |= __copy_from_user(regs, &(sf->uc.uc_mcontext.regs),
-				sizeof(*regs));
+				sizeof(sf->uc.uc_mcontext.regs.scratch));

 	return err;
 }
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling)
  2013-02-11  7:26   ` pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling) Vineet Gupta
@ 2013-02-11  9:36     ` Jonas Bonn
  2013-02-11 10:13       ` Vineet Gupta
  0 siblings, 1 reply; 57+ messages in thread
From: Jonas Bonn @ 2013-02-11  9:36 UTC (permalink / raw)
  To: Vineet Gupta; +Cc: Arnd Bergmann, linux-arch, linux-kernel, Al Viro

On 11 February 2013 08:26, Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:

>
> The only downside of this patch is that userspace signal stack grows in size,
> since signal frame only cares about scratch regs (pt_regs), but has to accommodate
> unused placeholder for callee regs too by virtue of using user_regs_struct.

Is this really true?  Don't setcontext and friends require that _all_
the registers be part of sigcontext?

/Jonas

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling)
  2013-02-11  9:36     ` Jonas Bonn
@ 2013-02-11 10:13       ` Vineet Gupta
  2013-02-11 10:28         ` James Hogan
  2013-02-11 10:30         ` Jonas Bonn
  0 siblings, 2 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-02-11 10:13 UTC (permalink / raw)
  To: Jonas Bonn; +Cc: Arnd Bergmann, linux-arch, linux-kernel, Al Viro

On Monday 11 February 2013 03:06 PM, Jonas Bonn wrote:
> On 11 February 2013 08:26, Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
>
>> The only downside of this patch is that userspace signal stack grows in size,
>> since signal frame only cares about scratch regs (pt_regs), but has to accommodate
>> unused placeholder for callee regs too by virtue of using user_regs_struct.
> Is this really true?  Don't setcontext and friends require that _all_
> the registers be part of sigcontext?

But for an ABI - callee saved regs will anyhow be saved/restored even in
setcontext case ! So collecting it for that purpose seems useless, or am I missing
something here.

-Vineet


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling)
  2013-02-11 10:13       ` Vineet Gupta
@ 2013-02-11 10:28         ` James Hogan
  2013-02-11 10:53           ` Jonas Bonn
  2013-02-11 10:30         ` Jonas Bonn
  1 sibling, 1 reply; 57+ messages in thread
From: James Hogan @ 2013-02-11 10:28 UTC (permalink / raw)
  To: Vineet Gupta; +Cc: Jonas Bonn, Arnd Bergmann, linux-arch, linux-kernel, Al Viro

On 11/02/13 10:13, Vineet Gupta wrote:
> On Monday 11 February 2013 03:06 PM, Jonas Bonn wrote:
>> On 11 February 2013 08:26, Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
>>
>>> The only downside of this patch is that userspace signal stack grows in size,
>>> since signal frame only cares about scratch regs (pt_regs), but has to accommodate
>>> unused placeholder for callee regs too by virtue of using user_regs_struct.
>> Is this really true?  Don't setcontext and friends require that _all_
>> the registers be part of sigcontext?
> 
> But for an ABI - callee saved regs will anyhow be saved/restored even in
> setcontext case ! So collecting it for that purpose seems useless, or am I missing
> something here.

I think Jonas' point was that signals are asynchronous, i.e. you could
get interrupted by a signal at virtually any time during the program's
execution.

Cheers
James


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling)
  2013-02-11 10:13       ` Vineet Gupta
  2013-02-11 10:28         ` James Hogan
@ 2013-02-11 10:30         ` Jonas Bonn
  2013-02-11 14:07           ` Al Viro
  1 sibling, 1 reply; 57+ messages in thread
From: Jonas Bonn @ 2013-02-11 10:30 UTC (permalink / raw)
  To: Vineet Gupta; +Cc: Arnd Bergmann, linux-arch, linux-kernel, Al Viro

On 11 February 2013 11:13, Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
> On Monday 11 February 2013 03:06 PM, Jonas Bonn wrote:
>> On 11 February 2013 08:26, Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
>>
>>> The only downside of this patch is that userspace signal stack grows in size,
>>> since signal frame only cares about scratch regs (pt_regs), but has to accommodate
>>> unused placeholder for callee regs too by virtue of using user_regs_struct.
>> Is this really true?  Don't setcontext and friends require that _all_
>> the registers be part of sigcontext?
>
> But for an ABI - callee saved regs will anyhow be saved/restored even in
> setcontext case ! So collecting it for that purpose seems useless, or am I missing
> something here.

Yes, I agree with you on the ABI bit... but set/get/swapcontext are
special in that they use rt_sigreturn to "trick" the kernel into
swapping out _all_ registers; it's a light-weight (userspace) context
switch.

(I really don't know this area very well, though, so I'm hoping
somebody more knowledgable jumps in here... Al?)

/Jonas

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling)
  2013-02-11 10:28         ` James Hogan
@ 2013-02-11 10:53           ` Jonas Bonn
  2013-02-11 10:57             ` James Hogan
                               ` (2 more replies)
  0 siblings, 3 replies; 57+ messages in thread
From: Jonas Bonn @ 2013-02-11 10:53 UTC (permalink / raw)
  To: James Hogan
  Cc: Vineet Gupta, Arnd Bergmann, linux-arch, linux-kernel, Al Viro

On 11 February 2013 11:28, James Hogan <james.hogan@imgtec.com> wrote:
> On 11/02/13 10:13, Vineet Gupta wrote:
>> On Monday 11 February 2013 03:06 PM, Jonas Bonn wrote:
>>> On 11 February 2013 08:26, Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
>>>
>>>> The only downside of this patch is that userspace signal stack grows in size,
>>>> since signal frame only cares about scratch regs (pt_regs), but has to accommodate
>>>> unused placeholder for callee regs too by virtue of using user_regs_struct.
>>> Is this really true?  Don't setcontext and friends require that _all_
>>> the registers be part of sigcontext?
>>
>> But for an ABI - callee saved regs will anyhow be saved/restored even in
>> setcontext case ! So collecting it for that purpose seems useless, or am I missing
>> something here.
>
> I think Jonas' point was that signals are asynchronous, i.e. you could
> get interrupted by a signal at virtually any time during the program's
> execution.

No, I agree that the callee-saved regs don't need to be saved across a
signal handler invocation.  It's really just the setcontext case that
wants to be able to swap out the callee-saved regs.

And now that I think about it some more, I think this is done
incorrectly in the openrisc arch, too, as the fast-path for
rt_sigreturn probably only restores the call-clobbered regs.
sigreturn probably needs to be special-cased to _always_ restore all
the regs on its way back to userspace.  Not for the "signal" case, but
for the "setcontext" case; but these two are pretty-much
indistinguishable.

/Jonas

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling)
  2013-02-11 10:53           ` Jonas Bonn
@ 2013-02-11 10:57             ` James Hogan
  2013-02-11 11:01             ` James Hogan
  2013-02-11 11:22             ` Vineet Gupta
  2 siblings, 0 replies; 57+ messages in thread
From: James Hogan @ 2013-02-11 10:57 UTC (permalink / raw)
  To: Jonas Bonn; +Cc: Vineet Gupta, Arnd Bergmann, linux-arch, linux-kernel, Al Viro

On 11/02/13 10:53, Jonas Bonn wrote:
> On 11 February 2013 11:28, James Hogan <james.hogan@imgtec.com> wrote:
>> On 11/02/13 10:13, Vineet Gupta wrote:
>>> On Monday 11 February 2013 03:06 PM, Jonas Bonn wrote:
>>>> On 11 February 2013 08:26, Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
>>>>
>>>>> The only downside of this patch is that userspace signal stack grows in size,
>>>>> since signal frame only cares about scratch regs (pt_regs), but has to accommodate
>>>>> unused placeholder for callee regs too by virtue of using user_regs_struct.
>>>> Is this really true?  Don't setcontext and friends require that _all_
>>>> the registers be part of sigcontext?
>>>
>>> But for an ABI - callee saved regs will anyhow be saved/restored even in
>>> setcontext case ! So collecting it for that purpose seems useless, or am I missing
>>> something here.
>>
>> I think Jonas' point was that signals are asynchronous, i.e. you could
>> get interrupted by a signal at virtually any time during the program's
>> execution.
> 
> No, I agree that the callee-saved regs don't need to be saved across a
> signal handler invocation.  It's really just the setcontext case that
> wants to be able to swap out the callee-saved regs.

Yes, I was getting muddled, sorry!

> And now that I think about it some more, I think this is done
> incorrectly in the openrisc arch, too, as the fast-path for
> rt_sigreturn probably only restores the call-clobbered regs.
> sigreturn probably needs to be special-cased to _always_ restore all
> the regs on its way back to userspace.  Not for the "signal" case, but
> for the "setcontext" case; but these two are pretty-much
> indistinguishable.

Cheers
James


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling)
  2013-02-11 10:53           ` Jonas Bonn
  2013-02-11 10:57             ` James Hogan
@ 2013-02-11 11:01             ` James Hogan
  2013-02-11 11:22             ` Vineet Gupta
  2 siblings, 0 replies; 57+ messages in thread
From: James Hogan @ 2013-02-11 11:01 UTC (permalink / raw)
  To: Jonas Bonn; +Cc: Vineet Gupta, Arnd Bergmann, linux-arch, linux-kernel, Al Viro

Hi Jonas,

On 11/02/13 10:53, Jonas Bonn wrote:
> And now that I think about it some more, I think this is done
> incorrectly in the openrisc arch, too, as the fast-path for
> rt_sigreturn probably only restores the call-clobbered regs.
> sigreturn probably needs to be special-cased to _always_ restore all
> the regs on its way back to userspace.  Not for the "signal" case, but
> for the "setcontext" case; but these two are pretty-much
> indistinguishable.

Wouldn't setcontext restore a different stack, so the sigreturn wouldn't
happen until the ucontext is switched back?

Cheers
James


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling)
  2013-02-11 10:53           ` Jonas Bonn
  2013-02-11 10:57             ` James Hogan
  2013-02-11 11:01             ` James Hogan
@ 2013-02-11 11:22             ` Vineet Gupta
  2013-02-11 12:12               ` Jonas Bonn
  2 siblings, 1 reply; 57+ messages in thread
From: Vineet Gupta @ 2013-02-11 11:22 UTC (permalink / raw)
  To: Jonas Bonn; +Cc: James Hogan, Arnd Bergmann, linux-arch, linux-kernel, Al Viro

On Monday 11 February 2013 04:23 PM, Jonas Bonn wrote:
> On 11 February 2013 11:28, James Hogan <james.hogan@imgtec.com> wrote:
>> On 11/02/13 10:13, Vineet Gupta wrote:
>>> On Monday 11 February 2013 03:06 PM, Jonas Bonn wrote:
>>>> On 11 February 2013 08:26, Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
>>>>
>>>>> The only downside of this patch is that userspace signal stack grows in size,
>>>>> since signal frame only cares about scratch regs (pt_regs), but has to accommodate
>>>>> unused placeholder for callee regs too by virtue of using user_regs_struct.
>>>> Is this really true?  Don't setcontext and friends require that _all_
>>>> the registers be part of sigcontext?
>>>
>>> But for an ABI - callee saved regs will anyhow be saved/restored even in
>>> setcontext case ! So collecting it for that purpose seems useless, or am I missing
>>> something here.
>>
>> I think Jonas' point was that signals are asynchronous, i.e. you could
>> get interrupted by a signal at virtually any time during the program's
>> execution.
> 
> No, I agree that the callee-saved regs don't need to be saved across a
> signal handler invocation.  It's really just the setcontext case that
> wants to be able to swap out the callee-saved regs.

I don't think that's needed either - and if thats mandated somewhere, it would
seem a unnecessary mis-optimization IMHO.

See, even a setcontext enabled control flow needs to be ABI compliant so that it
plays nicely with other normal flows of execution. Thus e.g. it can't fudge a
callee reg - it needs to save orig callee reg(s) and restore them in the end. And
if we agree to those semantics - I don't see any value in swapping the callee reg
context around usage of setcontext as it would be a wasted effort.

-Vineet

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v3 02/71] ARC: Build system: Makefiles, Kconfig, Linker script
  2013-01-24 10:50 ` [PATCH v3 02/71] ARC: Build system: Makefiles, Kconfig, Linker script Vineet Gupta
  2013-01-28  6:29   ` Vineet Gupta
@ 2013-02-11 11:29   ` James Hogan
  2013-02-11 11:44     ` Vineet Gupta
  1 sibling, 1 reply; 57+ messages in thread
From: James Hogan @ 2013-02-11 11:29 UTC (permalink / raw)
  To: Vineet Gupta; +Cc: linux-arch, linux-kernel, arnd, Sam Ravnborg

Hi Vineet,

On 24/01/13 10:50, Vineet Gupta wrote:
> diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
> new file mode 100644
> index 0000000..b0b09ae
> --- /dev/null
> +++ b/arch/arc/Kconfig
> @@ -0,0 +1,328 @@
> +#
> +# 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.
> +#
> +
> +config ARC
> +	def_bool y
> +	select ARCH_NO_VIRT_TO_BUS

I noticed this in linux-next. ARCH_NO_VIRT_TO_BUS was defined
generically in the past in linux-next but the patch seems to have gone.
Therefore with an arc defconfig I see CONFIG_VIRT_TO_BUS=y defined which
I'm guessing it shouldn't be.

Cheers
James


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v3 02/71] ARC: Build system: Makefiles, Kconfig, Linker script
  2013-02-11 11:29   ` James Hogan
@ 2013-02-11 11:44     ` Vineet Gupta
  0 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-02-11 11:44 UTC (permalink / raw)
  To: James Hogan; +Cc: linux-arch, linux-kernel, arnd, Sam Ravnborg

On Monday 11 February 2013 04:59 PM, James Hogan wrote:
> Hi Vineet,
> 
> On 24/01/13 10:50, Vineet Gupta wrote:
>> diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
>> new file mode 100644
>> index 0000000..b0b09ae
>> --- /dev/null
>> +++ b/arch/arc/Kconfig
>> @@ -0,0 +1,328 @@
>> +#
>> +# 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.
>> +#
>> +
>> +config ARC
>> +	def_bool y
>> +	select ARCH_NO_VIRT_TO_BUS
> 
> I noticed this in linux-next. ARCH_NO_VIRT_TO_BUS was defined
> generically in the past in linux-next but the patch seems to have gone.
> Therefore with an arc defconfig I see CONFIG_VIRT_TO_BUS=y defined which
> I'm guessing it shouldn't be.

Good catch ! I'll add a config ARCH_NO_VIRT_TO_BUS, but it would seem this is
better done in arch/Kconfig and get rid of extraneous defs in arch/*/Kconfig. I
can spin that patch, the only issue is merging logistics - our trees are not yet
apt for such changes.

Thx,
-Vineet

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling)
  2013-02-11 11:22             ` Vineet Gupta
@ 2013-02-11 12:12               ` Jonas Bonn
  2013-02-11 12:37                 ` Vineet Gupta
  0 siblings, 1 reply; 57+ messages in thread
From: Jonas Bonn @ 2013-02-11 12:12 UTC (permalink / raw)
  To: Vineet Gupta
  Cc: James Hogan, Arnd Bergmann, linux-arch, linux-kernel, Al Viro

On 11 February 2013 12:22, Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
> On Monday 11 February 2013 04:23 PM, Jonas Bonn wrote:
>> On 11 February 2013 11:28, James Hogan <james.hogan@imgtec.com> wrote:
>>> On 11/02/13 10:13, Vineet Gupta wrote:
>>>> On Monday 11 February 2013 03:06 PM, Jonas Bonn wrote:
>>>>> On 11 February 2013 08:26, Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
>>>>>
>>>>>> The only downside of this patch is that userspace signal stack grows in size,
>>>>>> since signal frame only cares about scratch regs (pt_regs), but has to accommodate
>>>>>> unused placeholder for callee regs too by virtue of using user_regs_struct.
>>>>> Is this really true?  Don't setcontext and friends require that _all_
>>>>> the registers be part of sigcontext?
>>>>
>>>> But for an ABI - callee saved regs will anyhow be saved/restored even in
>>>> setcontext case ! So collecting it for that purpose seems useless, or am I missing
>>>> something here.
>>>
>>> I think Jonas' point was that signals are asynchronous, i.e. you could
>>> get interrupted by a signal at virtually any time during the program's
>>> execution.
>>
>> No, I agree that the callee-saved regs don't need to be saved across a
>> signal handler invocation.  It's really just the setcontext case that
>> wants to be able to swap out the callee-saved regs.
>
> I don't think that's needed either - and if thats mandated somewhere, it would
> seem a unnecessary mis-optimization IMHO.
>
> See, even a setcontext enabled control flow needs to be ABI compliant so that it
> plays nicely with other normal flows of execution. Thus e.g. it can't fudge a
> callee reg - it needs to save orig callee reg(s) and restore them in the end. And
> if we agree to those semantics - I don't see any value in swapping the callee reg
> context around usage of setcontext as it would be a wasted effort.

Yeah, that makes sense.  I can see where you're coming from... and the
fact that you switch the stack, as James pointed out, means that you
end up restoring whatever callee-saved registers you need in the new
control flow on the way out of your setcontext wrapper.

BUT... a successful call to setcontext() does not return and whatever
code you end up jumping to as a result of the call has its own
expectations about the state of the registers.  Somebody has to set up
the registers to meet these expectations and, as far as I can see,
this means:

i) sigreturn fixes up the internal pt_regs with the new userspace state
ii) the syscall return path restores _all_ the regs, as though there
had been a context switch

What am I missing?  I'm totally open to the idea that I'm the one
who's confused here...

...and perhaps this is all moot since it seems that
getcontext/setcontext are obsolete anyway(???).

/Jonas

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling)
  2013-02-11 12:12               ` Jonas Bonn
@ 2013-02-11 12:37                 ` Vineet Gupta
  2013-02-11 13:02                   ` Jonas Bonn
  0 siblings, 1 reply; 57+ messages in thread
From: Vineet Gupta @ 2013-02-11 12:37 UTC (permalink / raw)
  To: Jonas Bonn; +Cc: James Hogan, Arnd Bergmann, linux-arch, linux-kernel, Al Viro

On Monday 11 February 2013 05:42 PM, Jonas Bonn wrote:
> On 11 February 2013 12:22, Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
>> On Monday 11 February 2013 04:23 PM, Jonas Bonn wrote:
>>> On 11 February 2013 11:28, James Hogan <james.hogan@imgtec.com> wrote:
>>>> On 11/02/13 10:13, Vineet Gupta wrote:
>>>>> On Monday 11 February 2013 03:06 PM, Jonas Bonn wrote:
>>>>>> On 11 February 2013 08:26, Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
>>>>>>
>>>>>>> The only downside of this patch is that userspace signal stack grows in size,
>>>>>>> since signal frame only cares about scratch regs (pt_regs), but has to accommodate
>>>>>>> unused placeholder for callee regs too by virtue of using user_regs_struct.
>>>>>> Is this really true?  Don't setcontext and friends require that _all_
>>>>>> the registers be part of sigcontext?
>>>>> But for an ABI - callee saved regs will anyhow be saved/restored even in
>>>>> setcontext case ! So collecting it for that purpose seems useless, or am I missing
>>>>> something here.
>>>> I think Jonas' point was that signals are asynchronous, i.e. you could
>>>> get interrupted by a signal at virtually any time during the program's
>>>> execution.
>>> No, I agree that the callee-saved regs don't need to be saved across a
>>> signal handler invocation.  It's really just the setcontext case that
>>> wants to be able to swap out the callee-saved regs.
>> I don't think that's needed either - and if thats mandated somewhere, it would
>> seem a unnecessary mis-optimization IMHO.
>>
>> See, even a setcontext enabled control flow needs to be ABI compliant so that it
>> plays nicely with other normal flows of execution. Thus e.g. it can't fudge a
>> callee reg - it needs to save orig callee reg(s) and restore them in the end. And
>> if we agree to those semantics - I don't see any value in swapping the callee reg
>> context around usage of setcontext as it would be a wasted effort.
> Yeah, that makes sense.  I can see where you're coming from... and the
> fact that you switch the stack, as James pointed out, means that you
> end up restoring whatever callee-saved registers you need in the new
> control flow on the way out of your setcontext wrapper.
>
> BUT... a successful call to setcontext() does not return and whatever
> code you end up jumping to as a result of the call has its own
> expectations about the state of the registers. 

It doesn't matter if the call returns or not. The point is the code jumped to - if
ABI compliant will save the callee regs before clobbering them.
For a new execution context, callee regs (for any ABI whatsoever) can have random
state, as the caller will save/restore them. It's only in the __switch_to kind of
scenario (see below) does the orig values really matter.


> Somebody has to set up
> the registers to meet these expectations and, as far as I can see,
> this means:
>
> i) sigreturn fixes up the internal pt_regs with the new userspace state
> ii) the syscall return path restores _all_ the regs, as though there
> had been a context switch
>
> What am I missing?  I'm totally open to the idea that I'm the one
> who's confused here...

Far from that - u seem to be the one in charge here :-)

I don't know how setcontext enabled app works - but there's a different use case
we can compare with - __switch_to( ) is the only legit place in kernel (ignoring
ptrace-peek/pokeusr for now) which saves callee regs (kernel mode) and restores
them for different task. And the only reason it does that is because it switches
context from the "middle" of control flow. Now if setcontext based switching works
in that fashion - then yes we do need callee regs setup there - if not then we don't.

> ...and perhaps this is all moot since it seems that
> getcontext/setcontext are obsolete anyway(???).

That would make it so much be easy :-)

Anyhow going back to my orig patch - if we park the
callee-regs-in-sigcontext-or-not, other bits look OK ?

-Vineet

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling)
  2013-02-11 12:37                 ` Vineet Gupta
@ 2013-02-11 13:02                   ` Jonas Bonn
  2013-02-11 13:08                     ` Vineet Gupta
  0 siblings, 1 reply; 57+ messages in thread
From: Jonas Bonn @ 2013-02-11 13:02 UTC (permalink / raw)
  To: Vineet Gupta
  Cc: James Hogan, Arnd Bergmann, linux-arch, linux-kernel, Al Viro

On 11 February 2013 13:37, Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
>
> Anyhow going back to my orig patch - if we park the
> callee-regs-in-sigcontext-or-not, other bits look OK ?
>

Aside from the callee-regs question (which I hope somebody more
knowledgeable can chime in on):  Acked-by: Jonas Bonn
<jonas@southpole.se>

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling)
  2013-02-11 13:02                   ` Jonas Bonn
@ 2013-02-11 13:08                     ` Vineet Gupta
  0 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-02-11 13:08 UTC (permalink / raw)
  To: Jonas Bonn; +Cc: James Hogan, Arnd Bergmann, linux-arch, linux-kernel, Al Viro

On Monday 11 February 2013 06:32 PM, Jonas Bonn wrote:
> On 11 February 2013 13:37, Vineet Gupta <Vineet.Gupta1@synopsys.com> wrote:
>> Anyhow going back to my orig patch - if we park the
>> callee-regs-in-sigcontext-or-not, other bits look OK ?
>>
> Aside from the callee-regs question (which I hope somebody more
> knowledgeable can chime in on):  Acked-by: Jonas Bonn
> <jonas@southpole.se>

Thx. As I mentioned, this patch will needed to be chopped and squashed into
several existing commits.
I presume I'll add the Ack to "ARC: Fundamental ARCH data-types/defines" which
contains the initial def of ptrace.h

-Vineet



^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling)
  2013-02-11 10:30         ` Jonas Bonn
@ 2013-02-11 14:07           ` Al Viro
  2013-02-15  7:23             ` Jonas Bonn
  0 siblings, 1 reply; 57+ messages in thread
From: Al Viro @ 2013-02-11 14:07 UTC (permalink / raw)
  To: Jonas Bonn; +Cc: Vineet Gupta, Arnd Bergmann, linux-arch, linux-kernel

On Mon, Feb 11, 2013 at 11:30:50AM +0100, Jonas Bonn wrote:

> >> Is this really true?  Don't setcontext and friends require that _all_
> >> the registers be part of sigcontext?
> >
> > But for an ABI - callee saved regs will anyhow be saved/restored even in
> > setcontext case ! So collecting it for that purpose seems useless, or am I missing
> > something here.
> 
> Yes, I agree with you on the ABI bit... but set/get/swapcontext are
> special in that they use rt_sigreturn to "trick" the kernel into
> swapping out _all_ registers; it's a light-weight (userspace) context
> switch.
> 
> (I really don't know this area very well, though, so I'm hoping
> somebody more knowledgable jumps in here... Al?)

I'd suggest asking itanic folks; they do *not* put callee-saved stuff into
sigcontext.  AFAICS, they don't have setcontext() implemented as a syscall
at all - it's done as sigprocmask() + doing to callee-saved registers what
longjmp() does.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling)
  2013-02-11 14:07           ` Al Viro
@ 2013-02-15  7:23             ` Jonas Bonn
  2013-02-15  7:35               ` Vineet Gupta
  0 siblings, 1 reply; 57+ messages in thread
From: Jonas Bonn @ 2013-02-15  7:23 UTC (permalink / raw)
  To: Al Viro; +Cc: Vineet Gupta, Arnd Bergmann, linux-arch, linux-kernel

On 11 February 2013 15:07, Al Viro <viro@zeniv.linux.org.uk> wrote:

> I'd suggest asking itanic folks; they do *not* put callee-saved stuff into
> sigcontext.  AFAICS, they don't have setcontext() implemented as a syscall
> at all - it's done as sigprocmask() + doing to callee-saved registers what
> longjmp() does.


Just to round off this discussion, after giving it some more thought I
agree that the case where you would need callee-saved registers
restored is probably rather pathological.  Any sane use of
get/set/swapcontext is manageable without this.

So, Vineet, I'm now convinced your approach is sound.  I will probably
amend the OpenRISC arch to behave similarly.  Consider your entire
patch Acked now.

/Jonas

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling)
  2013-02-15  7:23             ` Jonas Bonn
@ 2013-02-15  7:35               ` Vineet Gupta
  0 siblings, 0 replies; 57+ messages in thread
From: Vineet Gupta @ 2013-02-15  7:35 UTC (permalink / raw)
  To: Jonas Bonn; +Cc: Al Viro, Arnd Bergmann, linux-arch, linux-kernel

On Friday 15 February 2013 12:53 PM, Jonas Bonn wrote:
> On 11 February 2013 15:07, Al Viro <viro@zeniv.linux.org.uk> wrote:
>
>> I'd suggest asking itanic folks; they do *not* put callee-saved stuff into
>> sigcontext.  AFAICS, they don't have setcontext() implemented as a syscall
>> at all - it's done as sigprocmask() + doing to callee-saved registers what
>> longjmp() does.
>
> Just to round off this discussion, after giving it some more thought I
> agree that the case where you would need callee-saved registers
> restored is probably rather pathological.  Any sane use of
> get/set/swapcontext is manageable without this.
>
> So, Vineet, I'm now convinced your approach is sound.  I will probably
> amend the OpenRISC arch to behave similarly.  Consider your entire
> patch Acked now.

I'll add your ack to the the signal handling patch as the contention was primarily
on sigcontext bits.

Thx,
-Vineet

^ permalink raw reply	[flat|nested] 57+ messages in thread

end of thread, other threads:[~2013-02-15  7:36 UTC | newest]

Thread overview: 57+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-01-24 10:50 [PATCH v3 00/71] Synopsys ARC Linux kernel Port (Part #1) Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 01/71] ARC: Generic Headers Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 02/71] ARC: Build system: Makefiles, Kconfig, Linker script Vineet Gupta
2013-01-28  6:29   ` Vineet Gupta
2013-01-28 18:44     ` Sam Ravnborg
2013-01-29 13:45       ` Vineet Gupta
2013-01-29 17:52         ` Sam Ravnborg
2013-02-11 11:29   ` James Hogan
2013-02-11 11:44     ` Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 06/71] ARC: uaccess friends Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 11/71] ARC: Fundamental ARCH data-types/defines Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 17/71] ARC: Syscall support (no-legacy-syscall ABI) Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 18/71] ARC: Process-creation/scheduling/idle-loop Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 19/71] ARC: Timers/counters/delay management Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 20/71] ARC: Signal handling Vineet Gupta
2013-02-11  7:26   ` pt_regs leak into userspace (was Re: [PATCH v3 20/71] ARC: Signal handling) Vineet Gupta
2013-02-11  9:36     ` Jonas Bonn
2013-02-11 10:13       ` Vineet Gupta
2013-02-11 10:28         ` James Hogan
2013-02-11 10:53           ` Jonas Bonn
2013-02-11 10:57             ` James Hogan
2013-02-11 11:01             ` James Hogan
2013-02-11 11:22             ` Vineet Gupta
2013-02-11 12:12               ` Jonas Bonn
2013-02-11 12:37                 ` Vineet Gupta
2013-02-11 13:02                   ` Jonas Bonn
2013-02-11 13:08                     ` Vineet Gupta
2013-02-11 10:30         ` Jonas Bonn
2013-02-11 14:07           ` Al Viro
2013-02-15  7:23             ` Jonas Bonn
2013-02-15  7:35               ` Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 21/71] ARC: [Review] Preparing to fix incorrect syscall restarts due to signals Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 22/71] ARC: [Review] Prevent incorrect syscall restarts Vineet Gupta
2013-01-28  7:42   ` Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 23/71] ARC: Cache Flush Management Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 29/71] ARC: I/O and DMA Mappings Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 30/71] ARC: Boot #1: low-level, setup_arch(), /proc/cpuinfo, mem init Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 32/71] ARC: [DeviceTree] Basic support Vineet Gupta
2013-01-28  7:40   ` Vineet Gupta
2013-01-28 10:21   ` James Hogan
2013-01-29  9:53     ` Vineet Gupta
2013-01-29 10:06       ` James Hogan
2013-01-29 13:25   ` Rob Herring
2013-01-29 13:39     ` Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 33/71] ARC: [DeviceTree] Convert some Kconfig items to runtime values Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 34/71] ARC: [plat-arcfpga]: Enabling DeviceTree for Angel4 board Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 42/71] ARC: Module support Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 44/71] ARC: SMP support Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 48/71] ARC: kprobes support Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 57/71] ARC: Hostlink Pseudo-Driver for Metaware Debugger Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 58/71] ARC: UAPI Disintegrate arch/arc/include/asm Vineet Gupta
2013-01-28  7:36   ` Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 59/71] ARC: Add support for ioremap_prot API Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 62/71] ARC: [Review] Multi-platform image #2: Board callback Infrastructure Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 69/71] ARC: [plat-arcfpga] defconfig for fully loaded ARC Linux Vineet Gupta
2013-01-24 10:50 ` [PATCH v3 70/71] ARC: Provide a default serial.h for uart drivers needing BASE_BAUD Vineet Gupta
2013-01-24 11:01 ` [PATCH v3 45/71] ARC: DWARF2 .debug_frame based stack unwinder Vineet Gupta

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).