1 /* 2 * QEMU PowerPC pSeries Logical Partition capabilities handling 3 * 4 * Copyright (c) 2017 David Gibson, Red Hat Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 #include "qemu/osdep.h" 25 #include "qemu/error-report.h" 26 #include "qapi/error.h" 27 #include "qapi/visitor.h" 28 #include "sysemu/hw_accel.h" 29 #include "target/ppc/cpu.h" 30 #include "cpu-models.h" 31 #include "kvm_ppc.h" 32 33 #include "hw/ppc/spapr.h" 34 35 typedef struct sPAPRCapabilityInfo { 36 const char *name; 37 const char *description; 38 int index; 39 40 /* Getter and Setter Function Pointers */ 41 ObjectPropertyAccessor *get; 42 ObjectPropertyAccessor *set; 43 const char *type; 44 /* Make sure the virtual hardware can support this capability */ 45 void (*apply)(sPAPRMachineState *spapr, uint8_t val, Error **errp); 46 } sPAPRCapabilityInfo; 47 48 static void spapr_cap_get_bool(Object *obj, Visitor *v, const char *name, 49 void *opaque, Error **errp) 50 { 51 sPAPRCapabilityInfo *cap = opaque; 52 sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 53 bool value = spapr_get_cap(spapr, cap->index) == SPAPR_CAP_ON; 54 55 visit_type_bool(v, name, &value, errp); 56 } 57 58 static void spapr_cap_set_bool(Object *obj, Visitor *v, const char *name, 59 void *opaque, Error **errp) 60 { 61 sPAPRCapabilityInfo *cap = opaque; 62 sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 63 bool value; 64 Error *local_err = NULL; 65 66 visit_type_bool(v, name, &value, &local_err); 67 if (local_err) { 68 error_propagate(errp, local_err); 69 return; 70 } 71 72 spapr->cmd_line_caps[cap->index] = true; 73 spapr->eff.caps[cap->index] = value ? SPAPR_CAP_ON : SPAPR_CAP_OFF; 74 } 75 76 static void spapr_cap_get_tristate(Object *obj, Visitor *v, const char *name, 77 void *opaque, Error **errp) 78 { 79 sPAPRCapabilityInfo *cap = opaque; 80 sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 81 char *val = NULL; 82 uint8_t value = spapr_get_cap(spapr, cap->index); 83 84 switch (value) { 85 case SPAPR_CAP_BROKEN: 86 val = g_strdup("broken"); 87 break; 88 case SPAPR_CAP_WORKAROUND: 89 val = g_strdup("workaround"); 90 break; 91 case SPAPR_CAP_FIXED: 92 val = g_strdup("fixed"); 93 break; 94 default: 95 error_setg(errp, "Invalid value (%d) for cap-%s", value, cap->name); 96 return; 97 } 98 99 visit_type_str(v, name, &val, errp); 100 g_free(val); 101 } 102 103 static void spapr_cap_set_tristate(Object *obj, Visitor *v, const char *name, 104 void *opaque, Error **errp) 105 { 106 sPAPRCapabilityInfo *cap = opaque; 107 sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 108 char *val; 109 Error *local_err = NULL; 110 uint8_t value; 111 112 visit_type_str(v, name, &val, &local_err); 113 if (local_err) { 114 error_propagate(errp, local_err); 115 return; 116 } 117 118 if (!strcasecmp(val, "broken")) { 119 value = SPAPR_CAP_BROKEN; 120 } else if (!strcasecmp(val, "workaround")) { 121 value = SPAPR_CAP_WORKAROUND; 122 } else if (!strcasecmp(val, "fixed")) { 123 value = SPAPR_CAP_FIXED; 124 } else { 125 error_setg(errp, "Invalid capability mode \"%s\" for cap-%s", val, 126 cap->name); 127 goto out; 128 } 129 130 spapr->cmd_line_caps[cap->index] = true; 131 spapr->eff.caps[cap->index] = value; 132 out: 133 g_free(val); 134 } 135 136 static void cap_htm_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp) 137 { 138 if (!val) { 139 /* TODO: We don't support disabling htm yet */ 140 return; 141 } 142 if (tcg_enabled()) { 143 error_setg(errp, 144 "No Transactional Memory support in TCG, try cap-htm=off"); 145 } else if (kvm_enabled() && !kvmppc_has_cap_htm()) { 146 error_setg(errp, 147 "KVM implementation does not support Transactional Memory, try cap-htm=off" 148 ); 149 } 150 } 151 152 static void cap_vsx_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp) 153 { 154 PowerPCCPU *cpu = POWERPC_CPU(first_cpu); 155 CPUPPCState *env = &cpu->env; 156 157 if (!val) { 158 /* TODO: We don't support disabling vsx yet */ 159 return; 160 } 161 /* Allowable CPUs in spapr_cpu_core.c should already have gotten 162 * rid of anything that doesn't do VMX */ 163 g_assert(env->insns_flags & PPC_ALTIVEC); 164 if (!(env->insns_flags2 & PPC2_VSX)) { 165 error_setg(errp, "VSX support not available, try cap-vsx=off"); 166 } 167 } 168 169 static void cap_dfp_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp) 170 { 171 PowerPCCPU *cpu = POWERPC_CPU(first_cpu); 172 CPUPPCState *env = &cpu->env; 173 174 if (!val) { 175 /* TODO: We don't support disabling dfp yet */ 176 return; 177 } 178 if (!(env->insns_flags2 & PPC2_DFP)) { 179 error_setg(errp, "DFP support not available, try cap-dfp=off"); 180 } 181 } 182 183 static void cap_safe_cache_apply(sPAPRMachineState *spapr, uint8_t val, 184 Error **errp) 185 { 186 if (tcg_enabled() && val) { 187 /* TODO - for now only allow broken for TCG */ 188 error_setg(errp, "Requested safe cache capability level not supported by tcg, try a different value for cap-cfpc"); 189 } else if (kvm_enabled() && (val > kvmppc_get_cap_safe_cache())) { 190 error_setg(errp, "Requested safe cache capability level not supported by kvm, try a different value for cap-cfpc"); 191 } 192 } 193 194 static void cap_safe_bounds_check_apply(sPAPRMachineState *spapr, uint8_t val, 195 Error **errp) 196 { 197 if (tcg_enabled() && val) { 198 /* TODO - for now only allow broken for TCG */ 199 error_setg(errp, "Requested safe bounds check capability level not supported by tcg, try a different value for cap-sbbc"); 200 } else if (kvm_enabled() && (val > kvmppc_get_cap_safe_bounds_check())) { 201 error_setg(errp, "Requested safe bounds check capability level not supported by kvm, try a different value for cap-sbbc"); 202 } 203 } 204 205 static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr, 206 uint8_t val, Error **errp) 207 { 208 if (val == SPAPR_CAP_WORKAROUND) { /* Can only be Broken or Fixed */ 209 error_setg(errp, "Requested safe indirect branch capability level \"workaround\" not valid, try cap-ibs=fixed"); 210 } else if (tcg_enabled() && val) { 211 /* TODO - for now only allow broken for TCG */ 212 error_setg(errp, "Requested safe indirect branch capability level not supported by tcg, try a different value for cap-ibs"); 213 } else if (kvm_enabled() && (val > kvmppc_get_cap_safe_indirect_branch())) { 214 error_setg(errp, "Requested safe indirect branch capability level not supported by kvm, try a different value for cap-ibs"); 215 } 216 } 217 218 #define VALUE_DESC_TRISTATE " (broken, workaround, fixed)" 219 220 sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = { 221 [SPAPR_CAP_HTM] = { 222 .name = "htm", 223 .description = "Allow Hardware Transactional Memory (HTM)", 224 .index = SPAPR_CAP_HTM, 225 .get = spapr_cap_get_bool, 226 .set = spapr_cap_set_bool, 227 .type = "bool", 228 .apply = cap_htm_apply, 229 }, 230 [SPAPR_CAP_VSX] = { 231 .name = "vsx", 232 .description = "Allow Vector Scalar Extensions (VSX)", 233 .index = SPAPR_CAP_VSX, 234 .get = spapr_cap_get_bool, 235 .set = spapr_cap_set_bool, 236 .type = "bool", 237 .apply = cap_vsx_apply, 238 }, 239 [SPAPR_CAP_DFP] = { 240 .name = "dfp", 241 .description = "Allow Decimal Floating Point (DFP)", 242 .index = SPAPR_CAP_DFP, 243 .get = spapr_cap_get_bool, 244 .set = spapr_cap_set_bool, 245 .type = "bool", 246 .apply = cap_dfp_apply, 247 }, 248 [SPAPR_CAP_CFPC] = { 249 .name = "cfpc", 250 .description = "Cache Flush on Privilege Change" VALUE_DESC_TRISTATE, 251 .index = SPAPR_CAP_CFPC, 252 .get = spapr_cap_get_tristate, 253 .set = spapr_cap_set_tristate, 254 .type = "string", 255 .apply = cap_safe_cache_apply, 256 }, 257 [SPAPR_CAP_SBBC] = { 258 .name = "sbbc", 259 .description = "Speculation Barrier Bounds Checking" VALUE_DESC_TRISTATE, 260 .index = SPAPR_CAP_SBBC, 261 .get = spapr_cap_get_tristate, 262 .set = spapr_cap_set_tristate, 263 .type = "string", 264 .apply = cap_safe_bounds_check_apply, 265 }, 266 [SPAPR_CAP_IBS] = { 267 .name = "ibs", 268 .description = "Indirect Branch Serialisation (broken, fixed)", 269 .index = SPAPR_CAP_IBS, 270 .get = spapr_cap_get_tristate, 271 .set = spapr_cap_set_tristate, 272 .type = "string", 273 .apply = cap_safe_indirect_branch_apply, 274 }, 275 }; 276 277 static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr, 278 CPUState *cs) 279 { 280 sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 281 PowerPCCPU *cpu = POWERPC_CPU(cs); 282 sPAPRCapabilities caps; 283 284 caps = smc->default_caps; 285 286 if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_07, 287 0, spapr->max_compat_pvr)) { 288 caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF; 289 } 290 291 if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_2_06, 292 0, spapr->max_compat_pvr)) { 293 caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_OFF; 294 caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_OFF; 295 } 296 297 return caps; 298 } 299 300 int spapr_caps_pre_load(void *opaque) 301 { 302 sPAPRMachineState *spapr = opaque; 303 304 /* Set to default so we can tell if this came in with the migration */ 305 spapr->mig = spapr->def; 306 return 0; 307 } 308 309 int spapr_caps_pre_save(void *opaque) 310 { 311 sPAPRMachineState *spapr = opaque; 312 313 spapr->mig = spapr->eff; 314 return 0; 315 } 316 317 /* This has to be called from the top-level spapr post_load, not the 318 * caps specific one. Otherwise it wouldn't be called when the source 319 * caps are all defaults, which could still conflict with overridden 320 * caps on the destination */ 321 int spapr_caps_post_migration(sPAPRMachineState *spapr) 322 { 323 int i; 324 bool ok = true; 325 sPAPRCapabilities dstcaps = spapr->eff; 326 sPAPRCapabilities srccaps; 327 328 srccaps = default_caps_with_cpu(spapr, first_cpu); 329 for (i = 0; i < SPAPR_CAP_NUM; i++) { 330 /* If not default value then assume came in with the migration */ 331 if (spapr->mig.caps[i] != spapr->def.caps[i]) { 332 srccaps.caps[i] = spapr->mig.caps[i]; 333 } 334 } 335 336 for (i = 0; i < SPAPR_CAP_NUM; i++) { 337 sPAPRCapabilityInfo *info = &capability_table[i]; 338 339 if (srccaps.caps[i] > dstcaps.caps[i]) { 340 error_report("cap-%s higher level (%d) in incoming stream than on destination (%d)", 341 info->name, srccaps.caps[i], dstcaps.caps[i]); 342 ok = false; 343 } 344 345 if (srccaps.caps[i] < dstcaps.caps[i]) { 346 warn_report("cap-%s lower level (%d) in incoming stream than on destination (%d)", 347 info->name, srccaps.caps[i], dstcaps.caps[i]); 348 } 349 } 350 351 return ok ? 0 : -EINVAL; 352 } 353 354 /* Used to generate the migration field and needed function for a spapr cap */ 355 #define SPAPR_CAP_MIG_STATE(sname, cap) \ 356 static bool spapr_cap_##sname##_needed(void *opaque) \ 357 { \ 358 sPAPRMachineState *spapr = opaque; \ 359 \ 360 return spapr->cmd_line_caps[cap] && \ 361 (spapr->eff.caps[cap] != \ 362 spapr->def.caps[cap]); \ 363 } \ 364 \ 365 const VMStateDescription vmstate_spapr_cap_##sname = { \ 366 .name = "spapr/cap/" #sname, \ 367 .version_id = 1, \ 368 .minimum_version_id = 1, \ 369 .needed = spapr_cap_##sname##_needed, \ 370 .fields = (VMStateField[]) { \ 371 VMSTATE_UINT8(mig.caps[cap], \ 372 sPAPRMachineState), \ 373 VMSTATE_END_OF_LIST() \ 374 }, \ 375 } 376 377 SPAPR_CAP_MIG_STATE(htm, SPAPR_CAP_HTM); 378 SPAPR_CAP_MIG_STATE(vsx, SPAPR_CAP_VSX); 379 SPAPR_CAP_MIG_STATE(dfp, SPAPR_CAP_DFP); 380 SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC); 381 SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC); 382 SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS); 383 384 void spapr_caps_reset(sPAPRMachineState *spapr) 385 { 386 sPAPRCapabilities default_caps; 387 int i; 388 389 /* First compute the actual set of caps we're running with.. */ 390 default_caps = default_caps_with_cpu(spapr, first_cpu); 391 392 for (i = 0; i < SPAPR_CAP_NUM; i++) { 393 /* Store the defaults */ 394 spapr->def.caps[i] = default_caps.caps[i]; 395 /* If not set on the command line then apply the default value */ 396 if (!spapr->cmd_line_caps[i]) { 397 spapr->eff.caps[i] = default_caps.caps[i]; 398 } 399 } 400 401 /* .. then apply those caps to the virtual hardware */ 402 403 for (i = 0; i < SPAPR_CAP_NUM; i++) { 404 sPAPRCapabilityInfo *info = &capability_table[i]; 405 406 /* 407 * If the apply function can't set the desired level and thinks it's 408 * fatal, it should cause that. 409 */ 410 info->apply(spapr, spapr->eff.caps[i], &error_fatal); 411 } 412 } 413 414 void spapr_caps_add_properties(sPAPRMachineClass *smc, Error **errp) 415 { 416 Error *local_err = NULL; 417 ObjectClass *klass = OBJECT_CLASS(smc); 418 int i; 419 420 for (i = 0; i < ARRAY_SIZE(capability_table); i++) { 421 sPAPRCapabilityInfo *cap = &capability_table[i]; 422 const char *name = g_strdup_printf("cap-%s", cap->name); 423 char *desc; 424 425 object_class_property_add(klass, name, cap->type, 426 cap->get, cap->set, 427 NULL, cap, &local_err); 428 if (local_err) { 429 error_propagate(errp, local_err); 430 return; 431 } 432 433 desc = g_strdup_printf("%s", cap->description); 434 object_class_property_set_description(klass, name, desc, &local_err); 435 g_free(desc); 436 if (local_err) { 437 error_propagate(errp, local_err); 438 return; 439 } 440 } 441 } 442