diff options
| author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-08 14:43:17 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-08 14:43:17 -0400 |
| commit | 97d26b8042a6f14cc4a19e84e911a953363e3d69 (patch) | |
| tree | 9b72b650285720c17d0aa0a3795c30fe492700b3 | |
| parent | 5131bf5db73529e972459060d8559f72e036fe53 (diff) | |
| parent | dcef1f634657dabe7905af3ccda12cf7f0b6fcc1 (diff) | |
Merge master.kernel.org:/home/rmk/linux-2.6-arm
| -rw-r--r-- | arch/arm/kernel/entry-armv.S | 16 | ||||
| -rw-r--r-- | arch/arm/kernel/traps.c | 49 | ||||
| -rw-r--r-- | arch/arm/lib/io-writesw-armv4.S | 6 | ||||
| -rw-r--r-- | arch/arm/mm/Kconfig | 8 | ||||
| -rw-r--r-- | include/asm-arm/arch-pxa/pxa-regs.h | 2 |
5 files changed, 73 insertions, 8 deletions
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 4eb36155dc93..e14278d59882 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
| @@ -269,7 +269,7 @@ __pabt_svc: | |||
| 269 | add r5, sp, #S_PC | 269 | add r5, sp, #S_PC |
| 270 | ldmia r7, {r2 - r4} @ Get USR pc, cpsr | 270 | ldmia r7, {r2 - r4} @ Get USR pc, cpsr |
| 271 | 271 | ||
| 272 | #if __LINUX_ARM_ARCH__ < 6 | 272 | #if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) |
| 273 | @ make sure our user space atomic helper is aborted | 273 | @ make sure our user space atomic helper is aborted |
| 274 | cmp r2, #VIRT_OFFSET | 274 | cmp r2, #VIRT_OFFSET |
| 275 | bichs r3, r3, #PSR_Z_BIT | 275 | bichs r3, r3, #PSR_Z_BIT |
| @@ -616,11 +616,17 @@ __kuser_helper_start: | |||
| 616 | 616 | ||
| 617 | __kuser_cmpxchg: @ 0xffff0fc0 | 617 | __kuser_cmpxchg: @ 0xffff0fc0 |
| 618 | 618 | ||
| 619 | #if __LINUX_ARM_ARCH__ < 6 | 619 | #if defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) |
| 620 | 620 | ||
| 621 | #ifdef CONFIG_SMP /* sanity check */ | 621 | /* |
| 622 | #error "CONFIG_SMP on a machine supporting pre-ARMv6 processors?" | 622 | * Poor you. No fast solution possible... |
| 623 | #endif | 623 | * The kernel itself must perform the operation. |
| 624 | * A special ghost syscall is used for that (see traps.c). | ||
| 625 | */ | ||
| 626 | swi #0x9ffff0 | ||
| 627 | mov pc, lr | ||
| 628 | |||
| 629 | #elif __LINUX_ARM_ARCH__ < 6 | ||
| 624 | 630 | ||
| 625 | /* | 631 | /* |
| 626 | * Theory of operation: | 632 | * Theory of operation: |
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 14df16b983f4..45d2a032d890 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
| @@ -464,6 +464,55 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) | |||
| 464 | #endif | 464 | #endif |
| 465 | return 0; | 465 | return 0; |
| 466 | 466 | ||
| 467 | #ifdef CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG | ||
| 468 | /* | ||
| 469 | * Atomically store r1 in *r2 if *r2 is equal to r0 for user space. | ||
| 470 | * Return zero in r0 if *MEM was changed or non-zero if no exchange | ||
| 471 | * happened. Also set the user C flag accordingly. | ||
| 472 | * If access permissions have to be fixed up then non-zero is | ||
| 473 | * returned and the operation has to be re-attempted. | ||
| 474 | * | ||
| 475 | * *NOTE*: This is a ghost syscall private to the kernel. Only the | ||
| 476 | * __kuser_cmpxchg code in entry-armv.S should be aware of its | ||
| 477 | * existence. Don't ever use this from user code. | ||
| 478 | */ | ||
| 479 | case 0xfff0: | ||
| 480 | { | ||
| 481 | extern void do_DataAbort(unsigned long addr, unsigned int fsr, | ||
| 482 | struct pt_regs *regs); | ||
| 483 | unsigned long val; | ||
| 484 | unsigned long addr = regs->ARM_r2; | ||
| 485 | struct mm_struct *mm = current->mm; | ||
| 486 | pgd_t *pgd; pmd_t *pmd; pte_t *pte; | ||
| 487 | |||
| 488 | regs->ARM_cpsr &= ~PSR_C_BIT; | ||
| 489 | spin_lock(&mm->page_table_lock); | ||
| 490 | pgd = pgd_offset(mm, addr); | ||
| 491 | if (!pgd_present(*pgd)) | ||
| 492 | goto bad_access; | ||
| 493 | pmd = pmd_offset(pgd, addr); | ||
| 494 | if (!pmd_present(*pmd)) | ||
| 495 | goto bad_access; | ||
| 496 | pte = pte_offset_map(pmd, addr); | ||
| 497 | if (!pte_present(*pte) || !pte_write(*pte)) | ||
| 498 | goto bad_access; | ||
| 499 | val = *(unsigned long *)addr; | ||
| 500 | val -= regs->ARM_r0; | ||
| 501 | if (val == 0) { | ||
| 502 | *(unsigned long *)addr = regs->ARM_r1; | ||
| 503 | regs->ARM_cpsr |= PSR_C_BIT; | ||
| 504 | } | ||
| 505 | spin_unlock(&mm->page_table_lock); | ||
| 506 | return val; | ||
| 507 | |||
| 508 | bad_access: | ||
| 509 | spin_unlock(&mm->page_table_lock); | ||
| 510 | /* simulate a read access fault */ | ||
| 511 | do_DataAbort(addr, 15 + (1 << 11), regs); | ||
| 512 | return -1; | ||
| 513 | } | ||
| 514 | #endif | ||
| 515 | |||
| 467 | default: | 516 | default: |
| 468 | /* Calls 9f00xx..9f07ff are defined to return -ENOSYS | 517 | /* Calls 9f00xx..9f07ff are defined to return -ENOSYS |
| 469 | if not implemented, rather than raising SIGILL. This | 518 | if not implemented, rather than raising SIGILL. This |
diff --git a/arch/arm/lib/io-writesw-armv4.S b/arch/arm/lib/io-writesw-armv4.S index 6d1d7c27806e..5e240e452af6 100644 --- a/arch/arm/lib/io-writesw-armv4.S +++ b/arch/arm/lib/io-writesw-armv4.S | |||
| @@ -87,9 +87,9 @@ ENTRY(__raw_writesw) | |||
| 87 | subs r2, r2, #2 | 87 | subs r2, r2, #2 |
| 88 | orr ip, ip, r3, push_hbyte1 | 88 | orr ip, ip, r3, push_hbyte1 |
| 89 | strh ip, [r0] | 89 | strh ip, [r0] |
| 90 | bpl 2b | 90 | bpl 1b |
| 91 | 91 | ||
| 92 | 3: tst r2, #1 | 92 | tst r2, #1 |
| 93 | 2: movne ip, r3, lsr #8 | 93 | 3: movne ip, r3, lsr #8 |
| 94 | strneh ip, [r0] | 94 | strneh ip, [r0] |
| 95 | mov pc, lr | 95 | mov pc, lr |
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index ade0e2222f59..3fefb43c67f7 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
| @@ -422,3 +422,11 @@ config HAS_TLS_REG | |||
| 422 | assume directly accessing that register and always obtain the | 422 | assume directly accessing that register and always obtain the |
| 423 | expected value only on ARMv7 and above. | 423 | expected value only on ARMv7 and above. |
| 424 | 424 | ||
| 425 | config NEEDS_SYSCALL_FOR_CMPXCHG | ||
| 426 | bool | ||
| 427 | default y if SMP && (CPU_32v5 || CPU_32v4 || CPU_32v3) | ||
| 428 | help | ||
| 429 | SMP on a pre-ARMv6 processor? Well OK then. | ||
| 430 | Forget about fast user space cmpxchg support. | ||
| 431 | It is just not possible. | ||
| 432 | |||
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h index 39741d3c9a34..b5e54a9e9fa7 100644 --- a/include/asm-arm/arch-pxa/pxa-regs.h +++ b/include/asm-arm/arch-pxa/pxa-regs.h | |||
| @@ -1296,6 +1296,7 @@ | |||
| 1296 | #define GPIO111_MMCDAT3 111 /* MMC DAT3 (PXA27x) */ | 1296 | #define GPIO111_MMCDAT3 111 /* MMC DAT3 (PXA27x) */ |
| 1297 | #define GPIO111_MMCCS1 111 /* MMC Chip Select 1 (PXA27x) */ | 1297 | #define GPIO111_MMCCS1 111 /* MMC Chip Select 1 (PXA27x) */ |
| 1298 | #define GPIO112_MMCCMD 112 /* MMC CMD (PXA27x) */ | 1298 | #define GPIO112_MMCCMD 112 /* MMC CMD (PXA27x) */ |
| 1299 | #define GPIO113_I2S_SYSCLK 113 /* I2S System Clock (PXA27x) */ | ||
| 1299 | #define GPIO113_AC97_RESET_N 113 /* AC97 NRESET on (PXA27x) */ | 1300 | #define GPIO113_AC97_RESET_N 113 /* AC97 NRESET on (PXA27x) */ |
| 1300 | 1301 | ||
| 1301 | /* GPIO alternate function mode & direction */ | 1302 | /* GPIO alternate function mode & direction */ |
| @@ -1428,6 +1429,7 @@ | |||
| 1428 | #define GPIO111_MMCDAT3_MD (111 | GPIO_ALT_FN_1_OUT) | 1429 | #define GPIO111_MMCDAT3_MD (111 | GPIO_ALT_FN_1_OUT) |
| 1429 | #define GPIO110_MMCCS1_MD (111 | GPIO_ALT_FN_1_OUT) | 1430 | #define GPIO110_MMCCS1_MD (111 | GPIO_ALT_FN_1_OUT) |
| 1430 | #define GPIO112_MMCCMD_MD (112 | GPIO_ALT_FN_1_OUT) | 1431 | #define GPIO112_MMCCMD_MD (112 | GPIO_ALT_FN_1_OUT) |
| 1432 | #define GPIO113_I2S_SYSCLK_MD (113 | GPIO_ALT_FN_1_OUT) | ||
| 1431 | #define GPIO113_AC97_RESET_N_MD (113 | GPIO_ALT_FN_2_OUT) | 1433 | #define GPIO113_AC97_RESET_N_MD (113 | GPIO_ALT_FN_2_OUT) |
| 1432 | #define GPIO117_I2CSCL_MD (117 | GPIO_ALT_FN_1_OUT) | 1434 | #define GPIO117_I2CSCL_MD (117 | GPIO_ALT_FN_1_OUT) |
| 1433 | #define GPIO118_I2CSDA_MD (118 | GPIO_ALT_FN_1_IN) | 1435 | #define GPIO118_I2CSDA_MD (118 | GPIO_ALT_FN_1_IN) |
