xref: /openbmc/qemu/hw/ppc/spapr_caps.c (revision 93b799fafd9170da3a79a533ea6f73a18de82e22)
133face6bSDavid Gibson /*
233face6bSDavid Gibson  * QEMU PowerPC pSeries Logical Partition capabilities handling
333face6bSDavid Gibson  *
433face6bSDavid Gibson  * Copyright (c) 2017 David Gibson, Red Hat Inc.
533face6bSDavid Gibson  *
633face6bSDavid Gibson  * Permission is hereby granted, free of charge, to any person obtaining a copy
733face6bSDavid Gibson  * of this software and associated documentation files (the "Software"), to deal
833face6bSDavid Gibson  * in the Software without restriction, including without limitation the rights
933face6bSDavid Gibson  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1033face6bSDavid Gibson  * copies of the Software, and to permit persons to whom the Software is
1133face6bSDavid Gibson  * furnished to do so, subject to the following conditions:
1233face6bSDavid Gibson  *
1333face6bSDavid Gibson  * The above copyright notice and this permission notice shall be included in
1433face6bSDavid Gibson  * all copies or substantial portions of the Software.
1533face6bSDavid Gibson  *
1633face6bSDavid Gibson  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1733face6bSDavid Gibson  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1833face6bSDavid Gibson  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1933face6bSDavid Gibson  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2033face6bSDavid Gibson  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2133face6bSDavid Gibson  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2233face6bSDavid Gibson  * THE SOFTWARE.
2333face6bSDavid Gibson  */
2414a48c1dSMarkus Armbruster 
2533face6bSDavid Gibson #include "qemu/osdep.h"
26be85537dSDavid Gibson #include "qemu/error-report.h"
2733face6bSDavid Gibson #include "qapi/error.h"
2833face6bSDavid Gibson #include "qapi/visitor.h"
29ee76a09fSDavid Gibson #include "sysemu/hw_accel.h"
30123eec65SDavid Gibson #include "exec/ram_addr.h"
31ee76a09fSDavid Gibson #include "target/ppc/cpu.h"
322309832aSDavid Gibson #include "target/ppc/mmu-hash64.h"
33ee76a09fSDavid Gibson #include "cpu-models.h"
34ee76a09fSDavid Gibson #include "kvm_ppc.h"
35d6454270SMarkus Armbruster #include "migration/vmstate.h"
3614a48c1dSMarkus Armbruster #include "sysemu/tcg.h"
3733face6bSDavid Gibson 
3833face6bSDavid Gibson #include "hw/ppc/spapr.h"
3933face6bSDavid Gibson 
40ce2918cbSDavid Gibson typedef struct SpaprCapPossible {
4187175d1bSSuraj Jitindar Singh     int num;            /* size of vals array below */
4287175d1bSSuraj Jitindar Singh     const char *help;   /* help text for vals */
4387175d1bSSuraj Jitindar Singh     /*
4487175d1bSSuraj Jitindar Singh      * Note:
4587175d1bSSuraj Jitindar Singh      * - because of the way compatibility is determined vals MUST be ordered
4687175d1bSSuraj Jitindar Singh      *   such that later options are a superset of all preceding options.
4787175d1bSSuraj Jitindar Singh      * - the order of vals must be preserved, that is their index is important,
4887175d1bSSuraj Jitindar Singh      *   however vals may be added to the end of the list so long as the above
4987175d1bSSuraj Jitindar Singh      *   point is observed
5087175d1bSSuraj Jitindar Singh      */
5187175d1bSSuraj Jitindar Singh     const char *vals[];
52ce2918cbSDavid Gibson } SpaprCapPossible;
5387175d1bSSuraj Jitindar Singh 
54ce2918cbSDavid Gibson typedef struct SpaprCapabilityInfo {
5533face6bSDavid Gibson     const char *name;
5633face6bSDavid Gibson     const char *description;
574e5fe368SSuraj Jitindar Singh     int index;
5833face6bSDavid Gibson 
594e5fe368SSuraj Jitindar Singh     /* Getter and Setter Function Pointers */
604e5fe368SSuraj Jitindar Singh     ObjectPropertyAccessor *get;
614e5fe368SSuraj Jitindar Singh     ObjectPropertyAccessor *set;
624e5fe368SSuraj Jitindar Singh     const char *type;
6387175d1bSSuraj Jitindar Singh     /* Possible values if this is a custom string type */
64ce2918cbSDavid Gibson     SpaprCapPossible *possible;
6533face6bSDavid Gibson     /* Make sure the virtual hardware can support this capability */
66ce2918cbSDavid Gibson     void (*apply)(SpaprMachineState *spapr, uint8_t val, Error **errp);
67ce2918cbSDavid Gibson     void (*cpu_apply)(SpaprMachineState *spapr, PowerPCCPU *cpu,
68e2e4f641SDavid Gibson                       uint8_t val, Error **errp);
693725ef1aSGreg Kurz     bool (*migrate_needed)(void *opaque);
70ce2918cbSDavid Gibson } SpaprCapabilityInfo;
7133face6bSDavid Gibson 
spapr_cap_get_bool(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)724e5fe368SSuraj Jitindar Singh static void spapr_cap_get_bool(Object *obj, Visitor *v, const char *name,
734e5fe368SSuraj Jitindar Singh                                void *opaque, Error **errp)
74ee76a09fSDavid Gibson {
75ce2918cbSDavid Gibson     SpaprCapabilityInfo *cap = opaque;
76ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
774e5fe368SSuraj Jitindar Singh     bool value = spapr_get_cap(spapr, cap->index) == SPAPR_CAP_ON;
784e5fe368SSuraj Jitindar Singh 
794e5fe368SSuraj Jitindar Singh     visit_type_bool(v, name, &value, errp);
804e5fe368SSuraj Jitindar Singh }
814e5fe368SSuraj Jitindar Singh 
spapr_cap_set_bool(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)824e5fe368SSuraj Jitindar Singh static void spapr_cap_set_bool(Object *obj, Visitor *v, const char *name,
834e5fe368SSuraj Jitindar Singh                                void *opaque, Error **errp)
844e5fe368SSuraj Jitindar Singh {
85ce2918cbSDavid Gibson     SpaprCapabilityInfo *cap = opaque;
86ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
874e5fe368SSuraj Jitindar Singh     bool value;
884e5fe368SSuraj Jitindar Singh 
89668f62ecSMarkus Armbruster     if (!visit_type_bool(v, name, &value, errp)) {
904e5fe368SSuraj Jitindar Singh         return;
914e5fe368SSuraj Jitindar Singh     }
924e5fe368SSuraj Jitindar Singh 
934e5fe368SSuraj Jitindar Singh     spapr->cmd_line_caps[cap->index] = true;
944e5fe368SSuraj Jitindar Singh     spapr->eff.caps[cap->index] = value ? SPAPR_CAP_ON : SPAPR_CAP_OFF;
954e5fe368SSuraj Jitindar Singh }
964e5fe368SSuraj Jitindar Singh 
976898aed7SSuraj Jitindar Singh 
spapr_cap_get_string(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)98f27aa81eSSuraj Jitindar Singh static void spapr_cap_get_string(Object *obj, Visitor *v, const char *name,
9987175d1bSSuraj Jitindar Singh                                  void *opaque, Error **errp)
10087175d1bSSuraj Jitindar Singh {
101ce2918cbSDavid Gibson     SpaprCapabilityInfo *cap = opaque;
102ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
103bc940c46SDaniel Henrique Barboza     g_autofree char *val = NULL;
10487175d1bSSuraj Jitindar Singh     uint8_t value = spapr_get_cap(spapr, cap->index);
10587175d1bSSuraj Jitindar Singh 
10687175d1bSSuraj Jitindar Singh     if (value >= cap->possible->num) {
10787175d1bSSuraj Jitindar Singh         error_setg(errp, "Invalid value (%d) for cap-%s", value, cap->name);
10887175d1bSSuraj Jitindar Singh         return;
10987175d1bSSuraj Jitindar Singh     }
11087175d1bSSuraj Jitindar Singh 
11187175d1bSSuraj Jitindar Singh     val = g_strdup(cap->possible->vals[value]);
11287175d1bSSuraj Jitindar Singh 
11387175d1bSSuraj Jitindar Singh     visit_type_str(v, name, &val, errp);
11487175d1bSSuraj Jitindar Singh }
11587175d1bSSuraj Jitindar Singh 
spapr_cap_set_string(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)116f27aa81eSSuraj Jitindar Singh static void spapr_cap_set_string(Object *obj, Visitor *v, const char *name,
11787175d1bSSuraj Jitindar Singh                                  void *opaque, Error **errp)
11887175d1bSSuraj Jitindar Singh {
119ce2918cbSDavid Gibson     SpaprCapabilityInfo *cap = opaque;
120ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
12187175d1bSSuraj Jitindar Singh     uint8_t i;
122ea8464faSDaniel Henrique Barboza     g_autofree char *val = NULL;
12387175d1bSSuraj Jitindar Singh 
124668f62ecSMarkus Armbruster     if (!visit_type_str(v, name, &val, errp)) {
12587175d1bSSuraj Jitindar Singh         return;
12687175d1bSSuraj Jitindar Singh     }
12787175d1bSSuraj Jitindar Singh 
12887175d1bSSuraj Jitindar Singh     if (!strcmp(val, "?")) {
12987175d1bSSuraj Jitindar Singh         error_setg(errp, "%s", cap->possible->help);
130ea8464faSDaniel Henrique Barboza         return;
13187175d1bSSuraj Jitindar Singh     }
13287175d1bSSuraj Jitindar Singh     for (i = 0; i < cap->possible->num; i++) {
13387175d1bSSuraj Jitindar Singh         if (!strcasecmp(val, cap->possible->vals[i])) {
13487175d1bSSuraj Jitindar Singh             spapr->cmd_line_caps[cap->index] = true;
13587175d1bSSuraj Jitindar Singh             spapr->eff.caps[cap->index] = i;
136ea8464faSDaniel Henrique Barboza             return;
13787175d1bSSuraj Jitindar Singh         }
13887175d1bSSuraj Jitindar Singh     }
13987175d1bSSuraj Jitindar Singh 
14087175d1bSSuraj Jitindar Singh     error_setg(errp, "Invalid capability mode \"%s\" for cap-%s", val,
14187175d1bSSuraj Jitindar Singh                cap->name);
14287175d1bSSuraj Jitindar Singh }
14387175d1bSSuraj Jitindar Singh 
spapr_cap_get_pagesize(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)1442309832aSDavid Gibson static void spapr_cap_get_pagesize(Object *obj, Visitor *v, const char *name,
1452309832aSDavid Gibson                                    void *opaque, Error **errp)
1462309832aSDavid Gibson {
147ce2918cbSDavid Gibson     SpaprCapabilityInfo *cap = opaque;
148ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
1492309832aSDavid Gibson     uint8_t val = spapr_get_cap(spapr, cap->index);
1502309832aSDavid Gibson     uint64_t pagesize = (1ULL << val);
1512309832aSDavid Gibson 
1522309832aSDavid Gibson     visit_type_size(v, name, &pagesize, errp);
1532309832aSDavid Gibson }
1542309832aSDavid Gibson 
spapr_cap_set_pagesize(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)1552309832aSDavid Gibson static void spapr_cap_set_pagesize(Object *obj, Visitor *v, const char *name,
1562309832aSDavid Gibson                                    void *opaque, Error **errp)
1572309832aSDavid Gibson {
158ce2918cbSDavid Gibson     SpaprCapabilityInfo *cap = opaque;
159ce2918cbSDavid Gibson     SpaprMachineState *spapr = SPAPR_MACHINE(obj);
1602309832aSDavid Gibson     uint64_t pagesize;
1612309832aSDavid Gibson     uint8_t val;
1622309832aSDavid Gibson 
163668f62ecSMarkus Armbruster     if (!visit_type_size(v, name, &pagesize, errp)) {
1642309832aSDavid Gibson         return;
1652309832aSDavid Gibson     }
1662309832aSDavid Gibson 
1672309832aSDavid Gibson     if (!is_power_of_2(pagesize)) {
1682309832aSDavid Gibson         error_setg(errp, "cap-%s must be a power of 2", cap->name);
1692309832aSDavid Gibson         return;
1702309832aSDavid Gibson     }
1712309832aSDavid Gibson 
1722309832aSDavid Gibson     val = ctz64(pagesize);
1732309832aSDavid Gibson     spapr->cmd_line_caps[cap->index] = true;
1742309832aSDavid Gibson     spapr->eff.caps[cap->index] = val;
1752309832aSDavid Gibson }
1762309832aSDavid Gibson 
cap_htm_apply(SpaprMachineState * spapr,uint8_t val,Error ** errp)177ce2918cbSDavid Gibson static void cap_htm_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
1784e5fe368SSuraj Jitindar Singh {
179d9c5b5faSGreg Kurz     ERRP_GUARD();
1804e5fe368SSuraj Jitindar Singh     if (!val) {
1814e5fe368SSuraj Jitindar Singh         /* TODO: We don't support disabling htm yet */
1824e5fe368SSuraj Jitindar Singh         return;
1834e5fe368SSuraj Jitindar Singh     }
184ee76a09fSDavid Gibson     if (tcg_enabled()) {
185d9c5b5faSGreg Kurz         error_setg(errp, "No Transactional Memory support in TCG");
186d9c5b5faSGreg Kurz         error_append_hint(errp, "Try appending -machine cap-htm=off\n");
187ee76a09fSDavid Gibson     } else if (kvm_enabled() && !kvmppc_has_cap_htm()) {
188ee76a09fSDavid Gibson         error_setg(errp,
189d9c5b5faSGreg Kurz                    "KVM implementation does not support Transactional Memory");
190d9c5b5faSGreg Kurz         error_append_hint(errp, "Try appending -machine cap-htm=off\n");
191ee76a09fSDavid Gibson     }
192ee76a09fSDavid Gibson }
193ee76a09fSDavid Gibson 
cap_vsx_apply(SpaprMachineState * spapr,uint8_t val,Error ** errp)194ce2918cbSDavid Gibson static void cap_vsx_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
19529386642SDavid Gibson {
196d9c5b5faSGreg Kurz     ERRP_GUARD();
197794511bcSPhilippe Mathieu-Daudé     CPUPPCState *env = cpu_env(first_cpu);
19829386642SDavid Gibson 
1994e5fe368SSuraj Jitindar Singh     if (!val) {
2004e5fe368SSuraj Jitindar Singh         /* TODO: We don't support disabling vsx yet */
2014e5fe368SSuraj Jitindar Singh         return;
2024e5fe368SSuraj Jitindar Singh     }
20329386642SDavid Gibson     /* Allowable CPUs in spapr_cpu_core.c should already have gotten
20429386642SDavid Gibson      * rid of anything that doesn't do VMX */
20529386642SDavid Gibson     g_assert(env->insns_flags & PPC_ALTIVEC);
20629386642SDavid Gibson     if (!(env->insns_flags2 & PPC2_VSX)) {
207d9c5b5faSGreg Kurz         error_setg(errp, "VSX support not available");
208d9c5b5faSGreg Kurz         error_append_hint(errp, "Try appending -machine cap-vsx=off\n");
20929386642SDavid Gibson     }
21029386642SDavid Gibson }
21129386642SDavid Gibson 
cap_dfp_apply(SpaprMachineState * spapr,uint8_t val,Error ** errp)212ce2918cbSDavid Gibson static void cap_dfp_apply(SpaprMachineState *spapr, uint8_t val, Error **errp)
2132d1fb9bcSDavid Gibson {
214d9c5b5faSGreg Kurz     ERRP_GUARD();
2152d1fb9bcSDavid Gibson 
2164e5fe368SSuraj Jitindar Singh     if (!val) {
2174e5fe368SSuraj Jitindar Singh         /* TODO: We don't support disabling dfp yet */
2184e5fe368SSuraj Jitindar Singh         return;
2194e5fe368SSuraj Jitindar Singh     }
220794511bcSPhilippe Mathieu-Daudé     if (!(cpu_env(first_cpu)->insns_flags2 & PPC2_DFP)) {
221d9c5b5faSGreg Kurz         error_setg(errp, "DFP support not available");
222d9c5b5faSGreg Kurz         error_append_hint(errp, "Try appending -machine cap-dfp=off\n");
2232d1fb9bcSDavid Gibson     }
2242d1fb9bcSDavid Gibson }
2252d1fb9bcSDavid Gibson 
226ce2918cbSDavid Gibson SpaprCapPossible cap_cfpc_possible = {
227f27aa81eSSuraj Jitindar Singh     .num = 3,
228f27aa81eSSuraj Jitindar Singh     .vals = {"broken", "workaround", "fixed"},
229f27aa81eSSuraj Jitindar Singh     .help = "broken - no protection, workaround - workaround available,"
230f27aa81eSSuraj Jitindar Singh             " fixed - fixed in hardware",
231f27aa81eSSuraj Jitindar Singh };
232f27aa81eSSuraj Jitindar Singh 
cap_safe_cache_apply(SpaprMachineState * spapr,uint8_t val,Error ** errp)233ce2918cbSDavid Gibson static void cap_safe_cache_apply(SpaprMachineState *spapr, uint8_t val,
2348f38eaf8SSuraj Jitindar Singh                                  Error **errp)
2358f38eaf8SSuraj Jitindar Singh {
236d9c5b5faSGreg Kurz     ERRP_GUARD();
237f27aa81eSSuraj Jitindar Singh     uint8_t kvm_val =  kvmppc_get_cap_safe_cache();
238f27aa81eSSuraj Jitindar Singh 
2398f38eaf8SSuraj Jitindar Singh     if (tcg_enabled() && val) {
240006e9d36SSuraj Jitindar Singh         /* TCG only supports broken, allow other values and print a warning */
241a816f2d6SGreg Kurz         warn_report("TCG doesn't support requested feature, cap-cfpc=%s",
242006e9d36SSuraj Jitindar Singh                     cap_cfpc_possible.vals[val]);
243f27aa81eSSuraj Jitindar Singh     } else if (kvm_enabled() && (val > kvm_val)) {
244f27aa81eSSuraj Jitindar Singh         error_setg(errp,
245d9c5b5faSGreg Kurz                    "Requested safe cache capability level not supported by KVM");
246d9c5b5faSGreg Kurz         error_append_hint(errp, "Try appending -machine cap-cfpc=%s\n",
247f27aa81eSSuraj Jitindar Singh                           cap_cfpc_possible.vals[kvm_val]);
2488f38eaf8SSuraj Jitindar Singh     }
2498f38eaf8SSuraj Jitindar Singh }
2508f38eaf8SSuraj Jitindar Singh 
251ce2918cbSDavid Gibson SpaprCapPossible cap_sbbc_possible = {
252aaf265ffSSuraj Jitindar Singh     .num = 3,
253aaf265ffSSuraj Jitindar Singh     .vals = {"broken", "workaround", "fixed"},
254aaf265ffSSuraj Jitindar Singh     .help = "broken - no protection, workaround - workaround available,"
255aaf265ffSSuraj Jitindar Singh             " fixed - fixed in hardware",
256aaf265ffSSuraj Jitindar Singh };
257aaf265ffSSuraj Jitindar Singh 
cap_safe_bounds_check_apply(SpaprMachineState * spapr,uint8_t val,Error ** errp)258ce2918cbSDavid Gibson static void cap_safe_bounds_check_apply(SpaprMachineState *spapr, uint8_t val,
25909114fd8SSuraj Jitindar Singh                                         Error **errp)
26009114fd8SSuraj Jitindar Singh {
261d9c5b5faSGreg Kurz     ERRP_GUARD();
262aaf265ffSSuraj Jitindar Singh     uint8_t kvm_val =  kvmppc_get_cap_safe_bounds_check();
263aaf265ffSSuraj Jitindar Singh 
26409114fd8SSuraj Jitindar Singh     if (tcg_enabled() && val) {
265006e9d36SSuraj Jitindar Singh         /* TCG only supports broken, allow other values and print a warning */
266a816f2d6SGreg Kurz         warn_report("TCG doesn't support requested feature, cap-sbbc=%s",
267006e9d36SSuraj Jitindar Singh                     cap_sbbc_possible.vals[val]);
268aaf265ffSSuraj Jitindar Singh     } else if (kvm_enabled() && (val > kvm_val)) {
269aaf265ffSSuraj Jitindar Singh         error_setg(errp,
270d9c5b5faSGreg Kurz "Requested safe bounds check capability level not supported by KVM");
271d9c5b5faSGreg Kurz         error_append_hint(errp, "Try appending -machine cap-sbbc=%s\n",
272aaf265ffSSuraj Jitindar Singh                           cap_sbbc_possible.vals[kvm_val]);
27309114fd8SSuraj Jitindar Singh     }
27409114fd8SSuraj Jitindar Singh }
27509114fd8SSuraj Jitindar Singh 
276ce2918cbSDavid Gibson SpaprCapPossible cap_ibs_possible = {
277399b2896SSuraj Jitindar Singh     .num = 5,
278c76c0d30SSuraj Jitindar Singh     /* Note workaround only maintained for compatibility */
279399b2896SSuraj Jitindar Singh     .vals = {"broken", "workaround", "fixed-ibs", "fixed-ccd", "fixed-na"},
280399b2896SSuraj Jitindar Singh     .help = "broken - no protection, workaround - count cache flush"
281399b2896SSuraj Jitindar Singh             ", fixed-ibs - indirect branch serialisation,"
282399b2896SSuraj Jitindar Singh             " fixed-ccd - cache count disabled,"
283399b2896SSuraj Jitindar Singh             " fixed-na - fixed in hardware (no longer applicable)",
284c76c0d30SSuraj Jitindar Singh };
285c76c0d30SSuraj Jitindar Singh 
cap_safe_indirect_branch_apply(SpaprMachineState * spapr,uint8_t val,Error ** errp)286ce2918cbSDavid Gibson static void cap_safe_indirect_branch_apply(SpaprMachineState *spapr,
2874be8d4e7SSuraj Jitindar Singh                                            uint8_t val, Error **errp)
2884be8d4e7SSuraj Jitindar Singh {
289d9c5b5faSGreg Kurz     ERRP_GUARD();
290c76c0d30SSuraj Jitindar Singh     uint8_t kvm_val = kvmppc_get_cap_safe_indirect_branch();
291c76c0d30SSuraj Jitindar Singh 
292399b2896SSuraj Jitindar Singh     if (tcg_enabled() && val) {
293006e9d36SSuraj Jitindar Singh         /* TCG only supports broken, allow other values and print a warning */
294a816f2d6SGreg Kurz         warn_report("TCG doesn't support requested feature, cap-ibs=%s",
295006e9d36SSuraj Jitindar Singh                     cap_ibs_possible.vals[val]);
296399b2896SSuraj Jitindar Singh     } else if (kvm_enabled() && (val > kvm_val)) {
297c76c0d30SSuraj Jitindar Singh         error_setg(errp,
298d9c5b5faSGreg Kurz "Requested safe indirect branch capability level not supported by KVM");
299d9c5b5faSGreg Kurz         error_append_hint(errp, "Try appending -machine cap-ibs=%s\n",
300c76c0d30SSuraj Jitindar Singh                           cap_ibs_possible.vals[kvm_val]);
3014be8d4e7SSuraj Jitindar Singh     }
3024be8d4e7SSuraj Jitindar Singh }
3034be8d4e7SSuraj Jitindar Singh 
3048f38eaf8SSuraj Jitindar Singh #define VALUE_DESC_TRISTATE     " (broken, workaround, fixed)"
3054e5fe368SSuraj Jitindar Singh 
spapr_check_pagesize(SpaprMachineState * spapr,hwaddr pagesize,Error ** errp)30635dce34fSGreg Kurz bool spapr_check_pagesize(SpaprMachineState *spapr, hwaddr pagesize,
307123eec65SDavid Gibson                           Error **errp)
308123eec65SDavid Gibson {
309123eec65SDavid Gibson     hwaddr maxpagesize = (1ULL << spapr->eff.caps[SPAPR_CAP_HPT_MAXPAGESIZE]);
310123eec65SDavid Gibson 
311123eec65SDavid Gibson     if (!kvmppc_hpt_needs_host_contiguous_pages()) {
31235dce34fSGreg Kurz         return true;
313123eec65SDavid Gibson     }
314123eec65SDavid Gibson 
315123eec65SDavid Gibson     if (maxpagesize > pagesize) {
316123eec65SDavid Gibson         error_setg(errp,
317123eec65SDavid Gibson                    "Can't support %"HWADDR_PRIu" kiB guest pages with %"
318123eec65SDavid Gibson                    HWADDR_PRIu" kiB host pages with this KVM implementation",
319123eec65SDavid Gibson                    maxpagesize >> 10, pagesize >> 10);
32035dce34fSGreg Kurz         return false;
321123eec65SDavid Gibson     }
32235dce34fSGreg Kurz 
32335dce34fSGreg Kurz     return true;
324123eec65SDavid Gibson }
325123eec65SDavid Gibson 
cap_hpt_maxpagesize_apply(SpaprMachineState * spapr,uint8_t val,Error ** errp)326ce2918cbSDavid Gibson static void cap_hpt_maxpagesize_apply(SpaprMachineState *spapr,
3272309832aSDavid Gibson                                       uint8_t val, Error **errp)
3282309832aSDavid Gibson {
3292309832aSDavid Gibson     if (val < 12) {
3302309832aSDavid Gibson         error_setg(errp, "Require at least 4kiB hpt-max-page-size");
331123eec65SDavid Gibson         return;
3322309832aSDavid Gibson     } else if (val < 16) {
3332309832aSDavid Gibson         warn_report("Many guests require at least 64kiB hpt-max-page-size");
3342309832aSDavid Gibson     }
335123eec65SDavid Gibson 
336905b7ee4SDavid Hildenbrand     spapr_check_pagesize(spapr, qemu_minrampagesize(), errp);
3372309832aSDavid Gibson }
3382309832aSDavid Gibson 
cap_hpt_maxpagesize_migrate_needed(void * opaque)3393725ef1aSGreg Kurz static bool cap_hpt_maxpagesize_migrate_needed(void *opaque)
3403725ef1aSGreg Kurz {
3413725ef1aSGreg Kurz     return !SPAPR_MACHINE_GET_CLASS(opaque)->pre_4_1_migration;
3423725ef1aSGreg Kurz }
3433725ef1aSGreg Kurz 
spapr_pagesize_cb(void * opaque,uint32_t seg_pshift,uint32_t pshift)3449dceda5fSDavid Gibson static bool spapr_pagesize_cb(void *opaque, uint32_t seg_pshift,
3459dceda5fSDavid Gibson                               uint32_t pshift)
3469dceda5fSDavid Gibson {
3479dceda5fSDavid Gibson     unsigned maxshift = *((unsigned *)opaque);
3489dceda5fSDavid Gibson 
3499dceda5fSDavid Gibson     assert(pshift >= seg_pshift);
3509dceda5fSDavid Gibson 
3519dceda5fSDavid Gibson     /* Don't allow the guest to use pages bigger than the configured
3529dceda5fSDavid Gibson      * maximum size */
3539dceda5fSDavid Gibson     if (pshift > maxshift) {
3549dceda5fSDavid Gibson         return false;
3559dceda5fSDavid Gibson     }
3569dceda5fSDavid Gibson 
3579dceda5fSDavid Gibson     /* For whatever reason, KVM doesn't allow multiple pagesizes
3589dceda5fSDavid Gibson      * within a segment, *except* for the case of 16M pages in a 4k or
3599dceda5fSDavid Gibson      * 64k segment.  Always exclude other cases, so that TCG and KVM
3609dceda5fSDavid Gibson      * guests see a consistent environment */
3619dceda5fSDavid Gibson     if ((pshift != seg_pshift) && (pshift != 24)) {
3629dceda5fSDavid Gibson         return false;
3639dceda5fSDavid Gibson     }
3649dceda5fSDavid Gibson 
3659dceda5fSDavid Gibson     return true;
3669dceda5fSDavid Gibson }
3679dceda5fSDavid Gibson 
ppc_hash64_filter_pagesizes(PowerPCCPU * cpu,bool (* cb)(void *,uint32_t,uint32_t),void * opaque)368fd1eb085SLucas Mateus Castro (alqotel) static void ppc_hash64_filter_pagesizes(PowerPCCPU *cpu,
369fd1eb085SLucas Mateus Castro (alqotel)                                  bool (*cb)(void *, uint32_t, uint32_t),
370fd1eb085SLucas Mateus Castro (alqotel)                                  void *opaque)
371fd1eb085SLucas Mateus Castro (alqotel) {
372fd1eb085SLucas Mateus Castro (alqotel)     PPCHash64Options *opts = cpu->hash64_opts;
373fd1eb085SLucas Mateus Castro (alqotel)     int i;
374fd1eb085SLucas Mateus Castro (alqotel)     int n = 0;
375fd1eb085SLucas Mateus Castro (alqotel)     bool ci_largepage = false;
376fd1eb085SLucas Mateus Castro (alqotel) 
377fd1eb085SLucas Mateus Castro (alqotel)     assert(opts);
378fd1eb085SLucas Mateus Castro (alqotel) 
379fd1eb085SLucas Mateus Castro (alqotel)     n = 0;
380fd1eb085SLucas Mateus Castro (alqotel)     for (i = 0; i < ARRAY_SIZE(opts->sps); i++) {
381fd1eb085SLucas Mateus Castro (alqotel)         PPCHash64SegmentPageSizes *sps = &opts->sps[i];
382fd1eb085SLucas Mateus Castro (alqotel)         int j;
383fd1eb085SLucas Mateus Castro (alqotel)         int m = 0;
384fd1eb085SLucas Mateus Castro (alqotel) 
385fd1eb085SLucas Mateus Castro (alqotel)         assert(n <= i);
386fd1eb085SLucas Mateus Castro (alqotel) 
387fd1eb085SLucas Mateus Castro (alqotel)         if (!sps->page_shift) {
388fd1eb085SLucas Mateus Castro (alqotel)             break;
389fd1eb085SLucas Mateus Castro (alqotel)         }
390fd1eb085SLucas Mateus Castro (alqotel) 
391fd1eb085SLucas Mateus Castro (alqotel)         for (j = 0; j < ARRAY_SIZE(sps->enc); j++) {
392fd1eb085SLucas Mateus Castro (alqotel)             PPCHash64PageSize *ps = &sps->enc[j];
393fd1eb085SLucas Mateus Castro (alqotel) 
394fd1eb085SLucas Mateus Castro (alqotel)             assert(m <= j);
395fd1eb085SLucas Mateus Castro (alqotel)             if (!ps->page_shift) {
396fd1eb085SLucas Mateus Castro (alqotel)                 break;
397fd1eb085SLucas Mateus Castro (alqotel)             }
398fd1eb085SLucas Mateus Castro (alqotel) 
399fd1eb085SLucas Mateus Castro (alqotel)             if (cb(opaque, sps->page_shift, ps->page_shift)) {
400fd1eb085SLucas Mateus Castro (alqotel)                 if (ps->page_shift >= 16) {
401fd1eb085SLucas Mateus Castro (alqotel)                     ci_largepage = true;
402fd1eb085SLucas Mateus Castro (alqotel)                 }
403fd1eb085SLucas Mateus Castro (alqotel)                 sps->enc[m++] = *ps;
404fd1eb085SLucas Mateus Castro (alqotel)             }
405fd1eb085SLucas Mateus Castro (alqotel)         }
406fd1eb085SLucas Mateus Castro (alqotel) 
407fd1eb085SLucas Mateus Castro (alqotel)         /* Clear rest of the row */
408fd1eb085SLucas Mateus Castro (alqotel)         for (j = m; j < ARRAY_SIZE(sps->enc); j++) {
409fd1eb085SLucas Mateus Castro (alqotel)             memset(&sps->enc[j], 0, sizeof(sps->enc[j]));
410fd1eb085SLucas Mateus Castro (alqotel)         }
411fd1eb085SLucas Mateus Castro (alqotel) 
412fd1eb085SLucas Mateus Castro (alqotel)         if (m) {
413fd1eb085SLucas Mateus Castro (alqotel)             n++;
414fd1eb085SLucas Mateus Castro (alqotel)         }
415fd1eb085SLucas Mateus Castro (alqotel)     }
416fd1eb085SLucas Mateus Castro (alqotel) 
417fd1eb085SLucas Mateus Castro (alqotel)     /* Clear the rest of the table */
418fd1eb085SLucas Mateus Castro (alqotel)     for (i = n; i < ARRAY_SIZE(opts->sps); i++) {
419fd1eb085SLucas Mateus Castro (alqotel)         memset(&opts->sps[i], 0, sizeof(opts->sps[i]));
420fd1eb085SLucas Mateus Castro (alqotel)     }
421fd1eb085SLucas Mateus Castro (alqotel) 
422fd1eb085SLucas Mateus Castro (alqotel)     if (!ci_largepage) {
423fd1eb085SLucas Mateus Castro (alqotel)         opts->flags &= ~PPC_HASH64_CI_LARGEPAGE;
424fd1eb085SLucas Mateus Castro (alqotel)     }
425fd1eb085SLucas Mateus Castro (alqotel) }
426fd1eb085SLucas Mateus Castro (alqotel) 
cap_hpt_maxpagesize_cpu_apply(SpaprMachineState * spapr,PowerPCCPU * cpu,uint8_t val,Error ** errp)427ce2918cbSDavid Gibson static void cap_hpt_maxpagesize_cpu_apply(SpaprMachineState *spapr,
4289dceda5fSDavid Gibson                                           PowerPCCPU *cpu,
4299dceda5fSDavid Gibson                                           uint8_t val, Error **errp)
4309dceda5fSDavid Gibson {
4319dceda5fSDavid Gibson     unsigned maxshift = val;
4329dceda5fSDavid Gibson 
4339dceda5fSDavid Gibson     ppc_hash64_filter_pagesizes(cpu, spapr_pagesize_cb, &maxshift);
4349dceda5fSDavid Gibson }
4359dceda5fSDavid Gibson 
cap_nested_kvm_hv_apply(SpaprMachineState * spapr,uint8_t val,Error ** errp)436ce2918cbSDavid Gibson static void cap_nested_kvm_hv_apply(SpaprMachineState *spapr,
437b9a477b7SSuraj Jitindar Singh                                     uint8_t val, Error **errp)
438b9a477b7SSuraj Jitindar Singh {
439d9c5b5faSGreg Kurz     ERRP_GUARD();
44019d55e20SGreg Kurz     PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
441120f738aSNicholas Piggin     CPUPPCState *env = &cpu->env;
44219d55e20SGreg Kurz 
443b9a477b7SSuraj Jitindar Singh     if (!val) {
444b9a477b7SSuraj Jitindar Singh         /* capability disabled by default */
445b9a477b7SSuraj Jitindar Singh         return;
446b9a477b7SSuraj Jitindar Singh     }
447b9a477b7SSuraj Jitindar Singh 
448120f738aSNicholas Piggin     if (!(env->insns_flags2 & PPC2_ISA300)) {
449120f738aSNicholas Piggin         error_setg(errp, "Nested-HV only supported on POWER9 and later");
450d9c5b5faSGreg Kurz         error_append_hint(errp, "Try appending -machine cap-nested-hv=off\n");
451120f738aSNicholas Piggin         return;
452120f738aSNicholas Piggin     }
453120f738aSNicholas Piggin 
454120f738aSNicholas Piggin     if (kvm_enabled()) {
45519d55e20SGreg Kurz         if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0,
45619d55e20SGreg Kurz                               spapr->max_compat_pvr)) {
457120f738aSNicholas Piggin             error_setg(errp, "Nested-HV only supported on POWER9 and later");
45819d55e20SGreg Kurz             error_append_hint(errp,
45919d55e20SGreg Kurz                               "Try appending -machine max-cpu-compat=power9\n");
46019d55e20SGreg Kurz             return;
46119d55e20SGreg Kurz         }
46219d55e20SGreg Kurz 
463b9a477b7SSuraj Jitindar Singh         if (!kvmppc_has_cap_nested_kvm_hv()) {
464b9a477b7SSuraj Jitindar Singh             error_setg(errp,
465120f738aSNicholas Piggin                        "KVM implementation does not support Nested-HV");
466d9c5b5faSGreg Kurz             error_append_hint(errp,
467d9c5b5faSGreg Kurz                               "Try appending -machine cap-nested-hv=off\n");
468b9a477b7SSuraj Jitindar Singh         } else if (kvmppc_set_cap_nested_kvm_hv(val) < 0) {
469d9c5b5faSGreg Kurz                 error_setg(errp, "Error enabling cap-nested-hv with KVM");
470d9c5b5faSGreg Kurz                 error_append_hint(errp,
471d9c5b5faSGreg Kurz                                   "Try appending -machine cap-nested-hv=off\n");
472b9a477b7SSuraj Jitindar Singh         }
473dc5e0721SNicholas Piggin     } else if (tcg_enabled()) {
474dc5e0721SNicholas Piggin         MachineState *ms = MACHINE(spapr);
475dc5e0721SNicholas Piggin         unsigned int smp_threads = ms->smp.threads;
476dc5e0721SNicholas Piggin 
477dc5e0721SNicholas Piggin         /*
478dc5e0721SNicholas Piggin          * Nested-HV vCPU env state to L2, so SMT-shared SPR updates, for
479dc5e0721SNicholas Piggin          * example, do not necessarily update the correct SPR value on sibling
480dc5e0721SNicholas Piggin          * threads that are in a different guest/host context.
481dc5e0721SNicholas Piggin          */
482dc5e0721SNicholas Piggin         if (smp_threads > 1) {
483dc5e0721SNicholas Piggin             error_setg(errp, "TCG does not support nested-HV with SMT");
484dc5e0721SNicholas Piggin             error_append_hint(errp, "Try appending -machine cap-nested-hv=off "
485dc5e0721SNicholas Piggin                                     "or use threads=1 with -smp\n");
486dc5e0721SNicholas Piggin         }
487e1617b84SHarsh Prateek Bora         if (spapr_nested_api(spapr) &&
488e1617b84SHarsh Prateek Bora             spapr_nested_api(spapr) != NESTED_API_KVM_HV) {
489e1617b84SHarsh Prateek Bora             error_setg(errp, "Nested-HV APIs are mutually exclusive");
490e1617b84SHarsh Prateek Bora             error_append_hint(errp, "Please use either cap-nested-hv or "
491e1617b84SHarsh Prateek Bora                                     "cap-nested-papr to proceed.\n");
492e1617b84SHarsh Prateek Bora             return;
493e1617b84SHarsh Prateek Bora         } else {
494e1617b84SHarsh Prateek Bora             spapr->nested.api = NESTED_API_KVM_HV;
495e1617b84SHarsh Prateek Bora         }
496e1617b84SHarsh Prateek Bora     }
497e1617b84SHarsh Prateek Bora }
498e1617b84SHarsh Prateek Bora 
cap_nested_papr_apply(SpaprMachineState * spapr,uint8_t val,Error ** errp)499e1617b84SHarsh Prateek Bora static void cap_nested_papr_apply(SpaprMachineState *spapr,
500e1617b84SHarsh Prateek Bora                                     uint8_t val, Error **errp)
501e1617b84SHarsh Prateek Bora {
502e1617b84SHarsh Prateek Bora     ERRP_GUARD();
503e1617b84SHarsh Prateek Bora     PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
504e1617b84SHarsh Prateek Bora     CPUPPCState *env = &cpu->env;
505e1617b84SHarsh Prateek Bora 
506e1617b84SHarsh Prateek Bora     if (!val) {
507e1617b84SHarsh Prateek Bora         /* capability disabled by default */
508e1617b84SHarsh Prateek Bora         return;
509e1617b84SHarsh Prateek Bora     }
510e1617b84SHarsh Prateek Bora 
511e1617b84SHarsh Prateek Bora     if (tcg_enabled()) {
512e1617b84SHarsh Prateek Bora         if (!(env->insns_flags2 & PPC2_ISA300)) {
513e1617b84SHarsh Prateek Bora             error_setg(errp, "Nested-PAPR only supported on POWER9 and later");
514e1617b84SHarsh Prateek Bora             error_append_hint(errp,
515e1617b84SHarsh Prateek Bora                               "Try appending -machine cap-nested-papr=off\n");
516e1617b84SHarsh Prateek Bora             return;
517e1617b84SHarsh Prateek Bora         }
518e1617b84SHarsh Prateek Bora         if (spapr_nested_api(spapr) &&
519e1617b84SHarsh Prateek Bora             spapr_nested_api(spapr) != NESTED_API_PAPR) {
520e1617b84SHarsh Prateek Bora             error_setg(errp, "Nested-HV APIs are mutually exclusive");
521e1617b84SHarsh Prateek Bora             error_append_hint(errp, "Please use either cap-nested-hv or "
522e1617b84SHarsh Prateek Bora                                     "cap-nested-papr to proceed.\n");
523e1617b84SHarsh Prateek Bora             return;
524e1617b84SHarsh Prateek Bora         } else {
525e1617b84SHarsh Prateek Bora             spapr->nested.api = NESTED_API_PAPR;
526e1617b84SHarsh Prateek Bora         }
527e1617b84SHarsh Prateek Bora     } else if (kvm_enabled()) {
528e1617b84SHarsh Prateek Bora         error_setg(errp, "KVM implementation does not support Nested-PAPR");
529e1617b84SHarsh Prateek Bora         error_append_hint(errp,
530e1617b84SHarsh Prateek Bora                           "Try appending -machine cap-nested-papr=off\n");
531b9a477b7SSuraj Jitindar Singh     }
532b9a477b7SSuraj Jitindar Singh }
533b9a477b7SSuraj Jitindar Singh 
cap_large_decr_apply(SpaprMachineState * spapr,uint8_t val,Error ** errp)534ce2918cbSDavid Gibson static void cap_large_decr_apply(SpaprMachineState *spapr,
535c982f5cfSSuraj Jitindar Singh                                  uint8_t val, Error **errp)
536c982f5cfSSuraj Jitindar Singh {
537d9c5b5faSGreg Kurz     ERRP_GUARD();
538a8dafa52SSuraj Jitindar Singh     PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
5397d050527SSuraj Jitindar Singh     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
540a8dafa52SSuraj Jitindar Singh 
541a8dafa52SSuraj Jitindar Singh     if (!val) {
542a8dafa52SSuraj Jitindar Singh         return; /* Disabled by default */
543a8dafa52SSuraj Jitindar Singh     }
544a8dafa52SSuraj Jitindar Singh 
545a8dafa52SSuraj Jitindar Singh     if (tcg_enabled()) {
546a8dafa52SSuraj Jitindar Singh         if (!ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0,
547a8dafa52SSuraj Jitindar Singh                               spapr->max_compat_pvr)) {
548d9c5b5faSGreg Kurz             error_setg(errp, "Large decrementer only supported on POWER9");
549d9c5b5faSGreg Kurz             error_append_hint(errp, "Try -cpu POWER9\n");
550a8dafa52SSuraj Jitindar Singh             return;
551a8dafa52SSuraj Jitindar Singh         }
5527d050527SSuraj Jitindar Singh     } else if (kvm_enabled()) {
5537d050527SSuraj Jitindar Singh         int kvm_nr_bits = kvmppc_get_cap_large_decr();
5547d050527SSuraj Jitindar Singh 
5557d050527SSuraj Jitindar Singh         if (!kvm_nr_bits) {
556d9c5b5faSGreg Kurz             error_setg(errp, "No large decrementer support");
557d9c5b5faSGreg Kurz             error_append_hint(errp,
558d9c5b5faSGreg Kurz                               "Try appending -machine cap-large-decr=off\n");
5597d050527SSuraj Jitindar Singh         } else if (pcc->lrg_decr_bits != kvm_nr_bits) {
5607d050527SSuraj Jitindar Singh             error_setg(errp,
561d9c5b5faSGreg Kurz                        "KVM large decrementer size (%d) differs to model (%d)",
5627d050527SSuraj Jitindar Singh                        kvm_nr_bits, pcc->lrg_decr_bits);
563d9c5b5faSGreg Kurz             error_append_hint(errp,
564d9c5b5faSGreg Kurz                               "Try appending -machine cap-large-decr=off\n");
5657d050527SSuraj Jitindar Singh         }
566c982f5cfSSuraj Jitindar Singh     }
567a8dafa52SSuraj Jitindar Singh }
568a8dafa52SSuraj Jitindar Singh 
cap_large_decr_cpu_apply(SpaprMachineState * spapr,PowerPCCPU * cpu,uint8_t val,Error ** errp)569ce2918cbSDavid Gibson static void cap_large_decr_cpu_apply(SpaprMachineState *spapr,
570a8dafa52SSuraj Jitindar Singh                                      PowerPCCPU *cpu,
571a8dafa52SSuraj Jitindar Singh                                      uint8_t val, Error **errp)
572a8dafa52SSuraj Jitindar Singh {
573d9c5b5faSGreg Kurz     ERRP_GUARD();
574a8dafa52SSuraj Jitindar Singh     CPUPPCState *env = &cpu->env;
575a8dafa52SSuraj Jitindar Singh     target_ulong lpcr = env->spr[SPR_LPCR];
576a8dafa52SSuraj Jitindar Singh 
5777d050527SSuraj Jitindar Singh     if (kvm_enabled()) {
5787d050527SSuraj Jitindar Singh         if (kvmppc_enable_cap_large_decr(cpu, val)) {
579d9c5b5faSGreg Kurz             error_setg(errp, "No large decrementer support");
580d9c5b5faSGreg Kurz             error_append_hint(errp,
581d9c5b5faSGreg Kurz                               "Try appending -machine cap-large-decr=off\n");
5827d050527SSuraj Jitindar Singh         }
5837d050527SSuraj Jitindar Singh     }
5847d050527SSuraj Jitindar Singh 
585a8dafa52SSuraj Jitindar Singh     if (val) {
586a8dafa52SSuraj Jitindar Singh         lpcr |= LPCR_LD;
587a8dafa52SSuraj Jitindar Singh     } else {
588a8dafa52SSuraj Jitindar Singh         lpcr &= ~LPCR_LD;
589a8dafa52SSuraj Jitindar Singh     }
590a8dafa52SSuraj Jitindar Singh     ppc_store_lpcr(cpu, lpcr);
591a8dafa52SSuraj Jitindar Singh }
592c982f5cfSSuraj Jitindar Singh 
cap_ccf_assist_apply(SpaprMachineState * spapr,uint8_t val,Error ** errp)593ce2918cbSDavid Gibson static void cap_ccf_assist_apply(SpaprMachineState *spapr, uint8_t val,
5948ff43ee4SSuraj Jitindar Singh                                  Error **errp)
5958ff43ee4SSuraj Jitindar Singh {
596d9c5b5faSGreg Kurz     ERRP_GUARD();
5978ff43ee4SSuraj Jitindar Singh     uint8_t kvm_val = kvmppc_get_cap_count_cache_flush_assist();
5988ff43ee4SSuraj Jitindar Singh 
5998ff43ee4SSuraj Jitindar Singh     if (tcg_enabled() && val) {
60037965dfeSDavid Gibson         /* TCG doesn't implement anything here, but allow with a warning */
60137965dfeSDavid Gibson         warn_report("TCG doesn't support requested feature, cap-ccf-assist=on");
6028ff43ee4SSuraj Jitindar Singh     } else if (kvm_enabled() && (val > kvm_val)) {
60337965dfeSDavid Gibson         uint8_t kvm_ibs = kvmppc_get_cap_safe_indirect_branch();
60437965dfeSDavid Gibson 
60537965dfeSDavid Gibson         if (kvm_ibs == SPAPR_CAP_FIXED_CCD) {
60637965dfeSDavid Gibson             /*
60737965dfeSDavid Gibson              * If we don't have CCF assist on the host, the assist
60837965dfeSDavid Gibson              * instruction is a harmless no-op.  It won't correctly
60937965dfeSDavid Gibson              * implement the cache count flush *but* if we have
61037965dfeSDavid Gibson              * count-cache-disabled in the host, that flush is
611118d4ed0SDr. David Alan Gilbert              * unnecessary.  So, specifically allow this case.  This
61237965dfeSDavid Gibson              * allows us to have better performance on POWER9 DD2.3,
61337965dfeSDavid Gibson              * while still working on POWER9 DD2.2 and POWER8 host
61437965dfeSDavid Gibson              * cpus.
61537965dfeSDavid Gibson              */
61637965dfeSDavid Gibson             return;
61737965dfeSDavid Gibson         }
6188ff43ee4SSuraj Jitindar Singh         error_setg(errp,
619d9c5b5faSGreg Kurz                    "Requested count cache flush assist capability level not supported by KVM");
620d9c5b5faSGreg Kurz         error_append_hint(errp, "Try appending -machine cap-ccf-assist=off\n");
6218ff43ee4SSuraj Jitindar Singh     }
6228ff43ee4SSuraj Jitindar Singh }
6238ff43ee4SSuraj Jitindar Singh 
cap_fwnmi_apply(SpaprMachineState * spapr,uint8_t val,Error ** errp)6248af7e1feSNicholas Piggin static void cap_fwnmi_apply(SpaprMachineState *spapr, uint8_t val,
6259d953ce4SAravinda Prasad                                 Error **errp)
6269d953ce4SAravinda Prasad {
627d9c5b5faSGreg Kurz     ERRP_GUARD();
6289d953ce4SAravinda Prasad     if (!val) {
6299d953ce4SAravinda Prasad         return; /* Disabled by default */
6309d953ce4SAravinda Prasad     }
631f03496bcSAravinda Prasad 
63289ba4565SNicholas Piggin     if (kvm_enabled()) {
633ec010c00SNicholas Piggin         if (!kvmppc_get_fwnmi()) {
634ec010c00SNicholas Piggin             error_setg(errp,
635ec010c00SNicholas Piggin "Firmware Assisted Non-Maskable Interrupts(FWNMI) not supported by KVM.");
636ec010c00SNicholas Piggin             error_append_hint(errp, "Try appending -machine cap-fwnmi=off\n");
637f03496bcSAravinda Prasad         }
638f03496bcSAravinda Prasad     }
6399d953ce4SAravinda Prasad }
6409d953ce4SAravinda Prasad 
cap_rpt_invalidate_apply(SpaprMachineState * spapr,uint8_t val,Error ** errp)64182123b75SBharata B Rao static void cap_rpt_invalidate_apply(SpaprMachineState *spapr,
64282123b75SBharata B Rao                                      uint8_t val, Error **errp)
64382123b75SBharata B Rao {
64482123b75SBharata B Rao     ERRP_GUARD();
64582123b75SBharata B Rao 
64682123b75SBharata B Rao     if (!val) {
64782123b75SBharata B Rao         /* capability disabled by default */
64882123b75SBharata B Rao         return;
64982123b75SBharata B Rao     }
65082123b75SBharata B Rao 
65182123b75SBharata B Rao     if (tcg_enabled()) {
65282123b75SBharata B Rao         error_setg(errp, "No H_RPT_INVALIDATE support in TCG");
65382123b75SBharata B Rao         error_append_hint(errp,
65482123b75SBharata B Rao                           "Try appending -machine cap-rpt-invalidate=off\n");
65582123b75SBharata B Rao     } else if (kvm_enabled()) {
65682123b75SBharata B Rao         if (!kvmppc_has_cap_mmu_radix()) {
65782123b75SBharata B Rao             error_setg(errp, "H_RPT_INVALIDATE only supported on Radix");
65882123b75SBharata B Rao             return;
65982123b75SBharata B Rao         }
66082123b75SBharata B Rao 
66182123b75SBharata B Rao         if (!kvmppc_has_cap_rpt_invalidate()) {
66282123b75SBharata B Rao             error_setg(errp,
66382123b75SBharata B Rao                        "KVM implementation does not support H_RPT_INVALIDATE");
66482123b75SBharata B Rao             error_append_hint(errp,
66582123b75SBharata B Rao                               "Try appending -machine cap-rpt-invalidate=off\n");
66682123b75SBharata B Rao         } else {
66782123b75SBharata B Rao             kvmppc_enable_h_rpt_invalidate();
66882123b75SBharata B Rao         }
66982123b75SBharata B Rao     }
67082123b75SBharata B Rao }
67182123b75SBharata B Rao 
cap_ail_mode_3_apply(SpaprMachineState * spapr,uint8_t val,Error ** errp)672ccc5a4c5SNicholas Piggin static void cap_ail_mode_3_apply(SpaprMachineState *spapr,
673ccc5a4c5SNicholas Piggin                                      uint8_t val, Error **errp)
674ccc5a4c5SNicholas Piggin {
675ccc5a4c5SNicholas Piggin     ERRP_GUARD();
676ccc5a4c5SNicholas Piggin     PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
677ccc5a4c5SNicholas Piggin     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
678ccc5a4c5SNicholas Piggin 
679ccc5a4c5SNicholas Piggin     if (!val) {
680ccc5a4c5SNicholas Piggin         return;
681ccc5a4c5SNicholas Piggin     }
682ccc5a4c5SNicholas Piggin 
683ccc5a4c5SNicholas Piggin     if (tcg_enabled()) {
684ccc5a4c5SNicholas Piggin         /* AIL-3 is only supported on POWER8 and above CPUs. */
685ccc5a4c5SNicholas Piggin         if (!(pcc->insns_flags2 & PPC2_ISA207S)) {
686ccc5a4c5SNicholas Piggin             error_setg(errp, "TCG only supports cap-ail-mode-3 on POWER8 and later CPUs");
687ccc5a4c5SNicholas Piggin             error_append_hint(errp, "Try appending -machine cap-ail-mode-3=off\n");
688ccc5a4c5SNicholas Piggin             return;
689ccc5a4c5SNicholas Piggin         }
690ccc5a4c5SNicholas Piggin     } else if (kvm_enabled()) {
691ccc5a4c5SNicholas Piggin         if (!kvmppc_supports_ail_3()) {
692ccc5a4c5SNicholas Piggin             error_setg(errp, "KVM implementation does not support cap-ail-mode-3");
693ccc5a4c5SNicholas Piggin             error_append_hint(errp, "Try appending -machine cap-ail-mode-3=off\n");
694ccc5a4c5SNicholas Piggin             return;
695ccc5a4c5SNicholas Piggin         }
696ccc5a4c5SNicholas Piggin     }
697ccc5a4c5SNicholas Piggin }
698ccc5a4c5SNicholas Piggin 
699ce2918cbSDavid Gibson SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
7004e5fe368SSuraj Jitindar Singh     [SPAPR_CAP_HTM] = {
701ee76a09fSDavid Gibson         .name = "htm",
702ee76a09fSDavid Gibson         .description = "Allow Hardware Transactional Memory (HTM)",
7034e5fe368SSuraj Jitindar Singh         .index = SPAPR_CAP_HTM,
7044e5fe368SSuraj Jitindar Singh         .get = spapr_cap_get_bool,
7054e5fe368SSuraj Jitindar Singh         .set = spapr_cap_set_bool,
7064e5fe368SSuraj Jitindar Singh         .type = "bool",
7074e5fe368SSuraj Jitindar Singh         .apply = cap_htm_apply,
708ee76a09fSDavid Gibson     },
7094e5fe368SSuraj Jitindar Singh     [SPAPR_CAP_VSX] = {
71029386642SDavid Gibson         .name = "vsx",
71129386642SDavid Gibson         .description = "Allow Vector Scalar Extensions (VSX)",
7124e5fe368SSuraj Jitindar Singh         .index = SPAPR_CAP_VSX,
7134e5fe368SSuraj Jitindar Singh         .get = spapr_cap_get_bool,
7144e5fe368SSuraj Jitindar Singh         .set = spapr_cap_set_bool,
7154e5fe368SSuraj Jitindar Singh         .type = "bool",
7164e5fe368SSuraj Jitindar Singh         .apply = cap_vsx_apply,
71729386642SDavid Gibson     },
7184e5fe368SSuraj Jitindar Singh     [SPAPR_CAP_DFP] = {
7192d1fb9bcSDavid Gibson         .name = "dfp",
7202d1fb9bcSDavid Gibson         .description = "Allow Decimal Floating Point (DFP)",
7214e5fe368SSuraj Jitindar Singh         .index = SPAPR_CAP_DFP,
7224e5fe368SSuraj Jitindar Singh         .get = spapr_cap_get_bool,
7234e5fe368SSuraj Jitindar Singh         .set = spapr_cap_set_bool,
7244e5fe368SSuraj Jitindar Singh         .type = "bool",
7254e5fe368SSuraj Jitindar Singh         .apply = cap_dfp_apply,
7262d1fb9bcSDavid Gibson     },
7278f38eaf8SSuraj Jitindar Singh     [SPAPR_CAP_CFPC] = {
7288f38eaf8SSuraj Jitindar Singh         .name = "cfpc",
7298f38eaf8SSuraj Jitindar Singh         .description = "Cache Flush on Privilege Change" VALUE_DESC_TRISTATE,
7308f38eaf8SSuraj Jitindar Singh         .index = SPAPR_CAP_CFPC,
731f27aa81eSSuraj Jitindar Singh         .get = spapr_cap_get_string,
732f27aa81eSSuraj Jitindar Singh         .set = spapr_cap_set_string,
7338f38eaf8SSuraj Jitindar Singh         .type = "string",
734f27aa81eSSuraj Jitindar Singh         .possible = &cap_cfpc_possible,
7358f38eaf8SSuraj Jitindar Singh         .apply = cap_safe_cache_apply,
7368f38eaf8SSuraj Jitindar Singh     },
73709114fd8SSuraj Jitindar Singh     [SPAPR_CAP_SBBC] = {
73809114fd8SSuraj Jitindar Singh         .name = "sbbc",
73909114fd8SSuraj Jitindar Singh         .description = "Speculation Barrier Bounds Checking" VALUE_DESC_TRISTATE,
74009114fd8SSuraj Jitindar Singh         .index = SPAPR_CAP_SBBC,
741aaf265ffSSuraj Jitindar Singh         .get = spapr_cap_get_string,
742aaf265ffSSuraj Jitindar Singh         .set = spapr_cap_set_string,
74309114fd8SSuraj Jitindar Singh         .type = "string",
744aaf265ffSSuraj Jitindar Singh         .possible = &cap_sbbc_possible,
74509114fd8SSuraj Jitindar Singh         .apply = cap_safe_bounds_check_apply,
74609114fd8SSuraj Jitindar Singh     },
7474be8d4e7SSuraj Jitindar Singh     [SPAPR_CAP_IBS] = {
7484be8d4e7SSuraj Jitindar Singh         .name = "ibs",
749c76c0d30SSuraj Jitindar Singh         .description =
750399b2896SSuraj Jitindar Singh             "Indirect Branch Speculation (broken, workaround, fixed-ibs,"
751399b2896SSuraj Jitindar Singh             "fixed-ccd, fixed-na)",
7524be8d4e7SSuraj Jitindar Singh         .index = SPAPR_CAP_IBS,
753c76c0d30SSuraj Jitindar Singh         .get = spapr_cap_get_string,
754c76c0d30SSuraj Jitindar Singh         .set = spapr_cap_set_string,
7554be8d4e7SSuraj Jitindar Singh         .type = "string",
756c76c0d30SSuraj Jitindar Singh         .possible = &cap_ibs_possible,
7574be8d4e7SSuraj Jitindar Singh         .apply = cap_safe_indirect_branch_apply,
7584be8d4e7SSuraj Jitindar Singh     },
7592309832aSDavid Gibson     [SPAPR_CAP_HPT_MAXPAGESIZE] = {
7602309832aSDavid Gibson         .name = "hpt-max-page-size",
7612309832aSDavid Gibson         .description = "Maximum page size for Hash Page Table guests",
7622309832aSDavid Gibson         .index = SPAPR_CAP_HPT_MAXPAGESIZE,
7632309832aSDavid Gibson         .get = spapr_cap_get_pagesize,
7642309832aSDavid Gibson         .set = spapr_cap_set_pagesize,
7652309832aSDavid Gibson         .type = "int",
7662309832aSDavid Gibson         .apply = cap_hpt_maxpagesize_apply,
7679dceda5fSDavid Gibson         .cpu_apply = cap_hpt_maxpagesize_cpu_apply,
7683725ef1aSGreg Kurz         .migrate_needed = cap_hpt_maxpagesize_migrate_needed,
7692309832aSDavid Gibson     },
770b9a477b7SSuraj Jitindar Singh     [SPAPR_CAP_NESTED_KVM_HV] = {
771b9a477b7SSuraj Jitindar Singh         .name = "nested-hv",
772b9a477b7SSuraj Jitindar Singh         .description = "Allow Nested KVM-HV",
773b9a477b7SSuraj Jitindar Singh         .index = SPAPR_CAP_NESTED_KVM_HV,
774b9a477b7SSuraj Jitindar Singh         .get = spapr_cap_get_bool,
775b9a477b7SSuraj Jitindar Singh         .set = spapr_cap_set_bool,
776b9a477b7SSuraj Jitindar Singh         .type = "bool",
777b9a477b7SSuraj Jitindar Singh         .apply = cap_nested_kvm_hv_apply,
778b9a477b7SSuraj Jitindar Singh     },
779e1617b84SHarsh Prateek Bora     [SPAPR_CAP_NESTED_PAPR] = {
780e1617b84SHarsh Prateek Bora         .name = "nested-papr",
781e1617b84SHarsh Prateek Bora         .description = "Allow Nested HV (PAPR API)",
782e1617b84SHarsh Prateek Bora         .index = SPAPR_CAP_NESTED_PAPR,
783e1617b84SHarsh Prateek Bora         .get = spapr_cap_get_bool,
784e1617b84SHarsh Prateek Bora         .set = spapr_cap_set_bool,
785e1617b84SHarsh Prateek Bora         .type = "bool",
786e1617b84SHarsh Prateek Bora         .apply = cap_nested_papr_apply,
787e1617b84SHarsh Prateek Bora     },
788c982f5cfSSuraj Jitindar Singh     [SPAPR_CAP_LARGE_DECREMENTER] = {
789c982f5cfSSuraj Jitindar Singh         .name = "large-decr",
790c982f5cfSSuraj Jitindar Singh         .description = "Allow Large Decrementer",
791c982f5cfSSuraj Jitindar Singh         .index = SPAPR_CAP_LARGE_DECREMENTER,
792c982f5cfSSuraj Jitindar Singh         .get = spapr_cap_get_bool,
793c982f5cfSSuraj Jitindar Singh         .set = spapr_cap_set_bool,
794c982f5cfSSuraj Jitindar Singh         .type = "bool",
795c982f5cfSSuraj Jitindar Singh         .apply = cap_large_decr_apply,
796a8dafa52SSuraj Jitindar Singh         .cpu_apply = cap_large_decr_cpu_apply,
797c982f5cfSSuraj Jitindar Singh     },
7988ff43ee4SSuraj Jitindar Singh     [SPAPR_CAP_CCF_ASSIST] = {
7998ff43ee4SSuraj Jitindar Singh         .name = "ccf-assist",
8008ff43ee4SSuraj Jitindar Singh         .description = "Count Cache Flush Assist via HW Instruction",
8018ff43ee4SSuraj Jitindar Singh         .index = SPAPR_CAP_CCF_ASSIST,
8028ff43ee4SSuraj Jitindar Singh         .get = spapr_cap_get_bool,
8038ff43ee4SSuraj Jitindar Singh         .set = spapr_cap_set_bool,
8048ff43ee4SSuraj Jitindar Singh         .type = "bool",
8058ff43ee4SSuraj Jitindar Singh         .apply = cap_ccf_assist_apply,
8068ff43ee4SSuraj Jitindar Singh     },
8078af7e1feSNicholas Piggin     [SPAPR_CAP_FWNMI] = {
8088af7e1feSNicholas Piggin         .name = "fwnmi",
8098af7e1feSNicholas Piggin         .description = "Implements PAPR FWNMI option",
8108af7e1feSNicholas Piggin         .index = SPAPR_CAP_FWNMI,
8119d953ce4SAravinda Prasad         .get = spapr_cap_get_bool,
8129d953ce4SAravinda Prasad         .set = spapr_cap_set_bool,
8139d953ce4SAravinda Prasad         .type = "bool",
8148af7e1feSNicholas Piggin         .apply = cap_fwnmi_apply,
8159d953ce4SAravinda Prasad     },
81682123b75SBharata B Rao     [SPAPR_CAP_RPT_INVALIDATE] = {
81782123b75SBharata B Rao         .name = "rpt-invalidate",
81882123b75SBharata B Rao         .description = "Allow H_RPT_INVALIDATE",
81982123b75SBharata B Rao         .index = SPAPR_CAP_RPT_INVALIDATE,
82082123b75SBharata B Rao         .get = spapr_cap_get_bool,
82182123b75SBharata B Rao         .set = spapr_cap_set_bool,
82282123b75SBharata B Rao         .type = "bool",
82382123b75SBharata B Rao         .apply = cap_rpt_invalidate_apply,
82482123b75SBharata B Rao     },
825ccc5a4c5SNicholas Piggin     [SPAPR_CAP_AIL_MODE_3] = {
826ccc5a4c5SNicholas Piggin         .name = "ail-mode-3",
827ccc5a4c5SNicholas Piggin         .description = "Alternate Interrupt Location (AIL) mode 3 support",
828ccc5a4c5SNicholas Piggin         .index = SPAPR_CAP_AIL_MODE_3,
829ccc5a4c5SNicholas Piggin         .get = spapr_cap_get_bool,
830ccc5a4c5SNicholas Piggin         .set = spapr_cap_set_bool,
831ccc5a4c5SNicholas Piggin         .type = "bool",
832ccc5a4c5SNicholas Piggin         .apply = cap_ail_mode_3_apply,
833ccc5a4c5SNicholas Piggin     },
83433face6bSDavid Gibson };
83533face6bSDavid Gibson 
default_caps_with_cpu(SpaprMachineState * spapr,const char * cputype)836ce2918cbSDavid Gibson static SpaprCapabilities default_caps_with_cpu(SpaprMachineState *spapr,
837ad99d04cSDavid Gibson                                                const char *cputype)
83833face6bSDavid Gibson {
839ce2918cbSDavid Gibson     SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
840ce2918cbSDavid Gibson     SpaprCapabilities caps;
84133face6bSDavid Gibson 
84233face6bSDavid Gibson     caps = smc->default_caps;
84333face6bSDavid Gibson 
844edaa7995SSuraj Jitindar Singh     if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_3_00,
845edaa7995SSuraj Jitindar Singh                                0, spapr->max_compat_pvr)) {
846edaa7995SSuraj Jitindar Singh         caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF;
847edaa7995SSuraj Jitindar Singh     }
848edaa7995SSuraj Jitindar Singh 
849ad99d04cSDavid Gibson     if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_2_07,
850ee76a09fSDavid Gibson                                0, spapr->max_compat_pvr)) {
8514e5fe368SSuraj Jitindar Singh         caps.caps[SPAPR_CAP_HTM] = SPAPR_CAP_OFF;
852b2540203SSuraj Jitindar Singh         caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
853ccc5a4c5SNicholas Piggin         caps.caps[SPAPR_CAP_AIL_MODE_3] = SPAPR_CAP_OFF;
854ee76a09fSDavid Gibson     }
85533face6bSDavid Gibson 
856ad99d04cSDavid Gibson     if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_2_06_PLUS,
857813f3cf6SSuraj Jitindar Singh                                0, spapr->max_compat_pvr)) {
858813f3cf6SSuraj Jitindar Singh         caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
859813f3cf6SSuraj Jitindar Singh     }
860813f3cf6SSuraj Jitindar Singh 
861ad99d04cSDavid Gibson     if (!ppc_type_check_compat(cputype, CPU_POWERPC_LOGICAL_2_06,
86229386642SDavid Gibson                                0, spapr->max_compat_pvr)) {
8634e5fe368SSuraj Jitindar Singh         caps.caps[SPAPR_CAP_VSX] = SPAPR_CAP_OFF;
8644e5fe368SSuraj Jitindar Singh         caps.caps[SPAPR_CAP_DFP] = SPAPR_CAP_OFF;
865813f3cf6SSuraj Jitindar Singh         caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
86629386642SDavid Gibson     }
86729386642SDavid Gibson 
868e8937295SGreg Kurz     /* This is for pseries-2.12 and older */
869e8937295SGreg Kurz     if (smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] == 0) {
870e8937295SGreg Kurz         uint8_t mps;
871e8937295SGreg Kurz 
872e8937295SGreg Kurz         if (kvmppc_hpt_needs_host_contiguous_pages()) {
873905b7ee4SDavid Hildenbrand             mps = ctz64(qemu_minrampagesize());
874e8937295SGreg Kurz         } else {
875e8937295SGreg Kurz             mps = 34; /* allow everything up to 16GiB, i.e. everything */
876e8937295SGreg Kurz         }
877e8937295SGreg Kurz 
878e8937295SGreg Kurz         caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = mps;
879e8937295SGreg Kurz     }
880e8937295SGreg Kurz 
88133face6bSDavid Gibson     return caps;
88233face6bSDavid Gibson }
88333face6bSDavid Gibson 
spapr_caps_pre_load(void * opaque)8844e5fe368SSuraj Jitindar Singh int spapr_caps_pre_load(void *opaque)
885be85537dSDavid Gibson {
886ce2918cbSDavid Gibson     SpaprMachineState *spapr = opaque;
887be85537dSDavid Gibson 
8884e5fe368SSuraj Jitindar Singh     /* Set to default so we can tell if this came in with the migration */
8894e5fe368SSuraj Jitindar Singh     spapr->mig = spapr->def;
8904e5fe368SSuraj Jitindar Singh     return 0;
8914e5fe368SSuraj Jitindar Singh }
8924e5fe368SSuraj Jitindar Singh 
spapr_caps_pre_save(void * opaque)8934e5fe368SSuraj Jitindar Singh int spapr_caps_pre_save(void *opaque)
8944e5fe368SSuraj Jitindar Singh {
895ce2918cbSDavid Gibson     SpaprMachineState *spapr = opaque;
8964e5fe368SSuraj Jitindar Singh 
8974e5fe368SSuraj Jitindar Singh     spapr->mig = spapr->eff;
8984e5fe368SSuraj Jitindar Singh     return 0;
899be85537dSDavid Gibson }
900be85537dSDavid Gibson 
901be85537dSDavid Gibson /* This has to be called from the top-level spapr post_load, not the
902be85537dSDavid Gibson  * caps specific one.  Otherwise it wouldn't be called when the source
903be85537dSDavid Gibson  * caps are all defaults, which could still conflict with overridden
904be85537dSDavid Gibson  * caps on the destination */
spapr_caps_post_migration(SpaprMachineState * spapr)905ce2918cbSDavid Gibson int spapr_caps_post_migration(SpaprMachineState *spapr)
906be85537dSDavid Gibson {
907be85537dSDavid Gibson     int i;
908be85537dSDavid Gibson     bool ok = true;
909ce2918cbSDavid Gibson     SpaprCapabilities dstcaps = spapr->eff;
910ce2918cbSDavid Gibson     SpaprCapabilities srccaps;
911be85537dSDavid Gibson 
912ad99d04cSDavid Gibson     srccaps = default_caps_with_cpu(spapr, MACHINE(spapr)->cpu_type);
9134e5fe368SSuraj Jitindar Singh     for (i = 0; i < SPAPR_CAP_NUM; i++) {
9144e5fe368SSuraj Jitindar Singh         /* If not default value then assume came in with the migration */
9154e5fe368SSuraj Jitindar Singh         if (spapr->mig.caps[i] != spapr->def.caps[i]) {
9164e5fe368SSuraj Jitindar Singh             srccaps.caps[i] = spapr->mig.caps[i];
9174e5fe368SSuraj Jitindar Singh         }
9184e5fe368SSuraj Jitindar Singh     }
919be85537dSDavid Gibson 
9204e5fe368SSuraj Jitindar Singh     for (i = 0; i < SPAPR_CAP_NUM; i++) {
921ce2918cbSDavid Gibson         SpaprCapabilityInfo *info = &capability_table[i];
922be85537dSDavid Gibson 
9234e5fe368SSuraj Jitindar Singh         if (srccaps.caps[i] > dstcaps.caps[i]) {
9244e5fe368SSuraj Jitindar Singh             error_report("cap-%s higher level (%d) in incoming stream than on destination (%d)",
9254e5fe368SSuraj Jitindar Singh                          info->name, srccaps.caps[i], dstcaps.caps[i]);
926be85537dSDavid Gibson             ok = false;
927be85537dSDavid Gibson         }
928be85537dSDavid Gibson 
9294e5fe368SSuraj Jitindar Singh         if (srccaps.caps[i] < dstcaps.caps[i]) {
9304e5fe368SSuraj Jitindar Singh             warn_report("cap-%s lower level (%d) in incoming stream than on destination (%d)",
9314e5fe368SSuraj Jitindar Singh                          info->name, srccaps.caps[i], dstcaps.caps[i]);
932be85537dSDavid Gibson         }
933be85537dSDavid Gibson     }
934be85537dSDavid Gibson 
935be85537dSDavid Gibson     return ok ? 0 : -EINVAL;
936be85537dSDavid Gibson }
937be85537dSDavid Gibson 
9381f63ebaaSSuraj Jitindar Singh /* Used to generate the migration field and needed function for a spapr cap */
9398c5909c4SSuraj Jitindar Singh #define SPAPR_CAP_MIG_STATE(sname, cap)                 \
9408c5909c4SSuraj Jitindar Singh static bool spapr_cap_##sname##_needed(void *opaque)    \
9411f63ebaaSSuraj Jitindar Singh {                                                       \
942ce2918cbSDavid Gibson     SpaprMachineState *spapr = opaque;                  \
9433725ef1aSGreg Kurz     bool (*needed)(void *opaque) =                      \
9443725ef1aSGreg Kurz         capability_table[cap].migrate_needed;           \
9451f63ebaaSSuraj Jitindar Singh                                                         \
9463725ef1aSGreg Kurz     return needed ? needed(opaque) : true &&            \
9473725ef1aSGreg Kurz            spapr->cmd_line_caps[cap] &&                 \
9488c5909c4SSuraj Jitindar Singh            (spapr->eff.caps[cap] !=                     \
9498c5909c4SSuraj Jitindar Singh             spapr->def.caps[cap]);                      \
9501f63ebaaSSuraj Jitindar Singh }                                                       \
9511f63ebaaSSuraj Jitindar Singh                                                         \
9528c5909c4SSuraj Jitindar Singh const VMStateDescription vmstate_spapr_cap_##sname = {  \
9538c5909c4SSuraj Jitindar Singh     .name = "spapr/cap/" #sname,                        \
9541f63ebaaSSuraj Jitindar Singh     .version_id = 1,                                    \
9551f63ebaaSSuraj Jitindar Singh     .minimum_version_id = 1,                            \
9568c5909c4SSuraj Jitindar Singh     .needed = spapr_cap_##sname##_needed,               \
957078ddbc9SRichard Henderson     .fields = (const VMStateField[]) {                  \
9588c5909c4SSuraj Jitindar Singh         VMSTATE_UINT8(mig.caps[cap],                    \
959ce2918cbSDavid Gibson                       SpaprMachineState),               \
9601f63ebaaSSuraj Jitindar Singh         VMSTATE_END_OF_LIST()                           \
9611f63ebaaSSuraj Jitindar Singh     },                                                  \
962be85537dSDavid Gibson }
963be85537dSDavid Gibson 
9648c5909c4SSuraj Jitindar Singh SPAPR_CAP_MIG_STATE(htm, SPAPR_CAP_HTM);
9658c5909c4SSuraj Jitindar Singh SPAPR_CAP_MIG_STATE(vsx, SPAPR_CAP_VSX);
9668c5909c4SSuraj Jitindar Singh SPAPR_CAP_MIG_STATE(dfp, SPAPR_CAP_DFP);
9678c5909c4SSuraj Jitindar Singh SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC);
9688c5909c4SSuraj Jitindar Singh SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC);
9698c5909c4SSuraj Jitindar Singh SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS);
97064d4a534SDavid Gibson SPAPR_CAP_MIG_STATE(hpt_maxpagesize, SPAPR_CAP_HPT_MAXPAGESIZE);
971b9a477b7SSuraj Jitindar Singh SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
972e1617b84SHarsh Prateek Bora SPAPR_CAP_MIG_STATE(nested_papr, SPAPR_CAP_NESTED_PAPR);
973c982f5cfSSuraj Jitindar Singh SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER);
9748ff43ee4SSuraj Jitindar Singh SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST);
9758af7e1feSNicholas Piggin SPAPR_CAP_MIG_STATE(fwnmi, SPAPR_CAP_FWNMI);
97682123b75SBharata B Rao SPAPR_CAP_MIG_STATE(rpt_invalidate, SPAPR_CAP_RPT_INVALIDATE);
977*1a7a31aeSNicholas Piggin SPAPR_CAP_MIG_STATE(ail_mode_3, SPAPR_CAP_AIL_MODE_3);
978be85537dSDavid Gibson 
spapr_caps_init(SpaprMachineState * spapr)979ce2918cbSDavid Gibson void spapr_caps_init(SpaprMachineState *spapr)
98033face6bSDavid Gibson {
981ce2918cbSDavid Gibson     SpaprCapabilities default_caps;
98233face6bSDavid Gibson     int i;
98333face6bSDavid Gibson 
9849f6edd06SDavid Gibson     /* Compute the actual set of caps we should run with */
985ad99d04cSDavid Gibson     default_caps = default_caps_with_cpu(spapr, MACHINE(spapr)->cpu_type);
98633face6bSDavid Gibson 
9874e5fe368SSuraj Jitindar Singh     for (i = 0; i < SPAPR_CAP_NUM; i++) {
9884e5fe368SSuraj Jitindar Singh         /* Store the defaults */
9894e5fe368SSuraj Jitindar Singh         spapr->def.caps[i] = default_caps.caps[i];
9904e5fe368SSuraj Jitindar Singh         /* If not set on the command line then apply the default value */
9914e5fe368SSuraj Jitindar Singh         if (!spapr->cmd_line_caps[i]) {
9924e5fe368SSuraj Jitindar Singh             spapr->eff.caps[i] = default_caps.caps[i];
9934e5fe368SSuraj Jitindar Singh         }
9944e5fe368SSuraj Jitindar Singh     }
9959f6edd06SDavid Gibson }
99633face6bSDavid Gibson 
spapr_caps_apply(SpaprMachineState * spapr)997ce2918cbSDavid Gibson void spapr_caps_apply(SpaprMachineState *spapr)
9989f6edd06SDavid Gibson {
9999f6edd06SDavid Gibson     int i;
100033face6bSDavid Gibson 
10014e5fe368SSuraj Jitindar Singh     for (i = 0; i < SPAPR_CAP_NUM; i++) {
1002ce2918cbSDavid Gibson         SpaprCapabilityInfo *info = &capability_table[i];
100333face6bSDavid Gibson 
10044e5fe368SSuraj Jitindar Singh         /*
10054e5fe368SSuraj Jitindar Singh          * If the apply function can't set the desired level and thinks it's
10064e5fe368SSuraj Jitindar Singh          * fatal, it should cause that.
10074e5fe368SSuraj Jitindar Singh          */
10084e5fe368SSuraj Jitindar Singh         info->apply(spapr, spapr->eff.caps[i], &error_fatal);
100933face6bSDavid Gibson     }
101033face6bSDavid Gibson }
101133face6bSDavid Gibson 
spapr_caps_cpu_apply(SpaprMachineState * spapr,PowerPCCPU * cpu)1012ce2918cbSDavid Gibson void spapr_caps_cpu_apply(SpaprMachineState *spapr, PowerPCCPU *cpu)
1013e2e4f641SDavid Gibson {
1014e2e4f641SDavid Gibson     int i;
1015e2e4f641SDavid Gibson 
1016e2e4f641SDavid Gibson     for (i = 0; i < SPAPR_CAP_NUM; i++) {
1017ce2918cbSDavid Gibson         SpaprCapabilityInfo *info = &capability_table[i];
1018e2e4f641SDavid Gibson 
1019e2e4f641SDavid Gibson         /*
1020e2e4f641SDavid Gibson          * If the apply function can't set the desired level and thinks it's
1021e2e4f641SDavid Gibson          * fatal, it should cause that.
1022e2e4f641SDavid Gibson          */
1023e2e4f641SDavid Gibson         if (info->cpu_apply) {
1024e2e4f641SDavid Gibson             info->cpu_apply(spapr, cpu, spapr->eff.caps[i], &error_fatal);
1025e2e4f641SDavid Gibson         }
1026e2e4f641SDavid Gibson     }
1027e2e4f641SDavid Gibson }
1028e2e4f641SDavid Gibson 
spapr_caps_add_properties(SpaprMachineClass * smc)102940c2281cSMarkus Armbruster void spapr_caps_add_properties(SpaprMachineClass *smc)
103033face6bSDavid Gibson {
103133face6bSDavid Gibson     ObjectClass *klass = OBJECT_CLASS(smc);
103233face6bSDavid Gibson     int i;
103333face6bSDavid Gibson 
103433face6bSDavid Gibson     for (i = 0; i < ARRAY_SIZE(capability_table); i++) {
1035ce2918cbSDavid Gibson         SpaprCapabilityInfo *cap = &capability_table[i];
103637d19534SDaniel Henrique Barboza         g_autofree char *name = g_strdup_printf("cap-%s", cap->name);
103737d19534SDaniel Henrique Barboza         g_autofree char *desc = g_strdup_printf("%s", cap->description);
103833face6bSDavid Gibson 
10394e5fe368SSuraj Jitindar Singh         object_class_property_add(klass, name, cap->type,
10404e5fe368SSuraj Jitindar Singh                                   cap->get, cap->set,
1041d2623129SMarkus Armbruster                                   NULL, cap);
104233face6bSDavid Gibson 
10437eecec7dSMarkus Armbruster         object_class_property_set_description(klass, name, desc);
104433face6bSDavid Gibson     }
104533face6bSDavid Gibson }
1046