diff --git a/hw/misc/macio/mac_dbdma.c b/hw/misc/macio/mac_dbdma.c index f116f9c36d448b9f7ddd305f9933479924e02d49..15452b9a28331e2abfea7f6c1cd7ead43f38ccf8 100644 --- a/hw/misc/macio/mac_dbdma.c +++ b/hw/misc/macio/mac_dbdma.c @@ -45,14 +45,22 @@ #include "sysemu/dma.h" /* debug DBDMA */ -//#define DEBUG_DBDMA - -#ifdef DEBUG_DBDMA -#define DBDMA_DPRINTF(fmt, ...) \ - do { printf("DBDMA: " fmt , ## __VA_ARGS__); } while (0) -#else -#define DBDMA_DPRINTF(fmt, ...) -#endif +#define DEBUG_DBDMA 0 +#define DEBUG_DBDMA_CHANMASK ((1ull << DBDMA_CHANNELS) - 1) + +#define DBDMA_DPRINTF(fmt, ...) do { \ + if (DEBUG_DBDMA) { \ + printf("DBDMA: " fmt , ## __VA_ARGS__); \ + } \ +} while (0); + +#define DBDMA_DPRINTFCH(ch, fmt, ...) do { \ + if (DEBUG_DBDMA) { \ + if ((1ul << (ch)->channel) & DEBUG_DBDMA_CHANMASK) { \ + printf("DBDMA[%02x]: " fmt , (ch)->channel, ## __VA_ARGS__); \ + } \ + } \ +} while (0); /* */ @@ -62,7 +70,7 @@ static DBDMAState *dbdma_from_ch(DBDMA_channel *ch) return container_of(ch, DBDMAState, channels[ch->channel]); } -#ifdef DEBUG_DBDMA +#if DEBUG_DBDMA static void dump_dbdma_cmd(dbdma_cmd *cmd) { printf("dbdma_cmd %p\n", cmd); @@ -80,26 +88,26 @@ static void dump_dbdma_cmd(dbdma_cmd *cmd) #endif static void dbdma_cmdptr_load(DBDMA_channel *ch) { - DBDMA_DPRINTF("dbdma_cmdptr_load 0x%08x\n", - ch->regs[DBDMA_CMDPTR_LO]); + DBDMA_DPRINTFCH(ch, "dbdma_cmdptr_load 0x%08x\n", + ch->regs[DBDMA_CMDPTR_LO]); dma_memory_read(&address_space_memory, ch->regs[DBDMA_CMDPTR_LO], &ch->current, sizeof(dbdma_cmd)); } static void dbdma_cmdptr_save(DBDMA_channel *ch) { - DBDMA_DPRINTF("dbdma_cmdptr_save 0x%08x\n", - ch->regs[DBDMA_CMDPTR_LO]); - DBDMA_DPRINTF("xfer_status 0x%08x res_count 0x%04x\n", - le16_to_cpu(ch->current.xfer_status), - le16_to_cpu(ch->current.res_count)); + DBDMA_DPRINTFCH(ch, "dbdma_cmdptr_save 0x%08x\n", + ch->regs[DBDMA_CMDPTR_LO]); + DBDMA_DPRINTFCH(ch, "xfer_status 0x%08x res_count 0x%04x\n", + le16_to_cpu(ch->current.xfer_status), + le16_to_cpu(ch->current.res_count)); dma_memory_write(&address_space_memory, ch->regs[DBDMA_CMDPTR_LO], &ch->current, sizeof(dbdma_cmd)); } static void kill_channel(DBDMA_channel *ch) { - DBDMA_DPRINTF("kill_channel\n"); + DBDMA_DPRINTFCH(ch, "kill_channel\n"); ch->regs[DBDMA_STATUS] |= DEAD; ch->regs[DBDMA_STATUS] &= ~ACTIVE; @@ -115,7 +123,7 @@ static void conditional_interrupt(DBDMA_channel *ch) uint32_t status; int cond; - DBDMA_DPRINTF("%s\n", __func__); + DBDMA_DPRINTFCH(ch, "%s\n", __func__); intr = le16_to_cpu(current->command) & INTR_MASK; @@ -124,7 +132,7 @@ static void conditional_interrupt(DBDMA_channel *ch) return; case INTR_ALWAYS: /* always interrupt */ qemu_irq_raise(ch->irq); - DBDMA_DPRINTF("%s: raise\n", __func__); + DBDMA_DPRINTFCH(ch, "%s: raise\n", __func__); return; } @@ -139,13 +147,13 @@ static void conditional_interrupt(DBDMA_channel *ch) case INTR_IFSET: /* intr if condition bit is 1 */ if (cond) { qemu_irq_raise(ch->irq); - DBDMA_DPRINTF("%s: raise\n", __func__); + DBDMA_DPRINTFCH(ch, "%s: raise\n", __func__); } return; case INTR_IFCLR: /* intr if condition bit is 0 */ if (!cond) { qemu_irq_raise(ch->irq); - DBDMA_DPRINTF("%s: raise\n", __func__); + DBDMA_DPRINTFCH(ch, "%s: raise\n", __func__); } return; } @@ -159,7 +167,7 @@ static int conditional_wait(DBDMA_channel *ch) uint32_t status; int cond; - DBDMA_DPRINTF("conditional_wait\n"); + DBDMA_DPRINTFCH(ch, "conditional_wait\n"); wait = le16_to_cpu(current->command) & WAIT_MASK; @@ -205,7 +213,7 @@ static void branch(DBDMA_channel *ch) { dbdma_cmd *current = &ch->current; - ch->regs[DBDMA_CMDPTR_LO] = current->cmd_dep; + ch->regs[DBDMA_CMDPTR_LO] = le32_to_cpu(current->cmd_dep); ch->regs[DBDMA_STATUS] |= BT; dbdma_cmdptr_load(ch); } @@ -218,7 +226,7 @@ static void conditional_branch(DBDMA_channel *ch) uint32_t status; int cond; - DBDMA_DPRINTF("conditional_branch\n"); + DBDMA_DPRINTFCH(ch, "conditional_branch\n"); /* check if we must branch */ @@ -263,7 +271,7 @@ static void dbdma_end(DBDMA_io *io) DBDMA_channel *ch = io->channel; dbdma_cmd *current = &ch->current; - DBDMA_DPRINTF("%s\n", __func__); + DBDMA_DPRINTFCH(ch, "%s\n", __func__); if (conditional_wait(ch)) goto wait; @@ -289,13 +297,13 @@ wait: static void start_output(DBDMA_channel *ch, int key, uint32_t addr, uint16_t req_count, int is_last) { - DBDMA_DPRINTF("start_output\n"); + DBDMA_DPRINTFCH(ch, "start_output\n"); /* KEY_REGS, KEY_DEVICE and KEY_STREAM * are not implemented in the mac-io chip */ - DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key); + DBDMA_DPRINTFCH(ch, "addr 0x%x key 0x%x\n", addr, key); if (!addr || key > KEY_STREAM3) { kill_channel(ch); return; @@ -315,13 +323,13 @@ static void start_output(DBDMA_channel *ch, int key, uint32_t addr, static void start_input(DBDMA_channel *ch, int key, uint32_t addr, uint16_t req_count, int is_last) { - DBDMA_DPRINTF("start_input\n"); + DBDMA_DPRINTFCH(ch, "start_input\n"); /* KEY_REGS, KEY_DEVICE and KEY_STREAM * are not implemented in the mac-io chip */ - DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key); + DBDMA_DPRINTFCH(ch, "addr 0x%x key 0x%x\n", addr, key); if (!addr || key > KEY_STREAM3) { kill_channel(ch); return; @@ -342,9 +350,8 @@ static void load_word(DBDMA_channel *ch, int key, uint32_t addr, uint16_t len) { dbdma_cmd *current = &ch->current; - uint32_t val; - DBDMA_DPRINTF("load_word\n"); + DBDMA_DPRINTFCH(ch, "load_word %d bytes, addr=%08x\n", len, addr); /* only implements KEY_SYSTEM */ @@ -354,14 +361,7 @@ static void load_word(DBDMA_channel *ch, int key, uint32_t addr, return; } - dma_memory_read(&address_space_memory, addr, &val, len); - - if (len == 2) - val = (val << 16) | (current->cmd_dep & 0x0000ffff); - else if (len == 1) - val = (val << 24) | (current->cmd_dep & 0x00ffffff); - - current->cmd_dep = val; + dma_memory_read(&address_space_memory, addr, ¤t->cmd_dep, len); if (conditional_wait(ch)) goto wait; @@ -381,9 +381,9 @@ static void store_word(DBDMA_channel *ch, int key, uint32_t addr, uint16_t len) { dbdma_cmd *current = &ch->current; - uint32_t val; - DBDMA_DPRINTF("store_word\n"); + DBDMA_DPRINTFCH(ch, "store_word %d bytes, addr=%08x pa=%x\n", + len, addr, le32_to_cpu(current->cmd_dep)); /* only implements KEY_SYSTEM */ @@ -393,13 +393,7 @@ static void store_word(DBDMA_channel *ch, int key, uint32_t addr, return; } - val = current->cmd_dep; - if (len == 2) - val >>= 16; - else if (len == 1) - val >>= 24; - - dma_memory_write(&address_space_memory, addr, &val, len); + dma_memory_write(&address_space_memory, addr, ¤t->cmd_dep, len); if (conditional_wait(ch)) goto wait; @@ -446,7 +440,7 @@ static void channel_run(DBDMA_channel *ch) uint16_t req_count; uint32_t phy_addr; - DBDMA_DPRINTF("channel_run\n"); + DBDMA_DPRINTFCH(ch, "channel_run\n"); dump_dbdma_cmd(current); /* clear WAKE flag at command fetch */ @@ -540,9 +534,9 @@ static void DBDMA_run_bh(void *opaque) { DBDMAState *s = opaque; - DBDMA_DPRINTF("DBDMA_run_bh\n"); - + DBDMA_DPRINTF("-> DBDMA_run_bh\n"); DBDMA_run(s); + DBDMA_DPRINTF("<- DBDMA_run_bh\n"); } void DBDMA_kick(DBDMAState *dbdma) @@ -557,7 +551,7 @@ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, DBDMAState *s = dbdma; DBDMA_channel *ch = &s->channels[nchan]; - DBDMA_DPRINTF("DBDMA_register_channel 0x%x\n", nchan); + DBDMA_DPRINTFCH(ch, "DBDMA_register_channel 0x%x\n", nchan); assert(rw); assert(flush); @@ -601,7 +595,7 @@ dbdma_control_write(DBDMA_channel *ch) status &= ~FLUSH; } - DBDMA_DPRINTF(" status 0x%08x\n", status); + DBDMA_DPRINTFCH(ch, " status 0x%08x\n", status); ch->regs[DBDMA_STATUS] = status; @@ -618,10 +612,10 @@ static void dbdma_write(void *opaque, hwaddr addr, DBDMA_channel *ch = &s->channels[channel]; int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2; - DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08"PRIx64"\n", - addr, value); - DBDMA_DPRINTF("channel 0x%x reg 0x%x\n", - (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg); + DBDMA_DPRINTFCH(ch, "writel 0x" TARGET_FMT_plx " <= 0x%08"PRIx64"\n", + addr, value); + DBDMA_DPRINTFCH(ch, "channel 0x%x reg 0x%x\n", + (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg); /* cmdptr cannot be modified if channel is ACTIVE */ @@ -672,9 +666,9 @@ static uint64_t dbdma_read(void *opaque, hwaddr addr, value = ch->regs[reg]; - DBDMA_DPRINTF("readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value); - DBDMA_DPRINTF("channel 0x%x reg 0x%x\n", - (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg); + DBDMA_DPRINTFCH(ch, "readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value); + DBDMA_DPRINTFCH(ch, "channel 0x%x reg 0x%x\n", + (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg); switch(reg) { case DBDMA_CONTROL: @@ -784,13 +778,24 @@ static void dbdma_unassigned_rw(DBDMA_io *io) DBDMA_channel *ch = io->channel; qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n", __func__, ch->channel); + ch->io.processing = false; } static void dbdma_unassigned_flush(DBDMA_io *io) { DBDMA_channel *ch = io->channel; + dbdma_cmd *current = &ch->current; + uint16_t cmd; qemu_log_mask(LOG_GUEST_ERROR, "%s: use of unassigned channel %d\n", __func__, ch->channel); + + cmd = le16_to_cpu(current->command) & COMMAND_MASK; + if (cmd == OUTPUT_MORE || cmd == OUTPUT_LAST || + cmd == INPUT_MORE || cmd == INPUT_LAST) { + current->xfer_status = cpu_to_le16(ch->regs[DBDMA_STATUS] | FLUSH); + current->res_count = cpu_to_le16(io->len); + dbdma_cmdptr_save(ch); + } } void* DBDMA_init (MemoryRegion **dbdma_mem) diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index 9347f0741ed5398383a2a49128a3c1bada1091f2..4bfc96bd5a6798fdf7c3d7396eb5bb8756732d65 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -126,14 +126,23 @@ static void spapr_core_release(DeviceState *dev, void *opaque) void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { - sPAPRCPUCore *core = SPAPR_CPU_CORE(OBJECT(dev)); - PowerPCCPU *cpu = POWERPC_CPU(core->threads); - int id = ppc_get_vcpu_dt_id(cpu); + sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); + CPUCore *cc = CPU_CORE(dev); sPAPRDRConnector *drc = - spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, id); + spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, cc->core_id); sPAPRDRConnectorClass *drck; Error *local_err = NULL; + int smt = kvmppc_smt_threads(); + int index = cc->core_id / smt; + int spapr_max_cores = max_cpus / smp_threads; + int i; + for (i = spapr_max_cores - 1; i > index; i--) { + if (spapr->cores[i]) { + error_setg(errp, "core-id %d should be removed first", i * smt); + return; + } + } g_assert(drc); drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); @@ -216,7 +225,7 @@ void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(OBJECT(hotplug_dev)); sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); int spapr_max_cores = max_cpus / smp_threads; - int index; + int index, i; int smt = kvmppc_smt_threads(); Error *local_err = NULL; CPUCore *cc = CPU_CORE(dev); @@ -254,6 +263,14 @@ void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, goto out; } + for (i = 0; i < index; i++) { + if (!spapr->cores[i]) { + error_setg(&local_err, "core-id %d should be added first", + i * smt); + goto out; + } + } + out: g_free(base_core_type); error_propagate(errp, local_err); diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c index 0af342332c71a81c5cd068f38dae056cf6e4d3fe..7443d348d97e7dd1800284d7e2535cc442d7c111 100644 --- a/hw/vfio/spapr.c +++ b/hw/vfio/spapr.c @@ -177,7 +177,6 @@ int vfio_spapr_create_window(VFIOContainer *container, error_report("Host doesn't support DMA window at %"HWADDR_PRIx", must be %"PRIx64, section->offset_within_address_space, (uint64_t)create.start_addr); - ioctl(container->fd, VFIO_IOMMU_SPAPR_TCE_REMOVE, &remove); return -EINVAL; } trace_vfio_spapr_create_window(create.page_shift, diff --git a/target-ppc/helper_regs.h b/target-ppc/helper_regs.h index 8d388289363694301d8cee0e4574b7ff8f3ba78e..3d279f1d8aad8b769138103888cf2037cd776e06 100644 --- a/target-ppc/helper_regs.h +++ b/target-ppc/helper_regs.h @@ -41,17 +41,19 @@ static inline void hreg_swap_gpr_tgpr(CPUPPCState *env) static inline void hreg_compute_mem_idx(CPUPPCState *env) { - /* This is our encoding for server processors + /* This is our encoding for server processors. The architecture + * specifies that there is no such thing as userspace with + * translation off, however it appears that MacOS does it and + * some 32-bit CPUs support it. Weird... * * 0 = Guest User space virtual mode * 1 = Guest Kernel space virtual mode - * 2 = Guest Kernel space real mode - * 3 = HV User space virtual mode - * 4 = HV Kernel space virtual mode - * 5 = HV Kernel space real mode - * - * The combination PR=1 IR&DR=0 is invalid, we will treat - * it as IR=DR=1 + * 2 = Guest User space real mode + * 3 = Guest Kernel space real mode + * 4 = HV User space virtual mode + * 5 = HV Kernel space virtual mode + * 6 = HV User space real mode + * 7 = HV Kernel space real mode * * For BookE, we need 8 MMU modes as follow: * @@ -71,20 +73,11 @@ static inline void hreg_compute_mem_idx(CPUPPCState *env) env->immu_idx += msr_gs ? 4 : 0; env->dmmu_idx += msr_gs ? 4 : 0; } else { - /* First calucalte a base value independent of HV */ - if (msr_pr != 0) { - /* User space, ignore IR and DR */ - env->immu_idx = env->dmmu_idx = 0; - } else { - /* Kernel, setup a base I/D value */ - env->immu_idx = msr_ir ? 1 : 2; - env->dmmu_idx = msr_dr ? 1 : 2; - } - /* Then offset it for HV */ - if (msr_hv) { - env->immu_idx += 3; - env->dmmu_idx += 3; - } + env->immu_idx = env->dmmu_idx = msr_pr ? 0 : 1; + env->immu_idx += msr_ir ? 0 : 2; + env->dmmu_idx += msr_dr ? 0 : 2; + env->immu_idx += msr_hv ? 4 : 0; + env->dmmu_idx += msr_hv ? 4 : 0; } } @@ -136,8 +129,13 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value, /* Change the exception prefix on PowerPC 601 */ env->excp_prefix = ((value >> MSR_EP) & 1) * 0xFFF00000; } - /* If PR=1 then EE, IR and DR must be 1 */ - if ((value >> MSR_PR) & 1) { + /* If PR=1 then EE, IR and DR must be 1 + * + * Note: We only enforce this on 64-bit processors. It appears that + * 32-bit implementations supports PR=1 and EE/DR/IR=0 and MacOS + * exploits it. + */ + if ((env->insns_flags & PPC_64B) && ((value >> MSR_PR) & 1)) { value |= (1 << MSR_EE) | (1 << MSR_DR) | (1 << MSR_IR); } #endif diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index 884d564e0f17edb027ef6d46ecac9e8f97a549bf..7a8f5559d986556afbe29be4d5a20d9f5c1de99f 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -389,12 +389,16 @@ static long getrampagesize(void) object_child_foreach(memdev_root, find_max_supported_pagesize, &hpsize); - if (hpsize == LONG_MAX) { + if (hpsize == LONG_MAX || hpsize == getpagesize()) { return getpagesize(); } - if (nb_numa_nodes == 0 && hpsize > getpagesize()) { - /* No NUMA nodes and normal RAM without -mem-path ==> no huge pages! */ + /* If NUMA is disabled or the NUMA nodes are not backed with a + * memory-backend, then there is at least one node using "normal" + * RAM. And since normal RAM has not been configured with "-mem-path" + * (what we've checked earlier here already), we can not use huge pages! + */ + if (nb_numa_nodes == 0 || numa_info[0].node_memdev == NULL) { static bool warned; if (!warned) { error_report("Huge page support disabled (n/a for main memory)."); diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c index 82c2186bcf7d5aa2b33ea89cd9a13e3908dad48f..5de1358d1cfa1dc9b54c42d34883be827ea2e7ae 100644 --- a/target-ppc/mmu-hash64.c +++ b/target-ppc/mmu-hash64.c @@ -24,7 +24,6 @@ #include "exec/helper-proto.h" #include "qemu/error-report.h" #include "sysemu/kvm.h" -#include "qemu/error-report.h" #include "kvm_ppc.h" #include "mmu-hash64.h" #include "exec/log.h" @@ -479,7 +478,7 @@ static unsigned hpte_page_shift(const struct ppc_one_seg_page_size *sps, mask = ((1ULL << ps->page_shift) - 1) & HPTE64_R_RPN; - if ((pte1 & mask) == (ps->pte_enc << HPTE64_R_RPN_SHIFT)) { + if ((pte1 & mask) == ((uint64_t)ps->pte_enc << HPTE64_R_RPN_SHIFT)) { return ps->page_shift; } } diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 7cb784262cfbd1937234dbc84f3dbbc954dfae0f..5ecafc7b8b45a6f5f91e346ec3e69e10ef832ffd 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -8446,8 +8446,8 @@ static void powerpc_get_compat(Object *obj, Visitor *v, const char *name, case 0: break; default: - error_setg(errp, "Internal error: compat is set to %x", - max_compat ? *max_compat : -1); + error_report("Internal error: compat is set to %x", *max_compat); + abort(); break; }