diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/tile/kernel | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'arch/tile/kernel')
38 files changed, 5692 insertions, 690 deletions
diff --git a/arch/tile/kernel/Makefile b/arch/tile/kernel/Makefile index 112b1e248f05..b4dbc057baad 100644 --- a/arch/tile/kernel/Makefile +++ b/arch/tile/kernel/Makefile | |||
@@ -5,7 +5,7 @@ | |||
5 | extra-y := vmlinux.lds head_$(BITS).o | 5 | extra-y := vmlinux.lds head_$(BITS).o |
6 | obj-y := backtrace.o entry.o init_task.o irq.o messaging.o \ | 6 | obj-y := backtrace.o entry.o init_task.o irq.o messaging.o \ |
7 | pci-dma.o proc.o process.o ptrace.o reboot.o \ | 7 | pci-dma.o proc.o process.o ptrace.o reboot.o \ |
8 | setup.o signal.o single_step.o stack.o sys.o time.o traps.o \ | 8 | setup.o signal.o single_step.o stack.o sys.o sysfs.o time.o traps.o \ |
9 | intvec_$(BITS).o regs_$(BITS).o tile-desc_$(BITS).o | 9 | intvec_$(BITS).o regs_$(BITS).o tile-desc_$(BITS).o |
10 | 10 | ||
11 | obj-$(CONFIG_HARDWALL) += hardwall.o | 11 | obj-$(CONFIG_HARDWALL) += hardwall.o |
@@ -15,3 +15,4 @@ obj-$(CONFIG_SMP) += smpboot.o smp.o tlb.o | |||
15 | obj-$(CONFIG_MODULES) += module.o | 15 | obj-$(CONFIG_MODULES) += module.o |
16 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 16 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
17 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o | 17 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o |
18 | obj-$(CONFIG_PCI) += pci.o | ||
diff --git a/arch/tile/kernel/backtrace.c b/arch/tile/kernel/backtrace.c index d3c41c1ff6bd..1dc71eabfc5a 100644 --- a/arch/tile/kernel/backtrace.c +++ b/arch/tile/kernel/backtrace.c | |||
@@ -14,19 +14,11 @@ | |||
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
17 | |||
18 | #include <asm/backtrace.h> | 17 | #include <asm/backtrace.h> |
19 | |||
20 | #include <arch/chip.h> | ||
21 | |||
22 | #include <asm/opcode-tile.h> | 18 | #include <asm/opcode-tile.h> |
19 | #include <arch/abi.h> | ||
23 | 20 | ||
24 | 21 | #ifdef __tilegx__ | |
25 | #define TREG_SP 54 | ||
26 | #define TREG_LR 55 | ||
27 | |||
28 | |||
29 | #if TILE_CHIP >= 10 | ||
30 | #define tile_bundle_bits tilegx_bundle_bits | 22 | #define tile_bundle_bits tilegx_bundle_bits |
31 | #define TILE_MAX_INSTRUCTIONS_PER_BUNDLE TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE | 23 | #define TILE_MAX_INSTRUCTIONS_PER_BUNDLE TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE |
32 | #define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEGX_BUNDLE_ALIGNMENT_IN_BYTES | 24 | #define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEGX_BUNDLE_ALIGNMENT_IN_BYTES |
@@ -47,7 +39,7 @@ typedef long long bt_int_reg_t; | |||
47 | typedef int bt_int_reg_t; | 39 | typedef int bt_int_reg_t; |
48 | #endif | 40 | #endif |
49 | 41 | ||
50 | /** A decoded bundle used for backtracer analysis. */ | 42 | /* A decoded bundle used for backtracer analysis. */ |
51 | struct BacktraceBundle { | 43 | struct BacktraceBundle { |
52 | tile_bundle_bits bits; | 44 | tile_bundle_bits bits; |
53 | int num_insns; | 45 | int num_insns; |
@@ -56,23 +48,7 @@ struct BacktraceBundle { | |||
56 | }; | 48 | }; |
57 | 49 | ||
58 | 50 | ||
59 | /* This implementation only makes sense for native tools. */ | 51 | /* Locates an instruction inside the given bundle that |
60 | /** Default function to read memory. */ | ||
61 | static bool bt_read_memory(void *result, VirtualAddress addr, | ||
62 | unsigned int size, void *extra) | ||
63 | { | ||
64 | /* FIXME: this should do some horrible signal stuff to catch | ||
65 | * SEGV cleanly and fail. | ||
66 | * | ||
67 | * Or else the caller should do the setjmp for efficiency. | ||
68 | */ | ||
69 | |||
70 | memcpy(result, (const void *)addr, size); | ||
71 | return true; | ||
72 | } | ||
73 | |||
74 | |||
75 | /** Locates an instruction inside the given bundle that | ||
76 | * has the specified mnemonic, and whose first 'num_operands_to_match' | 52 | * has the specified mnemonic, and whose first 'num_operands_to_match' |
77 | * operands exactly match those in 'operand_values'. | 53 | * operands exactly match those in 'operand_values'. |
78 | */ | 54 | */ |
@@ -107,13 +83,13 @@ static const struct tile_decoded_instruction *find_matching_insn( | |||
107 | return NULL; | 83 | return NULL; |
108 | } | 84 | } |
109 | 85 | ||
110 | /** Does this bundle contain an 'iret' instruction? */ | 86 | /* Does this bundle contain an 'iret' instruction? */ |
111 | static inline bool bt_has_iret(const struct BacktraceBundle *bundle) | 87 | static inline bool bt_has_iret(const struct BacktraceBundle *bundle) |
112 | { | 88 | { |
113 | return find_matching_insn(bundle, TILE_OPC_IRET, NULL, 0) != NULL; | 89 | return find_matching_insn(bundle, TILE_OPC_IRET, NULL, 0) != NULL; |
114 | } | 90 | } |
115 | 91 | ||
116 | /** Does this bundle contain an 'addi sp, sp, OFFSET' or | 92 | /* Does this bundle contain an 'addi sp, sp, OFFSET' or |
117 | * 'addli sp, sp, OFFSET' instruction, and if so, what is OFFSET? | 93 | * 'addli sp, sp, OFFSET' instruction, and if so, what is OFFSET? |
118 | */ | 94 | */ |
119 | static bool bt_has_addi_sp(const struct BacktraceBundle *bundle, int *adjust) | 95 | static bool bt_has_addi_sp(const struct BacktraceBundle *bundle, int *adjust) |
@@ -124,7 +100,7 @@ static bool bt_has_addi_sp(const struct BacktraceBundle *bundle, int *adjust) | |||
124 | find_matching_insn(bundle, TILE_OPC_ADDI, vals, 2); | 100 | find_matching_insn(bundle, TILE_OPC_ADDI, vals, 2); |
125 | if (insn == NULL) | 101 | if (insn == NULL) |
126 | insn = find_matching_insn(bundle, TILE_OPC_ADDLI, vals, 2); | 102 | insn = find_matching_insn(bundle, TILE_OPC_ADDLI, vals, 2); |
127 | #if TILE_CHIP >= 10 | 103 | #ifdef __tilegx__ |
128 | if (insn == NULL) | 104 | if (insn == NULL) |
129 | insn = find_matching_insn(bundle, TILEGX_OPC_ADDXLI, vals, 2); | 105 | insn = find_matching_insn(bundle, TILEGX_OPC_ADDXLI, vals, 2); |
130 | if (insn == NULL) | 106 | if (insn == NULL) |
@@ -137,7 +113,7 @@ static bool bt_has_addi_sp(const struct BacktraceBundle *bundle, int *adjust) | |||
137 | return true; | 113 | return true; |
138 | } | 114 | } |
139 | 115 | ||
140 | /** Does this bundle contain any 'info OP' or 'infol OP' | 116 | /* Does this bundle contain any 'info OP' or 'infol OP' |
141 | * instruction, and if so, what are their OP? Note that OP is interpreted | 117 | * instruction, and if so, what are their OP? Note that OP is interpreted |
142 | * as an unsigned value by this code since that's what the caller wants. | 118 | * as an unsigned value by this code since that's what the caller wants. |
143 | * Returns the number of info ops found. | 119 | * Returns the number of info ops found. |
@@ -161,7 +137,7 @@ static int bt_get_info_ops(const struct BacktraceBundle *bundle, | |||
161 | return num_ops; | 137 | return num_ops; |
162 | } | 138 | } |
163 | 139 | ||
164 | /** Does this bundle contain a jrp instruction, and if so, to which | 140 | /* Does this bundle contain a jrp instruction, and if so, to which |
165 | * register is it jumping? | 141 | * register is it jumping? |
166 | */ | 142 | */ |
167 | static bool bt_has_jrp(const struct BacktraceBundle *bundle, int *target_reg) | 143 | static bool bt_has_jrp(const struct BacktraceBundle *bundle, int *target_reg) |
@@ -175,7 +151,7 @@ static bool bt_has_jrp(const struct BacktraceBundle *bundle, int *target_reg) | |||
175 | return true; | 151 | return true; |
176 | } | 152 | } |
177 | 153 | ||
178 | /** Does this bundle modify the specified register in any way? */ | 154 | /* Does this bundle modify the specified register in any way? */ |
179 | static bool bt_modifies_reg(const struct BacktraceBundle *bundle, int reg) | 155 | static bool bt_modifies_reg(const struct BacktraceBundle *bundle, int reg) |
180 | { | 156 | { |
181 | int i, j; | 157 | int i, j; |
@@ -195,34 +171,34 @@ static bool bt_modifies_reg(const struct BacktraceBundle *bundle, int reg) | |||
195 | return false; | 171 | return false; |
196 | } | 172 | } |
197 | 173 | ||
198 | /** Does this bundle modify sp? */ | 174 | /* Does this bundle modify sp? */ |
199 | static inline bool bt_modifies_sp(const struct BacktraceBundle *bundle) | 175 | static inline bool bt_modifies_sp(const struct BacktraceBundle *bundle) |
200 | { | 176 | { |
201 | return bt_modifies_reg(bundle, TREG_SP); | 177 | return bt_modifies_reg(bundle, TREG_SP); |
202 | } | 178 | } |
203 | 179 | ||
204 | /** Does this bundle modify lr? */ | 180 | /* Does this bundle modify lr? */ |
205 | static inline bool bt_modifies_lr(const struct BacktraceBundle *bundle) | 181 | static inline bool bt_modifies_lr(const struct BacktraceBundle *bundle) |
206 | { | 182 | { |
207 | return bt_modifies_reg(bundle, TREG_LR); | 183 | return bt_modifies_reg(bundle, TREG_LR); |
208 | } | 184 | } |
209 | 185 | ||
210 | /** Does this bundle contain the instruction 'move fp, sp'? */ | 186 | /* Does this bundle contain the instruction 'move fp, sp'? */ |
211 | static inline bool bt_has_move_r52_sp(const struct BacktraceBundle *bundle) | 187 | static inline bool bt_has_move_r52_sp(const struct BacktraceBundle *bundle) |
212 | { | 188 | { |
213 | static const int vals[2] = { 52, TREG_SP }; | 189 | static const int vals[2] = { 52, TREG_SP }; |
214 | return find_matching_insn(bundle, TILE_OPC_MOVE, vals, 2) != NULL; | 190 | return find_matching_insn(bundle, TILE_OPC_MOVE, vals, 2) != NULL; |
215 | } | 191 | } |
216 | 192 | ||
217 | /** Does this bundle contain a store of lr to sp? */ | 193 | /* Does this bundle contain a store of lr to sp? */ |
218 | static inline bool bt_has_sw_sp_lr(const struct BacktraceBundle *bundle) | 194 | static inline bool bt_has_sw_sp_lr(const struct BacktraceBundle *bundle) |
219 | { | 195 | { |
220 | static const int vals[2] = { TREG_SP, TREG_LR }; | 196 | static const int vals[2] = { TREG_SP, TREG_LR }; |
221 | return find_matching_insn(bundle, OPCODE_STORE, vals, 2) != NULL; | 197 | return find_matching_insn(bundle, OPCODE_STORE, vals, 2) != NULL; |
222 | } | 198 | } |
223 | 199 | ||
224 | #if TILE_CHIP >= 10 | 200 | #ifdef __tilegx__ |
225 | /** Track moveli values placed into registers. */ | 201 | /* Track moveli values placed into registers. */ |
226 | static inline void bt_update_moveli(const struct BacktraceBundle *bundle, | 202 | static inline void bt_update_moveli(const struct BacktraceBundle *bundle, |
227 | int moveli_args[]) | 203 | int moveli_args[]) |
228 | { | 204 | { |
@@ -238,7 +214,7 @@ static inline void bt_update_moveli(const struct BacktraceBundle *bundle, | |||
238 | } | 214 | } |
239 | } | 215 | } |
240 | 216 | ||
241 | /** Does this bundle contain an 'add sp, sp, reg' instruction | 217 | /* Does this bundle contain an 'add sp, sp, reg' instruction |
242 | * from a register that we saw a moveli into, and if so, what | 218 | * from a register that we saw a moveli into, and if so, what |
243 | * is the value in the register? | 219 | * is the value in the register? |
244 | */ | 220 | */ |
@@ -260,11 +236,11 @@ static bool bt_has_add_sp(const struct BacktraceBundle *bundle, int *adjust, | |||
260 | } | 236 | } |
261 | #endif | 237 | #endif |
262 | 238 | ||
263 | /** Locates the caller's PC and SP for a program starting at the | 239 | /* Locates the caller's PC and SP for a program starting at the |
264 | * given address. | 240 | * given address. |
265 | */ | 241 | */ |
266 | static void find_caller_pc_and_caller_sp(CallerLocation *location, | 242 | static void find_caller_pc_and_caller_sp(CallerLocation *location, |
267 | const VirtualAddress start_pc, | 243 | const unsigned long start_pc, |
268 | BacktraceMemoryReader read_memory_func, | 244 | BacktraceMemoryReader read_memory_func, |
269 | void *read_memory_func_extra) | 245 | void *read_memory_func_extra) |
270 | { | 246 | { |
@@ -288,9 +264,9 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location, | |||
288 | tile_bundle_bits prefetched_bundles[32]; | 264 | tile_bundle_bits prefetched_bundles[32]; |
289 | int num_bundles_prefetched = 0; | 265 | int num_bundles_prefetched = 0; |
290 | int next_bundle = 0; | 266 | int next_bundle = 0; |
291 | VirtualAddress pc; | 267 | unsigned long pc; |
292 | 268 | ||
293 | #if TILE_CHIP >= 10 | 269 | #ifdef __tilegx__ |
294 | /* Naively try to track moveli values to support addx for -m32. */ | 270 | /* Naively try to track moveli values to support addx for -m32. */ |
295 | int moveli_args[TILEGX_NUM_REGISTERS] = { 0 }; | 271 | int moveli_args[TILEGX_NUM_REGISTERS] = { 0 }; |
296 | #endif | 272 | #endif |
@@ -449,7 +425,7 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location, | |||
449 | if (!sp_determined) { | 425 | if (!sp_determined) { |
450 | int adjust; | 426 | int adjust; |
451 | if (bt_has_addi_sp(&bundle, &adjust) | 427 | if (bt_has_addi_sp(&bundle, &adjust) |
452 | #if TILE_CHIP >= 10 | 428 | #ifdef __tilegx__ |
453 | || bt_has_add_sp(&bundle, &adjust, moveli_args) | 429 | || bt_has_add_sp(&bundle, &adjust, moveli_args) |
454 | #endif | 430 | #endif |
455 | ) { | 431 | ) { |
@@ -500,7 +476,7 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location, | |||
500 | } | 476 | } |
501 | } | 477 | } |
502 | 478 | ||
503 | #if TILE_CHIP >= 10 | 479 | #ifdef __tilegx__ |
504 | /* Track moveli arguments for -m32 mode. */ | 480 | /* Track moveli arguments for -m32 mode. */ |
505 | bt_update_moveli(&bundle, moveli_args); | 481 | bt_update_moveli(&bundle, moveli_args); |
506 | #endif | 482 | #endif |
@@ -542,18 +518,26 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location, | |||
542 | } | 518 | } |
543 | } | 519 | } |
544 | 520 | ||
521 | /* Initializes a backtracer to start from the given location. | ||
522 | * | ||
523 | * If the frame pointer cannot be determined it is set to -1. | ||
524 | * | ||
525 | * state: The state to be filled in. | ||
526 | * read_memory_func: A callback that reads memory. | ||
527 | * read_memory_func_extra: An arbitrary argument to read_memory_func. | ||
528 | * pc: The current PC. | ||
529 | * lr: The current value of the 'lr' register. | ||
530 | * sp: The current value of the 'sp' register. | ||
531 | * r52: The current value of the 'r52' register. | ||
532 | */ | ||
545 | void backtrace_init(BacktraceIterator *state, | 533 | void backtrace_init(BacktraceIterator *state, |
546 | BacktraceMemoryReader read_memory_func, | 534 | BacktraceMemoryReader read_memory_func, |
547 | void *read_memory_func_extra, | 535 | void *read_memory_func_extra, |
548 | VirtualAddress pc, VirtualAddress lr, | 536 | unsigned long pc, unsigned long lr, |
549 | VirtualAddress sp, VirtualAddress r52) | 537 | unsigned long sp, unsigned long r52) |
550 | { | 538 | { |
551 | CallerLocation location; | 539 | CallerLocation location; |
552 | VirtualAddress fp, initial_frame_caller_pc; | 540 | unsigned long fp, initial_frame_caller_pc; |
553 | |||
554 | if (read_memory_func == NULL) { | ||
555 | read_memory_func = bt_read_memory; | ||
556 | } | ||
557 | 541 | ||
558 | /* Find out where we are in the initial frame. */ | 542 | /* Find out where we are in the initial frame. */ |
559 | find_caller_pc_and_caller_sp(&location, pc, | 543 | find_caller_pc_and_caller_sp(&location, pc, |
@@ -626,12 +610,15 @@ void backtrace_init(BacktraceIterator *state, | |||
626 | /* Handle the case where the register holds more bits than the VA. */ | 610 | /* Handle the case where the register holds more bits than the VA. */ |
627 | static bool valid_addr_reg(bt_int_reg_t reg) | 611 | static bool valid_addr_reg(bt_int_reg_t reg) |
628 | { | 612 | { |
629 | return ((VirtualAddress)reg == reg); | 613 | return ((unsigned long)reg == reg); |
630 | } | 614 | } |
631 | 615 | ||
616 | /* Advances the backtracing state to the calling frame, returning | ||
617 | * true iff successful. | ||
618 | */ | ||
632 | bool backtrace_next(BacktraceIterator *state) | 619 | bool backtrace_next(BacktraceIterator *state) |
633 | { | 620 | { |
634 | VirtualAddress next_fp, next_pc; | 621 | unsigned long next_fp, next_pc; |
635 | bt_int_reg_t next_frame[2]; | 622 | bt_int_reg_t next_frame[2]; |
636 | 623 | ||
637 | if (state->fp == -1) { | 624 | if (state->fp == -1) { |
diff --git a/arch/tile/kernel/compat.c b/arch/tile/kernel/compat.c index b1e06d041555..bf5e9d70266c 100644 --- a/arch/tile/kernel/compat.c +++ b/arch/tile/kernel/compat.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/kdev_t.h> | 21 | #include <linux/kdev_t.h> |
22 | #include <linux/fs.h> | 22 | #include <linux/fs.h> |
23 | #include <linux/fcntl.h> | 23 | #include <linux/fcntl.h> |
24 | #include <linux/smp_lock.h> | ||
25 | #include <linux/uaccess.h> | 24 | #include <linux/uaccess.h> |
26 | #include <linux/signal.h> | 25 | #include <linux/signal.h> |
27 | #include <asm/syscalls.h> | 26 | #include <asm/syscalls.h> |
@@ -136,26 +135,21 @@ long tile_compat_sys_msgrcv(int msqid, | |||
136 | 135 | ||
137 | /* Provide the compat syscall number to call mapping. */ | 136 | /* Provide the compat syscall number to call mapping. */ |
138 | #undef __SYSCALL | 137 | #undef __SYSCALL |
139 | #define __SYSCALL(nr, call) [nr] = (compat_##call), | 138 | #define __SYSCALL(nr, call) [nr] = (call), |
140 | 139 | ||
141 | /* The generic versions of these don't work for Tile. */ | 140 | /* The generic versions of these don't work for Tile. */ |
142 | #define compat_sys_msgrcv tile_compat_sys_msgrcv | 141 | #define compat_sys_msgrcv tile_compat_sys_msgrcv |
143 | #define compat_sys_msgsnd tile_compat_sys_msgsnd | 142 | #define compat_sys_msgsnd tile_compat_sys_msgsnd |
144 | 143 | ||
145 | /* See comments in sys.c */ | 144 | /* See comments in sys.c */ |
146 | #define compat_sys_fadvise64 sys32_fadvise64 | ||
147 | #define compat_sys_fadvise64_64 sys32_fadvise64_64 | 145 | #define compat_sys_fadvise64_64 sys32_fadvise64_64 |
148 | #define compat_sys_readahead sys32_readahead | 146 | #define compat_sys_readahead sys32_readahead |
149 | #define compat_sys_sync_file_range compat_sys_sync_file_range2 | ||
150 | 147 | ||
151 | /* The native 64-bit "struct stat" matches the 32-bit "struct stat64". */ | 148 | /* Call the trampolines to manage pt_regs where necessary. */ |
152 | #define compat_sys_stat64 sys_newstat | 149 | #define compat_sys_execve _compat_sys_execve |
153 | #define compat_sys_lstat64 sys_newlstat | 150 | #define compat_sys_sigaltstack _compat_sys_sigaltstack |
154 | #define compat_sys_fstat64 sys_newfstat | 151 | #define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn |
155 | #define compat_sys_fstatat64 sys_newfstatat | 152 | #define sys_clone _sys_clone |
156 | |||
157 | /* Pass full 64-bit values through ptrace. */ | ||
158 | #define compat_sys_ptrace tile_compat_sys_ptrace | ||
159 | 153 | ||
160 | /* | 154 | /* |
161 | * Note that we can't include <linux/unistd.h> here since the header | 155 | * Note that we can't include <linux/unistd.h> here since the header |
diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c index 9c710db43f13..a7869ad62776 100644 --- a/arch/tile/kernel/compat_signal.c +++ b/arch/tile/kernel/compat_signal.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
16 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
17 | #include <linux/smp.h> | 17 | #include <linux/smp.h> |
18 | #include <linux/smp_lock.h> | ||
19 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
20 | #include <linux/signal.h> | 19 | #include <linux/signal.h> |
21 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
@@ -256,9 +255,9 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from) | |||
256 | return err; | 255 | return err; |
257 | } | 256 | } |
258 | 257 | ||
259 | long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, | 258 | long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, |
260 | struct compat_sigaltstack __user *uoss_ptr, | 259 | struct compat_sigaltstack __user *uoss_ptr, |
261 | struct pt_regs *regs) | 260 | struct pt_regs *regs) |
262 | { | 261 | { |
263 | stack_t uss, uoss; | 262 | stack_t uss, uoss; |
264 | int ret; | 263 | int ret; |
@@ -291,12 +290,12 @@ long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr, | |||
291 | return ret; | 290 | return ret; |
292 | } | 291 | } |
293 | 292 | ||
294 | long _compat_sys_rt_sigreturn(struct pt_regs *regs) | 293 | /* The assembly shim for this function arranges to ignore the return value. */ |
294 | long compat_sys_rt_sigreturn(struct pt_regs *regs) | ||
295 | { | 295 | { |
296 | struct compat_rt_sigframe __user *frame = | 296 | struct compat_rt_sigframe __user *frame = |
297 | (struct compat_rt_sigframe __user *) compat_ptr(regs->sp); | 297 | (struct compat_rt_sigframe __user *) compat_ptr(regs->sp); |
298 | sigset_t set; | 298 | sigset_t set; |
299 | long r0; | ||
300 | 299 | ||
301 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 300 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
302 | goto badframe; | 301 | goto badframe; |
@@ -309,16 +308,16 @@ long _compat_sys_rt_sigreturn(struct pt_regs *regs) | |||
309 | recalc_sigpending(); | 308 | recalc_sigpending(); |
310 | spin_unlock_irq(¤t->sighand->siglock); | 309 | spin_unlock_irq(¤t->sighand->siglock); |
311 | 310 | ||
312 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) | 311 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) |
313 | goto badframe; | 312 | goto badframe; |
314 | 313 | ||
315 | if (_compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0) | 314 | if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0) |
316 | goto badframe; | 315 | goto badframe; |
317 | 316 | ||
318 | return r0; | 317 | return 0; |
319 | 318 | ||
320 | badframe: | 319 | badframe: |
321 | force_sig(SIGSEGV, current); | 320 | signal_fault("bad sigreturn frame", regs, frame, 0); |
322 | return 0; | 321 | return 0; |
323 | } | 322 | } |
324 | 323 | ||
@@ -432,6 +431,6 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
432 | return 0; | 431 | return 0; |
433 | 432 | ||
434 | give_sigsegv: | 433 | give_sigsegv: |
435 | force_sigsegv(sig, current); | 434 | signal_fault("bad setup frame", regs, frame, sig); |
436 | return -EFAULT; | 435 | return -EFAULT; |
437 | } | 436 | } |
diff --git a/arch/tile/kernel/early_printk.c b/arch/tile/kernel/early_printk.c index 2c54fd43a8a0..493a0e66d916 100644 --- a/arch/tile/kernel/early_printk.c +++ b/arch/tile/kernel/early_printk.c | |||
@@ -54,7 +54,7 @@ void early_printk(const char *fmt, ...) | |||
54 | void early_panic(const char *fmt, ...) | 54 | void early_panic(const char *fmt, ...) |
55 | { | 55 | { |
56 | va_list ap; | 56 | va_list ap; |
57 | raw_local_irq_disable_all(); | 57 | arch_local_irq_disable_all(); |
58 | va_start(ap, fmt); | 58 | va_start(ap, fmt); |
59 | early_printk("Kernel panic - not syncing: "); | 59 | early_printk("Kernel panic - not syncing: "); |
60 | early_vprintk(fmt, ap); | 60 | early_vprintk(fmt, ap); |
diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S index 3d01383b1b0e..431e9ae60488 100644 --- a/arch/tile/kernel/entry.S +++ b/arch/tile/kernel/entry.S | |||
@@ -15,7 +15,9 @@ | |||
15 | #include <linux/linkage.h> | 15 | #include <linux/linkage.h> |
16 | #include <linux/unistd.h> | 16 | #include <linux/unistd.h> |
17 | #include <asm/irqflags.h> | 17 | #include <asm/irqflags.h> |
18 | #include <asm/processor.h> | ||
18 | #include <arch/abi.h> | 19 | #include <arch/abi.h> |
20 | #include <arch/spr_def.h> | ||
19 | 21 | ||
20 | #ifdef __tilegx__ | 22 | #ifdef __tilegx__ |
21 | #define bnzt bnezt | 23 | #define bnzt bnezt |
@@ -25,28 +27,6 @@ STD_ENTRY(current_text_addr) | |||
25 | { move r0, lr; jrp lr } | 27 | { move r0, lr; jrp lr } |
26 | STD_ENDPROC(current_text_addr) | 28 | STD_ENDPROC(current_text_addr) |
27 | 29 | ||
28 | STD_ENTRY(_sim_syscall) | ||
29 | /* | ||
30 | * Wait for r0-r9 to be ready (and lr on the off chance we | ||
31 | * want the syscall to locate its caller), then make a magic | ||
32 | * simulator syscall. | ||
33 | * | ||
34 | * We carefully stall until the registers are readable in case they | ||
35 | * are the target of a slow load, etc. so that tile-sim will | ||
36 | * definitely be able to read all of them inside the magic syscall. | ||
37 | * | ||
38 | * Technically this is wrong for r3-r9 and lr, since an interrupt | ||
39 | * could come in and restore the registers with a slow load right | ||
40 | * before executing the mtspr. We may need to modify tile-sim to | ||
41 | * explicitly stall for this case, but we do not yet have | ||
42 | * a way to implement such a stall. | ||
43 | */ | ||
44 | { and zero, lr, r9 ; and zero, r8, r7 } | ||
45 | { and zero, r6, r5 ; and zero, r4, r3 } | ||
46 | { and zero, r2, r1 ; mtspr SIM_CONTROL, r0 } | ||
47 | { jrp lr } | ||
48 | STD_ENDPROC(_sim_syscall) | ||
49 | |||
50 | /* | 30 | /* |
51 | * Implement execve(). The i386 code has a note that forking from kernel | 31 | * Implement execve(). The i386 code has a note that forking from kernel |
52 | * space results in no copy on write until the execve, so we should be | 32 | * space results in no copy on write until the execve, so we should be |
@@ -58,12 +38,6 @@ STD_ENTRY(kernel_execve) | |||
58 | jrp lr | 38 | jrp lr |
59 | STD_ENDPROC(kernel_execve) | 39 | STD_ENDPROC(kernel_execve) |
60 | 40 | ||
61 | /* Delay a fixed number of cycles. */ | ||
62 | STD_ENTRY(__delay) | ||
63 | { addi r0, r0, -1; bnzt r0, . } | ||
64 | jrp lr | ||
65 | STD_ENDPROC(__delay) | ||
66 | |||
67 | /* | 41 | /* |
68 | * We don't run this function directly, but instead copy it to a page | 42 | * We don't run this function directly, but instead copy it to a page |
69 | * we map into every user process. See vdso_setup(). | 43 | * we map into every user process. See vdso_setup(). |
@@ -102,7 +76,7 @@ STD_ENTRY(KBacktraceIterator_init_current) | |||
102 | STD_ENTRY(cpu_idle_on_new_stack) | 76 | STD_ENTRY(cpu_idle_on_new_stack) |
103 | { | 77 | { |
104 | move sp, r1 | 78 | move sp, r1 |
105 | mtspr SYSTEM_SAVE_1_0, r2 | 79 | mtspr SPR_SYSTEM_SAVE_K_0, r2 |
106 | } | 80 | } |
107 | jal free_thread_info | 81 | jal free_thread_info |
108 | j cpu_idle | 82 | j cpu_idle |
@@ -117,23 +91,17 @@ STD_ENTRY(smp_nap) | |||
117 | 91 | ||
118 | /* | 92 | /* |
119 | * Enable interrupts racelessly and then nap until interrupted. | 93 | * Enable interrupts racelessly and then nap until interrupted. |
94 | * Architecturally, we are guaranteed that enabling interrupts via | ||
95 | * mtspr to INTERRUPT_CRITICAL_SECTION only interrupts at the next PC. | ||
120 | * This function's _cpu_idle_nap address is special; see intvec.S. | 96 | * This function's _cpu_idle_nap address is special; see intvec.S. |
121 | * When interrupted at _cpu_idle_nap, we bump the PC forward 8, and | 97 | * When interrupted at _cpu_idle_nap, we bump the PC forward 8, and |
122 | * as a result return to the function that called _cpu_idle(). | 98 | * as a result return to the function that called _cpu_idle(). |
123 | */ | 99 | */ |
124 | STD_ENTRY(_cpu_idle) | 100 | STD_ENTRY(_cpu_idle) |
125 | { | 101 | movei r1, 1 |
126 | lnk r0 | 102 | mtspr INTERRUPT_CRITICAL_SECTION, r1 |
127 | movei r1, 1 | 103 | IRQ_ENABLE(r2, r3) /* unmask, but still with ICS set */ |
128 | } | 104 | mtspr INTERRUPT_CRITICAL_SECTION, zero |
129 | { | ||
130 | addli r0, r0, _cpu_idle_nap - . | ||
131 | mtspr INTERRUPT_CRITICAL_SECTION, r1 | ||
132 | } | ||
133 | IRQ_ENABLE(r2, r3) /* unmask, but still with ICS set */ | ||
134 | mtspr EX_CONTEXT_1_1, r1 /* PL1, ICS clear */ | ||
135 | mtspr EX_CONTEXT_1_0, r0 | ||
136 | iret | ||
137 | .global _cpu_idle_nap | 105 | .global _cpu_idle_nap |
138 | _cpu_idle_nap: | 106 | _cpu_idle_nap: |
139 | nap | 107 | nap |
diff --git a/arch/tile/kernel/futex_64.S b/arch/tile/kernel/futex_64.S new file mode 100644 index 000000000000..f465d1eda20f --- /dev/null +++ b/arch/tile/kernel/futex_64.S | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * Copyright 2011 Tilera Corporation. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation, version 2. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
11 | * NON INFRINGEMENT. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * Atomically access user memory, but use MMU to avoid propagating | ||
15 | * kernel exceptions. | ||
16 | */ | ||
17 | |||
18 | #include <linux/linkage.h> | ||
19 | #include <asm/errno.h> | ||
20 | #include <asm/futex.h> | ||
21 | #include <asm/page.h> | ||
22 | #include <asm/processor.h> | ||
23 | |||
24 | /* | ||
25 | * Provide a set of atomic memory operations supporting <asm/futex.h>. | ||
26 | * | ||
27 | * r0: user address to manipulate | ||
28 | * r1: new value to write, or for cmpxchg, old value to compare against | ||
29 | * r2: (cmpxchg only) new value to write | ||
30 | * | ||
31 | * Return __get_user struct, r0 with value, r1 with error. | ||
32 | */ | ||
33 | #define FUTEX_OP(name, ...) \ | ||
34 | STD_ENTRY(futex_##name) \ | ||
35 | __VA_ARGS__; \ | ||
36 | { \ | ||
37 | move r1, zero; \ | ||
38 | jrp lr \ | ||
39 | }; \ | ||
40 | STD_ENDPROC(futex_##name); \ | ||
41 | .pushsection __ex_table,"a"; \ | ||
42 | .quad 1b, get_user_fault; \ | ||
43 | .popsection | ||
44 | |||
45 | .pushsection .fixup,"ax" | ||
46 | get_user_fault: | ||
47 | { movei r1, -EFAULT; jrp lr } | ||
48 | ENDPROC(get_user_fault) | ||
49 | .popsection | ||
50 | |||
51 | FUTEX_OP(cmpxchg, mtspr CMPEXCH_VALUE, r1; 1: cmpexch4 r0, r0, r2) | ||
52 | FUTEX_OP(set, 1: exch4 r0, r0, r1) | ||
53 | FUTEX_OP(add, 1: fetchadd4 r0, r0, r1) | ||
54 | FUTEX_OP(or, 1: fetchor4 r0, r0, r1) | ||
55 | FUTEX_OP(andn, nor r1, r1, zero; 1: fetchand4 r0, r0, r1) | ||
diff --git a/arch/tile/kernel/hardwall.c b/arch/tile/kernel/hardwall.c index 584b965dc824..8c41891aab34 100644 --- a/arch/tile/kernel/hardwall.c +++ b/arch/tile/kernel/hardwall.c | |||
@@ -40,16 +40,25 @@ | |||
40 | struct hardwall_info { | 40 | struct hardwall_info { |
41 | struct list_head list; /* "rectangles" list */ | 41 | struct list_head list; /* "rectangles" list */ |
42 | struct list_head task_head; /* head of tasks in this hardwall */ | 42 | struct list_head task_head; /* head of tasks in this hardwall */ |
43 | struct cpumask cpumask; /* cpus in the rectangle */ | ||
43 | int ulhc_x; /* upper left hand corner x coord */ | 44 | int ulhc_x; /* upper left hand corner x coord */ |
44 | int ulhc_y; /* upper left hand corner y coord */ | 45 | int ulhc_y; /* upper left hand corner y coord */ |
45 | int width; /* rectangle width */ | 46 | int width; /* rectangle width */ |
46 | int height; /* rectangle height */ | 47 | int height; /* rectangle height */ |
48 | int id; /* integer id for this hardwall */ | ||
47 | int teardown_in_progress; /* are we tearing this one down? */ | 49 | int teardown_in_progress; /* are we tearing this one down? */ |
48 | }; | 50 | }; |
49 | 51 | ||
50 | /* Currently allocated hardwall rectangles */ | 52 | /* Currently allocated hardwall rectangles */ |
51 | static LIST_HEAD(rectangles); | 53 | static LIST_HEAD(rectangles); |
52 | 54 | ||
55 | /* /proc/tile/hardwall */ | ||
56 | static struct proc_dir_entry *hardwall_proc_dir; | ||
57 | |||
58 | /* Functions to manage files in /proc/tile/hardwall. */ | ||
59 | static void hardwall_add_proc(struct hardwall_info *rect); | ||
60 | static void hardwall_remove_proc(struct hardwall_info *rect); | ||
61 | |||
53 | /* | 62 | /* |
54 | * Guard changes to the hardwall data structures. | 63 | * Guard changes to the hardwall data structures. |
55 | * This could be finer grained (e.g. one lock for the list of hardwall | 64 | * This could be finer grained (e.g. one lock for the list of hardwall |
@@ -105,6 +114,8 @@ static int setup_rectangle(struct hardwall_info *r, struct cpumask *mask) | |||
105 | r->ulhc_y = cpu_y(ulhc); | 114 | r->ulhc_y = cpu_y(ulhc); |
106 | r->width = cpu_x(lrhc) - r->ulhc_x + 1; | 115 | r->width = cpu_x(lrhc) - r->ulhc_x + 1; |
107 | r->height = cpu_y(lrhc) - r->ulhc_y + 1; | 116 | r->height = cpu_y(lrhc) - r->ulhc_y + 1; |
117 | cpumask_copy(&r->cpumask, mask); | ||
118 | r->id = ulhc; /* The ulhc cpu id can be the hardwall id. */ | ||
108 | 119 | ||
109 | /* Width and height must be positive */ | 120 | /* Width and height must be positive */ |
110 | if (r->width <= 0 || r->height <= 0) | 121 | if (r->width <= 0 || r->height <= 0) |
@@ -151,12 +162,12 @@ enum direction_protect { | |||
151 | 162 | ||
152 | static void enable_firewall_interrupts(void) | 163 | static void enable_firewall_interrupts(void) |
153 | { | 164 | { |
154 | raw_local_irq_unmask_now(INT_UDN_FIREWALL); | 165 | arch_local_irq_unmask_now(INT_UDN_FIREWALL); |
155 | } | 166 | } |
156 | 167 | ||
157 | static void disable_firewall_interrupts(void) | 168 | static void disable_firewall_interrupts(void) |
158 | { | 169 | { |
159 | raw_local_irq_mask_now(INT_UDN_FIREWALL); | 170 | arch_local_irq_mask_now(INT_UDN_FIREWALL); |
160 | } | 171 | } |
161 | 172 | ||
162 | /* Set up hardwall on this cpu based on the passed hardwall_info. */ | 173 | /* Set up hardwall on this cpu based on the passed hardwall_info. */ |
@@ -268,12 +279,10 @@ void __kprobes do_hardwall_trap(struct pt_regs* regs, int fault_num) | |||
268 | found_processes = 0; | 279 | found_processes = 0; |
269 | list_for_each_entry(p, &rect->task_head, thread.hardwall_list) { | 280 | list_for_each_entry(p, &rect->task_head, thread.hardwall_list) { |
270 | BUG_ON(p->thread.hardwall != rect); | 281 | BUG_ON(p->thread.hardwall != rect); |
271 | if (p->sighand) { | 282 | if (!(p->flags & PF_EXITING)) { |
272 | found_processes = 1; | 283 | found_processes = 1; |
273 | pr_notice("hardwall: killing %d\n", p->pid); | 284 | pr_notice("hardwall: killing %d\n", p->pid); |
274 | spin_lock(&p->sighand->siglock); | 285 | do_send_sig_info(info.si_signo, &info, p, false); |
275 | __group_send_sig_info(info.si_signo, &info, p); | ||
276 | spin_unlock(&p->sighand->siglock); | ||
277 | } | 286 | } |
278 | } | 287 | } |
279 | if (!found_processes) | 288 | if (!found_processes) |
@@ -390,6 +399,9 @@ static struct hardwall_info *hardwall_create( | |||
390 | /* Set up appropriate hardwalling on all affected cpus. */ | 399 | /* Set up appropriate hardwalling on all affected cpus. */ |
391 | hardwall_setup(rect); | 400 | hardwall_setup(rect); |
392 | 401 | ||
402 | /* Create a /proc/tile/hardwall entry. */ | ||
403 | hardwall_add_proc(rect); | ||
404 | |||
393 | return rect; | 405 | return rect; |
394 | } | 406 | } |
395 | 407 | ||
@@ -647,6 +659,9 @@ static void hardwall_destroy(struct hardwall_info *rect) | |||
647 | /* Restart switch and disable firewall. */ | 659 | /* Restart switch and disable firewall. */ |
648 | on_each_cpu_mask(&mask, restart_udn_switch, NULL, 1); | 660 | on_each_cpu_mask(&mask, restart_udn_switch, NULL, 1); |
649 | 661 | ||
662 | /* Remove the /proc/tile/hardwall entry. */ | ||
663 | hardwall_remove_proc(rect); | ||
664 | |||
650 | /* Now free the rectangle from the list. */ | 665 | /* Now free the rectangle from the list. */ |
651 | spin_lock_irqsave(&hardwall_lock, flags); | 666 | spin_lock_irqsave(&hardwall_lock, flags); |
652 | BUG_ON(!list_empty(&rect->task_head)); | 667 | BUG_ON(!list_empty(&rect->task_head)); |
@@ -656,35 +671,57 @@ static void hardwall_destroy(struct hardwall_info *rect) | |||
656 | } | 671 | } |
657 | 672 | ||
658 | 673 | ||
659 | /* | 674 | static int hardwall_proc_show(struct seq_file *sf, void *v) |
660 | * Dump hardwall state via /proc; initialized in arch/tile/sys/proc.c. | ||
661 | */ | ||
662 | int proc_tile_hardwall_show(struct seq_file *sf, void *v) | ||
663 | { | 675 | { |
664 | struct hardwall_info *r; | 676 | struct hardwall_info *rect = sf->private; |
677 | char buf[256]; | ||
665 | 678 | ||
666 | if (udn_disabled) { | 679 | int rc = cpulist_scnprintf(buf, sizeof(buf), &rect->cpumask); |
667 | seq_printf(sf, "%dx%d 0,0 pids:\n", smp_width, smp_height); | 680 | buf[rc++] = '\n'; |
668 | return 0; | 681 | seq_write(sf, buf, rc); |
669 | } | ||
670 | |||
671 | spin_lock_irq(&hardwall_lock); | ||
672 | list_for_each_entry(r, &rectangles, list) { | ||
673 | struct task_struct *p; | ||
674 | seq_printf(sf, "%dx%d %d,%d pids:", | ||
675 | r->width, r->height, r->ulhc_x, r->ulhc_y); | ||
676 | list_for_each_entry(p, &r->task_head, thread.hardwall_list) { | ||
677 | unsigned int cpu = cpumask_first(&p->cpus_allowed); | ||
678 | unsigned int x = cpu % smp_width; | ||
679 | unsigned int y = cpu / smp_width; | ||
680 | seq_printf(sf, " %d@%d,%d", p->pid, x, y); | ||
681 | } | ||
682 | seq_printf(sf, "\n"); | ||
683 | } | ||
684 | spin_unlock_irq(&hardwall_lock); | ||
685 | return 0; | 682 | return 0; |
686 | } | 683 | } |
687 | 684 | ||
685 | static int hardwall_proc_open(struct inode *inode, | ||
686 | struct file *file) | ||
687 | { | ||
688 | return single_open(file, hardwall_proc_show, PDE(inode)->data); | ||
689 | } | ||
690 | |||
691 | static const struct file_operations hardwall_proc_fops = { | ||
692 | .open = hardwall_proc_open, | ||
693 | .read = seq_read, | ||
694 | .llseek = seq_lseek, | ||
695 | .release = single_release, | ||
696 | }; | ||
697 | |||
698 | static void hardwall_add_proc(struct hardwall_info *rect) | ||
699 | { | ||
700 | char buf[64]; | ||
701 | snprintf(buf, sizeof(buf), "%d", rect->id); | ||
702 | proc_create_data(buf, 0444, hardwall_proc_dir, | ||
703 | &hardwall_proc_fops, rect); | ||
704 | } | ||
705 | |||
706 | static void hardwall_remove_proc(struct hardwall_info *rect) | ||
707 | { | ||
708 | char buf[64]; | ||
709 | snprintf(buf, sizeof(buf), "%d", rect->id); | ||
710 | remove_proc_entry(buf, hardwall_proc_dir); | ||
711 | } | ||
712 | |||
713 | int proc_pid_hardwall(struct task_struct *task, char *buffer) | ||
714 | { | ||
715 | struct hardwall_info *rect = task->thread.hardwall; | ||
716 | return rect ? sprintf(buffer, "%d\n", rect->id) : 0; | ||
717 | } | ||
718 | |||
719 | void proc_tile_hardwall_init(struct proc_dir_entry *root) | ||
720 | { | ||
721 | if (!udn_disabled) | ||
722 | hardwall_proc_dir = proc_mkdir("hardwall", root); | ||
723 | } | ||
724 | |||
688 | 725 | ||
689 | /* | 726 | /* |
690 | * Character device support via ioctl/close. | 727 | * Character device support via ioctl/close. |
@@ -718,6 +755,9 @@ static long hardwall_ioctl(struct file *file, unsigned int a, unsigned long b) | |||
718 | return -EINVAL; | 755 | return -EINVAL; |
719 | return hardwall_deactivate(current); | 756 | return hardwall_deactivate(current); |
720 | 757 | ||
758 | case _HARDWALL_GET_ID: | ||
759 | return rect ? rect->id : -EINVAL; | ||
760 | |||
721 | default: | 761 | default: |
722 | return -EINVAL; | 762 | return -EINVAL; |
723 | } | 763 | } |
@@ -768,6 +808,7 @@ static int hardwall_release(struct inode *inode, struct file *file) | |||
768 | } | 808 | } |
769 | 809 | ||
770 | static const struct file_operations dev_hardwall_fops = { | 810 | static const struct file_operations dev_hardwall_fops = { |
811 | .open = nonseekable_open, | ||
771 | .unlocked_ioctl = hardwall_ioctl, | 812 | .unlocked_ioctl = hardwall_ioctl, |
772 | #ifdef CONFIG_COMPAT | 813 | #ifdef CONFIG_COMPAT |
773 | .compat_ioctl = hardwall_compat_ioctl, | 814 | .compat_ioctl = hardwall_compat_ioctl, |
diff --git a/arch/tile/kernel/head_32.S b/arch/tile/kernel/head_32.S index 2b4f6c091701..1a39b7c1c87e 100644 --- a/arch/tile/kernel/head_32.S +++ b/arch/tile/kernel/head_32.S | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <asm/asm-offsets.h> | 23 | #include <asm/asm-offsets.h> |
24 | #include <hv/hypervisor.h> | 24 | #include <hv/hypervisor.h> |
25 | #include <arch/chip.h> | 25 | #include <arch/chip.h> |
26 | #include <arch/spr_def.h> | ||
26 | 27 | ||
27 | /* | 28 | /* |
28 | * This module contains the entry code for kernel images. It performs the | 29 | * This module contains the entry code for kernel images. It performs the |
@@ -76,7 +77,7 @@ ENTRY(_start) | |||
76 | } | 77 | } |
77 | 1: | 78 | 1: |
78 | 79 | ||
79 | /* Get our processor number and save it away in SAVE_1_0. */ | 80 | /* Get our processor number and save it away in SAVE_K_0. */ |
80 | jal hv_inquire_topology | 81 | jal hv_inquire_topology |
81 | mulll_uu r4, r1, r2 /* r1 == y, r2 == width */ | 82 | mulll_uu r4, r1, r2 /* r1 == y, r2 == width */ |
82 | add r4, r4, r0 /* r0 == x, so r4 == cpu == y*width + x */ | 83 | add r4, r4, r0 /* r0 == x, so r4 == cpu == y*width + x */ |
@@ -124,7 +125,7 @@ ENTRY(_start) | |||
124 | lw r0, r0 | 125 | lw r0, r0 |
125 | lw sp, r1 | 126 | lw sp, r1 |
126 | or r4, sp, r4 | 127 | or r4, sp, r4 |
127 | mtspr SYSTEM_SAVE_1_0, r4 /* save ksp0 + cpu */ | 128 | mtspr SPR_SYSTEM_SAVE_K_0, r4 /* save ksp0 + cpu */ |
128 | addi sp, sp, -STACK_TOP_DELTA | 129 | addi sp, sp, -STACK_TOP_DELTA |
129 | { | 130 | { |
130 | move lr, zero /* stop backtraces in the called function */ | 131 | move lr, zero /* stop backtraces in the called function */ |
@@ -132,7 +133,7 @@ ENTRY(_start) | |||
132 | } | 133 | } |
133 | ENDPROC(_start) | 134 | ENDPROC(_start) |
134 | 135 | ||
135 | .section ".bss.page_aligned","w" | 136 | __PAGE_ALIGNED_BSS |
136 | .align PAGE_SIZE | 137 | .align PAGE_SIZE |
137 | ENTRY(empty_zero_page) | 138 | ENTRY(empty_zero_page) |
138 | .fill PAGE_SIZE,1,0 | 139 | .fill PAGE_SIZE,1,0 |
@@ -144,10 +145,10 @@ ENTRY(empty_zero_page) | |||
144 | .endif | 145 | .endif |
145 | .word HV_PTE_PAGE | HV_PTE_DIRTY | HV_PTE_PRESENT | HV_PTE_ACCESSED | \ | 146 | .word HV_PTE_PAGE | HV_PTE_DIRTY | HV_PTE_PRESENT | HV_PTE_ACCESSED | \ |
146 | (HV_PTE_MODE_CACHE_NO_L3 << HV_PTE_INDEX_MODE) | 147 | (HV_PTE_MODE_CACHE_NO_L3 << HV_PTE_INDEX_MODE) |
147 | .word (\bits1) | (HV_CPA_TO_PFN(\cpa) << HV_PTE_INDEX_PFN) | 148 | .word (\bits1) | (HV_CPA_TO_PFN(\cpa) << (HV_PTE_INDEX_PFN - 32)) |
148 | .endm | 149 | .endm |
149 | 150 | ||
150 | .section ".data.page_aligned","wa" | 151 | __PAGE_ALIGNED_DATA |
151 | .align PAGE_SIZE | 152 | .align PAGE_SIZE |
152 | ENTRY(swapper_pg_dir) | 153 | ENTRY(swapper_pg_dir) |
153 | /* | 154 | /* |
@@ -157,12 +158,14 @@ ENTRY(swapper_pg_dir) | |||
157 | */ | 158 | */ |
158 | .set addr, 0 | 159 | .set addr, 0 |
159 | .rept (MEM_USER_INTRPT - PAGE_OFFSET) >> PGDIR_SHIFT | 160 | .rept (MEM_USER_INTRPT - PAGE_OFFSET) >> PGDIR_SHIFT |
160 | PTE addr + PAGE_OFFSET, addr, HV_PTE_READABLE | HV_PTE_WRITABLE | 161 | PTE addr + PAGE_OFFSET, addr, (1 << (HV_PTE_INDEX_READABLE - 32)) | \ |
162 | (1 << (HV_PTE_INDEX_WRITABLE - 32)) | ||
161 | .set addr, addr + PGDIR_SIZE | 163 | .set addr, addr + PGDIR_SIZE |
162 | .endr | 164 | .endr |
163 | 165 | ||
164 | /* The true text VAs are mapped as VA = PA + MEM_SV_INTRPT */ | 166 | /* The true text VAs are mapped as VA = PA + MEM_SV_INTRPT */ |
165 | PTE MEM_SV_INTRPT, 0, HV_PTE_READABLE | HV_PTE_EXECUTABLE | 167 | PTE MEM_SV_INTRPT, 0, (1 << (HV_PTE_INDEX_READABLE - 32)) | \ |
168 | (1 << (HV_PTE_INDEX_EXECUTABLE - 32)) | ||
166 | .org swapper_pg_dir + HV_L1_SIZE | 169 | .org swapper_pg_dir + HV_L1_SIZE |
167 | END(swapper_pg_dir) | 170 | END(swapper_pg_dir) |
168 | 171 | ||
@@ -175,6 +178,7 @@ ENTRY(swapper_pg_dir) | |||
175 | __INITDATA | 178 | __INITDATA |
176 | .align CHIP_L2_LINE_SIZE() | 179 | .align CHIP_L2_LINE_SIZE() |
177 | ENTRY(swapper_pgprot) | 180 | ENTRY(swapper_pgprot) |
178 | PTE 0, 0, HV_PTE_READABLE | HV_PTE_WRITABLE, 1 | 181 | PTE 0, 0, (1 << (HV_PTE_INDEX_READABLE - 32)) | \ |
182 | (1 << (HV_PTE_INDEX_WRITABLE - 32)), 1 | ||
179 | .align CHIP_L2_LINE_SIZE() | 183 | .align CHIP_L2_LINE_SIZE() |
180 | END(swapper_pgprot) | 184 | END(swapper_pgprot) |
diff --git a/arch/tile/kernel/head_64.S b/arch/tile/kernel/head_64.S new file mode 100644 index 000000000000..6bc3a932fe45 --- /dev/null +++ b/arch/tile/kernel/head_64.S | |||
@@ -0,0 +1,269 @@ | |||
1 | /* | ||
2 | * Copyright 2011 Tilera Corporation. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation, version 2. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
11 | * NON INFRINGEMENT. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * TILE startup code. | ||
15 | */ | ||
16 | |||
17 | #include <linux/linkage.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <asm/page.h> | ||
20 | #include <asm/pgtable.h> | ||
21 | #include <asm/thread_info.h> | ||
22 | #include <asm/processor.h> | ||
23 | #include <asm/asm-offsets.h> | ||
24 | #include <hv/hypervisor.h> | ||
25 | #include <arch/chip.h> | ||
26 | #include <arch/spr_def.h> | ||
27 | |||
28 | /* | ||
29 | * This module contains the entry code for kernel images. It performs the | ||
30 | * minimal setup needed to call the generic C routines. | ||
31 | */ | ||
32 | |||
33 | __HEAD | ||
34 | ENTRY(_start) | ||
35 | /* Notify the hypervisor of what version of the API we want */ | ||
36 | { | ||
37 | movei r1, TILE_CHIP | ||
38 | movei r2, TILE_CHIP_REV | ||
39 | } | ||
40 | { | ||
41 | moveli r0, _HV_VERSION | ||
42 | jal hv_init | ||
43 | } | ||
44 | /* Get a reasonable default ASID in r0 */ | ||
45 | { | ||
46 | move r0, zero | ||
47 | jal hv_inquire_asid | ||
48 | } | ||
49 | |||
50 | /* | ||
51 | * Install the default page table. The relocation required to | ||
52 | * statically define the table is a bit too complex, so we have | ||
53 | * to plug in the pointer from the L0 to the L1 table by hand. | ||
54 | * We only do this on the first cpu to boot, though, since the | ||
55 | * other CPUs should see a properly-constructed page table. | ||
56 | */ | ||
57 | { | ||
58 | v4int_l r2, zero, r0 /* ASID for hv_install_context */ | ||
59 | moveli r4, hw1_last(swapper_pgprot - PAGE_OFFSET) | ||
60 | } | ||
61 | { | ||
62 | shl16insli r4, r4, hw0(swapper_pgprot - PAGE_OFFSET) | ||
63 | } | ||
64 | { | ||
65 | ld r1, r4 /* access_pte for hv_install_context */ | ||
66 | } | ||
67 | { | ||
68 | moveli r0, hw1_last(.Lsv_data_pmd - PAGE_OFFSET) | ||
69 | moveli r6, hw1_last(temp_data_pmd - PAGE_OFFSET) | ||
70 | } | ||
71 | { | ||
72 | /* After initializing swapper_pgprot, HV_PTE_GLOBAL is set. */ | ||
73 | bfextu r7, r1, HV_PTE_INDEX_GLOBAL, HV_PTE_INDEX_GLOBAL | ||
74 | inv r4 | ||
75 | } | ||
76 | bnez r7, .Lno_write | ||
77 | { | ||
78 | shl16insli r0, r0, hw0(.Lsv_data_pmd - PAGE_OFFSET) | ||
79 | shl16insli r6, r6, hw0(temp_data_pmd - PAGE_OFFSET) | ||
80 | } | ||
81 | { | ||
82 | /* Cut off the low bits of the PT address. */ | ||
83 | shrui r6, r6, HV_LOG2_PAGE_TABLE_ALIGN | ||
84 | /* Start with our access pte. */ | ||
85 | move r5, r1 | ||
86 | } | ||
87 | { | ||
88 | /* Stuff the address into the page table pointer slot of the PTE. */ | ||
89 | bfins r5, r6, HV_PTE_INDEX_PTFN, \ | ||
90 | HV_PTE_INDEX_PTFN + HV_PTE_PTFN_BITS - 1 | ||
91 | } | ||
92 | { | ||
93 | /* Store the L0 data PTE. */ | ||
94 | st r0, r5 | ||
95 | addli r6, r6, (temp_code_pmd - temp_data_pmd) >> \ | ||
96 | HV_LOG2_PAGE_TABLE_ALIGN | ||
97 | } | ||
98 | { | ||
99 | addli r0, r0, .Lsv_code_pmd - .Lsv_data_pmd | ||
100 | bfins r5, r6, HV_PTE_INDEX_PTFN, \ | ||
101 | HV_PTE_INDEX_PTFN + HV_PTE_PTFN_BITS - 1 | ||
102 | } | ||
103 | /* Store the L0 code PTE. */ | ||
104 | st r0, r5 | ||
105 | |||
106 | .Lno_write: | ||
107 | moveli lr, hw2_last(1f) | ||
108 | { | ||
109 | shl16insli lr, lr, hw1(1f) | ||
110 | moveli r0, hw1_last(swapper_pg_dir - PAGE_OFFSET) | ||
111 | } | ||
112 | { | ||
113 | shl16insli lr, lr, hw0(1f) | ||
114 | shl16insli r0, r0, hw0(swapper_pg_dir - PAGE_OFFSET) | ||
115 | } | ||
116 | { | ||
117 | move r3, zero | ||
118 | j hv_install_context | ||
119 | } | ||
120 | 1: | ||
121 | |||
122 | /* Install the interrupt base. */ | ||
123 | moveli r0, hw2_last(MEM_SV_START) | ||
124 | shl16insli r0, r0, hw1(MEM_SV_START) | ||
125 | shl16insli r0, r0, hw0(MEM_SV_START) | ||
126 | mtspr SPR_INTERRUPT_VECTOR_BASE_K, r0 | ||
127 | |||
128 | /* | ||
129 | * Get our processor number and save it away in SAVE_K_0. | ||
130 | * Extract stuff from the topology structure: r4 = y, r6 = x, | ||
131 | * r5 = width. FIXME: consider whether we want to just make these | ||
132 | * 64-bit values (and if so fix smp_topology write below, too). | ||
133 | */ | ||
134 | jal hv_inquire_topology | ||
135 | { | ||
136 | v4int_l r5, zero, r1 /* r5 = width */ | ||
137 | shrui r4, r0, 32 /* r4 = y */ | ||
138 | } | ||
139 | { | ||
140 | v4int_l r6, zero, r0 /* r6 = x */ | ||
141 | mul_lu_lu r4, r4, r5 | ||
142 | } | ||
143 | { | ||
144 | add r4, r4, r6 /* r4 == cpu == y*width + x */ | ||
145 | } | ||
146 | |||
147 | #ifdef CONFIG_SMP | ||
148 | /* | ||
149 | * Load up our per-cpu offset. When the first (master) tile | ||
150 | * boots, this value is still zero, so we will load boot_pc | ||
151 | * with start_kernel, and boot_sp with init_stack + THREAD_SIZE. | ||
152 | * The master tile initializes the per-cpu offset array, so that | ||
153 | * when subsequent (secondary) tiles boot, they will instead load | ||
154 | * from their per-cpu versions of boot_sp and boot_pc. | ||
155 | */ | ||
156 | moveli r5, hw2_last(__per_cpu_offset) | ||
157 | shl16insli r5, r5, hw1(__per_cpu_offset) | ||
158 | shl16insli r5, r5, hw0(__per_cpu_offset) | ||
159 | shl3add r5, r4, r5 | ||
160 | ld r5, r5 | ||
161 | bnez r5, 1f | ||
162 | |||
163 | /* | ||
164 | * Save the width and height to the smp_topology variable | ||
165 | * for later use. | ||
166 | */ | ||
167 | moveli r0, hw2_last(smp_topology + HV_TOPOLOGY_WIDTH_OFFSET) | ||
168 | shl16insli r0, r0, hw1(smp_topology + HV_TOPOLOGY_WIDTH_OFFSET) | ||
169 | shl16insli r0, r0, hw0(smp_topology + HV_TOPOLOGY_WIDTH_OFFSET) | ||
170 | st r0, r1 | ||
171 | 1: | ||
172 | #else | ||
173 | move r5, zero | ||
174 | #endif | ||
175 | |||
176 | /* Load and go with the correct pc and sp. */ | ||
177 | { | ||
178 | moveli r1, hw2_last(boot_sp) | ||
179 | moveli r0, hw2_last(boot_pc) | ||
180 | } | ||
181 | { | ||
182 | shl16insli r1, r1, hw1(boot_sp) | ||
183 | shl16insli r0, r0, hw1(boot_pc) | ||
184 | } | ||
185 | { | ||
186 | shl16insli r1, r1, hw0(boot_sp) | ||
187 | shl16insli r0, r0, hw0(boot_pc) | ||
188 | } | ||
189 | { | ||
190 | add r1, r1, r5 | ||
191 | add r0, r0, r5 | ||
192 | } | ||
193 | ld r0, r0 | ||
194 | ld sp, r1 | ||
195 | or r4, sp, r4 | ||
196 | mtspr SPR_SYSTEM_SAVE_K_0, r4 /* save ksp0 + cpu */ | ||
197 | addi sp, sp, -STACK_TOP_DELTA | ||
198 | { | ||
199 | move lr, zero /* stop backtraces in the called function */ | ||
200 | jr r0 | ||
201 | } | ||
202 | ENDPROC(_start) | ||
203 | |||
204 | __PAGE_ALIGNED_BSS | ||
205 | .align PAGE_SIZE | ||
206 | ENTRY(empty_zero_page) | ||
207 | .fill PAGE_SIZE,1,0 | ||
208 | END(empty_zero_page) | ||
209 | |||
210 | .macro PTE cpa, bits1 | ||
211 | .quad HV_PTE_PAGE | HV_PTE_DIRTY | HV_PTE_PRESENT | HV_PTE_ACCESSED |\ | ||
212 | HV_PTE_GLOBAL | (HV_PTE_MODE_CACHE_NO_L3 << HV_PTE_INDEX_MODE) |\ | ||
213 | (\bits1) | (HV_CPA_TO_PFN(\cpa) << HV_PTE_INDEX_PFN) | ||
214 | .endm | ||
215 | |||
216 | __PAGE_ALIGNED_DATA | ||
217 | .align PAGE_SIZE | ||
218 | ENTRY(swapper_pg_dir) | ||
219 | .org swapper_pg_dir + HV_L0_INDEX(PAGE_OFFSET) * HV_PTE_SIZE | ||
220 | .Lsv_data_pmd: | ||
221 | .quad 0 /* PTE temp_data_pmd - PAGE_OFFSET, 0 */ | ||
222 | .org swapper_pg_dir + HV_L0_INDEX(MEM_SV_START) * HV_PTE_SIZE | ||
223 | .Lsv_code_pmd: | ||
224 | .quad 0 /* PTE temp_code_pmd - PAGE_OFFSET, 0 */ | ||
225 | .org swapper_pg_dir + HV_L0_SIZE | ||
226 | END(swapper_pg_dir) | ||
227 | |||
228 | .align HV_PAGE_TABLE_ALIGN | ||
229 | ENTRY(temp_data_pmd) | ||
230 | /* | ||
231 | * We fill the PAGE_OFFSET pmd with huge pages with | ||
232 | * VA = PA + PAGE_OFFSET. We remap things with more precise access | ||
233 | * permissions later. | ||
234 | */ | ||
235 | .set addr, 0 | ||
236 | .rept HV_L1_ENTRIES | ||
237 | PTE addr, HV_PTE_READABLE | HV_PTE_WRITABLE | ||
238 | .set addr, addr + HV_PAGE_SIZE_LARGE | ||
239 | .endr | ||
240 | .org temp_data_pmd + HV_L1_SIZE | ||
241 | END(temp_data_pmd) | ||
242 | |||
243 | .align HV_PAGE_TABLE_ALIGN | ||
244 | ENTRY(temp_code_pmd) | ||
245 | /* | ||
246 | * We fill the MEM_SV_START pmd with huge pages with | ||
247 | * VA = PA + PAGE_OFFSET. We remap things with more precise access | ||
248 | * permissions later. | ||
249 | */ | ||
250 | .set addr, 0 | ||
251 | .rept HV_L1_ENTRIES | ||
252 | PTE addr, HV_PTE_READABLE | HV_PTE_EXECUTABLE | ||
253 | .set addr, addr + HV_PAGE_SIZE_LARGE | ||
254 | .endr | ||
255 | .org temp_code_pmd + HV_L1_SIZE | ||
256 | END(temp_code_pmd) | ||
257 | |||
258 | /* | ||
259 | * Isolate swapper_pgprot to its own cache line, since each cpu | ||
260 | * starting up will read it using VA-is-PA and local homing. | ||
261 | * This would otherwise likely conflict with other data on the cache | ||
262 | * line, once we have set its permanent home in the page tables. | ||
263 | */ | ||
264 | __INITDATA | ||
265 | .align CHIP_L2_LINE_SIZE() | ||
266 | ENTRY(swapper_pgprot) | ||
267 | .quad HV_PTE_PRESENT | (HV_PTE_MODE_CACHE_NO_L3 << HV_PTE_INDEX_MODE) | ||
268 | .align CHIP_L2_LINE_SIZE() | ||
269 | END(swapper_pgprot) | ||
diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S index 8f58bdff20d7..72ade79b621b 100644 --- a/arch/tile/kernel/intvec_32.S +++ b/arch/tile/kernel/intvec_32.S | |||
@@ -32,10 +32,6 @@ | |||
32 | # error "No support for kernel preemption currently" | 32 | # error "No support for kernel preemption currently" |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | #if INT_INTCTRL_1 < 32 || INT_INTCTRL_1 >= 48 | ||
36 | # error INT_INTCTRL_1 coded to set high interrupt mask | ||
37 | #endif | ||
38 | |||
39 | #define PTREGS_PTR(reg, ptreg) addli reg, sp, C_ABI_SAVE_AREA_SIZE + (ptreg) | 35 | #define PTREGS_PTR(reg, ptreg) addli reg, sp, C_ABI_SAVE_AREA_SIZE + (ptreg) |
40 | 36 | ||
41 | #define PTREGS_OFFSET_SYSCALL PTREGS_OFFSET_REG(TREG_SYSCALL_NR) | 37 | #define PTREGS_OFFSET_SYSCALL PTREGS_OFFSET_REG(TREG_SYSCALL_NR) |
@@ -132,8 +128,8 @@ intvec_\vecname: | |||
132 | 128 | ||
133 | /* Temporarily save a register so we have somewhere to work. */ | 129 | /* Temporarily save a register so we have somewhere to work. */ |
134 | 130 | ||
135 | mtspr SYSTEM_SAVE_1_1, r0 | 131 | mtspr SPR_SYSTEM_SAVE_K_1, r0 |
136 | mfspr r0, EX_CONTEXT_1_1 | 132 | mfspr r0, SPR_EX_CONTEXT_K_1 |
137 | 133 | ||
138 | /* The cmpxchg code clears sp to force us to reset it here on fault. */ | 134 | /* The cmpxchg code clears sp to force us to reset it here on fault. */ |
139 | { | 135 | { |
@@ -167,18 +163,18 @@ intvec_\vecname: | |||
167 | * The page_fault handler may be downcalled directly by the | 163 | * The page_fault handler may be downcalled directly by the |
168 | * hypervisor even when Linux is running and has ICS set. | 164 | * hypervisor even when Linux is running and has ICS set. |
169 | * | 165 | * |
170 | * In this case the contents of EX_CONTEXT_1_1 reflect the | 166 | * In this case the contents of EX_CONTEXT_K_1 reflect the |
171 | * previous fault and can't be relied on to choose whether or | 167 | * previous fault and can't be relied on to choose whether or |
172 | * not to reinitialize the stack pointer. So we add a test | 168 | * not to reinitialize the stack pointer. So we add a test |
173 | * to see whether SYSTEM_SAVE_1_2 has the high bit set, | 169 | * to see whether SYSTEM_SAVE_K_2 has the high bit set, |
174 | * and if so we don't reinitialize sp, since we must be coming | 170 | * and if so we don't reinitialize sp, since we must be coming |
175 | * from Linux. (In fact the precise case is !(val & ~1), | 171 | * from Linux. (In fact the precise case is !(val & ~1), |
176 | * but any Linux PC has to have the high bit set.) | 172 | * but any Linux PC has to have the high bit set.) |
177 | * | 173 | * |
178 | * Note that the hypervisor *always* sets SYSTEM_SAVE_1_2 for | 174 | * Note that the hypervisor *always* sets SYSTEM_SAVE_K_2 for |
179 | * any path that turns into a downcall to one of our TLB handlers. | 175 | * any path that turns into a downcall to one of our TLB handlers. |
180 | */ | 176 | */ |
181 | mfspr r0, SYSTEM_SAVE_1_2 | 177 | mfspr r0, SPR_SYSTEM_SAVE_K_2 |
182 | { | 178 | { |
183 | blz r0, 0f /* high bit in S_S_1_2 is for a PC to use */ | 179 | blz r0, 0f /* high bit in S_S_1_2 is for a PC to use */ |
184 | move r0, sp | 180 | move r0, sp |
@@ -187,12 +183,12 @@ intvec_\vecname: | |||
187 | 183 | ||
188 | 2: | 184 | 2: |
189 | /* | 185 | /* |
190 | * SYSTEM_SAVE_1_0 holds the cpu number in the low bits, and | 186 | * SYSTEM_SAVE_K_0 holds the cpu number in the low bits, and |
191 | * the current stack top in the higher bits. So we recover | 187 | * the current stack top in the higher bits. So we recover |
192 | * our stack top by just masking off the low bits, then | 188 | * our stack top by just masking off the low bits, then |
193 | * point sp at the top aligned address on the actual stack page. | 189 | * point sp at the top aligned address on the actual stack page. |
194 | */ | 190 | */ |
195 | mfspr r0, SYSTEM_SAVE_1_0 | 191 | mfspr r0, SPR_SYSTEM_SAVE_K_0 |
196 | mm r0, r0, zero, LOG2_THREAD_SIZE, 31 | 192 | mm r0, r0, zero, LOG2_THREAD_SIZE, 31 |
197 | 193 | ||
198 | 0: | 194 | 0: |
@@ -254,7 +250,7 @@ intvec_\vecname: | |||
254 | sw sp, r3 | 250 | sw sp, r3 |
255 | addli sp, sp, PTREGS_OFFSET_PC - PTREGS_OFFSET_REG(3) | 251 | addli sp, sp, PTREGS_OFFSET_PC - PTREGS_OFFSET_REG(3) |
256 | } | 252 | } |
257 | mfspr r0, EX_CONTEXT_1_0 | 253 | mfspr r0, SPR_EX_CONTEXT_K_0 |
258 | .ifc \processing,handle_syscall | 254 | .ifc \processing,handle_syscall |
259 | /* | 255 | /* |
260 | * Bump the saved PC by one bundle so that when we return, we won't | 256 | * Bump the saved PC by one bundle so that when we return, we won't |
@@ -267,7 +263,7 @@ intvec_\vecname: | |||
267 | sw sp, r0 | 263 | sw sp, r0 |
268 | addli sp, sp, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_PC | 264 | addli sp, sp, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_PC |
269 | } | 265 | } |
270 | mfspr r0, EX_CONTEXT_1_1 | 266 | mfspr r0, SPR_EX_CONTEXT_K_1 |
271 | { | 267 | { |
272 | sw sp, r0 | 268 | sw sp, r0 |
273 | addi sp, sp, PTREGS_OFFSET_FAULTNUM - PTREGS_OFFSET_EX1 | 269 | addi sp, sp, PTREGS_OFFSET_FAULTNUM - PTREGS_OFFSET_EX1 |
@@ -289,7 +285,7 @@ intvec_\vecname: | |||
289 | .endif | 285 | .endif |
290 | addli sp, sp, PTREGS_OFFSET_REG(0) - PTREGS_OFFSET_FAULTNUM | 286 | addli sp, sp, PTREGS_OFFSET_REG(0) - PTREGS_OFFSET_FAULTNUM |
291 | } | 287 | } |
292 | mfspr r0, SYSTEM_SAVE_1_1 /* Original r0 */ | 288 | mfspr r0, SPR_SYSTEM_SAVE_K_1 /* Original r0 */ |
293 | { | 289 | { |
294 | sw sp, r0 | 290 | sw sp, r0 |
295 | addi sp, sp, -PTREGS_OFFSET_REG(0) - 4 | 291 | addi sp, sp, -PTREGS_OFFSET_REG(0) - 4 |
@@ -309,12 +305,12 @@ intvec_\vecname: | |||
309 | * See discussion below at "finish_interrupt_save". | 305 | * See discussion below at "finish_interrupt_save". |
310 | */ | 306 | */ |
311 | .ifc \c_routine, do_page_fault | 307 | .ifc \c_routine, do_page_fault |
312 | mfspr r2, SYSTEM_SAVE_1_3 /* address of page fault */ | 308 | mfspr r2, SPR_SYSTEM_SAVE_K_3 /* address of page fault */ |
313 | mfspr r3, SYSTEM_SAVE_1_2 /* info about page fault */ | 309 | mfspr r3, SPR_SYSTEM_SAVE_K_2 /* info about page fault */ |
314 | .else | 310 | .else |
315 | .ifc \vecnum, INT_DOUBLE_FAULT | 311 | .ifc \vecnum, INT_DOUBLE_FAULT |
316 | { | 312 | { |
317 | mfspr r2, SYSTEM_SAVE_1_2 /* double fault info from HV */ | 313 | mfspr r2, SPR_SYSTEM_SAVE_K_2 /* double fault info from HV */ |
318 | movei r3, 0 | 314 | movei r3, 0 |
319 | } | 315 | } |
320 | .else | 316 | .else |
@@ -467,7 +463,7 @@ intvec_\vecname: | |||
467 | /* Load tp with our per-cpu offset. */ | 463 | /* Load tp with our per-cpu offset. */ |
468 | #ifdef CONFIG_SMP | 464 | #ifdef CONFIG_SMP |
469 | { | 465 | { |
470 | mfspr r20, SYSTEM_SAVE_1_0 | 466 | mfspr r20, SPR_SYSTEM_SAVE_K_0 |
471 | moveli r21, lo16(__per_cpu_offset) | 467 | moveli r21, lo16(__per_cpu_offset) |
472 | } | 468 | } |
473 | { | 469 | { |
@@ -487,7 +483,7 @@ intvec_\vecname: | |||
487 | * We load flags in r32 here so we can jump to .Lrestore_regs | 483 | * We load flags in r32 here so we can jump to .Lrestore_regs |
488 | * directly after do_page_fault_ics() if necessary. | 484 | * directly after do_page_fault_ics() if necessary. |
489 | */ | 485 | */ |
490 | mfspr r32, EX_CONTEXT_1_1 | 486 | mfspr r32, SPR_EX_CONTEXT_K_1 |
491 | { | 487 | { |
492 | andi r32, r32, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ | 488 | andi r32, r32, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ |
493 | PTREGS_PTR(r21, PTREGS_OFFSET_FLAGS) | 489 | PTREGS_PTR(r21, PTREGS_OFFSET_FLAGS) |
@@ -855,14 +851,27 @@ STD_ENTRY(interrupt_return) | |||
855 | /* Check to see if there is any work to do before returning to user. */ | 851 | /* Check to see if there is any work to do before returning to user. */ |
856 | { | 852 | { |
857 | addi r29, r32, THREAD_INFO_FLAGS_OFFSET | 853 | addi r29, r32, THREAD_INFO_FLAGS_OFFSET |
858 | moveli r28, lo16(_TIF_ALLWORK_MASK) | 854 | moveli r1, lo16(_TIF_ALLWORK_MASK) |
859 | } | 855 | } |
860 | { | 856 | { |
861 | lw r29, r29 | 857 | lw r29, r29 |
862 | auli r28, r28, ha16(_TIF_ALLWORK_MASK) | 858 | auli r1, r1, ha16(_TIF_ALLWORK_MASK) |
863 | } | 859 | } |
864 | and r28, r29, r28 | 860 | and r1, r29, r1 |
865 | bnz r28, .Lwork_pending | 861 | bzt r1, .Lrestore_all |
862 | |||
863 | /* | ||
864 | * Make sure we have all the registers saved for signal | ||
865 | * handling or single-step. Call out to C code to figure out | ||
866 | * exactly what we need to do for each flag bit, then if | ||
867 | * necessary, reload the flags and recheck. | ||
868 | */ | ||
869 | push_extra_callee_saves r0 | ||
870 | { | ||
871 | PTREGS_PTR(r0, PTREGS_OFFSET_BASE) | ||
872 | jal do_work_pending | ||
873 | } | ||
874 | bnz r0, .Lresume_userspace | ||
866 | 875 | ||
867 | /* | 876 | /* |
868 | * In the NMI case we | 877 | * In the NMI case we |
@@ -957,11 +966,11 @@ STD_ENTRY(interrupt_return) | |||
957 | pop_reg_zero r21, r3, sp, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_PC | 966 | pop_reg_zero r21, r3, sp, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_PC |
958 | pop_reg_zero lr, r4, sp, PTREGS_OFFSET_REG(52) - PTREGS_OFFSET_EX1 | 967 | pop_reg_zero lr, r4, sp, PTREGS_OFFSET_REG(52) - PTREGS_OFFSET_EX1 |
959 | { | 968 | { |
960 | mtspr EX_CONTEXT_1_0, r21 | 969 | mtspr SPR_EX_CONTEXT_K_0, r21 |
961 | move r5, zero | 970 | move r5, zero |
962 | } | 971 | } |
963 | { | 972 | { |
964 | mtspr EX_CONTEXT_1_1, lr | 973 | mtspr SPR_EX_CONTEXT_K_1, lr |
965 | andi lr, lr, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ | 974 | andi lr, lr, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ |
966 | } | 975 | } |
967 | 976 | ||
@@ -1020,7 +1029,7 @@ STD_ENTRY(interrupt_return) | |||
1020 | 1029 | ||
1021 | /* Set r1 to errno if we are returning an error, otherwise zero. */ | 1030 | /* Set r1 to errno if we are returning an error, otherwise zero. */ |
1022 | { | 1031 | { |
1023 | moveli r29, 1024 | 1032 | moveli r29, 4096 |
1024 | sub r1, zero, r0 | 1033 | sub r1, zero, r0 |
1025 | } | 1034 | } |
1026 | slt_u r29, r1, r29 | 1035 | slt_u r29, r1, r29 |
@@ -1103,142 +1112,9 @@ STD_ENTRY(interrupt_return) | |||
1103 | pop_reg r50 | 1112 | pop_reg r50 |
1104 | pop_reg r51, sp, PTREGS_OFFSET_REG(29) - PTREGS_OFFSET_REG(51) | 1113 | pop_reg r51, sp, PTREGS_OFFSET_REG(29) - PTREGS_OFFSET_REG(51) |
1105 | j .Lcontinue_restore_regs | 1114 | j .Lcontinue_restore_regs |
1106 | |||
1107 | .Lwork_pending: | ||
1108 | /* Mask the reschedule flag */ | ||
1109 | andi r28, r29, _TIF_NEED_RESCHED | ||
1110 | |||
1111 | { | ||
1112 | /* | ||
1113 | * If the NEED_RESCHED flag is called, we call schedule(), which | ||
1114 | * may drop this context right here and go do something else. | ||
1115 | * On return, jump back to .Lresume_userspace and recheck. | ||
1116 | */ | ||
1117 | bz r28, .Lasync_tlb | ||
1118 | |||
1119 | /* Mask the async-tlb flag */ | ||
1120 | andi r28, r29, _TIF_ASYNC_TLB | ||
1121 | } | ||
1122 | |||
1123 | jal schedule | ||
1124 | FEEDBACK_REENTER(interrupt_return) | ||
1125 | |||
1126 | /* Reload the flags and check again */ | ||
1127 | j .Lresume_userspace | ||
1128 | |||
1129 | .Lasync_tlb: | ||
1130 | { | ||
1131 | bz r28, .Lneed_sigpending | ||
1132 | |||
1133 | /* Mask the sigpending flag */ | ||
1134 | andi r28, r29, _TIF_SIGPENDING | ||
1135 | } | ||
1136 | |||
1137 | PTREGS_PTR(r0, PTREGS_OFFSET_BASE) | ||
1138 | jal do_async_page_fault | ||
1139 | FEEDBACK_REENTER(interrupt_return) | ||
1140 | |||
1141 | /* | ||
1142 | * Go restart the "resume userspace" process. We may have | ||
1143 | * fired a signal, and we need to disable interrupts again. | ||
1144 | */ | ||
1145 | j .Lresume_userspace | ||
1146 | |||
1147 | .Lneed_sigpending: | ||
1148 | /* | ||
1149 | * At this point we are either doing signal handling or single-step, | ||
1150 | * so either way make sure we have all the registers saved. | ||
1151 | */ | ||
1152 | push_extra_callee_saves r0 | ||
1153 | |||
1154 | { | ||
1155 | /* If no signal pending, skip to singlestep check */ | ||
1156 | bz r28, .Lneed_singlestep | ||
1157 | |||
1158 | /* Mask the singlestep flag */ | ||
1159 | andi r28, r29, _TIF_SINGLESTEP | ||
1160 | } | ||
1161 | |||
1162 | jal do_signal | ||
1163 | FEEDBACK_REENTER(interrupt_return) | ||
1164 | |||
1165 | /* Reload the flags and check again */ | ||
1166 | j .Lresume_userspace | ||
1167 | |||
1168 | .Lneed_singlestep: | ||
1169 | { | ||
1170 | /* Get a pointer to the EX1 field */ | ||
1171 | PTREGS_PTR(r29, PTREGS_OFFSET_EX1) | ||
1172 | |||
1173 | /* If we get here, our bit must be set. */ | ||
1174 | bz r28, .Lwork_confusion | ||
1175 | } | ||
1176 | /* If we are in priv mode, don't single step */ | ||
1177 | lw r28, r29 | ||
1178 | andi r28, r28, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ | ||
1179 | bnz r28, .Lrestore_all | ||
1180 | |||
1181 | /* Allow interrupts within the single step code */ | ||
1182 | TRACE_IRQS_ON /* Note: clobbers registers r0-r29 */ | ||
1183 | IRQ_ENABLE(r20, r21) | ||
1184 | |||
1185 | /* try to single-step the current instruction */ | ||
1186 | PTREGS_PTR(r0, PTREGS_OFFSET_BASE) | ||
1187 | jal single_step_once | ||
1188 | FEEDBACK_REENTER(interrupt_return) | ||
1189 | |||
1190 | /* Re-disable interrupts. TRACE_IRQS_OFF in .Lrestore_all. */ | ||
1191 | IRQ_DISABLE(r20,r21) | ||
1192 | |||
1193 | j .Lrestore_all | ||
1194 | |||
1195 | .Lwork_confusion: | ||
1196 | move r0, r28 | ||
1197 | panic "thread_info allwork flags unhandled on userspace resume: %#x" | ||
1198 | |||
1199 | STD_ENDPROC(interrupt_return) | 1115 | STD_ENDPROC(interrupt_return) |
1200 | 1116 | ||
1201 | /* | 1117 | /* |
1202 | * This interrupt variant clears the INT_INTCTRL_1 interrupt mask bit | ||
1203 | * before returning, so we can properly get more downcalls. | ||
1204 | */ | ||
1205 | .pushsection .text.handle_interrupt_downcall,"ax" | ||
1206 | handle_interrupt_downcall: | ||
1207 | finish_interrupt_save handle_interrupt_downcall | ||
1208 | check_single_stepping normal, .Ldispatch_downcall | ||
1209 | .Ldispatch_downcall: | ||
1210 | |||
1211 | /* Clear INTCTRL_1 from the set of interrupts we ever enable. */ | ||
1212 | GET_INTERRUPTS_ENABLED_MASK_PTR(r30) | ||
1213 | { | ||
1214 | addi r30, r30, 4 | ||
1215 | movei r31, INT_MASK(INT_INTCTRL_1) | ||
1216 | } | ||
1217 | { | ||
1218 | lw r20, r30 | ||
1219 | nor r21, r31, zero | ||
1220 | } | ||
1221 | and r20, r20, r21 | ||
1222 | sw r30, r20 | ||
1223 | |||
1224 | { | ||
1225 | jalr r0 | ||
1226 | PTREGS_PTR(r0, PTREGS_OFFSET_BASE) | ||
1227 | } | ||
1228 | FEEDBACK_REENTER(handle_interrupt_downcall) | ||
1229 | |||
1230 | /* Allow INTCTRL_1 to be enabled next time we enable interrupts. */ | ||
1231 | lw r20, r30 | ||
1232 | or r20, r20, r31 | ||
1233 | sw r30, r20 | ||
1234 | |||
1235 | { | ||
1236 | movei r30, 0 /* not an NMI */ | ||
1237 | j interrupt_return | ||
1238 | } | ||
1239 | STD_ENDPROC(handle_interrupt_downcall) | ||
1240 | |||
1241 | /* | ||
1242 | * Some interrupts don't check for single stepping | 1118 | * Some interrupts don't check for single stepping |
1243 | */ | 1119 | */ |
1244 | .pushsection .text.handle_interrupt_no_single_step,"ax" | 1120 | .pushsection .text.handle_interrupt_no_single_step,"ax" |
@@ -1342,8 +1218,8 @@ handle_syscall: | |||
1342 | lw r20, r20 | 1218 | lw r20, r20 |
1343 | 1219 | ||
1344 | /* Jump to syscall handler. */ | 1220 | /* Jump to syscall handler. */ |
1345 | jalr r20; .Lhandle_syscall_link: | 1221 | jalr r20 |
1346 | FEEDBACK_REENTER(handle_syscall) | 1222 | .Lhandle_syscall_link: /* value of "lr" after "jalr r20" above */ |
1347 | 1223 | ||
1348 | /* | 1224 | /* |
1349 | * Write our r0 onto the stack so it gets restored instead | 1225 | * Write our r0 onto the stack so it gets restored instead |
@@ -1352,6 +1228,9 @@ handle_syscall: | |||
1352 | PTREGS_PTR(r29, PTREGS_OFFSET_REG(0)) | 1228 | PTREGS_PTR(r29, PTREGS_OFFSET_REG(0)) |
1353 | sw r29, r0 | 1229 | sw r29, r0 |
1354 | 1230 | ||
1231 | .Lsyscall_sigreturn_skip: | ||
1232 | FEEDBACK_REENTER(handle_syscall) | ||
1233 | |||
1355 | /* Do syscall trace again, if requested. */ | 1234 | /* Do syscall trace again, if requested. */ |
1356 | lw r30, r31 | 1235 | lw r30, r31 |
1357 | andi r30, r30, _TIF_SYSCALL_TRACE | 1236 | andi r30, r30, _TIF_SYSCALL_TRACE |
@@ -1472,7 +1351,12 @@ handle_ill: | |||
1472 | lw r26, r24 | 1351 | lw r26, r24 |
1473 | sw r28, r26 | 1352 | sw r28, r26 |
1474 | 1353 | ||
1475 | /* Clear TIF_SINGLESTEP */ | 1354 | /* |
1355 | * Clear TIF_SINGLESTEP to prevent recursion if we execute an ill. | ||
1356 | * The normal non-arch flow redundantly clears TIF_SINGLESTEP, but we | ||
1357 | * need to clear it here and can't really impose on all other arches. | ||
1358 | * So what's another write between friends? | ||
1359 | */ | ||
1476 | GET_THREAD_INFO(r0) | 1360 | GET_THREAD_INFO(r0) |
1477 | 1361 | ||
1478 | addi r1, r0, THREAD_INFO_FLAGS_OFFSET | 1362 | addi r1, r0, THREAD_INFO_FLAGS_OFFSET |
@@ -1509,7 +1393,7 @@ handle_ill: | |||
1509 | /* Various stub interrupt handlers and syscall handlers */ | 1393 | /* Various stub interrupt handlers and syscall handlers */ |
1510 | 1394 | ||
1511 | STD_ENTRY_LOCAL(_kernel_double_fault) | 1395 | STD_ENTRY_LOCAL(_kernel_double_fault) |
1512 | mfspr r1, EX_CONTEXT_1_0 | 1396 | mfspr r1, SPR_EX_CONTEXT_K_0 |
1513 | move r2, lr | 1397 | move r2, lr |
1514 | move r3, sp | 1398 | move r3, sp |
1515 | move r4, r52 | 1399 | move r4, r52 |
@@ -1518,34 +1402,44 @@ STD_ENTRY_LOCAL(_kernel_double_fault) | |||
1518 | STD_ENDPROC(_kernel_double_fault) | 1402 | STD_ENDPROC(_kernel_double_fault) |
1519 | 1403 | ||
1520 | STD_ENTRY_LOCAL(bad_intr) | 1404 | STD_ENTRY_LOCAL(bad_intr) |
1521 | mfspr r2, EX_CONTEXT_1_0 | 1405 | mfspr r2, SPR_EX_CONTEXT_K_0 |
1522 | panic "Unhandled interrupt %#x: PC %#lx" | 1406 | panic "Unhandled interrupt %#x: PC %#lx" |
1523 | STD_ENDPROC(bad_intr) | 1407 | STD_ENDPROC(bad_intr) |
1524 | 1408 | ||
1525 | /* Put address of pt_regs in reg and jump. */ | 1409 | /* Put address of pt_regs in reg and jump. */ |
1526 | #define PTREGS_SYSCALL(x, reg) \ | 1410 | #define PTREGS_SYSCALL(x, reg) \ |
1527 | STD_ENTRY(x); \ | 1411 | STD_ENTRY(_##x); \ |
1528 | { \ | 1412 | { \ |
1529 | PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ | 1413 | PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ |
1530 | j _##x \ | 1414 | j x \ |
1531 | }; \ | 1415 | }; \ |
1532 | STD_ENDPROC(x) | 1416 | STD_ENDPROC(_##x) |
1417 | |||
1418 | /* | ||
1419 | * Special-case sigreturn to not write r0 to the stack on return. | ||
1420 | * This is technically more efficient, but it also avoids difficulties | ||
1421 | * in the 64-bit OS when handling 32-bit compat code, since we must not | ||
1422 | * sign-extend r0 for the sigreturn return-value case. | ||
1423 | */ | ||
1424 | #define PTREGS_SYSCALL_SIGRETURN(x, reg) \ | ||
1425 | STD_ENTRY(_##x); \ | ||
1426 | addli lr, lr, .Lsyscall_sigreturn_skip - .Lhandle_syscall_link; \ | ||
1427 | { \ | ||
1428 | PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ | ||
1429 | j x \ | ||
1430 | }; \ | ||
1431 | STD_ENDPROC(_##x) | ||
1533 | 1432 | ||
1534 | PTREGS_SYSCALL(sys_execve, r3) | 1433 | PTREGS_SYSCALL(sys_execve, r3) |
1535 | PTREGS_SYSCALL(sys_sigaltstack, r2) | 1434 | PTREGS_SYSCALL(sys_sigaltstack, r2) |
1536 | PTREGS_SYSCALL(sys_rt_sigreturn, r0) | 1435 | PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) |
1537 | 1436 | PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1) | |
1538 | /* Save additional callee-saves to pt_regs, put address in reg and jump. */ | ||
1539 | #define PTREGS_SYSCALL_ALL_REGS(x, reg) \ | ||
1540 | STD_ENTRY(x); \ | ||
1541 | push_extra_callee_saves reg; \ | ||
1542 | j _##x; \ | ||
1543 | STD_ENDPROC(x) | ||
1544 | 1437 | ||
1545 | PTREGS_SYSCALL_ALL_REGS(sys_fork, r0) | 1438 | /* Save additional callee-saves to pt_regs, put address in r4 and jump. */ |
1546 | PTREGS_SYSCALL_ALL_REGS(sys_vfork, r0) | 1439 | STD_ENTRY(_sys_clone) |
1547 | PTREGS_SYSCALL_ALL_REGS(sys_clone, r4) | 1440 | push_extra_callee_saves r4 |
1548 | PTREGS_SYSCALL_ALL_REGS(sys_cmpxchg_badaddr, r1) | 1441 | j sys_clone |
1442 | STD_ENDPROC(_sys_clone) | ||
1549 | 1443 | ||
1550 | /* | 1444 | /* |
1551 | * This entrypoint is taken for the cmpxchg and atomic_update fast | 1445 | * This entrypoint is taken for the cmpxchg and atomic_update fast |
@@ -1558,12 +1452,14 @@ PTREGS_SYSCALL_ALL_REGS(sys_cmpxchg_badaddr, r1) | |||
1558 | * to be available to it on entry. It does not modify any callee-save | 1452 | * to be available to it on entry. It does not modify any callee-save |
1559 | * registers (including "lr"). It does not check what PL it is being | 1453 | * registers (including "lr"). It does not check what PL it is being |
1560 | * called at, so you'd better not call it other than at PL0. | 1454 | * called at, so you'd better not call it other than at PL0. |
1455 | * The <atomic.h> wrapper assumes it only clobbers r20-r29, so if | ||
1456 | * it ever is necessary to use more registers, be aware. | ||
1561 | * | 1457 | * |
1562 | * It does not use the stack, but since it might be re-interrupted by | 1458 | * It does not use the stack, but since it might be re-interrupted by |
1563 | * a page fault which would assume the stack was valid, it does | 1459 | * a page fault which would assume the stack was valid, it does |
1564 | * save/restore the stack pointer and zero it out to make sure it gets reset. | 1460 | * save/restore the stack pointer and zero it out to make sure it gets reset. |
1565 | * Since we always keep interrupts disabled, the hypervisor won't | 1461 | * Since we always keep interrupts disabled, the hypervisor won't |
1566 | * clobber our EX_CONTEXT_1_x registers, so we don't save/restore them | 1462 | * clobber our EX_CONTEXT_K_x registers, so we don't save/restore them |
1567 | * (other than to advance the PC on return). | 1463 | * (other than to advance the PC on return). |
1568 | * | 1464 | * |
1569 | * We have to manually validate the user vs kernel address range | 1465 | * We have to manually validate the user vs kernel address range |
@@ -1574,13 +1470,19 @@ PTREGS_SYSCALL_ALL_REGS(sys_cmpxchg_badaddr, r1) | |||
1574 | * We place it in the __HEAD section to ensure it is relatively | 1470 | * We place it in the __HEAD section to ensure it is relatively |
1575 | * near to the intvec_SWINT_1 code (reachable by a conditional branch). | 1471 | * near to the intvec_SWINT_1 code (reachable by a conditional branch). |
1576 | * | 1472 | * |
1577 | * Must match register usage in do_page_fault(). | 1473 | * Our use of ATOMIC_LOCK_REG here must match do_page_fault_ics(). |
1474 | * | ||
1475 | * As we do in lib/atomic_asm_32.S, we bypass a store if the value we | ||
1476 | * would store is the same as the value we just loaded. | ||
1578 | */ | 1477 | */ |
1579 | __HEAD | 1478 | __HEAD |
1580 | .align 64 | 1479 | .align 64 |
1581 | /* Align much later jump on the start of a cache line. */ | 1480 | /* Align much later jump on the start of a cache line. */ |
1582 | #if !ATOMIC_LOCKS_FOUND_VIA_TABLE() | 1481 | #if !ATOMIC_LOCKS_FOUND_VIA_TABLE() |
1583 | nop; nop | 1482 | nop |
1483 | #if PAGE_SIZE >= 0x10000 | ||
1484 | nop | ||
1485 | #endif | ||
1584 | #endif | 1486 | #endif |
1585 | ENTRY(sys_cmpxchg) | 1487 | ENTRY(sys_cmpxchg) |
1586 | 1488 | ||
@@ -1608,9 +1510,13 @@ ENTRY(sys_cmpxchg) | |||
1608 | * about aliasing among multiple mappings of the same physical page, | 1510 | * about aliasing among multiple mappings of the same physical page, |
1609 | * and we ignore the low 3 bits so we have one lock that covers | 1511 | * and we ignore the low 3 bits so we have one lock that covers |
1610 | * both a cmpxchg64() and a cmpxchg() on either its low or high word. | 1512 | * both a cmpxchg64() and a cmpxchg() on either its low or high word. |
1611 | * NOTE: this code must match __atomic_hashed_lock() in lib/atomic.c. | 1513 | * NOTE: this must match __atomic_hashed_lock() in lib/atomic_32.c. |
1612 | */ | 1514 | */ |
1613 | 1515 | ||
1516 | #if (PAGE_OFFSET & 0xffff) != 0 | ||
1517 | # error Code here assumes PAGE_OFFSET can be loaded with just hi16() | ||
1518 | #endif | ||
1519 | |||
1614 | #if ATOMIC_LOCKS_FOUND_VIA_TABLE() | 1520 | #if ATOMIC_LOCKS_FOUND_VIA_TABLE() |
1615 | { | 1521 | { |
1616 | /* Check for unaligned input. */ | 1522 | /* Check for unaligned input. */ |
@@ -1628,17 +1534,7 @@ ENTRY(sys_cmpxchg) | |||
1628 | { | 1534 | { |
1629 | shri r20, r25, 32 - ATOMIC_HASH_L1_SHIFT | 1535 | shri r20, r25, 32 - ATOMIC_HASH_L1_SHIFT |
1630 | slt_u r23, r0, r23 | 1536 | slt_u r23, r0, r23 |
1631 | 1537 | lw r26, r0 /* see comment in the "#else" for the "lw r26". */ | |
1632 | /* | ||
1633 | * Ensure that the TLB is loaded before we take out the lock. | ||
1634 | * On TILEPro, this will start fetching the value all the way | ||
1635 | * into our L1 as well (and if it gets modified before we | ||
1636 | * grab the lock, it will be invalidated from our cache | ||
1637 | * before we reload it). On tile64, we'll start fetching it | ||
1638 | * into our L1 if we're the home, and if we're not, we'll | ||
1639 | * still at least start fetching it into the home's L2. | ||
1640 | */ | ||
1641 | lw r26, r0 | ||
1642 | } | 1538 | } |
1643 | { | 1539 | { |
1644 | s2a r21, r20, r21 | 1540 | s2a r21, r20, r21 |
@@ -1654,18 +1550,9 @@ ENTRY(sys_cmpxchg) | |||
1654 | bbs r23, .Lcmpxchg64 | 1550 | bbs r23, .Lcmpxchg64 |
1655 | andi r23, r0, 7 /* Precompute alignment for cmpxchg64. */ | 1551 | andi r23, r0, 7 /* Precompute alignment for cmpxchg64. */ |
1656 | } | 1552 | } |
1657 | |||
1658 | { | 1553 | { |
1659 | /* | ||
1660 | * We very carefully align the code that actually runs with | ||
1661 | * the lock held (nine bundles) so that we know it is all in | ||
1662 | * the icache when we start. This instruction (the jump) is | ||
1663 | * at the start of the first cache line, address zero mod 64; | ||
1664 | * we jump to somewhere in the second cache line to issue the | ||
1665 | * tns, then jump back to finish up. | ||
1666 | */ | ||
1667 | s2a ATOMIC_LOCK_REG_NAME, r25, r21 | 1554 | s2a ATOMIC_LOCK_REG_NAME, r25, r21 |
1668 | j .Lcmpxchg32_tns | 1555 | j .Lcmpxchg32_tns /* see comment in the #else for the jump. */ |
1669 | } | 1556 | } |
1670 | 1557 | ||
1671 | #else /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ | 1558 | #else /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ |
@@ -1703,11 +1590,14 @@ ENTRY(sys_cmpxchg) | |||
1703 | lw r26, r0 | 1590 | lw r26, r0 |
1704 | } | 1591 | } |
1705 | { | 1592 | { |
1706 | /* atomic_locks is page aligned so this suffices to get its addr. */ | 1593 | auli r21, zero, ha16(atomic_locks) |
1707 | auli r21, zero, hi16(atomic_locks) | ||
1708 | 1594 | ||
1709 | bbns r23, .Lcmpxchg_badaddr | 1595 | bbns r23, .Lcmpxchg_badaddr |
1710 | } | 1596 | } |
1597 | #if PAGE_SIZE < 0x10000 | ||
1598 | /* atomic_locks is page-aligned so for big pages we don't need this. */ | ||
1599 | addli r21, r21, lo16(atomic_locks) | ||
1600 | #endif | ||
1711 | { | 1601 | { |
1712 | /* | 1602 | /* |
1713 | * Insert the hash bits into the page-aligned pointer. | 1603 | * Insert the hash bits into the page-aligned pointer. |
@@ -1727,24 +1617,25 @@ ENTRY(sys_cmpxchg) | |||
1727 | { | 1617 | { |
1728 | /* | 1618 | /* |
1729 | * We very carefully align the code that actually runs with | 1619 | * We very carefully align the code that actually runs with |
1730 | * the lock held (nine bundles) so that we know it is all in | 1620 | * the lock held (twelve bundles) so that we know it is all in |
1731 | * the icache when we start. This instruction (the jump) is | 1621 | * the icache when we start. This instruction (the jump) is |
1732 | * at the start of the first cache line, address zero mod 64; | 1622 | * at the start of the first cache line, address zero mod 64; |
1733 | * we jump to somewhere in the second cache line to issue the | 1623 | * we jump to the very end of the second cache line to get that |
1734 | * tns, then jump back to finish up. | 1624 | * line loaded in the icache, then fall through to issue the tns |
1625 | * in the third cache line, at which point it's all cached. | ||
1626 | * Note that is for performance, not correctness. | ||
1735 | */ | 1627 | */ |
1736 | j .Lcmpxchg32_tns | 1628 | j .Lcmpxchg32_tns |
1737 | } | 1629 | } |
1738 | 1630 | ||
1739 | #endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ | 1631 | #endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */ |
1740 | 1632 | ||
1741 | ENTRY(__sys_cmpxchg_grab_lock) | 1633 | /* Symbol for do_page_fault_ics() to use to compare against the PC. */ |
1634 | .global __sys_cmpxchg_grab_lock | ||
1635 | __sys_cmpxchg_grab_lock: | ||
1742 | 1636 | ||
1743 | /* | 1637 | /* |
1744 | * Perform the actual cmpxchg or atomic_update. | 1638 | * Perform the actual cmpxchg or atomic_update. |
1745 | * Note that __futex_mark_unlocked() in uClibc relies on | ||
1746 | * atomic_update() to always perform an "mf", so don't make | ||
1747 | * it optional or conditional without modifying that code. | ||
1748 | */ | 1639 | */ |
1749 | .Ldo_cmpxchg32: | 1640 | .Ldo_cmpxchg32: |
1750 | { | 1641 | { |
@@ -1762,18 +1653,20 @@ ENTRY(sys_cmpxchg) | |||
1762 | } | 1653 | } |
1763 | { | 1654 | { |
1764 | mvnz r24, r23, r25 /* Use atomic_update value if appropriate. */ | 1655 | mvnz r24, r23, r25 /* Use atomic_update value if appropriate. */ |
1765 | bbns r22, .Lcmpxchg32_mismatch | 1656 | bbns r22, .Lcmpxchg32_nostore |
1766 | } | 1657 | } |
1658 | seq r22, r24, r21 /* Are we storing the value we loaded? */ | ||
1659 | bbs r22, .Lcmpxchg32_nostore | ||
1767 | sw r0, r24 | 1660 | sw r0, r24 |
1768 | 1661 | ||
1662 | /* The following instruction is the start of the second cache line. */ | ||
1769 | /* Do slow mtspr here so the following "mf" waits less. */ | 1663 | /* Do slow mtspr here so the following "mf" waits less. */ |
1770 | { | 1664 | { |
1771 | move sp, r27 | 1665 | move sp, r27 |
1772 | mtspr EX_CONTEXT_1_0, r28 | 1666 | mtspr SPR_EX_CONTEXT_K_0, r28 |
1773 | } | 1667 | } |
1774 | mf | 1668 | mf |
1775 | 1669 | ||
1776 | /* The following instruction is the start of the second cache line. */ | ||
1777 | { | 1670 | { |
1778 | move r0, r21 | 1671 | move r0, r21 |
1779 | sw ATOMIC_LOCK_REG_NAME, zero | 1672 | sw ATOMIC_LOCK_REG_NAME, zero |
@@ -1781,14 +1674,14 @@ ENTRY(sys_cmpxchg) | |||
1781 | iret | 1674 | iret |
1782 | 1675 | ||
1783 | /* Duplicated code here in the case where we don't overlap "mf" */ | 1676 | /* Duplicated code here in the case where we don't overlap "mf" */ |
1784 | .Lcmpxchg32_mismatch: | 1677 | .Lcmpxchg32_nostore: |
1785 | { | 1678 | { |
1786 | move r0, r21 | 1679 | move r0, r21 |
1787 | sw ATOMIC_LOCK_REG_NAME, zero | 1680 | sw ATOMIC_LOCK_REG_NAME, zero |
1788 | } | 1681 | } |
1789 | { | 1682 | { |
1790 | move sp, r27 | 1683 | move sp, r27 |
1791 | mtspr EX_CONTEXT_1_0, r28 | 1684 | mtspr SPR_EX_CONTEXT_K_0, r28 |
1792 | } | 1685 | } |
1793 | iret | 1686 | iret |
1794 | 1687 | ||
@@ -1797,8 +1690,6 @@ ENTRY(sys_cmpxchg) | |||
1797 | * and for 64-bit cmpxchg. We provide it as a macro and put | 1690 | * and for 64-bit cmpxchg. We provide it as a macro and put |
1798 | * it into both versions. We can't share the code literally | 1691 | * it into both versions. We can't share the code literally |
1799 | * since it depends on having the right branch-back address. | 1692 | * since it depends on having the right branch-back address. |
1800 | * Note that the first few instructions should share the cache | ||
1801 | * line with the second half of the actual locked code. | ||
1802 | */ | 1693 | */ |
1803 | .macro cmpxchg_lock, bitwidth | 1694 | .macro cmpxchg_lock, bitwidth |
1804 | 1695 | ||
@@ -1816,7 +1707,7 @@ ENTRY(sys_cmpxchg) | |||
1816 | #endif | 1707 | #endif |
1817 | 1708 | ||
1818 | /* Issue the slow SPR here while the tns result is in flight. */ | 1709 | /* Issue the slow SPR here while the tns result is in flight. */ |
1819 | mfspr r28, EX_CONTEXT_1_0 | 1710 | mfspr r28, SPR_EX_CONTEXT_K_0 |
1820 | 1711 | ||
1821 | { | 1712 | { |
1822 | addi r28, r28, 8 /* return to the instruction after the swint1 */ | 1713 | addi r28, r28, 8 /* return to the instruction after the swint1 */ |
@@ -1824,7 +1715,7 @@ ENTRY(sys_cmpxchg) | |||
1824 | } | 1715 | } |
1825 | /* | 1716 | /* |
1826 | * The preceding instruction is the last thing that must be | 1717 | * The preceding instruction is the last thing that must be |
1827 | * on the second cache line. | 1718 | * hot in the icache before we do the "tns" above. |
1828 | */ | 1719 | */ |
1829 | 1720 | ||
1830 | #ifdef CONFIG_SMP | 1721 | #ifdef CONFIG_SMP |
@@ -1855,6 +1746,12 @@ ENTRY(sys_cmpxchg) | |||
1855 | .endm | 1746 | .endm |
1856 | 1747 | ||
1857 | .Lcmpxchg32_tns: | 1748 | .Lcmpxchg32_tns: |
1749 | /* | ||
1750 | * This is the last instruction on the second cache line. | ||
1751 | * The nop here loads the second line, then we fall through | ||
1752 | * to the tns to load the third line before we take the lock. | ||
1753 | */ | ||
1754 | nop | ||
1858 | cmpxchg_lock 32 | 1755 | cmpxchg_lock 32 |
1859 | 1756 | ||
1860 | /* | 1757 | /* |
@@ -1904,7 +1801,7 @@ ENTRY(sys_cmpxchg) | |||
1904 | .Lcmpxchg64_mismatch: | 1801 | .Lcmpxchg64_mismatch: |
1905 | { | 1802 | { |
1906 | move sp, r27 | 1803 | move sp, r27 |
1907 | mtspr EX_CONTEXT_1_0, r28 | 1804 | mtspr SPR_EX_CONTEXT_K_0, r28 |
1908 | } | 1805 | } |
1909 | mf | 1806 | mf |
1910 | { | 1807 | { |
@@ -1985,21 +1882,26 @@ int_unalign: | |||
1985 | int_hand INT_PERF_COUNT, PERF_COUNT, \ | 1882 | int_hand INT_PERF_COUNT, PERF_COUNT, \ |
1986 | op_handle_perf_interrupt, handle_nmi | 1883 | op_handle_perf_interrupt, handle_nmi |
1987 | int_hand INT_INTCTRL_3, INTCTRL_3, bad_intr | 1884 | int_hand INT_INTCTRL_3, INTCTRL_3, bad_intr |
1885 | #if CONFIG_KERNEL_PL == 2 | ||
1886 | dc_dispatch INT_INTCTRL_2, INTCTRL_2 | ||
1887 | int_hand INT_INTCTRL_1, INTCTRL_1, bad_intr | ||
1888 | #else | ||
1988 | int_hand INT_INTCTRL_2, INTCTRL_2, bad_intr | 1889 | int_hand INT_INTCTRL_2, INTCTRL_2, bad_intr |
1989 | dc_dispatch INT_INTCTRL_1, INTCTRL_1 | 1890 | dc_dispatch INT_INTCTRL_1, INTCTRL_1 |
1891 | #endif | ||
1990 | int_hand INT_INTCTRL_0, INTCTRL_0, bad_intr | 1892 | int_hand INT_INTCTRL_0, INTCTRL_0, bad_intr |
1991 | int_hand INT_MESSAGE_RCV_DWNCL, MESSAGE_RCV_DWNCL, \ | 1893 | int_hand INT_MESSAGE_RCV_DWNCL, MESSAGE_RCV_DWNCL, \ |
1992 | hv_message_intr, handle_interrupt_downcall | 1894 | hv_message_intr |
1993 | int_hand INT_DEV_INTR_DWNCL, DEV_INTR_DWNCL, \ | 1895 | int_hand INT_DEV_INTR_DWNCL, DEV_INTR_DWNCL, \ |
1994 | tile_dev_intr, handle_interrupt_downcall | 1896 | tile_dev_intr |
1995 | int_hand INT_I_ASID, I_ASID, bad_intr | 1897 | int_hand INT_I_ASID, I_ASID, bad_intr |
1996 | int_hand INT_D_ASID, D_ASID, bad_intr | 1898 | int_hand INT_D_ASID, D_ASID, bad_intr |
1997 | int_hand INT_DMATLB_MISS_DWNCL, DMATLB_MISS_DWNCL, \ | 1899 | int_hand INT_DMATLB_MISS_DWNCL, DMATLB_MISS_DWNCL, \ |
1998 | do_page_fault, handle_interrupt_downcall | 1900 | do_page_fault |
1999 | int_hand INT_SNITLB_MISS_DWNCL, SNITLB_MISS_DWNCL, \ | 1901 | int_hand INT_SNITLB_MISS_DWNCL, SNITLB_MISS_DWNCL, \ |
2000 | do_page_fault, handle_interrupt_downcall | 1902 | do_page_fault |
2001 | int_hand INT_DMATLB_ACCESS_DWNCL, DMATLB_ACCESS_DWNCL, \ | 1903 | int_hand INT_DMATLB_ACCESS_DWNCL, DMATLB_ACCESS_DWNCL, \ |
2002 | do_page_fault, handle_interrupt_downcall | 1904 | do_page_fault |
2003 | int_hand INT_SN_CPL, SN_CPL, bad_intr | 1905 | int_hand INT_SN_CPL, SN_CPL, bad_intr |
2004 | int_hand INT_DOUBLE_FAULT, DOUBLE_FAULT, do_trap | 1906 | int_hand INT_DOUBLE_FAULT, DOUBLE_FAULT, do_trap |
2005 | #if CHIP_HAS_AUX_PERF_COUNTERS() | 1907 | #if CHIP_HAS_AUX_PERF_COUNTERS() |
diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S new file mode 100644 index 000000000000..79c93e10ba27 --- /dev/null +++ b/arch/tile/kernel/intvec_64.S | |||
@@ -0,0 +1,1231 @@ | |||
1 | /* | ||
2 | * Copyright 2011 Tilera Corporation. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation, version 2. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
11 | * NON INFRINGEMENT. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * Linux interrupt vectors. | ||
15 | */ | ||
16 | |||
17 | #include <linux/linkage.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/unistd.h> | ||
20 | #include <asm/ptrace.h> | ||
21 | #include <asm/thread_info.h> | ||
22 | #include <asm/irqflags.h> | ||
23 | #include <asm/asm-offsets.h> | ||
24 | #include <asm/types.h> | ||
25 | #include <hv/hypervisor.h> | ||
26 | #include <arch/abi.h> | ||
27 | #include <arch/interrupts.h> | ||
28 | #include <arch/spr_def.h> | ||
29 | |||
30 | #ifdef CONFIG_PREEMPT | ||
31 | # error "No support for kernel preemption currently" | ||
32 | #endif | ||
33 | |||
34 | #define PTREGS_PTR(reg, ptreg) addli reg, sp, C_ABI_SAVE_AREA_SIZE + (ptreg) | ||
35 | |||
36 | #define PTREGS_OFFSET_SYSCALL PTREGS_OFFSET_REG(TREG_SYSCALL_NR) | ||
37 | |||
38 | |||
39 | .macro push_reg reg, ptr=sp, delta=-8 | ||
40 | { | ||
41 | st \ptr, \reg | ||
42 | addli \ptr, \ptr, \delta | ||
43 | } | ||
44 | .endm | ||
45 | |||
46 | .macro pop_reg reg, ptr=sp, delta=8 | ||
47 | { | ||
48 | ld \reg, \ptr | ||
49 | addli \ptr, \ptr, \delta | ||
50 | } | ||
51 | .endm | ||
52 | |||
53 | .macro pop_reg_zero reg, zreg, ptr=sp, delta=8 | ||
54 | { | ||
55 | move \zreg, zero | ||
56 | ld \reg, \ptr | ||
57 | addi \ptr, \ptr, \delta | ||
58 | } | ||
59 | .endm | ||
60 | |||
61 | .macro push_extra_callee_saves reg | ||
62 | PTREGS_PTR(\reg, PTREGS_OFFSET_REG(51)) | ||
63 | push_reg r51, \reg | ||
64 | push_reg r50, \reg | ||
65 | push_reg r49, \reg | ||
66 | push_reg r48, \reg | ||
67 | push_reg r47, \reg | ||
68 | push_reg r46, \reg | ||
69 | push_reg r45, \reg | ||
70 | push_reg r44, \reg | ||
71 | push_reg r43, \reg | ||
72 | push_reg r42, \reg | ||
73 | push_reg r41, \reg | ||
74 | push_reg r40, \reg | ||
75 | push_reg r39, \reg | ||
76 | push_reg r38, \reg | ||
77 | push_reg r37, \reg | ||
78 | push_reg r36, \reg | ||
79 | push_reg r35, \reg | ||
80 | push_reg r34, \reg, PTREGS_OFFSET_BASE - PTREGS_OFFSET_REG(34) | ||
81 | .endm | ||
82 | |||
83 | .macro panic str | ||
84 | .pushsection .rodata, "a" | ||
85 | 1: | ||
86 | .asciz "\str" | ||
87 | .popsection | ||
88 | { | ||
89 | moveli r0, hw2_last(1b) | ||
90 | } | ||
91 | { | ||
92 | shl16insli r0, r0, hw1(1b) | ||
93 | } | ||
94 | { | ||
95 | shl16insli r0, r0, hw0(1b) | ||
96 | jal panic | ||
97 | } | ||
98 | .endm | ||
99 | |||
100 | |||
101 | #ifdef __COLLECT_LINKER_FEEDBACK__ | ||
102 | .pushsection .text.intvec_feedback,"ax" | ||
103 | intvec_feedback: | ||
104 | .popsection | ||
105 | #endif | ||
106 | |||
107 | /* | ||
108 | * Default interrupt handler. | ||
109 | * | ||
110 | * vecnum is where we'll put this code. | ||
111 | * c_routine is the C routine we'll call. | ||
112 | * | ||
113 | * The C routine is passed two arguments: | ||
114 | * - A pointer to the pt_regs state. | ||
115 | * - The interrupt vector number. | ||
116 | * | ||
117 | * The "processing" argument specifies the code for processing | ||
118 | * the interrupt. Defaults to "handle_interrupt". | ||
119 | */ | ||
120 | .macro int_hand vecnum, vecname, c_routine, processing=handle_interrupt | ||
121 | .org (\vecnum << 8) | ||
122 | intvec_\vecname: | ||
123 | /* Temporarily save a register so we have somewhere to work. */ | ||
124 | |||
125 | mtspr SPR_SYSTEM_SAVE_K_1, r0 | ||
126 | mfspr r0, SPR_EX_CONTEXT_K_1 | ||
127 | |||
128 | andi r0, r0, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ | ||
129 | |||
130 | .ifc \vecnum, INT_DOUBLE_FAULT | ||
131 | /* | ||
132 | * For double-faults from user-space, fall through to the normal | ||
133 | * register save and stack setup path. Otherwise, it's the | ||
134 | * hypervisor giving us one last chance to dump diagnostics, and we | ||
135 | * branch to the kernel_double_fault routine to do so. | ||
136 | */ | ||
137 | beqz r0, 1f | ||
138 | j _kernel_double_fault | ||
139 | 1: | ||
140 | .else | ||
141 | /* | ||
142 | * If we're coming from user-space, then set sp to the top of | ||
143 | * the kernel stack. Otherwise, assume sp is already valid. | ||
144 | */ | ||
145 | { | ||
146 | bnez r0, 0f | ||
147 | move r0, sp | ||
148 | } | ||
149 | .endif | ||
150 | |||
151 | .ifc \c_routine, do_page_fault | ||
152 | /* | ||
153 | * The page_fault handler may be downcalled directly by the | ||
154 | * hypervisor even when Linux is running and has ICS set. | ||
155 | * | ||
156 | * In this case the contents of EX_CONTEXT_K_1 reflect the | ||
157 | * previous fault and can't be relied on to choose whether or | ||
158 | * not to reinitialize the stack pointer. So we add a test | ||
159 | * to see whether SYSTEM_SAVE_K_2 has the high bit set, | ||
160 | * and if so we don't reinitialize sp, since we must be coming | ||
161 | * from Linux. (In fact the precise case is !(val & ~1), | ||
162 | * but any Linux PC has to have the high bit set.) | ||
163 | * | ||
164 | * Note that the hypervisor *always* sets SYSTEM_SAVE_K_2 for | ||
165 | * any path that turns into a downcall to one of our TLB handlers. | ||
166 | * | ||
167 | * FIXME: if we end up never using this path, perhaps we should | ||
168 | * prevent the hypervisor from generating downcalls in this case. | ||
169 | * The advantage of getting a downcall is we can panic in Linux. | ||
170 | */ | ||
171 | mfspr r0, SPR_SYSTEM_SAVE_K_2 | ||
172 | { | ||
173 | bltz r0, 0f /* high bit in S_S_1_2 is for a PC to use */ | ||
174 | move r0, sp | ||
175 | } | ||
176 | .endif | ||
177 | |||
178 | |||
179 | /* | ||
180 | * SYSTEM_SAVE_K_0 holds the cpu number in the low bits, and | ||
181 | * the current stack top in the higher bits. So we recover | ||
182 | * our stack top by just masking off the low bits, then | ||
183 | * point sp at the top aligned address on the actual stack page. | ||
184 | */ | ||
185 | mfspr r0, SPR_SYSTEM_SAVE_K_0 | ||
186 | mm r0, zero, LOG2_THREAD_SIZE, 63 | ||
187 | |||
188 | 0: | ||
189 | /* | ||
190 | * Align the stack mod 64 so we can properly predict what | ||
191 | * cache lines we need to write-hint to reduce memory fetch | ||
192 | * latency as we enter the kernel. The layout of memory is | ||
193 | * as follows, with cache line 0 at the lowest VA, and cache | ||
194 | * line 8 just below the r0 value this "andi" computes. | ||
195 | * Note that we never write to cache line 8, and we skip | ||
196 | * cache lines 1-3 for syscalls. | ||
197 | * | ||
198 | * cache line 8: ptregs padding (two words) | ||
199 | * cache line 7: sp, lr, pc, ex1, faultnum, orig_r0, flags, cmpexch | ||
200 | * cache line 6: r46...r53 (tp) | ||
201 | * cache line 5: r38...r45 | ||
202 | * cache line 4: r30...r37 | ||
203 | * cache line 3: r22...r29 | ||
204 | * cache line 2: r14...r21 | ||
205 | * cache line 1: r6...r13 | ||
206 | * cache line 0: 2 x frame, r0..r5 | ||
207 | */ | ||
208 | andi r0, r0, -64 | ||
209 | |||
210 | /* | ||
211 | * Push the first four registers on the stack, so that we can set | ||
212 | * them to vector-unique values before we jump to the common code. | ||
213 | * | ||
214 | * Registers are pushed on the stack as a struct pt_regs, | ||
215 | * with the sp initially just above the struct, and when we're | ||
216 | * done, sp points to the base of the struct, minus | ||
217 | * C_ABI_SAVE_AREA_SIZE, so we can directly jal to C code. | ||
218 | * | ||
219 | * This routine saves just the first four registers, plus the | ||
220 | * stack context so we can do proper backtracing right away, | ||
221 | * and defers to handle_interrupt to save the rest. | ||
222 | * The backtracer needs pc, ex1, lr, sp, r52, and faultnum. | ||
223 | */ | ||
224 | addli r0, r0, PTREGS_OFFSET_LR - (PTREGS_SIZE + KSTK_PTREGS_GAP) | ||
225 | wh64 r0 /* cache line 7 */ | ||
226 | { | ||
227 | st r0, lr | ||
228 | addli r0, r0, PTREGS_OFFSET_SP - PTREGS_OFFSET_LR | ||
229 | } | ||
230 | { | ||
231 | st r0, sp | ||
232 | addli sp, r0, PTREGS_OFFSET_REG(52) - PTREGS_OFFSET_SP | ||
233 | } | ||
234 | wh64 sp /* cache line 6 */ | ||
235 | { | ||
236 | st sp, r52 | ||
237 | addli sp, sp, PTREGS_OFFSET_REG(1) - PTREGS_OFFSET_REG(52) | ||
238 | } | ||
239 | wh64 sp /* cache line 0 */ | ||
240 | { | ||
241 | st sp, r1 | ||
242 | addli sp, sp, PTREGS_OFFSET_REG(2) - PTREGS_OFFSET_REG(1) | ||
243 | } | ||
244 | { | ||
245 | st sp, r2 | ||
246 | addli sp, sp, PTREGS_OFFSET_REG(3) - PTREGS_OFFSET_REG(2) | ||
247 | } | ||
248 | { | ||
249 | st sp, r3 | ||
250 | addli sp, sp, PTREGS_OFFSET_PC - PTREGS_OFFSET_REG(3) | ||
251 | } | ||
252 | mfspr r0, SPR_EX_CONTEXT_K_0 | ||
253 | .ifc \processing,handle_syscall | ||
254 | /* | ||
255 | * Bump the saved PC by one bundle so that when we return, we won't | ||
256 | * execute the same swint instruction again. We need to do this while | ||
257 | * we're in the critical section. | ||
258 | */ | ||
259 | addi r0, r0, 8 | ||
260 | .endif | ||
261 | { | ||
262 | st sp, r0 | ||
263 | addli sp, sp, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_PC | ||
264 | } | ||
265 | mfspr r0, SPR_EX_CONTEXT_K_1 | ||
266 | { | ||
267 | st sp, r0 | ||
268 | addi sp, sp, PTREGS_OFFSET_FAULTNUM - PTREGS_OFFSET_EX1 | ||
269 | /* | ||
270 | * Use r0 for syscalls so it's a temporary; use r1 for interrupts | ||
271 | * so that it gets passed through unchanged to the handler routine. | ||
272 | * Note that the .if conditional confusingly spans bundles. | ||
273 | */ | ||
274 | .ifc \processing,handle_syscall | ||
275 | movei r0, \vecnum | ||
276 | } | ||
277 | { | ||
278 | st sp, r0 | ||
279 | .else | ||
280 | movei r1, \vecnum | ||
281 | } | ||
282 | { | ||
283 | st sp, r1 | ||
284 | .endif | ||
285 | addli sp, sp, PTREGS_OFFSET_REG(0) - PTREGS_OFFSET_FAULTNUM | ||
286 | } | ||
287 | mfspr r0, SPR_SYSTEM_SAVE_K_1 /* Original r0 */ | ||
288 | { | ||
289 | st sp, r0 | ||
290 | addi sp, sp, -PTREGS_OFFSET_REG(0) - 8 | ||
291 | } | ||
292 | { | ||
293 | st sp, zero /* write zero into "Next SP" frame pointer */ | ||
294 | addi sp, sp, -8 /* leave SP pointing at bottom of frame */ | ||
295 | } | ||
296 | .ifc \processing,handle_syscall | ||
297 | j handle_syscall | ||
298 | .else | ||
299 | /* Capture per-interrupt SPR context to registers. */ | ||
300 | .ifc \c_routine, do_page_fault | ||
301 | mfspr r2, SPR_SYSTEM_SAVE_K_3 /* address of page fault */ | ||
302 | mfspr r3, SPR_SYSTEM_SAVE_K_2 /* info about page fault */ | ||
303 | .else | ||
304 | .ifc \vecnum, INT_ILL_TRANS | ||
305 | mfspr r2, ILL_TRANS_REASON | ||
306 | .else | ||
307 | .ifc \vecnum, INT_DOUBLE_FAULT | ||
308 | mfspr r2, SPR_SYSTEM_SAVE_K_2 /* double fault info from HV */ | ||
309 | .else | ||
310 | .ifc \c_routine, do_trap | ||
311 | mfspr r2, GPV_REASON | ||
312 | .else | ||
313 | .ifc \c_routine, op_handle_perf_interrupt | ||
314 | mfspr r2, PERF_COUNT_STS | ||
315 | #if CHIP_HAS_AUX_PERF_COUNTERS() | ||
316 | .else | ||
317 | .ifc \c_routine, op_handle_aux_perf_interrupt | ||
318 | mfspr r2, AUX_PERF_COUNT_STS | ||
319 | .endif | ||
320 | #endif | ||
321 | .endif | ||
322 | .endif | ||
323 | .endif | ||
324 | .endif | ||
325 | .endif | ||
326 | /* Put function pointer in r0 */ | ||
327 | moveli r0, hw2_last(\c_routine) | ||
328 | shl16insli r0, r0, hw1(\c_routine) | ||
329 | { | ||
330 | shl16insli r0, r0, hw0(\c_routine) | ||
331 | j \processing | ||
332 | } | ||
333 | .endif | ||
334 | ENDPROC(intvec_\vecname) | ||
335 | |||
336 | #ifdef __COLLECT_LINKER_FEEDBACK__ | ||
337 | .pushsection .text.intvec_feedback,"ax" | ||
338 | .org (\vecnum << 5) | ||
339 | FEEDBACK_ENTER_EXPLICIT(intvec_\vecname, .intrpt1, 1 << 8) | ||
340 | jrp lr | ||
341 | .popsection | ||
342 | #endif | ||
343 | |||
344 | .endm | ||
345 | |||
346 | |||
347 | /* | ||
348 | * Save the rest of the registers that we didn't save in the actual | ||
349 | * vector itself. We can't use r0-r10 inclusive here. | ||
350 | */ | ||
351 | .macro finish_interrupt_save, function | ||
352 | |||
353 | /* If it's a syscall, save a proper orig_r0, otherwise just zero. */ | ||
354 | PTREGS_PTR(r52, PTREGS_OFFSET_ORIG_R0) | ||
355 | { | ||
356 | .ifc \function,handle_syscall | ||
357 | st r52, r0 | ||
358 | .else | ||
359 | st r52, zero | ||
360 | .endif | ||
361 | PTREGS_PTR(r52, PTREGS_OFFSET_TP) | ||
362 | } | ||
363 | st r52, tp | ||
364 | { | ||
365 | mfspr tp, CMPEXCH_VALUE | ||
366 | PTREGS_PTR(r52, PTREGS_OFFSET_CMPEXCH) | ||
367 | } | ||
368 | |||
369 | /* | ||
370 | * For ordinary syscalls, we save neither caller- nor callee- | ||
371 | * save registers, since the syscall invoker doesn't expect the | ||
372 | * caller-saves to be saved, and the called kernel functions will | ||
373 | * take care of saving the callee-saves for us. | ||
374 | * | ||
375 | * For interrupts we save just the caller-save registers. Saving | ||
376 | * them is required (since the "caller" can't save them). Again, | ||
377 | * the called kernel functions will restore the callee-save | ||
378 | * registers for us appropriately. | ||
379 | * | ||
380 | * On return, we normally restore nothing special for syscalls, | ||
381 | * and just the caller-save registers for interrupts. | ||
382 | * | ||
383 | * However, there are some important caveats to all this: | ||
384 | * | ||
385 | * - We always save a few callee-save registers to give us | ||
386 | * some scratchpad registers to carry across function calls. | ||
387 | * | ||
388 | * - fork/vfork/etc require us to save all the callee-save | ||
389 | * registers, which we do in PTREGS_SYSCALL_ALL_REGS, below. | ||
390 | * | ||
391 | * - We always save r0..r5 and r10 for syscalls, since we need | ||
392 | * to reload them a bit later for the actual kernel call, and | ||
393 | * since we might need them for -ERESTARTNOINTR, etc. | ||
394 | * | ||
395 | * - Before invoking a signal handler, we save the unsaved | ||
396 | * callee-save registers so they are visible to the | ||
397 | * signal handler or any ptracer. | ||
398 | * | ||
399 | * - If the unsaved callee-save registers are modified, we set | ||
400 | * a bit in pt_regs so we know to reload them from pt_regs | ||
401 | * and not just rely on the kernel function unwinding. | ||
402 | * (Done for ptrace register writes and SA_SIGINFO handler.) | ||
403 | */ | ||
404 | { | ||
405 | st r52, tp | ||
406 | PTREGS_PTR(r52, PTREGS_OFFSET_REG(33)) | ||
407 | } | ||
408 | wh64 r52 /* cache line 4 */ | ||
409 | push_reg r33, r52 | ||
410 | push_reg r32, r52 | ||
411 | push_reg r31, r52 | ||
412 | .ifc \function,handle_syscall | ||
413 | push_reg r30, r52, PTREGS_OFFSET_SYSCALL - PTREGS_OFFSET_REG(30) | ||
414 | push_reg TREG_SYSCALL_NR_NAME, r52, \ | ||
415 | PTREGS_OFFSET_REG(5) - PTREGS_OFFSET_SYSCALL | ||
416 | .else | ||
417 | |||
418 | push_reg r30, r52, PTREGS_OFFSET_REG(29) - PTREGS_OFFSET_REG(30) | ||
419 | wh64 r52 /* cache line 3 */ | ||
420 | push_reg r29, r52 | ||
421 | push_reg r28, r52 | ||
422 | push_reg r27, r52 | ||
423 | push_reg r26, r52 | ||
424 | push_reg r25, r52 | ||
425 | push_reg r24, r52 | ||
426 | push_reg r23, r52 | ||
427 | push_reg r22, r52 | ||
428 | wh64 r52 /* cache line 2 */ | ||
429 | push_reg r21, r52 | ||
430 | push_reg r20, r52 | ||
431 | push_reg r19, r52 | ||
432 | push_reg r18, r52 | ||
433 | push_reg r17, r52 | ||
434 | push_reg r16, r52 | ||
435 | push_reg r15, r52 | ||
436 | push_reg r14, r52 | ||
437 | wh64 r52 /* cache line 1 */ | ||
438 | push_reg r13, r52 | ||
439 | push_reg r12, r52 | ||
440 | push_reg r11, r52 | ||
441 | push_reg r10, r52 | ||
442 | push_reg r9, r52 | ||
443 | push_reg r8, r52 | ||
444 | push_reg r7, r52 | ||
445 | push_reg r6, r52 | ||
446 | |||
447 | .endif | ||
448 | |||
449 | push_reg r5, r52 | ||
450 | st r52, r4 | ||
451 | |||
452 | /* Load tp with our per-cpu offset. */ | ||
453 | #ifdef CONFIG_SMP | ||
454 | { | ||
455 | mfspr r20, SPR_SYSTEM_SAVE_K_0 | ||
456 | moveli r21, hw2_last(__per_cpu_offset) | ||
457 | } | ||
458 | { | ||
459 | shl16insli r21, r21, hw1(__per_cpu_offset) | ||
460 | bfextu r20, r20, 0, LOG2_THREAD_SIZE-1 | ||
461 | } | ||
462 | shl16insli r21, r21, hw0(__per_cpu_offset) | ||
463 | shl3add r20, r20, r21 | ||
464 | ld tp, r20 | ||
465 | #else | ||
466 | move tp, zero | ||
467 | #endif | ||
468 | |||
469 | /* | ||
470 | * If we will be returning to the kernel, we will need to | ||
471 | * reset the interrupt masks to the state they had before. | ||
472 | * Set DISABLE_IRQ in flags iff we came from PL1 with irqs disabled. | ||
473 | */ | ||
474 | mfspr r32, SPR_EX_CONTEXT_K_1 | ||
475 | { | ||
476 | andi r32, r32, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ | ||
477 | PTREGS_PTR(r21, PTREGS_OFFSET_FLAGS) | ||
478 | } | ||
479 | beqzt r32, 1f /* zero if from user space */ | ||
480 | IRQS_DISABLED(r32) /* zero if irqs enabled */ | ||
481 | #if PT_FLAGS_DISABLE_IRQ != 1 | ||
482 | # error Value of IRQS_DISABLED used to set PT_FLAGS_DISABLE_IRQ; fix | ||
483 | #endif | ||
484 | 1: | ||
485 | .ifnc \function,handle_syscall | ||
486 | /* Record the fact that we saved the caller-save registers above. */ | ||
487 | ori r32, r32, PT_FLAGS_CALLER_SAVES | ||
488 | .endif | ||
489 | st r21, r32 | ||
490 | |||
491 | #ifdef __COLLECT_LINKER_FEEDBACK__ | ||
492 | /* | ||
493 | * Notify the feedback routines that we were in the | ||
494 | * appropriate fixed interrupt vector area. Note that we | ||
495 | * still have ICS set at this point, so we can't invoke any | ||
496 | * atomic operations or we will panic. The feedback | ||
497 | * routines internally preserve r0..r10 and r30 up. | ||
498 | */ | ||
499 | .ifnc \function,handle_syscall | ||
500 | shli r20, r1, 5 | ||
501 | .else | ||
502 | moveli r20, INT_SWINT_1 << 5 | ||
503 | .endif | ||
504 | moveli r21, hw2_last(intvec_feedback) | ||
505 | shl16insli r21, r21, hw1(intvec_feedback) | ||
506 | shl16insli r21, r21, hw0(intvec_feedback) | ||
507 | add r20, r20, r21 | ||
508 | jalr r20 | ||
509 | |||
510 | /* And now notify the feedback routines that we are here. */ | ||
511 | FEEDBACK_ENTER(\function) | ||
512 | #endif | ||
513 | |||
514 | /* | ||
515 | * we've captured enough state to the stack (including in | ||
516 | * particular our EX_CONTEXT state) that we can now release | ||
517 | * the interrupt critical section and replace it with our | ||
518 | * standard "interrupts disabled" mask value. This allows | ||
519 | * synchronous interrupts (and profile interrupts) to punch | ||
520 | * through from this point onwards. | ||
521 | */ | ||
522 | .ifc \function,handle_nmi | ||
523 | IRQ_DISABLE_ALL(r20) | ||
524 | .else | ||
525 | IRQ_DISABLE(r20, r21) | ||
526 | .endif | ||
527 | mtspr INTERRUPT_CRITICAL_SECTION, zero | ||
528 | |||
529 | /* | ||
530 | * Prepare the first 256 stack bytes to be rapidly accessible | ||
531 | * without having to fetch the background data. | ||
532 | */ | ||
533 | addi r52, sp, -64 | ||
534 | { | ||
535 | wh64 r52 | ||
536 | addi r52, r52, -64 | ||
537 | } | ||
538 | { | ||
539 | wh64 r52 | ||
540 | addi r52, r52, -64 | ||
541 | } | ||
542 | { | ||
543 | wh64 r52 | ||
544 | addi r52, r52, -64 | ||
545 | } | ||
546 | wh64 r52 | ||
547 | |||
548 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
549 | .ifnc \function,handle_nmi | ||
550 | /* | ||
551 | * We finally have enough state set up to notify the irq | ||
552 | * tracing code that irqs were disabled on entry to the handler. | ||
553 | * The TRACE_IRQS_OFF call clobbers registers r0-r29. | ||
554 | * For syscalls, we already have the register state saved away | ||
555 | * on the stack, so we don't bother to do any register saves here, | ||
556 | * and later we pop the registers back off the kernel stack. | ||
557 | * For interrupt handlers, save r0-r3 in callee-saved registers. | ||
558 | */ | ||
559 | .ifnc \function,handle_syscall | ||
560 | { move r30, r0; move r31, r1 } | ||
561 | { move r32, r2; move r33, r3 } | ||
562 | .endif | ||
563 | TRACE_IRQS_OFF | ||
564 | .ifnc \function,handle_syscall | ||
565 | { move r0, r30; move r1, r31 } | ||
566 | { move r2, r32; move r3, r33 } | ||
567 | .endif | ||
568 | .endif | ||
569 | #endif | ||
570 | |||
571 | .endm | ||
572 | |||
573 | /* | ||
574 | * Redispatch a downcall. | ||
575 | */ | ||
576 | .macro dc_dispatch vecnum, vecname | ||
577 | .org (\vecnum << 8) | ||
578 | intvec_\vecname: | ||
579 | j hv_downcall_dispatch | ||
580 | ENDPROC(intvec_\vecname) | ||
581 | .endm | ||
582 | |||
583 | /* | ||
584 | * Common code for most interrupts. The C function we're eventually | ||
585 | * going to is in r0, and the faultnum is in r1; the original | ||
586 | * values for those registers are on the stack. | ||
587 | */ | ||
588 | .pushsection .text.handle_interrupt,"ax" | ||
589 | handle_interrupt: | ||
590 | finish_interrupt_save handle_interrupt | ||
591 | |||
592 | /* Jump to the C routine; it should enable irqs as soon as possible. */ | ||
593 | { | ||
594 | jalr r0 | ||
595 | PTREGS_PTR(r0, PTREGS_OFFSET_BASE) | ||
596 | } | ||
597 | FEEDBACK_REENTER(handle_interrupt) | ||
598 | { | ||
599 | movei r30, 0 /* not an NMI */ | ||
600 | j interrupt_return | ||
601 | } | ||
602 | STD_ENDPROC(handle_interrupt) | ||
603 | |||
604 | /* | ||
605 | * This routine takes a boolean in r30 indicating if this is an NMI. | ||
606 | * If so, we also expect a boolean in r31 indicating whether to | ||
607 | * re-enable the oprofile interrupts. | ||
608 | */ | ||
609 | STD_ENTRY(interrupt_return) | ||
610 | /* If we're resuming to kernel space, don't check thread flags. */ | ||
611 | { | ||
612 | bnez r30, .Lrestore_all /* NMIs don't special-case user-space */ | ||
613 | PTREGS_PTR(r29, PTREGS_OFFSET_EX1) | ||
614 | } | ||
615 | ld r29, r29 | ||
616 | andi r29, r29, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ | ||
617 | { | ||
618 | beqzt r29, .Lresume_userspace | ||
619 | PTREGS_PTR(r29, PTREGS_OFFSET_PC) | ||
620 | } | ||
621 | |||
622 | /* If we're resuming to _cpu_idle_nap, bump PC forward by 8. */ | ||
623 | moveli r27, hw2_last(_cpu_idle_nap) | ||
624 | { | ||
625 | ld r28, r29 | ||
626 | shl16insli r27, r27, hw1(_cpu_idle_nap) | ||
627 | } | ||
628 | { | ||
629 | shl16insli r27, r27, hw0(_cpu_idle_nap) | ||
630 | } | ||
631 | { | ||
632 | cmpeq r27, r27, r28 | ||
633 | } | ||
634 | { | ||
635 | blbc r27, .Lrestore_all | ||
636 | addi r28, r28, 8 | ||
637 | } | ||
638 | st r29, r28 | ||
639 | j .Lrestore_all | ||
640 | |||
641 | .Lresume_userspace: | ||
642 | FEEDBACK_REENTER(interrupt_return) | ||
643 | |||
644 | /* | ||
645 | * Disable interrupts so as to make sure we don't | ||
646 | * miss an interrupt that sets any of the thread flags (like | ||
647 | * need_resched or sigpending) between sampling and the iret. | ||
648 | * Routines like schedule() or do_signal() may re-enable | ||
649 | * interrupts before returning. | ||
650 | */ | ||
651 | IRQ_DISABLE(r20, r21) | ||
652 | TRACE_IRQS_OFF /* Note: clobbers registers r0-r29 */ | ||
653 | |||
654 | /* Get base of stack in r32; note r30/31 are used as arguments here. */ | ||
655 | GET_THREAD_INFO(r32) | ||
656 | |||
657 | |||
658 | /* Check to see if there is any work to do before returning to user. */ | ||
659 | { | ||
660 | addi r29, r32, THREAD_INFO_FLAGS_OFFSET | ||
661 | moveli r1, hw1_last(_TIF_ALLWORK_MASK) | ||
662 | } | ||
663 | { | ||
664 | ld r29, r29 | ||
665 | shl16insli r1, r1, hw0(_TIF_ALLWORK_MASK) | ||
666 | } | ||
667 | and r1, r29, r1 | ||
668 | beqzt r1, .Lrestore_all | ||
669 | |||
670 | /* | ||
671 | * Make sure we have all the registers saved for signal | ||
672 | * handling or single-step. Call out to C code to figure out | ||
673 | * exactly what we need to do for each flag bit, then if | ||
674 | * necessary, reload the flags and recheck. | ||
675 | */ | ||
676 | push_extra_callee_saves r0 | ||
677 | { | ||
678 | PTREGS_PTR(r0, PTREGS_OFFSET_BASE) | ||
679 | jal do_work_pending | ||
680 | } | ||
681 | bnez r0, .Lresume_userspace | ||
682 | |||
683 | /* | ||
684 | * In the NMI case we | ||
685 | * omit the call to single_process_check_nohz, which normally checks | ||
686 | * to see if we should start or stop the scheduler tick, because | ||
687 | * we can't call arbitrary Linux code from an NMI context. | ||
688 | * We always call the homecache TLB deferral code to re-trigger | ||
689 | * the deferral mechanism. | ||
690 | * | ||
691 | * The other chunk of responsibility this code has is to reset the | ||
692 | * interrupt masks appropriately to reset irqs and NMIs. We have | ||
693 | * to call TRACE_IRQS_OFF and TRACE_IRQS_ON to support all the | ||
694 | * lockdep-type stuff, but we can't set ICS until afterwards, since | ||
695 | * ICS can only be used in very tight chunks of code to avoid | ||
696 | * tripping over various assertions that it is off. | ||
697 | */ | ||
698 | .Lrestore_all: | ||
699 | PTREGS_PTR(r0, PTREGS_OFFSET_EX1) | ||
700 | { | ||
701 | ld r0, r0 | ||
702 | PTREGS_PTR(r32, PTREGS_OFFSET_FLAGS) | ||
703 | } | ||
704 | { | ||
705 | andi r0, r0, SPR_EX_CONTEXT_1_1__PL_MASK | ||
706 | ld r32, r32 | ||
707 | } | ||
708 | bnez r0, 1f | ||
709 | j 2f | ||
710 | #if PT_FLAGS_DISABLE_IRQ != 1 | ||
711 | # error Assuming PT_FLAGS_DISABLE_IRQ == 1 so we can use blbct below | ||
712 | #endif | ||
713 | 1: blbct r32, 2f | ||
714 | IRQ_DISABLE(r20,r21) | ||
715 | TRACE_IRQS_OFF | ||
716 | movei r0, 1 | ||
717 | mtspr INTERRUPT_CRITICAL_SECTION, r0 | ||
718 | beqzt r30, .Lrestore_regs | ||
719 | j 3f | ||
720 | 2: TRACE_IRQS_ON | ||
721 | movei r0, 1 | ||
722 | mtspr INTERRUPT_CRITICAL_SECTION, r0 | ||
723 | IRQ_ENABLE(r20, r21) | ||
724 | beqzt r30, .Lrestore_regs | ||
725 | 3: | ||
726 | |||
727 | |||
728 | /* | ||
729 | * We now commit to returning from this interrupt, since we will be | ||
730 | * doing things like setting EX_CONTEXT SPRs and unwinding the stack | ||
731 | * frame. No calls should be made to any other code after this point. | ||
732 | * This code should only be entered with ICS set. | ||
733 | * r32 must still be set to ptregs.flags. | ||
734 | * We launch loads to each cache line separately first, so we can | ||
735 | * get some parallelism out of the memory subsystem. | ||
736 | * We start zeroing caller-saved registers throughout, since | ||
737 | * that will save some cycles if this turns out to be a syscall. | ||
738 | */ | ||
739 | .Lrestore_regs: | ||
740 | FEEDBACK_REENTER(interrupt_return) /* called from elsewhere */ | ||
741 | |||
742 | /* | ||
743 | * Rotate so we have one high bit and one low bit to test. | ||
744 | * - low bit says whether to restore all the callee-saved registers, | ||
745 | * or just r30-r33, and r52 up. | ||
746 | * - high bit (i.e. sign bit) says whether to restore all the | ||
747 | * caller-saved registers, or just r0. | ||
748 | */ | ||
749 | #if PT_FLAGS_CALLER_SAVES != 2 || PT_FLAGS_RESTORE_REGS != 4 | ||
750 | # error Rotate trick does not work :-) | ||
751 | #endif | ||
752 | { | ||
753 | rotli r20, r32, 62 | ||
754 | PTREGS_PTR(sp, PTREGS_OFFSET_REG(0)) | ||
755 | } | ||
756 | |||
757 | /* | ||
758 | * Load cache lines 0, 4, 6 and 7, in that order, then use | ||
759 | * the last loaded value, which makes it likely that the other | ||
760 | * cache lines have also loaded, at which point we should be | ||
761 | * able to safely read all the remaining words on those cache | ||
762 | * lines without waiting for the memory subsystem. | ||
763 | */ | ||
764 | pop_reg r0, sp, PTREGS_OFFSET_REG(30) - PTREGS_OFFSET_REG(0) | ||
765 | pop_reg r30, sp, PTREGS_OFFSET_REG(52) - PTREGS_OFFSET_REG(30) | ||
766 | pop_reg_zero r52, r3, sp, PTREGS_OFFSET_CMPEXCH - PTREGS_OFFSET_REG(52) | ||
767 | pop_reg_zero r21, r27, sp, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_CMPEXCH | ||
768 | pop_reg_zero lr, r2, sp, PTREGS_OFFSET_PC - PTREGS_OFFSET_EX1 | ||
769 | { | ||
770 | mtspr CMPEXCH_VALUE, r21 | ||
771 | move r4, zero | ||
772 | } | ||
773 | pop_reg r21, sp, PTREGS_OFFSET_REG(31) - PTREGS_OFFSET_PC | ||
774 | { | ||
775 | mtspr SPR_EX_CONTEXT_K_1, lr | ||
776 | andi lr, lr, SPR_EX_CONTEXT_1_1__PL_MASK /* mask off ICS */ | ||
777 | } | ||
778 | { | ||
779 | mtspr SPR_EX_CONTEXT_K_0, r21 | ||
780 | move r5, zero | ||
781 | } | ||
782 | |||
783 | /* Restore callee-saveds that we actually use. */ | ||
784 | pop_reg_zero r31, r6 | ||
785 | pop_reg_zero r32, r7 | ||
786 | pop_reg_zero r33, r8, sp, PTREGS_OFFSET_REG(29) - PTREGS_OFFSET_REG(33) | ||
787 | |||
788 | /* | ||
789 | * If we modified other callee-saveds, restore them now. | ||
790 | * This is rare, but could be via ptrace or signal handler. | ||
791 | */ | ||
792 | { | ||
793 | move r9, zero | ||
794 | blbs r20, .Lrestore_callees | ||
795 | } | ||
796 | .Lcontinue_restore_regs: | ||
797 | |||
798 | /* Check if we're returning from a syscall. */ | ||
799 | { | ||
800 | move r10, zero | ||
801 | bltzt r20, 1f /* no, so go restore callee-save registers */ | ||
802 | } | ||
803 | |||
804 | /* | ||
805 | * Check if we're returning to userspace. | ||
806 | * Note that if we're not, we don't worry about zeroing everything. | ||
807 | */ | ||
808 | { | ||
809 | addli sp, sp, PTREGS_OFFSET_LR - PTREGS_OFFSET_REG(29) | ||
810 | bnez lr, .Lkernel_return | ||
811 | } | ||
812 | |||
813 | /* | ||
814 | * On return from syscall, we've restored r0 from pt_regs, but we | ||
815 | * clear the remainder of the caller-saved registers. We could | ||
816 | * restore the syscall arguments, but there's not much point, | ||
817 | * and it ensures user programs aren't trying to use the | ||
818 | * caller-saves if we clear them, as well as avoiding leaking | ||
819 | * kernel pointers into userspace. | ||
820 | */ | ||
821 | pop_reg_zero lr, r11, sp, PTREGS_OFFSET_TP - PTREGS_OFFSET_LR | ||
822 | pop_reg_zero tp, r12, sp, PTREGS_OFFSET_SP - PTREGS_OFFSET_TP | ||
823 | { | ||
824 | ld sp, sp | ||
825 | move r13, zero | ||
826 | move r14, zero | ||
827 | } | ||
828 | { move r15, zero; move r16, zero } | ||
829 | { move r17, zero; move r18, zero } | ||
830 | { move r19, zero; move r20, zero } | ||
831 | { move r21, zero; move r22, zero } | ||
832 | { move r23, zero; move r24, zero } | ||
833 | { move r25, zero; move r26, zero } | ||
834 | |||
835 | /* Set r1 to errno if we are returning an error, otherwise zero. */ | ||
836 | { | ||
837 | moveli r29, 4096 | ||
838 | sub r1, zero, r0 | ||
839 | } | ||
840 | { | ||
841 | move r28, zero | ||
842 | cmpltu r29, r1, r29 | ||
843 | } | ||
844 | { | ||
845 | mnz r1, r29, r1 | ||
846 | move r29, zero | ||
847 | } | ||
848 | iret | ||
849 | |||
850 | /* | ||
851 | * Not a syscall, so restore caller-saved registers. | ||
852 | * First kick off loads for cache lines 1-3, which we're touching | ||
853 | * for the first time here. | ||
854 | */ | ||
855 | .align 64 | ||
856 | 1: pop_reg r29, sp, PTREGS_OFFSET_REG(21) - PTREGS_OFFSET_REG(29) | ||
857 | pop_reg r21, sp, PTREGS_OFFSET_REG(13) - PTREGS_OFFSET_REG(21) | ||
858 | pop_reg r13, sp, PTREGS_OFFSET_REG(1) - PTREGS_OFFSET_REG(13) | ||
859 | pop_reg r1 | ||
860 | pop_reg r2 | ||
861 | pop_reg r3 | ||
862 | pop_reg r4 | ||
863 | pop_reg r5 | ||
864 | pop_reg r6 | ||
865 | pop_reg r7 | ||
866 | pop_reg r8 | ||
867 | pop_reg r9 | ||
868 | pop_reg r10 | ||
869 | pop_reg r11 | ||
870 | pop_reg r12, sp, 16 | ||
871 | /* r13 already restored above */ | ||
872 | pop_reg r14 | ||
873 | pop_reg r15 | ||
874 | pop_reg r16 | ||
875 | pop_reg r17 | ||
876 | pop_reg r18 | ||
877 | pop_reg r19 | ||
878 | pop_reg r20, sp, 16 | ||
879 | /* r21 already restored above */ | ||
880 | pop_reg r22 | ||
881 | pop_reg r23 | ||
882 | pop_reg r24 | ||
883 | pop_reg r25 | ||
884 | pop_reg r26 | ||
885 | pop_reg r27 | ||
886 | pop_reg r28, sp, PTREGS_OFFSET_LR - PTREGS_OFFSET_REG(28) | ||
887 | /* r29 already restored above */ | ||
888 | bnez lr, .Lkernel_return | ||
889 | pop_reg lr, sp, PTREGS_OFFSET_TP - PTREGS_OFFSET_LR | ||
890 | pop_reg tp, sp, PTREGS_OFFSET_SP - PTREGS_OFFSET_TP | ||
891 | ld sp, sp | ||
892 | iret | ||
893 | |||
894 | /* | ||
895 | * We can't restore tp when in kernel mode, since a thread might | ||
896 | * have migrated from another cpu and brought a stale tp value. | ||
897 | */ | ||
898 | .Lkernel_return: | ||
899 | pop_reg lr, sp, PTREGS_OFFSET_SP - PTREGS_OFFSET_LR | ||
900 | ld sp, sp | ||
901 | iret | ||
902 | |||
903 | /* Restore callee-saved registers from r34 to r51. */ | ||
904 | .Lrestore_callees: | ||
905 | addli sp, sp, PTREGS_OFFSET_REG(34) - PTREGS_OFFSET_REG(29) | ||
906 | pop_reg r34 | ||
907 | pop_reg r35 | ||
908 | pop_reg r36 | ||
909 | pop_reg r37 | ||
910 | pop_reg r38 | ||
911 | pop_reg r39 | ||
912 | pop_reg r40 | ||
913 | pop_reg r41 | ||
914 | pop_reg r42 | ||
915 | pop_reg r43 | ||
916 | pop_reg r44 | ||
917 | pop_reg r45 | ||
918 | pop_reg r46 | ||
919 | pop_reg r47 | ||
920 | pop_reg r48 | ||
921 | pop_reg r49 | ||
922 | pop_reg r50 | ||
923 | pop_reg r51, sp, PTREGS_OFFSET_REG(29) - PTREGS_OFFSET_REG(51) | ||
924 | j .Lcontinue_restore_regs | ||
925 | STD_ENDPROC(interrupt_return) | ||
926 | |||
927 | /* | ||
928 | * "NMI" interrupts mask ALL interrupts before calling the | ||
929 | * handler, and don't check thread flags, etc., on the way | ||
930 | * back out. In general, the only things we do here for NMIs | ||
931 | * are register save/restore and dataplane kernel-TLB management. | ||
932 | * We don't (for example) deal with start/stop of the sched tick. | ||
933 | */ | ||
934 | .pushsection .text.handle_nmi,"ax" | ||
935 | handle_nmi: | ||
936 | finish_interrupt_save handle_nmi | ||
937 | { | ||
938 | jalr r0 | ||
939 | PTREGS_PTR(r0, PTREGS_OFFSET_BASE) | ||
940 | } | ||
941 | FEEDBACK_REENTER(handle_nmi) | ||
942 | { | ||
943 | movei r30, 1 | ||
944 | move r31, r0 | ||
945 | } | ||
946 | j interrupt_return | ||
947 | STD_ENDPROC(handle_nmi) | ||
948 | |||
949 | /* | ||
950 | * Parallel code for syscalls to handle_interrupt. | ||
951 | */ | ||
952 | .pushsection .text.handle_syscall,"ax" | ||
953 | handle_syscall: | ||
954 | finish_interrupt_save handle_syscall | ||
955 | |||
956 | /* Enable irqs. */ | ||
957 | TRACE_IRQS_ON | ||
958 | IRQ_ENABLE(r20, r21) | ||
959 | |||
960 | /* Bump the counter for syscalls made on this tile. */ | ||
961 | moveli r20, hw2_last(irq_stat + IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET) | ||
962 | shl16insli r20, r20, hw1(irq_stat + IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET) | ||
963 | shl16insli r20, r20, hw0(irq_stat + IRQ_CPUSTAT_SYSCALL_COUNT_OFFSET) | ||
964 | add r20, r20, tp | ||
965 | ld4s r21, r20 | ||
966 | addi r21, r21, 1 | ||
967 | st4 r20, r21 | ||
968 | |||
969 | /* Trace syscalls, if requested. */ | ||
970 | GET_THREAD_INFO(r31) | ||
971 | addi r31, r31, THREAD_INFO_FLAGS_OFFSET | ||
972 | ld r30, r31 | ||
973 | andi r30, r30, _TIF_SYSCALL_TRACE | ||
974 | { | ||
975 | addi r30, r31, THREAD_INFO_STATUS_OFFSET - THREAD_INFO_FLAGS_OFFSET | ||
976 | beqzt r30, .Lrestore_syscall_regs | ||
977 | } | ||
978 | jal do_syscall_trace | ||
979 | FEEDBACK_REENTER(handle_syscall) | ||
980 | |||
981 | /* | ||
982 | * We always reload our registers from the stack at this | ||
983 | * point. They might be valid, if we didn't build with | ||
984 | * TRACE_IRQFLAGS, and this isn't a dataplane tile, and we're not | ||
985 | * doing syscall tracing, but there are enough cases now that it | ||
986 | * seems simplest just to do the reload unconditionally. | ||
987 | */ | ||
988 | .Lrestore_syscall_regs: | ||
989 | { | ||
990 | ld r30, r30 | ||
991 | PTREGS_PTR(r11, PTREGS_OFFSET_REG(0)) | ||
992 | } | ||
993 | pop_reg r0, r11 | ||
994 | pop_reg r1, r11 | ||
995 | pop_reg r2, r11 | ||
996 | pop_reg r3, r11 | ||
997 | pop_reg r4, r11 | ||
998 | pop_reg r5, r11, PTREGS_OFFSET_SYSCALL - PTREGS_OFFSET_REG(5) | ||
999 | { | ||
1000 | ld TREG_SYSCALL_NR_NAME, r11 | ||
1001 | moveli r21, __NR_syscalls | ||
1002 | } | ||
1003 | |||
1004 | /* Ensure that the syscall number is within the legal range. */ | ||
1005 | { | ||
1006 | moveli r20, hw2(sys_call_table) | ||
1007 | blbs r30, .Lcompat_syscall | ||
1008 | } | ||
1009 | { | ||
1010 | cmpltu r21, TREG_SYSCALL_NR_NAME, r21 | ||
1011 | shl16insli r20, r20, hw1(sys_call_table) | ||
1012 | } | ||
1013 | { | ||
1014 | blbc r21, .Linvalid_syscall | ||
1015 | shl16insli r20, r20, hw0(sys_call_table) | ||
1016 | } | ||
1017 | .Lload_syscall_pointer: | ||
1018 | shl3add r20, TREG_SYSCALL_NR_NAME, r20 | ||
1019 | ld r20, r20 | ||
1020 | |||
1021 | /* Jump to syscall handler. */ | ||
1022 | jalr r20 | ||
1023 | .Lhandle_syscall_link: /* value of "lr" after "jalr r20" above */ | ||
1024 | |||
1025 | /* | ||
1026 | * Write our r0 onto the stack so it gets restored instead | ||
1027 | * of whatever the user had there before. | ||
1028 | * In compat mode, sign-extend r0 before storing it. | ||
1029 | */ | ||
1030 | { | ||
1031 | PTREGS_PTR(r29, PTREGS_OFFSET_REG(0)) | ||
1032 | blbct r30, 1f | ||
1033 | } | ||
1034 | addxi r0, r0, 0 | ||
1035 | 1: st r29, r0 | ||
1036 | |||
1037 | .Lsyscall_sigreturn_skip: | ||
1038 | FEEDBACK_REENTER(handle_syscall) | ||
1039 | |||
1040 | /* Do syscall trace again, if requested. */ | ||
1041 | ld r30, r31 | ||
1042 | andi r30, r30, _TIF_SYSCALL_TRACE | ||
1043 | beqzt r30, 1f | ||
1044 | jal do_syscall_trace | ||
1045 | FEEDBACK_REENTER(handle_syscall) | ||
1046 | 1: j .Lresume_userspace /* jump into middle of interrupt_return */ | ||
1047 | |||
1048 | .Lcompat_syscall: | ||
1049 | /* | ||
1050 | * Load the base of the compat syscall table in r20, and | ||
1051 | * range-check the syscall number (duplicated from 64-bit path). | ||
1052 | * Sign-extend all the user's passed arguments to make them consistent. | ||
1053 | * Also save the original "r(n)" values away in "r(11+n)" in | ||
1054 | * case the syscall table entry wants to validate them. | ||
1055 | */ | ||
1056 | moveli r20, hw2(compat_sys_call_table) | ||
1057 | { | ||
1058 | cmpltu r21, TREG_SYSCALL_NR_NAME, r21 | ||
1059 | shl16insli r20, r20, hw1(compat_sys_call_table) | ||
1060 | } | ||
1061 | { | ||
1062 | blbc r21, .Linvalid_syscall | ||
1063 | shl16insli r20, r20, hw0(compat_sys_call_table) | ||
1064 | } | ||
1065 | { move r11, r0; addxi r0, r0, 0 } | ||
1066 | { move r12, r1; addxi r1, r1, 0 } | ||
1067 | { move r13, r2; addxi r2, r2, 0 } | ||
1068 | { move r14, r3; addxi r3, r3, 0 } | ||
1069 | { move r15, r4; addxi r4, r4, 0 } | ||
1070 | { move r16, r5; addxi r5, r5, 0 } | ||
1071 | j .Lload_syscall_pointer | ||
1072 | |||
1073 | .Linvalid_syscall: | ||
1074 | /* Report an invalid syscall back to the user program */ | ||
1075 | { | ||
1076 | PTREGS_PTR(r29, PTREGS_OFFSET_REG(0)) | ||
1077 | movei r28, -ENOSYS | ||
1078 | } | ||
1079 | st r29, r28 | ||
1080 | j .Lresume_userspace /* jump into middle of interrupt_return */ | ||
1081 | STD_ENDPROC(handle_syscall) | ||
1082 | |||
1083 | /* Return the address for oprofile to suppress in backtraces. */ | ||
1084 | STD_ENTRY_SECTION(handle_syscall_link_address, .text.handle_syscall) | ||
1085 | lnk r0 | ||
1086 | { | ||
1087 | addli r0, r0, .Lhandle_syscall_link - . | ||
1088 | jrp lr | ||
1089 | } | ||
1090 | STD_ENDPROC(handle_syscall_link_address) | ||
1091 | |||
1092 | STD_ENTRY(ret_from_fork) | ||
1093 | jal sim_notify_fork | ||
1094 | jal schedule_tail | ||
1095 | FEEDBACK_REENTER(ret_from_fork) | ||
1096 | j .Lresume_userspace | ||
1097 | STD_ENDPROC(ret_from_fork) | ||
1098 | |||
1099 | /* Various stub interrupt handlers and syscall handlers */ | ||
1100 | |||
1101 | STD_ENTRY_LOCAL(_kernel_double_fault) | ||
1102 | mfspr r1, SPR_EX_CONTEXT_K_0 | ||
1103 | move r2, lr | ||
1104 | move r3, sp | ||
1105 | move r4, r52 | ||
1106 | addi sp, sp, -C_ABI_SAVE_AREA_SIZE | ||
1107 | j kernel_double_fault | ||
1108 | STD_ENDPROC(_kernel_double_fault) | ||
1109 | |||
1110 | STD_ENTRY_LOCAL(bad_intr) | ||
1111 | mfspr r2, SPR_EX_CONTEXT_K_0 | ||
1112 | panic "Unhandled interrupt %#x: PC %#lx" | ||
1113 | STD_ENDPROC(bad_intr) | ||
1114 | |||
1115 | /* Put address of pt_regs in reg and jump. */ | ||
1116 | #define PTREGS_SYSCALL(x, reg) \ | ||
1117 | STD_ENTRY(_##x); \ | ||
1118 | { \ | ||
1119 | PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ | ||
1120 | j x \ | ||
1121 | }; \ | ||
1122 | STD_ENDPROC(_##x) | ||
1123 | |||
1124 | /* | ||
1125 | * Special-case sigreturn to not write r0 to the stack on return. | ||
1126 | * This is technically more efficient, but it also avoids difficulties | ||
1127 | * in the 64-bit OS when handling 32-bit compat code, since we must not | ||
1128 | * sign-extend r0 for the sigreturn return-value case. | ||
1129 | */ | ||
1130 | #define PTREGS_SYSCALL_SIGRETURN(x, reg) \ | ||
1131 | STD_ENTRY(_##x); \ | ||
1132 | addli lr, lr, .Lsyscall_sigreturn_skip - .Lhandle_syscall_link; \ | ||
1133 | { \ | ||
1134 | PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \ | ||
1135 | j x \ | ||
1136 | }; \ | ||
1137 | STD_ENDPROC(_##x) | ||
1138 | |||
1139 | PTREGS_SYSCALL(sys_execve, r3) | ||
1140 | PTREGS_SYSCALL(sys_sigaltstack, r2) | ||
1141 | PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0) | ||
1142 | #ifdef CONFIG_COMPAT | ||
1143 | PTREGS_SYSCALL(compat_sys_execve, r3) | ||
1144 | PTREGS_SYSCALL(compat_sys_sigaltstack, r2) | ||
1145 | PTREGS_SYSCALL_SIGRETURN(compat_sys_rt_sigreturn, r0) | ||
1146 | #endif | ||
1147 | |||
1148 | /* Save additional callee-saves to pt_regs, put address in r4 and jump. */ | ||
1149 | STD_ENTRY(_sys_clone) | ||
1150 | push_extra_callee_saves r4 | ||
1151 | j sys_clone | ||
1152 | STD_ENDPROC(_sys_clone) | ||
1153 | |||
1154 | /* The single-step support may need to read all the registers. */ | ||
1155 | int_unalign: | ||
1156 | push_extra_callee_saves r0 | ||
1157 | j do_trap | ||
1158 | |||
1159 | /* Include .intrpt1 array of interrupt vectors */ | ||
1160 | .section ".intrpt1", "ax" | ||
1161 | |||
1162 | #define op_handle_perf_interrupt bad_intr | ||
1163 | #define op_handle_aux_perf_interrupt bad_intr | ||
1164 | |||
1165 | #ifndef CONFIG_HARDWALL | ||
1166 | #define do_hardwall_trap bad_intr | ||
1167 | #endif | ||
1168 | |||
1169 | int_hand INT_MEM_ERROR, MEM_ERROR, bad_intr | ||
1170 | int_hand INT_SINGLE_STEP_3, SINGLE_STEP_3, bad_intr | ||
1171 | #if CONFIG_KERNEL_PL == 2 | ||
1172 | int_hand INT_SINGLE_STEP_2, SINGLE_STEP_2, gx_singlestep_handle | ||
1173 | int_hand INT_SINGLE_STEP_1, SINGLE_STEP_1, bad_intr | ||
1174 | #else | ||
1175 | int_hand INT_SINGLE_STEP_2, SINGLE_STEP_2, bad_intr | ||
1176 | int_hand INT_SINGLE_STEP_1, SINGLE_STEP_1, gx_singlestep_handle | ||
1177 | #endif | ||
1178 | int_hand INT_SINGLE_STEP_0, SINGLE_STEP_0, bad_intr | ||
1179 | int_hand INT_IDN_COMPLETE, IDN_COMPLETE, bad_intr | ||
1180 | int_hand INT_UDN_COMPLETE, UDN_COMPLETE, bad_intr | ||
1181 | int_hand INT_ITLB_MISS, ITLB_MISS, do_page_fault | ||
1182 | int_hand INT_ILL, ILL, do_trap | ||
1183 | int_hand INT_GPV, GPV, do_trap | ||
1184 | int_hand INT_IDN_ACCESS, IDN_ACCESS, do_trap | ||
1185 | int_hand INT_UDN_ACCESS, UDN_ACCESS, do_trap | ||
1186 | int_hand INT_SWINT_3, SWINT_3, do_trap | ||
1187 | int_hand INT_SWINT_2, SWINT_2, do_trap | ||
1188 | int_hand INT_SWINT_1, SWINT_1, SYSCALL, handle_syscall | ||
1189 | int_hand INT_SWINT_0, SWINT_0, do_trap | ||
1190 | int_hand INT_ILL_TRANS, ILL_TRANS, do_trap | ||
1191 | int_hand INT_UNALIGN_DATA, UNALIGN_DATA, int_unalign | ||
1192 | int_hand INT_DTLB_MISS, DTLB_MISS, do_page_fault | ||
1193 | int_hand INT_DTLB_ACCESS, DTLB_ACCESS, do_page_fault | ||
1194 | int_hand INT_IDN_FIREWALL, IDN_FIREWALL, bad_intr | ||
1195 | int_hand INT_UDN_FIREWALL, UDN_FIREWALL, do_hardwall_trap | ||
1196 | int_hand INT_TILE_TIMER, TILE_TIMER, do_timer_interrupt | ||
1197 | int_hand INT_IDN_TIMER, IDN_TIMER, bad_intr | ||
1198 | int_hand INT_UDN_TIMER, UDN_TIMER, bad_intr | ||
1199 | int_hand INT_IDN_AVAIL, IDN_AVAIL, bad_intr | ||
1200 | int_hand INT_UDN_AVAIL, UDN_AVAIL, bad_intr | ||
1201 | int_hand INT_IPI_3, IPI_3, bad_intr | ||
1202 | #if CONFIG_KERNEL_PL == 2 | ||
1203 | int_hand INT_IPI_2, IPI_2, tile_dev_intr | ||
1204 | int_hand INT_IPI_1, IPI_1, bad_intr | ||
1205 | #else | ||
1206 | int_hand INT_IPI_2, IPI_2, bad_intr | ||
1207 | int_hand INT_IPI_1, IPI_1, tile_dev_intr | ||
1208 | #endif | ||
1209 | int_hand INT_IPI_0, IPI_0, bad_intr | ||
1210 | int_hand INT_PERF_COUNT, PERF_COUNT, \ | ||
1211 | op_handle_perf_interrupt, handle_nmi | ||
1212 | int_hand INT_AUX_PERF_COUNT, AUX_PERF_COUNT, \ | ||
1213 | op_handle_perf_interrupt, handle_nmi | ||
1214 | int_hand INT_INTCTRL_3, INTCTRL_3, bad_intr | ||
1215 | #if CONFIG_KERNEL_PL == 2 | ||
1216 | dc_dispatch INT_INTCTRL_2, INTCTRL_2 | ||
1217 | int_hand INT_INTCTRL_1, INTCTRL_1, bad_intr | ||
1218 | #else | ||
1219 | int_hand INT_INTCTRL_2, INTCTRL_2, bad_intr | ||
1220 | dc_dispatch INT_INTCTRL_1, INTCTRL_1 | ||
1221 | #endif | ||
1222 | int_hand INT_INTCTRL_0, INTCTRL_0, bad_intr | ||
1223 | int_hand INT_MESSAGE_RCV_DWNCL, MESSAGE_RCV_DWNCL, \ | ||
1224 | hv_message_intr | ||
1225 | int_hand INT_DEV_INTR_DWNCL, DEV_INTR_DWNCL, bad_intr | ||
1226 | int_hand INT_I_ASID, I_ASID, bad_intr | ||
1227 | int_hand INT_D_ASID, D_ASID, bad_intr | ||
1228 | int_hand INT_DOUBLE_FAULT, DOUBLE_FAULT, do_trap | ||
1229 | |||
1230 | /* Synthetic interrupt delivered only by the simulator */ | ||
1231 | int_hand INT_BREAKPOINT, BREAKPOINT, do_breakpoint | ||
diff --git a/arch/tile/kernel/irq.c b/arch/tile/kernel/irq.c index 596c60086930..aa0134db2dd6 100644 --- a/arch/tile/kernel/irq.c +++ b/arch/tile/kernel/irq.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #define IS_HW_CLEARED 1 | 26 | #define IS_HW_CLEARED 1 |
27 | 27 | ||
28 | /* | 28 | /* |
29 | * The set of interrupts we enable for raw_local_irq_enable(). | 29 | * The set of interrupts we enable for arch_local_irq_enable(). |
30 | * This is initialized to have just a single interrupt that the kernel | 30 | * This is initialized to have just a single interrupt that the kernel |
31 | * doesn't actually use as a sentinel. During kernel init, | 31 | * doesn't actually use as a sentinel. During kernel init, |
32 | * interrupts are added as the kernel gets prepared to support them. | 32 | * interrupts are added as the kernel gets prepared to support them. |
@@ -61,9 +61,9 @@ static DEFINE_SPINLOCK(available_irqs_lock); | |||
61 | 61 | ||
62 | #if CHIP_HAS_IPI() | 62 | #if CHIP_HAS_IPI() |
63 | /* Use SPRs to manipulate device interrupts. */ | 63 | /* Use SPRs to manipulate device interrupts. */ |
64 | #define mask_irqs(irq_mask) __insn_mtspr(SPR_IPI_MASK_SET_1, irq_mask) | 64 | #define mask_irqs(irq_mask) __insn_mtspr(SPR_IPI_MASK_SET_K, irq_mask) |
65 | #define unmask_irqs(irq_mask) __insn_mtspr(SPR_IPI_MASK_RESET_1, irq_mask) | 65 | #define unmask_irqs(irq_mask) __insn_mtspr(SPR_IPI_MASK_RESET_K, irq_mask) |
66 | #define clear_irqs(irq_mask) __insn_mtspr(SPR_IPI_EVENT_RESET_1, irq_mask) | 66 | #define clear_irqs(irq_mask) __insn_mtspr(SPR_IPI_EVENT_RESET_K, irq_mask) |
67 | #else | 67 | #else |
68 | /* Use HV to manipulate device interrupts. */ | 68 | /* Use HV to manipulate device interrupts. */ |
69 | #define mask_irqs(irq_mask) hv_disable_intr(irq_mask) | 69 | #define mask_irqs(irq_mask) hv_disable_intr(irq_mask) |
@@ -89,16 +89,16 @@ void tile_dev_intr(struct pt_regs *regs, int intnum) | |||
89 | * masked by a previous interrupt. Then, mask out the ones | 89 | * masked by a previous interrupt. Then, mask out the ones |
90 | * we're going to handle. | 90 | * we're going to handle. |
91 | */ | 91 | */ |
92 | unsigned long masked = __insn_mfspr(SPR_IPI_MASK_1); | 92 | unsigned long masked = __insn_mfspr(SPR_IPI_MASK_K); |
93 | original_irqs = __insn_mfspr(SPR_IPI_EVENT_1) & ~masked; | 93 | original_irqs = __insn_mfspr(SPR_IPI_EVENT_K) & ~masked; |
94 | __insn_mtspr(SPR_IPI_MASK_SET_1, original_irqs); | 94 | __insn_mtspr(SPR_IPI_MASK_SET_K, original_irqs); |
95 | #else | 95 | #else |
96 | /* | 96 | /* |
97 | * Hypervisor performs the equivalent of the Gx code above and | 97 | * Hypervisor performs the equivalent of the Gx code above and |
98 | * then puts the pending interrupt mask into a system save reg | 98 | * then puts the pending interrupt mask into a system save reg |
99 | * for us to find. | 99 | * for us to find. |
100 | */ | 100 | */ |
101 | original_irqs = __insn_mfspr(SPR_SYSTEM_SAVE_1_3); | 101 | original_irqs = __insn_mfspr(SPR_SYSTEM_SAVE_K_3); |
102 | #endif | 102 | #endif |
103 | remaining_irqs = original_irqs; | 103 | remaining_irqs = original_irqs; |
104 | 104 | ||
@@ -176,43 +176,43 @@ void disable_percpu_irq(unsigned int irq) | |||
176 | EXPORT_SYMBOL(disable_percpu_irq); | 176 | EXPORT_SYMBOL(disable_percpu_irq); |
177 | 177 | ||
178 | /* Mask an interrupt. */ | 178 | /* Mask an interrupt. */ |
179 | static void tile_irq_chip_mask(unsigned int irq) | 179 | static void tile_irq_chip_mask(struct irq_data *d) |
180 | { | 180 | { |
181 | mask_irqs(1UL << irq); | 181 | mask_irqs(1UL << d->irq); |
182 | } | 182 | } |
183 | 183 | ||
184 | /* Unmask an interrupt. */ | 184 | /* Unmask an interrupt. */ |
185 | static void tile_irq_chip_unmask(unsigned int irq) | 185 | static void tile_irq_chip_unmask(struct irq_data *d) |
186 | { | 186 | { |
187 | unmask_irqs(1UL << irq); | 187 | unmask_irqs(1UL << d->irq); |
188 | } | 188 | } |
189 | 189 | ||
190 | /* | 190 | /* |
191 | * Clear an interrupt before processing it so that any new assertions | 191 | * Clear an interrupt before processing it so that any new assertions |
192 | * will trigger another irq. | 192 | * will trigger another irq. |
193 | */ | 193 | */ |
194 | static void tile_irq_chip_ack(unsigned int irq) | 194 | static void tile_irq_chip_ack(struct irq_data *d) |
195 | { | 195 | { |
196 | if ((unsigned long)get_irq_chip_data(irq) != IS_HW_CLEARED) | 196 | if ((unsigned long)irq_data_get_irq_chip_data(d) != IS_HW_CLEARED) |
197 | clear_irqs(1UL << irq); | 197 | clear_irqs(1UL << d->irq); |
198 | } | 198 | } |
199 | 199 | ||
200 | /* | 200 | /* |
201 | * For per-cpu interrupts, we need to avoid unmasking any interrupts | 201 | * For per-cpu interrupts, we need to avoid unmasking any interrupts |
202 | * that we disabled via disable_percpu_irq(). | 202 | * that we disabled via disable_percpu_irq(). |
203 | */ | 203 | */ |
204 | static void tile_irq_chip_eoi(unsigned int irq) | 204 | static void tile_irq_chip_eoi(struct irq_data *d) |
205 | { | 205 | { |
206 | if (!(__get_cpu_var(irq_disable_mask) & (1UL << irq))) | 206 | if (!(__get_cpu_var(irq_disable_mask) & (1UL << d->irq))) |
207 | unmask_irqs(1UL << irq); | 207 | unmask_irqs(1UL << d->irq); |
208 | } | 208 | } |
209 | 209 | ||
210 | static struct irq_chip tile_irq_chip = { | 210 | static struct irq_chip tile_irq_chip = { |
211 | .typename = "tile_irq_chip", | 211 | .name = "tile_irq_chip", |
212 | .ack = tile_irq_chip_ack, | 212 | .irq_ack = tile_irq_chip_ack, |
213 | .eoi = tile_irq_chip_eoi, | 213 | .irq_eoi = tile_irq_chip_eoi, |
214 | .mask = tile_irq_chip_mask, | 214 | .irq_mask = tile_irq_chip_mask, |
215 | .unmask = tile_irq_chip_unmask, | 215 | .irq_unmask = tile_irq_chip_unmask, |
216 | }; | 216 | }; |
217 | 217 | ||
218 | void __init init_IRQ(void) | 218 | void __init init_IRQ(void) |
@@ -225,7 +225,7 @@ void __cpuinit setup_irq_regs(void) | |||
225 | /* Enable interrupt delivery. */ | 225 | /* Enable interrupt delivery. */ |
226 | unmask_irqs(~0UL); | 226 | unmask_irqs(~0UL); |
227 | #if CHIP_HAS_IPI() | 227 | #if CHIP_HAS_IPI() |
228 | raw_local_irq_unmask(INT_IPI_1); | 228 | arch_local_irq_unmask(INT_IPI_K); |
229 | #endif | 229 | #endif |
230 | } | 230 | } |
231 | 231 | ||
@@ -241,14 +241,14 @@ void tile_irq_activate(unsigned int irq, int tile_irq_type) | |||
241 | irq_flow_handler_t handle = handle_level_irq; | 241 | irq_flow_handler_t handle = handle_level_irq; |
242 | if (tile_irq_type == TILE_IRQ_PERCPU) | 242 | if (tile_irq_type == TILE_IRQ_PERCPU) |
243 | handle = handle_percpu_irq; | 243 | handle = handle_percpu_irq; |
244 | set_irq_chip_and_handler(irq, &tile_irq_chip, handle); | 244 | irq_set_chip_and_handler(irq, &tile_irq_chip, handle); |
245 | 245 | ||
246 | /* | 246 | /* |
247 | * Flag interrupts that are hardware-cleared so that ack() | 247 | * Flag interrupts that are hardware-cleared so that ack() |
248 | * won't clear them. | 248 | * won't clear them. |
249 | */ | 249 | */ |
250 | if (tile_irq_type == TILE_IRQ_HW_CLEAR) | 250 | if (tile_irq_type == TILE_IRQ_HW_CLEAR) |
251 | set_irq_chip_data(irq, (void *)IS_HW_CLEARED); | 251 | irq_set_chip_data(irq, (void *)IS_HW_CLEARED); |
252 | } | 252 | } |
253 | EXPORT_SYMBOL(tile_irq_activate); | 253 | EXPORT_SYMBOL(tile_irq_activate); |
254 | 254 | ||
@@ -262,45 +262,6 @@ void ack_bad_irq(unsigned int irq) | |||
262 | * Generic, controller-independent functions: | 262 | * Generic, controller-independent functions: |
263 | */ | 263 | */ |
264 | 264 | ||
265 | int show_interrupts(struct seq_file *p, void *v) | ||
266 | { | ||
267 | int i = *(loff_t *) v, j; | ||
268 | struct irqaction *action; | ||
269 | unsigned long flags; | ||
270 | |||
271 | if (i == 0) { | ||
272 | seq_printf(p, " "); | ||
273 | for (j = 0; j < NR_CPUS; j++) | ||
274 | if (cpu_online(j)) | ||
275 | seq_printf(p, "CPU%-8d", j); | ||
276 | seq_putc(p, '\n'); | ||
277 | } | ||
278 | |||
279 | if (i < NR_IRQS) { | ||
280 | raw_spin_lock_irqsave(&irq_desc[i].lock, flags); | ||
281 | action = irq_desc[i].action; | ||
282 | if (!action) | ||
283 | goto skip; | ||
284 | seq_printf(p, "%3d: ", i); | ||
285 | #ifndef CONFIG_SMP | ||
286 | seq_printf(p, "%10u ", kstat_irqs(i)); | ||
287 | #else | ||
288 | for_each_online_cpu(j) | ||
289 | seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); | ||
290 | #endif | ||
291 | seq_printf(p, " %14s", irq_desc[i].chip->typename); | ||
292 | seq_printf(p, " %s", action->name); | ||
293 | |||
294 | for (action = action->next; action; action = action->next) | ||
295 | seq_printf(p, ", %s", action->name); | ||
296 | |||
297 | seq_putc(p, '\n'); | ||
298 | skip: | ||
299 | raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags); | ||
300 | } | ||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | #if CHIP_HAS_IPI() | 265 | #if CHIP_HAS_IPI() |
305 | int create_irq(void) | 266 | int create_irq(void) |
306 | { | 267 | { |
diff --git a/arch/tile/kernel/machine_kexec.c b/arch/tile/kernel/machine_kexec.c index ba7a265d6179..e00d7179989e 100644 --- a/arch/tile/kernel/machine_kexec.c +++ b/arch/tile/kernel/machine_kexec.c | |||
@@ -182,13 +182,13 @@ static void kexec_find_and_set_command_line(struct kimage *image) | |||
182 | 182 | ||
183 | if ((entry & IND_SOURCE)) { | 183 | if ((entry & IND_SOURCE)) { |
184 | void *va = | 184 | void *va = |
185 | kmap_atomic_pfn(entry >> PAGE_SHIFT, KM_USER0); | 185 | kmap_atomic_pfn(entry >> PAGE_SHIFT); |
186 | r = kexec_bn2cl(va); | 186 | r = kexec_bn2cl(va); |
187 | if (r) { | 187 | if (r) { |
188 | command_line = r; | 188 | command_line = r; |
189 | break; | 189 | break; |
190 | } | 190 | } |
191 | kunmap_atomic(va, KM_USER0); | 191 | kunmap_atomic(va); |
192 | } | 192 | } |
193 | } | 193 | } |
194 | 194 | ||
@@ -198,7 +198,7 @@ static void kexec_find_and_set_command_line(struct kimage *image) | |||
198 | 198 | ||
199 | hverr = hv_set_command_line( | 199 | hverr = hv_set_command_line( |
200 | (HV_VirtAddr) command_line, strlen(command_line)); | 200 | (HV_VirtAddr) command_line, strlen(command_line)); |
201 | kunmap_atomic(command_line, KM_USER0); | 201 | kunmap_atomic(command_line); |
202 | } else { | 202 | } else { |
203 | pr_info("%s: no command line found; making empty\n", | 203 | pr_info("%s: no command line found; making empty\n", |
204 | __func__); | 204 | __func__); |
@@ -240,8 +240,11 @@ static void setup_quasi_va_is_pa(void) | |||
240 | pte = hv_pte(_PAGE_KERNEL | _PAGE_HUGE_PAGE); | 240 | pte = hv_pte(_PAGE_KERNEL | _PAGE_HUGE_PAGE); |
241 | pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_NO_L3); | 241 | pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_NO_L3); |
242 | 242 | ||
243 | for (i = 0; i < pgd_index(PAGE_OFFSET); i++) | 243 | for (i = 0; i < pgd_index(PAGE_OFFSET); i++) { |
244 | pgtable[i] = pfn_pte(i << (HPAGE_SHIFT - PAGE_SHIFT), pte); | 244 | unsigned long pfn = i << (HPAGE_SHIFT - PAGE_SHIFT); |
245 | if (pfn_valid(pfn)) | ||
246 | __set_pte(&pgtable[i], pfn_pte(pfn, pte)); | ||
247 | } | ||
245 | } | 248 | } |
246 | 249 | ||
247 | 250 | ||
diff --git a/arch/tile/kernel/messaging.c b/arch/tile/kernel/messaging.c index 6d23ed271d10..0858ee6b520f 100644 --- a/arch/tile/kernel/messaging.c +++ b/arch/tile/kernel/messaging.c | |||
@@ -34,7 +34,7 @@ void __cpuinit init_messaging(void) | |||
34 | panic("hv_register_message_state: error %d", rc); | 34 | panic("hv_register_message_state: error %d", rc); |
35 | 35 | ||
36 | /* Make sure downcall interrupts will be enabled. */ | 36 | /* Make sure downcall interrupts will be enabled. */ |
37 | raw_local_irq_unmask(INT_INTCTRL_1); | 37 | arch_local_irq_unmask(INT_INTCTRL_K); |
38 | } | 38 | } |
39 | 39 | ||
40 | void hv_message_intr(struct pt_regs *regs, int intnum) | 40 | void hv_message_intr(struct pt_regs *regs, int intnum) |
diff --git a/arch/tile/kernel/module.c b/arch/tile/kernel/module.c index e2ab82b7c7e7..f68df69f1f67 100644 --- a/arch/tile/kernel/module.c +++ b/arch/tile/kernel/module.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <asm/opcode-tile.h> | 23 | #include <asm/opcode-tile.h> |
24 | #include <asm/pgtable.h> | 24 | #include <asm/pgtable.h> |
25 | #include <asm/homecache.h> | ||
25 | 26 | ||
26 | #ifdef __tilegx__ | 27 | #ifdef __tilegx__ |
27 | # define Elf_Rela Elf64_Rela | 28 | # define Elf_Rela Elf64_Rela |
@@ -86,8 +87,13 @@ error: | |||
86 | void module_free(struct module *mod, void *module_region) | 87 | void module_free(struct module *mod, void *module_region) |
87 | { | 88 | { |
88 | vfree(module_region); | 89 | vfree(module_region); |
90 | |||
91 | /* Globally flush the L1 icache. */ | ||
92 | flush_remote(0, HV_FLUSH_EVICT_L1I, cpu_online_mask, | ||
93 | 0, 0, 0, NULL, NULL, 0); | ||
94 | |||
89 | /* | 95 | /* |
90 | * FIXME: If module_region == mod->init_region, trim exception | 96 | * FIXME: If module_region == mod->module_init, trim exception |
91 | * table entries. | 97 | * table entries. |
92 | */ | 98 | */ |
93 | } | 99 | } |
diff --git a/arch/tile/kernel/pci-dma.c b/arch/tile/kernel/pci-dma.c index 5ad5e13b0fa6..658f2ce426a4 100644 --- a/arch/tile/kernel/pci-dma.c +++ b/arch/tile/kernel/pci-dma.c | |||
@@ -86,6 +86,21 @@ EXPORT_SYMBOL(dma_free_coherent); | |||
86 | * can count on nothing having been touched. | 86 | * can count on nothing having been touched. |
87 | */ | 87 | */ |
88 | 88 | ||
89 | /* Flush a PA range from cache page by page. */ | ||
90 | static void __dma_map_pa_range(dma_addr_t dma_addr, size_t size) | ||
91 | { | ||
92 | struct page *page = pfn_to_page(PFN_DOWN(dma_addr)); | ||
93 | size_t bytesleft = PAGE_SIZE - (dma_addr & (PAGE_SIZE - 1)); | ||
94 | |||
95 | while ((ssize_t)size > 0) { | ||
96 | /* Flush the page. */ | ||
97 | homecache_flush_cache(page++, 0); | ||
98 | |||
99 | /* Figure out if we need to continue on the next page. */ | ||
100 | size -= bytesleft; | ||
101 | bytesleft = PAGE_SIZE; | ||
102 | } | ||
103 | } | ||
89 | 104 | ||
90 | /* | 105 | /* |
91 | * dma_map_single can be passed any memory address, and there appear | 106 | * dma_map_single can be passed any memory address, and there appear |
@@ -97,26 +112,12 @@ EXPORT_SYMBOL(dma_free_coherent); | |||
97 | dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, | 112 | dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, |
98 | enum dma_data_direction direction) | 113 | enum dma_data_direction direction) |
99 | { | 114 | { |
100 | struct page *page; | 115 | dma_addr_t dma_addr = __pa(ptr); |
101 | dma_addr_t dma_addr; | ||
102 | int thispage; | ||
103 | 116 | ||
104 | BUG_ON(!valid_dma_direction(direction)); | 117 | BUG_ON(!valid_dma_direction(direction)); |
105 | WARN_ON(size == 0); | 118 | WARN_ON(size == 0); |
106 | 119 | ||
107 | dma_addr = __pa(ptr); | 120 | __dma_map_pa_range(dma_addr, size); |
108 | |||
109 | /* We might have been handed a buffer that wraps a page boundary */ | ||
110 | while ((int)size > 0) { | ||
111 | /* The amount to flush that's on this page */ | ||
112 | thispage = PAGE_SIZE - ((unsigned long)ptr & (PAGE_SIZE - 1)); | ||
113 | thispage = min((int)thispage, (int)size); | ||
114 | /* Is this valid for any page we could be handed? */ | ||
115 | page = pfn_to_page(kaddr_to_pfn(ptr)); | ||
116 | homecache_flush_cache(page, 0); | ||
117 | ptr += thispage; | ||
118 | size -= thispage; | ||
119 | } | ||
120 | 121 | ||
121 | return dma_addr; | 122 | return dma_addr; |
122 | } | 123 | } |
@@ -140,10 +141,8 @@ int dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents, | |||
140 | WARN_ON(nents == 0 || sglist->length == 0); | 141 | WARN_ON(nents == 0 || sglist->length == 0); |
141 | 142 | ||
142 | for_each_sg(sglist, sg, nents, i) { | 143 | for_each_sg(sglist, sg, nents, i) { |
143 | struct page *page; | ||
144 | sg->dma_address = sg_phys(sg); | 144 | sg->dma_address = sg_phys(sg); |
145 | page = pfn_to_page(sg->dma_address >> PAGE_SHIFT); | 145 | __dma_map_pa_range(sg->dma_address, sg->length); |
146 | homecache_flush_cache(page, 0); | ||
147 | } | 146 | } |
148 | 147 | ||
149 | return nents; | 148 | return nents; |
@@ -163,6 +162,7 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page, | |||
163 | { | 162 | { |
164 | BUG_ON(!valid_dma_direction(direction)); | 163 | BUG_ON(!valid_dma_direction(direction)); |
165 | 164 | ||
165 | BUG_ON(offset + size > PAGE_SIZE); | ||
166 | homecache_flush_cache(page, 0); | 166 | homecache_flush_cache(page, 0); |
167 | 167 | ||
168 | return page_to_pa(page) + offset; | 168 | return page_to_pa(page) + offset; |
@@ -244,7 +244,7 @@ EXPORT_SYMBOL(dma_sync_single_range_for_device); | |||
244 | * dma_alloc_noncoherent() returns non-cacheable memory, so there's no | 244 | * dma_alloc_noncoherent() returns non-cacheable memory, so there's no |
245 | * need to do any flushing here. | 245 | * need to do any flushing here. |
246 | */ | 246 | */ |
247 | void dma_cache_sync(void *vaddr, size_t size, | 247 | void dma_cache_sync(struct device *dev, void *vaddr, size_t size, |
248 | enum dma_data_direction direction) | 248 | enum dma_data_direction direction) |
249 | { | 249 | { |
250 | } | 250 | } |
diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c new file mode 100644 index 000000000000..6d4cb5d7a9fd --- /dev/null +++ b/arch/tile/kernel/pci.c | |||
@@ -0,0 +1,647 @@ | |||
1 | /* | ||
2 | * Copyright 2011 Tilera Corporation. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation, version 2. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
11 | * NON INFRINGEMENT. See the GNU General Public License for | ||
12 | * more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/pci.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/capability.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/bootmem.h> | ||
24 | #include <linux/irq.h> | ||
25 | #include <linux/io.h> | ||
26 | #include <linux/uaccess.h> | ||
27 | |||
28 | #include <asm/processor.h> | ||
29 | #include <asm/sections.h> | ||
30 | #include <asm/byteorder.h> | ||
31 | #include <asm/hv_driver.h> | ||
32 | #include <hv/drv_pcie_rc_intf.h> | ||
33 | |||
34 | |||
35 | /* | ||
36 | * Initialization flow and process | ||
37 | * ------------------------------- | ||
38 | * | ||
39 | * This files contains the routines to search for PCI buses, | ||
40 | * enumerate the buses, and configure any attached devices. | ||
41 | * | ||
42 | * There are two entry points here: | ||
43 | * 1) tile_pci_init | ||
44 | * This sets up the pci_controller structs, and opens the | ||
45 | * FDs to the hypervisor. This is called from setup_arch() early | ||
46 | * in the boot process. | ||
47 | * 2) pcibios_init | ||
48 | * This probes the PCI bus(es) for any attached hardware. It's | ||
49 | * called by subsys_initcall. All of the real work is done by the | ||
50 | * generic Linux PCI layer. | ||
51 | * | ||
52 | */ | ||
53 | |||
54 | /* | ||
55 | * This flag tells if the platform is TILEmpower that needs | ||
56 | * special configuration for the PLX switch chip. | ||
57 | */ | ||
58 | int __write_once tile_plx_gen1; | ||
59 | |||
60 | static struct pci_controller controllers[TILE_NUM_PCIE]; | ||
61 | static int num_controllers; | ||
62 | static int pci_scan_flags[TILE_NUM_PCIE]; | ||
63 | |||
64 | static struct pci_ops tile_cfg_ops; | ||
65 | |||
66 | |||
67 | /* | ||
68 | * We don't need to worry about the alignment of resources. | ||
69 | */ | ||
70 | resource_size_t pcibios_align_resource(void *data, const struct resource *res, | ||
71 | resource_size_t size, resource_size_t align) | ||
72 | { | ||
73 | return res->start; | ||
74 | } | ||
75 | EXPORT_SYMBOL(pcibios_align_resource); | ||
76 | |||
77 | /* | ||
78 | * Open a FD to the hypervisor PCI device. | ||
79 | * | ||
80 | * controller_id is the controller number, config type is 0 or 1 for | ||
81 | * config0 or config1 operations. | ||
82 | */ | ||
83 | static int __devinit tile_pcie_open(int controller_id, int config_type) | ||
84 | { | ||
85 | char filename[32]; | ||
86 | int fd; | ||
87 | |||
88 | sprintf(filename, "pcie/%d/config%d", controller_id, config_type); | ||
89 | |||
90 | fd = hv_dev_open((HV_VirtAddr)filename, 0); | ||
91 | |||
92 | return fd; | ||
93 | } | ||
94 | |||
95 | |||
96 | /* | ||
97 | * Get the IRQ numbers from the HV and set up the handlers for them. | ||
98 | */ | ||
99 | static int __devinit tile_init_irqs(int controller_id, | ||
100 | struct pci_controller *controller) | ||
101 | { | ||
102 | char filename[32]; | ||
103 | int fd; | ||
104 | int ret; | ||
105 | int x; | ||
106 | struct pcie_rc_config rc_config; | ||
107 | |||
108 | sprintf(filename, "pcie/%d/ctl", controller_id); | ||
109 | fd = hv_dev_open((HV_VirtAddr)filename, 0); | ||
110 | if (fd < 0) { | ||
111 | pr_err("PCI: hv_dev_open(%s) failed\n", filename); | ||
112 | return -1; | ||
113 | } | ||
114 | ret = hv_dev_pread(fd, 0, (HV_VirtAddr)(&rc_config), | ||
115 | sizeof(rc_config), PCIE_RC_CONFIG_MASK_OFF); | ||
116 | hv_dev_close(fd); | ||
117 | if (ret != sizeof(rc_config)) { | ||
118 | pr_err("PCI: wanted %zd bytes, got %d\n", | ||
119 | sizeof(rc_config), ret); | ||
120 | return -1; | ||
121 | } | ||
122 | /* Record irq_base so that we can map INTx to IRQ # later. */ | ||
123 | controller->irq_base = rc_config.intr; | ||
124 | |||
125 | for (x = 0; x < 4; x++) | ||
126 | tile_irq_activate(rc_config.intr + x, | ||
127 | TILE_IRQ_HW_CLEAR); | ||
128 | |||
129 | if (rc_config.plx_gen1) | ||
130 | controller->plx_gen1 = 1; | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | * First initialization entry point, called from setup_arch(). | ||
137 | * | ||
138 | * Find valid controllers and fill in pci_controller structs for each | ||
139 | * of them. | ||
140 | * | ||
141 | * Returns the number of controllers discovered. | ||
142 | */ | ||
143 | int __devinit tile_pci_init(void) | ||
144 | { | ||
145 | int i; | ||
146 | |||
147 | pr_info("PCI: Searching for controllers...\n"); | ||
148 | |||
149 | /* Re-init number of PCIe controllers to support hot-plug feature. */ | ||
150 | num_controllers = 0; | ||
151 | |||
152 | /* Do any configuration we need before using the PCIe */ | ||
153 | |||
154 | for (i = 0; i < TILE_NUM_PCIE; i++) { | ||
155 | /* | ||
156 | * To see whether we need a real config op based on | ||
157 | * the results of pcibios_init(), to support PCIe hot-plug. | ||
158 | */ | ||
159 | if (pci_scan_flags[i] == 0) { | ||
160 | int hv_cfg_fd0 = -1; | ||
161 | int hv_cfg_fd1 = -1; | ||
162 | int hv_mem_fd = -1; | ||
163 | char name[32]; | ||
164 | struct pci_controller *controller; | ||
165 | |||
166 | /* | ||
167 | * Open the fd to the HV. If it fails then this | ||
168 | * device doesn't exist. | ||
169 | */ | ||
170 | hv_cfg_fd0 = tile_pcie_open(i, 0); | ||
171 | if (hv_cfg_fd0 < 0) | ||
172 | continue; | ||
173 | hv_cfg_fd1 = tile_pcie_open(i, 1); | ||
174 | if (hv_cfg_fd1 < 0) { | ||
175 | pr_err("PCI: Couldn't open config fd to HV " | ||
176 | "for controller %d\n", i); | ||
177 | goto err_cont; | ||
178 | } | ||
179 | |||
180 | sprintf(name, "pcie/%d/mem", i); | ||
181 | hv_mem_fd = hv_dev_open((HV_VirtAddr)name, 0); | ||
182 | if (hv_mem_fd < 0) { | ||
183 | pr_err("PCI: Could not open mem fd to HV!\n"); | ||
184 | goto err_cont; | ||
185 | } | ||
186 | |||
187 | pr_info("PCI: Found PCI controller #%d\n", i); | ||
188 | |||
189 | controller = &controllers[i]; | ||
190 | |||
191 | controller->index = i; | ||
192 | controller->hv_cfg_fd[0] = hv_cfg_fd0; | ||
193 | controller->hv_cfg_fd[1] = hv_cfg_fd1; | ||
194 | controller->hv_mem_fd = hv_mem_fd; | ||
195 | controller->first_busno = 0; | ||
196 | controller->last_busno = 0xff; | ||
197 | controller->ops = &tile_cfg_ops; | ||
198 | |||
199 | num_controllers++; | ||
200 | continue; | ||
201 | |||
202 | err_cont: | ||
203 | if (hv_cfg_fd0 >= 0) | ||
204 | hv_dev_close(hv_cfg_fd0); | ||
205 | if (hv_cfg_fd1 >= 0) | ||
206 | hv_dev_close(hv_cfg_fd1); | ||
207 | if (hv_mem_fd >= 0) | ||
208 | hv_dev_close(hv_mem_fd); | ||
209 | continue; | ||
210 | } | ||
211 | } | ||
212 | |||
213 | /* | ||
214 | * Before using the PCIe, see if we need to do any platform-specific | ||
215 | * configuration, such as the PLX switch Gen 1 issue on TILEmpower. | ||
216 | */ | ||
217 | for (i = 0; i < num_controllers; i++) { | ||
218 | struct pci_controller *controller = &controllers[i]; | ||
219 | |||
220 | if (controller->plx_gen1) | ||
221 | tile_plx_gen1 = 1; | ||
222 | } | ||
223 | |||
224 | return num_controllers; | ||
225 | } | ||
226 | |||
227 | /* | ||
228 | * (pin - 1) converts from the PCI standard's [1:4] convention to | ||
229 | * a normal [0:3] range. | ||
230 | */ | ||
231 | static int tile_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
232 | { | ||
233 | struct pci_controller *controller = | ||
234 | (struct pci_controller *)dev->sysdata; | ||
235 | return (pin - 1) + controller->irq_base; | ||
236 | } | ||
237 | |||
238 | |||
239 | static void __devinit fixup_read_and_payload_sizes(void) | ||
240 | { | ||
241 | struct pci_dev *dev = NULL; | ||
242 | int smallest_max_payload = 0x1; /* Tile maxes out at 256 bytes. */ | ||
243 | int max_read_size = 0x2; /* Limit to 512 byte reads. */ | ||
244 | u16 new_values; | ||
245 | |||
246 | /* Scan for the smallest maximum payload size. */ | ||
247 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | ||
248 | int pcie_caps_offset; | ||
249 | u32 devcap; | ||
250 | int max_payload; | ||
251 | |||
252 | pcie_caps_offset = pci_find_capability(dev, PCI_CAP_ID_EXP); | ||
253 | if (pcie_caps_offset == 0) | ||
254 | continue; | ||
255 | |||
256 | pci_read_config_dword(dev, pcie_caps_offset + PCI_EXP_DEVCAP, | ||
257 | &devcap); | ||
258 | max_payload = devcap & PCI_EXP_DEVCAP_PAYLOAD; | ||
259 | if (max_payload < smallest_max_payload) | ||
260 | smallest_max_payload = max_payload; | ||
261 | } | ||
262 | |||
263 | /* Now, set the max_payload_size for all devices to that value. */ | ||
264 | new_values = (max_read_size << 12) | (smallest_max_payload << 5); | ||
265 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | ||
266 | int pcie_caps_offset; | ||
267 | u16 devctl; | ||
268 | |||
269 | pcie_caps_offset = pci_find_capability(dev, PCI_CAP_ID_EXP); | ||
270 | if (pcie_caps_offset == 0) | ||
271 | continue; | ||
272 | |||
273 | pci_read_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL, | ||
274 | &devctl); | ||
275 | devctl &= ~(PCI_EXP_DEVCTL_PAYLOAD | PCI_EXP_DEVCTL_READRQ); | ||
276 | devctl |= new_values; | ||
277 | pci_write_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL, | ||
278 | devctl); | ||
279 | } | ||
280 | } | ||
281 | |||
282 | |||
283 | /* | ||
284 | * Second PCI initialization entry point, called by subsys_initcall. | ||
285 | * | ||
286 | * The controllers have been set up by the time we get here, by a call to | ||
287 | * tile_pci_init. | ||
288 | */ | ||
289 | int __devinit pcibios_init(void) | ||
290 | { | ||
291 | int i; | ||
292 | |||
293 | pr_info("PCI: Probing PCI hardware\n"); | ||
294 | |||
295 | /* | ||
296 | * Delay a bit in case devices aren't ready. Some devices are | ||
297 | * known to require at least 20ms here, but we use a more | ||
298 | * conservative value. | ||
299 | */ | ||
300 | mdelay(250); | ||
301 | |||
302 | /* Scan all of the recorded PCI controllers. */ | ||
303 | for (i = 0; i < TILE_NUM_PCIE; i++) { | ||
304 | /* | ||
305 | * Do real pcibios init ops if the controller is initialized | ||
306 | * by tile_pci_init() successfully and not initialized by | ||
307 | * pcibios_init() yet to support PCIe hot-plug. | ||
308 | */ | ||
309 | if (pci_scan_flags[i] == 0 && controllers[i].ops != NULL) { | ||
310 | struct pci_controller *controller = &controllers[i]; | ||
311 | struct pci_bus *bus; | ||
312 | |||
313 | if (tile_init_irqs(i, controller)) { | ||
314 | pr_err("PCI: Could not initialize IRQs\n"); | ||
315 | continue; | ||
316 | } | ||
317 | |||
318 | pr_info("PCI: initializing controller #%d\n", i); | ||
319 | |||
320 | /* | ||
321 | * This comes from the generic Linux PCI driver. | ||
322 | * | ||
323 | * It reads the PCI tree for this bus into the Linux | ||
324 | * data structures. | ||
325 | * | ||
326 | * This is inlined in linux/pci.h and calls into | ||
327 | * pci_scan_bus_parented() in probe.c. | ||
328 | */ | ||
329 | bus = pci_scan_bus(0, controller->ops, controller); | ||
330 | controller->root_bus = bus; | ||
331 | controller->last_busno = bus->subordinate; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | /* Do machine dependent PCI interrupt routing */ | ||
336 | pci_fixup_irqs(pci_common_swizzle, tile_map_irq); | ||
337 | |||
338 | /* | ||
339 | * This comes from the generic Linux PCI driver. | ||
340 | * | ||
341 | * It allocates all of the resources (I/O memory, etc) | ||
342 | * associated with the devices read in above. | ||
343 | */ | ||
344 | pci_assign_unassigned_resources(); | ||
345 | |||
346 | /* Configure the max_read_size and max_payload_size values. */ | ||
347 | fixup_read_and_payload_sizes(); | ||
348 | |||
349 | /* Record the I/O resources in the PCI controller structure. */ | ||
350 | for (i = 0; i < TILE_NUM_PCIE; i++) { | ||
351 | /* | ||
352 | * Do real pcibios init ops if the controller is initialized | ||
353 | * by tile_pci_init() successfully and not initialized by | ||
354 | * pcibios_init() yet to support PCIe hot-plug. | ||
355 | */ | ||
356 | if (pci_scan_flags[i] == 0 && controllers[i].ops != NULL) { | ||
357 | struct pci_bus *root_bus = controllers[i].root_bus; | ||
358 | struct pci_bus *next_bus; | ||
359 | struct pci_dev *dev; | ||
360 | |||
361 | list_for_each_entry(dev, &root_bus->devices, bus_list) { | ||
362 | /* | ||
363 | * Find the PCI host controller, ie. the 1st | ||
364 | * bridge. | ||
365 | */ | ||
366 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && | ||
367 | (PCI_SLOT(dev->devfn) == 0)) { | ||
368 | next_bus = dev->subordinate; | ||
369 | controllers[i].mem_resources[0] = | ||
370 | *next_bus->resource[0]; | ||
371 | controllers[i].mem_resources[1] = | ||
372 | *next_bus->resource[1]; | ||
373 | controllers[i].mem_resources[2] = | ||
374 | *next_bus->resource[2]; | ||
375 | |||
376 | /* Setup flags. */ | ||
377 | pci_scan_flags[i] = 1; | ||
378 | |||
379 | break; | ||
380 | } | ||
381 | } | ||
382 | } | ||
383 | } | ||
384 | |||
385 | return 0; | ||
386 | } | ||
387 | subsys_initcall(pcibios_init); | ||
388 | |||
389 | /* | ||
390 | * No bus fixups needed. | ||
391 | */ | ||
392 | void __devinit pcibios_fixup_bus(struct pci_bus *bus) | ||
393 | { | ||
394 | /* Nothing needs to be done. */ | ||
395 | } | ||
396 | |||
397 | /* | ||
398 | * This can be called from the generic PCI layer, but doesn't need to | ||
399 | * do anything. | ||
400 | */ | ||
401 | char __devinit *pcibios_setup(char *str) | ||
402 | { | ||
403 | /* Nothing needs to be done. */ | ||
404 | return str; | ||
405 | } | ||
406 | |||
407 | /* | ||
408 | * This is called from the generic Linux layer. | ||
409 | */ | ||
410 | void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) | ||
411 | { | ||
412 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); | ||
413 | } | ||
414 | |||
415 | /* | ||
416 | * Enable memory and/or address decoding, as appropriate, for the | ||
417 | * device described by the 'dev' struct. | ||
418 | * | ||
419 | * This is called from the generic PCI layer, and can be called | ||
420 | * for bridges or endpoints. | ||
421 | */ | ||
422 | int pcibios_enable_device(struct pci_dev *dev, int mask) | ||
423 | { | ||
424 | u16 cmd, old_cmd; | ||
425 | u8 header_type; | ||
426 | int i; | ||
427 | struct resource *r; | ||
428 | |||
429 | pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); | ||
430 | |||
431 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
432 | old_cmd = cmd; | ||
433 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { | ||
434 | /* | ||
435 | * For bridges, we enable both memory and I/O decoding | ||
436 | * in call cases. | ||
437 | */ | ||
438 | cmd |= PCI_COMMAND_IO; | ||
439 | cmd |= PCI_COMMAND_MEMORY; | ||
440 | } else { | ||
441 | /* | ||
442 | * For endpoints, we enable memory and/or I/O decoding | ||
443 | * only if they have a memory resource of that type. | ||
444 | */ | ||
445 | for (i = 0; i < 6; i++) { | ||
446 | r = &dev->resource[i]; | ||
447 | if (r->flags & IORESOURCE_UNSET) { | ||
448 | pr_err("PCI: Device %s not available " | ||
449 | "because of resource collisions\n", | ||
450 | pci_name(dev)); | ||
451 | return -EINVAL; | ||
452 | } | ||
453 | if (r->flags & IORESOURCE_IO) | ||
454 | cmd |= PCI_COMMAND_IO; | ||
455 | if (r->flags & IORESOURCE_MEM) | ||
456 | cmd |= PCI_COMMAND_MEMORY; | ||
457 | } | ||
458 | } | ||
459 | |||
460 | /* | ||
461 | * We only write the command if it changed. | ||
462 | */ | ||
463 | if (cmd != old_cmd) | ||
464 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max) | ||
469 | { | ||
470 | unsigned long start = pci_resource_start(dev, bar); | ||
471 | unsigned long len = pci_resource_len(dev, bar); | ||
472 | unsigned long flags = pci_resource_flags(dev, bar); | ||
473 | |||
474 | if (!len) | ||
475 | return NULL; | ||
476 | if (max && len > max) | ||
477 | len = max; | ||
478 | |||
479 | if (!(flags & IORESOURCE_MEM)) { | ||
480 | pr_info("PCI: Trying to map invalid resource %#lx\n", flags); | ||
481 | start = 0; | ||
482 | } | ||
483 | |||
484 | return (void __iomem *)start; | ||
485 | } | ||
486 | EXPORT_SYMBOL(pci_iomap); | ||
487 | |||
488 | |||
489 | /**************************************************************** | ||
490 | * | ||
491 | * Tile PCI config space read/write routines | ||
492 | * | ||
493 | ****************************************************************/ | ||
494 | |||
495 | /* | ||
496 | * These are the normal read and write ops | ||
497 | * These are expanded with macros from pci_bus_read_config_byte() etc. | ||
498 | * | ||
499 | * devfn is the combined PCI slot & function. | ||
500 | * | ||
501 | * offset is in bytes, from the start of config space for the | ||
502 | * specified bus & slot. | ||
503 | */ | ||
504 | |||
505 | static int __devinit tile_cfg_read(struct pci_bus *bus, | ||
506 | unsigned int devfn, | ||
507 | int offset, | ||
508 | int size, | ||
509 | u32 *val) | ||
510 | { | ||
511 | struct pci_controller *controller = bus->sysdata; | ||
512 | int busnum = bus->number & 0xff; | ||
513 | int slot = (devfn >> 3) & 0x1f; | ||
514 | int function = devfn & 0x7; | ||
515 | u32 addr; | ||
516 | int config_mode = 1; | ||
517 | |||
518 | /* | ||
519 | * There is no bridge between the Tile and bus 0, so we | ||
520 | * use config0 to talk to bus 0. | ||
521 | * | ||
522 | * If we're talking to a bus other than zero then we | ||
523 | * must have found a bridge. | ||
524 | */ | ||
525 | if (busnum == 0) { | ||
526 | /* | ||
527 | * We fake an empty slot for (busnum == 0) && (slot > 0), | ||
528 | * since there is only one slot on bus 0. | ||
529 | */ | ||
530 | if (slot) { | ||
531 | *val = 0xFFFFFFFF; | ||
532 | return 0; | ||
533 | } | ||
534 | config_mode = 0; | ||
535 | } | ||
536 | |||
537 | addr = busnum << 20; /* Bus in 27:20 */ | ||
538 | addr |= slot << 15; /* Slot (device) in 19:15 */ | ||
539 | addr |= function << 12; /* Function is in 14:12 */ | ||
540 | addr |= (offset & 0xFFF); /* byte address in 0:11 */ | ||
541 | |||
542 | return hv_dev_pread(controller->hv_cfg_fd[config_mode], 0, | ||
543 | (HV_VirtAddr)(val), size, addr); | ||
544 | } | ||
545 | |||
546 | |||
547 | /* | ||
548 | * See tile_cfg_read() for relevant comments. | ||
549 | * Note that "val" is the value to write, not a pointer to that value. | ||
550 | */ | ||
551 | static int __devinit tile_cfg_write(struct pci_bus *bus, | ||
552 | unsigned int devfn, | ||
553 | int offset, | ||
554 | int size, | ||
555 | u32 val) | ||
556 | { | ||
557 | struct pci_controller *controller = bus->sysdata; | ||
558 | int busnum = bus->number & 0xff; | ||
559 | int slot = (devfn >> 3) & 0x1f; | ||
560 | int function = devfn & 0x7; | ||
561 | u32 addr; | ||
562 | int config_mode = 1; | ||
563 | HV_VirtAddr valp = (HV_VirtAddr)&val; | ||
564 | |||
565 | /* | ||
566 | * For bus 0 slot 0 we use config 0 accesses. | ||
567 | */ | ||
568 | if (busnum == 0) { | ||
569 | /* | ||
570 | * We fake an empty slot for (busnum == 0) && (slot > 0), | ||
571 | * since there is only one slot on bus 0. | ||
572 | */ | ||
573 | if (slot) | ||
574 | return 0; | ||
575 | config_mode = 0; | ||
576 | } | ||
577 | |||
578 | addr = busnum << 20; /* Bus in 27:20 */ | ||
579 | addr |= slot << 15; /* Slot (device) in 19:15 */ | ||
580 | addr |= function << 12; /* Function is in 14:12 */ | ||
581 | addr |= (offset & 0xFFF); /* byte address in 0:11 */ | ||
582 | |||
583 | #ifdef __BIG_ENDIAN | ||
584 | /* Point to the correct part of the 32-bit "val". */ | ||
585 | valp += 4 - size; | ||
586 | #endif | ||
587 | |||
588 | return hv_dev_pwrite(controller->hv_cfg_fd[config_mode], 0, | ||
589 | valp, size, addr); | ||
590 | } | ||
591 | |||
592 | |||
593 | static struct pci_ops tile_cfg_ops = { | ||
594 | .read = tile_cfg_read, | ||
595 | .write = tile_cfg_write, | ||
596 | }; | ||
597 | |||
598 | |||
599 | /* | ||
600 | * In the following, each PCI controller's mem_resources[1] | ||
601 | * represents its (non-prefetchable) PCI memory resource. | ||
602 | * mem_resources[0] and mem_resources[2] refer to its PCI I/O and | ||
603 | * prefetchable PCI memory resources, respectively. | ||
604 | * For more details, see pci_setup_bridge() in setup-bus.c. | ||
605 | * By comparing the target PCI memory address against the | ||
606 | * end address of controller 0, we can determine the controller | ||
607 | * that should accept the PCI memory access. | ||
608 | */ | ||
609 | #define TILE_READ(size, type) \ | ||
610 | type _tile_read##size(unsigned long addr) \ | ||
611 | { \ | ||
612 | type val; \ | ||
613 | int idx = 0; \ | ||
614 | if (addr > controllers[0].mem_resources[1].end && \ | ||
615 | addr > controllers[0].mem_resources[2].end) \ | ||
616 | idx = 1; \ | ||
617 | if (hv_dev_pread(controllers[idx].hv_mem_fd, 0, \ | ||
618 | (HV_VirtAddr)(&val), sizeof(type), addr)) \ | ||
619 | pr_err("PCI: read %zd bytes at 0x%lX failed\n", \ | ||
620 | sizeof(type), addr); \ | ||
621 | return val; \ | ||
622 | } \ | ||
623 | EXPORT_SYMBOL(_tile_read##size) | ||
624 | |||
625 | TILE_READ(b, u8); | ||
626 | TILE_READ(w, u16); | ||
627 | TILE_READ(l, u32); | ||
628 | TILE_READ(q, u64); | ||
629 | |||
630 | #define TILE_WRITE(size, type) \ | ||
631 | void _tile_write##size(type val, unsigned long addr) \ | ||
632 | { \ | ||
633 | int idx = 0; \ | ||
634 | if (addr > controllers[0].mem_resources[1].end && \ | ||
635 | addr > controllers[0].mem_resources[2].end) \ | ||
636 | idx = 1; \ | ||
637 | if (hv_dev_pwrite(controllers[idx].hv_mem_fd, 0, \ | ||
638 | (HV_VirtAddr)(&val), sizeof(type), addr)) \ | ||
639 | pr_err("PCI: write %zd bytes at 0x%lX failed\n", \ | ||
640 | sizeof(type), addr); \ | ||
641 | } \ | ||
642 | EXPORT_SYMBOL(_tile_write##size) | ||
643 | |||
644 | TILE_WRITE(b, u8); | ||
645 | TILE_WRITE(w, u16); | ||
646 | TILE_WRITE(l, u32); | ||
647 | TILE_WRITE(q, u64); | ||
diff --git a/arch/tile/kernel/proc.c b/arch/tile/kernel/proc.c index 2e02c41ddf3b..62d820833c68 100644 --- a/arch/tile/kernel/proc.c +++ b/arch/tile/kernel/proc.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <asm/processor.h> | 27 | #include <asm/processor.h> |
28 | #include <asm/sections.h> | 28 | #include <asm/sections.h> |
29 | #include <asm/homecache.h> | 29 | #include <asm/homecache.h> |
30 | #include <asm/hardwall.h> | ||
30 | #include <arch/chip.h> | 31 | #include <arch/chip.h> |
31 | 32 | ||
32 | 33 | ||
@@ -88,3 +89,75 @@ const struct seq_operations cpuinfo_op = { | |||
88 | .stop = c_stop, | 89 | .stop = c_stop, |
89 | .show = show_cpuinfo, | 90 | .show = show_cpuinfo, |
90 | }; | 91 | }; |
92 | |||
93 | /* | ||
94 | * Support /proc/tile directory | ||
95 | */ | ||
96 | |||
97 | static int __init proc_tile_init(void) | ||
98 | { | ||
99 | struct proc_dir_entry *root = proc_mkdir("tile", NULL); | ||
100 | if (root == NULL) | ||
101 | return 0; | ||
102 | |||
103 | proc_tile_hardwall_init(root); | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | arch_initcall(proc_tile_init); | ||
109 | |||
110 | /* | ||
111 | * Support /proc/sys/tile directory | ||
112 | */ | ||
113 | |||
114 | #ifndef __tilegx__ /* FIXME: GX: no support for unaligned access yet */ | ||
115 | static ctl_table unaligned_subtable[] = { | ||
116 | { | ||
117 | .procname = "enabled", | ||
118 | .data = &unaligned_fixup, | ||
119 | .maxlen = sizeof(int), | ||
120 | .mode = 0644, | ||
121 | .proc_handler = &proc_dointvec | ||
122 | }, | ||
123 | { | ||
124 | .procname = "printk", | ||
125 | .data = &unaligned_printk, | ||
126 | .maxlen = sizeof(int), | ||
127 | .mode = 0644, | ||
128 | .proc_handler = &proc_dointvec | ||
129 | }, | ||
130 | { | ||
131 | .procname = "count", | ||
132 | .data = &unaligned_fixup_count, | ||
133 | .maxlen = sizeof(int), | ||
134 | .mode = 0644, | ||
135 | .proc_handler = &proc_dointvec | ||
136 | }, | ||
137 | {} | ||
138 | }; | ||
139 | |||
140 | static ctl_table unaligned_table[] = { | ||
141 | { | ||
142 | .procname = "unaligned_fixup", | ||
143 | .mode = 0555, | ||
144 | .child = unaligned_subtable | ||
145 | }, | ||
146 | {} | ||
147 | }; | ||
148 | #endif | ||
149 | |||
150 | static struct ctl_path tile_path[] = { | ||
151 | { .procname = "tile" }, | ||
152 | { } | ||
153 | }; | ||
154 | |||
155 | static int __init proc_sys_tile_init(void) | ||
156 | { | ||
157 | #ifndef __tilegx__ /* FIXME: GX: no support for unaligned access yet */ | ||
158 | register_sysctl_paths(tile_path, unaligned_table); | ||
159 | #endif | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | arch_initcall(proc_sys_tile_init); | ||
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 84c29111756c..9c45d8bbdf57 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c | |||
@@ -25,10 +25,13 @@ | |||
25 | #include <linux/hardirq.h> | 25 | #include <linux/hardirq.h> |
26 | #include <linux/syscalls.h> | 26 | #include <linux/syscalls.h> |
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/tracehook.h> | ||
29 | #include <linux/signal.h> | ||
28 | #include <asm/system.h> | 30 | #include <asm/system.h> |
29 | #include <asm/stack.h> | 31 | #include <asm/stack.h> |
30 | #include <asm/homecache.h> | 32 | #include <asm/homecache.h> |
31 | #include <asm/syscalls.h> | 33 | #include <asm/syscalls.h> |
34 | #include <asm/traps.h> | ||
32 | #ifdef CONFIG_HARDWALL | 35 | #ifdef CONFIG_HARDWALL |
33 | #include <asm/hardwall.h> | 36 | #include <asm/hardwall.h> |
34 | #endif | 37 | #endif |
@@ -109,7 +112,7 @@ void cpu_idle(void) | |||
109 | } | 112 | } |
110 | } | 113 | } |
111 | 114 | ||
112 | struct thread_info *alloc_thread_info(struct task_struct *task) | 115 | struct thread_info *alloc_thread_info_node(struct task_struct *task, int node) |
113 | { | 116 | { |
114 | struct page *page; | 117 | struct page *page; |
115 | gfp_t flags = GFP_KERNEL; | 118 | gfp_t flags = GFP_KERNEL; |
@@ -118,7 +121,7 @@ struct thread_info *alloc_thread_info(struct task_struct *task) | |||
118 | flags |= __GFP_ZERO; | 121 | flags |= __GFP_ZERO; |
119 | #endif | 122 | #endif |
120 | 123 | ||
121 | page = alloc_pages(flags, THREAD_SIZE_ORDER); | 124 | page = alloc_pages_node(node, flags, THREAD_SIZE_ORDER); |
122 | if (!page) | 125 | if (!page) |
123 | return NULL; | 126 | return NULL; |
124 | 127 | ||
@@ -165,7 +168,7 @@ void free_thread_info(struct thread_info *info) | |||
165 | kfree(step_state); | 168 | kfree(step_state); |
166 | } | 169 | } |
167 | 170 | ||
168 | free_page((unsigned long)info); | 171 | free_pages((unsigned long)info, THREAD_SIZE_ORDER); |
169 | } | 172 | } |
170 | 173 | ||
171 | static void save_arch_state(struct thread_struct *t); | 174 | static void save_arch_state(struct thread_struct *t); |
@@ -212,11 +215,19 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
212 | childregs->sp = sp; /* override with new user stack pointer */ | 215 | childregs->sp = sp; /* override with new user stack pointer */ |
213 | 216 | ||
214 | /* | 217 | /* |
218 | * If CLONE_SETTLS is set, set "tp" in the new task to "r4", | ||
219 | * which is passed in as arg #5 to sys_clone(). | ||
220 | */ | ||
221 | if (clone_flags & CLONE_SETTLS) | ||
222 | childregs->tp = regs->regs[4]; | ||
223 | |||
224 | /* | ||
215 | * Copy the callee-saved registers from the passed pt_regs struct | 225 | * Copy the callee-saved registers from the passed pt_regs struct |
216 | * into the context-switch callee-saved registers area. | 226 | * into the context-switch callee-saved registers area. |
217 | * We have to restore the callee-saved registers since we may | 227 | * This way when we start the interrupt-return sequence, the |
218 | * be cloning a userspace task with userspace register state, | 228 | * callee-save registers will be correctly in registers, which |
219 | * and we won't be unwinding the same kernel frames to restore them. | 229 | * is how we assume the compiler leaves them as we start doing |
230 | * the normal return-from-interrupt path after calling C code. | ||
220 | * Zero out the C ABI save area to mark the top of the stack. | 231 | * Zero out the C ABI save area to mark the top of the stack. |
221 | */ | 232 | */ |
222 | ksp = (unsigned long) childregs; | 233 | ksp = (unsigned long) childregs; |
@@ -304,15 +315,25 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) | |||
304 | /* Allow user processes to access the DMA SPRs */ | 315 | /* Allow user processes to access the DMA SPRs */ |
305 | void grant_dma_mpls(void) | 316 | void grant_dma_mpls(void) |
306 | { | 317 | { |
318 | #if CONFIG_KERNEL_PL == 2 | ||
319 | __insn_mtspr(SPR_MPL_DMA_CPL_SET_1, 1); | ||
320 | __insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_1, 1); | ||
321 | #else | ||
307 | __insn_mtspr(SPR_MPL_DMA_CPL_SET_0, 1); | 322 | __insn_mtspr(SPR_MPL_DMA_CPL_SET_0, 1); |
308 | __insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_0, 1); | 323 | __insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_0, 1); |
324 | #endif | ||
309 | } | 325 | } |
310 | 326 | ||
311 | /* Forbid user processes from accessing the DMA SPRs */ | 327 | /* Forbid user processes from accessing the DMA SPRs */ |
312 | void restrict_dma_mpls(void) | 328 | void restrict_dma_mpls(void) |
313 | { | 329 | { |
330 | #if CONFIG_KERNEL_PL == 2 | ||
331 | __insn_mtspr(SPR_MPL_DMA_CPL_SET_2, 1); | ||
332 | __insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_2, 1); | ||
333 | #else | ||
314 | __insn_mtspr(SPR_MPL_DMA_CPL_SET_1, 1); | 334 | __insn_mtspr(SPR_MPL_DMA_CPL_SET_1, 1); |
315 | __insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_1, 1); | 335 | __insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_1, 1); |
336 | #endif | ||
316 | } | 337 | } |
317 | 338 | ||
318 | /* Pause the DMA engine, then save off its state registers. */ | 339 | /* Pause the DMA engine, then save off its state registers. */ |
@@ -523,19 +544,60 @@ struct task_struct *__sched _switch_to(struct task_struct *prev, | |||
523 | * Switch kernel SP, PC, and callee-saved registers. | 544 | * Switch kernel SP, PC, and callee-saved registers. |
524 | * In the context of the new task, return the old task pointer | 545 | * In the context of the new task, return the old task pointer |
525 | * (i.e. the task that actually called __switch_to). | 546 | * (i.e. the task that actually called __switch_to). |
526 | * Pass the value to use for SYSTEM_SAVE_1_0 when we reset our sp. | 547 | * Pass the value to use for SYSTEM_SAVE_K_0 when we reset our sp. |
527 | */ | 548 | */ |
528 | return __switch_to(prev, next, next_current_ksp0(next)); | 549 | return __switch_to(prev, next, next_current_ksp0(next)); |
529 | } | 550 | } |
530 | 551 | ||
531 | long _sys_fork(struct pt_regs *regs) | 552 | /* |
553 | * This routine is called on return from interrupt if any of the | ||
554 | * TIF_WORK_MASK flags are set in thread_info->flags. It is | ||
555 | * entered with interrupts disabled so we don't miss an event | ||
556 | * that modified the thread_info flags. If any flag is set, we | ||
557 | * handle it and return, and the calling assembly code will | ||
558 | * re-disable interrupts, reload the thread flags, and call back | ||
559 | * if more flags need to be handled. | ||
560 | * | ||
561 | * We return whether we need to check the thread_info flags again | ||
562 | * or not. Note that we don't clear TIF_SINGLESTEP here, so it's | ||
563 | * important that it be tested last, and then claim that we don't | ||
564 | * need to recheck the flags. | ||
565 | */ | ||
566 | int do_work_pending(struct pt_regs *regs, u32 thread_info_flags) | ||
532 | { | 567 | { |
533 | return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL); | 568 | if (thread_info_flags & _TIF_NEED_RESCHED) { |
569 | schedule(); | ||
570 | return 1; | ||
571 | } | ||
572 | #if CHIP_HAS_TILE_DMA() || CHIP_HAS_SN_PROC() | ||
573 | if (thread_info_flags & _TIF_ASYNC_TLB) { | ||
574 | do_async_page_fault(regs); | ||
575 | return 1; | ||
576 | } | ||
577 | #endif | ||
578 | if (thread_info_flags & _TIF_SIGPENDING) { | ||
579 | do_signal(regs); | ||
580 | return 1; | ||
581 | } | ||
582 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | ||
583 | clear_thread_flag(TIF_NOTIFY_RESUME); | ||
584 | tracehook_notify_resume(regs); | ||
585 | if (current->replacement_session_keyring) | ||
586 | key_replace_session_keyring(); | ||
587 | return 1; | ||
588 | } | ||
589 | if (thread_info_flags & _TIF_SINGLESTEP) { | ||
590 | if ((regs->ex1 & SPR_EX_CONTEXT_1_1__PL_MASK) == 0) | ||
591 | single_step_once(regs); | ||
592 | return 0; | ||
593 | } | ||
594 | panic("work_pending: bad flags %#x\n", thread_info_flags); | ||
534 | } | 595 | } |
535 | 596 | ||
536 | long _sys_clone(unsigned long clone_flags, unsigned long newsp, | 597 | /* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */ |
537 | void __user *parent_tidptr, void __user *child_tidptr, | 598 | SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, |
538 | struct pt_regs *regs) | 599 | void __user *, parent_tidptr, void __user *, child_tidptr, |
600 | struct pt_regs *, regs) | ||
539 | { | 601 | { |
540 | if (!newsp) | 602 | if (!newsp) |
541 | newsp = regs->sp; | 603 | newsp = regs->sp; |
@@ -543,18 +605,13 @@ long _sys_clone(unsigned long clone_flags, unsigned long newsp, | |||
543 | parent_tidptr, child_tidptr); | 605 | parent_tidptr, child_tidptr); |
544 | } | 606 | } |
545 | 607 | ||
546 | long _sys_vfork(struct pt_regs *regs) | ||
547 | { | ||
548 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, | ||
549 | regs, 0, NULL, NULL); | ||
550 | } | ||
551 | |||
552 | /* | 608 | /* |
553 | * sys_execve() executes a new program. | 609 | * sys_execve() executes a new program. |
554 | */ | 610 | */ |
555 | long _sys_execve(const char __user *path, | 611 | SYSCALL_DEFINE4(execve, const char __user *, path, |
556 | const char __user *const __user *argv, | 612 | const char __user *const __user *, argv, |
557 | const char __user *const __user *envp, struct pt_regs *regs) | 613 | const char __user *const __user *, envp, |
614 | struct pt_regs *, regs) | ||
558 | { | 615 | { |
559 | long error; | 616 | long error; |
560 | char *filename; | 617 | char *filename; |
@@ -565,14 +622,17 @@ long _sys_execve(const char __user *path, | |||
565 | goto out; | 622 | goto out; |
566 | error = do_execve(filename, argv, envp, regs); | 623 | error = do_execve(filename, argv, envp, regs); |
567 | putname(filename); | 624 | putname(filename); |
625 | if (error == 0) | ||
626 | single_step_execve(); | ||
568 | out: | 627 | out: |
569 | return error; | 628 | return error; |
570 | } | 629 | } |
571 | 630 | ||
572 | #ifdef CONFIG_COMPAT | 631 | #ifdef CONFIG_COMPAT |
573 | long _compat_sys_execve(const char __user *path, | 632 | long compat_sys_execve(const char __user *path, |
574 | const compat_uptr_t __user *argv, | 633 | compat_uptr_t __user *argv, |
575 | const compat_uptr_t __user *envp, struct pt_regs *regs) | 634 | compat_uptr_t __user *envp, |
635 | struct pt_regs *regs) | ||
576 | { | 636 | { |
577 | long error; | 637 | long error; |
578 | char *filename; | 638 | char *filename; |
@@ -583,6 +643,8 @@ long _compat_sys_execve(const char __user *path, | |||
583 | goto out; | 643 | goto out; |
584 | error = compat_do_execve(filename, argv, envp, regs); | 644 | error = compat_do_execve(filename, argv, envp, regs); |
585 | putname(filename); | 645 | putname(filename); |
646 | if (error == 0) | ||
647 | single_step_execve(); | ||
586 | out: | 648 | out: |
587 | return error; | 649 | return error; |
588 | } | 650 | } |
diff --git a/arch/tile/kernel/ptrace.c b/arch/tile/kernel/ptrace.c index 7161bd03d2fd..e92e40527d6d 100644 --- a/arch/tile/kernel/ptrace.c +++ b/arch/tile/kernel/ptrace.c | |||
@@ -32,25 +32,6 @@ void user_disable_single_step(struct task_struct *child) | |||
32 | } | 32 | } |
33 | 33 | ||
34 | /* | 34 | /* |
35 | * This routine will put a word on the process's privileged stack. | ||
36 | */ | ||
37 | static void putreg(struct task_struct *task, | ||
38 | unsigned long addr, unsigned long value) | ||
39 | { | ||
40 | unsigned int regno = addr / sizeof(unsigned long); | ||
41 | struct pt_regs *childregs = task_pt_regs(task); | ||
42 | childregs->regs[regno] = value; | ||
43 | childregs->flags |= PT_FLAGS_RESTORE_REGS; | ||
44 | } | ||
45 | |||
46 | static unsigned long getreg(struct task_struct *task, unsigned long addr) | ||
47 | { | ||
48 | unsigned int regno = addr / sizeof(unsigned long); | ||
49 | struct pt_regs *childregs = task_pt_regs(task); | ||
50 | return childregs->regs[regno]; | ||
51 | } | ||
52 | |||
53 | /* | ||
54 | * Called by kernel/ptrace.c when detaching.. | 35 | * Called by kernel/ptrace.c when detaching.. |
55 | */ | 36 | */ |
56 | void ptrace_disable(struct task_struct *child) | 37 | void ptrace_disable(struct task_struct *child) |
@@ -64,61 +45,80 @@ void ptrace_disable(struct task_struct *child) | |||
64 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 45 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
65 | } | 46 | } |
66 | 47 | ||
67 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 48 | long arch_ptrace(struct task_struct *child, long request, |
49 | unsigned long addr, unsigned long data) | ||
68 | { | 50 | { |
69 | unsigned long __user *datap; | 51 | unsigned long __user *datap = (long __user __force *)data; |
70 | unsigned long tmp; | 52 | unsigned long tmp; |
71 | int i; | ||
72 | long ret = -EIO; | 53 | long ret = -EIO; |
73 | 54 | char *childreg; | |
74 | #ifdef CONFIG_COMPAT | 55 | struct pt_regs copyregs; |
75 | if (task_thread_info(current)->status & TS_COMPAT) | 56 | int ex1_offset; |
76 | data = (u32)data; | ||
77 | if (task_thread_info(child)->status & TS_COMPAT) | ||
78 | addr = (u32)addr; | ||
79 | #endif | ||
80 | datap = (unsigned long __user __force *)data; | ||
81 | 57 | ||
82 | switch (request) { | 58 | switch (request) { |
83 | 59 | ||
84 | case PTRACE_PEEKUSR: /* Read register from pt_regs. */ | 60 | case PTRACE_PEEKUSR: /* Read register from pt_regs. */ |
85 | if (addr & (sizeof(data)-1)) | 61 | if (addr >= PTREGS_SIZE) |
86 | break; | ||
87 | if (addr < 0 || addr >= PTREGS_SIZE) | ||
88 | break; | 62 | break; |
89 | tmp = getreg(child, addr); /* Read register */ | 63 | childreg = (char *)task_pt_regs(child) + addr; |
90 | ret = put_user(tmp, datap); | 64 | #ifdef CONFIG_COMPAT |
65 | if (is_compat_task()) { | ||
66 | if (addr & (sizeof(compat_long_t)-1)) | ||
67 | break; | ||
68 | ret = put_user(*(compat_long_t *)childreg, | ||
69 | (compat_long_t __user *)datap); | ||
70 | } else | ||
71 | #endif | ||
72 | { | ||
73 | if (addr & (sizeof(long)-1)) | ||
74 | break; | ||
75 | ret = put_user(*(long *)childreg, datap); | ||
76 | } | ||
91 | break; | 77 | break; |
92 | 78 | ||
93 | case PTRACE_POKEUSR: /* Write register in pt_regs. */ | 79 | case PTRACE_POKEUSR: /* Write register in pt_regs. */ |
94 | if (addr & (sizeof(data)-1)) | 80 | if (addr >= PTREGS_SIZE) |
95 | break; | 81 | break; |
96 | if (addr < 0 || addr >= PTREGS_SIZE) | 82 | childreg = (char *)task_pt_regs(child) + addr; |
97 | break; | 83 | |
98 | putreg(child, addr, data); /* Write register */ | 84 | /* Guard against overwrites of the privilege level. */ |
85 | ex1_offset = PTREGS_OFFSET_EX1; | ||
86 | #if defined(CONFIG_COMPAT) && defined(__BIG_ENDIAN) | ||
87 | if (is_compat_task()) /* point at low word */ | ||
88 | ex1_offset += sizeof(compat_long_t); | ||
89 | #endif | ||
90 | if (addr == ex1_offset) | ||
91 | data = PL_ICS_EX1(USER_PL, EX1_ICS(data)); | ||
92 | |||
93 | #ifdef CONFIG_COMPAT | ||
94 | if (is_compat_task()) { | ||
95 | if (addr & (sizeof(compat_long_t)-1)) | ||
96 | break; | ||
97 | *(compat_long_t *)childreg = data; | ||
98 | } else | ||
99 | #endif | ||
100 | { | ||
101 | if (addr & (sizeof(long)-1)) | ||
102 | break; | ||
103 | *(long *)childreg = data; | ||
104 | } | ||
99 | ret = 0; | 105 | ret = 0; |
100 | break; | 106 | break; |
101 | 107 | ||
102 | case PTRACE_GETREGS: /* Get all registers from the child. */ | 108 | case PTRACE_GETREGS: /* Get all registers from the child. */ |
103 | if (!access_ok(VERIFY_WRITE, datap, PTREGS_SIZE)) | 109 | if (copy_to_user(datap, task_pt_regs(child), |
104 | break; | 110 | sizeof(struct pt_regs)) == 0) { |
105 | for (i = 0; i < PTREGS_SIZE; i += sizeof(long)) { | 111 | ret = 0; |
106 | ret = __put_user(getreg(child, i), datap); | ||
107 | if (ret != 0) | ||
108 | break; | ||
109 | datap++; | ||
110 | } | 112 | } |
111 | break; | 113 | break; |
112 | 114 | ||
113 | case PTRACE_SETREGS: /* Set all registers in the child. */ | 115 | case PTRACE_SETREGS: /* Set all registers in the child. */ |
114 | if (!access_ok(VERIFY_READ, datap, PTREGS_SIZE)) | 116 | if (copy_from_user(©regs, datap, |
115 | break; | 117 | sizeof(struct pt_regs)) == 0) { |
116 | for (i = 0; i < PTREGS_SIZE; i += sizeof(long)) { | 118 | copyregs.ex1 = |
117 | ret = __get_user(tmp, datap); | 119 | PL_ICS_EX1(USER_PL, EX1_ICS(copyregs.ex1)); |
118 | if (ret != 0) | 120 | *task_pt_regs(child) = copyregs; |
119 | break; | 121 | ret = 0; |
120 | putreg(child, i, tmp); | ||
121 | datap++; | ||
122 | } | 122 | } |
123 | break; | 123 | break; |
124 | 124 | ||
diff --git a/arch/tile/kernel/reboot.c b/arch/tile/kernel/reboot.c index acd86d20beba..baa3d905fee2 100644 --- a/arch/tile/kernel/reboot.c +++ b/arch/tile/kernel/reboot.c | |||
@@ -27,7 +27,7 @@ | |||
27 | void machine_halt(void) | 27 | void machine_halt(void) |
28 | { | 28 | { |
29 | warn_early_printk(); | 29 | warn_early_printk(); |
30 | raw_local_irq_disable_all(); | 30 | arch_local_irq_disable_all(); |
31 | smp_send_stop(); | 31 | smp_send_stop(); |
32 | hv_halt(); | 32 | hv_halt(); |
33 | } | 33 | } |
@@ -35,14 +35,14 @@ void machine_halt(void) | |||
35 | void machine_power_off(void) | 35 | void machine_power_off(void) |
36 | { | 36 | { |
37 | warn_early_printk(); | 37 | warn_early_printk(); |
38 | raw_local_irq_disable_all(); | 38 | arch_local_irq_disable_all(); |
39 | smp_send_stop(); | 39 | smp_send_stop(); |
40 | hv_power_off(); | 40 | hv_power_off(); |
41 | } | 41 | } |
42 | 42 | ||
43 | void machine_restart(char *cmd) | 43 | void machine_restart(char *cmd) |
44 | { | 44 | { |
45 | raw_local_irq_disable_all(); | 45 | arch_local_irq_disable_all(); |
46 | smp_send_stop(); | 46 | smp_send_stop(); |
47 | hv_restart((HV_VirtAddr) "vmlinux", (HV_VirtAddr) cmd); | 47 | hv_restart((HV_VirtAddr) "vmlinux", (HV_VirtAddr) cmd); |
48 | } | 48 | } |
diff --git a/arch/tile/kernel/regs_32.S b/arch/tile/kernel/regs_32.S index e88d6e122783..caa13101c264 100644 --- a/arch/tile/kernel/regs_32.S +++ b/arch/tile/kernel/regs_32.S | |||
@@ -85,7 +85,7 @@ STD_ENTRY_SECTION(__switch_to, .sched.text) | |||
85 | { | 85 | { |
86 | /* Update sp and ksp0 simultaneously to avoid backtracer warnings. */ | 86 | /* Update sp and ksp0 simultaneously to avoid backtracer warnings. */ |
87 | move sp, r13 | 87 | move sp, r13 |
88 | mtspr SYSTEM_SAVE_1_0, r2 | 88 | mtspr SPR_SYSTEM_SAVE_K_0, r2 |
89 | } | 89 | } |
90 | FOR_EACH_CALLEE_SAVED_REG(LOAD_REG) | 90 | FOR_EACH_CALLEE_SAVED_REG(LOAD_REG) |
91 | .L__switch_to_pc: | 91 | .L__switch_to_pc: |
diff --git a/arch/tile/kernel/regs_64.S b/arch/tile/kernel/regs_64.S new file mode 100644 index 000000000000..f748c1e85285 --- /dev/null +++ b/arch/tile/kernel/regs_64.S | |||
@@ -0,0 +1,145 @@ | |||
1 | /* | ||
2 | * Copyright 2011 Tilera Corporation. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation, version 2. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
11 | * NON INFRINGEMENT. See the GNU General Public License for | ||
12 | * more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/linkage.h> | ||
16 | #include <asm/system.h> | ||
17 | #include <asm/ptrace.h> | ||
18 | #include <asm/asm-offsets.h> | ||
19 | #include <arch/spr_def.h> | ||
20 | #include <asm/processor.h> | ||
21 | |||
22 | /* | ||
23 | * See <asm/system.h>; called with prev and next task_struct pointers. | ||
24 | * "prev" is returned in r0 for _switch_to and also for ret_from_fork. | ||
25 | * | ||
26 | * We want to save pc/sp in "prev", and get the new pc/sp from "next". | ||
27 | * We also need to save all the callee-saved registers on the stack. | ||
28 | * | ||
29 | * Intel enables/disables access to the hardware cycle counter in | ||
30 | * seccomp (secure computing) environments if necessary, based on | ||
31 | * has_secure_computing(). We might want to do this at some point, | ||
32 | * though it would require virtualizing the other SPRs under WORLD_ACCESS. | ||
33 | * | ||
34 | * Since we're saving to the stack, we omit sp from this list. | ||
35 | * And for parallels with other architectures, we save lr separately, | ||
36 | * in the thread_struct itself (as the "pc" field). | ||
37 | * | ||
38 | * This code also needs to be aligned with process.c copy_thread() | ||
39 | */ | ||
40 | |||
41 | #if CALLEE_SAVED_REGS_COUNT != 24 | ||
42 | # error Mismatch between <asm/system.h> and kernel/entry.S | ||
43 | #endif | ||
44 | #define FRAME_SIZE ((2 + CALLEE_SAVED_REGS_COUNT) * 8) | ||
45 | |||
46 | #define SAVE_REG(r) { st r12, r; addi r12, r12, 8 } | ||
47 | #define LOAD_REG(r) { ld r, r12; addi r12, r12, 8 } | ||
48 | #define FOR_EACH_CALLEE_SAVED_REG(f) \ | ||
49 | f(r30); f(r31); \ | ||
50 | f(r32); f(r33); f(r34); f(r35); f(r36); f(r37); f(r38); f(r39); \ | ||
51 | f(r40); f(r41); f(r42); f(r43); f(r44); f(r45); f(r46); f(r47); \ | ||
52 | f(r48); f(r49); f(r50); f(r51); f(r52); | ||
53 | |||
54 | STD_ENTRY_SECTION(__switch_to, .sched.text) | ||
55 | { | ||
56 | move r10, sp | ||
57 | st sp, lr | ||
58 | } | ||
59 | { | ||
60 | addli r11, sp, -FRAME_SIZE + 8 | ||
61 | addli sp, sp, -FRAME_SIZE | ||
62 | } | ||
63 | { | ||
64 | st r11, r10 | ||
65 | addli r4, r1, TASK_STRUCT_THREAD_KSP_OFFSET | ||
66 | } | ||
67 | { | ||
68 | ld r13, r4 /* Load new sp to a temp register early. */ | ||
69 | addi r12, sp, 16 | ||
70 | } | ||
71 | FOR_EACH_CALLEE_SAVED_REG(SAVE_REG) | ||
72 | addli r3, r0, TASK_STRUCT_THREAD_KSP_OFFSET | ||
73 | { | ||
74 | st r3, sp | ||
75 | addli r3, r0, TASK_STRUCT_THREAD_PC_OFFSET | ||
76 | } | ||
77 | { | ||
78 | st r3, lr | ||
79 | addli r4, r1, TASK_STRUCT_THREAD_PC_OFFSET | ||
80 | } | ||
81 | { | ||
82 | ld lr, r4 | ||
83 | addi r12, r13, 16 | ||
84 | } | ||
85 | { | ||
86 | /* Update sp and ksp0 simultaneously to avoid backtracer warnings. */ | ||
87 | move sp, r13 | ||
88 | mtspr SPR_SYSTEM_SAVE_K_0, r2 | ||
89 | } | ||
90 | FOR_EACH_CALLEE_SAVED_REG(LOAD_REG) | ||
91 | .L__switch_to_pc: | ||
92 | { | ||
93 | addli sp, sp, FRAME_SIZE | ||
94 | jrp lr /* r0 is still valid here, so return it */ | ||
95 | } | ||
96 | STD_ENDPROC(__switch_to) | ||
97 | |||
98 | /* Return a suitable address for the backtracer for suspended threads */ | ||
99 | STD_ENTRY_SECTION(get_switch_to_pc, .sched.text) | ||
100 | lnk r0 | ||
101 | { | ||
102 | addli r0, r0, .L__switch_to_pc - . | ||
103 | jrp lr | ||
104 | } | ||
105 | STD_ENDPROC(get_switch_to_pc) | ||
106 | |||
107 | STD_ENTRY(get_pt_regs) | ||
108 | .irp reg, r0, r1, r2, r3, r4, r5, r6, r7, \ | ||
109 | r8, r9, r10, r11, r12, r13, r14, r15, \ | ||
110 | r16, r17, r18, r19, r20, r21, r22, r23, \ | ||
111 | r24, r25, r26, r27, r28, r29, r30, r31, \ | ||
112 | r32, r33, r34, r35, r36, r37, r38, r39, \ | ||
113 | r40, r41, r42, r43, r44, r45, r46, r47, \ | ||
114 | r48, r49, r50, r51, r52, tp, sp | ||
115 | { | ||
116 | st r0, \reg | ||
117 | addi r0, r0, 8 | ||
118 | } | ||
119 | .endr | ||
120 | { | ||
121 | st r0, lr | ||
122 | addi r0, r0, PTREGS_OFFSET_PC - PTREGS_OFFSET_LR | ||
123 | } | ||
124 | lnk r1 | ||
125 | { | ||
126 | st r0, r1 | ||
127 | addi r0, r0, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_PC | ||
128 | } | ||
129 | mfspr r1, INTERRUPT_CRITICAL_SECTION | ||
130 | shli r1, r1, SPR_EX_CONTEXT_1_1__ICS_SHIFT | ||
131 | ori r1, r1, KERNEL_PL | ||
132 | { | ||
133 | st r0, r1 | ||
134 | addi r0, r0, PTREGS_OFFSET_FAULTNUM - PTREGS_OFFSET_EX1 | ||
135 | } | ||
136 | { | ||
137 | st r0, zero /* clear faultnum */ | ||
138 | addi r0, r0, PTREGS_OFFSET_ORIG_R0 - PTREGS_OFFSET_FAULTNUM | ||
139 | } | ||
140 | { | ||
141 | st r0, zero /* clear orig_r0 */ | ||
142 | addli r0, r0, -PTREGS_OFFSET_ORIG_R0 /* restore r0 to base */ | ||
143 | } | ||
144 | jrp lr | ||
145 | STD_ENDPROC(get_pt_regs) | ||
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c index e7d54c73d5c1..6cdc9ba55fe0 100644 --- a/arch/tile/kernel/setup.c +++ b/arch/tile/kernel/setup.c | |||
@@ -30,8 +30,6 @@ | |||
30 | #include <linux/timex.h> | 30 | #include <linux/timex.h> |
31 | #include <asm/setup.h> | 31 | #include <asm/setup.h> |
32 | #include <asm/sections.h> | 32 | #include <asm/sections.h> |
33 | #include <asm/sections.h> | ||
34 | #include <asm/cacheflush.h> | ||
35 | #include <asm/cacheflush.h> | 33 | #include <asm/cacheflush.h> |
36 | #include <asm/pgalloc.h> | 34 | #include <asm/pgalloc.h> |
37 | #include <asm/mmu_context.h> | 35 | #include <asm/mmu_context.h> |
@@ -61,6 +59,8 @@ unsigned long __initdata node_memmap_pfn[MAX_NUMNODES]; | |||
61 | unsigned long __initdata node_percpu_pfn[MAX_NUMNODES]; | 59 | unsigned long __initdata node_percpu_pfn[MAX_NUMNODES]; |
62 | unsigned long __initdata node_free_pfn[MAX_NUMNODES]; | 60 | unsigned long __initdata node_free_pfn[MAX_NUMNODES]; |
63 | 61 | ||
62 | static unsigned long __initdata node_percpu[MAX_NUMNODES]; | ||
63 | |||
64 | #ifdef CONFIG_HIGHMEM | 64 | #ifdef CONFIG_HIGHMEM |
65 | /* Page frame index of end of lowmem on each controller. */ | 65 | /* Page frame index of end of lowmem on each controller. */ |
66 | unsigned long __cpuinitdata node_lowmem_end_pfn[MAX_NUMNODES]; | 66 | unsigned long __cpuinitdata node_lowmem_end_pfn[MAX_NUMNODES]; |
@@ -187,11 +187,11 @@ early_param("vmalloc", parse_vmalloc); | |||
187 | 187 | ||
188 | #ifdef CONFIG_HIGHMEM | 188 | #ifdef CONFIG_HIGHMEM |
189 | /* | 189 | /* |
190 | * Determine for each controller where its lowmem is mapped and how | 190 | * Determine for each controller where its lowmem is mapped and how much of |
191 | * much of it is mapped there. On controller zero, the first few | 191 | * it is mapped there. On controller zero, the first few megabytes are |
192 | * megabytes are mapped at 0xfd000000 as code, so in principle we | 192 | * already mapped in as code at MEM_SV_INTRPT, so in principle we could |
193 | * could start our data mappings higher up, but for now we don't | 193 | * start our data mappings higher up, but for now we don't bother, to avoid |
194 | * bother, to avoid additional confusion. | 194 | * additional confusion. |
195 | * | 195 | * |
196 | * One question is whether, on systems with more than 768 Mb and | 196 | * One question is whether, on systems with more than 768 Mb and |
197 | * controllers of different sizes, to map in a proportionate amount of | 197 | * controllers of different sizes, to map in a proportionate amount of |
@@ -311,7 +311,7 @@ static void __init setup_memory(void) | |||
311 | #endif | 311 | #endif |
312 | 312 | ||
313 | /* We are using a char to hold the cpu_2_node[] mapping */ | 313 | /* We are using a char to hold the cpu_2_node[] mapping */ |
314 | BUG_ON(MAX_NUMNODES > 127); | 314 | BUILD_BUG_ON(MAX_NUMNODES > 127); |
315 | 315 | ||
316 | /* Discover the ranges of memory available to us */ | 316 | /* Discover the ranges of memory available to us */ |
317 | for (i = 0; ; ++i) { | 317 | for (i = 0; ; ++i) { |
@@ -556,7 +556,6 @@ static void __init setup_bootmem_allocator(void) | |||
556 | reserve_bootmem(crashk_res.start, | 556 | reserve_bootmem(crashk_res.start, |
557 | crashk_res.end - crashk_res.start + 1, 0); | 557 | crashk_res.end - crashk_res.start + 1, 0); |
558 | #endif | 558 | #endif |
559 | |||
560 | } | 559 | } |
561 | 560 | ||
562 | void *__init alloc_remap(int nid, unsigned long size) | 561 | void *__init alloc_remap(int nid, unsigned long size) |
@@ -570,11 +569,13 @@ void *__init alloc_remap(int nid, unsigned long size) | |||
570 | 569 | ||
571 | static int __init percpu_size(void) | 570 | static int __init percpu_size(void) |
572 | { | 571 | { |
573 | int size = ALIGN(__per_cpu_end - __per_cpu_start, PAGE_SIZE); | 572 | int size = __per_cpu_end - __per_cpu_start; |
574 | #ifdef CONFIG_MODULES | 573 | size += PERCPU_MODULE_RESERVE; |
575 | if (size < PERCPU_ENOUGH_ROOM) | 574 | size += PERCPU_DYNAMIC_EARLY_SIZE; |
576 | size = PERCPU_ENOUGH_ROOM; | 575 | if (size < PCPU_MIN_UNIT_SIZE) |
577 | #endif | 576 | size = PCPU_MIN_UNIT_SIZE; |
577 | size = roundup(size, PAGE_SIZE); | ||
578 | |||
578 | /* In several places we assume the per-cpu data fits on a huge page. */ | 579 | /* In several places we assume the per-cpu data fits on a huge page. */ |
579 | BUG_ON(kdata_huge && size > HPAGE_SIZE); | 580 | BUG_ON(kdata_huge && size > HPAGE_SIZE); |
580 | return size; | 581 | return size; |
@@ -591,7 +592,6 @@ static inline unsigned long alloc_bootmem_pfn(int size, unsigned long goal) | |||
591 | static void __init zone_sizes_init(void) | 592 | static void __init zone_sizes_init(void) |
592 | { | 593 | { |
593 | unsigned long zones_size[MAX_NR_ZONES] = { 0 }; | 594 | unsigned long zones_size[MAX_NR_ZONES] = { 0 }; |
594 | unsigned long node_percpu[MAX_NUMNODES] = { 0 }; | ||
595 | int size = percpu_size(); | 595 | int size = percpu_size(); |
596 | int num_cpus = smp_height * smp_width; | 596 | int num_cpus = smp_height * smp_width; |
597 | int i; | 597 | int i; |
@@ -676,7 +676,7 @@ static void __init zone_sizes_init(void) | |||
676 | NODE_DATA(i)->bdata = NODE_DATA(0)->bdata; | 676 | NODE_DATA(i)->bdata = NODE_DATA(0)->bdata; |
677 | 677 | ||
678 | free_area_init_node(i, zones_size, start, NULL); | 678 | free_area_init_node(i, zones_size, start, NULL); |
679 | printk(KERN_DEBUG " DMA zone: %ld per-cpu pages\n", | 679 | printk(KERN_DEBUG " Normal zone: %ld per-cpu pages\n", |
680 | PFN_UP(node_percpu[i])); | 680 | PFN_UP(node_percpu[i])); |
681 | 681 | ||
682 | /* Track the type of memory on each node */ | 682 | /* Track the type of memory on each node */ |
@@ -842,7 +842,7 @@ static int __init topology_init(void) | |||
842 | for_each_online_node(i) | 842 | for_each_online_node(i) |
843 | register_one_node(i); | 843 | register_one_node(i); |
844 | 844 | ||
845 | for_each_present_cpu(i) | 845 | for (i = 0; i < smp_height * smp_width; ++i) |
846 | register_cpu(&cpu_devices[i], i); | 846 | register_cpu(&cpu_devices[i], i); |
847 | 847 | ||
848 | return 0; | 848 | return 0; |
@@ -870,11 +870,14 @@ void __cpuinit setup_cpu(int boot) | |||
870 | 870 | ||
871 | /* Allow asynchronous TLB interrupts. */ | 871 | /* Allow asynchronous TLB interrupts. */ |
872 | #if CHIP_HAS_TILE_DMA() | 872 | #if CHIP_HAS_TILE_DMA() |
873 | raw_local_irq_unmask(INT_DMATLB_MISS); | 873 | arch_local_irq_unmask(INT_DMATLB_MISS); |
874 | raw_local_irq_unmask(INT_DMATLB_ACCESS); | 874 | arch_local_irq_unmask(INT_DMATLB_ACCESS); |
875 | #endif | 875 | #endif |
876 | #if CHIP_HAS_SN_PROC() | 876 | #if CHIP_HAS_SN_PROC() |
877 | raw_local_irq_unmask(INT_SNITLB_MISS); | 877 | arch_local_irq_unmask(INT_SNITLB_MISS); |
878 | #endif | ||
879 | #ifdef __tilegx__ | ||
880 | arch_local_irq_unmask(INT_SINGLE_STEP_K); | ||
878 | #endif | 881 | #endif |
879 | 882 | ||
880 | /* | 883 | /* |
@@ -893,11 +896,12 @@ void __cpuinit setup_cpu(int boot) | |||
893 | #endif | 896 | #endif |
894 | 897 | ||
895 | /* | 898 | /* |
896 | * Set the MPL for interrupt control 0 to user level. | 899 | * Set the MPL for interrupt control 0 & 1 to the corresponding |
897 | * This includes access to the SYSTEM_SAVE and EX_CONTEXT SPRs, | 900 | * values. This includes access to the SYSTEM_SAVE and EX_CONTEXT |
898 | * as well as the PL 0 interrupt mask. | 901 | * SPRs, as well as the interrupt mask. |
899 | */ | 902 | */ |
900 | __insn_mtspr(SPR_MPL_INTCTRL_0_SET_0, 1); | 903 | __insn_mtspr(SPR_MPL_INTCTRL_0_SET_0, 1); |
904 | __insn_mtspr(SPR_MPL_INTCTRL_1_SET_1, 1); | ||
901 | 905 | ||
902 | /* Initialize IRQ support for this cpu. */ | 906 | /* Initialize IRQ support for this cpu. */ |
903 | setup_irq_regs(); | 907 | setup_irq_regs(); |
@@ -908,6 +912,8 @@ void __cpuinit setup_cpu(int boot) | |||
908 | #endif | 912 | #endif |
909 | } | 913 | } |
910 | 914 | ||
915 | #ifdef CONFIG_BLK_DEV_INITRD | ||
916 | |||
911 | static int __initdata set_initramfs_file; | 917 | static int __initdata set_initramfs_file; |
912 | static char __initdata initramfs_file[128] = "initramfs.cpio.gz"; | 918 | static char __initdata initramfs_file[128] = "initramfs.cpio.gz"; |
913 | 919 | ||
@@ -965,6 +971,10 @@ void __init free_initrd_mem(unsigned long begin, unsigned long end) | |||
965 | free_bootmem(__pa(begin), end - begin); | 971 | free_bootmem(__pa(begin), end - begin); |
966 | } | 972 | } |
967 | 973 | ||
974 | #else | ||
975 | static inline void load_hv_initrd(void) {} | ||
976 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
977 | |||
968 | static void __init validate_hv(void) | 978 | static void __init validate_hv(void) |
969 | { | 979 | { |
970 | /* | 980 | /* |
@@ -1033,7 +1043,7 @@ static void __init validate_va(void) | |||
1033 | * In addition, make sure we CAN'T use the end of memory, since | 1043 | * In addition, make sure we CAN'T use the end of memory, since |
1034 | * we use the last chunk of each pgd for the pgd_list. | 1044 | * we use the last chunk of each pgd for the pgd_list. |
1035 | */ | 1045 | */ |
1036 | int i, fc_fd_ok = 0; | 1046 | int i, user_kernel_ok = 0; |
1037 | unsigned long max_va = 0; | 1047 | unsigned long max_va = 0; |
1038 | unsigned long list_va = | 1048 | unsigned long list_va = |
1039 | ((PGD_LIST_OFFSET / sizeof(pgd_t)) << PGDIR_SHIFT); | 1049 | ((PGD_LIST_OFFSET / sizeof(pgd_t)) << PGDIR_SHIFT); |
@@ -1044,13 +1054,13 @@ static void __init validate_va(void) | |||
1044 | break; | 1054 | break; |
1045 | if (range.start <= MEM_USER_INTRPT && | 1055 | if (range.start <= MEM_USER_INTRPT && |
1046 | range.start + range.size >= MEM_HV_INTRPT) | 1056 | range.start + range.size >= MEM_HV_INTRPT) |
1047 | fc_fd_ok = 1; | 1057 | user_kernel_ok = 1; |
1048 | if (range.start == 0) | 1058 | if (range.start == 0) |
1049 | max_va = range.size; | 1059 | max_va = range.size; |
1050 | BUG_ON(range.start + range.size > list_va); | 1060 | BUG_ON(range.start + range.size > list_va); |
1051 | } | 1061 | } |
1052 | if (!fc_fd_ok) | 1062 | if (!user_kernel_ok) |
1053 | early_panic("Hypervisor not configured for VAs 0xfc/0xfd\n"); | 1063 | early_panic("Hypervisor not configured for user/kernel VAs\n"); |
1054 | if (max_va == 0) | 1064 | if (max_va == 0) |
1055 | early_panic("Hypervisor not configured for low VAs\n"); | 1065 | early_panic("Hypervisor not configured for low VAs\n"); |
1056 | if (max_va < KERNEL_HIGH_VADDR) | 1066 | if (max_va < KERNEL_HIGH_VADDR) |
@@ -1310,6 +1320,8 @@ static void *__init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align) | |||
1310 | 1320 | ||
1311 | BUG_ON(size % PAGE_SIZE != 0); | 1321 | BUG_ON(size % PAGE_SIZE != 0); |
1312 | pfn_offset[nid] += size / PAGE_SIZE; | 1322 | pfn_offset[nid] += size / PAGE_SIZE; |
1323 | BUG_ON(node_percpu[nid] < size); | ||
1324 | node_percpu[nid] -= size; | ||
1313 | if (percpu_pfn[cpu] == 0) | 1325 | if (percpu_pfn[cpu] == 0) |
1314 | percpu_pfn[cpu] = pfn; | 1326 | percpu_pfn[cpu] = pfn; |
1315 | return pfn_to_kaddr(pfn); | 1327 | return pfn_to_kaddr(pfn); |
@@ -1334,6 +1346,10 @@ static void __init pcpu_fc_populate_pte(unsigned long addr) | |||
1334 | pte_t *pte; | 1346 | pte_t *pte; |
1335 | 1347 | ||
1336 | BUG_ON(pgd_addr_invalid(addr)); | 1348 | BUG_ON(pgd_addr_invalid(addr)); |
1349 | if (addr < VMALLOC_START || addr >= VMALLOC_END) | ||
1350 | panic("PCPU addr %#lx outside vmalloc range %#lx..%#lx;" | ||
1351 | " try increasing CONFIG_VMALLOC_RESERVE\n", | ||
1352 | addr, VMALLOC_START, VMALLOC_END); | ||
1337 | 1353 | ||
1338 | pgd = swapper_pg_dir + pgd_index(addr); | 1354 | pgd = swapper_pg_dir + pgd_index(addr); |
1339 | pud = pud_offset(pgd, addr); | 1355 | pud = pud_offset(pgd, addr); |
diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c index ce183aa1492c..bedaf4e9f3a7 100644 --- a/arch/tile/kernel/signal.c +++ b/arch/tile/kernel/signal.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/sched.h> | 16 | #include <linux/sched.h> |
17 | #include <linux/mm.h> | 17 | #include <linux/mm.h> |
18 | #include <linux/smp.h> | 18 | #include <linux/smp.h> |
19 | #include <linux/smp_lock.h> | ||
20 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
21 | #include <linux/signal.h> | 20 | #include <linux/signal.h> |
22 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
@@ -40,9 +39,8 @@ | |||
40 | 39 | ||
41 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 40 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
42 | 41 | ||
43 | 42 | SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss, | |
44 | long _sys_sigaltstack(const stack_t __user *uss, | 43 | stack_t __user *, uoss, struct pt_regs *, regs) |
45 | stack_t __user *uoss, struct pt_regs *regs) | ||
46 | { | 44 | { |
47 | return do_sigaltstack(uss, uoss, regs->sp); | 45 | return do_sigaltstack(uss, uoss, regs->sp); |
48 | } | 46 | } |
@@ -53,7 +51,7 @@ long _sys_sigaltstack(const stack_t __user *uss, | |||
53 | */ | 51 | */ |
54 | 52 | ||
55 | int restore_sigcontext(struct pt_regs *regs, | 53 | int restore_sigcontext(struct pt_regs *regs, |
56 | struct sigcontext __user *sc, long *pr0) | 54 | struct sigcontext __user *sc) |
57 | { | 55 | { |
58 | int err = 0; | 56 | int err = 0; |
59 | int i; | 57 | int i; |
@@ -71,19 +69,27 @@ int restore_sigcontext(struct pt_regs *regs, | |||
71 | for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) | 69 | for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) |
72 | err |= __get_user(regs->regs[i], &sc->gregs[i]); | 70 | err |= __get_user(regs->regs[i], &sc->gregs[i]); |
73 | 71 | ||
72 | /* Ensure that the PL is always set to USER_PL. */ | ||
73 | regs->ex1 = PL_ICS_EX1(USER_PL, EX1_ICS(regs->ex1)); | ||
74 | |||
74 | regs->faultnum = INT_SWINT_1_SIGRETURN; | 75 | regs->faultnum = INT_SWINT_1_SIGRETURN; |
75 | 76 | ||
76 | err |= __get_user(*pr0, &sc->gregs[0]); | ||
77 | return err; | 77 | return err; |
78 | } | 78 | } |
79 | 79 | ||
80 | /* sigreturn() returns long since it restores r0 in the interrupted code. */ | 80 | void signal_fault(const char *type, struct pt_regs *regs, |
81 | long _sys_rt_sigreturn(struct pt_regs *regs) | 81 | void __user *frame, int sig) |
82 | { | ||
83 | trace_unhandled_signal(type, regs, (unsigned long)frame, SIGSEGV); | ||
84 | force_sigsegv(sig, current); | ||
85 | } | ||
86 | |||
87 | /* The assembly shim for this function arranges to ignore the return value. */ | ||
88 | SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs) | ||
82 | { | 89 | { |
83 | struct rt_sigframe __user *frame = | 90 | struct rt_sigframe __user *frame = |
84 | (struct rt_sigframe __user *)(regs->sp); | 91 | (struct rt_sigframe __user *)(regs->sp); |
85 | sigset_t set; | 92 | sigset_t set; |
86 | long r0; | ||
87 | 93 | ||
88 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 94 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
89 | goto badframe; | 95 | goto badframe; |
@@ -96,16 +102,16 @@ long _sys_rt_sigreturn(struct pt_regs *regs) | |||
96 | recalc_sigpending(); | 102 | recalc_sigpending(); |
97 | spin_unlock_irq(¤t->sighand->siglock); | 103 | spin_unlock_irq(¤t->sighand->siglock); |
98 | 104 | ||
99 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) | 105 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) |
100 | goto badframe; | 106 | goto badframe; |
101 | 107 | ||
102 | if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) | 108 | if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) |
103 | goto badframe; | 109 | goto badframe; |
104 | 110 | ||
105 | return r0; | 111 | return 0; |
106 | 112 | ||
107 | badframe: | 113 | badframe: |
108 | force_sig(SIGSEGV, current); | 114 | signal_fault("bad sigreturn frame", regs, frame, 0); |
109 | return 0; | 115 | return 0; |
110 | } | 116 | } |
111 | 117 | ||
@@ -231,7 +237,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
231 | return 0; | 237 | return 0; |
232 | 238 | ||
233 | give_sigsegv: | 239 | give_sigsegv: |
234 | force_sigsegv(sig, current); | 240 | signal_fault("bad setup frame", regs, frame, sig); |
235 | return -EFAULT; | 241 | return -EFAULT; |
236 | } | 242 | } |
237 | 243 | ||
@@ -245,7 +251,6 @@ static int handle_signal(unsigned long sig, siginfo_t *info, | |||
245 | { | 251 | { |
246 | int ret; | 252 | int ret; |
247 | 253 | ||
248 | |||
249 | /* Are we from a system call? */ | 254 | /* Are we from a system call? */ |
250 | if (regs->faultnum == INT_SWINT_1) { | 255 | if (regs->faultnum == INT_SWINT_1) { |
251 | /* If so, check system call restarting.. */ | 256 | /* If so, check system call restarting.. */ |
@@ -330,7 +335,7 @@ void do_signal(struct pt_regs *regs) | |||
330 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; | 335 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; |
331 | } | 336 | } |
332 | 337 | ||
333 | return; | 338 | goto done; |
334 | } | 339 | } |
335 | 340 | ||
336 | /* Did we come from a system call? */ | 341 | /* Did we come from a system call? */ |
@@ -358,4 +363,123 @@ void do_signal(struct pt_regs *regs) | |||
358 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; | 363 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; |
359 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | 364 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); |
360 | } | 365 | } |
366 | |||
367 | done: | ||
368 | /* Avoid double syscall restart if there are nested signals. */ | ||
369 | regs->faultnum = INT_SWINT_1_SIGRETURN; | ||
370 | } | ||
371 | |||
372 | int show_unhandled_signals = 1; | ||
373 | |||
374 | static int __init crashinfo(char *str) | ||
375 | { | ||
376 | unsigned long val; | ||
377 | const char *word; | ||
378 | |||
379 | if (*str == '\0') | ||
380 | val = 2; | ||
381 | else if (*str != '=' || strict_strtoul(++str, 0, &val) != 0) | ||
382 | return 0; | ||
383 | show_unhandled_signals = val; | ||
384 | switch (show_unhandled_signals) { | ||
385 | case 0: | ||
386 | word = "No"; | ||
387 | break; | ||
388 | case 1: | ||
389 | word = "One-line"; | ||
390 | break; | ||
391 | default: | ||
392 | word = "Detailed"; | ||
393 | break; | ||
394 | } | ||
395 | pr_info("%s crash reports will be generated on the console\n", word); | ||
396 | return 1; | ||
397 | } | ||
398 | __setup("crashinfo", crashinfo); | ||
399 | |||
400 | static void dump_mem(void __user *address) | ||
401 | { | ||
402 | void __user *addr; | ||
403 | enum { region_size = 256, bytes_per_line = 16 }; | ||
404 | int i, j, k; | ||
405 | int found_readable_mem = 0; | ||
406 | |||
407 | pr_err("\n"); | ||
408 | if (!access_ok(VERIFY_READ, address, 1)) { | ||
409 | pr_err("Not dumping at address 0x%lx (kernel address)\n", | ||
410 | (unsigned long)address); | ||
411 | return; | ||
412 | } | ||
413 | |||
414 | addr = (void __user *) | ||
415 | (((unsigned long)address & -bytes_per_line) - region_size/2); | ||
416 | if (addr > address) | ||
417 | addr = NULL; | ||
418 | for (i = 0; i < region_size; | ||
419 | addr += bytes_per_line, i += bytes_per_line) { | ||
420 | unsigned char buf[bytes_per_line]; | ||
421 | char line[100]; | ||
422 | if (copy_from_user(buf, addr, bytes_per_line)) | ||
423 | continue; | ||
424 | if (!found_readable_mem) { | ||
425 | pr_err("Dumping memory around address 0x%lx:\n", | ||
426 | (unsigned long)address); | ||
427 | found_readable_mem = 1; | ||
428 | } | ||
429 | j = sprintf(line, REGFMT":", (unsigned long)addr); | ||
430 | for (k = 0; k < bytes_per_line; ++k) | ||
431 | j += sprintf(&line[j], " %02x", buf[k]); | ||
432 | pr_err("%s\n", line); | ||
433 | } | ||
434 | if (!found_readable_mem) | ||
435 | pr_err("No readable memory around address 0x%lx\n", | ||
436 | (unsigned long)address); | ||
437 | } | ||
438 | |||
439 | void trace_unhandled_signal(const char *type, struct pt_regs *regs, | ||
440 | unsigned long address, int sig) | ||
441 | { | ||
442 | struct task_struct *tsk = current; | ||
443 | |||
444 | if (show_unhandled_signals == 0) | ||
445 | return; | ||
446 | |||
447 | /* If the signal is handled, don't show it here. */ | ||
448 | if (!is_global_init(tsk)) { | ||
449 | void __user *handler = | ||
450 | tsk->sighand->action[sig-1].sa.sa_handler; | ||
451 | if (handler != SIG_IGN && handler != SIG_DFL) | ||
452 | return; | ||
453 | } | ||
454 | |||
455 | /* Rate-limit the one-line output, not the detailed output. */ | ||
456 | if (show_unhandled_signals <= 1 && !printk_ratelimit()) | ||
457 | return; | ||
458 | |||
459 | printk("%s%s[%d]: %s at %lx pc "REGFMT" signal %d", | ||
460 | task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, | ||
461 | tsk->comm, task_pid_nr(tsk), type, address, regs->pc, sig); | ||
462 | |||
463 | print_vma_addr(KERN_CONT " in ", regs->pc); | ||
464 | |||
465 | printk(KERN_CONT "\n"); | ||
466 | |||
467 | if (show_unhandled_signals > 1) { | ||
468 | switch (sig) { | ||
469 | case SIGILL: | ||
470 | case SIGFPE: | ||
471 | case SIGSEGV: | ||
472 | case SIGBUS: | ||
473 | pr_err("User crash: signal %d," | ||
474 | " trap %ld, address 0x%lx\n", | ||
475 | sig, regs->faultnum, address); | ||
476 | show_regs(regs); | ||
477 | dump_mem((void __user *)address); | ||
478 | break; | ||
479 | default: | ||
480 | pr_err("User crash: signal %d, trap %ld\n", | ||
481 | sig, regs->faultnum); | ||
482 | break; | ||
483 | } | ||
484 | } | ||
361 | } | 485 | } |
diff --git a/arch/tile/kernel/single_step.c b/arch/tile/kernel/single_step.c index 5ec4b9c651f2..4032ca8e51b6 100644 --- a/arch/tile/kernel/single_step.c +++ b/arch/tile/kernel/single_step.c | |||
@@ -15,7 +15,7 @@ | |||
15 | * Derived from iLib's single-stepping code. | 15 | * Derived from iLib's single-stepping code. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #ifndef __tilegx__ /* No support for single-step yet. */ | 18 | #ifndef __tilegx__ /* Hardware support for single step unavailable. */ |
19 | 19 | ||
20 | /* These functions are only used on the TILE platform */ | 20 | /* These functions are only used on the TILE platform */ |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
@@ -56,7 +56,7 @@ enum mem_op { | |||
56 | MEMOP_STORE_POSTINCR | 56 | MEMOP_STORE_POSTINCR |
57 | }; | 57 | }; |
58 | 58 | ||
59 | static inline tile_bundle_bits set_BrOff_X1(tile_bundle_bits n, int32_t offset) | 59 | static inline tile_bundle_bits set_BrOff_X1(tile_bundle_bits n, s32 offset) |
60 | { | 60 | { |
61 | tile_bundle_bits result; | 61 | tile_bundle_bits result; |
62 | 62 | ||
@@ -186,6 +186,8 @@ static tile_bundle_bits rewrite_load_store_unaligned( | |||
186 | .si_code = SEGV_MAPERR, | 186 | .si_code = SEGV_MAPERR, |
187 | .si_addr = addr | 187 | .si_addr = addr |
188 | }; | 188 | }; |
189 | trace_unhandled_signal("segfault", regs, | ||
190 | (unsigned long)addr, SIGSEGV); | ||
189 | force_sig_info(info.si_signo, &info, current); | 191 | force_sig_info(info.si_signo, &info, current); |
190 | return (tile_bundle_bits) 0; | 192 | return (tile_bundle_bits) 0; |
191 | } | 193 | } |
@@ -196,6 +198,8 @@ static tile_bundle_bits rewrite_load_store_unaligned( | |||
196 | .si_code = BUS_ADRALN, | 198 | .si_code = BUS_ADRALN, |
197 | .si_addr = addr | 199 | .si_addr = addr |
198 | }; | 200 | }; |
201 | trace_unhandled_signal("unaligned trap", regs, | ||
202 | (unsigned long)addr, SIGBUS); | ||
199 | force_sig_info(info.si_signo, &info, current); | 203 | force_sig_info(info.si_signo, &info, current); |
200 | return (tile_bundle_bits) 0; | 204 | return (tile_bundle_bits) 0; |
201 | } | 205 | } |
@@ -254,6 +258,18 @@ P("\n"); | |||
254 | return bundle; | 258 | return bundle; |
255 | } | 259 | } |
256 | 260 | ||
261 | /* | ||
262 | * Called after execve() has started the new image. This allows us | ||
263 | * to reset the info state. Note that the the mmap'ed memory, if there | ||
264 | * was any, has already been unmapped by the exec. | ||
265 | */ | ||
266 | void single_step_execve(void) | ||
267 | { | ||
268 | struct thread_info *ti = current_thread_info(); | ||
269 | kfree(ti->step_state); | ||
270 | ti->step_state = NULL; | ||
271 | } | ||
272 | |||
257 | /** | 273 | /** |
258 | * single_step_once() - entry point when single stepping has been triggered. | 274 | * single_step_once() - entry point when single stepping has been triggered. |
259 | * @regs: The machine register state | 275 | * @regs: The machine register state |
@@ -306,6 +322,14 @@ void single_step_once(struct pt_regs *regs) | |||
306 | " .popsection\n" | 322 | " .popsection\n" |
307 | ); | 323 | ); |
308 | 324 | ||
325 | /* | ||
326 | * Enable interrupts here to allow touching userspace and the like. | ||
327 | * The callers expect this: do_trap() already has interrupts | ||
328 | * enabled, and do_work_pending() handles functions that enable | ||
329 | * interrupts internally. | ||
330 | */ | ||
331 | local_irq_enable(); | ||
332 | |||
309 | if (state == NULL) { | 333 | if (state == NULL) { |
310 | /* allocate a page of writable, executable memory */ | 334 | /* allocate a page of writable, executable memory */ |
311 | state = kmalloc(sizeof(struct single_step_state), GFP_KERNEL); | 335 | state = kmalloc(sizeof(struct single_step_state), GFP_KERNEL); |
@@ -373,7 +397,7 @@ void single_step_once(struct pt_regs *regs) | |||
373 | /* branches */ | 397 | /* branches */ |
374 | case BRANCH_OPCODE_X1: | 398 | case BRANCH_OPCODE_X1: |
375 | { | 399 | { |
376 | int32_t offset = signExtend17(get_BrOff_X1(bundle)); | 400 | s32 offset = signExtend17(get_BrOff_X1(bundle)); |
377 | 401 | ||
378 | /* | 402 | /* |
379 | * For branches, we use a rewriting trick to let the | 403 | * For branches, we use a rewriting trick to let the |
@@ -660,4 +684,80 @@ void single_step_once(struct pt_regs *regs) | |||
660 | regs->pc += 8; | 684 | regs->pc += 8; |
661 | } | 685 | } |
662 | 686 | ||
687 | #else | ||
688 | #include <linux/smp.h> | ||
689 | #include <linux/ptrace.h> | ||
690 | #include <arch/spr_def.h> | ||
691 | |||
692 | static DEFINE_PER_CPU(unsigned long, ss_saved_pc); | ||
693 | |||
694 | |||
695 | /* | ||
696 | * Called directly on the occasion of an interrupt. | ||
697 | * | ||
698 | * If the process doesn't have single step set, then we use this as an | ||
699 | * opportunity to turn single step off. | ||
700 | * | ||
701 | * It has been mentioned that we could conditionally turn off single stepping | ||
702 | * on each entry into the kernel and rely on single_step_once to turn it | ||
703 | * on for the processes that matter (as we already do), but this | ||
704 | * implementation is somewhat more efficient in that we muck with registers | ||
705 | * once on a bum interrupt rather than on every entry into the kernel. | ||
706 | * | ||
707 | * If SINGLE_STEP_CONTROL_K has CANCELED set, then an interrupt occurred, | ||
708 | * so we have to run through this process again before we can say that an | ||
709 | * instruction has executed. | ||
710 | * | ||
711 | * swint will set CANCELED, but it's a legitimate instruction. Fortunately | ||
712 | * it changes the PC. If it hasn't changed, then we know that the interrupt | ||
713 | * wasn't generated by swint and we'll need to run this process again before | ||
714 | * we can say an instruction has executed. | ||
715 | * | ||
716 | * If either CANCELED == 0 or the PC's changed, we send out SIGTRAPs and get | ||
717 | * on with our lives. | ||
718 | */ | ||
719 | |||
720 | void gx_singlestep_handle(struct pt_regs *regs, int fault_num) | ||
721 | { | ||
722 | unsigned long *ss_pc = &__get_cpu_var(ss_saved_pc); | ||
723 | struct thread_info *info = (void *)current_thread_info(); | ||
724 | int is_single_step = test_ti_thread_flag(info, TIF_SINGLESTEP); | ||
725 | unsigned long control = __insn_mfspr(SPR_SINGLE_STEP_CONTROL_K); | ||
726 | |||
727 | if (is_single_step == 0) { | ||
728 | __insn_mtspr(SPR_SINGLE_STEP_EN_K_K, 0); | ||
729 | |||
730 | } else if ((*ss_pc != regs->pc) || | ||
731 | (!(control & SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK))) { | ||
732 | |||
733 | ptrace_notify(SIGTRAP); | ||
734 | control |= SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK; | ||
735 | control |= SPR_SINGLE_STEP_CONTROL_1__INHIBIT_MASK; | ||
736 | __insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control); | ||
737 | } | ||
738 | } | ||
739 | |||
740 | |||
741 | /* | ||
742 | * Called from need_singlestep. Set up the control registers and the enable | ||
743 | * register, then return back. | ||
744 | */ | ||
745 | |||
746 | void single_step_once(struct pt_regs *regs) | ||
747 | { | ||
748 | unsigned long *ss_pc = &__get_cpu_var(ss_saved_pc); | ||
749 | unsigned long control = __insn_mfspr(SPR_SINGLE_STEP_CONTROL_K); | ||
750 | |||
751 | *ss_pc = regs->pc; | ||
752 | control |= SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK; | ||
753 | control |= SPR_SINGLE_STEP_CONTROL_1__INHIBIT_MASK; | ||
754 | __insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control); | ||
755 | __insn_mtspr(SPR_SINGLE_STEP_EN_K_K, 1 << USER_PL); | ||
756 | } | ||
757 | |||
758 | void single_step_execve(void) | ||
759 | { | ||
760 | /* Nothing */ | ||
761 | } | ||
762 | |||
663 | #endif /* !__tilegx__ */ | 763 | #endif /* !__tilegx__ */ |
diff --git a/arch/tile/kernel/smp.c b/arch/tile/kernel/smp.c index 1cb5ec79de04..c52224d5ed45 100644 --- a/arch/tile/kernel/smp.c +++ b/arch/tile/kernel/smp.c | |||
@@ -36,6 +36,22 @@ static unsigned long __iomem *ipi_mappings[NR_CPUS]; | |||
36 | /* Set by smp_send_stop() to avoid recursive panics. */ | 36 | /* Set by smp_send_stop() to avoid recursive panics. */ |
37 | static int stopping_cpus; | 37 | static int stopping_cpus; |
38 | 38 | ||
39 | static void __send_IPI_many(HV_Recipient *recip, int nrecip, int tag) | ||
40 | { | ||
41 | int sent = 0; | ||
42 | while (sent < nrecip) { | ||
43 | int rc = hv_send_message(recip, nrecip, | ||
44 | (HV_VirtAddr)&tag, sizeof(tag)); | ||
45 | if (rc < 0) { | ||
46 | if (!stopping_cpus) /* avoid recursive panic */ | ||
47 | panic("hv_send_message returned %d", rc); | ||
48 | break; | ||
49 | } | ||
50 | WARN_ONCE(rc == 0, "hv_send_message() returned zero\n"); | ||
51 | sent += rc; | ||
52 | } | ||
53 | } | ||
54 | |||
39 | void send_IPI_single(int cpu, int tag) | 55 | void send_IPI_single(int cpu, int tag) |
40 | { | 56 | { |
41 | HV_Recipient recip = { | 57 | HV_Recipient recip = { |
@@ -43,14 +59,13 @@ void send_IPI_single(int cpu, int tag) | |||
43 | .x = cpu % smp_width, | 59 | .x = cpu % smp_width, |
44 | .state = HV_TO_BE_SENT | 60 | .state = HV_TO_BE_SENT |
45 | }; | 61 | }; |
46 | int rc = hv_send_message(&recip, 1, (HV_VirtAddr)&tag, sizeof(tag)); | 62 | __send_IPI_many(&recip, 1, tag); |
47 | BUG_ON(rc <= 0); | ||
48 | } | 63 | } |
49 | 64 | ||
50 | void send_IPI_many(const struct cpumask *mask, int tag) | 65 | void send_IPI_many(const struct cpumask *mask, int tag) |
51 | { | 66 | { |
52 | HV_Recipient recip[NR_CPUS]; | 67 | HV_Recipient recip[NR_CPUS]; |
53 | int cpu, sent; | 68 | int cpu; |
54 | int nrecip = 0; | 69 | int nrecip = 0; |
55 | int my_cpu = smp_processor_id(); | 70 | int my_cpu = smp_processor_id(); |
56 | for_each_cpu(cpu, mask) { | 71 | for_each_cpu(cpu, mask) { |
@@ -61,17 +76,7 @@ void send_IPI_many(const struct cpumask *mask, int tag) | |||
61 | r->x = cpu % smp_width; | 76 | r->x = cpu % smp_width; |
62 | r->state = HV_TO_BE_SENT; | 77 | r->state = HV_TO_BE_SENT; |
63 | } | 78 | } |
64 | sent = 0; | 79 | __send_IPI_many(recip, nrecip, tag); |
65 | while (sent < nrecip) { | ||
66 | int rc = hv_send_message(recip, nrecip, | ||
67 | (HV_VirtAddr)&tag, sizeof(tag)); | ||
68 | if (rc <= 0) { | ||
69 | if (!stopping_cpus) /* avoid recursive panic */ | ||
70 | panic("hv_send_message returned %d", rc); | ||
71 | break; | ||
72 | } | ||
73 | sent += rc; | ||
74 | } | ||
75 | } | 80 | } |
76 | 81 | ||
77 | void send_IPI_allbutself(int tag) | 82 | void send_IPI_allbutself(int tag) |
@@ -115,7 +120,7 @@ static void smp_start_cpu_interrupt(void) | |||
115 | static void smp_stop_cpu_interrupt(void) | 120 | static void smp_stop_cpu_interrupt(void) |
116 | { | 121 | { |
117 | set_cpu_online(smp_processor_id(), 0); | 122 | set_cpu_online(smp_processor_id(), 0); |
118 | raw_local_irq_disable_all(); | 123 | arch_local_irq_disable_all(); |
119 | for (;;) | 124 | for (;;) |
120 | asm("nap"); | 125 | asm("nap"); |
121 | } | 126 | } |
@@ -184,12 +189,8 @@ void flush_icache_range(unsigned long start, unsigned long end) | |||
184 | /* Called when smp_send_reschedule() triggers IRQ_RESCHEDULE. */ | 189 | /* Called when smp_send_reschedule() triggers IRQ_RESCHEDULE. */ |
185 | static irqreturn_t handle_reschedule_ipi(int irq, void *token) | 190 | static irqreturn_t handle_reschedule_ipi(int irq, void *token) |
186 | { | 191 | { |
187 | /* | ||
188 | * Nothing to do here; when we return from interrupt, the | ||
189 | * rescheduling will occur there. But do bump the interrupt | ||
190 | * profiler count in the meantime. | ||
191 | */ | ||
192 | __get_cpu_var(irq_stat).irq_resched_count++; | 192 | __get_cpu_var(irq_stat).irq_resched_count++; |
193 | scheduler_ipi(); | ||
193 | 194 | ||
194 | return IRQ_HANDLED; | 195 | return IRQ_HANDLED; |
195 | } | 196 | } |
@@ -212,7 +213,7 @@ void __init ipi_init(void) | |||
212 | 213 | ||
213 | tile.x = cpu_x(cpu); | 214 | tile.x = cpu_x(cpu); |
214 | tile.y = cpu_y(cpu); | 215 | tile.y = cpu_y(cpu); |
215 | if (hv_get_ipi_pte(tile, 1, &pte) != 0) | 216 | if (hv_get_ipi_pte(tile, KERNEL_PL, &pte) != 0) |
216 | panic("Failed to initialize IPI for cpu %d\n", cpu); | 217 | panic("Failed to initialize IPI for cpu %d\n", cpu); |
217 | 218 | ||
218 | offset = hv_pte_get_pfn(pte) << PAGE_SHIFT; | 219 | offset = hv_pte_get_pfn(pte) << PAGE_SHIFT; |
diff --git a/arch/tile/kernel/smpboot.c b/arch/tile/kernel/smpboot.c index 74d62d098edf..b949edcec200 100644 --- a/arch/tile/kernel/smpboot.c +++ b/arch/tile/kernel/smpboot.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
19 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
20 | #include <linux/kernel_stat.h> | 20 | #include <linux/kernel_stat.h> |
21 | #include <linux/smp_lock.h> | ||
22 | #include <linux/bootmem.h> | 21 | #include <linux/bootmem.h> |
23 | #include <linux/notifier.h> | 22 | #include <linux/notifier.h> |
24 | #include <linux/cpu.h> | 23 | #include <linux/cpu.h> |
diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c index ea2e0ce28380..37ee4d037e0b 100644 --- a/arch/tile/kernel/stack.c +++ b/arch/tile/kernel/stack.c | |||
@@ -30,9 +30,13 @@ | |||
30 | #include <arch/abi.h> | 30 | #include <arch/abi.h> |
31 | #include <arch/interrupts.h> | 31 | #include <arch/interrupts.h> |
32 | 32 | ||
33 | #define KBT_ONGOING 0 /* Backtrace still ongoing */ | ||
34 | #define KBT_DONE 1 /* Backtrace cleanly completed */ | ||
35 | #define KBT_RUNNING 2 /* Can't run backtrace on a running task */ | ||
36 | #define KBT_LOOP 3 /* Backtrace entered a loop */ | ||
33 | 37 | ||
34 | /* Is address on the specified kernel stack? */ | 38 | /* Is address on the specified kernel stack? */ |
35 | static int in_kernel_stack(struct KBacktraceIterator *kbt, VirtualAddress sp) | 39 | static int in_kernel_stack(struct KBacktraceIterator *kbt, unsigned long sp) |
36 | { | 40 | { |
37 | ulong kstack_base = (ulong) kbt->task->stack; | 41 | ulong kstack_base = (ulong) kbt->task->stack; |
38 | if (kstack_base == 0) /* corrupt task pointer; just follow stack... */ | 42 | if (kstack_base == 0) /* corrupt task pointer; just follow stack... */ |
@@ -40,15 +44,8 @@ static int in_kernel_stack(struct KBacktraceIterator *kbt, VirtualAddress sp) | |||
40 | return sp >= kstack_base && sp < kstack_base + THREAD_SIZE; | 44 | return sp >= kstack_base && sp < kstack_base + THREAD_SIZE; |
41 | } | 45 | } |
42 | 46 | ||
43 | /* Is address in the specified kernel code? */ | ||
44 | static int in_kernel_text(VirtualAddress address) | ||
45 | { | ||
46 | return (address >= MEM_SV_INTRPT && | ||
47 | address < MEM_SV_INTRPT + HPAGE_SIZE); | ||
48 | } | ||
49 | |||
50 | /* Is address valid for reading? */ | 47 | /* Is address valid for reading? */ |
51 | static int valid_address(struct KBacktraceIterator *kbt, VirtualAddress address) | 48 | static int valid_address(struct KBacktraceIterator *kbt, unsigned long address) |
52 | { | 49 | { |
53 | HV_PTE *l1_pgtable = kbt->pgtable; | 50 | HV_PTE *l1_pgtable = kbt->pgtable; |
54 | HV_PTE *l2_pgtable; | 51 | HV_PTE *l2_pgtable; |
@@ -59,6 +56,23 @@ static int valid_address(struct KBacktraceIterator *kbt, VirtualAddress address) | |||
59 | if (l1_pgtable == NULL) | 56 | if (l1_pgtable == NULL) |
60 | return 0; /* can't read user space in other tasks */ | 57 | return 0; /* can't read user space in other tasks */ |
61 | 58 | ||
59 | #ifdef CONFIG_64BIT | ||
60 | /* Find the real l1_pgtable by looking in the l0_pgtable. */ | ||
61 | pte = l1_pgtable[HV_L0_INDEX(address)]; | ||
62 | if (!hv_pte_get_present(pte)) | ||
63 | return 0; | ||
64 | pfn = hv_pte_get_pfn(pte); | ||
65 | if (pte_huge(pte)) { | ||
66 | if (!pfn_valid(pfn)) { | ||
67 | pr_err("L0 huge page has bad pfn %#lx\n", pfn); | ||
68 | return 0; | ||
69 | } | ||
70 | return hv_pte_get_present(pte) && hv_pte_get_readable(pte); | ||
71 | } | ||
72 | page = pfn_to_page(pfn); | ||
73 | BUG_ON(PageHighMem(page)); /* No HIGHMEM on 64-bit. */ | ||
74 | l1_pgtable = (HV_PTE *)pfn_to_kaddr(pfn); | ||
75 | #endif | ||
62 | pte = l1_pgtable[HV_L1_INDEX(address)]; | 76 | pte = l1_pgtable[HV_L1_INDEX(address)]; |
63 | if (!hv_pte_get_present(pte)) | 77 | if (!hv_pte_get_present(pte)) |
64 | return 0; | 78 | return 0; |
@@ -83,12 +97,12 @@ static int valid_address(struct KBacktraceIterator *kbt, VirtualAddress address) | |||
83 | } | 97 | } |
84 | 98 | ||
85 | /* Callback for backtracer; basically a glorified memcpy */ | 99 | /* Callback for backtracer; basically a glorified memcpy */ |
86 | static bool read_memory_func(void *result, VirtualAddress address, | 100 | static bool read_memory_func(void *result, unsigned long address, |
87 | unsigned int size, void *vkbt) | 101 | unsigned int size, void *vkbt) |
88 | { | 102 | { |
89 | int retval; | 103 | int retval; |
90 | struct KBacktraceIterator *kbt = (struct KBacktraceIterator *)vkbt; | 104 | struct KBacktraceIterator *kbt = (struct KBacktraceIterator *)vkbt; |
91 | if (in_kernel_text(address)) { | 105 | if (__kernel_text_address(address)) { |
92 | /* OK to read kernel code. */ | 106 | /* OK to read kernel code. */ |
93 | } else if (address >= PAGE_OFFSET) { | 107 | } else if (address >= PAGE_OFFSET) { |
94 | /* We only tolerate kernel-space reads of this task's stack */ | 108 | /* We only tolerate kernel-space reads of this task's stack */ |
@@ -110,7 +124,7 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt) | |||
110 | { | 124 | { |
111 | const char *fault = NULL; /* happy compiler */ | 125 | const char *fault = NULL; /* happy compiler */ |
112 | char fault_buf[64]; | 126 | char fault_buf[64]; |
113 | VirtualAddress sp = kbt->it.sp; | 127 | unsigned long sp = kbt->it.sp; |
114 | struct pt_regs *p; | 128 | struct pt_regs *p; |
115 | 129 | ||
116 | if (!in_kernel_stack(kbt, sp)) | 130 | if (!in_kernel_stack(kbt, sp)) |
@@ -128,7 +142,7 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt) | |||
128 | } | 142 | } |
129 | } | 143 | } |
130 | if (EX1_PL(p->ex1) == KERNEL_PL && | 144 | if (EX1_PL(p->ex1) == KERNEL_PL && |
131 | in_kernel_text(p->pc) && | 145 | __kernel_text_address(p->pc) && |
132 | in_kernel_stack(kbt, p->sp) && | 146 | in_kernel_stack(kbt, p->sp) && |
133 | p->sp >= sp) { | 147 | p->sp >= sp) { |
134 | if (kbt->verbose) | 148 | if (kbt->verbose) |
@@ -149,7 +163,7 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt) | |||
149 | } | 163 | } |
150 | 164 | ||
151 | /* Is the pc pointing to a sigreturn trampoline? */ | 165 | /* Is the pc pointing to a sigreturn trampoline? */ |
152 | static int is_sigreturn(VirtualAddress pc) | 166 | static int is_sigreturn(unsigned long pc) |
153 | { | 167 | { |
154 | return (pc == VDSO_BASE); | 168 | return (pc == VDSO_BASE); |
155 | } | 169 | } |
@@ -207,11 +221,11 @@ static int KBacktraceIterator_next_item_inclusive( | |||
207 | for (;;) { | 221 | for (;;) { |
208 | do { | 222 | do { |
209 | if (!KBacktraceIterator_is_sigreturn(kbt)) | 223 | if (!KBacktraceIterator_is_sigreturn(kbt)) |
210 | return 1; | 224 | return KBT_ONGOING; |
211 | } while (backtrace_next(&kbt->it)); | 225 | } while (backtrace_next(&kbt->it)); |
212 | 226 | ||
213 | if (!KBacktraceIterator_restart(kbt)) | 227 | if (!KBacktraceIterator_restart(kbt)) |
214 | return 0; | 228 | return KBT_DONE; |
215 | } | 229 | } |
216 | } | 230 | } |
217 | 231 | ||
@@ -246,7 +260,7 @@ static void validate_stack(struct pt_regs *regs) | |||
246 | void KBacktraceIterator_init(struct KBacktraceIterator *kbt, | 260 | void KBacktraceIterator_init(struct KBacktraceIterator *kbt, |
247 | struct task_struct *t, struct pt_regs *regs) | 261 | struct task_struct *t, struct pt_regs *regs) |
248 | { | 262 | { |
249 | VirtualAddress pc, lr, sp, r52; | 263 | unsigned long pc, lr, sp, r52; |
250 | int is_current; | 264 | int is_current; |
251 | 265 | ||
252 | /* | 266 | /* |
@@ -264,7 +278,7 @@ void KBacktraceIterator_init(struct KBacktraceIterator *kbt, | |||
264 | kbt->pgtable = NULL; | 278 | kbt->pgtable = NULL; |
265 | kbt->verbose = 0; /* override in caller if desired */ | 279 | kbt->verbose = 0; /* override in caller if desired */ |
266 | kbt->profile = 0; /* override in caller if desired */ | 280 | kbt->profile = 0; /* override in caller if desired */ |
267 | kbt->end = 0; | 281 | kbt->end = KBT_ONGOING; |
268 | kbt->new_context = 0; | 282 | kbt->new_context = 0; |
269 | if (is_current) { | 283 | if (is_current) { |
270 | HV_PhysAddr pgdir_pa = hv_inquire_context().page_table; | 284 | HV_PhysAddr pgdir_pa = hv_inquire_context().page_table; |
@@ -290,7 +304,7 @@ void KBacktraceIterator_init(struct KBacktraceIterator *kbt, | |||
290 | if (regs == NULL) { | 304 | if (regs == NULL) { |
291 | if (is_current || t->state == TASK_RUNNING) { | 305 | if (is_current || t->state == TASK_RUNNING) { |
292 | /* Can't do this; we need registers */ | 306 | /* Can't do this; we need registers */ |
293 | kbt->end = 1; | 307 | kbt->end = KBT_RUNNING; |
294 | return; | 308 | return; |
295 | } | 309 | } |
296 | pc = get_switch_to_pc(); | 310 | pc = get_switch_to_pc(); |
@@ -305,26 +319,29 @@ void KBacktraceIterator_init(struct KBacktraceIterator *kbt, | |||
305 | } | 319 | } |
306 | 320 | ||
307 | backtrace_init(&kbt->it, read_memory_func, kbt, pc, lr, sp, r52); | 321 | backtrace_init(&kbt->it, read_memory_func, kbt, pc, lr, sp, r52); |
308 | kbt->end = !KBacktraceIterator_next_item_inclusive(kbt); | 322 | kbt->end = KBacktraceIterator_next_item_inclusive(kbt); |
309 | } | 323 | } |
310 | EXPORT_SYMBOL(KBacktraceIterator_init); | 324 | EXPORT_SYMBOL(KBacktraceIterator_init); |
311 | 325 | ||
312 | int KBacktraceIterator_end(struct KBacktraceIterator *kbt) | 326 | int KBacktraceIterator_end(struct KBacktraceIterator *kbt) |
313 | { | 327 | { |
314 | return kbt->end; | 328 | return kbt->end != KBT_ONGOING; |
315 | } | 329 | } |
316 | EXPORT_SYMBOL(KBacktraceIterator_end); | 330 | EXPORT_SYMBOL(KBacktraceIterator_end); |
317 | 331 | ||
318 | void KBacktraceIterator_next(struct KBacktraceIterator *kbt) | 332 | void KBacktraceIterator_next(struct KBacktraceIterator *kbt) |
319 | { | 333 | { |
334 | unsigned long old_pc = kbt->it.pc, old_sp = kbt->it.sp; | ||
320 | kbt->new_context = 0; | 335 | kbt->new_context = 0; |
321 | if (!backtrace_next(&kbt->it) && | 336 | if (!backtrace_next(&kbt->it) && !KBacktraceIterator_restart(kbt)) { |
322 | !KBacktraceIterator_restart(kbt)) { | 337 | kbt->end = KBT_DONE; |
323 | kbt->end = 1; | 338 | return; |
324 | return; | 339 | } |
325 | } | 340 | kbt->end = KBacktraceIterator_next_item_inclusive(kbt); |
326 | 341 | if (old_pc == kbt->it.pc && old_sp == kbt->it.sp) { | |
327 | kbt->end = !KBacktraceIterator_next_item_inclusive(kbt); | 342 | /* Trapped in a loop; give up. */ |
343 | kbt->end = KBT_LOOP; | ||
344 | } | ||
328 | } | 345 | } |
329 | EXPORT_SYMBOL(KBacktraceIterator_next); | 346 | EXPORT_SYMBOL(KBacktraceIterator_next); |
330 | 347 | ||
@@ -387,6 +404,8 @@ void tile_show_stack(struct KBacktraceIterator *kbt, int headers) | |||
387 | break; | 404 | break; |
388 | } | 405 | } |
389 | } | 406 | } |
407 | if (kbt->end == KBT_LOOP) | ||
408 | pr_err("Stack dump stopped; next frame identical to this one\n"); | ||
390 | if (headers) | 409 | if (headers) |
391 | pr_err("Stack dump complete\n"); | 410 | pr_err("Stack dump complete\n"); |
392 | } | 411 | } |
diff --git a/arch/tile/kernel/sys.c b/arch/tile/kernel/sys.c index f0f87eab8c39..cb44ba7ccd2d 100644 --- a/arch/tile/kernel/sys.c +++ b/arch/tile/kernel/sys.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
21 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
22 | #include <linux/smp.h> | 22 | #include <linux/smp.h> |
23 | #include <linux/smp_lock.h> | ||
24 | #include <linux/syscalls.h> | 23 | #include <linux/syscalls.h> |
25 | #include <linux/mman.h> | 24 | #include <linux/mman.h> |
26 | #include <linux/file.h> | 25 | #include <linux/file.h> |
@@ -57,13 +56,6 @@ ssize_t sys32_readahead(int fd, u32 offset_lo, u32 offset_hi, u32 count) | |||
57 | return sys_readahead(fd, ((loff_t)offset_hi << 32) | offset_lo, count); | 56 | return sys_readahead(fd, ((loff_t)offset_hi << 32) | offset_lo, count); |
58 | } | 57 | } |
59 | 58 | ||
60 | long sys32_fadvise64(int fd, u32 offset_lo, u32 offset_hi, | ||
61 | u32 len, int advice) | ||
62 | { | ||
63 | return sys_fadvise64_64(fd, ((loff_t)offset_hi << 32) | offset_lo, | ||
64 | len, advice); | ||
65 | } | ||
66 | |||
67 | int sys32_fadvise64_64(int fd, u32 offset_lo, u32 offset_hi, | 59 | int sys32_fadvise64_64(int fd, u32 offset_lo, u32 offset_hi, |
68 | u32 len_lo, u32 len_hi, int advice) | 60 | u32 len_lo, u32 len_hi, int advice) |
69 | { | 61 | { |
@@ -104,10 +96,17 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, | |||
104 | 96 | ||
105 | #ifndef __tilegx__ | 97 | #ifndef __tilegx__ |
106 | /* See comments at the top of the file. */ | 98 | /* See comments at the top of the file. */ |
107 | #define sys_fadvise64 sys32_fadvise64 | ||
108 | #define sys_fadvise64_64 sys32_fadvise64_64 | 99 | #define sys_fadvise64_64 sys32_fadvise64_64 |
109 | #define sys_readahead sys32_readahead | 100 | #define sys_readahead sys32_readahead |
110 | #define sys_sync_file_range sys_sync_file_range2 | 101 | #endif |
102 | |||
103 | /* Call the trampolines to manage pt_regs where necessary. */ | ||
104 | #define sys_execve _sys_execve | ||
105 | #define sys_sigaltstack _sys_sigaltstack | ||
106 | #define sys_rt_sigreturn _sys_rt_sigreturn | ||
107 | #define sys_clone _sys_clone | ||
108 | #ifndef __tilegx__ | ||
109 | #define sys_cmpxchg_badaddr _sys_cmpxchg_badaddr | ||
111 | #endif | 110 | #endif |
112 | 111 | ||
113 | /* | 112 | /* |
diff --git a/arch/tile/kernel/sysfs.c b/arch/tile/kernel/sysfs.c new file mode 100644 index 000000000000..b671a86f4515 --- /dev/null +++ b/arch/tile/kernel/sysfs.c | |||
@@ -0,0 +1,185 @@ | |||
1 | /* | ||
2 | * Copyright 2011 Tilera Corporation. All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation, version 2. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but | ||
9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
11 | * NON INFRINGEMENT. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * /sys entry support. | ||
15 | */ | ||
16 | |||
17 | #include <linux/sysdev.h> | ||
18 | #include <linux/cpu.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/smp.h> | ||
21 | #include <hv/hypervisor.h> | ||
22 | |||
23 | /* Return a string queried from the hypervisor, truncated to page size. */ | ||
24 | static ssize_t get_hv_confstr(char *page, int query) | ||
25 | { | ||
26 | ssize_t n = hv_confstr(query, (unsigned long)page, PAGE_SIZE - 1); | ||
27 | n = n < 0 ? 0 : min(n, (ssize_t)PAGE_SIZE - 1) - 1; | ||
28 | if (n) | ||
29 | page[n++] = '\n'; | ||
30 | page[n] = '\0'; | ||
31 | return n; | ||
32 | } | ||
33 | |||
34 | static ssize_t chip_width_show(struct sysdev_class *dev, | ||
35 | struct sysdev_class_attribute *attr, | ||
36 | char *page) | ||
37 | { | ||
38 | return sprintf(page, "%u\n", smp_width); | ||
39 | } | ||
40 | static SYSDEV_CLASS_ATTR(chip_width, 0444, chip_width_show, NULL); | ||
41 | |||
42 | static ssize_t chip_height_show(struct sysdev_class *dev, | ||
43 | struct sysdev_class_attribute *attr, | ||
44 | char *page) | ||
45 | { | ||
46 | return sprintf(page, "%u\n", smp_height); | ||
47 | } | ||
48 | static SYSDEV_CLASS_ATTR(chip_height, 0444, chip_height_show, NULL); | ||
49 | |||
50 | static ssize_t chip_serial_show(struct sysdev_class *dev, | ||
51 | struct sysdev_class_attribute *attr, | ||
52 | char *page) | ||
53 | { | ||
54 | return get_hv_confstr(page, HV_CONFSTR_CHIP_SERIAL_NUM); | ||
55 | } | ||
56 | static SYSDEV_CLASS_ATTR(chip_serial, 0444, chip_serial_show, NULL); | ||
57 | |||
58 | static ssize_t chip_revision_show(struct sysdev_class *dev, | ||
59 | struct sysdev_class_attribute *attr, | ||
60 | char *page) | ||
61 | { | ||
62 | return get_hv_confstr(page, HV_CONFSTR_CHIP_REV); | ||
63 | } | ||
64 | static SYSDEV_CLASS_ATTR(chip_revision, 0444, chip_revision_show, NULL); | ||
65 | |||
66 | |||
67 | static ssize_t type_show(struct sysdev_class *dev, | ||
68 | struct sysdev_class_attribute *attr, | ||
69 | char *page) | ||
70 | { | ||
71 | return sprintf(page, "tilera\n"); | ||
72 | } | ||
73 | static SYSDEV_CLASS_ATTR(type, 0444, type_show, NULL); | ||
74 | |||
75 | #define HV_CONF_ATTR(name, conf) \ | ||
76 | static ssize_t name ## _show(struct sysdev_class *dev, \ | ||
77 | struct sysdev_class_attribute *attr, \ | ||
78 | char *page) \ | ||
79 | { \ | ||
80 | return get_hv_confstr(page, conf); \ | ||
81 | } \ | ||
82 | static SYSDEV_CLASS_ATTR(name, 0444, name ## _show, NULL); | ||
83 | |||
84 | HV_CONF_ATTR(version, HV_CONFSTR_HV_SW_VER) | ||
85 | HV_CONF_ATTR(config_version, HV_CONFSTR_HV_CONFIG_VER) | ||
86 | |||
87 | HV_CONF_ATTR(board_part, HV_CONFSTR_BOARD_PART_NUM) | ||
88 | HV_CONF_ATTR(board_serial, HV_CONFSTR_BOARD_SERIAL_NUM) | ||
89 | HV_CONF_ATTR(board_revision, HV_CONFSTR_BOARD_REV) | ||
90 | HV_CONF_ATTR(board_description, HV_CONFSTR_BOARD_DESC) | ||
91 | HV_CONF_ATTR(mezz_part, HV_CONFSTR_MEZZ_PART_NUM) | ||
92 | HV_CONF_ATTR(mezz_serial, HV_CONFSTR_MEZZ_SERIAL_NUM) | ||
93 | HV_CONF_ATTR(mezz_revision, HV_CONFSTR_MEZZ_REV) | ||
94 | HV_CONF_ATTR(mezz_description, HV_CONFSTR_MEZZ_DESC) | ||
95 | HV_CONF_ATTR(switch_control, HV_CONFSTR_SWITCH_CONTROL) | ||
96 | |||
97 | static struct attribute *board_attrs[] = { | ||
98 | &attr_board_part.attr, | ||
99 | &attr_board_serial.attr, | ||
100 | &attr_board_revision.attr, | ||
101 | &attr_board_description.attr, | ||
102 | &attr_mezz_part.attr, | ||
103 | &attr_mezz_serial.attr, | ||
104 | &attr_mezz_revision.attr, | ||
105 | &attr_mezz_description.attr, | ||
106 | &attr_switch_control.attr, | ||
107 | NULL | ||
108 | }; | ||
109 | |||
110 | static struct attribute_group board_attr_group = { | ||
111 | .name = "board", | ||
112 | .attrs = board_attrs, | ||
113 | }; | ||
114 | |||
115 | |||
116 | static struct bin_attribute hvconfig_bin; | ||
117 | |||
118 | static ssize_t | ||
119 | hvconfig_bin_read(struct file *filp, struct kobject *kobj, | ||
120 | struct bin_attribute *bin_attr, | ||
121 | char *buf, loff_t off, size_t count) | ||
122 | { | ||
123 | static size_t size; | ||
124 | |||
125 | /* Lazily learn the true size (minus the trailing NUL). */ | ||
126 | if (size == 0) | ||
127 | size = hv_confstr(HV_CONFSTR_HV_CONFIG, 0, 0) - 1; | ||
128 | |||
129 | /* Check and adjust input parameters. */ | ||
130 | if (off > size) | ||
131 | return -EINVAL; | ||
132 | if (count > size - off) | ||
133 | count = size - off; | ||
134 | |||
135 | if (count) { | ||
136 | /* Get a copy of the hvc and copy out the relevant portion. */ | ||
137 | char *hvc; | ||
138 | |||
139 | size = off + count; | ||
140 | hvc = kmalloc(size, GFP_KERNEL); | ||
141 | if (hvc == NULL) | ||
142 | return -ENOMEM; | ||
143 | hv_confstr(HV_CONFSTR_HV_CONFIG, (unsigned long)hvc, size); | ||
144 | memcpy(buf, hvc + off, count); | ||
145 | kfree(hvc); | ||
146 | } | ||
147 | |||
148 | return count; | ||
149 | } | ||
150 | |||
151 | static int __init create_sysfs_entries(void) | ||
152 | { | ||
153 | struct sysdev_class *cls = &cpu_sysdev_class; | ||
154 | int err = 0; | ||
155 | |||
156 | #define create_cpu_attr(name) \ | ||
157 | if (!err) \ | ||
158 | err = sysfs_create_file(&cls->kset.kobj, &attr_##name.attr); | ||
159 | create_cpu_attr(chip_width); | ||
160 | create_cpu_attr(chip_height); | ||
161 | create_cpu_attr(chip_serial); | ||
162 | create_cpu_attr(chip_revision); | ||
163 | |||
164 | #define create_hv_attr(name) \ | ||
165 | if (!err) \ | ||
166 | err = sysfs_create_file(hypervisor_kobj, &attr_##name.attr); | ||
167 | create_hv_attr(type); | ||
168 | create_hv_attr(version); | ||
169 | create_hv_attr(config_version); | ||
170 | |||
171 | if (!err) | ||
172 | err = sysfs_create_group(hypervisor_kobj, &board_attr_group); | ||
173 | |||
174 | if (!err) { | ||
175 | sysfs_bin_attr_init(&hvconfig_bin); | ||
176 | hvconfig_bin.attr.name = "hvconfig"; | ||
177 | hvconfig_bin.attr.mode = S_IRUGO; | ||
178 | hvconfig_bin.read = hvconfig_bin_read; | ||
179 | hvconfig_bin.size = PAGE_SIZE; | ||
180 | err = sysfs_create_bin_file(hypervisor_kobj, &hvconfig_bin); | ||
181 | } | ||
182 | |||
183 | return err; | ||
184 | } | ||
185 | subsys_initcall(create_sysfs_entries); | ||
diff --git a/arch/tile/kernel/tile-desc_32.c b/arch/tile/kernel/tile-desc_32.c index 69af0e150f78..7e31a1285788 100644 --- a/arch/tile/kernel/tile-desc_32.c +++ b/arch/tile/kernel/tile-desc_32.c | |||
@@ -2413,12 +2413,13 @@ const struct tile_operand tile_operands[43] = | |||
2413 | 2413 | ||
2414 | 2414 | ||
2415 | 2415 | ||
2416 | /* Given a set of bundle bits and the lookup FSM for a specific pipe, | 2416 | /* Given a set of bundle bits and a specific pipe, returns which |
2417 | * returns which instruction the bundle contains in that pipe. | 2417 | * instruction the bundle contains in that pipe. |
2418 | */ | 2418 | */ |
2419 | static const struct tile_opcode * | 2419 | const struct tile_opcode * |
2420 | find_opcode(tile_bundle_bits bits, const unsigned short *table) | 2420 | find_opcode(tile_bundle_bits bits, tile_pipeline pipe) |
2421 | { | 2421 | { |
2422 | const unsigned short *table = tile_bundle_decoder_fsms[pipe]; | ||
2422 | int index = 0; | 2423 | int index = 0; |
2423 | 2424 | ||
2424 | while (1) | 2425 | while (1) |
@@ -2465,7 +2466,7 @@ parse_insn_tile(tile_bundle_bits bits, | |||
2465 | int i; | 2466 | int i; |
2466 | 2467 | ||
2467 | d = &decoded[num_instructions++]; | 2468 | d = &decoded[num_instructions++]; |
2468 | opc = find_opcode (bits, tile_bundle_decoder_fsms[pipe]); | 2469 | opc = find_opcode (bits, (tile_pipeline)pipe); |
2469 | d->opcode = opc; | 2470 | d->opcode = opc; |
2470 | 2471 | ||
2471 | /* Decode each operand, sign extending, etc. as appropriate. */ | 2472 | /* Decode each operand, sign extending, etc. as appropriate. */ |
diff --git a/arch/tile/kernel/tile-desc_64.c b/arch/tile/kernel/tile-desc_64.c new file mode 100644 index 000000000000..d57007bed77f --- /dev/null +++ b/arch/tile/kernel/tile-desc_64.c | |||
@@ -0,0 +1,2200 @@ | |||
1 | /* This define is BFD_RELOC_##x for real bfd, or -1 for everyone else. */ | ||
2 | #define BFD_RELOC(x) -1 | ||
3 | |||
4 | /* Special registers. */ | ||
5 | #define TREG_LR 55 | ||
6 | #define TREG_SN 56 | ||
7 | #define TREG_ZERO 63 | ||
8 | |||
9 | /* FIXME: Rename this. */ | ||
10 | #include <asm/opcode-tile_64.h> | ||
11 | |||
12 | #include <linux/stddef.h> | ||
13 | |||
14 | const struct tilegx_opcode tilegx_opcodes[334] = | ||
15 | { | ||
16 | { "bpt", TILEGX_OPC_BPT, 0x2, 0, TREG_ZERO, 0, | ||
17 | { { 0, }, { }, { 0, }, { 0, }, { 0, } }, | ||
18 | }, | ||
19 | { "info", TILEGX_OPC_INFO, 0xf, 1, TREG_ZERO, 1, | ||
20 | { { 0 }, { 1 }, { 2 }, { 3 }, { 0, } }, | ||
21 | }, | ||
22 | { "infol", TILEGX_OPC_INFOL, 0x3, 1, TREG_ZERO, 1, | ||
23 | { { 4 }, { 5 }, { 0, }, { 0, }, { 0, } }, | ||
24 | }, | ||
25 | { "move", TILEGX_OPC_MOVE, 0xf, 2, TREG_ZERO, 1, | ||
26 | { { 6, 7 }, { 8, 9 }, { 10, 11 }, { 12, 13 }, { 0, } }, | ||
27 | }, | ||
28 | { "movei", TILEGX_OPC_MOVEI, 0xf, 2, TREG_ZERO, 1, | ||
29 | { { 6, 0 }, { 8, 1 }, { 10, 2 }, { 12, 3 }, { 0, } }, | ||
30 | }, | ||
31 | { "moveli", TILEGX_OPC_MOVELI, 0x3, 2, TREG_ZERO, 1, | ||
32 | { { 6, 4 }, { 8, 5 }, { 0, }, { 0, }, { 0, } }, | ||
33 | }, | ||
34 | { "prefetch", TILEGX_OPC_PREFETCH, 0x12, 1, TREG_ZERO, 1, | ||
35 | { { 0, }, { 9 }, { 0, }, { 0, }, { 14 } }, | ||
36 | }, | ||
37 | { "prefetch_add_l1", TILEGX_OPC_PREFETCH_ADD_L1, 0x2, 2, TREG_ZERO, 1, | ||
38 | { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
39 | }, | ||
40 | { "prefetch_add_l1_fault", TILEGX_OPC_PREFETCH_ADD_L1_FAULT, 0x2, 2, TREG_ZERO, 1, | ||
41 | { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
42 | }, | ||
43 | { "prefetch_add_l2", TILEGX_OPC_PREFETCH_ADD_L2, 0x2, 2, TREG_ZERO, 1, | ||
44 | { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
45 | }, | ||
46 | { "prefetch_add_l2_fault", TILEGX_OPC_PREFETCH_ADD_L2_FAULT, 0x2, 2, TREG_ZERO, 1, | ||
47 | { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
48 | }, | ||
49 | { "prefetch_add_l3", TILEGX_OPC_PREFETCH_ADD_L3, 0x2, 2, TREG_ZERO, 1, | ||
50 | { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
51 | }, | ||
52 | { "prefetch_add_l3_fault", TILEGX_OPC_PREFETCH_ADD_L3_FAULT, 0x2, 2, TREG_ZERO, 1, | ||
53 | { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
54 | }, | ||
55 | { "prefetch_l1", TILEGX_OPC_PREFETCH_L1, 0x12, 1, TREG_ZERO, 1, | ||
56 | { { 0, }, { 9 }, { 0, }, { 0, }, { 14 } }, | ||
57 | }, | ||
58 | { "prefetch_l1_fault", TILEGX_OPC_PREFETCH_L1_FAULT, 0x12, 1, TREG_ZERO, 1, | ||
59 | { { 0, }, { 9 }, { 0, }, { 0, }, { 14 } }, | ||
60 | }, | ||
61 | { "prefetch_l2", TILEGX_OPC_PREFETCH_L2, 0x12, 1, TREG_ZERO, 1, | ||
62 | { { 0, }, { 9 }, { 0, }, { 0, }, { 14 } }, | ||
63 | }, | ||
64 | { "prefetch_l2_fault", TILEGX_OPC_PREFETCH_L2_FAULT, 0x12, 1, TREG_ZERO, 1, | ||
65 | { { 0, }, { 9 }, { 0, }, { 0, }, { 14 } }, | ||
66 | }, | ||
67 | { "prefetch_l3", TILEGX_OPC_PREFETCH_L3, 0x12, 1, TREG_ZERO, 1, | ||
68 | { { 0, }, { 9 }, { 0, }, { 0, }, { 14 } }, | ||
69 | }, | ||
70 | { "prefetch_l3_fault", TILEGX_OPC_PREFETCH_L3_FAULT, 0x12, 1, TREG_ZERO, 1, | ||
71 | { { 0, }, { 9 }, { 0, }, { 0, }, { 14 } }, | ||
72 | }, | ||
73 | { "raise", TILEGX_OPC_RAISE, 0x2, 0, TREG_ZERO, 1, | ||
74 | { { 0, }, { }, { 0, }, { 0, }, { 0, } }, | ||
75 | }, | ||
76 | { "add", TILEGX_OPC_ADD, 0xf, 3, TREG_ZERO, 1, | ||
77 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
78 | }, | ||
79 | { "addi", TILEGX_OPC_ADDI, 0xf, 3, TREG_ZERO, 1, | ||
80 | { { 6, 7, 0 }, { 8, 9, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, | ||
81 | }, | ||
82 | { "addli", TILEGX_OPC_ADDLI, 0x3, 3, TREG_ZERO, 1, | ||
83 | { { 6, 7, 4 }, { 8, 9, 5 }, { 0, }, { 0, }, { 0, } }, | ||
84 | }, | ||
85 | { "addx", TILEGX_OPC_ADDX, 0xf, 3, TREG_ZERO, 1, | ||
86 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
87 | }, | ||
88 | { "addxi", TILEGX_OPC_ADDXI, 0xf, 3, TREG_ZERO, 1, | ||
89 | { { 6, 7, 0 }, { 8, 9, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, | ||
90 | }, | ||
91 | { "addxli", TILEGX_OPC_ADDXLI, 0x3, 3, TREG_ZERO, 1, | ||
92 | { { 6, 7, 4 }, { 8, 9, 5 }, { 0, }, { 0, }, { 0, } }, | ||
93 | }, | ||
94 | { "addxsc", TILEGX_OPC_ADDXSC, 0x3, 3, TREG_ZERO, 1, | ||
95 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
96 | }, | ||
97 | { "and", TILEGX_OPC_AND, 0xf, 3, TREG_ZERO, 1, | ||
98 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
99 | }, | ||
100 | { "andi", TILEGX_OPC_ANDI, 0xf, 3, TREG_ZERO, 1, | ||
101 | { { 6, 7, 0 }, { 8, 9, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, | ||
102 | }, | ||
103 | { "beqz", TILEGX_OPC_BEQZ, 0x2, 2, TREG_ZERO, 1, | ||
104 | { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, | ||
105 | }, | ||
106 | { "beqzt", TILEGX_OPC_BEQZT, 0x2, 2, TREG_ZERO, 1, | ||
107 | { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, | ||
108 | }, | ||
109 | { "bfexts", TILEGX_OPC_BFEXTS, 0x1, 4, TREG_ZERO, 1, | ||
110 | { { 6, 7, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
111 | }, | ||
112 | { "bfextu", TILEGX_OPC_BFEXTU, 0x1, 4, TREG_ZERO, 1, | ||
113 | { { 6, 7, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
114 | }, | ||
115 | { "bfins", TILEGX_OPC_BFINS, 0x1, 4, TREG_ZERO, 1, | ||
116 | { { 23, 7, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
117 | }, | ||
118 | { "bgez", TILEGX_OPC_BGEZ, 0x2, 2, TREG_ZERO, 1, | ||
119 | { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, | ||
120 | }, | ||
121 | { "bgezt", TILEGX_OPC_BGEZT, 0x2, 2, TREG_ZERO, 1, | ||
122 | { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, | ||
123 | }, | ||
124 | { "bgtz", TILEGX_OPC_BGTZ, 0x2, 2, TREG_ZERO, 1, | ||
125 | { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, | ||
126 | }, | ||
127 | { "bgtzt", TILEGX_OPC_BGTZT, 0x2, 2, TREG_ZERO, 1, | ||
128 | { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, | ||
129 | }, | ||
130 | { "blbc", TILEGX_OPC_BLBC, 0x2, 2, TREG_ZERO, 1, | ||
131 | { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, | ||
132 | }, | ||
133 | { "blbct", TILEGX_OPC_BLBCT, 0x2, 2, TREG_ZERO, 1, | ||
134 | { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, | ||
135 | }, | ||
136 | { "blbs", TILEGX_OPC_BLBS, 0x2, 2, TREG_ZERO, 1, | ||
137 | { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, | ||
138 | }, | ||
139 | { "blbst", TILEGX_OPC_BLBST, 0x2, 2, TREG_ZERO, 1, | ||
140 | { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, | ||
141 | }, | ||
142 | { "blez", TILEGX_OPC_BLEZ, 0x2, 2, TREG_ZERO, 1, | ||
143 | { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, | ||
144 | }, | ||
145 | { "blezt", TILEGX_OPC_BLEZT, 0x2, 2, TREG_ZERO, 1, | ||
146 | { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, | ||
147 | }, | ||
148 | { "bltz", TILEGX_OPC_BLTZ, 0x2, 2, TREG_ZERO, 1, | ||
149 | { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, | ||
150 | }, | ||
151 | { "bltzt", TILEGX_OPC_BLTZT, 0x2, 2, TREG_ZERO, 1, | ||
152 | { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, | ||
153 | }, | ||
154 | { "bnez", TILEGX_OPC_BNEZ, 0x2, 2, TREG_ZERO, 1, | ||
155 | { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, | ||
156 | }, | ||
157 | { "bnezt", TILEGX_OPC_BNEZT, 0x2, 2, TREG_ZERO, 1, | ||
158 | { { 0, }, { 9, 20 }, { 0, }, { 0, }, { 0, } }, | ||
159 | }, | ||
160 | { "clz", TILEGX_OPC_CLZ, 0x5, 2, TREG_ZERO, 1, | ||
161 | { { 6, 7 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, | ||
162 | }, | ||
163 | { "cmoveqz", TILEGX_OPC_CMOVEQZ, 0x5, 3, TREG_ZERO, 1, | ||
164 | { { 23, 7, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, | ||
165 | }, | ||
166 | { "cmovnez", TILEGX_OPC_CMOVNEZ, 0x5, 3, TREG_ZERO, 1, | ||
167 | { { 23, 7, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, | ||
168 | }, | ||
169 | { "cmpeq", TILEGX_OPC_CMPEQ, 0xf, 3, TREG_ZERO, 1, | ||
170 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
171 | }, | ||
172 | { "cmpeqi", TILEGX_OPC_CMPEQI, 0xf, 3, TREG_ZERO, 1, | ||
173 | { { 6, 7, 0 }, { 8, 9, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, | ||
174 | }, | ||
175 | { "cmpexch", TILEGX_OPC_CMPEXCH, 0x2, 3, TREG_ZERO, 1, | ||
176 | { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
177 | }, | ||
178 | { "cmpexch4", TILEGX_OPC_CMPEXCH4, 0x2, 3, TREG_ZERO, 1, | ||
179 | { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
180 | }, | ||
181 | { "cmples", TILEGX_OPC_CMPLES, 0xf, 3, TREG_ZERO, 1, | ||
182 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
183 | }, | ||
184 | { "cmpleu", TILEGX_OPC_CMPLEU, 0xf, 3, TREG_ZERO, 1, | ||
185 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
186 | }, | ||
187 | { "cmplts", TILEGX_OPC_CMPLTS, 0xf, 3, TREG_ZERO, 1, | ||
188 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
189 | }, | ||
190 | { "cmpltsi", TILEGX_OPC_CMPLTSI, 0xf, 3, TREG_ZERO, 1, | ||
191 | { { 6, 7, 0 }, { 8, 9, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, | ||
192 | }, | ||
193 | { "cmpltu", TILEGX_OPC_CMPLTU, 0xf, 3, TREG_ZERO, 1, | ||
194 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
195 | }, | ||
196 | { "cmpltui", TILEGX_OPC_CMPLTUI, 0x3, 3, TREG_ZERO, 1, | ||
197 | { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, | ||
198 | }, | ||
199 | { "cmpne", TILEGX_OPC_CMPNE, 0xf, 3, TREG_ZERO, 1, | ||
200 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
201 | }, | ||
202 | { "cmul", TILEGX_OPC_CMUL, 0x1, 3, TREG_ZERO, 1, | ||
203 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
204 | }, | ||
205 | { "cmula", TILEGX_OPC_CMULA, 0x1, 3, TREG_ZERO, 1, | ||
206 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
207 | }, | ||
208 | { "cmulaf", TILEGX_OPC_CMULAF, 0x1, 3, TREG_ZERO, 1, | ||
209 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
210 | }, | ||
211 | { "cmulf", TILEGX_OPC_CMULF, 0x1, 3, TREG_ZERO, 1, | ||
212 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
213 | }, | ||
214 | { "cmulfr", TILEGX_OPC_CMULFR, 0x1, 3, TREG_ZERO, 1, | ||
215 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
216 | }, | ||
217 | { "cmulh", TILEGX_OPC_CMULH, 0x1, 3, TREG_ZERO, 1, | ||
218 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
219 | }, | ||
220 | { "cmulhr", TILEGX_OPC_CMULHR, 0x1, 3, TREG_ZERO, 1, | ||
221 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
222 | }, | ||
223 | { "crc32_32", TILEGX_OPC_CRC32_32, 0x1, 3, TREG_ZERO, 1, | ||
224 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
225 | }, | ||
226 | { "crc32_8", TILEGX_OPC_CRC32_8, 0x1, 3, TREG_ZERO, 1, | ||
227 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
228 | }, | ||
229 | { "ctz", TILEGX_OPC_CTZ, 0x5, 2, TREG_ZERO, 1, | ||
230 | { { 6, 7 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, | ||
231 | }, | ||
232 | { "dblalign", TILEGX_OPC_DBLALIGN, 0x1, 3, TREG_ZERO, 1, | ||
233 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
234 | }, | ||
235 | { "dblalign2", TILEGX_OPC_DBLALIGN2, 0x3, 3, TREG_ZERO, 1, | ||
236 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
237 | }, | ||
238 | { "dblalign4", TILEGX_OPC_DBLALIGN4, 0x3, 3, TREG_ZERO, 1, | ||
239 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
240 | }, | ||
241 | { "dblalign6", TILEGX_OPC_DBLALIGN6, 0x3, 3, TREG_ZERO, 1, | ||
242 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
243 | }, | ||
244 | { "drain", TILEGX_OPC_DRAIN, 0x2, 0, TREG_ZERO, 0, | ||
245 | { { 0, }, { }, { 0, }, { 0, }, { 0, } }, | ||
246 | }, | ||
247 | { "dtlbpr", TILEGX_OPC_DTLBPR, 0x2, 1, TREG_ZERO, 1, | ||
248 | { { 0, }, { 9 }, { 0, }, { 0, }, { 0, } }, | ||
249 | }, | ||
250 | { "exch", TILEGX_OPC_EXCH, 0x2, 3, TREG_ZERO, 1, | ||
251 | { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
252 | }, | ||
253 | { "exch4", TILEGX_OPC_EXCH4, 0x2, 3, TREG_ZERO, 1, | ||
254 | { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
255 | }, | ||
256 | { "fdouble_add_flags", TILEGX_OPC_FDOUBLE_ADD_FLAGS, 0x1, 3, TREG_ZERO, 1, | ||
257 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
258 | }, | ||
259 | { "fdouble_addsub", TILEGX_OPC_FDOUBLE_ADDSUB, 0x1, 3, TREG_ZERO, 1, | ||
260 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
261 | }, | ||
262 | { "fdouble_mul_flags", TILEGX_OPC_FDOUBLE_MUL_FLAGS, 0x1, 3, TREG_ZERO, 1, | ||
263 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
264 | }, | ||
265 | { "fdouble_pack1", TILEGX_OPC_FDOUBLE_PACK1, 0x1, 3, TREG_ZERO, 1, | ||
266 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
267 | }, | ||
268 | { "fdouble_pack2", TILEGX_OPC_FDOUBLE_PACK2, 0x1, 3, TREG_ZERO, 1, | ||
269 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
270 | }, | ||
271 | { "fdouble_sub_flags", TILEGX_OPC_FDOUBLE_SUB_FLAGS, 0x1, 3, TREG_ZERO, 1, | ||
272 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
273 | }, | ||
274 | { "fdouble_unpack_max", TILEGX_OPC_FDOUBLE_UNPACK_MAX, 0x1, 3, TREG_ZERO, 1, | ||
275 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
276 | }, | ||
277 | { "fdouble_unpack_min", TILEGX_OPC_FDOUBLE_UNPACK_MIN, 0x1, 3, TREG_ZERO, 1, | ||
278 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
279 | }, | ||
280 | { "fetchadd", TILEGX_OPC_FETCHADD, 0x2, 3, TREG_ZERO, 1, | ||
281 | { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
282 | }, | ||
283 | { "fetchadd4", TILEGX_OPC_FETCHADD4, 0x2, 3, TREG_ZERO, 1, | ||
284 | { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
285 | }, | ||
286 | { "fetchaddgez", TILEGX_OPC_FETCHADDGEZ, 0x2, 3, TREG_ZERO, 1, | ||
287 | { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
288 | }, | ||
289 | { "fetchaddgez4", TILEGX_OPC_FETCHADDGEZ4, 0x2, 3, TREG_ZERO, 1, | ||
290 | { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
291 | }, | ||
292 | { "fetchand", TILEGX_OPC_FETCHAND, 0x2, 3, TREG_ZERO, 1, | ||
293 | { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
294 | }, | ||
295 | { "fetchand4", TILEGX_OPC_FETCHAND4, 0x2, 3, TREG_ZERO, 1, | ||
296 | { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
297 | }, | ||
298 | { "fetchor", TILEGX_OPC_FETCHOR, 0x2, 3, TREG_ZERO, 1, | ||
299 | { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
300 | }, | ||
301 | { "fetchor4", TILEGX_OPC_FETCHOR4, 0x2, 3, TREG_ZERO, 1, | ||
302 | { { 0, }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
303 | }, | ||
304 | { "finv", TILEGX_OPC_FINV, 0x2, 1, TREG_ZERO, 1, | ||
305 | { { 0, }, { 9 }, { 0, }, { 0, }, { 0, } }, | ||
306 | }, | ||
307 | { "flush", TILEGX_OPC_FLUSH, 0x2, 1, TREG_ZERO, 1, | ||
308 | { { 0, }, { 9 }, { 0, }, { 0, }, { 0, } }, | ||
309 | }, | ||
310 | { "flushwb", TILEGX_OPC_FLUSHWB, 0x2, 0, TREG_ZERO, 1, | ||
311 | { { 0, }, { }, { 0, }, { 0, }, { 0, } }, | ||
312 | }, | ||
313 | { "fnop", TILEGX_OPC_FNOP, 0xf, 0, TREG_ZERO, 1, | ||
314 | { { }, { }, { }, { }, { 0, } }, | ||
315 | }, | ||
316 | { "fsingle_add1", TILEGX_OPC_FSINGLE_ADD1, 0x1, 3, TREG_ZERO, 1, | ||
317 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
318 | }, | ||
319 | { "fsingle_addsub2", TILEGX_OPC_FSINGLE_ADDSUB2, 0x1, 3, TREG_ZERO, 1, | ||
320 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
321 | }, | ||
322 | { "fsingle_mul1", TILEGX_OPC_FSINGLE_MUL1, 0x1, 3, TREG_ZERO, 1, | ||
323 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
324 | }, | ||
325 | { "fsingle_mul2", TILEGX_OPC_FSINGLE_MUL2, 0x1, 3, TREG_ZERO, 1, | ||
326 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
327 | }, | ||
328 | { "fsingle_pack1", TILEGX_OPC_FSINGLE_PACK1, 0x5, 2, TREG_ZERO, 1, | ||
329 | { { 6, 7 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, | ||
330 | }, | ||
331 | { "fsingle_pack2", TILEGX_OPC_FSINGLE_PACK2, 0x1, 3, TREG_ZERO, 1, | ||
332 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
333 | }, | ||
334 | { "fsingle_sub1", TILEGX_OPC_FSINGLE_SUB1, 0x1, 3, TREG_ZERO, 1, | ||
335 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
336 | }, | ||
337 | { "icoh", TILEGX_OPC_ICOH, 0x2, 1, TREG_ZERO, 1, | ||
338 | { { 0, }, { 9 }, { 0, }, { 0, }, { 0, } }, | ||
339 | }, | ||
340 | { "ill", TILEGX_OPC_ILL, 0xa, 0, TREG_ZERO, 1, | ||
341 | { { 0, }, { }, { 0, }, { }, { 0, } }, | ||
342 | }, | ||
343 | { "inv", TILEGX_OPC_INV, 0x2, 1, TREG_ZERO, 1, | ||
344 | { { 0, }, { 9 }, { 0, }, { 0, }, { 0, } }, | ||
345 | }, | ||
346 | { "iret", TILEGX_OPC_IRET, 0x2, 0, TREG_ZERO, 1, | ||
347 | { { 0, }, { }, { 0, }, { 0, }, { 0, } }, | ||
348 | }, | ||
349 | { "j", TILEGX_OPC_J, 0x2, 1, TREG_ZERO, 1, | ||
350 | { { 0, }, { 25 }, { 0, }, { 0, }, { 0, } }, | ||
351 | }, | ||
352 | { "jal", TILEGX_OPC_JAL, 0x2, 1, TREG_LR, 1, | ||
353 | { { 0, }, { 25 }, { 0, }, { 0, }, { 0, } }, | ||
354 | }, | ||
355 | { "jalr", TILEGX_OPC_JALR, 0xa, 1, TREG_LR, 1, | ||
356 | { { 0, }, { 9 }, { 0, }, { 13 }, { 0, } }, | ||
357 | }, | ||
358 | { "jalrp", TILEGX_OPC_JALRP, 0xa, 1, TREG_LR, 1, | ||
359 | { { 0, }, { 9 }, { 0, }, { 13 }, { 0, } }, | ||
360 | }, | ||
361 | { "jr", TILEGX_OPC_JR, 0xa, 1, TREG_ZERO, 1, | ||
362 | { { 0, }, { 9 }, { 0, }, { 13 }, { 0, } }, | ||
363 | }, | ||
364 | { "jrp", TILEGX_OPC_JRP, 0xa, 1, TREG_ZERO, 1, | ||
365 | { { 0, }, { 9 }, { 0, }, { 13 }, { 0, } }, | ||
366 | }, | ||
367 | { "ld", TILEGX_OPC_LD, 0x12, 2, TREG_ZERO, 1, | ||
368 | { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 26, 14 } }, | ||
369 | }, | ||
370 | { "ld1s", TILEGX_OPC_LD1S, 0x12, 2, TREG_ZERO, 1, | ||
371 | { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 26, 14 } }, | ||
372 | }, | ||
373 | { "ld1s_add", TILEGX_OPC_LD1S_ADD, 0x2, 3, TREG_ZERO, 1, | ||
374 | { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
375 | }, | ||
376 | { "ld1u", TILEGX_OPC_LD1U, 0x12, 2, TREG_ZERO, 1, | ||
377 | { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 26, 14 } }, | ||
378 | }, | ||
379 | { "ld1u_add", TILEGX_OPC_LD1U_ADD, 0x2, 3, TREG_ZERO, 1, | ||
380 | { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
381 | }, | ||
382 | { "ld2s", TILEGX_OPC_LD2S, 0x12, 2, TREG_ZERO, 1, | ||
383 | { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 26, 14 } }, | ||
384 | }, | ||
385 | { "ld2s_add", TILEGX_OPC_LD2S_ADD, 0x2, 3, TREG_ZERO, 1, | ||
386 | { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
387 | }, | ||
388 | { "ld2u", TILEGX_OPC_LD2U, 0x12, 2, TREG_ZERO, 1, | ||
389 | { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 26, 14 } }, | ||
390 | }, | ||
391 | { "ld2u_add", TILEGX_OPC_LD2U_ADD, 0x2, 3, TREG_ZERO, 1, | ||
392 | { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
393 | }, | ||
394 | { "ld4s", TILEGX_OPC_LD4S, 0x12, 2, TREG_ZERO, 1, | ||
395 | { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 26, 14 } }, | ||
396 | }, | ||
397 | { "ld4s_add", TILEGX_OPC_LD4S_ADD, 0x2, 3, TREG_ZERO, 1, | ||
398 | { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
399 | }, | ||
400 | { "ld4u", TILEGX_OPC_LD4U, 0x12, 2, TREG_ZERO, 1, | ||
401 | { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 26, 14 } }, | ||
402 | }, | ||
403 | { "ld4u_add", TILEGX_OPC_LD4U_ADD, 0x2, 3, TREG_ZERO, 1, | ||
404 | { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
405 | }, | ||
406 | { "ld_add", TILEGX_OPC_LD_ADD, 0x2, 3, TREG_ZERO, 1, | ||
407 | { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
408 | }, | ||
409 | { "ldna", TILEGX_OPC_LDNA, 0x2, 2, TREG_ZERO, 1, | ||
410 | { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 0, } }, | ||
411 | }, | ||
412 | { "ldna_add", TILEGX_OPC_LDNA_ADD, 0x2, 3, TREG_ZERO, 1, | ||
413 | { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
414 | }, | ||
415 | { "ldnt", TILEGX_OPC_LDNT, 0x2, 2, TREG_ZERO, 1, | ||
416 | { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 0, } }, | ||
417 | }, | ||
418 | { "ldnt1s", TILEGX_OPC_LDNT1S, 0x2, 2, TREG_ZERO, 1, | ||
419 | { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 0, } }, | ||
420 | }, | ||
421 | { "ldnt1s_add", TILEGX_OPC_LDNT1S_ADD, 0x2, 3, TREG_ZERO, 1, | ||
422 | { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
423 | }, | ||
424 | { "ldnt1u", TILEGX_OPC_LDNT1U, 0x2, 2, TREG_ZERO, 1, | ||
425 | { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 0, } }, | ||
426 | }, | ||
427 | { "ldnt1u_add", TILEGX_OPC_LDNT1U_ADD, 0x2, 3, TREG_ZERO, 1, | ||
428 | { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
429 | }, | ||
430 | { "ldnt2s", TILEGX_OPC_LDNT2S, 0x2, 2, TREG_ZERO, 1, | ||
431 | { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 0, } }, | ||
432 | }, | ||
433 | { "ldnt2s_add", TILEGX_OPC_LDNT2S_ADD, 0x2, 3, TREG_ZERO, 1, | ||
434 | { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
435 | }, | ||
436 | { "ldnt2u", TILEGX_OPC_LDNT2U, 0x2, 2, TREG_ZERO, 1, | ||
437 | { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 0, } }, | ||
438 | }, | ||
439 | { "ldnt2u_add", TILEGX_OPC_LDNT2U_ADD, 0x2, 3, TREG_ZERO, 1, | ||
440 | { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
441 | }, | ||
442 | { "ldnt4s", TILEGX_OPC_LDNT4S, 0x2, 2, TREG_ZERO, 1, | ||
443 | { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 0, } }, | ||
444 | }, | ||
445 | { "ldnt4s_add", TILEGX_OPC_LDNT4S_ADD, 0x2, 3, TREG_ZERO, 1, | ||
446 | { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
447 | }, | ||
448 | { "ldnt4u", TILEGX_OPC_LDNT4U, 0x2, 2, TREG_ZERO, 1, | ||
449 | { { 0, }, { 8, 9 }, { 0, }, { 0, }, { 0, } }, | ||
450 | }, | ||
451 | { "ldnt4u_add", TILEGX_OPC_LDNT4U_ADD, 0x2, 3, TREG_ZERO, 1, | ||
452 | { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
453 | }, | ||
454 | { "ldnt_add", TILEGX_OPC_LDNT_ADD, 0x2, 3, TREG_ZERO, 1, | ||
455 | { { 0, }, { 8, 15, 1 }, { 0, }, { 0, }, { 0, } }, | ||
456 | }, | ||
457 | { "lnk", TILEGX_OPC_LNK, 0xa, 1, TREG_ZERO, 1, | ||
458 | { { 0, }, { 8 }, { 0, }, { 12 }, { 0, } }, | ||
459 | }, | ||
460 | { "mf", TILEGX_OPC_MF, 0x2, 0, TREG_ZERO, 1, | ||
461 | { { 0, }, { }, { 0, }, { 0, }, { 0, } }, | ||
462 | }, | ||
463 | { "mfspr", TILEGX_OPC_MFSPR, 0x2, 2, TREG_ZERO, 1, | ||
464 | { { 0, }, { 8, 27 }, { 0, }, { 0, }, { 0, } }, | ||
465 | }, | ||
466 | { "mm", TILEGX_OPC_MM, 0x1, 4, TREG_ZERO, 1, | ||
467 | { { 23, 7, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
468 | }, | ||
469 | { "mnz", TILEGX_OPC_MNZ, 0xf, 3, TREG_ZERO, 1, | ||
470 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
471 | }, | ||
472 | { "mtspr", TILEGX_OPC_MTSPR, 0x2, 2, TREG_ZERO, 1, | ||
473 | { { 0, }, { 28, 9 }, { 0, }, { 0, }, { 0, } }, | ||
474 | }, | ||
475 | { "mul_hs_hs", TILEGX_OPC_MUL_HS_HS, 0x5, 3, TREG_ZERO, 1, | ||
476 | { { 6, 7, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, | ||
477 | }, | ||
478 | { "mul_hs_hu", TILEGX_OPC_MUL_HS_HU, 0x1, 3, TREG_ZERO, 1, | ||
479 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
480 | }, | ||
481 | { "mul_hs_ls", TILEGX_OPC_MUL_HS_LS, 0x1, 3, TREG_ZERO, 1, | ||
482 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
483 | }, | ||
484 | { "mul_hs_lu", TILEGX_OPC_MUL_HS_LU, 0x1, 3, TREG_ZERO, 1, | ||
485 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
486 | }, | ||
487 | { "mul_hu_hu", TILEGX_OPC_MUL_HU_HU, 0x5, 3, TREG_ZERO, 1, | ||
488 | { { 6, 7, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, | ||
489 | }, | ||
490 | { "mul_hu_ls", TILEGX_OPC_MUL_HU_LS, 0x1, 3, TREG_ZERO, 1, | ||
491 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
492 | }, | ||
493 | { "mul_hu_lu", TILEGX_OPC_MUL_HU_LU, 0x1, 3, TREG_ZERO, 1, | ||
494 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
495 | }, | ||
496 | { "mul_ls_ls", TILEGX_OPC_MUL_LS_LS, 0x5, 3, TREG_ZERO, 1, | ||
497 | { { 6, 7, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, | ||
498 | }, | ||
499 | { "mul_ls_lu", TILEGX_OPC_MUL_LS_LU, 0x1, 3, TREG_ZERO, 1, | ||
500 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
501 | }, | ||
502 | { "mul_lu_lu", TILEGX_OPC_MUL_LU_LU, 0x5, 3, TREG_ZERO, 1, | ||
503 | { { 6, 7, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, | ||
504 | }, | ||
505 | { "mula_hs_hs", TILEGX_OPC_MULA_HS_HS, 0x5, 3, TREG_ZERO, 1, | ||
506 | { { 23, 7, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, | ||
507 | }, | ||
508 | { "mula_hs_hu", TILEGX_OPC_MULA_HS_HU, 0x1, 3, TREG_ZERO, 1, | ||
509 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
510 | }, | ||
511 | { "mula_hs_ls", TILEGX_OPC_MULA_HS_LS, 0x1, 3, TREG_ZERO, 1, | ||
512 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
513 | }, | ||
514 | { "mula_hs_lu", TILEGX_OPC_MULA_HS_LU, 0x1, 3, TREG_ZERO, 1, | ||
515 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
516 | }, | ||
517 | { "mula_hu_hu", TILEGX_OPC_MULA_HU_HU, 0x5, 3, TREG_ZERO, 1, | ||
518 | { { 23, 7, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, | ||
519 | }, | ||
520 | { "mula_hu_ls", TILEGX_OPC_MULA_HU_LS, 0x1, 3, TREG_ZERO, 1, | ||
521 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
522 | }, | ||
523 | { "mula_hu_lu", TILEGX_OPC_MULA_HU_LU, 0x1, 3, TREG_ZERO, 1, | ||
524 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
525 | }, | ||
526 | { "mula_ls_ls", TILEGX_OPC_MULA_LS_LS, 0x5, 3, TREG_ZERO, 1, | ||
527 | { { 23, 7, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, | ||
528 | }, | ||
529 | { "mula_ls_lu", TILEGX_OPC_MULA_LS_LU, 0x1, 3, TREG_ZERO, 1, | ||
530 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
531 | }, | ||
532 | { "mula_lu_lu", TILEGX_OPC_MULA_LU_LU, 0x5, 3, TREG_ZERO, 1, | ||
533 | { { 23, 7, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, | ||
534 | }, | ||
535 | { "mulax", TILEGX_OPC_MULAX, 0x5, 3, TREG_ZERO, 1, | ||
536 | { { 23, 7, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, | ||
537 | }, | ||
538 | { "mulx", TILEGX_OPC_MULX, 0x5, 3, TREG_ZERO, 1, | ||
539 | { { 6, 7, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, | ||
540 | }, | ||
541 | { "mz", TILEGX_OPC_MZ, 0xf, 3, TREG_ZERO, 1, | ||
542 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
543 | }, | ||
544 | { "nap", TILEGX_OPC_NAP, 0x2, 0, TREG_ZERO, 0, | ||
545 | { { 0, }, { }, { 0, }, { 0, }, { 0, } }, | ||
546 | }, | ||
547 | { "nop", TILEGX_OPC_NOP, 0xf, 0, TREG_ZERO, 1, | ||
548 | { { }, { }, { }, { }, { 0, } }, | ||
549 | }, | ||
550 | { "nor", TILEGX_OPC_NOR, 0xf, 3, TREG_ZERO, 1, | ||
551 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
552 | }, | ||
553 | { "or", TILEGX_OPC_OR, 0xf, 3, TREG_ZERO, 1, | ||
554 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
555 | }, | ||
556 | { "ori", TILEGX_OPC_ORI, 0x3, 3, TREG_ZERO, 1, | ||
557 | { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, | ||
558 | }, | ||
559 | { "pcnt", TILEGX_OPC_PCNT, 0x5, 2, TREG_ZERO, 1, | ||
560 | { { 6, 7 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, | ||
561 | }, | ||
562 | { "revbits", TILEGX_OPC_REVBITS, 0x5, 2, TREG_ZERO, 1, | ||
563 | { { 6, 7 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, | ||
564 | }, | ||
565 | { "revbytes", TILEGX_OPC_REVBYTES, 0x5, 2, TREG_ZERO, 1, | ||
566 | { { 6, 7 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, | ||
567 | }, | ||
568 | { "rotl", TILEGX_OPC_ROTL, 0xf, 3, TREG_ZERO, 1, | ||
569 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
570 | }, | ||
571 | { "rotli", TILEGX_OPC_ROTLI, 0xf, 3, TREG_ZERO, 1, | ||
572 | { { 6, 7, 29 }, { 8, 9, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } }, | ||
573 | }, | ||
574 | { "shl", TILEGX_OPC_SHL, 0xf, 3, TREG_ZERO, 1, | ||
575 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
576 | }, | ||
577 | { "shl16insli", TILEGX_OPC_SHL16INSLI, 0x3, 3, TREG_ZERO, 1, | ||
578 | { { 6, 7, 4 }, { 8, 9, 5 }, { 0, }, { 0, }, { 0, } }, | ||
579 | }, | ||
580 | { "shl1add", TILEGX_OPC_SHL1ADD, 0xf, 3, TREG_ZERO, 1, | ||
581 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
582 | }, | ||
583 | { "shl1addx", TILEGX_OPC_SHL1ADDX, 0xf, 3, TREG_ZERO, 1, | ||
584 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
585 | }, | ||
586 | { "shl2add", TILEGX_OPC_SHL2ADD, 0xf, 3, TREG_ZERO, 1, | ||
587 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
588 | }, | ||
589 | { "shl2addx", TILEGX_OPC_SHL2ADDX, 0xf, 3, TREG_ZERO, 1, | ||
590 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
591 | }, | ||
592 | { "shl3add", TILEGX_OPC_SHL3ADD, 0xf, 3, TREG_ZERO, 1, | ||
593 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
594 | }, | ||
595 | { "shl3addx", TILEGX_OPC_SHL3ADDX, 0xf, 3, TREG_ZERO, 1, | ||
596 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
597 | }, | ||
598 | { "shli", TILEGX_OPC_SHLI, 0xf, 3, TREG_ZERO, 1, | ||
599 | { { 6, 7, 29 }, { 8, 9, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } }, | ||
600 | }, | ||
601 | { "shlx", TILEGX_OPC_SHLX, 0x3, 3, TREG_ZERO, 1, | ||
602 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
603 | }, | ||
604 | { "shlxi", TILEGX_OPC_SHLXI, 0x3, 3, TREG_ZERO, 1, | ||
605 | { { 6, 7, 29 }, { 8, 9, 30 }, { 0, }, { 0, }, { 0, } }, | ||
606 | }, | ||
607 | { "shrs", TILEGX_OPC_SHRS, 0xf, 3, TREG_ZERO, 1, | ||
608 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
609 | }, | ||
610 | { "shrsi", TILEGX_OPC_SHRSI, 0xf, 3, TREG_ZERO, 1, | ||
611 | { { 6, 7, 29 }, { 8, 9, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } }, | ||
612 | }, | ||
613 | { "shru", TILEGX_OPC_SHRU, 0xf, 3, TREG_ZERO, 1, | ||
614 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
615 | }, | ||
616 | { "shrui", TILEGX_OPC_SHRUI, 0xf, 3, TREG_ZERO, 1, | ||
617 | { { 6, 7, 29 }, { 8, 9, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } }, | ||
618 | }, | ||
619 | { "shrux", TILEGX_OPC_SHRUX, 0x3, 3, TREG_ZERO, 1, | ||
620 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
621 | }, | ||
622 | { "shruxi", TILEGX_OPC_SHRUXI, 0x3, 3, TREG_ZERO, 1, | ||
623 | { { 6, 7, 29 }, { 8, 9, 30 }, { 0, }, { 0, }, { 0, } }, | ||
624 | }, | ||
625 | { "shufflebytes", TILEGX_OPC_SHUFFLEBYTES, 0x1, 3, TREG_ZERO, 1, | ||
626 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
627 | }, | ||
628 | { "st", TILEGX_OPC_ST, 0x12, 2, TREG_ZERO, 1, | ||
629 | { { 0, }, { 9, 17 }, { 0, }, { 0, }, { 14, 33 } }, | ||
630 | }, | ||
631 | { "st1", TILEGX_OPC_ST1, 0x12, 2, TREG_ZERO, 1, | ||
632 | { { 0, }, { 9, 17 }, { 0, }, { 0, }, { 14, 33 } }, | ||
633 | }, | ||
634 | { "st1_add", TILEGX_OPC_ST1_ADD, 0x2, 3, TREG_ZERO, 1, | ||
635 | { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, | ||
636 | }, | ||
637 | { "st2", TILEGX_OPC_ST2, 0x12, 2, TREG_ZERO, 1, | ||
638 | { { 0, }, { 9, 17 }, { 0, }, { 0, }, { 14, 33 } }, | ||
639 | }, | ||
640 | { "st2_add", TILEGX_OPC_ST2_ADD, 0x2, 3, TREG_ZERO, 1, | ||
641 | { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, | ||
642 | }, | ||
643 | { "st4", TILEGX_OPC_ST4, 0x12, 2, TREG_ZERO, 1, | ||
644 | { { 0, }, { 9, 17 }, { 0, }, { 0, }, { 14, 33 } }, | ||
645 | }, | ||
646 | { "st4_add", TILEGX_OPC_ST4_ADD, 0x2, 3, TREG_ZERO, 1, | ||
647 | { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, | ||
648 | }, | ||
649 | { "st_add", TILEGX_OPC_ST_ADD, 0x2, 3, TREG_ZERO, 1, | ||
650 | { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, | ||
651 | }, | ||
652 | { "stnt", TILEGX_OPC_STNT, 0x2, 2, TREG_ZERO, 1, | ||
653 | { { 0, }, { 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
654 | }, | ||
655 | { "stnt1", TILEGX_OPC_STNT1, 0x2, 2, TREG_ZERO, 1, | ||
656 | { { 0, }, { 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
657 | }, | ||
658 | { "stnt1_add", TILEGX_OPC_STNT1_ADD, 0x2, 3, TREG_ZERO, 1, | ||
659 | { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, | ||
660 | }, | ||
661 | { "stnt2", TILEGX_OPC_STNT2, 0x2, 2, TREG_ZERO, 1, | ||
662 | { { 0, }, { 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
663 | }, | ||
664 | { "stnt2_add", TILEGX_OPC_STNT2_ADD, 0x2, 3, TREG_ZERO, 1, | ||
665 | { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, | ||
666 | }, | ||
667 | { "stnt4", TILEGX_OPC_STNT4, 0x2, 2, TREG_ZERO, 1, | ||
668 | { { 0, }, { 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
669 | }, | ||
670 | { "stnt4_add", TILEGX_OPC_STNT4_ADD, 0x2, 3, TREG_ZERO, 1, | ||
671 | { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, | ||
672 | }, | ||
673 | { "stnt_add", TILEGX_OPC_STNT_ADD, 0x2, 3, TREG_ZERO, 1, | ||
674 | { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, | ||
675 | }, | ||
676 | { "sub", TILEGX_OPC_SUB, 0xf, 3, TREG_ZERO, 1, | ||
677 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
678 | }, | ||
679 | { "subx", TILEGX_OPC_SUBX, 0xf, 3, TREG_ZERO, 1, | ||
680 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
681 | }, | ||
682 | { "subxsc", TILEGX_OPC_SUBXSC, 0x3, 3, TREG_ZERO, 1, | ||
683 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
684 | }, | ||
685 | { "swint0", TILEGX_OPC_SWINT0, 0x2, 0, TREG_ZERO, 0, | ||
686 | { { 0, }, { }, { 0, }, { 0, }, { 0, } }, | ||
687 | }, | ||
688 | { "swint1", TILEGX_OPC_SWINT1, 0x2, 0, TREG_ZERO, 0, | ||
689 | { { 0, }, { }, { 0, }, { 0, }, { 0, } }, | ||
690 | }, | ||
691 | { "swint2", TILEGX_OPC_SWINT2, 0x2, 0, TREG_ZERO, 0, | ||
692 | { { 0, }, { }, { 0, }, { 0, }, { 0, } }, | ||
693 | }, | ||
694 | { "swint3", TILEGX_OPC_SWINT3, 0x2, 0, TREG_ZERO, 0, | ||
695 | { { 0, }, { }, { 0, }, { 0, }, { 0, } }, | ||
696 | }, | ||
697 | { "tblidxb0", TILEGX_OPC_TBLIDXB0, 0x5, 2, TREG_ZERO, 1, | ||
698 | { { 23, 7 }, { 0, }, { 24, 11 }, { 0, }, { 0, } }, | ||
699 | }, | ||
700 | { "tblidxb1", TILEGX_OPC_TBLIDXB1, 0x5, 2, TREG_ZERO, 1, | ||
701 | { { 23, 7 }, { 0, }, { 24, 11 }, { 0, }, { 0, } }, | ||
702 | }, | ||
703 | { "tblidxb2", TILEGX_OPC_TBLIDXB2, 0x5, 2, TREG_ZERO, 1, | ||
704 | { { 23, 7 }, { 0, }, { 24, 11 }, { 0, }, { 0, } }, | ||
705 | }, | ||
706 | { "tblidxb3", TILEGX_OPC_TBLIDXB3, 0x5, 2, TREG_ZERO, 1, | ||
707 | { { 23, 7 }, { 0, }, { 24, 11 }, { 0, }, { 0, } }, | ||
708 | }, | ||
709 | { "v1add", TILEGX_OPC_V1ADD, 0x3, 3, TREG_ZERO, 1, | ||
710 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
711 | }, | ||
712 | { "v1addi", TILEGX_OPC_V1ADDI, 0x3, 3, TREG_ZERO, 1, | ||
713 | { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, | ||
714 | }, | ||
715 | { "v1adduc", TILEGX_OPC_V1ADDUC, 0x3, 3, TREG_ZERO, 1, | ||
716 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
717 | }, | ||
718 | { "v1adiffu", TILEGX_OPC_V1ADIFFU, 0x1, 3, TREG_ZERO, 1, | ||
719 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
720 | }, | ||
721 | { "v1avgu", TILEGX_OPC_V1AVGU, 0x1, 3, TREG_ZERO, 1, | ||
722 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
723 | }, | ||
724 | { "v1cmpeq", TILEGX_OPC_V1CMPEQ, 0x3, 3, TREG_ZERO, 1, | ||
725 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
726 | }, | ||
727 | { "v1cmpeqi", TILEGX_OPC_V1CMPEQI, 0x3, 3, TREG_ZERO, 1, | ||
728 | { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, | ||
729 | }, | ||
730 | { "v1cmples", TILEGX_OPC_V1CMPLES, 0x3, 3, TREG_ZERO, 1, | ||
731 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
732 | }, | ||
733 | { "v1cmpleu", TILEGX_OPC_V1CMPLEU, 0x3, 3, TREG_ZERO, 1, | ||
734 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
735 | }, | ||
736 | { "v1cmplts", TILEGX_OPC_V1CMPLTS, 0x3, 3, TREG_ZERO, 1, | ||
737 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
738 | }, | ||
739 | { "v1cmpltsi", TILEGX_OPC_V1CMPLTSI, 0x3, 3, TREG_ZERO, 1, | ||
740 | { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, | ||
741 | }, | ||
742 | { "v1cmpltu", TILEGX_OPC_V1CMPLTU, 0x3, 3, TREG_ZERO, 1, | ||
743 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
744 | }, | ||
745 | { "v1cmpltui", TILEGX_OPC_V1CMPLTUI, 0x3, 3, TREG_ZERO, 1, | ||
746 | { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, | ||
747 | }, | ||
748 | { "v1cmpne", TILEGX_OPC_V1CMPNE, 0x3, 3, TREG_ZERO, 1, | ||
749 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
750 | }, | ||
751 | { "v1ddotpu", TILEGX_OPC_V1DDOTPU, 0x1, 3, TREG_ZERO, 1, | ||
752 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
753 | }, | ||
754 | { "v1ddotpua", TILEGX_OPC_V1DDOTPUA, 0x1, 3, TREG_ZERO, 1, | ||
755 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
756 | }, | ||
757 | { "v1ddotpus", TILEGX_OPC_V1DDOTPUS, 0x1, 3, TREG_ZERO, 1, | ||
758 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
759 | }, | ||
760 | { "v1ddotpusa", TILEGX_OPC_V1DDOTPUSA, 0x1, 3, TREG_ZERO, 1, | ||
761 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
762 | }, | ||
763 | { "v1dotp", TILEGX_OPC_V1DOTP, 0x1, 3, TREG_ZERO, 1, | ||
764 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
765 | }, | ||
766 | { "v1dotpa", TILEGX_OPC_V1DOTPA, 0x1, 3, TREG_ZERO, 1, | ||
767 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
768 | }, | ||
769 | { "v1dotpu", TILEGX_OPC_V1DOTPU, 0x1, 3, TREG_ZERO, 1, | ||
770 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
771 | }, | ||
772 | { "v1dotpua", TILEGX_OPC_V1DOTPUA, 0x1, 3, TREG_ZERO, 1, | ||
773 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
774 | }, | ||
775 | { "v1dotpus", TILEGX_OPC_V1DOTPUS, 0x1, 3, TREG_ZERO, 1, | ||
776 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
777 | }, | ||
778 | { "v1dotpusa", TILEGX_OPC_V1DOTPUSA, 0x1, 3, TREG_ZERO, 1, | ||
779 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
780 | }, | ||
781 | { "v1int_h", TILEGX_OPC_V1INT_H, 0x3, 3, TREG_ZERO, 1, | ||
782 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
783 | }, | ||
784 | { "v1int_l", TILEGX_OPC_V1INT_L, 0x3, 3, TREG_ZERO, 1, | ||
785 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
786 | }, | ||
787 | { "v1maxu", TILEGX_OPC_V1MAXU, 0x3, 3, TREG_ZERO, 1, | ||
788 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
789 | }, | ||
790 | { "v1maxui", TILEGX_OPC_V1MAXUI, 0x3, 3, TREG_ZERO, 1, | ||
791 | { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, | ||
792 | }, | ||
793 | { "v1minu", TILEGX_OPC_V1MINU, 0x3, 3, TREG_ZERO, 1, | ||
794 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
795 | }, | ||
796 | { "v1minui", TILEGX_OPC_V1MINUI, 0x3, 3, TREG_ZERO, 1, | ||
797 | { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, | ||
798 | }, | ||
799 | { "v1mnz", TILEGX_OPC_V1MNZ, 0x3, 3, TREG_ZERO, 1, | ||
800 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
801 | }, | ||
802 | { "v1multu", TILEGX_OPC_V1MULTU, 0x1, 3, TREG_ZERO, 1, | ||
803 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
804 | }, | ||
805 | { "v1mulu", TILEGX_OPC_V1MULU, 0x1, 3, TREG_ZERO, 1, | ||
806 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
807 | }, | ||
808 | { "v1mulus", TILEGX_OPC_V1MULUS, 0x1, 3, TREG_ZERO, 1, | ||
809 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
810 | }, | ||
811 | { "v1mz", TILEGX_OPC_V1MZ, 0x3, 3, TREG_ZERO, 1, | ||
812 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
813 | }, | ||
814 | { "v1sadau", TILEGX_OPC_V1SADAU, 0x1, 3, TREG_ZERO, 1, | ||
815 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
816 | }, | ||
817 | { "v1sadu", TILEGX_OPC_V1SADU, 0x1, 3, TREG_ZERO, 1, | ||
818 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
819 | }, | ||
820 | { "v1shl", TILEGX_OPC_V1SHL, 0x3, 3, TREG_ZERO, 1, | ||
821 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
822 | }, | ||
823 | { "v1shli", TILEGX_OPC_V1SHLI, 0x3, 3, TREG_ZERO, 1, | ||
824 | { { 6, 7, 29 }, { 8, 9, 30 }, { 0, }, { 0, }, { 0, } }, | ||
825 | }, | ||
826 | { "v1shrs", TILEGX_OPC_V1SHRS, 0x3, 3, TREG_ZERO, 1, | ||
827 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
828 | }, | ||
829 | { "v1shrsi", TILEGX_OPC_V1SHRSI, 0x3, 3, TREG_ZERO, 1, | ||
830 | { { 6, 7, 29 }, { 8, 9, 30 }, { 0, }, { 0, }, { 0, } }, | ||
831 | }, | ||
832 | { "v1shru", TILEGX_OPC_V1SHRU, 0x3, 3, TREG_ZERO, 1, | ||
833 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
834 | }, | ||
835 | { "v1shrui", TILEGX_OPC_V1SHRUI, 0x3, 3, TREG_ZERO, 1, | ||
836 | { { 6, 7, 29 }, { 8, 9, 30 }, { 0, }, { 0, }, { 0, } }, | ||
837 | }, | ||
838 | { "v1sub", TILEGX_OPC_V1SUB, 0x3, 3, TREG_ZERO, 1, | ||
839 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
840 | }, | ||
841 | { "v1subuc", TILEGX_OPC_V1SUBUC, 0x3, 3, TREG_ZERO, 1, | ||
842 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
843 | }, | ||
844 | { "v2add", TILEGX_OPC_V2ADD, 0x3, 3, TREG_ZERO, 1, | ||
845 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
846 | }, | ||
847 | { "v2addi", TILEGX_OPC_V2ADDI, 0x3, 3, TREG_ZERO, 1, | ||
848 | { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, | ||
849 | }, | ||
850 | { "v2addsc", TILEGX_OPC_V2ADDSC, 0x3, 3, TREG_ZERO, 1, | ||
851 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
852 | }, | ||
853 | { "v2adiffs", TILEGX_OPC_V2ADIFFS, 0x1, 3, TREG_ZERO, 1, | ||
854 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
855 | }, | ||
856 | { "v2avgs", TILEGX_OPC_V2AVGS, 0x1, 3, TREG_ZERO, 1, | ||
857 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
858 | }, | ||
859 | { "v2cmpeq", TILEGX_OPC_V2CMPEQ, 0x3, 3, TREG_ZERO, 1, | ||
860 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
861 | }, | ||
862 | { "v2cmpeqi", TILEGX_OPC_V2CMPEQI, 0x3, 3, TREG_ZERO, 1, | ||
863 | { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, | ||
864 | }, | ||
865 | { "v2cmples", TILEGX_OPC_V2CMPLES, 0x3, 3, TREG_ZERO, 1, | ||
866 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
867 | }, | ||
868 | { "v2cmpleu", TILEGX_OPC_V2CMPLEU, 0x3, 3, TREG_ZERO, 1, | ||
869 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
870 | }, | ||
871 | { "v2cmplts", TILEGX_OPC_V2CMPLTS, 0x3, 3, TREG_ZERO, 1, | ||
872 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
873 | }, | ||
874 | { "v2cmpltsi", TILEGX_OPC_V2CMPLTSI, 0x3, 3, TREG_ZERO, 1, | ||
875 | { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, | ||
876 | }, | ||
877 | { "v2cmpltu", TILEGX_OPC_V2CMPLTU, 0x3, 3, TREG_ZERO, 1, | ||
878 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
879 | }, | ||
880 | { "v2cmpltui", TILEGX_OPC_V2CMPLTUI, 0x3, 3, TREG_ZERO, 1, | ||
881 | { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, | ||
882 | }, | ||
883 | { "v2cmpne", TILEGX_OPC_V2CMPNE, 0x3, 3, TREG_ZERO, 1, | ||
884 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
885 | }, | ||
886 | { "v2dotp", TILEGX_OPC_V2DOTP, 0x1, 3, TREG_ZERO, 1, | ||
887 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
888 | }, | ||
889 | { "v2dotpa", TILEGX_OPC_V2DOTPA, 0x1, 3, TREG_ZERO, 1, | ||
890 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
891 | }, | ||
892 | { "v2int_h", TILEGX_OPC_V2INT_H, 0x3, 3, TREG_ZERO, 1, | ||
893 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
894 | }, | ||
895 | { "v2int_l", TILEGX_OPC_V2INT_L, 0x3, 3, TREG_ZERO, 1, | ||
896 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
897 | }, | ||
898 | { "v2maxs", TILEGX_OPC_V2MAXS, 0x3, 3, TREG_ZERO, 1, | ||
899 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
900 | }, | ||
901 | { "v2maxsi", TILEGX_OPC_V2MAXSI, 0x3, 3, TREG_ZERO, 1, | ||
902 | { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, | ||
903 | }, | ||
904 | { "v2mins", TILEGX_OPC_V2MINS, 0x3, 3, TREG_ZERO, 1, | ||
905 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
906 | }, | ||
907 | { "v2minsi", TILEGX_OPC_V2MINSI, 0x3, 3, TREG_ZERO, 1, | ||
908 | { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, | ||
909 | }, | ||
910 | { "v2mnz", TILEGX_OPC_V2MNZ, 0x3, 3, TREG_ZERO, 1, | ||
911 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
912 | }, | ||
913 | { "v2mulfsc", TILEGX_OPC_V2MULFSC, 0x1, 3, TREG_ZERO, 1, | ||
914 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
915 | }, | ||
916 | { "v2muls", TILEGX_OPC_V2MULS, 0x1, 3, TREG_ZERO, 1, | ||
917 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
918 | }, | ||
919 | { "v2mults", TILEGX_OPC_V2MULTS, 0x1, 3, TREG_ZERO, 1, | ||
920 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
921 | }, | ||
922 | { "v2mz", TILEGX_OPC_V2MZ, 0x3, 3, TREG_ZERO, 1, | ||
923 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
924 | }, | ||
925 | { "v2packh", TILEGX_OPC_V2PACKH, 0x3, 3, TREG_ZERO, 1, | ||
926 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
927 | }, | ||
928 | { "v2packl", TILEGX_OPC_V2PACKL, 0x3, 3, TREG_ZERO, 1, | ||
929 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
930 | }, | ||
931 | { "v2packuc", TILEGX_OPC_V2PACKUC, 0x3, 3, TREG_ZERO, 1, | ||
932 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
933 | }, | ||
934 | { "v2sadas", TILEGX_OPC_V2SADAS, 0x1, 3, TREG_ZERO, 1, | ||
935 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
936 | }, | ||
937 | { "v2sadau", TILEGX_OPC_V2SADAU, 0x1, 3, TREG_ZERO, 1, | ||
938 | { { 23, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
939 | }, | ||
940 | { "v2sads", TILEGX_OPC_V2SADS, 0x1, 3, TREG_ZERO, 1, | ||
941 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
942 | }, | ||
943 | { "v2sadu", TILEGX_OPC_V2SADU, 0x1, 3, TREG_ZERO, 1, | ||
944 | { { 6, 7, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, | ||
945 | }, | ||
946 | { "v2shl", TILEGX_OPC_V2SHL, 0x3, 3, TREG_ZERO, 1, | ||
947 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
948 | }, | ||
949 | { "v2shli", TILEGX_OPC_V2SHLI, 0x3, 3, TREG_ZERO, 1, | ||
950 | { { 6, 7, 29 }, { 8, 9, 30 }, { 0, }, { 0, }, { 0, } }, | ||
951 | }, | ||
952 | { "v2shlsc", TILEGX_OPC_V2SHLSC, 0x3, 3, TREG_ZERO, 1, | ||
953 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
954 | }, | ||
955 | { "v2shrs", TILEGX_OPC_V2SHRS, 0x3, 3, TREG_ZERO, 1, | ||
956 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
957 | }, | ||
958 | { "v2shrsi", TILEGX_OPC_V2SHRSI, 0x3, 3, TREG_ZERO, 1, | ||
959 | { { 6, 7, 29 }, { 8, 9, 30 }, { 0, }, { 0, }, { 0, } }, | ||
960 | }, | ||
961 | { "v2shru", TILEGX_OPC_V2SHRU, 0x3, 3, TREG_ZERO, 1, | ||
962 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
963 | }, | ||
964 | { "v2shrui", TILEGX_OPC_V2SHRUI, 0x3, 3, TREG_ZERO, 1, | ||
965 | { { 6, 7, 29 }, { 8, 9, 30 }, { 0, }, { 0, }, { 0, } }, | ||
966 | }, | ||
967 | { "v2sub", TILEGX_OPC_V2SUB, 0x3, 3, TREG_ZERO, 1, | ||
968 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
969 | }, | ||
970 | { "v2subsc", TILEGX_OPC_V2SUBSC, 0x3, 3, TREG_ZERO, 1, | ||
971 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
972 | }, | ||
973 | { "v4add", TILEGX_OPC_V4ADD, 0x3, 3, TREG_ZERO, 1, | ||
974 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
975 | }, | ||
976 | { "v4addsc", TILEGX_OPC_V4ADDSC, 0x3, 3, TREG_ZERO, 1, | ||
977 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
978 | }, | ||
979 | { "v4int_h", TILEGX_OPC_V4INT_H, 0x3, 3, TREG_ZERO, 1, | ||
980 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
981 | }, | ||
982 | { "v4int_l", TILEGX_OPC_V4INT_L, 0x3, 3, TREG_ZERO, 1, | ||
983 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
984 | }, | ||
985 | { "v4packsc", TILEGX_OPC_V4PACKSC, 0x3, 3, TREG_ZERO, 1, | ||
986 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
987 | }, | ||
988 | { "v4shl", TILEGX_OPC_V4SHL, 0x3, 3, TREG_ZERO, 1, | ||
989 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
990 | }, | ||
991 | { "v4shlsc", TILEGX_OPC_V4SHLSC, 0x3, 3, TREG_ZERO, 1, | ||
992 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
993 | }, | ||
994 | { "v4shrs", TILEGX_OPC_V4SHRS, 0x3, 3, TREG_ZERO, 1, | ||
995 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
996 | }, | ||
997 | { "v4shru", TILEGX_OPC_V4SHRU, 0x3, 3, TREG_ZERO, 1, | ||
998 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
999 | }, | ||
1000 | { "v4sub", TILEGX_OPC_V4SUB, 0x3, 3, TREG_ZERO, 1, | ||
1001 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
1002 | }, | ||
1003 | { "v4subsc", TILEGX_OPC_V4SUBSC, 0x3, 3, TREG_ZERO, 1, | ||
1004 | { { 6, 7, 16 }, { 8, 9, 17 }, { 0, }, { 0, }, { 0, } }, | ||
1005 | }, | ||
1006 | { "wh64", TILEGX_OPC_WH64, 0x2, 1, TREG_ZERO, 1, | ||
1007 | { { 0, }, { 9 }, { 0, }, { 0, }, { 0, } }, | ||
1008 | }, | ||
1009 | { "xor", TILEGX_OPC_XOR, 0xf, 3, TREG_ZERO, 1, | ||
1010 | { { 6, 7, 16 }, { 8, 9, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, | ||
1011 | }, | ||
1012 | { "xori", TILEGX_OPC_XORI, 0x3, 3, TREG_ZERO, 1, | ||
1013 | { { 6, 7, 0 }, { 8, 9, 1 }, { 0, }, { 0, }, { 0, } }, | ||
1014 | }, | ||
1015 | { NULL, TILEGX_OPC_NONE, 0, 0, TREG_ZERO, 0, { { 0, } }, | ||
1016 | } | ||
1017 | }; | ||
1018 | #define BITFIELD(start, size) ((start) | (((1 << (size)) - 1) << 6)) | ||
1019 | #define CHILD(array_index) (TILEGX_OPC_NONE + (array_index)) | ||
1020 | |||
1021 | static const unsigned short decode_X0_fsm[936] = | ||
1022 | { | ||
1023 | BITFIELD(22, 9) /* index 0 */, | ||
1024 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1025 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1026 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1027 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1028 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1029 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1030 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1031 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1032 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1033 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1034 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1035 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1036 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1037 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1038 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1039 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1040 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1041 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1042 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1043 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1044 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1045 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1046 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1047 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1048 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1049 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1050 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), TILEGX_OPC_ADDXLI, | ||
1051 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1052 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1053 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1054 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1055 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1056 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1057 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1058 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1059 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1060 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1061 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1062 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1063 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1064 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1065 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1066 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_NONE, | ||
1067 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1068 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1069 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1070 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_BFEXTS, | ||
1071 | TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTU, | ||
1072 | TILEGX_OPC_BFEXTU, TILEGX_OPC_BFEXTU, TILEGX_OPC_BFEXTU, TILEGX_OPC_BFINS, | ||
1073 | TILEGX_OPC_BFINS, TILEGX_OPC_BFINS, TILEGX_OPC_BFINS, TILEGX_OPC_MM, | ||
1074 | TILEGX_OPC_MM, TILEGX_OPC_MM, TILEGX_OPC_MM, TILEGX_OPC_NONE, | ||
1075 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1076 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1077 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1078 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1079 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1080 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1081 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1082 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(528), CHILD(578), | ||
1083 | CHILD(583), CHILD(588), CHILD(593), CHILD(598), TILEGX_OPC_NONE, | ||
1084 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1085 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1086 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1087 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1088 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1089 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1090 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1091 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1092 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1093 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1094 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1095 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1096 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1097 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1098 | TILEGX_OPC_NONE, CHILD(603), CHILD(620), CHILD(637), CHILD(654), CHILD(671), | ||
1099 | CHILD(703), CHILD(797), CHILD(814), CHILD(831), CHILD(848), CHILD(865), | ||
1100 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1101 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1102 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1103 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1104 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1105 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1106 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1107 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1108 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1109 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1110 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1111 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1112 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1113 | TILEGX_OPC_NONE, CHILD(889), TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1114 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1115 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1116 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1117 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1118 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1119 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1120 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1121 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1122 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1123 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1124 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1125 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1126 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1127 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1128 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1129 | TILEGX_OPC_NONE, CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), | ||
1130 | CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), | ||
1131 | CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), | ||
1132 | CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), | ||
1133 | CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), | ||
1134 | CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), | ||
1135 | CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), | ||
1136 | CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), | ||
1137 | CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), | ||
1138 | CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), | ||
1139 | CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), | ||
1140 | BITFIELD(6, 2) /* index 513 */, | ||
1141 | TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(518), | ||
1142 | BITFIELD(8, 2) /* index 518 */, | ||
1143 | TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(523), | ||
1144 | BITFIELD(10, 2) /* index 523 */, | ||
1145 | TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_MOVELI, | ||
1146 | BITFIELD(20, 2) /* index 528 */, | ||
1147 | TILEGX_OPC_NONE, CHILD(533), TILEGX_OPC_ADDXI, CHILD(548), | ||
1148 | BITFIELD(6, 2) /* index 533 */, | ||
1149 | TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(538), | ||
1150 | BITFIELD(8, 2) /* index 538 */, | ||
1151 | TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(543), | ||
1152 | BITFIELD(10, 2) /* index 543 */, | ||
1153 | TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI, | ||
1154 | BITFIELD(0, 2) /* index 548 */, | ||
1155 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(553), | ||
1156 | BITFIELD(2, 2) /* index 553 */, | ||
1157 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(558), | ||
1158 | BITFIELD(4, 2) /* index 558 */, | ||
1159 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(563), | ||
1160 | BITFIELD(6, 2) /* index 563 */, | ||
1161 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(568), | ||
1162 | BITFIELD(8, 2) /* index 568 */, | ||
1163 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(573), | ||
1164 | BITFIELD(10, 2) /* index 573 */, | ||
1165 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO, | ||
1166 | BITFIELD(20, 2) /* index 578 */, | ||
1167 | TILEGX_OPC_CMPEQI, TILEGX_OPC_CMPLTSI, TILEGX_OPC_CMPLTUI, TILEGX_OPC_ORI, | ||
1168 | BITFIELD(20, 2) /* index 583 */, | ||
1169 | TILEGX_OPC_V1ADDI, TILEGX_OPC_V1CMPEQI, TILEGX_OPC_V1CMPLTSI, | ||
1170 | TILEGX_OPC_V1CMPLTUI, | ||
1171 | BITFIELD(20, 2) /* index 588 */, | ||
1172 | TILEGX_OPC_V1MAXUI, TILEGX_OPC_V1MINUI, TILEGX_OPC_V2ADDI, | ||
1173 | TILEGX_OPC_V2CMPEQI, | ||
1174 | BITFIELD(20, 2) /* index 593 */, | ||
1175 | TILEGX_OPC_V2CMPLTSI, TILEGX_OPC_V2CMPLTUI, TILEGX_OPC_V2MAXSI, | ||
1176 | TILEGX_OPC_V2MINSI, | ||
1177 | BITFIELD(20, 2) /* index 598 */, | ||
1178 | TILEGX_OPC_XORI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1179 | BITFIELD(18, 4) /* index 603 */, | ||
1180 | TILEGX_OPC_NONE, TILEGX_OPC_ADDXSC, TILEGX_OPC_ADDX, TILEGX_OPC_ADD, | ||
1181 | TILEGX_OPC_AND, TILEGX_OPC_CMOVEQZ, TILEGX_OPC_CMOVNEZ, TILEGX_OPC_CMPEQ, | ||
1182 | TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU, | ||
1183 | TILEGX_OPC_CMPNE, TILEGX_OPC_CMULAF, TILEGX_OPC_CMULA, TILEGX_OPC_CMULFR, | ||
1184 | BITFIELD(18, 4) /* index 620 */, | ||
1185 | TILEGX_OPC_CMULF, TILEGX_OPC_CMULHR, TILEGX_OPC_CMULH, TILEGX_OPC_CMUL, | ||
1186 | TILEGX_OPC_CRC32_32, TILEGX_OPC_CRC32_8, TILEGX_OPC_DBLALIGN2, | ||
1187 | TILEGX_OPC_DBLALIGN4, TILEGX_OPC_DBLALIGN6, TILEGX_OPC_DBLALIGN, | ||
1188 | TILEGX_OPC_FDOUBLE_ADDSUB, TILEGX_OPC_FDOUBLE_ADD_FLAGS, | ||
1189 | TILEGX_OPC_FDOUBLE_MUL_FLAGS, TILEGX_OPC_FDOUBLE_PACK1, | ||
1190 | TILEGX_OPC_FDOUBLE_PACK2, TILEGX_OPC_FDOUBLE_SUB_FLAGS, | ||
1191 | BITFIELD(18, 4) /* index 637 */, | ||
1192 | TILEGX_OPC_FDOUBLE_UNPACK_MAX, TILEGX_OPC_FDOUBLE_UNPACK_MIN, | ||
1193 | TILEGX_OPC_FSINGLE_ADD1, TILEGX_OPC_FSINGLE_ADDSUB2, | ||
1194 | TILEGX_OPC_FSINGLE_MUL1, TILEGX_OPC_FSINGLE_MUL2, TILEGX_OPC_FSINGLE_PACK2, | ||
1195 | TILEGX_OPC_FSINGLE_SUB1, TILEGX_OPC_MNZ, TILEGX_OPC_MULAX, | ||
1196 | TILEGX_OPC_MULA_HS_HS, TILEGX_OPC_MULA_HS_HU, TILEGX_OPC_MULA_HS_LS, | ||
1197 | TILEGX_OPC_MULA_HS_LU, TILEGX_OPC_MULA_HU_HU, TILEGX_OPC_MULA_HU_LS, | ||
1198 | BITFIELD(18, 4) /* index 654 */, | ||
1199 | TILEGX_OPC_MULA_HU_LU, TILEGX_OPC_MULA_LS_LS, TILEGX_OPC_MULA_LS_LU, | ||
1200 | TILEGX_OPC_MULA_LU_LU, TILEGX_OPC_MULX, TILEGX_OPC_MUL_HS_HS, | ||
1201 | TILEGX_OPC_MUL_HS_HU, TILEGX_OPC_MUL_HS_LS, TILEGX_OPC_MUL_HS_LU, | ||
1202 | TILEGX_OPC_MUL_HU_HU, TILEGX_OPC_MUL_HU_LS, TILEGX_OPC_MUL_HU_LU, | ||
1203 | TILEGX_OPC_MUL_LS_LS, TILEGX_OPC_MUL_LS_LU, TILEGX_OPC_MUL_LU_LU, | ||
1204 | TILEGX_OPC_MZ, | ||
1205 | BITFIELD(18, 4) /* index 671 */, | ||
1206 | TILEGX_OPC_NOR, CHILD(688), TILEGX_OPC_ROTL, TILEGX_OPC_SHL1ADDX, | ||
1207 | TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADDX, TILEGX_OPC_SHL2ADD, | ||
1208 | TILEGX_OPC_SHL3ADDX, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHLX, TILEGX_OPC_SHL, | ||
1209 | TILEGX_OPC_SHRS, TILEGX_OPC_SHRUX, TILEGX_OPC_SHRU, TILEGX_OPC_SHUFFLEBYTES, | ||
1210 | TILEGX_OPC_SUBXSC, | ||
1211 | BITFIELD(12, 2) /* index 688 */, | ||
1212 | TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(693), | ||
1213 | BITFIELD(14, 2) /* index 693 */, | ||
1214 | TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(698), | ||
1215 | BITFIELD(16, 2) /* index 698 */, | ||
1216 | TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE, | ||
1217 | BITFIELD(18, 4) /* index 703 */, | ||
1218 | TILEGX_OPC_SUBX, TILEGX_OPC_SUB, CHILD(720), TILEGX_OPC_V1ADDUC, | ||
1219 | TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADIFFU, TILEGX_OPC_V1AVGU, | ||
1220 | TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLEU, | ||
1221 | TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPNE, | ||
1222 | TILEGX_OPC_V1DDOTPUSA, TILEGX_OPC_V1DDOTPUS, TILEGX_OPC_V1DOTPA, | ||
1223 | BITFIELD(12, 4) /* index 720 */, | ||
1224 | TILEGX_OPC_NONE, CHILD(737), CHILD(742), CHILD(747), CHILD(752), CHILD(757), | ||
1225 | CHILD(762), CHILD(767), CHILD(772), CHILD(777), CHILD(782), CHILD(787), | ||
1226 | CHILD(792), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1227 | BITFIELD(16, 2) /* index 737 */, | ||
1228 | TILEGX_OPC_CLZ, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1229 | BITFIELD(16, 2) /* index 742 */, | ||
1230 | TILEGX_OPC_CTZ, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1231 | BITFIELD(16, 2) /* index 747 */, | ||
1232 | TILEGX_OPC_FNOP, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1233 | BITFIELD(16, 2) /* index 752 */, | ||
1234 | TILEGX_OPC_FSINGLE_PACK1, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1235 | BITFIELD(16, 2) /* index 757 */, | ||
1236 | TILEGX_OPC_NOP, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1237 | BITFIELD(16, 2) /* index 762 */, | ||
1238 | TILEGX_OPC_PCNT, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1239 | BITFIELD(16, 2) /* index 767 */, | ||
1240 | TILEGX_OPC_REVBITS, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1241 | BITFIELD(16, 2) /* index 772 */, | ||
1242 | TILEGX_OPC_REVBYTES, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1243 | BITFIELD(16, 2) /* index 777 */, | ||
1244 | TILEGX_OPC_TBLIDXB0, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1245 | BITFIELD(16, 2) /* index 782 */, | ||
1246 | TILEGX_OPC_TBLIDXB1, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1247 | BITFIELD(16, 2) /* index 787 */, | ||
1248 | TILEGX_OPC_TBLIDXB2, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1249 | BITFIELD(16, 2) /* index 792 */, | ||
1250 | TILEGX_OPC_TBLIDXB3, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1251 | BITFIELD(18, 4) /* index 797 */, | ||
1252 | TILEGX_OPC_V1DOTPUSA, TILEGX_OPC_V1DOTPUS, TILEGX_OPC_V1DOTP, | ||
1253 | TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1MAXU, | ||
1254 | TILEGX_OPC_V1MINU, TILEGX_OPC_V1MNZ, TILEGX_OPC_V1MULTU, TILEGX_OPC_V1MULUS, | ||
1255 | TILEGX_OPC_V1MULU, TILEGX_OPC_V1MZ, TILEGX_OPC_V1SADAU, TILEGX_OPC_V1SADU, | ||
1256 | TILEGX_OPC_V1SHL, TILEGX_OPC_V1SHRS, | ||
1257 | BITFIELD(18, 4) /* index 814 */, | ||
1258 | TILEGX_OPC_V1SHRU, TILEGX_OPC_V1SUBUC, TILEGX_OPC_V1SUB, TILEGX_OPC_V2ADDSC, | ||
1259 | TILEGX_OPC_V2ADD, TILEGX_OPC_V2ADIFFS, TILEGX_OPC_V2AVGS, | ||
1260 | TILEGX_OPC_V2CMPEQ, TILEGX_OPC_V2CMPLES, TILEGX_OPC_V2CMPLEU, | ||
1261 | TILEGX_OPC_V2CMPLTS, TILEGX_OPC_V2CMPLTU, TILEGX_OPC_V2CMPNE, | ||
1262 | TILEGX_OPC_V2DOTPA, TILEGX_OPC_V2DOTP, TILEGX_OPC_V2INT_H, | ||
1263 | BITFIELD(18, 4) /* index 831 */, | ||
1264 | TILEGX_OPC_V2INT_L, TILEGX_OPC_V2MAXS, TILEGX_OPC_V2MINS, TILEGX_OPC_V2MNZ, | ||
1265 | TILEGX_OPC_V2MULFSC, TILEGX_OPC_V2MULS, TILEGX_OPC_V2MULTS, TILEGX_OPC_V2MZ, | ||
1266 | TILEGX_OPC_V2PACKH, TILEGX_OPC_V2PACKL, TILEGX_OPC_V2PACKUC, | ||
1267 | TILEGX_OPC_V2SADAS, TILEGX_OPC_V2SADAU, TILEGX_OPC_V2SADS, | ||
1268 | TILEGX_OPC_V2SADU, TILEGX_OPC_V2SHLSC, | ||
1269 | BITFIELD(18, 4) /* index 848 */, | ||
1270 | TILEGX_OPC_V2SHL, TILEGX_OPC_V2SHRS, TILEGX_OPC_V2SHRU, TILEGX_OPC_V2SUBSC, | ||
1271 | TILEGX_OPC_V2SUB, TILEGX_OPC_V4ADDSC, TILEGX_OPC_V4ADD, TILEGX_OPC_V4INT_H, | ||
1272 | TILEGX_OPC_V4INT_L, TILEGX_OPC_V4PACKSC, TILEGX_OPC_V4SHLSC, | ||
1273 | TILEGX_OPC_V4SHL, TILEGX_OPC_V4SHRS, TILEGX_OPC_V4SHRU, TILEGX_OPC_V4SUBSC, | ||
1274 | TILEGX_OPC_V4SUB, | ||
1275 | BITFIELD(18, 3) /* index 865 */, | ||
1276 | CHILD(874), CHILD(877), CHILD(880), CHILD(883), CHILD(886), TILEGX_OPC_NONE, | ||
1277 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1278 | BITFIELD(21, 1) /* index 874 */, | ||
1279 | TILEGX_OPC_XOR, TILEGX_OPC_NONE, | ||
1280 | BITFIELD(21, 1) /* index 877 */, | ||
1281 | TILEGX_OPC_V1DDOTPUA, TILEGX_OPC_NONE, | ||
1282 | BITFIELD(21, 1) /* index 880 */, | ||
1283 | TILEGX_OPC_V1DDOTPU, TILEGX_OPC_NONE, | ||
1284 | BITFIELD(21, 1) /* index 883 */, | ||
1285 | TILEGX_OPC_V1DOTPUA, TILEGX_OPC_NONE, | ||
1286 | BITFIELD(21, 1) /* index 886 */, | ||
1287 | TILEGX_OPC_V1DOTPU, TILEGX_OPC_NONE, | ||
1288 | BITFIELD(18, 4) /* index 889 */, | ||
1289 | TILEGX_OPC_NONE, TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHLXI, | ||
1290 | TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, TILEGX_OPC_SHRUXI, TILEGX_OPC_V1SHLI, | ||
1291 | TILEGX_OPC_V1SHRSI, TILEGX_OPC_V1SHRUI, TILEGX_OPC_V2SHLI, | ||
1292 | TILEGX_OPC_V2SHRSI, TILEGX_OPC_V2SHRUI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1293 | TILEGX_OPC_NONE, | ||
1294 | BITFIELD(0, 2) /* index 906 */, | ||
1295 | TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, | ||
1296 | CHILD(911), | ||
1297 | BITFIELD(2, 2) /* index 911 */, | ||
1298 | TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, | ||
1299 | CHILD(916), | ||
1300 | BITFIELD(4, 2) /* index 916 */, | ||
1301 | TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, | ||
1302 | CHILD(921), | ||
1303 | BITFIELD(6, 2) /* index 921 */, | ||
1304 | TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, | ||
1305 | CHILD(926), | ||
1306 | BITFIELD(8, 2) /* index 926 */, | ||
1307 | TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, | ||
1308 | CHILD(931), | ||
1309 | BITFIELD(10, 2) /* index 931 */, | ||
1310 | TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, | ||
1311 | TILEGX_OPC_INFOL, | ||
1312 | }; | ||
1313 | |||
1314 | static const unsigned short decode_X1_fsm[1206] = | ||
1315 | { | ||
1316 | BITFIELD(53, 9) /* index 0 */, | ||
1317 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1318 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1319 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1320 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1321 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1322 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1323 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1324 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1325 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1326 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), | ||
1327 | CHILD(513), CHILD(513), CHILD(513), CHILD(513), TILEGX_OPC_ADDXLI, | ||
1328 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1329 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1330 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1331 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1332 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1333 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1334 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1335 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1336 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1337 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1338 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1339 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1340 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1341 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1342 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, | ||
1343 | TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_NONE, | ||
1344 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1345 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1346 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1347 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1348 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1349 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1350 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1351 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_BEQZT, | ||
1352 | TILEGX_OPC_BEQZT, TILEGX_OPC_BEQZ, TILEGX_OPC_BEQZ, TILEGX_OPC_BGEZT, | ||
1353 | TILEGX_OPC_BGEZT, TILEGX_OPC_BGEZ, TILEGX_OPC_BGEZ, TILEGX_OPC_BGTZT, | ||
1354 | TILEGX_OPC_BGTZT, TILEGX_OPC_BGTZ, TILEGX_OPC_BGTZ, TILEGX_OPC_BLBCT, | ||
1355 | TILEGX_OPC_BLBCT, TILEGX_OPC_BLBC, TILEGX_OPC_BLBC, TILEGX_OPC_BLBST, | ||
1356 | TILEGX_OPC_BLBST, TILEGX_OPC_BLBS, TILEGX_OPC_BLBS, TILEGX_OPC_BLEZT, | ||
1357 | TILEGX_OPC_BLEZT, TILEGX_OPC_BLEZ, TILEGX_OPC_BLEZ, TILEGX_OPC_BLTZT, | ||
1358 | TILEGX_OPC_BLTZT, TILEGX_OPC_BLTZ, TILEGX_OPC_BLTZ, TILEGX_OPC_BNEZT, | ||
1359 | TILEGX_OPC_BNEZT, TILEGX_OPC_BNEZ, TILEGX_OPC_BNEZ, CHILD(528), CHILD(578), | ||
1360 | CHILD(598), CHILD(663), CHILD(683), CHILD(688), CHILD(693), CHILD(698), | ||
1361 | CHILD(703), CHILD(708), CHILD(713), CHILD(718), TILEGX_OPC_NONE, | ||
1362 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1363 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1364 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1365 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1366 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1367 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1368 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1369 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1370 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1371 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1372 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1373 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1374 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_JAL, | ||
1375 | TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, | ||
1376 | TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, | ||
1377 | TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, | ||
1378 | TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, | ||
1379 | TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, | ||
1380 | TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, | ||
1381 | TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, | ||
1382 | TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_J, TILEGX_OPC_J, | ||
1383 | TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, | ||
1384 | TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, | ||
1385 | TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, | ||
1386 | TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, | ||
1387 | TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, | ||
1388 | TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, | ||
1389 | CHILD(723), CHILD(740), CHILD(772), CHILD(789), CHILD(1108), CHILD(1125), | ||
1390 | CHILD(1142), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1391 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1392 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1393 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1394 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1395 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1396 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1397 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1398 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1399 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1400 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1401 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1402 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1403 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1404 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(1159), TILEGX_OPC_NONE, | ||
1405 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1406 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1407 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1408 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1409 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1410 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1411 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1412 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1413 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1414 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1415 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1416 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1417 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1418 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1419 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1420 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(1176), CHILD(1176), CHILD(1176), | ||
1421 | CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), | ||
1422 | CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), | ||
1423 | CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), | ||
1424 | CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), | ||
1425 | CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), | ||
1426 | CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), | ||
1427 | CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), | ||
1428 | CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), | ||
1429 | CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), | ||
1430 | CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), | ||
1431 | CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), | ||
1432 | CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), CHILD(1176), | ||
1433 | CHILD(1176), | ||
1434 | BITFIELD(37, 2) /* index 513 */, | ||
1435 | TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(518), | ||
1436 | BITFIELD(39, 2) /* index 518 */, | ||
1437 | TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(523), | ||
1438 | BITFIELD(41, 2) /* index 523 */, | ||
1439 | TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_MOVELI, | ||
1440 | BITFIELD(51, 2) /* index 528 */, | ||
1441 | TILEGX_OPC_NONE, CHILD(533), TILEGX_OPC_ADDXI, CHILD(548), | ||
1442 | BITFIELD(37, 2) /* index 533 */, | ||
1443 | TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(538), | ||
1444 | BITFIELD(39, 2) /* index 538 */, | ||
1445 | TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(543), | ||
1446 | BITFIELD(41, 2) /* index 543 */, | ||
1447 | TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI, | ||
1448 | BITFIELD(31, 2) /* index 548 */, | ||
1449 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(553), | ||
1450 | BITFIELD(33, 2) /* index 553 */, | ||
1451 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(558), | ||
1452 | BITFIELD(35, 2) /* index 558 */, | ||
1453 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(563), | ||
1454 | BITFIELD(37, 2) /* index 563 */, | ||
1455 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(568), | ||
1456 | BITFIELD(39, 2) /* index 568 */, | ||
1457 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(573), | ||
1458 | BITFIELD(41, 2) /* index 573 */, | ||
1459 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO, | ||
1460 | BITFIELD(51, 2) /* index 578 */, | ||
1461 | TILEGX_OPC_CMPEQI, TILEGX_OPC_CMPLTSI, TILEGX_OPC_CMPLTUI, CHILD(583), | ||
1462 | BITFIELD(31, 2) /* index 583 */, | ||
1463 | TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, CHILD(588), | ||
1464 | BITFIELD(33, 2) /* index 588 */, | ||
1465 | TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, CHILD(593), | ||
1466 | BITFIELD(35, 2) /* index 593 */, | ||
1467 | TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, | ||
1468 | TILEGX_OPC_PREFETCH_ADD_L1_FAULT, | ||
1469 | BITFIELD(51, 2) /* index 598 */, | ||
1470 | CHILD(603), CHILD(618), CHILD(633), CHILD(648), | ||
1471 | BITFIELD(31, 2) /* index 603 */, | ||
1472 | TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, CHILD(608), | ||
1473 | BITFIELD(33, 2) /* index 608 */, | ||
1474 | TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, CHILD(613), | ||
1475 | BITFIELD(35, 2) /* index 613 */, | ||
1476 | TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, | ||
1477 | TILEGX_OPC_PREFETCH_ADD_L1, | ||
1478 | BITFIELD(31, 2) /* index 618 */, | ||
1479 | TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, CHILD(623), | ||
1480 | BITFIELD(33, 2) /* index 623 */, | ||
1481 | TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, CHILD(628), | ||
1482 | BITFIELD(35, 2) /* index 628 */, | ||
1483 | TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, | ||
1484 | TILEGX_OPC_PREFETCH_ADD_L2_FAULT, | ||
1485 | BITFIELD(31, 2) /* index 633 */, | ||
1486 | TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, CHILD(638), | ||
1487 | BITFIELD(33, 2) /* index 638 */, | ||
1488 | TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, CHILD(643), | ||
1489 | BITFIELD(35, 2) /* index 643 */, | ||
1490 | TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, | ||
1491 | TILEGX_OPC_PREFETCH_ADD_L2, | ||
1492 | BITFIELD(31, 2) /* index 648 */, | ||
1493 | TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, CHILD(653), | ||
1494 | BITFIELD(33, 2) /* index 653 */, | ||
1495 | TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, CHILD(658), | ||
1496 | BITFIELD(35, 2) /* index 658 */, | ||
1497 | TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, | ||
1498 | TILEGX_OPC_PREFETCH_ADD_L3_FAULT, | ||
1499 | BITFIELD(51, 2) /* index 663 */, | ||
1500 | CHILD(668), TILEGX_OPC_LDNT1S_ADD, TILEGX_OPC_LDNT1U_ADD, | ||
1501 | TILEGX_OPC_LDNT2S_ADD, | ||
1502 | BITFIELD(31, 2) /* index 668 */, | ||
1503 | TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, CHILD(673), | ||
1504 | BITFIELD(33, 2) /* index 673 */, | ||
1505 | TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, CHILD(678), | ||
1506 | BITFIELD(35, 2) /* index 678 */, | ||
1507 | TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, | ||
1508 | TILEGX_OPC_PREFETCH_ADD_L3, | ||
1509 | BITFIELD(51, 2) /* index 683 */, | ||
1510 | TILEGX_OPC_LDNT2U_ADD, TILEGX_OPC_LDNT4S_ADD, TILEGX_OPC_LDNT4U_ADD, | ||
1511 | TILEGX_OPC_LDNT_ADD, | ||
1512 | BITFIELD(51, 2) /* index 688 */, | ||
1513 | TILEGX_OPC_LD_ADD, TILEGX_OPC_LDNA_ADD, TILEGX_OPC_MFSPR, TILEGX_OPC_MTSPR, | ||
1514 | BITFIELD(51, 2) /* index 693 */, | ||
1515 | TILEGX_OPC_ORI, TILEGX_OPC_ST1_ADD, TILEGX_OPC_ST2_ADD, TILEGX_OPC_ST4_ADD, | ||
1516 | BITFIELD(51, 2) /* index 698 */, | ||
1517 | TILEGX_OPC_STNT1_ADD, TILEGX_OPC_STNT2_ADD, TILEGX_OPC_STNT4_ADD, | ||
1518 | TILEGX_OPC_STNT_ADD, | ||
1519 | BITFIELD(51, 2) /* index 703 */, | ||
1520 | TILEGX_OPC_ST_ADD, TILEGX_OPC_V1ADDI, TILEGX_OPC_V1CMPEQI, | ||
1521 | TILEGX_OPC_V1CMPLTSI, | ||
1522 | BITFIELD(51, 2) /* index 708 */, | ||
1523 | TILEGX_OPC_V1CMPLTUI, TILEGX_OPC_V1MAXUI, TILEGX_OPC_V1MINUI, | ||
1524 | TILEGX_OPC_V2ADDI, | ||
1525 | BITFIELD(51, 2) /* index 713 */, | ||
1526 | TILEGX_OPC_V2CMPEQI, TILEGX_OPC_V2CMPLTSI, TILEGX_OPC_V2CMPLTUI, | ||
1527 | TILEGX_OPC_V2MAXSI, | ||
1528 | BITFIELD(51, 2) /* index 718 */, | ||
1529 | TILEGX_OPC_V2MINSI, TILEGX_OPC_XORI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1530 | BITFIELD(49, 4) /* index 723 */, | ||
1531 | TILEGX_OPC_NONE, TILEGX_OPC_ADDXSC, TILEGX_OPC_ADDX, TILEGX_OPC_ADD, | ||
1532 | TILEGX_OPC_AND, TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPEXCH4, TILEGX_OPC_CMPEXCH, | ||
1533 | TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU, | ||
1534 | TILEGX_OPC_CMPNE, TILEGX_OPC_DBLALIGN2, TILEGX_OPC_DBLALIGN4, | ||
1535 | TILEGX_OPC_DBLALIGN6, | ||
1536 | BITFIELD(49, 4) /* index 740 */, | ||
1537 | TILEGX_OPC_EXCH4, TILEGX_OPC_EXCH, TILEGX_OPC_FETCHADD4, | ||
1538 | TILEGX_OPC_FETCHADDGEZ4, TILEGX_OPC_FETCHADDGEZ, TILEGX_OPC_FETCHADD, | ||
1539 | TILEGX_OPC_FETCHAND4, TILEGX_OPC_FETCHAND, TILEGX_OPC_FETCHOR4, | ||
1540 | TILEGX_OPC_FETCHOR, TILEGX_OPC_MNZ, TILEGX_OPC_MZ, TILEGX_OPC_NOR, | ||
1541 | CHILD(757), TILEGX_OPC_ROTL, TILEGX_OPC_SHL1ADDX, | ||
1542 | BITFIELD(43, 2) /* index 757 */, | ||
1543 | TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(762), | ||
1544 | BITFIELD(45, 2) /* index 762 */, | ||
1545 | TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(767), | ||
1546 | BITFIELD(47, 2) /* index 767 */, | ||
1547 | TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE, | ||
1548 | BITFIELD(49, 4) /* index 772 */, | ||
1549 | TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADDX, TILEGX_OPC_SHL2ADD, | ||
1550 | TILEGX_OPC_SHL3ADDX, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHLX, TILEGX_OPC_SHL, | ||
1551 | TILEGX_OPC_SHRS, TILEGX_OPC_SHRUX, TILEGX_OPC_SHRU, TILEGX_OPC_ST1, | ||
1552 | TILEGX_OPC_ST2, TILEGX_OPC_ST4, TILEGX_OPC_STNT1, TILEGX_OPC_STNT2, | ||
1553 | TILEGX_OPC_STNT4, | ||
1554 | BITFIELD(46, 7) /* index 789 */, | ||
1555 | TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, | ||
1556 | TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, | ||
1557 | TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, | ||
1558 | TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_SUBXSC, | ||
1559 | TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, | ||
1560 | TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBX, | ||
1561 | TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, | ||
1562 | TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUB, | ||
1563 | TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, | ||
1564 | TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, CHILD(918), CHILD(927), | ||
1565 | CHILD(1006), CHILD(1090), CHILD(1099), TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1566 | TILEGX_OPC_NONE, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, | ||
1567 | TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, | ||
1568 | TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, | ||
1569 | TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, | ||
1570 | TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, | ||
1571 | TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, | ||
1572 | TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, | ||
1573 | TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, | ||
1574 | TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, | ||
1575 | TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLEU, | ||
1576 | TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, | ||
1577 | TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, | ||
1578 | TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, | ||
1579 | TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, | ||
1580 | TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, | ||
1581 | TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, | ||
1582 | TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, | ||
1583 | TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPNE, | ||
1584 | TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, | ||
1585 | TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, | ||
1586 | TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, | ||
1587 | TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, | ||
1588 | TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, | ||
1589 | TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, | ||
1590 | TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, | ||
1591 | TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, | ||
1592 | BITFIELD(43, 3) /* index 918 */, | ||
1593 | TILEGX_OPC_NONE, TILEGX_OPC_DRAIN, TILEGX_OPC_DTLBPR, TILEGX_OPC_FINV, | ||
1594 | TILEGX_OPC_FLUSHWB, TILEGX_OPC_FLUSH, TILEGX_OPC_FNOP, TILEGX_OPC_ICOH, | ||
1595 | BITFIELD(43, 3) /* index 927 */, | ||
1596 | CHILD(936), TILEGX_OPC_INV, TILEGX_OPC_IRET, TILEGX_OPC_JALRP, | ||
1597 | TILEGX_OPC_JALR, TILEGX_OPC_JRP, TILEGX_OPC_JR, CHILD(991), | ||
1598 | BITFIELD(31, 2) /* index 936 */, | ||
1599 | CHILD(941), CHILD(966), TILEGX_OPC_ILL, TILEGX_OPC_ILL, | ||
1600 | BITFIELD(33, 2) /* index 941 */, | ||
1601 | TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_ILL, CHILD(946), | ||
1602 | BITFIELD(35, 2) /* index 946 */, | ||
1603 | TILEGX_OPC_ILL, CHILD(951), TILEGX_OPC_ILL, TILEGX_OPC_ILL, | ||
1604 | BITFIELD(37, 2) /* index 951 */, | ||
1605 | TILEGX_OPC_ILL, CHILD(956), TILEGX_OPC_ILL, TILEGX_OPC_ILL, | ||
1606 | BITFIELD(39, 2) /* index 956 */, | ||
1607 | TILEGX_OPC_ILL, CHILD(961), TILEGX_OPC_ILL, TILEGX_OPC_ILL, | ||
1608 | BITFIELD(41, 2) /* index 961 */, | ||
1609 | TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_BPT, TILEGX_OPC_ILL, | ||
1610 | BITFIELD(33, 2) /* index 966 */, | ||
1611 | TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_ILL, CHILD(971), | ||
1612 | BITFIELD(35, 2) /* index 971 */, | ||
1613 | TILEGX_OPC_ILL, CHILD(976), TILEGX_OPC_ILL, TILEGX_OPC_ILL, | ||
1614 | BITFIELD(37, 2) /* index 976 */, | ||
1615 | TILEGX_OPC_ILL, CHILD(981), TILEGX_OPC_ILL, TILEGX_OPC_ILL, | ||
1616 | BITFIELD(39, 2) /* index 981 */, | ||
1617 | TILEGX_OPC_ILL, CHILD(986), TILEGX_OPC_ILL, TILEGX_OPC_ILL, | ||
1618 | BITFIELD(41, 2) /* index 986 */, | ||
1619 | TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_RAISE, TILEGX_OPC_ILL, | ||
1620 | BITFIELD(31, 2) /* index 991 */, | ||
1621 | TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, CHILD(996), | ||
1622 | BITFIELD(33, 2) /* index 996 */, | ||
1623 | TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, CHILD(1001), | ||
1624 | BITFIELD(35, 2) /* index 1001 */, | ||
1625 | TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, | ||
1626 | TILEGX_OPC_PREFETCH_L1_FAULT, | ||
1627 | BITFIELD(43, 3) /* index 1006 */, | ||
1628 | CHILD(1015), CHILD(1030), CHILD(1045), CHILD(1060), CHILD(1075), | ||
1629 | TILEGX_OPC_LDNA, TILEGX_OPC_LDNT1S, TILEGX_OPC_LDNT1U, | ||
1630 | BITFIELD(31, 2) /* index 1015 */, | ||
1631 | TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, CHILD(1020), | ||
1632 | BITFIELD(33, 2) /* index 1020 */, | ||
1633 | TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, CHILD(1025), | ||
1634 | BITFIELD(35, 2) /* index 1025 */, | ||
1635 | TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_PREFETCH, | ||
1636 | BITFIELD(31, 2) /* index 1030 */, | ||
1637 | TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, CHILD(1035), | ||
1638 | BITFIELD(33, 2) /* index 1035 */, | ||
1639 | TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, CHILD(1040), | ||
1640 | BITFIELD(35, 2) /* index 1040 */, | ||
1641 | TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, | ||
1642 | TILEGX_OPC_PREFETCH_L2_FAULT, | ||
1643 | BITFIELD(31, 2) /* index 1045 */, | ||
1644 | TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, CHILD(1050), | ||
1645 | BITFIELD(33, 2) /* index 1050 */, | ||
1646 | TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, CHILD(1055), | ||
1647 | BITFIELD(35, 2) /* index 1055 */, | ||
1648 | TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_PREFETCH_L2, | ||
1649 | BITFIELD(31, 2) /* index 1060 */, | ||
1650 | TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(1065), | ||
1651 | BITFIELD(33, 2) /* index 1065 */, | ||
1652 | TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(1070), | ||
1653 | BITFIELD(35, 2) /* index 1070 */, | ||
1654 | TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, | ||
1655 | TILEGX_OPC_PREFETCH_L3_FAULT, | ||
1656 | BITFIELD(31, 2) /* index 1075 */, | ||
1657 | TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(1080), | ||
1658 | BITFIELD(33, 2) /* index 1080 */, | ||
1659 | TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(1085), | ||
1660 | BITFIELD(35, 2) /* index 1085 */, | ||
1661 | TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_PREFETCH_L3, | ||
1662 | BITFIELD(43, 3) /* index 1090 */, | ||
1663 | TILEGX_OPC_LDNT2S, TILEGX_OPC_LDNT2U, TILEGX_OPC_LDNT4S, TILEGX_OPC_LDNT4U, | ||
1664 | TILEGX_OPC_LDNT, TILEGX_OPC_LD, TILEGX_OPC_LNK, TILEGX_OPC_MF, | ||
1665 | BITFIELD(43, 3) /* index 1099 */, | ||
1666 | TILEGX_OPC_NAP, TILEGX_OPC_NOP, TILEGX_OPC_SWINT0, TILEGX_OPC_SWINT1, | ||
1667 | TILEGX_OPC_SWINT2, TILEGX_OPC_SWINT3, TILEGX_OPC_WH64, TILEGX_OPC_NONE, | ||
1668 | BITFIELD(49, 4) /* index 1108 */, | ||
1669 | TILEGX_OPC_V1MAXU, TILEGX_OPC_V1MINU, TILEGX_OPC_V1MNZ, TILEGX_OPC_V1MZ, | ||
1670 | TILEGX_OPC_V1SHL, TILEGX_OPC_V1SHRS, TILEGX_OPC_V1SHRU, TILEGX_OPC_V1SUBUC, | ||
1671 | TILEGX_OPC_V1SUB, TILEGX_OPC_V2ADDSC, TILEGX_OPC_V2ADD, TILEGX_OPC_V2CMPEQ, | ||
1672 | TILEGX_OPC_V2CMPLES, TILEGX_OPC_V2CMPLEU, TILEGX_OPC_V2CMPLTS, | ||
1673 | TILEGX_OPC_V2CMPLTU, | ||
1674 | BITFIELD(49, 4) /* index 1125 */, | ||
1675 | TILEGX_OPC_V2CMPNE, TILEGX_OPC_V2INT_H, TILEGX_OPC_V2INT_L, | ||
1676 | TILEGX_OPC_V2MAXS, TILEGX_OPC_V2MINS, TILEGX_OPC_V2MNZ, TILEGX_OPC_V2MZ, | ||
1677 | TILEGX_OPC_V2PACKH, TILEGX_OPC_V2PACKL, TILEGX_OPC_V2PACKUC, | ||
1678 | TILEGX_OPC_V2SHLSC, TILEGX_OPC_V2SHL, TILEGX_OPC_V2SHRS, TILEGX_OPC_V2SHRU, | ||
1679 | TILEGX_OPC_V2SUBSC, TILEGX_OPC_V2SUB, | ||
1680 | BITFIELD(49, 4) /* index 1142 */, | ||
1681 | TILEGX_OPC_V4ADDSC, TILEGX_OPC_V4ADD, TILEGX_OPC_V4INT_H, | ||
1682 | TILEGX_OPC_V4INT_L, TILEGX_OPC_V4PACKSC, TILEGX_OPC_V4SHLSC, | ||
1683 | TILEGX_OPC_V4SHL, TILEGX_OPC_V4SHRS, TILEGX_OPC_V4SHRU, TILEGX_OPC_V4SUBSC, | ||
1684 | TILEGX_OPC_V4SUB, TILEGX_OPC_XOR, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1685 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1686 | BITFIELD(49, 4) /* index 1159 */, | ||
1687 | TILEGX_OPC_NONE, TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHLXI, | ||
1688 | TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, TILEGX_OPC_SHRUXI, TILEGX_OPC_V1SHLI, | ||
1689 | TILEGX_OPC_V1SHRSI, TILEGX_OPC_V1SHRUI, TILEGX_OPC_V2SHLI, | ||
1690 | TILEGX_OPC_V2SHRSI, TILEGX_OPC_V2SHRUI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1691 | TILEGX_OPC_NONE, | ||
1692 | BITFIELD(31, 2) /* index 1176 */, | ||
1693 | TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, | ||
1694 | CHILD(1181), | ||
1695 | BITFIELD(33, 2) /* index 1181 */, | ||
1696 | TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, | ||
1697 | CHILD(1186), | ||
1698 | BITFIELD(35, 2) /* index 1186 */, | ||
1699 | TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, | ||
1700 | CHILD(1191), | ||
1701 | BITFIELD(37, 2) /* index 1191 */, | ||
1702 | TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, | ||
1703 | CHILD(1196), | ||
1704 | BITFIELD(39, 2) /* index 1196 */, | ||
1705 | TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, | ||
1706 | CHILD(1201), | ||
1707 | BITFIELD(41, 2) /* index 1201 */, | ||
1708 | TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, | ||
1709 | TILEGX_OPC_INFOL, | ||
1710 | }; | ||
1711 | |||
1712 | static const unsigned short decode_Y0_fsm[178] = | ||
1713 | { | ||
1714 | BITFIELD(27, 4) /* index 0 */, | ||
1715 | CHILD(17), TILEGX_OPC_ADDXI, CHILD(32), TILEGX_OPC_CMPEQI, | ||
1716 | TILEGX_OPC_CMPLTSI, CHILD(62), CHILD(67), CHILD(118), CHILD(123), | ||
1717 | CHILD(128), CHILD(133), CHILD(153), CHILD(158), CHILD(163), CHILD(168), | ||
1718 | CHILD(173), | ||
1719 | BITFIELD(6, 2) /* index 17 */, | ||
1720 | TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(22), | ||
1721 | BITFIELD(8, 2) /* index 22 */, | ||
1722 | TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(27), | ||
1723 | BITFIELD(10, 2) /* index 27 */, | ||
1724 | TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI, | ||
1725 | BITFIELD(0, 2) /* index 32 */, | ||
1726 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(37), | ||
1727 | BITFIELD(2, 2) /* index 37 */, | ||
1728 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(42), | ||
1729 | BITFIELD(4, 2) /* index 42 */, | ||
1730 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(47), | ||
1731 | BITFIELD(6, 2) /* index 47 */, | ||
1732 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(52), | ||
1733 | BITFIELD(8, 2) /* index 52 */, | ||
1734 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(57), | ||
1735 | BITFIELD(10, 2) /* index 57 */, | ||
1736 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO, | ||
1737 | BITFIELD(18, 2) /* index 62 */, | ||
1738 | TILEGX_OPC_ADDX, TILEGX_OPC_ADD, TILEGX_OPC_SUBX, TILEGX_OPC_SUB, | ||
1739 | BITFIELD(15, 5) /* index 67 */, | ||
1740 | TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, | ||
1741 | TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, | ||
1742 | TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADD, | ||
1743 | TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, | ||
1744 | TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, | ||
1745 | TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, | ||
1746 | TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, | ||
1747 | TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, CHILD(100), | ||
1748 | CHILD(109), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1749 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1750 | BITFIELD(12, 3) /* index 100 */, | ||
1751 | TILEGX_OPC_NONE, TILEGX_OPC_CLZ, TILEGX_OPC_CTZ, TILEGX_OPC_FNOP, | ||
1752 | TILEGX_OPC_FSINGLE_PACK1, TILEGX_OPC_NOP, TILEGX_OPC_PCNT, | ||
1753 | TILEGX_OPC_REVBITS, | ||
1754 | BITFIELD(12, 3) /* index 109 */, | ||
1755 | TILEGX_OPC_REVBYTES, TILEGX_OPC_TBLIDXB0, TILEGX_OPC_TBLIDXB1, | ||
1756 | TILEGX_OPC_TBLIDXB2, TILEGX_OPC_TBLIDXB3, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1757 | TILEGX_OPC_NONE, | ||
1758 | BITFIELD(18, 2) /* index 118 */, | ||
1759 | TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU, | ||
1760 | BITFIELD(18, 2) /* index 123 */, | ||
1761 | TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPNE, TILEGX_OPC_MULAX, TILEGX_OPC_MULX, | ||
1762 | BITFIELD(18, 2) /* index 128 */, | ||
1763 | TILEGX_OPC_CMOVEQZ, TILEGX_OPC_CMOVNEZ, TILEGX_OPC_MNZ, TILEGX_OPC_MZ, | ||
1764 | BITFIELD(18, 2) /* index 133 */, | ||
1765 | TILEGX_OPC_AND, TILEGX_OPC_NOR, CHILD(138), TILEGX_OPC_XOR, | ||
1766 | BITFIELD(12, 2) /* index 138 */, | ||
1767 | TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(143), | ||
1768 | BITFIELD(14, 2) /* index 143 */, | ||
1769 | TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(148), | ||
1770 | BITFIELD(16, 2) /* index 148 */, | ||
1771 | TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE, | ||
1772 | BITFIELD(18, 2) /* index 153 */, | ||
1773 | TILEGX_OPC_ROTL, TILEGX_OPC_SHL, TILEGX_OPC_SHRS, TILEGX_OPC_SHRU, | ||
1774 | BITFIELD(18, 2) /* index 158 */, | ||
1775 | TILEGX_OPC_NONE, TILEGX_OPC_SHL1ADDX, TILEGX_OPC_SHL2ADDX, | ||
1776 | TILEGX_OPC_SHL3ADDX, | ||
1777 | BITFIELD(18, 2) /* index 163 */, | ||
1778 | TILEGX_OPC_MUL_HS_HS, TILEGX_OPC_MUL_HU_HU, TILEGX_OPC_MUL_LS_LS, | ||
1779 | TILEGX_OPC_MUL_LU_LU, | ||
1780 | BITFIELD(18, 2) /* index 168 */, | ||
1781 | TILEGX_OPC_MULA_HS_HS, TILEGX_OPC_MULA_HU_HU, TILEGX_OPC_MULA_LS_LS, | ||
1782 | TILEGX_OPC_MULA_LU_LU, | ||
1783 | BITFIELD(18, 2) /* index 173 */, | ||
1784 | TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, | ||
1785 | }; | ||
1786 | |||
1787 | static const unsigned short decode_Y1_fsm[167] = | ||
1788 | { | ||
1789 | BITFIELD(58, 4) /* index 0 */, | ||
1790 | TILEGX_OPC_NONE, CHILD(17), TILEGX_OPC_ADDXI, CHILD(32), TILEGX_OPC_CMPEQI, | ||
1791 | TILEGX_OPC_CMPLTSI, CHILD(62), CHILD(67), CHILD(117), CHILD(122), | ||
1792 | CHILD(127), CHILD(132), CHILD(152), CHILD(157), CHILD(162), TILEGX_OPC_NONE, | ||
1793 | BITFIELD(37, 2) /* index 17 */, | ||
1794 | TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(22), | ||
1795 | BITFIELD(39, 2) /* index 22 */, | ||
1796 | TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(27), | ||
1797 | BITFIELD(41, 2) /* index 27 */, | ||
1798 | TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI, | ||
1799 | BITFIELD(31, 2) /* index 32 */, | ||
1800 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(37), | ||
1801 | BITFIELD(33, 2) /* index 37 */, | ||
1802 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(42), | ||
1803 | BITFIELD(35, 2) /* index 42 */, | ||
1804 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(47), | ||
1805 | BITFIELD(37, 2) /* index 47 */, | ||
1806 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(52), | ||
1807 | BITFIELD(39, 2) /* index 52 */, | ||
1808 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(57), | ||
1809 | BITFIELD(41, 2) /* index 57 */, | ||
1810 | TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO, | ||
1811 | BITFIELD(49, 2) /* index 62 */, | ||
1812 | TILEGX_OPC_ADDX, TILEGX_OPC_ADD, TILEGX_OPC_SUBX, TILEGX_OPC_SUB, | ||
1813 | BITFIELD(47, 4) /* index 67 */, | ||
1814 | TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, | ||
1815 | TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, | ||
1816 | TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL3ADD, | ||
1817 | TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, CHILD(84), | ||
1818 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, | ||
1819 | BITFIELD(43, 3) /* index 84 */, | ||
1820 | CHILD(93), CHILD(96), CHILD(99), CHILD(102), CHILD(105), CHILD(108), | ||
1821 | CHILD(111), CHILD(114), | ||
1822 | BITFIELD(46, 1) /* index 93 */, | ||
1823 | TILEGX_OPC_NONE, TILEGX_OPC_FNOP, | ||
1824 | BITFIELD(46, 1) /* index 96 */, | ||
1825 | TILEGX_OPC_NONE, TILEGX_OPC_ILL, | ||
1826 | BITFIELD(46, 1) /* index 99 */, | ||
1827 | TILEGX_OPC_NONE, TILEGX_OPC_JALRP, | ||
1828 | BITFIELD(46, 1) /* index 102 */, | ||
1829 | TILEGX_OPC_NONE, TILEGX_OPC_JALR, | ||
1830 | BITFIELD(46, 1) /* index 105 */, | ||
1831 | TILEGX_OPC_NONE, TILEGX_OPC_JRP, | ||
1832 | BITFIELD(46, 1) /* index 108 */, | ||
1833 | TILEGX_OPC_NONE, TILEGX_OPC_JR, | ||
1834 | BITFIELD(46, 1) /* index 111 */, | ||
1835 | TILEGX_OPC_NONE, TILEGX_OPC_LNK, | ||
1836 | BITFIELD(46, 1) /* index 114 */, | ||
1837 | TILEGX_OPC_NONE, TILEGX_OPC_NOP, | ||
1838 | BITFIELD(49, 2) /* index 117 */, | ||
1839 | TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU, | ||
1840 | BITFIELD(49, 2) /* index 122 */, | ||
1841 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPNE, | ||
1842 | BITFIELD(49, 2) /* index 127 */, | ||
1843 | TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_MNZ, TILEGX_OPC_MZ, | ||
1844 | BITFIELD(49, 2) /* index 132 */, | ||
1845 | TILEGX_OPC_AND, TILEGX_OPC_NOR, CHILD(137), TILEGX_OPC_XOR, | ||
1846 | BITFIELD(43, 2) /* index 137 */, | ||
1847 | TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(142), | ||
1848 | BITFIELD(45, 2) /* index 142 */, | ||
1849 | TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(147), | ||
1850 | BITFIELD(47, 2) /* index 147 */, | ||
1851 | TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE, | ||
1852 | BITFIELD(49, 2) /* index 152 */, | ||
1853 | TILEGX_OPC_ROTL, TILEGX_OPC_SHL, TILEGX_OPC_SHRS, TILEGX_OPC_SHRU, | ||
1854 | BITFIELD(49, 2) /* index 157 */, | ||
1855 | TILEGX_OPC_NONE, TILEGX_OPC_SHL1ADDX, TILEGX_OPC_SHL2ADDX, | ||
1856 | TILEGX_OPC_SHL3ADDX, | ||
1857 | BITFIELD(49, 2) /* index 162 */, | ||
1858 | TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, | ||
1859 | }; | ||
1860 | |||
1861 | static const unsigned short decode_Y2_fsm[118] = | ||
1862 | { | ||
1863 | BITFIELD(62, 2) /* index 0 */, | ||
1864 | TILEGX_OPC_NONE, CHILD(5), CHILD(66), CHILD(109), | ||
1865 | BITFIELD(55, 3) /* index 5 */, | ||
1866 | CHILD(14), CHILD(14), CHILD(14), CHILD(17), CHILD(40), CHILD(40), CHILD(40), | ||
1867 | CHILD(43), | ||
1868 | BITFIELD(26, 1) /* index 14 */, | ||
1869 | TILEGX_OPC_LD1S, TILEGX_OPC_LD1U, | ||
1870 | BITFIELD(26, 1) /* index 17 */, | ||
1871 | CHILD(20), CHILD(30), | ||
1872 | BITFIELD(51, 2) /* index 20 */, | ||
1873 | TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, CHILD(25), | ||
1874 | BITFIELD(53, 2) /* index 25 */, | ||
1875 | TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, | ||
1876 | TILEGX_OPC_PREFETCH_L1_FAULT, | ||
1877 | BITFIELD(51, 2) /* index 30 */, | ||
1878 | TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, CHILD(35), | ||
1879 | BITFIELD(53, 2) /* index 35 */, | ||
1880 | TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_PREFETCH, | ||
1881 | BITFIELD(26, 1) /* index 40 */, | ||
1882 | TILEGX_OPC_LD2S, TILEGX_OPC_LD2U, | ||
1883 | BITFIELD(26, 1) /* index 43 */, | ||
1884 | CHILD(46), CHILD(56), | ||
1885 | BITFIELD(51, 2) /* index 46 */, | ||
1886 | TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, CHILD(51), | ||
1887 | BITFIELD(53, 2) /* index 51 */, | ||
1888 | TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, | ||
1889 | TILEGX_OPC_PREFETCH_L2_FAULT, | ||
1890 | BITFIELD(51, 2) /* index 56 */, | ||
1891 | TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, CHILD(61), | ||
1892 | BITFIELD(53, 2) /* index 61 */, | ||
1893 | TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_PREFETCH_L2, | ||
1894 | BITFIELD(56, 2) /* index 66 */, | ||
1895 | CHILD(71), CHILD(74), CHILD(90), CHILD(93), | ||
1896 | BITFIELD(26, 1) /* index 71 */, | ||
1897 | TILEGX_OPC_NONE, TILEGX_OPC_LD4S, | ||
1898 | BITFIELD(26, 1) /* index 74 */, | ||
1899 | TILEGX_OPC_NONE, CHILD(77), | ||
1900 | BITFIELD(51, 2) /* index 77 */, | ||
1901 | TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(82), | ||
1902 | BITFIELD(53, 2) /* index 82 */, | ||
1903 | TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(87), | ||
1904 | BITFIELD(55, 1) /* index 87 */, | ||
1905 | TILEGX_OPC_LD4S, TILEGX_OPC_PREFETCH_L3_FAULT, | ||
1906 | BITFIELD(26, 1) /* index 90 */, | ||
1907 | TILEGX_OPC_LD4U, TILEGX_OPC_LD, | ||
1908 | BITFIELD(26, 1) /* index 93 */, | ||
1909 | CHILD(96), TILEGX_OPC_LD, | ||
1910 | BITFIELD(51, 2) /* index 96 */, | ||
1911 | TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(101), | ||
1912 | BITFIELD(53, 2) /* index 101 */, | ||
1913 | TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(106), | ||
1914 | BITFIELD(55, 1) /* index 106 */, | ||
1915 | TILEGX_OPC_LD4U, TILEGX_OPC_PREFETCH_L3, | ||
1916 | BITFIELD(26, 1) /* index 109 */, | ||
1917 | CHILD(112), CHILD(115), | ||
1918 | BITFIELD(57, 1) /* index 112 */, | ||
1919 | TILEGX_OPC_ST1, TILEGX_OPC_ST4, | ||
1920 | BITFIELD(57, 1) /* index 115 */, | ||
1921 | TILEGX_OPC_ST2, TILEGX_OPC_ST, | ||
1922 | }; | ||
1923 | |||
1924 | #undef BITFIELD | ||
1925 | #undef CHILD | ||
1926 | const unsigned short * const | ||
1927 | tilegx_bundle_decoder_fsms[TILEGX_NUM_PIPELINE_ENCODINGS] = | ||
1928 | { | ||
1929 | decode_X0_fsm, | ||
1930 | decode_X1_fsm, | ||
1931 | decode_Y0_fsm, | ||
1932 | decode_Y1_fsm, | ||
1933 | decode_Y2_fsm | ||
1934 | }; | ||
1935 | const struct tilegx_operand tilegx_operands[35] = | ||
1936 | { | ||
1937 | { | ||
1938 | TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_X0), | ||
1939 | 8, 1, 0, 0, 0, 0, | ||
1940 | create_Imm8_X0, get_Imm8_X0 | ||
1941 | }, | ||
1942 | { | ||
1943 | TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_X1), | ||
1944 | 8, 1, 0, 0, 0, 0, | ||
1945 | create_Imm8_X1, get_Imm8_X1 | ||
1946 | }, | ||
1947 | { | ||
1948 | TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_Y0), | ||
1949 | 8, 1, 0, 0, 0, 0, | ||
1950 | create_Imm8_Y0, get_Imm8_Y0 | ||
1951 | }, | ||
1952 | { | ||
1953 | TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_Y1), | ||
1954 | 8, 1, 0, 0, 0, 0, | ||
1955 | create_Imm8_Y1, get_Imm8_Y1 | ||
1956 | }, | ||
1957 | { | ||
1958 | TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM16_X0_HW0_LAST), | ||
1959 | 16, 1, 0, 0, 0, 0, | ||
1960 | create_Imm16_X0, get_Imm16_X0 | ||
1961 | }, | ||
1962 | { | ||
1963 | TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM16_X1_HW0_LAST), | ||
1964 | 16, 1, 0, 0, 0, 0, | ||
1965 | create_Imm16_X1, get_Imm16_X1 | ||
1966 | }, | ||
1967 | { | ||
1968 | TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), | ||
1969 | 6, 0, 0, 1, 0, 0, | ||
1970 | create_Dest_X0, get_Dest_X0 | ||
1971 | }, | ||
1972 | { | ||
1973 | TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), | ||
1974 | 6, 0, 1, 0, 0, 0, | ||
1975 | create_SrcA_X0, get_SrcA_X0 | ||
1976 | }, | ||
1977 | { | ||
1978 | TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), | ||
1979 | 6, 0, 0, 1, 0, 0, | ||
1980 | create_Dest_X1, get_Dest_X1 | ||
1981 | }, | ||
1982 | { | ||
1983 | TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), | ||
1984 | 6, 0, 1, 0, 0, 0, | ||
1985 | create_SrcA_X1, get_SrcA_X1 | ||
1986 | }, | ||
1987 | { | ||
1988 | TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), | ||
1989 | 6, 0, 0, 1, 0, 0, | ||
1990 | create_Dest_Y0, get_Dest_Y0 | ||
1991 | }, | ||
1992 | { | ||
1993 | TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), | ||
1994 | 6, 0, 1, 0, 0, 0, | ||
1995 | create_SrcA_Y0, get_SrcA_Y0 | ||
1996 | }, | ||
1997 | { | ||
1998 | TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), | ||
1999 | 6, 0, 0, 1, 0, 0, | ||
2000 | create_Dest_Y1, get_Dest_Y1 | ||
2001 | }, | ||
2002 | { | ||
2003 | TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), | ||
2004 | 6, 0, 1, 0, 0, 0, | ||
2005 | create_SrcA_Y1, get_SrcA_Y1 | ||
2006 | }, | ||
2007 | { | ||
2008 | TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), | ||
2009 | 6, 0, 1, 0, 0, 0, | ||
2010 | create_SrcA_Y2, get_SrcA_Y2 | ||
2011 | }, | ||
2012 | { | ||
2013 | TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), | ||
2014 | 6, 0, 1, 1, 0, 0, | ||
2015 | create_SrcA_X1, get_SrcA_X1 | ||
2016 | }, | ||
2017 | { | ||
2018 | TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), | ||
2019 | 6, 0, 1, 0, 0, 0, | ||
2020 | create_SrcB_X0, get_SrcB_X0 | ||
2021 | }, | ||
2022 | { | ||
2023 | TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), | ||
2024 | 6, 0, 1, 0, 0, 0, | ||
2025 | create_SrcB_X1, get_SrcB_X1 | ||
2026 | }, | ||
2027 | { | ||
2028 | TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), | ||
2029 | 6, 0, 1, 0, 0, 0, | ||
2030 | create_SrcB_Y0, get_SrcB_Y0 | ||
2031 | }, | ||
2032 | { | ||
2033 | TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), | ||
2034 | 6, 0, 1, 0, 0, 0, | ||
2035 | create_SrcB_Y1, get_SrcB_Y1 | ||
2036 | }, | ||
2037 | { | ||
2038 | TILEGX_OP_TYPE_ADDRESS, BFD_RELOC(TILEGX_BROFF_X1), | ||
2039 | 17, 1, 0, 0, 1, TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES, | ||
2040 | create_BrOff_X1, get_BrOff_X1 | ||
2041 | }, | ||
2042 | { | ||
2043 | TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE), | ||
2044 | 6, 0, 0, 0, 0, 0, | ||
2045 | create_BFStart_X0, get_BFStart_X0 | ||
2046 | }, | ||
2047 | { | ||
2048 | TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(NONE), | ||
2049 | 6, 0, 0, 0, 0, 0, | ||
2050 | create_BFEnd_X0, get_BFEnd_X0 | ||
2051 | }, | ||
2052 | { | ||
2053 | TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), | ||
2054 | 6, 0, 1, 1, 0, 0, | ||
2055 | create_Dest_X0, get_Dest_X0 | ||
2056 | }, | ||
2057 | { | ||
2058 | TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), | ||
2059 | 6, 0, 1, 1, 0, 0, | ||
2060 | create_Dest_Y0, get_Dest_Y0 | ||
2061 | }, | ||
2062 | { | ||
2063 | TILEGX_OP_TYPE_ADDRESS, BFD_RELOC(TILEGX_JUMPOFF_X1), | ||
2064 | 27, 1, 0, 0, 1, TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES, | ||
2065 | create_JumpOff_X1, get_JumpOff_X1 | ||
2066 | }, | ||
2067 | { | ||
2068 | TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), | ||
2069 | 6, 0, 0, 1, 0, 0, | ||
2070 | create_SrcBDest_Y2, get_SrcBDest_Y2 | ||
2071 | }, | ||
2072 | { | ||
2073 | TILEGX_OP_TYPE_SPR, BFD_RELOC(TILEGX_MF_IMM14_X1), | ||
2074 | 14, 0, 0, 0, 0, 0, | ||
2075 | create_MF_Imm14_X1, get_MF_Imm14_X1 | ||
2076 | }, | ||
2077 | { | ||
2078 | TILEGX_OP_TYPE_SPR, BFD_RELOC(TILEGX_MT_IMM14_X1), | ||
2079 | 14, 0, 0, 0, 0, 0, | ||
2080 | create_MT_Imm14_X1, get_MT_Imm14_X1 | ||
2081 | }, | ||
2082 | { | ||
2083 | TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_X0), | ||
2084 | 6, 0, 0, 0, 0, 0, | ||
2085 | create_ShAmt_X0, get_ShAmt_X0 | ||
2086 | }, | ||
2087 | { | ||
2088 | TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_X1), | ||
2089 | 6, 0, 0, 0, 0, 0, | ||
2090 | create_ShAmt_X1, get_ShAmt_X1 | ||
2091 | }, | ||
2092 | { | ||
2093 | TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_Y0), | ||
2094 | 6, 0, 0, 0, 0, 0, | ||
2095 | create_ShAmt_Y0, get_ShAmt_Y0 | ||
2096 | }, | ||
2097 | { | ||
2098 | TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_Y1), | ||
2099 | 6, 0, 0, 0, 0, 0, | ||
2100 | create_ShAmt_Y1, get_ShAmt_Y1 | ||
2101 | }, | ||
2102 | { | ||
2103 | TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), | ||
2104 | 6, 0, 1, 0, 0, 0, | ||
2105 | create_SrcBDest_Y2, get_SrcBDest_Y2 | ||
2106 | }, | ||
2107 | { | ||
2108 | TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_DEST_IMM8_X1), | ||
2109 | 8, 1, 0, 0, 0, 0, | ||
2110 | create_Dest_Imm8_X1, get_Dest_Imm8_X1 | ||
2111 | } | ||
2112 | }; | ||
2113 | |||
2114 | |||
2115 | |||
2116 | |||
2117 | /* Given a set of bundle bits and the lookup FSM for a specific pipe, | ||
2118 | * returns which instruction the bundle contains in that pipe. | ||
2119 | */ | ||
2120 | static const struct tilegx_opcode * | ||
2121 | find_opcode(tilegx_bundle_bits bits, const unsigned short *table) | ||
2122 | { | ||
2123 | int index = 0; | ||
2124 | |||
2125 | while (1) | ||
2126 | { | ||
2127 | unsigned short bitspec = table[index]; | ||
2128 | unsigned int bitfield = | ||
2129 | ((unsigned int)(bits >> (bitspec & 63))) & (bitspec >> 6); | ||
2130 | |||
2131 | unsigned short next = table[index + 1 + bitfield]; | ||
2132 | if (next <= TILEGX_OPC_NONE) | ||
2133 | return &tilegx_opcodes[next]; | ||
2134 | |||
2135 | index = next - TILEGX_OPC_NONE; | ||
2136 | } | ||
2137 | } | ||
2138 | |||
2139 | |||
2140 | int | ||
2141 | parse_insn_tilegx(tilegx_bundle_bits bits, | ||
2142 | unsigned long long pc, | ||
2143 | struct tilegx_decoded_instruction | ||
2144 | decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]) | ||
2145 | { | ||
2146 | int num_instructions = 0; | ||
2147 | int pipe; | ||
2148 | |||
2149 | int min_pipe, max_pipe; | ||
2150 | if ((bits & TILEGX_BUNDLE_MODE_MASK) == 0) | ||
2151 | { | ||
2152 | min_pipe = TILEGX_PIPELINE_X0; | ||
2153 | max_pipe = TILEGX_PIPELINE_X1; | ||
2154 | } | ||
2155 | else | ||
2156 | { | ||
2157 | min_pipe = TILEGX_PIPELINE_Y0; | ||
2158 | max_pipe = TILEGX_PIPELINE_Y2; | ||
2159 | } | ||
2160 | |||
2161 | /* For each pipe, find an instruction that fits. */ | ||
2162 | for (pipe = min_pipe; pipe <= max_pipe; pipe++) | ||
2163 | { | ||
2164 | const struct tilegx_opcode *opc; | ||
2165 | struct tilegx_decoded_instruction *d; | ||
2166 | int i; | ||
2167 | |||
2168 | d = &decoded[num_instructions++]; | ||
2169 | opc = find_opcode (bits, tilegx_bundle_decoder_fsms[pipe]); | ||
2170 | d->opcode = opc; | ||
2171 | |||
2172 | /* Decode each operand, sign extending, etc. as appropriate. */ | ||
2173 | for (i = 0; i < opc->num_operands; i++) | ||
2174 | { | ||
2175 | const struct tilegx_operand *op = | ||
2176 | &tilegx_operands[opc->operands[pipe][i]]; | ||
2177 | int raw_opval = op->extract (bits); | ||
2178 | long long opval; | ||
2179 | |||
2180 | if (op->is_signed) | ||
2181 | { | ||
2182 | /* Sign-extend the operand. */ | ||
2183 | int shift = (int)((sizeof(int) * 8) - op->num_bits); | ||
2184 | raw_opval = (raw_opval << shift) >> shift; | ||
2185 | } | ||
2186 | |||
2187 | /* Adjust PC-relative scaled branch offsets. */ | ||
2188 | if (op->type == TILEGX_OP_TYPE_ADDRESS) | ||
2189 | opval = (raw_opval * TILEGX_BUNDLE_SIZE_IN_BYTES) + pc; | ||
2190 | else | ||
2191 | opval = raw_opval; | ||
2192 | |||
2193 | /* Record the final value. */ | ||
2194 | d->operands[i] = op; | ||
2195 | d->operand_values[i] = opval; | ||
2196 | } | ||
2197 | } | ||
2198 | |||
2199 | return num_instructions; | ||
2200 | } | ||
diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c index 6bed820e1421..c4be58cc5d50 100644 --- a/arch/tile/kernel/time.c +++ b/arch/tile/kernel/time.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
23 | #include <linux/smp.h> | 23 | #include <linux/smp.h> |
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/module.h> | ||
25 | #include <asm/irq_regs.h> | 26 | #include <asm/irq_regs.h> |
26 | #include <asm/traps.h> | 27 | #include <asm/traps.h> |
27 | #include <hv/hypervisor.h> | 28 | #include <hv/hypervisor.h> |
@@ -56,6 +57,7 @@ cycles_t get_cycles(void) | |||
56 | 57 | ||
57 | return (((cycles_t)high) << 32) | low; | 58 | return (((cycles_t)high) << 32) | low; |
58 | } | 59 | } |
60 | EXPORT_SYMBOL(get_cycles); | ||
59 | #endif | 61 | #endif |
60 | 62 | ||
61 | /* | 63 | /* |
@@ -132,7 +134,7 @@ static int tile_timer_set_next_event(unsigned long ticks, | |||
132 | { | 134 | { |
133 | BUG_ON(ticks > MAX_TICK); | 135 | BUG_ON(ticks > MAX_TICK); |
134 | __insn_mtspr(SPR_TILE_TIMER_CONTROL, ticks); | 136 | __insn_mtspr(SPR_TILE_TIMER_CONTROL, ticks); |
135 | raw_local_irq_unmask_now(INT_TILE_TIMER); | 137 | arch_local_irq_unmask_now(INT_TILE_TIMER); |
136 | return 0; | 138 | return 0; |
137 | } | 139 | } |
138 | 140 | ||
@@ -143,7 +145,7 @@ static int tile_timer_set_next_event(unsigned long ticks, | |||
143 | static void tile_timer_set_mode(enum clock_event_mode mode, | 145 | static void tile_timer_set_mode(enum clock_event_mode mode, |
144 | struct clock_event_device *evt) | 146 | struct clock_event_device *evt) |
145 | { | 147 | { |
146 | raw_local_irq_mask_now(INT_TILE_TIMER); | 148 | arch_local_irq_mask_now(INT_TILE_TIMER); |
147 | } | 149 | } |
148 | 150 | ||
149 | /* | 151 | /* |
@@ -172,7 +174,7 @@ void __cpuinit setup_tile_timer(void) | |||
172 | evt->cpumask = cpumask_of(smp_processor_id()); | 174 | evt->cpumask = cpumask_of(smp_processor_id()); |
173 | 175 | ||
174 | /* Start out with timer not firing. */ | 176 | /* Start out with timer not firing. */ |
175 | raw_local_irq_mask_now(INT_TILE_TIMER); | 177 | arch_local_irq_mask_now(INT_TILE_TIMER); |
176 | 178 | ||
177 | /* Register tile timer. */ | 179 | /* Register tile timer. */ |
178 | clockevents_register_device(evt); | 180 | clockevents_register_device(evt); |
@@ -188,7 +190,7 @@ void do_timer_interrupt(struct pt_regs *regs, int fault_num) | |||
188 | * Mask the timer interrupt here, since we are a oneshot timer | 190 | * Mask the timer interrupt here, since we are a oneshot timer |
189 | * and there are now by definition no events pending. | 191 | * and there are now by definition no events pending. |
190 | */ | 192 | */ |
191 | raw_local_irq_mask(INT_TILE_TIMER); | 193 | arch_local_irq_mask(INT_TILE_TIMER); |
192 | 194 | ||
193 | /* Track time spent here in an interrupt context */ | 195 | /* Track time spent here in an interrupt context */ |
194 | irq_enter(); | 196 | irq_enter(); |
@@ -224,3 +226,13 @@ int setup_profiling_timer(unsigned int multiplier) | |||
224 | { | 226 | { |
225 | return -EINVAL; | 227 | return -EINVAL; |
226 | } | 228 | } |
229 | |||
230 | /* | ||
231 | * Use the tile timer to convert nsecs to core clock cycles, relying | ||
232 | * on it having the same frequency as SPR_CYCLE. | ||
233 | */ | ||
234 | cycles_t ns2cycles(unsigned long nsecs) | ||
235 | { | ||
236 | struct clock_event_device *dev = &__get_cpu_var(tile_timer); | ||
237 | return ((u64)nsecs * dev->mult) >> dev->shift; | ||
238 | } | ||
diff --git a/arch/tile/kernel/tlb.c b/arch/tile/kernel/tlb.c index 2dffc1044d83..a5f241c24cac 100644 --- a/arch/tile/kernel/tlb.c +++ b/arch/tile/kernel/tlb.c | |||
@@ -34,13 +34,13 @@ void flush_tlb_mm(struct mm_struct *mm) | |||
34 | { | 34 | { |
35 | HV_Remote_ASID asids[NR_CPUS]; | 35 | HV_Remote_ASID asids[NR_CPUS]; |
36 | int i = 0, cpu; | 36 | int i = 0, cpu; |
37 | for_each_cpu(cpu, &mm->cpu_vm_mask) { | 37 | for_each_cpu(cpu, mm_cpumask(mm)) { |
38 | HV_Remote_ASID *asid = &asids[i++]; | 38 | HV_Remote_ASID *asid = &asids[i++]; |
39 | asid->y = cpu / smp_topology.width; | 39 | asid->y = cpu / smp_topology.width; |
40 | asid->x = cpu % smp_topology.width; | 40 | asid->x = cpu % smp_topology.width; |
41 | asid->asid = per_cpu(current_asid, cpu); | 41 | asid->asid = per_cpu(current_asid, cpu); |
42 | } | 42 | } |
43 | flush_remote(0, HV_FLUSH_EVICT_L1I, &mm->cpu_vm_mask, | 43 | flush_remote(0, HV_FLUSH_EVICT_L1I, mm_cpumask(mm), |
44 | 0, 0, 0, NULL, asids, i); | 44 | 0, 0, 0, NULL, asids, i); |
45 | } | 45 | } |
46 | 46 | ||
@@ -54,8 +54,8 @@ void flush_tlb_page_mm(const struct vm_area_struct *vma, struct mm_struct *mm, | |||
54 | { | 54 | { |
55 | unsigned long size = hv_page_size(vma); | 55 | unsigned long size = hv_page_size(vma); |
56 | int cache = (vma->vm_flags & VM_EXEC) ? HV_FLUSH_EVICT_L1I : 0; | 56 | int cache = (vma->vm_flags & VM_EXEC) ? HV_FLUSH_EVICT_L1I : 0; |
57 | flush_remote(0, cache, &mm->cpu_vm_mask, | 57 | flush_remote(0, cache, mm_cpumask(mm), |
58 | va, size, size, &mm->cpu_vm_mask, NULL, 0); | 58 | va, size, size, mm_cpumask(mm), NULL, 0); |
59 | } | 59 | } |
60 | 60 | ||
61 | void flush_tlb_page(const struct vm_area_struct *vma, unsigned long va) | 61 | void flush_tlb_page(const struct vm_area_struct *vma, unsigned long va) |
@@ -70,8 +70,8 @@ void flush_tlb_range(const struct vm_area_struct *vma, | |||
70 | unsigned long size = hv_page_size(vma); | 70 | unsigned long size = hv_page_size(vma); |
71 | struct mm_struct *mm = vma->vm_mm; | 71 | struct mm_struct *mm = vma->vm_mm; |
72 | int cache = (vma->vm_flags & VM_EXEC) ? HV_FLUSH_EVICT_L1I : 0; | 72 | int cache = (vma->vm_flags & VM_EXEC) ? HV_FLUSH_EVICT_L1I : 0; |
73 | flush_remote(0, cache, &mm->cpu_vm_mask, start, end - start, size, | 73 | flush_remote(0, cache, mm_cpumask(mm), start, end - start, size, |
74 | &mm->cpu_vm_mask, NULL, 0); | 74 | mm_cpumask(mm), NULL, 0); |
75 | } | 75 | } |
76 | 76 | ||
77 | void flush_tlb_all(void) | 77 | void flush_tlb_all(void) |
diff --git a/arch/tile/kernel/traps.c b/arch/tile/kernel/traps.c index 0f362dc2c57f..f9803dfa7357 100644 --- a/arch/tile/kernel/traps.c +++ b/arch/tile/kernel/traps.c | |||
@@ -260,7 +260,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, | |||
260 | address = regs->pc; | 260 | address = regs->pc; |
261 | break; | 261 | break; |
262 | case INT_UNALIGN_DATA: | 262 | case INT_UNALIGN_DATA: |
263 | #ifndef __tilegx__ /* FIXME: GX: no single-step yet */ | 263 | #ifndef __tilegx__ /* Emulated support for single step debugging */ |
264 | if (unaligned_fixup >= 0) { | 264 | if (unaligned_fixup >= 0) { |
265 | struct single_step_state *state = | 265 | struct single_step_state *state = |
266 | current_thread_info()->step_state; | 266 | current_thread_info()->step_state; |
@@ -278,7 +278,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, | |||
278 | case INT_DOUBLE_FAULT: | 278 | case INT_DOUBLE_FAULT: |
279 | /* | 279 | /* |
280 | * For double fault, "reason" is actually passed as | 280 | * For double fault, "reason" is actually passed as |
281 | * SYSTEM_SAVE_1_2, the hypervisor's double-fault info, so | 281 | * SYSTEM_SAVE_K_2, the hypervisor's double-fault info, so |
282 | * we can provide the original fault number rather than | 282 | * we can provide the original fault number rather than |
283 | * the uninteresting "INT_DOUBLE_FAULT" so the user can | 283 | * the uninteresting "INT_DOUBLE_FAULT" so the user can |
284 | * learn what actually struck while PL0 ICS was set. | 284 | * learn what actually struck while PL0 ICS was set. |
@@ -308,6 +308,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, | |||
308 | info.si_addr = (void __user *)address; | 308 | info.si_addr = (void __user *)address; |
309 | if (signo == SIGILL) | 309 | if (signo == SIGILL) |
310 | info.si_trapno = fault_num; | 310 | info.si_trapno = fault_num; |
311 | trace_unhandled_signal("trap", regs, address, signo); | ||
311 | force_sig_info(signo, &info, current); | 312 | force_sig_info(signo, &info, current); |
312 | } | 313 | } |
313 | 314 | ||
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S index 25fdc0c1839a..631f10de12fe 100644 --- a/arch/tile/kernel/vmlinux.lds.S +++ b/arch/tile/kernel/vmlinux.lds.S | |||
@@ -59,11 +59,8 @@ SECTIONS | |||
59 | 59 | ||
60 | . = ALIGN(PAGE_SIZE); | 60 | . = ALIGN(PAGE_SIZE); |
61 | VMLINUX_SYMBOL(_sinitdata) = .; | 61 | VMLINUX_SYMBOL(_sinitdata) = .; |
62 | .init.page : AT (ADDR(.init.page) - LOAD_OFFSET) { | 62 | INIT_DATA_SECTION(16) :data =0 |
63 | *(.init.page) | 63 | PERCPU_SECTION(L2_CACHE_BYTES) |
64 | } :data =0 | ||
65 | INIT_DATA_SECTION(16) | ||
66 | PERCPU(PAGE_SIZE) | ||
67 | . = ALIGN(PAGE_SIZE); | 64 | . = ALIGN(PAGE_SIZE); |
68 | VMLINUX_SYMBOL(_einitdata) = .; | 65 | VMLINUX_SYMBOL(_einitdata) = .; |
69 | 66 | ||