1263323Smarcel/*- 2263323Smarcel * Copyright (c) 2014 Marcel Moolenaar 3263323Smarcel * All rights reserved. 4263323Smarcel * 5263323Smarcel * Redistribution and use in source and binary forms, with or without 6263323Smarcel * modification, are permitted provided that the following conditions 7263323Smarcel * are met: 8263323Smarcel * 1. Redistributions of source code must retain the above copyright 9263323Smarcel * notice, this list of conditions and the following disclaimer. 10263323Smarcel * 2. Redistributions in binary form must reproduce the above copyright 11263323Smarcel * notice, this list of conditions and the following disclaimer in the 12263323Smarcel * documentation and/or other materials provided with the distribution. 13263323Smarcel * 14263323Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15263323Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16263323Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17263323Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18263323Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19263323Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20263323Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21263323Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22263323Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23263323Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24263323Smarcel * SUCH DAMAGE. 25263323Smarcel */ 26263323Smarcel 27263323Smarcel#include "opt_ddb.h" 28263323Smarcel#include "opt_xtrace.h" 29263323Smarcel 30263323Smarcel#include <sys/cdefs.h> 31263323Smarcel__FBSDID("$FreeBSD: releng/10.3/sys/ia64/ia64/xtrace.c 271211 2014-09-06 22:17:54Z marcel $"); 32263323Smarcel 33263323Smarcel#include <sys/param.h> 34263323Smarcel#include <sys/systm.h> 35263323Smarcel#include <sys/kernel.h> 36263323Smarcel#include <sys/ktr.h> 37263323Smarcel#include <sys/malloc.h> 38263323Smarcel#include <sys/pcpu.h> 39263323Smarcel#include <machine/md_var.h> 40263323Smarcel#include <machine/pte.h> 41263323Smarcel#include <vm/vm.h> 42263323Smarcel#include <vm/vm_extern.h> 43263323Smarcel#include <vm/vm_kern.h> 44263323Smarcel 45263323Smarcel#define XTRACE_LOG2SZ 14 /* 16KB trace buffers */ 46263323Smarcel 47263323Smarcelstruct ia64_xtrace_record { 48263323Smarcel uint64_t ivt; 49263323Smarcel uint64_t itc; 50263323Smarcel uint64_t iip; 51263323Smarcel uint64_t ifa; 52263323Smarcel uint64_t isr; 53263323Smarcel uint64_t ipsr; 54263323Smarcel uint64_t itir; 55263323Smarcel uint64_t iipa; 56263323Smarcel 57263323Smarcel uint64_t ifs; 58263323Smarcel uint64_t iim; 59263323Smarcel uint64_t iha; 60263323Smarcel uint64_t unat; 61263323Smarcel uint64_t rsc; 62263323Smarcel uint64_t bsp; 63263323Smarcel uint64_t tp; 64263323Smarcel uint64_t sp; 65263323Smarcel}; 66263323Smarcel 67263323Smarcelextern uint32_t ia64_xtrace_enabled; 68263323Smarcelextern uint64_t ia64_xtrace_mask; 69263323Smarcel 70263323Smarcelstatic uint64_t ia64_xtrace_base; 71263323Smarcel 72263323Smarcelstatic void 73263323Smarcelia64_xtrace_init_common(vm_paddr_t pa) 74263323Smarcel{ 75263323Smarcel uint64_t psr; 76263323Smarcel pt_entry_t pte; 77263323Smarcel 78263323Smarcel pte = PTE_PRESENT | PTE_MA_WB | PTE_ACCESSED | PTE_DIRTY | 79263323Smarcel PTE_PL_KERN | PTE_AR_RW; 80263323Smarcel pte |= pa & PTE_PPN_MASK; 81263323Smarcel 82263323Smarcel __asm __volatile("ptr.d %0,%1" :: "r"(ia64_xtrace_base), 83263323Smarcel "r"(XTRACE_LOG2SZ << 2)); 84263323Smarcel 85263323Smarcel __asm __volatile("mov %0=psr" : "=r"(psr)); 86263323Smarcel __asm __volatile("rsm psr.ic|psr.i"); 87263323Smarcel ia64_srlz_i(); 88263323Smarcel 89263323Smarcel ia64_set_ifa(ia64_xtrace_base); 90263323Smarcel ia64_set_itir(XTRACE_LOG2SZ << 2); 91263323Smarcel ia64_srlz_d(); 92263323Smarcel __asm __volatile("itr.d dtr[%0]=%1" :: "r"(6), "r"(pte)); 93263323Smarcel 94263323Smarcel __asm __volatile("mov psr.l=%0" :: "r" (psr)); 95263323Smarcel ia64_srlz_i(); 96263323Smarcel 97271211Smarcel pcpup->pc_md.xtrace_tail = ia64_xtrace_base; 98263323Smarcel ia64_set_k3(ia64_xtrace_base); 99263323Smarcel} 100263323Smarcel 101263323Smarcelvoid * 102263323Smarcelia64_xtrace_alloc(void) 103263323Smarcel{ 104263323Smarcel uintptr_t buf; 105263323Smarcel size_t sz; 106263323Smarcel 107263323Smarcel sz = 1UL << XTRACE_LOG2SZ; 108263323Smarcel buf = kmem_alloc_contig(kernel_arena, sz, M_WAITOK | M_ZERO, 109263323Smarcel 0UL, ~0UL, sz, 0, VM_MEMATTR_DEFAULT); 110263323Smarcel return ((void *)buf); 111263323Smarcel} 112263323Smarcel 113263323Smarcelvoid 114263323Smarcelia64_xtrace_init_ap(void *buf) 115263323Smarcel{ 116263323Smarcel vm_paddr_t pa; 117263323Smarcel 118263323Smarcel if (buf == NULL) { 119263323Smarcel ia64_set_k3(0); 120263323Smarcel return; 121263323Smarcel } 122271211Smarcel pcpup->pc_md.xtrace_buffer = buf; 123263323Smarcel pa = ia64_tpa((uintptr_t)buf); 124263323Smarcel ia64_xtrace_init_common(pa); 125263323Smarcel} 126263323Smarcel 127263323Smarcelvoid 128263323Smarcelia64_xtrace_init_bsp(void) 129263323Smarcel{ 130263323Smarcel void *buf; 131263323Smarcel vm_paddr_t pa; 132263323Smarcel size_t sz; 133263323Smarcel 134263323Smarcel sz = 1UL << XTRACE_LOG2SZ; 135263323Smarcel ia64_xtrace_base = VM_MIN_KERNEL_ADDRESS + (sz << 1); 136263323Smarcel ia64_xtrace_mask = ~sz; 137263323Smarcel 138263323Smarcel buf = ia64_physmem_alloc(sz, sz); 139263323Smarcel if (buf == NULL) { 140263323Smarcel ia64_set_k3(0); 141263323Smarcel return; 142263323Smarcel } 143271211Smarcel pcpup->pc_md.xtrace_buffer = buf; 144263323Smarcel pa = IA64_RR_MASK((uintptr_t)buf); 145263323Smarcel ia64_xtrace_init_common(pa); 146263323Smarcel} 147263323Smarcel 148263323Smarcelstatic void 149263323Smarcelia64_xtrace_init(void *dummy __unused) 150263323Smarcel{ 151263323Smarcel 152263323Smarcel TUNABLE_INT_FETCH("machdep.xtrace.enabled", &ia64_xtrace_enabled); 153263323Smarcel} 154263323SmarcelSYSINIT(xtrace, SI_SUB_CPU, SI_ORDER_ANY, ia64_xtrace_init, NULL); 155263323Smarcel 156263323Smarcelvoid 157263323Smarcelia64_xtrace_save(void) 158263323Smarcel{ 159263323Smarcel struct ia64_xtrace_record *rec; 160263323Smarcel uint64_t head, tail; 161263323Smarcel 162263323Smarcel critical_enter(); 163263323Smarcel head = ia64_get_k3(); 164263323Smarcel tail = PCPU_GET(md.xtrace_tail); 165263323Smarcel if (head == 0 || tail == 0) { 166263323Smarcel critical_exit(); 167263323Smarcel return; 168263323Smarcel } 169263323Smarcel while (head != tail) { 170263323Smarcel rec = (void *)(uintptr_t)tail; 171263323Smarcel CTR6(KTR_TRAP, "XTRACE: itc=%lu, ticks=%d: " 172263323Smarcel "IVT=%#lx, IIP=%#lx, IFA=%#lx, ISR=%#lx", 173263323Smarcel rec->itc, ticks, 174263323Smarcel rec->ivt, rec->iip, rec->ifa, rec->isr); 175263323Smarcel tail += sizeof(*rec); 176263323Smarcel tail &= ia64_xtrace_mask; 177263323Smarcel } 178263323Smarcel PCPU_SET(md.xtrace_tail, tail); 179263323Smarcel critical_exit(); 180263323Smarcel} 181263323Smarcel 182263323Smarcelvoid 183263323Smarcelia64_xtrace_stop(void) 184263323Smarcel{ 185263323Smarcel ia64_xtrace_enabled = 0; 186263323Smarcel} 187263323Smarcel 188263323Smarcel#if 0 189263323Smarcel#ifdef DDB 190263323Smarcel 191263323Smarcel#include <ddb/ddb.h> 192263323Smarcel 193263323SmarcelDB_SHOW_COMMAND(xtrace, db_xtrace) 194263323Smarcel{ 195263323Smarcel struct ia64_xtrace_record *p, *r; 196263323Smarcel 197263323Smarcel p = (ia64_xtptr == 0) ? ia64_xtptr1 : ia64_xtptr; 198263323Smarcel if (p == 0) { 199263323Smarcel db_printf("Exception trace buffer not allocated\n"); 200263323Smarcel return; 201263323Smarcel } 202263323Smarcel 203263323Smarcel r = (p->ivt == 0) ? ia64_xtbase : p; 204263323Smarcel if (r->ivt == 0) { 205263323Smarcel db_printf("No exception trace records written\n"); 206263323Smarcel return; 207263323Smarcel } 208263323Smarcel 209263323Smarcel db_printf("IVT\t\t ITC\t\t IIP\t\t IFA\n"); 210263323Smarcel do { 211263323Smarcel db_printf("%016lx %016lx %016lx %016lx\n", 212263323Smarcel r->ivt, r->itc, r->iip, r->ifa); 213263323Smarcel r++; 214263323Smarcel if (r == ia64_xtlim) 215263323Smarcel r = ia64_xtbase; 216263323Smarcel } while (r != p); 217263323Smarcel} 218263323Smarcel 219263323Smarcel#endif /* DDB */ 220263323Smarcel#endif 221