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