qemu/hw/ppc/spapr_caps.c
<<
>>
Prefs
   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 "exec/ram_addr.h"
  30#include "target/ppc/cpu.h"
  31#include "target/ppc/mmu-hash64.h"
  32#include "cpu-models.h"
  33#include "kvm_ppc.h"
  34
  35#include "hw/ppc/spapr.h"
  36
  37typedef struct sPAPRCapPossible {
  38    int num;            /* size of vals array below */
  39    const char *help;   /* help text for vals */
  40    /*
  41     * Note:
  42     * - because of the way compatibility is determined vals MUST be ordered
  43     *   such that later options are a superset of all preceding options.
  44     * - the order of vals must be preserved, that is their index is important,
  45     *   however vals may be added to the end of the list so long as the above
  46     *   point is observed
  47     */
  48    const char *vals[];
  49} sPAPRCapPossible;
  50
  51typedef struct sPAPRCapabilityInfo {
  52    const char *name;
  53    const char *description;
  54    int index;
  55
  56    /* Getter and Setter Function Pointers */
  57    ObjectPropertyAccessor *get;
  58    ObjectPropertyAccessor *set;
  59    const char *type;
  60    /* Possible values if this is a custom string type */
  61    sPAPRCapPossible *possible;
  62    /* Make sure the virtual hardware can support this capability */
  63    void (*apply)(sPAPRMachineState *spapr, uint8_t val, Error **errp);
  64    void (*cpu_apply)(sPAPRMachineState *spapr, PowerPCCPU *cpu,
  65                      uint8_t val, Error **errp);
  66} sPAPRCapabilityInfo;
  67
  68static void spapr_cap_get_bool(Object *obj, Visitor *v, const char *name,
  69                               void *opaque, Error **errp)
  70{
  71    sPAPRCapabilityInfo *cap = opaque;
  72    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
  73    bool value = spapr_get_cap(spapr, cap->index) == SPAPR_CAP_ON;
  74
  75    visit_type_bool(v, name, &value, errp);
  76}
  77
  78static void spapr_cap_set_bool(Object *obj, Visitor *v, const char *name,
  79                               void *opaque, Error **errp)
  80{
  81    sPAPRCapabilityInfo *cap = opaque;
  82    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
  83    bool value;
  84    Error *local_err = NULL;
  85
  86    visit_type_bool(v, name, &value, &local_err);
  87    if (local_err) {
  88        error_propagate(errp, local_err);
  89        return;
  90    }
  91
  92    spapr->cmd_line_caps[cap->index] = true;
  93    spapr->eff.caps[cap->index] = value ? SPAPR_CAP_ON : SPAPR_CAP_OFF;
  94}
  95
  96
  97static void  spapr_cap_get_string(Object *obj, Visitor *v, const char *name,
  98                                  void *opaque, Error **errp)
  99{
 100    sPAPRCapabilityInfo *cap = opaque;
 101    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
 102    char *val = NULL;
 103    uint8_t value = spapr_get_cap(spapr, cap->index);
 104
 105    if (value >= cap->possible->num) {
 106        error_setg(errp, "Invalid value (%d) for cap-%s", value, cap->name);
 107        return;
 108    }
 109
 110    val = g_strdup(cap->possible->vals[value]);
 111
 112    visit_type_str(v, name, &val, errp);
 113    g_free(val);
 114}
 115
 116static void spapr_cap_set_string(Object *obj, Visitor *v, const char *name,
 117                                 void *opaque, Error **errp)
 118{
 119    sPAPRCapabilityInfo *cap = opaque;
 120    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
 121    Error *local_err = NULL;
 122    uint8_t i;
 123    char *val;
 124
 125    visit_type_str(v, name, &val, &local_err);
 126    if (local_err) {
 127        error_propagate(errp, local_err);
 128        return;
 129    }
 130
 131    if (!strcmp(val, "?")) {
 132        error_setg(errp, "%s", cap->possible->help);
 133        goto out;
 134    }
 135    for (i = 0; i < cap->possible->num; i++) {
 136        if (!strcasecmp(val, cap->possible->vals[i])) {
 137            spapr->cmd_line_caps[cap->index] = true;
 138            spapr->eff.caps[cap->index] = i;
 139            goto out;
 140        }
 141    }
 142
 143    error_setg(errp, "Invalid capability mode \"%s\" for cap-%s", val,
 144               cap->name);
 145out:
 146    g_free(val);
 147}
 148
 149static void spapr_cap_get_pagesize(Object *obj, Visitor *v, const char *name,
 150                                   void *opaque, Error **errp)
 151{
 152    sPAPRCapabilityInfo *cap = opaque;
 153    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
 154    uint8_t val = spapr_get_cap(spapr, cap->index);
 155    uint64_t pagesize = (1ULL << val);
 156
 157    visit_type_size(v, name, &pagesize, errp);
 158}
 159
 160static void spapr_cap_set_pagesize(Object *obj, Visitor *v, const char *name,
 161                                   void *opaque, Error **errp)
 162{
 163    sPAPRCapabilityInfo *cap = opaque;
 164    sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
 165    uint64_t pagesize;
 166    uint8_t val;
 167    Error *local_err = NULL;
 168
 169    visit_type_size(v, name, &pagesize, &local_err);
 170    if (local_err) {
 171        error_propagate(errp, local_err);
 172        return;
 173    }
 174
 175    if (!is_power_of_2(pagesize)) {
 176        error_setg(errp, "cap-%s must be a power of 2", cap->name);
 177        return;
 178    }
 179
 180    val = ctz64(pagesize);
 181    spapr->cmd_line_caps[cap->index] = true;
 182    spapr->eff.caps[cap->index] = val;
 183}
 184
 185static void cap_htm_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp)
 186{
 187    if (!val) {
 188        /* TODO: We don't support disabling htm yet */
 189        return;
 190    }
 191    if (tcg_enabled()) {
 192        error_setg(errp,
 193                   "No Transactional Memory support in TCG, try cap-htm=off");
 194    } else if (kvm_enabled() && !kvmppc_has_cap_htm()) {
 195        error_setg(errp,
 196"KVM implementation does not support Transactional Memory, try cap-htm=off"
 197            );
 198    }
 199}
 200
 201static void cap_vsx_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp)
 202{
 203    PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
 204    CPUPPCState *env = &cpu->env;
 205
 206    if (!val) {
 207        /* TODO: We don't support disabling vsx yet */
 208        return;
 209    }
 210    /* Allowable CPUs in spapr_cpu_core.c should already have gotten
 211     * rid of anything that doesn't do VMX */
 212    g_assert(env->insns_flags & PPC_ALTIVEC);
 213    if (!(env->insns_flags2 & PPC2_VSX)) {
 214        error_setg(errp, "VSX support not available, try cap-vsx=off");
 215    }
 216}
 217
 218static void cap_dfp_apply(sPAPRMachineState *spapr, uint8_t val, Error **errp)
 219{
 220    PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
 221    CPUPPCState *env = &cpu->env;
 222
 223    if (!val) {
 224        /* TODO: We don't support disabling dfp yet */
 225        return;
 226    }
 227    if (!(env->insns_flags2 & PPC2_DFP)) {
 228        error_setg(errp, "DFP support not available, try cap-dfp=off");
 229    }
 230}
 231
 232sPAPRCapPossible cap_cfpc_possible = {
 233    .num = 3,
 234    .vals = {"broken", "workaround", "fixed"},
 235    .help = "broken - no protection, workaround - workaround available,"
 236            " fixed - fixed in hardware",
 237};
 238
 239static void cap_safe_cache_apply(sPAPRMachineState *spapr, uint8_t val,
 240                                 Error **errp)
 241{
 242    uint8_t kvm_val =  kvmppc_get_cap_safe_cache();
 243
 244    if (tcg_enabled() && val) {
 245        /* TODO - for now only allow broken for TCG */
 246        error_setg(errp,
 247"Requested safe cache capability level not supported by tcg, try a different value for cap-cfpc");
 248    } else if (kvm_enabled() && (val > kvm_val)) {
 249        error_setg(errp,
 250"Requested safe cache capability level not supported by kvm, try cap-cfpc=%s",
 251                   cap_cfpc_possible.vals[kvm_val]);
 252    }
 253}
 254
 255sPAPRCapPossible cap_sbbc_possible = {
 256    .num = 3,
 257    .vals = {"broken", "workaround", "fixed"},
 258    .help = "broken - no protection, workaround - workaround available,"
 259            " fixed - fixed in hardware",
 260};
 261
 262static void cap_safe_bounds_check_apply(sPAPRMachineState *spapr, uint8_t val,
 263                                        Error **errp)
 264{
 265    uint8_t kvm_val =  kvmppc_get_cap_safe_bounds_check();
 266
 267    if (tcg_enabled() && val) {
 268        /* TODO - for now only allow broken for TCG */
 269        error_setg(errp,
 270"Requested safe bounds check capability level not supported by tcg, try a different value for cap-sbbc");
 271    } else if (kvm_enabled() && (val > kvm_val)) {
 272        error_setg(errp,
 273"Requested safe bounds check capability level not supported by kvm, try cap-sbbc=%s",
 274                   cap_sbbc_possible.vals[kvm_val]);
 275    }
 276}
 277
 278sPAPRCapPossible cap_ibs_possible = {
 279    .num = 4,
 280    /* Note workaround only maintained for compatibility */
 281    .vals = {"broken", "workaround", "fixed-ibs", "fixed-ccd"},
 282    .help = "broken - no protection, fixed-ibs - indirect branch serialisation,"
 283            " fixed-ccd - cache count disabled",
 284};
 285
 286static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr,
 287                                           uint8_t val, Error **errp)
 288{
 289    uint8_t kvm_val = kvmppc_get_cap_safe_indirect_branch();
 290
 291    if (val == SPAPR_CAP_WORKAROUND) { /* Can only be Broken or Fixed */
 292        error_setg(errp,
 293"Requested safe indirect branch capability level \"workaround\" not valid, try cap-ibs=%s",
 294                   cap_ibs_possible.vals[kvm_val]);
 295    } else if (tcg_enabled() && val) {
 296        /* TODO - for now only allow broken for TCG */
 297        error_setg(errp,
 298"Requested safe indirect branch capability level not supported by tcg, try a different value for cap-ibs");
 299    } else if (kvm_enabled() && val && (val != kvm_val)) {
 300        error_setg(errp,
 301"Requested safe indirect branch capability level not supported by kvm, try cap-ibs=%s",
 302                   cap_ibs_possible.vals[kvm_val]);
 303    }
 304}
 305
 306#define VALUE_DESC_TRISTATE     " (broken, workaround, fixed)"
 307
 308void spapr_check_pagesize(sPAPRMachineState *spapr, hwaddr pagesize,
 309                          Error **errp)
 310{
 311    hwaddr maxpagesize = (1ULL << spapr->eff.caps[SPAPR_CAP_HPT_MAXPAGESIZE]);
 312
 313    if (!kvmppc_hpt_needs_host_contiguous_pages()) {
 314        return;
 315    }
 316
 317    if (maxpagesize > pagesize) {
 318        error_setg(errp,
 319                   "Can't support %"HWADDR_PRIu" kiB guest pages with %"
 320                   HWADDR_PRIu" kiB host pages with this KVM implementation",
 321                   maxpagesize >> 10, pagesize >> 10);
 322    }
 323}
 324
 325static void cap_hpt_maxpagesize_apply(sPAPRMachineState *spapr,
 326                                      uint8_t val, Error **errp)
 327{
 328    if (val < 12) {
 329        error_setg(errp, "Require at least 4kiB hpt-max-page-size");
 330        return;
 331    } else if (val < 16) {
 332        warn_report("Many guests require at least 64kiB hpt-max-page-size");
 333    }
 334
 335    spapr_check_pagesize(spapr, qemu_getrampagesize(), errp);
 336}
 337
 338static bool spapr_pagesize_cb(void *opaque, uint32_t seg_pshift,
 339                              uint32_t pshift)
 340{
 341    unsigned maxshift = *((unsigned *)opaque);
 342
 343    assert(pshift >= seg_pshift);
 344
 345    /* Don't allow the guest to use pages bigger than the configured
 346     * maximum size */
 347    if (pshift > maxshift) {
 348        return false;
 349    }
 350
 351    /* For whatever reason, KVM doesn't allow multiple pagesizes
 352     * within a segment, *except* for the case of 16M pages in a 4k or
 353     * 64k segment.  Always exclude other cases, so that TCG and KVM
 354     * guests see a consistent environment */
 355    if ((pshift != seg_pshift) && (pshift != 24)) {
 356        return false;
 357    }
 358
 359    return true;
 360}
 361
 362static void cap_hpt_maxpagesize_cpu_apply(sPAPRMachineState *spapr,
 363                                          PowerPCCPU *cpu,
 364                                          uint8_t val, Error **errp)
 365{
 366    unsigned maxshift = val;
 367
 368    ppc_hash64_filter_pagesizes(cpu, spapr_pagesize_cb, &maxshift);
 369}
 370
 371static void cap_nested_kvm_hv_apply(sPAPRMachineState *spapr,
 372                                    uint8_t val, Error **errp)
 373{
 374    if (!val) {
 375        /* capability disabled by default */
 376        return;
 377    }
 378
 379    if (tcg_enabled()) {
 380        error_setg(errp,
 381                   "No Nested KVM-HV support in tcg, try cap-nested-hv=off");
 382    } else if (kvm_enabled()) {
 383        if (!kvmppc_has_cap_nested_kvm_hv()) {
 384            error_setg(errp,
 385"KVM implementation does not support Nested KVM-HV, try cap-nested-hv=off");
 386        } else if (kvmppc_set_cap_nested_kvm_hv(val) < 0) {
 387                error_setg(errp,
 388"Error enabling cap-nested-hv with KVM, try cap-nested-hv=off");
 389        }
 390    }
 391}
 392
 393sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
 394    [SPAPR_CAP_HTM] = {
 395        .name = "htm",
 396        .description = "Allow Hardware Transactional Memory (HTM)",
 397        .index = SPAPR_CAP_HTM,
 398        .get = spapr_cap_get_bool,
 399        .set = spapr_cap_set_bool,
 400        .type = "bool",
 401        .apply = cap_htm_apply,
 402    },
 403    [SPAPR_CAP_VSX] = {
 404        .name = "vsx",
 405        .description = "Allow Vector Scalar Extensions (VSX)",
 406        .index = SPAPR_CAP_VSX,
 407        .get = spapr_cap_get_bool,
 408        .set = spapr_cap_set_bool,
 409        .type = "bool",
 410        .apply = cap_vsx_apply,
 411    },
 412    [SPAPR_CAP_DFP] = {
 413        .name = "dfp",
 414        .description = "Allow Decimal Floating Point (DFP)",
 415        .index = SPAPR_CAP_DFP,
 416        .get = spapr_cap_get_bool,
 417        .set = spapr_cap_set_bool,
 418        .type = "bool",
 419        .apply = cap_dfp_apply,
 420    },
 421    [SPAPR_CAP_CFPC] = {
 422        .name = "cfpc",
 423        .description = "Cache Flush on Privilege Change" VALUE_DESC_TRISTATE,
 424        .index = SPAPR_CAP_CFPC,
 425        .get = spapr_cap_get_string,
 426        .set = spapr_cap_set_string,
 427        .type = "string",
 428        .possible = &cap_cfpc_possible,
 429        .apply = cap_safe_cache_apply,
 430    },
 431    [SPAPR_CAP_SBBC] = {
 432        .name = "sbbc",
 433        .description = "Speculation Barrier Bounds Checking" VALUE_DESC_TRISTATE,
 434        .index = SPAPR_CAP_SBBC,
 435        .get = spapr_cap_get_string,
 436        .set = spapr_cap_set_string,
 437        .type = "string",
 438        .possible = &cap_sbbc_possible,
 439        .apply = cap_safe_bounds_check_apply,
 440    },
 441    [SPAPR_CAP_IBS] = {
 442        .name = "ibs",
 443        .description =
 444            "Indirect Branch Speculation (broken, fixed-ibs, fixed-ccd)",
 445        .index = SPAPR_CAP_IBS,
 446        .get = spapr_cap_get_string,
 447        .set = spapr_cap_set_string,
 448        .type = "string",
 449        .possible = &cap_ibs_possible,
 450        .apply = cap_safe_indirect_branch_apply,
 451    },
 452    [SPAPR_CAP_HPT_MAXPAGESIZE] = {
 453        .name = "hpt-max-page-size",
 454        .description = "Maximum page size for Hash Page Table guests",
 455        .index = SPAPR_CAP_HPT_MAXPAGESIZE,
 456        .get = spapr_cap_get_pagesize,
 457        .set = spapr_cap_set_pagesize,
 458        .type = "int",
 459        .apply = cap_hpt_maxpagesize_apply,
 460        .cpu_apply = cap_hpt_maxpagesize_cpu_apply,
 461    },
 462    [SPAPR_CAP_NESTED_KVM_HV] = {
 463        .name = "nested-hv",
 464        .description = "Allow Nested KVM-HV",
 465        .index = SPAPR_CAP_NESTED_KVM_HV,
 466        .get = spapr_cap_get_bool,
 467        .set = spapr_cap_set_bool,
 468        .type = "bool",
 469        .apply = cap_nested_kvm_hv_apply,
 470    },
 471};
 472
 473static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr,
 474                                               const char *cputype)
 475{
 476    sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
 477    sPAPRCapabilities caps;
 478
 479    caps = smc->default_caps;
 480
 481    if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_2_07,
 482                               0, spapr->max_compat_pvr)) {
 483        caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
 484        caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
 485    }
 486
 487    if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_2_06_PLUS,
 488                               0, spapr->max_compat_pvr)) {
 489        caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
 490    }
 491
 492    if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_2_06,
 493                               0, spapr->max_compat_pvr)) {
 494        caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_OFF;
 495        caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_OFF;
 496        caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
 497    }
 498
 499    /* This is for pseries-2.12 and older */
 500    if (smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] == 0) {
 501        uint8_t mps;
 502
 503        if (kvmppc_hpt_needs_host_contiguous_pages()) {
 504            mps = ctz64(qemu_getrampagesize());
 505        } else {
 506            mps = 34; /* allow everything up to 16GiB, i.e. everything */
 507        }
 508
 509        caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = mps;
 510    }
 511
 512    return caps;
 513}
 514
 515int spapr_caps_pre_load(void *opaque)
 516{
 517    sPAPRMachineState *spapr = opaque;
 518
 519    /* Set to default so we can tell if this came in with the migration */
 520    spapr->mig = spapr->def;
 521    return 0;
 522}
 523
 524int spapr_caps_pre_save(void *opaque)
 525{
 526    sPAPRMachineState *spapr = opaque;
 527
 528    spapr->mig = spapr->eff;
 529    return 0;
 530}
 531
 532/* This has to be called from the top-level spapr post_load, not the
 533 * caps specific one.  Otherwise it wouldn't be called when the source
 534 * caps are all defaults, which could still conflict with overridden
 535 * caps on the destination */
 536int spapr_caps_post_migration(sPAPRMachineState *spapr)
 537{
 538    int i;
 539    bool ok = true;
 540    sPAPRCapabilities dstcaps = spapr->eff;
 541    sPAPRCapabilities srccaps;
 542
 543    srccaps = default_caps_with_cpu(spapr, MACHINE(spapr)->cpu_type);
 544    for (i = 0; i < SPAPR_CAP_NUM; i++) {
 545        /* If not default value then assume came in with the migration */
 546        if (spapr->mig.caps[i] != spapr->def.caps[i]) {
 547            srccaps.caps[i] = spapr->mig.caps[i];
 548        }
 549    }
 550
 551    for (i = 0; i < SPAPR_CAP_NUM; i++) {
 552        sPAPRCapabilityInfo *info = &capability_table[i];
 553
 554        if (srccaps.caps[i] > dstcaps.caps[i]) {
 555            error_report("cap-%s higher level (%d) in incoming stream than on destination (%d)",
 556                         info->name, srccaps.caps[i], dstcaps.caps[i]);
 557            ok = false;
 558        }
 559
 560        if (srccaps.caps[i] < dstcaps.caps[i]) {
 561            warn_report("cap-%s lower level (%d) in incoming stream than on destination (%d)",
 562                         info->name, srccaps.caps[i], dstcaps.caps[i]);
 563        }
 564    }
 565
 566    return ok ? 0 : -EINVAL;
 567}
 568
 569/* Used to generate the migration field and needed function for a spapr cap */
 570#define SPAPR_CAP_MIG_STATE(sname, cap)                 \
 571static bool spapr_cap_##sname##_needed(void *opaque)    \
 572{                                                       \
 573    sPAPRMachineState *spapr = opaque;                  \
 574                                                        \
 575    return spapr->cmd_line_caps[cap] &&                 \
 576           (spapr->eff.caps[cap] !=                     \
 577            spapr->def.caps[cap]);                      \
 578}                                                       \
 579                                                        \
 580const VMStateDescription vmstate_spapr_cap_##sname = {  \
 581    .name = "spapr/cap/" #sname,                        \
 582    .version_id = 1,                                    \
 583    .minimum_version_id = 1,                            \
 584    .needed = spapr_cap_##sname##_needed,               \
 585    .fields = (VMStateField[]) {                        \
 586        VMSTATE_UINT8(mig.caps[cap],                    \
 587                      sPAPRMachineState),               \
 588        VMSTATE_END_OF_LIST()                           \
 589    },                                                  \
 590}
 591
 592SPAPR_CAP_MIG_STATE(htm, SPAPR_CAP_HTM);
 593SPAPR_CAP_MIG_STATE(vsx, SPAPR_CAP_VSX);
 594SPAPR_CAP_MIG_STATE(dfp, SPAPR_CAP_DFP);
 595SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC);
 596SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC);
 597SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS);
 598SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
 599
 600void spapr_caps_init(sPAPRMachineState *spapr)
 601{
 602    sPAPRCapabilities default_caps;
 603    int i;
 604
 605    /* Compute the actual set of caps we should run with */
 606    default_caps = default_caps_with_cpu(spapr, MACHINE(spapr)->cpu_type);
 607
 608    for (i = 0; i < SPAPR_CAP_NUM; i++) {
 609        /* Store the defaults */
 610        spapr->def.caps[i] = default_caps.caps[i];
 611        /* If not set on the command line then apply the default value */
 612        if (!spapr->cmd_line_caps[i]) {
 613            spapr->eff.caps[i] = default_caps.caps[i];
 614        }
 615    }
 616}
 617
 618void spapr_caps_apply(sPAPRMachineState *spapr)
 619{
 620    int i;
 621
 622    for (i = 0; i < SPAPR_CAP_NUM; i++) {
 623        sPAPRCapabilityInfo *info = &capability_table[i];
 624
 625        /*
 626         * If the apply function can't set the desired level and thinks it's
 627         * fatal, it should cause that.
 628         */
 629        info->apply(spapr, spapr->eff.caps[i], &error_fatal);
 630    }
 631}
 632
 633void spapr_caps_cpu_apply(sPAPRMachineState *spapr, PowerPCCPU *cpu)
 634{
 635    int i;
 636
 637    for (i = 0; i < SPAPR_CAP_NUM; i++) {
 638        sPAPRCapabilityInfo *info = &capability_table[i];
 639
 640        /*
 641         * If the apply function can't set the desired level and thinks it's
 642         * fatal, it should cause that.
 643         */
 644        if (info->cpu_apply) {
 645            info->cpu_apply(spapr, cpu, spapr->eff.caps[i], &error_fatal);
 646        }
 647    }
 648}
 649
 650void spapr_caps_add_properties(sPAPRMachineClass *smc, Error **errp)
 651{
 652    Error *local_err = NULL;
 653    ObjectClass *klass = OBJECT_CLASS(smc);
 654    int i;
 655
 656    for (i = 0; i < ARRAY_SIZE(capability_table); i++) {
 657        sPAPRCapabilityInfo *cap = &capability_table[i];
 658        const char *name = g_strdup_printf("cap-%s", cap->name);
 659        char *desc;
 660
 661        object_class_property_add(klass, name, cap->type,
 662                                  cap->get, cap->set,
 663                                  NULL, cap, &local_err);
 664        if (local_err) {
 665            error_propagate(errp, local_err);
 666            return;
 667        }
 668
 669        desc = g_strdup_printf("%s", cap->description);
 670        object_class_property_set_description(klass, name, desc, &local_err);
 671        g_free(desc);
 672        if (local_err) {
 673            error_propagate(errp, local_err);
 674            return;
 675        }
 676    }
 677}
 678