1 // © 2021 Qualcomm Innovation Center, Inc. All rights reserved.
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4
5 #include <assert.h>
6 #include <hyptypes.h>
7
8 #include <hypregisters.h>
9
10 #include <cpulocal.h>
11
12 #include <events/debug.h>
13
14 #include <asm/barrier.h>
15
16 #include "debug_bps.h"
17 #include "event_handlers.h"
18
19 static asm_ordering_dummy_t debug_asm_order;
20
21 static void
debug_os_unlock(void)22 debug_os_unlock(void)
23 {
24 OSLAR_EL1_t oslar = OSLAR_EL1_default();
25 OSLAR_EL1_set_oslk(&oslar, false);
26 register_OSLAR_EL1_write_ordered(oslar, &debug_asm_order);
27 OSDLR_EL1_t osdlr = OSDLR_EL1_default();
28 OSDLR_EL1_set_dlk(&osdlr, false);
29 register_OSDLR_EL1_write_ordered(osdlr, &debug_asm_order);
30 asm_context_sync_ordered(&debug_asm_order);
31 }
32
33 void
debug_handle_boot_cpu_warm_init(void)34 debug_handle_boot_cpu_warm_init(void)
35 {
36 debug_os_unlock();
37 }
38
39 #if PLATFORM_DEBUG_SAVE_STATE
40
41 CPULOCAL_DECLARE_STATIC(debug_ext_state_t, debug_ext_state);
42
43 static void
debug_os_lock(void)44 debug_os_lock(void)
45 {
46 OSLAR_EL1_t oslar = OSLAR_EL1_default();
47 OSLAR_EL1_set_oslk(&oslar, true);
48 register_OSLAR_EL1_write_ordered(oslar, &debug_asm_order);
49 asm_context_sync_ordered(&debug_asm_order);
50 }
51
52 static inline bool
debug_force_save_ext(void)53 debug_force_save_ext(void)
54 {
55 return PLATFORM_DEBUG_SAVE_STATE > 1U;
56 }
57
58 void
debug_handle_power_cpu_offline(void)59 debug_handle_power_cpu_offline(void)
60 {
61 (void)debug_handle_power_cpu_suspend(true);
62 }
63
64 error_t
debug_handle_power_cpu_suspend(bool may_poweroff)65 debug_handle_power_cpu_suspend(bool may_poweroff)
66 {
67 if (may_poweroff) {
68 debug_ext_state_t *state = &CPULOCAL(debug_ext_state);
69
70 debug_os_lock();
71
72 #if defined(PLATFORM_HAS_NO_DBGCLAIM_EL1) && PLATFORM_HAS_NO_DBGCLAIM_EL1
73 state->dbgclaim = DBGCLAIM_EL1_default();
74 #else
75 state->dbgclaim =
76 register_DBGCLAIMCLR_EL1_read_ordered(&debug_asm_order);
77 #endif
78
79 if (debug_force_save_ext() ||
80 DBGCLAIM_EL1_get_debug_ext(&state->dbgclaim)) {
81 state->mdccint = register_MDCCINT_EL1_read_ordered(
82 &debug_asm_order);
83 debug_save_common(&state->common, &debug_asm_order);
84 state->dtrrx = register_OSDTRRX_EL1_read_ordered(
85 &debug_asm_order);
86 state->dtrtx = register_OSDTRTX_EL1_read_ordered(
87 &debug_asm_order);
88 state->eccr = register_OSECCR_EL1_read_ordered(
89 &debug_asm_order);
90 }
91 }
92
93 return OK;
94 }
95
96 void
debug_unwind_power_cpu_suspend(bool may_poweroff)97 debug_unwind_power_cpu_suspend(bool may_poweroff)
98 {
99 if (may_poweroff) {
100 debug_os_unlock();
101 }
102 }
103
104 void
debug_handle_power_cpu_resume(bool was_poweroff)105 debug_handle_power_cpu_resume(bool was_poweroff)
106 {
107 if (was_poweroff) {
108 debug_ext_state_t *state = &CPULOCAL(debug_ext_state);
109
110 if (debug_force_save_ext() ||
111 DBGCLAIM_EL1_get_debug_ext(&state->dbgclaim)) {
112 // Lock just in case; the lock should already be set
113 debug_os_lock();
114
115 register_DBGCLAIMSET_EL1_write_ordered(
116 state->dbgclaim, &debug_asm_order);
117 register_MDCCINT_EL1_write_ordered(state->mdccint,
118 &debug_asm_order);
119 debug_load_common(&state->common, &debug_asm_order);
120 register_OSDTRRX_EL1_write_ordered(state->dtrrx,
121 &debug_asm_order);
122 register_OSDTRTX_EL1_write_ordered(state->dtrtx,
123 &debug_asm_order);
124 register_OSECCR_EL1_write_ordered(state->eccr,
125 &debug_asm_order);
126 asm_context_sync_ordered(&debug_asm_order);
127 }
128 }
129
130 debug_os_unlock();
131 }
132 #endif
133