1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright 2016-17 IBM Corp. 4 */ 5 6 #define pr_fmt(fmt) "vas: " fmt 7 8 #include <linux/types.h> 9 #include <linux/slab.h> 10 #include <linux/debugfs.h> 11 #include <linux/seq_file.h> 12 #include "vas.h" 13 14 static struct dentry *vas_debugfs; 15 16 static char *cop_to_str(int cop) 17 { 18 switch (cop) { 19 case VAS_COP_TYPE_FAULT: return "Fault"; 20 case VAS_COP_TYPE_842: return "NX-842 Normal Priority"; 21 case VAS_COP_TYPE_842_HIPRI: return "NX-842 High Priority"; 22 case VAS_COP_TYPE_GZIP: return "NX-GZIP Normal Priority"; 23 case VAS_COP_TYPE_GZIP_HIPRI: return "NX-GZIP High Priority"; 24 case VAS_COP_TYPE_FTW: return "Fast Thread-wakeup"; 25 default: return "Unknown"; 26 } 27 } 28 29 static int info_show(struct seq_file *s, void *private) 30 { 31 struct vas_window *window = s->private; 32 33 mutex_lock(&vas_mutex); 34 35 /* ensure window is not unmapped */ 36 if (!window->hvwc_map) 37 goto unlock; 38 39 seq_printf(s, "Type: %s, %s\n", cop_to_str(window->cop), 40 window->tx_win ? "Send" : "Receive"); 41 seq_printf(s, "Pid : %d\n", window->pid); 42 43 unlock: 44 mutex_unlock(&vas_mutex); 45 return 0; 46 } 47 48 DEFINE_SHOW_ATTRIBUTE(info); 49 50 static inline void print_reg(struct seq_file *s, struct vas_window *win, 51 char *name, u32 reg) 52 { 53 seq_printf(s, "0x%016llx %s\n", read_hvwc_reg(win, name, reg), name); 54 } 55 56 static int hvwc_show(struct seq_file *s, void *private) 57 { 58 struct vas_window *window = s->private; 59 60 mutex_lock(&vas_mutex); 61 62 /* ensure window is not unmapped */ 63 if (!window->hvwc_map) 64 goto unlock; 65 66 print_reg(s, window, VREG(LPID)); 67 print_reg(s, window, VREG(PID)); 68 print_reg(s, window, VREG(XLATE_MSR)); 69 print_reg(s, window, VREG(XLATE_LPCR)); 70 print_reg(s, window, VREG(XLATE_CTL)); 71 print_reg(s, window, VREG(AMR)); 72 print_reg(s, window, VREG(SEIDR)); 73 print_reg(s, window, VREG(FAULT_TX_WIN)); 74 print_reg(s, window, VREG(OSU_INTR_SRC_RA)); 75 print_reg(s, window, VREG(HV_INTR_SRC_RA)); 76 print_reg(s, window, VREG(PSWID)); 77 print_reg(s, window, VREG(LFIFO_BAR)); 78 print_reg(s, window, VREG(LDATA_STAMP_CTL)); 79 print_reg(s, window, VREG(LDMA_CACHE_CTL)); 80 print_reg(s, window, VREG(LRFIFO_PUSH)); 81 print_reg(s, window, VREG(CURR_MSG_COUNT)); 82 print_reg(s, window, VREG(LNOTIFY_AFTER_COUNT)); 83 print_reg(s, window, VREG(LRX_WCRED)); 84 print_reg(s, window, VREG(LRX_WCRED_ADDER)); 85 print_reg(s, window, VREG(TX_WCRED)); 86 print_reg(s, window, VREG(TX_WCRED_ADDER)); 87 print_reg(s, window, VREG(LFIFO_SIZE)); 88 print_reg(s, window, VREG(WINCTL)); 89 print_reg(s, window, VREG(WIN_STATUS)); 90 print_reg(s, window, VREG(WIN_CTX_CACHING_CTL)); 91 print_reg(s, window, VREG(TX_RSVD_BUF_COUNT)); 92 print_reg(s, window, VREG(LRFIFO_WIN_PTR)); 93 print_reg(s, window, VREG(LNOTIFY_CTL)); 94 print_reg(s, window, VREG(LNOTIFY_PID)); 95 print_reg(s, window, VREG(LNOTIFY_LPID)); 96 print_reg(s, window, VREG(LNOTIFY_TID)); 97 print_reg(s, window, VREG(LNOTIFY_SCOPE)); 98 print_reg(s, window, VREG(NX_UTIL_ADDER)); 99 unlock: 100 mutex_unlock(&vas_mutex); 101 return 0; 102 } 103 104 DEFINE_SHOW_ATTRIBUTE(hvwc); 105 106 void vas_window_free_dbgdir(struct vas_window *window) 107 { 108 if (window->dbgdir) { 109 debugfs_remove_recursive(window->dbgdir); 110 kfree(window->dbgname); 111 window->dbgdir = NULL; 112 window->dbgname = NULL; 113 } 114 } 115 116 void vas_window_init_dbgdir(struct vas_window *window) 117 { 118 struct dentry *f, *d; 119 120 if (!window->vinst->dbgdir) 121 return; 122 123 window->dbgname = kzalloc(16, GFP_KERNEL); 124 if (!window->dbgname) 125 return; 126 127 snprintf(window->dbgname, 16, "w%d", window->winid); 128 129 d = debugfs_create_dir(window->dbgname, window->vinst->dbgdir); 130 if (IS_ERR(d)) 131 goto free_name; 132 133 window->dbgdir = d; 134 135 f = debugfs_create_file("info", 0444, d, window, &info_fops); 136 if (IS_ERR(f)) 137 goto remove_dir; 138 139 f = debugfs_create_file("hvwc", 0444, d, window, &hvwc_fops); 140 if (IS_ERR(f)) 141 goto remove_dir; 142 143 return; 144 145 remove_dir: 146 debugfs_remove_recursive(window->dbgdir); 147 window->dbgdir = NULL; 148 149 free_name: 150 kfree(window->dbgname); 151 window->dbgname = NULL; 152 } 153 154 void vas_instance_init_dbgdir(struct vas_instance *vinst) 155 { 156 struct dentry *d; 157 158 vas_init_dbgdir(); 159 if (!vas_debugfs) 160 return; 161 162 vinst->dbgname = kzalloc(16, GFP_KERNEL); 163 if (!vinst->dbgname) 164 return; 165 166 snprintf(vinst->dbgname, 16, "v%d", vinst->vas_id); 167 168 d = debugfs_create_dir(vinst->dbgname, vas_debugfs); 169 if (IS_ERR(d)) 170 goto free_name; 171 172 vinst->dbgdir = d; 173 return; 174 175 free_name: 176 kfree(vinst->dbgname); 177 vinst->dbgname = NULL; 178 vinst->dbgdir = NULL; 179 } 180 181 /* 182 * Set up the "root" VAS debugfs dir. Return if we already set it up 183 * (or failed to) in an earlier instance of VAS. 184 */ 185 void vas_init_dbgdir(void) 186 { 187 static bool first_time = true; 188 189 if (!first_time) 190 return; 191 192 first_time = false; 193 vas_debugfs = debugfs_create_dir("vas", NULL); 194 if (IS_ERR(vas_debugfs)) 195 vas_debugfs = NULL; 196 } 197