diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-01 10:43:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-01 10:43:05 -0400 |
commit | d70b1e06eb331afe1576ac23bb9523708026ba1f (patch) | |
tree | a6e430d45f8f7f37285369dcfd863a0358080c83 /arch/hexagon | |
parent | b0b885657b6c8ef63a46bc9299b2a7715d19acde (diff) | |
parent | 426d29ccb2a8d44c18d3167327ee82b38287e7bf (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')
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 | ||
36 | config HEXAGON_ARCH_V1 | 39 | config HEXAGON_PHYS_OFFSET |
37 | bool | 40 | def_bool y |
38 | 41 | ---help--- | |
39 | config HEXAGON_ARCH_V2 | 42 | Platforms that don't load the kernel at zero set this. |
40 | bool | ||
41 | |||
42 | config HEXAGON_ARCH_V3 | ||
43 | bool | ||
44 | |||
45 | config HEXAGON_ARCH_V4 | ||
46 | bool | ||
47 | 43 | ||
48 | config FRAME_POINTER | 44 | config FRAME_POINTER |
49 | def_bool y | 45 | def_bool y |
@@ -81,9 +77,6 @@ config RWSEM_GENERIC_SPINLOCK | |||
81 | config RWSEM_XCHGADD_ALGORITHM | 77 | config RWSEM_XCHGADD_ALGORITHM |
82 | def_bool y | 78 | def_bool y |
83 | 79 | ||
84 | config GENERIC_FIND_NEXT_BIT | ||
85 | def_bool y | ||
86 | |||
87 | config GENERIC_HWEIGHT | 80 | config GENERIC_HWEIGHT |
88 | def_bool y | 81 | def_bool y |
89 | 82 | ||
@@ -103,14 +96,14 @@ choice | |||
103 | 96 | ||
104 | config HEXAGON_COMET | 97 | config 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 | ||
110 | endchoice | 102 | endchoice |
111 | 103 | ||
112 | config HEXAGON_VM | 104 | config HEXAGON_ARCH_VERSION |
113 | def_bool y | 105 | int "Architecture version" |
106 | default 2 | ||
114 | 107 | ||
115 | config CMDLINE | 108 | config 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 | ||
125 | config HEXAGON_ANGEL_TRAPS | ||
126 | bool "Use Angel Traps" | ||
127 | default n | ||
128 | ---help--- | ||
129 | Enable angel debug traps (for printk's). | ||
130 | |||
131 | config SMP | 118 | config 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 |
16 | CFLAGS_MODULE += -mlong-calls | 16 | CFLAGS_MODULE += -mlong-calls |
17 | 17 | ||
18 | cflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1) | 18 | cflags-y += $(call cc-option,-mv${CONFIG_HEXAGON_ARCH_VERSION}) |
19 | cflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2) | 19 | aflags-y += $(call cc-option,-mv${CONFIG_HEXAGON_ARCH_VERSION}) |
20 | cflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3) | 20 | ldflags-y += $(call cc-option,-mv${CONFIG_HEXAGON_ARCH_VERSION}) |
21 | cflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4) | ||
22 | |||
23 | aflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1) | ||
24 | aflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2) | ||
25 | aflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3) | ||
26 | aflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4) | ||
27 | |||
28 | ldflags-$(CONFIG_HEXAGON_ARCH_V1) += $(call cc-option,-mv1) | ||
29 | ldflags-$(CONFIG_HEXAGON_ARCH_V2) += $(call cc-option,-mv2) | ||
30 | ldflags-$(CONFIG_HEXAGON_ARCH_V3) += $(call cc-option,-mv3) | ||
31 | ldflags-$(CONFIG_HEXAGON_ARCH_V4) += $(call cc-option,-mv4) | ||
32 | 21 | ||
33 | KBUILD_CFLAGS += $(cflags-y) | 22 | KBUILD_CFLAGS += $(cflags-y) |
34 | KBUILD_AFLAGS += $(aflags-y) | 23 | KBUILD_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 | |||
25 | generic-y += kmap_types.h | 25 | generic-y += kmap_types.h |
26 | generic-y += local64.h | 26 | generic-y += local64.h |
27 | generic-y += local.h | 27 | generic-y += local.h |
28 | generic-y += local.h | ||
29 | generic-y += mman.h | 28 | generic-y += mman.h |
30 | generic-y += msgbuf.h | 29 | generic-y += msgbuf.h |
31 | generic-y += pci.h | 30 | generic-y += pci.h |
@@ -41,6 +40,7 @@ generic-y += sembuf.h | |||
41 | generic-y += shmbuf.h | 40 | generic-y += shmbuf.h |
42 | generic-y += shmparam.h | 41 | generic-y += shmparam.h |
43 | generic-y += siginfo.h | 42 | generic-y += siginfo.h |
43 | generic-y += sizes.h | ||
44 | generic-y += socket.h | 44 | generic-y += socket.h |
45 | generic-y += sockios.h | 45 | generic-y += sockios.h |
46 | generic-y += statfs.h | 46 | generic-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 | |||
127 | static inline int __atomic_add_unless(atomic_t *v, int a, int u) | 129 | static 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) \ | ||
109 | do {\ | ||
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) \ |
108 | do { \ | 118 | do { \ |
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 | |||
43 | extern int remap_area_pages(unsigned long start, unsigned long phys_addr, | 45 | extern 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__ |
42 | extern 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 */ |
59 | extern int max_kernel_seg; | 68 | extern 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 */ |
103 | struct page; | 103 | struct 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 | ||
102 | struct hexagon_switch_stack { | 102 | struct 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 | |||
22 | extern unsigned long __rt_sigtramp_template[2]; | 24 | extern unsigned long __rt_sigtramp_template[2]; |
23 | 25 | ||
26 | void 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 @@ | |||
1 | extra-y := head.o vmlinux.lds | 1 | extra-y := head.o vmlinux.lds |
2 | 2 | ||
3 | obj-$(CONFIG_SMP) += smp.o topology.o | 3 | obj-$(CONFIG_SMP) += smp.o |
4 | 4 | ||
5 | obj-y += setup.o irq_cpu.o traps.o syscalltab.o signal.o time.o | 5 | obj-y += setup.o irq_cpu.o traps.o syscalltab.o signal.o time.o |
6 | obj-y += process.o trampoline.o reset.o ptrace.o vdso.o | 6 | obj-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 | ||
27 | struct dma_map_ops *dma_ops; | 28 | struct dma_map_ops *dma_ops; |
28 | EXPORT_SYMBOL(dma_ops); | 29 | EXPORT_SYMBOL(dma_ops); |
29 | 30 | ||
30 | int bad_dma_address; /* globals are automatically initialized to zero */ | 31 | int bad_dma_address; /* globals are automatically initialized to zero */ |
31 | 32 | ||
33 | static inline void *dma_addr_to_virt(dma_addr_t dma_addr) | ||
34 | { | ||
35 | return phys_to_virt((unsigned long) dma_addr); | ||
36 | } | ||
37 | |||
32 | int dma_supported(struct device *dev, u64 mask) | 38 | int 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 | ||
152 | static 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 |
30 | ENTRY(stext) | 33 | ENTRY(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) | 103 | 1: |
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); |
123 | 1: | ||
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 | |||
98 | 1: | 165 | 1: |
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 | |||
200 | int 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 */ | ||
37 | void 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 | |||
43 | void 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 | |||
35 | static int genregs_get(struct task_struct *target, | 50 | static 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(®s->cs0, cs0); | ||
96 | ONEXT(®s->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(®s->cs0, cs0); | ||
147 | INEXT(®s->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 | */ |
196 | static void do_signal(struct pt_regs *regs) | 206 | void 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 | ||
237 | void 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 | ||
291 | badframe: | 282 | badframe: |
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 | |||
30 | static DEFINE_PER_CPU(struct cpu, cpu_devices); | ||
31 | |||
32 | static 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 | |||
52 | subsys_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 | ||
349 | void do_trap0(struct pt_regs *regs) | 359 | void 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 | |||
451 | void 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 | */ | ||
192 | return_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 | ||
214 | work_pending: | 310 | check_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 | ||
222 | work_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 | ||
231 | restore_all: | 324 | restore_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 |
267 | ret_from_fork: | 375 | ret_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 | |||
43 | SECTIONS | 37 | SECTIONS |
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 | ||
36 | unsigned long bootmem_lastpg; /* Should be set by platform code */ | 36 | unsigned long bootmem_lastpg; /* Should be set by platform code */ |
37 | unsigned 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 */ |
39 | int max_kernel_seg = 0x303; | 40 | int 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 */ |
45 | unsigned long highstart_pfn, highend_pfn; | 46 | unsigned long highstart_pfn, highend_pfn; |
46 | 47 | ||
47 | /* struct mmu_gather defined in asm-generic.h; */ | ||
48 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | 48 | DEFINE_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 | ||
153 | bad_area: | 153 | bad_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 */ |