diff options
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/align.c | 36 | ||||
-rw-r--r-- | arch/powerpc/kernel/ftrace.c | 5 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_32.S | 15 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci-common.c | 17 |
4 files changed, 49 insertions, 24 deletions
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index 5af4e9b2dbe2..73cb6a3229ae 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c | |||
@@ -367,27 +367,24 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, | |||
367 | static int emulate_fp_pair(unsigned char __user *addr, unsigned int reg, | 367 | static int emulate_fp_pair(unsigned char __user *addr, unsigned int reg, |
368 | unsigned int flags) | 368 | unsigned int flags) |
369 | { | 369 | { |
370 | char *ptr = (char *) ¤t->thread.TS_FPR(reg); | 370 | char *ptr0 = (char *) ¤t->thread.TS_FPR(reg); |
371 | int i, ret; | 371 | char *ptr1 = (char *) ¤t->thread.TS_FPR(reg+1); |
372 | int i, ret, sw = 0; | ||
372 | 373 | ||
373 | if (!(flags & F)) | 374 | if (!(flags & F)) |
374 | return 0; | 375 | return 0; |
375 | if (reg & 1) | 376 | if (reg & 1) |
376 | return 0; /* invalid form: FRS/FRT must be even */ | 377 | return 0; /* invalid form: FRS/FRT must be even */ |
377 | if (!(flags & SW)) { | 378 | if (flags & SW) |
378 | /* not byte-swapped - easy */ | 379 | sw = 7; |
379 | if (!(flags & ST)) | 380 | ret = 0; |
380 | ret = __copy_from_user(ptr, addr, 16); | 381 | for (i = 0; i < 8; ++i) { |
381 | else | 382 | if (!(flags & ST)) { |
382 | ret = __copy_to_user(addr, ptr, 16); | 383 | ret |= __get_user(ptr0[i^sw], addr + i); |
383 | } else { | 384 | ret |= __get_user(ptr1[i^sw], addr + i + 8); |
384 | /* each FPR value is byte-swapped separately */ | 385 | } else { |
385 | ret = 0; | 386 | ret |= __put_user(ptr0[i^sw], addr + i); |
386 | for (i = 0; i < 16; ++i) { | 387 | ret |= __put_user(ptr1[i^sw], addr + i + 8); |
387 | if (!(flags & ST)) | ||
388 | ret |= __get_user(ptr[i^7], addr + i); | ||
389 | else | ||
390 | ret |= __put_user(ptr[i^7], addr + i); | ||
391 | } | 388 | } |
392 | } | 389 | } |
393 | if (ret) | 390 | if (ret) |
@@ -646,11 +643,16 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg, | |||
646 | unsigned int areg, struct pt_regs *regs, | 643 | unsigned int areg, struct pt_regs *regs, |
647 | unsigned int flags, unsigned int length) | 644 | unsigned int flags, unsigned int length) |
648 | { | 645 | { |
649 | char *ptr = (char *) ¤t->thread.TS_FPR(reg); | 646 | char *ptr; |
650 | int ret = 0; | 647 | int ret = 0; |
651 | 648 | ||
652 | flush_vsx_to_thread(current); | 649 | flush_vsx_to_thread(current); |
653 | 650 | ||
651 | if (reg < 32) | ||
652 | ptr = (char *) ¤t->thread.TS_FPR(reg); | ||
653 | else | ||
654 | ptr = (char *) ¤t->thread.vr[reg - 32]; | ||
655 | |||
654 | if (flags & ST) | 656 | if (flags & ST) |
655 | ret = __copy_to_user(addr, ptr, length); | 657 | ret = __copy_to_user(addr, ptr, length); |
656 | else { | 658 | else { |
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c index 5355244c99ff..60c60ccf5e3c 100644 --- a/arch/powerpc/kernel/ftrace.c +++ b/arch/powerpc/kernel/ftrace.c | |||
@@ -195,8 +195,9 @@ __ftrace_make_nop(struct module *mod, | |||
195 | return -EINVAL; | 195 | return -EINVAL; |
196 | } | 196 | } |
197 | 197 | ||
198 | offset = (unsigned)((unsigned short)jmp[0]) << 16 | | 198 | /* The bottom half is signed extended */ |
199 | (unsigned)((unsigned short)jmp[1]); | 199 | offset = ((unsigned)((unsigned short)jmp[0]) << 16) + |
200 | (int)((short)jmp[1]); | ||
200 | 201 | ||
201 | DEBUGP(" %x ", offset); | 202 | DEBUGP(" %x ", offset); |
202 | 203 | ||
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index a1c4cfd25ded..d794a637e421 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S | |||
@@ -511,8 +511,11 @@ InstructionTLBMiss: | |||
511 | and r1,r1,r2 /* writable if _RW and _DIRTY */ | 511 | and r1,r1,r2 /* writable if _RW and _DIRTY */ |
512 | rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ | 512 | rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ |
513 | rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */ | 513 | rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */ |
514 | ori r1,r1,0xe14 /* clear out reserved bits and M */ | 514 | ori r1,r1,0xe04 /* clear out reserved bits */ |
515 | andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */ | 515 | andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */ |
516 | BEGIN_FTR_SECTION | ||
517 | rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ | ||
518 | END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) | ||
516 | mtspr SPRN_RPA,r1 | 519 | mtspr SPRN_RPA,r1 |
517 | mfspr r3,SPRN_IMISS | 520 | mfspr r3,SPRN_IMISS |
518 | tlbli r3 | 521 | tlbli r3 |
@@ -585,8 +588,11 @@ DataLoadTLBMiss: | |||
585 | and r1,r1,r2 /* writable if _RW and _DIRTY */ | 588 | and r1,r1,r2 /* writable if _RW and _DIRTY */ |
586 | rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ | 589 | rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ |
587 | rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */ | 590 | rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */ |
588 | ori r1,r1,0xe14 /* clear out reserved bits and M */ | 591 | ori r1,r1,0xe04 /* clear out reserved bits */ |
589 | andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */ | 592 | andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */ |
593 | BEGIN_FTR_SECTION | ||
594 | rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ | ||
595 | END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) | ||
590 | mtspr SPRN_RPA,r1 | 596 | mtspr SPRN_RPA,r1 |
591 | mfspr r3,SPRN_DMISS | 597 | mfspr r3,SPRN_DMISS |
592 | tlbld r3 | 598 | tlbld r3 |
@@ -653,8 +659,11 @@ DataStoreTLBMiss: | |||
653 | stw r3,0(r2) /* update PTE (accessed/dirty bits) */ | 659 | stw r3,0(r2) /* update PTE (accessed/dirty bits) */ |
654 | /* Convert linux-style PTE to low word of PPC-style PTE */ | 660 | /* Convert linux-style PTE to low word of PPC-style PTE */ |
655 | rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ | 661 | rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ |
656 | li r1,0xe15 /* clear out reserved bits and M */ | 662 | li r1,0xe05 /* clear out reserved bits & PP lsb */ |
657 | andc r1,r3,r1 /* PP = user? 2: 0 */ | 663 | andc r1,r3,r1 /* PP = user? 2: 0 */ |
664 | BEGIN_FTR_SECTION | ||
665 | rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ | ||
666 | END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) | ||
658 | mtspr SPRN_RPA,r1 | 667 | mtspr SPRN_RPA,r1 |
659 | mfspr r3,SPRN_DMISS | 668 | mfspr r3,SPRN_DMISS |
660 | tlbld r3 | 669 | tlbld r3 |
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 19b12d2cbb4b..0f4181272311 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -561,8 +561,21 @@ int pci_mmap_legacy_page_range(struct pci_bus *bus, | |||
561 | (unsigned long long)(offset + size - 1)); | 561 | (unsigned long long)(offset + size - 1)); |
562 | 562 | ||
563 | if (mmap_state == pci_mmap_mem) { | 563 | if (mmap_state == pci_mmap_mem) { |
564 | if ((offset + size) > hose->isa_mem_size) | 564 | /* Hack alert ! |
565 | return -ENXIO; | 565 | * |
566 | * Because X is lame and can fail starting if it gets an error trying | ||
567 | * to mmap legacy_mem (instead of just moving on without legacy memory | ||
568 | * access) we fake it here by giving it anonymous memory, effectively | ||
569 | * behaving just like /dev/zero | ||
570 | */ | ||
571 | if ((offset + size) > hose->isa_mem_size) { | ||
572 | printk(KERN_DEBUG | ||
573 | "Process %s (pid:%d) mapped non-existing PCI legacy memory for 0%04x:%02x\n", | ||
574 | current->comm, current->pid, pci_domain_nr(bus), bus->number); | ||
575 | if (vma->vm_flags & VM_SHARED) | ||
576 | return shmem_zero_setup(vma); | ||
577 | return 0; | ||
578 | } | ||
566 | offset += hose->isa_mem_phys; | 579 | offset += hose->isa_mem_phys; |
567 | } else { | 580 | } else { |
568 | unsigned long io_offset = (unsigned long)hose->io_base_virt - _IO_BASE; | 581 | unsigned long io_offset = (unsigned long)hose->io_base_virt - _IO_BASE; |