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