1*c2043483Smaxv /* $NetBSD: dbregs.h,v 1.8 2019/01/13 10:01:07 maxv Exp $ */ 2266caf90Skamil 32b859092Smaxv /* 4266caf90Skamil * Copyright (c) 2016 The NetBSD Foundation, Inc. 5266caf90Skamil * All rights reserved. 6266caf90Skamil * 7266caf90Skamil * Redistribution and use in source and binary forms, with or without 8266caf90Skamil * modification, are permitted provided that the following conditions 9266caf90Skamil * are met: 10266caf90Skamil * 1. Redistributions of source code must retain the above copyright 11266caf90Skamil * notice, this list of conditions and the following disclaimer. 12266caf90Skamil * 2. Redistributions in binary form must reproduce the above copyright 13266caf90Skamil * notice, this list of conditions and the following disclaimer in the 14266caf90Skamil * documentation and/or other materials provided with the distribution. 15266caf90Skamil * 16266caf90Skamil * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17266caf90Skamil * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18266caf90Skamil * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19266caf90Skamil * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20266caf90Skamil * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21266caf90Skamil * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22266caf90Skamil * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23266caf90Skamil * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24266caf90Skamil * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25266caf90Skamil * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26266caf90Skamil * POSSIBILITY OF SUCH DAMAGE. 27266caf90Skamil */ 28266caf90Skamil 29266caf90Skamil #ifndef _X86_DBREGS_H_ 30266caf90Skamil #define _X86_DBREGS_H_ 31266caf90Skamil 32241cf91dSkamil #include <sys/param.h> 33241cf91dSkamil #include <sys/types.h> 34988eb7edSkamil #include <machine/reg.h> 35266caf90Skamil 36241cf91dSkamil /* 37241cf91dSkamil * CPU Debug Status Register (DR6) 38241cf91dSkamil * 39241cf91dSkamil * Reserved bits: 4-12 and on x86_64 32-64 40241cf91dSkamil */ 41988eb7edSkamil #define X86_DR6_DR0_BREAKPOINT_CONDITION_DETECTED __BIT(0) 42988eb7edSkamil #define X86_DR6_DR1_BREAKPOINT_CONDITION_DETECTED __BIT(1) 43988eb7edSkamil #define X86_DR6_DR2_BREAKPOINT_CONDITION_DETECTED __BIT(2) 44988eb7edSkamil #define X86_DR6_DR3_BREAKPOINT_CONDITION_DETECTED __BIT(3) 45988eb7edSkamil #define X86_DR6_DEBUG_REGISTER_ACCESS_DETECTED __BIT(13) 46988eb7edSkamil #define X86_DR6_SINGLE_STEP __BIT(14) 47988eb7edSkamil #define X86_DR6_TASK_SWITCH __BIT(15) 48*c2043483Smaxv #define X86_DR6_MBZ __BITS(32, 63) 49266caf90Skamil 50241cf91dSkamil /* 51241cf91dSkamil * CPU Debug Control Register (DR7) 52241cf91dSkamil * 532b859092Smaxv * LOCAL_EXACT_BREAKPOINT and GLOBAL_EXACT_BREAKPOINT are no longer used 542b859092Smaxv * since the P6 processor family - portable code should set these bits 552b859092Smaxv * unconditionally in order to get exact breakpoints. 56241cf91dSkamil * 572b859092Smaxv * Reserved bits: 10, 12, 14-15 and on x86_64 32-64. 58241cf91dSkamil */ 59988eb7edSkamil #define X86_DR7_LOCAL_DR0_BREAKPOINT __BIT(0) 60988eb7edSkamil #define X86_DR7_GLOBAL_DR0_BREAKPOINT __BIT(1) 61988eb7edSkamil #define X86_DR7_LOCAL_DR1_BREAKPOINT __BIT(2) 62988eb7edSkamil #define X86_DR7_GLOBAL_DR1_BREAKPOINT __BIT(3) 63988eb7edSkamil #define X86_DR7_LOCAL_DR2_BREAKPOINT __BIT(4) 64988eb7edSkamil #define X86_DR7_GLOBAL_DR2_BREAKPOINT __BIT(5) 65988eb7edSkamil #define X86_DR7_LOCAL_DR3_BREAKPOINT __BIT(6) 66988eb7edSkamil #define X86_DR7_GLOBAL_DR3_BREAKPOINT __BIT(7) 67988eb7edSkamil #define X86_DR7_LOCAL_EXACT_BREAKPOINT __BIT(8) 68988eb7edSkamil #define X86_DR7_GLOBAL_EXACT_BREAKPOINT __BIT(9) 69988eb7edSkamil #define X86_DR7_RESTRICTED_TRANSACTIONAL_MEMORY __BIT(11) 70988eb7edSkamil #define X86_DR7_GENERAL_DETECT_ENABLE __BIT(13) 71988eb7edSkamil #define X86_DR7_DR0_CONDITION_MASK __BITS(16, 17) 72988eb7edSkamil #define X86_DR7_DR0_LENGTH_MASK __BITS(18, 19) 73988eb7edSkamil #define X86_DR7_DR1_CONDITION_MASK __BITS(20, 21) 74988eb7edSkamil #define X86_DR7_DR1_LENGTH_MASK __BITS(22, 23) 75988eb7edSkamil #define X86_DR7_DR2_CONDITION_MASK __BITS(24, 25) 76988eb7edSkamil #define X86_DR7_DR2_LENGTH_MASK __BITS(26, 27) 77988eb7edSkamil #define X86_DR7_DR3_CONDITION_MASK __BITS(28, 29) 78988eb7edSkamil #define X86_DR7_DR3_LENGTH_MASK __BITS(30, 31) 79*c2043483Smaxv #define X86_DR7_MBZ __BITS(32, 63) 80241cf91dSkamil 81241cf91dSkamil /* 822b859092Smaxv * X86_DR7_CONDITION_IO_READWRITE is currently unused. It requires DE 832b859092Smaxv * (debug extension) flag in control register CR4 set, and not all CPUs 842b859092Smaxv * support it. 85241cf91dSkamil */ 86988eb7edSkamil enum x86_dr7_condition { 87988eb7edSkamil X86_DR7_CONDITION_EXECUTION = 0x0, 88988eb7edSkamil X86_DR7_CONDITION_DATA_WRITE = 0x1, 89988eb7edSkamil X86_DR7_CONDITION_IO_READWRITE = 0x2, 90988eb7edSkamil X86_DR7_CONDITION_DATA_READWRITE = 0x3 91241cf91dSkamil }; 92241cf91dSkamil 93241cf91dSkamil /* 942b859092Smaxv * 0x2 is currently unimplemented - it reflects 8 bytes on modern CPUs. 95241cf91dSkamil */ 96988eb7edSkamil enum x86_dr7_length { 97988eb7edSkamil X86_DR7_LENGTH_BYTE = 0x0, 98988eb7edSkamil X86_DR7_LENGTH_TWOBYTES = 0x1, 99241cf91dSkamil /* 0x2 undefined */ 100988eb7edSkamil X86_DR7_LENGTH_FOURBYTES = 0x3 101241cf91dSkamil }; 102241cf91dSkamil 103ec5d7d9cSkamil /* 104988eb7edSkamil * The number of available watchpoint/breakpoint registers available since 105988eb7edSkamil * Intel 80386. New CPUs (x86_64) ship with up to 16 Debug Registers but they 106988eb7edSkamil * still offer the same number of watchpoints/breakpoints. 107ec5d7d9cSkamil */ 108988eb7edSkamil #define X86_DBREGS 4 109241cf91dSkamil 1102b859092Smaxv void x86_dbregs_init(void); 1112b859092Smaxv void x86_dbregs_clear(struct lwp *); 112d30a34e8Smaxv void x86_dbregs_abandon(struct lwp *); 1132b859092Smaxv void x86_dbregs_read(struct lwp *, struct dbreg *); 114b66992d6Smaxv 115b66992d6Smaxv void x86_dbregs_save(struct lwp *); 116b66992d6Smaxv void x86_dbregs_restore(struct lwp *); 117b66992d6Smaxv 1182b859092Smaxv void x86_dbregs_store_dr6(struct lwp *); 119988eb7edSkamil int x86_dbregs_user_trap(void); 1202b859092Smaxv int x86_dbregs_validate(const struct dbreg *); 1212b859092Smaxv void x86_dbregs_write(struct lwp *, const struct dbreg *); 122d30a34e8Smaxv void x86_dbregs_switch(struct lwp *, struct lwp *); 123241cf91dSkamil 124241cf91dSkamil #endif /* !_X86_DBREGS_H_ */ 125