diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-23 15:05:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-23 15:05:44 -0400 |
commit | 3813d4024a75562baf77d3907fb6afbf8f9c8232 (patch) | |
tree | 6675ef449bd0ed7adbe1b785eaed25db55bc29f3 /arch/ia64/kernel | |
parent | 2335a8366f63a5191b5a2b3c5a05d90fe814654c (diff) | |
parent | 4035c6db5a9dedf5e79c502bf39389a0b714cb38 (diff) |
Merge tag 'ia64-3.5-merge' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux
Pull Itanium fixes from Tony Luck.
* tag 'ia64-3.5-merge' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux:
[IA64] Liberate the signal layer from IA64 assembler
[IA64] Add cmpxchg.h to exported userspace headers
[IA64] Fix fast syscall version of getcpu()
[IA64] Removed "task_size" element from thread_struct - it is now constant
Diffstat (limited to 'arch/ia64/kernel')
-rw-r--r-- | arch/ia64/kernel/fsys.S | 191 |
1 files changed, 13 insertions, 178 deletions
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S index cc26edac0ec6..e662f178b990 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S | |||
@@ -372,175 +372,6 @@ ENTRY(fsys_clock_gettime) | |||
372 | END(fsys_clock_gettime) | 372 | END(fsys_clock_gettime) |
373 | 373 | ||
374 | /* | 374 | /* |
375 | * long fsys_rt_sigprocmask (int how, sigset_t *set, sigset_t *oset, size_t sigsetsize). | ||
376 | */ | ||
377 | #if _NSIG_WORDS != 1 | ||
378 | # error Sorry, fsys_rt_sigprocmask() needs to be updated for _NSIG_WORDS != 1. | ||
379 | #endif | ||
380 | ENTRY(fsys_rt_sigprocmask) | ||
381 | .prologue | ||
382 | .altrp b6 | ||
383 | .body | ||
384 | |||
385 | add r2=IA64_TASK_BLOCKED_OFFSET,r16 | ||
386 | add r9=TI_FLAGS+IA64_TASK_SIZE,r16 | ||
387 | cmp4.ltu p6,p0=SIG_SETMASK,r32 | ||
388 | |||
389 | cmp.ne p15,p0=r0,r34 // oset != NULL? | ||
390 | tnat.nz p8,p0=r34 | ||
391 | add r31=IA64_TASK_SIGHAND_OFFSET,r16 | ||
392 | ;; | ||
393 | ld8 r3=[r2] // read/prefetch current->blocked | ||
394 | ld4 r9=[r9] | ||
395 | tnat.nz.or p6,p0=r35 | ||
396 | |||
397 | cmp.ne.or p6,p0=_NSIG_WORDS*8,r35 | ||
398 | tnat.nz.or p6,p0=r32 | ||
399 | (p6) br.spnt.few .fail_einval // fail with EINVAL | ||
400 | ;; | ||
401 | #ifdef CONFIG_SMP | ||
402 | ld8 r31=[r31] // r31 <- current->sighand | ||
403 | #endif | ||
404 | and r9=TIF_ALLWORK_MASK,r9 | ||
405 | tnat.nz.or p8,p0=r33 | ||
406 | ;; | ||
407 | cmp.ne p7,p0=0,r9 | ||
408 | cmp.eq p6,p0=r0,r33 // set == NULL? | ||
409 | add r31=IA64_SIGHAND_SIGLOCK_OFFSET,r31 // r31 <- current->sighand->siglock | ||
410 | (p8) br.spnt.few .fail_efault // fail with EFAULT | ||
411 | (p7) br.spnt.many fsys_fallback_syscall // got pending kernel work... | ||
412 | (p6) br.dpnt.many .store_mask // -> short-circuit to just reading the signal mask | ||
413 | |||
414 | /* Argh, we actually have to do some work and _update_ the signal mask: */ | ||
415 | |||
416 | EX(.fail_efault, probe.r.fault r33, 3) // verify user has read-access to *set | ||
417 | EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set | ||
418 | mov r17=(1 << (SIGKILL - 1)) | (1 << (SIGSTOP - 1)) | ||
419 | ;; | ||
420 | |||
421 | RSM_PSR_I(p0, r18, r19) // mask interrupt delivery | ||
422 | andcm r14=r14,r17 // filter out SIGKILL & SIGSTOP | ||
423 | mov r8=EINVAL // default to EINVAL | ||
424 | |||
425 | #ifdef CONFIG_SMP | ||
426 | // __ticket_spin_trylock(r31) | ||
427 | ld4 r17=[r31] | ||
428 | ;; | ||
429 | mov.m ar.ccv=r17 | ||
430 | extr.u r9=r17,17,15 | ||
431 | adds r19=1,r17 | ||
432 | extr.u r18=r17,0,15 | ||
433 | ;; | ||
434 | cmp.eq p6,p7=r9,r18 | ||
435 | ;; | ||
436 | (p6) cmpxchg4.acq r9=[r31],r19,ar.ccv | ||
437 | (p6) dep.z r20=r19,1,15 // next serving ticket for unlock | ||
438 | (p7) br.cond.spnt.many .lock_contention | ||
439 | ;; | ||
440 | cmp4.eq p0,p7=r9,r17 | ||
441 | adds r31=2,r31 | ||
442 | (p7) br.cond.spnt.many .lock_contention | ||
443 | ld8 r3=[r2] // re-read current->blocked now that we hold the lock | ||
444 | ;; | ||
445 | #else | ||
446 | ld8 r3=[r2] // re-read current->blocked now that we hold the lock | ||
447 | #endif | ||
448 | add r18=IA64_TASK_PENDING_OFFSET+IA64_SIGPENDING_SIGNAL_OFFSET,r16 | ||
449 | add r19=IA64_TASK_SIGNAL_OFFSET,r16 | ||
450 | cmp4.eq p6,p0=SIG_BLOCK,r32 | ||
451 | ;; | ||
452 | ld8 r19=[r19] // r19 <- current->signal | ||
453 | cmp4.eq p7,p0=SIG_UNBLOCK,r32 | ||
454 | cmp4.eq p8,p0=SIG_SETMASK,r32 | ||
455 | ;; | ||
456 | ld8 r18=[r18] // r18 <- current->pending.signal | ||
457 | .pred.rel.mutex p6,p7,p8 | ||
458 | (p6) or r14=r3,r14 // SIG_BLOCK | ||
459 | (p7) andcm r14=r3,r14 // SIG_UNBLOCK | ||
460 | |||
461 | (p8) mov r14=r14 // SIG_SETMASK | ||
462 | (p6) mov r8=0 // clear error code | ||
463 | // recalc_sigpending() | ||
464 | add r17=IA64_SIGNAL_GROUP_STOP_COUNT_OFFSET,r19 | ||
465 | |||
466 | add r19=IA64_SIGNAL_SHARED_PENDING_OFFSET+IA64_SIGPENDING_SIGNAL_OFFSET,r19 | ||
467 | ;; | ||
468 | ld4 r17=[r17] // r17 <- current->signal->group_stop_count | ||
469 | (p7) mov r8=0 // clear error code | ||
470 | |||
471 | ld8 r19=[r19] // r19 <- current->signal->shared_pending | ||
472 | ;; | ||
473 | cmp4.gt p6,p7=r17,r0 // p6/p7 <- (current->signal->group_stop_count > 0)? | ||
474 | (p8) mov r8=0 // clear error code | ||
475 | |||
476 | or r18=r18,r19 // r18 <- current->pending | current->signal->shared_pending | ||
477 | ;; | ||
478 | // r18 <- (current->pending | current->signal->shared_pending) & ~current->blocked: | ||
479 | andcm r18=r18,r14 | ||
480 | add r9=TI_FLAGS+IA64_TASK_SIZE,r16 | ||
481 | ;; | ||
482 | |||
483 | (p7) cmp.ne.or.andcm p6,p7=r18,r0 // p6/p7 <- signal pending | ||
484 | mov r19=0 // i must not leak kernel bits... | ||
485 | (p6) br.cond.dpnt.many .sig_pending | ||
486 | ;; | ||
487 | |||
488 | 1: ld4 r17=[r9] // r17 <- current->thread_info->flags | ||
489 | ;; | ||
490 | mov ar.ccv=r17 | ||
491 | and r18=~_TIF_SIGPENDING,r17 // r18 <- r17 & ~(1 << TIF_SIGPENDING) | ||
492 | ;; | ||
493 | |||
494 | st8 [r2]=r14 // update current->blocked with new mask | ||
495 | cmpxchg4.acq r8=[r9],r18,ar.ccv // current->thread_info->flags <- r18 | ||
496 | ;; | ||
497 | cmp.ne p6,p0=r17,r8 // update failed? | ||
498 | (p6) br.cond.spnt.few 1b // yes -> retry | ||
499 | |||
500 | #ifdef CONFIG_SMP | ||
501 | // __ticket_spin_unlock(r31) | ||
502 | st2.rel [r31]=r20 | ||
503 | mov r20=0 // i must not leak kernel bits... | ||
504 | #endif | ||
505 | SSM_PSR_I(p0, p9, r31) | ||
506 | ;; | ||
507 | |||
508 | srlz.d // ensure psr.i is set again | ||
509 | mov r18=0 // i must not leak kernel bits... | ||
510 | |||
511 | .store_mask: | ||
512 | EX(.fail_efault, (p15) probe.w.fault r34, 3) // verify user has write-access to *oset | ||
513 | EX(.fail_efault, (p15) st8 [r34]=r3) | ||
514 | mov r2=0 // i must not leak kernel bits... | ||
515 | mov r3=0 // i must not leak kernel bits... | ||
516 | mov r8=0 // return 0 | ||
517 | mov r9=0 // i must not leak kernel bits... | ||
518 | mov r14=0 // i must not leak kernel bits... | ||
519 | mov r17=0 // i must not leak kernel bits... | ||
520 | mov r31=0 // i must not leak kernel bits... | ||
521 | FSYS_RETURN | ||
522 | |||
523 | .sig_pending: | ||
524 | #ifdef CONFIG_SMP | ||
525 | // __ticket_spin_unlock(r31) | ||
526 | st2.rel [r31]=r20 // release the lock | ||
527 | #endif | ||
528 | SSM_PSR_I(p0, p9, r17) | ||
529 | ;; | ||
530 | srlz.d | ||
531 | br.sptk.many fsys_fallback_syscall // with signal pending, do the heavy-weight syscall | ||
532 | |||
533 | #ifdef CONFIG_SMP | ||
534 | .lock_contention: | ||
535 | /* Rather than spinning here, fall back on doing a heavy-weight syscall. */ | ||
536 | SSM_PSR_I(p0, p9, r17) | ||
537 | ;; | ||
538 | srlz.d | ||
539 | br.sptk.many fsys_fallback_syscall | ||
540 | #endif | ||
541 | END(fsys_rt_sigprocmask) | ||
542 | |||
543 | /* | ||
544 | * fsys_getcpu doesn't use the third parameter in this implementation. It reads | 375 | * fsys_getcpu doesn't use the third parameter in this implementation. It reads |
545 | * current_thread_info()->cpu and corresponding node in cpu_to_node_map. | 376 | * current_thread_info()->cpu and corresponding node in cpu_to_node_map. |
546 | */ | 377 | */ |
@@ -559,11 +390,15 @@ ENTRY(fsys_getcpu) | |||
559 | ;; | 390 | ;; |
560 | tnat.nz p7,p0 = r33 // I guard against NaT argument | 391 | tnat.nz p7,p0 = r33 // I guard against NaT argument |
561 | (p7) br.cond.spnt.few .fail_einval // B | 392 | (p7) br.cond.spnt.few .fail_einval // B |
393 | ;; | ||
394 | cmp.ne p6,p0=r32,r0 | ||
395 | cmp.ne p7,p0=r33,r0 | ||
396 | ;; | ||
562 | #ifdef CONFIG_NUMA | 397 | #ifdef CONFIG_NUMA |
563 | movl r17=cpu_to_node_map | 398 | movl r17=cpu_to_node_map |
564 | ;; | 399 | ;; |
565 | EX(.fail_efault, probe.w.fault r32, 3) // M This takes 5 cycles | 400 | EX(.fail_efault, (p6) probe.w.fault r32, 3) // M This takes 5 cycles |
566 | EX(.fail_efault, probe.w.fault r33, 3) // M This takes 5 cycles | 401 | EX(.fail_efault, (p7) probe.w.fault r33, 3) // M This takes 5 cycles |
567 | shladd r18=r3,1,r17 | 402 | shladd r18=r3,1,r17 |
568 | ;; | 403 | ;; |
569 | ld2 r20=[r18] // r20 = cpu_to_node_map[cpu] | 404 | ld2 r20=[r18] // r20 = cpu_to_node_map[cpu] |
@@ -573,20 +408,20 @@ EX(.fail_efault, probe.w.fault r33, 3) // M This takes 5 cycles | |||
573 | (p8) br.spnt.many fsys_fallback_syscall | 408 | (p8) br.spnt.many fsys_fallback_syscall |
574 | ;; | 409 | ;; |
575 | ;; | 410 | ;; |
576 | EX(.fail_efault, st4 [r32] = r3) | 411 | EX(.fail_efault, (p6) st4 [r32] = r3) |
577 | EX(.fail_efault, st2 [r33] = r20) | 412 | EX(.fail_efault, (p7) st2 [r33] = r20) |
578 | mov r8=0 | 413 | mov r8=0 |
579 | ;; | 414 | ;; |
580 | #else | 415 | #else |
581 | EX(.fail_efault, probe.w.fault r32, 3) // M This takes 5 cycles | 416 | EX(.fail_efault, (p6) probe.w.fault r32, 3) // M This takes 5 cycles |
582 | EX(.fail_efault, probe.w.fault r33, 3) // M This takes 5 cycles | 417 | EX(.fail_efault, (p7) probe.w.fault r33, 3) // M This takes 5 cycles |
583 | and r2 = TIF_ALLWORK_MASK,r2 | 418 | and r2 = TIF_ALLWORK_MASK,r2 |
584 | ;; | 419 | ;; |
585 | cmp.ne p8,p0=0,r2 | 420 | cmp.ne p8,p0=0,r2 |
586 | (p8) br.spnt.many fsys_fallback_syscall | 421 | (p8) br.spnt.many fsys_fallback_syscall |
587 | ;; | 422 | ;; |
588 | EX(.fail_efault, st4 [r32] = r3) | 423 | EX(.fail_efault, (p6) st4 [r32] = r3) |
589 | EX(.fail_efault, st2 [r33] = r0) | 424 | EX(.fail_efault, (p7) st2 [r33] = r0) |
590 | mov r8=0 | 425 | mov r8=0 |
591 | ;; | 426 | ;; |
592 | #endif | 427 | #endif |
@@ -916,7 +751,7 @@ paravirt_fsyscall_table: | |||
916 | data8 0 // sigaltstack | 751 | data8 0 // sigaltstack |
917 | data8 0 // rt_sigaction | 752 | data8 0 // rt_sigaction |
918 | data8 0 // rt_sigpending | 753 | data8 0 // rt_sigpending |
919 | data8 fsys_rt_sigprocmask // rt_sigprocmask | 754 | data8 0 // rt_sigprocmask |
920 | data8 0 // rt_sigqueueinfo // 1180 | 755 | data8 0 // rt_sigqueueinfo // 1180 |
921 | data8 0 // rt_sigreturn | 756 | data8 0 // rt_sigreturn |
922 | data8 0 // rt_sigsuspend | 757 | data8 0 // rt_sigsuspend |