All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port
@ 2018-07-01 17:30 Guo Ren
  2018-07-01 17:30 ` [PATCH V2 01/19] csky: Build infrastructure Guo Ren
                   ` (19 more replies)
  0 siblings, 20 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

This is the 2th version patchset to add the Linux kernel port for C-SKY(csky).
Thanks to everyone who provided feedback on the previous version.

This patchset adds architecture support to Linux for C-SKY's 32-bit embedded
CPU cores and the patches are based on linux-4.16.2.

There are two ABI versions with several CPU cores in this patchset:
  ABIv1: ck610 (16-bit instruction, 32-bit data path, VIPT Cache ...)
  ABIv2: ck807 ck810 ck860 (16/32-bit variable length instruction, PIPT Cache,
	 SMP ...)

More information: http://en.c-sky.com

I'm from Hangzhou,China C-SKY Microsystems and responsible for C-SKY Linux
port. The development repo is
https://github.com/c-sky/csky-linux

We use buildroot as our CI-test enviornment. "LTP, Lmbench, uclibc-ng-test ..."
will be tested for every commit. See here for more details:
  https://gitlab.com/c-sky/buildroot/pipelines

You can try C-SKY linux in a few steps:
  $ git clone https://github.com/c-sky/buildroot.git
  $ cd buildroot
  $ make qemu_csky_ck807_uclibc_bt_defconfig
  $ make
It will download "linux uclibc-ng gcc binutils qemu busybox" source code and build
them into one image. How to run, See:
  https://github.com/c-sky/buildroot/blob/master/board/qemu/csky/readme.txt

I've finished uClibc-ng.org upstream and "gcc glibc binutils qemu ..." upstream is
on going and the source code is here:
  https://github.com/c-sky

Any feedback is welcome.

Changes in v2:
a29bfc8 csky: add pre_mmu_init, move misc mmu setup to mm/init.c
4eab702 csky: no need kmap for !VM_EXEC.
6770eec csky: Use TEE as the name of CPU Trusted Execution Enviornment.
a56c8c7 csky: update the cache flush api.
1a48a95 csky: add C-SKY Trust Zone.
b7a0a44 csky: use CONFIG_RAM_BASE as the same in memory of dts.
15adf81 csky: remove unused code.
35c0d97 csky: bugfix lost a cacheline flush when start isn't cacheline-aligned.
4e82c8d csky: use tlbi.alls for ck860 smp temporary.
ae7149e csky: bugfix use kmap_atomic() to prevent no mapped addr.
5538795 csky: bugfix user access in kernel space.
a7aa591 csky: add 16bit user space bkpt.
0de70ec csky: add sync.is for cmpxchg in SMP.
c5c08a1 csky: seperate sync.is and sync for SMP and Non-SMP.
dbbf4dc csky: use sync.is for ck860 mb().
f33f8da csky: rewrite the alignment implement.
68152c7 csky: bugfix alignment pt_regs error.
d618d43 csky: support set_affinity for irq balance in SMP
ebf86c9 csky: bugfix compile error without CONFIG_SMP.
8537eea csky: remove debug code.
4ebc051 csky: bugfix compile error with linux-4.9.56
75a938e csky: C-SKY SMP supported.
0eebc07 csky: use internal function for map_sg.
3d29751 csky: bugfix can't support highmem
b545d2a csky: bugfix r26 is the link reg for jsri_to_jsr.
9e3313a csky: bugfix sync tls for abiv1 in ptrace.
587a0d2 csky: use __NR_rt_sigreturn in asm-generic.
f562b46 csky: bugfix gpr_set & fpr_set
f57266f csky: bugfix fpu_fpe_helper excute mtcr mfcr.
c676669 csky: bugfix ave is default enable on reset.
d40d34d csky: remove unused sc_mask in sigcontext.h.
274b7a2 csky: redesign the signal's api
7501771 csky: bugfix forget restore usp.
923e2ca csky: re-struct the pt_regs for regset.
2a1e499 csky: fixup config.
ada81ec csky: bugfix abiv1 compile error.
e34acb9 csky: bugfix abiv1 couldn't support -mno-stack-size.
ec53560 csky: change irq map, reserve soft_irq&private_irq space.
c7576f7 csky: bugfix modpost warning with -mno-stack-size
c8ff9d4 csky: support csky mp timer alpha version.
deabaaf csky: update .gitignore.
574815c csky: bugfix compile error with abiv1 in 4.15
0b426a7 csky: bugfix format of cpu verion id.
083435f csky: irq-csky-v2 alpha init.
21209e5 csky: add .gitignore
73e19b4 csky: remove FMFS_FPU_REGS/FMTS_FPU_REGS
07e8fac csky: add fpu regset in ptrace.c
cac779d csky: add CSKY_VECIRQ_LEGENCY for SOC bug.
54bab1d csky: move usp into pt_regs.
b167422 csky: support regset for ptrace.
a098d4c csky: remove ARCH_WANT_IPC_PARSE_VERSION
fe61a84 csky: add timer-of support.
27702e2 csky: bugfix boot error.
ebe3edb csky: bugfix gx6605s boot failed  - add __HEAD to head.section for head.S  - move INIT_SECTION together to fix compile warning.
7138cae csky: coding convension for timer-nationalchip.c
fa7f9bb csky: use ffs instead of fls.
ddc9e81 csky: change to generic irq chip for irq-csky.c
e9be8b9 irqchip: add generic irq chip for irq-nationalchip
2ee83fe csky: add set_handle_irq(), ref from openrisc & arm.
74181d6 csky: use irq_domain_add_linear instead of leagcy.
fa45ae4 csky: bugfix setup stroge order for uncached.
eb8030f csky: add HIGHMEM config in Kconfig
4f983d4 csky: remove "default n" in Kconfig
2467575 csky: use asm-generic/signal.h
77438e5 csky: coding conventions for irq.c
2e4a2b4 csky: optimize the cache flush ops.
96e1c58 csky: add CONFIG_CPU_ASID_BITS.
9339666 csky: add cprcr() cpwcr() for abiv1
ff05be4 csky: add THREAD_SHIFT define in asm/page.h
52ab022 csky: add mfcr() mtcr() in asm/reg_ops.h
bdcd8f3 csky: revert back Kconfig select.
590c7e6 csky: bugfix compile error with CONFIG_AUDIT
1989292 csky: revert some back with cleanup unistd.h
f1454fe csky: cleanup unistd.h
5d2985f csky: cleanup Kconfig and Makefile.
423d97e csky: cancel subdirectories
cae2af4 csky: use asm-generic/fcntl.h

Guo Ren (19):
  csky: Build infrastructure
  csky: defconfig
  csky: Kernel booting
  csky: Exception handling
  csky: System Call
  csky: Cache and TLB routines
  csky: MMU and page table management
  csky: Process management and Signal
  csky: VDSO and rt_sigreturn
  csky: IRQ handling
  csky: Atomic operations
  csky: ELF and module probe
  csky: Library functions
  csky: User access
  csky: Debug and Ptrace GDB
  csky: SMP support
  csky: Misc headers
  clocksource: add C-SKY clocksource drivers
  irqchip: add C-SKY irqchip drivers

 arch/csky/Kconfig                        | 211 ++++++++++++
 arch/csky/Kconfig.debug                  |  29 ++
 arch/csky/Makefile                       |  92 ++++++
 arch/csky/abiv1/Makefile                 |   8 +
 arch/csky/abiv1/alignment.c              | 332 +++++++++++++++++++
 arch/csky/abiv1/bswapdi.c                |  18 +
 arch/csky/abiv1/bswapsi.c                |  15 +
 arch/csky/abiv1/cacheflush.c             |  51 +++
 arch/csky/abiv1/inc/abi/cacheflush.h     |  42 +++
 arch/csky/abiv1/inc/abi/ckmmu.h          |  80 +++++
 arch/csky/abiv1/inc/abi/entry.h          | 152 +++++++++
 arch/csky/abiv1/inc/abi/page.h           |  26 ++
 arch/csky/abiv1/inc/abi/pgtable-bits.h   |  36 ++
 arch/csky/abiv1/inc/abi/reg_ops.h        |  47 +++
 arch/csky/abiv1/inc/abi/regdef.h         |  15 +
 arch/csky/abiv1/inc/abi/tlb.h            |  11 +
 arch/csky/abiv1/inc/abi/vdso.h           |  17 +
 arch/csky/abiv1/memcpy.S                 | 344 +++++++++++++++++++
 arch/csky/abiv1/mmap.c                   |  65 ++++
 arch/csky/abiv2/Makefile                 |   4 +
 arch/csky/abiv2/cacheflush.c             |  55 ++++
 arch/csky/abiv2/fpu.c                    | 242 ++++++++++++++
 arch/csky/abiv2/inc/abi/cacheflush.h     |  38 +++
 arch/csky/abiv2/inc/abi/ckmmu.h          |  88 +++++
 arch/csky/abiv2/inc/abi/entry.h          | 149 +++++++++
 arch/csky/abiv2/inc/abi/fpu.h            | 219 ++++++++++++
 arch/csky/abiv2/inc/abi/page.h           |  14 +
 arch/csky/abiv2/inc/abi/pgtable-bits.h   |  36 ++
 arch/csky/abiv2/inc/abi/reg_ops.h        |  38 +++
 arch/csky/abiv2/inc/abi/regdef.h         |  15 +
 arch/csky/abiv2/inc/abi/tlb.h            |  12 +
 arch/csky/abiv2/inc/abi/vdso.h           |  18 +
 arch/csky/abiv2/memcpy.c                 |  43 +++
 arch/csky/boot/Makefile                  |  25 ++
 arch/csky/boot/dts/Makefile              |  14 +
 arch/csky/boot/dts/include/dt-bindings   |   1 +
 arch/csky/configs/gx66xx_defconfig       | 549 +++++++++++++++++++++++++++++++
 arch/csky/configs/qemu_ck807_defconfig   | 541 ++++++++++++++++++++++++++++++
 arch/csky/include/asm/Kbuild             |  72 ++++
 arch/csky/include/asm/addrspace.h        |  10 +
 arch/csky/include/asm/barrier.h          |  19 ++
 arch/csky/include/asm/bitops.h           | 277 ++++++++++++++++
 arch/csky/include/asm/cache.h            |  29 ++
 arch/csky/include/asm/cacheflush.h       |   9 +
 arch/csky/include/asm/checksum.h         |  77 +++++
 arch/csky/include/asm/cmpxchg.h          |  68 ++++
 arch/csky/include/asm/dma-mapping.h      |  13 +
 arch/csky/include/asm/elf.h              | 149 +++++++++
 arch/csky/include/asm/fixmap.h           |  65 ++++
 arch/csky/include/asm/highmem.h          |  50 +++
 arch/csky/include/asm/io.h               |  23 ++
 arch/csky/include/asm/irq.h              |  10 +
 arch/csky/include/asm/irqflags.h         |  49 +++
 arch/csky/include/asm/mmu.h              |  11 +
 arch/csky/include/asm/mmu_context.h      | 158 +++++++++
 arch/csky/include/asm/page.h             | 104 ++++++
 arch/csky/include/asm/pgalloc.h          | 108 ++++++
 arch/csky/include/asm/pgtable.h          | 301 +++++++++++++++++
 arch/csky/include/asm/processor.h        | 123 +++++++
 arch/csky/include/asm/reg_ops.h          |  16 +
 arch/csky/include/asm/segment.h          |  18 +
 arch/csky/include/asm/shmparam.h         |  10 +
 arch/csky/include/asm/smp.h              |  26 ++
 arch/csky/include/asm/spinlock.h         | 174 ++++++++++
 arch/csky/include/asm/spinlock_types.h   |  20 ++
 arch/csky/include/asm/string.h           |  19 ++
 arch/csky/include/asm/syscall.h          |  69 ++++
 arch/csky/include/asm/syscalls.h         |  14 +
 arch/csky/include/asm/thread_info.h      |  73 ++++
 arch/csky/include/asm/tlb.h              |  19 ++
 arch/csky/include/asm/tlbflush.h         |  22 ++
 arch/csky/include/asm/traps.h            |  39 +++
 arch/csky/include/asm/uaccess.h          | 397 ++++++++++++++++++++++
 arch/csky/include/asm/unistd.h           |   4 +
 arch/csky/include/asm/vdso.h             |  12 +
 arch/csky/include/uapi/asm/Kbuild        |  33 ++
 arch/csky/include/uapi/asm/byteorder.h   |  14 +
 arch/csky/include/uapi/asm/cachectl.h    |  13 +
 arch/csky/include/uapi/asm/ptrace.h      | 105 ++++++
 arch/csky/include/uapi/asm/sigcontext.h  |  13 +
 arch/csky/include/uapi/asm/unistd.h      |  63 ++++
 arch/csky/kernel/Makefile                |   8 +
 arch/csky/kernel/asm-offsets.c           |  85 +++++
 arch/csky/kernel/atomic.S                |  87 +++++
 arch/csky/kernel/cpu-probe.c             |  83 +++++
 arch/csky/kernel/cskyksyms.c             |  31 ++
 arch/csky/kernel/dumpstack.c             |  65 ++++
 arch/csky/kernel/entry.S                 | 407 +++++++++++++++++++++++
 arch/csky/kernel/head.S                  |  81 +++++
 arch/csky/kernel/irq.c                   |  31 ++
 arch/csky/kernel/module.c                |  82 +++++
 arch/csky/kernel/platform.c              |  18 +
 arch/csky/kernel/power.c                 |  31 ++
 arch/csky/kernel/process.c               | 134 ++++++++
 arch/csky/kernel/ptrace.c                | 288 ++++++++++++++++
 arch/csky/kernel/setup.c                 | 148 +++++++++
 arch/csky/kernel/signal.c                | 350 ++++++++++++++++++++
 arch/csky/kernel/smp.c                   | 256 ++++++++++++++
 arch/csky/kernel/syscall.c               |  63 ++++
 arch/csky/kernel/syscall_table.c         |  12 +
 arch/csky/kernel/time.c                  |  12 +
 arch/csky/kernel/traps.c                 | 167 ++++++++++
 arch/csky/kernel/vdso.c                  |  89 +++++
 arch/csky/kernel/vmlinux.lds.S           |  65 ++++
 arch/csky/lib/Makefile                   |   1 +
 arch/csky/lib/delay.c                    |  40 +++
 arch/csky/lib/memset.c                   |  38 +++
 arch/csky/lib/usercopy.c                 | 271 +++++++++++++++
 arch/csky/mm/Makefile                    |  13 +
 arch/csky/mm/cachev1.c                   | 132 ++++++++
 arch/csky/mm/cachev2.c                   |  97 ++++++
 arch/csky/mm/dma-mapping.c               | 216 ++++++++++++
 arch/csky/mm/fault.c                     | 223 +++++++++++++
 arch/csky/mm/highmem.c                   | 210 ++++++++++++
 arch/csky/mm/init.c                      | 122 +++++++
 arch/csky/mm/ioremap.c                   |  49 +++
 arch/csky/mm/syscache.c                  |  29 ++
 arch/csky/mm/tlb.c                       | 210 ++++++++++++
 drivers/clocksource/Makefile             |   1 +
 drivers/clocksource/timer-csky-v1.c      | 169 ++++++++++
 drivers/clocksource/timer-nationalchip.c | 165 ++++++++++
 drivers/irqchip/Makefile                 |   1 +
 drivers/irqchip/irq-csky-v1.c            | 126 +++++++
 drivers/irqchip/irq-csky-v2.c            | 191 +++++++++++
 drivers/irqchip/irq-nationalchip.c       | 131 ++++++++
 125 files changed, 11618 insertions(+)
 create mode 100644 arch/csky/Kconfig
 create mode 100644 arch/csky/Kconfig.debug
 create mode 100644 arch/csky/Makefile
 create mode 100644 arch/csky/abiv1/Makefile
 create mode 100644 arch/csky/abiv1/alignment.c
 create mode 100644 arch/csky/abiv1/bswapdi.c
 create mode 100644 arch/csky/abiv1/bswapsi.c
 create mode 100644 arch/csky/abiv1/cacheflush.c
 create mode 100644 arch/csky/abiv1/inc/abi/cacheflush.h
 create mode 100644 arch/csky/abiv1/inc/abi/ckmmu.h
 create mode 100644 arch/csky/abiv1/inc/abi/entry.h
 create mode 100644 arch/csky/abiv1/inc/abi/page.h
 create mode 100644 arch/csky/abiv1/inc/abi/pgtable-bits.h
 create mode 100644 arch/csky/abiv1/inc/abi/reg_ops.h
 create mode 100644 arch/csky/abiv1/inc/abi/regdef.h
 create mode 100644 arch/csky/abiv1/inc/abi/tlb.h
 create mode 100644 arch/csky/abiv1/inc/abi/vdso.h
 create mode 100644 arch/csky/abiv1/memcpy.S
 create mode 100644 arch/csky/abiv1/mmap.c
 create mode 100644 arch/csky/abiv2/Makefile
 create mode 100644 arch/csky/abiv2/cacheflush.c
 create mode 100644 arch/csky/abiv2/fpu.c
 create mode 100644 arch/csky/abiv2/inc/abi/cacheflush.h
 create mode 100644 arch/csky/abiv2/inc/abi/ckmmu.h
 create mode 100644 arch/csky/abiv2/inc/abi/entry.h
 create mode 100644 arch/csky/abiv2/inc/abi/fpu.h
 create mode 100644 arch/csky/abiv2/inc/abi/page.h
 create mode 100644 arch/csky/abiv2/inc/abi/pgtable-bits.h
 create mode 100644 arch/csky/abiv2/inc/abi/reg_ops.h
 create mode 100644 arch/csky/abiv2/inc/abi/regdef.h
 create mode 100644 arch/csky/abiv2/inc/abi/tlb.h
 create mode 100644 arch/csky/abiv2/inc/abi/vdso.h
 create mode 100644 arch/csky/abiv2/memcpy.c
 create mode 100644 arch/csky/boot/Makefile
 create mode 100644 arch/csky/boot/dts/Makefile
 create mode 120000 arch/csky/boot/dts/include/dt-bindings
 create mode 100644 arch/csky/configs/gx66xx_defconfig
 create mode 100644 arch/csky/configs/qemu_ck807_defconfig
 create mode 100644 arch/csky/include/asm/Kbuild
 create mode 100644 arch/csky/include/asm/addrspace.h
 create mode 100644 arch/csky/include/asm/barrier.h
 create mode 100644 arch/csky/include/asm/bitops.h
 create mode 100644 arch/csky/include/asm/cache.h
 create mode 100644 arch/csky/include/asm/cacheflush.h
 create mode 100644 arch/csky/include/asm/checksum.h
 create mode 100644 arch/csky/include/asm/cmpxchg.h
 create mode 100644 arch/csky/include/asm/dma-mapping.h
 create mode 100644 arch/csky/include/asm/elf.h
 create mode 100644 arch/csky/include/asm/fixmap.h
 create mode 100644 arch/csky/include/asm/highmem.h
 create mode 100644 arch/csky/include/asm/io.h
 create mode 100644 arch/csky/include/asm/irq.h
 create mode 100644 arch/csky/include/asm/irqflags.h
 create mode 100644 arch/csky/include/asm/mmu.h
 create mode 100644 arch/csky/include/asm/mmu_context.h
 create mode 100644 arch/csky/include/asm/page.h
 create mode 100644 arch/csky/include/asm/pgalloc.h
 create mode 100644 arch/csky/include/asm/pgtable.h
 create mode 100644 arch/csky/include/asm/processor.h
 create mode 100644 arch/csky/include/asm/reg_ops.h
 create mode 100644 arch/csky/include/asm/segment.h
 create mode 100644 arch/csky/include/asm/shmparam.h
 create mode 100644 arch/csky/include/asm/smp.h
 create mode 100644 arch/csky/include/asm/spinlock.h
 create mode 100644 arch/csky/include/asm/spinlock_types.h
 create mode 100644 arch/csky/include/asm/string.h
 create mode 100644 arch/csky/include/asm/syscall.h
 create mode 100644 arch/csky/include/asm/syscalls.h
 create mode 100644 arch/csky/include/asm/thread_info.h
 create mode 100644 arch/csky/include/asm/tlb.h
 create mode 100644 arch/csky/include/asm/tlbflush.h
 create mode 100644 arch/csky/include/asm/traps.h
 create mode 100644 arch/csky/include/asm/uaccess.h
 create mode 100644 arch/csky/include/asm/unistd.h
 create mode 100644 arch/csky/include/asm/vdso.h
 create mode 100644 arch/csky/include/uapi/asm/Kbuild
 create mode 100644 arch/csky/include/uapi/asm/byteorder.h
 create mode 100644 arch/csky/include/uapi/asm/cachectl.h
 create mode 100644 arch/csky/include/uapi/asm/ptrace.h
 create mode 100644 arch/csky/include/uapi/asm/sigcontext.h
 create mode 100644 arch/csky/include/uapi/asm/unistd.h
 create mode 100644 arch/csky/kernel/Makefile
 create mode 100644 arch/csky/kernel/asm-offsets.c
 create mode 100644 arch/csky/kernel/atomic.S
 create mode 100644 arch/csky/kernel/cpu-probe.c
 create mode 100644 arch/csky/kernel/cskyksyms.c
 create mode 100644 arch/csky/kernel/dumpstack.c
 create mode 100644 arch/csky/kernel/entry.S
 create mode 100644 arch/csky/kernel/head.S
 create mode 100644 arch/csky/kernel/irq.c
 create mode 100644 arch/csky/kernel/module.c
 create mode 100644 arch/csky/kernel/platform.c
 create mode 100644 arch/csky/kernel/power.c
 create mode 100644 arch/csky/kernel/process.c
 create mode 100644 arch/csky/kernel/ptrace.c
 create mode 100644 arch/csky/kernel/setup.c
 create mode 100644 arch/csky/kernel/signal.c
 create mode 100644 arch/csky/kernel/smp.c
 create mode 100644 arch/csky/kernel/syscall.c
 create mode 100644 arch/csky/kernel/syscall_table.c
 create mode 100644 arch/csky/kernel/time.c
 create mode 100644 arch/csky/kernel/traps.c
 create mode 100644 arch/csky/kernel/vdso.c
 create mode 100644 arch/csky/kernel/vmlinux.lds.S
 create mode 100644 arch/csky/lib/Makefile
 create mode 100644 arch/csky/lib/delay.c
 create mode 100644 arch/csky/lib/memset.c
 create mode 100644 arch/csky/lib/usercopy.c
 create mode 100644 arch/csky/mm/Makefile
 create mode 100644 arch/csky/mm/cachev1.c
 create mode 100644 arch/csky/mm/cachev2.c
 create mode 100644 arch/csky/mm/dma-mapping.c
 create mode 100644 arch/csky/mm/fault.c
 create mode 100644 arch/csky/mm/highmem.c
 create mode 100644 arch/csky/mm/init.c
 create mode 100644 arch/csky/mm/ioremap.c
 create mode 100644 arch/csky/mm/syscache.c
 create mode 100644 arch/csky/mm/tlb.c
 create mode 100644 drivers/clocksource/timer-csky-v1.c
 create mode 100644 drivers/clocksource/timer-nationalchip.c
 create mode 100644 drivers/irqchip/irq-csky-v1.c
 create mode 100644 drivers/irqchip/irq-csky-v2.c
 create mode 100644 drivers/irqchip/irq-nationalchip.c

-- 
2.7.4


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

* [PATCH V2 01/19] csky: Build infrastructure
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
@ 2018-07-01 17:30 ` Guo Ren
  2018-07-01 21:01   ` Randy Dunlap
                     ` (2 more replies)
  2018-07-01 17:30 ` [PATCH V2 02/19] csky: defconfig Guo Ren
                   ` (18 subsequent siblings)
  19 siblings, 3 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/Kconfig                      | 211 +++++++++++++++++++++++++++++++++
 arch/csky/Kconfig.debug                |  29 +++++
 arch/csky/Makefile                     |  92 ++++++++++++++
 arch/csky/abiv1/Makefile               |   8 ++
 arch/csky/abiv2/Makefile               |   4 +
 arch/csky/boot/Makefile                |  25 ++++
 arch/csky/boot/dts/Makefile            |  14 +++
 arch/csky/boot/dts/include/dt-bindings |   1 +
 arch/csky/include/asm/Kbuild           |  72 +++++++++++
 arch/csky/include/uapi/asm/Kbuild      |  33 ++++++
 arch/csky/kernel/Makefile              |   8 ++
 arch/csky/lib/Makefile                 |   1 +
 arch/csky/mm/Makefile                  |  13 ++
 13 files changed, 511 insertions(+)
 create mode 100644 arch/csky/Kconfig
 create mode 100644 arch/csky/Kconfig.debug
 create mode 100644 arch/csky/Makefile
 create mode 100644 arch/csky/abiv1/Makefile
 create mode 100644 arch/csky/abiv2/Makefile
 create mode 100644 arch/csky/boot/Makefile
 create mode 100644 arch/csky/boot/dts/Makefile
 create mode 120000 arch/csky/boot/dts/include/dt-bindings
 create mode 100644 arch/csky/include/asm/Kbuild
 create mode 100644 arch/csky/include/uapi/asm/Kbuild
 create mode 100644 arch/csky/kernel/Makefile
 create mode 100644 arch/csky/lib/Makefile
 create mode 100644 arch/csky/mm/Makefile

diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig
new file mode 100644
index 0000000..cfeb312
--- /dev/null
+++ b/arch/csky/Kconfig
@@ -0,0 +1,211 @@
+config CSKY
+	bool
+	default y
+	select ARCH_USE_BUILTIN_BSWAP
+	select COMMON_CLK
+	select CLKSRC_MMIO
+	select CLKSRC_OF
+	select IRQ_DOMAIN
+	select HANDLE_DOMAIN_IRQ
+	select DW_APB_TIMER_OF
+	select GENERIC_ATOMIC64
+	select GENERIC_CLOCKEVENTS
+	select GENERIC_CPU_DEVICES
+	select GENERIC_IRQ_CHIP
+	select GENERIC_IRQ_PROBE
+	select GENERIC_IRQ_SHOW
+	select GENERIC_SCHED_CLOCK
+	select GENERIC_SMP_IDLE_THREAD
+	select HAVE_ARCH_TRACEHOOK
+	select HAVE_GENERIC_DMA_COHERENT
+	select HAVE_KERNEL_GZIP
+	select HAVE_KERNEL_LZO
+	select HAVE_KERNEL_LZMA
+	select HAVE_PERF_EVENTS
+	select HAVE_C_RECORDMCOUNT
+	select HAVE_KPROBES
+	select HAVE_KRETPROBES
+	select HAVE_DMA_API_DEBUG
+	select HAVE_MEMBLOCK
+	select MAY_HAVE_SPARSE_IRQ
+	select MODULES_USE_ELF_RELA if MODULES
+	select NO_BOOTMEM
+	select OF
+	select OF_EARLY_FLATTREE
+	select OF_RESERVED_MEM
+	select PERF_USE_VMALLOC
+	select RTC_LIB
+	select TIMER_OF
+	select USB_ARCH_HAS_EHCI
+	select USB_ARCH_HAS_OHCI
+
+config CPU_HAS_CACHEV2
+	bool
+
+config CPU_HAS_HILO
+	bool
+
+config CPU_HAS_TLBI
+	bool
+
+config CPU_HAS_LDSTEX
+	bool
+	help
+	  For SMP cpu need "ldex&stex" instrcutions to keep atomic.
+
+config CPU_NEED_TLBSYNC
+	bool
+
+config CPU_NEED_SOFTALIGN
+	bool
+
+config CPU_NO_USER_BKPT
+	bool
+	help
+	  For abiv2 we couldn't use "trap 1" as user space bkpt in gdbserver, because
+	  abiv2 is 16/32bit instruction set and "trap 1" is 32bit.
+	  So we need a 16bit instruction as user space bkpt, and it will cause a illegal
+	  instruction exception.
+	  In kernel we parse the *regs->pc to determine wether send SIGTRAP or not.
+
+config GENERIC_CALIBRATE_DELAY
+	bool
+	default y
+
+config HZ
+	int
+	default 100
+
+config GENERIC_CSUM
+	bool
+	default y
+
+config GENERIC_HWEIGHT
+	bool
+	default y
+
+config MMU
+	bool
+	default y
+
+config RWSEM_GENERIC_SPINLOCK
+	bool
+	default y
+
+config TIME_LOW_RES
+	bool
+	default y
+
+config TRACE_IRQFLAGS_SUPPORT
+	bool
+	default y
+
+source "init/Kconfig"
+
+source "kernel/Kconfig.freezer"
+
+menu "Processor type and features"
+
+comment "Processor type"
+
+choice
+	prompt "CPU MODEL"
+	default CPU_CK610
+
+config CPU_CK610
+	bool "CSKY CPU ck610"
+	select CPU_NEED_TLBSYNC
+	select CPU_NEED_SOFTALIGN
+	select CPU_NO_USER_BKPT
+
+config CPU_CK810
+	bool "CSKY CPU ck810"
+	select CPU_HAS_HILO
+	select CPU_NEED_TLBSYNC
+
+config CPU_CK807
+	bool "CSKY CPU ck807"
+	select CPU_HAS_HILO
+
+config CPU_CK860
+	bool "CSKY CPU ck860"
+	select CPU_HAS_TLBI
+	select CPU_HAS_CACHEV2
+	select CPU_HAS_LDSTEX
+endchoice
+
+config CPU_TLB_SIZE
+	int
+	default "128"	if(CPU_CK610 || CPU_CK807 || CPU_CK810)
+	default "1024"	if(CPU_CK860)
+
+config CPU_ASID_BITS
+	int
+	default "8"	if(CPU_CK610 || CPU_CK807 || CPU_CK810)
+	default "12"	if(CPU_CK860)
+
+config L1_CACHE_SHIFT
+	int
+	default "4"	if(CPU_CK610)
+	default "5"	if(CPU_CK807 || CPU_CK810)
+	default "6"	if(CPU_CK860)
+
+config HIGHMEM
+	bool "High Memory Support"
+	depends on !CPU_CK610
+	default y
+
+menuconfig CPU_HAS_FPU
+	bool "CPU has FPU coprocessor"
+	depends on CPU_CK807 || CPU_CK810 || CPU_CK860
+
+menuconfig CPU_HAS_TEE
+	bool "CPU has Trusted Execution Environment"
+	depends on CPU_CK810
+
+config SMP
+	bool "Symmetric Multi-Processing (SMP) support for C-SKY"
+	depends on CPU_CK860
+	default n
+
+config NR_CPUS
+	int "Maximum number of CPUs (2-32)"
+	range 2 32
+	depends on SMP
+	default "4"
+
+comment "*****System type*****"
+
+config RAM_BASE
+	hex "It must be the same with the memory section in your dts"
+	default 0x0
+endmenu
+
+menu "Power management options"
+
+source "kernel/power/Kconfig"
+
+config ARCH_SUSPEND_POSSIBLE
+	bool
+	default y
+endmenu
+
+source "mm/Kconfig"
+
+source "fs/Kconfig.binfmt"
+
+source "kernel/Kconfig.preempt"
+
+source "net/Kconfig"
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/csky/Kconfig.debug"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
diff --git a/arch/csky/Kconfig.debug b/arch/csky/Kconfig.debug
new file mode 100644
index 0000000..6978702
--- /dev/null
+++ b/arch/csky/Kconfig.debug
@@ -0,0 +1,29 @@
+menu "Kernel hacking"
+
+menu "C-SKY Debug Options"
+config CSKY_DEBUG_INFO
+	bool "Compile the kernel with debug info, just add -g"
+	depends on !DEBUG_INFO
+	help
+	  DEBUG_INFO and COMPILE_TEST is conflict, so we provide
+	  another way to support -g.
+	  Some drivers eg: DW_MMC need COMPILE_TEST for new cpu
+	  arch :(
+
+config CSKY_VECIRQ_LEGENCY
+	bool "Use legency IRQ vector for interrupt, it's for SOC bugfix."
+	help
+	  It's a deprecated method for arch/csky. Don't use it, unless your
+	  SOC has bug.
+
+config CSKY_BUILTIN_DTB
+	bool "Use kernel builtin dtb"
+
+config CSKY_BUILTIN_DTB_NAME
+	string "kernel builtin dtb name"
+	depends on CSKY_BUILTIN_DTB
+endmenu
+
+source "lib/Kconfig.debug"
+
+endmenu
diff --git a/arch/csky/Makefile b/arch/csky/Makefile
new file mode 100644
index 0000000..c297324
--- /dev/null
+++ b/arch/csky/Makefile
@@ -0,0 +1,92 @@
+OBJCOPYFLAGS	:=-O binary
+GZFLAGS		:=-9
+
+ifdef CONFIG_CPU_HAS_FPU
+FPUEXT = f
+endif
+
+ifdef CONFIG_CPU_HAS_TEE
+TEEEXT = t
+endif
+
+ifdef CONFIG_CPU_CK610
+CPUTYPE	= ck610
+CSKYABI	= abiv1
+endif
+
+ifdef CONFIG_CPU_CK810
+CPUTYPE = ck810$(FPUEXT)$(TEEEXT)
+CSKYABI	= abiv2
+endif
+
+ifdef CONFIG_CPU_CK807
+CPUTYPE = ck807$(FPUEXT)$(TEEEXT)
+CSKYABI	= abiv2
+endif
+
+ifdef CONFIG_CPU_CK860
+CPUTYPE = ck860$(FPUEXT)$(TEEEXT)
+CSKYABI	= abiv2
+endif
+
+ifneq ($(CSKYABI),)
+KBUILD_CFLAGS += -mcpu=$(CPUTYPE)
+KBUILD_CFLAGS += -DCSKYCPU_DEF_NAME=\"$(CPUTYPE)\"
+endif
+
+KBUILD_CFLAGS += -pipe
+ifeq ($(CSKYABI),abiv2)
+KBUILD_CFLAGS += -mno-stack-size
+endif
+
+ifeq ($(CONFIG_CSKY_DEBUG_INFO),y)
+KBUILD_CFLAGS += -g
+endif
+
+abidirs := $(patsubst %,arch/csky/%/,$(CSKYABI))
+
+KBUILD_CFLAGS += $(patsubst %,-I$(srctree)/%inc,$(abidirs))
+
+KBUILD_CPPFLAGS += -mlittle-endian
+LDFLAGS += -EL
+
+KBUILD_AFLAGS += $(KBUILD_CFLAGS)
+
+head-y := arch/csky/kernel/head.o
+
+core-y += arch/csky/kernel/
+core-y += arch/csky/mm/
+core-y += arch/csky/$(CSKYABI)/
+
+libs-y += arch/csky/lib/ \
+	$(shell $(CC) $(KBUILD_CFLAGS) $(KCFLAGS) -print-libgcc-file-name)
+
+ifdef CONFIG_CSKY_BUILTIN_DTB
+core-y += arch/csky/boot/dts/
+endif
+
+all: zImage
+
+boot := arch/csky/boot
+
+dtbs: scripts
+	$(Q)$(MAKE) $(build)=$(boot)/dts
+
+%.dtb %.dtb.S %.dtb.o: scripts
+	$(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@
+
+zImage Image uImage: vmlinux dtbs
+	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+archmrproper:
+
+archclean:
+	$(Q)$(MAKE) $(clean)=$(boot)
+	rm -rf arch/csky/include/generated
+
+define archhelp
+  echo  '* zImage       - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
+  echo  '  Image        - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
+  echo  '  uImage       - U-Boot wrapped zImage'
+endef
+
diff --git a/arch/csky/abiv1/Makefile b/arch/csky/abiv1/Makefile
new file mode 100644
index 0000000..c63c6d2
--- /dev/null
+++ b/arch/csky/abiv1/Makefile
@@ -0,0 +1,8 @@
+obj-y +=	bswapdi.o
+obj-y +=	bswapsi.o
+obj-y +=	cacheflush.o
+obj-y +=	memcpy.o
+obj-y +=	mmap.o
+
+obj-$(CONFIG_CPU_NEED_SOFTALIGN) +=	alignment.o
+
diff --git a/arch/csky/abiv2/Makefile b/arch/csky/abiv2/Makefile
new file mode 100644
index 0000000..c90d0fe
--- /dev/null
+++ b/arch/csky/abiv2/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_CPU_HAS_FPU)	+= fpu.o
+obj-y				+= memcpy.o
+obj-y				+= cacheflush.o
+
diff --git a/arch/csky/boot/Makefile b/arch/csky/boot/Makefile
new file mode 100644
index 0000000..c3301a8
--- /dev/null
+++ b/arch/csky/boot/Makefile
@@ -0,0 +1,25 @@
+targets := Image zImage uImage
+targets += $(dtb-y)
+
+$(obj)/Image: vmlinux FORCE
+	$(call if_changed,objcopy)
+	@echo '  Kernel: $@ is ready'
+
+compress-$(CONFIG_KERNEL_GZIP) = gzip
+compress-$(CONFIG_KERNEL_LZO)  = lzo
+compress-$(CONFIG_KERNEL_LZMA) = lzma
+compress-$(CONFIG_KERNEL_XZ)   = xzkern
+compress-$(CONFIG_KERNEL_LZ4)  = lz4
+
+$(obj)/zImage:  $(obj)/Image FORCE
+	$(call if_changed,$(compress-y))
+	@echo '  Kernel: $@ is ready'
+
+UIMAGE_ARCH		= sandbox
+UIMAGE_COMPRESSION	= $(compress-y)
+UIMAGE_LOADADDR		= $(shell $(NM) vmlinux | awk '$$NF == "_start" {print $$1}')
+
+$(obj)/uImage: $(obj)/zImage
+	$(call if_changed,uimage)
+	@echo 'Image: $@ is ready'
+
diff --git a/arch/csky/boot/dts/Makefile b/arch/csky/boot/dts/Makefile
new file mode 100644
index 0000000..9afc954
--- /dev/null
+++ b/arch/csky/boot/dts/Makefile
@@ -0,0 +1,14 @@
+dtstree	:= $(srctree)/$(src)
+
+ifdef CONFIG_CSKY_BUILTIN_DTB
+builtindtb-y := $(patsubst "%",%,$(CONFIG_CSKY_BUILTIN_DTB_NAME))
+dtb-y += $(builtindtb-y).dtb
+obj-y += $(builtindtb-y).dtb.o
+.SECONDARY: $(obj)/$(builtindtb-y).dtb.S
+else
+dtb-y := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts))
+endif
+
+always += $(dtb-y)
+clean-files += *.dtb *.dtb.S
+
diff --git a/arch/csky/boot/dts/include/dt-bindings b/arch/csky/boot/dts/include/dt-bindings
new file mode 120000
index 0000000..08c00e4
--- /dev/null
+++ b/arch/csky/boot/dts/include/dt-bindings
@@ -0,0 +1 @@
+../../../../../include/dt-bindings
\ No newline at end of file
diff --git a/arch/csky/include/asm/Kbuild b/arch/csky/include/asm/Kbuild
new file mode 100644
index 0000000..5de6519
--- /dev/null
+++ b/arch/csky/include/asm/Kbuild
@@ -0,0 +1,72 @@
+generic-y += asm-offsets.h
+generic-y += atomic.h
+generic-y += auxvec.h
+generic-y += bitsperlong.h
+generic-y += bug.h
+generic-y += bugs.h
+generic-y += clkdev.h
+generic-y += cputime.h
+generic-y += current.h
+generic-y += delay.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += dma.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += exec.h
+generic-y += fb.h
+generic-y += ftrace.h
+generic-y += futex.h
+generic-y += gpio.h
+generic-y += hardirq.h
+generic-y += hw_irq.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += irq_regs.h
+generic-y += ipcbuf.h
+generic-y += irq_work.h
+generic-y += kdebug.h
+generic-y += kmap_types.h
+generic-y += kprobes.h
+generic-y += kvm_para.h
+generic-y += linkage.h
+generic-y += local.h
+generic-y += local64.h
+generic-y += mman.h
+generic-y += mm-arch-hooks.h
+generic-y += module.h
+generic-y += msgbuf.h
+generic-y += mutex.h
+generic-y += param.h
+generic-y += pci.h
+generic-y += percpu.h
+generic-y += posix_types.h
+generic-y += poll.h
+generic-y += preempt.h
+generic-y += resource.h
+generic-y += scatterlist.h
+generic-y += sections.h
+generic-y += sembuf.h
+generic-y += serial.h
+generic-y += setup.h
+generic-y += shmbuf.h
+generic-y += shm.h
+generic-y += siginfo.h
+generic-y += signal.h
+generic-y += sizes.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += statfs.h
+generic-y += switch_to.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += timex.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 += vmlinux.lds.h
+generic-y += word-at-a-time.h
diff --git a/arch/csky/include/uapi/asm/Kbuild b/arch/csky/include/uapi/asm/Kbuild
new file mode 100644
index 0000000..b65252b
--- /dev/null
+++ b/arch/csky/include/uapi/asm/Kbuild
@@ -0,0 +1,33 @@
+include include/uapi/asm-generic/Kbuild.asm
+
+header-y += cachectl.h
+header-y += stat.h
+
+generic-y += auxvec.h
+generic-y += param.h
+generic-y += bpf_perf_event.h
+generic-y += errno.h
+generic-y += fcntl.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += ipcbuf.h
+generic-y += shmbuf.h
+generic-y += bitsperlong.h
+generic-y += mman.h
+generic-y += msgbuf.h
+generic-y += poll.h
+generic-y += posix_types.h
+generic-y += resource.h
+generic-y += sembuf.h
+generic-y += siginfo.h
+generic-y += signal.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += statfs.h
+generic-y += stat.h
+generic-y += setup.h
+generic-y += swab.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += types.h
+generic-y += ucontext.h
diff --git a/arch/csky/kernel/Makefile b/arch/csky/kernel/Makefile
new file mode 100644
index 0000000..5403650
--- /dev/null
+++ b/arch/csky/kernel/Makefile
@@ -0,0 +1,8 @@
+extra-y := head.o vmlinux.lds
+
+obj-y += entry.o atomic.o signal.o traps.o irq.o time.o vdso.o \
+	 power.o syscall.o platform.o syscall_table.o setup.o \
+	 cskyksyms.o process.o cpu-probe.o ptrace.o dumpstack.o
+
+obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/csky/lib/Makefile b/arch/csky/lib/Makefile
new file mode 100644
index 0000000..02aefbc
--- /dev/null
+++ b/arch/csky/lib/Makefile
@@ -0,0 +1 @@
+lib-y  := memset.o usercopy.o delay.o
diff --git a/arch/csky/mm/Makefile b/arch/csky/mm/Makefile
new file mode 100644
index 0000000..c870eb3
--- /dev/null
+++ b/arch/csky/mm/Makefile
@@ -0,0 +1,13 @@
+ifeq ($(CONFIG_CPU_HAS_CACHEV2),y)
+obj-y +=			cachev2.o
+else
+obj-y +=			cachev1.o
+endif
+
+obj-y +=			dma-mapping.o
+obj-y +=			fault.o
+obj-$(CONFIG_HIGHMEM) +=	highmem.o
+obj-y +=			init.o
+obj-y +=			ioremap.o
+obj-y +=			syscache.o
+obj-y +=			tlb.o
-- 
2.7.4


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

* [PATCH V2 02/19] csky: defconfig
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
  2018-07-01 17:30 ` [PATCH V2 01/19] csky: Build infrastructure Guo Ren
@ 2018-07-01 17:30 ` Guo Ren
  2018-07-03  3:16   ` Rob Herring
  2018-07-01 17:30 ` [PATCH V2 03/19] csky: Kernel booting Guo Ren
                   ` (17 subsequent siblings)
  19 siblings, 1 reply; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/configs/gx66xx_defconfig     | 549 +++++++++++++++++++++++++++++++++
 arch/csky/configs/qemu_ck807_defconfig | 541 ++++++++++++++++++++++++++++++++
 2 files changed, 1090 insertions(+)
 create mode 100644 arch/csky/configs/gx66xx_defconfig
 create mode 100644 arch/csky/configs/qemu_ck807_defconfig

diff --git a/arch/csky/configs/gx66xx_defconfig b/arch/csky/configs/gx66xx_defconfig
new file mode 100644
index 0000000..7f2a987
--- /dev/null
+++ b/arch/csky/configs/gx66xx_defconfig
@@ -0,0 +1,549 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_DEFAULT_HOSTNAME="github.com/c-sky"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_FHANDLE is not set
+CONFIG_USELIB=y
+CONFIG_AUDIT=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_RELAY=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_AIO is not set
+CONFIG_USERFAULTFD=y
+CONFIG_EMBEDDED=y
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_BLK_DEV_BSGLIB=y
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ACORN_PARTITION=y
+CONFIG_ACORN_PARTITION_ICS=y
+CONFIG_ACORN_PARTITION_RISCIX=y
+CONFIG_AIX_PARTITION=y
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_SGI_PARTITION=y
+CONFIG_ULTRIX_PARTITION=y
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_SYSV68_PARTITION=y
+CONFIG_CMDLINE_PARTITION=y
+CONFIG_DEFAULT_DEADLINE=y
+CONFIG_FB_NATIONALCHIP=y
+CONFIG_RAM_BASE=0x10000000
+# CONFIG_SUSPEND is not set
+# CONFIG_COMPACTION is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_IPV6 is not set
+CONFIG_CFG80211=y
+CONFIG_CFG80211_DEBUGFS=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=y
+CONFIG_MAC80211_DEBUGFS=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_VIRTIO_BLK=y
+CONFIG_AD525X_DPOT=m
+CONFIG_AD525X_DPOT_I2C=m
+CONFIG_DUMMY_IRQ=m
+CONFIG_ICS932S401=m
+CONFIG_ENCLOSURE_SERVICES=m
+CONFIG_APDS9802ALS=m
+CONFIG_ISL29003=m
+CONFIG_ISL29020=m
+CONFIG_SENSORS_TSL2550=m
+CONFIG_SENSORS_BH1770=m
+CONFIG_SENSORS_APDS990X=m
+CONFIG_HMC6352=m
+CONFIG_DS1682=m
+CONFIG_USB_SWITCH_FSA9480=m
+CONFIG_SRAM=y
+CONFIG_C2PORT=m
+CONFIG_EEPROM_AT24=m
+CONFIG_EEPROM_LEGACY=m
+CONFIG_EEPROM_MAX6875=m
+CONFIG_SENSORS_LIS3_I2C=m
+CONFIG_ALTERA_STAPL=m
+CONFIG_ECHO=m
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_SAS_LIBSAS=m
+CONFIG_SCSI_SRP_ATTRS=m
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_USB_RTL8150=y
+CONFIG_USB_RTL8152=y
+CONFIG_USB_USBNET=y
+# CONFIG_WLAN_VENDOR_ADMTEK is not set
+# CONFIG_WLAN_VENDOR_ATH is not set
+# CONFIG_WLAN_VENDOR_ATMEL is not set
+# CONFIG_WLAN_VENDOR_BROADCOM is not set
+# CONFIG_WLAN_VENDOR_CISCO is not set
+# CONFIG_WLAN_VENDOR_INTEL is not set
+# CONFIG_WLAN_VENDOR_INTERSIL is not set
+# CONFIG_WLAN_VENDOR_MARVELL is not set
+CONFIG_MT7601U=m
+# CONFIG_WLAN_VENDOR_RALINK is not set
+CONFIG_RTL8187=y
+CONFIG_RTL8XXXU=y
+CONFIG_RTL8XXXU_UNTESTED=y
+# CONFIG_WLAN_VENDOR_RSI is not set
+# CONFIG_WLAN_VENDOR_ST is not set
+# CONFIG_WLAN_VENDOR_TI is not set
+# CONFIG_WLAN_VENDOR_ZYDAS is not set
+CONFIG_INPUT_SPARSEKMAP=m
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_ADP5588=m
+CONFIG_KEYBOARD_ADP5589=m
+CONFIG_KEYBOARD_QT1070=m
+CONFIG_KEYBOARD_QT2160=m
+CONFIG_KEYBOARD_LKKBD=m
+CONFIG_KEYBOARD_GPIO_POLLED=m
+CONFIG_KEYBOARD_TCA6416=m
+CONFIG_KEYBOARD_TCA8418=m
+CONFIG_KEYBOARD_LM8323=m
+CONFIG_KEYBOARD_LM8333=m
+CONFIG_KEYBOARD_MAX7359=m
+CONFIG_KEYBOARD_MCS=m
+CONFIG_KEYBOARD_MPR121=m
+CONFIG_KEYBOARD_NEWTON=m
+CONFIG_KEYBOARD_OPENCORES=m
+CONFIG_KEYBOARD_STOWAWAY=m
+CONFIG_KEYBOARD_SUNKBD=m
+CONFIG_KEYBOARD_XTKBD=m
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_MOUSE_PS2_SENTELIC=y
+CONFIG_MOUSE_PS2_TOUCHKIT=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_CYAPA=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_MOUSE_SYNAPTICS_I2C=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_ZHENHUA=m
+CONFIG_JOYSTICK_AS5011=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TABLET=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_AD7879=m
+CONFIG_TOUCHSCREEN_AD7879_I2C=m
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+CONFIG_TOUCHSCREEN_BU21013=m
+CONFIG_TOUCHSCREEN_CYTTSP_CORE=m
+CONFIG_TOUCHSCREEN_CYTTSP_I2C=m
+CONFIG_TOUCHSCREEN_CYTTSP4_CORE=m
+CONFIG_TOUCHSCREEN_CYTTSP4_I2C=m
+CONFIG_TOUCHSCREEN_DYNAPRO=m
+CONFIG_TOUCHSCREEN_HAMPSHIRE=m
+CONFIG_TOUCHSCREEN_EETI=m
+CONFIG_TOUCHSCREEN_FUJITSU=m
+CONFIG_TOUCHSCREEN_ILI210X=m
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_WACOM_W8001=m
+CONFIG_TOUCHSCREEN_WACOM_I2C=m
+CONFIG_TOUCHSCREEN_MAX11801=m
+CONFIG_TOUCHSCREEN_MCS5000=m
+CONFIG_TOUCHSCREEN_MMS114=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_INEXIO=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_TOUCHSCREEN_PENMOUNT=m
+CONFIG_TOUCHSCREEN_EDT_FT5X06=m
+CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
+CONFIG_TOUCHSCREEN_TOUCHWIN=m
+CONFIG_TOUCHSCREEN_PIXCIR=m
+CONFIG_TOUCHSCREEN_TOUCHIT213=m
+CONFIG_TOUCHSCREEN_TSC_SERIO=m
+CONFIG_TOUCHSCREEN_TSC2007=m
+CONFIG_TOUCHSCREEN_ST1232=m
+CONFIG_TOUCHSCREEN_TPS6507X=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AD714X=m
+CONFIG_INPUT_BMA150=m
+CONFIG_INPUT_MMA8450=m
+CONFIG_INPUT_MPU3050=m
+CONFIG_INPUT_KXTJ9=m
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_PCF8574=m
+CONFIG_INPUT_ADXL34X=m
+CONFIG_INPUT_CMA3000=m
+CONFIG_INPUT_CMA3000_I2C=m
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_RAW=m
+CONFIG_SERIO_ALTERA_PS2=m
+CONFIG_SERIO_PS2MULT=m
+CONFIG_SERIO_ARC_PS2=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_TTY_PRINTK=y
+CONFIG_VIRTIO_CONSOLE=y
+CONFIG_IPMI_HANDLER=y
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_TIMERIOMEM=m
+CONFIG_HW_RANDOM_VIRTIO=m
+CONFIG_HW_RANDOM_TPM=m
+CONFIG_TCG_TIS_I2C_ATMEL=m
+CONFIG_TCG_TIS_I2C_INFINEON=m
+CONFIG_TCG_TIS_I2C_NUVOTON=m
+CONFIG_TCG_ATMEL=m
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_MUX_PCA9541=m
+CONFIG_I2C_DESIGNWARE_PLATFORM=m
+CONFIG_I2C_OCORES=m
+CONFIG_I2C_PCA_PLATFORM=m
+CONFIG_I2C_SIMTEC=m
+CONFIG_I2C_XILINX=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_TAOS_EVM=m
+CONFIG_I2C_STUB=m
+CONFIG_PPS=m
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_PPS_CLIENT_GPIO=m
+CONFIG_GPIOLIB=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+CONFIG_POWER_RESET=y
+# CONFIG_HWMON is not set
+CONFIG_SSB=m
+CONFIG_BCMA=m
+CONFIG_BCMA_HOST_SOC=y
+CONFIG_BCMA_DRIVER_GMAC_CMN=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=y
+# CONFIG_USB_GSPCA is not set
+CONFIG_FB=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_SIMPLE=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_HID_A4TECH=m
+CONFIG_HID_ACRUX=m
+CONFIG_HID_ACRUX_FF=y
+CONFIG_HID_APPLE=m
+CONFIG_HID_AUREAL=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DRAGONRISE=m
+CONFIG_DRAGONRISE_FF=y
+CONFIG_HID_EMS_FF=m
+CONFIG_HID_ELECOM=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_KEYTOUCH=m
+CONFIG_HID_KYE=m
+CONFIG_HID_WALTOP=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_ICADE=m
+CONFIG_HID_TWINHAN=m
+CONFIG_HID_KENSINGTON=m
+CONFIG_HID_LCPOWER=m
+CONFIG_HID_LOGITECH=m
+CONFIG_HID_LOGITECH_HIDPP=m
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_LOGIG940_FF=y
+CONFIG_HID_MAGICMOUSE=m
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_MULTITOUCH=m
+CONFIG_HID_ORTEK=m
+CONFIG_HID_PANTHERLORD=m
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_PICOLCD=m
+CONFIG_HID_PICOLCD_LEDS=y
+CONFIG_HID_PRIMAX=m
+CONFIG_HID_SAITEK=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SPEEDLINK=m
+CONFIG_HID_STEELSERIES=m
+CONFIG_HID_SUNPLUS=m
+CONFIG_HID_RMI=m
+CONFIG_HID_GREENASIA=m
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_SMARTJOYPLUS=m
+CONFIG_SMARTJOYPLUS_FF=y
+CONFIG_HID_TIVO=m
+CONFIG_HID_TOPSEED=m
+CONFIG_HID_THINGM=m
+CONFIG_HID_THRUSTMASTER=m
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_HID_WACOM=m
+CONFIG_HID_WIIMOTE=m
+CONFIG_HID_XINMO=m
+CONFIG_HID_ZEROPLUS=m
+CONFIG_ZEROPLUS_FF=y
+CONFIG_HID_ZYDACRON=m
+CONFIG_HID_SENSOR_HUB=m
+CONFIG_HID_PID=y
+CONFIG_I2C_HID=m
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_LM3530=m
+CONFIG_LEDS_LM3642=m
+CONFIG_LEDS_PCA9532=m
+CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_LP3944=m
+CONFIG_LEDS_LP5521=m
+CONFIG_LEDS_LP5523=m
+CONFIG_LEDS_LP5562=m
+CONFIG_LEDS_LP8501=m
+CONFIG_LEDS_PCA955X=m
+CONFIG_LEDS_PCA963X=m
+CONFIG_LEDS_BD2802=m
+CONFIG_LEDS_TCA6507=m
+CONFIG_LEDS_LM355x=m
+CONFIG_LEDS_BLINKM=m
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_LEDS_TRIGGER_TRANSIENT=y
+CONFIG_LEDS_TRIGGER_CAMERA=y
+CONFIG_LEDS_TRIGGER_PANIC=y
+CONFIG_VIRTIO_BALLOON=y
+CONFIG_VIRTIO_MMIO=y
+CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_STE_MODEM_RPROC=m
+CONFIG_PM_DEVFREQ=y
+CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
+CONFIG_DEVFREQ_GOV_PERFORMANCE=y
+CONFIG_DEVFREQ_GOV_POWERSAVE=y
+CONFIG_DEVFREQ_GOV_USERSPACE=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_FANOTIFY=y
+CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
+CONFIG_QUOTA=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_FSCACHE=m
+CONFIG_FSCACHE_STATS=y
+CONFIG_CACHEFILES=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_UTF8=y
+CONFIG_NTFS_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=y
+CONFIG_NLS_CODEPAGE_775=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_CODEPAGE_857=y
+CONFIG_NLS_CODEPAGE_860=y
+CONFIG_NLS_CODEPAGE_861=y
+CONFIG_NLS_CODEPAGE_863=y
+CONFIG_NLS_CODEPAGE_864=y
+CONFIG_NLS_CODEPAGE_865=y
+CONFIG_NLS_CODEPAGE_866=y
+CONFIG_NLS_CODEPAGE_869=y
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=y
+CONFIG_NLS_CODEPAGE_932=y
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOCKUP_DETECTOR=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_RBTREE_TEST=m
+CONFIG_INTERVAL_TREE_TEST=m
+CONFIG_PERCPU_TEST=m
+CONFIG_TEST_STRING_HELPERS=m
+CONFIG_TEST_KSTRTOX=m
+CONFIG_PERSISTENT_KEYRINGS=y
+CONFIG_TRUSTED_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_PATH=y
+CONFIG_SECURITY_YAMA=y
+CONFIG_INTEGRITY_SIGNATURE=y
+CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
+CONFIG_IMA=y
+CONFIG_IMA_APPRAISE=y
+CONFIG_EVM=y
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_CMAC=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_CRC32=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_LZO=y
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRC_CCITT=m
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
+CONFIG_CRC8=m
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_TEST=m
+CONFIG_CORDIC=m
+CONFIG_DDR=y
diff --git a/arch/csky/configs/qemu_ck807_defconfig b/arch/csky/configs/qemu_ck807_defconfig
new file mode 100644
index 0000000..0591cbc
--- /dev/null
+++ b/arch/csky/configs/qemu_ck807_defconfig
@@ -0,0 +1,541 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_DEFAULT_HOSTNAME="github.com/c-sky"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_FHANDLE is not set
+CONFIG_USELIB=y
+CONFIG_AUDIT=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_RELAY=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_AIO is not set
+CONFIG_USERFAULTFD=y
+CONFIG_EMBEDDED=y
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_BLK_DEV_BSGLIB=y
+CONFIG_BLK_DEV_INTEGRITY=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ACORN_PARTITION=y
+CONFIG_ACORN_PARTITION_ICS=y
+CONFIG_ACORN_PARTITION_RISCIX=y
+CONFIG_AIX_PARTITION=y
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_SGI_PARTITION=y
+CONFIG_ULTRIX_PARTITION=y
+CONFIG_SUN_PARTITION=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_SYSV68_PARTITION=y
+CONFIG_CMDLINE_PARTITION=y
+CONFIG_DEFAULT_DEADLINE=y
+CONFIG_NATIONALCHIP_TIMER=y
+CONFIG_NATIONALCHIP_IRQ=y
+CONFIG_CSKY_IRQ=y
+CONFIG_CSKYMAC=y
+CONFIG_CPU_CK807=y
+CONFIG_CPU_HAS_FPU=y
+CONFIG_RAM_BASE=0x0
+# CONFIG_SUSPEND is not set
+# CONFIG_COMPACTION is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_VIRTIO_BLK=y
+CONFIG_AD525X_DPOT=m
+CONFIG_AD525X_DPOT_I2C=m
+CONFIG_DUMMY_IRQ=m
+CONFIG_ICS932S401=m
+CONFIG_ENCLOSURE_SERVICES=m
+CONFIG_APDS9802ALS=m
+CONFIG_ISL29003=m
+CONFIG_ISL29020=m
+CONFIG_SENSORS_TSL2550=m
+CONFIG_SENSORS_BH1770=m
+CONFIG_SENSORS_APDS990X=m
+CONFIG_HMC6352=m
+CONFIG_DS1682=m
+CONFIG_USB_SWITCH_FSA9480=m
+CONFIG_SRAM=y
+CONFIG_C2PORT=m
+CONFIG_EEPROM_AT24=m
+CONFIG_EEPROM_LEGACY=m
+CONFIG_EEPROM_MAX6875=m
+CONFIG_EEPROM_93CX6=m
+CONFIG_SENSORS_LIS3_I2C=m
+CONFIG_ALTERA_STAPL=m
+CONFIG_ECHO=m
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_SAS_LIBSAS=m
+CONFIG_SCSI_SRP_ATTRS=m
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+CONFIG_STMMAC_ETH=y
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_USB_NET_DRIVERS is not set
+# CONFIG_WLAN is not set
+CONFIG_INPUT_SPARSEKMAP=m
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_ADP5588=m
+CONFIG_KEYBOARD_ADP5589=m
+CONFIG_KEYBOARD_QT1070=m
+CONFIG_KEYBOARD_QT2160=m
+CONFIG_KEYBOARD_LKKBD=m
+CONFIG_KEYBOARD_TCA6416=m
+CONFIG_KEYBOARD_TCA8418=m
+CONFIG_KEYBOARD_LM8323=m
+CONFIG_KEYBOARD_LM8333=m
+CONFIG_KEYBOARD_MAX7359=m
+CONFIG_KEYBOARD_MCS=m
+CONFIG_KEYBOARD_MPR121=m
+CONFIG_KEYBOARD_NEWTON=m
+CONFIG_KEYBOARD_OPENCORES=m
+CONFIG_KEYBOARD_STOWAWAY=m
+CONFIG_KEYBOARD_SUNKBD=m
+CONFIG_KEYBOARD_XTKBD=m
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_MOUSE_PS2_SENTELIC=y
+CONFIG_MOUSE_PS2_TOUCHKIT=y
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_CYAPA=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_MOUSE_SYNAPTICS_I2C=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_ZHENHUA=m
+CONFIG_JOYSTICK_AS5011=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TABLET=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_AD7879=m
+CONFIG_TOUCHSCREEN_AD7879_I2C=m
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+CONFIG_TOUCHSCREEN_BU21013=m
+CONFIG_TOUCHSCREEN_CYTTSP_CORE=m
+CONFIG_TOUCHSCREEN_CYTTSP_I2C=m
+CONFIG_TOUCHSCREEN_CYTTSP4_CORE=m
+CONFIG_TOUCHSCREEN_CYTTSP4_I2C=m
+CONFIG_TOUCHSCREEN_DYNAPRO=m
+CONFIG_TOUCHSCREEN_HAMPSHIRE=m
+CONFIG_TOUCHSCREEN_EETI=m
+CONFIG_TOUCHSCREEN_FUJITSU=m
+CONFIG_TOUCHSCREEN_ILI210X=m
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_WACOM_W8001=m
+CONFIG_TOUCHSCREEN_WACOM_I2C=m
+CONFIG_TOUCHSCREEN_MAX11801=m
+CONFIG_TOUCHSCREEN_MCS5000=m
+CONFIG_TOUCHSCREEN_MMS114=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_INEXIO=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_TOUCHSCREEN_PENMOUNT=m
+CONFIG_TOUCHSCREEN_EDT_FT5X06=m
+CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
+CONFIG_TOUCHSCREEN_TOUCHWIN=m
+CONFIG_TOUCHSCREEN_PIXCIR=m
+CONFIG_TOUCHSCREEN_TOUCHIT213=m
+CONFIG_TOUCHSCREEN_TSC_SERIO=m
+CONFIG_TOUCHSCREEN_TSC2007=m
+CONFIG_TOUCHSCREEN_ST1232=m
+CONFIG_TOUCHSCREEN_TPS6507X=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AD714X=m
+CONFIG_INPUT_BMA150=m
+CONFIG_INPUT_MMA8450=m
+CONFIG_INPUT_MPU3050=m
+CONFIG_INPUT_KXTJ9=m
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_PCF8574=m
+CONFIG_INPUT_ADXL34X=m
+CONFIG_INPUT_CMA3000=m
+CONFIG_INPUT_CMA3000_I2C=m
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_RAW=m
+CONFIG_SERIO_ALTERA_PS2=m
+CONFIG_SERIO_PS2MULT=m
+CONFIG_SERIO_ARC_PS2=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_TTY_PRINTK=y
+CONFIG_VIRTIO_CONSOLE=y
+CONFIG_IPMI_HANDLER=y
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_TIMERIOMEM=m
+CONFIG_HW_RANDOM_VIRTIO=m
+CONFIG_HW_RANDOM_TPM=m
+CONFIG_TCG_TIS_I2C_ATMEL=m
+CONFIG_TCG_TIS_I2C_INFINEON=m
+CONFIG_TCG_TIS_I2C_NUVOTON=m
+CONFIG_TCG_ATMEL=m
+CONFIG_I2C_CHARDEV=m
+CONFIG_I2C_MUX_PCA9541=m
+CONFIG_I2C_DESIGNWARE_PLATFORM=m
+CONFIG_I2C_OCORES=m
+CONFIG_I2C_PCA_PLATFORM=m
+CONFIG_I2C_SIMTEC=m
+CONFIG_I2C_XILINX=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_TAOS_EVM=m
+CONFIG_I2C_STUB=m
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_PPS_CLIENT_GPIO=m
+CONFIG_POWER_RESET=y
+# CONFIG_HWMON is not set
+CONFIG_SSB=m
+CONFIG_BCMA=m
+CONFIG_BCMA_HOST_SOC=y
+CONFIG_BCMA_DRIVER_GMAC_CMN=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=y
+# CONFIG_USB_GSPCA is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_PLATFORM=m
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=m
+CONFIG_BACKLIGHT_ADP8860=m
+CONFIG_BACKLIGHT_ADP8870=m
+CONFIG_BACKLIGHT_LM3639=m
+CONFIG_BACKLIGHT_LV5207LP=m
+CONFIG_BACKLIGHT_BD6107=m
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_HID_GENERIC is not set
+CONFIG_HID_A4TECH=m
+CONFIG_HID_ACRUX=m
+CONFIG_HID_ACRUX_FF=y
+CONFIG_HID_APPLE=m
+CONFIG_HID_AUREAL=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DRAGONRISE=m
+CONFIG_DRAGONRISE_FF=y
+CONFIG_HID_EMS_FF=m
+CONFIG_HID_ELECOM=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_KEYTOUCH=m
+CONFIG_HID_KYE=m
+CONFIG_HID_WALTOP=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_ICADE=m
+CONFIG_HID_TWINHAN=m
+CONFIG_HID_KENSINGTON=m
+CONFIG_HID_LCPOWER=m
+CONFIG_HID_LOGITECH=m
+CONFIG_HID_LOGITECH_HIDPP=m
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_LOGIG940_FF=y
+CONFIG_HID_MAGICMOUSE=m
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_MULTITOUCH=m
+CONFIG_HID_ORTEK=m
+CONFIG_HID_PANTHERLORD=m
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_PICOLCD=m
+CONFIG_HID_PICOLCD_BACKLIGHT=y
+CONFIG_HID_PICOLCD_LCD=y
+CONFIG_HID_PICOLCD_LEDS=y
+CONFIG_HID_PRIMAX=m
+CONFIG_HID_SAITEK=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SPEEDLINK=m
+CONFIG_HID_STEELSERIES=m
+CONFIG_HID_SUNPLUS=m
+CONFIG_HID_RMI=m
+CONFIG_HID_GREENASIA=m
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_SMARTJOYPLUS=m
+CONFIG_SMARTJOYPLUS_FF=y
+CONFIG_HID_TIVO=m
+CONFIG_HID_TOPSEED=m
+CONFIG_HID_THINGM=m
+CONFIG_HID_THRUSTMASTER=m
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_HID_WACOM=m
+CONFIG_HID_WIIMOTE=m
+CONFIG_HID_XINMO=m
+CONFIG_HID_ZEROPLUS=m
+CONFIG_ZEROPLUS_FF=y
+CONFIG_HID_ZYDACRON=m
+CONFIG_HID_SENSOR_HUB=m
+CONFIG_I2C_HID=m
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_LM3530=m
+CONFIG_LEDS_LM3642=m
+CONFIG_LEDS_PCA9532=m
+CONFIG_LEDS_LP3944=m
+CONFIG_LEDS_LP5521=m
+CONFIG_LEDS_LP5523=m
+CONFIG_LEDS_LP5562=m
+CONFIG_LEDS_LP8501=m
+CONFIG_LEDS_PCA955X=m
+CONFIG_LEDS_PCA963X=m
+CONFIG_LEDS_BD2802=m
+CONFIG_LEDS_TCA6507=m
+CONFIG_LEDS_LM355x=m
+CONFIG_LEDS_BLINKM=m
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_ONESHOT=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+CONFIG_LEDS_TRIGGER_TRANSIENT=m
+CONFIG_LEDS_TRIGGER_CAMERA=m
+CONFIG_VIRTIO_BALLOON=y
+CONFIG_VIRTIO_MMIO=y
+CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_STE_MODEM_RPROC=m
+CONFIG_PM_DEVFREQ=y
+CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
+CONFIG_DEVFREQ_GOV_PERFORMANCE=y
+CONFIG_DEVFREQ_GOV_POWERSAVE=y
+CONFIG_DEVFREQ_GOV_USERSPACE=y
+CONFIG_GENERIC_PHY=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_FANOTIFY=y
+CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
+CONFIG_QUOTA=y
+# CONFIG_PRINT_QUOTA_WARNING is not set
+CONFIG_FSCACHE=m
+CONFIG_FSCACHE_STATS=y
+CONFIG_CACHEFILES=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_UTF8=y
+CONFIG_NTFS_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=y
+CONFIG_NLS_CODEPAGE_775=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_CODEPAGE_857=y
+CONFIG_NLS_CODEPAGE_860=y
+CONFIG_NLS_CODEPAGE_861=y
+CONFIG_NLS_CODEPAGE_863=y
+CONFIG_NLS_CODEPAGE_864=y
+CONFIG_NLS_CODEPAGE_865=y
+CONFIG_NLS_CODEPAGE_866=y
+CONFIG_NLS_CODEPAGE_869=y
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=y
+CONFIG_NLS_CODEPAGE_932=y
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
+CONFIG_NLS_UTF8=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOCKUP_DETECTOR=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_RBTREE_TEST=m
+CONFIG_INTERVAL_TREE_TEST=m
+CONFIG_PERCPU_TEST=m
+CONFIG_TEST_STRING_HELPERS=m
+CONFIG_TEST_KSTRTOX=m
+CONFIG_PERSISTENT_KEYRINGS=y
+CONFIG_TRUSTED_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_PATH=y
+CONFIG_SECURITY_YAMA=y
+CONFIG_INTEGRITY_SIGNATURE=y
+CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
+CONFIG_IMA=y
+CONFIG_IMA_APPRAISE=y
+CONFIG_EVM=y
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_CMAC=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_CRC32=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_LZO=y
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRC_CCITT=m
+CONFIG_CRC7=m
+CONFIG_LIBCRC32C=m
+CONFIG_CRC8=m
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_TEST=m
+CONFIG_CORDIC=m
+CONFIG_DDR=y
-- 
2.7.4


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

* [PATCH V2 03/19] csky: Kernel booting
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
  2018-07-01 17:30 ` [PATCH V2 01/19] csky: Build infrastructure Guo Ren
  2018-07-01 17:30 ` [PATCH V2 02/19] csky: defconfig Guo Ren
@ 2018-07-01 17:30 ` Guo Ren
  2018-07-01 17:30 ` [PATCH V2 04/19] csky: Exception handling Guo Ren
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/kernel/head.S        |  81 ++++++++++++++++++++++
 arch/csky/kernel/setup.c       | 148 +++++++++++++++++++++++++++++++++++++++++
 arch/csky/kernel/vmlinux.lds.S |  65 ++++++++++++++++++
 3 files changed, 294 insertions(+)
 create mode 100644 arch/csky/kernel/head.S
 create mode 100644 arch/csky/kernel/setup.c
 create mode 100644 arch/csky/kernel/vmlinux.lds.S

diff --git a/arch/csky/kernel/head.S b/arch/csky/kernel/head.S
new file mode 100644
index 0000000..3f0be9a
--- /dev/null
+++ b/arch/csky/kernel/head.S
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/page.h>
+#include <abi/regdef.h>
+
+__HEAD
+ENTRY(_start)
+	/* set super user mode */
+	lrw	a3, DEFAULT_PSR_VALUE
+	mtcr    a3, psr
+	psrset  ee
+
+	/* set stack point */
+	lrw     a3, init_thread_union + THREAD_SIZE
+	mov	sp, a3
+
+	jmpi	csky_start
+END(_start)
+
+#ifdef CONFIG_SMP
+.align 10
+ENTRY(_start_smp_secondary)
+	/* Invalid I/Dcache BTB BHT */
+	movi	a3, 7
+	lsli	a3, 16
+	addi	a3, (1<<4) | 3
+	mtcr	a3, cr17
+
+	tlbi.all
+
+	/* setup PAGEMASK */
+	movi	a3, 0
+	mtcr	a3, cr<6, 15>
+
+	/* setup MEL0/MEL1 */
+	grs	a0, _start_smp_pc
+_start_smp_pc:
+	bmaski  a1, 13
+	andn    a0, a1
+	movi    a1, 0x00000006
+	movi    a2, 0x00001006
+	or      a1, a0
+	or      a2, a0
+	mtcr	a1, cr<2, 15>
+	mtcr	a2, cr<3, 15>
+
+	/* setup MEH */
+	mtcr	a0, cr<4, 15>
+
+	/* write TLB */
+	bgeni   a3, 28
+	mtcr	a3, cr<8, 15>
+
+	/* setup msa0 & msa1 */
+	lrw	a3, PHYS_OFFSET | 0x8e
+	mtcr	a3, cr<30, 15>
+	lrw	a3, PHYS_OFFSET | 0x26
+	mtcr	a3, cr<31, 15>
+
+	/* enable MMU */
+	movi	a3, 1
+	mtcr    a3, cr18
+
+	jmpi	_goto_mmu_on
+_goto_mmu_on:
+	movi	a3, 0xaa
+
+	lrw	a3, DEFAULT_PSR_VALUE
+	mtcr    a3, psr
+	psrset  ee
+
+	/* set stack point */
+	lrw     a3, secondary_stack
+	ld.w	a3, (a3, 0)
+	mov	sp, a3
+
+	jmpi	csky_start_secondary
+END(_start_smp_secondary)
+#endif
diff --git a/arch/csky/kernel/setup.c b/arch/csky/kernel/setup.c
new file mode 100644
index 0000000..b7e14c8
--- /dev/null
+++ b/arch/csky/kernel/setup.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/console.h>
+#include <linux/memblock.h>
+#include <linux/bootmem.h>
+#include <linux/initrd.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/start_kernel.h>
+#include <asm/sections.h>
+#include <asm/mmu_context.h>
+#include <asm/pgalloc.h>
+
+phys_addr_t __init_memblock memblock_end_of_REG0(void)
+{
+	return (memblock.memory.regions[0].base + memblock.memory.regions[0].size);
+}
+
+phys_addr_t __init_memblock memblock_start_of_REG1(void)
+{
+	return memblock.memory.regions[1].base;
+}
+
+size_t __init_memblock memblock_size_of_REG1(void)
+{
+	return memblock.memory.regions[1].size;
+}
+
+static void __init csky_memblock_init(void)
+{
+	unsigned long zone_size[MAX_NR_ZONES];
+	unsigned long zhole_size[MAX_NR_ZONES];
+	signed long size;
+
+	memblock_reserve(__pa(_stext), _end - _stext);
+#ifdef CONFIG_BLK_DEV_INITRD
+	memblock_reserve(__pa(initrd_start), initrd_end - initrd_start);
+#endif
+
+	early_init_fdt_reserve_self();
+	early_init_fdt_scan_reserved_mem();
+
+	memblock_dump_all();
+
+	memset(zone_size, 0, sizeof(zone_size));
+	memset(zhole_size, 0, sizeof(zhole_size));
+
+	min_low_pfn = PFN_UP(memblock_start_of_DRAM());
+	max_low_pfn = PFN_UP(memblock_end_of_REG0());
+	max_pfn = PFN_DOWN(memblock_end_of_DRAM());
+
+	size = max_pfn - min_low_pfn;
+
+	if (memblock.memory.cnt > 1) {
+		zone_size[ZONE_NORMAL]  = PFN_DOWN(memblock_start_of_REG1()) - min_low_pfn;
+		zhole_size[ZONE_NORMAL] = PFN_DOWN(memblock_start_of_REG1()) - max_low_pfn;
+	} else {
+		if (size <= PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET))
+			zone_size[ZONE_NORMAL] = max_pfn - min_low_pfn;
+		else {
+			zone_size[ZONE_NORMAL] = PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET);
+			max_low_pfn = min_low_pfn + zone_size[ZONE_NORMAL];
+		}
+	}
+
+#ifdef CONFIG_HIGHMEM
+	size = 0;
+	if(memblock.memory.cnt > 1) {
+		size = PFN_DOWN(memblock_size_of_REG1());
+		highstart_pfn = PFN_DOWN(memblock_start_of_REG1());
+	} else {
+		size = max_pfn - min_low_pfn - PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET);
+		highstart_pfn =  min_low_pfn + PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET);
+	}
+
+	if (size > 0)
+		zone_size[ZONE_HIGHMEM] = size;
+
+	highend_pfn = max_pfn;
+#endif
+	memblock_set_current_limit(PFN_PHYS(max_low_pfn));
+
+	free_area_init_node(0, zone_size, min_low_pfn, zhole_size);
+}
+
+extern void cpu_dt_probe(void);
+void __init setup_arch(char **cmdline_p)
+{
+	*cmdline_p = boot_command_line;
+
+	console_verbose();
+
+	pr_info("C-SKY: https://github.com/c-sky/csky-linux\n");
+	pr_info("Phys. mem: %ldMB\n", (unsigned long) memblock_phys_mem_size()/1024/1024);
+
+	init_mm.start_code = (unsigned long) _stext;
+	init_mm.end_code = (unsigned long) _etext;
+	init_mm.end_data = (unsigned long) _edata;
+	init_mm.brk = (unsigned long) _end;
+
+	parse_early_param();
+
+	csky_memblock_init();
+
+	unflatten_and_copy_device_tree();
+
+	cpu_dt_probe();
+
+#ifdef CONFIG_SMP
+	setup_smp();
+#endif
+
+	sparse_init();
+
+#ifdef CONFIG_HIGHMEM
+	kmap_init();
+#endif
+
+#if defined(CONFIG_VT) && defined(CONFIG_DUMMY_CONSOLE)
+	conswitchp = &dummy_con;
+#endif
+}
+
+extern void pre_trap_init(void);
+extern void pre_mmu_init(void);
+
+asmlinkage __visible void __init csky_start(
+	unsigned int	unused,
+	void *		param
+	)
+{
+	/* Clean up bss section */
+	memset(__bss_start, 0, __bss_stop - __bss_start);
+
+	pre_trap_init();
+	pre_mmu_init();
+
+#ifdef CONFIG_CSKY_BUILTIN_DTB
+	pr_info("Use builtin dtb\n");
+	early_init_dt_scan(__dtb_start);
+#else
+	early_init_dt_scan(param);
+#endif
+	start_kernel();
+
+	while(1);
+}
+
diff --git a/arch/csky/kernel/vmlinux.lds.S b/arch/csky/kernel/vmlinux.lds.S
new file mode 100644
index 0000000..fd02acf
--- /dev/null
+++ b/arch/csky/kernel/vmlinux.lds.S
@@ -0,0 +1,65 @@
+#include <asm/vmlinux.lds.h>
+#include <asm/page.h>
+
+OUTPUT_ARCH(csky)
+ENTRY(_start)
+
+#ifndef __cskyBE__
+jiffies = jiffies_64;
+#else
+jiffies = jiffies_64 + 4;
+#endif
+
+#define VBR_BASE \
+	. = ALIGN(1024); \
+	VMLINUX_SYMBOL(vec_base) = .; \
+	. += 512;
+
+SECTIONS
+{
+	. = PAGE_OFFSET + PHYS_OFFSET_OFFSET;
+
+	_stext = .;
+	__init_begin = .;
+	HEAD_TEXT_SECTION
+	INIT_TEXT_SECTION(PAGE_SIZE)
+	INIT_DATA_SECTION(PAGE_SIZE)
+	PERCPU_SECTION(L1_CACHE_BYTES)
+	. = ALIGN(PAGE_SIZE);
+	__init_end = .;
+
+	.text : AT(ADDR(.text) - LOAD_OFFSET) {
+		_text = .;
+		IRQENTRY_TEXT
+		SOFTIRQENTRY_TEXT
+		TEXT_TEXT
+		SCHED_TEXT
+		CPUIDLE_TEXT
+		LOCK_TEXT
+		KPROBES_TEXT
+		*(.fixup)
+		*(.gnu.warning)
+	} = 0
+	_etext = .;
+
+	/* __init_begin __init_end must be page aligned for free_initmem */
+	. = ALIGN(PAGE_SIZE);
+
+
+	_sdata = .;
+	RO_DATA_SECTION(PAGE_SIZE)
+	RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
+	_edata = .;
+
+	NOTES
+	EXCEPTION_TABLE(L1_CACHE_BYTES)
+	BSS_SECTION(L1_CACHE_BYTES, PAGE_SIZE, L1_CACHE_BYTES)
+	VBR_BASE
+	_end = . ;
+
+	STABS_DEBUG
+	DWARF_DEBUG
+
+	DISCARDS
+}
+
-- 
2.7.4


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

* [PATCH V2 04/19] csky: Exception handling
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (2 preceding siblings ...)
  2018-07-01 17:30 ` [PATCH V2 03/19] csky: Kernel booting Guo Ren
@ 2018-07-01 17:30 ` Guo Ren
  2018-07-01 17:30 ` [PATCH V2 05/19] csky: System Call Guo Ren
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/abiv1/alignment.c     | 332 ++++++++++++++++++++++++++++++++
 arch/csky/abiv1/inc/abi/entry.h | 152 +++++++++++++++
 arch/csky/abiv2/inc/abi/entry.h | 149 +++++++++++++++
 arch/csky/include/asm/traps.h   |  39 ++++
 arch/csky/include/asm/unistd.h  |   4 +
 arch/csky/kernel/cpu-probe.c    |  83 ++++++++
 arch/csky/kernel/entry.S        | 407 ++++++++++++++++++++++++++++++++++++++++
 arch/csky/kernel/traps.c        | 167 +++++++++++++++++
 arch/csky/mm/fault.c            | 223 ++++++++++++++++++++++
 9 files changed, 1556 insertions(+)
 create mode 100644 arch/csky/abiv1/alignment.c
 create mode 100644 arch/csky/abiv1/inc/abi/entry.h
 create mode 100644 arch/csky/abiv2/inc/abi/entry.h
 create mode 100644 arch/csky/include/asm/traps.h
 create mode 100644 arch/csky/include/asm/unistd.h
 create mode 100644 arch/csky/kernel/cpu-probe.c
 create mode 100644 arch/csky/kernel/entry.S
 create mode 100644 arch/csky/kernel/traps.c
 create mode 100644 arch/csky/mm/fault.c

diff --git a/arch/csky/abiv1/alignment.c b/arch/csky/abiv1/alignment.c
new file mode 100644
index 0000000..5acc86f
--- /dev/null
+++ b/arch/csky/abiv1/alignment.c
@@ -0,0 +1,332 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/kernel.h>
+#include <linux/uaccess.h>
+#include <linux/ptrace.h>
+
+static int align_enable = 1;
+static int align_count  = 0;
+
+static inline uint32_t get_ptreg(struct pt_regs *regs, uint32_t rx)
+{
+	return *((int *)&(regs->a0) - 2 + rx);
+}
+
+static inline void put_ptreg(struct pt_regs *regs, uint32_t rx, uint32_t val)
+{
+	*((int *)&(regs->a0) - 2 + rx) = val;
+}
+
+/*
+ * Get byte-value from addr and set it to *valp.
+ *
+ * Success: return 0
+ * Failure: return 1
+ */
+static int ldb_asm(uint32_t addr, uint32_t *valp)
+{
+	uint32_t val;
+	int err;
+
+	if (!access_ok(VERIFY_READ, (void *)addr, 1))
+		return 1;
+
+	asm volatile (
+		"movi	%0, 0			\n"
+		"1:				\n"
+		"ldb	%1, (%2)		\n"
+		"br	3f			\n"
+		"2:				\n"
+		"movi	%0, 1			\n"
+		"br	3f			\n"
+		".section __ex_table,\"a\"	\n"
+		".align 2			\n"
+		".long	1b, 2b			\n"
+		".previous			\n"
+		"3:				\n"
+		: "=&r"(err), "=r"(val)
+		: "r" (addr)
+	);
+
+	*valp = val;
+
+	return err;
+}
+
+/*
+ * Put byte-value to addr.
+ *
+ * Success: return 0
+ * Failure: return 1
+ */
+static volatile int stb_asm(uint32_t addr, uint32_t val)
+{
+	int err;
+
+	if (!access_ok(VERIFY_WRITE, (void *)addr, 1))
+		return 1;
+
+	asm volatile (
+		"movi	%0, 0			\n"
+		"1:				\n"
+		"stb	%1, (%2)		\n"
+		"br	3f			\n"
+		"2:				\n"
+		"movi	%0, 1			\n"
+		"br	3f			\n"
+		".section __ex_table,\"a\"	\n"
+		".align 2			\n"
+		".long	1b, 2b			\n"
+		".previous			\n"
+		"3:				\n"
+		: "=&r"(err)
+		: "r"(val), "r" (addr)
+	);
+
+	return err;
+}
+
+/*
+ * Get half-word from [rx + imm]
+ *
+ * Success: return 0
+ * Failure: return 1
+ */
+static int ldh_c(struct pt_regs *regs, uint32_t rz, uint32_t addr)
+{
+	uint32_t byte0, byte1;
+
+	if (ldb_asm(addr, &byte0))
+		return 1;
+	addr += 1;
+	if (ldb_asm(addr, &byte1))
+		return 1;
+
+	byte0 |= byte1 << 8;
+	put_ptreg(regs, rz, byte0);
+
+	return 0;
+}
+
+/*
+ * Store half-word to [rx + imm]
+ *
+ * Success: return 0
+ * Failure: return 1
+ */
+static int sth_c(struct pt_regs *regs, uint32_t rz, uint32_t addr)
+{
+	uint32_t byte0, byte1;
+
+	byte0 = byte1 = get_ptreg(regs, rz);
+
+	byte0 &= 0xff;
+
+	if (stb_asm(addr, byte0))
+		return 1;
+
+	addr += 1;
+	byte1 = (byte1 >> 8) & 0xff;
+	if (stb_asm(addr, byte1))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * Get word from [rx + imm]
+ *
+ * Success: return 0
+ * Failure: return 1
+ */
+static int ldw_c(struct pt_regs *regs, uint32_t rz, uint32_t addr)
+{
+	uint32_t byte0, byte1, byte2, byte3;
+
+	if (ldb_asm(addr, &byte0))
+		return 1;
+
+	addr += 1;
+	if (ldb_asm(addr, &byte1))
+		return 1;
+
+	addr += 1;
+	if (ldb_asm(addr, &byte2))
+		return 1;
+
+	addr += 1;
+	if (ldb_asm(addr, &byte3))
+		return 1;
+
+	byte0 |= byte1 << 8;
+	byte0 |= byte2 << 16;
+	byte0 |= byte3 << 24;
+
+	put_ptreg(regs, rz, byte0);
+
+	return 0;
+}
+
+/*
+ * Store word to [rx + imm]
+ *
+ * Success: return 0
+ * Failure: return 1
+ */
+static int stw_c(struct pt_regs *regs, uint32_t rz, uint32_t addr)
+{
+	uint32_t byte0, byte1, byte2, byte3;
+
+	byte0 = byte1 = byte2 = byte3 = get_ptreg(regs, rz);
+
+	byte0 &= 0xff;
+
+	if (stb_asm(addr, byte0))
+		return 1;
+
+	addr += 1;
+	byte1 = (byte1 >> 8) & 0xff;
+	if (stb_asm(addr, byte1))
+		return 1;
+
+	addr += 1;
+	byte2 = (byte2 >> 16) & 0xff;
+	if (stb_asm(addr, byte2))
+		return 1;
+
+	addr += 1;
+	byte3 = (byte3 >> 24) & 0xff;
+	if (stb_asm(addr, byte3))
+		return 1;
+
+	align_count++;
+
+	return 0;
+}
+
+extern int fixup_exception(struct pt_regs *regs);
+
+#define OP_LDH 0xc000
+#define OP_STH 0xd000
+#define OP_LDW 0x8000
+#define OP_STW 0x9000
+
+void csky_alignment(struct pt_regs *regs)
+{
+	int ret;
+	uint16_t tmp;
+	uint32_t opcode = 0;
+	uint32_t rx     = 0;
+	uint32_t rz     = 0;
+	uint32_t imm    = 0;
+	uint32_t addr   = 0;
+
+	siginfo_t info;
+
+	if (!user_mode(regs))
+		goto bad_area;
+
+	ret = get_user(tmp, (uint16_t *)instruction_pointer(regs));
+	if (ret) {
+		pr_err("%s get_user failed.\n", __func__);
+		goto bad_area;
+	}
+
+	opcode = (uint32_t)tmp;
+
+	rx  = opcode & 0xf;
+	imm = (opcode >> 4) & 0xf;
+	rz  = (opcode >> 8) & 0xf;
+	opcode &= 0xf000;
+
+	if (rx == 0 || rx == 15 || rz == 0 || rz == 15)
+		goto bad_area;
+
+	switch(opcode) {
+	case OP_LDH:
+		addr = get_ptreg(regs, rx) + (imm << 1);
+		ret = ldh_c(regs, rz, addr);
+		break;
+	case OP_LDW:
+		addr = get_ptreg(regs, rx) + (imm << 2);
+		ret = ldw_c(regs, rz, addr);
+		break;
+	case OP_STH:
+		addr = get_ptreg(regs, rx) + (imm << 1);
+		ret = sth_c(regs, rz, addr);
+		break;
+	case OP_STW:
+		addr = get_ptreg(regs, rx) + (imm << 2);
+		ret = stw_c(regs, rz, addr);
+		break;
+	}
+
+	if(ret)
+		goto bad_area;
+
+	regs->pc += 2;
+
+	return;
+
+bad_area:
+	if (!user_mode(regs)) {
+		if (fixup_exception(regs))
+			return;
+
+		bust_spinlocks(1);
+		pr_alert("%s opcode: %x, rz: %d, rx: %d, imm: %d, addr: %x.\n",
+		          __func__, opcode, rz, rx, imm, addr);
+		show_regs(regs);
+		bust_spinlocks(0);
+		do_exit(SIGKILL);
+	}
+
+	info.si_signo = SIGBUS;
+	info.si_errno = 0;
+	info.si_code  = BUS_ADRALN;
+	info.si_addr  = (void __user *)addr;
+
+	force_sig_info(info.si_signo, &info, current);
+
+	return;
+}
+
+static struct ctl_table alignment_tbl[4] = {
+	{
+		.procname = "enable",
+		.data = &align_enable,
+		.maxlen = sizeof(align_enable),
+		.mode = 0666,
+		.proc_handler = &proc_dointvec
+	},
+	{
+		.procname = "count",
+		.data = &align_count,
+		.maxlen = sizeof(align_count),
+		.mode = 0666,
+		.proc_handler = &proc_dointvec
+	},
+	{}
+};
+
+static struct ctl_table sysctl_table[2] = {
+	{
+	 .procname = "csky_alignment",
+	 .mode = 0555,
+	 .child = alignment_tbl},
+	{}
+};
+
+static struct ctl_path sysctl_path[2] = {
+	{.procname = "csky"},
+	{}
+};
+
+static int __init csky_alignment_init(void)
+{
+	register_sysctl_paths(sysctl_path, sysctl_table);
+	return 0;
+}
+
+arch_initcall(csky_alignment_init);
+
diff --git a/arch/csky/abiv1/inc/abi/entry.h b/arch/csky/abiv1/inc/abi/entry.h
new file mode 100644
index 0000000..b4b5062
--- /dev/null
+++ b/arch/csky/abiv1/inc/abi/entry.h
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_ENTRY_H
+#define __ASM_CSKY_ENTRY_H
+
+#include <asm/setup.h>
+#include <abi/regdef.h>
+
+#define LSAVE_PC	8
+#define LSAVE_PSR	12
+#define LSAVE_A0	24
+#define LSAVE_A1	28
+#define LSAVE_A2	32
+#define LSAVE_A3	36
+#define LSAVE_A4	40
+#define LSAVE_A5	44
+
+#define EPC_INCREASE	2
+#define EPC_KEEP	0
+
+.macro USPTOKSP
+	mtcr	sp, ss1
+	mfcr	sp, ss0
+.endm
+
+.macro KSPTOUSP
+	mtcr	sp, ss0
+	mfcr	sp, ss1
+.endm
+
+.macro INCTRAP	rx
+	addi	\rx, EPC_INCREASE
+.endm
+
+.macro	SAVE_ALL epc_inc
+	mtcr    r13, ss2
+	mfcr    r13, epsr
+	btsti   r13, 31
+	bt      1f
+	USPTOKSP
+1:
+	subi    sp, 32
+	subi    sp, 32
+	subi    sp, 16
+	stw     r13, (sp, 12)
+
+	stw     lr, (sp, 4)
+
+	mfcr	lr, epc
+	movi	r13, \epc_inc
+	add	lr, r13
+	stw     lr, (sp, 8)
+
+	mfcr	lr, ss1
+	stw     lr, (sp, 16)
+
+	stw     a0, (sp, 20)
+	stw     a0, (sp, 24)
+	stw     a1, (sp, 28)
+	stw     a2, (sp, 32)
+	stw     a3, (sp, 36)
+
+	addi	sp, 32
+	addi	sp, 8
+	mfcr    r13, ss2
+	stw	r6, (sp)
+	stw	r7, (sp, 4)
+	stw	r8, (sp, 8)
+	stw	r9, (sp, 12)
+	stw	r10, (sp, 16)
+	stw	r11, (sp, 20)
+	stw	r12, (sp, 24)
+	stw	r13, (sp, 28)
+	stw	r14, (sp, 32)
+	stw	r1, (sp, 36)
+	subi	sp, 32
+	subi	sp, 8
+.endm
+
+.macro	RESTORE_ALL
+	psrclr  ie
+	ldw	lr, (sp, 4)
+	ldw     a0, (sp, 8)
+	mtcr    a0, epc
+	ldw     a0, (sp, 12)
+	mtcr    a0, epsr
+	btsti   a0, 31
+	ldw     a0, (sp, 16)
+	mtcr	a0, ss1
+
+	ldw     a0, (sp, 24)
+	ldw     a1, (sp, 28)
+	ldw     a2, (sp, 32)
+	ldw     a3, (sp, 36)
+
+	addi	sp, 32
+	addi	sp, 8
+	ldw	r6, (sp)
+	ldw	r7, (sp, 4)
+	ldw	r8, (sp, 8)
+	ldw	r9, (sp, 12)
+	ldw	r10, (sp, 16)
+	ldw	r11, (sp, 20)
+	ldw	r12, (sp, 24)
+	ldw	r13, (sp, 28)
+	ldw	r14, (sp, 32)
+	ldw	r1, (sp, 36)
+	addi	sp, 32
+	addi	sp, 8
+
+	bt      1f
+	KSPTOUSP
+1:
+	rte
+.endm
+
+.macro SAVE_SWITCH_STACK
+	subi    sp, 32
+	stm     r8-r15,(sp)
+.endm
+
+.macro RESTORE_SWITCH_STACK
+        ldm     r8-r15,(sp)
+        addi    sp, 32
+.endm
+
+/* MMU registers operators. */
+.macro RD_MIR	rx
+	cprcr   \rx, cpcr0
+.endm
+
+.macro RD_MEH	rx
+	cprcr   \rx, cpcr4
+.endm
+
+.macro RD_MCIR	rx
+	cprcr   \rx, cpcr8
+.endm
+
+.macro RD_PGDR  rx
+        cprcr   \rx, cpcr29
+.endm
+
+.macro WR_MEH	rx
+	cpwcr   \rx, cpcr4
+.endm
+
+.macro WR_MCIR	rx
+	cpwcr   \rx, cpcr8
+.endm
+
+#endif /* __ASM_CSKY_ENTRY_H */
diff --git a/arch/csky/abiv2/inc/abi/entry.h b/arch/csky/abiv2/inc/abi/entry.h
new file mode 100644
index 0000000..398d02e
--- /dev/null
+++ b/arch/csky/abiv2/inc/abi/entry.h
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_ENTRY_H
+#define __ASM_CSKY_ENTRY_H
+
+#include <asm/setup.h>
+#include <abi/regdef.h>
+
+#define LSAVE_PC	8
+#define LSAVE_PSR	12
+#define LSAVE_A0	24
+#define LSAVE_A1	28
+#define LSAVE_A2	32
+#define LSAVE_A3	36
+
+#define EPC_INCREASE	4
+#define EPC_KEEP	0
+
+#define KSPTOUSP
+#define USPTOKSP
+
+#define usp cr<14, 1>
+
+.macro INCTRAP	rx
+	addi	\rx, EPC_INCREASE
+.endm
+
+.macro SAVE_ALL epc_inc
+	subi    sp, 152
+	stw	tls, (sp, 0)
+	stw	lr, (sp, 4)
+
+	mfcr	lr, epc
+	movi	tls, \epc_inc
+	add	lr, tls
+	stw	lr, (sp, 8)
+
+	mfcr	lr, epsr
+	stw	lr, (sp, 12)
+	mfcr	lr, usp
+	stw	lr, (sp, 16)
+
+	stw     a0, (sp, 20)
+	stw     a0, (sp, 24)
+	stw     a1, (sp, 28)
+	stw     a2, (sp, 32)
+	stw     a3, (sp, 36)
+
+	addi	sp, 40
+	stm	r4-r13, (sp)
+
+	addi    sp, 40
+	stm     r16-r30,(sp)
+#ifdef CONFIG_CPU_HAS_HILO
+	mfhi	lr
+	stw	lr, (sp, 60)
+	mflo	lr
+	stw	lr, (sp, 64)
+#endif
+	subi	sp, 80
+.endm
+
+.macro	RESTORE_ALL
+	psrclr  ie
+	ldw	tls, (sp, 0)
+	ldw	lr, (sp, 4)
+	ldw	a0, (sp, 8)
+	mtcr	a0, epc
+	ldw	a0, (sp, 12)
+	mtcr	a0, epsr
+	ldw	a0, (sp, 16)
+	mtcr	a0, usp
+
+#ifdef CONFIG_CPU_HAS_HILO
+	ldw	a0, (sp, 140)
+	mthi	a0
+	ldw	a0, (sp, 144)
+	mtlo	a0
+#endif
+
+	ldw     a0, (sp, 24)
+	ldw     a1, (sp, 28)
+	ldw     a2, (sp, 32)
+	ldw     a3, (sp, 36)
+
+	addi	sp, 40
+	ldm	r4-r13, (sp)
+	addi    sp, 40
+	ldm     r16-r30,(sp)
+	addi    sp, 72
+	rte
+.endm
+
+.macro SAVE_SWITCH_STACK
+        subi    sp, 64
+        stm     r4-r11,(sp)
+        stw     r15, (sp, 32)
+        stw     r16, (sp, 36)
+        stw     r17, (sp, 40)
+        stw     r26, (sp, 44)
+        stw     r27, (sp, 48)
+        stw     r28, (sp, 52)
+        stw     r29, (sp, 56)
+        stw     r30, (sp, 60)
+.endm
+
+.macro RESTORE_SWITCH_STACK
+        ldm     r4-r11,(sp)
+        ldw     r15, (sp, 32)
+        ldw     r16, (sp, 36)
+        ldw     r17, (sp, 40)
+        ldw     r26, (sp, 44)
+        ldw     r27, (sp, 48)
+        ldw     r28, (sp, 52)
+        ldw     r29, (sp, 56)
+        ldw     r30, (sp, 60)
+        addi    sp, 64
+.endm
+
+/* MMU registers operators. */
+.macro RD_MIR	rx
+	mfcr    \rx, cr<0, 15>
+.endm
+
+.macro RD_MEH	rx
+	mfcr    \rx, cr<4, 15>
+.endm
+
+.macro RD_MCIR	rx
+	mfcr    \rx, cr<8, 15>
+.endm
+
+.macro RD_PGDR  rx
+	mfcr    \rx, cr<29, 15>
+.endm
+
+.macro RD_PGDR_K  rx
+	mfcr    \rx, cr<28, 15>
+.endm
+
+.macro WR_MEH	rx
+	mtcr    \rx, cr<4, 15>
+.endm
+
+.macro WR_MCIR	rx
+	mtcr    \rx, cr<8, 15>
+.endm
+
+#endif /* __ASM_CSKY_ENTRY_H */
diff --git a/arch/csky/include/asm/traps.h b/arch/csky/include/asm/traps.h
new file mode 100644
index 0000000..ca82b19
--- /dev/null
+++ b/arch/csky/include/asm/traps.h
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_TRAPS_H
+#define __ASM_CSKY_TRAPS_H
+
+#define VEC_RESET	0
+#define VEC_ALIGN	1
+#define VEC_ACCESS	2
+#define VEC_ZERODIV	3
+#define VEC_ILLEGAL	4
+#define VEC_PRIV	5
+#define VEC_TRACE	6
+#define VEC_BREAKPOINT	7
+#define VEC_UNRECOVER	8
+#define VEC_SOFTRESET	9
+#define VEC_AUTOVEC	10
+#define VEC_FAUTOVEC	11
+#define VEC_HWACCEL	12
+
+#define	VEC_TLBMISS	14
+#define	VEC_TLBMODIFIED	15
+
+#define VEC_TRAP0	16
+#define VEC_TRAP1	17
+#define VEC_TRAP2	18
+#define VEC_TRAP3	19
+
+#define	VEC_TLBINVALIDL	20
+#define	VEC_TLBINVALIDS	21
+
+#define VEC_PRFL	29
+#define VEC_FPE		30
+
+extern void * vec_base[];
+#define VEC_INIT(i, func) vec_base[i] = (void *)func
+
+void csky_alignment(struct pt_regs*);
+
+#endif /* __ASM_CSKY_TRAPS_H */
diff --git a/arch/csky/include/asm/unistd.h b/arch/csky/include/asm/unistd.h
new file mode 100644
index 0000000..704526c
--- /dev/null
+++ b/arch/csky/include/asm/unistd.h
@@ -0,0 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <uapi/asm/unistd.h>
+
diff --git a/arch/csky/kernel/cpu-probe.c b/arch/csky/kernel/cpu-probe.c
new file mode 100644
index 0000000..b898ec9
--- /dev/null
+++ b/arch/csky/kernel/cpu-probe.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/of.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <linux/memblock.h>
+
+#include <abi/reg_ops.h>
+
+static __init void setup_cpu_msa(void)
+{
+	if (memblock_start_of_DRAM() != CONFIG_RAM_BASE) {
+		panic("dts-ram-start doesn't equal CONFIG_RAM_BASE in .config: %x-%x.\n",
+			memblock_start_of_DRAM(), CONFIG_RAM_BASE);
+	}
+
+	mtcr_msa0(PHYS_OFFSET | 0xe);
+	mtcr_msa1(PHYS_OFFSET | 0x26);
+}
+
+__init void cpu_dt_probe(void)
+{
+	setup_cpu_msa();
+}
+
+static void percpu_print(void *arg)
+{
+	struct seq_file *m = (struct seq_file *)arg;
+
+	seq_printf(m, "processor       : %d\n", smp_processor_id());
+	seq_printf(m, "C-SKY CPU model : %s\n", CSKYCPU_DEF_NAME);
+
+	/* Read 4 times to get all the cpuid info */
+	seq_printf(m, "product info[0] : 0x%08x\n", mfcr("cr13"));
+	seq_printf(m, "product info[1] : 0x%08x\n", mfcr("cr13"));
+	seq_printf(m, "product info[2] : 0x%08x\n", mfcr("cr13"));
+	seq_printf(m, "product info[3] : 0x%08x\n", mfcr("cr13"));
+
+	seq_printf(m, "mpid reg        : 0x%08x\n", mfcr("cr30"));
+	seq_printf(m, "ccr reg         : 0x%08x\n", mfcr("cr18"));
+	seq_printf(m, "ccr2 reg        : 0x%08x\n", mfcr_ccr2());
+	seq_printf(m, "hint reg        : 0x%08x\n", mfcr_hint());
+	seq_printf(m, "msa0 reg        : 0x%08x\n", mfcr_msa0());
+	seq_printf(m, "msa1 reg        : 0x%08x\n", mfcr_msa1());
+	seq_printf(m, "\n");
+}
+
+static int c_show(struct seq_file *m, void *v)
+{
+	int cpu;
+
+	for_each_online_cpu(cpu)
+		smp_call_function_single(cpu, percpu_print, m, true);
+
+#ifdef CSKY_ARCH_VERSION
+	seq_printf(m, "\n");
+	seq_printf(m, "arch-version : %s\n", CSKY_ARCH_VERSION);
+	seq_printf(m, "\n");
+#endif
+
+	return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	return *pos < 1 ? (void *)1 : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	++*pos;
+	return NULL;
+}
+
+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	= c_show,
+};
+
diff --git a/arch/csky/kernel/entry.S b/arch/csky/kernel/entry.S
new file mode 100644
index 0000000..2e59403
--- /dev/null
+++ b/arch/csky/kernel/entry.S
@@ -0,0 +1,407 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/linkage.h>
+#include <abi/entry.h>
+#include <abi/pgtable-bits.h>
+#include <asm/errno.h>
+#include <asm/setup.h>
+#include <asm/unistd.h>
+#include <asm/asm-offsets.h>
+#include <linux/threads.h>
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <asm/thread_info.h>
+#ifdef CONFIG_CPU_HAS_FPU
+#include <abi/fpu.h>
+#endif
+
+#define PTE_INDX_MSK    0xffc
+#define PTE_INDX_SHIFT  10
+#define _PGDIR_SHIFT    22
+
+.macro tlbop_begin name, val0, val1, val2
+ENTRY(csky_\name)
+	mtcr    a3, ss2
+	mtcr    r6, ss3
+	mtcr    a2, ss4
+
+	RD_PGDR	r6
+	RD_MEH	a3
+#ifdef CONFIG_CPU_HAS_TLBI
+	tlbi.alls
+	sync.is
+
+	btsti	a3, 31
+	bf	1f
+	RD_PGDR_K r6
+1:
+#else
+	bgeni	a2, 31
+	WR_MCIR	a2
+	bgeni	a2, 25
+	WR_MCIR	a2
+#endif
+	bclri   r6, 0
+	lrw	a2, PHYS_OFFSET
+	subu	r6, a2
+	bseti	r6, 31
+
+	mov     a2, a3
+   	lsri    a2, _PGDIR_SHIFT
+	lsli    a2, 2
+	addu    r6, a2
+	ldw     r6, (r6)
+
+	lrw	a2, PHYS_OFFSET
+	subu	r6, a2
+	bseti	r6, 31
+
+	lsri    a3, PTE_INDX_SHIFT
+	lrw     a2, PTE_INDX_MSK
+	and     a3, a2
+	addu    r6, a3
+	ldw     a3, (r6)
+
+	movi	a2, (_PAGE_PRESENT | \val0)
+	and     a3, a2
+	cmpne   a3, a2
+	bt	\name
+
+	/* First read/write the page, just update the flags */
+	ldw     a3, (r6)
+	bgeni   a2, PAGE_VALID_BIT
+	bseti   a2, PAGE_ACCESSED_BIT
+	bseti   a2, \val1
+	bseti   a2, \val2
+	or      a3, a2
+	stw     a3, (r6)
+
+	/* Some cpu tlb-hardrefill bypass the cache */
+#ifdef CONFIG_CPU_NEED_TLBSYNC
+	movi	a2, 0x22
+	bseti	a2, 6
+	mtcr	r6, cr22
+	mtcr	a2, cr17
+	sync
+#endif
+
+	mfcr    a3, ss2
+	mfcr    r6, ss3
+	mfcr    a2, ss4
+	rte
+\name:
+	mfcr    a3, ss2
+	mfcr    r6, ss3
+	mfcr    a2, ss4
+	SAVE_ALL EPC_KEEP
+.endm
+.macro tlbop_end is_write
+	RD_MEH	a2
+	psrset  ee, ie
+	mov     a0, sp
+	movi    a1, \is_write
+	jbsr    do_page_fault
+	movi    r11_sig, 0             /* r11 = 0, Not a syscall. */
+	jmpi    ret_from_exception
+.endm
+
+.text
+
+tlbop_begin tlbinvalidl, _PAGE_READ, PAGE_VALID_BIT, PAGE_ACCESSED_BIT
+tlbop_end 0
+
+tlbop_begin tlbinvalids, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT
+tlbop_end 1
+
+tlbop_begin tlbmodified, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT
+#ifndef CONFIG_CPU_HAS_LDSTEX
+jbsr csky_cmpxchg_fixup
+#endif
+tlbop_end 1
+
+ENTRY(csky_systemcall)
+	SAVE_ALL EPC_INCREASE
+
+	psrset  ee, ie
+
+	/* Stack frame for syscall, origin call set_esp0 */
+	mov     r12, sp
+
+	bmaski  r11, 13
+	andn    r12, r11
+	bgeni   r11, 9
+	addi    r11, 32
+	addu    r12, r11
+	st      sp, (r12, 0)
+
+	lrw     r11, __NR_syscalls
+	cmphs   syscallid, r11                 /* Check nr of syscall */
+	bt      ret_from_exception
+
+	lrw     r13, sys_call_table
+	ixw     r13, syscallid                 /* Index into syscall table */
+	ldw     r11, (r13)               /* Get syscall function */
+	cmpnei  r11, 0                  /* Check for not null */
+	bf      ret_from_exception
+
+	mov     r9, sp				 /* Get task pointer */
+	bmaski  r10, THREAD_SHIFT
+	andn    r9, r10                      /* Get thread_info */
+	ldw     r8, (r9, TINFO_FLAGS)       /* Get thread_info.flags value */
+	btsti   r8, TIF_SYSCALL_TRACE       /* Check if TIF_SYSCALL_TRACE set */
+	bt      1f
+#if defined(__CSKYABIV2__)
+	subi    sp, 8
+	stw  	r5, (sp, 0x4)
+	stw  	r4, (sp, 0x0)
+	jsr     r11                      /* Do system call */
+	addi 	sp, 8
+#else
+	jsr     r11
+#endif
+	stw     a0, (sp, LSAVE_A0)      /* Save return value */
+	jmpi    ret_from_exception
+
+1:
+	movi    a0, 0                   /* enter system call */
+	mov     a1, sp                  /* right now, sp --> pt_regs */
+	jbsr    syscall_trace
+	/* Prepare args before do system call */
+	ldw     a0, (sp, LSAVE_A0)
+	ldw     a1, (sp, LSAVE_A1)
+	ldw     a2, (sp, LSAVE_A2)
+	ldw     a3, (sp, LSAVE_A3)
+#if defined(__CSKYABIV2__)
+	subi    sp, 8
+	stw     r5, (sp, 0x4)
+	stw     r4, (sp, 0x0)
+#else
+	ldw     r6, (sp, LSAVE_A4)
+	ldw     r7, (sp, LSAVE_A5)
+#endif
+	jsr     r11                     /* Do system call */
+#if defined(__CSKYABIV2__)
+	addi    sp, 8
+#endif
+	stw     a0, (sp, LSAVE_A0)     /* Save return value */
+
+	movi    a0, 1                   /* leave system call */
+	mov     a1, sp                  /* right now, sp --> pt_regs */
+	jbsr    syscall_trace
+
+syscall_exit_work:
+	ld       syscallid, (sp, LSAVE_PSR)
+	btsti    syscallid, 31
+	bt       2f
+
+	jmpi     resume_userspace
+
+2:      RESTORE_ALL
+
+ENTRY(ret_from_kernel_thread)
+	jbsr     schedule_tail
+	mov	 a0, r8
+	jsr	 r9
+	jbsr     ret_from_exception
+
+ENTRY(ret_from_fork)
+	jbsr     schedule_tail
+	mov      r9, sp				 /* Get task pointer */
+	bmaski   r10, THREAD_SHIFT
+	andn     r9, r10                     /* Get thread_info */
+	ldw      r8, (r9, TINFO_FLAGS)       /* Get thread_info.flags value */
+	movi     r11_sig, 1                  /* is a syscall */
+	btsti    r8, TIF_SYSCALL_TRACE       /* Check if TIF_SYSCALL_TRACE set */
+	bf       3f
+	movi     a0, 1                       /* leave system call */
+	mov      a1, sp                      /* right now, sp --> pt_regs */
+	jbsr     syscall_trace
+3:
+	jbsr     ret_from_exception
+
+ret_from_exception:
+	ld       syscallid, (sp, LSAVE_PSR)
+	btsti    syscallid, 31
+	bt       1f
+	/*
+	 * Load address of current->thread_info, Then get address of task_struct
+	 * Get task_needreshed in task_struct
+	 */
+	mov     r9, sp     					 /* Get current stack  pointer */
+	bmaski  r10, THREAD_SHIFT
+	andn    r9, r10                      /* Get task_struct */
+
+resume_userspace:
+	ldw      r8, (r9, TINFO_FLAGS)
+	andi     r8, (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED)
+	cmpnei   r8, 0
+	bt       exit_work
+1:  RESTORE_ALL
+
+exit_work:
+	mov      a0, sp                 /* Stack address is arg[0] */
+	jbsr     set_esp0               /* Call C level */
+	btsti    r8, TIF_NEED_RESCHED
+	bt       work_resched
+	cmpnei   r8, 0		/* If thread_info->flag is empty, RESTORE_ALL. */
+	bf       1b
+	mov      a1, sp
+	mov      a0, r8
+	mov      a2, r11_sig        /* syscall? */
+	btsti    r8, TIF_SIGPENDING /* delivering a signal? */
+	clrt     r11_sig            /* prevent further restarts(set r11 = 0) */
+	jbsr     do_notify_resume	/* do signals */
+	br       resume_userspace
+
+work_resched:
+	lrw      syscallid, ret_from_exception
+	mov      r15, syscallid                /* Return address in link */
+	jmpi     schedule
+
+ENTRY(sys_rt_sigreturn)
+	movi	r11_sig, 0
+	jmpi	do_rt_sigreturn
+
+/*
+ * Common trap handler. Standard traps come through here first
+ */
+
+ENTRY(csky_trap)
+	SAVE_ALL EPC_KEEP
+	psrset   ee
+	movi     r11_sig, 0             /* r11 = 0, Not a syscall. */
+	mov      a0, sp                 /* Push Stack pointer arg */
+	jbsr     trap_c                 /* Call C-level trap handler */
+	jmpi     ret_from_exception
+
+/*
+ * Prototype from libc:
+ * register unsigned int __result asm("a0");
+ * asm( "trap 3" :"=r"(__result)::);
+ */
+ENTRY(csky_get_tls)
+	USPTOKSP
+
+	/* increase epc for continue */
+	mfcr	a0, epc
+	INCTRAP	a0
+	mtcr	a0, epc
+
+	/* get current task thread_info with kernel 8K stack */
+	bmaski   a0, THREAD_SHIFT
+	not      a0
+	subi     sp, 1
+	and      a0, sp
+	addi     sp, 1
+
+	/* get tls */
+	ldw      a0, (a0, TINFO_TP_VALUE)
+
+	KSPTOUSP
+	rte
+
+ENTRY(csky_irq)
+	SAVE_ALL EPC_KEEP
+	psrset  ee       // enable exception
+	movi    r11_sig, 0                   /* r11 = 0, Not a syscall. */
+
+#ifdef CONFIG_PREEMPT
+	mov     r9, sp                       /* Get current stack  pointer */
+	bmaski  r10, THREAD_SHIFT
+	andn    r9, r10                      /* Get thread_info */
+
+	/*
+	 * Get task_struct->stack.preempt_count for current,
+	 * and increase 1.
+	 */
+	ldw      r8, (r9, TINFO_PREEMPT)
+	addi     r8, 1
+	stw      r8, (r9, TINFO_PREEMPT)
+#endif
+
+	mov      a0, sp
+	jbsr     csky_do_IRQ
+
+#ifdef CONFIG_PREEMPT
+	subi     r8, 1
+	stw      r8, (r9, TINFO_PREEMPT)
+	cmpnei   r8, 0
+	bt       2f
+	ldw      r8, (r9, TINFO_FLAGS)
+	btsti    r8, TIF_NEED_RESCHED
+	bf       2f
+1:
+	jbsr     preempt_schedule_irq   /* irq en/disable is done inside */
+	ldw      r7, (r9, TINFO_FLAGS)  /* get new tasks TI_FLAGS */
+	btsti    r7, TIF_NEED_RESCHED
+	bt       1b                     /* go again */
+#endif
+2:
+	jmpi     ret_from_exception
+
+/*
+ * a0 =  prev task_struct *
+ * a1 =  next task_struct *
+ * a0 =  return next
+ */
+ENTRY(__switch_to)
+	lrw      a3, TASK_THREAD        /* struct_thread offset in task_struct */
+	addu     a3, a0                 /* a3 point to thread in prev task_struct */
+
+	mfcr     a2, psr                /* Save PSR value */
+	stw      a2, (a3, THREAD_SR)    /* Save PSR in task struct */
+	bclri    a2, 6                  /* Disable interrupts */
+	mtcr     a2, psr
+
+	SAVE_SWITCH_STACK
+
+	stw      sp, (a3, THREAD_KSP)   /* Save ksp in task struct */
+
+#ifdef CONFIG_CPU_HAS_FPU
+	FPU_SAVE_REGS
+#endif
+
+#ifdef CONFIG_CPU_HAS_HILO
+	lrw      r10, THREAD_DSPHI
+	add      r10, a3
+	mfhi     r6
+	mflo     r7
+	stw      r6, (r10, 0)           /* THREAD_DSPHI */
+	stw      r7, (r10, 4)           /* THREAD_DSPLO */
+	mfcr     r6, cr14
+	stw      r6, (r10, 8)           /* THREAD_DSPCSR */
+#endif
+
+	/* Set up next process to run */
+	lrw      a3, TASK_THREAD	/* struct_thread offset in task_struct */
+	addu     a3, a1			/* a3 point to thread in next task_struct */
+
+	ldw      sp, (a3, THREAD_KSP)	/* Set next ksp */
+
+#ifdef CONFIG_CPU_HAS_FPU
+	FPU_RESTORE_REGS
+#endif
+
+#ifdef CONFIG_CPU_HAS_HILO
+	lrw      r10, THREAD_DSPHI
+	add      r10, a3
+	ldw      r6, (r10, 8)   /* THREAD_DSPCSR */
+	mtcr     r6, cr14
+	ldw      r6, (r10, 0)    /* THREAD_DSPHI */
+	ldw      r7, (r10, 4)    /* THREAD_DSPLO */
+	mthi     r6
+	mtlo     r7
+#endif
+
+	ldw      a2, (a3, THREAD_SR)    /* Set next PSR */
+	mtcr     a2, psr
+
+#if  defined(__CSKYABIV2__)
+	addi     r7, a1, TASK_THREAD_INFO
+	ldw      tls, (r7, TINFO_TP_VALUE)
+#endif
+
+	RESTORE_SWITCH_STACK
+
+	rts
+ENDPROC(__switch_to)
diff --git a/arch/csky/kernel/traps.c b/arch/csky/kernel/traps.c
new file mode 100644
index 0000000..0dbc6ce
--- /dev/null
+++ b/arch/csky/kernel/traps.c
@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/user.h>
+#include <linux/string.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/kallsyms.h>
+#include <linux/rtc.h>
+#include <linux/uaccess.h>
+
+#include <asm/setup.h>
+#include <asm/traps.h>
+#include <asm/pgalloc.h>
+#include <asm/siginfo.h>
+
+#include <asm/mmu_context.h>
+
+#ifdef CONFIG_CPU_HAS_FPU
+#include <abi/fpu.h>
+#endif
+
+/* Defined in entry.S */
+asmlinkage void csky_trap(void);
+
+asmlinkage void csky_systemcall(void);
+asmlinkage void csky_cmpxchg(void);
+asmlinkage void csky_get_tls(void);
+asmlinkage void csky_irq(void);
+
+asmlinkage void csky_tlbinvalidl(void);
+asmlinkage void csky_tlbinvalids(void);
+asmlinkage void csky_tlbmodified(void);
+
+/* Defined in head.S */
+asmlinkage void _start_smp_secondary(void);
+
+void __init pre_trap_init(void)
+{
+	int i;
+
+	mtcr("vbr", vec_base);
+
+	for(i=1;i<128;i++) VEC_INIT(i, csky_trap);
+}
+
+void __init trap_init (void)
+{
+#ifdef CONFIG_CSKY_VECIRQ_LEGENCY
+	int i;
+
+	/* setup irq */
+	for(i=32;i<128;i++)
+		  VEC_INIT(i, csky_irq);
+#endif
+
+	VEC_INIT(VEC_AUTOVEC, csky_irq);
+
+	/* setup trap0 trap2 trap3 */
+	VEC_INIT(VEC_TRAP0, csky_systemcall);
+	VEC_INIT(VEC_TRAP2, csky_cmpxchg);
+	VEC_INIT(VEC_TRAP3, csky_get_tls);
+
+	/* setup MMU TLB exception */
+	VEC_INIT(VEC_TLBINVALIDL, csky_tlbinvalidl);
+	VEC_INIT(VEC_TLBINVALIDS, csky_tlbinvalids);
+	VEC_INIT(VEC_TLBMODIFIED, csky_tlbmodified);
+
+
+#ifdef CONFIG_CPU_HAS_FPU
+	init_fpu();
+#endif
+
+#ifdef CONFIG_SMP
+	mtcr("cr<28, 0>", virt_to_phys(vec_base));
+
+	VEC_INIT(VEC_RESET, (void *)virt_to_phys(_start_smp_secondary));
+#endif
+}
+
+void die_if_kernel (char *str, struct pt_regs *regs, int nr)
+{
+	if (user_mode(regs)) return;
+
+	console_verbose();
+	pr_err("%s: %08x\n",str,nr);
+        show_regs(regs);
+        add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
+	do_exit(SIGSEGV);
+}
+
+void buserr(struct pt_regs *regs)
+{
+	siginfo_t info;
+
+	die_if_kernel("Kernel mode BUS error", regs, 0);
+
+	pr_err("User mode Bus Error\n");
+	show_regs(regs);
+
+	current->thread.esp0 = (unsigned long) regs;
+	info.si_signo = SIGSEGV;
+	info.si_errno = 0;
+	force_sig_info(SIGSEGV, &info, current);
+}
+
+asmlinkage void trap_c(struct pt_regs *regs)
+{
+	int sig;
+	unsigned long vector;
+	siginfo_t info;
+
+	vector = (mfcr("psr") >> 16) & 0xff;
+
+	switch (vector) {
+		case VEC_ZERODIV:
+			sig = SIGFPE;
+			break;
+		/* ptrace */
+		case VEC_TRACE:
+			info.si_code = TRAP_TRACE;
+			sig = SIGTRAP;
+			break;
+		case VEC_ILLEGAL:
+#ifndef CONFIG_CPU_NO_USER_BKPT
+		if (*(uint16_t *)instruction_pointer(regs) != 0x1464)
+#endif
+		{
+			sig = SIGILL;
+			break;
+		}
+		/* gdbserver  breakpoint */
+		case VEC_TRAP1:
+		/* jtagserver breakpoint */
+		case VEC_BREAKPOINT:
+			info.si_code = TRAP_BRKPT;
+			sig = SIGTRAP;
+			break;
+		case VEC_ACCESS:
+			return buserr(regs);
+#ifdef CONFIG_CPU_NEED_SOFTALIGN
+		case VEC_ALIGN:
+			return csky_alignment(regs);
+#endif
+#ifdef CONFIG_CPU_HAS_FPU
+		case VEC_FPE:
+			return fpu_fpe(regs);
+		case VEC_PRIV:
+			if(fpu_libc_helper(regs)) return;
+#endif
+		default:
+			sig = SIGSEGV;
+			break;
+	}
+	send_sig(sig, current, 0);
+}
+
+asmlinkage void set_esp0 (unsigned long ssp)
+{
+	current->thread.esp0 = ssp;
+}
+
diff --git a/arch/csky/mm/fault.c b/arch/csky/mm/fault.c
new file mode 100644
index 0000000..3ff4491
--- /dev/null
+++ b/arch/csky/mm/fault.c
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/signal.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/version.h>
+#include <linux/vt_kern.h>
+#include <linux/kernel.h>
+#include <linux/extable.h>
+#include <linux/uaccess.h>
+
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/traps.h>
+#include <asm/page.h>
+
+extern void die_if_kernel(char *, struct pt_regs *, long);
+
+int fixup_exception(struct pt_regs *regs)
+{
+        const struct exception_table_entry *fixup;
+
+        fixup = search_exception_tables(instruction_pointer(regs));
+        if (fixup) {
+                regs->pc = fixup->nextinsn;
+
+                return 1;
+        }
+
+        return 0;
+}
+
+/*
+ * This routine handles page faults.  It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ */
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
+                              unsigned long mmu_meh)
+{
+        struct vm_area_struct * vma = NULL;
+        struct task_struct *tsk = current;
+        struct mm_struct *mm = tsk->mm;
+        siginfo_t info;
+	int fault;
+	unsigned long address = mmu_meh & PAGE_MASK;
+
+        info.si_code = SEGV_MAPERR;
+
+#ifndef CONFIG_CPU_HAS_TLBI
+        /*
+         * We fault-in kernel-space virtual memory on-demand. The
+         * 'reference' page table is init_mm.pgd.
+         *
+         * NOTE! We MUST NOT take any locks for this case. We may
+         * be in an interrupt or a critical region, and should
+         * only copy the information from the master page table,
+         * nothing more.
+         */
+        if (unlikely(address >= VMALLOC_START && address <= VMALLOC_END))
+        {
+                /*
+                 * Synchronize this task's top level page-table
+                 * with the 'reference' page table.
+                 *
+                 * Do _not_ use "tsk" here. We might be inside
+                 * an interrupt in the middle of a task switch..
+                 */
+                int offset = __pgd_offset(address);
+                pgd_t *pgd, *pgd_k;
+                pud_t *pud, *pud_k;
+                pmd_t *pmd, *pmd_k;
+                pte_t *pte_k;
+
+                unsigned long pgd_base;
+		pgd_base = tlb_get_pgd();
+                pgd = (pgd_t *)pgd_base + offset;
+                pgd_k = init_mm.pgd + offset;
+
+                if (!pgd_present(*pgd_k))
+                        goto no_context;
+                set_pgd(pgd, *pgd_k);
+
+                pud = (pud_t *)pgd;
+                pud_k = (pud_t *)pgd_k;
+                if (!pud_present(*pud_k))
+                        goto no_context;
+
+                pmd = pmd_offset(pud, address);
+                pmd_k = pmd_offset(pud_k, address);
+                if (!pmd_present(*pmd_k))
+                        goto no_context;
+                set_pmd(pmd, *pmd_k);
+
+                pte_k = pte_offset_kernel(pmd_k, address);
+                if (!pte_present(*pte_k))
+                        goto no_context;
+                return;
+        }
+#endif
+        /*
+         * If we're in an interrupt or have no user
+         * context, we must not take the fault..
+         */
+        if (in_atomic() || !mm)
+                goto bad_area_nosemaphore;
+
+        down_read(&mm->mmap_sem);
+        vma = find_vma(mm, address);
+        if (!vma)
+                goto bad_area;
+        if (vma->vm_start <= address)
+                goto good_area;
+        if (!(vma->vm_flags & VM_GROWSDOWN))
+                goto bad_area;
+        if (expand_stack(vma, address))
+                goto bad_area;
+/*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
+good_area:
+info.si_code = SEGV_ACCERR;
+
+        if (write) {
+                if (!(vma->vm_flags & VM_WRITE))
+                        goto bad_area;
+        } else {
+                if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)))
+                        goto bad_area;
+        }
+
+        /*
+         * If for any reason at all we couldn't handle the fault,
+         * make sure we exit gracefully rather than endlessly redo
+         * the fault.
+         */
+        fault = handle_mm_fault(vma, address, write ? FAULT_FLAG_WRITE : 0);
+        if (unlikely(fault & VM_FAULT_ERROR)) {
+                if (fault & VM_FAULT_OOM)
+                        goto out_of_memory;
+                else if (fault & VM_FAULT_SIGBUS)
+                        goto do_sigbus;
+                else if (fault & VM_FAULT_SIGSEGV)
+                        goto bad_area;
+                BUG();
+        }
+        if (fault & VM_FAULT_MAJOR)
+                tsk->maj_flt++;
+        else
+                tsk->min_flt++;
+
+        up_read(&mm->mmap_sem);
+        return;
+
+/*
+ * Something tried to access memory that isn't in our memory map..
+ * Fix it, but check if it's kernel or user first..
+ */
+bad_area:
+        up_read(&mm->mmap_sem);
+
+bad_area_nosemaphore:
+        /* User mode accesses just cause a SIGSEGV */
+        if (user_mode(regs)) {
+                tsk->thread.address = address;
+                tsk->thread.error_code = write;
+                info.si_signo = SIGSEGV;
+                info.si_errno = 0;
+                /* info.si_code has been set above */
+                info.si_addr = (void __user *) address;
+                force_sig_info(SIGSEGV, &info, tsk);
+                return;
+        }
+
+no_context:
+	/* Are we prepared to handle this kernel fault? */
+        if (fixup_exception(regs)) return;
+
+	/*
+         * Oops. The kernel tried to access some bad page. We'll have to
+         * terminate things with extreme prejudice.
+         */
+        bust_spinlocks(1);
+        pr_alert("Unable to handle kernel paging request at virtual "
+               "address %08lx, epc == %08lx\n",
+               address, regs->pc);
+	die_if_kernel("Oops", regs, write);
+
+out_of_memory:
+        /*
+         * We ran out of memory, call the OOM killer, and return the userspace
+         * (which will retry the fault, or kill us if we got oom-killed).
+         */
+        pagefault_out_of_memory();
+        return;
+
+do_sigbus:
+        up_read(&mm->mmap_sem);
+
+        /* Kernel mode? Handle exceptions or die */
+        if (!user_mode(regs))
+                goto no_context;
+
+        tsk->thread.address = address;
+        info.si_signo = SIGBUS;
+        info.si_errno = 0;
+        info.si_code = BUS_ADRERR;
+        info.si_addr = (void __user *) address;
+        force_sig_info(SIGBUS, &info, tsk);
+
+        return;
+}
+
-- 
2.7.4


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

* [PATCH V2 05/19] csky: System Call
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (3 preceding siblings ...)
  2018-07-01 17:30 ` [PATCH V2 04/19] csky: Exception handling Guo Ren
@ 2018-07-01 17:30 ` Guo Ren
  2018-07-03 19:53   ` Arnd Bergmann
  2018-07-01 17:30 ` [PATCH V2 06/19] csky: Cache and TLB routines Guo Ren
                   ` (14 subsequent siblings)
  19 siblings, 1 reply; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/include/asm/syscall.h     | 69 +++++++++++++++++++++++++++++++++++++
 arch/csky/include/asm/syscalls.h    | 14 ++++++++
 arch/csky/include/uapi/asm/unistd.h | 63 +++++++++++++++++++++++++++++++++
 arch/csky/kernel/syscall.c          | 63 +++++++++++++++++++++++++++++++++
 arch/csky/kernel/syscall_table.c    | 12 +++++++
 5 files changed, 221 insertions(+)
 create mode 100644 arch/csky/include/asm/syscall.h
 create mode 100644 arch/csky/include/asm/syscalls.h
 create mode 100644 arch/csky/include/uapi/asm/unistd.h
 create mode 100644 arch/csky/kernel/syscall.c
 create mode 100644 arch/csky/kernel/syscall_table.c

diff --git a/arch/csky/include/asm/syscall.h b/arch/csky/include/asm/syscall.h
new file mode 100644
index 0000000..8966739
--- /dev/null
+++ b/arch/csky/include/asm/syscall.h
@@ -0,0 +1,69 @@
+#ifndef __ASM_SYSCALL_H
+#define __ASM_SYSCALL_H
+
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <abi/regdef.h>
+
+static inline int
+syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
+{
+	return regs_syscallid(regs);
+}
+
+static inline void
+syscall_rollback(struct task_struct *task, struct pt_regs *regs)
+{
+	regs->a0 = regs->orig_a0;
+}
+
+static inline long
+syscall_get_error(struct task_struct *task, struct pt_regs *regs)
+{
+	unsigned long error = regs->a0;
+
+	return IS_ERR_VALUE(error) ? error : 0;
+}
+
+static inline long
+syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
+{
+	return regs->a0;
+}
+
+static inline void
+syscall_set_return_value(struct task_struct *task, struct pt_regs *regs,
+			 int error, long val)
+{
+	regs->a0 = (long) error ?: val;
+}
+
+static inline void
+syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
+		      unsigned int i, unsigned int n, unsigned long *args)
+{
+	BUG_ON(i + n > 6);
+	if (i == 0) {
+		args[0] = regs->orig_a0;
+		args++;
+		i++;
+		n--;
+	}
+	memcpy(args, &regs->a1 + i * sizeof(regs->a1), n * sizeof(args[0]));
+}
+
+static inline void
+syscall_set_arguments(struct task_struct *task, struct pt_regs *regs,
+		      unsigned int i, unsigned int n, const unsigned long *args)
+{
+	BUG_ON(i + n > 6);
+        if (i == 0) {
+		regs->orig_a0 = args[0];
+		args++;
+		i++;
+		n--;
+        }
+	memcpy(&regs->a1 + i * sizeof(regs->a1), args, n * sizeof(regs->a0));
+}
+
+#endif	/* __ASM_SYSCALL_H */
diff --git a/arch/csky/include/asm/syscalls.h b/arch/csky/include/asm/syscalls.h
new file mode 100644
index 0000000..c478830
--- /dev/null
+++ b/arch/csky/include/asm/syscalls.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_SYSCALLS_H
+#define __ASM_CSKY_SYSCALLS_H
+
+#include <asm-generic/syscalls.h>
+
+long sys_cacheflush(void __user *, unsigned long, int);
+
+long sys_set_thread_area(unsigned long addr);
+
+long sys_csky_fadvise64_64(int fd, int advice, loff_t offset, loff_t len);
+
+#endif /* __ASM_CSKY_SYSCALLS_H */
diff --git a/arch/csky/include/uapi/asm/unistd.h b/arch/csky/include/uapi/asm/unistd.h
new file mode 100644
index 0000000..0ea9b5a
--- /dev/null
+++ b/arch/csky/include/uapi/asm/unistd.h
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#define __ARCH_WANT_OLD_READDIR
+#define __ARCH_WANT_RENAMEAT
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_SYS_ALARM
+#define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_FORK
+#define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_GETPGRP
+#define __ARCH_WANT_SYS_IPC
+#define __ARCH_WANT_SYS_LLSEEK
+#define __ARCH_WANT_SYS_NICE
+#define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLDUMOUNT
+#define __ARCH_WANT_SYS_PAUSE
+#define __ARCH_WANT_SYS_SIGNAL
+#define __ARCH_WANT_SYS_SIGPENDING
+#define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_SOCKETCALL
+#define __ARCH_WANT_SYS_TIME
+#define __ARCH_WANT_SYS_UTIME
+#define __ARCH_WANT_SYS_VFORK
+#define __ARCH_WANT_SYS_WAITPID
+
+#include <asm-generic/unistd.h>
+
+/*
+ * other define
+ */
+#define __NR_set_thread_area	(__NR_arch_specific_syscall + 0)
+__SYSCALL(__NR_set_thread_area, sys_set_thread_area)
+#define __NR_ipc		(__NR_arch_specific_syscall + 1)
+__SYSCALL(__NR_ipc, sys_ipc)
+#define __NR_socketcall		(__NR_arch_specific_syscall + 2)
+__SYSCALL(__NR_socketcall, sys_socketcall)
+#define __NR_ugetrlimit		(__NR_arch_specific_syscall + 3)
+__SYSCALL(__NR_ugetrlimit, sys_getrlimit)
+#define __NR_cacheflush		(__NR_arch_specific_syscall + 4)
+__SYSCALL(__NR_cacheflush, sys_cacheflush)
+#define __NR_sysfs		(__NR_arch_specific_syscall + 5)
+__SYSCALL(__NR_sysfs, sys_sysfs)
+
+__SYSCALL(__NR_fadvise64_64, sys_csky_fadvise64_64)
+
+#define __NR_setgroups32	__NR_setgroups
+#define __NR_getgid32		__NR_getgid
+#define __NR_getgroups32	__NR_getgroups
+#define __NR_setuid32		__NR_setuid
+#define __NR_setgid32		__NR_setgid
+#define __NR_getresgid32	__NR_getresgid
+#define __NR_setfsuid32		__NR_setfsuid
+#define __NR_setfsgid32		__NR_setfsgid
+#define __NR_fchown32		__NR_fchown
+#define __NR_geteuid32		__NR_geteuid
+#define __NR_getegid32		__NR_getegid
+#define __NR_getresuid32	__NR_getresuid
+#define __NR_setresuid32	__NR_setresuid
+#define __NR_setresgid32	__NR_setresgid
+#define __NR_setreuid32		__NR_setreuid
+#define __NR_setregid32		__NR_setregid
+#define __NR__llseek		__NR_llseek
+
diff --git a/arch/csky/kernel/syscall.c b/arch/csky/kernel/syscall.c
new file mode 100644
index 0000000..f0a1294
--- /dev/null
+++ b/arch/csky/kernel/syscall.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/syscalls.h>
+
+SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
+{
+	struct thread_info *ti = task_thread_info(current);
+	struct pt_regs *reg = current_pt_regs();
+
+	reg->tls = addr;
+	ti->tp_value = addr;
+
+	return 0;
+}
+
+SYSCALL_DEFINE6(mmap2,
+	unsigned long, addr,
+	unsigned long, len,
+	unsigned long, prot,
+	unsigned long, flags,
+	unsigned long, fd,
+	off_t, offset)
+{
+	if (unlikely(offset & (~PAGE_MASK >> 12)))
+		return -EINVAL;
+	return sys_mmap_pgoff(addr, len, prot, flags, fd,
+		offset >> (PAGE_SHIFT - 12));
+}
+
+struct mmap_arg_struct {
+	unsigned long addr;
+	unsigned long len;
+	unsigned long prot;
+	unsigned long flags;
+	unsigned long fd;
+	unsigned long offset;
+};
+
+SYSCALL_DEFINE1(mmap,
+	struct mmap_arg_struct *, arg)
+{
+	struct mmap_arg_struct a;
+
+	if (copy_from_user(&a, arg, sizeof(a)))
+		return -EINVAL;
+
+	if (unlikely(a.offset & ~PAGE_MASK))
+		return -EINVAL;
+
+	return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
+}
+
+/*
+ * for abiv1 the 64bits args should be even th, So we need mov the advice forward.
+ */
+SYSCALL_DEFINE4(csky_fadvise64_64,
+	int, fd,
+	int, advice,
+	loff_t, offset,
+	loff_t, len)
+{
+	return sys_fadvise64_64(fd, offset, len, advice);
+}
diff --git a/arch/csky/kernel/syscall_table.c b/arch/csky/kernel/syscall_table.c
new file mode 100644
index 0000000..bea8558
--- /dev/null
+++ b/arch/csky/kernel/syscall_table.c
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/syscalls.h>
+#include <asm/syscalls.h>
+
+#undef __SYSCALL
+#define __SYSCALL(nr, call) [nr] = (call),
+
+void * const sys_call_table[__NR_syscalls] __page_aligned_data = {
+	[0 ... __NR_syscalls - 1] = sys_ni_syscall,
+#include <asm/unistd.h>
+};
-- 
2.7.4


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

* [PATCH V2 06/19] csky: Cache and TLB routines
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (4 preceding siblings ...)
  2018-07-01 17:30 ` [PATCH V2 05/19] csky: System Call Guo Ren
@ 2018-07-01 17:30 ` Guo Ren
  2018-07-05 17:40   ` Peter Zijlstra
  2018-07-01 17:30 ` [PATCH V2 07/19] csky: MMU and page table management Guo Ren
                   ` (13 subsequent siblings)
  19 siblings, 1 reply; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/abiv1/cacheflush.c          |  51 +++++++++
 arch/csky/abiv1/inc/abi/cacheflush.h  |  42 +++++++
 arch/csky/abiv1/inc/abi/tlb.h         |  11 ++
 arch/csky/abiv2/cacheflush.c          |  55 +++++++++
 arch/csky/abiv2/inc/abi/cacheflush.h  |  38 ++++++
 arch/csky/abiv2/inc/abi/tlb.h         |  12 ++
 arch/csky/include/asm/barrier.h       |  19 +++
 arch/csky/include/asm/cache.h         |  29 +++++
 arch/csky/include/asm/cacheflush.h    |   9 ++
 arch/csky/include/asm/dma-mapping.h   |  13 +++
 arch/csky/include/asm/io.h            |  23 ++++
 arch/csky/include/asm/tlb.h           |  19 +++
 arch/csky/include/asm/tlbflush.h      |  22 ++++
 arch/csky/include/uapi/asm/cachectl.h |  13 +++
 arch/csky/mm/cachev1.c                | 132 +++++++++++++++++++++
 arch/csky/mm/cachev2.c                |  97 ++++++++++++++++
 arch/csky/mm/syscache.c               |  29 +++++
 arch/csky/mm/tlb.c                    | 210 ++++++++++++++++++++++++++++++++++
 18 files changed, 824 insertions(+)
 create mode 100644 arch/csky/abiv1/cacheflush.c
 create mode 100644 arch/csky/abiv1/inc/abi/cacheflush.h
 create mode 100644 arch/csky/abiv1/inc/abi/tlb.h
 create mode 100644 arch/csky/abiv2/cacheflush.c
 create mode 100644 arch/csky/abiv2/inc/abi/cacheflush.h
 create mode 100644 arch/csky/abiv2/inc/abi/tlb.h
 create mode 100644 arch/csky/include/asm/barrier.h
 create mode 100644 arch/csky/include/asm/cache.h
 create mode 100644 arch/csky/include/asm/cacheflush.h
 create mode 100644 arch/csky/include/asm/dma-mapping.h
 create mode 100644 arch/csky/include/asm/io.h
 create mode 100644 arch/csky/include/asm/tlb.h
 create mode 100644 arch/csky/include/asm/tlbflush.h
 create mode 100644 arch/csky/include/uapi/asm/cachectl.h
 create mode 100644 arch/csky/mm/cachev1.c
 create mode 100644 arch/csky/mm/cachev2.c
 create mode 100644 arch/csky/mm/syscache.c
 create mode 100644 arch/csky/mm/tlb.c

diff --git a/arch/csky/abiv1/cacheflush.c b/arch/csky/abiv1/cacheflush.c
new file mode 100644
index 0000000..cb176f4
--- /dev/null
+++ b/arch/csky/abiv1/cacheflush.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/syscalls.h>
+#include <linux/spinlock.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/cacheflush.h>
+#include <asm/cachectl.h>
+
+void flush_dcache_page(struct page *page)
+{
+	struct address_space *mapping = page_mapping(page);
+	unsigned long addr;
+
+	if (mapping && !mapping_mapped(mapping)) {
+		set_bit(PG_arch_1, &(page)->flags);
+		return;
+	}
+
+	/*
+	 * We could delay the flush for the !page_mapping case too.  But that
+	 * case is for exec env/arg pages and those are %99 certainly going to
+	 * get faulted into the tlb (and thus flushed) anyways.
+	 */
+	addr = (unsigned long) page_address(page);
+	dcache_wbinv_range(addr, addr + PAGE_SIZE);
+}
+
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *pte)
+{
+	unsigned long addr;
+	struct page *page;
+	unsigned long pfn;
+
+	pfn = pte_pfn(*pte);
+	if (unlikely(!pfn_valid(pfn)))
+		return;
+
+	page = pfn_to_page(pfn);
+	addr = (unsigned long) page_address(page);
+
+	if (vma->vm_flags & VM_EXEC ||
+	    pages_do_alias(addr, address & PAGE_MASK))
+		cache_wbinv_all();
+
+	clear_bit(PG_arch_1, &(page)->flags);
+}
+
diff --git a/arch/csky/abiv1/inc/abi/cacheflush.h b/arch/csky/abiv1/inc/abi/cacheflush.h
new file mode 100644
index 0000000..3f99f25
--- /dev/null
+++ b/arch/csky/abiv1/inc/abi/cacheflush.h
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ABI_CSKY_CACHEFLUSH_H
+#define __ABI_CSKY_CACHEFLUSH_H
+
+#include <linux/compiler.h>
+#include <asm/string.h>
+#include <asm/cache.h>
+
+#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
+extern void flush_dcache_page(struct page *);
+
+#define flush_cache_mm(mm)		cache_wbinv_all()
+#define flush_cache_page(vma,page,pfn)	cache_wbinv_all()
+#define flush_cache_dup_mm(mm)		cache_wbinv_all()
+
+#define flush_cache_range(mm,start,end)	cache_wbinv_range(start, end)
+#define flush_cache_vmap(start, end)	cache_wbinv_range(start, end)
+#define flush_cache_vunmap(start, end)  cache_wbinv_range(start, end)
+
+#define flush_icache_page(vma, page)	cache_wbinv_all()
+#define flush_icache_range(start, end)	cache_wbinv_range(start, end)
+#define flush_icache_user_range(vma,pg,adr,len)	cache_wbinv_range(adr, adr + len)
+
+#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
+do{ \
+	cache_wbinv_all(); \
+	memcpy(dst, src, len); \
+	icache_inv_all(); \
+}while(0)
+
+#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
+do{ \
+	cache_wbinv_all(); \
+	memcpy(dst, src, len); \
+}while(0)
+
+#define flush_dcache_mmap_lock(mapping)		do{}while(0)
+#define flush_dcache_mmap_unlock(mapping)	do{}while(0)
+
+#endif /* __ABI_CSKY_CACHEFLUSH_H */
+
diff --git a/arch/csky/abiv1/inc/abi/tlb.h b/arch/csky/abiv1/inc/abi/tlb.h
new file mode 100644
index 0000000..cf0c8d9
--- /dev/null
+++ b/arch/csky/abiv1/inc/abi/tlb.h
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ABI_CSKY_TLB_H
+#define __ABI_CSKY_TLB_H
+
+#define tlb_start_vma(tlb, vma) \
+	do { \
+		if (!tlb->fullmm) \
+			cache_wbinv_all(); \
+	}  while (0)
+#endif /* __ABI_CSKY_TLB_H */
diff --git a/arch/csky/abiv2/cacheflush.c b/arch/csky/abiv2/cacheflush.c
new file mode 100644
index 0000000..32a02f0
--- /dev/null
+++ b/arch/csky/abiv2/cacheflush.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/cache.h>
+#include <linux/highmem.h>
+#include <linux/mm.h>
+#include <asm/cache.h>
+
+void flush_icache_page(struct vm_area_struct *vma, struct page *page)
+{
+	void *va;
+	unsigned long start, end;
+
+	va = page_address(page);
+	start = (unsigned long) va;
+
+	if (va == NULL && PageHighMem(page))
+		start = (unsigned long) kmap_atomic(page);
+
+	end = start + PAGE_SIZE;
+
+	cache_wbinv_range(start, end);
+
+	if (va == NULL && PageHighMem(page))
+		kunmap_atomic((void *)start);
+}
+
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *pte)
+{
+	unsigned long addr, pfn;
+	struct page *page;
+	void *va;
+
+	if (!(vma->vm_flags & VM_EXEC))
+		return;
+
+	pfn = pte_pfn(*pte);
+	if (unlikely(!pfn_valid(pfn)))
+		return;
+
+	page = pfn_to_page(pfn);
+	if (page == ZERO_PAGE(0))
+		return;
+
+	va = page_address(page);
+	addr = (unsigned long) va;
+
+	if (va == NULL && PageHighMem(page))
+		addr = (unsigned long) kmap_atomic(page);
+
+	cache_wbinv_range(addr, addr + PAGE_SIZE);
+
+	if (va == NULL && PageHighMem(page))
+		kunmap_atomic((void *) addr);
+}
+
diff --git a/arch/csky/abiv2/inc/abi/cacheflush.h b/arch/csky/abiv2/inc/abi/cacheflush.h
new file mode 100644
index 0000000..3c99bb2
--- /dev/null
+++ b/arch/csky/abiv2/inc/abi/cacheflush.h
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+#ifndef __ABI_CSKY_CACHEFLUSH_H
+#define __ABI_CSKY_CACHEFLUSH_H
+
+/* Keep includes the same across arches.  */
+#include <linux/mm.h>
+
+/*
+ * The cache doesn't need to be flushed when TLB entries change when
+ * the cache is mapped to physical memory, not virtual memory
+ */
+#define flush_cache_all()			do { } while (0)
+#define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_dup_mm(mm)			do { } while (0)
+#define flush_cache_range(vma, start, end)	do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
+#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
+#define flush_dcache_page(page)			do { } while (0)
+#define flush_dcache_mmap_lock(mapping)		do { } while (0)
+#define flush_dcache_mmap_unlock(mapping)	do { } while (0)
+
+#define flush_icache_range(start, end)		cache_wbinv_range(start, end)
+#define flush_icache_user_range(vma,pg,adr,len)	cache_wbinv_range(adr, adr + len)
+void flush_icache_page(struct vm_area_struct *vma, struct page *page);
+
+#define flush_cache_vmap(start, end)		do { } while (0)
+#define flush_cache_vunmap(start, end)		do { } while (0)
+
+#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
+	do { \
+		memcpy(dst, src, len); \
+		flush_icache_user_range(vma, page, vaddr, len); \
+	} while (0)
+#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
+	memcpy(dst, src, len)
+
+#endif /* __ABI_CSKY_CACHEFLUSH_H */
+
diff --git a/arch/csky/abiv2/inc/abi/tlb.h b/arch/csky/abiv2/inc/abi/tlb.h
new file mode 100644
index 0000000..0faa4e9
--- /dev/null
+++ b/arch/csky/abiv2/inc/abi/tlb.h
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ABI_CSKY_TLB_H
+#define __ABI_CSKY_TLB_H
+
+#define tlb_start_vma(tlb, vma) \
+	do { \
+		if (!tlb->fullmm && (vma->vm_flags & VM_EXEC)) \
+			icache_inv_all(); \
+	}  while (0)
+
+#endif /* __ABI_CSKY_TLB_H */
diff --git a/arch/csky/include/asm/barrier.h b/arch/csky/include/asm/barrier.h
new file mode 100644
index 0000000..7254527
--- /dev/null
+++ b/arch/csky/include/asm/barrier.h
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_BARRIER_H
+#define __ASM_CSKY_BARRIER_H
+
+#ifndef __ASSEMBLY__
+
+#define nop()	asm volatile ("nop")
+
+#ifdef CONFIG_SMP
+#define mb()	asm volatile ("sync.is":::"memory")
+#else
+#define mb()	asm volatile ("sync":::"memory")
+#endif
+
+#include <asm-generic/barrier.h>
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_CSKY_BARRIER_H */
diff --git a/arch/csky/include/asm/cache.h b/arch/csky/include/asm/cache.h
new file mode 100644
index 0000000..d9224f9
--- /dev/null
+++ b/arch/csky/include/asm/cache.h
@@ -0,0 +1,29 @@
+#ifndef __ASM_CSKY_CACHE_H
+#define __ASM_CSKY_CACHE_H
+
+/* bytes per L1 cache line */
+#define L1_CACHE_SHIFT	CONFIG_L1_CACHE_SHIFT
+
+#define L1_CACHE_BYTES	(1 << L1_CACHE_SHIFT)
+
+#define ARCH_DMA_MINALIGN	L1_CACHE_BYTES
+
+#ifndef __ASSEMBLY__
+
+void dcache_wb_line(unsigned long start);
+
+void icache_inv_range(unsigned long start, unsigned long end);
+void icache_inv_all(void);
+
+void dcache_wb_range(unsigned long start, unsigned long end);
+void dcache_wbinv_range(unsigned long start, unsigned long end);
+void dcache_wbinv_all(void);
+
+void cache_wbinv_range(unsigned long start, unsigned long end);
+void cache_wbinv_all(void);
+
+void dma_wbinv_range(unsigned long start, unsigned long end);
+void dma_wb_range(unsigned long start, unsigned long end);
+
+#endif
+#endif  /* __ASM_CSKY_CACHE_H */
diff --git a/arch/csky/include/asm/cacheflush.h b/arch/csky/include/asm/cacheflush.h
new file mode 100644
index 0000000..6a4233b
--- /dev/null
+++ b/arch/csky/include/asm/cacheflush.h
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_CACHEFLUSH_H
+#define __ASM_CSKY_CACHEFLUSH_H
+
+#include <abi/cacheflush.h>
+
+#endif /* __ASM_CSKY_CACHEFLUSH_H */
+
diff --git a/arch/csky/include/asm/dma-mapping.h b/arch/csky/include/asm/dma-mapping.h
new file mode 100644
index 0000000..4c91a3e
--- /dev/null
+++ b/arch/csky/include/asm/dma-mapping.h
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_DMA_MAPPING_H
+#define __ASM_DMA_MAPPING_H
+
+extern struct dma_map_ops csky_dma_map_ops;
+
+static inline struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
+{
+	return &csky_dma_map_ops;
+}
+
+#endif /* __ASM_DMA_MAPPING_H */
diff --git a/arch/csky/include/asm/io.h b/arch/csky/include/asm/io.h
new file mode 100644
index 0000000..fcb2142
--- /dev/null
+++ b/arch/csky/include/asm/io.h
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_IO_H
+#define __ASM_CSKY_IO_H
+
+#include <abi/pgtable-bits.h>
+#include <linux/types.h>
+#include <linux/version.h>
+
+extern void __iomem *ioremap(phys_addr_t offset, size_t size);
+
+extern void iounmap(void *addr);
+
+extern int remap_area_pages(unsigned long address, phys_addr_t phys_addr,
+		size_t size, unsigned long flags);
+
+#define ioremap_nocache(phy, sz)	ioremap(phy, sz)
+#define ioremap_wc ioremap_nocache
+#define ioremap_wt ioremap_nocache
+
+#include <asm-generic/io.h>
+
+#endif /* __ASM_CSKY_IO_H */
diff --git a/arch/csky/include/asm/tlb.h b/arch/csky/include/asm/tlb.h
new file mode 100644
index 0000000..b2ea919
--- /dev/null
+++ b/arch/csky/include/asm/tlb.h
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_TLB_H
+#define __ASM_CSKY_TLB_H
+
+#include <asm/cacheflush.h>
+#include <abi/tlb.h>
+
+#define tlb_end_vma(tlb, vma) \
+	do { \
+		if (!tlb->fullmm) \
+			flush_tlb_range(vma, vma->vm_start, vma->vm_end); \
+	}  while (0)
+
+#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
+
+#include <asm-generic/tlb.h>
+
+#endif /* __ASM_CSKY_TLB_H */
diff --git a/arch/csky/include/asm/tlbflush.h b/arch/csky/include/asm/tlbflush.h
new file mode 100644
index 0000000..d44cb07
--- /dev/null
+++ b/arch/csky/include/asm/tlbflush.h
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_TLBFLUSH_H
+#define __ASM_TLBFLUSH_H
+/*
+ * TLB flushing:
+ *
+ *  - flush_tlb_all() flushes all processes TLB entries
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB entries
+ *  - flush_tlb_page(vma, vmaddr) flushes one page
+ *  - flush_tlb_range(vma, start, end) flushes a range of pages
+ *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
+ */
+extern void flush_tlb_all(void);
+extern void flush_tlb_mm(struct mm_struct *mm);
+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
+extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
+extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+
+extern void flush_tlb_one(unsigned long vaddr);
+
+#endif
diff --git a/arch/csky/include/uapi/asm/cachectl.h b/arch/csky/include/uapi/asm/cachectl.h
new file mode 100644
index 0000000..38a1a28
--- /dev/null
+++ b/arch/csky/include/uapi/asm/cachectl.h
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_CACHECTL_H
+#define __ASM_CSKY_CACHECTL_H
+
+/*
+ * See "man cacheflush"
+ */
+#define ICACHE  (1<<0)
+#define DCACHE  (1<<1)
+#define BCACHE  (ICACHE|DCACHE)
+
+#endif /* __ASM_CSKY_CACHECTL_H */
diff --git a/arch/csky/mm/cachev1.c b/arch/csky/mm/cachev1.c
new file mode 100644
index 0000000..afdc916
--- /dev/null
+++ b/arch/csky/mm/cachev1.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/spinlock.h>
+#include <asm/cache.h>
+#include <abi/reg_ops.h>
+
+/* for L1-cache */
+#define INS_CACHE		(1 << 0)
+#define DATA_CACHE		(1 << 1)
+#define CACHE_INV		(1 << 4)
+#define CACHE_CLR		(1 << 5)
+#define CACHE_OMS		(1 << 6)
+#define CACHE_ITS		(1 << 7)
+#define CACHE_LICF		(1 << 31)
+
+/* for L2-cache */
+#define CR22_LEVEL_SHIFT        (1)
+#define CR22_SET_SHIFT		(7)
+#define CR22_WAY_SHIFT          (30)
+#define CR22_WAY_SHIFT_L2	(29)
+
+#define SYNC asm volatile("sync\n")
+
+static DEFINE_SPINLOCK(cache_lock);
+
+static inline void cache_op_line(unsigned long i, unsigned int val)
+{
+	mtcr("cr22", i);
+	mtcr("cr17", val);
+}
+
+#define CCR2_L2E (1 << 3)
+static void cache_op_all(unsigned int value, unsigned int l2)
+{
+	mtcr("cr17", value | CACHE_CLR);
+	SYNC;
+
+	if (l2 && (mfcr_ccr2() & CCR2_L2E)) {
+		mtcr("cr24", value | CACHE_CLR);
+		SYNC;
+	}
+}
+
+static void cache_op_range(
+	unsigned int start,
+	unsigned int end,
+	unsigned int value,
+	unsigned int l2)
+{
+	unsigned long i, flags;
+	unsigned int val = value | CACHE_CLR | CACHE_OMS;
+	bool l2_sync;
+
+	if (unlikely((end - start) >= PAGE_SIZE) ||
+	    unlikely(start < PAGE_OFFSET) ||
+	    unlikely(start >= PAGE_OFFSET + LOWMEM_LIMIT)) {
+		cache_op_all(value, l2);
+		return;
+	}
+
+	if ((mfcr_ccr2() & CCR2_L2E) && l2)
+		l2_sync = 1;
+	else
+		l2_sync = 0;
+
+	spin_lock_irqsave(&cache_lock, flags);
+
+	i = start & ~(L1_CACHE_BYTES - 1);
+	for(; i < end; i += L1_CACHE_BYTES) {
+		cache_op_line(i, val);
+		if (l2_sync) {
+			SYNC;
+			mtcr("cr24", val);
+		}
+	}
+	spin_unlock_irqrestore(&cache_lock, flags);
+
+	SYNC;
+}
+
+void dcache_wb_line(unsigned long start)
+{
+	asm volatile("idly4\n");
+	cache_op_line(start, DATA_CACHE|CACHE_CLR);
+	SYNC;
+}
+
+void icache_inv_range(unsigned long start, unsigned long end)
+{
+	cache_op_range(start, end, INS_CACHE|CACHE_INV, 0);
+}
+
+void icache_inv_all(void)
+{
+	cache_op_all(INS_CACHE|CACHE_INV, 0);
+}
+
+void dcache_wb_range(unsigned long start, unsigned long end)
+{
+	cache_op_range(start, end, DATA_CACHE|CACHE_CLR, 0);
+}
+
+void dcache_wbinv_range(unsigned long start, unsigned long end)
+{
+	cache_op_range(start, end, DATA_CACHE|CACHE_CLR|CACHE_INV, 0);
+}
+
+void dcache_wbinv_all(void)
+{
+	cache_op_all(DATA_CACHE|CACHE_CLR|CACHE_INV, 0);
+}
+
+void cache_wbinv_range(unsigned long start, unsigned long end)
+{
+	cache_op_range(start, end, INS_CACHE|DATA_CACHE|CACHE_CLR|CACHE_INV, 0);
+}
+
+void cache_wbinv_all(void)
+{
+	cache_op_all(INS_CACHE|DATA_CACHE|CACHE_CLR|CACHE_INV, 0);
+}
+
+void dma_wbinv_range(unsigned long start, unsigned long end)
+{
+	cache_op_range(start, end, DATA_CACHE|CACHE_CLR|CACHE_INV, 1);
+}
+
+void dma_wb_range(unsigned long start, unsigned long end)
+{
+	cache_op_range(start, end, DATA_CACHE|CACHE_INV, 1);
+}
+
diff --git a/arch/csky/mm/cachev2.c b/arch/csky/mm/cachev2.c
new file mode 100644
index 0000000..dc640d5
--- /dev/null
+++ b/arch/csky/mm/cachev2.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/spinlock.h>
+#include <linux/smp.h>
+#include <asm/cache.h>
+
+#define SYNC asm volatile("sync.is\n")
+
+void inline dcache_wb_line(unsigned long start)
+{
+	asm volatile("dcache.cval1 %0\n"::"r"(start));
+	SYNC;
+}
+
+void icache_inv_range(unsigned long start, unsigned long end)
+{
+	unsigned long i = start & ~(L1_CACHE_BYTES - 1);
+
+	for (;i < end; i += L1_CACHE_BYTES)
+		asm volatile("icache.iva %0\n"::"r"(i));
+	SYNC;
+}
+
+void icache_inv_all(void)
+{
+	asm volatile("icache.ialls\n");
+	SYNC;
+}
+
+void dcache_wb_range(unsigned long start, unsigned long end)
+{
+	unsigned long i = start & ~(L1_CACHE_BYTES - 1);
+
+	for (;i < end; i += L1_CACHE_BYTES)
+		asm volatile("dcache.cval1 %0\n"::"r"(i));
+	SYNC;
+}
+
+void dcache_wbinv_range(unsigned long start, unsigned long end)
+{
+	unsigned long i = start & ~(L1_CACHE_BYTES - 1);
+
+	for (;i < end; i += L1_CACHE_BYTES) {
+		asm volatile("dcache.cval1 %0\n"::"r"(i));
+	}
+	SYNC;
+	for (;i < end; i += L1_CACHE_BYTES) {
+		asm volatile("dcache.iva %0\n"::"r"(i));
+	}
+	SYNC;
+}
+
+void dcache_inv_range(unsigned long start, unsigned long end)
+{
+	unsigned long i = start & ~(L1_CACHE_BYTES - 1);
+
+	for (;i < end; i += L1_CACHE_BYTES)
+		asm volatile("dcache.civa %0\n"::"r"(i));
+	SYNC;
+}
+
+void cache_wbinv_range(unsigned long start, unsigned long end)
+{
+	unsigned long i = start & ~(L1_CACHE_BYTES - 1);
+
+	for (;i < end; i += L1_CACHE_BYTES) {
+		asm volatile("dcache.cval1 %0\n"::"r"(i));
+	}
+	SYNC;
+	for (;i < end; i += L1_CACHE_BYTES) {
+		asm volatile("dcache.iva %0\n"::"r"(i));
+	}
+	SYNC;
+	for (;i < end; i += L1_CACHE_BYTES) {
+		asm volatile("icache.iva %0\n"::"r"(i));
+	}
+	SYNC;
+}
+
+void dma_wbinv_range(unsigned long start, unsigned long end)
+{
+	unsigned long i = start & ~(L1_CACHE_BYTES - 1);
+
+	for (; i < end; i += L1_CACHE_BYTES)
+		asm volatile("dcache.civa %0\n"::"r"(i));
+	SYNC;
+}
+
+void dma_wb_range(unsigned long start, unsigned long end)
+{
+	unsigned long i = start & ~(L1_CACHE_BYTES - 1);
+
+	for (; i < end; i += L1_CACHE_BYTES)
+		asm volatile("dcache.civa %0\n"::"r"(i));
+
+	SYNC;
+}
diff --git a/arch/csky/mm/syscache.c b/arch/csky/mm/syscache.c
new file mode 100644
index 0000000..9f5a373
--- /dev/null
+++ b/arch/csky/mm/syscache.c
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/syscalls.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/cachectl.h>
+
+SYSCALL_DEFINE3(cacheflush,
+		void __user *, addr,
+		unsigned long, bytes,
+		int, cache)
+{
+	switch(cache) {
+	case ICACHE:
+		icache_inv_range((unsigned long)addr, (unsigned long)addr + bytes);
+		break;
+	case DCACHE:
+		dcache_wbinv_range((unsigned long)addr, (unsigned long)addr + bytes);
+		break;
+	case BCACHE:
+		cache_wbinv_range((unsigned long)addr, (unsigned long)addr + bytes);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
diff --git a/arch/csky/mm/tlb.c b/arch/csky/mm/tlb.c
new file mode 100644
index 0000000..172c380
--- /dev/null
+++ b/arch/csky/mm/tlb.c
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/setup.h>
+
+#define CSKY_TLB_SIZE CONFIG_CPU_TLB_SIZE
+
+void flush_tlb_all(void)
+{
+	tlb_invalid_all();
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+	int cpu = smp_processor_id();
+
+	if (cpu_context(cpu, mm) != 0)
+		drop_mmu_context(mm,cpu);
+}
+
+#define restore_asid_inv_utlb(oldpid, newpid) \
+do { \
+	if((oldpid & ASID_MASK) == newpid) \
+		write_mmu_entryhi(oldpid +1); \
+	write_mmu_entryhi(oldpid); \
+} while(0)
+
+void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+			   unsigned long end)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	int cpu = smp_processor_id();
+
+	if (cpu_context(cpu, mm) != 0) {
+		unsigned long size, flags;
+
+		local_irq_save(flags);
+		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+		size = (size + 1) >> 1;
+		if (size <= CSKY_TLB_SIZE/2) {
+			start &= (PAGE_MASK << 1);
+			end += ((PAGE_SIZE << 1) - 1);
+			end &= (PAGE_MASK << 1);
+#ifdef CONFIG_CPU_HAS_TLBI
+			while (start < end) {
+				asm volatile("tlbi.alls"::"r"(start):);
+				start += (PAGE_SIZE << 1);
+			}
+			asm volatile("sync.is\n");
+#else
+			{
+			int oldpid = read_mmu_entryhi();
+			int newpid = cpu_asid(cpu, mm);
+
+			while (start < end) {
+				int idx;
+
+				write_mmu_entryhi(start | newpid);
+				start += (PAGE_SIZE << 1);
+				tlb_probe();
+				idx = read_mmu_index();
+				if (idx >= 0)
+					tlb_invalid_indexed();
+			}
+			restore_asid_inv_utlb(oldpid, newpid);
+			}
+#endif
+		} else {
+			drop_mmu_context(mm, cpu);
+		}
+		local_irq_restore(flags);
+	}
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+        unsigned long size, flags;
+
+        local_irq_save(flags);
+        size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+        if (size <= CSKY_TLB_SIZE) {
+		start &= (PAGE_MASK << 1);
+		end += ((PAGE_SIZE << 1) - 1);
+		end &= (PAGE_MASK << 1);
+#ifdef CONFIG_CPU_HAS_TLBI
+		while (start < end) {
+			asm volatile("tlbi.alls"::"r"(start):);
+			start += (PAGE_SIZE << 1);
+		}
+		asm volatile("sync.is\n");
+#else
+		{
+                int oldpid = read_mmu_entryhi();
+                while (start < end) {
+                        int idx;
+                        write_mmu_entryhi(start);
+			start += (PAGE_SIZE << 1);
+                        tlb_probe();
+                        idx = read_mmu_index();
+                        if (idx >= 0)
+                                tlb_invalid_indexed();
+                }
+		restore_asid_inv_utlb(oldpid, 0);
+		}
+#endif
+	} else
+		flush_tlb_all();
+
+        local_irq_restore(flags);
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+	int cpu = smp_processor_id();
+
+	if (!vma || cpu_context(cpu, vma->vm_mm) != 0) {
+		page &= (PAGE_MASK << 1);
+
+#ifdef CONFIG_CPU_HAS_TLBI
+		asm volatile("tlbi.alls"::"r"(page):);
+		asm volatile("sync.is\n");
+#else
+		{
+		int newpid, oldpid, idx;
+		unsigned long flags;
+		local_irq_save(flags);
+		newpid = cpu_asid(cpu, vma->vm_mm);
+		oldpid = read_mmu_entryhi();
+		write_mmu_entryhi(page | newpid);
+		tlb_probe();
+		idx = read_mmu_index();
+		if(idx >= 0)
+			tlb_invalid_indexed();
+
+		restore_asid_inv_utlb(oldpid, newpid);
+		local_irq_restore(flags);
+		}
+#endif
+	}
+}
+
+/*
+ * Remove one kernel space TLB entry.  This entry is assumed to be marked
+ * global so we don't do the ASID thing.
+ */
+void flush_tlb_one(unsigned long page)
+{
+	page &= (PAGE_MASK << 1);
+
+#ifdef CONFIG_CPU_HAS_TLBI
+	asm volatile("tlbi.alls"::"r"(page):);
+	asm volatile("sync.is\n");
+#else
+	{
+	int idx, oldpid;
+	unsigned long flags;
+	oldpid = read_mmu_entryhi();
+
+	local_irq_save(flags);
+	page = page | (oldpid & 0xff);
+	write_mmu_entryhi(page);
+	tlb_probe();
+	idx = read_mmu_index();
+	if (idx >= 0)
+		tlb_invalid_indexed();
+	restore_asid_inv_utlb(oldpid, oldpid);
+	local_irq_restore(flags);
+	}
+#endif
+}
+
+EXPORT_SYMBOL(flush_tlb_one);
+
+/* show current 32 jtlbs */
+void show_jtlb_table(void)
+{
+	unsigned long flags;
+	int entryhi, entrylo0, entrylo1;
+	int entry;
+	int oldpid;
+
+	local_irq_save(flags);
+	entry = 0;
+	pr_info("\n\n\n");
+
+	oldpid = read_mmu_entryhi();
+	while (entry < CSKY_TLB_SIZE)
+	{
+		write_mmu_index(entry);
+		tlb_read();
+		entryhi = read_mmu_entryhi();
+		entrylo0 = read_mmu_entrylo0();
+		entrylo0 = entrylo0;
+		entrylo1 = read_mmu_entrylo1();
+		entrylo1 = entrylo1;
+		pr_info("jtlb[%d]:	entryhi - 0x%x;	entrylo0 - 0x%x;"
+		        "	entrylo1 - 0x%x\n",
+			 entry, entryhi, entrylo0, entrylo1);
+		entry++;
+	}
+	write_mmu_entryhi(oldpid);
+	local_irq_restore(flags);
+}
+
-- 
2.7.4


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

* [PATCH V2 07/19] csky: MMU and page table management
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (5 preceding siblings ...)
  2018-07-01 17:30 ` [PATCH V2 06/19] csky: Cache and TLB routines Guo Ren
@ 2018-07-01 17:30 ` Guo Ren
  2018-07-02 13:29   ` Christoph Hellwig
  2018-07-01 17:30 ` [PATCH V2 08/19] csky: Process management and Signal Guo Ren
                   ` (12 subsequent siblings)
  19 siblings, 1 reply; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/abiv1/inc/abi/ckmmu.h        |  80 +++++++++
 arch/csky/abiv1/inc/abi/page.h         |  26 +++
 arch/csky/abiv1/inc/abi/pgtable-bits.h |  36 ++++
 arch/csky/abiv1/mmap.c                 |  65 +++++++
 arch/csky/abiv2/inc/abi/ckmmu.h        |  88 ++++++++++
 arch/csky/abiv2/inc/abi/page.h         |  14 ++
 arch/csky/abiv2/inc/abi/pgtable-bits.h |  36 ++++
 arch/csky/include/asm/addrspace.h      |  10 ++
 arch/csky/include/asm/fixmap.h         |  65 +++++++
 arch/csky/include/asm/highmem.h        |  50 ++++++
 arch/csky/include/asm/mmu.h            |  11 ++
 arch/csky/include/asm/page.h           | 104 ++++++++++++
 arch/csky/include/asm/pgalloc.h        | 108 ++++++++++++
 arch/csky/include/asm/pgtable.h        | 301 +++++++++++++++++++++++++++++++++
 arch/csky/include/asm/segment.h        |  18 ++
 arch/csky/include/asm/shmparam.h       |  10 ++
 arch/csky/mm/dma-mapping.c             | 216 +++++++++++++++++++++++
 arch/csky/mm/highmem.c                 | 210 +++++++++++++++++++++++
 arch/csky/mm/init.c                    | 122 +++++++++++++
 arch/csky/mm/ioremap.c                 |  49 ++++++
 20 files changed, 1619 insertions(+)
 create mode 100644 arch/csky/abiv1/inc/abi/ckmmu.h
 create mode 100644 arch/csky/abiv1/inc/abi/page.h
 create mode 100644 arch/csky/abiv1/inc/abi/pgtable-bits.h
 create mode 100644 arch/csky/abiv1/mmap.c
 create mode 100644 arch/csky/abiv2/inc/abi/ckmmu.h
 create mode 100644 arch/csky/abiv2/inc/abi/page.h
 create mode 100644 arch/csky/abiv2/inc/abi/pgtable-bits.h
 create mode 100644 arch/csky/include/asm/addrspace.h
 create mode 100644 arch/csky/include/asm/fixmap.h
 create mode 100644 arch/csky/include/asm/highmem.h
 create mode 100644 arch/csky/include/asm/mmu.h
 create mode 100644 arch/csky/include/asm/page.h
 create mode 100644 arch/csky/include/asm/pgalloc.h
 create mode 100644 arch/csky/include/asm/pgtable.h
 create mode 100644 arch/csky/include/asm/segment.h
 create mode 100644 arch/csky/include/asm/shmparam.h
 create mode 100644 arch/csky/mm/dma-mapping.c
 create mode 100644 arch/csky/mm/highmem.c
 create mode 100644 arch/csky/mm/init.c
 create mode 100644 arch/csky/mm/ioremap.c

diff --git a/arch/csky/abiv1/inc/abi/ckmmu.h b/arch/csky/abiv1/inc/abi/ckmmu.h
new file mode 100644
index 0000000..e8e7d43
--- /dev/null
+++ b/arch/csky/abiv1/inc/abi/ckmmu.h
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_CKMMUV1_H
+#define __ASM_CSKY_CKMMUV1_H
+#include <abi/reg_ops.h>
+
+static inline void select_mmu_cp(void)
+{
+	 asm volatile("cpseti cp15\n");
+}
+
+static inline int read_mmu_index(void)
+{
+	return cprcr("cpcr0");
+}
+
+static inline void write_mmu_index(int value)
+{
+	cpwcr("cpcr0", value);
+}
+
+static inline int read_mmu_entrylo0(void)
+{
+	return cprcr("cpcr2") << 6;
+}
+
+static inline int read_mmu_entrylo1(void)
+{
+	return cprcr("cpcr3") << 6;
+}
+
+static inline void write_mmu_pagemask(int value)
+{
+	cpwcr("cpcr6", value);
+}
+
+static inline int read_mmu_entryhi(void)
+{
+	return cprcr("cpcr4");
+}
+
+static inline void write_mmu_entryhi(int value)
+{
+	cpwcr("cpcr4", value);
+}
+
+/*
+ * TLB operations.
+ */
+static inline void tlb_probe(void)
+{
+	cpwcr("cpcr8", 0x80000000);
+}
+
+static inline void tlb_read(void)
+{
+	cpwcr("cpcr8", 0x40000000);
+}
+
+static inline void tlb_invalid_all(void)
+{
+	cpwcr("cpcr8", 0x04000000);
+}
+
+static inline void tlb_invalid_indexed(void)
+{
+	cpwcr("cpcr8", 0x02000000);
+}
+
+static inline void setup_pgd(unsigned long pgd)
+{
+	cpwcr("cpcr29", pgd);
+}
+
+static inline unsigned long get_pgd(void)
+{
+	return cprcr("cpcr29");
+}
+#endif /* __ASM_CSKY_CKMMUV1_H */
+
diff --git a/arch/csky/abiv1/inc/abi/page.h b/arch/csky/abiv1/inc/abi/page.h
new file mode 100644
index 0000000..b0d2122
--- /dev/null
+++ b/arch/csky/abiv1/inc/abi/page.h
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+extern unsigned long shm_align_mask;
+extern void flush_dcache_page(struct page *);
+
+static inline unsigned long pages_do_alias(unsigned long addr1,
+					   unsigned long addr2)
+{
+	return (addr1 ^ addr2) & shm_align_mask;
+}
+
+static inline void clear_user_page(void *addr, unsigned long vaddr,
+				   struct page *page)
+{
+	clear_page(addr);
+	if (pages_do_alias((unsigned long) addr, vaddr & PAGE_MASK))
+		flush_dcache_page(page);
+}
+
+static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
+				  struct page *page)
+{
+	copy_page(to, from);
+	if (pages_do_alias((unsigned long) to, vaddr & PAGE_MASK))
+		flush_dcache_page(page);
+}
diff --git a/arch/csky/abiv1/inc/abi/pgtable-bits.h b/arch/csky/abiv1/inc/abi/pgtable-bits.h
new file mode 100644
index 0000000..3d614f3
--- /dev/null
+++ b/arch/csky/abiv1/inc/abi/pgtable-bits.h
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_PGTABLE_BITS_H
+#define __ASM_CSKY_PGTABLE_BITS_H
+
+/* implemented in software */
+#define _PAGE_ACCESSED		(1<<3)
+#define PAGE_ACCESSED_BIT	(3)
+
+#define _PAGE_READ		(1<<1)
+#define _PAGE_WRITE		(1<<2)
+#define _PAGE_PRESENT		(1<<0)
+
+#define _PAGE_MODIFIED		(1<<4)
+#define PAGE_MODIFIED_BIT	(4)
+
+/* implemented in hardware */
+#define _PAGE_GLOBAL		(1<<6)
+
+#define _PAGE_VALID		(1<<7)
+#define PAGE_VALID_BIT		(7)
+
+#define _PAGE_DIRTY		(1<<8)
+#define PAGE_DIRTY_BIT		(8)
+
+#define _PAGE_CACHE		(3<<9)
+#define _PAGE_UNCACHE		(2<<9)
+
+#define _CACHE_MASK		(7<<9)
+
+#define _CACHE_CACHED		(_PAGE_VALID | _PAGE_CACHE)
+#define _CACHE_UNCACHED		(_PAGE_VALID | _PAGE_UNCACHE)
+
+#define HAVE_ARCH_UNMAPPED_AREA
+
+#endif /* __ASM_CSKY_PGTABLE_BITS_H */
diff --git a/arch/csky/abiv1/mmap.c b/arch/csky/abiv1/mmap.c
new file mode 100644
index 0000000..e70a74b
--- /dev/null
+++ b/arch/csky/abiv1/mmap.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/shm.h>
+#include <linux/sched.h>
+#include <linux/random.h>
+#include <linux/io.h>
+
+unsigned long shm_align_mask = (0x4000 >> 1) - 1;   /* Sane caches */
+
+#define COLOUR_ALIGN(addr,pgoff)                            \
+	((((addr) + shm_align_mask) & ~shm_align_mask) +        \
+	 (((pgoff) << PAGE_SHIFT) & shm_align_mask))
+
+unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
+		unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+	struct vm_area_struct * vmm;
+	int do_color_align;
+
+	if (flags & MAP_FIXED) {
+		/*
+		 * We do not accept a shared mapping if it would violate
+		 * cache aliasing constraints.
+		 */
+		if ((flags & MAP_SHARED) &&
+				((addr - (pgoff << PAGE_SHIFT)) & shm_align_mask))
+			return -EINVAL;
+		return addr;
+	}
+
+	if (len > TASK_SIZE)
+		return -ENOMEM;
+	do_color_align = 0;
+	if (filp || (flags & MAP_SHARED))
+		do_color_align = 1;
+	if (addr) {
+		if (do_color_align)
+			addr = COLOUR_ALIGN(addr, pgoff);
+		else
+			addr = PAGE_ALIGN(addr);
+		vmm = find_vma(current->mm, addr);
+		if (TASK_SIZE - len >= addr &&
+				(!vmm || addr + len <= vmm->vm_start))
+			return addr;
+	}
+	addr = TASK_UNMAPPED_BASE;
+	if (do_color_align)
+		addr = COLOUR_ALIGN(addr, pgoff);
+	else
+		addr = PAGE_ALIGN(addr);
+
+	for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
+		/* At this point:  (!vmm || addr < vmm->vm_end). */
+		if (TASK_SIZE - len < addr)
+			return -ENOMEM;
+		if (!vmm || addr + len <= vmm->vm_start)
+			return addr;
+		addr = vmm->vm_end;
+		if (do_color_align)
+			addr = COLOUR_ALIGN(addr, pgoff);
+	}
+}
diff --git a/arch/csky/abiv2/inc/abi/ckmmu.h b/arch/csky/abiv2/inc/abi/ckmmu.h
new file mode 100644
index 0000000..4b698f9
--- /dev/null
+++ b/arch/csky/abiv2/inc/abi/ckmmu.h
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_CKMMUV2_H
+#define __ASM_CSKY_CKMMUV2_H
+#include <abi/reg_ops.h>
+
+static inline void select_mmu_cp(void){}
+
+static inline int  read_mmu_index(void)
+{
+	return mfcr("cr<0, 15>");
+}
+
+static inline void  write_mmu_index(int value)
+{
+	mtcr("cr<0, 15>", value);
+}
+
+static inline int  read_mmu_entrylo0(void)
+{
+	return mfcr("cr<2, 15>");
+}
+
+static inline int  read_mmu_entrylo1(void)
+{
+	return mfcr("cr<3, 15>");
+}
+
+static inline void  write_mmu_pagemask(int value)
+{
+	mtcr("cr<6, 15>", value);
+}
+
+static inline int  read_mmu_entryhi(void)
+{
+	return mfcr("cr<4, 15>");
+}
+
+static inline void  write_mmu_entryhi(int value)
+{
+	mtcr("cr<4, 15>", value);
+}
+
+/*
+ * TLB operations.
+ */
+static inline void tlb_probe(void)
+{
+	mtcr("cr<8, 15>", 0x80000000);
+}
+
+static inline void tlb_read(void)
+{
+	mtcr("cr<8, 15>", 0x40000000);
+}
+
+static inline void tlb_invalid_all(void)
+{
+#ifdef CONFIG_CPU_HAS_TLBI
+	asm volatile("tlbi.alls\n");
+#else
+	mtcr("cr<8, 15>", 0x04000000);
+#endif
+}
+
+static inline void tlb_invalid_indexed(void)
+{
+	mtcr("cr<8, 15>", 0x02000000);
+}
+
+/* setup hardrefil pgd */
+static inline unsigned long get_pgd(void)
+{
+	return mfcr("cr<29, 15>");
+}
+
+static inline void setup_pgd(unsigned long pgd)
+{
+	mtcr("cr<29, 15>", pgd);
+}
+
+static inline void setup_pgd_kernel(unsigned long pgd)
+{
+	mtcr("cr<28, 15>", pgd);
+}
+
+#endif /* __ASM_CSKY_CKMMUV2_H */
+
diff --git a/arch/csky/abiv2/inc/abi/page.h b/arch/csky/abiv2/inc/abi/page.h
new file mode 100644
index 0000000..41f5633
--- /dev/null
+++ b/arch/csky/abiv2/inc/abi/page.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+static inline void clear_user_page(void *addr, unsigned long vaddr,
+				   struct page *page)
+{
+	clear_page(addr);
+}
+
+static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
+				  struct page *page)
+{
+	copy_page(to, from);
+}
+
diff --git a/arch/csky/abiv2/inc/abi/pgtable-bits.h b/arch/csky/abiv2/inc/abi/pgtable-bits.h
new file mode 100644
index 0000000..3ca90fa
--- /dev/null
+++ b/arch/csky/abiv2/inc/abi/pgtable-bits.h
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_PGTABLE_BITS_H
+#define __ASM_CSKY_PGTABLE_BITS_H
+
+/* implemented in software */
+#define _PAGE_ACCESSED		(1<<7)
+#define PAGE_ACCESSED_BIT	(7)
+
+#define _PAGE_READ		(1<<8)
+#define _PAGE_WRITE		(1<<9)
+#define _PAGE_PRESENT		(1<<10)
+
+#define _PAGE_MODIFIED		(1<<11)
+#define PAGE_MODIFIED_BIT	(11)
+
+/* implemented in hardware */
+#define _PAGE_GLOBAL		(1<<0)
+
+#define _PAGE_VALID		(1<<1)
+#define PAGE_VALID_BIT		(1)
+
+#define _PAGE_DIRTY		(1<<2)
+#define PAGE_DIRTY_BIT		(2)
+
+#define _PAGE_SO		(1<<5)
+#define _PAGE_BUF		(1<<6)
+
+#define _PAGE_CACHE		(1<<3)
+
+#define _CACHE_MASK		_PAGE_CACHE
+
+#define _CACHE_CACHED		(_PAGE_VALID | _PAGE_CACHE | _PAGE_BUF)
+#define _CACHE_UNCACHED		(_PAGE_VALID | _PAGE_SO)
+
+#endif /* __ASM_CSKY_PGTABLE_BITS_H */
diff --git a/arch/csky/include/asm/addrspace.h b/arch/csky/include/asm/addrspace.h
new file mode 100644
index 0000000..63f86ad
--- /dev/null
+++ b/arch/csky/include/asm/addrspace.h
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_ADDRSPACE_H
+#define __ASM_CSKY_ADDRSPACE_H
+
+#define KSEG0		0x80000000ul
+#define KSEG0ADDR(a)	(((unsigned long)a & 0x1fffffff) | KSEG0)
+
+#endif /* __ASM_CSKY_ADDRSPACE_H */
+
diff --git a/arch/csky/include/asm/fixmap.h b/arch/csky/include/asm/fixmap.h
new file mode 100644
index 0000000..65a9cf5
--- /dev/null
+++ b/arch/csky/include/asm/fixmap.h
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_FIXMAP_H
+#define __ASM_CSKY_FIXMAP_H
+
+#include <asm/page.h>
+#ifdef CONFIG_HIGHMEM
+#include <linux/threads.h>
+#include <asm/kmap_types.h>
+#endif
+
+/*
+ * Here we define all the compile-time 'special' virtual
+ * addresses. The point is to have a constant address at
+ * compile time, but to set the physical address only
+ * in the boot process. We allocate these special  addresses
+ * from the end of virtual memory (0xfffff000) backwards.
+ * Also this lets us do fail-safe vmalloc(), we
+ * can guarantee that these special addresses and
+ * vmalloc()-ed addresses never overlap.
+ *
+ * these 'compile-time allocated' memory buffers are
+ * fixed-size 4k pages. (or larger if used with an increment
+ * highger than 1) use fixmap_set(idx,phys) to associate
+ * physical memory with fixmap indices.
+ *
+ * TLB entries of such buffers will not be flushed across
+ * task switches.
+ */
+
+/*
+ * on UP currently we will have no trace of the fixmap mechanizm,
+ * no page table allocations, etc. This might change in the
+ * future, say framebuffers for the console driver(s) could be
+ * fix-mapped?
+ */
+enum fixed_addresses {
+#define FIX_N_COLOURS 8
+	FIX_CMAP_BEGIN,
+	FIX_CMAP_END = FIX_CMAP_BEGIN + (FIX_N_COLOURS * 2),
+#ifdef CONFIG_HIGHMEM
+	/* reserved pte's for temporary kernel mappings */
+	FIX_KMAP_BEGIN = FIX_CMAP_END + 1,
+	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
+#endif
+	__end_of_fixed_addresses
+};
+
+/*
+ * used by vmalloc.c.
+ *
+ * Leave one empty page between vmalloc'ed areas and
+ * the start of the fixmap, and leave one page empty
+ * at the top of mem..
+ */
+#define FIXADDR_TOP	((unsigned long)(long)(int)0xfffe0000)
+#define FIXADDR_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
+#define FIXADDR_START	(FIXADDR_TOP - FIXADDR_SIZE)
+
+#include <asm-generic/fixmap.h>
+
+#define kmap_get_fixmap_pte(vaddr) \
+	pte_offset_kernel(pmd_offset((pud_t *)pgd_offset_k(vaddr), vaddr), (vaddr))
+
+#endif /* __ASM_CSKY_FIXMAP_H */
diff --git a/arch/csky/include/asm/highmem.h b/arch/csky/include/asm/highmem.h
new file mode 100644
index 0000000..976db37
--- /dev/null
+++ b/arch/csky/include/asm/highmem.h
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_HIGHMEM_H
+#define __ASM_CSKY_HIGHMEM_H
+
+#ifdef __KERNEL__
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/uaccess.h>
+#include <asm/kmap_types.h>
+#include <asm/cache.h>
+
+/* undef for production */
+#define HIGHMEM_DEBUG 1
+
+/* declarations for highmem.c */
+extern unsigned long highstart_pfn, highend_pfn;
+
+extern pte_t *pkmap_page_table;
+
+/*
+ * Right now we initialize only a single pte table. It can be extended
+ * easily, subsequent pte tables have to be allocated in one physical
+ * chunk of RAM.
+ */
+#define LAST_PKMAP 1024
+#define LAST_PKMAP_MASK (LAST_PKMAP-1)
+#define PKMAP_NR(virt)  ((virt-PKMAP_BASE) >> PAGE_SHIFT)
+#define PKMAP_ADDR(nr)  (PKMAP_BASE + ((nr) << PAGE_SHIFT))
+
+extern void * kmap_high(struct page *page);
+extern void kunmap_high(struct page *page);
+
+extern void *kmap(struct page *page);
+extern void kunmap(struct page *page);
+extern void *kmap_atomic(struct page *page);
+extern void __kunmap_atomic(void *kvaddr);
+extern void *kmap_atomic_pfn(unsigned long pfn);
+extern struct page *kmap_atomic_to_page(void *ptr);
+
+#define flush_cache_kmaps() do {} while(0)
+
+extern void kmap_init(void);
+
+#define kmap_prot PAGE_KERNEL
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_CSKY_HIGHMEM_H */
diff --git a/arch/csky/include/asm/mmu.h b/arch/csky/include/asm/mmu.h
new file mode 100644
index 0000000..db29c17
--- /dev/null
+++ b/arch/csky/include/asm/mmu.h
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_MMU_H
+#define __ASM_CSKY_MMU_H
+
+typedef struct {
+	unsigned long asid[NR_CPUS];
+	void *vdso;
+} mm_context_t;
+
+#endif /* __ASM_CSKY_MMU_H */
diff --git a/arch/csky/include/asm/page.h b/arch/csky/include/asm/page.h
new file mode 100644
index 0000000..cb4855c
--- /dev/null
+++ b/arch/csky/include/asm/page.h
@@ -0,0 +1,104 @@
+#ifndef __ASM_CSKY_PAGE_H
+#define __ASM_CSKY_PAGE_H
+
+#include <asm/setup.h>
+#include <asm/cache.h>
+#include <linux/const.h>
+
+/*
+ * PAGE_SHIFT determines the page size
+ */
+#define PAGE_SHIFT	12
+#define PAGE_SIZE	(_AC(1, UL) << PAGE_SHIFT)
+#define PAGE_MASK	(~(PAGE_SIZE - 1))
+#define THREAD_SIZE	(PAGE_SIZE * 2)
+#define THREAD_MASK	(~(THREAD_SIZE -1))
+#define THREAD_SHIFT	(PAGE_SHIFT + 1)
+
+/*
+ * NOTE: virtual isn't really correct, actually it should be the offset into the
+ * memory node, but we have no highmem, so that works for now.
+ * TODO: implement (fast) pfn<->pgdat_idx conversion functions, this makes lots
+ * of the shifts unnecessary.
+ */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/pfn.h>
+
+#define virt_to_pfn(kaddr)      (__pa(kaddr) >> PAGE_SHIFT)
+#define pfn_to_virt(pfn)        __va((pfn) << PAGE_SHIFT)
+
+#define virt_addr_valid(kaddr)  ((void *)(kaddr) >= (void *)PAGE_OFFSET && \
+                                 (void *)(kaddr) < high_memory)
+extern unsigned long min_low_pfn, max_pfn;
+#define pfn_valid(pfn)		((pfn >= min_low_pfn) && (pfn < max_pfn))
+
+extern void *memset(void *dest, int c, size_t l);
+extern void *memcpy (void *to, const void *from, size_t l);
+
+#define clear_page(page)        memset((page), 0, PAGE_SIZE)
+#define copy_page(to,from)      memcpy((to), (from), PAGE_SIZE)
+
+#define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
+
+struct page;
+
+#include <abi/page.h>
+
+struct vm_area_struct;
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte_low; } pte_t;
+#define pte_val(x)    ((x).pte_low)
+
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct page *pgtable_t;
+
+#define pgd_val(x)	((x).pgd)
+#define pgprot_val(x)	((x).pgprot)
+
+#define ptep_buddy(x)	((pte_t *)((unsigned long)(x) ^ sizeof(pte_t)))
+
+#define __pte(x)	((pte_t) { (x) } )
+#define __pgd(x)	((pgd_t) { (x) } )
+#define __pgprot(x)	((pgprot_t) { (x) } )
+
+#endif /* !__ASSEMBLY__ */
+
+#define PHYS_OFFSET		(CONFIG_RAM_BASE & ~(LOWMEM_LIMIT - 1))
+#define PHYS_OFFSET_OFFSET	(CONFIG_RAM_BASE & (LOWMEM_LIMIT - 1))
+#define ARCH_PFN_OFFSET		PFN_DOWN(CONFIG_RAM_BASE)
+
+#define	PAGE_OFFSET	0x80000000
+#define LOWMEM_LIMIT	0x20000000
+
+#define MASK_SSEG1(x) ((unsigned long)(x) & (~LOWMEM_LIMIT))
+
+#define __pa(x)		(MASK_SSEG1(x) - PAGE_OFFSET + PHYS_OFFSET)
+#define __va(x)		((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
+#define __pa_symbol(x)  __pa(RELOC_HIDE(MASK_SSEG1(x), 0))
+
+#define MAP_NR(x)	PFN_DOWN(MASK_SSEG1(x) - PAGE_OFFSET - PHYS_OFFSET_OFFSET)
+#define virt_to_page(x)		(mem_map + MAP_NR(x))
+
+#define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
+				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#define UNCACHE_ADDR(x)		((unsigned long)(x) | LOWMEM_LIMIT)
+
+/*
+ * main RAM and kernel working space are coincident at 0x80000000, but to make
+ * life more interesting, there's also an uncached virtual shadow at 0xb0000000
+ * - these mappings are fixed in the MMU
+ */
+
+#define pfn_to_kaddr(x)       __va(PFN_PHYS(x))
+
+#include <asm-generic/memory_model.h>
+#include <asm-generic/getorder.h>
+
+#endif /* __ASM_CSKY_PAGE_H */
diff --git a/arch/csky/include/asm/pgalloc.h b/arch/csky/include/asm/pgalloc.h
new file mode 100644
index 0000000..5df106f
--- /dev/null
+++ b/arch/csky/include/asm/pgalloc.h
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_PGALLOC_H
+#define __ASM_CSKY_PGALLOC_H
+
+#include <linux/highmem.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
+        pte_t *pte)
+{
+        set_pmd(pmd, __pmd(__pa(pte)));
+}
+
+static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
+        pgtable_t pte)
+{
+        set_pmd(pmd, __pmd(__pa(page_address(pte))));
+}
+
+#define pmd_pgtable(pmd) pmd_page(pmd)
+
+extern void pgd_init(unsigned long *p);
+
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+        unsigned long address)
+{
+        pte_t *pte;
+	unsigned long *kaddr, i;
+
+	pte = (pte_t *) __get_free_pages(GFP_KERNEL | __GFP_RETRY_MAYFAIL, PTE_ORDER);
+	kaddr = (unsigned long *)pte;
+	if (address & 0x80000000)
+		for(i=0; i<(PAGE_SIZE/4); i++)
+			*(kaddr + i) = 0x1;
+	else
+		clear_page(kaddr);
+
+        return pte;
+}
+
+static inline struct page *pte_alloc_one(struct mm_struct *mm,
+                                            unsigned long address)
+{
+	struct page *pte;
+	unsigned long *kaddr, i;
+
+        pte = alloc_pages(GFP_KERNEL | __GFP_RETRY_MAYFAIL, PTE_ORDER);
+        if (pte) {
+		kaddr = kmap_atomic(pte);
+		if (address & 0x80000000) {
+			for(i=0; i<(PAGE_SIZE/4); i++)
+				*(kaddr + i) = 0x1;
+		} else
+			clear_page(kaddr);
+		kunmap_atomic(kaddr);
+		pgtable_page_ctor(pte);
+        }
+        return pte;
+}
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+        free_pages((unsigned long)pte, PTE_ORDER);
+}
+
+static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
+{
+        pgtable_page_dtor(pte);
+        __free_pages(pte, PTE_ORDER);
+}
+
+static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+        free_pages((unsigned long)pgd, PGD_ORDER);
+}
+
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+        pgd_t *ret, *init;
+
+        ret = (pgd_t *) __get_free_pages(GFP_KERNEL, PGD_ORDER);
+        if (ret) {
+                init = pgd_offset(&init_mm, 0UL);
+                pgd_init((unsigned long *)ret);
+                memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
+                       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+#ifdef CONFIG_CPU_NEED_TLBSYNC
+		dcache_wb_range((unsigned int)ret, (unsigned int)(ret + PTRS_PER_PGD));
+#endif
+        }
+
+        return ret;
+}
+
+#define __pte_free_tlb(tlb,pte,address)                 \
+do {                                                    \
+        pgtable_page_dtor(pte);                         \
+        tlb_remove_page((tlb), pte);                    \
+} while (0)
+
+#define check_pgt_cache()               do {} while(0)
+
+extern void pagetable_init(void);
+
+#endif /* __ASM_CSKY_PGALLOC_H */
+
diff --git a/arch/csky/include/asm/pgtable.h b/arch/csky/include/asm/pgtable.h
new file mode 100644
index 0000000..fabdfcd
--- /dev/null
+++ b/arch/csky/include/asm/pgtable.h
@@ -0,0 +1,301 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_PGTABLE_H
+#define __ASM_CSKY_PGTABLE_H
+
+#include <asm/fixmap.h>
+#include <asm/addrspace.h>
+#include <abi/pgtable-bits.h>
+#include <asm-generic/pgtable-nopmd.h>
+
+/* PGDIR_SHIFT determines what a third-level page table entry can map */
+#define PGDIR_SHIFT		22
+#define PGDIR_SIZE		(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK		(~(PGDIR_SIZE-1))
+
+#define USER_PTRS_PER_PGD	(0x80000000UL/PGDIR_SIZE)
+#define FIRST_USER_ADDRESS	0UL
+
+#define VMALLOC_START		(0xc0008000)
+#ifdef CONFIG_HIGHMEM
+#define PKMAP_BASE		(0xfe000000UL)
+#define VMALLOC_END		(PKMAP_BASE - 2*PAGE_SIZE)
+#else
+#define VMALLOC_END		(FIXADDR_START - 2*PAGE_SIZE)
+#endif
+
+/*
+ * traditional two-level paging structure:
+ */
+#define PGD_ORDER	0
+#define PTE_ORDER	0
+
+#define PTRS_PER_PGD	((PAGE_SIZE << PGD_ORDER) / sizeof(pgd_t))
+#define PTRS_PER_PMD	1
+#define PTRS_PER_PTE	((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t))
+
+#define pte_ERROR(e) \
+	pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte_low)
+#define pgd_ERROR(e) \
+	pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+
+/* Find an entry in the third-level page table.. */
+#define __pte_offset_t(address) \
+	(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset_kernel(dir, address) \
+	(pmd_page_vaddr(*(dir)) + __pte_offset_t(address))
+#define pte_offset_map(dir, address) \
+	((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset_t(address))
+#define pmd_page(pmd)			(pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
+#define pte_clear(mm,addr,ptep)		set_pte((ptep), \
+					(((unsigned int)addr&0x80000000)?__pte(1):__pte(0)))
+#define pte_none(pte)			(!(pte_val(pte)&0xfffffffe))
+#define pte_present(pte)		(pte_val(pte) & _PAGE_PRESENT )
+#define pte_pfn(x)			((unsigned long)((x).pte_low >> PAGE_SHIFT))
+#define pfn_pte(pfn, prot)		__pte(((unsigned long long)(pfn) << PAGE_SHIFT) \
+						| pgprot_val(prot))
+
+#define __READABLE	(_PAGE_READ | _PAGE_VALID | _PAGE_ACCESSED)
+#define __WRITEABLE	(_PAGE_WRITE | _PAGE_DIRTY | _PAGE_MODIFIED)
+
+#define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_ACCESSED | _PAGE_MODIFIED | _CACHE_MASK)
+
+#define pte_unmap(pte) ((void)(pte))
+
+#define __swp_type(x)			(((x).val >> 4) & 0xff)
+#define __swp_offset(x)			((x).val >> 12)
+#define __swp_entry(type, offset)	((swp_entry_t) {((type) << 4) | ((offset) << 12) })
+#define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x)		((pte_t) { (x).val })
+
+#define pte_page(x)			pfn_to_page(pte_pfn(x))
+#define __mk_pte(page_nr,pgprot)	__pte(((page_nr) << PAGE_SHIFT) | pgprot_val(pgprot))
+
+/*
+ * CSKY can't do page protection for execute, and considers that the same like
+ * read. Also, write permissions imply read permissions. This is the closest
+ * we can get by reasonable means..
+ */
+#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _CACHE_CACHED)
+#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
+				_CACHE_CACHED)
+#define PAGE_COPY	__pgprot(_PAGE_PRESENT | _PAGE_READ | _CACHE_CACHED)
+#define PAGE_READONLY	__pgprot(_PAGE_PRESENT | _PAGE_READ | _CACHE_CACHED)
+#define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
+				_PAGE_GLOBAL | _CACHE_CACHED)
+#define PAGE_USERIO	__pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
+				_CACHE_CACHED)
+
+#define __P000	PAGE_NONE
+#define __P001	PAGE_READONLY
+#define __P010	PAGE_COPY
+#define __P011	PAGE_COPY
+#define __P100	PAGE_READONLY
+#define __P101	PAGE_READONLY
+#define __P110	PAGE_COPY
+#define __P111	PAGE_COPY
+
+#define __S000	PAGE_NONE
+#define __S001	PAGE_READONLY
+#define __S010	PAGE_SHARED
+#define __S011	PAGE_SHARED
+#define __S100	PAGE_READONLY
+#define __S101	PAGE_READONLY
+#define __S110	PAGE_SHARED
+#define __S111	PAGE_SHARED
+
+extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
+#define ZERO_PAGE(vaddr)	(virt_to_page(empty_zero_page))
+
+extern void load_pgd(unsigned long pg_dir);
+extern pte_t invalid_pte_table[PTRS_PER_PTE];
+
+static inline int pte_special(pte_t pte) { return 0; }
+static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+
+static inline void set_pte(pte_t *p, pte_t pte)
+{
+	*p = pte;
+#if defined(CONFIG_CPU_NEED_TLBSYNC)
+	dcache_wb_line((u32)p);
+#endif
+}
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+
+static inline pte_t *pmd_page_vaddr(pmd_t pmd)
+{
+	unsigned long ptr;
+
+	ptr = pmd_val(pmd);
+
+	return __va(ptr);
+}
+
+#define pmd_phys(pmd) pmd_val(pmd)
+
+static inline void set_pmd(pmd_t *p, pmd_t pmd)
+{
+	*p = pmd;
+#if defined(CONFIG_CPU_NEED_TLBSYNC)
+	dcache_wb_line((u32)p);
+#endif
+}
+
+
+static inline int pmd_none(pmd_t pmd)
+{
+	return pmd_val(pmd) == __pa(invalid_pte_table);
+}
+
+#define pmd_bad(pmd)	(pmd_val(pmd) & ~PAGE_MASK)
+
+static inline int pmd_present(pmd_t pmd)
+{
+        return (pmd_val(pmd) != __pa(invalid_pte_table));
+}
+
+static inline void pmd_clear(pmd_t *p)
+{
+        pmd_val(*p) = (__pa(invalid_pte_table));
+#if defined(CONFIG_CPU_NEED_TLBSYNC)
+        dcache_wb_line((u32)p);
+#endif
+}
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+static inline int pte_read(pte_t pte)
+{
+	return pte.pte_low & _PAGE_READ;
+}
+
+static inline int pte_write(pte_t pte)
+{
+	return (pte).pte_low & _PAGE_WRITE;
+}
+
+static inline int pte_dirty(pte_t pte)
+{
+	return (pte).pte_low & _PAGE_MODIFIED;
+}
+
+static inline int pte_young(pte_t pte)
+{
+	return (pte).pte_low & _PAGE_ACCESSED;
+}
+
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+	pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_DIRTY);
+	return pte;
+}
+
+static inline pte_t pte_mkclean(pte_t pte)
+{
+	pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_DIRTY);
+	return pte;
+}
+
+static inline pte_t pte_mkold(pte_t pte)
+{
+	pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_VALID);
+	return pte;
+}
+
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_WRITE;
+	if (pte_val(pte) & _PAGE_MODIFIED)
+		pte_val(pte) |= _PAGE_DIRTY;
+	return pte;
+}
+
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_MODIFIED;
+	if (pte_val(pte) & _PAGE_WRITE)
+		pte_val(pte) |= _PAGE_DIRTY;
+	return pte;
+}
+
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_ACCESSED;
+	if (pte_val(pte) & _PAGE_READ)
+		pte_val(pte) |= _PAGE_VALID;
+	return pte;
+}
+
+#define __pgd_offset(address)	pgd_index(address)
+#define __pud_offset(address)	(((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
+#define __pmd_offset(address)	(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address)	pgd_offset(&init_mm, address)
+
+#define pgd_index(address)	((address) >> PGDIR_SHIFT)
+
+/*
+ * Macro to make mark a page protection value as "uncacheable".  Note
+ * that "protection" is really a misnomer here as the protection value
+ * contains the memory attribute bits, dirty bits, and various other
+ * bits as well.
+ */
+#define pgprot_noncached pgprot_noncached
+
+static inline pgprot_t pgprot_noncached(pgprot_t _prot)
+{
+	unsigned long prot = pgprot_val(_prot);
+
+	prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED;
+
+	return __pgprot(prot);
+}
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+#define mk_pte(page, pgprot)    pfn_pte(page_to_pfn(page), (pgprot))
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	return __pte((pte_val(pte) & _PAGE_CHG_MASK) |
+		     (pgprot_val(newprot)));
+}
+
+/* to find an entry in a page-table-directory */
+static inline pgd_t *pgd_offset(struct mm_struct *mm, unsigned long address)
+{
+	return mm->pgd + pgd_index(address);
+}
+
+/* Find an entry in the third-level page table.. */
+static inline pte_t *pte_offset(pmd_t * dir, unsigned long address)
+{
+	return (pte_t *) (pmd_page_vaddr(*dir)) +
+		((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
+}
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+extern void paging_init(void);
+
+extern void show_jtlb_table(void);
+
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *pte);
+
+/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+#define kern_addr_valid(addr)	(1)
+
+/*
+ * No page table caches to initialise
+ */
+#define pgtable_cache_init()	do {} while(0)
+
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+	remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+#include <asm-generic/pgtable.h>
+
+#endif /* __ASM_CSKY_PGTABLE_H */
diff --git a/arch/csky/include/asm/segment.h b/arch/csky/include/asm/segment.h
new file mode 100644
index 0000000..cf1440c
--- /dev/null
+++ b/arch/csky/include/asm/segment.h
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_SEGMENT_H
+#define __ASM_CSKY_SEGMENT_H
+
+typedef struct {
+	unsigned long seg;
+} mm_segment_t;
+
+#define KERNEL_DS		((mm_segment_t) { 0xFFFFFFFF })
+#define get_ds()		KERNEL_DS
+
+#define USER_DS			((mm_segment_t) { 0x80000000UL })
+#define get_fs()		(current_thread_info()->addr_limit)
+#define set_fs(x)		(current_thread_info()->addr_limit = (x))
+#define segment_eq(a,b)		((a).seg == (b).seg)
+
+#endif /* __ASM_CSKY_SEGMENT_H */
diff --git a/arch/csky/include/asm/shmparam.h b/arch/csky/include/asm/shmparam.h
new file mode 100644
index 0000000..ecf7b65
--- /dev/null
+++ b/arch/csky/include/asm/shmparam.h
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_SHMPARAM_H
+#define __ASM_CSKY_SHMPARAM_H
+
+#define SHMLBA	(4 * PAGE_SIZE)
+
+#define __ARCH_FORCE_SHMLBA
+
+#endif /* __ASM_CSKY_SHMPARAM_H */
diff --git a/arch/csky/mm/dma-mapping.c b/arch/csky/mm/dma-mapping.c
new file mode 100644
index 0000000..f05e4b6
--- /dev/null
+++ b/arch/csky/mm/dma-mapping.c
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/types.h>
+#include <linux/highmem.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/io.h>
+#include <linux/cache.h>
+#include <asm/cache.h>
+
+static void *csky_dma_alloc(
+	struct device *dev,
+	size_t size,
+	dma_addr_t *dma_handle,
+	gfp_t gfp,
+	unsigned long attrs
+	)
+{
+	unsigned long ret;
+	void * vaddr;
+
+	if (DMA_ATTR_NON_CONSISTENT & attrs)
+		panic("csky %s panic DMA_ATTR_NON_CONSISTENT.\n", __func__);
+
+	ret =  __get_free_pages((gfp | __GFP_NORETRY) & (~__GFP_HIGHMEM), get_order(size));
+	if (!ret) {
+		pr_err("csky %s no more free pages, %ld.\n", __func__, ret);
+		return NULL;
+	}
+
+	memset((void *)ret, 0, size);
+
+	dma_wbinv_range(ret, ret + size);
+
+	*dma_handle = virt_to_phys((void*)ret);
+
+	vaddr = (void *) UNCACHE_ADDR(ret);
+
+	return vaddr;
+}
+
+static void csky_dma_free(
+	struct device *dev,
+	size_t size,
+	void *vaddr,
+	dma_addr_t dma_handle,
+	unsigned long attrs
+	)
+{
+	unsigned long addr = (unsigned long)phys_to_virt(dma_handle);
+
+	free_pages(addr, get_order(size));
+}
+
+static void __dma_sync(
+	void *va,
+	struct page *page,
+	unsigned long offset,
+	size_t size,
+	enum dma_data_direction direction)
+{
+	unsigned long vaddr = (unsigned long) va;
+
+	if (va == NULL && PageHighMem(page))
+		vaddr = (unsigned long) kmap_atomic(page);
+
+	switch (direction) {
+	case DMA_TO_DEVICE:
+		dma_wb_range(vaddr + offset, vaddr + offset + size);
+		break;
+	case DMA_FROM_DEVICE:
+	case DMA_BIDIRECTIONAL:
+		dma_wbinv_range(vaddr + offset, vaddr + offset + size);
+		break;
+	default:
+		BUG();
+	}
+
+	if (va == NULL && PageHighMem(page))
+		kunmap_atomic((void *) vaddr);
+}
+
+static dma_addr_t csky_dma_map_page(
+	struct device *dev,
+	struct page *page,
+	unsigned long offset,
+	size_t size,
+	enum dma_data_direction direction,
+	unsigned long attrs
+	)
+{
+	__dma_sync(page_address(page), page, offset, size, direction);
+
+	return page_to_phys(page) + offset;
+}
+
+static void csky_dma_unmap_page(
+	struct device *dev,
+	dma_addr_t handle,
+	size_t size,
+	enum dma_data_direction direction,
+	unsigned long attrs
+	)
+{
+	unsigned long offset = handle & ~PAGE_MASK;
+	struct page *page = pfn_to_page(__phys_to_pfn(handle));
+
+	__dma_sync(page_address(page), page, offset, size, direction);
+}
+
+static int csky_dma_map_sg(
+	struct device *dev,
+	struct scatterlist *sglist,
+	int nelems,
+	enum dma_data_direction dir,
+	unsigned long attrs
+	)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(sglist, sg, nelems, i)
+		sg->dma_address = csky_dma_map_page(dev, sg_page(sg), sg->offset, sg->length, dir, attrs);
+
+	return nelems;
+}
+
+static void csky_dma_unmap_sg(
+	struct device *dev,
+	struct scatterlist *sglist,
+	int nelems,
+	enum dma_data_direction dir,
+	unsigned long attrs
+	)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(sglist, sg, nelems, i)
+		csky_dma_unmap_page(dev, sg_dma_address(sg), sg_dma_len(sg), dir, attrs);
+}
+
+static void csky_dma_sync_single_for_all(
+	struct device *dev,
+	dma_addr_t handle,
+	size_t size,
+	enum dma_data_direction dir
+	)
+{
+	unsigned int offset = handle & ~PAGE_MASK;
+	struct page *page = pfn_to_page(__phys_to_pfn(handle));
+
+	__dma_sync(page_address(page), page, offset, size, dir);
+}
+
+static void csky_dma_sync_sg_for_cpu(
+	struct device *dev,
+	struct scatterlist *sglist,
+	int nelems,
+	enum dma_data_direction direction
+	)
+{
+	int i;
+	struct scatterlist *sg;
+
+	for_each_sg(sglist, sg, nelems, i)
+		__dma_sync(page_address(sg_page(sg)), sg_page(sg), 0,
+			   sg->length, direction);
+}
+
+static void csky_dma_sync_sg_for_device(
+	struct device *dev,
+	struct scatterlist *sglist,
+	int nelems,
+	enum dma_data_direction direction
+	)
+{
+	int i;
+	struct scatterlist *sg;
+
+	for_each_sg(sglist, sg, nelems, i)
+		__dma_sync(page_address(sg_page(sg)), sg_page(sg), 0,
+			   sg->length, direction);
+}
+
+int csky_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+	return 0;
+}
+
+int csky_dma_supported(struct device *dev, u64 mask)
+{
+	return DMA_BIT_MASK(32);
+}
+
+struct dma_map_ops csky_dma_map_ops = {
+	.alloc			= csky_dma_alloc,
+	.free			= csky_dma_free,
+	.mmap			= NULL,
+	.get_sgtable		= NULL,
+	.map_page		= csky_dma_map_page,
+	.unmap_page		= csky_dma_unmap_page,
+
+	.map_sg			= csky_dma_map_sg,
+	.unmap_sg		= csky_dma_unmap_sg,
+	.sync_single_for_cpu	= csky_dma_sync_single_for_all,
+	.sync_single_for_device	= csky_dma_sync_single_for_all,
+	.sync_sg_for_cpu	= csky_dma_sync_sg_for_cpu,
+	.sync_sg_for_device	= csky_dma_sync_sg_for_device,
+
+	.mapping_error		= csky_dma_mapping_error,
+	.dma_supported		= csky_dma_supported,
+};
+EXPORT_SYMBOL(csky_dma_map_ops);
+
diff --git a/arch/csky/mm/highmem.c b/arch/csky/mm/highmem.c
new file mode 100644
index 0000000..a979b2d
--- /dev/null
+++ b/arch/csky/mm/highmem.c
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/module.h>
+#include <linux/highmem.h>
+#include <linux/smp.h>
+#include <linux/bootmem.h>
+#include <asm/fixmap.h>
+#include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
+
+static pte_t *kmap_pte;
+
+unsigned long highstart_pfn, highend_pfn;
+
+void *kmap(struct page *page)
+{
+	void *addr;
+
+	might_sleep();
+	if (!PageHighMem(page))
+		return page_address(page);
+	addr = kmap_high(page);
+        flush_tlb_one((unsigned long)addr);
+
+	return addr;
+}
+EXPORT_SYMBOL(kmap);
+
+void kunmap(struct page *page)
+{
+	BUG_ON(in_interrupt());
+	if (!PageHighMem(page))
+		return;
+	kunmap_high(page);
+}
+EXPORT_SYMBOL(kunmap);
+
+/*
+ * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because
+ * no global lock is needed and because the kmap code must perform a global TLB
+ * invalidation when the kmap pool wraps.
+ *
+ * However when holding an atomic kmap is is not legal to sleep, so atomic
+ * kmaps are appropriate for short, tight code paths only.
+ */
+
+void *kmap_atomic(struct page *page)
+{
+	unsigned long vaddr;
+	int idx, type;
+
+	/* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
+	pagefault_disable();
+	if (!PageHighMem(page))
+		return page_address(page);
+
+	type = kmap_atomic_idx_push();
+	idx = type + KM_TYPE_NR*smp_processor_id();
+	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+#ifdef CONFIG_DEBUG_HIGHMEM
+	BUG_ON(!pte_none(*(kmap_pte - idx)));
+#endif
+	set_pte(kmap_pte-idx, mk_pte(page, PAGE_KERNEL));
+	flush_tlb_one((unsigned long)vaddr);
+
+	return (void*) vaddr;
+}
+EXPORT_SYMBOL(kmap_atomic);
+
+void __kunmap_atomic(void *kvaddr)
+{
+	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
+	int type;
+	
+	if (vaddr < FIXADDR_START) {
+	    pagefault_enable();
+	    return;
+	}
+	
+	type = kmap_atomic_idx();
+#ifdef CONFIG_DEBUG_HIGHMEM
+	int idx = type + KM_TYPE_NR * smp_processor_id();
+
+	BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
+
+	/*
+	 * force other mappings to Oops if they'll try to access
+	 * this pte without first remap it
+	 */
+	pte_clear(&init_mm, vaddr, kmap_pte-idx);
+	flush_tlb_one(vaddr);
+#endif
+
+	kmap_atomic_idx_pop();
+	pagefault_enable();
+}
+EXPORT_SYMBOL(__kunmap_atomic);
+
+/*
+ * This is the same as kmap_atomic() but can map memory that doesn't
+ * have a struct page associated with it.
+ */
+void *kmap_atomic_pfn(unsigned long pfn)
+{
+	unsigned long vaddr;
+	int idx, type;
+
+	pagefault_disable();
+
+	type = kmap_atomic_idx_push();
+	idx = type + KM_TYPE_NR*smp_processor_id();
+	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+	set_pte(kmap_pte-idx, pfn_pte(pfn, PAGE_KERNEL));
+	flush_tlb_one(vaddr);
+
+	return (void*) vaddr;
+}
+
+struct page *kmap_atomic_to_page(void *ptr)
+{
+	unsigned long idx, vaddr = (unsigned long)ptr;
+	pte_t *pte;
+
+	if (vaddr < FIXADDR_START)
+		return virt_to_page(ptr);
+
+	idx = virt_to_fix(vaddr);
+	pte = kmap_pte - (idx - FIX_KMAP_BEGIN);
+	return pte_page(*pte);
+}
+
+static void __init fixrange_init (unsigned long start, unsigned long end,
+                   pgd_t *pgd_base)
+{
+#ifdef CONFIG_HIGHMEM
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+	int i, j, k;
+	unsigned long vaddr;
+
+	vaddr = start;
+	i = __pgd_offset(vaddr);
+	j = __pud_offset(vaddr);
+	k = __pmd_offset(vaddr);
+	pgd = pgd_base + i;
+
+	for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
+		pud = (pud_t *)pgd;
+		for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) {
+			pmd = (pmd_t *)pud;
+			for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) {
+				if (pmd_none(*pmd)) {
+					pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+					set_pmd(pmd, __pmd(__pa(pte)));
+					BUG_ON(pte != pte_offset_kernel(pmd, 0));
+				}
+				vaddr += PMD_SIZE;
+			}
+			k = 0;
+		}
+		j = 0;
+	}
+#endif
+}
+
+void __init fixaddr_kmap_pages_init(void)
+{
+	unsigned long vaddr;
+	pgd_t *pgd_base;
+#ifdef CONFIG_HIGHMEM
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pud_t *pud;
+	pte_t *pte;
+#endif
+	pgd_base = swapper_pg_dir;
+
+	/*
+	 * Fixed mappings:
+	 */
+	vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+	fixrange_init(vaddr, 0, pgd_base);
+
+#ifdef CONFIG_HIGHMEM
+	/*
+	 * Permanent kmaps:
+	 */
+	vaddr = PKMAP_BASE;
+	fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
+
+	pgd = swapper_pg_dir + __pgd_offset(vaddr);
+	pud = (pud_t *)pgd;
+	pmd = pmd_offset(pud, vaddr);
+	pte = pte_offset_kernel(pmd, vaddr);
+	pkmap_page_table = pte;
+#endif
+}
+
+void __init kmap_init(void)
+{
+	unsigned long kmap_vstart;
+
+	fixaddr_kmap_pages_init();
+
+	/* cache the first kmap pte */
+	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
+	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
+}
diff --git a/arch/csky/mm/init.c b/arch/csky/mm/init.c
new file mode 100644
index 0000000..37038d1
--- /dev/null
+++ b/arch/csky/mm/init.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/bug.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/pagemap.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
+#include <linux/memblock.h>
+#include <linux/swap.h>
+#include <linux/proc_fs.h>
+#include <linux/pfn.h>
+
+#include <asm/setup.h>
+#include <asm/cachectl.h>
+#include <asm/dma.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/sections.h>
+#include <asm/tlb.h>
+
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
+pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned_bss;
+unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] __page_aligned_bss;
+
+void __init mem_init(void)
+{
+#ifdef CONFIG_HIGHMEM
+	unsigned long tmp;
+	max_mapnr = highend_pfn;
+#else
+	max_mapnr = max_low_pfn;
+#endif
+	high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
+
+	free_all_bootmem();
+
+#ifdef CONFIG_HIGHMEM
+	for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) {
+		struct page *page = pfn_to_page(tmp);
+
+		/* FIXME not sure about */
+		if (!memblock_is_reserved(tmp << PAGE_SHIFT))
+			free_highmem_page(page);
+	}
+#endif
+	mem_init_print_info(NULL);
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+	if (start < end)
+		pr_info("Freeing initrd memory: %ldk freed\n",
+                     (end - start) >> 10);
+
+	for (; start < end; start += PAGE_SIZE) {
+	ClearPageReserved(virt_to_page(start));
+	init_page_count(virt_to_page(start));
+	free_page(start);
+	totalram_pages++;
+    }
+}
+#endif
+
+extern char __init_begin[], __init_end[];
+extern void __init prom_free_prom_memory(void);
+
+void free_initmem(void)
+{
+	unsigned long addr;
+
+	addr = (unsigned long) &__init_begin;
+	while (addr < (unsigned long) &__init_end) {
+	        ClearPageReserved(virt_to_page(addr));
+	        init_page_count(virt_to_page(addr));
+	        free_page(addr);
+	        totalram_pages++;
+	        addr += PAGE_SIZE;
+	}
+	pr_info("Freeing unused kernel memory: %dk freed\n",
+	        ((unsigned int)&__init_end - (unsigned int)&__init_begin) >> 10);
+}
+
+void pgd_init(unsigned long *p)
+{
+	int i;
+	for (i = 0; i<PTRS_PER_PGD; i++)
+		p[i] = __pa(invalid_pte_table);
+}
+
+void __init pre_mmu_init(void)
+{
+	/* Setup mmu as coprocessor */
+	select_mmu_cp();
+
+	/*
+	 * Setup page-table and enable TLB-hardrefill
+	 */
+	flush_tlb_all();
+	pgd_init((unsigned long *)swapper_pg_dir);
+	TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir);
+
+#ifdef CONFIG_CPU_HAS_TLBI
+	TLBMISS_HANDLER_SETUP_PGD_KERNEL(swapper_pg_dir);
+#endif
+
+	asid_cache(smp_processor_id()) = ASID_FIRST_VERSION;
+
+	/* Setup page mask to 4k */
+	write_mmu_pagemask(0);
+}
diff --git a/arch/csky/mm/ioremap.c b/arch/csky/mm/ioremap.c
new file mode 100644
index 0000000..000d3ce
--- /dev/null
+++ b/arch/csky/mm/ioremap.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/export.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/io.h>
+
+#include <asm/pgtable.h>
+
+void __iomem *ioremap(phys_addr_t addr, size_t size)
+{
+	phys_addr_t last_addr;
+	unsigned long offset, vaddr;
+	struct vm_struct *area;
+	pgprot_t prot;
+
+	last_addr = addr + size - 1;
+	if (!size || last_addr < addr) {
+		return NULL;
+	}
+
+	offset = addr & (~PAGE_MASK);
+	addr &= PAGE_MASK;
+	size = PAGE_ALIGN(size + offset);
+
+	area = get_vm_area_caller(size, VM_ALLOC, __builtin_return_address(0));
+	if (!area) {
+		return NULL;
+	}
+	vaddr = (unsigned long)area->addr;
+
+	prot = __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE |
+			_PAGE_GLOBAL | _CACHE_UNCACHED);
+
+	if (ioremap_page_range(vaddr, vaddr + size, addr, prot)) {
+		free_vm_area(area);
+		return NULL;
+	}
+
+	return (void __iomem *)(vaddr + offset);
+}
+EXPORT_SYMBOL(ioremap);
+
+void iounmap(void __iomem *addr)
+{
+	vunmap((void *)((unsigned long)addr & PAGE_MASK));
+}
+EXPORT_SYMBOL(iounmap);
+
-- 
2.7.4


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

* [PATCH V2 08/19] csky: Process management and Signal
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (6 preceding siblings ...)
  2018-07-01 17:30 ` [PATCH V2 07/19] csky: MMU and page table management Guo Ren
@ 2018-07-01 17:30 ` Guo Ren
  2018-07-01 17:30 ` [PATCH V2 09/19] csky: VDSO and rt_sigreturn Guo Ren
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/abiv2/fpu.c                   | 242 ++++++++++++++++++++++
 arch/csky/abiv2/inc/abi/fpu.h           | 219 ++++++++++++++++++++
 arch/csky/include/asm/mmu_context.h     | 158 ++++++++++++++
 arch/csky/include/asm/processor.h       | 123 +++++++++++
 arch/csky/include/asm/thread_info.h     |  73 +++++++
 arch/csky/include/uapi/asm/sigcontext.h |  13 ++
 arch/csky/kernel/process.c              | 134 ++++++++++++
 arch/csky/kernel/signal.c               | 350 ++++++++++++++++++++++++++++++++
 arch/csky/kernel/time.c                 |  12 ++
 9 files changed, 1324 insertions(+)
 create mode 100644 arch/csky/abiv2/fpu.c
 create mode 100644 arch/csky/abiv2/inc/abi/fpu.h
 create mode 100644 arch/csky/include/asm/mmu_context.h
 create mode 100644 arch/csky/include/asm/processor.h
 create mode 100644 arch/csky/include/asm/thread_info.h
 create mode 100644 arch/csky/include/uapi/asm/sigcontext.h
 create mode 100644 arch/csky/kernel/process.c
 create mode 100644 arch/csky/kernel/signal.c
 create mode 100644 arch/csky/kernel/time.c

diff --git a/arch/csky/abiv2/fpu.c b/arch/csky/abiv2/fpu.c
new file mode 100644
index 0000000..330a908
--- /dev/null
+++ b/arch/csky/abiv2/fpu.c
@@ -0,0 +1,242 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/ptrace.h>
+#include <linux/uaccess.h>
+#include <abi/reg_ops.h>
+
+#define MTCR_MASK	0xFC00FFE0
+#define MFCR_MASK	0xFC00FFE0
+#define MTCR_DIST	0xC0006420
+#define MFCR_DIST	0xC0006020
+
+void __init init_fpu(void)
+{
+	mtcr("cr<1, 2>", 0);
+}
+
+/*
+ * fpu_libc_helper() is to help libc to excute:
+ *  - mfcr %a, cr<1, 2>
+ *  - mfcr %a, cr<2, 2>
+ *  - mtcr %a, cr<1, 2>
+ *  - mtcr %a, cr<2, 2>
+ */
+int fpu_libc_helper(struct pt_regs * regs)
+{
+	int fault;
+	unsigned long instrptr, regx = 0;
+	unsigned long index = 0, tmp = 0;
+	unsigned long tinstr = 0;
+	u16 instr_hi, instr_low;
+
+	instrptr = instruction_pointer(regs);
+	if (instrptr & 1) return 0;
+
+	fault = __get_user(instr_low, (u16 *)instrptr);
+	if (fault) return 0;
+
+	fault = __get_user(instr_hi, (u16 *)(instrptr + 2));
+	if (fault) return 0;
+
+	tinstr = instr_hi | ((unsigned long)instr_low << 16);
+
+	if (((tinstr >> 21) & 0x1F) != 2) return 0;
+
+	if ((tinstr & MTCR_MASK) == MTCR_DIST)
+	{
+		index = (tinstr >> 16) & 0x1F;
+		if(index > 13) return 0;
+
+		tmp = tinstr & 0x1F;
+		if (tmp > 2) return 0;
+
+		regx =  *(&regs->a0 + index);
+
+		if(tmp == 1)
+			mtcr("cr<1, 2>", regx);
+		else if (tmp == 2)
+			mtcr("cr<2, 2>", regx);
+		else
+			return 0;
+
+		regs->pc +=4;
+		return 1;
+	}
+
+	if ((tinstr & MFCR_MASK) == MFCR_DIST) {
+		index = tinstr & 0x1F;
+		if(index > 13) return 0;
+
+		tmp = ((tinstr >> 16) & 0x1F);
+		if (tmp > 2) return 0;
+
+		if (tmp == 1)
+			regx = mfcr("cr<1, 2>");
+		else if (tmp == 2)
+			regx = mfcr("cr<2, 2>");
+		else
+			return 0;
+
+		*(&regs->a0 + index) = regx;
+
+		regs->pc +=4;
+		return 1;
+	}
+
+	return 0;
+}
+
+void fpu_fpe(struct pt_regs * regs)
+{
+	int sig;
+	unsigned int fesr;
+	siginfo_t info;
+	asm volatile("mfcr %0, cr<2, 2>":"=r"(fesr));
+
+	if(fesr & FPE_ILLE){
+		info.si_code = ILL_ILLOPC;
+		sig = SIGILL;
+	}
+	else if(fesr & FPE_IDC){
+		info.si_code = ILL_ILLOPN;
+		sig = SIGILL;
+	}
+	else if(fesr & FPE_FEC){
+		sig = SIGFPE;
+		if(fesr & FPE_IOC){
+			info.si_code = FPE_FLTINV;
+		}
+		else if(fesr & FPE_DZC){
+			info.si_code = FPE_FLTDIV;
+		}
+		else if(fesr & FPE_UFC){
+			info.si_code = FPE_FLTUND;
+		}
+		else if(fesr & FPE_OFC){
+			info.si_code = FPE_FLTOVF;
+		}
+		else if(fesr & FPE_IXC){
+			info.si_code = FPE_FLTRES;
+		}
+		else {
+			info.si_code = NSIGFPE;
+		}
+	}
+	else {
+		info.si_code = NSIGFPE;
+		sig = SIGFPE;
+	}
+	info.si_signo = SIGFPE;
+	info.si_errno = 0;
+	info.si_addr = (void *)regs->pc;
+	force_sig_info(sig, &info, current);
+}
+
+#define FMFVR_FPU_REGS(vrx, vry)	\
+	"fmfvrl %0, "#vrx" \n"		\
+	"fmfvrh %1, "#vrx" \n"		\
+	"fmfvrl %2, "#vry" \n"		\
+	"fmfvrh %3, "#vry" \n"
+
+#define FMTVR_FPU_REGS(vrx, vry)	\
+	"fmtvrl "#vrx", %0 \n"		\
+	"fmtvrh "#vrx", %1 \n"		\
+	"fmtvrl "#vry", %2 \n"		\
+	"fmtvrh "#vry", %3 \n"
+
+#define STW_FPU_REGS(a, b, c, d)	\
+	"stw    %0, (%4, "#a") \n"	\
+	"stw    %1, (%4, "#b") \n"	\
+	"stw    %2, (%4, "#c") \n"	\
+	"stw    %3, (%4, "#d") \n"
+
+#define LDW_FPU_REGS(a, b, c, d)	\
+	"ldw    %0, (%4, "#a") \n"	\
+	"ldw    %1, (%4, "#b") \n"	\
+	"ldw    %2, (%4, "#c") \n"	\
+	"ldw    %3, (%4, "#d") \n"
+
+void save_to_user_fp(struct user_fp *user_fp)
+{
+	unsigned long flg;
+	unsigned long tmp1, tmp2, tmp3, tmp4;
+	unsigned long *fpregs;
+
+	local_save_flags(flg);
+
+
+	asm volatile(
+		"mfcr    %0, cr<1, 2> \n"
+		"mfcr    %1, cr<2, 2> \n"
+		:"=r"(tmp1),"=r"(tmp2));
+
+	user_fp->fcr = tmp1;
+	user_fp->fesr = tmp2;
+
+	fpregs = &user_fp->vr[0];
+	asm volatile(
+		FMFVR_FPU_REGS(vr0, vr1)
+		STW_FPU_REGS(0, 4, 16, 20)
+		FMFVR_FPU_REGS(vr2, vr3)
+		STW_FPU_REGS(32, 36, 48, 52)
+		FMFVR_FPU_REGS(vr4, vr5)
+		STW_FPU_REGS(64, 68, 80, 84)
+		FMFVR_FPU_REGS(vr6, vr7)
+		STW_FPU_REGS(96, 100, 112, 116)
+		"addi    %4, 128\n"
+		FMFVR_FPU_REGS(vr8, vr9)
+		STW_FPU_REGS(0, 4, 16, 20)
+		FMFVR_FPU_REGS(vr10, vr11)
+		STW_FPU_REGS(32, 36, 48, 52)
+		FMFVR_FPU_REGS(vr12, vr13)
+		STW_FPU_REGS(64, 68, 80, 84)
+		FMFVR_FPU_REGS(vr14, vr15)
+		STW_FPU_REGS(96, 100, 112, 116)
+		:"=a"(tmp1),"=a"(tmp2),"=a"(tmp3),
+		"=a"(tmp4),"+a"(fpregs));
+
+	local_irq_restore(flg);
+}
+
+void restore_from_user_fp(struct user_fp *user_fp)
+{
+	unsigned long flg;
+	unsigned long tmp1, tmp2, tmp3, tmp4;
+	unsigned long *fpregs;
+
+	local_irq_save(flg);
+
+	tmp1 = user_fp->fcr;
+	tmp2 = user_fp->fesr;
+
+	asm volatile(
+		"mtcr   %0, cr<1, 2>\n"
+		"mtcr   %1, cr<2, 2>\n"
+		::"r"(tmp1), "r"(tmp2));
+
+	fpregs = &user_fp->vr[0];
+	asm volatile(
+		LDW_FPU_REGS(0, 4, 16, 20)
+		FMTVR_FPU_REGS(vr0, vr1)
+		LDW_FPU_REGS(32, 36, 48, 52)
+		FMTVR_FPU_REGS(vr2, vr3)
+		LDW_FPU_REGS(64, 68, 80, 84)
+		FMTVR_FPU_REGS(vr4, vr5)
+		LDW_FPU_REGS(96, 100, 112, 116)
+		FMTVR_FPU_REGS(vr6, vr7)
+		"addi   %4, 128\n"
+		LDW_FPU_REGS(0, 4, 16, 20)
+		FMTVR_FPU_REGS(vr8, vr9)
+		LDW_FPU_REGS(32, 36, 48, 52)
+		FMTVR_FPU_REGS(vr10, vr11)
+		LDW_FPU_REGS(64, 68, 80, 84)
+		FMTVR_FPU_REGS(vr12, vr13)
+		LDW_FPU_REGS(96, 100, 112, 116)
+		FMTVR_FPU_REGS(vr14, vr15)
+		:"=a"(tmp1),"=a"(tmp2),"=a"(tmp3),
+		"=a"(tmp4),"+a"(fpregs));
+
+	local_irq_restore(flg);
+}
+
+
diff --git a/arch/csky/abiv2/inc/abi/fpu.h b/arch/csky/abiv2/inc/abi/fpu.h
new file mode 100644
index 0000000..eaa0f1c
--- /dev/null
+++ b/arch/csky/abiv2/inc/abi/fpu.h
@@ -0,0 +1,219 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_FPU_H
+#define __ASM_CSKY_FPU_H
+
+#ifndef __ASSEMBLY__ /* C source */
+
+#include <asm/sigcontext.h>
+#include <asm/ptrace.h>
+
+int fpu_libc_helper(struct pt_regs *regs);
+void fpu_fpe(struct pt_regs *regs);
+void __init init_fpu(void);
+
+void save_to_user_fp(struct user_fp *user_fp);
+void restore_from_user_fp(struct user_fp *user_fp);
+
+/*
+ * Define the fesr bit for fpe handle.
+ */
+#define  FPE_ILLE  (1 << 16)    /* Illegal instruction  */
+#define  FPE_FEC   (1 << 7)     /* Input float-point arithmetic exception */
+#define  FPE_IDC   (1 << 5)     /* Input denormalized exception */
+#define  FPE_IXC   (1 << 4)     /* Inexact exception */
+#define  FPE_UFC   (1 << 3)     /* Underflow exception */
+#define  FPE_OFC   (1 << 2)     /* Overflow exception */
+#define  FPE_DZC   (1 << 1)     /* Divide by zero exception */
+#define  FPE_IOC   (1 << 0)     /* Invalid operation exception */
+#define  FPE_REGULAR_EXCEPTION (FPE_IXC | FPE_UFC | FPE_OFC | FPE_DZC | FPE_IOC)
+
+#ifdef CONFIG_OPEN_FPU_IDE
+#define IDE_STAT   (1 << 5)
+#else
+#define IDE_STAT   0
+#endif
+
+#ifdef CONFIG_OPEN_FPU_IXE
+#define IXE_STAT   (1 << 4)
+#else
+#define IXE_STAT   0
+#endif
+
+#ifdef CONFIG_OPEN_FPU_UFE
+#define UFE_STAT   (1 << 3)
+#else
+#define UFE_STAT   0
+#endif
+
+#ifdef CONFIG_OPEN_FPU_OFE
+#define OFE_STAT   (1 << 2)
+#else
+#define OFE_STAT   0
+#endif
+
+#ifdef CONFIG_OPEN_FPU_DZE
+#define DZE_STAT   (1 << 1)
+#else
+#define DZE_STAT   0
+#endif
+
+#ifdef CONFIG_OPEN_FPU_IOE
+#define IOE_STAT   (1 << 0)
+#else
+#define IOE_STAT   0
+#endif
+
+#else  /* __ASSEMBLY__ */
+
+#include <asm/asm-offsets.h>
+
+.macro  FPU_SAVE_REGS
+	/* Save FPU control regs task struct */
+	mfcr     r7, cr<1, 2>
+	mfcr     r6, cr<2, 2>
+	stw      r7, (a3, THREAD_FCR)
+	stw      r6, (a3, THREAD_FESR)
+	/* Save FPU general regs task struct */
+	fmfvrl   r6, vr0
+	fmfvrh   r7, vr0
+	fmfvrl   r8, vr1
+	fmfvrh   r9, vr1
+	stw      r6, (a3, THREAD_FPREG + 0)  /* In aviv2: stw can load longer */
+	stw      r7, (a3, THREAD_FPREG + 4)
+	stw      r8, (a3, THREAD_FPREG + 16)
+	stw      r9, (a3, THREAD_FPREG + 20)
+	fmfvrl   r6, vr2
+	fmfvrh   r7, vr2
+	fmfvrl   r8, vr3
+	fmfvrh   r9, vr3
+	stw      r6, (a3, THREAD_FPREG + 32)
+	stw      r7, (a3, THREAD_FPREG + 36)
+	stw      r8, (a3, THREAD_FPREG + 48)
+	stw      r9, (a3, THREAD_FPREG + 52)
+	fmfvrl   r6, vr4
+	fmfvrh   r7, vr4
+	fmfvrl   r8, vr5
+	fmfvrh   r9, vr5
+	stw      r6, (a3, THREAD_FPREG + 64)
+	stw      r7, (a3, THREAD_FPREG + 68)
+	stw      r8, (a3, THREAD_FPREG + 80)
+	stw      r9, (a3, THREAD_FPREG + 84)
+	fmfvrl   r6, vr6
+	fmfvrh   r7, vr6
+	fmfvrl   r8, vr7
+	fmfvrh   r9, vr7
+	stw      r6, (a3, THREAD_FPREG + 96)
+	stw      r7, (a3, THREAD_FPREG + 100)
+	stw      r8, (a3, THREAD_FPREG + 112)
+	stw      r9, (a3, THREAD_FPREG + 116)
+	fmfvrl   r6, vr8
+	fmfvrh   r7, vr8
+	fmfvrl   r8, vr9
+	fmfvrh   r9, vr9
+	stw      r6, (a3, THREAD_FPREG + 128)
+	stw      r7, (a3, THREAD_FPREG + 132)
+	stw      r8, (a3, THREAD_FPREG + 144)
+	stw      r9, (a3, THREAD_FPREG + 148)
+	fmfvrl   r6, vr10
+	fmfvrh   r7, vr10
+	fmfvrl   r8, vr11
+	fmfvrh   r9, vr11
+	stw      r6, (a3, THREAD_FPREG + 160)
+	stw      r7, (a3, THREAD_FPREG + 164)
+	stw      r8, (a3, THREAD_FPREG + 176)
+	stw      r9, (a3, THREAD_FPREG + 180)
+	fmfvrl   r6, vr12
+	fmfvrh   r7, vr12
+	fmfvrl   r8, vr13
+	fmfvrh   r9, vr13
+	stw      r6, (a3, THREAD_FPREG + 192)
+	stw      r7, (a3, THREAD_FPREG + 196)
+	stw      r8, (a3, THREAD_FPREG + 208)
+	stw      r9, (a3, THREAD_FPREG + 212)
+	fmfvrl   r6, vr14
+	fmfvrh   r7, vr14
+	fmfvrl   r8, vr15
+	fmfvrh   r9, vr15
+	stw      r6, (a3, THREAD_FPREG + 224)
+	stw      r7, (a3, THREAD_FPREG + 228)
+	stw      r8, (a3, THREAD_FPREG + 240)
+	stw      r9, (a3, THREAD_FPREG + 244)
+.endm
+
+.macro  FPU_RESTORE_REGS
+	/* Save FPU control regs task struct */
+	ldw      r6, (a3, THREAD_FCR)
+	ldw      r7, (a3, THREAD_FESR)
+	mtcr     r6, cr<1, 2>
+	mtcr     r7, cr<2, 2>
+	/* restore FPU general regs task struct */
+	ldw      r6, (a3, THREAD_FPREG + 0)
+	ldw      r7, (a3, THREAD_FPREG + 4)
+	ldw      r8, (a3, THREAD_FPREG + 16)
+	ldw      r9, (a3, THREAD_FPREG + 20)
+	fmtvrl   vr0, r6
+	fmtvrh   vr0, r7
+	fmtvrl   vr1, r8
+	fmtvrh   vr1, r9
+	ldw      r6, (a3, THREAD_FPREG + 32)
+	ldw      r7, (a3, THREAD_FPREG + 36)
+	ldw      r8, (a3, THREAD_FPREG + 48)
+	ldw      r9, (a3, THREAD_FPREG + 52)
+	fmtvrl   vr2, r6
+	fmtvrh   vr2, r7
+	fmtvrl   vr3, r8
+	fmtvrh   vr3, r9
+	ldw      r6, (a3, THREAD_FPREG + 64)
+	ldw      r7, (a3, THREAD_FPREG + 68)
+	ldw      r8, (a3, THREAD_FPREG + 80)
+	ldw      r9, (a3, THREAD_FPREG + 84)
+	fmtvrl   vr4, r6
+	fmtvrh   vr4, r7
+	fmtvrl   vr5, r8
+	fmtvrh   vr5, r9
+	ldw      r6, (a3, THREAD_FPREG + 96)
+	ldw      r7, (a3, THREAD_FPREG + 100)
+	ldw      r8, (a3, THREAD_FPREG + 112)
+	ldw      r9, (a3, THREAD_FPREG + 116)
+	fmtvrl   vr6, r6
+	fmtvrh   vr6, r7
+	fmtvrl   vr7, r8
+	fmtvrh   vr7, r9
+	ldw      r6, (a3, THREAD_FPREG + 128)
+	ldw      r7, (a3, THREAD_FPREG + 132)
+	ldw      r8, (a3, THREAD_FPREG + 144)
+	ldw      r9, (a3, THREAD_FPREG + 148)
+	fmtvrl   vr8, r6
+	fmtvrh   vr8, r7
+	fmtvrl   vr9, r8
+	fmtvrh   vr9, r9
+	ldw      r6, (a3, THREAD_FPREG + 160)
+	ldw      r7, (a3, THREAD_FPREG + 164)
+	ldw      r8, (a3, THREAD_FPREG + 176)
+	ldw      r9, (a3, THREAD_FPREG + 180)
+	fmtvrl   vr10, r6
+	fmtvrh   vr10, r7
+	fmtvrl   vr11, r8
+	fmtvrh   vr11, r9
+	ldw      r6, (a3, THREAD_FPREG + 192)
+	ldw      r7, (a3, THREAD_FPREG + 196)
+	ldw      r8, (a3, THREAD_FPREG + 208)
+	ldw      r9, (a3, THREAD_FPREG + 212)
+	fmtvrl   vr12, r6
+	fmtvrh   vr12, r7
+	fmtvrl   vr13, r8
+	fmtvrh   vr13, r9
+	ldw      r6, (a3, THREAD_FPREG + 224)
+	ldw      r7, (a3, THREAD_FPREG + 228)
+	ldw      r8, (a3, THREAD_FPREG + 240)
+	ldw      r9, (a3, THREAD_FPREG + 244)
+	fmtvrl   vr14, r6
+	fmtvrh   vr14, r7
+	fmtvrl   vr15, r8
+	fmtvrh   vr15, r9
+.endm
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_CSKY_FPU_H */
diff --git a/arch/csky/include/asm/mmu_context.h b/arch/csky/include/asm/mmu_context.h
new file mode 100644
index 0000000..0964194
--- /dev/null
+++ b/arch/csky/include/asm/mmu_context.h
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_MMU_CONTEXT_H
+#define __ASM_CSKY_MMU_CONTEXT_H
+
+#include <asm-generic/mm_hooks.h>
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <abi/ckmmu.h>
+
+/* misc */
+static inline void tlbmiss_handler_setup_pgd(unsigned long pgd)
+{
+	pgd &= ~(1<<31);
+	pgd += PHYS_OFFSET;
+	pgd |= 1;
+	setup_pgd(pgd);
+}
+
+static inline unsigned long tlb_get_pgd(void)
+{
+	return ((get_pgd()|(1<<31)) - PHYS_OFFSET) & ~1;
+}
+#define TLBMISS_HANDLER_SETUP_PGD(pgd) tlbmiss_handler_setup_pgd((unsigned long)pgd)
+
+#ifdef CONFIG_CPU_HAS_TLBI
+/* misc */
+static inline void tlbmiss_handler_setup_pgd_kernel(unsigned long pgd)
+{
+	pgd &= ~(1<<31);
+	pgd += PHYS_OFFSET;
+	pgd |= 1;
+	setup_pgd_kernel(pgd);
+}
+
+#define TLBMISS_HANDLER_SETUP_PGD_KERNEL(pgd) tlbmiss_handler_setup_pgd_kernel((unsigned long)pgd)
+#endif
+
+#define cpu_context(cpu, mm)	((mm)->context.asid[cpu])
+#define cpu_asid(cpu, mm)	(cpu_context((cpu), (mm)) & ASID_MASK)
+#define asid_cache(cpu)		(cpu_data[cpu].asid_cache)
+
+#define ASID_FIRST_VERSION	(1 << CONFIG_CPU_ASID_BITS)
+#define ASID_INC		0x1
+#define ASID_MASK		(ASID_FIRST_VERSION - 1)
+#define ASID_VERSION_MASK	~ASID_MASK
+
+#define destroy_context(mm)		do{}while(0)
+#define enter_lazy_tlb(mm,tsk)		do{}while(0)
+#define deactivate_mm(tsk,mm)		do{}while(0)
+
+/*
+ *  All unused by hardware upper bits will be considered
+ *  as a software asid extension.
+ */
+static inline void
+get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
+{
+	unsigned long asid = asid_cache(cpu);
+
+	if (! ((asid += ASID_INC) & ASID_MASK) ) {
+		flush_tlb_all();	/* start new asid cycle */
+		if (!asid)		/* fix version if needed */
+			asid = ASID_FIRST_VERSION;
+	}
+	cpu_context(cpu, mm) = asid_cache(cpu) = asid;
+}
+
+/*
+ * Initialize the context related info for a new mm_struct
+ * instance.
+ */
+static inline int
+init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+	int i;
+
+	for_each_online_cpu(i)
+		cpu_context(i, mm) = 0;
+	return 0;
+}
+
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+                             struct task_struct *tsk)
+{
+	unsigned int cpu = smp_processor_id();
+	unsigned long flags;
+
+	local_irq_save(flags);
+	/* Check if our ASID is of an older version and thus invalid */
+	if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK)
+		get_new_mmu_context(next, cpu);
+	write_mmu_entryhi(cpu_asid(cpu, next));
+	TLBMISS_HANDLER_SETUP_PGD(next->pgd);
+
+	/*
+	 * Mark current->active_mm as not "active" anymore.
+	 * We don't want to mislead possible IPI tlb flush routines.
+	 */
+	cpumask_clear_cpu(cpu, mm_cpumask(prev));
+	cpumask_set_cpu(cpu, mm_cpumask(next));
+
+	local_irq_restore(flags);
+}
+
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+static inline void
+activate_mm(struct mm_struct *prev, struct mm_struct *next)
+{
+	unsigned long flags;
+	int cpu = smp_processor_id();
+
+	local_irq_save(flags);
+
+	/* Unconditionally get a new ASID.  */
+	get_new_mmu_context(next, cpu);
+
+	write_mmu_entryhi(cpu_asid(cpu, next));
+	TLBMISS_HANDLER_SETUP_PGD(next->pgd);
+
+	/* mark mmu ownership change */
+	cpumask_clear_cpu(cpu, mm_cpumask(prev));
+	cpumask_set_cpu(cpu, mm_cpumask(next));
+
+	local_irq_restore(flags);
+}
+
+/*
+ * If mm is currently active_mm, we can't really drop it. Instead,
+ * we will get a new one for it.
+ */
+static inline void
+drop_mmu_context(struct mm_struct *mm, unsigned cpu)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	if (cpumask_test_cpu(cpu, mm_cpumask(mm)))  {
+		get_new_mmu_context(mm, cpu);
+		write_mmu_entryhi(cpu_asid(cpu, mm));
+	} else {
+		/* will get a new context next time */
+		cpu_context(cpu, mm) = 0;
+	}
+
+	local_irq_restore(flags);
+}
+
+#endif /* __ASM_CSKY_MMU_CONTEXT_H */
diff --git a/arch/csky/include/asm/processor.h b/arch/csky/include/asm/processor.h
new file mode 100644
index 0000000..fb9d0bf
--- /dev/null
+++ b/arch/csky/include/asm/processor.h
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_PROCESSOR_H
+#define __ASM_CSKY_PROCESSOR_H
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+
+#include <linux/bitops.h>
+#include <asm/segment.h>
+#include <asm/ptrace.h>
+#include <asm/current.h>
+#include <asm/cache.h>
+#include <abi/reg_ops.h>
+#include <abi/regdef.h>
+#ifdef CONFIG_CPU_HAS_FPU
+#include <abi/fpu.h>
+#endif
+
+struct cpuinfo_csky {
+	unsigned long udelay_val;
+	unsigned long asid_cache;
+	/*
+	 * Capability and feature descriptor structure for CSKY CPU
+	 */
+	unsigned long options;
+	unsigned int processor_id[4];
+	unsigned int fpu_id;
+} __attribute__((aligned(SMP_CACHE_BYTES)));
+
+extern struct cpuinfo_csky cpu_data[];
+
+/*
+ * User space process size: 2GB. This is hardcoded into a few places,
+ * so don't change it unless you know what you are doing.  TASK_SIZE
+ * for a 64 bit kernel expandable to 8192EB, of which the current CSKY
+ * implementations will "only" be able to use 1TB ...
+ */
+#define TASK_SIZE       0x7fff8000UL
+
+#ifdef __KERNEL__
+#define STACK_TOP       TASK_SIZE
+#define STACK_TOP_MAX   STACK_TOP
+#endif
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE      (TASK_SIZE / 3)
+
+struct thread_struct {
+	unsigned long  ksp;       /* kernel stack pointer */
+	unsigned long  sr;        /* saved status register */
+	unsigned long  esp0;      /* points to SR of stack frame */
+
+	/* FPU regs */
+	struct user_fp	user_fp;
+
+	unsigned long  hi;
+	unsigned long  lo;
+	unsigned long  dspcsr;
+
+	/* Other stuff associated with the thread. */
+	unsigned long address;      /* Last user fault */
+	unsigned long error_code;
+	unsigned long trap_no;
+};
+
+#define INIT_THREAD  { \
+	.ksp = (unsigned long) init_thread_union.stack + THREAD_SIZE, \
+	.sr = DEFAULT_PSR_VALUE, \
+}
+
+/*
+ * Do necessary setup to start up a newly executed thread.
+ *
+ * pass the data segment into user programs if it exists,
+ * it can't hurt anything as far as I can tell
+ */
+#define start_thread(_regs, _pc, _usp)					\
+do {									\
+	set_fs(USER_DS); /* reads from user space */			\
+	(_regs)->pc = (_pc);						\
+	(_regs)->regs[1] = 0; /* ABIV1 is R7, uClibc_main rtdl arg */	\
+	(_regs)->regs[2] = 0;						\
+	(_regs)->regs[3] = 0; /* ABIV2 is R7, use it? */		\
+	(_regs)->sr &= ~PS_S;						\
+	(_regs)->usp = (_usp);						\
+} while(0)
+
+/* Forward declaration, a strange C thing */
+struct task_struct;
+
+/* Free all resources held by a thread. */
+static inline void release_thread(struct task_struct *dead_task)
+{
+}
+
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)    do { } while (0)
+
+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 forget_segments()		do { } while (0)
+
+extern unsigned long thread_saved_pc(struct task_struct *tsk);
+
+unsigned long get_wchan(struct task_struct *p);
+
+#define KSTK_EIP(tsk)		(task_pt_regs(tsk)->pc)
+#define KSTK_ESP(tsk)		(task_pt_regs(tsk)->usp)
+
+#define task_pt_regs(p) \
+	((struct pt_regs *)(THREAD_SIZE + p->stack) - 1)
+
+#define cpu_relax() barrier()
+
+#endif /* __ASM_CSKY_PROCESSOR_H */
diff --git a/arch/csky/include/asm/thread_info.h b/arch/csky/include/asm/thread_info.h
new file mode 100644
index 0000000..fa28924
--- /dev/null
+++ b/arch/csky/include/asm/thread_info.h
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef _ASM_CSKY_THREAD_INFO_H
+#define _ASM_CSKY_THREAD_INFO_H
+
+#ifndef __ASSEMBLY__
+
+#include <asm/types.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+
+struct thread_info {
+	struct task_struct	*task;
+	void			*dump_exec_domain;
+	unsigned long		flags;
+	int			preempt_count;
+	unsigned long		tp_value;
+	mm_segment_t		addr_limit;
+	struct restart_block	restart_block;
+	struct pt_regs		*regs;
+	unsigned int		cpu;
+};
+
+#define INIT_THREAD_INFO(tsk)			\
+{						\
+	.task		= &tsk,			\
+	.preempt_count  = INIT_PREEMPT_COUNT,	\
+	.addr_limit     = KERNEL_DS,		\
+	.cpu		= 0,			\
+	.restart_block = {			\
+		.fn = do_no_restart_syscall,	\
+	},					\
+}
+
+#define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT)
+
+static inline struct thread_info *current_thread_info(void)
+{
+	unsigned long sp;
+
+	asm volatile("mov %0, sp\n":"=r"(sp));
+
+	return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
+}
+
+#endif /* !__ASSEMBLY__ */
+
+/* entry.S relies on these definitions!
+ * bits 0-5 are tested at every exception exit
+ */
+#define TIF_SIGPENDING		0	/* signal pending */
+#define TIF_NOTIFY_RESUME	1       /* callback before returning to user */
+#define TIF_NEED_RESCHED	2	/* rescheduling necessary */
+#define TIF_SYSCALL_TRACE	5	/* syscall trace active */
+#define TIF_DELAYED_TRACE	14	/* single step a syscall */
+#define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
+#define TIF_MEMDIE		18      /* is terminating due to OOM killer */
+#define TIF_FREEZE		19	/* thread is freezing for suspend */
+#define TIF_RESTORE_SIGMASK	20	/* restore signal mask in do_signal() */
+#define TIF_SECCOMP		21	/* secure computing */
+
+#define _TIF_SIGPENDING         (1 << TIF_SIGPENDING)
+#define _TIF_NOTIFY_RESUME      (1 << TIF_NOTIFY_RESUME)
+#define _TIF_NEED_RESCHED       (1 << TIF_NEED_RESCHED)
+#define _TIF_SYSCALL_TRACE      (1 << TIF_SYSCALL_TRACE)
+#define _TIF_DELAYED_TRACE	(1 << TIF_DELAYED_TRACE)
+#define _TIF_POLLING_NRFLAG     (1 << TIF_POLLING_NRFLAG)
+#define _TIF_MEMDIE		(1 << TIF_MEMDIE)
+#define _TIF_FREEZE             (1 << TIF_FREEZE)
+#define _TIF_RESTORE_SIGMASK    (1 << TIF_RESTORE_SIGMASK)
+#define _TIF_SECCOMP            (1 << TIF_SECCOMP)
+
+#endif	/* _ASM_CSKY_THREAD_INFO_H */
diff --git a/arch/csky/include/uapi/asm/sigcontext.h b/arch/csky/include/uapi/asm/sigcontext.h
new file mode 100644
index 0000000..633cb14
--- /dev/null
+++ b/arch/csky/include/uapi/asm/sigcontext.h
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_SIGCONTEXT_H
+#define __ASM_CSKY_SIGCONTEXT_H
+
+#include <asm/ptrace.h>
+
+struct sigcontext {
+	struct pt_regs	sc_pt_regs;
+	struct user_fp	sc_user_fp;
+};
+
+#endif /* __ASM_CSKY_SIGCONTEXT_H */
diff --git a/arch/csky/kernel/process.c b/arch/csky/kernel/process.c
new file mode 100644
index 0000000..5b916b0
--- /dev/null
+++ b/arch/csky/kernel/process.c
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/sched.h>
+#include <linux/sched/task_stack.h>
+#include <linux/sched/debug.h>
+#include <linux/delay.h>
+#include <linux/kallsyms.h>
+#include <linux/uaccess.h>
+#include <linux/ptrace.h>
+
+#include <asm/elf.h>
+#include <abi/reg_ops.h>
+
+struct cpuinfo_csky cpu_data[NR_CPUS];
+
+asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
+
+/*
+ * Some archs flush debug and FPU info here
+ */
+void flush_thread(void){}
+
+/*
+ * Return saved PC from a blocked thread
+ */
+unsigned long thread_saved_pc(struct task_struct *tsk)
+{
+	struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
+
+	return sw->r15;
+}
+
+int copy_thread(unsigned long clone_flags,
+		unsigned long usp,
+		unsigned long kthread_arg,
+		struct task_struct *p)
+{
+	struct switch_stack * childstack;
+	unsigned long reg_psr = 0;
+	struct pt_regs *childregs = task_pt_regs(p);
+
+	preempt_disable();
+
+	reg_psr = mfcr("psr");
+
+#ifdef CONFIG_CPU_HAS_FPU
+	save_to_user_fp(&p->thread.user_fp);
+#endif
+#ifdef CONFIG_CPU_HAS_HILO
+	asm volatile(
+		"mfhi	%0 \n"
+		"mflo	%1 \n"
+		:"=r"(p->thread.hi),"=r"(p->thread.lo));
+#endif
+	preempt_enable();
+
+	childstack = ((struct switch_stack *) childregs) - 1;
+	memset(childstack, 0, sizeof(struct switch_stack));
+
+	/* setup ksp for switch_to !!! */
+	p->thread.ksp = (unsigned long)childstack;
+
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		memset(childregs, 0, sizeof(struct pt_regs));
+		childstack->r15 = (unsigned long) ret_from_kernel_thread;
+		childstack->r8 = kthread_arg;
+		childstack->r9 = usp;
+		childregs->sr = reg_psr;
+
+		return 0;
+	} else {
+		*childregs = *(current_pt_regs());
+		childstack->r15 = (unsigned long) ret_from_fork;
+	}
+
+	/* Return 0 for subprocess when return from fork(),vfork(),clone() */
+	childregs->a0 = 0;
+
+	if (usp != 0) childregs->usp = usp;
+
+	if (clone_flags & CLONE_SETTLS) {
+		task_thread_info(p)->tp_value = (current_pt_regs())->regs[0];
+		childregs->tls = task_thread_info(p)->tp_value;
+	}
+
+	return 0;
+}
+
+/* Fill in the fpu structure for a core dump.  */
+int dump_fpu (struct pt_regs *regs, struct user_fp *fpu)
+{
+	memcpy(fpu, &current->thread.user_fp, sizeof(*fpu));
+	return 1;
+}
+EXPORT_SYMBOL(dump_fpu);
+
+int dump_task_regs(struct task_struct *tsk, elf_gregset_t *pr_regs)
+{
+	struct pt_regs *regs = (struct pt_regs *)(tsk->thread.esp0);
+
+	/* NOTE: usp is error value. */
+	ELF_CORE_COPY_REGS ((*pr_regs), regs)
+
+	return 1;
+}
+
+unsigned long get_wchan(struct task_struct *p)
+{
+	unsigned long esp, pc;
+	unsigned long stack_page;
+	int count = 0;
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+
+	stack_page = (unsigned long)p;
+	esp = p->thread.esp0;
+	do {
+		if (esp < stack_page+sizeof(struct task_struct) ||
+		    esp >= 8184+stack_page)
+			return 0;
+		/*FIXME: There's may be error here!*/
+		pc = ((unsigned long *)esp)[1];
+		/* FIXME: This depends on the order of these functions. */
+		if (!in_sched_functions(pc))
+			return pc;
+		esp = *(unsigned long *) esp;
+	} while (count++ < 16);
+	return 0;
+}
+
+EXPORT_SYMBOL(get_wchan);
diff --git a/arch/csky/kernel/signal.c b/arch/csky/kernel/signal.c
new file mode 100644
index 0000000..c40775a
--- /dev/null
+++ b/arch/csky/kernel/signal.c
@@ -0,0 +1,350 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/syscalls.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <linux/highuid.h>
+#include <linux/personality.h>
+#include <linux/tty.h>
+#include <linux/binfmts.h>
+#include <linux/tracehook.h>
+#include <linux/freezer.h>
+#include <linux/uaccess.h>
+
+#include <asm/setup.h>
+#include <asm/pgtable.h>
+#include <asm/traps.h>
+#include <asm/ucontext.h>
+#include <asm/vdso.h>
+
+#include <abi/regdef.h>
+
+#ifdef CONFIG_CPU_HAS_FPU
+#include <abi/fpu.h>
+
+static int restore_fpu_state(struct sigcontext *sc)
+{
+	int err = 0;
+	struct user_fp user_fp;
+
+	err = copy_from_user(&user_fp, &sc->sc_user_fp, sizeof(user_fp));
+
+	restore_from_user_fp(&user_fp);
+
+	return err;
+}
+
+static int save_fpu_state(struct sigcontext *sc)
+{
+	struct user_fp user_fp;
+
+	save_to_user_fp(&user_fp);
+
+	return copy_to_user(&sc->sc_user_fp, &user_fp, sizeof(user_fp));
+}
+#else
+static inline int restore_fpu_state(struct sigcontext *sc){return 0;}
+static inline int save_fpu_state(struct sigcontext *sc){return 0;}
+#endif
+
+struct rt_sigframe
+{
+	int sig;
+	struct siginfo *pinfo;
+	void *puc;
+	struct siginfo info;
+	struct ucontext uc;
+};
+
+static int
+restore_sigframe(struct pt_regs *regs,
+		 struct sigcontext *sc, int *pr2)
+{
+	int err = 0;
+
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->task->restart_block.fn = do_no_restart_syscall;
+
+	err |= copy_from_user(regs, &sc->sc_pt_regs, sizeof(struct pt_regs));
+
+	err |= restore_fpu_state(sc);
+
+	*pr2 = regs->a0;
+	return err;
+}
+
+asmlinkage int
+do_rt_sigreturn(void)
+{
+	sigset_t set;
+	int a0;
+	struct pt_regs *regs = current_pt_regs();
+	struct rt_sigframe *frame = (struct rt_sigframe *)(regs->usp);
+
+	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+		goto badframe;
+
+	sigdelsetmask(&set, (sigmask(SIGKILL) | sigmask(SIGSTOP)));
+	spin_lock_irq(&current->sighand->siglock);
+	current->blocked = set;
+	recalc_sigpending( );
+	spin_unlock_irq(&current->sighand->siglock);
+
+	if (restore_sigframe(regs, &frame->uc.uc_mcontext, &a0))
+		goto badframe;
+
+	return a0;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+static int setup_sigframe(struct sigcontext *sc, struct pt_regs *regs)
+{
+	int err = 0;
+
+	err |= copy_to_user(&sc->sc_pt_regs, regs, sizeof(struct pt_regs));
+	err |= save_fpu_state(sc);
+
+	return err;
+}
+
+static inline void *
+get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
+{
+	unsigned long usp;
+
+	/* Default to using normal stack.  */
+	usp = regs->usp;
+
+	/* This is the X/Open sanctioned signal stack switching.  */
+	if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(usp)) {
+		if (!on_sig_stack(usp))
+			usp = current->sas_ss_sp + current->sas_ss_size;
+	}
+	return (void *)((usp - frame_size) & -8UL);
+}
+
+static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
+		sigset_t *set, struct pt_regs *regs)
+{
+	struct rt_sigframe *frame;
+	int err = 0;
+
+	struct csky_vdso *vdso = current->mm->context.vdso;
+
+	frame = get_sigframe(ka, regs, sizeof(*frame));
+	if (!frame)
+		return 1;
+
+	err |= __put_user(sig, &frame->sig);
+	err |= __put_user(&frame->info, &frame->pinfo);
+	err |= __put_user(&frame->uc, &frame->puc);
+	err |= copy_siginfo_to_user(&frame->info, info);
+
+	/* Create the ucontext.  */
+	err |= __put_user(0, &frame->uc.uc_flags);
+	err |= __put_user(0, &frame->uc.uc_link);
+	err |= __put_user((void *)current->sas_ss_sp,
+			&frame->uc.uc_stack.ss_sp);
+	err |= __put_user(sas_ss_flags(regs->usp),
+			&frame->uc.uc_stack.ss_flags);
+	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+	err |= setup_sigframe(&frame->uc.uc_mcontext, regs);
+	err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
+
+	if (err)
+		goto give_sigsegv;
+
+	/* Set up registers for signal handler */
+	regs->usp = (unsigned long) frame;
+	regs->pc = (unsigned long) ka->sa.sa_handler;
+	regs->lr = (unsigned long)vdso->rt_signal_retcode;
+
+adjust_stack:
+	regs->a0 = sig; /* first arg is signo */
+	regs->a1 = (unsigned long)(&(frame->info)); /* second arg is (siginfo_t*) */
+	regs->a2 = (unsigned long)(&(frame->uc));/* third arg pointer to ucontext */
+	return err;
+
+give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+	force_sig(SIGSEGV, current);
+	goto adjust_stack;
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+static int
+handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
+		sigset_t *oldset, struct pt_regs *regs)
+{
+	struct task_struct *tsk = current;
+	int ret;
+
+	/* set up the stack frame, regardless of SA_SIGINFO, and pass info anyway. */
+	ret = setup_rt_frame(sig, ka, info, oldset, regs);
+
+	if (ret != 0) {
+		force_sigsegv(sig, tsk);
+		return ret;
+	}
+
+	/* Block the signal if we were successful. */
+	spin_lock_irq(&current->sighand->siglock);
+	sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
+	if (!(ka->sa.sa_flags & SA_NODEFER))
+		sigaddset(&current->blocked, sig);
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	return 0;
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ *
+ * Note that we go through the signals twice: once to check the signals
+ * that the kernel can handle, and then we build all the user-level signal
+ * handling stack-frames in one go after that.
+ */
+static void do_signal(struct pt_regs *regs, int syscall)
+{
+	unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
+	struct ksignal ksig;
+
+	/*
+	 * We want the common case to go fast, which
+	 * is why we may in certain cases get here from
+	 * kernel mode. Just return without doing anything
+	 * if so.
+	 */
+	if (!user_mode(regs))
+		return;
+
+	current->thread.esp0 = (unsigned long)regs;
+
+	/*
+	 * If we were from a system call, check for system call restarting...
+	 */
+	if (syscall) {
+		continue_addr = regs->pc;
+#if defined(__CSKYABIV2__)
+		restart_addr = continue_addr - 4;
+#else
+		restart_addr = continue_addr - 2;
+#endif
+		retval = regs->a0;
+
+		/*
+		 * Prepare for system call restart.  We do this here so that a
+		 * debugger will see the already changed.
+		 */
+		switch (retval) {
+		case -ERESTARTNOHAND:
+		case -ERESTARTSYS:
+		case -ERESTARTNOINTR:
+			regs->a0 = regs->orig_a0;
+			regs->pc = restart_addr;
+			break;
+		case -ERESTART_RESTARTBLOCK:
+			regs->a0 = -EINTR;
+			break;
+		}
+	}
+
+	if (try_to_freeze())
+		goto no_signal;
+
+	/*
+	 * Get the signal to deliver.  When running under ptrace, at this
+	 * point the debugger may change all our registers ...
+	 */
+	if (get_signal(&ksig)) {
+		sigset_t *oldset;
+
+		/*
+		 * Depending on the signal settings we may need to revert the
+		 * decision to restart the system call.  But skip this if a
+		 * debugger has chosen to restart at a different PC.
+		 */
+		if (regs->pc == restart_addr) {
+			if (retval == -ERESTARTNOHAND
+					|| (retval == -ERESTARTSYS
+						&& !(ksig.ka.sa.sa_flags & SA_RESTART))) {
+				regs->a0 = -EINTR;
+				regs->pc = continue_addr;
+			}
+		}
+
+		if (test_thread_flag(TIF_RESTORE_SIGMASK))
+			oldset = &current->saved_sigmask;
+		else
+			oldset = &current->blocked;
+		/* Whee!  Actually deliver the signal.  */
+		if (handle_signal(ksig.sig, &ksig.ka, &ksig.info, oldset, regs) == 0) {
+			/*
+			 * A signal was successfully delivered; the saved
+			 * sigmask will have been stored in the signal frame,
+			 * and will be restored by sigreturn, so we can simply
+			 * clear the TIF_RESTORE_SIGMASK flag.
+			 */
+			if (test_thread_flag(TIF_RESTORE_SIGMASK))
+				clear_thread_flag(TIF_RESTORE_SIGMASK);
+		}
+		return;
+	}
+
+no_signal:
+	if (syscall) {
+		/*
+		 * Handle restarting a different system call.  As above,
+		 * if a debugger has chosen to restart at a different PC,
+		 * ignore the restart.
+		 */
+		if (retval == -ERESTART_RESTARTBLOCK
+				&& regs->pc == continue_addr) {
+#if defined(__CSKYABIV2__)
+			regs->regs[3] = __NR_restart_syscall;
+			regs->pc -= 4;
+#else
+			regs->regs[9] = __NR_restart_syscall;
+			regs->pc -= 2;
+#endif
+		}
+
+		/* If there's no signal to deliver, we just put the saved sigmask
+		 * back.
+		 */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+			sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+		}
+	}
+}
+
+asmlinkage void
+do_notify_resume(unsigned int thread_flags, struct pt_regs *regs, int syscall)
+{
+	if (thread_flags & _TIF_SIGPENDING)
+		do_signal(regs, syscall);
+
+	if (thread_flags & _TIF_NOTIFY_RESUME) {
+		clear_thread_flag(TIF_NOTIFY_RESUME);
+		tracehook_notify_resume(regs);
+	}
+}
diff --git a/arch/csky/kernel/time.c b/arch/csky/kernel/time.c
new file mode 100644
index 0000000..7cbdc1e
--- /dev/null
+++ b/arch/csky/kernel/time.c
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/clk-provider.h>
+#include <linux/clocksource.h>
+
+void __init time_init(void)
+{
+	of_clk_init(NULL);
+
+	timer_probe();
+}
+
-- 
2.7.4


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

* [PATCH V2 09/19] csky: VDSO and rt_sigreturn
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (7 preceding siblings ...)
  2018-07-01 17:30 ` [PATCH V2 08/19] csky: Process management and Signal Guo Ren
@ 2018-07-01 17:30 ` Guo Ren
  2018-07-01 17:30 ` [PATCH V2 10/19] csky: IRQ handling Guo Ren
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/abiv1/inc/abi/vdso.h | 17 ++++++++
 arch/csky/abiv2/inc/abi/vdso.h | 18 +++++++++
 arch/csky/include/asm/vdso.h   | 12 ++++++
 arch/csky/kernel/vdso.c        | 89 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 136 insertions(+)
 create mode 100644 arch/csky/abiv1/inc/abi/vdso.h
 create mode 100644 arch/csky/abiv2/inc/abi/vdso.h
 create mode 100644 arch/csky/include/asm/vdso.h
 create mode 100644 arch/csky/kernel/vdso.c

diff --git a/arch/csky/abiv1/inc/abi/vdso.h b/arch/csky/abiv1/inc/abi/vdso.h
new file mode 100644
index 0000000..a99f0e4
--- /dev/null
+++ b/arch/csky/abiv1/inc/abi/vdso.h
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/uaccess.h>
+
+static inline int setup_vdso_page(unsigned short *ptr)
+{
+	int err = 0;
+
+	/* movi r1, 127 */
+	err |= __put_user(0x67f1, ptr + 0);
+	/* addi r1, (139 - 127) */
+	err |= __put_user(0x20b1, ptr + 1);
+	/* trap 0 */
+	err |= __put_user(0x0008, ptr + 2);
+
+	return err;
+}
diff --git a/arch/csky/abiv2/inc/abi/vdso.h b/arch/csky/abiv2/inc/abi/vdso.h
new file mode 100644
index 0000000..aa2d489
--- /dev/null
+++ b/arch/csky/abiv2/inc/abi/vdso.h
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/uaccess.h>
+
+static inline int setup_vdso_page(unsigned short *ptr)
+{
+	int err = 0;
+
+	/* movi r7, 173 */
+	err |= __put_user(0xea07, ptr);
+	err |= __put_user(0x008b,      ptr+1);
+
+	/* trap 0 */
+	err |= __put_user(0xc000,   ptr+2);
+	err |= __put_user(0x2020,   ptr+3);
+
+	return err;
+}
diff --git a/arch/csky/include/asm/vdso.h b/arch/csky/include/asm/vdso.h
new file mode 100644
index 0000000..b275440
--- /dev/null
+++ b/arch/csky/include/asm/vdso.h
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_VDSO_H
+#define __ASM_CSKY_VDSO_H
+
+#include <abi/vdso.h>
+
+struct csky_vdso {
+	unsigned short rt_signal_retcode[4];
+};
+
+#endif /* __ASM_CSKY_VDSO_H */
diff --git a/arch/csky/kernel/vdso.c b/arch/csky/kernel/vdso.c
new file mode 100644
index 0000000..dd59aae
--- /dev/null
+++ b/arch/csky/kernel/vdso.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/binfmts.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/unistd.h>
+#include <linux/uaccess.h>
+
+#include <asm/vdso.h>
+#include <asm/cacheflush.h>
+
+static struct page *vdso_page;
+
+static int __init init_vdso(void)
+{
+	struct csky_vdso *vdso;
+	int err = 0;
+
+	vdso_page = alloc_page(GFP_KERNEL);
+	if (!vdso_page)
+		panic("Cannot allocate vdso");
+
+	vdso = vmap(&vdso_page, 1, 0, PAGE_KERNEL);
+	if (!vdso)
+		panic("Cannot map vdso");
+
+	clear_page(vdso);
+
+	/*
+	 * __NR_rt_sigreturn must be 173
+	 * Because gcc/config/csky/linux-unwind.h use hard code to parse rt_sigframe.
+	 */
+	err = setup_vdso_page(vdso->rt_signal_retcode);
+	if (err) panic("Cannot set signal return code, err: %x.", err);
+
+	dcache_wb_range((unsigned long)vdso, (unsigned long)vdso + 16);
+
+	vunmap(vdso);
+
+	return 0;
+}
+subsys_initcall(init_vdso);
+
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+	int ret;
+	unsigned long addr;
+	struct mm_struct *mm = current->mm;
+
+	down_write(&mm->mmap_sem);
+
+	addr = get_unmapped_area(NULL, STACK_TOP, PAGE_SIZE, 0, 0);
+	if (IS_ERR_VALUE(addr)) {
+		ret = addr;
+		goto up_fail;
+	}
+
+	ret = install_special_mapping(
+			mm,
+			addr,
+			PAGE_SIZE,
+			VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
+			&vdso_page);
+	if (ret)
+		goto up_fail;
+
+	mm->context.vdso = (void *)addr;
+
+up_fail:
+	up_write(&mm->mmap_sem);
+	return ret;
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	if (vma->vm_mm == NULL)
+		return NULL;
+
+	if (vma->vm_start == (long)vma->vm_mm->context.vdso)
+		return "[vdso]";
+	else
+		return NULL;
+}
+
-- 
2.7.4


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

* [PATCH V2 10/19] csky: IRQ handling
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (8 preceding siblings ...)
  2018-07-01 17:30 ` [PATCH V2 09/19] csky: VDSO and rt_sigreturn Guo Ren
@ 2018-07-01 17:30 ` Guo Ren
  2018-07-01 17:30 ` [PATCH V2 11/19] csky: Atomic operations Guo Ren
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/include/asm/irq.h      | 10 ++++++++
 arch/csky/include/asm/irqflags.h | 49 ++++++++++++++++++++++++++++++++++++++++
 arch/csky/kernel/irq.c           | 31 +++++++++++++++++++++++++
 3 files changed, 90 insertions(+)
 create mode 100644 arch/csky/include/asm/irq.h
 create mode 100644 arch/csky/include/asm/irqflags.h
 create mode 100644 arch/csky/kernel/irq.c

diff --git a/arch/csky/include/asm/irq.h b/arch/csky/include/asm/irq.h
new file mode 100644
index 0000000..9390cb0
--- /dev/null
+++ b/arch/csky/include/asm/irq.h
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_IRQ_H
+#define __ASM_CSKY_IRQ_H
+
+#include <asm-generic/irq.h>
+
+extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
+
+#endif /* __ASM_CSKY_IRQ_H */
diff --git a/arch/csky/include/asm/irqflags.h b/arch/csky/include/asm/irqflags.h
new file mode 100644
index 0000000..5216ec0
--- /dev/null
+++ b/arch/csky/include/asm/irqflags.h
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_IRQFLAGS_H
+#define __ASM_CSKY_IRQFLAGS_H
+#include <abi/reg_ops.h>
+
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags;
+
+	flags = mfcr("psr");
+	asm volatile("psrclr ie\n");
+	return flags;
+}
+#define arch_local_irq_save arch_local_irq_save
+
+static inline void arch_local_irq_enable(void)
+{
+	asm volatile("psrset ee, ie\n");
+}
+#define arch_local_irq_enable arch_local_irq_enable
+
+static inline void arch_local_irq_disable(void)
+{
+	asm volatile("psrclr ie\n");
+}
+#define arch_local_irq_disable arch_local_irq_disable
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	return mfcr("psr");
+}
+#define arch_local_save_flags arch_local_save_flags
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	mtcr("psr", flags);
+}
+#define arch_local_irq_restore arch_local_irq_restore
+
+static inline int arch_irqs_disabled_flags(unsigned long flags)
+{
+	return !(flags & (1<<6));
+}
+#define arch_irqs_disabled_flags arch_irqs_disabled_flags
+
+#include <asm-generic/irqflags.h>
+
+#endif /* __ASM_CSKY_IRQFLAGS_H */
diff --git a/arch/csky/kernel/irq.c b/arch/csky/kernel/irq.c
new file mode 100644
index 0000000..ef2600d
--- /dev/null
+++ b/arch/csky/kernel/irq.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <asm/traps.h>
+#include <asm/smp.h>
+
+static void (*handle_arch_irq)(struct pt_regs *regs) = NULL;
+
+void __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
+{
+	if (handle_arch_irq)
+		return;
+
+	handle_arch_irq = handle_irq;
+}
+
+void __init init_IRQ(void)
+{
+	irqchip_init();
+#ifdef CONFIG_SMP
+	setup_smp_ipi();
+#endif
+}
+
+asmlinkage void __irq_entry csky_do_IRQ(struct pt_regs *regs)
+{
+	handle_arch_irq(regs);
+}
-- 
2.7.4


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

* [PATCH V2 11/19] csky: Atomic operations
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (9 preceding siblings ...)
  2018-07-01 17:30 ` [PATCH V2 10/19] csky: IRQ handling Guo Ren
@ 2018-07-01 17:30 ` Guo Ren
  2018-07-05 17:50   ` Peter Zijlstra
                     ` (2 more replies)
  2018-07-01 17:30 ` [PATCH V2 12/19] csky: ELF and module probe Guo Ren
                   ` (8 subsequent siblings)
  19 siblings, 3 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/include/asm/cmpxchg.h        |  68 +++++++++++++
 arch/csky/include/asm/spinlock.h       | 174 +++++++++++++++++++++++++++++++++
 arch/csky/include/asm/spinlock_types.h |  20 ++++
 arch/csky/kernel/atomic.S              |  87 +++++++++++++++++
 4 files changed, 349 insertions(+)
 create mode 100644 arch/csky/include/asm/cmpxchg.h
 create mode 100644 arch/csky/include/asm/spinlock.h
 create mode 100644 arch/csky/include/asm/spinlock_types.h
 create mode 100644 arch/csky/kernel/atomic.S

diff --git a/arch/csky/include/asm/cmpxchg.h b/arch/csky/include/asm/cmpxchg.h
new file mode 100644
index 0000000..1c30a28
--- /dev/null
+++ b/arch/csky/include/asm/cmpxchg.h
@@ -0,0 +1,68 @@
+#ifndef __ASM_CSKY_CMPXCHG_H
+#define __ASM_CSKY_CMPXCHG_H
+
+#ifdef CONFIG_CPU_HAS_LDSTEX
+#include <linux/bug.h>
+#include <asm/barrier.h>
+
+#define __xchg(new, ptr, size)					\
+({								\
+	__typeof__(ptr) __ptr = (ptr);				\
+	__typeof__(new) __new = (new);				\
+	__typeof__(*(ptr)) __ret;				\
+	unsigned long tmp;					\
+	switch (size) {						\
+	case 4:							\
+		asm volatile (					\
+		"1:	ldex.w		%0, (%3) \n"		\
+		"	mov		%1, %2   \n"		\
+		"	stex.w		%1, (%3) \n"		\
+		"	bez		%1, 1b   \n"		\
+			: "=&r" (__ret), "=&r" (tmp)		\
+			: "r" (__new), "r"(__ptr)		\
+			: "memory");				\
+		smp_mb();					\
+		break;						\
+	default:						\
+		BUILD_BUG();					\
+	}							\
+	__ret;							\
+})
+
+#define xchg(ptr, x)	(__xchg((x), (ptr), sizeof(*(ptr))))
+
+#define __cmpxchg(ptr, old, new, size)				\
+({								\
+	__typeof__(ptr) __ptr = (ptr);				\
+	__typeof__(new) __new = (new);				\
+	__typeof__(new) __tmp;					\
+	__typeof__(old) __old = (old);				\
+	__typeof__(*(ptr)) __ret;				\
+	switch (size) {						\
+	case 4:							\
+		asm volatile (					\
+		"1:	ldex.w		%0, (%3) \n"		\
+		"	cmpne		%0, %4   \n"		\
+		"	bt		2f       \n"		\
+		"	mov		%1, %2   \n"		\
+		"	stex.w		%1, (%3) \n"		\
+		"	bez		%1, 1b   \n"		\
+		"2:				 \n"		\
+			: "=&r" (__ret), "=&r" (__tmp)		\
+			: "r" (__new), "r"(__ptr), "r"(__old)	\
+			: "memory");				\
+		smp_mb();					\
+		break;						\
+	default:						\
+		BUILD_BUG();					\
+	}							\
+	__ret;							\
+})
+
+#define cmpxchg(ptr, o, n) \
+	(__cmpxchg((ptr), (o), (n), sizeof(*(ptr))))
+#else
+#include <asm-generic/cmpxchg.h>
+#endif
+
+#endif /* __ASM_CSKY_CMPXCHG_H */
diff --git a/arch/csky/include/asm/spinlock.h b/arch/csky/include/asm/spinlock.h
new file mode 100644
index 0000000..ca10d0e
--- /dev/null
+++ b/arch/csky/include/asm/spinlock.h
@@ -0,0 +1,174 @@
+#ifndef __ASM_CSKY_SPINLOCK_H
+#define __ASM_CSKY_SPINLOCK_H
+
+#include <linux/spinlock_types.h>
+#include <asm/barrier.h>
+
+#define arch_spin_is_locked(x)	(READ_ONCE((x)->lock) != 0)
+
+/****** spin lock/unlock/trylock ******/
+static inline void arch_spin_lock(arch_spinlock_t *lock)
+{
+	unsigned int *p = &lock->lock;
+	unsigned int tmp;
+
+	asm volatile (
+		"1:	ldex.w		%0, (%1) \n"
+		"	bnez		%0, 1b   \n"
+		"	movi		%0, 1    \n"
+		"	stex.w		%0, (%1) \n"
+		"	bez		%0, 1b   \n"
+		: "=&r" (tmp)
+		: "r"(p)
+		: "memory");
+	smp_mb();
+}
+
+static inline void arch_spin_unlock(arch_spinlock_t *lock)
+{
+	unsigned int *p = &lock->lock;
+	unsigned int tmp;
+
+	smp_mb();
+	asm volatile (
+		"1:	ldex.w		%0, (%1) \n"
+		"	movi		%0, 0    \n"
+		"	stex.w		%0, (%1) \n"
+		"	bez		%0, 1b   \n"
+		: "=&r" (tmp)
+		: "r"(p)
+		: "memory");
+}
+
+static inline int arch_spin_trylock(arch_spinlock_t *lock)
+{
+	unsigned int *p = &lock->lock;
+	unsigned int tmp;
+
+	asm volatile (
+		"1:	ldex.w		%0, (%1) \n"
+		"	bnez		%0, 2f   \n"
+		"	movi		%0, 1    \n"
+		"	stex.w		%0, (%1) \n"
+		"	bez		%0, 1b   \n"
+		"	movi		%0, 0    \n"
+		"2:				 \n"
+		: "=&r" (tmp)
+		: "r"(p)
+		: "memory");
+	smp_mb();
+
+	return !tmp;
+}
+
+/****** read lock/unlock/trylock ******/
+static inline void arch_read_lock(arch_rwlock_t *lock)
+{
+	unsigned int *p = &lock->lock;
+	unsigned int tmp;
+
+	asm volatile (
+		"1:	ldex.w		%0, (%1) \n"
+		"	blz		%0, 1b   \n"
+		"	addi		%0, 1    \n"
+		"	stex.w		%0, (%1) \n"
+		"	bez		%0, 1b   \n"
+		: "=&r" (tmp)
+		: "r"(p)
+		: "memory");
+	smp_mb();
+}
+
+static inline void arch_read_unlock(arch_rwlock_t *lock)
+{
+	unsigned int *p = &lock->lock;
+	unsigned int tmp;
+
+	smp_mb();
+	asm volatile (
+		"1:	ldex.w		%0, (%1) \n"
+		"	subi		%0, 1    \n"
+		"	stex.w		%0, (%1) \n"
+		"	bez		%0, 1b   \n"
+		: "=&r" (tmp)
+		: "r"(p)
+		: "memory");
+}
+
+static inline int arch_read_trylock(arch_rwlock_t *lock)
+{
+	unsigned int *p = &lock->lock;
+	unsigned int tmp;
+
+	asm volatile (
+		"1:	ldex.w		%0, (%1) \n"
+		"	blz		%0, 2f   \n"
+		"	addi		%0, 1    \n"
+		"	stex.w		%0, (%1) \n"
+		"	bez		%0, 1b   \n"
+		"	movi		%0, 0    \n"
+		"2:				 \n"
+		: "=&r" (tmp)
+		: "r"(p)
+		: "memory");
+	smp_mb();
+
+	return !tmp;
+}
+
+/****** write lock/unlock/trylock ******/
+static inline void arch_write_lock(arch_rwlock_t *lock)
+{
+	unsigned int *p = &lock->lock;
+	unsigned int tmp;
+
+	asm volatile (
+		"1:	ldex.w		%0, (%1) \n"
+		"	bnez		%0, 1b   \n"
+		"	subi		%0, 1    \n"
+		"	stex.w		%0, (%1) \n"
+		"	bez		%0, 1b   \n"
+		: "=&r" (tmp)
+		: "r"(p)
+		: "memory");
+	smp_mb();
+}
+
+static inline void arch_write_unlock(arch_rwlock_t *lock)
+{
+	unsigned int *p = &lock->lock;
+	unsigned int tmp;
+
+	smp_mb();
+	asm volatile (
+		"1:	ldex.w		%0, (%1) \n"
+		"	movi		%0, 0    \n"
+		"	stex.w		%0, (%1) \n"
+		"	bez		%0, 1b   \n"
+		: "=&r" (tmp)
+		: "r"(p)
+		: "memory");
+}
+
+static inline int arch_write_trylock(arch_rwlock_t *lock)
+{
+	unsigned int *p = &lock->lock;
+	unsigned int tmp;
+
+	asm volatile (
+		"1:	ldex.w		%0, (%1) \n"
+		"	bnez		%0, 2f   \n"
+		"	subi		%0, 1    \n"
+		"	stex.w		%0, (%1) \n"
+		"	bez		%0, 1b   \n"
+		"	movi		%0, 0    \n"
+		"2:				 \n"
+		: "=&r" (tmp)
+		: "r"(p)
+		: "memory");
+	smp_mb();
+
+	return !tmp;
+}
+
+#endif /* __ASM_CSKY_SPINLOCK_H */
diff --git a/arch/csky/include/asm/spinlock_types.h b/arch/csky/include/asm/spinlock_types.h
new file mode 100644
index 0000000..ea890ef
--- /dev/null
+++ b/arch/csky/include/asm/spinlock_types.h
@@ -0,0 +1,20 @@
+#ifndef __ASM_CSKY_SPINLOCK_TYPES_H
+#define __ASM_CSKY_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+	unsigned int lock;
+} arch_spinlock_t;
+
+#define __ARCH_SPIN_LOCK_UNLOCKED	{ 0 }
+
+typedef struct {
+	unsigned int lock;
+} arch_rwlock_t;
+
+#define __ARCH_RW_LOCK_UNLOCKED		{ 0 }
+
+#endif
diff --git a/arch/csky/kernel/atomic.S b/arch/csky/kernel/atomic.S
new file mode 100644
index 0000000..95ae696
--- /dev/null
+++ b/arch/csky/kernel/atomic.S
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/linkage.h>
+#include <abi/entry.h>
+
+.text
+
+/*
+ * int csky_cmpxchg(int oldval, int newval, int *ptr)
+ *
+ * If *ptr != oldval && return 1,
+ * else *ptr = newval return 0.
+ */
+#ifdef CONFIG_CPU_HAS_LDSTEX
+ENTRY(csky_cmpxchg)
+	USPTOKSP
+	mfcr	a3, epc
+	INCTRAP	a3
+
+	subi    sp, 8
+	stw     a3, (sp, 0)
+	mfcr    a3, epsr
+	stw     a3, (sp, 4)
+
+	psrset	ee
+1:
+	ldex	a3, (a2)
+	cmpne	a0, a3
+	bt16	2f
+	mov	a3, a1
+	stex	a3, (a2)
+	bez	a3, 1b
+2:
+	sync.is
+	mvc	a0
+	ldw	a3, (sp, 0)
+	mtcr	a3, epc
+	ldw     a3, (sp, 4)
+	mtcr	a3, epsr
+	addi	sp, 8
+	KSPTOUSP
+	rte
+END(csky_cmpxchg)
+#else
+ENTRY(csky_cmpxchg)
+	USPTOKSP
+	mfcr	a3, epc
+	INCTRAP	a3
+
+	subi    sp, 8
+	stw     a3, (sp, 0)
+	mfcr    a3, epsr
+	stw     a3, (sp, 4)
+
+	psrset	ee
+1:
+	ldw	a3, (a2)
+	cmpne	a0, a3
+	bt16	3f
+2:
+	stw	a1, (a2)
+3:
+	mvc	a0
+	ldw	a3, (sp, 0)
+	mtcr	a3, epc
+	ldw     a3, (sp, 4)
+	mtcr	a3, epsr
+	addi	sp, 8
+	KSPTOUSP
+	rte
+END(csky_cmpxchg)
+
+/*
+ * Called from tlbmodified exception
+ */
+ENTRY(csky_cmpxchg_fixup)
+	mfcr	a0, epc
+	lrw	a1, 2b
+	cmpne	a1, a0
+	bt	1f
+	subi	a1, (2b - 1b)
+	stw	a1, (sp, LSAVE_PC)
+1:
+	rts
+END(csky_cmpxchg_fixup)
+#endif
+
-- 
2.7.4


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

* [PATCH V2 12/19] csky: ELF and module probe
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (10 preceding siblings ...)
  2018-07-01 17:30 ` [PATCH V2 11/19] csky: Atomic operations Guo Ren
@ 2018-07-01 17:30 ` Guo Ren
  2018-07-01 17:30 ` [PATCH V2 13/19] csky: Library functions Guo Ren
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/include/asm/elf.h | 149 ++++++++++++++++++++++++++++++++++++++++++++
 arch/csky/kernel/module.c   |  82 ++++++++++++++++++++++++
 2 files changed, 231 insertions(+)
 create mode 100644 arch/csky/include/asm/elf.h
 create mode 100644 arch/csky/kernel/module.c

diff --git a/arch/csky/include/asm/elf.h b/arch/csky/include/asm/elf.h
new file mode 100644
index 0000000..9a7967c
--- /dev/null
+++ b/arch/csky/include/asm/elf.h
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASMCSKY_ELF_H
+#define __ASMCSKY_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+#include <abi/regdef.h>
+
+#define ELF_ARCH 39
+
+/* CSKY Relocations */
+#define R_CSKY_NONE               0
+#define R_CSKY_32                 1
+#define R_CSKY_PCIMM8BY4          2
+#define R_CSKY_PCIMM11BY2         3
+#define R_CSKY_PCIMM4BY2          4
+#define R_CSKY_PC32               5
+#define R_CSKY_PCRELJSR_IMM11BY2  6
+#define R_CSKY_GNU_VTINHERIT      7
+#define R_CSKY_GNU_VTENTRY        8
+#define R_CSKY_RELATIVE           9
+#define R_CSKY_COPY               10
+#define R_CSKY_GLOB_DAT           11
+#define R_CSKY_JUMP_SLOT          12
+#define R_CSKY_ADDR_HI16          24
+#define R_CSKY_ADDR_LO16          25
+#define R_CSKY_PCRELJSR_IMM26BY2  40
+
+typedef unsigned long elf_greg_t;
+
+typedef struct user_fp elf_fpregset_t;
+
+#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t))
+
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) ((x)->e_machine == ELF_ARCH)
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE		4096
+#define ELF_CLASS			ELFCLASS32
+#define ELF_PLAT_INIT(_r, load_addr)	_r->a0 = 0
+
+#ifdef  __cskyBE__
+#define ELF_DATA	ELFDATA2MSB
+#else
+#define ELF_DATA	ELFDATA2LSB
+#endif
+
+/* 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	0x0UL
+
+/* The member sort in array pr_reg[x] is pc, r1, r0, psr, r2, r3,r4,
+   r5, r6...... Because GDB difine */
+#if defined(__CSKYABIV2__)
+   #define ELF_CORE_COPY_REGS(pr_reg, regs)     \
+        pr_reg[0] = regs->pc;                   \
+        pr_reg[1] = regs->a1;                   \
+        pr_reg[2] = regs->a0;                   \
+        pr_reg[3] = regs->sr;                   \
+        pr_reg[4] = regs->a2;                   \
+        pr_reg[5] = regs->a3;                   \
+        pr_reg[6] = regs->regs[0];              \
+        pr_reg[7] = regs->regs[1];              \
+        pr_reg[8] = regs->regs[2];              \
+        pr_reg[9] = regs->regs[3];              \
+        pr_reg[10] = regs->regs[4];             \
+        pr_reg[11] = regs->regs[5];             \
+        pr_reg[12] = regs->regs[6];             \
+        pr_reg[13] = regs->regs[7];             \
+        pr_reg[14] = regs->regs[8];             \
+        pr_reg[15] = regs->regs[9];             \
+        pr_reg[16] = regs->usp;			\
+        pr_reg[17] = regs->lr;			\
+        pr_reg[18] = regs->exregs[0];           \
+        pr_reg[19] = regs->exregs[1];           \
+        pr_reg[20] = regs->exregs[2];           \
+        pr_reg[21] = regs->exregs[3];           \
+        pr_reg[22] = regs->exregs[4];           \
+        pr_reg[23] = regs->exregs[5];           \
+        pr_reg[24] = regs->exregs[6];           \
+        pr_reg[25] = regs->exregs[7];           \
+        pr_reg[26] = regs->exregs[8];           \
+        pr_reg[27] = regs->exregs[9];           \
+        pr_reg[28] = regs->exregs[10];          \
+        pr_reg[29] = regs->exregs[11];          \
+        pr_reg[30] = regs->exregs[12];          \
+        pr_reg[31] = regs->exregs[13];          \
+        pr_reg[32] = regs->exregs[14];          \
+        pr_reg[33] = regs->tls;
+#else
+     #define ELF_CORE_COPY_REGS(pr_reg, regs)   \
+        pr_reg[0] = regs->pc;                   \
+        pr_reg[1] = regs->regs[9];              \
+        pr_reg[2] = regs->usp;			\
+        pr_reg[3] = regs->sr;                   \
+        pr_reg[4] = regs->a0;                   \
+        pr_reg[5] = regs->a1;                   \
+        pr_reg[6] = regs->a2;                   \
+        pr_reg[7] = regs->a3;                   \
+        pr_reg[8] = regs->regs[0];              \
+        pr_reg[9] = regs->regs[1];              \
+        pr_reg[10] = regs->regs[2];             \
+        pr_reg[11] = regs->regs[3];             \
+        pr_reg[12] = regs->regs[4];             \
+        pr_reg[13] = regs->regs[5];             \
+        pr_reg[14] = regs->regs[6];             \
+        pr_reg[15] = regs->regs[7];             \
+        pr_reg[16] = regs->regs[8];             \
+        pr_reg[17] = regs->lr;
+#endif
+
+/* Similar, but for a thread other than current. */
+struct task_struct;
+extern int dump_task_regs(struct task_struct *, elf_gregset_t *);
+#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
+
+/* 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)
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+struct linux_binprm;
+extern int arch_setup_additional_pages(
+		struct linux_binprm *bprm,
+		int uses_interp);
+
+#endif
diff --git a/arch/csky/kernel/module.c b/arch/csky/kernel/module.c
new file mode 100644
index 0000000..a8816e1
--- /dev/null
+++ b/arch/csky/kernel/module.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <asm/pgtable.h>
+
+#define IS_BSR32(hi16, lo16)        (((hi16) & 0xFC00) == 0xE000)
+#define IS_JSRI32(hi16, lo16)       ((hi16) == 0xEAE0)
+#define CHANGE_JSRI_TO_LRW(addr)    *(uint16_t *)(addr) = (*(uint16_t *)(addr) & 0xFF9F) | 0x001a; \
+							  *((uint16_t *)(addr) + 1) = *((uint16_t *)(addr) + 1) & 0xFFFF
+#define SET_JSR32_R26(addr)         *(uint16_t *)(addr) = 0xE8Fa; \
+							  *((uint16_t *)(addr) + 1) = 0x0000;
+
+int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
+		unsigned int symindex, unsigned int relsec, struct module *me)
+{
+	unsigned int i;
+	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+	Elf32_Sym *sym;
+	uint32_t *location;
+	short * temp;
+#ifdef CONFIG_CPU_CSKYV2
+	uint16_t *location_tmp;
+#endif
+
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* This is where to make the change */
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset;
+		/* This is the symbol it is referring to.  Note that all
+		   undefined symbols have been resolved.  */
+		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+			+ ELF32_R_SYM(rel[i].r_info);
+
+		switch (ELF32_R_TYPE(rel[i].r_info)) {
+		case R_CSKY_32:
+			/* We add the value into the location given */
+			*location = rel[i].r_addend + sym->st_value;
+			break;
+		case R_CSKY_PC32:
+			/* Add the value, subtract its postition */
+			*location = rel[i].r_addend + sym->st_value
+				- (uint32_t)location;
+			break;
+		case R_CSKY_PCRELJSR_IMM11BY2:
+			break;
+		case R_CSKY_PCRELJSR_IMM26BY2:
+#ifdef CONFIG_CPU_CSKYV2
+			location_tmp = (uint16_t *)location;
+			if (IS_BSR32(*location_tmp, *(location_tmp + 1)))
+				break;
+			else if (IS_JSRI32(*location_tmp, *(location_tmp + 1))) {
+				/* jsri 0x...  --> lrw r26, 0x... */
+				CHANGE_JSRI_TO_LRW(location);
+				/* lsli r0, r0 --> jsr r26 */
+				SET_JSR32_R26(location + 1);
+			}
+#endif
+			break;
+		case R_CSKY_ADDR_HI16:
+			temp = ((short  *)location) + 1;
+			*temp = (short)((rel[i].r_addend + sym->st_value) >> 16);
+			break;
+		case R_CSKY_ADDR_LO16:
+			temp = ((short  *)location) + 1;
+			*temp = (short)((rel[i].r_addend + sym->st_value) & 0xffff);
+			break;
+		default:
+			pr_err("module %s: Unknown relocation: %u\n",
+				me->name, ELF32_R_TYPE(rel[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+	return 0;
+}
-- 
2.7.4


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

* [PATCH V2 13/19] csky: Library functions
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (11 preceding siblings ...)
  2018-07-01 17:30 ` [PATCH V2 12/19] csky: ELF and module probe Guo Ren
@ 2018-07-01 17:30 ` Guo Ren
  2018-07-03 20:04   ` Arnd Bergmann
  2018-07-01 17:30 ` [PATCH V2 14/19] csky: User access Guo Ren
                   ` (6 subsequent siblings)
  19 siblings, 1 reply; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/abiv1/bswapdi.c      |  18 +++
 arch/csky/abiv1/bswapsi.c      |  15 ++
 arch/csky/abiv1/memcpy.S       | 344 +++++++++++++++++++++++++++++++++++++++++
 arch/csky/abiv2/memcpy.c       |  43 ++++++
 arch/csky/include/asm/string.h |  19 +++
 arch/csky/kernel/asm-offsets.c |  85 ++++++++++
 arch/csky/kernel/cskyksyms.c   |  31 ++++
 arch/csky/kernel/platform.c    |  18 +++
 arch/csky/kernel/power.c       |  31 ++++
 arch/csky/lib/delay.c          |  40 +++++
 arch/csky/lib/memset.c         |  38 +++++
 11 files changed, 682 insertions(+)
 create mode 100644 arch/csky/abiv1/bswapdi.c
 create mode 100644 arch/csky/abiv1/bswapsi.c
 create mode 100644 arch/csky/abiv1/memcpy.S
 create mode 100644 arch/csky/abiv2/memcpy.c
 create mode 100644 arch/csky/include/asm/string.h
 create mode 100644 arch/csky/kernel/asm-offsets.c
 create mode 100644 arch/csky/kernel/cskyksyms.c
 create mode 100644 arch/csky/kernel/platform.c
 create mode 100644 arch/csky/kernel/power.c
 create mode 100644 arch/csky/lib/delay.c
 create mode 100644 arch/csky/lib/memset.c

diff --git a/arch/csky/abiv1/bswapdi.c b/arch/csky/abiv1/bswapdi.c
new file mode 100644
index 0000000..7346252
--- /dev/null
+++ b/arch/csky/abiv1/bswapdi.c
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/export.h>
+#include <linux/compiler.h>
+
+unsigned long long notrace __bswapdi2(unsigned long long u)
+{
+	return (((u) & 0xff00000000000000ull) >> 56) |
+	       (((u) & 0x00ff000000000000ull) >> 40) |
+	       (((u) & 0x0000ff0000000000ull) >> 24) |
+	       (((u) & 0x000000ff00000000ull) >>  8) |
+	       (((u) & 0x00000000ff000000ull) <<  8) |
+	       (((u) & 0x0000000000ff0000ull) << 24) |
+	       (((u) & 0x000000000000ff00ull) << 40) |
+	       (((u) & 0x00000000000000ffull) << 56);
+}
+
+EXPORT_SYMBOL(__bswapdi2);
diff --git a/arch/csky/abiv1/bswapsi.c b/arch/csky/abiv1/bswapsi.c
new file mode 100644
index 0000000..21958ca
--- /dev/null
+++ b/arch/csky/abiv1/bswapsi.c
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/export.h>
+#include <linux/compiler.h>
+
+unsigned int notrace __bswapsi2(unsigned int u)
+{
+	return (((u) & 0xff000000) >> 24) |
+	       (((u) & 0x00ff0000) >>  8) |
+	       (((u) & 0x0000ff00) <<  8) |
+	       (((u) & 0x000000ff) << 24);
+}
+
+EXPORT_SYMBOL(__bswapsi2);
+
diff --git a/arch/csky/abiv1/memcpy.S b/arch/csky/abiv1/memcpy.S
new file mode 100644
index 0000000..f86ad75
--- /dev/null
+++ b/arch/csky/abiv1/memcpy.S
@@ -0,0 +1,344 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/linkage.h>
+
+.macro	GET_FRONT_BITS rx y
+#ifdef	__cskyLE__
+	lsri	\rx, \y
+#else
+	lsli	\rx, \y
+#endif
+.endm
+
+.macro	GET_AFTER_BITS rx y
+#ifdef	__cskyLE__
+	lsli	\rx, \y
+#else
+	lsri	\rx, \y
+#endif
+.endm
+
+/* void *memcpy(void *dest, const void *src, size_t n); */
+ENTRY(memcpy)
+	mov	r7, r2
+	cmplti	r4, 4                                   /* If len less than 4 bytes */
+	bt	.L_copy_by_byte
+	mov	r6, r2
+	andi	r6, 3
+	cmpnei	r6, 0
+	jbt	.L_dest_not_aligned                     /* If dest is not 4 bytes aligned */
+	mov	r6, r3
+	andi	r6, 3
+	cmpnei	r6, 0
+	jbt	.L_dest_aligned_but_src_not_aligned     /* If dest is aligned, but src is not aligned */
+.L0:
+	cmplti	r4, 16
+	jbt	.L_aligned_and_len_less_16bytes         /* If len less than 16 bytes */
+	subi	sp, 8
+	stw	r8, (sp, 0)
+.L_aligned_and_len_larger_16bytes:                      /* src and dst are all aligned, and len > 16 bytes */
+	ldw	r1, (r3, 0)
+	ldw	r5, (r3, 4)
+	ldw	r8, (r3, 8)
+	stw	r1, (r7, 0)
+	ldw	r1, (r3, 12)
+	stw	r5, (r7, 4)
+	stw	r8, (r7, 8)
+	stw	r1, (r7, 12)
+	subi	r4, 16
+	addi	r3, 16
+	addi	r7, 16
+	cmplti	r4, 16
+	jbf	.L_aligned_and_len_larger_16bytes
+	ldw	r8, (sp, 0)
+	addi	sp, 8
+	cmpnei	r4, 0                    /* If len == 0, return, else goto .L_aligned_and_len_less_16bytes  */
+	jbf	.L_return
+
+.L_aligned_and_len_less_16bytes:
+	cmplti	r4, 4
+	bt	.L_copy_by_byte
+.L1:
+	ldw	r1, (r3, 0)
+	stw	r1, (r7, 0)
+	subi	r4, 4
+	addi	r3, 4
+	addi	r7, 4
+	cmplti	r4, 4
+	jbf	.L1
+	br	.L_copy_by_byte
+
+.L_return:
+	rts
+
+.L_copy_by_byte:                      /* len less than 4 bytes */
+	cmpnei	r4, 0
+	jbf	.L_return
+.L4:
+	ldb	r1, (r3, 0)
+	stb	r1, (r7, 0)
+	addi	r3, 1
+	addi	r7, 1
+	decne	r4
+	jbt	.L4
+	rts
+
+/* If dest is not aligned, just copying some bytes makes the dest align.
+   Afther that, we judge whether the src is aligned. */
+.L_dest_not_aligned:
+	mov	r5, r3
+	rsub	r5, r5, r7
+	abs	r5, r5
+	cmplt	r5, r4
+	bt	.L_copy_by_byte
+	mov	r5, r7
+	sub	r5, r3
+	cmphs	r5, r4
+	bf	.L_copy_by_byte
+	mov	r5, r6
+.L5:
+	ldb	r1, (r3, 0)              /* makes the dest align. */
+	stb	r1, (r7, 0)
+	addi	r5, 1
+	subi	r4, 1
+	addi	r3, 1
+	addi	r7, 1
+	cmpnei	r5, 4
+	jbt	.L5
+	cmplti	r4, 4
+	jbt	.L_copy_by_byte
+	mov	r6, r3                   /* judge whether the src is aligned. */
+	andi	r6, 3
+	cmpnei	r6, 0
+	jbf	.L0
+
+/* Judge the number of misaligned, 1, 2, 3? */
+.L_dest_aligned_but_src_not_aligned:
+	mov	r5, r3
+	rsub	r5, r5, r7
+	abs	r5, r5
+	cmplt	r5, r4
+	bt	.L_copy_by_byte
+	bclri	r3, 0
+	bclri	r3, 1
+	ldw	r1, (r3, 0)
+	addi	r3, 4
+	cmpnei	r6, 2
+	bf	.L_dest_aligned_but_src_not_aligned_2bytes
+	cmpnei	r6, 3
+	bf	.L_dest_aligned_but_src_not_aligned_3bytes
+
+.L_dest_aligned_but_src_not_aligned_1byte:
+	mov	r5, r7
+	sub	r5, r3
+	cmphs	r5, r4
+	bf	.L_copy_by_byte
+	cmplti	r4, 16
+	bf	.L11
+.L10:                                     /* If the len is less than 16 bytes */
+	GET_FRONT_BITS r1 8
+	mov	r5, r1
+	ldw	r6, (r3, 0)
+	mov	r1, r6
+	GET_AFTER_BITS r6 24
+	or	r5, r6
+	stw	r5, (r7, 0)
+	subi	r4, 4
+	addi	r3, 4
+	addi	r7, 4
+	cmplti	r4, 4
+	bf	.L10
+	subi	r3, 3
+	br	.L_copy_by_byte
+.L11:
+	subi	sp, 16
+	stw	r8, (sp, 0)
+	stw	r9, (sp, 4)
+	stw	r10, (sp, 8)
+	stw	r11, (sp, 12)
+.L12:
+	ldw	r5, (r3, 0)
+	ldw	r11, (r3, 4)
+	ldw	r8, (r3, 8)
+	ldw	r9, (r3, 12)
+
+	GET_FRONT_BITS r1 8               /* little or big endian? */
+	mov	r10, r5
+	GET_AFTER_BITS r5 24
+	or	r5, r1
+
+	GET_FRONT_BITS r10 8
+	mov	r1, r11
+	GET_AFTER_BITS r11 24
+	or	r11, r10
+
+	GET_FRONT_BITS r1 8
+	mov	r10, r8
+	GET_AFTER_BITS r8 24
+	or	r8, r1
+
+	GET_FRONT_BITS r10 8
+	mov	r1, r9
+	GET_AFTER_BITS r9 24
+	or	r9, r10
+
+	stw	r5, (r7, 0)
+	stw	r11, (r7, 4)
+	stw	r8, (r7, 8)
+	stw	r9, (r7, 12)
+	subi	r4, 16
+	addi	r3, 16
+	addi	r7, 16
+	cmplti	r4, 16
+	jbf	.L12
+	ldw	r8, (sp, 0)
+	ldw	r9, (sp, 4)
+	ldw	r10, (sp, 8)
+	ldw	r11, (sp, 12)
+	addi	sp , 16
+	cmplti	r4, 4
+	bf	.L10
+	subi	r3, 3
+	br	.L_copy_by_byte
+
+.L_dest_aligned_but_src_not_aligned_2bytes:
+	cmplti	r4, 16
+	bf	.L21
+.L20:
+	GET_FRONT_BITS r1 16
+	mov	r5, r1
+	ldw	r6, (r3, 0)
+	mov	r1, r6
+	GET_AFTER_BITS r6 16
+	or	r5, r6
+	stw	r5, (r7, 0)
+	subi	r4, 4
+	addi	r3, 4
+	addi	r7, 4
+	cmplti	r4, 4
+	bf	.L20
+	subi	r3, 2
+	br	.L_copy_by_byte
+	rts
+
+.L21:	/* n > 16 */
+	subi 	sp, 16
+	stw	r8, (sp, 0)
+	stw	r9, (sp, 4)
+	stw	r10, (sp, 8)
+	stw	r11, (sp, 12)
+
+.L22:
+	ldw	r5, (r3, 0)
+	ldw	r11, (r3, 4)
+	ldw	r8, (r3, 8)
+	ldw	r9, (r3, 12)
+
+	GET_FRONT_BITS r1 16
+	mov	r10, r5
+	GET_AFTER_BITS r5 16
+	or	r5, r1
+
+	GET_FRONT_BITS r10 16
+	mov	r1, r11
+	GET_AFTER_BITS r11 16
+	or	r11, r10
+
+	GET_FRONT_BITS r1 16
+	mov	r10, r8
+	GET_AFTER_BITS r8 16
+	or	r8, r1
+
+	GET_FRONT_BITS r10 16
+	mov	r1, r9
+	GET_AFTER_BITS r9 16
+	or	r9, r10
+
+	stw	r5, (r7, 0)
+	stw	r11, (r7, 4)
+	stw	r8, (r7, 8)
+	stw	r9, (r7, 12)
+	subi	r4, 16
+	addi	r3, 16
+	addi	r7, 16
+	cmplti	r4, 16
+	jbf	.L22
+	ldw	r8, (sp, 0)
+	ldw	r9, (sp, 4)
+	ldw	r10, (sp, 8)
+	ldw	r11, (sp, 12)
+	addi	sp, 16
+	cmplti	r4, 4
+	bf	.L20
+	subi	r3, 2
+	br	.L_copy_by_byte
+
+
+.L_dest_aligned_but_src_not_aligned_3bytes:
+	cmplti	r4, 16
+	bf	.L31
+.L30:
+	GET_FRONT_BITS r1 24
+	mov	r5, r1
+	ldw	r6, (r3, 0)
+	mov	r1, r6
+	GET_AFTER_BITS r6 8
+	or	r5, r6
+	stw	r5, (r7, 0)
+	subi	r4, 4
+	addi	r3, 4
+	addi	r7, 4
+	cmplti	r4, 4
+	bf	.L30
+	subi	r3, 1
+	br	.L_copy_by_byte
+.L31:
+	subi	sp, 16
+	stw	r8, (sp, 0)
+	stw	r9, (sp, 4)
+	stw	r10, (sp, 8)
+	stw	r11, (sp, 12)
+.L32:
+	ldw	r5, (r3, 0)
+	ldw	r11, (r3, 4)
+	ldw	r8, (r3, 8)
+	ldw	r9, (r3, 12)
+
+	GET_FRONT_BITS r1 24
+	mov	r10, r5
+	GET_AFTER_BITS r5 8
+	or	r5, r1
+
+	GET_FRONT_BITS r10 24
+	mov	r1, r11
+	GET_AFTER_BITS r11 8
+	or	r11, r10
+
+	GET_FRONT_BITS r1 24
+	mov	r10, r8
+	GET_AFTER_BITS r8 8
+	or	r8, r1
+
+	GET_FRONT_BITS r10 24
+	mov	r1, r9
+	GET_AFTER_BITS r9 8
+	or	r9, r10
+
+	stw	r5, (r7, 0)
+	stw	r11, (r7, 4)
+	stw	r8, (r7, 8)
+	stw	r9, (r7, 12)
+	subi	r4, 16
+	addi	r3, 16
+	addi	r7, 16
+	cmplti	r4, 16
+	jbf	.L32
+	ldw	r8, (sp, 0)
+	ldw	r9, (sp, 4)
+	ldw	r10, (sp, 8)
+	ldw	r11, (sp, 12)
+	addi	sp, 16
+	cmplti	r4, 4
+	bf	.L30
+	subi	r3, 1
+	br	.L_copy_by_byte
diff --git a/arch/csky/abiv2/memcpy.c b/arch/csky/abiv2/memcpy.c
new file mode 100644
index 0000000..67d8d01
--- /dev/null
+++ b/arch/csky/abiv2/memcpy.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/types.h>
+
+/*
+ * memory copy function.
+ */
+void *memcpy (void *to, const void *from, size_t l)
+{
+	char *d = to;
+	const char *s = from;
+
+	if (((long)d | (long)s) & 0x3)
+	{
+		while (l--) *d++ = *s++;
+	}
+	else
+	{
+        	while (l >= 16)
+		{
+			*(((long *)d)) = *(((long *)s));
+			*(((long *)d)+1) = *(((long *)s)+1);
+			*(((long *)d)+2) = *(((long *)s)+2);
+			*(((long *)d)+3) = *(((long *)s)+3);
+			l -= 16;
+			d += 16;
+			s += 16;
+		}
+		while (l > 3)
+		{
+			*(((long *)d)) = *(((long *)s));
+			d = d +4;
+			s = s +4;
+			l -= 4;
+		}
+		while (l)
+		{
+			*d++ = *s++;
+			l--;	
+		}
+	}
+	return to;
+}
diff --git a/arch/csky/include/asm/string.h b/arch/csky/include/asm/string.h
new file mode 100644
index 0000000..2c4878b
--- /dev/null
+++ b/arch/csky/include/asm/string.h
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef _CSKY_STRING_MM_H_
+#define _CSKY_STRING_MM_H_
+
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+#define __HAVE_ARCH_MEMCPY
+extern void * memcpy(void *to, const void *from, size_t l);
+
+/* New and improved.  In arch/csky/lib/memset.c */
+#define __HAVE_ARCH_MEMSET
+extern void * memset(void *dest, int c, size_t l);
+
+#endif
+
+#endif /* _CSKY_STRING_MM_H_ */
diff --git a/arch/csky/kernel/asm-offsets.c b/arch/csky/kernel/asm-offsets.c
new file mode 100644
index 0000000..d7868dd
--- /dev/null
+++ b/arch/csky/kernel/asm-offsets.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/kbuild.h>
+#include <abi/regdef.h>
+
+int main(void)
+{
+	/* offsets into the task struct */
+	DEFINE(TASK_STATE,        offsetof(struct task_struct, state));
+	DEFINE(TASK_THREAD_INFO,  offsetof(struct task_struct, stack));
+	DEFINE(TASK_FLAGS,        offsetof(struct task_struct, flags));
+	DEFINE(TASK_PTRACE,       offsetof(struct task_struct, ptrace));
+	DEFINE(TASK_THREAD,       offsetof(struct task_struct, thread));
+	DEFINE(TASK_MM,           offsetof(struct task_struct, mm));
+	DEFINE(TASK_ACTIVE_MM,    offsetof(struct task_struct, active_mm));
+
+	/* offsets into the thread struct */
+	DEFINE(THREAD_KSP,        offsetof(struct thread_struct, ksp));
+	DEFINE(THREAD_SR,         offsetof(struct thread_struct, sr));
+	DEFINE(THREAD_ESP0,       offsetof(struct thread_struct, esp0));
+	DEFINE(THREAD_FESR,       offsetof(struct thread_struct, user_fp.fesr));
+	DEFINE(THREAD_FCR,        offsetof(struct thread_struct, user_fp.fcr));
+	DEFINE(THREAD_FPREG,      offsetof(struct thread_struct, user_fp.vr));
+	DEFINE(THREAD_DSPHI,      offsetof(struct thread_struct, hi));
+	DEFINE(THREAD_DSPLO,      offsetof(struct thread_struct, lo));
+
+	/* offsets into the thread_info struct */
+	DEFINE(TINFO_FLAGS,       offsetof(struct thread_info, flags));
+	DEFINE(TINFO_PREEMPT,     offsetof(struct thread_info, preempt_count));
+	DEFINE(TINFO_ADDR_LIMIT,  offsetof(struct thread_info, addr_limit));
+	DEFINE(TINFO_TP_VALUE,   offsetof(struct thread_info, tp_value));
+	DEFINE(TINFO_TASK,        offsetof(struct thread_info, task));
+
+	/* offsets into the pt_regs */
+	DEFINE(PT_PC,             offsetof(struct pt_regs, pc));
+	DEFINE(PT_ORIG_AO,        offsetof(struct pt_regs, orig_a0));
+	DEFINE(PT_SR,             offsetof(struct pt_regs, sr));
+
+	DEFINE(PT_A0,             offsetof(struct pt_regs, a0));
+	DEFINE(PT_A1,             offsetof(struct pt_regs, a1));
+	DEFINE(PT_A2,             offsetof(struct pt_regs, a2));
+	DEFINE(PT_A3,             offsetof(struct pt_regs, a3));
+	DEFINE(PT_REGS0,          offsetof(struct pt_regs, regs[0]));
+	DEFINE(PT_REGS1,          offsetof(struct pt_regs, regs[1]));
+	DEFINE(PT_REGS2,          offsetof(struct pt_regs, regs[2]));
+	DEFINE(PT_REGS3,          offsetof(struct pt_regs, regs[3]));
+	DEFINE(PT_REGS4,          offsetof(struct pt_regs, regs[4]));
+	DEFINE(PT_REGS5,          offsetof(struct pt_regs, regs[5]));
+	DEFINE(PT_REGS6,          offsetof(struct pt_regs, regs[6]));
+	DEFINE(PT_REGS7,          offsetof(struct pt_regs, regs[7]));
+	DEFINE(PT_REGS8,          offsetof(struct pt_regs, regs[8]));
+	DEFINE(PT_REGS9,          offsetof(struct pt_regs, regs[9]));
+	DEFINE(PT_R15,            offsetof(struct pt_regs, lr));
+#if defined(__CSKYABIV2__)
+	DEFINE(PT_R16,            offsetof(struct pt_regs, exregs[0]));
+	DEFINE(PT_R17,            offsetof(struct pt_regs, exregs[1]));
+	DEFINE(PT_R18,            offsetof(struct pt_regs, exregs[2]));
+	DEFINE(PT_R19,            offsetof(struct pt_regs, exregs[3]));
+	DEFINE(PT_R20,            offsetof(struct pt_regs, exregs[4]));
+	DEFINE(PT_R21,            offsetof(struct pt_regs, exregs[5]));
+	DEFINE(PT_R22,            offsetof(struct pt_regs, exregs[6]));
+	DEFINE(PT_R23,            offsetof(struct pt_regs, exregs[7]));
+	DEFINE(PT_R24,            offsetof(struct pt_regs, exregs[8]));
+	DEFINE(PT_R25,            offsetof(struct pt_regs, exregs[9]));
+	DEFINE(PT_R26,            offsetof(struct pt_regs, exregs[10]));
+	DEFINE(PT_R27,            offsetof(struct pt_regs, exregs[11]));
+	DEFINE(PT_R28,            offsetof(struct pt_regs, exregs[12]));
+	DEFINE(PT_R29,            offsetof(struct pt_regs, exregs[13]));
+	DEFINE(PT_R30,            offsetof(struct pt_regs, exregs[14]));
+	DEFINE(PT_R31,            offsetof(struct pt_regs, exregs[15]));
+	DEFINE(PT_RHI,            offsetof(struct pt_regs, rhi));
+	DEFINE(PT_RLO,            offsetof(struct pt_regs, rlo));
+#endif
+	DEFINE(PT_USP,            offsetof(struct pt_regs, usp));
+	/* offsets into the irq_cpustat_t struct */
+	DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
+
+	/* signal defines */
+	DEFINE(SIGSEGV, SIGSEGV);
+	DEFINE(SIGTRAP, SIGTRAP);
+
+	return 0;
+}
diff --git a/arch/csky/kernel/cskyksyms.c b/arch/csky/kernel/cskyksyms.c
new file mode 100644
index 0000000..3f13594
--- /dev/null
+++ b/arch/csky/kernel/cskyksyms.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <asm/cacheflush.h>
+
+/*
+ * Defined in libgcc
+ *
+ * See arch/csky/Makefile:
+ *	-print-libgcc-file-name
+ */
+extern void __ashldi3 (void);
+extern void __ashrdi3 (void);
+extern void __lshrdi3 (void);
+extern void __muldi3 (void);
+extern void __ucmpdi2 (void);
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__ucmpdi2);
+
+/*
+ * Defined in abiv1/src/memcpy.S
+ * and abiv2/src/memcpy.c
+ */
+EXPORT_SYMBOL(memcpy);
+
+/* Defined in lib/memset.c */
+EXPORT_SYMBOL(memset);
diff --git a/arch/csky/kernel/platform.c b/arch/csky/kernel/platform.c
new file mode 100644
index 0000000..f51654f
--- /dev/null
+++ b/arch/csky/kernel/platform.c
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/init.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
+#include <linux/io.h>
+
+static int __init csky_platform_init(void)
+{
+	return of_platform_default_populate(NULL, NULL, NULL);
+}
+device_initcall(csky_platform_init);
+
+
diff --git a/arch/csky/kernel/power.c b/arch/csky/kernel/power.c
new file mode 100644
index 0000000..d35e882
--- /dev/null
+++ b/arch/csky/kernel/power.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/reboot.h>
+
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
+void machine_power_off(void)
+{
+	local_irq_disable();
+	if (pm_power_off)
+		pm_power_off();
+	asm volatile ("bkpt");
+}
+
+void machine_halt(void)
+{
+	local_irq_disable();
+	if (pm_power_off)
+		pm_power_off();
+	asm volatile ("bkpt");
+}
+
+void machine_restart(char *cmd)
+{
+	local_irq_disable();
+	do_kernel_restart(cmd);
+	asm volatile ("bkpt");
+}
+
+
diff --git a/arch/csky/lib/delay.c b/arch/csky/lib/delay.c
new file mode 100644
index 0000000..34766a4
--- /dev/null
+++ b/arch/csky/lib/delay.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+void __delay(unsigned long loops)
+{
+       asm volatile (
+		"mov r0, r0\n"
+		"1:declt %0\n"
+		"bf	1b"
+                :"=r"(loops)
+	        :"0"(loops));
+}
+EXPORT_SYMBOL(__delay);
+
+extern unsigned long loops_per_jiffy;
+
+void __const_udelay(unsigned long xloops)
+{
+	unsigned long long loops;
+
+	loops = (unsigned long long)xloops * loops_per_jiffy * HZ;
+
+	__delay(loops >> 32);
+}
+EXPORT_SYMBOL(__const_udelay);
+
+void __udelay(unsigned long usecs)
+{
+	__const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */
+}
+EXPORT_SYMBOL(__udelay);
+
+void __ndelay(unsigned long nsecs)
+{
+	__const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */
+}
+EXPORT_SYMBOL(__ndelay);
diff --git a/arch/csky/lib/memset.c b/arch/csky/lib/memset.c
new file mode 100644
index 0000000..b7897af
--- /dev/null
+++ b/arch/csky/lib/memset.c
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/types.h>
+
+void *memset(void *dest, int c, size_t l)
+{
+	char *d = dest;
+	int ch = c;
+	int tmp;
+
+	if ((long)d & 0x3)
+		while (l--) *d++ = ch;
+	else {
+		ch &= 0xff;
+		tmp = (ch | ch << 8 | ch << 16 | ch << 24);
+
+		while (l >= 16) {
+			*(((long *)d)) = tmp;
+			*(((long *)d)+1) = tmp;
+			*(((long *)d)+2) = tmp;
+			*(((long *)d)+3) = tmp;
+			l -= 16;
+			d += 16;
+		}
+
+		while (l > 3) {
+			*(((long *)d)) = tmp;
+			d = d + 4;
+			l -= 4;
+		}
+
+		while (l) {
+			*d++ = ch;
+			l--;
+		}
+	}
+	return dest;
+}
-- 
2.7.4


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

* [PATCH V2 14/19] csky: User access
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (12 preceding siblings ...)
  2018-07-01 17:30 ` [PATCH V2 13/19] csky: Library functions Guo Ren
@ 2018-07-01 17:30 ` Guo Ren
  2018-07-01 17:30 ` [PATCH V2 15/19] csky: Debug and Ptrace GDB Guo Ren
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/include/asm/uaccess.h | 397 ++++++++++++++++++++++++++++++++++++++++
 arch/csky/lib/usercopy.c        | 271 +++++++++++++++++++++++++++
 2 files changed, 668 insertions(+)
 create mode 100644 arch/csky/include/asm/uaccess.h
 create mode 100644 arch/csky/lib/usercopy.c

diff --git a/arch/csky/include/asm/uaccess.h b/arch/csky/include/asm/uaccess.h
new file mode 100644
index 0000000..81063c3
--- /dev/null
+++ b/arch/csky/include/asm/uaccess.h
@@ -0,0 +1,397 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_UACCESS_H
+#define __ASM_CSKY_UACCESS_H
+
+/*
+ * User space memory access functions
+ */
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <asm/segment.h>
+
+#define VERIFY_READ	0
+#define VERIFY_WRITE	1
+
+static inline int access_ok(int type, const void * addr, unsigned long size)
+{
+    return (((unsigned long)addr < current_thread_info()->addr_limit.seg) &&
+              ((unsigned long)(addr + size) < current_thread_info()->addr_limit.seg));
+}
+
+static inline int verify_area(int type, const void * addr, unsigned long size)
+{
+    return access_ok(type, addr, size) ? 0 : -EFAULT;
+}
+
+#define __addr_ok(addr) (access_ok(VERIFY_READ, addr,0))
+
+extern int __put_user_bad(void);
+
+/*
+ * Tell gcc we read from memory instead of writing: this is because
+ * we do not write to any memory gcc knows about, so there are no
+ * aliasing issues.
+ */
+
+/*
+ * These are the main single-value transfer routines.  They automatically
+ * use the right size if we just have the right pointer type.
+ *
+ * This gets kind of ugly. We want to return _two_ values in "get_user()"
+ * and yet we don't want to do any pointers, because that is too much
+ * of a performance impact. Thus we have a few rather ugly macros here,
+ * and hide all the ugliness from the user.
+ *
+ * The "__xxx" versions of the user access functions are versions that
+ * do not verify the address space, that must have been done previously
+ * with a separate "access_ok()" call (this is used when we do multiple
+ * accesses to the same area of user memory).
+ *
+ * As we use the same address space for kernel and user data on
+ * Ckcore, we can just do these as direct assignments.  (Of course, the
+ * exception handling means that it's no longer "just"...)
+ */
+
+#define put_user(x,ptr) \
+  __put_user_check((x), (ptr), sizeof(*(ptr)))
+
+#define __put_user(x,ptr) \
+  __put_user_nocheck((x), (ptr), sizeof(*(ptr)))
+
+#define __ptr(x) ((unsigned long *)(x))
+
+#define get_user(x,ptr) \
+  __get_user_check((x), (ptr), sizeof(*(ptr)))
+
+#define __get_user(x,ptr) \
+  __get_user_nocheck((x), (ptr), sizeof(*(ptr)))
+
+#define __put_user_nocheck(x, ptr, size)                                \
+({                                                                      \
+	long __pu_err=0;                                                \
+	typeof(*(ptr)) *__pu_addr = (ptr);                              \
+	typeof(*(ptr)) __pu_val = (typeof(*(ptr)))(x);                  \
+	if(__pu_addr){                                                  \
+	    __put_user_size(__pu_val, (__pu_addr), (size), __pu_err);   \
+	}                                                               \
+	__pu_err;                                                       \
+})
+
+#define __put_user_check(x,ptr,size)                                    \
+({                                                                      \
+	long __pu_err = -EFAULT;                                        \
+	typeof(*(ptr)) *__pu_addr = (ptr);                              \
+	typeof(*(ptr)) __pu_val = (typeof(*(ptr)))(x);                  \
+	if (access_ok(VERIFY_WRITE, __pu_addr, size) && __pu_addr)      \
+		__put_user_size(__pu_val, __pu_addr, (size), __pu_err); \
+	__pu_err;                                                       \
+})
+
+#define __put_user_size(x,ptr,size,retval)                              \
+do {                                                                    \
+	retval = 0;                                                     \
+	switch (size) {                                                 \
+		case 1: __put_user_asm_b(x, ptr, retval); break;        \
+		case 2: __put_user_asm_h(x, ptr, retval); break;        \
+		case 4: __put_user_asm_w(x, ptr, retval); break;        \
+		case 8: __put_user_asm_64(x, ptr, retval); break;       \
+		default: __put_user_bad();                              \
+	}	                                                        \
+} while (0)
+
+/*
+ * We don't tell gcc that we are accessing memory, but this is OK
+ * because we do not write to any memory gcc knows about, so there
+ * are no aliasing issues.
+ *
+ * Note that PC at a fault is the address *after* the faulting
+ * instruction.
+ */
+#define __put_user_asm_b(x, ptr, err)                           \
+do{                                                             \
+	int errcode;                                            \
+	asm volatile(                                           \
+	         "1:     stb   %1, (%2,0)        \n"            \
+	         "       br    3f                \n"            \
+	         "2:     mov   %0, %3            \n"            \
+	         "       br    3f                \n"            \
+	         ".section __ex_table,\"a\"      \n"            \
+	         ".align   2                     \n"            \
+	         ".long    1b,2b                 \n"            \
+	         ".previous                      \n"            \
+	          "3:                            \n"            \
+	         : "=r"(err), "=r"(x), "=r"(ptr), "=r"(errcode) \
+	         : "0"(err), "1"(x), "2"(ptr), "3"(-EFAULT)     \
+	         : "memory");                                   \
+}while(0)
+
+#define __put_user_asm_h(x, ptr, err)                           \
+do{                                                             \
+	int errcode;                                            \
+	asm volatile(                                           \
+	         "1:     sth   %1, (%2,0)        \n"            \
+	         "       br    3f                \n"            \
+	         "2:     mov   %0, %3            \n"            \
+	         "       br    3f                \n"            \
+	         ".section __ex_table,\"a\"      \n"            \
+	         ".align   2                     \n"            \
+	         ".long    1b,2b                 \n"            \
+	         ".previous                      \n"            \
+	          "3:                            \n"            \
+	         :"=r"(err), "=r"(x), "=r"(ptr), "=r"(errcode)  \
+	         :"0"(err), "1"(x), "2"(ptr), "3"(-EFAULT)      \
+	         : "memory");                                   \
+}while(0)
+
+#define __put_user_asm_w(x, ptr, err)                           \
+do{                                                             \
+	int errcode;                                            \
+	asm volatile(                                           \
+	         "1:     stw   %1, (%2,0)        \n"            \
+	         "       br    3f                \n"            \
+	         "2:     mov   %0, %3            \n"            \
+	         "       br    3f                \n"            \
+	         ".section __ex_table,\"a\"      \n"            \
+	         ".align   2                     \n"            \
+	         ".long    1b,2b                 \n"            \
+	         ".previous                      \n"            \
+	          "3:                            \n"            \
+	         :"=r"(err), "=r"(x), "=r"(ptr), "=r"(errcode)  \
+	         :"0"(err), "1"(x), "2"(ptr), "3"(-EFAULT)      \
+	         : "memory");                                   \
+}while(0)
+
+
+#define __put_user_asm_64(x, ptr, err)                          \
+do{                                                             \
+	int tmp;                                                \
+	int errcode;                                            \
+	typeof(*(ptr)) src = ( typeof(*(ptr)))x;                \
+	typeof(*(ptr)) *psrc = &src;                            \
+	                                                        \
+	asm volatile(                                           \
+	        "     ldw     %3, (%1, 0)     \n"               \
+	        "1:   stw     %3, (%2, 0)     \n"               \
+	        "     ldw     %3, (%1, 4)     \n"               \
+	        "2:   stw     %3, (%2, 4)     \n"               \
+	        "     br      4f              \n"               \
+	        "3:   mov     %0, %4          \n"               \
+	        "     br      4f              \n"               \
+	        ".section __ex_table, \"a\"   \n"               \
+	        ".align   2                   \n"               \
+	        ".long    1b, 3b              \n"               \
+	        ".long    2b, 3b              \n"               \
+	        ".previous                    \n"               \
+	        "4:                           \n"               \
+	        :"=r"(err),"=r"(psrc),"=r"(ptr),"=r"(tmp),"=r"(errcode) \
+	        : "0"(err), "1"(psrc), "2"(ptr), "3"(0), "4"(-EFAULT) \
+	        : "memory" );                                   \
+}while (0)
+
+#define __get_user_nocheck(x, ptr, size)                        \
+({                                                              \
+	long  __gu_err;	                                        \
+	__get_user_size(x, (ptr), (size), __gu_err);            \
+	__gu_err;                                               \
+})
+
+#define __get_user_check(x, ptr, size)                          \
+({                                                              \
+	int __gu_err = -EFAULT;	                                \
+	const __typeof__(*(ptr)) __user * __gu_ptr = (ptr);     \
+	if (access_ok(VERIFY_READ, __gu_ptr, size) && __gu_ptr) \
+		__get_user_size(x, __gu_ptr, (size), __gu_err); \
+	__gu_err;                                               \
+})
+
+#define __get_user_size(x, ptr, size, retval)                   \
+do {                                                            \
+	switch (size) {                                         \
+		case 1: __get_user_asm_common((x),ptr,"ldb",retval); break; \
+		case 2: __get_user_asm_common((x),ptr,"ldh",retval); break; \
+		case 4: __get_user_asm_common((x),ptr,"ldw",retval); break; \
+		default:                                        \
+			x=0;                                    \
+			(retval) = __get_user_bad();            \
+	}                                                       \
+} while (0)
+
+#define __get_user_asm_common(x, ptr, ins, err)                 \
+do{                                                             \
+	int errcode;                                            \
+	asm volatile(                                           \
+	        "1:   " ins "   %1, (%4,0)      \n"             \
+	        "       br    3f                \n"             \
+	        /* Fix up codes */                              \
+	        "2:     mov   %0, %2            \n"             \
+	        "       movi  %1, 0             \n"             \
+	        "       br    3f                \n"             \
+	        ".section __ex_table,\"a\"      \n"             \
+	        ".align   2                     \n"             \
+	        ".long    1b,2b                 \n"             \
+	        ".previous                      \n"             \
+	        "3:                            \n"              \
+	        :"=r"(err), "=r"(x), "=r"(errcode)              \
+	        :"0"(0), "r"(ptr), "2"(-EFAULT)                 \
+	        : "memory");                                    \
+}while(0)
+
+extern int __get_user_bad(void);
+
+#define __copy_user(to, from, n)                                \
+do{                                                             \
+	int w0, w1, w2, w3;                                     \
+	asm volatile(                                           \
+		"0:     cmpnei  %1, 0           \n"             \
+		"       bf      8f              \n"             \
+		"       mov     %3, %1          \n"             \
+		"       or      %3, %2          \n"             \
+		"       andi    %3, 3           \n"             \
+		"       cmpnei  %3, 0           \n"             \
+		"       bf      1f              \n"             \
+		"       br      5f              \n"             \
+		"1:     cmplti  %0, 16          \n"   /* 4W */  \
+		"       bt      3f              \n"             \
+		"       ldw     %3, (%2, 0)     \n"             \
+		"       ldw     %4, (%2, 4)     \n"             \
+		"       ldw     %5, (%2, 8)     \n"             \
+		"       ldw     %6, (%2, 12)    \n"             \
+		"2:     stw     %3, (%1, 0)     \n"             \
+		"9:     stw     %4, (%1, 4)     \n"             \
+		"10:    stw     %5, (%1, 8)     \n"             \
+		"11:    stw     %6, (%1, 12)    \n"             \
+		"       addi    %2, 16          \n"             \
+		"       addi    %1, 16          \n"             \
+		"       subi    %0, 16          \n"             \
+		"       br      1b              \n"             \
+		"3:     cmplti  %0, 4           \n"  /* 1W */   \
+		"       bt      5f              \n"             \
+		"       ldw     %3, (%2, 0)     \n"             \
+		"4:     stw     %3, (%1, 0)     \n"             \
+		"       addi    %2, 4           \n"             \
+		"       addi    %1, 4           \n"             \
+		"       subi    %0, 4           \n"             \
+		"       br      3b              \n"             \
+		"5:     cmpnei  %0, 0           \n"  /* 1B */   \
+		"       bf      8f              \n"             \
+		"       ldb     %3, (%2, 0)     \n"             \
+		"6:     stb     %3, (%1, 0)     \n"             \
+		"       addi    %2,  1          \n"             \
+		"       addi    %1,  1          \n"             \
+		"       subi    %0,  1          \n"             \
+		"       br      5b              \n"             \
+		"7:     br      8f              \n"             \
+		".section __ex_table, \"a\"     \n"             \
+		".align   2                     \n"             \
+		".long    2b, 7b                \n"             \
+		".long    9b, 7b                \n"             \
+		".long   10b, 7b                \n"             \
+		".long   11b, 7b                \n"             \
+		".long    4b, 7b                \n"             \
+		".long    6b, 7b                \n"             \
+		".previous                      \n"             \
+		"8:                             \n"             \
+	        : "=r"(n), "=r"(to), "=r"(from), "=r"(w0), "=r"(w1), "=r"(w2), "=r"(w3)   \
+		: "0"(n), "1"(to), "2"(from)                    \
+		: "memory" );                                   \
+} while (0)
+
+#define __copy_user_zeroing(to, from, n) \
+do{                                                             \
+	int tmp;                                                \
+	int nsave;                                              \
+	asm volatile(                                           \
+		"0:     cmpnei  %1, 0           \n"             \
+		"       bf      7f              \n"             \
+		"       mov     %3, %1          \n"             \
+		"       or      %3, %2          \n"             \
+		"       andi    %3, 3           \n"             \
+		"       cmpnei  %3, 0           \n"             \
+		"       bf      1f              \n"             \
+		"       br      5f              \n"             \
+		"1:     cmplti  %0, 16          \n"   /* 4W */  \
+		"       bt      3f              \n"             \
+		"2:     ldw     %3, (%2, 0)     \n"             \
+		"10:    ldw     %4, (%2, 4)     \n"             \
+		"       stw     %3, (%1, 0)     \n"             \
+		"       stw     %4, (%1, 4)     \n"             \
+		"11:    ldw     %3, (%2, 8)     \n"             \
+		"12:    ldw     %4, (%2, 12)    \n"             \
+		"       stw     %3, (%1, 8)     \n"             \
+		"       stw     %4, (%1, 12)    \n"             \
+		"       addi    %2, 16          \n"             \
+		"       addi    %1, 16          \n"             \
+		"       subi    %0, 16          \n"             \
+		"       br      1b              \n"             \
+		"3:     cmplti  %0, 4           \n"  /* 1W */   \
+		"       bt      5f              \n"             \
+		"4:     ldw     %3, (%2, 0)     \n"             \
+		"       stw     %3, (%1, 0)     \n"             \
+		"       addi    %2, 4           \n"             \
+		"       addi    %1, 4           \n"             \
+		"       subi    %0, 4           \n"             \
+		"       br      3b              \n"             \
+		"5:     cmpnei  %0, 0           \n"  /* 1B */   \
+		"       bf      7f              \n"             \
+		"6:     ldb     %3, (%2, 0)     \n"             \
+		"       stb     %3, (%1, 0)     \n"             \
+		"       addi    %2,  1          \n"             \
+		"       addi    %1,  1          \n"             \
+		"       subi    %0,  1          \n"             \
+		"       br      5b              \n"             \
+		"8:     mov     %3, %0          \n" /* zero */  \
+		"       movi    %4, 0           \n"             \
+		"9:     stb     %4, (%1, 0)     \n"             \
+		"       addi    %1, 1           \n"             \
+		"       subi    %3, 1           \n"             \
+		"       cmpnei  %3, 0           \n"             \
+		"       bt      9b              \n"             \
+		"       br      7f              \n"             \
+		".section __ex_table, \"a\"     \n"             \
+		".align   2                     \n"             \
+		".long    2b, 8b                \n"             \
+		".long   10b, 8b                \n"             \
+		".long   11b, 8b                \n"             \
+		".long   12b, 8b                \n"             \
+		".long    4b, 8b                \n"             \
+		".long    6b, 8b                \n"             \
+		".previous                      \n"             \
+		"7:                             \n"             \
+		: "=r"(n), "=r"(to), "=r"(from), "=r"(nsave), "=r"(tmp)   \
+		: "0"(n), "1"(to), "2"(from)                    \
+		: "memory" );                                   \
+} while (0)
+
+unsigned long raw_copy_from_user(void *to, const void *from, unsigned long n);
+unsigned long raw_copy_to_user(void *to, const void *from, unsigned long n);
+
+unsigned long clear_user(void *to, unsigned long n);
+unsigned long __clear_user(void __user *to, unsigned long n);
+
+long strncpy_from_user(char *dst, const char *src, long count);
+long __strncpy_from_user(char *dst, const char *src, long count);
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 on exception, a value greater than N if too long
+ */
+long strnlen_user(const char *src, long n);
+
+#define strlen_user(str) strnlen_user(str, 32767)
+
+struct exception_table_entry
+{
+	unsigned long insn;
+	unsigned long nextinsn;
+};
+
+extern int fixup_exception(struct pt_regs *regs);
+
+#endif /* __ASM_CSKY_UACCESS_H */
diff --git a/arch/csky/lib/usercopy.c b/arch/csky/lib/usercopy.c
new file mode 100644
index 0000000..ace4190
--- /dev/null
+++ b/arch/csky/lib/usercopy.c
@@ -0,0 +1,271 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/uaccess.h>
+#include <linux/types.h>
+
+unsigned long
+raw_copy_from_user(
+		void *to,
+		const void *from,
+		unsigned long n)
+{
+	if (access_ok(VERIFY_READ, from, n))
+		__copy_user_zeroing(to,from,n); 
+	else
+		memset(to,0, n);
+	return n;
+}
+EXPORT_SYMBOL(raw_copy_from_user);
+
+unsigned long
+raw_copy_to_user(
+		void *to,
+		const void *from,
+		unsigned long n)
+{
+	if (access_ok(VERIFY_WRITE, to, n))
+		__copy_user(to,from,n);
+	return n;
+}
+EXPORT_SYMBOL(raw_copy_to_user);
+
+
+/*
+ * copy a null terminated string from userspace.	
+ */
+#define __do_strncpy_from_user(dst,src,count,res)       \
+do{                                                     \
+        int tmp;                                        \
+        long faultres;                                  \
+        asm volatile(                           \
+        "       cmpnei  %3, 0           \n"             \
+        "       bf      4f              \n"             \
+        "1:     cmpnei  %1, 0          	\n"             \
+        "       bf      5f              \n"             \
+        "2:     ldb     %4, (%3, 0)     \n"             \
+        "       stb     %4, (%2, 0)     \n"             \
+        "       cmpnei  %4, 0           \n"             \
+        "       bf      3f              \n"             \
+        "       addi    %3,  1          \n"             \
+        "       addi    %2,  1          \n"             \
+        "       subi    %1,  1          \n"             \
+        "       br      1b              \n"             \
+        "3:     subu	%0, %1          \n"             \
+        "       br      5f              \n"             \
+        "4:     mov     %0, %5          \n"             \
+        "       br      5f              \n"             \
+        ".section __ex_table, \"a\"     \n"             \
+        ".align   2                     \n"             \
+        ".long    2b, 4b                \n"             \
+        ".previous                      \n"             \
+        "5:                             \n"             \
+          :"=r"(res),"=r"(count),"=r"(dst),"=r"(src), "=r"(tmp),"=r"(faultres) \
+          : "5"(-EFAULT),"0"(count), "1"(count), "2"(dst),"3"(src)     	       \
+          : "memory" );	                                \
+} while(0)		
+
+/*
+ * __strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking.
+ * @dst:   Destination address, in kernel space.  This buffer must be at
+ *         least @count bytes long.
+ * @src:   Source address, in user space.
+ * @count: Maximum number of bytes to copy, including the trailing NUL.
+ * 
+ * Copies a NUL-terminated string from userspace to kernel space.
+ * Caller must check the specified block with access_ok() before calling
+ * this function.
+ *
+ * On success, returns the length of the string (not including the trailing
+ * NUL).
+ *
+ * If access to userspace fails, returns -EFAULT (some data may have been
+ * copied).
+ *
+ * If @count is smaller than the length of the string, copies @count bytes
+ * and returns @count.
+ */
+long
+__strncpy_from_user(
+	char *dst,
+	const char *src,
+	long count)
+{
+	long res;
+	__do_strncpy_from_user(dst, src, count, res);
+	return res;
+}
+EXPORT_SYMBOL(__strncpy_from_user);
+
+/*
+ * strncpy_from_user: - Copy a NUL terminated string from userspace.
+ * @dst:   Destination address, in kernel space.  This buffer must be at
+ *         least @count bytes long.
+ * @src:   Source address, in user space.
+ * @count: Maximum number of bytes to copy, including the trailing NUL.
+ * 
+ * Copies a NUL-terminated string from userspace to kernel space.
+ *
+ * On success, returns the length of the string (not including the trailing
+ * NUL).
+ *
+ * If access to userspace fails, returns -EFAULT (some data may have been
+ * copied).
+ *
+ * If @count is smaller than the length of the string, copies @count bytes
+ * and returns @count.
+ */
+long
+strncpy_from_user(
+	char *dst,
+	const char *src,
+	long count)
+{
+	long res = -EFAULT;
+	if (access_ok(VERIFY_READ, src, 1))
+		__do_strncpy_from_user(dst, src, count, res);
+	return res;
+}
+EXPORT_SYMBOL(strncpy_from_user);
+
+/*
+ * strlen_user: - Get the size of a string in user space.
+ * @str: The string to measure.
+ * @n:   The maximum valid length
+ *
+ * Get the size of a NUL-terminated string in user space.
+ *
+ * Returns the size of the string INCLUDING the terminating NUL.
+ * On exception, returns 0.
+ * If the string is too long, returns a value greater than @n.
+ */
+long strnlen_user(const char *s, long n)
+{
+
+	unsigned long res,tmp;
+	if(s){
+	asm volatile(
+        "       cmpnei  %1, 0           \n"
+        "       bf      3f              \n"
+        "1:     cmpnei  %0, 0           \n"              
+        "       bf      3f              \n"
+        "2:     ldb     %3, (%1, 0)     \n"             
+        "       cmpnei  %3, 0           \n"             
+        "       bf      3f              \n"             
+        "       subi    %0,  1          \n"             
+        "       addi    %1,  1          \n"             
+        "       br      1b              \n"
+        "3:     subu    %2, %0          \n"
+        "       addi    %2,  1          \n"             
+        "       br      5f              \n"             
+        "4:     movi    %0, 0           \n"             
+        "       br      5f              \n"             
+        ".section __ex_table, \"a\"     \n"             
+        ".align   2                     \n"
+        ".long    2b, 4b                \n"             
+        ".previous                      \n"             
+        "5:                             \n"             
+        :"=r"(n),"=r"(s), "=r"(res), "=r"(tmp)   
+        : "0"(n), "1"(s), "2"(n)      
+        : "cc" );
+		return res;     
+	}
+	return 0;     
+}
+EXPORT_SYMBOL(strnlen_user);
+
+#define __do_clear_user(addr, size)                             \
+do {                                                            \
+	int __d0;                                               \
+	int zvalue;                                             \
+	int tmp;                                                \
+	asm volatile(						\
+		"0:     cmpnei  %1, 0           \n"             \
+		"       bf      7f              \n"             \
+		"       mov     %3, %1          \n"             \
+		"       andi    %3, 3           \n"             \
+		"       cmpnei  %3, 0           \n"             \
+		"       bf      1f              \n"             \
+		"       br      5f              \n"             \
+		"1:     cmplti  %0, 32          \n"   /* 4W */  \
+		"       bt      3f              \n"             \
+		"8:     stw     %2, (%1, 0)     \n"             \
+		"10:    stw     %2, (%1, 4)     \n"             \
+		"11:    stw     %2, (%1, 8)     \n"             \
+		"12:    stw     %2, (%1, 12)    \n"             \
+		"13:    stw     %2, (%1, 16)    \n"             \
+		"14:    stw     %2, (%1, 20)    \n"             \
+		"15:    stw     %2, (%1, 24)    \n"             \
+		"16:    stw     %2, (%1, 28)    \n"             \
+		"       addi    %1, 32          \n"             \
+		"       subi    %0, 32          \n"             \
+		"       br      1b              \n"             \
+		"3:     cmplti  %0, 4           \n"  /* 1W */   \
+		"       bt      5f              \n"             \
+		"4:     stw     %2, (%1, 0)     \n"             \
+		"       addi    %1, 4           \n"             \
+		"       subi    %0, 4           \n"             \
+		"       br      3b              \n"             \
+		"5:     cmpnei  %0, 0           \n"  /* 1B */   \
+		"9:     bf      7f              \n"             \
+		"6:     stb     %2, (%1, 0)     \n"             \
+		"       addi    %1,  1          \n"             \
+		"       subi    %0,  1          \n"             \
+		"       br      5b              \n"             \
+		".section __ex_table,\"a\"      \n"             \
+		".align   2                     \n"             \
+		".long    8b, 9b                \n"             \
+		".long    10b, 9b               \n"             \
+		".long    11b, 9b               \n"             \
+		".long    12b, 9b               \n"             \
+		".long    13b, 9b               \n"             \
+		".long    14b, 9b               \n"             \
+		".long    15b, 9b               \n"             \
+		".long    16b, 9b               \n"             \
+		".long    4b, 9b                \n"             \
+		".long    6b, 9b                \n"             \
+		".previous                      \n"             \
+		"7:                             \n"             \
+		: "=r"(size), "=r" (__d0), "=r"(zvalue), "=r"(tmp) \
+		: "0"(size), "1"(addr), "2"(0)                  \
+		: "memory"                                      \
+	);                                                      \
+} while (0)
+
+/*
+ * clear_user: - Zero a block of memory in user space.
+ * @to:   Destination address, in user space.
+ * @n:    Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */	
+unsigned long 
+clear_user(void __user *to, unsigned long n)
+{
+	if (access_ok(VERIFY_WRITE, to, n))
+		__do_clear_user(to, n);
+	return n;
+}
+EXPORT_SYMBOL(clear_user);
+
+/*
+ * __clear_user: - Zero a block of memory in user space, with less checking.
+ * @to:   Destination address, in user space.
+ * @n:    Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
+unsigned long
+__clear_user(void __user *to, unsigned long n)
+{
+	__do_clear_user(to, n);
+	return n;
+}
+EXPORT_SYMBOL(__clear_user);
+
-- 
2.7.4


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

* [PATCH V2 15/19] csky: Debug and Ptrace GDB
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (13 preceding siblings ...)
  2018-07-01 17:30 ` [PATCH V2 14/19] csky: User access Guo Ren
@ 2018-07-01 17:30 ` Guo Ren
  2018-07-01 17:30 ` [PATCH V2 16/19] csky: SMP support Guo Ren
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/include/uapi/asm/ptrace.h | 105 +++++++++++++
 arch/csky/kernel/dumpstack.c        |  65 ++++++++
 arch/csky/kernel/ptrace.c           | 288 ++++++++++++++++++++++++++++++++++++
 3 files changed, 458 insertions(+)
 create mode 100644 arch/csky/include/uapi/asm/ptrace.h
 create mode 100644 arch/csky/kernel/dumpstack.c
 create mode 100644 arch/csky/kernel/ptrace.c

diff --git a/arch/csky/include/uapi/asm/ptrace.h b/arch/csky/include/uapi/asm/ptrace.h
new file mode 100644
index 0000000..f5228dd
--- /dev/null
+++ b/arch/csky/include/uapi/asm/ptrace.h
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef _CSKY_PTRACE_H
+#define _CSKY_PTRACE_H
+
+#ifndef __ASSEMBLY__
+
+struct pt_regs {
+	unsigned long	tls;
+	unsigned long	lr;
+	unsigned long	pc;
+	unsigned long	sr;
+	unsigned long	usp;
+
+	/*
+	 * a0, a1, a2, a3:
+	 * abiv1: r2, r3, r4, r5
+	 * abiv2: r0, r1, r2, r3
+	 */
+	unsigned long	orig_a0;
+	unsigned long	a0;
+	unsigned long	a1;
+	unsigned long	a2;
+	unsigned long	a3;
+
+	/*
+	 * ABIV2: r4 ~ r13
+	 * ABIV1: r6 ~ r14, r1
+	 */
+	unsigned long	regs[10];
+
+#if defined(__CSKYABIV2__)
+	/* r16 ~ r30 */
+	unsigned long	exregs[15];
+
+	unsigned long	rhi;
+	unsigned long	rlo;
+	unsigned long	pad; /* reserved */
+#endif
+};
+
+struct user_fp {
+	unsigned long	vr[64];
+	unsigned long	fcr;
+	unsigned long	fesr;
+	unsigned long	fid;
+	unsigned long	reserved;
+};
+
+/*
+ * Switch stack for switch_to after push pt_regs.
+ *
+ * ABI_CSKYV2: r4 ~ r11, r15 ~ r17, r26 ~ r30;
+ * ABI_CSKYV1: r8 ~ r14, r15;
+ */
+struct  switch_stack {
+#if defined(__CSKYABIV2__)
+	unsigned long   r4;
+        unsigned long   r5;
+        unsigned long   r6;
+        unsigned long   r7;
+	unsigned long   r8;
+        unsigned long   r9;
+        unsigned long   r10;
+        unsigned long   r11;
+#else
+	unsigned long   r8;
+        unsigned long   r9;
+        unsigned long   r10;
+        unsigned long   r11;
+        unsigned long   r12;
+        unsigned long   r13;
+        unsigned long   r14;
+#endif
+        unsigned long   r15;
+#if defined(__CSKYABIV2__)
+        unsigned long   r16;
+        unsigned long   r17;
+        unsigned long   r26;
+        unsigned long   r27;
+        unsigned long   r28;
+        unsigned long   r29;
+        unsigned long   r30;
+#endif
+};
+
+#ifdef __KERNEL__
+
+#define PS_S            0x80000000              /* Supervisor Mode */
+
+#define arch_has_single_step() (1)
+#define current_pt_regs() \
+	(struct pt_regs *)((char *)current_thread_info() + THREAD_SIZE) - 1
+
+#define user_stack_pointer(regs) ((regs)->usp)
+
+#define user_mode(regs) (!((regs)->sr & PS_S))
+#define instruction_pointer(regs) ((regs)->pc)
+#define profile_pc(regs) instruction_pointer(regs)
+
+void show_regs(struct pt_regs *);
+
+#endif /* __KERNEL__ */
+#endif /* __ASSEMBLY__ */
+#endif /* _CSKY_PTRACE_H */
diff --git a/arch/csky/kernel/dumpstack.c b/arch/csky/kernel/dumpstack.c
new file mode 100644
index 0000000..d4be08a
--- /dev/null
+++ b/arch/csky/kernel/dumpstack.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/ptrace.h>
+
+int kstack_depth_to_print = 48;
+
+void show_trace(unsigned long *stack)
+{
+	unsigned long *endstack;
+	unsigned long addr;
+	int i;
+
+	pr_info("Call Trace:");
+	addr = (unsigned long)stack + THREAD_SIZE - 1;
+	endstack = (unsigned long *)(addr & -THREAD_SIZE);
+	i = 0;
+	while (stack + 1 <= endstack) {
+		addr = *stack++;
+		/*
+		 * If the address is either in the text segment of the
+		 * kernel, or in the region which contains vmalloc'ed
+		 * memory, it *may* be the address of a calling
+		 * routine; if so, print it so that someone tracing
+		 * down the cause of the crash will be able to figure
+		 * out the call path that was taken.
+		 */
+		if (__kernel_text_address(addr)) {
+#ifndef CONFIG_KALLSYMS
+			if (i % 5 == 0)
+				pr_cont("\n       ");
+#endif
+			pr_cont(" [<%08lx>] %pS\n", addr, (void *)addr);
+			i++;
+		}
+	}
+	pr_cont("\n");
+}
+
+void show_stack(struct task_struct *task, unsigned long *stack)
+{
+	unsigned long *p;
+	unsigned long *endstack;
+	int i;
+
+	if (!stack) {
+		if (task)
+			stack = (unsigned long *)task->thread.esp0;
+		else
+			stack = (unsigned long *)&stack;
+	}
+	endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
+
+	pr_info("Stack from %08lx:", (unsigned long)stack);
+	p = stack;
+	for (i = 0; i < kstack_depth_to_print; i++) {
+		if (p + 1 > endstack)
+			break;
+		if (i % 8 == 0)
+			pr_cont("\n       ");
+		pr_cont(" %08lx", *p++);
+	}
+	pr_cont("\n");
+	show_trace(stack);
+}
+
diff --git a/arch/csky/kernel/ptrace.c b/arch/csky/kernel/ptrace.c
new file mode 100644
index 0000000..eeaebfe
--- /dev/null
+++ b/arch/csky/kernel/ptrace.c
@@ -0,0 +1,288 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/elf.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/ptrace.h>
+#include <linux/regset.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/smp.h>
+#include <linux/uaccess.h>
+#include <linux/user.h>
+
+#include <asm/thread_info.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/asm-offsets.h>
+
+#include <abi/regdef.h>
+
+/* sets the trace bits. */
+#define TRACE_MODE_SI      1 << 14
+#define TRACE_MODE_RUN     0
+#define TRACE_MODE_MASK    ~(0x3 << 14)
+
+/*
+ * Make sure the single step bit is not set.
+ */
+static void singlestep_disable(struct task_struct *tsk)
+{
+	struct pt_regs *regs;
+
+	regs = task_pt_regs(tsk);
+	regs->sr = (regs->sr & TRACE_MODE_MASK) | TRACE_MODE_RUN;
+}
+
+static void singlestep_enable(struct task_struct *tsk)
+{
+	struct pt_regs *regs;
+
+	regs = task_pt_regs(tsk);
+	regs->sr = (regs->sr & TRACE_MODE_MASK) | TRACE_MODE_SI;
+}
+
+/*
+ * Make sure the single step bit is set.
+ */
+void user_enable_single_step(struct task_struct *child)
+{
+	if (child->thread.esp0 == 0) return;
+	singlestep_enable(child);
+}
+
+void user_disable_single_step(struct task_struct *child)
+{
+	if (child->thread.esp0 == 0) return;
+	singlestep_disable(child);
+}
+
+enum csky_regset {
+	REGSET_GPR,
+	REGSET_FPR,
+};
+
+static int gpr_get(struct task_struct *target,
+		   const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	struct pt_regs *regs;
+
+	regs = task_pt_regs(target);
+
+	/* Abiv1 regs->tls is fake and we need sync here. */
+	regs->tls = task_thread_info(target)->tp_value;
+
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, regs, 0, -1);
+}
+
+static int gpr_set(struct task_struct *target,
+		    const struct user_regset *regset,
+		    unsigned int pos, unsigned int count,
+		    const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+	struct pt_regs regs;
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &regs, 0, -1);
+	if (ret)
+		return ret;
+
+	regs.sr = task_pt_regs(target)->sr;
+
+	task_thread_info(target)->tp_value = regs.tls;
+
+	*task_pt_regs(target) = regs;
+
+	return 0;
+}
+
+static int fpr_get(struct task_struct *target,
+		   const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	struct user_fp *regs;
+
+	regs = (struct user_fp *)&target->thread.user_fp;
+
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, regs, 0, -1);
+}
+
+static int fpr_set(struct task_struct *target,
+		    const struct user_regset *regset,
+		    unsigned int pos, unsigned int count,
+		    const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+	struct user_fp *regs;
+
+	regs = (struct user_fp *)&target->thread.user_fp;
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, regs, 0, -1);
+
+	return ret;
+}
+
+static const struct user_regset csky_regsets[] = {
+	[REGSET_GPR] = {
+		.core_note_type = NT_PRSTATUS,
+		.n = ELF_NGREG,
+		.size = sizeof(u32),
+		.align = sizeof(u32),
+		.get = &gpr_get,
+		.set = &gpr_set,
+	},
+	[REGSET_FPR] = {
+		.core_note_type = NT_PRFPREG,
+		.n = sizeof(struct user_fp) / sizeof(u32),
+		.size = sizeof(u32),
+		.align = sizeof(u32),
+		.get = &fpr_get,
+		.set = &fpr_set,
+	},
+};
+
+static const struct user_regset_view user_csky_view = {
+	.name = "csky",
+	.e_machine = ELF_ARCH,
+	.regsets = csky_regsets,
+	.n = ARRAY_SIZE(csky_regsets),
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+	return &user_csky_view;
+}
+
+void ptrace_disable(struct task_struct *child)
+{
+	singlestep_disable(child);
+}
+
+long arch_ptrace(struct task_struct *child, long request,
+		 unsigned long addr, unsigned long data)
+{
+	long ret = -EIO;
+
+	switch (request) {
+	default:
+		ret = ptrace_request(child, request, addr, data);
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ * If process's system calls is traces, do some corresponding handles in this
+ * fuction before entering system call function and after exiting system call
+ * fuction.
+ */
+asmlinkage void syscall_trace(int why, struct pt_regs * regs)
+{
+	long saved_why;
+	/*
+	 * Save saved_why, why is used to denote syscall entry/exit;
+	 * why = 0:entry, why = 1: exit
+	 */
+	saved_why = regs->regs[SYSTRACE_SAVENUM];
+	regs->regs[SYSTRACE_SAVENUM] = why;
+
+	/* the 0x80 provides a way for the tracing parent to distinguish
+	   between a syscall stop and SIGTRAP delivery */
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				? 0x80 : 0));
+	/*
+	 * this isn't the same as continuing with a signal, but it will do
+	 * for normal use.  strace only continues with a signal if the
+	 * stopping signal is not SIGTRAP.  -brl
+	 */
+	if (current->exit_code) {
+		send_sig(current->exit_code, current, 1);
+		current->exit_code = 0;
+	}
+
+	regs->regs[SYSTRACE_SAVENUM] = saved_why;
+	return;
+}
+
+void show_regs(struct pt_regs *fp)
+{
+	unsigned long   *sp;
+	unsigned char   *tp;
+	int	i;
+
+	pr_info("\nCURRENT PROCESS:\n\n");
+	pr_info("COMM=%s PID=%d\n", current->comm, current->pid);
+
+	if (current->mm) {
+		pr_info("TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n",
+		       (int) current->mm->start_code,
+		       (int) current->mm->end_code,
+		       (int) current->mm->start_data,
+		       (int) current->mm->end_data,
+		       (int) current->mm->end_data,
+		       (int) current->mm->brk);
+		pr_info("USER-STACK=%08x  KERNEL-STACK=%08x\n\n",
+		       (int) current->mm->start_stack,
+		       (int) (((unsigned long) current) + 2 * PAGE_SIZE));
+	}
+
+	pr_info("PC: 0x%08lx\n", (long)fp->pc);
+	pr_info("orig_a0: 0x%08lx\n", fp->orig_a0);
+	pr_info("PSR: 0x%08lx\n", (long)fp->sr);
+
+	pr_info("a0: 0x%08lx  a1: 0x%08lx  a2: 0x%08lx  a3: 0x%08lx\n",
+	       fp->a0, fp->a1, fp->a2, fp->a3);
+#if defined(__CSKYABIV2__)
+	pr_info("r4: 0x%08lx  r5: 0x%08lx    r6: 0x%08lx    r7: 0x%08lx\n",
+	       fp->regs[0], fp->regs[1], fp->regs[2], fp->regs[3]);
+	pr_info("r8: 0x%08lx  r9: 0x%08lx   r10: 0x%08lx   r11: 0x%08lx\n",
+	       fp->regs[4], fp->regs[5], fp->regs[6], fp->regs[7]);
+	pr_info("r12 0x%08lx  r13: 0x%08lx   r15: 0x%08lx\n",
+	       fp->regs[8], fp->regs[9], fp->lr);
+	pr_info("r16:0x%08lx   r17: 0x%08lx   r18: 0x%08lx    r19: 0x%08lx\n",
+	       fp->exregs[0], fp->exregs[1], fp->exregs[2], fp->exregs[3]);
+	pr_info("r20 0x%08lx   r21: 0x%08lx   r22: 0x%08lx    r23: 0x%08lx\n",
+	       fp->exregs[4], fp->exregs[5], fp->exregs[6], fp->exregs[7]);
+	pr_info("r24 0x%08lx   r25: 0x%08lx   r26: 0x%08lx    r27: 0x%08lx\n",
+	       fp->exregs[8], fp->exregs[9], fp->exregs[10], fp->exregs[11]);
+	pr_info("r28 0x%08lx   r29: 0x%08lx   r30: 0x%08lx    tls: 0x%08lx\n",
+	       fp->exregs[12], fp->exregs[13], fp->exregs[14], fp->tls);
+	pr_info("hi 0x%08lx     lo: 0x%08lx \n",
+	       fp->rhi, fp->rlo);
+#else
+	pr_info("r6: 0x%08lx   r7: 0x%08lx   r8: 0x%08lx   r9: 0x%08lx\n",
+	       fp->regs[0], fp->regs[1], fp->regs[2], fp->regs[3]);
+	pr_info("r10: 0x%08lx   r11: 0x%08lx   r12: 0x%08lx   r13: 0x%08lx\n",
+	       fp->regs[4], fp->regs[5], fp->regs[6], fp->regs[7]);
+	pr_info("r14 0x%08lx   r1: 0x%08lx   r15: 0x%08lx\n",
+	       fp->regs[8], fp->regs[9], fp->lr);
+#endif
+
+	pr_info("\nCODE:");
+	tp = ((unsigned char *) fp->pc) - 0x20;
+	tp += ((int)tp % 4) ? 2 : 0;
+	for (sp = (unsigned long *) tp, i = 0; (i < 0x40);  i += 4) {
+		if ((i % 0x10) == 0)
+			pr_cont("\n%08x: ", (int) (tp + i));
+		pr_cont("%08x ", (int) *sp++);
+	}
+	pr_cont("\n");
+
+	pr_info("\nKERNEL STACK:");
+	tp = ((unsigned char *) fp) - 0x40;
+	for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) {
+		if ((i % 0x10) == 0)
+			pr_cont("\n%08x: ", (int) (tp + i));
+		pr_cont("%08x ", (int) *sp++);
+	}
+	pr_cont("\n");
+
+	return;
+}
+
-- 
2.7.4


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

* [PATCH V2 16/19] csky: SMP support
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (14 preceding siblings ...)
  2018-07-01 17:30 ` [PATCH V2 15/19] csky: Debug and Ptrace GDB Guo Ren
@ 2018-07-01 17:30 ` Guo Ren
  2018-07-05 18:05   ` Peter Zijlstra
  2018-07-06  5:24   ` Mark Rutland
  2018-07-01 17:30 ` [PATCH V2 17/19] csky: Misc headers Guo Ren
                   ` (3 subsequent siblings)
  19 siblings, 2 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/include/asm/smp.h |  26 +++++
 arch/csky/kernel/smp.c      | 256 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 282 insertions(+)
 create mode 100644 arch/csky/include/asm/smp.h
 create mode 100644 arch/csky/kernel/smp.c

diff --git a/arch/csky/include/asm/smp.h b/arch/csky/include/asm/smp.h
new file mode 100644
index 0000000..9a53abf
--- /dev/null
+++ b/arch/csky/include/asm/smp.h
@@ -0,0 +1,26 @@
+#ifndef __ASM_CSKY_SMP_H
+#define __ASM_CSKY_SMP_H
+
+#include <linux/cpumask.h>
+#include <linux/irqreturn.h>
+#include <linux/threads.h>
+
+#ifdef CONFIG_SMP
+
+void __init setup_smp(void);
+
+void __init setup_smp_ipi(void);
+
+void __init enable_smp_ipi(void);
+
+void arch_send_call_function_ipi_mask(struct cpumask *mask);
+
+void arch_send_call_function_single_ipi(int cpu);
+
+void __init set_send_ipi(void (*func)(const unsigned long *, unsigned long));
+
+#define raw_smp_processor_id()	(current_thread_info()->cpu)
+
+#endif /* CONFIG_SMP */
+
+#endif /* __ASM_CSKY_SMP_H */
diff --git a/arch/csky/kernel/smp.c b/arch/csky/kernel/smp.c
new file mode 100644
index 0000000..42308cd
--- /dev/null
+++ b/arch/csky/kernel/smp.c
@@ -0,0 +1,256 @@
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/percpu.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/sched/task_stack.h>
+#include <linux/sched/mm.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+#include <asm/sections.h>
+#include <asm/mmu_context.h>
+#include <asm/pgalloc.h>
+
+#define IPI_IRQ	15
+
+static struct {
+	unsigned long bits ____cacheline_aligned;
+} ipi_data[NR_CPUS] __cacheline_aligned;
+
+enum ipi_message_type {
+	IPI_EMPTY,
+	IPI_RESCHEDULE,
+	IPI_CALL_FUNC,
+	IPI_MAX
+};
+
+static irqreturn_t handle_ipi(int irq, void *dev)
+{
+	unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits;
+
+	while (true) {
+		unsigned long ops;
+
+		/* Order bit clearing and data access. */
+		mb();
+
+		ops = xchg(pending_ipis, 0);
+		if (ops == 0)
+			return IRQ_HANDLED;
+
+		if (ops & (1 << IPI_RESCHEDULE))
+			scheduler_ipi();
+
+		if (ops & (1 << IPI_CALL_FUNC))
+			generic_smp_call_function_interrupt();
+
+		BUG_ON((ops >> IPI_MAX) != 0);
+
+		/* Order data access and bit testing. */
+		mb();
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void (*send_arch_ipi)(const unsigned long *mask, unsigned long irq) = NULL;
+
+void __init set_send_ipi(void (*func)(const unsigned long *, unsigned long))
+{
+	if (send_arch_ipi)
+		return;
+
+	send_arch_ipi = func;
+}
+
+static void
+send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation)
+{
+	int i;
+
+	mb();
+	for_each_cpu(i, to_whom)
+		set_bit(operation, &ipi_data[i].bits);
+
+	mb();
+	send_arch_ipi(cpumask_bits(to_whom), IPI_IRQ);
+}
+
+void arch_send_call_function_ipi_mask(struct cpumask *mask)
+{
+	send_ipi_message(mask, IPI_CALL_FUNC);
+}
+
+void arch_send_call_function_single_ipi(int cpu)
+{
+	send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC);
+}
+
+static void ipi_stop(void *unused)
+{
+	while (1);
+}
+
+void smp_send_stop(void)
+{
+	on_each_cpu(ipi_stop, NULL, 1);
+}
+
+void smp_send_reschedule(int cpu)
+{
+	send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE);
+}
+
+void *__cpu_up_stack_pointer[NR_CPUS];
+void *__cpu_up_task_pointer[NR_CPUS];
+
+void __init smp_prepare_boot_cpu(void)
+{
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+}
+
+static int ipi_dummy_dev;
+
+void __init enable_smp_ipi(void)
+{
+	enable_percpu_irq(IPI_IRQ, 0);
+}
+
+void __init setup_smp_ipi(void)
+{
+	int rc;
+
+	irq_create_mapping(NULL, IPI_IRQ);
+
+	rc = request_percpu_irq(IPI_IRQ, handle_ipi, "IPI Interrupt", &ipi_dummy_dev);
+	if (rc)
+		panic("%s IRQ request failed\n", __func__);
+
+	enable_smp_ipi();
+}
+
+static int csky_of_cpu(struct device_node *node)
+{
+	const char *status;
+	int cpu;
+
+	if (of_property_read_u32(node, "reg", &cpu))
+		goto error;
+
+	if (cpu >= NR_CPUS)
+		goto error;
+
+	if (of_property_read_string(node, "status", &status))
+		status = "enable";
+
+	if (strcmp(status, "disable") == 0)
+		goto error;
+
+	return cpu;
+error:
+	return -ENODEV;
+}
+
+void __init setup_smp(void)
+{
+	struct device_node *node = NULL;
+	int cpu;
+
+	while ((node = of_find_node_by_type(node, "cpu"))) {
+		cpu = csky_of_cpu(node);
+		if (cpu >= 0) {
+			set_cpu_possible(cpu, true);
+			set_cpu_present(cpu, true);
+		}
+	}
+}
+
+extern void _start_smp_secondary(void);
+
+static unsigned int secondary_hint;
+static unsigned int secondary_ccr;
+
+unsigned int secondary_stack;
+
+int __cpu_up(unsigned int cpu, struct task_struct *tidle)
+{
+	unsigned int tmp;
+
+	secondary_stack = (unsigned int)tidle->stack + THREAD_SIZE;
+
+	secondary_hint = mfcr("cr31");
+
+	secondary_ccr  = mfcr("cr18");
+
+	pr_info("%s: CPU%u\n", __func__, cpu);
+
+	tmp = mfcr("cr<29, 0>");
+	tmp |= 1 << cpu;
+	mtcr("cr<29, 0>", tmp);
+
+	while (!cpu_online(cpu));
+
+	secondary_stack = 0;
+
+	return 0;
+}
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
+}
+
+int setup_profiling_timer(unsigned int multiplier)
+{
+	return -EINVAL;
+}
+
+void csky_start_secondary(void)
+{
+	struct mm_struct *mm = &init_mm;
+	unsigned int cpu = smp_processor_id();
+
+	mtcr("cr31", secondary_hint);
+	mtcr("cr18", secondary_ccr);
+
+	mtcr("vbr", vec_base);
+
+	flush_tlb_all();
+	write_mmu_pagemask(0);
+	TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir);
+	TLBMISS_HANDLER_SETUP_PGD_KERNEL(swapper_pg_dir);
+
+	asid_cache(smp_processor_id()) = ASID_FIRST_VERSION;
+
+#ifdef CONFIG_CPU_HAS_FPU
+	init_fpu();
+#endif
+
+	enable_smp_ipi();
+
+	mmget(mm);
+	mmgrab(mm);
+	current->active_mm = mm;
+	cpumask_set_cpu(cpu, mm_cpumask(mm));
+
+	notify_cpu_starting(cpu);
+	set_cpu_online(cpu, true);
+
+	pr_info("CPU%u Online: %s...\n", cpu, __func__);
+
+	local_irq_enable();
+	preempt_disable();
+	cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
+}
+
-- 
2.7.4


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

* [PATCH V2 17/19] csky: Misc headers
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (15 preceding siblings ...)
  2018-07-01 17:30 ` [PATCH V2 16/19] csky: SMP support Guo Ren
@ 2018-07-01 17:30 ` Guo Ren
  2018-07-01 17:34   ` Guo Ren
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 arch/csky/abiv1/inc/abi/reg_ops.h      |  47 ++++++
 arch/csky/abiv1/inc/abi/regdef.h       |  15 ++
 arch/csky/abiv2/inc/abi/reg_ops.h      |  38 +++++
 arch/csky/abiv2/inc/abi/regdef.h       |  15 ++
 arch/csky/include/asm/bitops.h         | 277 +++++++++++++++++++++++++++++++++
 arch/csky/include/asm/checksum.h       |  77 +++++++++
 arch/csky/include/asm/reg_ops.h        |  16 ++
 arch/csky/include/uapi/asm/byteorder.h |  14 ++
 8 files changed, 499 insertions(+)
 create mode 100644 arch/csky/abiv1/inc/abi/reg_ops.h
 create mode 100644 arch/csky/abiv1/inc/abi/regdef.h
 create mode 100644 arch/csky/abiv2/inc/abi/reg_ops.h
 create mode 100644 arch/csky/abiv2/inc/abi/regdef.h
 create mode 100644 arch/csky/include/asm/bitops.h
 create mode 100644 arch/csky/include/asm/checksum.h
 create mode 100644 arch/csky/include/asm/reg_ops.h
 create mode 100644 arch/csky/include/uapi/asm/byteorder.h

diff --git a/arch/csky/abiv1/inc/abi/reg_ops.h b/arch/csky/abiv1/inc/abi/reg_ops.h
new file mode 100644
index 0000000..7c31ac3
--- /dev/null
+++ b/arch/csky/abiv1/inc/abi/reg_ops.h
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ABI_REG_OPS_H
+#define __ABI_REG_OPS_H
+#include <asm/reg_ops.h>
+
+#define cprcr(reg)					\
+({							\
+	unsigned int tmp;				\
+	asm volatile("cprcr %0, "reg"\n":"=b"(tmp));	\
+	tmp;						\
+})
+
+#define cpwcr(reg, val)					\
+({							\
+	asm volatile("cpwcr %0, "reg"\n"::"b"(val));	\
+})
+
+static inline unsigned int mfcr_hint(void)
+{
+	return mfcr("cr30");
+}
+
+static inline unsigned int mfcr_msa0(void)
+{
+	return cprcr("cpcr30");
+}
+
+static inline void mtcr_msa0(unsigned int value)
+{
+	cpwcr("cpcr30", value);
+}
+
+static inline unsigned int mfcr_msa1(void)
+{
+	return cprcr("cpcr31");
+}
+
+static inline void mtcr_msa1(unsigned int value)
+{
+	cpwcr("cpcr31", value);
+}
+
+static inline unsigned int mfcr_ccr2(void){return 0;}
+
+#endif /* __ABI_REG_OPS_H */
+
diff --git a/arch/csky/abiv1/inc/abi/regdef.h b/arch/csky/abiv1/inc/abi/regdef.h
new file mode 100644
index 0000000..0c3596d
--- /dev/null
+++ b/arch/csky/abiv1/inc/abi/regdef.h
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef  __ASM_CSKY_REGDEF_H
+#define  __ASM_CSKY_REGDEF_H
+
+#define syscallid	r1
+#define r11_sig		r11
+
+#define regs_syscallid(regs) regs->regs[9]
+
+#define DEFAULT_PSR_VALUE	0x8f000000
+
+#define SYSTRACE_SAVENUM	2
+
+#endif /* __ASM_CSKY_REGDEF_H */
diff --git a/arch/csky/abiv2/inc/abi/reg_ops.h b/arch/csky/abiv2/inc/abi/reg_ops.h
new file mode 100644
index 0000000..a8b2a52
--- /dev/null
+++ b/arch/csky/abiv2/inc/abi/reg_ops.h
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ABI_REG_OPS_H
+#define __ABI_REG_OPS_H
+#include <asm/reg_ops.h>
+
+static inline unsigned int mfcr_hint(void)
+{
+	return mfcr("cr31");
+}
+
+static inline unsigned int mfcr_ccr2(void)
+{
+	return mfcr("cr23");
+}
+
+static inline unsigned int mfcr_msa0(void)
+{
+	return mfcr("cr<30, 15>");
+}
+
+static inline void mtcr_msa0(unsigned int value)
+{
+	mtcr("cr<30, 15>", value);
+}
+
+static inline unsigned int mfcr_msa1(void)
+{
+	return mfcr("cr<31, 15>");
+}
+
+static inline void mtcr_msa1(unsigned int value)
+{
+	mtcr("cr<31, 15>", value);
+}
+
+#endif /* __ABI_REG_OPS_H */
+
diff --git a/arch/csky/abiv2/inc/abi/regdef.h b/arch/csky/abiv2/inc/abi/regdef.h
new file mode 100644
index 0000000..2c36d60
--- /dev/null
+++ b/arch/csky/abiv2/inc/abi/regdef.h
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef  __ASM_CSKY_REGDEF_H
+#define  __ASM_CSKY_REGDEF_H
+
+#define syscallid	r7
+#define r11_sig		r11
+
+#define regs_syscallid(regs) regs->regs[3]
+
+#define DEFAULT_PSR_VALUE	0x8f000200
+
+#define SYSTRACE_SAVENUM	5
+
+#endif /* __ASM_CSKY_REGDEF_H */
diff --git a/arch/csky/include/asm/bitops.h b/arch/csky/include/asm/bitops.h
new file mode 100644
index 0000000..b2460c5
--- /dev/null
+++ b/arch/csky/include/asm/bitops.h
@@ -0,0 +1,277 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_BITOPS_H
+#define __ASM_CSKY_BITOPS_H
+
+#include <linux/compiler.h>
+
+/*
+ * asm-generic/bitops/ffs.h
+ */
+static inline int ffs(int x)
+{
+	if(!x) return 0;
+
+	asm volatile (
+		"brev %0\n"
+		"ff1  %0\n"
+		"addi %0, 1\n"
+		:"=&r"(x)
+		:"0"(x));
+	return x;
+}
+
+/*
+ * asm-generic/bitops/__ffs.h
+ */
+static __always_inline unsigned long __ffs(unsigned long x)
+{
+	asm volatile (
+		"brev %0\n"
+		"ff1  %0\n"
+		:"=&r"(x)
+		:"0"(x));
+	return x;
+}
+
+/*
+ * asm-generic/bitops/fls.h
+ */
+static __always_inline int fls(int x)
+{
+	asm volatile(
+		"ff1 %0\n"
+		:"=&r"(x)
+		:"0"(x));
+
+	return (32 - x);
+}
+
+/*
+ * asm-generic/bitops/__fls.h
+ */
+static __always_inline unsigned long __fls(unsigned long x)
+{
+	return fls(x) - 1;
+}
+
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/find.h>
+
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
+
+#ifdef CONFIG_CPU_HAS_LDSTEX
+
+/*
+ * set_bit - Atomically set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * This function is atomic and may not be reordered.  See __set_bit()
+ * if you do not require the atomic guarantees.
+ *
+ * Note: there are no guarantees that this function will not be reordered
+ * on non x86 architectures, so if you are writing portable code,
+ * make sure not to rely on its reordering guarantees.
+ *
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static inline void set_bit(int nr, volatile unsigned long *addr)
+{
+	unsigned long mask = BIT_MASK(nr);
+	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+	unsigned long tmp;
+
+	/* *p  |= mask; */
+	asm volatile (
+		"1:	ldex.w		%0, (%2)	\n"
+		"	or32		%0, %0, %1	\n"
+		"	stex.w		%0, (%2)	\n"
+		"	bez		%0, 1b		\n"
+		: "=&r"(tmp)
+		: "r"(mask), "r"(p)
+		: "memory");
+	smp_mb();
+}
+
+/**
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and may not be reordered.  However, it does
+ * not contain a memory barrier, so if it is used for locking purposes,
+ * you should call smp_mb__before_atomic() and/or smp_mb__after_atomic()
+ * in order to ensure changes are visible on other processors.
+ */
+static inline void clear_bit(int nr, volatile unsigned long *addr)
+{
+	unsigned long mask = BIT_MASK(nr);
+	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+	unsigned long tmp;
+
+	/* *p &= ~mask; */
+	mask = ~mask;
+	asm volatile (
+		"1:	ldex.w		%0, (%2)	\n"
+		"	and32		%0, %0, %1	\n"
+		"	stex.w		%0, (%2)	\n"
+		"	bez		%0, 1b		\n"
+		: "=&r"(tmp)
+		: "r"(mask), "r"(p)
+		: "memory");
+	smp_mb();
+}
+
+/**
+ * change_bit - Toggle a bit in memory
+ * @nr: Bit to change
+ * @addr: Address to start counting from
+ *
+ * change_bit() is atomic and may not be reordered. It may be
+ * reordered on other architectures than x86.
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static inline void change_bit(int nr, volatile unsigned long *addr)
+{
+	unsigned long mask = BIT_MASK(nr);
+	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+	unsigned long tmp;
+
+	/* *p ^= mask; */
+	asm volatile (
+		"1:	ldex.w		%0, (%2)	\n"
+		"	xor32		%0, %0, %1	\n"
+		"	stex.w		%0, (%2)	\n"
+		"	bez		%0, 1b		\n"
+		: "=&r"(tmp)
+		: "r"(mask), "r"(p)
+		: "memory");
+	smp_mb();
+}
+
+/**
+ * test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It may be reordered on other architectures than x86.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
+{
+	unsigned long mask = BIT_MASK(nr);
+	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+	unsigned long old, tmp;
+
+	/*
+	 * old = *p;
+	 * *p = old | mask;
+	 */
+	asm volatile (
+		"1:	ldex.w		%1, (%3)	\n"
+		"	mov		%0, %1		\n"
+		"	or32		%0, %0, %2	\n"
+		"	stex.w		%0, (%3)	\n"
+		"	bez		%0, 1b		\n"
+		: "=&r"(tmp), "=&r"(old)
+		: "r"(mask), "r"(p)
+		: "memory");
+
+	smp_mb();
+
+	return (old & mask) != 0;
+}
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It can be reorderdered on other architectures other than x86.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
+{
+	unsigned long mask = BIT_MASK(nr);
+	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+	unsigned long old, tmp, mask_not;
+
+	/*
+	 * old = *p;
+	 * *p = old & ~mask;
+	 */
+	mask_not = ~mask;
+	asm volatile (
+		"1:	ldex.w		%1, (%3)	\n"
+		"	mov		%0, %1		\n"
+		"	and32		%0, %0, %2	\n"
+		"	stex.w		%0, (%3)	\n"
+		"	bez		%0, 1b		\n"
+		: "=&r"(tmp), "=&r"(old)
+		: "r"(mask_not), "r"(p)
+		: "memory");
+
+	smp_mb();
+
+	return (old & mask) != 0;
+}
+
+/**
+ * test_and_change_bit - Change a bit and return its old value
+ * @nr: Bit to change
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
+{
+	unsigned long mask = BIT_MASK(nr);
+	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+	unsigned long old, tmp;
+
+	/*
+	 * old = *p;
+	 * *p = old ^ mask;
+	 */
+	asm volatile (
+		"1:	ldex.w		%1, (%3)	\n"
+		"	mov		%0, %1		\n"
+		"	xor32		%0, %0, %2	\n"
+		"	stex.w		%0, (%3)	\n"
+		"	bez		%0, 1b		\n"
+		: "=&r"(tmp), "=&r"(old)
+		: "r"(mask), "r"(p)
+		: "memory");
+
+	smp_mb();
+
+	return (old & mask) != 0;
+}
+
+#else
+#include <asm-generic/bitops/atomic.h>
+#endif
+
+/*
+ * bug fix, why only could use atomic!!!!
+ */
+#include <asm-generic/bitops/non-atomic.h>
+#define __clear_bit(nr,vaddr) clear_bit(nr,vaddr)
+
+#include <asm-generic/bitops/le.h>
+#include <asm-generic/bitops/ext2-atomic.h>
+#endif /* __ASM_CSKY_BITOPS_H */
+
diff --git a/arch/csky/include/asm/checksum.h b/arch/csky/include/asm/checksum.h
new file mode 100644
index 0000000..3f7d255
--- /dev/null
+++ b/arch/csky/include/asm/checksum.h
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_CHECKSUM_H
+#define __ASM_CSKY_CHECKSUM_H
+
+#include <linux/in6.h>
+#include <asm/byteorder.h>
+
+static inline __sum16 csum_fold(__wsum csum)
+{
+	u32 tmp;
+	asm volatile(
+		"mov	%1, %0\n"
+		"rori	%0, 16\n"
+		"addu	%0, %1\n"
+		"lsri	%0, 16\n"
+		:"=r"(csum), "=r"(tmp)
+		:"0"(csum));
+	return (__force __sum16)~csum;
+}
+#define csum_fold csum_fold
+
+static inline __wsum
+csum_tcpudp_nofold(
+	__be32 saddr,
+	__be32 daddr,
+	unsigned short len,
+	unsigned short proto,
+	__wsum sum
+	)
+{
+	asm volatile(
+		"clrc\n"
+		"addc    %0, %1\n"
+		"addc    %0, %2\n"
+		"addc    %0, %3\n"
+		"inct    %0\n"
+		:"=r"(sum)
+		:"r"((__force u32)saddr),
+		"r"((__force u32)daddr),
+#ifdef __BIG_ENDIAN
+		"r"(proto + len),
+#else
+		"r"((proto + len) << 8),
+#endif
+		"0" ((__force unsigned long)sum)
+		:"cc");
+	return sum;
+}
+#define csum_tcpudp_nofold csum_tcpudp_nofold
+
+static __inline__ __sum16
+csum_ipv6_magic(
+	const struct in6_addr *saddr,
+	const struct in6_addr *daddr,
+	__u32 len,
+	unsigned short proto,
+	__wsum sum
+	)
+{
+	sum += saddr->in6_u.u6_addr32[0];
+	sum += saddr->in6_u.u6_addr32[1];
+	sum += saddr->in6_u.u6_addr32[2];
+	sum += saddr->in6_u.u6_addr32[3];
+	sum += daddr->in6_u.u6_addr32[0];
+	sum += daddr->in6_u.u6_addr32[1];
+	sum += daddr->in6_u.u6_addr32[2];
+	sum += daddr->in6_u.u6_addr32[3];
+	sum += (len + proto);
+
+	return csum_fold(sum);
+}
+#define _HAVE_ARCH_IPV6_CSUM
+
+#include <asm-generic/checksum.h>
+
+#endif /* __ASM_CSKY_CHECKSUM_H */
diff --git a/arch/csky/include/asm/reg_ops.h b/arch/csky/include/asm/reg_ops.h
new file mode 100644
index 0000000..6963e5a
--- /dev/null
+++ b/arch/csky/include/asm/reg_ops.h
@@ -0,0 +1,16 @@
+#ifndef __ASM_REGS_OPS_H
+#define __ASM_REGS_OPS_H
+
+#define mfcr(reg)					\
+({							\
+	unsigned int tmp;				\
+	asm volatile("mfcr %0, "reg"\n":"=r"(tmp));	\
+	tmp;						\
+})
+
+#define mtcr(reg, val)					\
+({							\
+	asm volatile("mtcr %0, "reg"\n"::"r"(val));	\
+})
+
+#endif /* __ASM_REGS_OPS_H */
diff --git a/arch/csky/include/uapi/asm/byteorder.h b/arch/csky/include/uapi/asm/byteorder.h
new file mode 100644
index 0000000..d254522
--- /dev/null
+++ b/arch/csky/include/uapi/asm/byteorder.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#ifndef __ASM_CSKY_BYTEORDER_H
+#define __ASM_CSKY_BYTEORDER_H
+
+#if defined(__cskyBE__)
+#include <linux/byteorder/big_endian.h>
+#elif defined(__cskyLE__)
+#include <linux/byteorder/little_endian.h>
+#else
+# error "There is no __cskyBE__, __cskyLE__"
+#endif
+
+#endif /* __ASM_CSKY_BYTEORDER_H */
-- 
2.7.4


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

* [PATCH V2 18/19] clocksource: add C-SKY clocksource drivers
@ 2018-07-01 17:34   ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 drivers/clocksource/Makefile             |   1 +
 drivers/clocksource/timer-csky-v1.c      | 169 +++++++++++++++++++++++++++++++
 drivers/clocksource/timer-nationalchip.c | 165 ++++++++++++++++++++++++++++++
 3 files changed, 335 insertions(+)
 create mode 100644 drivers/clocksource/timer-csky-v1.c
 create mode 100644 drivers/clocksource/timer-nationalchip.c

diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index d6dec44..bbc567b 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -76,3 +76,4 @@ obj-$(CONFIG_H8300_TMR16)		+= h8300_timer16.o
 obj-$(CONFIG_H8300_TPU)			+= h8300_tpu.o
 obj-$(CONFIG_CLKSRC_ST_LPC)		+= clksrc_st_lpc.o
 obj-$(CONFIG_X86_NUMACHIP)		+= numachip.o
+obj-$(CONFIG_CSKY)			+= timer-csky-v1.o timer-nationalchip.o
diff --git a/drivers/clocksource/timer-csky-v1.c b/drivers/clocksource/timer-csky-v1.c
new file mode 100644
index 0000000..f3a822a
--- /dev/null
+++ b/drivers/clocksource/timer-csky-v1.c
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou NationalChip Science & Technology Co.,Ltd.
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched_clock.h>
+#include <linux/cpu.h>
+#include <asm/reg_ops.h>
+
+#include "timer-of.h"
+
+#define PTIM_CTLR	"cr<0, 14>"
+#define PTIM_TSR	"cr<1, 14>"
+#define PTIM_CCVR_HI	"cr<2, 14>"
+#define PTIM_CCVR_LO	"cr<3, 14>"
+#define PTIM_LVR	"cr<6, 14>"
+
+#define BITS_CSKY_TIMER	56
+
+DECLARE_PER_CPU(struct timer_of, csky_to);
+
+static int csky_timer_irq;
+static int csky_timer_rate;
+
+static inline u64 get_ccvr(void)
+{
+	u32 lo, hi, t;
+
+	do {
+		hi = mfcr(PTIM_CCVR_HI);
+		lo = mfcr(PTIM_CCVR_LO);
+		t  = mfcr(PTIM_CCVR_HI);
+	} while(t != hi);
+
+	return ((u64)hi << 32) | lo;
+}
+
+static irqreturn_t timer_interrupt(int irq, void *dev)
+{
+	struct timer_of *to = this_cpu_ptr(&csky_to);
+
+	mtcr(PTIM_TSR, 0);
+
+	to->clkevt.event_handler(&to->clkevt);
+
+	return IRQ_HANDLED;
+}
+
+static int csky_timer_set_next_event(unsigned long delta, struct clock_event_device *ce)
+{
+	mtcr(PTIM_LVR, delta);
+
+	return 0;
+}
+
+static int csky_timer_shutdown(struct clock_event_device *ce)
+{
+	mtcr(PTIM_CTLR, 0);
+
+	return 0;
+}
+
+static int csky_timer_oneshot(struct clock_event_device *ce)
+{
+	mtcr(PTIM_CTLR, 1);
+
+	return 0;
+}
+
+static int csky_timer_oneshot_stopped(struct clock_event_device *ce)
+{
+	mtcr(PTIM_CTLR, 0);
+
+	return 0;
+}
+
+DEFINE_PER_CPU(struct timer_of, csky_to) = {
+	.flags = TIMER_OF_CLOCK | TIMER_OF_IRQ,
+
+	.clkevt = {
+		.name = "C-SKY SMP Timer V1",
+		.rating = 300,
+		.features = CLOCK_EVT_FEAT_PERCPU | CLOCK_EVT_FEAT_ONESHOT,
+		.set_state_shutdown		= csky_timer_shutdown,
+		.set_state_oneshot		= csky_timer_oneshot,
+		.set_state_oneshot_stopped	= csky_timer_oneshot_stopped,
+		.set_next_event			= csky_timer_set_next_event,
+	},
+
+	.of_irq = {
+		.handler = timer_interrupt,
+		.flags = IRQF_TIMER,
+		.percpu = 1,
+	},
+};
+
+/*** clock event for percpu ***/
+static int csky_timer_starting_cpu(unsigned int cpu)
+{
+	struct timer_of *to = this_cpu_ptr(&csky_to);
+
+	to->clkevt.cpumask = cpumask_of(smp_processor_id());
+
+	clockevents_config_and_register(&to->clkevt, csky_timer_rate, 0, ULONG_MAX);
+
+	enable_percpu_irq(csky_timer_irq, 0);
+
+	return 0;
+}
+
+static int csky_timer_dying_cpu(unsigned int cpu)
+{
+	disable_percpu_irq(csky_timer_irq);
+
+	return 0;
+}
+
+/*** clock source ***/
+static u64 sched_clock_read(void)
+{
+	return get_ccvr();
+}
+
+static u64 clksrc_read(struct clocksource *c)
+{
+	return get_ccvr();
+}
+
+struct clocksource csky_clocksource = {
+	.name = "csky_timer_v1_clksrc",
+	.rating = 400,
+	.mask = CLOCKSOURCE_MASK(BITS_CSKY_TIMER),
+	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
+	.read = clksrc_read,
+};
+
+static void csky_clksrc_init(void)
+{
+	clocksource_register_hz(&csky_clocksource, csky_timer_rate);
+
+	sched_clock_register(sched_clock_read, BITS_CSKY_TIMER, csky_timer_rate);
+}
+
+static int __init csky_timer_v1_init(struct device_node *np)
+{
+	int ret;
+	struct timer_of *to = this_cpu_ptr(&csky_to);
+
+	ret = timer_of_init(np, to);
+	if (ret)
+		return ret;
+
+	csky_timer_irq = to->of_irq.irq;
+	csky_timer_rate = timer_of_rate(to);
+
+	ret = cpuhp_setup_state(CPUHP_AP_DUMMY_TIMER_STARTING,
+				"clockevents/csky/timer:starting",
+				csky_timer_starting_cpu,
+				csky_timer_dying_cpu);
+	if (ret) {
+		pr_err("%s: Failed to cpuhp_setup_state.\n", __func__);
+		return ret;
+	}
+
+	csky_clksrc_init();
+
+	return ret;
+}
+TIMER_OF_DECLARE(csky_timer_v1, "csky,timer-v1", csky_timer_v1_init);
+
diff --git a/drivers/clocksource/timer-nationalchip.c b/drivers/clocksource/timer-nationalchip.c
new file mode 100644
index 0000000..8f4e1e5
--- /dev/null
+++ b/drivers/clocksource/timer-nationalchip.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou NationalChip Science & Technology Co.,Ltd.
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched_clock.h>
+
+#include "timer-of.h"
+
+#define TIMER_NAME	"nc_timer"
+#define TIMER_FREQ	1000000
+#define CLKSRC_OFFSET	0x40
+
+#define TIMER_STATUS	0x00
+#define TIMER_VALUE	0x04
+#define TIMER_CONTRL	0x10
+#define TIMER_CONFIG	0x20
+#define TIMER_DIV	0x24
+#define TIMER_INI	0x28
+
+#define STATUS_clr	BIT(0)
+
+#define CONTRL_rst	BIT(0)
+#define CONTRL_start	BIT(1)
+
+#define CONFIG_en	BIT(0)
+#define CONFIG_irq_en	BIT(1)
+
+static irqreturn_t timer_interrupt(int irq, void *dev)
+{
+	struct clock_event_device *ce = (struct clock_event_device *) dev;
+	void __iomem *base = timer_of_base(to_timer_of(ce));
+
+	writel_relaxed(STATUS_clr, base + TIMER_STATUS);
+
+	ce->event_handler(ce);
+
+	return IRQ_HANDLED;
+}
+
+static int nc_timer_set_periodic(struct clock_event_device *ce)
+{
+	void __iomem *base = timer_of_base(to_timer_of(ce));
+
+	/* reset */
+	writel_relaxed(CONTRL_rst, base + TIMER_CONTRL);
+
+	/* config the timeout value */
+	writel_relaxed(ULONG_MAX - timer_of_period(to_timer_of(ce)),
+		       base + TIMER_INI);
+
+	/* enable with irq and start */
+	writel_relaxed(CONFIG_en|CONFIG_irq_en, base + TIMER_CONFIG);
+	writel_relaxed(CONTRL_start, base + TIMER_CONTRL);
+
+	return 0;
+}
+
+static int nc_timer_set_next_event(unsigned long delta, struct clock_event_device *ce)
+{
+	void __iomem *base = timer_of_base(to_timer_of(ce));
+
+	/* use reset to pause timer */
+	writel_relaxed(CONTRL_rst, base + TIMER_CONTRL);
+
+	/* config next timeout value */
+	writel_relaxed(ULONG_MAX - delta, base + TIMER_INI);
+	writel_relaxed(CONTRL_start, base + TIMER_CONTRL);
+
+	return 0;
+}
+
+static int nc_timer_shutdown(struct clock_event_device *ce)
+{
+	void __iomem *base = timer_of_base(to_timer_of(ce));
+
+	writel_relaxed(0, base + TIMER_CONTRL);
+	writel_relaxed(0, base + TIMER_CONFIG);
+
+	return 0;
+}
+
+static struct timer_of to = {
+	.flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
+
+	.clkevt = {
+		.name = TIMER_NAME,
+		.rating = 300,
+		.features = CLOCK_EVT_FEAT_DYNIRQ | CLOCK_EVT_FEAT_PERIODIC |
+			CLOCK_EVT_FEAT_ONESHOT,
+		.set_state_shutdown	= nc_timer_shutdown,
+		.set_state_periodic	= nc_timer_set_periodic,
+		.set_next_event		= nc_timer_set_next_event,
+		.cpumask = cpu_possible_mask,
+	},
+
+	.of_irq = {
+		.handler = timer_interrupt,
+		.flags = IRQF_TIMER | IRQF_IRQPOLL,
+	},
+};
+
+static u64 notrace nc_sched_clock_read(void)
+{
+	void __iomem *base;
+
+	base = timer_of_base(&to) + CLKSRC_OFFSET; 
+
+	return (u64) readl_relaxed(base + TIMER_VALUE);
+}
+
+static void nc_timer_set_div(void __iomem *base)
+{
+	unsigned int div;
+
+	div = timer_of_rate(&to)/TIMER_FREQ - 1;
+
+	writel_relaxed(div, base + TIMER_DIV);
+}
+
+static void nc_clkevt_init(void __iomem *base)
+{
+	/* reset */
+	writel_relaxed(CONTRL_rst, base + TIMER_CONTRL);
+
+	/* reset config */
+	writel_relaxed(0, base + TIMER_CONFIG);
+
+	nc_timer_set_div(base);
+
+	clockevents_config_and_register(&to.clkevt, TIMER_FREQ, 1, ULONG_MAX);
+}
+
+static void nc_clksrc_init(void __iomem *base)
+{
+	writel_relaxed(CONTRL_rst, base + TIMER_CONTRL);
+
+	writel_relaxed(CONFIG_en, base + TIMER_CONFIG);
+
+	nc_timer_set_div(base);
+
+	writel_relaxed(0, base + TIMER_INI);
+	writel_relaxed(CONTRL_start, base + TIMER_CONTRL);
+
+	clocksource_mmio_init(base + TIMER_VALUE, "nationalchip", TIMER_FREQ, 200, 32,
+			      clocksource_mmio_readl_up);
+
+	sched_clock_register(nc_sched_clock_read, 32, TIMER_FREQ);
+}
+
+static int __init nc_timer_init(struct device_node *np)
+{
+	int ret;
+
+	ret = timer_of_init(np, &to);
+	if (ret)
+		return ret;
+
+	nc_clkevt_init(timer_of_base(&to));
+
+	nc_clksrc_init(timer_of_base(&to) + CLKSRC_OFFSET);
+
+	return 0;
+}
+TIMER_OF_DECLARE(nc_timer, "nationalchip,timer-v1", nc_timer_init);
+
-- 
2.7.4


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

* [PATCH V2 19/19] irqchip: add C-SKY irqchip drivers
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (17 preceding siblings ...)
  2018-07-01 17:34   ` Guo Ren
@ 2018-07-01 17:30 ` Guo Ren
  2018-07-03  3:27   ` Rob Herring
  2018-07-03  9:28   ` Thomas Gleixner
  2018-07-11  9:51 ` [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port David Howells
  19 siblings, 2 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:30 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 drivers/irqchip/Makefile           |   1 +
 drivers/irqchip/irq-csky-v1.c      | 126 ++++++++++++++++++++++++
 drivers/irqchip/irq-csky-v2.c      | 191 +++++++++++++++++++++++++++++++++++++
 drivers/irqchip/irq-nationalchip.c | 131 +++++++++++++++++++++++++
 4 files changed, 449 insertions(+)
 create mode 100644 drivers/irqchip/irq-csky-v1.c
 create mode 100644 drivers/irqchip/irq-csky-v2.c
 create mode 100644 drivers/irqchip/irq-nationalchip.c

diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index d27e3e3..51e7316 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -85,3 +85,4 @@ obj-$(CONFIG_IRQ_UNIPHIER_AIDET)	+= irq-uniphier-aidet.o
 obj-$(CONFIG_ARCH_SYNQUACER)		+= irq-sni-exiu.o
 obj-$(CONFIG_MESON_IRQ_GPIO)		+= irq-meson-gpio.o
 obj-$(CONFIG_GOLDFISH_PIC) 		+= irq-goldfish-pic.o
+obj-$(CONFIG_CSKY) 			+= irq-csky-v1.o irq-csky-v2.o irq-nationalchip.o
diff --git a/drivers/irqchip/irq-csky-v1.c b/drivers/irqchip/irq-csky-v1.c
new file mode 100644
index 0000000..64ea564
--- /dev/null
+++ b/drivers/irqchip/irq-csky-v1.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/module.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/traps.h>
+
+#ifdef CONFIG_CSKY_VECIRQ_LEGENCY
+#include <asm/reg_ops.h>
+#endif
+
+static void __iomem *reg_base;
+
+#define INTC_ICR	0x00
+#define INTC_ISR	0x00
+#define INTC_NEN31_00	0x10
+#define INTC_NEN63_32	0x28
+#define INTC_IFR31_00	0x08
+#define INTC_IFR63_32	0x20
+#define INTC_SOURCE	0x40
+
+#define INTC_IRQS	64
+
+#define INTC_ICR_AVE	BIT(31)
+
+#define VEC_IRQ_BASE	32
+
+static struct irq_domain *root_domain;
+
+static void __init ck_set_gc(void __iomem *reg_base, u32 irq_base,
+			     u32 mask_reg)
+{
+	struct irq_chip_generic *gc;
+
+	gc = irq_get_domain_generic_chip(root_domain, irq_base);
+	gc->reg_base = reg_base;
+	gc->chip_types[0].regs.mask = mask_reg;
+	gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
+	gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
+}
+
+static struct irq_domain *root_domain;
+static void ck_irq_handler(struct pt_regs *regs)
+{
+#ifdef CONFIG_CSKY_VECIRQ_LEGENCY
+	irq_hw_number_t irq = ((mfcr("psr") >> 16) & 0xff) - VEC_IRQ_BASE;
+#else
+	irq_hw_number_t irq = readl_relaxed(reg_base + INTC_ISR) & 0x3f;
+#endif
+	handle_domain_irq(root_domain, irq, regs);
+}
+
+#define expand_byte_to_word(i) (i|(i<<8)|(i<<16)|(i<<24))
+static inline void setup_irq_channel(void __iomem *reg_base)
+{
+	int i;
+
+	/*
+	 * There are 64 irq nums and irq-channels and one byte per channel.
+	 * Setup every channel with the same hwirq num.
+	 */
+	for (i = 0; i < INTC_IRQS; i += 4) {
+		writel_relaxed(expand_byte_to_word(i) + 0x00010203,
+			       reg_base + INTC_SOURCE + i);
+	}
+}
+
+static int __init
+csky_intc_v1_init(struct device_node *node, struct device_node *parent)
+{
+	u32 clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
+	int ret;
+
+	if (parent) {
+		pr_err("C-SKY Intc not a root irq controller\n");
+		return -EINVAL;
+	}
+
+	reg_base = of_iomap(node, 0);
+	if (!reg_base) {
+		pr_err("C-SKY Intc unable to map: %p.\n", node);
+		return -EINVAL;
+	}
+
+	writel_relaxed(0, reg_base + INTC_NEN31_00);
+	writel_relaxed(0, reg_base + INTC_NEN63_32);
+
+#ifndef CONFIG_CSKY_VECIRQ_LEGENCY
+	writel_relaxed(INTC_ICR_AVE, reg_base + INTC_ICR);
+#else
+	writel_relaxed(0, reg_base + INTC_ICR);
+#endif
+
+	setup_irq_channel(reg_base);
+
+	root_domain = irq_domain_add_linear(node, INTC_IRQS, &irq_generic_chip_ops, NULL);
+	if (!root_domain) {
+		pr_err("C-SKY Intc irq_domain_add failed.\n");
+		return -ENOMEM;
+	}
+
+	ret = irq_alloc_domain_generic_chips(root_domain, 32, 1,
+					     "csky_intc_v1", handle_level_irq,
+					     clr, 0, 0);
+	if (ret) {
+		pr_err("C-SKY Intc irq_alloc_gc failed.\n");
+		return -ENOMEM;
+	}
+
+	ck_set_gc(reg_base, 0,  INTC_NEN31_00);
+	ck_set_gc(reg_base, 32, INTC_NEN63_32);
+
+	set_handle_irq(ck_irq_handler);
+
+	return 0;
+}
+IRQCHIP_DECLARE(csky_intc_v1, "csky,intc-v1", csky_intc_v1_init);
+
diff --git a/drivers/irqchip/irq-csky-v2.c b/drivers/irqchip/irq-csky-v2.c
new file mode 100644
index 0000000..b588364
--- /dev/null
+++ b/drivers/irqchip/irq-csky-v2.c
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/module.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/traps.h>
+#include <asm/reg_ops.h>
+#include <asm/smp.h>
+
+static void __iomem *INTCG_base;
+static void __iomem *INTCL_base;
+
+#define COMM_IRQ_BASE	32
+
+#define INTCG_SIZE	0x8000
+#define INTCL_SIZE	0x1000
+#define INTC_SIZE	INTCL_SIZE*nr_cpu_ids + INTCG_SIZE
+
+#define INTCG_ICTLR	0x0
+#define INTCG_CICFGR	0x100
+#define INTCG_CIDSTR	0x1000
+
+#define INTCL_PICTLR	0x0
+#define INTCL_SIGR	0x60
+#define INTCL_RDYIR	0x6c
+#define INTCL_SENR	0xa0
+#define INTCL_CENR	0xa4
+#define INTCL_CACR	0xb4
+
+#define INTC_IRQS	256
+
+#define INTC_ICR_AVE	BIT(31)
+
+DEFINE_PER_CPU(void __iomem *, intcl_reg);
+
+static void csky_irq_v2_handler(struct pt_regs *regs)
+{
+	static void __iomem	*reg_base;
+	irq_hw_number_t		hwirq;
+
+	reg_base = *this_cpu_ptr(&intcl_reg);
+
+	hwirq = readl_relaxed(reg_base + INTCL_RDYIR);
+	handle_domain_irq(NULL, hwirq, regs);
+}
+
+static void csky_irq_v2_enable(struct irq_data *d)
+{
+	static void __iomem	*reg_base;
+
+	reg_base = *this_cpu_ptr(&intcl_reg);
+
+	writel_relaxed(d->hwirq, reg_base + INTCL_SENR);
+}
+
+static void csky_irq_v2_disable(struct irq_data *d)
+{
+	static void __iomem	*reg_base;
+
+	reg_base = *this_cpu_ptr(&intcl_reg);
+
+	writel_relaxed(d->hwirq, reg_base + INTCL_CENR);
+}
+
+static void csky_irq_v2_eoi(struct irq_data *d)
+{
+	static void __iomem	*reg_base;
+
+	reg_base = *this_cpu_ptr(&intcl_reg);
+
+	writel_relaxed(d->hwirq, reg_base + INTCL_CACR);
+}
+
+#ifdef CONFIG_SMP
+static int csky_irq_set_affinity(struct irq_data *d,
+				 const struct cpumask *mask_val,
+				 bool force)
+{
+	unsigned int cpu;
+
+	if (!force)
+		cpu = cpumask_any_and(mask_val, cpu_online_mask);
+	else
+		cpu = cpumask_first(mask_val);
+
+	if (cpu >= nr_cpu_ids)
+		return -EINVAL;
+
+	/* Enable interrupt destination */
+	cpu |= BIT(31);
+
+	writel_relaxed(cpu, INTCG_base + INTCG_CIDSTR + (4*(d->hwirq - COMM_IRQ_BASE)));
+
+	irq_data_update_effective_affinity(d, cpumask_of(cpu));
+
+	return IRQ_SET_MASK_OK_DONE;
+}
+#endif
+
+static struct irq_chip csky_irq_chip = {
+	.name           = "C-SKY SMP Intc V2",
+	.irq_eoi	= csky_irq_v2_eoi,
+	.irq_enable	= csky_irq_v2_enable,
+	.irq_disable	= csky_irq_v2_disable,
+#ifdef CONFIG_SMP
+	.irq_set_affinity = csky_irq_set_affinity,
+#endif
+};
+
+static int csky_irqdomain_map(struct irq_domain *d, unsigned int irq,
+			      irq_hw_number_t hwirq)
+{
+	if(hwirq < COMM_IRQ_BASE) {
+		irq_set_percpu_devid(irq);
+		irq_set_chip_and_handler(irq, &csky_irq_chip, handle_percpu_irq);
+	} else
+		irq_set_chip_and_handler(irq, &csky_irq_chip, handle_fasteoi_irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops csky_irqdomain_ops = {
+	.map	= csky_irqdomain_map,
+	.xlate	= irq_domain_xlate_onecell,
+};
+
+#ifdef CONFIG_SMP
+static void csky_irq_v2_send_ipi(const unsigned long *mask, unsigned long irq)
+{
+	static void __iomem	*reg_base;
+
+	reg_base = *this_cpu_ptr(&intcl_reg);
+
+	/*
+	 * INTCL_SIGR[3:0] INTID
+	 * INTCL_SIGR[8:15] CPUMASK
+	 */
+	writel_relaxed((*mask) << 8 | irq, reg_base + INTCL_SIGR);
+}
+#endif
+
+static int __init
+csky_intc_v2_init(struct device_node *node, struct device_node *parent)
+{
+	struct irq_domain *root_domain;
+	int cpu;
+
+	if (parent)
+		return 0;
+
+	if (INTCG_base == NULL) {
+		INTCG_base = ioremap(mfcr("cr<31, 14>"), INTC_SIZE);
+		if (INTCG_base == NULL)
+			return -EIO;
+
+		INTCL_base = INTCG_base + INTCG_SIZE;
+
+		writel_relaxed(BIT(0), INTCG_base + INTCG_ICTLR);
+	}
+
+	root_domain = irq_domain_add_linear(node, INTC_IRQS,
+					&csky_irqdomain_ops, NULL);
+	if (!root_domain)
+		return -ENXIO;
+
+	irq_set_default_host(root_domain);
+
+	/* for every cpu */
+	for_each_present_cpu(cpu) {
+		per_cpu(intcl_reg, cpu) = INTCL_base + (INTCL_SIZE * cpu);
+		writel_relaxed(BIT(0), per_cpu(intcl_reg, cpu) + INTCL_PICTLR);
+	}
+
+	set_handle_irq(&csky_irq_v2_handler);
+
+#ifdef CONFIG_SMP
+	set_send_ipi(&csky_irq_v2_send_ipi);
+#endif
+
+	return 0;
+}
+IRQCHIP_DECLARE(csky_intc_v2, "csky,intc-v2", csky_intc_v2_init);
+
diff --git a/drivers/irqchip/irq-nationalchip.c b/drivers/irqchip/irq-nationalchip.c
new file mode 100644
index 0000000..90b1805
--- /dev/null
+++ b/drivers/irqchip/irq-nationalchip.c
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou NationalChip Science & Technology Co.,Ltd.
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/module.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/traps.h>
+
+static void __iomem *reg_base;
+
+#define INTC_NINT31_00		0x00
+#define INTC_NINT63_32		0x04
+#define INTC_NEN31_00		0x40
+#define INTC_NEN63_32		0x44
+#define INTC_NENSET31_00	0x20
+#define INTC_NENSET63_32	0x24
+#define INTC_NENCLR31_00	0x30
+#define INTC_NENCLR63_32	0x34
+#define INTC_NMASK31_00		0x50
+#define INTC_NMASK63_32		0x54
+#define INTC_SOURCE		0x60
+
+#define INTC_IRQS		64
+
+static struct irq_domain *root_domain;
+
+static void nc_irq_handler(struct pt_regs *regs)
+{
+	u32 status, irq;
+
+	do {
+		status = readl_relaxed(reg_base + INTC_NINT31_00);
+		if (status) {
+			irq = __ffs(status);
+		} else {
+			status = readl_relaxed(reg_base + INTC_NINT63_32);
+			if (status)
+				irq = __ffs(status) + 32;
+			else
+				return;
+		}
+		handle_domain_irq(root_domain, irq, regs);
+	} while(1);
+}
+
+static void __init nc_set_gc(void __iomem *reg_base, u32 irq_base,
+			     u32 en_reg, u32 dis_reg)
+{
+	struct irq_chip_generic *gc;
+
+	gc = irq_get_domain_generic_chip(root_domain, irq_base);
+	gc->reg_base = reg_base;
+	gc->chip_types[0].regs.enable = en_reg;
+	gc->chip_types[0].regs.disable = dis_reg;
+	gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg;
+	gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg;
+}
+
+#define expand_byte_to_word(i) (i|(i<<8)|(i<<16)|(i<<24))
+static inline void setup_irq_channel(void __iomem *reg_base)
+{
+	int i;
+
+	/*
+	 * There are 64 irq nums and irq-channels and one byte per channel.
+	 * Setup every channel with the same hwirq num.
+	 */
+	for (i = 0; i < INTC_IRQS; i += 4) {
+		writel_relaxed(expand_byte_to_word(i) + 0x03020100,
+			       reg_base + INTC_SOURCE + i);
+	}
+}
+
+static int __init
+intc_init(struct device_node *node, struct device_node *parent)
+{
+	u32 clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
+	int ret;
+
+	if (parent) {
+		pr_err("Nationalchip gx6605s Intc not a root irq controller\n");
+		return -EINVAL;
+	}
+
+	reg_base = of_iomap(node, 0);
+	if (!reg_base) {
+		pr_err("Nationalchip gx6605s Intc unable to map: %p.\n", node);
+		return -EINVAL;
+	}
+
+	/* Initial enable reg to disable all interrupts */
+	writel_relaxed(0x0, reg_base + INTC_NEN31_00);
+	writel_relaxed(0x0, reg_base + INTC_NEN63_32);
+
+	/* Initial mask reg with all unmasked, becasue we only use enalbe reg */
+	writel_relaxed(0x0, reg_base + INTC_NMASK31_00);
+	writel_relaxed(0x0, reg_base + INTC_NMASK63_32);
+
+	setup_irq_channel(reg_base);
+
+	root_domain = irq_domain_add_linear(node, INTC_IRQS, &irq_generic_chip_ops, NULL);
+	if (!root_domain) {
+		pr_err("Nationalchip gx6605s Intc irq_domain_add failed.\n");
+		return -ENOMEM;
+	}
+
+	ret = irq_alloc_domain_generic_chips(root_domain, 32, 1,
+					     "gx6605s_irq", handle_level_irq,
+					     clr, 0, 0);
+	if (ret) {
+		pr_err("Nationalchip gx6605s Intc irq_alloc_gc failed.\n");
+		return -ENOMEM;
+	}
+
+	nc_set_gc(reg_base, 0,  INTC_NENSET31_00, INTC_NENCLR31_00);
+	nc_set_gc(reg_base, 32, INTC_NENSET63_32, INTC_NENCLR63_32);
+
+	set_handle_irq(nc_irq_handler);
+
+	return 0;
+}
+
+IRQCHIP_DECLARE(nationalchip_intc_v1_ave, "nationalchip,intc-v1,ave", intc_init);
+
-- 
2.7.4


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

* [PATCH V2 18/19] clocksource: add C-SKY clocksource drivers
@ 2018-07-01 17:34   ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-01 17:34 UTC (permalink / raw)
  To: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, ren_guo, green.hu

Signed-off-by: Guo Ren <ren_guo@c-sky.com>
---
 drivers/clocksource/Makefile             |   1 +
 drivers/clocksource/timer-csky-v1.c      | 169 +++++++++++++++++++++++++++++++
 drivers/clocksource/timer-nationalchip.c | 165 ++++++++++++++++++++++++++++++
 3 files changed, 335 insertions(+)
 create mode 100644 drivers/clocksource/timer-csky-v1.c
 create mode 100644 drivers/clocksource/timer-nationalchip.c

diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index d6dec44..bbc567b 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -76,3 +76,4 @@ obj-$(CONFIG_H8300_TMR16)		+= h8300_timer16.o
 obj-$(CONFIG_H8300_TPU)			+= h8300_tpu.o
 obj-$(CONFIG_CLKSRC_ST_LPC)		+= clksrc_st_lpc.o
 obj-$(CONFIG_X86_NUMACHIP)		+= numachip.o
+obj-$(CONFIG_CSKY)			+= timer-csky-v1.o timer-nationalchip.o
diff --git a/drivers/clocksource/timer-csky-v1.c b/drivers/clocksource/timer-csky-v1.c
new file mode 100644
index 0000000..f3a822a
--- /dev/null
+++ b/drivers/clocksource/timer-csky-v1.c
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou NationalChip Science & Technology Co.,Ltd.
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched_clock.h>
+#include <linux/cpu.h>
+#include <asm/reg_ops.h>
+
+#include "timer-of.h"
+
+#define PTIM_CTLR	"cr<0, 14>"
+#define PTIM_TSR	"cr<1, 14>"
+#define PTIM_CCVR_HI	"cr<2, 14>"
+#define PTIM_CCVR_LO	"cr<3, 14>"
+#define PTIM_LVR	"cr<6, 14>"
+
+#define BITS_CSKY_TIMER	56
+
+DECLARE_PER_CPU(struct timer_of, csky_to);
+
+static int csky_timer_irq;
+static int csky_timer_rate;
+
+static inline u64 get_ccvr(void)
+{
+	u32 lo, hi, t;
+
+	do {
+		hi = mfcr(PTIM_CCVR_HI);
+		lo = mfcr(PTIM_CCVR_LO);
+		t  = mfcr(PTIM_CCVR_HI);
+	} while(t != hi);
+
+	return ((u64)hi << 32) | lo;
+}
+
+static irqreturn_t timer_interrupt(int irq, void *dev)
+{
+	struct timer_of *to = this_cpu_ptr(&csky_to);
+
+	mtcr(PTIM_TSR, 0);
+
+	to->clkevt.event_handler(&to->clkevt);
+
+	return IRQ_HANDLED;
+}
+
+static int csky_timer_set_next_event(unsigned long delta, struct clock_event_device *ce)
+{
+	mtcr(PTIM_LVR, delta);
+
+	return 0;
+}
+
+static int csky_timer_shutdown(struct clock_event_device *ce)
+{
+	mtcr(PTIM_CTLR, 0);
+
+	return 0;
+}
+
+static int csky_timer_oneshot(struct clock_event_device *ce)
+{
+	mtcr(PTIM_CTLR, 1);
+
+	return 0;
+}
+
+static int csky_timer_oneshot_stopped(struct clock_event_device *ce)
+{
+	mtcr(PTIM_CTLR, 0);
+
+	return 0;
+}
+
+DEFINE_PER_CPU(struct timer_of, csky_to) = {
+	.flags = TIMER_OF_CLOCK | TIMER_OF_IRQ,
+
+	.clkevt = {
+		.name = "C-SKY SMP Timer V1",
+		.rating = 300,
+		.features = CLOCK_EVT_FEAT_PERCPU | CLOCK_EVT_FEAT_ONESHOT,
+		.set_state_shutdown		= csky_timer_shutdown,
+		.set_state_oneshot		= csky_timer_oneshot,
+		.set_state_oneshot_stopped	= csky_timer_oneshot_stopped,
+		.set_next_event			= csky_timer_set_next_event,
+	},
+
+	.of_irq = {
+		.handler = timer_interrupt,
+		.flags = IRQF_TIMER,
+		.percpu = 1,
+	},
+};
+
+/*** clock event for percpu ***/
+static int csky_timer_starting_cpu(unsigned int cpu)
+{
+	struct timer_of *to = this_cpu_ptr(&csky_to);
+
+	to->clkevt.cpumask = cpumask_of(smp_processor_id());
+
+	clockevents_config_and_register(&to->clkevt, csky_timer_rate, 0, ULONG_MAX);
+
+	enable_percpu_irq(csky_timer_irq, 0);
+
+	return 0;
+}
+
+static int csky_timer_dying_cpu(unsigned int cpu)
+{
+	disable_percpu_irq(csky_timer_irq);
+
+	return 0;
+}
+
+/*** clock source ***/
+static u64 sched_clock_read(void)
+{
+	return get_ccvr();
+}
+
+static u64 clksrc_read(struct clocksource *c)
+{
+	return get_ccvr();
+}
+
+struct clocksource csky_clocksource = {
+	.name = "csky_timer_v1_clksrc",
+	.rating = 400,
+	.mask = CLOCKSOURCE_MASK(BITS_CSKY_TIMER),
+	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
+	.read = clksrc_read,
+};
+
+static void csky_clksrc_init(void)
+{
+	clocksource_register_hz(&csky_clocksource, csky_timer_rate);
+
+	sched_clock_register(sched_clock_read, BITS_CSKY_TIMER, csky_timer_rate);
+}
+
+static int __init csky_timer_v1_init(struct device_node *np)
+{
+	int ret;
+	struct timer_of *to = this_cpu_ptr(&csky_to);
+
+	ret = timer_of_init(np, to);
+	if (ret)
+		return ret;
+
+	csky_timer_irq = to->of_irq.irq;
+	csky_timer_rate = timer_of_rate(to);
+
+	ret = cpuhp_setup_state(CPUHP_AP_DUMMY_TIMER_STARTING,
+				"clockevents/csky/timer:starting",
+				csky_timer_starting_cpu,
+				csky_timer_dying_cpu);
+	if (ret) {
+		pr_err("%s: Failed to cpuhp_setup_state.\n", __func__);
+		return ret;
+	}
+
+	csky_clksrc_init();
+
+	return ret;
+}
+TIMER_OF_DECLARE(csky_timer_v1, "csky,timer-v1", csky_timer_v1_init);
+
diff --git a/drivers/clocksource/timer-nationalchip.c b/drivers/clocksource/timer-nationalchip.c
new file mode 100644
index 0000000..8f4e1e5
--- /dev/null
+++ b/drivers/clocksource/timer-nationalchip.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Hangzhou NationalChip Science & Technology Co.,Ltd.
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched_clock.h>
+
+#include "timer-of.h"
+
+#define TIMER_NAME	"nc_timer"
+#define TIMER_FREQ	1000000
+#define CLKSRC_OFFSET	0x40
+
+#define TIMER_STATUS	0x00
+#define TIMER_VALUE	0x04
+#define TIMER_CONTRL	0x10
+#define TIMER_CONFIG	0x20
+#define TIMER_DIV	0x24
+#define TIMER_INI	0x28
+
+#define STATUS_clr	BIT(0)
+
+#define CONTRL_rst	BIT(0)
+#define CONTRL_start	BIT(1)
+
+#define CONFIG_en	BIT(0)
+#define CONFIG_irq_en	BIT(1)
+
+static irqreturn_t timer_interrupt(int irq, void *dev)
+{
+	struct clock_event_device *ce = (struct clock_event_device *) dev;
+	void __iomem *base = timer_of_base(to_timer_of(ce));
+
+	writel_relaxed(STATUS_clr, base + TIMER_STATUS);
+
+	ce->event_handler(ce);
+
+	return IRQ_HANDLED;
+}
+
+static int nc_timer_set_periodic(struct clock_event_device *ce)
+{
+	void __iomem *base = timer_of_base(to_timer_of(ce));
+
+	/* reset */
+	writel_relaxed(CONTRL_rst, base + TIMER_CONTRL);
+
+	/* config the timeout value */
+	writel_relaxed(ULONG_MAX - timer_of_period(to_timer_of(ce)),
+		       base + TIMER_INI);
+
+	/* enable with irq and start */
+	writel_relaxed(CONFIG_en|CONFIG_irq_en, base + TIMER_CONFIG);
+	writel_relaxed(CONTRL_start, base + TIMER_CONTRL);
+
+	return 0;
+}
+
+static int nc_timer_set_next_event(unsigned long delta, struct clock_event_device *ce)
+{
+	void __iomem *base = timer_of_base(to_timer_of(ce));
+
+	/* use reset to pause timer */
+	writel_relaxed(CONTRL_rst, base + TIMER_CONTRL);
+
+	/* config next timeout value */
+	writel_relaxed(ULONG_MAX - delta, base + TIMER_INI);
+	writel_relaxed(CONTRL_start, base + TIMER_CONTRL);
+
+	return 0;
+}
+
+static int nc_timer_shutdown(struct clock_event_device *ce)
+{
+	void __iomem *base = timer_of_base(to_timer_of(ce));
+
+	writel_relaxed(0, base + TIMER_CONTRL);
+	writel_relaxed(0, base + TIMER_CONFIG);
+
+	return 0;
+}
+
+static struct timer_of to = {
+	.flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
+
+	.clkevt = {
+		.name = TIMER_NAME,
+		.rating = 300,
+		.features = CLOCK_EVT_FEAT_DYNIRQ | CLOCK_EVT_FEAT_PERIODIC |
+			CLOCK_EVT_FEAT_ONESHOT,
+		.set_state_shutdown	= nc_timer_shutdown,
+		.set_state_periodic	= nc_timer_set_periodic,
+		.set_next_event		= nc_timer_set_next_event,
+		.cpumask = cpu_possible_mask,
+	},
+
+	.of_irq = {
+		.handler = timer_interrupt,
+		.flags = IRQF_TIMER | IRQF_IRQPOLL,
+	},
+};
+
+static u64 notrace nc_sched_clock_read(void)
+{
+	void __iomem *base;
+
+	base = timer_of_base(&to) + CLKSRC_OFFSET; 
+
+	return (u64) readl_relaxed(base + TIMER_VALUE);
+}
+
+static void nc_timer_set_div(void __iomem *base)
+{
+	unsigned int div;
+
+	div = timer_of_rate(&to)/TIMER_FREQ - 1;
+
+	writel_relaxed(div, base + TIMER_DIV);
+}
+
+static void nc_clkevt_init(void __iomem *base)
+{
+	/* reset */
+	writel_relaxed(CONTRL_rst, base + TIMER_CONTRL);
+
+	/* reset config */
+	writel_relaxed(0, base + TIMER_CONFIG);
+
+	nc_timer_set_div(base);
+
+	clockevents_config_and_register(&to.clkevt, TIMER_FREQ, 1, ULONG_MAX);
+}
+
+static void nc_clksrc_init(void __iomem *base)
+{
+	writel_relaxed(CONTRL_rst, base + TIMER_CONTRL);
+
+	writel_relaxed(CONFIG_en, base + TIMER_CONFIG);
+
+	nc_timer_set_div(base);
+
+	writel_relaxed(0, base + TIMER_INI);
+	writel_relaxed(CONTRL_start, base + TIMER_CONTRL);
+
+	clocksource_mmio_init(base + TIMER_VALUE, "nationalchip", TIMER_FREQ, 200, 32,
+			      clocksource_mmio_readl_up);
+
+	sched_clock_register(nc_sched_clock_read, 32, TIMER_FREQ);
+}
+
+static int __init nc_timer_init(struct device_node *np)
+{
+	int ret;
+
+	ret = timer_of_init(np, &to);
+	if (ret)
+		return ret;
+
+	nc_clkevt_init(timer_of_base(&to));
+
+	nc_clksrc_init(timer_of_base(&to) + CLKSRC_OFFSET);
+
+	return 0;
+}
+TIMER_OF_DECLARE(nc_timer, "nationalchip,timer-v1", nc_timer_init);
+
-- 
2.7.4


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

* Re: [PATCH V2 01/19] csky: Build infrastructure
  2018-07-01 17:30 ` [PATCH V2 01/19] csky: Build infrastructure Guo Ren
@ 2018-07-01 21:01   ` Randy Dunlap
  2018-07-02  1:13     ` Guo Ren
  2018-07-03  3:33   ` Rob Herring
  2018-07-03 16:03   ` Arnd Bergmann
  2 siblings, 1 reply; 88+ messages in thread
From: Randy Dunlap @ 2018-07-01 21:01 UTC (permalink / raw)
  To: Guo Ren, linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On 07/01/18 10:30, Guo Ren wrote:
> Signed-off-by: Guo Ren <ren_guo@c-sky.com>
> ---

Hi,
Just a few comments...

> 
> diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig
> new file mode 100644
> index 0000000..cfeb312
> --- /dev/null
> +++ b/arch/csky/Kconfig
> @@ -0,0 +1,211 @@
> +config CSKY
> +	bool
> +	default y

shorter:
	def_bool y

> +	select ARCH_USE_BUILTIN_BSWAP
> +	select COMMON_CLK
> +	select CLKSRC_MMIO
> +	select CLKSRC_OF
> +	select IRQ_DOMAIN
> +	select HANDLE_DOMAIN_IRQ
> +	select DW_APB_TIMER_OF
> +	select GENERIC_ATOMIC64
> +	select GENERIC_CLOCKEVENTS
> +	select GENERIC_CPU_DEVICES
> +	select GENERIC_IRQ_CHIP
> +	select GENERIC_IRQ_PROBE
> +	select GENERIC_IRQ_SHOW
> +	select GENERIC_SCHED_CLOCK
> +	select GENERIC_SMP_IDLE_THREAD
> +	select HAVE_ARCH_TRACEHOOK
> +	select HAVE_GENERIC_DMA_COHERENT
> +	select HAVE_KERNEL_GZIP
> +	select HAVE_KERNEL_LZO
> +	select HAVE_KERNEL_LZMA
> +	select HAVE_PERF_EVENTS
> +	select HAVE_C_RECORDMCOUNT
> +	select HAVE_KPROBES
> +	select HAVE_KRETPROBES
> +	select HAVE_DMA_API_DEBUG
> +	select HAVE_MEMBLOCK
> +	select MAY_HAVE_SPARSE_IRQ
> +	select MODULES_USE_ELF_RELA if MODULES
> +	select NO_BOOTMEM
> +	select OF
> +	select OF_EARLY_FLATTREE
> +	select OF_RESERVED_MEM
> +	select PERF_USE_VMALLOC
> +	select RTC_LIB
> +	select TIMER_OF
> +	select USB_ARCH_HAS_EHCI
> +	select USB_ARCH_HAS_OHCI
> +
> +config CPU_HAS_CACHEV2
> +	bool
> +
> +config CPU_HAS_HILO
> +	bool
> +
> +config CPU_HAS_TLBI
> +	bool
> +
> +config CPU_HAS_LDSTEX
> +	bool
> +	help
> +	  For SMP cpu need "ldex&stex" instrcutions to keep atomic.

	  For SMP, CPU needs           instructions for atomic operations.


> +
> +config CPU_NEED_TLBSYNC
> +	bool
> +
> +config CPU_NEED_SOFTALIGN
> +	bool
> +
> +config CPU_NO_USER_BKPT
> +	bool
> +	help
> +	  For abiv2 we couldn't use "trap 1" as user space bkpt in gdbserver, because
> +	  abiv2 is 16/32bit instruction set and "trap 1" is 32bit.
> +	  So we need a 16bit instruction as user space bkpt, and it will cause a illegal

	                                                                 cause an illegal

> +	  instruction exception.
> +	  In kernel we parse the *regs->pc to determine wether send SIGTRAP or not.

	                                                whether to send

> +
> +config GENERIC_CALIBRATE_DELAY
> +	bool
> +	default y

	def_bool y

> +
> +config HZ
> +	int
> +	default 100
> +
> +config GENERIC_CSUM
> +	bool
> +	default y

	def_bool y

> +
> +config GENERIC_HWEIGHT
> +	bool
> +	default y

	def_bool y

> +
> +config MMU
> +	bool
> +	default y

same.

> +
> +config RWSEM_GENERIC_SPINLOCK
> +	bool
> +	default y

same.

> +
> +config TIME_LOW_RES
> +	bool
> +	default y

again.

> +
> +config TRACE_IRQFLAGS_SUPPORT
> +	bool
> +	default y

again.

> +
> +source "init/Kconfig"
> +
> +source "kernel/Kconfig.freezer"
> +
> +menu "Processor type and features"
> +
> +comment "Processor type"
> +
> +choice
> +	prompt "CPU MODEL"
> +	default CPU_CK610
> +
> +config CPU_CK610
> +	bool "CSKY CPU ck610"
> +	select CPU_NEED_TLBSYNC
> +	select CPU_NEED_SOFTALIGN
> +	select CPU_NO_USER_BKPT
> +
> +config CPU_CK810
> +	bool "CSKY CPU ck810"
> +	select CPU_HAS_HILO
> +	select CPU_NEED_TLBSYNC
> +
> +config CPU_CK807
> +	bool "CSKY CPU ck807"
> +	select CPU_HAS_HILO
> +
> +config CPU_CK860
> +	bool "CSKY CPU ck860"
> +	select CPU_HAS_TLBI
> +	select CPU_HAS_CACHEV2
> +	select CPU_HAS_LDSTEX
> +endchoice
> +
> +config CPU_TLB_SIZE
> +	int
> +	default "128"	if(CPU_CK610 || CPU_CK807 || CPU_CK810)
> +	default "1024"	if(CPU_CK860)
> +
> +config CPU_ASID_BITS
> +	int
> +	default "8"	if(CPU_CK610 || CPU_CK807 || CPU_CK810)
> +	default "12"	if(CPU_CK860)
> +
> +config L1_CACHE_SHIFT
> +	int
> +	default "4"	if(CPU_CK610)
> +	default "5"	if(CPU_CK807 || CPU_CK810)
> +	default "6"	if(CPU_CK860)

prefer a space after "if" on all those lines above.

> +
> +config HIGHMEM
> +	bool "High Memory Support"
> +	depends on !CPU_CK610
> +	default y
> +
> +menuconfig CPU_HAS_FPU
> +	bool "CPU has FPU coprocessor"
> +	depends on CPU_CK807 || CPU_CK810 || CPU_CK860
> +
> +menuconfig CPU_HAS_TEE
> +	bool "CPU has Trusted Execution Environment"
> +	depends on CPU_CK810
> +
> +config SMP
> +	bool "Symmetric Multi-Processing (SMP) support for C-SKY"
> +	depends on CPU_CK860
> +	default n
> +
> +config NR_CPUS
> +	int "Maximum number of CPUs (2-32)"
> +	range 2 32
> +	depends on SMP
> +	default "4"
> +
> +comment "*****System type*****"
> +
> +config RAM_BASE
> +	hex "It must be the same with the memory section in your dts"
> +	default 0x0
> +endmenu
> +
> +menu "Power management options"
> +
> +source "kernel/power/Kconfig"
> +
> +config ARCH_SUSPEND_POSSIBLE
> +	bool
> +	default y

shorter:
	def_bool y

> +endmenu
> +
> +source "mm/Kconfig"
> +
> +source "fs/Kconfig.binfmt"
> +
> +source "kernel/Kconfig.preempt"
> +
> +source "net/Kconfig"
> +
> +source "drivers/Kconfig"
> +
> +source "fs/Kconfig"
> +
> +source "arch/csky/Kconfig.debug"
> +
> +source "security/Kconfig"
> +
> +source "crypto/Kconfig"
> +
> +source "lib/Kconfig"
> diff --git a/arch/csky/Kconfig.debug b/arch/csky/Kconfig.debug
> new file mode 100644
> index 0000000..6978702
> --- /dev/null
> +++ b/arch/csky/Kconfig.debug
> @@ -0,0 +1,29 @@
> +menu "Kernel hacking"
> +
> +menu "C-SKY Debug Options"
> +config CSKY_DEBUG_INFO
> +	bool "Compile the kernel with debug info, just add -g"
> +	depends on !DEBUG_INFO
> +	help
> +	  DEBUG_INFO and COMPILE_TEST is conflict, so we provide
> +	  another way to support -g.
> +	  Some drivers eg: DW_MMC need COMPILE_TEST for new cpu
> +	  arch :(
> +
> +config CSKY_VECIRQ_LEGENCY
> +	bool "Use legency IRQ vector for interrupt, it's for SOC bugfix."

	          legacy

> +	help
> +	  It's a deprecated method for arch/csky. Don't use it, unless your
> +	  SOC has bug.
> +
> +config CSKY_BUILTIN_DTB
> +	bool "Use kernel builtin dtb"
> +
> +config CSKY_BUILTIN_DTB_NAME
> +	string "kernel builtin dtb name"
> +	depends on CSKY_BUILTIN_DTB
> +endmenu
> +
> +source "lib/Kconfig.debug"
> +
> +endmenu


-- 
~Randy

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

* Re: [PATCH V2 01/19] csky: Build infrastructure
  2018-07-01 21:01   ` Randy Dunlap
@ 2018-07-02  1:13     ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-02  1:13 UTC (permalink / raw)
  To: Randy Dunlap
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

Hi Randy,

On Sun, Jul 01, 2018 at 02:01:52PM -0700, Randy Dunlap wrote:
> Hi,
> Just a few comments...
>
Thx for your review. I'll fixup all of you mentioned and self-check
again.

 Guo Ren


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

* Re: [PATCH V2 07/19] csky: MMU and page table management
  2018-07-01 17:30 ` [PATCH V2 07/19] csky: MMU and page table management Guo Ren
@ 2018-07-02 13:29   ` Christoph Hellwig
  2018-07-03  2:53     ` Guo Ren
  0 siblings, 1 reply; 88+ messages in thread
From: Christoph Hellwig @ 2018-07-02 13:29 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

This commit is missing an explanation.

For the dma-mapping code please use the generic kernel/dma/noncoherent.c
code instead of duplicating it.

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

* Re: [PATCH V2 07/19] csky: MMU and page table management
  2018-07-02 13:29   ` Christoph Hellwig
@ 2018-07-03  2:53     ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-03  2:53 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Mon, Jul 02, 2018 at 06:29:15AM -0700, Christoph Hellwig wrote:
> This commit is missing an explanation.
 The patch is for abiv1 & abiv2 CPU series' MMU support.
  - abiv1 CPU (CK610) is VIPT cache and it doesn't support highmem.
  - abiv2 CPUs are all PIPT cache and they could support highmem.
 We seperate abiv1 and abiv2 into two direcotries for coding convention. 

> For the dma-mapping code please use the generic kernel/dma/noncoherent.c
> code instead of duplicating it.
 Thx for the tips and I think you mean the lib/dma-noncoherent.c in the
 lastest kernel source and not in linux-4.16.2.

 I'll rebase on the newest RC version of linux in next version patch and
 reuse the code in lib/dma-noncoherent.c.

 Current csky_dma_alloc implementation is not good, it use 512MB uncached
 area to mirror the Normal cachable-512MB area. In next version patch,
 we will increase the max-Normal memory zone to (1GB + 768MB).
 In csky_dma_alloc we will seperate the atomic_dma and non-atomic_dma
 and reserve the area in fixmap area.

 Here is my memory layout plan in next version patch:
   Fixmap	: 0xffc02000 – 0xfffff000       (4 MB - 12KB) kmap_atomic, dma_atomic ...
   Pkmap	: 0xff800000 – 0xffc00000	(4 MB)        PTR_PER_PTE = 1024
   Vmalloc	: 0xf0200000 – 0xff000000       (238 MB)      max: 238MB + 256MB + 1GB
   Lowmem	: 0x80000000 – 0xf0000000	(1G + 768 MB)

 Guo Ren

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

* Re: [PATCH V2 02/19] csky: defconfig
  2018-07-01 17:30 ` [PATCH V2 02/19] csky: defconfig Guo Ren
@ 2018-07-03  3:16   ` Rob Herring
  2018-07-03  8:31     ` Guo Ren
  0 siblings, 1 reply; 88+ messages in thread
From: Rob Herring @ 2018-07-03  3:16 UTC (permalink / raw)
  To: ren_guo
  Cc: linux-arch, Linux Kernel Mailing List, Thomas Gleixner,
	Daniel Lezcano, Jason Cooper, Arnd Bergmann, c-sky_gcc_upstream,
	gnu-csky, thomas.petazzoni, wbx, Greentime Hu

On Sun, Jul 1, 2018 at 11:34 AM Guo Ren <ren_guo@c-sky.com> wrote:
>

Needs a commit msg. Perhaps some overview of what's in each config.

> Signed-off-by: Guo Ren <ren_guo@c-sky.com>
> ---
>  arch/csky/configs/gx66xx_defconfig     | 549 +++++++++++++++++++++++++++++++++
>  arch/csky/configs/qemu_ck807_defconfig | 541 ++++++++++++++++++++++++++++++++
>  2 files changed, 1090 insertions(+)
>  create mode 100644 arch/csky/configs/gx66xx_defconfig
>  create mode 100644 arch/csky/configs/qemu_ck807_defconfig

Are these configs mutually exclusive? We try to have one kernel build
serve many platforms. So you'd probably want to divide things between
the 2 ABIs.

It looks like you still have lots of options enabled that I wouldn't
expect you to need. Start with something more minimal for what you
need to boot and support upstream.

For a full config, you can use allmodconfig at least to build test.

Rob

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

* Re: [PATCH V2 19/19] irqchip: add C-SKY irqchip drivers
  2018-07-01 17:30 ` [PATCH V2 19/19] irqchip: add C-SKY irqchip drivers Guo Ren
@ 2018-07-03  3:27   ` Rob Herring
  2018-07-03  7:38     ` Guo Ren
  2018-07-03  9:28   ` Thomas Gleixner
  1 sibling, 1 reply; 88+ messages in thread
From: Rob Herring @ 2018-07-03  3:27 UTC (permalink / raw)
  To: ren_guo
  Cc: linux-arch, Linux Kernel Mailing List, Thomas Gleixner,
	Daniel Lezcano, Jason Cooper, Arnd Bergmann, c-sky_gcc_upstream,
	gnu-csky, thomas.petazzoni, wbx, Greentime Hu

On Sun, Jul 1, 2018 at 11:35 AM Guo Ren <ren_guo@c-sky.com> wrote:
>
Commit message needed.

> Signed-off-by: Guo Ren <ren_guo@c-sky.com>
> ---
>  drivers/irqchip/Makefile           |   1 +
>  drivers/irqchip/irq-csky-v1.c      | 126 ++++++++++++++++++++++++
>  drivers/irqchip/irq-csky-v2.c      | 191 +++++++++++++++++++++++++++++++++++++
>  drivers/irqchip/irq-nationalchip.c | 131 +++++++++++++++++++++++++
>  4 files changed, 449 insertions(+)
>  create mode 100644 drivers/irqchip/irq-csky-v1.c
>  create mode 100644 drivers/irqchip/irq-csky-v2.c
>  create mode 100644 drivers/irqchip/irq-nationalchip.c
>
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index d27e3e3..51e7316 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -85,3 +85,4 @@ obj-$(CONFIG_IRQ_UNIPHIER_AIDET)      += irq-uniphier-aidet.o
>  obj-$(CONFIG_ARCH_SYNQUACER)           += irq-sni-exiu.o
>  obj-$(CONFIG_MESON_IRQ_GPIO)           += irq-meson-gpio.o
>  obj-$(CONFIG_GOLDFISH_PIC)             += irq-goldfish-pic.o
> +obj-$(CONFIG_CSKY)                     += irq-csky-v1.o irq-csky-v2.o irq-nationalchip.o
> diff --git a/drivers/irqchip/irq-csky-v1.c b/drivers/irqchip/irq-csky-v1.c
> new file mode 100644
> index 0000000..64ea564
> --- /dev/null
> +++ b/drivers/irqchip/irq-csky-v1.c
> @@ -0,0 +1,126 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/module.h>
> +#include <linux/irqdomain.h>
> +#include <linux/irqchip.h>
> +#include <linux/irq.h>
> +#include <linux/interrupt.h>
> +#include <asm/irq.h>
> +#include <asm/io.h>
> +#include <asm/traps.h>
> +
> +#ifdef CONFIG_CSKY_VECIRQ_LEGENCY

Do you mean "legacy"?

It would be better to make this run-time so you can support multiple
platforms in one build. You should be able to determine this from DT.

> +#include <asm/reg_ops.h>
> +#endif

[...]

> +IRQCHIP_DECLARE(csky_intc_v1, "csky,intc-v1", csky_intc_v1_init);

DT bindings must be documented. And the vendor prefix must also be
registered in vendor-prefixes.txt.

[...]

> +IRQCHIP_DECLARE(csky_intc_v2, "csky,intc-v2", csky_intc_v2_init);

And this one. Use of v1, v2, etc. is generally discouraged unless
there is some strict versioning behind it. Most bindings use
implementation specific compatible strings (which typically means the
SoC name/number as part of it).

[...]

> +IRQCHIP_DECLARE(nationalchip_intc_v1_ave, "nationalchip,intc-v1,ave", intc_init);

Here too. And your timers as well.

You'll also need to do cpu bindings as well especially for SMP.

Rob

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

* Re: [PATCH V2 01/19] csky: Build infrastructure
  2018-07-01 17:30 ` [PATCH V2 01/19] csky: Build infrastructure Guo Ren
  2018-07-01 21:01   ` Randy Dunlap
@ 2018-07-03  3:33   ` Rob Herring
  2018-07-03  9:14     ` Guo Ren
  2018-07-03 16:03   ` Arnd Bergmann
  2 siblings, 1 reply; 88+ messages in thread
From: Rob Herring @ 2018-07-03  3:33 UTC (permalink / raw)
  To: ren_guo
  Cc: linux-arch, Linux Kernel Mailing List, Thomas Gleixner,
	Daniel Lezcano, Jason Cooper, Arnd Bergmann, c-sky_gcc_upstream,
	gnu-csky, thomas.petazzoni, wbx, Greentime Hu

On Sun, Jul 1, 2018 at 11:36 AM Guo Ren <ren_guo@c-sky.com> wrote:
>
> Signed-off-by: Guo Ren <ren_guo@c-sky.com>
> ---

[...]

> +config CSKY_BUILTIN_DTB
> +       bool "Use kernel builtin dtb"
> +
> +config CSKY_BUILTIN_DTB_NAME
> +       string "kernel builtin dtb name"
> +       depends on CSKY_BUILTIN_DTB
> +endmenu

These options generally exist for backwards compatibility with legacy
bootloaders that don't support DT which shouldn't apply here given
this is a new arch. If we need this for other reasons, it should not
be an architecture specific option.

Rob

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

* Re: [PATCH V2 19/19] irqchip: add C-SKY irqchip drivers
  2018-07-03  3:27   ` Rob Herring
@ 2018-07-03  7:38     ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-03  7:38 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-arch, Linux Kernel Mailing List, Thomas Gleixner,
	Daniel Lezcano, Jason Cooper, Arnd Bergmann, c-sky_gcc_upstream,
	gnu-csky, thomas.petazzoni, wbx, Greentime Hu

On Mon, Jul 02, 2018 at 09:27:13PM -0600, Rob Herring wrote:
> Commit message needed.
Ok

> Do you mean "legacy"?
Yes, it's from arch/csky/Kconfig.debug, and I'll correct it in next
version patch.
 
> It would be better to make this run-time so you can support multiple
> platforms in one build. You should be able to determine this from DT.
The CSKY_VECIRQ_LEGACY means when cpu receive the IRQ, it will directly
enter into the exception vector entry indexed by IRQ number. Just some
old SOC need the feature. We reserve it just as we've mentioned in
arch/csky/Kconfig.debug:

config CSKY_VECIRQ_LEGENCY
	bool "Use legency IRQ vector for interrupt, it's for SOC bugfix."
	help
	  It's a deprecated method for arch/csky. Don't use it, unless your
	  SOC has bug.

As we need this config to setup the vector tables in
arch/csky/kernel/traps.c, "determine this from DT" isn't suitable for us.

> > +IRQCHIP_DECLARE(csky_intc_v1, "csky,intc-v1", csky_intc_v1_init);
> 
> DT bindings must be documented. And the vendor prefix must also be
> registered in vendor-prefixes.txt.
Ok, thx for the tips. I'll follow the rules.

> > +IRQCHIP_DECLARE(csky_intc_v2, "csky,intc-v2", csky_intc_v2_init);
> 
> And this one. Use of v1, v2, etc. is generally discouraged unless
> there is some strict versioning behind it. Most bindings use
> implementation specific compatible strings (which typically means the
> SoC name/number as part of it).

> > +IRQCHIP_DECLARE(nationalchip_intc_v1_ave, "nationalchip,intc-v1,ave", intc_init);
> 
> Here too. And your timers as well.
"csky,intc-v1/v2" are used in many SOCs, just like "arm,gic-v2/v3". So may I
change them like these?:
 csky,intc-v1 >>> csky,ck807-intc
                  csky,ck810-intc
                  csky,ck860-intc

 csky,intc-v2 >>> csky,ck860-mpintc

 nationalchip,intc-v1,ave >>> nationalchip,ck610-gx6605s-intc
 
> You'll also need to do cpu bindings as well especially for SMP.
Ok, thx for tips.


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

* Re: [PATCH V2 02/19] csky: defconfig
  2018-07-03  3:16   ` Rob Herring
@ 2018-07-03  8:31     ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-03  8:31 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-arch, Linux Kernel Mailing List, Thomas Gleixner,
	Daniel Lezcano, Jason Cooper, Arnd Bergmann, c-sky_gcc_upstream,
	gnu-csky, thomas.petazzoni, wbx, Greentime Hu

On Mon, Jul 02, 2018 at 09:16:27PM -0600, Rob Herring wrote:
> 
> Are these configs mutually exclusive? We try to have one kernel build
> serve many platforms. So you'd probably want to divide things between
> the 2 ABIs.
Yes, they are mutually exclusive, and may I prepare defconfigs like
these:
 abiv1_defconfig
 abiv2_defconfig (ck807 ck810 ck860 are also mutually exclusive in
 -mcpu=ck807/ck810/ck860, you need "make menuconfig" to select correct CPU,
 so they couldn't be determined from DT. just like ARMv5, ARMv7-A and 
 ARMv7-M)

> It looks like you still have lots of options enabled that I wouldn't
> expect you to need. Start with something more minimal for what you
> need to boot and support upstream.
Ok, I'll clean them up in next version patch.
 
> For a full config, you can use allmodconfig at least to build test.
Thx for the tip.

Guo Ren

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

* Re: [PATCH V2 01/19] csky: Build infrastructure
  2018-07-03  3:33   ` Rob Herring
@ 2018-07-03  9:14     ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-03  9:14 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-arch, Linux Kernel Mailing List, Thomas Gleixner,
	Daniel Lezcano, Jason Cooper, Arnd Bergmann, c-sky_gcc_upstream,
	gnu-csky, thomas.petazzoni, wbx, Greentime Hu

On Mon, Jul 02, 2018 at 09:33:51PM -0600, Rob Herring wrote:
> > +config CSKY_BUILTIN_DTB
> > +       bool "Use kernel builtin dtb"
> > +
> > +config CSKY_BUILTIN_DTB_NAME
> > +       string "kernel builtin dtb name"
> > +       depends on CSKY_BUILTIN_DTB
> > +endmenu
> 
> These options generally exist for backwards compatibility with legacy
> bootloaders that don't support DT which shouldn't apply here given
> this is a new arch. If we need this for other reasons, it should not
> be an architecture specific option.
We want the BUILTIN_DTB for some boards and they don't need change dtb
at all. And I just follow other archs BUILTIN_DTB in their Kconfig. eg:
xtensa, h8300, mips, nds32, sh, openrisc, arc ...

I just keep this in Kconfig.debug and it's not a recommended method.

Guo Ren

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

* Re: [PATCH V2 19/19] irqchip: add C-SKY irqchip drivers
  2018-07-01 17:30 ` [PATCH V2 19/19] irqchip: add C-SKY irqchip drivers Guo Ren
  2018-07-03  3:27   ` Rob Herring
@ 2018-07-03  9:28   ` Thomas Gleixner
  2018-07-04  5:08     ` Guo Ren
  1 sibling, 1 reply; 88+ messages in thread
From: Thomas Gleixner @ 2018-07-03  9:28 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Mon, 2 Jul 2018, Guo Ren wrote:

-EEMPTYCHANGELOG

> Signed-off-by: Guo Ren <ren_guo@c-sky.com>
> +
> +#ifdef CONFIG_CSKY_VECIRQ_LEGENCY

I assume you meant _LEGACY

> +#include <asm/reg_ops.h>
> +#endif

Also why making the include conditional. Just include it always and be done
with it.

> +static void __iomem *reg_base;
> +
> +#define INTC_ICR	0x00
> +#define INTC_ISR	0x00
> +#define INTC_NEN31_00	0x10
> +#define INTC_NEN63_32	0x28
> +#define INTC_IFR31_00	0x08
> +#define INTC_IFR63_32	0x20
> +#define INTC_SOURCE	0x40
> +
> +#define INTC_IRQS	64
> +
> +#define INTC_ICR_AVE	BIT(31)
> +
> +#define VEC_IRQ_BASE	32
> +
> +static struct irq_domain *root_domain;
> +
> +static void __init ck_set_gc(void __iomem *reg_base, u32 irq_base,
> +			     u32 mask_reg)
> +{
> +	struct irq_chip_generic *gc;
> +
> +	gc = irq_get_domain_generic_chip(root_domain, irq_base);
> +	gc->reg_base = reg_base;
> +	gc->chip_types[0].regs.mask = mask_reg;
> +	gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
> +	gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
> +}
> +
> +static struct irq_domain *root_domain;

You have the same declaration 10 lines above already....

> +static void ck_irq_handler(struct pt_regs *regs)
> +{
> +#ifdef CONFIG_CSKY_VECIRQ_LEGENCY
> +	irq_hw_number_t irq = ((mfcr("psr") >> 16) & 0xff) - VEC_IRQ_BASE;
> +#else
> +	irq_hw_number_t irq = readl_relaxed(reg_base + INTC_ISR) & 0x3f;
> +#endif

You can avoid the ifdeffery by doing:

	irq_hw_number_t irq;

	if (IS_ENABLED(CONFIG_CSKY_VECIRQ_LEGENCY))
		irq = ((mfcr("psr") >> 16) & 0xff) - VEC_IRQ_BASE;
	else
		irq = readl_relaxed(reg_base + INTC_ISR) & 0x3f;

which makes the whole thing more readable.

> +	handle_domain_irq(root_domain, irq, regs);
> +}
> +
> +#define expand_byte_to_word(i) (i|(i<<8)|(i<<16)|(i<<24))
> +static inline void setup_irq_channel(void __iomem *reg_base)

Please do not glue a define and a function declaration togetther w/o a new
line in between. That's really hard to parse.

Also please make that expand macro an inline function.

> +{
> +	int i;

Bah: writel_relaxed(u32 value, ...). So why 'int' ? Just because?

> +
> +	/*
> +	 * There are 64 irq nums and irq-channels and one byte per channel.
> +	 * Setup every channel with the same hwirq num.

This is magic and not understandable for an outsider.

> +	 */
> +	for (i = 0; i < INTC_IRQS; i += 4) {
> +		writel_relaxed(expand_byte_to_word(i) + 0x00010203,

No magic numbers please w/o explanation. And '+' is the wrong operator
here, really.  Stick that into the expand function:

static inline u32 build_intc_ctrl(u32 idx)
{
	u32 res;

	/*
	 * Set the same index for each channel (or whatever
	 * this means in reality).
	 */
	res = idx | (idx << 8) | (idx || 16) | (idx << 24);

	/*
	 * Set the channel magic number in descending order because
	 * the most significant bit comes first. (Replace with
	 * something which has not been pulled out of thin air).
	 */
	return res | 0x00010203;
}

Hmm?

> +			       reg_base + INTC_SOURCE + i);
> +	}
> +}
> +
> +static int __init
> +csky_intc_v1_init(struct device_node *node, struct device_node *parent)
> +{
> +	u32 clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
> +	int ret;
> +
> +	if (parent) {
> +		pr_err("C-SKY Intc not a root irq controller\n");
> +		return -EINVAL;
> +	}
> +
> +	reg_base = of_iomap(node, 0);
> +	if (!reg_base) {
> +		pr_err("C-SKY Intc unable to map: %p.\n", node);
> +		return -EINVAL;
> +	}
> +
> +	writel_relaxed(0, reg_base + INTC_NEN31_00);
> +	writel_relaxed(0, reg_base + INTC_NEN63_32);
> +
> +#ifndef CONFIG_CSKY_VECIRQ_LEGENCY
> +	writel_relaxed(INTC_ICR_AVE, reg_base + INTC_ICR);
> +#else
> +	writel_relaxed(0, reg_base + INTC_ICR);
> +#endif

See above.

> +++ b/drivers/irqchip/irq-csky-v2.c
> @@ -0,0 +1,191 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.

Please stick an empty newline here for separation

> +#include <linux/kernel.h>

...

> +static void csky_irq_v2_handler(struct pt_regs *regs)
> +{
> +	static void __iomem	*reg_base;
> +	irq_hw_number_t		hwirq;
> +
> +	reg_base = *this_cpu_ptr(&intcl_reg);

Wheee!

	static void __iomem *reg_base = this_cpu_read(intcl_reg);
	irq_hw_number_t	hwirq;

Hmm?

> +
> +#ifdef CONFIG_SMP
> +static int csky_irq_set_affinity(struct irq_data *d,
> +				 const struct cpumask *mask_val,
> +				 bool force)
> +{
> +	unsigned int cpu;
> +
> +	if (!force)
> +		cpu = cpumask_any_and(mask_val, cpu_online_mask);
> +	else
> +		cpu = cpumask_first(mask_val);
> +
> +	if (cpu >= nr_cpu_ids)
> +		return -EINVAL;
> +
> +	/* Enable interrupt destination */
> +	cpu |= BIT(31);
> +
> +	writel_relaxed(cpu, INTCG_base + INTCG_CIDSTR + (4*(d->hwirq - COMM_IRQ_BASE)));

Spaces between '4' and '*' and '(d->)' please. And to avoid the overly long
line use a local variable to calculate the value.

> +	irq_data_update_effective_affinity(d, cpumask_of(cpu));
> +
> +	return IRQ_SET_MASK_OK_DONE;
> +}
> +#endif
> +
> +static struct irq_chip csky_irq_chip = {
> +	.name           = "C-SKY SMP Intc V2",
> +	.irq_eoi	= csky_irq_v2_eoi,
> +	.irq_enable	= csky_irq_v2_enable,
> +	.irq_disable	= csky_irq_v2_disable,
> +#ifdef CONFIG_SMP
> +	.irq_set_affinity = csky_irq_set_affinity,
> +#endif
> +};
> +
> +static int csky_irqdomain_map(struct irq_domain *d, unsigned int irq,
> +			      irq_hw_number_t hwirq)
> +{
> +	if(hwirq < COMM_IRQ_BASE) {
> +		irq_set_percpu_devid(irq);
> +		irq_set_chip_and_handler(irq, &csky_irq_chip, handle_percpu_irq);
> +	} else
> +		irq_set_chip_and_handler(irq, &csky_irq_chip, handle_fasteoi_irq);

The else path wants curly braces as well. 

> +
> +	return 0;
> +}
> +++ b/drivers/irqchip/irq-nationalchip.c
> @@ -0,0 +1,131 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2018 Hangzhou NationalChip Science & Technology Co.,Ltd.

See above

> +#include <linux/kernel.h>

...

> +static struct irq_domain *root_domain;
> +
> +static void nc_irq_handler(struct pt_regs *regs)
> +{
> +	u32 status, irq;
> +
> +	do {
> +		status = readl_relaxed(reg_base + INTC_NINT31_00);
> +		if (status) {
> +			irq = __ffs(status);
> +		} else {
> +			status = readl_relaxed(reg_base + INTC_NINT63_32);
> +			if (status)
> +				irq = __ffs(status) + 32;
> +			else
> +				return;
> +		}
> +		handle_domain_irq(root_domain, irq, regs);
> +	} while(1);
> +}
> +

> +#define expand_byte_to_word(i) (i|(i<<8)|(i<<16)|(i<<24))
> +static inline void setup_irq_channel(void __iomem *reg_base)
> +{
> +	int i;
> +
> +	/*
> +	 * There are 64 irq nums and irq-channels and one byte per channel.
> +	 * Setup every channel with the same hwirq num.
> +	 */
> +	for (i = 0; i < INTC_IRQS; i += 4) {
> +		writel_relaxed(expand_byte_to_word(i) + 0x03020100,

This magic number is the reverse of the above magic. Is that intentional.

> +			       reg_base + INTC_SOURCE + i);
> +	}

See above. 

> +}
> +
> +static int __init
> +intc_init(struct device_node *node, struct device_node *parent)
> +{
> +	u32 clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
> +	int ret;

Aside of that the whole thing might share the code with the other one, but
it might not be worth it. At least this wants to be documented in the
changelog why sharing the code is not useful...

Thanks,

	tglx

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

* Re: [PATCH V2 18/19] clocksource: add C-SKY clocksource drivers
  2018-07-01 17:34   ` Guo Ren
  (?)
@ 2018-07-03  9:39   ` Thomas Gleixner
  2018-07-04 10:49     ` Guo Ren
  -1 siblings, 1 reply; 88+ messages in thread
From: Thomas Gleixner @ 2018-07-03  9:39 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Mon, 2 Jul 2018, Guo Ren wrote:

-EEMPTYCHANGELOG

> Signed-off-by: Guo Ren <ren_guo@c-sky.com>
> --- /dev/null
> +++ b/drivers/clocksource/timer-csky-v1.c
> @@ -0,0 +1,169 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2018 Hangzhou NationalChip Science & Technology Co.,Ltd.

newline please

> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/sched_clock.h>
> +#include <linux/cpu.h>
> +#include <asm/reg_ops.h>
> +
> +#include "timer-of.h"
> +
> +#define PTIM_CTLR	"cr<0, 14>"
> +#define PTIM_TSR	"cr<1, 14>"
> +#define PTIM_CCVR_HI	"cr<2, 14>"
> +#define PTIM_CCVR_LO	"cr<3, 14>"
> +#define PTIM_LVR	"cr<6, 14>"
> +
> +#define BITS_CSKY_TIMER	56
> +
> +DECLARE_PER_CPU(struct timer_of, csky_to);

static?

> +
> +static int csky_timer_irq;
> +static int csky_timer_rate;
> +
> +static inline u64 get_ccvr(void)
> +{
> +	u32 lo, hi, t;
> +
> +	do {
> +		hi = mfcr(PTIM_CCVR_HI);
> +		lo = mfcr(PTIM_CCVR_LO);
> +		t  = mfcr(PTIM_CCVR_HI);
> +	} while(t != hi);

No idea which frequency this timer ticks at, but if the 32 bit wrap does
not come too fast, then you really should avoid that loop. That function is
called very frequently.

> +	return ((u64)hi << 32) | lo;
> +}
> +

> +DEFINE_PER_CPU(struct timer_of, csky_to) = {

static

> +	.flags = TIMER_OF_CLOCK | TIMER_OF_IRQ,
> +
> +	.clkevt = {
> +		.name = "C-SKY SMP Timer V1",
> +		.rating = 300,
> +		.features = CLOCK_EVT_FEAT_PERCPU | CLOCK_EVT_FEAT_ONESHOT,
> +		.set_state_shutdown		= csky_timer_shutdown,
> +		.set_state_oneshot		= csky_timer_oneshot,
> +		.set_state_oneshot_stopped	= csky_timer_oneshot_stopped,
> +		.set_next_event			= csky_timer_set_next_event,
> +	},
> +
> +	.of_irq = {
> +		.handler = timer_interrupt,
> +		.flags = IRQF_TIMER,
> +		.percpu = 1,

This is inconsistent. You made it half tabular and half not. Please use
tabular style consistently.

> +	},
> +};
> +
> +/*** clock event for percpu ***/

Please refrain from inventing new horrible comment styles.

> +static int csky_timer_starting_cpu(unsigned int cpu)
> +{
> +	struct timer_of *to = this_cpu_ptr(&csky_to);
> +
> +	to->clkevt.cpumask = cpumask_of(smp_processor_id());
> +
> +	clockevents_config_and_register(&to->clkevt, csky_timer_rate, 0, ULONG_MAX);
> +
> +	enable_percpu_irq(csky_timer_irq, 0);
> +
> +	return 0;
> +}
> +
> +static int csky_timer_dying_cpu(unsigned int cpu)
> +{
> +	disable_percpu_irq(csky_timer_irq);
> +
> +	return 0;
> +}
> +
> +/*** clock source ***/
> +static u64 sched_clock_read(void)
> +{
> +	return get_ccvr();
> +}
> +
> +static u64 clksrc_read(struct clocksource *c)
> +{
> +	return get_ccvr();
> +}
> +
> +struct clocksource csky_clocksource = {
> +	.name = "csky_timer_v1_clksrc",
> +	.rating = 400,
> +	.mask = CLOCKSOURCE_MASK(BITS_CSKY_TIMER),
> +	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
> +	.read = clksrc_read,

tabular style please

> +};
> +
> +static void csky_clksrc_init(void)
> +{
> +	clocksource_register_hz(&csky_clocksource, csky_timer_rate);
> +
> +	sched_clock_register(sched_clock_read, BITS_CSKY_TIMER, csky_timer_rate);
> +}
> +
> +static int __init csky_timer_v1_init(struct device_node *np)
> +{
> +	int ret;
> +	struct timer_of *to = this_cpu_ptr(&csky_to);
> +
> +	ret = timer_of_init(np, to);
> +	if (ret)
> +		return ret;
> +
> +	csky_timer_irq = to->of_irq.irq;
> +	csky_timer_rate = timer_of_rate(to);
> +
> +	ret = cpuhp_setup_state(CPUHP_AP_DUMMY_TIMER_STARTING,
> +				"clockevents/csky/timer:starting",
> +				csky_timer_starting_cpu,
> +				csky_timer_dying_cpu);

Oh no. Just picking a random hotplug event is not how it works. Add your
own please and make sure it's at the proper place.

> +++ b/drivers/clocksource/timer-nationalchip.c
> @@ -0,0 +1,165 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2018 Hangzhou NationalChip Science & Technology Co.,Ltd.

...

> +#include <linux/init.h>

> +static irqreturn_t timer_interrupt(int irq, void *dev)
> +{
> +	struct clock_event_device *ce = (struct clock_event_device *) dev;

Pointless type cast.

> +	void __iomem *base = timer_of_base(to_timer_of(ce));
> +
> +	writel_relaxed(STATUS_clr, base + TIMER_STATUS);
> +
> +	ce->event_handler(ce);
> +
> +	return IRQ_HANDLED;
> +}

> +static struct timer_of to = {
> +	.flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
> +
> +	.clkevt = {
> +		.name = TIMER_NAME,
> +		.rating = 300,
> +		.features = CLOCK_EVT_FEAT_DYNIRQ | CLOCK_EVT_FEAT_PERIODIC |
> +			CLOCK_EVT_FEAT_ONESHOT,
> +		.set_state_shutdown	= nc_timer_shutdown,
> +		.set_state_periodic	= nc_timer_set_periodic,
> +		.set_next_event		= nc_timer_set_next_event,
> +		.cpumask = cpu_possible_mask,
> +	},
> +
> +	.of_irq = {
> +		.handler = timer_interrupt,
> +		.flags = IRQF_TIMER | IRQF_IRQPOLL,
> +	},

See above

> +};

Thanks,

	tglx

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

* Re: [PATCH V2 01/19] csky: Build infrastructure
  2018-07-01 17:30 ` [PATCH V2 01/19] csky: Build infrastructure Guo Ren
  2018-07-01 21:01   ` Randy Dunlap
  2018-07-03  3:33   ` Rob Herring
@ 2018-07-03 16:03   ` Arnd Bergmann
  2018-07-04 11:40     ` Guo Ren
  2 siblings, 1 reply; 88+ messages in thread
From: Arnd Bergmann @ 2018-07-03 16:03 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, Linux Kernel Mailing List, Thomas Gleixner,
	Daniel Lezcano, Jason Cooper, c-sky_gcc_upstream, gnu-csky,
	thomas.petazzoni, wbx, Greentime Hu

On Sun, Jul 1, 2018 at 7:30 PM, Guo Ren <ren_guo@c-sky.com> wrote:
> Signed-off-by: Guo Ren <ren_guo@c-sky.com>

> +choice
> +       prompt "CPU MODEL"
> +       default CPU_CK610
> +
> +config CPU_CK610
> +       bool "CSKY CPU ck610"
> +       select CPU_NEED_TLBSYNC
> +       select CPU_NEED_SOFTALIGN
> +       select CPU_NO_USER_BKPT
> +
> +config CPU_CK810
> +       bool "CSKY CPU ck810"
> +       select CPU_HAS_HILO
> +       select CPU_NEED_TLBSYNC
> +
> +config CPU_CK807
> +       bool "CSKY CPU ck807"
> +       select CPU_HAS_HILO
> +
> +config CPU_CK860
> +       bool "CSKY CPU ck860"
> +       select CPU_HAS_TLBI
> +       select CPU_HAS_CACHEV2
> +       select CPU_HAS_LDSTEX
> +endchoice

It looks like the CK8xx CPUs are basically compatible, so it would
be nice to have a way to configure a kernel that can run on all
of them, picking a safe default for options that depend on a
particular CPU. E.g. when only CK860 supports SMP, you might
start out by making SMP "depend on !(CPU_CK807 || CPU_CK810)",
as an alternative to implementing a way for an SMP-enabled kernel
to run on non-SMP CPUs (arm has that, but it's probably too complex
for your needs).

Similarly, you can set L1_CACHE_BYTES to the largest possible
size, and make things like CPU_TLB_SIZE dynamically detected.

> +menu "C-SKY Debug Options"
> +config CSKY_DEBUG_INFO
> +       bool "Compile the kernel with debug info, just add -g"
> +       depends on !DEBUG_INFO
> +       help
> +         DEBUG_INFO and COMPILE_TEST is conflict, so we provide
> +         another way to support -g.
> +         Some drivers eg: DW_MMC need COMPILE_TEST for new cpu
> +         arch :(

Just send a patch to change those dependencies, there is no reason
not to apply those. Generally speaking, the kernel should not contain
workarounds for particular (mis-)features of the kernel, when you can
just change those.

> diff --git a/arch/csky/include/asm/Kbuild b/arch/csky/include/asm/Kbuild
> new file mode 100644
> index 0000000..5de6519
> --- /dev/null
> +++ b/arch/csky/include/asm/Kbuild
> @@ -0,0 +1,72 @@
> +generic-y += asm-offsets.h
> +generic-y += atomic.h

The asm-generic version of atomic.h is a bit inefficient,
you might want to provide an optimized version for your
architecture.

> +generic-y += auxvec.h

You should not need asm/auxvec.h or uapi/asm/auxvec.h

> +generic-y += bitsperlong.h
> +generic-y += bug.h

providing your own bug.h might be helpful too.
Have a look

> +generic-y += bugs.h
> +generic-y += clkdev.h
> +generic-y += cputime.h

asm-generic/cputime.h no loinger exists

> +generic-y += kvm_para.h

Do you support KVM?

> +generic-y += sizes.h

Deprecated and should not be needed

          Arnd

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

* Re: [PATCH V2 05/19] csky: System Call
  2018-07-01 17:30 ` [PATCH V2 05/19] csky: System Call Guo Ren
@ 2018-07-03 19:53   ` Arnd Bergmann
  2018-07-04 11:49     ` Guo Ren
  0 siblings, 1 reply; 88+ messages in thread
From: Arnd Bergmann @ 2018-07-03 19:53 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, Linux Kernel Mailing List, Thomas Gleixner,
	Daniel Lezcano, Jason Cooper, c-sky_gcc_upstream, gnu-csky,
	thomas.petazzoni, wbx, Greentime Hu

On Sun, Jul 1, 2018 at 7:30 PM, Guo Ren <ren_guo@c-sky.com> wrote:
> Signed-off-by: Guo Ren <ren_guo@c-sky.com>

We really need all new architectures to use the generic syscall ABI,
see below for the details.

> diff --git a/arch/csky/include/uapi/asm/unistd.h b/arch/csky/include/uapi/asm/unistd.h
> new file mode 100644
> index 0000000..0ea9b5a
> --- /dev/null
> +++ b/arch/csky/include/uapi/asm/unistd.h
> @@ -0,0 +1,63 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
> +#define __ARCH_WANT_OLD_READDIR
> +#define __ARCH_WANT_RENAMEAT
> +#define __ARCH_WANT_STAT64
> +#define __ARCH_WANT_SYS_ALARM
> +#define __ARCH_WANT_SYS_CLONE
> +#define __ARCH_WANT_SYS_FORK
> +#define __ARCH_WANT_SYS_GETHOSTNAME
> +#define __ARCH_WANT_SYS_GETPGRP
> +#define __ARCH_WANT_SYS_IPC
> +#define __ARCH_WANT_SYS_LLSEEK
> +#define __ARCH_WANT_SYS_NICE
> +#define __ARCH_WANT_SYS_OLD_GETRLIMIT
> +#define __ARCH_WANT_SYS_OLDUMOUNT
> +#define __ARCH_WANT_SYS_PAUSE
> +#define __ARCH_WANT_SYS_SIGNAL
> +#define __ARCH_WANT_SYS_SIGPENDING
> +#define __ARCH_WANT_SYS_SIGPROCMASK
> +#define __ARCH_WANT_SYS_SOCKETCALL
> +#define __ARCH_WANT_SYS_TIME
> +#define __ARCH_WANT_SYS_UTIME
> +#define __ARCH_WANT_SYS_VFORK
> +#define __ARCH_WANT_SYS_WAITPID

I think these all need to be removed, with the exception of
__ARCH_WANT_SYS_CLONE. It would be nice though to change
the imlpementation in the kernel so we no longer need to set that
either.

> +#define __NR_set_thread_area   (__NR_arch_specific_syscall + 0)
> +__SYSCALL(__NR_set_thread_area, sys_set_thread_area)
> +#define __NR_ipc               (__NR_arch_specific_syscall + 1)
> +__SYSCALL(__NR_ipc, sys_ipc)
> +#define __NR_socketcall                (__NR_arch_specific_syscall + 2)
> +__SYSCALL(__NR_socketcall, sys_socketcall)
> +#define __NR_ugetrlimit                (__NR_arch_specific_syscall + 3)
> +__SYSCALL(__NR_ugetrlimit, sys_getrlimit)
> +#define __NR_cacheflush                (__NR_arch_specific_syscall + 4)
> +__SYSCALL(__NR_cacheflush, sys_cacheflush)
> +#define __NR_sysfs             (__NR_arch_specific_syscall + 5)
> +__SYSCALL(__NR_sysfs, sys_sysfs)
> +
> +__SYSCALL(__NR_fadvise64_64, sys_csky_fadvise64_64)

We definitely don't want ipc, socketcall, ugetrlimit, or sysfs.

cacheflush is probbably needed.

For fadvise64_64, please redefine the symbol name so the
table points at the right entry.

I'm not completely sure about set_thread_area, can you explain
what you need that for?

> +#define __NR_setgroups32       __NR_setgroups
> +#define __NR_getgid32          __NR_getgid
> +#define __NR_getgroups32       __NR_getgroups
> +#define __NR_setuid32          __NR_setuid
> +#define __NR_setgid32          __NR_setgid
> +#define __NR_getresgid32       __NR_getresgid
> +#define __NR_setfsuid32                __NR_setfsuid
> +#define __NR_setfsgid32                __NR_setfsgid
> +#define __NR_fchown32          __NR_fchown
> +#define __NR_geteuid32         __NR_geteuid
> +#define __NR_getegid32         __NR_getegid
> +#define __NR_getresuid32       __NR_getresuid
> +#define __NR_setresuid32       __NR_setresuid
> +#define __NR_setresgid32       __NR_setresgid
> +#define __NR_setreuid32                __NR_setreuid
> +#define __NR_setregid32                __NR_setregid
> +#define __NR__llseek           __NR_llseek

These should also get removed.

> +struct mmap_arg_struct {
> +       unsigned long addr;
> +       unsigned long len;
> +       unsigned long prot;
> +       unsigned long flags;
> +       unsigned long fd;
> +       unsigned long offset;
> +};
> +
> +SYSCALL_DEFINE1(mmap,
> +       struct mmap_arg_struct *, arg)
> +{
> +       struct mmap_arg_struct a;
> +
> +       if (copy_from_user(&a, arg, sizeof(a)))
> +               return -EINVAL;
> +
> +       if (unlikely(a.offset & ~PAGE_MASK))
> +               return -EINVAL;
> +
> +       return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
> +}

This can be removed since there is mmap2()

       Arnd

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

* Re: [PATCH V2 13/19] csky: Library functions
  2018-07-01 17:30 ` [PATCH V2 13/19] csky: Library functions Guo Ren
@ 2018-07-03 20:04   ` Arnd Bergmann
  2018-07-04 10:51     ` Guo Ren
  0 siblings, 1 reply; 88+ messages in thread
From: Arnd Bergmann @ 2018-07-03 20:04 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, Linux Kernel Mailing List, Thomas Gleixner,
	Daniel Lezcano, Jason Cooper, c-sky_gcc_upstream, gnu-csky,
	thomas.petazzoni, wbx, Greentime Hu

On Sun, Jul 1, 2018 at 7:30 PM, Guo Ren <ren_guo@c-sky.com> wrote:
>
> diff --git a/arch/csky/kernel/cskyksyms.c b/arch/csky/kernel/cskyksyms.c
> new file mode 100644
> index 0000000..3f13594
> --- /dev/null
> +++ b/arch/csky/kernel/cskyksyms.c
> @@ -0,0 +1,31 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
> +#include <linux/module.h>
> +#include <linux/uaccess.h>
> +#include <asm/cacheflush.h>
> +
> +/*
> + * Defined in libgcc
> + *
> + * See arch/csky/Makefile:
> + *     -print-libgcc-file-name
> + */
> +extern void __ashldi3 (void);
> +extern void __ashrdi3 (void);
> +extern void __lshrdi3 (void);
> +extern void __muldi3 (void);
> +extern void __ucmpdi2 (void);
> +EXPORT_SYMBOL(__ashldi3);
> +EXPORT_SYMBOL(__ashrdi3);
> +EXPORT_SYMBOL(__lshrdi3);
> +EXPORT_SYMBOL(__muldi3);
> +EXPORT_SYMBOL(__ucmpdi2);

It's better to avoid relying on libgcc here. Please use the
CONFIG_GENERIC_LIB_ASHLDI3/ASHRDI3/LSHRDI3/etc
helpers that we already have in the kernel.

       Arnd

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

* Re: [PATCH V2 19/19] irqchip: add C-SKY irqchip drivers
  2018-07-03  9:28   ` Thomas Gleixner
@ 2018-07-04  5:08     ` Guo Ren
  2018-07-04  6:43       ` Thomas Gleixner
  0 siblings, 1 reply; 88+ messages in thread
From: Guo Ren @ 2018-07-04  5:08 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-arch, linux-kernel, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Tue, Jul 03, 2018 at 11:28:03AM +0200, Thomas Gleixner wrote:
> -EEMPTYCHANGELOG
Ok, I'll seperate this patchset's changelog from cover-letter in next
version patch.

> > +#ifdef CONFIG_CSKY_VECIRQ_LEGENCY
> 
> I assume you meant _LEGACY
Yes.

> > +#include <asm/reg_ops.h>
> > +#endif
> 
> Also why making the include conditional. Just include it always and be done
> with it.
Ok.

> > +static void __iomem *reg_base;
> > +
> > +#define INTC_ICR	0x00
> > +#define INTC_ISR	0x00
> > +#define INTC_NEN31_00	0x10
> > +#define INTC_NEN63_32	0x28
> > +#define INTC_IFR31_00	0x08
> > +#define INTC_IFR63_32	0x20
> > +#define INTC_SOURCE	0x40
> > +
> > +#define INTC_IRQS	64
> > +
> > +#define INTC_ICR_AVE	BIT(31)
> > +
> > +#define VEC_IRQ_BASE	32
> > +
> > +static struct irq_domain *root_domain;
> > +
> > +static void __init ck_set_gc(void __iomem *reg_base, u32 irq_base,
> > +			     u32 mask_reg)
> > +{
> > +	struct irq_chip_generic *gc;
> > +
> > +	gc = irq_get_domain_generic_chip(root_domain, irq_base);
> > +	gc->reg_base = reg_base;
> > +	gc->chip_types[0].regs.mask = mask_reg;
> > +	gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
> > +	gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
> > +}
> > +
> > +static struct irq_domain *root_domain;
> 
> You have the same declaration 10 lines above already....
Opps, thx. I'll remove.

> > +static void ck_irq_handler(struct pt_regs *regs)
> > +{
> > +#ifdef CONFIG_CSKY_VECIRQ_LEGENCY
> > +	irq_hw_number_t irq = ((mfcr("psr") >> 16) & 0xff) - VEC_IRQ_BASE;
> > +#else
> > +	irq_hw_number_t irq = readl_relaxed(reg_base + INTC_ISR) & 0x3f;
> > +#endif
> 
> You can avoid the ifdeffery by doing:
> 
> 	irq_hw_number_t irq;
> 
> 	if (IS_ENABLED(CONFIG_CSKY_VECIRQ_LEGENCY))
> 		irq = ((mfcr("psr") >> 16) & 0xff) - VEC_IRQ_BASE;
> 	else
> 		irq = readl_relaxed(reg_base + INTC_ISR) & 0x3f;
> 
> which makes the whole thing more readable.
Ok, good idea.

> > +#define expand_byte_to_word(i) (i|(i<<8)|(i<<16)|(i<<24))
> > +static inline void setup_irq_channel(void __iomem *reg_base)
> 
> Please do not glue a define and a function declaration togetther w/o a new
> line in between. That's really hard to parse.
> 
> Also please make that expand macro an inline function.
> 
> > +{
> > +	int i;
> 
> Bah: writel_relaxed(u32 value, ...). So why 'int' ? Just because?
> 
> > +
> > +	/*
> > +	 * There are 64 irq nums and irq-channels and one byte per channel.
> > +	 * Setup every channel with the same hwirq num.
> 
> This is magic and not understandable for an outsider.
> 
> > +	 */
> > +	for (i = 0; i < INTC_IRQS; i += 4) {
> > +		writel_relaxed(expand_byte_to_word(i) + 0x00010203,
> 
> No magic numbers please w/o explanation. And '+' is the wrong operator
> here, really.  Stick that into the expand function:
> 
> static inline u32 build_intc_ctrl(u32 idx)
> {
> 	u32 res;
> 
> 	/*
> 	 * Set the same index for each channel (or whatever
> 	 * this means in reality).
> 	 */
> 	res = idx | (idx << 8) | (idx || 16) | (idx << 24);
> 
> 	/*
> 	 * Set the channel magic number in descending order because
> 	 * the most significant bit comes first. (Replace with
> 	 * something which has not been pulled out of thin air).
> 	 */
> 	return res | 0x00010203;
> }
> 
> Hmm?
That's Ok. And here is my implementation:

static inline u32 build_intc_ctrl(u32 idx)
{
	/*
	 * One channel is one byte in a word-width register, so
	 * there are four channels in a word-width register.
	 *
	 * Set the same index for each channel and it will make
	 * "irq num = channel num".
	 */
	return (idx             | ((idx + 1) << 8) |
	      ((idx + 2) << 16) | ((idx + 3) << 24));
}
Hmm? (No magic number)

> > +#ifndef CONFIG_CSKY_VECIRQ_LEGENCY
> > +	writel_relaxed(INTC_ICR_AVE, reg_base + INTC_ICR);
> > +#else
> > +	writel_relaxed(0, reg_base + INTC_ICR);
> > +#endif
> 
> See above.
Ok, use if (IS_ENABLED(CONFIG_CSKY_VECIRQ_LEGENCY))

> > +++ b/drivers/irqchip/irq-csky-v2.c
> > @@ -0,0 +1,191 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
> 
> Please stick an empty newline here for separation
Ok

> > +	static void __iomem	*reg_base;
> > +	irq_hw_number_t		hwirq;
> > +
> > +	reg_base = *this_cpu_ptr(&intcl_reg);
> 
> Wheee!
> 
> 	static void __iomem *reg_base = this_cpu_read(intcl_reg);
> 	irq_hw_number_t	hwirq;
> 
> Hmm?
Thx for the tips and I'll use this_cpu_read() without static.
 	void __iomem *reg_base = this_cpu_read(intcl_reg);

> > +	writel_relaxed(cpu, INTCG_base + INTCG_CIDSTR + (4*(d->hwirq - COMM_IRQ_BASE)));
> 
> Spaces between '4' and '*' and '(d->)' please. And to avoid the overly long
> line use a local variable to calculate the value.
Ok.

> > +	} else
> > +		irq_set_chip_and_handler(irq, &csky_irq_chip, handle_fasteoi_irq);
> 
> The else path wants curly braces as well.
Ok.

> > +// SPDX-License-Identifier: GPL-2.0
> > +// Copyright (C) 2018 Hangzhou NationalChip Science & Technology Co.,Ltd.
> 
> See above
Ok, stick an empty newline

> > +		writel_relaxed(expand_byte_to_word(i) + 0x03020100,
> 
> This magic number is the reverse of the above magic. Is that intentional.
> 
> > +			       reg_base + INTC_SOURCE + i);
> > +	}
> 
> See above. 
No magic number and use inline func.


> > +static int __init
> > +intc_init(struct device_node *node, struct device_node *parent)
> > +{
> > +	u32 clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
> > +	int ret;
> 
> Aside of that the whole thing might share the code with the other one, but
> it might not be worth it. At least this wants to be documented in the
> changelog why sharing the code is not useful...
Do you mean merge irq-csky-v1.c irq-csky-v2.c irq-nationalchip.c into
one file eg: irq-csky.c? 

Guo Ren

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

* Re: [PATCH V2 19/19] irqchip: add C-SKY irqchip drivers
  2018-07-04  5:08     ` Guo Ren
@ 2018-07-04  6:43       ` Thomas Gleixner
  2018-07-04 11:58         ` Guo Ren
  0 siblings, 1 reply; 88+ messages in thread
From: Thomas Gleixner @ 2018-07-04  6:43 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Wed, 4 Jul 2018, Guo Ren wrote:
> On Tue, Jul 03, 2018 at 11:28:03AM +0200, Thomas Gleixner wrote:
> That's Ok. And here is my implementation:
> 
> static inline u32 build_intc_ctrl(u32 idx)
> {
> 	/*
> 	 * One channel is one byte in a word-width register, so
> 	 * there are four channels in a word-width register.
> 	 *
> 	 * Set the same index for each channel and it will make
> 	 * "irq num = channel num".
> 	 */
> 	return (idx             | ((idx + 1) << 8) |
> 	      ((idx + 2) << 16) | ((idx + 3) << 24));
> }
> Hmm? (No magic number)

Ok :)

> > > +	static void __iomem	*reg_base;
> > > +	irq_hw_number_t		hwirq;
> > > +
> > > +	reg_base = *this_cpu_ptr(&intcl_reg);
> > 
> > Wheee!
> > 
> > 	static void __iomem *reg_base = this_cpu_read(intcl_reg);
> > 	irq_hw_number_t	hwirq;
> > 
> > Hmm?
> Thx for the tips and I'll use this_cpu_read() without static.
>  	void __iomem *reg_base = this_cpu_read(intcl_reg);

Yeah, I surely missed to drop the static ...

> > 
> > Aside of that the whole thing might share the code with the other one, but
> > it might not be worth it. At least this wants to be documented in the
> > changelog why sharing the code is not useful...
>
> Do you mean merge irq-csky-v1.c irq-csky-v2.c irq-nationalchip.c into
> one file eg: irq-csky.c? 

Yes, but only if there is enough code to share without creating an ifdef
mess. But that looks doable

Thanks,

	tglx

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

* Re: [PATCH V2 18/19] clocksource: add C-SKY clocksource drivers
  2018-07-03  9:39   ` Thomas Gleixner
@ 2018-07-04 10:49     ` Guo Ren
  2018-07-04 14:35       ` Thomas Gleixner
  0 siblings, 1 reply; 88+ messages in thread
From: Guo Ren @ 2018-07-04 10:49 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-arch, linux-kernel, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Tue, Jul 03, 2018 at 11:39:05AM +0200, Thomas Gleixner wrote:
> -EEMPTYCHANGELOG
Ok

> > +// SPDX-License-Identifier: GPL-2.0
> > +// Copyright (C) 2018 Hangzhou NationalChip Science & Technology Co.,Ltd.
> 
> newline please
Ok

> > +#define BITS_CSKY_TIMER	56
> > +
> > +DECLARE_PER_CPU(struct timer_of, csky_to);
> 
> static?
Ok.

> 
> > +
> > +static int csky_timer_irq;
> > +static int csky_timer_rate;
> > +
> > +static inline u64 get_ccvr(void)
> > +{
> > +	u32 lo, hi, t;
> > +
> > +	do {
> > +		hi = mfcr(PTIM_CCVR_HI);
> > +		lo = mfcr(PTIM_CCVR_LO);
> > +		t  = mfcr(PTIM_CCVR_HI);
> > +	} while(t != hi);
> 
> No idea which frequency this timer ticks at, but if the 32 bit wrap does
> not come too fast, then you really should avoid that loop. That function is
> called very frequently.

0000006c <clksrc_read>:
		hi = mfcr(PTIM_CCVR_HI);
  6c:	c1c26023 	mfcr      	r3, cr<2, 14>
		lo = mfcr(PTIM_CCVR_LO);
  70:	c1c36021 	mfcr      	r1, cr<3, 14>
		t  = mfcr(PTIM_CCVR_HI);
  74:	c1c26022 	mfcr      	r2, cr<2, 14>
	} while(t != hi);
  78:	648e      	cmpne      	r3, r2
  7a:	0bf9      	bt      	0x6c	// 6c <clksrc_read>

When two read cr<2, 14> is not equal, we'll retry. So only when
CCVR_LO is at 0xffffffff between the two read of CCVR_HI. That's very
very small probability event for "bt 0x6c".

Don't worry about the "do {...} whie(t != hi)", it's no performance issue.

> > +DEFINE_PER_CPU(struct timer_of, csky_to) = {
> 
> static
Ok.

> > +	.flags = TIMER_OF_CLOCK | TIMER_OF_IRQ,
> > +
> > +	.clkevt = {
> > +		.name = "C-SKY SMP Timer V1",
> > +		.rating = 300,
> > +		.features = CLOCK_EVT_FEAT_PERCPU | CLOCK_EVT_FEAT_ONESHOT,
> > +		.set_state_shutdown		= csky_timer_shutdown,
> > +		.set_state_oneshot		= csky_timer_oneshot,
> > +		.set_state_oneshot_stopped	= csky_timer_oneshot_stopped,
> > +		.set_next_event			= csky_timer_set_next_event,
> > +	},
> > +
> > +	.of_irq = {
> > +		.handler = timer_interrupt,
> > +		.flags = IRQF_TIMER,
> > +		.percpu = 1,
> 
> This is inconsistent. You made it half tabular and half not. Please use
> tabular style consistently.
Ok.
	.clkevt = {
		.name				= "C-SKY SMP Timer V1",
		.features			= CLOCK_EVT_FEAT_PERCPU |
						  CLOCK_EVT_FEAT_ONESHOT,
		.rating				= 300,
		.set_state_shutdown		= csky_timer_shutdown,
		.set_state_oneshot		= csky_timer_oneshot,
		.set_state_oneshot_stopped	= csky_timer_oneshot_stopped,
		.set_next_event			= csky_timer_set_next_event,
	},

	.of_irq = {
		.handler			= timer_interrupt,
		.flags				= IRQF_TIMER,
		.percpu				= 1,

> > +/*** clock event for percpu ***/
> 
> Please refrain from inventing new horrible comment styles.
Ok.
/* clock event for percpu */

> > +struct clocksource csky_clocksource = {
> > +	.name = "csky_timer_v1_clksrc",
> > +	.rating = 400,
> > +	.mask = CLOCKSOURCE_MASK(BITS_CSKY_TIMER),
> > +	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
> > +	.read = clksrc_read,
> 
> tabular style please
Ok.

> > +	ret = cpuhp_setup_state(CPUHP_AP_DUMMY_TIMER_STARTING,
> > +				"clockevents/csky/timer:starting",
> > +				csky_timer_starting_cpu,
> > +				csky_timer_dying_cpu);
> 
> Oh no. Just picking a random hotplug event is not how it works. Add your
> own please and make sure it's at the proper place.
like this?
include/linux/cpuhotplug.h:
	CPUHP_AP_KVM_ARM_TIMER_STARTING,
+	CPUHP_AP_CSKY_TIMER_STARTING,
	/* Must be the last timer callback */
	CPUHP_AP_DUMMY_TIMER_STARTING,

> > +	struct clock_event_device *ce = (struct clock_event_device *) dev;
> 
> Pointless type cast.
Ok.
struct clock_event_device *ce = dev;

> > +		.flags = IRQF_TIMER | IRQF_IRQPOLL,
> > +	},
> 
> See above
Ok, tabular

Guo Ren

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

* Re: [PATCH V2 13/19] csky: Library functions
  2018-07-03 20:04   ` Arnd Bergmann
@ 2018-07-04 10:51     ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-04 10:51 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arch, Linux Kernel Mailing List, Thomas Gleixner,
	Daniel Lezcano, Jason Cooper, c-sky_gcc_upstream, gnu-csky,
	thomas.petazzoni, wbx, Greentime Hu

On Tue, Jul 03, 2018 at 10:04:57PM +0200, Arnd Bergmann wrote:
> It's better to avoid relying on libgcc here. Please use the
> CONFIG_GENERIC_LIB_ASHLDI3/ASHRDI3/LSHRDI3/etc
> helpers that we already have in the kernel.
Ok, I'll try

Guo Ren

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

* Re: [PATCH V2 01/19] csky: Build infrastructure
  2018-07-03 16:03   ` Arnd Bergmann
@ 2018-07-04 11:40     ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-04 11:40 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arch, Linux Kernel Mailing List, Thomas Gleixner,
	Daniel Lezcano, Jason Cooper, c-sky_gcc_upstream, gnu-csky,
	thomas.petazzoni, wbx, Greentime Hu

On Tue, Jul 03, 2018 at 06:03:04PM +0200, Arnd Bergmann wrote:
> It looks like the CK8xx CPUs are basically compatible, so it would
> be nice to have a way to configure a kernel that can run on all
> of them, picking a safe default for options that depend on a
> particular CPU. E.g. when only CK860 supports SMP, you might
> start out by making SMP "depend on !(CPU_CK807 || CPU_CK810)",
> as an alternative to implementing a way for an SMP-enabled kernel
> to run on non-SMP CPUs (arm has that, but it's probably too complex
> for your needs).
> 
> Similarly, you can set L1_CACHE_BYTES to the largest possible
> size, and make things like CPU_TLB_SIZE dynamically detected.
We talked about this topic in the last patchsets. Ck807/810/860 are mutually
incompatible in kernel level but both can run user space programs in
ck807/810.

On Wed, Mar 28, 2018 at 09:40:49AM +0200, Arnd Bergmann wrote:
> Ok, thanks for the clarification. Obviously if they are mutually incompatible,
> there is no point in using a common kernel, so your current version is
> absolutely fine, and this is similar to how we cannot have a common kernel
> between ARMv5, ARMv7-A and ARMv7-M, which are all incompatible
> at the kernel level.
Yes.

> One more question for my understanding: Are the three types of ck8xx
> CPUs mutually incompatible in user space as well, or are the differences
> only for the kernel? For the ARM example, ARMv5 and ARMv7
> fundamentally require separate kernels, but both can run user space
> programs built for ARMv5.

 -mcpu=ck807 app could run on ck807, ck810, ck860.
 -mcpu=ck810 app could run on ck807, ck810, ck860.
 -mcpu=ck860 app only  run on ck860.

They are all incompatible at the kernel level.

 
> > +menu "C-SKY Debug Options"
> > +config CSKY_DEBUG_INFO
> > +       bool "Compile the kernel with debug info, just add -g"
> > +       depends on !DEBUG_INFO
> > +       help
> > +         DEBUG_INFO and COMPILE_TEST is conflict, so we provide
> > +         another way to support -g.
> > +         Some drivers eg: DW_MMC need COMPILE_TEST for new cpu
> > +         arch :(
> 
> Just send a patch to change those dependencies, there is no reason
> not to apply those. Generally speaking, the kernel should not contain
> workarounds for particular (mis-)features of the kernel, when you can
> just change those.
Ok.

> > +generic-y += atomic.h
> 
> The asm-generic version of atomic.h is a bit inefficient,
> you might want to provide an optimized version for your
> architecture.
Ok.

> > +generic-y += auxvec.h
> 
> You should not need asm/auxvec.h or uapi/asm/auxvec.h
Ok.

> > +generic-y += bug.h
> 
> providing your own bug.h might be helpful too.
> Have a look
Ok.

> > +generic-y += cputime.h
> 
> asm-generic/cputime.h no loinger exists
Ok, remove it.

> > +generic-y += kvm_para.h
> 
> Do you support KVM?
No, remove it, thx.
 
> > +generic-y += sizes.h
> 
> Deprecated and should not be needed
Ok, remove it.

 Guo Ren

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

* Re: [PATCH V2 05/19] csky: System Call
  2018-07-03 19:53   ` Arnd Bergmann
@ 2018-07-04 11:49     ` Guo Ren
  2018-07-04 21:04       ` Arnd Bergmann
  0 siblings, 1 reply; 88+ messages in thread
From: Guo Ren @ 2018-07-04 11:49 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arch, Linux Kernel Mailing List, Thomas Gleixner,
	Daniel Lezcano, Jason Cooper, c-sky_gcc_upstream, gnu-csky,
	thomas.petazzoni, wbx, Greentime Hu

On Tue, Jul 03, 2018 at 09:53:48PM +0200, Arnd Bergmann wrote:
> We really need all new architectures to use the generic syscall ABI,
> see below for the details.
Ok, follow the rules.

> > +#define __ARCH_WANT_OLD_READDIR
> > +#define __ARCH_WANT_RENAMEAT
> > +#define __ARCH_WANT_STAT64
> > +#define __ARCH_WANT_SYS_ALARM
> > +#define __ARCH_WANT_SYS_CLONE
> > +#define __ARCH_WANT_SYS_FORK
> > +#define __ARCH_WANT_SYS_GETHOSTNAME
> > +#define __ARCH_WANT_SYS_GETPGRP
> > +#define __ARCH_WANT_SYS_IPC
> > +#define __ARCH_WANT_SYS_LLSEEK
> > +#define __ARCH_WANT_SYS_NICE
> > +#define __ARCH_WANT_SYS_OLD_GETRLIMIT
> > +#define __ARCH_WANT_SYS_OLDUMOUNT
> > +#define __ARCH_WANT_SYS_PAUSE
> > +#define __ARCH_WANT_SYS_SIGNAL
> > +#define __ARCH_WANT_SYS_SIGPENDING
> > +#define __ARCH_WANT_SYS_SIGPROCMASK
> > +#define __ARCH_WANT_SYS_SOCKETCALL
> > +#define __ARCH_WANT_SYS_TIME
> > +#define __ARCH_WANT_SYS_UTIME
> > +#define __ARCH_WANT_SYS_VFORK
> > +#define __ARCH_WANT_SYS_WAITPID
> 
> I think these all need to be removed, with the exception of
> __ARCH_WANT_SYS_CLONE. It would be nice though to change
> the imlpementation in the kernel so we no longer need to set that
> either.
Ok.

 
> > +#define __NR_set_thread_area   (__NR_arch_specific_syscall + 0)
> > +__SYSCALL(__NR_set_thread_area, sys_set_thread_area)
> > +#define __NR_ipc               (__NR_arch_specific_syscall + 1)
> > +__SYSCALL(__NR_ipc, sys_ipc)
> > +#define __NR_socketcall                (__NR_arch_specific_syscall + 2)
> > +__SYSCALL(__NR_socketcall, sys_socketcall)
> > +#define __NR_ugetrlimit                (__NR_arch_specific_syscall + 3)
> > +__SYSCALL(__NR_ugetrlimit, sys_getrlimit)
> > +#define __NR_cacheflush                (__NR_arch_specific_syscall + 4)
> > +__SYSCALL(__NR_cacheflush, sys_cacheflush)
> > +#define __NR_sysfs             (__NR_arch_specific_syscall + 5)
> > +__SYSCALL(__NR_sysfs, sys_sysfs)
> > +
> > +__SYSCALL(__NR_fadvise64_64, sys_csky_fadvise64_64)
> 
> We definitely don't want ipc, socketcall, ugetrlimit, or sysfs.
Ok, remove them.
 
> For fadvise64_64, please redefine the symbol name so the
> table points at the right entry.
We need exchange the args for abiv1. loff_t is 64bit and abiv1 need
8-bytes align in args.
/*
 * for abiv1 the 64bits args should be even th, So we need mov the advice forward.
 */
SYSCALL_DEFINE4(csky_fadvise64_64,
	int, fd,
	int, advice,
	loff_t, offset,
	loff_t, len)
{
	return sys_fadvise64_64(fd, offset, len, advice);
}

> 
> I'm not completely sure about set_thread_area, can you explain
> what you need that for?
In abiv1 there is no tls register, so we use "trap 3" for csky_get_tls
defined in arch/csky/kernel/entry.S to get tls.

Also we use set_thread_area to set tls in kernel.

For abiv2 it has r31 for tls-reg, but we still keep the mechanism.

> > +#define __NR_setgroups32       __NR_setgroups
> > +#define __NR_getgid32          __NR_getgid
> > +#define __NR_getgroups32       __NR_getgroups
> > +#define __NR_setuid32          __NR_setuid
> > +#define __NR_setgid32          __NR_setgid
> > +#define __NR_getresgid32       __NR_getresgid
> > +#define __NR_setfsuid32                __NR_setfsuid
> > +#define __NR_setfsgid32                __NR_setfsgid
> > +#define __NR_fchown32          __NR_fchown
> > +#define __NR_geteuid32         __NR_geteuid
> > +#define __NR_getegid32         __NR_getegid
> > +#define __NR_getresuid32       __NR_getresuid
> > +#define __NR_setresuid32       __NR_setresuid
> > +#define __NR_setresgid32       __NR_setresgid
> > +#define __NR_setreuid32                __NR_setreuid
> > +#define __NR_setregid32                __NR_setregid
> > +#define __NR__llseek           __NR_llseek
> 
> These should also get removed.
Ok.

> > +struct mmap_arg_struct {
> > +       unsigned long addr;
> > +       unsigned long len;
> > +       unsigned long prot;
> > +       unsigned long flags;
> > +       unsigned long fd;
> > +       unsigned long offset;
> > +};
> > +
> > +SYSCALL_DEFINE1(mmap,
> > +       struct mmap_arg_struct *, arg)
> > +{
> > +       struct mmap_arg_struct a;
> > +
> > +       if (copy_from_user(&a, arg, sizeof(a)))
> > +               return -EINVAL;
> > +
> > +       if (unlikely(a.offset & ~PAGE_MASK))
> > +               return -EINVAL;
> > +
> > +       return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
> > +}
> 
> This can be removed since there is mmap2()
Ok.

 Guo Ren

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

* Re: [PATCH V2 19/19] irqchip: add C-SKY irqchip drivers
  2018-07-04  6:43       ` Thomas Gleixner
@ 2018-07-04 11:58         ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-04 11:58 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-arch, linux-kernel, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Wed, Jul 04, 2018 at 08:43:29AM +0200, Thomas Gleixner wrote:
> > Do you mean merge irq-csky-v1.c irq-csky-v2.c irq-nationalchip.c into
> > one file eg: irq-csky.c? 
> 
> Yes, but only if there is enough code to share without creating an ifdef
> mess. But that looks doable
Ok, I'll try.

 Guo Ren

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

* Re: [PATCH V2 18/19] clocksource: add C-SKY clocksource drivers
  2018-07-04 10:49     ` Guo Ren
@ 2018-07-04 14:35       ` Thomas Gleixner
  2018-07-05  5:03         ` Guo Ren
  0 siblings, 1 reply; 88+ messages in thread
From: Thomas Gleixner @ 2018-07-04 14:35 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Wed, 4 Jul 2018, Guo Ren wrote:
> On Tue, Jul 03, 2018 at 11:39:05AM +0200, Thomas Gleixner wrote:
> > > +static inline u64 get_ccvr(void)
> > > +{
> > > +	u32 lo, hi, t;
> > > +
> > > +	do {
> > > +		hi = mfcr(PTIM_CCVR_HI);
> > > +		lo = mfcr(PTIM_CCVR_LO);
> > > +		t  = mfcr(PTIM_CCVR_HI);
> > > +	} while(t != hi);
> > 
> > No idea which frequency this timer ticks at, but if the 32 bit wrap does
> > not come too fast, then you really should avoid that loop. That function is
> > called very frequently.
> 
> 0000006c <clksrc_read>:
> 		hi = mfcr(PTIM_CCVR_HI);
>   6c:	c1c26023 	mfcr      	r3, cr<2, 14>
> 		lo = mfcr(PTIM_CCVR_LO);
>   70:	c1c36021 	mfcr      	r1, cr<3, 14>
> 		t  = mfcr(PTIM_CCVR_HI);
>   74:	c1c26022 	mfcr      	r2, cr<2, 14>
> 	} while(t != hi);
>   78:	648e      	cmpne      	r3, r2
>   7a:	0bf9      	bt      	0x6c	// 6c <clksrc_read>
> 
> When two read cr<2, 14> is not equal, we'll retry. So only when
> CCVR_LO is at 0xffffffff between the two read of CCVR_HI. That's very
> very small probability event for "bt 0x6c".
> 
> Don't worry about the "do {...} whie(t != hi)", it's no performance issue.

But _three_ mfcr plus a conditional jump which _cannot_ be predicted are a
performance issue. When you can replace that with a single mfcr, then you
win a lot, really. The time keeping and the sched clock code can handle
that nicely unless you really have fast wrap arounds on the LO word.

Thanks,

	tglx



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

* Re: [PATCH V2 18/19] clocksource: add C-SKY clocksource drivers
  2018-07-01 17:34   ` Guo Ren
  (?)
  (?)
@ 2018-07-04 17:05   ` Daniel Lezcano
  2018-07-05  3:30     ` Guo Ren
  -1 siblings, 1 reply; 88+ messages in thread
From: Daniel Lezcano @ 2018-07-04 17:05 UTC (permalink / raw)
  To: Guo Ren, linux-arch, linux-kernel, tglx, jason, arnd
  Cc: c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu


Hi Guo,

as you are introducing a new drivers, add a detailed changelog
describing in details the timers.

On 01/07/2018 19:34, Guo Ren wrote:
> Signed-off-by: Guo Ren <ren_guo@c-sky.com>
> ---
>  drivers/clocksource/Makefile             |   1 +
>  drivers/clocksource/timer-csky-v1.c      | 169 +++++++++++++++++++++++++++++++
>  drivers/clocksource/timer-nationalchip.c | 165 ++++++++++++++++++++++++++++++
>  3 files changed, 335 insertions(+)
>  create mode 100644 drivers/clocksource/timer-csky-v1.c
>  create mode 100644 drivers/clocksource/timer-nationalchip.c

Provide two separates patches, one for each timer.

> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
> index d6dec44..bbc567b 100644
> --- a/drivers/clocksource/Makefile
> +++ b/drivers/clocksource/Makefile
> @@ -76,3 +76,4 @@ obj-$(CONFIG_H8300_TMR16)		+= h8300_timer16.o
>  obj-$(CONFIG_H8300_TPU)			+= h8300_tpu.o
>  obj-$(CONFIG_CLKSRC_ST_LPC)		+= clksrc_st_lpc.o
>  obj-$(CONFIG_X86_NUMACHIP)		+= numachip.o
> +obj-$(CONFIG_CSKY)			+= timer-csky-v1.o timer-nationalchip.o

Split this in two.

CONFIG_TIMER_CSKY += timer-csky.o

Note, no v1.

CONFIG_TIMER_NATCHIP += timer-natchip.o


And in the Kconfig add the silent timer option.

config TIMER_CSKY
 bool

config TIMER_NATCHIP
 bool

(If you want to keep the nationalchip name, I'm fine with that).

> diff --git a/drivers/clocksource/timer-csky-v1.c b/drivers/clocksource/timer-csky-v1.c
> new file mode 100644
> index 0000000..f3a822a
> --- /dev/null
> +++ b/drivers/clocksource/timer-csky-v1.c
> @@ -0,0 +1,169 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2018 Hangzhou NationalChip Science & Technology Co.,Ltd.
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/sched_clock.h>
> +#include <linux/cpu.h>
> +#include <asm/reg_ops.h>
> +
> +#include "timer-of.h"
> +
> +#define PTIM_CTLR	"cr<0, 14>"
> +#define PTIM_TSR	"cr<1, 14>"
> +#define PTIM_CCVR_HI	"cr<2, 14>"
> +#define PTIM_CCVR_LO	"cr<3, 14>"
> +#define PTIM_LVR	"cr<6, 14>"
> +
> +#define BITS_CSKY_TIMER	56
> +
> +DECLARE_PER_CPU(struct timer_of, csky_to);
> +
> +static int csky_timer_irq;
> +static int csky_timer_rate;

You can get the value from the timer-of in all the places it is needed.

> +static inline u64 get_ccvr(void)
> +{
> +	u32 lo, hi, t;
> +
> +	do {
> +		hi = mfcr(PTIM_CCVR_HI);
> +		lo = mfcr(PTIM_CCVR_LO);
> +		t  = mfcr(PTIM_CCVR_HI);
> +	} while(t != hi);
> +
> +	return ((u64)hi << 32) | lo;
> +}
> +
> +static irqreturn_t timer_interrupt(int irq, void *dev)
> +{
> +	struct timer_of *to = this_cpu_ptr(&csky_to);
> +
> +	mtcr(PTIM_TSR, 0);
> +
> +	to->clkevt.event_handler(&to->clkevt);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int csky_timer_set_next_event(unsigned long delta, struct clock_event_device *ce)
> +{
> +	mtcr(PTIM_LVR, delta);
> +
> +	return 0;
> +}
> +
> +static int csky_timer_shutdown(struct clock_event_device *ce)
> +{
> +	mtcr(PTIM_CTLR, 0);
> +
> +	return 0;
> +}
> +
> +static int csky_timer_oneshot(struct clock_event_device *ce)
> +{
> +	mtcr(PTIM_CTLR, 1);
> +
> +	return 0;
> +}
> +
> +static int csky_timer_oneshot_stopped(struct clock_event_device *ce)
> +{
> +	mtcr(PTIM_CTLR, 0);
> +
> +	return 0;
> +}
> +
> +DEFINE_PER_CPU(struct timer_of, csky_to) = {
> +	.flags = TIMER_OF_CLOCK | TIMER_OF_IRQ,
> +
> +	.clkevt = {
> +		.name = "C-SKY SMP Timer V1",

If the node name is nice enough, you can discard this. See below
TIMER_OF_DECLARE comment.

> +		.rating = 300,
> +		.features = CLOCK_EVT_FEAT_PERCPU | CLOCK_EVT_FEAT_ONESHOT,
> +		.set_state_shutdown		= csky_timer_shutdown,
> +		.set_state_oneshot		= csky_timer_oneshot,
> +		.set_state_oneshot_stopped	= csky_timer_oneshot_stopped,
> +		.set_next_event			= csky_timer_set_next_event,
> +	},
> +
> +	.of_irq = {
> +		.handler = timer_interrupt,
> +		.flags = IRQF_TIMER> +		.percpu = 1,> +	},
> +};
> +
> +/*** clock event for percpu ***/
> +static int csky_timer_starting_cpu(unsigned int cpu)
> +{
> +	struct timer_of *to = this_cpu_ptr(&csky_to);

per_cpu_ptr(&csky_to, cpu);

> +	to->clkevt.cpumask = cpumask_of(smp_processor_id());

cpumask_of(cpu);  ?

> +
> +	clockevents_config_and_register(&to->clkevt, csky_timer_rate, 0, ULONG_MAX);

I suggest to choose something different than zero for the min_delta.

> +	enable_percpu_irq(csky_timer_irq, 0);
> +
> +	return 0;
> +}
> +
> +static int csky_timer_dying_cpu(unsigned int cpu)
> +{
> +	disable_percpu_irq(csky_timer_irq);
> +
> +	return 0;
> +}
> +
> +/*** clock source ***/
> +static u64 sched_clock_read(void)
> +{
> +	return get_ccvr();
> +}
> +
> +static u64 clksrc_read(struct clocksource *c)
> +{
> +	return get_ccvr();
> +}
> +
> +struct clocksource csky_clocksource = {
> +	.name = "csky_timer_v1_clksrc",

"csky"

> +	.rating = 400,
> +	.mask = CLOCKSOURCE_MASK(BITS_CSKY_TIMER),
> +	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
> +	.read = clksrc_read,
> +};
> +
> +static void csky_clksrc_init(void)
> +{
> +	clocksource_register_hz(&csky_clocksource, csky_timer_rate);
> +
> +	sched_clock_register(sched_clock_read, BITS_CSKY_TIMER, csky_timer_rate);
> +}
> +
> +static int __init csky_timer_v1_init(struct device_node *np)
> +{
> +	int ret;
> +	struct timer_of *to = this_cpu_ptr(&csky_to);
> +
> +	ret = timer_of_init(np, to);
> +	if (ret)
> +		return ret;
> +
> +	csky_timer_irq = to->of_irq.irq;
> +	csky_timer_rate = timer_of_rate(to);
> +
> +	ret = cpuhp_setup_state(CPUHP_AP_DUMMY_TIMER_STARTING,
> +				"clockevents/csky/timer:starting",
> +				csky_timer_starting_cpu,
> +				csky_timer_dying_cpu);
> +	if (ret) {
> +		pr_err("%s: Failed to cpuhp_setup_state.\n", __func__);
> +		return ret;
> +	}
> +
> +	csky_clksrc_init();

inline the function here. It is not worth to add a function for a couple
of lines which is called one time.

> +
> +	return ret;

return 0;

> +}
> +TIMER_OF_DECLARE(csky_timer_v1, "csky,timer-v1", csky_timer_v1_init);

Stick to the hardware name.

eg.

TIMER_OF_DECLARE(csky_610, "csky,ck610-timer", csky_timer_init);
TIMER_OF_DECLARE(csky_807, "csky,ck807-timer", csky_timer_init);

(Beside /proc/interrupts will show the node name which states clearly
what timer it is).

...

v1, v2, etc ... has no sense here.

> +
> diff --git a/drivers/clocksource/timer-nationalchip.c b/drivers/clocksource/timer-nationalchip.c
> new file mode 100644
> index 0000000..8f4e1e5
> --- /dev/null
> +++ b/drivers/clocksource/timer-nationalchip.c
> @@ -0,0 +1,165 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2018 Hangzhou NationalChip Science & Technology Co.,Ltd.
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/sched_clock.h>
> +
> +#include "timer-of.h"
> +
> +#define TIMER_NAME	"nc_timer"
> +#define TIMER_FREQ	1000000
> +#define CLKSRC_OFFSET	0x40
> +
> +#define TIMER_STATUS	0x00
> +#define TIMER_VALUE	0x04
> +#define TIMER_CONTRL	0x10
> +#define TIMER_CONFIG	0x20
> +#define TIMER_DIV	0x24
> +#define TIMER_INI	0x28
> +
> +#define STATUS_clr	BIT(0)
> +
> +#define CONTRL_rst	BIT(0)
> +#define CONTRL_start	BIT(1)
> +
> +#define CONFIG_en	BIT(0)
> +#define CONFIG_irq_en	BIT(1)

Prefix the macros with a shortened timer name and don't mix lower case
and uppercase.

NC_ is too short, something like NATCHIP may be better.

> +
> +static irqreturn_t timer_interrupt(int irq, void *dev)

Fix the function name.

> +{
> +	struct clock_event_device *ce = (struct clock_event_device *) dev;
> +	void __iomem *base = timer_of_base(to_timer_of(ce));
> +
> +	writel_relaxed(STATUS_clr, base + TIMER_STATUS);
> +
> +	ce->event_handler(ce);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int nc_timer_set_periodic(struct clock_event_device *ce)
> +{
> +	void __iomem *base = timer_of_base(to_timer_of(ce));
> +
> +	/* reset */
> +	writel_relaxed(CONTRL_rst, base + TIMER_CONTRL);
> +
> +	/* config the timeout value */
> +	writel_relaxed(ULONG_MAX - timer_of_period(to_timer_of(ce)),
> +		       base + TIMER_INI);
> +
> +	/* enable with irq and start */
> +	writel_relaxed(CONFIG_en|CONFIG_irq_en, base + TIMER_CONFIG);
> +	writel_relaxed(CONTRL_start, base + TIMER_CONTRL);
> +
> +	return 0;
> +}
> +
> +static int nc_timer_set_next_event(unsigned long delta, struct clock_event_device *ce)
> +{
> +	void __iomem *base = timer_of_base(to_timer_of(ce));
> +
> +	/* use reset to pause timer */
> +	writel_relaxed(CONTRL_rst, base + TIMER_CONTRL);
> +
> +	/* config next timeout value */
> +	writel_relaxed(ULONG_MAX - delta, base + TIMER_INI);
> +	writel_relaxed(CONTRL_start, base + TIMER_CONTRL);
> +
> +	return 0;
> +}
> +
> +static int nc_timer_shutdown(struct clock_event_device *ce)
> +{
> +	void __iomem *base = timer_of_base(to_timer_of(ce));
> +
> +	writel_relaxed(0, base + TIMER_CONTRL);
> +	writel_relaxed(0, base + TIMER_CONFIG);
> +
> +	return 0;
> +}
> +
> +static struct timer_of to = {
> +	.flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
> +
> +	.clkevt = {
> +		.name = TIMER_NAME,

Let the node name.

> +		.rating = 300,
> +		.features = CLOCK_EVT_FEAT_DYNIRQ | CLOCK_EVT_FEAT_PERIODIC |
> +			CLOCK_EVT_FEAT_ONESHOT,
> +		.set_state_shutdown	= nc_timer_shutdown,
> +		.set_state_periodic	= nc_timer_set_periodic,
> +		.set_next_event		= nc_timer_set_next_event,

set_oneshot ?

> +		.cpumask = cpu_possible_mask,
> +	},
> +
> +	.of_irq = {
> +		.handler = timer_interrupt,
> +		.flags = IRQF_TIMER | IRQF_IRQPOLL,
> +	},
> +};
> +
> +static u64 notrace nc_sched_clock_read(void)
> +{
> +	void __iomem *base;
> +
> +	base = timer_of_base(&to) + CLKSRC_OFFSET; 
> +
> +	return (u64) readl_relaxed(base + TIMER_VALUE);
> +}
> +
> +static void nc_timer_set_div(void __iomem *base)
> +{
> +	unsigned int div;
> +
> +	div = timer_of_rate(&to)/TIMER_FREQ - 1;

space ' / '

Is it
  (timer_of_rate(&to) / TIMER_FREQ) - 1
or
  timer_of_rate(&to) / (TIMER_FREQ - 1)

?

> +
> +	writel_relaxed(div, base + TIMER_DIV);
> +}
> +
> +static void nc_clkevt_init(void __iomem *base)
> +{
> +	/* reset */
> +	writel_relaxed(CONTRL_rst, base + TIMER_CONTRL);
> +
> +	/* reset config */
> +	writel_relaxed(0, base + TIMER_CONFIG);
> +
> +	nc_timer_set_div(base);
> +
> +	clockevents_config_and_register(&to.clkevt, TIMER_FREQ, 1, ULONG_MAX);
> +}
> +
> +static void nc_clksrc_init(void __iomem *base)
> +{
> +	writel_relaxed(CONTRL_rst, base + TIMER_CONTRL);
> +
> +	writel_relaxed(CONFIG_en, base + TIMER_CONFIG);
> +
> +	nc_timer_set_div(base);
> +
> +	writel_relaxed(0, base + TIMER_INI);
> +	writel_relaxed(CONTRL_start, base + TIMER_CONTRL);
> +
> +	clocksource_mmio_init(base + TIMER_VALUE, "nationalchip", TIMER_FREQ, 200, 32,
> +			      clocksource_mmio_readl_up);

return code check ?

> +	sched_clock_register(nc_sched_clock_read, 32, TIMER_FREQ);
> +}
> +
> +static int __init nc_timer_init(struct device_node *np)
> +{
> +	int ret;
> +
> +	ret = timer_of_init(np, &to);
> +	if (ret)
> +		return ret;
> +
> +	nc_clkevt_init(timer_of_base(&to));
> +
> +	nc_clksrc_init(timer_of_base(&to) + CLKSRC_OFFSET);
> +
> +	return 0;
> +}
> +TIMER_OF_DECLARE(nc_timer, "nationalchip,timer-v1", nc_timer_init);

same comment than cksy timer.


-- 
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


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

* Re: [PATCH V2 05/19] csky: System Call
  2018-07-04 11:49     ` Guo Ren
@ 2018-07-04 21:04       ` Arnd Bergmann
  2018-07-05  5:38         ` Guo Ren
  0 siblings, 1 reply; 88+ messages in thread
From: Arnd Bergmann @ 2018-07-04 21:04 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, Linux Kernel Mailing List, Thomas Gleixner,
	Daniel Lezcano, Jason Cooper, c-sky_gcc_upstream, gnu-csky,
	thomas.petazzoni, wbx, Greentime Hu

On Wed, Jul 4, 2018 at 1:49 PM, Guo Ren <ren_guo@c-sky.com> wrote:

>
>> > +#define __NR_set_thread_area   (__NR_arch_specific_syscall + 0)
>> > +__SYSCALL(__NR_set_thread_area, sys_set_thread_area)
>> > +#define __NR_ipc               (__NR_arch_specific_syscall + 1)
>> > +__SYSCALL(__NR_ipc, sys_ipc)
>> > +#define __NR_socketcall                (__NR_arch_specific_syscall + 2)
>> > +__SYSCALL(__NR_socketcall, sys_socketcall)
>> > +#define __NR_ugetrlimit                (__NR_arch_specific_syscall + 3)
>> > +__SYSCALL(__NR_ugetrlimit, sys_getrlimit)
>> > +#define __NR_cacheflush                (__NR_arch_specific_syscall + 4)
>> > +__SYSCALL(__NR_cacheflush, sys_cacheflush)
>> > +#define __NR_sysfs             (__NR_arch_specific_syscall + 5)
>> > +__SYSCALL(__NR_sysfs, sys_sysfs)
>> > +
>> > +__SYSCALL(__NR_fadvise64_64, sys_csky_fadvise64_64)
>>
>> We definitely don't want ipc, socketcall, ugetrlimit, or sysfs.
> Ok, remove them.
>
>> For fadvise64_64, please redefine the symbol name so the
>> table points at the right entry.
> We need exchange the args for abiv1. loff_t is 64bit and abiv1 need
> 8-bytes align in args.
> /*
>  * for abiv1 the 64bits args should be even th, So we need mov the advice forward.
>  */
> SYSCALL_DEFINE4(csky_fadvise64_64,
>         int, fd,
>         int, advice,
>         loff_t, offset,
>         loff_t, len)
> {
>         return sys_fadvise64_64(fd, offset, len, advice);
> }

Right, I do understand what it's used for, my point was that you
don't really need a separate system call number for it, just redirect
the entry point using the same trick that nds32 has in
arch/nds32/kernel/syscall_table.c:

#define sys_fadvise64_64 csky_fadvise64_64

>> I'm not completely sure about set_thread_area, can you explain
>> what you need that for?
> In abiv1 there is no tls register, so we use "trap 3" for csky_get_tls
> defined in arch/csky/kernel/entry.S to get tls.
>
> Also we use set_thread_area to set tls in kernel.
>
> For abiv2 it has r31 for tls-reg, but we still keep the mechanism.

ok.

            Arnd

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

* Re: [PATCH V2 18/19] clocksource: add C-SKY clocksource drivers
  2018-07-04 17:05   ` Daniel Lezcano
@ 2018-07-05  3:30     ` Guo Ren
  2018-07-05  9:23       ` Daniel Lezcano
  0 siblings, 1 reply; 88+ messages in thread
From: Guo Ren @ 2018-07-05  3:30 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: linux-arch, linux-kernel, tglx, jason, arnd, c-sky_gcc_upstream,
	gnu-csky, thomas.petazzoni, wbx, green.hu

On Wed, Jul 04, 2018 at 07:05:05PM +0200, Daniel Lezcano wrote:
> >  create mode 100644 drivers/clocksource/timer-csky-v1.c
> >  create mode 100644 drivers/clocksource/timer-nationalchip.c
> 
> Provide two separates patches, one for each timer.
Ok.

> > +obj-$(CONFIG_CSKY)			+= timer-csky-v1.o timer-nationalchip.o
> 
> Split this in two.
> 
> CONFIG_TIMER_CSKY += timer-csky.o
> 
> Note, no v1.
> 
> CONFIG_TIMER_NATCHIP += timer-natchip.o
> 
> 
> And in the Kconfig add the silent timer option.
> 
> config TIMER_CSKY
>  bool
> 
> config TIMER_NATCHIP
>  bool
> 
> (If you want to keep the nationalchip name, I'm fine with that).
Ok, NATCHIP & timer-natchip :)

> > +static int csky_timer_irq;
> > +static int csky_timer_rate;
> 
> You can get the value from the timer-of in all the places it is needed.
Ok, I could remove them.

But in csky_timer_v1_init: ret = timer_of_init(np, to)
We only init 1th cpu's timer_of struct, and others just static inited by:

DEFINE_PER_CPU(struct timer_of, csky_to) = {
	.flags = TIMER_OF_CLOCK | TIMER_OF_IRQ,

	.clkevt = {
		.name = "C-SKY SMP Timer V1",
		.rating = 300,
		.features = CLOCK_EVT_FEAT_PERCPU | CLOCK_EVT_FEAT_ONESHOT,
		.set_state_shutdown		= csky_timer_shutdown,
		.set_state_oneshot		= csky_timer_oneshot,
		.set_state_oneshot_stopped	= csky_timer_oneshot_stopped,
		.set_next_event			= csky_timer_set_next_event,
	},

	.of_irq = {
		.handler = timer_interrupt,
		.flags = IRQF_TIMER,
		.percpu = 1,
	},
};

So I still need "for_each_cpu(cpu, cpu_possible_mask)" to init every
csky_to ...

> > +
> > +	.clkevt = {
> > +		.name = "C-SKY SMP Timer V1",
> 
> If the node name is nice enough, you can discard this. See below
> TIMER_OF_DECLARE comment.
Ok, remove it :)


> > +static int csky_timer_starting_cpu(unsigned int cpu)
> > +{
> > +	struct timer_of *to = this_cpu_ptr(&csky_to);
> 
> per_cpu_ptr(&csky_to, cpu);
Ok, thx for the tip.
 
> > +	to->clkevt.cpumask = cpumask_of(smp_processor_id());
> 
> cpumask_of(cpu);  ?
Yes.

> > +	clockevents_config_and_register(&to->clkevt, csky_timer_rate, 0, ULONG_MAX);
> 
> I suggest to choose something different than zero for the min_delta.
Agree, I'll use 1 :)
clockevents_config_and_register(&to->clkevt, csky_timer_rate, 1, ULONG_MAX);

> > +struct clocksource csky_clocksource = {
> > +	.name = "csky_timer_v1_clksrc",
> 
> "csky"
struct clocksource csky_clocksource = {
	.name = "csky,mptimer",
Hmm?

> > +	csky_clksrc_init();
> 
> inline the function here. It is not worth to add a function for a couple
> of lines which is called one time.
Ok

> > +TIMER_OF_DECLARE(csky_timer_v1, "csky,timer-v1", csky_timer_v1_init);
> 
> Stick to the hardware name.
> 
> eg.
> 
> TIMER_OF_DECLARE(csky_610, "csky,ck610-timer", csky_timer_init);
> TIMER_OF_DECLARE(csky_807, "csky,ck807-timer", csky_timer_init);
> 
> (Beside /proc/interrupts will show the node name which states clearly
> what timer it is).
> 
> ...
> 
> v1, v2, etc ... has no sense here.
TIMER_OF_DECLARE(csky_610, "nationachip,ck610-timer", natchip_timer_init);
TIMER_OF_DECLARE(csky_807, "csky,ck807-timer", csky_timer_init);
TIMER_OF_DECLARE(csky_810, "csky,ck810-timer", csky_timer_init);
TIMER_OF_DECLARE(csky_860, "csky,ck860-timer", csky_timer_init);
TIMER_OF_DECLARE(csky_860mp, "csky,ck860-mptimer", csky_mptimer_init);

Hmm?

> > +#define STATUS_clr	BIT(0)
> > +
> > +#define CONTRL_rst	BIT(0)
> > +#define CONTRL_start	BIT(1)
> > +
> > +#define CONFIG_en	BIT(0)
> > +#define CONFIG_irq_en	BIT(1)
> 
> Prefix the macros with a shortened timer name and don't mix lower case
> and uppercase.
Ok.

#define STATUS_CLR	BIT(0)

#define CONTRL_RST	BIT(0)
#define CONTRL_START	BIT(1)

#define CONFIG_EN	BIT(0)
#define CONFIG_IRQ_EN	BIT(1)

> NC_ is too short, something like NATCHIP may be better.
Ok, good name.

> > +static irqreturn_t timer_interrupt(int irq, void *dev)
> 
> Fix the function name.
static irqreturn_t natchip_timer_interrupt(int irq, void *dev)
Hmm?

> > +static struct timer_of to = {
> > +	.flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
> > +
> > +	.clkevt = {
> > +		.name = TIMER_NAME,
> 
> Let the node name.
Ok, remove it.
 
> > +		.rating = 300,
> > +		.features = CLOCK_EVT_FEAT_DYNIRQ | CLOCK_EVT_FEAT_PERIODIC |
> > +			CLOCK_EVT_FEAT_ONESHOT,
> > +		.set_state_shutdown	= nc_timer_shutdown,
> > +		.set_state_periodic	= nc_timer_set_periodic,
> > +		.set_next_event		= nc_timer_set_next_event,
> 
> set_oneshot ?
Yes oneshort, but also could support periodic. But in fact, it only
works with oneshort.

> > +		.cpumask = cpu_possible_mask,
> > +	},
> > +
> > +	.of_irq = {
> > +		.handler = timer_interrupt,
> > +		.flags = IRQF_TIMER | IRQF_IRQPOLL,
> > +	},
> > +};
> > +
> > +static u64 notrace nc_sched_clock_read(void)
> > +{
> > +	void __iomem *base;
> > +
> > +	base = timer_of_base(&to) + CLKSRC_OFFSET; 
> > +
> > +	return (u64) readl_relaxed(base + TIMER_VALUE);
> > +}
> > +
> > +static void nc_timer_set_div(void __iomem *base)
> > +{
> > +	unsigned int div;
> > +
> > +	div = timer_of_rate(&to)/TIMER_FREQ - 1;
> 
> space ' / '
> 
> Is it
>   (timer_of_rate(&to) / TIMER_FREQ) - 1
> or
>   timer_of_rate(&to) / (TIMER_FREQ - 1)
> 
> ?
Thx, I'll modify it like this:
div = (timer_of_rate(&to) / TIMER_FREQ) - 1;

> > +	clocksource_mmio_init(base + TIMER_VALUE, "nationalchip", TIMER_FREQ, 200, 32,
> > +			      clocksource_mmio_readl_up);
> 
> return code check ?
Ok, add return code check.

> > +TIMER_OF_DECLARE(nc_timer, "nationalchip,timer-v1", nc_timer_init);
> 
> same comment than cksy timer.
Ok.

 Guo Ren

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

* Re: [PATCH V2 18/19] clocksource: add C-SKY clocksource drivers
  2018-07-04 14:35       ` Thomas Gleixner
@ 2018-07-05  5:03         ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-05  5:03 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-arch, linux-kernel, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Wed, Jul 04, 2018 at 04:35:43PM +0200, Thomas Gleixner wrote:
> On Wed, 4 Jul 2018, Guo Ren wrote:
> > On Tue, Jul 03, 2018 at 11:39:05AM +0200, Thomas Gleixner wrote:
> > > > +static inline u64 get_ccvr(void)
> > > > +{
> > > > +	u32 lo, hi, t;
> > > > +
> > > > +	do {
> > > > +		hi = mfcr(PTIM_CCVR_HI);
> > > > +		lo = mfcr(PTIM_CCVR_LO);
> > > > +		t  = mfcr(PTIM_CCVR_HI);
> > > > +	} while(t != hi);
> > > 
> > > No idea which frequency this timer ticks at, but if the 32 bit wrap does
> > > not come too fast, then you really should avoid that loop. That function is
> > > called very frequently.
> > 
> > 0000006c <clksrc_read>:
> > 		hi = mfcr(PTIM_CCVR_HI);
> >   6c:	c1c26023 	mfcr      	r3, cr<2, 14>
> > 		lo = mfcr(PTIM_CCVR_LO);
> >   70:	c1c36021 	mfcr      	r1, cr<3, 14>
> > 		t  = mfcr(PTIM_CCVR_HI);
> >   74:	c1c26022 	mfcr      	r2, cr<2, 14>
> > 	} while(t != hi);
> >   78:	648e      	cmpne      	r3, r2
> >   7a:	0bf9      	bt      	0x6c	// 6c <clksrc_read>
> > 
> > When two read cr<2, 14> is not equal, we'll retry. So only when
> > CCVR_LO is at 0xffffffff between the two read of CCVR_HI. That's very
> > very small probability event for "bt 0x6c".
> > 
> > Don't worry about the "do {...} whie(t != hi)", it's no performance issue.
> 
> But _three_ mfcr plus a conditional jump which _cannot_ be predicted are a
> performance issue. When you can replace that with a single mfcr, then you
> win a lot, really. The time keeping and the sched clock code can handle
> that nicely unless you really have fast wrap arounds on the LO word.
Timer's frequency is about 50Mhz-100Mhz and LO word wrap arounds timer is
about 42s ~ 84s.

Our Branch prediction buffer will let the CPU speculative execute
continually. So the "bt" won't be the performance issue.

And I could modify it like this:

static inline u64 get_ccvr(void)
{
	u32 lo, hi, t;

	t  = mfcr(PTIM_CCVR_LO);
	hi = mfcr(PTIM_CCVR_HI);
	lo = mfcr(PTIM_CCVR_LO);

	if (lo < t) hi++;

	return ((u64)hi << 32) | lo;
}

	t  = mfcr(PTIM_CCVR_LO);
  50:	c1c36023 	mfcr      	r3, cr<3, 14>
	hi = mfcr(PTIM_CCVR_HI);
  54:	c1c26021 	mfcr      	r1, cr<2, 14>
	lo = mfcr(PTIM_CCVR_LO);
  58:	c1c3602c 	mfcr      	r12, cr<3, 14>
	if (lo < t) hi++;
  5c:	64f0      	cmphs      	r12, r3
  5e:	c4210c21 	incf      	r1, r1, 1
	return ((u64)hi << 32) | lo;
  62:	3200      	movi      	r2, 0
 
Hmm? (No jump at all)

 Guo Ren

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

* Re: [PATCH V2 05/19] csky: System Call
  2018-07-04 21:04       ` Arnd Bergmann
@ 2018-07-05  5:38         ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-05  5:38 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arch, Linux Kernel Mailing List, Thomas Gleixner,
	Daniel Lezcano, Jason Cooper, c-sky_gcc_upstream, gnu-csky,
	thomas.petazzoni, wbx, Greentime Hu

On Wed, Jul 04, 2018 at 11:04:37PM +0200, Arnd Bergmann wrote:
> Right, I do understand what it's used for, my point was that you
> don't really need a separate system call number for it, just redirect
> the entry point using the same trick that nds32 has in
> arch/nds32/kernel/syscall_table.c:
> 
> #define sys_fadvise64_64 csky_fadvise64_64
Thx for the tip :)

 Guo Ren

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

* Re: [PATCH V2 18/19] clocksource: add C-SKY clocksource drivers
  2018-07-05  3:30     ` Guo Ren
@ 2018-07-05  9:23       ` Daniel Lezcano
  2018-07-06  5:57         ` Guo Ren
  0 siblings, 1 reply; 88+ messages in thread
From: Daniel Lezcano @ 2018-07-05  9:23 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, tglx, jason, arnd, c-sky_gcc_upstream,
	gnu-csky, thomas.petazzoni, wbx, green.hu

On 05/07/2018 05:30, Guo Ren wrote:

[ ... ]

>>
>> You can get the value from the timer-of in all the places it is needed.
> Ok, I could remove them.
> 
> But in csky_timer_v1_init: ret = timer_of_init(np, to)
> We only init 1th cpu's timer_of struct, and others just static inited by:
> 
> DEFINE_PER_CPU(struct timer_of, csky_to) = {
> 	.flags = TIMER_OF_CLOCK | TIMER_OF_IRQ,
> 
> 	.clkevt = {
> 		.name = "C-SKY SMP Timer V1",
> 		.rating = 300,
> 		.features = CLOCK_EVT_FEAT_PERCPU | CLOCK_EVT_FEAT_ONESHOT,
> 		.set_state_shutdown		= csky_timer_shutdown,
> 		.set_state_oneshot		= csky_timer_oneshot,
> 		.set_state_oneshot_stopped	= csky_timer_oneshot_stopped,
> 		.set_next_event			= csky_timer_set_next_event,
> 	},
> 
> 	.of_irq = {
> 		.handler = timer_interrupt,
> 		.flags = IRQF_TIMER,
> 		.percpu = 1,
> 	},
> };
> 
> So I still need "for_each_cpu(cpu, cpu_possible_mask)" to init every
> csky_to ...

That is what is unclear for me. percpu or IRQF_PERCPU ?

Have a look at the commit 9995f4f184613fb02ee73092b03545520a72b104,
changelog and the comment in the init function.

Can you give a similar description for this timer ?

[ ... ]


>>> +struct clocksource csky_clocksource = {
>>> +	.name = "csky_timer_v1_clksrc",
>>
>> "csky"
> struct clocksource csky_clocksource = {
> 	.name = "csky,mptimer",
> Hmm?

Yes

[ ... ]

>> v1, v2, etc ... has no sense here.
> TIMER_OF_DECLARE(csky_610, "nationachip,ck610-timer", natchip_timer_init);
> TIMER_OF_DECLARE(csky_807, "csky,ck807-timer", csky_timer_init);
> TIMER_OF_DECLARE(csky_810, "csky,ck810-timer", csky_timer_init);
> TIMER_OF_DECLARE(csky_860, "csky,ck860-timer", csky_timer_init);
> TIMER_OF_DECLARE(csky_860mp, "csky,ck860-mptimer", csky_mptimer_init);
> 
> Hmm?

Yep, fine.

>>> +#define STATUS_clr	BIT(0)
>>> +
>>> +#define CONTRL_rst	BIT(0)
>>> +#define CONTRL_start	BIT(1)
>>> +
>>> +#define CONFIG_en	BIT(0)
>>> +#define CONFIG_irq_en	BIT(1)
>>
>> Prefix the macros with a shortened timer name and don't mix lower case
>> and uppercase.
> Ok.
> 
> #define STATUS_CLR	BIT(0)
> 
> #define CONTRL_RST	BIT(0)
> #define CONTRL_START	BIT(1)
> 
> #define CONFIG_EN	BIT(0)
> #define CONFIG_IRQ_EN	BIT(1)

NATCHIP_STATUS_CLR
NATCHIP_CONTROL_RST
NATCHIP_CONTROL_START

NATCHIP_CONFIG_EN
NATCHIP_CONFIG_IRQ_EN

>> NC_ is too short, something like NATCHIP may be better.
> Ok, good name.
> 
>>> +static irqreturn_t timer_interrupt(int irq, void *dev)
>>
>> Fix the function name.
> static irqreturn_t natchip_timer_interrupt(int irq, void *dev)
> Hmm?

Fine.

>>> +static struct timer_of to = {
>>> +	.flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
>>> +
>>> +	.clkevt = {
>>> +		.name = TIMER_NAME,
>>
>> Let the node name.
> Ok, remove it.
>  
>>> +		.rating = 300,
>>> +		.features = CLOCK_EVT_FEAT_DYNIRQ | CLOCK_EVT_FEAT_PERIODIC |
>>> +			CLOCK_EVT_FEAT_ONESHOT,
>>> +		.set_state_shutdown	= nc_timer_shutdown,
>>> +		.set_state_periodic	= nc_timer_set_periodic,
>>> +		.set_next_event		= nc_timer_set_next_event,
>>
>> set_oneshot ?
> Yes oneshort, but also could support periodic. But in fact, it only
> works with oneshort.

In the flags, it is specified periodic and oneshot but only the
set_periodic ops is set.

[ ... ]

>>> +	div = timer_of_rate(&to)/TIMER_FREQ - 1;
>>
>> space ' / '
>>
>> Is it
>>   (timer_of_rate(&to) / TIMER_FREQ) - 1
>> or
>>   timer_of_rate(&to) / (TIMER_FREQ - 1)
>>
>> ?
> Thx, I'll modify it like this:
> div = (timer_of_rate(&to) / TIMER_FREQ) - 1;

I wanted to be sure it wasn't the latter. In this case, you don't need
parenthesis, so just add the spaces around the '/' operator.




-- 
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog


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

* Re: [PATCH V2 06/19] csky: Cache and TLB routines
  2018-07-01 17:30 ` [PATCH V2 06/19] csky: Cache and TLB routines Guo Ren
@ 2018-07-05 17:40   ` Peter Zijlstra
  2018-07-07 11:51     ` Guo Ren
  0 siblings, 1 reply; 88+ messages in thread
From: Peter Zijlstra @ 2018-07-05 17:40 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu,
	Will Deacon

On Mon, Jul 02, 2018 at 01:30:09AM +0800, Guo Ren wrote:
> diff --git a/arch/csky/include/asm/barrier.h b/arch/csky/include/asm/barrier.h
> new file mode 100644
> index 0000000..7254527
> --- /dev/null
> +++ b/arch/csky/include/asm/barrier.h
> @@ -0,0 +1,19 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
> +#ifndef __ASM_CSKY_BARRIER_H
> +#define __ASM_CSKY_BARRIER_H
> +
> +#ifndef __ASSEMBLY__
> +
> +#define nop()	asm volatile ("nop")
> +
> +#ifdef CONFIG_SMP
> +#define mb()	asm volatile ("sync.is":::"memory")
> +#else
> +#define mb()	asm volatile ("sync":::"memory")
> +#endif

This is very suspect, please elaborate.

What I would've expected is:

#define mb() asm volatile ("sync" ::: "memory")

#ifdef CONFIG_SMP
#define __smp_mb() asm volatile ("sync.is" ::: "memory")
#endif

Is that in fact what you meant?

Do you have a reference to your architecture manual and memory model
description somewhere?


> +
> +#include <asm-generic/barrier.h>
> +
> +#endif /* __ASSEMBLY__ */
> +#endif /* __ASM_CSKY_BARRIER_H */

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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-01 17:30 ` [PATCH V2 11/19] csky: Atomic operations Guo Ren
@ 2018-07-05 17:50   ` Peter Zijlstra
  2018-07-06 11:01     ` Guo Ren
  2018-07-05 17:59   ` Peter Zijlstra
  2018-07-05 18:00   ` Peter Zijlstra
  2 siblings, 1 reply; 88+ messages in thread
From: Peter Zijlstra @ 2018-07-05 17:50 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu,
	Will Deacon

On Mon, Jul 02, 2018 at 01:30:14AM +0800, Guo Ren wrote:

> +#include <asm/barrier.h>
> +
> +#define __xchg(new, ptr, size)					\
> +({								\
> +	__typeof__(ptr) __ptr = (ptr);				\
> +	__typeof__(new) __new = (new);				\
> +	__typeof__(*(ptr)) __ret;				\
> +	unsigned long tmp;					\
> +	switch (size) {						\
> +	case 4:							\
> +		asm volatile (					\
> +		"1:	ldex.w		%0, (%3) \n"		\
> +		"	mov		%1, %2   \n"		\
> +		"	stex.w		%1, (%3) \n"		\
> +		"	bez		%1, 1b   \n"		\
> +			: "=&r" (__ret), "=&r" (tmp)		\
> +			: "r" (__new), "r"(__ptr)		\
> +			: "memory");				\
> +		smp_mb();					\
> +		break;						\
> +	default:						\
> +		BUILD_BUG();					\
> +	}							\
> +	__ret;							\
> +})
> +
> +#define xchg(ptr, x)	(__xchg((x), (ptr), sizeof(*(ptr))))
> +
> +#define __cmpxchg(ptr, old, new, size)				\
> +({								\
> +	__typeof__(ptr) __ptr = (ptr);				\
> +	__typeof__(new) __new = (new);				\
> +	__typeof__(new) __tmp;					\
> +	__typeof__(old) __old = (old);				\
> +	__typeof__(*(ptr)) __ret;				\
> +	switch (size) {						\
> +	case 4:							\
> +		asm volatile (					\
> +		"1:	ldex.w		%0, (%3) \n"		\
> +		"	cmpne		%0, %4   \n"		\
> +		"	bt		2f       \n"		\
> +		"	mov		%1, %2   \n"		\
> +		"	stex.w		%1, (%3) \n"		\
> +		"	bez		%1, 1b   \n"		\
> +		"2:				 \n"		\
> +			: "=&r" (__ret), "=&r" (__tmp)		\
> +			: "r" (__new), "r"(__ptr), "r"(__old)	\
> +			: "memory");				\
> +		smp_mb();					\
> +		break;						\
> +	default:						\
> +		BUILD_BUG();					\
> +	}							\
> +	__ret;							\
> +})
> +
> +#define cmpxchg(ptr, o, n) \
> +	(__cmpxchg((ptr), (o), (n), sizeof(*(ptr))))

What's the memory ordering rules for your LDEX/STEX ?

The mandated semantics for xchg() / cmpxchg() is an effective smp_mb()
before _and_ after.

The above implementation suggests LDEX implies a SYNC.IS, is this
correct?

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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-01 17:30 ` [PATCH V2 11/19] csky: Atomic operations Guo Ren
  2018-07-05 17:50   ` Peter Zijlstra
@ 2018-07-05 17:59   ` Peter Zijlstra
  2018-07-06 11:44     ` Guo Ren
  2018-07-05 18:00   ` Peter Zijlstra
  2 siblings, 1 reply; 88+ messages in thread
From: Peter Zijlstra @ 2018-07-05 17:59 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Mon, Jul 02, 2018 at 01:30:14AM +0800, Guo Ren wrote:

> +static inline void arch_spin_lock(arch_spinlock_t *lock)
> +{
> +	unsigned int *p = &lock->lock;
> +	unsigned int tmp;
> +
> +	asm volatile (
> +		"1:	ldex.w		%0, (%1) \n"
> +		"	bnez		%0, 1b   \n"
> +		"	movi		%0, 1    \n"
> +		"	stex.w		%0, (%1) \n"
> +		"	bez		%0, 1b   \n"
> +		: "=&r" (tmp)
> +		: "r"(p)
> +		: "memory");
> +	smp_mb();
> +}

Test-and-set with MB acting as ACQUIRE, ok.

> +static inline void arch_spin_unlock(arch_spinlock_t *lock)
> +{
> +	unsigned int *p = &lock->lock;
> +	unsigned int tmp;
> +
> +	smp_mb();
> +	asm volatile (
> +		"1:	ldex.w		%0, (%1) \n"
> +		"	movi		%0, 0    \n"
> +		"	stex.w		%0, (%1) \n"
> +		"	bez		%0, 1b   \n"
> +		: "=&r" (tmp)
> +		: "r"(p)
> +		: "memory");
> +}

MB acting for RELEASE, but _why_ are you using a LDEX/STEX to clear the
lock word? Would not a normal store work?

Also, the fact that you need MB for release implies your LDEX does not
in fact imply anything and your xchg/cmpxchg implementation is broken.

> +static inline int arch_spin_trylock(arch_spinlock_t *lock)
> +{
> +	unsigned int *p = &lock->lock;
> +	unsigned int tmp;
> +
> +	asm volatile (
> +		"1:	ldex.w		%0, (%1) \n"
> +		"	bnez		%0, 2f   \n"
> +		"	movi		%0, 1    \n"
> +		"	stex.w		%0, (%1) \n"
> +		"	bez		%0, 1b   \n"
> +		"	movi		%0, 0    \n"
> +		"2:				 \n"
> +		: "=&r" (tmp)
> +		: "r"(p)
> +		: "memory");
> +	smp_mb();
> +
> +	return !tmp;
> +}

Strictly speaking you can avoid the MB on failure. You only need to
provide ACQUIRE semantics on success.

That said, I would really suggest you implement a ticket lock instead of
a test-and-set lock. They're not really all that complicated and do
provide better worst case behaviour.


> +/****** read lock/unlock/trylock ******/

Please have a look at using qrwlock -- esp. if you implement a ticket
lock, then the rwlock comes for 'free'.

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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-01 17:30 ` [PATCH V2 11/19] csky: Atomic operations Guo Ren
  2018-07-05 17:50   ` Peter Zijlstra
  2018-07-05 17:59   ` Peter Zijlstra
@ 2018-07-05 18:00   ` Peter Zijlstra
  2018-07-06 11:48     ` Guo Ren
  2 siblings, 1 reply; 88+ messages in thread
From: Peter Zijlstra @ 2018-07-05 18:00 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Mon, Jul 02, 2018 at 01:30:14AM +0800, Guo Ren wrote:
> +#ifdef CONFIG_CPU_HAS_LDSTEX
> +ENTRY(csky_cmpxchg)
> +	USPTOKSP
> +	mfcr	a3, epc
> +	INCTRAP	a3
> +
> +	subi    sp, 8
> +	stw     a3, (sp, 0)
> +	mfcr    a3, epsr
> +	stw     a3, (sp, 4)
> +
> +	psrset	ee
> +1:
> +	ldex	a3, (a2)
> +	cmpne	a0, a3
> +	bt16	2f
> +	mov	a3, a1
> +	stex	a3, (a2)
> +	bez	a3, 1b
> +2:
> +	sync.is
> +	mvc	a0
> +	ldw	a3, (sp, 0)
> +	mtcr	a3, epc
> +	ldw     a3, (sp, 4)
> +	mtcr	a3, epsr
> +	addi	sp, 8
> +	KSPTOUSP
> +	rte
> +END(csky_cmpxchg)
> +#else

Please explain... if the CPU has LDEX/STEX, then _why_ do you need this?

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

* Re: [PATCH V2 16/19] csky: SMP support
  2018-07-01 17:30 ` [PATCH V2 16/19] csky: SMP support Guo Ren
@ 2018-07-05 18:05   ` Peter Zijlstra
  2018-07-06  6:07     ` Guo Ren
  2018-07-06  5:24   ` Mark Rutland
  1 sibling, 1 reply; 88+ messages in thread
From: Peter Zijlstra @ 2018-07-05 18:05 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Mon, Jul 02, 2018 at 01:30:19AM +0800, Guo Ren wrote:
> +static irqreturn_t handle_ipi(int irq, void *dev)
> +{
> +	unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits;
> +
> +	while (true) {
> +		unsigned long ops;
> +
> +		/* Order bit clearing and data access. */
> +		mb();
> +
> +		ops = xchg(pending_ipis, 0);
> +		if (ops == 0)
> +			return IRQ_HANDLED;
> +
> +		if (ops & (1 << IPI_RESCHEDULE))
> +			scheduler_ipi();
> +
> +		if (ops & (1 << IPI_CALL_FUNC))
> +			generic_smp_call_function_interrupt();
> +
> +		BUG_ON((ops >> IPI_MAX) != 0);
> +
> +		/* Order data access and bit testing. */
> +		mb();
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static void (*send_arch_ipi)(const unsigned long *mask, unsigned long irq) = NULL;
> +
> +void __init set_send_ipi(void (*func)(const unsigned long *, unsigned long))
> +{
> +	if (send_arch_ipi)
> +		return;
> +
> +	send_arch_ipi = func;
> +}
> +
> +static void
> +send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation)
> +{
> +	int i;
> +
> +	mb();
> +	for_each_cpu(i, to_whom)
> +		set_bit(operation, &ipi_data[i].bits);
> +
> +	mb();
> +	send_arch_ipi(cpumask_bits(to_whom), IPI_IRQ);
> +}


Please explain those mb()'s... I'm thinking you meant to use smp_mb().

But then for handle_ipi(), the xchg() should already imply all those.
And the send_ipi_message() only needs the second.


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

* Re: [PATCH V2 16/19] csky: SMP support
  2018-07-01 17:30 ` [PATCH V2 16/19] csky: SMP support Guo Ren
  2018-07-05 18:05   ` Peter Zijlstra
@ 2018-07-06  5:24   ` Mark Rutland
  2018-07-06 11:32     ` Guo Ren
  1 sibling, 1 reply; 88+ messages in thread
From: Mark Rutland @ 2018-07-06  5:24 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Mon, Jul 02, 2018 at 01:30:19AM +0800, Guo Ren wrote:
> +static int csky_of_cpu(struct device_node *node)
> +{
> +	const char *status;
> +	int cpu;
> +
> +	if (of_property_read_u32(node, "reg", &cpu))
> +		goto error;
> +
> +	if (cpu >= NR_CPUS)
> +		goto error;
> +
> +	if (of_property_read_string(node, "status", &status))
> +		status = "enable";
> +
> +	if (strcmp(status, "disable") == 0)
> +		goto error;

Please use of_device_is_available(node); "enable" is not a sensible value for
the status property, and "disable" (rather than "disabled") is simply unusual.

Neither "enable" nor "disable" are correct values for the status property.

What is the value in the reg property, exactly? Is there a unique ID in
hardware for each CPU in the system?

It would be good to document this, e.g. as arm does in
Documentation/devicetree/bindings/arm/cpus.txt

> +
> +	return cpu;
> +error:
> +	return -ENODEV;
> +}
> +
> +void __init setup_smp(void)
> +{
> +	struct device_node *node = NULL;
> +	int cpu;
> +
> +	while ((node = of_find_node_by_type(node, "cpu"))) {
> +		cpu = csky_of_cpu(node);
> +		if (cpu >= 0) {
> +			set_cpu_possible(cpu, true);
> +			set_cpu_present(cpu, true);
> +		}
> +	}
> +}

What happens if/when the value in the reg property is larger than NR_CPUS?

> +int __cpu_up(unsigned int cpu, struct task_struct *tidle)
> +{
> +	unsigned int tmp;
> +
> +	secondary_stack = (unsigned int)tidle->stack + THREAD_SIZE;
> +
> +	secondary_hint = mfcr("cr31");
> +
> +	secondary_ccr  = mfcr("cr18");
> +
> +	pr_info("%s: CPU%u\n", __func__, cpu);
> +
> +	tmp = mfcr("cr<29, 0>");
> +	tmp |= 1 << cpu;
> +	mtcr("cr<29, 0>", tmp);
> +
> +	while (!cpu_online(cpu));
> +
> +	secondary_stack = 0;
> +
> +	return 0;
> +}

I don't see a start address being setup here, so I assume that CPUs branch to a
fixed address out-of-reset. Does that mean that the kernel has to be loaded at
a particular physical address on a given platform?

Thanks,
Mark.

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

* Re: [PATCH V2 18/19] clocksource: add C-SKY clocksource drivers
  2018-07-05  9:23       ` Daniel Lezcano
@ 2018-07-06  5:57         ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-06  5:57 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: linux-arch, linux-kernel, tglx, jason, arnd, c-sky_gcc_upstream,
	gnu-csky, thomas.petazzoni, wbx, green.hu

On Thu, Jul 05, 2018 at 11:23:36AM +0200, Daniel Lezcano wrote:
> > So I still need "for_each_cpu(cpu, cpu_possible_mask)" to init every
> > csky_to ...
> 
> That is what is unclear for me. percpu or IRQF_PERCPU ?
IRQF_PERCPU
 
> Have a look at the commit 9995f4f184613fb02ee73092b03545520a72b104,
> changelog and the comment in the init function.
> 
> Can you give a similar description for this timer ?
Ok, thx for the tip.

> > #define STATUS_CLR	BIT(0)
> > 
> > #define CONTRL_RST	BIT(0)
> > #define CONTRL_START	BIT(1)
> > 
> > #define CONFIG_EN	BIT(0)
> > #define CONFIG_IRQ_EN	BIT(1)
> 
> NATCHIP_STATUS_CLR
> NATCHIP_CONTROL_RST
> NATCHIP_CONTROL_START
> 
> NATCHIP_CONFIG_EN
> NATCHIP_CONFIG_IRQ_EN
Ok

> >>> +		.rating = 300,
> >>> +		.features = CLOCK_EVT_FEAT_DYNIRQ | CLOCK_EVT_FEAT_PERIODIC |
> >>> +			CLOCK_EVT_FEAT_ONESHOT,
> >>> +		.set_state_shutdown	= nc_timer_shutdown,
> >>> +		.set_state_periodic	= nc_timer_set_periodic,
> >>> +		.set_next_event		= nc_timer_set_next_event,
> >>
> >> set_oneshot ?
> > Yes oneshort, but also could support periodic. But in fact, it only
> > works with oneshort.
> 
> In the flags, it is specified periodic and oneshot but only the
> set_periodic ops is set.
Got it, add set_oneshot.

> > Thx, I'll modify it like this:
> > div = (timer_of_rate(&to) / TIMER_FREQ) - 1;
> 
> I wanted to be sure it wasn't the latter. In this case, you don't need
> parenthesis, so just add the spaces around the '/' operator.
Ok

 Guo Ren

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

* Re: [PATCH V2 16/19] csky: SMP support
  2018-07-05 18:05   ` Peter Zijlstra
@ 2018-07-06  6:07     ` Guo Ren
  2018-07-06  9:39       ` Peter Zijlstra
  0 siblings, 1 reply; 88+ messages in thread
From: Guo Ren @ 2018-07-06  6:07 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Thu, Jul 05, 2018 at 08:05:03PM +0200, Peter Zijlstra wrote:
> On Mon, Jul 02, 2018 at 01:30:19AM +0800, Guo Ren wrote:
> > +static irqreturn_t handle_ipi(int irq, void *dev)
> > +{
> > +	unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits;
> > +
> > +	while (true) {
> > +		unsigned long ops;
> > +
> > +		/* Order bit clearing and data access. */
> > +		mb();
> > +
> > +		ops = xchg(pending_ipis, 0);
> > +		if (ops == 0)
> > +			return IRQ_HANDLED;
> > +
> > +		if (ops & (1 << IPI_RESCHEDULE))
> > +			scheduler_ipi();
> > +
> > +		if (ops & (1 << IPI_CALL_FUNC))
> > +			generic_smp_call_function_interrupt();
> > +
> > +		BUG_ON((ops >> IPI_MAX) != 0);
> > +
> > +		/* Order data access and bit testing. */
> > +		mb();
> > +	}
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static void (*send_arch_ipi)(const unsigned long *mask, unsigned long irq) = NULL;
> > +
> > +void __init set_send_ipi(void (*func)(const unsigned long *, unsigned long))
> > +{
> > +	if (send_arch_ipi)
> > +		return;
> > +
> > +	send_arch_ipi = func;
> > +}
> > +
> > +static void
> > +send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation)
> > +{
> > +	int i;
> > +
> > +	mb();
> > +	for_each_cpu(i, to_whom)
> > +		set_bit(operation, &ipi_data[i].bits);
> > +
> > +	mb();
> > +	send_arch_ipi(cpumask_bits(to_whom), IPI_IRQ);
> > +}
> 
> 
> Please explain those mb()'s... I'm thinking you meant to use smp_mb().
Yes, smp_mb(). Current smp_mb()&mb() is the same: sync.is.

In next version patch, I'll seperate smp_mb() and mb() and use ld/st.barrier
instead of sync.is. Sync.is is expensive that it flush cpu's pipeline.

> But then for handle_ipi(), the xchg() should already imply all those.
Yes, approve.

> And the send_ipi_message() only needs the second.
Yes, approve.

 Guo Ren

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

* Re: [PATCH V2 16/19] csky: SMP support
  2018-07-06  6:07     ` Guo Ren
@ 2018-07-06  9:39       ` Peter Zijlstra
  2018-07-06 13:22         ` Guo Ren
  0 siblings, 1 reply; 88+ messages in thread
From: Peter Zijlstra @ 2018-07-06  9:39 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu,
	Will Deacon

On Fri, Jul 06, 2018 at 02:07:40PM +0800, Guo Ren wrote:

> > Please explain those mb()'s... I'm thinking you meant to use smp_mb().
> Yes, smp_mb(). Current smp_mb()&mb() is the same: sync.is.
> 
> In next version patch, I'll seperate smp_mb() and mb() and use ld/st.barrier
> instead of sync.is. Sync.is is expensive that it flush cpu's pipeline.

I'll second my own call for documentation, because now there's three
memory ordering instructions:

 "SYNC", "SYNC.IS" and "LD/ST.BARRIER"

None of which have yet been explained.

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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-05 17:50   ` Peter Zijlstra
@ 2018-07-06 11:01     ` Guo Ren
  2018-07-06 11:56       ` Peter Zijlstra
  0 siblings, 1 reply; 88+ messages in thread
From: Guo Ren @ 2018-07-06 11:01 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu,
	Will Deacon

On Thu, Jul 05, 2018 at 07:50:59PM +0200, Peter Zijlstra wrote:
> On Mon, Jul 02, 2018 at 01:30:14AM +0800, Guo Ren wrote:
> 
> > +#include <asm/barrier.h>
> > +
> > +#define __xchg(new, ptr, size)					\
> > +({								\
> > +	__typeof__(ptr) __ptr = (ptr);				\
> > +	__typeof__(new) __new = (new);				\
> > +	__typeof__(*(ptr)) __ret;				\
> > +	unsigned long tmp;					\
> > +	switch (size) {						\
> > +	case 4:							\
> > +		asm volatile (					\
> > +		"1:	ldex.w		%0, (%3) \n"		\
> > +		"	mov		%1, %2   \n"		\
> > +		"	stex.w		%1, (%3) \n"		\
> > +		"	bez		%1, 1b   \n"		\
> > +			: "=&r" (__ret), "=&r" (tmp)		\
> > +			: "r" (__new), "r"(__ptr)		\
> > +			: "memory");				\
> > +		smp_mb();					\
> > +		break;						\
> > +	default:						\
> > +		BUILD_BUG();					\
> > +	}							\
> > +	__ret;							\
> > +})
> > +
> > +#define xchg(ptr, x)	(__xchg((x), (ptr), sizeof(*(ptr))))
> > +
> > +#define __cmpxchg(ptr, old, new, size)				\
> > +({								\
> > +	__typeof__(ptr) __ptr = (ptr);				\
> > +	__typeof__(new) __new = (new);				\
> > +	__typeof__(new) __tmp;					\
> > +	__typeof__(old) __old = (old);				\
> > +	__typeof__(*(ptr)) __ret;				\
> > +	switch (size) {						\
> > +	case 4:							\
> > +		asm volatile (					\
> > +		"1:	ldex.w		%0, (%3) \n"		\
> > +		"	cmpne		%0, %4   \n"		\
> > +		"	bt		2f       \n"		\
> > +		"	mov		%1, %2   \n"		\
> > +		"	stex.w		%1, (%3) \n"		\
> > +		"	bez		%1, 1b   \n"		\
> > +		"2:				 \n"		\
> > +			: "=&r" (__ret), "=&r" (__tmp)		\
> > +			: "r" (__new), "r"(__ptr), "r"(__old)	\
> > +			: "memory");				\
> > +		smp_mb();					\
> > +		break;						\
> > +	default:						\
> > +		BUILD_BUG();					\
> > +	}							\
> > +	__ret;							\
> > +})
> > +
> > +#define cmpxchg(ptr, o, n) \
> > +	(__cmpxchg((ptr), (o), (n), sizeof(*(ptr))))
> 
> What's the memory ordering rules for your LDEX/STEX ?
Every CPU has a local exclusive monitor.

"Ldex rz, (rx, #off)" will add an entry into the local monitor, and the 
entry is composed of a address tag and a exclusive flag (inited with 1). 
Any stores (include other cores') will break the exclusive flag to 0 in
the entry which could be indexed by the address tag.

"Stex rz, (rx, #off)" has two condition:
1. Store Success: When the entry's exclusive flag is 1, it will store rz
to the [rx + off] address and the rz will be set to 1.
2. Store Failure: When the entry's exclusive flag is 0, just rz will be
set to 0.

> The mandated semantics for xchg() / cmpxchg() is an effective smp_mb()
> before _and_ after.

	switch (size) {						\
	case 4:							\
		smp_mb();					\
		asm volatile (					\
		"1:	ldex.w		%0, (%3) \n"		\
		"	mov		%1, %2   \n"		\
		"	stex.w		%1, (%3) \n"		\
		"	bez		%1, 1b   \n"		\
			: "=&r" (__ret), "=&r" (tmp)		\
			: "r" (__new), "r"(__ptr)		\
			: "memory");				\
		smp_mb();					\
		break;						\
Hmm?
But I couldn't undertand what's wrong without the 1th smp_mb()?
1th smp_mb will make all ld/st finish before ldex.w. Is it necessary?

> The above implementation suggests LDEX implies a SYNC.IS, is this
> correct?
No, ldex doesn't imply a sync.is.

 Guo Ren


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

* Re: [PATCH V2 16/19] csky: SMP support
  2018-07-06  5:24   ` Mark Rutland
@ 2018-07-06 11:32     ` Guo Ren
  2018-07-06 11:43       ` Mark Rutland
  0 siblings, 1 reply; 88+ messages in thread
From: Guo Ren @ 2018-07-06 11:32 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Fri, Jul 06, 2018 at 06:24:33AM +0100, Mark Rutland wrote:
> > +	if (cpu >= NR_CPUS)
> > +		goto error;
> > +
> > +	if (of_property_read_string(node, "status", &status))
> > +		status = "enable";
> > +
> > +	if (strcmp(status, "disable") == 0)
> > +		goto error;
> 
> Please use of_device_is_available(node); 
Ok.

> "enable" is not a sensible value for
> the status property, and "disable" (rather than "disabled") is simply unusual.
> 
> Neither "enable" nor "disable" are correct values for the status property.

	cpus {
		#address-cells = <1>;
		#size-cells = <0>;
		cpu@0 {
			device_type = "cpu";
			reg = <0>;
			status = "on";
		};

		cpu@1 {
			device_type = "cpu";
			reg = <1>;
			status = "off";
		};
	};

> What is the value in the reg property, exactly?
See above, I'll remove the reg property and it's no use.

> Is there a unique ID in
> hardware for each CPU in the system?
There is no unique ID in current CPU: ck860.

> 
> It would be good to document this, e.g. as arm does in
> Documentation/devicetree/bindings/arm/cpus.txt
Ok.

> > +
> > +	return cpu;
> > +error:
> > +	return -ENODEV;
> > +}
> > +
> > +void __init setup_smp(void)
> > +{
> > +	struct device_node *node = NULL;
> > +	int cpu;
> > +
> > +	while ((node = of_find_node_by_type(node, "cpu"))) {
> > +		cpu = csky_of_cpu(node);
> > +		if (cpu >= 0) {
> > +			set_cpu_possible(cpu, true);
> > +			set_cpu_present(cpu, true);
> > +		}
> > +	}
> > +}
> 
> What happens if/when the value in the reg property is larger than NR_CPUS?
Bug. I'll add NR_CPUS limit.

> > +int __cpu_up(unsigned int cpu, struct task_struct *tidle)
> > +{
> > +	unsigned int tmp;
> > +
> > +	secondary_stack = (unsigned int)tidle->stack + THREAD_SIZE;
> > +
> > +	secondary_hint = mfcr("cr31");
> > +
> > +	secondary_ccr  = mfcr("cr18");
> > +
> > +	pr_info("%s: CPU%u\n", __func__, cpu);
> > +
> > +	tmp = mfcr("cr<29, 0>");
> > +	tmp |= 1 << cpu;
> > +	mtcr("cr<29, 0>", tmp);
> > +
> > +	while (!cpu_online(cpu));
> > +
> > +	secondary_stack = 0;
> > +
> > +	return 0;
> > +}
> 
> I don't see a start address being setup here, so I assume that CPUs branch to a
> fixed address out-of-reset. Does that mean that the kernel has to be loaded at
> a particular physical address on a given platform?
No, not a fixed address. I put it arch/csky/kernel/traps.c:79-83
trap_init()
#ifdef CONFIG_SMP
	mtcr("cr<28, 0>", virt_to_phys(vec_base));

	VEC_INIT(VEC_RESET, (void *)virt_to_phys(_start_smp_secondary));
#endi

 Guo Ren

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

* Re: [PATCH V2 16/19] csky: SMP support
  2018-07-06 11:32     ` Guo Ren
@ 2018-07-06 11:43       ` Mark Rutland
  2018-07-06 12:26         ` Guo Ren
  0 siblings, 1 reply; 88+ messages in thread
From: Mark Rutland @ 2018-07-06 11:43 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Fri, Jul 06, 2018 at 07:32:01PM +0800, Guo Ren wrote:
> On Fri, Jul 06, 2018 at 06:24:33AM +0100, Mark Rutland wrote:
> > > +	if (cpu >= NR_CPUS)
> > > +		goto error;
> > > +
> > > +	if (of_property_read_string(node, "status", &status))
> > > +		status = "enable";
> > > +
> > > +	if (strcmp(status, "disable") == 0)
> > > +		goto error;
> > 
> > Please use of_device_is_available(node); 
> Ok.
> 
> > "enable" is not a sensible value for
> > the status property, and "disable" (rather than "disabled") is simply unusual.
> > 
> > Neither "enable" nor "disable" are correct values for the status property.
> 
> 	cpus {
> 		#address-cells = <1>;
> 		#size-cells = <0>;
> 		cpu@0 {
> 			device_type = "cpu";
> 			reg = <0>;
> 			status = "on";
> 		};
> 
> 		cpu@1 {
> 			device_type = "cpu";
> 			reg = <1>;
> 			status = "off";
> 		};
> 	};

Neither "on" nor "off" are standard status values either.

Please see the devicetree spec [1], section 2.3.4. Valid values are:

* "okay" // equivalent to no status property present
* "disabled"
* "fail"
* "fail-sss"

> > What is the value in the reg property, exactly?
> See above, I'll remove the reg property and it's no use.
> 
> > Is there a unique ID in
> > hardware for each CPU in the system?
> There is no unique ID in current CPU: ck860.

I'm a bit confused. You write (1 << cpu) into cv<29, 0>, to enable a
particular CPU, so I assume that bit uniquely identifies a CPU, and
therefore the reg is some unique ID for the CPU.

[...]

> > > +int __cpu_up(unsigned int cpu, struct task_struct *tidle)
> > > +{
> > > +	unsigned int tmp;
> > > +
> > > +	secondary_stack = (unsigned int)tidle->stack + THREAD_SIZE;
> > > +
> > > +	secondary_hint = mfcr("cr31");
> > > +
> > > +	secondary_ccr  = mfcr("cr18");
> > > +
> > > +	pr_info("%s: CPU%u\n", __func__, cpu);
> > > +
> > > +	tmp = mfcr("cr<29, 0>");
> > > +	tmp |= 1 << cpu;
> > > +	mtcr("cr<29, 0>", tmp);
> > > +
> > > +	while (!cpu_online(cpu));
> > > +
> > > +	secondary_stack = 0;
> > > +
> > > +	return 0;
> > > +}
> > 
> > I don't see a start address being setup here, so I assume that CPUs branch to a
> > fixed address out-of-reset. Does that mean that the kernel has to be loaded at
> > a particular physical address on a given platform?
> No, not a fixed address. I put it arch/csky/kernel/traps.c:79-83
> trap_init()
> #ifdef CONFIG_SMP
> 	mtcr("cr<28, 0>", virt_to_phys(vec_base));
> 
> 	VEC_INIT(VEC_RESET, (void *)virt_to_phys(_start_smp_secondary));
> #endi

I see.

Is this SMP bringup mechanism architectual, or are you likely to need
another mechanism to turn on CPUs on future chips?

You probably want to use an enable-method property to describe this.

Thanks,
Mark.

[1] https://www.devicetree.org/specifications/

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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-05 17:59   ` Peter Zijlstra
@ 2018-07-06 11:44     ` Guo Ren
  2018-07-06 12:03       ` Peter Zijlstra
  0 siblings, 1 reply; 88+ messages in thread
From: Guo Ren @ 2018-07-06 11:44 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Thu, Jul 05, 2018 at 07:59:02PM +0200, Peter Zijlstra wrote:
> On Mon, Jul 02, 2018 at 01:30:14AM +0800, Guo Ren wrote:
> 
> > +static inline void arch_spin_lock(arch_spinlock_t *lock)
> > +{
> > +	unsigned int *p = &lock->lock;
> > +	unsigned int tmp;
> > +
> > +	asm volatile (
> > +		"1:	ldex.w		%0, (%1) \n"
> > +		"	bnez		%0, 1b   \n"
> > +		"	movi		%0, 1    \n"
> > +		"	stex.w		%0, (%1) \n"
> > +		"	bez		%0, 1b   \n"
> > +		: "=&r" (tmp)
> > +		: "r"(p)
> > +		: "memory");
> > +	smp_mb();
> > +}
> 
> Test-and-set with MB acting as ACQUIRE, ok.
Em ... Ok, I'll try to use test-and-set function instead of it.

> > +static inline void arch_spin_unlock(arch_spinlock_t *lock)
> > +{
> > +	unsigned int *p = &lock->lock;
> > +	unsigned int tmp;
> > +
> > +	smp_mb();
> > +	asm volatile (
> > +		"1:	ldex.w		%0, (%1) \n"
> > +		"	movi		%0, 0    \n"
> > +		"	stex.w		%0, (%1) \n"
> > +		"	bez		%0, 1b   \n"
> > +		: "=&r" (tmp)
> > +		: "r"(p)
> > +		: "memory");
> > +}
> 
> MB acting for RELEASE, but _why_ are you using a LDEX/STEX to clear the
> lock word? Would not a normal store work?
Normal store is enough, I'll fixup it in next version patch.
 
> Also, the fact that you need MB for release implies your LDEX does not
> in fact imply anything and your xchg/cmpxchg implementation is broken.
xchg/cmxchg broken without 1th smp_mb()? Why we need protect the
instructions flow before the ldex.w?

> > +static inline int arch_spin_trylock(arch_spinlock_t *lock)
> > +{
> > +	unsigned int *p = &lock->lock;
> > +	unsigned int tmp;
> > +
> > +	asm volatile (
> > +		"1:	ldex.w		%0, (%1) \n"
> > +		"	bnez		%0, 2f   \n"
> > +		"	movi		%0, 1    \n"
> > +		"	stex.w		%0, (%1) \n"
> > +		"	bez		%0, 1b   \n"
> > +		"	movi		%0, 0    \n"
> > +		"2:				 \n"
> > +		: "=&r" (tmp)
> > +		: "r"(p)
> > +		: "memory");
> > +	smp_mb();
> > +
> > +	return !tmp;
> > +}
> 
> Strictly speaking you can avoid the MB on failure. You only need to
> provide ACQUIRE semantics on success.
> 
> That said, I would really suggest you implement a ticket lock instead of
> a test-and-set lock. They're not really all that complicated and do
> provide better worst case behaviour.
Ok, I'll try to implement ticket lock in next version patch.

> 
> 
> > +/****** read lock/unlock/trylock ******/
> 
> Please have a look at using qrwlock -- esp. if you implement a ticket
> lock, then the rwlock comes for 'free'.
Ok, I'll try it.

 Guo Ren

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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-05 18:00   ` Peter Zijlstra
@ 2018-07-06 11:48     ` Guo Ren
  2018-07-06 12:05       ` Peter Zijlstra
  0 siblings, 1 reply; 88+ messages in thread
From: Guo Ren @ 2018-07-06 11:48 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Thu, Jul 05, 2018 at 08:00:08PM +0200, Peter Zijlstra wrote:
> On Mon, Jul 02, 2018 at 01:30:14AM +0800, Guo Ren wrote:
> > +#ifdef CONFIG_CPU_HAS_LDSTEX
> > +ENTRY(csky_cmpxchg)
> > +	USPTOKSP
> > +	mfcr	a3, epc
> > +	INCTRAP	a3
> > +
> > +	subi    sp, 8
> > +	stw     a3, (sp, 0)
> > +	mfcr    a3, epsr
> > +	stw     a3, (sp, 4)
> > +
> > +	psrset	ee
> > +1:
> > +	ldex	a3, (a2)
> > +	cmpne	a0, a3
> > +	bt16	2f
> > +	mov	a3, a1
> > +	stex	a3, (a2)
> > +	bez	a3, 1b
> > +2:
> > +	sync.is
> > +	mvc	a0
> > +	ldw	a3, (sp, 0)
> > +	mtcr	a3, epc
> > +	ldw     a3, (sp, 4)
> > +	mtcr	a3, epsr
> > +	addi	sp, 8
> > +	KSPTOUSP
> > +	rte
> > +END(csky_cmpxchg)
> > +#else
> 
> Please explain... if the CPU has LDEX/STEX, then _why_ do you need this?
Our libc use csky_cmpxchg and we want it compatible. Of course, we'll
also implement the ldex/stex atomic operations in libs in future.

 Guo Ren


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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-06 11:01     ` Guo Ren
@ 2018-07-06 11:56       ` Peter Zijlstra
  2018-07-06 12:17         ` Peter Zijlstra
  2018-07-07  7:42         ` Guo Ren
  0 siblings, 2 replies; 88+ messages in thread
From: Peter Zijlstra @ 2018-07-06 11:56 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu,
	Will Deacon

On Fri, Jul 06, 2018 at 07:01:31PM +0800, Guo Ren wrote:
> On Thu, Jul 05, 2018 at 07:50:59PM +0200, Peter Zijlstra wrote:

> > What's the memory ordering rules for your LDEX/STEX ?
> Every CPU has a local exclusive monitor.
> 
> "Ldex rz, (rx, #off)" will add an entry into the local monitor, and the 
> entry is composed of a address tag and a exclusive flag (inited with 1). 
> Any stores (include other cores') will break the exclusive flag to 0 in
> the entry which could be indexed by the address tag.
> 
> "Stex rz, (rx, #off)" has two condition:
> 1. Store Success: When the entry's exclusive flag is 1, it will store rz
> to the [rx + off] address and the rz will be set to 1.
> 2. Store Failure: When the entry's exclusive flag is 0, just rz will be
> set to 0.

That's how LL/SC works. What I was asking is if they have any effect on
memory ordering. Some architectures have LL/SC imply memory ordering,
most do not.

Going by your spinlock implementation they don't imply any memory
ordering.

> > The mandated semantics for xchg() / cmpxchg() is an effective smp_mb()
> > before _and_ after.
> 
> 	switch (size) {						\
> 	case 4:							\
> 		smp_mb();					\
> 		asm volatile (					\
> 		"1:	ldex.w		%0, (%3) \n"		\
> 		"	mov		%1, %2   \n"		\
> 		"	stex.w		%1, (%3) \n"		\
> 		"	bez		%1, 1b   \n"		\
> 			: "=&r" (__ret), "=&r" (tmp)		\
> 			: "r" (__new), "r"(__ptr)		\
> 			: "memory");				\
> 		smp_mb();					\
> 		break;						\
> Hmm?
> But I couldn't undertand what's wrong without the 1th smp_mb()?
> 1th smp_mb will make all ld/st finish before ldex.w. Is it necessary?

Yes.

	CPU0			CPU1

	r1 = READ_ONCE(x);	WRITE_ONCE(y, 1);
	r2 = xchg(&y, 2);	smp_store_release(&x, 1);

must not allow: r1==1 && r2==0

> > The above implementation suggests LDEX implies a SYNC.IS, is this
> > correct?
> No, ldex doesn't imply a sync.is.

Right, as per the spinlock emails, then your proposed primitives are
incorrect.

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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-06 11:44     ` Guo Ren
@ 2018-07-06 12:03       ` Peter Zijlstra
  2018-07-06 13:01         ` Peter Zijlstra
  2018-07-06 14:06         ` Guo Ren
  0 siblings, 2 replies; 88+ messages in thread
From: Peter Zijlstra @ 2018-07-06 12:03 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Fri, Jul 06, 2018 at 07:44:03PM +0800, Guo Ren wrote:
> On Thu, Jul 05, 2018 at 07:59:02PM +0200, Peter Zijlstra wrote:
> > On Mon, Jul 02, 2018 at 01:30:14AM +0800, Guo Ren wrote:
> > 
> > > +static inline void arch_spin_lock(arch_spinlock_t *lock)
> > > +{
> > > +	unsigned int *p = &lock->lock;
> > > +	unsigned int tmp;
> > > +
> > > +	asm volatile (
> > > +		"1:	ldex.w		%0, (%1) \n"
> > > +		"	bnez		%0, 1b   \n"
> > > +		"	movi		%0, 1    \n"
> > > +		"	stex.w		%0, (%1) \n"
> > > +		"	bez		%0, 1b   \n"
> > > +		: "=&r" (tmp)
> > > +		: "r"(p)
> > > +		: "memory");
> > > +	smp_mb();
> > > +}
> > 
> > Test-and-set with MB acting as ACQUIRE, ok.
> Em ... Ok, I'll try to use test-and-set function instead of it.

"test-and-set" is just the name of this type of spinlock implementation.

You _could_ use the linux test_and_set bitop, but those are defined on
unsigned long and spinlock_t is generally assumed to be of unsigned int
size.

Go with the ticket locks as per below.

> > Also, the fact that you need MB for release implies your LDEX does not
> > in fact imply anything and your xchg/cmpxchg implementation is broken.
> xchg/cmxchg broken without 1th smp_mb()? Why we need protect the
> instructions flow before the ldex.w?

See the email I send earlier in that thread.

> Ok, I'll try to implement ticket lock in next version patch.

If you need inspiration, look at:

  git show 81bb5c6420635dfd058c210bd342c29c95ccd145^1:arch/arm64/include/asm/spinlock.h

Or look at the current version of that file and ignore the LSE version.

Note that unlock is a store half-word (u16), not having seen your arch
manual yet I don't know if you even have that.

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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-06 11:48     ` Guo Ren
@ 2018-07-06 12:05       ` Peter Zijlstra
  2018-07-06 13:46         ` Guo Ren
  0 siblings, 1 reply; 88+ messages in thread
From: Peter Zijlstra @ 2018-07-06 12:05 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Fri, Jul 06, 2018 at 07:48:12PM +0800, Guo Ren wrote:
> On Thu, Jul 05, 2018 at 08:00:08PM +0200, Peter Zijlstra wrote:
> > On Mon, Jul 02, 2018 at 01:30:14AM +0800, Guo Ren wrote:
> > > +#ifdef CONFIG_CPU_HAS_LDSTEX
> > > +ENTRY(csky_cmpxchg)
> > > +	USPTOKSP
> > > +	mfcr	a3, epc
> > > +	INCTRAP	a3
> > > +
> > > +	subi    sp, 8
> > > +	stw     a3, (sp, 0)
> > > +	mfcr    a3, epsr
> > > +	stw     a3, (sp, 4)
> > > +
> > > +	psrset	ee
> > > +1:
> > > +	ldex	a3, (a2)
> > > +	cmpne	a0, a3
> > > +	bt16	2f
> > > +	mov	a3, a1
> > > +	stex	a3, (a2)
> > > +	bez	a3, 1b
> > > +2:
> > > +	sync.is
> > > +	mvc	a0
> > > +	ldw	a3, (sp, 0)
> > > +	mtcr	a3, epc
> > > +	ldw     a3, (sp, 4)
> > > +	mtcr	a3, epsr
> > > +	addi	sp, 8
> > > +	KSPTOUSP
> > > +	rte
> > > +END(csky_cmpxchg)
> > > +#else
> > 
> > Please explain... if the CPU has LDEX/STEX, then _why_ do you need this?
> Our libc use csky_cmpxchg and we want it compatible. Of course, we'll
> also implement the ldex/stex atomic operations in libs in future.

I would strongly suggest not providing this syscall on SMP systems from
the get go. There is no point in starting with legacy problems without
an actual legacy.



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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-06 11:56       ` Peter Zijlstra
@ 2018-07-06 12:17         ` Peter Zijlstra
  2018-07-07  8:08           ` Guo Ren
  2018-07-07  7:42         ` Guo Ren
  1 sibling, 1 reply; 88+ messages in thread
From: Peter Zijlstra @ 2018-07-06 12:17 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu,
	Will Deacon

On Fri, Jul 06, 2018 at 01:56:14PM +0200, Peter Zijlstra wrote:

> > But I couldn't undertand what's wrong without the 1th smp_mb()?
> > 1th smp_mb will make all ld/st finish before ldex.w. Is it necessary?
> 
> Yes.
> 
> 	CPU0			CPU1
> 
> 	r1 = READ_ONCE(x);	WRITE_ONCE(y, 1);
> 	r2 = xchg(&y, 2);	smp_store_release(&x, 1);
> 
> must not allow: r1==1 && r2==0

Also, since you said "SYNC.IS" is a pipeline flush, those
instruction-sync primitives normally do not imply a store-buffer flush,
does yours? If not it is not a valid smp_mb() implementation.

Notably:

	CPU0				CPU1

	WRITE_ONCE(x, 1);		WRITE_ONCE(y, 1);
	smp_mb();			smp_mb();
	r0 = READ_ONCE(y);		r1 = READ_ONCE(x);

must not allow: r0==0 && r1==0

Which would be possible with a regular instruction-sync barrier, but
must absolutely not be true with a full memory barrier.

(and you can replace the smp_mb(); r = READ_ONCE(); with r = xchg() to
again see why you need that first smp_mb()).

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

* Re: [PATCH V2 16/19] csky: SMP support
  2018-07-06 11:43       ` Mark Rutland
@ 2018-07-06 12:26         ` Guo Ren
  2018-07-06 16:21           ` Mark Rutland
  0 siblings, 1 reply; 88+ messages in thread
From: Guo Ren @ 2018-07-06 12:26 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Fri, Jul 06, 2018 at 12:43:52PM +0100, Mark Rutland wrote:
> Please see the devicetree spec [1], section 2.3.4. Valid values are:
> 
> * "okay" // equivalent to no status property present
> * "disabled"
> * "fail"
> * "fail-sss"
Nice tip, thx.

> I'm a bit confused. You write (1 << cpu) into cv<29, 0>, to enable a
> particular CPU, so I assume that bit uniquely identifies a CPU,
Yes, you're right and cr<29, 0>'s bit uniquely identifies a cpu.

> and
> therefore the reg is some unique ID for the CPU.
static int csky_of_cpu(struct device_node *node)
{
	const char *status;

	if (of_property_read_string(node, "status", &status))
		status = "okay";

	if (strcmp(status, "disabled") == 0)
		goto error;

	return 1;
error:
	return 0;
}

void __init setup_smp(void)
{
	struct device_node *node = NULL;
	int i = 0;

	while ((node = of_find_node_by_type(node, "cpu"))) {
		if (!csky_of_cpu(node))
			continue;

		set_cpu_possible(i, true);
		set_cpu_present(i, true);

		i++;
	}
}
Hmm?

No <reg> in next version patch, it's no use.

> I see.
> 
> Is this SMP bringup mechanism architectual, or are you likely to need
> another mechanism to turn on CPUs on future chips?
It's the only SMP bringup mechanism architectual for C-SKY SMP. There is
no another way in future and SOC vendor couldn't change it.

> You probably want to use an enable-method property to describe this.
No, thx.

 Guo Ren

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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-06 12:03       ` Peter Zijlstra
@ 2018-07-06 13:01         ` Peter Zijlstra
  2018-07-06 14:06         ` Guo Ren
  1 sibling, 0 replies; 88+ messages in thread
From: Peter Zijlstra @ 2018-07-06 13:01 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Fri, Jul 06, 2018 at 02:03:23PM +0200, Peter Zijlstra wrote:
> > Ok, I'll try to implement ticket lock in next version patch.
> 
> If you need inspiration, look at:
> 

My bad, just look at the arm (not arm64) version.

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

* Re: [PATCH V2 16/19] csky: SMP support
  2018-07-06  9:39       ` Peter Zijlstra
@ 2018-07-06 13:22         ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-06 13:22 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu,
	Will Deacon

On Fri, Jul 06, 2018 at 11:39:32AM +0200, Peter Zijlstra wrote:
> On Fri, Jul 06, 2018 at 02:07:40PM +0800, Guo Ren wrote:
> 
> > > Please explain those mb()'s... I'm thinking you meant to use smp_mb().
> > Yes, smp_mb(). Current smp_mb()&mb() is the same: sync.is.
> > 
> > In next version patch, I'll seperate smp_mb() and mb() and use ld/st.barrier
> > instead of sync.is. Sync.is is expensive that it flush cpu's pipeline.
> 
> I'll second my own call for documentation, because now there's three
> memory ordering instructions:
> 
>  "SYNC", "SYNC.IS" and "LD/ST.BARRIER"
> 
> None of which have yet been explained.
In C-SKY there are:

sync:        completion barrier
sync.s:      completion barrier and shareable to other cores
sync.i:      completion barrier with flush cpu pipeline
sync.is:     completion barrier with flush cpu pipeline and shareable to other cores 

bar.brwarw:  ordering barrier for all load/store instructions before it
bar.brwarws: ordering barrier for all load/store instructions before it and shareable to other cores
bar.brar:    ordering barrier for all load       instructions before it
bar.brars:   ordering barrier for all load       instructions before it and shareable to other cores
bar.bwaw:    ordering barrier for all store      instructions before it
bar.bwaws:   ordering barrier for all store      instructions before it and shareable to other cores


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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-06 12:05       ` Peter Zijlstra
@ 2018-07-06 13:46         ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-06 13:46 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Fri, Jul 06, 2018 at 02:05:32PM +0200, Peter Zijlstra wrote:
> On Fri, Jul 06, 2018 at 07:48:12PM +0800, Guo Ren wrote:
> > On Thu, Jul 05, 2018 at 08:00:08PM +0200, Peter Zijlstra wrote:
> > > On Mon, Jul 02, 2018 at 01:30:14AM +0800, Guo Ren wrote:
> > > > +#ifdef CONFIG_CPU_HAS_LDSTEX
> > > > +ENTRY(csky_cmpxchg)
> > > > +	USPTOKSP
> > > > +	mfcr	a3, epc
> > > > +	INCTRAP	a3
> > > > +
> > > > +	subi    sp, 8
> > > > +	stw     a3, (sp, 0)
> > > > +	mfcr    a3, epsr
> > > > +	stw     a3, (sp, 4)
> > > > +
> > > > +	psrset	ee
> > > > +1:
> > > > +	ldex	a3, (a2)
> > > > +	cmpne	a0, a3
> > > > +	bt16	2f
> > > > +	mov	a3, a1
> > > > +	stex	a3, (a2)
> > > > +	bez	a3, 1b
> > > > +2:
> > > > +	sync.is
> > > > +	mvc	a0
> > > > +	ldw	a3, (sp, 0)
> > > > +	mtcr	a3, epc
> > > > +	ldw     a3, (sp, 4)
> > > > +	mtcr	a3, epsr
> > > > +	addi	sp, 8
> > > > +	KSPTOUSP
> > > > +	rte
> > > > +END(csky_cmpxchg)
> > > > +#else
> > > 
> > > Please explain... if the CPU has LDEX/STEX, then _why_ do you need this?
> > Our libc use csky_cmpxchg and we want it compatible. Of course, we'll
> > also implement the ldex/stex atomic operations in libs in future.
> 
> I would strongly suggest not providing this syscall on SMP systems from
> the get go. There is no point in starting with legacy problems without
> an actual legacy.
Ok.
 

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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-06 12:03       ` Peter Zijlstra
  2018-07-06 13:01         ` Peter Zijlstra
@ 2018-07-06 14:06         ` Guo Ren
  1 sibling, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-06 14:06 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Fri, Jul 06, 2018 at 02:03:23PM +0200, Peter Zijlstra wrote:
> > > Test-and-set with MB acting as ACQUIRE, ok.
> > Em ... Ok, I'll try to use test-and-set function instead of it.
> 
> "test-and-set" is just the name of this type of spinlock implementation.
> 
> You _could_ use the linux test_and_set bitop, but those are defined on
> unsigned long and spinlock_t is generally assumed to be of unsigned int
> size.
> 
> Go with the ticket locks as per below.
Ok, I'll learn it.

> > Ok, I'll try to implement ticket lock in next version patch.
> 
> If you need inspiration, look at:
> 
arch/arm/include/asm/spinlock.h
> 
> Or look at the current version of that file and ignore the LSE version.
> 
> Note that unlock is a store half-word (u16), not having seen your arch
> manual yet I don't know if you even have that.
Nice tips, thank you very much.

 Guo Ren


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

* Re: [PATCH V2 16/19] csky: SMP support
  2018-07-06 12:26         ` Guo Ren
@ 2018-07-06 16:21           ` Mark Rutland
  2018-07-07  6:16             ` Guo Ren
  0 siblings, 1 reply; 88+ messages in thread
From: Mark Rutland @ 2018-07-06 16:21 UTC (permalink / raw)
  To: Guo Ren
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Fri, Jul 06, 2018 at 08:26:31PM +0800, Guo Ren wrote:
> On Fri, Jul 06, 2018 at 12:43:52PM +0100, Mark Rutland wrote:
> > Please see the devicetree spec [1], section 2.3.4. Valid values are:
> > 
> > * "okay" // equivalent to no status property present
> > * "disabled"
> > * "fail"
> > * "fail-sss"
> Nice tip, thx.
> 
> > I'm a bit confused. You write (1 << cpu) into cv<29, 0>, to enable a
> > particular CPU, so I assume that bit uniquely identifies a CPU,
> Yes, you're right and cr<29, 0>'s bit uniquely identifies a cpu.
> 
> > and
> > therefore the reg is some unique ID for the CPU.
> static int csky_of_cpu(struct device_node *node)
> {
> 	const char *status;
> 
> 	if (of_property_read_string(node, "status", &status))
> 		status = "okay";
> 
> 	if (strcmp(status, "disabled") == 0)
> 		goto error;
> 
> 	return 1;
> error:
> 	return 0;
> }

Please don't open-code this. Use of_device_is_available(), which checks
the status property itself. e.g.

void __init setup_smp(void)
{
	struct device_node *node = NULL;

	while ((node = of_find_node_by_type(node, "cpu"))) {
		if (!of_device_is_available(node))
			continue;

		...
	}
}

> void __init setup_smp(void)
> {
> 	struct device_node *node = NULL;
> 	int i = 0;
> 
> 	while ((node = of_find_node_by_type(node, "cpu"))) {
> 		if (!csky_of_cpu(node))
> 			continue;
> 
> 		set_cpu_possible(i, true);
> 		set_cpu_present(i, true);
> 
> 		i++;
> 	}
> }
> Hmm?
> 
> No <reg> in next version patch, it's no use.

Please use the reg property, you need it to describe which particular
CPUs are available.

You probably also want a mapping from Linux logical CPU id to your
physical CPU id, and a sanity check on this. See arm64 for an example.

> > I see.
> > 
> > Is this SMP bringup mechanism architectual, or are you likely to need
> > another mechanism to turn on CPUs on future chips?
> It's the only SMP bringup mechanism architectual for C-SKY SMP. There is
> no another way in future and SOC vendor couldn't change it.
> 
> > You probably want to use an enable-method property to describe this.
> No, thx.

Fair enough.

Thanks,
Mark.

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

* Re: [PATCH V2 16/19] csky: SMP support
  2018-07-06 16:21           ` Mark Rutland
@ 2018-07-07  6:16             ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-07  6:16 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Fri, Jul 06, 2018 at 05:21:00PM +0100, Mark Rutland wrote:
> Please don't open-code this. Use of_device_is_available(), which checks
> the status property itself. e.g.
> 
> void __init setup_smp(void)
> {
> 	struct device_node *node = NULL;
> 
> 	while ((node = of_find_node_by_type(node, "cpu"))) {
> 		if (!of_device_is_available(node))
> 			continue;
> 
> 		...
> 	}
> }
Ok, approve.

> Please use the reg property, you need it to describe which particular
> CPUs are available.
> 
> You probably also want a mapping from Linux logical CPU id to your
> physical CPU id, and a sanity check on this. See arm64 for an example.
Yes, you are right. Reg property could determine which bit of CPU in
cr<0, 29> could be booted.

Thx for the tips.

 Guo Ren


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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-06 11:56       ` Peter Zijlstra
  2018-07-06 12:17         ` Peter Zijlstra
@ 2018-07-07  7:42         ` Guo Ren
  2018-07-07 19:54           ` Andrea Parri
  1 sibling, 1 reply; 88+ messages in thread
From: Guo Ren @ 2018-07-07  7:42 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu,
	Will Deacon

On Fri, Jul 06, 2018 at 01:56:14PM +0200, Peter Zijlstra wrote:
> That's how LL/SC works. What I was asking is if they have any effect on
> memory ordering. Some architectures have LL/SC imply memory ordering,
> most do not.
> 
> Going by your spinlock implementation they don't imply any memory
> ordering.
ldex/stex don't imply any memory ordering.

> 
> > > The mandated semantics for xchg() / cmpxchg() is an effective smp_mb()
> > > before _and_ after.
> > 
> > 	switch (size) {						\
> > 	case 4:							\
> > 		smp_mb();					\
> > 		asm volatile (					\
> > 		"1:	ldex.w		%0, (%3) \n"		\
> > 		"	mov		%1, %2   \n"		\
> > 		"	stex.w		%1, (%3) \n"		\
> > 		"	bez		%1, 1b   \n"		\
> > 			: "=&r" (__ret), "=&r" (tmp)		\
> > 			: "r" (__new), "r"(__ptr)		\
> > 			: "memory");				\
> > 		smp_mb();					\
> > 		break;						\
> > Hmm?
> > But I couldn't undertand what's wrong without the 1th smp_mb()?
> > 1th smp_mb will make all ld/st finish before ldex.w. Is it necessary?
> 
> Yes.
> 
> 	CPU0			CPU1
> 
> 	r1 = READ_ONCE(x);	WRITE_ONCE(y, 1);
> 	r2 = xchg(&y, 2);	smp_store_release(&x, 1);
> 
> must not allow: r1==1 && r2==0
CPU1 smp_store_release could be finished before WRITE_ONCE, so r1=1 &&
r2=0?
 
> > > The above implementation suggests LDEX implies a SYNC.IS, is this
> > > correct?
> > No, ldex doesn't imply a sync.is.
> 
> Right, as per the spinlock emails, then your proposed primitives are
> incorrect.
Yes, approve.

 Guo Ren

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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-06 12:17         ` Peter Zijlstra
@ 2018-07-07  8:08           ` Guo Ren
  2018-07-07 20:10             ` Andrea Parri
  0 siblings, 1 reply; 88+ messages in thread
From: Guo Ren @ 2018-07-07  8:08 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu,
	Will Deacon

On Fri, Jul 06, 2018 at 02:17:16PM +0200, Peter Zijlstra wrote:
> > 
> > 	CPU0			CPU1
> > 
> > 	r1 = READ_ONCE(x);	WRITE_ONCE(y, 1);
> > 	r2 = xchg(&y, 2);	smp_store_release(&x, 1);
> > 
> > must not allow: r1==1 && r2==0
> 
> Also, since you said "SYNC.IS" is a pipeline flush, those
> instruction-sync primitives normally do not imply a store-buffer flush,
> does yours? If not it is not a valid smp_mb() implementation.
Sync.is will flush pipeline and store-buffer.

"sync"	means completion memory barrier.
"i"	means flush cpu pipeline.
"s"	means sharable to other cpus.

> 
> Notably:
> 
> 	CPU0				CPU1
> 
> 	WRITE_ONCE(x, 1);		WRITE_ONCE(y, 1);
> 	smp_mb();			smp_mb();
> 	r0 = READ_ONCE(y);		r1 = READ_ONCE(x);
> 
> must not allow: r0==0 && r1==0
> 
> Which would be possible with a regular instruction-sync barrier, but
> must absolutely not be true with a full memory barrier.
> 
> (and you can replace the smp_mb(); r = READ_ONCE(); with r = xchg() to
> again see why you need that first smp_mb()).

	CPU0			CPU1

	WRITE_ONCE(x, 1)	WRITE_ONCE(y, 1)
	r0 = xchg(&y, 2)	r1 = xchg(&x, 2)

must not allow: r0==0 && r1==0
So we must add a smp_mb between WRITE_ONCE() and xchg(), right?

 Guo Ren


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

* Re: [PATCH V2 06/19] csky: Cache and TLB routines
  2018-07-05 17:40   ` Peter Zijlstra
@ 2018-07-07 11:51     ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-07 11:51 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu,
	Will Deacon

On Thu, Jul 05, 2018 at 07:40:25PM +0200, Peter Zijlstra wrote:
> > +#ifdef CONFIG_SMP
> > +#define mb()	asm volatile ("sync.is":::"memory")
> > +#else
> > +#define mb()	asm volatile ("sync":::"memory")
> > +#endif
> 
> This is very suspect, please elaborate.
> 
> What I would've expected is:
> 
> #define mb() asm volatile ("sync" ::: "memory")
> 
> #ifdef CONFIG_SMP
> #define __smp_mb() asm volatile ("sync.is" ::: "memory")
> #endif
> 
> Is that in fact what you meant?
> 
> Do you have a reference to your architecture manual and memory model
> description somewhere?
I'll fixup it in next version patch.


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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-07  7:42         ` Guo Ren
@ 2018-07-07 19:54           ` Andrea Parri
  2018-07-08  0:39             ` Guo Ren
  0 siblings, 1 reply; 88+ messages in thread
From: Andrea Parri @ 2018-07-07 19:54 UTC (permalink / raw)
  To: Guo Ren
  Cc: Peter Zijlstra, linux-arch, linux-kernel, tglx, daniel.lezcano,
	jason, arnd, c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx,
	green.hu, Will Deacon

Hi Guo,

On Sat, Jul 07, 2018 at 03:42:10PM +0800, Guo Ren wrote:
> On Fri, Jul 06, 2018 at 01:56:14PM +0200, Peter Zijlstra wrote:
> > 	CPU0			CPU1
> > 
> > 	r1 = READ_ONCE(x);	WRITE_ONCE(y, 1);
> > 	r2 = xchg(&y, 2);	smp_store_release(&x, 1);
> > 
> > must not allow: r1==1 && r2==0
> CPU1 smp_store_release could be finished before WRITE_ONCE, so r1=1 &&
> r2=0?

The emphasis is on the "must": your implementation __must__ prevent this
from happening (say, by inserting memory barriers in smp_store_release());
if your implementation allows the state (r1==1 && r2==0), then the imple-
mentation is incorrect.

I'd suggest you have a look at the Linux-kernel memory consistency model
documentation and the associated tools, starting with:

  Documentation/memory-barriers.txt
  tools/memory-model/

(and please do not hesitate to ask questions about them, if something is
 unclear).

  Andrea

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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-07  8:08           ` Guo Ren
@ 2018-07-07 20:10             ` Andrea Parri
  2018-07-08  1:05               ` Guo Ren
  0 siblings, 1 reply; 88+ messages in thread
From: Andrea Parri @ 2018-07-07 20:10 UTC (permalink / raw)
  To: Guo Ren
  Cc: Peter Zijlstra, linux-arch, linux-kernel, tglx, daniel.lezcano,
	jason, arnd, c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx,
	green.hu, Will Deacon

On Sat, Jul 07, 2018 at 04:08:47PM +0800, Guo Ren wrote:
> On Fri, Jul 06, 2018 at 02:17:16PM +0200, Peter Zijlstra wrote:

> 	CPU0			CPU1
> 
> 	WRITE_ONCE(x, 1)	WRITE_ONCE(y, 1)
> 	r0 = xchg(&y, 2)	r1 = xchg(&x, 2)
> 
> must not allow: r0==0 && r1==0
> So we must add a smp_mb between WRITE_ONCE() and xchg(), right?

The state (r0==0 && r1==0) _must_ not be allowed in the above snippet (so,
even without the additional smp_mb() between WRITE_ONCE() and xchg()).  In
informal terms, xchg() provides the smp_mb().

Compare implementations of xchg() and xchg_relaxed().  The following could
also be helpful (in addition to the references pointed out earlier):

  Documentation/atomic_t.txt

  Andrea


> 
>  Guo Ren
> 

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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-07 19:54           ` Andrea Parri
@ 2018-07-08  0:39             ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-08  0:39 UTC (permalink / raw)
  To: Andrea Parri
  Cc: Peter Zijlstra, linux-arch, linux-kernel, tglx, daniel.lezcano,
	jason, arnd, c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx,
	green.hu, Will Deacon

On Sat, Jul 07, 2018 at 09:54:37PM +0200, Andrea Parri wrote:
> Hi Guo,
> 
> On Sat, Jul 07, 2018 at 03:42:10PM +0800, Guo Ren wrote:
> > On Fri, Jul 06, 2018 at 01:56:14PM +0200, Peter Zijlstra wrote:
> > > 	CPU0			CPU1
> > > 
> > > 	r1 = READ_ONCE(x);	WRITE_ONCE(y, 1);
> > > 	r2 = xchg(&y, 2);	smp_store_release(&x, 1);
> > > 
> > > must not allow: r1==1 && r2==0
> > CPU1 smp_store_release could be finished before WRITE_ONCE, so r1=1 &&
> > r2=0?
> 
> The emphasis is on the "must": your implementation __must__ prevent this
> from happening (say, by inserting memory barriers in smp_store_release());
> if your implementation allows the state (r1==1 && r2==0), then the imple-
> mentation is incorrect.
Ok, Got it.

> I'd suggest you have a look at the Linux-kernel memory consistency model
> documentation and the associated tools, starting with:
> 
>   Documentation/memory-barriers.txt
>   tools/memory-model/
Thx for the tips.

> (and please do not hesitate to ask questions about them, if something is
>  unclear).
I'll. Thx again.

 Guo Ren

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

* Re: [PATCH V2 11/19] csky: Atomic operations
  2018-07-07 20:10             ` Andrea Parri
@ 2018-07-08  1:05               ` Guo Ren
  0 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-08  1:05 UTC (permalink / raw)
  To: Andrea Parri
  Cc: Peter Zijlstra, linux-arch, linux-kernel, tglx, daniel.lezcano,
	jason, arnd, c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx,
	green.hu, Will Deacon

On Sat, Jul 07, 2018 at 10:10:24PM +0200, Andrea Parri wrote:
> On Sat, Jul 07, 2018 at 04:08:47PM +0800, Guo Ren wrote:
> > On Fri, Jul 06, 2018 at 02:17:16PM +0200, Peter Zijlstra wrote:
> 
> > 	CPU0			CPU1
> > 
> > 	WRITE_ONCE(x, 1)	WRITE_ONCE(y, 1)
> > 	r0 = xchg(&y, 2)	r1 = xchg(&x, 2)
> > 
> > must not allow: r0==0 && r1==0
> > So we must add a smp_mb between WRITE_ONCE() and xchg(), right?
> 
> The state (r0==0 && r1==0) _must_ not be allowed in the above snippet (so,
> even without the additional smp_mb() between WRITE_ONCE() and xchg()).  In
> informal terms, xchg() provides the smp_mb().
Got it, thx.

> Compare implementations of xchg() and xchg_relaxed().  The following could
> also be helpful (in addition to the references pointed out earlier):
> 
>   Documentation/atomic_t.txt
Thx for the tip.

 Guo Ren

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

* Re: [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port
  2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
                   ` (18 preceding siblings ...)
  2018-07-01 17:30 ` [PATCH V2 19/19] irqchip: add C-SKY irqchip drivers Guo Ren
@ 2018-07-11  9:51 ` David Howells
  2018-07-12 12:51   ` Guo Ren
  19 siblings, 1 reply; 88+ messages in thread
From: David Howells @ 2018-07-11  9:51 UTC (permalink / raw)
  To: Guo Ren
  Cc: dhowells, linux-arch, linux-kernel, tglx, daniel.lezcano, jason,
	arnd, c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx,
	green.hu

Can you say what the --target tuple should be so that I can add the arch to my
collection of Fedora cross-binutils and cross-gcc tools built from upstream
binutils and gcc sources?

Thanks,
David

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

* Re: [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port
  2018-07-11  9:51 ` [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port David Howells
@ 2018-07-12 12:51   ` Guo Ren
  2018-07-12 16:04       ` Sandra Loosemore
  2018-07-13 10:23     ` David Howells
  0 siblings, 2 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-12 12:51 UTC (permalink / raw)
  To: David Howells, sandra
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On Wed, Jul 11, 2018 at 10:51:33AM +0100, David Howells wrote:
> Can you say what the --target tuple should be so that I can add the arch to my
> collection of Fedora cross-binutils and cross-gcc tools built from upstream
> binutils and gcc sources?
Metor Graghics are helping us upstream gcc and binutils.

@Sandra,

Could you help me to reply the question?


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

* Re: [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port
  2018-07-12 12:51   ` Guo Ren
@ 2018-07-12 16:04       ` Sandra Loosemore
  2018-07-13 10:23     ` David Howells
  1 sibling, 0 replies; 88+ messages in thread
From: Sandra Loosemore @ 2018-07-12 16:04 UTC (permalink / raw)
  To: Guo Ren, David Howells
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On 07/12/2018 06:51 AM, Guo Ren wrote:
> On Wed, Jul 11, 2018 at 10:51:33AM +0100, David Howells wrote:
>> Can you say what the --target tuple should be so that I can add the arch to my
>> collection of Fedora cross-binutils and cross-gcc tools built from upstream
>> binutils and gcc sources?
> Metor Graghics are helping us upstream gcc and binutils.
> 
> @Sandra,
> 
> Could you help me to reply the question?

Neither binutils nor gcc support for C-SKY are in the upstream 
repositories yet.  We should be resubmitting the binutils port soon 
(with bug fixes to address the test failures that caused it to be 
rejected the last time), and the gcc port will follow that shortly.

The target triplets we have been testing are csky-elf, csky-linux-gnu, 
and csky-linux-uclibc.  Note that the gcc port will only support v2 
processors/ABI so that is the default ABI for these triplets.

I'm not familiar with the Fedora tools, but to build a complete 
toolchain you'll need library support as well and I'm not sure what the 
submission status/plans for that are.  E.g. Mentor did a newlib/libgloss 
port for local testing of the ELF toolchain and provided it to C-SKY, 
but pushing that to the upstream repository ourselves is not on our todo 
list.

-Sandra

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

* Re: [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port
@ 2018-07-12 16:04       ` Sandra Loosemore
  0 siblings, 0 replies; 88+ messages in thread
From: Sandra Loosemore @ 2018-07-12 16:04 UTC (permalink / raw)
  To: Guo Ren, David Howells
  Cc: linux-arch, linux-kernel, tglx, daniel.lezcano, jason, arnd,
	c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx, green.hu

On 07/12/2018 06:51 AM, Guo Ren wrote:
> On Wed, Jul 11, 2018 at 10:51:33AM +0100, David Howells wrote:
>> Can you say what the --target tuple should be so that I can add the arch to my
>> collection of Fedora cross-binutils and cross-gcc tools built from upstream
>> binutils and gcc sources?
> Metor Graghics are helping us upstream gcc and binutils.
> 
> @Sandra,
> 
> Could you help me to reply the question?

Neither binutils nor gcc support for C-SKY are in the upstream 
repositories yet.  We should be resubmitting the binutils port soon 
(with bug fixes to address the test failures that caused it to be 
rejected the last time), and the gcc port will follow that shortly.

The target triplets we have been testing are csky-elf, csky-linux-gnu, 
and csky-linux-uclibc.  Note that the gcc port will only support v2 
processors/ABI so that is the default ABI for these triplets.

I'm not familiar with the Fedora tools, but to build a complete 
toolchain you'll need library support as well and I'm not sure what the 
submission status/plans for that are.  E.g. Mentor did a newlib/libgloss 
port for local testing of the ELF toolchain and provided it to C-SKY, 
but pushing that to the upstream repository ourselves is not on our todo 
list.

-Sandra

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

* Re: [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port
  2018-07-12 16:04       ` Sandra Loosemore
  (?)
@ 2018-07-13  1:30       ` Guo Ren
  -1 siblings, 0 replies; 88+ messages in thread
From: Guo Ren @ 2018-07-13  1:30 UTC (permalink / raw)
  To: Sandra Loosemore
  Cc: David Howells, linux-arch, linux-kernel, tglx, daniel.lezcano,
	jason, arnd, c-sky_gcc_upstream, gnu-csky, thomas.petazzoni, wbx,
	green.hu

On Thu, Jul 12, 2018 at 10:04:10AM -0600, Sandra Loosemore wrote:
> On 07/12/2018 06:51 AM, Guo Ren wrote:
> >On Wed, Jul 11, 2018 at 10:51:33AM +0100, David Howells wrote:
> >>Can you say what the --target tuple should be so that I can add the arch to my
> >>collection of Fedora cross-binutils and cross-gcc tools built from upstream
> >>binutils and gcc sources?
> >Metor Graghics are helping us upstream gcc and binutils.
> >
> >@Sandra,
> >
> >Could you help me to reply the question?
> 
> Neither binutils nor gcc support for C-SKY are in the upstream repositories
> yet.  We should be resubmitting the binutils port soon (with bug fixes to
> address the test failures that caused it to be rejected the last time), and
> the gcc port will follow that shortly.
> 
> The target triplets we have been testing are csky-elf, csky-linux-gnu, and
> csky-linux-uclibc.  Note that the gcc port will only support v2
> processors/ABI so that is the default ABI for these triplets.
> 
> I'm not familiar with the Fedora tools, but to build a complete toolchain
> you'll need library support as well and I'm not sure what the submission
> status/plans for that are.  E.g. Mentor did a newlib/libgloss port for local
> testing of the ELF toolchain and provided it to C-SKY, but pushing that to
> the upstream repository ourselves is not on our todo list.
> 
> -Sandra

Thank you, Sandra.

 Guo Ren

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

* Re: [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port
  2018-07-12 12:51   ` Guo Ren
  2018-07-12 16:04       ` Sandra Loosemore
@ 2018-07-13 10:23     ` David Howells
  1 sibling, 0 replies; 88+ messages in thread
From: David Howells @ 2018-07-13 10:23 UTC (permalink / raw)
  To: Sandra Loosemore
  Cc: dhowells, Guo Ren, linux-arch, linux-kernel, tglx,
	daniel.lezcano, jason, arnd, c-sky_gcc_upstream, gnu-csky,
	thomas.petazzoni, wbx, green.hu

Sandra Loosemore <sandra@codesourcery.com> wrote:

> I'm not familiar with the Fedora tools, but to build a complete toolchain
> you'll need library support as well and I'm not sure what the submission
> status/plans for that are.

The idea behind the cross-gcc package in Fedora is that it's for kernel builds
and bootloader-type things only.  It builds libgcc, but doesn't use kernel
headers or a C library[*] as this enormously simplifies things.

The reasons being:

 (1) Not all arches can use the same set of C libraries (some can't use glibc
     and some don't have a uClibc port).

 (2) I can only build each individual compiler against a single C library - so
     if you have two or more incompatible environments, you're out of luck -
     I can only use one.

 (3) Building lots more compilers for individual environments would massively
     increase the build size and time.  A full cross-gcc build now takes the
     best part of a day to build.

[*] Yes, there's one exception: it builds the arm compiler against an arm
    cross-glibc - not my idea.

David

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

end of thread, other threads:[~2018-07-13 10:23 UTC | newest]

Thread overview: 88+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-01 17:30 [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port Guo Ren
2018-07-01 17:30 ` [PATCH V2 01/19] csky: Build infrastructure Guo Ren
2018-07-01 21:01   ` Randy Dunlap
2018-07-02  1:13     ` Guo Ren
2018-07-03  3:33   ` Rob Herring
2018-07-03  9:14     ` Guo Ren
2018-07-03 16:03   ` Arnd Bergmann
2018-07-04 11:40     ` Guo Ren
2018-07-01 17:30 ` [PATCH V2 02/19] csky: defconfig Guo Ren
2018-07-03  3:16   ` Rob Herring
2018-07-03  8:31     ` Guo Ren
2018-07-01 17:30 ` [PATCH V2 03/19] csky: Kernel booting Guo Ren
2018-07-01 17:30 ` [PATCH V2 04/19] csky: Exception handling Guo Ren
2018-07-01 17:30 ` [PATCH V2 05/19] csky: System Call Guo Ren
2018-07-03 19:53   ` Arnd Bergmann
2018-07-04 11:49     ` Guo Ren
2018-07-04 21:04       ` Arnd Bergmann
2018-07-05  5:38         ` Guo Ren
2018-07-01 17:30 ` [PATCH V2 06/19] csky: Cache and TLB routines Guo Ren
2018-07-05 17:40   ` Peter Zijlstra
2018-07-07 11:51     ` Guo Ren
2018-07-01 17:30 ` [PATCH V2 07/19] csky: MMU and page table management Guo Ren
2018-07-02 13:29   ` Christoph Hellwig
2018-07-03  2:53     ` Guo Ren
2018-07-01 17:30 ` [PATCH V2 08/19] csky: Process management and Signal Guo Ren
2018-07-01 17:30 ` [PATCH V2 09/19] csky: VDSO and rt_sigreturn Guo Ren
2018-07-01 17:30 ` [PATCH V2 10/19] csky: IRQ handling Guo Ren
2018-07-01 17:30 ` [PATCH V2 11/19] csky: Atomic operations Guo Ren
2018-07-05 17:50   ` Peter Zijlstra
2018-07-06 11:01     ` Guo Ren
2018-07-06 11:56       ` Peter Zijlstra
2018-07-06 12:17         ` Peter Zijlstra
2018-07-07  8:08           ` Guo Ren
2018-07-07 20:10             ` Andrea Parri
2018-07-08  1:05               ` Guo Ren
2018-07-07  7:42         ` Guo Ren
2018-07-07 19:54           ` Andrea Parri
2018-07-08  0:39             ` Guo Ren
2018-07-05 17:59   ` Peter Zijlstra
2018-07-06 11:44     ` Guo Ren
2018-07-06 12:03       ` Peter Zijlstra
2018-07-06 13:01         ` Peter Zijlstra
2018-07-06 14:06         ` Guo Ren
2018-07-05 18:00   ` Peter Zijlstra
2018-07-06 11:48     ` Guo Ren
2018-07-06 12:05       ` Peter Zijlstra
2018-07-06 13:46         ` Guo Ren
2018-07-01 17:30 ` [PATCH V2 12/19] csky: ELF and module probe Guo Ren
2018-07-01 17:30 ` [PATCH V2 13/19] csky: Library functions Guo Ren
2018-07-03 20:04   ` Arnd Bergmann
2018-07-04 10:51     ` Guo Ren
2018-07-01 17:30 ` [PATCH V2 14/19] csky: User access Guo Ren
2018-07-01 17:30 ` [PATCH V2 15/19] csky: Debug and Ptrace GDB Guo Ren
2018-07-01 17:30 ` [PATCH V2 16/19] csky: SMP support Guo Ren
2018-07-05 18:05   ` Peter Zijlstra
2018-07-06  6:07     ` Guo Ren
2018-07-06  9:39       ` Peter Zijlstra
2018-07-06 13:22         ` Guo Ren
2018-07-06  5:24   ` Mark Rutland
2018-07-06 11:32     ` Guo Ren
2018-07-06 11:43       ` Mark Rutland
2018-07-06 12:26         ` Guo Ren
2018-07-06 16:21           ` Mark Rutland
2018-07-07  6:16             ` Guo Ren
2018-07-01 17:30 ` [PATCH V2 17/19] csky: Misc headers Guo Ren
2018-07-01 17:30 ` [PATCH V2 18/19] clocksource: add C-SKY clocksource drivers Guo Ren
2018-07-01 17:34   ` Guo Ren
2018-07-03  9:39   ` Thomas Gleixner
2018-07-04 10:49     ` Guo Ren
2018-07-04 14:35       ` Thomas Gleixner
2018-07-05  5:03         ` Guo Ren
2018-07-04 17:05   ` Daniel Lezcano
2018-07-05  3:30     ` Guo Ren
2018-07-05  9:23       ` Daniel Lezcano
2018-07-06  5:57         ` Guo Ren
2018-07-01 17:30 ` [PATCH V2 19/19] irqchip: add C-SKY irqchip drivers Guo Ren
2018-07-03  3:27   ` Rob Herring
2018-07-03  7:38     ` Guo Ren
2018-07-03  9:28   ` Thomas Gleixner
2018-07-04  5:08     ` Guo Ren
2018-07-04  6:43       ` Thomas Gleixner
2018-07-04 11:58         ` Guo Ren
2018-07-11  9:51 ` [PATCH V2 00/19] C-SKY(csky) Linux Kernel Port David Howells
2018-07-12 12:51   ` Guo Ren
2018-07-12 16:04     ` Sandra Loosemore
2018-07-12 16:04       ` Sandra Loosemore
2018-07-13  1:30       ` Guo Ren
2018-07-13 10:23     ` David Howells

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.