aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64')
-rw-r--r--arch/ia64/Kconfig11
-rw-r--r--arch/ia64/ia32/elfcore32.h14
-rw-r--r--arch/ia64/ia32/sys_ia32.c649
-rw-r--r--arch/ia64/kernel/asm-offsets.c6
-rw-r--r--arch/ia64/kernel/entry.S65
-rw-r--r--arch/ia64/kernel/fsys.S54
-rw-r--r--arch/ia64/kernel/head.S20
-rw-r--r--arch/ia64/kernel/ivt.S69
-rw-r--r--arch/ia64/kernel/minstate.h14
-rw-r--r--arch/ia64/kernel/patch.c8
-rw-r--r--arch/ia64/kernel/process.c30
-rw-r--r--arch/ia64/kernel/ptrace.c1217
-rw-r--r--arch/ia64/kernel/time.c78
-rw-r--r--arch/ia64/pci/pci.c7
14 files changed, 1843 insertions, 399 deletions
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 8fa3faf5ef1b..eef457fda08f 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -283,6 +283,17 @@ config FORCE_MAX_ZONEORDER
283 default "17" if HUGETLB_PAGE 283 default "17" if HUGETLB_PAGE
284 default "11" 284 default "11"
285 285
286config VIRT_CPU_ACCOUNTING
287 bool "Deterministic task and CPU time accounting"
288 default n
289 help
290 Select this option to enable more accurate task and CPU time
291 accounting. This is done by reading a CPU counter on each
292 kernel entry and exit and on transitions within the kernel
293 between system, softirq and hardirq state, so there is a
294 small performance impact.
295 If in doubt, say N here.
296
286config SMP 297config SMP
287 bool "Symmetric multi-processing support" 298 bool "Symmetric multi-processing support"
288 help 299 help
diff --git a/arch/ia64/ia32/elfcore32.h b/arch/ia64/ia32/elfcore32.h
index 446c9aac924d..9a3abf58cea3 100644
--- a/arch/ia64/ia32/elfcore32.h
+++ b/arch/ia64/ia32/elfcore32.h
@@ -30,7 +30,19 @@ struct elf_siginfo
30 int si_errno; /* errno */ 30 int si_errno; /* errno */
31}; 31};
32 32
33#define jiffies_to_timeval(a,b) do { (b)->tv_usec = 0; (b)->tv_sec = (a)/HZ; }while(0) 33#ifdef CONFIG_VIRT_CPU_ACCOUNTING
34/*
35 * Hacks are here since types between compat_timeval (= pair of s32) and
36 * ia64-native timeval (= pair of s64) are not compatible, at least a file
37 * arch/ia64/ia32/../../../fs/binfmt_elf.c will get warnings from compiler on
38 * use of cputime_to_timeval(), which usually an alias of jiffies_to_timeval().
39 */
40#define cputime_to_timeval(a,b) \
41 do { (b)->tv_usec = 0; (b)->tv_sec = (a)/NSEC_PER_SEC; } while(0)
42#else
43#define jiffies_to_timeval(a,b) \
44 do { (b)->tv_usec = 0; (b)->tv_sec = (a)/HZ; } while(0)
45#endif
34 46
35struct elf_prstatus 47struct elf_prstatus
36{ 48{
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index b1bf51fe97b4..7e028ceb93ba 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -38,6 +38,7 @@
38#include <linux/eventpoll.h> 38#include <linux/eventpoll.h>
39#include <linux/personality.h> 39#include <linux/personality.h>
40#include <linux/ptrace.h> 40#include <linux/ptrace.h>
41#include <linux/regset.h>
41#include <linux/stat.h> 42#include <linux/stat.h>
42#include <linux/ipc.h> 43#include <linux/ipc.h>
43#include <linux/capability.h> 44#include <linux/capability.h>
@@ -2387,16 +2388,45 @@ get_free_idx (void)
2387 return -ESRCH; 2388 return -ESRCH;
2388} 2389}
2389 2390
2391static void set_tls_desc(struct task_struct *p, int idx,
2392 const struct ia32_user_desc *info, int n)
2393{
2394 struct thread_struct *t = &p->thread;
2395 struct desc_struct *desc = &t->tls_array[idx - GDT_ENTRY_TLS_MIN];
2396 int cpu;
2397
2398 /*
2399 * We must not get preempted while modifying the TLS.
2400 */
2401 cpu = get_cpu();
2402
2403 while (n-- > 0) {
2404 if (LDT_empty(info)) {
2405 desc->a = 0;
2406 desc->b = 0;
2407 } else {
2408 desc->a = LDT_entry_a(info);
2409 desc->b = LDT_entry_b(info);
2410 }
2411
2412 ++info;
2413 ++desc;
2414 }
2415
2416 if (t == &current->thread)
2417 load_TLS(t, cpu);
2418
2419 put_cpu();
2420}
2421
2390/* 2422/*
2391 * Set a given TLS descriptor: 2423 * Set a given TLS descriptor:
2392 */ 2424 */
2393asmlinkage int 2425asmlinkage int
2394sys32_set_thread_area (struct ia32_user_desc __user *u_info) 2426sys32_set_thread_area (struct ia32_user_desc __user *u_info)
2395{ 2427{
2396 struct thread_struct *t = &current->thread;
2397 struct ia32_user_desc info; 2428 struct ia32_user_desc info;
2398 struct desc_struct *desc; 2429 int idx;
2399 int cpu, idx;
2400 2430
2401 if (copy_from_user(&info, u_info, sizeof(info))) 2431 if (copy_from_user(&info, u_info, sizeof(info)))
2402 return -EFAULT; 2432 return -EFAULT;
@@ -2416,18 +2446,7 @@ sys32_set_thread_area (struct ia32_user_desc __user *u_info)
2416 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) 2446 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
2417 return -EINVAL; 2447 return -EINVAL;
2418 2448
2419 desc = t->tls_array + idx - GDT_ENTRY_TLS_MIN; 2449 set_tls_desc(current, idx, &info, 1);
2420
2421 cpu = smp_processor_id();
2422
2423 if (LDT_empty(&info)) {
2424 desc->a = 0;
2425 desc->b = 0;
2426 } else {
2427 desc->a = LDT_entry_a(&info);
2428 desc->b = LDT_entry_b(&info);
2429 }
2430 load_TLS(t, cpu);
2431 return 0; 2450 return 0;
2432} 2451}
2433 2452
@@ -2451,6 +2470,20 @@ sys32_set_thread_area (struct ia32_user_desc __user *u_info)
2451#define GET_PRESENT(desc) (((desc)->b >> 15) & 1) 2470#define GET_PRESENT(desc) (((desc)->b >> 15) & 1)
2452#define GET_USEABLE(desc) (((desc)->b >> 20) & 1) 2471#define GET_USEABLE(desc) (((desc)->b >> 20) & 1)
2453 2472
2473static void fill_user_desc(struct ia32_user_desc *info, int idx,
2474 const struct desc_struct *desc)
2475{
2476 info->entry_number = idx;
2477 info->base_addr = GET_BASE(desc);
2478 info->limit = GET_LIMIT(desc);
2479 info->seg_32bit = GET_32BIT(desc);
2480 info->contents = GET_CONTENTS(desc);
2481 info->read_exec_only = !GET_WRITABLE(desc);
2482 info->limit_in_pages = GET_LIMIT_PAGES(desc);
2483 info->seg_not_present = !GET_PRESENT(desc);
2484 info->useable = GET_USEABLE(desc);
2485}
2486
2454asmlinkage int 2487asmlinkage int
2455sys32_get_thread_area (struct ia32_user_desc __user *u_info) 2488sys32_get_thread_area (struct ia32_user_desc __user *u_info)
2456{ 2489{
@@ -2464,22 +2497,588 @@ sys32_get_thread_area (struct ia32_user_desc __user *u_info)
2464 return -EINVAL; 2497 return -EINVAL;
2465 2498
2466 desc = current->thread.tls_array + idx - GDT_ENTRY_TLS_MIN; 2499 desc = current->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
2467 2500 fill_user_desc(&info, idx, desc);
2468 info.entry_number = idx;
2469 info.base_addr = GET_BASE(desc);
2470 info.limit = GET_LIMIT(desc);
2471 info.seg_32bit = GET_32BIT(desc);
2472 info.contents = GET_CONTENTS(desc);
2473 info.read_exec_only = !GET_WRITABLE(desc);
2474 info.limit_in_pages = GET_LIMIT_PAGES(desc);
2475 info.seg_not_present = !GET_PRESENT(desc);
2476 info.useable = GET_USEABLE(desc);
2477 2501
2478 if (copy_to_user(u_info, &info, sizeof(info))) 2502 if (copy_to_user(u_info, &info, sizeof(info)))
2479 return -EFAULT; 2503 return -EFAULT;
2480 return 0; 2504 return 0;
2481} 2505}
2482 2506
2507struct regset_get {
2508 void *kbuf;
2509 void __user *ubuf;
2510};
2511
2512struct regset_set {
2513 const void *kbuf;
2514 const void __user *ubuf;
2515};
2516
2517struct regset_getset {
2518 struct task_struct *target;
2519 const struct user_regset *regset;
2520 union {
2521 struct regset_get get;
2522 struct regset_set set;
2523 } u;
2524 unsigned int pos;
2525 unsigned int count;
2526 int ret;
2527};
2528
2529static void getfpreg(struct task_struct *task, int regno, int *val)
2530{
2531 switch (regno / sizeof(int)) {
2532 case 0:
2533 *val = task->thread.fcr & 0xffff;
2534 break;
2535 case 1:
2536 *val = task->thread.fsr & 0xffff;
2537 break;
2538 case 2:
2539 *val = (task->thread.fsr>>16) & 0xffff;
2540 break;
2541 case 3:
2542 *val = task->thread.fir;
2543 break;
2544 case 4:
2545 *val = (task->thread.fir>>32) & 0xffff;
2546 break;
2547 case 5:
2548 *val = task->thread.fdr;
2549 break;
2550 case 6:
2551 *val = (task->thread.fdr >> 32) & 0xffff;
2552 break;
2553 }
2554}
2555
2556static void setfpreg(struct task_struct *task, int regno, int val)
2557{
2558 switch (regno / sizeof(int)) {
2559 case 0:
2560 task->thread.fcr = (task->thread.fcr & (~0x1f3f))
2561 | (val & 0x1f3f);
2562 break;
2563 case 1:
2564 task->thread.fsr = (task->thread.fsr & (~0xffff)) | val;
2565 break;
2566 case 2:
2567 task->thread.fsr = (task->thread.fsr & (~0xffff0000))
2568 | (val << 16);
2569 break;
2570 case 3:
2571 task->thread.fir = (task->thread.fir & (~0xffffffff)) | val;
2572 break;
2573 case 5:
2574 task->thread.fdr = (task->thread.fdr & (~0xffffffff)) | val;
2575 break;
2576 }
2577}
2578
2579static void access_fpreg_ia32(int regno, void *reg,
2580 struct pt_regs *pt, struct switch_stack *sw,
2581 int tos, int write)
2582{
2583 void *f;
2584
2585 if ((regno += tos) >= 8)
2586 regno -= 8;
2587 if (regno < 4)
2588 f = &pt->f8 + regno;
2589 else if (regno <= 7)
2590 f = &sw->f12 + (regno - 4);
2591 else {
2592 printk(KERN_ERR "regno must be less than 7 \n");
2593 return;
2594 }
2595
2596 if (write)
2597 memcpy(f, reg, sizeof(struct _fpreg_ia32));
2598 else
2599 memcpy(reg, f, sizeof(struct _fpreg_ia32));
2600}
2601
2602static void do_fpregs_get(struct unw_frame_info *info, void *arg)
2603{
2604 struct regset_getset *dst = arg;
2605 struct task_struct *task = dst->target;
2606 struct pt_regs *pt;
2607 int start, end, tos;
2608 char buf[80];
2609
2610 if (dst->count == 0 || unw_unwind_to_user(info) < 0)
2611 return;
2612 if (dst->pos < 7 * sizeof(int)) {
2613 end = min((dst->pos + dst->count),
2614 (unsigned int)(7 * sizeof(int)));
2615 for (start = dst->pos; start < end; start += sizeof(int))
2616 getfpreg(task, start, (int *)(buf + start));
2617 dst->ret = user_regset_copyout(&dst->pos, &dst->count,
2618 &dst->u.get.kbuf, &dst->u.get.ubuf, buf,
2619 0, 7 * sizeof(int));
2620 if (dst->ret || dst->count == 0)
2621 return;
2622 }
2623 if (dst->pos < sizeof(struct ia32_user_i387_struct)) {
2624 pt = task_pt_regs(task);
2625 tos = (task->thread.fsr >> 11) & 7;
2626 end = min(dst->pos + dst->count,
2627 (unsigned int)(sizeof(struct ia32_user_i387_struct)));
2628 start = (dst->pos - 7 * sizeof(int)) /
2629 sizeof(struct _fpreg_ia32);
2630 end = (end - 7 * sizeof(int)) / sizeof(struct _fpreg_ia32);
2631 for (; start < end; start++)
2632 access_fpreg_ia32(start,
2633 (struct _fpreg_ia32 *)buf + start,
2634 pt, info->sw, tos, 0);
2635 dst->ret = user_regset_copyout(&dst->pos, &dst->count,
2636 &dst->u.get.kbuf, &dst->u.get.ubuf,
2637 buf, 7 * sizeof(int),
2638 sizeof(struct ia32_user_i387_struct));
2639 if (dst->ret || dst->count == 0)
2640 return;
2641 }
2642}
2643
2644static void do_fpregs_set(struct unw_frame_info *info, void *arg)
2645{
2646 struct regset_getset *dst = arg;
2647 struct task_struct *task = dst->target;
2648 struct pt_regs *pt;
2649 char buf[80];
2650 int end, start, tos;
2651
2652 if (dst->count == 0 || unw_unwind_to_user(info) < 0)
2653 return;
2654
2655 if (dst->pos < 7 * sizeof(int)) {
2656 start = dst->pos;
2657 dst->ret = user_regset_copyin(&dst->pos, &dst->count,
2658 &dst->u.set.kbuf, &dst->u.set.ubuf, buf,
2659 0, 7 * sizeof(int));
2660 if (dst->ret)
2661 return;
2662 for (; start < dst->pos; start += sizeof(int))
2663 setfpreg(task, start, *((int *)(buf + start)));
2664 if (dst->count == 0)
2665 return;
2666 }
2667 if (dst->pos < sizeof(struct ia32_user_i387_struct)) {
2668 start = (dst->pos - 7 * sizeof(int)) /
2669 sizeof(struct _fpreg_ia32);
2670 dst->ret = user_regset_copyin(&dst->pos, &dst->count,
2671 &dst->u.set.kbuf, &dst->u.set.ubuf,
2672 buf, 7 * sizeof(int),
2673 sizeof(struct ia32_user_i387_struct));
2674 if (dst->ret)
2675 return;
2676 pt = task_pt_regs(task);
2677 tos = (task->thread.fsr >> 11) & 7;
2678 end = (dst->pos - 7 * sizeof(int)) / sizeof(struct _fpreg_ia32);
2679 for (; start < end; start++)
2680 access_fpreg_ia32(start,
2681 (struct _fpreg_ia32 *)buf + start,
2682 pt, info->sw, tos, 1);
2683 if (dst->count == 0)
2684 return;
2685 }
2686}
2687
2688#define OFFSET(member) ((int)(offsetof(struct ia32_user_fxsr_struct, member)))
2689static void getfpxreg(struct task_struct *task, int start, int end, char *buf)
2690{
2691 int min_val;
2692
2693 min_val = min(end, OFFSET(fop));
2694 while (start < min_val) {
2695 if (start == OFFSET(cwd))
2696 *((short *)buf) = task->thread.fcr & 0xffff;
2697 else if (start == OFFSET(swd))
2698 *((short *)buf) = task->thread.fsr & 0xffff;
2699 else if (start == OFFSET(twd))
2700 *((short *)buf) = (task->thread.fsr>>16) & 0xffff;
2701 buf += 2;
2702 start += 2;
2703 }
2704 /* skip fop element */
2705 if (start == OFFSET(fop)) {
2706 start += 2;
2707 buf += 2;
2708 }
2709 while (start < end) {
2710 if (start == OFFSET(fip))
2711 *((int *)buf) = task->thread.fir;
2712 else if (start == OFFSET(fcs))
2713 *((int *)buf) = (task->thread.fir>>32) & 0xffff;
2714 else if (start == OFFSET(foo))
2715 *((int *)buf) = task->thread.fdr;
2716 else if (start == OFFSET(fos))
2717 *((int *)buf) = (task->thread.fdr>>32) & 0xffff;
2718 else if (start == OFFSET(mxcsr))
2719 *((int *)buf) = ((task->thread.fcr>>32) & 0xff80)
2720 | ((task->thread.fsr>>32) & 0x3f);
2721 buf += 4;
2722 start += 4;
2723 }
2724}
2725
2726static void setfpxreg(struct task_struct *task, int start, int end, char *buf)
2727{
2728 int min_val, num32;
2729 short num;
2730 unsigned long num64;
2731
2732 min_val = min(end, OFFSET(fop));
2733 while (start < min_val) {
2734 num = *((short *)buf);
2735 if (start == OFFSET(cwd)) {
2736 task->thread.fcr = (task->thread.fcr & (~0x1f3f))
2737 | (num & 0x1f3f);
2738 } else if (start == OFFSET(swd)) {
2739 task->thread.fsr = (task->thread.fsr & (~0xffff)) | num;
2740 } else if (start == OFFSET(twd)) {
2741 task->thread.fsr = (task->thread.fsr & (~0xffff0000))
2742 | (((int)num) << 16);
2743 }
2744 buf += 2;
2745 start += 2;
2746 }
2747 /* skip fop element */
2748 if (start == OFFSET(fop)) {
2749 start += 2;
2750 buf += 2;
2751 }
2752 while (start < end) {
2753 num32 = *((int *)buf);
2754 if (start == OFFSET(fip))
2755 task->thread.fir = (task->thread.fir & (~0xffffffff))
2756 | num32;
2757 else if (start == OFFSET(foo))
2758 task->thread.fdr = (task->thread.fdr & (~0xffffffff))
2759 | num32;
2760 else if (start == OFFSET(mxcsr)) {
2761 num64 = num32 & 0xff10;
2762 task->thread.fcr = (task->thread.fcr &
2763 (~0xff1000000000UL)) | (num64<<32);
2764 num64 = num32 & 0x3f;
2765 task->thread.fsr = (task->thread.fsr &
2766 (~0x3f00000000UL)) | (num64<<32);
2767 }
2768 buf += 4;
2769 start += 4;
2770 }
2771}
2772
2773static void do_fpxregs_get(struct unw_frame_info *info, void *arg)
2774{
2775 struct regset_getset *dst = arg;
2776 struct task_struct *task = dst->target;
2777 struct pt_regs *pt;
2778 char buf[128];
2779 int start, end, tos;
2780
2781 if (dst->count == 0 || unw_unwind_to_user(info) < 0)
2782 return;
2783 if (dst->pos < OFFSET(st_space[0])) {
2784 end = min(dst->pos + dst->count, (unsigned int)32);
2785 getfpxreg(task, dst->pos, end, buf);
2786 dst->ret = user_regset_copyout(&dst->pos, &dst->count,
2787 &dst->u.get.kbuf, &dst->u.get.ubuf, buf,
2788 0, OFFSET(st_space[0]));
2789 if (dst->ret || dst->count == 0)
2790 return;
2791 }
2792 if (dst->pos < OFFSET(xmm_space[0])) {
2793 pt = task_pt_regs(task);
2794 tos = (task->thread.fsr >> 11) & 7;
2795 end = min(dst->pos + dst->count,
2796 (unsigned int)OFFSET(xmm_space[0]));
2797 start = (dst->pos - OFFSET(st_space[0])) / 16;
2798 end = (end - OFFSET(st_space[0])) / 16;
2799 for (; start < end; start++)
2800 access_fpreg_ia32(start, buf + 16 * start, pt,
2801 info->sw, tos, 0);
2802 dst->ret = user_regset_copyout(&dst->pos, &dst->count,
2803 &dst->u.get.kbuf, &dst->u.get.ubuf,
2804 buf, OFFSET(st_space[0]), OFFSET(xmm_space[0]));
2805 if (dst->ret || dst->count == 0)
2806 return;
2807 }
2808 if (dst->pos < OFFSET(padding[0]))
2809 dst->ret = user_regset_copyout(&dst->pos, &dst->count,
2810 &dst->u.get.kbuf, &dst->u.get.ubuf,
2811 &info->sw->f16, OFFSET(xmm_space[0]),
2812 OFFSET(padding[0]));
2813}
2814
2815static void do_fpxregs_set(struct unw_frame_info *info, void *arg)
2816{
2817 struct regset_getset *dst = arg;
2818 struct task_struct *task = dst->target;
2819 char buf[128];
2820 int start, end;
2821
2822 if (dst->count == 0 || unw_unwind_to_user(info) < 0)
2823 return;
2824
2825 if (dst->pos < OFFSET(st_space[0])) {
2826 start = dst->pos;
2827 dst->ret = user_regset_copyin(&dst->pos, &dst->count,
2828 &dst->u.set.kbuf, &dst->u.set.ubuf,
2829 buf, 0, OFFSET(st_space[0]));
2830 if (dst->ret)
2831 return;
2832 setfpxreg(task, start, dst->pos, buf);
2833 if (dst->count == 0)
2834 return;
2835 }
2836 if (dst->pos < OFFSET(xmm_space[0])) {
2837 struct pt_regs *pt;
2838 int tos;
2839 pt = task_pt_regs(task);
2840 tos = (task->thread.fsr >> 11) & 7;
2841 start = (dst->pos - OFFSET(st_space[0])) / 16;
2842 dst->ret = user_regset_copyin(&dst->pos, &dst->count,
2843 &dst->u.set.kbuf, &dst->u.set.ubuf,
2844 buf, OFFSET(st_space[0]), OFFSET(xmm_space[0]));
2845 if (dst->ret)
2846 return;
2847 end = (dst->pos - OFFSET(st_space[0])) / 16;
2848 for (; start < end; start++)
2849 access_fpreg_ia32(start, buf + 16 * start, pt, info->sw,
2850 tos, 1);
2851 if (dst->count == 0)
2852 return;
2853 }
2854 if (dst->pos < OFFSET(padding[0]))
2855 dst->ret = user_regset_copyin(&dst->pos, &dst->count,
2856 &dst->u.set.kbuf, &dst->u.set.ubuf,
2857 &info->sw->f16, OFFSET(xmm_space[0]),
2858 OFFSET(padding[0]));
2859}
2860#undef OFFSET
2861
2862static int do_regset_call(void (*call)(struct unw_frame_info *, void *),
2863 struct task_struct *target,
2864 const struct user_regset *regset,
2865 unsigned int pos, unsigned int count,
2866 const void *kbuf, const void __user *ubuf)
2867{
2868 struct regset_getset info = { .target = target, .regset = regset,
2869 .pos = pos, .count = count,
2870 .u.set = { .kbuf = kbuf, .ubuf = ubuf },
2871 .ret = 0 };
2872
2873 if (target == current)
2874 unw_init_running(call, &info);
2875 else {
2876 struct unw_frame_info ufi;
2877 memset(&ufi, 0, sizeof(ufi));
2878 unw_init_from_blocked_task(&ufi, target);
2879 (*call)(&ufi, &info);
2880 }
2881
2882 return info.ret;
2883}
2884
2885static int ia32_fpregs_get(struct task_struct *target,
2886 const struct user_regset *regset,
2887 unsigned int pos, unsigned int count,
2888 void *kbuf, void __user *ubuf)
2889{
2890 return do_regset_call(do_fpregs_get, target, regset, pos, count,
2891 kbuf, ubuf);
2892}
2893
2894static int ia32_fpregs_set(struct task_struct *target,
2895 const struct user_regset *regset,
2896 unsigned int pos, unsigned int count,
2897 const void *kbuf, const void __user *ubuf)
2898{
2899 return do_regset_call(do_fpregs_set, target, regset, pos, count,
2900 kbuf, ubuf);
2901}
2902
2903static int ia32_fpxregs_get(struct task_struct *target,
2904 const struct user_regset *regset,
2905 unsigned int pos, unsigned int count,
2906 void *kbuf, void __user *ubuf)
2907{
2908 return do_regset_call(do_fpxregs_get, target, regset, pos, count,
2909 kbuf, ubuf);
2910}
2911
2912static int ia32_fpxregs_set(struct task_struct *target,
2913 const struct user_regset *regset,
2914 unsigned int pos, unsigned int count,
2915 const void *kbuf, const void __user *ubuf)
2916{
2917 return do_regset_call(do_fpxregs_set, target, regset, pos, count,
2918 kbuf, ubuf);
2919}
2920
2921static int ia32_genregs_get(struct task_struct *target,
2922 const struct user_regset *regset,
2923 unsigned int pos, unsigned int count,
2924 void *kbuf, void __user *ubuf)
2925{
2926 if (kbuf) {
2927 u32 *kp = kbuf;
2928 while (count > 0) {
2929 *kp++ = getreg(target, pos);
2930 pos += 4;
2931 count -= 4;
2932 }
2933 } else {
2934 u32 __user *up = ubuf;
2935 while (count > 0) {
2936 if (__put_user(getreg(target, pos), up++))
2937 return -EFAULT;
2938 pos += 4;
2939 count -= 4;
2940 }
2941 }
2942 return 0;
2943}
2944
2945static int ia32_genregs_set(struct task_struct *target,
2946 const struct user_regset *regset,
2947 unsigned int pos, unsigned int count,
2948 const void *kbuf, const void __user *ubuf)
2949{
2950 int ret = 0;
2951
2952 if (kbuf) {
2953 const u32 *kp = kbuf;
2954 while (!ret && count > 0) {
2955 putreg(target, pos, *kp++);
2956 pos += 4;
2957 count -= 4;
2958 }
2959 } else {
2960 const u32 __user *up = ubuf;
2961 u32 val;
2962 while (!ret && count > 0) {
2963 ret = __get_user(val, up++);
2964 if (!ret)
2965 putreg(target, pos, val);
2966 pos += 4;
2967 count -= 4;
2968 }
2969 }
2970 return ret;
2971}
2972
2973static int ia32_tls_active(struct task_struct *target,
2974 const struct user_regset *regset)
2975{
2976 struct thread_struct *t = &target->thread;
2977 int n = GDT_ENTRY_TLS_ENTRIES;
2978 while (n > 0 && desc_empty(&t->tls_array[n -1]))
2979 --n;
2980 return n;
2981}
2982
2983static int ia32_tls_get(struct task_struct *target,
2984 const struct user_regset *regset, unsigned int pos,
2985 unsigned int count, void *kbuf, void __user *ubuf)
2986{
2987 const struct desc_struct *tls;
2988
2989 if (pos > GDT_ENTRY_TLS_ENTRIES * sizeof(struct ia32_user_desc) ||
2990 (pos % sizeof(struct ia32_user_desc)) != 0 ||
2991 (count % sizeof(struct ia32_user_desc)) != 0)
2992 return -EINVAL;
2993
2994 pos /= sizeof(struct ia32_user_desc);
2995 count /= sizeof(struct ia32_user_desc);
2996
2997 tls = &target->thread.tls_array[pos];
2998
2999 if (kbuf) {
3000 struct ia32_user_desc *info = kbuf;
3001 while (count-- > 0)
3002 fill_user_desc(info++, GDT_ENTRY_TLS_MIN + pos++,
3003 tls++);
3004 } else {
3005 struct ia32_user_desc __user *u_info = ubuf;
3006 while (count-- > 0) {
3007 struct ia32_user_desc info;
3008 fill_user_desc(&info, GDT_ENTRY_TLS_MIN + pos++, tls++);
3009 if (__copy_to_user(u_info++, &info, sizeof(info)))
3010 return -EFAULT;
3011 }
3012 }
3013
3014 return 0;
3015}
3016
3017static int ia32_tls_set(struct task_struct *target,
3018 const struct user_regset *regset, unsigned int pos,
3019 unsigned int count, const void *kbuf, const void __user *ubuf)
3020{
3021 struct ia32_user_desc infobuf[GDT_ENTRY_TLS_ENTRIES];
3022 const struct ia32_user_desc *info;
3023
3024 if (pos > GDT_ENTRY_TLS_ENTRIES * sizeof(struct ia32_user_desc) ||
3025 (pos % sizeof(struct ia32_user_desc)) != 0 ||
3026 (count % sizeof(struct ia32_user_desc)) != 0)
3027 return -EINVAL;
3028
3029 if (kbuf)
3030 info = kbuf;
3031 else if (__copy_from_user(infobuf, ubuf, count))
3032 return -EFAULT;
3033 else
3034 info = infobuf;
3035
3036 set_tls_desc(target,
3037 GDT_ENTRY_TLS_MIN + (pos / sizeof(struct ia32_user_desc)),
3038 info, count / sizeof(struct ia32_user_desc));
3039
3040 return 0;
3041}
3042
3043/*
3044 * This should match arch/i386/kernel/ptrace.c:native_regsets.
3045 * XXX ioperm? vm86?
3046 */
3047static const struct user_regset ia32_regsets[] = {
3048 {
3049 .core_note_type = NT_PRSTATUS,
3050 .n = sizeof(struct user_regs_struct32)/4,
3051 .size = 4, .align = 4,
3052 .get = ia32_genregs_get, .set = ia32_genregs_set
3053 },
3054 {
3055 .core_note_type = NT_PRFPREG,
3056 .n = sizeof(struct ia32_user_i387_struct) / 4,
3057 .size = 4, .align = 4,
3058 .get = ia32_fpregs_get, .set = ia32_fpregs_set
3059 },
3060 {
3061 .core_note_type = NT_PRXFPREG,
3062 .n = sizeof(struct ia32_user_fxsr_struct) / 4,
3063 .size = 4, .align = 4,
3064 .get = ia32_fpxregs_get, .set = ia32_fpxregs_set
3065 },
3066 {
3067 .core_note_type = NT_386_TLS,
3068 .n = GDT_ENTRY_TLS_ENTRIES,
3069 .bias = GDT_ENTRY_TLS_MIN,
3070 .size = sizeof(struct ia32_user_desc),
3071 .align = sizeof(struct ia32_user_desc),
3072 .active = ia32_tls_active,
3073 .get = ia32_tls_get, .set = ia32_tls_set,
3074 },
3075};
3076
3077const struct user_regset_view user_ia32_view = {
3078 .name = "i386", .e_machine = EM_386,
3079 .regsets = ia32_regsets, .n = ARRAY_SIZE(ia32_regsets)
3080};
3081
2483long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, 3082long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high,
2484 __u32 len_low, __u32 len_high, int advice) 3083 __u32 len_low, __u32 len_high, int advice)
2485{ 3084{
diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
index 0aebc6f79e95..5865130b0a92 100644
--- a/arch/ia64/kernel/asm-offsets.c
+++ b/arch/ia64/kernel/asm-offsets.c
@@ -39,6 +39,12 @@ void foo(void)
39 DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); 39 DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
40 DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); 40 DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
41 DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); 41 DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
42#ifdef CONFIG_VIRT_CPU_ACCOUNTING
43 DEFINE(TI_AC_STAMP, offsetof(struct thread_info, ac_stamp));
44 DEFINE(TI_AC_LEAVE, offsetof(struct thread_info, ac_leave));
45 DEFINE(TI_AC_STIME, offsetof(struct thread_info, ac_stime));
46 DEFINE(TI_AC_UTIME, offsetof(struct thread_info, ac_utime));
47#endif
42 48
43 BLANK(); 49 BLANK();
44 50
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 3c331c464b40..b0be4a280174 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -710,6 +710,16 @@ ENTRY(ia64_leave_syscall)
710(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk 710(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
711#endif 711#endif
712.work_processed_syscall: 712.work_processed_syscall:
713#ifdef CONFIG_VIRT_CPU_ACCOUNTING
714 adds r2=PT(LOADRS)+16,r12
715(pUStk) mov.m r22=ar.itc // fetch time at leave
716 adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
717 ;;
718(p6) ld4 r31=[r18] // load current_thread_info()->flags
719 ld8 r19=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs"
720 adds r3=PT(AR_BSPSTORE)+16,r12 // deferred
721 ;;
722#else
713 adds r2=PT(LOADRS)+16,r12 723 adds r2=PT(LOADRS)+16,r12
714 adds r3=PT(AR_BSPSTORE)+16,r12 724 adds r3=PT(AR_BSPSTORE)+16,r12
715 adds r18=TI_FLAGS+IA64_TASK_SIZE,r13 725 adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
@@ -718,6 +728,7 @@ ENTRY(ia64_leave_syscall)
718 ld8 r19=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs" 728 ld8 r19=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs"
719 nop.i 0 729 nop.i 0
720 ;; 730 ;;
731#endif
721 mov r16=ar.bsp // M2 get existing backing store pointer 732 mov r16=ar.bsp // M2 get existing backing store pointer
722 ld8 r18=[r2],PT(R9)-PT(B6) // load b6 733 ld8 r18=[r2],PT(R9)-PT(B6) // load b6
723(p6) and r15=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE? 734(p6) and r15=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE?
@@ -737,12 +748,21 @@ ENTRY(ia64_leave_syscall)
737 748
738 ld8 r29=[r2],16 // M0|1 load cr.ipsr 749 ld8 r29=[r2],16 // M0|1 load cr.ipsr
739 ld8 r28=[r3],16 // M0|1 load cr.iip 750 ld8 r28=[r3],16 // M0|1 load cr.iip
751#ifdef CONFIG_VIRT_CPU_ACCOUNTING
752(pUStk) add r14=TI_AC_LEAVE+IA64_TASK_SIZE,r13
753 ;;
754 ld8 r30=[r2],16 // M0|1 load cr.ifs
755 ld8 r25=[r3],16 // M0|1 load ar.unat
756(pUStk) add r15=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
757 ;;
758#else
740 mov r22=r0 // A clear r22 759 mov r22=r0 // A clear r22
741 ;; 760 ;;
742 ld8 r30=[r2],16 // M0|1 load cr.ifs 761 ld8 r30=[r2],16 // M0|1 load cr.ifs
743 ld8 r25=[r3],16 // M0|1 load ar.unat 762 ld8 r25=[r3],16 // M0|1 load ar.unat
744(pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13 763(pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
745 ;; 764 ;;
765#endif
746 ld8 r26=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs 766 ld8 r26=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs
747(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled 767(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled
748 nop 0 768 nop 0
@@ -759,7 +779,11 @@ ENTRY(ia64_leave_syscall)
759 ld8.fill r1=[r3],16 // M0|1 load r1 779 ld8.fill r1=[r3],16 // M0|1 load r1
760(pUStk) mov r17=1 // A 780(pUStk) mov r17=1 // A
761 ;; 781 ;;
782#ifdef CONFIG_VIRT_CPU_ACCOUNTING
783(pUStk) st1 [r15]=r17 // M2|3
784#else
762(pUStk) st1 [r14]=r17 // M2|3 785(pUStk) st1 [r14]=r17 // M2|3
786#endif
763 ld8.fill r13=[r3],16 // M0|1 787 ld8.fill r13=[r3],16 // M0|1
764 mov f8=f0 // F clear f8 788 mov f8=f0 // F clear f8
765 ;; 789 ;;
@@ -775,12 +799,22 @@ ENTRY(ia64_leave_syscall)
775 shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition 799 shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition
776 cover // B add current frame into dirty partition & set cr.ifs 800 cover // B add current frame into dirty partition & set cr.ifs
777 ;; 801 ;;
802#ifdef CONFIG_VIRT_CPU_ACCOUNTING
803 mov r19=ar.bsp // M2 get new backing store pointer
804 st8 [r14]=r22 // M save time at leave
805 mov f10=f0 // F clear f10
806
807 mov r22=r0 // A clear r22
808 movl r14=__kernel_syscall_via_epc // X
809 ;;
810#else
778 mov r19=ar.bsp // M2 get new backing store pointer 811 mov r19=ar.bsp // M2 get new backing store pointer
779 mov f10=f0 // F clear f10 812 mov f10=f0 // F clear f10
780 813
781 nop.m 0 814 nop.m 0
782 movl r14=__kernel_syscall_via_epc // X 815 movl r14=__kernel_syscall_via_epc // X
783 ;; 816 ;;
817#endif
784 mov.m ar.csd=r0 // M2 clear ar.csd 818 mov.m ar.csd=r0 // M2 clear ar.csd
785 mov.m ar.ccv=r0 // M2 clear ar.ccv 819 mov.m ar.ccv=r0 // M2 clear ar.ccv
786 mov b7=r14 // I0 clear b7 (hint with __kernel_syscall_via_epc) 820 mov b7=r14 // I0 clear b7 (hint with __kernel_syscall_via_epc)
@@ -913,10 +947,18 @@ GLOBAL_ENTRY(ia64_leave_kernel)
913 adds r16=PT(CR_IPSR)+16,r12 947 adds r16=PT(CR_IPSR)+16,r12
914 adds r17=PT(CR_IIP)+16,r12 948 adds r17=PT(CR_IIP)+16,r12
915 949
950#ifdef CONFIG_VIRT_CPU_ACCOUNTING
951 .pred.rel.mutex pUStk,pKStk
952(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled
953(pUStk) mov.m r22=ar.itc // M fetch time at leave
954 nop.i 0
955 ;;
956#else
916(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled 957(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled
917 nop.i 0 958 nop.i 0
918 nop.i 0 959 nop.i 0
919 ;; 960 ;;
961#endif
920 ld8 r29=[r16],16 // load cr.ipsr 962 ld8 r29=[r16],16 // load cr.ipsr
921 ld8 r28=[r17],16 // load cr.iip 963 ld8 r28=[r17],16 // load cr.iip
922 ;; 964 ;;
@@ -938,15 +980,37 @@ GLOBAL_ENTRY(ia64_leave_kernel)
938 ;; 980 ;;
939 ld8.fill r12=[r16],16 981 ld8.fill r12=[r16],16
940 ld8.fill r13=[r17],16 982 ld8.fill r13=[r17],16
983#ifdef CONFIG_VIRT_CPU_ACCOUNTING
984(pUStk) adds r3=TI_AC_LEAVE+IA64_TASK_SIZE,r18
985#else
941(pUStk) adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18 986(pUStk) adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18
987#endif
942 ;; 988 ;;
943 ld8 r20=[r16],16 // ar.fpsr 989 ld8 r20=[r16],16 // ar.fpsr
944 ld8.fill r15=[r17],16 990 ld8.fill r15=[r17],16
991#ifdef CONFIG_VIRT_CPU_ACCOUNTING
992(pUStk) adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18 // deferred
993#endif
945 ;; 994 ;;
946 ld8.fill r14=[r16],16 995 ld8.fill r14=[r16],16
947 ld8.fill r2=[r17] 996 ld8.fill r2=[r17]
948(pUStk) mov r17=1 997(pUStk) mov r17=1
949 ;; 998 ;;
999#ifdef CONFIG_VIRT_CPU_ACCOUNTING
1000 // mmi_ : ld8 st1 shr;; mmi_ : st8 st1 shr;;
1001 // mib : mov add br -> mib : ld8 add br
1002 // bbb_ : br nop cover;; mbb_ : mov br cover;;
1003 //
1004 // no one require bsp in r16 if (pKStk) branch is selected.
1005(pUStk) st8 [r3]=r22 // save time at leave
1006(pUStk) st1 [r18]=r17 // restore current->thread.on_ustack
1007 shr.u r18=r19,16 // get byte size of existing "dirty" partition
1008 ;;
1009 ld8.fill r3=[r16] // deferred
1010 LOAD_PHYS_STACK_REG_SIZE(r17)
1011(pKStk) br.cond.dpnt skip_rbs_switch
1012 mov r16=ar.bsp // get existing backing store pointer
1013#else
950 ld8.fill r3=[r16] 1014 ld8.fill r3=[r16]
951(pUStk) st1 [r18]=r17 // restore current->thread.on_ustack 1015(pUStk) st1 [r18]=r17 // restore current->thread.on_ustack
952 shr.u r18=r19,16 // get byte size of existing "dirty" partition 1016 shr.u r18=r19,16 // get byte size of existing "dirty" partition
@@ -954,6 +1018,7 @@ GLOBAL_ENTRY(ia64_leave_kernel)
954 mov r16=ar.bsp // get existing backing store pointer 1018 mov r16=ar.bsp // get existing backing store pointer
955 LOAD_PHYS_STACK_REG_SIZE(r17) 1019 LOAD_PHYS_STACK_REG_SIZE(r17)
956(pKStk) br.cond.dpnt skip_rbs_switch 1020(pKStk) br.cond.dpnt skip_rbs_switch
1021#endif
957 1022
958 /* 1023 /*
959 * Restore user backing store. 1024 * Restore user backing store.
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
index 44841971f077..357b7e2adc63 100644
--- a/arch/ia64/kernel/fsys.S
+++ b/arch/ia64/kernel/fsys.S
@@ -210,27 +210,25 @@ ENTRY(fsys_gettimeofday)
210 // Note that instructions are optimized for McKinley. McKinley can 210 // Note that instructions are optimized for McKinley. McKinley can
211 // process two bundles simultaneously and therefore we continuously 211 // process two bundles simultaneously and therefore we continuously
212 // try to feed the CPU two bundles and then a stop. 212 // try to feed the CPU two bundles and then a stop.
213 // 213
214 // Additional note that code has changed a lot. Optimization is TBD.
215 // Comments begin with "?" are maybe outdated.
216 tnat.nz p6,p0 = r31 // ? branch deferred to fit later bundle
217 mov pr = r30,0xc000 // Set predicates according to function
218 add r2 = TI_FLAGS+IA64_TASK_SIZE,r16 214 add r2 = TI_FLAGS+IA64_TASK_SIZE,r16
215 tnat.nz p6,p0 = r31 // guard against Nat argument
216(p6) br.cond.spnt.few .fail_einval
219 movl r20 = fsyscall_gtod_data // load fsyscall gettimeofday data address 217 movl r20 = fsyscall_gtod_data // load fsyscall gettimeofday data address
220 ;; 218 ;;
219 ld4 r2 = [r2] // process work pending flags
221 movl r29 = itc_jitter_data // itc_jitter 220 movl r29 = itc_jitter_data // itc_jitter
222 add r22 = IA64_GTOD_WALL_TIME_OFFSET,r20 // wall_time 221 add r22 = IA64_GTOD_WALL_TIME_OFFSET,r20 // wall_time
223 ld4 r2 = [r2] // process work pending flags
224 ;;
225(p15) add r22 = IA64_GTOD_MONO_TIME_OFFSET,r20 // monotonic_time
226 add r21 = IA64_CLKSRC_MMIO_OFFSET,r20 222 add r21 = IA64_CLKSRC_MMIO_OFFSET,r20
227 add r19 = IA64_ITC_LASTCYCLE_OFFSET,r29 223 mov pr = r30,0xc000 // Set predicates according to function
224 ;;
228 and r2 = TIF_ALLWORK_MASK,r2 225 and r2 = TIF_ALLWORK_MASK,r2
229(p6) br.cond.spnt.few .fail_einval // ? deferred branch 226 add r19 = IA64_ITC_LASTCYCLE_OFFSET,r29
227(p15) add r22 = IA64_GTOD_MONO_TIME_OFFSET,r20 // monotonic_time
230 ;; 228 ;;
231 add r26 = IA64_CLKSRC_CYCLE_LAST_OFFSET,r20 // clksrc_cycle_last 229 add r26 = IA64_CLKSRC_CYCLE_LAST_OFFSET,r20 // clksrc_cycle_last
232 cmp.ne p6, p0 = 0, r2 // Fallback if work is scheduled 230 cmp.ne p6, p0 = 0, r2 // Fallback if work is scheduled
233(p6) br.cond.spnt.many fsys_fallback_syscall 231(p6) br.cond.spnt.many fsys_fallback_syscall
234 ;; 232 ;;
235 // Begin critical section 233 // Begin critical section
236.time_redo: 234.time_redo:
@@ -258,7 +256,6 @@ ENTRY(fsys_gettimeofday)
258(p8) mov r2 = ar.itc // CPU_TIMER. 36 clocks latency!!! 256(p8) mov r2 = ar.itc // CPU_TIMER. 36 clocks latency!!!
259(p9) ld8 r2 = [r30] // MMIO_TIMER. Could also have latency issues.. 257(p9) ld8 r2 = [r30] // MMIO_TIMER. Could also have latency issues..
260(p13) ld8 r25 = [r19] // get itc_lastcycle value 258(p13) ld8 r25 = [r19] // get itc_lastcycle value
261 ;; // ? could be removed by moving the last add upward
262 ld8 r9 = [r22],IA64_TIMESPEC_TV_NSEC_OFFSET // tv_sec 259 ld8 r9 = [r22],IA64_TIMESPEC_TV_NSEC_OFFSET // tv_sec
263 ;; 260 ;;
264 ld8 r8 = [r22],-IA64_TIMESPEC_TV_NSEC_OFFSET // tv_nsec 261 ld8 r8 = [r22],-IA64_TIMESPEC_TV_NSEC_OFFSET // tv_nsec
@@ -285,13 +282,12 @@ ENTRY(fsys_gettimeofday)
285EX(.fail_efault, probe.w.fault r31, 3) 282EX(.fail_efault, probe.w.fault r31, 3)
286 xmpy.l f8 = f8,f7 // nsec_per_cyc*(counter-last_counter) 283 xmpy.l f8 = f8,f7 // nsec_per_cyc*(counter-last_counter)
287 ;; 284 ;;
288 // ? simulate tbit.nz.or p7,p0 = r28,0
289 getf.sig r2 = f8 285 getf.sig r2 = f8
290 mf 286 mf
291 ;; 287 ;;
292 ld4 r10 = [r20] // gtod_lock.sequence 288 ld4 r10 = [r20] // gtod_lock.sequence
293 shr.u r2 = r2,r23 // shift by factor 289 shr.u r2 = r2,r23 // shift by factor
294 ;; // ? overloaded 3 bundles! 290 ;;
295 add r8 = r8,r2 // Add xtime.nsecs 291 add r8 = r8,r2 // Add xtime.nsecs
296 cmp4.ne p7,p0 = r28,r10 292 cmp4.ne p7,p0 = r28,r10
297(p7) br.cond.dpnt.few .time_redo // sequence number changed, redo 293(p7) br.cond.dpnt.few .time_redo // sequence number changed, redo
@@ -319,9 +315,9 @@ EX(.fail_efault, probe.w.fault r31, 3)
319EX(.fail_efault, probe.w.fault r23, 3) // This also costs 5 cycles 315EX(.fail_efault, probe.w.fault r23, 3) // This also costs 5 cycles
320(p14) xmpy.hu f8 = f8, f7 // xmpy has 5 cycles latency so use it 316(p14) xmpy.hu f8 = f8, f7 // xmpy has 5 cycles latency so use it
321 ;; 317 ;;
322 mov r8 = r0
323(p14) getf.sig r2 = f8 318(p14) getf.sig r2 = f8
324 ;; 319 ;;
320 mov r8 = r0
325(p14) shr.u r21 = r2, 4 321(p14) shr.u r21 = r2, 4
326 ;; 322 ;;
327EX(.fail_efault, st8 [r31] = r9) 323EX(.fail_efault, st8 [r31] = r9)
@@ -660,7 +656,11 @@ GLOBAL_ENTRY(fsys_bubble_down)
660 nop.i 0 656 nop.i 0
661 ;; 657 ;;
662 mov ar.rsc=0 // M2 set enforced lazy mode, pl 0, LE, loadrs=0 658 mov ar.rsc=0 // M2 set enforced lazy mode, pl 0, LE, loadrs=0
659#ifdef CONFIG_VIRT_CPU_ACCOUNTING
660 mov.m r30=ar.itc // M get cycle for accounting
661#else
663 nop.m 0 662 nop.m 0
663#endif
664 nop.i 0 664 nop.i 0
665 ;; 665 ;;
666 mov r23=ar.bspstore // M2 (12 cyc) save ar.bspstore 666 mov r23=ar.bspstore // M2 (12 cyc) save ar.bspstore
@@ -682,6 +682,28 @@ GLOBAL_ENTRY(fsys_bubble_down)
682 cmp.ne pKStk,pUStk=r0,r0 // A set pKStk <- 0, pUStk <- 1 682 cmp.ne pKStk,pUStk=r0,r0 // A set pKStk <- 0, pUStk <- 1
683 br.call.sptk.many b7=ia64_syscall_setup // B 683 br.call.sptk.many b7=ia64_syscall_setup // B
684 ;; 684 ;;
685#ifdef CONFIG_VIRT_CPU_ACCOUNTING
686 // mov.m r30=ar.itc is called in advance
687 add r16=TI_AC_STAMP+IA64_TASK_SIZE,r2
688 add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r2
689 ;;
690 ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP // time at last check in kernel
691 ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE // time at leave kernel
692 ;;
693 ld8 r20=[r16],TI_AC_STAMP-TI_AC_STIME // cumulated stime
694 ld8 r21=[r17] // cumulated utime
695 sub r22=r19,r18 // stime before leave kernel
696 ;;
697 st8 [r16]=r30,TI_AC_STIME-TI_AC_STAMP // update stamp
698 sub r18=r30,r19 // elapsed time in user mode
699 ;;
700 add r20=r20,r22 // sum stime
701 add r21=r21,r18 // sum utime
702 ;;
703 st8 [r16]=r20 // update stime
704 st8 [r17]=r21 // update utime
705 ;;
706#endif
685 mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0 707 mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0
686 mov rp=r14 // I0 set the real return addr 708 mov rp=r14 // I0 set the real return addr
687 and r3=_TIF_SYSCALL_TRACEAUDIT,r3 // A 709 and r3=_TIF_SYSCALL_TRACEAUDIT,r3 // A
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index d3a41d5f8d12..ddeab4e36fd5 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -1002,6 +1002,26 @@ GLOBAL_ENTRY(sched_clock)
1002 br.ret.sptk.many rp 1002 br.ret.sptk.many rp
1003END(sched_clock) 1003END(sched_clock)
1004 1004
1005#ifdef CONFIG_VIRT_CPU_ACCOUNTING
1006GLOBAL_ENTRY(cycle_to_cputime)
1007 alloc r16=ar.pfs,1,0,0,0
1008 addl r8=THIS_CPU(cpu_info) + IA64_CPUINFO_NSEC_PER_CYC_OFFSET,r0
1009 ;;
1010 ldf8 f8=[r8]
1011 ;;
1012 setf.sig f9=r32
1013 ;;
1014 xmpy.lu f10=f9,f8 // calculate low 64 bits of 128-bit product (4 cyc)
1015 xmpy.hu f11=f9,f8 // calculate high 64 bits of 128-bit product
1016 ;;
1017 getf.sig r8=f10 // (5 cyc)
1018 getf.sig r9=f11
1019 ;;
1020 shrp r8=r9,r8,IA64_NSEC_PER_CYC_SHIFT
1021 br.ret.sptk.many rp
1022END(cycle_to_cputime)
1023#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
1024
1005GLOBAL_ENTRY(start_kernel_thread) 1025GLOBAL_ENTRY(start_kernel_thread)
1006 .prologue 1026 .prologue
1007 .save rp, r0 // this is the end of the call-chain 1027 .save rp, r0 // this is the end of the call-chain
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
index 34f44d8be00d..6678c49daba3 100644
--- a/arch/ia64/kernel/ivt.S
+++ b/arch/ia64/kernel/ivt.S
@@ -805,8 +805,13 @@ ENTRY(break_fault)
805 805
806(p8) adds r28=16,r28 // A switch cr.iip to next bundle 806(p8) adds r28=16,r28 // A switch cr.iip to next bundle
807(p9) adds r8=1,r8 // A increment ei to next slot 807(p9) adds r8=1,r8 // A increment ei to next slot
808#ifdef CONFIG_VIRT_CPU_ACCOUNTING
809 ;;
810 mov b6=r30 // I0 setup syscall handler branch reg early
811#else
808 nop.i 0 812 nop.i 0
809 ;; 813 ;;
814#endif
810 815
811 mov.m r25=ar.unat // M2 (5 cyc) 816 mov.m r25=ar.unat // M2 (5 cyc)
812 dep r29=r8,r29,41,2 // I0 insert new ei into cr.ipsr 817 dep r29=r8,r29,41,2 // I0 insert new ei into cr.ipsr
@@ -817,7 +822,11 @@ ENTRY(break_fault)
817 // 822 //
818/////////////////////////////////////////////////////////////////////// 823///////////////////////////////////////////////////////////////////////
819 st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag 824 st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag
825#ifdef CONFIG_VIRT_CPU_ACCOUNTING
826 mov.m r30=ar.itc // M get cycle for accounting
827#else
820 mov b6=r30 // I0 setup syscall handler branch reg early 828 mov b6=r30 // I0 setup syscall handler branch reg early
829#endif
821 cmp.eq pKStk,pUStk=r0,r17 // A were we on kernel stacks already? 830 cmp.eq pKStk,pUStk=r0,r17 // A were we on kernel stacks already?
822 831
823 and r9=_TIF_SYSCALL_TRACEAUDIT,r9 // A mask trace or audit 832 and r9=_TIF_SYSCALL_TRACEAUDIT,r9 // A mask trace or audit
@@ -829,6 +838,30 @@ ENTRY(break_fault)
829 cmp.eq p14,p0=r9,r0 // A are syscalls being traced/audited? 838 cmp.eq p14,p0=r9,r0 // A are syscalls being traced/audited?
830 br.call.sptk.many b7=ia64_syscall_setup // B 839 br.call.sptk.many b7=ia64_syscall_setup // B
8311: 8401:
841#ifdef CONFIG_VIRT_CPU_ACCOUNTING
842 // mov.m r30=ar.itc is called in advance, and r13 is current
843 add r16=TI_AC_STAMP+IA64_TASK_SIZE,r13 // A
844 add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r13 // A
845(pKStk) br.cond.spnt .skip_accounting // B unlikely skip
846 ;;
847 ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP // M get last stamp
848 ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE // M time at leave
849 ;;
850 ld8 r20=[r16],TI_AC_STAMP-TI_AC_STIME // M cumulated stime
851 ld8 r21=[r17] // M cumulated utime
852 sub r22=r19,r18 // A stime before leave
853 ;;
854 st8 [r16]=r30,TI_AC_STIME-TI_AC_STAMP // M update stamp
855 sub r18=r30,r19 // A elapsed time in user
856 ;;
857 add r20=r20,r22 // A sum stime
858 add r21=r21,r18 // A sum utime
859 ;;
860 st8 [r16]=r20 // M update stime
861 st8 [r17]=r21 // M update utime
862 ;;
863.skip_accounting:
864#endif
832 mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0 865 mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0
833 nop 0 866 nop 0
834 bsw.1 // B (6 cyc) regs are saved, switch to bank 1 867 bsw.1 // B (6 cyc) regs are saved, switch to bank 1
@@ -928,6 +961,7 @@ END(interrupt)
928 * - r27: saved ar.rsc 961 * - r27: saved ar.rsc
929 * - r28: saved cr.iip 962 * - r28: saved cr.iip
930 * - r29: saved cr.ipsr 963 * - r29: saved cr.ipsr
964 * - r30: ar.itc for accounting (don't touch)
931 * - r31: saved pr 965 * - r31: saved pr
932 * - b0: original contents (to be saved) 966 * - b0: original contents (to be saved)
933 * On exit: 967 * On exit:
@@ -1090,6 +1124,41 @@ END(dispatch_illegal_op_fault)
1090 DBG_FAULT(16) 1124 DBG_FAULT(16)
1091 FAULT(16) 1125 FAULT(16)
1092 1126
1127#ifdef CONFIG_VIRT_CPU_ACCOUNTING
1128 /*
1129 * There is no particular reason for this code to be here, other than
1130 * that there happens to be space here that would go unused otherwise.
1131 * If this fault ever gets "unreserved", simply moved the following
1132 * code to a more suitable spot...
1133 *
1134 * account_sys_enter is called from SAVE_MIN* macros if accounting is
1135 * enabled and if the macro is entered from user mode.
1136 */
1137ENTRY(account_sys_enter)
1138 // mov.m r20=ar.itc is called in advance, and r13 is current
1139 add r16=TI_AC_STAMP+IA64_TASK_SIZE,r13
1140 add r17=TI_AC_LEAVE+IA64_TASK_SIZE,r13
1141 ;;
1142 ld8 r18=[r16],TI_AC_STIME-TI_AC_STAMP // time at last check in kernel
1143 ld8 r19=[r17],TI_AC_UTIME-TI_AC_LEAVE // time at left from kernel
1144 ;;
1145 ld8 r23=[r16],TI_AC_STAMP-TI_AC_STIME // cumulated stime
1146 ld8 r21=[r17] // cumulated utime
1147 sub r22=r19,r18 // stime before leave kernel
1148 ;;
1149 st8 [r16]=r20,TI_AC_STIME-TI_AC_STAMP // update stamp
1150 sub r18=r20,r19 // elapsed time in user mode
1151 ;;
1152 add r23=r23,r22 // sum stime
1153 add r21=r21,r18 // sum utime
1154 ;;
1155 st8 [r16]=r23 // update stime
1156 st8 [r17]=r21 // update utime
1157 ;;
1158 br.ret.sptk.many rp
1159END(account_sys_enter)
1160#endif
1161
1093 .org ia64_ivt+0x4400 1162 .org ia64_ivt+0x4400
1094///////////////////////////////////////////////////////////////////////////////////////// 1163/////////////////////////////////////////////////////////////////////////////////////////
1095// 0x4400 Entry 17 (size 64 bundles) Reserved 1164// 0x4400 Entry 17 (size 64 bundles) Reserved
diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h
index c9ac8bada786..7c548ac52bbc 100644
--- a/arch/ia64/kernel/minstate.h
+++ b/arch/ia64/kernel/minstate.h
@@ -3,6 +3,18 @@
3 3
4#include "entry.h" 4#include "entry.h"
5 5
6#ifdef CONFIG_VIRT_CPU_ACCOUNTING
7/* read ar.itc in advance, and use it before leaving bank 0 */
8#define ACCOUNT_GET_STAMP \
9(pUStk) mov.m r20=ar.itc;
10#define ACCOUNT_SYS_ENTER \
11(pUStk) br.call.spnt rp=account_sys_enter \
12 ;;
13#else
14#define ACCOUNT_GET_STAMP
15#define ACCOUNT_SYS_ENTER
16#endif
17
6/* 18/*
7 * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves 19 * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves
8 * the minimum state necessary that allows us to turn psr.ic back 20 * the minimum state necessary that allows us to turn psr.ic back
@@ -122,11 +134,13 @@
122 ;; \ 134 ;; \
123.mem.offset 0,0; st8.spill [r16]=r2,16; \ 135.mem.offset 0,0; st8.spill [r16]=r2,16; \
124.mem.offset 8,0; st8.spill [r17]=r3,16; \ 136.mem.offset 8,0; st8.spill [r17]=r3,16; \
137 ACCOUNT_GET_STAMP \
125 adds r2=IA64_PT_REGS_R16_OFFSET,r1; \ 138 adds r2=IA64_PT_REGS_R16_OFFSET,r1; \
126 ;; \ 139 ;; \
127 EXTRA; \ 140 EXTRA; \
128 movl r1=__gp; /* establish kernel global pointer */ \ 141 movl r1=__gp; /* establish kernel global pointer */ \
129 ;; \ 142 ;; \
143 ACCOUNT_SYS_ENTER \
130 bsw.1; /* switch back to bank 1 (must be last in insn group) */ \ 144 bsw.1; /* switch back to bank 1 (must be last in insn group) */ \
131 ;; 145 ;;
132 146
diff --git a/arch/ia64/kernel/patch.c b/arch/ia64/kernel/patch.c
index 2cb9425e0421..e0dca8743dbb 100644
--- a/arch/ia64/kernel/patch.c
+++ b/arch/ia64/kernel/patch.c
@@ -135,10 +135,10 @@ ia64_patch_mckinley_e9 (unsigned long start, unsigned long end)
135 135
136 while (offp < (s32 *) end) { 136 while (offp < (s32 *) end) {
137 wp = (u64 *) ia64_imva((char *) offp + *offp); 137 wp = (u64 *) ia64_imva((char *) offp + *offp);
138 wp[0] = 0x0000000100000000UL; /* nop.m 0; nop.i 0; nop.i 0 */ 138 wp[0] = 0x0000000100000011UL; /* nop.m 0; nop.i 0; br.ret.sptk.many b6 */
139 wp[1] = 0x0004000000000200UL; 139 wp[1] = 0x0084006880000200UL;
140 wp[2] = 0x0000000100000011UL; /* nop.m 0; nop.i 0; br.ret.sptk.many b6 */ 140 wp[2] = 0x0000000100000000UL; /* nop.m 0; nop.i 0; nop.i 0 */
141 wp[3] = 0x0084006880000200UL; 141 wp[3] = 0x0004000000000200UL;
142 ia64_fc(wp); ia64_fc(wp + 2); 142 ia64_fc(wp); ia64_fc(wp + 2);
143 ++offp; 143 ++offp;
144 } 144 }
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 49937a383b23..a5ea817cbcbf 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -625,21 +625,6 @@ do_dump_fpu (struct unw_frame_info *info, void *arg)
625 do_dump_task_fpu(current, info, arg); 625 do_dump_task_fpu(current, info, arg);
626} 626}
627 627
628int
629dump_task_regs(struct task_struct *task, elf_gregset_t *regs)
630{
631 struct unw_frame_info tcore_info;
632
633 if (current == task) {
634 unw_init_running(do_copy_regs, regs);
635 } else {
636 memset(&tcore_info, 0, sizeof(tcore_info));
637 unw_init_from_blocked_task(&tcore_info, task);
638 do_copy_task_regs(task, &tcore_info, regs);
639 }
640 return 1;
641}
642
643void 628void
644ia64_elf_core_copy_regs (struct pt_regs *pt, elf_gregset_t dst) 629ia64_elf_core_copy_regs (struct pt_regs *pt, elf_gregset_t dst)
645{ 630{
@@ -647,21 +632,6 @@ ia64_elf_core_copy_regs (struct pt_regs *pt, elf_gregset_t dst)
647} 632}
648 633
649int 634int
650dump_task_fpu (struct task_struct *task, elf_fpregset_t *dst)
651{
652 struct unw_frame_info tcore_info;
653
654 if (current == task) {
655 unw_init_running(do_dump_fpu, dst);
656 } else {
657 memset(&tcore_info, 0, sizeof(tcore_info));
658 unw_init_from_blocked_task(&tcore_info, task);
659 do_dump_task_fpu(task, &tcore_info, dst);
660 }
661 return 1;
662}
663
664int
665dump_fpu (struct pt_regs *pt, elf_fpregset_t dst) 635dump_fpu (struct pt_regs *pt, elf_fpregset_t dst)
666{ 636{
667 unw_init_running(do_dump_fpu, dst); 637 unw_init_running(do_dump_fpu, dst);
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index ab784ec4319d..2a9943b5947f 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -3,6 +3,9 @@
3 * 3 *
4 * Copyright (C) 1999-2005 Hewlett-Packard Co 4 * Copyright (C) 1999-2005 Hewlett-Packard Co
5 * David Mosberger-Tang <davidm@hpl.hp.com> 5 * David Mosberger-Tang <davidm@hpl.hp.com>
6 * Copyright (C) 2006 Intel Co
7 * 2006-08-12 - IA64 Native Utrace implementation support added by
8 * Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
6 * 9 *
7 * Derived from the x86 and Alpha versions. 10 * Derived from the x86 and Alpha versions.
8 */ 11 */
@@ -17,6 +20,8 @@
17#include <linux/security.h> 20#include <linux/security.h>
18#include <linux/audit.h> 21#include <linux/audit.h>
19#include <linux/signal.h> 22#include <linux/signal.h>
23#include <linux/regset.h>
24#include <linux/elf.h>
20 25
21#include <asm/pgtable.h> 26#include <asm/pgtable.h>
22#include <asm/processor.h> 27#include <asm/processor.h>
@@ -740,25 +745,6 @@ ia64_sync_fph (struct task_struct *task)
740 psr->dfh = 1; 745 psr->dfh = 1;
741} 746}
742 747
743static int
744access_fr (struct unw_frame_info *info, int regnum, int hi,
745 unsigned long *data, int write_access)
746{
747 struct ia64_fpreg fpval;
748 int ret;
749
750 ret = unw_get_fr(info, regnum, &fpval);
751 if (ret < 0)
752 return ret;
753
754 if (write_access) {
755 fpval.u.bits[hi] = *data;
756 ret = unw_set_fr(info, regnum, fpval);
757 } else
758 *data = fpval.u.bits[hi];
759 return ret;
760}
761
762/* 748/*
763 * Change the machine-state of CHILD such that it will return via the normal 749 * Change the machine-state of CHILD such that it will return via the normal
764 * kernel exit-path, rather than the syscall-exit path. 750 * kernel exit-path, rather than the syscall-exit path.
@@ -860,309 +846,7 @@ access_nat_bits (struct task_struct *child, struct pt_regs *pt,
860 846
861static int 847static int
862access_uarea (struct task_struct *child, unsigned long addr, 848access_uarea (struct task_struct *child, unsigned long addr,
863 unsigned long *data, int write_access) 849 unsigned long *data, int write_access);
864{
865 unsigned long *ptr, regnum, urbs_end, cfm;
866 struct switch_stack *sw;
867 struct pt_regs *pt;
868# define pt_reg_addr(pt, reg) ((void *) \
869 ((unsigned long) (pt) \
870 + offsetof(struct pt_regs, reg)))
871
872
873 pt = task_pt_regs(child);
874 sw = (struct switch_stack *) (child->thread.ksp + 16);
875
876 if ((addr & 0x7) != 0) {
877 dprintk("ptrace: unaligned register address 0x%lx\n", addr);
878 return -1;
879 }
880
881 if (addr < PT_F127 + 16) {
882 /* accessing fph */
883 if (write_access)
884 ia64_sync_fph(child);
885 else
886 ia64_flush_fph(child);
887 ptr = (unsigned long *)
888 ((unsigned long) &child->thread.fph + addr);
889 } else if ((addr >= PT_F10) && (addr < PT_F11 + 16)) {
890 /* scratch registers untouched by kernel (saved in pt_regs) */
891 ptr = pt_reg_addr(pt, f10) + (addr - PT_F10);
892 } else if (addr >= PT_F12 && addr < PT_F15 + 16) {
893 /*
894 * Scratch registers untouched by kernel (saved in
895 * switch_stack).
896 */
897 ptr = (unsigned long *) ((long) sw
898 + (addr - PT_NAT_BITS - 32));
899 } else if (addr < PT_AR_LC + 8) {
900 /* preserved state: */
901 struct unw_frame_info info;
902 char nat = 0;
903 int ret;
904
905 unw_init_from_blocked_task(&info, child);
906 if (unw_unwind_to_user(&info) < 0)
907 return -1;
908
909 switch (addr) {
910 case PT_NAT_BITS:
911 return access_nat_bits(child, pt, &info,
912 data, write_access);
913
914 case PT_R4: case PT_R5: case PT_R6: case PT_R7:
915 if (write_access) {
916 /* read NaT bit first: */
917 unsigned long dummy;
918
919 ret = unw_get_gr(&info, (addr - PT_R4)/8 + 4,
920 &dummy, &nat);
921 if (ret < 0)
922 return ret;
923 }
924 return unw_access_gr(&info, (addr - PT_R4)/8 + 4, data,
925 &nat, write_access);
926
927 case PT_B1: case PT_B2: case PT_B3:
928 case PT_B4: case PT_B5:
929 return unw_access_br(&info, (addr - PT_B1)/8 + 1, data,
930 write_access);
931
932 case PT_AR_EC:
933 return unw_access_ar(&info, UNW_AR_EC, data,
934 write_access);
935
936 case PT_AR_LC:
937 return unw_access_ar(&info, UNW_AR_LC, data,
938 write_access);
939
940 default:
941 if (addr >= PT_F2 && addr < PT_F5 + 16)
942 return access_fr(&info, (addr - PT_F2)/16 + 2,
943 (addr & 8) != 0, data,
944 write_access);
945 else if (addr >= PT_F16 && addr < PT_F31 + 16)
946 return access_fr(&info,
947 (addr - PT_F16)/16 + 16,
948 (addr & 8) != 0,
949 data, write_access);
950 else {
951 dprintk("ptrace: rejecting access to register "
952 "address 0x%lx\n", addr);
953 return -1;
954 }
955 }
956 } else if (addr < PT_F9+16) {
957 /* scratch state */
958 switch (addr) {
959 case PT_AR_BSP:
960 /*
961 * By convention, we use PT_AR_BSP to refer to
962 * the end of the user-level backing store.
963 * Use ia64_rse_skip_regs(PT_AR_BSP, -CFM.sof)
964 * to get the real value of ar.bsp at the time
965 * the kernel was entered.
966 *
967 * Furthermore, when changing the contents of
968 * PT_AR_BSP (or PT_CFM) while the task is
969 * blocked in a system call, convert the state
970 * so that the non-system-call exit
971 * path is used. This ensures that the proper
972 * state will be picked up when resuming
973 * execution. However, it *also* means that
974 * once we write PT_AR_BSP/PT_CFM, it won't be
975 * possible to modify the syscall arguments of
976 * the pending system call any longer. This
977 * shouldn't be an issue because modifying
978 * PT_AR_BSP/PT_CFM generally implies that
979 * we're either abandoning the pending system
980 * call or that we defer it's re-execution
981 * (e.g., due to GDB doing an inferior
982 * function call).
983 */
984 urbs_end = ia64_get_user_rbs_end(child, pt, &cfm);
985 if (write_access) {
986 if (*data != urbs_end) {
987 if (in_syscall(pt))
988 convert_to_non_syscall(child,
989 pt,
990 cfm);
991 /*
992 * Simulate user-level write
993 * of ar.bsp:
994 */
995 pt->loadrs = 0;
996 pt->ar_bspstore = *data;
997 }
998 } else
999 *data = urbs_end;
1000 return 0;
1001
1002 case PT_CFM:
1003 urbs_end = ia64_get_user_rbs_end(child, pt, &cfm);
1004 if (write_access) {
1005 if (((cfm ^ *data) & PFM_MASK) != 0) {
1006 if (in_syscall(pt))
1007 convert_to_non_syscall(child,
1008 pt,
1009 cfm);
1010 pt->cr_ifs = ((pt->cr_ifs & ~PFM_MASK)
1011 | (*data & PFM_MASK));
1012 }
1013 } else
1014 *data = cfm;
1015 return 0;
1016
1017 case PT_CR_IPSR:
1018 if (write_access) {
1019 unsigned long tmp = *data;
1020 /* psr.ri==3 is a reserved value: SDM 2:25 */
1021 if ((tmp & IA64_PSR_RI) == IA64_PSR_RI)
1022 tmp &= ~IA64_PSR_RI;
1023 pt->cr_ipsr = ((tmp & IPSR_MASK)
1024 | (pt->cr_ipsr & ~IPSR_MASK));
1025 } else
1026 *data = (pt->cr_ipsr & IPSR_MASK);
1027 return 0;
1028
1029 case PT_AR_RSC:
1030 if (write_access)
1031 pt->ar_rsc = *data | (3 << 2); /* force PL3 */
1032 else
1033 *data = pt->ar_rsc;
1034 return 0;
1035
1036 case PT_AR_RNAT:
1037 ptr = pt_reg_addr(pt, ar_rnat);
1038 break;
1039 case PT_R1:
1040 ptr = pt_reg_addr(pt, r1);
1041 break;
1042 case PT_R2: case PT_R3:
1043 ptr = pt_reg_addr(pt, r2) + (addr - PT_R2);
1044 break;
1045 case PT_R8: case PT_R9: case PT_R10: case PT_R11:
1046 ptr = pt_reg_addr(pt, r8) + (addr - PT_R8);
1047 break;
1048 case PT_R12: case PT_R13:
1049 ptr = pt_reg_addr(pt, r12) + (addr - PT_R12);
1050 break;
1051 case PT_R14:
1052 ptr = pt_reg_addr(pt, r14);
1053 break;
1054 case PT_R15:
1055 ptr = pt_reg_addr(pt, r15);
1056 break;
1057 case PT_R16: case PT_R17: case PT_R18: case PT_R19:
1058 case PT_R20: case PT_R21: case PT_R22: case PT_R23:
1059 case PT_R24: case PT_R25: case PT_R26: case PT_R27:
1060 case PT_R28: case PT_R29: case PT_R30: case PT_R31:
1061 ptr = pt_reg_addr(pt, r16) + (addr - PT_R16);
1062 break;
1063 case PT_B0:
1064 ptr = pt_reg_addr(pt, b0);
1065 break;
1066 case PT_B6:
1067 ptr = pt_reg_addr(pt, b6);
1068 break;
1069 case PT_B7:
1070 ptr = pt_reg_addr(pt, b7);
1071 break;
1072 case PT_F6: case PT_F6+8: case PT_F7: case PT_F7+8:
1073 case PT_F8: case PT_F8+8: case PT_F9: case PT_F9+8:
1074 ptr = pt_reg_addr(pt, f6) + (addr - PT_F6);
1075 break;
1076 case PT_AR_BSPSTORE:
1077 ptr = pt_reg_addr(pt, ar_bspstore);
1078 break;
1079 case PT_AR_UNAT:
1080 ptr = pt_reg_addr(pt, ar_unat);
1081 break;
1082 case PT_AR_PFS:
1083 ptr = pt_reg_addr(pt, ar_pfs);
1084 break;
1085 case PT_AR_CCV:
1086 ptr = pt_reg_addr(pt, ar_ccv);
1087 break;
1088 case PT_AR_FPSR:
1089 ptr = pt_reg_addr(pt, ar_fpsr);
1090 break;
1091 case PT_CR_IIP:
1092 ptr = pt_reg_addr(pt, cr_iip);
1093 break;
1094 case PT_PR:
1095 ptr = pt_reg_addr(pt, pr);
1096 break;
1097 /* scratch register */
1098
1099 default:
1100 /* disallow accessing anything else... */
1101 dprintk("ptrace: rejecting access to register "
1102 "address 0x%lx\n", addr);
1103 return -1;
1104 }
1105 } else if (addr <= PT_AR_SSD) {
1106 ptr = pt_reg_addr(pt, ar_csd) + (addr - PT_AR_CSD);
1107 } else {
1108 /* access debug registers */
1109
1110 if (addr >= PT_IBR) {
1111 regnum = (addr - PT_IBR) >> 3;
1112 ptr = &child->thread.ibr[0];
1113 } else {
1114 regnum = (addr - PT_DBR) >> 3;
1115 ptr = &child->thread.dbr[0];
1116 }
1117
1118 if (regnum >= 8) {
1119 dprintk("ptrace: rejecting access to register "
1120 "address 0x%lx\n", addr);
1121 return -1;
1122 }
1123#ifdef CONFIG_PERFMON
1124 /*
1125 * Check if debug registers are used by perfmon. This
1126 * test must be done once we know that we can do the
1127 * operation, i.e. the arguments are all valid, but
1128 * before we start modifying the state.
1129 *
1130 * Perfmon needs to keep a count of how many processes
1131 * are trying to modify the debug registers for system
1132 * wide monitoring sessions.
1133 *
1134 * We also include read access here, because they may
1135 * cause the PMU-installed debug register state
1136 * (dbr[], ibr[]) to be reset. The two arrays are also
1137 * used by perfmon, but we do not use
1138 * IA64_THREAD_DBG_VALID. The registers are restored
1139 * by the PMU context switch code.
1140 */
1141 if (pfm_use_debug_registers(child)) return -1;
1142#endif
1143
1144 if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) {
1145 child->thread.flags |= IA64_THREAD_DBG_VALID;
1146 memset(child->thread.dbr, 0,
1147 sizeof(child->thread.dbr));
1148 memset(child->thread.ibr, 0,
1149 sizeof(child->thread.ibr));
1150 }
1151
1152 ptr += regnum;
1153
1154 if ((regnum & 1) && write_access) {
1155 /* don't let the user set kernel-level breakpoints: */
1156 *ptr = *data & ~(7UL << 56);
1157 return 0;
1158 }
1159 }
1160 if (write_access)
1161 *ptr = *data;
1162 else
1163 *data = *ptr;
1164 return 0;
1165}
1166 850
1167static long 851static long
1168ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr) 852ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
@@ -1626,3 +1310,892 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
1626 if (test_thread_flag(TIF_RESTORE_RSE)) 1310 if (test_thread_flag(TIF_RESTORE_RSE))
1627 ia64_sync_krbs(); 1311 ia64_sync_krbs();
1628} 1312}
1313
1314/* Utrace implementation starts here */
1315struct regset_get {
1316 void *kbuf;
1317 void __user *ubuf;
1318};
1319
1320struct regset_set {
1321 const void *kbuf;
1322 const void __user *ubuf;
1323};
1324
1325struct regset_getset {
1326 struct task_struct *target;
1327 const struct user_regset *regset;
1328 union {
1329 struct regset_get get;
1330 struct regset_set set;
1331 } u;
1332 unsigned int pos;
1333 unsigned int count;
1334 int ret;
1335};
1336
1337static int
1338access_elf_gpreg(struct task_struct *target, struct unw_frame_info *info,
1339 unsigned long addr, unsigned long *data, int write_access)
1340{
1341 struct pt_regs *pt;
1342 unsigned long *ptr = NULL;
1343 int ret;
1344 char nat = 0;
1345
1346 pt = task_pt_regs(target);
1347 switch (addr) {
1348 case ELF_GR_OFFSET(1):
1349 ptr = &pt->r1;
1350 break;
1351 case ELF_GR_OFFSET(2):
1352 case ELF_GR_OFFSET(3):
1353 ptr = (void *)&pt->r2 + (addr - ELF_GR_OFFSET(2));
1354 break;
1355 case ELF_GR_OFFSET(4) ... ELF_GR_OFFSET(7):
1356 if (write_access) {
1357 /* read NaT bit first: */
1358 unsigned long dummy;
1359
1360 ret = unw_get_gr(info, addr/8, &dummy, &nat);
1361 if (ret < 0)
1362 return ret;
1363 }
1364 return unw_access_gr(info, addr/8, data, &nat, write_access);
1365 case ELF_GR_OFFSET(8) ... ELF_GR_OFFSET(11):
1366 ptr = (void *)&pt->r8 + addr - ELF_GR_OFFSET(8);
1367 break;
1368 case ELF_GR_OFFSET(12):
1369 case ELF_GR_OFFSET(13):
1370 ptr = (void *)&pt->r12 + addr - ELF_GR_OFFSET(12);
1371 break;
1372 case ELF_GR_OFFSET(14):
1373 ptr = &pt->r14;
1374 break;
1375 case ELF_GR_OFFSET(15):
1376 ptr = &pt->r15;
1377 }
1378 if (write_access)
1379 *ptr = *data;
1380 else
1381 *data = *ptr;
1382 return 0;
1383}
1384
1385static int
1386access_elf_breg(struct task_struct *target, struct unw_frame_info *info,
1387 unsigned long addr, unsigned long *data, int write_access)
1388{
1389 struct pt_regs *pt;
1390 unsigned long *ptr = NULL;
1391
1392 pt = task_pt_regs(target);
1393 switch (addr) {
1394 case ELF_BR_OFFSET(0):
1395 ptr = &pt->b0;
1396 break;
1397 case ELF_BR_OFFSET(1) ... ELF_BR_OFFSET(5):
1398 return unw_access_br(info, (addr - ELF_BR_OFFSET(0))/8,
1399 data, write_access);
1400 case ELF_BR_OFFSET(6):
1401 ptr = &pt->b6;
1402 break;
1403 case ELF_BR_OFFSET(7):
1404 ptr = &pt->b7;
1405 }
1406 if (write_access)
1407 *ptr = *data;
1408 else
1409 *data = *ptr;
1410 return 0;
1411}
1412
1413static int
1414access_elf_areg(struct task_struct *target, struct unw_frame_info *info,
1415 unsigned long addr, unsigned long *data, int write_access)
1416{
1417 struct pt_regs *pt;
1418 unsigned long cfm, urbs_end;
1419 unsigned long *ptr = NULL;
1420
1421 pt = task_pt_regs(target);
1422 if (addr >= ELF_AR_RSC_OFFSET && addr <= ELF_AR_SSD_OFFSET) {
1423 switch (addr) {
1424 case ELF_AR_RSC_OFFSET:
1425 /* force PL3 */
1426 if (write_access)
1427 pt->ar_rsc = *data | (3 << 2);
1428 else
1429 *data = pt->ar_rsc;
1430 return 0;
1431 case ELF_AR_BSP_OFFSET:
1432 /*
1433 * By convention, we use PT_AR_BSP to refer to
1434 * the end of the user-level backing store.
1435 * Use ia64_rse_skip_regs(PT_AR_BSP, -CFM.sof)
1436 * to get the real value of ar.bsp at the time
1437 * the kernel was entered.
1438 *
1439 * Furthermore, when changing the contents of
1440 * PT_AR_BSP (or PT_CFM) while the task is
1441 * blocked in a system call, convert the state
1442 * so that the non-system-call exit
1443 * path is used. This ensures that the proper
1444 * state will be picked up when resuming
1445 * execution. However, it *also* means that
1446 * once we write PT_AR_BSP/PT_CFM, it won't be
1447 * possible to modify the syscall arguments of
1448 * the pending system call any longer. This
1449 * shouldn't be an issue because modifying
1450 * PT_AR_BSP/PT_CFM generally implies that
1451 * we're either abandoning the pending system
1452 * call or that we defer it's re-execution
1453 * (e.g., due to GDB doing an inferior
1454 * function call).
1455 */
1456 urbs_end = ia64_get_user_rbs_end(target, pt, &cfm);
1457 if (write_access) {
1458 if (*data != urbs_end) {
1459 if (in_syscall(pt))
1460 convert_to_non_syscall(target,
1461 pt,
1462 cfm);
1463 /*
1464 * Simulate user-level write
1465 * of ar.bsp:
1466 */
1467 pt->loadrs = 0;
1468 pt->ar_bspstore = *data;
1469 }
1470 } else
1471 *data = urbs_end;
1472 return 0;
1473 case ELF_AR_BSPSTORE_OFFSET:
1474 ptr = &pt->ar_bspstore;
1475 break;
1476 case ELF_AR_RNAT_OFFSET:
1477 ptr = &pt->ar_rnat;
1478 break;
1479 case ELF_AR_CCV_OFFSET:
1480 ptr = &pt->ar_ccv;
1481 break;
1482 case ELF_AR_UNAT_OFFSET:
1483 ptr = &pt->ar_unat;
1484 break;
1485 case ELF_AR_FPSR_OFFSET:
1486 ptr = &pt->ar_fpsr;
1487 break;
1488 case ELF_AR_PFS_OFFSET:
1489 ptr = &pt->ar_pfs;
1490 break;
1491 case ELF_AR_LC_OFFSET:
1492 return unw_access_ar(info, UNW_AR_LC, data,
1493 write_access);
1494 case ELF_AR_EC_OFFSET:
1495 return unw_access_ar(info, UNW_AR_EC, data,
1496 write_access);
1497 case ELF_AR_CSD_OFFSET:
1498 ptr = &pt->ar_csd;
1499 break;
1500 case ELF_AR_SSD_OFFSET:
1501 ptr = &pt->ar_ssd;
1502 }
1503 } else if (addr >= ELF_CR_IIP_OFFSET && addr <= ELF_CR_IPSR_OFFSET) {
1504 switch (addr) {
1505 case ELF_CR_IIP_OFFSET:
1506 ptr = &pt->cr_iip;
1507 break;
1508 case ELF_CFM_OFFSET:
1509 urbs_end = ia64_get_user_rbs_end(target, pt, &cfm);
1510 if (write_access) {
1511 if (((cfm ^ *data) & PFM_MASK) != 0) {
1512 if (in_syscall(pt))
1513 convert_to_non_syscall(target,
1514 pt,
1515 cfm);
1516 pt->cr_ifs = ((pt->cr_ifs & ~PFM_MASK)
1517 | (*data & PFM_MASK));
1518 }
1519 } else
1520 *data = cfm;
1521 return 0;
1522 case ELF_CR_IPSR_OFFSET:
1523 if (write_access) {
1524 unsigned long tmp = *data;
1525 /* psr.ri==3 is a reserved value: SDM 2:25 */
1526 if ((tmp & IA64_PSR_RI) == IA64_PSR_RI)
1527 tmp &= ~IA64_PSR_RI;
1528 pt->cr_ipsr = ((tmp & IPSR_MASK)
1529 | (pt->cr_ipsr & ~IPSR_MASK));
1530 } else
1531 *data = (pt->cr_ipsr & IPSR_MASK);
1532 return 0;
1533 }
1534 } else if (addr == ELF_NAT_OFFSET)
1535 return access_nat_bits(target, pt, info,
1536 data, write_access);
1537 else if (addr == ELF_PR_OFFSET)
1538 ptr = &pt->pr;
1539 else
1540 return -1;
1541
1542 if (write_access)
1543 *ptr = *data;
1544 else
1545 *data = *ptr;
1546
1547 return 0;
1548}
1549
1550static int
1551access_elf_reg(struct task_struct *target, struct unw_frame_info *info,
1552 unsigned long addr, unsigned long *data, int write_access)
1553{
1554 if (addr >= ELF_GR_OFFSET(1) && addr <= ELF_GR_OFFSET(15))
1555 return access_elf_gpreg(target, info, addr, data, write_access);
1556 else if (addr >= ELF_BR_OFFSET(0) && addr <= ELF_BR_OFFSET(7))
1557 return access_elf_breg(target, info, addr, data, write_access);
1558 else
1559 return access_elf_areg(target, info, addr, data, write_access);
1560}
1561
1562void do_gpregs_get(struct unw_frame_info *info, void *arg)
1563{
1564 struct pt_regs *pt;
1565 struct regset_getset *dst = arg;
1566 elf_greg_t tmp[16];
1567 unsigned int i, index, min_copy;
1568
1569 if (unw_unwind_to_user(info) < 0)
1570 return;
1571
1572 /*
1573 * coredump format:
1574 * r0-r31
1575 * NaT bits (for r0-r31; bit N == 1 iff rN is a NaT)
1576 * predicate registers (p0-p63)
1577 * b0-b7
1578 * ip cfm user-mask
1579 * ar.rsc ar.bsp ar.bspstore ar.rnat
1580 * ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec
1581 */
1582
1583
1584 /* Skip r0 */
1585 if (dst->count > 0 && dst->pos < ELF_GR_OFFSET(1)) {
1586 dst->ret = user_regset_copyout_zero(&dst->pos, &dst->count,
1587 &dst->u.get.kbuf,
1588 &dst->u.get.ubuf,
1589 0, ELF_GR_OFFSET(1));
1590 if (dst->ret || dst->count == 0)
1591 return;
1592 }
1593
1594 /* gr1 - gr15 */
1595 if (dst->count > 0 && dst->pos < ELF_GR_OFFSET(16)) {
1596 index = (dst->pos - ELF_GR_OFFSET(1)) / sizeof(elf_greg_t);
1597 min_copy = ELF_GR_OFFSET(16) > (dst->pos + dst->count) ?
1598 (dst->pos + dst->count) : ELF_GR_OFFSET(16);
1599 for (i = dst->pos; i < min_copy; i += sizeof(elf_greg_t),
1600 index++)
1601 if (access_elf_reg(dst->target, info, i,
1602 &tmp[index], 0) < 0) {
1603 dst->ret = -EIO;
1604 return;
1605 }
1606 dst->ret = user_regset_copyout(&dst->pos, &dst->count,
1607 &dst->u.get.kbuf, &dst->u.get.ubuf, tmp,
1608 ELF_GR_OFFSET(1), ELF_GR_OFFSET(16));
1609 if (dst->ret || dst->count == 0)
1610 return;
1611 }
1612
1613 /* r16-r31 */
1614 if (dst->count > 0 && dst->pos < ELF_NAT_OFFSET) {
1615 pt = task_pt_regs(dst->target);
1616 dst->ret = user_regset_copyout(&dst->pos, &dst->count,
1617 &dst->u.get.kbuf, &dst->u.get.ubuf, &pt->r16,
1618 ELF_GR_OFFSET(16), ELF_NAT_OFFSET);
1619 if (dst->ret || dst->count == 0)
1620 return;
1621 }
1622
1623 /* nat, pr, b0 - b7 */
1624 if (dst->count > 0 && dst->pos < ELF_CR_IIP_OFFSET) {
1625 index = (dst->pos - ELF_NAT_OFFSET) / sizeof(elf_greg_t);
1626 min_copy = ELF_CR_IIP_OFFSET > (dst->pos + dst->count) ?
1627 (dst->pos + dst->count) : ELF_CR_IIP_OFFSET;
1628 for (i = dst->pos; i < min_copy; i += sizeof(elf_greg_t),
1629 index++)
1630 if (access_elf_reg(dst->target, info, i,
1631 &tmp[index], 0) < 0) {
1632 dst->ret = -EIO;
1633 return;
1634 }
1635 dst->ret = user_regset_copyout(&dst->pos, &dst->count,
1636 &dst->u.get.kbuf, &dst->u.get.ubuf, tmp,
1637 ELF_NAT_OFFSET, ELF_CR_IIP_OFFSET);
1638 if (dst->ret || dst->count == 0)
1639 return;
1640 }
1641
1642 /* ip cfm psr ar.rsc ar.bsp ar.bspstore ar.rnat
1643 * ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec ar.csd ar.ssd
1644 */
1645 if (dst->count > 0 && dst->pos < (ELF_AR_END_OFFSET)) {
1646 index = (dst->pos - ELF_CR_IIP_OFFSET) / sizeof(elf_greg_t);
1647 min_copy = ELF_AR_END_OFFSET > (dst->pos + dst->count) ?
1648 (dst->pos + dst->count) : ELF_AR_END_OFFSET;
1649 for (i = dst->pos; i < min_copy; i += sizeof(elf_greg_t),
1650 index++)
1651 if (access_elf_reg(dst->target, info, i,
1652 &tmp[index], 0) < 0) {
1653 dst->ret = -EIO;
1654 return;
1655 }
1656 dst->ret = user_regset_copyout(&dst->pos, &dst->count,
1657 &dst->u.get.kbuf, &dst->u.get.ubuf, tmp,
1658 ELF_CR_IIP_OFFSET, ELF_AR_END_OFFSET);
1659 }
1660}
1661
1662void do_gpregs_set(struct unw_frame_info *info, void *arg)
1663{
1664 struct pt_regs *pt;
1665 struct regset_getset *dst = arg;
1666 elf_greg_t tmp[16];
1667 unsigned int i, index;
1668
1669 if (unw_unwind_to_user(info) < 0)
1670 return;
1671
1672 /* Skip r0 */
1673 if (dst->count > 0 && dst->pos < ELF_GR_OFFSET(1)) {
1674 dst->ret = user_regset_copyin_ignore(&dst->pos, &dst->count,
1675 &dst->u.set.kbuf,
1676 &dst->u.set.ubuf,
1677 0, ELF_GR_OFFSET(1));
1678 if (dst->ret || dst->count == 0)
1679 return;
1680 }
1681
1682 /* gr1-gr15 */
1683 if (dst->count > 0 && dst->pos < ELF_GR_OFFSET(16)) {
1684 i = dst->pos;
1685 index = (dst->pos - ELF_GR_OFFSET(1)) / sizeof(elf_greg_t);
1686 dst->ret = user_regset_copyin(&dst->pos, &dst->count,
1687 &dst->u.set.kbuf, &dst->u.set.ubuf, tmp,
1688 ELF_GR_OFFSET(1), ELF_GR_OFFSET(16));
1689 if (dst->ret)
1690 return;
1691 for ( ; i < dst->pos; i += sizeof(elf_greg_t), index++)
1692 if (access_elf_reg(dst->target, info, i,
1693 &tmp[index], 1) < 0) {
1694 dst->ret = -EIO;
1695 return;
1696 }
1697 if (dst->count == 0)
1698 return;
1699 }
1700
1701 /* gr16-gr31 */
1702 if (dst->count > 0 && dst->pos < ELF_NAT_OFFSET) {
1703 pt = task_pt_regs(dst->target);
1704 dst->ret = user_regset_copyin(&dst->pos, &dst->count,
1705 &dst->u.set.kbuf, &dst->u.set.ubuf, &pt->r16,
1706 ELF_GR_OFFSET(16), ELF_NAT_OFFSET);
1707 if (dst->ret || dst->count == 0)
1708 return;
1709 }
1710
1711 /* nat, pr, b0 - b7 */
1712 if (dst->count > 0 && dst->pos < ELF_CR_IIP_OFFSET) {
1713 i = dst->pos;
1714 index = (dst->pos - ELF_NAT_OFFSET) / sizeof(elf_greg_t);
1715 dst->ret = user_regset_copyin(&dst->pos, &dst->count,
1716 &dst->u.set.kbuf, &dst->u.set.ubuf, tmp,
1717 ELF_NAT_OFFSET, ELF_CR_IIP_OFFSET);
1718 if (dst->ret)
1719 return;
1720 for (; i < dst->pos; i += sizeof(elf_greg_t), index++)
1721 if (access_elf_reg(dst->target, info, i,
1722 &tmp[index], 1) < 0) {
1723 dst->ret = -EIO;
1724 return;
1725 }
1726 if (dst->count == 0)
1727 return;
1728 }
1729
1730 /* ip cfm psr ar.rsc ar.bsp ar.bspstore ar.rnat
1731 * ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec ar.csd ar.ssd
1732 */
1733 if (dst->count > 0 && dst->pos < (ELF_AR_END_OFFSET)) {
1734 i = dst->pos;
1735 index = (dst->pos - ELF_CR_IIP_OFFSET) / sizeof(elf_greg_t);
1736 dst->ret = user_regset_copyin(&dst->pos, &dst->count,
1737 &dst->u.set.kbuf, &dst->u.set.ubuf, tmp,
1738 ELF_CR_IIP_OFFSET, ELF_AR_END_OFFSET);
1739 if (dst->ret)
1740 return;
1741 for ( ; i < dst->pos; i += sizeof(elf_greg_t), index++)
1742 if (access_elf_reg(dst->target, info, i,
1743 &tmp[index], 1) < 0) {
1744 dst->ret = -EIO;
1745 return;
1746 }
1747 }
1748}
1749
1750#define ELF_FP_OFFSET(i) (i * sizeof(elf_fpreg_t))
1751
1752void do_fpregs_get(struct unw_frame_info *info, void *arg)
1753{
1754 struct regset_getset *dst = arg;
1755 struct task_struct *task = dst->target;
1756 elf_fpreg_t tmp[30];
1757 int index, min_copy, i;
1758
1759 if (unw_unwind_to_user(info) < 0)
1760 return;
1761
1762 /* Skip pos 0 and 1 */
1763 if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(2)) {
1764 dst->ret = user_regset_copyout_zero(&dst->pos, &dst->count,
1765 &dst->u.get.kbuf,
1766 &dst->u.get.ubuf,
1767 0, ELF_FP_OFFSET(2));
1768 if (dst->count == 0 || dst->ret)
1769 return;
1770 }
1771
1772 /* fr2-fr31 */
1773 if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(32)) {
1774 index = (dst->pos - ELF_FP_OFFSET(2)) / sizeof(elf_fpreg_t);
1775
1776 min_copy = min(((unsigned int)ELF_FP_OFFSET(32)),
1777 dst->pos + dst->count);
1778 for (i = dst->pos; i < min_copy; i += sizeof(elf_fpreg_t),
1779 index++)
1780 if (unw_get_fr(info, i / sizeof(elf_fpreg_t),
1781 &tmp[index])) {
1782 dst->ret = -EIO;
1783 return;
1784 }
1785 dst->ret = user_regset_copyout(&dst->pos, &dst->count,
1786 &dst->u.get.kbuf, &dst->u.get.ubuf, tmp,
1787 ELF_FP_OFFSET(2), ELF_FP_OFFSET(32));
1788 if (dst->count == 0 || dst->ret)
1789 return;
1790 }
1791
1792 /* fph */
1793 if (dst->count > 0) {
1794 ia64_flush_fph(dst->target);
1795 if (task->thread.flags & IA64_THREAD_FPH_VALID)
1796 dst->ret = user_regset_copyout(
1797 &dst->pos, &dst->count,
1798 &dst->u.get.kbuf, &dst->u.get.ubuf,
1799 &dst->target->thread.fph,
1800 ELF_FP_OFFSET(32), -1);
1801 else
1802 /* Zero fill instead. */
1803 dst->ret = user_regset_copyout_zero(
1804 &dst->pos, &dst->count,
1805 &dst->u.get.kbuf, &dst->u.get.ubuf,
1806 ELF_FP_OFFSET(32), -1);
1807 }
1808}
1809
1810void do_fpregs_set(struct unw_frame_info *info, void *arg)
1811{
1812 struct regset_getset *dst = arg;
1813 elf_fpreg_t fpreg, tmp[30];
1814 int index, start, end;
1815
1816 if (unw_unwind_to_user(info) < 0)
1817 return;
1818
1819 /* Skip pos 0 and 1 */
1820 if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(2)) {
1821 dst->ret = user_regset_copyin_ignore(&dst->pos, &dst->count,
1822 &dst->u.set.kbuf,
1823 &dst->u.set.ubuf,
1824 0, ELF_FP_OFFSET(2));
1825 if (dst->count == 0 || dst->ret)
1826 return;
1827 }
1828
1829 /* fr2-fr31 */
1830 if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(32)) {
1831 start = dst->pos;
1832 end = min(((unsigned int)ELF_FP_OFFSET(32)),
1833 dst->pos + dst->count);
1834 dst->ret = user_regset_copyin(&dst->pos, &dst->count,
1835 &dst->u.set.kbuf, &dst->u.set.ubuf, tmp,
1836 ELF_FP_OFFSET(2), ELF_FP_OFFSET(32));
1837 if (dst->ret)
1838 return;
1839
1840 if (start & 0xF) { /* only write high part */
1841 if (unw_get_fr(info, start / sizeof(elf_fpreg_t),
1842 &fpreg)) {
1843 dst->ret = -EIO;
1844 return;
1845 }
1846 tmp[start / sizeof(elf_fpreg_t) - 2].u.bits[0]
1847 = fpreg.u.bits[0];
1848 start &= ~0xFUL;
1849 }
1850 if (end & 0xF) { /* only write low part */
1851 if (unw_get_fr(info, end / sizeof(elf_fpreg_t),
1852 &fpreg)) {
1853 dst->ret = -EIO;
1854 return;
1855 }
1856 tmp[end / sizeof(elf_fpreg_t) - 2].u.bits[1]
1857 = fpreg.u.bits[1];
1858 end = (end + 0xF) & ~0xFUL;
1859 }
1860
1861 for ( ; start < end ; start += sizeof(elf_fpreg_t)) {
1862 index = start / sizeof(elf_fpreg_t);
1863 if (unw_set_fr(info, index, tmp[index - 2])) {
1864 dst->ret = -EIO;
1865 return;
1866 }
1867 }
1868 if (dst->ret || dst->count == 0)
1869 return;
1870 }
1871
1872 /* fph */
1873 if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(128)) {
1874 ia64_sync_fph(dst->target);
1875 dst->ret = user_regset_copyin(&dst->pos, &dst->count,
1876 &dst->u.set.kbuf,
1877 &dst->u.set.ubuf,
1878 &dst->target->thread.fph,
1879 ELF_FP_OFFSET(32), -1);
1880 }
1881}
1882
1883static int
1884do_regset_call(void (*call)(struct unw_frame_info *, void *),
1885 struct task_struct *target,
1886 const struct user_regset *regset,
1887 unsigned int pos, unsigned int count,
1888 const void *kbuf, const void __user *ubuf)
1889{
1890 struct regset_getset info = { .target = target, .regset = regset,
1891 .pos = pos, .count = count,
1892 .u.set = { .kbuf = kbuf, .ubuf = ubuf },
1893 .ret = 0 };
1894
1895 if (target == current)
1896 unw_init_running(call, &info);
1897 else {
1898 struct unw_frame_info ufi;
1899 memset(&ufi, 0, sizeof(ufi));
1900 unw_init_from_blocked_task(&ufi, target);
1901 (*call)(&ufi, &info);
1902 }
1903
1904 return info.ret;
1905}
1906
1907static int
1908gpregs_get(struct task_struct *target,
1909 const struct user_regset *regset,
1910 unsigned int pos, unsigned int count,
1911 void *kbuf, void __user *ubuf)
1912{
1913 return do_regset_call(do_gpregs_get, target, regset, pos, count,
1914 kbuf, ubuf);
1915}
1916
1917static int gpregs_set(struct task_struct *target,
1918 const struct user_regset *regset,
1919 unsigned int pos, unsigned int count,
1920 const void *kbuf, const void __user *ubuf)
1921{
1922 return do_regset_call(do_gpregs_set, target, regset, pos, count,
1923 kbuf, ubuf);
1924}
1925
1926static void do_gpregs_writeback(struct unw_frame_info *info, void *arg)
1927{
1928 do_sync_rbs(info, ia64_sync_user_rbs);
1929}
1930
1931/*
1932 * This is called to write back the register backing store.
1933 * ptrace does this before it stops, so that a tracer reading the user
1934 * memory after the thread stops will get the current register data.
1935 */
1936static int
1937gpregs_writeback(struct task_struct *target,
1938 const struct user_regset *regset,
1939 int now)
1940{
1941 if (test_and_set_tsk_thread_flag(target, TIF_RESTORE_RSE))
1942 return 0;
1943 tsk_set_notify_resume(target);
1944 return do_regset_call(do_gpregs_writeback, target, regset, 0, 0,
1945 NULL, NULL);
1946}
1947
1948static int
1949fpregs_active(struct task_struct *target, const struct user_regset *regset)
1950{
1951 return (target->thread.flags & IA64_THREAD_FPH_VALID) ? 128 : 32;
1952}
1953
1954static int fpregs_get(struct task_struct *target,
1955 const struct user_regset *regset,
1956 unsigned int pos, unsigned int count,
1957 void *kbuf, void __user *ubuf)
1958{
1959 return do_regset_call(do_fpregs_get, target, regset, pos, count,
1960 kbuf, ubuf);
1961}
1962
1963static int fpregs_set(struct task_struct *target,
1964 const struct user_regset *regset,
1965 unsigned int pos, unsigned int count,
1966 const void *kbuf, const void __user *ubuf)
1967{
1968 return do_regset_call(do_fpregs_set, target, regset, pos, count,
1969 kbuf, ubuf);
1970}
1971
1972static int
1973access_uarea(struct task_struct *child, unsigned long addr,
1974 unsigned long *data, int write_access)
1975{
1976 unsigned int pos = -1; /* an invalid value */
1977 int ret;
1978 unsigned long *ptr, regnum;
1979
1980 if ((addr & 0x7) != 0) {
1981 dprintk("ptrace: unaligned register address 0x%lx\n", addr);
1982 return -1;
1983 }
1984 if ((addr >= PT_NAT_BITS + 8 && addr < PT_F2) ||
1985 (addr >= PT_R7 + 8 && addr < PT_B1) ||
1986 (addr >= PT_AR_LC + 8 && addr < PT_CR_IPSR) ||
1987 (addr >= PT_AR_SSD + 8 && addr < PT_DBR)) {
1988 dprintk("ptrace: rejecting access to register "
1989 "address 0x%lx\n", addr);
1990 return -1;
1991 }
1992
1993 switch (addr) {
1994 case PT_F32 ... (PT_F127 + 15):
1995 pos = addr - PT_F32 + ELF_FP_OFFSET(32);
1996 break;
1997 case PT_F2 ... (PT_F5 + 15):
1998 pos = addr - PT_F2 + ELF_FP_OFFSET(2);
1999 break;
2000 case PT_F10 ... (PT_F31 + 15):
2001 pos = addr - PT_F10 + ELF_FP_OFFSET(10);
2002 break;
2003 case PT_F6 ... (PT_F9 + 15):
2004 pos = addr - PT_F6 + ELF_FP_OFFSET(6);
2005 break;
2006 }
2007
2008 if (pos != -1) {
2009 if (write_access)
2010 ret = fpregs_set(child, NULL, pos,
2011 sizeof(unsigned long), data, NULL);
2012 else
2013 ret = fpregs_get(child, NULL, pos,
2014 sizeof(unsigned long), data, NULL);
2015 if (ret != 0)
2016 return -1;
2017 return 0;
2018 }
2019
2020 switch (addr) {
2021 case PT_NAT_BITS:
2022 pos = ELF_NAT_OFFSET;
2023 break;
2024 case PT_R4 ... PT_R7:
2025 pos = addr - PT_R4 + ELF_GR_OFFSET(4);
2026 break;
2027 case PT_B1 ... PT_B5:
2028 pos = addr - PT_B1 + ELF_BR_OFFSET(1);
2029 break;
2030 case PT_AR_EC:
2031 pos = ELF_AR_EC_OFFSET;
2032 break;
2033 case PT_AR_LC:
2034 pos = ELF_AR_LC_OFFSET;
2035 break;
2036 case PT_CR_IPSR:
2037 pos = ELF_CR_IPSR_OFFSET;
2038 break;
2039 case PT_CR_IIP:
2040 pos = ELF_CR_IIP_OFFSET;
2041 break;
2042 case PT_CFM:
2043 pos = ELF_CFM_OFFSET;
2044 break;
2045 case PT_AR_UNAT:
2046 pos = ELF_AR_UNAT_OFFSET;
2047 break;
2048 case PT_AR_PFS:
2049 pos = ELF_AR_PFS_OFFSET;
2050 break;
2051 case PT_AR_RSC:
2052 pos = ELF_AR_RSC_OFFSET;
2053 break;
2054 case PT_AR_RNAT:
2055 pos = ELF_AR_RNAT_OFFSET;
2056 break;
2057 case PT_AR_BSPSTORE:
2058 pos = ELF_AR_BSPSTORE_OFFSET;
2059 break;
2060 case PT_PR:
2061 pos = ELF_PR_OFFSET;
2062 break;
2063 case PT_B6:
2064 pos = ELF_BR_OFFSET(6);
2065 break;
2066 case PT_AR_BSP:
2067 pos = ELF_AR_BSP_OFFSET;
2068 break;
2069 case PT_R1 ... PT_R3:
2070 pos = addr - PT_R1 + ELF_GR_OFFSET(1);
2071 break;
2072 case PT_R12 ... PT_R15:
2073 pos = addr - PT_R12 + ELF_GR_OFFSET(12);
2074 break;
2075 case PT_R8 ... PT_R11:
2076 pos = addr - PT_R8 + ELF_GR_OFFSET(8);
2077 break;
2078 case PT_R16 ... PT_R31:
2079 pos = addr - PT_R16 + ELF_GR_OFFSET(16);
2080 break;
2081 case PT_AR_CCV:
2082 pos = ELF_AR_CCV_OFFSET;
2083 break;
2084 case PT_AR_FPSR:
2085 pos = ELF_AR_FPSR_OFFSET;
2086 break;
2087 case PT_B0:
2088 pos = ELF_BR_OFFSET(0);
2089 break;
2090 case PT_B7:
2091 pos = ELF_BR_OFFSET(7);
2092 break;
2093 case PT_AR_CSD:
2094 pos = ELF_AR_CSD_OFFSET;
2095 break;
2096 case PT_AR_SSD:
2097 pos = ELF_AR_SSD_OFFSET;
2098 break;
2099 }
2100
2101 if (pos != -1) {
2102 if (write_access)
2103 ret = gpregs_set(child, NULL, pos,
2104 sizeof(unsigned long), data, NULL);
2105 else
2106 ret = gpregs_get(child, NULL, pos,
2107 sizeof(unsigned long), data, NULL);
2108 if (ret != 0)
2109 return -1;
2110 return 0;
2111 }
2112
2113 /* access debug registers */
2114 if (addr >= PT_IBR) {
2115 regnum = (addr - PT_IBR) >> 3;
2116 ptr = &child->thread.ibr[0];
2117 } else {
2118 regnum = (addr - PT_DBR) >> 3;
2119 ptr = &child->thread.dbr[0];
2120 }
2121
2122 if (regnum >= 8) {
2123 dprintk("ptrace: rejecting access to register "
2124 "address 0x%lx\n", addr);
2125 return -1;
2126 }
2127#ifdef CONFIG_PERFMON
2128 /*
2129 * Check if debug registers are used by perfmon. This
2130 * test must be done once we know that we can do the
2131 * operation, i.e. the arguments are all valid, but
2132 * before we start modifying the state.
2133 *
2134 * Perfmon needs to keep a count of how many processes
2135 * are trying to modify the debug registers for system
2136 * wide monitoring sessions.
2137 *
2138 * We also include read access here, because they may
2139 * cause the PMU-installed debug register state
2140 * (dbr[], ibr[]) to be reset. The two arrays are also
2141 * used by perfmon, but we do not use
2142 * IA64_THREAD_DBG_VALID. The registers are restored
2143 * by the PMU context switch code.
2144 */
2145 if (pfm_use_debug_registers(child))
2146 return -1;
2147#endif
2148
2149 if (!(child->thread.flags & IA64_THREAD_DBG_VALID)) {
2150 child->thread.flags |= IA64_THREAD_DBG_VALID;
2151 memset(child->thread.dbr, 0,
2152 sizeof(child->thread.dbr));
2153 memset(child->thread.ibr, 0,
2154 sizeof(child->thread.ibr));
2155 }
2156
2157 ptr += regnum;
2158
2159 if ((regnum & 1) && write_access) {
2160 /* don't let the user set kernel-level breakpoints: */
2161 *ptr = *data & ~(7UL << 56);
2162 return 0;
2163 }
2164 if (write_access)
2165 *ptr = *data;
2166 else
2167 *data = *ptr;
2168 return 0;
2169}
2170
2171static const struct user_regset native_regsets[] = {
2172 {
2173 .core_note_type = NT_PRSTATUS,
2174 .n = ELF_NGREG,
2175 .size = sizeof(elf_greg_t), .align = sizeof(elf_greg_t),
2176 .get = gpregs_get, .set = gpregs_set,
2177 .writeback = gpregs_writeback
2178 },
2179 {
2180 .core_note_type = NT_PRFPREG,
2181 .n = ELF_NFPREG,
2182 .size = sizeof(elf_fpreg_t), .align = sizeof(elf_fpreg_t),
2183 .get = fpregs_get, .set = fpregs_set, .active = fpregs_active
2184 },
2185};
2186
2187static const struct user_regset_view user_ia64_view = {
2188 .name = "ia64",
2189 .e_machine = EM_IA_64,
2190 .regsets = native_regsets, .n = ARRAY_SIZE(native_regsets)
2191};
2192
2193const struct user_regset_view *task_user_regset_view(struct task_struct *tsk)
2194{
2195#ifdef CONFIG_IA32_SUPPORT
2196 extern const struct user_regset_view user_ia32_view;
2197 if (IS_IA32_PROCESS(task_pt_regs(tsk)))
2198 return &user_ia32_view;
2199#endif
2200 return &user_ia64_view;
2201}
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 17fda5293c67..48e15a51782f 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -59,6 +59,84 @@ static struct clocksource clocksource_itc = {
59}; 59};
60static struct clocksource *itc_clocksource; 60static struct clocksource *itc_clocksource;
61 61
62#ifdef CONFIG_VIRT_CPU_ACCOUNTING
63
64#include <linux/kernel_stat.h>
65
66extern cputime_t cycle_to_cputime(u64 cyc);
67
68/*
69 * Called from the context switch with interrupts disabled, to charge all
70 * accumulated times to the current process, and to prepare accounting on
71 * the next process.
72 */
73void ia64_account_on_switch(struct task_struct *prev, struct task_struct *next)
74{
75 struct thread_info *pi = task_thread_info(prev);
76 struct thread_info *ni = task_thread_info(next);
77 cputime_t delta_stime, delta_utime;
78 __u64 now;
79
80 now = ia64_get_itc();
81
82 delta_stime = cycle_to_cputime(pi->ac_stime + (now - pi->ac_stamp));
83 account_system_time(prev, 0, delta_stime);
84 account_system_time_scaled(prev, delta_stime);
85
86 if (pi->ac_utime) {
87 delta_utime = cycle_to_cputime(pi->ac_utime);
88 account_user_time(prev, delta_utime);
89 account_user_time_scaled(prev, delta_utime);
90 }
91
92 pi->ac_stamp = ni->ac_stamp = now;
93 ni->ac_stime = ni->ac_utime = 0;
94}
95
96/*
97 * Account time for a transition between system, hard irq or soft irq state.
98 * Note that this function is called with interrupts enabled.
99 */
100void account_system_vtime(struct task_struct *tsk)
101{
102 struct thread_info *ti = task_thread_info(tsk);
103 unsigned long flags;
104 cputime_t delta_stime;
105 __u64 now;
106
107 local_irq_save(flags);
108
109 now = ia64_get_itc();
110
111 delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp));
112 account_system_time(tsk, 0, delta_stime);
113 account_system_time_scaled(tsk, delta_stime);
114 ti->ac_stime = 0;
115
116 ti->ac_stamp = now;
117
118 local_irq_restore(flags);
119}
120
121/*
122 * Called from the timer interrupt handler to charge accumulated user time
123 * to the current process. Must be called with interrupts disabled.
124 */
125void account_process_tick(struct task_struct *p, int user_tick)
126{
127 struct thread_info *ti = task_thread_info(p);
128 cputime_t delta_utime;
129
130 if (ti->ac_utime) {
131 delta_utime = cycle_to_cputime(ti->ac_utime);
132 account_user_time(p, delta_utime);
133 account_user_time_scaled(p, delta_utime);
134 ti->ac_utime = 0;
135 }
136}
137
138#endif /* CONFIG_VIRT_CPU_ACCOUNTING */
139
62static irqreturn_t 140static irqreturn_t
63timer_interrupt (int irq, void *dev_id) 141timer_interrupt (int irq, void *dev_id)
64{ 142{
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index e282c348dcde..53d0a8ee35d7 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -362,7 +362,12 @@ pci_acpi_scan_root(struct acpi_device *device, int domain, int bus)
362 info.name = name; 362 info.name = name;
363 acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window, 363 acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window,
364 &info); 364 &info);
365 365 /*
366 * See arch/x86/pci/acpi.c.
367 * The desired pci bus might already be scanned in a quirk. We
368 * should handle the case here, but it appears that IA64 hasn't
369 * such quirk. So we just ignore the case now.
370 */
366 pbus = pci_scan_bus_parented(NULL, bus, &pci_root_ops, controller); 371 pbus = pci_scan_bus_parented(NULL, bus, &pci_root_ops, controller);
367 if (pbus) 372 if (pbus)
368 pcibios_setup_root_windows(pbus, controller); 373 pcibios_setup_root_windows(pbus, controller);