]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/ia64/ia64/xtrace.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / ia64 / ia64 / xtrace.c
1 /*-
2  * Copyright (c) 2014 Marcel Moolenaar
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include "opt_ddb.h"
28 #include "opt_xtrace.h"
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/ktr.h>
37 #include <sys/malloc.h>
38 #include <sys/pcpu.h>
39 #include <machine/md_var.h>
40 #include <machine/pte.h>
41 #include <vm/vm.h>
42 #include <vm/vm_extern.h>
43 #include <vm/vm_kern.h>
44
45 #define XTRACE_LOG2SZ   14      /* 16KB trace buffers */
46
47 struct ia64_xtrace_record {
48         uint64_t        ivt;
49         uint64_t        itc;
50         uint64_t        iip;
51         uint64_t        ifa;
52         uint64_t        isr;
53         uint64_t        ipsr;
54         uint64_t        itir;
55         uint64_t        iipa;
56
57         uint64_t        ifs;
58         uint64_t        iim;
59         uint64_t        iha;
60         uint64_t        unat;
61         uint64_t        rsc;
62         uint64_t        bsp;
63         uint64_t        tp;
64         uint64_t        sp;
65 };
66
67 extern uint32_t ia64_xtrace_enabled;
68 extern uint64_t ia64_xtrace_mask;
69
70 static uint64_t ia64_xtrace_base;
71
72 static void
73 ia64_xtrace_init_common(vm_paddr_t pa)
74 {
75         uint64_t psr;
76         pt_entry_t pte;
77
78         pte = PTE_PRESENT | PTE_MA_WB | PTE_ACCESSED | PTE_DIRTY |
79             PTE_PL_KERN | PTE_AR_RW;
80         pte |= pa & PTE_PPN_MASK;
81
82         __asm __volatile("ptr.d %0,%1" :: "r"(ia64_xtrace_base),
83             "r"(XTRACE_LOG2SZ << 2));
84
85         __asm __volatile("mov   %0=psr" : "=r"(psr));
86         __asm __volatile("rsm   psr.ic|psr.i");
87         ia64_srlz_i();
88
89         ia64_set_ifa(ia64_xtrace_base);
90         ia64_set_itir(XTRACE_LOG2SZ << 2);
91         ia64_srlz_d();
92         __asm __volatile("itr.d dtr[%0]=%1" :: "r"(6), "r"(pte));
93
94         __asm __volatile("mov   psr.l=%0" :: "r" (psr));
95         ia64_srlz_i();
96
97         pcpup->pc_md.xtrace_tail = ia64_xtrace_base;
98         ia64_set_k3(ia64_xtrace_base);
99 }
100
101 void *
102 ia64_xtrace_alloc(void)
103 {
104         uintptr_t buf;
105         size_t sz;
106
107         sz = 1UL << XTRACE_LOG2SZ;
108         buf = kmem_alloc_contig(kernel_arena, sz, M_WAITOK | M_ZERO,
109             0UL, ~0UL, sz, 0, VM_MEMATTR_DEFAULT);
110         return ((void *)buf);
111 }
112
113 void
114 ia64_xtrace_init_ap(void *buf)
115 {
116         vm_paddr_t pa;
117
118         if (buf == NULL) {
119                 ia64_set_k3(0);
120                 return;
121         }
122         pcpup->pc_md.xtrace_buffer = buf;
123         pa = ia64_tpa((uintptr_t)buf);
124         ia64_xtrace_init_common(pa);
125 }
126
127 void
128 ia64_xtrace_init_bsp(void)
129 {
130         void *buf;
131         vm_paddr_t pa;
132         size_t sz;
133
134         sz = 1UL << XTRACE_LOG2SZ;
135         ia64_xtrace_base = VM_MIN_KERNEL_ADDRESS + (sz << 1);
136         ia64_xtrace_mask = ~sz;
137
138         buf = ia64_physmem_alloc(sz, sz);
139         if (buf == NULL) {
140                 ia64_set_k3(0);
141                 return;
142         }
143         pcpup->pc_md.xtrace_buffer = buf;
144         pa = IA64_RR_MASK((uintptr_t)buf);
145         ia64_xtrace_init_common(pa);
146 }
147
148 static void
149 ia64_xtrace_init(void *dummy __unused)
150 {
151
152         TUNABLE_INT_FETCH("machdep.xtrace.enabled", &ia64_xtrace_enabled);
153 }
154 SYSINIT(xtrace, SI_SUB_CPU, SI_ORDER_ANY, ia64_xtrace_init, NULL);
155
156 void
157 ia64_xtrace_save(void)
158 {
159         struct ia64_xtrace_record *rec;
160         uint64_t head, tail;
161
162         critical_enter();
163         head = ia64_get_k3();
164         tail = PCPU_GET(md.xtrace_tail);
165         if (head == 0 || tail == 0) {
166                 critical_exit();
167                 return;
168         }
169         while (head != tail) {
170                 rec = (void *)(uintptr_t)tail;
171                 CTR6(KTR_TRAP, "XTRACE: itc=%lu, ticks=%d: "
172                     "IVT=%#lx, IIP=%#lx, IFA=%#lx, ISR=%#lx",
173                     rec->itc, ticks,
174                     rec->ivt, rec->iip, rec->ifa, rec->isr);
175                 tail += sizeof(*rec);
176                 tail &= ia64_xtrace_mask;
177         }
178         PCPU_SET(md.xtrace_tail, tail);
179         critical_exit();
180 }
181
182 void
183 ia64_xtrace_stop(void)
184 {
185         ia64_xtrace_enabled = 0;
186 }
187
188 #if 0
189 #ifdef DDB
190
191 #include <ddb/ddb.h>
192
193 DB_SHOW_COMMAND(xtrace, db_xtrace)
194 {
195         struct ia64_xtrace_record *p, *r;
196
197         p = (ia64_xtptr == 0) ? ia64_xtptr1 : ia64_xtptr;
198         if (p == 0) {
199                 db_printf("Exception trace buffer not allocated\n");
200                 return;
201         }
202
203         r = (p->ivt == 0) ? ia64_xtbase : p;
204         if (r->ivt == 0) {
205                 db_printf("No exception trace records written\n");
206                 return;
207         }
208
209         db_printf("IVT\t\t ITC\t\t  IIP\t\t   IFA\n");
210         do {
211                 db_printf("%016lx %016lx %016lx %016lx\n",
212                     r->ivt, r->itc, r->iip, r->ifa);
213                 r++;
214                 if (r == ia64_xtlim)
215                         r = ia64_xtbase;
216         } while (r != p);
217 }
218
219 #endif /* DDB */
220 #endif