diff options
Diffstat (limited to 'hw/ppc/spapr.c')
| -rw-r--r-- | hw/ppc/spapr.c | 80 |
1 files changed, 57 insertions, 23 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index c15340a58d..a415e51d07 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -4,6 +4,9 @@ * Copyright (c) 2004-2007 Fabrice Bellard * Copyright (c) 2007 Jocelyn Mayer * Copyright (c) 2010 David Gibson, IBM Corporation. + * Copyright (c) 2010-2024, IBM Corporation.. + * + * SPDX-License-Identifier: GPL-2.0-or-later * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -243,7 +246,7 @@ static void spapr_dt_pa_features(SpaprMachineState *spapr, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */ /* 54: DecFP, 56: DecI, 58: SHA */ 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */ - /* 60: NM atomic, 62: RNG */ + /* 60: NM atomic, 62: RNG, 64: DAWR1 (ISA 3.1) */ 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */ /* 68: DEXCR[SBHE|IBRTPDUS|SRAPD|NPHIE|PHIE] */ 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, /* 66 - 71 */ @@ -292,6 +295,9 @@ static void spapr_dt_pa_features(SpaprMachineState *spapr, * in pa-features. So hide it from them. */ pa_features[40 + 2] &= ~0x80; /* Radix MMU */ } + if (spapr_get_cap(spapr, SPAPR_CAP_DAWR1)) { + pa_features[66] |= 0x80; + } _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size))); } @@ -1399,11 +1405,34 @@ static bool spapr_get_pate(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu, } } -#define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2)) -#define HPTE_VALID(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID) -#define HPTE_DIRTY(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY) -#define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY)) -#define DIRTY_HPTE(_hpte) ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY)) +static uint64_t *hpte_get_ptr(SpaprMachineState *s, unsigned index) +{ + uint64_t *table = s->htab; + + return &table[2 * index]; +} + +static bool hpte_is_valid(SpaprMachineState *s, unsigned index) +{ + return ldq_be_p(hpte_get_ptr(s, index)) & HPTE64_V_VALID; +} + +static bool hpte_is_dirty(SpaprMachineState *s, unsigned index) +{ + return ldq_be_p(hpte_get_ptr(s, index)) & HPTE64_V_HPTE_DIRTY; +} + +static void hpte_set_clean(SpaprMachineState *s, unsigned index) +{ + stq_be_p(hpte_get_ptr(s, index), + ldq_be_p(hpte_get_ptr(s, index)) & ~HPTE64_V_HPTE_DIRTY); +} + +static void hpte_set_dirty(SpaprMachineState *s, unsigned index) +{ + stq_be_p(hpte_get_ptr(s, index), + ldq_be_p(hpte_get_ptr(s, index)) | HPTE64_V_HPTE_DIRTY); +} /* * Get the fd to access the kernel htab, re-opening it if necessary @@ -1614,7 +1643,7 @@ int spapr_reallocate_hpt(SpaprMachineState *spapr, int shift, Error **errp) spapr->htab_shift = shift; for (i = 0; i < size / HASH_PTE_SIZE_64; i++) { - DIRTY_HPTE(HPTE(spapr->htab, i)); + hpte_set_dirty(spapr, i); } } /* We're setting up a hash table, so that means we're not radix */ @@ -2137,6 +2166,7 @@ static const VMStateDescription vmstate_spapr = { &vmstate_spapr_cap_rpt_invalidate, &vmstate_spapr_cap_ail_mode_3, &vmstate_spapr_cap_nested_papr, + &vmstate_spapr_cap_dawr1, NULL } }; @@ -2171,7 +2201,7 @@ static void htab_save_chunk(QEMUFile *f, SpaprMachineState *spapr, qemu_put_be32(f, chunkstart); qemu_put_be16(f, n_valid); qemu_put_be16(f, n_invalid); - qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), + qemu_put_buffer(f, (void *)hpte_get_ptr(spapr, chunkstart), HASH_PTE_SIZE_64 * n_valid); } @@ -2197,16 +2227,16 @@ static void htab_save_first_pass(QEMUFile *f, SpaprMachineState *spapr, /* Consume invalid HPTEs */ while ((index < htabslots) - && !HPTE_VALID(HPTE(spapr->htab, index))) { - CLEAN_HPTE(HPTE(spapr->htab, index)); + && !hpte_is_valid(spapr, index)) { + hpte_set_clean(spapr, index); index++; } /* Consume valid HPTEs */ chunkstart = index; while ((index < htabslots) && (index - chunkstart < USHRT_MAX) - && HPTE_VALID(HPTE(spapr->htab, index))) { - CLEAN_HPTE(HPTE(spapr->htab, index)); + && hpte_is_valid(spapr, index)) { + hpte_set_clean(spapr, index); index++; } @@ -2246,7 +2276,7 @@ static int htab_save_later_pass(QEMUFile *f, SpaprMachineState *spapr, /* Consume non-dirty HPTEs */ while ((index < htabslots) - && !HPTE_DIRTY(HPTE(spapr->htab, index))) { + && !hpte_is_dirty(spapr, index)) { index++; examined++; } @@ -2254,9 +2284,9 @@ static int htab_save_later_pass(QEMUFile *f, SpaprMachineState *spapr, chunkstart = index; /* Consume valid dirty HPTEs */ while ((index < htabslots) && (index - chunkstart < USHRT_MAX) - && HPTE_DIRTY(HPTE(spapr->htab, index)) - && HPTE_VALID(HPTE(spapr->htab, index))) { - CLEAN_HPTE(HPTE(spapr->htab, index)); + && hpte_is_dirty(spapr, index) + && hpte_is_valid(spapr, index)) { + hpte_set_clean(spapr, index); index++; examined++; } @@ -2264,9 +2294,9 @@ static int htab_save_later_pass(QEMUFile *f, SpaprMachineState *spapr, invalidstart = index; /* Consume invalid dirty HPTEs */ while ((index < htabslots) && (index - invalidstart < USHRT_MAX) - && HPTE_DIRTY(HPTE(spapr->htab, index)) - && !HPTE_VALID(HPTE(spapr->htab, index))) { - CLEAN_HPTE(HPTE(spapr->htab, index)); + && hpte_is_dirty(spapr, index) + && !hpte_is_valid(spapr, index)) { + hpte_set_clean(spapr, index); index++; examined++; } @@ -2448,11 +2478,11 @@ static int htab_load(QEMUFile *f, void *opaque, int version_id) if (spapr->htab) { if (n_valid) { - qemu_get_buffer(f, HPTE(spapr->htab, index), + qemu_get_buffer(f, (void *)hpte_get_ptr(spapr, index), HASH_PTE_SIZE_64 * n_valid); } if (n_invalid) { - memset(HPTE(spapr->htab, index + n_valid), 0, + memset(hpte_get_ptr(spapr, index + n_valid), 0, HASH_PTE_SIZE_64 * n_invalid); } } else { @@ -2887,6 +2917,9 @@ static void spapr_machine_init(MachineState *machine) spapr_ovec_set(spapr->ov5, OV5_XIVE_EXPLOIT); } + qemu_guest_getrandom_nofail(&spapr->hashpkey_val, + sizeof(spapr->hashpkey_val)); + /* init CPUs */ spapr_init_cpus(spapr); @@ -4436,7 +4469,7 @@ static void spapr_pic_print_info(InterruptStatsProvider *obj, GString *buf) */ static int spapr_match_nvt(XiveFabric *xfb, uint8_t format, uint8_t nvt_blk, uint32_t nvt_idx, - bool cam_ignore, uint8_t priority, + bool crowd, bool cam_ignore, uint8_t priority, uint32_t logic_serv, XiveTCTXMatch *match) { SpaprMachineState *spapr = SPAPR_MACHINE(xfb); @@ -4444,7 +4477,7 @@ static int spapr_match_nvt(XiveFabric *xfb, uint8_t format, XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); int count; - count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, + count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, crowd, cam_ignore, priority, logic_serv, match); if (count < 0) { return count; @@ -4654,6 +4687,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_ON; smc->default_caps.caps[SPAPR_CAP_FWNMI] = SPAPR_CAP_ON; smc->default_caps.caps[SPAPR_CAP_RPT_INVALIDATE] = SPAPR_CAP_OFF; + smc->default_caps.caps[SPAPR_CAP_DAWR1] = SPAPR_CAP_ON; /* * This cap specifies whether the AIL 3 mode for |