xtrace.c revision 268200
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: stable/10/sys/ia64/ia64/xtrace.c 268200 2014-07-02 23:47:43Z marcel $"); 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 47struct 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 67extern uint32_t ia64_xtrace_enabled; 68extern uint64_t ia64_xtrace_mask; 69 70static uint64_t ia64_xtrace_base; 71 72static void 73ia64_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 PCPU_SET(md.xtrace_tail, ia64_xtrace_base); 98 ia64_set_k3(ia64_xtrace_base); 99} 100 101void * 102ia64_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 113void 114ia64_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 PCPU_SET(md.xtrace_buffer, buf); 123 pa = ia64_tpa((uintptr_t)buf); 124 ia64_xtrace_init_common(pa); 125} 126 127void 128ia64_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 PCPU_SET(md.xtrace_buffer, buf); 144 pa = IA64_RR_MASK((uintptr_t)buf); 145 ia64_xtrace_init_common(pa); 146} 147 148static void 149ia64_xtrace_init(void *dummy __unused) 150{ 151 152 TUNABLE_INT_FETCH("machdep.xtrace.enabled", &ia64_xtrace_enabled); 153} 154SYSINIT(xtrace, SI_SUB_CPU, SI_ORDER_ANY, ia64_xtrace_init, NULL); 155 156void 157ia64_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 182void 183ia64_xtrace_stop(void) 184{ 185 ia64_xtrace_enabled = 0; 186} 187 188#if 0 189#ifdef DDB 190 191#include <ddb/ddb.h> 192 193DB_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 221