diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2022-04-20 21:54:24 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2022-04-20 21:54:24 -0700 |
commit | b1efff6bf031a93b5b8bf3912ddc720cc1653a61 (patch) | |
tree | ec136bdbf0359cd45ed1c83082bc7ee84cf969b8 | |
parent | 9c125d17e9402c232c46610802e5931b3639d77b (diff) | |
parent | 2d94af4b16c40758eee3a8591307ae173090d4ad (diff) |
Merge tag 'pull-ppc-20220420-2' of https://gitlab.com/danielhb/qemu into staging
ppc patch queue for 2022-04-20
First batch of ppc patches for QEMU 7.1:
- skiboot firmware version bump
- pseries: add 2M DDW pagesize
- pseries: make virtual hypervisor code TCG only
- powernv: introduce GPIO lines for PSIHB device
- powernv: remove PCIE root bridge LSI
- target/ppc: alternative softfloat 128 bit integer support
- assorted fixes
# -----BEGIN PGP SIGNATURE-----
#
# iHUEABYKAB0WIQQX6/+ZI9AYAK8oOBk82cqW3gMxZAUCYmB/ngAKCRA82cqW3gMx
# ZE10AP4wPeJQ3fxXb5ylVtL4qkJaLWy6VrJBQSKSb5YEA0fhegEA9ZufpnENQePU
# gZF0eFAQK/DbSnDyvRQVpGcJM0K1UgI=
# =nVRw
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 20 Apr 2022 02:48:14 PM PDT
# gpg: using EDDSA key 17EBFF9923D01800AF2838193CD9CA96DE033164
# gpg: Can't check signature: No public key
* tag 'pull-ppc-20220420-2' of https://gitlab.com/danielhb/qemu: (23 commits)
hw/ppc: change indentation to spaces from TABs
target/ppc: Add two missing register callbacks on POWER10
ppc/pnv: Remove LSI on the PCIE host bridge
pcie: Don't try triggering a LSI when not defined
ppc/vof: Fix uninitialized string tracing
hw/ppc/ppc405_boards: Initialize g_autofree pointer
target/ppc: implement xscvqp[su]qz
target/ppc: implement xscv[su]qqp
softfloat: add float128_to_int128
softfloat: add float128_to_uint128
softfloat: add int128_to_float128
softfloat: add uint128_to_float128
qemu/int128: add int128_urshift
target/ppc: Improve KVM hypercall trace
spapr: Move nested KVM hypercalls under a TCG only config.
spapr: Move hypercall_register_softmmu
ppc/pnv: Remove useless checks in set_irq handlers
ppc/pnv: Remove PnvPsiClas::irq_set
ppc/pnv: Remove PnvOCC::psi link
ppc/pnv: Remove PnvLpcController::psi link
...
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
32 files changed, 445 insertions, 136 deletions
diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 7f524d4377..5e2cf20448 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -3154,6 +3154,60 @@ static int64_t float128_to_int64_scalbn(float128 a, FloatRoundMode rmode, return parts_float_to_sint(&p, rmode, scale, INT64_MIN, INT64_MAX, s); } +static Int128 float128_to_int128_scalbn(float128 a, FloatRoundMode rmode, + int scale, float_status *s) +{ + int flags = 0; + Int128 r; + FloatParts128 p; + + float128_unpack_canonical(&p, a, s); + + switch (p.cls) { + case float_class_snan: + flags |= float_flag_invalid_snan; + /* fall through */ + case float_class_qnan: + flags |= float_flag_invalid; + r = UINT128_MAX; + break; + + case float_class_inf: + flags = float_flag_invalid | float_flag_invalid_cvti; + r = p.sign ? INT128_MIN : INT128_MAX; + break; + + case float_class_zero: + return int128_zero(); + + case float_class_normal: + if (parts_round_to_int_normal(&p, rmode, scale, 128 - 2)) { + flags = float_flag_inexact; + } + + if (p.exp < 127) { + int shift = 127 - p.exp; + r = int128_urshift(int128_make128(p.frac_lo, p.frac_hi), shift); + if (p.sign) { + r = int128_neg(r); + } + } else if (p.exp == 127 && p.sign && p.frac_lo == 0 && + p.frac_hi == DECOMPOSED_IMPLICIT_BIT) { + r = INT128_MIN; + } else { + flags = float_flag_invalid | float_flag_invalid_cvti; + r = p.sign ? INT128_MIN : INT128_MAX; + } + break; + + default: + g_assert_not_reached(); + } + + float_raise(flags, s); + return r; +} + static int32_t floatx80_to_int32_scalbn(floatx80 a, FloatRoundMode rmode, int scale, float_status *s) { @@ -3236,6 +3290,11 @@ int64_t float128_to_int64(float128 a, float_status *s) return float128_to_int64_scalbn(a, s->float_rounding_mode, 0, s); } +Int128 float128_to_int128(float128 a, float_status *s) +{ + return float128_to_int128_scalbn(a, s->float_rounding_mode, 0, s); +} + int32_t floatx80_to_int32(floatx80 a, float_status *s) { return floatx80_to_int32_scalbn(a, s->float_rounding_mode, 0, s); @@ -3301,6 +3360,11 @@ int64_t float128_to_int64_round_to_zero(float128 a, float_status *s) return float128_to_int64_scalbn(a, float_round_to_zero, 0, s); } +Int128 float128_to_int128_round_to_zero(float128 a, float_status *s) +{ + return float128_to_int128_scalbn(a, float_round_to_zero, 0, s); +} + int32_t floatx80_to_int32_round_to_zero(floatx80 a, float_status *s) { return floatx80_to_int32_scalbn(a, float_round_to_zero, 0, s); @@ -3480,6 +3544,61 @@ static uint64_t float128_to_uint64_scalbn(float128 a, FloatRoundMode rmode, return parts_float_to_uint(&p, rmode, scale, UINT64_MAX, s); } +static Int128 float128_to_uint128_scalbn(float128 a, FloatRoundMode rmode, + int scale, float_status *s) +{ + int flags = 0; + Int128 r; + FloatParts128 p; + + float128_unpack_canonical(&p, a, s); + + switch (p.cls) { + case float_class_snan: + flags |= float_flag_invalid_snan; + /* fall through */ + case float_class_qnan: + flags |= float_flag_invalid; + r = UINT128_MAX; + break; + + case float_class_inf: + flags = float_flag_invalid | float_flag_invalid_cvti; + r = p.sign ? int128_zero() : UINT128_MAX; + break; + + case float_class_zero: + return int128_zero(); + + case float_class_normal: + if (parts_round_to_int_normal(&p, rmode, scale, 128 - 2)) { + flags = float_flag_inexact; + if (p.cls == float_class_zero) { + r = int128_zero(); + break; + } + } + + if (p.sign) { + flags = float_flag_invalid | float_flag_invalid_cvti; + r = int128_zero(); + } else if (p.exp <= 127) { + int shift = 127 - p.exp; + r = int128_urshift(int128_make128(p.frac_lo, p.frac_hi), shift); + } else { + flags = float_flag_invalid | float_flag_invalid_cvti; + r = UINT128_MAX; + } + break; + + default: + g_assert_not_reached(); + } + + float_raise(flags, s); + return r; +} + uint8_t float16_to_uint8(float16 a, float_status *s) { return float16_to_uint8_scalbn(a, s->float_rounding_mode, 0, s); @@ -3540,6 +3659,11 @@ uint64_t float128_to_uint64(float128 a, float_status *s) return float128_to_uint64_scalbn(a, s->float_rounding_mode, 0, s); } +Int128 float128_to_uint128(float128 a, float_status *s) +{ + return float128_to_uint128_scalbn(a, s->float_rounding_mode, 0, s); +} + uint16_t float16_to_uint16_round_to_zero(float16 a, float_status *s) { return float16_to_uint16_scalbn(a, float_round_to_zero, 0, s); @@ -3595,6 +3719,11 @@ uint64_t float128_to_uint64_round_to_zero(float128 a, float_status *s) return float128_to_uint64_scalbn(a, float_round_to_zero, 0, s); } +Int128 float128_to_uint128_round_to_zero(float128 a, float_status *s) +{ + return float128_to_uint128_scalbn(a, float_round_to_zero, 0, s); +} + uint16_t bfloat16_to_uint16(bfloat16 a, float_status *s) { return bfloat16_to_uint16_scalbn(a, s->float_rounding_mode, 0, s); @@ -3780,6 +3909,35 @@ bfloat16 int16_to_bfloat16(int16_t a, float_status *status) return int64_to_bfloat16_scalbn(a, 0, status); } +float128 int128_to_float128(Int128 a, float_status *status) +{ + FloatParts128 p = { }; + int shift; + + if (int128_nz(a)) { + p.cls = float_class_normal; + if (!int128_nonneg(a)) { + p.sign = true; + a = int128_neg(a); + } + + shift = clz64(int128_gethi(a)); + if (shift == 64) { + shift += clz64(int128_getlo(a)); + } + + p.exp = 127 - shift; + a = int128_lshift(a, shift); + + p.frac_hi = int128_gethi(a); + p.frac_lo = int128_getlo(a); + } else { + p.cls = float_class_zero; + } + + return float128_round_pack_canonical(&p, status); +} + float128 int64_to_float128(int64_t a, float_status *status) { FloatParts128 p; @@ -3969,6 +4127,31 @@ float128 uint64_to_float128(uint64_t a, float_status *status) return float128_round_pack_canonical(&p, status); } +float128 uint128_to_float128(Int128 a, float_status *status) +{ + FloatParts128 p = { }; + int shift; + + if (int128_nz(a)) { + p.cls = float_class_normal; + + shift = clz64(int128_gethi(a)); + if (shift == 64) { + shift += clz64(int128_getlo(a)); + } + + p.exp = 127 - shift; + a = int128_lshift(a, shift); + + p.frac_hi = int128_gethi(a); + p.frac_lo = int128_getlo(a); + } else { + p.cls = float_class_zero; + } + + return float128_round_pack_canonical(&p, status); +} + /* * Minimum and maximum */ diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index 4e68ad4f03..3f03467dde 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -1161,6 +1161,7 @@ static void pnv_phb3_root_port_realize(DeviceState *dev, Error **errp) error_propagate(errp, local_err); return; } + pci_config_set_interrupt_pin(pci->config, 0); } static void pnv_phb3_root_port_class_init(ObjectClass *klass, void *data) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 3c4c2dace0..13ba9e45d8 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1771,6 +1771,7 @@ static void pnv_phb4_root_port_reset(DeviceState *dev) pci_set_word(conf + PCI_PREF_MEMORY_LIMIT, 0xfff1); pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0x1); /* Hack */ pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0xffffffff); + pci_config_set_interrupt_pin(conf, 0); } static void pnv_phb4_root_port_realize(DeviceState *dev, Error **errp) diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index 67a5d67372..68a62da0b5 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -353,7 +353,7 @@ static void hotplug_event_notify(PCIDevice *dev) msix_notify(dev, pcie_cap_flags_get_vector(dev)); } else if (msi_enabled(dev)) { msi_notify(dev, pcie_cap_flags_get_vector(dev)); - } else { + } else if (pci_intx(dev) != -1) { pci_set_irq(dev, dev->exp.hpev_notified); } } @@ -361,7 +361,8 @@ static void hotplug_event_notify(PCIDevice *dev) static void hotplug_event_clear(PCIDevice *dev) { hotplug_event_update_event_status(dev); - if (!msix_enabled(dev) && !msi_enabled(dev) && !dev->exp.hpev_notified) { + if (!msix_enabled(dev) && !msi_enabled(dev) && pci_intx(dev) != -1 && + !dev->exp.hpev_notified) { pci_irq_deassert(dev); } } diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c index e1a8a88c8c..92bd0530dd 100644 --- a/hw/pci/pcie_aer.c +++ b/hw/pci/pcie_aer.c @@ -290,7 +290,7 @@ static void pcie_aer_root_notify(PCIDevice *dev) msix_notify(dev, pcie_aer_root_get_vector(dev)); } else if (msi_enabled(dev)) { msi_notify(dev, pcie_aer_root_get_vector(dev)); - } else { + } else if (pci_intx(dev) != -1) { pci_irq_assert(dev); } } diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index c5e48992d9..7c08a78d6c 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -614,24 +614,36 @@ static void pnv_reset(MachineState *machine) static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp) { Pnv8Chip *chip8 = PNV8_CHIP(chip); + qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_EXTERNAL); + + qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq); return pnv_lpc_isa_create(&chip8->lpc, true, errp); } static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp) { Pnv8Chip *chip8 = PNV8_CHIP(chip); + qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_LPC_I2C); + + qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq); return pnv_lpc_isa_create(&chip8->lpc, false, errp); } static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) { Pnv9Chip *chip9 = PNV9_CHIP(chip); + qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip9->psi), PSIHB9_IRQ_LPCHC); + + qdev_connect_gpio_out(DEVICE(&chip9->lpc), 0, irq); return pnv_lpc_isa_create(&chip9->lpc, false, errp); } static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp) { Pnv10Chip *chip10 = PNV10_CHIP(chip); + qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip10->psi), PSIHB9_IRQ_LPCHC); + + qdev_connect_gpio_out(DEVICE(&chip10->lpc), 0, irq); return pnv_lpc_isa_create(&chip10->lpc, false, errp); } @@ -1222,8 +1234,6 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) &PNV_PSI(psi8)->xscom_regs); /* Create LPC controller */ - object_property_set_link(OBJECT(&chip8->lpc), "psi", OBJECT(&chip8->psi), - &error_abort); qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal); pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); @@ -1243,12 +1253,12 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) } /* Create the simplified OCC model */ - object_property_set_link(OBJECT(&chip8->occ), "psi", OBJECT(&chip8->psi), - &error_abort); if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) { return; } pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs); + qdev_connect_gpio_out(DEVICE(&chip8->occ), 0, + qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_OCC)); /* OCC SRAM model */ memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip), @@ -1507,8 +1517,6 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) &PNV_PSI(psi9)->xscom_regs); /* LPC */ - object_property_set_link(OBJECT(&chip9->lpc), "psi", OBJECT(&chip9->psi), - &error_abort); if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) { return; } @@ -1520,12 +1528,12 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) (uint64_t) PNV9_LPCM_BASE(chip)); /* Create the simplified OCC model */ - object_property_set_link(OBJECT(&chip9->occ), "psi", OBJECT(&chip9->psi), - &error_abort); if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) { return; } pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs); + qdev_connect_gpio_out(DEVICE(&chip9->occ), 0, qdev_get_gpio_in( + DEVICE(&chip9->psi), PSIHB9_IRQ_OCC)); /* OCC SRAM model */ memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip), @@ -1712,8 +1720,6 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) &PNV_PSI(&chip10->psi)->xscom_regs); /* LPC */ - object_property_set_link(OBJECT(&chip10->lpc), "psi", - OBJECT(&chip10->psi), &error_abort); if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) { return; } @@ -1725,13 +1731,13 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) (uint64_t) PNV10_LPCM_BASE(chip)); /* Create the simplified OCC model */ - object_property_set_link(OBJECT(&chip10->occ), "psi", OBJECT(&chip10->psi), - &error_abort); if (!qdev_realize(DEVICE(&chip10->occ), NULL, errp)) { return; } pnv_xscom_add_subregion(chip, PNV10_XSCOM_OCC_BASE, &chip10->occ.xscom_regs); + qdev_connect_gpio_out(DEVICE(&chip10->occ), 0, qdev_get_gpio_in( + DEVICE(&chip10->psi), PSIHB9_IRQ_OCC)); /* OCC SRAM model */ memory_region_add_subregion(get_system_memory(), diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c index bcbca3db97..ee890e7ab4 100644 --- a/hw/ppc/pnv_lpc.c +++ b/hw/ppc/pnv_lpc.c @@ -422,7 +422,6 @@ static const MemoryRegionOps pnv_lpc_mmio_ops = { static void pnv_lpc_eval_irqs(PnvLpcController *lpc) { bool lpc_to_opb_irq = false; - PnvLpcClass *plc = PNV_LPC_GET_CLASS(lpc); /* Update LPC controller to OPB line */ if (lpc->lpc_hc_irqser_ctrl & LPC_HC_IRQSER_EN) { @@ -445,7 +444,7 @@ static void pnv_lpc_eval_irqs(PnvLpcController *lpc) lpc->opb_irq_stat |= lpc->opb_irq_input & lpc->opb_irq_mask; /* Reflect the interrupt */ - pnv_psi_irq_set(lpc->psi, plc->psi_irq, lpc->opb_irq_stat != 0); + qemu_set_irq(lpc->psi_irq, lpc->opb_irq_stat != 0); } static uint64_t lpc_hc_read(void *opaque, hwaddr addr, unsigned size) @@ -637,8 +636,6 @@ static void pnv_lpc_power8_class_init(ObjectClass *klass, void *data) xdc->dt_xscom = pnv_lpc_dt_xscom; - plc->psi_irq = PSIHB_IRQ_LPC_I2C; - device_class_set_parent_realize(dc, pnv_lpc_power8_realize, &plc->parent_realize); } @@ -677,8 +674,6 @@ static void pnv_lpc_power9_class_init(ObjectClass *klass, void *data) dc->desc = "PowerNV LPC Controller POWER9"; - plc->psi_irq = PSIHB9_IRQ_LPCHC; - device_class_set_parent_realize(dc, pnv_lpc_power9_realize, &plc->parent_realize); } @@ -706,8 +701,6 @@ static void pnv_lpc_realize(DeviceState *dev, Error **errp) { PnvLpcController *lpc = PNV_LPC(dev); - assert(lpc->psi); - /* Reg inits */ lpc->lpc_hc_fw_rd_acc_size = LPC_HC_FW_RD_4B; @@ -746,12 +739,9 @@ static void pnv_lpc_realize(DeviceState *dev, Error **errp) "lpc-hc", LPC_HC_REGS_OPB_SIZE); memory_region_add_subregion(&lpc->opb_mr, LPC_HC_REGS_OPB_ADDR, &lpc->lpc_hc_regs); -} -static Property pnv_lpc_properties[] = { - DEFINE_PROP_LINK("psi", PnvLpcController, psi, TYPE_PNV_PSI, PnvPsi *), - DEFINE_PROP_END_OF_LIST(), -}; + qdev_init_gpio_out(DEVICE(dev), &lpc->psi_irq, 1); +} static void pnv_lpc_class_init(ObjectClass *klass, void *data) { @@ -759,7 +749,6 @@ static void pnv_lpc_class_init(ObjectClass *klass, void *data) dc->realize = pnv_lpc_realize; dc->desc = "PowerNV LPC Controller"; - device_class_set_props(dc, pnv_lpc_properties); dc->user_creatable = false; } @@ -803,7 +792,7 @@ static void pnv_lpc_isa_irq_handler_cpld(void *opaque, int n, int level) } if (pnv->cpld_irqstate != old_state) { - pnv_psi_irq_set(lpc->psi, PSIHB_IRQ_EXTERNAL, pnv->cpld_irqstate != 0); + qemu_set_irq(lpc->psi_irq, pnv->cpld_irqstate != 0); } } diff --git a/hw/ppc/pnv_occ.c b/hw/ppc/pnv_occ.c index 4ed66f5e1f..9fa6d91d31 100644 --- a/hw/ppc/pnv_occ.c +++ b/hw/ppc/pnv_occ.c @@ -21,6 +21,7 @@ #include "qapi/error.h" #include "qemu/log.h" #include "qemu/module.h" +#include "hw/irq.h" #include "hw/qdev-properties.h" #include "hw/ppc/pnv.h" #include "hw/ppc/pnv_xscom.h" @@ -51,13 +52,12 @@ static void pnv_occ_set_misc(PnvOCC *occ, uint64_t val) { bool irq_state; - PnvOCCClass *poc = PNV_OCC_GET_CLASS(occ); val &= 0xffff000000000000ull; occ->occmisc = val; irq_state = !!(val >> 63); - pnv_psi_irq_set(occ->psi, poc->psi_irq, irq_state); + qemu_set_irq(occ->psi_irq, irq_state); } static uint64_t pnv_occ_power8_xscom_read(void *opaque, hwaddr addr, @@ -168,7 +168,6 @@ static void pnv_occ_power8_class_init(ObjectClass *klass, void *data) poc->xscom_size = PNV_XSCOM_OCC_SIZE; poc->xscom_ops = &pnv_occ_power8_xscom_ops; - poc->psi_irq = PSIHB_IRQ_OCC; } static const TypeInfo pnv_occ_power8_type_info = { @@ -241,7 +240,6 @@ static void pnv_occ_power9_class_init(ObjectClass *klass, void *data) dc->desc = "PowerNV OCC Controller (POWER9)"; poc->xscom_size = PNV9_XSCOM_OCC_SIZE; poc->xscom_ops = &pnv_occ_power9_xscom_ops; - poc->psi_irq = PSIHB9_IRQ_OCC; } static const TypeInfo pnv_occ_power9_type_info = { @@ -269,8 +267,6 @@ static void pnv_occ_realize(DeviceState *dev, Error **errp) PnvOCC *occ = PNV_OCC(dev); PnvOCCClass *poc = PNV_OCC_GET_CLASS(occ); - assert(occ->psi); - occ->occmisc = 0; /* XScom region for OCC registers */ @@ -281,12 +277,9 @@ static void pnv_occ_realize(DeviceState *dev, Error **errp) memory_region_init_io(&occ->sram_regs, OBJECT(dev), &pnv_occ_sram_ops, occ, "occ-common-area", PNV_OCC_SENSOR_DATA_BLOCK_SIZE); -} -static Property pnv_occ_properties[] = { - DEFINE_PROP_LINK("psi", PnvOCC, psi, TYPE_PNV_PSI, PnvPsi *), - DEFINE_PROP_END_OF_LIST(), -}; + qdev_init_gpio_out(DEVICE(dev), &occ->psi_irq, 1); +} static void pnv_occ_class_init(ObjectClass *klass, void *data) { @@ -294,7 +287,6 @@ static void pnv_occ_class_init(ObjectClass *klass, void *data) dc->realize = pnv_occ_realize; dc->desc = "PowerNV OCC Controller"; - device_class_set_props(dc, pnv_occ_properties); dc->user_creatable = false; } diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c index 466fb79798..98045ed3d2 100644 --- a/hw/ppc/pnv_psi.c +++ b/hw/ppc/pnv_psi.c @@ -184,8 +184,7 @@ static void pnv_psi_set_irsn(PnvPsi *psi, uint64_t val) /* * FSP and PSI interrupts are muxed under the same number. */ -static const uint32_t xivr_regs[] = { - [PSIHB_IRQ_PSI] = PSIHB_XSCOM_XIVR_FSP, +static const uint32_t xivr_regs[PSI_NUM_INTERRUPTS] = { [PSIHB_IRQ_FSP] = PSIHB_XSCOM_XIVR_FSP, [PSIHB_IRQ_OCC] = PSIHB_XSCOM_XIVR_OCC, [PSIHB_IRQ_FSI] = PSIHB_XSCOM_XIVR_FSI, @@ -194,8 +193,7 @@ static const uint32_t xivr_regs[] = { [PSIHB_IRQ_EXTERNAL] = PSIHB_XSCOM_XIVR_EXT, }; -static const uint32_t stat_regs[] = { - [PSIHB_IRQ_PSI] = PSIHB_XSCOM_CR, +static const uint32_t stat_regs[PSI_NUM_INTERRUPTS] = { [PSIHB_IRQ_FSP] = PSIHB_XSCOM_CR, [PSIHB_IRQ_OCC] = PSIHB_XSCOM_IRQ_STAT, [PSIHB_IRQ_FSI] = PSIHB_XSCOM_IRQ_STAT, @@ -204,8 +202,7 @@ static const uint32_t stat_regs[] = { [PSIHB_IRQ_EXTERNAL] = PSIHB_XSCOM_IRQ_STAT, }; -static const uint64_t stat_bits[] = { - [PSIHB_IRQ_PSI] = PSIHB_CR_PSI_IRQ, +static const uint64_t stat_bits[PSI_NUM_INTERRUPTS] = { [PSIHB_IRQ_FSP] = PSIHB_CR_FSP_IRQ, [PSIHB_IRQ_OCC] = PSIHB_IRQ_STAT_OCC, [PSIHB_IRQ_FSI] = PSIHB_IRQ_STAT_FSI, @@ -214,23 +211,14 @@ static const uint64_t stat_bits[] = { [PSIHB_IRQ_EXTERNAL] = PSIHB_IRQ_STAT_EXT, }; -void pnv_psi_irq_set(PnvPsi *psi, int irq, bool state) -{ - PNV_PSI_GET_CLASS(psi)->irq_set(psi, irq, state); -} - -static void pnv_psi_power8_irq_set(PnvPsi *psi, int irq, bool state) +static void pnv_psi_power8_set_irq(void *opaque, int irq, int state) { + PnvPsi *psi = opaque; uint32_t xivr_reg; uint32_t stat_reg; uint32_t src; bool masked; - if (irq > PSIHB_IRQ_EXTERNAL) { - qemu_log_mask(LOG_GUEST_ERROR, "PSI: Unsupported irq %d\n", irq); - return; - } - xivr_reg = xivr_regs[irq]; stat_reg = stat_regs[irq]; @@ -515,6 +503,8 @@ static void pnv_psi_power8_realize(DeviceState *dev, Error **errp) ics_set_irq_type(ics, i, true); } + qdev_init_gpio_in(dev, pnv_psi_power8_set_irq, ics->nr_irqs); + psi->qirqs = qemu_allocate_irqs(ics_set_irq, ics, ics->nr_irqs); /* XSCOM region for PSI registers */ @@ -576,7 +566,6 @@ static void pnv_psi_power8_class_init(ObjectClass *klass, void *data) ppc->xscom_pcba = PNV_XSCOM_PSIHB_BASE; ppc->xscom_size = PNV_XSCOM_PSIHB_SIZE; ppc->bar_mask = PSIHB_BAR_MASK; - ppc->irq_set = pnv_psi_power8_irq_set; ppc->compat = compat; ppc->compat_size = sizeof(compat); } @@ -814,15 +803,11 @@ static const MemoryRegionOps pnv_psi_p9_xscom_ops = { } }; -static void pnv_psi_power9_irq_set(PnvPsi *psi, int irq, bool state) +static void pnv_psi_power9_set_irq(void *opaque, int irq, int state) { + PnvPsi *psi = opaque; uint64_t irq_method = psi->regs[PSIHB_REG(PSIHB9_INTERRUPT_CONTROL)]; - if (irq > PSIHB9_NUM_IRQS) { - qemu_log_mask(LOG_GUEST_ERROR, "PSI: Unsupported irq %d\n", irq); - return; - } - if (irq_method & PSIHB9_IRQ_METHOD) { qemu_log_mask(LOG_GUEST_ERROR, "PSI: LSI IRQ method no supported\n"); return; @@ -876,6 +861,8 @@ static void pnv_psi_power9_realize(DeviceState *dev, Error **errp) psi->qirqs = qemu_allocate_irqs(xive_source_set_irq, xsrc, xsrc->nr_irqs); + qdev_init_gpio_in(dev, pnv_psi_power9_set_irq, xsrc->nr_irqs); + /* XSCOM region for PSI registers */ pnv_xscom_region_init(&psi->xscom_regs, OBJECT(dev), &pnv_psi_p9_xscom_ops, psi, "xscom-psi", PNV9_XSCOM_PSIHB_SIZE); @@ -901,7 +888,6 @@ static void pnv_psi_power9_class_init(ObjectClass *klass, void *data) ppc->xscom_pcba = PNV9_XSCOM_PSIHB_BASE; ppc->xscom_size = PNV9_XSCOM_PSIHB_SIZE; ppc->bar_mask = PSIHB9_BAR_MASK; - ppc->irq_set = pnv_psi_power9_irq_set; ppc->compat = compat; ppc->compat_size = sizeof(compat); diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index 32013b8983..a66ad05e3a 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -261,13 +261,13 @@ static void ref405ep_init(MachineState *machine) /* allocate and load BIOS */ if (machine->firmware) { MemoryRegion *bios = g_new(MemoryRegion, 1); - g_autofree char *filename; + g_autofree char *filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, + machine->firmware); long bios_size; memory_region_init_rom(bios, NULL, "ef405ep.bios", BIOS_SIZE, &error_fatal); - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware); if (!filename) { error_report("Could not find firmware '%s'", machine->firmware); exit(1); diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c index efa90ef5ba..d5973f2484 100644 --- a/hw/ppc/ppc440_bamboo.c +++ b/hw/ppc/ppc440_bamboo.c @@ -3,9 +3,9 @@ * * Copyright 2007 IBM Corporation. * Authors: - * Jerone Young <jyoung5@us.ibm.com> - * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com> - * Hollis Blanchard <hollisb@us.ibm.com> + * Jerone Young <jyoung5@us.ibm.com> + * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com> + * Hollis Blanchard <hollisb@us.ibm.com> * * This work is licensed under the GNU GPL license version 2 or later. * diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 7c8bb76f99..d761a7d0c3 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -1473,32 +1473,7 @@ target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode, return H_FUNCTION; } -#ifndef CONFIG_TCG -static target_ulong h_softmmu(PowerPCCPU *cpu, SpaprMachineState *spapr, - target_ulong opcode, target_ulong *args) -{ - g_assert_not_reached(); -} - -static void hypercall_register_softmmu(void) -{ - /* hcall-pft */ - spapr_register_hypercall(H_ENTER, h_softmmu); - spapr_register_hypercall(H_REMOVE, h_softmmu); - spapr_register_hypercall(H_PROTECT, h_softmmu); - spapr_register_hypercall(H_READ, h_softmmu); - - /* hcall-bulk */ - spapr_register_hypercall(H_BULK_REMOVE, h_softmmu); -} -#else -static void hypercall_register_softmmu(void) -{ - /* DO NOTHING */ -} -#endif - -/* TCG only */ +#ifdef CONFIG_TCG #define PRTS_MASK 0x1f static target_ulong h_set_ptbl(PowerPCCPU *cpu, @@ -1825,6 +1800,48 @@ out_restore_l1: spapr_cpu->nested_host_state = NULL; } +static void hypercall_register_nested(void) +{ + spapr_register_hypercall(KVMPPC_H_SET_PARTITION_TABLE, h_set_ptbl); + spapr_register_hypercall(KVMPPC_H_ENTER_NESTED, h_enter_nested); + spapr_register_hypercall(KVMPPC_H_TLB_INVALIDATE, h_tlb_invalidate); + spapr_register_hypercall(KVMPPC_H_COPY_TOFROM_GUEST, h_copy_tofrom_guest); +} + +static void hypercall_register_softmmu(void) +{ + /* DO NOTHING */ +} +#else +void spapr_exit_nested(PowerPCCPU *cpu, int excp) +{ + g_assert_not_reached(); +} + +static target_ulong h_softmmu(PowerPCCPU *cpu, SpaprMachineState *spapr, + target_ulong opcode, target_ulong *args) +{ + g_assert_not_reached(); +} + +static void hypercall_register_nested(void) +{ + /* DO NOTHING */ +} + +static void hypercall_register_softmmu(void) +{ + /* hcall-pft */ + spapr_register_hypercall(H_ENTER, h_softmmu); + spapr_register_hypercall(H_REMOVE, h_softmmu); + spapr_register_hypercall(H_PROTECT, h_softmmu); + spapr_register_hypercall(H_READ, h_softmmu); + + /* hcall-bulk */ + spapr_register_hypercall(H_BULK_REMOVE, h_softmmu); +} +#endif + static void hypercall_register_types(void) { hypercall_register_softmmu(); @@ -1881,10 +1898,7 @@ static void hypercall_register_types(void) spapr_register_hypercall(KVMPPC_H_UPDATE_DT, h_update_dt); - spapr_register_hypercall(KVMPPC_H_SET_PARTITION_TABLE, h_set_ptbl); - spapr_register_hypercall(KVMPPC_H_ENTER_NESTED, h_enter_nested); - spapr_register_hypercall(KVMPPC_H_TLB_INVALIDATE, h_tlb_invalidate); - spapr_register_hypercall(KVMPPC_H_COPY_TOFROM_GUEST, h_copy_tofrom_guest); + hypercall_register_nested(); } type_init(hypercall_register_types) diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index d7c04237fe..d58b65e88f 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -474,16 +474,16 @@ static void rtas_ibm_nmi_interlock(PowerPCCPU *cpu, if (spapr->fwnmi_machine_check_interlock != cpu->vcpu_id) { /* - * The vCPU that hit the NMI should invoke "ibm,nmi-interlock" + * The vCPU that hit the NMI should invoke "ibm,nmi-interlock" * This should be PARAM_ERROR, but Linux calls "ibm,nmi-interlock" - * for system reset interrupts, despite them not being interlocked. - * PowerVM silently ignores this and returns success here. Returning - * failure causes Linux to print the error "FWNMI: nmi-interlock - * failed: -3", although no other apparent ill effects, this is a - * regression for the user when enabling FWNMI. So for now, match - * PowerVM. When most Linux clients are fixed, this could be - * changed. - */ + * for system reset interrupts, despite them not being interlocked. + * PowerVM silently ignores this and returns success here. Returning + * failure causes Linux to print the error "FWNMI: nmi-interlock + * failed: -3", although no other apparent ill effects, this is a + * regression for the user when enabling FWNMI. So for now, match + * PowerVM. When most Linux clients are fixed, this could be + * changed. + */ rtas_st(rets, 0, RTAS_OUT_SUCCESS); return; } diff --git a/hw/ppc/spapr_rtas_ddw.c b/hw/ppc/spapr_rtas_ddw.c index 3e826e1308..13d339c807 100644 --- a/hw/ppc/spapr_rtas_ddw.c +++ b/hw/ppc/spapr_rtas_ddw.c @@ -72,6 +72,7 @@ static uint32_t spapr_page_mask_to_query_mask(uint64_t page_mask) const struct { int shift; uint32_t mask; } masks[] = { { 12, RTAS_DDW_PGSIZE_4K }, { 16, RTAS_DDW_PGSIZE_64K }, + { 21, RTAS_DDW_PGSIZE_2M }, { 24, RTAS_DDW_PGSIZE_16M }, { 25, RTAS_DDW_PGSIZE_32M }, { 26, RTAS_DDW_PGSIZE_64M }, diff --git a/hw/ppc/vof.c b/hw/ppc/vof.c index 8d96593677..18c3f92317 100644 --- a/hw/ppc/vof.c +++ b/hw/ppc/vof.c @@ -293,7 +293,7 @@ static uint32_t vof_setprop(MachineState *ms, void *fdt, Vof *vof, uint32_t nodeph, uint32_t pname, uint32_t valaddr, uint32_t vallen) { - char propname[OF_PROPNAME_LEN_MAX + 1]; + char propname[OF_PROPNAME_LEN_MAX + 1] = ""; uint32_t ret = PROM_ERROR; int offset, rc; char trval[64] = ""; diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index d34b2c44d2..3dcf20e3a2 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -95,6 +95,7 @@ typedef enum { #include "fpu/softfloat-types.h" #include "fpu/softfloat-helpers.h" +#include "qemu/int128.h" /*---------------------------------------------------------------------------- | Routine to raise any or all of the software IEC/IEEE floating-point @@ -182,7 +183,9 @@ floatx80 int64_to_floatx80(int64_t, float_status *status); float128 int32_to_float128(int32_t, float_status *status); float128 int64_to_float128(int64_t, float_status *status); +float128 int128_to_float128(Int128, float_status *status); float128 uint64_to_float128(uint64_t, float_status *status); +float128 uint128_to_float128(Int128, float_status *status); /*---------------------------------------------------------------------------- | Software half-precision conversion routines. @@ -1201,9 +1204,13 @@ floatx80 floatx80_default_nan(float_status *status); int32_t float128_to_int32(float128, float_status *status); int32_t float128_to_int32_round_to_zero(float128, float_status *status); int64_t float128_to_int64(float128, float_status *status); +Int128 float128_to_int128(float128, float_status *status); int64_t float128_to_int64_round_to_zero(float128, float_status *status); +Int128 float128_to_int128_round_to_zero(float128, float_status *status); uint64_t float128_to_uint64(float128, float_status *status); +Int128 float128_to_uint128(float128, float_status *status); uint64_t float128_to_uint64_round_to_zero(float128, float_status *status); +Int128 float128_to_uint128_round_to_zero(float128, float_status *status); uint32_t float128_to_uint32(float128, float_status *status); uint32_t float128_to_uint32_round_to_zero(float128, float_status *status); float32 float128_to_float32(float128, float_status *status); diff --git a/include/hw/ppc/pnv_lpc.h b/include/hw/ppc/pnv_lpc.h index e893e763dd..8a8d1a3d42 100644 --- a/include/hw/ppc/pnv_lpc.h +++ b/include/hw/ppc/pnv_lpc.h @@ -1,7 +1,7 @@ /* * QEMU PowerPC PowerNV LPC controller * - * Copyright (c) 2016, IBM Corporation. + * Copyright (c) 2016-2022, IBM Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,7 +20,6 @@ #ifndef PPC_PNV_LPC_H #define PPC_PNV_LPC_H -#include "hw/ppc/pnv_psi.h" #include "qom/object.h" #define TYPE_PNV_LPC "pnv-lpc" @@ -84,15 +83,12 @@ struct PnvLpcController { MemoryRegion xscom_regs; /* PSI to generate interrupts */ - PnvPsi *psi; + qemu_irq psi_irq; }; - struct PnvLpcClass { DeviceClass parent_class; - int psi_irq; - DeviceRealize parent_realize; }; diff --git a/include/hw/ppc/pnv_occ.h b/include/hw/ppc/pnv_occ.h index f982ba0024..90a81dae2b 100644 --- a/include/hw/ppc/pnv_occ.h +++ b/include/hw/ppc/pnv_occ.h @@ -1,7 +1,7 @@ /* * QEMU PowerPC PowerNV Emulation of a few OCC related registers * - * Copyright (c) 2015-2017, IBM Corporation. + * Copyright (c) 2015-2022, IBM Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,7 +20,6 @@ #ifndef PPC_PNV_OCC_H #define PPC_PNV_OCC_H -#include "hw/ppc/pnv_psi.h" #include "qom/object.h" #define TYPE_PNV_OCC "pnv-occ" @@ -44,19 +43,17 @@ struct PnvOCC { /* OCC Misc interrupt */ uint64_t occmisc; - PnvPsi *psi; + qemu_irq psi_irq; MemoryRegion xscom_regs; MemoryRegion sram_regs; }; - struct PnvOCCClass { DeviceClass parent_class; int xscom_size; const MemoryRegionOps *xscom_ops; - int psi_irq; }; #define PNV_OCC_SENSOR_DATA_BLOCK_BASE(i) \ diff --git a/include/hw/ppc/pnv_psi.h b/include/hw/ppc/pnv_psi.h index eb841b34a1..8253469b8f 100644 --- a/include/hw/ppc/pnv_psi.h +++ b/include/hw/ppc/pnv_psi.h @@ -1,7 +1,7 @@ /* * QEMU PowerPC PowerNV Processor Service Interface (PSI) model * - * Copyright (c) 2015-2017, IBM Corporation. + * Copyright (c) 2015-2022, IBM Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -79,13 +79,10 @@ struct PnvPsiClass { uint64_t bar_mask; const char *compat; int compat_size; - - void (*irq_set)(PnvPsi *psi, int, bool state); }; /* The PSI and FSP interrupts are muxed on the same IRQ number */ typedef enum PnvPsiIrq { - PSIHB_IRQ_PSI, /* internal use only */ PSIHB_IRQ_FSP, /* internal use only */ PSIHB_IRQ_OCC, PSIHB_IRQ_FSI, @@ -96,8 +93,6 @@ typedef enum PnvPsiIrq { #define PSI_NUM_INTERRUPTS 6 -void pnv_psi_irq_set(PnvPsi *psi, int irq, bool state); - /* P9 PSI Interrupts */ #define PSIHB9_IRQ_PSI 0 #define PSIHB9_IRQ_OCC 1 diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h index 364f165b4b..02af03ada2 100644 --- a/include/hw/ppc/ppc.h +++ b/include/hw/ppc/ppc.h @@ -99,11 +99,11 @@ enum { ARCH_MAC99_U3, }; -#define FW_CFG_PPC_WIDTH (FW_CFG_ARCH_LOCAL + 0x00) -#define FW_CFG_PPC_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01) -#define FW_CFG_PPC_DEPTH (FW_CFG_ARCH_LOCAL + 0x02) -#define FW_CFG_PPC_TBFREQ (FW_CFG_ARCH_LOCAL + 0x03) -#define FW_CFG_PPC_CLOCKFREQ (FW_CFG_ARCH_LOCAL + 0x04) +#define FW_CFG_PPC_WIDTH (FW_CFG_ARCH_LOCAL + 0x00) +#define FW_CFG_PPC_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01) +#define FW_CFG_PPC_DEPTH (FW_CFG_ARCH_LOCAL + 0x02) +#define FW_CFG_PPC_TBFREQ (FW_CFG_ARCH_LOCAL + 0x03) +#define FW_CFG_PPC_CLOCKFREQ (FW_CFG_ARCH_LOCAL + 0x04) #define FW_CFG_PPC_IS_KVM (FW_CFG_ARCH_LOCAL + 0x05) #define FW_CFG_PPC_KVM_HC (FW_CFG_ARCH_LOCAL + 0x06) #define FW_CFG_PPC_KVM_PID (FW_CFG_ARCH_LOCAL + 0x07) diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index f5c33dcc86..14b01c3f59 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -745,6 +745,7 @@ void push_sregs_to_kvm_pr(SpaprMachineState *spapr); #define RTAS_DDW_PGSIZE_128M 0x20 #define RTAS_DDW_PGSIZE_256M 0x40 #define RTAS_DDW_PGSIZE_16G 0x80 +#define RTAS_DDW_PGSIZE_2M 0x100 /* RTAS tokens */ #define RTAS_TOKEN_BASE 0x2000 diff --git a/include/qemu/int128.h b/include/qemu/int128.h index 37e07fd6dd..ef71f56e3f 100644 --- a/include/qemu/int128.h +++ b/include/qemu/int128.h @@ -83,6 +83,11 @@ static inline Int128 int128_rshift(Int128 a, int n) return a >> n; } +static inline Int128 int128_urshift(Int128 a, int n) +{ + return (__uint128_t)a >> n; +} + static inline Int128 int128_lshift(Int128 a, int n) { return a << n; @@ -299,6 +304,20 @@ static inline Int128 int128_rshift(Int128 a, int n) } } +static inline Int128 int128_urshift(Int128 a, int n) +{ + uint64_t h = a.hi; + if (!n) { + return a; + } + h = h >> (n & 63); + if (n >= 64) { + return int128_make64(h); + } else { + return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h); + } +} + static inline Int128 int128_lshift(Int128 a, int n) { uint64_t l = a.lo << (n & 63); @@ -412,5 +431,7 @@ static inline void bswap128s(Int128 *s) } #define UINT128_MAX int128_make128(~0LL, ~0LL) +#define INT128_MAX int128_make128(UINT64_MAX, INT64_MAX) +#define INT128_MIN int128_make128(0, INT64_MIN) #endif /* INT128_H */ diff --git a/pc-bios/skiboot.lid b/pc-bios/skiboot.lid Binary files differindex 8a3c278512..58ec5ec38e 100644 --- a/pc-bios/skiboot.lid +++ b/pc-bios/skiboot.lid diff --git a/roms/skiboot b/roms/skiboot -Subproject 820d43c0a7751e75a8830561f35535dfffd522b +Subproject 24a7eb35966d93455520bc2debdd7954314b638 diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 5062d0e478..d42e2ba8e0 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -6457,6 +6457,7 @@ static void init_proc_POWER10(CPUPPCState *env) register_power5p_common_sprs(env); register_power5p_lpar_sprs(env); register_power5p_ear_sprs(env); + register_power5p_tb_sprs(env); register_power6_common_sprs(env); register_power6_dbg_sprs(env); register_power8_tce_address_control_sprs(env); @@ -6467,6 +6468,7 @@ static void init_proc_POWER10(CPUPPCState *env) register_power8_pmu_user_sprs(env); register_power8_tm_sprs(env); register_power8_pspb_sprs(env); + register_power8_dpdes_sprs(env); register_vtb_sprs(env); register_power8_ic_sprs(env); register_power8_book4_sprs(env); diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c index 7e8be99cc0..99281cc37a 100644 --- a/target/ppc/fpu_helper.c +++ b/target/ppc/fpu_helper.c @@ -2925,6 +2925,27 @@ VSX_CVT_FP_TO_INT(xvcvspsxws, 4, float32, int32, VsrW(i), VsrW(i), 0x80000000U) VSX_CVT_FP_TO_INT(xvcvspuxds, 2, float32, uint64, VsrW(2 * i), VsrD(i), 0ULL) VSX_CVT_FP_TO_INT(xvcvspuxws, 4, float32, uint32, VsrW(i), VsrW(i), 0U) +#define VSX_CVT_FP_TO_INT128(op, tp, rnan) \ +void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ +{ \ + ppc_vsr_t t; \ + int flags; \ + \ + helper_reset_fpstatus(env); \ + t.s128 = float128_to_##tp##_round_to_zero(xb->f128, &env->fp_status); \ + flags = get_float_exception_flags(&env->fp_status); \ + if (unlikely(flags & float_flag_invalid)) { \ + t.VsrD(0) = float_invalid_cvt(env, flags, t.VsrD(0), rnan, 0, GETPC());\ + t.VsrD(1) = -(t.VsrD(0) & 1); \ + } \ + \ + *xt = t; \ + do_float_check_status(env, GETPC()); \ +} + +VSX_CVT_FP_TO_INT128(XSCVQPUQZ, uint128, 0) +VSX_CVT_FP_TO_INT128(XSCVQPSQZ, int128, 0x8000000000000000ULL); + /* * Likewise, except that the result is duplicated into both subwords. * Power ISA v3.1 has Programming Notes for these insns: @@ -3058,6 +3079,18 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ VSX_CVT_INT_TO_FP2(xvcvsxdsp, int64, float32) VSX_CVT_INT_TO_FP2(xvcvuxdsp, uint64, float32) +#define VSX_CVT_INT128_TO_FP(op, tp) \ +void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb)\ +{ \ + helper_reset_fpstatus(env); \ + xt->f128 = tp##_to_float128(xb->s128, &env->fp_status); \ + helper_compute_fprf_float128(env, xt->f128); \ + do_float_check_status(env, GETPC()); \ +} + +VSX_CVT_INT128_TO_FP(XSCVUQQP, uint128); +VSX_CVT_INT128_TO_FP(XSCVSQQP, int128); + /* * VSX_CVT_INT_TO_FP_VECTOR - VSX integer to floating point conversion * op - instruction mnemonic diff --git a/target/ppc/helper.h b/target/ppc/helper.h index 57da11c77e..aa6773c4a5 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -388,6 +388,10 @@ DEF_HELPER_4(xscvqpsdz, void, env, i32, vsr, vsr) DEF_HELPER_4(xscvqpswz, void, env, i32, vsr, vsr) DEF_HELPER_4(xscvqpudz, void, env, i32, vsr, vsr) DEF_HELPER_4(xscvqpuwz, void, env, i32, vsr, vsr) +DEF_HELPER_3(XSCVQPUQZ, void, env, vsr, vsr) +DEF_HELPER_3(XSCVQPSQZ, void, env, vsr, vsr) +DEF_HELPER_3(XSCVUQQP, void, env, vsr, vsr) +DEF_HELPER_3(XSCVSQQP, void, env, vsr, vsr) DEF_HELPER_3(xscvhpdp, void, env, vsr, vsr) DEF_HELPER_4(xscvsdqp, void, env, i32, vsr, vsr) DEF_HELPER_3(xscvspdp, void, env, vsr, vsr) diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode index ac2d3da9a7..39372fe673 100644 --- a/target/ppc/insn32.decode +++ b/target/ppc/insn32.decode @@ -91,6 +91,9 @@ @X_tp_a_bp_rc ...... ....0 ra:5 ....0 .......... rc:1 &X_rc rt=%x_frtp rb=%x_frbp +&X_tb rt rb +@X_tb ...... rt:5 ..... rb:5 .......... . &X_tb + &X_tb_rc rt rb rc:bool @X_tb_rc ...... rt:5 ..... rb:5 .......... rc:1 &X_tb_rc @@ -692,6 +695,10 @@ XSCMPGTQP 111111 ..... ..... ..... 0011100100 - @X ## VSX Binary Floating-Point Convert Instructions XSCVQPDP 111111 ..... 10100 ..... 1101000100 . @X_tb_rc +XSCVQPUQZ 111111 ..... 00000 ..... 1101000100 - @X_tb +XSCVQPSQZ 111111 ..... 01000 ..... 1101000100 - @X_tb +XSCVUQQP 111111 ..... 00011 ..... 1101000100 - @X_tb +XSCVSQQP 111111 ..... 01011 ..... 1101000100 - @X_tb XVCVBF16SPN 111100 ..... 10000 ..... 111011011 .. @XX2 XVCVSPBF16 111100 ..... 10001 ..... 111011011 .. @XX2 diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index f905a2af17..a3c31b4e48 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -1680,7 +1680,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) break; #if defined(TARGET_PPC64) case KVM_EXIT_PAPR_HCALL: - trace_kvm_handle_papr_hcall(); + trace_kvm_handle_papr_hcall(run->papr_hcall.nr); run->papr_hcall.ret = spapr_hypercall(cpu, run->papr_hcall.nr, run->papr_hcall.args); diff --git a/target/ppc/trace-events b/target/ppc/trace-events index 53b107f56e..a79f1b4370 100644 --- a/target/ppc/trace-events +++ b/target/ppc/trace-events @@ -23,7 +23,7 @@ kvm_failed_get_vpa(void) "Warning: Unable to get VPA information from KVM" kvm_handle_dcr_write(void) "handle dcr write" kvm_handle_dcr_read(void) "handle dcr read" kvm_handle_halt(void) "handle halt" -kvm_handle_papr_hcall(void) "handle PAPR hypercall" +kvm_handle_papr_hcall(uint64_t hcall) "0x%" PRIx64 kvm_handle_epr(void) "handle epr" kvm_handle_watchdog_expiry(void) "handle watchdog expiry" kvm_handle_debug_exception(void) "handle debug exception" diff --git a/target/ppc/translate/vsx-impl.c.inc b/target/ppc/translate/vsx-impl.c.inc index 7181a672d8..3692740736 100644 --- a/target/ppc/translate/vsx-impl.c.inc +++ b/target/ppc/translate/vsx-impl.c.inc @@ -838,6 +838,28 @@ static bool trans_XSCVQPDP(DisasContext *ctx, arg_X_tb_rc *a) return true; } +static bool do_helper_env_X_tb(DisasContext *ctx, arg_X_tb *a, + void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr)) +{ + TCGv_ptr xt, xb; + + REQUIRE_INSNS_FLAGS2(ctx, ISA310); + REQUIRE_VSX(ctx); + + xt = gen_avr_ptr(a->rt); + xb = gen_avr_ptr(a->rb); + gen_helper(cpu_env, xt, xb); + tcg_temp_free_ptr(xt); + tcg_temp_free_ptr(xb); + + return true; +} + +TRANS(XSCVUQQP, do_helper_env_X_tb, gen_helper_XSCVUQQP) +TRANS(XSCVSQQP, do_helper_env_X_tb, gen_helper_XSCVSQQP) +TRANS(XSCVQPUQZ, do_helper_env_X_tb, gen_helper_XSCVQPUQZ) +TRANS(XSCVQPSQZ, do_helper_env_X_tb, gen_helper_XSCVQPSQZ) + #define GEN_VSX_HELPER_2(name, op1, op2, inval, type) \ static void gen_##name(DisasContext *ctx) \ { \ diff --git a/tests/unit/test-int128.c b/tests/unit/test-int128.c index b86a3c76e6..25db2455e8 100644 --- a/tests/unit/test-int128.c +++ b/tests/unit/test-int128.c @@ -206,6 +206,55 @@ static void test_rshift(void) test_rshift_one(0xFFFE8000U, 0, 0xFFFFFFFFFFFFFFFEULL, 0x8000000000000000ULL); } +static void __attribute__((__noinline__)) ATTRIBUTE_NOCLONE +test_urshift_one(uint32_t x, int n, uint64_t h, uint64_t l) +{ + Int128 a = expand(x); + Int128 r = int128_urshift(a, n); + g_assert_cmpuint(int128_getlo(r), ==, l); + g_assert_cmpuint(int128_gethi(r), ==, h); +} + +static void test_urshift(void) +{ + test_urshift_one(0x00010000U, 64, 0x0000000000000000ULL, + 0x0000000000000001ULL); + test_urshift_one(0x80010000U, 64, 0x0000000000000000ULL, + 0x8000000000000001ULL); + test_urshift_one(0x7FFE0000U, 64, 0x0000000000000000ULL, + 0x7FFFFFFFFFFFFFFEULL); + test_urshift_one(0xFFFE0000U, 64, 0x0000000000000000ULL, + 0xFFFFFFFFFFFFFFFEULL); + test_urshift_one(0x00010000U, 60, 0x0000000000000000ULL, + 0x0000000000000010ULL); + test_urshift_one(0x80010000U, 60, 0x0000000000000008ULL, + 0x0000000000000010ULL); + test_urshift_one(0x00018000U, 60, 0x0000000000000000ULL, + 0x0000000000000018ULL); + test_urshift_one(0x80018000U, 60, 0x0000000000000008ULL, + 0x0000000000000018ULL); + test_urshift_one(0x7FFE0000U, 60, 0x0000000000000007ULL, + 0xFFFFFFFFFFFFFFE0ULL); + test_urshift_one(0xFFFE0000U, 60, 0x000000000000000FULL, + 0xFFFFFFFFFFFFFFE0ULL); + test_urshift_one(0x7FFE8000U, 60, 0x0000000000000007ULL, + 0xFFFFFFFFFFFFFFE8ULL); + test_urshift_one(0xFFFE8000U, 60, 0x000000000000000FULL, + 0xFFFFFFFFFFFFFFE8ULL); + test_urshift_one(0x00018000U, 0, 0x0000000000000001ULL, + 0x8000000000000000ULL); + test_urshift_one(0x80018000U, 0, 0x8000000000000001ULL, + 0x8000000000000000ULL); + test_urshift_one(0x7FFE0000U, 0, 0x7FFFFFFFFFFFFFFEULL, + 0x0000000000000000ULL); + test_urshift_one(0xFFFE0000U, 0, 0xFFFFFFFFFFFFFFFEULL, + 0x0000000000000000ULL); + test_urshift_one(0x7FFE8000U, 0, 0x7FFFFFFFFFFFFFFEULL, + 0x8000000000000000ULL); + test_urshift_one(0xFFFE8000U, 0, 0xFFFFFFFFFFFFFFFEULL, + 0x8000000000000000ULL); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); @@ -219,5 +268,6 @@ int main(int argc, char **argv) g_test_add_func("/int128/int128_ge", test_ge); g_test_add_func("/int128/int128_gt", test_gt); g_test_add_func("/int128/int128_rshift", test_rshift); + g_test_add_func("/int128/int128_urshift", test_urshift); return g_test_run(); } |