Thu Mar 11 09:48:40 2021 UTC ()
- fixed a problem where hardware {break,watch}points other than #0 could not be cleared
- hardware {break,watch}point addresses are now strictly checked


(ryo)
diff -r1.37 -r1.38 src/sys/arch/aarch64/aarch64/db_machdep.c
diff -r1.12 -r1.13 src/sys/arch/aarch64/include/db_machdep.h

cvs diff -r1.37 -r1.38 src/sys/arch/aarch64/aarch64/db_machdep.c (expand / switch to unified diff)

--- src/sys/arch/aarch64/aarch64/db_machdep.c 2021/03/09 16:44:27 1.37
+++ src/sys/arch/aarch64/aarch64/db_machdep.c 2021/03/11 09:48:40 1.38
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: db_machdep.c,v 1.37 2021/03/09 16:44:27 ryo Exp $ */ 1/* $NetBSD: db_machdep.c,v 1.38 2021/03/11 09:48:40 ryo Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2014 The NetBSD Foundation, Inc. 4 * Copyright (c) 2014 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matt Thomas of 3am Software Foundry. 8 * by Matt Thomas of 3am Software Foundry.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -20,27 +20,27 @@ @@ -20,27 +20,27 @@
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: db_machdep.c,v 1.37 2021/03/09 16:44:27 ryo Exp $"); 33__KERNEL_RCSID(0, "$NetBSD: db_machdep.c,v 1.38 2021/03/11 09:48:40 ryo Exp $");
34 34
35#ifdef _KERNEL_OPT 35#ifdef _KERNEL_OPT
36#include "opt_compat_netbsd32.h" 36#include "opt_compat_netbsd32.h"
37#endif 37#endif
38 38
39#include <sys/param.h> 39#include <sys/param.h>
40#include <sys/systm.h> 40#include <sys/systm.h>
41#include <sys/atomic.h> 41#include <sys/atomic.h>
42#include <sys/cpu.h> 42#include <sys/cpu.h>
43#include <sys/lwp.h> 43#include <sys/lwp.h>
44#include <sys/intr.h> 44#include <sys/intr.h>
45 45
46#include <uvm/uvm.h> 46#include <uvm/uvm.h>
@@ -689,97 +689,114 @@ aarch64_set_wcr_wvr(int n, uint64_t wcr, @@ -689,97 +689,114 @@ aarch64_set_wcr_wvr(int n, uint64_t wcr,
689 case 15: DBG_WCR_WVR_SET(15, wcr, wvr); break; 689 case 15: DBG_WCR_WVR_SET(15, wcr, wvr); break;
690 } 690 }
691} 691}
692 692
693void 693void
694aarch64_breakpoint_set(int n, vaddr_t addr) 694aarch64_breakpoint_set(int n, vaddr_t addr)
695{ 695{
696 uint64_t bcr, bvr; 696 uint64_t bcr, bvr;
697 697
698 if (addr == 0) { 698 if (addr == 0) {
699 bvr = 0; 699 bvr = 0;
700 bcr = 0; 700 bcr = 0;
701 } else { 701 } else {
702 bvr = addr; 702 bvr = addr & DBGBVR_MASK;
703 bcr = 703 bcr =
704 __SHIFTIN(0, DBGBCR_BT) | 704 __SHIFTIN(0, DBGBCR_BT) |
705 __SHIFTIN(0, DBGBCR_LBN) | 705 __SHIFTIN(0, DBGBCR_LBN) |
706 __SHIFTIN(0, DBGBCR_SSC) | 706 __SHIFTIN(0, DBGBCR_SSC) |
707 __SHIFTIN(0, DBGBCR_HMC) | 707 __SHIFTIN(0, DBGBCR_HMC) |
708 __SHIFTIN(15, DBGBCR_BAS) | 708 __SHIFTIN(15, DBGBCR_BAS) |
709 __SHIFTIN(3, DBGBCR_PMC) | 709 __SHIFTIN(3, DBGBCR_PMC) |
710 __SHIFTIN(1, DBGBCR_E); 710 __SHIFTIN(1, DBGBCR_E);
711 } 711 }
712 712
713 aarch64_set_bcr_bvr(n, bcr, bvr); 713 aarch64_set_bcr_bvr(n, bcr, bvr);
714} 714}
715 715
716void 716void
717aarch64_watchpoint_set(int n, vaddr_t addr, int size, int accesstype) 717aarch64_watchpoint_set(int n, vaddr_t addr, u_int size, u_int accesstype)
718{ 718{
719 uint64_t wvr, wcr; 719 uint64_t wvr, wcr;
720 uint32_t matchbytebit; 720 uint32_t matchbytebit;
721 721
722 KASSERT(size <= 8); 722 KASSERT(size <= 8);
723 if (size > 8) 723 if (size > 8)
724 size = 8; 724 size = 8;
725 725
726 /* BAS must be all of whose set bits are contiguous */ 726 /*
 727 * It is always watched in 8byte units, and
 728 * BAS is a bit field of byte offset in 8byte units.
 729 */
727 matchbytebit = 0xff >> (8 - size); 730 matchbytebit = 0xff >> (8 - size);
728 matchbytebit <<= (addr & 7); 731 matchbytebit <<= (addr & 7);
 732 addr &= ~7UL;
729 733
730 /* load, store, or both */ 734 /* load, store, or both */
731 accesstype &= WATCHPOINT_ACCESS_MASK; 735 accesstype &= WATCHPOINT_ACCESS_MASK;
732 if (accesstype == 0) 736 if (accesstype == 0)
733 accesstype = WATCHPOINT_ACCESS_LOADSTORE; 737 accesstype = WATCHPOINT_ACCESS_LOADSTORE;
734 738
735 if (addr == 0) { 739 if (addr == 0) {
736 wvr = 0; 740 wvr = 0;
737 wcr = 0; 741 wcr = 0;
738 } else { 742 } else {
739 wvr = addr; 743 wvr = addr;
740 wcr = 744 wcr =
741 __SHIFTIN(0, DBGWCR_MASK) | /* MASK: no mask */ 745 __SHIFTIN(0, DBGWCR_MASK) | /* MASK: no mask */
742 __SHIFTIN(0, DBGWCR_WT) | /* WT: 0 */ 746 __SHIFTIN(0, DBGWCR_WT) | /* WT: 0 */
743 __SHIFTIN(0, DBGWCR_LBN) | /* LBN: 0 */ 747 __SHIFTIN(0, DBGWCR_LBN) | /* LBN: 0 */
744 __SHIFTIN(0, DBGWCR_SSC) | /* SSC: 00 */ 748 __SHIFTIN(0, DBGWCR_SSC) | /* SSC: 00 */
745 __SHIFTIN(0, DBGWCR_HMC) | /* HMC: 0 */ 749 __SHIFTIN(0, DBGWCR_HMC) | /* HMC: 0 */
746 __SHIFTIN(matchbytebit, DBGWCR_BAS) | /* BAS: 0-8byte */ 750 __SHIFTIN(matchbytebit, DBGWCR_BAS) | /* BAS: 0-8byte */
747 __SHIFTIN(accesstype, DBGWCR_LSC) | /* LSC: Load/Store */ 751 __SHIFTIN(accesstype, DBGWCR_LSC) | /* LSC: Load/Store */
748 __SHIFTIN(3, DBGWCR_PAC) | /* PAC: 11 */ 752 __SHIFTIN(3, DBGWCR_PAC) | /* PAC: 11 */
749 __SHIFTIN(1, DBGWCR_E); /* Enable */ 753 __SHIFTIN(1, DBGWCR_E); /* Enable */
750 } 754 }
751 755
752 aarch64_set_wcr_wvr(n, wcr, wvr); 756 aarch64_set_wcr_wvr(n, wcr, wvr);
753} 757}
754 758
755static void 759static int
756db_md_breakpoint_set(int n, vaddr_t addr) 760db_md_breakpoint_set(int n, vaddr_t addr)
757{ 761{
758 if (n >= __arraycount(breakpoint_buf)) 762 if (n >= __arraycount(breakpoint_buf))
759 return; 763 return -1;
 764
 765 if ((addr & 3) != 0) {
 766 db_printf("address must be 4bytes aligned\n");
 767 return -1;
 768 }
760 769
761 breakpoint_buf[n].addr = addr; 770 breakpoint_buf[n].addr = addr;
 771 return 0;
762} 772}
763 773
764static void 774static int
765db_md_watchpoint_set(int n, vaddr_t addr, int size, int accesstype) 775db_md_watchpoint_set(int n, vaddr_t addr, u_int size, u_int accesstype)
766{ 776{
767 if (n >= __arraycount(watchpoint_buf)) 777 if (n >= __arraycount(watchpoint_buf))
768 return; 778 return -1;
 779
 780 if (size != 0 && ((addr) & ~7UL) != ((addr + size - 1) & ~7UL)) {
 781 db_printf(
 782 "address and size must fit within a block of 8bytes\n");
 783 return -1;
 784 }
769 785
770 watchpoint_buf[n].addr = addr; 786 watchpoint_buf[n].addr = addr;
771 watchpoint_buf[n].size = size; 787 watchpoint_buf[n].size = size;
772 watchpoint_buf[n].accesstype = accesstype; 788 watchpoint_buf[n].accesstype = accesstype;
 789 return 0;
773} 790}
774 791
775static void 792static void
776db_md_breakwatchpoints_clear(void) 793db_md_breakwatchpoints_clear(void)
777{ 794{
778 int i; 795 int i;
779 796
780 for (i = 0; i <= max_breakpoint; i++) 797 for (i = 0; i <= max_breakpoint; i++)
781 aarch64_breakpoint_set(i, 0); 798 aarch64_breakpoint_set(i, 0);
782 for (i = 0; i <= max_watchpoint; i++) 799 for (i = 0; i <= max_watchpoint; i++)
783 aarch64_watchpoint_set(i, 0, 0, 0); 800 aarch64_watchpoint_set(i, 0, 0, 0);
784} 801}
785 802
@@ -883,87 +900,87 @@ show_watchpoints(void) @@ -883,87 +900,87 @@ show_watchpoints(void)
883 break; 900 break;
884 } 901 }
885 db_printf("\n"); 902 db_printf("\n");
886 nused++; 903 nused++;
887 } 904 }
888 } 905 }
889 db_printf("watchpoint used %d/%d\n", nused, max_watchpoint + 1); 906 db_printf("watchpoint used %d/%d\n", nused, max_watchpoint + 1);
890} 907}
891 908
892void 909void
893db_md_break_cmd(db_expr_t addr, bool have_addr, db_expr_t count, 910db_md_break_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
894 const char *modif) 911 const char *modif)
895{ 912{
896 int i; 913 int i, rc;
897 int added, cleared; 914 int added, cleared;
898 915
899 if (!have_addr) { 916 if (!have_addr) {
900 show_breakpoints(); 917 show_breakpoints();
901 return; 918 return;
902 } 919 }
903 920
904 addr &= DBGBVR_MASK; 
905 added = -1; 921 added = -1;
906 cleared = -1; 922 cleared = -1;
907 if (0 <= addr && addr <= max_breakpoint) { 923 if (0 <= addr && addr <= max_breakpoint) {
908 i = addr; 924 i = addr;
909 if (breakpoint_buf[i].addr != 0) { 925 if (breakpoint_buf[i].addr != 0) {
910 db_md_breakpoint_set(i, 0); 926 db_md_breakpoint_set(i, 0);
911 cleared = i; 927 cleared = i;
912 } 928 }
913 } else { 929 } else {
914 for (i = 0; i <= max_breakpoint; i++) { 930 for (i = 0; i <= max_breakpoint; i++) {
915 if (breakpoint_buf[i].addr == addr) { 931 if (breakpoint_buf[i].addr == addr) {
916 db_md_breakpoint_set(i, 0); 932 db_md_breakpoint_set(i, 0);
917 cleared = i; 933 cleared = i;
918 } 934 }
919 } 935 }
920 if (cleared == -1) { 936 if (cleared == -1) {
921 for (i = 0; i <= max_breakpoint; i++) { 937 for (i = 0; i <= max_breakpoint; i++) {
922 if (breakpoint_buf[i].addr == 0) { 938 if (breakpoint_buf[i].addr == 0) {
923 db_md_breakpoint_set(i, addr); 939 rc = db_md_breakpoint_set(i, addr);
 940 if (rc != 0)
 941 return;
924 added = i; 942 added = i;
925 break; 943 break;
926 } 944 }
927 } 945 }
928 if (i > max_breakpoint) { 946 if (i > max_breakpoint) {
929 db_printf("no more available breakpoint\n"); 947 db_printf("no more available breakpoint\n");
930 } 948 }
931 } 949 }
932 } 950 }
933 951
934 if (added >= 0) 952 if (added >= 0)
935 db_printf("add breakpoint %d as %016"DDB_EXPR_FMT"x\n", 953 db_printf("add breakpoint %d as %016"DDB_EXPR_FMT"x\n",
936 added, addr); 954 added, addr);
937 if (cleared >= 0) 955 if (cleared >= 0)
938 db_printf("clear breakpoint %d\n", cleared); 956 db_printf("clear breakpoint %d\n", cleared);
939 957
940 show_breakpoints(); 958 show_breakpoints();
941} 959}
942 960
943void 961void
944db_md_watch_cmd(db_expr_t addr, bool have_addr, db_expr_t count, 962db_md_watch_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
945 const char *modif) 963 const char *modif)
946{ 964{
947 int i; 965 int i, rc;
948 int added, cleared; 966 int added, cleared;
949 int accesstype, watchsize; 967 u_int accesstype, watchsize;
950 968
951 if (!have_addr) { 969 if (!have_addr) {
952 show_watchpoints(); 970 show_watchpoints();
953 return; 971 return;
954 } 972 }
955 973
956 addr &= DBGWVR_MASK; 
957 accesstype = watchsize = 0; 974 accesstype = watchsize = 0;
958 if ((modif != NULL) && (*modif != '\0')) { 975 if ((modif != NULL) && (*modif != '\0')) {
959 int ch; 976 int ch;
960 for (; *modif != '\0'; modif++) { 977 for (; *modif != '\0'; modif++) {
961 ch = *modif; 978 ch = *modif;
962 979
963 switch (ch) { 980 switch (ch) {
964 case '1': 981 case '1':
965 case '2': 982 case '2':
966 case '3': 983 case '3':
967 case '4': 984 case '4':
968 case '5': 985 case '5':
969 case '6': 986 case '6':
@@ -993,28 +1010,30 @@ db_md_watch_cmd(db_expr_t addr, bool hav @@ -993,28 +1010,30 @@ db_md_watch_cmd(db_expr_t addr, bool hav
993 db_md_watchpoint_set(i, 0, 0, 0); 1010 db_md_watchpoint_set(i, 0, 0, 0);
994 cleared = i; 1011 cleared = i;
995 } 1012 }
996 } else { 1013 } else {
997 for (i = 0; i <= max_watchpoint; i++) { 1014 for (i = 0; i <= max_watchpoint; i++) {
998 if (watchpoint_buf[i].addr == addr) { 1015 if (watchpoint_buf[i].addr == addr) {
999 db_md_watchpoint_set(i, 0, 0, 0); 1016 db_md_watchpoint_set(i, 0, 0, 0);
1000 cleared = i; 1017 cleared = i;
1001 } 1018 }
1002 } 1019 }
1003 if (cleared == -1) { 1020 if (cleared == -1) {
1004 for (i = 0; i <= max_watchpoint; i++) { 1021 for (i = 0; i <= max_watchpoint; i++) {
1005 if (watchpoint_buf[i].addr == 0) { 1022 if (watchpoint_buf[i].addr == 0) {
1006 db_md_watchpoint_set(i, addr, watchsize, 1023 rc = db_md_watchpoint_set(i, addr,
1007 accesstype); 1024 watchsize, accesstype);
 1025 if (rc != 0)
 1026 return;
1008 added = i; 1027 added = i;
1009 break; 1028 break;
1010 } 1029 }
1011 } 1030 }
1012 if (i > max_watchpoint) { 1031 if (i > max_watchpoint) {
1013 db_printf("no more available watchpoint\n"); 1032 db_printf("no more available watchpoint\n");
1014 } 1033 }
1015 } 1034 }
1016 } 1035 }
1017 1036
1018 if (added >= 0) 1037 if (added >= 0)
1019 db_printf("add watchpoint %d as %016"DDB_EXPR_FMT"x\n", 1038 db_printf("add watchpoint %d as %016"DDB_EXPR_FMT"x\n",
1020 added, addr); 1039 added, addr);

cvs diff -r1.12 -r1.13 src/sys/arch/aarch64/include/db_machdep.h (expand / switch to unified diff)

--- src/sys/arch/aarch64/include/db_machdep.h 2021/03/09 16:44:27 1.12
+++ src/sys/arch/aarch64/include/db_machdep.h 2021/03/11 09:48:40 1.13
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: db_machdep.h,v 1.12 2021/03/09 16:44:27 ryo Exp $ */ 1/* $NetBSD: db_machdep.h,v 1.13 2021/03/11 09:48:40 ryo Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2014 The NetBSD Foundation, Inc. 4 * Copyright (c) 2014 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matt Thomas of 3am Software Foundry. 8 * by Matt Thomas of 3am Software Foundry.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -208,27 +208,27 @@ db_addr_t db_branch_taken(db_expr_t, db_ @@ -208,27 +208,27 @@ db_addr_t db_branch_taken(db_expr_t, db_
208#define inst_unconditional_flow_transfer(ins) \ 208#define inst_unconditional_flow_transfer(ins) \
209 db_inst_unconditional_flow_transfer(ins) 209 db_inst_unconditional_flow_transfer(ins)
210 210
211#endif /* SOFTWARE_SSTEP */ 211#endif /* SOFTWARE_SSTEP */
212 212
213#define DB_MACHINE_COMMANDS 213#define DB_MACHINE_COMMANDS
214void dump_trapframe(struct trapframe *, void (*)(const char *, ...)); 214void dump_trapframe(struct trapframe *, void (*)(const char *, ...));
215void dump_switchframe(struct trapframe *, void (*)(const char *, ...)); 215void dump_switchframe(struct trapframe *, void (*)(const char *, ...));
216const char *strdisasm(vaddr_t, uint64_t); 216const char *strdisasm(vaddr_t, uint64_t);
217void db_machdep_init(void); 217void db_machdep_init(void);
218 218
219/* hardware breakpoint/watchpoint functions */ 219/* hardware breakpoint/watchpoint functions */
220void aarch64_breakpoint_set(int, vaddr_t); 220void aarch64_breakpoint_set(int, vaddr_t);
221void aarch64_watchpoint_set(int, vaddr_t, int, int); 221void aarch64_watchpoint_set(int, vaddr_t, u_int, u_int);
222#define WATCHPOINT_ACCESS_LOAD 0x01 222#define WATCHPOINT_ACCESS_LOAD 0x01
223#define WATCHPOINT_ACCESS_STORE 0x02 223#define WATCHPOINT_ACCESS_STORE 0x02
224#define WATCHPOINT_ACCESS_LOADSTORE 0x03 224#define WATCHPOINT_ACCESS_LOADSTORE 0x03
225#define WATCHPOINT_ACCESS_MASK 0x03 225#define WATCHPOINT_ACCESS_MASK 0x03
226 226
227#define DB_ELF_SYMBOLS 227#define DB_ELF_SYMBOLS
228 228
229#elif defined(__arm__) 229#elif defined(__arm__)
230 230
231#include <arm/db_machdep.h> 231#include <arm/db_machdep.h>
232 232
233#endif 233#endif
234 234