From a3cfa18eb075c7ef78358ca1956fe7b01caa1724 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 29 Oct 2012 17:24:57 +0000 Subject: [PATCH 1/5] Revert "PPC: pseries: Remove hack for PIO window" This reverts commit a178274efabcbbc5d44805b51def874e47051325. Contrary to that commit's message, the users of old_portio are not all gone. In particular VGA still uses it via portio_list_add(). Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr_pci.c | 44 +++++++++++++++++++++++++++++++++++++++++++- hw/spapr_pci.h | 2 +- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index c2c3079d21..a08ed11166 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -439,6 +439,43 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level) qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level); } +static uint64_t spapr_io_read(void *opaque, hwaddr addr, + unsigned size) +{ + switch (size) { + case 1: + return cpu_inb(addr); + case 2: + return cpu_inw(addr); + case 4: + return cpu_inl(addr); + } + assert(0); +} + +static void spapr_io_write(void *opaque, hwaddr addr, + uint64_t data, unsigned size) +{ + switch (size) { + case 1: + cpu_outb(addr, data); + return; + case 2: + cpu_outw(addr, data); + return; + case 4: + cpu_outl(addr, data); + return; + } + assert(0); +} + +static const MemoryRegionOps spapr_io_ops = { + .endianness = DEVICE_LITTLE_ENDIAN, + .read = spapr_io_read, + .write = spapr_io_write +}; + /* * MSI/MSIX memory region implementation. * The handler handles both MSI and MSIX. @@ -508,9 +545,14 @@ static int spapr_phb_init(SysBusDevice *s) * old_portion are updated */ sprintf(namebuf, "%s.io", sphb->dtbusname); memory_region_init(&sphb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE); + /* FIXME: fix to support multiple PHBs */ + memory_region_add_subregion(get_system_io(), 0, &sphb->iospace); + sprintf(namebuf, "%s.io-alias", sphb->dtbusname); + memory_region_init_io(&sphb->iowindow, &spapr_io_ops, sphb, + namebuf, SPAPR_PCI_IO_WIN_SIZE); memory_region_add_subregion(get_system_memory(), sphb->io_win_addr, - &sphb->iospace); + &sphb->iowindow); /* As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors, * we need to allocate some memory to catch those writes coming diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index a77d7d5448..e307ac8035 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -44,7 +44,7 @@ typedef struct sPAPRPHBState { MemoryRegion memspace, iospace; hwaddr mem_win_addr, mem_win_size, io_win_addr, io_win_size; hwaddr msi_win_addr; - MemoryRegion memwindow, msiwindow; + MemoryRegion memwindow, iowindow, msiwindow; uint32_t dma_liobn; uint64_t dma_window_start; From ac7d12ba256b7c9d4e122d0d6877e2312d6c19ed Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 29 Oct 2012 17:24:58 +0000 Subject: [PATCH 2/5] target-ppc: Rework storage of VPA registration state We change the storage of the VPA information to explicitly use fixed size integer types which will make life easier for syncing this data with KVM, which we will need in future. Signed-off-by: David Gibson [agraf: fix commit message] Signed-off-by: Alexander Graf --- target-ppc/cpu.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 286f42a808..e603d9f936 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -1045,9 +1045,9 @@ struct CPUPPCState { #endif #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) - hwaddr vpa_addr; - hwaddr slb_shadow_addr, slb_shadow_size; - hwaddr dtl_addr, dtl_size; + uint64_t vpa_addr; + uint64_t slb_shadow_addr, slb_shadow_size; + uint64_t dtl_addr, dtl_size; #endif /* TARGET_PPC64 */ int error_code; From 3030442054e04b2538016920f0da6e94743f48be Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 29 Oct 2012 17:24:59 +0000 Subject: [PATCH 3/5] target-ppc: Extend FPU state for newer POWER CPUs This patch adds some extra FPU state to CPUPPCState. Specifically, fpscr is extended to a target_ulong bits, since some recent (64 bit) CPUs now have more status bits than fit inside 32 bits. Also, we add the 32 VSR registers present on CPUs with VSX (these extend the standard FP regs, which together with the Altivec/VMX registers form a 64 x 128bit register file for VSX). We don't actually support the instructions using these extra registers in TCG yet, but we still need a place to store the state so we can sync it with KVM and savevm/loadvm it. This patch updates the savevm code to not fail on the extended state, but also does not actually save it - that's a project for another patch. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- target-ppc/cpu.h | 4 +++- target-ppc/machine.c | 8 ++++++-- target-ppc/translate.c | 29 ++++++++++++++++++----------- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index e603d9f936..380a8d2926 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -963,7 +963,7 @@ struct CPUPPCState { /* floating point registers */ float64 fpr[32]; /* floating point status and control register */ - uint32_t fpscr; + target_ulong fpscr; /* Next instruction pointer */ target_ulong nip; @@ -1014,6 +1014,8 @@ struct CPUPPCState { /* Altivec registers */ ppc_avr_t avr[32]; uint32_t vscr; + /* VSX registers */ + uint64_t vsr[32]; /* SPE registers */ uint64_t spe_acc; uint32_t spe_fscr; diff --git a/target-ppc/machine.c b/target-ppc/machine.c index 21ce7575e3..5e7bc00e26 100644 --- a/target-ppc/machine.c +++ b/target-ppc/machine.c @@ -6,6 +6,7 @@ void cpu_save(QEMUFile *f, void *opaque) { CPUPPCState *env = (CPUPPCState *)opaque; unsigned int i, j; + uint32_t fpscr; for (i = 0; i < 32; i++) qemu_put_betls(f, &env->gpr[i]); @@ -30,7 +31,8 @@ void cpu_save(QEMUFile *f, void *opaque) u.d = env->fpr[i]; qemu_put_be64(f, u.l); } - qemu_put_be32s(f, &env->fpscr); + fpscr = env->fpscr; + qemu_put_be32s(f, &fpscr); qemu_put_sbe32s(f, &env->access_type); #if defined(TARGET_PPC64) qemu_put_betls(f, &env->asr); @@ -90,6 +92,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) CPUPPCState *env = (CPUPPCState *)opaque; unsigned int i, j; target_ulong sdr1; + uint32_t fpscr; for (i = 0; i < 32; i++) qemu_get_betls(f, &env->gpr[i]); @@ -114,7 +117,8 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) u.l = qemu_get_be64(f); env->fpr[i] = u.d; } - qemu_get_be32s(f, &env->fpscr); + qemu_get_be32s(f, &fpscr); + env->fpscr = fpscr; qemu_get_sbe32s(f, &env->access_type); #if defined(TARGET_PPC64) qemu_get_betls(f, &env->asr); diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 1042268ecf..56725e6a61 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -68,7 +68,7 @@ static TCGv cpu_cfar; #endif static TCGv cpu_xer; static TCGv cpu_reserve; -static TCGv_i32 cpu_fpscr; +static TCGv cpu_fpscr; static TCGv_i32 cpu_access_type; #include "gen-icount.h" @@ -163,8 +163,8 @@ void ppc_translate_init(void) offsetof(CPUPPCState, reserve_addr), "reserve_addr"); - cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0, - offsetof(CPUPPCState, fpscr), "fpscr"); + cpu_fpscr = tcg_global_mem_new(TCG_AREG0, + offsetof(CPUPPCState, fpscr), "fpscr"); cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUPPCState, access_type), "access_type"); @@ -2302,6 +2302,7 @@ GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT); /* mcrfs */ static void gen_mcrfs(DisasContext *ctx) { + TCGv tmp = tcg_temp_new(); int bfa; if (unlikely(!ctx->fpu_enabled)) { @@ -2309,9 +2310,11 @@ static void gen_mcrfs(DisasContext *ctx) return; } bfa = 4 * (7 - crfS(ctx->opcode)); - tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_fpscr, bfa); + tcg_gen_shri_tl(tmp, cpu_fpscr, bfa); + tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp); + tcg_temp_free(tmp); tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf); - tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(0xF << bfa)); + tcg_gen_andi_tl(cpu_fpscr, cpu_fpscr, ~(0xF << bfa)); } /* mffs */ @@ -2322,7 +2325,7 @@ static void gen_mffs(DisasContext *ctx) return; } gen_reset_fpstatus(); - tcg_gen_extu_i32_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr); + tcg_gen_extu_tl_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr); gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0); } @@ -2346,7 +2349,8 @@ static void gen_mtfsb0(DisasContext *ctx) tcg_temp_free_i32(t0); } if (unlikely(Rc(ctx->opcode) != 0)) { - tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX); + tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); + tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); } } @@ -2371,7 +2375,8 @@ static void gen_mtfsb1(DisasContext *ctx) tcg_temp_free_i32(t0); } if (unlikely(Rc(ctx->opcode) != 0)) { - tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX); + tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); + tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); } /* We can raise a differed exception */ gen_helper_float_check_status(cpu_env); @@ -2397,7 +2402,8 @@ static void gen_mtfsf(DisasContext *ctx) gen_helper_store_fpscr(cpu_env, cpu_fpr[rB(ctx->opcode)], t0); tcg_temp_free_i32(t0); if (unlikely(Rc(ctx->opcode) != 0)) { - tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX); + tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); + tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); } /* We can raise a differed exception */ gen_helper_float_check_status(cpu_env); @@ -2425,7 +2431,8 @@ static void gen_mtfsfi(DisasContext *ctx) tcg_temp_free_i64(t0); tcg_temp_free_i32(t1); if (unlikely(Rc(ctx->opcode) != 0)) { - tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX); + tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr); + tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX); } /* We can raise a differed exception */ gen_helper_float_check_status(cpu_env); @@ -9463,7 +9470,7 @@ void cpu_dump_state (CPUPPCState *env, FILE *f, fprintf_function cpu_fprintf, if ((i & (RFPL - 1)) == (RFPL - 1)) cpu_fprintf(f, "\n"); } - cpu_fprintf(f, "FPSCR %08x\n", env->fpscr); + cpu_fprintf(f, "FPSCR " TARGET_FMT_lx "\n", env->fpscr); #if !defined(CONFIG_USER_ONLY) cpu_fprintf(f, " SRR0 " TARGET_FMT_lx " SRR1 " TARGET_FMT_lx " PVR " TARGET_FMT_lx " VRSAVE " TARGET_FMT_lx "\n", From bf0175de6c76779d4c8b0606de7bd2a5a0b87c7a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 29 Oct 2012 17:25:00 +0000 Subject: [PATCH 4/5] pseries: Clean up inconsistent variable name in xics.c Throughout xics.c 'nr' is used to refer to a global interrupt number, and 'server' is used to refer to an interrupt server number (i.e. CPU number). Except in icp_set_mfrr(), where 'nr' is used as a server number. Fix this confusing inconsistency. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/xics.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/xics.c b/hw/xics.c index ce88aa750b..7a899dd44f 100644 --- a/hw/xics.c +++ b/hw/xics.c @@ -108,13 +108,13 @@ static void icp_set_cppr(struct icp_state *icp, int server, uint8_t cppr) } } -static void icp_set_mfrr(struct icp_state *icp, int nr, uint8_t mfrr) +static void icp_set_mfrr(struct icp_state *icp, int server, uint8_t mfrr) { - struct icp_server_state *ss = icp->ss + nr; + struct icp_server_state *ss = icp->ss + server; ss->mfrr = mfrr; if (mfrr < CPPR(ss)) { - icp_check_ipi(icp, nr); + icp_check_ipi(icp, server); } } From 1ecbbab46925d4810fc35aba45cf93cb80ff0734 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 29 Oct 2012 17:25:02 +0000 Subject: [PATCH 5/5] pseries: Cleanup duplications of ics_valid_irq() code A couple of places in xics.c open-coded the same logic as is already implemented in ics_valid_irq(). This patch fixes the code duplication. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/xics.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/xics.c b/hw/xics.c index 7a899dd44f..ff4b5e210f 100644 --- a/hw/xics.c +++ b/hw/xics.c @@ -326,8 +326,7 @@ static void ics_eoi(struct ics_state *ics, int nr) qemu_irq xics_get_qirq(struct icp_state *icp, int irq) { - if ((irq < icp->ics->offset) - || (irq >= (icp->ics->offset + icp->ics->nr_irqs))) { + if (!ics_valid_irq(icp->ics, irq)) { return NULL; } @@ -336,8 +335,7 @@ qemu_irq xics_get_qirq(struct icp_state *icp, int irq) void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi) { - assert((irq >= icp->ics->offset) - && (irq < (icp->ics->offset + icp->ics->nr_irqs))); + assert(ics_valid_irq(icp->ics, irq)); icp->ics->irqs[irq - icp->ics->offset].lsi = lsi; }