KVM
debug-sr.h
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2015 - ARM Ltd
4  * Author: Marc Zyngier <marc.zyngier@arm.com>
5  */
6 
7 #ifndef __ARM64_KVM_HYP_DEBUG_SR_H__
8 #define __ARM64_KVM_HYP_DEBUG_SR_H__
9 
10 #include <linux/compiler.h>
11 #include <linux/kvm_host.h>
12 
13 #include <asm/debug-monitors.h>
14 #include <asm/kvm_asm.h>
15 #include <asm/kvm_hyp.h>
16 #include <asm/kvm_mmu.h>
17 
18 #define read_debug(r,n) read_sysreg(r##n##_el1)
19 #define write_debug(v,r,n) write_sysreg(v, r##n##_el1)
20 
21 #define save_debug(ptr,reg,nr) \
22  switch (nr) { \
23  case 15: ptr[15] = read_debug(reg, 15); \
24  fallthrough; \
25  case 14: ptr[14] = read_debug(reg, 14); \
26  fallthrough; \
27  case 13: ptr[13] = read_debug(reg, 13); \
28  fallthrough; \
29  case 12: ptr[12] = read_debug(reg, 12); \
30  fallthrough; \
31  case 11: ptr[11] = read_debug(reg, 11); \
32  fallthrough; \
33  case 10: ptr[10] = read_debug(reg, 10); \
34  fallthrough; \
35  case 9: ptr[9] = read_debug(reg, 9); \
36  fallthrough; \
37  case 8: ptr[8] = read_debug(reg, 8); \
38  fallthrough; \
39  case 7: ptr[7] = read_debug(reg, 7); \
40  fallthrough; \
41  case 6: ptr[6] = read_debug(reg, 6); \
42  fallthrough; \
43  case 5: ptr[5] = read_debug(reg, 5); \
44  fallthrough; \
45  case 4: ptr[4] = read_debug(reg, 4); \
46  fallthrough; \
47  case 3: ptr[3] = read_debug(reg, 3); \
48  fallthrough; \
49  case 2: ptr[2] = read_debug(reg, 2); \
50  fallthrough; \
51  case 1: ptr[1] = read_debug(reg, 1); \
52  fallthrough; \
53  default: ptr[0] = read_debug(reg, 0); \
54  }
55 
56 #define restore_debug(ptr,reg,nr) \
57  switch (nr) { \
58  case 15: write_debug(ptr[15], reg, 15); \
59  fallthrough; \
60  case 14: write_debug(ptr[14], reg, 14); \
61  fallthrough; \
62  case 13: write_debug(ptr[13], reg, 13); \
63  fallthrough; \
64  case 12: write_debug(ptr[12], reg, 12); \
65  fallthrough; \
66  case 11: write_debug(ptr[11], reg, 11); \
67  fallthrough; \
68  case 10: write_debug(ptr[10], reg, 10); \
69  fallthrough; \
70  case 9: write_debug(ptr[9], reg, 9); \
71  fallthrough; \
72  case 8: write_debug(ptr[8], reg, 8); \
73  fallthrough; \
74  case 7: write_debug(ptr[7], reg, 7); \
75  fallthrough; \
76  case 6: write_debug(ptr[6], reg, 6); \
77  fallthrough; \
78  case 5: write_debug(ptr[5], reg, 5); \
79  fallthrough; \
80  case 4: write_debug(ptr[4], reg, 4); \
81  fallthrough; \
82  case 3: write_debug(ptr[3], reg, 3); \
83  fallthrough; \
84  case 2: write_debug(ptr[2], reg, 2); \
85  fallthrough; \
86  case 1: write_debug(ptr[1], reg, 1); \
87  fallthrough; \
88  default: write_debug(ptr[0], reg, 0); \
89  }
90 
91 static void __debug_save_state(struct kvm_guest_debug_arch *dbg,
92  struct kvm_cpu_context *ctxt)
93 {
94  u64 aa64dfr0;
95  int brps, wrps;
96 
97  aa64dfr0 = read_sysreg(id_aa64dfr0_el1);
98  brps = (aa64dfr0 >> 12) & 0xf;
99  wrps = (aa64dfr0 >> 20) & 0xf;
100 
101  save_debug(dbg->dbg_bcr, dbgbcr, brps);
102  save_debug(dbg->dbg_bvr, dbgbvr, brps);
103  save_debug(dbg->dbg_wcr, dbgwcr, wrps);
104  save_debug(dbg->dbg_wvr, dbgwvr, wrps);
105 
106  ctxt_sys_reg(ctxt, MDCCINT_EL1) = read_sysreg(mdccint_el1);
107 }
108 
109 static void __debug_restore_state(struct kvm_guest_debug_arch *dbg,
110  struct kvm_cpu_context *ctxt)
111 {
112  u64 aa64dfr0;
113  int brps, wrps;
114 
115  aa64dfr0 = read_sysreg(id_aa64dfr0_el1);
116 
117  brps = (aa64dfr0 >> 12) & 0xf;
118  wrps = (aa64dfr0 >> 20) & 0xf;
119 
120  restore_debug(dbg->dbg_bcr, dbgbcr, brps);
121  restore_debug(dbg->dbg_bvr, dbgbvr, brps);
122  restore_debug(dbg->dbg_wcr, dbgwcr, wrps);
123  restore_debug(dbg->dbg_wvr, dbgwvr, wrps);
124 
125  write_sysreg(ctxt_sys_reg(ctxt, MDCCINT_EL1), mdccint_el1);
126 }
127 
128 static inline void __debug_switch_to_guest_common(struct kvm_vcpu *vcpu)
129 {
130  struct kvm_cpu_context *host_ctxt;
131  struct kvm_cpu_context *guest_ctxt;
132  struct kvm_guest_debug_arch *host_dbg;
133  struct kvm_guest_debug_arch *guest_dbg;
134 
135  if (!vcpu_get_flag(vcpu, DEBUG_DIRTY))
136  return;
137 
138  host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
139  guest_ctxt = &vcpu->arch.ctxt;
140  host_dbg = &vcpu->arch.host_debug_state.regs;
141  guest_dbg = kern_hyp_va(vcpu->arch.debug_ptr);
142 
143  __debug_save_state(host_dbg, host_ctxt);
144  __debug_restore_state(guest_dbg, guest_ctxt);
145 }
146 
147 static inline void __debug_switch_to_host_common(struct kvm_vcpu *vcpu)
148 {
149  struct kvm_cpu_context *host_ctxt;
150  struct kvm_cpu_context *guest_ctxt;
151  struct kvm_guest_debug_arch *host_dbg;
152  struct kvm_guest_debug_arch *guest_dbg;
153 
154  if (!vcpu_get_flag(vcpu, DEBUG_DIRTY))
155  return;
156 
157  host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
158  guest_ctxt = &vcpu->arch.ctxt;
159  host_dbg = &vcpu->arch.host_debug_state.regs;
160  guest_dbg = kern_hyp_va(vcpu->arch.debug_ptr);
161 
162  __debug_save_state(guest_dbg, guest_ctxt);
163  __debug_restore_state(host_dbg, host_ctxt);
164 
165  vcpu_clear_flag(vcpu, DEBUG_DIRTY);
166 }
167 
168 #endif /* __ARM64_KVM_HYP_DEBUG_SR_H__ */
static void __debug_switch_to_host_common(struct kvm_vcpu *vcpu)
Definition: debug-sr.h:147
#define restore_debug(ptr, reg, nr)
Definition: debug-sr.h:56
static void __debug_restore_state(struct kvm_guest_debug_arch *dbg, struct kvm_cpu_context *ctxt)
Definition: debug-sr.h:109
#define save_debug(ptr, reg, nr)
Definition: debug-sr.h:21
static void __debug_switch_to_guest_common(struct kvm_vcpu *vcpu)
Definition: debug-sr.h:128
static void __debug_save_state(struct kvm_guest_debug_arch *dbg, struct kvm_cpu_context *ctxt)
Definition: debug-sr.h:91