diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-15 23:43:33 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-15 23:43:33 -0400 |
| commit | 7318413077a5141a50a753b1fab687b7907eef16 (patch) | |
| tree | 21a59cf856f4bb762f6d3d0635c898ca6b24cff6 /arch/mips/kernel/process.c | |
| parent | 8d93c7a4315711ea0f7a95ca353a89c4ed0763fb (diff) | |
| parent | 35eed7cb2cf1c58a225a0140729ba787fbb06c88 (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.c | 102 |
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 | ||
| 316 | static inline int is_sp_move_ins(union mips_instruction *ip) | 316 | static 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; |
