diff options
Diffstat (limited to 'arch/nios2/include/asm')
39 files changed, 2861 insertions, 0 deletions
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild new file mode 100644 index 000000000000..bb160be0dc28 --- /dev/null +++ b/arch/nios2/include/asm/Kbuild @@ -0,0 +1,66 @@ +generic-y += atomic.h +generic-y += auxvec.h +generic-y += barrier.h +generic-y += bitops.h +generic-y += bitsperlong.h +generic-y += bug.h +generic-y += bugs.h +generic-y += clkdev.h +generic-y += cputime.h +generic-y += current.h +generic-y += 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 += futex.h +generic-y += hardirq.h +generic-y += hash.h +generic-y += hw_irq.h +generic-y += ioctl.h +generic-y += ioctls.h +generic-y += ipcbuf.h +generic-y += irq_regs.h +generic-y += irq_work.h +generic-y += kdebug.h +generic-y += kmap_types.h +generic-y += kvm_para.h +generic-y += local.h +generic-y += mcs_spinlock.h +generic-y += mman.h +generic-y += module.h +generic-y += msgbuf.h +generic-y += param.h +generic-y += pci.h +generic-y += percpu.h +generic-y += poll.h +generic-y += posix_types.h +generic-y += preempt.h +generic-y += resource.h +generic-y += scatterlist.h +generic-y += sections.h +generic-y += segment.h +generic-y += sembuf.h +generic-y += serial.h +generic-y += shmbuf.h +generic-y += shmparam.h +generic-y += siginfo.h +generic-y += signal.h +generic-y += socket.h +generic-y += sockios.h +generic-y += spinlock.h +generic-y += stat.h +generic-y += statfs.h +generic-y += termbits.h +generic-y += termios.h +generic-y += topology.h +generic-y += trace_clock.h +generic-y += types.h +generic-y += unaligned.h +generic-y += user.h +generic-y += vga.h +generic-y += xor.h diff --git a/arch/nios2/include/asm/asm-macros.h b/arch/nios2/include/asm/asm-macros.h new file mode 100644 index 000000000000..29fa2e4d7b00 --- /dev/null +++ b/arch/nios2/include/asm/asm-macros.h @@ -0,0 +1,309 @@ +/* + * Macro used to simplify coding multi-line assembler. + * Some of the bit test macro can simplify down to one line + * depending on the mask value. + * + * Copyright (C) 2004 Microtronix Datacom Ltd. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + */ +#ifndef _ASM_NIOS2_ASMMACROS_H +#define _ASM_NIOS2_ASMMACROS_H +/* + * ANDs reg2 with mask and places the result in reg1. + * + * You cannnot use the same register for reg1 & reg2. + */ + +.macro ANDI32 reg1, reg2, mask +.if \mask & 0xffff + .if \mask & 0xffff0000 + movhi \reg1, %hi(\mask) + movui \reg1, %lo(\mask) + and \reg1, \reg1, \reg2 + .else + andi \reg1, \reg2, %lo(\mask) + .endif +.else + andhi \reg1, \reg2, %hi(\mask) +.endif +.endm + +/* + * ORs reg2 with mask and places the result in reg1. + * + * It is safe to use the same register for reg1 & reg2. + */ + +.macro ORI32 reg1, reg2, mask +.if \mask & 0xffff + .if \mask & 0xffff0000 + orhi \reg1, \reg2, %hi(\mask) + ori \reg1, \reg2, %lo(\mask) + .else + ori \reg1, \reg2, %lo(\mask) + .endif +.else + orhi \reg1, \reg2, %hi(\mask) +.endif +.endm + +/* + * XORs reg2 with mask and places the result in reg1. + * + * It is safe to use the same register for reg1 & reg2. + */ + +.macro XORI32 reg1, reg2, mask +.if \mask & 0xffff + .if \mask & 0xffff0000 + xorhi \reg1, \reg2, %hi(\mask) + xori \reg1, \reg1, %lo(\mask) + .else + xori \reg1, \reg2, %lo(\mask) + .endif +.else + xorhi \reg1, \reg2, %hi(\mask) +.endif +.endm + +/* + * This is a support macro for BTBZ & BTBNZ. It checks + * the bit to make sure it is valid 32 value. + * + * It is safe to use the same register for reg1 & reg2. + */ + +.macro BT reg1, reg2, bit +.if \bit > 31 + .err +.else + .if \bit < 16 + andi \reg1, \reg2, (1 << \bit) + .else + andhi \reg1, \reg2, (1 << (\bit - 16)) + .endif +.endif +.endm + +/* + * Tests the bit in reg2 and branches to label if the + * bit is zero. The result of the bit test is stored in reg1. + * + * It is safe to use the same register for reg1 & reg2. + */ + +.macro BTBZ reg1, reg2, bit, label + BT \reg1, \reg2, \bit + beq \reg1, r0, \label +.endm + +/* + * Tests the bit in reg2 and branches to label if the + * bit is non-zero. The result of the bit test is stored in reg1. + * + * It is safe to use the same register for reg1 & reg2. + */ + +.macro BTBNZ reg1, reg2, bit, label + BT \reg1, \reg2, \bit + bne \reg1, r0, \label +.endm + +/* + * Tests the bit in reg2 and then compliments the bit in reg2. + * The result of the bit test is stored in reg1. + * + * It is NOT safe to use the same register for reg1 & reg2. + */ + +.macro BTC reg1, reg2, bit +.if \bit > 31 + .err +.else + .if \bit < 16 + andi \reg1, \reg2, (1 << \bit) + xori \reg2, \reg2, (1 << \bit) + .else + andhi \reg1, \reg2, (1 << (\bit - 16)) + xorhi \reg2, \reg2, (1 << (\bit - 16)) + .endif +.endif +.endm + +/* + * Tests the bit in reg2 and then sets the bit in reg2. + * The result of the bit test is stored in reg1. + * + * It is NOT safe to use the same register for reg1 & reg2. + */ + +.macro BTS reg1, reg2, bit +.if \bit > 31 + .err +.else + .if \bit < 16 + andi \reg1, \reg2, (1 << \bit) + ori \reg2, \reg2, (1 << \bit) + .else + andhi \reg1, \reg2, (1 << (\bit - 16)) + orhi \reg2, \reg2, (1 << (\bit - 16)) + .endif +.endif +.endm + +/* + * Tests the bit in reg2 and then resets the bit in reg2. + * The result of the bit test is stored in reg1. + * + * It is NOT safe to use the same register for reg1 & reg2. + */ + +.macro BTR reg1, reg2, bit +.if \bit > 31 + .err +.else + .if \bit < 16 + andi \reg1, \reg2, (1 << \bit) + andi \reg2, \reg2, %lo(~(1 << \bit)) + .else + andhi \reg1, \reg2, (1 << (\bit - 16)) + andhi \reg2, \reg2, %lo(~(1 << (\bit - 16))) + .endif +.endif +.endm + +/* + * Tests the bit in reg2 and then compliments the bit in reg2. + * The result of the bit test is stored in reg1. If the + * original bit was zero it branches to label. + * + * It is NOT safe to use the same register for reg1 & reg2. + */ + +.macro BTCBZ reg1, reg2, bit, label + BTC \reg1, \reg2, \bit + beq \reg1, r0, \label +.endm + +/* + * Tests the bit in reg2 and then compliments the bit in reg2. + * The result of the bit test is stored in reg1. If the + * original bit was non-zero it branches to label. + * + * It is NOT safe to use the same register for reg1 & reg2. + */ + +.macro BTCBNZ reg1, reg2, bit, label + BTC \reg1, \reg2, \bit + bne \reg1, r0, \label +.endm + +/* + * Tests the bit in reg2 and then sets the bit in reg2. + * The result of the bit test is stored in reg1. If the + * original bit was zero it branches to label. + * + * It is NOT safe to use the same register for reg1 & reg2. + */ + +.macro BTSBZ reg1, reg2, bit, label + BTS \reg1, \reg2, \bit + beq \reg1, r0, \label +.endm + +/* + * Tests the bit in reg2 and then sets the bit in reg2. + * The result of the bit test is stored in reg1. If the + * original bit was non-zero it branches to label. + * + * It is NOT safe to use the same register for reg1 & reg2. + */ + +.macro BTSBNZ reg1, reg2, bit, label + BTS \reg1, \reg2, \bit + bne \reg1, r0, \label +.endm + +/* + * Tests the bit in reg2 and then resets the bit in reg2. + * The result of the bit test is stored in reg1. If the + * original bit was zero it branches to label. + * + * It is NOT safe to use the same register for reg1 & reg2. + */ + +.macro BTRBZ reg1, reg2, bit, label + BTR \reg1, \reg2, \bit + bne \reg1, r0, \label +.endm + +/* + * Tests the bit in reg2 and then resets the bit in reg2. + * The result of the bit test is stored in reg1. If the + * original bit was non-zero it branches to label. + * + * It is NOT safe to use the same register for reg1 & reg2. + */ + +.macro BTRBNZ reg1, reg2, bit, label + BTR \reg1, \reg2, \bit + bne \reg1, r0, \label +.endm + +/* + * Tests the bits in mask against reg2 stores the result in reg1. + * If the all the bits in the mask are zero it branches to label. + * + * It is safe to use the same register for reg1 & reg2. + */ + +.macro TSTBZ reg1, reg2, mask, label + ANDI32 \reg1, \reg2, \mask + beq \reg1, r0, \label +.endm + +/* + * Tests the bits in mask against reg2 stores the result in reg1. + * If the any of the bits in the mask are 1 it branches to label. + * + * It is safe to use the same register for reg1 & reg2. + */ + +.macro TSTBNZ reg1, reg2, mask, label + ANDI32 \reg1, \reg2, \mask + bne \reg1, r0, \label +.endm + +/* + * Pushes reg onto the stack. + */ + +.macro PUSH reg + addi sp, sp, -4 + stw \reg, 0(sp) +.endm + +/* + * Pops the top of the stack into reg. + */ + +.macro POP reg + ldw \reg, 0(sp) + addi sp, sp, 4 +.endm + + +#endif /* _ASM_NIOS2_ASMMACROS_H */ diff --git a/arch/nios2/include/asm/asm-offsets.h b/arch/nios2/include/asm/asm-offsets.h new file mode 100644 index 000000000000..5b9f5e04a058 --- /dev/null +++ b/arch/nios2/include/asm/asm-offsets.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch> + * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <generated/asm-offsets.h> diff --git a/arch/nios2/include/asm/cache.h b/arch/nios2/include/asm/cache.h new file mode 100644 index 000000000000..2293cf57e307 --- /dev/null +++ b/arch/nios2/include/asm/cache.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2004 Microtronix Datacom Ltd. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + */ + +#ifndef _ASM_NIOS2_CACHE_H +#define _ASM_NIOS2_CACHE_H + +#define NIOS2_DCACHE_SIZE CONFIG_NIOS2_DCACHE_SIZE +#define NIOS2_ICACHE_SIZE CONFIG_NIOS2_ICACHE_SIZE +#define NIOS2_DCACHE_LINE_SIZE CONFIG_NIOS2_DCACHE_LINE_SIZE +#define NIOS2_ICACHE_LINE_SHIFT 5 +#define NIOS2_ICACHE_LINE_SIZE (1 << NIOS2_ICACHE_LINE_SHIFT) + +/* bytes per L1 cache line */ +#define L1_CACHE_SHIFT NIOS2_ICACHE_LINE_SHIFT +#define L1_CACHE_BYTES NIOS2_ICACHE_LINE_SIZE + +#define ARCH_DMA_MINALIGN L1_CACHE_BYTES + +#define __cacheline_aligned +#define ____cacheline_aligned + +#endif diff --git a/arch/nios2/include/asm/cacheflush.h b/arch/nios2/include/asm/cacheflush.h new file mode 100644 index 000000000000..52abba973dc2 --- /dev/null +++ b/arch/nios2/include/asm/cacheflush.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2003 Microtronix Datacom Ltd. + * Copyright (C) 2000-2002 Greg Ungerer <gerg@snapgear.com> + * + * 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. + */ + +#ifndef _ASM_NIOS2_CACHEFLUSH_H +#define _ASM_NIOS2_CACHEFLUSH_H + +#include <linux/mm_types.h> + +/* + * This flag is used to indicate that the page pointed to by a pte is clean + * and does not require cleaning before returning it to the user. + */ +#define PG_dcache_clean PG_arch_1 + +struct mm_struct; + +extern void flush_cache_all(void); +extern void flush_cache_mm(struct mm_struct *mm); +extern void flush_cache_dup_mm(struct mm_struct *mm); +extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end); +extern void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, + unsigned long pfn); +#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 +extern void flush_dcache_page(struct page *page); + +extern void flush_icache_range(unsigned long start, unsigned long end); +extern void flush_icache_page(struct vm_area_struct *vma, struct page *page); + +#define flush_cache_vmap(start, end) flush_dcache_range(start, end) +#define flush_cache_vunmap(start, end) flush_dcache_range(start, end) + +extern void copy_to_user_page(struct vm_area_struct *vma, struct page *page, + unsigned long user_vaddr, + void *dst, void *src, int len); +extern void copy_from_user_page(struct vm_area_struct *vma, struct page *page, + unsigned long user_vaddr, + void *dst, void *src, int len); + +extern void flush_dcache_range(unsigned long start, unsigned long end); +extern void invalidate_dcache_range(unsigned long start, unsigned long end); + +#define flush_dcache_mmap_lock(mapping) do { } while (0) +#define flush_dcache_mmap_unlock(mapping) do { } while (0) + +#endif /* _ASM_NIOS2_CACHEFLUSH_H */ diff --git a/arch/nios2/include/asm/checksum.h b/arch/nios2/include/asm/checksum.h new file mode 100644 index 000000000000..6bc1f0d5df7b --- /dev/null +++ b/arch/nios2/include/asm/checksum.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch> + * Copyright (C) 2004 Microtronix Datacom Ltd. + * + * 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. + */ + +#ifndef _ASM_NIOS_CHECKSUM_H +#define _ASM_NIOS_CHECKSUM_H + +/* Take these from lib/checksum.c */ +extern __wsum csum_partial(const void *buff, int len, __wsum sum); +extern __wsum csum_partial_copy(const void *src, void *dst, int len, + __wsum sum); +extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst, + int len, __wsum sum, int *csum_err); +#define csum_partial_copy_nocheck(src, dst, len, sum) \ + csum_partial_copy((src), (dst), (len), (sum)) + +extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl); +extern __sum16 ip_compute_csum(const void *buff, int len); + +/* + * Fold a partial checksum + */ +static inline __sum16 csum_fold(__wsum sum) +{ + __asm__ __volatile__( + "add %0, %1, %0\n" + "cmpltu r8, %0, %1\n" + "srli %0, %0, 16\n" + "add %0, %0, r8\n" + "nor %0, %0, %0\n" + : "=r" (sum) + : "r" (sum << 16), "0" (sum) + : "r8"); + return (__force __sum16) sum; +} + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +#define csum_tcpudp_nofold csum_tcpudp_nofold +static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, + unsigned short len, + unsigned short proto, + __wsum sum) +{ + __asm__ __volatile__( + "add %0, %1, %0\n" + "cmpltu r8, %0, %1\n" + "add %0, %0, r8\n" /* add carry */ + "add %0, %2, %0\n" + "cmpltu r8, %0, %2\n" + "add %0, %0, r8\n" /* add carry */ + "add %0, %3, %0\n" + "cmpltu r8, %0, %3\n" + "add %0, %0, r8\n" /* add carry */ + : "=r" (sum), "=r" (saddr) + : "r" (daddr), "r" ((ntohs(len) << 16) + (proto * 256)), + "0" (sum), + "1" (saddr) + : "r8"); + + return sum; +} + +static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, + unsigned short len, + unsigned short proto, __wsum sum) +{ + return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); +} + +#endif /* _ASM_NIOS_CHECKSUM_H */ diff --git a/arch/nios2/include/asm/cmpxchg.h b/arch/nios2/include/asm/cmpxchg.h new file mode 100644 index 000000000000..85938711542d --- /dev/null +++ b/arch/nios2/include/asm/cmpxchg.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2004 Microtronix Datacom Ltd. + * + * 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. + */ + +#ifndef _ASM_NIOS2_CMPXCHG_H +#define _ASM_NIOS2_CMPXCHG_H + +#include <linux/irqflags.h> + +#define xchg(ptr, x) \ + ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr)))) + +struct __xchg_dummy { unsigned long a[100]; }; +#define __xg(x) ((volatile struct __xchg_dummy *)(x)) + +static inline unsigned long __xchg(unsigned long x, volatile void *ptr, + int size) +{ + unsigned long tmp, flags; + + local_irq_save(flags); + + switch (size) { + case 1: + __asm__ __volatile__( + "ldb %0, %2\n" + "stb %1, %2\n" + : "=&r" (tmp) + : "r" (x), "m" (*__xg(ptr)) + : "memory"); + break; + case 2: + __asm__ __volatile__( + "ldh %0, %2\n" + "sth %1, %2\n" + : "=&r" (tmp) + : "r" (x), "m" (*__xg(ptr)) + : "memory"); + break; + case 4: + __asm__ __volatile__( + "ldw %0, %2\n" + "stw %1, %2\n" + : "=&r" (tmp) + : "r" (x), "m" (*__xg(ptr)) + : "memory"); + break; + } + + local_irq_restore(flags); + return tmp; +} + +#include <asm-generic/cmpxchg.h> +#include <asm-generic/cmpxchg-local.h> + +#endif /* _ASM_NIOS2_CMPXCHG_H */ diff --git a/arch/nios2/include/asm/cpuinfo.h b/arch/nios2/include/asm/cpuinfo.h new file mode 100644 index 000000000000..e88fcae464d9 --- /dev/null +++ b/arch/nios2/include/asm/cpuinfo.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef _ASM_NIOS2_CPUINFO_H +#define _ASM_NIOS2_CPUINFO_H + +#include <linux/types.h> + +struct cpuinfo { + /* Core CPU configuration */ + char cpu_impl[12]; + u32 cpu_clock_freq; + u32 mmu; + u32 has_div; + u32 has_mul; + u32 has_mulx; + + /* CPU caches */ + u32 icache_line_size; + u32 icache_size; + u32 dcache_line_size; + u32 dcache_size; + + /* TLB */ + u32 tlb_pid_num_bits; /* number of bits used for the PID in TLBMISC */ + u32 tlb_num_ways; + u32 tlb_num_ways_log2; + u32 tlb_num_entries; + u32 tlb_num_lines; + u32 tlb_ptr_sz; + + /* Addresses */ + u32 reset_addr; + u32 exception_addr; + u32 fast_tlb_miss_exc_addr; +}; + +extern struct cpuinfo cpuinfo; + +extern void setup_cpuinfo(void); + +#endif /* _ASM_NIOS2_CPUINFO_H */ diff --git a/arch/nios2/include/asm/delay.h b/arch/nios2/include/asm/delay.h new file mode 100644 index 000000000000..098e49bf3aa3 --- /dev/null +++ b/arch/nios2/include/asm/delay.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2014 Altera Corporation + * Copyright (C) 2004 Microtronix Datacom Ltd + * + * 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. + */ + +#ifndef _ASM_NIOS2_DELAY_H +#define _ASM_NIOS2_DELAY_H + +#include <asm-generic/delay.h> + +/* Undefined functions to get compile-time errors */ +extern void __bad_udelay(void); +extern void __bad_ndelay(void); + +extern unsigned long loops_per_jiffy; + +#endif /* _ASM_NIOS2_DELAY_H */ diff --git a/arch/nios2/include/asm/dma-mapping.h b/arch/nios2/include/asm/dma-mapping.h new file mode 100644 index 000000000000..b5567233f7f1 --- /dev/null +++ b/arch/nios2/include/asm/dma-mapping.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> + * Copyright (C) 2009 Wind River Systems Inc + * + * 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. + */ + +#ifndef _ASM_NIOS2_DMA_MAPPING_H +#define _ASM_NIOS2_DMA_MAPPING_H + +#include <linux/scatterlist.h> +#include <linux/cache.h> +#include <asm/cacheflush.h> + +static inline void __dma_sync_for_device(void *vaddr, size_t size, + enum dma_data_direction direction) +{ + switch (direction) { + case DMA_FROM_DEVICE: + invalidate_dcache_range((unsigned long)vaddr, + (unsigned long)(vaddr + size)); + break; + case DMA_TO_DEVICE: + /* + * We just need to flush the caches here , but Nios2 flush + * instruction will do both writeback and invalidate. + */ + case DMA_BIDIRECTIONAL: /* flush and invalidate */ + flush_dcache_range((unsigned long)vaddr, + (unsigned long)(vaddr + size)); + break; + default: + BUG(); + } +} + +static inline void __dma_sync_for_cpu(void *vaddr, size_t size, + enum dma_data_direction direction) +{ + switch (direction) { + case DMA_BIDIRECTIONAL: + case DMA_FROM_DEVICE: + invalidate_dcache_range((unsigned long)vaddr, + (unsigned long)(vaddr + size)); + break; + case DMA_TO_DEVICE: + break; + default: + BUG(); + } +} + +#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) +#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) + +void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag); + +void dma_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle); + +static inline dma_addr_t dma_map_single(struct device *dev, void *ptr, + size_t size, + enum dma_data_direction direction) +{ + BUG_ON(!valid_dma_direction(direction)); + __dma_sync_for_device(ptr, size, direction); + return virt_to_phys(ptr); +} + +static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, + size_t size, enum dma_data_direction direction) +{ +} + +extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction direction); +extern dma_addr_t dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, enum dma_data_direction direction); +extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address, + size_t size, enum dma_data_direction direction); +extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg, + int nhwentries, enum dma_data_direction direction); +extern void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, + size_t size, enum dma_data_direction direction); +extern void dma_sync_single_for_device(struct device *dev, + dma_addr_t dma_handle, size_t size, enum dma_data_direction direction); +extern void dma_sync_single_range_for_cpu(struct device *dev, + dma_addr_t dma_handle, unsigned long offset, size_t size, + enum dma_data_direction direction); +extern void dma_sync_single_range_for_device(struct device *dev, + dma_addr_t dma_handle, unsigned long offset, size_t size, + enum dma_data_direction direction); +extern void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, + int nelems, enum dma_data_direction direction); +extern void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, + int nelems, enum dma_data_direction direction); + +static inline int dma_supported(struct device *dev, u64 mask) +{ + return 1; +} + +static inline int dma_set_mask(struct device *dev, u64 mask) +{ + if (!dev->dma_mask || !dma_supported(dev, mask)) + return -EIO; + + *dev->dma_mask = mask; + + return 0; +} + +static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) +{ + return 0; +} + +/* +* dma_alloc_noncoherent() returns non-cacheable memory, so there's no need to +* do any flushing here. +*/ +static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, + enum dma_data_direction direction) +{ +} + +/* drivers/base/dma-mapping.c */ +extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, + void *cpu_addr, dma_addr_t dma_addr, size_t size); +extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt, + void *cpu_addr, dma_addr_t dma_addr, + size_t size); + +#define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s) +#define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s) + +#endif /* _ASM_NIOS2_DMA_MAPPING_H */ diff --git a/arch/nios2/include/asm/elf.h b/arch/nios2/include/asm/elf.h new file mode 100644 index 000000000000..b7d655dff731 --- /dev/null +++ b/arch/nios2/include/asm/elf.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef _ASM_NIOS2_ELF_H +#define _ASM_NIOS2_ELF_H + +#include <uapi/asm/elf.h> + +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(x) ((x)->e_machine == EM_ALTERA_NIOS2) + +#define ELF_PLAT_INIT(_r, load_addr) + +#define CORE_DUMP_USE_REGSET +#define ELF_EXEC_PAGESIZE 4096 + +/* 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 0xD0000000UL + +/* regs is struct pt_regs, pr_reg is elf_gregset_t (which is + now struct_user_regs, they are different) */ + +#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 +struct linux_binprm; +extern int arch_setup_additional_pages(struct linux_binprm *bprm, + int uses_interp); +#define ELF_CORE_COPY_REGS(pr_reg, regs) \ +{ do { \ + /* Bleech. */ \ + pr_reg[0] = regs->r8; \ + pr_reg[1] = regs->r9; \ + pr_reg[2] = regs->r10; \ + pr_reg[3] = regs->r11; \ + pr_reg[4] = regs->r12; \ + pr_reg[5] = regs->r13; \ + pr_reg[6] = regs->r14; \ + pr_reg[7] = regs->r15; \ + pr_reg[8] = regs->r1; \ + pr_reg[9] = regs->r2; \ + pr_reg[10] = regs->r3; \ + pr_reg[11] = regs->r4; \ + pr_reg[12] = regs->r5; \ + pr_reg[13] = regs->r6; \ + pr_reg[14] = regs->r7; \ + pr_reg[15] = regs->orig_r2; \ + pr_reg[16] = regs->ra; \ + pr_reg[17] = regs->fp; \ + pr_reg[18] = regs->sp; \ + pr_reg[19] = regs->gp; \ + pr_reg[20] = regs->estatus; \ + pr_reg[21] = regs->ea; \ + pr_reg[22] = regs->orig_r7; \ + { \ + struct switch_stack *sw = ((struct switch_stack *)regs) - 1; \ + pr_reg[23] = sw->r16; \ + pr_reg[24] = sw->r17; \ + pr_reg[25] = sw->r18; \ + pr_reg[26] = sw->r19; \ + pr_reg[27] = sw->r20; \ + pr_reg[28] = sw->r21; \ + pr_reg[29] = sw->r22; \ + pr_reg[30] = sw->r23; \ + pr_reg[31] = sw->fp; \ + pr_reg[32] = sw->gp; \ + pr_reg[33] = sw->ra; \ + } \ +} while (0); } + +/* This yields a mask that user programs can use to figure out what + instruction set this cpu supports. */ + +#define ELF_HWCAP (0) + +/* This yields a string that ld.so will use to load implementation + specific libraries for optimization. This is more specific in + intent than poking at uname or /proc/cpuinfo. */ + +#define ELF_PLATFORM (NULL) + +#endif /* _ASM_NIOS2_ELF_H */ diff --git a/arch/nios2/include/asm/entry.h b/arch/nios2/include/asm/entry.h new file mode 100644 index 000000000000..cf37f55efbc2 --- /dev/null +++ b/arch/nios2/include/asm/entry.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch> + * Copyright (C) 2004 Microtronix Datacom Ltd. + * + * 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. + */ + +#ifndef _ASM_NIOS2_ENTRY_H +#define _ASM_NIOS2_ENTRY_H + +#ifdef __ASSEMBLY__ + +#include <asm/processor.h> +#include <asm/registers.h> +#include <asm/asm-offsets.h> + +/* + * Standard Nios2 interrupt entry and exit macros. + * Must be called with interrupts disabled. + */ +.macro SAVE_ALL + rdctl r24, estatus + andi r24, r24, ESTATUS_EU + beq r24, r0, 1f /* In supervisor mode, already on kernel stack */ + + movia r24, _current_thread /* Switch to current kernel stack */ + ldw r24, 0(r24) /* using the thread_info */ + addi r24, r24, THREAD_SIZE-PT_REGS_SIZE + stw sp, PT_SP(r24) /* Save user stack before changing */ + mov sp, r24 + br 2f + +1 : mov r24, sp + addi sp, sp, -PT_REGS_SIZE /* Backup the kernel stack pointer */ + stw r24, PT_SP(sp) +2 : stw r1, PT_R1(sp) + stw r2, PT_R2(sp) + stw r3, PT_R3(sp) + stw r4, PT_R4(sp) + stw r5, PT_R5(sp) + stw r6, PT_R6(sp) + stw r7, PT_R7(sp) + stw r8, PT_R8(sp) + stw r9, PT_R9(sp) + stw r10, PT_R10(sp) + stw r11, PT_R11(sp) + stw r12, PT_R12(sp) + stw r13, PT_R13(sp) + stw r14, PT_R14(sp) + stw r15, PT_R15(sp) + stw r2, PT_ORIG_R2(sp) + stw r7, PT_ORIG_R7(sp) + + stw ra, PT_RA(sp) + stw fp, PT_FP(sp) + stw gp, PT_GP(sp) + rdctl r24, estatus + stw r24, PT_ESTATUS(sp) + stw ea, PT_EA(sp) +.endm + +.macro RESTORE_ALL + ldw r1, PT_R1(sp) /* Restore registers */ + ldw r2, PT_R2(sp) + ldw r3, PT_R3(sp) + ldw r4, PT_R4(sp) + ldw r5, PT_R5(sp) + ldw r6, PT_R6(sp) + ldw r7, PT_R7(sp) + ldw r8, PT_R8(sp) + ldw r9, PT_R9(sp) + ldw r10, PT_R10(sp) + ldw r11, PT_R11(sp) + ldw r12, PT_R12(sp) + ldw r13, PT_R13(sp) + ldw r14, PT_R14(sp) + ldw r15, PT_R15(sp) + ldw ra, PT_RA(sp) + ldw fp, PT_FP(sp) + ldw gp, PT_GP(sp) + ldw r24, PT_ESTATUS(sp) + wrctl estatus, r24 + ldw ea, PT_EA(sp) + ldw sp, PT_SP(sp) /* Restore sp last */ +.endm + +.macro SAVE_SWITCH_STACK + addi sp, sp, -SWITCH_STACK_SIZE + stw r16, SW_R16(sp) + stw r17, SW_R17(sp) + stw r18, SW_R18(sp) + stw r19, SW_R19(sp) + stw r20, SW_R20(sp) + stw r21, SW_R21(sp) + stw r22, SW_R22(sp) + stw r23, SW_R23(sp) + stw fp, SW_FP(sp) + stw gp, SW_GP(sp) + stw ra, SW_RA(sp) +.endm + +.macro RESTORE_SWITCH_STACK + ldw r16, SW_R16(sp) + ldw r17, SW_R17(sp) + ldw r18, SW_R18(sp) + ldw r19, SW_R19(sp) + ldw r20, SW_R20(sp) + ldw r21, SW_R21(sp) + ldw r22, SW_R22(sp) + ldw r23, SW_R23(sp) + ldw fp, SW_FP(sp) + ldw gp, SW_GP(sp) + ldw ra, SW_RA(sp) + addi sp, sp, SWITCH_STACK_SIZE +.endm + +#endif /* __ASSEMBLY__ */ +#endif /* _ASM_NIOS2_ENTRY_H */ diff --git a/arch/nios2/include/asm/io.h b/arch/nios2/include/asm/io.h new file mode 100644 index 000000000000..9102bfd3fa1c --- /dev/null +++ b/arch/nios2/include/asm/io.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2014 Altera Corporation + * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch> + * Copyright (C) 2004 Microtronix Datacom Ltd. + * + * 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. + */ + +#ifndef _ASM_NIOS2_IO_H +#define _ASM_NIOS2_IO_H + +#include <linux/types.h> +#include <asm/pgtable-bits.h> + +/* PCI is not supported in nios2, set this to 0. */ +#define IO_SPACE_LIMIT 0 + +#define readb_relaxed(addr) readb(addr) +#define readw_relaxed(addr) readw(addr) +#define readl_relaxed(addr) readl(addr) + +#define writeb_relaxed(x, addr) writeb(x, addr) +#define writew_relaxed(x, addr) writew(x, addr) +#define writel_relaxed(x, addr) writel(x, addr) + +extern void __iomem *__ioremap(unsigned long physaddr, unsigned long size, + unsigned long cacheflag); +extern void __iounmap(void __iomem *addr); + +static inline void __iomem *ioremap(unsigned long physaddr, unsigned long size) +{ + return __ioremap(physaddr, size, 0); +} + +static inline void __iomem *ioremap_nocache(unsigned long physaddr, + unsigned long size) +{ + return __ioremap(physaddr, size, 0); +} + +static inline void iounmap(void __iomem *addr) +{ + __iounmap(addr); +} + +/* Pages to physical address... */ +#define page_to_phys(page) virt_to_phys(page_to_virt(page)) +#define page_to_bus(page) page_to_virt(page) + +/* Macros used for converting between virtual and physical mappings. */ +#define phys_to_virt(vaddr) \ + ((void *)((unsigned long)(vaddr) | CONFIG_NIOS2_KERNEL_REGION_BASE)) +/* Clear top 3 bits */ +#define virt_to_phys(vaddr) \ + ((unsigned long)((unsigned long)(vaddr) & ~0xE0000000)) + +#include <asm-generic/io.h> + +#endif /* _ASM_NIOS2_IO_H */ diff --git a/arch/nios2/include/asm/irq.h b/arch/nios2/include/asm/irq.h new file mode 100644 index 000000000000..8e40fd94a36c --- /dev/null +++ b/arch/nios2/include/asm/irq.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2013 Altera Corporation + * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef _ASM_NIOS2_IRQ_H +#define _ASM_NIOS2_IRQ_H + +#define NIOS2_CPU_NR_IRQS 32 + +#include <asm-generic/irq.h> +#include <linux/irqdomain.h> + +#endif diff --git a/arch/nios2/include/asm/irqflags.h b/arch/nios2/include/asm/irqflags.h new file mode 100644 index 000000000000..75ab92e639f8 --- /dev/null +++ b/arch/nios2/include/asm/irqflags.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ +#ifndef _ASM_IRQFLAGS_H +#define _ASM_IRQFLAGS_H + +#include <asm/registers.h> + +static inline unsigned long arch_local_save_flags(void) +{ + return RDCTL(CTL_STATUS); +} + +/* + * This will restore ALL status register flags, not only the interrupt + * mask flag. + */ +static inline void arch_local_irq_restore(unsigned long flags) +{ + WRCTL(CTL_STATUS, flags); +} + +static inline void arch_local_irq_disable(void) +{ + unsigned long flags; + + flags = arch_local_save_flags(); + arch_local_irq_restore(flags & ~STATUS_PIE); +} + +static inline void arch_local_irq_enable(void) +{ + unsigned long flags; + + flags = arch_local_save_flags(); + arch_local_irq_restore(flags | STATUS_PIE); +} + +static inline int arch_irqs_disabled_flags(unsigned long flags) +{ + return (flags & STATUS_PIE) == 0; +} + +static inline int arch_irqs_disabled(void) +{ + return arch_irqs_disabled_flags(arch_local_save_flags()); +} + +static inline unsigned long arch_local_irq_save(void) +{ + unsigned long flags; + + flags = arch_local_save_flags(); + arch_local_irq_restore(flags & ~STATUS_PIE); + return flags; +} + +#endif /* _ASM_IRQFLAGS_H */ diff --git a/arch/nios2/include/asm/linkage.h b/arch/nios2/include/asm/linkage.h new file mode 100644 index 000000000000..e0c6decd7d58 --- /dev/null +++ b/arch/nios2/include/asm/linkage.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw> + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + */ + +#ifndef _ASM_NIOS2_LINKAGE_H +#define _ASM_NIOS2_LINKAGE_H + +/* This file is required by include/linux/linkage.h */ +#define __ALIGN .align 4 +#define __ALIGN_STR ".align 4" + +#endif diff --git a/arch/nios2/include/asm/mmu.h b/arch/nios2/include/asm/mmu.h new file mode 100644 index 000000000000..d9c0b1010f26 --- /dev/null +++ b/arch/nios2/include/asm/mmu.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch> + * Copyright (C) 2004 Microtronix Datacom Ltd. + * + * 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. + */ + +#ifndef _ASM_NIOS2_MMU_H +#define _ASM_NIOS2_MMU_H + +/* Default "unsigned long" context */ +typedef unsigned long mm_context_t; + +#endif /* _ASM_NIOS2_MMU_H */ diff --git a/arch/nios2/include/asm/mmu_context.h b/arch/nios2/include/asm/mmu_context.h new file mode 100644 index 000000000000..294b4b1f81d4 --- /dev/null +++ b/arch/nios2/include/asm/mmu_context.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch> + * Copyright (C) 1996, 1997, 1998, 1999 by Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + * + * based on MIPS asm/mmu_context.h + * + * 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. + */ + +#ifndef _ASM_NIOS2_MMU_CONTEXT_H +#define _ASM_NIOS2_MMU_CONTEXT_H + +#include <asm-generic/mm_hooks.h> + +extern void mmu_context_init(void); +extern unsigned long get_pid_from_context(mm_context_t *ctx); + +/* + * For the fast tlb miss handlers, we keep a pointer to the current pgd. + * processor. + */ +extern pgd_t *pgd_current; + +static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) +{ +} + +/* + * Initialize the context related info for a new mm_struct instance. + * + * Set all new contexts to 0, that way the generation will never match + * the currently running generation when this context is switched in. + */ +static inline int init_new_context(struct task_struct *tsk, + struct mm_struct *mm) +{ + mm->context = 0; + return 0; +} + +/* + * Destroy context related info for an mm_struct that is about + * to be put to rest. + */ +static inline void destroy_context(struct mm_struct *mm) +{ +} + +void switch_mm(struct mm_struct *prev, struct mm_struct *next, + struct task_struct *tsk); + +static inline void deactivate_mm(struct task_struct *tsk, + struct mm_struct *mm) +{ +} + +/* + * After we have set current->mm to a new value, this activates + * the context for the new mm so we see the new mappings. + */ +void activate_mm(struct mm_struct *prev, struct mm_struct *next); + +#endif /* _ASM_NIOS2_MMU_CONTEXT_H */ diff --git a/arch/nios2/include/asm/mutex.h b/arch/nios2/include/asm/mutex.h new file mode 100644 index 000000000000..ff6101aa2c71 --- /dev/null +++ b/arch/nios2/include/asm/mutex.h @@ -0,0 +1 @@ +#include <asm-generic/mutex-dec.h> diff --git a/arch/nios2/include/asm/page.h b/arch/nios2/include/asm/page.h new file mode 100644 index 000000000000..4b32d6fd9d98 --- /dev/null +++ b/arch/nios2/include/asm/page.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> + * Copyright (C) 2004 Microtronix Datacom Ltd. + * + * MMU support based on asm/page.h from mips which is: + * + * Copyright (C) 1994 - 1999, 2000, 03 Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * + * 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. + */ + +#ifndef _ASM_NIOS2_PAGE_H +#define _ASM_NIOS2_PAGE_H + +#include <linux/pfn.h> +#include <linux/const.h> + +/* + * PAGE_SHIFT determines the page size + */ +#define PAGE_SHIFT 12 +#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE - 1)) + +/* + * PAGE_OFFSET -- the first address of the first page of memory. + */ +#define PAGE_OFFSET \ + (CONFIG_NIOS2_MEM_BASE + CONFIG_NIOS2_KERNEL_REGION_BASE) + +#ifndef __ASSEMBLY__ + +/* + * This gives the physical RAM offset. + */ +#define PHYS_OFFSET CONFIG_NIOS2_MEM_BASE + +/* + * It's normally defined only for FLATMEM config but it's + * used in our early mem init code for all memory models. + * So always define it. + */ +#define ARCH_PFN_OFFSET PFN_UP(PHYS_OFFSET) + +#define clear_page(page) memset((page), 0, PAGE_SIZE) +#define copy_page(to, from) memcpy((to), (from), PAGE_SIZE) + +struct page; + +extern void clear_user_page(void *addr, unsigned long vaddr, struct page *page); +extern void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, + struct page *to); + +/* + * These are used to make use of C type-checking. + */ +typedef struct page *pgtable_t; +typedef struct { unsigned long pte; } pte_t; +typedef struct { unsigned long pgd; } pgd_t; +typedef struct { unsigned long pgprot; } pgprot_t; + +#define pte_val(x) ((x).pte) +#define pgd_val(x) ((x).pgd) +#define pgprot_val(x) ((x).pgprot) + +#define __pte(x) ((pte_t) { (x) }) +#define __pgd(x) ((pgd_t) { (x) }) +#define __pgprot(x) ((pgprot_t) { (x) }) + +extern unsigned long memory_start; +extern unsigned long memory_end; +extern unsigned long memory_size; + +extern struct page *mem_map; + +#endif /* !__ASSEMBLY__ */ + +# define __pa(x) \ + ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET) +# define __va(x) \ + ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET)) + +#define page_to_virt(page) \ + ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET) + +# define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) +# define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && \ + (pfn) < max_mapnr) + +# define virt_to_page(vaddr) pfn_to_page(PFN_DOWN(virt_to_phys(vaddr))) +# define virt_addr_valid(vaddr) pfn_valid(PFN_DOWN(virt_to_phys(vaddr))) + +# define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +# define UNCAC_ADDR(addr) \ + ((void *)((unsigned)(addr) | CONFIG_NIOS2_IO_REGION_BASE)) +# define CAC_ADDR(addr) \ + ((void *)(((unsigned)(addr) & ~CONFIG_NIOS2_IO_REGION_BASE) | \ + CONFIG_NIOS2_KERNEL_REGION_BASE)) + +#include <asm-generic/memory_model.h> + +#include <asm-generic/getorder.h> + +#endif /* _ASM_NIOS2_PAGE_H */ diff --git a/arch/nios2/include/asm/pgalloc.h b/arch/nios2/include/asm/pgalloc.h new file mode 100644 index 000000000000..6e2985e0a7b9 --- /dev/null +++ b/arch/nios2/include/asm/pgalloc.h @@ -0,0 +1,86 @@ +/* + * 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 - 2001, 2003 by Ralf Baechle + * Copyright (C) 1999, 2000, 2001 Silicon Graphics, Inc. + */ + +#ifndef _ASM_NIOS2_PGALLOC_H +#define _ASM_NIOS2_PGALLOC_H + +#include <linux/mm.h> + +static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, + pte_t *pte) +{ + set_pmd(pmd, __pmd((unsigned long)pte)); +} + +static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, + pgtable_t pte) +{ + set_pmd(pmd, __pmd((unsigned long)page_address(pte))); +} +#define pmd_pgtable(pmd) pmd_page(pmd) + +/* + * Initialize a new pmd table with invalid pointers. + */ +extern void pmd_init(unsigned long page, unsigned long pagetable); + +extern pgd_t *pgd_alloc(struct mm_struct *mm); + +static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) +{ + free_pages((unsigned long)pgd, PGD_ORDER); +} + +static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, + unsigned long address) +{ + pte_t *pte; + + pte = (pte_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, + PTE_ORDER); + + return pte; +} + +static inline pgtable_t pte_alloc_one(struct mm_struct *mm, + unsigned long address) +{ + struct page *pte; + + pte = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER); + if (pte) { + if (!pgtable_page_ctor(pte)) { + __free_page(pte); + return NULL; + } + clear_highpage(pte); + } + return pte; +} + +static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) +{ + free_pages((unsigned long)pte, PTE_ORDER); +} + +static inline void pte_free(struct mm_struct *mm, struct page *pte) +{ + pgtable_page_dtor(pte); + __free_pages(pte, PTE_ORDER); +} + +#define __pte_free_tlb(tlb, pte, addr) \ + do { \ + pgtable_page_dtor(pte); \ + tlb_remove_page((tlb), (pte)); \ + } while (0) + +#define check_pgt_cache() do { } while (0) + +#endif /* _ASM_NIOS2_PGALLOC_H */ diff --git a/arch/nios2/include/asm/pgtable-bits.h b/arch/nios2/include/asm/pgtable-bits.h new file mode 100644 index 000000000000..ce9e7069aa96 --- /dev/null +++ b/arch/nios2/include/asm/pgtable-bits.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> + * Copyright (C) 2009 Wind River Systems Inc + * + * 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. + */ + +#ifndef _ASM_NIOS2_PGTABLE_BITS_H +#define _ASM_NIOS2_PGTABLE_BITS_H + +/* + * These are actual hardware defined protection bits in the tlbacc register + * which looks like this: + * + * 31 30 ... 26 25 24 23 22 21 20 19 18 ... 1 0 + * ignored........ C R W X G PFN............ + */ +#define _PAGE_GLOBAL (1<<20) +#define _PAGE_EXEC (1<<21) +#define _PAGE_WRITE (1<<22) +#define _PAGE_READ (1<<23) +#define _PAGE_CACHED (1<<24) /* C: data access cacheable */ + +/* + * Software defined bits. They are ignored by the hardware and always read back + * as zero, but can be written as non-zero. + */ +#define _PAGE_PRESENT (1<<25) /* PTE contains a translation */ +#define _PAGE_ACCESSED (1<<26) /* page referenced */ +#define _PAGE_DIRTY (1<<27) /* dirty page */ +#define _PAGE_FILE (1<<28) /* PTE used for file mapping or swap */ + +#endif /* _ASM_NIOS2_PGTABLE_BITS_H */ diff --git a/arch/nios2/include/asm/pgtable.h b/arch/nios2/include/asm/pgtable.h new file mode 100644 index 000000000000..ccbaffd47671 --- /dev/null +++ b/arch/nios2/include/asm/pgtable.h @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> + * Copyright (C) 2009 Wind River Systems Inc + * + * Based on asm/pgtable-32.h from mips which is: + * + * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 2003 Ralf Baechle + * Copyright (C) 1999, 2000, 2001 Silicon Graphics, Inc. + * + * 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. + */ + +#ifndef _ASM_NIOS2_PGTABLE_H +#define _ASM_NIOS2_PGTABLE_H + +#include <linux/io.h> +#include <linux/bug.h> +#include <asm/page.h> +#include <asm/cacheflush.h> +#include <asm/tlbflush.h> + +#include <asm/pgtable-bits.h> +#include <asm-generic/pgtable-nopmd.h> + +#define FIRST_USER_ADDRESS 0 + +#define VMALLOC_START CONFIG_NIOS2_KERNEL_MMU_REGION_BASE +#define VMALLOC_END (CONFIG_NIOS2_KERNEL_REGION_BASE - 1) + +struct mm_struct; + +/* Helper macro */ +#define MKP(x, w, r) __pgprot(_PAGE_PRESENT | _PAGE_CACHED | \ + ((x) ? _PAGE_EXEC : 0) | \ + ((r) ? _PAGE_READ : 0) | \ + ((w) ? _PAGE_WRITE : 0)) +/* + * These are the macros that generic kernel code needs + * (to populate protection_map[]) + */ + +/* Remove W bit on private pages for COW support */ +#define __P000 MKP(0, 0, 0) +#define __P001 MKP(0, 0, 1) +#define __P010 MKP(0, 0, 0) /* COW */ +#define __P011 MKP(0, 0, 1) /* COW */ +#define __P100 MKP(1, 0, 0) +#define __P101 MKP(1, 0, 1) +#define __P110 MKP(1, 0, 0) /* COW */ +#define __P111 MKP(1, 0, 1) /* COW */ + +/* Shared pages can have exact HW mapping */ +#define __S000 MKP(0, 0, 0) +#define __S001 MKP(0, 0, 1) +#define __S010 MKP(0, 1, 0) +#define __S011 MKP(0, 1, 1) +#define __S100 MKP(1, 0, 0) +#define __S101 MKP(1, 0, 1) +#define __S110 MKP(1, 1, 0) +#define __S111 MKP(1, 1, 1) + +/* Used all over the kernel */ +#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_CACHED | _PAGE_READ | \ + _PAGE_WRITE | _PAGE_EXEC | _PAGE_GLOBAL) + +#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_CACHED | _PAGE_READ | \ + _PAGE_WRITE | _PAGE_ACCESSED) + +#define PAGE_COPY MKP(0, 0, 1) + +#define PGD_ORDER 0 +#define PTE_ORDER 0 + +#define PTRS_PER_PGD ((PAGE_SIZE << PGD_ORDER) / sizeof(pgd_t)) +#define PTRS_PER_PTE ((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t)) + +#define USER_PTRS_PER_PGD \ + (CONFIG_NIOS2_KERNEL_MMU_REGION_BASE / PGDIR_SIZE) + +#define PGDIR_SHIFT 22 +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) + +/* + * ZERO_PAGE is a global shared page that is always zero: used + * for zero-mapped memory areas etc.. + */ +extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; +#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) + +extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; +extern pte_t invalid_pte_table[PAGE_SIZE/sizeof(pte_t)]; + +/* + * (pmds are folded into puds so this doesn't get actually called, + * but the define is needed for a generic inline function.) + */ +static inline void set_pmd(pmd_t *pmdptr, pmd_t pmdval) +{ + pmdptr->pud.pgd.pgd = pmdval.pud.pgd.pgd; +} + +/* to find an entry in a page-table-directory */ +#define pgd_index(addr) (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) +#define pgd_offset(mm, addr) ((mm)->pgd + pgd_index(addr)) + +static inline int pte_write(pte_t pte) \ + { return pte_val(pte) & _PAGE_WRITE; } +static inline int pte_dirty(pte_t pte) \ + { return pte_val(pte) & _PAGE_DIRTY; } +static inline int pte_young(pte_t pte) \ + { return pte_val(pte) & _PAGE_ACCESSED; } +static inline int pte_file(pte_t pte) \ + { return pte_val(pte) & _PAGE_FILE; } +static inline int pte_special(pte_t pte) { return 0; } + +#define pgprot_noncached pgprot_noncached + +static inline pgprot_t pgprot_noncached(pgprot_t _prot) +{ + unsigned long prot = pgprot_val(_prot); + + prot &= ~_PAGE_CACHED; + + return __pgprot(prot); +} + +static inline int pte_none(pte_t pte) +{ + return !(pte_val(pte) & ~(_PAGE_GLOBAL|0xf)); +} + +static inline int pte_present(pte_t pte) \ + { return pte_val(pte) & _PAGE_PRESENT; } + +/* + * The following only work if pte_present() is true. + * Undefined behaviour if not.. + */ +static inline pte_t pte_wrprotect(pte_t pte) +{ + pte_val(pte) &= ~_PAGE_WRITE; + return pte; +} + +static inline pte_t pte_mkclean(pte_t pte) +{ + pte_val(pte) &= ~_PAGE_DIRTY; + return pte; +} + +static inline pte_t pte_mkold(pte_t pte) +{ + pte_val(pte) &= ~_PAGE_ACCESSED; + return pte; +} + +static inline pte_t pte_mkwrite(pte_t pte) +{ + pte_val(pte) |= _PAGE_WRITE; + return pte; +} + +static inline pte_t pte_mkdirty(pte_t pte) +{ + pte_val(pte) |= _PAGE_DIRTY; + return pte; +} + +static inline pte_t pte_mkspecial(pte_t pte) { return pte; } + +static inline pte_t pte_mkyoung(pte_t pte) +{ + pte_val(pte) |= _PAGE_ACCESSED; + return pte; +} + +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +{ + const unsigned long mask = _PAGE_READ | _PAGE_WRITE | _PAGE_EXEC; + + pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask); + return pte; +} + +static inline int pmd_present(pmd_t pmd) +{ + return (pmd_val(pmd) != (unsigned long) invalid_pte_table) + && (pmd_val(pmd) != 0UL); +} + +static inline void pmd_clear(pmd_t *pmdp) +{ + pmd_val(*pmdp) = (unsigned long) invalid_pte_table; +} + +#define pte_pfn(pte) (pte_val(pte) & 0xfffff) +#define pfn_pte(pfn, prot) (__pte(pfn | pgprot_val(prot))) +#define pte_page(pte) (pfn_to_page(pte_pfn(pte))) + +/* + * Store a linux PTE into the linux page table. + */ +static inline void set_pte(pte_t *ptep, pte_t pteval) +{ + *ptep = pteval; +} + +static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, pte_t pteval) +{ + unsigned long paddr = page_to_virt(pte_page(pteval)); + + flush_dcache_range(paddr, paddr + PAGE_SIZE); + set_pte(ptep, pteval); +} + +static inline int pmd_none(pmd_t pmd) +{ + return (pmd_val(pmd) == + (unsigned long) invalid_pte_table) || (pmd_val(pmd) == 0UL); +} + +#define pmd_bad(pmd) (pmd_val(pmd) & ~PAGE_MASK) + +static inline void pte_clear(struct mm_struct *mm, + unsigned long addr, pte_t *ptep) +{ + pte_t null; + + pte_val(null) = (addr >> PAGE_SHIFT) & 0xf; + + set_pte_at(mm, addr, ptep, null); + flush_tlb_one(addr); +} + +/* + * 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)) + +#define pte_unmap(pte) do { } while (0) + +/* + * 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 pmd_phys(pmd) virt_to_phys((void *)pmd_val(pmd)) +#define pmd_page(pmd) (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT)) +#define pmd_page_vaddr(pmd) pmd_val(pmd) + +#define pte_offset_map(dir, addr) \ + ((pte_t *) page_address(pmd_page(*dir)) + \ + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))) + +/* to find an entry in a kernel page-table-directory */ +#define pgd_offset_k(addr) pgd_offset(&init_mm, addr) + +/* Get the address to the PTE for a vaddr in specific directory */ +#define pte_offset_kernel(dir, addr) \ + ((pte_t *) pmd_page_vaddr(*(dir)) + \ + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))) + +#define pte_ERROR(e) \ + pr_err("%s:%d: bad pte %08lx.\n", \ + __FILE__, __LINE__, pte_val(e)) +#define pgd_ERROR(e) \ + pr_err("%s:%d: bad pgd %08lx.\n", \ + __FILE__, __LINE__, pgd_val(e)) + +/* + * Encode and decode a swap entry (must be !pte_none(pte) && !pte_present(pte) + * && !pte_file(pte)): + * + * 31 30 29 28 27 26 25 24 23 22 21 20 19 18 ... 1 0 + * 0 0 0 0 type. 0 0 0 0 0 0 offset......... + * + * This gives us up to 2**2 = 4 swap files and 2**20 * 4K = 4G per swap file. + * + * Note that the offset field is always non-zero, thus !pte_none(pte) is always + * true. + */ +#define __swp_type(swp) (((swp).val >> 26) & 0x3) +#define __swp_offset(swp) ((swp).val & 0xfffff) +#define __swp_entry(type, off) ((swp_entry_t) { (((type) & 0x3) << 26) \ + | ((off) & 0xfffff) }) +#define __swp_entry_to_pte(swp) ((pte_t) { (swp).val }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) + +/* Encode and decode a nonlinear file mapping entry */ +#define PTE_FILE_MAX_BITS 25 +#define pte_to_pgoff(pte) (pte_val(pte) & 0x1ffffff) +#define pgoff_to_pte(off) __pte(((off) & 0x1ffffff) | _PAGE_FILE) + +#define kern_addr_valid(addr) (1) + +#include <asm-generic/pgtable.h> + +#define pgtable_cache_init() do { } while (0) + +extern void __init paging_init(void); +extern void __init mmu_init(void); + +extern void update_mmu_cache(struct vm_area_struct *vma, + unsigned long address, pte_t *pte); + +#endif /* _ASM_NIOS2_PGTABLE_H */ diff --git a/arch/nios2/include/asm/processor.h b/arch/nios2/include/asm/processor.h new file mode 100644 index 000000000000..3bd349473b06 --- /dev/null +++ b/arch/nios2/include/asm/processor.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2013 Altera Corporation + * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch> + * Copyright (C) 2004 Microtronix Datacom Ltd + * Copyright (C) 2001 Ken Hill (khill@microtronix.com) + * Vic Phillips (vic@microtronix.com) + * + * based on SPARC asm/processor_32.h which is: + * + * Copyright (C) 1994 David S. Miller + * + * 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. + */ + +#ifndef _ASM_NIOS2_PROCESSOR_H +#define _ASM_NIOS2_PROCESSOR_H + +#include <asm/ptrace.h> +#include <asm/registers.h> +#include <asm/page.h> + +#define NIOS2_FLAG_KTHREAD 0x00000001 /* task is a kernel thread */ + +#define NIOS2_OP_NOP 0x1883a +#define NIOS2_OP_BREAK 0x3da03a + +#ifdef __KERNEL__ + +#define STACK_TOP TASK_SIZE +#define STACK_TOP_MAX STACK_TOP + +#endif /* __KERNEL__ */ + +/* Kuser helpers is mapped to this user space address */ +#define KUSER_BASE 0x1000 +#define KUSER_SIZE (PAGE_SIZE) +#ifndef __ASSEMBLY__ + +/* + * Default implementation of macro that returns current + * instruction pointer ("program counter"). + */ +#define current_text_addr() ({ __label__ _l; _l: &&_l; }) + +# define TASK_SIZE 0x7FFF0000UL +# define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3)) + +/* The Nios processor specific thread struct. */ +struct thread_struct { + struct pt_regs *kregs; + + /* Context switch saved kernel state. */ + unsigned long ksp; + unsigned long kpsr; +}; + +#define INIT_MMAP \ + { &init_mm, (0), (0), __pgprot(0x0), VM_READ | VM_WRITE | VM_EXEC } + +# define INIT_THREAD { \ + .kregs = NULL, \ + .ksp = 0, \ + .kpsr = 0, \ +} + +extern void start_thread(struct pt_regs *regs, unsigned long pc, + unsigned long sp); + +struct task_struct; + +/* Free all resources held by a thread. */ +static inline void release_thread(struct task_struct *dead_task) +{ +} + +/* Free current thread data structures etc.. */ +static inline void exit_thread(void) +{ +} + +/* Return saved PC of a blocked thread. */ +#define thread_saved_pc(tsk) ((tsk)->thread.kregs->ea) + +extern unsigned long get_wchan(struct task_struct *p); + +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + +#define task_pt_regs(p) \ + ((struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1) + +/* Used by procfs */ +#define KSTK_EIP(tsk) ((tsk)->thread.kregs->ea) +#define KSTK_ESP(tsk) ((tsk)->thread.kregs->sp) + +#define cpu_relax() barrier() +#define cpu_relax_lowlatency() cpu_relax() + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_NIOS2_PROCESSOR_H */ diff --git a/arch/nios2/include/asm/ptrace.h b/arch/nios2/include/asm/ptrace.h new file mode 100644 index 000000000000..20fb1cf2dab6 --- /dev/null +++ b/arch/nios2/include/asm/ptrace.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2013 Altera Corporation + * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch> + * Copyright (C) 2004 Microtronix Datacom Ltd + * + * based on m68k asm/processor.h + * + * 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. + */ + +#ifndef _ASM_NIOS2_PTRACE_H +#define _ASM_NIOS2_PTRACE_H + +#include <uapi/asm/ptrace.h> + +#ifndef __ASSEMBLY__ +#define user_mode(regs) (((regs)->estatus & ESTATUS_EU)) + +#define instruction_pointer(regs) ((regs)->ra) +#define profile_pc(regs) instruction_pointer(regs) +#define user_stack_pointer(regs) ((regs)->sp) +extern void show_regs(struct pt_regs *); + +#define current_pt_regs() \ + ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE)\ + - 1) + +int do_syscall_trace_enter(void); +void do_syscall_trace_exit(void); +#endif /* __ASSEMBLY__ */ +#endif /* _ASM_NIOS2_PTRACE_H */ diff --git a/arch/nios2/include/asm/registers.h b/arch/nios2/include/asm/registers.h new file mode 100644 index 000000000000..615bce19b546 --- /dev/null +++ b/arch/nios2/include/asm/registers.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef _ASM_NIOS2_REGISTERS_H +#define _ASM_NIOS2_REGISTERS_H + +#ifndef __ASSEMBLY__ +#include <asm/cpuinfo.h> +#endif + +/* control register numbers */ +#define CTL_STATUS 0 +#define CTL_ESTATUS 1 +#define CTL_BSTATUS 2 +#define CTL_IENABLE 3 +#define CTL_IPENDING 4 +#define CTL_CPUID 5 +#define CTL_RSV1 6 +#define CTL_EXCEPTION 7 +#define CTL_PTEADDR 8 +#define CTL_TLBACC 9 +#define CTL_TLBMISC 10 +#define CTL_RSV2 11 +#define CTL_BADADDR 12 +#define CTL_CONFIG 13 +#define CTL_MPUBASE 14 +#define CTL_MPUACC 15 + +/* access control registers using GCC builtins */ +#define RDCTL(r) __builtin_rdctl(r) +#define WRCTL(r, v) __builtin_wrctl(r, v) + +/* status register bits */ +#define STATUS_PIE (1 << 0) /* processor interrupt enable */ +#define STATUS_U (1 << 1) /* user mode */ +#define STATUS_EH (1 << 2) /* Exception mode */ + +/* estatus register bits */ +#define ESTATUS_EPIE (1 << 0) /* processor interrupt enable */ +#define ESTATUS_EU (1 << 1) /* user mode */ +#define ESTATUS_EH (1 << 2) /* Exception mode */ + +/* tlbmisc register bits */ +#define TLBMISC_PID_SHIFT 4 +#ifndef __ASSEMBLY__ +#define TLBMISC_PID_MASK ((1UL << cpuinfo.tlb_pid_num_bits) - 1) +#endif +#define TLBMISC_WAY_MASK 0xf +#define TLBMISC_WAY_SHIFT 20 + +#define TLBMISC_PID (TLBMISC_PID_MASK << TLBMISC_PID_SHIFT) /* TLB PID */ +#define TLBMISC_WE (1 << 18) /* TLB write enable */ +#define TLBMISC_RD (1 << 19) /* TLB read */ +#define TLBMISC_WAY (TLBMISC_WAY_MASK << TLBMISC_WAY_SHIFT) /* TLB way */ + +#endif /* _ASM_NIOS2_REGISTERS_H */ diff --git a/arch/nios2/include/asm/setup.h b/arch/nios2/include/asm/setup.h new file mode 100644 index 000000000000..dcbf8cf1a344 --- /dev/null +++ b/arch/nios2/include/asm/setup.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef _ASM_NIOS2_SETUP_H +#define _ASM_NIOS2_SETUP_H + +#include <asm-generic/setup.h> + +#ifndef __ASSEMBLY__ +#ifdef __KERNEL__ + +extern char exception_handler_hook[]; +extern char fast_handler[]; +extern char fast_handler_end[]; + +extern void pagetable_init(void); + +extern void setup_early_printk(void); + +#endif/* __KERNEL__ */ +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_NIOS2_SETUP_H */ diff --git a/arch/nios2/include/asm/signal.h b/arch/nios2/include/asm/signal.h new file mode 100644 index 000000000000..bbcf11eecb01 --- /dev/null +++ b/arch/nios2/include/asm/signal.h @@ -0,0 +1,22 @@ +/* + * Copyright Altera Corporation (C) 2013. All rights reserved + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + * + */ +#ifndef _NIOS2_SIGNAL_H +#define _NIOS2_SIGNAL_H + +#include <uapi/asm/signal.h> + +#endif /* _NIOS2_SIGNAL_H */ diff --git a/arch/nios2/include/asm/string.h b/arch/nios2/include/asm/string.h new file mode 100644 index 000000000000..14dd570d64f7 --- /dev/null +++ b/arch/nios2/include/asm/string.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2004 Microtronix Datacom Ltd + * + * 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. + */ + +#ifndef _ASM_NIOS2_STRING_H +#define _ASM_NIOS2_STRING_H + +#ifdef __KERNEL__ + +#define __HAVE_ARCH_MEMSET +#define __HAVE_ARCH_MEMCPY +#define __HAVE_ARCH_MEMMOVE + +extern void *memset(void *s, int c, size_t count); +extern void *memcpy(void *d, const void *s, size_t count); +extern void *memmove(void *d, const void *s, size_t count); + +#endif /* __KERNEL__ */ + +#endif /* _ASM_NIOS2_STRING_H */ diff --git a/arch/nios2/include/asm/switch_to.h b/arch/nios2/include/asm/switch_to.h new file mode 100644 index 000000000000..c47b3f4afbcd --- /dev/null +++ b/arch/nios2/include/asm/switch_to.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2004 Microtronix Datacom Ltd. + * + * 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. + */ +#ifndef _ASM_NIOS2_SWITCH_TO_H +#define _ASM_NIOS2_SWITCH_TO_H + +/* + * switch_to(n) should switch tasks to task ptr, first checking that + * ptr isn't the current task, in which case it does nothing. This + * also clears the TS-flag if the task we switched to has used the + * math co-processor latest. + */ +#define switch_to(prev, next, last) \ +{ \ + void *_last; \ + __asm__ __volatile__ ( \ + "mov r4, %1\n" \ + "mov r5, %2\n" \ + "call resume\n" \ + "mov %0,r4\n" \ + : "=r" (_last) \ + : "r" (prev), "r" (next) \ + : "r4", "r5", "r7", "r8", "ra"); \ + (last) = _last; \ +} + +#endif /* _ASM_NIOS2_SWITCH_TO_H */ diff --git a/arch/nios2/include/asm/syscall.h b/arch/nios2/include/asm/syscall.h new file mode 100644 index 000000000000..9de220854c4a --- /dev/null +++ b/arch/nios2/include/asm/syscall.h @@ -0,0 +1,138 @@ +/* + * Copyright Altera Corporation (C) <2014>. All rights reserved + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __ASM_NIOS2_SYSCALL_H__ +#define __ASM_NIOS2_SYSCALL_H__ + +#include <linux/err.h> +#include <linux/sched.h> + +static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs) +{ + return regs->r2; +} + +static inline void syscall_rollback(struct task_struct *task, + struct pt_regs *regs) +{ + regs->r2 = regs->orig_r2; + regs->r7 = regs->orig_r7; +} + +static inline long syscall_get_error(struct task_struct *task, + struct pt_regs *regs) +{ + return regs->r7 ? regs->r2 : 0; +} + +static inline long syscall_get_return_value(struct task_struct *task, + struct pt_regs *regs) +{ + return regs->r2; +} + +static inline void syscall_set_return_value(struct task_struct *task, + struct pt_regs *regs, int error, long val) +{ + if (error) { + /* error < 0, but nios2 uses > 0 return value */ + regs->r2 = -error; + regs->r7 = 1; + } else { + regs->r2 = val; + regs->r7 = 0; + } +} + +static inline void syscall_get_arguments(struct task_struct *task, + struct pt_regs *regs, unsigned int i, unsigned int n, + unsigned long *args) +{ + BUG_ON(i + n > 6); + + switch (i) { + case 0: + if (!n--) + break; + *args++ = regs->r4; + case 1: + if (!n--) + break; + *args++ = regs->r5; + case 2: + if (!n--) + break; + *args++ = regs->r6; + case 3: + if (!n--) + break; + *args++ = regs->r7; + case 4: + if (!n--) + break; + *args++ = regs->r8; + case 5: + if (!n--) + break; + *args++ = regs->r9; + case 6: + if (!n--) + break; + default: + BUG(); + } +} + +static inline void syscall_set_arguments(struct task_struct *task, + struct pt_regs *regs, unsigned int i, unsigned int n, + const unsigned long *args) +{ + BUG_ON(i + n > 6); + + switch (i) { + case 0: + if (!n--) + break; + regs->r4 = *args++; + case 1: + if (!n--) + break; + regs->r5 = *args++; + case 2: + if (!n--) + break; + regs->r6 = *args++; + case 3: + if (!n--) + break; + regs->r7 = *args++; + case 4: + if (!n--) + break; + regs->r8 = *args++; + case 5: + if (!n--) + break; + regs->r9 = *args++; + case 6: + if (!n) + break; + default: + BUG(); + } +} + +#endif diff --git a/arch/nios2/include/asm/syscalls.h b/arch/nios2/include/asm/syscalls.h new file mode 100644 index 000000000000..0245d780351b --- /dev/null +++ b/arch/nios2/include/asm/syscalls.h @@ -0,0 +1,25 @@ +/* + * Copyright Altera Corporation (C) 2013. All rights reserved + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + * + */ +#ifndef __ASM_NIOS2_SYSCALLS_H +#define __ASM_NIOS2_SYSCALLS_H + +int sys_cacheflush(unsigned long addr, unsigned long len, + unsigned int op); + +#include <asm-generic/syscalls.h> + +#endif /* __ASM_NIOS2_SYSCALLS_H */ diff --git a/arch/nios2/include/asm/thread_info.h b/arch/nios2/include/asm/thread_info.h new file mode 100644 index 000000000000..1f266575beb5 --- /dev/null +++ b/arch/nios2/include/asm/thread_info.h @@ -0,0 +1,120 @@ +/* + * NiosII low-level thread information + * + * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> + * Copyright (C) 2004 Microtronix Datacom Ltd. + * + * Based on asm/thread_info_no.h from m68k which is: + * + * Copyright (C) 2002 David Howells <dhowells@redhat.com> + * + * 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. + */ + +#ifndef _ASM_NIOS2_THREAD_INFO_H +#define _ASM_NIOS2_THREAD_INFO_H + +#ifdef __KERNEL__ + +/* + * Size of the kernel stack for each process. + */ +#define THREAD_SIZE_ORDER 1 +#define THREAD_SIZE 8192 /* 2 * PAGE_SIZE */ + +#ifndef __ASSEMBLY__ + +typedef struct { + unsigned long seg; +} mm_segment_t; + +/* + * low level task data that entry.S needs immediate access to + * - this struct should fit entirely inside of one cache line + * - this struct shares the supervisor stack pages + * - if the contents of this structure are changed, the assembly constants + * must also be changed + */ +struct thread_info { + struct task_struct *task; /* main task structure */ + struct exec_domain *exec_domain; /* execution domain */ + unsigned long flags; /* low level flags */ + __u32 cpu; /* current CPU */ + int preempt_count; /* 0 => preemptable,<0 => BUG */ + mm_segment_t addr_limit; /* thread address space: + 0-0x7FFFFFFF for user-thead + 0-0xFFFFFFFF for kernel-thread + */ + struct restart_block restart_block; + struct pt_regs *regs; +}; + +/* + * macros/functions for gaining access to the thread information structure + * + * preempt_count needs to be 1 initially, until the scheduler is functional. + */ +#define INIT_THREAD_INFO(tsk) \ +{ \ + .task = &tsk, \ + .exec_domain = &default_exec_domain, \ + .flags = 0, \ + .cpu = 0, \ + .preempt_count = INIT_PREEMPT_COUNT, \ + .addr_limit = KERNEL_DS, \ + .restart_block = { \ + .fn = do_no_restart_syscall, \ + }, \ +} + +#define init_thread_info (init_thread_union.thread_info) +#define init_stack (init_thread_union.stack) + +/* how to get the thread information struct from C */ +static inline struct thread_info *current_thread_info(void) +{ + register unsigned long sp asm("sp"); + + return (struct thread_info *)(sp & ~(THREAD_SIZE - 1)); +} +#endif /* !__ASSEMBLY__ */ + +/* + * thread information flags + * - these are process state flags that various assembly files may need to + * access + * - pending work-to-be-done flags are in LSW + * - other flags in MSW + */ +#define TIF_SYSCALL_TRACE 0 /* syscall trace active */ +#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */ +#define TIF_SIGPENDING 2 /* signal pending */ +#define TIF_NEED_RESCHED 3 /* rescheduling necessary */ +#define TIF_MEMDIE 4 /* is terminating due to OOM killer */ +#define TIF_SECCOMP 5 /* secure computing */ +#define TIF_SYSCALL_AUDIT 6 /* syscall auditing active */ +#define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */ + +#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling + TIF_NEED_RESCHED */ + +#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) +#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) +#define _TIF_SIGPENDING (1 << TIF_SIGPENDING) +#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) +#define _TIF_SECCOMP (1 << TIF_SECCOMP) +#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) +#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) +#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) + +/* work to do on interrupt/exception return */ +#define _TIF_WORK_MASK 0x0000FFFE + +/* work to do on any return to u-space */ +# define _TIF_ALLWORK_MASK 0x0000FFFF + +#endif /* __KERNEL__ */ + +#endif /* _ASM_NIOS2_THREAD_INFO_H */ diff --git a/arch/nios2/include/asm/timex.h b/arch/nios2/include/asm/timex.h new file mode 100644 index 000000000000..2f2abb28ec2f --- /dev/null +++ b/arch/nios2/include/asm/timex.h @@ -0,0 +1,24 @@ +/* Copyright Altera Corporation (C) 2014. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef _ASM_NIOS2_TIMEX_H +#define _ASM_NIOS2_TIMEX_H + +typedef unsigned long cycles_t; + +extern cycles_t get_cycles(void); + +#endif diff --git a/arch/nios2/include/asm/tlb.h b/arch/nios2/include/asm/tlb.h new file mode 100644 index 000000000000..d3bc648e08b5 --- /dev/null +++ b/arch/nios2/include/asm/tlb.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch> + * Copyright (C) 2009 Wind River Systems Inc + * Copyright (C) 2004 Microtronix Datacom Ltd. + * + * 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. + */ + +#ifndef _ASM_NIOS2_TLB_H +#define _ASM_NIOS2_TLB_H + +#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) + +extern void set_mmu_pid(unsigned long pid); + +/* + * NiosII doesn't need any special per-pte or per-vma handling, except + * we need to flush cache for the area to be unmapped. + */ +#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 { } while (0) +#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0) + +#include <linux/pagemap.h> +#include <asm-generic/tlb.h> + +#endif /* _ASM_NIOS2_TLB_H */ diff --git a/arch/nios2/include/asm/tlbflush.h b/arch/nios2/include/asm/tlbflush.h new file mode 100644 index 000000000000..e19652fca1c6 --- /dev/null +++ b/arch/nios2/include/asm/tlbflush.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef _ASM_NIOS2_TLBFLUSH_H +#define _ASM_NIOS2_TLBFLUSH_H + +struct mm_struct; + +/* + * TLB flushing: + * + * - flush_tlb_all() flushes all processes TLB entries + * - flush_tlb_mm(mm) flushes the specified mm context TLB entries + * - flush_tlb_page(vma, vmaddr) flushes one page + * - flush_tlb_range(vma, start, end) flushes a range of pages + * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages + */ +extern void flush_tlb_all(void); +extern void flush_tlb_mm(struct mm_struct *mm); +extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end); +extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); +extern void flush_tlb_one(unsigned long vaddr); + +static inline void flush_tlb_page(struct vm_area_struct *vma, + unsigned long addr) +{ + flush_tlb_one(addr); +} + +#endif /* _ASM_NIOS2_TLBFLUSH_H */ diff --git a/arch/nios2/include/asm/traps.h b/arch/nios2/include/asm/traps.h new file mode 100644 index 000000000000..82a48473280d --- /dev/null +++ b/arch/nios2/include/asm/traps.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch> + * Copyright (C) 2004 Microtronix Datacom Ltd. + * + * 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. + */ + +#ifndef _ASM_NIOS2_TRAPS_H +#define _ASM_NIOS2_TRAPS_H + +#define TRAP_ID_SYSCALL 0 + +#ifndef __ASSEMBLY__ +void _exception(int signo, struct pt_regs *regs, int code, unsigned long addr); +#endif + +#endif /* _ASM_NIOS2_TRAPS_H */ diff --git a/arch/nios2/include/asm/uaccess.h b/arch/nios2/include/asm/uaccess.h new file mode 100644 index 000000000000..acedc0a2860e --- /dev/null +++ b/arch/nios2/include/asm/uaccess.h @@ -0,0 +1,231 @@ +/* + * User space memory access functions for Nios II + * + * Copyright (C) 2010-2011, Tobias Klauser <tklauser@distanz.ch> + * Copyright (C) 2009, Wind River Systems Inc + * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com + * + * 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. + */ + +#ifndef _ASM_NIOS2_UACCESS_H +#define _ASM_NIOS2_UACCESS_H + +#include <linux/errno.h> +#include <linux/thread_info.h> +#include <linux/string.h> + +#include <asm/page.h> + +#define VERIFY_READ 0 +#define VERIFY_WRITE 1 + +/* + * 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; + unsigned long fixup; +}; + +extern int fixup_exception(struct pt_regs *regs); + +/* + * Segment stuff + */ +#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) +#define USER_DS MAKE_MM_SEG(0x80000000UL) +#define KERNEL_DS MAKE_MM_SEG(0) + +#define get_ds() (KERNEL_DS) + +#define get_fs() (current_thread_info()->addr_limit) +#define set_fs(seg) (current_thread_info()->addr_limit = (seg)) + +#define segment_eq(a, b) ((a).seg == (b).seg) + +#define __access_ok(addr, len) \ + (((signed long)(((long)get_fs().seg) & \ + ((long)(addr) | (((long)(addr)) + (len)) | (len)))) == 0) + +#define access_ok(type, addr, len) \ + likely(__access_ok((unsigned long)(addr), (unsigned long)(len))) + +# define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n" + +/* + * Zero Userspace + */ + +static inline unsigned long __must_check __clear_user(void __user *to, + unsigned long n) +{ + __asm__ __volatile__ ( + "1: stb zero, 0(%1)\n" + " addi %0, %0, -1\n" + " addi %1, %1, 1\n" + " bne %0, zero, 1b\n" + "2:\n" + __EX_TABLE_SECTION + ".word 1b, 2b\n" + ".previous\n" + : "=r" (n), "=r" (to) + : "0" (n), "1" (to) + ); + + return n; +} + +static inline unsigned long __must_check clear_user(void __user *to, + unsigned long n) +{ + if (!access_ok(VERIFY_WRITE, to, n)) + return n; + return __clear_user(to, n); +} + +extern long __copy_from_user(void *to, const void __user *from, + unsigned long n); +extern long __copy_to_user(void __user *to, const void *from, unsigned long n); + +static inline long copy_from_user(void *to, const void __user *from, + unsigned long n) +{ + if (!access_ok(VERIFY_READ, from, n)) + return n; + return __copy_from_user(to, from, n); +} + +static inline long copy_to_user(void __user *to, const void *from, + unsigned long n) +{ + if (!access_ok(VERIFY_WRITE, to, n)) + return n; + return __copy_to_user(to, from, n); +} + +extern long strncpy_from_user(char *__to, const char __user *__from, + long __len); +extern long strnlen_user(const char __user *s, long n); + +#define __copy_from_user_inatomic __copy_from_user +#define __copy_to_user_inatomic __copy_to_user + +/* Optimized macros */ +#define __get_user_asm(val, insn, addr, err) \ +{ \ + __asm__ __volatile__( \ + " movi %0, %3\n" \ + "1: " insn " %1, 0(%2)\n" \ + " movi %0, 0\n" \ + "2:\n" \ + " .section __ex_table,\"a\"\n" \ + " .word 1b, 2b\n" \ + " .previous" \ + : "=&r" (err), "=r" (val) \ + : "r" (addr), "i" (-EFAULT)); \ +} + +#define __get_user_unknown(val, size, ptr, err) do { \ + err = 0; \ + if (copy_from_user(&(val), ptr, size)) { \ + err = -EFAULT; \ + } \ + } while (0) + +#define __get_user_common(val, size, ptr, err) \ +do { \ + switch (size) { \ + case 1: \ + __get_user_asm(val, "ldbu", ptr, err); \ + break; \ + case 2: \ + __get_user_asm(val, "ldhu", ptr, err); \ + break; \ + case 4: \ + __get_user_asm(val, "ldw", ptr, err); \ + break; \ + default: \ + __get_user_unknown(val, size, ptr, err); \ + break; \ + } \ +} while (0) + +#define __get_user(x, ptr) \ + ({ \ + long __gu_err = -EFAULT; \ + const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ + unsigned long __gu_val; \ + __get_user_common(__gu_val, sizeof(*(ptr)), __gu_ptr, __gu_err);\ + (x) = (__typeof__(x))__gu_val; \ + __gu_err; \ + }) + +#define get_user(x, ptr) \ +({ \ + long __gu_err = -EFAULT; \ + const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ + unsigned long __gu_val = 0; \ + if (access_ok(VERIFY_READ, __gu_ptr, sizeof(*__gu_ptr))) \ + __get_user_common(__gu_val, sizeof(*__gu_ptr), \ + __gu_ptr, __gu_err); \ + (x) = (__typeof__(x))__gu_val; \ + __gu_err; \ +}) + +#define __put_user_asm(val, insn, ptr, err) \ +{ \ + __asm__ __volatile__( \ + " movi %0, %3\n" \ + "1: " insn " %1, 0(%2)\n" \ + " movi %0, 0\n" \ + "2:\n" \ + " .section __ex_table,\"a\"\n" \ + " .word 1b, 2b\n" \ + " .previous\n" \ + : "=&r" (err) \ + : "r" (val), "r" (ptr), "i" (-EFAULT)); \ +} + +#define put_user(x, ptr) \ +({ \ + long __pu_err = -EFAULT; \ + __typeof__(*(ptr)) __user *__pu_ptr = (ptr); \ + __typeof__(*(ptr)) __pu_val = (__typeof(*ptr))(x); \ + if (access_ok(VERIFY_WRITE, __pu_ptr, sizeof(*__pu_ptr))) { \ + switch (sizeof(*__pu_ptr)) { \ + case 1: \ + __put_user_asm(__pu_val, "stb", __pu_ptr, __pu_err); \ + break; \ + case 2: \ + __put_user_asm(__pu_val, "sth", __pu_ptr, __pu_err); \ + break; \ + case 4: \ + __put_user_asm(__pu_val, "stw", __pu_ptr, __pu_err); \ + break; \ + default: \ + /* XXX: This looks wrong... */ \ + __pu_err = 0; \ + if (copy_to_user(__pu_ptr, &(__pu_val), \ + sizeof(*__pu_ptr))) \ + __pu_err = -EFAULT; \ + break; \ + } \ + } \ + __pu_err; \ +}) + +#define __put_user(x, ptr) put_user(x, ptr) + +#endif /* _ASM_NIOS2_UACCESS_H */ diff --git a/arch/nios2/include/asm/ucontext.h b/arch/nios2/include/asm/ucontext.h new file mode 100644 index 000000000000..2c87614b0f6e --- /dev/null +++ b/arch/nios2/include/asm/ucontext.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch> + * Copyright (C) 2004 Microtronix Datacom Ltd + * + * 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. + */ + +#ifndef _ASM_NIOS2_UCONTEXT_H +#define _ASM_NIOS2_UCONTEXT_H + +typedef int greg_t; +#define NGREG 32 +typedef greg_t gregset_t[NGREG]; + +struct mcontext { + int version; + gregset_t gregs; +}; + +#define MCONTEXT_VERSION 2 + +struct ucontext { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + struct mcontext uc_mcontext; + sigset_t uc_sigmask; /* mask last for extensibility */ +}; + +#endif |