diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2016-01-12 05:01:12 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2016-01-12 05:01:12 -0500 |
commit | 1f16f116b01c110db20ab808562c8b8bc3ee3d6e (patch) | |
tree | 44db563f64cf5f8d62af8f99a61e2b248c44ea3a /arch/parisc/kernel | |
parent | 03724ac3d48f8f0e3caf1d30fa134f8fd96c94e2 (diff) | |
parent | f9eccf24615672896dc13251410c3f2f33a14f95 (diff) |
Merge branches 'clockevents/4.4-fixes' and 'clockevents/4.5-fixes' of http://git.linaro.org/people/daniel.lezcano/linux into timers/urgent
Pull in fixes from Daniel Lezcano:
- Fix the vt8500 timer leading to a system lock up when dealing with too
small delta (Roman Volkov)
- Select the CLKSRC_MMIO when the fsl_ftm_timer is enabled with COMPILE_TEST
(Daniel Lezcano)
- Prevent to compile timers using the 'iomem' API when the architecture has
not HAS_IOMEM set (Richard Weinberger)
Diffstat (limited to 'arch/parisc/kernel')
-rw-r--r-- | arch/parisc/kernel/pci.c | 18 | ||||
-rw-r--r-- | arch/parisc/kernel/signal.c | 64 | ||||
-rw-r--r-- | arch/parisc/kernel/syscall_table.S | 1 |
3 files changed, 53 insertions, 30 deletions
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c index 64f2764a8cef..c99f3dde455c 100644 --- a/arch/parisc/kernel/pci.c +++ b/arch/parisc/kernel/pci.c | |||
@@ -171,24 +171,6 @@ void pcibios_set_master(struct pci_dev *dev) | |||
171 | } | 171 | } |
172 | 172 | ||
173 | 173 | ||
174 | void __init pcibios_init_bus(struct pci_bus *bus) | ||
175 | { | ||
176 | struct pci_dev *dev = bus->self; | ||
177 | unsigned short bridge_ctl; | ||
178 | |||
179 | /* We deal only with pci controllers and pci-pci bridges. */ | ||
180 | if (!dev || (dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) | ||
181 | return; | ||
182 | |||
183 | /* PCI-PCI bridge - set the cache line and default latency | ||
184 | (32) for primary and secondary buses. */ | ||
185 | pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 32); | ||
186 | |||
187 | pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bridge_ctl); | ||
188 | bridge_ctl |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR; | ||
189 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bridge_ctl); | ||
190 | } | ||
191 | |||
192 | /* | 174 | /* |
193 | * pcibios align resources() is called every time generic PCI code | 175 | * pcibios align resources() is called every time generic PCI code |
194 | * wants to generate a new address. The process of looking for | 176 | * wants to generate a new address. The process of looking for |
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index dc1ea796fd60..2264f68f3c2f 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c | |||
@@ -435,6 +435,55 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs, int in_syscall) | |||
435 | regs->gr[28]); | 435 | regs->gr[28]); |
436 | } | 436 | } |
437 | 437 | ||
438 | /* | ||
439 | * Check how the syscall number gets loaded into %r20 within | ||
440 | * the delay branch in userspace and adjust as needed. | ||
441 | */ | ||
442 | |||
443 | static void check_syscallno_in_delay_branch(struct pt_regs *regs) | ||
444 | { | ||
445 | u32 opcode, source_reg; | ||
446 | u32 __user *uaddr; | ||
447 | int err; | ||
448 | |||
449 | /* Usually we don't have to restore %r20 (the system call number) | ||
450 | * because it gets loaded in the delay slot of the branch external | ||
451 | * instruction via the ldi instruction. | ||
452 | * In some cases a register-to-register copy instruction might have | ||
453 | * been used instead, in which case we need to copy the syscall | ||
454 | * number into the source register before returning to userspace. | ||
455 | */ | ||
456 | |||
457 | /* A syscall is just a branch, so all we have to do is fiddle the | ||
458 | * return pointer so that the ble instruction gets executed again. | ||
459 | */ | ||
460 | regs->gr[31] -= 8; /* delayed branching */ | ||
461 | |||
462 | /* Get assembler opcode of code in delay branch */ | ||
463 | uaddr = (unsigned int *) ((regs->gr[31] & ~3) + 4); | ||
464 | err = get_user(opcode, uaddr); | ||
465 | if (err) | ||
466 | return; | ||
467 | |||
468 | /* Check if delay branch uses "ldi int,%r20" */ | ||
469 | if ((opcode & 0xffff0000) == 0x34140000) | ||
470 | return; /* everything ok, just return */ | ||
471 | |||
472 | /* Check if delay branch uses "nop" */ | ||
473 | if (opcode == INSN_NOP) | ||
474 | return; | ||
475 | |||
476 | /* Check if delay branch uses "copy %rX,%r20" */ | ||
477 | if ((opcode & 0xffe0ffff) == 0x08000254) { | ||
478 | source_reg = (opcode >> 16) & 31; | ||
479 | regs->gr[source_reg] = regs->gr[20]; | ||
480 | return; | ||
481 | } | ||
482 | |||
483 | pr_warn("syscall restart: %s (pid %d): unexpected opcode 0x%08x\n", | ||
484 | current->comm, task_pid_nr(current), opcode); | ||
485 | } | ||
486 | |||
438 | static inline void | 487 | static inline void |
439 | syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) | 488 | syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) |
440 | { | 489 | { |
@@ -457,10 +506,7 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) | |||
457 | } | 506 | } |
458 | /* fallthrough */ | 507 | /* fallthrough */ |
459 | case -ERESTARTNOINTR: | 508 | case -ERESTARTNOINTR: |
460 | /* A syscall is just a branch, so all | 509 | check_syscallno_in_delay_branch(regs); |
461 | * we have to do is fiddle the return pointer. | ||
462 | */ | ||
463 | regs->gr[31] -= 8; /* delayed branching */ | ||
464 | break; | 510 | break; |
465 | } | 511 | } |
466 | } | 512 | } |
@@ -510,15 +556,9 @@ insert_restart_trampoline(struct pt_regs *regs) | |||
510 | } | 556 | } |
511 | case -ERESTARTNOHAND: | 557 | case -ERESTARTNOHAND: |
512 | case -ERESTARTSYS: | 558 | case -ERESTARTSYS: |
513 | case -ERESTARTNOINTR: { | 559 | case -ERESTARTNOINTR: |
514 | /* Hooray for delayed branching. We don't | 560 | check_syscallno_in_delay_branch(regs); |
515 | * have to restore %r20 (the system call | ||
516 | * number) because it gets loaded in the delay | ||
517 | * slot of the branch external instruction. | ||
518 | */ | ||
519 | regs->gr[31] -= 8; | ||
520 | return; | 561 | return; |
521 | } | ||
522 | default: | 562 | default: |
523 | break; | 563 | break; |
524 | } | 564 | } |
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 78c3ef8c348d..d4ffcfbc9885 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S | |||
@@ -440,6 +440,7 @@ | |||
440 | ENTRY_COMP(execveat) | 440 | ENTRY_COMP(execveat) |
441 | ENTRY_SAME(membarrier) | 441 | ENTRY_SAME(membarrier) |
442 | ENTRY_SAME(userfaultfd) | 442 | ENTRY_SAME(userfaultfd) |
443 | ENTRY_SAME(mlock2) /* 345 */ | ||
443 | 444 | ||
444 | 445 | ||
445 | .ifne (. - 90b) - (__NR_Linux_syscalls * (91b - 90b)) | 446 | .ifne (. - 90b) - (__NR_Linux_syscalls * (91b - 90b)) |