diff options
75 files changed, 1356 insertions, 689 deletions
diff --git a/docs/system/ppc/powernv.rst b/docs/system/ppc/powernv.rst index c8f9762342..09f3965858 100644 --- a/docs/system/ppc/powernv.rst +++ b/docs/system/ppc/powernv.rst @@ -195,11 +195,6 @@ Use a MTD drive to add a PNOR to the machine, and get a NVRAM : -drive file=./witherspoon.pnor,format=raw,if=mtd -CAVEATS -------- - - * No support for multiple HW threads (SMT=1). Same as pseries. - Maintainer contact information ------------------------------ diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c index c2e0a9fa1a..64e1cbce17 100644 --- a/hw/arm/sbsa-ref.c +++ b/hw/arm/sbsa-ref.c @@ -689,13 +689,7 @@ static void create_pcie(SBSAMachineState *sms) pci = PCI_HOST_BRIDGE(dev); if (pci->bus) { for (i = 0; i < nb_nics; i++) { - NICInfo *nd = &nd_table[i]; - - if (!nd->model) { - nd->model = g_strdup(mc->default_nic); - } - - pci_nic_init_nofail(nd, pci->bus, nd->model, NULL); + pci_nic_init_nofail(&nd_table[i], pci->bus, mc->default_nic, NULL); } } diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 55f2706bc9..6b674231c2 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -29,6 +29,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/bitmap.h" +#include "qemu/error-report.h" #include "trace.h" #include "hw/core/cpu.h" #include "target/arm/cpu.h" diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 796181e169..8a4c663735 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1479,13 +1479,7 @@ static void create_pcie(VirtMachineState *vms) vms->bus = pci->bus; if (vms->bus) { for (i = 0; i < nb_nics; i++) { - NICInfo *nd = &nd_table[i]; - - if (!nd->model) { - nd->model = g_strdup(mc->default_nic); - } - - pci_nic_init_nofail(nd, pci->bus, nd->model, NULL); + pci_nic_init_nofail(&nd_table[i], pci->bus, mc->default_nic, NULL); } } diff --git a/hw/intc/pnv_xive2.c b/hw/intc/pnv_xive2.c index ed438a20ed..bbb44a533c 100644 --- a/hw/intc/pnv_xive2.c +++ b/hw/intc/pnv_xive2.c @@ -1590,6 +1590,18 @@ static uint32_t pnv_xive2_ic_tm_get_pir(PnvXive2 *xive, hwaddr offset) return xive->chip->chip_id << 8 | offset >> xive->ic_shift; } +static uint32_t pnv_xive2_ic_tm_get_hw_page_offset(PnvXive2 *xive, + hwaddr offset) +{ + /* + * Indirect TIMA accesses are similar to direct accesses for + * privilege ring 0. So remove any traces of the hw thread ID from + * the offset in the IC BAR as it could be interpreted as the ring + * privilege when calling the underlying direct access functions. + */ + return offset & ((1ull << xive->ic_shift) - 1); +} + static XiveTCTX *pnv_xive2_get_indirect_tctx(PnvXive2 *xive, uint32_t pir) { PnvChip *chip = xive->chip; @@ -1612,14 +1624,17 @@ static uint64_t pnv_xive2_ic_tm_indirect_read(void *opaque, hwaddr offset, unsigned size) { PnvXive2 *xive = PNV_XIVE2(opaque); + XivePresenter *xptr = XIVE_PRESENTER(xive); + hwaddr hw_page_offset; uint32_t pir; XiveTCTX *tctx; uint64_t val = -1; pir = pnv_xive2_ic_tm_get_pir(xive, offset); + hw_page_offset = pnv_xive2_ic_tm_get_hw_page_offset(xive, offset); tctx = pnv_xive2_get_indirect_tctx(xive, pir); if (tctx) { - val = xive_tctx_tm_read(NULL, tctx, offset, size); + val = xive_tctx_tm_read(xptr, tctx, hw_page_offset, size); } return val; @@ -1629,13 +1644,16 @@ static void pnv_xive2_ic_tm_indirect_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) { PnvXive2 *xive = PNV_XIVE2(opaque); + XivePresenter *xptr = XIVE_PRESENTER(xive); + hwaddr hw_page_offset; uint32_t pir; XiveTCTX *tctx; pir = pnv_xive2_ic_tm_get_pir(xive, offset); + hw_page_offset = pnv_xive2_ic_tm_get_hw_page_offset(xive, offset); tctx = pnv_xive2_get_indirect_tctx(xive, pir); if (tctx) { - xive_tctx_tm_write(NULL, tctx, offset, val, size); + xive_tctx_tm_write(xptr, tctx, hw_page_offset, val, size); } } @@ -1644,11 +1662,11 @@ static const MemoryRegionOps pnv_xive2_ic_tm_indirect_ops = { .write = pnv_xive2_ic_tm_indirect_write, .endianness = DEVICE_BIG_ENDIAN, .valid = { - .min_access_size = 8, + .min_access_size = 1, .max_access_size = 8, }, .impl = { - .min_access_size = 8, + .min_access_size = 1, .max_access_size = 8, }, }; diff --git a/hw/intc/trace-events b/hw/intc/trace-events index 5c6094c457..36ff71f947 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -265,8 +265,8 @@ xive_source_esb_read(uint64_t addr, uint32_t srcno, uint64_t value) "@0x%"PRIx64 xive_source_esb_write(uint64_t addr, uint32_t srcno, uint64_t value) "@0x%"PRIx64" IRQ 0x%x val=0x%"PRIx64 xive_router_end_notify(uint8_t end_blk, uint32_t end_idx, uint32_t end_data) "END 0x%02x/0x%04x -> enqueue 0x%08x" xive_router_end_escalate(uint8_t end_blk, uint32_t end_idx, uint8_t esc_blk, uint32_t esc_idx, uint32_t end_data) "END 0x%02x/0x%04x -> escalate END 0x%02x/0x%04x data 0x%08x" -xive_tctx_tm_write(uint64_t offset, unsigned int size, uint64_t value) "@0x%"PRIx64" sz=%d val=0x%" PRIx64 -xive_tctx_tm_read(uint64_t offset, unsigned int size, uint64_t value) "@0x%"PRIx64" sz=%d val=0x%" PRIx64 +xive_tctx_tm_write(uint32_t index, uint64_t offset, unsigned int size, uint64_t value) "target=%d @0x%"PRIx64" sz=%d val=0x%" PRIx64 +xive_tctx_tm_read(uint32_t index, uint64_t offset, unsigned int size, uint64_t value) "target=%d @0x%"PRIx64" sz=%d val=0x%" PRIx64 xive_presenter_notify(uint8_t nvt_blk, uint32_t nvt_idx, uint8_t ring) "found NVT 0x%x/0x%x ring=0x%x" xive_end_source_read(uint8_t end_blk, uint32_t end_idx, uint64_t addr) "END 0x%x/0x%x @0x%"PRIx64 diff --git a/hw/intc/xive.c b/hw/intc/xive.c index 84c079b034..56670b2cac 100644 --- a/hw/intc/xive.c +++ b/hw/intc/xive.c @@ -566,7 +566,7 @@ void xive_tctx_tm_write(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, { const XiveTmOp *xto; - trace_xive_tctx_tm_write(offset, size, value); + trace_xive_tctx_tm_write(tctx->cs->cpu_index, offset, size, value); /* * TODO: check V bit in Q[0-3]W2 @@ -639,7 +639,7 @@ uint64_t xive_tctx_tm_read(XivePresenter *xptr, XiveTCTX *tctx, hwaddr offset, */ ret = xive_tm_raw_read(tctx, offset, size); out: - trace_xive_tctx_tm_read(offset, size, ret); + trace_xive_tctx_tm_read(tctx->cs->cpu_index, offset, size, ret); return ret; } @@ -1175,11 +1175,11 @@ static const MemoryRegionOps xive_source_esb_ops = { .write = xive_source_esb_write, .endianness = DEVICE_BIG_ENDIAN, .valid = { - .min_access_size = 8, + .min_access_size = 1, .max_access_size = 8, }, .impl = { - .min_access_size = 8, + .min_access_size = 1, .max_access_size = 8, }, }; @@ -1232,8 +1232,7 @@ static void xive_source_reset(void *dev) /* Do not clear the LSI bitmap */ - /* PQs are initialized to 0b01 (Q=1) which corresponds to "ints off" */ - memset(xsrc->status, XIVE_ESB_OFF, xsrc->nr_irqs); + memset(xsrc->status, xsrc->reset_pq, xsrc->nr_irqs); } static void xive_source_realize(DeviceState *dev, Error **errp) @@ -1287,6 +1286,11 @@ static Property xive_source_properties[] = { DEFINE_PROP_UINT64("flags", XiveSource, esb_flags, 0), DEFINE_PROP_UINT32("nr-irqs", XiveSource, nr_irqs, 0), DEFINE_PROP_UINT32("shift", XiveSource, esb_shift, XIVE_ESB_64K_2PAGE), + /* + * By default, PQs are initialized to 0b01 (Q=1) which corresponds + * to "ints off" + */ + DEFINE_PROP_UINT8("reset-pq", XiveSource, reset_pq, XIVE_ESB_OFF), DEFINE_PROP_LINK("xive", XiveSource, xive, TYPE_XIVE_NOTIFIER, XiveNotifier *), DEFINE_PROP_END_OF_LIST(), @@ -2002,11 +2006,11 @@ static const MemoryRegionOps xive_end_source_ops = { .write = xive_end_source_write, .endianness = DEVICE_BIG_ENDIAN, .valid = { - .min_access_size = 8, + .min_access_size = 1, .max_access_size = 8, }, .impl = { - .min_access_size = 8, + .min_access_size = 1, .max_access_size = 8, }, }; diff --git a/hw/intc/xive2.c b/hw/intc/xive2.c index 4d9ff41956..c37ef25d44 100644 --- a/hw/intc/xive2.c +++ b/hw/intc/xive2.c @@ -954,11 +954,11 @@ static const MemoryRegionOps xive2_end_source_ops = { .write = xive2_end_source_write, .endianness = DEVICE_BIG_ENDIAN, .valid = { - .min_access_size = 8, + .min_access_size = 1, .max_access_size = 8, }, .impl = { - .min_access_size = 8, + .min_access_size = 1, .max_access_size = 8, }, }; diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index ca8824b6ef..51a453fa9a 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -547,13 +547,7 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState * /* Network init */ for (i = 0; i < nb_nics; i++) { - NICInfo *nd = &nd_table[i]; - - if (!nd->model) { - nd->model = g_strdup(mc->default_nic); - } - - pci_nic_init_nofail(nd, pci_bus, nd->model, NULL); + pci_nic_init_nofail(&nd_table[i], pci_bus, mc->default_nic, NULL); } /* diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c index 216812f660..3dd91da7a6 100644 --- a/hw/mips/loongson3_virt.c +++ b/hw/mips/loongson3_virt.c @@ -454,13 +454,7 @@ static inline void loongson3_virt_devices_init(MachineState *machine, } for (i = 0; i < nb_nics; i++) { - NICInfo *nd = &nd_table[i]; - - if (!nd->model) { - nd->model = g_strdup(mc->default_nic); - } - - pci_nic_init_nofail(nd, pci_bus, nd->model, NULL); + pci_nic_init_nofail(&nd_table[i], pci_bus, mc->default_nic, NULL); } } diff --git a/hw/net/e1000.c b/hw/net/e1000.c index aae5f0bdc0..093c2d4531 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -888,7 +888,6 @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt) uint16_t vlan_special = 0; uint8_t vlan_status = 0; uint8_t min_buf[ETH_ZLEN]; - struct iovec min_iov; uint8_t *filter_buf = iov->iov_base; size_t size = iov_size(iov, iovcnt); size_t iov_ofs = 0; @@ -905,15 +904,7 @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt) return 0; } - /* Pad to minimum Ethernet frame length */ - if (size < sizeof(min_buf)) { - iov_to_buf(iov, iovcnt, 0, min_buf, size); - memset(&min_buf[size], 0, sizeof(min_buf) - size); - min_iov.iov_base = filter_buf = min_buf; - min_iov.iov_len = size = sizeof(min_buf); - iovcnt = 1; - iov = &min_iov; - } else if (iov->iov_len < MAXIMUM_ETHERNET_HDR_LEN) { + if (iov->iov_len < MAXIMUM_ETHERNET_HDR_LEN) { /* This is very unlikely, but may happen. */ iov_to_buf(iov, iovcnt, 0, min_buf, MAXIMUM_ETHERNET_HDR_LEN); filter_buf = min_buf; diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c index 9f185d099c..f8aeafa16b 100644 --- a/hw/net/e1000e_core.c +++ b/hw/net/e1000e_core.c @@ -2604,12 +2604,38 @@ e1000e_mac_icr_read(E1000ECore *core, int index) e1000e_lower_interrupts(core, ICR, 0xffffffff); } - if ((core->mac[ICR] & E1000_ICR_ASSERTED) && - (core->mac[CTRL_EXT] & E1000_CTRL_EXT_IAME)) { - trace_e1000e_irq_icr_clear_iame(); - e1000e_lower_interrupts(core, ICR, 0xffffffff); - trace_e1000e_irq_icr_process_iame(); - e1000e_lower_interrupts(core, IMS, core->mac[IAM]); + if (core->mac[ICR] & E1000_ICR_ASSERTED) { + if (core->mac[CTRL_EXT] & E1000_CTRL_EXT_IAME) { + trace_e1000e_irq_icr_clear_iame(); + e1000e_lower_interrupts(core, ICR, 0xffffffff); + trace_e1000e_irq_icr_process_iame(); + e1000e_lower_interrupts(core, IMS, core->mac[IAM]); + } + + /* + * The datasheet does not say what happens when interrupt was asserted + * (ICR.INT_ASSERT=1) and auto mask is *not* active. + * However, section of 13.3.27 the PCIe* GbE Controllers Open Source + * Software Developer’s Manual, which were written for older devices, + * namely 631xESB/632xESB, 82563EB/82564EB, 82571EB/82572EI & + * 82573E/82573V/82573L, does say: + * > If IMS = 0b, then the ICR register is always clear-on-read. If IMS + * > is not 0b, but some ICR bit is set where the corresponding IMS bit + * > is not set, then a read does not clear the ICR register. For + * > example, if IMS = 10101010b and ICR = 01010101b, then a read to the + * > ICR register does not clear it. If IMS = 10101010b and + * > ICR = 0101011b, then a read to the ICR register clears it entirely + * > (ICR.INT_ASSERTED = 1b). + * + * Linux does no longer activate auto mask since commit + * 0a8047ac68e50e4ccbadcfc6b6b070805b976885 and the real hardware + * clears ICR even in such a case so we also should do so. + */ + if (core->mac[ICR] & core->mac[IMS]) { + trace_e1000e_irq_icr_clear_icr_bit_ims(core->mac[ICR], + core->mac[IMS]); + e1000e_lower_interrupts(core, ICR, 0xffffffff); + } } return ret; diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c index d3bf14be53..702b001be2 100644 --- a/hw/net/ftgmac100.c +++ b/hw/net/ftgmac100.c @@ -968,14 +968,6 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf, return -1; } - /* TODO : Pad to minimum Ethernet frame length */ - /* handle small packets. */ - if (size < 10) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: dropped frame of %zd bytes\n", - __func__, size); - return size; - } - if (!ftgmac100_filter(s, buf, size)) { return size; } diff --git a/hw/net/i82596.c b/hw/net/i82596.c index ec21e2699a..ab26f8bea1 100644 --- a/hw/net/i82596.c +++ b/hw/net/i82596.c @@ -72,10 +72,6 @@ enum commands { #define I596_EOF 0x8000 #define SIZE_MASK 0x3fff -#define ETHER_TYPE_LEN 2 -#define VLAN_TCI_LEN 2 -#define VLAN_HLEN (ETHER_TYPE_LEN + VLAN_TCI_LEN) - /* various flags in the chip config registers */ #define I596_PREFETCH (s->config[0] & 0x80) #define I596_PROMISC (s->config[8] & 0x01) @@ -488,8 +484,6 @@ bool i82596_can_receive(NetClientState *nc) return true; } -#define MIN_BUF_SIZE 60 - ssize_t i82596_receive(NetClientState *nc, const uint8_t *buf, size_t sz) { I82596State *s = qemu_get_nic_opaque(nc); @@ -500,7 +494,6 @@ ssize_t i82596_receive(NetClientState *nc, const uint8_t *buf, size_t sz) size_t bufsz = sz; /* length of data in buf */ uint32_t crc; uint8_t *crc_ptr; - uint8_t buf1[MIN_BUF_SIZE + VLAN_HLEN]; static const uint8_t broadcast_macaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -583,17 +576,6 @@ ssize_t i82596_receive(NetClientState *nc, const uint8_t *buf, size_t sz) } } - /* if too small buffer, then expand it */ - if (len < MIN_BUF_SIZE + VLAN_HLEN) { - memcpy(buf1, buf, len); - memset(buf1 + len, 0, MIN_BUF_SIZE + VLAN_HLEN - len); - buf = buf1; - if (len < MIN_BUF_SIZE) { - len = MIN_BUF_SIZE; - } - bufsz = len; - } - /* Calculate the ethernet checksum (4 bytes) */ len += 4; crc = cpu_to_be32(crc32(~0, buf, sz)); diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c index d00b1caa6a..8b6b75c522 100644 --- a/hw/net/igb_core.c +++ b/hw/net/igb_core.c @@ -2678,12 +2678,7 @@ static uint32_t igb_get_status(IGBCore *core, int index) res |= E1000_STATUS_IOV_MODE; } - /* - * Windows driver 12.18.9.23 resets if E1000_STATUS_GIO_MASTER_ENABLE is - * left set after E1000_CTRL_LRST is set. - */ - if (!(core->mac[CTRL] & E1000_CTRL_GIO_MASTER_DISABLE) && - !(core->mac[CTRL] & E1000_CTRL_LRST)) { + if (!(core->mac[CTRL] & E1000_CTRL_GIO_MASTER_DISABLE)) { res |= E1000_STATUS_GIO_MASTER_ENABLE; } diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c index 3f31d04efb..d79c884d50 100644 --- a/hw/net/ne2000.c +++ b/hw/net/ne2000.c @@ -167,15 +167,12 @@ static int ne2000_buffer_full(NE2000State *s) return 0; } -#define MIN_BUF_SIZE 60 - ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_) { NE2000State *s = qemu_get_nic_opaque(nc); size_t size = size_; uint8_t *p; unsigned int total_len, next, avail, len, index, mcast_idx; - uint8_t buf1[60]; static const uint8_t broadcast_macaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -213,15 +210,6 @@ ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_) } } - - /* if too small buffer, then expand it */ - if (size < MIN_BUF_SIZE) { - memcpy(buf1, buf, size); - memset(buf1 + size, 0, MIN_BUF_SIZE - size); - buf = buf1; - size = MIN_BUF_SIZE; - } - index = s->curpag << 8; if (index >= NE2000_PMEM_END) { index = s->start; diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c index d456094575..02828ae716 100644 --- a/hw/net/pcnet.c +++ b/hw/net/pcnet.c @@ -987,7 +987,6 @@ ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_) { PCNetState *s = qemu_get_nic_opaque(nc); int is_padr = 0, is_bcast = 0, is_ladr = 0; - uint8_t buf1[60]; int remaining; int crc_err = 0; size_t size = size_; @@ -1000,14 +999,6 @@ ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_) printf("pcnet_receive size=%zu\n", size); #endif - /* if too small buffer, then expand it */ - if (size < MIN_BUF_SIZE) { - memcpy(buf1, buf, size); - memset(buf1 + size, 0, MIN_BUF_SIZE - size); - buf = buf1; - size = MIN_BUF_SIZE; - } - if (CSR_PROM(s) || (is_padr=padr_match(s, buf, size)) || (is_bcast=padr_bcast(s, buf, size)) diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index 5f1a4d359b..b4df75b2c9 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -826,7 +826,6 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t uint32_t packet_header = 0; - uint8_t buf1[MIN_BUF_SIZE + VLAN_HLEN]; static const uint8_t broadcast_macaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -938,17 +937,6 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t } } - /* if too small buffer, then expand it - * Include some tailroom in case a vlan tag is later removed. */ - if (size < MIN_BUF_SIZE + VLAN_HLEN) { - memcpy(buf1, buf, size); - memset(buf1 + size, 0, MIN_BUF_SIZE + VLAN_HLEN - size); - buf = buf1; - if (size < MIN_BUF_SIZE) { - size = MIN_BUF_SIZE; - } - } - if (rtl8139_cp_receiver_enabled(s)) { if (!rtl8139_cp_rx_valid(s)) { diff --git a/hw/net/sungem.c b/hw/net/sungem.c index eb01520790..510b370e5f 100644 --- a/hw/net/sungem.c +++ b/hw/net/sungem.c @@ -107,6 +107,15 @@ OBJECT_DECLARE_SIMPLE_TYPE(SunGEMState, SUNGEM) #define RXDMA_FTAG 0x0110UL /* RX FIFO Tag */ #define RXDMA_FSZ 0x0120UL /* RX FIFO Size */ +/* WOL Registers */ +#define SUNGEM_MMIO_WOL_SIZE 0x14 + +#define WOL_MATCH0 0x0000UL +#define WOL_MATCH1 0x0004UL +#define WOL_MATCH2 0x0008UL +#define WOL_MCOUNT 0x000CUL +#define WOL_WAKECSR 0x0010UL + /* MAC Registers */ #define SUNGEM_MMIO_MAC_SIZE 0x200 @@ -168,6 +177,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(SunGEMState, SUNGEM) #define SUNGEM_MMIO_PCS_SIZE 0x60 #define PCS_MIISTAT 0x0004UL /* PCS MII Status Register */ #define PCS_ISTAT 0x0018UL /* PCS Interrupt Status Reg */ + #define PCS_SSTATE 0x005CUL /* Serialink State Register */ /* Descriptors */ @@ -200,6 +210,7 @@ struct SunGEMState { MemoryRegion greg; MemoryRegion txdma; MemoryRegion rxdma; + MemoryRegion wol; MemoryRegion mac; MemoryRegion mif; MemoryRegion pcs; @@ -550,7 +561,6 @@ static ssize_t sungem_receive(NetClientState *nc, const uint8_t *buf, PCIDevice *d = PCI_DEVICE(s); uint32_t mac_crc, done, kick, max_fsize; uint32_t fcs_size, ints, rxdma_cfg, rxmac_cfg, csum, coff; - uint8_t smallbuf[60]; struct gem_rxd desc; uint64_t dbase, baddr; unsigned int rx_cond; @@ -584,19 +594,6 @@ static ssize_t sungem_receive(NetClientState *nc, const uint8_t *buf, return size; } - /* We don't drop too small frames since we get them in qemu, we pad - * them instead. We should probably use the min frame size register - * but I don't want to use a variable size staging buffer and I - * know both MacOS and Linux use the default 64 anyway. We use 60 - * here to account for the non-existent FCS. - */ - if (size < 60) { - memcpy(smallbuf, buf, size); - memset(&smallbuf[size], 0, 60 - size); - buf = smallbuf; - size = 60; - } - /* Get MAC crc */ mac_crc = net_crc32_le(buf, ETH_ALEN); @@ -1076,6 +1073,43 @@ static const MemoryRegionOps sungem_mmio_rxdma_ops = { }, }; +static void sungem_mmio_wol_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) +{ + trace_sungem_mmio_wol_write(addr, val); + + switch (addr) { + case WOL_WAKECSR: + if (val != 0) { + qemu_log_mask(LOG_UNIMP, "sungem: WOL not supported\n"); + } + break; + default: + qemu_log_mask(LOG_UNIMP, "sungem: WOL not supported\n"); + } +} + +static uint64_t sungem_mmio_wol_read(void *opaque, hwaddr addr, unsigned size) +{ + uint32_t val = -1; + + qemu_log_mask(LOG_UNIMP, "sungem: WOL not supported\n"); + + trace_sungem_mmio_wol_read(addr, val); + + return val; +} + +static const MemoryRegionOps sungem_mmio_wol_ops = { + .read = sungem_mmio_wol_read, + .write = sungem_mmio_wol_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + static void sungem_mmio_mac_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { @@ -1344,6 +1378,10 @@ static void sungem_realize(PCIDevice *pci_dev, Error **errp) "sungem.rxdma", SUNGEM_MMIO_RXDMA_SIZE); memory_region_add_subregion(&s->sungem, 0x4000, &s->rxdma); + memory_region_init_io(&s->wol, OBJECT(s), &sungem_mmio_wol_ops, s, + "sungem.wol", SUNGEM_MMIO_WOL_SIZE); + memory_region_add_subregion(&s->sungem, 0x3000, &s->wol); + memory_region_init_io(&s->mac, OBJECT(s), &sungem_mmio_mac_ops, s, "sungem.mac", SUNGEM_MMIO_MAC_SIZE); memory_region_add_subregion(&s->sungem, 0x6000, &s->mac); diff --git a/hw/net/sunhme.c b/hw/net/sunhme.c index 1f3d8011ae..391d26fb82 100644 --- a/hw/net/sunhme.c +++ b/hw/net/sunhme.c @@ -714,8 +714,6 @@ static inline void sunhme_set_rx_ring_nr(SunHMEState *s, int i) s->erxregs[HME_ERXI_RING >> 2] = ring; } -#define MIN_BUF_SIZE 60 - static ssize_t sunhme_receive(NetClientState *nc, const uint8_t *buf, size_t size) { @@ -724,7 +722,6 @@ static ssize_t sunhme_receive(NetClientState *nc, const uint8_t *buf, dma_addr_t rb, addr; uint32_t intstatus, status, buffer, buffersize, sum; uint16_t csum; - uint8_t buf1[60]; int nr, cr, len, rxoffset, csum_offset; trace_sunhme_rx_incoming(size); @@ -775,14 +772,6 @@ static ssize_t sunhme_receive(NetClientState *nc, const uint8_t *buf, trace_sunhme_rx_filter_accept(); - /* If too small buffer, then expand it */ - if (size < MIN_BUF_SIZE) { - memcpy(buf1, buf, size); - memset(buf1 + size, 0, MIN_BUF_SIZE - size); - buf = buf1; - size = MIN_BUF_SIZE; - } - rb = s->erxregs[HME_ERXI_RING >> 2] & HME_ERXI_RING_ADDR; nr = sunhme_get_rx_ring_count(s); cr = sunhme_get_rx_ring_nr(s); diff --git a/hw/net/trace-events b/hw/net/trace-events index e4a98b2c7d..6b5ba669a2 100644 --- a/hw/net/trace-events +++ b/hw/net/trace-events @@ -217,6 +217,7 @@ e1000e_irq_read_ims(uint32_t ims) "Current IMS: 0x%x" e1000e_irq_icr_clear_nonmsix_icr_read(void) "Clearing ICR on read due to non MSI-X int" e1000e_irq_icr_clear_zero_ims(void) "Clearing ICR on read due to zero IMS" e1000e_irq_icr_clear_iame(void) "Clearing ICR on read due to IAME" +e1000e_irq_icr_clear_icr_bit_ims(uint32_t icr, uint32_t ims) "Clearing ICR on read due corresponding IMS bit: 0x%x & 0x%x" e1000e_irq_iam_clear_eiame(uint32_t iam, uint32_t cause) "Clearing IMS due to EIAME, IAM: 0x%X, cause: 0x%X" e1000e_irq_icr_clear_eiac(uint32_t icr, uint32_t eiac) "Clearing ICR bits due to EIAC, ICR: 0x%X, EIAC: 0x%X" e1000e_irq_ims_clear_set_imc(uint32_t val) "Clearing IMS bits due to IMC write 0x%x" @@ -350,6 +351,8 @@ sungem_mmio_txdma_write(uint64_t addr, uint64_t val) "MMIO txdma write to 0x%"PR sungem_mmio_txdma_read(uint64_t addr, uint64_t val) "MMIO txdma read from 0x%"PRIx64" val=0x%"PRIx64 sungem_mmio_rxdma_write(uint64_t addr, uint64_t val) "MMIO rxdma write to 0x%"PRIx64" val=0x%"PRIx64 sungem_mmio_rxdma_read(uint64_t addr, uint64_t val) "MMIO rxdma read from 0x%"PRIx64" val=0x%"PRIx64 +sungem_mmio_wol_write(uint64_t addr, uint64_t val) "MMIO wol write to 0x%"PRIx64" val=0x%"PRIx64 +sungem_mmio_wol_read(uint64_t addr, uint64_t val) "MMIO wol read from 0x%"PRIx64" val=0x%"PRIx64 sungem_mmio_mac_write(uint64_t addr, uint64_t val) "MMIO mac write to 0x%"PRIx64" val=0x%"PRIx64 sungem_mmio_mac_read(uint64_t addr, uint64_t val) "MMIO mac read from 0x%"PRIx64" val=0x%"PRIx64 sungem_mmio_mif_write(uint64_t addr, uint64_t val) "MMIO mif write to 0x%"PRIx64" val=0x%"PRIx64 diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index aa421a908a..04783f5b94 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -3630,12 +3630,12 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) } if (n->net_conf.tx_queue_size < VIRTIO_NET_TX_QUEUE_MIN_SIZE || - n->net_conf.tx_queue_size > VIRTQUEUE_MAX_SIZE || + n->net_conf.tx_queue_size > virtio_net_max_tx_queue_size(n) || !is_power_of_2(n->net_conf.tx_queue_size)) { error_setg(errp, "Invalid tx_queue_size (= %" PRIu16 "), " "must be a power of 2 between %d and %d", n->net_conf.tx_queue_size, VIRTIO_NET_TX_QUEUE_MIN_SIZE, - VIRTQUEUE_MAX_SIZE); + virtio_net_max_tx_queue_size(n)); virtio_cleanup(vdev); return; } diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index 18b9edfdb2..5dfacb1098 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -40,7 +40,6 @@ #define PCI_DEVICE_ID_VMWARE_VMXNET3_REVISION 0x1 #define VMXNET3_MSIX_BAR_SIZE 0x2000 -#define MIN_BUF_SIZE 60 /* Compatibility flags for migration */ #define VMXNET3_COMPAT_FLAG_OLD_MSI_OFFSETS_BIT 0 @@ -1977,7 +1976,6 @@ vmxnet3_receive(NetClientState *nc, const uint8_t *buf, size_t size) { VMXNET3State *s = qemu_get_nic_opaque(nc); size_t bytes_indicated; - uint8_t min_buf[MIN_BUF_SIZE]; if (!vmxnet3_can_receive(nc)) { VMW_PKPRN("Cannot receive now"); @@ -1990,14 +1988,6 @@ vmxnet3_receive(NetClientState *nc, const uint8_t *buf, size_t size) size -= sizeof(struct virtio_net_hdr); } - /* Pad to minimum Ethernet frame length */ - if (size < sizeof(min_buf)) { - memcpy(min_buf, buf, size); - memset(&min_buf[size], 0, sizeof(min_buf) - size); - buf = min_buf; - size = sizeof(min_buf); - } - net_rx_pkt_set_packet_type(s->rx_pkt, get_eth_packet_type(PKT_GET_ETH_HDR(buf))); diff --git a/hw/pci-host/mv64361.c b/hw/pci-host/mv64361.c index 19e8031a3f..01bd8c887f 100644 --- a/hw/pci-host/mv64361.c +++ b/hw/pci-host/mv64361.c @@ -541,6 +541,12 @@ static uint64_t mv64361_read(void *opaque, hwaddr addr, unsigned int size) } } break; + case MV64340_ETH_PHY_ADDR: + ret = 0x98; + break; + case MV64340_ETH_SMI: + ret = BIT(27); + break; case MV64340_CUNIT_ARBITER_CONTROL_REG: ret = 0x11ff0000 | (s->gpp_int_level << 10); break; diff --git a/hw/pci-host/mv643xx.h b/hw/pci-host/mv643xx.h index cd26a43f18..f2e1baea88 100644 --- a/hw/pci-host/mv643xx.h +++ b/hw/pci-host/mv643xx.h @@ -656,6 +656,9 @@ /* Ethernet Unit Registers */ /****************************************/ +#define MV64340_ETH_PHY_ADDR 0x2000 +#define MV64340_ETH_SMI 0x2004 + /*******************************************/ /* CUNIT Registers */ /*******************************************/ diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c index af5489de26..9c9944188b 100644 --- a/hw/ppc/pegasos2.c +++ b/hw/ppc/pegasos2.c @@ -44,6 +44,8 @@ #define PROM_ADDR 0xfff00000 #define PROM_SIZE 0x80000 +#define INITRD_MIN_ADDR 0x600000 + #define KVMPPC_HCALL_BASE 0xf000 #define KVMPPC_H_RTAS (KVMPPC_HCALL_BASE + 0x0) #define KVMPPC_H_VOF_CLIENT (KVMPPC_HCALL_BASE + 0x5) @@ -80,6 +82,8 @@ struct Pegasos2MachineState { uint64_t kernel_addr; uint64_t kernel_entry; uint64_t kernel_size; + uint64_t initrd_addr; + uint64_t initrd_size; }; static void *build_fdt(MachineState *machine, int *fdt_size); @@ -117,7 +121,8 @@ static void pegasos2_init(MachineState *machine) I2CBus *i2c_bus; const char *fwname = machine->firmware ?: PROM_FILENAME; char *filename; - int i, sz; + int i; + ssize_t sz; uint8_t *spd_data; /* init CPU */ @@ -213,6 +218,20 @@ static void pegasos2_init(MachineState *machine) warn_report("Using Virtual OpenFirmware but no -kernel option."); } + if (machine->initrd_filename) { + pm->initrd_addr = pm->kernel_addr + pm->kernel_size + 64 * KiB; + pm->initrd_addr = ROUND_UP(pm->initrd_addr, 4); + pm->initrd_addr = MAX(pm->initrd_addr, INITRD_MIN_ADDR); + sz = load_image_targphys(machine->initrd_filename, pm->initrd_addr, + machine->ram_size - pm->initrd_addr); + if (sz <= 0) { + error_report("Could not load initrd '%s'", + machine->initrd_filename); + exit(1); + } + pm->initrd_size = sz; + } + if (!pm->vof && machine->kernel_cmdline && machine->kernel_cmdline[0]) { warn_report("Option -append may be ineffective with -bios."); } @@ -335,6 +354,11 @@ static void pegasos2_machine_reset(MachineState *machine, ShutdownCause reason) error_report("Memory for kernel is in use"); exit(1); } + if (pm->initrd_size && + vof_claim(pm->vof, pm->initrd_addr, pm->initrd_size, 0) == -1) { + error_report("Memory for initrd is in use"); + exit(1); + } fdt = build_fdt(machine, &sz); /* FIXME: VOF assumes entry is same as load address */ d[0] = cpu_to_be64(pm->kernel_entry); @@ -966,6 +990,12 @@ static void *build_fdt(MachineState *machine, int *fdt_size) qemu_fdt_setprop_string(fdt, "/memory@0", "name", "memory"); qemu_fdt_add_subnode(fdt, "/chosen"); + if (pm->initrd_addr && pm->initrd_size) { + qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", + pm->initrd_addr + pm->initrd_size); + qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", + pm->initrd_addr); + } qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", machine->kernel_cmdline ?: ""); qemu_fdt_setprop_string(fdt, "/chosen", "name", "chosen"); diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index fc083173f3..eb54f93986 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -887,6 +887,18 @@ static void pnv_init(MachineState *machine) pnv->num_chips = machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads); + + if (machine->smp.threads > 8) { + error_report("Cannot support more than 8 threads/core " + "on a powernv machine"); + exit(1); + } + if (!is_power_of_2(machine->smp.threads)) { + error_report("Cannot support %d threads/core on a powernv" + "machine because it must be a power of 2", + machine->smp.threads); + exit(1); + } /* * TODO: should we decide on how many chips we can create based * on #cores and Venice vs. Murano vs. Naples chip type etc..., @@ -1429,14 +1441,15 @@ static void pnv_chip_power9_instance_init(Object *obj) } static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq, - PnvCore *pnv_core) + PnvCore *pnv_core, + const char *type) { char eq_name[32]; int core_id = CPU_CORE(pnv_core)->core_id; snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); object_initialize_child_with_props(OBJECT(chip), eq_name, eq, - sizeof(*eq), TYPE_PNV_QUAD, + sizeof(*eq), type, &error_fatal, NULL); object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal); @@ -1454,7 +1467,8 @@ static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) for (i = 0; i < chip9->nr_quads; i++) { PnvQuad *eq = &chip9->quads[i]; - pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]); + pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4], + PNV_QUAD_TYPE_NAME("power9")); pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id), &eq->xscom_regs); @@ -1666,10 +1680,14 @@ static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp) for (i = 0; i < chip10->nr_quads; i++) { PnvQuad *eq = &chip10->quads[i]; - pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]); + pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4], + PNV_QUAD_TYPE_NAME("power10")); pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id), &eq->xscom_regs); + + pnv_xscom_add_subregion(chip, PNV10_XSCOM_QME_BASE(eq->quad_id), + &eq->xscom_qme_regs); } } diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 0bc3ad41c8..9b39d527de 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -85,8 +85,8 @@ static uint64_t pnv_core_power8_xscom_read(void *opaque, hwaddr addr, val = 0x24f000000000000ull; break; default: - qemu_log_mask(LOG_UNIMP, "Warning: reading reg=0x%" HWADDR_PRIx "\n", - addr); + qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, + offset); } return val; @@ -95,8 +95,10 @@ static uint64_t pnv_core_power8_xscom_read(void *opaque, hwaddr addr, static void pnv_core_power8_xscom_write(void *opaque, hwaddr addr, uint64_t val, unsigned int width) { - qemu_log_mask(LOG_UNIMP, "Warning: writing to reg=0x%" HWADDR_PRIx "\n", - addr); + uint32_t offset = addr >> 3; + + qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, + offset); } static const MemoryRegionOps pnv_core_power8_xscom_ops = { @@ -116,6 +118,8 @@ static const MemoryRegionOps pnv_core_power8_xscom_ops = { #define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP 0xf010d #define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR 0xf010a +#define PNV9_XSCOM_EC_CORE_THREAD_STATE 0x10ab3 + static uint64_t pnv_core_power9_xscom_read(void *opaque, hwaddr addr, unsigned int width) { @@ -134,9 +138,12 @@ static uint64_t pnv_core_power9_xscom_read(void *opaque, hwaddr addr, case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR: val = 0x0; break; + case PNV9_XSCOM_EC_CORE_THREAD_STATE: + val = 0; + break; default: - qemu_log_mask(LOG_UNIMP, "Warning: reading reg=0x%" HWADDR_PRIx "\n", - addr); + qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, + offset); } return val; @@ -152,8 +159,8 @@ static void pnv_core_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val, case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR: break; default: - qemu_log_mask(LOG_UNIMP, "Warning: writing to reg=0x%" HWADDR_PRIx "\n", - addr); + qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, + offset); } } @@ -167,12 +174,59 @@ static const MemoryRegionOps pnv_core_power9_xscom_ops = { .endianness = DEVICE_BIG_ENDIAN, }; -static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp) +/* + * POWER10 core controls + */ + +#define PNV10_XSCOM_EC_CORE_THREAD_STATE 0x412 + +static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr, + unsigned int width) +{ + uint32_t offset = addr >> 3; + uint64_t val = 0; + + switch (offset) { + case PNV10_XSCOM_EC_CORE_THREAD_STATE: + val = 0; + break; + default: + qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, + offset); + } + + return val; +} + +static void pnv_core_power10_xscom_write(void *opaque, hwaddr addr, + uint64_t val, unsigned int width) +{ + uint32_t offset = addr >> 3; + + switch (offset) { + default: + qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, + offset); + } +} + +static const MemoryRegionOps pnv_core_power10_xscom_ops = { + .read = pnv_core_power10_xscom_read, + .write = pnv_core_power10_xscom_write, + .valid.min_access_size = 8, + .valid.max_access_size = 8, + .impl.min_access_size = 8, + .impl.max_access_size = 8, + .endianness = DEVICE_BIG_ENDIAN, +}; + +static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp, + int thread_index) { CPUPPCState *env = &cpu->env; int core_pir; - int thread_index = 0; /* TODO: TCG supports only one thread */ ppc_spr_t *pir = &env->spr_cb[SPR_PIR]; + ppc_spr_t *tir = &env->spr_cb[SPR_TIR]; Error *local_err = NULL; PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip); @@ -188,11 +242,7 @@ static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp) core_pir = object_property_get_uint(OBJECT(pc), "pir", &error_abort); - /* - * The PIR of a thread is the core PIR + the thread index. We will - * need to find a way to get the thread index when TCG supports - * more than 1. We could use the object name ? - */ + tir->default_value = thread_index; pir->default_value = core_pir + thread_index; /* Set time-base frequency to 512 MHz */ @@ -241,16 +291,15 @@ static void pnv_core_realize(DeviceState *dev, Error **errp) } for (j = 0; j < cc->nr_threads; j++) { - pnv_core_cpu_realize(pc, pc->threads[j], &local_err); + pnv_core_cpu_realize(pc, pc->threads[j], &local_err, j); if (local_err) { goto err; } } snprintf(name, sizeof(name), "xscom-core.%d", cc->core_id); - /* TODO: check PNV_XSCOM_EX_SIZE for p10 */ pnv_xscom_region_init(&pc->xscom_regs, OBJECT(dev), pcc->xscom_ops, - pc, name, PNV_XSCOM_EX_SIZE); + pc, name, pcc->xscom_size); qemu_register_reset(pnv_core_reset, pc); return; @@ -302,6 +351,7 @@ static void pnv_core_power8_class_init(ObjectClass *oc, void *data) PnvCoreClass *pcc = PNV_CORE_CLASS(oc); pcc->xscom_ops = &pnv_core_power8_xscom_ops; + pcc->xscom_size = PNV_XSCOM_EX_SIZE; } static void pnv_core_power9_class_init(ObjectClass *oc, void *data) @@ -309,14 +359,15 @@ static void pnv_core_power9_class_init(ObjectClass *oc, void *data) PnvCoreClass *pcc = PNV_CORE_CLASS(oc); pcc->xscom_ops = &pnv_core_power9_xscom_ops; + pcc->xscom_size = PNV_XSCOM_EX_SIZE; } static void pnv_core_power10_class_init(ObjectClass *oc, void *data) { PnvCoreClass *pcc = PNV_CORE_CLASS(oc); - /* TODO: Use the P9 XSCOMs for now on P10 */ - pcc->xscom_ops = &pnv_core_power9_xscom_ops; + pcc->xscom_ops = &pnv_core_power10_xscom_ops; + pcc->xscom_size = PNV10_XSCOM_EC_SIZE; } static void pnv_core_class_init(ObjectClass *oc, void *data) @@ -360,8 +411,8 @@ DEFINE_TYPES(pnv_core_infos) #define P9X_EX_NCU_SPEC_BAR 0x11010 -static uint64_t pnv_quad_xscom_read(void *opaque, hwaddr addr, - unsigned int width) +static uint64_t pnv_quad_power9_xscom_read(void *opaque, hwaddr addr, + unsigned int width) { uint32_t offset = addr >> 3; uint64_t val = -1; @@ -372,15 +423,15 @@ static uint64_t pnv_quad_xscom_read(void *opaque, hwaddr addr, val = 0; break; default: - qemu_log_mask(LOG_UNIMP, "%s: writing @0x%08x\n", __func__, + qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, offset); } return val; } -static void pnv_quad_xscom_write(void *opaque, hwaddr addr, uint64_t val, - unsigned int width) +static void pnv_quad_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val, + unsigned int width) { uint32_t offset = addr >> 3; @@ -389,14 +440,14 @@ static void pnv_quad_xscom_write(void *opaque, hwaddr addr, uint64_t val, case P9X_EX_NCU_SPEC_BAR + 0x400: /* Second EX */ break; default: - qemu_log_mask(LOG_UNIMP, "%s: writing @0x%08x\n", __func__, + qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, offset); } } -static const MemoryRegionOps pnv_quad_xscom_ops = { - .read = pnv_quad_xscom_read, - .write = pnv_quad_xscom_write, +static const MemoryRegionOps pnv_quad_power9_xscom_ops = { + .read = pnv_quad_power9_xscom_read, + .write = pnv_quad_power9_xscom_write, .valid.min_access_size = 8, .valid.max_access_size = 8, .impl.min_access_size = 8, @@ -404,14 +455,124 @@ static const MemoryRegionOps pnv_quad_xscom_ops = { .endianness = DEVICE_BIG_ENDIAN, }; -static void pnv_quad_realize(DeviceState *dev, Error **errp) +/* + * POWER10 Quads + */ + +static uint64_t pnv_quad_power10_xscom_read(void *opaque, hwaddr addr, + unsigned int width) +{ + uint32_t offset = addr >> 3; + uint64_t val = -1; + + switch (offset) { + default: + qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, + offset); + } + + return val; +} + +static void pnv_quad_power10_xscom_write(void *opaque, hwaddr addr, + uint64_t val, unsigned int width) +{ + uint32_t offset = addr >> 3; + + switch (offset) { + default: + qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, + offset); + } +} + +static const MemoryRegionOps pnv_quad_power10_xscom_ops = { + .read = pnv_quad_power10_xscom_read, + .write = pnv_quad_power10_xscom_write, + .valid.min_access_size = 8, + .valid.max_access_size = 8, + .impl.min_access_size = 8, + .impl.max_access_size = 8, + .endianness = DEVICE_BIG_ENDIAN, +}; + +#define P10_QME_SPWU_HYP 0x83c +#define P10_QME_SSH_HYP 0x82c + +static uint64_t pnv_qme_power10_xscom_read(void *opaque, hwaddr addr, + unsigned int width) +{ + uint32_t offset = addr >> 3; + uint64_t val = -1; + + /* + * Forth nibble selects the core within a quad, mask it to process read + * for any core. + */ + switch (offset & ~0xf000) { + case P10_QME_SPWU_HYP: + case P10_QME_SSH_HYP: + return 0; + default: + qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, + offset); + } + + return val; +} + +static void pnv_qme_power10_xscom_write(void *opaque, hwaddr addr, + uint64_t val, unsigned int width) +{ + uint32_t offset = addr >> 3; + + switch (offset) { + default: + qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, + offset); + } +} + +static const MemoryRegionOps pnv_qme_power10_xscom_ops = { + .read = pnv_qme_power10_xscom_read, + .write = pnv_qme_power10_xscom_write, + .valid.min_access_size = 8, + .valid.max_access_size = 8, + .impl.min_access_size = 8, + .impl.max_access_size = 8, + .endianness = DEVICE_BIG_ENDIAN, +}; + +static void pnv_quad_power9_realize(DeviceState *dev, Error **errp) { PnvQuad *eq = PNV_QUAD(dev); + PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq); char name[32]; snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id); - pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev), &pnv_quad_xscom_ops, - eq, name, PNV9_XSCOM_EQ_SIZE); + pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev), + pqc->xscom_ops, + eq, name, + pqc->xscom_size); +} + +static void pnv_quad_power10_realize(DeviceState *dev, Error **errp) +{ + PnvQuad *eq = PNV_QUAD(dev); + PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq); + char name[32]; + + snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id); + pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev), + pqc->xscom_ops, + eq, name, + pqc->xscom_size); + + snprintf(name, sizeof(name), "xscom-qme.%d", eq->quad_id); + pnv_xscom_region_init(&eq->xscom_qme_regs, OBJECT(dev), + pqc->xscom_qme_ops, + eq, name, + pqc->xscom_qme_size); } static Property pnv_quad_properties[] = { @@ -419,25 +580,58 @@ static Property pnv_quad_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +static void pnv_quad_power9_class_init(ObjectClass *oc, void *data) +{ + PnvQuadClass *pqc = PNV_QUAD_CLASS(oc); + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = pnv_quad_power9_realize; + + pqc->xscom_ops = &pnv_quad_power9_xscom_ops; + pqc->xscom_size = PNV9_XSCOM_EQ_SIZE; +} + +static void pnv_quad_power10_class_init(ObjectClass *oc, void *data) +{ + PnvQuadClass *pqc = PNV_QUAD_CLASS(oc); + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = pnv_quad_power10_realize; + + pqc->xscom_ops = &pnv_quad_power10_xscom_ops; + pqc->xscom_size = PNV10_XSCOM_EQ_SIZE; + + pqc->xscom_qme_ops = &pnv_qme_power10_xscom_ops; + pqc->xscom_qme_size = PNV10_XSCOM_QME_SIZE; +} + static void pnv_quad_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); - dc->realize = pnv_quad_realize; device_class_set_props(dc, pnv_quad_properties); dc->user_creatable = false; } -static const TypeInfo pnv_quad_info = { - .name = TYPE_PNV_QUAD, - .parent = TYPE_DEVICE, - .instance_size = sizeof(PnvQuad), - .class_init = pnv_quad_class_init, +static const TypeInfo pnv_quad_infos[] = { + { + .name = TYPE_PNV_QUAD, + .parent = TYPE_DEVICE, + .instance_size = sizeof(PnvQuad), + .class_size = sizeof(PnvQuadClass), + .class_init = pnv_quad_class_init, + .abstract = true, + }, + { + .parent = TYPE_PNV_QUAD, + .name = PNV_QUAD_TYPE_NAME("power9"), + .class_init = pnv_quad_power9_class_init, + }, + { + .parent = TYPE_PNV_QUAD, + .name = PNV_QUAD_TYPE_NAME("power10"), + .class_init = pnv_quad_power10_class_init, + }, }; -static void pnv_core_register_types(void) -{ - type_register_static(&pnv_quad_info); -} - -type_init(pnv_core_register_types) +DEFINE_TYPES(pnv_quad_infos); diff --git a/hw/ppc/pnv_psi.c b/hw/ppc/pnv_psi.c index 8aa09ab26b..daaa2f0575 100644 --- a/hw/ppc/pnv_psi.c +++ b/hw/ppc/pnv_psi.c @@ -121,8 +121,12 @@ #define PSIHB9_BAR_MASK 0x00fffffffff00000ull #define PSIHB9_FSPBAR_MASK 0x00ffffff00000000ull +/* mmio address to xscom address */ #define PSIHB_REG(addr) (((addr) >> 3) + PSIHB_XSCOM_BAR) +/* xscom address to mmio address */ +#define PSIHB_MMIO(reg) ((reg - PSIHB_XSCOM_BAR) << 3) + static void pnv_psi_set_bar(PnvPsi *psi, uint64_t bar) { PnvPsiClass *ppc = PNV_PSI_GET_CLASS(psi); @@ -769,24 +773,31 @@ static const MemoryRegionOps pnv_psi_p9_mmio_ops = { static uint64_t pnv_psi_p9_xscom_read(void *opaque, hwaddr addr, unsigned size) { - /* No read are expected */ - qemu_log_mask(LOG_GUEST_ERROR, "PSI: xscom read at 0x%" PRIx64 "\n", addr); - return -1; + uint32_t reg = addr >> 3; + uint64_t val = -1; + + if (reg < PSIHB_XSCOM_BAR) { + /* FIR, not modeled */ + qemu_log_mask(LOG_UNIMP, "PSI: xscom read at 0x%08x\n", reg); + } else { + val = pnv_psi_p9_mmio_read(opaque, PSIHB_MMIO(reg), size); + } + return val; } static void pnv_psi_p9_xscom_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { PnvPsi *psi = PNV_PSI(opaque); + uint32_t reg = addr >> 3; - /* XSCOM is only used to set the PSIHB MMIO region */ - switch (addr >> 3) { - case PSIHB_XSCOM_BAR: + if (reg < PSIHB_XSCOM_BAR) { + /* FIR, not modeled */ + qemu_log_mask(LOG_UNIMP, "PSI: xscom write at 0x%08x\n", reg); + } else if (reg == PSIHB_XSCOM_BAR) { pnv_psi_set_bar(psi, val); - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, "PSI: xscom write at 0x%" PRIx64 "\n", - addr); + } else { + pnv_psi_p9_mmio_write(opaque, PSIHB_MMIO(reg), val, size); } } @@ -852,6 +863,8 @@ static void pnv_psi_power9_realize(DeviceState *dev, Error **errp) object_property_set_int(OBJECT(xsrc), "nr-irqs", PSIHB9_NUM_IRQS, &error_fatal); object_property_set_link(OBJECT(xsrc), "xive", OBJECT(psi), &error_abort); + object_property_set_int(OBJECT(xsrc), "reset-pq", XIVE_ESB_RESET, + &error_abort); if (!qdev_realize(DEVICE(xsrc), NULL, errp)) { return; } diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index 82e4408c5c..0e0a3d93c3 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -535,23 +535,24 @@ static inline void cpu_ppc_store_tb(ppc_tb_t *tb_env, uint64_t vmclk, void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value) { ppc_tb_t *tb_env = env->tb_env; + int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); uint64_t tb; - tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset); + tb = cpu_ppc_get_tb(tb_env, clock, tb_env->tb_offset); tb &= 0xFFFFFFFF00000000ULL; - cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - &tb_env->tb_offset, tb | (uint64_t)value); + cpu_ppc_store_tb(tb_env, clock, &tb_env->tb_offset, tb | (uint64_t)value); } static inline void _cpu_ppc_store_tbu(CPUPPCState *env, uint32_t value) { ppc_tb_t *tb_env = env->tb_env; + int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); uint64_t tb; - tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->tb_offset); + tb = cpu_ppc_get_tb(tb_env, clock, tb_env->tb_offset); tb &= 0x00000000FFFFFFFFULL; - cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - &tb_env->tb_offset, ((uint64_t)value << 32) | tb); + cpu_ppc_store_tb(tb_env, clock, &tb_env->tb_offset, + ((uint64_t)value << 32) | tb); } void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value) @@ -584,23 +585,24 @@ uint32_t cpu_ppc_load_atbu (CPUPPCState *env) void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value) { ppc_tb_t *tb_env = env->tb_env; + int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); uint64_t tb; - tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset); + tb = cpu_ppc_get_tb(tb_env, clock, tb_env->atb_offset); tb &= 0xFFFFFFFF00000000ULL; - cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - &tb_env->atb_offset, tb | (uint64_t)value); + cpu_ppc_store_tb(tb_env, clock, &tb_env->atb_offset, tb | (uint64_t)value); } void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value) { ppc_tb_t *tb_env = env->tb_env; + int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); uint64_t tb; - tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tb_env->atb_offset); + tb = cpu_ppc_get_tb(tb_env, clock, tb_env->atb_offset); tb &= 0x00000000FFFFFFFFULL; - cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - &tb_env->atb_offset, ((uint64_t)value << 32) | tb); + cpu_ppc_store_tb(tb_env, clock, &tb_env->atb_offset, + ((uint64_t)value << 32) | tb); } uint64_t cpu_ppc_load_vtb(CPUPPCState *env) @@ -622,14 +624,13 @@ void cpu_ppc_store_vtb(CPUPPCState *env, uint64_t value) void cpu_ppc_store_tbu40(CPUPPCState *env, uint64_t value) { ppc_tb_t *tb_env = env->tb_env; + int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); uint64_t tb; - tb = cpu_ppc_get_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - tb_env->tb_offset); + tb = cpu_ppc_get_tb(tb_env, clock, tb_env->tb_offset); tb &= 0xFFFFFFUL; tb |= (value & ~0xFFFFFFUL); - cpu_ppc_store_tb(tb_env, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - &tb_env->tb_offset, tb); + cpu_ppc_store_tb(tb_env, clock, &tb_env->tb_offset, tb); } static void cpu_ppc_tb_stop (CPUPPCState *env) @@ -788,8 +789,8 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp, QEMUTimer *timer, void (*raise_excp)(void *), void (*lower_excp)(PowerPCCPU *), - target_ulong decr, target_ulong value, - int nr_bits) + uint32_t flags, target_ulong decr, + target_ulong value, int nr_bits) { CPUPPCState *env = &cpu->env; ppc_tb_t *tb_env = env->tb_env; @@ -819,15 +820,15 @@ static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp, * On MSB edge based DEC implementations the MSB going from 0 -> 1 triggers * an edge interrupt, so raise it here too. */ - if (((tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL) && signed_value < 0) || - ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED) && signed_value < 0 + if (((flags & PPC_DECR_UNDERFLOW_LEVEL) && signed_value < 0) || + ((flags & PPC_DECR_UNDERFLOW_TRIGGERED) && signed_value < 0 && signed_decr >= 0)) { (*raise_excp)(cpu); return; } /* On MSB level based systems a 0 for the MSB stops interrupt delivery */ - if (signed_value >= 0 && (tb_env->flags & PPC_DECR_UNDERFLOW_LEVEL)) { + if (signed_value >= 0 && (flags & PPC_DECR_UNDERFLOW_LEVEL)) { (*lower_excp)(cpu); } @@ -846,8 +847,8 @@ static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, target_ulong decr, ppc_tb_t *tb_env = cpu->env.tb_env; __cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer, - tb_env->decr_timer->cb, &cpu_ppc_decr_lower, decr, - value, nr_bits); + tb_env->decr_timer->cb, &cpu_ppc_decr_lower, + tb_env->flags, decr, value, nr_bits); } void cpu_ppc_store_decr(CPUPPCState *env, target_ulong value) @@ -876,8 +877,10 @@ static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, target_ulong hdecr, ppc_tb_t *tb_env = cpu->env.tb_env; if (tb_env->hdecr_timer != NULL) { + /* HDECR (Book3S 64bit) is edge-based, not level like DECR */ __cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer, tb_env->hdecr_timer->cb, &cpu_ppc_hdecr_lower, + PPC_DECR_UNDERFLOW_TRIGGERED, hdecr, value, nr_bits); } } diff --git a/hw/ppc/ppc440.h b/hw/ppc/ppc440.h index 7c24db8504..909373fb38 100644 --- a/hw/ppc/ppc440.h +++ b/hw/ppc/ppc440.h @@ -18,6 +18,5 @@ void ppc4xx_cpr_init(CPUPPCState *env); void ppc4xx_sdr_init(CPUPPCState *env); void ppc4xx_ahb_init(CPUPPCState *env); void ppc4xx_dma_init(CPUPPCState *env, int dcr_base); -void ppc460ex_pcie_init(CPUPPCState *env); #endif /* PPC440_H */ diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c index f061b8cf3b..45f409c838 100644 --- a/hw/ppc/ppc440_bamboo.c +++ b/hw/ppc/ppc440_bamboo.c @@ -205,8 +205,7 @@ static void bamboo_init(MachineState *machine) ppc4xx_sdram_ddr_enable(PPC4xx_SDRAM_DDR(dev)); /* PCI */ - dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST_BRIDGE, - PPC440EP_PCI_CONFIG, + dev = sysbus_create_varargs(TYPE_PPC4xx_PCI_HOST, PPC440EP_PCI_CONFIG, qdev_get_gpio_in(uicdev, pci_irq_nrs[0]), qdev_get_gpio_in(uicdev, pci_irq_nrs[1]), qdev_get_gpio_in(uicdev, pci_irq_nrs[2]), diff --git a/hw/ppc/ppc440_pcix.c b/hw/ppc/ppc440_pcix.c index f10f93c533..672090de94 100644 --- a/hw/ppc/ppc440_pcix.c +++ b/hw/ppc/ppc440_pcix.c @@ -23,6 +23,7 @@ #include "qemu/error-report.h" #include "qemu/log.h" #include "qemu/module.h" +#include "qemu/units.h" #include "hw/irq.h" #include "hw/ppc/ppc.h" #include "hw/ppc/ppc4xx.h" @@ -44,8 +45,7 @@ struct PLBInMap { MemoryRegion mr; }; -#define TYPE_PPC440_PCIX_HOST_BRIDGE "ppc440-pcix-host" -OBJECT_DECLARE_SIMPLE_TYPE(PPC440PCIXState, PPC440_PCIX_HOST_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(PPC440PCIXState, PPC440_PCIX_HOST) #define PPC440_PCIX_NR_POMS 3 #define PPC440_PCIX_NR_PIMS 3 @@ -64,6 +64,7 @@ struct PPC440PCIXState { MemoryRegion container; MemoryRegion iomem; MemoryRegion busmem; + MemoryRegion regs; }; #define PPC440_REG_BASE 0x80000 @@ -397,7 +398,7 @@ static const MemoryRegionOps pci_reg_ops = { static void ppc440_pcix_reset(DeviceState *dev) { - struct PPC440PCIXState *s = PPC440_PCIX_HOST_BRIDGE(dev); + struct PPC440PCIXState *s = PPC440_PCIX_HOST(dev); int i; for (i = 0; i < PPC440_PCIX_NR_POMS; i++) { @@ -487,15 +488,17 @@ static void ppc440_pcix_realize(DeviceState *dev, Error **errp) PCIHostState *h; h = PCI_HOST_BRIDGE(dev); - s = PPC440_PCIX_HOST_BRIDGE(dev); + s = PPC440_PCIX_HOST(dev); sysbus_init_irq(sbd, &s->irq); - memory_region_init(&s->busmem, OBJECT(dev), "pci bus memory", UINT64_MAX); + memory_region_init(&s->busmem, OBJECT(dev), "pci-mem", UINT64_MAX); + memory_region_init(&s->iomem, OBJECT(dev), "pci-io", 64 * KiB); h->bus = pci_register_root_bus(dev, NULL, ppc440_pcix_set_irq, - ppc440_pcix_map_irq, &s->irq, &s->busmem, - get_system_io(), PCI_DEVFN(0, 0), 1, TYPE_PCI_BUS); + ppc440_pcix_map_irq, &s->irq, &s->busmem, &s->iomem, + PCI_DEVFN(0, 0), 1, TYPE_PCI_BUS); - s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), "ppc4xx-host-bridge"); + s->dev = pci_create_simple(h->bus, PCI_DEVFN(0, 0), + TYPE_PPC4xx_HOST_BRIDGE); memory_region_init(&s->bm, OBJECT(s), "bm-ppc440-pcix", UINT64_MAX); memory_region_add_subregion(&s->bm, 0x0, &s->busmem); @@ -507,12 +510,13 @@ static void ppc440_pcix_realize(DeviceState *dev, Error **errp) h, "pci-conf-idx", 4); memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops, h, "pci-conf-data", 4); - memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s, - "pci.reg", PPC440_REG_SIZE); + memory_region_init_io(&s->regs, OBJECT(s), &pci_reg_ops, s, "pci-reg", + PPC440_REG_SIZE); memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem); memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem); - memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->iomem); + memory_region_add_subregion(&s->container, PPC440_REG_BASE, &s->regs); sysbus_init_mmio(sbd, &s->container); + sysbus_init_mmio(sbd, &s->iomem); } static void ppc440_pcix_class_init(ObjectClass *klass, void *data) @@ -524,7 +528,7 @@ static void ppc440_pcix_class_init(ObjectClass *klass, void *data) } static const TypeInfo ppc440_pcix_info = { - .name = TYPE_PPC440_PCIX_HOST_BRIDGE, + .name = TYPE_PPC440_PCIX_HOST, .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(PPC440PCIXState), .class_init = ppc440_pcix_class_init, diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index 651263926e..4181c843a8 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -17,6 +17,7 @@ #include "hw/qdev-properties.h" #include "hw/pci/pci.h" #include "sysemu/reset.h" +#include "cpu.h" #include "ppc440.h" /*****************************************************************************/ @@ -769,15 +770,17 @@ void ppc4xx_dma_init(CPUPPCState *env, int dcr_base) */ #include "hw/pci/pcie_host.h" -#define TYPE_PPC460EX_PCIE_HOST "ppc460ex-pcie-host" OBJECT_DECLARE_SIMPLE_TYPE(PPC460EXPCIEState, PPC460EX_PCIE_HOST) struct PPC460EXPCIEState { - PCIExpressHost host; + PCIExpressHost parent_obj; + MemoryRegion busmem; MemoryRegion iomem; qemu_irq irq[4]; + int32_t num; int32_t dcrn_base; + PowerPCCPU *cpu; uint64_t cfg_base; uint32_t cfg_mask; @@ -795,9 +798,6 @@ struct PPC460EXPCIEState { uint32_t cfg; }; -#define DCRN_PCIE0_BASE 0x100 -#define DCRN_PCIE1_BASE 0x120 - enum { PEGPL_CFGBAH = 0x0, PEGPL_CFGBAL, @@ -826,78 +826,78 @@ enum { static uint32_t dcr_read_pcie(void *opaque, int dcrn) { - PPC460EXPCIEState *state = opaque; + PPC460EXPCIEState *s = opaque; uint32_t ret = 0; - switch (dcrn - state->dcrn_base) { + switch (dcrn - s->dcrn_base) { case PEGPL_CFGBAH: - ret = state->cfg_base >> 32; + ret = s->cfg_base >> 32; break; case PEGPL_CFGBAL: - ret = state->cfg_base; + ret = s->cfg_base; break; case PEGPL_CFGMSK: - ret = state->cfg_mask; + ret = s->cfg_mask; break; case PEGPL_MSGBAH: - ret = state->msg_base >> 32; + ret = s->msg_base >> 32; break; case PEGPL_MSGBAL: - ret = state->msg_base; + ret = s->msg_base; break; case PEGPL_MSGMSK: - ret = state->msg_mask; + ret = s->msg_mask; break; case PEGPL_OMR1BAH: - ret = state->omr1_base >> 32; + ret = s->omr1_base >> 32; break; case PEGPL_OMR1BAL: - ret = state->omr1_base; + ret = s->omr1_base; break; case PEGPL_OMR1MSKH: - ret = state->omr1_mask >> 32; + ret = s->omr1_mask >> 32; break; case PEGPL_OMR1MSKL: - ret = state->omr1_mask; + ret = s->omr1_mask; break; case PEGPL_OMR2BAH: - ret = state->omr2_base >> 32; + ret = s->omr2_base >> 32; break; case PEGPL_OMR2BAL: - ret = state->omr2_base; + ret = s->omr2_base; break; case PEGPL_OMR2MSKH: - ret = state->omr2_mask >> 32; + ret = s->omr2_mask >> 32; break; case PEGPL_OMR2MSKL: - ret = state->omr3_mask; + ret = s->omr3_mask; break; case PEGPL_OMR3BAH: - ret = state->omr3_base >> 32; + ret = s->omr3_base >> 32; break; case PEGPL_OMR3BAL: - ret = state->omr3_base; + ret = s->omr3_base; break; case PEGPL_OMR3MSKH: - ret = state->omr3_mask >> 32; + ret = s->omr3_mask >> 32; break; case PEGPL_OMR3MSKL: - ret = state->omr3_mask; + ret = s->omr3_mask; break; case PEGPL_REGBAH: - ret = state->reg_base >> 32; + ret = s->reg_base >> 32; break; case PEGPL_REGBAL: - ret = state->reg_base; + ret = s->reg_base; break; case PEGPL_REGMSK: - ret = state->reg_mask; + ret = s->reg_mask; break; case PEGPL_SPECIAL: - ret = state->special; + ret = s->special; break; case PEGPL_CFG: - ret = state->cfg; + ret = s->cfg; break; } @@ -1000,37 +1000,72 @@ static void ppc460ex_set_irq(void *opaque, int irq_num, int level) qemu_set_irq(s->irq[irq_num], level); } +#define PPC440_PCIE_DCR(s, dcrn) \ + ppc_dcr_register(&(s)->cpu->env, (s)->dcrn_base + (dcrn), (s), \ + &dcr_read_pcie, &dcr_write_pcie) + + +static void ppc460ex_pcie_register_dcrs(PPC460EXPCIEState *s) +{ + PPC440_PCIE_DCR(s, PEGPL_CFGBAH); + PPC440_PCIE_DCR(s, PEGPL_CFGBAL); + PPC440_PCIE_DCR(s, PEGPL_CFGMSK); + PPC440_PCIE_DCR(s, PEGPL_MSGBAH); + PPC440_PCIE_DCR(s, PEGPL_MSGBAL); + PPC440_PCIE_DCR(s, PEGPL_MSGMSK); + PPC440_PCIE_DCR(s, PEGPL_OMR1BAH); + PPC440_PCIE_DCR(s, PEGPL_OMR1BAL); + PPC440_PCIE_DCR(s, PEGPL_OMR1MSKH); + PPC440_PCIE_DCR(s, PEGPL_OMR1MSKL); + PPC440_PCIE_DCR(s, PEGPL_OMR2BAH); + PPC440_PCIE_DCR(s, PEGPL_OMR2BAL); + PPC440_PCIE_DCR(s, PEGPL_OMR2MSKH); + PPC440_PCIE_DCR(s, PEGPL_OMR2MSKL); + PPC440_PCIE_DCR(s, PEGPL_OMR3BAH); + PPC440_PCIE_DCR(s, PEGPL_OMR3BAL); + PPC440_PCIE_DCR(s, PEGPL_OMR3MSKH); + PPC440_PCIE_DCR(s, PEGPL_OMR3MSKL); + PPC440_PCIE_DCR(s, PEGPL_REGBAH); + PPC440_PCIE_DCR(s, PEGPL_REGBAL); + PPC440_PCIE_DCR(s, PEGPL_REGMSK); + PPC440_PCIE_DCR(s, PEGPL_SPECIAL); + PPC440_PCIE_DCR(s, PEGPL_CFG); +} + static void ppc460ex_pcie_realize(DeviceState *dev, Error **errp) { PPC460EXPCIEState *s = PPC460EX_PCIE_HOST(dev); PCIHostState *pci = PCI_HOST_BRIDGE(dev); - int i, id; - char buf[16]; + int i; + char buf[20]; - switch (s->dcrn_base) { - case DCRN_PCIE0_BASE: - id = 0; - break; - case DCRN_PCIE1_BASE: - id = 1; - break; - default: - error_setg(errp, "invalid PCIe DCRN base"); + if (!s->cpu) { + error_setg(errp, "cpu link property must be set"); + return; + } + if (s->num < 0 || s->dcrn_base < 0) { + error_setg(errp, "busnum and dcrn-base properties must be set"); return; } - snprintf(buf, sizeof(buf), "pcie%d-io", id); - memory_region_init(&s->iomem, OBJECT(s), buf, UINT64_MAX); + snprintf(buf, sizeof(buf), "pcie%d-mem", s->num); + memory_region_init(&s->busmem, OBJECT(s), buf, UINT64_MAX); + snprintf(buf, sizeof(buf), "pcie%d-io", s->num); + memory_region_init(&s->iomem, OBJECT(s), buf, 64 * KiB); for (i = 0; i < 4; i++) { sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]); } - snprintf(buf, sizeof(buf), "pcie.%d", id); + snprintf(buf, sizeof(buf), "pcie.%d", s->num); pci->bus = pci_register_root_bus(DEVICE(s), buf, ppc460ex_set_irq, - pci_swizzle_map_irq_fn, s, &s->iomem, - get_system_io(), 0, 4, TYPE_PCIE_BUS); + pci_swizzle_map_irq_fn, s, &s->busmem, + &s->iomem, 0, 4, TYPE_PCIE_BUS); + ppc460ex_pcie_register_dcrs(s); } static Property ppc460ex_pcie_props[] = { + DEFINE_PROP_INT32("busnum", PPC460EXPCIEState, num, -1), DEFINE_PROP_INT32("dcrn-base", PPC460EXPCIEState, dcrn_base, -1), + DEFINE_PROP_LINK("cpu", PPC460EXPCIEState, cpu, TYPE_POWERPC_CPU, + PowerPCCPU *), DEFINE_PROP_END_OF_LIST(), }; @@ -1057,68 +1092,3 @@ static void ppc460ex_pcie_register(void) } type_init(ppc460ex_pcie_register) - -static void ppc460ex_pcie_register_dcrs(PPC460EXPCIEState *s, CPUPPCState *env) -{ - ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGBAH, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGBAL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_CFGMSK, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_MSGBAH, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_MSGBAL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_MSGMSK, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1BAH, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1BAL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1MSKH, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR1MSKL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2BAH, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2BAL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2MSKH, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR2MSKL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3BAH, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3BAL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3MSKH, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_OMR3MSKL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_REGBAH, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_REGBAL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_REGMSK, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_SPECIAL, s, - &dcr_read_pcie, &dcr_write_pcie); - ppc_dcr_register(env, s->dcrn_base + PEGPL_CFG, s, - &dcr_read_pcie, &dcr_write_pcie); -} - -void ppc460ex_pcie_init(CPUPPCState *env) -{ - DeviceState *dev; - - dev = qdev_new(TYPE_PPC460EX_PCIE_HOST); - qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE0_BASE); - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), env); - - dev = qdev_new(TYPE_PPC460EX_PCIE_HOST); - qdev_prop_set_int32(dev, "dcrn-base", DCRN_PCIE1_BASE); - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - ppc460ex_pcie_register_dcrs(PPC460EX_PCIE_HOST(dev), env); -} diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c index 1d4a50fa7c..6652119008 100644 --- a/hw/ppc/ppc4xx_pci.c +++ b/hw/ppc/ppc4xx_pci.c @@ -46,7 +46,7 @@ struct PCITargetMap { uint32_t la; }; -OBJECT_DECLARE_SIMPLE_TYPE(PPC4xxPCIState, PPC4xx_PCI_HOST_BRIDGE) +OBJECT_DECLARE_SIMPLE_TYPE(PPC4xxPCIState, PPC4xx_PCI_HOST) #define PPC4xx_PCI_NR_PMMS 3 #define PPC4xx_PCI_NR_PTMS 2 @@ -321,7 +321,7 @@ static void ppc4xx_pcihost_realize(DeviceState *dev, Error **errp) int i; h = PCI_HOST_BRIDGE(dev); - s = PPC4xx_PCI_HOST_BRIDGE(dev); + s = PPC4xx_PCI_HOST(dev); for (i = 0; i < ARRAY_SIZE(s->irq); i++) { sysbus_init_irq(sbd, &s->irq[i]); @@ -333,7 +333,7 @@ static void ppc4xx_pcihost_realize(DeviceState *dev, Error **errp) TYPE_PCI_BUS); h->bus = b; - pci_create_simple(b, 0, "ppc4xx-host-bridge"); + pci_create_simple(b, 0, TYPE_PPC4xx_HOST_BRIDGE); /* XXX split into 2 memory regions, one for config space, one for regs */ memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE); @@ -367,7 +367,7 @@ static void ppc4xx_host_bridge_class_init(ObjectClass *klass, void *data) } static const TypeInfo ppc4xx_host_bridge_info = { - .name = "ppc4xx-host-bridge", + .name = TYPE_PPC4xx_HOST_BRIDGE, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCIDevice), .class_init = ppc4xx_host_bridge_class_init, @@ -386,7 +386,7 @@ static void ppc4xx_pcihost_class_init(ObjectClass *klass, void *data) } static const TypeInfo ppc4xx_pcihost_info = { - .name = TYPE_PPC4xx_PCI_HOST_BRIDGE, + .name = TYPE_PPC4xx_PCI_HOST, .parent = TYPE_PCI_HOST_BRIDGE, .instance_size = sizeof(PPC4xxPCIState), .class_init = ppc4xx_pcihost_class_init, diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index cf065aae0e..1e615b8d35 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -45,6 +45,9 @@ /* dd bs=1 skip=$(($(stat -c '%s' updater/updater-460) - 0x80000)) \ if=updater/updater-460 of=u-boot-sam460-20100605.bin */ +#define PCIE0_DCRN_BASE 0x100 +#define PCIE1_DCRN_BASE 0x120 + /* from Sam460 U-Boot include/configs/Sam460ex.h */ #define FLASH_BASE 0xfff00000 #define FLASH_BASE_H 0x4 @@ -266,8 +269,6 @@ static void main_cpu_reset(void *opaque) static void sam460ex_init(MachineState *machine) { - MemoryRegion *address_space_mem = get_system_memory(); - MemoryRegion *isa = g_new(MemoryRegion, 1); MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1); DeviceState *uic[4]; int i; @@ -406,7 +407,8 @@ static void sam460ex_init(MachineState *machine) /* FIXME: remove this after fixing l2sram mapping in ppc440_uc.c? */ memory_region_init_ram(l2cache_ram, NULL, "ppc440.l2cache_ram", 256 * KiB, &error_abort); - memory_region_add_subregion(address_space_mem, 0x400000000LL, l2cache_ram); + memory_region_add_subregion(get_system_memory(), 0x400000000LL, + l2cache_ram); /* USB */ sysbus_create_simple(TYPE_PPC4xx_EHCI, 0x4bffd0400, @@ -421,17 +423,26 @@ static void sam460ex_init(MachineState *machine) usb_create_simple(usb_bus_find(-1), "usb-kbd"); usb_create_simple(usb_bus_find(-1), "usb-mouse"); + /* PCIe buses */ + dev = qdev_new(TYPE_PPC460EX_PCIE_HOST); + qdev_prop_set_int32(dev, "busnum", 0); + qdev_prop_set_int32(dev, "dcrn-base", PCIE0_DCRN_BASE); + object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + dev = qdev_new(TYPE_PPC460EX_PCIE_HOST); + qdev_prop_set_int32(dev, "busnum", 1); + qdev_prop_set_int32(dev, "dcrn-base", PCIE1_DCRN_BASE); + object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + /* PCI bus */ - ppc460ex_pcie_init(env); /* All PCI irqs are connected to the same UIC pin (cf. UBoot source) */ - dev = sysbus_create_simple("ppc440-pcix-host", 0xc0ec00000, + dev = sysbus_create_simple(TYPE_PPC440_PCIX_HOST, 0xc0ec00000, qdev_get_gpio_in(uic[1], 0)); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, 0xc08000000); pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci.0")); - memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(), - 0, 0x10000); - memory_region_add_subregion(get_system_memory(), 0xc08000000, isa); - /* PCI devices */ pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "sm501"); /* SoC has a single SATA port but we don't emulate that yet @@ -444,13 +455,13 @@ static void sam460ex_init(MachineState *machine) /* SoC has 4 UARTs * but board has only one wired and two are present in fdt */ if (serial_hd(0) != NULL) { - serial_mm_init(address_space_mem, 0x4ef600300, 0, + serial_mm_init(get_system_memory(), 0x4ef600300, 0, qdev_get_gpio_in(uic[1], 1), PPC_SERIAL_MM_BAUDBASE, serial_hd(0), DEVICE_BIG_ENDIAN); } if (serial_hd(1) != NULL) { - serial_mm_init(address_space_mem, 0x4ef600400, 0, + serial_mm_init(get_system_memory(), 0x4ef600400, 0, qdev_get_gpio_in(uic[0], 1), PPC_SERIAL_MM_BAUDBASE, serial_hd(1), DEVICE_BIG_ENDIAN); diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index a4e3c2fadd..b482d9754a 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -270,6 +270,8 @@ static bool spapr_realize_vcpu(PowerPCCPU *cpu, SpaprMachineState *spapr, env->spr_cb[SPR_PIR].default_value = cs->cpu_index; env->spr_cb[SPR_TIR].default_value = thread_index; + cpu_ppc_set_1lpar(cpu); + /* Set time-base frequency to 512 MHz. vhyp must be set first. */ cpu_ppc_tb_init(env, SPAPR_TIMEBASE_FREQ); diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index ed4c27487e..68ccd0bde1 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -1692,7 +1692,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) virt_set_aia); object_class_property_set_description(oc, "aia", "Set type of AIA interrupt " - "conttoller. Valid values are " + "controller. Valid values are " "none, aplic, and aplic-imsic."); object_class_property_add_str(oc, "aia-guests", diff --git a/hw/xtensa/virt.c b/hw/xtensa/virt.c index b87f842e74..a6cf646e99 100644 --- a/hw/xtensa/virt.c +++ b/hw/xtensa/virt.c @@ -103,13 +103,7 @@ static void create_pcie(MachineState *ms, CPUXtensaState *env, int irq_base, pci = PCI_HOST_BRIDGE(dev); if (pci->bus) { for (i = 0; i < nb_nics; i++) { - NICInfo *nd = &nd_table[i]; - - if (!nd->model) { - nd->model = g_strdup(mc->default_nic); - } - - pci_nic_init_nofail(nd, pci->bus, nd->model, NULL); + pci_nic_init_nofail(&nd_table[i], pci->bus, mc->default_nic, NULL); } } } diff --git a/include/hw/ppc/pnv_core.h b/include/hw/ppc/pnv_core.h index 3d75706e95..4db21229a6 100644 --- a/include/hw/ppc/pnv_core.h +++ b/include/hw/ppc/pnv_core.h @@ -46,6 +46,7 @@ struct PnvCoreClass { DeviceClass parent_class; const MemoryRegionOps *xscom_ops; + uint64_t xscom_size; }; #define PNV_CORE_TYPE_SUFFIX "-" TYPE_PNV_CORE @@ -60,13 +61,28 @@ static inline PnvCPUState *pnv_cpu_state(PowerPCCPU *cpu) return (PnvCPUState *)cpu->machine_data; } +struct PnvQuadClass { + DeviceClass parent_class; + + const MemoryRegionOps *xscom_ops; + uint64_t xscom_size; + + const MemoryRegionOps *xscom_qme_ops; + uint64_t xscom_qme_size; +}; + #define TYPE_PNV_QUAD "powernv-cpu-quad" -OBJECT_DECLARE_SIMPLE_TYPE(PnvQuad, PNV_QUAD) + +#define PNV_QUAD_TYPE_SUFFIX "-" TYPE_PNV_QUAD +#define PNV_QUAD_TYPE_NAME(cpu_model) cpu_model PNV_QUAD_TYPE_SUFFIX + +OBJECT_DECLARE_TYPE(PnvQuad, PnvQuadClass, PNV_QUAD) struct PnvQuad { DeviceState parent_obj; uint32_t quad_id; MemoryRegion xscom_regs; + MemoryRegion xscom_qme_regs; }; #endif /* PPC_PNV_CORE_H */ diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h index cbe848d27b..9bc6463547 100644 --- a/include/hw/ppc/pnv_xscom.h +++ b/include/hw/ppc/pnv_xscom.h @@ -127,13 +127,24 @@ struct PnvXScomInterfaceClass { #define PNV10_XSCOM_EC(proc) \ ((0x2 << 16) | ((1 << (3 - (proc))) << 12)) +#define PNV10_XSCOM_QME(chiplet) \ + (PNV10_XSCOM_EQ(chiplet) | (0xE << 16)) + +/* + * Make the region larger by 0x1000 (instead of starting at an offset) so the + * modelled addresses start from 0 + */ +#define PNV10_XSCOM_QME_BASE(core) \ + ((uint64_t) PNV10_XSCOM_QME(PNV10_XSCOM_EQ_CHIPLET(core))) +#define PNV10_XSCOM_QME_SIZE (0x8000 + 0x1000) + #define PNV10_XSCOM_EQ_BASE(core) \ ((uint64_t) PNV10_XSCOM_EQ(PNV10_XSCOM_EQ_CHIPLET(core))) -#define PNV10_XSCOM_EQ_SIZE 0x100000 +#define PNV10_XSCOM_EQ_SIZE 0x20000 #define PNV10_XSCOM_EC_BASE(core) \ ((uint64_t) PNV10_XSCOM_EQ_BASE(core) | PNV10_XSCOM_EC(core & 0x3)) -#define PNV10_XSCOM_EC_SIZE 0x100000 +#define PNV10_XSCOM_EC_SIZE 0x1000 #define PNV10_XSCOM_PSIHB_BASE 0x3011D00 #define PNV10_XSCOM_PSIHB_SIZE 0x100 diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h index f8c86e09ec..ea7740239b 100644 --- a/include/hw/ppc/ppc4xx.h +++ b/include/hw/ppc/ppc4xx.h @@ -29,7 +29,10 @@ #include "exec/memory.h" #include "hw/sysbus.h" -#define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost" +#define TYPE_PPC4xx_HOST_BRIDGE "ppc4xx-host-bridge" +#define TYPE_PPC4xx_PCI_HOST "ppc4xx-pci-host" +#define TYPE_PPC440_PCIX_HOST "ppc440-pcix-host" +#define TYPE_PPC460EX_PCIE_HOST "ppc460ex-pcie-host" /* * Generic DCR device diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h index 3dfb06e002..9f580a2699 100644 --- a/include/hw/ppc/xive.h +++ b/include/hw/ppc/xive.h @@ -187,6 +187,7 @@ struct XiveSource { /* PQ bits and LSI assertion bit */ uint8_t *status; + uint8_t reset_pq; /* PQ state on reset */ /* ESB memory region */ uint64_t esb_flags; diff --git a/meson.build b/meson.build index b82d5b7cd0..c77faa0b6e 100644 --- a/meson.build +++ b/meson.build @@ -473,19 +473,10 @@ if targetos != 'darwin' warn_flags += ['-Wthread-safety'] endif -# Check that the C++ compiler exists and works with the C compiler. -link_language = 'c' -linker = cc +# Set up C++ compiler flags qemu_cxxflags = [] if 'cpp' in all_languages qemu_cxxflags = ['-D__STDC_LIMIT_MACROS', '-D__STDC_CONSTANT_MACROS', '-D__STDC_FORMAT_MACROS'] + qemu_cflags - if cxx.links(files('scripts/main.c'), args: qemu_cflags) - link_language = 'cpp' - linker = cxx - else - message('C++ compiler does not work with C compiler') - message('Disabling C++-specific optional code') - endif endif # clang does not support glibc + FORTIFY_SOURCE (is it still true?) @@ -1600,7 +1591,7 @@ if not get_option('snappy').auto() or have_system snappy = cc.find_library('snappy', has_headers: ['snappy-c.h'], required: get_option('snappy')) endif -if snappy.found() and not linker.links(''' +if snappy.found() and not cc.links(''' #include <snappy-c.h> int main(void) { snappy_max_compressed_length(4096); return 0; }''', dependencies: snappy) snappy = not_found @@ -2746,7 +2737,7 @@ config_host_data.set('CONFIG_AF_VSOCK', cc.has_header_symbol( have_vss = false have_vss_sdk = false # old xp/2003 SDK -if targetos == 'windows' and link_language == 'cpp' +if targetos == 'windows' and 'cpp' in all_languages have_vss = cxx.compiles(''' #define __MIDL_user_allocate_free_DEFINED__ #include <vss.h> @@ -3827,7 +3818,6 @@ foreach target : target_dirs c_args: c_args, dependencies: arch_deps + deps + exe['dependencies'], objects: lib.extract_all_objects(recursive: true), - link_language: link_language, link_depends: [block_syms, qemu_syms] + exe.get('link_depends', []), link_args: link_args, win_subsystem: exe['win_subsystem']) @@ -4061,7 +4051,7 @@ summary_info += {'host CPU': cpu} summary_info += {'host endianness': build_machine.endian()} summary_info += {'C compiler': ' '.join(meson.get_compiler('c').cmd_array())} summary_info += {'Host C compiler': ' '.join(meson.get_compiler('c', native: true).cmd_array())} -if link_language == 'cpp' +if 'cpp' in all_languages summary_info += {'C++ compiler': ' '.join(meson.get_compiler('cpp').cmd_array())} else summary_info += {'C++ compiler': false} @@ -4074,13 +4064,13 @@ if get_option('optimization') != 'plain' option_cflags += ['-O' + get_option('optimization')] endif summary_info += {'CFLAGS': ' '.join(get_option('c_args') + option_cflags)} -if link_language == 'cpp' +if 'cpp' in all_languages summary_info += {'CXXFLAGS': ' '.join(get_option('cpp_args') + option_cflags)} endif if targetos == 'darwin' summary_info += {'OBJCFLAGS': ' '.join(get_option('objc_args') + option_cflags)} endif -link_args = get_option(link_language + '_link_args') +link_args = get_option('c_link_args') if link_args.length() > 0 summary_info += {'LDFLAGS': ' '.join(link_args)} endif diff --git a/migration/migration.c b/migration/migration.c index 096e8191d1..91bba630a8 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1220,7 +1220,7 @@ static void migrate_error_free(MigrationState *s) } } -void migrate_fd_error(MigrationState *s, const Error *error) +static void migrate_fd_error(MigrationState *s, const Error *error) { trace_migrate_fd_error(error_get_pretty(error)); assert(s->to_dst_file == NULL); @@ -1637,6 +1637,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, bool has_inc, bool inc, bool has_detach, bool detach, bool has_resume, bool resume, Error **errp) { + bool resume_requested; Error *local_err = NULL; MigrationState *s = migrate_get_current(); const char *p = NULL; @@ -1646,13 +1647,14 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, return; } + resume_requested = has_resume && resume; if (!migrate_prepare(s, has_blk && blk, has_inc && inc, - has_resume && resume, errp)) { + resume_requested, errp)) { /* Error detected, put into errp */ return; } - if (!(has_resume && resume)) { + if (!resume_requested) { if (!yank_register_instance(MIGRATION_YANK_INSTANCE, errp)) { return; } @@ -1671,7 +1673,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, } else if (strstart(uri, "fd:", &p)) { fd_start_outgoing_migration(s, p, &local_err); } else { - if (!(has_resume && resume)) { + if (!resume_requested) { yank_unregister_instance(MIGRATION_YANK_INSTANCE); } error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "uri", @@ -1683,7 +1685,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, } if (local_err) { - if (!(has_resume && resume)) { + if (!resume_requested) { yank_unregister_instance(MIGRATION_YANK_INSTANCE); } migrate_fd_error(s, local_err); diff --git a/migration/migration.h b/migration/migration.h index a80b22b703..b7c8b67542 100644 --- a/migration/migration.h +++ b/migration/migration.h @@ -466,7 +466,6 @@ bool migration_has_all_channels(void); uint64_t migrate_max_downtime(void); void migrate_set_error(MigrationState *s, const Error *error); -void migrate_fd_error(MigrationState *s, const Error *error); void migrate_fd_connect(MigrationState *s, Error *error_in); diff --git a/net/socket.c b/net/socket.c index ba6e5b0b00..8e3702e1f3 100644 --- a/net/socket.c +++ b/net/socket.c @@ -446,31 +446,21 @@ static NetSocketState *net_socket_fd_init_stream(NetClientState *peer, return s; } -static NetSocketState *net_socket_fd_init(NetClientState *peer, - const char *model, const char *name, - int fd, int is_connected, - const char *mc, Error **errp) +static int net_socket_fd_check(int fd, Error **errp) { - int so_type = -1, optlen=sizeof(so_type); + int so_type, optlen = sizeof(so_type); - if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type, - (socklen_t *)&optlen)< 0) { + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type, + (socklen_t *)&optlen) < 0) { error_setg(errp, "can't get socket option SO_TYPE"); - close(fd); - return NULL; + return -1; } - switch(so_type) { - case SOCK_DGRAM: - return net_socket_fd_init_dgram(peer, model, name, fd, is_connected, - mc, errp); - case SOCK_STREAM: - return net_socket_fd_init_stream(peer, model, name, fd, is_connected); - default: + if (so_type != SOCK_DGRAM && so_type != SOCK_STREAM) { error_setg(errp, "socket type=%d for fd=%d must be either" " SOCK_DGRAM or SOCK_STREAM", so_type, fd); - close(fd); + return -1; } - return NULL; + return so_type; } static void net_socket_accept(void *opaque) @@ -587,7 +577,7 @@ static int net_socket_connect_init(NetClientState *peer, break; } } - s = net_socket_fd_init(peer, model, name, fd, connected, NULL, errp); + s = net_socket_fd_init_stream(peer, model, name, fd, connected); if (!s) { return -1; } @@ -629,7 +619,7 @@ static int net_socket_mcast_init(NetClientState *peer, return -1; } - s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp); + s = net_socket_fd_init_dgram(peer, model, name, fd, 0, NULL, errp); if (!s) { return -1; } @@ -683,7 +673,7 @@ static int net_socket_udp_init(NetClientState *peer, } qemu_socket_set_nonblock(fd); - s = net_socket_fd_init(peer, model, name, fd, 0, NULL, errp); + s = net_socket_fd_init_dgram(peer, model, name, fd, 0, NULL, errp); if (!s) { return -1; } @@ -716,21 +706,34 @@ int net_init_socket(const Netdev *netdev, const char *name, } if (sock->fd) { - int fd, ret; + int fd, ret, so_type; fd = monitor_fd_param(monitor_cur(), sock->fd, errp); if (fd == -1) { return -1; } + so_type = net_socket_fd_check(fd, errp); + if (so_type < 0) { + return -1; + } ret = qemu_socket_try_set_nonblock(fd); if (ret < 0) { error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", name, fd); return -1; } - if (!net_socket_fd_init(peer, "socket", name, fd, 1, sock->mcast, - errp)) { - return -1; + switch (so_type) { + case SOCK_DGRAM: + if (!net_socket_fd_init_dgram(peer, "socket", name, fd, 1, + sock->mcast, errp)) { + return -1; + } + break; + case SOCK_STREAM: + if (!net_socket_fd_init_stream(peer, "socket", name, fd, 1)) { + return -1; + } + break; } return 0; } diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index e19ab063fa..c0e93ce568 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -50,39 +50,45 @@ typedef struct VhostVDPAState { bool started; } VhostVDPAState; +/* + * The array is sorted alphabetically in ascending order, + * with the exception of VHOST_INVALID_FEATURE_BIT, + * which should always be the last entry. + */ const int vdpa_feature_bits[] = { - VIRTIO_F_NOTIFY_ON_EMPTY, - VIRTIO_RING_F_INDIRECT_DESC, - VIRTIO_RING_F_EVENT_IDX, VIRTIO_F_ANY_LAYOUT, + VIRTIO_F_IOMMU_PLATFORM, + VIRTIO_F_NOTIFY_ON_EMPTY, + VIRTIO_F_RING_PACKED, + VIRTIO_F_RING_RESET, VIRTIO_F_VERSION_1, VIRTIO_NET_F_CSUM, - VIRTIO_NET_F_GUEST_CSUM, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, + VIRTIO_NET_F_CTRL_MAC_ADDR, + VIRTIO_NET_F_CTRL_RX, + VIRTIO_NET_F_CTRL_RX_EXTRA, + VIRTIO_NET_F_CTRL_VLAN, + VIRTIO_NET_F_CTRL_VQ, VIRTIO_NET_F_GSO, + VIRTIO_NET_F_GUEST_CSUM, + VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, - VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO, + VIRTIO_NET_F_HASH_REPORT, + VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_TSO6, - VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_HOST_UFO, + VIRTIO_NET_F_MQ, VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_MTU, - VIRTIO_NET_F_CTRL_RX, - VIRTIO_NET_F_CTRL_RX_EXTRA, - VIRTIO_NET_F_CTRL_VLAN, - VIRTIO_NET_F_CTRL_MAC_ADDR, - VIRTIO_NET_F_RSS, - VIRTIO_NET_F_MQ, - VIRTIO_NET_F_CTRL_VQ, - VIRTIO_F_IOMMU_PLATFORM, - VIRTIO_F_RING_PACKED, - VIRTIO_F_RING_RESET, VIRTIO_NET_F_RSS, - VIRTIO_NET_F_HASH_REPORT, VIRTIO_NET_F_STATUS, + VIRTIO_RING_F_EVENT_IDX, + VIRTIO_RING_F_INDIRECT_DESC, + + /* VHOST_INVALID_FEATURE_BIT should always be the last entry */ VHOST_INVALID_FEATURE_BIT }; diff --git a/python/qemu/qmp/qmp_tui.py b/python/qemu/qmp/qmp_tui.py index 8369144723..2d9ebbd20b 100644 --- a/python/qemu/qmp/qmp_tui.py +++ b/python/qemu/qmp/qmp_tui.py @@ -346,7 +346,10 @@ class App(QMPClient): self._set_status('[Disconnected]') await self.disconnect() # check if a retry is needed - if self.runstate == Runstate.IDLE: + # mypy 1.4.0 doesn't believe runstate can change after + # disconnect(), hence the cast. + state = cast(Runstate, self.runstate) + if state == Runstate.IDLE: continue await self.runstate_changed() diff --git a/python/setup.cfg b/python/setup.cfg index 42f0b0be07..5d7e95f5d2 100644 --- a/python/setup.cfg +++ b/python/setup.cfg @@ -39,7 +39,7 @@ devel = flake8 >= 5.0.4 fusepy >= 2.0.4 isort >= 5.1.2 - mypy >= 0.780 + mypy >= 1.4.0 pylint >= 2.17.3 tox >= 3.18.0 urwid >= 2.1.2 diff --git a/python/tests/minreqs.txt b/python/tests/minreqs.txt index 1ce72cef6d..979461be6b 100644 --- a/python/tests/minreqs.txt +++ b/python/tests/minreqs.txt @@ -28,7 +28,7 @@ avocado-framework==90.0 # Linters flake8==5.0.4 isort==5.1.2 -mypy==0.780 +mypy==1.4.0 pylint==2.17.3 # Transitive flake8 dependencies @@ -37,12 +37,11 @@ pycodestyle==2.9.1 pyflakes==2.5.0 # Transitive mypy dependencies -mypy-extensions==0.4.3 -typed-ast==1.4.0 -typing-extensions==4.5.0 +mypy-extensions==1.0.0 +typing-extensions==4.7.1 # Transitive pylint dependencies astroid==2.15.4 lazy-object-proxy==1.4.0 toml==0.10.0 -wrapt==1.12.1 +wrapt==1.14.0 diff --git a/qemu-options.hx b/qemu-options.hx index 3a6c7d3ef9..96087505b2 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -652,7 +652,7 @@ DEF("m", HAS_ARG, QEMU_OPTION_m, " size: initial amount of guest memory\n" " slots: number of hotplug slots (default: none)\n" " maxmem: maximum amount of guest memory (default: none)\n" - "NOTE: Some architectures might enforce a specific granularity\n", + " Note: Some architectures might enforce a specific granularity\n", QEMU_ARCH_ALL) SRST ``-m [size=]megs[,slots=n,maxmem=size]`` @@ -2143,6 +2143,9 @@ SRST ``show-menubar=on|off`` : Display the main window menubar, defaults to "on" + ``zoom-to-fit=on|off`` : Expand video output to the window size, + defaults to "off" + ``curses[,charset=<encoding>]`` Display video output via curses. For graphics device models which support a text mode, QEMU can display this output using a @@ -2214,8 +2217,8 @@ DEF("spice", HAS_ARG, QEMU_OPTION_spice, " [,disable-agent-file-xfer=on|off][,agent-mouse=[on|off]]\n" " [,playback-compression=[on|off]][,seamless-migration=[on|off]]\n" " [,gl=[on|off]][,rendernode=<file>]\n" - " enable spice\n" - " at least one of {port, tls-port} is mandatory\n", + " enable spice\n" + " at least one of {port, tls-port} is mandatory\n", QEMU_ARCH_ALL) #endif SRST diff --git a/qga/meson.build b/qga/meson.build index d3291b4376..dd18092f56 100644 --- a/qga/meson.build +++ b/qga/meson.build @@ -9,7 +9,7 @@ endif have_qga_vss = get_option('qga_vss') \ .require(targetos == 'windows', error_message: 'VSS support requires Windows') \ - .require(link_language == 'cpp', + .require('cpp' in all_languages, error_message: 'VSS support requires a C++ compiler') \ .require(have_vss, error_message: '''VSS support requires VSS headers. If your Visual Studio installation doesn't have the VSS headers, diff --git a/scripts/main.c b/scripts/main.c deleted file mode 100644 index b552c8e4ed..0000000000 --- a/scripts/main.c +++ /dev/null @@ -1 +0,0 @@ -int main(void) {} diff --git a/softmmu/runstate.c b/softmmu/runstate.c index a9fbcf4862..f3bd862818 100644 --- a/softmmu/runstate.c +++ b/softmmu/runstate.c @@ -802,21 +802,21 @@ void qemu_cleanup(void) */ blk_exp_close_all(); + + /* No more vcpu or device emulation activity beyond this point */ + vm_shutdown(); + replay_finish(); + /* * We must cancel all block jobs while the block layer is drained, * or cancelling will be affected by throttling and thus may block * for an extended period of time. - * vm_shutdown() will bdrv_drain_all(), so we may as well include - * it in the drained section. + * Begin the drained section after vm_shutdown() to avoid requests being + * stuck in the BlockBackend's request queue. * We do not need to end this section, because we do not want any * requests happening from here on anyway. */ bdrv_drain_all_begin(); - - /* No more vcpu or device emulation activity beyond this point */ - vm_shutdown(); - replay_finish(); - job_cancel_sync_all(); bdrv_close_all(); diff --git a/target/avr/helper.c b/target/avr/helper.c index 2bad242a66..e6e7d51487 100644 --- a/target/avr/helper.c +++ b/target/avr/helper.c @@ -52,7 +52,7 @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request) } if (interrupt_request & CPU_INTERRUPT_HARD) { if (cpu_interrupts_enabled(env) && env->intsrc != 0) { - int index = ctz32(env->intsrc); + int index = ctz64(env->intsrc); cs->exception_index = EXCP_INT(index); avr_cpu_do_interrupt(cs); @@ -79,7 +79,7 @@ void avr_cpu_do_interrupt(CPUState *cs) if (cs->exception_index == EXCP_RESET) { vector = 0; } else if (env->intsrc != 0) { - vector = ctz32(env->intsrc) + 1; + vector = ctz64(env->intsrc) + 1; } if (avr_feature(env, AVR_FEATURE_3_BYTE_PC)) { diff --git a/target/i386/cpu.c b/target/i386/cpu.c index b5688cabb4..97ad229d8b 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -739,6 +739,7 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, #define TCG_7_1_EAX_FEATURES (CPUID_7_1_EAX_FZRM | CPUID_7_1_EAX_FSRS | \ CPUID_7_1_EAX_FSRC) #define TCG_7_1_EDX_FEATURES 0 +#define TCG_7_2_EDX_FEATURES 0 #define TCG_APM_FEATURES 0 #define TCG_6_EAX_FEATURES CPUID_6_EAX_ARAT #define TCG_XSAVE_FEATURES (CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XGETBV1) @@ -993,6 +994,25 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { }, .tcg_features = TCG_7_1_EDX_FEATURES, }, + [FEAT_7_2_EDX] = { + .type = CPUID_FEATURE_WORD, + .feat_names = { + NULL, NULL, NULL, NULL, + NULL, "mcdt-no", NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, + .cpuid = { + .eax = 7, + .needs_ecx = true, .ecx = 2, + .reg = R_EDX, + }, + .tcg_features = TCG_7_2_EDX_FEATURES, + }, [FEAT_8000_0007_EDX] = { .type = CPUID_FEATURE_WORD, .feat_names = { @@ -3924,6 +3944,151 @@ static const X86CPUDefinition builtin_x86_defs[] = { .model_id = "Intel Xeon Processor (SapphireRapids)", .versions = (X86CPUVersionDefinition[]) { { .version = 1 }, + { + .version = 2, + .props = (PropValue[]) { + { "sbdr-ssdp-no", "on" }, + { "fbsdp-no", "on" }, + { "psdp-no", "on" }, + { /* end of list */ } + } + }, + { /* end of list */ } + } + }, + { + .name = "GraniteRapids", + .level = 0x20, + .vendor = CPUID_VENDOR_INTEL, + .family = 6, + .model = 173, + .stepping = 0, + /* + * please keep the ascending order so that we can have a clear view of + * bit position of each feature. + */ + .features[FEAT_1_EDX] = + CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | + CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | + CPUID_SEP | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | + CPUID_PAT | CPUID_PSE36 | CPUID_CLFLUSH | CPUID_MMX | CPUID_FXSR | + CPUID_SSE | CPUID_SSE2, + .features[FEAT_1_ECX] = + CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSSE3 | + CPUID_EXT_FMA | CPUID_EXT_CX16 | CPUID_EXT_PCID | CPUID_EXT_SSE41 | + CPUID_EXT_SSE42 | CPUID_EXT_X2APIC | CPUID_EXT_MOVBE | + CPUID_EXT_POPCNT | CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_AES | + CPUID_EXT_XSAVE | CPUID_EXT_AVX | CPUID_EXT_F16C | CPUID_EXT_RDRAND, + .features[FEAT_8000_0001_EDX] = + CPUID_EXT2_SYSCALL | CPUID_EXT2_NX | CPUID_EXT2_PDPE1GB | + CPUID_EXT2_RDTSCP | CPUID_EXT2_LM, + .features[FEAT_8000_0001_ECX] = + CPUID_EXT3_LAHF_LM | CPUID_EXT3_ABM | CPUID_EXT3_3DNOWPREFETCH, + .features[FEAT_8000_0008_EBX] = + CPUID_8000_0008_EBX_WBNOINVD, + .features[FEAT_7_0_EBX] = + CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_HLE | + CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 | + CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | CPUID_7_0_EBX_RTM | + CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | + CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP | + CPUID_7_0_EBX_AVX512IFMA | CPUID_7_0_EBX_CLFLUSHOPT | + CPUID_7_0_EBX_CLWB | CPUID_7_0_EBX_AVX512CD | CPUID_7_0_EBX_SHA_NI | + CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512VL, + .features[FEAT_7_0_ECX] = + CPUID_7_0_ECX_AVX512_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | + CPUID_7_0_ECX_AVX512_VBMI2 | CPUID_7_0_ECX_GFNI | + CPUID_7_0_ECX_VAES | CPUID_7_0_ECX_VPCLMULQDQ | + CPUID_7_0_ECX_AVX512VNNI | CPUID_7_0_ECX_AVX512BITALG | + CPUID_7_0_ECX_AVX512_VPOPCNTDQ | CPUID_7_0_ECX_LA57 | + CPUID_7_0_ECX_RDPID | CPUID_7_0_ECX_BUS_LOCK_DETECT, + .features[FEAT_7_0_EDX] = + CPUID_7_0_EDX_FSRM | CPUID_7_0_EDX_SERIALIZE | + CPUID_7_0_EDX_TSX_LDTRK | CPUID_7_0_EDX_AMX_BF16 | + CPUID_7_0_EDX_AVX512_FP16 | CPUID_7_0_EDX_AMX_TILE | + CPUID_7_0_EDX_AMX_INT8 | CPUID_7_0_EDX_SPEC_CTRL | + CPUID_7_0_EDX_ARCH_CAPABILITIES | CPUID_7_0_EDX_SPEC_CTRL_SSBD, + .features[FEAT_ARCH_CAPABILITIES] = + MSR_ARCH_CAP_RDCL_NO | MSR_ARCH_CAP_IBRS_ALL | + MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY | MSR_ARCH_CAP_MDS_NO | + MSR_ARCH_CAP_PSCHANGE_MC_NO | MSR_ARCH_CAP_TAA_NO | + MSR_ARCH_CAP_SBDR_SSDP_NO | MSR_ARCH_CAP_FBSDP_NO | + MSR_ARCH_CAP_PSDP_NO | MSR_ARCH_CAP_PBRSB_NO, + .features[FEAT_XSAVE] = + CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | + CPUID_XSAVE_XGETBV1 | CPUID_XSAVE_XSAVES | CPUID_D_1_EAX_XFD, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, + .features[FEAT_7_1_EAX] = + CPUID_7_1_EAX_AVX_VNNI | CPUID_7_1_EAX_AVX512_BF16 | + CPUID_7_1_EAX_FZRM | CPUID_7_1_EAX_FSRS | CPUID_7_1_EAX_FSRC | + CPUID_7_1_EAX_AMX_FP16, + .features[FEAT_7_1_EDX] = + CPUID_7_1_EDX_PREFETCHITI, + .features[FEAT_7_2_EDX] = + CPUID_7_2_EDX_MCDT_NO, + .features[FEAT_VMX_BASIC] = + MSR_VMX_BASIC_INS_OUTS | MSR_VMX_BASIC_TRUE_CTLS, + .features[FEAT_VMX_ENTRY_CTLS] = + VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_IA32E_MODE | + VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | + VMX_VM_ENTRY_LOAD_IA32_PAT | VMX_VM_ENTRY_LOAD_IA32_EFER, + .features[FEAT_VMX_EPT_VPID_CAPS] = + MSR_VMX_EPT_EXECONLY | + MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_PAGE_WALK_LENGTH_5 | + MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | MSR_VMX_EPT_1GB | + MSR_VMX_EPT_INVEPT | MSR_VMX_EPT_AD_BITS | + MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | + MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | + MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | + MSR_VMX_EPT_INVVPID_ALL_CONTEXT | + MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, + .features[FEAT_VMX_EXIT_CTLS] = + VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | + VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | + VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_IA32_PAT | + VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | + VMX_VM_EXIT_LOAD_IA32_EFER | VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, + .features[FEAT_VMX_MISC] = + MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_ACTIVITY_HLT | + MSR_VMX_MISC_VMWRITE_VMEXIT, + .features[FEAT_VMX_PINBASED_CTLS] = + VMX_PIN_BASED_EXT_INTR_MASK | VMX_PIN_BASED_NMI_EXITING | + VMX_PIN_BASED_VIRTUAL_NMIS | VMX_PIN_BASED_VMX_PREEMPTION_TIMER | + VMX_PIN_BASED_POSTED_INTR, + .features[FEAT_VMX_PROCBASED_CTLS] = + VMX_CPU_BASED_VIRTUAL_INTR_PENDING | + VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | + VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | + VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | + VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | + VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | + VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_VIRTUAL_NMI_PENDING | + VMX_CPU_BASED_MOV_DR_EXITING | VMX_CPU_BASED_UNCOND_IO_EXITING | + VMX_CPU_BASED_USE_IO_BITMAPS | VMX_CPU_BASED_MONITOR_TRAP_FLAG | + VMX_CPU_BASED_USE_MSR_BITMAPS | VMX_CPU_BASED_MONITOR_EXITING | + VMX_CPU_BASED_PAUSE_EXITING | + VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, + .features[FEAT_VMX_SECONDARY_CTLS] = + VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | + VMX_SECONDARY_EXEC_ENABLE_EPT | VMX_SECONDARY_EXEC_DESC | + VMX_SECONDARY_EXEC_RDTSCP | + VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | + VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_WBINVD_EXITING | + VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | + VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | + VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | + VMX_SECONDARY_EXEC_RDRAND_EXITING | + VMX_SECONDARY_EXEC_ENABLE_INVPCID | + VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | + VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML | + VMX_SECONDARY_EXEC_XSAVES, + .features[FEAT_VMX_VMFUNC] = + MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Xeon Processor (GraniteRapids)", + .versions = (X86CPUVersionDefinition[]) { + { .version = 1 }, { /* end of list */ }, }, }, @@ -6017,6 +6182,11 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *edx = env->features[FEAT_7_1_EDX]; *ebx = 0; *ecx = 0; + } else if (count == 2) { + *edx = env->features[FEAT_7_2_EDX]; + *eax = 0; + *ebx = 0; + *ecx = 0; } else { *eax = 0; *ebx = 0; @@ -6880,6 +7050,8 @@ void x86_cpu_expand_features(X86CPU *cpu, Error **errp) x86_cpu_adjust_feat_level(cpu, FEAT_6_EAX); x86_cpu_adjust_feat_level(cpu, FEAT_7_0_ECX); x86_cpu_adjust_feat_level(cpu, FEAT_7_1_EAX); + x86_cpu_adjust_feat_level(cpu, FEAT_7_1_EDX); + x86_cpu_adjust_feat_level(cpu, FEAT_7_2_EDX); x86_cpu_adjust_feat_level(cpu, FEAT_8000_0001_EDX); x86_cpu_adjust_feat_level(cpu, FEAT_8000_0001_ECX); x86_cpu_adjust_feat_level(cpu, FEAT_8000_0007_EDX); diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 2c9b0d2ebc..e0771a1043 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -628,6 +628,7 @@ typedef enum FeatureWord { FEAT_XSAVE_XSS_LO, /* CPUID[EAX=0xd,ECX=1].ECX */ FEAT_XSAVE_XSS_HI, /* CPUID[EAX=0xd,ECX=1].EDX */ FEAT_7_1_EDX, /* CPUID[EAX=7,ECX=1].EDX */ + FEAT_7_2_EDX, /* CPUID[EAX=7,ECX=2].EDX */ FEATURE_WORDS, } FeatureWord; @@ -932,6 +933,9 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, /* PREFETCHIT0/1 Instructions */ #define CPUID_7_1_EDX_PREFETCHITI (1U << 14) +/* Do not exhibit MXCSR Configuration Dependent Timing (MCDT) behavior */ +#define CPUID_7_2_EDX_MCDT_NO (1U << 5) + /* XFD Extend Feature Disabled */ #define CPUID_D_1_EAX_XFD (1U << 4) @@ -1018,7 +1022,11 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, #define MSR_ARCH_CAP_PSCHANGE_MC_NO (1U << 6) #define MSR_ARCH_CAP_TSX_CTRL_MSR (1U << 7) #define MSR_ARCH_CAP_TAA_NO (1U << 8) +#define MSR_ARCH_CAP_SBDR_SSDP_NO (1U << 13) +#define MSR_ARCH_CAP_FBSDP_NO (1U << 14) +#define MSR_ARCH_CAP_PSDP_NO (1U << 15) #define MSR_ARCH_CAP_FB_CLEAR (1U << 17) +#define MSR_ARCH_CAP_PBRSB_NO (1U << 24) #define MSR_CORE_CAP_SPLIT_LOCK_DETECT (1U << 5) diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index de531842f6..ebfaf3d24c 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -432,6 +432,10 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, uint32_t eax; host_cpuid(7, 1, &eax, &unused, &unused, &unused); ret |= eax & (CPUID_7_1_EAX_FZRM | CPUID_7_1_EAX_FSRS | CPUID_7_1_EAX_FSRC); + } else if (function == 7 && index == 2 && reg == R_EDX) { + uint32_t edx; + host_cpuid(7, 2, &unused, &unused, &unused, &edx); + ret |= edx & CPUID_7_2_EDX_MCDT_NO; } else if (function == 0xd && index == 0 && (reg == R_EAX || reg == R_EDX)) { /* diff --git a/target/ppc/arch_dump.c b/target/ppc/arch_dump.c index f58e6359d5..a8315659d9 100644 --- a/target/ppc/arch_dump.c +++ b/target/ppc/arch_dump.c @@ -237,7 +237,7 @@ int cpu_get_dump_info(ArchDumpInfo *info, info->d_machine = PPC_ELF_MACHINE; info->d_class = ELFCLASS; - if (ppc_interrupts_little_endian(cpu, cpu->env.has_hv_mode)) { + if (ppc_interrupts_little_endian(cpu, !!(cpu->env.msr_mask & MSR_HVB))) { info->d_endian = ELFDATA2LSB; } else { info->d_endian = ELFDATA2MSB; diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h index 9666f54f65..be33786bd8 100644 --- a/target/ppc/cpu-qom.h +++ b/target/ppc/cpu-qom.h @@ -31,6 +31,12 @@ OBJECT_DECLARE_CPU_TYPE(PowerPCCPU, PowerPCCPUClass, POWERPC_CPU) +#define POWERPC_CPU_TYPE_SUFFIX "-" TYPE_POWERPC_CPU +#define POWERPC_CPU_TYPE_NAME(model) model POWERPC_CPU_TYPE_SUFFIX +#define CPU_RESOLVING_TYPE TYPE_POWERPC_CPU + +#define TYPE_HOST_POWERPC_CPU POWERPC_CPU_TYPE_NAME("host") + ObjectClass *ppc_cpu_class_by_name(const char *name); typedef struct CPUArchState CPUPPCState; diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index af12c93ebc..25fac9577a 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -674,6 +674,8 @@ enum { POWERPC_FLAG_SCV = 0x00200000, /* Has >1 thread per core */ POWERPC_FLAG_SMT = 0x00400000, + /* Using "LPAR per core" mode (as opposed to per-thread) */ + POWERPC_FLAG_SMT_1LPAR = 0x00800000, }; /* @@ -1437,6 +1439,7 @@ void store_booke_tsr(CPUPPCState *env, target_ulong val); void ppc_tlb_invalidate_all(CPUPPCState *env); void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr); void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp); +void cpu_ppc_set_1lpar(PowerPCCPU *cpu); int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb, hwaddr *raddrp, target_ulong address, uint32_t pid); int ppcemb_tlb_search(CPUPPCState *env, target_ulong address, uint32_t pid); @@ -1468,10 +1471,6 @@ static inline uint64_t ppc_dump_gpr(CPUPPCState *env, int gprn) int ppc_dcr_read(ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp); int ppc_dcr_write(ppc_dcr_t *dcr_env, int dcrn, uint32_t val); -#define POWERPC_CPU_TYPE_SUFFIX "-" TYPE_POWERPC_CPU -#define POWERPC_CPU_TYPE_NAME(model) model POWERPC_CPU_TYPE_SUFFIX -#define CPU_RESOLVING_TYPE TYPE_POWERPC_CPU - #define cpu_list ppc_cpu_list /* MMU modes definitions */ diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index aeff71d063..02b7aad9b0 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -21,7 +21,6 @@ #include "qemu/osdep.h" #include "disas/dis-asm.h" #include "gdbstub/helpers.h" -#include "kvm_ppc.h" #include "sysemu/cpus.h" #include "sysemu/hw_accel.h" #include "sysemu/tcg.h" @@ -49,6 +48,7 @@ #ifndef CONFIG_USER_ONLY #include "hw/boards.h" #include "hw/intc/intc.h" +#include "kvm_ppc.h" #endif /* #define PPC_DEBUG_SPR */ @@ -5370,31 +5370,6 @@ static void register_book3s_ids_sprs(CPUPPCState *env) &spr_read_generic, SPR_NOACCESS, &spr_read_generic, NULL, 0x00000000); - spr_register_hv(env, SPR_HID0, "HID0", - SPR_NOACCESS, SPR_NOACCESS, - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - spr_register_hv(env, SPR_TSCR, "TSCR", - SPR_NOACCESS, SPR_NOACCESS, - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic32, - 0x00000000); - spr_register_hv(env, SPR_HMER, "HMER", - SPR_NOACCESS, SPR_NOACCESS, - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_hmer, - 0x00000000); - spr_register_hv(env, SPR_HMEER, "HMEER", - SPR_NOACCESS, SPR_NOACCESS, - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); - spr_register_hv(env, SPR_TFMR, "TFMR", - SPR_NOACCESS, SPR_NOACCESS, - SPR_NOACCESS, SPR_NOACCESS, - &spr_read_generic, &spr_write_generic, - 0x00000000); spr_register_hv(env, SPR_LPIDR, "LPIDR", SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, SPR_NOACCESS, @@ -5656,14 +5631,60 @@ static void register_power8_ic_sprs(CPUPPCState *env) #endif } +/* SPRs specific to IBM POWER CPUs */ +static void register_power_common_book4_sprs(CPUPPCState *env) +{ +#if !defined(CONFIG_USER_ONLY) + spr_register_hv(env, SPR_HID0, "HID0", + SPR_NOACCESS, SPR_NOACCESS, + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_core_write_generic, + 0x00000000); + spr_register_hv(env, SPR_TSCR, "TSCR", + SPR_NOACCESS, SPR_NOACCESS, + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic32, + 0x00000000); + spr_register_hv(env, SPR_HMER, "HMER", + SPR_NOACCESS, SPR_NOACCESS, + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_hmer, + 0x00000000); + spr_register_hv(env, SPR_HMEER, "HMEER", + SPR_NOACCESS, SPR_NOACCESS, + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + spr_register_hv(env, SPR_TFMR, "TFMR", + SPR_NOACCESS, SPR_NOACCESS, + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_tfmr, &spr_write_tfmr, + 0x00000000); +#endif +} + +static void register_power9_book4_sprs(CPUPPCState *env) +{ + /* Add a number of P9 book4 registers */ + register_power_common_book4_sprs(env); +#if !defined(CONFIG_USER_ONLY) + spr_register_kvm(env, SPR_WORT, "WORT", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + KVM_REG_PPC_WORT, 0); +#endif +} + static void register_power8_book4_sprs(CPUPPCState *env) { /* Add a number of P8 book4 registers */ + register_power_common_book4_sprs(env); #if !defined(CONFIG_USER_ONLY) spr_register_kvm(env, SPR_ACOP, "ACOP", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, KVM_REG_PPC_ACOP, 0); + /* PID is only in BookE in ISA v2.07 */ spr_register_kvm(env, SPR_BOOKS_PID, "PID", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_pidr, @@ -5679,10 +5700,12 @@ static void register_power7_book4_sprs(CPUPPCState *env) { /* Add a number of P7 book4 registers */ #if !defined(CONFIG_USER_ONLY) + register_power_common_book4_sprs(env); spr_register_kvm(env, SPR_ACOP, "ACOP", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, KVM_REG_PPC_ACOP, 0); + /* PID is only in BookE in ISA v2.06 */ spr_register_kvm(env, SPR_BOOKS_PID, "PID", SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic32, @@ -5716,6 +5739,11 @@ static void register_power9_mmu_sprs(CPUPPCState *env) SPR_NOACCESS, SPR_NOACCESS, &spr_read_generic, &spr_write_generic, 0x0000000000000000); + /* PID is part of the BookS ISA from v3.0 */ + spr_register_kvm(env, SPR_BOOKS_PID, "PID", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_pidr, + KVM_REG_PPC_PID, 0); #endif } @@ -6269,7 +6297,7 @@ static void init_proc_POWER9(CPUPPCState *env) register_power8_dpdes_sprs(env); register_vtb_sprs(env); register_power8_ic_sprs(env); - register_power8_book4_sprs(env); + register_power9_book4_sprs(env); register_power8_rpr_sprs(env); register_power9_mmu_sprs(env); @@ -6462,7 +6490,7 @@ static void init_proc_POWER10(CPUPPCState *env) register_power8_dpdes_sprs(env); register_vtb_sprs(env); register_power8_ic_sprs(env); - register_power8_book4_sprs(env); + register_power9_book4_sprs(env); register_power8_rpr_sprs(env); register_power9_mmu_sprs(env); register_power10_hash_sprs(env); @@ -6601,6 +6629,18 @@ void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp) env->msr_mask &= ~MSR_HVB; } +void cpu_ppc_set_1lpar(PowerPCCPU *cpu) +{ + CPUPPCState *env = &cpu->env; + + /* + * pseries SMT means "LPAR per core" mode, e.g., msgsndp is usable + * between threads. + */ + if (env->flags & POWERPC_FLAG_SMT) { + env->flags |= POWERPC_FLAG_SMT_1LPAR; + } +} #endif /* !defined(CONFIG_USER_ONLY) */ #endif /* defined(TARGET_PPC64) */ @@ -7295,6 +7335,7 @@ static const struct TCGCPUOps ppc_tcg_ops = { .cpu_exec_enter = ppc_cpu_exec_enter, .cpu_exec_exit = ppc_cpu_exec_exit, .do_unaligned_access = ppc_cpu_do_unaligned_access, + .do_transaction_failed = ppc_cpu_do_transaction_failed, #endif /* !CONFIG_USER_ONLY */ }; #endif /* CONFIG_TCG */ diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 2158390e27..003805b202 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -187,8 +187,7 @@ static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp) } #if defined(TARGET_PPC64) -static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, - target_ulong *msr) +static int powerpc_reset_wakeup(CPUPPCState *env, int excp, target_ulong *msr) { /* We no longer are in a PM state */ env->resume_as_sreset = false; @@ -223,8 +222,8 @@ static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, *msr |= SRR1_WAKEHVI; break; default: - cpu_abort(cs, "Unsupported exception %d in Power Save mode\n", - excp); + cpu_abort(env_cpu(env), + "Unsupported exception %d in Power Save mode\n", excp); } return POWERPC_EXCP_RESET; } @@ -425,6 +424,25 @@ static void powerpc_set_excp_state(PowerPCCPU *cpu, target_ulong vector, env->reserve_addr = -1; } +static void powerpc_mcheck_checkstop(CPUPPCState *env) +{ + CPUState *cs = env_cpu(env); + + if (FIELD_EX64(env->msr, MSR, ME)) { + return; + } + + /* Machine check exception is not enabled. Enter checkstop state. */ + fprintf(stderr, "Machine check while not allowed. " + "Entering checkstop state\n"); + if (qemu_log_separate()) { + qemu_log("Machine check while not allowed. " + "Entering checkstop state\n"); + } + cs->halted = 1; + cpu_interrupt_exittb(cs); +} + static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) { CPUState *cs = CPU(cpu); @@ -467,21 +485,7 @@ static void powerpc_excp_40x(PowerPCCPU *cpu, int excp) srr1 = SPR_40x_SRR3; break; case POWERPC_EXCP_MCHECK: /* Machine check exception */ - if (!FIELD_EX64(env->msr, MSR, ME)) { - /* - * Machine check exception is not enabled. Enter - * checkstop state. - */ - fprintf(stderr, "Machine check while not allowed. " - "Entering checkstop state\n"); - if (qemu_log_separate()) { - qemu_log("Machine check while not allowed. " - "Entering checkstop state\n"); - } - cs->halted = 1; - cpu_interrupt_exittb(cs); - } - + powerpc_mcheck_checkstop(env); /* machine check exceptions don't have ME set */ new_msr &= ~((target_ulong)1 << MSR_ME); @@ -598,21 +602,7 @@ static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp) case POWERPC_EXCP_CRITICAL: /* Critical input */ break; case POWERPC_EXCP_MCHECK: /* Machine check exception */ - if (!FIELD_EX64(env->msr, MSR, ME)) { - /* - * Machine check exception is not enabled. Enter - * checkstop state. - */ - fprintf(stderr, "Machine check while not allowed. " - "Entering checkstop state\n"); - if (qemu_log_separate()) { - qemu_log("Machine check while not allowed. " - "Entering checkstop state\n"); - } - cs->halted = 1; - cpu_interrupt_exittb(cs); - } - + powerpc_mcheck_checkstop(env); /* machine check exceptions don't have ME set */ new_msr &= ~((target_ulong)1 << MSR_ME); @@ -771,21 +761,7 @@ static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp) switch (excp) { case POWERPC_EXCP_MCHECK: /* Machine check exception */ - if (!FIELD_EX64(env->msr, MSR, ME)) { - /* - * Machine check exception is not enabled. Enter - * checkstop state. - */ - fprintf(stderr, "Machine check while not allowed. " - "Entering checkstop state\n"); - if (qemu_log_separate()) { - qemu_log("Machine check while not allowed. " - "Entering checkstop state\n"); - } - cs->halted = 1; - cpu_interrupt_exittb(cs); - } - + powerpc_mcheck_checkstop(env); /* machine check exceptions don't have ME set */ new_msr &= ~((target_ulong)1 << MSR_ME); @@ -956,21 +932,7 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) switch (excp) { case POWERPC_EXCP_MCHECK: /* Machine check exception */ - if (!FIELD_EX64(env->msr, MSR, ME)) { - /* - * Machine check exception is not enabled. Enter - * checkstop state. - */ - fprintf(stderr, "Machine check while not allowed. " - "Entering checkstop state\n"); - if (qemu_log_separate()) { - qemu_log("Machine check while not allowed. " - "Entering checkstop state\n"); - } - cs->halted = 1; - cpu_interrupt_exittb(cs); - } - + powerpc_mcheck_checkstop(env); /* machine check exceptions don't have ME set */ new_msr &= ~((target_ulong)1 << MSR_ME); @@ -1030,7 +992,7 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) { int lev = env->error_code; - if ((lev == 1) && cpu->vhyp) { + if (lev == 1 && cpu->vhyp) { dump_hcall(env); } else { dump_syscall(env); @@ -1048,7 +1010,7 @@ static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp) * uses VOF and the 74xx CPUs, so although the 74xx don't have * HV mode, we need to keep hypercall support. */ - if ((lev == 1) && cpu->vhyp) { + if (lev == 1 && cpu->vhyp) { PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); vhc->hypercall(cpu->vhyp, cpu); @@ -1151,21 +1113,7 @@ static void powerpc_excp_booke(PowerPCCPU *cpu, int excp) srr1 = SPR_BOOKE_CSRR1; break; case POWERPC_EXCP_MCHECK: /* Machine check exception */ - if (!FIELD_EX64(env->msr, MSR, ME)) { - /* - * Machine check exception is not enabled. Enter - * checkstop state. - */ - fprintf(stderr, "Machine check while not allowed. " - "Entering checkstop state\n"); - if (qemu_log_separate()) { - qemu_log("Machine check while not allowed. " - "Entering checkstop state\n"); - } - cs->halted = 1; - cpu_interrupt_exittb(cs); - } - + powerpc_mcheck_checkstop(env); /* machine check exceptions don't have ME set */ new_msr &= ~((target_ulong)1 << MSR_ME); @@ -1440,7 +1388,7 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) * P7/P8/P9 */ if (env->resume_as_sreset) { - excp = powerpc_reset_wakeup(cs, env, excp, &msr); + excp = powerpc_reset_wakeup(env, excp, &msr); } /* @@ -1468,20 +1416,7 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) switch (excp) { case POWERPC_EXCP_MCHECK: /* Machine check exception */ - if (!FIELD_EX64(env->msr, MSR, ME)) { - /* - * Machine check exception is not enabled. Enter - * checkstop state. - */ - fprintf(stderr, "Machine check while not allowed. " - "Entering checkstop state\n"); - if (qemu_log_separate()) { - qemu_log("Machine check while not allowed. " - "Entering checkstop state\n"); - } - cs->halted = 1; - cpu_interrupt_exittb(cs); - } + powerpc_mcheck_checkstop(env); if (env->msr_mask & MSR_HVB) { /* * ISA specifies HV, but can be delivered to guest with HV @@ -1493,7 +1428,9 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) /* machine check exceptions don't have ME set */ new_msr &= ~((target_ulong)1 << MSR_ME); + msr |= env->error_code; break; + case POWERPC_EXCP_DSI: /* Data storage exception */ trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]); break; @@ -1572,7 +1509,7 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) case POWERPC_EXCP_SYSCALL: /* System call exception */ lev = env->error_code; - if ((lev == 1) && cpu->vhyp) { + if (lev == 1 && cpu->vhyp) { dump_hcall(env); } else { dump_syscall(env); @@ -1585,7 +1522,7 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp) env->nip += 4; /* "PAPR mode" built-in hypercall emulation */ - if ((lev == 1) && books_vhyp_handles_hcall(cpu)) { + if (lev == 1 && books_vhyp_handles_hcall(cpu)) { PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); vhc->hypercall(cpu->vhyp, cpu); @@ -1835,8 +1772,8 @@ static int p7_interrupt_powersave(CPUPPCState *env) static int p7_next_unmasked_interrupt(CPUPPCState *env) { - PowerPCCPU *cpu = env_archcpu(env); - CPUState *cs = CPU(cpu); + CPUState *cs = env_cpu(env); + /* Ignore MSR[EE] when coming out of some power management states */ bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset; @@ -1925,8 +1862,8 @@ static int p8_interrupt_powersave(CPUPPCState *env) static int p8_next_unmasked_interrupt(CPUPPCState *env) { - PowerPCCPU *cpu = env_archcpu(env); - CPUState *cs = CPU(cpu); + CPUState *cs = env_cpu(env); + /* Ignore MSR[EE] when coming out of some power management states */ bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset; @@ -2046,8 +1983,8 @@ static int p9_interrupt_powersave(CPUPPCState *env) static int p9_next_unmasked_interrupt(CPUPPCState *env) { - PowerPCCPU *cpu = env_archcpu(env); - CPUState *cs = CPU(cpu); + CPUState *cs = env_cpu(env); + /* Ignore MSR[EE] when coming out of some power management states */ bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset; @@ -2718,8 +2655,7 @@ void helper_store_msr(CPUPPCState *env, target_ulong val) uint32_t excp = hreg_store_msr(env, val, 0); if (excp != 0) { - CPUState *cs = env_cpu(env); - cpu_interrupt_exittb(cs); + cpu_interrupt_exittb(env_cpu(env)); raise_exception(env, excp); } } @@ -2741,9 +2677,8 @@ void helper_scv(CPUPPCState *env, uint32_t lev) void helper_pminsn(CPUPPCState *env, uint32_t insn) { - CPUState *cs; + CPUState *cs = env_cpu(env); - cs = env_cpu(env); cs->halted = 1; /* Condition for waking up at 0x100 */ @@ -2756,8 +2691,6 @@ void helper_pminsn(CPUPPCState *env, uint32_t insn) static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr) { - CPUState *cs = env_cpu(env); - /* MSR:POW cannot be set by any form of rfi */ msr &= ~(1ULL << MSR_POW); @@ -2781,7 +2714,7 @@ static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr) * No need to raise an exception here, as rfi is always the last * insn of a TB */ - cpu_interrupt_exittb(cs); + cpu_interrupt_exittb(env_cpu(env)); /* Reset the reservation */ env->reserve_addr = -1; @@ -3199,6 +3132,10 @@ void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb) helper_hfscr_facility_check(env, HFSCR_MSGP, "msgsndp", HFSCR_IC_MSGP); + if (!(env->flags & POWERPC_FLAG_SMT_1LPAR)) { + nr_threads = 1; /* msgsndp behaves as 1-thread in LPAR-per-thread mode*/ + } + if (!dbell_type_server(rb) || ttir >= nr_threads) { return; } @@ -3253,5 +3190,52 @@ void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, env->error_code = insn & 0x03FF0000; cpu_loop_exit(cs); } + +void ppc_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, + vaddr vaddr, unsigned size, + MMUAccessType access_type, + int mmu_idx, MemTxAttrs attrs, + MemTxResult response, uintptr_t retaddr) +{ + CPUPPCState *env = cs->env_ptr; + + switch (env->excp_model) { +#if defined(TARGET_PPC64) + case POWERPC_EXCP_POWER9: + case POWERPC_EXCP_POWER10: + /* + * Machine check codes can be found in processor User Manual or + * Linux or skiboot source. + */ + if (access_type == MMU_DATA_LOAD) { + env->spr[SPR_DAR] = vaddr; + env->spr[SPR_DSISR] = PPC_BIT(57); + env->error_code = PPC_BIT(42); + + } else if (access_type == MMU_DATA_STORE) { + /* + * MCE for stores in POWER is asynchronous so hardware does + * not set DAR, but QEMU can do better. + */ + env->spr[SPR_DAR] = vaddr; + env->error_code = PPC_BIT(36) | PPC_BIT(43) | PPC_BIT(45); + env->error_code |= PPC_BIT(42); + + } else { /* Fetch */ + env->error_code = PPC_BIT(36) | PPC_BIT(44) | PPC_BIT(45); + } + break; +#endif + default: + /* + * TODO: Check behaviour for other CPUs, for now do nothing. + * Could add a basic MCE even if real hardware ignores. + */ + return; + } + + cs->exception_index = POWERPC_EXCP_MCHECK; + cpu_loop_exit_restore(cs, retaddr); +} #endif /* CONFIG_TCG */ #endif /* !CONFIG_USER_ONLY */ diff --git a/target/ppc/helper.h b/target/ppc/helper.h index fda40b8a60..abec6fe341 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -704,6 +704,7 @@ DEF_HELPER_3(store_dcr, void, env, tl, tl) DEF_HELPER_2(load_dump_spr, void, env, i32) DEF_HELPER_2(store_dump_spr, void, env, i32) +DEF_HELPER_3(spr_core_write_generic, void, env, i32, tl) DEF_HELPER_3(spr_write_CTRL, void, env, i32, tl) DEF_HELPER_4(fscr_facility_check, void, env, i32, i32, i32) @@ -722,6 +723,8 @@ DEF_HELPER_FLAGS_1(load_dpdes, TCG_CALL_NO_RWG, tl, env) DEF_HELPER_FLAGS_2(store_dpdes, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_2(book3s_msgsndp, void, env, tl) DEF_HELPER_2(book3s_msgclrp, void, env, tl) +DEF_HELPER_1(load_tfmr, tl, env) +DEF_HELPER_2(store_tfmr, void, env, tl) #endif DEF_HELPER_2(store_sdr1, void, env, tl) DEF_HELPER_2(store_pidr, void, env, tl) diff --git a/target/ppc/internal.h b/target/ppc/internal.h index 901bae6d39..57acb3212c 100644 --- a/target/ppc/internal.h +++ b/target/ppc/internal.h @@ -296,6 +296,11 @@ bool ppc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, G_NORETURN void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr addr, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr); +void ppc_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, + vaddr addr, unsigned size, + MMUAccessType access_type, + int mmu_idx, MemTxAttrs attrs, + MemTxResult response, uintptr_t retaddr); #endif FIELD(GER_MSK, XMSK, 0, 4) diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h index 611debc3ce..6a4dd9c560 100644 --- a/target/ppc/kvm_ppc.h +++ b/target/ppc/kvm_ppc.h @@ -9,11 +9,10 @@ #ifndef KVM_PPC_H #define KVM_PPC_H +#include "sysemu/kvm.h" #include "exec/hwaddr.h" #include "cpu.h" -#define TYPE_HOST_POWERPC_CPU POWERPC_CPU_TYPE_NAME("host") - #ifdef CONFIG_KVM uint32_t kvmppc_get_tbfreq(void); @@ -43,7 +42,6 @@ int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu); target_ulong kvmppc_configure_v3_mmu(PowerPCCPU *cpu, bool radix, bool gtse, uint64_t proc_tbl); -#ifndef CONFIG_USER_ONLY bool kvmppc_spapr_use_multitce(void); int kvmppc_spapr_enable_inkernel_multitce(void); void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t page_shift, @@ -53,7 +51,6 @@ int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size); int kvmppc_reset_htab(int shift_hint); uint64_t kvmppc_vrma_limit(unsigned int hash_shift); bool kvmppc_has_cap_spapr_vfio(void); -#endif /* !CONFIG_USER_ONLY */ bool kvmppc_has_cap_epr(void); int kvmppc_define_rtas_kernel_token(uint32_t token, const char *function); int kvmppc_get_htab_fd(bool write, uint64_t index, Error **errp); @@ -92,7 +89,34 @@ void kvmppc_set_reg_tb_offset(PowerPCCPU *cpu, int64_t tb_offset); int kvm_handle_nmi(PowerPCCPU *cpu, struct kvm_run *run); -#else +#define kvmppc_eieio() \ + do { \ + if (kvm_enabled()) { \ + asm volatile("eieio" : : : "memory"); \ + } \ + } while (0) + +/* Store data cache blocks back to memory */ +static inline void kvmppc_dcbst_range(PowerPCCPU *cpu, uint8_t *addr, int len) +{ + uint8_t *p; + + for (p = addr; p < addr + len; p += cpu->env.dcache_line_size) { + asm volatile("dcbst 0,%0" : : "r"(p) : "memory"); + } +} + +/* Invalidate instruction cache blocks */ +static inline void kvmppc_icbi_range(PowerPCCPU *cpu, uint8_t *addr, int len) +{ + uint8_t *p; + + for (p = addr; p < addr + len; p += cpu->env.icache_line_size) { + asm volatile("icbi 0,%0" : : "r"(p)); + } +} + +#else /* !CONFIG_KVM */ static inline uint32_t kvmppc_get_tbfreq(void) { @@ -236,7 +260,6 @@ static inline void kvmppc_set_reg_tb_offset(PowerPCCPU *cpu, int64_t tb_offset) { } -#ifndef CONFIG_USER_ONLY static inline bool kvmppc_spapr_use_multitce(void) { return false; @@ -296,8 +319,6 @@ static inline void kvmppc_write_hpte(hwaddr ptex, uint64_t pte0, uint64_t pte1) abort(); } -#endif /* !CONFIG_USER_ONLY */ - static inline bool kvmppc_has_cap_epr(void) { return false; @@ -439,10 +460,6 @@ static inline bool kvmppc_pvr_workaround_required(PowerPCCPU *cpu) return false; } -#endif - -#ifndef CONFIG_KVM - #define kvmppc_eieio() do { } while (0) static inline void kvmppc_dcbst_range(PowerPCCPU *cpu, uint8_t *addr, int len) @@ -453,35 +470,6 @@ static inline void kvmppc_icbi_range(PowerPCCPU *cpu, uint8_t *addr, int len) { } -#else /* CONFIG_KVM */ - -#define kvmppc_eieio() \ - do { \ - if (kvm_enabled()) { \ - asm volatile("eieio" : : : "memory"); \ - } \ - } while (0) - -/* Store data cache blocks back to memory */ -static inline void kvmppc_dcbst_range(PowerPCCPU *cpu, uint8_t *addr, int len) -{ - uint8_t *p; - - for (p = addr; p < addr + len; p += cpu->env.dcache_line_size) { - asm volatile("dcbst 0,%0" : : "r"(p) : "memory"); - } -} - -/* Invalidate instruction cache blocks */ -static inline void kvmppc_icbi_range(PowerPCCPU *cpu, uint8_t *addr, int len) -{ - uint8_t *p; - - for (p = addr; p < addr + len; p += cpu->env.icache_line_size) { - asm volatile("icbi 0,%0" : : "r"(p)); - } -} - #endif /* CONFIG_KVM */ #endif /* KVM_PPC_H */ diff --git a/target/ppc/meson.build b/target/ppc/meson.build index a69f174f41..4c2635039e 100644 --- a/target/ppc/meson.build +++ b/target/ppc/meson.build @@ -28,7 +28,7 @@ gen = [ extra_args: ['--static-decode=decode_insn64', '--insnwidth=64']), ] -ppc_ss.add(gen) +ppc_ss.add(when: 'CONFIG_TCG', if_true: gen) ppc_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'), if_false: files('kvm-stub.c')) ppc_ss.add(when: 'CONFIG_USER_ONLY', if_true: files('user_only_helper.c')) diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c index 1f1af21f33..692d058665 100644 --- a/target/ppc/misc_helper.c +++ b/target/ppc/misc_helper.c @@ -43,6 +43,27 @@ void helper_store_dump_spr(CPUPPCState *env, uint32_t sprn) env->spr[sprn]); } +void helper_spr_core_write_generic(CPUPPCState *env, uint32_t sprn, + target_ulong val) +{ + CPUState *cs = env_cpu(env); + CPUState *ccs; + uint32_t nr_threads = cs->nr_threads; + uint32_t core_id = env->spr[SPR_PIR] & ~(nr_threads - 1); + + assert(core_id == env->spr[SPR_PIR] - env->spr[SPR_TIR]); + + if (nr_threads == 1) { + env->spr[sprn] = val; + return; + } + + THREAD_SIBLING_FOREACH(cs, ccs) { + CPUPPCState *cenv = &POWERPC_CPU(ccs)->env; + cenv->spr[sprn] = val; + } +} + void helper_spr_write_CTRL(CPUPPCState *env, uint32_t sprn, target_ulong val) { @@ -191,6 +212,10 @@ target_ulong helper_load_dpdes(CPUPPCState *env) helper_hfscr_facility_check(env, HFSCR_MSGP, "load DPDES", HFSCR_IC_MSGP); + if (!(env->flags & POWERPC_FLAG_SMT_1LPAR)) { + nr_threads = 1; /* DPDES behaves as 1-thread in LPAR-per-thread mode */ + } + if (nr_threads == 1) { if (env->pending_interrupts & PPC_INTERRUPT_DOORBELL) { dpdes = 1; @@ -222,6 +247,10 @@ void helper_store_dpdes(CPUPPCState *env, target_ulong val) helper_hfscr_facility_check(env, HFSCR_MSGP, "store DPDES", HFSCR_IC_MSGP); + if (!(env->flags & POWERPC_FLAG_SMT_1LPAR)) { + nr_threads = 1; /* DPDES behaves as 1-thread in LPAR-per-thread mode */ + } + if (val & ~(nr_threads - 1)) { qemu_log_mask(LOG_GUEST_ERROR, "Invalid DPDES register value " TARGET_FMT_lx"\n", val); diff --git a/target/ppc/spr_common.h b/target/ppc/spr_common.h index 4c0f2bed77..5995070eaf 100644 --- a/target/ppc/spr_common.h +++ b/target/ppc/spr_common.h @@ -82,6 +82,7 @@ void spr_noaccess(DisasContext *ctx, int gprn, int sprn); void spr_read_generic(DisasContext *ctx, int gprn, int sprn); void spr_write_generic(DisasContext *ctx, int sprn, int gprn); void spr_write_generic32(DisasContext *ctx, int sprn, int gprn); +void spr_core_write_generic(DisasContext *ctx, int sprn, int gprn); void spr_write_MMCR0(DisasContext *ctx, int sprn, int gprn); void spr_write_MMCR1(DisasContext *ctx, int sprn, int gprn); void spr_write_PMC(DisasContext *ctx, int sprn, int gprn); @@ -194,6 +195,8 @@ void spr_write_ebb(DisasContext *ctx, int sprn, int gprn); void spr_read_ebb_upper32(DisasContext *ctx, int gprn, int sprn); void spr_write_ebb_upper32(DisasContext *ctx, int sprn, int gprn); void spr_write_hmer(DisasContext *ctx, int sprn, int gprn); +void spr_read_tfmr(DisasContext *ctx, int gprn, int sprn); +void spr_write_tfmr(DisasContext *ctx, int sprn, int gprn); void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn); void spr_read_dexcr_ureg(DisasContext *ctx, int gprn, int sprn); #endif diff --git a/target/ppc/timebase_helper.c b/target/ppc/timebase_helper.c index b80f56af7e..08a6b47ee0 100644 --- a/target/ppc/timebase_helper.c +++ b/target/ppc/timebase_helper.c @@ -144,6 +144,19 @@ void helper_store_booke_tsr(CPUPPCState *env, target_ulong val) store_booke_tsr(env, val); } +#if defined(TARGET_PPC64) +/* POWER processor Timebase Facility */ +target_ulong helper_load_tfmr(CPUPPCState *env) +{ + return env->spr[SPR_TFMR]; +} + +void helper_store_tfmr(CPUPPCState *env, target_ulong val) +{ + env->spr[SPR_TFMR] = val; +} +#endif + /*****************************************************************************/ /* Embedded PowerPC specific helpers */ diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 372ee600b2..e6a0709066 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -246,9 +246,9 @@ static inline bool gen_serialize(DisasContext *ctx) } #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) -static inline bool gen_serialize_core(DisasContext *ctx) +static inline bool gen_serialize_core_lpar(DisasContext *ctx) { - if (ctx->flags & POWERPC_FLAG_SMT) { + if (ctx->flags & POWERPC_FLAG_SMT_1LPAR) { return gen_serialize(ctx); } @@ -438,6 +438,22 @@ void spr_write_generic32(DisasContext *ctx, int sprn, int gprn) #endif } +void spr_core_write_generic(DisasContext *ctx, int sprn, int gprn) +{ + if (!(ctx->flags & POWERPC_FLAG_SMT)) { + spr_write_generic(ctx, sprn, gprn); + return; + } + + if (!gen_serialize(ctx)) { + return; + } + + gen_helper_spr_core_write_generic(cpu_env, tcg_constant_i32(sprn), + cpu_gpr[gprn]); + spr_store_dump_spr(sprn); +} + static void spr_write_CTRL_ST(DisasContext *ctx, int sprn, int gprn) { /* This does not implement >1 thread */ @@ -451,7 +467,8 @@ static void spr_write_CTRL_ST(DisasContext *ctx, int sprn, int gprn) void spr_write_CTRL(DisasContext *ctx, int sprn, int gprn) { - if (!(ctx->flags & POWERPC_FLAG_SMT)) { + if (!(ctx->flags & POWERPC_FLAG_SMT_1LPAR)) { + /* CTRL behaves as 1-thread in LPAR-per-thread mode */ spr_write_CTRL_ST(ctx, sprn, gprn); goto out; } @@ -815,7 +832,7 @@ void spr_write_pcr(DisasContext *ctx, int sprn, int gprn) /* DPDES */ void spr_read_dpdes(DisasContext *ctx, int gprn, int sprn) { - if (!gen_serialize_core(ctx)) { + if (!gen_serialize_core_lpar(ctx)) { return; } @@ -824,7 +841,7 @@ void spr_read_dpdes(DisasContext *ctx, int gprn, int sprn) void spr_write_dpdes(DisasContext *ctx, int sprn, int gprn) { - if (!gen_serialize_core(ctx)) { + if (!gen_serialize_core_lpar(ctx)) { return; } @@ -1175,8 +1192,19 @@ void spr_write_hmer(DisasContext *ctx, int sprn, int gprn) spr_store_dump_spr(sprn); } +void spr_read_tfmr(DisasContext *ctx, int gprn, int sprn) +{ + gen_helper_load_tfmr(cpu_gpr[gprn], cpu_env); +} + +void spr_write_tfmr(DisasContext *ctx, int sprn, int gprn) +{ + gen_helper_store_tfmr(cpu_env, cpu_gpr[gprn]); +} + void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn) { + translator_io_start(&ctx->base); gen_helper_store_lpcr(cpu_env, cpu_gpr[gprn]); } #endif /* !defined(CONFIG_USER_ONLY) */ @@ -4002,6 +4030,7 @@ static void gen_doze(DisasContext *ctx) TCGv_i32 t; CHK_HV(ctx); + translator_io_start(&ctx->base); t = tcg_constant_i32(PPC_PM_DOZE); gen_helper_pminsn(cpu_env, t); /* Stop translation, as the CPU is supposed to sleep from now */ @@ -4017,6 +4046,7 @@ static void gen_nap(DisasContext *ctx) TCGv_i32 t; CHK_HV(ctx); + translator_io_start(&ctx->base); t = tcg_constant_i32(PPC_PM_NAP); gen_helper_pminsn(cpu_env, t); /* Stop translation, as the CPU is supposed to sleep from now */ @@ -4032,6 +4062,7 @@ static void gen_stop(DisasContext *ctx) TCGv_i32 t; CHK_HV(ctx); + translator_io_start(&ctx->base); t = tcg_constant_i32(PPC_PM_STOP); gen_helper_pminsn(cpu_env, t); /* Stop translation, as the CPU is supposed to sleep from now */ @@ -4047,6 +4078,7 @@ static void gen_sleep(DisasContext *ctx) TCGv_i32 t; CHK_HV(ctx); + translator_io_start(&ctx->base); t = tcg_constant_i32(PPC_PM_SLEEP); gen_helper_pminsn(cpu_env, t); /* Stop translation, as the CPU is supposed to sleep from now */ @@ -4062,6 +4094,7 @@ static void gen_rvwinkle(DisasContext *ctx) TCGv_i32 t; CHK_HV(ctx); + translator_io_start(&ctx->base); t = tcg_constant_i32(PPC_PM_RVWINKLE); gen_helper_pminsn(cpu_env, t); /* Stop translation, as the CPU is supposed to sleep from now */ @@ -4458,6 +4491,7 @@ static void gen_hrfid(DisasContext *ctx) #else /* Restore CPU state */ CHK_HV(ctx); + translator_io_start(&ctx->base); gen_helper_hrfid(cpu_env); ctx->base.is_jmp = DISAS_EXIT; #endif @@ -4469,7 +4503,6 @@ static void gen_hrfid(DisasContext *ctx) #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER #else #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL -#define POWERPC_SYSCALL_VECTORED POWERPC_EXCP_SYSCALL_VECTORED #endif static void gen_sc(DisasContext *ctx) { diff --git a/tests/avocado/ppc_powernv.py b/tests/avocado/ppc_powernv.py new file mode 100644 index 0000000000..d0e5c07bde --- /dev/null +++ b/tests/avocado/ppc_powernv.py @@ -0,0 +1,87 @@ +# Test that Linux kernel boots on ppc powernv machines and check the console +# +# Copyright (c) 2018, 2020 Red Hat, Inc. +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +from avocado.utils import archive +from avocado_qemu import QemuSystemTest +from avocado_qemu import wait_for_console_pattern + +class powernvMachine(QemuSystemTest): + + timeout = 90 + KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' + panic_message = 'Kernel panic - not syncing' + good_message = 'VFS: Cannot open root device' + + def do_test_linux_boot(self): + self.require_accelerator("tcg") + kernel_url = ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/29/Everything/ppc64le/os' + '/ppc/ppc64/vmlinuz') + kernel_hash = '3fe04abfc852b66653b8c3c897a59a689270bc77' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + self.vm.set_console() + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'console=hvc0' + self.vm.add_args('-kernel', kernel_path, + '-append', kernel_command_line) + self.vm.launch() + + def test_linux_boot(self): + """ + :avocado: tags=arch:ppc64 + :avocado: tags=machine:powernv + :avocado: tags=accel:tcg + """ + + self.do_test_linux_boot() + console_pattern = 'VFS: Cannot open root device' + wait_for_console_pattern(self, console_pattern, self.panic_message) + + def test_linux_smp_boot(self): + """ + :avocado: tags=arch:ppc64 + :avocado: tags=machine:powernv + :avocado: tags=accel:tcg + """ + + self.vm.add_args('-smp', '4') + self.do_test_linux_boot() + console_pattern = 'smp: Brought up 1 node, 4 CPUs' + wait_for_console_pattern(self, console_pattern, self.panic_message) + wait_for_console_pattern(self, self.good_message, self.panic_message) + + def test_linux_smt_boot(self): + """ + :avocado: tags=arch:ppc64 + :avocado: tags=machine:powernv + :avocado: tags=accel:tcg + """ + + self.vm.add_args('-smp', '4,threads=4') + self.do_test_linux_boot() + console_pattern = 'CPU maps initialized for 4 threads per core' + wait_for_console_pattern(self, console_pattern, self.panic_message) + console_pattern = 'smp: Brought up 1 node, 4 CPUs' + wait_for_console_pattern(self, console_pattern, self.panic_message) + wait_for_console_pattern(self, self.good_message, self.panic_message) + + def test_linux_big_boot(self): + """ + :avocado: tags=arch:ppc64 + :avocado: tags=machine:powernv + :avocado: tags=accel:tcg + """ + + self.vm.add_args('-smp', '16,threads=4,cores=2,sockets=2') + + # powernv does not support NUMA + self.do_test_linux_boot() + console_pattern = 'CPU maps initialized for 4 threads per core' + wait_for_console_pattern(self, console_pattern, self.panic_message) + console_pattern = 'smp: Brought up 2 nodes, 16 CPUs' + wait_for_console_pattern(self, console_pattern, self.panic_message) + wait_for_console_pattern(self, self.good_message, self.panic_message) diff --git a/tests/avocado/replay_kernel.py b/tests/avocado/replay_kernel.py index fe1e901f4b..79c607b0e7 100644 --- a/tests/avocado/replay_kernel.py +++ b/tests/avocado/replay_kernel.py @@ -259,6 +259,23 @@ class ReplayKernelNormal(ReplayKernelBase): console_pattern = 'Kernel command line: %s' % kernel_command_line self.run_rr(kernel_path, kernel_command_line, console_pattern) + def test_ppc64_powernv(self): + """ + :avocado: tags=arch:ppc64 + :avocado: tags=machine:powernv + :avocado: tags=accel:tcg + """ + kernel_url = ('https://archives.fedoraproject.org/pub/archive' + '/fedora-secondary/releases/29/Everything/ppc64le/os' + '/ppc/ppc64/vmlinuz') + kernel_hash = '3fe04abfc852b66653b8c3c897a59a689270bc77' + kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) + + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + \ + 'console=tty0 console=hvc0' + console_pattern = 'VFS: Cannot open root device' + self.run_rr(kernel_path, kernel_command_line, console_pattern) + def test_m68k_q800(self): """ :avocado: tags=arch:m68k diff --git a/tests/qtest/pnv-xscom-test.c b/tests/qtest/pnv-xscom-test.c index 2c46d5cf6d..8a5ac11037 100644 --- a/tests/qtest/pnv-xscom-test.c +++ b/tests/qtest/pnv-xscom-test.c @@ -15,6 +15,7 @@ typedef enum PnvChipType { PNV_CHIP_POWER8, /* AKA Venice */ PNV_CHIP_POWER8NVL, /* AKA Naples */ PNV_CHIP_POWER9, /* AKA Nimbus */ + PNV_CHIP_POWER10, } PnvChipType; typedef struct PnvChip { @@ -46,13 +47,22 @@ static const PnvChip pnv_chips[] = { .cfam_id = 0x220d104900008000ull, .first_core = 0x0, }, + { + .chip_type = PNV_CHIP_POWER10, + .cpu_model = "POWER10", + .xscom_base = 0x000603fc00000000ull, + .cfam_id = 0x120da04900008000ull, + .first_core = 0x0, + }, }; static uint64_t pnv_xscom_addr(const PnvChip *chip, uint32_t pcba) { uint64_t addr = chip->xscom_base; - if (chip->chip_type == PNV_CHIP_POWER9) { + if (chip->chip_type == PNV_CHIP_POWER10) { + addr |= ((uint64_t) pcba << 3); + } else if (chip->chip_type == PNV_CHIP_POWER9) { addr |= ((uint64_t) pcba << 3); } else { addr |= (((uint64_t) pcba << 4) & ~0xffull) | @@ -82,6 +92,8 @@ static void test_cfam_id(const void *data) if (chip->chip_type == PNV_CHIP_POWER9) { machine = "powernv9"; + } else if (chip->chip_type == PNV_CHIP_POWER10) { + machine = "powernv10"; } qts = qtest_initf("-M %s -accel tcg -cpu %s", @@ -96,23 +108,36 @@ static void test_cfam_id(const void *data) (PNV_XSCOM_EX_CORE_BASE | ((uint64_t)(core) << 24)) #define PNV_XSCOM_P9_EC_BASE(core) \ ((uint64_t)(((core) & 0x1F) + 0x20) << 24) +#define PNV_XSCOM_P10_EC_BASE(core) \ + ((uint64_t)((((core) & ~0x3) + 0x20) << 24) + 0x20000 + \ + (0x1000 << (3 - (core & 0x3)))) #define PNV_XSCOM_EX_DTS_RESULT0 0x50000 static void test_xscom_core(QTestState *qts, const PnvChip *chip) { - uint32_t first_core_dts0 = PNV_XSCOM_EX_DTS_RESULT0; - uint64_t dts0; + if (chip->chip_type == PNV_CHIP_POWER10) { + uint32_t first_core_thread_state = + PNV_XSCOM_P10_EC_BASE(chip->first_core) + 0x412; + uint64_t thread_state; + + thread_state = pnv_xscom_read(qts, chip, first_core_thread_state); - if (chip->chip_type != PNV_CHIP_POWER9) { - first_core_dts0 |= PNV_XSCOM_EX_BASE(chip->first_core); + g_assert_cmphex(thread_state, ==, 0); } else { - first_core_dts0 |= PNV_XSCOM_P9_EC_BASE(chip->first_core); - } + uint32_t first_core_dts0 = PNV_XSCOM_EX_DTS_RESULT0; + uint64_t dts0; - dts0 = pnv_xscom_read(qts, chip, first_core_dts0); + if (chip->chip_type == PNV_CHIP_POWER9) { + first_core_dts0 |= PNV_XSCOM_P9_EC_BASE(chip->first_core); + } else { /* POWER8 */ + first_core_dts0 |= PNV_XSCOM_EX_BASE(chip->first_core); + } - g_assert_cmphex(dts0, ==, 0x26f024f023f0000ull); + dts0 = pnv_xscom_read(qts, chip, first_core_dts0); + + g_assert_cmphex(dts0, ==, 0x26f024f023f0000ull); + } } static void test_core(const void *data) @@ -123,6 +148,8 @@ static void test_core(const void *data) if (chip->chip_type == PNV_CHIP_POWER9) { machine = "powernv9"; + } else if (chip->chip_type == PNV_CHIP_POWER10) { + machine = "powernv10"; } qts = qtest_initf("-M %s -accel tcg -cpu %s", |