All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/31] Andes(nds32) Linux Kernel Port
@ 2017-11-08  5:54 Greentime Hu
  2017-11-08  5:54 ` [PATCH 01/31] nds32: Assembly macros and definitions Greentime Hu
                   ` (32 more replies)
  0 siblings, 33 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:54 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: Greentime Hu

This patchset adds core architecture support to Linux for Andestech's
N13, N15, D15, N10, D10 processor cores.

Based on the 16/32-bit AndeStar RISC-like architecture, we designed the
configurable AndesCore series of embedded processor families. AndesCores
range from highly performance-efficient small-footprint cores for
microcontrollers and deeply-embedded applications to 1GHz+ cores running
Linux, covering general-purpose N-series cores for a wide range of computing
need, DSP-capable D-series cores for digital signal control,
instruction-extensible E-series cores for application-specific acceleration,
and secure S-series cores for best protection of the most valuable.

The patches are based on v4.14-rc8, and can also be found in the
following git tree:
  https://github.com/andestech/linux.git nds32-4.14-rc8

The build script and toolchain repositories are able to be found here:
  https://github.com/andestech/build_script.git

Freely available instruction set and architecture overview documents can
be found on the following page:
  http://www.andestech.com/product.php?cls=9


Vincent Ren-Wei Chen and I will maintain this port. Thanks to everyone who
helped us and contributed to it. :) Any feedback is welcome.

Greentime Hu (31):
  nds32: Assembly macros and definitions
  nds32: Kernel booting and initialization
  nds32: Support early_printk
  nds32: Exception handling
  nds32: MMU definitions
  nds32: MMU initialization
  nds32: MMU fault handling and page table management
  nds32: Cache and TLB routines
  nds32: Process management
  nds32: IRQ handling
  nds32: Atomic operations
  nds32: Device specific operations
  nds32: DMA mapping API
  nds32: ELF definitions
  nds32: System calls handling
  nds32: VDSO support
  nds32: Signal handling support
  nds32: Library functions
  nds32: Debugging support
  nds32: L2 cache support
  nds32: Loadable modules
  nds32: Generic timers support
  nds32: Device tree support
  nds32: Miscellaneous header files
  nds32: defconfig
  nds32: Build infrastructure
  dt-bindings: interrupt-controller: Andestech Internal Vector
    Interrupt Controller
  irqchip: Andestech Internal Vector Interrupt Controller driver
  MAINTAINERS: Add nds32
  dt-bindings: nds32 CPU Bindings
  net: faraday add nds32 support.

 .../interrupt-controller/andestech,ativic32.txt    |   27 +
 Documentation/devicetree/bindings/nds32/cpus.txt   |   33 +
 MAINTAINERS                                        |    9 +
 arch/nds32/Kconfig                                 |  107 +++
 arch/nds32/Kconfig.cpu                             |  100 ++
 arch/nds32/Kconfig.debug                           |   14 +
 arch/nds32/Makefile                                |   60 ++
 arch/nds32/boot/Makefile                           |   15 +
 arch/nds32/boot/dts/Makefile                       |    8 +
 arch/nds32/boot/dts/ae3xx.dts                      |   55 ++
 arch/nds32/boot/dts/ag101p.dts                     |   60 ++
 arch/nds32/configs/ae3xx_defconfig                 |  110 +++
 arch/nds32/configs/ag101p_defconfig                |  109 +++
 arch/nds32/include/asm/Kbuild                      |   54 ++
 arch/nds32/include/asm/assembler.h                 |   52 ++
 arch/nds32/include/asm/bitfield.h                  |  982 ++++++++++++++++++++
 arch/nds32/include/asm/cache.h                     |   25 +
 arch/nds32/include/asm/cache_info.h                |   26 +
 arch/nds32/include/asm/cacheflush.h                |   57 ++
 arch/nds32/include/asm/current.h                   |   25 +
 arch/nds32/include/asm/delay.h                     |   51 +
 arch/nds32/include/asm/dma-mapping.h               |   27 +
 arch/nds32/include/asm/elf.h                       |  192 ++++
 arch/nds32/include/asm/fixmap.h                    |   41 +
 arch/nds32/include/asm/futex.h                     |  116 +++
 arch/nds32/include/asm/highmem.h                   |   78 ++
 arch/nds32/include/asm/io.h                        |   33 +
 arch/nds32/include/asm/irqflags.h                  |   49 +
 arch/nds32/include/asm/l2_cache.h                  |  158 ++++
 arch/nds32/include/asm/linkage.h                   |   24 +
 arch/nds32/include/asm/memory.h                    |  147 +++
 arch/nds32/include/asm/mmu.h                       |   25 +
 arch/nds32/include/asm/mmu_context.h               |   81 ++
 arch/nds32/include/asm/module.h                    |   24 +
 arch/nds32/include/asm/nds32.h                     |   92 ++
 arch/nds32/include/asm/page.h                      |   78 ++
 arch/nds32/include/asm/pgalloc.h                   |  109 +++
 arch/nds32/include/asm/pgtable.h                   |  426 +++++++++
 arch/nds32/include/asm/proc-fns.h                  |   94 ++
 arch/nds32/include/asm/processor.h                 |  116 +++
 arch/nds32/include/asm/ptrace.h                    |   79 ++
 arch/nds32/include/asm/shmparam.h                  |   33 +
 arch/nds32/include/asm/spinlock.h                  |  178 ++++
 arch/nds32/include/asm/string.h                    |   30 +
 arch/nds32/include/asm/swab.h                      |   48 +
 arch/nds32/include/asm/syscall.h                   |  203 ++++
 arch/nds32/include/asm/syscalls.h                  |   27 +
 arch/nds32/include/asm/thread_info.h               |   91 ++
 arch/nds32/include/asm/tlb.h                       |   41 +
 arch/nds32/include/asm/tlbflush.h                  |   60 ++
 arch/nds32/include/asm/uaccess.h                   |  385 ++++++++
 arch/nds32/include/asm/unistd.h                    |   21 +
 arch/nds32/include/asm/vdso.h                      |   35 +
 arch/nds32/include/asm/vdso_datapage.h             |   51 +
 arch/nds32/include/uapi/asm/Kbuild                 |   26 +
 arch/nds32/include/uapi/asm/auxvec.h               |   25 +
 arch/nds32/include/uapi/asm/byteorder.h            |   26 +
 arch/nds32/include/uapi/asm/cachectl.h             |   19 +
 arch/nds32/include/uapi/asm/param.h                |   24 +
 arch/nds32/include/uapi/asm/posix_types.h          |   41 +
 arch/nds32/include/uapi/asm/ptrace.h               |   42 +
 arch/nds32/include/uapi/asm/sigcontext.h           |   73 ++
 arch/nds32/include/uapi/asm/signal.h               |   23 +
 arch/nds32/include/uapi/asm/unistd.h               |   36 +
 arch/nds32/kernel/Makefile                         |   24 +
 arch/nds32/kernel/asm-offsets.c                    |   40 +
 arch/nds32/kernel/atl2c.c                          |   77 ++
 arch/nds32/kernel/cacheinfo.c                      |   62 ++
 arch/nds32/kernel/devtree.c                        |   45 +
 arch/nds32/kernel/dma.c                            |  478 ++++++++++
 arch/nds32/kernel/early_printk.c                   |  124 +++
 arch/nds32/kernel/ex-entry.S                       |  169 ++++
 arch/nds32/kernel/ex-exit.S                        |  207 +++++
 arch/nds32/kernel/ex-scall.S                       |  146 +++
 arch/nds32/kernel/head.S                           |  211 +++++
 arch/nds32/kernel/irq.c                            |   34 +
 arch/nds32/kernel/module.c                         |  299 ++++++
 arch/nds32/kernel/nds32_ksyms.c                    |   54 ++
 arch/nds32/kernel/process.c                        |  219 +++++
 arch/nds32/kernel/ptrace.c                         |  325 +++++++
 arch/nds32/kernel/setup.c                          |  406 ++++++++
 arch/nds32/kernel/signal.c                         |  370 ++++++++
 arch/nds32/kernel/stacktrace.c                     |   60 ++
 arch/nds32/kernel/sys_nds32.c                      |   63 ++
 arch/nds32/kernel/syscall_table.c                  |   28 +
 arch/nds32/kernel/time.c                           |   22 +
 arch/nds32/kernel/traps.c                          |  442 +++++++++
 arch/nds32/kernel/vdso.c                           |  243 +++++
 arch/nds32/kernel/vdso/Makefile                    |   82 ++
 arch/nds32/kernel/vdso/datapage.S                  |   34 +
 arch/nds32/kernel/vdso/gen_vdso_offsets.sh         |   15 +
 arch/nds32/kernel/vdso/gettimeofday.c              |  260 ++++++
 arch/nds32/kernel/vdso/note.S                      |   29 +
 arch/nds32/kernel/vdso/sigreturn.S                 |   32 +
 arch/nds32/kernel/vdso/vdso.S                      |   33 +
 arch/nds32/kernel/vdso/vdso.lds.S                  |   87 ++
 arch/nds32/kernel/vmlinux.lds.S                    |   70 ++
 arch/nds32/lib/Makefile                            |    4 +
 arch/nds32/lib/copy_page.S                         |   50 +
 arch/nds32/lib/getuser.S                           |   57 ++
 arch/nds32/lib/memcpy.S                            |   93 ++
 arch/nds32/lib/memmove.S                           |   83 ++
 arch/nds32/lib/memset.S                            |   46 +
 arch/nds32/lib/memzero.S                           |   31 +
 arch/nds32/lib/putuser.S                           |   53 ++
 arch/nds32/lib/uaccess.S                           |  160 ++++
 arch/nds32/mm/Makefile                             |    7 +
 arch/nds32/mm/alignment.c                          |  564 +++++++++++
 arch/nds32/mm/cacheflush.c                         |  331 +++++++
 arch/nds32/mm/extable.c                            |   29 +
 arch/nds32/mm/fault.c                              |  420 +++++++++
 arch/nds32/mm/highmem.c                            |   92 ++
 arch/nds32/mm/init.c                               |  328 +++++++
 arch/nds32/mm/ioremap.c                            |   67 ++
 arch/nds32/mm/mm-nds32.c                           |  103 ++
 arch/nds32/mm/mmap.c                               |   88 ++
 arch/nds32/mm/proc-n13.c                           |  608 ++++++++++++
 arch/nds32/mm/tlb.c                                |   63 ++
 drivers/irqchip/Makefile                           |    1 +
 drivers/irqchip/irq-ativic32.c                     |  149 +++
 drivers/net/ethernet/faraday/Kconfig               |    6 +-
 121 files changed, 13726 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt
 create mode 100644 Documentation/devicetree/bindings/nds32/cpus.txt
 create mode 100644 arch/nds32/Kconfig
 create mode 100644 arch/nds32/Kconfig.cpu
 create mode 100644 arch/nds32/Kconfig.debug
 create mode 100644 arch/nds32/Makefile
 create mode 100644 arch/nds32/boot/Makefile
 create mode 100644 arch/nds32/boot/dts/Makefile
 create mode 100644 arch/nds32/boot/dts/ae3xx.dts
 create mode 100644 arch/nds32/boot/dts/ag101p.dts
 create mode 100644 arch/nds32/configs/ae3xx_defconfig
 create mode 100644 arch/nds32/configs/ag101p_defconfig
 create mode 100644 arch/nds32/include/asm/Kbuild
 create mode 100644 arch/nds32/include/asm/assembler.h
 create mode 100644 arch/nds32/include/asm/bitfield.h
 create mode 100644 arch/nds32/include/asm/cache.h
 create mode 100644 arch/nds32/include/asm/cache_info.h
 create mode 100644 arch/nds32/include/asm/cacheflush.h
 create mode 100644 arch/nds32/include/asm/current.h
 create mode 100644 arch/nds32/include/asm/delay.h
 create mode 100644 arch/nds32/include/asm/dma-mapping.h
 create mode 100644 arch/nds32/include/asm/elf.h
 create mode 100644 arch/nds32/include/asm/fixmap.h
 create mode 100644 arch/nds32/include/asm/futex.h
 create mode 100644 arch/nds32/include/asm/highmem.h
 create mode 100644 arch/nds32/include/asm/io.h
 create mode 100644 arch/nds32/include/asm/irqflags.h
 create mode 100644 arch/nds32/include/asm/l2_cache.h
 create mode 100644 arch/nds32/include/asm/linkage.h
 create mode 100644 arch/nds32/include/asm/memory.h
 create mode 100644 arch/nds32/include/asm/mmu.h
 create mode 100644 arch/nds32/include/asm/mmu_context.h
 create mode 100644 arch/nds32/include/asm/module.h
 create mode 100644 arch/nds32/include/asm/nds32.h
 create mode 100644 arch/nds32/include/asm/page.h
 create mode 100644 arch/nds32/include/asm/pgalloc.h
 create mode 100644 arch/nds32/include/asm/pgtable.h
 create mode 100644 arch/nds32/include/asm/proc-fns.h
 create mode 100644 arch/nds32/include/asm/processor.h
 create mode 100644 arch/nds32/include/asm/ptrace.h
 create mode 100644 arch/nds32/include/asm/shmparam.h
 create mode 100644 arch/nds32/include/asm/spinlock.h
 create mode 100644 arch/nds32/include/asm/string.h
 create mode 100644 arch/nds32/include/asm/swab.h
 create mode 100644 arch/nds32/include/asm/syscall.h
 create mode 100644 arch/nds32/include/asm/syscalls.h
 create mode 100644 arch/nds32/include/asm/thread_info.h
 create mode 100644 arch/nds32/include/asm/tlb.h
 create mode 100644 arch/nds32/include/asm/tlbflush.h
 create mode 100644 arch/nds32/include/asm/uaccess.h
 create mode 100644 arch/nds32/include/asm/unistd.h
 create mode 100644 arch/nds32/include/asm/vdso.h
 create mode 100644 arch/nds32/include/asm/vdso_datapage.h
 create mode 100644 arch/nds32/include/uapi/asm/Kbuild
 create mode 100644 arch/nds32/include/uapi/asm/auxvec.h
 create mode 100644 arch/nds32/include/uapi/asm/byteorder.h
 create mode 100644 arch/nds32/include/uapi/asm/cachectl.h
 create mode 100644 arch/nds32/include/uapi/asm/param.h
 create mode 100644 arch/nds32/include/uapi/asm/posix_types.h
 create mode 100644 arch/nds32/include/uapi/asm/ptrace.h
 create mode 100644 arch/nds32/include/uapi/asm/sigcontext.h
 create mode 100644 arch/nds32/include/uapi/asm/signal.h
 create mode 100644 arch/nds32/include/uapi/asm/unistd.h
 create mode 100644 arch/nds32/kernel/Makefile
 create mode 100644 arch/nds32/kernel/asm-offsets.c
 create mode 100644 arch/nds32/kernel/atl2c.c
 create mode 100644 arch/nds32/kernel/cacheinfo.c
 create mode 100644 arch/nds32/kernel/devtree.c
 create mode 100644 arch/nds32/kernel/dma.c
 create mode 100644 arch/nds32/kernel/early_printk.c
 create mode 100644 arch/nds32/kernel/ex-entry.S
 create mode 100644 arch/nds32/kernel/ex-exit.S
 create mode 100644 arch/nds32/kernel/ex-scall.S
 create mode 100644 arch/nds32/kernel/head.S
 create mode 100644 arch/nds32/kernel/irq.c
 create mode 100644 arch/nds32/kernel/module.c
 create mode 100644 arch/nds32/kernel/nds32_ksyms.c
 create mode 100644 arch/nds32/kernel/process.c
 create mode 100644 arch/nds32/kernel/ptrace.c
 create mode 100644 arch/nds32/kernel/setup.c
 create mode 100644 arch/nds32/kernel/signal.c
 create mode 100644 arch/nds32/kernel/stacktrace.c
 create mode 100644 arch/nds32/kernel/sys_nds32.c
 create mode 100644 arch/nds32/kernel/syscall_table.c
 create mode 100644 arch/nds32/kernel/time.c
 create mode 100644 arch/nds32/kernel/traps.c
 create mode 100644 arch/nds32/kernel/vdso.c
 create mode 100644 arch/nds32/kernel/vdso/Makefile
 create mode 100644 arch/nds32/kernel/vdso/datapage.S
 create mode 100755 arch/nds32/kernel/vdso/gen_vdso_offsets.sh
 create mode 100644 arch/nds32/kernel/vdso/gettimeofday.c
 create mode 100644 arch/nds32/kernel/vdso/note.S
 create mode 100644 arch/nds32/kernel/vdso/sigreturn.S
 create mode 100644 arch/nds32/kernel/vdso/vdso.S
 create mode 100644 arch/nds32/kernel/vdso/vdso.lds.S
 create mode 100644 arch/nds32/kernel/vmlinux.lds.S
 create mode 100644 arch/nds32/lib/Makefile
 create mode 100644 arch/nds32/lib/copy_page.S
 create mode 100644 arch/nds32/lib/getuser.S
 create mode 100644 arch/nds32/lib/memcpy.S
 create mode 100644 arch/nds32/lib/memmove.S
 create mode 100644 arch/nds32/lib/memset.S
 create mode 100644 arch/nds32/lib/memzero.S
 create mode 100644 arch/nds32/lib/putuser.S
 create mode 100644 arch/nds32/lib/uaccess.S
 create mode 100644 arch/nds32/mm/Makefile
 create mode 100644 arch/nds32/mm/alignment.c
 create mode 100644 arch/nds32/mm/cacheflush.c
 create mode 100644 arch/nds32/mm/extable.c
 create mode 100644 arch/nds32/mm/fault.c
 create mode 100644 arch/nds32/mm/highmem.c
 create mode 100644 arch/nds32/mm/init.c
 create mode 100644 arch/nds32/mm/ioremap.c
 create mode 100644 arch/nds32/mm/mm-nds32.c
 create mode 100644 arch/nds32/mm/mmap.c
 create mode 100644 arch/nds32/mm/proc-n13.c
 create mode 100644 arch/nds32/mm/tlb.c
 create mode 100644 drivers/irqchip/irq-ativic32.c

-- 
1.7.9.5

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

* [PATCH 01/31] nds32: Assembly macros and definitions
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
@ 2017-11-08  5:54 ` Greentime Hu
  2017-11-08  5:54 ` [PATCH 02/31] nds32: Kernel booting and initialization Greentime Hu
                   ` (31 subsequent siblings)
  32 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:54 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/asm/assembler.h |   52 ++
 arch/nds32/include/asm/bitfield.h  |  982 ++++++++++++++++++++++++++++++++++++
 arch/nds32/include/asm/nds32.h     |   92 ++++
 arch/nds32/kernel/asm-offsets.c    |   40 ++
 4 files changed, 1166 insertions(+)
 create mode 100644 arch/nds32/include/asm/assembler.h
 create mode 100644 arch/nds32/include/asm/bitfield.h
 create mode 100644 arch/nds32/include/asm/nds32.h
 create mode 100644 arch/nds32/kernel/asm-offsets.c

diff --git a/arch/nds32/include/asm/assembler.h b/arch/nds32/include/asm/assembler.h
new file mode 100644
index 0000000..d469af0
--- /dev/null
+++ b/arch/nds32/include/asm/assembler.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NDS32_ASSEMBLER_H__
+#define __NDS32_ASSEMBLER_H__
+
+.macro gie_disable
+	setgie.d
+	dsb
+.endm
+
+.macro gie_enable
+	setgie.e
+	dsb
+.endm
+
+.macro gie_save oldpsw
+	mfsr \oldpsw, $ir0
+	setgie.d
+        dsb
+.endm
+
+.macro gie_restore oldpsw
+	andi \oldpsw, \oldpsw, #0x1
+	beqz \oldpsw, 7001f
+	setgie.e
+	dsb
+7001:
+.endm
+
+
+#define USER(insn,  reg, addr, opr)	\
+9999:	insn  reg, addr, opr;		\
+	.section __ex_table,"a";	\
+	.align 3;			\
+	.long	9999b, 9001f;		\
+	.previous
+
+#endif /* __NDS32_ASSEMBLER_H__ */
diff --git a/arch/nds32/include/asm/bitfield.h b/arch/nds32/include/asm/bitfield.h
new file mode 100644
index 0000000..bb032ce
--- /dev/null
+++ b/arch/nds32/include/asm/bitfield.h
@@ -0,0 +1,982 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NDS32_BITFIELD_H__
+#define __NDS32_BITFIELD_H__
+/******************************************************************************
+ * cr0: CPU_VER (CPU Version Register)
+ *****************************************************************************/
+#define CPU_VER_offCFGID	0	/* Minor configuration */
+#define CPU_VER_offREV		16	/* Revision of the CPU version */
+#define CPU_VER_offCPUID	24	/* Major CPU versions */
+
+#define CPU_VER_mskCFGID	( 0xFFFF  << CPU_VER_offCFGID )
+#define CPU_VER_mskREV		( 0xFF  << CPU_VER_offREV )
+#define CPU_VER_mskCPUID	( 0xFF  << CPU_VER_offCPUID )
+
+/******************************************************************************
+ * cr1: ICM_CFG (Instruction Cache/Memory Configuration Register)
+ *****************************************************************************/
+#define ICM_CFG_offISET		0	/* I-cache sets (# of cache lines) per way */
+#define ICM_CFG_offIWAY		3	/* I-cache ways */
+#define ICM_CFG_offISZ		6	/* I-cache line size */
+#define ICM_CFG_offILCK		9	/* I-cache locking support */
+#define ICM_CFG_offILMB		10	/* On-chip ILM banks */
+#define ICM_CFG_offBSAV		13	/* ILM base register alignment version */
+/* bit 15:31 reserved */
+
+#define ICM_CFG_mskISET		( 0x7  << ICM_CFG_offISET )
+#define ICM_CFG_mskIWAY		( 0x7  << ICM_CFG_offIWAY )
+#define ICM_CFG_mskISZ		( 0x7  << ICM_CFG_offISZ )
+#define ICM_CFG_mskILCK		( 0x1  << ICM_CFG_offILCK )
+#define ICM_CFG_mskILMB		( 0x7  << ICM_CFG_offILMB )
+#define ICM_CFG_mskBSAV		( 0x3  << ICM_CFG_offBSAV )
+
+/******************************************************************************
+ * cr2: DCM_CFG (Data Cache/Memory Configuration Register)
+ *****************************************************************************/
+#define DCM_CFG_offDSET		0	/* D-cache sets (# of cache lines) per way */
+#define DCM_CFG_offDWAY		3	/* D-cache ways */
+#define DCM_CFG_offDSZ		6	/* D-cache line size */
+#define DCM_CFG_offDLCK		9	/* D-cache locking support */
+#define DCM_CFG_offDLMB		10	/* On-chip DLM banks */
+#define DCM_CFG_offBSAV		13	/* DLM base register alignment version */
+/* bit 15:31 reserved */
+
+#define DCM_CFG_mskDSET		( 0x7  << DCM_CFG_offDSET )
+#define DCM_CFG_mskDWAY		( 0x7  << DCM_CFG_offDWAY )
+#define DCM_CFG_mskDSZ		( 0x7  << DCM_CFG_offDSZ )
+#define DCM_CFG_mskDLCK		( 0x1  << DCM_CFG_offDLCK )
+#define DCM_CFG_mskDLMB		( 0x7  << DCM_CFG_offDLMB )
+#define DCM_CFG_mskBSAV		( 0x3  << DCM_CFG_offBSAV )
+
+/******************************************************************************
+ * cr3: MMU_CFG (MMU Configuration Register)
+ *****************************************************************************/
+#define MMU_CFG_offMMPS		0	/* Memory management protection scheme */
+#define MMU_CFG_offMMPV		2	/* Memory management protection version number */
+#define MMU_CFG_offFATB		7	/* Fully-associative or non-fully-associative TLB */
+
+#ifdef CONFIG_FULL_ASSOC
+#define MMU_CFG_offFATBSZ	8	/* TLB entries while using full-associative TLB */
+#else
+#define MMU_CFG_offTBW		8	/* TLB ways(non-associative) TBS */
+#define MMU_CFG_offTBS		11	/* TLB sets per way(non-associative) TBS */
+/* bit 14:14 reserved */
+#endif
+
+#define MMU_CFG_offEP8MIN4	15	/* 8KB page supported while minimum page is 4KB */
+#define MMU_CFG_offfEPSZ	16	/* Extra page size supported */
+#define MMU_CFG_offTLBLCK	24	/* TLB locking support */
+#define MMU_CFG_offHPTWK	25	/* Hardware Page Table Walker implemented */
+#define MMU_CFG_offDE		26	/* Default endian */
+#define MMU_CFG_offNTPT		27	/* Partitions for non-translated attributes */
+#define MMU_CFG_offIVTB		28	/* Invisible TLB */
+#define MMU_CFG_offVLPT		29	/* VLPT for fast TLB fill handling implemented */
+#define MMU_CFG_offNTME		30	/* Non-translated VA to PA mapping */
+/* bit 31 reserved */
+
+#define MMU_CFG_mskMMPS		( 0x3  << MMU_CFG_offMMPS )
+#define MMU_CFG_mskMMPV		( 0x1F  << MMU_CFG_offMMPV )
+#define MMU_CFG_mskFATB		( 0x1  << MMU_CFG_offFATB )
+#ifdef CONFIG_FULL_ASSOC
+#define MMU_CFG_mskFATBSZ	( 0x7f  << MMU_CFG_offFATBSZ )
+#else
+#define MMU_CFG_mskTBW		( 0x7  << MMU_CFG_offTBW )
+#define MMU_CFG_mskTBS		( 0x7  << MMU_CFG_offTBS )
+#endif
+#define MMU_CFG_mskEP8MIN4	( 0x1  << MMU_CFG_offEP8MIN4 )
+#define MMU_CFG_mskfEPSZ	( 0xFF  << MMU_CFG_offfEPSZ )
+#define MMU_CFG_mskTLBLCK	( 0x1  << MMU_CFG_offTLBLCK )
+#define MMU_CFG_mskHPTWK	( 0x1  << MMU_CFG_offHPTWK )
+#define MMU_CFG_mskDE		( 0x1  << MMU_CFG_offDE )
+#define MMU_CFG_mskNTPT		( 0x1  << MMU_CFG_offNTPT )
+#define MMU_CFG_mskIVTB		( 0x1  << MMU_CFG_offIVTB )
+#define MMU_CFG_mskVLPT		( 0x1  << MMU_CFG_offVLPT )
+#define MMU_CFG_mskNTME		( 0x1  << MMU_CFG_offNTME )
+
+/******************************************************************************
+ * cr4: MSC_CFG (Misc Configuration Register)
+ *****************************************************************************/
+#define MSC_CFG_offEDM		0
+#define MSC_CFG_offLMDMA	1
+#define MSC_CFG_offPFM		2
+#define MSC_CFG_offHSMP		3
+#define MSC_CFG_offTRACE	4
+#define MSC_CFG_offDIV		5
+#define MSC_CFG_offMAC		6
+#define MSC_CFG_offAUDIO	7
+#define MSC_CFG_offL2C		9
+#define MSC_CFG_offRDREG	10
+#define MSC_CFG_offADR24	11
+#define MSC_CFG_offINTLC	12
+#define MSC_CFG_offBASEV	13
+#define MSC_CFG_offNOD		16
+/* bit 13:31 reserved */
+
+#define MSC_CFG_mskEDM		( 0x1  << MSC_CFG_offEDM )
+#define MSC_CFG_mskLMDMA	( 0x1  << MSC_CFG_offLMDMA )
+#define MSC_CFG_mskPFM		( 0x1  << MSC_CFG_offPFM )
+#define MSC_CFG_mskHSMP		( 0x1  << MSC_CFG_offHSMP )
+#define MSC_CFG_mskTRACE	( 0x1  << MSC_CFG_offTRACE )
+#define MSC_CFG_mskDIV		( 0x1  << MSC_CFG_offDIV )
+#define MSC_CFG_mskMAC		( 0x1  << MSC_CFG_offMAC )
+#define MSC_CFG_mskAUDIO	( 0x3  << MSC_CFG_offAUDIO )
+#define MSC_CFG_mskL2C		( 0x1  << MSC_CFG_offL2C )
+#define MSC_CFG_mskRDREG	( 0x1  << MSC_CFG_offRDREG )
+#define MSC_CFG_mskADR24	( 0x1  << MSC_CFG_offADR24 )
+#define MSC_CFG_mskINTLC	( 0x1  << MSC_CFG_offINTLC )
+#define MSC_CFG_mskBASEV	( 0x7  << MSC_CFG_offBASEV )
+#define MSC_CFG_mskNOD		( 0x1  << MSC_CFG_offNOD )
+
+/******************************************************************************
+ * cr5: CORE_CFG (Core Identification Register)
+ *****************************************************************************/
+#define CORE_ID_offCOREID	0
+/* bit 4:31 reserved */
+
+#define CORE_ID_mskCOREID	( 0xF  << CORE_ID_offCOREID )
+
+/******************************************************************************
+ * cr6: FUCOP_EXIST (FPU and Coprocessor Existence Configuration Register)
+ *****************************************************************************/
+#define FUCOP_EXIST_offCP0EX	0
+#define FUCOP_EXIST_offCP1EX	1
+#define FUCOP_EXIST_offCP2EX	2
+#define FUCOP_EXIST_offCP3EX	3
+#define FUCOP_EXIST_offCP0ISFPU	31
+
+#define FUCOP_EXIST_mskCP0EX	( 0x1  << FUCOP_EXIST_offCP0EX )
+#define FUCOP_EXIST_mskCP1EX	( 0x1  << FUCOP_EXIST_offCP1EX )
+#define FUCOP_EXIST_mskCP2EX	( 0x1  << FUCOP_EXIST_offCP2EX )
+#define FUCOP_EXIST_mskCP3EX	( 0x1  << FUCOP_EXIST_offCP3EX )
+#define FUCOP_EXIST_mskCP0ISFPU	( 0x1  << FUCOP_EXIST_offCP0ISFPU )
+
+/******************************************************************************
+ * ir0: PSW (Processor Status Word Register)
+ * ir1: IPSW (Interruption PSW Register)
+ * ir2: P_IPSW (Previous IPSW Register)
+ *****************************************************************************/
+#define PSW_offGIE		0	/* Global Interrupt Enable */
+#define PSW_offINTL		1	/* Interruption Stack Level */
+#define PSW_offPOM		3	/* Processor Operation Mode, User/Superuser */
+#define PSW_offBE		5	/* Endianness for data memory access, 1:MSB, 0:LSB */
+#define PSW_offIT		6	/* Enable instruction address translation */
+#define PSW_offDT		7	/* Enable data address translation */
+#define PSW_offIME		8	/* Instruction Machine Error flag */
+#define PSW_offDME		9	/* Data Machine Error flag */
+#define PSW_offDEX		10	/* Debug Exception */
+#define PSW_offHSS		11	/* Hardware Single Stepping */
+#define PSW_offDRBE		12	/* Device Register Endian Mode */
+#define PSW_offAEN		13	/* Audio ISA special feature */
+#define PSW_offWBNA		14	/* Write Back Non-Allocate */
+#define PSW_offIFCON		15	/* IFC On */
+#define PSW_offCPL		16	/* Current Priority Level */
+/* bit 19:31 reserved */
+
+#define PSW_mskGIE		( 0x1  << PSW_offGIE )
+#define PSW_mskINTL		( 0x3  << PSW_offINTL )
+#define PSW_mskPOM		( 0x3  << PSW_offPOM )
+#define PSW_mskBE		( 0x1  << PSW_offBE )
+#define PSW_mskIT		( 0x1  << PSW_offIT )
+#define PSW_mskDT		( 0x1  << PSW_offDT )
+#define PSW_mskIME		( 0x1  << PSW_offIME )
+#define PSW_mskDME		( 0x1  << PSW_offDME )
+#define PSW_mskDEX		( 0x1  << PSW_offDEX )
+#define PSW_mskHSS		( 0x1  << PSW_offHSS )
+#define PSW_mskDRBE		( 0x1  << PSW_offDRBE )
+#define PSW_mskAEN		( 0x1  << PSW_offAEN )
+#define PSW_mskWBNA		( 0x1  << PSW_offWBNA )
+#define PSW_mskIFCON		( 0x1  << PSW_offIFCON )
+#define PSW_mskCPL		( 0x7  << PSW_offCPL )
+
+#define PSW_SYSTEM		( 1 << PSW_offPOM )
+#define PSW_INTL_1		( 1 << PSW_offINTL )
+#define PSW_CPL_NO		( 0 << PSW_offCPL )
+#define PSW_CPL_ANY		( 7 << PSW_offCPL )
+
+#define PSW_clr			(PSW_mskGIE|PSW_mskINTL|PSW_mskPOM|PSW_mskIT|PSW_mskDT|PSW_mskIME|PSW_mskWBNA)
+#ifdef __NDS32_EB__
+#ifdef CONFIG_WBNA
+#define PSW_init		(PSW_mskWBNA|(1<<PSW_offINTL)|(1<<PSW_offPOM)|PSW_mskIT|PSW_mskDT|PSW_mskBE)
+#else
+#define PSW_init		((1<<PSW_offINTL)|(1<<PSW_offPOM)|PSW_mskIT|PSW_mskDT|PSW_mskBE)
+#endif
+#else
+#ifdef CONFIG_WBNA
+#define PSW_init		(PSW_mskWBNA|(1<<PSW_offINTL)|(1<<PSW_offPOM)|PSW_mskIT|PSW_mskDT)
+#else
+#define PSW_init		((1<<PSW_offINTL)|(1<<PSW_offPOM)|PSW_mskIT|PSW_mskDT)
+#endif
+#endif
+/******************************************************************************
+ * ir3: IVB (Interruption Vector Base Register)
+ *****************************************************************************/
+/* bit 0:12 reserved */
+#define IVB_offNIVIC		1	/* Number of input for IVIC Controller */
+#define IVB_offIVIC_VER		11	/* IVIC Version */
+#define IVB_offEVIC		13	/* External Vector Interrupt Controller mode */
+#define IVB_offESZ		14	/* Size of each vector entry */
+#define IVB_offIVBASE		16	/* BasePA of interrupt vector table */
+
+#define IVB_mskNIVIC		( 0x7  << IVB_offNIVIC )
+#define IVB_mskIVIC_VER		( 0x3  << IVB_offIVIC_VER )
+#define IVB_mskEVIC		( 0x1  << IVB_offEVIC )
+#define IVB_mskESZ		( 0x3  << IVB_offESZ )
+#define IVB_mskIVBASE		( 0xFFFF  << IVB_offIVBASE )
+
+#define IVB_valESZ4		0
+#define IVB_valESZ16		1
+#define IVB_valESZ64		2
+#define IVB_valESZ256		3
+/******************************************************************************
+ * ir4: EVA (Exception Virtual Address Register)
+ * ir5: P_EVA (Previous EVA Register)
+ *****************************************************************************/
+
+	/* This register contains the VA that causes the exception */
+
+/******************************************************************************
+ * ir6: ITYPE (Interruption Type Register)
+ * ir7: P_ITYPE (Previous ITYPE Register)
+ *****************************************************************************/
+#define ITYPE_offETYPE		0	/* Exception Type */
+#define ITYPE_offINST		4	/* Exception caused by insn fetch or data access */
+/* bit 5:15 reserved */
+#define ITYPE_offVECTOR		5	/* Vector */
+#define ITYPE_offSWID		16	/* SWID of debugging exception */
+/* bit 31:31 reserved */
+
+#define ITYPE_mskETYPE		( 0xF  << ITYPE_offETYPE )
+#define ITYPE_mskINST		( 0x1  << ITYPE_offINST )
+#define ITYPE_mskVECTOR		( 0x7F  << ITYPE_offVECTOR )
+#define ITYPE_mskSWID		( 0x7FFF  << ITYPE_offSWID )
+
+/* Additional definitions for ITYPE register */
+#define ITYPE_offSTYPE          16	/* Arithmetic Sub Type */
+#define ITYPE_offCPID           20	/* Co-Processor ID which generate the exception */
+
+#define ITYPE_mskSTYPE		( 0xF  << ITYPE_offSTYPE )
+#define ITYPE_mskCPID		( 0x3  << ITYPE_offCPID )
+
+#define NDS32_VECTOR_mskNONEXCEPTION	0x78
+#define NDS32_VECTOR_offEXCEPTION	8
+#define NDS32_VECTOR_offINTERRUPT	9
+
+/* Interrupt vector entry */
+#define ENTRY_RESET_NMI			0
+#define ENTRY_TLB_FILL			1
+#define ENTRY_PTE_NOT_PRESENT		2
+#define ENTRY_TLB_MISC			3
+#define ENTRY_TLB_VLPT_MISS		4
+#define ENTRY_MACHINE_ERROR		5
+#define ENTRY_DEBUG_RELATED		6
+#define ENTRY_GENERAL_EXCPETION		7
+#define ENTRY_SYSCALL			8
+
+/* PTE not present exception definition */
+#define ETYPE_NON_LEAF_PTE_NOT_PRESENT	0
+#define ETYPE_LEAF_PTE_NOT_PRESENT	1
+
+/* General exception ETYPE definition */
+#define ETYPE_ALIGNMENT_CHECK		0
+#define ETYPE_RESERVED_INSTRUCTION	1
+#define ETYPE_TRAP			2
+#define ETYPE_ARITHMETIC		3
+#define ETYPE_PRECISE_BUS_ERROR		4
+#define ETYPE_IMPRECISE_BUS_ERROR	5
+#define ETYPE_COPROCESSOR		6
+#define ETYPE_RESERVED_VALUE		7
+#define ETYPE_NONEXISTENT_MEM_ADDRESS	8
+#define ETYPE_MPZIU_CONTROL		9
+#define ETYPE_NEXT_PRECISE_STACK_OFL	10
+
+/* Kerenl reserves software ID */
+#define SWID_RAISE_INTERRUPT_LEVEL	0x1a	/* SWID_RAISE_INTERRUPT_LEVEL is used to
+						 * raise interrupt level for debug exception
+						 */
+
+/******************************************************************************
+ * ir8: MERR (Machine Error Log Register)
+ *****************************************************************************/
+/* bit 0:30 reserved */
+#define MERR_offBUSERR		31	/* Bus error caused by a load insn */
+
+#define MERR_mskBUSERR		( 0x1  << MERR_offBUSERR )
+
+/******************************************************************************
+ * ir9: IPC (Interruption Program Counter Register)
+ * ir10: P_IPC (Previous IPC Register)
+ * ir11: OIPC (Overflow Interruption Program Counter Register)
+ *****************************************************************************/
+
+	/* This is the shadow stack register of the Program Counter */
+
+/******************************************************************************
+ * ir12: P_P0 (Previous P0 Register)
+ * ir13: P_P1 (Previous P1 Register)
+ *****************************************************************************/
+
+	/* These are shadow registers of $p0 and $p1 */
+
+/******************************************************************************
+ * ir14: INT_MASK (Interruption Masking Register)
+ *****************************************************************************/
+#define INT_MASK_offH0IM	0	/* Hardware Interrupt 0 Mask bit */
+#define INT_MASK_offH1IM	1	/* Hardware Interrupt 1 Mask bit */
+#define INT_MASK_offH2IM	2	/* Hardware Interrupt 2 Mask bit */
+#define INT_MASK_offH3IM	3	/* Hardware Interrupt 3 Mask bit */
+#define INT_MASK_offH4IM	4	/* Hardware Interrupt 4 Mask bit */
+#define INT_MASK_offH5IM	5	/* Hardware Interrupt 5 Mask bit */
+/* bit 6:15 reserved */
+#define INT_MASK_offSIM		16	/* Software Interrupt Mask bit */
+/* bit 17:29 reserved */
+#define INT_MASK_offIDIVZE	30	/* Enable detection for Divide-By-Zero */
+#define INT_MASK_offDSSIM	31	/* Default Single Stepping Interruption Mask */
+
+#define INT_MASK_mskH0IM	( 0x1  << INT_MASK_offH0IM )
+#define INT_MASK_mskH1IM	( 0x1  << INT_MASK_offH1IM )
+#define INT_MASK_mskH2IM	( 0x1  << INT_MASK_offH2IM )
+#define INT_MASK_mskH3IM	( 0x1  << INT_MASK_offH3IM )
+#define INT_MASK_mskH4IM	( 0x1  << INT_MASK_offH4IM )
+#define INT_MASK_mskH5IM	( 0x1  << INT_MASK_offH5IM )
+#define INT_MASK_mskSIM		( 0x1  << INT_MASK_offSIM )
+#define INT_MASK_mskIDIVZE	( 0x1  << INT_MASK_offIDIVZE )
+#define INT_MASK_mskDSSIM	( 0x1  << INT_MASK_offDSSIM )
+
+#define INT_MASK_INITAIAL_VAL	0x10003
+
+/******************************************************************************
+ * ir15: INT_PEND (Interrupt Pending Register)
+ *****************************************************************************/
+#define INT_PEND_offH0I		0	/* Hardware Interrupt 0 pending bit */
+#define INT_PEND_offH1I		1	/* Hardware Interrupt 1 pending bit */
+#define INT_PEND_offH2I		2	/* Hardware Interrupt 2 pending bit */
+#define INT_PEND_offH3I		3	/* Hardware Interrupt 3 pending bit */
+#define INT_PEND_offH4I		4	/* Hardware Interrupt 4 pending bit */
+#define INT_PEND_offH5I		5	/* Hardware Interrupt 5 pending bit */
+
+#define INT_PEND_offCIPL	0	/* Current Interrupt Priority Level */
+
+/* bit 6:15 reserved */
+#define INT_PEND_offSWI		16	/* Software Interrupt pending bit */
+/* bit 17:31 reserved */
+
+#define INT_PEND_mskH0I		( 0x1  << INT_PEND_offH0I )
+#define INT_PEND_mskH1I		( 0x1  << INT_PEND_offH1I )
+#define INT_PEND_mskH2I		( 0x1  << INT_PEND_offH2I )
+#define INT_PEND_mskH3I		( 0x1  << INT_PEND_offH3I )
+#define INT_PEND_mskH4I		( 0x1  << INT_PEND_offH4I )
+#define INT_PEND_mskH5I		( 0x1  << INT_PEND_offH5I )
+#define INT_PEND_mskCIPL	( 0x1  << INT_PEND_offCIPL )
+#define INT_PEND_mskSWI		( 0x1  << INT_PEND_offSWI )
+
+/******************************************************************************
+ * mr0: MMU_CTL (MMU Control Register)
+ *****************************************************************************/
+#define MMU_CTL_offD		0	/* Default minimum page size */
+#define MMU_CTL_offNTC0		1	/* Non-Translated Cachebility of partition 0 */
+#define MMU_CTL_offNTC1		3	/* Non-Translated Cachebility of partition 1 */
+#define MMU_CTL_offNTC2		5	/* Non-Translated Cachebility of partition 2 */
+#define MMU_CTL_offNTC3		7	/* Non-Translated Cachebility of partition 3 */
+#define MMU_CTL_offTBALCK	9	/* TLB all-lock resolution scheme */
+#define MMU_CTL_offMPZIU	10	/* Multiple Page Size In Use bit */
+#define MMU_CTL_offNTM0		11	/* Non-Translated VA to PA of partition 0 */
+#define MMU_CTL_offNTM1		13	/* Non-Translated VA to PA of partition 1 */
+#define MMU_CTL_offNTM2		15	/* Non-Translated VA to PA of partition 2 */
+#define MMU_CTL_offNTM3		17	/* Non-Translated VA to PA of partition 3 */
+/* bit 19:31 reserved */
+
+#define MMU_CTL_mskD		( 0x1  << MMU_CTL_offD )
+#define MMU_CTL_mskNTC0		( 0x3  << MMU_CTL_offNTC0 )
+#define MMU_CTL_mskNTC1		( 0x3  << MMU_CTL_offNTC1 )
+#define MMU_CTL_mskNTC2		( 0x3  << MMU_CTL_offNTC2 )
+#define MMU_CTL_mskNTC3		( 0x3  << MMU_CTL_offNTC3 )
+#define MMU_CTL_mskTBALCK	( 0x1  << MMU_CTL_offTBALCK )
+#define MMU_CTL_mskMPZIU	( 0x1  << MMU_CTL_offMPZIU )
+#define MMU_CTL_mskNTM0		( 0x3  << MMU_CTL_offNTM0 )
+#define MMU_CTL_mskNTM1         ( 0x3  << MMU_CTL_offNTM1 )
+#define MMU_CTL_mskNTM2         ( 0x3  << MMU_CTL_offNTM2 )
+#define MMU_CTL_mskNTM3         ( 0x3  << MMU_CTL_offNTM3 )
+
+#define MMU_CTL_D4KB		0
+#define MMU_CTL_D8KB		1
+
+#define MMU_CTL_CACHEABLE_WB	2
+#define MMU_CTL_CACHEABLE_WT	3
+
+/******************************************************************************
+ * mr1: L1_PPTB (L1 Physical Page Table Base Register)
+ *****************************************************************************/
+#define L1_PPTB_offNV		0	/* Enable Hardware Page Table Walker (HPTWK) */
+/* bit 1:11 reserved */
+#define L1_PPTB_offBASE		12	/* First level physical page table base address */
+
+#define L1_PPTB_mskNV		( 0x1  << L1_PPTB_offNV )
+#define L1_PPTB_mskBASE		( 0xFFFFF  << L1_PPTB_offBASE )
+
+/******************************************************************************
+ * mr2: TLB_VPN (TLB Access VPN Register)
+ *****************************************************************************/
+/* bit 0:11 reserved */
+#define TLB_VPN_offVPN		12	/* Virtual Page Number */
+
+#define TLB_VPN_mskVPN		( 0xFFFFF  << TLB_VPN_offVPN )
+
+/******************************************************************************
+ * mr3: TLB_DATA (TLB Access Data Register)
+ *****************************************************************************/
+#define TLB_DATA_offV		0	/* PTE is valid and present */
+#define TLB_DATA_offM		1	/* Page read/write access privilege */
+#define TLB_DATA_offD		4	/* Dirty bit */
+#define TLB_DATA_offX		5	/* Executable bit */
+#define TLB_DATA_offA		6	/* Access bit */
+#define TLB_DATA_offG		7	/* Global page (shared across contexts) */
+#define TLB_DATA_offC		8	/* Cacheability atribute */
+/* bit 11:11 reserved */
+#define TLB_DATA_offPPN		12	/* Phisical Page Number */
+
+#define TLB_DATA_mskV		( 0x1  << TLB_DATA_offV )
+#define TLB_DATA_mskM		( 0x7  << TLB_DATA_offM )
+#define TLB_DATA_mskD		( 0x1  << TLB_DATA_offD )
+#define TLB_DATA_mskX		( 0x1  << TLB_DATA_offX )
+#define TLB_DATA_mskA		( 0x1  << TLB_DATA_offA )
+#define TLB_DATA_mskG		( 0x1  << TLB_DATA_offG )
+#define TLB_DATA_mskC		( 0x7  << TLB_DATA_offC )
+#define TLB_DATA_mskPPN		( 0xFFFFF  << TLB_DATA_offPPN )
+
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+#define TLB_DATA_kernel_text_attr	(TLB_DATA_mskV|TLB_DATA_mskM|TLB_DATA_mskD|TLB_DATA_mskX|TLB_DATA_mskG|TLB_DATA_mskC)
+#else
+#define TLB_DATA_kernel_text_attr	(TLB_DATA_mskV|TLB_DATA_mskM|TLB_DATA_mskD|TLB_DATA_mskX|TLB_DATA_mskG|(0x6 << TLB_DATA_offC))
+#endif
+
+/******************************************************************************
+ * mr4: TLB_MISC (TLB Access Misc Register)
+ *****************************************************************************/
+#define TLB_MISC_offACC_PSZ	0	/* Page size of a PTE entry */
+#define TLB_MISC_offCID		4	/* Context id */
+/* bit 13:31 reserved */
+
+#define TLB_MISC_mskACC_PSZ    ( 0xF  << TLB_MISC_offACC_PSZ )
+#define TLB_MISC_mskCID        ( 0x1FF  << TLB_MISC_offCID )
+
+/******************************************************************************
+ * mr5: VLPT_IDX (Virtual Linear Page Table Index Register)
+ *****************************************************************************/
+#define VLPT_IDX_offZERO	0	/* Always 0 */
+#define VLPT_IDX_offEVPN	2	/* Exception Virtual Page Number */
+#define VLPT_IDX_offVLPTB	22	/* Base VA of VLPT */
+
+#define VLPT_IDX_mskZERO	( 0x3  << VLPT_IDX_offZERO )
+#define VLPT_IDX_mskEVPN	( 0xFFFFF  << VLPT_IDX_offEVPN )
+#define VLPT_IDX_mskVLPTB	( 0x3FF  << VLPT_IDX_offVLPTB )
+
+/******************************************************************************
+ * mr6: ILMB (Instruction Local Memory Base Register)
+ *****************************************************************************/
+#define ILMB_offIEN		0	/* Enable ILM */
+#define ILMB_offILMSZ		1	/* Size of ILM */
+/* bit 5:19 reserved */
+#define ILMB_offIBPA		20	/* Base PA of ILM */
+
+#define ILMB_mskIEN		( 0x1  << ILMB_offIEN )
+#define ILMB_mskILMSZ		( 0xF  << ILMB_offILMSZ )
+#define ILMB_mskIBPA		( 0xFFF  << ILMB_offIBPA )
+
+/******************************************************************************
+ * mr7: DLMB (Data Local Memory Base Register)
+ *****************************************************************************/
+#define DLMB_offDEN		0	/* Enable DLM */
+#define DLMB_offDLMSZ		1	/* Size of DLM */
+#define DLMB_offDBM		5	/* Enable Double-Buffer Mode for DLM */
+#define DLMB_offDBB		6	/* Double-buffer bank which can be accessed by the processor */
+/* bit 7:19 reserved */
+#define DLMB_offDBPA		20	/* Base PA of DLM */
+
+#define DLMB_mskDEN		( 0x1  << DLMB_offDEN )
+#define DLMB_mskDLMSZ		( 0xF  << DLMB_offDLMSZ )
+#define DLMB_mskDBM		( 0x1  << DLMB_offDBM )
+#define DLMB_mskDBB		( 0x1  << DLMB_offDBB )
+#define DLMB_mskDBPA		( 0xFFF  << DLMB_offDBPA )
+
+/******************************************************************************
+ * mr8: CACHE_CTL (Cache Control Register)
+ *****************************************************************************/
+#define CACHE_CTL_offIC_EN	0	/* Enable I-cache */
+#define CACHE_CTL_offDC_EN	1	/* Enable D-cache */
+#define CACHE_CTL_offICALCK	2	/* I-cache all-lock resolution scheme */
+#define CACHE_CTL_offDCALCK	3	/* D-cache all-lock resolution scheme */
+#define CACHE_CTL_offDCCWF	4	/* Enable D-cache Critical Word Forwarding */
+#define CACHE_CTL_offDCPMW	5	/* Enable D-cache concurrent miss and write-back processing */
+/* bit 6:31 reserved */
+
+#define CACHE_CTL_mskIC_EN	( 0x1  << CACHE_CTL_offIC_EN )
+#define CACHE_CTL_mskDC_EN	( 0x1  << CACHE_CTL_offDC_EN )
+#define CACHE_CTL_mskICALCK	( 0x1  << CACHE_CTL_offICALCK )
+#define CACHE_CTL_mskDCALCK	( 0x1  << CACHE_CTL_offDCALCK )
+#define CACHE_CTL_mskDCCWF	( 0x1  << CACHE_CTL_offDCCWF )
+#define CACHE_CTL_mskDCPMW	( 0x1  << CACHE_CTL_offDCPMW )
+
+/******************************************************************************
+ * mr9: HSMP_SADDR (High Speed Memory Port Starting Address)
+ *****************************************************************************/
+#define HSMP_SADDR_offEN	0	/* Enable control bit for the High Speed Memory port */
+/* bit 1:19 reserved */
+
+#define HSMP_SADDR_offRANGE	1	/* Denote the address range (only defined in HSMP v2 ) */
+#define HSMP_SADDR_offSADDR	20	/* Starting base PA of the High Speed Memory Port region */
+
+#define HSMP_SADDR_mskEN	( 0x1  << HSMP_SADDR_offEN )
+#define HSMP_SADDR_mskRANGE	( 0xFFF  << HSMP_SADDR_offRANGE )
+#define HSMP_SADDR_mskSADDR	( 0xFFF  << HSMP_SADDR_offSADDR )
+
+/******************************************************************************
+ * mr10: HSMP_EADDR (High Speed Memory Port Ending Address)
+ *****************************************************************************/
+/* bit 0:19 reserved */
+#define HSMP_EADDR_offEADDR	20
+
+#define HSMP_EADDR_mskEADDR	( 0xFFF  << HSMP_EADDR_offEADDR )
+
+/******************************************************************************
+ * dr0+(n*5): BPCn (n=0-7) (Breakpoint Control Register)
+ *****************************************************************************/
+#define BPC_offWP		0	/* Configuration of BPAn */
+#define BPC_offEL		1	/* Enable BPAn */
+#define BPC_offS		2	/* Data address comparison for a store instruction */
+#define BPC_offP		3	/* Compared data address is PA */
+#define BPC_offC		4	/* CID value is compared with the BPCIDn register */
+#define BPC_offBE0		5	/* Enable byte mask for the comparison with register */
+#define BPC_offBE1		6	/* Enable byte mask for the comparison with register */
+#define BPC_offBE2		7	/* Enable byte mask for the comparison with register */
+#define BPC_offBE3		8	/* Enable byte mask for the comparison with register */
+#define BPC_offT		9	/* Enable breakpoint Embedded Tracer triggering operation */
+
+#define BPC_mskWP		( 0x1  << BPC_offWP )
+#define BPC_mskEL		( 0x1  << BPC_offEL )
+#define BPC_mskS		( 0x1  << BPC_offS )
+#define BPC_mskP		( 0x1  << BPC_offP )
+#define BPC_mskC		( 0x1  << BPC_offC )
+#define BPC_mskBE0		( 0x1  << BPC_offBE0 )
+#define BPC_mskBE1		( 0x1  << BPC_offBE1 )
+#define BPC_mskBE2		( 0x1  << BPC_offBE2 )
+#define BPC_mskBE3		( 0x1  << BPC_offBE3 )
+#define BPC_mskT		( 0x1  << BPC_offT )
+
+/******************************************************************************
+ * dr1+(n*5): BPAn (n=0-7) (Breakpoint Address Register)
+ *****************************************************************************/
+
+	/* These registers contain break point address */
+
+/******************************************************************************
+ * dr2+(n*5): BPAMn (n=0-7) (Breakpoint Address Mask Register)
+ *****************************************************************************/
+
+	/* These registerd contain the address comparison mask for the BPAn register */
+
+/******************************************************************************
+ * dr3+(n*5): BPVn (n=0-7) Breakpoint Data Value Register
+ *****************************************************************************/
+
+	/* The BPVn register contains the data value that will be compared with the
+	 * incoming load/store data value */
+
+/******************************************************************************
+ * dr4+(n*5): BPCIDn (n=0-7) (Breakpoint Context ID Register)
+ *****************************************************************************/
+#define BPCID_offCID		0	/* CID that will be compared with a process's CID */
+/* bit 9:31 reserved */
+
+#define BPCID_mskCID		( 0x1FF  << BPCID_offCID )
+
+/******************************************************************************
+ * dr40: EDM_CFG (EDM Configuration Register)
+ *****************************************************************************/
+#define EDM_CFG_offBC		0	/* Number of hardware breakpoint sets implemented */
+#define EDM_CFG_offDIMU		3	/* Debug Instruction Memory Unit exists */
+/* bit 4:15 reserved */
+#define EDM_CFG_offVER		16	/* EDM version */
+
+#define EDM_CFG_mskBC		( 0x7  << EDM_CFG_offBC )
+#define EDM_CFG_mskDIMU		( 0x1  << EDM_CFG_offDIMU )
+#define EDM_CFG_mskVER		( 0xFFFF  << EDM_CFG_offVER )
+
+/******************************************************************************
+ * dr41: EDMSW (EDM Status Word)
+ *****************************************************************************/
+#define EDMSW_offWV		0	/* Write Valid */
+#define EDMSW_offRV		1	/* Read Valid */
+#define EDMSW_offDE		2	/* Debug exception has occurred for this core */
+/* bit 3:31 reserved */
+
+#define EDMSW_mskWV		( 0x1  << EDMSW_offWV )
+#define EDMSW_mskRV		( 0x1  << EDMSW_offRV )
+#define EDMSW_mskDE		( 0x1  << EDMSW_offDE )
+
+/******************************************************************************
+ * dr42: EDM_CTL (EDM Control Register)
+ *****************************************************************************/
+/* bit 0:30 reserved */
+#define EDM_CTL_offV3_EDM_MODE	6	/* EDM compatibility control bit */
+#define EDM_CTL_offDEH_SEL	31	/* Controls where debug exception is directed to */
+
+#define EDM_CTL_mskV3_EDM_MODE	( 0x1 << EDM_CTL_offV3_EDM_MODE )
+#define EDM_CTL_mskDEH_SEL	( 0x1 << EDM_CTL_offDEH_SEL )
+
+/******************************************************************************
+ * dr43: EDM_DTR (EDM Data Transfer Register)
+ *****************************************************************************/
+
+	/* This is used to exchange data between the embedded EDM logic
+	 * and the processor core */
+
+/******************************************************************************
+ * dr44: BPMTC (Breakpoint Match Trigger Counter Register)
+ *****************************************************************************/
+#define BPMTC_offBPMTC		0	/* Breakpoint match trigger counter value */
+/* bit 16:31 reserved */
+
+#define BPMTC_mskBPMTC		( 0xFFFF  << BPMTC_offBPMTC )
+
+/******************************************************************************
+ * dr45: DIMBR (Debug Instruction Memory Base Register)
+ *****************************************************************************/
+/* bit 0:11 reserved */
+#define DIMBR_offDIMB		12	/* Base address of the Debug Instruction Memory (DIM) */
+#define DIMBR_mskDIMB		( 0xFFFFF  << DIMBR_offDIMB )
+
+/******************************************************************************
+ * dr46: TECR0(Trigger Event Control register 0)
+ * dr47: TECR1 (Trigger Event Control register 1)
+ *****************************************************************************/
+#define TECR_offBP		0	/* Controld which BP is used as a trigger source */
+#define TECR_offNMI		8	/* Use NMI as a trigger source */
+#define TECR_offHWINT		9	/* Corresponding interrupt is used as a trigger source */
+#define TECR_offEVIC		15	/* Enable HWINT as a trigger source in EVIC mode */
+#define TECR_offSYS		16	/* Enable SYSCALL instruction as a trigger source */
+#define TECR_offDBG		17	/* Enable debug exception as a trigger source */
+#define TECR_offMRE		18	/* Enable MMU related exception as a trigger source */
+#define TECR_offE		19	/* An exception is used as a trigger source */
+/* bit 20:30 reserved */
+#define TECR_offL		31	/* Link/Cascade TECR0 trigger event to TECR1 trigger event */
+
+#define TECR_mskBP		( 0xFF  << TECR_offBP )
+#define TECR_mskNMI		( 0x1  << TECR_offBNMI )
+#define TECR_mskHWINT		( 0x3F  << TECR_offBHWINT )
+#define TECR_mskEVIC		( 0x1  << TECR_offBEVIC )
+#define TECR_mskSYS		( 0x1  << TECR_offBSYS )
+#define TECR_mskDBG		( 0x1  << TECR_offBDBG )
+#define TECR_mskMRE		( 0x1  << TECR_offBMRE )
+#define TECR_mskE		( 0x1  << TECR_offE )
+#define TECR_mskL		( 0x1  << TECR_offL )
+
+/******************************************************************************
+ * pfr0-2: PFMC0-2 (Performance Counter Register 0-2)
+ *****************************************************************************/
+
+	/* These registers contains performance event count */
+
+/******************************************************************************
+ * pfr3: PFM_CTL (Performance Counter Control Register)
+ *****************************************************************************/
+#define PFM_CTL_offEN0		0	/* Enable PFMC0 */
+#define PFM_CTL_offEN1		1	/* Enable PFMC1 */
+#define PFM_CTL_offEN2		2	/* Enable PFMC2 */
+#define PFM_CTL_offIE0		3	/* Enable interrupt for PFMC0 */
+#define PFM_CTL_offIE1		4	/* Enable interrupt for PFMC1 */
+#define PFM_CTL_offIE2		5	/* Enable interrupt for PFMC2 */
+#define PFM_CTL_offOVF0		6	/* Overflow bit of PFMC0 */
+#define PFM_CTL_offOVF1		7	/* Overflow bit of PFMC1 */
+#define PFM_CTL_offOVF2		8	/* Overflow bit of PFMC2 */
+#define PFM_CTL_offKS0		9	/* Enable superuser mode event counting for PFMC0 */
+#define PFM_CTL_offKS1		10	/* Enable superuser mode event counting for PFMC1 */
+#define PFM_CTL_offKS2		11	/* Enable superuser mode event counting for PFMC2 */
+#define PFM_CTL_offKU0		12	/* Enable user mode event counting for PFMC0 */
+#define PFM_CTL_offKU1		13	/* Enable user mode event counting for PFMC1 */
+#define PFM_CTL_offKU2		14	/* Enable user mode event counting for PFMC2 */
+#define PFM_CTL_offSEL0		15	/* The event selection for PFMC0 */
+#define PFM_CTL_offSEL1		21	/* The event selection for PFMC1 */
+#define PFM_CTL_offSEL2		27	/* The event selection for PFMC2 */
+/* bit 28:31 reserved */
+
+#define PFM_CTL_mskEN0		( 0x01  << PFM_CTL_offEN0 )
+#define PFM_CTL_mskEN1		( 0x01  << PFM_CTL_offEN1 )
+#define PFM_CTL_mskEN2		( 0x01  << PFM_CTL_offEN2 )
+#define PFM_CTL_mskIE0		( 0x01  << PFM_CTL_offIE0 )
+#define PFM_CTL_mskIE1		( 0x01  << PFM_CTL_offIE1 )
+#define PFM_CTL_mskIE2		( 0x01  << PFM_CTL_offIE2 )
+#define PFM_CTL_mskOVF0		( 0x01  << PFM_CTL_offOVF0 )
+#define PFM_CTL_mskOVF1		( 0x01  << PFM_CTL_offOVF1 )
+#define PFM_CTL_mskOVF2		( 0x01  << PFM_CTL_offOVF2 )
+#define PFM_CTL_mskKS0		( 0x01  << PFM_CTL_offKS0 )
+#define PFM_CTL_mskKS1		( 0x01  << PFM_CTL_offKS1 )
+#define PFM_CTL_mskKS2		( 0x01  << PFM_CTL_offKS2 )
+#define PFM_CTL_mskKU0		( 0x01  << PFM_CTL_offKU0 )
+#define PFM_CTL_mskKU1		( 0x01  << PFM_CTL_offKU1 )
+#define PFM_CTL_mskKU2		( 0x01  << PFM_CTL_offKU2 )
+#define PFM_CTL_mskSEL0		( 0x01  << PFM_CTL_offSEL0 )
+#define PFM_CTL_mskSEL1		( 0x3F  << PFM_CTL_offSEL1 )
+#define PFM_CTL_mskSEL2		( 0x3F  << PFM_CTL_offSEL2 )
+
+/******************************************************************************
+ * SDZ_CTL (Structure Downsizing Control Register)
+ *****************************************************************************/
+#define SDZ_CTL_offICDZ		0	/* I-cache downsizing control */
+#define SDZ_CTL_offDCDZ		3	/* D-cache downsizing control */
+#define SDZ_CTL_offMTBDZ	6	/* MTLB downsizing control */
+#define SDZ_CTL_offBTBDZ	9	/* Branch Target Table downsizing control */
+/* bit 12:31 reserved */
+#define SDZ_CTL_mskICDZ		( 0x07  << SDZ_CTL_offICDZ )
+#define SDZ_CTL_mskDCDZ		( 0x07  << SDZ_CTL_offDCDZ )
+#define SDZ_CTL_mskMTBDZ	( 0x07  << SDZ_CTL_offMTBDZ )
+#define SDZ_CTL_mskBTBDZ	( 0x07  << SDZ_CTL_offBTBDZ )
+
+/******************************************************************************
+ * N13MISC_CTL (N13 Miscellaneous Control Register)
+ *****************************************************************************/
+#define N13MISC_CTL_offBTB	0	/* Disable Branch Target Buffer */
+#define N13MISC_CTL_offRTP	1	/* Disable Return Target Predictor */
+#define N13MISC_CTL_offPTEPF	2	/* Disable HPTWK L2 PTE pefetch */
+#define N13MISC_CTL_offSP_SHADOW_EN	4	/* Enable shadow stack pointers */
+/* bit 6, 9:31 reserved */
+
+#define N13MISC_CTL_makBTB	( 0x1  << N13MISC_CTL_offBTB )
+#define N13MISC_CTL_makRTP	( 0x1  << N13MISC_CTL_offRTP )
+#define N13MISC_CTL_makPTEPF	( 0x1  << N13MISC_CTL_offPTEPF )
+#define N13MISC_CTL_makSP_SHADOW_EN	( 0x1  << N13MISC_CTL_offSP_SHADOW_EN )
+
+#define MISC_init	(N13MISC_CTL_makBTB|N13MISC_CTL_makRTP|N13MISC_CTL_makSP_SHADOW_EN)
+
+/******************************************************************************
+ * PRUSR_ACC_CTL (Privileged Resource User Access Control Registers)
+ *****************************************************************************/
+#define PRUSR_ACC_CTL_offDMA_EN	0	/* Allow user mode access of DMA registers */
+#define PRUSR_ACC_CTL_offPFM_EN	1	/* Allow user mode access of PFM registers */
+
+#define PRUSR_ACC_CTL_mskDMA_EN	( 0x1  << PRUSR_ACC_CTL_offDMA_EN )
+#define PRUSR_ACC_CTL_mskPFM_EN	( 0x1  << PRUSR_ACC_CTL_offPFM_EN )
+
+/******************************************************************************
+ * dmar0: DMA_CFG (DMA Configuration Register)
+ *****************************************************************************/
+#define DMA_CFG_offNCHN		0	/* The number of DMA channels implemented */
+#define DMA_CFG_offUNEA		2	/* Un-aligned External Address transfer feature */
+#define DMA_CFG_off2DET		3	/* 2-D Element Transfer feature */
+/* bit 4:15 reserved */
+#define DMA_CFG_offVER		16	/* DMA architecture and implementation version */
+
+#define DMA_CFG_mskNCHN		( 0x3  << DMA_CFG_offNCHN )
+#define DMA_CFG_mskUNEA		( 0x1  << DMA_CFG_offUNEA )
+#define DMA_CFG_msk2DET		( 0x1  << DMA_CFG_off2DET )
+#define DMA_CFG_mskVER		( 0xFFFF  << DMA_CFG_offVER )
+
+/******************************************************************************
+ * dmar1: DMA_GCSW (DMA Global Control and Status Word Register)
+ *****************************************************************************/
+#define DMA_GCSW_offC0STAT	0	/* DMA channel 0 state */
+#define DMA_GCSW_offC1STAT	3	/* DMA channel 1 state */
+/* bit 6:11 reserved */
+#define DMA_GCSW_offC0INT	12	/* DMA channel 0 generate interrupt */
+#define DMA_GCSW_offC1INT	13	/* DMA channel 1 generate interrupt */
+/* bit 14:30 reserved */
+#define DMA_GCSW_offEN		31	/* Enable DMA engine */
+
+#define DMA_GCSW_mskC0STAT	( 0x7  << DMA_GCSW_offC0STAT )
+#define DMA_GCSW_mskC1STAT	( 0x7  << DMA_GCSW_offC1STAT )
+#define DMA_GCSW_mskC0INT	( 0x1  << DMA_GCSW_offC0INT )
+#define DMA_GCSW_mskC1INT	( 0x1  << DMA_GCSW_offC1INT )
+#define DMA_GCSW_mskEN		( 0x1  << DMA_GCSW_offEN )
+
+/******************************************************************************
+ * dmar2: DMA_CHNSEL (DMA Channel Selection Register)
+ *****************************************************************************/
+#define DMA_CHNSEL_offCHAN	0	/* Selected channel number */
+/* bit 2:31 reserved */
+
+#define DMA_CHNSEL_mskCHAN	( 0x3  << DMA_CHNSEL_offCHAN )
+
+/******************************************************************************
+ * dmar3: DMA_ACT (DMA Action Register)
+ *****************************************************************************/
+#define DMA_ACT_offACMD		0	/* DMA Action Command */
+/* bit 2:31 reserved */
+#define DMA_ACT_mskACMD		( 0x3  << DMA_ACT_offACMD )
+
+/******************************************************************************
+ * dmar4: DMA_SETUP (DMA Setup Register)
+ *****************************************************************************/
+#define DMA_SETUP_offLM		0	/* Local Memory Selection */
+#define DMA_SETUP_offTDIR	1	/* Transfer Direction */
+#define DMA_SETUP_offTES	2	/* Transfer Element Size */
+#define DMA_SETUP_offESTR	4	/* External memory transfer Stride */
+#define DMA_SETUP_offCIE	16	/* Interrupt Enable on Completion */
+#define DMA_SETUP_offSIE	17	/* Interrupt Enable on explicit Stop */
+#define DMA_SETUP_offEIE	18	/* Interrupt Enable on Error */
+#define DMA_SETUP_offUE		19	/* Enable the Un-aligned External Address */
+#define DMA_SETUP_off2DE	20	/* Enable the 2-D External Transfer */
+#define DMA_SETUP_offCOA	21	/* Transfer Coalescable */
+/* bit 22:31 reserved */
+
+#define DMA_SETUP_mskLM		( 0x1  << DMA_SETUP_offLM )
+#define DMA_SETUP_mskTDIR	( 0x1  << DMA_SETUP_offTDIR )
+#define DMA_SETUP_mskTES	( 0x3  << DMA_SETUP_offTES )
+#define DMA_SETUP_mskESTR	( 0xFFF  << DMA_SETUP_offESTR )
+#define DMA_SETUP_mskCIE	( 0x1  << DMA_SETUP_offCIE )
+#define DMA_SETUP_mskSIE	( 0x1  << DMA_SETUP_offSIE )
+#define DMA_SETUP_mskEIE	( 0x1  << DMA_SETUP_offEIE )
+#define DMA_SETUP_mskUE		( 0x1  << DMA_SETUP_offUE )
+#define DMA_SETUP_msk2DE	( 0x1  << DMA_SETUP_off2DE )
+#define DMA_SETUP_mskCOA	( 0x1  << DMA_SETUP_offCOA )
+
+/******************************************************************************
+ * dmar5: DMA_ISADDR (DMA Internal Start Address Register)
+ *****************************************************************************/
+#define DMA_ISADDR_offISADDR	0	/* Internal Start Address */
+/* bit 20:31 reserved */
+#define DMA_ISADDR_mskISADDR	( 0xFFFFF  << DMA_ISADDR_offISADDR )
+
+/******************************************************************************
+ * dmar6: DMA_ESADDR (DMA External Start Address Register)
+ *****************************************************************************/
+/* This register holds External Start Address */
+
+/******************************************************************************
+ * dmar7: DMA_TCNT (DMA Transfer Element Count Register)
+ *****************************************************************************/
+#define DMA_TCNT_offTCNT	0	/* DMA transfer element count */
+/* bit 18:31 reserved */
+#define DMA_TCNT_mskTCNT	( 0x3FFFF  << DMA_TCNT_offTCNT )
+
+/******************************************************************************
+ * dmar8: DMA_STATUS (DMA Status Register)
+ *****************************************************************************/
+#define DMA_STATUS_offSTAT	0	/* DMA channel state */
+#define DMA_STATUS_offSTUNA	3	/* Un-aligned error on External Stride value */
+#define DMA_STATUS_offDERR	4	/* DMA Transfer Disruption Error */
+#define DMA_STATUS_offEUNA	5	/* Un-aligned error on the External address */
+#define DMA_STATUS_offIUNA	6	/* Un-aligned error on the Internal address */
+#define DMA_STATUS_offIOOR	7	/* Out-Of-Range error on the Internal address */
+#define DMA_STATUS_offEBUS	8	/* Bus Error on an External DMA transfer */
+#define DMA_STATUS_offESUP	9	/* DMA setup error */
+/* bit 10:31 reserved */
+
+#define DMA_STATUS_mskSTAT	( 0x7  << DMA_STATUS_offSTAT )
+#define DMA_STATUS_mskSTUNA	( 0x1  << DMDMA_STATUS_offSTUNA )
+#define DMA_STATUS_mskDERR	( 0x1  << DMDMA_STATUS_offDERR )
+#define DMA_STATUS_mskEUNA	( 0x1  << DMDMA_STATUS_offEUNA )
+#define DMA_STATUS_mskIUNA	( 0x1  << DMDMA_STATUS_offIUNA )
+#define DMA_STATUS_mskIOOR	( 0x1  << DMDMA_STATUS_offIOOR )
+#define DMA_STATUS_mskEBUS	( 0x1  << DMDMA_STATUS_offEBUS )
+#define DMA_STATUS_mskESUP	( 0x1  << DMDMA_STATUS_offESUP )
+
+/******************************************************************************
+ * dmar9: DMA_2DSET (DMA 2D Setup Register)
+ *****************************************************************************/
+#define DMA_2DSET_offWECNT	0	/* The Width Element Count for a 2-D region */
+#define DMA_2DSET_offHTSTR	16	/* The Height Stride for a 2-D region */
+
+#define DMA_2DSET_mskHTSTR	( 0xFFFF  << DMA_2DSET_offHTSTR )
+#define DMA_2DSET_mskWECNT	( 0xFFFF  << DMA_2DSET_offWECNT )
+
+/******************************************************************************
+ * dmar10: DMA_2DSCTL (DMA 2D Startup Control Register)
+ *****************************************************************************/
+#define DMA_2DSCTL_offSTWECNT	0	/* Startup Width Element Count for a 2-D region */
+/* bit 16:31 reserved */
+
+#define DMA_2DSCTL_mskSTWECNT	( 0xFFFF  << DMA_2DSCTL_offSTWECNT )
+
+/******************************************************************************
+ * fpcsr: FPCSR (Floating-Point Control Status Register)
+ *****************************************************************************/
+#define FPCSR_offRM		0
+#define FPCSR_offIVO		2
+#define FPCSR_offDBZ		3
+#define FPCSR_offOVF		4
+#define FPCSR_offUDF		5
+#define FPCSR_offIEX		6
+#define FPCSR_offIVOE		7
+#define FPCSR_offDBZE		8
+#define FPCSR_offOVFE		9
+#define FPCSR_offUDFE		10
+#define FPCSR_offIEXE		11
+#define FPCSR_offDNZ		12
+#define FPCSR_offIVOT		13
+#define FPCSR_offDBZT		14
+#define FPCSR_offOVFT		15
+#define FPCSR_offUDFT		16
+#define FPCSR_offIEXT		17
+#define FPCSR_offDNIT		18
+#define FPCSR_offRIT		19
+
+#define FPCSR_mskRM             ( 0x3  << FPCSR_offRM )
+#define FPCSR_mskIVO            ( 0x1  << FPCSR_offIVO )
+#define FPCSR_mskDBZ            ( 0x1  << FPCSR_offDBZ )
+#define FPCSR_mskOVF            ( 0x1  << FPCSR_offOVF )
+#define FPCSR_mskUDF            ( 0x1  << FPCSR_offUDF )
+#define FPCSR_mskIEX            ( 0x1  << FPCSR_offIEX )
+#define FPCSR_mskIVOE           ( 0x1  << FPCSR_offIVOE )
+#define FPCSR_mskDBZE           ( 0x1  << FPCSR_offDBZE )
+#define FPCSR_mskOVFE           ( 0x1  << FPCSR_offOVFE )
+#define FPCSR_mskUDFE           ( 0x1  << FPCSR_offUDFE )
+#define FPCSR_mskIEXE           ( 0x1  << FPCSR_offIEXE )
+#define FPCSR_mskDNZ            ( 0x1  << FPCSR_offDNZ )
+#define FPCSR_mskIVOT           ( 0x1  << FPCSR_offIVOT )
+#define FPCSR_mskDBZT           ( 0x1  << FPCSR_offDBZT )
+#define FPCSR_mskOVFT           ( 0x1  << FPCSR_offOVFT )
+#define FPCSR_mskUDFT           ( 0x1  << FPCSR_offUDFT )
+#define FPCSR_mskIEXT           ( 0x1  << FPCSR_offIEXT )
+#define FPCSR_mskDNIT           ( 0x1  << FPCSR_offDNIT )
+#define FPCSR_mskRIT		( 0x1  << FPCSR_offRIT )
+#define FPCSR_mskALL		(FPCSR_mskIVO | FPCSR_mskDBZ | FPCSR_mskOVF | FPCSR_mskUDF | FPCSR_mskIEX)
+#define FPCSR_mskALLE		(FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE | FPCSR_mskUDFE | FPCSR_mskIEXE)
+#define FPCSR_mskALLT           (FPCSR_mskIVOT | FPCSR_mskDBZT | FPCSR_mskOVFT | FPCSR_mskUDFT | FPCSR_mskIEXT |FPCSR_mskDNIT | FPCSR_mskRIT)
+
+/******************************************************************************
+ * fpcfg: FPCFG (Floating-Point Configuration Register)
+ *****************************************************************************/
+#define	FPCFG_offSP		0
+#define FPCFG_offDP		1
+#define FPCFG_offFREG		2
+#define FPCFG_offFMA		4
+#define FPCFG_offIMVER		22
+#define FPCFG_offAVER		27
+
+#define FPCFG_mskSP		( 0x1  << FPCFG_offSP )
+#define FPCFG_mskDP		( 0x1  << FPCFG_offDP )
+#define FPCFG_mskFREG		( 0x3  << FPCFG_offFREG )
+#define FPCFG_mskFMA		( 0x1  << FPCFG_offFMA )
+#define FPCFG_mskIMVER		( 0x1F  << FPCFG_offIMVER )
+#define FPCFG_mskAVER		( 0x1F  << FPCFG_offAVER )
+
+/******************************************************************************
+ * fucpr: FUCOP_CTL (FPU and Coprocessor Enable Control Register)
+ *****************************************************************************/
+#define FUCOP_CTL_offCP0EN	0
+#define FUCOP_CTL_offCP1EN	1
+#define FUCOP_CTL_offCP2EN	2
+#define FUCOP_CTL_offCP3EN	3
+#define FUCOP_CTL_offAUEN	31
+
+#define FUCOP_CTL_mskCP0EN	( 0x1  << FUCOP_CTL_offCP0EN )
+#define FUCOP_CTL_mskCP1EN	( 0x1  << FUCOP_CTL_offCP1EN )
+#define FUCOP_CTL_mskCP2EN      ( 0x1  << FUCOP_CTL_offCP2EN )
+#define FUCOP_CTL_mskCP3EN      ( 0x1  << FUCOP_CTL_offCP3EN )
+#define FUCOP_CTL_mskAUEN       ( 0x1  << FUCOP_CTL_offAUEN )
+
+#endif /* __NDS32_BITFIELD_H__ */
diff --git a/arch/nds32/include/asm/nds32.h b/arch/nds32/include/asm/nds32.h
new file mode 100644
index 0000000..f405db3
--- /dev/null
+++ b/arch/nds32/include/asm/nds32.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ASM_NDS32_NDS32_H_
+#define _ASM_NDS32_NDS32_H_
+
+#include <asm/bitfield.h>
+#include <asm/cachectl.h>
+
+#ifndef __ASSEMBLY__
+#include <asm/barrier.h>
+#include <nds32_intrinsic.h>
+
+#ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
+#define FP_OFFSET (-3)
+#else
+#define FP_OFFSET (-2)
+#endif
+
+static inline void GIE_ENABLE(void)
+{
+	mb();
+	__nds32__gie_en();
+}
+
+static inline void GIE_DISABLE(void)
+{
+	mb();
+	__nds32__gie_dis();
+}
+
+static inline unsigned long CACHE_SET(unsigned char cache)
+{
+
+	if (cache == ICACHE)
+		return 64 << ((__nds32__mfsr(NDS32_SR_ICM_CFG) & ICM_CFG_mskISET) >>
+			      ICM_CFG_offISET);
+	else
+		return 64 << ((__nds32__mfsr(NDS32_SR_DCM_CFG) & DCM_CFG_mskDSET) >>
+			      DCM_CFG_offDSET);
+}
+
+static inline unsigned long CACHE_WAY(unsigned char cache)
+{
+
+	if (cache == ICACHE)
+		return 1 +
+		    ((__nds32__mfsr(NDS32_SR_ICM_CFG) & ICM_CFG_mskIWAY) >> ICM_CFG_offIWAY);
+	else
+		return 1 +
+		    ((__nds32__mfsr(NDS32_SR_DCM_CFG) & DCM_CFG_mskDWAY) >> DCM_CFG_offDWAY);
+}
+
+static inline unsigned long CACHE_LINE_SIZE(unsigned char cache)
+{
+
+	if (cache == ICACHE)
+		return 8 <<
+		    (((__nds32__mfsr(NDS32_SR_ICM_CFG) & ICM_CFG_mskISZ) >> ICM_CFG_offISZ) - 1);
+	else
+		return 8 <<
+		    (((__nds32__mfsr(NDS32_SR_DCM_CFG) & DCM_CFG_mskDSZ) >> DCM_CFG_offDSZ) - 1);
+}
+
+#endif /* __ASSEMBLY__ */
+
+#define IVB_BASE		PHYS_OFFSET	/* in user space for intr/exc/trap/break table base, 64KB aligned
+						 * We defined at the start of the physical memory */
+
+/* dispatched sub-entry exception handler numbering */
+#define RD_PROT			0	/* read protrection */
+#define WRT_PROT		1	/* write protection */
+#define NOEXEC			2	/* non executable */
+#define PAGE_MODIFY		3	/* page modified */
+#define ACC_BIT			4	/* access bit */
+#define RESVED_PTE		5	/* reserved PTE attribute */
+/* reserved 6 ~ 16 */
+
+#endif /* _ASM_NDS32_NDS32_H_ */
diff --git a/arch/nds32/kernel/asm-offsets.c b/arch/nds32/kernel/asm-offsets.c
new file mode 100644
index 0000000..2d9468b
--- /dev/null
+++ b/arch/nds32/kernel/asm-offsets.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/sched.h>
+#include <linux/sched/task_stack.h>
+#include <linux/kbuild.h>
+#include <asm/thread_info.h>
+#include <asm/ptrace.h>
+
+int main(void)
+{
+	DEFINE(TSK_TI_FLAGS, offsetof(struct task_struct, thread_info.flags));
+	DEFINE(TSK_TI_PREEMPT,
+	       offsetof(struct task_struct, thread_info.preempt_count));
+	DEFINE(THREAD_CPU_CONTEXT,
+	       offsetof(struct task_struct, thread.cpu_context));
+	DEFINE(OSP_OFFSET, offsetof(struct pt_regs, osp));
+	DEFINE(SP_OFFSET, offsetof(struct pt_regs, sp));
+	DEFINE(FUCOP_CTL_OFFSET, offsetof(struct pt_regs, fucop_ctl));
+	DEFINE(IPSW_OFFSET, offsetof(struct pt_regs, ipsw));
+	DEFINE(SYSCALLNO_OFFSET, offsetof(struct pt_regs, syscallno));
+	DEFINE(IPC_OFFSET, offsetof(struct pt_regs, ipc));
+	DEFINE(R0_OFFSET, offsetof(struct pt_regs, uregs[0]));
+	DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
+	DEFINE(CLOCK_COARSE_RES, LOW_RES_NSEC);
+	return 0;
+}
-- 
1.7.9.5

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

* [PATCH 02/31] nds32: Kernel booting and initialization
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
  2017-11-08  5:54 ` [PATCH 01/31] nds32: Assembly macros and definitions Greentime Hu
@ 2017-11-08  5:54 ` Greentime Hu
  2017-11-08 13:38   ` Rob Herring
  2017-11-08  5:54 ` [PATCH 03/31] nds32: Support early_printk Greentime Hu
                   ` (30 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:54 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/kernel/head.S  |  211 +++++++++++++++++++++++
 arch/nds32/kernel/setup.c |  406 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 617 insertions(+)
 create mode 100644 arch/nds32/kernel/head.S
 create mode 100644 arch/nds32/kernel/setup.c

diff --git a/arch/nds32/kernel/head.S b/arch/nds32/kernel/head.S
new file mode 100644
index 0000000..c2e1a5e
--- /dev/null
+++ b/arch/nds32/kernel/head.S
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/ptrace.h>
+#include <asm/asm-offsets.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/l2_cache.h>
+#include <asm/sizes.h>
+#include <asm/thread_info.h>
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+#define OF_DT_MAGIC 0xd00dfeed
+#else
+#define OF_DT_MAGIC 0xedfe0dd0
+#endif
+
+	.globl  swapper_pg_dir
+	.equ    swapper_pg_dir, TEXTADDR - 0x4000
+
+/*
+ * Kernel startup entry point.
+ */
+	.section ".head.text", "ax"
+	.type   _stext, %function
+ENTRY(_stext)
+	setgie.d                            ! Disable interrupt
+	isb
+/*
+ * Disable I/D-cache and enable it at a proper time
+ */
+	mfsr    $r0, $mr8
+	li      $r1, #~(CACHE_CTL_mskIC_EN|CACHE_CTL_mskDC_EN)
+	and     $r0, $r0, $r1
+	mtsr    $r0, $mr8
+
+/*
+ * Process device tree blob
+ */
+	andi 	$r0,$r2,#0x3
+	li	$r10, 0
+	bne     $r0, $r10, _nodtb
+	lwi	$r0, [$r2]
+	li	$r1, OF_DT_MAGIC
+	bne     $r0, $r1, _nodtb
+	move	$r10, $r2
+_nodtb:
+
+/*
+ * Create a temporary mapping area for booting, before start_kernel
+ */
+	sethi   $r4, hi20(swapper_pg_dir)
+	li      $p0, (PAGE_OFFSET - PHYS_OFFSET)
+	sub     $r4, $r4, $p0
+	tlbop   FlushAll            ! invalidate TLB\n"
+	isb
+	mtsr    $r4, $L1_PPTB       ! load page table pointer\n"
+
+/* set NTC0 cacheable/writeback, mutliple page size in use */
+	mfsr    $r3, $MMU_CTL
+	li      $r0, #~MMU_CTL_mskNTC0
+	and     $r3, $r3, $r0
+#ifdef CONFIG_ANDES_PAGE_SIZE_4KB
+	ori     $r3, $r3, #(MMU_CTL_mskMPZIU|(MMU_CTL_CACHEABLE_WB << MMU_CTL_offNTC0))
+#else
+	ori     $r3, $r3, #(MMU_CTL_mskMPZIU|(MMU_CTL_CACHEABLE_WB << MMU_CTL_offNTC0)|MMU_CTL_mskD)
+#endif
+	mtsr    $r3, $MMU_CTL
+	isb
+
+/* set page size and size of kernel image */
+        mfsr    $r0, $MMU_CFG
+        srli    $r3, $r0, MMU_CFG_offfEPSZ
+        zeb     $r3, $r3
+        bnez    $r3, _extra_page_size_support
+#ifdef CONFIG_ANDES_PAGE_SIZE_4KB
+        li      $r5, #SZ_4K                 ! Use 4KB page size
+#else
+        li      $r5, #SZ_8K                 ! Use 8KB page size
+        li      $r3, #1
+#endif
+        mtsr    $r3, $TLB_MISC
+        b       _image_size_check
+
+_extra_page_size_support:                    ! Use epzs pages size
+        clz     $r6, $r3
+        subri   $r2, $r6, #31
+        li      $r3, #1
+        sll     $r3, $r3, $r2
+        /* MMU_CFG.EPSZ value -> meaning */
+        mul     $r5, $r3, $r3
+        slli    $r5, $r5, #14
+        /* MMU_CFG.EPSZ  -> TLB_MISC.ACC_PSZ */
+        addi    $r3, $r2, #0x2
+        mtsr    $r3, $TLB_MISC
+
+_image_size_check:
+        /* calculate the image maximum size accepted by TLB config */
+        andi    $r6, $r0, MMU_CFG_mskTBW
+        andi    $r0, $r0, MMU_CFG_mskTBS
+        srli    $r6, $r6, MMU_CFG_offTBW
+        srli    $r0, $r0, MMU_CFG_offTBS
+        /*
+         * we just map the kernel to the maximum way - 1 of tlb
+         * reserver one way for UART VA mapping
+         * it will cause page fault if UART mapping cover the kernel mapping
+         *
+         * direct mapping is not supported now.
+         */
+        li      $r2, 't'
+        beqz    $r6, __error                 ! MMU_CFG.TBW = 0 is direct mappin
+        addi    $r0, $r0, #0x2               ! MMU_CFG.TBS value -> meaning
+        sll     $r0, $r6, $r0                ! entries = k-way * n-set
+        mul     $r6, $r0, $r5                ! max size = entries * page size
+        /* check kernel image size */
+        la      $r3, (_end - PAGE_OFFSET)
+        li      $r2, 's'
+        bgt     $r3, $r6, __error
+
+	li      $r2, #(PHYS_OFFSET + TLB_DATA_kernel_text_attr)
+        li      $r3, PAGE_OFFSET
+        add     $r6, $r6, $r3
+
+_tlb:
+	mtsr    $r3, $TLB_VPN
+	dsb
+	tlbop   $r2, RWR
+	isb
+	add     $r3, $r3, $r5
+	add     $r2, $r2, $r5
+	bgt     $r6, $r3, _tlb
+	mfsr    $r3, $TLB_MISC      ! setup access page size
+	li      $r2, #~0xf
+	and     $r3, $r3, $r2
+#ifdef CONFIG_ANDES_PAGE_SIZE_8KB
+	ori    $r3, $r3, #0x1
+#endif
+	mtsr    $r3, $TLB_MISC
+
+	mfsr    $r0, $MISC_CTL      ! Enable BTB and RTP and shadow sp
+	ori     $r0, $r0, #MISC_init
+	mtsr    $r0, $MISC_CTL
+
+/*
+ * Disable L2CC and wait until L2CC registers are mapped into memory to use L2$.
+ */
+#ifdef CONFIG_CACHE_L2
+	mfsr	$p0, $MSC_CFG
+	andi	$p0, $p0, #MSC_CFG_mskL2C
+	beqz	$p0, 1f
+	li  	$p0, L2CC_PA_BASE
+	li  	$p1, 0
+	swi 	$p1, [$p0 + L2CC_CTRL_OFF]
+1:
+#endif
+
+	mfsr    $p1, $PSW
+	li      $r15, #~PSW_clr             ! clear WBNA|DME|IME|DT|IT|POM|INTL|GIE
+	and     $p1, $p1, $r15
+	ori     $p1, $p1, #PSW_init
+	mtsr    $p1, $IPSW                  ! when iret, it will automatically enable MMU
+	la      $lp, __mmap_switched
+	mtsr    $lp, $IPC
+	iret
+	nop
+
+	.type   __switch_data, %object
+__switch_data:
+	.long   __bss_start                 ! $r6
+	.long   _end                        ! $r7
+	.long	__atags_pointer 	    ! $atag_pointer
+	.long   init_task                   ! $r9, move to $r25
+	.long   init_thread_union + THREAD_SIZE    ! $sp
+
+
+/*
+ * The following fragment of code is executed with the MMU on in MMU mode,
+ * and uses absolute addresses; this is not position independent.
+ */
+	.align
+	.type   __mmap_switched, %function
+__mmap_switched:
+	la  $r3, __switch_data
+	lmw.bim $r6, [$r3], $r9, #0b0001
+	move	$r25, $r9
+	move    $fp, #0             ! Clear  BSS (and zero $fp)
+	beq $r7, $r6, _RRT
+1:	swi.bi  $fp, [$r6], #4
+	bne $r7, $r6, 1b
+	swi	$r10, [$r8]
+
+_RRT:
+	b   start_kernel
+
+__error:
+	b   __error
diff --git a/arch/nds32/kernel/setup.c b/arch/nds32/kernel/setup.c
new file mode 100644
index 0000000..ce4349a
--- /dev/null
+++ b/arch/nds32/kernel/setup.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/cpu.h>
+#include <linux/bootmem.h>
+#include <linux/seq_file.h>
+#include <linux/memblock.h>
+#include <linux/console.h>
+#include <linux/screen_info.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+#include <asm/setup.h>
+#include <asm/sections.h>
+#include <asm/proc-fns.h>
+#include <asm/cache_info.h>
+#include <asm/elf.h>
+#include <nds32_intrinsic.h>
+
+#define HWCAP_MFUSR_PC		0x000001
+#define HWCAP_EXT		0x000002
+#define HWCAP_EXT2		0x000004
+#define HWCAP_FPU		0x000008
+#define HWCAP_AUDIO		0x000010
+#define HWCAP_BASE16		0x000020
+#define HWCAP_STRING		0x000040
+#define HWCAP_REDUCED_REGS	0x000080
+#define HWCAP_VIDEO		0x000100
+#define HWCAP_ENCRYPT		0x000200
+#define HWCAP_EDM		0x000400
+#define HWCAP_LMDMA		0x000800
+#define HWCAP_PFM		0x001000
+#define HWCAP_HSMP		0x002000
+#define HWCAP_TRACE		0x004000
+#define HWCAP_DIV		0x008000
+#define HWCAP_MAC		0x010000
+#define HWCAP_L2C		0x020000
+#define HWCAP_FPU_DP		0x040000
+#define HWCAP_V2		0x080000
+#define HWCAP_DX_REGS		0x100000
+
+extern struct mm_struct init_mm;
+unsigned long cpu_id, cpu_rev, cpu_cfgid;
+char cpu_series;
+char *endianness = NULL;
+
+unsigned int __atags_pointer __initdata;
+unsigned int elf_hwcap;
+EXPORT_SYMBOL(elf_hwcap);
+
+extern void __init early_init_devtree(void *params);
+extern void __init early_trap_init(void);
+/*
+ * The following string table, must sync with HWCAP_xx bitmask,
+ * which is defined in <asm/procinfo.h>
+ */
+static const char *hwcap_str[] = {
+	"mfusr_pc",
+	"perf1",
+	"perf2",
+	"fpu",
+	"audio",
+	"16b",
+	"string",
+	"reduced_regs",
+	"video",
+	"encrypt",
+	"edm",
+	"lmdma",
+	"pfm",
+	"hsmp",
+	"trace",
+	"div",
+	"mac",
+	"l2c",
+	"dx_regs",
+	"v2",
+	NULL,
+};
+
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+#define WRITE_METHOD "write through"
+#else
+#define WRITE_METHOD "write back"
+#endif
+
+struct cache_info L1_cache_info[2];
+static void __init dump_cpu_info(int cpu)
+{
+	int i, p = 0;
+	char str[sizeof(hwcap_str) + 16];
+
+	for (i = 0; hwcap_str[i]; i++) {
+		if (elf_hwcap & (1 << i)) {
+			sprintf(str + p, "%s ", hwcap_str[i]);
+			p += strlen(hwcap_str[i]) + 1;
+		}
+	}
+
+	pr_info("CPU%d Featuretures: %s\n", cpu, str);
+
+	L1_cache_info[ICACHE].ways = CACHE_WAY(ICACHE);
+	L1_cache_info[ICACHE].line_size = CACHE_LINE_SIZE(ICACHE);
+	L1_cache_info[ICACHE].sets = CACHE_SET(ICACHE);
+	L1_cache_info[ICACHE].size =
+	    L1_cache_info[ICACHE].ways * L1_cache_info[ICACHE].line_size *
+	    L1_cache_info[ICACHE].sets / 1024;
+	pr_info("L1I:%dKB/%dS/%dW/%dB\n", L1_cache_info[ICACHE].size,
+		L1_cache_info[ICACHE].sets, L1_cache_info[ICACHE].ways,
+		L1_cache_info[ICACHE].line_size);
+	L1_cache_info[DCACHE].ways = CACHE_WAY(DCACHE);
+	L1_cache_info[DCACHE].line_size = CACHE_LINE_SIZE(DCACHE);
+	L1_cache_info[DCACHE].sets = CACHE_SET(DCACHE);
+	L1_cache_info[DCACHE].size =
+	    L1_cache_info[DCACHE].ways * L1_cache_info[DCACHE].line_size *
+	    L1_cache_info[DCACHE].sets / 1024;
+	pr_info("L1D:%dKB/%dS/%dW/%dB\n", L1_cache_info[DCACHE].size,
+		L1_cache_info[DCACHE].sets, L1_cache_info[DCACHE].ways,
+		L1_cache_info[DCACHE].line_size);
+	pr_info("L1 D-Cache is %s\n", WRITE_METHOD);
+	if (L1_cache_info[DCACHE].size != L1_CACHE_BYTES)
+		pr_crit
+		    ("The cache line size(%d) of this processor is not the same as L1_CACHE_BYTES(%d).\n",
+		     L1_cache_info[DCACHE].size, L1_CACHE_BYTES);
+#if !defined(CONFIG_CPU_CACHE_NONALIASING)
+	{
+		int aliasing_num;
+		aliasing_num =
+		    L1_cache_info[ICACHE].size * 1024 / PAGE_SIZE /
+		    L1_cache_info[ICACHE].ways;
+		L1_cache_info[ICACHE].aliasing_num = aliasing_num;
+		L1_cache_info[ICACHE].aliasing_mask =
+		    (aliasing_num - 1) << PAGE_SHIFT;
+		aliasing_num =
+		    L1_cache_info[DCACHE].size * 1024 / PAGE_SIZE /
+		    L1_cache_info[DCACHE].ways;
+		L1_cache_info[DCACHE].aliasing_num = aliasing_num;
+		L1_cache_info[DCACHE].aliasing_mask =
+		    (aliasing_num - 1) << PAGE_SHIFT;
+	}
+#endif
+
+}
+
+static void __init setup_cpuinfo(void)
+{
+	unsigned long tmp = 0, cpu_name;
+
+	cpu_dcache_inval_all();
+	cpu_icache_inval_all();
+	__nds32__isb();
+
+	cpu_id = (__nds32__mfsr(NDS32_SR_CPU_VER) & CPU_VER_mskCPUID) >> CPU_VER_offCPUID;
+	cpu_name = ((cpu_id) & 0xf0) >> 4;
+	cpu_series = cpu_name ? cpu_name - 10 + 'A' : 'N';
+	cpu_id = cpu_id & 0xf;
+	cpu_rev = (__nds32__mfsr(NDS32_SR_CPU_VER) & CPU_VER_mskREV) >> CPU_VER_offREV;
+	cpu_cfgid = (__nds32__mfsr(NDS32_SR_CPU_VER) & CPU_VER_mskCFGID) >> CPU_VER_offCFGID;
+
+	pr_info("CPU:%c%ld, CPU_VER 0x%08x(id %lu, rev %lu, cfg %lu)\n",
+		cpu_series, cpu_id, __nds32__mfsr(NDS32_SR_CPU_VER), cpu_id, cpu_rev, cpu_cfgid);
+
+	elf_hwcap |= HWCAP_MFUSR_PC;
+
+	if (((__nds32__mfsr(NDS32_SR_MSC_CFG) & MSC_CFG_mskBASEV) >> MSC_CFG_offBASEV) == 0) {
+		if (__nds32__mfsr(NDS32_SR_MSC_CFG) & MSC_CFG_mskDIV)
+			elf_hwcap |= HWCAP_DIV;
+
+		if ((__nds32__mfsr(NDS32_SR_MSC_CFG) & MSC_CFG_mskMAC)
+		    || (cpu_id == 12 && cpu_rev < 4))
+			elf_hwcap |= HWCAP_MAC;
+	} else {
+		elf_hwcap |= HWCAP_V2;
+		elf_hwcap |= HWCAP_DIV;
+		elf_hwcap |= HWCAP_MAC;
+	}
+
+	if (cpu_cfgid & 0x0001)
+		elf_hwcap |= HWCAP_EXT;
+
+	if (cpu_cfgid & 0x0002)
+		elf_hwcap |= HWCAP_BASE16;
+
+	if (cpu_cfgid & 0x0004)
+		elf_hwcap |= HWCAP_EXT2;
+
+	if (cpu_cfgid & 0x0008)
+		elf_hwcap |= HWCAP_FPU;
+
+	if (cpu_cfgid & 0x0010)
+		elf_hwcap |= HWCAP_STRING;
+
+	if (__nds32__mfsr(NDS32_SR_MMU_CFG) & MMU_CFG_mskDE)
+		endianness = "MSB";
+	else
+		endianness = "LSB";
+
+	if (__nds32__mfsr(NDS32_SR_MSC_CFG) & MSC_CFG_mskEDM)
+		elf_hwcap |= HWCAP_EDM;
+
+	if (__nds32__mfsr(NDS32_SR_MSC_CFG) & MSC_CFG_mskLMDMA)
+		elf_hwcap |= HWCAP_LMDMA;
+
+	if (__nds32__mfsr(NDS32_SR_MSC_CFG) & MSC_CFG_mskPFM)
+		elf_hwcap |= HWCAP_PFM;
+
+	if (__nds32__mfsr(NDS32_SR_MSC_CFG) & MSC_CFG_mskHSMP)
+		elf_hwcap |= HWCAP_HSMP;
+
+	if (__nds32__mfsr(NDS32_SR_MSC_CFG) & MSC_CFG_mskTRACE)
+		elf_hwcap |= HWCAP_TRACE;
+
+	if (__nds32__mfsr(NDS32_SR_MSC_CFG) & MSC_CFG_mskAUDIO)
+		elf_hwcap |= HWCAP_AUDIO;
+
+	if (__nds32__mfsr(NDS32_SR_MSC_CFG) & MSC_CFG_mskL2C)
+		elf_hwcap |= HWCAP_L2C;
+
+	tmp = __nds32__mfsr(NDS32_SR_CACHE_CTL);
+#ifndef CONFIG_CPU_DCACHE_DISABLE
+	tmp |= CACHE_CTL_mskDC_EN;
+#endif
+
+#ifndef CONFIG_CPU_ICACHE_DISABLE
+	tmp |= CACHE_CTL_mskIC_EN;
+#endif
+	__nds32__mtsr_isb(tmp, NDS32_SR_CACHE_CTL);
+
+	dump_cpu_info(smp_processor_id());
+}
+
+static unsigned long __init setup_memory(void)
+{
+	unsigned long bootmap_size;
+	unsigned long ram_start_pfn;
+	unsigned long free_ram_start_pfn;
+	phys_addr_t memory_start, memory_end;
+	struct memblock_region *region;
+
+	memory_end = memory_start = 0;
+
+	/* Find main memory where is the kernel */
+	for_each_memblock(memory, region) {
+		memory_start = region->base;
+		memory_end = region->base + region->size;
+		pr_info("%s: Memory: 0x%x-0x%x\n", __func__,
+			memory_start, memory_end);
+	}
+
+	if (!memory_end) {
+		panic("No memory!");
+	}
+
+	ram_start_pfn = PFN_UP(memblock_start_of_DRAM());
+	/* free_ram_start_pfn is first page after kernel */
+	free_ram_start_pfn = PFN_UP(__pa(&_end));
+	max_pfn = PFN_DOWN(memblock_end_of_DRAM());
+
+	/* it could update max_pfn */
+	if (max_pfn - ram_start_pfn <= MAXMEM_PFN)
+		max_low_pfn = max_pfn;
+	else {
+		max_low_pfn = MAXMEM_PFN + ram_start_pfn;
+#ifndef CONFIG_HIGHMEM
+		max_pfn = MAXMEM_PFN + ram_start_pfn;
+#endif
+	}
+	/* high_memory is related with VMALLOC */
+	high_memory = (void *)__va(max_low_pfn * PAGE_SIZE);
+	min_low_pfn = free_ram_start_pfn;
+
+	/*
+	 * initialize the boot-time allocator (with low memory only).
+	 *
+	 * This makes the memory from the end of the kernel to the end of
+	 * RAM usable.
+	 * init_bootmem sets the global values min_low_pfn, max_low_pfn.
+	 */
+	bootmap_size = init_bootmem_node(NODE_DATA(0), free_ram_start_pfn,
+					 ram_start_pfn, max_low_pfn);
+	free_bootmem(PFN_PHYS(free_ram_start_pfn),
+		     (max_low_pfn - free_ram_start_pfn) << PAGE_SHIFT);
+	reserve_bootmem(PFN_PHYS(free_ram_start_pfn), bootmap_size,
+			BOOTMEM_DEFAULT);
+
+	for_each_memblock(reserved, region) {
+		if (region->size != 0) {
+			pr_info("Reserved - 0x%08x-0x%08x\n",
+				(u32) region->base, (u32) region->size);
+			reserve_bootmem(region->base, region->size,
+					BOOTMEM_DEFAULT);
+		}
+	}
+	return max_low_pfn;
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+	early_init_devtree(__atags_pointer ?
+			   phys_to_virt(__atags_pointer) : __dtb_start);
+
+	setup_cpuinfo();
+
+	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;
+
+	/* use generic way to parse */
+	parse_early_param();
+
+	/* setup bootmem allocator */
+	setup_memory();
+
+	/* paging_init() sets up the MMU and marks all pages as reserved */
+	paging_init();
+
+	unflatten_and_copy_device_tree();
+
+#if defined(CONFIG_VT)
+#if defined(CONFIG_VGA_CONSOLE)
+	conswitchp = &vga_con;
+#elif defined(CONFIG_DUMMY_CONSOLE)
+	conswitchp = &dummy_con;
+#endif
+#endif
+
+	*cmdline_p = boot_command_line;
+	early_trap_init();
+}
+
+static int __init nds32_device_probe(void)
+{
+	return of_platform_populate(NULL, NULL, NULL, NULL);
+}
+
+device_initcall(nds32_device_probe);
+
+static int c_show(struct seq_file *m, void *v)
+{
+	int i;
+
+	seq_printf(m, "Processor\t: %c%ld (id %lu, rev %lu, cfg %lu)\n",
+		   cpu_series, cpu_id, cpu_id, cpu_rev, cpu_cfgid);
+
+	seq_printf(m, "L1I\t\t: %luKB/%luS/%luW/%luB\n",
+		   CACHE_SET(ICACHE) * CACHE_WAY(ICACHE) *
+		   CACHE_LINE_SIZE(ICACHE) / 1024, CACHE_SET(ICACHE),
+		   CACHE_WAY(ICACHE), CACHE_LINE_SIZE(ICACHE));
+
+	seq_printf(m, "L1D\t\t: %luKB/%luS/%luW/%luB\n",
+		   CACHE_SET(DCACHE) * CACHE_WAY(DCACHE) *
+		   CACHE_LINE_SIZE(DCACHE) / 1024, CACHE_SET(DCACHE),
+		   CACHE_WAY(DCACHE), CACHE_LINE_SIZE(DCACHE));
+
+	seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
+		   loops_per_jiffy / (500000 / HZ),
+		   (loops_per_jiffy / (5000 / HZ)) % 100);
+
+	/* dump out the processor features */
+	seq_puts(m, "Features\t: ");
+
+	for (i = 0; hwcap_str[i]; i++)
+		if (elf_hwcap & (1 << i))
+			seq_printf(m, "%s ", hwcap_str[i]);
+
+	seq_puts(m, "\n\n");
+
+	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)
+{
+}
+
+struct seq_operations cpuinfo_op = {
+	.start = c_start,
+	.next = c_next,
+	.stop = c_stop,
+	.show = c_show
+};
-- 
1.7.9.5

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

* [PATCH 03/31] nds32: Support early_printk
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
  2017-11-08  5:54 ` [PATCH 01/31] nds32: Assembly macros and definitions Greentime Hu
  2017-11-08  5:54 ` [PATCH 02/31] nds32: Kernel booting and initialization Greentime Hu
@ 2017-11-08  5:54 ` Greentime Hu
  2017-11-08  9:47   ` Tobias Klauser
  2017-11-08  5:54 ` [PATCH 04/31] nds32: Exception handling Greentime Hu
                   ` (29 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:54 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Rick Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Rick Chen <rick@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/kernel/early_printk.c |  124 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)
 create mode 100644 arch/nds32/kernel/early_printk.c

diff --git a/arch/nds32/kernel/early_printk.c b/arch/nds32/kernel/early_printk.c
new file mode 100644
index 0000000..269c3cd
--- /dev/null
+++ b/arch/nds32/kernel/early_printk.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <linux/serial_reg.h>
+
+extern void __iomem *early_io_map(phys_addr_t phys);
+static void __iomem *early_base;
+static void (*printch) (char ch);
+
+/*
+ * 8250/16550 (8-bit aligned registers) single character TX.
+ */
+static void uart8250_8bit_printch(char ch)
+{
+	while (!(readb(early_base + UART_LSR) & UART_LSR_THRE)) ;
+	writeb(ch, early_base + UART_TX);
+}
+
+/*
+ * 8250/16550 (32-bit aligned registers) single character TX.
+ */
+static void uart8250_32bit_printch(char ch)
+{
+	while (!(readl(early_base + (UART_LSR << 2)) & UART_LSR_THRE)) ;
+	writel(ch, early_base + (UART_TX << 2));
+}
+
+struct earlycon_match {
+	const char *name;
+	void (*printch) (char ch);
+};
+
+static const struct earlycon_match earlycon_match[] __initconst = {
+	{.name = "uart8250-8bit",.printch = uart8250_8bit_printch,},
+	{.name = "uart8250-32bit",.printch = uart8250_32bit_printch,},
+	{}
+};
+
+static void early_write(struct console *con, const char *s, unsigned n)
+{
+	while (n-- > 0) {
+		if (*s == '\n')
+			printch('\r');
+		printch(*s);
+		s++;
+	}
+}
+
+static struct console early_console_dev = {
+	.name = "earlycon",
+	.write = early_write,
+	.flags = CON_PRINTBUFFER | CON_BOOT,
+	.index = -1,
+};
+
+/*
+ * Parse earlyprintk=... parameter in the format:
+ *
+ *   <name>[,<addr>][,<options>]
+ *
+ * and register the early console. It is assumed that the UART has been
+ * initialised by the bootloader already.
+ */
+static int __init setup_early_printk(char *buf)
+{
+	const struct earlycon_match *match = earlycon_match;
+	phys_addr_t paddr = 0;
+
+	if (!buf) {
+		pr_warning("No earlyprintk arguments passed.\n");
+		return 0;
+	}
+
+	while (match->name) {
+		size_t len = strlen(match->name);
+		if (!strncmp(buf, match->name, len)) {
+			buf += len;
+			break;
+		}
+		match++;
+	}
+	if (!match->name) {
+		pr_warning("Unknown earlyprintk arguments: %s\n", buf);
+		return 0;
+	}
+
+	/* I/O address */
+	if (!strncmp(buf, ",0x", 3)) {
+		char *e;
+		paddr = simple_strtoul(buf + 1, &e, 16);
+		buf = e;
+	}
+
+	if (paddr)
+		early_base = early_io_map(paddr);
+
+	if (!strcmp(CONFIG_NDS32_BUILTIN_DTB, "ae3xx"))
+		early_base += 32;
+
+	printch = match->printch;
+	register_console(&early_console_dev);
+
+	return 0;
+}
+
+early_param("earlyprintk", setup_early_printk);
-- 
1.7.9.5

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

* [PATCH 04/31] nds32: Exception handling
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (2 preceding siblings ...)
  2017-11-08  5:54 ` [PATCH 03/31] nds32: Support early_printk Greentime Hu
@ 2017-11-08  5:54 ` Greentime Hu
  2017-11-08  8:23   ` Arnd Bergmann
  2017-11-08  5:54 ` [PATCH 05/31] nds32: MMU definitions Greentime Hu
                   ` (28 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:54 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/asm/ptrace.h |   79 ++++++
 arch/nds32/kernel/ex-entry.S    |  169 ++++++++++++
 arch/nds32/kernel/ex-exit.S     |  207 ++++++++++++++
 arch/nds32/kernel/stacktrace.c  |   60 +++++
 arch/nds32/kernel/traps.c       |  442 ++++++++++++++++++++++++++++++
 arch/nds32/mm/alignment.c       |  564 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 1521 insertions(+)
 create mode 100644 arch/nds32/include/asm/ptrace.h
 create mode 100644 arch/nds32/kernel/ex-entry.S
 create mode 100644 arch/nds32/kernel/ex-exit.S
 create mode 100644 arch/nds32/kernel/stacktrace.c
 create mode 100644 arch/nds32/kernel/traps.c
 create mode 100644 arch/nds32/mm/alignment.c

diff --git a/arch/nds32/include/asm/ptrace.h b/arch/nds32/include/asm/ptrace.h
new file mode 100644
index 0000000..2c9c03d
--- /dev/null
+++ b/arch/nds32/include/asm/ptrace.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_NDS32_PTRACE_H
+#define __ASM_NDS32_PTRACE_H
+
+#define PTRACE_GETREGS		12
+#define PTRACE_SETREGS		13
+#define PTRACE_GETFPREGS	14
+#define PTRACE_SETFPREGS	15
+
+#include <uapi/asm/ptrace.h>
+
+#ifndef __ASSEMBLY__
+
+struct pt_regs {
+	union {
+		struct user_pt_regs user_regs;
+		struct {
+			long uregs[26];
+			long fp;
+			long gp;
+			long lp;
+			long sp;
+			long ipc;
+#if defined(CONFIG_HWZOL)
+			long lb;
+			long le;
+			long lc;
+#else
+			long dummy[3];
+#endif
+			long syscallno;
+		};
+	};
+	long orig_r0;
+	long ir0;
+	long ipsw;
+	long pipsw;
+	long pipc;
+	long pp0;
+	long pp1;
+	long fucop_ctl;
+	long osp;
+};
+
+#include <asm/bitfield.h>
+extern void show_regs(struct pt_regs *);
+/* Avoid circular header include via sched.h */
+struct task_struct;
+extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
+			 int error_code, int si_code);
+
+#define arch_has_single_step()		(1)
+#define user_mode(regs)			(((regs)->ipsw & PSW_mskPOM) == 0)
+#define interrupts_enabled(regs)	(!!((regs)->ipsw & PSW_mskGIE))
+#define valid_user_regs(regs)		(user_mode(regs) && interrupts_enabled(regs))
+#define regs_return_value(regs)		((regs)->uregs[0])
+#define instruction_pointer(regs)	((regs)->ipc)
+#define user_stack_pointer(regs)        ((regs)->sp)
+#define profile_pc(regs) 		instruction_pointer(regs)
+
+#define ARCH_HAS_USER_SINGLE_STEP_INFO
+
+#endif /* __ASSEMBLY__ */
+#endif
diff --git a/arch/nds32/kernel/ex-entry.S b/arch/nds32/kernel/ex-entry.S
new file mode 100644
index 0000000..3e977cf
--- /dev/null
+++ b/arch/nds32/kernel/ex-entry.S
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <asm/memory.h>
+#include <asm/nds32.h>
+#include <asm/errno.h>
+#include <asm/asm-offsets.h>
+#include <asm/page.h>
+
+	.macro push_zol
+#ifdef CONFIG_HWZOL
+	mfusr	$r14, $LB
+	mfusr	$r15, $LE
+	mfusr	$r16, $LC
+#endif
+	.endm
+
+	.macro	save_user_regs
+
+	smw.adm $sp, [$sp], $sp, #0x1
+        addi    $sp, $sp, -OSP_OFFSET /* move $SP to the bottom of pt_regs*/
+
+	/*push $r0 ~ $r25*/
+	smw.bim $r0, [$sp], $r25
+	/*push $fp, $gp, $lp*/
+	smw.bim $sp, [$sp], $sp, #0xe
+
+	mfsr	$r12, $SP_USR
+	mfsr	$r13, $IPC
+#ifdef CONFIG_HWZOL
+	push_zol
+#endif
+	movi	$r17, -1
+	move	$r18, $r0
+	mfsr	$r19, $PSW
+	mfsr	$r20, $IPSW
+	mfsr	$r21, $P_IPSW
+	mfsr	$r22, $P_IPC
+	mfsr	$r23, $P_P0
+	mfsr	$r24, $P_P1
+	smw.bim $r12, [$sp], $r24, #0
+	addi	$sp, $sp, -FUCOP_CTL_OFFSET
+
+/*Initialize kernel space $fp*/
+	andi    $p0, $r20, #PSW_mskPOM
+	movi    $p1, #0x0
+	cmovz   $fp, $p1, $p0
+
+	andi	$r16, $r19, #PSW_mskINTL
+	slti	$r17, $r16, #4
+	bnez	$r17, 1f
+	addi	$r17, $r19, #-2
+	mtsr	$r17, $PSW
+	isb
+1:
+	/* If it was superuser mode, we don't need to update $r25*/
+	bnez	$p0, 2f
+	la	$p0, __entry_task
+	lw	$r25, [$p0]
+2:
+	.endm
+
+	.text
+
+/*
+ * Exception Vector
+ */
+exception_handlers:
+	.long	unhandled_exceptions	!Reset/NMI
+	.long	unhandled_exceptions	!TLB fill
+	.long	do_page_fault		!PTE not present
+	.long	do_dispatch_tlb_misc	!TLB misc
+	.long	unhandled_exceptions	!TLB VLPT
+	.long	unhandled_exceptions	!Machine Error
+	.long	do_debug_trap		!Debug related
+	.long	do_dispatch_general	!General exception
+	.long	eh_syscall		!Syscall
+	.long	asm_do_IRQ		!IRQ
+
+common_exception_handler:
+	save_user_regs
+	mfsr	$p0, $ITYPE
+	andi	$p0, $p0, #ITYPE_mskVECTOR
+	srli	$p0, $p0, #ITYPE_offVECTOR
+	andi	$p1, $p0, #NDS32_VECTOR_mskNONEXCEPTION
+	bnez	$p1, 1f
+	sethi	$lp, hi20(ret_from_exception)
+	ori	$lp, $lp, lo12(ret_from_exception)
+	sethi	$p1, hi20(exception_handlers)
+	ori	$p1, $p1, lo12(exception_handlers)
+	lw	$p1, [$p1+$p0<<2]
+	move	$r0, $p0
+	mfsr	$r1, $EVA
+	mfsr	$r2, $ITYPE
+	move	$r3, $sp
+	mfsr    $r4, $OIPC
+	/* enable gie if it is enabled in IPSW. */
+	mfsr	$r21, $PSW
+	andi	$r20, $r20, #PSW_mskGIE	/* r20 is $IPSW*/
+	or	$r21, $r21, $r20
+	mtsr	$r21, $PSW
+	dsb
+	jr	$p1
+
+	/* syscall */
+1:
+	addi	$p1, $p0, #-NDS32_VECTOR_offEXCEPTION
+	bnez	$p1, 2f
+	sethi	$lp, hi20(ret_from_exception)
+	ori	$lp, $lp, lo12(ret_from_exception)
+	sethi	$p1, hi20(exception_handlers)
+	ori	$p1, $p1, lo12(exception_handlers)
+	lwi	$p1, [$p1+#NDS32_VECTOR_offEXCEPTION<<2]
+	jr	$p1
+
+	/* interrupt */
+2:
+#ifdef CONFIG_TRACE_IRQFLAGS
+	jal     arch_trace_hardirqs_off
+#endif
+	move	$r0, $sp
+	sethi	$lp, hi20(ret_from_intr)
+	ori	$lp, $lp, lo12(ret_from_intr)
+	sethi	$p0, hi20(exception_handlers)
+	ori	$p0, $p0, lo12(exception_handlers)
+	lwi	$p0, [$p0+#NDS32_VECTOR_offINTERRUPT<<2]
+	jr	$p0
+
+	.macro	EXCEPTION_VECTOR_DEBUG
+	.align 4
+	mfsr     $p0, $EDM_CTL
+	andi     $p0, $p0, EDM_CTL_mskV3_EDM_MODE
+	tnez     $p0, SWID_RAISE_INTERRUPT_LEVEL
+	.endm
+
+	.macro	EXCEPTION_VECTOR
+	.align 4
+	sethi	 $p0, hi20(common_exception_handler)
+	ori	 $p0, $p0, lo12(common_exception_handler)
+	jral.ton $p0, $p0
+	.endm
+
+	.section	".text.init", #alloc, #execinstr
+	.global	exception_vector
+exception_vector:
+.rept 5
+	EXCEPTION_VECTOR
+.endr
+	EXCEPTION_VECTOR_DEBUG
+.rept 122
+	EXCEPTION_VECTOR
+.endr
+	.align 4
+	.global	exception_vector_end
+exception_vector_end:
diff --git a/arch/nds32/kernel/ex-exit.S b/arch/nds32/kernel/ex-exit.S
new file mode 100644
index 0000000..c7cda60
--- /dev/null
+++ b/arch/nds32/kernel/ex-exit.S
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <asm/unistd.h>
+#include <asm/assembler.h>
+#include <asm/nds32.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/current.h>
+
+#define why	$r8
+
+
+	.macro pop_zol
+#ifdef CONFIG_HWZOL
+	mtusr	$r14, $LB
+	mtusr	$r15, $LE
+	mtusr	$r16, $LC
+#endif
+	.endm
+
+	.macro	restore_user_regs_first
+	setgie.d
+	isb
+
+	addi	$sp, $sp, FUCOP_CTL_OFFSET
+
+	lmw.adm $r12, [$sp], $r24, #0x0
+	mtsr	$r12, $SP_USR
+	mtsr	$r13, $IPC
+#ifdef CONFIG_HWZOL
+	pop_zol
+#endif
+	mtsr	$r19, $PSW
+	mtsr	$r20, $IPSW
+	mtsr    $r21, $P_IPSW
+	mtsr	$r22, $P_IPC
+	mtsr	$r23, $P_P0
+	mtsr	$r24, $P_P1
+	lmw.adm $sp, [$sp], $sp, #0xe
+	.endm
+
+	.macro	restore_user_regs_last
+	pop	$p0
+	cmovn	$sp, $p0, $p0
+
+	iret
+	nop
+
+	.endm
+
+	.macro	restore_user_regs
+	restore_user_regs_first
+	lmw.adm $r0, [$sp], $r25, #0x0
+	addi	$sp, $sp, OSP_OFFSET
+	restore_user_regs_last
+	.endm
+
+	.macro	fast_restore_user_regs
+	restore_user_regs_first
+	lmw.adm $r1, [$sp], $r25, #0x0
+	addi	$sp, $sp, OSP_OFFSET-4
+	restore_user_regs_last
+	.endm
+
+#ifdef CONFIG_PREEMPT
+	.macro	preempt_stop
+	.endm
+#else
+	.macro	preempt_stop
+	setgie.d
+	isb
+	.endm
+#define	resume_kernel	no_work_pending
+#endif
+
+ENTRY(ret_from_exception)
+	preempt_stop
+ENTRY(ret_from_intr)
+	move	why, #0				! not system call
+
+/*
+ * judge Kernel or user mode
+ *
+ */
+	lwi	$p0, [$sp+(#IPSW_OFFSET)]	! Check if in nested interrupt
+	andi	$p0, $p0, #PSW_mskINTL
+	bnez	$p0, resume_kernel		! done with iret
+	j	resume_userspace
+
+
+/*
+ * This is the fast syscall return path.  We do as little as
+ * possible here, and this includes saving $r0 back into the SVC
+ * stack.
+ * fixed: tsk - $r25, why - $r8, $r7 - syscall #, $r8 - syscall table pointer
+ */
+ENTRY(ret_fast_syscall)
+	gie_disable
+	lwi	$r1, [tsk+#TSK_TI_FLAGS]
+	andi	$p1, $r1, #_TIF_WORK_MASK
+	bnez	$p1, fast_work_pending
+	fast_restore_user_regs			! iret
+
+/*
+ * Ok, we need to do extra processing,
+ * enter the slow path returning from syscall, while pending work.
+ */
+fast_work_pending:
+	swi	$r0, [$sp+(#R0_OFFSET)]		! what is different from ret_from_exception
+	move	why, #1				! come from a syscall
+work_pending:
+	andi	$p1, $r1, #_TIF_NEED_RESCHED
+	bnez	$p1, work_resched
+
+	andi	$p1, $r1, #_TIF_SIGPENDING|#_TIF_NOTIFY_RESUME
+	beqz	$p1, no_work_pending
+
+	move	$r0, $sp			! 'regs'
+	move	$r2, why
+	gie_enable
+	bal	do_notify_resume
+	beqz	$r0, ret_slow_syscall
+	bgtz	$r0, 1f
+	movi	$r7, #__NR_restart_syscall
+1:
+	b	eh_syscall_phase_2
+work_resched:
+	bal	schedule			! path, return to user mode
+
+/*
+ * "slow" syscall return path.
+ * "why" tells us if this was a real syscall.
+ */
+ENTRY(resume_userspace)
+ENTRY(ret_slow_syscall)
+	gie_disable
+	lwi	$p0, [$sp+(#IPSW_OFFSET)]	! Check if in nested interrupt
+	andi	$p0, $p0, #PSW_mskINTL
+	bnez	$p0, no_work_pending		! done with iret
+	lwi	$r1, [tsk+#TSK_TI_FLAGS]
+	andi	$p1, $r1, #_TIF_WORK_MASK
+	bnez	$p1, work_pending		! handle work_resched, sig_pend
+
+no_work_pending:
+#ifdef CONFIG_TRACE_IRQFLAGS
+	lwi	$p0, [$sp+(#IPSW_OFFSET)]
+	andi	$p0, $p0, #0x1
+	la	$r10, arch_trace_hardirqs_off
+	la	$r9, arch_trace_hardirqs_on
+	cmovz	$r9, $p0, $r10
+	jral	$r9
+#endif
+	restore_user_regs			! return from iret
+
+
+/*
+ * preemptive kernel
+ */
+#ifdef CONFIG_PREEMPT
+resume_kernel:
+	gie_disable
+	lwi	$t0, [tsk+#TSK_TI_PREEMPT]
+	bnez	$t0, no_work_pending
+need_resched:
+	lwi	$t0, [tsk+#TSK_TI_FLAGS]
+	andi	$p1, $t0, #_TIF_NEED_RESCHED
+	beqz	$p1, no_work_pending
+
+	lwi	$t0, [$sp+(#IPSW_OFFSET)]	! Interrupts off?
+	andi	$t0, $t0, #1
+	beqz	$t0, no_work_pending
+
+	jal	preempt_schedule_irq
+	b	need_resched
+#endif
+
+/*
+ * This is how we return from a fork.
+ */
+ENTRY(ret_from_fork)
+	bal	schedule_tail
+	beqz	$r6, 1f				! r6 stores fn for kernel thread
+	move	$r0, $r7			! prepare kernel thread arg
+	jral	$r6
+1:
+	lwi	$r1, [tsk+#TSK_TI_FLAGS]		! check for syscall tracing
+	move	why, #1
+	andi	$p1, $r1, #_TIF_WORK_SYSCALL_LEAVE	! are we tracing syscalls?
+	beqz	$p1, ret_slow_syscall
+	move    $r0, $sp
+	bal	syscall_trace_leave
+	b	ret_slow_syscall
diff --git a/arch/nds32/kernel/stacktrace.c b/arch/nds32/kernel/stacktrace.c
new file mode 100644
index 0000000..78e816d
--- /dev/null
+++ b/arch/nds32/kernel/stacktrace.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/sched/debug.h>
+#include <linux/sched/task_stack.h>
+#include <linux/stacktrace.h>
+
+void save_stack_trace(struct stack_trace *trace)
+{
+	save_stack_trace_tsk(current, trace);
+}
+
+void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
+{
+	unsigned long *fpn;
+	int skip = trace->skip;
+	int savesched;
+
+	if (tsk == current) {
+		__asm__ __volatile__("\tori\t%0, $fp, #0\n":"=r"(fpn));
+		savesched = 1;
+	} else {
+		fpn = (unsigned long *)thread_saved_fp(tsk);
+		savesched = 0;
+	}
+
+	while (!kstack_end(fpn) && !((unsigned long)fpn & 0x3)
+	       && (fpn >= (unsigned long *)TASK_SIZE)) {
+		unsigned long lpp, fpp;
+
+		lpp = fpn[-1];
+		fpp = fpn[FP_OFFSET];
+		if (!__kernel_text_address(lpp))
+			break;
+
+		if (savesched || !in_sched_functions(lpp)) {
+			if (skip) {
+				skip--;
+			} else {
+				trace->entries[trace->nr_entries++] = lpp;
+				if (trace->nr_entries >= trace->max_entries)
+					break;
+			}
+		}
+		fpn = (unsigned long *)fpp;
+	}
+}
diff --git a/arch/nds32/kernel/traps.c b/arch/nds32/kernel/traps.c
new file mode 100644
index 0000000..07d8f77
--- /dev/null
+++ b/arch/nds32/kernel/traps.c
@@ -0,0 +1,442 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/personality.h>
+#include <linux/kallsyms.h>
+#include <linux/hardirq.h>
+#include <linux/kdebug.h>
+#include <linux/sched/task_stack.h>
+
+#include <asm/cacheflush.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+
+#include <linux/ptrace.h>
+#include <nds32_intrinsic.h>
+
+extern void show_pte(struct mm_struct *mm, unsigned long addr);
+
+/*
+ * Dump out the contents of some memory nicely...
+ */
+void dump_mem(const char *lvl, unsigned long bottom, unsigned long top)
+{
+	unsigned long first;
+	mm_segment_t fs;
+	int i;
+
+	/*
+	 * We need to switch to kernel mode so that we can use __get_user
+	 * to safely read from kernel space.  Note that we now dump the
+	 * code first, just in case the backtrace kills us.
+	 */
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	pr_emerg("%s(0x%08lx to 0x%08lx)\n", lvl, bottom, top);
+
+	for (first = bottom & ~31; first < top; first += 32) {
+		unsigned long p;
+		char str[sizeof(" 12345678") * 8 + 1];
+
+		memset(str, ' ', sizeof(str));
+		str[sizeof(str) - 1] = '\0';
+
+		for (p = first, i = 0; i < 8 && p < top; i++, p += 4) {
+			if (p >= bottom && p < top) {
+				unsigned long val;
+				if (__get_user(val, (unsigned long *)p) == 0)
+					sprintf(str + i * 9, " %08lx", val);
+				else
+					sprintf(str + i * 9, " ????????");
+			}
+		}
+		pr_emerg("%s%04lx:%s\n", lvl, first & 0xffff, str);
+	}
+
+	set_fs(fs);
+}
+
+EXPORT_SYMBOL(dump_mem);
+
+static void dump_instr(struct pt_regs *regs)
+{
+	unsigned long addr = instruction_pointer(regs);
+	mm_segment_t fs;
+	char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str;
+	int i;
+
+	return;
+	/*
+	 * We need to switch to kernel mode so that we can use __get_user
+	 * to safely read from kernel space.  Note that we now dump the
+	 * code first, just in case the backtrace kills us.
+	 */
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	pr_emerg("Code: ");
+	for (i = -4; i < 1; i++) {
+		unsigned int val, bad;
+
+		bad = __get_user(val, &((u32 *) addr)[i]);
+
+		if (!bad) {
+			p += sprintf(p, i == 0 ? "(%08x) " : "%08x ", val);
+		} else {
+			p += sprintf(p, "bad PC value");
+			break;
+		}
+	}
+	pr_emerg("Code: %s\n", str);
+
+	set_fs(fs);
+}
+
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+#include <linux/ftrace.h>
+static void
+get_real_ret_addr(unsigned long *addr, struct task_struct *tsk, int *graph)
+{
+	if (*addr == (unsigned long)return_to_handler) {
+		int index = tsk->curr_ret_stack;
+
+		if (tsk->ret_stack && index >= *graph) {
+			index -= *graph;
+			*addr = tsk->ret_stack[index].ret;
+			(*graph)++;
+		}
+	}
+}
+#else
+static inline void
+get_real_ret_addr(unsigned long *addr, struct task_struct *tsk, int *graph)
+{
+}
+#endif
+
+#define LOOP_TIMES (100)
+static void __dump(struct task_struct *tsk, unsigned long *base_reg)
+{
+	unsigned long ret_addr;
+	int cnt = LOOP_TIMES, graph = 0;
+	pr_emerg("Call Trace:\n");
+#ifndef CONFIG_FRAME_POINTER
+	while (!kstack_end(base_reg)) {
+		ret_addr = *base_reg++;
+		if (__kernel_text_address(ret_addr)) {
+			get_real_ret_addr(&ret_addr, tsk, &graph);
+			print_ip_sym(ret_addr);
+		}
+		if (--cnt < 0)
+			break;
+	}
+#else
+	while (!kstack_end((void *)base_reg) &&
+	       !((unsigned long)base_reg & 0x3) &&
+	       ((unsigned long)base_reg >= TASK_SIZE)) {
+		unsigned long next_fp;
+#if !defined(NDS32_ABI_2)
+		ret_addr = base_reg[0];
+		next_fp = base_reg[1];
+#else
+		ret_addr = base_reg[-1];
+		next_fp = base_reg[FP_OFFSET];
+#endif
+		if (__kernel_text_address(ret_addr)) {
+			get_real_ret_addr(&ret_addr, tsk, &graph);
+			print_ip_sym(ret_addr);
+		}
+
+		if (--cnt < 0)
+			break;
+
+		base_reg = (unsigned long *)next_fp;
+	}
+#endif
+	pr_emerg("\n");
+}
+
+void dump_stack(void)
+{
+	unsigned long *base_reg;
+#ifndef CONFIG_FRAME_POINTER
+	__asm__ __volatile__("\tori\t%0, $sp, #0\n":"=r"(base_reg));
+#else
+	__asm__ __volatile__("\tori\t%0, $fp, #0\n":"=r"(base_reg));
+#endif
+	__dump(NULL, base_reg);
+}
+
+EXPORT_SYMBOL(dump_stack);
+
+void show_stack(struct task_struct *tsk, unsigned long *sp)
+{
+	unsigned long *base_reg;
+
+	if (!tsk)
+		tsk = current;
+#ifndef CONFIG_FRAME_POINTER
+	if (tsk != current)
+		base_reg = (unsigned long *)(tsk->thread.cpu_context);
+	else
+		__asm__ __volatile__("\tori\t%0, $sp, #0\n":"=r"(base_reg));
+#else
+	if (tsk != current)
+		base_reg = (unsigned long *)(tsk->thread.cpu_context.fp);
+	else
+		__asm__ __volatile__("\tori\t%0, $fp, #0\n":"=r"(base_reg));
+#endif
+	__dump(tsk, base_reg);
+	barrier();
+}
+
+DEFINE_SPINLOCK(die_lock);
+
+/*
+ * This function is protected against re-entrancy.
+ */
+void die(const char *str, struct pt_regs *regs, int err)
+{
+	struct task_struct *tsk = current;
+	static int die_counter;
+
+	console_verbose();
+	spin_lock_irq(&die_lock);
+	bust_spinlocks(1);
+
+	pr_emerg("Internal error: %s: %x [#%d]\n", str, err, ++die_counter);
+	print_modules();
+	pr_emerg("CPU: %i\n", smp_processor_id());
+	show_regs(regs);
+	pr_emerg("Process %s (pid: %d, stack limit = 0x%p)\n",
+		 tsk->comm, tsk->pid, task_thread_info(tsk) + 1);
+
+	if (!user_mode(regs) || in_interrupt()) {
+		dump_mem("Stack: ", regs->sp,
+			 THREAD_SIZE + (unsigned long)task_thread_info(tsk));
+		dump_instr(regs);
+		dump_stack();
+	}
+
+	bust_spinlocks(0);
+	spin_unlock_irq(&die_lock);
+	do_exit(SIGSEGV);
+}
+
+EXPORT_SYMBOL(die);
+
+void die_if_kernel(const char *str, struct pt_regs *regs, int err)
+{
+	if (user_mode(regs))
+		return;
+
+	die(str, regs, err);
+}
+
+int bad_syscall(int n, struct pt_regs *regs)
+{
+	siginfo_t info;
+
+	if (current->personality != PER_LINUX) {
+		send_sig(SIGSEGV, current, 1);
+		return regs->uregs[0];
+	}
+
+	info.si_signo = SIGILL;
+	info.si_errno = 0;
+	info.si_code = ILL_ILLTRP;
+	info.si_addr = (void __user *)instruction_pointer(regs) - 4;
+
+	force_sig_info(SIGILL, &info, current);
+	die_if_kernel("Oops - bad syscall", regs, n);
+	return regs->uregs[0];
+}
+
+void __pte_error(const char *file, int line, unsigned long val)
+{
+	pr_emerg("%s:%d: bad pte %08lx.\n", file, line, val);
+}
+
+void __pmd_error(const char *file, int line, unsigned long val)
+{
+	pr_emerg("%s:%d: bad pmd %08lx.\n", file, line, val);
+}
+
+void __pgd_error(const char *file, int line, unsigned long val)
+{
+	pr_emerg("%s:%d: bad pgd %08lx.\n", file, line, val);
+}
+
+extern char *exception_vector, *exception_vector_end;
+void __init trap_init(void)
+{
+	return;
+}
+
+void __init early_trap_init(void)
+{
+	unsigned long ivb = 0;
+	unsigned long base = PAGE_OFFSET;
+
+	memcpy((unsigned long *)base, (unsigned long *)&exception_vector,
+	       ((unsigned long)&exception_vector_end -
+		(unsigned long)&exception_vector));
+	ivb = __nds32__mfsr(NDS32_SR_IVB);
+	/* Check platform support. */
+	if (((ivb & IVB_mskNIVIC) >> IVB_offNIVIC) < 2)
+		panic
+		    ("IVIC mode is not allowed on the platform with interrupt controller\n");
+	__nds32__mtsr((ivb & ~IVB_mskESZ) | (IVB_valESZ16 << IVB_offESZ) |
+		      IVB_BASE, NDS32_SR_IVB);
+	__nds32__mtsr(INT_MASK_INITAIAL_VAL, NDS32_SR_INT_MASK);
+
+	/*
+	 * 0x800 = 128 vectors * 16byte.
+	 * It should be enough to flush a page.
+	 */
+	flush_icache_range(base, base + PAGE_SIZE);
+}
+
+void do_debug_trap(unsigned long entry, unsigned long addr,
+		   unsigned long type, struct pt_regs *regs)
+{
+	if (notify_die(DIE_OOPS, "Oops", regs, addr, type, SIGTRAP)
+	    == NOTIFY_STOP)
+		return;
+
+	if (user_mode(regs)) {
+		/* trap_signal */
+		send_sigtrap(current, regs, 0, TRAP_BRKPT);
+	} else {
+		/* kernel_trap */
+		if (!fixup_exception(regs))
+			die("unexpected kernel_trap", regs, 0);
+	}
+}
+
+void unhandled_interruption(struct pt_regs *regs)
+{
+	siginfo_t si;
+	pr_emerg("unhandled_interruption\n");
+	show_regs(regs);
+	if (!user_mode(regs))
+		do_exit(SIGKILL);
+	si.si_signo = SIGKILL;
+	si.si_errno = 0;
+	force_sig_info(SIGKILL, &si, current);
+}
+
+void unhandled_exceptions(unsigned long entry, unsigned long addr,
+			  unsigned long type, struct pt_regs *regs)
+{
+	siginfo_t si;
+	pr_emerg("Unhandled Exception: entry: %lx addr:%lx itype:%lx\n", entry,
+		 addr, type);
+	show_regs(regs);
+	if (!user_mode(regs))
+		do_exit(SIGKILL);
+	si.si_signo = SIGKILL;
+	si.si_errno = 0;
+	si.si_addr = (void *)addr;
+	force_sig_info(SIGKILL, &si, current);
+}
+
+extern int do_page_fault(unsigned long entry, unsigned long addr,
+			 unsigned int error_code, struct pt_regs *regs);
+
+/*
+ * 2:DEF dispatch for TLB MISC exception handler
+*/
+
+void do_dispatch_tlb_misc(unsigned long entry, unsigned long addr,
+			  unsigned long type, struct pt_regs *regs)
+{
+	type = type & (ITYPE_mskINST | ITYPE_mskETYPE);
+	if ((type & ITYPE_mskETYPE) < 5) {
+		/* Permission exceptions */
+		do_page_fault(entry, addr, type, regs);
+	} else
+		unhandled_exceptions(entry, addr, type, regs);
+}
+
+int (*do_unaligned_access) (unsigned long entry, unsigned long addr,
+			    unsigned long type, struct pt_regs * regs) = NULL;
+
+EXPORT_SYMBOL(do_unaligned_access);
+
+void do_revinsn(struct pt_regs *regs)
+{
+	siginfo_t si;
+	pr_emerg("Reserved Instruction\n");
+	show_regs(regs);
+	if (!user_mode(regs))
+		do_exit(SIGILL);
+	si.si_signo = SIGILL;
+	si.si_errno = 0;
+	force_sig_info(SIGILL, &si, current);
+}
+
+void do_dispatch_general(unsigned long entry, unsigned long addr,
+			 unsigned long itype, struct pt_regs *regs,
+			 unsigned long oipc)
+{
+	unsigned int swid = itype >> ITYPE_offSWID;
+	unsigned long type = itype & (ITYPE_mskINST | ITYPE_mskETYPE);
+	if (type == ETYPE_ALIGNMENT_CHECK) {
+		/* Alignment check */
+		if (do_unaligned_access) {
+
+			int ret = do_unaligned_access(entry, addr, type, regs);
+
+			if (ret == 0)
+				return;
+
+			if (ret == -EFAULT)
+				pr_emerg
+				    ("Unhandled unaligned access exception\n");
+		}
+		do_page_fault(entry, addr, type, regs);
+	} else if (type == ETYPE_RESERVED_INSTRUCTION) {
+		/* Reserved instruction */
+		do_revinsn(regs);
+	} else if (type == ETYPE_TRAP && swid == SWID_RAISE_INTERRUPT_LEVEL) {
+		/* trap, used on v3 EDM target debugging workaround */
+		/*
+		 * DIPC(OIPC) is passed as parameter before
+		 * interrupt is enabled, so the DIPC will not be corrupted
+		 * even though interrupts are coming in
+		 */
+		/*
+		 * 1. update ipc
+		 * 2. update pt_regs ipc with oipc
+		 * 3. update pt_regs ipsw (clear DEX)
+		 */
+		__asm__ volatile ("mtsr %0, $IPC\n\t"::"r" (oipc));
+		regs->ipc = oipc;
+		if (regs->pipsw & PSW_mskDEX) {
+			pr_emerg
+			    ("Nested Debug exception is possibly happened\n");
+			pr_emerg("ipc:%08x pipc:%08x\n",
+				 (unsigned int)regs->ipc,
+				 (unsigned int)regs->pipc);
+		}
+		do_debug_trap(entry, addr, itype, regs);
+		regs->ipsw &= ~PSW_mskDEX;
+	} else
+		unhandled_exceptions(entry, addr, type, regs);
+}
diff --git a/arch/nds32/mm/alignment.c b/arch/nds32/mm/alignment.c
new file mode 100644
index 0000000..05589e7
--- /dev/null
+++ b/arch/nds32/mm/alignment.c
@@ -0,0 +1,564 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/uaccess.h>
+
+#include <asm/unaligned.h>
+
+#ifdef CONFIG_PROC_FS
+extern struct proc_dir_entry *proc_dir_cpu;
+#endif
+
+#define DEBUG(enable, tagged, ...)				\
+	do{							\
+		if (enable) {					\
+			if (tagged)				\
+			pr_warn("[ %30s() ] ", __func__);	\
+			pr_warn(__VA_ARGS__);			\
+		}						\
+	} while (0)
+
+#define RT(inst)	(((inst) >> 20) & 0x1FUL)
+#define RA(inst)	(((inst) >> 15) & 0x1FUL)
+#define RB(inst)	(((inst) >> 10) & 0x1FUL)
+#define SV(inst)	(((inst) >> 8) & 0x3UL)
+#define IMM(inst)	(((inst) >> 0) & 0x3FFFUL)
+
+#define RA3(inst)	(((inst) >> 3) & 0x7UL)
+#define RT3(inst)	(((inst) >> 6) & 0x7UL)
+#define IMM3U(inst)	(((inst) >> 0) & 0x7UL)
+
+#define RA5(inst)	(((inst) >> 0) & 0x1FUL)
+#define RT4(inst)	(((inst) >> 5) & 0xFUL)
+
+extern int (*do_unaligned_access)
+ (unsigned long entry, unsigned long addr,
+  unsigned long type, struct pt_regs * regs);
+extern pte_t va_present(struct mm_struct *mm, unsigned long addr);
+extern pte_t va_kernel_present(unsigned long addr);
+extern int va_readable(struct pt_regs *regs, unsigned long addr);
+extern int va_writable(struct pt_regs *regs, unsigned long addr);
+
+static int mode = 0x3;
+module_param(mode, int, S_IWUSR | S_IRUGO);
+
+static inline unsigned long *idx_to_addr(struct pt_regs *regs, int idx)
+{
+	/* this should be consistent with ptrace.h */
+	if (idx >= 0 && idx <= 25)	/* R0-R25 */
+		return &regs->uregs[0] + idx;
+	else if (idx >= 28 && idx <= 30)	/* FP, GP, LP */
+		return &regs->fp + (idx - 28);
+	else if (idx == 31)	/* SP */
+		return &regs->sp;
+	else
+		return NULL;	/* cause a segfault */
+}
+
+static inline unsigned long get_inst(unsigned long addr)
+{
+	/* FIXME: consider 16-bit inst. */
+	return be32_to_cpu(get_unaligned((u32 *) addr));
+}
+
+static inline unsigned long get_data(unsigned long addr, int len)
+{
+	if (len == 4)
+		return get_unaligned((u32 *) addr);
+	else
+		return get_unaligned((u16 *) addr);
+}
+
+static inline void set_data(unsigned long addr, unsigned long val, int len)
+{
+	if (len == 4)
+		put_unaligned(val, (u32 *) addr);
+	else
+		put_unaligned(val, (u16 *) addr);
+}
+
+static inline unsigned long sign_extend(unsigned long val, int len)
+{
+	unsigned long ret = 0;
+	unsigned char *s, *t;
+	int i = 0;
+
+	val = cpu_to_le32(val);
+
+	s = (void *)&val;
+	t = (void *)&ret;
+
+	while (i++ < len)
+		*t++ = *s++;
+
+	if (((*(t - 1)) & 0x80) && (i < 4)) {
+
+		while (i++ <= 4)
+			*t++ = 0xff;
+	}
+
+	return le32_to_cpu(ret);
+}
+
+static inline int do_16(unsigned long inst, struct pt_regs *regs)
+{
+	int imm, regular, load, len, addr_mode, idx_mode;
+	unsigned long unaligned_addr, target_val, source_idx, target_idx,
+	    shift = 0;
+	switch ((inst >> 9) & 0x3F) {
+
+	case 0x12:		/* LHI333    */
+		imm = 1;
+		regular = 1;
+		load = 1;
+		len = 2;
+		addr_mode = 3;
+		idx_mode = 3;
+		break;
+	case 0x10:		/* LWI333    */
+		imm = 1;
+		regular = 1;
+		load = 1;
+		len = 4;
+		addr_mode = 3;
+		idx_mode = 3;
+		break;
+	case 0x11:		/* LWI333.bi */
+		imm = 1;
+		regular = 0;
+		load = 1;
+		len = 4;
+		addr_mode = 3;
+		idx_mode = 3;
+		break;
+	case 0x1A:		/* LWI450    */
+		imm = 0;
+		regular = 1;
+		load = 1;
+		len = 4;
+		addr_mode = 5;
+		idx_mode = 4;
+		break;
+	case 0x16:		/* SHI333    */
+		imm = 1;
+		regular = 1;
+		load = 0;
+		len = 2;
+		addr_mode = 3;
+		idx_mode = 3;
+		break;
+	case 0x14:		/* SWI333    */
+		imm = 1;
+		regular = 1;
+		load = 0;
+		len = 4;
+		addr_mode = 3;
+		idx_mode = 3;
+		break;
+	case 0x15:		/* SWI333.bi */
+		imm = 1;
+		regular = 0;
+		load = 0;
+		len = 4;
+		addr_mode = 3;
+		idx_mode = 3;
+		break;
+	case 0x1B:		/* SWI450    */
+		imm = 0;
+		regular = 1;
+		load = 0;
+		len = 4;
+		addr_mode = 5;
+		idx_mode = 4;
+		break;
+
+	default:
+		return -EFAULT;
+	}
+
+	if (addr_mode == 3) {
+		unaligned_addr = *idx_to_addr(regs, RA3(inst));
+		source_idx = RA3(inst);
+	} else {
+		unaligned_addr = *idx_to_addr(regs, RA5(inst));
+		source_idx = RA5(inst);
+	}
+
+	if (idx_mode == 3)
+		target_idx = RT3(inst);
+	else
+		target_idx = RT4(inst);
+
+	if (imm)
+		shift = IMM3U(inst) * len;
+
+	if (regular)
+		unaligned_addr += shift;
+	else
+		*idx_to_addr(regs, source_idx) = unaligned_addr + shift;
+
+	if (load) {
+
+		if (!va_readable(regs, unaligned_addr))
+			return -EACCES;
+
+		if (!access_ok(VERIFY_READ, (void *)unaligned_addr, len))
+			return -EACCES;
+
+		*idx_to_addr(regs, target_idx) = get_data(unaligned_addr, len);
+	} else {
+
+		if (!va_writable(regs, unaligned_addr))
+			return -EACCES;
+
+		if (!access_ok(VERIFY_WRITE, (void *)unaligned_addr, len))
+			return -EACCES;
+
+		target_val = *idx_to_addr(regs, target_idx);
+		set_data(unaligned_addr, target_val, len);
+	}
+
+	regs->ipc += 2;
+
+	return 0;
+}
+
+static inline int do_32(unsigned long inst, struct pt_regs *regs)
+{
+	int imm, regular, load, len, sign_ext;
+	unsigned long unsligned_addr, target_val, shift;
+
+	unsligned_addr = *idx_to_addr(regs, RA(inst));
+
+	switch ((inst >> 25) << 1) {
+
+	case 0x02:		/* LHI       */
+		imm = 1;
+		regular = 1;
+		load = 1;
+		len = 2;
+		sign_ext = 0;
+		break;
+	case 0x0A:		/* LHI.bi    */
+		imm = 1;
+		regular = 0;
+		load = 1;
+		len = 2;
+		sign_ext = 0;
+		break;
+	case 0x22:		/* LHSI      */
+		imm = 1;
+		regular = 1;
+		load = 1;
+		len = 2;
+		sign_ext = 1;
+		break;
+	case 0x2A:		/* LHSI.bi   */
+		imm = 1;
+		regular = 0;
+		load = 1;
+		len = 2;
+		sign_ext = 1;
+		break;
+	case 0x04:		/* LWI       */
+		imm = 1;
+		regular = 1;
+		load = 1;
+		len = 4;
+		sign_ext = 0;
+		break;
+	case 0x0C:		/* LWI.bi    */
+		imm = 1;
+		regular = 0;
+		load = 1;
+		len = 4;
+		sign_ext = 0;
+		break;
+	case 0x12:		/* SHI       */
+		imm = 1;
+		regular = 1;
+		load = 0;
+		len = 2;
+		sign_ext = 0;
+		break;
+	case 0x1A:		/* SHI.bi    */
+		imm = 1;
+		regular = 0;
+		load = 0;
+		len = 2;
+		sign_ext = 0;
+		break;
+	case 0x14:		/* SWI       */
+		imm = 1;
+		regular = 1;
+		load = 0;
+		len = 4;
+		sign_ext = 0;
+		break;
+	case 0x1C:		/* SWI.bi    */
+		imm = 1;
+		regular = 0;
+		load = 0;
+		len = 4;
+		sign_ext = 0;
+		break;
+
+	default:
+		switch (inst & 0xff) {
+
+		case 0x01:	/* LH        */
+			imm = 0;
+			regular = 1;
+			load = 1;
+			len = 2;
+			sign_ext = 0;
+			break;
+		case 0x05:	/* LH.bi     */
+			imm = 0;
+			regular = 0;
+			load = 1;
+			len = 2;
+			sign_ext = 0;
+			break;
+		case 0x11:	/* LHS       */
+			imm = 0;
+			regular = 1;
+			load = 1;
+			len = 2;
+			sign_ext = 1;
+			break;
+		case 0x15:	/* LHS.bi    */
+			imm = 0;
+			regular = 0;
+			load = 1;
+			len = 2;
+			sign_ext = 1;
+			break;
+		case 0x02:	/* LW        */
+			imm = 0;
+			regular = 1;
+			load = 1;
+			len = 4;
+			sign_ext = 0;
+			break;
+		case 0x06:	/* LW.bi     */
+			imm = 0;
+			regular = 0;
+			load = 1;
+			len = 4;
+			sign_ext = 0;
+			break;
+		case 0x09:	/* SH        */
+			imm = 0;
+			regular = 1;
+			load = 0;
+			len = 2;
+			sign_ext = 0;
+			break;
+		case 0x0D:	/* SH.bi     */
+			imm = 0;
+			regular = 0;
+			load = 0;
+			len = 2;
+			sign_ext = 0;
+			break;
+		case 0x0A:	/* SW        */
+			imm = 0;
+			regular = 1;
+			load = 0;
+			len = 4;
+			sign_ext = 0;
+			break;
+		case 0x0E:	/* SW.bi     */
+			imm = 0;
+			regular = 0;
+			load = 0;
+			len = 4;
+			sign_ext = 0;
+			break;
+
+		default:
+			return -EFAULT;
+		}
+	}
+
+	if (imm)
+		shift = IMM(inst) * len;
+	else
+		shift = *idx_to_addr(regs, RB(inst)) << SV(inst);
+
+	if (regular)
+		unsligned_addr += shift;
+	else
+		*idx_to_addr(regs, RA(inst)) = unsligned_addr + shift;
+
+	if (load) {
+
+		if (!va_readable(regs, unsligned_addr))
+			return -EACCES;
+
+		if (!access_ok(VERIFY_READ, (void *)unsligned_addr, len))
+			return -EACCES;
+
+		if (sign_ext)
+			*idx_to_addr(regs, RT(inst)) =
+			    sign_extend(get_data(unsligned_addr, len), len);
+		else
+			*idx_to_addr(regs, RT(inst)) =
+			    get_data(unsligned_addr, len);
+	} else {
+
+		if (!va_writable(regs, unsligned_addr))
+			return -EACCES;
+
+		if (!access_ok(VERIFY_WRITE, (void *)unsligned_addr, len))
+			return -EACCES;
+
+		target_val = *idx_to_addr(regs, RT(inst));
+		set_data(unsligned_addr, target_val, len);
+	}
+
+	regs->ipc += 4;
+
+	return 0;
+}
+
+static int _do_unaligned_access(unsigned long entry, unsigned long addr,
+				unsigned long type, struct pt_regs *regs)
+{
+	unsigned long inst;
+	int ret = -EFAULT;
+
+	if (user_mode(regs)) {
+		/* user mode */
+		if (!va_present(current->mm, addr))
+			return ret;
+	} else {
+		/* kernel mode */
+		if (!va_kernel_present(addr))
+			return ret;
+	}
+
+	inst = get_inst(regs->ipc);
+
+	DEBUG(mode & 0x04, 1,
+	      "Faulting Addr: 0x%08lx, PC: 0x%08lx [ 0x%08lx ]\n", addr,
+	      regs->ipc, inst);
+
+	if ((user_mode(regs) && (mode & 0x01))
+	    || (!user_mode(regs) && (mode & 0x02))) {
+
+		mm_segment_t seg = get_fs();
+
+		set_fs(KERNEL_DS);
+
+		if (inst & 0x80000000)
+			ret = do_16((inst >> 16) & 0xffff, regs);
+		else
+			ret = do_32(inst, regs);
+
+		set_fs(seg);
+	}
+
+	return ret;
+}
+
+#ifdef CONFIG_PROC_FS
+
+static int proc_alignment_read(struct file *file, char __user * ubuf,
+			       size_t count, loff_t * ppos)
+{
+	char p[80];
+	int ret;
+
+	ret = sprintf(p, "(0x01) User Mode: %s\n"
+		      "(0x02) Kernel Mode: %s\n"
+		      "(0x04) Warning: %s\n",
+		      mode & 0x01 ? "on" : "off",
+		      mode & 0x02 ? "on" : "off", mode & 0x04 ? "on" : "off");
+
+	return simple_read_from_buffer(ubuf, count, ppos, p, ret);
+}
+
+#define INPUTLEN 12		/* '0' + 'x' + 8digit + '\n' + '\0' */
+
+static ssize_t proc_alignment_write(struct file *file,
+				    const char __user * ubuf, size_t count,
+				    loff_t * ppos)
+{
+	unsigned long en;
+	char *endp;
+	char inbuf[INPUTLEN];
+
+	if (count > INPUTLEN - 1)
+		return -EFAULT;
+
+	if (copy_from_user(inbuf, ubuf, count))
+		return -EFAULT;
+
+	inbuf[count - 1] = '\0';
+
+	en = simple_strtoul(inbuf, &endp, 0);
+	if (en > 0x07)
+		return -EFAULT;
+
+	mode = en & 0x7;
+
+	return count;
+}
+
+static const struct file_operations fops = {
+	.open = simple_open,
+	.read = proc_alignment_read,
+	.write = proc_alignment_write,
+};
+#endif /* CONFIG_PROC_FS */
+
+static int __init unaligned_access_init(void)
+{
+#ifdef CONFIG_PROC_FS
+	static struct proc_dir_entry *res_alignment;
+
+	if (!proc_dir_cpu)
+		if (!(proc_dir_cpu = proc_mkdir("cpu", NULL)))
+			return -ENOMEM;
+
+	if (!
+	    (res_alignment =
+	     proc_create("alignment", S_IWUSR | S_IRUGO, proc_dir_cpu, &fops)))
+		return -ENOMEM;
+
+#endif
+	do_unaligned_access = _do_unaligned_access;
+
+	return 0;
+}
+
+static void __exit unaligned_access_exit(void)
+{
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("alignment", proc_dir_cpu);
+#endif
+	do_unaligned_access = NULL;
+}
+
+MODULE_DESCRIPTION("Unaligned Access Handler");
+MODULE_LICENSE("GPL");
+
+module_init(unaligned_access_init);
+module_exit(unaligned_access_exit);
-- 
1.7.9.5

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

* [PATCH 05/31] nds32: MMU definitions
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (3 preceding siblings ...)
  2017-11-08  5:54 ` [PATCH 04/31] nds32: Exception handling Greentime Hu
@ 2017-11-08  5:54 ` Greentime Hu
  2017-11-08  8:36   ` Arnd Bergmann
  2017-11-08  5:54 ` [PATCH 06/31] nds32: MMU initialization Greentime Hu
                   ` (27 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:54 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/asm/fixmap.h   |   41 ++++
 arch/nds32/include/asm/highmem.h  |   78 +++++++
 arch/nds32/include/asm/memory.h   |  147 +++++++++++++
 arch/nds32/include/asm/mmu.h      |   25 +++
 arch/nds32/include/asm/page.h     |   78 +++++++
 arch/nds32/include/asm/pgalloc.h  |  109 ++++++++++
 arch/nds32/include/asm/pgtable.h  |  426 +++++++++++++++++++++++++++++++++++++
 arch/nds32/include/asm/shmparam.h |   33 +++
 8 files changed, 937 insertions(+)
 create mode 100644 arch/nds32/include/asm/fixmap.h
 create mode 100644 arch/nds32/include/asm/highmem.h
 create mode 100644 arch/nds32/include/asm/memory.h
 create mode 100644 arch/nds32/include/asm/mmu.h
 create mode 100644 arch/nds32/include/asm/page.h
 create mode 100644 arch/nds32/include/asm/pgalloc.h
 create mode 100644 arch/nds32/include/asm/pgtable.h
 create mode 100644 arch/nds32/include/asm/shmparam.h

diff --git a/arch/nds32/include/asm/fixmap.h b/arch/nds32/include/asm/fixmap.h
new file mode 100644
index 0000000..38e8ee1
--- /dev/null
+++ b/arch/nds32/include/asm/fixmap.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_NDS32_FIXMAP_H
+#define __ASM_NDS32_FIXMAP_H
+
+#ifdef CONFIG_HIGHMEM
+#include <linux/threads.h>
+#include <asm/kmap_types.h>
+#endif
+
+enum fixed_addresses {
+	FIX_KMAP_RESERVED,
+	FIX_KMAP_BEGIN,
+#ifdef CONFIG_HIGHMEM
+	FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS),
+#endif
+#ifdef CONFIG_EARLY_PRINTK
+	FIX_EARLY_DEBUG,
+#endif
+	__end_of_fixed_addresses
+};
+#define FIXADDR_TOP             ((unsigned long) (-(16 * PAGE_SIZE)))
+#define FIXADDR_SIZE		((__end_of_fixed_addresses) << PAGE_SHIFT)
+#define FIXADDR_START		(FIXADDR_TOP - FIXADDR_SIZE)
+
+#include <asm-generic/fixmap.h>
+#endif /* __ASM_NDS32_FIXMAP_H */
diff --git a/arch/nds32/include/asm/highmem.h b/arch/nds32/include/asm/highmem.h
new file mode 100644
index 0000000..6a569c1
--- /dev/null
+++ b/arch/nds32/include/asm/highmem.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ASM_HIGHMEM_H
+#define _ASM_HIGHMEM_H
+
+#include <asm/proc-fns.h>
+#include <asm/kmap_types.h>
+#include <asm/fixmap.h>
+#include <asm/pgtable.h>
+
+/*
+ * 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.
+ */
+/*
+ * Ordering is (from lower to higher memory addresses):
+ *
+ * high_memory
+ *			Persistent kmap area
+ * PKMAP_BASE
+ *			fixed_addresses
+ * FIXADDR_START
+ * FIXADDR_TOP
+ *			Vmalloc area
+ * VMALLOC_START
+ * VMALLOC_END
+ */
+#define PKMAP_BASE		((FIXADDR_START - PGDIR_SIZE) & (PGDIR_MASK))
+#define LAST_PKMAP		PTRS_PER_PTE
+#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))
+#define kmap_prot		PAGE_KERNEL
+
+static inline void flush_cache_kmaps(void)
+{
+	cpu_dcache_wbinval_all();
+}
+
+/* declarations for highmem.c */
+extern unsigned long highstart_pfn, highend_pfn;
+
+extern pte_t *pkmap_page_table;
+
+extern void *kmap_high(struct page *page);
+extern void kunmap_high(struct page *page);
+
+extern void kmap_init(void);
+
+/*
+ * The following functions are already defined by <linux/highmem.h>
+ * when CONFIG_HIGHMEM is not set.
+ */
+#ifdef CONFIG_HIGHMEM
+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);
+#endif
+
+#endif
diff --git a/arch/nds32/include/asm/memory.h b/arch/nds32/include/asm/memory.h
new file mode 100644
index 0000000..5043d59
--- /dev/null
+++ b/arch/nds32/include/asm/memory.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_NDS32_MEMORY_H
+#define __ASM_NDS32_MEMORY_H
+
+#include <linux/compiler.h>
+
+#ifndef __ASSEMBLY__
+#include <asm/page.h>
+#endif
+
+#ifndef PHYS_OFFSET
+#define PHYS_OFFSET     (CONFIG_MEMORY_START)
+#endif
+
+#ifndef PAGE_OFFSET
+#define PAGE_OFFSET     (0xC0000000)
+#endif
+
+#ifndef __virt_to_bus
+#define __virt_to_bus	__virt_to_phys
+#endif
+
+#ifndef __bus_to_virt
+#define __bus_to_virt	__phys_to_virt
+#endif
+
+#ifndef TASK_SIZE
+/*
+ * TASK_SIZE - the maximum size of a user space task.
+ * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area
+ */
+#define TASK_SIZE		(0xbf000000UL)
+#define TASK_UNMAPPED_BASE	(0x40000000UL)
+#endif
+
+/*
+ * Page offset: 3GB
+ */
+#ifndef PAGE_OFFSET
+#define PAGE_OFFSET		(0xc0000000)
+#endif
+
+/*
+ * Physical vs virtual RAM address space conversion.  These are
+ * private definitions which should NOT be used outside memory.h
+ * files.  Use virt_to_phys/phys_to_virt/__pa/__va instead.
+ */
+#ifndef __virt_to_phys
+#define __virt_to_phys(x)	((x) - PAGE_OFFSET + PHYS_OFFSET)
+#define __phys_to_virt(x)	((x) - PHYS_OFFSET + PAGE_OFFSET)
+#endif
+
+/*
+ * The module space lives between the addresses given by TASK_SIZE
+ * and PAGE_OFFSET - it must be within 32MB of the kernel text.
+ */
+#define MODULES_END	(PAGE_OFFSET)
+#define MODULES_VADDR	(MODULES_END - 16*1048576)
+
+#if TASK_SIZE > MODULES_VADDR
+#error Top of user space clashes with start of module space
+#endif
+
+#ifndef __ASSEMBLY__
+
+/*
+ * The DMA mask corresponding to the maximum bus address allocatable
+ * using GFP_DMA.  The default here places no restriction on DMA
+ * allocations.  This must be the smallest DMA mask in the system,
+ * so a successful GFP_DMA allocation will always satisfy this.
+ */
+#ifndef ISA_DMA_THRESHOLD
+#define ISA_DMA_THRESHOLD	(0xffffffffULL)
+#endif
+
+/*
+ * PFNs are used to describe any physical page; this means
+ * PFN 0 == physical address 0.
+ *
+ * This is the PFN of the first RAM page in the kernel
+ * direct-mapped view.  We assume this is the first page
+ * of RAM in the mem_map as well.
+ */
+#define PHYS_PFN_OFFSET	(PHYS_OFFSET >> PAGE_SHIFT)
+
+/*
+ * Drivers should NOT use these either.
+ */
+#define __pa(x)			__virt_to_phys((unsigned long)(x))
+#define __va(x)			((void *)__phys_to_virt((unsigned long)(x)))
+
+/*
+ * Conversion between a struct page and a physical address.
+ *
+ * Note: when converting an unknown physical address to a
+ * struct page, the resulting pointer must be validated
+ * using VALID_PAGE().  It must return an invalid struct page
+ * for any physical address not corresponding to a system
+ * RAM address.
+ *
+ *  pfn_valid(pfn)	indicates whether a PFN number is valid
+ *
+ *  virt_to_page(k)	convert a _valid_ virtual address to struct page *
+ *  virt_addr_valid(k)	indicates whether a virtual address is valid
+ */
+#ifndef CONFIG_DISCONTIGMEM
+
+#define ARCH_PFN_OFFSET		PHYS_PFN_OFFSET
+#define pfn_valid(pfn)		((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
+
+#define virt_to_page(kaddr)	(pfn_to_page(__pa(kaddr) >> PAGE_SHIFT))
+#define virt_addr_valid(kaddr)	((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
+
+#else /* CONFIG_DISCONTIGMEM */
+#error CONFIG_DISCONTIGMEM is not supported yet.
+#endif /* !CONFIG_DISCONTIGMEM */
+
+#define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
+
+/*
+ * Optional device DMA address remapping. Do _not_ use directly!
+ * We should really eliminate virt_to_bus() here - it's deprecated.
+ */
+#define page_to_dma(dev, page)		((dma_addr_t)__virt_to_phys((unsigned long)page_address(page)))
+#define dma_to_virt(dev, addr)		((void *)__phys_to_virt(addr))
+#define virt_to_dma(dev, addr)		((dma_addr_t)__virt_to_phys((unsigned long)(addr)))
+
+#endif
+
+#include <asm-generic/memory_model.h>
+
+#endif
diff --git a/arch/nds32/include/asm/mmu.h b/arch/nds32/include/asm/mmu.h
new file mode 100644
index 0000000..147fd06
--- /dev/null
+++ b/arch/nds32/include/asm/mmu.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NDS32_MMU_H
+#define __NDS32_MMU_H
+
+typedef struct {
+	unsigned int id;
+	void *vdso;
+} mm_context_t;
+
+#endif
diff --git a/arch/nds32/include/asm/page.h b/arch/nds32/include/asm/page.h
new file mode 100644
index 0000000..7e93d69
--- /dev/null
+++ b/arch/nds32/include/asm/page.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ASMNDS32_PAGE_H
+#define _ASMNDS32_PAGE_H
+
+#ifdef CONFIG_ANDES_PAGE_SIZE_4KB
+#define PAGE_SHIFT      12
+#endif
+#ifdef CONFIG_ANDES_PAGE_SIZE_8KB
+#define PAGE_SHIFT      13
+#endif
+#include <linux/const.h>
+#define PAGE_SIZE       (_AC(1,UL) << PAGE_SHIFT)
+#define PAGE_MASK       (~(PAGE_SIZE-1))
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+struct page;
+struct vm_area_struct;
+#ifndef CONFIG_CPU_CACHE_NONALIASING
+extern void copy_user_highpage(struct page *to, struct page *from,
+			       unsigned long vaddr, struct vm_area_struct *vma);
+extern void clear_user_highpage(struct page *page, unsigned long vaddr);
+
+#define __HAVE_ARCH_COPY_USER_HIGHPAGE
+#define clear_user_highpage	clear_user_highpage
+#else
+#define clear_user_page(page, vaddr, pg)        clear_page(page)
+#define copy_user_page(to, from, vaddr, pg)     copy_page(to, from)
+#endif
+
+void clear_page(void *page);
+void copy_page(void *to, void *from);
+
+typedef unsigned long pte_t;
+typedef unsigned long pmd_t;
+typedef unsigned long pgd_t;
+typedef unsigned long pgprot_t;
+
+#define pte_val(x)      (x)
+#define pmd_val(x)      (x)
+#define pgd_val(x)	(x)
+#define pgprot_val(x)   (x)
+
+#define __pte(x)        (x)
+#define __pmd(x)        (x)
+#define __pgd(x)        (x)
+#define __pgprot(x)     (x)
+
+typedef struct page *pgtable_t;
+
+#include <asm/memory.h>
+#include <asm-generic/getorder.h>
+
+#endif /* !__ASSEMBLY__ */
+
+#define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
+				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/arch/nds32/include/asm/pgalloc.h b/arch/nds32/include/asm/pgalloc.h
new file mode 100644
index 0000000..0b7530b
--- /dev/null
+++ b/arch/nds32/include/asm/pgalloc.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ASMNDS32_PGALLOC_H
+#define _ASMNDS32_PGALLOC_H
+
+#include <asm/processor.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/proc-fns.h>
+
+/*
+ * Since we have only two-level page tables, these are trivial
+ */
+#define pmd_alloc_one(mm, addr)		({ BUG(); ((pmd_t *)2); })
+#define pmd_free(mm, pmd)			do { } while (0)
+#define pgd_populate(mm, pmd, pte)	BUG()
+#define pmd_pgtable(pmd) pmd_page(pmd)
+
+extern pgd_t *pgd_alloc(struct mm_struct *mm);
+extern void pgd_free(struct mm_struct *mm, pgd_t * pgd);
+
+#define check_pgt_cache()		do { } while (0)
+
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+					  unsigned long addr)
+{
+	pte_t *pte;
+
+	pte =
+	    (pte_t *) __get_free_page(GFP_KERNEL | __GFP_RETRY_MAYFAIL |
+				      __GFP_ZERO);
+
+	return pte;
+}
+
+static inline pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+	pgtable_t pte;
+
+	pte = alloc_pages(GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_ZERO, 0);
+	if (pte)
+		cpu_dcache_wb_page((unsigned long)page_address(pte));
+
+	return pte;
+}
+
+/*
+ * Free one PTE table.
+ */
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t * pte)
+{
+	if (pte) {
+		free_page((unsigned long)pte);
+	}
+}
+
+static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
+{
+	__free_page(pte);
+}
+
+/*
+ * Populate the pmdp entry with a pointer to the pte.  This pmd is part
+ * of the mm address space.
+ *
+ * Ensure that we always set both PMD entries.
+ */
+static inline void
+pmd_populate_kernel(struct mm_struct *mm, pmd_t * pmdp, pte_t * ptep)
+{
+	unsigned long pte_ptr = (unsigned long)ptep;
+	unsigned long pmdval;
+
+	BUG_ON(mm != &init_mm);
+
+	/*
+	 * The pmd must be loaded with the physical
+	 * address of the PTE table
+	 */
+	pmdval = __pa(pte_ptr) | _PAGE_KERNEL_TABLE;
+	set_pmd(pmdp, __pmd(pmdval));
+}
+
+static inline void
+pmd_populate(struct mm_struct *mm, pmd_t * pmdp, pgtable_t ptep)
+{
+	unsigned long pmdval;
+
+	BUG_ON(mm == &init_mm);
+
+	pmdval = page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE;
+	set_pmd(pmdp, __pmd(pmdval));
+}
+
+#endif
diff --git a/arch/nds32/include/asm/pgtable.h b/arch/nds32/include/asm/pgtable.h
new file mode 100644
index 0000000..a09f1f8
--- /dev/null
+++ b/arch/nds32/include/asm/pgtable.h
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ASMNDS32_PGTABLE_H
+#define _ASMNDS32_PGTABLE_H
+
+#define __PAGETABLE_PMD_FOLDED
+#include <asm-generic/4level-fixup.h>
+#include <asm-generic/sizes.h>
+
+#include <asm/memory.h>
+#include <asm/nds32.h>
+#ifndef __ASSEMBLY__
+#include <asm/fixmap.h>
+#include <asm-generic/io.h>
+#include <nds32_intrinsic.h>
+#endif
+
+#ifdef CONFIG_CACHE_L2
+#include <asm/l2_cache.h>
+#endif
+
+#ifdef CONFIG_ANDES_PAGE_SIZE_4KB
+#define PGDIR_SHIFT      22
+#define PTRS_PER_PGD     1024
+#define PMD_SHIFT        22
+#define PTRS_PER_PMD     1
+#define PTRS_PER_PTE     1024
+#endif
+
+#ifdef CONFIG_ANDES_PAGE_SIZE_8KB
+#define PGDIR_SHIFT      24
+#define PTRS_PER_PGD     256
+#define PMD_SHIFT        24
+#define PTRS_PER_PMD     1
+#define PTRS_PER_PTE     2048
+#endif
+
+#ifndef __ASSEMBLY__
+extern void __pte_error(const char *file, int line, unsigned long val);
+extern void __pmd_error(const char *file, int line, unsigned long val);
+extern void __pgd_error(const char *file, int line, unsigned long val);
+
+#define pte_ERROR(pte)		__pte_error(__FILE__, __LINE__, pte_val(pte))
+#define pmd_ERROR(pmd)		__pmd_error(__FILE__, __LINE__, pmd_val(pmd))
+#define pgd_ERROR(pgd)		__pgd_error(__FILE__, __LINE__, pgd_val(pgd))
+#endif /* !__ASSEMBLY__ */
+
+#define PMD_SIZE		(1UL << PMD_SHIFT)
+#define PMD_MASK		(~(PMD_SIZE-1))
+#define PGDIR_SIZE		(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK		(~(PGDIR_SIZE-1))
+
+/*
+ * This is the lowest virtual address we can permit any user space
+ * mapping to be mapped at.  This is particularly important for
+ * non-high vector CPUs.
+ */
+#define FIRST_USER_ADDRESS	0x8000
+
+#ifdef CONFIG_HIGHMEM
+#define CONSISTENT_BASE		((PKMAP_BASE) - (SZ_2M))
+#define CONSISTENT_END		(PKMAP_BASE)
+#else
+#define CONSISTENT_BASE		(FIXADDR_START - SZ_2M)
+#define CONSISTENT_END		(FIXADDR_START)
+#endif
+#define CONSISTENT_OFFSET(x)	(((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
+
+#ifdef CONFIG_HIGHMEM
+#ifndef __ASSEMBLY__
+#include <asm/highmem.h>
+#endif
+#endif
+
+#define VMALLOC_RESERVE 	SZ_128M
+#define VMALLOC_END		(CONSISTENT_BASE - PAGE_SIZE)
+#define VMALLOC_START		((VMALLOC_END) - VMALLOC_RESERVE)
+#define VMALLOC_VMADDR(x)	((unsigned long)(x))
+#define MAXMEM			__pa(VMALLOC_START)
+#define MAXMEM_PFN		PFN_DOWN(MAXMEM)
+
+#define FIRST_USER_PGD_NR	0
+#define USER_PTRS_PER_PGD	((TASK_SIZE/PGDIR_SIZE) + FIRST_USER_PGD_NR)
+
+/* L2 PTE */
+#define _PAGE_V			(1UL << 0)
+
+#define _PAGE_M_XKRW            (0UL << 1)
+#define _PAGE_M_UR_KR		(1UL << 1)
+#define _PAGE_M_UR_KRW		(2UL << 1)
+#define _PAGE_M_URW_KRW		(3UL << 1)
+#define _PAGE_M_KR		(5UL << 1)
+#define _PAGE_M_KRW		(7UL << 1)
+
+#define _PAGE_D			(1UL << 4)
+#define _PAGE_E			(1UL << 5)
+#define _PAGE_A			(1UL << 6)
+#define _PAGE_G			(1UL << 7)
+
+#define _PAGE_C_DEV		(0UL << 8)
+#define _PAGE_C_DEV_WB		(1UL << 8)
+#define _PAGE_C_MEM		(2UL << 8)
+#define _PAGE_C_MEM_SHRD_WB	(4UL << 8)
+#define _PAGE_C_MEM_SHRD_WT	(5UL << 8)
+#define _PAGE_C_MEM_WB		(6UL << 8)
+#define _PAGE_C_MEM_WT		(7UL << 8)
+
+#define _PAGE_L			(1UL << 11)
+
+#define _HAVE_PAGE_L		(_PAGE_L)
+#define _PAGE_FILE		(1UL << 1)
+#define _PAGE_YOUNG		0
+#define _PAGE_M_MASK		_PAGE_M_KRW
+#define _PAGE_C_MASK		_PAGE_C_MEM_WT
+
+#ifdef CONFIG_SMP
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+#define _PAGE_CACHE_SHRD	_PAGE_C_MEM_SHRD_WT
+#else
+#define _PAGE_CACHE_SHRD	_PAGE_C_MEM_SHRD_WB
+#endif
+#else
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+#define _PAGE_CACHE_SHRD	_PAGE_C_MEM_WT
+#else
+#define _PAGE_CACHE_SHRD	_PAGE_C_MEM_WB
+#endif
+#endif
+
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+#define _PAGE_CACHE		_PAGE_C_MEM_WT
+#else
+#define _PAGE_CACHE		_PAGE_C_MEM_WB
+#endif
+
+/*
+ * + Level 1 descriptor (PMD)
+ */
+#define PMD_TYPE_TABLE		0
+
+#ifndef __ASSEMBLY__
+
+#define _PAGE_USER_TABLE     PMD_TYPE_TABLE
+#define _PAGE_KERNEL_TABLE   PMD_TYPE_TABLE
+
+#define PAGE_EXEC	__pgprot(_PAGE_V | _PAGE_M_XKRW | _PAGE_E)
+#define PAGE_NONE	__pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_A)
+#define PAGE_READ	__pgprot(_PAGE_V | _PAGE_M_UR_KR)
+#define PAGE_RDWR	__pgprot(_PAGE_V | _PAGE_M_URW_KRW | _PAGE_D)
+#define PAGE_COPY	__pgprot(_PAGE_V | _PAGE_M_UR_KR)
+
+#define PAGE_UXKRWX_V1	__pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE_SHRD)
+#define PAGE_UXKRWX_V2	__pgprot(_PAGE_V | _PAGE_M_XKRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE_SHRD)
+#define PAGE_URXKRWX_V2	__pgprot(_PAGE_V | _PAGE_M_UR_KRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE_SHRD)
+#define PAGE_CACHE_L1	__pgprot(_HAVE_PAGE_L | _PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE)
+#define PAGE_MEMORY	__pgprot(_HAVE_PAGE_L | _PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE_SHRD)
+#define PAGE_KERNEL	__pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE_SHRD)
+#define PAGE_DEVICE    __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_G | _PAGE_C_DEV)
+#endif /* __ASSEMBLY__ */
+
+/*         xwr */
+#define __P000  (PAGE_NONE | _PAGE_CACHE_SHRD)
+#define __P001  (PAGE_READ | _PAGE_CACHE_SHRD)
+#define __P010  (PAGE_COPY | _PAGE_CACHE_SHRD)
+#define __P011  (PAGE_COPY | _PAGE_CACHE_SHRD)
+#define __P100  (PAGE_EXEC | _PAGE_CACHE_SHRD)
+#define __P101  (PAGE_READ | _PAGE_E | _PAGE_CACHE_SHRD)
+#define __P110  (PAGE_COPY | _PAGE_E | _PAGE_CACHE_SHRD)
+#define __P111  (PAGE_COPY | _PAGE_E | _PAGE_CACHE_SHRD)
+
+#define __S000  (PAGE_NONE | _PAGE_CACHE_SHRD)
+#define __S001  (PAGE_READ | _PAGE_CACHE_SHRD)
+#define __S010  (PAGE_RDWR | _PAGE_CACHE_SHRD)
+#define __S011  (PAGE_RDWR | _PAGE_CACHE_SHRD)
+#define __S100  (PAGE_EXEC | _PAGE_CACHE_SHRD)
+#define __S101  (PAGE_READ | _PAGE_E | _PAGE_CACHE_SHRD)
+#define __S110  (PAGE_RDWR | _PAGE_E | _PAGE_CACHE_SHRD)
+#define __S111  (PAGE_RDWR | _PAGE_E | _PAGE_CACHE_SHRD)
+
+#ifndef __ASSEMBLY__
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern struct page *empty_zero_page;
+extern void paging_init(void);
+#define ZERO_PAGE(vaddr)	(empty_zero_page)
+
+#define pte_pfn(pte)		(pte_val(pte) >> PAGE_SHIFT)
+#define pfn_pte(pfn,prot)	(__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)))
+
+#define pte_none(pte)	        !(pte_val(pte))
+#define pte_clear(mm,addr,ptep)	set_pte_at((mm),(addr),(ptep), __pte(0))
+#define pte_page(pte)		(pfn_to_page(pte_pfn(pte)))
+
+#define pte_index(address)                   (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset_kernel(dir, address)	     ((pte_t *)pmd_page_kernel(*(dir)) + pte_index(address))
+#define pte_offset_map(dir, address)	     ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
+#define pte_offset_map_nested(dir, address)  pte_offset_map(dir, address)
+#define pmd_page_kernel(pmd)	  	     ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+
+#define pte_unmap(pte)		do { } while (0)
+#define pte_unmap_nested(pte)	do { } while (0)
+
+#define pmd_off_k(address)	pmd_offset(pgd_offset_k(address), address)
+
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+/*
+ * Set a level 1 translation table entry, and clean it out of
+ * any caches such that the MMUs can load it correctly.
+ */
+static inline void set_pmd(pmd_t * pmdp, pmd_t pmd)
+{
+
+	*pmdp = pmd;
+#if !defined(CONFIG_CPU_DCACHE_DISABLE) && !defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
+	__asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (pmdp):"memory");
+	__nds32__msync_all();
+	__nds32__dsb();
+#endif
+}
+
+/*
+ * Set a PTE and flush it out
+ */
+static inline void set_pte(pte_t * ptep, pte_t pte)
+{
+
+	*ptep = pte;
+#if !defined(CONFIG_CPU_DCACHE_DISABLE) && !defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
+	__asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (ptep):"memory");
+	__nds32__msync_all();
+	__nds32__dsb();
+#endif
+}
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+
+/*
+ * pte_write: 	     this page is writeable for user mode
+ * pte_read:         this page is readable for user mode
+ * pte_kernel_write: this page is writeable for kernel mode
+ *
+ * We don't have pte_kernel_read because kernel always can read.
+ *
+ * */
+
+#define pte_present(pte)        (pte_val(pte) & _PAGE_V)
+#define pte_write(pte)          ((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_URW_KRW)
+#define pte_read(pte)		(((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_UR_KR) || \
+				((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_UR_KRW) || \
+				((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_URW_KRW))
+#define pte_kernel_write(pte)   (((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_URW_KRW) || \
+				((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_UR_KRW) || \
+				((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_KRW) || \
+				(((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_XKRW) && pte_exec(pte)))
+#define pte_exec(pte)		(pte_val(pte) & _PAGE_E)
+#define pte_dirty(pte)		(pte_val(pte) & _PAGE_D)
+#define pte_young(pte)		(pte_val(pte) & _PAGE_YOUNG)
+
+/*
+ * The following only works if pte_present() is not true.
+ */
+#define pte_file(pte)		(pte_val(pte) & _PAGE_FILE)
+#define pte_to_pgoff(x)		(pte_val(x) >> 2)
+#define pgoff_to_pte(x)		__pte(((x) << 2) | _PAGE_FILE)
+
+#define PTE_FILE_MAX_BITS	29
+
+#define PTE_BIT_FUNC(fn,op) \
+static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
+
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+	pte_val(pte) = pte_val(pte) & ~_PAGE_M_MASK;
+	pte_val(pte) = pte_val(pte) | _PAGE_M_UR_KR;
+	return pte;
+}
+
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+	pte_val(pte) = pte_val(pte) & ~_PAGE_M_MASK;
+	pte_val(pte) = pte_val(pte) | _PAGE_M_URW_KRW;
+	return pte;
+}
+
+PTE_BIT_FUNC(exprotect, &=~_PAGE_E);
+PTE_BIT_FUNC(mkexec, |=_PAGE_E);
+PTE_BIT_FUNC(mkclean, &=~_PAGE_D);
+PTE_BIT_FUNC(mkdirty, |=_PAGE_D);
+PTE_BIT_FUNC(mkold, &=~_PAGE_YOUNG);
+PTE_BIT_FUNC(mkyoung, |=_PAGE_YOUNG);
+static inline int pte_special(pte_t pte)
+{
+	return 0;
+}
+
+static inline pte_t pte_mkspecial(pte_t pte)
+{
+	return pte;
+}
+
+/*
+ * Mark the prot value as uncacheable and unbufferable.
+ */
+#define pgprot_noncached(prot)	   __pgprot((pgprot_val(prot)&~_PAGE_C_MASK) | _PAGE_C_DEV)
+#define pgprot_writecombine(prot)  __pgprot((pgprot_val(prot)&~_PAGE_C_MASK) | _PAGE_C_DEV_WB)
+
+#define pmd_none(pmd)         (pmd_val(pmd)&0x1)
+#define pmd_present(pmd)      (!pmd_none(pmd))
+#define	pmd_bad(pmd)	      pmd_none(pmd)
+
+#define copy_pmd(pmdpd,pmdps)	set_pmd((pmdpd), *(pmdps))
+#define pmd_clear(pmdp)		set_pmd((pmdp), __pmd(1))
+
+static inline pmd_t __mk_pmd(pte_t * ptep, unsigned long prot)
+{
+	unsigned long ptr = (unsigned long)ptep;
+	pmd_t pmd;
+
+	/*
+	 * The pmd must be loaded with the physical
+	 * address of the PTE table
+	 */
+
+	pmd_val(pmd) = __virt_to_phys(ptr) | prot;
+	return pmd;
+}
+
+#define pmd_page(pmd)        virt_to_page(__va(pmd_val(pmd)))
+
+/*
+ * Permanent address of a page. We never have highmem, so this is trivial.
+ */
+#define pages_to_mb(x)       ((x) >> (20 - PAGE_SHIFT))
+
+/*
+ * 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,prot)	pfn_pte(page_to_pfn(page),prot)
+
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+#define pgd_none(pgd)		(0)
+#define pgd_bad(pgd)		(0)
+#define pgd_present(pgd)  	(1)
+#define pgd_clear(pgdp)		do { } while (0)
+
+#define page_pte_prot(page,prot)     	mk_pte(page, prot)
+#define page_pte(page)		        mk_pte(page, __pgprot(0))
+/*
+ *     L1PTE = $mr1 + ((virt >> PMD_SHIFT) << 2);
+ *     L2PTE = (((virt >> PAGE_SHIFT) & (PTRS_PER_PTE -1 )) << 2);
+ *     PPN = (phys & 0xfffff000);
+ *
+*/
+
+/* to find an entry in a page-table-directory */
+#define pgd_index(address)      (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
+#define pgd_offset(mm, address)	((mm)->pgd + pgd_index(address))
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(addr)      pgd_offset(&init_mm, addr)
+
+/* Find an entry in the second-level page table.. */
+#define pmd_offset(dir, addr)	((pmd_t *)(dir))
+
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	const unsigned long mask = 0xfff;
+	pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
+	return pte;
+}
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+/* Encode and decode a swap entry.
+ *
+ * We support up to 32GB of swap on 4k machines
+ */
+#define __swp_type(x)	 	     (((x).val >> 2) & 0x7f)
+#define __swp_offset(x)	   	     ((x).val >> 9)
+#define __swp_entry(type,offset)     ((swp_entry_t) { ((type) << 2) | ((offset) << 9) })
+#define __pte_to_swp_entry(pte)	     ((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(swp)	     ((pte_t) { (swp).val })
+
+/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+#define kern_addr_valid(addr)	(1)
+
+#include <asm-generic/pgtable.h>
+
+/*
+ * We provide our own arch_get_unmapped_area to cope with VIPT caches.
+ */
+#define HAVE_ARCH_UNMAPPED_AREA
+
+/*
+ * remap a physical address `phys' of size `size' with page protection `prot'
+ * into virtual address `from'
+ */
+
+#define pgtable_cache_init()       do { } while (0)
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASMNDS32_PGTABLE_H */
diff --git a/arch/nds32/include/asm/shmparam.h b/arch/nds32/include/asm/shmparam.h
new file mode 100644
index 0000000..5679648
--- /dev/null
+++ b/arch/nds32/include/asm/shmparam.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ASMNDS32_SHMPARAM_H
+#define _ASMNDS32_SHMPARAM_H
+
+/*
+ * This should be the size of the virtually indexed cache/ways,
+ * whichever is greater since the cache aliases every size/ways
+ * bytes.
+ */
+#define	SHMLBA	(4 * PAGE_SIZE)	/* attach addr a multiple of this */
+#define	REALSHMLBA	SHMLBA
+
+/*
+ * Enforce SHMLBA in shmat
+ */
+#define __ARCH_FORCE_SHMLBA
+
+#endif /* _ASMNDS32_SHMPARAM_H */
-- 
1.7.9.5

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

* [PATCH 06/31] nds32: MMU initialization
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (4 preceding siblings ...)
  2017-11-08  5:54 ` [PATCH 05/31] nds32: MMU definitions Greentime Hu
@ 2017-11-08  5:54 ` Greentime Hu
  2017-11-08  5:54 ` [PATCH 07/31] nds32: MMU fault handling and page table management Greentime Hu
                   ` (26 subsequent siblings)
  32 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:54 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/mm/highmem.c  |   92 +++++++++++++
 arch/nds32/mm/init.c     |  328 ++++++++++++++++++++++++++++++++++++++++++++++
 arch/nds32/mm/mm-nds32.c |  103 +++++++++++++++
 3 files changed, 523 insertions(+)
 create mode 100644 arch/nds32/mm/highmem.c
 create mode 100644 arch/nds32/mm/init.c
 create mode 100644 arch/nds32/mm/mm-nds32.c

diff --git a/arch/nds32/mm/highmem.c b/arch/nds32/mm/highmem.c
new file mode 100644
index 0000000..d5101bd
--- /dev/null
+++ b/arch/nds32/mm/highmem.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/export.h>
+#include <linux/highmem.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/bootmem.h>
+#include <asm/fixmap.h>
+#include <asm/tlbflush.h>
+
+void *kmap(struct page *page)
+{
+	unsigned long vaddr;
+	might_sleep();
+	if (!PageHighMem(page))
+		return page_address(page);
+	vaddr = (unsigned long)kmap_high(page);
+	return (void *)vaddr;
+}
+
+EXPORT_SYMBOL(kmap);
+
+void kunmap(struct page *page)
+{
+	BUG_ON(in_interrupt());
+	if (!PageHighMem(page))
+		return;
+	kunmap_high(page);
+}
+
+EXPORT_SYMBOL(kunmap);
+
+void *kmap_atomic(struct page *page)
+{
+	unsigned int idx;
+	unsigned long vaddr, pte;
+	int type;
+	pte_t *ptep;
+
+	preempt_disable();
+	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);
+	pte = (page_to_pfn(page) << PAGE_SHIFT) | (PAGE_KERNEL);
+	ptep = pte_offset_kernel(pmd_off_k(vaddr), vaddr);
+	set_pte(ptep, pte);
+
+	__nds32__tlbop_inv(vaddr);
+	__nds32__mtsr_dsb(vaddr, NDS32_SR_TLB_VPN);
+	__nds32__tlbop_rwr(pte);
+	__nds32__isb();
+	return (void *)vaddr;
+}
+
+EXPORT_SYMBOL(kmap_atomic);
+
+void __kunmap_atomic(void *kvaddr)
+{
+	if (kvaddr >= (void *)FIXADDR_START) {
+		unsigned long vaddr = (unsigned long)kvaddr;
+		pte_t *ptep;
+		kmap_atomic_idx_pop();
+		__nds32__tlbop_inv(vaddr);
+		__nds32__isb();
+		ptep = pte_offset_kernel(pmd_off_k(vaddr), vaddr);
+		set_pte(ptep, 0);
+	}
+	pagefault_enable();
+	preempt_enable();
+}
+
+EXPORT_SYMBOL(__kunmap_atomic);
diff --git a/arch/nds32/mm/init.c b/arch/nds32/mm/init.c
new file mode 100644
index 0000000..9dee3ee
--- /dev/null
+++ b/arch/nds32/mm/init.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/swap.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/mman.h>
+#include <linux/nodemask.h>
+#include <linux/initrd.h>
+#include <linux/highmem.h>
+#include <linux/memblock.h>
+
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/tlb.h>
+#include <asm/page.h>
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+DEFINE_SPINLOCK(anon_alias_lock);
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+extern unsigned long phys_initrd_start;
+extern unsigned long phys_initrd_size;
+
+/*
+ * empty_zero_page is a special page that is used for
+ * zero-initialized data and COW.
+ */
+struct page *empty_zero_page;
+#ifdef CONFIG_EARLY_PRINTK
+#include <asm/fixmap.h>
+
+/*
+ * Using tlbop to create an early I/O mapping
+ */
+void __iomem *__init early_io_map(phys_addr_t pa)
+{
+	unsigned long va;
+	pa &= PAGE_MASK;
+	pa += pgprot_val(PAGE_DEVICE);
+	va = __fix_to_virt(FIX_EARLY_DEBUG);
+	/* insert and lock this page to tlb entry directly */
+
+	__nds32__mtsr_dsb(va, NDS32_SR_TLB_VPN);
+	__nds32__tlbop_rwlk(pa);
+	__nds32__isb();
+	return (void __iomem *)va;
+}
+
+int __init early_io_unmap(void)
+{
+	unsigned long va;
+	va = __fix_to_virt(FIX_EARLY_DEBUG);
+	__nds32__tlbop_unlk(va);
+	__nds32__tlbop_inv(va);
+	__nds32__isb();
+	return 0;
+}
+
+late_initcall(early_io_unmap);
+#endif
+
+static void __init zone_sizes_init(void)
+{
+	unsigned long zones_size[MAX_NR_ZONES];
+
+	/* Clear the zone sizes */
+	memset(zones_size, 0, sizeof(zones_size));
+
+	zones_size[ZONE_NORMAL] = max_low_pfn;
+#ifdef CONFIG_HIGHMEM
+	zones_size[ZONE_HIGHMEM] = max_pfn;
+#endif
+	free_area_init_nodes(zones_size);
+
+}
+
+/*
+ * Map all physical memory under high_memory into kernel's address space.
+ *
+ * This is explicitly coded for two-level page tables, so if you need
+ * something else then this needs to change.
+ */
+static void __init map_ram(void)
+{
+	unsigned long v, p, e;
+	pgd_t *pge;
+	pud_t *pue;
+	pmd_t *pme;
+	pte_t *pte;
+	/* These mark extents of read-only kernel pages...
+	 * ...from vmlinux.lds.S
+	 */
+
+	p = (u32) memblock_start_of_DRAM() & PAGE_MASK;
+	e = min((u32) memblock_end_of_DRAM(), (u32) __pa(high_memory));
+
+	v = (u32) __va(p);
+	pge = pgd_offset_k(v);
+
+	while (p < e) {
+		int j;
+		pue = pud_offset(pge, v);
+		pme = pmd_offset(pue, v);
+
+		if ((u32) pue != (u32) pge || (u32) pme != (u32) pge) {
+			panic("%s: Kernel hardcoded for "
+			      "two-level page tables", __func__);
+		}
+
+		/* Alloc one page for holding PTE's... */
+		pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+		set_pmd(pme, __pmd(__pa(pte) + _PAGE_KERNEL_TABLE));
+
+		/* Fill the newly allocated page with PTE'S */
+		for (j = 0; p < e && j < PTRS_PER_PTE;
+		     v += PAGE_SIZE, p += PAGE_SIZE, j++, pte++) {
+			/* Create mapping between p and v. */
+			/* TODO: more fine grant for page access permission */
+			set_pte(pte, __pte(p + pgprot_val(PAGE_KERNEL)));
+		}
+
+		pge++;
+	}
+}
+
+static void __init fixedrange_init(void)
+{
+	unsigned long vaddr;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	/*
+	 * Fixed mappings:
+	 */
+	vaddr = __fix_to_virt(__end_of_fixed_addresses - 1);
+	pgd = swapper_pg_dir + pgd_index(vaddr);
+	pud = pud_offset(pgd, vaddr);
+	pmd = pmd_offset(pud, vaddr);
+	pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+	set_pmd(pmd, __pmd(__pa(pte) + _PAGE_KERNEL_TABLE));
+
+#ifdef CONFIG_HIGHMEM
+	/*
+	 * Permanent kmaps:
+	 */
+	vaddr = PKMAP_BASE;
+
+	pgd = swapper_pg_dir + pgd_index(vaddr);
+	pud = pud_offset(pgd, vaddr);
+	pmd = pmd_offset(pud, vaddr);
+	pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+	set_pmd(pmd, __pmd(__pa(pte) + _PAGE_KERNEL_TABLE));
+	pkmap_page_table = pte;
+#endif /* CONFIG_HIGHMEM */
+}
+
+/*
+ * paging_init() sets up the page tables, initialises the zone memory
+ * maps, and sets up the zero page, bad page and bad page tables.
+ */
+void __init paging_init(void)
+{
+	void *zero_page;
+	int i;
+
+	pr_info("Setting up paging and PTEs.\n");
+	/* clear out the init_mm.pgd that will contain the kernel's mappings */
+	for (i = 0; i < PTRS_PER_PGD; i++)
+		swapper_pg_dir[i] = __pgd(1);
+
+	map_ram();
+
+	fixedrange_init();
+
+	/* allocate space for empty_zero_page */
+	zero_page = alloc_bootmem_low_pages(PAGE_SIZE);
+	memset(zero_page, 0, PAGE_SIZE);
+
+	zone_sizes_init();
+
+	empty_zero_page = virt_to_page(zero_page);
+	flush_dcache_page(empty_zero_page);
+}
+
+static inline int free_area(unsigned long addr, unsigned long end, char *s)
+{
+	unsigned int size = (end - addr) >> 10;
+	int pages = 0;
+
+	for (; addr < end; addr += PAGE_SIZE) {
+		struct page *page = virt_to_page(addr);
+		ClearPageReserved(page);
+		init_page_count(page);
+		free_page(addr);
+		totalram_pages++;
+		pages++;
+	}
+
+	if (size && s)
+		pr_info("free_area: Freeing %s memory: %dK\n", s, size);
+
+	return pages;
+}
+
+static inline void __init free_highmem(void)
+{
+#ifdef CONFIG_HIGHMEM
+	unsigned long pfn;
+	for (pfn = PFN_UP(__pa(high_memory)); pfn < max_pfn; pfn++) {
+		phys_addr_t paddr = (phys_addr_t) pfn << PAGE_SHIFT;
+		if (!memblock_is_reserved(paddr))
+			free_highmem_page(pfn_to_page(pfn));
+	}
+#endif
+}
+
+static void __init set_max_mapnr_init(void)
+{
+	max_mapnr = max_pfn;
+}
+
+/*
+ * mem_init() marks the free areas in the mem_map and tells us how much
+ * memory is free.  This is done after various parts of the system have
+ * claimed their memory after the kernel image.
+ */
+void __init mem_init(void)
+{
+	phys_addr_t memory_start = memblock_start_of_DRAM();
+	BUG_ON(!mem_map);
+	set_max_mapnr_init();
+
+	free_highmem();
+
+	/* this will put all low memory onto the freelists */
+	free_all_bootmem();
+
+	pr_info("virtual kernel memory layout:\n"
+		"    fixmap  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+#ifdef CONFIG_HIGHMEM
+		"    pkmap   : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+#endif
+		"    consist : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+		"    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+		"    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+		"      .init : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+		"      .data : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+		"      .text : 0x%08lx - 0x%08lx   (%4ld kB)\n",
+		FIXADDR_START, FIXADDR_TOP, (FIXADDR_TOP - FIXADDR_START) >> 10,
+#ifdef CONFIG_HIGHMEM
+		PKMAP_BASE, PKMAP_BASE + LAST_PKMAP * PAGE_SIZE,
+		(LAST_PKMAP * PAGE_SIZE) >> 10,
+#endif
+		CONSISTENT_BASE, CONSISTENT_END,
+		((CONSISTENT_END) - (CONSISTENT_BASE)) >> 20, VMALLOC_START,
+		(unsigned long)VMALLOC_END, (VMALLOC_END - VMALLOC_START) >> 20,
+		(unsigned long)__va(memory_start), (unsigned long)high_memory,
+		((unsigned long)high_memory -
+		 (unsigned long)__va(memory_start)) >> 20,
+		(unsigned long)&__init_begin, (unsigned long)&__init_end,
+		((unsigned long)&__init_end -
+		 (unsigned long)&__init_begin) >> 10, (unsigned long)&_etext,
+		(unsigned long)&_edata,
+		((unsigned long)&_edata - (unsigned long)&_etext) >> 10,
+		(unsigned long)&_text, (unsigned long)&_etext,
+		((unsigned long)&_etext - (unsigned long)&_text) >> 10);
+
+	/*
+	 * Check boundaries twice: Some fundamental inconsistencies can
+	 * be detected at build time already.
+	 */
+#ifdef CONFIG_HIGHMEM
+	BUILD_BUG_ON(PKMAP_BASE + LAST_PKMAP * PAGE_SIZE > FIXADDR_START);
+	BUILD_BUG_ON((CONSISTENT_END) > PKMAP_BASE);
+#endif
+	BUILD_BUG_ON(VMALLOC_END > CONSISTENT_BASE);
+	BUILD_BUG_ON(VMALLOC_START >= VMALLOC_END);
+
+#ifdef CONFIG_HIGHMEM
+	BUG_ON(PKMAP_BASE + LAST_PKMAP * PAGE_SIZE > FIXADDR_START);
+	BUG_ON(CONSISTENT_END > PKMAP_BASE);
+#endif
+	BUG_ON(VMALLOC_END > CONSISTENT_BASE);
+	BUG_ON(VMALLOC_START >= VMALLOC_END);
+	BUG_ON((unsigned long)high_memory > VMALLOC_START);
+
+	return;
+}
+
+void free_initmem(void)
+{
+	free_initmem_default(-1);
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+static int keep_initrd;
+
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+	if (!keep_initrd)
+		free_area(start, end, "initrd");
+}
+
+static int __init keepinitrd_setup(char *__unused)
+{
+	keep_initrd = 1;
+	return 1;
+}
+
+__setup("keepinitrd", keepinitrd_setup);
+#endif
diff --git a/arch/nds32/mm/mm-nds32.c b/arch/nds32/mm/mm-nds32.c
new file mode 100644
index 0000000..2801496
--- /dev/null
+++ b/arch/nds32/mm/mm-nds32.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init_task.h>
+#include <asm/pgalloc.h>
+
+#define FIRST_KERNEL_PGD_NR	(USER_PTRS_PER_PGD)
+
+/*
+ * need to get a page for level 1
+ */
+
+pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	pgd_t *new_pgd, *init_pgd;
+	int i;
+
+	new_pgd = (pgd_t *) __get_free_pages(GFP_KERNEL, 0);
+	if (!new_pgd)
+		return NULL;
+	for (i = 0; i < PTRS_PER_PGD; i++) {
+		(*new_pgd) = 1;
+		new_pgd++;
+	}
+	new_pgd -= PTRS_PER_PGD;
+
+	init_pgd = pgd_offset_k(0);
+
+	memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
+	       (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
+
+	cpu_dcache_wb_range((unsigned long)new_pgd,
+			    (unsigned long)new_pgd +
+			    PTRS_PER_PGD * sizeof(pgd_t));
+	inc_zone_page_state(virt_to_page((unsigned long *)new_pgd),
+			    NR_PAGETABLE);
+
+	return new_pgd;
+}
+
+void pgd_free(struct mm_struct *mm, pgd_t * pgd)
+{
+	pmd_t *pmd;
+	struct page *pte;
+
+	if (!pgd)
+		return;
+
+	pmd = (pmd_t *) pgd;
+	if (pmd_none(*pmd))
+		goto free;
+	if (pmd_bad(*pmd)) {
+		pmd_ERROR(*pmd);
+		pmd_clear(pmd);
+		goto free;
+	}
+
+	pte = pmd_page(*pmd);
+	pmd_clear(pmd);
+	dec_zone_page_state(virt_to_page((unsigned long *)pgd), NR_PAGETABLE);
+	pte_free(mm, pte);
+	atomic_long_dec(&mm->nr_ptes);
+	pmd_free(mm, pmd);
+free:
+	free_pages((unsigned long)pgd, 0);
+}
+
+/*
+ * In order to soft-boot, we need to insert a 1:1 mapping in place of
+ * the user-mode pages.  This will then ensure that we have predictable
+ * results when turning the mmu off
+ */
+void setup_mm_for_reboot(char mode)
+{
+	unsigned long pmdval;
+	pgd_t *pgd;
+	pmd_t *pmd;
+	int i;
+
+	if (current->mm && current->mm->pgd)
+		pgd = current->mm->pgd;
+	else
+		pgd = init_mm.pgd;
+
+	for (i = 0; i < USER_PTRS_PER_PGD; i++) {
+		pmdval = (i << PGDIR_SHIFT);
+		pmd = pmd_offset(pgd + i, i << PGDIR_SHIFT);
+		set_pmd(pmd, __pmd(pmdval));
+	}
+}
-- 
1.7.9.5

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

* [PATCH 07/31] nds32: MMU fault handling and page table management
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (5 preceding siblings ...)
  2017-11-08  5:54 ` [PATCH 06/31] nds32: MMU initialization Greentime Hu
@ 2017-11-08  5:54 ` Greentime Hu
  2017-11-08  5:54 ` [PATCH 08/31] nds32: Cache and TLB routines Greentime Hu
                   ` (25 subsequent siblings)
  32 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:54 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/lib/copy_page.S |   50 ++++++
 arch/nds32/mm/extable.c    |   29 +++
 arch/nds32/mm/fault.c      |  420 ++++++++++++++++++++++++++++++++++++++++++++
 arch/nds32/mm/mmap.c       |   88 ++++++++++
 4 files changed, 587 insertions(+)
 create mode 100644 arch/nds32/lib/copy_page.S
 create mode 100644 arch/nds32/mm/extable.c
 create mode 100644 arch/nds32/mm/fault.c
 create mode 100644 arch/nds32/mm/mmap.c

diff --git a/arch/nds32/lib/copy_page.S b/arch/nds32/lib/copy_page.S
new file mode 100644
index 0000000..a55a5cc
--- /dev/null
+++ b/arch/nds32/lib/copy_page.S
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <asm/page.h>
+
+	.text
+ENTRY(copy_page)
+	pushm	$r2, $r10
+	movi	$r2, PAGE_SIZE >> 5
+.Lcopy_loop:
+	lmw.bim	$r3, [$r1], $r10
+	smw.bim	$r3, [$r0], $r10
+	subi45	$r2, #1
+	bnez38	$r2, .Lcopy_loop
+	popm	$r2, $r10
+	ret
+ENDPROC(copy_page)
+
+ENTRY(clear_page)
+	pushm	$r1, $r9
+	movi	$r1, PAGE_SIZE >> 5
+	movi55	$r2, #0
+	movi55	$r3, #0
+	movi55	$r4, #0
+	movi55	$r5, #0
+	movi55	$r6, #0
+	movi55	$r7, #0
+	movi55	$r8, #0
+	movi55	$r9, #0
+.Lclear_loop:
+	smw.bim	$r2, [$r0], $r9
+	subi45	$r1, #1
+	bnez38	$r1, .Lclear_loop
+	popm	$r1, $r9
+        ret
+ENDPROC(clear_page)
diff --git a/arch/nds32/mm/extable.c b/arch/nds32/mm/extable.c
new file mode 100644
index 0000000..bce62d7
--- /dev/null
+++ b/arch/nds32/mm/extable.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/extable.h>
+#include <asm/uaccess.h>
+
+int fixup_exception(struct pt_regs *regs)
+{
+	const struct exception_table_entry *fixup;
+
+	fixup = search_exception_tables(instruction_pointer(regs));
+	if (fixup)
+		regs->ipc = fixup->fixup;
+
+	return fixup != NULL;
+}
diff --git a/arch/nds32/mm/fault.c b/arch/nds32/mm/fault.c
new file mode 100644
index 0000000..e15b2c1
--- /dev/null
+++ b/arch/nds32/mm/fault.c
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/extable.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/ptrace.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/hardirq.h>
+
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+#include <asm/uaccess.h>
+
+extern void die(const char *str, struct pt_regs *regs, long err);
+
+/*
+ * This is useful to dump out the page tables associated with
+ * 'addr' in mm 'mm'.
+ */
+void show_pte(struct mm_struct *mm, unsigned long addr)
+{
+	pgd_t *pgd;
+	if (!mm)
+		mm = &init_mm;
+
+	pr_alert("pgd = %p\n", mm->pgd);
+	pgd = pgd_offset(mm, addr);
+	pr_alert("[%08lx] *pgd=%08lx", addr, pgd_val(*pgd));
+
+	do {
+		pmd_t *pmd;
+
+		if (pgd_none(*pgd))
+			break;
+
+		if (pgd_bad(*pgd)) {
+			pr_alert("(bad)");
+			break;
+		}
+
+		pmd = pmd_offset(pgd, addr);
+#if PTRS_PER_PMD != 1
+		pr_alert(", *pmd=%08lx", pmd_val(*pmd));
+#endif
+
+		if (pmd_none(*pmd))
+			break;
+
+		if (pmd_bad(*pmd)) {
+			pr_alert("(bad)");
+			break;
+		}
+#ifndef CONFIG_HIGHMEM
+		{
+			pte_t *pte;
+			/* We must not map this if we have highmem enabled */
+			pte = pte_offset_map(pmd, addr);
+			pr_alert(", *pte=%08lx", pte_val(*pte));
+			pte_unmap(pte);
+		}
+#endif
+	} while (0);
+
+	pr_alert("\n");
+}
+
+void do_page_fault(unsigned long entry, unsigned long addr,
+		   unsigned int error_code, struct pt_regs *regs)
+{
+	struct task_struct *tsk;
+	struct mm_struct *mm;
+	struct vm_area_struct *vma;
+	siginfo_t info;
+	int fault;
+	unsigned int mask = VM_READ | VM_WRITE | VM_EXEC;
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
+
+	error_code = error_code & (ITYPE_mskINST | ITYPE_mskETYPE);
+	tsk = current;
+	mm = tsk->mm;
+	info.si_code = SEGV_MAPERR;
+	/*
+	 * 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 (addr >= TASK_SIZE) {
+		if (user_mode(regs))
+			goto bad_area_nosemaphore;
+
+		if (addr >= TASK_SIZE && addr < VMALLOC_END
+		    && (entry == ENTRY_PTE_NOT_PRESENT))
+			goto vmalloc_fault;
+		else
+			goto no_context;
+	}
+
+	/* Send a signal to the task for handling the unalignment access. */
+	if (entry == ENTRY_GENERAL_EXCPETION
+	    && error_code == ETYPE_ALIGNMENT_CHECK) {
+		if (user_mode(regs))
+			goto bad_area_nosemaphore;
+		else
+			goto no_context;
+	}
+
+	/*
+	 * If we're in an interrupt or have no user
+	 * context, we must not take the fault..
+	 */
+	if (unlikely(in_atomic() || !mm))
+		goto no_context;
+
+	/*
+	 * As per x86, we may deadlock here. However, since the kernel only
+	 * validly references user space from well defined areas of the code,
+	 * we can bug out early if this is from code which shouldn't.
+	 */
+	if (unlikely(!down_read_trylock(&mm->mmap_sem))) {
+		if (!user_mode(regs) &&
+		    !search_exception_tables(instruction_pointer(regs)))
+			goto no_context;
+retry:
+		down_read(&mm->mmap_sem);
+	} else {
+		/*
+		 * The above down_read_trylock() might have succeeded in which
+		 * case, we'll have missed the might_sleep() from down_read().
+		 */
+		might_sleep();
+#ifdef CONFIG_DEBUG_VM
+		if (!user_mode(regs) &&
+		    !search_exception_tables(instruction_pointer(regs)))
+			goto no_context;
+#endif
+	}
+
+	vma = find_vma(mm, addr);
+
+	if (unlikely(!vma))
+		goto bad_area;
+
+	if (vma->vm_start <= addr)
+		goto good_area;
+
+	if (unlikely(!(vma->vm_flags & VM_GROWSDOWN)))
+		goto bad_area;
+
+	if (unlikely(expand_stack(vma, addr)))
+		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;
+
+	/* first do some preliminary protection checks */
+	if (entry == ENTRY_PTE_NOT_PRESENT) {
+		if (error_code & ITYPE_mskINST)
+			mask = VM_EXEC;
+		else {
+			mask = VM_READ | VM_WRITE;
+			if (vma->vm_flags & VM_WRITE)
+				flags |= FAULT_FLAG_WRITE;
+		}
+	} else if (entry == ENTRY_TLB_MISC) {
+		switch (error_code & ITYPE_mskETYPE) {
+		case RD_PROT:
+			mask = VM_READ;
+			break;
+		case WRT_PROT:
+			mask = VM_WRITE;
+			flags |= FAULT_FLAG_WRITE;
+			break;
+		case NOEXEC:
+			mask = VM_EXEC;
+			break;
+		case PAGE_MODIFY:
+			mask = VM_WRITE;
+			flags |= FAULT_FLAG_WRITE;
+			break;
+		case ACC_BIT:
+			BUG();
+		default:
+			break;
+		}
+
+	}
+	if (!(vma->vm_flags & mask))
+		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, addr, flags);
+
+	/*
+	 * If we need to retry but a fatal signal is pending, handle the
+	 * signal first. We do not need to release the mmap_sem because it
+	 * would already be released in __lock_page_or_retry in mm/filemap.c.
+	 */
+	if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+		return;
+
+	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
+			goto bad_area;
+	}
+
+	/*
+	 * Major/minor page fault accounting is only done on the initial
+	 * attempt. If we go through a retry, it is extremely likely that the
+	 * page will be found in page cache at that point.
+	 */
+	if (flags & FAULT_FLAG_ALLOW_RETRY) {
+		if (fault & VM_FAULT_MAJOR)
+			tsk->maj_flt++;
+		else
+			tsk->min_flt++;
+		if (fault & VM_FAULT_RETRY) {
+			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			flags |= FAULT_FLAG_TRIED;
+
+			/* No need to up_read(&mm->mmap_sem) as we would
+			 * have already released it in __lock_page_or_retry
+			 * in mm/filemap.c.
+			 */
+			goto retry;
+		}
+	}
+
+	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 = addr;
+		tsk->thread.error_code = error_code;
+		tsk->thread.trap_no = entry;
+		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		/* info.si_code has been set above */
+		info.si_addr = (void *)addr;
+		force_sig_info(SIGSEGV, &info, tsk);
+		return;
+	}
+
+no_context:
+
+	/* Are we prepared to handle this kernel fault?
+	 *
+	 * (The kernel has valid exception-points in the source
+	 *  when it acesses user-memory. When it fails in one
+	 *  of those points, we find it in a table and do a jump
+	 *  to some fixup code that loads an appropriate error
+	 *  code)
+	 */
+
+	{
+		const struct exception_table_entry *entry;
+
+		if ((entry =
+		     search_exception_tables(instruction_pointer(regs))) !=
+		    NULL) {
+			/* Adjust the instruction pointer in the stackframe */
+			instruction_pointer(regs) = entry->fixup;
+			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 %s at virtual address %08lx\n",
+		 (addr < PAGE_SIZE) ? "NULL pointer dereference" :
+		 "paging request", addr);
+
+	show_pte(mm, addr);
+	die("Oops", regs, error_code);
+	bust_spinlocks(0);
+	do_exit(SIGKILL);
+
+	return;
+
+	/*
+	 * We ran out of memory, or some other thing happened to us that made
+	 * us unable to handle the page fault gracefully.
+	 */
+
+out_of_memory:
+	up_read(&mm->mmap_sem);
+	if (!user_mode(regs))
+		goto no_context;
+	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;
+
+	/*
+	 * Send a sigbus
+	 */
+	tsk->thread.address = addr;
+	tsk->thread.error_code = error_code;
+	tsk->thread.trap_no = entry;
+	info.si_signo = SIGBUS;
+	info.si_errno = 0;
+	info.si_code = BUS_ADRERR;
+	info.si_addr = (void *)addr;
+	force_sig_info(SIGBUS, &info, tsk);
+
+	return;
+
+vmalloc_fault:
+	{
+		/*
+		 * Synchronize this task's top level page-table
+		 * with the 'reference' page table.
+		 *
+		 * Use current_pgd instead of tsk->active_mm->pgd
+		 * since the latter might be unavailable if this
+		 * code is executed in a misfortunately run irq
+		 * (like inside schedule() between switch_mm and
+		 *  switch_to...).
+		 */
+
+		unsigned int index = pgd_index(addr);
+		pgd_t *pgd, *pgd_k;
+		pud_t *pud, *pud_k;
+		pmd_t *pmd, *pmd_k;
+		pte_t *pte_k;
+
+		pgd = (pgd_t *) __va(__nds32__mfsr(NDS32_SR_L1_PPTB)) + index;
+		pgd_k = init_mm.pgd + index;
+
+		if (!pgd_present(*pgd_k))
+			goto no_context;
+
+		pud = pud_offset(pgd, addr);
+		pud_k = pud_offset(pgd_k, addr);
+		if (!pud_present(*pud_k))
+			goto no_context;
+
+		pmd = pmd_offset(pud, addr);
+		pmd_k = pmd_offset(pud_k, addr);
+		if (!pmd_present(*pmd_k))
+			goto no_context;
+
+		if (!pmd_present(*pmd))
+			set_pmd(pmd, *pmd_k);
+		else
+			BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
+
+		/*
+		 * Since the vmalloc area is global, we don't
+		 * need to copy individual PTE's, it is enough to
+		 * copy the pgd pointer into the pte page of the
+		 * root task. If that is there, we'll find our pte if
+		 * it exists.
+		 */
+
+		/* Make sure the actual PTE exists as well to
+		 * catch kernel vmalloc-area accesses to non-mapped
+		 * addres. If we don't do this, this will just
+		 * silently loop forever.
+		 */
+
+		pte_k = pte_offset_kernel(pmd_k, addr);
+		if (!pte_present(*pte_k))
+			goto no_context;
+
+		return;
+	}
+}
diff --git a/arch/nds32/mm/mmap.c b/arch/nds32/mm/mmap.c
new file mode 100644
index 0000000..91394f5
--- /dev/null
+++ b/arch/nds32/mm/mmap.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/sched.h>
+#include <linux/mman.h>
+#include <linux/shm.h>
+
+#define COLOUR_ALIGN(addr,pgoff)		\
+	((((addr)+REALSHMLBA-1)&~(REALSHMLBA-1)) +	\
+	 (((pgoff)<<PAGE_SHIFT) & (REALSHMLBA-1)))
+
+/*
+ * We need to ensure that shared mappings are correctly aligned to
+ * avoid aliasing issues with VIPT caches.  We need to ensure that
+ * a specific page of an object is always mapped at a multiple of
+ * SHMLBA bytes.
+ *
+ * We unconditionally provide this function for all cases, however
+ * in the VIVT case, we optimise out the alignment rules.
+ */
+unsigned long
+arch_get_unmapped_area(struct file *filp, unsigned long addr,
+		       unsigned long len, unsigned long pgoff,
+		       unsigned long flags)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	int do_align = 0;
+#ifdef CONFIG_CPU_CACHE_NONALIASING
+	int aliasing = 0;
+#else
+	int aliasing = 1;
+#endif
+	struct vm_unmapped_area_info info;
+
+	/*
+	 * We only need to do colour alignment if either the I or D
+	 * caches alias.
+	 */
+	if (aliasing)
+		do_align = filp || (flags & MAP_SHARED);
+
+	/*
+	 * We enforce the MAP_FIXED case.
+	 */
+	if (flags & MAP_FIXED) {
+		if (aliasing && flags & MAP_SHARED &&
+		    (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))
+			return -EINVAL;
+		return addr;
+	}
+
+	if (len > TASK_SIZE)
+		return -ENOMEM;
+
+	if (addr) {
+		if (do_align)
+			addr = COLOUR_ALIGN(addr, pgoff);
+		else
+			addr = PAGE_ALIGN(addr);
+
+		vma = find_vma(mm, addr);
+		if (TASK_SIZE - len >= addr &&
+		    (!vma || addr + len <= vma->vm_start))
+			return addr;
+	}
+
+	info.flags = 0;
+	info.length = len;
+	info.low_limit = mm->mmap_base;
+	info.high_limit = TASK_SIZE;
+	info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
+	info.align_offset = pgoff << PAGE_SHIFT;
+	return vm_unmapped_area(&info);
+}
-- 
1.7.9.5

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

* [PATCH 08/31] nds32: Cache and TLB routines
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (6 preceding siblings ...)
  2017-11-08  5:54 ` [PATCH 07/31] nds32: MMU fault handling and page table management Greentime Hu
@ 2017-11-08  5:54 ` Greentime Hu
  2017-11-08  8:45   ` Arnd Bergmann
  2017-11-08  5:54 ` [PATCH 09/31] nds32: Process management Greentime Hu
                   ` (24 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:54 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/asm/cache.h         |   25 ++
 arch/nds32/include/asm/cache_info.h    |   26 ++
 arch/nds32/include/asm/cacheflush.h    |   57 +++
 arch/nds32/include/asm/mmu_context.h   |   81 +++++
 arch/nds32/include/asm/proc-fns.h      |   94 +++++
 arch/nds32/include/asm/tlb.h           |   41 +++
 arch/nds32/include/asm/tlbflush.h      |   60 ++++
 arch/nds32/include/uapi/asm/cachectl.h |   19 +
 arch/nds32/kernel/cacheinfo.c          |   62 ++++
 arch/nds32/mm/cacheflush.c             |  331 +++++++++++++++++
 arch/nds32/mm/proc-n13.c               |  608 ++++++++++++++++++++++++++++++++
 arch/nds32/mm/tlb.c                    |   63 ++++
 12 files changed, 1467 insertions(+)
 create mode 100644 arch/nds32/include/asm/cache.h
 create mode 100644 arch/nds32/include/asm/cache_info.h
 create mode 100644 arch/nds32/include/asm/cacheflush.h
 create mode 100644 arch/nds32/include/asm/mmu_context.h
 create mode 100644 arch/nds32/include/asm/proc-fns.h
 create mode 100644 arch/nds32/include/asm/tlb.h
 create mode 100644 arch/nds32/include/asm/tlbflush.h
 create mode 100644 arch/nds32/include/uapi/asm/cachectl.h
 create mode 100644 arch/nds32/kernel/cacheinfo.c
 create mode 100644 arch/nds32/mm/cacheflush.c
 create mode 100644 arch/nds32/mm/proc-n13.c
 create mode 100644 arch/nds32/mm/tlb.c

diff --git a/arch/nds32/include/asm/cache.h b/arch/nds32/include/asm/cache.h
new file mode 100644
index 0000000..36ec549
--- /dev/null
+++ b/arch/nds32/include/asm/cache.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NDS32_CACHE_H__
+#define __NDS32_CACHE_H__
+
+#define L1_CACHE_BYTES	32
+#define L1_CACHE_SHIFT	5
+
+#define ARCH_DMA_MINALIGN   L1_CACHE_BYTES
+
+#endif /* __NDS32_CACHE_H__ */
diff --git a/arch/nds32/include/asm/cache_info.h b/arch/nds32/include/asm/cache_info.h
new file mode 100644
index 0000000..a59d73d
--- /dev/null
+++ b/arch/nds32/include/asm/cache_info.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+struct cache_info {
+	unsigned char ways;
+	unsigned char line_size;
+	unsigned short sets;
+	unsigned short size;
+#if !defined(CONFIG_CPU_CACHE_NONALIASING)
+	unsigned short aliasing_num;
+	unsigned int aliasing_mask;
+#endif
+};
diff --git a/arch/nds32/include/asm/cacheflush.h b/arch/nds32/include/asm/cacheflush.h
new file mode 100644
index 0000000..0c7c9db
--- /dev/null
+++ b/arch/nds32/include/asm/cacheflush.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NDS32_CACHEFLUSH_H__
+#define __NDS32_CACHEFLUSH_H__
+
+#include <linux/mm.h>
+
+#define PG_dcache_dirty PG_arch_1
+
+#ifndef CONFIG_CPU_CACHE_NONALIASING
+void flush_cache_mm(struct mm_struct *mm);
+void flush_cache_dup_mm(struct mm_struct *mm);
+void flush_cache_range(struct vm_area_struct *vma,
+		       unsigned long start, unsigned long end);
+void flush_cache_page(struct vm_area_struct *vma,
+		      unsigned long addr, unsigned long pfn);
+void flush_cache_kmaps(void);
+void flush_cache_vmap(unsigned long start, unsigned long end);
+void flush_cache_vunmap(unsigned long start, unsigned long end);
+
+#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
+void flush_dcache_page(struct page *page);
+void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
+		       unsigned long vaddr, void *dst, void *src, int len);
+void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
+			 unsigned long vaddr, void *dst, void *src, int len);
+
+#define ARCH_HAS_FLUSH_ANON_PAGE
+void flush_anon_page(struct vm_area_struct *vma,
+		     struct page *page, unsigned long vaddr);
+
+#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
+void flush_kernel_dcache_page(struct page *page);
+void flush_icache_range(unsigned long start, unsigned long end);
+void flush_icache_page(struct vm_area_struct *vma, struct page *page);
+#define flush_dcache_mmap_lock(mapping)   spin_lock_irq(&(mapping)->tree_lock)
+#define flush_dcache_mmap_unlock(mapping) spin_unlock_irq(&(mapping)->tree_lock)
+
+#else
+#include <asm-generic/cacheflush.h>
+#endif
+
+#endif /* __NDS32_CACHEFLUSH_H__ */
diff --git a/arch/nds32/include/asm/mmu_context.h b/arch/nds32/include/asm/mmu_context.h
new file mode 100644
index 0000000..4a59b5d
--- /dev/null
+++ b/arch/nds32/include/asm/mmu_context.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_NDS32_MMU_CONTEXT_H
+#define __ASM_NDS32_MMU_CONTEXT_H
+
+#include <linux/spinlock.h>
+#include <asm/tlbflush.h>
+#include <asm/proc-fns.h>
+#include <asm-generic/mm_hooks.h>
+
+static inline int
+init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+	mm->context.id = 0;
+	return 0;
+}
+
+#define destroy_context(mm)	do { } while(0)
+
+#define CID_BITS	9
+extern spinlock_t cid_lock;
+extern unsigned int cpu_last_cid;
+
+static inline void __new_context(struct mm_struct *mm)
+{
+	unsigned int cid;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cid_lock, flags);
+	cid = cpu_last_cid;
+	cpu_last_cid += 1 << TLB_MISC_offCID;
+	if (cpu_last_cid == 0)
+		cpu_last_cid = 1 << TLB_MISC_offCID << CID_BITS;
+
+	if ((cid & TLB_MISC_mskCID) == 0)
+		flush_tlb_all();
+	spin_unlock_irqrestore(&cid_lock, flags);
+
+	mm->context.id = cid;
+}
+
+static inline void check_context(struct mm_struct *mm)
+{
+	if (unlikely
+	    ((mm->context.id ^ cpu_last_cid) >> TLB_MISC_offCID >> CID_BITS))
+		__new_context(mm);
+}
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+			     struct task_struct *tsk)
+{
+	unsigned int cpu = smp_processor_id();
+
+	if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next) {
+		check_context(next);
+		cpu_switch_mm(next);
+	}
+}
+
+#define deactivate_mm(tsk,mm)	do { } while (0)
+#define activate_mm(prev,next)	switch_mm(prev, next, NULL)
+
+#endif
diff --git a/arch/nds32/include/asm/proc-fns.h b/arch/nds32/include/asm/proc-fns.h
new file mode 100644
index 0000000..4321014
--- /dev/null
+++ b/arch/nds32/include/asm/proc-fns.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NDS32_PROCFNS_H__
+#define __NDS32_PROCFNS_H__
+
+#define CPU_NAME n13
+
+#ifdef __KERNEL__
+
+#ifdef __STDC__
+#define ____cpu_fn(name,fn)       name##fn
+#else
+#define ____cpu_fn(name,fn)       name/**/fn
+#endif
+#define __cpu_fn(name,fn)         ____cpu_fn(name,fn)
+
+#define cpu_proc_init			__cpu_fn( CPU_NAME, _proc_init)
+#define cpu_proc_fin			__cpu_fn( CPU_NAME, _proc_fin)
+#define cpu_do_idle			__cpu_fn( CPU_NAME, _do_idle)
+#define cpu_reset			__cpu_fn( CPU_NAME, _reset)
+#define cpu_switch_mm			__cpu_fn( CPU_NAME, _switch_mm)
+
+#define cpu_dcache_inval_all		__cpu_fn( CPU_NAME, _dcache_inval_all)
+#define cpu_dcache_wbinval_all		__cpu_fn( CPU_NAME, _dcache_wbinval_all)
+#define cpu_dcache_inval_page		__cpu_fn( CPU_NAME, _dcache_inval_page)
+#define cpu_dcache_wb_page		__cpu_fn( CPU_NAME, _dcache_wb_page)
+#define cpu_dcache_wbinval_page		__cpu_fn( CPU_NAME, _dcache_wbinval_page)
+#define cpu_dcache_inval_range		__cpu_fn( CPU_NAME, _dcache_inval_range)
+#define cpu_dcache_wb_range		__cpu_fn( CPU_NAME, _dcache_wb_range)
+#define cpu_dcache_wbinval_range	__cpu_fn( CPU_NAME, _dcache_wbinval_range)
+
+#define cpu_icache_inval_all		__cpu_fn( CPU_NAME, _icache_inval_all)
+#define cpu_icache_inval_page		__cpu_fn( CPU_NAME, _icache_inval_page)
+#define cpu_icache_inval_range		__cpu_fn( CPU_NAME, _icache_inval_range)
+
+#define cpu_cache_wbinval_page		__cpu_fn( CPU_NAME, _cache_wbinval_page)
+#define cpu_cache_wbinval_range		__cpu_fn( CPU_NAME, _cache_wbinval_range)
+#define cpu_cache_wbinval_range_check	__cpu_fn( CPU_NAME, _cache_wbinval_range_check)
+
+#define cpu_dma_wb_range		__cpu_fn( CPU_NAME, _dma_wb_range)
+#define cpu_dma_inval_range		__cpu_fn( CPU_NAME, _dma_inval_range)
+#define cpu_dma_wbinval_range		__cpu_fn( CPU_NAME, _dma_wbinval_range)
+
+#include <asm/page.h>
+
+struct mm_struct;
+struct vm_area_struct;
+extern void cpu_proc_init(void);
+extern void cpu_proc_fin(void);
+extern void cpu_do_idle(void);
+extern void cpu_reset(unsigned long reset);
+extern void cpu_switch_mm(struct mm_struct *mm);
+
+extern void cpu_dcache_inval_all(void);
+extern void cpu_dcache_wbinval_all(void);
+extern void cpu_dcache_inval_page(unsigned long page);
+extern void cpu_dcache_wb_page(unsigned long page);
+extern void cpu_dcache_wbinval_page(unsigned long page);
+extern void cpu_dcache_inval_range(unsigned long start, unsigned long end);
+extern void cpu_dcache_wb_range(unsigned long start, unsigned long end);
+extern void cpu_dcache_wbinval_range(unsigned long start, unsigned long end);
+
+extern void cpu_icache_inval_all(void);
+extern void cpu_icache_inval_page(unsigned long page);
+extern void cpu_icache_inval_range(unsigned long start, unsigned long end);
+
+extern void cpu_cache_wbinval_page(unsigned long page, int flushi);
+extern void cpu_cache_wbinval_range(unsigned long start,
+				    unsigned long end, int flushi);
+extern void cpu_cache_wbinval_range_check(struct vm_area_struct *vma,
+					  unsigned long start,
+					  unsigned long end, bool flushi,
+					  bool wbd);
+
+extern void cpu_dma_wb_range(unsigned long start, unsigned long end);
+extern void cpu_dma_inval_range(unsigned long start, unsigned long end);
+extern void cpu_dma_wbinval_range(unsigned long start, unsigned long end);
+
+#endif /* __KERNEL__ */
+#endif /* __NDS32_PROCFNS_H__ */
diff --git a/arch/nds32/include/asm/tlb.h b/arch/nds32/include/asm/tlb.h
new file mode 100644
index 0000000..c599827
--- /dev/null
+++ b/arch/nds32/include/asm/tlb.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASMNDS32_TLB_H
+#define __ASMNDS32_TLB_H
+
+#define tlb_start_vma(tlb,vma)						\
+	do {								\
+		if (!tlb->fullmm)					\
+			flush_cache_range(vma, vma->vm_start, vma->vm_end); \
+	} while (0)
+
+#define tlb_end_vma(tlb,vma)				\
+	do { 						\
+		if(!tlb->fullmm)			\
+			flush_tlb_range(vma, vma->vm_start, vma->vm_end); \
+	} while (0)
+
+#define __tlb_remove_tlb_entry(tlb, pte, addr) do { } while (0)
+
+#define tlb_flush(tlb)	flush_tlb_mm((tlb)->mm)
+
+#include <asm-generic/tlb.h>
+
+#define __pte_free_tlb(tlb, pte, addr)	pte_free((tlb)->mm, pte)
+#define __pmd_free_tlb(tlb, pmd, addr)	pmd_free((tln)->mm, pmd)
+
+#endif
diff --git a/arch/nds32/include/asm/tlbflush.h b/arch/nds32/include/asm/tlbflush.h
new file mode 100644
index 0000000..680aeb3
--- /dev/null
+++ b/arch/nds32/include/asm/tlbflush.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ASMNDS32_TLBFLUSH_H
+#define _ASMNDS32_TLBFLUSH_H
+
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <nds32_intrinsic.h>
+
+static inline void local_flush_tlb_all(void)
+{
+	__nds32__tlbop_flua();
+	__nds32__isb();
+}
+
+static inline void local_flush_tlb_mm(struct mm_struct *mm)
+{
+	__nds32__tlbop_flua();
+	__nds32__isb();
+}
+
+static inline void local_flush_tlb_kernel_range(unsigned long start,
+						unsigned long end)
+{
+	while (start < end) {
+		__nds32__tlbop_inv(start);
+		__nds32__isb();
+		start += PAGE_SIZE;
+	}
+}
+
+void local_flush_tlb_range(struct vm_area_struct *vma,
+			   unsigned long start, unsigned long end);
+void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
+
+#define flush_tlb_all		local_flush_tlb_all
+#define flush_tlb_mm		local_flush_tlb_mm
+#define flush_tlb_range		local_flush_tlb_range
+#define flush_tlb_page		local_flush_tlb_page
+#define flush_tlb_kernel_range	local_flush_tlb_kernel_range
+
+void update_mmu_cache(struct vm_area_struct *vma,
+		      unsigned long address, pte_t * pte);
+void tlb_migrate_finish(struct mm_struct *mm);
+
+#endif
diff --git a/arch/nds32/include/uapi/asm/cachectl.h b/arch/nds32/include/uapi/asm/cachectl.h
new file mode 100644
index 0000000..a56a37d
--- /dev/null
+++ b/arch/nds32/include/uapi/asm/cachectl.h
@@ -0,0 +1,19 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ */
+#ifndef	_ASM_CACHECTL
+#define	_ASM_CACHECTL
+
+/*
+ * Options for cacheflush system call
+ */
+#define	ICACHE	0		/* flush instruction cache        */
+#define	DCACHE	1		/* writeback and flush data cache */
+#define	BCACHE	2		/* flush instruction cache + writeback and flush data cache */
+
+#endif /* _ASM_CACHECTL */
diff --git a/arch/nds32/kernel/cacheinfo.c b/arch/nds32/kernel/cacheinfo.c
new file mode 100644
index 0000000..edc0fda
--- /dev/null
+++ b/arch/nds32/kernel/cacheinfo.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/bitops.h>
+#include <linux/cacheinfo.h>
+#include <linux/cpu.h>
+
+static void ci_leaf_init(struct cacheinfo *this_leaf,
+			 enum cache_type type, unsigned int level)
+{
+	char cache_type = (type & CACHE_TYPE_INST ? ICACHE : DCACHE);
+
+	this_leaf->level = level;
+	this_leaf->type = type;
+	this_leaf->coherency_line_size = CACHE_LINE_SIZE(cache_type);
+	this_leaf->number_of_sets = CACHE_SET(cache_type);;
+	this_leaf->ways_of_associativity = CACHE_WAY(cache_type);
+	this_leaf->size = this_leaf->number_of_sets *
+	    this_leaf->coherency_line_size * this_leaf->ways_of_associativity;
+#if defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
+	this_leaf->attributes = CACHE_WRITE_THROUGH;
+#else
+	this_leaf->attributes = CACHE_WRITE_BACK;
+#endif
+}
+
+int init_cache_level(unsigned int cpu)
+{
+	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
+
+	/* Only 1 level and I/D cache seperate. */
+	this_cpu_ci->num_levels = 1;
+	this_cpu_ci->num_leaves = 2;
+	return 0;
+}
+
+int populate_cache_leaves(unsigned int cpu)
+{
+	unsigned int level, idx;
+	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
+	struct cacheinfo *this_leaf = this_cpu_ci->info_list;
+
+	for (idx = 0, level = 1; level <= this_cpu_ci->num_levels &&
+	     idx < this_cpu_ci->num_leaves; idx++, level++) {
+		ci_leaf_init(this_leaf++, CACHE_TYPE_DATA, level);
+		ci_leaf_init(this_leaf++, CACHE_TYPE_INST, level);
+	}
+	return 0;
+}
diff --git a/arch/nds32/mm/cacheflush.c b/arch/nds32/mm/cacheflush.c
new file mode 100644
index 0000000..f5917fb
--- /dev/null
+++ b/arch/nds32/mm/cacheflush.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/module.h>
+#include <asm/cacheflush.h>
+#include <asm/proc-fns.h>
+#include <asm/shmparam.h>
+#include <asm/cache_info.h>
+
+extern struct cache_info L1_cache_info[2];
+
+#ifdef CONFIG_CPU_CACHE_NONALIASING
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
+		      pte_t * pte)
+{
+	struct page *page;
+	unsigned long pfn = pte_pfn(*pte);
+
+	if (!pfn_valid(pfn))
+		return;
+
+	if (vma->vm_mm == current->active_mm) {
+
+		__nds32__mtsr_dsb(addr, NDS32_SR_TLB_VPN);
+		__nds32__tlbop_rwr(*pte);
+		__nds32__isb();
+	}
+	page = pfn_to_page(pfn);
+
+	if ((test_and_clear_bit(PG_dcache_dirty, &page->flags)) ||
+	    (vma->vm_flags & VM_EXEC)) {
+
+		if (!PageHighMem(page)) {
+			cpu_cache_wbinval_page((unsigned long)
+					       page_address(page),
+					       vma->vm_flags & VM_EXEC);
+		} else {
+			unsigned long kaddr = (unsigned long)kmap_atomic(page);
+			cpu_cache_wbinval_page(kaddr, vma->vm_flags & VM_EXEC);
+			kunmap_atomic((void *)kaddr);
+		}
+	}
+}
+#else
+extern pte_t va_present(struct mm_struct *mm, unsigned long addr);
+
+static inline unsigned long aliasing(unsigned long addr, unsigned long page)
+{
+	return ((addr & PAGE_MASK) ^ page) & (REALSHMLBA - 1);
+}
+
+static inline unsigned long kremap0(unsigned long uaddr, unsigned long pa)
+{
+	unsigned long kaddr, pte;
+
+#define BASE_ADDR0 0xffffc000
+	kaddr = BASE_ADDR0 | (uaddr & L1_cache_info[DCACHE].aliasing_mask);
+	pte = (pa | PAGE_KERNEL);
+	__nds32__mtsr_dsb(kaddr, NDS32_SR_TLB_VPN);
+	__nds32__tlbop_rwlk(pte);
+	__nds32__isb();
+	return kaddr;
+}
+
+static inline void kunmap01(unsigned long kaddr)
+{
+	__nds32__tlbop_unlk(kaddr);
+	__nds32__tlbop_inv(kaddr);
+	__nds32__isb();
+}
+
+static inline unsigned long kremap1(unsigned long uaddr, unsigned long pa)
+{
+	unsigned long kaddr, pte;
+
+#define BASE_ADDR1 0xffff8000
+	kaddr = BASE_ADDR1 | (uaddr & L1_cache_info[DCACHE].aliasing_mask);
+	pte = (pa | PAGE_KERNEL);
+	__nds32__mtsr_dsb(kaddr, NDS32_SR_TLB_VPN);
+	__nds32__tlbop_rwlk(pte);
+	__nds32__isb();
+	return kaddr;
+}
+
+void flush_cache_mm(struct mm_struct *mm)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	cpu_dcache_wbinval_all();
+	cpu_icache_inval_all();
+	local_irq_restore(flags);
+}
+
+void flush_cache_dup_mm(struct mm_struct *mm)
+{
+}
+
+void flush_cache_range(struct vm_area_struct *vma,
+		       unsigned long start, unsigned long end)
+{
+	unsigned long flags;
+
+	if ((end - start) > 8 * PAGE_SIZE) {
+		cpu_dcache_wbinval_all();
+		if (vma->vm_flags & VM_EXEC)
+			cpu_icache_inval_all();
+		return;
+	}
+	local_irq_save(flags);
+	while (start < end) {
+		if (va_present(vma->vm_mm, start))
+			cpu_cache_wbinval_page(start, vma->vm_flags & VM_EXEC);
+		start += PAGE_SIZE;
+	}
+	local_irq_restore(flags);
+	return;
+}
+
+void flush_cache_page(struct vm_area_struct *vma,
+		      unsigned long addr, unsigned long pfn)
+{
+	unsigned long vto, flags;
+
+	local_irq_save(flags);
+	vto = kremap0(addr, pfn << PAGE_SHIFT);
+	cpu_cache_wbinval_page(vto, vma->vm_flags & VM_EXEC);
+	kunmap01(vto);
+	local_irq_restore(flags);
+}
+
+void flush_cache_vmap(unsigned long start, unsigned long end)
+{
+	cpu_dcache_wbinval_all();
+	cpu_icache_inval_all();
+}
+
+void flush_cache_vunmap(unsigned long start, unsigned long end)
+{
+	cpu_dcache_wbinval_all();
+	cpu_icache_inval_all();
+}
+
+void copy_user_highpage(struct page *to, struct page *from,
+			unsigned long vaddr, struct vm_area_struct *vma)
+{
+	unsigned long vto, vfrom, flags, kto, kfrom, pfrom, pto;
+	kto = ((unsigned long)page_address(to) & PAGE_MASK);
+	kfrom = ((unsigned long)page_address(from) & PAGE_MASK);
+	pto = page_to_phys(to);
+	pfrom = page_to_phys(from);
+
+	if (aliasing(vaddr, (unsigned long)kfrom))
+		cpu_dcache_wb_page((unsigned long)kfrom);
+	if (aliasing(vaddr, (unsigned long)kto))
+		cpu_dcache_inval_page((unsigned long)kto);
+	local_irq_save(flags);
+	vto = kremap0(vaddr, pto);
+	vfrom = kremap1(vaddr, pfrom);
+	copy_page((void *)vto, (void *)vfrom);
+	kunmap01(vfrom);
+	kunmap01(vto);
+	local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(copy_user_highpage);
+
+void clear_user_highpage(struct page *page, unsigned long vaddr)
+{
+	unsigned long vto, flags, kto;
+
+	kto = ((unsigned long)page_address(page) & PAGE_MASK);
+
+	local_irq_save(flags);
+	if (aliasing(kto, vaddr) && kto != 0) {
+		cpu_dcache_inval_page(kto);
+		cpu_icache_inval_page(kto);
+	}
+	vto = kremap0(vaddr, page_to_phys(page));
+	clear_page((void *)vto);
+	kunmap01(vto);
+	local_irq_restore(flags);
+}
+
+EXPORT_SYMBOL(clear_user_highpage);
+
+void flush_dcache_page(struct page *page)
+{
+	struct address_space *mapping;
+
+	mapping = page_mapping(page);
+	if (mapping && !mapping_mapped(mapping))
+		set_bit(PG_dcache_dirty, &page->flags);
+	else {
+		int i, pc;
+		unsigned long vto, kaddr, flags;
+		kaddr = (unsigned long)page_address(page);
+		cpu_dcache_wbinval_page(kaddr);
+		pc = CACHE_SET(DCACHE) * CACHE_LINE_SIZE(DCACHE) / PAGE_SIZE;
+		local_irq_save(flags);
+		for (i = 0; i < pc; i++) {
+			vto =
+			    kremap0(kaddr + i * PAGE_SIZE, page_to_phys(page));
+			cpu_dcache_wbinval_page(vto);
+			kunmap01(vto);
+		}
+		local_irq_restore(flags);
+	}
+}
+
+void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
+		       unsigned long vaddr, void *dst, void *src, int len)
+{
+	unsigned long line_size, start, end, vto, flags;
+
+	local_irq_save(flags);
+	vto = kremap0(vaddr, page_to_phys(page));
+	dst = (void *)(vto | (vaddr & (PAGE_SIZE - 1)));
+	memcpy(dst, src, len);
+	if (vma->vm_flags & VM_EXEC) {
+		line_size = L1_cache_info[DCACHE].line_size;
+		start = (unsigned long)dst & ~(line_size - 1);
+		end =
+		    ((unsigned long)dst + len + line_size - 1) & ~(line_size -
+								   1);
+		cpu_cache_wbinval_range(start, end, 1);
+	}
+	kunmap01(vto);
+	local_irq_restore(flags);
+}
+
+void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
+			 unsigned long vaddr, void *dst, void *src, int len)
+{
+	unsigned long vto, flags;
+
+	local_irq_save(flags);
+	vto = kremap0(vaddr, page_to_phys(page));
+	src = (void *)(vto | (vaddr & (PAGE_SIZE - 1)));
+	memcpy(dst, src, len);
+	kunmap01(vto);
+	local_irq_restore(flags);
+}
+
+void flush_anon_page(struct vm_area_struct *vma,
+		     struct page *page, unsigned long vaddr)
+{
+	unsigned long flags;
+	if (!PageAnon(page))
+		return;
+
+	if (vma->vm_mm != current->active_mm)
+		return;
+
+	local_irq_save(flags);
+	if (vma->vm_flags & VM_EXEC)
+		cpu_icache_inval_page(vaddr & PAGE_MASK);
+	cpu_dcache_wbinval_page((unsigned long)page_address(page));
+	local_irq_restore(flags);
+}
+
+void flush_kernel_dcache_page(struct page *page)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+	cpu_dcache_wbinval_page((unsigned long)page_address(page));
+	local_irq_restore(flags);
+}
+
+void flush_icache_range(unsigned long start, unsigned long end)
+{
+	unsigned long line_size, flags;
+	line_size = L1_cache_info[DCACHE].line_size;
+	start = start & ~(line_size - 1);
+	end = (end + line_size - 1) & ~(line_size - 1);
+	local_irq_save(flags);
+	cpu_cache_wbinval_range(start, end, 1);
+	local_irq_restore(flags);
+}
+
+void flush_icache_page(struct vm_area_struct *vma, struct page *page)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+	cpu_cache_wbinval_page((unsigned long)page_address(page),
+			       vma->vm_flags & VM_EXEC);
+	local_irq_restore(flags);
+}
+
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
+		      pte_t * pte)
+{
+	struct page *page;
+	unsigned long flags;
+	unsigned long pfn = pte_pfn(*pte);
+
+	if (!pfn_valid(pfn))
+		return;
+
+	if (vma->vm_mm == current->active_mm) {
+		__nds32__mtsr_dsb(addr, NDS32_SR_TLB_VPN);
+		__nds32__tlbop_rwr(*pte);
+		__nds32__isb();
+	}
+
+	page = pfn_to_page(pfn);
+	if (test_and_clear_bit(PG_dcache_dirty, &page->flags) ||
+	    (vma->vm_flags & VM_EXEC)) {
+		local_irq_save(flags);
+		cpu_dcache_wbinval_page((unsigned long)page_address(page));
+		local_irq_restore(flags);
+	}
+}
+#endif
diff --git a/arch/nds32/mm/proc-n13.c b/arch/nds32/mm/proc-n13.c
new file mode 100644
index 0000000..9956785
--- /dev/null
+++ b/arch/nds32/mm/proc-n13.c
@@ -0,0 +1,608 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/nds32.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+#include <asm/cacheflush.h>
+#ifdef CONFIG_CACHE_L2
+#include <asm/l2_cache.h>
+#endif
+#include <nds32_intrinsic.h>
+
+#include <asm/cache_info.h>
+extern struct cache_info L1_cache_info[2];
+
+int va_kernel_present(unsigned long addr)
+{
+	pmd_t *pmd;
+	pte_t *ptep, pte;
+
+	pmd = pmd_offset(pgd_offset_k(addr), addr);
+	if (!pmd_none(*pmd)) {
+		ptep = pte_offset_map(pmd, addr);
+		pte = *ptep;
+		if (pte_present(pte))
+			return pte;
+	}
+	return 0;
+}
+
+pte_t va_present(struct mm_struct * mm, unsigned long addr)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *ptep, pte;
+
+	pgd = pgd_offset(mm, addr);
+	if (!pgd_none(*pgd)) {
+		pud = pud_offset(pgd, addr);
+		if (!pud_none(*pud)) {
+			pmd = pmd_offset(pud, addr);
+			if (!pmd_none(*pmd)) {
+				ptep = pte_offset_map(pmd, addr);
+				pte = *ptep;
+				if (pte_present(pte))
+					return pte;
+			}
+		}
+	}
+	return 0;
+
+}
+
+int va_readable(struct pt_regs *regs, unsigned long addr)
+{
+	struct mm_struct *mm = current->mm;
+	pte_t pte;
+	int ret = 0;
+
+	if (user_mode(regs)) {
+		/* user mode */
+		pte = va_present(mm, addr);
+		if (!pte && pte_read(pte))
+			ret = 1;
+	} else {
+		/* superuser mode is always readable, so we can only
+		 * check it is present or not*/
+		return (! !va_kernel_present(addr));
+	}
+	return ret;
+}
+
+int va_writable(struct pt_regs *regs, unsigned long addr)
+{
+	struct mm_struct *mm = current->mm;
+	pte_t pte;
+	int ret = 0;
+
+	if (user_mode(regs)) {
+		/* user mode */
+		pte = va_present(mm, addr);
+		if (!pte && pte_write(pte))
+			ret = 1;
+	} else {
+		/* superuser mode */
+		pte = va_kernel_present(addr);
+		if (!pte && pte_kernel_write(pte))
+			ret = 1;
+	}
+	return ret;
+}
+
+/*
+ * All
+ */
+void n13_icache_inval_all(void)
+{
+	unsigned long end, line_size;
+
+	line_size = L1_cache_info[ICACHE].line_size;
+	end =
+	    line_size * L1_cache_info[ICACHE].ways * L1_cache_info[ICACHE].sets;
+
+	do {
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL"::"r" (end));
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL"::"r" (end));
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL"::"r" (end));
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL"::"r" (end));
+	} while (end > 0);
+}
+
+void n13_dcache_inval_all(void)
+{
+	__nds32__cctl_l1d_invalall();
+}
+
+void n13_dcache_wb_all(void)
+{
+#ifdef CONFIG_CACHE_L2
+	if (atl2c_base)
+		__nds32__cctl_l1d_wball_alvl();
+	else
+		__nds32__cctl_l1d_wball_one_lvl();
+#else
+	__nds32__cctl_l1d_wball_one_lvl();
+#endif
+}
+
+void n13_dcache_wbinval_all(void)
+{
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	unsigned long flags;
+#endif
+
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	local_irq_save(flags);
+#endif
+#ifdef CONFIG_CACHE_L2
+	if (atl2c_base)
+		__nds32__cctl_l1d_wball_alvl();
+	else
+		__nds32__cctl_l1d_wball_one_lvl();
+#else
+	__nds32__cctl_l1d_wball_one_lvl();
+#endif
+	__nds32__cctl_l1d_invalall();
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	local_irq_restore(flags);
+#endif
+}
+
+/*
+ * Page
+ */
+void n13_icache_inval_page(unsigned long start)
+{
+	unsigned long line_size, end;
+
+	line_size = L1_cache_info[ICACHE].line_size;
+	end = start + PAGE_SIZE;
+
+	do {
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL"::"r" (end));
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL"::"r" (end));
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL"::"r" (end));
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL"::"r" (end));
+	} while (end != start);
+}
+
+void n13_dcache_inval_page(unsigned long start)
+{
+	unsigned long line_size, end;
+
+	line_size = L1_cache_info[DCACHE].line_size;
+	end = start + PAGE_SIZE;
+
+	do {
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
+	} while (end != start);
+}
+
+void n13_dcache_wb_page(unsigned long start)
+{
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	unsigned long line_size, end;
+
+	line_size = L1_cache_info[DCACHE].line_size;
+	end = start + PAGE_SIZE;
+
+	do {
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
+		end -= line_size;
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
+	} while (end != start);
+#endif
+}
+
+void n13_dcache_wbinval_page(unsigned long start)
+{
+	unsigned long line_size, end;
+
+	line_size = L1_cache_info[DCACHE].line_size;
+	end = start + PAGE_SIZE;
+
+	do {
+		end -= line_size;
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
+#endif
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
+		end -= line_size;
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
+#endif
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
+		end -= line_size;
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
+#endif
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
+		end -= line_size;
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
+#endif
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
+	} while (end != start);
+}
+
+void n13_cache_wbinval_page(unsigned long page, int flushi)
+{
+	n13_dcache_wbinval_page(page);
+	if (flushi)
+		n13_icache_inval_page(page);
+}
+
+/*
+ * Range
+ */
+void n13_icache_inval_range(unsigned long start, unsigned long end)
+{
+	unsigned long line_size;
+
+	line_size = L1_cache_info[ICACHE].line_size;
+
+	while (end > start) {
+		__asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL"::"r" (start));
+		start += line_size;
+	}
+}
+
+void n13_dcache_inval_range(unsigned long start, unsigned long end)
+{
+	unsigned long line_size;
+
+	line_size = L1_cache_info[DCACHE].line_size;
+
+	while (end > start) {
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (start));
+		start += line_size;
+	}
+}
+
+void n13_dcache_wb_range(unsigned long start, unsigned long end)
+{
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+	unsigned long line_size;
+
+	line_size = L1_cache_info[DCACHE].line_size;
+
+	while (end > start) {
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (start));
+		start += line_size;
+	}
+#endif
+}
+
+void n13_dcache_wbinval_range(unsigned long start, unsigned long end)
+{
+	unsigned long line_size;
+
+	line_size = L1_cache_info[DCACHE].line_size;
+
+	while (end > start) {
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (start));
+#endif
+		__asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (start));
+		start += line_size;
+	}
+}
+
+void n13_cache_wbinval_range(unsigned long start, unsigned long end, int flushi)
+{
+	unsigned long line_size, align_start, align_end;
+
+	line_size = L1_cache_info[DCACHE].line_size;
+	align_start = start & ~(line_size - 1);
+	align_end = (end + line_size - 1) & ~(line_size - 1);
+	n13_dcache_wbinval_range(align_start, align_end);
+
+	if (flushi) {
+		line_size = L1_cache_info[ICACHE].line_size;
+		align_start = start & ~(line_size - 1);
+		align_end = (end + line_size - 1) & ~(line_size - 1);
+		n13_icache_inval_range(align_start, align_end);
+	}
+}
+
+void n13_cache_wbinval_range_check(struct vm_area_struct *vma,
+				   unsigned long start, unsigned long end,
+				   bool flushi, bool wbd)
+{
+	unsigned long line_size, t_start, t_end;
+
+	if (!flushi && !wbd)
+		return;
+	line_size = L1_cache_info[DCACHE].line_size;
+	start = start & ~(line_size - 1);
+	end = (end + line_size - 1) & ~(line_size - 1);
+
+	if ((end - start) > (8 * PAGE_SIZE)) {
+		if (wbd)
+			n13_dcache_wbinval_all();
+		if (flushi)
+			n13_icache_inval_all();
+		return;
+	}
+
+	t_start = (start + PAGE_SIZE) & PAGE_MASK;
+	t_end = ((end - 1) & PAGE_MASK);
+
+	if ((start & PAGE_MASK) == t_end) {
+		if (va_present(vma->vm_mm, start)) {
+			if (wbd)
+				n13_dcache_wbinval_range(start, end);
+			if (flushi)
+				n13_icache_inval_range(start, end);
+		}
+		return;
+	}
+
+	if (va_present(vma->vm_mm, start)) {
+		if (wbd)
+			n13_dcache_wbinval_range(start, end);
+		if (flushi)
+			n13_icache_inval_range(start, end);
+	}
+
+	if (va_present(vma->vm_mm, end - 1)) {
+		if (wbd)
+			n13_dcache_wbinval_range(start, end);
+		if (flushi)
+			n13_icache_inval_range(start, end);
+	}
+
+	while (t_start < t_end) {
+		if (va_present(vma->vm_mm, t_start)) {
+			if (wbd)
+				n13_dcache_wbinval_page(t_start);
+			if (flushi)
+				n13_icache_inval_page(t_start);
+		}
+		t_start += PAGE_SIZE;
+	}
+}
+
+/*
+ * DMA
+ */
+void n13_dma_wb_range(unsigned long start, unsigned long end)
+{
+	unsigned long line_size;
+	unsigned long flags;
+	line_size = L1_cache_info[DCACHE].line_size;
+	start = start & (~(line_size - 1));
+	end = (end + line_size - 1) & (~(line_size - 1));
+	if (unlikely(start == end))
+		return;
+
+	local_irq_save(flags);
+	n13_dcache_wb_range(start, end);
+
+#ifdef CONFIG_CACHE_L2
+	if (atl2c_base) {
+		unsigned long p_start = __pa(start);
+		unsigned long p_end = __pa(end);
+		unsigned long cmd;
+		/* TODO Can Use PAGE Mode to optimize if range large than PAGE_SIZE */
+		line_size = L2_CACHE_LINE_SIZE();
+		p_start = p_start & (~(line_size - 1));
+		p_end = (p_end + line_size - 1) & (~(line_size - 1));
+		cmd =
+		    (p_start & ~(line_size - 1)) | CCTL_CMD_L2_PA_WB |
+		    CCTL_SINGLE_CMD;
+		do {
+			L2_CMD_RDY();
+			L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
+			cmd += line_size;
+			p_start += line_size;
+		} while (p_end > p_start);
+		cmd = CCTL_CMD_L2_SYNC;
+		L2_CMD_RDY();
+		L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
+		L2_CMD_RDY();
+
+	}
+#endif
+	local_irq_restore(flags);
+}
+
+#ifdef CONFIG_CACHE_L2
+void n13_l2dcache_wbinval_range(unsigned long start, unsigned long end)
+{
+	unsigned long p_start;
+	unsigned long p_end;
+	unsigned long cmd;
+	unsigned long line_size;
+
+	p_start = __pa(start);
+	p_end = __pa(end);
+	/* TODO Can Use PAGE Mode to optimize if range large than PAGE_SIZE */
+	line_size = L2_CACHE_LINE_SIZE();
+	p_start = p_start & (~(line_size - 1));
+	p_end = (p_end + line_size - 1) & (~(line_size - 1));
+	cmd =
+	    (p_start & ~(line_size - 1)) | CCTL_CMD_L2_PA_WBINVAL |
+	    CCTL_SINGLE_CMD;
+	do {
+		L2_CMD_RDY();
+		L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
+		cmd += line_size;
+		p_start += line_size;
+	} while (p_end > p_start);
+	cmd = CCTL_CMD_L2_SYNC;
+	L2_CMD_RDY();
+	L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
+	L2_CMD_RDY();
+
+}
+#endif
+
+void n13_dma_inval_range(unsigned long start, unsigned long end)
+{
+	unsigned long line_size;
+	unsigned long old_start = start;
+	unsigned long old_end = end;
+	unsigned long flags;
+	line_size = L1_cache_info[DCACHE].line_size;
+	start = start & (~(line_size - 1));
+	end = (end + line_size - 1) & (~(line_size - 1));
+	if (unlikely(start == end))
+		return;
+	local_irq_save(flags);
+	if (start != old_start) {
+		n13_dcache_wbinval_range(start, start + line_size);
+#ifdef CONFIG_CACHE_L2
+		if (atl2c_base)
+			n13_l2dcache_wbinval_range(start, start + line_size);
+#endif
+	}
+	if (end != old_end) {
+		n13_dcache_wbinval_range(end - line_size, end);
+#ifdef CONFIG_CACHE_L2
+		if (atl2c_base)
+			n13_l2dcache_wbinval_range(end - line_size, end);
+#endif
+	}
+	n13_dcache_inval_range(start, end);
+#ifdef CONFIG_CACHE_L2
+	if (atl2c_base) {
+		unsigned long p_start = __pa(start);
+		unsigned long p_end = __pa(end);
+		unsigned long cmd;
+		/* TODO Can Use PAGE Mode to optimize if range large than PAGE_SIZE */
+		line_size = L2_CACHE_LINE_SIZE();
+		p_start = p_start & (~(line_size - 1));
+		p_end = (p_end + line_size - 1) & (~(line_size - 1));
+		cmd =
+		    (p_start & ~(line_size - 1)) | CCTL_CMD_L2_PA_INVAL |
+		    CCTL_SINGLE_CMD;
+		do {
+			L2_CMD_RDY();
+			L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
+			cmd += line_size;
+			p_start += line_size;
+		} while (p_end > p_start);
+		cmd = CCTL_CMD_L2_SYNC;
+		L2_CMD_RDY();
+		L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
+		L2_CMD_RDY();
+	}
+#endif
+	local_irq_restore(flags);
+
+}
+
+void n13_dma_wbinval_range(unsigned long start, unsigned long end)
+{
+	unsigned long line_size;
+	unsigned long flags;
+	line_size = L1_cache_info[DCACHE].line_size;
+	start = start & (~(line_size - 1));
+	end = (end + line_size - 1) & (~(line_size - 1));
+	if (unlikely(start == end))
+		return;
+
+	local_irq_save(flags);
+	n13_dcache_wbinval_range(start, end);
+#ifdef CONFIG_CACHE_L2
+	if (atl2c_base) {
+		unsigned long p_start = __pa(start);
+		unsigned long p_end = __pa(end);
+		unsigned long cmd;
+
+		/* TODO Can Use PAGE Mode to optimize if range large than PAGE_SIZE */
+		line_size = L2_CACHE_LINE_SIZE();
+		p_start = p_start & (~(line_size - 1));
+		p_end = (p_end + line_size - 1) & (~(line_size - 1));
+		cmd =
+		    (p_start & ~(line_size - 1)) | CCTL_CMD_L2_PA_WBINVAL |
+		    CCTL_SINGLE_CMD;
+		do {
+			L2_CMD_RDY();
+			L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
+			cmd += line_size;
+			p_start += line_size;
+		} while (p_end > p_start);
+		cmd = CCTL_CMD_L2_SYNC;
+		L2_CMD_RDY();
+		L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
+		L2_CMD_RDY();
+
+	}
+#endif
+	local_irq_restore(flags);
+}
+
+void n13_proc_init(void)
+{
+}
+
+void n13_proc_fin(void)
+{
+}
+
+void n13_do_idle(void)
+{
+	__nds32__standby_no_wake_grant();
+}
+
+void n13_reset(unsigned long reset)
+{
+	u32 tmp;
+	GIE_DISABLE();
+	tmp = __nds32__mfsr(NDS32_SR_CACHE_CTL);
+	tmp &= ~(CACHE_CTL_mskIC_EN | CACHE_CTL_mskDC_EN);
+	__nds32__mtsr_isb(tmp, NDS32_SR_CACHE_CTL);
+	n13_dcache_wbinval_all();
+	n13_icache_inval_all();
+
+	__asm__ __volatile__("jr.toff %0\n\t"::"r"(reset));
+}
+
+void n13_switch_mm(struct mm_struct *mm)
+{
+	unsigned long cid;
+	cid = __nds32__mfsr(NDS32_SR_TLB_MISC);
+	cid = (cid & ~TLB_MISC_mskCID) | mm->context.id;
+	__nds32__mtsr_dsb(cid, NDS32_SR_TLB_MISC);
+	__nds32__mtsr_isb(__pa(mm->pgd), NDS32_SR_L1_PPTB);
+}
diff --git a/arch/nds32/mm/tlb.c b/arch/nds32/mm/tlb.c
new file mode 100644
index 0000000..b397b9f
--- /dev/null
+++ b/arch/nds32/mm/tlb.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/spinlock_types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <asm/nds32.h>
+#include <nds32_intrinsic.h>
+
+unsigned int cpu_last_cid = { TLB_MISC_mskCID + (2 << TLB_MISC_offCID) };
+
+DEFINE_SPINLOCK(cid_lock);
+
+void local_flush_tlb_range(struct vm_area_struct *vma,
+			   unsigned long start, unsigned long end)
+{
+	unsigned long flags, ocid, ncid;
+
+	if ((end - start) > 0x400000) {
+		__nds32__tlbop_flua();
+		__nds32__isb();
+		return;
+	}
+
+	spin_lock_irqsave(&cid_lock, flags);
+	ocid = __nds32__mfsr(NDS32_SR_TLB_MISC);
+	ncid = (ocid & ~TLB_MISC_mskCID) | vma->vm_mm->context.id;
+	__nds32__mtsr_dsb(ncid, NDS32_SR_TLB_MISC);
+	while (start < end) {
+		__nds32__tlbop_inv(start);
+		__nds32__isb();
+		start += PAGE_SIZE;
+	}
+	__nds32__mtsr_dsb(ocid, NDS32_SR_TLB_MISC);
+	spin_unlock_irqrestore(&cid_lock, flags);
+}
+
+void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
+{
+	unsigned long flags, ocid, ncid;
+
+	spin_lock_irqsave(&cid_lock, flags);
+	ocid = __nds32__mfsr(NDS32_SR_TLB_MISC);
+	ncid = (ocid & ~TLB_MISC_mskCID) | vma->vm_mm->context.id;
+	__nds32__mtsr_dsb(ncid, NDS32_SR_TLB_MISC);
+	__nds32__tlbop_inv(addr);
+	__nds32__isb();
+	__nds32__mtsr_dsb(ocid, NDS32_SR_TLB_MISC);
+	spin_unlock_irqrestore(&cid_lock, flags);
+}
-- 
1.7.9.5

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

* [PATCH 09/31] nds32: Process management
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (7 preceding siblings ...)
  2017-11-08  5:54 ` [PATCH 08/31] nds32: Cache and TLB routines Greentime Hu
@ 2017-11-08  5:54 ` Greentime Hu
  2017-11-08  5:54 ` [PATCH 10/31] nds32: IRQ handling Greentime Hu
                   ` (23 subsequent siblings)
  32 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:54 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/asm/current.h     |   25 ++++
 arch/nds32/include/asm/processor.h   |  116 ++++++++++++++++++
 arch/nds32/include/asm/thread_info.h |   91 ++++++++++++++
 arch/nds32/kernel/process.c          |  219 ++++++++++++++++++++++++++++++++++
 4 files changed, 451 insertions(+)
 create mode 100644 arch/nds32/include/asm/current.h
 create mode 100644 arch/nds32/include/asm/processor.h
 create mode 100644 arch/nds32/include/asm/thread_info.h
 create mode 100644 arch/nds32/kernel/process.c

diff --git a/arch/nds32/include/asm/current.h b/arch/nds32/include/asm/current.h
new file mode 100644
index 0000000..027f7df
--- /dev/null
+++ b/arch/nds32/include/asm/current.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ASM_NDS32_CURRENT_H
+#define _ASM_NDS32_CURRENT_H
+
+#ifndef __ASSEMBLY__
+register struct task_struct *current asm("$r25");
+#endif /* __ASSEMBLY__ */
+#define tsk $r25
+
+#endif /* _ASM_NDS32_CURRENT_H */
diff --git a/arch/nds32/include/asm/processor.h b/arch/nds32/include/asm/processor.h
new file mode 100644
index 0000000..03dab61
--- /dev/null
+++ b/arch/nds32/include/asm/processor.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_NDS32_PROCESSOR_H
+#define __ASM_NDS32_PROCESSOR_H
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+
+#ifdef __KERNEL__
+
+#include <asm/ptrace.h>
+#include <asm/types.h>
+#include <asm/sigcontext.h>
+
+#define KERNEL_STACK_SIZE	PAGE_SIZE
+#define STACK_TOP	TASK_SIZE
+#define STACK_TOP_MAX   TASK_SIZE
+
+struct cpu_context {
+	unsigned long r6;
+	unsigned long r7;
+	unsigned long r8;
+	unsigned long r9;
+	unsigned long r10;
+	unsigned long r11;
+	unsigned long r12;
+	unsigned long r13;
+	unsigned long r14;
+	unsigned long fp;
+	unsigned long pc;
+	unsigned long sp;
+};
+
+struct thread_struct {
+	struct cpu_context cpu_context;	/* cpu context */
+	/* fault info     */
+	unsigned long address;
+	unsigned long trap_no;
+	unsigned long error_code;
+};
+
+#define INIT_THREAD  {	}
+
+#ifdef __NDS32_EB__
+#define PSW_DE	PSW_mskBE
+#else
+#define PSW_DE	0x0
+#endif
+
+#ifdef CONFIG_WBNA
+#define PSW_valWBNA	PSW_mskWBNA
+#else
+#define PSW_valWBNA	0x0
+#endif
+
+#ifdef CONFIG_HWZOL
+#define	PSW_valINIT (PSW_CPL_ANY | PSW_mskAEN | PSW_valWBNA | PSW_mskDT | PSW_mskIT | PSW_DE | PSW_mskGIE)
+#else
+#define	PSW_valINIT (PSW_CPL_ANY | PSW_valWBNA | PSW_mskDT | PSW_mskIT | PSW_DE | PSW_mskGIE)
+#endif
+
+#define start_thread(regs,pc,stack)			\
+({							\
+	set_fs(USER_DS);				\
+	memzero(regs, sizeof(struct pt_regs));		\
+	regs->ipsw = PSW_valINIT;			\
+	regs->ir0 = (PSW_CPL_ANY | PSW_valWBNA | PSW_mskDT | PSW_mskIT | PSW_DE | PSW_SYSTEM | PSW_INTL_1);	\
+	regs->ipc = pc;					\
+	regs->sp = stack;				\
+})
+
+/* Forward declaration, a strange C thing */
+struct task_struct;
+
+/* Free all resources held by a thread. */
+#define release_thread(thread) do { } while(0)
+
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
+unsigned long get_wchan(struct task_struct *p);
+
+#define cpu_relax()			barrier()
+
+#define task_pt_regs(task) \
+	((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE \
+		- 8) - 1)
+
+/*
+ * Create a new kernel thread
+ */
+extern int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags);
+
+#define KSTK_EIP(tsk)	instruction_pointer(task_pt_regs(tsk))
+#define KSTK_ESP(tsk)	user_stack_pointer(task_pt_regs(tsk))
+
+#endif
+
+#endif /* __ASM_NDS32_PROCESSOR_H */
diff --git a/arch/nds32/include/asm/thread_info.h b/arch/nds32/include/asm/thread_info.h
new file mode 100644
index 0000000..216cc85
--- /dev/null
+++ b/arch/nds32/include/asm/thread_info.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_NDS32_THREAD_INFO_H
+#define __ASM_NDS32_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#define THREAD_SIZE_ORDER 	(1)
+#define THREAD_SIZE		(PAGE_SIZE << THREAD_SIZE_ORDER)
+
+#ifndef __ASSEMBLY__
+
+struct task_struct;
+
+#include <asm/ptrace.h>
+#include <asm/types.h>
+
+typedef unsigned long mm_segment_t;
+
+/*
+ * low level task data that entry.S needs immediate access to.
+ * __switch_to() assumes cpu_context follows immediately after cpu_domain.
+ */
+struct thread_info {
+	unsigned long flags;	/* low level flags */
+	__s32 preempt_count;	/* 0 => preemptable, <0 => bug */
+	mm_segment_t addr_limit;	/* address limit */
+};
+#define INIT_THREAD_INFO(tsk)						\
+{									\
+	.preempt_count	= INIT_PREEMPT_COUNT,				\
+	.addr_limit	= KERNEL_DS,					\
+}
+#define init_thread_info	(init_thread_union.thread_info)
+#define init_stack		(init_thread_union.stack)
+#define thread_saved_pc(tsk) ((unsigned long)(tsk->thread.cpu_context.pc))
+#define thread_saved_fp(tsk) ((unsigned long)(tsk->thread.cpu_context.fp))
+#endif
+
+/*
+ * thread information flags:
+ *  TIF_SYSCALL_TRACE	- syscall trace active
+ *  TIF_SIGPENDING	- signal pending
+ *  TIF_NEED_RESCHED	- rescheduling necessary
+ *  TIF_NOTIFY_RESUME	- callback before returning to user
+ *  TIF_USEDFPU		- FPU was used by this task this quantum (SMP)
+ *  TIF_POLLING_NRFLAG	- true if poll_idle() is polling TIF_NEED_RESCHED
+ */
+#define TIF_SIGPENDING		1
+#define TIF_NEED_RESCHED	2
+#define TIF_SINGLESTEP		3
+#define TIF_NOTIFY_RESUME	4	/* callback before returning to user */
+#define TIF_SYSCALL_TRACE	8
+#define TIF_USEDFPU             16
+#define TIF_POLLING_NRFLAG	17
+#define TIF_MEMDIE		18
+#define TIF_FREEZE		19
+#define TIF_RESTORE_SIGMASK	20
+
+#define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
+#define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
+#define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
+#define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
+#define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
+#define _TIF_FREEZE		(1 << TIF_FREEZE)
+#define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
+
+/*
+ * Change these and you break ASM code in entry-common.S
+ */
+#define _TIF_WORK_MASK		0x000000ff
+#define _TIF_WORK_SYSCALL_ENTRY (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP)
+#define _TIF_WORK_SYSCALL_LEAVE (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP)
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_NDS32_THREAD_INFO_H */
diff --git a/arch/nds32/kernel/process.c b/arch/nds32/kernel/process.c
new file mode 100644
index 0000000..0cbef3f
--- /dev/null
+++ b/arch/nds32/kernel/process.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/sched.h>
+#include <linux/sched/debug.h>
+#include <linux/sched/task_stack.h>
+#include <linux/delay.h>
+#include <linux/kallsyms.h>
+#include <asm/uaccess.h>
+#include <asm/elf.h>
+#include <asm/proc-fns.h>
+#include <linux/ptrace.h>
+
+extern void setup_mm_for_reboot(char mode);
+#ifdef CONFIG_PROC_FS
+struct proc_dir_entry *proc_dir_cpu;
+EXPORT_SYMBOL(proc_dir_cpu);
+#endif
+
+extern inline void arch_reset(char mode)
+{
+	if (mode == 's') {
+		/* Use cpu handler, jump to 0 */
+		cpu_reset(0);
+	}
+}
+
+void (*pm_power_off) (void);
+EXPORT_SYMBOL(pm_power_off);
+
+static char reboot_mode = 'h';
+
+int __init reboot_setup(char *str)
+{
+	reboot_mode = str[0];
+	return 1;
+}
+
+static int cpub_pwroff(void)
+{
+	return 0;
+}
+
+__setup("reboot=", reboot_setup);
+
+void machine_halt(void)
+{
+	cpub_pwroff();
+}
+
+EXPORT_SYMBOL(machine_halt);
+
+void machine_power_off(void)
+{
+	if (pm_power_off)
+		pm_power_off();
+}
+
+EXPORT_SYMBOL(machine_power_off);
+
+void machine_restart(char *__unused)
+{
+	/*
+	 * Clean and disable cache, and turn off interrupts
+	 */
+	cpu_proc_fin();
+
+	/*
+	 * Tell the mm system that we are going to reboot -
+	 * we may need it to insert some 1:1 mappings so that
+	 * soft boot works.
+	 */
+	setup_mm_for_reboot(reboot_mode);
+
+	/*
+	 * Now call the architecture specific reboot code.
+	 */
+	arch_reset(reboot_mode);
+
+	/*
+	 * Whoops - the architecture was unable to reboot.
+	 * Tell the user!
+	 */
+	mdelay(1000);
+	pr_info("Reboot failed -- System halted\n");
+	while (1) ;
+}
+
+EXPORT_SYMBOL(machine_restart);
+
+void show_regs(struct pt_regs *regs)
+{
+	print_symbol("PC is at %s\n", instruction_pointer(regs));
+	print_symbol("LP is at %s\n", regs->lp);
+	pr_info("pc : [<%08lx>]    lp : [<%08lx>]    %s\n"
+		"sp : %08lx  fp : %08lx  gp : %08lx\n",
+		instruction_pointer(regs),
+		regs->lp, print_tainted(), regs->sp, regs->fp, regs->gp);
+	pr_info("r25: %08lx  r24: %08lx\n", regs->uregs[25], regs->uregs[24]);
+
+	pr_info("r23: %08lx  r22: %08lx  r21: %08lx  r20: %08lx\n",
+		regs->uregs[23], regs->uregs[22],
+		regs->uregs[21], regs->uregs[20]);
+	pr_info("r19: %08lx  r18: %08lx  r17: %08lx  r16: %08lx\n",
+		regs->uregs[19], regs->uregs[18],
+		regs->uregs[17], regs->uregs[16]);
+	pr_info("r15: %08lx  r14: %08lx  r13: %08lx  r12: %08lx\n",
+		regs->uregs[15], regs->uregs[14],
+		regs->uregs[13], regs->uregs[12]);
+	pr_info("r11: %08lx  r10: %08lx  r9 : %08lx  r8 : %08lx\n",
+		regs->uregs[11], regs->uregs[10],
+		regs->uregs[9], regs->uregs[8]);
+	pr_info("r7 : %08lx  r6 : %08lx  r5 : %08lx  r4 : %08lx\n",
+		regs->uregs[7], regs->uregs[6], regs->uregs[5], regs->uregs[4]);
+	pr_info("r3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n",
+		regs->uregs[3], regs->uregs[2], regs->uregs[1], regs->uregs[0]);
+	pr_info("  IRQs o%s  Segment %s\n",
+		interrupts_enabled(regs) ? "n" : "ff",
+		segment_eq(get_fs(), get_ds())? "kernel" : "user");
+}
+
+EXPORT_SYMBOL(show_regs);
+
+void flush_thread(void)
+{
+}
+
+DEFINE_PER_CPU(struct task_struct *, __entry_task);
+
+asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+int copy_thread(unsigned long clone_flags, unsigned long stack_start,
+	    unsigned long stk_sz, struct task_struct *p)
+{
+	struct pt_regs *childregs = task_pt_regs(p);
+
+	memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));
+
+	if (unlikely(p->flags & PF_KTHREAD)) {
+		memset(childregs, 0, sizeof(struct pt_regs));
+		/* kernel thread fn */
+		p->thread.cpu_context.r6 = stack_start;
+		/* kernel thread argument */
+		p->thread.cpu_context.r7 = stk_sz;
+	} else {
+		*childregs = *current_pt_regs();
+		if (stack_start)
+			childregs->sp = stack_start;
+		/* child get zero as ret. */
+		childregs->uregs[0] = 0;
+		childregs->osp = 0;
+		if (clone_flags & CLONE_SETTLS)
+			childregs->uregs[25] = childregs->uregs[3];
+	}
+	/* cpu context switching  */
+	p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
+	p->thread.cpu_context.sp = (unsigned long)childregs;
+
+#ifdef CONFIG_HWZOL
+	childregs->lb = 0;
+	childregs->le = 0;
+	childregs->lc = 0;
+#endif
+
+	return 0;
+}
+
+/*
+ * fill in the fpe structure for a core dump...
+ */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpu)
+{
+	int fpvalid = 0;
+	return fpvalid;
+}
+
+EXPORT_SYMBOL(dump_fpu);
+
+unsigned long get_wchan(struct task_struct *p)
+{
+	unsigned long fp, lr;
+	unsigned long stack_start, stack_end;
+	int count = 0;
+
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+
+#ifdef CONFIG_FRAME_POINTER
+	stack_start = (unsigned long)end_of_stack(p);
+	stack_end = (unsigned long)task_stack_page(p) + THREAD_SIZE;
+
+	fp = thread_saved_fp(p);
+	do {
+		if (fp < stack_start || fp > stack_end)
+			return 0;
+		lr = ((unsigned long *)fp)[0];
+		if (!in_sched_functions(lr))
+			return lr;
+		fp = *(unsigned long *)(fp + 4);
+	} while (count++ < 16);
+	return 0;
+#else
+	return 0;
+#endif
+}
+
+EXPORT_SYMBOL(get_wchan);
-- 
1.7.9.5

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

* [PATCH 10/31] nds32: IRQ handling
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (8 preceding siblings ...)
  2017-11-08  5:54 ` [PATCH 09/31] nds32: Process management Greentime Hu
@ 2017-11-08  5:54 ` Greentime Hu
  2017-11-08  8:49   ` Arnd Bergmann
  2017-11-08  5:54 ` [PATCH 11/31] nds32: Atomic operations Greentime Hu
                   ` (22 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:54 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/asm/irqflags.h |   49 +++++++++++++++++++++++++++++++++++++
 arch/nds32/kernel/irq.c           |   34 +++++++++++++++++++++++++
 2 files changed, 83 insertions(+)
 create mode 100644 arch/nds32/include/asm/irqflags.h
 create mode 100644 arch/nds32/kernel/irq.c

diff --git a/arch/nds32/include/asm/irqflags.h b/arch/nds32/include/asm/irqflags.h
new file mode 100644
index 0000000..7c1940f
--- /dev/null
+++ b/arch/nds32/include/asm/irqflags.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <asm/nds32.h>
+#include <nds32_intrinsic.h>
+
+#define arch_local_irq_disable()	\
+	GIE_DISABLE();
+
+#define arch_local_irq_enable()	\
+	GIE_ENABLE();
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags;
+	flags = __nds32__mfsr(NDS32_SR_PSW) & PSW_mskGIE;
+	GIE_DISABLE();
+	return flags;
+}
+
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+	flags = __nds32__mfsr(NDS32_SR_PSW) & PSW_mskGIE;
+	return flags;
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	if(flags)
+		GIE_ENABLE();
+}
+
+static inline int arch_irqs_disabled_flags(unsigned long flags)
+{
+	return !flags;
+}
diff --git a/arch/nds32/kernel/irq.c b/arch/nds32/kernel/irq.c
new file mode 100644
index 0000000..1b935f7
--- /dev/null
+++ b/arch/nds32/kernel/irq.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/irqchip.h>
+
+void __init init_IRQ(void)
+{
+	irqchip_init();
+}
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+void notrace arch_trace_hardirqs_on(void)
+{
+	trace_hardirqs_on();
+}
+
+void notrace arch_trace_hardirqs_off(void)
+{
+	trace_hardirqs_off();
+}
+#endif
-- 
1.7.9.5

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

* [PATCH 11/31] nds32: Atomic operations
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (9 preceding siblings ...)
  2017-11-08  5:54 ` [PATCH 10/31] nds32: IRQ handling Greentime Hu
@ 2017-11-08  5:54 ` Greentime Hu
  2017-11-08  8:54   ` Arnd Bergmann
  2017-11-20 14:29   ` Will Deacon
  2017-11-08  5:55 ` [PATCH 12/31] nds32: Device specific operations Greentime Hu
                   ` (21 subsequent siblings)
  32 siblings, 2 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:54 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/asm/futex.h    |  116 ++++++++++++++++++++++++
 arch/nds32/include/asm/spinlock.h |  178 +++++++++++++++++++++++++++++++++++++
 2 files changed, 294 insertions(+)
 create mode 100644 arch/nds32/include/asm/futex.h
 create mode 100644 arch/nds32/include/asm/spinlock.h

diff --git a/arch/nds32/include/asm/futex.h b/arch/nds32/include/asm/futex.h
new file mode 100644
index 0000000..5aa107c
--- /dev/null
+++ b/arch/nds32/include/asm/futex.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NDS32_FUTEX_H__
+#define __NDS32_FUTEX_H__
+
+#include <linux/futex.h>
+#include <linux/uaccess.h>
+#include <asm/errno.h>
+
+#define __futex_atomic_ex_table(err_reg)			\
+	"	.pushsection __ex_table,\"a\"\n"		\
+	"	.align	3\n"					\
+	"	.long	1b, 4f\n"				\
+	"	.long	2b, 4f\n"				\
+	"	.popsection\n"					\
+	"	.pushsection .fixup,\"ax\"\n"			\
+	"4:	move	%0, " err_reg "\n"			\
+	"	j	3b\n"					\
+	"	.popsection"
+
+#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg)	\
+	smp_mb();						\
+	asm volatile(					\
+	"	movi	$ta, #0\n"				\
+	"1:	llw	%1, [%2+$ta]\n"				\
+	"	" insn "\n"					\
+	"2:	scw	%0, [%2+$ta]\n"				\
+	"	beqz	%0, 1b\n"				\
+	"	movi	%0, #0\n"				\
+	"3:\n"							\
+	__futex_atomic_ex_table("%4")				\
+	: "=&r" (ret), "=&r" (oldval)				\
+	: "r" (uaddr), "r" (oparg), "i" (-EFAULT)		\
+	: "cc", "memory")
+static inline int
+futex_atomic_cmpxchg_inatomic(u32 * uval, u32 __user * uaddr,
+			      u32 oldval, u32 newval)
+{
+	int ret = 0;
+	u32 val, tmp, flags;
+
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+		return -EFAULT;
+
+	smp_mb();
+	asm volatile ("       movi    $ta, #0\n"
+		      "1:     llw     %1, [%6 + $ta]\n"
+		      "       sub     %3, %1, %4\n"
+		      "       cmovz   %2, %5, %3\n"
+		      "       cmovn   %2, %1, %3\n"
+		      "2:     scw     %2, [%6 + $ta]\n"
+		      "       beqz    %2, 1b\n"
+		      "3:\n                   " __futex_atomic_ex_table("%7")
+		      :"+&r"(ret), "=&r"(val), "=&r"(tmp), "=&r"(flags)
+		      :"r"(oldval), "r"(newval), "r"(uaddr), "i"(-EFAULT)
+		      :"$ta", "memory");
+	smp_mb();
+
+	*uval = val;
+	return ret;
+}
+
+static inline int
+arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr)
+{
+	int oldval = 0, ret;
+
+
+	pagefault_disable();
+	switch (op) {
+	case FUTEX_OP_SET:
+		__futex_atomic_op("move	%0, %3", ret, oldval, tmp, uaddr,
+				  oparg);
+		break;
+	case FUTEX_OP_ADD:
+		__futex_atomic_op("add	%0, %1, %3", ret, oldval, tmp, uaddr,
+				  oparg);
+		break;
+	case FUTEX_OP_OR:
+		__futex_atomic_op("or	%0, %1, %3", ret, oldval, tmp, uaddr,
+				  oparg);
+		break;
+	case FUTEX_OP_ANDN:
+		__futex_atomic_op("and	%0, %1, %3", ret, oldval, tmp, uaddr,
+				  ~oparg);
+		break;
+	case FUTEX_OP_XOR:
+		__futex_atomic_op("xor	%0, %1, %3", ret, oldval, tmp, uaddr,
+				  oparg);
+		break;
+	default:
+		ret = -ENOSYS;
+	}
+
+	pagefault_enable();
+
+	if (!ret)
+		*oval = oldval;
+
+	return ret;
+}
+#endif /* __NDS32_FUTEX_H__ */
diff --git a/arch/nds32/include/asm/spinlock.h b/arch/nds32/include/asm/spinlock.h
new file mode 100644
index 0000000..dd5fc71
--- /dev/null
+++ b/arch/nds32/include/asm/spinlock.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_SPINLOCK_H
+#define __ASM_SPINLOCK_H
+
+#include <asm/processor.h>
+
+#define arch_spin_is_locked(x)		((x)->lock != 0)
+
+#define arch_spin_unlock_wait(lock) \
+	do { while (arch_spin_is_locked(lock)) cpu_relax(); } while (0)
+
+#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
+
+static inline void arch_spin_lock(arch_spinlock_t * lock)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__("1:\n"
+			     "\tllw\t%0, [%1]\n"
+			     "\tbnez\t%0, 1b\n"
+			     "\tmovi\t%0, #0x1\n"
+			     "\tscw\t%0, [%1]\n"
+			     "\tbeqz\t%0, 1b\n"
+			     :"=&r"(tmp)
+			     :"r"(&lock->lock)
+			     :"memory");
+}
+
+static inline int arch_spin_trylock(arch_spinlock_t * lock)
+{
+	unsigned long ret, tmp;
+
+	__asm__ __volatile__("1:\n"
+			     "\tllw\t%0, [%2]\n"
+			     "\tmovi\t%1, #0x1\n"
+			     "\tscw\t%1, [%2]\n"
+			     "\tbeqz\t%1, 1b\n"
+			     :"=&r"(ret), "=&r"(tmp)
+			     :"r"(&lock->lock)
+			     :"memory");
+
+	return ret == 0;
+}
+
+static inline void arch_spin_unlock(arch_spinlock_t * lock)
+{
+	__asm__ __volatile__("xor\t$r15,  $r15, $r15\n"
+			     "\tswi\t$r15, [%0]\n"
+			     :
+			     :"r"(&lock->lock)
+			     :"memory");
+}
+
+static inline void arch_write_lock(arch_rwlock_t * rw)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__("1:\n"
+			     "\tllw\t%0, [%1]\n"
+			     "\tbnez\t%0, 1b\n"
+			     "\tsethi\t%0, 0x80000\n"
+			     "\tscw\t%0, [%1]\n"
+			     "\tbeqz\t%0, 1b\n"
+			     :"=&r"(tmp)
+			     :"r"(&rw->lock)
+			     :"memory");
+}
+
+static inline void arch_write_unlock(arch_rwlock_t * rw)
+{
+	__asm__ __volatile__("xor\t$r15, $r15, $r15\n"
+			     "\tswi\t$r15, [%0]\n"
+			     :
+			     :"r"(&rw->lock)
+			     :"memory","$r15");
+}
+
+#define arch_write_can_lock(x)		((x)->lock == 0)
+static inline void arch_read_lock(arch_rwlock_t * rw)
+{
+	int tmp;
+
+	__asm__ __volatile__("1:\n"
+			     "\tllw\t%0, [%1]\n"
+			     "\tbltz\t%0, 1b\n"
+			     "\taddi\t%0, %0, #1\n"
+			     "\tscw\t%0, [%1]\n"
+			     "\tbeqz\t%0, 1b\n"
+			     :"=&r"(tmp)
+			     :"r"(&rw->lock)
+			     :"memory");
+}
+
+static inline void arch_read_unlock(arch_rwlock_t * rw)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__("1:\n"
+			     "\tllw\t%0, [%1]\n"
+			     "\taddi\t%0, %0, #-1\n"
+			     "\tscw\t%0, [%1]\n"
+			     "\tbeqz\t%0, 1b\n"
+			     :"=&r"(tmp)
+			     :"r"(&rw->lock)
+			     :"memory");
+}
+
+static inline int arch_read_trylock(arch_rwlock_t * rw)
+{
+	unsigned long ret, tmp;
+
+	__asm__ __volatile__("\tmovi\t%0, #0x0\n"
+			     "1:\n"
+			     "\tllw\t%1, [%2]\n"
+			     "\tbltz\t%1, 2f\n"
+			     "\taddi\t%1, %1, #1\n"
+			     "\tscw\t%1, [%2]\n"
+			     "\tbeqz\t%1, 1b\n"
+			     "\tmovi\t%0, #0x1\n"
+			     "\tj\t3f\n"
+			     "2:\n"
+			     "\tscw\t%1, [%2]\n"
+			     "3:\n"
+			     :"=&r"(ret), "=&r"(tmp)
+			     :"r"(&rw->lock)
+			     :"memory");
+
+	return ret;
+}
+
+static inline int arch_write_trylock(arch_rwlock_t * rw)
+{
+	unsigned long ret, tmp;
+
+	__asm__ __volatile__("\tmovi\t%0, #0x0\n"
+			     "1:\n"
+			     "\tllw\t%1, [%2]\n"
+			     "\tbnez\t%1, 2f\n"
+			     "\tsethi\t%1, 0x80000\n"
+			     "\tscw\t%1, [%2]\n"
+			     "\tbeqz\t%1, 1b\n"
+			     "\tmovi\t%0, #0x1\n"
+			     "\tj\t3f\n"
+			     "2:\n"
+			     "\tscw\t%1, [%2]\n"
+			     "3:\n"
+			     :"=&r"(ret), "=&r"(tmp)
+			     :"r"(&rw->lock)
+			     :"memory");
+
+	return ret;
+}
+
+#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
+#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
+
+#define arch_read_can_lock(x)	((x)->lock < 0x80000000)
+
+#define arch_spin_relax(lock)	cpu_relax()
+#define arch_read_relax(lock)	cpu_relax()
+#define arch_write_relax(lock)	cpu_relax()
+
+#endif /* __ASM_SPINLOCK_H */
-- 
1.7.9.5

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

* [PATCH 12/31] nds32: Device specific operations
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (10 preceding siblings ...)
  2017-11-08  5:54 ` [PATCH 11/31] nds32: Atomic operations Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08  9:04   ` Arnd Bergmann
  2017-11-08  5:55 ` [PATCH 13/31] nds32: DMA mapping API Greentime Hu
                   ` (20 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/asm/io.h |   33 +++++++++++++++++++++
 arch/nds32/mm/ioremap.c     |   67 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 100 insertions(+)
 create mode 100644 arch/nds32/include/asm/io.h
 create mode 100644 arch/nds32/mm/ioremap.c

diff --git a/arch/nds32/include/asm/io.h b/arch/nds32/include/asm/io.h
new file mode 100644
index 0000000..98b3ae9
--- /dev/null
+++ b/arch/nds32/include/asm/io.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_NDS32_IO_H
+#define __ASM_NDS32_IO_H
+
+#ifdef __KERNEL__
+
+#include <asm-generic/iomap.h>
+extern void __iomem *__ioremap(unsigned long, size_t, unsigned long,
+			       unsigned long);
+extern void __iounmap(void __iomem * addr);
+
+#define ioremap(cookie,size)		__ioremap(cookie,size,0,1)
+#define ioremap_nocache(cookie,size)	__ioremap(cookie,size,0,1)
+#define iounmap(cookie)			__iounmap(cookie)
+#include <asm-generic/io.h>
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_NDS32_IO_H */
diff --git a/arch/nds32/mm/ioremap.c b/arch/nds32/mm/ioremap.c
new file mode 100644
index 0000000..532e6cf
--- /dev/null
+++ b/arch/nds32/mm/ioremap.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/vmalloc.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <asm/pgtable.h>
+
+void __iomem *__ioremap(unsigned long phys_addr, size_t size,
+			unsigned long flags, unsigned long align)
+{
+	struct vm_struct *area;
+	unsigned long addr, offset, last_addr;
+	pgprot_t prot;
+
+	/* Don't allow wraparound or zero size */
+	last_addr = phys_addr + size - 1;
+	if (!size || last_addr < phys_addr)
+		return NULL;
+
+	/*
+	 * Mappings have to be page-aligned
+	 */
+	offset = phys_addr & ~PAGE_MASK;
+	phys_addr &= PAGE_MASK;
+	size = PAGE_ALIGN(last_addr + 1) - phys_addr;
+
+	/*
+	 * Ok, go for it..
+	 */
+	area = get_vm_area(size, VM_IOREMAP);
+	if (!area)
+		return NULL;
+
+	area->phys_addr = phys_addr;
+	addr = (unsigned long)area->addr;
+	prot = __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D |
+			_PAGE_G | _PAGE_C_DEV);
+	if (ioremap_page_range(addr, addr + size, phys_addr, prot)) {
+		vunmap((void *)addr);
+		return NULL;
+	}
+	return (__force void __iomem *)(offset + (char *)addr);
+
+}
+
+EXPORT_SYMBOL(__ioremap);
+
+void __iounmap(void __iomem * addr)
+{
+	vunmap((void *)(PAGE_MASK & (unsigned long)addr));
+}
+
+EXPORT_SYMBOL(__iounmap);
-- 
1.7.9.5

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

* [PATCH 13/31] nds32: DMA mapping API
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (11 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 12/31] nds32: Device specific operations Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08  9:09   ` Arnd Bergmann
  2017-11-08  5:55 ` [PATCH 14/31] nds32: ELF definitions Greentime Hu
                   ` (19 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/asm/dma-mapping.h |   27 ++
 arch/nds32/kernel/dma.c              |  478 ++++++++++++++++++++++++++++++++++
 2 files changed, 505 insertions(+)
 create mode 100644 arch/nds32/include/asm/dma-mapping.h
 create mode 100644 arch/nds32/kernel/dma.c

diff --git a/arch/nds32/include/asm/dma-mapping.h b/arch/nds32/include/asm/dma-mapping.h
new file mode 100644
index 0000000..63dbeb7
--- /dev/null
+++ b/arch/nds32/include/asm/dma-mapping.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ASMNDS32_DMA_MAPPING_H
+#define ASMNDS32_DMA_MAPPING_H
+
+extern struct dma_map_ops nds32_dma_ops;
+
+static inline struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
+{
+	return &nds32_dma_ops;
+}
+
+#endif
diff --git a/arch/nds32/kernel/dma.c b/arch/nds32/kernel/dma.c
new file mode 100644
index 0000000..939702e
--- /dev/null
+++ b/arch/nds32/kernel/dma.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/export.h>
+#include <linux/string.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/cache.h>
+#include <linux/highmem.h>
+#include <linux/slab.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/dma-mapping.h>
+#include <asm/proc-fns.h>
+
+/*
+ * This is the page table (2MB) covering uncached, DMA consistent allocations
+ */
+static pte_t *consistent_pte;
+static DEFINE_RAW_SPINLOCK(consistent_lock);
+
+/*
+ * VM region handling support.
+ *
+ * This should become something generic, handling VM region allocations for
+ * vmalloc and similar (ioremap, module space, etc).
+ *
+ * I envisage vmalloc()'s supporting vm_struct becoming:
+ *
+ *  struct vm_struct {
+ *    struct vm_region	region;
+ *    unsigned long	flags;
+ *    struct page	**pages;
+ *    unsigned int	nr_pages;
+ *    unsigned long	phys_addr;
+ *  };
+ *
+ * get_vm_area() would then call vm_region_alloc with an appropriate
+ * struct vm_region head (eg):
+ *
+ *  struct vm_region vmalloc_head = {
+ *	.vm_list	= LIST_HEAD_INIT(vmalloc_head.vm_list),
+ *	.vm_start	= VMALLOC_START,
+ *	.vm_end		= VMALLOC_END,
+ *  };
+ *
+ * However, vmalloc_head.vm_start is variable (typically, it is dependent on
+ * the amount of RAM found at boot time.)  I would imagine that get_vm_area()
+ * would have to initialise this each time prior to calling vm_region_alloc().
+ */
+struct arch_vm_region {
+	struct list_head vm_list;
+	unsigned long vm_start;
+	unsigned long vm_end;
+	struct page *vm_pages;
+};
+
+static struct arch_vm_region consistent_head = {
+	.vm_list = LIST_HEAD_INIT(consistent_head.vm_list),
+	.vm_start = CONSISTENT_BASE,
+	.vm_end = CONSISTENT_END,
+};
+
+static struct arch_vm_region *vm_region_alloc(struct arch_vm_region *head,
+					      size_t size, int gfp)
+{
+	unsigned long addr = head->vm_start, end = head->vm_end - size;
+	unsigned long flags;
+	struct arch_vm_region *c, *new;
+
+	new = kmalloc(sizeof(struct arch_vm_region), gfp);
+	if (!new)
+		goto out;
+
+	raw_spin_lock_irqsave(&consistent_lock, flags);
+
+	list_for_each_entry(c, &head->vm_list, vm_list) {
+		if ((addr + size) < addr)
+			goto nospc;
+		if ((addr + size) <= c->vm_start)
+			goto found;
+		addr = c->vm_end;
+		if (addr > end)
+			goto nospc;
+	}
+
+found:
+	/*
+	 * Insert this entry _before_ the one we found.
+	 */
+	list_add_tail(&new->vm_list, &c->vm_list);
+	new->vm_start = addr;
+	new->vm_end = addr + size;
+
+	raw_spin_unlock_irqrestore(&consistent_lock, flags);
+	return new;
+
+nospc:
+	raw_spin_unlock_irqrestore(&consistent_lock, flags);
+	kfree(new);
+out:
+	return NULL;
+}
+
+static struct arch_vm_region *vm_region_find(struct arch_vm_region *head,
+					     unsigned long addr)
+{
+	struct arch_vm_region *c;
+
+	list_for_each_entry(c, &head->vm_list, vm_list) {
+		if (c->vm_start == addr)
+			goto out;
+	}
+	c = NULL;
+out:
+	return c;
+}
+
+/* FIXME: attrs is not used. */
+static void *nds32_dma_alloc_coherent(struct device *dev, size_t size,
+				      dma_addr_t * handle, gfp_t gfp,
+				      unsigned long attrs)
+{
+	struct page *page;
+	struct arch_vm_region *c;
+	unsigned long order;
+	u64 mask = ISA_DMA_THRESHOLD, limit;
+	pgprot_t prot = pgprot_noncached(PAGE_KERNEL);
+
+	if (!consistent_pte) {
+		pr_err("%s: not initialized\n", __func__);
+		dump_stack();
+		return NULL;
+	}
+
+	if (dev) {
+		mask = dev->coherent_dma_mask;
+
+		/*
+		 * Sanity check the DMA mask - it must be non-zero, and
+		 * must be able to be satisfied by a DMA allocation.
+		 */
+		if (mask == 0) {
+			dev_warn(dev, "coherent DMA mask is unset\n");
+			goto no_page;
+		}
+
+		if ((~mask) & ISA_DMA_THRESHOLD) {
+			dev_warn(dev, "coherent DMA mask %#llx is smaller "
+				 "than system GFP_DMA mask %#llx\n",
+				 mask, (unsigned long long)ISA_DMA_THRESHOLD);
+			goto no_page;
+		}
+	}
+
+	/*
+	 * Sanity check the allocation size.
+	 */
+	size = PAGE_ALIGN(size);
+	limit = (mask + 1) & ~mask;
+	if ((limit && size >= limit) ||
+	    size >= (CONSISTENT_END - CONSISTENT_BASE)) {
+		pr_warn("coherent allocation too big "
+			"(requested %#x mask %#llx)\n", size, mask);
+		goto no_page;
+	}
+
+	order = get_order(size);
+
+	if (mask != 0xffffffff)
+		gfp |= GFP_DMA;
+
+	page = alloc_pages(gfp, order);
+	if (!page)
+		goto no_page;
+
+	/*
+	 * Invalidate any data that might be lurking in the
+	 * kernel direct-mapped region for device DMA.
+	 */
+	{
+		unsigned long kaddr = (unsigned long)page_address(page);
+		memset(page_address(page), 0, size);
+		cpu_dma_wbinval_range(kaddr, kaddr + size);
+	}
+
+	/*
+	 * Allocate a virtual address in the consistent mapping region.
+	 */
+	c = vm_region_alloc(&consistent_head, size,
+			    gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
+	if (c) {
+		pte_t *pte = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+		struct page *end = page + (1 << order);
+
+		c->vm_pages = page;
+
+		/*
+		 * Set the "dma handle"
+		 */
+		*handle = page_to_dma(dev, page);
+
+		do {
+			BUG_ON(!pte_none(*pte));
+
+			/*
+			 * x86 does not mark the pages reserved...
+			 */
+			SetPageReserved(page);
+			set_pte(pte, mk_pte(page, prot));
+			page++;
+			pte++;
+		} while (size -= PAGE_SIZE);
+
+		/*
+		 * Free the otherwise unused pages.
+		 */
+		while (page < end) {
+			__free_page(page);
+			page++;
+		}
+
+		return (void *)c->vm_start;
+	}
+
+	if (page)
+		__free_pages(page, order);
+no_page:
+	*handle = ~0;
+	return NULL;
+}
+
+static void nds32_dma_free(struct device *dev, size_t size, void *cpu_addr,
+			   dma_addr_t handle, unsigned long attrs)
+{
+	struct arch_vm_region *c;
+	unsigned long flags, addr;
+	pte_t *ptep;
+
+	size = PAGE_ALIGN(size);
+
+	raw_spin_lock_irqsave(&consistent_lock, flags);
+
+	c = vm_region_find(&consistent_head, (unsigned long)cpu_addr);
+	if (!c)
+		goto no_area;
+
+	if ((c->vm_end - c->vm_start) != size) {
+		pr_err("%s: freeing wrong coherent size (%ld != %d)\n",
+		       __func__, c->vm_end - c->vm_start, size);
+		dump_stack();
+		size = c->vm_end - c->vm_start;
+	}
+
+	ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+	addr = c->vm_start;
+	do {
+		pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep);
+		unsigned long pfn;
+
+		ptep++;
+		addr += PAGE_SIZE;
+
+		if (!pte_none(pte) && pte_present(pte)) {
+			pfn = pte_pfn(pte);
+
+			if (pfn_valid(pfn)) {
+				struct page *page = pfn_to_page(pfn);
+
+				/*
+				 * x86 does not mark the pages reserved...
+				 */
+				ClearPageReserved(page);
+
+				__free_page(page);
+				continue;
+			}
+		}
+
+		pr_crit("%s: bad page in kernel page table\n", __func__);
+	} while (size -= PAGE_SIZE);
+
+	flush_tlb_kernel_range(c->vm_start, c->vm_end);
+
+	list_del(&c->vm_list);
+
+	raw_spin_unlock_irqrestore(&consistent_lock, flags);
+
+	kfree(c);
+	return;
+
+no_area:
+	raw_spin_unlock_irqrestore(&consistent_lock, flags);
+	pr_err("%s: trying to free invalid coherent area: %p\n",
+	       __func__, cpu_addr);
+	dump_stack();
+}
+
+/*
+ * Initialise the consistent memory allocation.
+ */
+static int __init consistent_init(void)
+{
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+	int ret = 0;
+
+	do {
+		pgd = pgd_offset(&init_mm, CONSISTENT_BASE);
+		pmd = pmd_alloc(&init_mm, pgd, CONSISTENT_BASE);
+		if (!pmd) {
+			pr_err("%s: no pmd tables\n", __func__);
+			ret = -ENOMEM;
+			break;
+		}
+		/* The first level mapping may be created in somewhere.
+		 * It's not necessary to warn here. */
+		/* WARN_ON(!pmd_none(*pmd)); */
+
+		pte = pte_alloc_kernel(pmd, CONSISTENT_BASE);
+		if (!pte) {
+			ret = -ENOMEM;
+			break;
+		}
+
+		consistent_pte = pte;
+	} while (0);
+
+	return ret;
+}
+
+core_initcall(consistent_init);
+static void consistent_sync(void *vaddr, size_t size, int direction);
+static dma_addr_t nds32_dma_map_page(struct device *dev, struct page *page,
+				     unsigned long offset, size_t size,
+				     enum dma_data_direction dir,
+				     unsigned long attrs)
+{
+	consistent_sync((void *)(page_address(page) + offset), size, dir);
+	return page_to_phys(page) + offset;
+}
+
+static void nds32_dma_unmap_page(struct device *dev, dma_addr_t handle,
+				 size_t size, enum dma_data_direction dir,
+				 unsigned long attrs)
+{
+	consistent_sync(phys_to_virt(handle), size, dir);
+}
+
+/*
+ * Make an area consistent for devices.
+ */
+static void consistent_sync(void *vaddr, size_t size, int direction)
+{
+	unsigned long start = (unsigned long)vaddr;
+	unsigned long end = start + size;
+
+	switch (direction) {
+	case DMA_FROM_DEVICE:	/* invalidate only */
+		cpu_dma_inval_range(start, end);
+		break;
+	case DMA_TO_DEVICE:	/* writeback only */
+		cpu_dma_wb_range(start, end);
+		break;
+	case DMA_BIDIRECTIONAL:	/* writeback and invalidate */
+		cpu_dma_wbinval_range(start, end);
+		break;
+	default:
+		BUG();
+	}
+}
+
+static int nds32_dma_map_sg(struct device *dev, struct scatterlist *sg,
+			    int nents, enum dma_data_direction dir,
+			    unsigned long attrs)
+{
+	int i;
+
+	for (i = 0; i < nents; i++, sg++) {
+		void *virt;
+		unsigned long pfn;
+		struct page *page = sg_page(sg);
+
+		sg->dma_address = page_to_dma(dev, page) + sg->offset;
+		pfn = page_to_pfn(page) + sg->offset / PAGE_SIZE;
+		page = pfn_to_page(pfn);
+		if (PageHighMem(page)) {
+			virt = kmap_atomic(page);
+			consistent_sync(virt, sg->length, dir);
+			kunmap_atomic(virt);
+		} else {
+			if (sg->offset > PAGE_SIZE)
+				panic("sg->offset:%08x > PAGE_SIZE\n",
+				      sg->offset);
+			virt = page_address(page) + sg->offset;
+			consistent_sync(virt, sg->length, dir);
+		}
+	}
+	return nents;
+}
+
+static void nds32_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+			       int nhwentries, enum dma_data_direction dir,
+			       unsigned long attrs)
+{
+}
+
+static void
+nds32_dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle,
+			      size_t size, enum dma_data_direction dir)
+{
+	consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
+}
+
+static void
+nds32_dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
+				 size_t size, enum dma_data_direction dir)
+{
+	consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
+}
+
+static void
+nds32_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
+			  enum dma_data_direction dir)
+{
+	int i;
+
+	for (i = 0; i < nents; i++, sg++) {
+		char *virt =
+		    page_address((struct page *)sg->page_link) + sg->offset;
+		consistent_sync(virt, sg->length, dir);
+	}
+}
+
+static void
+nds32_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
+			     int nents, enum dma_data_direction dir)
+{
+	int i;
+
+	for (i = 0; i < nents; i++, sg++) {
+		char *virt =
+		    page_address((struct page *)sg->page_link) + sg->offset;
+		consistent_sync(virt, sg->length, dir);
+	}
+}
+
+struct dma_map_ops nds32_dma_ops = {
+	.alloc = nds32_dma_alloc_coherent,
+	.free = nds32_dma_free,
+	.map_page = nds32_dma_map_page,
+	.unmap_page = nds32_dma_unmap_page,
+	.map_sg = nds32_dma_map_sg,
+	.unmap_sg = nds32_dma_unmap_sg,
+	.sync_single_for_device = nds32_dma_sync_single_for_device,
+	.sync_single_for_cpu = nds32_dma_sync_single_for_cpu,
+	.sync_sg_for_cpu = nds32_dma_sync_sg_for_cpu,
+	.sync_sg_for_device = nds32_dma_sync_sg_for_device,
+};
+
+EXPORT_SYMBOL(nds32_dma_ops);
-- 
1.7.9.5

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

* [PATCH 14/31] nds32: ELF definitions
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (12 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 13/31] nds32: DMA mapping API Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08  5:55 ` [PATCH 15/31] nds32: System calls handling Greentime Hu
                   ` (18 subsequent siblings)
  32 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/asm/elf.h         |  192 ++++++++++++++++++++++++++++++++++
 arch/nds32/include/uapi/asm/auxvec.h |   25 +++++
 arch/nds32/include/uapi/asm/param.h  |   24 +++++
 3 files changed, 241 insertions(+)
 create mode 100644 arch/nds32/include/asm/elf.h
 create mode 100644 arch/nds32/include/uapi/asm/auxvec.h
 create mode 100644 arch/nds32/include/uapi/asm/param.h

diff --git a/arch/nds32/include/asm/elf.h b/arch/nds32/include/asm/elf.h
new file mode 100644
index 0000000..a6e4c56
--- /dev/null
+++ b/arch/nds32/include/asm/elf.h
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASMNDS32_ELF_H
+#define __ASMNDS32_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+
+typedef unsigned long elf_greg_t;
+typedef unsigned long elf_freg_t[3];
+
+extern unsigned int elf_hwcap;
+
+#define EM_NDS32			167
+
+#define R_NDS32_NONE			0
+#define R_NDS32_16_RELA			19
+#define R_NDS32_32_RELA			20
+#define R_NDS32_9_PCREL_RELA		22
+#define R_NDS32_15_PCREL_RELA		23
+#define R_NDS32_17_PCREL_RELA		24
+#define R_NDS32_25_PCREL_RELA		25
+#define R_NDS32_HI20_RELA		26
+#define R_NDS32_LO12S3_RELA		27
+#define R_NDS32_LO12S2_RELA		28
+#define R_NDS32_LO12S1_RELA		29
+#define R_NDS32_LO12S0_RELA		30
+#define R_NDS32_SDA15S3_RELA    	31
+#define R_NDS32_SDA15S2_RELA    	32
+#define R_NDS32_SDA15S1_RELA    	33
+#define R_NDS32_SDA15S0_RELA    	34
+#define R_NDS32_GOT20			37
+#define R_NDS32_25_PLTREL		38
+#define R_NDS32_COPY			39
+#define R_NDS32_GLOB_DAT		40
+#define R_NDS32_JMP_SLOT		41
+#define R_NDS32_RELATIVE		42
+#define R_NDS32_GOTOFF			43
+#define R_NDS32_GOTPC20			44
+#define R_NDS32_GOT_HI20		45
+#define R_NDS32_GOT_LO12		46
+#define R_NDS32_GOTPC_HI20		47
+#define R_NDS32_GOTPC_LO12		48
+#define R_NDS32_GOTOFF_HI20		49
+#define R_NDS32_GOTOFF_LO12		50
+#define R_NDS32_INSN16			51
+#define R_NDS32_LABEL			52
+#define R_NDS32_LONGCALL1		53
+#define R_NDS32_LONGCALL2		54
+#define R_NDS32_LONGCALL3		55
+#define R_NDS32_LONGJUMP1		56
+#define R_NDS32_LONGJUMP2		57
+#define R_NDS32_LONGJUMP3		58
+#define R_NDS32_LOADSTORE		59
+#define R_NDS32_9_FIXED_RELA		60
+#define R_NDS32_15_FIXED_RELA		61
+#define R_NDS32_17_FIXED_RELA		62
+#define R_NDS32_25_FIXED_RELA		63
+#define R_NDS32_PLTREL_HI20		64
+#define R_NDS32_PLTREL_LO12		65
+#define R_NDS32_PLT_GOTREL_HI20		66
+#define R_NDS32_PLT_GOTREL_LO12		67
+#define R_NDS32_LO12S0_ORI_RELA		72
+#define R_NDS32_DWARF2_OP1_RELA     	77
+#define R_NDS32_DWARF2_OP2_RELA     	78
+#define R_NDS32_DWARF2_LEB_RELA     	79
+#define R_NDS32_WORD_9_PCREL_RELA	94
+#define R_NDS32_LONGCALL4 		107
+#define R_NDS32_RELA_NOP_MIX		192
+#define R_NDS32_RELA_NOP_MAX		255
+
+#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/* Core file format: The core file is written in such a way that gdb
+   can understand it and provide useful information to the user (under
+   linux we use the 'trad-core' bfd).  There are quite a number of
+   obstacles to being able to view the contents of the floating point
+   registers, and until these are solved you will not be able to view the
+   contents of them.  Actually, you can read in the core file and look at
+   the contents of the user struct to find out what the floating point
+   registers contain.
+   The actual file contents are as follows:
+   UPAGE: 1 page consisting of a user struct that tells gdb what is present
+   in the file.  Directly after this is a copy of the task_struct, which
+   is currently not used by gdb, but it may come in useful at some point.
+   All of the registers are stored as part of the upage.  The upage should
+   always be only one page.
+   DATA: The data area is stored.  We use current->end_text to
+   current->brk to pick up all of the user variables, plus any memory
+   that may have been malloced.  No attempt is made to determine if a page
+   is demand-zero or if a page is totally unused, we just cover the entire
+   range.  All of the addresses are rounded in such a way that an integral
+   number of pages is written.
+   STACK: We need the stack information in order to get a meaningful
+   backtrace.  We need to write the data from (esp) to
+   current->start_stack, so we round each of these off in order to be able
+   to write an integer number of pages.
+   The minimum core file size is 3 pages, or 12288 bytes.
+*/
+
+struct user_fp {
+	struct fp_reg {
+		unsigned int sign1:1;
+		unsigned int unused:15;
+		unsigned int sign2:1;
+		unsigned int exponent:14;
+		unsigned int j:1;
+		unsigned int mantissa1:31;
+		unsigned int mantissa0:32;
+	} fpregs[8];
+	unsigned int fpsr:32;
+	unsigned int fpcr:32;
+	unsigned char ftype[8];
+	unsigned int init_flag;
+};
+
+typedef struct user_fp elf_fpregset_t;
+
+struct elf32_hdr;
+#define elf_check_arch(x)		((x)->e_machine == EM_NDS32)
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS32
+#ifdef __NDS32_EB__
+#define ELF_DATA	ELFDATA2MSB;
+#else
+#define ELF_DATA	ELFDATA2LSB;
+#endif
+#define ELF_ARCH	EM_NDS32
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE	PAGE_SIZE
+
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+   use of this is to invoke "./ld.so someprog" to test out a new version of
+   the loader.  We need to make sure that it is out of the way of the program
+   that it will "exec", and that there is sufficient room for the brk.  */
+
+#define ELF_ET_DYN_BASE	(2 * TASK_SIZE / 3)
+
+/* When the program starts, a1 contains a pointer to a function to be
+   registered with atexit, as per the SVR4 ABI.  A value of 0 means we
+   have no such handler.  */
+#define ELF_PLAT_INIT(_r, load_addr)	(_r)->uregs[0] = 0
+
+/* This yields a mask that user programs can use to figure out what
+   instruction set this cpu supports. */
+
+#define ELF_HWCAP	(elf_hwcap)
+
+#ifdef __KERNEL__
+
+#define ELF_PLATFORM    (NULL)
+
+/* Old NetWinder binaries were compiled in such a way that the iBCS
+   heuristic always trips on them.  Until these binaries become uncommon
+   enough not to care, don't trust the `ibcs' flag here.  In any case
+   there is no other ELF system currently supported by iBCS.
+   @@ Could print a warning message to encourage users to upgrade.  */
+#define SET_PERSONALITY(ex)	set_personality(PER_LINUX)
+
+#endif
+
+#define ARCH_DLINFO						\
+do {								\
+	NEW_AUX_ENT(AT_SYSINFO_EHDR,				\
+		    (elf_addr_t)current->mm->context.vdso);	\
+} while (0)
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+struct linux_binprm;
+int arch_setup_additional_pages(struct linux_binprm *, int);
+
+#endif
diff --git a/arch/nds32/include/uapi/asm/auxvec.h b/arch/nds32/include/uapi/asm/auxvec.h
new file mode 100644
index 0000000..02e9757
--- /dev/null
+++ b/arch/nds32/include/uapi/asm/auxvec.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_AUXVEC_H
+#define __ASM_AUXVEC_H
+
+/* VDSO location */
+#define AT_SYSINFO_EHDR	33
+
+#define AT_VECTOR_SIZE_ARCH 1
+
+#endif
diff --git a/arch/nds32/include/uapi/asm/param.h b/arch/nds32/include/uapi/asm/param.h
new file mode 100644
index 0000000..2e4527f3
--- /dev/null
+++ b/arch/nds32/include/uapi/asm/param.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_NDS32_PARAM_H
+#define __ASM_NDS32_PARAM_H
+
+#define EXEC_PAGESIZE	8192
+
+#include <asm-generic/param.h>
+
+#endif /* __ASM_NDS32_PARAM_H */
-- 
1.7.9.5

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

* [PATCH 15/31] nds32: System calls handling
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (13 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 14/31] nds32: ELF definitions Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08  9:30   ` Arnd Bergmann
  2017-11-08  5:55 ` [PATCH 16/31] nds32: VDSO support Greentime Hu
                   ` (17 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/asm/syscall.h     |  203 ++++++++++++++++++++++++++++++++++
 arch/nds32/include/asm/syscalls.h    |   27 +++++
 arch/nds32/include/asm/unistd.h      |   21 ++++
 arch/nds32/include/uapi/asm/unistd.h |   36 ++++++
 arch/nds32/kernel/ex-scall.S         |  146 ++++++++++++++++++++++++
 arch/nds32/kernel/sys_nds32.c        |   63 +++++++++++
 arch/nds32/kernel/syscall_table.c    |   28 +++++
 7 files changed, 524 insertions(+)
 create mode 100644 arch/nds32/include/asm/syscall.h
 create mode 100644 arch/nds32/include/asm/syscalls.h
 create mode 100644 arch/nds32/include/asm/unistd.h
 create mode 100644 arch/nds32/include/uapi/asm/unistd.h
 create mode 100644 arch/nds32/kernel/ex-scall.S
 create mode 100644 arch/nds32/kernel/sys_nds32.c
 create mode 100644 arch/nds32/kernel/syscall_table.c

diff --git a/arch/nds32/include/asm/syscall.h b/arch/nds32/include/asm/syscall.h
new file mode 100644
index 0000000..3066bae
--- /dev/null
+++ b/arch/nds32/include/asm/syscall.h
@@ -0,0 +1,203 @@
+/*
+ * Access to user system call parameters and results
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU General Public License v.2.
+ *
+ * This file is a stub providing documentation for what functions
+ * asm-ARCH/syscall.h files need to define.  Most arch definitions
+ * will be simple inlines.
+ *
+ * All of these functions expect to be called with no locks,
+ * and only when the caller is sure that the task of interest
+ * cannot return to user mode while we are looking at it.
+ */
+
+#ifndef _ASM_NDS32_SYSCALL_H
+#define _ASM_NDS32_SYSCALL_H	1
+
+#include <linux/err.h>
+struct task_struct;
+struct pt_regs;
+
+/**
+ * syscall_get_nr - find what system call a task is executing
+ * @task:	task of interest, must be blocked
+ * @regs:	task_pt_regs() of @task
+ *
+ * If @task is executing a system call or is at system call
+ * tracing about to attempt one, returns the system call number.
+ * If @task is not executing a system call, i.e. it's blocked
+ * inside the kernel for a fault or signal, returns -1.
+ *
+ * Note this returns int even on 64-bit machines.  Only 32 bits of
+ * system call number can be meaningful.  If the actual arch value
+ * is 64 bits, this truncates to 32 bits so 0xffffffff means -1.
+ *
+ * It's only valid to call this when @task is known to be blocked.
+ */
+int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
+{
+	return regs->syscallno;
+}
+
+/**
+ * syscall_rollback - roll back registers after an aborted system call
+ * @task:	task of interest, must be in system call exit tracing
+ * @regs:	task_pt_regs() of @task
+ *
+ * It's only valid to call this when @task is stopped for system
+ * call exit tracing (due to TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT),
+ * after tracehook_report_syscall_entry() returned nonzero to prevent
+ * the system call from taking place.
+ *
+ * This rolls back the register state in @regs so it's as if the
+ * system call instruction was a no-op.  The registers containing
+ * the system call number and arguments are as they were before the
+ * system call instruction.  This may not be the same as what the
+ * register state looked like at system call entry tracing.
+ */
+void syscall_rollback(struct task_struct *task, struct pt_regs *regs)
+{
+	regs->uregs[0] = regs->orig_r0;
+}
+
+/**
+ * syscall_get_error - check result of traced system call
+ * @task:	task of interest, must be blocked
+ * @regs:	task_pt_regs() of @task
+ *
+ * Returns 0 if the system call succeeded, or -ERRORCODE if it failed.
+ *
+ * It's only valid to call this when @task is stopped for tracing on exit
+ * from a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
+ */
+long syscall_get_error(struct task_struct *task, struct pt_regs *regs)
+{
+	unsigned long error = regs->uregs[0];
+	return IS_ERR_VALUE(error) ? error : 0;
+}
+
+/**
+ * syscall_get_return_value - get the return value of a traced system call
+ * @task:	task of interest, must be blocked
+ * @regs:	task_pt_regs() of @task
+ *
+ * Returns the return value of the successful system call.
+ * This value is meaningless if syscall_get_error() returned nonzero.
+ *
+ * It's only valid to call this when @task is stopped for tracing on exit
+ * from a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
+ */
+long syscall_get_return_value(struct task_struct *task, struct pt_regs *regs)
+{
+	return regs->uregs[0];
+}
+
+/**
+ * syscall_set_return_value - change the return value of a traced system call
+ * @task:	task of interest, must be blocked
+ * @regs:	task_pt_regs() of @task
+ * @error:	negative error code, or zero to indicate success
+ * @val:	user return value if @error is zero
+ *
+ * This changes the results of the system call that user mode will see.
+ * If @error is zero, the user sees a successful system call with a
+ * return value of @val.  If @error is nonzero, it's a negated errno
+ * code; the user sees a failed system call with this errno code.
+ *
+ * It's only valid to call this when @task is stopped for tracing on exit
+ * from a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
+ */
+void syscall_set_return_value(struct task_struct *task, struct pt_regs *regs,
+			      int error, long val)
+{
+	regs->uregs[0] = (long)error ? error : val;
+}
+
+/**
+ * syscall_get_arguments - extract system call parameter values
+ * @task:	task of interest, must be blocked
+ * @regs:	task_pt_regs() of @task
+ * @i:		argument index [0,5]
+ * @n:		number of arguments; n+i must be [1,6].
+ * @args:	array filled with argument values
+ *
+ * Fetches @n arguments to the system call starting with the @i'th argument
+ * (from 0 through 5).  Argument @i is stored in @args[0], and so on.
+ * An arch inline version is probably optimal when @i and @n are constants.
+ *
+ * It's only valid to call this when @task is stopped for tracing on
+ * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
+ * It's invalid to call this with @i + @n > 6; we only support system calls
+ * taking up to 6 arguments.
+ */
+#define SYSCALL_MAX_ARGS 6
+void syscall_get_arguments(struct task_struct *task, struct pt_regs *regs,
+			   unsigned int i, unsigned int n, unsigned long *args)
+{
+	if (n == 0)
+		return;
+	if (i + n > SYSCALL_MAX_ARGS) {
+		unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i;
+		unsigned int n_bad = n + i - SYSCALL_MAX_ARGS;
+		pr_warning("%s called with max args %d, handling only %d\n",
+			   __func__, i + n, SYSCALL_MAX_ARGS);
+		memset(args_bad, 0, n_bad * sizeof(args[0]));
+		memset(args_bad, 0, n_bad * sizeof(args[0]));
+	}
+
+	if (i == 0) {
+		args[0] = regs->orig_r0;
+		args++;
+		i++;
+		n--;
+	}
+
+	memcpy(args, &regs->uregs[0] + i, n * sizeof(args[0]));
+}
+
+/**
+ * syscall_set_arguments - change system call parameter value
+ * @task:	task of interest, must be in system call entry tracing
+ * @regs:	task_pt_regs() of @task
+ * @i:		argument index [0,5]
+ * @n:		number of arguments; n+i must be [1,6].
+ * @args:	array of argument values to store
+ *
+ * Changes @n arguments to the system call starting with the @i'th argument.
+ * Argument @i gets value @args[0], and so on.
+ * An arch inline version is probably optimal when @i and @n are constants.
+ *
+ * It's only valid to call this when @task is stopped for tracing on
+ * entry to a system call, due to %TIF_SYSCALL_TRACE or %TIF_SYSCALL_AUDIT.
+ * It's invalid to call this with @i + @n > 6; we only support system calls
+ * taking up to 6 arguments.
+ */
+void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs,
+			   unsigned int i, unsigned int n,
+			   const unsigned long *args)
+{
+	if (n == 0)
+		return;
+
+	if (i + n > SYSCALL_MAX_ARGS) {
+		pr_warn("%s called with max args %d, handling only %d\n",
+			__func__, i + n, SYSCALL_MAX_ARGS);
+		n = SYSCALL_MAX_ARGS - i;
+	}
+
+	if (i == 0) {
+		regs->orig_r0 = args[0];
+		args++;
+		i++;
+		n--;
+	}
+
+	memcpy(&regs->uregs[0] + i, args, n * sizeof(args[0]));
+}
+#endif /* _ASM_NDS32_SYSCALL_H */
diff --git a/arch/nds32/include/asm/syscalls.h b/arch/nds32/include/asm/syscalls.h
new file mode 100644
index 0000000..741ccdc
--- /dev/null
+++ b/arch/nds32/include/asm/syscalls.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_NDS32_SYSCALLS_H
+#define __ASM_NDS32_SYSCALLS_H
+
+int sys_cacheflush(unsigned long addr, unsigned long len, unsigned int op);
+long sys_fadvise64_64_wrapper(int fd, int advice, loff_t offset, loff_t len);
+asmlinkage int sys_syscall(void);
+asmlinkage int sys_rt_sigreturn_wrapper(void);
+
+#include <asm-generic/syscalls.h>
+
+#endif /* __ASM_NDS32_SYSCALLS_H */
diff --git a/arch/nds32/include/asm/unistd.h b/arch/nds32/include/asm/unistd.h
new file mode 100644
index 0000000..b30adca
--- /dev/null
+++ b/arch/nds32/include/asm/unistd.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define __ARCH_WANT_SYS_LLSEEK
+#define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_OLD_MMAP
+
+#include <uapi/asm/unistd.h>
diff --git a/arch/nds32/include/uapi/asm/unistd.h b/arch/nds32/include/uapi/asm/unistd.h
new file mode 100644
index 0000000..01b466d
--- /dev/null
+++ b/arch/nds32/include/uapi/asm/unistd.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define __ARCH_WANT_RENAMEAT
+#define __ARCH_WANT_SYSCALL_OFF_T
+
+/* Use the standard ABI for syscalls */
+#include <asm-generic/unistd.h>
+
+/* Additional NDS32 specific syscalls. */
+#define __NR_cacheflush		(__NR_arch_specific_syscall)
+#define __NR_syscall		(__NR_arch_specific_syscall + 1)
+#define __NR_ipc		(__NR_arch_specific_syscall + 2)
+#define __NR_sysfs		(__NR_arch_specific_syscall + 3)
+#define __NR__llseek             __NR_llseek
+__SYSCALL(__NR_cacheflush, sys_cacheflush)
+__SYSCALL(__NR_syscall, sys_syscall)
+__SYSCALL(__NR_ipc, sys_ipc)
+__SYSCALL(__NR_sysfs, sys_sysfs)
+
+__SYSCALL(__NR_fadvise64_64, sys_fadvise64_64_wrapper)
+__SYSCALL(__NR_rt_sigreturn, sys_rt_sigreturn_wrapper)
+__SYSCALL(__NR_mmap, sys_old_mmap)
diff --git a/arch/nds32/kernel/ex-scall.S b/arch/nds32/kernel/ex-scall.S
new file mode 100644
index 0000000..52691ce
--- /dev/null
+++ b/arch/nds32/kernel/ex-scall.S
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <asm/unistd.h>
+#include <asm/assembler.h>
+#include <asm/nds32.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/current.h>
+
+/*
+ * $r0 = previous task_struct,
+ * $r1 = next task_struct,
+ * previous and next are guaranteed not to be the same.
+ */
+
+ENTRY(__switch_to)
+
+	la	$p0, __entry_task
+	sw	$r1, [$p0]
+	move	$p1, $r0
+	addi	$p1, $p1, #THREAD_CPU_CONTEXT
+	smw.bi 	$r6, [$p1], $r14, #0xb		! push r6~r14, fp, lp, sp
+	move	$r25, $r1
+	addi	$r1, $r1, #THREAD_CPU_CONTEXT
+	lmw.bi 	$r6, [$r1], $r14, #0xb		! pop r6~r14, fp, lp, sp
+	ret
+
+/*
+ * These are the registers used in the syscall handler, and allow us
+ * to have in theory up to 6 arguments to a function - $r0 to $r5.
+ *
+ * We must set at least "tsk" and "tbl" when calling ret_with_reschedule.
+ */
+#define tbl	$r8            //  syscall table pointer
+
+/*
+ * $r7 will be writen as syscall nr
+ * by retrieving from $ITYPE 'SWID' bitfiled
+ */
+	.macro	get_scno
+	mfsr	$r7, $ITYPE
+	srli	$r7, $r7, #ITYPE_offSWID
+	swi	$r7, [$sp + SYSCALLNO_OFFSET]
+	.endm
+
+	.macro	updateipc
+	addi	$r17, $r13, #4				! $r13 is $IPC
+	swi	$r17, [$sp + IPC_OFFSET]
+	.endm
+
+ENTRY(eh_syscall)
+	updateipc
+
+	get_scno
+	gie_enable
+
+ENTRY(eh_syscall_phase_2)
+	lwi	$p0, [tsk+#TSK_TI_FLAGS]		! check for syscall tracing
+
+	andi	$p1, $p0, #_TIF_WORK_SYSCALL_ENTRY	! are we tracing syscalls?
+	bnez	$p1, __sys_trace
+
+	la	$lp, ret_fast_syscall		! return address
+jmp_systbl:
+	addi	$p1, $r7, #-__NR_syscalls	! syscall number of syscall instruction is guarded by addembler
+	bgez	$p1, _SCNO_EXCEED		! call sys_* routine
+	la	tbl, sys_call_table		! load syscall table pointer
+	slli	$p1, $r7, #2
+	add	$p1, tbl, $p1
+	lwi	$p1, [$p1]
+	jr	$p1				! no return
+
+_SCNO_EXCEED:
+	ori	$r0, $r7, #0
+        ori	$r1, $sp, #0
+	b	bad_syscall
+
+/*
+ * This is the really slow path.  We're going to be doing
+ * context switches, and waiting for our parent to respond.
+ */
+__sys_trace:
+	move	$r1, $sp
+	move	$r0, $r7			! trace entry [IP = 0]
+	bal	syscall_trace_enter
+	move	$r7, $r0
+	la	$lp, __sys_trace_return		! return address
+
+	addi    $p1, $r7, #1
+	beqz    $p1, ret_slow_syscall		! fatal signal is pending
+
+	addi	$p1, $sp, #R0_OFFSET		! pointer to regs
+	lmw.bi	$r0, [$p1], $r5			! have to reload $r0 - $r5
+	b	jmp_systbl
+
+__sys_trace_return:
+	swi	$r0, [$sp+#R0_OFFSET]		! T: save returned $r0
+	move	$r0, $sp			! set pt_regs for syscall_trace_leave
+	bal	syscall_trace_leave
+	b	ret_slow_syscall
+
+/*
+ * Special system call wrappers
+ *
+ * $r0 = syscall number
+ * $r8 = syscall table
+ */
+       .type   sys_syscall, #function
+ENTRY(sys_syscall)
+	addi	$p1, $r0, #-__NR_syscalls
+	bgtz	$p1, 3f
+	move	$p1, $r0
+	move	$r0, $r1
+	move	$r1, $r2
+	move	$r2, $r3
+	move	$r3, $r4
+	move	$r4, $r5
+! add for syscall 6 args
+	lwi	$r5, [$sp + #SP_OFFSET ]
+	lwi	$r5, [$r5]
+! ~add for syscall 6 args
+
+	lw	$p1, [tbl+$p1<<2]
+	jr	$p1
+3:	b	sys_ni_syscall
+ENDPROC(sys_syscall)
+
+ENTRY(sys_rt_sigreturn_wrapper)
+	addi	$r0, $sp, #0
+	b	sys_rt_sigreturn
+ENDPROC(sys_rt_sigreturn_wrapper)
diff --git a/arch/nds32/kernel/sys_nds32.c b/arch/nds32/kernel/sys_nds32.c
new file mode 100644
index 0000000..39110fe
--- /dev/null
+++ b/arch/nds32/kernel/sys_nds32.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/syscalls.h>
+
+#include <asm/uaccess.h>
+#include <asm/cachectl.h>
+#include <asm/proc-fns.h>
+
+long sys_mmap2(unsigned long addr, unsigned long len,
+	       unsigned long prot, unsigned long flags,
+	       unsigned long fd, unsigned long pgoff)
+{
+	if (pgoff & (~PAGE_MASK >> 12))
+		return -EINVAL;
+
+	return sys_mmap_pgoff(addr, len, prot, flags, fd,
+			      pgoff >> (PAGE_SHIFT - 12));
+}
+
+asmlinkage long sys_fadvise64_64_wrapper(int fd, int advice, loff_t offset,
+					 loff_t len)
+{
+	return sys_fadvise64_64(fd, offset, len, advice);
+}
+
+int sys_cacheflush(unsigned int start, unsigned int end, int cache)
+{
+	struct vm_area_struct *vma;
+	bool flushi = true, wbd = true;
+
+	vma = find_vma(current->mm, start);
+	if (!vma)
+		return -EFAULT;
+	switch (cache) {
+	case ICACHE:
+		wbd = false;
+		break;
+	case DCACHE:
+		flushi = false;
+		break;
+	case BCACHE:
+		break;
+	default:
+		return -EINVAL;
+	}
+	cpu_cache_wbinval_range_check(vma, start, end, flushi, wbd);
+
+	return 0;
+}
diff --git a/arch/nds32/kernel/syscall_table.c b/arch/nds32/kernel/syscall_table.c
new file mode 100644
index 0000000..bafd896
--- /dev/null
+++ b/arch/nds32/kernel/syscall_table.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/syscalls.h>
+#include <linux/signal.h>
+#include <linux/unistd.h>
+#include <asm/syscalls.h>
+
+#undef __SYSCALL
+#define __SYSCALL(nr, call) [nr] = (call),
+
+void *sys_call_table[__NR_syscalls] __aligned(8192) = {
+	[0 ... __NR_syscalls - 1] = sys_ni_syscall,
+#include <asm/unistd.h>
+};
-- 
1.7.9.5

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

* [PATCH 16/31] nds32: VDSO support
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (14 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 15/31] nds32: System calls handling Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08  9:37   ` Arnd Bergmann
  2017-11-08  5:55 ` [PATCH 17/31] nds32: Signal handling support Greentime Hu
                   ` (16 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/asm/vdso.h              |   35 ++++
 arch/nds32/include/asm/vdso_datapage.h     |   51 ++++++
 arch/nds32/kernel/vdso.c                   |  243 ++++++++++++++++++++++++++
 arch/nds32/kernel/vdso/Makefile            |   82 +++++++++
 arch/nds32/kernel/vdso/datapage.S          |   34 ++++
 arch/nds32/kernel/vdso/gen_vdso_offsets.sh |   15 ++
 arch/nds32/kernel/vdso/gettimeofday.c      |  260 ++++++++++++++++++++++++++++
 arch/nds32/kernel/vdso/note.S              |   29 ++++
 arch/nds32/kernel/vdso/sigreturn.S         |   32 ++++
 arch/nds32/kernel/vdso/vdso.S              |   33 ++++
 arch/nds32/kernel/vdso/vdso.lds.S          |   87 ++++++++++
 11 files changed, 901 insertions(+)
 create mode 100644 arch/nds32/include/asm/vdso.h
 create mode 100644 arch/nds32/include/asm/vdso_datapage.h
 create mode 100644 arch/nds32/kernel/vdso.c
 create mode 100644 arch/nds32/kernel/vdso/Makefile
 create mode 100644 arch/nds32/kernel/vdso/datapage.S
 create mode 100755 arch/nds32/kernel/vdso/gen_vdso_offsets.sh
 create mode 100644 arch/nds32/kernel/vdso/gettimeofday.c
 create mode 100644 arch/nds32/kernel/vdso/note.S
 create mode 100644 arch/nds32/kernel/vdso/sigreturn.S
 create mode 100644 arch/nds32/kernel/vdso/vdso.S
 create mode 100644 arch/nds32/kernel/vdso/vdso.lds.S

diff --git a/arch/nds32/include/asm/vdso.h b/arch/nds32/include/asm/vdso.h
new file mode 100644
index 0000000..7298c49
--- /dev/null
+++ b/arch/nds32/include/asm/vdso.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_VDSO_H
+#define __ASM_VDSO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+#include <generated/vdso-offsets.h>
+
+#define VDSO_SYMBOL(base, name)						   \
+({									   \
+	(unsigned long)(vdso_offset_##name + (unsigned long)(base)); \
+})
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_VDSO_H */
diff --git a/arch/nds32/include/asm/vdso_datapage.h b/arch/nds32/include/asm/vdso_datapage.h
new file mode 100644
index 0000000..ffae33c
--- /dev/null
+++ b/arch/nds32/include/asm/vdso_datapage.h
@@ -0,0 +1,51 @@
+/*
+ * Adapted from arm64 version.
+ *
+ * Copyright (C) 2012 ARM Limited
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_VDSO_DATAPAGE_H
+#define __ASM_VDSO_DATAPAGE_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+struct vdso_data {
+	bool cycle_count_down;	/* timer cyclye counter is decrease with time */
+	u32 cycle_count_offset;	/* offset of timer cycle counter register */
+	u32 seq_count;		/* sequence count - odd during updates */
+	u32 xtime_coarse_sec;	/* coarse time */
+	u32 xtime_coarse_nsec;
+
+	u32 wtm_clock_sec;	/* wall to monotonic offset */
+	u32 wtm_clock_nsec;
+	u32 xtime_clock_sec;	/* CLOCK_REALTIME - seconds */
+	u32 cs_mult;		/* clocksource multiplier */
+	u32 cs_shift;		/* Cycle to nanosecond divisor (power of two) */
+
+	u64 cs_cycle_last;	/* last cycle value */
+	u64 cs_mask;		/* clocksource mask */
+
+	u64 xtime_clock_nsec;	/* CLOCK_REALTIME sub-ns base */
+	u32 tz_minuteswest;	/* timezone info for gettimeofday(2) */
+	u32 tz_dsttime;
+};
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_VDSO_DATAPAGE_H */
diff --git a/arch/nds32/kernel/vdso.c b/arch/nds32/kernel/vdso.c
new file mode 100644
index 0000000..d7ef70c
--- /dev/null
+++ b/arch/nds32/kernel/vdso.c
@@ -0,0 +1,243 @@
+/*
+ * VDSO implementation for AArch64 and vector page setup for AArch32.
+ *
+ * Copyright (C) 2012 ARM Limited
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#include <linux/cache.h>
+#include <linux/clocksource.h>
+#include <linux/elf.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/gfp.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/timekeeper_internal.h>
+#include <linux/vmalloc.h>
+
+#include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <asm/cacheflush.h>
+#include <asm/vdso.h>
+#include <asm/vdso_datapage.h>
+#include <linux/random.h>
+#include <asm/cache_info.h>
+extern struct cache_info L1_cache_info[2];
+extern char vdso_start, vdso_end;
+static unsigned long vdso_pages __ro_after_init;
+struct resource timer_res;
+
+/*
+ * The vDSO data page.
+ */
+static struct page *no_pages[] = { NULL };
+
+static union {
+	struct vdso_data data;
+	u8 page[PAGE_SIZE];
+} vdso_data_store __page_aligned_data;
+struct vdso_data *vdso_data = &vdso_data_store.data;
+static struct vm_special_mapping vdso_spec[2] __ro_after_init = {
+	{
+	 .name = "[vvar]",
+	 .pages = no_pages,
+	 },
+	{
+	 .name = "[vdso]",
+	 },
+};
+
+static int grab_timer_node_info(void)
+{
+	struct device_node *timer_node;
+
+	timer_node = of_find_node_by_name(NULL, "timer");
+	of_property_read_u32(timer_node, "cycle-count-offset",
+			     &vdso_data->cycle_count_offset);
+	vdso_data->cycle_count_down =
+	    of_property_read_bool(timer_node, "cycle-count-down");
+	return of_address_to_resource(timer_node, 0, &timer_res);
+}
+
+static int __init vdso_init(void)
+{
+	int i;
+	struct page **vdso_pagelist;
+
+	if (memcmp(&vdso_start, "\177ELF", 4)) {
+		pr_err("vDSO is not a valid ELF object!\n");
+		return -EINVAL;
+	}
+	/* Creat a timer io mapping to get clock cycles counter */
+	if (grab_timer_node_info())
+		return -ENODEV;
+
+	vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT;
+	pr_info("vdso: %ld pages (%ld code @ %p, %ld data @ %p)\n",
+		vdso_pages + 1, vdso_pages, &vdso_start, 1L, vdso_data);
+
+	/* Allocate the vDSO pagelist */
+	vdso_pagelist = kcalloc(vdso_pages, sizeof(struct page *), GFP_KERNEL);
+	if (vdso_pagelist == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < vdso_pages; i++)
+		vdso_pagelist[i] = virt_to_page(&vdso_start + i * PAGE_SIZE);
+	vdso_spec[1].pages = &vdso_pagelist[0];
+
+	return 0;
+}
+
+arch_initcall(vdso_init);
+
+unsigned long inline vdso_random_addr(unsigned long vdso_mapping_len)
+{
+	unsigned long start = current->mm->mmap_base, end, offset, addr;
+	start = PAGE_ALIGN(start);
+
+	/* Round the lowest possible end address up to a PMD boundary. */
+	end = (start + vdso_mapping_len + PMD_SIZE - 1) & PMD_MASK;
+	if (end >= TASK_SIZE)
+		end = TASK_SIZE;
+	end -= vdso_mapping_len;
+
+	if (end > start) {
+		offset = get_random_int() % (((end - start) >> PAGE_SHIFT) + 1);
+		addr = start + (offset << PAGE_SHIFT);
+	} else {
+		addr = start;
+	}
+	return addr;
+}
+
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+	struct mm_struct *mm = current->mm;
+	unsigned long vdso_base, vdso_text_len, vdso_mapping_len;
+	struct vm_area_struct *vma;
+	unsigned long addr = 0;
+	pgprot_t prot;
+	int ret;
+
+	vdso_text_len = vdso_pages << PAGE_SHIFT;
+	/* Be sure to map the data page */
+	vdso_mapping_len = vdso_text_len + 2 * PAGE_SIZE;
+#ifndef CONFIG_CPU_CACHE_NONALIASING
+	vdso_mapping_len += L1_cache_info[DCACHE].aliasing_num - 1;
+#endif
+
+	if (down_write_killable(&mm->mmap_sem))
+		return -EINTR;
+
+	addr = vdso_random_addr(vdso_mapping_len);
+	vdso_base = get_unmapped_area(NULL, addr, vdso_mapping_len, 0, 0);
+	if (IS_ERR_VALUE(vdso_base)) {
+		ret = vdso_base;
+		goto up_fail;
+	}
+#ifndef CONFIG_CPU_CACHE_NONALIASING
+	{
+		unsigned int aliasing_mask =
+		    L1_cache_info[DCACHE].aliasing_mask;
+		unsigned int page_colour_ofs;
+		page_colour_ofs = ((unsigned int)vdso_data & aliasing_mask) -
+		    (vdso_base & aliasing_mask);
+		vdso_base += page_colour_ofs & aliasing_mask;
+	}
+#endif
+	vma = _install_special_mapping(mm, vdso_base, 2 * PAGE_SIZE,
+				       VM_READ | VM_MAYREAD, &vdso_spec[0]);
+	if (IS_ERR(vma)) {
+		ret = PTR_ERR(vma);
+		goto up_fail;
+	}
+
+	/*Map vdata to user space */
+	ret = io_remap_pfn_range(vma, vdso_base,
+				 virt_to_phys(vdso_data) >> PAGE_SHIFT,
+				 PAGE_SIZE, vma->vm_page_prot);
+	if (ret)
+		goto up_fail;
+
+	/*Map timer to user space */
+	vdso_base += PAGE_SIZE;
+	prot = __pgprot(_PAGE_V | _PAGE_M_UR_KR | _PAGE_D |
+			_PAGE_G | _PAGE_C_DEV);
+	ret = io_remap_pfn_range(vma, vdso_base, timer_res.start >> PAGE_SHIFT,
+				 PAGE_SIZE, prot);
+	if (ret)
+		goto up_fail;
+
+	/*Map vdso to user space */
+	vdso_base += PAGE_SIZE;
+	mm->context.vdso = (void *)vdso_base;
+	vma = _install_special_mapping(mm, vdso_base, vdso_text_len,
+				       VM_READ | VM_EXEC |
+				       VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
+				       &vdso_spec[1]);
+	if (IS_ERR(vma)) {
+		ret = PTR_ERR(vma);
+		goto up_fail;
+	}
+
+	up_write(&mm->mmap_sem);
+	return 0;
+
+up_fail:
+	mm->context.vdso = NULL;
+	up_write(&mm->mmap_sem);
+	return ret;
+}
+
+static void vdso_write_begin(struct vdso_data *vdata)
+{
+	++vdso_data->seq_count;
+	smp_wmb();		/* Pairs with smp_rmb in vdso_read_retry */
+}
+
+static void vdso_write_end(struct vdso_data *vdata)
+{
+	smp_wmb();		/* Pairs with smp_rmb in vdso_read_begin */
+	++vdso_data->seq_count;
+}
+
+void update_vsyscall(struct timekeeper *tk)
+{
+	vdso_write_begin(vdso_data);
+	vdso_data->cs_mask = tk->tkr_mono.mask;
+	vdso_data->cs_mult = tk->tkr_mono.mult;
+	vdso_data->cs_shift = tk->tkr_mono.shift;
+	vdso_data->cs_cycle_last = tk->tkr_mono.cycle_last;
+	vdso_data->wtm_clock_sec = tk->wall_to_monotonic.tv_sec;
+	vdso_data->wtm_clock_nsec = tk->wall_to_monotonic.tv_nsec;
+	vdso_data->xtime_clock_sec = tk->xtime_sec;
+	vdso_data->xtime_clock_nsec = tk->tkr_mono.xtime_nsec;
+	vdso_data->xtime_coarse_sec = tk->xtime_sec;
+	vdso_data->xtime_coarse_nsec = tk->tkr_mono.xtime_nsec >>
+	    tk->tkr_mono.shift;
+	vdso_write_end(vdso_data);
+}
+
+void update_vsyscall_tz(void)
+{
+	vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
+	vdso_data->tz_dsttime = sys_tz.tz_dsttime;
+}
diff --git a/arch/nds32/kernel/vdso/Makefile b/arch/nds32/kernel/vdso/Makefile
new file mode 100644
index 0000000..e6c50a7
--- /dev/null
+++ b/arch/nds32/kernel/vdso/Makefile
@@ -0,0 +1,82 @@
+#
+# Building a vDSO image for AArch64.
+#
+# Author: Will Deacon <will.deacon@arm.com>
+# Heavily based on the vDSO Makefiles for other archs.
+#
+
+obj-vdso := note.o datapage.o sigreturn.o gettimeofday.o
+
+# Build rules
+targets := $(obj-vdso) vdso.so vdso.so.dbg
+obj-vdso := $(addprefix $(obj)/, $(obj-vdso))
+
+ccflags-y := -shared -fno-common -fno-builtin
+ccflags-y += -nostdlib -Wl,-soname=linux-vdso.so.1 \
+		$(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+ccflags-y += -fPIC -Wl,-shared -g
+
+# Disable gcov profiling for VDSO code
+GCOV_PROFILE := n
+
+
+obj-y += vdso.o
+extra-y += vdso.lds
+CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
+
+# Force dependency
+$(obj)/vdso.o : $(obj)/vdso.so
+
+# Link rule for the .so file, .lds has to be first
+$(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso)
+	$(call if_changed,vdsold)
+
+
+# Strip rule for the .so file
+$(obj)/%.so: OBJCOPYFLAGS := -S
+$(obj)/%.so: $(obj)/%.so.dbg FORCE
+	$(call if_changed,objcopy)
+
+# Generate VDSO offsets using helper script
+gen-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh
+quiet_cmd_vdsosym = VDSOSYM $@
+define cmd_vdsosym
+	$(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@
+endef
+
+include/generated/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
+	$(call if_changed,vdsosym)
+
+
+
+# Assembly rules for the .S files
+
+sigreturn.o : sigreturn.S
+	$(call if_changed_dep,vdsoas)
+
+note.o : note.S
+	$(call if_changed_dep,vdsoas)
+
+datapage.o : datapage.S
+	$(call if_changed_dep,vdsoas)
+
+gettimeofday.o : gettimeofday.c FORCE
+	$(call if_changed_dep,vdsocc)
+
+# Actual build commands
+quiet_cmd_vdsold = VDSOL   $@
+      cmd_vdsold = $(CC) $(c_flags) -Wl,-n -Wl,-T $^ -o $@
+quiet_cmd_vdsoas = VDSOA   $@
+      cmd_vdsoas = $(CC) $(a_flags) -c -o $@ $<
+quiet_cmd_vdsocc = VDSOA   $@
+      cmd_vdsocc = $(CC) $(c_flags) -c -o $@ $<
+
+# Install commands for the unstripped file
+quiet_cmd_vdso_install = INSTALL $@
+      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+
+vdso.so: $(obj)/vdso.so.dbg
+	@mkdir -p $(MODLIB)/vdso
+	$(call cmd,vdso_install)
+
+vdso_install: vdso.so
diff --git a/arch/nds32/kernel/vdso/datapage.S b/arch/nds32/kernel/vdso/datapage.S
new file mode 100644
index 0000000..d86af66
--- /dev/null
+++ b/arch/nds32/kernel/vdso/datapage.S
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <asm/page.h>
+
+ENTRY(__get_timerpage)
+	sethi	$r0, hi20(. + PAGE_SIZE + 8)
+	ori	$r0, $r0, lo12(. + PAGE_SIZE + 4)
+	mfusr	$r1, $pc
+	sub	$r0, $r1, $r0
+	ret
+ENDPROC(__get_timerpage)
+
+ENTRY(__get_datapage)
+	sethi	$r0, hi20(. + 2*PAGE_SIZE + 8)
+	ori	$r0, $r0, lo12(. + 2*PAGE_SIZE + 4)
+	mfusr	$r1, $pc
+	sub	$r0, $r1, $r0
+	ret
+ENDPROC(__get_datapage)
diff --git a/arch/nds32/kernel/vdso/gen_vdso_offsets.sh b/arch/nds32/kernel/vdso/gen_vdso_offsets.sh
new file mode 100755
index 0000000..01924ff
--- /dev/null
+++ b/arch/nds32/kernel/vdso/gen_vdso_offsets.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+#
+# Match symbols in the DSO that look like VDSO_*; produce a header file
+# of constant offsets into the shared object.
+#
+# Doing this inside the Makefile will break the $(filter-out) function,
+# causing Kbuild to rebuild the vdso-offsets header file every time.
+#
+# Author: Will Deacon <will.deacon@arm.com
+#
+
+LC_ALL=C
+sed -n -e 's/^00*/0/' -e \
+'s/^\([0-9a-fA-F]*\) . VDSO_\([a-zA-Z0-9_]*\)$/\#define vdso_offset_\2\t0x\1/p'
diff --git a/arch/nds32/kernel/vdso/gettimeofday.c b/arch/nds32/kernel/vdso/gettimeofday.c
new file mode 100644
index 0000000..3a93d4e
--- /dev/null
+++ b/arch/nds32/kernel/vdso/gettimeofday.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2015 Mentor Graphics Corporation.
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/compiler.h>
+#include <linux/hrtimer.h>
+#include <linux/time.h>
+#include <asm/io.h>
+#include <asm/barrier.h>
+#include <asm/bug.h>
+#include <asm/page.h>
+#include <asm/unistd.h>
+#include <asm/vdso_datapage.h>
+#include <asm/asm-offsets.h>
+
+#define X(x) #x
+#define Y(x) X(x)
+
+extern struct vdso_data *__get_datapage(void);
+extern struct vdso_data *__get_timerpage(void);
+
+static notrace unsigned int __vdso_read_begin(const struct vdso_data *vdata)
+{
+	u32 seq;
+repeat:
+	seq = ACCESS_ONCE(vdata->seq_count);
+	if (seq & 1) {
+		cpu_relax();
+		goto repeat;
+	}
+	return seq;
+}
+
+static notrace unsigned int vdso_read_begin(const struct vdso_data *vdata)
+{
+	unsigned int seq;
+
+	seq = __vdso_read_begin(vdata);
+
+	smp_rmb();		/* Pairs with smp_wmb in vdso_write_end */
+	return seq;
+}
+
+static notrace int vdso_read_retry(const struct vdso_data *vdata, u32 start)
+{
+	smp_rmb();		/* Pairs with smp_wmb in vdso_write_begin */
+	return vdata->seq_count != start;
+}
+
+static notrace long clock_gettime_fallback(clockid_t _clkid,
+					   struct timespec *_ts)
+{
+	register struct timespec *ts asm("$r1") = _ts;
+	register clockid_t clkid asm("$r0") = _clkid;
+	register long ret asm("$r0");
+
+	asm volatile ("	syscall " Y(__NR_clock_gettime) "\n":"=r"(ret)
+		      :"r"(clkid), "r"(ts)
+		      :"memory");
+
+	return ret;
+}
+
+static notrace int do_realtime_coarse(struct timespec *ts,
+				      struct vdso_data *vdata)
+{
+	u32 seq;
+
+	do {
+		seq = vdso_read_begin(vdata);
+
+		ts->tv_sec = vdata->xtime_coarse_sec;
+		ts->tv_nsec = vdata->xtime_coarse_nsec;
+
+	} while (vdso_read_retry(vdata, seq));
+	return 0;
+}
+
+static notrace int do_monotonic_coarse(struct timespec *ts,
+				       struct vdso_data *vdata)
+{
+	struct timespec tomono;
+	u32 seq;
+
+	do {
+		seq = vdso_read_begin(vdata);
+
+		ts->tv_sec = vdata->xtime_coarse_sec;
+		ts->tv_nsec = vdata->xtime_coarse_nsec;
+
+		tomono.tv_sec = vdata->wtm_clock_sec;
+		tomono.tv_nsec = vdata->wtm_clock_nsec;
+
+	} while (vdso_read_retry(vdata, seq));
+
+	ts->tv_sec += tomono.tv_sec;
+	timespec_add_ns(ts, tomono.tv_nsec);
+	return 0;
+}
+
+static inline u64 vgetsns(struct vdso_data *vdso)
+{
+	u32 cycle_now;
+	u32 cycle_delta;
+	u32 *timer_cycle_base;
+
+	timer_cycle_base =
+	    (u32 *) ((char *)__get_timerpage() + vdso->cycle_count_offset);
+	cycle_now = readl_relaxed(timer_cycle_base);
+	if (true == vdso->cycle_count_down)
+		cycle_now = ~(*timer_cycle_base);
+	cycle_delta = cycle_now - (u32) vdso->cs_cycle_last;
+	return ((u64) cycle_delta & vdso->cs_mask) * vdso->cs_mult;
+}
+
+static notrace int do_realtime(struct timespec *ts, struct vdso_data *vdata)
+{
+	unsigned count;
+	u64 ns;
+	do {
+		count = vdso_read_begin(vdata);
+		ts->tv_sec = vdata->xtime_clock_sec;
+		ns = vdata->xtime_clock_nsec;
+		ns += vgetsns(vdata);
+		ns >>= vdata->cs_shift;
+	} while (vdso_read_retry(vdata, count));
+
+	ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
+	ts->tv_nsec = ns;
+
+	return 0;
+}
+
+static notrace int do_monotonic(struct timespec *ts, struct vdso_data *vdata)
+{
+	struct timespec tomono;
+	u64 nsecs;
+	u32 seq;
+
+	do {
+		seq = vdso_read_begin(vdata);
+
+		ts->tv_sec = vdata->xtime_clock_sec;
+		nsecs = vdata->xtime_clock_nsec;
+		nsecs += vgetsns(vdata);
+		nsecs >>= vdata->cs_shift;
+
+		tomono.tv_sec = vdata->wtm_clock_sec;
+		tomono.tv_nsec = vdata->wtm_clock_nsec;
+
+	} while (vdso_read_retry(vdata, seq));
+
+	ts->tv_sec += tomono.tv_sec;
+	ts->tv_nsec = 0;
+	timespec_add_ns(ts, nsecs + tomono.tv_nsec);
+	return 0;
+}
+
+notrace int __vdso_clock_gettime(clockid_t clkid, struct timespec *ts)
+{
+	struct vdso_data *vdata;
+	int ret = -1;
+
+	vdata = __get_datapage();
+
+	switch (clkid) {
+	case CLOCK_REALTIME_COARSE:
+		ret = do_realtime_coarse(ts, vdata);
+		break;
+	case CLOCK_MONOTONIC_COARSE:
+		ret = do_monotonic_coarse(ts, vdata);
+		break;
+	case CLOCK_REALTIME:
+		ret = do_realtime(ts, vdata);
+		break;
+	case CLOCK_MONOTONIC:
+		ret = do_monotonic(ts, vdata);
+		break;
+	default:
+		break;
+	}
+
+	if (ret)
+		ret = clock_gettime_fallback(clkid, ts);
+
+	return ret;
+}
+
+static notrace long clock_getres_fallback(clockid_t _clk_id,
+					  struct timespec *_res)
+{
+	register clockid_t clk_id asm("$r0") = _clk_id;
+	register struct timespec *res asm("$r1") = _res;
+	register long ret asm("$r0");
+
+	asm volatile ("	syscall " Y(__NR_clock_getres) " \n":"=r"(ret)
+		      :"r"(clk_id), "r"(res)
+		      :"memory");
+
+	return ret;
+}
+
+notrace int __vdso_clock_getres(clockid_t clk_id, struct timespec *res)
+{
+	if (res == NULL)
+		return -EFAULT;
+	switch (clk_id) {
+	case CLOCK_REALTIME:
+	case CLOCK_MONOTONIC:
+	case CLOCK_MONOTONIC_RAW:
+		res->tv_sec = 0;
+		res->tv_nsec = CLOCK_REALTIME_RES;
+		break;
+	case CLOCK_REALTIME_COARSE:
+	case CLOCK_MONOTONIC_COARSE:
+		res->tv_sec = 0;
+		res->tv_nsec = CLOCK_COARSE_RES;
+		break;
+	default:
+		clock_getres_fallback(clk_id, res);
+		break;
+	}
+	return 0;
+}
+
+notrace int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+	struct timespec ts;
+	struct vdso_data *vdata;
+	int ret;
+
+	vdata = __get_datapage();
+
+	ret = do_realtime(&ts, vdata);
+
+	if (tv) {
+		tv->tv_sec = ts.tv_sec;
+		tv->tv_usec = ts.tv_nsec / 1000;
+	}
+	if (tz) {
+		tz->tz_minuteswest = vdata->tz_minuteswest;
+		tz->tz_dsttime = vdata->tz_dsttime;
+	}
+
+	return ret;
+}
diff --git a/arch/nds32/kernel/vdso/note.S b/arch/nds32/kernel/vdso/note.S
new file mode 100644
index 0000000..59c6397
--- /dev/null
+++ b/arch/nds32/kernel/vdso/note.S
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 ARM Limited
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ *
+ * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
+ * Here we can supply some information useful to userland.
+ */
+
+#include <linux/uts.h>
+#include <linux/version.h>
+#include <linux/elfnote.h>
+
+ELFNOTE_START(Linux, 0, "a")
+	.long LINUX_VERSION_CODE
+ELFNOTE_END
diff --git a/arch/nds32/kernel/vdso/sigreturn.S b/arch/nds32/kernel/vdso/sigreturn.S
new file mode 100644
index 0000000..e3cd9d7
--- /dev/null
+++ b/arch/nds32/kernel/vdso/sigreturn.S
@@ -0,0 +1,32 @@
+/*
+ * Sigreturn trampoline for returning from a signal when the SA_RESTORER
+ * flag is not set.
+ *
+ * Copyright (C) 2012 ARM Limited
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#include <linux/linkage.h>
+#include <asm/unistd.h>
+
+	.text
+
+ENTRY(__kernel_rt_sigreturn)
+	.cfi_startproc
+	syscall	#__NR_rt_sigreturn
+	.cfi_endproc
+ENDPROC(__kernel_rt_sigreturn)
diff --git a/arch/nds32/kernel/vdso/vdso.S b/arch/nds32/kernel/vdso/vdso.S
new file mode 100644
index 0000000..4444082
--- /dev/null
+++ b/arch/nds32/kernel/vdso/vdso.S
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012 ARM Limited
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/const.h>
+#include <asm/page.h>
+
+	.globl vdso_start, vdso_end
+	.section .rodata
+	.balign PAGE_SIZE
+vdso_start:
+	.incbin "arch/nds32/kernel/vdso/vdso.so"
+	.balign PAGE_SIZE
+vdso_end:
+
+	.previous
diff --git a/arch/nds32/kernel/vdso/vdso.lds.S b/arch/nds32/kernel/vdso/vdso.lds.S
new file mode 100644
index 0000000..9842ec7
--- /dev/null
+++ b/arch/nds32/kernel/vdso/vdso.lds.S
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <linux/const.h>
+#include <asm/page.h>
+#include <asm/vdso.h>
+
+OUTPUT_FORMAT("elf32-nds32le-linux", "elf32-nds32be-linux", "elf32-nds32le-linux")
+OUTPUT_ARCH(nds32)
+
+SECTIONS
+{
+	. = SIZEOF_HEADERS;
+
+	.hash		: { *(.hash) }			:text
+	.gnu.hash	: { *(.gnu.hash) }
+	.dynsym		: { *(.dynsym) }
+	.dynstr		: { *(.dynstr) }
+	.gnu.version	: { *(.gnu.version) }
+	.gnu.version_d	: { *(.gnu.version_d) }
+	.gnu.version_r	: { *(.gnu.version_r) }
+
+	.note		: { *(.note.*) }		:text	:note
+
+
+	.text		: { *(.text*) }			:text
+
+	.eh_frame_hdr	: { *(.eh_frame_hdr) }		:text	:eh_frame_hdr
+	.eh_frame	: { KEEP (*(.eh_frame)) }	:text
+
+	.dynamic	: { *(.dynamic) }		:text	:dynamic
+
+	.rodata		: { *(.rodata*) }		:text
+
+
+	/DISCARD/	: {
+		*(.note.GNU-stack)
+		*(.data .data.* .gnu.linkonce.d.* .sdata*)
+		*(.bss .sbss .dynbss .dynsbss)
+	}
+}
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+	text		PT_LOAD		FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
+	dynamic		PT_DYNAMIC	FLAGS(4);		/* PF_R */
+	note		PT_NOTE		FLAGS(4);		/* PF_R */
+	eh_frame_hdr	PT_GNU_EH_FRAME;
+}
+
+/*
+ * This controls what symbols we export from the DSO.
+ */
+VERSION
+{
+	LINUX_2.6 {
+	global:
+		__kernel_rt_sigreturn;
+		__vdso_gettimeofday;
+		__vdso_clock_getres;
+		__vdso_clock_gettime;
+	local: *;
+	};
+}
+
+/*
+ * Make the rt_sigreturn code visible to the kernel.
+ */
+VDSO_rt_sigtramp	= __kernel_rt_sigreturn;
-- 
1.7.9.5

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

* [PATCH 17/31] nds32: Signal handling support
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (15 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 16/31] nds32: VDSO support Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-09  1:26   ` Al Viro
  2017-11-08  5:55 ` [PATCH 18/31] nds32: Library functions Greentime Hu
                   ` (15 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/uapi/asm/sigcontext.h |   73 ++++++
 arch/nds32/include/uapi/asm/signal.h     |   23 ++
 arch/nds32/kernel/signal.c               |  370 ++++++++++++++++++++++++++++++
 3 files changed, 466 insertions(+)
 create mode 100644 arch/nds32/include/uapi/asm/sigcontext.h
 create mode 100644 arch/nds32/include/uapi/asm/signal.h
 create mode 100644 arch/nds32/kernel/signal.c

diff --git a/arch/nds32/include/uapi/asm/sigcontext.h b/arch/nds32/include/uapi/asm/sigcontext.h
new file mode 100644
index 0000000..1c0dfcb
--- /dev/null
+++ b/arch/nds32/include/uapi/asm/sigcontext.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ASMNDS32_SIGCONTEXT_H
+#define _ASMNDS32_SIGCONTEXT_H
+
+/*
+ * Signal context structure - contains all info to do with the state
+ * before the signal handler was invoked.  Note: only add new entries
+ * to the end of the structure.
+ */
+
+struct zol_struct {
+	unsigned long nds32_lc;	/* $LC */
+	unsigned long nds32_le;	/* $LE */
+	unsigned long nds32_lb;	/* $LB */
+};
+
+struct sigcontext {
+	unsigned long trap_no;
+	unsigned long error_code;
+	unsigned long oldmask;
+	unsigned long nds32_r0;
+	unsigned long nds32_r1;
+	unsigned long nds32_r2;
+	unsigned long nds32_r3;
+	unsigned long nds32_r4;
+	unsigned long nds32_r5;
+	unsigned long nds32_r6;
+	unsigned long nds32_r7;
+	unsigned long nds32_r8;
+	unsigned long nds32_r9;
+	unsigned long nds32_r10;
+	unsigned long nds32_r11;
+	unsigned long nds32_r12;
+	unsigned long nds32_r13;
+	unsigned long nds32_r14;
+	unsigned long nds32_r15;
+	unsigned long nds32_r16;
+	unsigned long nds32_r17;
+	unsigned long nds32_r18;
+	unsigned long nds32_r19;
+	unsigned long nds32_r20;
+	unsigned long nds32_r21;
+	unsigned long nds32_r22;
+	unsigned long nds32_r23;
+	unsigned long nds32_r24;
+	unsigned long nds32_r25;
+	unsigned long nds32_fp;	/* $r28 */
+	unsigned long nds32_gp;	/* $r29 */
+	unsigned long nds32_lp;	/* $r30 */
+	unsigned long nds32_sp;	/* $r31 */
+	unsigned long nds32_ipc;
+	unsigned long fault_address;
+	unsigned long used_math_flag;
+	/* FPU Registers */
+	struct zol_struct zol;
+};
+
+#endif
diff --git a/arch/nds32/include/uapi/asm/signal.h b/arch/nds32/include/uapi/asm/signal.h
new file mode 100644
index 0000000..5ef6915
--- /dev/null
+++ b/arch/nds32/include/uapi/asm/signal.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ASMNDS32_SIGNAL_H
+#define _ASMNDS32_SIGNAL_H
+
+#define SA_RESTORER	0x04000000
+
+#include <asm-generic/signal.h>
+#endif
diff --git a/arch/nds32/kernel/signal.c b/arch/nds32/kernel/signal.c
new file mode 100644
index 0000000..4bcc45b
--- /dev/null
+++ b/arch/nds32/kernel/signal.c
@@ -0,0 +1,370 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/ptrace.h>
+#include <linux/personality.h>
+#include <linux/freezer.h>
+#include <linux/tracehook.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ucontext.h>
+#include <asm/unistd.h>
+
+#include <asm/ptrace.h>
+#include <asm/vdso.h>
+
+struct rt_sigframe {
+	struct siginfo info;
+	struct ucontext uc;
+};
+
+static int restore_sigframe(struct pt_regs *regs,
+			    struct rt_sigframe __user * sf)
+{
+	sigset_t set;
+	int err;
+
+	err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
+	if (err == 0) {
+		set_current_blocked(&set);
+	}
+
+	__get_user_error(regs->uregs[0], &sf->uc.uc_mcontext.nds32_r0, err);
+	__get_user_error(regs->uregs[1], &sf->uc.uc_mcontext.nds32_r1, err);
+	__get_user_error(regs->uregs[2], &sf->uc.uc_mcontext.nds32_r2, err);
+	__get_user_error(regs->uregs[3], &sf->uc.uc_mcontext.nds32_r3, err);
+	__get_user_error(regs->uregs[4], &sf->uc.uc_mcontext.nds32_r4, err);
+	__get_user_error(regs->uregs[5], &sf->uc.uc_mcontext.nds32_r5, err);
+	__get_user_error(regs->uregs[6], &sf->uc.uc_mcontext.nds32_r6, err);
+	__get_user_error(regs->uregs[7], &sf->uc.uc_mcontext.nds32_r7, err);
+	__get_user_error(regs->uregs[8], &sf->uc.uc_mcontext.nds32_r8, err);
+	__get_user_error(regs->uregs[9], &sf->uc.uc_mcontext.nds32_r9, err);
+	__get_user_error(regs->uregs[10], &sf->uc.uc_mcontext.nds32_r10, err);
+	__get_user_error(regs->uregs[11], &sf->uc.uc_mcontext.nds32_r11, err);
+	__get_user_error(regs->uregs[12], &sf->uc.uc_mcontext.nds32_r12, err);
+	__get_user_error(regs->uregs[13], &sf->uc.uc_mcontext.nds32_r13, err);
+	__get_user_error(regs->uregs[14], &sf->uc.uc_mcontext.nds32_r14, err);
+	__get_user_error(regs->uregs[15], &sf->uc.uc_mcontext.nds32_r15, err);
+	__get_user_error(regs->uregs[16], &sf->uc.uc_mcontext.nds32_r16, err);
+	__get_user_error(regs->uregs[17], &sf->uc.uc_mcontext.nds32_r17, err);
+	__get_user_error(regs->uregs[18], &sf->uc.uc_mcontext.nds32_r18, err);
+	__get_user_error(regs->uregs[19], &sf->uc.uc_mcontext.nds32_r19, err);
+	__get_user_error(regs->uregs[20], &sf->uc.uc_mcontext.nds32_r20, err);
+
+	__get_user_error(regs->uregs[21], &sf->uc.uc_mcontext.nds32_r21, err);
+	__get_user_error(regs->uregs[22], &sf->uc.uc_mcontext.nds32_r22, err);
+	__get_user_error(regs->uregs[23], &sf->uc.uc_mcontext.nds32_r23, err);
+	__get_user_error(regs->uregs[24], &sf->uc.uc_mcontext.nds32_r24, err);
+	__get_user_error(regs->uregs[25], &sf->uc.uc_mcontext.nds32_r25, err);
+	__get_user_error(regs->fp, &sf->uc.uc_mcontext.nds32_fp, err);
+	__get_user_error(regs->gp, &sf->uc.uc_mcontext.nds32_gp, err);
+	__get_user_error(regs->lp, &sf->uc.uc_mcontext.nds32_lp, err);
+	__get_user_error(regs->sp, &sf->uc.uc_mcontext.nds32_sp, err);
+	__get_user_error(regs->ipc, &sf->uc.uc_mcontext.nds32_ipc, err);
+#if defined(CONFIG_HWZOL)
+	__get_user_error(regs->lc, &sf->uc.uc_mcontext.zol.nds32_lc, err);
+	__get_user_error(regs->le, &sf->uc.uc_mcontext.zol.nds32_le, err);
+	__get_user_error(regs->lb, &sf->uc.uc_mcontext.zol.nds32_lb, err);
+#endif
+
+	err |= !valid_user_regs(regs);
+
+	return err;
+}
+
+asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+{
+	struct rt_sigframe __user *frame;
+
+	/* Always make any pending restarted system calls return -EINTR */
+	current->restart_block.fn = do_no_restart_syscall;
+
+	/*
+	 * Since we stacked the signal on a 64-bit boundary,
+	 * then 'sp' should be two-word aligned here.  If it's
+	 * not, then the user is trying to mess with us.
+	 */
+	if (regs->sp & 7)
+		goto badframe;
+
+	frame = (struct rt_sigframe __user *)regs->sp;
+
+	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+
+	if (restore_sigframe(regs, frame))
+		goto badframe;
+
+	if (restore_altstack(&frame->uc.uc_stack))
+		goto badframe;
+
+	return regs->uregs[0];
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+static int
+setup_sigframe(struct rt_sigframe __user * sf, struct pt_regs *regs,
+	       sigset_t * set)
+{
+	int err = 0;
+
+
+	__put_user_error(regs->uregs[0], &sf->uc.uc_mcontext.nds32_r0, err);
+	__put_user_error(regs->uregs[1], &sf->uc.uc_mcontext.nds32_r1, err);
+	__put_user_error(regs->uregs[2], &sf->uc.uc_mcontext.nds32_r2, err);
+	__put_user_error(regs->uregs[3], &sf->uc.uc_mcontext.nds32_r3, err);
+	__put_user_error(regs->uregs[4], &sf->uc.uc_mcontext.nds32_r4, err);
+	__put_user_error(regs->uregs[5], &sf->uc.uc_mcontext.nds32_r5, err);
+	__put_user_error(regs->uregs[6], &sf->uc.uc_mcontext.nds32_r6, err);
+	__put_user_error(regs->uregs[7], &sf->uc.uc_mcontext.nds32_r7, err);
+	__put_user_error(regs->uregs[8], &sf->uc.uc_mcontext.nds32_r8, err);
+	__put_user_error(regs->uregs[9], &sf->uc.uc_mcontext.nds32_r9, err);
+	__put_user_error(regs->uregs[10], &sf->uc.uc_mcontext.nds32_r10, err);
+	__put_user_error(regs->uregs[11], &sf->uc.uc_mcontext.nds32_r11, err);
+	__put_user_error(regs->uregs[12], &sf->uc.uc_mcontext.nds32_r12, err);
+	__put_user_error(regs->uregs[13], &sf->uc.uc_mcontext.nds32_r13, err);
+	__put_user_error(regs->uregs[14], &sf->uc.uc_mcontext.nds32_r14, err);
+	__put_user_error(regs->uregs[15], &sf->uc.uc_mcontext.nds32_r15, err);
+	__put_user_error(regs->uregs[16], &sf->uc.uc_mcontext.nds32_r16, err);
+	__put_user_error(regs->uregs[17], &sf->uc.uc_mcontext.nds32_r17, err);
+	__put_user_error(regs->uregs[18], &sf->uc.uc_mcontext.nds32_r18, err);
+	__put_user_error(regs->uregs[19], &sf->uc.uc_mcontext.nds32_r19, err);
+	__put_user_error(regs->uregs[20], &sf->uc.uc_mcontext.nds32_r20, err);
+
+	__put_user_error(regs->uregs[21], &sf->uc.uc_mcontext.nds32_r21, err);
+	__put_user_error(regs->uregs[22], &sf->uc.uc_mcontext.nds32_r22, err);
+	__put_user_error(regs->uregs[23], &sf->uc.uc_mcontext.nds32_r23, err);
+	__put_user_error(regs->uregs[24], &sf->uc.uc_mcontext.nds32_r24, err);
+	__put_user_error(regs->uregs[25], &sf->uc.uc_mcontext.nds32_r25, err);
+	__put_user_error(regs->fp, &sf->uc.uc_mcontext.nds32_fp, err);
+	__put_user_error(regs->gp, &sf->uc.uc_mcontext.nds32_gp, err);
+	__put_user_error(regs->lp, &sf->uc.uc_mcontext.nds32_lp, err);
+	__put_user_error(regs->sp, &sf->uc.uc_mcontext.nds32_sp, err);
+	__put_user_error(regs->ipc, &sf->uc.uc_mcontext.nds32_ipc, err);
+#if defined(CONFIG_HWZOL)
+	__put_user_error(regs->lc, &sf->uc.uc_mcontext.zol.nds32_lc, err);
+	__put_user_error(regs->le, &sf->uc.uc_mcontext.zol.nds32_le, err);
+	__put_user_error(regs->lb, &sf->uc.uc_mcontext.zol.nds32_lb, err);
+#endif
+
+	__put_user_error(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no,
+			 err);
+	__put_user_error(current->thread.error_code,
+			 &sf->uc.uc_mcontext.error_code, err);
+	__put_user_error(current->thread.address,
+			 &sf->uc.uc_mcontext.fault_address, err);
+	__put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err);
+
+	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
+
+	return err;
+}
+
+static inline void __user *get_sigframe(struct ksignal *ksig,
+					struct pt_regs *regs, int framesize)
+{
+	unsigned long sp = sigsp(regs->sp, ksig);
+	void __user *frame;
+
+	/*
+	 * ATPCS B01 mandates 8-byte alignment
+	 */
+	frame = (void __user *)((sp - framesize) & ~7);
+
+	/*
+	 * Check that we can actually write to the signal frame.
+	 */
+	if (!access_ok(VERIFY_WRITE, frame, framesize))
+		frame = NULL;
+
+	return frame;
+}
+
+static int
+setup_return(struct pt_regs *regs, struct ksignal *ksig, void __user * frame)
+{
+	unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler;
+	unsigned long retcode;
+
+	/*
+	 * Maybe we need to deliver a 32-bit signal to a 26-bit task.
+	 */
+	if (ksig->ka.sa.sa_flags & SA_RESTORER)
+		retcode = (unsigned long)ksig->ka.sa.sa_restorer;
+	else
+		retcode = VDSO_SYMBOL(current->mm->context.vdso, rt_sigtramp);
+
+	regs->uregs[0] = ksig->sig;
+	regs->sp = (unsigned long)frame;
+	regs->lp = retcode;
+	regs->ipc = handler;
+	/* Also store handler address in r15 for updating GP in the handler. */
+	regs->uregs[15] = handler;
+
+	return 0;
+}
+
+static int
+setup_rt_frame(struct ksignal *ksig, sigset_t * set, struct pt_regs *regs)
+{
+	struct rt_sigframe __user *frame =
+	    get_sigframe(ksig, regs, sizeof(*frame));
+	int err = 0;
+
+	if (!frame)
+		return 1;
+
+	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
+
+	__put_user_error(0, &frame->uc.uc_flags, err);
+	__put_user_error(NULL, &frame->uc.uc_link, err);
+
+	err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
+	err |= setup_sigframe(frame, regs, set);
+	if (err == 0) {
+		setup_return(regs, ksig, frame);
+
+		if (err == 0) {
+			/*
+			 * For realtime signals we must also set the second and third
+			 * arguments for the signal handler.
+			 *   -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06
+			 */
+			regs->uregs[1] = (unsigned long)&frame->info;
+			regs->uregs[2] = (unsigned long)&frame->uc;
+		}
+	}
+	return err;
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
+{
+	int ret;
+	sigset_t *oldset = sigmask_to_save();
+
+	/*
+	 * Set up the stack frame
+	 */
+	ret = setup_rt_frame(ksig, oldset, regs);
+
+	/*
+	 * Check that the resulting registers are actually sane.
+	 */
+	ret |= !valid_user_regs(regs);
+
+	signal_setup_done(ret, ksig, 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 int do_signal(struct pt_regs *regs, int syscall)
+{
+	unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
+	struct ksignal ksig;
+	int restart = 0;
+
+	/*
+	 * 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 0;
+
+	/*
+	 * If we were from a system call, check for system call restarting...
+	 */
+	if (syscall) {
+		continue_addr = regs->ipc;
+		restart_addr = continue_addr - 4;
+		retval = regs->uregs[0];
+
+		/*
+		 * Prepare for system call restart.  We do this here so that a
+		 * debugger will see the already changed PSW.
+		 */
+		switch (retval) {
+		case -ERESTART_RESTARTBLOCK:
+			restart -= 2;
+		case -ERESTARTNOHAND:
+		case -ERESTARTSYS:
+		case -ERESTARTNOINTR:
+			restart++;
+			regs->uregs[0] = regs->orig_r0;
+			regs->ipc = restart_addr;
+			break;
+		}
+	}
+
+	/*
+	 * Get the signal to deliver.  When running under ptrace, at this
+	 * point the debugger may change all our registers ...
+	 */
+	/*
+	 * 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 (get_signal(&ksig)) {
+		if (unlikely(restart) && regs->ipc == restart_addr) {
+			if (retval == -ERESTARTNOHAND ||
+			    retval == -ERESTART_RESTARTBLOCK
+			    || (retval == -ERESTARTSYS
+				&& !(ksig.ka.sa.sa_flags & SA_RESTART))) {
+				regs->uregs[0] = -EINTR;
+				regs->ipc = continue_addr;
+			}
+		}
+		handle_signal(&ksig, regs);
+	} else {
+		restore_saved_sigmask();
+		if (unlikely(restart) && regs->ipc == restart_addr) {
+			regs->ipc = continue_addr;
+			return restart;
+		}
+	}
+	return 0;
+}
+
+asmlinkage int
+do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)
+{
+	if (thread_flags & _TIF_SIGPENDING)
+		return do_signal(regs, syscall);
+
+	if (thread_flags & _TIF_NOTIFY_RESUME) {
+		clear_thread_flag(TIF_NOTIFY_RESUME);
+		tracehook_notify_resume(regs);
+	}
+	return 0;
+}
-- 
1.7.9.5

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

* [PATCH 18/31] nds32: Library functions
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (16 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 17/31] nds32: Signal handling support Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08  9:45   ` Arnd Bergmann
  2017-11-09  0:40   ` Al Viro
  2017-11-08  5:55 ` [PATCH 19/31] nds32: Debugging support Greentime Hu
                   ` (14 subsequent siblings)
  32 siblings, 2 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/asm/string.h  |   30 +++
 arch/nds32/include/asm/swab.h    |   48 +++++
 arch/nds32/include/asm/uaccess.h |  385 ++++++++++++++++++++++++++++++++++++++
 arch/nds32/kernel/nds32_ksyms.c  |   54 ++++++
 arch/nds32/lib/Makefile          |    4 +
 arch/nds32/lib/getuser.S         |   57 ++++++
 arch/nds32/lib/memcpy.S          |   93 +++++++++
 arch/nds32/lib/memmove.S         |   83 ++++++++
 arch/nds32/lib/memset.S          |   46 +++++
 arch/nds32/lib/memzero.S         |   31 +++
 arch/nds32/lib/putuser.S         |   53 ++++++
 arch/nds32/lib/uaccess.S         |  160 ++++++++++++++++
 12 files changed, 1044 insertions(+)
 create mode 100644 arch/nds32/include/asm/string.h
 create mode 100644 arch/nds32/include/asm/swab.h
 create mode 100644 arch/nds32/include/asm/uaccess.h
 create mode 100644 arch/nds32/kernel/nds32_ksyms.c
 create mode 100644 arch/nds32/lib/Makefile
 create mode 100644 arch/nds32/lib/getuser.S
 create mode 100644 arch/nds32/lib/memcpy.S
 create mode 100644 arch/nds32/lib/memmove.S
 create mode 100644 arch/nds32/lib/memset.S
 create mode 100644 arch/nds32/lib/memzero.S
 create mode 100644 arch/nds32/lib/putuser.S
 create mode 100644 arch/nds32/lib/uaccess.S

diff --git a/arch/nds32/include/asm/string.h b/arch/nds32/include/asm/string.h
new file mode 100644
index 0000000..cf4d4b8
--- /dev/null
+++ b/arch/nds32/include/asm/string.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_NDS32_STRING_H
+#define __ASM_NDS32_STRING_H
+
+#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *, const void *, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMMOVE
+extern void *memmove(void *, const void *, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMSET
+extern void *memset(void *, int, __kernel_size_t);
+
+extern void *memzero(void *ptr, __kernel_size_t n);
+#endif
diff --git a/arch/nds32/include/asm/swab.h b/arch/nds32/include/asm/swab.h
new file mode 100644
index 0000000..4815d6a
--- /dev/null
+++ b/arch/nds32/include/asm/swab.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NDS32_SWAB_H__
+#define __NDS32_SWAB_H__
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
+{
+	__asm__("wsbh   %0, %0\n\t"	/* word swap byte within halfword */
+		"rotri  %0, %0, #16\n"
+		:"=r"(x)
+		:"0"(x));
+	return x;
+}
+
+static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
+{
+	__asm__("wsbh   %0, %0\n"	/* word swap byte within halfword */
+		:"=r"(x)
+		:"0"(x));
+	return x;
+}
+
+#define __arch_swab32(x) ___arch__swab32(x)
+#define __arch_swab16(x) ___arch__swab16(x)
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#define __BYTEORDER_HAS_U64__
+#define __SWAB_64_THRU_32__
+#endif
+
+#endif /* __NDS32_SWAB_H__ */
diff --git a/arch/nds32/include/asm/uaccess.h b/arch/nds32/include/asm/uaccess.h
new file mode 100644
index 0000000..b87a41a
--- /dev/null
+++ b/arch/nds32/include/asm/uaccess.h
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ASMANDES_UACCESS_H
+#define _ASMANDES_UACCESS_H
+
+/*
+ * User space memory access functions
+ */
+#include <linux/sched.h>
+#include <asm/errno.h>
+#include <asm/memory.h>
+#include <asm/types.h>
+#include <linux/mm.h>
+
+#define VERIFY_READ	0
+#define VERIFY_WRITE	1
+
+#define __asmeq(x, y)  ".ifnc " x "," y " ; .err ; .endif\n\t"
+
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue.  No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path.  This means when everything is well,
+ * we don't even have to jump over them.  Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+
+struct exception_table_entry {
+	unsigned long insn, fixup;
+};
+
+extern int fixup_exception(struct pt_regs *regs);
+
+#define KERNEL_DS ((mm_segment_t) { ~0UL })
+#define USER_DS     ((mm_segment_t) {TASK_SIZE - 1})
+
+#define get_ds()	(KERNEL_DS)
+#define get_fs()	(current_thread_info()->addr_limit)
+#define user_addr_max	get_fs
+
+static inline void set_fs(mm_segment_t fs)
+{
+	current_thread_info()->addr_limit = fs;
+}
+
+#define segment_eq(a, b)    ((a) == (b))
+
+#define __range_ok(addr, size) (size <= get_fs() && addr <= (get_fs() -size))
+
+#define access_ok(type, addr, size)                 \
+	__range_ok((unsigned long)addr, (unsigned long)size)
+/*
+ * Single-value transfer routines.  They automatically use the right
+ * size if we just have the right pointer type.  Note that the functions
+ * which read from user space (*get_*) need to take care not to leak
+ * kernel data even if the calling code is buggy and fails to check
+ * the return value.  This means zeroing out the destination variable
+ * or buffer on error.  Normally this is done out of line by the
+ * fixup code, but there are a few places where it intrudes on the
+ * main code path.  When we only write to user space, there is no
+ * problem.
+ *
+ * The "__xxx" versions of the user access functions do not verify the
+ * address space - it must have been done previously with a separate
+ * "access_ok()" call.
+ *
+ * The "xxx_error" versions set the third argument to EFAULT if an
+ * error occurs, and leave it unchanged on success.  Note that these
+ * versions are void (ie, don't return a value as such).
+ */
+
+extern int __get_user_1(void *);
+extern int __get_user_2(void *);
+extern int __get_user_4(void *);
+extern int __get_user_8(void *);
+extern int __get_user_bad(void);
+
+#define __get_user_x(__r2,__p,__e,__s,__i...)				\
+	   __asm__ __volatile__ (					\
+		__asmeq("%0", "$r0") __asmeq("%1", "$r2")		\
+		"bal	__get_user_" #__s				\
+		: "=&r" (__e), "=r" (__r2)				\
+		: "0" (__p)						\
+		: __i, "cc")
+
+#define get_user(x,p)							\
+	({								\
+		const register typeof(*(p)) __user *__p asm("$r0") = (p);\
+		register unsigned long __r2 asm("$r2");			\
+		register int __e asm("$r0");				\
+		switch (sizeof(*(__p))) {				\
+		case 1:							\
+			__get_user_x(__r2, __p, __e, 1, "$lp");		\
+			break;						\
+		case 2:							\
+			__get_user_x(__r2, __p, __e, 2, "$lp");		\
+			break;						\
+		case 4:							\
+			__get_user_x(__r2, __p, __e, 4, "$lp");		\
+			break;						\
+		case 8:							\
+			__get_user_x(__r2, __p, __e, 8, "$r3", "$lp");	\
+			break;						\
+		default: __e = __get_user_bad(); break;			\
+		}							\
+		x = (typeof(*(p))) __r2;	\
+		__e;							\
+	})
+
+#define __get_user(x,ptr)						\
+({									\
+	long __gu_err = 0;						\
+	__get_user_err((x),(ptr),__gu_err);				\
+	__gu_err;							\
+})
+
+#define __get_user_error(x,ptr,err)					\
+({									\
+	__get_user_err((x),(ptr),err);					\
+	(void) 0;							\
+})
+
+#define __get_user_err(x,ptr,err)					\
+do {									\
+	unsigned long __gu_addr = (unsigned long)(ptr);			\
+	unsigned long __gu_val;						\
+	__chk_user_ptr(ptr);						\
+	switch (sizeof(*(ptr))) {					\
+	case 1:	__get_user_asm_byte(__gu_val,__gu_addr,err);	break;	\
+	case 2:	__get_user_asm_half(__gu_val,__gu_addr,err);	break;	\
+	case 4:	__get_user_asm_word(__gu_val,__gu_addr,err);	break;	\
+	default: (__gu_val) = __get_user_bad();				\
+	}								\
+	(x) = (__typeof__(*(ptr)))__gu_val;				\
+} while (0)
+
+#define __get_user_asm_byte(x,addr,err)				\
+	__asm__ __volatile__(					\
+	"1:	lbi	%1,[%2]\n"				\
+	"2:\n"							\
+	"	.section .fixup,\"ax\"\n"			\
+	"	.align	2\n"					\
+	"3:	move %0, %3\n"				\
+	"	move %1, #0\n"				\
+	"	b	2b\n"					\
+	"	.previous\n"					\
+	"	.section __ex_table,\"a\"\n"			\
+	"	.align	3\n"					\
+	"	.long	1b, 3b\n"				\
+	"	.previous"					\
+	: "+r" (err), "=&r" (x)					\
+	: "r" (addr), "i" (-EFAULT)				\
+	: "cc")
+
+#ifndef __NDS32_EB__
+#define __get_user_asm_half(x,__gu_addr,err)			\
+({								\
+	unsigned long __b1, __b2;				\
+	__get_user_asm_byte(__b1, __gu_addr, err);		\
+	__get_user_asm_byte(__b2, __gu_addr + 1, err);		\
+	(x) = __b1 | (__b2 << 8);				\
+})
+#else
+#define __get_user_asm_half(x,__gu_addr,err)			\
+({								\
+	unsigned long __b1, __b2;				\
+	__get_user_asm_byte(__b1, __gu_addr, err);		\
+	__get_user_asm_byte(__b2, __gu_addr + 1, err);		\
+	(x) = (__b1 << 8) | __b2;				\
+})
+#endif
+
+#define __get_user_asm_word(x,addr,err)				\
+	__asm__ __volatile__(					\
+	"1:	lwi	%1,[%2]\n"				\
+	"2:\n"							\
+	"	.section .fixup,\"ax\"\n"			\
+	"	.align	2\n"					\
+	"3:	move	%0, %3\n"				\
+	"	move	%1, #0\n"				\
+	"	b	2b\n"					\
+	"	.previous\n"					\
+	"	.section __ex_table,\"a\"\n"			\
+	"	.align	3\n"					\
+	"	.long	1b, 3b\n"				\
+	"	.previous"					\
+	: "+r" (err), "=&r" (x)					\
+	: "r" (addr), "i" (-EFAULT)				\
+	: "cc")
+
+extern int __put_user_1(void *, unsigned int);
+extern int __put_user_2(void *, unsigned int);
+extern int __put_user_4(void *, unsigned int);
+extern int __put_user_8(void *, unsigned long long);
+extern int __put_user_bad(void);
+
+#define __put_user_x(__r2,__p,__e,__s,__i)				\
+	   __asm__ __volatile__ (					\
+		__asmeq("%0", "$r0") __asmeq("%2", "$r2")		\
+		"bal	__put_user_" #__s				\
+		: "=&r" (__e)						\
+		: "0" (__p), "r" (__r2)					\
+		: __i, "cc")
+
+#define put_user(x,p)							\
+	({								\
+		const register typeof(*(p)) __r2 asm("$r2") = (x);	\
+		const register typeof(*(p)) __user *__p asm("$r0") = (p);\
+		register int __e asm("$r0");				\
+		switch (sizeof(*(__p))) {				\
+		case 1:							\
+			__put_user_x(__r2, __p, __e, 1, "$lp");		\
+			break;						\
+		case 2:							\
+			__put_user_x(__r2, __p, __e, 2, "$lp");		\
+			break;						\
+		case 4:							\
+			__put_user_x(__r2, __p, __e, 4, "$lp");		\
+			break;						\
+		case 8:							\
+			__put_user_x(__r2, __p, __e, 8, "$lp");		\
+			break;						\
+		default: __e = __put_user_bad(); break;			\
+		}							\
+		__e;							\
+	})
+
+#define __put_user(x,ptr)						\
+({									\
+	long __pu_err = 0;						\
+	__put_user_err((x),(ptr),__pu_err);				\
+	__pu_err;							\
+})
+
+#define __put_user_error(x,ptr,err)					\
+({									\
+	__put_user_err((x),(ptr),err);					\
+	(void) 0;							\
+})
+
+#define __put_user_err(x,ptr,err)					\
+do {									\
+	unsigned long __pu_addr = (unsigned long)(ptr);			\
+	__typeof__(*(ptr)) __pu_val = (x);				\
+	__chk_user_ptr(ptr);						\
+	switch (sizeof(*(ptr))) {					\
+	case 1: __put_user_asm_byte(__pu_val,__pu_addr,err);	break;	\
+	case 2: __put_user_asm_half(__pu_val,__pu_addr,err);	break;	\
+	case 4: __put_user_asm_word(__pu_val,__pu_addr,err);	break;	\
+	case 8:	__put_user_asm_dword(__pu_val,__pu_addr,err);	break;	\
+	default: __put_user_bad();					\
+	}								\
+} while (0)
+
+#define __put_user_asm_byte(x,__pu_addr,err)			\
+	__asm__ __volatile__(					\
+	"1:	sbi	%1,[%2]\n"				\
+	"2:\n"							\
+	"	.section .fixup,\"ax\"\n"			\
+	"	.align	2\n"					\
+	"3:	move	%0, %3\n"				\
+	"	b	2b\n"					\
+	"	.previous\n"					\
+	"	.section __ex_table,\"a\"\n"			\
+	"	.align	3\n"					\
+	"	.long	1b, 3b\n"				\
+	"	.previous"					\
+	: "+r" (err)						\
+	: "r" (x), "r" (__pu_addr), "i" (-EFAULT)		\
+	: "cc")
+
+#ifndef __NDS32_EB__
+#define __put_user_asm_half(x,__pu_addr,err)			\
+({								\
+	unsigned long __temp = (unsigned long)(x);		\
+	__put_user_asm_byte(__temp, __pu_addr, err);		\
+	__put_user_asm_byte(__temp >> 8, __pu_addr + 1, err);	\
+})
+#else
+#define __put_user_asm_half(x,__pu_addr,err)			\
+({								\
+	unsigned long __temp = (unsigned long)(x);		\
+	__put_user_asm_byte(__temp >> 8, __pu_addr, err);	\
+	__put_user_asm_byte(__temp, __pu_addr + 1, err);	\
+})
+#endif
+
+#define __put_user_asm_word(x,__pu_addr,err)			\
+	__asm__ __volatile__(					\
+	"1:	swi	%1,[%2]\n"				\
+	"2:\n"							\
+	"	.section .fixup,\"ax\"\n"			\
+	"	.align	2\n"					\
+	"3:	move	%0, %3\n"				\
+	"	b	2b\n"					\
+	"	.previous\n"					\
+	"	.section __ex_table,\"a\"\n"			\
+	"	.align	3\n"					\
+	"	.long	1b, 3b\n"				\
+	"	.previous"					\
+	: "+r" (err)						\
+	: "r" (x), "r" (__pu_addr), "i" (-EFAULT)		\
+	: "cc")
+
+#ifdef __NDS32_EB__
+#define __reg_oper0 "%H2"
+#define __reg_oper1 "%L2"
+#else
+#define __reg_oper0 "%L2"
+#define __reg_oper1 "%H2"
+#endif
+
+#define __put_user_asm_dword(x, __pu_addr, __pu_err) \
+	__asm__ __volatile__ (			    \
+	"\n1:\tswi " __reg_oper0 ",[%1]\n"	\
+	"\n2:\tswi " __reg_oper1 ",[%1+4]\n"	\
+	"3:\n"					\
+	"	.section .fixup,\"ax\"\n"	\
+	"	.align	2\n"			\
+	"4:	move	%0, %3\n"		\
+	"	b	3b\n"			\
+	"	.previous\n"			\
+	"	.section __ex_table,\"a\"\n"	\
+	"	.align	3\n"			\
+	"	.long	1b, 4b\n"		\
+	"	.long	2b, 4b\n"		\
+	"	.previous"			\
+	: "+r"(__pu_err)                \
+	: "r"(__pu_addr), "r"(x), "i"(-EFAULT) \
+	: "cc")
+extern unsigned long __arch_copy_from_user(void *to, const void __user * from,
+					   unsigned long n);
+extern unsigned long __arch_copy_to_user(void __user * to, const void *from,
+					 unsigned long n);
+extern unsigned long __arch_clear_user(void __user * addr, unsigned long n);
+extern long strncpy_from_user(char *dest, const char __user * src, long count);
+extern __must_check long strlen_user(const char __user * str);
+extern __must_check long strnlen_user(const char __user * str, long n);
+static inline unsigned long raw_copy_from_user(void *to,
+					       const void __user * from,
+					       unsigned long n)
+{
+	return __arch_copy_from_user(to, from, n);
+}
+
+static inline unsigned long raw_copy_to_user(void __user * to, const void *from,
+					     unsigned long n)
+{
+	return __arch_copy_to_user(to, from, n);
+}
+
+#define INLINE_COPY_FROM_USER
+#define INLINE_COPY_TO_USER
+static inline unsigned long clear_user(void __user * to, unsigned long n)
+{
+	if (access_ok(VERIFY_WRITE, to, n))
+		n = __arch_clear_user(to, n);
+	return n;
+}
+
+static inline unsigned long __clear_user(void __user * to, unsigned long n)
+{
+	return __arch_clear_user(to, n);
+}
+
+#endif /* _ASMNDS32_UACCESS_H */
diff --git a/arch/nds32/kernel/nds32_ksyms.c b/arch/nds32/kernel/nds32_ksyms.c
new file mode 100644
index 0000000..3f8f29f
--- /dev/null
+++ b/arch/nds32/kernel/nds32_ksyms.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/in6.h>
+#include <linux/syscalls.h>
+
+#include <asm/checksum.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/ftrace.h>
+#include <asm/proc-fns.h>
+
+/* mem functions */
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memzero);
+
+/* user mem (segment) */
+EXPORT_SYMBOL(__arch_copy_from_user);
+EXPORT_SYMBOL(__arch_copy_to_user);
+EXPORT_SYMBOL(__arch_clear_user);
+
+EXPORT_SYMBOL(__get_user_1);
+EXPORT_SYMBOL(__get_user_2);
+EXPORT_SYMBOL(__get_user_4);
+EXPORT_SYMBOL(__get_user_8);
+
+EXPORT_SYMBOL(__put_user_1);
+EXPORT_SYMBOL(__put_user_2);
+EXPORT_SYMBOL(__put_user_4);
+EXPORT_SYMBOL(__put_user_8);
+
+/* cache handling */
+EXPORT_SYMBOL(cpu_icache_inval_all);
+EXPORT_SYMBOL(cpu_dcache_wbinval_all);
+EXPORT_SYMBOL(cpu_dma_inval_range);
+EXPORT_SYMBOL(cpu_dma_wb_range);
diff --git a/arch/nds32/lib/Makefile b/arch/nds32/lib/Makefile
new file mode 100644
index 0000000..4c53eb8
--- /dev/null
+++ b/arch/nds32/lib/Makefile
@@ -0,0 +1,4 @@
+lib-y		:= copy_page.o memcpy.o memmove.o   \
+		   memset.o memzero.o \
+		   uaccess.o getuser.o \
+		   putuser.o
diff --git a/arch/nds32/lib/getuser.S b/arch/nds32/lib/getuser.S
new file mode 100644
index 0000000..d3e9108
--- /dev/null
+++ b/arch/nds32/lib/getuser.S
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/errno.h>
+#include <linux/linkage.h>
+
+
+ENTRY(__get_user_1)
+1:	lbi	$r2, [$r0]
+	move	$r0, #0
+	ret
+
+ENTRY(__get_user_2)
+2:	lhi	$r2, [$r0]
+	move	$r0, #0
+	ret
+
+ENTRY(__get_user_4)
+3:	lwi	$r2, [$r0]
+	move	$r0, #0
+	ret
+
+ENTRY(__get_user_8)
+4:	lwi.bi	$r2, [$r0], #4
+5:	lwi	$r3, [$r0]
+	move	$r0, #0
+	ret
+
+__get_user_bad_8:
+	move	$r3, #0
+__get_user_bad:
+	move	$r2, #0
+	move	$r0, #-EFAULT
+	ret
+
+.section __ex_table, "a"
+	.long	1b, __get_user_bad
+	.long	2b, __get_user_bad
+	.long	3b, __get_user_bad
+	.long	4b, __get_user_bad_8
+	.long	5b, __get_user_bad_8
+.previous
diff --git a/arch/nds32/lib/memcpy.S b/arch/nds32/lib/memcpy.S
new file mode 100644
index 0000000..e809fd6
--- /dev/null
+++ b/arch/nds32/lib/memcpy.S
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+	.text
+
+ENTRY(memcpy)
+	move	$r5, $r0
+	beq	$r0, $r1, quit_memcpy
+	beqz	$r2, quit_memcpy
+	srli    $r3, $r2, #5	 ! check if len < cache-line size 32
+	beqz	$r3, word_copy_entry
+	andi	$r4, $r0, #0x3	! check byte-align
+	beqz	$r4, unalign_word_copy_entry
+
+	addi	$r4, $r4,#-4
+	abs	$r4, $r4		! check how many un-align byte to copy
+	sub	$r2, $r2, $r4	! update $R2
+
+unalign_byte_copy:
+	lbi.bi	$r3, [$r1], #1
+	addi	$r4, $r4, #-1
+	sbi.bi	$r3, [$r0], #1
+	bnez	$r4, unalign_byte_copy
+	beqz	$r2, quit_memcpy
+
+unalign_word_copy_entry:
+	andi	$r3, $r0, 0x1f	! check cache-line unaligncount
+	beqz	$r3, cache_copy
+
+	addi	$r3, $r3, #-32
+	abs	$r3, $r3
+	sub	$r2, $r2, $r3	! update $R2
+
+unalign_word_copy:
+	lmw.bim	$r4, [$r1], $r4
+	addi	$r3, $r3, #-4
+	smw.bim	$r4, [$r0], $r4
+	bnez	$r3, unalign_word_copy
+	beqz	$r2, quit_memcpy
+
+	addi	$r3, $r2, #-32	! to check $r2< cache_line , than go to word_copy
+	bltz	$r3, word_copy_entry
+cache_copy:
+	srli	$r3, $r2, #5
+	beqz	$r3, word_copy_entry
+	pushm	$r6, $r13
+3:
+	lmw.bim	$r6, [$r1], $r13
+	addi	$r3, $r3, #-1
+	smw.bim	$r6, [$r0], $r13
+	bnez	$r3, 3b
+	popm	$r6, $r13
+
+word_copy_entry:
+	andi	$r2, $r2, #31
+
+	beqz	$r2, quit_memcpy
+5:
+	srli	$r3, $r2, #2
+	beqz	$r3, byte_copy
+word_copy:
+	lmw.bim	$r4, [$r1], $r4
+	addi	$r3, $r3, #-1
+	smw.bim	$r4, [$r0], $r4
+	bnez	$r3, word_copy
+	andi	$r2, $r2, #3
+	beqz	$r2, quit_memcpy
+byte_copy:
+	lbi.bi	$r3, [$r1], #1
+	addi	$r2, $r2, #-1
+
+	sbi.bi	$r3, [$r0], #1
+	bnez	$r2, byte_copy
+quit_memcpy:
+	move	$r0, $r5
+	ret
+
+ENDPROC(memcpy)
diff --git a/arch/nds32/lib/memmove.S b/arch/nds32/lib/memmove.S
new file mode 100644
index 0000000..0c54350
--- /dev/null
+++ b/arch/nds32/lib/memmove.S
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+/*
+  void *memmove(void *dst, const void *src, int n);
+
+  dst: $r0
+  src: $r1
+  n  : $r2
+  ret: $r0 - pointer to the memory area dst.
+*/
+	.text
+
+ENTRY(memmove)
+	move	$r5, $r0		! Set return value = det
+	beq	$r0, $r1, exit_memcpy	! Exit when det = src
+	beqz	$r2, exit_memcpy	! Exit when n = 0
+	pushm	$t0, $t1		! Save reg
+	srli	$p1, $r2, #2		! $p1 is how many words to copy
+
+	! Avoid data lost when memory overlap
+	! Copy data reversely when src < dst
+	slt	$p0, $r0, $r1		! check if $r0 < $r1
+	beqz	$p0, do_reverse		! branch if dst > src
+
+	! No reverse, dst < src
+	andi	$r2, $r2, #3		! How many bytes are less than a word
+	li	$t0, #1			! Determining copy direction in byte_cpy
+	beqz	$p1, byte_cpy		! When n is less than a word
+
+word_cpy:
+	lmw.bim	$p0, [$r1], $p0		! Read a word from src
+	addi	$p1, $p1, #-1		! How many words left to copy
+	smw.bim	$p0, [$r0], $p0		! Copy the word to det
+	bnez	$p1, word_cpy		! If remained words > 0
+	beqz	$r2, end_memcpy		! No left bytes to copy
+	b	byte_cpy
+
+do_reverse:
+	add	$r0, $r0, $r2		! Start with the end of $r0
+	add	$r1, $r1, $r2		! Start with the end of $r1
+	andi	$r2, $r2, #3		! How many bytes are less than a word
+	li	$t0, #-1		! Determining copy direction in byte_cpy
+	beqz	$p1, reverse_byte_cpy	! When n is less than a word
+
+reverse_word_cpy:
+	lmw.adm	$p0, [$r1], $p0		! Read a word from src
+	addi	$p1, $p1, #-1		! How many words left to copy
+	smw.adm	$p0, [$r0], $p0		! Copy the word to det
+	bnez	$p1, reverse_word_cpy	! If remained words > 0
+	beqz	$r2, end_memcpy		! No left bytes to copy
+
+reverse_byte_cpy:
+	addi	$r0, $r0, #-1
+	addi	$r1, $r1, #-1
+byte_cpy:				! Less than 4 bytes to copy now
+	lb.bi	$p0, [$r1], $t0		! Read a byte from src
+	addi	$r2, $r2, #-1		! How many bytes left to copy
+	sb.bi	$p0, [$r0], $t0		! copy the byte to det
+	bnez	$r2, byte_cpy		! If remained bytes > 0
+
+end_memcpy:
+	popm	$t0, $t1
+exit_memcpy:
+	move	$r0, $r5
+	ret
+
+ENDPROC(memmove)
diff --git a/arch/nds32/lib/memset.S b/arch/nds32/lib/memset.S
new file mode 100644
index 0000000..05ec352
--- /dev/null
+++ b/arch/nds32/lib/memset.S
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+	.text
+ENTRY(memset)
+	move	$r5, $r0		! Return value
+	beqz	$r2, end_memset		! Exit when len = 0
+	srli	$p1, $r2, 2		! $p1 is how many words to copy
+	andi	$r2, $r2, 3		! How many bytes are less than a word
+	beqz	$p1, byte_set		! When n is less than a word
+
+	! set $r1 from ??????ab to abababab
+	andi	$r1, $r1, #0x00ff	! $r1 = 000000ab
+	slli	$p0, $r1, #8		! $p0 = 0000ab00
+	or	$r1, $r1, $p0		! $r1 = 0000abab
+	slli	$p0, $r1, #16		! $p0 = abab0000
+	or	$r1, $r1, $p0		! $r1 = abababab
+word_set:
+	addi	$p1, $p1, #-1		! How many words left to copy
+	smw.bim	$r1, [$r0], $r1		! Copy the word to det
+	bnez	$p1, word_set		! Still words to set, continue looping
+	beqz	$r2, end_memset		! No left byte to set
+byte_set:				! Less than 4 bytes left to set
+	addi	$r2, $r2, #-1		! Decrease len by 1
+	sbi.bi	$r1, [$r0], #1		! Set data of the next byte to $r1
+	bnez	$r2, byte_set		! Still bytes left to set
+end_memset:
+	move	$r0, $r5
+	ret
+
+ENDPROC(memset)
diff --git a/arch/nds32/lib/memzero.S b/arch/nds32/lib/memzero.S
new file mode 100644
index 0000000..00c9996
--- /dev/null
+++ b/arch/nds32/lib/memzero.S
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+	.text
+ENTRY(memzero)
+	beqz	$r1, 1f
+	push	$lp
+        move    $r2, $r1
+        move    $r1, #0
+	push	$r0
+        bal     memset
+	pop	$r0
+	pop	$lp
+1:
+        ret
+ENDPROC(memzero)
diff --git a/arch/nds32/lib/putuser.S b/arch/nds32/lib/putuser.S
new file mode 100644
index 0000000..2f8a20f
--- /dev/null
+++ b/arch/nds32/lib/putuser.S
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <asm/errno.h>
+#include <linux/linkage.h>
+
+	.text
+
+ENTRY(__put_user_1)
+1:	sb	$r2, [$r0]
+	move	$r0, #0
+	ret
+
+ENTRY(__put_user_2)
+2:	shi	$r2, [$r0]	! Store input halfword
+	move	$r0, #0
+	ret
+
+ENTRY(__put_user_4)
+3:	sw	$r2, [$r0]
+	move	$r0, #0
+	ret
+
+ENTRY(__put_user_8)
+4:	swi.bi	$r2, [$r0], #4
+5:	sw	$r3, [$r0]
+	move	$r0, #0
+	ret
+
+__put_user_bad:
+	move	$r0, #-EFAULT
+	ret
+
+.section __ex_table, "a"
+	.long	1b, __put_user_bad
+	.long	2b, __put_user_bad
+	.long	3b, __put_user_bad
+	.long	4b, __put_user_bad
+	.long	5b, __put_user_bad
+.previous
diff --git a/arch/nds32/lib/uaccess.S b/arch/nds32/lib/uaccess.S
new file mode 100644
index 0000000..dc2583e
--- /dev/null
+++ b/arch/nds32/lib/uaccess.S
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/errno.h>
+
+	.text
+
+/* Prototype: int __arch_copy_to_user(void *to, const char *from, size_t n)
+ * Purpose  : copy a block to user memory from kernel memory
+ * Params   : to   - user memory
+ *          : from - kernel memory
+ *          : n    - number of bytes to copy
+ * Returns  : Number of bytes NOT copied.
+ */
+
+ENTRY(__arch_copy_to_user)
+	push	$r0
+	push	$r2
+	beqz	$r2, ctu_exit
+	srli	$p0, $r2, #2		! $p0 = number of word to clear
+	andi	$r2, $r2, #3		! Bytes less than a word to copy
+	beqz	$p0, byte_ctu		! Only less than a word to copy
+word_ctu:
+	lmw.bim	$p1, [$r1], $p1		! Load the next word
+USER(	smw.bim,$p1, [$r0], $p1)	! Store the next word
+	addi	$p0, $p0, #-1		! Decrease word count
+	bnez	$p0, word_ctu		! Continue looping to copy all words
+	beqz	$r2, ctu_exit		! No left bytes to copy
+byte_ctu:
+	lbi.bi	$p1, [$r1], #1		! Load the next byte
+USER(	sbi.bi,	$p1, [$r0], #1)		! Store the next byte
+	addi	$r2, $r2, #-1		! Decrease byte count
+	bnez	$r2, byte_ctu		! Continue looping to clear all left bytes
+ctu_exit:
+	move	$r0, $r2		! Set return value
+	pop	$r2
+	pop	$r2			! Pop saved $r0 to $r2 to not corrupt return value
+	ret
+
+	.section .fixup,"ax"
+	.align	0
+9001:
+	pop	$p1			! Original $r2, n
+	pop	$p0			! Original $r0, void *to
+	sub	$r1, $r0, $p0		! Bytes copied
+	sub	$r2, $p1, $r1		! Bytes left to copy
+	push	$lp
+	move	$r0, $p0
+	bal	memzero			! Clean up the memory
+	pop	$lp
+	move	$r0, $r2
+	ret
+	.previous
+ENDPROC(__arch_copy_to_user)
+
+/* Prototype: unsigned long __arch_copy_from_user(void *to,const void *from,unsigned long n);
+ * Purpose  : copy a block from user memory to kernel memory
+ * Params   : to   - kernel memory
+ *          : from - user memory
+ *          : n    - number of bytes to copy
+ * Returns  : Number of bytes NOT copied.
+ */
+
+
+ENTRY(__arch_copy_from_user)
+	push	$r1
+	push	$r2
+	beqz	$r2, cfu_exit
+	srli	$p0, $r2, #2		! $p0 = number of word to clear
+	andi	$r2, $r2, #3		! Bytes less than a word to copy
+	beqz	$p0, byte_cfu		! Only less than a word to copy
+word_cfu:
+USER(	lmw.bim,$p1, [$r1], $p1)	! Load the next word
+	smw.bim	$p1, [$r0], $p1		! Store the next word
+	addi	$p0, $p0, #-1		! Decrease word count
+	bnez	$p0, word_cfu		! Continue looping to copy all words
+	beqz	$r2, cfu_exit		! No left bytes to copy
+byte_cfu:
+USER(	lbi.bi,	$p1, [$r1], #1)		! Load the next byte
+	sbi.bi	$p1, [$r0], #1		! Store the next byte
+	addi	$r2, $r2, #-1		! Decrease byte count
+	bnez	$r2, byte_cfu		! Continue looping to clear all left bytes
+cfu_exit:
+	move	$r0, $r2		! Set return value
+	pop	$r2
+	pop	$r1
+	ret
+
+	.section .fixup,"ax"
+	.align	0
+	/*
+	 * We took an exception.  $r0 contains a pointer to
+	 * the byte not copied.
+	 */
+9001:
+	pop	$p1			! Original $r2, n
+	pop	$p0			! Original $r0, void *to
+	sub	$r1, $r1, $p0		! Bytes copied
+	sub	$r2, $p1, $r1		! Bytes left to copy
+	push	$lp
+	bal	memzero			! Clean up the memory
+	pop	$lp
+	move	$r0, $r2
+	ret
+	.previous
+ENDPROC(__arch_copy_from_user)
+
+/* Prototype: int __arch_clear_user(void *addr, size_t sz)
+ * Purpose  : clear some user memory
+ * Params   : addr - user memory address to clear
+ *          : sz   - number of bytes to clear
+ * Returns  : number of bytes NOT cleared
+ */
+	.align	5
+ENTRY(__arch_clear_user)
+	pushm	$r0, $r1
+	beqz	$r1, clear_exit
+	xor	$p1, $p1, $p1		! Use $p1=0 to clear mem
+	srli	$p0, $r1, #2		! $p0 = number of word to clear
+	andi	$r1, $r1, #3		! Bytes less than a word to copy
+	beqz	$p0, byte_clear		! Only less than a word to clear
+word_clear:
+USER(	smw.bim,$p1, [$r0], $p1)	! Clear the word
+	addi	$p0, $p0, #-1		! Decrease word count
+	bnez	$p0, word_clear		! Continue looping to clear all words
+	beqz	$r1, clear_exit		! No left bytes to copy
+byte_clear:
+USER(	sbi.bi,	$p1, [$r0], #1)		! Clear the byte
+	addi	$r1, $r1, #-1		! Decrease byte count
+	bnez	$r1, byte_clear		! Continue looping to clear all left bytes
+clear_exit:
+	move	$r0, $r1		! Set return value
+	pop	$r1
+	pop	$r1			! Pop saved $r0 to $r1 to not corrupt return value
+	ret
+
+	.section .fixup,"ax"
+	.align	0
+9001:
+	popm	$p0, $p1		! $p0 = original $r0, *addr, $p1 = original $r1, n
+	sub	$p0, $r0, $p0		! Bytes copied
+	sub	$r0, $p1, $p0		! Bytes left to copy
+	ret
+	.previous
+ENDPROC(__arch_clear_user)
-- 
1.7.9.5

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

* [PATCH 19/31] nds32: Debugging support
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (17 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 18/31] nds32: Library functions Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08  5:55 ` [PATCH 20/31] nds32: L2 cache support Greentime Hu
                   ` (13 subsequent siblings)
  32 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/uapi/asm/ptrace.h |   42 +++++
 arch/nds32/kernel/ptrace.c           |  325 ++++++++++++++++++++++++++++++++++
 2 files changed, 367 insertions(+)
 create mode 100644 arch/nds32/include/uapi/asm/ptrace.h
 create mode 100644 arch/nds32/kernel/ptrace.c

diff --git a/arch/nds32/include/uapi/asm/ptrace.h b/arch/nds32/include/uapi/asm/ptrace.h
new file mode 100644
index 0000000..20f9718
--- /dev/null
+++ b/arch/nds32/include/uapi/asm/ptrace.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __UAPI_ASM_NDS32_PTRACE_H
+#define __UAPI_ASM_NDS32_PTRACE_H
+
+#ifndef __ASSEMBLY__
+
+/*
+ * User structures for general purpose register.
+ */
+struct user_pt_regs {
+	long uregs[26];
+	long fp;
+	long gp;
+	long lp;
+	long sp;
+	long ipc;
+#if defined(CONFIG_HWZOL)
+	long lb;
+	long le;
+	long lc;
+#else
+	long dummy[3];
+#endif
+	long syscallno;
+};
+#endif
+#endif
diff --git a/arch/nds32/kernel/ptrace.c b/arch/nds32/kernel/ptrace.c
new file mode 100644
index 0000000..d91b3b8
--- /dev/null
+++ b/arch/nds32/kernel/ptrace.c
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/security.h>
+#include <linux/init.h>
+#include <linux/uaccess.h>
+#include <linux/regset.h>
+#include <linux/tracehook.h>
+#include <linux/elf.h>
+#include <linux/sched/task_stack.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+enum nds32_regset {
+	REGSET_GPR,
+};
+
+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 user_pt_regs *uregs = &task_pt_regs(target)->user_regs;
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 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 err;
+	struct user_pt_regs newregs = task_pt_regs(target)->user_regs;
+
+	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1);
+	if (err)
+		return err;
+
+	task_pt_regs(target)->user_regs = newregs;
+	return 0;
+}
+
+static const struct user_regset nds32_regsets[] = {
+	[REGSET_GPR] = {
+			.core_note_type = NT_PRSTATUS,
+			.n = sizeof(struct user_pt_regs) / sizeof(u32),
+			.size = sizeof(u32),
+			.align = sizeof(u32),
+			.get = gpr_get,
+			.set = gpr_set}
+};
+
+static const struct user_regset_view nds32_user_view = {
+	.name = "nds32",.e_machine = EM_NDS32,
+	.regsets = nds32_regsets,.n = ARRAY_SIZE(nds32_regsets)
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+	return &nds32_user_view;
+}
+
+/* get_user_reg()
+ *
+ * This routine will get a word off of the processes privileged stack.
+ * the offset is how far from the base addr as stored in the THREAD.
+ * this routine assumes that all the privileged stacks are in our
+ * data space.
+ */
+static inline unsigned int get_user_reg(struct task_struct *task, int offset)
+{
+	return task_pt_regs(task)->uregs[offset];
+}
+
+/* put_user_reg()
+ *
+ * this routine will put a word on the processes privileged stack.
+ * the offset is how far from the base addr as stored in the THREAD.
+ * this routine assumes that all the privileged stacks are in our
+ * data space.
+ */
+static inline int put_user_reg(struct task_struct *task, int offset, long data)
+{
+	struct pt_regs newregs, *regs = task_pt_regs(task);
+	int ret = -EINVAL;
+
+	newregs = *regs;
+	newregs.uregs[offset] = data;
+
+	if (valid_user_regs(&newregs)) {
+		regs->uregs[offset] = data;
+		ret = 0;
+	}
+
+	return ret;
+}
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure the single step bit is not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+	user_disable_single_step(child);
+}
+
+static void fill_sigtrap_info(struct task_struct *tsk,
+			      struct pt_regs *regs,
+			      int error_code, int si_code, struct siginfo *info)
+{
+	tsk->thread.trap_no = ENTRY_DEBUG_RELATED;
+	tsk->thread.error_code = error_code;
+
+	memset(info, 0, sizeof(*info));
+	info->si_signo = SIGTRAP;
+	info->si_code = si_code;
+	info->si_addr = (void __user *)instruction_pointer(regs);
+}
+
+void user_single_step_siginfo(struct task_struct *tsk,
+			      struct pt_regs *regs, struct siginfo *info)
+{
+	fill_sigtrap_info(tsk, regs, 0, TRAP_BRKPT, info);
+}
+
+/*
+ * Handle hitting a breakpoint.
+ */
+void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
+		  int error_code, int si_code)
+{
+	struct siginfo info;
+
+	fill_sigtrap_info(tsk, regs, error_code, TRAP_BRKPT, &info);
+	/* Send us the fake SIGTRAP */
+	force_sig_info(SIGTRAP, &info, tsk);
+}
+
+/* ptrace_read_user()
+ *
+ * Read the word at offset "off" into the "struct user".  We
+ * actually access the pt_regs stored on the kernel stack.
+ */
+static int
+ptrace_read_user(struct task_struct *tsk, unsigned long off,
+		 unsigned long __user * ret)
+{
+	unsigned long tmp = 0;
+
+	if (off < sizeof(struct pt_regs)) {
+		if (off & 3)
+			return -EIO;
+		tmp = get_user_reg(tsk, off >> 2);
+		return put_user(tmp, ret);
+	} else
+		return -EIO;
+}
+
+/* ptrace_write_user()
+ *
+ * Write the word at offset "off" into "struct user".  We
+ * actually access the pt_regs stored on the kernel stack.
+ */
+static int
+ptrace_write_user(struct task_struct *tsk, unsigned long off, unsigned long val)
+{
+	if (off < sizeof(struct pt_regs)) {
+		if (off & 3)
+			return -EIO;
+		return put_user_reg(tsk, off >> 2, val);
+	} else
+		return -EIO;
+}
+
+/* ptrace_getregs()
+ *
+ * Get all user integer registers.
+ */
+static int ptrace_getregs(struct task_struct *tsk, void __user * uregs)
+{
+	struct pt_regs *regs = task_pt_regs(tsk);
+
+	return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
+}
+
+/* ptrace_setregs()
+ *
+ * Set all user integer registers.
+ */
+static int ptrace_setregs(struct task_struct *tsk, void __user * uregs)
+{
+	struct pt_regs newregs;
+	int ret;
+
+	ret = -EFAULT;
+	if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) {
+		struct pt_regs *regs = task_pt_regs(tsk);
+
+		ret = -EINVAL;
+		if (valid_user_regs(&newregs)) {
+			*regs = newregs;
+			ret = 0;
+		}
+	}
+
+	return ret;
+}
+
+/* ptrace_getfpregs()
+ *
+ * Get the child FPU state.
+ */
+static int ptrace_getfpregs(struct task_struct *tsk, void __user * ufpregs)
+{
+	return -EFAULT;
+}
+
+/*
+ * Set the child FPU state.
+ */
+static int ptrace_setfpregs(struct task_struct *tsk, void __user * ufpregs)
+{
+	return -EFAULT;
+}
+
+/* do_ptrace()
+ *
+ * Provide ptrace defined service.
+ */
+long arch_ptrace(struct task_struct *child, long request, unsigned long addr,
+		 unsigned long data)
+{
+	int ret;
+
+	switch (request) {
+	case PTRACE_PEEKUSR:
+		ret =
+		    ptrace_read_user(child, addr, (unsigned long __user *)data);
+		break;
+
+	case PTRACE_POKEUSR:
+		ret = ptrace_write_user(child, addr, data);
+		break;
+
+	case PTRACE_GETREGS:
+		ret = ptrace_getregs(child, (void __user *)data);
+		break;
+
+	case PTRACE_SETREGS:
+		ret = ptrace_setregs(child, (void __user *)data);
+		break;
+
+	case PTRACE_GETFPREGS:
+		ret = ptrace_getfpregs(child, (void __user *)data);
+		break;
+
+	case PTRACE_SETFPREGS:
+		ret = ptrace_setfpregs(child, (void __user *)data);
+		break;
+
+	default:
+		ret = ptrace_request(child, request, addr, data);
+		break;
+	}
+
+	return ret;
+}
+
+void user_enable_single_step(struct task_struct *child)
+{
+	struct pt_regs *regs;
+	regs = task_pt_regs(child);
+	regs->ipsw |= PSW_mskHSS;
+	set_tsk_thread_flag(child, TIF_SINGLESTEP);
+}
+
+void user_disable_single_step(struct task_struct *child)
+{
+	struct pt_regs *regs;
+	regs = task_pt_regs(child);
+	regs->ipsw &= ~PSW_mskHSS;
+	clear_tsk_thread_flag(child, TIF_SINGLESTEP);
+}
+
+/* sys_trace()
+ *
+ * syscall trace handler.
+ */
+
+asmlinkage int syscall_trace_enter(int syscall, struct pt_regs *regs)
+{
+	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
+		if (tracehook_report_syscall_entry(regs))
+			return -1;
+	}
+	return syscall;
+}
+
+asmlinkage void syscall_trace_leave(struct pt_regs *regs)
+{
+	int step = test_thread_flag(TIF_SINGLESTEP);
+	if (step || test_thread_flag(TIF_SYSCALL_TRACE))
+		tracehook_report_syscall_exit(regs, step);
+
+}
-- 
1.7.9.5

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

* [PATCH 20/31] nds32: L2 cache support
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (18 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 19/31] nds32: Debugging support Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08  9:48   ` Arnd Bergmann
  2017-11-08  5:55 ` [PATCH 21/31] nds32: Loadable modules Greentime Hu
                   ` (12 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/asm/l2_cache.h |  158 +++++++++++++++++++++++++++++++++++++
 arch/nds32/kernel/atl2c.c         |   77 ++++++++++++++++++
 2 files changed, 235 insertions(+)
 create mode 100644 arch/nds32/include/asm/l2_cache.h
 create mode 100644 arch/nds32/kernel/atl2c.c

diff --git a/arch/nds32/include/asm/l2_cache.h b/arch/nds32/include/asm/l2_cache.h
new file mode 100644
index 0000000..b8530bd
--- /dev/null
+++ b/arch/nds32/include/asm/l2_cache.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef L2_CACHE_H
+#define L2_CACHE_H
+
+/* This is defined for head.S to use due to device tree is not yet built. */
+#define L2CC_PA_BASE		0x90F00000
+
+/* CCTL_CMD_OP */
+#define L2_CA_CONF_OFF		0x0
+#define	L2_IF_CONF_OFF		0x4
+#define L2CC_SETUP_OFF		0x8
+#define L2CC_PROT_OFF		0xC
+#define L2CC_CTRL_OFF		0x10
+#define L2_INT_EN_OFF           0x20
+#define L2_STA_OFF              0x24
+#define RDERR_ADDR_OFF		0x28
+#define WRERR_ADDR_OFF		0x2c
+#define EVDPTERR_ADDR_OFF	0x30
+#define IMPL3ERR_ADDR_OFF	0x34
+#define L2_CNT0_CTRL_OFF        0x40
+#define L2_EVNT_CNT0_OFF        0x44
+#define L2_CNT1_CTRL_OFF        0x48
+#define L2_EVNT_CNT1_OFF        0x4c
+#define L2_CCTL_CMD_OFF		0x60
+#define L2_CCTL_STATUS_OFF	0x64
+#define L2_LINE_TAG_OFF		0x68
+#define L2_LINE_DPT_OFF		0x70
+
+#define CCTL_CMD_L2_IX_INVAL    0x0
+#define CCTL_CMD_L2_PA_INVAL    0x1
+#define CCTL_CMD_L2_IX_WB       0x2
+#define CCTL_CMD_L2_PA_WB       0x3
+#define CCTL_CMD_L2_PA_WBINVAL  0x5
+#define CCTL_CMD_L2_SYNC        0xa
+
+/* CCTL_CMD_TYPE */
+#define CCTL_SINGLE_CMD         0
+#define CCTL_BLOCK_CMD          0x10
+#define CCTL_ALL_CMD		0x10
+
+/******************************************************************************
+ * L2_CA_CONF (Cache architecture configuration)
+ *****************************************************************************/
+#define L2_CA_CONF_offL2SET		0
+#define L2_CA_CONF_offL2WAY		4
+#define L2_CA_CONF_offL2CLSZ            8
+#define L2_CA_CONF_offL2DW		11
+#define L2_CA_CONF_offL2PT		14
+#define L2_CA_CONF_offL2VER		16
+
+#define L2_CA_CONF_mskL2SET	(0xFUL << L2_CA_CONF_offL2SET)
+#define L2_CA_CONF_mskL2WAY	(0xFUL << L2_CA_CONF_offL2WAY)
+#define L2_CA_CONF_mskL2CLSZ    (0x7UL << L2_CA_CONF_offL2CLSZ)
+#define L2_CA_CONF_mskL2DW	(0x7UL << L2_CA_CONF_offL2DW)
+#define L2_CA_CONF_mskL2PT	(0x3UL << L2_CA_CONF_offL2PT)
+#define L2_CA_CONF_mskL2VER	(0xFFFFUL << L2_CA_CONF_offL2VER)
+
+/******************************************************************************
+ * L2CC_SETUP (L2CC Setup register)
+ *****************************************************************************/
+#define L2CC_SETUP_offPART              0
+#define L2CC_SETUP_mskPART              (0x3UL << L2CC_SETUP_offPART)
+#define L2CC_SETUP_offDDLATC            4
+#define L2CC_SETUP_mskDDLATC            (0x3UL << L2CC_SETUP_offDDLATC)
+#define L2CC_SETUP_offTDLATC            8
+#define L2CC_SETUP_mskTDLATC            (0x3UL << L2CC_SETUP_offTDLATC)
+
+/******************************************************************************
+ * L2CC_PROT (L2CC Protect register)
+ *****************************************************************************/
+#define L2CC_PROT_offMRWEN              31
+#define L2CC_PROT_mskMRWEN      (0x1UL << L2CC_PROT_offMRWEN)
+
+/******************************************************************************
+ * L2_CCTL_STATUS_Mn (The L2CCTL command working status for Master n)
+ *****************************************************************************/
+#define L2CC_CTRL_offEN                 31
+#define L2CC_CTRL_mskEN                 (0x1UL << L2CC_CTRL_offEN)
+
+/******************************************************************************
+ * L2_CCTL_STATUS_Mn (The L2CCTL command working status for Master n)
+ *****************************************************************************/
+#define L2_CCTL_STATUS_offCMD_COMP      31
+#define L2_CCTL_STATUS_mskCMD_COMP      (0x1 << L2_CCTL_STATUS_offCMD_COMP)
+
+#ifndef __ASSEMBLY__
+extern void __iomem *atl2c_base;
+
+#include <linux/smp.h>
+#include <asm/io.h>
+#include <asm/bitfield.h>
+
+#define L2C_R_REG(offset)               __raw_readl(atl2c_base + offset)
+#define L2C_W_REG(offset, value)        __raw_writel(value, atl2c_base + offset)
+
+#define L2_CMD_RDY()    \
+        do{;}while((L2C_R_REG(L2_CCTL_STATUS_OFF) & L2_CCTL_STATUS_mskCMD_COMP) == 0)
+
+static inline unsigned long L2_CACHE_SET(void)
+{
+	return 64 << ((L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2SET) >>
+		      L2_CA_CONF_offL2SET);
+}
+
+static inline unsigned long L2_CACHE_WAY(void)
+{
+	return 1 +
+	    ((L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2WAY) >>
+	     L2_CA_CONF_offL2WAY);
+}
+
+static inline unsigned long L2_CACHE_LINE_SIZE(void)
+{
+
+	return 4 << ((L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2CLSZ) >>
+		     L2_CA_CONF_offL2CLSZ);
+}
+
+static inline unsigned long GET_L2CC_CTRL_CPU(unsigned long cpu)
+{
+	if (cpu == smp_processor_id())
+		return L2C_R_REG(L2CC_CTRL_OFF);
+	return L2C_R_REG(L2CC_CTRL_OFF + (cpu << 8));
+}
+
+static inline void SET_L2CC_CTRL_CPU(unsigned long cpu, unsigned long val)
+{
+	if (cpu == smp_processor_id())
+		L2C_W_REG(L2CC_CTRL_OFF, val);
+	else
+		L2C_W_REG(L2CC_CTRL_OFF + (cpu << 8), val);
+}
+
+static inline unsigned long GET_L2CC_STATUS_CPU(unsigned long cpu)
+{
+	if (cpu == smp_processor_id())
+		return L2C_R_REG(L2_CCTL_STATUS_OFF);
+	return L2C_R_REG(L2_CCTL_STATUS_OFF + (cpu << 8));
+}
+
+#endif
+
+#endif
diff --git a/arch/nds32/kernel/atl2c.c b/arch/nds32/kernel/atl2c.c
new file mode 100644
index 0000000..dd87fc9
--- /dev/null
+++ b/arch/nds32/kernel/atl2c.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/compiler.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+#include <asm/l2_cache.h>
+
+void __iomem *atl2c_base;
+static const struct of_device_id atl2c_ids[] __initconst = {
+	{.compatible = "andestech,atl2c",}
+};
+
+static int __init atl2c_of_init(void)
+{
+	struct device_node *np;
+	struct resource res;
+	unsigned long tmp = 0;
+	unsigned long l2set, l2way, l2clsz;
+
+	if (!(__nds32__mfsr(NDS32_SR_MSC_CFG) & MSC_CFG_mskL2C))
+		return -ENODEV;
+
+	np = of_find_matching_node(NULL, atl2c_ids);
+	if (!np)
+		return -ENODEV;
+
+	if (of_address_to_resource(np, 0, &res))
+		return -ENODEV;
+
+	atl2c_base = ioremap(res.start, resource_size(&res));
+	if (!atl2c_base)
+		return -ENOMEM;
+
+	l2set =
+	    64 << ((L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2SET) >>
+		   L2_CA_CONF_offL2SET);
+	l2way =
+	    1 +
+	    ((L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2WAY) >>
+	     L2_CA_CONF_offL2WAY);
+	l2clsz =
+	    4 << ((L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2CLSZ) >>
+		  L2_CA_CONF_offL2CLSZ);
+	pr_info("L2:%luKB/%luS/%luW/%luB\n",
+		l2set * l2way * l2clsz / 1024, l2set, l2way, l2clsz);
+
+	tmp = L2C_R_REG(L2CC_PROT_OFF);
+	tmp &= ~L2CC_PROT_mskMRWEN;
+	L2C_W_REG(L2CC_PROT_OFF, tmp);
+
+	tmp = L2C_R_REG(L2CC_SETUP_OFF);
+	tmp &= ~L2CC_SETUP_mskPART;
+	L2C_W_REG(L2CC_SETUP_OFF, tmp);
+
+	tmp = L2C_R_REG(L2CC_CTRL_OFF);
+	tmp |= L2CC_CTRL_mskEN;
+	L2C_W_REG(L2CC_CTRL_OFF, tmp);
+
+	return 0;
+}
+
+subsys_initcall(atl2c_of_init);
-- 
1.7.9.5

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

* [PATCH 21/31] nds32: Loadable modules
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (19 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 20/31] nds32: L2 cache support Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08  5:55 ` [PATCH 22/31] nds32: Generic timers support Greentime Hu
                   ` (11 subsequent siblings)
  32 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/asm/module.h |   24 ++++
 arch/nds32/kernel/module.c      |  299 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 323 insertions(+)
 create mode 100644 arch/nds32/include/asm/module.h
 create mode 100644 arch/nds32/kernel/module.c

diff --git a/arch/nds32/include/asm/module.h b/arch/nds32/include/asm/module.h
new file mode 100644
index 0000000..5ed2b75
--- /dev/null
+++ b/arch/nds32/include/asm/module.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _ASM_NDS32_MODULE_H
+#define _ASM_NDS32_MODULE_H
+
+#include <asm-generic/module.h>
+
+#define MODULE_ARCH_VERMAGIC	"NDS32v3"
+
+#endif /* _ASM_NDS32_MODULE_H */
diff --git a/arch/nds32/kernel/module.c b/arch/nds32/kernel/module.c
new file mode 100644
index 0000000..bb34e23
--- /dev/null
+++ b/arch/nds32/kernel/module.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+
+#include <asm/pgtable.h>
+
+void *module_alloc(unsigned long size)
+{
+	return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
+				    GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE,
+				    __builtin_return_address(0));
+}
+
+void module_free(struct module *module, void *region)
+{
+	vfree(region);
+}
+
+int module_frob_arch_sections(Elf_Ehdr * hdr,
+			      Elf_Shdr * sechdrs,
+			      char *secstrings, struct module *mod)
+{
+	return 0;
+}
+
+void do_reloc16(unsigned int val, unsigned int *loc, unsigned int val_mask,
+		unsigned int val_shift, unsigned int loc_mask,
+		unsigned int partial_in_place, unsigned int swap)
+{
+	unsigned int tmp = 0, tmp2 = 0;
+
+	__asm__ __volatile__("\tlhi.bi\t%0, [%2], 0\n"
+			     "\tbeqz\t%3, 1f\n"
+			     "\twsbh\t%0, %1\n"
+			     "1:\n":"=r"(tmp):"0"(tmp), "r"(loc), "r"(swap)
+	    );
+
+	tmp2 = tmp & loc_mask;
+	if (partial_in_place) {
+		tmp &= (!loc_mask);
+		tmp =
+		    tmp2 | ((tmp + ((val & val_mask) >> val_shift)) & val_mask);
+	} else {
+		tmp = tmp2 | ((val & val_mask) >> val_shift);
+	}
+
+	__asm__ __volatile__("\tbeqz\t%3, 2f\n"
+			     "\twsbh\t%0, %1\n"
+			     "2:\n"
+			     "\tshi.bi\t%0, [%2], 0\n":"=r"(tmp):"0"(tmp),
+			     "r"(loc), "r"(swap)
+	    );
+}
+
+void do_reloc32(unsigned int val, unsigned int *loc, unsigned int val_mask,
+		unsigned int val_shift, unsigned int loc_mask,
+		unsigned int partial_in_place, unsigned int swap)
+{
+	unsigned int tmp = 0, tmp2 = 0;
+
+	__asm__ __volatile__("\tlmw.bi\t%0, [%2], %0, 0\n"
+			     "\tbeqz\t%3, 1f\n"
+			     "\twsbh\t%0, %1\n"
+			     "\trotri\t%0, %1, 16\n"
+			     "1:\n":"=r"(tmp):"0"(tmp), "r"(loc), "r"(swap)
+	    );
+
+	tmp2 = tmp & loc_mask;
+	if (partial_in_place) {
+		tmp &= (!loc_mask);
+		tmp =
+		    tmp2 | ((tmp + ((val & val_mask) >> val_shift)) & val_mask);
+	} else {
+		tmp = tmp2 | ((val & val_mask) >> val_shift);
+	}
+
+	__asm__ __volatile__("\tbeqz\t%3, 2f\n"
+			     "\twsbh\t%0, %1\n"
+			     "\trotri\t%0, %1, 16\n"
+			     "2:\n"
+			     "\tsmw.bi\t%0, [%2], %0, 0\n":"=r"(tmp):"0"(tmp),
+			     "r"(loc), "r"(swap)
+	    );
+}
+
+static inline int exceed_limit(int offset, unsigned int val_mask,
+			       struct module *module, Elf32_Rela * rel,
+			       unsigned int relindex, unsigned int reloc_order)
+{
+	int abs_off = offset < 0 ? ~offset : offset;
+
+	if (abs_off & (~val_mask)) {
+		pr_err("\n%s: relocation type %d out of range.\n"
+		       "please rebuild the kernel module with gcc option \"-Wa,-mno-small-text\".\n",
+		       module->name, ELF32_R_TYPE(rel->r_info));
+		pr_err("section %d reloc %d offset 0x%x relative 0x%x.\n",
+		       relindex, reloc_order, rel->r_offset, offset);
+		return true;
+	}
+	return false;
+}
+
+#ifdef __NDS32_EL__
+#define NEED_SWAP 1
+#else
+#define NEED_SWAP 0
+#endif
+
+int
+apply_relocate_add(Elf32_Shdr * sechdrs, const char *strtab,
+		   unsigned int symindex, unsigned int relindex,
+		   struct module *module)
+{
+	Elf32_Shdr *symsec = sechdrs + symindex;
+	Elf32_Shdr *relsec = sechdrs + relindex;
+	Elf32_Shdr *dstsec = sechdrs + relsec->sh_info;
+	Elf32_Rela *rel = (void *)relsec->sh_addr;
+	unsigned int i;
+
+	for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rela); i++, rel++) {
+		Elf32_Addr *loc;
+		Elf32_Sym *sym;
+		Elf32_Addr v;
+		s32 offset;
+
+		offset = ELF32_R_SYM(rel->r_info);
+		if (offset < 0
+		    || offset > (symsec->sh_size / sizeof(Elf32_Sym))) {
+			pr_err("%s: bad relocation\n", module->name);
+			pr_err("section %d reloc %d\n", relindex, i);
+			return -ENOEXEC;
+		}
+
+		sym = ((Elf32_Sym *) symsec->sh_addr) + offset;
+
+		if (rel->r_offset < 0
+		    || rel->r_offset > dstsec->sh_size - sizeof(u16)) {
+			pr_err("%s: out of bounds relocation\n", module->name);
+			pr_err("section %d reloc %d offset 0x%0x size %d\n",
+			       relindex, i, rel->r_offset, dstsec->sh_size);
+			return -ENOEXEC;
+		}
+
+		loc = (Elf32_Addr *) (dstsec->sh_addr + rel->r_offset);
+		v = sym->st_value + rel->r_addend;
+
+		switch (ELF32_R_TYPE(rel->r_info)) {
+		case R_NDS32_NONE:
+		case R_NDS32_INSN16:
+		case R_NDS32_LABEL:
+		case R_NDS32_LONGCALL1:
+		case R_NDS32_LONGCALL2:
+		case R_NDS32_LONGCALL3:
+		case R_NDS32_LONGCALL4:
+		case R_NDS32_LONGJUMP1:
+		case R_NDS32_LONGJUMP2:
+		case R_NDS32_LONGJUMP3:
+		case R_NDS32_9_FIXED_RELA:
+		case R_NDS32_15_FIXED_RELA:
+		case R_NDS32_17_FIXED_RELA:
+		case R_NDS32_25_FIXED_RELA:
+		case R_NDS32_LOADSTORE:
+		case R_NDS32_DWARF2_OP1_RELA:
+		case R_NDS32_DWARF2_OP2_RELA:
+		case R_NDS32_DWARF2_LEB_RELA:
+		case R_NDS32_RELA_NOP_MIX ... R_NDS32_RELA_NOP_MAX:
+			break;
+
+		case R_NDS32_32_RELA:
+			do_reloc32(v, loc, 0xffffffff, 0, 0, 0, 0);
+			break;
+
+		case R_NDS32_HI20_RELA:
+			do_reloc32(v, loc, 0xfffff000, 12, 0xfff00000, 0,
+				   NEED_SWAP);
+			break;
+
+		case R_NDS32_LO12S3_RELA:
+			do_reloc32(v, loc, 0x00000fff, 3, 0xfffff000, 0,
+				   NEED_SWAP);
+			break;
+
+		case R_NDS32_LO12S2_RELA:
+			do_reloc32(v, loc, 0x00000fff, 2, 0xfffff000, 0,
+				   NEED_SWAP);
+			break;
+
+		case R_NDS32_LO12S1_RELA:
+			do_reloc32(v, loc, 0x00000fff, 1, 0xfffff000, 0,
+				   NEED_SWAP);
+			break;
+
+		case R_NDS32_LO12S0_RELA:
+		case R_NDS32_LO12S0_ORI_RELA:
+			do_reloc32(v, loc, 0x00000fff, 0, 0xfffff000, 0,
+				   NEED_SWAP);
+			break;
+
+		case R_NDS32_9_PCREL_RELA:
+			if (exceed_limit
+			    ((v - (Elf32_Addr) loc), 0x000000ff, module, rel,
+			     relindex, i))
+				return -ENOEXEC;
+			do_reloc16(v - (Elf32_Addr) loc, loc, 0x000001ff, 1,
+				   0xffffff00, 0, NEED_SWAP);
+			break;
+
+		case R_NDS32_15_PCREL_RELA:
+			if (exceed_limit
+			    ((v - (Elf32_Addr) loc), 0x00003fff, module, rel,
+			     relindex, i))
+				return -ENOEXEC;
+			do_reloc32(v - (Elf32_Addr) loc, loc, 0x00007fff, 1,
+				   0xffffc000, 0, NEED_SWAP);
+			break;
+
+		case R_NDS32_17_PCREL_RELA:
+			if (exceed_limit
+			    ((v - (Elf32_Addr) loc), 0x0000ffff, module, rel,
+			     relindex, i))
+				return -ENOEXEC;
+			do_reloc32(v - (Elf32_Addr) loc, loc, 0x0001ffff, 1,
+				   0xffff0000, 0, NEED_SWAP);
+			break;
+
+		case R_NDS32_25_PCREL_RELA:
+			if (exceed_limit
+			    ((v - (Elf32_Addr) loc), 0x00ffffff, module, rel,
+			     relindex, i))
+				return -ENOEXEC;
+			do_reloc32(v - (Elf32_Addr) loc, loc, 0x01ffffff, 1,
+				   0xff000000, 0, NEED_SWAP);
+			break;
+		case R_NDS32_WORD_9_PCREL_RELA:
+			if (exceed_limit
+			    ((v - (Elf32_Addr) loc), 0x000000ff, module, rel,
+			     relindex, i))
+				return -ENOEXEC;
+			do_reloc32(v - (Elf32_Addr) loc, loc, 0x000001ff, 1,
+				   0xffffff00, 0, NEED_SWAP);
+			break;
+
+		case R_NDS32_SDA15S3_RELA:
+		case R_NDS32_SDA15S2_RELA:
+		case R_NDS32_SDA15S1_RELA:
+		case R_NDS32_SDA15S0_RELA:
+			pr_err("%s: unsupported relocation type %d.\n",
+			       module->name, ELF32_R_TYPE(rel->r_info));
+			pr_err
+			    ("Small data section access doesn't work in the kernel space; "
+			     "please rebuild the kernel module with gcc option -mcmodel=large.\n");
+			pr_err("section %d reloc %d offset 0x%x size %d\n",
+			       relindex, i, rel->r_offset, dstsec->sh_size);
+			break;
+
+		default:
+			pr_err("%s: unsupported relocation type %d.\n",
+			       module->name, ELF32_R_TYPE(rel->r_info));
+			pr_err("section %d reloc %d offset 0x%x size %d\n",
+			       relindex, i, rel->r_offset, dstsec->sh_size);
+		}
+	}
+	return 0;
+}
+
+int
+apply_relocate(Elf32_Shdr * sechdrs, const char *strtab,
+	       unsigned int symindex, unsigned int relsec,
+	       struct module *module)
+{
+	return 0;
+}
+
+int
+module_finalize(const Elf32_Ehdr * hdr, const Elf_Shdr * sechdrs,
+		struct module *module)
+{
+	return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+}
-- 
1.7.9.5

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

* [PATCH 22/31] nds32: Generic timers support
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (20 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 21/31] nds32: Loadable modules Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08  5:55 ` [PATCH 23/31] nds32: Device tree support Greentime Hu
                   ` (10 subsequent siblings)
  32 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/kernel/time.c |   22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
 create mode 100644 arch/nds32/kernel/time.c

diff --git a/arch/nds32/kernel/time.c b/arch/nds32/kernel/time.c
new file mode 100644
index 0000000..96e2f87
--- /dev/null
+++ b/arch/nds32/kernel/time.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clocksource.h>
+
+void __init time_init(void)
+{
+	timer_probe();
+}
-- 
1.7.9.5

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

* [PATCH 23/31] nds32: Device tree support
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (21 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 22/31] nds32: Generic timers support Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08  9:53   ` Arnd Bergmann
  2017-11-08  5:55 ` [PATCH 24/31] nds32: Miscellaneous header files Greentime Hu
                   ` (9 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/boot/dts/Makefile   |    8 ++++++
 arch/nds32/boot/dts/ae3xx.dts  |   55 ++++++++++++++++++++++++++++++++++++
 arch/nds32/boot/dts/ag101p.dts |   60 ++++++++++++++++++++++++++++++++++++++++
 arch/nds32/kernel/devtree.c    |   45 ++++++++++++++++++++++++++++++
 4 files changed, 168 insertions(+)
 create mode 100644 arch/nds32/boot/dts/Makefile
 create mode 100644 arch/nds32/boot/dts/ae3xx.dts
 create mode 100644 arch/nds32/boot/dts/ag101p.dts
 create mode 100644 arch/nds32/kernel/devtree.c

diff --git a/arch/nds32/boot/dts/Makefile b/arch/nds32/boot/dts/Makefile
new file mode 100644
index 0000000..d31faa8
--- /dev/null
+++ b/arch/nds32/boot/dts/Makefile
@@ -0,0 +1,8 @@
+ifneq '$(CONFIG_NDS32_BUILTIN_DTB)' '""'
+BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_NDS32_BUILTIN_DTB)).dtb.o
+else
+BUILTIN_DTB :=
+endif
+obj-$(CONFIG_OF) += $(BUILTIN_DTB)
+
+clean-files := *.dtb *.dtb.S
diff --git a/arch/nds32/boot/dts/ae3xx.dts b/arch/nds32/boot/dts/ae3xx.dts
new file mode 100644
index 0000000..b6c85dc
--- /dev/null
+++ b/arch/nds32/boot/dts/ae3xx.dts
@@ -0,0 +1,55 @@
+/dts-v1/;
+/ {
+	compatible = "nds32 ae3xx";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&intc>;
+
+	chosen {
+		bootargs = "console=ttyS0,38400n8 earlyprintk=uart8250-32bit,0xf0300000 debug loglevel=7";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x00000000 0x40000000>;
+	};
+
+	cpus {
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "andestech,n13", "andestech,n15";
+		};
+	};
+
+	intc: interrupt-controller {
+		compatible = "andestech,ativic32";
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	serial0: serial@f0300000 {
+		compatible = "andestech,uart16550", "ns16550a";
+		reg = <0xf0300000 0x1000>;
+		interrupts = <8 4>;
+		clock-frequency = <14745600>;
+		reg-shift = <2>;
+		reg-offset = <32>;
+		no-loopback-test = <1>;
+	};
+
+	timer0: timer@f0400000 {
+		compatible = "andestech,atcpit100";
+		reg = <0xf0400000 0x1000>;
+		interrupts = <2 4>;
+		clock-frequency = <30000000>;
+		cycle-count-offset = <0x38>;
+		cycle-count-down;
+	};
+
+	mac0: mac@e0100000 {
+		compatible = "andestech,atmac100";
+		reg = <0xe0100000 0x1000>;
+		interrupts = <18 4>;
+	};
+
+};
diff --git a/arch/nds32/boot/dts/ag101p.dts b/arch/nds32/boot/dts/ag101p.dts
new file mode 100644
index 0000000..b34760b
--- /dev/null
+++ b/arch/nds32/boot/dts/ag101p.dts
@@ -0,0 +1,60 @@
+/dts-v1/;
+/ {
+	compatible = "nds32 ag101p";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&intc>;
+
+	chosen {
+		bootargs = "console=ttyS0,38400n8 earlyprintk=uart8250-32bit,0x99600000 debug loglevel=7";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x00000000 0x40000000>;
+	};
+
+	cpus {
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "andestech,n13";
+			next-level-cache = <&L2>;
+		};
+	};
+
+	intc: interrupt-controller {
+		compatible = "andestech,atnointc010";
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	serial0: serial@99600000 {
+		compatible = "andestech,uart16550", "ns16550a";
+		reg = <0x99600000 0x1000>;
+		interrupts = <7 4>;
+		clock-frequency = <14745600>;
+		reg-shift = <2>;
+		no-loopback-test = <1>;
+	};
+
+	timer0: timer@98400000 {
+		compatible = "andestech,atftmr010";
+		reg = <0x98400000 0x1000>;
+		interrupts = <19 4>;
+		clock-frequency = <15000000>;
+		cycle-count-offset = <0x20>;
+	};
+
+	mac0: mac@90900000 {
+		compatible = "andestech,atmac100";
+		reg = <0x90900000 0x1000>;
+		interrupts = <25 4>;
+	};
+
+	L2: l2-cache {
+		compatible = "andestech,atl2c";
+		reg = <0x90f00000 0x1000>;
+		cache-unified;
+		cache-level = <2>;
+	};
+};
diff --git a/arch/nds32/kernel/devtree.c b/arch/nds32/kernel/devtree.c
new file mode 100644
index 0000000..2af0f1c
--- /dev/null
+++ b/arch/nds32/kernel/devtree.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/memblock.h>
+#include <linux/of_fdt.h>
+#include <linux/bootmem.h>
+
+void __init early_init_dt_add_memory_arch(u64 base, u64 size)
+{
+	size &= PAGE_MASK;
+	memblock_add_node(base, size, 0);
+}
+
+void *__init early_init_dt_alloc_memory_arch(u64 size, u64 align)
+{
+	return alloc_bootmem_align(size, align);
+}
+
+void __init early_init_devtree(void *params)
+{
+	if (!params || !early_init_dt_scan(params)) {
+		pr_crit("\n"
+			"Error: invalid device tree blob at (virtual address 0x%p)\n"
+			"The dtb must be 8-byte aligned and must not exceed 8 KB in size\n"
+			"\nPlease check your bootloader.", params);
+
+		while (true)
+			cpu_relax();
+	}
+
+	dump_stack_set_arch_desc("%s (DT)", of_flat_dt_get_machine_name());
+}
-- 
1.7.9.5

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

* [PATCH 24/31] nds32: Miscellaneous header files
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (22 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 23/31] nds32: Device tree support Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08  9:57   ` Arnd Bergmann
  2017-11-08  5:55 ` [PATCH 25/31] nds32: defconfig Greentime Hu
                   ` (8 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/asm/delay.h            |   51 +++++++++++++++++++++++++++++
 arch/nds32/include/asm/linkage.h          |   24 ++++++++++++++
 arch/nds32/include/uapi/asm/byteorder.h   |   26 +++++++++++++++
 arch/nds32/include/uapi/asm/posix_types.h |   41 +++++++++++++++++++++++
 4 files changed, 142 insertions(+)
 create mode 100644 arch/nds32/include/asm/delay.h
 create mode 100644 arch/nds32/include/asm/linkage.h
 create mode 100644 arch/nds32/include/uapi/asm/byteorder.h
 create mode 100644 arch/nds32/include/uapi/asm/posix_types.h

diff --git a/arch/nds32/include/asm/delay.h b/arch/nds32/include/asm/delay.h
new file mode 100644
index 0000000..bdeeb76
--- /dev/null
+++ b/arch/nds32/include/asm/delay.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NDS32_DELAY_H__
+#define __NDS32_DELAY_H__
+
+#include <asm/param.h>
+
+static inline void __delay(unsigned long loops)
+{
+	__asm__ __volatile__(".align 2\n"
+			     "1:\n"
+			     "\taddi\t%0, %0, -1\n"
+			     "\tbgtz\t%0, 1b\n"
+			     :"=r"(loops)
+			     :"0"(loops));
+}
+
+static inline void __udelay(unsigned long usecs, unsigned long lpj)
+{
+	usecs *= (unsigned long)(((0x8000000000000000ULL / (500000 / HZ)) +
+				  0x80000000ULL) >> 32);
+	usecs = (unsigned long)(((unsigned long long)usecs * lpj) >> 32);
+	__delay(usecs);
+}
+
+#define udelay(usecs) __udelay((usecs), loops_per_jiffy)
+
+/* make sure "usecs *= ..." in udelay do not overflow. */
+#if HZ >= 1000
+#define MAX_UDELAY_MS	1
+#elif HZ <= 200
+#define MAX_UDELAY_MS	5
+#else
+#define MAX_UDELAY_MS	(1000 / HZ)
+#endif
+
+#endif
diff --git a/arch/nds32/include/asm/linkage.h b/arch/nds32/include/asm/linkage.h
new file mode 100644
index 0000000..d17abd8
--- /dev/null
+++ b/arch/nds32/include/asm/linkage.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+/* This file is required by include/linux/linkage.h */
+#define __ALIGN .align 2
+#define __ALIGN_STR ".align 2"
+
+#endif
diff --git a/arch/nds32/include/uapi/asm/byteorder.h b/arch/nds32/include/uapi/asm/byteorder.h
new file mode 100644
index 0000000..198e8dd
--- /dev/null
+++ b/arch/nds32/include/uapi/asm/byteorder.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __NDS32_BYTEORDER_H__
+#define __NDS32_BYTEORDER_H__
+
+#ifdef __NDS32_EB__
+#include <linux/byteorder/big_endian.h>
+#else
+#include <linux/byteorder/little_endian.h>
+#endif
+
+#endif /* __NDS32_BYTEORDER_H__ */
diff --git a/arch/nds32/include/uapi/asm/posix_types.h b/arch/nds32/include/uapi/asm/posix_types.h
new file mode 100644
index 0000000..d0aca66
--- /dev/null
+++ b/arch/nds32/include/uapi/asm/posix_types.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARCH_NDS32_POSIX_TYPES_H
+#define __ARCH_NDS32_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned short __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
+typedef unsigned short __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
+typedef unsigned short __kernel_uid_t;
+typedef unsigned short __kernel_gid_t;
+#define __kernel_uid_t __kernel_uid_t
+
+typedef unsigned short __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
+
+#include <asm-generic/posix_types.h>
+
+#endif
-- 
1.7.9.5

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

* [PATCH 25/31] nds32: defconfig
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (23 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 24/31] nds32: Miscellaneous header files Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08 10:03   ` Arnd Bergmann
  2017-11-08  5:55 ` [PATCH 26/31] nds32: Build infrastructure Greentime Hu
                   ` (7 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/configs/ae3xx_defconfig  |  110 +++++++++++++++++++++++++++++++++++
 arch/nds32/configs/ag101p_defconfig |  109 ++++++++++++++++++++++++++++++++++
 2 files changed, 219 insertions(+)
 create mode 100644 arch/nds32/configs/ae3xx_defconfig
 create mode 100644 arch/nds32/configs/ag101p_defconfig

diff --git a/arch/nds32/configs/ae3xx_defconfig b/arch/nds32/configs/ae3xx_defconfig
new file mode 100644
index 0000000..14d49a3
--- /dev/null
+++ b/arch/nds32/configs/ae3xx_defconfig
@@ -0,0 +1,110 @@
+CONFIG_CROSS_COMPILE="nds32le-linux-"
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+CONFIG_USER_NS=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_PROFILING=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_HWZOL is not set
+CONFIG_ANDES_PAGE_SIZE_8KB=y
+CONFIG_NDS32_BUILTIN_DTB="ae3xx"
+CONFIG_PREEMPT=y
+# CONFIG_COMPACTION is not set
+CONFIG_HZ_100=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_BRIDGE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+CONFIG_FTMAC100=y
+# 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_SEEQ is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_SERIO 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=3
+CONFIG_SERIAL_8250_RUNTIME_UARTS=3
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_FB=y
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_HCTOSYS is not set
+CONFIG_CLKSRC_ATCPIT100=y
+CONFIG_EXT2_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_USE_LEGACY_DNS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_DWARF4=y
+CONFIG_GDB_SCRIPTS=y
+CONFIG_READABLE_ASM=y
+CONFIG_HEADERS_CHECK=y
+CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_PANIC_ON_OOPS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_STACKTRACE=y
+CONFIG_RCU_CPU_STALL_TIMEOUT=300
+# CONFIG_CRYPTO_HW is not set
diff --git a/arch/nds32/configs/ag101p_defconfig b/arch/nds32/configs/ag101p_defconfig
new file mode 100644
index 0000000..0641a97
--- /dev/null
+++ b/arch/nds32/configs/ag101p_defconfig
@@ -0,0 +1,109 @@
+CONFIG_CROSS_COMPILE="nds32le-linux-"
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+CONFIG_USER_NS=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_PROFILING=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_HWZOL is not set
+CONFIG_NDS32_BUILTIN_DTB="ag101p"
+CONFIG_PREEMPT=y
+# CONFIG_COMPACTION is not set
+CONFIG_HZ_100=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_BRIDGE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+CONFIG_FTMAC100=y
+# 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_SEEQ is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_SERIO 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=3
+CONFIG_SERIAL_8250_RUNTIME_UARTS=3
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_FB=y
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_HCTOSYS is not set
+CONFIG_CLKSRC_ATFMR010=y
+CONFIG_EXT2_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_USE_LEGACY_DNS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_DWARF4=y
+CONFIG_GDB_SCRIPTS=y
+CONFIG_READABLE_ASM=y
+CONFIG_HEADERS_CHECK=y
+CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_PANIC_ON_OOPS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_STACKTRACE=y
+CONFIG_RCU_CPU_STALL_TIMEOUT=300
+# CONFIG_CRYPTO_HW is not set
-- 
1.7.9.5

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

* [PATCH 26/31] nds32: Build infrastructure
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (24 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 25/31] nds32: defconfig Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08 10:16   ` Arnd Bergmann
  2017-11-08  5:55 ` [PATCH 27/31] dt-bindings: interrupt-controller: Andestech Internal Vector Interrupt Controller Greentime Hu
                   ` (6 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/Kconfig                 |  107 ++++++++++++++++++++++++++++++++++++
 arch/nds32/Kconfig.cpu             |  100 +++++++++++++++++++++++++++++++++
 arch/nds32/Kconfig.debug           |   14 +++++
 arch/nds32/Makefile                |   60 ++++++++++++++++++++
 arch/nds32/boot/Makefile           |   15 +++++
 arch/nds32/include/asm/Kbuild      |   54 ++++++++++++++++++
 arch/nds32/include/uapi/asm/Kbuild |   26 +++++++++
 arch/nds32/kernel/Makefile         |   24 ++++++++
 arch/nds32/kernel/vmlinux.lds.S    |   70 +++++++++++++++++++++++
 arch/nds32/mm/Makefile             |    7 +++
 10 files changed, 477 insertions(+)
 create mode 100644 arch/nds32/Kconfig
 create mode 100644 arch/nds32/Kconfig.cpu
 create mode 100644 arch/nds32/Kconfig.debug
 create mode 100644 arch/nds32/Makefile
 create mode 100644 arch/nds32/boot/Makefile
 create mode 100644 arch/nds32/include/asm/Kbuild
 create mode 100644 arch/nds32/include/uapi/asm/Kbuild
 create mode 100644 arch/nds32/kernel/Makefile
 create mode 100644 arch/nds32/kernel/vmlinux.lds.S
 create mode 100644 arch/nds32/mm/Makefile

diff --git a/arch/nds32/Kconfig b/arch/nds32/Kconfig
new file mode 100644
index 0000000..112f470
--- /dev/null
+++ b/arch/nds32/Kconfig
@@ -0,0 +1,107 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+
+config NDS32
+        def_bool y
+	select ARCH_HAS_RAW_COPY_USER
+	select ARCH_WANT_FRAME_POINTERS if FTRACE
+	select ARCH_WANT_IPC_PARSE_VERSION
+	select CLKSRC_MMIO
+	select CLONE_BACKWARDS
+	select TIMER_OF
+	select FRAME_POINTER
+	select GENERIC_ATOMIC64
+	select GENERIC_CPU_DEVICES
+	select GENERIC_CLOCKEVENTS
+	select GENERIC_IOMAP
+	select GENERIC_IRQ_CHIP
+	select GENERIC_IRQ_PROBE
+	select GENERIC_IRQ_SHOW
+	select GENERIC_STRNCPY_FROM_USER
+	select GENERIC_STRNLEN_USER
+	select GENERIC_TIME_VSYSCALL
+	select HAVE_ARCH_TRACEHOOK
+	select HAVE_GENERIC_IOMAP
+	select HAVE_DEBUG_KMEMLEAK
+	select HAVE_IDE
+	select HAVE_MEMBLOCK
+	select HAVE_MEMBLOCK_NODE_MAP
+	select HAVE_UID16
+	select HAVE_REGS_AND_STACK_ACCESS_API
+	select IRQ_DOMAIN
+	select LOCKDEP_SUPPORT
+	select MODULES_USE_ELF_REL
+	select MODULES_USE_ELF_RELA
+	select OF
+	select OF_EARLY_FLATTREE
+	select OLD_SIGACTION
+	select OLD_SIGSUSPEND3
+	select NO_IOPORT_MAP
+	select RTC_LIB
+	select THREAD_INFO_IN_TASK
+	select SYS_SUPPORTS_APM_EMULATION
+	help
+	  Andes(nds32) Linux support.
+
+config GENERIC_CALIBRATE_DELAY
+	def_bool y
+
+config GENERIC_CSUM
+        def_bool y
+
+config GENERIC_HWEIGHT
+        def_bool y
+
+config GENERIC_LOCKBREAK
+        def_bool y
+	depends on PREEMPT
+
+config RWSEM_GENERIC_SPINLOCK
+	def_bool y
+
+config TRACE_IRQFLAGS_SUPPORT
+	def_bool y
+
+config STACKTRACE_SUPPORT
+        def_bool y
+
+config PGTABLE_LEVELS
+	default 2
+
+source "init/Kconfig"
+
+menu "System Type"
+source "arch/nds32/Kconfig.cpu"
+config NR_CPUS
+	int
+	default 1
+
+config MMU
+        def_bool y
+
+config NDS32_BUILTIN_DTB
+        string "Builtin DTB"
+        default ""
+	help
+	  User can use it to specify the dts of the SoC
+endmenu
+
+menu "Kernel Features"
+source "kernel/Kconfig.preempt"
+source "mm/Kconfig"
+source "kernel/Kconfig.hz"
+endmenu
+
+menu "Executable file formats"
+source "fs/Kconfig.binfmt"
+endmenu
+
+source "net/Kconfig"
+source "drivers/Kconfig"
+source "fs/Kconfig"
+source "arch/nds32/Kconfig.debug"
+source "security/Kconfig"
+source "crypto/Kconfig"
+source "lib/Kconfig"
diff --git a/arch/nds32/Kconfig.cpu b/arch/nds32/Kconfig.cpu
new file mode 100644
index 0000000..40eaa97
--- /dev/null
+++ b/arch/nds32/Kconfig.cpu
@@ -0,0 +1,100 @@
+comment "Processor Features"
+config HWZOL
+	bool "hardware zero overhead loop support"
+	default y
+	help
+	  A set of Zero-Overhead Loop mechanism is provided to reduce the
+	  instruction fetch and execution overhead of loop-control instructions.
+	  It will save 3 registers($LB, $LC, $LE) for context saving if say Y.
+	  You don't need to save these registers if you can make sure your user
+	  program doesn't use these registers.
+
+	  If unsure, say N.
+
+config CPU_CACHE_NONALIASING
+	bool "Non-aliasing cache"
+	help
+	  If this CPU is using VIPT data cache and its cache way size is larger
+	  than page size, say N. If it is using PIPT data cache, say Y.
+
+	  If unsure, say Y.
+
+choice
+	prompt "Paging -- page size "
+	default ANDES_PAGE_SIZE_4KB
+config  ANDES_PAGE_SIZE_4KB
+	bool "use 4KB page size"
+config  ANDES_PAGE_SIZE_8KB
+	bool "use 8KB page size"
+endchoice
+
+config CPU_ICACHE_DISABLE
+	bool "Disable I-Cache"
+	help
+	  Say Y here to disable the processor instruction cache. Unless
+	  you have a reason not to or are unsure, say N.
+
+config CPU_DCACHE_DISABLE
+	bool "Disable D-Cache"
+	help
+	  Say Y here to disable the processor data cache. Unless
+	  you have a reason not to or are unsure, say N.
+
+config CPU_DCACHE_WRITETHROUGH
+	bool "Force write through D-cache"
+	depends on !CPU_DCACHE_DISABLE
+	help
+	  Say Y here to use the data cache in writethrough mode. Unless you
+	  specifically require this or are unsure, say N.
+
+config WBNA
+	bool "WBNA"
+	default n
+	help
+	  Say Y here to enable write-back memory with no-write-allocation policy.
+
+config ALIGNMENT_TRAP
+	tristate "Kernel support unaligned access handling"
+	default y
+	help
+	  Andes processors cannot fetch/store information which is not
+	  naturally aligned on the bus, i.e., a 4 byte fetch must start at an
+	  address divisible by 4. On 32-bit Andes processors, these non-aligned
+	  fetch/store instructions will be emulated in software if you say
+	  here, which has a severe performance impact. This is necessary for
+	  correct operation of some network protocols. With an IP-only
+	  configuration it is safe to say N, otherwise say Y.
+
+config HIGHMEM
+	bool "High Memory Support"
+	depends on MMU && CPU_CACHE_NONALIASING
+	help
+	  The address space of Andes processors is only 4 Gigabytes large
+	  and it has to accommodate user address space, kernel address
+	  space as well as some memory mapped IO. That means that, if you
+	  have a large amount of physical memory and/or IO, not all of the
+	  memory can be "permanently mapped" by the kernel. The physical
+	  memory that is not permanently mapped is called "high memory".
+
+	  Depending on the selected kernel/user memory split, minimum
+	  vmalloc space and actual amount of RAM, you may not need this
+	  option which should result in a slightly faster kernel.
+
+	  If unsure, say N.
+
+config CACHE_L2
+	bool "Support L2 cache"
+        default y
+	help
+	  Say Y here to enable L2 cache if your SoC are integrated with L2CC.
+	  If unsure, say N.
+
+menu "Memory configuration"
+
+config MEMORY_START
+	hex "Physical memory start address"
+	default "0x00000000"
+	help
+	  Physical memory start address, you may modify it if it is porting to
+	  a new SoC with different start address.
+endmenu
diff --git a/arch/nds32/Kconfig.debug b/arch/nds32/Kconfig.debug
new file mode 100644
index 0000000..665da0a
--- /dev/null
+++ b/arch/nds32/Kconfig.debug
@@ -0,0 +1,14 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config EARLY_PRINTK
+        bool "Early printk support"
+        default y
+        help
+          Say Y here if you want to have an early console using the
+          earlyprintk=<name>[,<addr>][,<options>] kernel parameter. It
+          is assumed that the early console device has been initialised
+          by the boot loader prior to starting the Linux kernel.
+
+endmenu
diff --git a/arch/nds32/Makefile b/arch/nds32/Makefile
new file mode 100644
index 0000000..1bef714
--- /dev/null
+++ b/arch/nds32/Makefile
@@ -0,0 +1,60 @@
+LDFLAGS_vmlinux	:= --no-undefined -X
+OBJCOPYFLAGS	:= -O binary -R .note -R .note.gnu.build-id -R .comment -S
+
+KBUILD_DEFCONFIG := ae3xx_defconfig
+
+comma = ,
+
+KBUILD_CFLAGS	+=-mno-sched-prolog-epilog -mcmodel=large
+
+KBUILD_CFLAGS	+=$(arch-y) $(tune-y)
+KBUILD_AFLAGS	+=$(arch-y) $(tune-y)
+
+#Default value
+head-y		 := arch/nds32/kernel/head.o
+textaddr-y	 := 0xc000c000
+
+TEXTADDR := $(textaddr-y)
+
+export	TEXTADDR
+
+
+# If we have a machine-specific directory, then include it in the build.
+core-y				+= arch/nds32/kernel/ arch/nds32/mm/
+libs-y				+= arch/nds32/lib/
+LIBGCC_PATH     		:= \
+  $(shell $(CC) $(KBUILD_CFLAGS) $(KCFLAGS) -print-libgcc-file-name)
+libs-y				+= $(LIBGCC_PATH)
+
+ifneq '$(CONFIG_NDS32_BUILTIN_DTB)' '""'
+BUILTIN_DTB := y
+else
+BUILTIN_DTB := n
+endif
+
+boot := arch/nds32/boot
+core-$(BUILTIN_DTB) += $(boot)/dts/
+
+.PHONY: FORCE
+
+Image: vmlinux
+	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+
+PHONY += vdso_install
+vdso_install:
+	$(Q)$(MAKE) $(build)=arch/nds32/kernel/vdso $@
+
+prepare: vdso_prepare
+vdso_prepare: prepare0
+	$(Q)$(MAKE) $(build)=arch/nds32/kernel/vdso include/generated/vdso-offsets.h
+
+CLEAN_FILES += include/asm-nds32/constants.h*
+
+# We use MRPROPER_FILES and CLEAN_FILES now
+archclean:
+	$(Q)$(MAKE) $(clean)=$(boot)
+
+define archhelp
+  echo  '  Image         - kernel image (arch/$(ARCH)/boot/Image)'
+endef
diff --git a/arch/nds32/boot/Makefile b/arch/nds32/boot/Makefile
new file mode 100644
index 0000000..3f9b86f
--- /dev/null
+++ b/arch/nds32/boot/Makefile
@@ -0,0 +1,15 @@
+targets := Image Image.gz
+
+$(obj)/Image: vmlinux FORCE
+	$(call if_changed,objcopy)
+
+$(obj)/Image.gz: $(obj)/Image FORCE
+	$(call if_changed,gzip)
+
+install: $(obj)/Image
+	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
+	$(obj)/Image System.map "$(INSTALL_PATH)"
+
+zinstall: $(obj)/Image.gz
+	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
+	$(obj)/Image.gz System.map "$(INSTALL_PATH)"
diff --git a/arch/nds32/include/asm/Kbuild b/arch/nds32/include/asm/Kbuild
new file mode 100644
index 0000000..414ca9d
--- /dev/null
+++ b/arch/nds32/include/asm/Kbuild
@@ -0,0 +1,54 @@
+generic-y += asm-offsets.h
+generic-y += atomic.h
+generic-y += barrier.h
+generic-y += bitops.h
+generic-y += bitsperlong.h
+generic-y += bug.h
+generic-y += bugs.h
+generic-y += checksum.h
+generic-y += clkdev.h
+generic-y += cmpxchg.h
+generic-y += cmpxchg-local.h
+generic-y += cputime.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 += fcntl.h
+generic-y += ftrace.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.h
+generic-y += irq_regs.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 += limits.h
+generic-y += local.h
+generic-y += mm-arch-hooks.h
+generic-y += mman.h
+generic-y += parport.h
+generic-y += pci.h
+generic-y += percpu.h
+generic-y += preempt.h
+generic-y += sections.h
+generic-y += segment.h
+generic-y += serial.h
+generic-y += shmbuf.h
+generic-y += sizes.h
+generic-y += stat.h
+generic-y += switch_to.h
+generic-y += timex.h
+generic-y += topology.h
+generic-y += trace_clock.h
+generic-y += unaligned.h
+generic-y += user.h
+generic-y += word-at-a-time.h
diff --git a/arch/nds32/include/uapi/asm/Kbuild b/arch/nds32/include/uapi/asm/Kbuild
new file mode 100644
index 0000000..c3911f5
--- /dev/null
+++ b/arch/nds32/include/uapi/asm/Kbuild
@@ -0,0 +1,26 @@
+# UAPI Header export list
+include include/uapi/asm-generic/Kbuild.asm
+
+generic-y += errno.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += ipcbuf.h
+generic-y += shmbuf.h
+generic-y += bitsperlong.h
+generic-y += fcntl.h
+generic-y += stat.h
+generic-y += mman.h
+generic-y += msgbuf.h
+generic-y += poll.h
+generic-y += resource.h
+generic-y += sembuf.h
+generic-y += setup.h
+generic-y += siginfo.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += swab.h
+generic-y += statfs.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += types.h
+generic-y += ucontext.h
diff --git a/arch/nds32/kernel/Makefile b/arch/nds32/kernel/Makefile
new file mode 100644
index 0000000..5abcb0d
--- /dev/null
+++ b/arch/nds32/kernel/Makefile
@@ -0,0 +1,24 @@
+#
+# Makefile for the linux kernel.
+#
+
+CPPFLAGS_vmlinux.lds	:= -DTEXTADDR=$(TEXTADDR)
+AFLAGS_head.o		:= -DTEXTADDR=$(TEXTADDR)
+
+# Object file lists.
+
+obj-y			:= ex-entry.o ex-exit.o ex-scall.o irq.o \
+			process.o ptrace.o setup.o signal.o \
+			sys_nds32.o time.o traps.o cacheinfo.o \
+			dma.o syscall_table.o vdso.o
+
+obj-$(CONFIG_MODULES)		+= nds32_ksyms.o module.o
+obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
+obj-$(CONFIG_OF)		+= devtree.o
+obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
+obj-$(CONFIG_CACHE_L2)		+= atl2c.o
+
+extra-y := head.o vmlinux.lds
+
+
+obj-y				+= vdso/
diff --git a/arch/nds32/kernel/vmlinux.lds.S b/arch/nds32/kernel/vmlinux.lds.S
new file mode 100644
index 0000000..2b1e55d
--- /dev/null
+++ b/arch/nds32/kernel/vmlinux.lds.S
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <asm/page.h>
+#include <asm/thread_info.h>
+#include <asm/cache.h>
+#include <asm/memory.h>
+
+#define LOAD_OFFSET	(PAGE_OFFSET - PHYS_OFFSET)
+#include <asm-generic/vmlinux.lds.h>
+
+OUTPUT_ARCH(nds32)
+ENTRY(_stext_lma)
+jiffies = jiffies_64;
+
+SECTIONS
+{
+	_stext_lma = TEXTADDR - LOAD_OFFSET;
+	. = TEXTADDR;
+	__init_begin = .;
+	HEAD_TEXT_SECTION
+	INIT_TEXT_SECTION(PAGE_SIZE)
+	INIT_DATA_SECTION(16)
+	PERCPU_SECTION(L1_CACHE_BYTES)
+	__init_end = .;
+
+	. = ALIGN(PAGE_SIZE);
+	_stext = .;
+	/* Real text segment */
+	.text : AT(ADDR(.text) - LOAD_OFFSET) {
+		_text = .;		/* Text and read-only data	*/
+		TEXT_TEXT
+		SCHED_TEXT
+		CPUIDLE_TEXT
+		LOCK_TEXT
+		KPROBES_TEXT
+		IRQENTRY_TEXT
+		*(.fixup)
+	}
+
+	_etext = .;			/* End of text and rodata section */
+
+	_sdata = .;
+	RO_DATA_SECTION(PAGE_SIZE)
+	RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
+	_edata  =  .;
+
+	EXCEPTION_TABLE(16)
+	NOTES
+	BSS_SECTION(4, 4, 4)
+	_end = .;
+
+	STABS_DEBUG
+	DWARF_DEBUG
+
+	DISCARDS
+}
diff --git a/arch/nds32/mm/Makefile b/arch/nds32/mm/Makefile
new file mode 100644
index 0000000..278d28f
--- /dev/null
+++ b/arch/nds32/mm/Makefile
@@ -0,0 +1,7 @@
+obj-y				:= extable.o tlb.o \
+				   fault.o init.o ioremap.o mmap.o \
+                                   mm-nds32.o cacheflush.o proc-n13.o
+
+obj-$(CONFIG_ALIGNMENT_TRAP)	+= alignment.o
+obj-$(CONFIG_HIGHMEM)           += highmem.o
+CFLAGS_proc-n13.o		+= -fomit-frame-pointer
-- 
1.7.9.5

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

* [PATCH 27/31] dt-bindings: interrupt-controller: Andestech Internal Vector Interrupt Controller
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (25 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 26/31] nds32: Build infrastructure Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08 13:25   ` Rob Herring
  2017-11-08  5:55 ` [PATCH 28/31] irqchip: Andestech Internal Vector Interrupt Controller driver Greentime Hu
                   ` (5 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Rick Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Rick Chen <rick@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 .../interrupt-controller/andestech,ativic32.txt    |   27 ++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt

diff --git a/Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt b/Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt
new file mode 100644
index 0000000..6bac908
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt
@@ -0,0 +1,27 @@
+* Andestech Internal Vector Interrupt Controller
+
+The Internal Vector Interrupt Controller (IVIC) is a basic interrupt controller
+suitable for a simpler SoC platform not requiring a more sophisticated and
+bigger External Vector Interrupt Controller.
+
+
+Main node required properties:
+
+- compatible : should at least contain  "andestech,ativic32".
+- interrupt-parent: Empty for the interrupt controller itself
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells: The number of cells to define the interrupts. Should be 2.
+	The first cell is the IRQ number
+	The second cell is used to specify mode:
+		1 = low-to-high edge triggered
+		2 = high-to-low edge triggered
+		4 = active high level-sensitive
+		8 = active low level-sensitive
+		Default for internal sources should be set to 4 (active high).
+
+Examples:
+	intc: interrupt-controller {
+		compatible = "andestech,ativic32";
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
-- 
1.7.9.5

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

* [PATCH 28/31] irqchip: Andestech Internal Vector Interrupt Controller driver
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (26 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 27/31] dt-bindings: interrupt-controller: Andestech Internal Vector Interrupt Controller Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08 14:24   ` Marc Zyngier
  2017-11-08  5:55 ` [PATCH 29/31] MAINTAINERS: Add nds32 Greentime Hu
                   ` (4 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Rick Chen

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Rick Chen <rick@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 drivers/irqchip/Makefile       |    1 +
 drivers/irqchip/irq-ativic32.c |  149 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 150 insertions(+)
 create mode 100644 drivers/irqchip/irq-ativic32.c

diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index b842dfd..201ca9f 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -80,3 +80,4 @@ obj-$(CONFIG_ARCH_ASPEED)		+= irq-aspeed-vic.o irq-aspeed-i2c-ic.o
 obj-$(CONFIG_STM32_EXTI) 		+= irq-stm32-exti.o
 obj-$(CONFIG_QCOM_IRQ_COMBINER)		+= qcom-irq-combiner.o
 obj-$(CONFIG_IRQ_UNIPHIER_AIDET)	+= irq-uniphier-aidet.o
+obj-$(CONFIG_NDS32)			+= irq-ativic32.o
diff --git a/drivers/irqchip/irq-ativic32.c b/drivers/irqchip/irq-ativic32.c
new file mode 100644
index 0000000..d3dae59
--- /dev/null
+++ b/drivers/irqchip/irq-ativic32.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip.h>
+#include <nds32_intrinsic.h>
+
+static void ativic32_ack_irq(struct irq_data *data)
+{
+	__nds32__mtsr_dsb(1 << data->hwirq, NDS32_SR_INT_PEND2);
+}
+
+static void ativic32_mask_irq(struct irq_data *data)
+{
+	unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2);
+	__nds32__mtsr_dsb(int_mask2 & (~(1 << data->hwirq)), NDS32_SR_INT_MASK2);
+}
+
+static void ativic32_mask_ack_irq(struct irq_data *data)
+{
+	unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2);
+	__nds32__mtsr_dsb(int_mask2 & (~(1 << data->hwirq)), NDS32_SR_INT_MASK2);
+	__nds32__mtsr_dsb((1 << data->hwirq), NDS32_SR_INT_PEND2);
+
+}
+
+static void ativic32_unmask_irq(struct irq_data *data)
+{
+	unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2);
+	__nds32__mtsr_dsb(int_mask2 | (1 << data->hwirq), NDS32_SR_INT_MASK2);
+}
+
+static int ativic32_set_type(struct irq_data *data, unsigned int flow_type)
+{
+	printk(KERN_WARNING "interrupt type is not configurable\n");
+	return 0;
+}
+
+static struct irq_chip ativic32_chip = {
+	.name = "ativic32",
+	.irq_ack = ativic32_ack_irq,
+	.irq_mask = ativic32_mask_irq,
+	.irq_mask_ack = ativic32_mask_ack_irq,
+	.irq_unmask = ativic32_unmask_irq,
+	.irq_set_type = ativic32_set_type,
+};
+
+static unsigned int __initdata nivic_map[6] = { 6, 2, 10, 16, 24, 32 };
+
+struct irq_domain *root_domain;
+static int ativic32_irq_domain_map(struct irq_domain *id, unsigned int virq,
+				  irq_hw_number_t hw)
+{
+
+	unsigned long int_trigger_type;
+	int_trigger_type = __nds32__mfsr(NDS32_SR_INT_TRIGGER);
+	if (int_trigger_type & (1 << hw))
+		irq_set_chip_and_handler(virq, &ativic32_chip, handle_edge_irq);
+	else
+		irq_set_chip_and_handler(virq, &ativic32_chip, handle_level_irq);
+
+	return 0;
+}
+
+static struct irq_domain_ops ativic32_ops = {
+	.map = ativic32_irq_domain_map,
+	.xlate = irq_domain_xlate_onecell
+};
+
+static int get_intr_src(void)
+{
+	return ((__nds32__mfsr(NDS32_SR_ITYPE)&ITYPE_mskVECTOR) >> ITYPE_offVECTOR)
+		- NDS32_VECTOR_offINTERRUPT;
+}
+
+asmlinkage void asm_do_IRQ(struct pt_regs *regs)
+{
+	struct pt_regs *old_regs = set_irq_regs(regs);
+	int virq;
+	int irq = get_intr_src();
+
+	/*
+	 * Some hardware gives randomly wrong interrupts.  Rather
+	 * than crashing, do something sensible.
+	 */
+	if (unlikely(irq >= NR_IRQS)) {
+		pr_emerg( "IRQ exceeds NR_IRQS\n");
+		BUG();
+	}
+
+	irq_enter();
+	virq = irq_find_mapping(root_domain, irq);
+	generic_handle_irq(virq);
+	irq_exit();
+	set_irq_regs(old_regs);
+
+}
+
+int __init ativic32_init_irq(struct device_node *node, struct device_node *parent)
+{
+	unsigned long int_vec_base, nivic, i;
+
+	if (WARN(parent, "non-root ativic32 are not supported"))
+		return -EINVAL;
+
+	int_vec_base = __nds32__mfsr(NDS32_SR_IVB);
+
+	if (((int_vec_base & IVB_mskIVIC_VER) >> IVB_offIVIC_VER) == 0) {
+		panic("Unable to use NOINTC option to boot on this cpu\n");
+	}
+
+	nivic = (int_vec_base & IVB_mskNIVIC) >> IVB_offNIVIC;
+	if (nivic >= (sizeof nivic_map / sizeof nivic_map[0])) {
+		panic
+		    ("The number of input for IVIC Controller is not supported on this cpu\n");
+	}
+	nivic = nivic_map[nivic];
+
+	root_domain = irq_domain_add_linear(node, nivic,
+			&ativic32_ops, NULL);
+
+	if (!root_domain)
+		panic("%s: unable to create IRQ domain\n", node->full_name);
+
+	for(i = 0; i < nivic; i++)
+		irq_create_mapping(root_domain, i);
+
+	return 0;
+
+}
+IRQCHIP_DECLARE(ativic32, "andestech,ativic32", ativic32_init_irq);
-- 
1.7.9.5

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

* [PATCH 29/31] MAINTAINERS: Add nds32
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (27 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 28/31] irqchip: Andestech Internal Vector Interrupt Controller driver Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08 13:31   ` Rob Herring
  2017-11-08  5:55 ` [PATCH 30/31] dt-bindings: nds32 CPU Bindings Greentime Hu
                   ` (3 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 MAINTAINERS |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 2f4e462..bce1181 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -857,6 +857,15 @@ X:	drivers/iio/*/adjd*
 F:	drivers/staging/iio/*/ad*
 F:	drivers/staging/iio/trigger/iio-trig-bfin-timer.c
 
+ANDES ARCHITECTURE
+M:	Greentime Hu <green.hu@gmail.com>
+M:	Vincent Chen <deanbo422@gmail.com>
+T:	git https://github.com/andestech/linux.git
+S:	Supported
+F:	arch/nds32
+K:	nds32
+N:	nds32
+
 ANDROID CONFIG FRAGMENTS
 M:	Rob Herring <robh@kernel.org>
 S:	Supported
-- 
1.7.9.5

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

* [PATCH 30/31] dt-bindings: nds32 CPU Bindings
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (28 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 29/31] MAINTAINERS: Add nds32 Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08 13:18   ` Rob Herring
  2017-11-08  5:55 ` [PATCH 31/31] net: faraday add nds32 support Greentime Hu
                   ` (2 subsequent siblings)
  32 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu, Vincent Chen, Rick Chen, Zong Li

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Rick Chen <rick@andestech.com>
Signed-off-by: Zong Li <zong@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 Documentation/devicetree/bindings/nds32/cpus.txt |   33 ++++++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nds32/cpus.txt

diff --git a/Documentation/devicetree/bindings/nds32/cpus.txt b/Documentation/devicetree/bindings/nds32/cpus.txt
new file mode 100644
index 0000000..97394cb
--- /dev/null
+++ b/Documentation/devicetree/bindings/nds32/cpus.txt
@@ -0,0 +1,33 @@
+* Andestech Processor Binding
+
+This binding specifies what properties must be available in the device tree
+representation of a Andestech Processor Core, which is the root node in the
+tree.
+
+Required properties:
+
+	- compatible:
+		Usage: required
+		Value type: <string>
+		Definition: should be one of:
+			"andestech,n13"
+			"andestech,n15"
+			"andestech,d15"
+			"andestech,n10"
+			"andestech,d10"
+
+    - device_type
+		Usage: required
+		Value type: <string>
+		Definition: must be "cpu"
+
+* Examples
+
+/ {
+	cpus {
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "andestech,n13", "andestech,n15";
+		};
+	};
+};
-- 
1.7.9.5

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

* [PATCH 31/31] net: faraday add nds32 support.
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (29 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 30/31] dt-bindings: nds32 CPU Bindings Greentime Hu
@ 2017-11-08  5:55 ` Greentime Hu
  2017-11-08  8:32 ` [PATCH 00/31] Andes(nds32) Linux Kernel Port David Howells
  2017-11-08 10:26 ` Arnd Bergmann
  32 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  5:55 UTC (permalink / raw)
  To: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev
  Cc: green.hu

From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 drivers/net/ethernet/faraday/Kconfig |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/faraday/Kconfig b/drivers/net/ethernet/faraday/Kconfig
index 040c7f1..0ae6e9a 100644
--- a/drivers/net/ethernet/faraday/Kconfig
+++ b/drivers/net/ethernet/faraday/Kconfig
@@ -5,7 +5,7 @@
 config NET_VENDOR_FARADAY
 	bool "Faraday devices"
 	default y
-	depends on ARM
+	depends on ARM || NDS32
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y.
 
@@ -18,7 +18,7 @@ if NET_VENDOR_FARADAY
 
 config FTMAC100
 	tristate "Faraday FTMAC100 10/100 Ethernet support"
-	depends on ARM
+	depends on ARM || NDS32
 	select MII
 	---help---
 	  This driver supports the FTMAC100 10/100 Ethernet controller
@@ -27,7 +27,7 @@ config FTMAC100
 
 config FTGMAC100
 	tristate "Faraday FTGMAC100 Gigabit Ethernet support"
-	depends on ARM
+	depends on ARM || NDS32
 	select PHYLIB
 	---help---
 	  This driver supports the FTGMAC100 Gigabit Ethernet controller
-- 
1.7.9.5

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

* Re: [PATCH 04/31] nds32: Exception handling
  2017-11-08  5:54 ` [PATCH 04/31] nds32: Exception handling Greentime Hu
@ 2017-11-08  8:23   ` Arnd Bergmann
       [not found]     ` <E26F4CF8B7DDDB4383A6C2D78D5C3CD56B4974CE@ATCPCS16.andestech.com>
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-08  8:23 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

On Wed, Nov 8, 2017 at 6:54 AM, Greentime Hu <green.hu@gmail.com> wrote:
> From: Greentime Hu <greentime@andestech.com>
>
> Signed-off-by: Vincent Chen <vincentc@andestech.com>
> Signed-off-by: Greentime Hu <greentime@andestech.com>
>  arch/nds32/mm/alignment.c       |  564 +++++++++++++++++++++++++++++++++++++++

> diff --git a/arch/nds32/mm/alignment.c b/arch/nds32/mm/alignment.c
> new file mode 100644
> index 0000000..05589e7
> --- /dev/null
> +++ b/arch/nds32/mm/alignment.c

> +static int mode = 0x3;
> +module_param(mode, int, S_IWUSR | S_IRUGO);

It's an interesting question how to best handle alignment faults, both in
kernel and user mode. While it can help for debugging to have the handler,
I'd argue that you are better off in the long run not fixing up the faults
automatically but to modify the code that triggers them instead.

How about making the faults disabled by default?

> +static int _do_unaligned_access(unsigned long entry, unsigned long addr,
> +                               unsigned long type, struct pt_regs *regs)
> +{
> +       unsigned long inst;
> +       int ret = -EFAULT;
> +
> +       if (user_mode(regs)) {
> +               /* user mode */
> +               if (!va_present(current->mm, addr))
> +                       return ret;
> +       } else {
> +               /* kernel mode */
> +               if (!va_kernel_present(addr))
> +                       return ret;
> +       }

This looks racy, the address might be present when you get here, but not
later when you actually access it. I think what you need here is something
like ARM does with get32_unaligned_check() etc and their fixup tables.

> +       inst = get_inst(regs->ipc);
> +
> +       DEBUG(mode & 0x04, 1,
> +             "Faulting Addr: 0x%08lx, PC: 0x%08lx [ 0x%08lx ]\n", addr,
> +             regs->ipc, inst);
> +
> +       if ((user_mode(regs) && (mode & 0x01))
> +           || (!user_mode(regs) && (mode & 0x02))) {
> +
> +               mm_segment_t seg = get_fs();
> +
> +               set_fs(KERNEL_DS);
> +
> +               if (inst & 0x80000000)
> +                       ret = do_16((inst >> 16) & 0xffff, regs);
> +               else
> +                       ret = do_32(inst, regs);
> +
> +               set_fs(seg);
> +       }
> +
> +       return ret;
> +}

Doesn't this allow user space to read all of kernel memory simply by
passing unaligned addresses?

> +static const struct file_operations fops = {
> +       .open = simple_open,
> +       .read = proc_alignment_read,
> +       .write = proc_alignment_write,
> +};

This should really be a sysctl rather than an open-coded procfs file,
for consistency with other architectures.

Please have a look at that interface on other architectures and pick
whatever the majority do.

     Arnd

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

* Re: [PATCH 00/31] Andes(nds32) Linux Kernel Port
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (30 preceding siblings ...)
  2017-11-08  5:55 ` [PATCH 31/31] net: faraday add nds32 support Greentime Hu
@ 2017-11-08  8:32 ` David Howells
  2017-11-08  8:41   ` Greentime Hu
  2017-11-08 10:26 ` Arnd Bergmann
  32 siblings, 1 reply; 116+ messages in thread
From: David Howells @ 2017-11-08  8:32 UTC (permalink / raw)
  To: Greentime Hu
  Cc: dhowells, greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev

Greentime Hu <green.hu@gmail.com> wrote:

> The build script and toolchain repositories are able to be found here:
>   https://github.com/andestech/build_script.git

Is arch support in upstream binutils and gcc?

David

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

* Re: [PATCH 05/31] nds32: MMU definitions
  2017-11-08  5:54 ` [PATCH 05/31] nds32: MMU definitions Greentime Hu
@ 2017-11-08  8:36   ` Arnd Bergmann
  2017-11-08  8:46     ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-08  8:36 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

On Wed, Nov 8, 2017 at 6:54 AM, Greentime Hu <green.hu@gmail.com> wrote:

> +/*
> + * The DMA mask corresponding to the maximum bus address allocatable
> + * using GFP_DMA.  The default here places no restriction on DMA
> + * allocations.  This must be the smallest DMA mask in the system,
> + * so a successful GFP_DMA allocation will always satisfy this.
> + */
> +#ifndef ISA_DMA_THRESHOLD
> +#define ISA_DMA_THRESHOLD      (0xffffffffULL)
> +#endif

I see this one only in powerpc, I think it can be removed.

> +
> +/*
> + * Optional device DMA address remapping. Do _not_ use directly!
> + * We should really eliminate virt_to_bus() here - it's deprecated.
> + */
> +#define page_to_dma(dev, page)         ((dma_addr_t)__virt_to_phys((unsigned long)page_address(page)))
> +#define dma_to_virt(dev, addr)         ((void *)__phys_to_virt(addr))
> +#define virt_to_dma(dev, addr)         ((dma_addr_t)__virt_to_phys((unsigned long)(addr)))

This looks like an older comment, I think we have eliminated them from the
mainline kernel in all drivers, so you should remove them here too.

> diff --git a/arch/nds32/include/asm/shmparam.h b/arch/nds32/include/asm/shmparam.h
> new file mode 100644
> index 0000000..5679648
> --- /dev/null
> +++ b/arch/nds32/include/asm/shmparam.h

> +
> +/*
> + * This should be the size of the virtually indexed cache/ways,
> + * whichever is greater since the cache aliases every size/ways
> + * bytes.
> + */
> +#define        SHMLBA  (4 * PAGE_SIZE) /* attach addr a multiple of this */
> +#define        REALSHMLBA      SHMLBA

I don't see REALSHMLBA anywhere in the kernel, do you need it?

For SHMLBA, I think it should be defined as an absolute number, using
the maximum
that you might need for any possible value of PAGE_SIZE. Otherwise user space
has a much harder time figuring out what it should use.

        Arnd

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

* Re: [PATCH 00/31] Andes(nds32) Linux Kernel Port
  2017-11-08  8:32 ` [PATCH 00/31] Andes(nds32) Linux Kernel Port David Howells
@ 2017-11-08  8:41   ` Greentime Hu
  2017-11-08 10:18     ` Arnd Bergmann
  0 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  8:41 UTC (permalink / raw)
  To: David Howells
  Cc: Greentime, Linux Kernel Mailing List, Arnd Bergmann, linux-arch,
	tglx, jason, marc.zyngier, robh+dt, netdev

2017-11-08 16:32 GMT+08:00 David Howells <dhowells@redhat.com>:
> Greentime Hu <green.hu@gmail.com> wrote:
>
>> The build script and toolchain repositories are able to be found here:
>>   https://github.com/andestech/build_script.git
>
> Is arch support in upstream binutils and gcc?

Yes, it is but only supporting elf-toolchain now. We will do the
upstream for Linux-toolchain in the next step.

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

* Re: [PATCH 08/31] nds32: Cache and TLB routines
  2017-11-08  5:54 ` [PATCH 08/31] nds32: Cache and TLB routines Greentime Hu
@ 2017-11-08  8:45   ` Arnd Bergmann
  2017-11-08  9:01     ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-08  8:45 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

On Wed, Nov 8, 2017 at 6:54 AM, Greentime Hu <green.hu@gmail.com> wrote:

> +#ifndef __NDS32_PROCFNS_H__
> +#define __NDS32_PROCFNS_H__
> +
> +#define CPU_NAME n13
> +
> +#ifdef __KERNEL__
> +
> +#ifdef __STDC__
> +#define ____cpu_fn(name,fn)       name##fn
> +#else
> +#define ____cpu_fn(name,fn)       name/**/fn
> +#endif
> +#define __cpu_fn(name,fn)         ____cpu_fn(name,fn)
> +
> +#define cpu_proc_init                  __cpu_fn( CPU_NAME, _proc_init)
> +#define cpu_proc_fin                   __cpu_fn( CPU_NAME, _proc_fin)
> +#define cpu_do_idle                    __cpu_fn( CPU_NAME, _do_idle)
> +#define cpu_reset                      __cpu_fn( CPU_NAME, _reset)
> +#define cpu_switch_mm                  __cpu_fn( CPU_NAME, _switch_mm)

I see you have copied this from ARM. Do you actually need the same complexity,
with the ability to build either optimal code for a particular CPU or
a multi-CPU
version?

Most other architectures seem to have settled for doing just one of the two
models. How many CPU implementations to you expect to support that
differ in all of those functions?

      Arnd

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

* Re: [PATCH 05/31] nds32: MMU definitions
  2017-11-08  8:36   ` Arnd Bergmann
@ 2017-11-08  8:46     ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  8:46 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

2017-11-08 16:36 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Wed, Nov 8, 2017 at 6:54 AM, Greentime Hu <green.hu@gmail.com> wrote:
>
>> +/*
>> + * The DMA mask corresponding to the maximum bus address allocatable
>> + * using GFP_DMA.  The default here places no restriction on DMA
>> + * allocations.  This must be the smallest DMA mask in the system,
>> + * so a successful GFP_DMA allocation will always satisfy this.
>> + */
>> +#ifndef ISA_DMA_THRESHOLD
>> +#define ISA_DMA_THRESHOLD      (0xffffffffULL)
>> +#endif
>
> I see this one only in powerpc, I think it can be removed.

Thanks. I will remove it in next version patch.

>
>> +
>> +/*
>> + * Optional device DMA address remapping. Do _not_ use directly!
>> + * We should really eliminate virt_to_bus() here - it's deprecated.
>> + */
>> +#define page_to_dma(dev, page)         ((dma_addr_t)__virt_to_phys((unsigned long)page_address(page)))
>> +#define dma_to_virt(dev, addr)         ((void *)__phys_to_virt(addr))
>> +#define virt_to_dma(dev, addr)         ((dma_addr_t)__virt_to_phys((unsigned long)(addr)))
>
> This looks like an older comment, I think we have eliminated them from the
> mainline kernel in all drivers, so you should remove them here too.

Thanks. I will remove it in next version patch.

>> diff --git a/arch/nds32/include/asm/shmparam.h b/arch/nds32/include/asm/shmparam.h
>> new file mode 100644
>> index 0000000..5679648
>> --- /dev/null
>> +++ b/arch/nds32/include/asm/shmparam.h
>
>> +
>> +/*
>> + * This should be the size of the virtually indexed cache/ways,
>> + * whichever is greater since the cache aliases every size/ways
>> + * bytes.
>> + */
>> +#define        SHMLBA  (4 * PAGE_SIZE) /* attach addr a multiple of this */
>> +#define        REALSHMLBA      SHMLBA
>
> I don't see REALSHMLBA anywhere in the kernel, do you need it?
>
> For SHMLBA, I think it should be defined as an absolute number, using
> the maximum
> that you might need for any possible value of PAGE_SIZE. Otherwise user space
> has a much harder time figuring out what it should use.

Thanks. I will remove REALSHMLBA. I will consider to use 8KB or larger
page size in the next version patch.

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

* Re: [PATCH 10/31] nds32: IRQ handling
  2017-11-08  5:54 ` [PATCH 10/31] nds32: IRQ handling Greentime Hu
@ 2017-11-08  8:49   ` Arnd Bergmann
  2017-11-08  9:06     ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-08  8:49 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

On Wed, Nov 8, 2017 at 6:54 AM, Greentime Hu <green.hu@gmail.com> wrote:

> +
> +#ifdef CONFIG_TRACE_IRQFLAGS
> +void notrace arch_trace_hardirqs_on(void)
> +{
> +       trace_hardirqs_on();
> +}
> +
> +void notrace arch_trace_hardirqs_off(void)
> +{
> +       trace_hardirqs_off();
> +}
> +#endif

I don't see those wrappers on other architectures, what do you need them for?

       Arnd

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

* Re: [PATCH 11/31] nds32: Atomic operations
  2017-11-08  5:54 ` [PATCH 11/31] nds32: Atomic operations Greentime Hu
@ 2017-11-08  8:54   ` Arnd Bergmann
  2017-11-08  9:32       ` vincentc
  2017-11-20 14:29   ` Will Deacon
  1 sibling, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-08  8:54 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen, Palmer Dabbelt

On Wed, Nov 8, 2017 at 6:54 AM, Greentime Hu <green.hu@gmail.com> wrote:
> From: Greentime Hu <greentime@andestech.com>
>
> Signed-off-by: Vincent Chen <vincentc@andestech.com>
> Signed-off-by: Greentime Hu <greentime@andestech.com>
> ---
>  arch/nds32/include/asm/futex.h    |  116 ++++++++++++++++++++++++
>  arch/nds32/include/asm/spinlock.h |  178 +++++++++++++++++++++++++++++++++++++
>  2 files changed, 294 insertions(+)
>  create mode 100644 arch/nds32/include/asm/futex.h
>  create mode 100644 arch/nds32/include/asm/spinlock.h


> diff --git a/arch/nds32/include/asm/spinlock.h b/arch/nds32/include/asm/spinlock.h
> new file mode 100644
> index 0000000..dd5fc71
> --- /dev/null
> +++ b/arch/nds32/include/asm/spinlock.h
> @@ -0,0 +1,178 @@
> +
> +#define arch_spin_unlock_wait(lock) \
> +       do { while (arch_spin_is_locked(lock)) cpu_relax(); } while (0)

This was removed from the other architectures in commit
952111d7db02 ("arch: Remove spin_unlock_wait() arch-specific definitions")

Please remove this as well.

Palmer, I see riscv has the same thing, please also add a patch to your
tree to remove it.

> +#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
> +
> +static inline void arch_spin_lock(arch_spinlock_t * lock)
> +{
> +       unsigned long tmp;
> +
> +       __asm__ __volatile__("1:\n"
> +                            "\tllw\t%0, [%1]\n"
> +                            "\tbnez\t%0, 1b\n"
> +                            "\tmovi\t%0, #0x1\n"
> +                            "\tscw\t%0, [%1]\n"
> +                            "\tbeqz\t%0, 1b\n"
> +                            :"=&r"(tmp)
> +                            :"r"(&lock->lock)
> +                            :"memory");

The coding style seems inconsistent here, the other inline asm uses real tabs
instead of \t, and 'asm volatile' is generally preferred over '__asm__
__volatile__'.

       Arnd

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

* Re: [PATCH 08/31] nds32: Cache and TLB routines
  2017-11-08  8:45   ` Arnd Bergmann
@ 2017-11-08  9:01     ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  9:01 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

2017-11-08 16:45 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Wed, Nov 8, 2017 at 6:54 AM, Greentime Hu <green.hu@gmail.com> wrote:
>
>> +#ifndef __NDS32_PROCFNS_H__
>> +#define __NDS32_PROCFNS_H__
>> +
>> +#define CPU_NAME n13
>> +
>> +#ifdef __KERNEL__
>> +
>> +#ifdef __STDC__
>> +#define ____cpu_fn(name,fn)       name##fn
>> +#else
>> +#define ____cpu_fn(name,fn)       name/**/fn
>> +#endif
>> +#define __cpu_fn(name,fn)         ____cpu_fn(name,fn)
>> +
>> +#define cpu_proc_init                  __cpu_fn( CPU_NAME, _proc_init)
>> +#define cpu_proc_fin                   __cpu_fn( CPU_NAME, _proc_fin)
>> +#define cpu_do_idle                    __cpu_fn( CPU_NAME, _do_idle)
>> +#define cpu_reset                      __cpu_fn( CPU_NAME, _reset)
>> +#define cpu_switch_mm                  __cpu_fn( CPU_NAME, _switch_mm)
>
> I see you have copied this from ARM. Do you actually need the same complexity,
> with the ability to build either optimal code for a particular CPU or
> a multi-CPU
> version?
>
> Most other architectures seem to have settled for doing just one of the two
> models. How many CPU implementations to you expect to support that
> differ in all of those functions?
>

I think we can simplify the implementations because we may not have that
many implementations. I will refine it in the next version patch.

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

* Re: [PATCH 12/31] nds32: Device specific operations
  2017-11-08  5:55 ` [PATCH 12/31] nds32: Device specific operations Greentime Hu
@ 2017-11-08  9:04   ` Arnd Bergmann
  2017-11-09  7:04     ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-08  9:04 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:

> +
> +#define ioremap(cookie,size)           __ioremap(cookie,size,0,1)
> +#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
> +#define iounmap(cookie)                        __iounmap(cookie)

> +#include <asm-generic/io.h>

asm-generic/io.h now provides an ioremap_nocache() helper along with
ioremap_uc/ioremap_wc/ioremap_wt, so I think you can remove the
ioremap_nocache definition here. You might also be able to remove
__ioremap and __iounmap, and only provide ioremap/iounmap, plus
the identity macro 'define ioremap ioremap'

> +void __iomem *__ioremap(unsigned long phys_addr, size_t size,
> +                       unsigned long flags, unsigned long align)

The 'align' argument is unused here, and not used on other architectures
either.

> +{
> +       struct vm_struct *area;
> +       unsigned long addr, offset, last_addr;
> +       pgprot_t prot;
> +
> +       /* Don't allow wraparound or zero size */
> +       last_addr = phys_addr + size - 1;
> +       if (!size || last_addr < phys_addr)
> +               return NULL;
> +
> +       /*
> +        * Mappings have to be page-aligned
> +        */
> +       offset = phys_addr & ~PAGE_MASK;
> +       phys_addr &= PAGE_MASK;
> +       size = PAGE_ALIGN(last_addr + 1) - phys_addr;
> +
> +       /*
> +        * Ok, go for it..
> +        */
> +       area = get_vm_area(size, VM_IOREMAP);

Better use get_vm_area_caller here to have the ioremap areas show up
in a more useful form in /proc/vmallocinfo

Please also have a look at what you can do for memremap().

Since you have no cacheable version of ioremap_wb/wt, it will
return an uncached mapping all the time, which is not ideal.

     Arnd

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

* Re: [PATCH 10/31] nds32: IRQ handling
  2017-11-08  8:49   ` Arnd Bergmann
@ 2017-11-08  9:06     ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-08  9:06 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

2017-11-08 16:49 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Wed, Nov 8, 2017 at 6:54 AM, Greentime Hu <green.hu@gmail.com> wrote:
>
>> +
>> +#ifdef CONFIG_TRACE_IRQFLAGS
>> +void notrace arch_trace_hardirqs_on(void)
>> +{
>> +       trace_hardirqs_on();
>> +}
>> +
>> +void notrace arch_trace_hardirqs_off(void)
>> +{
>> +       trace_hardirqs_off();
>> +}
>> +#endif
>
> I don't see those wrappers on other architectures, what do you need them for?

Thanks.

I will remove them in the next version patch.

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

* Re: [PATCH 13/31] nds32: DMA mapping API
  2017-11-08  5:55 ` [PATCH 13/31] nds32: DMA mapping API Greentime Hu
@ 2017-11-08  9:09   ` Arnd Bergmann
  2017-11-09  7:12     ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-08  9:09 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:

> +static void consistent_sync(void *vaddr, size_t size, int direction)
> +{
> +       unsigned long start = (unsigned long)vaddr;
> +       unsigned long end = start + size;
> +
> +       switch (direction) {
> +       case DMA_FROM_DEVICE:   /* invalidate only */
> +               cpu_dma_inval_range(start, end);
> +               break;
> +       case DMA_TO_DEVICE:     /* writeback only */
> +               cpu_dma_wb_range(start, end);
> +               break;
> +       case DMA_BIDIRECTIONAL: /* writeback and invalidate */
> +               cpu_dma_wbinval_range(start, end);
> +               break;
> +       default:
> +               BUG();
> +       }
> +}

> +
> +static void
> +nds32_dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle,
> +                             size_t size, enum dma_data_direction dir)
> +{
> +       consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
> +}
> +
> +static void
> +nds32_dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
> +                                size_t size, enum dma_data_direction dir)
> +{
> +       consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
> +}

You do the same cache operations for _to_cpu and _to_device, which
usually works,
but is more expensive than you need. It's better to take the ownership into
account and only do what you need.

     Arnd

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

* Re: [PATCH 15/31] nds32: System calls handling
  2017-11-08  5:55 ` [PATCH 15/31] nds32: System calls handling Greentime Hu
@ 2017-11-08  9:30   ` Arnd Bergmann
       [not found]     ` <E26F4CF8B7DDDB4383A6C2D78D5C3CD56B497241@ATCPCS16.andestech.com>
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-08  9:30 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
> From: Greentime Hu <greentime@andestech.com>

> +#endif /* __ASM_NDS32_SYSCALLS_H */
> diff --git a/arch/nds32/include/asm/unistd.h b/arch/nds32/include/asm/unistd.h
> new file mode 100644
> index 0000000..b30adca
> --- /dev/null
> +++ b/arch/nds32/include/asm/unistd.h
> @@ -0,0 +1,21 @@

> +#define __ARCH_WANT_SYS_LLSEEK

This gets set from include/asm-generic/unistd.h if you include that file.

> +#define __ARCH_WANT_SYS_CLONE

This seems ok, though it would be nice to have the reverse logic and have
architectures opt-out of the generic version when they need to provide their
own, rather than having most architectures set it.

> +#define __ARCH_WANT_SYS_OLD_MMAP

I don't see why you need this, can it be dropped?

> diff --git a/arch/nds32/include/uapi/asm/unistd.h b/arch/nds32/include/uapi/asm/unistd.h
> new file mode 100644
> index 0000000..01b466d
> --- /dev/null
> +++ b/arch/nds32/include/uapi/asm/unistd.h

> +#define __NR_ipc               (__NR_arch_specific_syscall + 2)
> +#define __NR_sysfs             (__NR_arch_specific_syscall + 3)
> +#define __NR__llseek             __NR_llseek



> +__SYSCALL(__NR_cacheflush, sys_cacheflush)
> +__SYSCALL(__NR_syscall, sys_syscall)
> +__SYSCALL(__NR_ipc, sys_ipc)
> +__SYSCALL(__NR_sysfs, sys_sysfs)
> +
> +__SYSCALL(__NR_fadvise64_64, sys_fadvise64_64_wrapper)
> +__SYSCALL(__NR_rt_sigreturn, sys_rt_sigreturn_wrapper)
> +__SYSCALL(__NR_mmap, sys_old_mmap)

Usually we handle those overrides by defining the macros in asm/unistd.h
before including the asm-generic version. Can you do that as well for
consistency?

I don't see a reason for sys_ipc, sys_sysfs or sys_old_mmap() here
in a new architecture. Can you drop those or explain why you need them?

> +/*
> + * Special system call wrappers
> + *
> + * $r0 = syscall number
> + * $r8 = syscall table
> + */
> +       .type   sys_syscall, #function
> +ENTRY(sys_syscall)
> +       addi    $p1, $r0, #-__NR_syscalls
> +       bgtz    $p1, 3f
> +       move    $p1, $r0
> +       move    $r0, $r1
> +       move    $r1, $r2
> +       move    $r2, $r3
> +       move    $r3, $r4
> +       move    $r4, $r5
> +! add for syscall 6 args
> +       lwi     $r5, [$sp + #SP_OFFSET ]
> +       lwi     $r5, [$r5]
> +! ~add for syscall 6 args
> +
> +       lw      $p1, [tbl+$p1<<2]
> +       jr      $p1
> +3:     b       sys_ni_syscall
> +ENDPROC(sys_syscall)

Can you explain what this is used for?

> --- /dev/null
> +++ b/arch/nds32/kernel/sys_nds32.c
> +
> +long sys_mmap2(unsigned long addr, unsigned long len,
> +              unsigned long prot, unsigned long flags,
> +              unsigned long fd, unsigned long pgoff)
> +{
> +       if (pgoff & (~PAGE_MASK >> 12))
> +               return -EINVAL;
> +
> +       return sys_mmap_pgoff(addr, len, prot, flags, fd,
> +                             pgoff >> (PAGE_SHIFT - 12));
> +}
> +
> +asmlinkage long sys_fadvise64_64_wrapper(int fd, int advice, loff_t offset,
> +                                        loff_t len)
> +{
> +       return sys_fadvise64_64(fd, offset, len, advice);
> +}

You should always use SYSCALL_DEFINE*() macros to define entry points
for your own syscalls in C code for consistency. I also wonder if we should
just move those two into common code, a lot of architectures need the first
one in particular.

        Arnd

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

* RE: [PATCH 11/31] nds32: Atomic operations
  2017-11-08  8:54   ` Arnd Bergmann
@ 2017-11-08  9:32       ` vincentc
  0 siblings, 0 replies; 116+ messages in thread
From: vincentc @ 2017-11-08  9:32 UTC (permalink / raw)
  To: arnd
  Cc: greentime, linux-kernel, linux-arch, tglx, jason, marc.zyngier,
	robh+dt, netdev, palmer

> -----Original Message-----
> From: arndbergmann@gmail.com [mailto:arndbergmann@gmail.com] On
> Behalf Of Arnd Bergmann
> Sent: Wednesday, November 08, 2017 4:54 PM
> To: Greentime Hu
> Cc: Greentime Ying-Han Hu(胡英漢); Linux Kernel Mailing List; linux-arch;
> Thomas Gleixner; Jason Cooper; Marc Zyngier; Rob Herring; Networking;
> Vincent Ren-Wei Chen(陳人維); Palmer Dabbelt
> Subject: Re: [PATCH 11/31] nds32: Atomic operations
>
> On Wed, Nov 8, 2017 at 6:54 AM, Greentime Hu <green.hu@gmail.com>
> wrote:
> > From: Greentime Hu <greentime@andestech.com>
> >
> > Signed-off-by: Vincent Chen <vincentc@andestech.com>
> > Signed-off-by: Greentime Hu <greentime@andestech.com>
> > ---
> >  arch/nds32/include/asm/futex.h    |  116 ++++++++++++++++++++++++
> >  arch/nds32/include/asm/spinlock.h |  178
> > +++++++++++++++++++++++++++++++++++++
> >  2 files changed, 294 insertions(+)
> >  create mode 100644 arch/nds32/include/asm/futex.h  create mode
> 100644
> > arch/nds32/include/asm/spinlock.h
>
>
> > diff --git a/arch/nds32/include/asm/spinlock.h
> > b/arch/nds32/include/asm/spinlock.h
> > new file mode 100644
> > index 0000000..dd5fc71
> > --- /dev/null
> > +++ b/arch/nds32/include/asm/spinlock.h
> > @@ -0,0 +1,178 @@
> > +
> > +#define arch_spin_unlock_wait(lock) \
> > +       do { while (arch_spin_is_locked(lock)) cpu_relax(); } while
> > +(0)
>
> This was removed from the other architectures in commit
> 952111d7db02 ("arch: Remove spin_unlock_wait() arch-specific definitions")
>
> Please remove this as well.
>
Dear Arnd:

I will remove them in the next version patch.


> Palmer, I see riscv has the same thing, please also add a patch to your tree to
> remove it.
>
> > +#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
> > +
> > +static inline void arch_spin_lock(arch_spinlock_t * lock) {
> > +       unsigned long tmp;
> > +
> > +       __asm__ __volatile__("1:\n"
> > +                            "\tllw\t%0, [%1]\n"
> > +                            "\tbnez\t%0, 1b\n"
> > +                            "\tmovi\t%0, #0x1\n"
> > +                            "\tscw\t%0, [%1]\n"
> > +                            "\tbeqz\t%0, 1b\n"
> > +                            :"=&r"(tmp)
> > +                            :"r"(&lock->lock)
> > +                            :"memory");
>
> The coding style seems inconsistent here, the other inline asm uses real tabs
> instead of \t, and 'asm volatile' is generally preferred over '__asm__
> __volatile__'.
>
>        Arnd

OK, I will modify it in the next version patch.

Thanks

Best regards
Vincent
CONFIDENTIALITY NOTICE:

This e-mail (and its attachments) may contain confidential and legally privileged information or information protected from disclosure. If you are not the intended recipient, you are hereby notified that any disclosure, copying, distribution, or use of the information contained herein is strictly prohibited. In this case, please immediately notify the sender by return e-mail, delete the message (and any accompanying documents) and destroy all printed hard copies. Thank you for your cooperation.

Copyright ANDES TECHNOLOGY CORPORATION - All Rights Reserved.

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

* RE: [PATCH 11/31] nds32: Atomic operations
@ 2017-11-08  9:32       ` vincentc
  0 siblings, 0 replies; 116+ messages in thread
From: vincentc @ 2017-11-08  9:32 UTC (permalink / raw)
  To: arnd
  Cc: greentime, linux-kernel, linux-arch, tglx, jason, marc.zyngier,
	robh+dt, netdev, palmer

> -----Original Message-----
> From: arndbergmann@gmail.com [mailto:arndbergmann@gmail.com] On
> Behalf Of Arnd Bergmann
> Sent: Wednesday, November 08, 2017 4:54 PM
> To: Greentime Hu
> Cc: Greentime Ying-Han Hu(胡英漢); Linux Kernel Mailing List; linux-arch;
> Thomas Gleixner; Jason Cooper; Marc Zyngier; Rob Herring; Networking;
> Vincent Ren-Wei Chen(陳人維); Palmer Dabbelt
> Subject: Re: [PATCH 11/31] nds32: Atomic operations
>
> On Wed, Nov 8, 2017 at 6:54 AM, Greentime Hu <green.hu@gmail.com>
> wrote:
> > From: Greentime Hu <greentime@andestech.com>
> >
> > Signed-off-by: Vincent Chen <vincentc@andestech.com>
> > Signed-off-by: Greentime Hu <greentime@andestech.com>
> > ---
> >  arch/nds32/include/asm/futex.h    |  116 ++++++++++++++++++++++++
> >  arch/nds32/include/asm/spinlock.h |  178
> > +++++++++++++++++++++++++++++++++++++
> >  2 files changed, 294 insertions(+)
> >  create mode 100644 arch/nds32/include/asm/futex.h  create mode
> 100644
> > arch/nds32/include/asm/spinlock.h
>
>
> > diff --git a/arch/nds32/include/asm/spinlock.h
> > b/arch/nds32/include/asm/spinlock.h
> > new file mode 100644
> > index 0000000..dd5fc71
> > --- /dev/null
> > +++ b/arch/nds32/include/asm/spinlock.h
> > @@ -0,0 +1,178 @@
> > +
> > +#define arch_spin_unlock_wait(lock) \
> > +       do { while (arch_spin_is_locked(lock)) cpu_relax(); } while
> > +(0)
>
> This was removed from the other architectures in commit
> 952111d7db02 ("arch: Remove spin_unlock_wait() arch-specific definitions")
>
> Please remove this as well.
>
Dear Arnd:

I will remove them in the next version patch.


> Palmer, I see riscv has the same thing, please also add a patch to your tree to
> remove it.
>
> > +#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
> > +
> > +static inline void arch_spin_lock(arch_spinlock_t * lock) {
> > +       unsigned long tmp;
> > +
> > +       __asm__ __volatile__("1:\n"
> > +                            "\tllw\t%0, [%1]\n"
> > +                            "\tbnez\t%0, 1b\n"
> > +                            "\tmovi\t%0, #0x1\n"
> > +                            "\tscw\t%0, [%1]\n"
> > +                            "\tbeqz\t%0, 1b\n"
> > +                            :"=&r"(tmp)
> > +                            :"r"(&lock->lock)
> > +                            :"memory");
>
> The coding style seems inconsistent here, the other inline asm uses real tabs
> instead of \t, and 'asm volatile' is generally preferred over '__asm__
> __volatile__'.
>
>        Arnd

OK, I will modify it in the next version patch.

Thanks

Best regards
Vincent
CONFIDENTIALITY NOTICE:

This e-mail (and its attachments) may contain confidential and legally privileged information or information protected from disclosure. If you are not the intended recipient, you are hereby notified that any disclosure, copying, distribution, or use of the information contained herein is strictly prohibited. In this case, please immediately notify the sender by return e-mail, delete the message (and any accompanying documents) and destroy all printed hard copies. Thank you for your cooperation.

Copyright ANDES TECHNOLOGY CORPORATION - All Rights Reserved.

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

* Re: [PATCH 16/31] nds32: VDSO support
  2017-11-08  5:55 ` [PATCH 16/31] nds32: VDSO support Greentime Hu
@ 2017-11-08  9:37   ` Arnd Bergmann
  2017-11-08 20:00     ` Deepa Dinamani
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-08  9:37 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen, Palmer Dabbelt, Deepa Dinamani

On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:

> --- /dev/null
> +++ b/arch/nds32/include/asm/vdso_datapage.h
> @@ -0,0 +1,51 @@

> +#ifndef __ASM_VDSO_DATAPAGE_H
> +#define __ASM_VDSO_DATAPAGE_H
> +
> +#ifdef __KERNEL__
> +
> +#ifndef __ASSEMBLY__
> +
> +struct vdso_data {
> +       bool cycle_count_down;  /* timer cyclye counter is decrease with time */
> +       u32 cycle_count_offset; /* offset of timer cycle counter register */
> +       u32 seq_count;          /* sequence count - odd during updates */
> +       u32 xtime_coarse_sec;   /* coarse time */
> +       u32 xtime_coarse_nsec;
> +
> +       u32 wtm_clock_sec;      /* wall to monotonic offset */
> +       u32 wtm_clock_nsec;
> +       u32 xtime_clock_sec;    /* CLOCK_REALTIME - seconds */
> +       u32 cs_mult;            /* clocksource multiplier */
> +       u32 cs_shift;           /* Cycle to nanosecond divisor (power of two) */
> +
> +       u64 cs_cycle_last;      /* last cycle value */
> +       u64 cs_mask;            /* clocksource mask */
> +
> +       u64 xtime_clock_nsec;   /* CLOCK_REALTIME sub-ns base */
> +       u32 tz_minuteswest;     /* timezone info for gettimeofday(2) */
> +       u32 tz_dsttime;
> +};

I need some insight from Deepa and Palmer here: to prepare for 64-bit
time_t in the
future, would it make sense to define the vdso to use 64-bit seconds numbers
consistently, and provide vdso symbols that return 64-bit times, having the
glibc convert that to normal timespec values, or should we leave it for now?

For the normal syscalls I think we are better off keeping things consistent
between architectures, but the vdso is architecture specific by definition, so
we may as well use 64-bit times there now (same for risc-v, which still
has time to modify this before the 4.15 release and glibc merge).

> +/*
> + * This controls what symbols we export from the DSO.
> + */
> +VERSION
> +{
> +       LINUX_2.6 {
> +       global:
> +               __kernel_rt_sigreturn;
> +               __vdso_gettimeofday;
> +               __vdso_clock_getres;
> +               __vdso_clock_gettime;
> +       local: *;
> +       };
> +}

I still struggle to understand how symbol versioning is supposed to work
in a vdso (as opposed to a library you compile against), but I think this should
use the version from the kernel that you plan to merge into, i.e. LINUX_4
or LINUX_4_16.

       Arnd

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

* Re: [PATCH 18/31] nds32: Library functions
  2017-11-08  5:55 ` [PATCH 18/31] nds32: Library functions Greentime Hu
@ 2017-11-08  9:45   ` Arnd Bergmann
  2017-11-09  0:40   ` Al Viro
  1 sibling, 0 replies; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-08  9:45 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:

> +#define get_user(x,p)                                                  \
> +       ({                                                              \
> +               const register typeof(*(p)) __user *__p asm("$r0") = (p);\
> +               register unsigned long __r2 asm("$r2");                 \
> +               register int __e asm("$r0");                            \
> +               switch (sizeof(*(__p))) {                               \
> +               case 1:                                                 \
> +                       __get_user_x(__r2, __p, __e, 1, "$lp");         \
> +                       break;                                          \
> +               case 2:                                                 \
> +                       __get_user_x(__r2, __p, __e, 2, "$lp");         \
> +                       break;                                          \
> +               case 4:                                                 \
> +                       __get_user_x(__r2, __p, __e, 4, "$lp");         \
> +                       break;                                          \
> +               case 8:                                                 \
> +                       __get_user_x(__r2, __p, __e, 8, "$r3", "$lp");  \
> +                       break;                                          \
> +               default: __e = __get_user_bad(); break;                 \
> +               }                                                       \
> +               x = (typeof(*(p))) __r2;        \
> +               __e;                                                    \
> +       })

Something looks odd here: __get_user_bad above looks like it is meant
to provide a link-time error

> +__get_user_bad_8:
> +       move    $r3, #0
> +__get_user_bad:
> +       move    $r2, #0
> +       move    $r0, #-EFAULT
> +       ret
> +

but here you actually have a symbol with that name, it gets turned
into a runtime error. I think the first one needs to get renamed to
actually work as expected and force the link error in built-in code
(it works in modules ins __get_user_bad is not exported).

> +
> +__put_user_bad:
> +       move    $r0, #-EFAULT
> +       ret
> +

same here.

      Arnd

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

* Re: [PATCH 03/31] nds32: Support early_printk
  2017-11-08  5:54 ` [PATCH 03/31] nds32: Support early_printk Greentime Hu
@ 2017-11-08  9:47   ` Tobias Klauser
  2017-11-09  7:19     ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Tobias Klauser @ 2017-11-08  9:47 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev, Rick Chen

On 2017-11-08 at 06:54:51 +0100, Greentime Hu <green.hu@gmail.com> wrote:
> From: Greentime Hu <greentime@andestech.com>
> 
> Signed-off-by: Rick Chen <rick@andestech.com>
> Signed-off-by: Greentime Hu <greentime@andestech.com>
> ---
>  arch/nds32/kernel/early_printk.c |  124 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 124 insertions(+)
>  create mode 100644 arch/nds32/kernel/early_printk.c
> 
> diff --git a/arch/nds32/kernel/early_printk.c b/arch/nds32/kernel/early_printk.c
> new file mode 100644
> index 0000000..269c3cd
> --- /dev/null
> +++ b/arch/nds32/kernel/early_printk.c

Could be implemented using earlycon (the 8250 drivers already supports
it) instead of duplicating functionality in arch/nds32?  See e.g. the
nios2 port for how this could be done, specifically commit e118c3fec9c0
("nios2: remove custom early console implementation").

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

* Re: [PATCH 20/31] nds32: L2 cache support
  2017-11-08  5:55 ` [PATCH 20/31] nds32: L2 cache support Greentime Hu
@ 2017-11-08  9:48   ` Arnd Bergmann
  2017-11-09  7:24     ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-08  9:48 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
> From: Greentime Hu <greentime@andestech.com>
>
> Signed-off-by: Vincent Chen <vincentc@andestech.com>
> Signed-off-by: Greentime Hu <greentime@andestech.com>

> +
> +/* This is defined for head.S to use due to device tree is not yet built. */
> +#define L2CC_PA_BASE           0x90F00000

This looks problematic, since it prevents you from using the same head.S for
multiple SoCs that have different L2 controllers or that have them at different
addresses.

What does head.S actually do to the L2CC? Could the boot protocol require
that to be done by the boot loader before entering the kernel instead?

     Arnd

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

* Re: [PATCH 23/31] nds32: Device tree support
  2017-11-08  5:55 ` [PATCH 23/31] nds32: Device tree support Greentime Hu
@ 2017-11-08  9:53   ` Arnd Bergmann
  2017-11-09  7:48     ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-08  9:53 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
> From: Greentime Hu <greentime@andestech.com>
>
> Signed-off-by: Vincent Chen <vincentc@andestech.com>
> Signed-off-by: Greentime Hu <greentime@andestech.com>
> ---
>  arch/nds32/boot/dts/Makefile   |    8 ++++++
>  arch/nds32/boot/dts/ae3xx.dts  |   55 ++++++++++++++++++++++++++++++++++++
>  arch/nds32/boot/dts/ag101p.dts |   60 ++++++++++++++++++++++++++++++++++++++++
>  arch/nds32/kernel/devtree.c    |   45 ++++++++++++++++++++++++++++++
>  4 files changed, 168 insertions(+)
>  create mode 100644 arch/nds32/boot/dts/Makefile
>  create mode 100644 arch/nds32/boot/dts/ae3xx.dts
>  create mode 100644 arch/nds32/boot/dts/ag101p.dts
>  create mode 100644 arch/nds32/kernel/devtree.c
>
> diff --git a/arch/nds32/boot/dts/Makefile b/arch/nds32/boot/dts/Makefile
> new file mode 100644
> index 0000000..d31faa8
> --- /dev/null
> +++ b/arch/nds32/boot/dts/Makefile
> @@ -0,0 +1,8 @@
> +ifneq '$(CONFIG_NDS32_BUILTIN_DTB)' '""'
> +BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_NDS32_BUILTIN_DTB)).dtb.o
> +else
> +BUILTIN_DTB :=
> +endif
> +obj-$(CONFIG_OF) += $(BUILTIN_DTB)

For new architectures, I think it's better to not support built-in dtb
but instead require the
boot loader to be aware of device trees.

> +clean-files := *.dtb *.dtb.S
> diff --git a/arch/nds32/boot/dts/ae3xx.dts b/arch/nds32/boot/dts/ae3xx.dts
> new file mode 100644
> index 0000000..b6c85dc
> --- /dev/null
> +++ b/arch/nds32/boot/dts/ae3xx.dts
> @@ -0,0 +1,55 @@
> +/dts-v1/;
> +/ {
> +       compatible = "nds32 ae3xx";

ae3xx looks like a wildcard name for multiple boards. Please always
have compatible
names without wildcards. You usually also want to list both the SoC
and the board
here.

> +       #address-cells = <1>;
> +       #size-cells = <1>;
> +       interrupt-parent = <&intc>;
> +
> +       chosen {
> +               bootargs = "console=ttyS0,38400n8 earlyprintk=uart8250-32bit,0xf0300000 debug loglevel=7";
> +       };

Remove the earlyprintk option from the bootargs here, regular boards
should never rely
on earlyprintk. The "earlycon" support in the uart drivers works
almost as well (it starts
slightly later in the boot process), and it will pick up the uart from
the chosen/stdout-path
property.

> +       if (!params || !early_init_dt_scan(params)) {
> +               pr_crit("\n"
> +                       "Error: invalid device tree blob at (virtual address 0x%p)\n"
> +                       "The dtb must be 8-byte aligned and must not exceed 8 KB in size\n"
> +                       "\nPlease check your bootloader.", params);

What is the 8KB limit for the dtb for? This sounds really limiting
once you get to
more complex SoCs.

       Arnd

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

* Re: [PATCH 24/31] nds32: Miscellaneous header files
  2017-11-08  5:55 ` [PATCH 24/31] nds32: Miscellaneous header files Greentime Hu
@ 2017-11-08  9:57   ` Arnd Bergmann
  0 siblings, 0 replies; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-08  9:57 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
> +
> +static inline void __delay(unsigned long loops)
> +{
> +       __asm__ __volatile__(".align 2\n"
> +                            "1:\n"
> +                            "\taddi\t%0, %0, -1\n"
> +                            "\tbgtz\t%0, 1b\n"
> +                            :"=r"(loops)
> +                            :"0"(loops));
> +}

Does the architecture define a high-resolution clock source? If yes,
then it's better
to use that to get exact timing than to rely on the loop calibration.

> +/*
> + * This file is generally used by user-level software, so you need to
> + * be a little careful about namespace pollution etc.  Also, we cannot
> + * assume GCC is being used.
> + */
> +
> +typedef unsigned short __kernel_mode_t;
> +#define __kernel_mode_t __kernel_mode_t
> +
> +typedef unsigned short __kernel_ipc_pid_t;
> +#define __kernel_ipc_pid_t __kernel_ipc_pid_t
> +
> +typedef unsigned short __kernel_uid_t;
> +typedef unsigned short __kernel_gid_t;
> +#define __kernel_uid_t __kernel_uid_t
> +
> +typedef unsigned short __kernel_old_dev_t;
> +#define __kernel_old_dev_t __kernel_old_dev_t
> +
> +#include <asm-generic/posix_types.h>

I don't understand why you would want to override any of those.
Changing them unfortunately means rebuilding all of your user
space, but I think it would be better to do that now than to suffer
from this later on.

      Arnd

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

* Re: [PATCH 25/31] nds32: defconfig
  2017-11-08  5:55 ` [PATCH 25/31] nds32: defconfig Greentime Hu
@ 2017-11-08 10:03   ` Arnd Bergmann
  2017-11-09  8:00     ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-08 10:03 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
> From: Greentime Hu <greentime@andestech.com>
>
> Signed-off-by: Vincent Chen <vincentc@andestech.com>
> Signed-off-by: Greentime Hu <greentime@andestech.com>
> ---
>  arch/nds32/configs/ae3xx_defconfig  |  110 +++++++++++++++++++++++++++++++++++
>  arch/nds32/configs/ag101p_defconfig |  109 ++++++++++++++++++++++++++++++++++

Are those two incompatible? I would recommend starting without board
specific defconfig
files, it just gets messy once you get more than a few machines you
want to support.

> diff --git a/arch/nds32/configs/ae3xx_defconfig b/arch/nds32/configs/ae3xx_defconfig
> new file mode 100644
> index 0000000..14d49a3
> --- /dev/null
> +++ b/arch/nds32/configs/ae3xx_defconfig
> @@ -0,0 +1,110 @@
> +CONFIG_CROSS_COMPILE="nds32le-linux-"
> +CONFIG_SYSVIPC=y
> +CONFIG_POSIX_MQUEUE=y
> +CONFIG_HIGH_RES_TIMERS=y
> +CONFIG_BSD_PROCESS_ACCT=y
> +CONFIG_BSD_PROCESS_ACCT_V3=y
> +CONFIG_IKCONFIG=y
> +CONFIG_IKCONFIG_PROC=y
> +CONFIG_LOG_BUF_SHIFT=14
> +CONFIG_NAMESPACES=y
> +CONFIG_USER_NS=y
> +CONFIG_RELAY=y
> +CONFIG_BLK_DEV_INITRD=y
> +CONFIG_SYSCTL_SYSCALL=y
> +CONFIG_KALLSYMS_ALL=y
> +CONFIG_EMBEDDED=y

You usually don't want to select 'CONFIG_EMBEDDED' for regular
builds, it's should only be needed to disable options that are
usually considered essential.

> +CONFIG_FB=y
> +# CONFIG_VGA_CONSOLE is not set
> +CONFIG_FRAMEBUFFER_CONSOLE=y

You have a framebuffer console here, but no framebuffer driver?

> +CONFIG_MMC=y
> +CONFIG_RTC_CLASS=y
> +# CONFIG_RTC_HCTOSYS is not set
> +CONFIG_CLKSRC_ATCPIT100=y
> +CONFIG_EXT2_FS=y

Maybe use EXT4, not EXT2, in the defconfig?

       Arnd

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

* Re: [PATCH 26/31] nds32: Build infrastructure
  2017-11-08  5:55 ` [PATCH 26/31] nds32: Build infrastructure Greentime Hu
@ 2017-11-08 10:16   ` Arnd Bergmann
  2017-11-09  9:02     ` Greentime Hu
  2017-11-13 10:45       ` Geert Uytterhoeven
  0 siblings, 2 replies; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-08 10:16 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:

> diff --git a/arch/nds32/Kconfig b/arch/nds32/Kconfig
> new file mode 100644
> index 0000000..112f470
> --- /dev/null
> +++ b/arch/nds32/Kconfig
> @@ -0,0 +1,107 @@
> +#
> +# For a description of the syntax of this configuration file,
> +# see Documentation/kbuild/kconfig-language.txt.
> +#
> +
> +config NDS32
> +        def_bool y
> +       select ARCH_HAS_RAW_COPY_USER
> +       select ARCH_WANT_FRAME_POINTERS if FTRACE
> +       select ARCH_WANT_IPC_PARSE_VERSION
> +       select CLKSRC_MMIO
> +       select CLONE_BACKWARDS
> +       select TIMER_OF
> +       select FRAME_POINTER
> +       select GENERIC_ATOMIC64
> +       select GENERIC_CPU_DEVICES
> +       select GENERIC_CLOCKEVENTS
> +       select GENERIC_IOMAP
> +       select GENERIC_IRQ_CHIP
> +       select GENERIC_IRQ_PROBE
> +       select GENERIC_IRQ_SHOW
> +       select GENERIC_STRNCPY_FROM_USER
> +       select GENERIC_STRNLEN_USER
> +       select GENERIC_TIME_VSYSCALL
> +       select HAVE_ARCH_TRACEHOOK
> +       select HAVE_GENERIC_IOMAP

You normally don't want HAVE_GENERIC_IOMAP, at least unless the CPU
has special instructions to trigger PCI I/O port access.

> +       select HAVE_DEBUG_KMEMLEAK
> +       select HAVE_IDE

You certainly don't want HAVE_IDE

> +       select HAVE_MEMBLOCK
> +       select HAVE_MEMBLOCK_NODE_MAP
> +       select HAVE_UID16

HAVE_UID16 shouldn't be used on new architectures, as mentioned in the
comment about asm/posix_types.h

> +       select HAVE_REGS_AND_STACK_ACCESS_API
> +       select IRQ_DOMAIN
> +       select LOCKDEP_SUPPORT
> +       select MODULES_USE_ELF_REL
> +       select MODULES_USE_ELF_RELA

I would think that you use either MODULES_USE_ELF_REL or
MODULES_USE_ELF_RELA, but not both.

> +       select OF
> +       select OF_EARLY_FLATTREE
> +       select OLD_SIGACTION
> +       select OLD_SIGSUSPEND3

What are the OLD_SIG* ones for? It sounds like something you shouldn't
need, although I'm not familiar wiht them.

> +       select NO_IOPORT_MAP
> +       select RTC_LIB
> +       select THREAD_INFO_IN_TASK
> +       select SYS_SUPPORTS_APM_EMULATION

I don't see what SYS_SUPPORTS_APM_EMULATION gains you.

> +config GENERIC_CALIBRATE_DELAY
> +       def_bool y

It's better to avoid the delay loop completely and skip the calibration,
if your hardware allows.

> +
> +config NDS32_BUILTIN_DTB
> +        string "Builtin DTB"
> +        default ""
> +       help
> +         User can use it to specify the dts of the SoC

Better leave this up to the boot loader.

> +config ALIGNMENT_TRAP
> +       tristate "Kernel support unaligned access handling"
> +       default y
> +       help
> +         Andes processors cannot fetch/store information which is not
> +         naturally aligned on the bus, i.e., a 4 byte fetch must start at an
> +         address divisible by 4. On 32-bit Andes processors, these non-aligned
> +         fetch/store instructions will be emulated in software if you say
> +         here, which has a severe performance impact. This is necessary for
> +         correct operation of some network protocols. With an IP-only
> +         configuration it is safe to say N, otherwise say Y.

Which network protocols are you referring to?

> +config HIGHMEM
> +       bool "High Memory Support"
> +       depends on MMU && CPU_CACHE_NONALIASING
> +       help
> +         The address space of Andes processors is only 4 Gigabytes large
> +         and it has to accommodate user address space, kernel address
> +         space as well as some memory mapped IO. That means that, if you
> +         have a large amount of physical memory and/or IO, not all of the
> +         memory can be "permanently mapped" by the kernel. The physical
> +         memory that is not permanently mapped is called "high memory".
> +
> +         Depending on the selected kernel/user memory split, minimum
> +         vmalloc space and actual amount of RAM, you may not need this
> +         option which should result in a slightly faster kernel.
> +
> +         If unsure, say N.

Generally speaking, highmem support is a mess, and it's better to avoid it.

I see that the two device tree files you have list 1GB of memory. Do you think
that is a common configuration for actual products? Do you expect any to
have more than 1GB (or more than 4GB) in the future, or is that the upper
end of the scale?

If 1GB is a reasonable upper bound, then you could change the vmsplit
to give slightly less address space to user space and have 1GB of direct-mapped
kernel memory plus 256MB of vmalloc space reserved for the kernel,
and completely avoid highmem.

> +config MEMORY_START
> +       hex "Physical memory start address"
> +       default "0x00000000"
> +       help
> +         Physical memory start address, you may modify it if it is porting to
> +         a new SoC with different start address.
> +endmenu

On ARM, we found options like this to be rather problematic since it prevents
you from running the same kernel on boards that are otherwise compatible.

If the architecture easily allows the memory to start at address 0, could
you require this address for all SoCs that want to run Linux, and get
rid of the compile-time option?

       Arnd

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

* Re: [PATCH 00/31] Andes(nds32) Linux Kernel Port
  2017-11-08  8:41   ` Greentime Hu
@ 2017-11-08 10:18     ` Arnd Bergmann
  2017-11-09  9:26       ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-08 10:18 UTC (permalink / raw)
  To: Greentime Hu
  Cc: David Howells, Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring, netdev

On Wed, Nov 8, 2017 at 9:41 AM, Greentime Hu <green.hu@gmail.com> wrote:
> 2017-11-08 16:32 GMT+08:00 David Howells <dhowells@redhat.com>:
>> Greentime Hu <green.hu@gmail.com> wrote:
>>
>>> The build script and toolchain repositories are able to be found here:
>>>   https://github.com/andestech/build_script.git
>>
>> Is arch support in upstream binutils and gcc?
>
> Yes, it is but only supporting elf-toolchain now. We will do the
> upstream for Linux-toolchain in the next step.

Is the Linux toolchain only required for building user space, or do
you also need it
for building kernels? It's often possible to build kernels with a bare
toolchain, and
that helps a lot for automated testing.

      Arnd

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

* Re: [PATCH 00/31] Andes(nds32) Linux Kernel Port
  2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
                   ` (31 preceding siblings ...)
  2017-11-08  8:32 ` [PATCH 00/31] Andes(nds32) Linux Kernel Port David Howells
@ 2017-11-08 10:26 ` Arnd Bergmann
  2017-11-09  9:33   ` Greentime Hu
  32 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-08 10:26 UTC (permalink / raw)
  To: Greentime Hu
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking

On Wed, Nov 8, 2017 at 6:54 AM, Greentime Hu <green.hu@gmail.com> wrote:
> This patchset adds core architecture support to Linux for Andestech's
> N13, N15, D15, N10, D10 processor cores.
>
> Based on the 16/32-bit AndeStar RISC-like architecture, we designed the
> configurable AndesCore series of embedded processor families. AndesCores
> range from highly performance-efficient small-footprint cores for
> microcontrollers and deeply-embedded applications to 1GHz+ cores running
> Linux, covering general-purpose N-series cores for a wide range of computing
> need, DSP-capable D-series cores for digital signal control,
> instruction-extensible E-series cores for application-specific acceleration,
> and secure S-series cores for best protection of the most valuable.

I looked at the entire patch series now and commented on anything I noticed
that could be improved, overall this looks very nice, great work!

Most of my comments are about tiny details that are easy to address.

I see two areas that need to be looked at carefully, and that may take a
few more rounds to get right:

- In the user space ABI, you have a couple of things that differ from the
  normal asm-generic definitions, i.e. s few syscall entry points and some
  types in asm/posix-types.h. I guess you did that to remain compatible
  with an older glibc port, but IMHO this compatibility should be broken
  in favor of having the standard ABI before the port gets merged.

- For the boot interface, you need to clearly define what can be expected
  and what cannot. This involves the presence of the l2cc, the physical
  memory address, the built-in dtb, and probably a few more things I
  missed. For long-term maintainability, you probably want to ensure that
  you can build a kernel that runs on as much diverse hardware as possible.

       Arnd

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

* Re: [PATCH 30/31] dt-bindings: nds32 CPU Bindings
  2017-11-08  5:55 ` [PATCH 30/31] dt-bindings: nds32 CPU Bindings Greentime Hu
@ 2017-11-08 13:18   ` Rob Herring
  2017-11-09  9:39     ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Rob Herring @ 2017-11-08 13:18 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, linux-kernel, Arnd Bergmann, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, netdev,
	Vincent Chen, Rick Chen, Zong Li, devicetree

Please Cc the DT list on bindings.

On Tue, Nov 7, 2017 at 11:55 PM, Greentime Hu <green.hu@gmail.com> wrote:
> From: Greentime Hu <greentime@andestech.com>

Commit message needed.

> Signed-off-by: Vincent Chen <vincentc@andestech.com>
> Signed-off-by: Rick Chen <rick@andestech.com>
> Signed-off-by: Zong Li <zong@andestech.com>
> Signed-off-by: Greentime Hu <greentime@andestech.com>
> ---
>  Documentation/devicetree/bindings/nds32/cpus.txt |   33 ++++++++++++++++++++++
>  1 file changed, 33 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/nds32/cpus.txt
>
> diff --git a/Documentation/devicetree/bindings/nds32/cpus.txt b/Documentation/devicetree/bindings/nds32/cpus.txt
> new file mode 100644
> index 0000000..97394cb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/nds32/cpus.txt
> @@ -0,0 +1,33 @@
> +* Andestech Processor Binding
> +
> +This binding specifies what properties must be available in the device tree
> +representation of a Andestech Processor Core, which is the root node in the
> +tree.
> +
> +Required properties:
> +
> +       - compatible:
> +               Usage: required
> +               Value type: <string>
> +               Definition: should be one of:
> +                       "andestech,n13"
> +                       "andestech,n15"
> +                       "andestech,d15"
> +                       "andestech,n10"
> +                       "andestech,d10"

SMP supported for any of these?

> +
> +    - device_type
> +               Usage: required
> +               Value type: <string>
> +               Definition: must be "cpu"
> +
> +* Examples
> +
> +/ {
> +       cpus {
> +               cpu@0 {

Needs a reg property or drop the unit address.

> +                       device_type = "cpu";
> +                       compatible = "andestech,n13", "andestech,n15";

n13 is a superset of n15?

> +               };
> +       };
> +};
> --
> 1.7.9.5
>

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

* Re: [PATCH 27/31] dt-bindings: interrupt-controller: Andestech Internal Vector Interrupt Controller
  2017-11-08  5:55 ` [PATCH 27/31] dt-bindings: interrupt-controller: Andestech Internal Vector Interrupt Controller Greentime Hu
@ 2017-11-08 13:25   ` Rob Herring
  2017-11-09  9:43     ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Rob Herring @ 2017-11-08 13:25 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, linux-kernel, Arnd Bergmann, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, netdev, Rick Chen,
	devicetree

+DT list

On Tue, Nov 7, 2017 at 11:55 PM, Greentime Hu <green.hu@gmail.com> wrote:
> From: Greentime Hu <greentime@andestech.com>

Commit msg needed.

> Signed-off-by: Rick Chen <rick@andestech.com>
> Signed-off-by: Greentime Hu <greentime@andestech.com>
> ---
>  .../interrupt-controller/andestech,ativic32.txt    |   27 ++++++++++++++++++++
>  1 file changed, 27 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt
>
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt b/Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt
> new file mode 100644
> index 0000000..6bac908
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt
> @@ -0,0 +1,27 @@
> +* Andestech Internal Vector Interrupt Controller
> +
> +The Internal Vector Interrupt Controller (IVIC) is a basic interrupt controller
> +suitable for a simpler SoC platform not requiring a more sophisticated and
> +bigger External Vector Interrupt Controller.
> +
> +
> +Main node required properties:
> +
> +- compatible : should at least contain  "andestech,ativic32".
> +- interrupt-parent: Empty for the interrupt controller itself

Drop this.

> +- interrupt-controller : Identifies the node as an interrupt controller
> +- #interrupt-cells: The number of cells to define the interrupts. Should be 2.
> +       The first cell is the IRQ number
> +       The second cell is used to specify mode:
> +               1 = low-to-high edge triggered
> +               2 = high-to-low edge triggered
> +               4 = active high level-sensitive
> +               8 = active low level-sensitive

Just state 2 cells and refer to interrupt-controller/interrupts.txt.

> +               Default for internal sources should be set to 4 (active high).
> +
> +Examples:
> +       intc: interrupt-controller {
> +               compatible = "andestech,ativic32";
> +               #interrupt-cells = <2>;
> +               interrupt-controller;
> +       };
> --
> 1.7.9.5
>

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

* Re: [PATCH 29/31] MAINTAINERS: Add nds32
  2017-11-08  5:55 ` [PATCH 29/31] MAINTAINERS: Add nds32 Greentime Hu
@ 2017-11-08 13:31   ` Rob Herring
  2017-11-09  9:46     ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Rob Herring @ 2017-11-08 13:31 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, linux-kernel, Arnd Bergmann, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, netdev

On Tue, Nov 7, 2017 at 11:55 PM, Greentime Hu <green.hu@gmail.com> wrote:
> From: Greentime Hu <greentime@andestech.com>
>
> Signed-off-by: Greentime Hu <greentime@andestech.com>
> ---
>  MAINTAINERS |    9 +++++++++
>  1 file changed, 9 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 2f4e462..bce1181 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -857,6 +857,15 @@ X: drivers/iio/*/adjd*
>  F:     drivers/staging/iio/*/ad*
>  F:     drivers/staging/iio/trigger/iio-trig-bfin-timer.c
>
> +ANDES ARCHITECTURE
> +M:     Greentime Hu <green.hu@gmail.com>
> +M:     Vincent Chen <deanbo422@gmail.com>
> +T:     git https://github.com/andestech/linux.git
> +S:     Supported
> +F:     arch/nds32

DT binding files?

> +K:     nds32
> +N:     nds32
> +
>  ANDROID CONFIG FRAGMENTS
>  M:     Rob Herring <robh@kernel.org>
>  S:     Supported
> --
> 1.7.9.5
>

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

* Re: [PATCH 02/31] nds32: Kernel booting and initialization
  2017-11-08  5:54 ` [PATCH 02/31] nds32: Kernel booting and initialization Greentime Hu
@ 2017-11-08 13:38   ` Rob Herring
  2017-11-09  9:49     ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Rob Herring @ 2017-11-08 13:38 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, linux-kernel, Arnd Bergmann, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, netdev,
	Vincent Chen

On Tue, Nov 7, 2017 at 11:54 PM, Greentime Hu <green.hu@gmail.com> wrote:
> From: Greentime Hu <greentime@andestech.com>
>

Commit message needed.

> Signed-off-by: Vincent Chen <vincentc@andestech.com>
> Signed-off-by: Greentime Hu <greentime@andestech.com>
> ---

> +       /* it could update max_pfn */
> +       if (max_pfn - ram_start_pfn <= MAXMEM_PFN)
> +               max_low_pfn = max_pfn;
> +       else {
> +               max_low_pfn = MAXMEM_PFN + ram_start_pfn;
> +#ifndef CONFIG_HIGHMEM

Use IS_ENABLED here and other ifdef's if possible.

> +               max_pfn = MAXMEM_PFN + ram_start_pfn;
> +#endif
> +       }


> +static int __init nds32_device_probe(void)
> +{
> +       return of_platform_populate(NULL, NULL, NULL, NULL);
> +}
> +
> +device_initcall(nds32_device_probe);

You can drop this. The core code will call of_platform_populate for you.

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

* Re: [PATCH 28/31] irqchip: Andestech Internal Vector Interrupt Controller driver
  2017-11-08  5:55 ` [PATCH 28/31] irqchip: Andestech Internal Vector Interrupt Controller driver Greentime Hu
@ 2017-11-08 14:24   ` Marc Zyngier
  2017-11-09 10:10     ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Marc Zyngier @ 2017-11-08 14:24 UTC (permalink / raw)
  To: Greentime Hu, greentime, linux-kernel, arnd, linux-arch, tglx,
	jason, robh+dt, netdev
  Cc: Rick Chen

On 08/11/17 05:55, Greentime Hu wrote:
> From: Greentime Hu <greentime@andestech.com>
> 

Please add a commit message, indicating what this does, and potentially
a pointer to some documentation (if publicly available).

> Signed-off-by: Rick Chen <rick@andestech.com>
> Signed-off-by: Greentime Hu <greentime@andestech.com>
> ---
>  drivers/irqchip/Makefile       |    1 +
>  drivers/irqchip/irq-ativic32.c |  149 ++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 150 insertions(+)
>  create mode 100644 drivers/irqchip/irq-ativic32.c
> 
> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
> index b842dfd..201ca9f 100644
> --- a/drivers/irqchip/Makefile
> +++ b/drivers/irqchip/Makefile
> @@ -80,3 +80,4 @@ obj-$(CONFIG_ARCH_ASPEED)		+= irq-aspeed-vic.o irq-aspeed-i2c-ic.o
>  obj-$(CONFIG_STM32_EXTI) 		+= irq-stm32-exti.o
>  obj-$(CONFIG_QCOM_IRQ_COMBINER)		+= qcom-irq-combiner.o
>  obj-$(CONFIG_IRQ_UNIPHIER_AIDET)	+= irq-uniphier-aidet.o
> +obj-$(CONFIG_NDS32)			+= irq-ativic32.o
> diff --git a/drivers/irqchip/irq-ativic32.c b/drivers/irqchip/irq-ativic32.c
> new file mode 100644
> index 0000000..d3dae59
> --- /dev/null
> +++ b/drivers/irqchip/irq-ativic32.c
> @@ -0,0 +1,149 @@
> +/*
> + * Copyright (C) 2005-2017 Andes Technology Corporation
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/irq.h>
> +#include <linux/of.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_address.h>
> +#include <linux/interrupt.h>
> +#include <linux/irqdomain.h>
> +#include <linux/irqchip.h>
> +#include <nds32_intrinsic.h>
> +
> +static void ativic32_ack_irq(struct irq_data *data)
> +{
> +	__nds32__mtsr_dsb(1 << data->hwirq, NDS32_SR_INT_PEND2);
> +}
> +
> +static void ativic32_mask_irq(struct irq_data *data)
> +{
> +	unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2);
> +	__nds32__mtsr_dsb(int_mask2 & (~(1 << data->hwirq)), NDS32_SR_INT_MASK2);
> +}
> +
> +static void ativic32_mask_ack_irq(struct irq_data *data)
> +{
> +	unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2);
> +	__nds32__mtsr_dsb(int_mask2 & (~(1 << data->hwirq)), NDS32_SR_INT_MASK2);
> +	__nds32__mtsr_dsb((1 << data->hwirq), NDS32_SR_INT_PEND2);
> +
> +}
> +
> +static void ativic32_unmask_irq(struct irq_data *data)
> +{
> +	unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2);
> +	__nds32__mtsr_dsb(int_mask2 | (1 << data->hwirq), NDS32_SR_INT_MASK2);
> +}
> +
> +static int ativic32_set_type(struct irq_data *data, unsigned int flow_type)
> +{
> +	printk(KERN_WARNING "interrupt type is not configurable\n");

If it is not configurable, what is the point of having each interrupt
carry a trigger type in DT?

> +	return 0;
> +}
> +
> +static struct irq_chip ativic32_chip = {
> +	.name = "ativic32",
> +	.irq_ack = ativic32_ack_irq,
> +	.irq_mask = ativic32_mask_irq,
> +	.irq_mask_ack = ativic32_mask_ack_irq,
> +	.irq_unmask = ativic32_unmask_irq,
> +	.irq_set_type = ativic32_set_type,
> +};
> +
> +static unsigned int __initdata nivic_map[6] = { 6, 2, 10, 16, 24, 32 };
> +
> +struct irq_domain *root_domain;

Why isn't this static? Is there anything accessing it from outside of
this driver?

> +static int ativic32_irq_domain_map(struct irq_domain *id, unsigned int virq,
> +				  irq_hw_number_t hw)
> +{
> +
> +	unsigned long int_trigger_type;
> +	int_trigger_type = __nds32__mfsr(NDS32_SR_INT_TRIGGER);
> +	if (int_trigger_type & (1 << hw))
> +		irq_set_chip_and_handler(virq, &ativic32_chip, handle_edge_irq);
> +	else
> +		irq_set_chip_and_handler(virq, &ativic32_chip, handle_level_irq);
> +
> +	return 0;
> +}
> +
> +static struct irq_domain_ops ativic32_ops = {
> +	.map = ativic32_irq_domain_map,
> +	.xlate = irq_domain_xlate_onecell

Huh... Your DT binding insist on two cells, and yet...

> +};
> +
> +static int get_intr_src(void)
> +{
> +	return ((__nds32__mfsr(NDS32_SR_ITYPE)&ITYPE_mskVECTOR) >> ITYPE_offVECTOR)
> +		- NDS32_VECTOR_offINTERRUPT;
> +}
> +
> +asmlinkage void asm_do_IRQ(struct pt_regs *regs)
> +{
> +	struct pt_regs *old_regs = set_irq_regs(regs);
> +	int virq;
> +	int irq = get_intr_src();
> +
> +	/*
> +	 * Some hardware gives randomly wrong interrupts.  Rather
> +	 * than crashing, do something sensible.
> +	 */
> +	if (unlikely(irq >= NR_IRQS)) {
> +		pr_emerg( "IRQ exceeds NR_IRQS\n");
> +		BUG();

Given the above comment, I find this hilarious!

> +	}
> +
> +	irq_enter();
> +	virq = irq_find_mapping(root_domain, irq);
> +	generic_handle_irq(virq);
> +	irq_exit();
> +	set_irq_regs(old_regs);

Why can't you use handle_domain_irq() directly instead of what looks
like a copy of it (this is where the comment comes from...)?

> +
> +}
> +
> +int __init ativic32_init_irq(struct device_node *node, struct device_node *parent)
> +{
> +	unsigned long int_vec_base, nivic, i;
> +
> +	if (WARN(parent, "non-root ativic32 are not supported"))
> +		return -EINVAL;
> +
> +	int_vec_base = __nds32__mfsr(NDS32_SR_IVB);
> +
> +	if (((int_vec_base & IVB_mskIVIC_VER) >> IVB_offIVIC_VER) == 0) {
> +		panic("Unable to use NOINTC option to boot on this cpu\n");
> +	}
> +
> +	nivic = (int_vec_base & IVB_mskNIVIC) >> IVB_offNIVIC;
> +	if (nivic >= (sizeof nivic_map / sizeof nivic_map[0])) {
> +		panic
> +		    ("The number of input for IVIC Controller is not supported on this cpu\n");

Irk. Please leave this on a single line... Or better yet, get rid of it
(see below).

> +	}
> +	nivic = nivic_map[nivic];

If you have multiple configurations, I'd rather they live in DT,
specially if the IP is easily configurable.

> +
> +	root_domain = irq_domain_add_linear(node, nivic,
> +			&ativic32_ops, NULL);
> +
> +	if (!root_domain)
> +		panic("%s: unable to create IRQ domain\n", node->full_name);
> +
> +	for(i = 0; i < nivic; i++)
> +		irq_create_mapping(root_domain, i);

You shouldn't need this, as the core DT code will populate the interrupt
on demand.

> +
> +	return 0;
> +
> +}
> +IRQCHIP_DECLARE(ativic32, "andestech,ativic32", ativic32_init_irq);
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

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

* Re: [PATCH 16/31] nds32: VDSO support
  2017-11-08  9:37   ` Arnd Bergmann
@ 2017-11-08 20:00     ` Deepa Dinamani
  2017-11-08 20:06       ` Arnd Bergmann
  0 siblings, 1 reply; 116+ messages in thread
From: Deepa Dinamani @ 2017-11-08 20:00 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime Hu, greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen, Palmer Dabbelt

On Wed, Nov 8, 2017 at 1:37 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>
>> --- /dev/null
>> +++ b/arch/nds32/include/asm/vdso_datapage.h
>> @@ -0,0 +1,51 @@
>
>> +#ifndef __ASM_VDSO_DATAPAGE_H
>> +#define __ASM_VDSO_DATAPAGE_H
>> +
>> +#ifdef __KERNEL__
>> +
>> +#ifndef __ASSEMBLY__
>> +
>> +struct vdso_data {
>> +       bool cycle_count_down;  /* timer cyclye counter is decrease with time */
>> +       u32 cycle_count_offset; /* offset of timer cycle counter register */
>> +       u32 seq_count;          /* sequence count - odd during updates */
>> +       u32 xtime_coarse_sec;   /* coarse time */
>> +       u32 xtime_coarse_nsec;
>> +
>> +       u32 wtm_clock_sec;      /* wall to monotonic offset */
>> +       u32 wtm_clock_nsec;
>> +       u32 xtime_clock_sec;    /* CLOCK_REALTIME - seconds */
>> +       u32 cs_mult;            /* clocksource multiplier */
>> +       u32 cs_shift;           /* Cycle to nanosecond divisor (power of two) */
>> +
>> +       u64 cs_cycle_last;      /* last cycle value */
>> +       u64 cs_mask;            /* clocksource mask */
>> +
>> +       u64 xtime_clock_nsec;   /* CLOCK_REALTIME sub-ns base */
>> +       u32 tz_minuteswest;     /* timezone info for gettimeofday(2) */
>> +       u32 tz_dsttime;
>> +};
>
> I need some insight from Deepa and Palmer here: to prepare for 64-bit
> time_t in the
> future, would it make sense to define the vdso to use 64-bit seconds numbers
> consistently, and provide vdso symbols that return 64-bit times, having the
> glibc convert that to normal timespec values, or should we leave it for now?

Other architectures also have a similar way of defining these as u32
(eg: x86) I think for performance reasons on 32 bit systems.
u32 still works until 2106 as the timekeeping structures are s64. I
was planning to leave it that way for x86.
If this architecture can live with u64, then it will be better to use it here.

> For the normal syscalls I think we are better off keeping things consistent
> between architectures, but the vdso is architecture specific by definition, so
> we may as well use 64-bit times there now (same for risc-v, which still
> has time to modify this before the 4.15 release and glibc merge).

But, I don't think this vdso can return 64 bit times without syscalls
for the architecture also supporting that. The problem is that all
fallback paths depend on syscalls directly.
Also I couldn't find any arch specific handling of vdso interfaces in
glibc. I think they expect the vdso wrappers in the kernel to handle
this part.

-Deepa

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

* Re: [PATCH 16/31] nds32: VDSO support
  2017-11-08 20:00     ` Deepa Dinamani
@ 2017-11-08 20:06       ` Arnd Bergmann
  2017-11-08 20:14         ` Deepa Dinamani
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-08 20:06 UTC (permalink / raw)
  To: Deepa Dinamani
  Cc: Greentime Hu, Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen, Palmer Dabbelt

On Wed, Nov 8, 2017 at 9:00 PM, Deepa Dinamani <deepa.kernel@gmail.com> wrote:
> On Wed, Nov 8, 2017 at 1:37 AM, Arnd Bergmann <arnd@arndb.de> wrote:
>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>

>>
>> I need some insight from Deepa and Palmer here: to prepare for 64-bit
>> time_t in the
>> future, would it make sense to define the vdso to use 64-bit seconds numbers
>> consistently, and provide vdso symbols that return 64-bit times, having the
>> glibc convert that to normal timespec values, or should we leave it for now?
>
> Other architectures also have a similar way of defining these as u32
> (eg: x86) I think for performance reasons on 32 bit systems.
> u32 still works until 2106 as the timekeeping structures are s64. I
> was planning to leave it that way for x86.

Right, good point.

> If this architecture can live with u64, then it will be better to use it here.

As long as we don't need a division, using u64 is probably cheap enough,
we already need the retry loop.

>> For the normal syscalls I think we are better off keeping things consistent
>> between architectures, but the vdso is architecture specific by definition, so
>> we may as well use 64-bit times there now (same for risc-v, which still
>> has time to modify this before the 4.15 release and glibc merge).
>
> But, I don't think this vdso can return 64 bit times without syscalls
> for the architecture also supporting that. The problem is that all
> fallback paths depend on syscalls directly.
> Also I couldn't find any arch specific handling of vdso interfaces in
> glibc. I think they expect the vdso wrappers in the kernel to handle
> this part.

Do applications call into the vdso directly and expect to get a timespec
out? If they always go through the C library as an intermediate, then
the glibc clock_gettime() could do the conversion.

       Arnd

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

* Re: [PATCH 16/31] nds32: VDSO support
  2017-11-08 20:06       ` Arnd Bergmann
@ 2017-11-08 20:14         ` Deepa Dinamani
  0 siblings, 0 replies; 116+ messages in thread
From: Deepa Dinamani @ 2017-11-08 20:14 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime Hu, Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen, Palmer Dabbelt

> Do applications call into the vdso directly and expect to get a timespec
> out? If they always go through the C library as an intermediate, then
> the glibc clock_gettime() could do the conversion.

It is recommended that applications do not call vdso symbols directly.
According to manpage:

"If you're trying to call the vDSO in your own application rather than
using the C library, you're most likely doing it wrong."

-Deepa

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

* Re: [PATCH 18/31] nds32: Library functions
  2017-11-08  5:55 ` [PATCH 18/31] nds32: Library functions Greentime Hu
  2017-11-08  9:45   ` Arnd Bergmann
@ 2017-11-09  0:40   ` Al Viro
       [not found]     ` <E26F4CF8B7DDDB4383A6C2D78D5C3CD56B497559@ATCPCS16.andestech.com>
  1 sibling, 1 reply; 116+ messages in thread
From: Al Viro @ 2017-11-09  0:40 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev, Vincent Chen

On Wed, Nov 08, 2017 at 01:55:06PM +0800, Greentime Hu wrote:

> +#define __range_ok(addr, size) (size <= get_fs() && addr <= (get_fs() -size))
> +
> +#define access_ok(type, addr, size)                 \
> +	__range_ok((unsigned long)addr, (unsigned long)size)

> +#define __get_user_x(__r2,__p,__e,__s,__i...)				\
> +	   __asm__ __volatile__ (					\
> +		__asmeq("%0", "$r0") __asmeq("%1", "$r2")		\
> +		"bal	__get_user_" #__s				\

... which does not check access_ok() or do any visible equivalents; OK...

> +#define get_user(x,p)							\
> +	({								\
> +		const register typeof(*(p)) __user *__p asm("$r0") = (p);\
> +		register unsigned long __r2 asm("$r2");			\
> +		register int __e asm("$r0");				\
> +		switch (sizeof(*(__p))) {				\
> +		case 1:							\
> +			__get_user_x(__r2, __p, __e, 1, "$lp");		\

... and neither does this, which is almost certainly *not* OK.

> +#define put_user(x,p)							\

Same here, AFAICS.

> +extern unsigned long __arch_copy_from_user(void *to, const void __user * from,
> +					   unsigned long n);

> +static inline unsigned long raw_copy_from_user(void *to,
> +					       const void __user * from,
> +					       unsigned long n)
> +{
> +	return __arch_copy_from_user(to, from, n);
> +}

Er...  Why not call your __arch_... raw_... and be done with that?

> +#define INLINE_COPY_FROM_USER
> +#define INLINE_COPY_TO_USER

Are those actually worth bothering?  IOW, have you compared behaviour
with and without them?

> +ENTRY(__arch_copy_to_user)
> +	push	$r0
> +	push	$r2
> +	beqz	$r2, ctu_exit
> +	srli	$p0, $r2, #2		! $p0 = number of word to clear
> +	andi	$r2, $r2, #3		! Bytes less than a word to copy
> +	beqz	$p0, byte_ctu		! Only less than a word to copy
> +word_ctu:
> +	lmw.bim	$p1, [$r1], $p1		! Load the next word
> +USER(	smw.bim,$p1, [$r0], $p1)	! Store the next word

Umm...  It's that happy with unaligned loads and stores?  Your memcpy seems
to be trying to avoid those...

> +9001:
> +	pop	$p1			! Original $r2, n
> +	pop	$p0			! Original $r0, void *to
> +	sub	$r1, $r0, $p0		! Bytes copied
> +	sub	$r2, $p1, $r1		! Bytes left to copy
> +	push	$lp
> +	move	$r0, $p0
> +	bal	memzero			! Clean up the memory

Just what memory are you zeroing here?  The one you had been
unable to store into in the first place?

> +ENTRY(__arch_copy_from_user)

> +9001:
> +	pop	$p1			! Original $r2, n
> +	pop	$p0			! Original $r0, void *to
> +	sub	$r1, $r1, $p0		! Bytes copied
> +	sub	$r2, $p1, $r1		! Bytes left to copy
> +	push	$lp
> +	bal	memzero			! Clean up the memory

Ditto, only this one is even worse - instead of just oopsing on
you, it will quietly destroy data past the area you've copied
into.  raw_copy_..._user() MUST NOT ZERO ANYTHING.  Ever.

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

* Re: [PATCH 17/31] nds32: Signal handling support
  2017-11-08  5:55 ` [PATCH 17/31] nds32: Signal handling support Greentime Hu
@ 2017-11-09  1:26   ` Al Viro
       [not found]     ` <E26F4CF8B7DDDB4383A6C2D78D5C3CD56B497460@ATCPCS16.andestech.com>
  0 siblings, 1 reply; 116+ messages in thread
From: Al Viro @ 2017-11-09  1:26 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev, Vincent Chen

On Wed, Nov 08, 2017 at 01:55:05PM +0800, Greentime Hu wrote:

> +static int restore_sigframe(struct pt_regs *regs,
> +			    struct rt_sigframe __user * sf)
> +{

[snip]

> +	err |= !valid_user_regs(regs);

IDGI...  Where do you modify ->ipsw at all and how can valid_user_regs() come
to be false here?

> +asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
> +{
> +	struct rt_sigframe __user *frame;
> +
> +	/* Always make any pending restarted system calls return -EINTR */
> +	current->restart_block.fn = do_no_restart_syscall;
> +
> +	/*
> +	 * Since we stacked the signal on a 64-bit boundary,
> +	 * then 'sp' should be two-word aligned here.  If it's
> +	 * not, then the user is trying to mess with us.
> +	 */
> +	if (regs->sp & 7)
> +		goto badframe;
> +
> +	frame = (struct rt_sigframe __user *)regs->sp;
> +
> +	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
> +		goto badframe;
> +
> +	if (restore_sigframe(regs, frame))
> +		goto badframe;
> +
> +	if (restore_altstack(&frame->uc.uc_stack))
> +		goto badframe;
> +
> +	return regs->uregs[0];
> +
> +badframe:
> +	force_sig(SIGSEGV, current);
> +	return 0;
> +}

AFAICS, you are copying arm; take a good look at sys_rt_sigreturn_wrapper
there - specifically, the 'mov why, #0' part.  Consider what happens if
you get an interrupt at the moment when $r0 contains -ERESTARTSYS (for
example) and signal arrives while we are processing the interrupt.  It
will be handled on the way out, without any syscall restart crap ('why'
is 0 on that codepath).  So far, so good, but think what'll happen when
you are done with the signal handler.  sigreturn() is called, the values
we had stashed in sigcontext go back into registers (OK, pt_regs on
kernel stack that will be used to reload the registers on return to
userland)... and the signals that had been blocked for the duration of
handlers (see sa_mask in sigaction(2)) get unblocked.  And it turns
out that you have one of those pending - it had arrived while we'd been
in the handler.

Now we are fucked.  You have TIF_SIGPENDING set, so do_notify_resume()
is called.  And everything looks exactly as if you had a syscall restart
situation - regs->uregs[0] being one of -ERESTART... and 'syscall' flag
being true.  So we go into the second signal handler (as we ought to)
with saved ->ipc set 4 bytes back from where we were going to return.
It would've been the right thing to do if it *was* a syscall restart,
but we were returning to the location where the original interrupt
had caught us.

Result: with the right timing, an interrupt arriving when userland process
has $r0 equal -512 may lead to instruction pointer jumping 4 bytes back.
Pity the poor sod trying to debug that kind of breakage...

Restart should *NOT* be triggered upon sigreturn(2).

> +static int
> +setup_return(struct pt_regs *regs, struct ksignal *ksig, void __user * frame)
> +{
> +	unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler;
> +	unsigned long retcode;
> +
> +	/*
> +	 * Maybe we need to deliver a 32-bit signal to a 26-bit task.

Deliver to what, again?  That comment made sense (if rather sad one) on arm, but
what is it doing here?

> +static int do_signal(struct pt_regs *regs, int syscall)
> +{
> +	unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
> +	struct ksignal ksig;
> +	int restart = 0;
> +
> +	/*
> +	 * 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 0;

Which cases would those be?

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

* Re: [PATCH 12/31] nds32: Device specific operations
  2017-11-08  9:04   ` Arnd Bergmann
@ 2017-11-09  7:04     ` Greentime Hu
  2017-11-10 16:07       ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-09  7:04 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen, deanbo422

2017-11-08 17:04 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>
>> +
>> +#define ioremap(cookie,size)           __ioremap(cookie,size,0,1)
>> +#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
>> +#define iounmap(cookie)                        __iounmap(cookie)
>
>> +#include <asm-generic/io.h>
>
> asm-generic/io.h now provides an ioremap_nocache() helper along with
> ioremap_uc/ioremap_wc/ioremap_wt, so I think you can remove the
> ioremap_nocache definition here. You might also be able to remove
> __ioremap and __iounmap, and only provide ioremap/iounmap, plus
> the identity macro 'define ioremap ioremap'

Thanks. I will try to use generic ioremap_nocache() helper in the next
version patch.

>> +void __iomem *__ioremap(unsigned long phys_addr, size_t size,
>> +                       unsigned long flags, unsigned long align)
>
> The 'align' argument is unused here, and not used on other architectures
> either.
>

Thanks. I will remove this argument in the next version patch.

>> +{
>> +       struct vm_struct *area;
>> +       unsigned long addr, offset, last_addr;
>> +       pgprot_t prot;
>> +
>> +       /* Don't allow wraparound or zero size */
>> +       last_addr = phys_addr + size - 1;
>> +       if (!size || last_addr < phys_addr)
>> +               return NULL;
>> +
>> +       /*
>> +        * Mappings have to be page-aligned
>> +        */
>> +       offset = phys_addr & ~PAGE_MASK;
>> +       phys_addr &= PAGE_MASK;
>> +       size = PAGE_ALIGN(last_addr + 1) - phys_addr;
>> +
>> +       /*
>> +        * Ok, go for it..
>> +        */
>> +       area = get_vm_area(size, VM_IOREMAP);
>
> Better use get_vm_area_caller here to have the ioremap areas show up
> in a more useful form in /proc/vmallocinfo

Thanks.
I will use get_vm_area_caller() in the next version patch.

> Please also have a look at what you can do for memremap().
>
> Since you have no cacheable version of ioremap_wb/wt, it will
> return an uncached mapping all the time, which is not ideal.

Thanks.
I will study kernel/memremap.c

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

* Re: [PATCH 13/31] nds32: DMA mapping API
  2017-11-08  9:09   ` Arnd Bergmann
@ 2017-11-09  7:12     ` Greentime Hu
  2017-11-09 10:14       ` Arnd Bergmann
  0 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-09  7:12 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen, deanbo422

2017-11-08 17:09 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>
>> +static void consistent_sync(void *vaddr, size_t size, int direction)
>> +{
>> +       unsigned long start = (unsigned long)vaddr;
>> +       unsigned long end = start + size;
>> +
>> +       switch (direction) {
>> +       case DMA_FROM_DEVICE:   /* invalidate only */
>> +               cpu_dma_inval_range(start, end);
>> +               break;
>> +       case DMA_TO_DEVICE:     /* writeback only */
>> +               cpu_dma_wb_range(start, end);
>> +               break;
>> +       case DMA_BIDIRECTIONAL: /* writeback and invalidate */
>> +               cpu_dma_wbinval_range(start, end);
>> +               break;
>> +       default:
>> +               BUG();
>> +       }
>> +}
>
>> +
>> +static void
>> +nds32_dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle,
>> +                             size_t size, enum dma_data_direction dir)
>> +{
>> +       consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
>> +}
>> +
>> +static void
>> +nds32_dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
>> +                                size_t size, enum dma_data_direction dir)
>> +{
>> +       consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
>> +}
>
> You do the same cache operations for _to_cpu and _to_device, which
> usually works,
> but is more expensive than you need. It's better to take the ownership into
> account and only do what you need.
>

Thanks.

Like this?

static void
nds32_dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle,
                              size_t size, enum dma_data_direction dir)
{
        consistent_sync((void *)dma_to_virt(dev, handle), size,
DMA_FROM_DEVICE);
}

static void
nds32_dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
                                 size_t size, enum dma_data_direction dir)
{
        consistent_sync((void *)dma_to_virt(dev, handle), size,
DMA_TO_DEVICE);
}

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

* Re: [PATCH 03/31] nds32: Support early_printk
  2017-11-08  9:47   ` Tobias Klauser
@ 2017-11-09  7:19     ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-09  7:19 UTC (permalink / raw)
  To: Tobias Klauser
  Cc: Greentime, Linux Kernel Mailing List, Arnd Bergmann, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring, netdev,
	Rick Chen

2017-11-08 17:47 GMT+08:00 Tobias Klauser <tklauser@distanz.ch>:
> On 2017-11-08 at 06:54:51 +0100, Greentime Hu <green.hu@gmail.com> wrote:
>> From: Greentime Hu <greentime@andestech.com>
>>
>> Signed-off-by: Rick Chen <rick@andestech.com>
>> Signed-off-by: Greentime Hu <greentime@andestech.com>
>> ---
>>  arch/nds32/kernel/early_printk.c |  124 ++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 124 insertions(+)
>>  create mode 100644 arch/nds32/kernel/early_printk.c
>>
>> diff --git a/arch/nds32/kernel/early_printk.c b/arch/nds32/kernel/early_printk.c
>> new file mode 100644
>> index 0000000..269c3cd
>> --- /dev/null
>> +++ b/arch/nds32/kernel/early_printk.c
>
> Could be implemented using earlycon (the 8250 drivers already supports
> it) instead of duplicating functionality in arch/nds32?  See e.g. the
> nios2 port for how this could be done, specifically commit e118c3fec9c0
> ("nios2: remove custom early console implementation").

Thanks.
I will try to use earlycon in the next version patch.
I will remove this patch if earlycon is able to be used in nds32.

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

* Re: [PATCH 20/31] nds32: L2 cache support
  2017-11-08  9:48   ` Arnd Bergmann
@ 2017-11-09  7:24     ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-09  7:24 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen, deanbo422

2017-11-08 17:48 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>> From: Greentime Hu <greentime@andestech.com>
>>
>> Signed-off-by: Vincent Chen <vincentc@andestech.com>
>> Signed-off-by: Greentime Hu <greentime@andestech.com>
>
>> +
>> +/* This is defined for head.S to use due to device tree is not yet built. */
>> +#define L2CC_PA_BASE           0x90F00000
>
> This looks problematic, since it prevents you from using the same head.S for
> multiple SoCs that have different L2 controllers or that have them at different
> addresses.
>
> What does head.S actually do to the L2CC? Could the boot protocol require
> that to be done by the boot loader before entering the kernel instead?
>

Thanks.
It will disable and invalidate L2 cache. I think we can do these
things in bootloader.
I will refine it in the next version patch.

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

* Re: [PATCH 23/31] nds32: Device tree support
  2017-11-08  9:53   ` Arnd Bergmann
@ 2017-11-09  7:48     ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-09  7:48 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

2017-11-08 17:53 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>> From: Greentime Hu <greentime@andestech.com>
>>
>> Signed-off-by: Vincent Chen <vincentc@andestech.com>
>> Signed-off-by: Greentime Hu <greentime@andestech.com>
>> ---
>>  arch/nds32/boot/dts/Makefile   |    8 ++++++
>>  arch/nds32/boot/dts/ae3xx.dts  |   55 ++++++++++++++++++++++++++++++++++++
>>  arch/nds32/boot/dts/ag101p.dts |   60 ++++++++++++++++++++++++++++++++++++++++
>>  arch/nds32/kernel/devtree.c    |   45 ++++++++++++++++++++++++++++++
>>  4 files changed, 168 insertions(+)
>>  create mode 100644 arch/nds32/boot/dts/Makefile
>>  create mode 100644 arch/nds32/boot/dts/ae3xx.dts
>>  create mode 100644 arch/nds32/boot/dts/ag101p.dts
>>  create mode 100644 arch/nds32/kernel/devtree.c
>>
>> diff --git a/arch/nds32/boot/dts/Makefile b/arch/nds32/boot/dts/Makefile
>> new file mode 100644
>> index 0000000..d31faa8
>> --- /dev/null
>> +++ b/arch/nds32/boot/dts/Makefile
>> @@ -0,0 +1,8 @@
>> +ifneq '$(CONFIG_NDS32_BUILTIN_DTB)' '""'
>> +BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_NDS32_BUILTIN_DTB)).dtb.o
>> +else
>> +BUILTIN_DTB :=
>> +endif
>> +obj-$(CONFIG_OF) += $(BUILTIN_DTB)
>
> For new architectures, I think it's better to not support built-in dtb
> but instead require the
> boot loader to be aware of device trees.

Thanks.
I got your point and we have uboot supporting DTB too.
But we use gdb to load vmlinux without uboot sometimes, it can help us
to verify kernel more easily.
If dtb pointer is set by uboot, we will use it instead of using built-in dtb.

>> +clean-files := *.dtb *.dtb.S
>> diff --git a/arch/nds32/boot/dts/ae3xx.dts b/arch/nds32/boot/dts/ae3xx.dts
>> new file mode 100644
>> index 0000000..b6c85dc
>> --- /dev/null
>> +++ b/arch/nds32/boot/dts/ae3xx.dts
>> @@ -0,0 +1,55 @@
>> +/dts-v1/;
>> +/ {
>> +       compatible = "nds32 ae3xx";
>
> ae3xx looks like a wildcard name for multiple boards. Please always
> have compatible
> names without wildcards. You usually also want to list both the SoC
> and the board
> here.

Thanks.
It looks a little bit weird but its not a wildcards. :p
I will list all the names instead of wildcards if I need to add more platforms.

>> +       #address-cells = <1>;
>> +       #size-cells = <1>;
>> +       interrupt-parent = <&intc>;
>> +
>> +       chosen {
>> +               bootargs = "console=ttyS0,38400n8 earlyprintk=uart8250-32bit,0xf0300000 debug loglevel=7";
>> +       };
>
> Remove the earlyprintk option from the bootargs here, regular boards
> should never rely
> on earlyprintk. The "earlycon" support in the uart drivers works
> almost as well (it starts
> slightly later in the boot process), and it will pick up the uart from
> the chosen/stdout-path
> property.

Thanks.
I will remove it.

>> +       if (!params || !early_init_dt_scan(params)) {
>> +               pr_crit("\n"
>> +                       "Error: invalid device tree blob at (virtual address 0x%p)\n"
>> +                       "The dtb must be 8-byte aligned and must not exceed 8 KB in size\n"
>> +                       "\nPlease check your bootloader.", params);
>
> What is the 8KB limit for the dtb for? This sounds really limiting
> once you get to
> more complex SoCs.

Thanks.
We allow uboot to set its start address and we think it might not be
too big thus we limit it to 8KB.
Maybe I should use a big size for complex SoCs.
I will update it in the next version patch.

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

* Re: [PATCH 25/31] nds32: defconfig
  2017-11-08 10:03   ` Arnd Bergmann
@ 2017-11-09  8:00     ` Greentime Hu
  2017-11-09 10:20       ` Arnd Bergmann
  0 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-09  8:00 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen, deanbo422

2017-11-08 18:03 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>> From: Greentime Hu <greentime@andestech.com>
>>
>> Signed-off-by: Vincent Chen <vincentc@andestech.com>
>> Signed-off-by: Greentime Hu <greentime@andestech.com>
>> ---
>>  arch/nds32/configs/ae3xx_defconfig  |  110 +++++++++++++++++++++++++++++++++++
>>  arch/nds32/configs/ag101p_defconfig |  109 ++++++++++++++++++++++++++++++++++
>
> Are those two incompatible? I would recommend starting without board
> specific defconfig
> files, it just gets messy once you get more than a few machines you
> want to support.

Thanks.
These 2 are incompatible.
They use different drivers. I may still keep these 2 defconfigs.

>> diff --git a/arch/nds32/configs/ae3xx_defconfig b/arch/nds32/configs/ae3xx_defconfig
>> new file mode 100644
>> index 0000000..14d49a3
>> --- /dev/null
>> +++ b/arch/nds32/configs/ae3xx_defconfig
>> @@ -0,0 +1,110 @@
>> +CONFIG_CROSS_COMPILE="nds32le-linux-"
>> +CONFIG_SYSVIPC=y
>> +CONFIG_POSIX_MQUEUE=y
>> +CONFIG_HIGH_RES_TIMERS=y
>> +CONFIG_BSD_PROCESS_ACCT=y
>> +CONFIG_BSD_PROCESS_ACCT_V3=y
>> +CONFIG_IKCONFIG=y
>> +CONFIG_IKCONFIG_PROC=y
>> +CONFIG_LOG_BUF_SHIFT=14
>> +CONFIG_NAMESPACES=y
>> +CONFIG_USER_NS=y
>> +CONFIG_RELAY=y
>> +CONFIG_BLK_DEV_INITRD=y
>> +CONFIG_SYSCTL_SYSCALL=y
>> +CONFIG_KALLSYMS_ALL=y
>> +CONFIG_EMBEDDED=y
>
> You usually don't want to select 'CONFIG_EMBEDDED' for regular
> builds, it's should only be needed to disable options that are
> usually considered essential.

Thanks.
I will remove this config in the next version patch.

>> +CONFIG_FB=y
>> +# CONFIG_VGA_CONSOLE is not set
>> +CONFIG_FRAMEBUFFER_CONSOLE=y
>
> You have a framebuffer console here, but no framebuffer driver?

Thanks.
I shall enable it when I push our framebuffer in the next time.
I will disable it in the next version patch.

>> +CONFIG_MMC=y
>> +CONFIG_RTC_CLASS=y
>> +# CONFIG_RTC_HCTOSYS is not set
>> +CONFIG_CLKSRC_ATCPIT100=y
>> +CONFIG_EXT2_FS=y
>
> Maybe use EXT4, not EXT2, in the defconfig?
>

Thanks.
I will enable EXT4 instead of EXT2 in the defconfig.

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

* Re: [PATCH 26/31] nds32: Build infrastructure
  2017-11-08 10:16   ` Arnd Bergmann
@ 2017-11-09  9:02     ` Greentime Hu
  2017-11-09 10:33       ` Arnd Bergmann
  2017-11-13 10:45       ` Geert Uytterhoeven
  1 sibling, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-09  9:02 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

2017-11-08 18:16 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>
>> diff --git a/arch/nds32/Kconfig b/arch/nds32/Kconfig
>> new file mode 100644
>> index 0000000..112f470
>> --- /dev/null
>> +++ b/arch/nds32/Kconfig
>> @@ -0,0 +1,107 @@
>> +#
>> +# For a description of the syntax of this configuration file,
>> +# see Documentation/kbuild/kconfig-language.txt.
>> +#
>> +
>> +config NDS32
>> +        def_bool y
>> +       select ARCH_HAS_RAW_COPY_USER
>> +       select ARCH_WANT_FRAME_POINTERS if FTRACE
>> +       select ARCH_WANT_IPC_PARSE_VERSION
>> +       select CLKSRC_MMIO
>> +       select CLONE_BACKWARDS
>> +       select TIMER_OF
>> +       select FRAME_POINTER
>> +       select GENERIC_ATOMIC64
>> +       select GENERIC_CPU_DEVICES
>> +       select GENERIC_CLOCKEVENTS
>> +       select GENERIC_IOMAP
>> +       select GENERIC_IRQ_CHIP
>> +       select GENERIC_IRQ_PROBE
>> +       select GENERIC_IRQ_SHOW
>> +       select GENERIC_STRNCPY_FROM_USER
>> +       select GENERIC_STRNLEN_USER
>> +       select GENERIC_TIME_VSYSCALL
>> +       select HAVE_ARCH_TRACEHOOK
>> +       select HAVE_GENERIC_IOMAP
>
> You normally don't want HAVE_GENERIC_IOMAP, at least unless the CPU
> has special instructions to trigger PCI I/O port access.

Thanks.
I will remove it in the next version patch.

>> +       select HAVE_DEBUG_KMEMLEAK
>> +       select HAVE_IDE
>
> You certainly don't want HAVE_IDE

Thanks.
I will remove it in the next version patch.

>> +       select HAVE_MEMBLOCK
>> +       select HAVE_MEMBLOCK_NODE_MAP
>> +       select HAVE_UID16
>
> HAVE_UID16 shouldn't be used on new architectures, as mentioned in the
> comment about asm/posix_types.h

Thanks.
I will remove it in the next version patch.

>> +       select HAVE_REGS_AND_STACK_ACCESS_API
>> +       select IRQ_DOMAIN
>> +       select LOCKDEP_SUPPORT
>> +       select MODULES_USE_ELF_REL
>> +       select MODULES_USE_ELF_RELA
>
> I would think that you use either MODULES_USE_ELF_REL or
> MODULES_USE_ELF_RELA, but not both.

Thanks.
I will check which one we used and remove the other one if posible.

>> +       select OF
>> +       select OF_EARLY_FLATTREE
>> +       select OLD_SIGACTION
>> +       select OLD_SIGSUSPEND3
>
> What are the OLD_SIG* ones for? It sounds like something you shouldn't
> need, although I'm not familiar wiht them.

Thanks I will check if we need it or not.

>> +       select NO_IOPORT_MAP
>> +       select RTC_LIB
>> +       select THREAD_INFO_IN_TASK
>> +       select SYS_SUPPORTS_APM_EMULATION
>
> I don't see what SYS_SUPPORTS_APM_EMULATION gains you.

Thanks.
I will remove it in the next version patch.

>> +config GENERIC_CALIBRATE_DELAY
>> +       def_bool y
>
> It's better to avoid the delay loop completely and skip the calibration,
> if your hardware allows.

Thanks.
Do you mean that this config should be def_bool n?
why? Almost all arch enable it.

>> +
>> +config NDS32_BUILTIN_DTB
>> +        string "Builtin DTB"
>> +        default ""
>> +       help
>> +         User can use it to specify the dts of the SoC
>
> Better leave this up to the boot loader.

Thanks.
uboot will pass it too.

>> +config ALIGNMENT_TRAP
>> +       tristate "Kernel support unaligned access handling"
>> +       default y
>> +       help
>> +         Andes processors cannot fetch/store information which is not
>> +         naturally aligned on the bus, i.e., a 4 byte fetch must start at an
>> +         address divisible by 4. On 32-bit Andes processors, these non-aligned
>> +         fetch/store instructions will be emulated in software if you say
>> +         here, which has a severe performance impact. This is necessary for
>> +         correct operation of some network protocols. With an IP-only
>> +         configuration it is safe to say N, otherwise say Y.
>
> Which network protocols are you referring to?

I will modify these descriptions. It was written by someone I don't know. :p
This case only happened when I found is compiler code gen issue or
wrong pointer usage.

>> +config HIGHMEM
>> +       bool "High Memory Support"
>> +       depends on MMU && CPU_CACHE_NONALIASING
>> +       help
>> +         The address space of Andes processors is only 4 Gigabytes large
>> +         and it has to accommodate user address space, kernel address
>> +         space as well as some memory mapped IO. That means that, if you
>> +         have a large amount of physical memory and/or IO, not all of the
>> +         memory can be "permanently mapped" by the kernel. The physical
>> +         memory that is not permanently mapped is called "high memory".
>> +
>> +         Depending on the selected kernel/user memory split, minimum
>> +         vmalloc space and actual amount of RAM, you may not need this
>> +         option which should result in a slightly faster kernel.
>> +
>> +         If unsure, say N.
>
> Generally speaking, highmem support is a mess, and it's better to avoid it.
>
> I see that the two device tree files you have list 1GB of memory. Do you think
> that is a common configuration for actual products? Do you expect any to
> have more than 1GB (or more than 4GB) in the future, or is that the upper
> end of the scale?
>
> If 1GB is a reasonable upper bound, then you could change the vmsplit
> to give slightly less address space to user space and have 1GB of direct-mapped
> kernel memory plus 256MB of vmalloc space reserved for the kernel,
> and completely avoid highmem.

Thanks.
We do realy use 1GB ram in some products.
We also verify CONFIG_HIGHMEM with LTP too.
It seems fine but I will study vmsplit to see if we should use it.

>> +config MEMORY_START
>> +       hex "Physical memory start address"
>> +       default "0x00000000"
>> +       help
>> +         Physical memory start address, you may modify it if it is porting to
>> +         a new SoC with different start address.
>> +endmenu
>
> On ARM, we found options like this to be rather problematic since it prevents
> you from running the same kernel on boards that are otherwise compatible.
>
> If the architecture easily allows the memory to start at address 0, could
> you require this address for all SoCs that want to run Linux, and get
> rid of the compile-time option?

Thanks.
The reason we need this config is because we need to define PHYS_OFFSET.
#define PHYS_OFFSET     (CONFIG_MEMORY_START)

It needs to be set in compile-time. I don't know how to get rid of it.

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

* Re: [PATCH 00/31] Andes(nds32) Linux Kernel Port
  2017-11-08 10:18     ` Arnd Bergmann
@ 2017-11-09  9:26       ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-09  9:26 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: David Howells, Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring, netdev,
	deanbo422

2017-11-08 18:18 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Wed, Nov 8, 2017 at 9:41 AM, Greentime Hu <green.hu@gmail.com> wrote:
>> 2017-11-08 16:32 GMT+08:00 David Howells <dhowells@redhat.com>:
>>> Greentime Hu <green.hu@gmail.com> wrote:
>>>
>>>> The build script and toolchain repositories are able to be found here:
>>>>   https://github.com/andestech/build_script.git
>>>
>>> Is arch support in upstream binutils and gcc?
>>
>> Yes, it is but only supporting elf-toolchain now. We will do the
>> upstream for Linux-toolchain in the next step.
>
> Is the Linux toolchain only required for building user space, or do
> you also need it
> for building kernels? It's often possible to build kernels with a bare
> toolchain, and
> that helps a lot for automated testing.

Yes, nds32 kernel is able to be built with elf-toolchain too.

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

* Re: [PATCH 00/31] Andes(nds32) Linux Kernel Port
  2017-11-08 10:26 ` Arnd Bergmann
@ 2017-11-09  9:33   ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-09  9:33 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking

2017-11-08 18:26 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Wed, Nov 8, 2017 at 6:54 AM, Greentime Hu <green.hu@gmail.com> wrote:
>> This patchset adds core architecture support to Linux for Andestech's
>> N13, N15, D15, N10, D10 processor cores.
>>
>> Based on the 16/32-bit AndeStar RISC-like architecture, we designed the
>> configurable AndesCore series of embedded processor families. AndesCores
>> range from highly performance-efficient small-footprint cores for
>> microcontrollers and deeply-embedded applications to 1GHz+ cores running
>> Linux, covering general-purpose N-series cores for a wide range of computing
>> need, DSP-capable D-series cores for digital signal control,
>> instruction-extensible E-series cores for application-specific acceleration,
>> and secure S-series cores for best protection of the most valuable.
>
> I looked at the entire patch series now and commented on anything I noticed
> that could be improved, overall this looks very nice, great work!
>
> Most of my comments are about tiny details that are easy to address.
>
> I see two areas that need to be looked at carefully, and that may take a
> few more rounds to get right:
>
> - In the user space ABI, you have a couple of things that differ from the
>   normal asm-generic definitions, i.e. s few syscall entry points and some
>   types in asm/posix-types.h. I guess you did that to remain compatible
>   with an older glibc port, but IMHO this compatibility should be broken
>   in favor of having the standard ABI before the port gets merged.
>
> - For the boot interface, you need to clearly define what can be expected
>   and what cannot. This involves the presence of the l2cc, the physical
>   memory address, the built-in dtb, and probably a few more things I
>   missed. For long-term maintainability, you probably want to ensure that
>   you can build a kernel that runs on as much diverse hardware as possible.
>

Many thanks to all your feedbacks. We will prepare the V2 patch to fix
them ASAP. :)

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

* Re: [PATCH 30/31] dt-bindings: nds32 CPU Bindings
  2017-11-08 13:18   ` Rob Herring
@ 2017-11-09  9:39     ` Greentime Hu
  2017-11-09 13:57         ` Rob Herring
  0 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-09  9:39 UTC (permalink / raw)
  To: Rob Herring
  Cc: Greentime, linux-kernel, Arnd Bergmann, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, netdev,
	Vincent Chen, Rick Chen, Zong Li, devicetree

2017-11-08 21:18 GMT+08:00 Rob Herring <robh+dt@kernel.org>:
> Please Cc the DT list on bindings.

Sorry. I am not sure what you mean.
Do you mean add devicetree@vger.kernel.org to cc list?

> On Tue, Nov 7, 2017 at 11:55 PM, Greentime Hu <green.hu@gmail.com> wrote:
>> From: Greentime Hu <greentime@andestech.com>
>
> Commit message needed.

Thanks. I will add more commit messages in the next version patch.

>> Signed-off-by: Vincent Chen <vincentc@andestech.com>
>> Signed-off-by: Rick Chen <rick@andestech.com>
>> Signed-off-by: Zong Li <zong@andestech.com>
>> Signed-off-by: Greentime Hu <greentime@andestech.com>
>> ---
>>  Documentation/devicetree/bindings/nds32/cpus.txt |   33 ++++++++++++++++++++++
>>  1 file changed, 33 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/nds32/cpus.txt
>>
>> diff --git a/Documentation/devicetree/bindings/nds32/cpus.txt b/Documentation/devicetree/bindings/nds32/cpus.txt
>> new file mode 100644
>> index 0000000..97394cb
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/nds32/cpus.txt
>> @@ -0,0 +1,33 @@
>> +* Andestech Processor Binding
>> +
>> +This binding specifies what properties must be available in the device tree
>> +representation of a Andestech Processor Core, which is the root node in the
>> +tree.
>> +
>> +Required properties:
>> +
>> +       - compatible:
>> +               Usage: required
>> +               Value type: <string>
>> +               Definition: should be one of:
>> +                       "andestech,n13"
>> +                       "andestech,n15"
>> +                       "andestech,d15"
>> +                       "andestech,n10"
>> +                       "andestech,d10"
>
> SMP supported for any of these?

We don't support SMP now.

>> +
>> +    - device_type
>> +               Usage: required
>> +               Value type: <string>
>> +               Definition: must be "cpu"
>> +
>> +* Examples
>> +
>> +/ {
>> +       cpus {
>> +               cpu@0 {
>
> Needs a reg property or drop the unit address.

Thanks.
I will fix it in the next version patch.

>> +                       device_type = "cpu";
>> +                       compatible = "andestech,n13", "andestech,n15";
>
> n13 is a superset of n15?

No, they are independent ones.

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

* Re: [PATCH 27/31] dt-bindings: interrupt-controller: Andestech Internal Vector Interrupt Controller
  2017-11-08 13:25   ` Rob Herring
@ 2017-11-09  9:43     ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-09  9:43 UTC (permalink / raw)
  To: Rob Herring
  Cc: Greentime, linux-kernel, Arnd Bergmann, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, netdev, Rick Chen,
	devicetree

2017-11-08 21:25 GMT+08:00 Rob Herring <robh+dt@kernel.org>:
> +DT list
>
> On Tue, Nov 7, 2017 at 11:55 PM, Greentime Hu <green.hu@gmail.com> wrote:
>> From: Greentime Hu <greentime@andestech.com>
>
> Commit msg needed.

Thanks.
I will add commit msg in the next version patch.

>> Signed-off-by: Rick Chen <rick@andestech.com>
>> Signed-off-by: Greentime Hu <greentime@andestech.com>
>> ---
>>  .../interrupt-controller/andestech,ativic32.txt    |   27 ++++++++++++++++++++
>>  1 file changed, 27 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt
>>
>> diff --git a/Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt b/Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt
>> new file mode 100644
>> index 0000000..6bac908
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt
>> @@ -0,0 +1,27 @@
>> +* Andestech Internal Vector Interrupt Controller
>> +
>> +The Internal Vector Interrupt Controller (IVIC) is a basic interrupt controller
>> +suitable for a simpler SoC platform not requiring a more sophisticated and
>> +bigger External Vector Interrupt Controller.
>> +
>> +
>> +Main node required properties:
>> +
>> +- compatible : should at least contain  "andestech,ativic32".
>> +- interrupt-parent: Empty for the interrupt controller itself
>
> Drop this.

Thanks.
I will fix it in the next version patch.

>> +- interrupt-controller : Identifies the node as an interrupt controller
>> +- #interrupt-cells: The number of cells to define the interrupts. Should be 2.
>> +       The first cell is the IRQ number
>> +       The second cell is used to specify mode:
>> +               1 = low-to-high edge triggered
>> +               2 = high-to-low edge triggered
>> +               4 = active high level-sensitive
>> +               8 = active low level-sensitive
>
> Just state 2 cells and refer to interrupt-controller/interrupts.txt.

Thanks.
I will fix it in the next version patch.

>> +               Default for internal sources should be set to 4 (active high).
>> +
>> +Examples:
>> +       intc: interrupt-controller {
>> +               compatible = "andestech,ativic32";
>> +               #interrupt-cells = <2>;
>> +               interrupt-controller;
>> +       };
>> --
>> 1.7.9.5
>>

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

* Re: [PATCH 29/31] MAINTAINERS: Add nds32
  2017-11-08 13:31   ` Rob Herring
@ 2017-11-09  9:46     ` Greentime Hu
  2017-11-09 10:36       ` Arnd Bergmann
  0 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-09  9:46 UTC (permalink / raw)
  To: Rob Herring
  Cc: Greentime, linux-kernel, Arnd Bergmann, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, netdev

2017-11-08 21:31 GMT+08:00 Rob Herring <robh+dt@kernel.org>:
> On Tue, Nov 7, 2017 at 11:55 PM, Greentime Hu <green.hu@gmail.com> wrote:
>> From: Greentime Hu <greentime@andestech.com>
>>
>> Signed-off-by: Greentime Hu <greentime@andestech.com>
>> ---
>>  MAINTAINERS |    9 +++++++++
>>  1 file changed, 9 insertions(+)
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 2f4e462..bce1181 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -857,6 +857,15 @@ X: drivers/iio/*/adjd*
>>  F:     drivers/staging/iio/*/ad*
>>  F:     drivers/staging/iio/trigger/iio-trig-bfin-timer.c
>>
>> +ANDES ARCHITECTURE
>> +M:     Greentime Hu <green.hu@gmail.com>
>> +M:     Vincent Chen <deanbo422@gmail.com>
>> +T:     git https://github.com/andestech/linux.git
>> +S:     Supported
>> +F:     arch/nds32
>
> DT binding files?

Thanks.
I should add
F:    Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt
F:    Documentation/devicetree/bindings/nds32/cpus.txt

I will fix it in the next version patch.

>
>> +K:     nds32
>> +N:     nds32
>> +
>>  ANDROID CONFIG FRAGMENTS
>>  M:     Rob Herring <robh@kernel.org>
>>  S:     Supported
>> --
>> 1.7.9.5
>>

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

* Re: [PATCH 02/31] nds32: Kernel booting and initialization
  2017-11-08 13:38   ` Rob Herring
@ 2017-11-09  9:49     ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-09  9:49 UTC (permalink / raw)
  To: Rob Herring
  Cc: Greentime, linux-kernel, Arnd Bergmann, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, netdev,
	Vincent Chen

2017-11-08 21:38 GMT+08:00 Rob Herring <robh+dt@kernel.org>:
> On Tue, Nov 7, 2017 at 11:54 PM, Greentime Hu <green.hu@gmail.com> wrote:
>> From: Greentime Hu <greentime@andestech.com>
>>
>
> Commit message needed.

Thanks.
I will add more commit messages in the next version patch.

>
>> Signed-off-by: Vincent Chen <vincentc@andestech.com>
>> Signed-off-by: Greentime Hu <greentime@andestech.com>
>> ---
>
>> +       /* it could update max_pfn */
>> +       if (max_pfn - ram_start_pfn <= MAXMEM_PFN)
>> +               max_low_pfn = max_pfn;
>> +       else {
>> +               max_low_pfn = MAXMEM_PFN + ram_start_pfn;
>> +#ifndef CONFIG_HIGHMEM
>
> Use IS_ENABLED here and other ifdef's if possible.
>

Thanks
I will try to use IS_ENABLED here in the next version patch.

>> +               max_pfn = MAXMEM_PFN + ram_start_pfn;
>> +#endif
>> +       }
>
>
>> +static int __init nds32_device_probe(void)
>> +{
>> +       return of_platform_populate(NULL, NULL, NULL, NULL);
>> +}
>> +
>> +device_initcall(nds32_device_probe);
>
> You can drop this. The core code will call of_platform_populate for you.

Thanks.
I will drop this in the next version patch.

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

* Re: [PATCH 28/31] irqchip: Andestech Internal Vector Interrupt Controller driver
  2017-11-08 14:24   ` Marc Zyngier
@ 2017-11-09 10:10     ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-09 10:10 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Greentime, Linux Kernel Mailing List, Arnd Bergmann, linux-arch,
	Thomas Gleixner, Jason Cooper, Rob Herring, netdev, Rick Chen

2017-11-08 22:24 GMT+08:00 Marc Zyngier <marc.zyngier@arm.com>:
> On 08/11/17 05:55, Greentime Hu wrote:
>> From: Greentime Hu <greentime@andestech.com>
>>
>
> Please add a commit message, indicating what this does, and potentially
> a pointer to some documentation (if publicly available).
>

Thans.
I will add proper commit messages in the next version patch.

>> Signed-off-by: Rick Chen <rick@andestech.com>
>> Signed-off-by: Greentime Hu <greentime@andestech.com>
>> ---
>>  drivers/irqchip/Makefile       |    1 +
>>  drivers/irqchip/irq-ativic32.c |  149 ++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 150 insertions(+)
>>  create mode 100644 drivers/irqchip/irq-ativic32.c
>>
>> diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
>> index b842dfd..201ca9f 100644
>> --- a/drivers/irqchip/Makefile
>> +++ b/drivers/irqchip/Makefile
>> @@ -80,3 +80,4 @@ obj-$(CONFIG_ARCH_ASPEED)           += irq-aspeed-vic.o irq-aspeed-i2c-ic.o
>>  obj-$(CONFIG_STM32_EXTI)             += irq-stm32-exti.o
>>  obj-$(CONFIG_QCOM_IRQ_COMBINER)              += qcom-irq-combiner.o
>>  obj-$(CONFIG_IRQ_UNIPHIER_AIDET)     += irq-uniphier-aidet.o
>> +obj-$(CONFIG_NDS32)                  += irq-ativic32.o
>> diff --git a/drivers/irqchip/irq-ativic32.c b/drivers/irqchip/irq-ativic32.c
>> new file mode 100644
>> index 0000000..d3dae59
>> --- /dev/null
>> +++ b/drivers/irqchip/irq-ativic32.c
>> @@ -0,0 +1,149 @@
>> +/*
>> + * Copyright (C) 2005-2017 Andes Technology Corporation
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <linux/irq.h>
>> +#include <linux/of.h>
>> +#include <linux/of_irq.h>
>> +#include <linux/of_address.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/irqdomain.h>
>> +#include <linux/irqchip.h>
>> +#include <nds32_intrinsic.h>
>> +
>> +static void ativic32_ack_irq(struct irq_data *data)
>> +{
>> +     __nds32__mtsr_dsb(1 << data->hwirq, NDS32_SR_INT_PEND2);
>> +}
>> +
>> +static void ativic32_mask_irq(struct irq_data *data)
>> +{
>> +     unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2);
>> +     __nds32__mtsr_dsb(int_mask2 & (~(1 << data->hwirq)), NDS32_SR_INT_MASK2);
>> +}
>> +
>> +static void ativic32_mask_ack_irq(struct irq_data *data)
>> +{
>> +     unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2);
>> +     __nds32__mtsr_dsb(int_mask2 & (~(1 << data->hwirq)), NDS32_SR_INT_MASK2);
>> +     __nds32__mtsr_dsb((1 << data->hwirq), NDS32_SR_INT_PEND2);
>> +
>> +}
>> +
>> +static void ativic32_unmask_irq(struct irq_data *data)
>> +{
>> +     unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2);
>> +     __nds32__mtsr_dsb(int_mask2 | (1 << data->hwirq), NDS32_SR_INT_MASK2);
>> +}
>> +
>> +static int ativic32_set_type(struct irq_data *data, unsigned int flow_type)
>> +{
>> +     printk(KERN_WARNING "interrupt type is not configurable\n");
>
> If it is not configurable, what is the point of having each interrupt
> carry a trigger type in DT?

Make sense.
We should remove this function and DT trigger type description.

>> +     return 0;
>> +}
>> +
>> +static struct irq_chip ativic32_chip = {
>> +     .name = "ativic32",
>> +     .irq_ack = ativic32_ack_irq,
>> +     .irq_mask = ativic32_mask_irq,
>> +     .irq_mask_ack = ativic32_mask_ack_irq,
>> +     .irq_unmask = ativic32_unmask_irq,
>> +     .irq_set_type = ativic32_set_type,
>> +};
>> +
>> +static unsigned int __initdata nivic_map[6] = { 6, 2, 10, 16, 24, 32 };
>> +
>> +struct irq_domain *root_domain;
>
> Why isn't this static? Is there anything accessing it from outside of
> this driver?

Thanks.
I will check if it is not used outside and add static in the next version patch.

>> +static int ativic32_irq_domain_map(struct irq_domain *id, unsigned int virq,
>> +                               irq_hw_number_t hw)
>> +{
>> +
>> +     unsigned long int_trigger_type;
>> +     int_trigger_type = __nds32__mfsr(NDS32_SR_INT_TRIGGER);
>> +     if (int_trigger_type & (1 << hw))
>> +             irq_set_chip_and_handler(virq, &ativic32_chip, handle_edge_irq);
>> +     else
>> +             irq_set_chip_and_handler(virq, &ativic32_chip, handle_level_irq);
>> +
>> +     return 0;
>> +}
>> +
>> +static struct irq_domain_ops ativic32_ops = {
>> +     .map = ativic32_irq_domain_map,
>> +     .xlate = irq_domain_xlate_onecell
>
> Huh... Your DT binding insist on two cells, and yet...

Thanks.
It is inconsistent. We will fix it in the next version patch.

>> +};
>> +
>> +static int get_intr_src(void)
>> +{
>> +     return ((__nds32__mfsr(NDS32_SR_ITYPE)&ITYPE_mskVECTOR) >> ITYPE_offVECTOR)
>> +             - NDS32_VECTOR_offINTERRUPT;
>> +}
>> +
>> +asmlinkage void asm_do_IRQ(struct pt_regs *regs)
>> +{
>> +     struct pt_regs *old_regs = set_irq_regs(regs);
>> +     int virq;
>> +     int irq = get_intr_src();
>> +
>> +     /*
>> +      * Some hardware gives randomly wrong interrupts.  Rather
>> +      * than crashing, do something sensible.
>> +      */
>> +     if (unlikely(irq >= NR_IRQS)) {
>> +             pr_emerg( "IRQ exceeds NR_IRQS\n");
>> +             BUG();
>
> Given the above comment, I find this hilarious!

Thanks.
We will write more proper comments.

>> +     }
>> +
>> +     irq_enter();
>> +     virq = irq_find_mapping(root_domain, irq);
>> +     generic_handle_irq(virq);
>> +     irq_exit();
>> +     set_irq_regs(old_regs);
>
> Why can't you use handle_domain_irq() directly instead of what looks
> like a copy of it (this is where the comment comes from...)?

Thanks.
We will try to use handle_domain_irq() in the next version patch.

>> +
>> +}
>> +
>> +int __init ativic32_init_irq(struct device_node *node, struct device_node *parent)
>> +{
>> +     unsigned long int_vec_base, nivic, i;
>> +
>> +     if (WARN(parent, "non-root ativic32 are not supported"))
>> +             return -EINVAL;
>> +
>> +     int_vec_base = __nds32__mfsr(NDS32_SR_IVB);
>> +
>> +     if (((int_vec_base & IVB_mskIVIC_VER) >> IVB_offIVIC_VER) == 0) {
>> +             panic("Unable to use NOINTC option to boot on this cpu\n");
>> +     }
>> +
>> +     nivic = (int_vec_base & IVB_mskNIVIC) >> IVB_offNIVIC;
>> +     if (nivic >= (sizeof nivic_map / sizeof nivic_map[0])) {
>> +             panic
>> +                 ("The number of input for IVIC Controller is not supported on this cpu\n");
>
> Irk. Please leave this on a single line... Or better yet, get rid of it
> (see below).

Thanks.
We will fix it in the next version patch.

>> +     }
>> +     nivic = nivic_map[nivic];
>
> If you have multiple configurations, I'd rather they live in DT,
> specially if the IP is easily configurable.

Thanks.
But this is read from HW register. IMHO it will be more readable if we
read this
config from HW and do the relative actions.

>> +
>> +     root_domain = irq_domain_add_linear(node, nivic,
>> +                     &ativic32_ops, NULL);
>> +
>> +     if (!root_domain)
>> +             panic("%s: unable to create IRQ domain\n", node->full_name);
>> +
>> +     for(i = 0; i < nivic; i++)
>> +             irq_create_mapping(root_domain, i);
>
> You shouldn't need this, as the core DT code will populate the interrupt
> on demand.

Thanks.
We will fix it in the next version patch.

>> +
>> +     return 0;
>> +
>> +}
>> +IRQCHIP_DECLARE(ativic32, "andestech,ativic32", ativic32_init_irq);
>>
>
> Thanks,
>
>         M.
> --
> Jazz is not dead. It just smells funny...

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

* Re: [PATCH 13/31] nds32: DMA mapping API
  2017-11-09  7:12     ` Greentime Hu
@ 2017-11-09 10:14       ` Arnd Bergmann
  2017-11-10  8:13         ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-09 10:14 UTC (permalink / raw)
  To: Greentime Hu
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen, deanbo422

On Thu, Nov 9, 2017 at 8:12 AM, Greentime Hu <green.hu@gmail.com> wrote:
> 2017-11-08 17:09 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>

>> You do the same cache operations for _to_cpu and _to_device, which
>> usually works,
>> but is more expensive than you need. It's better to take the ownership into
>> account and only do what you need.
>>
> Like this?
>
> static void
> nds32_dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle,
>                               size_t size, enum dma_data_direction dir)
> {
>         consistent_sync((void *)dma_to_virt(dev, handle), size,
> DMA_FROM_DEVICE);
> }
>
> static void
> nds32_dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
>                                  size_t size, enum dma_data_direction dir)
> {
>         consistent_sync((void *)dma_to_virt(dev, handle), size,
> DMA_TO_DEVICE);
> }

No, it's more complicated than that. You need to pass both the direction of the
DMA transaction and the ownership to consistent_sync(), and then do the
correct cache maintenance operation for each of the six combinations.

Which operation that is depends on the microarchitecture to some degree,
e.g. on machines that can load arbitrary cache lines during speculative
execution, you have to invalidate the caches during both
_for_device/FROM_DEVICE _for_cpu/FROM_DEVICE, while machines
without speculative execution can skip the second invalidation, they
only need to get rid of dirty cache lines before the DMA from device.

Usually you don't have to do a writeback during _for_cpu, since there
are no dirty cache lines after the _for_device operation.

It's not entirely clear what the correct behavior is for buffers that
are not cache line aligned, some architectures use wbinval instead
of inval for the _for_device/_FROM_DEVICE operation, on
any partial cache line, but you wouldn't want to do that on the
_for_cpu/_FROM_DEVICE operation.

       Arnd

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

* Re: [PATCH 25/31] nds32: defconfig
  2017-11-09  8:00     ` Greentime Hu
@ 2017-11-09 10:20       ` Arnd Bergmann
  2017-11-10  8:16         ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-09 10:20 UTC (permalink / raw)
  To: Greentime Hu
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen, deanbo422

On Thu, Nov 9, 2017 at 9:00 AM, Greentime Hu <green.hu@gmail.com> wrote:
> 2017-11-08 18:03 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>> From: Greentime Hu <greentime@andestech.com>
>>>
>>> Signed-off-by: Vincent Chen <vincentc@andestech.com>
>>> Signed-off-by: Greentime Hu <greentime@andestech.com>
>>> ---
>>>  arch/nds32/configs/ae3xx_defconfig  |  110 +++++++++++++++++++++++++++++++++++
>>>  arch/nds32/configs/ag101p_defconfig |  109 ++++++++++++++++++++++++++++++++++
>>
>> Are those two incompatible? I would recommend starting without board
>> specific defconfig
>> files, it just gets messy once you get more than a few machines you
>> want to support.
>
> Thanks.
> These 2 are incompatible.
> They use different drivers. I may still keep these 2 defconfigs.

Using different drivers doesn't make machines incompatible. For instance, the
x86 desktop machine has drivers for all kinds of devices, but it uses
one configuration
that works on basically any x86 machine.

Similarly, we only have one defconfig file on arm64, and it works across very
diverse machines (phone, home routers, large servers, etc.).

All drivers should be written in a way to allow being built into the
kernel without
doing any harm when you don't have the respective hardware.

>>> +CONFIG_FB=y
>>> +# CONFIG_VGA_CONSOLE is not set
>>> +CONFIG_FRAMEBUFFER_CONSOLE=y
>>
>> You have a framebuffer console here, but no framebuffer driver?
>
> Thanks.
> I shall enable it when I push our framebuffer in the next time.
> I will disable it in the next version patch.

The fbdev subsystem is no longer recommended for new drivers, they
should be written on top of the DRM framework. You can use
CONFIG_DRM_FBDEV_EMULATION to get the framebuffer
console on top of that, but then you don't need to enable CONFIG_FB.

Please have a look at drivers/gpu/drm/tinydrm/ to see if you can either
use that directly, or take it as a skeleton for your own driver.

       Arnd

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

* Re: [PATCH 26/31] nds32: Build infrastructure
  2017-11-09  9:02     ` Greentime Hu
@ 2017-11-09 10:33       ` Arnd Bergmann
  2017-11-10  8:26         ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-09 10:33 UTC (permalink / raw)
  To: Greentime Hu
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

On Thu, Nov 9, 2017 at 10:02 AM, Greentime Hu <green.hu@gmail.com> wrote:
> 2017-11-08 18:16 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:

>>> +config GENERIC_CALIBRATE_DELAY
>>> +       def_bool y
>>
>> It's better to avoid the delay loop completely and skip the calibration,
>> if your hardware allows.
>
> Thanks.
> Do you mean that this config should be def_bool n?
> why? Almost all arch enable it.

It depends on what your hardware can do. If you have a way to see how much
time has passed that is guaranteed to be reliable on all machines, then
use that instead.

On a lot of architectures, it's not possible, so they have to fall back to using
the delay loop.

>>> +config ALIGNMENT_TRAP
>>> +       tristate "Kernel support unaligned access handling"
>>> +       default y
>>> +       help
>>> +         Andes processors cannot fetch/store information which is not
>>> +         naturally aligned on the bus, i.e., a 4 byte fetch must start at an
>>> +         address divisible by 4. On 32-bit Andes processors, these non-aligned
>>> +         fetch/store instructions will be emulated in software if you say
>>> +         here, which has a severe performance impact. This is necessary for
>>> +         correct operation of some network protocols. With an IP-only
>>> +         configuration it is safe to say N, otherwise say Y.
>>
>> Which network protocols are you referring to?
>
> I will modify these descriptions. It was written by someone I don't know. :p
> This case only happened when I found is compiler code gen issue or
> wrong pointer usage.

Ok, should it also be 'default n' then?

>>> +config HIGHMEM
>>> +       bool "High Memory Support"
>>> +       depends on MMU && CPU_CACHE_NONALIASING
>>> +       help
>>> +         The address space of Andes processors is only 4 Gigabytes large
>>> +         and it has to accommodate user address space, kernel address
>>> +         space as well as some memory mapped IO. That means that, if you
>>> +         have a large amount of physical memory and/or IO, not all of the
>>> +         memory can be "permanently mapped" by the kernel. The physical
>>> +         memory that is not permanently mapped is called "high memory".
>>> +
>>> +         Depending on the selected kernel/user memory split, minimum
>>> +         vmalloc space and actual amount of RAM, you may not need this
>>> +         option which should result in a slightly faster kernel.
>>> +
>>> +         If unsure, say N.
>>
>> Generally speaking, highmem support is a mess, and it's better to avoid it.
>>
>> I see that the two device tree files you have list 1GB of memory. Do you think
>> that is a common configuration for actual products? Do you expect any to
>> have more than 1GB (or more than 4GB) in the future, or is that the upper
>> end of the scale?
>>
>> If 1GB is a reasonable upper bound, then you could change the vmsplit
>> to give slightly less address space to user space and have 1GB of direct-mapped
>> kernel memory plus 256MB of vmalloc space reserved for the kernel,
>> and completely avoid highmem.
>
> Thanks.
> We do realy use 1GB ram in some products.
> We also verify CONFIG_HIGHMEM with LTP too.
> It seems fine but I will study vmsplit to see if we should use it.

For the 1GB configuration, something like ARM's CONFIG_VMSPLIT_3G_OPT
should be optimal, it will result in better performance because it allows you
to completely turn off CONFIG_HIGHMEM. The reason we don't always
use it on ARM is that traditionally we had the 3GB vmsplit, and some
applications
might rely on having the exact amount of available address space that they
expect. For a new architecture that should be less of a problem.

The interesting case is what happens if you have machines with 1.5GB or
or more physical RAM. You can obviously have another vmsplit configuration
for those, but at some point going to highmem is better than limiting the
user address space.

Ideally 1.5GB is the point where you start using a 64-bit CPU, but of course
that is not something you have available at the moment.

>>> +config MEMORY_START
>>> +       hex "Physical memory start address"
>>> +       default "0x00000000"
>>> +       help
>>> +         Physical memory start address, you may modify it if it is porting to
>>> +         a new SoC with different start address.
>>> +endmenu
>>
>> On ARM, we found options like this to be rather problematic since it prevents
>> you from running the same kernel on boards that are otherwise compatible.
>>
>> If the architecture easily allows the memory to start at address 0, could
>> you require this address for all SoCs that want to run Linux, and get
>> rid of the compile-time option?
>
> Thanks.
> The reason we need this config is because we need to define PHYS_OFFSET.
> #define PHYS_OFFSET     (CONFIG_MEMORY_START)
>
> It needs to be set in compile-time. I don't know how to get rid of it.

PHYS_OFFSET doesn't have to be a constant, a lot of architectures make
the __va()/__pa() and related functions use a variable for the offset.
This is also useful to implement KASLR, and booting the kernel from
a random physical address.

My actual suggestion however was to just mandate that PHYS_OFFSET
is always zero for your architecture, and not support any other value.
This is easy as long as you don't have existing hardware that would
break.

        Arnd

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

* Re: [PATCH 29/31] MAINTAINERS: Add nds32
  2017-11-09  9:46     ` Greentime Hu
@ 2017-11-09 10:36       ` Arnd Bergmann
  2017-11-14 15:39         ` Joe Perches
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-09 10:36 UTC (permalink / raw)
  To: Greentime Hu
  Cc: Rob Herring, Greentime, linux-kernel, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, netdev

On Thu, Nov 9, 2017 at 10:46 AM, Greentime Hu <green.hu@gmail.com> wrote:
> 2017-11-08 21:31 GMT+08:00 Rob Herring <robh+dt@kernel.org>:
>> On Tue, Nov 7, 2017 at 11:55 PM, Greentime Hu <green.hu@gmail.com> wrote:
>>> From: Greentime Hu <greentime@andestech.com>
>>>
>>> Signed-off-by: Greentime Hu <greentime@andestech.com>
>>> ---
>>>  MAINTAINERS |    9 +++++++++
>>>  1 file changed, 9 insertions(+)
>>>
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>> index 2f4e462..bce1181 100644
>>> --- a/MAINTAINERS
>>> +++ b/MAINTAINERS
>>> @@ -857,6 +857,15 @@ X: drivers/iio/*/adjd*
>>>  F:     drivers/staging/iio/*/ad*
>>>  F:     drivers/staging/iio/trigger/iio-trig-bfin-timer.c
>>>
>>> +ANDES ARCHITECTURE
>>> +M:     Greentime Hu <green.hu@gmail.com>
>>> +M:     Vincent Chen <deanbo422@gmail.com>
>>> +T:     git https://github.com/andestech/linux.git
>>> +S:     Supported
>>> +F:     arch/nds32
>>
>> DT binding files?
>
> Thanks.
> I should add
> F:    Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt
> F:    Documentation/devicetree/bindings/nds32/cpus.txt
>
> I will fix it in the next version patch.

Better make the second one the directory, in case you add more files
there later.

I would also add a "K: nds32" line to catch all files that have this
in their names.

       Arnd

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

* Re: [PATCH 30/31] dt-bindings: nds32 CPU Bindings
@ 2017-11-09 13:57         ` Rob Herring
  0 siblings, 0 replies; 116+ messages in thread
From: Rob Herring @ 2017-11-09 13:57 UTC (permalink / raw)
  To: Greentime Hu
  Cc: Rob Herring, Greentime, linux-kernel, Arnd Bergmann, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, netdev,
	Vincent Chen, Rick Chen, Zong Li, devicetree

On Thu, Nov 9, 2017 at 3:39 AM, Greentime Hu <green.hu@gmail.com> wrote:
> 2017-11-08 21:18 GMT+08:00 Rob Herring <robh+dt@kernel.org>:
>> Please Cc the DT list on bindings.
>
> Sorry. I am not sure what you mean.
> Do you mean add devicetree@vger.kernel.org to cc list?

Yes. Use get_maintainers.pl as a guide.

>> On Tue, Nov 7, 2017 at 11:55 PM, Greentime Hu <green.hu@gmail.com> wrote:
>>> From: Greentime Hu <greentime@andestech.com>
>>

>>> +                       device_type = "cpu";
>>> +                       compatible = "andestech,n13", "andestech,n15";
>>
>> n13 is a superset of n15?
>
> No, they are independent ones.

Then having both is not valid. The strings should be in order of best
match to worst match where worst match is typically either older
implementations of IP blocks or generic'ish strings such as "ns16550"
for a UART.

Rob

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

* Re: [PATCH 30/31] dt-bindings: nds32 CPU Bindings
@ 2017-11-09 13:57         ` Rob Herring
  0 siblings, 0 replies; 116+ messages in thread
From: Rob Herring @ 2017-11-09 13:57 UTC (permalink / raw)
  To: Greentime Hu
  Cc: Rob Herring, Greentime, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Arnd Bergmann, linux-arch-u79uwXL29TY76Z2rM5mHXA,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, netdev,
	Vincent Chen, Rick Chen, Zong Li,
	devicetree-u79uwXL29TY76Z2rM5mHXA

On Thu, Nov 9, 2017 at 3:39 AM, Greentime Hu <green.hu-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> 2017-11-08 21:18 GMT+08:00 Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>:
>> Please Cc the DT list on bindings.
>
> Sorry. I am not sure what you mean.
> Do you mean add devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org to cc list?

Yes. Use get_maintainers.pl as a guide.

>> On Tue, Nov 7, 2017 at 11:55 PM, Greentime Hu <green.hu-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>>> From: Greentime Hu <greentime-MUIXKm3Oiri1Z/+hSey0Gg@public.gmane.org>
>>

>>> +                       device_type = "cpu";
>>> +                       compatible = "andestech,n13", "andestech,n15";
>>
>> n13 is a superset of n15?
>
> No, they are independent ones.

Then having both is not valid. The strings should be in order of best
match to worst match where worst match is typically either older
implementations of IP blocks or generic'ish strings such as "ns16550"
for a UART.

Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 30/31] dt-bindings: nds32 CPU Bindings
  2017-11-09 13:57         ` Rob Herring
  (?)
@ 2017-11-10  6:22         ` Greentime Hu
  2017-11-10  8:25           ` Arnd Bergmann
  -1 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-10  6:22 UTC (permalink / raw)
  To: Rob Herring
  Cc: Rob Herring, Greentime, linux-kernel, Arnd Bergmann, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, netdev,
	Vincent Chen, Rick Chen, Zong Li, devicetree

2017-11-09 21:57 GMT+08:00 Rob Herring <robh@kernel.org>:
> On Thu, Nov 9, 2017 at 3:39 AM, Greentime Hu <green.hu@gmail.com> wrote:
>> 2017-11-08 21:18 GMT+08:00 Rob Herring <robh+dt@kernel.org>:
>>> Please Cc the DT list on bindings.
>>
>> Sorry. I am not sure what you mean.
>> Do you mean add devicetree@vger.kernel.org to cc list?
>
> Yes. Use get_maintainers.pl as a guide.

Roger that! Thanks!

>>> On Tue, Nov 7, 2017 at 11:55 PM, Greentime Hu <green.hu@gmail.com> wrote:
>>>> From: Greentime Hu <greentime@andestech.com>
>>>
>
>>>> +                       device_type = "cpu";
>>>> +                       compatible = "andestech,n13", "andestech,n15";
>>>
>>> n13 is a superset of n15?
>>
>> No, they are independent ones.
>
> Then having both is not valid. The strings should be in order of best
> match to worst match where worst match is typically either older
> implementations of IP blocks or generic'ish strings such as "ns16550"
> for a UART.

Thanks.
I would like to explain it more clearly.
They are independent ones in implementations.
They are implemented based on the same nds32 ISA and architecture spec
with different configurations
like cache size, page size, cache type(VIPT/PIPT), pipeline stages...
Most of them are compatible.
They use the same toolchain to build vmlinux which can run on
different nds32 cores.

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

* Re: [PATCH 13/31] nds32: DMA mapping API
  2017-11-09 10:14       ` Arnd Bergmann
@ 2017-11-10  8:13         ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-10  8:13 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen, deanbo422

2017-11-09 18:14 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Thu, Nov 9, 2017 at 8:12 AM, Greentime Hu <green.hu@gmail.com> wrote:
>> 2017-11-08 17:09 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
>>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>>
>
>>> You do the same cache operations for _to_cpu and _to_device, which
>>> usually works,
>>> but is more expensive than you need. It's better to take the ownership into
>>> account and only do what you need.
>>>
>> Like this?
>>
>> static void
>> nds32_dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle,
>>                               size_t size, enum dma_data_direction dir)
>> {
>>         consistent_sync((void *)dma_to_virt(dev, handle), size,
>> DMA_FROM_DEVICE);
>> }
>>
>> static void
>> nds32_dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
>>                                  size_t size, enum dma_data_direction dir)
>> {
>>         consistent_sync((void *)dma_to_virt(dev, handle), size,
>> DMA_TO_DEVICE);
>> }
>
> No, it's more complicated than that. You need to pass both the direction of the
> DMA transaction and the ownership to consistent_sync(), and then do the
> correct cache maintenance operation for each of the six combinations.
>
> Which operation that is depends on the microarchitecture to some degree,
> e.g. on machines that can load arbitrary cache lines during speculative
> execution, you have to invalidate the caches during both
> _for_device/FROM_DEVICE _for_cpu/FROM_DEVICE, while machines
> without speculative execution can skip the second invalidation, they
> only need to get rid of dirty cache lines before the DMA from device.
>
> Usually you don't have to do a writeback during _for_cpu, since there
> are no dirty cache lines after the _for_device operation.
>
> It's not entirely clear what the correct behavior is for buffers that
> are not cache line aligned, some architectures use wbinval instead
> of inval for the _for_device/_FROM_DEVICE operation, on
> any partial cache line, but you wouldn't want to do that on the
> _for_cpu/_FROM_DEVICE operation.


I get your point. I prefer to keep it that way because it will be a
little bit complex.
I will still study the code to see what I can improve in the next version patch.

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

* Re: [PATCH 25/31] nds32: defconfig
  2017-11-09 10:20       ` Arnd Bergmann
@ 2017-11-10  8:16         ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-10  8:16 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen, deanbo422

2017-11-09 18:20 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Thu, Nov 9, 2017 at 9:00 AM, Greentime Hu <green.hu@gmail.com> wrote:
>> 2017-11-08 18:03 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
>>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>>> From: Greentime Hu <greentime@andestech.com>
>>>>
>>>> Signed-off-by: Vincent Chen <vincentc@andestech.com>
>>>> Signed-off-by: Greentime Hu <greentime@andestech.com>
>>>> ---
>>>>  arch/nds32/configs/ae3xx_defconfig  |  110 +++++++++++++++++++++++++++++++++++
>>>>  arch/nds32/configs/ag101p_defconfig |  109 ++++++++++++++++++++++++++++++++++
>>>
>>> Are those two incompatible? I would recommend starting without board
>>> specific defconfig
>>> files, it just gets messy once you get more than a few machines you
>>> want to support.
>>
>> Thanks.
>> These 2 are incompatible.
>> They use different drivers. I may still keep these 2 defconfigs.
>
> Using different drivers doesn't make machines incompatible. For instance, the
> x86 desktop machine has drivers for all kinds of devices, but it uses
> one configuration
> that works on basically any x86 machine.
>
> Similarly, we only have one defconfig file on arm64, and it works across very
> diverse machines (phone, home routers, large servers, etc.).
>
> All drivers should be written in a way to allow being built into the
> kernel without
> doing any harm when you don't have the respective hardware.

Thanks.
Make sense.
I will keep only one defconfig in the next version patch.

>>>> +CONFIG_FB=y
>>>> +# CONFIG_VGA_CONSOLE is not set
>>>> +CONFIG_FRAMEBUFFER_CONSOLE=y
>>>
>>> You have a framebuffer console here, but no framebuffer driver?
>>
>> Thanks.
>> I shall enable it when I push our framebuffer in the next time.
>> I will disable it in the next version patch.
>
> The fbdev subsystem is no longer recommended for new drivers, they
> should be written on top of the DRM framework. You can use
> CONFIG_DRM_FBDEV_EMULATION to get the framebuffer
> console on top of that, but then you don't need to enable CONFIG_FB.
>
> Please have a look at drivers/gpu/drm/tinydrm/ to see if you can either
> use that directly, or take it as a skeleton for your own driver.
>

Thanks.
We will check how to use CONFIG_DRM_FBDEV_EMULATION to get framebuffer.

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

* Re: [PATCH 30/31] dt-bindings: nds32 CPU Bindings
  2017-11-10  6:22         ` Greentime Hu
@ 2017-11-10  8:25           ` Arnd Bergmann
  2017-11-10  8:43               ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-10  8:25 UTC (permalink / raw)
  To: Greentime Hu
  Cc: Rob Herring, Rob Herring, Greentime, linux-kernel, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, netdev,
	Vincent Chen, Rick Chen, Zong Li, devicetree

On Fri, Nov 10, 2017 at 7:22 AM, Greentime Hu <green.hu@gmail.com> wrote:
> 2017-11-09 21:57 GMT+08:00 Rob Herring <robh@kernel.org>:
>> On Thu, Nov 9, 2017 at 3:39 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>> 2017-11-08 21:18 GMT+08:00 Rob Herring <robh+dt@kernel.org>:
>>>> Please Cc the DT list on bindings.
>>>
>>> Sorry. I am not sure what you mean.
>>> Do you mean add devicetree@vger.kernel.org to cc list?
>>
>> Yes. Use get_maintainers.pl as a guide.
>
> Roger that! Thanks!
>
>>>> On Tue, Nov 7, 2017 at 11:55 PM, Greentime Hu <green.hu@gmail.com> wrote:
>>>>> From: Greentime Hu <greentime@andestech.com>
>>>>
>>
>>>>> +                       device_type = "cpu";
>>>>> +                       compatible = "andestech,n13", "andestech,n15";
>>>>
>>>> n13 is a superset of n15?
>>>
>>> No, they are independent ones.
>>
>> Then having both is not valid. The strings should be in order of best
>> match to worst match where worst match is typically either older
>> implementations of IP blocks or generic'ish strings such as "ns16550"
>> for a UART.
>
> Thanks.
> I would like to explain it more clearly.
> They are independent ones in implementations.
> They are implemented based on the same nds32 ISA and architecture spec
> with different configurations
> like cache size, page size, cache type(VIPT/PIPT), pipeline stages...
> Most of them are compatible.
> They use the same toolchain to build vmlinux which can run on
> different nds32 cores.

Du you have a name for the ISA spec that distinguishes it from other nds32
versions that are incompatible? If you do, this could be written like

compatible = "andestech,n13", "andestech,nds32v3.0";

to signify that a an 'n13' core implements the 'v3.0' ISA (will it
whatever you call the ISA in reality).

       Arnd

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

* Re: [PATCH 26/31] nds32: Build infrastructure
  2017-11-09 10:33       ` Arnd Bergmann
@ 2017-11-10  8:26         ` Greentime Hu
  2017-11-17 12:39           ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-10  8:26 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

2017-11-09 18:33 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Thu, Nov 9, 2017 at 10:02 AM, Greentime Hu <green.hu@gmail.com> wrote:
>> 2017-11-08 18:16 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
>>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>
>>>> +config GENERIC_CALIBRATE_DELAY
>>>> +       def_bool y
>>>
>>> It's better to avoid the delay loop completely and skip the calibration,
>>> if your hardware allows.
>>
>> Thanks.
>> Do you mean that this config should be def_bool n?
>> why? Almost all arch enable it.
>
> It depends on what your hardware can do. If you have a way to see how much
> time has passed that is guaranteed to be reliable on all machines, then
> use that instead.
>
> On a lot of architectures, it's not possible, so they have to fall back to using
> the delay loop.

I get it. I will discuss it with our HW colleagues.
We may get these informations in some registers.

>>>> +config ALIGNMENT_TRAP
>>>> +       tristate "Kernel support unaligned access handling"
>>>> +       default y
>>>> +       help
>>>> +         Andes processors cannot fetch/store information which is not
>>>> +         naturally aligned on the bus, i.e., a 4 byte fetch must start at an
>>>> +         address divisible by 4. On 32-bit Andes processors, these non-aligned
>>>> +         fetch/store instructions will be emulated in software if you say
>>>> +         here, which has a severe performance impact. This is necessary for
>>>> +         correct operation of some network protocols. With an IP-only
>>>> +         configuration it is safe to say N, otherwise say Y.
>>>
>>> Which network protocols are you referring to?
>>
>> I will modify these descriptions. It was written by someone I don't know. :p
>> This case only happened when I found is compiler code gen issue or
>> wrong pointer usage.
>
> Ok, should it also be 'default n' then?

Yup. I will use 'default n' in the next version patch.

>>>> +config HIGHMEM
>>>> +       bool "High Memory Support"
>>>> +       depends on MMU && CPU_CACHE_NONALIASING
>>>> +       help
>>>> +         The address space of Andes processors is only 4 Gigabytes large
>>>> +         and it has to accommodate user address space, kernel address
>>>> +         space as well as some memory mapped IO. That means that, if you
>>>> +         have a large amount of physical memory and/or IO, not all of the
>>>> +         memory can be "permanently mapped" by the kernel. The physical
>>>> +         memory that is not permanently mapped is called "high memory".
>>>> +
>>>> +         Depending on the selected kernel/user memory split, minimum
>>>> +         vmalloc space and actual amount of RAM, you may not need this
>>>> +         option which should result in a slightly faster kernel.
>>>> +
>>>> +         If unsure, say N.
>>>
>>> Generally speaking, highmem support is a mess, and it's better to avoid it.
>>>
>>> I see that the two device tree files you have list 1GB of memory. Do you think
>>> that is a common configuration for actual products? Do you expect any to
>>> have more than 1GB (or more than 4GB) in the future, or is that the upper
>>> end of the scale?
>>>
>>> If 1GB is a reasonable upper bound, then you could change the vmsplit
>>> to give slightly less address space to user space and have 1GB of direct-mapped
>>> kernel memory plus 256MB of vmalloc space reserved for the kernel,
>>> and completely avoid highmem.
>>
>> Thanks.
>> We do realy use 1GB ram in some products.
>> We also verify CONFIG_HIGHMEM with LTP too.
>> It seems fine but I will study vmsplit to see if we should use it.
>
> For the 1GB configuration, something like ARM's CONFIG_VMSPLIT_3G_OPT
> should be optimal, it will result in better performance because it allows you
> to completely turn off CONFIG_HIGHMEM. The reason we don't always
> use it on ARM is that traditionally we had the 3GB vmsplit, and some
> applications
> might rely on having the exact amount of available address space that they
> expect. For a new architecture that should be less of a problem.
>
> The interesting case is what happens if you have machines with 1.5GB or
> or more physical RAM. You can obviously have another vmsplit configuration
> for those, but at some point going to highmem is better than limiting the
> user address space.
>
> Ideally 1.5GB is the point where you start using a 64-bit CPU, but of course
> that is not something you have available at the moment.



>>>> +config MEMORY_START
>>>> +       hex "Physical memory start address"
>>>> +       default "0x00000000"
>>>> +       help
>>>> +         Physical memory start address, you may modify it if it is porting to
>>>> +         a new SoC with different start address.
>>>> +endmenu
>>>
>>> On ARM, we found options like this to be rather problematic since it prevents
>>> you from running the same kernel on boards that are otherwise compatible.
>>>
>>> If the architecture easily allows the memory to start at address 0, could
>>> you require this address for all SoCs that want to run Linux, and get
>>> rid of the compile-time option?
>>
>> Thanks.
>> The reason we need this config is because we need to define PHYS_OFFSET.
>> #define PHYS_OFFSET     (CONFIG_MEMORY_START)
>>
>> It needs to be set in compile-time. I don't know how to get rid of it.
>
> PHYS_OFFSET doesn't have to be a constant, a lot of architectures make
> the __va()/__pa() and related functions use a variable for the offset.
> This is also useful to implement KASLR, and booting the kernel from
> a random physical address.
>
> My actual suggestion however was to just mandate that PHYS_OFFSET
> is always zero for your architecture, and not support any other value.
> This is easy as long as you don't have existing hardware that would
> break.

Thanks.
I will check how other architectures do.
I can mandate that PHYS_OFFSET is zero but our customers(SoC company)
may not use 0x0 as default DRAM starting address.
This assumption is a little bit too strong.

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

* Re: [PATCH 30/31] dt-bindings: nds32 CPU Bindings
@ 2017-11-10  8:43               ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-10  8:43 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Rob Herring, Rob Herring, Greentime, linux-kernel, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, netdev,
	Vincent Chen, Rick Chen, Zong Li, devicetree

>>> Then having both is not valid. The strings should be in order of best
>>> match to worst match where worst match is typically either older
>>> implementations of IP blocks or generic'ish strings such as "ns16550"
>>> for a UART.
>>
>> Thanks.
>> I would like to explain it more clearly.
>> They are independent ones in implementations.
>> They are implemented based on the same nds32 ISA and architecture spec
>> with different configurations
>> like cache size, page size, cache type(VIPT/PIPT), pipeline stages...
>> Most of them are compatible.
>> They use the same toolchain to build vmlinux which can run on
>> different nds32 cores.
>
> Du you have a name for the ISA spec that distinguishes it from other nds32
> versions that are incompatible? If you do, this could be written like
>
> compatible = "andestech,n13", "andestech,nds32v3.0";
>
> to signify that a an 'n13' core implements the 'v3.0' ISA (will it
> whatever you call the ISA in reality).
>

Thanks. I got you.
I will use a proper name(maybe 'nds32v3') of ISA in this compatible
string in the next version patch.

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

* Re: [PATCH 30/31] dt-bindings: nds32 CPU Bindings
@ 2017-11-10  8:43               ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-10  8:43 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Rob Herring, Rob Herring, Greentime,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arch-u79uwXL29TY76Z2rM5mHXA, Thomas Gleixner, Jason Cooper,
	Marc Zyngier, netdev, Vincent Chen, Rick Chen, Zong Li,
	devicetree-u79uwXL29TY76Z2rM5mHXA

>>> Then having both is not valid. The strings should be in order of best
>>> match to worst match where worst match is typically either older
>>> implementations of IP blocks or generic'ish strings such as "ns16550"
>>> for a UART.
>>
>> Thanks.
>> I would like to explain it more clearly.
>> They are independent ones in implementations.
>> They are implemented based on the same nds32 ISA and architecture spec
>> with different configurations
>> like cache size, page size, cache type(VIPT/PIPT), pipeline stages...
>> Most of them are compatible.
>> They use the same toolchain to build vmlinux which can run on
>> different nds32 cores.
>
> Du you have a name for the ISA spec that distinguishes it from other nds32
> versions that are incompatible? If you do, this could be written like
>
> compatible = "andestech,n13", "andestech,nds32v3.0";
>
> to signify that a an 'n13' core implements the 'v3.0' ISA (will it
> whatever you call the ISA in reality).
>

Thanks. I got you.
I will use a proper name(maybe 'nds32v3') of ISA in this compatible
string in the next version patch.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 12/31] nds32: Device specific operations
  2017-11-09  7:04     ` Greentime Hu
@ 2017-11-10 16:07       ` Greentime Hu
  2017-11-10 16:14         ` Arnd Bergmann
  0 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-10 16:07 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen, deanbo422

2017-11-09 15:04 GMT+08:00 Greentime Hu <green.hu@gmail.com>:
> 2017-11-08 17:04 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>
>>> +
>>> +#define ioremap(cookie,size)           __ioremap(cookie,size,0,1)
>>> +#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
>>> +#define iounmap(cookie)                        __iounmap(cookie)
>>
>>> +#include <asm-generic/io.h>
>>
>> asm-generic/io.h now provides an ioremap_nocache() helper along with
>> ioremap_uc/ioremap_wc/ioremap_wt, so I think you can remove the
>> ioremap_nocache definition here. You might also be able to remove
>> __ioremap and __iounmap, and only provide ioremap/iounmap, plus
>> the identity macro 'define ioremap ioremap'
>
> Thanks. I will try to use generic ioremap_nocache() helper in the next
> version patch.

I think I can't remove ioremap_nocache definition because it is defined
in asm-generic/io.h with !CONFIG_MMU.

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

* Re: [PATCH 12/31] nds32: Device specific operations
  2017-11-10 16:07       ` Greentime Hu
@ 2017-11-10 16:14         ` Arnd Bergmann
  2017-11-22 10:02           ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-10 16:14 UTC (permalink / raw)
  To: Greentime Hu
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen, deanbo422

On Fri, Nov 10, 2017 at 5:07 PM, Greentime Hu <green.hu@gmail.com> wrote:
> 2017-11-09 15:04 GMT+08:00 Greentime Hu <green.hu@gmail.com>:
>> 2017-11-08 17:04 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
>>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>>
>>>> +
>>>> +#define ioremap(cookie,size)           __ioremap(cookie,size,0,1)
>>>> +#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
>>>> +#define iounmap(cookie)                        __iounmap(cookie)
>>>
>>>> +#include <asm-generic/io.h>
>>>
>>> asm-generic/io.h now provides an ioremap_nocache() helper along with
>>> ioremap_uc/ioremap_wc/ioremap_wt, so I think you can remove the
>>> ioremap_nocache definition here. You might also be able to remove
>>> __ioremap and __iounmap, and only provide ioremap/iounmap, plus
>>> the identity macro 'define ioremap ioremap'
>>
>> Thanks. I will try to use generic ioremap_nocache() helper in the next
>> version patch.
>
> I think I can't remove ioremap_nocache definition because it is defined
> in asm-generic/io.h with !CONFIG_MMU.

Ah, I see.

Could you move ioremap_nocache/ioremap_uc/ioremap_wc/ioremap_wt
out of that #ifdef, or would that break other architectures?

      Arnd

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

* Fwd: FW: [PATCH 17/31] nds32: Signal handling support
       [not found]     ` <E26F4CF8B7DDDB4383A6C2D78D5C3CD56B497460@ATCPCS16.andestech.com>
@ 2017-11-13  2:34       ` Vincent Chen
  0 siblings, 0 replies; 116+ messages in thread
From: Vincent Chen @ 2017-11-13  2:34 UTC (permalink / raw)
  To: viro
  Cc: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev, vincentc

>> +static int restore_sigframe(struct pt_regs *regs,
>> +                         struct rt_sigframe __user * sf) {
>
>[snip]
>
>> +     err |= !valid_user_regs(regs);
>
>IDGI...  Where do you modify ->ipsw at all and how can valid_user_regs() come to be false here?
>
Thanks.
This code is trivial and I will remove it in the next version patch



>> +asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) {
>> +     struct rt_sigframe __user *frame;
>> +
>> +     /* Always make any pending restarted system calls return -EINTR */
>> +     current->restart_block.fn = do_no_restart_syscall;
>> +
>> +     /*
>> +      * Since we stacked the signal on a 64-bit boundary,
>> +      * then 'sp' should be two-word aligned here.  If it's
>> +      * not, then the user is trying to mess with us.
>> +      */
>> +     if (regs->sp & 7)
>> +             goto badframe;
>> +
>> +     frame = (struct rt_sigframe __user *)regs->sp;
>> +
>> +     if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
>> +             goto badframe;
>> +
>> +     if (restore_sigframe(regs, frame))
>> +             goto badframe;
>> +
>> +     if (restore_altstack(&frame->uc.uc_stack))
>> +             goto badframe;
>> +
>> +     return regs->uregs[0];
>> +
>> +badframe:
>> +     force_sig(SIGSEGV, current);
>> +     return 0;
>> +}\
>
>AFAICS, you are copying arm; take a good look at sys_rt_sigreturn_wrapper there - specifically, the 'mov why, #0' part.  Consider what happens if you get an interrupt at the moment when $r0 contains -ERESTARTSYS (for
example) and signal arrives while we are processing the interrupt.  It
will be handled on the way out, without any syscall restart crap
('why'
is 0 on that codepath).  So far, so good, but think what'll happen
when you are done with the signal handler.  sigreturn() is called, the
values we had stashed in sigcontext go back into registers (OK,
pt_regs on kernel stack that will be used to reload the registers on
return to userland)... and the signals that had been blocked for the
duration of handlers (see sa_mask in sigaction(2)) get unblocked.  And
it turns out that you have one of those pending - it had arrived while
we'd been in the handler.

>Now we are fucked.  You have TIF_SIGPENDING set, so do_notify_resume() is called.  And everything looks exactly as if you had a syscall restart situation - regs->uregs[0] being one of -ERESTART... and 'syscall' flag being true.  So we go into the second signal handler (as we ought to) with saved ->ipc set 4 bytes back from where we were going to return.
>It would've been the right thing to do if it *was* a syscall restart, but we were returning to the location where the original interrupt had caught us.
>
>Result: with the right timing, an interrupt arriving when userland process has $r0 equal -512 may lead to instruction pointer jumping 4 bytes back.
>Pity the poor sod trying to debug that kind of breakage...
>
>Restart should *NOT* be triggered upon sigreturn(2).

Thanks for your detailed description.
I got it and I will fix this bug in the next version patch


>>
>> +static int
>> +setup_return(struct pt_regs *regs, struct ksignal *ksig, void __user
>> +* frame) {
>> +     unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler;
>> +     unsigned long retcode;
>> +
>> +     /*
>> +      * Maybe we need to deliver a 32-bit signal to a 26-bit task.
>>
>Deliver to what, again?  That comment made sense (if rather sad one) on arm, but what is it doing here?
>
Thanks.
I will remove it in the next version patch


>> +static int do_signal(struct pt_regs *regs, int syscall) {
>> +     unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
>> +     struct ksignal ksig;
>> +     int restart = 0;
>> +
>> +     /*
>> +      * 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 0;
>
>Which cases would those be?

Thanks.
This code is trivial too. I will remove it in the next version patch

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

* Fwd: FW: [PATCH 15/31] nds32: System calls handling
       [not found]     ` <E26F4CF8B7DDDB4383A6C2D78D5C3CD56B497241@ATCPCS16.andestech.com>
@ 2017-11-13  2:51       ` Vincent Chen
  2017-11-13 11:42         ` Arnd Bergmann
  0 siblings, 1 reply; 116+ messages in thread
From: Vincent Chen @ 2017-11-13  2:51 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: greentime, linux-kernel, linux-arch, tglx, jason, marc.zyngier,
	robh+dt, netdev, vincentc

>>On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>> From: Greentime Hu <greentime@andestech.com>
>
>> +#endif /* __ASM_NDS32_SYSCALLS_H */
>> diff --git a/arch/nds32/include/asm/unistd.h
>> b/arch/nds32/include/asm/unistd.h new file mode 100644 index
>> 0000000..b30adca
>> --- /dev/null
>> +++ b/arch/nds32/include/asm/unistd.h
>> @@ -0,0 +1,21 @@
>
>> +#define __ARCH_WANT_SYS_LLSEEK
>
>This gets set from include/asm-generic/unistd.h if you include that file.
>
Dear Arnd:

Thanks
I will remove it in the next version patch.


>> +#define __ARCH_WANT_SYS_CLONE
>
>This seems ok, though it would be nice to have the reverse logic and have architectures opt-out of the generic version when they need to provide their own, rather than having most architectures set it.
>

Thanks
I will provide nds32 SYSCALL_DEFINE_5(clone) in the next version patch.

>> +#define __ARCH_WANT_SYS_OLD_MMAP
>
>I don't see why you need this, can it be dropped?

Thanks
I will remove it in the next version patch.

>
>> diff --git a/arch/nds32/include/uapi/asm/unistd.h
>> b/arch/nds32/include/uapi/asm/unistd.h
>> new file mode 100644
>> index 0000000..01b466d
>> --- /dev/null
>> +++ b/arch/nds32/include/uapi/asm/unistd.h
>
>> +#define __NR_ipc               (__NR_arch_specific_syscall + 2)
>> +#define __NR_sysfs             (__NR_arch_specific_syscall + 3)
>> +#define __NR__llseek             __NR_llseek
>
>
>
>> +__SYSCALL(__NR_cacheflush, sys_cacheflush) __SYSCALL(__NR_syscall,
>> +sys_syscall) __SYSCALL(__NR_ipc, sys_ipc) __SYSCALL(__NR_sysfs,
>> +sys_sysfs)
>> +
>> +__SYSCALL(__NR_fadvise64_64, sys_fadvise64_64_wrapper)
>> +__SYSCALL(__NR_rt_sigreturn, sys_rt_sigreturn_wrapper)
>> +__SYSCALL(__NR_mmap, sys_old_mmap)
>
>Usually we handle those overrides by defining the macros in asm/unistd.h before including the asm-generic version. Can you do that as well for consistency?
>

Thanks
Ok, I will modify it in the next version patch

>I don't see a reason for sys_ipc, sys_sysfs or sys_old_mmap() here in a new architecture. Can you drop those or explain why you need them?
>

Thanks
 I will remove them in the next version patch

>> +/*
>> + * Special system call wrappers
>> + *
>> + * $r0 = syscall number
>> + * $r8 = syscall table
>> + */
>> +       .type   sys_syscall, #function
>> +ENTRY(sys_syscall)
>> +       addi    $p1, $r0, #-__NR_syscalls
>> +       bgtz    $p1, 3f
>> +       move    $p1, $r0
>> +       move    $r0, $r1
>> +       move    $r1, $r2
>> +       move    $r2, $r3
>> +       move    $r3, $r4
>> +       move    $r4, $r5
>> +! add for syscall 6 args
>> +       lwi     $r5, [$sp + #SP_OFFSET ]
>> +       lwi     $r5, [$r5]
>> +! ~add for syscall 6 args
>> +
>> +       lw      $p1, [tbl+$p1<<2]
>> .+       jr      $p1
>> +3:     b       sys_ni_syscall
>> +ENDPROC(sys_syscall)
>
>Can you explain what this is used for?
>

This is used to handle syscall(int number, ....).
Unlike other architectures,  the system number shall be determined in
compile time when issuing system call in nds32.
Therefore, we  only can parse the content of syscall(int number, ....)
and distribute it to destination handler in kernel space
(Other architecture can handle it in user space by glibc's syscall wrapper)

>> --- /dev/null
>> +++ b/arch/nds32/kernel/sys_nds32.c
>> +
>> +long sys_mmap2(unsigned long addr, unsigned long len,
>> +              unsigned long prot, unsigned long flags,
>> +              unsigned long fd, unsigned long pgoff) {
>> +       if (pgoff & (~PAGE_MASK >> 12))
>> +               return -EINVAL;
>> +
>> +       return sys_mmap_pgoff(addr, len, prot, flags, fd,
>> +                             pgoff >> (PAGE_SHIFT - 12)); }
>> +
>> +asmlinkage long sys_fadvise64_64_wrapper(int fd, int advice, loff_t offset,
>> +                                        loff_t len) {
>> +       return sys_fadvise64_64(fd, offset, len, advice); }
>
>You should always use SYSCALL_DEFINE*() macros to define entry points for your own syscalls in C code for consistency. I also wonder if we should just move those two into common code, a lot of architectures need the first one in particular.
>

The sys_fadvise64_64_wrapper is used to reorder the input parameter.

In order to solve register alignment problem, we adjust the input
parameter order of fadvise64_64 while issuing this syscall.
Therefore, we need this wrapper to reorder the input parameter to fit
sys_fadvise64_64's API in kernel.

>       Arnd


Best regard
Vincent

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

* Re: [PATCH 26/31] nds32: Build infrastructure
  2017-11-08 10:16   ` Arnd Bergmann
@ 2017-11-13 10:45       ` Geert Uytterhoeven
  2017-11-13 10:45       ` Geert Uytterhoeven
  1 sibling, 0 replies; 116+ messages in thread
From: Geert Uytterhoeven @ 2017-11-13 10:45 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime Hu, greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

On Wed, Nov 8, 2017 at 11:16 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>> --- /dev/null
>> +++ b/arch/nds32/Kconfig
>> @@ -0,0 +1,107 @@
>> +#
>> +# For a description of the syntax of this configuration file,
>> +# see Documentation/kbuild/kconfig-language.txt.
>> +#
>> +
>> +config NDS32
>> +        def_bool y
>> +       select ARCH_HAS_RAW_COPY_USER
>> +       select ARCH_WANT_FRAME_POINTERS if FTRACE
>> +       select ARCH_WANT_IPC_PARSE_VERSION
>> +       select CLKSRC_MMIO
>> +       select CLONE_BACKWARDS
>> +       select TIMER_OF
>> +       select FRAME_POINTER
>> +       select GENERIC_ATOMIC64
>> +       select GENERIC_CPU_DEVICES
>> +       select GENERIC_CLOCKEVENTS
>> +       select GENERIC_IOMAP
>> +       select GENERIC_IRQ_CHIP
>> +       select GENERIC_IRQ_PROBE
>> +       select GENERIC_IRQ_SHOW
>> +       select GENERIC_STRNCPY_FROM_USER
>> +       select GENERIC_STRNLEN_USER
>> +       select GENERIC_TIME_VSYSCALL
>> +       select HAVE_ARCH_TRACEHOOK
>> +       select HAVE_GENERIC_IOMAP
>
> You normally don't want HAVE_GENERIC_IOMAP, at least unless the CPU
> has special instructions to trigger PCI I/O port access.

GENERIC_IOMAP or HAVE_GENERIC_IOMAP?

The latter doesn't even exist, except in
Documentation/kbuild/kconfig-language.txt, so it cannot be selected.

Given the checks for __NDS32_EB__, NDS32 can be either big or little endian,
so you should have (excatly one of) CPU_BIG_ENDIAN or CPU_LITTLE_ENDIAN set.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 26/31] nds32: Build infrastructure
@ 2017-11-13 10:45       ` Geert Uytterhoeven
  0 siblings, 0 replies; 116+ messages in thread
From: Geert Uytterhoeven @ 2017-11-13 10:45 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime Hu, greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

On Wed, Nov 8, 2017 at 11:16 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>> --- /dev/null
>> +++ b/arch/nds32/Kconfig
>> @@ -0,0 +1,107 @@
>> +#
>> +# For a description of the syntax of this configuration file,
>> +# see Documentation/kbuild/kconfig-language.txt.
>> +#
>> +
>> +config NDS32
>> +        def_bool y
>> +       select ARCH_HAS_RAW_COPY_USER
>> +       select ARCH_WANT_FRAME_POINTERS if FTRACE
>> +       select ARCH_WANT_IPC_PARSE_VERSION
>> +       select CLKSRC_MMIO
>> +       select CLONE_BACKWARDS
>> +       select TIMER_OF
>> +       select FRAME_POINTER
>> +       select GENERIC_ATOMIC64
>> +       select GENERIC_CPU_DEVICES
>> +       select GENERIC_CLOCKEVENTS
>> +       select GENERIC_IOMAP
>> +       select GENERIC_IRQ_CHIP
>> +       select GENERIC_IRQ_PROBE
>> +       select GENERIC_IRQ_SHOW
>> +       select GENERIC_STRNCPY_FROM_USER
>> +       select GENERIC_STRNLEN_USER
>> +       select GENERIC_TIME_VSYSCALL
>> +       select HAVE_ARCH_TRACEHOOK
>> +       select HAVE_GENERIC_IOMAP
>
> You normally don't want HAVE_GENERIC_IOMAP, at least unless the CPU
> has special instructions to trigger PCI I/O port access.

GENERIC_IOMAP or HAVE_GENERIC_IOMAP?

The latter doesn't even exist, except in
Documentation/kbuild/kconfig-language.txt, so it cannot be selected.

Given the checks for __NDS32_EB__, NDS32 can be either big or little endian,
so you should have (excatly one of) CPU_BIG_ENDIAN or CPU_LITTLE_ENDIAN set.

Gr{oetje,eeting}s,

                        Geert

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

* Fwd: FW: [PATCH 04/31] nds32: Exception handling
       [not found]     ` <E26F4CF8B7DDDB4383A6C2D78D5C3CD56B4974CE@ATCPCS16.andestech.com>
@ 2017-11-13 10:54       ` Vincent Chen
  0 siblings, 0 replies; 116+ messages in thread
From: Vincent Chen @ 2017-11-13 10:54 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: greentime, linux-kernel, linux-arch, tglx, jason, marc.zyngier,
	robh+dt, netdev

>> From: Greentime Hu <greentime@andestech.com>
>>
>> Signed-off-by: Vincent Chen <vincentc@andestech.com>
>> Signed-off-by: Greentime Hu <greentime@andestech.com>
>>  arch/nds32/mm/alignment.c       |  564 +++++++++++++++++++++++++++++++++++++++
>
>> diff --git a/arch/nds32/mm/alignment.c b/arch/nds32/mm/alignment.c new
>> file mode 100644 index 0000000..05589e7
>> --- /dev/null
>> +++ b/arch/nds32/mm/alignment.c
>
>> +static int mode = 0x3;
>> +module_param(mode, int, S_IWUSR | S_IRUGO);
>
>It's an interesting question how to best handle alignment faults, both in
>kernel and user mode. While it can help for debugging to have the handler,
>I'd argue that you are better off in the long run not fixing up the faults
>automatically but to modify the code that triggers them instead.
>
>How about making the faults disabled by default?

Thanks
OK, I will disable alignment fault handling by default in next version patch

>> +static int _do_unaligned_access(unsigned long entry, unsigned long addr,
>> +                               unsigned long type, struct pt_regs *regs)
>> +{
>> +       unsigned long inst;
>> +       int ret = -EFAULT;
>> +
>> +       if (user_mode(regs)) {
>> +               /* user mode */
>> +               if (!va_present(current->mm, addr))
>> +                       return ret;
>> +       } else {
>> +               /* kernel mode */
>> +               if (!va_kernel_present(addr))
>> +                       return ret;
>> +       }
>
>This looks racy, the address might be present when you get here, but not
>later when you actually access it. I think what you need here is something
>like ARM does with get32_unaligned_check() etc and their fixup tables.

Thanks.
I will follow your suggestion to modify it


>> +       inst = get_inst(regs->ipc);
>> +
>> +       DEBUG(mode & 0x04, 1,
>> +             "Faulting Addr: 0x%08lx, PC: 0x%08lx [ 0x%08lx ]\n", addr,
>> +             regs->ipc, inst);
>> +
>> +       if ((user_mode(regs) && (mode & 0x01))
>> +           || (!user_mode(regs) && (mode & 0x02))) {
>> +
>> +               mm_segment_t seg = get_fs();
>> +
>> +               set_fs(KERNEL_DS);
>> +
>> +               if (inst & 0x80000000)
>> +                       ret = do_16((inst >> 16) & 0xffff, regs);
>> +               else
>> +                       ret = do_32(inst, regs);
>> +
>> +               set_fs(seg);
>> +       }
>> +
>> +       return ret;
>> +}
>
>Doesn't this allow user space to read all of kernel memory simply by
>passing unaligned addresses?

Thanks
I will fix it in next version patch.


>> +static const struct file_operations fops = {
>> +       .open = simple_open,
>> +       .read = proc_alignment_read,
>> +       .write = proc_alignment_write,
>> +};
>
>This should really be a sysctl rather than an open-coded procfs file,
>for consistency with other architectures.
>
>Please have a look at that interface on other architectures and pick
>whatever the majority do.

OK. I will use sysctl instaed of procfs to control this alignment
correction feature.
Thanks

>
>     Arnd

Best regards
Vincent

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

* Re: FW: [PATCH 15/31] nds32: System calls handling
  2017-11-13  2:51       ` Fwd: FW: " Vincent Chen
@ 2017-11-13 11:42         ` Arnd Bergmann
  2017-11-22  3:13           ` Vincent Chen
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-13 11:42 UTC (permalink / raw)
  To: Vincent Chen
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

On Mon, Nov 13, 2017 at 3:51 AM, Vincent Chen <deanbo422@gmail.com> wrote:
>>>On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>> From: Greentime Hu <greentime@andestech.com>

>
>>> +#define __ARCH_WANT_SYS_CLONE
>>
>>This seems ok, though it would be nice to have the reverse logic and have architectures opt-out of the generic version when they need to provide their own, rather than having most architectures set it.
>>
>
> Thanks
> I will provide nds32 SYSCALL_DEFINE_5(clone) in the next version patch.

That's not what I meant, my suggestion is to create a new patch to remove the
__ARCH_WANT_SYS_CLONE symbol from all architectures, and instead use
something like __ARCH_HAVE_SYS_CLONE on architectures that do *not*
want the generic implementation.

nds32 clearly wants the generic implementation here, it just shouldn't have to
select that symbol to get it.

>>> +/*
>>> + * Special system call wrappers
>>> + *
>>> + * $r0 = syscall number
>>> + * $r8 = syscall table
>>> + */
>>> +       .type   sys_syscall, #function
>>> +ENTRY(sys_syscall)
>>> +       addi    $p1, $r0, #-__NR_syscalls
>>> +       bgtz    $p1, 3f
>>> +       move    $p1, $r0
>>> +       move    $r0, $r1
>>> +       move    $r1, $r2
>>> +       move    $r2, $r3
>>> +       move    $r3, $r4
>>> +       move    $r4, $r5
>>> +! add for syscall 6 args
>>> +       lwi     $r5, [$sp + #SP_OFFSET ]
>>> +       lwi     $r5, [$r5]
>>> +! ~add for syscall 6 args
>>> +
>>> +       lw      $p1, [tbl+$p1<<2]
>>> .+       jr      $p1
>>> +3:     b       sys_ni_syscall
>>> +ENDPROC(sys_syscall)
>>
>>Can you explain what this is used for?
>>
>
> This is used to handle syscall(int number, ....).
> Unlike other architectures,  the system number shall be determined in
> compile time when issuing system call in nds32.
> Therefore, we  only can parse the content of syscall(int number, ....)
> and distribute it to destination handler in kernel space
> (Other architecture can handle it in user space by glibc's syscall wrapper)

Hmm, I think other architectures that run into this problem use self-modifying
code for syscall(), but that is also ugly as it requires having a page that
is both writable and executable.

I think your approach can be tricky for things like seccomp(). It's possible
that you get all of it right, but if you can come up with a different solution,
that might be better.

How much would it cost to simply always pass the syscall number
in a register, and not use the immediate argument at all?

>>> --- /dev/null
>>> +++ b/arch/nds32/kernel/sys_nds32.c
>>> +
>>> +long sys_mmap2(unsigned long addr, unsigned long len,
>>> +              unsigned long prot, unsigned long flags,
>>> +              unsigned long fd, unsigned long pgoff) {
>>> +       if (pgoff & (~PAGE_MASK >> 12))
>>> +               return -EINVAL;
>>> +
>>> +       return sys_mmap_pgoff(addr, len, prot, flags, fd,
>>> +                             pgoff >> (PAGE_SHIFT - 12)); }
>>> +
>>> +asmlinkage long sys_fadvise64_64_wrapper(int fd, int advice, loff_t offset,
>>> +                                        loff_t len) {
>>> +       return sys_fadvise64_64(fd, offset, len, advice); }
>>
>>You should always use SYSCALL_DEFINE*() macros to define entry points for your own syscalls in C code for consistency. I also wonder if we should just move those two into common code, a lot of architectures need the first one in particular.
>>
>
> The sys_fadvise64_64_wrapper is used to reorder the input parameter.
>
> In order to solve register alignment problem, we adjust the input
> parameter order of fadvise64_64 while issuing this syscall.
> Therefore, we need this wrapper to reorder the input parameter to fit
> sys_fadvise64_64's API in kernel.

I understand what it's used for, it's just that I would recommend writing it
differently, as

SYSCALL_DEFINE4(fadvise64_64_wrapper, int, fd, int, advice, loff_t,
offset, loff_t, len)
{
       return sys_fadvise64_64(fd, offset, len, advice);
}

      Arnd

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

* Fwd: FW: [PATCH 18/31] nds32: Library functions
       [not found]     ` <E26F4CF8B7DDDB4383A6C2D78D5C3CD56B497559@ATCPCS16.andestech.com>
@ 2017-11-14  4:47       ` Vincent Chen
  2017-11-18  2:44         ` Al Viro
  0 siblings, 1 reply; 116+ messages in thread
From: Vincent Chen @ 2017-11-14  4:47 UTC (permalink / raw)
  To: viro
  Cc: greentime, Green Hu, linux-kernel, Arnd Bergmann, linux-arch,
	tglx, jason, marc.zyngier, robh+dt, netdev, vincentc

>>On Wed, Nov 08, 2017 at 01:55:06PM +0800, Greentime Hu wrote:
>
>> +#define __range_ok(addr, size) (size <= get_fs() && addr <= (get_fs()
>> +-size))
>> +
>> +#define access_ok(type, addr, size)                 \
>> +     __range_ok((unsigned long)addr, (unsigned long)size)
>
>> +#define __get_user_x(__r2,__p,__e,__s,__i...)                                \
>> +        __asm__ __volatile__ (                                       \
>> +             __asmeq("%0", "$r0") __asmeq("%1", "$r2")               \
>> +             "bal    __get_user_" #__s                               \
>
>... which does not check access_ok() or do any visible equivalents; OK...
>
>> +#define get_user(x,p)                                                        \
>> +     ({                                                              \
>> +             const register typeof(*(p)) __user *__p asm("$r0") = (p);\
>> +             register unsigned long __r2 asm("$r2");                 \
>> +             register int __e asm("$r0");                            \
>> +             switch (sizeof(*(__p))) {                               \
>> +             case 1:                                                 \
>> +                     __get_user_x(__r2, __p, __e, 1, "$lp");         \
>
>... and neither does this, which is almost certainly *not* OK.
>
>> +#define put_user(x,p)                                                        \
>
>Same here, AFAICS.

Thanks.
I will add access_ok() in get_user/put_user

>> +extern unsigned long __arch_copy_from_user(void *to, const void __user * from,
>> +                                        unsigned long n);
>
>> +static inline unsigned long raw_copy_from_user(void *to,
>> +                                            const void __user * from,
>> +                                            unsigned long n)
>> +{
>> +     return __arch_copy_from_user(to, from, n); }
>
>Er...  Why not call your __arch_... raw_... and be done with that?

Thanks.
I will modify it in next patch version

>> +#define INLINE_COPY_FROM_USER
>> +#define INLINE_COPY_TO_USER
>
>Are those actually worth bothering?  IOW, have you compared behaviour with and without them?

We compared the assembly code of copy_from/to_user's caller function,
and we think the performance is better by making copy_from/to_user as
inline


>> +ENTRY(__arch_copy_to_user)
>> +     push    $r0
>> +     push    $r2
>> +     beqz    $r2, ctu_exit
>> +     srli    $p0, $r2, #2            ! $p0 = number of word to clear
>> +     andi    $r2, $r2, #3            ! Bytes less than a word to copy
>> +     beqz    $p0, byte_ctu           ! Only less than a word to copy
>> +word_ctu:
>> +     lmw.bim $p1, [$r1], $p1         ! Load the next word
>> +USER(        smw.bim,$p1, [$r0], $p1)        ! Store the next word
>
>Umm...  It's that happy with unaligned loads and stores?  Your memcpy seems to be trying to avoid those...

Thanks.
This should be aligned loads and stores, too.
I will modify it in next version patch.

>> +9001:
>> +     pop     $p1                     ! Original $r2, n
>> +     pop     $p0                     ! Original $r0, void *to
>> +     sub     $r1, $r0, $p0           ! Bytes copied
>> +     sub     $r2, $p1, $r1           ! Bytes left to copy
>> +     push    $lp
>> +     move    $r0, $p0
>> +     bal     memzero                 ! Clean up the memory
>
>Just what memory are you zeroing here?  The one you had been unable to store into in the first place?
>
>> +ENTRY(__arch_copy_from_user)
>
>> +9001:
>> +     pop     $p1                     ! Original $r2, n
>> +     pop     $p0                     ! Original $r0, void *to
>> +     sub     $r1, $r1, $p0           ! Bytes copied
>> +     sub     $r2, $p1, $r1           ! Bytes left to copy
>> +     push    $lp
>> +     bal     memzero                 ! Clean up the memory
>
>Ditto, only this one is even worse - instead of just oopsing on you, it will quietly destroy data past the area you've copied into.  raw_copy_..._user() MUST NOT ZERO ANYTHING.  Ever.


Thanks
So, I should keep the area that we've copied into instead of zeroing
the area even if unpredicted exception is happened. Right?


Best regards
Vincent

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

* Re: [PATCH 29/31] MAINTAINERS: Add nds32
  2017-11-09 10:36       ` Arnd Bergmann
@ 2017-11-14 15:39         ` Joe Perches
  2017-11-16 12:22           ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Joe Perches @ 2017-11-14 15:39 UTC (permalink / raw)
  To: Arnd Bergmann, Greentime Hu
  Cc: Rob Herring, Greentime, linux-kernel, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, netdev

On Thu, 2017-11-09 at 11:36 +0100, Arnd Bergmann wrote:
> On Thu, Nov 9, 2017 at 10:46 AM, Greentime Hu <green.hu@gmail.com> wrote:
> > 2017-11-08 21:31 GMT+08:00 Rob Herring <robh+dt@kernel.org>:
> > > On Tue, Nov 7, 2017 at 11:55 PM, Greentime Hu <green.hu@gmail.com> wrote:
> > > > From: Greentime Hu <greentime@andestech.com>
> > > > 
> > > > Signed-off-by: Greentime Hu <greentime@andestech.com>
> > > > ---
> > > >  MAINTAINERS |    9 +++++++++
> > > >  1 file changed, 9 insertions(+)
> > > > 
> > > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > > index 2f4e462..bce1181 100644
> > > > --- a/MAINTAINERS
> > > > +++ b/MAINTAINERS
> > > > @@ -857,6 +857,15 @@ X: drivers/iio/*/adjd*
> > > >  F:     drivers/staging/iio/*/ad*
> > > >  F:     drivers/staging/iio/trigger/iio-trig-bfin-timer.c
> > > > 
> > > > +ANDES ARCHITECTURE
> > > > +M:     Greentime Hu <green.hu@gmail.com>
> > > > +M:     Vincent Chen <deanbo422@gmail.com>
> > > > +T:     git https://github.com/andestech/linux.git
> > > > +S:     Supported
> > > > +F:     arch/nds32
> > > 
> > > DT binding files?
> > 
> > Thanks.
> > I should add
> > F:    Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt
> > F:    Documentation/devicetree/bindings/nds32/cpus.txt
> > 
> > I will fix it in the next version patch.
> 
> Better make the second one the directory, in case you add more files
> there later.
> 
> I would also add a "K: nds32" line to catch all files that have this
> in their names.

That's probably not what would be desired

K: looks for keywords inside all file contents
N: looks for filenames matching a regex pattern

See the header in MAINTAINERS for more details

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

* Re: [PATCH 26/31] nds32: Build infrastructure
  2017-11-13 10:45       ` Geert Uytterhoeven
  (?)
@ 2017-11-16 10:03       ` Greentime Hu
  2017-11-16 10:25         ` Arnd Bergmann
  -1 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-16 10:03 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Arnd Bergmann, Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

2017-11-13 18:45 GMT+08:00 Geert Uytterhoeven <geert@linux-m68k.org>:
> On Wed, Nov 8, 2017 at 11:16 AM, Arnd Bergmann <arnd@arndb.de> wrote:
>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>> --- /dev/null
>>> +++ b/arch/nds32/Kconfig
>>> @@ -0,0 +1,107 @@
>>> +#
>>> +# For a description of the syntax of this configuration file,
>>> +# see Documentation/kbuild/kconfig-language.txt.
>>> +#
>>> +
>>> +config NDS32
>>> +        def_bool y
>>> +       select ARCH_HAS_RAW_COPY_USER
>>> +       select ARCH_WANT_FRAME_POINTERS if FTRACE
>>> +       select ARCH_WANT_IPC_PARSE_VERSION
>>> +       select CLKSRC_MMIO
>>> +       select CLONE_BACKWARDS
>>> +       select TIMER_OF
>>> +       select FRAME_POINTER
>>> +       select GENERIC_ATOMIC64
>>> +       select GENERIC_CPU_DEVICES
>>> +       select GENERIC_CLOCKEVENTS
>>> +       select GENERIC_IOMAP
>>> +       select GENERIC_IRQ_CHIP
>>> +       select GENERIC_IRQ_PROBE
>>> +       select GENERIC_IRQ_SHOW
>>> +       select GENERIC_STRNCPY_FROM_USER
>>> +       select GENERIC_STRNLEN_USER
>>> +       select GENERIC_TIME_VSYSCALL
>>> +       select HAVE_ARCH_TRACEHOOK
>>> +       select HAVE_GENERIC_IOMAP
>>
>> You normally don't want HAVE_GENERIC_IOMAP, at least unless the CPU
>> has special instructions to trigger PCI I/O port access.
>
> GENERIC_IOMAP or HAVE_GENERIC_IOMAP?
>
> The latter doesn't even exist, except in
> Documentation/kbuild/kconfig-language.txt, so it cannot be selected.

Thanks.
I will remove HAVE_GENERIC_IOMAP in the next version patch.

> Given the checks for __NDS32_EB__, NDS32 can be either big or little endian,
> so you should have (excatly one of) CPU_BIG_ENDIAN or CPU_LITTLE_ENDIAN set.

Thanks.
I will check if we need this config or not and update in the next version patch.

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

* Re: [PATCH 26/31] nds32: Build infrastructure
  2017-11-16 10:03       ` Greentime Hu
@ 2017-11-16 10:25         ` Arnd Bergmann
  2017-11-17 13:53           ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-16 10:25 UTC (permalink / raw)
  To: Greentime Hu
  Cc: Geert Uytterhoeven, Greentime, Linux Kernel Mailing List,
	linux-arch, Thomas Gleixner, Jason Cooper, Marc Zyngier,
	Rob Herring, Networking, Vincent Chen

On Thu, Nov 16, 2017 at 11:03 AM, Greentime Hu <green.hu@gmail.com> wrote:
> 2017-11-13 18:45 GMT+08:00 Geert Uytterhoeven <geert@linux-m68k.org>:
>> Given the checks for __NDS32_EB__, NDS32 can be either big or little endian,
>> so you should have (excatly one of) CPU_BIG_ENDIAN or CPU_LITTLE_ENDIAN set.
>
> Thanks.
> I will check if we need this config or not and update in the next version patch.

I think we have one architecture in the kernel that determines endianess from
the way that the toolchain is built. What all the others do it to have a Kconfig
option, at least CONFIG_CPU_BIG_ENDIAN that is used to pass -mbig-endian
or -mlittle-endian to the compiler. You should do it that way so you can use
any toolchain with any kernel configuration.

       Arnd

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

* Re: [PATCH 29/31] MAINTAINERS: Add nds32
  2017-11-14 15:39         ` Joe Perches
@ 2017-11-16 12:22           ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-16 12:22 UTC (permalink / raw)
  To: Joe Perches
  Cc: Arnd Bergmann, Rob Herring, Greentime, linux-kernel, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, netdev

2017-11-14 23:39 GMT+08:00 Joe Perches <joe@perches.com>:
> On Thu, 2017-11-09 at 11:36 +0100, Arnd Bergmann wrote:
>> On Thu, Nov 9, 2017 at 10:46 AM, Greentime Hu <green.hu@gmail.com> wrote:
>> > 2017-11-08 21:31 GMT+08:00 Rob Herring <robh+dt@kernel.org>:
>> > > On Tue, Nov 7, 2017 at 11:55 PM, Greentime Hu <green.hu@gmail.com> wrote:
>> > > > From: Greentime Hu <greentime@andestech.com>
>> > > >
>> > > > Signed-off-by: Greentime Hu <greentime@andestech.com>
>> > > > ---
>> > > >  MAINTAINERS |    9 +++++++++
>> > > >  1 file changed, 9 insertions(+)
>> > > >
>> > > > diff --git a/MAINTAINERS b/MAINTAINERS
>> > > > index 2f4e462..bce1181 100644
>> > > > --- a/MAINTAINERS
>> > > > +++ b/MAINTAINERS
>> > > > @@ -857,6 +857,15 @@ X: drivers/iio/*/adjd*
>> > > >  F:     drivers/staging/iio/*/ad*
>> > > >  F:     drivers/staging/iio/trigger/iio-trig-bfin-timer.c
>> > > >
>> > > > +ANDES ARCHITECTURE
>> > > > +M:     Greentime Hu <green.hu@gmail.com>
>> > > > +M:     Vincent Chen <deanbo422@gmail.com>
>> > > > +T:     git https://github.com/andestech/linux.git
>> > > > +S:     Supported
>> > > > +F:     arch/nds32
>> > >
>> > > DT binding files?
>> >
>> > Thanks.
>> > I should add
>> > F:    Documentation/devicetree/bindings/interrupt-controller/andestech,ativic32.txt
>> > F:    Documentation/devicetree/bindings/nds32/cpus.txt
>> >
>> > I will fix it in the next version patch.
>>
>> Better make the second one the directory, in case you add more files
>> there later.
>>
Thanks. I will add the second one directory.

>> I would also add a "K: nds32" line to catch all files that have this
>> in their names.
>
> That's probably not what would be desired
>
> K: looks for keywords inside all file contents
> N: looks for filenames matching a regex pattern
>
> See the header in MAINTAINERS for more details
>

Thanks.
I will add K and N both.

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

* Re: [PATCH 26/31] nds32: Build infrastructure
  2017-11-10  8:26         ` Greentime Hu
@ 2017-11-17 12:39           ` Greentime Hu
  2017-11-17 12:50             ` Arnd Bergmann
  0 siblings, 1 reply; 116+ messages in thread
From: Greentime Hu @ 2017-11-17 12:39 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

2017-11-10 16:26 GMT+08:00 Greentime Hu <green.hu@gmail.com>:
> 2017-11-09 18:33 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
>> On Thu, Nov 9, 2017 at 10:02 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>> 2017-11-08 18:16 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
>>>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>
>>>>> +config GENERIC_CALIBRATE_DELAY
>>>>> +       def_bool y
>>>>
>>>> It's better to avoid the delay loop completely and skip the calibration,
>>>> if your hardware allows.
>>>
>>> Thanks.
>>> Do you mean that this config should be def_bool n?
>>> why? Almost all arch enable it.
>>
>> It depends on what your hardware can do. If you have a way to see how much
>> time has passed that is guaranteed to be reliable on all machines, then
>> use that instead.
>>
>> On a lot of architectures, it's not possible, so they have to fall back to using
>> the delay loop.
>
> I get it. I will discuss it with our HW colleagues.
> We may get these informations in some registers.

Hi, Arnd:

I think I can't set it to default n because it will be called in start_kernel.

start_kernel() -> calibrate_delay()

If I don't enable this config, it will link error because it didn't
build init/calibrate.c

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

* Re: [PATCH 26/31] nds32: Build infrastructure
  2017-11-17 12:39           ` Greentime Hu
@ 2017-11-17 12:50             ` Arnd Bergmann
  2017-11-17 13:50               ` Greentime Hu
  0 siblings, 1 reply; 116+ messages in thread
From: Arnd Bergmann @ 2017-11-17 12:50 UTC (permalink / raw)
  To: Greentime Hu
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

On Fri, Nov 17, 2017 at 1:39 PM, Greentime Hu <green.hu@gmail.com> wrote:
> 2017-11-10 16:26 GMT+08:00 Greentime Hu <green.hu@gmail.com>:
>> 2017-11-09 18:33 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
>>> On Thu, Nov 9, 2017 at 10:02 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>>> 2017-11-08 18:16 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
>>>>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>>
>>>>>> +config GENERIC_CALIBRATE_DELAY
>>>>>> +       def_bool y
>>>>>
>>>>> It's better to avoid the delay loop completely and skip the calibration,
>>>>> if your hardware allows.
>>>>
>>>> Thanks.
>>>> Do you mean that this config should be def_bool n?
>>>> why? Almost all arch enable it.
>>>
>>> It depends on what your hardware can do. If you have a way to see how much
>>> time has passed that is guaranteed to be reliable on all machines, then
>>> use that instead.
>>>
>>> On a lot of architectures, it's not possible, so they have to fall back to using
>>> the delay loop.
>>
>> I get it. I will discuss it with our HW colleagues.
>> We may get these informations in some registers.
>
> Hi, Arnd:
>
> I think I can't set it to default n because it will be called in start_kernel.
>
> start_kernel() -> calibrate_delay()
>
> If I don't enable this config, it will link error because it didn't
> build init/calibrate.c

You will have to provide an architecture-specific implementation of
this function, please ahve a look at what others are doing, e.g. tile,
openrisc or
h8300.

          Arnd

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

* Re: [PATCH 26/31] nds32: Build infrastructure
  2017-11-17 12:50             ` Arnd Bergmann
@ 2017-11-17 13:50               ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-17 13:50 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

2017-11-17 20:50 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Fri, Nov 17, 2017 at 1:39 PM, Greentime Hu <green.hu@gmail.com> wrote:
>> 2017-11-10 16:26 GMT+08:00 Greentime Hu <green.hu@gmail.com>:
>>> 2017-11-09 18:33 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
>>>> On Thu, Nov 9, 2017 at 10:02 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>>>> 2017-11-08 18:16 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
>>>>>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>>>
>>>>>>> +config GENERIC_CALIBRATE_DELAY
>>>>>>> +       def_bool y
>>>>>>
>>>>>> It's better to avoid the delay loop completely and skip the calibration,
>>>>>> if your hardware allows.
>>>>>
>>>>> Thanks.
>>>>> Do you mean that this config should be def_bool n?
>>>>> why? Almost all arch enable it.
>>>>
>>>> It depends on what your hardware can do. If you have a way to see how much
>>>> time has passed that is guaranteed to be reliable on all machines, then
>>>> use that instead.
>>>>
>>>> On a lot of architectures, it's not possible, so they have to fall back to using
>>>> the delay loop.
>>>
>>> I get it. I will discuss it with our HW colleagues.
>>> We may get these informations in some registers.
>>
>> Hi, Arnd:
>>
>> I think I can't set it to default n because it will be called in start_kernel.
>>
>> start_kernel() -> calibrate_delay()
>>
>> If I don't enable this config, it will link error because it didn't
>> build init/calibrate.c
>
> You will have to provide an architecture-specific implementation of
> this function, please ahve a look at what others are doing, e.g. tile,
> openrisc or
> h8300.

Thanks. I got you.

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

* Re: [PATCH 26/31] nds32: Build infrastructure
  2017-11-16 10:25         ` Arnd Bergmann
@ 2017-11-17 13:53           ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-17 13:53 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Geert Uytterhoeven, Greentime, Linux Kernel Mailing List,
	linux-arch, Thomas Gleixner, Jason Cooper, Marc Zyngier,
	Rob Herring, Networking, Vincent Chen

2017-11-16 18:25 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Thu, Nov 16, 2017 at 11:03 AM, Greentime Hu <green.hu@gmail.com> wrote:
>> 2017-11-13 18:45 GMT+08:00 Geert Uytterhoeven <geert@linux-m68k.org>:
>>> Given the checks for __NDS32_EB__, NDS32 can be either big or little endian,
>>> so you should have (excatly one of) CPU_BIG_ENDIAN or CPU_LITTLE_ENDIAN set.
>>
>> Thanks.
>> I will check if we need this config or not and update in the next version patch.
>
> I think we have one architecture in the kernel that determines endianess from
> the way that the toolchain is built. What all the others do it to have a Kconfig
> option, at least CONFIG_CPU_BIG_ENDIAN that is used to pass -mbig-endian
> or -mlittle-endian to the compiler. You should do it that way so you can use
> any toolchain with any kernel configuration.

Thanks
I will add these 2 configs in the next version patch.
Pass -EL or -EB to compiler based on different configs.

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

* Re: Fwd: FW: [PATCH 18/31] nds32: Library functions
  2017-11-14  4:47       ` Fwd: FW: " Vincent Chen
@ 2017-11-18  2:44         ` Al Viro
  0 siblings, 0 replies; 116+ messages in thread
From: Al Viro @ 2017-11-18  2:44 UTC (permalink / raw)
  To: Vincent Chen
  Cc: viro, greentime, Green Hu, linux-kernel, Arnd Bergmann,
	linux-arch, tglx, jason, marc.zyngier, robh+dt, netdev, vincentc

On Tue, Nov 14, 2017 at 12:47:04PM +0800, Vincent Chen wrote:

> Thanks
> So, I should keep the area that we've copied into instead of zeroing
> the area even if unpredicted exception is happened. Right?

Yes.  Here's what's required: if raw_copy_{from,to}_user(from, to, size)
returns n, we want
	* 0 <= n <= size
	* no bytes outside of to[0 .. size - n - 1] modified
	* all bytes in that range replaced with corresponding bytes of range
from[0 .. size - n - 1]
	* non-zero return values should happen only when some loads (in case
of raw_copy_from_user()) or stores (in case of raw_copy_to_user()) had failed.
If everything could have been read and written, we must copy everything.
	* return value should be equal to size only if no load or no store
had been possible.  In all other cases you need to copy at least something.
You don't have to squeeze all bytes that can be copied (you can, of course,
but it's not required).
	* you should not assume that failing load guarantees that subsequent
loads further into the same page will keep failing; normally they will, but
relying upon that is asking for trouble.  Several architectures had bugs
of that sort, with varying amounts of nastiness happening when e.g. write(2)
raced with mprotect(2) from another thread...

For almost any architecture these should be more or less parallel to memcpy();
the only exception I know of is the situation when cross-address-space copy
has timing very different from that for normal load+store.  s390 is that
way - there's considerable overhead of setting such copying, and you really
want it done in bigger chunks than would be optimal for memcpy().  uml is
similar.  However, generally it's memcpy tweaked to deal with exceptions.

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

* Re: [PATCH 11/31] nds32: Atomic operations
  2017-11-08  5:54 ` [PATCH 11/31] nds32: Atomic operations Greentime Hu
  2017-11-08  8:54   ` Arnd Bergmann
@ 2017-11-20 14:29   ` Will Deacon
  2017-11-22  3:02     ` Vincent Chen
  1 sibling, 1 reply; 116+ messages in thread
From: Will Deacon @ 2017-11-20 14:29 UTC (permalink / raw)
  To: Greentime Hu
  Cc: greentime, linux-kernel, arnd, linux-arch, tglx, jason,
	marc.zyngier, robh+dt, netdev, Vincent Chen, peterz, paulmck

Hi Greentime,

On Wed, Nov 08, 2017 at 01:54:59PM +0800, Greentime Hu wrote:
> From: Greentime Hu <greentime@andestech.com>
> 
> Signed-off-by: Vincent Chen <vincentc@andestech.com>
> Signed-off-by: Greentime Hu <greentime@andestech.com>
> ---
>  arch/nds32/include/asm/futex.h    |  116 ++++++++++++++++++++++++
>  arch/nds32/include/asm/spinlock.h |  178 +++++++++++++++++++++++++++++++++++++
>  2 files changed, 294 insertions(+)
>  create mode 100644 arch/nds32/include/asm/futex.h
>  create mode 100644 arch/nds32/include/asm/spinlock.h

[...]

> +static inline int
> +futex_atomic_cmpxchg_inatomic(u32 * uval, u32 __user * uaddr,
> +			      u32 oldval, u32 newval)
> +{
> +	int ret = 0;
> +	u32 val, tmp, flags;
> +
> +	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
> +		return -EFAULT;
> +
> +	smp_mb();
> +	asm volatile ("       movi    $ta, #0\n"
> +		      "1:     llw     %1, [%6 + $ta]\n"
> +		      "       sub     %3, %1, %4\n"
> +		      "       cmovz   %2, %5, %3\n"
> +		      "       cmovn   %2, %1, %3\n"
> +		      "2:     scw     %2, [%6 + $ta]\n"
> +		      "       beqz    %2, 1b\n"
> +		      "3:\n                   " __futex_atomic_ex_table("%7")
> +		      :"+&r"(ret), "=&r"(val), "=&r"(tmp), "=&r"(flags)
> +		      :"r"(oldval), "r"(newval), "r"(uaddr), "i"(-EFAULT)
> +		      :"$ta", "memory");
> +	smp_mb();
> +
> +	*uval = val;
> +	return ret;
> +}

I see you rely on asm-generic/barrier.h for your barrier definitions, which
suggests that you only need to prevent reordering by the compiler because
you're not SMP. Is that right? If so, using smp_mb() is a little weird.

What about DMA transactions? I imagine you might need some extra
instructions for the mandatory barriers there.

Also:

> +static inline void arch_spin_lock(arch_spinlock_t * lock)
> +{
> +	unsigned long tmp;
> +
> +	__asm__ __volatile__("1:\n"
> +			     "\tllw\t%0, [%1]\n"
> +			     "\tbnez\t%0, 1b\n"
> +			     "\tmovi\t%0, #0x1\n"
> +			     "\tscw\t%0, [%1]\n"
> +			     "\tbeqz\t%0, 1b\n"
> +			     :"=&r"(tmp)
> +			     :"r"(&lock->lock)
> +			     :"memory");
> +}

Here it looks like you're eliding an explicit barrier here because you
already have a "memory" clobber. Can't you do the same for the futex code
above?

Will

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

* Re: [PATCH 11/31] nds32: Atomic operations
  2017-11-20 14:29   ` Will Deacon
@ 2017-11-22  3:02     ` Vincent Chen
  0 siblings, 0 replies; 116+ messages in thread
From: Vincent Chen @ 2017-11-22  3:02 UTC (permalink / raw)
  To: Will Deacon
  Cc: Greentime Hu, greentime, linux-kernel, Arnd Bergmann, linux-arch,
	tglx, jason, marc.zyngier, robh+dt, netdev, Vincent Chen, peterz,
	paulmck

2017-11-20 22:29 GMT+08:00 Will Deacon <will.deacon@arm.com>:
> Hi Greentime,
>
> On Wed, Nov 08, 2017 at 01:54:59PM +0800, Greentime Hu wrote:
>> From: Greentime Hu <greentime@andestech.com>
>>
>> Signed-off-by: Vincent Chen <vincentc@andestech.com>
>> Signed-off-by: Greentime Hu <greentime@andestech.com>
>> ---
>>  arch/nds32/include/asm/futex.h    |  116 ++++++++++++++++++++++++
>>  arch/nds32/include/asm/spinlock.h |  178 +++++++++++++++++++++++++++++++++++++
>>  2 files changed, 294 insertions(+)
>>  create mode 100644 arch/nds32/include/asm/futex.h
>>  create mode 100644 arch/nds32/include/asm/spinlock.h
>
> [...]
>
>> +static inline int
>> +futex_atomic_cmpxchg_inatomic(u32 * uval, u32 __user * uaddr,
>> +                           u32 oldval, u32 newval)
>> +{
>> +     int ret = 0;
>> +     u32 val, tmp, flags;
>> +
>> +     if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
>> +             return -EFAULT;
>> +
>> +     smp_mb();
>> +     asm volatile ("       movi    $ta, #0\n"
>> +                   "1:     llw     %1, [%6 + $ta]\n"
>> +                   "       sub     %3, %1, %4\n"
>> +                   "       cmovz   %2, %5, %3\n"
>> +                   "       cmovn   %2, %1, %3\n"
>> +                   "2:     scw     %2, [%6 + $ta]\n"
>> +                   "       beqz    %2, 1b\n"
>> +                   "3:\n                   " __futex_atomic_ex_table("%7")
>> +                   :"+&r"(ret), "=&r"(val), "=&r"(tmp), "=&r"(flags)
>> +                   :"r"(oldval), "r"(newval), "r"(uaddr), "i"(-EFAULT)
>> +                   :"$ta", "memory");
>> +     smp_mb();
>> +
>> +     *uval = val;
>> +     return ret;
>> +}
>
> I see you rely on asm-generic/barrier.h for your barrier definitions, which
> suggests that you only need to prevent reordering by the compiler because
> you're not SMP. Is that right? If so, using smp_mb() is a little weird.
>

Thanks.
So, Is it better to replace smp_mb() with mb() for us?


> What about DMA transactions? I imagine you might need some extra
> instructions for the mandatory barriers there.
>

I don't get it. Do you mean before DMA transations?

Data are moved from memory to device, we will writeback data cache
before DMA transactions.

Data are moved from device to memory, we will invalidate data cache
after DMA transactions.



> Also:
>
>> +static inline void arch_spin_lock(arch_spinlock_t * lock)
>> +{
>> +     unsigned long tmp;
>> +
>> +     __asm__ __volatile__("1:\n"
>> +                          "\tllw\t%0, [%1]\n"
>> +                          "\tbnez\t%0, 1b\n"
>> +                          "\tmovi\t%0, #0x1\n"
>> +                          "\tscw\t%0, [%1]\n"
>> +                          "\tbeqz\t%0, 1b\n"
>> +                          :"=&r"(tmp)
>> +                          :"r"(&lock->lock)
>> +                          :"memory");
>> +}
>
> Here it looks like you're eliding an explicit barrier here because you
> already have a "memory" clobber. Can't you do the same for the futex code
> above?
>
Thanks.
OK. I will modify it in the next version patch.

> Will


Best regards
Vincent

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

* Re: FW: [PATCH 15/31] nds32: System calls handling
  2017-11-13 11:42         ` Arnd Bergmann
@ 2017-11-22  3:13           ` Vincent Chen
  0 siblings, 0 replies; 116+ messages in thread
From: Vincent Chen @ 2017-11-22  3:13 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen

2017-11-13 19:42 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Mon, Nov 13, 2017 at 3:51 AM, Vincent Chen <deanbo422@gmail.com> wrote:
>>>>On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>>> From: Greentime Hu <greentime@andestech.com>
>
>>
>>>> +#define __ARCH_WANT_SYS_CLONE
>>>
>>>This seems ok, though it would be nice to have the reverse logic and have architectures opt-out of the generic version when they need to provide their own, rather than having most architectures set it.
>>>
>>
>> Thanks
>> I will provide nds32 SYSCALL_DEFINE_5(clone) in the next version patch.
>
> That's not what I meant, my suggestion is to create a new patch to remove the
> __ARCH_WANT_SYS_CLONE symbol from all architectures, and instead use
> something like __ARCH_HAVE_SYS_CLONE on architectures that do *not*
> want the generic implementation.
>
> nds32 clearly wants the generic implementation here, it just shouldn't have to
> select that symbol to get it.
>
>>>> +/*
>>>> + * Special system call wrappers
>>>> + *
>>>> + * $r0 = syscall number
>>>> + * $r8 = syscall table
>>>> + */
>>>> +       .type   sys_syscall, #function
>>>> +ENTRY(sys_syscall)
>>>> +       addi    $p1, $r0, #-__NR_syscalls
>>>> +       bgtz    $p1, 3f
>>>> +       move    $p1, $r0
>>>> +       move    $r0, $r1
>>>> +       move    $r1, $r2
>>>> +       move    $r2, $r3
>>>> +       move    $r3, $r4
>>>> +       move    $r4, $r5
>>>> +! add for syscall 6 args
>>>> +       lwi     $r5, [$sp + #SP_OFFSET ]
>>>> +       lwi     $r5, [$r5]
>>>> +! ~add for syscall 6 args
>>>> +
>>>> +       lw      $p1, [tbl+$p1<<2]
>>>> .+       jr      $p1
>>>> +3:     b       sys_ni_syscall
>>>> +ENDPROC(sys_syscall)
>>>
>>>Can you explain what this is used for?
>>>
>>
>> This is used to handle syscall(int number, ....).
>> Unlike other architectures,  the system number shall be determined in
>> compile time when issuing system call in nds32.
>> Therefore, we  only can parse the content of syscall(int number, ....)
>> and distribute it to destination handler in kernel space
>> (Other architecture can handle it in user space by glibc's syscall wrapper)
>
> Hmm, I think other architectures that run into this problem use self-modifying
> code for syscall(), but that is also ugly as it requires having a page that
> is both writable and executable.
>
> I think your approach can be tricky for things like seccomp(). It's possible
> that you get all of it right, but if you can come up with a different solution,
> that might be better.
>
> How much would it cost to simply always pass the syscall number
> in a register, and not use the immediate argument at all?
>

After re-evaluating the performance, we decide to use a particular
register to transfer syscall number
instead of immediate argument. So, above sys_syscall will be removed
in the next version patch

Thanks


>>>> --- /dev/null
>>>> +++ b/arch/nds32/kernel/sys_nds32.c
>>>> +
>>>> +long sys_mmap2(unsigned long addr, unsigned long len,
>>>> +              unsigned long prot, unsigned long flags,
>>>> +              unsigned long fd, unsigned long pgoff) {
>>>> +       if (pgoff & (~PAGE_MASK >> 12))
>>>> +               return -EINVAL;
>>>> +
>>>> +       return sys_mmap_pgoff(addr, len, prot, flags, fd,
>>>> +                             pgoff >> (PAGE_SHIFT - 12)); }
>>>> +
>>>> +asmlinkage long sys_fadvise64_64_wrapper(int fd, int advice, loff_t offset,
>>>> +                                        loff_t len) {
>>>> +       return sys_fadvise64_64(fd, offset, len, advice); }
>>>
>>>You should always use SYSCALL_DEFINE*() macros to define entry points for your own syscalls in C code for consistency. I also wonder if we should just move those two into common code, a lot of architectures need the first one in particular.
>>>
>>
>> The sys_fadvise64_64_wrapper is used to reorder the input parameter.
>>
>> In order to solve register alignment problem, we adjust the input
>> parameter order of fadvise64_64 while issuing this syscall.
>> Therefore, we need this wrapper to reorder the input parameter to fit
>> sys_fadvise64_64's API in kernel.
>
> I understand what it's used for, it's just that I would recommend writing it
> differently, as
>
> SYSCALL_DEFINE4(fadvise64_64_wrapper, int, fd, int, advice, loff_t,
> offset, loff_t, len)
> {
>        return sys_fadvise64_64(fd, offset, len, advice);
> }
>
>       Arnd

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

* Re: [PATCH 12/31] nds32: Device specific operations
  2017-11-10 16:14         ` Arnd Bergmann
@ 2017-11-22 10:02           ` Greentime Hu
  0 siblings, 0 replies; 116+ messages in thread
From: Greentime Hu @ 2017-11-22 10:02 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Greentime, Linux Kernel Mailing List, linux-arch,
	Thomas Gleixner, Jason Cooper, Marc Zyngier, Rob Herring,
	Networking, Vincent Chen, deanbo422

2017-11-11 0:14 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> Could you move ioremap_nocache/ioremap_uc/ioremap_wc/ioremap_wt
> out of that #ifdef, or would that break other architectures?
>

It seems ok. I just tried arm64, x86 and nds32.

#endif /* CONFIG_MMU */
#ifndef ioremap_nocache
void __iomem *ioremap(phys_addr_t phys_addr, size_t size);
#define ioremap_nocache ioremap_nocache
static inline void __iomem *ioremap_nocache(phys_addr_t offset, size_t size)
{
        return ioremap(offset, size);
}
#endif

#ifndef ioremap_uc
#define ioremap_uc ioremap_uc
static inline void __iomem *ioremap_uc(phys_addr_t offset, size_t size)
{
        return ioremap_nocache(offset, size);
}
#endif

#ifndef ioremap_wc
#define ioremap_wc ioremap_wc
static inline void __iomem *ioremap_wc(phys_addr_t offset, size_t size)
{
        return ioremap_nocache(offset, size);
}
#endif

#ifndef ioremap_wt
#define ioremap_wt ioremap_wt
static inline void __iomem *ioremap_wt(phys_addr_t offset, size_t size)
{
        return ioremap_nocache(offset, size);
}
#endif

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

end of thread, other threads:[~2017-11-22 10:03 UTC | newest]

Thread overview: 116+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-08  5:54 [PATCH 00/31] Andes(nds32) Linux Kernel Port Greentime Hu
2017-11-08  5:54 ` [PATCH 01/31] nds32: Assembly macros and definitions Greentime Hu
2017-11-08  5:54 ` [PATCH 02/31] nds32: Kernel booting and initialization Greentime Hu
2017-11-08 13:38   ` Rob Herring
2017-11-09  9:49     ` Greentime Hu
2017-11-08  5:54 ` [PATCH 03/31] nds32: Support early_printk Greentime Hu
2017-11-08  9:47   ` Tobias Klauser
2017-11-09  7:19     ` Greentime Hu
2017-11-08  5:54 ` [PATCH 04/31] nds32: Exception handling Greentime Hu
2017-11-08  8:23   ` Arnd Bergmann
     [not found]     ` <E26F4CF8B7DDDB4383A6C2D78D5C3CD56B4974CE@ATCPCS16.andestech.com>
2017-11-13 10:54       ` Fwd: FW: " Vincent Chen
2017-11-08  5:54 ` [PATCH 05/31] nds32: MMU definitions Greentime Hu
2017-11-08  8:36   ` Arnd Bergmann
2017-11-08  8:46     ` Greentime Hu
2017-11-08  5:54 ` [PATCH 06/31] nds32: MMU initialization Greentime Hu
2017-11-08  5:54 ` [PATCH 07/31] nds32: MMU fault handling and page table management Greentime Hu
2017-11-08  5:54 ` [PATCH 08/31] nds32: Cache and TLB routines Greentime Hu
2017-11-08  8:45   ` Arnd Bergmann
2017-11-08  9:01     ` Greentime Hu
2017-11-08  5:54 ` [PATCH 09/31] nds32: Process management Greentime Hu
2017-11-08  5:54 ` [PATCH 10/31] nds32: IRQ handling Greentime Hu
2017-11-08  8:49   ` Arnd Bergmann
2017-11-08  9:06     ` Greentime Hu
2017-11-08  5:54 ` [PATCH 11/31] nds32: Atomic operations Greentime Hu
2017-11-08  8:54   ` Arnd Bergmann
2017-11-08  9:32     ` vincentc
2017-11-08  9:32       ` vincentc
2017-11-20 14:29   ` Will Deacon
2017-11-22  3:02     ` Vincent Chen
2017-11-08  5:55 ` [PATCH 12/31] nds32: Device specific operations Greentime Hu
2017-11-08  9:04   ` Arnd Bergmann
2017-11-09  7:04     ` Greentime Hu
2017-11-10 16:07       ` Greentime Hu
2017-11-10 16:14         ` Arnd Bergmann
2017-11-22 10:02           ` Greentime Hu
2017-11-08  5:55 ` [PATCH 13/31] nds32: DMA mapping API Greentime Hu
2017-11-08  9:09   ` Arnd Bergmann
2017-11-09  7:12     ` Greentime Hu
2017-11-09 10:14       ` Arnd Bergmann
2017-11-10  8:13         ` Greentime Hu
2017-11-08  5:55 ` [PATCH 14/31] nds32: ELF definitions Greentime Hu
2017-11-08  5:55 ` [PATCH 15/31] nds32: System calls handling Greentime Hu
2017-11-08  9:30   ` Arnd Bergmann
     [not found]     ` <E26F4CF8B7DDDB4383A6C2D78D5C3CD56B497241@ATCPCS16.andestech.com>
2017-11-13  2:51       ` Fwd: FW: " Vincent Chen
2017-11-13 11:42         ` Arnd Bergmann
2017-11-22  3:13           ` Vincent Chen
2017-11-08  5:55 ` [PATCH 16/31] nds32: VDSO support Greentime Hu
2017-11-08  9:37   ` Arnd Bergmann
2017-11-08 20:00     ` Deepa Dinamani
2017-11-08 20:06       ` Arnd Bergmann
2017-11-08 20:14         ` Deepa Dinamani
2017-11-08  5:55 ` [PATCH 17/31] nds32: Signal handling support Greentime Hu
2017-11-09  1:26   ` Al Viro
     [not found]     ` <E26F4CF8B7DDDB4383A6C2D78D5C3CD56B497460@ATCPCS16.andestech.com>
2017-11-13  2:34       ` Fwd: FW: " Vincent Chen
2017-11-08  5:55 ` [PATCH 18/31] nds32: Library functions Greentime Hu
2017-11-08  9:45   ` Arnd Bergmann
2017-11-09  0:40   ` Al Viro
     [not found]     ` <E26F4CF8B7DDDB4383A6C2D78D5C3CD56B497559@ATCPCS16.andestech.com>
2017-11-14  4:47       ` Fwd: FW: " Vincent Chen
2017-11-18  2:44         ` Al Viro
2017-11-08  5:55 ` [PATCH 19/31] nds32: Debugging support Greentime Hu
2017-11-08  5:55 ` [PATCH 20/31] nds32: L2 cache support Greentime Hu
2017-11-08  9:48   ` Arnd Bergmann
2017-11-09  7:24     ` Greentime Hu
2017-11-08  5:55 ` [PATCH 21/31] nds32: Loadable modules Greentime Hu
2017-11-08  5:55 ` [PATCH 22/31] nds32: Generic timers support Greentime Hu
2017-11-08  5:55 ` [PATCH 23/31] nds32: Device tree support Greentime Hu
2017-11-08  9:53   ` Arnd Bergmann
2017-11-09  7:48     ` Greentime Hu
2017-11-08  5:55 ` [PATCH 24/31] nds32: Miscellaneous header files Greentime Hu
2017-11-08  9:57   ` Arnd Bergmann
2017-11-08  5:55 ` [PATCH 25/31] nds32: defconfig Greentime Hu
2017-11-08 10:03   ` Arnd Bergmann
2017-11-09  8:00     ` Greentime Hu
2017-11-09 10:20       ` Arnd Bergmann
2017-11-10  8:16         ` Greentime Hu
2017-11-08  5:55 ` [PATCH 26/31] nds32: Build infrastructure Greentime Hu
2017-11-08 10:16   ` Arnd Bergmann
2017-11-09  9:02     ` Greentime Hu
2017-11-09 10:33       ` Arnd Bergmann
2017-11-10  8:26         ` Greentime Hu
2017-11-17 12:39           ` Greentime Hu
2017-11-17 12:50             ` Arnd Bergmann
2017-11-17 13:50               ` Greentime Hu
2017-11-13 10:45     ` Geert Uytterhoeven
2017-11-13 10:45       ` Geert Uytterhoeven
2017-11-16 10:03       ` Greentime Hu
2017-11-16 10:25         ` Arnd Bergmann
2017-11-17 13:53           ` Greentime Hu
2017-11-08  5:55 ` [PATCH 27/31] dt-bindings: interrupt-controller: Andestech Internal Vector Interrupt Controller Greentime Hu
2017-11-08 13:25   ` Rob Herring
2017-11-09  9:43     ` Greentime Hu
2017-11-08  5:55 ` [PATCH 28/31] irqchip: Andestech Internal Vector Interrupt Controller driver Greentime Hu
2017-11-08 14:24   ` Marc Zyngier
2017-11-09 10:10     ` Greentime Hu
2017-11-08  5:55 ` [PATCH 29/31] MAINTAINERS: Add nds32 Greentime Hu
2017-11-08 13:31   ` Rob Herring
2017-11-09  9:46     ` Greentime Hu
2017-11-09 10:36       ` Arnd Bergmann
2017-11-14 15:39         ` Joe Perches
2017-11-16 12:22           ` Greentime Hu
2017-11-08  5:55 ` [PATCH 30/31] dt-bindings: nds32 CPU Bindings Greentime Hu
2017-11-08 13:18   ` Rob Herring
2017-11-09  9:39     ` Greentime Hu
2017-11-09 13:57       ` Rob Herring
2017-11-09 13:57         ` Rob Herring
2017-11-10  6:22         ` Greentime Hu
2017-11-10  8:25           ` Arnd Bergmann
2017-11-10  8:43             ` Greentime Hu
2017-11-10  8:43               ` Greentime Hu
2017-11-08  5:55 ` [PATCH 31/31] net: faraday add nds32 support Greentime Hu
2017-11-08  8:32 ` [PATCH 00/31] Andes(nds32) Linux Kernel Port David Howells
2017-11-08  8:41   ` Greentime Hu
2017-11-08 10:18     ` Arnd Bergmann
2017-11-09  9:26       ` Greentime Hu
2017-11-08 10:26 ` Arnd Bergmann
2017-11-09  9:33   ` Greentime Hu

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.