aboutsummaryrefslogtreecommitdiffstats
path: root/arch/hexagon
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-01 10:43:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-01 10:43:05 -0400
commitd70b1e06eb331afe1576ac23bb9523708026ba1f (patch)
treea6e430d45f8f7f37285369dcfd863a0358080c83 /arch/hexagon
parentb0b885657b6c8ef63a46bc9299b2a7715d19acde (diff)
parent426d29ccb2a8d44c18d3167327ee82b38287e7bf (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rkuo/linux-hexagon-kernel
Pull Hexagon fixes from Richard Kuo: "Changes for the Hexagon architecture (and one touching OpenRISC). They include various fixes to make use of additional arch features and cleanups. The largest functional change is a cleanup of the signal and event return paths" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rkuo/linux-hexagon-kernel: (32 commits) Hexagon: add v4 CS regs to core copyout macro Hexagon: use correct translation for VMALLOC_START Hexagon: use correct translations for DMA mappings Hexagon: fix return value for notify_resume case in do_work_pending Hexagon: fix signal number for user mem faults Hexagon: remove two Kconfig entries arch: remove CONFIG_GENERIC_FIND_NEXT_BIT again Hexagon: update copyright dates Hexagon: add translation types for __vmnewmap Hexagon: fix signal.c compile error Hexagon: break up user fn/arg register setting Hexagon: use generic sys_fork, sys_vfork, and sys_clone Hexagon: fix psp/sp macro Hexagon: fix up int enable/disable at ret_from_fork Hexagon: add IOMEM and _relaxed IO macros Hexagon: switch to using the device type for IO mappings Hexagon: don't print info for offline CPU's Hexagon: add support for single-stepping (v4+) Hexagon: use correct work mask when checking for more work Hexagon: add support for additional exceptions ...
Diffstat (limited to 'arch/hexagon')
-rw-r--r--arch/hexagon/Kconfig33
-rw-r--r--arch/hexagon/Makefile17
-rw-r--r--arch/hexagon/include/asm/Kbuild2
-rw-r--r--arch/hexagon/include/asm/atomic.h22
-rw-r--r--arch/hexagon/include/asm/elf.h23
-rw-r--r--arch/hexagon/include/asm/hexagon_vm.h56
-rw-r--r--arch/hexagon/include/asm/io.h16
-rw-r--r--arch/hexagon/include/asm/mem-layout.h28
-rw-r--r--arch/hexagon/include/asm/page.h12
-rw-r--r--arch/hexagon/include/asm/processor.h51
-rw-r--r--arch/hexagon/include/asm/vm_mmu.h11
-rw-r--r--arch/hexagon/include/uapi/asm/ptrace.h5
-rw-r--r--arch/hexagon/include/uapi/asm/registers.h17
-rw-r--r--arch/hexagon/include/uapi/asm/signal.h4
-rw-r--r--arch/hexagon/include/uapi/asm/unistd.h3
-rw-r--r--arch/hexagon/include/uapi/asm/user.h6
-rw-r--r--arch/hexagon/kernel/Makefile2
-rw-r--r--arch/hexagon/kernel/asm-offsets.c5
-rw-r--r--arch/hexagon/kernel/dma.c27
-rw-r--r--arch/hexagon/kernel/head.S107
-rw-r--r--arch/hexagon/kernel/kgdb.c4
-rw-r--r--arch/hexagon/kernel/process.c42
-rw-r--r--arch/hexagon/kernel/ptrace.c26
-rw-r--r--arch/hexagon/kernel/setup.c9
-rw-r--r--arch/hexagon/kernel/signal.c45
-rw-r--r--arch/hexagon/kernel/topology.c52
-rw-r--r--arch/hexagon/kernel/traps.c36
-rw-r--r--arch/hexagon/kernel/vm_entry.S282
-rw-r--r--arch/hexagon/kernel/vm_events.c4
-rw-r--r--arch/hexagon/kernel/vm_vectors.S4
-rw-r--r--arch/hexagon/kernel/vmlinux.lds.S12
-rw-r--r--arch/hexagon/mm/init.c35
-rw-r--r--arch/hexagon/mm/vm_fault.c4
33 files changed, 659 insertions, 343 deletions
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
index e4decc6b8947..04dff5bdcbf7 100644
--- a/arch/hexagon/Kconfig
+++ b/arch/hexagon/Kconfig
@@ -29,21 +29,17 @@ config HEXAGON
29 select GENERIC_CLOCKEVENTS 29 select GENERIC_CLOCKEVENTS
30 select GENERIC_CLOCKEVENTS_BROADCAST 30 select GENERIC_CLOCKEVENTS_BROADCAST
31 select MODULES_USE_ELF_RELA 31 select MODULES_USE_ELF_RELA
32 select GENERIC_CPU_DEVICES
33 select GENERIC_KERNEL_THREAD
34 select GENERIC_KERNEL_EXECVE
32 ---help--- 35 ---help---
33 Qualcomm Hexagon is a processor architecture designed for high 36 Qualcomm Hexagon is a processor architecture designed for high
34 performance and low power across a wide variety of applications. 37 performance and low power across a wide variety of applications.
35 38
36config HEXAGON_ARCH_V1 39config HEXAGON_PHYS_OFFSET
37 bool 40 def_bool y
38 41 ---help---
39config HEXAGON_ARCH_V2 42 Platforms that don't load the kernel at zero set this.
40 bool
41
42config HEXAGON_ARCH_V3
43 bool
44
45config HEXAGON_ARCH_V4
46 bool
47 43
48config FRAME_POINTER 44config FRAME_POINTER
49 def_bool y 45 def_bool y
@@ -81,9 +77,6 @@ config RWSEM_GENERIC_SPINLOCK
81config RWSEM_XCHGADD_ALGORITHM 77config RWSEM_XCHGADD_ALGORITHM
82 def_bool y 78 def_bool y
83 79
84config GENERIC_FIND_NEXT_BIT
85 def_bool y
86
87config GENERIC_HWEIGHT 80config GENERIC_HWEIGHT
88 def_bool y 81 def_bool y
89 82
@@ -103,14 +96,14 @@ choice
103 96
104config HEXAGON_COMET 97config HEXAGON_COMET
105 bool "Comet Board" 98 bool "Comet Board"
106 select HEXAGON_ARCH_V2
107 ---help--- 99 ---help---
108 Support for the Comet platform. 100 Support for the Comet platform.
109 101
110endchoice 102endchoice
111 103
112config HEXAGON_VM 104config HEXAGON_ARCH_VERSION
113 def_bool y 105 int "Architecture version"
106 default 2
114 107
115config CMDLINE 108config CMDLINE
116 string "Default kernel command string" 109 string "Default kernel command string"
@@ -122,12 +115,6 @@ config CMDLINE
122 minimum, you should specify the memory size and the root device 115 minimum, you should specify the memory size and the root device
123 (e.g., mem=64M root=/dev/nfs). 116 (e.g., mem=64M root=/dev/nfs).
124 117
125config HEXAGON_ANGEL_TRAPS
126 bool "Use Angel Traps"
127 default n
128 ---help---
129 Enable angel debug traps (for printk's).
130
131config SMP 118config SMP
132 bool "Multi-Processing support" 119 bool "Multi-Processing support"
133 ---help--- 120 ---help---
diff --git a/arch/hexagon/Makefile b/arch/hexagon/Makefile
index d00d900b2566..207711a0fd0c 100644
--- a/arch/hexagon/Makefile
+++ b/arch/hexagon/Makefile
@@ -15,20 +15,9 @@ KBUILD_CFLAGS += -fno-short-enums
15# LDFLAGS_MODULE += -shared 15# LDFLAGS_MODULE += -shared
16CFLAGS_MODULE += -mlong-calls 16CFLAGS_MODULE += -mlong-calls
17 17
18cflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1) 18cflags-y += $(call cc-option,-mv${CONFIG_HEXAGON_ARCH_VERSION})
19cflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2) 19aflags-y += $(call cc-option,-mv${CONFIG_HEXAGON_ARCH_VERSION})
20cflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3) 20ldflags-y += $(call cc-option,-mv${CONFIG_HEXAGON_ARCH_VERSION})
21cflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
22
23aflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
24aflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
25aflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
26aflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
27
28ldflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1)
29ldflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2)
30ldflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3)
31ldflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4)
32 21
33KBUILD_CFLAGS += $(cflags-y) 22KBUILD_CFLAGS += $(cflags-y)
34KBUILD_AFLAGS += $(aflags-y) 23KBUILD_AFLAGS += $(aflags-y)
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index bdb54ceb53bc..1da17caac23c 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -25,7 +25,6 @@ generic-y += kdebug.h
25generic-y += kmap_types.h 25generic-y += kmap_types.h
26generic-y += local64.h 26generic-y += local64.h
27generic-y += local.h 27generic-y += local.h
28generic-y += local.h
29generic-y += mman.h 28generic-y += mman.h
30generic-y += msgbuf.h 29generic-y += msgbuf.h
31generic-y += pci.h 30generic-y += pci.h
@@ -41,6 +40,7 @@ generic-y += sembuf.h
41generic-y += shmbuf.h 40generic-y += shmbuf.h
42generic-y += shmparam.h 41generic-y += shmparam.h
43generic-y += siginfo.h 42generic-y += siginfo.h
43generic-y += sizes.h
44generic-y += socket.h 44generic-y += socket.h
45generic-y += sockios.h 45generic-y += sockios.h
46generic-y += statfs.h 46generic-y += statfs.h
diff --git a/arch/hexagon/include/asm/atomic.h b/arch/hexagon/include/asm/atomic.h
index 468fbb0781cd..8a64ff2337f6 100644
--- a/arch/hexagon/include/asm/atomic.h
+++ b/arch/hexagon/include/asm/atomic.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * Atomic operations for the Hexagon architecture 2 * Atomic operations for the Hexagon architecture
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
5 * 5 *
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -117,35 +117,37 @@ static inline int atomic_sub_return(int i, atomic_t *v)
117#define atomic_sub(i, v) atomic_sub_return(i, (v)) 117#define atomic_sub(i, v) atomic_sub_return(i, (v))
118 118
119/** 119/**
120 * atomic_add_unless - add unless the number is a given value 120 * __atomic_add_unless - add unless the number is a given value
121 * @v: pointer to value 121 * @v: pointer to value
122 * @a: amount to add 122 * @a: amount to add
123 * @u: unless value is equal to u 123 * @u: unless value is equal to u
124 * 124 *
125 * Returns 1 if the add happened, 0 if it didn't. 125 * Returns old value.
126 *
126 */ 127 */
128
127static inline int __atomic_add_unless(atomic_t *v, int a, int u) 129static inline int __atomic_add_unless(atomic_t *v, int a, int u)
128{ 130{
129 int output, __oldval; 131 int __oldval;
132 register int tmp;
133
130 asm volatile( 134 asm volatile(
131 "1: %0 = memw_locked(%2);" 135 "1: %0 = memw_locked(%2);"
132 " {" 136 " {"
133 " p3 = cmp.eq(%0, %4);" 137 " p3 = cmp.eq(%0, %4);"
134 " if (p3.new) jump:nt 2f;" 138 " if (p3.new) jump:nt 2f;"
135 " %0 = add(%0, %3);" 139 " %1 = add(%0, %3);"
136 " %1 = #0;"
137 " }" 140 " }"
138 " memw_locked(%2, p3) = %0;" 141 " memw_locked(%2, p3) = %1;"
139 " {" 142 " {"
140 " if !p3 jump 1b;" 143 " if !p3 jump 1b;"
141 " %1 = #1;"
142 " }" 144 " }"
143 "2:" 145 "2:"
144 : "=&r" (__oldval), "=&r" (output) 146 : "=&r" (__oldval), "=&r" (tmp)
145 : "r" (v), "r" (a), "r" (u) 147 : "r" (v), "r" (a), "r" (u)
146 : "memory", "p3" 148 : "memory", "p3"
147 ); 149 );
148 return output; 150 return __oldval;
149} 151}
150 152
151#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) 153#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
diff --git a/arch/hexagon/include/asm/elf.h b/arch/hexagon/include/asm/elf.h
index 1f14e082588e..e1b933a0e121 100644
--- a/arch/hexagon/include/asm/elf.h
+++ b/arch/hexagon/include/asm/elf.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * ELF definitions for the Hexagon architecture 2 * ELF definitions for the Hexagon architecture
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and 7 * it under the terms of the GNU General Public License version 2 and
@@ -104,6 +104,16 @@ typedef unsigned long elf_fpregset_t;
104 * Bypass the whole "regsets" thing for now and use the define. 104 * Bypass the whole "regsets" thing for now and use the define.
105 */ 105 */
106 106
107#if CONFIG_HEXAGON_ARCH_VERSION >= 4
108#define CS_COPYREGS(DEST,REGS) \
109do {\
110 DEST.cs0 = REGS->cs0;\
111 DEST.cs1 = REGS->cs1;\
112} while (0)
113#else
114#define CS_COPYREGS(DEST,REGS)
115#endif
116
107#define ELF_CORE_COPY_REGS(DEST, REGS) \ 117#define ELF_CORE_COPY_REGS(DEST, REGS) \
108do { \ 118do { \
109 DEST.r0 = REGS->r00; \ 119 DEST.r0 = REGS->r00; \
@@ -148,13 +158,12 @@ do { \
148 DEST.p3_0 = REGS->preds; \ 158 DEST.p3_0 = REGS->preds; \
149 DEST.gp = REGS->gp; \ 159 DEST.gp = REGS->gp; \
150 DEST.ugp = REGS->ugp; \ 160 DEST.ugp = REGS->ugp; \
151 DEST.pc = pt_elr(REGS); \ 161 CS_COPYREGS(DEST,REGS); \
162 DEST.pc = pt_elr(REGS); \
152 DEST.cause = pt_cause(REGS); \ 163 DEST.cause = pt_cause(REGS); \
153 DEST.badva = pt_badva(REGS); \ 164 DEST.badva = pt_badva(REGS); \
154} while (0); 165} while (0);
155 166
156
157
158/* 167/*
159 * This is used to ensure we don't load something for the wrong architecture. 168 * This is used to ensure we don't load something for the wrong architecture.
160 * Checks the machine and ABI type. 169 * Checks the machine and ABI type.
@@ -168,15 +177,15 @@ do { \
168#define ELF_DATA ELFDATA2LSB 177#define ELF_DATA ELFDATA2LSB
169#define ELF_ARCH EM_HEXAGON 178#define ELF_ARCH EM_HEXAGON
170 179
171#ifdef CONFIG_HEXAGON_ARCH_V2 180#if CONFIG_HEXAGON_ARCH_VERSION == 2
172#define ELF_CORE_EFLAGS 0x1 181#define ELF_CORE_EFLAGS 0x1
173#endif 182#endif
174 183
175#ifdef CONFIG_HEXAGON_ARCH_V3 184#if CONFIG_HEXAGON_ARCH_VERSION == 3
176#define ELF_CORE_EFLAGS 0x2 185#define ELF_CORE_EFLAGS 0x2
177#endif 186#endif
178 187
179#ifdef CONFIG_HEXAGON_ARCH_V4 188#if CONFIG_HEXAGON_ARCH_VERSION == 4
180#define ELF_CORE_EFLAGS 0x3 189#define ELF_CORE_EFLAGS 0x3
181#endif 190#endif
182 191
diff --git a/arch/hexagon/include/asm/hexagon_vm.h b/arch/hexagon/include/asm/hexagon_vm.h
index c144bee6cabe..67bb6d6f3337 100644
--- a/arch/hexagon/include/asm/hexagon_vm.h
+++ b/arch/hexagon/include/asm/hexagon_vm.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * Declarations for to Hexagon Virtal Machine. 2 * Declarations for to Hexagon Virtal Machine.
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and 7 * it under the terms of the GNU General Public License version 2 and
@@ -31,10 +31,26 @@
31 * for tracing/debugging. 31 * for tracing/debugging.
32 */ 32 */
33 33
34/* 34#define HVM_TRAP1_VMVERSION 0
35 * Lets make this stuff visible only if configured, 35#define HVM_TRAP1_VMRTE 1
36 * so we can unconditionally include the file. 36#define HVM_TRAP1_VMSETVEC 2
37 */ 37#define HVM_TRAP1_VMSETIE 3
38#define HVM_TRAP1_VMGETIE 4
39#define HVM_TRAP1_VMINTOP 5
40#define HVM_TRAP1_VMCLRMAP 10
41#define HVM_TRAP1_VMNEWMAP 11
42#define HVM_TRAP1_FORMERLY_VMWIRE 12
43#define HVM_TRAP1_VMCACHE 13
44#define HVM_TRAP1_VMGETTIME 14
45#define HVM_TRAP1_VMSETTIME 15
46#define HVM_TRAP1_VMWAIT 16
47#define HVM_TRAP1_VMYIELD 17
48#define HVM_TRAP1_VMSTART 18
49#define HVM_TRAP1_VMSTOP 19
50#define HVM_TRAP1_VMVPID 20
51#define HVM_TRAP1_VMSETREGS 21
52#define HVM_TRAP1_VMGETREGS 22
53#define HVM_TRAP1_VMTIMEROP 24
38 54
39#ifndef __ASSEMBLY__ 55#ifndef __ASSEMBLY__
40 56
@@ -175,31 +191,19 @@ static inline long __vmintop_clear(long i)
175 191
176#else /* Only assembly code should reference these */ 192#else /* Only assembly code should reference these */
177 193
178#define HVM_TRAP1_VMRTE 1
179#define HVM_TRAP1_VMSETVEC 2
180#define HVM_TRAP1_VMSETIE 3
181#define HVM_TRAP1_VMGETIE 4
182#define HVM_TRAP1_VMINTOP 5
183#define HVM_TRAP1_VMCLRMAP 10
184#define HVM_TRAP1_VMNEWMAP 11
185#define HVM_TRAP1_FORMERLY_VMWIRE 12
186#define HVM_TRAP1_VMCACHE 13
187#define HVM_TRAP1_VMGETTIME 14
188#define HVM_TRAP1_VMSETTIME 15
189#define HVM_TRAP1_VMWAIT 16
190#define HVM_TRAP1_VMYIELD 17
191#define HVM_TRAP1_VMSTART 18
192#define HVM_TRAP1_VMSTOP 19
193#define HVM_TRAP1_VMVPID 20
194#define HVM_TRAP1_VMSETREGS 21
195#define HVM_TRAP1_VMGETREGS 22
196
197#endif /* __ASSEMBLY__ */ 194#endif /* __ASSEMBLY__ */
198 195
199/* 196/*
200 * Constants for virtual instruction parameters and return values 197 * Constants for virtual instruction parameters and return values
201 */ 198 */
202 199
200/* vmnewmap arguments */
201
202#define VM_TRANS_TYPE_LINEAR 0
203#define VM_TRANS_TYPE_TABLE 1
204#define VM_TLB_INVALIDATE_FALSE 0
205#define VM_TLB_INVALIDATE_TRUE 1
206
203/* vmsetie arguments */ 207/* vmsetie arguments */
204 208
205#define VM_INT_DISABLE 0 209#define VM_INT_DISABLE 0
@@ -224,6 +228,8 @@ static inline long __vmintop_clear(long i)
224#define HVM_VMEST_UM_MSK 1 228#define HVM_VMEST_UM_MSK 1
225#define HVM_VMEST_IE_SFT 30 229#define HVM_VMEST_IE_SFT 30
226#define HVM_VMEST_IE_MSK 1 230#define HVM_VMEST_IE_MSK 1
231#define HVM_VMEST_SS_SFT 29
232#define HVM_VMEST_SS_MSK 1
227#define HVM_VMEST_EVENTNUM_SFT 16 233#define HVM_VMEST_EVENTNUM_SFT 16
228#define HVM_VMEST_EVENTNUM_MSK 0xff 234#define HVM_VMEST_EVENTNUM_MSK 0xff
229#define HVM_VMEST_CAUSE_SFT 0 235#define HVM_VMEST_CAUSE_SFT 0
@@ -260,6 +266,8 @@ static inline long __vmintop_clear(long i)
260#define HVM_GE_C_INVI 0x15 266#define HVM_GE_C_INVI 0x15
261#define HVM_GE_C_PRIVI 0x1B 267#define HVM_GE_C_PRIVI 0x1B
262#define HVM_GE_C_XMAL 0x1C 268#define HVM_GE_C_XMAL 0x1C
269#define HVM_GE_C_WREG 0x1D
270#define HVM_GE_C_PCAL 0x1E
263#define HVM_GE_C_RMAL 0x20 271#define HVM_GE_C_RMAL 0x20
264#define HVM_GE_C_WMAL 0x21 272#define HVM_GE_C_WMAL 0x21
265#define HVM_GE_C_RPROT 0x22 273#define HVM_GE_C_RPROT 0x22
diff --git a/arch/hexagon/include/asm/io.h b/arch/hexagon/include/asm/io.h
index e527cfeff5ba..1b7698e19139 100644
--- a/arch/hexagon/include/asm/io.h
+++ b/arch/hexagon/include/asm/io.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * IO definitions for the Hexagon architecture 2 * IO definitions for the Hexagon architecture
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and 7 * it under the terms of the GNU General Public License version 2 and
@@ -40,6 +40,8 @@
40#define IO_SPACE_LIMIT 0xffff 40#define IO_SPACE_LIMIT 0xffff
41#define _IO_BASE ((void __iomem *)0xfe000000) 41#define _IO_BASE ((void __iomem *)0xfe000000)
42 42
43#define IOMEM(x) ((void __force __iomem *)(x))
44
43extern int remap_area_pages(unsigned long start, unsigned long phys_addr, 45extern int remap_area_pages(unsigned long start, unsigned long phys_addr,
44 unsigned long end, unsigned long flags); 46 unsigned long end, unsigned long flags);
45 47
@@ -176,6 +178,18 @@ static inline void writel(u32 data, volatile void __iomem *addr)
176#define __raw_readl readl 178#define __raw_readl readl
177 179
178/* 180/*
181 * http://comments.gmane.org/gmane.linux.ports.arm.kernel/117626
182 */
183
184#define readb_relaxed __raw_readb
185#define readw_relaxed __raw_readw
186#define readl_relaxed __raw_readl
187
188#define writeb_relaxed __raw_writeb
189#define writew_relaxed __raw_writew
190#define writel_relaxed __raw_writel
191
192/*
179 * Need an mtype somewhere in here, for cache type deals? 193 * Need an mtype somewhere in here, for cache type deals?
180 * This is probably too long for an inline. 194 * This is probably too long for an inline.
181 */ 195 */
diff --git a/arch/hexagon/include/asm/mem-layout.h b/arch/hexagon/include/asm/mem-layout.h
index af16e977c55e..60556f8c45d8 100644
--- a/arch/hexagon/include/asm/mem-layout.h
+++ b/arch/hexagon/include/asm/mem-layout.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * Memory layout definitions for the Hexagon architecture 2 * Memory layout definitions for the Hexagon architecture
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and 7 * it under the terms of the GNU General Public License version 2 and
@@ -32,16 +32,25 @@
32#define PAGE_OFFSET _AC(0xc0000000, UL) 32#define PAGE_OFFSET _AC(0xc0000000, UL)
33 33
34/* 34/*
35 * LOAD_ADDRESS is the physical/linear address of where in memory 35 * Compiling for a platform that needs a crazy physical offset
36 * the kernel gets loaded. The 12 least significant bits must be zero (0) 36 * (like if the memory starts at 1GB and up) means we need
37 * due to limitations on setting the EVB 37 * an actual PHYS_OFFSET. Should be set up in head.S.
38 *
39 */ 38 */
40 39
41#ifndef LOAD_ADDRESS 40#ifdef CONFIG_HEXAGON_PHYS_OFFSET
42#define LOAD_ADDRESS 0x00000000 41#ifndef __ASSEMBLY__
42extern unsigned long __phys_offset;
43#endif
44#define PHYS_OFFSET __phys_offset
45#endif
46
47#ifndef PHYS_OFFSET
48#define PHYS_OFFSET 0
43#endif 49#endif
44 50
51#define PHYS_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT)
52#define ARCH_PFN_OFFSET PHYS_PFN_OFFSET
53
45#define TASK_SIZE (PAGE_OFFSET) 54#define TASK_SIZE (PAGE_OFFSET)
46 55
47/* not sure how these are used yet */ 56/* not sure how these are used yet */
@@ -55,7 +64,7 @@ enum fixed_addresses {
55 __end_of_fixed_addresses 64 __end_of_fixed_addresses
56}; 65};
57 66
58#define MIN_KERNEL_SEG 0x300 /* From 0xc0000000 */ 67#define MIN_KERNEL_SEG (PAGE_OFFSET >> PGDIR_SHIFT) /* L1 shift is 22 bits */
59extern int max_kernel_seg; 68extern int max_kernel_seg;
60 69
61/* 70/*
@@ -63,8 +72,7 @@ extern int max_kernel_seg;
63 * supposed to be based on the amount of physical memory available 72 * supposed to be based on the amount of physical memory available
64 */ 73 */
65 74
66#define VMALLOC_START (PAGE_OFFSET + VMALLOC_OFFSET + \ 75#define VMALLOC_START ((unsigned long) __va(high_memory + VMALLOC_OFFSET))
67 (unsigned long)high_memory)
68 76
69/* Gap between physical ram and vmalloc space for guard purposes. */ 77/* Gap between physical ram and vmalloc space for guard purposes. */
70#define VMALLOC_OFFSET PAGE_SIZE 78#define VMALLOC_OFFSET PAGE_SIZE
diff --git a/arch/hexagon/include/asm/page.h b/arch/hexagon/include/asm/page.h
index 692adc213429..93f5669b4aa1 100644
--- a/arch/hexagon/include/asm/page.h
+++ b/arch/hexagon/include/asm/page.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * Page management definitions for the Hexagon architecture 2 * Page management definitions for the Hexagon architecture
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and 7 * it under the terms of the GNU General Public License version 2 and
@@ -96,8 +96,8 @@ typedef struct page *pgtable_t;
96 * MIPS says they're only used during mem_init. 96 * MIPS says they're only used during mem_init.
97 * also, check if we need a PHYS_OFFSET. 97 * also, check if we need a PHYS_OFFSET.
98 */ 98 */
99#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET) 99#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
100#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET)) 100#define __va(x) ((void *)((unsigned long)(x) - PHYS_OFFSET + PAGE_OFFSET))
101 101
102/* The "page frame" descriptor is defined in linux/mm.h */ 102/* The "page frame" descriptor is defined in linux/mm.h */
103struct page; 103struct page;
@@ -140,6 +140,11 @@ static inline void clear_page(void *page)
140 */ 140 */
141#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) 141#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
142 142
143#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT)
144#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT)
145
146#define page_to_virt(page) __va(page_to_phys(page))
147
143/* 148/*
144 * For port to Hexagon Virtual Machine, MAYBE we check for attempts 149 * For port to Hexagon Virtual Machine, MAYBE we check for attempts
145 * to reference reserved HVM space, but in any case, the VM will be 150 * to reference reserved HVM space, but in any case, the VM will be
@@ -147,6 +152,7 @@ static inline void clear_page(void *page)
147 */ 152 */
148#define kern_addr_valid(addr) (1) 153#define kern_addr_valid(addr) (1)
149 154
155#include <asm/mem-layout.h>
150#include <asm-generic/memory_model.h> 156#include <asm-generic/memory_model.h>
151/* XXX Todo: implement assembly-optimized version of getorder. */ 157/* XXX Todo: implement assembly-optimized version of getorder. */
152#include <asm-generic/getorder.h> 158#include <asm-generic/getorder.h>
diff --git a/arch/hexagon/include/asm/processor.h b/arch/hexagon/include/asm/processor.h
index 6dd5d3706869..45a825402f63 100644
--- a/arch/hexagon/include/asm/processor.h
+++ b/arch/hexagon/include/asm/processor.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * Process/processor support for the Hexagon architecture 2 * Process/processor support for the Hexagon architecture
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and 7 * it under the terms of the GNU General Public License version 2 and
@@ -100,12 +100,49 @@ extern unsigned long get_wchan(struct task_struct *p);
100 */ 100 */
101 101
102struct hexagon_switch_stack { 102struct hexagon_switch_stack {
103 unsigned long long r1716; 103 union {
104 unsigned long long r1918; 104 struct {
105 unsigned long long r2120; 105 unsigned long r16;
106 unsigned long long r2322; 106 unsigned long r17;
107 unsigned long long r2524; 107 };
108 unsigned long long r2726; 108 unsigned long long r1716;
109 };
110 union {
111 struct {
112 unsigned long r18;
113 unsigned long r19;
114 };
115 unsigned long long r1918;
116 };
117 union {
118 struct {
119 unsigned long r20;
120 unsigned long r21;
121 };
122 unsigned long long r2120;
123 };
124 union {
125 struct {
126 unsigned long r22;
127 unsigned long r23;
128 };
129 unsigned long long r2322;
130 };
131 union {
132 struct {
133 unsigned long r24;
134 unsigned long r25;
135 };
136 unsigned long long r2524;
137 };
138 union {
139 struct {
140 unsigned long r26;
141 unsigned long r27;
142 };
143 unsigned long long r2726;
144 };
145
109 unsigned long fp; 146 unsigned long fp;
110 unsigned long lr; 147 unsigned long lr;
111}; 148};
diff --git a/arch/hexagon/include/asm/vm_mmu.h b/arch/hexagon/include/asm/vm_mmu.h
index 9a94de7969bb..096537d8f4c5 100644
--- a/arch/hexagon/include/asm/vm_mmu.h
+++ b/arch/hexagon/include/asm/vm_mmu.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * Hexagon VM page table entry definitions 2 * Hexagon VM page table entry definitions
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2011,2013 The Linux Foundation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and 7 * it under the terms of the GNU General Public License version 2 and
@@ -68,14 +68,13 @@
68 68
69#define __HEXAGON_C_WB 0x0 /* Write-back, no L2 */ 69#define __HEXAGON_C_WB 0x0 /* Write-back, no L2 */
70#define __HEXAGON_C_WT 0x1 /* Write-through, no L2 */ 70#define __HEXAGON_C_WT 0x1 /* Write-through, no L2 */
71#define __HEXAGON_C_UNC 0x6 /* Uncached memory */
72#if CONFIG_HEXAGON_ARCH_VERSION >= 2
71#define __HEXAGON_C_DEV 0x4 /* Device register space */ 73#define __HEXAGON_C_DEV 0x4 /* Device register space */
72#define __HEXAGON_C_WT_L2 0x5 /* Write-through, with L2 */
73/* this really should be #if CONFIG_HEXAGON_ARCH = 2 but that's not defined */
74#if defined(CONFIG_HEXAGON_COMET) || defined(CONFIG_QDSP6_ST1)
75#define __HEXAGON_C_UNC __HEXAGON_C_DEV
76#else 74#else
77#define __HEXAGON_C_UNC 0x6 /* Uncached memory */ 75#define __HEXAGON_C_DEV __HEXAGON_C_UNC
78#endif 76#endif
77#define __HEXAGON_C_WT_L2 0x5 /* Write-through, with L2 */
79#define __HEXAGON_C_WB_L2 0x7 /* Write-back, with L2 */ 78#define __HEXAGON_C_WB_L2 0x7 /* Write-back, with L2 */
80 79
81/* 80/*
diff --git a/arch/hexagon/include/uapi/asm/ptrace.h b/arch/hexagon/include/uapi/asm/ptrace.h
index 1ffce0c6ee07..065e5b32313f 100644
--- a/arch/hexagon/include/uapi/asm/ptrace.h
+++ b/arch/hexagon/include/uapi/asm/ptrace.h
@@ -36,4 +36,9 @@ extern const char *regs_query_register_name(unsigned int offset);
36 ((struct pt_regs *) \ 36 ((struct pt_regs *) \
37 ((unsigned long)current_thread_info() + THREAD_SIZE) - 1) 37 ((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
38 38
39#if CONFIG_HEXAGON_ARCH_VERSION >= 4
40#define arch_has_single_step() (1)
41#endif
42
43
39#endif 44#endif
diff --git a/arch/hexagon/include/uapi/asm/registers.h b/arch/hexagon/include/uapi/asm/registers.h
index c20406f63b5c..487d6ceca5e7 100644
--- a/arch/hexagon/include/uapi/asm/registers.h
+++ b/arch/hexagon/include/uapi/asm/registers.h
@@ -57,10 +57,17 @@ struct pt_regs {
57 }; 57 };
58 union { 58 union {
59 struct { 59 struct {
60 unsigned long gp;
61 unsigned long ugp; 60 unsigned long ugp;
61 unsigned long gp;
62 }; 62 };
63 long long int ugpgp; 63 long long int gpugp;
64 };
65 union {
66 struct {
67 unsigned long cs0;
68 unsigned long cs1;
69 };
70 long long int cs1cs0;
64 }; 71 };
65 /* 72 /*
66 * Be extremely careful with rearranging these, if at all. Some code 73 * Be extremely careful with rearranging these, if at all. Some code
@@ -204,9 +211,11 @@ struct pt_regs {
204#define pt_psp(regs) ((regs)->hvmer.vmpsp) 211#define pt_psp(regs) ((regs)->hvmer.vmpsp)
205#define pt_badva(regs) ((regs)->hvmer.vmbadva) 212#define pt_badva(regs) ((regs)->hvmer.vmbadva)
206 213
214#define pt_set_singlestep(regs) ((regs)->hvmer.vmest |= (1<<HVM_VMEST_SS_SFT))
215#define pt_clr_singlestep(regs) ((regs)->hvmer.vmest &= ~(1<<HVM_VMEST_SS_SFT))
216
207#define pt_set_rte_sp(regs, sp) do {\ 217#define pt_set_rte_sp(regs, sp) do {\
208 pt_psp(regs) = (sp);\ 218 pt_psp(regs) = (regs)->SP = (sp);\
209 (regs)->SP = (unsigned long) &((regs)->hvmer);\
210 } while (0) 219 } while (0)
211 220
212#define pt_set_kmode(regs) \ 221#define pt_set_kmode(regs) \
diff --git a/arch/hexagon/include/uapi/asm/signal.h b/arch/hexagon/include/uapi/asm/signal.h
index 939556817d34..98106e55ad4f 100644
--- a/arch/hexagon/include/uapi/asm/signal.h
+++ b/arch/hexagon/include/uapi/asm/signal.h
@@ -19,8 +19,12 @@
19#ifndef _ASM_SIGNAL_H 19#ifndef _ASM_SIGNAL_H
20#define _ASM_SIGNAL_H 20#define _ASM_SIGNAL_H
21 21
22#include <uapi/asm/registers.h>
23
22extern unsigned long __rt_sigtramp_template[2]; 24extern unsigned long __rt_sigtramp_template[2];
23 25
26void do_signal(struct pt_regs *regs);
27
24#include <asm-generic/signal.h> 28#include <asm-generic/signal.h>
25 29
26#endif 30#endif
diff --git a/arch/hexagon/include/uapi/asm/unistd.h b/arch/hexagon/include/uapi/asm/unistd.h
index 4a87cc47075c..ffee405d6803 100644
--- a/arch/hexagon/include/uapi/asm/unistd.h
+++ b/arch/hexagon/include/uapi/asm/unistd.h
@@ -27,6 +27,9 @@
27 */ 27 */
28 28
29#define sys_mmap2 sys_mmap_pgoff 29#define sys_mmap2 sys_mmap_pgoff
30#define __ARCH_WANT_SYS_EXECVE
30#define __ARCH_WANT_SYS_CLONE 31#define __ARCH_WANT_SYS_CLONE
32#define __ARCH_WANT_SYS_VFORK
33#define __ARCH_WANT_SYS_FORK
31 34
32#include <asm-generic/unistd.h> 35#include <asm-generic/unistd.h>
diff --git a/arch/hexagon/include/uapi/asm/user.h b/arch/hexagon/include/uapi/asm/user.h
index cef13ee1413f..3dae94d9ced7 100644
--- a/arch/hexagon/include/uapi/asm/user.h
+++ b/arch/hexagon/include/uapi/asm/user.h
@@ -55,9 +55,15 @@ struct user_regs_struct {
55 unsigned long pc; 55 unsigned long pc;
56 unsigned long cause; 56 unsigned long cause;
57 unsigned long badva; 57 unsigned long badva;
58#if CONFIG_HEXAGON_ARCH_VERSION < 4
58 unsigned long pad1; /* pad out to 48 words total */ 59 unsigned long pad1; /* pad out to 48 words total */
59 unsigned long pad2; /* pad out to 48 words total */ 60 unsigned long pad2; /* pad out to 48 words total */
60 unsigned long pad3; /* pad out to 48 words total */ 61 unsigned long pad3; /* pad out to 48 words total */
62#else
63 unsigned long cs0;
64 unsigned long cs1;
65 unsigned long pad1; /* pad out to 48 words total */
66#endif
61}; 67};
62 68
63#endif 69#endif
diff --git a/arch/hexagon/kernel/Makefile b/arch/hexagon/kernel/Makefile
index 6c19501b487c..29fc933a7722 100644
--- a/arch/hexagon/kernel/Makefile
+++ b/arch/hexagon/kernel/Makefile
@@ -1,6 +1,6 @@
1extra-y := head.o vmlinux.lds 1extra-y := head.o vmlinux.lds
2 2
3obj-$(CONFIG_SMP) += smp.o topology.o 3obj-$(CONFIG_SMP) += smp.o
4 4
5obj-y += setup.o irq_cpu.o traps.o syscalltab.o signal.o time.o 5obj-y += setup.o irq_cpu.o traps.o syscalltab.o signal.o time.o
6obj-y += process.o trampoline.o reset.o ptrace.o vdso.o 6obj-y += process.o trampoline.o reset.o ptrace.o vdso.o
diff --git a/arch/hexagon/kernel/asm-offsets.c b/arch/hexagon/kernel/asm-offsets.c
index 2d5e84d3b00d..308be68d4fb3 100644
--- a/arch/hexagon/kernel/asm-offsets.c
+++ b/arch/hexagon/kernel/asm-offsets.c
@@ -5,7 +5,7 @@
5 * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com 5 * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
6 * Copyright (C) 2000 MIPS Technologies, Inc. 6 * Copyright (C) 2000 MIPS Technologies, Inc.
7 * 7 *
8 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 8 * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 and 11 * it under the terms of the GNU General Public License version 2 and
@@ -44,7 +44,8 @@ int main(void)
44 44
45 COMMENT("Hexagon pt_regs definitions"); 45 COMMENT("Hexagon pt_regs definitions");
46 OFFSET(_PT_SYSCALL_NR, pt_regs, syscall_nr); 46 OFFSET(_PT_SYSCALL_NR, pt_regs, syscall_nr);
47 OFFSET(_PT_UGPGP, pt_regs, ugpgp); 47 OFFSET(_PT_GPUGP, pt_regs, gpugp);
48 OFFSET(_PT_CS1CS0, pt_regs, cs1cs0);
48 OFFSET(_PT_R3130, pt_regs, r3130); 49 OFFSET(_PT_R3130, pt_regs, r3130);
49 OFFSET(_PT_R2928, pt_regs, r2928); 50 OFFSET(_PT_R2928, pt_regs, r2928);
50 OFFSET(_PT_R2726, pt_regs, r2726); 51 OFFSET(_PT_R2726, pt_regs, r2726);
diff --git a/arch/hexagon/kernel/dma.c b/arch/hexagon/kernel/dma.c
index 65c7bdcf565e..b74f9bae31a3 100644
--- a/arch/hexagon/kernel/dma.c
+++ b/arch/hexagon/kernel/dma.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * DMA implementation for Hexagon 2 * DMA implementation for Hexagon
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and 7 * it under the terms of the GNU General Public License version 2 and
@@ -23,12 +23,18 @@
23#include <linux/genalloc.h> 23#include <linux/genalloc.h>
24#include <asm/dma-mapping.h> 24#include <asm/dma-mapping.h>
25#include <linux/module.h> 25#include <linux/module.h>
26#include <asm/page.h>
26 27
27struct dma_map_ops *dma_ops; 28struct dma_map_ops *dma_ops;
28EXPORT_SYMBOL(dma_ops); 29EXPORT_SYMBOL(dma_ops);
29 30
30int bad_dma_address; /* globals are automatically initialized to zero */ 31int bad_dma_address; /* globals are automatically initialized to zero */
31 32
33static inline void *dma_addr_to_virt(dma_addr_t dma_addr)
34{
35 return phys_to_virt((unsigned long) dma_addr);
36}
37
32int dma_supported(struct device *dev, u64 mask) 38int dma_supported(struct device *dev, u64 mask)
33{ 39{
34 if (mask == DMA_BIT_MASK(32)) 40 if (mask == DMA_BIT_MASK(32))
@@ -60,6 +66,12 @@ static void *hexagon_dma_alloc_coherent(struct device *dev, size_t size,
60{ 66{
61 void *ret; 67 void *ret;
62 68
69 /*
70 * Our max_low_pfn should have been backed off by 16MB in
71 * mm/init.c to create DMA coherent space. Use that as the VA
72 * for the pool.
73 */
74
63 if (coherent_pool == NULL) { 75 if (coherent_pool == NULL) {
64 coherent_pool = gen_pool_create(PAGE_SHIFT, -1); 76 coherent_pool = gen_pool_create(PAGE_SHIFT, -1);
65 77
@@ -67,7 +79,7 @@ static void *hexagon_dma_alloc_coherent(struct device *dev, size_t size,
67 panic("Can't create %s() memory pool!", __func__); 79 panic("Can't create %s() memory pool!", __func__);
68 else 80 else
69 gen_pool_add(coherent_pool, 81 gen_pool_add(coherent_pool,
70 (PAGE_OFFSET + (max_low_pfn << PAGE_SHIFT)), 82 pfn_to_virt(max_low_pfn),
71 hexagon_coherent_pool_size, -1); 83 hexagon_coherent_pool_size, -1);
72 } 84 }
73 85
@@ -75,7 +87,7 @@ static void *hexagon_dma_alloc_coherent(struct device *dev, size_t size,
75 87
76 if (ret) { 88 if (ret) {
77 memset(ret, 0, size); 89 memset(ret, 0, size);
78 *dma_addr = (dma_addr_t) (ret - PAGE_OFFSET); 90 *dma_addr = (dma_addr_t) virt_to_phys(ret);
79 } else 91 } else
80 *dma_addr = ~0; 92 *dma_addr = ~0;
81 93
@@ -118,8 +130,8 @@ static int hexagon_map_sg(struct device *hwdev, struct scatterlist *sg,
118 130
119 s->dma_length = s->length; 131 s->dma_length = s->length;
120 132
121 flush_dcache_range(PAGE_OFFSET + s->dma_address, 133 flush_dcache_range(dma_addr_to_virt(s->dma_address),
122 PAGE_OFFSET + s->dma_address + s->length); 134 dma_addr_to_virt(s->dma_address + s->length));
123 } 135 }
124 136
125 return nents; 137 return nents;
@@ -149,11 +161,6 @@ static inline void dma_sync(void *addr, size_t size,
149 } 161 }
150} 162}
151 163
152static inline void *dma_addr_to_virt(dma_addr_t dma_addr)
153{
154 return phys_to_virt((unsigned long) dma_addr);
155}
156
157/** 164/**
158 * hexagon_map_page() - maps an address for device DMA 165 * hexagon_map_page() - maps an address for device DMA
159 * @dev: pointer to DMA device 166 * @dev: pointer to DMA device
diff --git a/arch/hexagon/kernel/head.S b/arch/hexagon/kernel/head.S
index d859402c73ba..b9b63d085db2 100644
--- a/arch/hexagon/kernel/head.S
+++ b/arch/hexagon/kernel/head.S
@@ -1,7 +1,7 @@
1/* 1/*
2 * Early kernel startup code for Hexagon 2 * Early kernel startup code for Hexagon
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
5 * 5 *
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -25,6 +25,9 @@
25#include <asm/mem-layout.h> 25#include <asm/mem-layout.h>
26#include <asm/vm_mmu.h> 26#include <asm/vm_mmu.h>
27#include <asm/page.h> 27#include <asm/page.h>
28#include <asm/hexagon_vm.h>
29
30#define SEGTABLE_ENTRIES #0x0e0
28 31
29 __INIT 32 __INIT
30ENTRY(stext) 33ENTRY(stext)
@@ -43,40 +46,93 @@ ENTRY(stext)
43 * Symbol is kernel segment address, but we need 46 * Symbol is kernel segment address, but we need
44 * the logical/physical address. 47 * the logical/physical address.
45 */ 48 */
46 r24 = asl(r24, #2) 49 r25 = pc;
47 r24 = lsr(r24, #2) 50 r2.h = #0xffc0;
51 r2.l = #0x0000;
52 r25 = and(r2,r25); /* R25 holds PHYS_OFFSET now */
53 r1.h = #HI(PAGE_OFFSET);
54 r1.l = #LO(PAGE_OFFSET);
55 r24 = sub(r24,r1); /* swapper_pg_dir - PAGE_OFFSET */
56 r24 = add(r24,r25); /* + PHYS_OFFSET */
48 57
49 r0 = r24 58 r0 = r24; /* aka __pa(swapper_pg_dir) */
50 59
51 /* 60 /*
52 * Initialize a 16MB PTE to make the virtual and physical 61 * Initialize page dir to make the virtual and physical
53 * addresses where the kernel was loaded be identical. 62 * addresses where the kernel was loaded be identical.
63 * Done in 4MB chunks.
54 */ 64 */
55#define PTE_BITS ( __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X \ 65#define PTE_BITS ( __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X \
56 | __HEXAGON_C_WB_L2 << 6 \ 66 | __HEXAGON_C_WB_L2 << 6 \
57 | __HVM_PDE_S_4MB) 67 | __HVM_PDE_S_4MB)
58 68
59 r1 = pc 69 /*
60 r2.H = #0xffc0 70 * Get number of VA=PA entries; only really needed for jump
61 r2.L = #0x0000 71 * to hyperspace; gets blown away immediately after
62 r1 = and(r1,r2) /* round PC to 4MB boundary */ 72 */
73
74 {
75 r1.l = #LO(_end);
76 r2.l = #LO(stext);
77 r3 = #1;
78 }
79 {
80 r1.h = #HI(_end);
81 r2.h = #HI(stext);
82 r3 = asl(r3, #22);
83 }
84 {
85 r1 = sub(r1, r2);
86 r3 = add(r3, #-1);
87 } /* r1 = _end - stext */
88 r1 = add(r1, r3); /* + (4M-1) */
89 r26 = lsr(r1, #22); /* / 4M = # of entries */
90
91 r1 = r25;
92 r2.h = #0xffc0;
93 r2.l = #0x0000; /* round back down to 4MB boundary */
94 r1 = and(r1,r2);
63 r2 = lsr(r1, #22) /* 4MB page number */ 95 r2 = lsr(r1, #22) /* 4MB page number */
64 r2 = asl(r2, #2) /* times sizeof(PTE) (4bytes) */ 96 r2 = asl(r2, #2) /* times sizeof(PTE) (4bytes) */
65 r0 = add(r0,r2) /* r0 = address of correct PTE */ 97 r0 = add(r0,r2) /* r0 = address of correct PTE */
66 r2 = #PTE_BITS 98 r2 = #PTE_BITS
67 r1 = add(r1,r2) /* r1 = 4MB PTE for the first entry */ 99 r1 = add(r1,r2) /* r1 = 4MB PTE for the first entry */
68 r2.h = #0x0040 100 r2.h = #0x0040
69 r2.l = #0x0000 /* 4MB */ 101 r2.l = #0x0000 /* 4MB increments */
70 memw(r0 ++ #4) = r1 102 loop0(1f,r26);
71 r1 = add(r1, r2) 1031:
72 memw(r0 ++ #4) = r1 104 memw(r0 ++ #4) = r1
105 { r1 = add(r1, r2); } :endloop0
106
107 /* Also need to overwrite the initial 0xc0000000 entries */
108 /* PAGE_OFFSET >> (4MB shift - 4 bytes per entry shift) */
109 R1.H = #HI(PAGE_OFFSET >> (22 - 2))
110 R1.L = #LO(PAGE_OFFSET >> (22 - 2))
111
112 r0 = add(r1, r24); /* advance to 0xc0000000 entry */
113 r1 = r25;
114 r2.h = #0xffc0;
115 r2.l = #0x0000; /* round back down to 4MB boundary */
116 r1 = and(r1,r2); /* for huge page */
117 r2 = #PTE_BITS
118 r1 = add(r1,r2);
119 r2.h = #0x0040
120 r2.l = #0x0000 /* 4MB increments */
73 121
74 r0 = r24 122 loop0(1f,SEGTABLE_ENTRIES);
1231:
124 memw(r0 ++ #4) = r1;
125 { r1 = add(r1,r2); } :endloop0
126
127 r0 = r24;
75 128
76 /* 129 /*
77 * The subroutine wrapper around the virtual instruction touches 130 * The subroutine wrapper around the virtual instruction touches
78 * no memory, so we should be able to use it even here. 131 * no memory, so we should be able to use it even here.
132 * Note that in this version, R1 and R2 get "clobbered"; see
133 * vm_ops.S
79 */ 134 */
135 r1 = #VM_TRANS_TYPE_TABLE
80 call __vmnewmap; 136 call __vmnewmap;
81 137
82 /* Jump into virtual address range. */ 138 /* Jump into virtual address range. */
@@ -90,17 +146,29 @@ ENTRY(stext)
90__head_s_vaddr_target: 146__head_s_vaddr_target:
91 /* 147 /*
92 * Tear down VA=PA translation now that we are running 148 * Tear down VA=PA translation now that we are running
93 * in the desgnated kernel segments. 149 * in kernel virtual space.
94 */ 150 */
95 r0 = #__HVM_PDE_S_INVALID 151 r0 = #__HVM_PDE_S_INVALID
96 r1 = r24 152
97 loop0(1f,#0x100) 153 r1.h = #0xffc0;
154 r1.l = #0x0000;
155 r2 = r25; /* phys_offset */
156 r2 = and(r1,r2);
157
158 r1.l = #lo(swapper_pg_dir)
159 r1.h = #hi(swapper_pg_dir)
160 r2 = lsr(r2, #22) /* 4MB page number */
161 r2 = asl(r2, #2) /* times sizeof(PTE) (4bytes) */
162 r1 = add(r1,r2);
163 loop0(1f,r26)
164
981: 1651:
99 { 166 {
100 memw(R1 ++ #4) = R0 167 memw(R1 ++ #4) = R0
101 }:endloop0 168 }:endloop0
102 169
103 r0 = r24 170 r0 = r24
171 r1 = #VM_TRANS_TYPE_TABLE
104 call __vmnewmap 172 call __vmnewmap
105 173
106 /* Go ahead and install the trap0 return so angel calls work */ 174 /* Go ahead and install the trap0 return so angel calls work */
@@ -143,6 +211,13 @@ __head_s_vaddr_target:
143 r2 = sub(r2,r0); 211 r2 = sub(r2,r0);
144 call memset; 212 call memset;
145 213
214 /* Set PHYS_OFFSET; should be in R25 */
215#ifdef CONFIG_HEXAGON_PHYS_OFFSET
216 r0.l = #LO(__phys_offset);
217 r0.h = #HI(__phys_offset);
218 memw(r0) = r25;
219#endif
220
146 /* Time to make the doughnuts. */ 221 /* Time to make the doughnuts. */
147 call start_kernel 222 call start_kernel
148 223
diff --git a/arch/hexagon/kernel/kgdb.c b/arch/hexagon/kernel/kgdb.c
index 344645370646..82d5c2593323 100644
--- a/arch/hexagon/kernel/kgdb.c
+++ b/arch/hexagon/kernel/kgdb.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * arch/hexagon/kernel/kgdb.c - Hexagon KGDB Support 2 * arch/hexagon/kernel/kgdb.c - Hexagon KGDB Support
3 * 3 *
4 * Copyright (c) 2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and 7 * it under the terms of the GNU General Public License version 2 and
@@ -70,6 +70,8 @@ struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
70 { "lc1", GDB_SIZEOF_REG, offsetof(struct pt_regs, lc1)}, 70 { "lc1", GDB_SIZEOF_REG, offsetof(struct pt_regs, lc1)},
71 { " gp", GDB_SIZEOF_REG, offsetof(struct pt_regs, gp)}, 71 { " gp", GDB_SIZEOF_REG, offsetof(struct pt_regs, gp)},
72 { "ugp", GDB_SIZEOF_REG, offsetof(struct pt_regs, ugp)}, 72 { "ugp", GDB_SIZEOF_REG, offsetof(struct pt_regs, ugp)},
73 { "cs0", GDB_SIZEOF_REG, offsetof(struct pt_regs, cs0)},
74 { "cs1", GDB_SIZEOF_REG, offsetof(struct pt_regs, cs1)},
73 { "psp", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmpsp)}, 75 { "psp", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmpsp)},
74 { "elr", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmel)}, 76 { "elr", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmel)},
75 { "est", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmest)}, 77 { "est", GDB_SIZEOF_REG, offsetof(struct pt_regs, hvmer.vmest)},
diff --git a/arch/hexagon/kernel/process.c b/arch/hexagon/kernel/process.c
index 9b948c619a03..0a0dd5c05b46 100644
--- a/arch/hexagon/kernel/process.c
+++ b/arch/hexagon/kernel/process.c
@@ -24,6 +24,7 @@
24#include <linux/tick.h> 24#include <linux/tick.h>
25#include <linux/uaccess.h> 25#include <linux/uaccess.h>
26#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/tracehook.h>
27 28
28/* 29/*
29 * Program thread launch. Often defined as a macro in processor.h, 30 * Program thread launch. Often defined as a macro in processor.h,
@@ -95,7 +96,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
95 if (unlikely(p->flags & PF_KTHREAD)) { 96 if (unlikely(p->flags & PF_KTHREAD)) {
96 memset(childregs, 0, sizeof(struct pt_regs)); 97 memset(childregs, 0, sizeof(struct pt_regs));
97 /* r24 <- fn, r25 <- arg */ 98 /* r24 <- fn, r25 <- arg */
98 ss->r2524 = usp | ((u64)arg << 32); 99 ss->r24 = usp;
100 ss->r25 = arg;
99 pt_set_kmode(childregs); 101 pt_set_kmode(childregs);
100 return 0; 102 return 0;
101 } 103 }
@@ -185,3 +187,41 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
185{ 187{
186 return 0; 188 return 0;
187} 189}
190
191
192/*
193 * Called on the exit path of event entry; see vm_entry.S
194 *
195 * Interrupts will already be disabled.
196 *
197 * Returns 0 if there's no need to re-check for more work.
198 */
199
200int do_work_pending(struct pt_regs *regs, u32 thread_info_flags)
201{
202 if (!(thread_info_flags & _TIF_WORK_MASK)) {
203 return 0;
204 } /* shortcut -- no work to be done */
205
206 local_irq_enable();
207
208 if (thread_info_flags & _TIF_NEED_RESCHED) {
209 schedule();
210 return 1;
211 }
212
213 if (thread_info_flags & _TIF_SIGPENDING) {
214 do_signal(regs);
215 return 1;
216 }
217
218 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
219 clear_thread_flag(TIF_NOTIFY_RESUME);
220 tracehook_notify_resume(regs);
221 return 1;
222 }
223
224 /* Should not even reach here */
225 panic("%s: bad thread_info flags 0x%08x\n", __func__,
226 thread_info_flags);
227}
diff --git a/arch/hexagon/kernel/ptrace.c b/arch/hexagon/kernel/ptrace.c
index 670b1b0bee63..de829eb7f185 100644
--- a/arch/hexagon/kernel/ptrace.c
+++ b/arch/hexagon/kernel/ptrace.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Ptrace support for Hexagon 2 * Ptrace support for Hexagon
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and 7 * it under the terms of the GNU General Public License version 2 and
@@ -32,6 +32,21 @@
32 32
33#include <asm/user.h> 33#include <asm/user.h>
34 34
35#if arch_has_single_step()
36/* Both called from ptrace_resume */
37void user_enable_single_step(struct task_struct *child)
38{
39 pt_set_singlestep(task_pt_regs(child));
40 set_tsk_thread_flag(child, TIF_SINGLESTEP);
41}
42
43void user_disable_single_step(struct task_struct *child)
44{
45 pt_clr_singlestep(task_pt_regs(child));
46 clear_tsk_thread_flag(child, TIF_SINGLESTEP);
47}
48#endif
49
35static int genregs_get(struct task_struct *target, 50static int genregs_get(struct task_struct *target,
36 const struct user_regset *regset, 51 const struct user_regset *regset,
37 unsigned int pos, unsigned int count, 52 unsigned int pos, unsigned int count,
@@ -76,6 +91,10 @@ static int genregs_get(struct task_struct *target,
76 dummy = pt_cause(regs); 91 dummy = pt_cause(regs);
77 ONEXT(&dummy, cause); 92 ONEXT(&dummy, cause);
78 ONEXT(&pt_badva(regs), badva); 93 ONEXT(&pt_badva(regs), badva);
94#if CONFIG_HEXAGON_ARCH_VERSION >=4
95 ONEXT(&regs->cs0, cs0);
96 ONEXT(&regs->cs1, cs1);
97#endif
79 98
80 /* Pad the rest with zeros, if needed */ 99 /* Pad the rest with zeros, if needed */
81 if (!ret) 100 if (!ret)
@@ -123,6 +142,11 @@ static int genregs_set(struct task_struct *target,
123 INEXT(&bucket, cause); 142 INEXT(&bucket, cause);
124 INEXT(&bucket, badva); 143 INEXT(&bucket, badva);
125 144
145#if CONFIG_HEXAGON_ARCH_VERSION >=4
146 INEXT(&regs->cs0, cs0);
147 INEXT(&regs->cs1, cs1);
148#endif
149
126 /* Ignore the rest, if needed */ 150 /* Ignore the rest, if needed */
127 if (!ret) 151 if (!ret)
128 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 152 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
diff --git a/arch/hexagon/kernel/setup.c b/arch/hexagon/kernel/setup.c
index 94a387835008..bfe13311d70d 100644
--- a/arch/hexagon/kernel/setup.c
+++ b/arch/hexagon/kernel/setup.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Arch related setup for Hexagon 2 * Arch related setup for Hexagon
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and 7 * it under the terms of the GNU General Public License version 2 and
@@ -68,6 +68,8 @@ void __init setup_arch(char **cmdline_p)
68 */ 68 */
69 __vmsetvec(_K_VM_event_vector); 69 __vmsetvec(_K_VM_event_vector);
70 70
71 printk(KERN_INFO "PHYS_OFFSET=0x%08x\n", PHYS_OFFSET);
72
71 /* 73 /*
72 * Simulator has a few differences from the hardware. 74 * Simulator has a few differences from the hardware.
73 * For now, check uninitialized-but-mapped memory 75 * For now, check uninitialized-but-mapped memory
@@ -128,6 +130,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
128{ 130{
129 int cpu = (unsigned long) v - 1; 131 int cpu = (unsigned long) v - 1;
130 132
133#ifdef CONFIG_SMP
134 if (!cpu_online(cpu))
135 return 0;
136#endif
137
131 seq_printf(m, "processor\t: %d\n", cpu); 138 seq_printf(m, "processor\t: %d\n", cpu);
132 seq_printf(m, "model name\t: Hexagon Virtual Machine\n"); 139 seq_printf(m, "model name\t: Hexagon Virtual Machine\n");
133 seq_printf(m, "BogoMips\t: %lu.%02lu\n", 140 seq_printf(m, "BogoMips\t: %lu.%02lu\n",
diff --git a/arch/hexagon/kernel/signal.c b/arch/hexagon/kernel/signal.c
index 60fa2ca3202b..d7c73874b515 100644
--- a/arch/hexagon/kernel/signal.c
+++ b/arch/hexagon/kernel/signal.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Signal support for Hexagon processor 2 * Signal support for Hexagon processor
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and 7 * it under the terms of the GNU General Public License version 2 and
@@ -41,6 +41,10 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
41{ 41{
42 unsigned long sp = regs->r29; 42 unsigned long sp = regs->r29;
43 43
44 /* check if we would overflow the alt stack */
45 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
46 return (void __user __force *)-1UL;
47
44 /* Switch to signal stack if appropriate */ 48 /* Switch to signal stack if appropriate */
45 if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) 49 if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
46 sp = current->sas_ss_sp + current->sas_ss_size; 50 sp = current->sas_ss_sp + current->sas_ss_size;
@@ -66,7 +70,10 @@ static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
66 err |= __put_user(regs->preds, &sc->sc_regs.p3_0); 70 err |= __put_user(regs->preds, &sc->sc_regs.p3_0);
67 err |= __put_user(regs->gp, &sc->sc_regs.gp); 71 err |= __put_user(regs->gp, &sc->sc_regs.gp);
68 err |= __put_user(regs->ugp, &sc->sc_regs.ugp); 72 err |= __put_user(regs->ugp, &sc->sc_regs.ugp);
69 73#if CONFIG_HEXAGON_ARCH_VERSION >= 4
74 err |= __put_user(regs->cs0, &sc->sc_regs.cs0);
75 err |= __put_user(regs->cs1, &sc->sc_regs.cs1);
76#endif
70 tmp = pt_elr(regs); err |= __put_user(tmp, &sc->sc_regs.pc); 77 tmp = pt_elr(regs); err |= __put_user(tmp, &sc->sc_regs.pc);
71 tmp = pt_cause(regs); err |= __put_user(tmp, &sc->sc_regs.cause); 78 tmp = pt_cause(regs); err |= __put_user(tmp, &sc->sc_regs.cause);
72 tmp = pt_badva(regs); err |= __put_user(tmp, &sc->sc_regs.badva); 79 tmp = pt_badva(regs); err |= __put_user(tmp, &sc->sc_regs.badva);
@@ -93,7 +100,10 @@ static int restore_sigcontext(struct pt_regs *regs,
93 err |= __get_user(regs->preds, &sc->sc_regs.p3_0); 100 err |= __get_user(regs->preds, &sc->sc_regs.p3_0);
94 err |= __get_user(regs->gp, &sc->sc_regs.gp); 101 err |= __get_user(regs->gp, &sc->sc_regs.gp);
95 err |= __get_user(regs->ugp, &sc->sc_regs.ugp); 102 err |= __get_user(regs->ugp, &sc->sc_regs.ugp);
96 103#if CONFIG_HEXAGON_ARCH_VERSION >= 4
104 err |= __get_user(regs->cs0, &sc->sc_regs.cs0);
105 err |= __get_user(regs->cs1, &sc->sc_regs.cs1);
106#endif
97 err |= __get_user(tmp, &sc->sc_regs.pc); pt_set_elr(regs, tmp); 107 err |= __get_user(tmp, &sc->sc_regs.pc); pt_set_elr(regs, tmp);
98 108
99 return err; 109 return err;
@@ -193,7 +203,7 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
193/* 203/*
194 * Called from return-from-event code. 204 * Called from return-from-event code.
195 */ 205 */
196static void do_signal(struct pt_regs *regs) 206void do_signal(struct pt_regs *regs)
197{ 207{
198 struct k_sigaction sigact; 208 struct k_sigaction sigact;
199 siginfo_t info; 209 siginfo_t info;
@@ -210,8 +220,9 @@ static void do_signal(struct pt_regs *regs)
210 } 220 }
211 221
212 /* 222 /*
213 * If we came from a system call, handle the restart. 223 * No (more) signals; if we came from a system call, handle the restart.
214 */ 224 */
225
215 if (regs->syscall_nr >= 0) { 226 if (regs->syscall_nr >= 0) {
216 switch (regs->r00) { 227 switch (regs->r00) {
217 case -ERESTARTNOHAND: 228 case -ERESTARTNOHAND:
@@ -234,17 +245,6 @@ no_restart:
234 restore_saved_sigmask(); 245 restore_saved_sigmask();
235} 246}
236 247
237void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
238{
239 if (thread_info_flags & _TIF_SIGPENDING)
240 do_signal(regs);
241
242 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
243 clear_thread_flag(TIF_NOTIFY_RESUME);
244 tracehook_notify_resume(regs);
245 }
246}
247
248/* 248/*
249 * Architecture-specific wrappers for signal-related system calls 249 * Architecture-specific wrappers for signal-related system calls
250 */ 250 */
@@ -272,21 +272,12 @@ asmlinkage int sys_rt_sigreturn(void)
272 /* Restore the user's stack as well */ 272 /* Restore the user's stack as well */
273 pt_psp(regs) = regs->r29; 273 pt_psp(regs) = regs->r29;
274 274
275 /* 275 regs->syscall_nr = -1;
276 * Leave a trace in the stack frame that this was a sigreturn.
277 * If the system call is to replay, we've already restored the
278 * number in the GPR slot and it will be regenerated on the
279 * new system call trap entry. Note that if restore_sigcontext()
280 * did something other than a bulk copy of the pt_regs struct,
281 * we could avoid this assignment by simply not overwriting
282 * regs->syscall_nr.
283 */
284 regs->syscall_nr = __NR_rt_sigreturn;
285 276
286 if (restore_altstack(&frame->uc.uc_stack)) 277 if (restore_altstack(&frame->uc.uc_stack))
287 goto badframe; 278 goto badframe;
288 279
289 return 0; 280 return regs->r00;
290 281
291badframe: 282badframe:
292 force_sig(SIGSEGV, current); 283 force_sig(SIGSEGV, current);
diff --git a/arch/hexagon/kernel/topology.c b/arch/hexagon/kernel/topology.c
deleted file mode 100644
index 352f27e809fd..000000000000
--- a/arch/hexagon/kernel/topology.c
+++ /dev/null
@@ -1,52 +0,0 @@
1/*
2 * CPU topology for Hexagon
3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and
8 * only version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA.
19 */
20
21#include <linux/cpu.h>
22#include <linux/cpumask.h>
23#include <linux/init.h>
24#include <linux/node.h>
25#include <linux/nodemask.h>
26#include <linux/percpu.h>
27
28/* Swiped from MIPS. */
29
30static DEFINE_PER_CPU(struct cpu, cpu_devices);
31
32static int __init topology_init(void)
33{
34 int i, ret;
35
36 for_each_present_cpu(i) {
37
38 /*
39 * register_cpu takes a per_cpu pointer and
40 * just points it at another per_cpu struct...
41 */
42
43 ret = register_cpu(&per_cpu(cpu_devices, i), i);
44 if (ret)
45 printk(KERN_WARNING "topology_init: register_cpu %d "
46 "failed (%d)\n", i, ret);
47 }
48
49 return 0;
50}
51
52subsys_initcall(topology_init);
diff --git a/arch/hexagon/kernel/traps.c b/arch/hexagon/kernel/traps.c
index cc2171b2aa04..7858663352b9 100644
--- a/arch/hexagon/kernel/traps.c
+++ b/arch/hexagon/kernel/traps.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Kernel traps/events for Hexagon processor 2 * Kernel traps/events for Hexagon processor
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and 7 * it under the terms of the GNU General Public License version 2 and
@@ -65,6 +65,10 @@ static const char *ex_name(int ex)
65 return "Write protection fault"; 65 return "Write protection fault";
66 case HVM_GE_C_XMAL: 66 case HVM_GE_C_XMAL:
67 return "Misaligned instruction"; 67 return "Misaligned instruction";
68 case HVM_GE_C_WREG:
69 return "Multiple writes to same register in packet";
70 case HVM_GE_C_PCAL:
71 return "Program counter values that are not properly aligned";
68 case HVM_GE_C_RMAL: 72 case HVM_GE_C_RMAL:
69 return "Misaligned data load"; 73 return "Misaligned data load";
70 case HVM_GE_C_WMAL: 74 case HVM_GE_C_WMAL:
@@ -316,6 +320,12 @@ void do_genex(struct pt_regs *regs)
316 case HVM_GE_C_XMAL: 320 case HVM_GE_C_XMAL:
317 misaligned_instruction(regs); 321 misaligned_instruction(regs);
318 break; 322 break;
323 case HVM_GE_C_WREG:
324 illegal_instruction(regs);
325 break;
326 case HVM_GE_C_PCAL:
327 misaligned_instruction(regs);
328 break;
319 case HVM_GE_C_RMAL: 329 case HVM_GE_C_RMAL:
320 misaligned_data_load(regs); 330 misaligned_data_load(regs);
321 break; 331 break;
@@ -348,7 +358,6 @@ long sys_syscall(void)
348 358
349void do_trap0(struct pt_regs *regs) 359void do_trap0(struct pt_regs *regs)
350{ 360{
351 unsigned long syscallret = 0;
352 syscall_fn syscall; 361 syscall_fn syscall;
353 362
354 switch (pt_cause(regs)) { 363 switch (pt_cause(regs)) {
@@ -388,21 +397,11 @@ void do_trap0(struct pt_regs *regs)
388 } else { 397 } else {
389 syscall = (syscall_fn) 398 syscall = (syscall_fn)
390 (sys_call_table[regs->syscall_nr]); 399 (sys_call_table[regs->syscall_nr]);
391 syscallret = syscall(regs->r00, regs->r01, 400 regs->r00 = syscall(regs->r00, regs->r01,
392 regs->r02, regs->r03, 401 regs->r02, regs->r03,
393 regs->r04, regs->r05); 402 regs->r04, regs->r05);
394 } 403 }
395 404
396 /*
397 * If it was a sigreturn system call, don't overwrite
398 * r0 value in stack frame with return value.
399 *
400 * __NR_sigreturn doesn't seem to exist in new unistd.h
401 */
402
403 if (regs->syscall_nr != __NR_rt_sigreturn)
404 regs->r00 = syscallret;
405
406 /* allow strace to get the syscall return state */ 405 /* allow strace to get the syscall return state */
407 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE))) 406 if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE)))
408 tracehook_report_syscall_exit(regs, 0); 407 tracehook_report_syscall_exit(regs, 0);
@@ -444,3 +443,14 @@ void do_machcheck(struct pt_regs *regs)
444 /* Halt and catch fire */ 443 /* Halt and catch fire */
445 __vmstop(); 444 __vmstop();
446} 445}
446
447/*
448 * Treat this like the old 0xdb trap.
449 */
450
451void do_debug_exception(struct pt_regs *regs)
452{
453 regs->hvmer.vmest &= ~HVM_VMEST_CAUSE_MSK;
454 regs->hvmer.vmest |= (TRAP_DEBUG << HVM_VMEST_CAUSE_SFT);
455 do_trap0(regs);
456}
diff --git a/arch/hexagon/kernel/vm_entry.S b/arch/hexagon/kernel/vm_entry.S
index 425e50c694f7..e3086185fc9f 100644
--- a/arch/hexagon/kernel/vm_entry.S
+++ b/arch/hexagon/kernel/vm_entry.S
@@ -1,7 +1,7 @@
1/* 1/*
2 * Event entry/exit for Hexagon 2 * Event entry/exit for Hexagon
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and 7 * it under the terms of the GNU General Public License version 2 and
@@ -45,48 +45,88 @@
45 * number in the case where we decode a system call (trap0(#1)). 45 * number in the case where we decode a system call (trap0(#1)).
46 */ 46 */
47 47
48#if CONFIG_HEXAGON_ARCH_VERSION < 4
48#define save_pt_regs()\ 49#define save_pt_regs()\
49 memd(R0 + #_PT_R3130) = R31:30; \ 50 memd(R0 + #_PT_R3130) = R31:30; \
51 { memw(R0 + #_PT_R2928) = R28; \
52 R31 = memw(R0 + #_PT_ER_VMPSP); }\
53 { memw(R0 + #(_PT_R2928 + 4)) = R31; \
54 R31 = ugp; } \
55 { memd(R0 + #_PT_R2726) = R27:26; \
56 R30 = gp ; } \
57 memd(R0 + #_PT_R2524) = R25:24; \
58 memd(R0 + #_PT_R2322) = R23:22; \
59 memd(R0 + #_PT_R2120) = R21:20; \
60 memd(R0 + #_PT_R1918) = R19:18; \
61 memd(R0 + #_PT_R1716) = R17:16; \
62 memd(R0 + #_PT_R1514) = R15:14; \
63 memd(R0 + #_PT_R1312) = R13:12; \
64 { memd(R0 + #_PT_R1110) = R11:10; \
65 R15 = lc0; } \
66 { memd(R0 + #_PT_R0908) = R9:8; \
67 R14 = sa0; } \
68 { memd(R0 + #_PT_R0706) = R7:6; \
69 R13 = lc1; } \
70 { memd(R0 + #_PT_R0504) = R5:4; \
71 R12 = sa1; } \
72 { memd(R0 + #_PT_GPUGP) = R31:30; \
73 R11 = m1; \
74 R2.H = #HI(_THREAD_SIZE); } \
75 { memd(R0 + #_PT_LC0SA0) = R15:14; \
76 R10 = m0; \
77 R2.L = #LO(_THREAD_SIZE); } \
78 { memd(R0 + #_PT_LC1SA1) = R13:12; \
79 R15 = p3:0; \
80 R2 = neg(R2); } \
81 { memd(R0 + #_PT_M1M0) = R11:10; \
82 R14 = usr; \
83 R2 = and(R0,R2); } \
84 { memd(R0 + #_PT_PREDSUSR) = R15:14; \
85 THREADINFO_REG = R2; } \
86 { r24 = memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS); \
87 memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R0; \
88 R2 = #-1; } \
89 { memw(R0 + #_PT_SYSCALL_NR) = R2; \
90 R30 = #0; }
91#else
92/* V4+ */
93/* the # ## # syntax inserts a literal ## */
94#define save_pt_regs()\
95 { memd(R0 + #_PT_R3130) = R31:30; \
96 R30 = memw(R0 + #_PT_ER_VMPSP); }\
50 { memw(R0 + #_PT_R2928) = R28; \ 97 { memw(R0 + #_PT_R2928) = R28; \
51 R31 = memw(R0 + #_PT_ER_VMPSP); }\ 98 memw(R0 + #(_PT_R2928 + 4)) = R30; }\
52 { memw(R0 + #(_PT_R2928 + 4)) = R31; \ 99 { R31:30 = C11:10; \
53 R31 = ugp; } \ 100 memd(R0 + #_PT_R2726) = R27:26; \
54 { memd(R0 + #_PT_R2726) = R27:26; \ 101 memd(R0 + #_PT_R2524) = R25:24; }\
55 R30 = gp ; } \ 102 { memd(R0 + #_PT_R2322) = R23:22; \
56 memd(R0 + #_PT_R2524) = R25:24; \ 103 memd(R0 + #_PT_R2120) = R21:20; }\
57 memd(R0 + #_PT_R2322) = R23:22; \ 104 { memd(R0 + #_PT_R1918) = R19:18; \
58 memd(R0 + #_PT_R2120) = R21:20; \ 105 memd(R0 + #_PT_R1716) = R17:16; }\
59 memd(R0 + #_PT_R1918) = R19:18; \ 106 { memd(R0 + #_PT_R1514) = R15:14; \
60 memd(R0 + #_PT_R1716) = R17:16; \ 107 memd(R0 + #_PT_R1312) = R13:12; \
61 memd(R0 + #_PT_R1514) = R15:14; \ 108 R17:16 = C13:12; }\
62 memd(R0 + #_PT_R1312) = R13:12; \
63 { memd(R0 + #_PT_R1110) = R11:10; \ 109 { memd(R0 + #_PT_R1110) = R11:10; \
64 R15 = lc0; } \ 110 memd(R0 + #_PT_R0908) = R9:8; \
65 { memd(R0 + #_PT_R0908) = R9:8; \ 111 R15:14 = C1:0; } \
66 R14 = sa0; } \
67 { memd(R0 + #_PT_R0706) = R7:6; \ 112 { memd(R0 + #_PT_R0706) = R7:6; \
68 R13 = lc1; } \ 113 memd(R0 + #_PT_R0504) = R5:4; \
69 { memd(R0 + #_PT_R0504) = R5:4; \ 114 R13:12 = C3:2; } \
70 R12 = sa1; } \ 115 { memd(R0 + #_PT_GPUGP) = R31:30; \
71 { memd(R0 + #_PT_UGPGP) = R31:30; \ 116 memd(R0 + #_PT_LC0SA0) = R15:14; \
72 R11 = m1; \ 117 R11:10 = C7:6; }\
73 R2.H = #HI(_THREAD_SIZE); } \ 118 { THREADINFO_REG = and(R0, # ## #-_THREAD_SIZE); \
74 { memd(R0 + #_PT_LC0SA0) = R15:14; \ 119 memd(R0 + #_PT_LC1SA1) = R13:12; \
75 R10 = m0; \ 120 R15 = p3:0; }\
76 R2.L = #LO(_THREAD_SIZE); } \
77 { memd(R0 + #_PT_LC1SA1) = R13:12; \
78 R15 = p3:0; \
79 R2 = neg(R2); } \
80 { memd(R0 + #_PT_M1M0) = R11:10; \ 121 { memd(R0 + #_PT_M1M0) = R11:10; \
81 R14 = usr; \ 122 memw(R0 + #_PT_PREDSUSR + 4) = R15; }\
82 R2 = and(R0,R2); } \
83 { memd(R0 + #_PT_PREDSUSR) = R15:14; \
84 THREADINFO_REG = R2; } \
85 { r24 = memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS); \ 123 { r24 = memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS); \
86 memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R0; \ 124 memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R0; \
87 R2 = #-1; } \ 125 R2 = #-1; } \
88 { memw(R0 + #_PT_SYSCALL_NR) = R2; \ 126 { memw(R0 + #_PT_SYSCALL_NR) = R2; \
127 memd(R0 + #_PT_CS1CS0) = R17:16; \
89 R30 = #0; } 128 R30 = #0; }
129#endif
90 130
91/* 131/*
92 * Restore registers and thread_info.regs state. THREADINFO_REG 132 * Restore registers and thread_info.regs state. THREADINFO_REG
@@ -94,6 +134,7 @@
94 * preserved. Don't restore R29 (SP) until later. 134 * preserved. Don't restore R29 (SP) until later.
95 */ 135 */
96 136
137#if CONFIG_HEXAGON_ARCH_VERSION < 4
97#define restore_pt_regs() \ 138#define restore_pt_regs() \
98 { memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R24; \ 139 { memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R24; \
99 R15:14 = memd(R0 + #_PT_PREDSUSR); } \ 140 R15:14 = memd(R0 + #_PT_PREDSUSR); } \
@@ -121,11 +162,44 @@
121 R23:22 = memd(R0 + #_PT_R2322); } \ 162 R23:22 = memd(R0 + #_PT_R2322); } \
122 { R25:24 = memd(R0 + #_PT_R2524); \ 163 { R25:24 = memd(R0 + #_PT_R2524); \
123 R27:26 = memd(R0 + #_PT_R2726); } \ 164 R27:26 = memd(R0 + #_PT_R2726); } \
124 R31:30 = memd(R0 + #_PT_UGPGP); \ 165 R31:30 = memd(R0 + #_PT_GPUGP); \
125 { R28 = memw(R0 + #_PT_R2928); \ 166 { R28 = memw(R0 + #_PT_R2928); \
126 ugp = R31; } \ 167 ugp = R31; } \
127 { R31:30 = memd(R0 + #_PT_R3130); \ 168 { R31:30 = memd(R0 + #_PT_R3130); \
128 gp = R30; } 169 gp = R30; }
170#else
171/* V4+ */
172#define restore_pt_regs() \
173 { memw(THREADINFO_REG + #_THREAD_INFO_PT_REGS) = R24; \
174 R15:14 = memd(R0 + #_PT_PREDSUSR); } \
175 { R11:10 = memd(R0 + #_PT_M1M0); \
176 R13:12 = memd(R0 + #_PT_LC1SA1); \
177 p3:0 = R15; } \
178 { R15:14 = memd(R0 + #_PT_LC0SA0); \
179 R3:2 = memd(R0 + #_PT_R0302); \
180 usr = R14; } \
181 { R5:4 = memd(R0 + #_PT_R0504); \
182 R7:6 = memd(R0 + #_PT_R0706); \
183 C7:6 = R11:10; }\
184 { R9:8 = memd(R0 + #_PT_R0908); \
185 R11:10 = memd(R0 + #_PT_R1110); \
186 C3:2 = R13:12; }\
187 { R13:12 = memd(R0 + #_PT_R1312); \
188 R15:14 = memd(R0 + #_PT_R1514); \
189 C1:0 = R15:14; }\
190 { R17:16 = memd(R0 + #_PT_R1716); \
191 R19:18 = memd(R0 + #_PT_R1918); } \
192 { R21:20 = memd(R0 + #_PT_R2120); \
193 R23:22 = memd(R0 + #_PT_R2322); } \
194 { R25:24 = memd(R0 + #_PT_R2524); \
195 R27:26 = memd(R0 + #_PT_R2726); } \
196 R31:30 = memd(R0 + #_PT_CS1CS0); \
197 { C13:12 = R31:30; \
198 R31:30 = memd(R0 + #_PT_GPUGP) ; \
199 R28 = memw(R0 + #_PT_R2928); }\
200 { C11:10 = R31:30; \
201 R31:30 = memd(R0 + #_PT_R3130); }
202#endif
129 203
130 /* 204 /*
131 * Clears off enough space for the rest of pt_regs; evrec is a part 205 * Clears off enough space for the rest of pt_regs; evrec is a part
@@ -139,6 +213,7 @@
139 * Need to save off R0, R1, R2, R3 immediately. 213 * Need to save off R0, R1, R2, R3 immediately.
140 */ 214 */
141 215
216#if CONFIG_HEXAGON_ARCH_VERSION < 4
142#define vm_event_entry(CHandler) \ 217#define vm_event_entry(CHandler) \
143 { \ 218 { \
144 R29 = add(R29, #-(_PT_REGS_SIZE)); \ 219 R29 = add(R29, #-(_PT_REGS_SIZE)); \
@@ -158,6 +233,34 @@
158 R1.H = #HI(CHandler); \ 233 R1.H = #HI(CHandler); \
159 jump event_dispatch; \ 234 jump event_dispatch; \
160 } 235 }
236#else
237/* V4+ */
238/* turn on I$ prefetch early */
239/* the # ## # syntax inserts a literal ## */
240#define vm_event_entry(CHandler) \
241 { \
242 R29 = add(R29, #-(_PT_REGS_SIZE)); \
243 memd(R29 + #(_PT_R0100 + -_PT_REGS_SIZE)) = R1:0; \
244 memd(R29 + #(_PT_R0302 + -_PT_REGS_SIZE)) = R3:2; \
245 R0 = usr; \
246 } \
247 { \
248 memw(R29 + #_PT_PREDSUSR) = R0; \
249 R0 = setbit(R0, #16); \
250 } \
251 usr = R0; \
252 R1:0 = G1:0; \
253 { \
254 memd(R29 + #_PT_ER_VMEL) = R1:0; \
255 R1 = # ## #(CHandler); \
256 R3:2 = G3:2; \
257 } \
258 { \
259 R0 = R29; \
260 memd(R29 + #_PT_ER_VMPSP) = R3:2; \
261 jump event_dispatch; \
262 }
263#endif
161 264
162.text 265.text
163 /* 266 /*
@@ -171,6 +274,9 @@ event_dispatch:
171 callr r1 274 callr r1
172 275
173 /* 276 /*
277 * Coming back from the C-world, our thread info pointer
278 * should be in the designated register (usually R19)
279 *
174 * If we were in kernel mode, we don't need to check scheduler 280 * If we were in kernel mode, we don't need to check scheduler
175 * or signals if CONFIG_PREEMPT is not set. If set, then it has 281 * or signals if CONFIG_PREEMPT is not set. If set, then it has
176 * to jump to a need_resched kind of block. 282 * to jump to a need_resched kind of block.
@@ -183,69 +289,68 @@ event_dispatch:
183#endif 289#endif
184 290
185 /* "Nested control path" -- if the previous mode was kernel */ 291 /* "Nested control path" -- if the previous mode was kernel */
186 R0 = memw(R29 + #_PT_ER_VMEST);
187 P0 = tstbit(R0, #HVM_VMEST_UM_SFT);
188 if !P0 jump restore_all;
189 /*
190 * Returning from system call, normally coming back from user mode
191 */
192return_from_syscall:
193 /* Disable interrupts while checking TIF */
194 R0 = #VM_INT_DISABLE
195 trap1(#HVM_TRAP1_VMSETIE)
196
197 /*
198 * Coming back from the C-world, our thread info pointer
199 * should be in the designated register (usually R19)
200 */
201 R1.L = #LO(_TIF_ALLWORK_MASK)
202 { 292 {
203 R1.H = #HI(_TIF_ALLWORK_MASK); 293 R0 = memw(R29 + #_PT_ER_VMEST);
204 R0 = memw(THREADINFO_REG + #_THREAD_INFO_FLAGS); 294 R16.L = #LO(do_work_pending);
295 }
296 {
297 P0 = tstbit(R0, #HVM_VMEST_UM_SFT);
298 if (!P0.new) jump:nt restore_all;
299 R16.H = #HI(do_work_pending);
300 R0 = #VM_INT_DISABLE;
205 } 301 }
206 302
207 /* 303 /*
208 * Compare against the "return to userspace" _TIF_WORK_MASK 304 * Check also the return from fork/system call, normally coming back from
305 * user mode
306 *
307 * R16 needs to have do_work_pending, and R0 should have VM_INT_DISABLE
209 */ 308 */
210 R1 = and(R1,R0);
211 { P0 = cmp.eq(R1,#0); if (!P0.new) jump:t work_pending;}
212 jump restore_all; /* we're outta here! */
213 309
214work_pending: 310check_work_pending:
311 /* Disable interrupts while checking TIF */
312 trap1(#HVM_TRAP1_VMSETIE)
215 { 313 {
216 P0 = tstbit(R1, #TIF_NEED_RESCHED); 314 R0 = R29; /* regs should still be at top of stack */
217 if (!P0.new) jump:nt work_notifysig; 315 R1 = memw(THREADINFO_REG + #_THREAD_INFO_FLAGS);
316 callr R16;
218 } 317 }
219 call schedule
220 jump return_from_syscall; /* check for more work */
221 318
222work_notifysig: 319 {
223 /* this is the part that's kind of fuzzy. */ 320 P0 = cmp.eq(R0, #0); if (!P0.new) jump:nt check_work_pending;
224 R1 = and(R0, #(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME)); 321 R0 = #VM_INT_DISABLE;
225 P0 = cmp.eq(R1, #0); 322 }
226 if P0 jump restore_all
227 R1 = R0; /* unsigned long thread_info_flags */
228 R0 = R29; /* regs should still be at top of stack */
229 call do_notify_resume
230 323
231restore_all: 324restore_all:
232 /* Disable interrupts, if they weren't already, before reg restore. */ 325 /*
233 R0 = #VM_INT_DISABLE 326 * Disable interrupts, if they weren't already, before reg restore.
327 * R0 gets preloaded with #VM_INT_DISABLE before we get here.
328 */
234 trap1(#HVM_TRAP1_VMSETIE) 329 trap1(#HVM_TRAP1_VMSETIE)
235 330
236 /* do the setregs here for VM 0.5 */ 331 /* do the setregs here for VM 0.5 */
237 /* R29 here should already be pointing at pt_regs */ 332 /* R29 here should already be pointing at pt_regs */
238 R1:0 = memd(R29 + #_PT_ER_VMEL); 333 {
239 R3:2 = memd(R29 + #_PT_ER_VMPSP); 334 R1:0 = memd(R29 + #_PT_ER_VMEL);
335 R3:2 = memd(R29 + #_PT_ER_VMPSP);
336 }
337#if CONFIG_HEXAGON_ARCH_VERSION < 4
240 trap1(#HVM_TRAP1_VMSETREGS); 338 trap1(#HVM_TRAP1_VMSETREGS);
339#else
340 G1:0 = R1:0;
341 G3:2 = R3:2;
342#endif
241 343
242 R0 = R29 344 R0 = R29
243 restore_pt_regs() 345 restore_pt_regs()
244 R1:0 = memd(R29 + #_PT_R0100); 346 {
245 R29 = add(R29, #_PT_REGS_SIZE); 347 R1:0 = memd(R29 + #_PT_R0100);
348 R29 = add(R29, #_PT_REGS_SIZE);
349 }
246 trap1(#HVM_TRAP1_VMRTE) 350 trap1(#HVM_TRAP1_VMRTE)
247 /* Notreached */ 351 /* Notreached */
248 352
353
249 .globl _K_enter_genex 354 .globl _K_enter_genex
250_K_enter_genex: 355_K_enter_genex:
251 vm_event_entry(do_genex) 356 vm_event_entry(do_genex)
@@ -262,12 +367,27 @@ _K_enter_trap0:
262_K_enter_machcheck: 367_K_enter_machcheck:
263 vm_event_entry(do_machcheck) 368 vm_event_entry(do_machcheck)
264 369
370 .globl _K_enter_debug
371_K_enter_debug:
372 vm_event_entry(do_debug_exception)
265 373
266 .globl ret_from_fork 374 .globl ret_from_fork
267ret_from_fork: 375ret_from_fork:
268 call schedule_tail 376 {
269 P0 = cmp.eq(R24, #0); 377 call schedule_tail
270 if P0 jump return_from_syscall 378 R16.H = #HI(do_work_pending);
271 R0 = R25; 379 }
272 callr R24 380 {
273 jump return_from_syscall 381 P0 = cmp.eq(R24, #0);
382 R16.L = #LO(do_work_pending);
383 R0 = #VM_INT_DISABLE;
384 }
385 if P0 jump check_work_pending
386 {
387 R0 = R25;
388 callr R24
389 }
390 {
391 jump check_work_pending
392 R0 = #VM_INT_DISABLE;
393 }
diff --git a/arch/hexagon/kernel/vm_events.c b/arch/hexagon/kernel/vm_events.c
index f337281ebe67..741aaa917cda 100644
--- a/arch/hexagon/kernel/vm_events.c
+++ b/arch/hexagon/kernel/vm_events.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Mostly IRQ support for Hexagon 2 * Mostly IRQ support for Hexagon
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and 7 * it under the terms of the GNU General Public License version 2 and
@@ -44,6 +44,8 @@ void show_regs(struct pt_regs *regs)
44 regs->lc1, regs->sa1, regs->m1); 44 regs->lc1, regs->sa1, regs->m1);
45 printk(KERN_EMERG "gp: \t0x%08lx ugp: 0x%08lx usr: 0x%08lx\n", 45 printk(KERN_EMERG "gp: \t0x%08lx ugp: 0x%08lx usr: 0x%08lx\n",
46 regs->gp, regs->ugp, regs->usr); 46 regs->gp, regs->ugp, regs->usr);
47 printk(KERN_EMERG "cs0: \t0x%08lx cs1: 0x%08lx\n",
48 regs->cs0, regs->cs1);
47 printk(KERN_EMERG "r0: \t0x%08lx %08lx %08lx %08lx\n", regs->r00, 49 printk(KERN_EMERG "r0: \t0x%08lx %08lx %08lx %08lx\n", regs->r00,
48 regs->r01, 50 regs->r01,
49 regs->r02, 51 regs->r02,
diff --git a/arch/hexagon/kernel/vm_vectors.S b/arch/hexagon/kernel/vm_vectors.S
index 620f42cc582a..791a7422dde4 100644
--- a/arch/hexagon/kernel/vm_vectors.S
+++ b/arch/hexagon/kernel/vm_vectors.S
@@ -1,7 +1,7 @@
1/* 1/*
2 * Event jump tables 2 * Event jump tables
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2012,2013, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and 7 * it under the terms of the GNU General Public License version 2 and
@@ -41,7 +41,7 @@ _K_VM_event_vector:
41 jump 1b; /* Reset */ 41 jump 1b; /* Reset */
42 jump _K_enter_machcheck; 42 jump _K_enter_machcheck;
43 jump _K_enter_genex; 43 jump _K_enter_genex;
44 jump 1b; /* 3 Rsvd */ 44 jump _K_enter_debug;
45 jump 1b; /* 4 Rsvd */ 45 jump 1b; /* 4 Rsvd */
46 jump _K_enter_trap0; 46 jump _K_enter_trap0;
47 jump 1b; /* 6 Rsvd */ 47 jump 1b; /* 6 Rsvd */
diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
index 14e793f6abbf..44d8c47bae2f 100644
--- a/arch/hexagon/kernel/vmlinux.lds.S
+++ b/arch/hexagon/kernel/vmlinux.lds.S
@@ -1,7 +1,7 @@
1/* 1/*
2 * Linker script for Hexagon kernel 2 * Linker script for Hexagon kernel
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and 7 * it under the terms of the GNU General Public License version 2 and
@@ -18,8 +18,6 @@
18 * 02110-1301, USA. 18 * 02110-1301, USA.
19 */ 19 */
20 20
21#define LOAD_OFFSET PAGE_OFFSET
22
23#include <asm-generic/vmlinux.lds.h> 21#include <asm-generic/vmlinux.lds.h>
24#include <asm/asm-offsets.h> /* Most of the kernel defines are here */ 22#include <asm/asm-offsets.h> /* Most of the kernel defines are here */
25#include <asm/mem-layout.h> /* except for page_offset */ 23#include <asm/mem-layout.h> /* except for page_offset */
@@ -36,13 +34,9 @@ See asm-generic/sections.h for seemingly required labels.
36 34
37#define PAGE_SIZE _PAGE_SIZE 35#define PAGE_SIZE _PAGE_SIZE
38 36
39/* This LOAD_OFFSET is temporary for debugging on the simulator; it may change
40 for hypervisor pseudo-physical memory. */
41
42
43SECTIONS 37SECTIONS
44{ 38{
45 . = PAGE_OFFSET + LOAD_ADDRESS; 39 . = PAGE_OFFSET;
46 40
47 __init_begin = .; 41 __init_begin = .;
48 HEAD_TEXT_SECTION 42 HEAD_TEXT_SECTION
@@ -52,7 +46,7 @@ SECTIONS
52 46
53 . = ALIGN(_PAGE_SIZE); 47 . = ALIGN(_PAGE_SIZE);
54 _stext = .; 48 _stext = .;
55 .text : AT(ADDR(.text) - LOAD_OFFSET) { 49 .text : AT(ADDR(.text)) {
56 _text = .; 50 _text = .;
57 TEXT_TEXT 51 TEXT_TEXT
58 SCHED_TEXT 52 SCHED_TEXT
diff --git a/arch/hexagon/mm/init.c b/arch/hexagon/mm/init.c
index 69ffcfd28794..2561d259a296 100644
--- a/arch/hexagon/mm/init.c
+++ b/arch/hexagon/mm/init.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Memory subsystem initialization for Hexagon 2 * Memory subsystem initialization for Hexagon
3 * 3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify 6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and 7 * it under the terms of the GNU General Public License version 2 and
@@ -31,9 +31,10 @@
31 * Define a startpg just past the end of the kernel image and a lastpg 31 * Define a startpg just past the end of the kernel image and a lastpg
32 * that corresponds to the end of real or simulated platform memory. 32 * that corresponds to the end of real or simulated platform memory.
33 */ 33 */
34#define bootmem_startpg (PFN_UP(((unsigned long) _end) - PAGE_OFFSET)) 34#define bootmem_startpg (PFN_UP(((unsigned long) _end) - PAGE_OFFSET + PHYS_OFFSET))
35 35
36unsigned long bootmem_lastpg; /* Should be set by platform code */ 36unsigned long bootmem_lastpg; /* Should be set by platform code */
37unsigned long __phys_offset; /* physical kernel offset >> 12 */
37 38
38/* Set as variable to limit PMD copies */ 39/* Set as variable to limit PMD copies */
39int max_kernel_seg = 0x303; 40int max_kernel_seg = 0x303;
@@ -44,7 +45,6 @@ unsigned long zero_page_mask;
44/* indicate pfn's of high memory */ 45/* indicate pfn's of high memory */
45unsigned long highstart_pfn, highend_pfn; 46unsigned long highstart_pfn, highend_pfn;
46 47
47/* struct mmu_gather defined in asm-generic.h; */
48DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); 48DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
49 49
50/* Default cache attribute for newly created page tables */ 50/* Default cache attribute for newly created page tables */
@@ -71,7 +71,7 @@ void __init mem_init(void)
71{ 71{
72 /* No idea where this is actually declared. Seems to evade LXR. */ 72 /* No idea where this is actually declared. Seems to evade LXR. */
73 totalram_pages += free_all_bootmem(); 73 totalram_pages += free_all_bootmem();
74 num_physpages = bootmem_lastpg; /* seriously, what? */ 74 num_physpages = bootmem_lastpg-ARCH_PFN_OFFSET;
75 75
76 printk(KERN_INFO "totalram_pages = %ld\n", totalram_pages); 76 printk(KERN_INFO "totalram_pages = %ld\n", totalram_pages);
77 77
@@ -193,6 +193,9 @@ void __init setup_arch_memory(void)
193 * This needs to change for highmem setups. 193 * This needs to change for highmem setups.
194 */ 194 */
195 195
196 /* Prior to this, bootmem_lastpg is actually mem size */
197 bootmem_lastpg += ARCH_PFN_OFFSET;
198
196 /* Memory size needs to be a multiple of 16M */ 199 /* Memory size needs to be a multiple of 16M */
197 bootmem_lastpg = PFN_DOWN((bootmem_lastpg << PAGE_SHIFT) & 200 bootmem_lastpg = PFN_DOWN((bootmem_lastpg << PAGE_SHIFT) &
198 ~((BIG_KERNEL_PAGE_SIZE) - 1)); 201 ~((BIG_KERNEL_PAGE_SIZE) - 1));
@@ -201,12 +204,15 @@ void __init setup_arch_memory(void)
201 * Reserve the top DMA_RESERVE bytes of RAM for DMA (uncached) 204 * Reserve the top DMA_RESERVE bytes of RAM for DMA (uncached)
202 * memory allocation 205 * memory allocation
203 */ 206 */
204 bootmap_size = init_bootmem(bootmem_startpg, bootmem_lastpg - 207
205 PFN_DOWN(DMA_RESERVED_BYTES)); 208 max_low_pfn = bootmem_lastpg - PFN_DOWN(DMA_RESERVED_BYTES);
209 min_low_pfn = ARCH_PFN_OFFSET;
210 bootmap_size = init_bootmem_node(NODE_DATA(0), bootmem_startpg, min_low_pfn, max_low_pfn);
206 211
207 printk(KERN_INFO "bootmem_startpg: 0x%08lx\n", bootmem_startpg); 212 printk(KERN_INFO "bootmem_startpg: 0x%08lx\n", bootmem_startpg);
208 printk(KERN_INFO "bootmem_lastpg: 0x%08lx\n", bootmem_lastpg); 213 printk(KERN_INFO "bootmem_lastpg: 0x%08lx\n", bootmem_lastpg);
209 printk(KERN_INFO "bootmap_size: %d\n", bootmap_size); 214 printk(KERN_INFO "bootmap_size: %d\n", bootmap_size);
215 printk(KERN_INFO "min_low_pfn: 0x%08lx\n", min_low_pfn);
210 printk(KERN_INFO "max_low_pfn: 0x%08lx\n", max_low_pfn); 216 printk(KERN_INFO "max_low_pfn: 0x%08lx\n", max_low_pfn);
211 217
212 /* 218 /*
@@ -221,14 +227,17 @@ void __init setup_arch_memory(void)
221 /* this actually only goes to the end of the first gig */ 227 /* this actually only goes to the end of the first gig */
222 segtable_end = segtable + (1<<(30-22)); 228 segtable_end = segtable + (1<<(30-22));
223 229
224 /* Move forward to the start of empty pages */ 230 /*
225 segtable += bootmem_lastpg >> (22-PAGE_SHIFT); 231 * Move forward to the start of empty pages; take into account
232 * phys_offset shift.
233 */
226 234
235 segtable += (bootmem_lastpg-ARCH_PFN_OFFSET)>>(22-PAGE_SHIFT);
227 { 236 {
228 int i; 237 int i;
229 238
230 for (i = 1 ; i <= DMA_RESERVE ; i++) 239 for (i = 1 ; i <= DMA_RESERVE ; i++)
231 segtable[-i] = ((segtable[-i] & __HVM_PTE_PGMASK_4MB) 240 segtable[-i] = ((segtable[-i] & __HVM_PTE_PGMASK_4MB)
232 | __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X 241 | __HVM_PTE_R | __HVM_PTE_W | __HVM_PTE_X
233 | __HEXAGON_C_UNC << 6 242 | __HEXAGON_C_UNC << 6
234 | __HVM_PDE_S_4MB); 243 | __HVM_PDE_S_4MB);
@@ -256,7 +265,7 @@ void __init setup_arch_memory(void)
256 * Free all the memory that wasn't taken up by the bootmap, the DMA 265 * Free all the memory that wasn't taken up by the bootmap, the DMA
257 * reserve, or kernel itself. 266 * reserve, or kernel itself.
258 */ 267 */
259 free_bootmem(PFN_PHYS(bootmem_startpg)+bootmap_size, 268 free_bootmem(PFN_PHYS(bootmem_startpg) + bootmap_size,
260 PFN_PHYS(bootmem_lastpg - bootmem_startpg) - bootmap_size - 269 PFN_PHYS(bootmem_lastpg - bootmem_startpg) - bootmap_size -
261 DMA_RESERVED_BYTES); 270 DMA_RESERVED_BYTES);
262 271
diff --git a/arch/hexagon/mm/vm_fault.c b/arch/hexagon/mm/vm_fault.c
index 308ef0ce648b..1bd276dbec7d 100644
--- a/arch/hexagon/mm/vm_fault.c
+++ b/arch/hexagon/mm/vm_fault.c
@@ -147,7 +147,7 @@ good_area:
147 } 147 }
148 info.si_errno = 0; 148 info.si_errno = 0;
149 info.si_addr = (void __user *)address; 149 info.si_addr = (void __user *)address;
150 force_sig_info(info.si_code, &info, current); 150 force_sig_info(info.si_signo, &info, current);
151 return; 151 return;
152 152
153bad_area: 153bad_area:
@@ -158,7 +158,7 @@ bad_area:
158 info.si_errno = 0; 158 info.si_errno = 0;
159 info.si_code = si_code; 159 info.si_code = si_code;
160 info.si_addr = (void *)address; 160 info.si_addr = (void *)address;
161 force_sig_info(SIGSEGV, &info, current); 161 force_sig_info(info.si_signo, &info, current);
162 return; 162 return;
163 } 163 }
164 /* Kernel-mode fault falls through */ 164 /* Kernel-mode fault falls through */