166174Sbsd/* 266174Sbsd * Copyright 2000 Brian S. Dean <bsd@bsdhome.com> 366174Sbsd * All Rights Reserved. 466174Sbsd * 566174Sbsd * Redistribution and use in source and binary forms, with or without 666174Sbsd * modification, are permitted provided that the following conditions 766174Sbsd * are met: 866174Sbsd * 966174Sbsd * 1. Redistributions of source code must retain the above copyright 1066174Sbsd * notice, this list of conditions and the following disclaimer. 1166174Sbsd * 2. Redistributions in binary form must reproduce the above copyright 1266174Sbsd * notice, this list of conditions and the following disclaimer in the 1366174Sbsd * documentation and/or other materials provided with the distribution. 1466174Sbsd * 1566174Sbsd * THIS SOFTWARE IS PROVIDED BY BRIAN S. DEAN ``AS IS'' AND ANY 1666174Sbsd * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1766174Sbsd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1866174Sbsd * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BRIAN S. DEAN BE LIABLE 1966174Sbsd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2066174Sbsd * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 2166174Sbsd * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 2266174Sbsd * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 2366174Sbsd * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2466174Sbsd * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 2566174Sbsd * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 2666174Sbsd * DAMAGE. 2766174Sbsd */ 2866174Sbsd 2992986Sobrien#include <sys/cdefs.h> 3092986Sobrien__FBSDID("$FreeBSD: releng/10.2/lib/libc/i386/sys/i386_set_watch.c 105604 2002-10-21 03:47:22Z sam $"); 3166174Sbsd 3266174Sbsd#include <machine/reg.h> 3366174Sbsd#include <machine/sysarch.h> 3466174Sbsd 3566174Sbsdint 3666174Sbsdi386_set_watch(int watchnum, unsigned int watchaddr, int size, 3766174Sbsd int access, struct dbreg * d) 3866174Sbsd{ 3966174Sbsd int i; 4066174Sbsd unsigned int mask; 4166174Sbsd 4266174Sbsd if (watchnum == -1) { 4366174Sbsd for (i = 0, mask = 0x3; i < 4; i++, mask <<= 2) 44105604Ssam if ((DBREG_DRX(d,7) & mask) == 0) 4566174Sbsd break; 4666174Sbsd if (i < 4) 4766174Sbsd watchnum = i; 4866174Sbsd else 4966174Sbsd return -1; 5066174Sbsd } 5166174Sbsd 5266174Sbsd switch (access) { 5366174Sbsd case DBREG_DR7_EXEC: 5466174Sbsd size = 1; /* size must be 1 for an execution breakpoint */ 5566174Sbsd /* fall through */ 5666174Sbsd case DBREG_DR7_WRONLY: 5766174Sbsd case DBREG_DR7_RDWR: 5866174Sbsd break; 5966174Sbsd default : return -1; break; 6066174Sbsd } 6166174Sbsd 6266174Sbsd /* 6366174Sbsd * we can watch a 1, 2, or 4 byte sized location 6466174Sbsd */ 6566174Sbsd switch (size) { 6666174Sbsd case 1 : mask = 0x00; break; 6766174Sbsd case 2 : mask = 0x01 << 2; break; 6866174Sbsd case 4 : mask = 0x03 << 2; break; 6966174Sbsd default : return -1; break; 7066174Sbsd } 7166174Sbsd 7266174Sbsd mask |= access; 7366174Sbsd 7466174Sbsd /* clear the bits we are about to affect */ 75105604Ssam DBREG_DRX(d,7) &= ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16))); 7666174Sbsd 7766174Sbsd /* set drN register to the address, N=watchnum */ 7866174Sbsd DBREG_DRX(d,watchnum) = watchaddr; 7966174Sbsd 8066174Sbsd /* enable the watchpoint */ 81105604Ssam DBREG_DRX(d,7) |= (0x2 << (watchnum*2)) | (mask << (watchnum*4+16)); 8266174Sbsd 8366174Sbsd return watchnum; 8466174Sbsd} 85