From patchwork Wed Nov 8 05:54:49 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835624 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="NGPWWEcR"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWx413922z9sNc for ; Wed, 8 Nov 2017 17:20:17 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754009AbdKHGUG (ORCPT ); Wed, 8 Nov 2017 01:20:06 -0500 Received: from mail-pl0-f65.google.com ([209.85.160.65]:55686 "EHLO mail-pl0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753961AbdKHGT6 (ORCPT ); Wed, 8 Nov 2017 01:19:58 -0500 Received: by mail-pl0-f65.google.com with SMTP id f6so665542pln.12; Tue, 07 Nov 2017 22:19:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=2h6YEGKGJ/j9SCJAhOhX6A38f6Q/FOtfOuH3FSG8GM4=; b=NGPWWEcRS1bwZV9iIf3YZXNcQqDebGV5A0y2jPR7+idK3GQJ06c3gy8ga5FTl9pxst DP+7ET16Opz5ni+DrNaYrg0NYGSz05aguBp4uMXvfZdfuvebp9dL8sRscjQmM7HGNaPM xFSEmoxtwq/MIQ/EpKGZC4R6OAonMYj2t8eWnWHuthUctHsi706YBImmb/TqhRHCZvLM KezvOV96KFlJgPnMJ3fCUEm0Ry2Pz55VlYDTkavQfrL0wKUW7rhULKo0GnMEtHgxDotd MlCJPymguv7hd8BKesvpewDjhLTrniDKcOIus4Lyhy7A/Yx4MiUh6io+VFjW9OzXzZOW BNng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=2h6YEGKGJ/j9SCJAhOhX6A38f6Q/FOtfOuH3FSG8GM4=; b=aMsFn9c6s1F6hhzkk2zPesL7yeEcZxGcu4uyEh/BK8ZJQFybPUxzxUZklMJAVXdMWn vjKiVYHMuhTbEvQs9HlSEsUj8q45GaA2dGLCyL1xz8lxozhyTEWsVePmWiVIPZc+z40F VLJFEwE/26O1pvY64lopcYttCNA6eW/VU8RJchV3EkrYbJex4LbWvJ7hDqmLBrpBwhwt 5dwfzAj/nB4Nw4sFVVSLRkRjG76RwBJwAYvSiIu3joA2QX/qBrWzoSF5xyglaP74qjdN IyhnwJLBa8UiZEbIgqbjlVWxUKGndMc4Isl5S3H2B5Nas0gBdN5UY5GXGMqD0hQWRGlv dVPw== X-Gm-Message-State: AJaThX766oWGzlxYqpXqvggQHbnZxqhbqNO/hXC9++gY+AIiZQffTyKf CIwf7L51ckmn9juPrSvngSM= X-Google-Smtp-Source: ABhQp+T/06iV1XJv8PT6GEM4KBfkslRInTWAdL155bDMAIvpZidl1hd3LF4Oi+YN6UqNLF9PVhzI5Q== X-Received: by 10.159.235.142 with SMTP id f14mr1230790plr.450.1510121997748; Tue, 07 Nov 2017 22:19:57 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.19.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:19:57 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 01/31] nds32: Assembly macros and definitions Date: Wed, 8 Nov 2017 13:54:49 +0800 Message-Id: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#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 . + */ + +#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<. + */ + +#ifndef _ASM_NDS32_NDS32_H_ +#define _ASM_NDS32_NDS32_H_ + +#include +#include + +#ifndef __ASSEMBLY__ +#include +#include + +#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 . + */ + +#include +#include +#include +#include +#include + +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; +} From patchwork Wed Nov 8 05:54:50 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835660 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="f0mgAIhK"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWxJq16MSz9s7C for ; Wed, 8 Nov 2017 17:31:23 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755462AbdKHGbV (ORCPT ); Wed, 8 Nov 2017 01:31:21 -0500 Received: from mail-pl0-f67.google.com ([209.85.160.67]:49877 "EHLO mail-pl0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751261AbdKHGUB (ORCPT ); Wed, 8 Nov 2017 01:20:01 -0500 Received: by mail-pl0-f67.google.com with SMTP id f2so665404plj.6; Tue, 07 Nov 2017 22:20:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=QWvxXxYFDEc0duqaSFDnK3CBca+iNUUoYbamim702BY=; b=f0mgAIhK/X+E3ugxFLPp0f18P7cx60LLfqzNGzmTuu31R34cwdVuEt6YCwFJou7le1 DsRsiZaWlNQfTpEgfdmD6Kqq1Bj2NAcJvLdKMyBdaiqG+F/qgn1eiOT70YGPD9dalYEb eNbTBDpUtDLOHUZN842UEr0froQGDgpWfjef+zfueplGMkRvIs72IFOEt1rZ6hpeVXQB wNntUJs6eI1HRrhHDHMkRpS15JFNMhAM2JJxK6yvtG7Xx19rPTYX255HwU3RCoOwCQlX oEXSDhtuDVlCU3bWaka5I1osIPLtP4QgxYOyMbiginBqxKUOPa4/uYfitZKQG1RzmfZz tWCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=QWvxXxYFDEc0duqaSFDnK3CBca+iNUUoYbamim702BY=; b=A6Vd4z5mJj9bV6OPccDjCymbahFjZud3mZnOOB0YiKuf/Gf8U1wC407umL5wg1tx/Q 1yblPpPHLhabsm1kiznnbvZ6iZuEQirWByG77fK15Ukvd1vFOUl3zCUxj2/vVMwJ+4E0 S6y6e9fm5Q9pr/YUUHJwTkucA56lgom3D57fx1msPtbzsUGh9+Tb8/SbyuNA73tY1OEa r3BW5dgyD2XT6Wo8+EcK+NoEFTilFSiSMmdJRdXzu0nAEyDqKuGmX1IXZkVqvsT3TGzB XvnASP/NaLa6E2XNfy1jRZKZKtjz1JohzflpkKeRqoPW230xPLBPCtiGK4IbDcutWfru 0q1Q== X-Gm-Message-State: AJaThX7o8q87zjGgLfPDU9eCkHvRX+knBs7jvgc8Z8YHDMfHaKDz4cpa 2QjH726MpX3z2MZXl3+3IIc= X-Google-Smtp-Source: ABhQp+TlvH2ygtTJA2sWRecgnOUt3Hz7GxPqn4h8QnzfQM8knl+Vfi4/2O9QQxVIrsjW41YfAOSjIQ== X-Received: by 10.84.128.75 with SMTP id 69mr1251377pla.151.1510122000271; Tue, 07 Nov 2017 22:20:00 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.19.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:19:59 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 02/31] nds32: Kernel booting and initialization Date: Wed, 8 Nov 2017 13:54:50 +0800 Message-Id: <5d06ac8d2a19c78a445b958a1b0a925559bd9f9c.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + */ +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 +}; From patchwork Wed Nov 8 05:54:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835661 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="W1d+bx5q"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWxKQ4jK4z9s7C for ; Wed, 8 Nov 2017 17:31:54 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932292AbdKHGbU (ORCPT ); Wed, 8 Nov 2017 01:31:20 -0500 Received: from mail-pl0-f65.google.com ([209.85.160.65]:46938 "EHLO mail-pl0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753779AbdKHGUD (ORCPT ); Wed, 8 Nov 2017 01:20:03 -0500 Received: by mail-pl0-f65.google.com with SMTP id y61so664252plh.3; Tue, 07 Nov 2017 22:20:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=iuwlqMbUf2T+jAKioxnQrxC3FgaivdEK9z4Z3Db56eo=; b=W1d+bx5qY94IT1B+7WNXLSlwuOyDwy0pLR/fUPxnBjuYag6x61sKf3W1BCK8gBgXXk Med2me+YGa4xwxLT0tUf1miCUS7MVaKmMHWl9kkwya1IqjLQoZv4XFqxKqiUa8xF7lvd nLcnWGkAr2fq6WzCKuRF1Jg0M/mxvZOU07Zb0kchZdMp505quZPzkLaFuFbdY//5h79+ aa8fkLShMi1eG6zaG+z1jGXf+eb9yi5DMrWOcNeMCkKWut/buhY48MgHhCALnYHQSgKi t9Rxa5ZALUBYllE3QJcC8rGx0YGmxA3vxoG1VQptWPegMiTr5aQRqfwYzefUBHy0z77S QxiQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=iuwlqMbUf2T+jAKioxnQrxC3FgaivdEK9z4Z3Db56eo=; b=RqzFAh/io44Cc+I9Alk3Wrea6eCWSvFUOornnVtrdEEtmnUGpQwJO216I586mdinNl RCoFIoQKCdijb60hyqbJT2A9n8mEzjn3tejlScIHXuzP51TWMZA66IdvWei5/XKv/gQ+ YXF4oOyBzjKa6sMiD175Wo6vP0qF4p3jgByWAQF1ESATufl37Hmig1Vr5wqAUfobIPQk CiuHygQd/Jxnkdt2cgioSwxSAfCi3yCR5x5nRMRFQIFi5i1HDProBVBsDHXj53ouNtkU 2qpZSXNZycr0bA2H73EP6yelBhGFm6Qu4VQevSIZjNwecg7tt4oNbCgq0sVrPUkgm3C5 lUKQ== X-Gm-Message-State: AJaThX7zQtBichwufrZfxSPTGNh27ezmBXWiENlkla6Z4A2yFqtifQEY sjKFMS9nkr/Rs/R1S+jmE2A= X-Google-Smtp-Source: ABhQp+RoTE6Hyrk71I1bBJLGh/xVllVYwp9MyGWVSCJ/wepeG6h63gBIMfEWnWN+e+RwUUxfbWlVTA== X-Received: by 10.159.211.4 with SMTP id bc4mr1278956plb.160.1510122002758; Tue, 07 Nov 2017 22:20:02 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:02 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Rick Chen Subject: [PATCH 03/31] nds32: Support early_printk Date: Wed, 8 Nov 2017 13:54:51 +0800 Message-Id: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Rick Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#include +#include +#include +#include + +#include + +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: + * + * [,][,] + * + * 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); From patchwork Wed Nov 8 05:54:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835626 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="JNP8QMrR"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWx4H5dLLz9s0Z for ; Wed, 8 Nov 2017 17:20:31 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754037AbdKHGUR (ORCPT ); Wed, 8 Nov 2017 01:20:17 -0500 Received: from mail-pl0-f68.google.com ([209.85.160.68]:53453 "EHLO mail-pl0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753998AbdKHGUG (ORCPT ); Wed, 8 Nov 2017 01:20:06 -0500 Received: by mail-pl0-f68.google.com with SMTP id g15so667284plk.10; Tue, 07 Nov 2017 22:20:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=CFdrfCff2v4vAqK8Mf/nGf2qHrUAxvWsFVHPqShlZmg=; b=JNP8QMrREgK0uEplHjpG57Xi0MRAsl95ZRizD1H4ir+4L3f8B5Sw93t+K2QNicnTt/ NBOPrxP3yqvoCX9XtqBaUds1XWtWu55szrUjLKuaXEEAqemwwqAkMKONc2R512h3w0x7 /jcxEjT7dMbG5KrKGX3g4vXErV3Y+WinD8Q/IAU2mToAbLVkWz9C4RW8mGq5vHwHXVvM L8bOHbHLaRJZIG9tJ2I0ERGGO8pk5Vv07G51W5zJiD0aNZRNcvmXFZK93cVFWWv9smOn 4p0z6fsTzLhpOqdQKJjURRlOd7dpjRSZmHU7lW0QlI78MDHVgm1doDhgf9keJtcVOilJ XNCQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=CFdrfCff2v4vAqK8Mf/nGf2qHrUAxvWsFVHPqShlZmg=; b=akfMpOR0E6BHa6pfmlrYo7xSRC+7khsmBomfYb/X7kAj0N0yAoUdOrisomWPcM9T6z enwulhdSbR3Xd2Bn4cbqrkXcHcM++PnnIm4wBI3Regsm9Ve5K3vd1NM2I21ZUDapbKvX FkO3r9jvp1bwrT0zu+EW08cZrC+Rg+Ubz0CsaIppSGnNWxjOnnJpCwZVWKrkagSb8d9q 7Sc8/EXTpTIIyIwNnhkh1ufK1CLeP8sSNpc9xQEnfqTmDxdvR5qnNwLhxA1S4x8t73Le OyN50+n0TKOqx4fnJiZjh23kfNNHY+eV/Y7hr5qyAiQqlzFPi7iJ4ZuzsAHq8DfIWZ7X dzBA== X-Gm-Message-State: AJaThX5Xt3YkJhzjNzMtIWOALfwARqhV4FONevgLJju3mlmQOm1Tf+is uAFdYT6NQkZsQJDaImAY9sk= X-Google-Smtp-Source: ABhQp+RPmLhZMMuadIXZ1iOe6aInZ9M1Q6usqo7ym0XbiXx30ZwJbI++7OFqUAGQgu/XsXsSdWquCQ== X-Received: by 10.159.206.193 with SMTP id x1mr1249214plo.319.1510122005493; Tue, 07 Nov 2017 22:20:05 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:04 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 04/31] nds32: Exception handling Date: Wed, 8 Nov 2017 13:54:52 +0800 Message-Id: <9caaf73b79b22357ef957382eb7c0151a2d7d189.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#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 + +#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 +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 . + */ + +#include +#include +#include +#include +#include +#include + + .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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +#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 . + */ + +#include +#include +#include + +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 . + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +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 +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 . + */ + +#include +#include +#include + +#include + +#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 ®s->uregs[0] + idx; + else if (idx >= 28 && idx <= 30) /* FP, GP, LP */ + return ®s->fp + (idx - 28); + else if (idx == 31) /* SP */ + return ®s->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); From patchwork Wed Nov 8 05:54:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835657 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="dwg+P580"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWxHh31mTz9sNr for ; Wed, 8 Nov 2017 17:30:24 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932247AbdKHGaG (ORCPT ); Wed, 8 Nov 2017 01:30:06 -0500 Received: from mail-pf0-f193.google.com ([209.85.192.193]:44834 "EHLO mail-pf0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753961AbdKHGUK (ORCPT ); Wed, 8 Nov 2017 01:20:10 -0500 Received: by mail-pf0-f193.google.com with SMTP id x7so1121806pfa.1; Tue, 07 Nov 2017 22:20:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=nyZFdI9Ea64pXt6hcFSnOik3J0LH0AhWzZSMUSbbeNg=; b=dwg+P5806z1b6WZ9fVemhIdMaVFhT1fzEbKuFiNNqsw4I/nN6sketTXQhHv/oswf1Y EkhKjFQ8TaYL2YM+07+FTBVVX62f9AwGO8BNaifaSJ56a+asTITwpwPd4mRcAmFAt8So 7GRQD+DKSEgBeyMwrcXkdtU9BPU/5bIcoqLGFk1f94PE5/oEinJUQ5Kpoh134/mPLDW6 7RqQ3gG6Ycjrxx1Sol1VrPLSC8A7WrAtZnYI/wdyWle4ojWk0zqQJh7vTszz+mkZPtob CoersFSs5DCzZEMPctT28b+2o/Xh5XJnWL3KcRuBX1sNwXsx1kunzyAmjGRyewcGjKVs ik2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=nyZFdI9Ea64pXt6hcFSnOik3J0LH0AhWzZSMUSbbeNg=; b=LHuhB5YoqR+0W2M+6cT/eaei7966VaBtBg+330r7NsVilPRH+U0uisyp3WkrqoP2V2 tCV3u1J7GHpU+L+d+6VtgIyXgVdZSzLTDH9mqP2ijPsvAJ6syE9at4d+d2MBkBPjAJN6 VqPhrFqA08mXasxOiNEn+7M7upamQ4v+XrDnLZaLrBtYusj3DxXkvhpl3CZ3tgyGpXxp nscqPheBnpXLNdoFNk6UCPOZOHcS6P8MWfY9e/Hh6u0oGNXLMxLEi+Z9zXobUK7SoQ9Z Yag2x+QwXQFB37XbL6jftqLhtDGTI/sMVb9rgzFpoqO1tfnZ64j84IGEsRPLxH/gTwHJ 4Eew== X-Gm-Message-State: AJaThX5QBjAMShmg9aGil1h3zYXKAnbll4kATTmVL02uTCWG8/JpvKO1 Op0ZDJlVjbTY/H5PbYz0/PQ= X-Google-Smtp-Source: ABhQp+QIXv+juXcdDffbMas6m/lr3ZE3cErsyXb1dR3JNp3HJMbgVB5xQsyCI2Hj7n5k+yKTDeYQDw== X-Received: by 10.99.95.139 with SMTP id t133mr1263268pgb.448.1510122008588; Tue, 07 Nov 2017 22:20:08 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:07 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 05/31] nds32: MMU definitions Date: Wed, 8 Nov 2017 13:54:53 +0800 Message-Id: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#ifndef __ASM_NDS32_FIXMAP_H +#define __ASM_NDS32_FIXMAP_H + +#ifdef CONFIG_HIGHMEM +#include +#include +#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 +#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 . + */ + +#ifndef _ASM_HIGHMEM_H +#define _ASM_HIGHMEM_H + +#include +#include +#include +#include + +/* + * 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 + * 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 . + */ + +#ifndef __ASM_NDS32_MEMORY_H +#define __ASM_NDS32_MEMORY_H + +#include + +#ifndef __ASSEMBLY__ +#include +#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 + +#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 . + */ + +#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 . + */ + +#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 +#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 +#include + +#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 . + */ + +#ifndef _ASMNDS32_PGALLOC_H +#define _ASMNDS32_PGALLOC_H + +#include +#include +#include +#include + +/* + * 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 . + */ + +#ifndef _ASMNDS32_PGTABLE_H +#define _ASMNDS32_PGTABLE_H + +#define __PAGETABLE_PMD_FOLDED +#include +#include + +#include +#include +#ifndef __ASSEMBLY__ +#include +#include +#include +#endif + +#ifdef CONFIG_CACHE_L2 +#include +#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 +#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 + +/* + * 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 . + */ + +#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 */ From patchwork Wed Nov 8 05:54:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835658 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="O9wyYnd7"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWxJ463Ddz9s7C for ; Wed, 8 Nov 2017 17:30:44 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932165AbdKHGaF (ORCPT ); Wed, 8 Nov 2017 01:30:05 -0500 Received: from mail-pf0-f196.google.com ([209.85.192.196]:44836 "EHLO mail-pf0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754017AbdKHGUM (ORCPT ); Wed, 8 Nov 2017 01:20:12 -0500 Received: by mail-pf0-f196.google.com with SMTP id x7so1121846pfa.1; Tue, 07 Nov 2017 22:20:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=+q75Fa4rh8sqegf65JC0UNFaRYtZ1DL6ComrquAsjkg=; b=O9wyYnd7HerOJsNGlTVU928pMqFF1RbmpYVdc5teZOWfIuUj5LkINSdKIvglJBkcmt f8p/PjW+82xG7Lsc6gNz7uMg9FPJreRt1ax2Hb043Fj/dFnD82LbsN5JLnntU3sAoqUZ jveLNdMVS7BllWDFKLxlz3oYZk/LYWp0B81NQcyvuarCdtE8d+oHGx79CDJbo/5f8/t7 ujWhWQyEHBSqRr214Z+54kvPnclBkw5Lm5HfKKcq6/BmH4SHol96WQ+Jd8ufneoOW6iy tjJGSgwnKczrxKxLYclFZV4yvoS//rZjNhmAen7uYha+EDa3Hp9Z3ytlHrY6MY91CgRZ ai/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=+q75Fa4rh8sqegf65JC0UNFaRYtZ1DL6ComrquAsjkg=; b=GKgG/W0M3VpqC9AIedCMqJXYWfp8/rLdbGFqIS+tVPcrblVpv+4ELCRN2zhe6vMHqh 79kqd+chbxidxacAEp3DjGDq8XVk9T5DcNZzPRRyPPae2uB6H9HR3Jlc+YEMyApoch8H Ipw3p2Tmli3eb/luzEO3hwiM/3I++2Y3vG/CMnRU2kTvoeDk3g0lPa2r6tI1PQ35COhL Z3tuW9ShjnbS87zZmQIdluykKPgle0u+gAl9/T2CoVYadleMIw40StyWmWEHjV9cvF7Z zA6LkrITW/pn97g6NNk/f3ox1tLX2BEZDRoP+omXASZ7RjuFCBagf/sG33pJEtuYxLBr dfJw== X-Gm-Message-State: AJaThX7AR2TuW+G7aOrs07aBw3LKmcwTmVVWqMSNRIen1a8ojehMgXo8 AWAfkoXJ0SDB1u7CyVew558= X-Google-Smtp-Source: ABhQp+Q0GNueCOgovG/XiScQwyUdNfaS74kcpLbneRHoqGKJUvlHrf1PMk8KWcuhiosmz9BfAOE9HA== X-Received: by 10.99.4.209 with SMTP id 200mr1307508pge.123.1510122011152; Tue, 07 Nov 2017 22:20:11 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:10 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 06/31] nds32: MMU initialization Date: Wed, 8 Nov 2017 13:54:54 +0800 Message-Id: <9ff6624a27139cf00776362856aa07a0f8d35cd4.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +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 + +/* + * 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 . + */ + +#include +#include + +#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)); + } +} From patchwork Wed Nov 8 05:54:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835659 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="ag1gesAi"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWxJP6pj5z9s7C for ; Wed, 8 Nov 2017 17:31:01 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755385AbdKHGaD (ORCPT ); Wed, 8 Nov 2017 01:30:03 -0500 Received: from mail-pf0-f194.google.com ([209.85.192.194]:57127 "EHLO mail-pf0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754021AbdKHGUO (ORCPT ); Wed, 8 Nov 2017 01:20:14 -0500 Received: by mail-pf0-f194.google.com with SMTP id b85so1098403pfj.13; Tue, 07 Nov 2017 22:20:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=akklE2uAZSQ4E6W0P2WDFKBwHsEF5TSbKFOfXFEH3ts=; b=ag1gesAibBxH/ucZ/CevsTwZUkCNkWn40JH6lUeRi2NP18APhiQNgbMjtCjpLbA9C9 lBLSZ5GztOvCU0A5jMZABIxxgmmXeZs6Hjcepn0wcnCdWUUbOwe7SG5137vDH7TG4FB6 WgSCSCEiI5O1Vcia8+aKGh5rbkVnAf7wMsiC/729UAsQKRW9/cx/wEYRz33yqq7ZFLhi XqSBlfPhExKPJS3hok3aGmOKTZAqCP1VLVDFX93nwGtmkLxJ46+oFdMet4tV5hN/To/U KwRhi0tngWJlB7GVV/7bAtXvEKk8cGdUejPx8kxGYvmNQYoOur8dnDdD1NacbE7TFh9s 4ojQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=akklE2uAZSQ4E6W0P2WDFKBwHsEF5TSbKFOfXFEH3ts=; b=M46CO9FokoIrTT5CshpEs6pf/Sf8wTdnbUsmyyYYuUe3bgXiwKBopUoJkDTm/pdrdH KjzYUn7CLQz9WRBtDRYiRi8+l6UecXcxezxYqCjyjkwEtWhor20QRw6MhF+0CjVPxYqS GfsuUIpyYuUGsa33OtbnFf9yc5PsHIfdVWGt+FCj7jdCEo7Wd5VLpHSLC4v0clnG1MYr 12u27fqXUkNvTMCPnWCbZpcdrcuhiv+s5B56TWU64TglYQjlrxMmgtuTsK+P/jCRjdxv B6mqJp0skx38azH0lcHHiSgSL5mIS9mtQkLvESaQKy8sRdvAQgbO1GlWWSB0FWprxeqU sIuQ== X-Gm-Message-State: AJaThX7+IfWzMDmPMXOAcmJvwTO4N693jZkziFJdU5NTc8mBH1qkiiAX DB0EzmQdyI85rSzQ5KGCwFM= X-Google-Smtp-Source: ABhQp+ReCu2VCqKr/EyQkGREOd6mXeRkGwjdnOPdO7/fkDuKu4Q127c6YOHJlWCkUaaCwWAGXGW37A== X-Received: by 10.99.110.197 with SMTP id j188mr1283778pgc.34.1510122013624; Tue, 07 Nov 2017 22:20:13 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:13 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 07/31] nds32: MMU fault handling and page table management Date: Wed, 8 Nov 2017 13:54:55 +0800 Message-Id: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#include +#include + + .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 . + */ + +#include +#include + +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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +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 . + */ + +#include +#include +#include + +#define COLOUR_ALIGN(addr,pgoff) \ + ((((addr)+REALSHMLBA-1)&~(REALSHMLBA-1)) + \ + (((pgoff)<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); +} From patchwork Wed Nov 8 05:54:56 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835650 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="jcAVISDc"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWxC56KFtz9sNr for ; Wed, 8 Nov 2017 17:26:25 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754085AbdKHGUf (ORCPT ); Wed, 8 Nov 2017 01:20:35 -0500 Received: from mail-pf0-f195.google.com ([209.85.192.195]:49461 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754045AbdKHGUS (ORCPT ); Wed, 8 Nov 2017 01:20:18 -0500 Received: by mail-pf0-f195.google.com with SMTP id i5so1110196pfe.6; Tue, 07 Nov 2017 22:20:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=8zRYAkDhVrNO3gWAh/dTR0MU7K6NE4gHiKTCCXlX94o=; b=jcAVISDcQxZWOvn/0ClJawrbLwLtkSAASyIqqn7vTiLqRbozvJpQqGx6PqGUkvMDAD pbAO2Mo2gs/WUNHpGy3KM6Bc7kLBBG5JFcM8o/e2E//N9+e6PmKwIdPKTUBaCSGnA2y2 B39JnUUHvOprWwwApe6s69Spmp+4oXnJQVr2ZhnRT5Tki4BzzDztxgwCDH3az8w/vmT4 e2SGeQgbGFWzPqWoqebL+5cR863F/HO3ebxgEmJtq38AKjv1tHISWvf44v66iv+dBcUf RuhwI2hCd/KR6OlaL3oXDMdQ1shmuUZh+9cKfiZvoKyAsjx8b0bnME9uEjtezkQ7WKut RkEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=8zRYAkDhVrNO3gWAh/dTR0MU7K6NE4gHiKTCCXlX94o=; b=dB7rxEIRC96cQk87sXND6N6rPfn800hNnPn/GUXKhX/cGFjiZSdm9u7GGzLD7C79MU U+bN6Yuhx8sppXwO66qq8w0+Xi90S7MWgnOxS7bbkIfr5iyejvEsfIDRJkZaLKqkLWvq ZBZAen++LVOGce9R+ASLsqgBpsBB1g96LU7oqTPG1SnFqaTph/U2ibKtZ7z0DJvTq3NX AmdQZyVbjg0L0Zx9q0MnhqBu+t18KFv2OUXaIDLt/EuD1KIoLABzkRWJDp2bh1gnKgG1 GBcMQmH6ZYdrSETk7WDlsI2GlI/Hu/ZO11GRD98QhjIoIy6UCDL1XVEOfpjpHtebGrMA FjeQ== X-Gm-Message-State: AJaThX4w0gi3Sy/jJ1OIlsZHBxHybw+AVJhtb8b2PGstdOkrnrD+HHMR zUqZG4eqsmodjORSTVIdgOw= X-Google-Smtp-Source: ABhQp+QT/JvuV0Fey/Jlrwz+9LU0enNRIyrd0ZsnQOHoACfYRqua7G2qcFaSTnnfW8HKcwltYhYa9g== X-Received: by 10.99.140.22 with SMTP id m22mr1291143pgd.258.1510122016347; Tue, 07 Nov 2017 22:20:16 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:15 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 08/31] nds32: Cache and TLB routines Date: Wed, 8 Nov 2017 13:54:56 +0800 Message-Id: <220aabe68365f970ed6de79ef88f9598f272dcb9.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#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 . + */ + +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 . + */ + +#ifndef __NDS32_CACHEFLUSH_H__ +#define __NDS32_CACHEFLUSH_H__ + +#include + +#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 +#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 . + */ + +#ifndef __ASM_NDS32_MMU_CONTEXT_H +#define __ASM_NDS32_MMU_CONTEXT_H + +#include +#include +#include +#include + +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 . + */ + +#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 + +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 . + */ + +#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 + +#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 . + */ + +#ifndef _ASMNDS32_TLBFLUSH_H +#define _ASMNDS32_TLBFLUSH_H + +#include +#include +#include + +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 . + */ + +#include +#include +#include + +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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_CACHE_L2 +#include +#endif +#include + +#include +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 . + */ + +#include +#include +#include +#include +#include + +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); +} From patchwork Wed Nov 8 05:54:57 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835655 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="jx1nMyRs"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWxFY2wTSz9s8J for ; Wed, 8 Nov 2017 17:28:33 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932129AbdKHG2b (ORCPT ); Wed, 8 Nov 2017 01:28:31 -0500 Received: from mail-pl0-f67.google.com ([209.85.160.67]:55889 "EHLO mail-pl0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753998AbdKHGUT (ORCPT ); Wed, 8 Nov 2017 01:20:19 -0500 Received: by mail-pl0-f67.google.com with SMTP id f6so666068pln.12; Tue, 07 Nov 2017 22:20:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=Q2gCIjdfT2q8G/Mefp5vdfMmB2THsmv8IV0Spa8PW7w=; b=jx1nMyRswZeTx8oZXSD368ysYBceyZ6DIPEOflWtb+h7aTh8sSOQ4FbXoWqUD9XwGH yt1f6f4x7q5OgNcX0rPmB3LB50kT/fZBy8iLekLbRc9l4+QGRjMxSllO4nPA6+gHxEKn UJ930EM+WYEQbbwAUgX6KKASIoi+Y06Xo3a018oSFkbn+fxAzKPiwoTiII3evDByhrC2 kNs5sV0DcqZmadTVbcHUFmcnr4PZ/KLlUr2XeQJ/Oc4wRKQNe1t76DLZsNN73bW20VQJ 29jGVYnJhAknsRq5b9eRvepQJSjSlhsCPnkPIf6Ybt6eX2T6R/j46+v9heFlkUPT0Fxf 6luA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=Q2gCIjdfT2q8G/Mefp5vdfMmB2THsmv8IV0Spa8PW7w=; b=ngXvBgZWCaWL+ymfedUjAPIkRnQrIXAN8OmYoZQNNzifWLoJ3F3KflbtqFbcec5uoY raEKNpc5TdM9vdj9hUrPwoNLTwzIssxzQW9VSneI53E9yY8xUAcXN+3pFBq4d9R9IXeX 50QP0qdupJUzshB5z1qoeUaK+SzpgBU+wLOQesd8+/Xdku6vnHo0nJn7yR+5jYqRyMFn ST0lO7Nzwf+eQf1s8Ey3KWX9J5jviVmC6TbKxSGSYVfdaWi4aqtuxfgFZKpcy1tPAb52 TyjGFQHJ8absV50ymQqyuJzVJ6mxOjTVO5Bt4Ev6ZP5arbkyXtIGqU8OEM6VtjeQtEEY CydA== X-Gm-Message-State: AJaThX5xjW5fX8h/EIe/in3hi77hzl+RRJtGyOFVafncwrR4/0eMWPmc WmO02zHoGx+rNBLPlVgJOzBgieXc X-Google-Smtp-Source: ABhQp+Q81o4ezfD3hRHToaMMW7e8KaVMFiOzrr1g9MEQbYj9pIbT1MuBd1iSsWSZcmuTCd4mWWkehg== X-Received: by 10.84.194.131 with SMTP id h3mr1252238pld.215.1510122019032; Tue, 07 Nov 2017 22:20:19 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:18 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 09/31] nds32: Process management Date: Wed, 8 Nov 2017 13:54:57 +0800 Message-Id: <88fea1189a8034f5307c21dd5cefb708d3d1b78b.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#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 . + */ + +#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 +#include +#include + +#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 . + */ + +#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 +#include + +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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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); From patchwork Wed Nov 8 05:54:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835656 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="jvNaft4t"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWxH50BCBz9sNr for ; Wed, 8 Nov 2017 17:29:53 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755273AbdKHG23 (ORCPT ); Wed, 8 Nov 2017 01:28:29 -0500 Received: from mail-pl0-f68.google.com ([209.85.160.68]:44414 "EHLO mail-pl0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752725AbdKHGUW (ORCPT ); Wed, 8 Nov 2017 01:20:22 -0500 Received: by mail-pl0-f68.google.com with SMTP id g16so668519plj.1; Tue, 07 Nov 2017 22:20:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=opB1C4pxvbrN1XMCNgv6cUwMwsRULbjReV+vbtLouNk=; b=jvNaft4tZBRCiBYRXcfoRDZYawmnjH4z36boA8OGctRuVAhrtBxp6EuubM89lUaWrz nGq8rm9qSw9glPqeuoLhs0W4hsy4L5DH/vIJziaYuU4o0bsdQmeblBOWNeRjqi3a3RcQ xfXrWzuUplM6r9kV4gYwznyqOHp2YDOb1iB9vC1+zIkYZcc5kF9pZAeFy0ngKJRFgjbB YYbgUT/8bkFUKauHQ76iSXO8HkmVLvuI9l0LnMl5yYcDAZIJaEd8AZP9TzwilBeN7Qt/ p3pecNvpkQFBItRS+9LFp3ha8z0ErEHc9AfHgp5pUAduIovgpuCu903BaBNYim2JFo/0 uqPg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=opB1C4pxvbrN1XMCNgv6cUwMwsRULbjReV+vbtLouNk=; b=YkNKqfirr8qLeh4ouDF89BrwXrI5bwFGXqNIymnhZ2hjc4u+lMfm0+rm3U2H18NAmK 0BpnLLxEYh+phUPhrUvlbuxW5Od89K3vXNKM09gIq81GRvslw+RDkOZ36cXs3hvAgJ9Q HV4pY0Qns6EOrWjphyoD3VKEw9TZsUeCSLwGCyEQ1sOS5muUMhIa3AeDEFL5/7s4Jk2K +YXzQq5A3RAqh5nAiUiPGWpLwG2ny00r8/0k5xRk8+yYbkjJKRaIGo4F+I6QtVgj0rsA 9ywjYr8wT2tLrCZqOj4jOKqg/8J9D00R9NpQdT8B1lSI5STTZUD+O5X9KDecmorXljdv T+dw== X-Gm-Message-State: AJaThX6mbMstySAihV4C5ikEZnh4adMXXbbL4HilD8V1R/HThDaKFkqh P7dKwTUeDvGODu/AQCo9RfE= X-Google-Smtp-Source: ABhQp+QoRtMxN6iMp6PvbgA14lA5aj2DZrmiCTxvgcn0NBP91V3uW2pNzPXDMe8uo795gdhXpYrqBQ== X-Received: by 10.159.218.135 with SMTP id w7mr1254603plp.229.1510122021750; Tue, 07 Nov 2017 22:20:21 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.19 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:20 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 10/31] nds32: IRQ handling Date: Wed, 8 Nov 2017 13:54:58 +0800 Message-Id: <9dea9004aa59acc2e02405b192887b8e60449100.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#include +#include + +#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 . + */ + +#include + +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 From patchwork Wed Nov 8 05:54:59 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835652 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="qu7xfytC"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWxCP2W2Yz9s8J for ; Wed, 8 Nov 2017 17:26:41 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754995AbdKHG0i (ORCPT ); Wed, 8 Nov 2017 01:26:38 -0500 Received: from mail-pf0-f193.google.com ([209.85.192.193]:49469 "EHLO mail-pf0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753864AbdKHGUZ (ORCPT ); Wed, 8 Nov 2017 01:20:25 -0500 Received: by mail-pf0-f193.google.com with SMTP id i5so1110320pfe.6; Tue, 07 Nov 2017 22:20:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=qESlqYm4mwTFyIZxoiO4dC189AquJbzJN9xNsbrgtJo=; b=qu7xfytC/3hNi/9zW46IW1R6qaUwupptax2mmD+xzh9jRZSVjDp+kfnra2/JCP9yNn dLYT2mMLyO1JRYcwc9ntrD21k+p+RrmuC+avodwGDXTc4B8CMkOcDlrxTaBTKZNZcSBY 6pi4cwL32MFjJwnc25J4VIromcw1Vv1Y14EGOVepfYf0MPMoC1GaLqUbjoW7iycQI/cA gGA+8vX73hXM4ypKwIxS6II4GQYdM2xGF1RR464qxxMkkQ0M+DIt3pWeWf8AQ5L89eOb Q6x4hRhrKHklwAIDunmDV/7ou7RtwmiC0DzH/zfKpoXbaOF8hrawdSqWsgmRLTs1ybW9 /Ccw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=qESlqYm4mwTFyIZxoiO4dC189AquJbzJN9xNsbrgtJo=; b=bjkO9j5QPXw9YheIY6NrEuUGSyeY154WHydBPT0B4M48nftgmJkrRlF836mrOFVvhK mDeBzmcWnG20njFe5lx5jiV+/6xcIwzWfG7kTBDESHFh3pRwcIUVeaaDleVjxVJZBdgi vkMccBMwUikQKqFePDPXGwTUmt0CtKkEU8xE1tad2/KzWdArjCC2oIY+SuACWlVCMIil o8epV8C4JuZCQK2HYaweZkVkJzjT9F2NGLVvdF0i1bJvJYZBHSp1uhwKTWt4bEfeVApG 6jqIwANeIw2OtsxndKNiZsBTDQZXX/Kz47qEeupoAxFtsL11tJTxJ96kCg8kBIcEyRAh ot1w== X-Gm-Message-State: AJaThX6R2WiI4B0xzygB8LmpTqZHi1KsPTNpoblnNC1EFT/7l77UASXx eFKaE2pagkQ6bkUU53F9fpM= X-Google-Smtp-Source: ABhQp+Rl2ieAZRulSscOZtk6wR9HPlferZFmenjVizaYA985AxR38numKzpTdqdpq3skkzP4sr9AOA== X-Received: by 10.98.202.133 with SMTP id y5mr1410962pfk.122.1510122024269; Tue, 07 Nov 2017 22:20:24 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:23 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 11/31] nds32: Atomic operations Date: Wed, 8 Nov 2017 13:54:59 +0800 Message-Id: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#ifndef __NDS32_FUTEX_H__ +#define __NDS32_FUTEX_H__ + +#include +#include +#include + +#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 . + */ + +#ifndef __ASM_SPINLOCK_H +#define __ASM_SPINLOCK_H + +#include + +#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 */ From patchwork Wed Nov 8 05:55:00 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835653 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="emzJhxt0"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWxDG066Hz9s8J for ; Wed, 8 Nov 2017 17:27:26 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754978AbdKHG0g (ORCPT ); Wed, 8 Nov 2017 01:26:36 -0500 Received: from mail-pf0-f195.google.com ([209.85.192.195]:45127 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754063AbdKHGU3 (ORCPT ); Wed, 8 Nov 2017 01:20:29 -0500 Received: by mail-pf0-f195.google.com with SMTP id d28so1120403pfe.2; Tue, 07 Nov 2017 22:20:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=AYDMA+Ccki/GgCYeDOf9TCWza8OYBoatZLbp04chwOE=; b=emzJhxt0c4HqomdHZXrkIB7lO1CPuS5DXRssahS7NbwrJN42KKd0AWLwavCUd6BETD IvoXSPNaoa75XhABRCGZmMX+cnuX79WIhp1+rogBS4C3CNlmHCBlY7vNJBAT0l9o7RiM C1kd6RymSgie4HZTCrpgTAWY4DzcxgfQKQVZW1XwujduNlr1Uwl2ry3LVCLNB7XPSzCg XeEf+zjug6oDF+FbNsuhGdUSIuSJ30hoJaE9v/iPOuzvotadu1auEgC3IYepEfgWisv9 k7WBk5deqTIZ6ibc8KFPwlhBTabX2kDOFI1eqT1lzYXBAtDv0ASw0lRJ9bB6gbCxNPQ+ VcWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=AYDMA+Ccki/GgCYeDOf9TCWza8OYBoatZLbp04chwOE=; b=IMvVzN6TnOP31K8ezJuiGpAQb4XaGQOMIviqKfAaDryaRkEWrfqC3VagdVel6O4cZf N/10CCI/ABO9p78+weiLNkTyEo/BRysuj2GAQAKN0KQoDU8ura/3oKxgkXf9yravCiOn rMQeP5eJNyhM6pSEmSIAiZwlJTV/BktaqzeK7MJw/hMcfg8wbfGOU4zYOJKhfpJ/B6GR w3djt9+UjiI9MdrlkmiSRQ2cTHzvZTcejF9JJE45qdRPEKrWJ8aoXuiEcJrwQUDvOsaa nCg2eXJtHLUJLp7dOS6DGeY2gvu8S8mysMGggd9FR8s6HCatAqQGI3AqqjRDFVhJ2sbe g3WA== X-Gm-Message-State: AJaThX41y8Vuj682Rds4bL4SOclxlqKr0kV/ka2TXQz20fCDMuk4CAKp D8lljDGkmKH0Xam6+Gsftck= X-Google-Smtp-Source: ABhQp+QoLCUv9qkuEDvIDh66cmk4ZQreJp8fOkbbBW1NuU4esl4+yFIzaua5cG0OkfV1e6ABoCEPXA== X-Received: by 10.98.224.11 with SMTP id f11mr1385040pfh.43.1510122026823; Tue, 07 Nov 2017 22:20:26 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:26 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 12/31] nds32: Device specific operations Date: Wed, 8 Nov 2017 13:55:00 +0800 Message-Id: <4e9acf2ec55fb26ddb290ca2d955eeea628e0a77.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#ifndef __ASM_NDS32_IO_H +#define __ASM_NDS32_IO_H + +#ifdef __KERNEL__ + +#include +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 + +#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 . + */ + +#include +#include +#include +#include + +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); From patchwork Wed Nov 8 05:55:01 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835651 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="p/zRvFk9"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWxCK51RXz9s8J for ; Wed, 8 Nov 2017 17:26:37 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932143AbdKHG0f (ORCPT ); Wed, 8 Nov 2017 01:26:35 -0500 Received: from mail-pl0-f68.google.com ([209.85.160.68]:44526 "EHLO mail-pl0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754069AbdKHGUa (ORCPT ); Wed, 8 Nov 2017 01:20:30 -0500 Received: by mail-pl0-f68.google.com with SMTP id g16so668710plj.1; Tue, 07 Nov 2017 22:20:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=eoM9XptiViYne5XeHQbbi5n90v6YpYZ1R++LiO3mi/g=; b=p/zRvFk9iyOV5EiJHyIrpyAgCkZKTLSErByz1ksKV/+pQvv0d4A7gjdleoc84WNkVX teUHlC0fox4rvMTafsjtpHcuw7vmmbWl6GslOikLDKObPbA8ED5r0gfglwGGoLggi/a4 sIg4w+Vjyq9a/MiVmJxs8Vwg1TwEPPPw0d3PRN1kmCdlddXbMcn+aaAMXxmPCSiKbz3+ 0XVZHcXRWUBAHE+n60YpCivk1d8mIhKJMAld7sKzW3qBudgpNaICDQKKCREfnLNdPMgM bcwYN88mlpVPVGnbulxlauHm9RkvQU7fU223BobZrw4now4leh29gIG4qo8plftIZSfO 2lxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=eoM9XptiViYne5XeHQbbi5n90v6YpYZ1R++LiO3mi/g=; b=G9UzwE0P3nnDqYjq+XEqoF/sYwFEkHGw6/haWJMoPG4Gplgbk26JMu2hUc8Wpte4Ui QoJEt7c54YLT3KWklIB6VQvBMDILrZH9/5KJGiD3WICfxfaQiuJXiNcQjE4i3r4fDdZX 5D2Rpvsw1VNtc6QbPbO6ppjKS+CQQR0IdG4LFvh20y3DEjWAPkw5cDAm7J18SlFA7yMJ IkIUE42byEWZYkSANk3MC1E22CkTAJiqfSLJ/oySPUbjpr1AFmln7zrWFj4DFlO858EG FT8iUWJIXO+NfPHkKgvz0M2tU/PLnfYvnZR0YMV4DtWkgIGONjTgpIBnR5baBW673cOE kVSQ== X-Gm-Message-State: AJaThX7KtSaJZ3/Fk/mcfBw81DqSCDWuI3jDMBy763O9i5GLyxCArY6Q 5peBpEK7OKeACduj1Ogwfj4= X-Google-Smtp-Source: ABhQp+QDitfin1pTRIY4mMqbAxRgpuFWgaO/S0FhiVEpiWai671NvrIh/FyoqwHuxuc8Aaj5UODk0A== X-Received: by 10.84.246.197 with SMTP id j5mr1227397plt.7.1510122029361; Tue, 07 Nov 2017 22:20:29 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:28 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 13/31] nds32: DMA mapping API Date: Wed, 8 Nov 2017 13:55:01 +0800 Message-Id: <763e6a252de1ad8ccd28344fd0676ae2f92f796d.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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); From patchwork Wed Nov 8 05:55:02 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835654 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="MKEmBRQL"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWxFN6QSYz9s8J for ; Wed, 8 Nov 2017 17:28:24 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754954AbdKHG0d (ORCPT ); Wed, 8 Nov 2017 01:26:33 -0500 Received: from mail-pl0-f68.google.com ([209.85.160.68]:43353 "EHLO mail-pl0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754072AbdKHGUc (ORCPT ); Wed, 8 Nov 2017 01:20:32 -0500 Received: by mail-pl0-f68.google.com with SMTP id t7so668116plm.0; Tue, 07 Nov 2017 22:20:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=maWFsOnPeEoq5bUK4im4HT0oLK8ZhBeuq17Tn6RsQCo=; b=MKEmBRQL3BKCkn1ccyeKtaWcm3ympxOghW0KmXfqJZePN6WyLNYnZmJ8SjQFC34CkP PsjuS2FEF227QlAXlLbZ1pW1CgTGH8S8YK16T+63TDrPzRAHo9KXXn2FYMBawT7a2y2F gHbN/UWHioNIrhmLXRFKOYHlt+kYpBFEpzZiZYAQAI/nfgDQA0b2lTjpDUd6EP15dX8F MYcn1+J5iAXXOhjQUT/J5iaQVFH9FCysMxatWhXszk3O/UJobr+D9+4HBdb3pwkNRbX2 vtUyAciTsKzJC9bX8d83ueyJ0SS55RWIffo/Au3AwkCwNTliA36J6ezvJbZDVTkrOP20 HrPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=maWFsOnPeEoq5bUK4im4HT0oLK8ZhBeuq17Tn6RsQCo=; b=nUdcm6zNsuHfFwsN20yNCeZU3hDHIN/zzi8jNNNjpJ+tOkel02RFE8MnNkx472THGE EY71ZmnZE+lwZBOhVcm5W2I5tc4ECoA0yYzYkpWrwQrUfJmIos3Tn8cH1Jbd+rvRaVlV N+kwFDTwsgIDISu4wiakaswZesOnQOijcTvUGdvLP5piu5NchfIngMPBFirmNQmKXHBy bF3avnoLgcT25WljipYM5qOZteQOTWYT6Zod8w6IGLZ98Nu/V3Rm5XnLxJ09r5bNGmdo om+pw+u78Ppt42iJNfiuE7Kc3K788xP4UdAaj6LAGI/wNh9CE8TKlRrYMmlg2tnYxvne r0rg== X-Gm-Message-State: AJaThX7BJ910fHkmY2O0pqsal/72PkTyR/TUPpdm2LHRfIAaasi76OQn bo9SnWvF0ndflBjQQBYdoIgAWU3G X-Google-Smtp-Source: ABhQp+Tic6PCnlpvPAgMd8tD3JOqQWGUNDEcfVGM+8YFDc4GPVH1pGw3RbTJl4j6kMr17agyAi4twg== X-Received: by 10.159.229.15 with SMTP id s15mr1223546plq.69.1510122032003; Tue, 07 Nov 2017 22:20:32 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:31 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 14/31] nds32: ELF definitions Date: Wed, 8 Nov 2017 13:55:02 +0800 Message-Id: <2889e83774846be0e914bc16e0d6807c13903eb2.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#ifndef __ASMNDS32_ELF_H +#define __ASMNDS32_ELF_H + +/* + * ELF register definitions.. + */ + +#include + +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 . + */ + +#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 . + */ + +#ifndef __ASM_NDS32_PARAM_H +#define __ASM_NDS32_PARAM_H + +#define EXEC_PAGESIZE 8192 + +#include + +#endif /* __ASM_NDS32_PARAM_H */ From patchwork Wed Nov 8 05:55:03 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835646 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="rlhAOpdy"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWx9w6X4mz9sNr for ; Wed, 8 Nov 2017 17:25:24 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754138AbdKHGUn (ORCPT ); Wed, 8 Nov 2017 01:20:43 -0500 Received: from mail-pg0-f65.google.com ([74.125.83.65]:47416 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754094AbdKHGUg (ORCPT ); Wed, 8 Nov 2017 01:20:36 -0500 Received: by mail-pg0-f65.google.com with SMTP id o7so1174929pgc.4; Tue, 07 Nov 2017 22:20:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=t6gHRrrzTiGO1SzKKNobiZiRs75jHG2hDCQUmWcl2HA=; b=rlhAOpdyEUIMs1l7oqLGjsWbxufUUhhHDK3X4mQG5Ir3VkiSyb0E5IiYXcSWFXSk6b IfHf3yHbRVkRmueP7NbP3oZZGHjL0b5Ym8wGZsg+Y2FtL5lVsJJA76ZE63pw06LDNI3p C8Q8HxB6OVS8oX7wfMo3Vf4AnCsgRWi6ALJOBJsY2o2ozwKm1PDqt5aVf8A6xptrSzVc VETtyhtCsWcnBHL53OHMuNDtMsETiBVV4G4ggRd3w431GvwuMrGxyWZajgt5ytFvozIM HpX6wM00vt9ZhVFVAI18vKeeNYMGsXGIPgJU8Qu9X5KVGkBD8kH6VsB495IuR7XwOQaR L3Ig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=t6gHRrrzTiGO1SzKKNobiZiRs75jHG2hDCQUmWcl2HA=; b=ZzpT4raaIBf8bEohOGs9Wuo+n34B1KFRqzgv73tSGbkmPBXrKWuNCvqlczwJvdpSQU g919c7t4MdJ90FCJpcIIr0kUgStwZNWZegYR7eD6Aaa7nhjG86O2yaG+qmVAmcHOCYrX MbMdZjEZFnBgvjdVL2jlyxpNbdT/zojhO7f98L5tZLPUkwktRHJo+ecPb+Mp9Vmn3FH3 pLqn2Z+Z8gkoW/NLmJ89cjaQ5CmB8sTZgjck8QKGEuV0Hr+HvMqIe4B8zAe2Z+oJ85ej V/XoqfeA8jwxPR4JUf8XMkNC2MIZIJp2S4XNLXHhk/iCYLQypAT6+yEJBLOyx2129Xe2 A9tg== X-Gm-Message-State: AJaThX5FPfG1CzZt/onqgsxMV/nib5E35ll/JgIzWJ3s/qhJBHV6yEzH AceNsD6eWHkw2v9deA/2zpQ= X-Google-Smtp-Source: ABhQp+TEusNEb9ig/9l8n8YN86Bd3dj4O7TdqNSp+K6FiCmM3I86ZvhrqExeuyih80N34tP4AsD79Q== X-Received: by 10.99.122.28 with SMTP id v28mr1246330pgc.394.1510122034625; Tue, 07 Nov 2017 22:20:34 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:33 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 15/31] nds32: System calls handling Date: Wed, 8 Nov 2017 13:55:03 +0800 Message-Id: <61b5cd5e7f2cf2f485a990cdf238788b817a1d53.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 +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, ®s->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(®s->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 . + */ + +#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 + +#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 . + */ + +#define __ARCH_WANT_SYS_LLSEEK +#define __ARCH_WANT_SYS_CLONE +#define __ARCH_WANT_SYS_OLD_MMAP + +#include 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 . + */ + +#define __ARCH_WANT_RENAMEAT +#define __ARCH_WANT_SYSCALL_OFF_T + +/* Use the standard ABI for syscalls */ +#include + +/* 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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * $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 . + */ + +#include + +#include +#include +#include + +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 . + */ + +#include +#include +#include +#include + +#undef __SYSCALL +#define __SYSCALL(nr, call) [nr] = (call), + +void *sys_call_table[__NR_syscalls] __aligned(8192) = { + [0 ... __NR_syscalls - 1] = sys_ni_syscall, +#include +}; From patchwork Wed Nov 8 05:55:04 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835647 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="YFvEepeR"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWxBH5J98z9sNw for ; Wed, 8 Nov 2017 17:25:43 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754936AbdKHGZi (ORCPT ); Wed, 8 Nov 2017 01:25:38 -0500 Received: from mail-pf0-f196.google.com ([209.85.192.196]:53726 "EHLO mail-pf0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754045AbdKHGUi (ORCPT ); Wed, 8 Nov 2017 01:20:38 -0500 Received: by mail-pf0-f196.google.com with SMTP id b6so861473pff.10; Tue, 07 Nov 2017 22:20:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=iqLN2Z6x97ggK0O3/yIF92aqgNm70DHEwAPpIhFA3Jo=; b=YFvEepeRsntkGLd8tl1TMd/fP0/2c7yQj0Au63hE5iTaBcthITHnt06uyehjQ0yVIF tF4ID1TfmN9Ld0JLzyCC3b5kEJVYHg25zErmLLLl4cLmBh/s026eDxrFEcgmsoJLAOKO jiZWveArBRGP32sCHtpyVx2FkYGTxnmjAGcrc7x/zeixmCqeSJeQuLm4KOOUSOuPXqKQ qv6RhPJtGVa8hn6xwHYc821rjANdjyovzJH/w1J1UZwua34mdw9LHo4aeqsmWu17IYFz dmfFrC9u/ybRdG78BKQVgTY4srSTIWVKz+OiP0GqJ7j7Fi5D4T3opvUoIJpnBzjiJK1t PLhw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=iqLN2Z6x97ggK0O3/yIF92aqgNm70DHEwAPpIhFA3Jo=; b=NobIQWLh4ts+AurqMg45W1rLSwAlHt7qnE40Gn2KbJ0hrc0+hHcs74r7HyIKJCTxTK 3DM9iGIlVnSaTd+S2/bVD+JTDPFcO5oYrGqbcG78HtlZT61HrEpp7MH6+sBBZU4uMMuO jpw/KEX5l26khvUZTZLkFOHFhsqXOtsPaB+oA0XpCRyjSgr+KfD6nLnaPxDI4qpuA8fF HW6DRFBvjsRIlbH14PU12/hhuVAqFNutJB/MEM0ex2EGLlKB+iY3Fs29i5gwEoCvWIbn PPA79ilYdAPCNkTsnxwxzsR52GQISkPxaVOsFVzlpmcbQFQBIpjG5ADV3OS6694YHGdI ZdmQ== X-Gm-Message-State: AJaThX4nqAm2IC0/sRKxwsszlxTGRBeiqTSzv/JfH/AsGYVfxyyGcX+d a5Tnj3PEud+NpN1m/MV95Y0= X-Google-Smtp-Source: ABhQp+T+96CRYEfZGvax95sfLmB8Qbal4UGNlVNojPujzFuonU89UR1ftk01/KlU2wIXj40lC5JtZA== X-Received: by 10.99.96.71 with SMTP id u68mr1235548pgb.389.1510122037111; Tue, 07 Nov 2017 22:20:37 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:36 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 16/31] nds32: VDSO support Date: Wed, 8 Nov 2017 13:55:04 +0800 Message-Id: <0911917e908c7648d25b33663afc88f5aca6bb4d.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#ifndef __ASM_VDSO_H +#define __ASM_VDSO_H + +#ifdef __KERNEL__ + +#ifndef __ASSEMBLY__ + +#include + +#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 . + */ +#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 . + * + * Author: Will Deacon + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +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 +# 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 . + */ + +#include +#include + +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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 . + * + * Author: Will Deacon + * + * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text. + * Here we can supply some information useful to userland. + */ + +#include +#include +#include + +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 . + * + * Author: Will Deacon + */ + +#include +#include + + .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 . + * + * Author: Will Deacon + */ + +#include +#include +#include +#include + + .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 . + */ + + +#include +#include +#include + +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; From patchwork Wed Nov 8 05:55:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835649 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="t3+MJMmp"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWxBr5L0gz9s8J for ; Wed, 8 Nov 2017 17:26:12 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754642AbdKHGZg (ORCPT ); Wed, 8 Nov 2017 01:25:36 -0500 Received: from mail-pg0-f65.google.com ([74.125.83.65]:45396 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754120AbdKHGUl (ORCPT ); Wed, 8 Nov 2017 01:20:41 -0500 Received: by mail-pg0-f65.google.com with SMTP id b192so1178671pga.2; Tue, 07 Nov 2017 22:20:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=wUmmZD65saqriA9pwHUFkkeqt1zuczs5NukJsBkUzVE=; b=t3+MJMmpU9g/drmAvVnpaI3NKLu0b+Cyk/CTlLu854+XeO7FXvc8PQVgH5gafFrxGe LAgzGRIpUR1J/lMZt0TY7sUeBFBkunxIBG5Whm6bp9FJgrYTkTv7ePTDmL/vfLOaIIER gDTZZFoOFk0hd8mBbwKrXjk1DIn+krWtSOH4Z41gTCjoVazZPz5svbKMybM2yrKWq3Fh Wmctl6Gmu4wteXUCfA7iHzFyrqle2V58e6W6pKzHse+vtJeFc3rtzMZ/7YrnIInzKK55 aRWXxKKHNztpbu5zVMzGI4AvWbnUDTT1DRqrBc9IuZT0UiKc2q51GSdtm0JJT5Kri1PY JZZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=wUmmZD65saqriA9pwHUFkkeqt1zuczs5NukJsBkUzVE=; b=sviyWCW9AK2sq3YOThGZczdDz6d9ti8AA3ZrGc5bLdfAa1CK5sb0zydE1FIckUSWRW qEv8ycN1qF9oOgB64R26R7+S760l2S7ns7nOaxQT6pW0UN9g194eBBD/VQvKfRWF0JQ9 aT0VFUQDf975pi4YJMg8npchf+kELzKCR5oZbllVw0FW3X17sUpD0Br+Cx2O49dE06He tSTOjMGnIvgPfvpfY5htoh1ZlViaz6gq3p/k3wiMmrqaFc/5p1PJOR7iDRAd8zOyjFmS tlRVG81Zvp7NojNP5Ci3bPGThihjAmMobRB0xhifT8PhuZv5UWaCLn+b1UeL7l+9BY/m 5Nlg== X-Gm-Message-State: AJaThX7rsXbk4sem1O1ZJQQv4TCxlCd1Y59LZXA98kR+NR9jcE1h0vfs WFdDAgOHPmBfXGCVrhjkqfs= X-Google-Smtp-Source: ABhQp+QygZu7b5bQEfrDOArRkVsKij0GhE/v9503qXwdYLv4Sy2ixRAGNMtEKIzETsSFLjeOXx/R5g== X-Received: by 10.99.54.202 with SMTP id d193mr1253033pga.343.1510122039625; Tue, 07 Nov 2017 22:20:39 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:39 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 17/31] nds32: Signal handling support Date: Wed, 8 Nov 2017 13:55:05 +0800 Message-Id: <82ac0fc50f8fcdaf423b6ef1a66ee4d1d88d366b.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#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 . + */ + +#ifndef _ASMNDS32_SIGNAL_H +#define _ASMNDS32_SIGNAL_H + +#define SA_RESTORER 0x04000000 + +#include +#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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +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 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; +} From patchwork Wed Nov 8 05:55:06 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835641 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="QMxPmayg"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWx8j1qjsz9sNr for ; Wed, 8 Nov 2017 17:24:21 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754234AbdKHGU4 (ORCPT ); Wed, 8 Nov 2017 01:20:56 -0500 Received: from mail-pg0-f68.google.com ([74.125.83.68]:44286 "EHLO mail-pg0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754128AbdKHGUn (ORCPT ); Wed, 8 Nov 2017 01:20:43 -0500 Received: by mail-pg0-f68.google.com with SMTP id j3so1185515pga.1; Tue, 07 Nov 2017 22:20:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=ykRQBvo/uMdr4a6wlJQROWQqxzIJ6ODmlmIWTVfMoM8=; b=QMxPmayg2Tn/KoAqsE9+sJZLyRflEYyfl4je9iEoVY/oDOMd25/bRa/PsC3yZxYrwP U+MmU9D/Zu/jQIZoYHBBupM4cRGuSyabyMgs8vhx9DpZFz5zMJIr1z7S8ei8Lec/gVfa zPr5JTFmcx+ZaZyMppgTdoC4B8em2XWYXjmc0DY3MRyU/d8Peh5V4y4LySIMV1kBJzaY cCrQtcW35U/oEpM83LObEpu/Hy0C5sllU46/Vjxx+OspQvuaaU1S8DKbMjFB9ss4sRhS WGyhwEosiHBLwJtRfllzPzxKahfNc8u6aMyE50lmpKNkOj/Bw7huSUnLWWxCjdRnfFih S+9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=ykRQBvo/uMdr4a6wlJQROWQqxzIJ6ODmlmIWTVfMoM8=; b=kisa0LfuEXDW334UmL3PlVD4ihTdFor0y3BoWujXF4qnB9bV6SfWVCpIKeHDnHf68g vjkmlrjLadL9YUOQEEzUnT9HRtn6qOjSPpG9c2PCr9CNT2k10rOa0qCl/UmwMOGjhEZ9 B1TmCANjLTLO6VFgOlvcvCwyf7YmFgkkUBY2NBy9h08uSdeiqD8SXdvMCEb3ngwWwkJ7 MgcWKcd4hBeNXOqR8FeT958JJcZqfaoZIuEt5Cqfnt/bGnoyUe5847jiXUssiAonvs8G tSVtIxwOs1dNHv5RzWB06FLFGOvaxvr3ivfsm2Z8NQawszTG2SHVPEgfWk7JfgH7Hkv1 di+g== X-Gm-Message-State: AJaThX5+RTWgFBUVylTqwdik+y7EXp+4+xUNQgq1BoF5FzD+9fpkpBpm TL9qf/zIyAFWc7rcY2acPqg= X-Google-Smtp-Source: ABhQp+Q1T/qoZadToJ8u4CbKq2rxO84Z0XbXv0g4Sw560sqr2H7AjRlgIlSyVTmpRG/VkJvnWUg9bQ== X-Received: by 10.99.4.209 with SMTP id 200mr1308839pge.123.1510122042143; Tue, 07 Nov 2017 22:20:42 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:41 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 18/31] nds32: Library functions Date: Wed, 8 Nov 2017 13:55:06 +0800 Message-Id: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#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 . + */ + +#ifndef __NDS32_SWAB_H__ +#define __NDS32_SWAB_H__ + +#include +#include + +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 . + */ + +#ifndef _ASMANDES_UACCESS_H +#define _ASMANDES_UACCESS_H + +/* + * User space memory access functions + */ +#include +#include +#include +#include +#include + +#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 . + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* 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 . + */ + +#include +#include +#include +#include + + +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 . + */ + +#include + + .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 . + */ + +#include + +/* + 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 . + */ + +#include + + .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 . + */ + +#include + + .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 . + */ + +#include +#include + + .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 . + */ + +#include +#include +#include + + .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) From patchwork Wed Nov 8 05:55:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835645 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="mF73fUNQ"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWx9l6jYlz9sPk for ; Wed, 8 Nov 2017 17:25:15 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754186AbdKHGUx (ORCPT ); Wed, 8 Nov 2017 01:20:53 -0500 Received: from mail-pl0-f65.google.com ([209.85.160.65]:52952 "EHLO mail-pl0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754094AbdKHGUp (ORCPT ); Wed, 8 Nov 2017 01:20:45 -0500 Received: by mail-pl0-f65.google.com with SMTP id z41so667840plh.9; Tue, 07 Nov 2017 22:20:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=ZauUSMvnPFKSkuOVirB9/uxbyJUj/3JryIWOwU3hc1s=; b=mF73fUNQ+3eeC+l+Ut80yrh0XPrFDOrUCrbGK3xehf4mAj79I/y1BuFTLCrYwdrv2i aDjX8/enroII593OOZt/6ka04nEzw1udwFAqFIlLx3RIPdz5+6vxjI+UxJRKkfyzivJv LlKffSYy2AunRkOpWzPNgvKB+kQTHiztwFCgnyB1u0FbORE8gYVLvvFdpHlIFooxiA1/ Se5I46brdwv05/MAAgonOw1R2lqWB8wNtrc2EDdFqKu57RPPLsPaDN5wZIZ+hTKfyJ/s ZBGuHe2cQEBbS1xwW3QAnKF+bdBjqAZhnlpjcJse/Qimsl3Q0aLXUldoKko3zKTmCwIQ qF+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=ZauUSMvnPFKSkuOVirB9/uxbyJUj/3JryIWOwU3hc1s=; b=WZixRm3XolkfBqo7ypwTrQEkTjBwJfzqKmY2Io2dfXn0OcUkylCz/tAUt2Llmq048/ VYLUKQ3etC8U329likQo6E2neYluzbBYl5FMwMvabMlGIMjoYgacwc4cPURy2ERgU36G VeP4c30dH3FvFpULOTL/ZaBO5Nl05I6RPhAtTYuWXK4LPGyj2nwt40+bbG3IA32/sAGm Z+Q2D8Ia4d+DW3v5+zXE1DRGFyFQo2pKCWkeRUWjTJnDD+IUWMhxicFv/t3BlltUO/74 INgCKMwYHHnZUcRLyqE0ILFfKPAR3i/Xd+P1NMgQ3WXVegIAnuKxJ5KEHKF/ObvR9g98 /7Gw== X-Gm-Message-State: AJaThX4jih3T3eK2YIaXkhpj3PcyPINWJ4stq5WWllaXMQxGUb+D86Fn VjWmtqXwWsb84pGeAC8qau4= X-Google-Smtp-Source: ABhQp+RzM29GxfvW4XRAdJSxOfz8c118er8izqmngenzzCLN29qrAEk1woYfZreIGNtG4XNsE+esWA== X-Received: by 10.159.234.10 with SMTP id be10mr1260203plb.386.1510122044667; Tue, 07 Nov 2017 22:20:44 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:44 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 19/31] nds32: Debugging support Date: Wed, 8 Nov 2017 13:55:07 +0800 Message-Id: <0d98a5eb51422ca3cd7854835fec46d58dd41b76.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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); + +} From patchwork Wed Nov 8 05:55:08 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835637 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="kpFsB3/a"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWx7s2BhWz9s5L for ; Wed, 8 Nov 2017 17:23:37 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754309AbdKHGU7 (ORCPT ); Wed, 8 Nov 2017 01:20:59 -0500 Received: from mail-pl0-f67.google.com ([209.85.160.67]:48211 "EHLO mail-pl0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754160AbdKHGUr (ORCPT ); Wed, 8 Nov 2017 01:20:47 -0500 Received: by mail-pl0-f67.google.com with SMTP id m2so666728plk.5; Tue, 07 Nov 2017 22:20:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=T6HP/g6MDbiJgen2Cmvu+IQOPqq+wHocbUB0QeCGvBY=; b=kpFsB3/aCnC3IniJ2XKyy6WhTMpXYdQHx1SyBGsop/PjIKdZaRlCVovFbT9vkgMdrb 3dWGVG92zVRP4utzUs5DH7JAuHMiwJ85BqghulOdesdj+vvT34yupPTzIYKJzLb/G3wE uIBOLLcV5w0L4wMNfYxey7WToRfo0fdcotQq6wYjA7hB0ev0uTv206RtirHAvir/FWQt qGvVQbbh/Y1dUff4v9D1nRClRShSKknCtTxdQsjKIrttJ5oWglo8CTu2Fy381UUDL2nI Cfu5ELvvK4DxZo6fZPwfqmwMSyFGgQN0LpgXasaGCfslIzVz6ue/Qw6htyyjaDxPoKN3 w+tA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=T6HP/g6MDbiJgen2Cmvu+IQOPqq+wHocbUB0QeCGvBY=; b=liSxJERQgW2fpsWos5HmSwdpxmE9Hw/hC0Zpdzk9PQHLjemv4MIJfuhmX4yqV7Qqad cACu1zMqJpL9D1O9Yzx6H98WiqaHMPAyaoFS3oVB50YKcW3szcu73oxUd/QJYTaZXsgj +GvBRLDFi9ZTGlE+q6ps73fjsn3b5uH6teOPAmNvSkYF0Z/PqQP6n4WZn/h2tRujrLmy 7oBBAMOMLQBSTG6D2o71u06bKufdfsC8mCQYypJaB+ouZ0p9nq57SKqeNhrQI6Ua4Jvl Aqn4YcuJgcKBzshgI8D0vCqXfaOm235gfa9dtZLMdlt+BYpBCw3ftOsjwvRkhhpZUsVk DBmQ== X-Gm-Message-State: AJaThX6IxD5Smfjwbc0SpGMgnAqlI2Z2caC8geNtLpHHWrU+Hr31BS8Y QzSN5JwBJDXSuJSbwnkfcuGePw4d X-Google-Smtp-Source: ABhQp+Tbd8Au840b+t+w3qGCYfsupTYFSyk7wepRkeEKUOplCkqjGHqwi4bRFsdYjrtZQoDlPgDYPg== X-Received: by 10.84.241.15 with SMTP id a15mr1248459pll.388.1510122047150; Tue, 07 Nov 2017 22:20:47 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:46 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 20/31] nds32: L2 cache support Date: Wed, 8 Nov 2017 13:55:08 +0800 Message-Id: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#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 +#include +#include + +#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 . + */ + +#include +#include +#include +#include +#include + +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); From patchwork Wed Nov 8 05:55:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835638 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="DlJG/8H6"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWx7z01jCz9s5L for ; Wed, 8 Nov 2017 17:23:43 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754282AbdKHGU6 (ORCPT ); Wed, 8 Nov 2017 01:20:58 -0500 Received: from mail-pg0-f66.google.com ([74.125.83.66]:51051 "EHLO mail-pg0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754161AbdKHGUv (ORCPT ); Wed, 8 Nov 2017 01:20:51 -0500 Received: by mail-pg0-f66.google.com with SMTP id y5so1169281pgq.7; Tue, 07 Nov 2017 22:20:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=DRyk03tl4GF97tNZJQoOe8PCfToiNCa56vUW+8U9TIo=; b=DlJG/8H60qWxh05np+TiMhS4IF/POthya6y7B6CaWlpTfvxTgJvuYBtEaybDGIsMmf 3VOY1Lh6PDlNB1ELUtpBEJmhxjFIPR5VrDDGWKGMypqplJG6QHu1qlP86bTtVU6sEBPH o9npw1V0qHWlsjjkAtWqYPJCjWTJ3e423DLh/sZ32t0NuklwfHrkbgurRGARxivV/M5f P/XEmspuk0ApEWuHe39ToOjLvPvLS6P1xdBxl8pxq6SNYjSS+5o4eGWFopZDSrDNlAT1 zvdg2eunAVp/TjKOfhsvgMCWU90uyxFB6gHUOA8HS2d3Yct77luZx5aqpVjf30dbj/ia EZjg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=DRyk03tl4GF97tNZJQoOe8PCfToiNCa56vUW+8U9TIo=; b=Tr9ducF48g367fdz6gHC86C4Ika12ky9DN/RIymxqYhdEaRZy0d3Tzt36i75v7CWyr D1JvobKVjAlMViF3IEq0OOcFDpDEHU+FTQh1HBcOsD6xPKl567vUEBrEQL9pQ1FAxOjL EyBoEURZbsveCqB/7X/xEguofNJ0W+eumU3ZNzXJhMmNIIFgqSA8R63K+gpaNnyIeriA /XA4OPbpzWnR4p6YAkho/uAXL4yxJqJmUTQJpd2BjlHIOaVqPLsw6LPz640x6pwdepQi A4yQEnpr0ornmaIiBuTPCZZbVr2X0KRYrbLDKxK+HNvsqYbFPu847wEb0xGzN+JlnTj6 vhRQ== X-Gm-Message-State: AJaThX6bZWkN89vV90JmNI4DrgZpTrOAzuP/fUgUtaYMUqMQIqWO9Mfs OD9jyOCxGgnZZ/52Zp2al6o= X-Google-Smtp-Source: ABhQp+Q1pW4e9Ph3t9B/KBocEy9zYBDIEf9VkHd4mSntpw075nBzB4JZ3TQ4ttbur9eCwU+VwA2QmA== X-Received: by 10.99.160.100 with SMTP id u36mr1311001pgn.22.1510122049627; Tue, 07 Nov 2017 22:20:49 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.47 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:49 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 21/31] nds32: Loadable modules Date: Wed, 8 Nov 2017 13:55:09 +0800 Message-Id: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#ifndef _ASM_NDS32_MODULE_H +#define _ASM_NDS32_MODULE_H + +#include + +#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 . + */ + +#include +#include +#include + +#include + +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) +{ +} From patchwork Wed Nov 8 05:55:10 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835644 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="pVwtW9XJ"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWx9M38jHz9sNw for ; Wed, 8 Nov 2017 17:24:55 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754913AbdKHGYy (ORCPT ); Wed, 8 Nov 2017 01:24:54 -0500 Received: from mail-pg0-f68.google.com ([74.125.83.68]:56457 "EHLO mail-pg0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754178AbdKHGUx (ORCPT ); Wed, 8 Nov 2017 01:20:53 -0500 Received: by mail-pg0-f68.google.com with SMTP id m18so1154573pgd.13; Tue, 07 Nov 2017 22:20:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=ZgVoCLpbLPQSXK54H/Nr6QHPPXtr20YqXR9i09xS+Us=; b=pVwtW9XJhFTUufr7XKdKsZZhgRAbuOLs6cwIxlLbqnVxTKIGqbpPez9H0CeONg7w7i fufzvpcy4B+WYYEXLTHHXuqhlZMRkl/h1w5ZoVR+9KxZWlo/cEykVZp99gHHpQiVd7Hk PjKzd9R0zGEFmfCZ675PCXA0fuAnlQgS5PTKRCGey8htPNzi+HCmaYqSz+DX8Igpfs86 V1ZtkQ6gqm9ZJYG2xCxt/PN2SxiVKUaB8YHfrcxcNmc1q0kPj9oP9Gy8Igz8SNZyeRDd hbcmvvrRgE+YEJfhCXSOdUNqZExpzkbRmVSpTfGJMK2P5FLOempM6Vul3ALDDVwsqzEi cKJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=ZgVoCLpbLPQSXK54H/Nr6QHPPXtr20YqXR9i09xS+Us=; b=gvTq7XM/NqYUje1B/wxa5NRnrlcYZNq9TRI8YDDINvM2lUwcYFukn5ROHfIvqGFuHN 5fQvzgQNY5V1lHrScSvMXt/CEXI4N0ZlPEBR6dL1f6E2CCm2Xs0Hs484vGDZizDPdSjJ ejr88mqDlkG5kcwUKFAEqVpwpIQ5ltMFqH/wtY7sMmWrBmMmUG3DV1Hew1U4MR0i6AUH /0zlEWalmAfbbdsHYewFNJdfpOLwIJCR8ULw2e/gFMGBBmvzV+P3ALUJXxTczPbkqU/o lEHYa09g6vPFq7wZIugfdzppAskk3K8KebB/FuWUV7LFl0bp2OhDrMyXUKlYo/0TA27Z zR2w== X-Gm-Message-State: AJaThX7/4bO1csYnveVDjqbip95Rp0oL+gHUTSmua90fdTIqHiZ9rm7h gSCKyB4vk3YPH0h+pflxglY= X-Google-Smtp-Source: ABhQp+TPgL/0jA+Zx2w0wmaDpENoxYwk+ER4SIi1yiwjVKvoRv+Ouzyallr0REryDbrZILynPVtY1w== X-Received: by 10.99.104.6 with SMTP id d6mr1266710pgc.319.1510122052361; Tue, 07 Nov 2017 22:20:52 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:51 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 22/31] nds32: Generic timers support Date: Wed, 8 Nov 2017 13:55:10 +0800 Message-Id: <33e12422e3ac76495fd9b24b81a2f00ea50d336a.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#include + +void __init time_init(void) +{ + timer_probe(); +} From patchwork Wed Nov 8 05:55:11 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835642 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="t5EWIEC4"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWx952Q46z9sNr for ; Wed, 8 Nov 2017 17:24:41 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754898AbdKHGY1 (ORCPT ); Wed, 8 Nov 2017 01:24:27 -0500 Received: from mail-pl0-f66.google.com ([209.85.160.66]:49461 "EHLO mail-pl0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754213AbdKHGUz (ORCPT ); Wed, 8 Nov 2017 01:20:55 -0500 Received: by mail-pl0-f66.google.com with SMTP id f2so666664plj.6; Tue, 07 Nov 2017 22:20:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=Vj8h6axVq03dz52m2yXMRE7RcD/UZbpYo5W/WoTSRnY=; b=t5EWIEC4eYSazocqqzhyv+BQGDll8bMDIGCk5HXQmoyDs3z5iaDLxEm7HdFsMMpECi 4zZw6Z9v0FSFMVUmBOpAEbR3XH63PpDlPFPuifMO+q+oHL4H62jeULQRMVgO0RitSKal A3j0zrPPEHsvljBHx9cPOWnhuA6lGhv/jzroteiT8j92cX8zO3E0HVEwwQpIA8orKsJj pHbmdf9CbVhaC4uTzUilZq6hxP7Y1fryY/sBvdIZTBvB56KqdGPMcFPz+A1FeVS+gIun TC67hsgqRIngkXmizurF4drQgOzTXSeoc8s4Fm3A2VUzm8FN8yDBB1Y+C/CpfKgnrD4d y0iw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=Vj8h6axVq03dz52m2yXMRE7RcD/UZbpYo5W/WoTSRnY=; b=gEtvJ0eWZRM0nlcO5X9A1HcnXznx925hZNyxVPUScB8M+4zuknvL/cmTFYlYZgX6wc Hiw0V7AdIQU6Igfm/y50lG5H1I+7lG5+lltQ+CvKvfUaWwp5Xq7RdU2P94Xudbd2Adgu AUtk/+vnqsV4HOdkHuOFWMbHzAzvS7lSd109cZig0ch7xrPewHBH0Jatm8iJkpw6S9EK prues2DJxlMLQOvoSXququMXvOcqEKcf4hUI6FppJFOJ9XKqkpFRBpA86nTyy5JjlaaH o7TFQtw0mgk73ql10v+vxITxCH3emyjK8LuHn71O5U9BGg8NZMqVTIdPabMWDbNKak6H HlJw== X-Gm-Message-State: AJaThX72jYjuaAfoqONSorpXGQdYbMtV0bz4MmuLjcUee/TAtrkj2xKG Cu0sPM0T9z2kC7xsXmkiXwc= X-Google-Smtp-Source: ABhQp+SFrsWB50x22kLjKtHvbrmu6+LyH9SPeN08B+XH01xsfkFKyq5IGeSB2Pxx/6i+Twyom+44HQ== X-Received: by 10.159.206.193 with SMTP id x1mr1251162plo.319.1510122054868; Tue, 07 Nov 2017 22:20:54 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:54 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 23/31] nds32: Device tree support Date: Wed, 8 Nov 2017 13:55:11 +0800 Message-Id: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#include +#include +#include + +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()); +} From patchwork Wed Nov 8 05:55:12 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835639 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="abKbxORT"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWx8D4TVHz9sNr for ; Wed, 8 Nov 2017 17:23:56 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754832AbdKHGXm (ORCPT ); Wed, 8 Nov 2017 01:23:42 -0500 Received: from mail-pl0-f67.google.com ([209.85.160.67]:45532 "EHLO mail-pl0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754270AbdKHGU6 (ORCPT ); Wed, 8 Nov 2017 01:20:58 -0500 Received: by mail-pl0-f67.google.com with SMTP id 30so668133pla.2; Tue, 07 Nov 2017 22:20:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=a1FgkYlYxlGT1kWhGiXILNIHorP52G4t4nYrihEtBiQ=; b=abKbxORTGATyUqEnpyB9mo+LGAabmY4RXefNkN18EGGA2nYAA0xZNfragz3aRMWd/k pnuzN+MUIsC3s/xRdBbz7lNf6eNu+8jF34Fvg2gDZR+uBZshSRQQhyFAxam8wQho4sPW vSSRsgCistL+oy5Vaq1U0HGLzbeYRkIoWMLvlN2NVkqp2EdYB6RLFx5YI+uiZ8m2HTud 8Qb8PDAHEM7Y+NkLuFH8znvSOtVrULSbSHOdu/wthXSDBbF4i49crfP7E9SE7Edj6MuX fEjGyR3Gvw1+7Uu9FcvE43V9VkUWrExkw+vGszLMiI44T5ZKe+LDhUIHv/sgTDKn5cKY gt2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=a1FgkYlYxlGT1kWhGiXILNIHorP52G4t4nYrihEtBiQ=; b=l9a0oNGyeocQ7o3eXruNEby5R0SX7EcjTVnO+jKrwNOtZuWomiSEEoFBlQiGl7e6rB ROylK06Zi+9lAs22eaSp8JGucLZ4h4uc50/zdvh4DmLGj9ePoxTeDCYulTnRujeQB3Gh x/SKqwXTo5nkmmwB6xYkW7Y1HVa76npPMl6dYFA0ePHDgoVzwKlgWhwOmuBLVP5hJQyU rj6e5W6sKkg6ChIyYpH7IDOicc4KPXGm6HM5lxB4t4QYClekHgPca7pUzDwgXhXt014S W8072eOloX0/1ehmcmkZ6kFiLh1xA+2WDSP/0/MWJYDX4dtQlY7+hP20X6F2hf6fgsFo ol4w== X-Gm-Message-State: AJaThX41LWkjogGe4uUKPGdbm0n1RNyRuJyKqjLiVdY3CdNaih7cPA1q 9btG24a9dzD9HZI133Ux9WWFG9sw X-Google-Smtp-Source: ABhQp+TtciiQcIiL62o9zr6N9mRXOJTSlz2R1Bt8wDQOAgRNdDmr3G9B7dP2WtRxuLEFzC/Ijnx8ew== X-Received: by 10.84.168.129 with SMTP id f1mr1233383plb.71.1510122057344; Tue, 07 Nov 2017 22:20:57 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:56 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 24/31] nds32: Miscellaneous header files Date: Wed, 8 Nov 2017 13:55:12 +0800 Message-Id: <6f3f5675b73bc7fe895c615b0d48f93966499782.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#ifndef __NDS32_DELAY_H__ +#define __NDS32_DELAY_H__ + +#include + +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 . + */ + +#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 . + */ + +#ifndef __NDS32_BYTEORDER_H__ +#define __NDS32_BYTEORDER_H__ + +#ifdef __NDS32_EB__ +#include +#else +#include +#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 . + */ + +#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 + +#endif From patchwork Wed Nov 8 05:55:13 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835635 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="jeqJBkz2"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWx7L20R6z9sNw for ; Wed, 8 Nov 2017 17:23:10 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754760AbdKHGXI (ORCPT ); Wed, 8 Nov 2017 01:23:08 -0500 Received: from mail-pl0-f66.google.com ([209.85.160.66]:43449 "EHLO mail-pl0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754161AbdKHGVA (ORCPT ); Wed, 8 Nov 2017 01:21:00 -0500 Received: by mail-pl0-f66.google.com with SMTP id t7so668734plm.0; Tue, 07 Nov 2017 22:21:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=Kip0r+6XrYU3cbzbTb2iRnazzjHuVC4PTfJ9L6h1fyE=; b=jeqJBkz2CxOTIU9hLqqSOAM3p14F5IMXH7eb1ZxYFDWoHVTYRMFhUPUgtZZLVdXFXn CrXvj94XOPJPR6oN80V2QqrIuVAz7QzAdLFHB1RPQJsJg4TviWf8DqJF3fg34pV8USGQ 4+RwG1+ROOm/u8xBI4IiOAbe6CAXWLzKpA+AmGs1TaoFrq3Y8vVhl85GnreGf+9uiLZj H2/2wIdYiqd+igaqmO3sowz62UUx18GJyrDjUxTcXGGCmwnvAvIu0N/X3XIUxb0n2jVy JITxgaoMbJaBcp0tsjO1nkmChff7if2BNdpot+cJBt1P2bTa37ak99nHOygVcoOVBjj+ OfyQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=Kip0r+6XrYU3cbzbTb2iRnazzjHuVC4PTfJ9L6h1fyE=; b=hfbAuQIX69EC66e5EgVwc8PiSmMI1eCEuYSC7WS+wJO6BjuHbOPIIcKMeIozpPcRWi QTcLUc7NYsuD6+8/qVKmxm8i4WOH6seXbg+/8V2lsWT+x470bdQCtmZ5e0oX/ioxBSO4 s1hU40tjACiNNcnLh3o6MUqhYt24gFvim7xRnBkCHFgEi+rUhz39tUWCD2JCbh+0ivb2 dzpNcFB3giK6XzJKBdpEBdU7fjTWs1pXNE9u9MfdbL/GySgk9gEavzOYvZPESyjQY1sh KRFxq3sLzp+ycHE2BuqafsZmcnRqbY3u5iVn4rUwWnxBQD3/IBFv3YYQNs3DykgOIw8D OJYA== X-Gm-Message-State: AJaThX4T3Sl3jAAs+KByFGPF8WWth69HS7CgHV3eV1t60v+j11qubF2u /I9BAojIHfbmpa3KHJRoMp8= X-Google-Smtp-Source: ABhQp+SnXPBaUKyqsfyiI5f/aJ3SrfTyrXGjPrHljr14MudJE9DZ8N+o8JvMpwAe2lZGGyEZZWu9Mw== X-Received: by 10.84.246.197 with SMTP id j5mr1228579plt.7.1510122059800; Tue, 07 Nov 2017 22:20:59 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:20:59 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 25/31] nds32: defconfig Date: Wed, 8 Nov 2017 13:55:13 +0800 Message-Id: <805f8432979e2707fbc9bf62dc52b8abfbd2cb14.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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 From patchwork Wed Nov 8 05:55:14 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835627 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="ENYIwHXh"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWx552qGhz9s0Z for ; Wed, 8 Nov 2017 17:21:13 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754493AbdKHGVL (ORCPT ); Wed, 8 Nov 2017 01:21:11 -0500 Received: from mail-pl0-f68.google.com ([209.85.160.68]:47224 "EHLO mail-pl0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754401AbdKHGVD (ORCPT ); Wed, 8 Nov 2017 01:21:03 -0500 Received: by mail-pl0-f68.google.com with SMTP id 14so668058plf.4; Tue, 07 Nov 2017 22:21:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=vIL3fhNk3EIK6AH7oZ5fscML6lINXo1cSkUCas6d3Oc=; b=ENYIwHXheZ5HqNm7FDUMEpjbdS6OoSqF9pQIc1P+Piay2ZGLQf629AEFfygY6OPwb0 JXVIEZE+nkwjsqga43QEXerrQalJSSMRrTmgNky6QPM2sWHENk31OiIG36WLnQZNSOfq vfTBF7OfHQ83O5qJoYuP5npbf8uP7ESFEZKJ/koLuDq1zC1+PJatEBOQ742QNbLvsB1U +j06vKUJvuTgpLsNO4TQkV9kB9CdHcRJz/+PQR6rA3xEDUbvjleh8dt6tnz4UKfXQy3R 9V+JfRLtR075jcl2CCvZhD2I8jiTCXk6jbMfrwG+uLEHhbkEy7tTxaq9ndVO4RvdEiH0 ucVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=vIL3fhNk3EIK6AH7oZ5fscML6lINXo1cSkUCas6d3Oc=; b=acT4MX61HjmL/rKROYyANNfScDDCR+NthIdkrVB4pSGw1gcUMbHF/rlHtV8wlub30F GbhKzDsxg7pCHeZnxsYsuyPLf7fB6kJfe48IUr2JnjppQ3FHOEvoFtgdq0c+no2BRuWf VgOHiuxHbYzDbVxZ1sV8kcri31UGDZ88LqjjO298cGVGgHVBZb27dlgNYc9kCfPMQWVh U9WDB4rqPS1MrC6egAEKvNg9ypD/p7wnjwzmFULR0qY9+Zx4M2G+314TkW+J/MpkTv3O e0FzXmfHaJQiXKbrQIBrIhsAAJCBfr7rNfnKTm/uhUR8+ApnBK+BHM5w+gwAyiTG/R5W BYuw== X-Gm-Message-State: AJaThX7H9kDQUegx5/HqSJtndFodud3gLQNYqrR12etB/vy2uCgQtHYJ ZsBGNi96Sp/MM2Yq6uWEVOw= X-Google-Smtp-Source: ABhQp+SpXYbXdbUULCStpLHOeol2sW8uOgEPEGpxybyt5ItSRbOJ1fSX8IpfkQ4stgQjrSrDWBYGNQ== X-Received: by 10.159.234.10 with SMTP id be10mr1260904plb.386.1510122062505; Tue, 07 Nov 2017 22:21:02 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.20.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:21:01 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen Subject: [PATCH 26/31] nds32: Build infrastructure Date: Wed, 8 Nov 2017 13:55:14 +0800 Message-Id: <7278eca76456b412e02d9baa5dc164e83199cbab.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Greentime Hu --- 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=[,][,] 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 . + */ + +#include +#include +#include +#include + +#define LOAD_OFFSET (PAGE_OFFSET - PHYS_OFFSET) +#include + +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 From patchwork Wed Nov 8 05:55:15 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835633 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="WCbyICWw"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWx6p0H6lz9s5L for ; Wed, 8 Nov 2017 17:22:42 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754702AbdKHGW2 (ORCPT ); Wed, 8 Nov 2017 01:22:28 -0500 Received: from mail-pl0-f65.google.com ([209.85.160.65]:49536 "EHLO mail-pl0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754403AbdKHGVF (ORCPT ); Wed, 8 Nov 2017 01:21:05 -0500 Received: by mail-pl0-f65.google.com with SMTP id f2so666910plj.6; Tue, 07 Nov 2017 22:21:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=NSrxMQNDw81kBi2X+tVji+A66q5bG3q8R7oyBufFJlQ=; b=WCbyICWwACjPjS5mF4PUzLJOj47MrYpU7fFN2qA3zczzHHaBexzXbccj85aU7Cp+ru KMgdUmZ/yh80gQwGBgkFz1J9cuoi9PGBIzzrXWdQ4BqoMFlQp/o8wukArYGPM+xhV/HN qHZBjZgpd69ad10klzUTdLZIO4GgMMDnnZEMJ6tPzBwOZxn6P+WWJFA8+yBVBNEF3FUl edX2g0BgY6iQ+UxPj7dA75O+icQSm46K5bcdB5ygccfbUFZh4fXVwXJRg0NsEYjj0w36 xEZFER8rGgBw8zqZpsdVMZdLt7EQm32wH3nR0T7Hru7ECz1tslHzN6T5brabZFa5KU0Z 9OAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=NSrxMQNDw81kBi2X+tVji+A66q5bG3q8R7oyBufFJlQ=; b=hVgzZBiajDzFYYwatYlyJrRX0gAEIERBzGX4T+NucGCatvlSR2WWlQONoEp1bQhQRu D0XLcj+CIbC4AlM4smijfCTEMHZpfoV9lrDKWpAUqhgBr/ar1xKIoehUdanBFr19TF2N iBYhIkCPcERKl34QzyTAcY6Rt2Kkp79VhZflqBYFKNNogqsaMN/FvMKlHJwifl45FKPO 5FtokhvBGMGIFhesYU3wk7YIHXpQPTlxj14VsFZtna3w2z4tXhb1Wfz/Hea0NEfP36H7 kUx3552cZmZa2VrhZvit4v8DM1oNhcWOl3LII8ay/B03bZ2cwEZ/XTSiYChoSxBgb68e zM4A== X-Gm-Message-State: AJaThX5R6sMpZ1nHDIDWgtrsoPwDJHXKzP30OBrd7299dWbDOLoPRizD Jovf8jaQP1CjQcF5yMJfu0E= X-Google-Smtp-Source: ABhQp+ScBMgjICBuD5eB7L4b8TIFQ5hz3fHKvEDAxbqrXIkhTNbIMMQ+TrdN7V0Mbu9qXvnnNy3huQ== X-Received: by 10.159.211.4 with SMTP id bc4mr1281430plb.160.1510122065066; Tue, 07 Nov 2017 22:21:05 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.21.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:21:04 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Rick Chen Subject: [PATCH 27/31] dt-bindings: interrupt-controller: Andestech Internal Vector Interrupt Controller Date: Wed, 8 Nov 2017 13:55:15 +0800 Message-Id: X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Rick Chen Signed-off-by: Greentime Hu --- .../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; + }; From patchwork Wed Nov 8 05:55:16 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835634 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="k6Ej0Avm"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWx744qHgz9s5L for ; Wed, 8 Nov 2017 17:22:56 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754666AbdKHGW1 (ORCPT ); Wed, 8 Nov 2017 01:22:27 -0500 Received: from mail-pl0-f65.google.com ([209.85.160.65]:45654 "EHLO mail-pl0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754436AbdKHGVI (ORCPT ); Wed, 8 Nov 2017 01:21:08 -0500 Received: by mail-pl0-f65.google.com with SMTP id 30so668338pla.2; Tue, 07 Nov 2017 22:21:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=h/0V9kO8jsFikj58eDLvhcS/fQjgbLwNZld5K3te5Xk=; b=k6Ej0Avmtq34SGDbBvY0YHVNMWW9KmKba3B6UDPwJNilsbcZnpi3eyJEJUp5ZncBv9 TvXJmiZSiUzw0ZsRU7lbR8deQsFNJ8uKSoxem+5DuTgyozzRTlPQBKROLt1dCPKTfuzD gfjc+iKWGqrbABQrx/+HMq6IvzYAOo5vYMXl6G9DczMv3wdW1n9HCobfrFBxvxnPSHOX hjDLmoJuIs2d5sNu9+pI0mw19dGejr+YKCa+Dgsd3c+QPxROHkLUVTVhM3RHUcbV2Q3+ xT0Lk6nHE2bdbnqUXEgv46DSJ8kqWqQjOAc4KWswcdStXv8zF4Gawznr3xeqI0BmscNe 8Lbg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=h/0V9kO8jsFikj58eDLvhcS/fQjgbLwNZld5K3te5Xk=; b=ktnmQHbkX2C71X1granQLpLwQR/NTBoYk4Kug8stgW5MIqBDa6Bz8FqlOKC3sqGSe0 OwMGcohoYp88Yw+/2JUCaGSqTHYZi1dtkIxtLndCp2IkWpXabzf8Q+u756kUvUsMyFMj Lqufwaw/TFLupWI4k+gIHs7SOSTfuXicamPM9R0CDyQzPemHDpr1Lr8bFQNAesaCotxC lX3IDhd17xDYb0xtMh/XrXwP6TJUl8jOMnkUmfk6BObUVYniwLMjZJdcnbtojAn3kf9I ykBJZuT7km1RvMhTsars5k9iHZVb45HdfXXVnNEV8jot9ezpbTmWzb/x/94o48F/MzSw KkwA== X-Gm-Message-State: AJaThX6xU9x45gXa7dHNlaClexqFEpVUtYqLuYGmqcRG+WY9BprcUrps pPkHG4eLQCvWyhJ4tWKiLAw= X-Google-Smtp-Source: ABhQp+QsS3cgZuMKjr4edRwGkjw6N2umAO2wNIgDQaWgpuwn6C8LvmdvjARG0bKyQZrS/f3Gcx/Vnw== X-Received: by 10.159.244.138 with SMTP id y10mr1217792plr.399.1510122067558; Tue, 07 Nov 2017 22:21:07 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.21.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:21:06 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Rick Chen Subject: [PATCH 28/31] irqchip: Andestech Internal Vector Interrupt Controller driver Date: Wed, 8 Nov 2017 13:55:16 +0800 Message-Id: <4572b290f40d62876b83328331a17c2343710b20.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Rick Chen Signed-off-by: Greentime Hu --- 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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); From patchwork Wed Nov 8 05:55:17 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835631 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="YhoBEFOg"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWx6F6n7hz9s5L for ; Wed, 8 Nov 2017 17:22:13 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754157AbdKHGV7 (ORCPT ); Wed, 8 Nov 2017 01:21:59 -0500 Received: from mail-pf0-f195.google.com ([209.85.192.195]:51609 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754450AbdKHGVK (ORCPT ); Wed, 8 Nov 2017 01:21:10 -0500 Received: by mail-pf0-f195.google.com with SMTP id n14so1108856pfh.8; Tue, 07 Nov 2017 22:21:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=09tvVVgMuPhszC8kvG3DhKzcOPXNCnFY8WJwglUgHD0=; b=YhoBEFOg2m631dc/4RB+pecU7VgkIvq5jzDj8YEjMwHf7wODMXvZXgBRXAAl2vXbP6 73e7atn52V60D8MR5/+yuervf/QKHkXzyYQJ0FplgxJXFld2noftTucNpnkt3I0McNcF 6D2mD2V2UEhVxwdGLj4+9nL/yvbcDDU0rMsPm0dscMq5jsBtH9RDs4tGENB/1EQSMBZm 4N0OeTaAA7VllndT1oHB3BJDUrRPLEU68dov4iBqjEqafkIlOB8NyZRjUSZC4AH8EiGA KXb7EvfFP7hN+2KtekkE9br6PgJHDgf9r5oJ7glCJMkQAXDtXMaPJVT+kmwGhFPVS0+S 65QQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=09tvVVgMuPhszC8kvG3DhKzcOPXNCnFY8WJwglUgHD0=; b=i8PAsF6XeTIY3PpFEHtENpU4wg+T8wffl+S6dST1KjVUnCsNe/6KjYANJwp6XLNg86 ymRzFmvEPjepCKURUpCcYIOww6B0m1f3sUC4jp5LXUmtW96WNoJyjDXUwC54qknmPcwL 3Zps+eudU1xpSdsacFoBpcEgJCGssw9shkGOHVYeTeab/GF5CvbVX36YlDZiE/RZrhIm JS4wEgJH7WmAsdsy2jMaaA2slrt5FRk0IxnDX4JMvq/ujQlu7ZOzF1xvEfRYRg+qtFiR okwhBJQt8ecqeEK7BFqVOE/lKB0ACG0eszH66nyH6ZWvSRaFkc1pB6prhOHA05caOehJ S5rw== X-Gm-Message-State: AJaThX4uR+T94pjS+S0vOAXf1OZpI77TCQXOB7l7xpXTYeQ57/Hj0vKD M4f/PqrPMkE07J2CFYZtkic= X-Google-Smtp-Source: ABhQp+Q/zIN3qLdSIKF5C8NpNKE7lhi5gAENiz3rk9oGsMqTgGtR85OGp7bnyz4CbdFtLL0/WEwJ1Q== X-Received: by 10.101.70.130 with SMTP id h2mr1318773pgr.238.1510122069914; Tue, 07 Nov 2017 22:21:09 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.21.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:21:09 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com Subject: [PATCH 29/31] MAINTAINERS: Add nds32 Date: Wed, 8 Nov 2017 13:55:17 +0800 Message-Id: <16035efb78f70411998755693339471032743377.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Greentime Hu --- 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 +M: Vincent Chen +T: git https://github.com/andestech/linux.git +S: Supported +F: arch/nds32 +K: nds32 +N: nds32 + ANDROID CONFIG FRAGMENTS M: Rob Herring S: Supported From patchwork Wed Nov 8 05:55:18 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835629 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="TRepbSl3"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWx5c1wryz9s0Z for ; Wed, 8 Nov 2017 17:21:40 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754588AbdKHGVW (ORCPT ); Wed, 8 Nov 2017 01:21:22 -0500 Received: from mail-pf0-f196.google.com ([209.85.192.196]:50239 "EHLO mail-pf0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754401AbdKHGVN (ORCPT ); Wed, 8 Nov 2017 01:21:13 -0500 Received: by mail-pf0-f196.google.com with SMTP id b6so1112958pfh.7; Tue, 07 Nov 2017 22:21:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=SEXh1S3mhxyzUA/xQqLkUQ3L6lNImy/wUf96478MvNg=; b=TRepbSl3t1rr/mu9MMpsfUsLg/RV3PhnIichiBvsVpZ72BTXZLdEwX/v+l2H7u8zPr rzBrkc+fPvszX3sts4dxBAKNmj5Duyp6OfVFMMIqpnHBLkvQVI0MFIdqEFcPHtxcFaET t0rHxfOMqBZ1nwsRPYCGEU60Myzq2UtaFw7Z1cus1Xj74n7d4qCYPr95HW3OS7hXnPa9 hAkiV/PGH0EZHWTVyDBRZwQzbf4T6XwQm7G70Ko1XxVKwZhPK7c6xyyew0bDWGnxkbFU SwNPezHAVMLOnj6uY+F6OS9+p5t695dfI2QTForCkPqkP3LmerRa3A5Nde+msEUByHSI NOfQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=SEXh1S3mhxyzUA/xQqLkUQ3L6lNImy/wUf96478MvNg=; b=WLxFgFkteHBKJ6edmm1Xeeym1c7mC1sTYjH3fJJZ0cgV/WmAGfP/k1PxBHek1mIrQp YvGN/Rw4BguniJAoCEb7vT7ObeAHx98GF0m34F28/fTBA6exvckjQHMdMlUMJ8XaDqsM hcnLi4VFBtCMZMZjVwzm98xb0K3Wbjp85KfYxH9BubfyTnk1oCZESA286RkDo0d+RlSR qg7bN0/BCn3wASbXG1i6V3uFmC4/kN8/X6qbSTouJJjQBd1x3IroLRjskSIVF+kNboQP yRD6PEgqDKsLgKiyu795BmLNzt1EDy8SBzp6IDFnrz7d3xEkb6rF8UTlt4qIn/dbswwH Qwsw== X-Gm-Message-State: AJaThX6NPPg4EBYvTjzbNHZLAjn+q5JKRwjtaHVnZ4YMret7VmbVlKzB tB+V2O7vvp8EV4gF1Io0Z9E= X-Google-Smtp-Source: ABhQp+TjBz2hgbhHUng+Jvx1Ex/bJOWVCSdZi35XzKgFAY7hXqEIzzr4Lzrdgm7OvYpl4tVw5jnY1g== X-Received: by 10.99.95.20 with SMTP id t20mr1147186pgb.398.1510122072712; Tue, 07 Nov 2017 22:21:12 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.21.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:21:12 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com, Vincent Chen , Rick Chen , Zong Li Subject: [PATCH 30/31] dt-bindings: nds32 CPU Bindings Date: Wed, 8 Nov 2017 13:55:18 +0800 Message-Id: <1a8efba0727437d510d10755f3fcea806833651d.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Vincent Chen Signed-off-by: Rick Chen Signed-off-by: Zong Li Signed-off-by: Greentime Hu --- 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: + Definition: should be one of: + "andestech,n13" + "andestech,n15" + "andestech,d15" + "andestech,n10" + "andestech,d10" + + - device_type + Usage: required + Value type: + Definition: must be "cpu" + +* Examples + +/ { + cpus { + cpu@0 { + device_type = "cpu"; + compatible = "andestech,n13", "andestech,n15"; + }; + }; +}; From patchwork Wed Nov 8 05:55:19 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greentime Hu X-Patchwork-Id: 835630 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="QR+T1K98"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yWx5r0Vxgz9s0Z for ; Wed, 8 Nov 2017 17:21:52 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754545AbdKHGVV (ORCPT ); Wed, 8 Nov 2017 01:21:21 -0500 Received: from mail-pg0-f67.google.com ([74.125.83.67]:48955 "EHLO mail-pg0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754440AbdKHGVP (ORCPT ); Wed, 8 Nov 2017 01:21:15 -0500 Received: by mail-pg0-f67.google.com with SMTP id v78so1176939pgb.5; Tue, 07 Nov 2017 22:21:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=NhV6D5xw1uBVjQERFqeyEQf0daxwC3PYiFsj0GmtG6Y=; b=QR+T1K98DeHPX6VJZSKIiTKNT1WpTN2gxI6qq36i3Jmvu4czI6nJX9DPnjyPhV1D6/ 3nOhWm2JQheJ+tTpKOj4z0zYN/kqXK+5wGoPr2PW/zSIYJ9HKtr5ZoiWTH2rRDyJ7D5E BIiHhbuQVkoZ8hFqqs9HeuHaugRAqBD2wlAlW7TCJpMZbsUwBmtSXrJ8dYVaOutmat7d U1gJryiejVRuuCSK7qngqrGxe3Ao64Tg5MKEuPeMdVd9GpHkzJaGv8N5RD7LXEsLMT21 m3u12ZzeOoS4CANaiA5EkSJs9nkpFvDgwdWFpWas7AwG1ZpcxDJJRe2XcA4i/yQa7+me G2bw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=NhV6D5xw1uBVjQERFqeyEQf0daxwC3PYiFsj0GmtG6Y=; b=Fx59T5Wd9y02jHFrn6c9ECvMyjpZu7yyd+DxTAdf5xauqNqK2zzsZEkm9FamRfBk/D 4OCoax6KBgLy9tW0DPblH7VYCaQmRINTMdMi1rPZvXB+ZQHv8m7+BRd4GqdG7WAE893n AFdYMUSsa7/EDrmbN+C7KzOQSgRVn0Zl7xPhv9lspEpO3TlBpIVbIo3I6V/lTP32N1hW bUCBzkOqE59UiS7KUnK5UT4L8JRWIhV2FRk3rj5m0TCArbeaXBIoeTcWO0FMMo3n14PQ GtTrWR67v1Kb/gWDtRtlL8io+QTJPI04oTp6JME1k2cpkiv9W2uIsB0JvVmWpV9i7Wrd FIXQ== X-Gm-Message-State: AJaThX4G9UsjxefG44tI5KKoK/oGObPypAP29+flB/O3mSW20bXQc/e/ Txsc2yCpO8XiwnQqzLShd5GFRrO2 X-Google-Smtp-Source: ABhQp+QsifQk4G1dg3jtQmtcNgkJ08/GAC1z4KVoPANsCyiWdD4FA7BhUlmQkzQkt21Ry/Py2TS5TA== X-Received: by 10.99.96.71 with SMTP id u68mr1237072pgb.389.1510122075101; Tue, 07 Nov 2017 22:21:15 -0800 (PST) Received: from app09.andestech.com ([118.163.51.199]) by smtp.gmail.com with ESMTPSA id a4sm6581339pfj.72.2017.11.07.22.21.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 07 Nov 2017 22:21:14 -0800 (PST) From: Greentime Hu To: greentime@andestech.com, linux-kernel@vger.kernel.org, arnd@arndb.de, linux-arch@vger.kernel.org, tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com, robh+dt@kernel.org, netdev@vger.kernel.org Cc: green.hu@gmail.com Subject: [PATCH 31/31] net: faraday add nds32 support. Date: Wed, 8 Nov 2017 13:55:19 +0800 Message-Id: <20c6d5d39d49397d2e7ba597072495ae1c7a816f.1510118606.git.green.hu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: References: In-Reply-To: References: Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Greentime Hu Signed-off-by: Greentime Hu --- 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