182007Sjake/*- 282007Sjake * Copyright (c) 2001 Jake Burkholder. 382007Sjake * All rights reserved. 482007Sjake * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. All rights reserved. 582007Sjake * 682007Sjake * Redistribution and use in source and binary forms, with or without 782007Sjake * modification, are permitted provided that the following conditions 882007Sjake * are met: 982007Sjake * 1. Redistributions of source code must retain the above copyright 1082007Sjake * notice, this list of conditions and the following disclaimer. 1182007Sjake * 2. Redistributions in binary form must reproduce the above copyright 1282007Sjake * notice, this list of conditions and the following disclaimer in the 1382007Sjake * documentation and/or other materials provided with the distribution. 1482007Sjake * 1582007Sjake * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1682007Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1782007Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1882007Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1982007Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2082007Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2182007Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2282007Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2382007Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2482007Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2582007Sjake * SUCH DAMAGE. 2682007Sjake * 2782007Sjake * $FreeBSD$ 2882007Sjake */ 2982007Sjake 3082007Sjake#include <sys/param.h> 3182007Sjake 3282007Sjake#include <vm/vm.h> 3382007Sjake 3482007Sjake#include <machine/asi.h> 3582007Sjake#include <machine/cpufunc.h> 3682007Sjake#include <machine/lsu.h> 3782007Sjake#include <machine/watch.h> 3882007Sjake 3982007Sjake#include <ddb/ddb.h> 4082007Sjake#include <ddb/db_access.h> 4182007Sjake#include <ddb/db_sym.h> 4282007Sjake#include <ddb/db_variables.h> 4382007Sjake#include <ddb/db_watch.h> 4482007Sjake 4582007Sjakestatic void db_watch_print(vm_offset_t wp, int bm); 4682007Sjake 4782007Sjakeint 48113238Sjakewatch_phys_set_mask(vm_paddr_t pa, u_long mask) 4982007Sjake{ 5082007Sjake u_long lsucr; 5182007Sjake 5290621Stmm stxa_sync(AA_DMMU_PWPR, ASI_DMMU, pa & (((2UL << 38) - 1) << 3)); 5382007Sjake lsucr = ldxa(0, ASI_LSU_CTL_REG); 5482007Sjake lsucr = ((lsucr | LSU_PW) & ~LSU_PM_MASK) | 5582007Sjake (mask << LSU_PM_SHIFT); 5690621Stmm stxa_sync(0, ASI_LSU_CTL_REG, lsucr); 5782007Sjake return (0); 5882007Sjake} 5982007Sjake 6082007Sjakeint 61113238Sjakewatch_phys_set(vm_paddr_t pa, int sz) 6282007Sjake{ 6382007Sjake u_long off; 6482007Sjake 6582007Sjake off = (u_long)pa & 7; 6682007Sjake /* Test for misaligned watch points. */ 6782007Sjake if (off + sz > 8) 6882007Sjake return (-1); 6982007Sjake return (watch_phys_set_mask(pa, ((1 << sz) - 1) << off)); 7082007Sjake} 7182007Sjake 72113238Sjakevm_paddr_t 7382007Sjakewatch_phys_get(int *bm) 7482007Sjake{ 75113238Sjake vm_paddr_t pa; 7682007Sjake u_long lsucr; 7782007Sjake 7882007Sjake if (!watch_phys_active()) 7982007Sjake return (0); 8082007Sjake 8182007Sjake pa = ldxa(AA_DMMU_PWPR, ASI_DMMU); 8282007Sjake lsucr = ldxa(0, ASI_LSU_CTL_REG); 8382007Sjake *bm = (lsucr & LSU_PM_MASK) >> LSU_PM_SHIFT; 8482007Sjake 85113238Sjake return (pa); 8682007Sjake} 8782007Sjake 8882007Sjakevoid 8982007Sjakewatch_phys_clear() 9082007Sjake{ 9190621Stmm stxa_sync(0, ASI_LSU_CTL_REG, 9282007Sjake ldxa(0, ASI_LSU_CTL_REG) & ~LSU_PW); 9382007Sjake} 9482007Sjake 9582007Sjakeint 9682007Sjakewatch_phys_active() 9782007Sjake{ 9882007Sjake 9982007Sjake return (ldxa(0, ASI_LSU_CTL_REG) & LSU_PW); 10082007Sjake} 10182007Sjake 10282007Sjakeint 10382007Sjakewatch_virt_set_mask(vm_offset_t va, u_long mask) 10482007Sjake{ 10582007Sjake u_long lsucr; 10682007Sjake 10790621Stmm stxa_sync(AA_DMMU_VWPR, ASI_DMMU, va & (((2UL << 41) - 1) << 3)); 10882007Sjake lsucr = ldxa(0, ASI_LSU_CTL_REG); 10982007Sjake lsucr = ((lsucr | LSU_VW) & ~LSU_VM_MASK) | 11082007Sjake (mask << LSU_VM_SHIFT); 11190621Stmm stxa_sync(0, ASI_LSU_CTL_REG, lsucr); 11282007Sjake return (0); 11382007Sjake} 11482007Sjake 11582007Sjakeint 11682007Sjakewatch_virt_set(vm_offset_t va, int sz) 11782007Sjake{ 11882007Sjake u_long off; 11982007Sjake 12082007Sjake off = (u_long)va & 7; 12182007Sjake /* Test for misaligned watch points. */ 12282007Sjake if (off + sz > 8) 12382007Sjake return (-1); 12482007Sjake return (watch_virt_set_mask(va, ((1 << sz) - 1) << off)); 12582007Sjake} 12682007Sjake 12782007Sjakevm_offset_t 12882007Sjakewatch_virt_get(int *bm) 12982007Sjake{ 13082007Sjake u_long va; 13182007Sjake u_long lsucr; 13282007Sjake 13382007Sjake if (!watch_virt_active()) 13482007Sjake return (0); 13582007Sjake 13682007Sjake va = ldxa(AA_DMMU_VWPR, ASI_DMMU); 13782007Sjake lsucr = ldxa(0, ASI_LSU_CTL_REG); 13882007Sjake *bm = (lsucr & LSU_VM_MASK) >> LSU_VM_SHIFT; 13982007Sjake 14082007Sjake return ((vm_offset_t)va); 14182007Sjake} 14282007Sjake 14382007Sjakevoid 14482007Sjakewatch_virt_clear() 14582007Sjake{ 14690621Stmm stxa_sync(0, ASI_LSU_CTL_REG, 14782007Sjake ldxa(0, ASI_LSU_CTL_REG) & ~LSU_VW); 14882007Sjake} 14982007Sjake 15082007Sjakeint 15182007Sjakewatch_virt_active() 15282007Sjake{ 15382007Sjake 15482007Sjake return (ldxa(0, ASI_LSU_CTL_REG) & LSU_VW); 15582007Sjake} 15682007Sjake 15782007Sjakeint 15882007Sjakedb_md_set_watchpoint(db_expr_t addr, db_expr_t size) 15982007Sjake{ 16082007Sjake int dummy; 16182007Sjake 16282007Sjake if (watch_virt_active()) { 16382007Sjake db_printf("Overwriting previously active watch point at " 16482007Sjake "0x%lx\n", watch_virt_get(&dummy)); 16582007Sjake } 16682007Sjake return (watch_virt_set(addr, size)); 16782007Sjake} 16882007Sjake 16982007Sjakeint 17082007Sjakedb_md_clr_watchpoint(db_expr_t addr, db_expr_t size) 17182007Sjake{ 17282007Sjake 17382007Sjake watch_virt_clear(); 17482007Sjake return (0); 17582007Sjake} 17682007Sjake 17782007Sjakevoid 17882007Sjakedb_watch_print(vm_offset_t wp, int bm) 17982007Sjake{ 18082007Sjake int i; 18182007Sjake 18282007Sjake db_printf("\tat 0x%lx, active bytes: ", (u_long)wp); 18382007Sjake for (i = 0; i < 8; i++) { 18482007Sjake if ((bm & (1 << i)) != 0) 18582007Sjake db_printf("%d ", i); 18682007Sjake } 18782007Sjake if (bm == 0) 18882007Sjake db_printf("none"); 18982007Sjake db_printf("\n"); 19082007Sjake} 19182007Sjake 19282007Sjakevoid 19382007Sjakedb_md_list_watchpoints(void) 19482007Sjake{ 195113238Sjake vm_offset_t va; 196113238Sjake vm_paddr_t pa; 19782007Sjake int bm; 19882007Sjake 19982007Sjake db_printf("Physical address watchpoint:\n"); 20082007Sjake if (watch_phys_active()) { 201113238Sjake pa = watch_phys_get(&bm); 202113238Sjake db_watch_print(pa, bm); 20382007Sjake } else 20482007Sjake db_printf("\tnot active.\n"); 20582007Sjake db_printf("Virtual address watchpoint:\n"); 20682007Sjake if (watch_virt_active()) { 207113238Sjake va = watch_virt_get(&bm); 208113238Sjake db_watch_print(va, bm); 20982007Sjake } else 21082007Sjake db_printf("\tnot active.\n"); 21182007Sjake} 212