aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/process.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-09-15 23:43:33 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-09-15 23:43:33 -0400
commit7318413077a5141a50a753b1fab687b7907eef16 (patch)
tree21a59cf856f4bb762f6d3d0635c898ca6b24cff6 /arch/mips/kernel/process.c
parent8d93c7a4315711ea0f7a95ca353a89c4ed0763fb (diff)
parent35eed7cb2cf1c58a225a0140729ba787fbb06c88 (diff)
Merge branch '4.14-features' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle: "This is the main pull request for 4.14 for MIPS; below a summary of the non-merge commits: CM: - Rename mips_cm_base to mips_gcr_base - Specify register size when generating accessors - Use BIT/GENMASK for register fields, order & drop shifts - Add cluster & block args to mips_cm_lock_other() CPC: - Use common CPS accessor generation macros - Use BIT/GENMASK for register fields, order & drop shifts - Introduce register modify (set/clear/change) accessors - Use change_*, set_* & clear_* where appropriate - Add CM/CPC 3.5 register definitions - Use GlobalNumber macros rather than magic numbers - Have asm/mips-cps.h include CM & CPC headers - Cluster support for topology functions - Detect CPUs in secondary clusters CPS: - Read GIC_VL_IDENT directly, not via irqchip driver DMA: - Consolidate coherent and non-coherent dma_alloc code - Don't use dma_cache_sync to implement fd_cacheflush FPU emulation / FP assist code: - Another series of 14 commits fixing corner cases such as NaN propgagation and other special input values. - Zero bits 32-63 of the result for a CLASS.D instruction. - Enhanced statics via debugfs - Do not use bools for arithmetic. GCC 7.1 moans about this. - Correct user fault_addr type Generic MIPS: - Enhancement of stack backtraces - Cleanup from non-existing options - Handle non word sized instructions when examining frame - Fix detection and decoding of ADDIUSP instruction - Fix decoding of SWSP16 instruction - Refactor handling of stack pointer in get_frame_info - Remove unreachable code from force_fcr31_sig() - Convert to using %pOF instead of full_name - Remove the R6000 support. - Move FP code from *_switch.S to *_fpu.S - Remove unused ST_OFF from r2300_switch.S - Allow platform to specify multiple its.S files - Add #includes to various files to ensure code builds reliable and without warning.. - Remove __invalidate_kernel_vmap_range - Remove plat_timer_setup - Declare various variables & functions static - Abstract CPU core & VP(E) ID access through accessor functions - Store core & VP IDs in GlobalNumber-style variable - Unify checks for sibling CPUs - Add CPU cluster number accessors - Prevent direct use of generic_defconfig - Make CONFIG_MIPS_MT_SMP default y - Add __ioread64_copy - Remove unnecessary inclusions of linux/irqchip/mips-gic.h GIC: - Introduce asm/mips-gic.h with accessor functions - Use new GIC accessor functions in mips-gic-timer - Remove counter access functions from irq-mips-gic.c - Remove gic_read_local_vp_id() from irq-mips-gic.c - Simplify shared interrupt pending/mask reads in irq-mips-gic.c - Simplify gic_local_irq_domain_map() in irq-mips-gic.c - Drop gic_(re)set_mask() functions in irq-mips-gic.c - Remove gic_set_polarity(), gic_set_trigger(), gic_set_dual_edge(), gic_map_to_pin() and gic_map_to_vpe() from irq-mips-gic.c. - Convert remaining shared reg access, local int mask access and remaining local reg access to new accessors - Move GIC_LOCAL_INT_* to asm/mips-gic.h - Remove GIC_CPU_INT* macros from irq-mips-gic.c - Move various definitions to the driver - Remove gic_get_usm_range() - Remove __gic_irq_dispatch() forward declaration - Remove gic_init() - Use mips_gic_present() in place of gic_present and remove gic_present - Move gic_get_c0_*_int() to asm/mips-gic.h - Remove linux/irqchip/mips-gic.h - Inline __gic_init() - Inline gic_basic_init() - Make pcpu_masks a per-cpu variable - Use pcpu_masks to avoid reading GIC_SH_MASK* - Clean up mti, reserved-cpu-vectors handling - Use cpumask_first_and() in gic_set_affinity() - Let the core set struct irq_common_data affinity microMIPS: - Fix microMIPS stack unwinding on big endian systems MIPS-GIC: - SYNC after enabling GIC region NUMA: - Remove the unused parent_node() macro R6: - Constify r2_decoder_tables - Add accessor & bit definitions for GlobalNumber SMP: - Constify smp ops - Allow boot_secondary SMP op to return errors VDSO: - Drop gic_get_usm_range() usage - Avoid use of linux/irqchip/mips-gic.h Platform changes: Alchemy: - Add devboard machine type to cpuinfo - update cpu feature overrides - Threaded carddetect irqs for devboards AR7: - allow NULL clock for clk_get_rate BCM63xx: - Fix ENETDMA_6345_MAXBURST_REG offset - Allow NULL clock for clk_get_rate CI20: - Enable GPIO and RTC drivers in defconfig - Add ethernet and fixed-regulator nodes to DTS Generic platform: - Move Boston and NI 169445 FIT image source to their own files - Include asm/bootinfo.h for plat_fdt_relocated() - Include asm/time.h for get_c0_*_int() - Include asm/bootinfo.h for plat_fdt_relocated() - Include asm/time.h for get_c0_*_int() - Allow filtering enabled boards by requirements - Don't explicitly disable CONFIG_USB_SUPPORT - Bump default NR_CPUS to 16 JZ4700: - Probe the jz4740-rtc driver from devicetree Lantiq: - Drop check of boot select from the spi-falcon driver. - Drop check of boot select from the lantiq-flash MTD driver. - Access boot cause register in the watchdog driver through regmap - Add device tree binding documentation for the watchdog driver - Add docs for the RCU DT bindings. - Convert the fpi bus driver to a platform_driver - Remove ltq_reset_cause() and ltq_boot_select( - Switch to a proper reset driver - Switch to a new drivers/soc GPHY driver - Add an USB PHY driver for the Lantiq SoCs using the RCU module - Use of_platform_default_populate instead of __dt_register_buses - Enable MFD_SYSCON to be able to use it for the RCU MFD - Replace ltq_boot_select() with dummy implementation. Loongson 2F: - Allow NULL clock for clk_get_rate Malta: - Use new GIC accessor functions NI 169445: - Add support for NI 169445 board. - Only include in 32r2el kernels Octeon: - Add support for watchdog of 78XX SOCs. - Add support for watchdog of CN68XX SOCs. - Expose support for mips32r1, mips32r2 and mips64r1 - Enable more drivers in config file - Add support for accessing the boot vector. - Remove old boot vector code from watchdog driver - Define watchdog registers for 70xx, 73xx, 78xx, F75xx. - Make CSR functions node aware. - Allow access to CIU3 IRQ domains. - Misc cleanups in the watchdog driver Omega2+: - New board, add support and defconfig Pistachio: - Enable Root FS on NFS in defconfig Ralink: - Add Mediatek MT7628A SoC - Allow NULL clock for clk_get_rate - Explicitly request exclusive reset control in the pci-mt7620 PCI driver. SEAD3: - Only include in 32 bit kernels by default VoCore: - Add VoCore as a vendor t0 dt-bindings - Add defconfig file" * '4.14-features' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (167 commits) MIPS: Refactor handling of stack pointer in get_frame_info MIPS: Stacktrace: Fix microMIPS stack unwinding on big endian systems MIPS: microMIPS: Fix decoding of swsp16 instruction MIPS: microMIPS: Fix decoding of addiusp instruction MIPS: microMIPS: Fix detection of addiusp instruction MIPS: Handle non word sized instructions when examining frame MIPS: ralink: allow NULL clock for clk_get_rate MIPS: Loongson 2F: allow NULL clock for clk_get_rate MIPS: BCM63XX: allow NULL clock for clk_get_rate MIPS: AR7: allow NULL clock for clk_get_rate MIPS: BCM63XX: fix ENETDMA_6345_MAXBURST_REG offset mips: Save all registers when saving the frame MIPS: Add DWARF unwinding to assembly MIPS: Make SAVE_SOME more standard MIPS: Fix issues in backtraces MIPS: jz4780: DTS: Probe the jz4740-rtc driver from devicetree MIPS: Ci20: Enable RTC driver watchdog: octeon-wdt: Add support for 78XX SOCs. watchdog: octeon-wdt: Add support for cn68XX SOCs. watchdog: octeon-wdt: File cleaning. ...
Diffstat (limited to 'arch/mips/kernel/process.c')
-rw-r--r--arch/mips/kernel/process.c102
1 files changed, 61 insertions, 41 deletions
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 5351e1f3950d..c5ff6bfe2825 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -208,13 +208,13 @@ static inline int is_ra_save_ins(union mips_instruction *ip, int *poff)
208 * 208 *
209 * microMIPS is way more fun... 209 * microMIPS is way more fun...
210 */ 210 */
211 if (mm_insn_16bit(ip->halfword[1])) { 211 if (mm_insn_16bit(ip->word >> 16)) {
212 switch (ip->mm16_r5_format.opcode) { 212 switch (ip->mm16_r5_format.opcode) {
213 case mm_swsp16_op: 213 case mm_swsp16_op:
214 if (ip->mm16_r5_format.rt != 31) 214 if (ip->mm16_r5_format.rt != 31)
215 return 0; 215 return 0;
216 216
217 *poff = ip->mm16_r5_format.simmediate; 217 *poff = ip->mm16_r5_format.imm;
218 *poff = (*poff << 2) / sizeof(ulong); 218 *poff = (*poff << 2) / sizeof(ulong);
219 return 1; 219 return 1;
220 220
@@ -287,7 +287,7 @@ static inline int is_jump_ins(union mips_instruction *ip)
287 * 287 *
288 * microMIPS is kind of more fun... 288 * microMIPS is kind of more fun...
289 */ 289 */
290 if (mm_insn_16bit(ip->halfword[1])) { 290 if (mm_insn_16bit(ip->word >> 16)) {
291 if ((ip->mm16_r5_format.opcode == mm_pool16c_op && 291 if ((ip->mm16_r5_format.opcode == mm_pool16c_op &&
292 (ip->mm16_r5_format.rt & mm_jr16_op) == mm_jr16_op)) 292 (ip->mm16_r5_format.rt & mm_jr16_op) == mm_jr16_op))
293 return 1; 293 return 1;
@@ -313,9 +313,11 @@ static inline int is_jump_ins(union mips_instruction *ip)
313#endif 313#endif
314} 314}
315 315
316static inline int is_sp_move_ins(union mips_instruction *ip) 316static inline int is_sp_move_ins(union mips_instruction *ip, int *frame_size)
317{ 317{
318#ifdef CONFIG_CPU_MICROMIPS 318#ifdef CONFIG_CPU_MICROMIPS
319 unsigned short tmp;
320
319 /* 321 /*
320 * addiusp -imm 322 * addiusp -imm
321 * addius5 sp,-imm 323 * addius5 sp,-imm
@@ -324,21 +326,40 @@ static inline int is_sp_move_ins(union mips_instruction *ip)
324 * 326 *
325 * microMIPS is not more fun... 327 * microMIPS is not more fun...
326 */ 328 */
327 if (mm_insn_16bit(ip->halfword[1])) { 329 if (mm_insn_16bit(ip->word >> 16)) {
328 return (ip->mm16_r3_format.opcode == mm_pool16d_op && 330 if (ip->mm16_r3_format.opcode == mm_pool16d_op &&
329 ip->mm16_r3_format.simmediate && mm_addiusp_func) || 331 ip->mm16_r3_format.simmediate & mm_addiusp_func) {
330 (ip->mm16_r5_format.opcode == mm_pool16d_op && 332 tmp = ip->mm_b0_format.simmediate >> 1;
331 ip->mm16_r5_format.rt == 29); 333 tmp = ((tmp & 0x1ff) ^ 0x100) - 0x100;
334 if ((tmp + 2) < 4) /* 0x0,0x1,0x1fe,0x1ff are special */
335 tmp ^= 0x100;
336 *frame_size = -(signed short)(tmp << 2);
337 return 1;
338 }
339 if (ip->mm16_r5_format.opcode == mm_pool16d_op &&
340 ip->mm16_r5_format.rt == 29) {
341 tmp = ip->mm16_r5_format.imm >> 1;
342 *frame_size = -(signed short)(tmp & 0xf);
343 return 1;
344 }
345 return 0;
332 } 346 }
333 347
334 return ip->mm_i_format.opcode == mm_addiu32_op && 348 if (ip->mm_i_format.opcode == mm_addiu32_op &&
335 ip->mm_i_format.rt == 29 && ip->mm_i_format.rs == 29; 349 ip->mm_i_format.rt == 29 && ip->mm_i_format.rs == 29) {
350 *frame_size = -ip->i_format.simmediate;
351 return 1;
352 }
336#else 353#else
337 /* addiu/daddiu sp,sp,-imm */ 354 /* addiu/daddiu sp,sp,-imm */
338 if (ip->i_format.rs != 29 || ip->i_format.rt != 29) 355 if (ip->i_format.rs != 29 || ip->i_format.rt != 29)
339 return 0; 356 return 0;
340 if (ip->i_format.opcode == addiu_op || ip->i_format.opcode == daddiu_op) 357
358 if (ip->i_format.opcode == addiu_op ||
359 ip->i_format.opcode == daddiu_op) {
360 *frame_size = -ip->i_format.simmediate;
341 return 1; 361 return 1;
362 }
342#endif 363#endif
343 return 0; 364 return 0;
344} 365}
@@ -348,7 +369,9 @@ static int get_frame_info(struct mips_frame_info *info)
348 bool is_mmips = IS_ENABLED(CONFIG_CPU_MICROMIPS); 369 bool is_mmips = IS_ENABLED(CONFIG_CPU_MICROMIPS);
349 union mips_instruction insn, *ip, *ip_end; 370 union mips_instruction insn, *ip, *ip_end;
350 const unsigned int max_insns = 128; 371 const unsigned int max_insns = 128;
372 unsigned int last_insn_size = 0;
351 unsigned int i; 373 unsigned int i;
374 bool saw_jump = false;
352 375
353 info->pc_offset = -1; 376 info->pc_offset = -1;
354 info->frame_size = 0; 377 info->frame_size = 0;
@@ -359,47 +382,44 @@ static int get_frame_info(struct mips_frame_info *info)
359 382
360 ip_end = (void *)ip + info->func_size; 383 ip_end = (void *)ip + info->func_size;
361 384
362 for (i = 0; i < max_insns && ip < ip_end; i++, ip++) { 385 for (i = 0; i < max_insns && ip < ip_end; i++) {
386 ip = (void *)ip + last_insn_size;
363 if (is_mmips && mm_insn_16bit(ip->halfword[0])) { 387 if (is_mmips && mm_insn_16bit(ip->halfword[0])) {
364 insn.halfword[0] = 0; 388 insn.word = ip->halfword[0] << 16;
365 insn.halfword[1] = ip->halfword[0]; 389 last_insn_size = 2;
366 } else if (is_mmips) { 390 } else if (is_mmips) {
367 insn.halfword[0] = ip->halfword[1]; 391 insn.word = ip->halfword[0] << 16 | ip->halfword[1];
368 insn.halfword[1] = ip->halfword[0]; 392 last_insn_size = 4;
369 } else { 393 } else {
370 insn.word = ip->word; 394 insn.word = ip->word;
395 last_insn_size = 4;
371 } 396 }
372 397
373 if (is_jump_ins(&insn))
374 break;
375
376 if (!info->frame_size) { 398 if (!info->frame_size) {
377 if (is_sp_move_ins(&insn)) 399 is_sp_move_ins(&insn, &info->frame_size);
378 { 400 continue;
379#ifdef CONFIG_CPU_MICROMIPS 401 } else if (!saw_jump && is_jump_ins(ip)) {
380 if (mm_insn_16bit(ip->halfword[0])) 402 /*
381 { 403 * If we see a jump instruction, we are finished
382 unsigned short tmp; 404 * with the frame save.
383 405 *
384 if (ip->halfword[0] & mm_addiusp_func) 406 * Some functions can have a shortcut return at
385 { 407 * the beginning of the function, so don't start
386 tmp = (((ip->halfword[0] >> 1) & 0x1ff) << 2); 408 * looking for jump instruction until we see the
387 info->frame_size = -(signed short)(tmp | ((tmp & 0x100) ? 0xfe00 : 0)); 409 * frame setup.
388 } else { 410 *
389 tmp = (ip->halfword[0] >> 1); 411 * The RA save instruction can get put into the
390 info->frame_size = -(signed short)(tmp & 0xf); 412 * delay slot of the jump instruction, so look
391 } 413 * at the next instruction, too.
392 ip = (void *) &ip->halfword[1]; 414 */
393 ip--; 415 saw_jump = true;
394 } else
395#endif
396 info->frame_size = - ip->i_format.simmediate;
397 }
398 continue; 416 continue;
399 } 417 }
400 if (info->pc_offset == -1 && 418 if (info->pc_offset == -1 &&
401 is_ra_save_ins(&insn, &info->pc_offset)) 419 is_ra_save_ins(&insn, &info->pc_offset))
402 break; 420 break;
421 if (saw_jump)
422 break;
403 } 423 }
404 if (info->frame_size && info->pc_offset >= 0) /* nested */ 424 if (info->frame_size && info->pc_offset >= 0) /* nested */
405 return 0; 425 return 0;