1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Xen hypercall batching. 4 * 5 * Xen allows multiple hypercalls to be issued at once, using the 6 * multicall interface. This allows the cost of trapping into the 7 * hypervisor to be amortized over several calls. 8 * 9 * This file implements a simple interface for multicalls. There's a 10 * per-cpu buffer of outstanding multicalls. When you want to queue a 11 * multicall for issuing, you can allocate a multicall slot for the 12 * call and its arguments, along with storage for space which is 13 * pointed to by the arguments (for passing pointers to structures, 14 * etc). When the multicall is actually issued, all the space for the 15 * commands and allocated memory is freed for reuse. 16 * 17 * Multicalls are flushed whenever any of the buffers get full, or 18 * when explicitly requested. There's no way to get per-multicall 19 * return results back. It will BUG if any of the multicalls fail. 20 * 21 * Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007 22 */ 23 #include <linux/percpu.h> 24 #include <linux/hardirq.h> 25 #include <linux/debugfs.h> 26 #include <linux/jump_label.h> 27 #include <linux/printk.h> 28 29 #include <asm/xen/hypercall.h> 30 31 #include "xen-ops.h" 32 33 #define MC_BATCH 32 34 35 #define MC_ARGS (MC_BATCH * 16) 36 37 38 struct mc_buffer { 39 unsigned mcidx, argidx, cbidx; 40 struct multicall_entry entries[MC_BATCH]; 41 unsigned char args[MC_ARGS]; 42 struct callback { 43 void (*fn)(void *); 44 void *data; 45 } callbacks[MC_BATCH]; 46 }; 47 48 struct mc_debug_data { 49 struct multicall_entry entries[MC_BATCH]; 50 void *caller[MC_BATCH]; 51 size_t argsz[MC_BATCH]; 52 unsigned long *args[MC_BATCH]; 53 }; 54 55 static DEFINE_PER_CPU(struct mc_buffer, mc_buffer); 56 static struct mc_debug_data mc_debug_data_early __initdata; 57 static DEFINE_PER_CPU(struct mc_debug_data *, mc_debug_data) = 58 &mc_debug_data_early; 59 static struct mc_debug_data __percpu *mc_debug_data_ptr; 60 DEFINE_PER_CPU(unsigned long, xen_mc_irq_flags); 61 62 static struct static_key mc_debug __ro_after_init; 63 static bool mc_debug_enabled __initdata; 64 65 static int __init xen_parse_mc_debug(char *arg) 66 { 67 mc_debug_enabled = true; 68 static_key_slow_inc(&mc_debug); 69 70 return 0; 71 } 72 early_param("xen_mc_debug", xen_parse_mc_debug); 73 74 void mc_percpu_init(unsigned int cpu) 75 { 76 per_cpu(mc_debug_data, cpu) = per_cpu_ptr(mc_debug_data_ptr, cpu); 77 } 78 79 static int __init mc_debug_enable(void) 80 { 81 unsigned long flags; 82 83 if (!mc_debug_enabled) 84 return 0; 85 86 mc_debug_data_ptr = alloc_percpu(struct mc_debug_data); 87 if (!mc_debug_data_ptr) { 88 pr_err("xen_mc_debug inactive\n"); 89 static_key_slow_dec(&mc_debug); 90 return -ENOMEM; 91 } 92 93 /* Be careful when switching to percpu debug data. */ 94 local_irq_save(flags); 95 xen_mc_flush(); 96 mc_percpu_init(0); 97 local_irq_restore(flags); 98 99 pr_info("xen_mc_debug active\n"); 100 101 return 0; 102 } 103 early_initcall(mc_debug_enable); 104 105 /* Number of parameters of hypercalls used via multicalls. */ 106 static const uint8_t hpcpars[] = { 107 [__HYPERVISOR_mmu_update] = 4, 108 [__HYPERVISOR_stack_switch] = 2, 109 [__HYPERVISOR_fpu_taskswitch] = 1, 110 [__HYPERVISOR_update_descriptor] = 2, 111 [__HYPERVISOR_update_va_mapping] = 3, 112 [__HYPERVISOR_mmuext_op] = 4, 113 }; 114 115 static void print_debug_data(struct mc_buffer *b, struct mc_debug_data *mcdb, 116 int idx) 117 { 118 unsigned int arg; 119 unsigned int opidx = mcdb->entries[idx].op & 0xff; 120 unsigned int pars = 0; 121 122 pr_err(" call %2d: op=%lu result=%ld caller=%pS ", idx + 1, 123 mcdb->entries[idx].op, b->entries[idx].result, 124 mcdb->caller[idx]); 125 if (opidx < ARRAY_SIZE(hpcpars)) 126 pars = hpcpars[opidx]; 127 if (pars) { 128 pr_cont("pars="); 129 for (arg = 0; arg < pars; arg++) 130 pr_cont("%lx ", mcdb->entries[idx].args[arg]); 131 } 132 if (mcdb->argsz[idx]) { 133 pr_cont("args="); 134 for (arg = 0; arg < mcdb->argsz[idx] / 8; arg++) 135 pr_cont("%lx ", mcdb->args[idx][arg]); 136 } 137 pr_cont("\n"); 138 } 139 140 void xen_mc_flush(void) 141 { 142 struct mc_buffer *b = this_cpu_ptr(&mc_buffer); 143 struct multicall_entry *mc; 144 struct mc_debug_data *mcdb = NULL; 145 int ret = 0; 146 unsigned long flags; 147 int i; 148 149 BUG_ON(preemptible()); 150 151 /* Disable interrupts in case someone comes in and queues 152 something in the middle */ 153 local_irq_save(flags); 154 155 trace_xen_mc_flush(b->mcidx, b->argidx, b->cbidx); 156 157 if (static_key_false(&mc_debug)) { 158 mcdb = __this_cpu_read(mc_debug_data); 159 memcpy(mcdb->entries, b->entries, 160 b->mcidx * sizeof(struct multicall_entry)); 161 } 162 163 switch (b->mcidx) { 164 case 0: 165 /* no-op */ 166 BUG_ON(b->argidx != 0); 167 break; 168 169 case 1: 170 /* Singleton multicall - bypass multicall machinery 171 and just do the call directly. */ 172 mc = &b->entries[0]; 173 174 mc->result = xen_single_call(mc->op, mc->args[0], mc->args[1], 175 mc->args[2], mc->args[3], 176 mc->args[4]); 177 ret = mc->result < 0; 178 break; 179 180 default: 181 if (HYPERVISOR_multicall(b->entries, b->mcidx) != 0) 182 BUG(); 183 for (i = 0; i < b->mcidx; i++) 184 if (b->entries[i].result < 0) 185 ret++; 186 } 187 188 if (WARN_ON(ret)) { 189 pr_err("%d of %d multicall(s) failed: cpu %d\n", 190 ret, b->mcidx, smp_processor_id()); 191 for (i = 0; i < b->mcidx; i++) { 192 if (static_key_false(&mc_debug)) { 193 print_debug_data(b, mcdb, i); 194 } else if (b->entries[i].result < 0) { 195 pr_err(" call %2d: op=%lu arg=[%lx] result=%ld\n", 196 i + 1, 197 b->entries[i].op, 198 b->entries[i].args[0], 199 b->entries[i].result); 200 } 201 } 202 } 203 204 b->mcidx = 0; 205 b->argidx = 0; 206 207 for (i = 0; i < b->cbidx; i++) { 208 struct callback *cb = &b->callbacks[i]; 209 210 (*cb->fn)(cb->data); 211 } 212 b->cbidx = 0; 213 214 local_irq_restore(flags); 215 } 216 217 struct multicall_space __xen_mc_entry(size_t args) 218 { 219 struct mc_buffer *b = this_cpu_ptr(&mc_buffer); 220 struct multicall_space ret; 221 unsigned argidx = roundup(b->argidx, sizeof(u64)); 222 223 trace_xen_mc_entry_alloc(args); 224 225 BUG_ON(preemptible()); 226 BUG_ON(b->argidx >= MC_ARGS); 227 228 if (unlikely(b->mcidx == MC_BATCH || 229 (argidx + args) >= MC_ARGS)) { 230 trace_xen_mc_flush_reason((b->mcidx == MC_BATCH) ? 231 XEN_MC_FL_BATCH : XEN_MC_FL_ARGS); 232 xen_mc_flush(); 233 argidx = roundup(b->argidx, sizeof(u64)); 234 } 235 236 ret.mc = &b->entries[b->mcidx]; 237 if (static_key_false(&mc_debug)) { 238 struct mc_debug_data *mcdb = __this_cpu_read(mc_debug_data); 239 240 mcdb->caller[b->mcidx] = __builtin_return_address(0); 241 mcdb->argsz[b->mcidx] = args; 242 mcdb->args[b->mcidx] = (unsigned long *)(&b->args[argidx]); 243 } 244 b->mcidx++; 245 ret.args = &b->args[argidx]; 246 b->argidx = argidx + args; 247 248 BUG_ON(b->argidx >= MC_ARGS); 249 return ret; 250 } 251 252 struct multicall_space xen_mc_extend_args(unsigned long op, size_t size) 253 { 254 struct mc_buffer *b = this_cpu_ptr(&mc_buffer); 255 struct multicall_space ret = { NULL, NULL }; 256 257 BUG_ON(preemptible()); 258 BUG_ON(b->argidx >= MC_ARGS); 259 260 if (unlikely(b->mcidx == 0 || 261 b->entries[b->mcidx - 1].op != op)) { 262 trace_xen_mc_extend_args(op, size, XEN_MC_XE_BAD_OP); 263 goto out; 264 } 265 266 if (unlikely((b->argidx + size) >= MC_ARGS)) { 267 trace_xen_mc_extend_args(op, size, XEN_MC_XE_NO_SPACE); 268 goto out; 269 } 270 271 ret.mc = &b->entries[b->mcidx - 1]; 272 ret.args = &b->args[b->argidx]; 273 b->argidx += size; 274 275 BUG_ON(b->argidx >= MC_ARGS); 276 277 trace_xen_mc_extend_args(op, size, XEN_MC_XE_OK); 278 out: 279 return ret; 280 } 281 282 void xen_mc_callback(void (*fn)(void *), void *data) 283 { 284 struct mc_buffer *b = this_cpu_ptr(&mc_buffer); 285 struct callback *cb; 286 287 if (b->cbidx == MC_BATCH) { 288 trace_xen_mc_flush_reason(XEN_MC_FL_CALLBACK); 289 xen_mc_flush(); 290 } 291 292 trace_xen_mc_callback(fn, data); 293 294 cb = &b->callbacks[b->cbidx++]; 295 cb->fn = fn; 296 cb->data = data; 297 } 298