aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc/kernel
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2016-01-12 05:01:12 -0500
committerThomas Gleixner <tglx@linutronix.de>2016-01-12 05:01:12 -0500
commit1f16f116b01c110db20ab808562c8b8bc3ee3d6e (patch)
tree44db563f64cf5f8d62af8f99a61e2b248c44ea3a /arch/parisc/kernel
parent03724ac3d48f8f0e3caf1d30fa134f8fd96c94e2 (diff)
parentf9eccf24615672896dc13251410c3f2f33a14f95 (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.c18
-rw-r--r--arch/parisc/kernel/signal.c64
-rw-r--r--arch/parisc/kernel/syscall_table.S1
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
174void __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
443static 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
438static inline void 487static inline void
439syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) 488syscall_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))