From 32a2003af9cb0cb11b3992fd3248cb89752c53e9 Mon Sep 17 00:00:00 2001 From: Alex Barcelo Date: Thu, 9 Feb 2012 23:55:46 +0000 Subject: Bad zero comparison for sas_ss_flags on powerpc All architectures work the same way, and all check for sas_ss_flags == 0. The powerpc lines are wrong, and do the check the other way round (it's a qemu internal check, which is done wrong only for this architecture, it's more a typo than a bug). It's NOT ppc specific, it's POSIX standard (sigaltstack) and qemu internal. I have a test source that I will send in a follow-up (it's longer than I would have wished, I'm sure that a better test case can be written if needed) Signed-off-by: Alex Barcelo Signed-off-by: Alexander Graf --- linux-user/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/signal.c b/linux-user/signal.c index fca51e2b1..b1e139d6f 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -4118,7 +4118,7 @@ static target_ulong get_sigframe(struct target_sigaction *ka, oldsp = env->gpr[1]; if ((ka->sa_flags & TARGET_SA_ONSTACK) && - (sas_ss_flags(oldsp))) { + (sas_ss_flags(oldsp) == 0)) { oldsp = (target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size); } -- cgit v1.2.3 From d715ea961254512c6989e17edbfaf959aa7805b0 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Tue, 21 Feb 2012 19:01:11 +0100 Subject: PPC: 405: Fix ppc405ep initialization When trying to run a ppc405 guest, it segfaults quite quickly, trying to access timers that weren't initialized. Initialize them properly instead. Reported-by: Andreas Faerber Signed-off-by: Alexander Graf --- hw/ppc405_uc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c index 6f8342e0e..89e5013b5 100644 --- a/hw/ppc405_uc.c +++ b/hw/ppc405_uc.c @@ -2471,6 +2471,8 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem, ppc4xx_pob_init(env); /* OBP arbitrer */ ppc4xx_opba_init(0xef600600); + /* Initialize timers */ + ppc_booke_timers_init(env, sysclk, 0); /* Universal interrupt controller */ irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB); irqs[PPCUIC_OUTPUT_INT] = -- cgit v1.2.3 From b7c28f02a12c98a4710b5c150b0753d39454101e Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 25 Feb 2012 02:37:12 +0000 Subject: ppc: Add missing 'static' to spin_rw_ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit spin_rw_ops is only used in hw/ppce500_spin.c. Signed-off-by: Stefan Weil Acked-by: Andreas Färber Signed-off-by: Alexander Graf --- hw/ppce500_spin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c index 268f5fdb9..960b7b0c3 100644 --- a/hw/ppce500_spin.c +++ b/hw/ppce500_spin.c @@ -182,7 +182,7 @@ static uint64_t spin_read(void *opaque, target_phys_addr_t addr, unsigned len) } } -const MemoryRegionOps spin_rw_ops = { +static const MemoryRegionOps spin_rw_ops = { .read = spin_read, .write = spin_write, .endianness = DEVICE_BIG_ENDIAN, -- cgit v1.2.3 From b5aec39672dc6084b43fa3f77764a6f549255a53 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 27 Feb 2012 17:18:07 +0000 Subject: pseries: Don't try to munmap() a malloc()ed TCE table For the pseries machine, TCE (IOMMU) tables can either be directly malloc()ed in qemu or, when running on a KVM which supports it, mmap()ed from a KVM ioctl. The latter option is used when available, because it allows the (frequent bottlenext) H_PUT_TCE hypercall to be KVM accelerated. However, even when KVM is persent, TCE acceleration is not always possible. Only KVM HV supports this ioctl(), not KVM PR, or the kernel could run out of contiguous memory to allocate the new table. In this case we need to fall back on the malloc()ed table. When a device is removed, and we need to remove the TCE table, we need to either munmap() or free() the table as appropriate for how it was allocated. The code is supposed to do that, but we buggily fail to initialize the tcet->fd variable in the malloc() case, which is used as a flag to determine which is the right choice. This patch fixes the bug, and cleans up error messages relating to this path while we're at it. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- target-ppc/kvm.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index aeb3de9ae..724f4c781 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -843,12 +843,18 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd) int fd; void *table; + /* Must set fd to -1 so we don't try to munmap when called for + * destroying the table, which the upper layers -will- do + */ + *pfd = -1; if (!cap_spapr_tce) { return NULL; } fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE, &args); if (fd < 0) { + fprintf(stderr, "KVM: Failed to create TCE table for liobn 0x%x\n", + liobn); return NULL; } @@ -857,6 +863,8 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd) table = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (table == MAP_FAILED) { + fprintf(stderr, "KVM: Failed to map TCE table for liobn 0x%x\n", + liobn); close(fd); return NULL; } @@ -876,8 +884,8 @@ int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t window_size) len = (window_size / SPAPR_VIO_TCE_PAGE_SIZE)*sizeof(VIOsPAPR_RTCE); if ((munmap(table, len) < 0) || (close(fd) < 0)) { - fprintf(stderr, "KVM: Unexpected error removing KVM SPAPR TCE " - "table: %s", strerror(errno)); + fprintf(stderr, "KVM: Unexpected error removing TCE table: %s", + strerror(errno)); /* Leak the table */ } -- cgit v1.2.3 From cd6e9320142fea0d9e82c8ca7f3a4c2f20fecf39 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 27 Feb 2012 17:18:08 +0000 Subject: PPC64: Add support for ldbrx and stdbrx instructions These instructions for loading and storing byte-swapped 64-bit values have been introduced in PowerISA 2.06. Signed-off-by: Thomas Huth Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- target-ppc/cpu.h | 4 +++- target-ppc/translate.c | 52 +++++++++++++++++++++++++++++++++++++-------- target-ppc/translate_init.c | 2 +- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index ad09cbe06..ca6f1cb58 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -1918,8 +1918,10 @@ enum { PPC2_DFP = 0x0000000000000004ULL, /* Embedded.Processor Control */ PPC2_PRCNTL = 0x0000000000000008ULL, + /* Byte-reversed, indexed, double-word load and store */ + PPC2_DBRX = 0x0000000000000010ULL, -#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_PRCNTL) +#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_DBRX) }; /*****************************************************************************/ diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 3ec59a7ee..4722a0902 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -2650,7 +2650,7 @@ static void glue(gen_, name##ux)(DisasContext *ctx) tcg_temp_free(EA); \ } -#define GEN_LDX(name, ldop, opc2, opc3, type) \ +#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2) \ static void glue(gen_, name##x)(DisasContext *ctx) \ { \ TCGv EA; \ @@ -2660,6 +2660,8 @@ static void glue(gen_, name##x)(DisasContext *ctx) \ gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \ tcg_temp_free(EA); \ } +#define GEN_LDX(name, ldop, opc2, opc3, type) \ + GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE) #define GEN_LDS(name, ldop, op, type) \ GEN_LD(name, ldop, op | 0x20, type); \ @@ -2793,8 +2795,8 @@ static void glue(gen_, name##ux)(DisasContext *ctx) tcg_temp_free(EA); \ } -#define GEN_STX(name, stop, opc2, opc3, type) \ -static void glue(gen_, name##x)(DisasContext *ctx) \ +#define GEN_STX_E(name, stop, opc2, opc3, type, type2) \ +static void glue(gen_, name##x)(DisasContext *ctx) \ { \ TCGv EA; \ gen_set_access_type(ctx, ACCESS_INT); \ @@ -2803,6 +2805,8 @@ static void glue(gen_, name##x)(DisasContext *ctx) gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \ tcg_temp_free(EA); \ } +#define GEN_STX(name, stop, opc2, opc3, type) \ + GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE) #define GEN_STS(name, stop, op, type) \ GEN_ST(name, stop, op | 0x20, type); \ @@ -2891,6 +2895,18 @@ static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2) } GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER); +#if defined(TARGET_PPC64) +/* ldbrx */ +static inline void gen_qemu_ld64ur(DisasContext *ctx, TCGv arg1, TCGv arg2) +{ + tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx); + if (likely(!ctx->le_mode)) { + tcg_gen_bswap64_tl(arg1, arg1); + } +} +GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX); +#endif /* TARGET_PPC64 */ + /* sthbrx */ static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2) { @@ -2921,6 +2937,22 @@ static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2) } GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER); +#if defined(TARGET_PPC64) +/* stdbrx */ +static inline void gen_qemu_st64r(DisasContext *ctx, TCGv arg1, TCGv arg2) +{ + if (likely(!ctx->le_mode)) { + TCGv t0 = tcg_temp_new(); + tcg_gen_bswap64_tl(t0, arg1); + tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx); + tcg_temp_free(t0); + } else { + tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx); + } +} +GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX); +#endif /* TARGET_PPC64 */ + /*** Integer load and store multiple ***/ /* lmw */ @@ -8818,7 +8850,7 @@ GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT), #undef GEN_LD #undef GEN_LDU #undef GEN_LDUX -#undef GEN_LDX +#undef GEN_LDX_E #undef GEN_LDS #define GEN_LD(name, ldop, opc, type) \ GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type), @@ -8826,8 +8858,8 @@ GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type), GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type), #define GEN_LDUX(name, ldop, opc2, opc3, type) \ GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type), -#define GEN_LDX(name, ldop, opc2, opc3, type) \ -GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type), +#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2) \ +GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2), #define GEN_LDS(name, ldop, op, type) \ GEN_LD(name, ldop, op | 0x20, type) \ GEN_LDU(name, ldop, op | 0x21, type) \ @@ -8843,6 +8875,7 @@ GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B) GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B) GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B) GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B) +GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX) #endif GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER) GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER) @@ -8850,7 +8883,7 @@ GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER) #undef GEN_ST #undef GEN_STU #undef GEN_STUX -#undef GEN_STX +#undef GEN_STX_E #undef GEN_STS #define GEN_ST(name, stop, opc, type) \ GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type), @@ -8858,8 +8891,8 @@ GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type), GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type), #define GEN_STUX(name, stop, opc2, opc3, type) \ GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type), -#define GEN_STX(name, stop, opc2, opc3, type) \ -GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type), +#define GEN_STX_E(name, stop, opc2, opc3, type, type2) \ +GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2), #define GEN_STS(name, stop, op, type) \ GEN_ST(name, stop, op | 0x20, type) \ GEN_STU(name, stop, op | 0x21, type) \ @@ -8872,6 +8905,7 @@ GEN_STS(stw, st32, 0x04, PPC_INTEGER) #if defined(TARGET_PPC64) GEN_STUX(std, st64, 0x15, 0x05, PPC_64B) GEN_STX(std, st64, 0x15, 0x04, PPC_64B) +GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX) #endif GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER) GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 1ec6f4248..c707959e2 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -6571,7 +6571,7 @@ static void init_proc_970MP (CPUPPCState *env) PPC_64B | PPC_ALTIVEC | \ PPC_SEGMENT_64B | PPC_SLBI | \ PPC_POPCNTB | PPC_POPCNTWD) -#define POWERPC_INSNS2_POWER7 (PPC2_VSX | PPC2_DFP) +#define POWERPC_INSNS2_POWER7 (PPC2_VSX | PPC2_DFP | PPC2_DBRX) #define POWERPC_MSRM_POWER7 (0x800000000204FF36ULL) #define POWERPC_MMU_POWER7 (POWERPC_MMU_2_06) #define POWERPC_EXCP_POWER7 (POWERPC_EXCP_POWER7) -- cgit v1.2.3 From 53f649e863dd08b6ff212093556add42f456d14d Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 27 Feb 2012 17:18:10 +0000 Subject: pseries: Update SLOF firmware image This patch updates the SLOF firmware image used on the pseries machine. The new version adds support for Cirrus VGA and virtfs, as well as including a number of bugfixes. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- pc-bios/README | 2 +- pc-bios/slof.bin | Bin 869584 -> 880496 bytes roms/SLOF | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pc-bios/README b/pc-bios/README index 5dce355f5..71f48711b 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -17,7 +17,7 @@ - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at https://github.com/dgibson/SLOF, and the image currently in qemu is - built from git tag qemu-slof-20120111.1. + built from git tag qemu-slof-20120217. - sgabios (the Serial Graphics Adapter option ROM) provides a means for legacy x86 software to communicate with an attached serial console as diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin index 8554f54b5..449a7bb2a 100644 Binary files a/pc-bios/slof.bin and b/pc-bios/slof.bin differ diff --git a/roms/SLOF b/roms/SLOF index ab062ff3b..d15336425 160000 --- a/roms/SLOF +++ b/roms/SLOF @@ -1 +1 @@ -Subproject commit ab062ff3b37c39649f2b0d94ed607adc6f6b3c7d +Subproject commit d153364253548d6cd91403711f84996e6a7dab31 -- cgit v1.2.3 From 323abebf9997f30fb357602e169ea6333ac20bc3 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 27 Feb 2012 17:18:11 +0000 Subject: pseries: Remove unused constant from PCI code The 'bars' constant array was used in experimental device allocation code which is no longer necessary now that we always run the SLOF firmware. This patch removes the now redundant variable. Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr_pci.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 374dcf8be..3d5e50a1e 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -32,13 +32,6 @@ #include "hw/pci_internals.h" -static const uint32_t bars[] = { - PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, - PCI_BASE_ADDRESS_2, PCI_BASE_ADDRESS_3, - PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5 - /*, PCI_ROM_ADDRESS*/ -}; - static PCIDevice *find_dev(sPAPREnvironment *spapr, uint64_t buid, uint32_t config_addr) { -- cgit v1.2.3 From 76ab9583cea5c742f32743cc65abc326719bd646 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Mon, 27 Feb 2012 17:18:12 +0000 Subject: pseries: Remove PCI device from PCI host bridge code The sPAPR PCI code defines a PCI device "spapr-pci-host-bridge-pci" which is never used. This came over from the earlier bridge driver we used as a template. Some other bridges appear on their own PCI bus as a device, but that is not true of pSeries bridges, which are pure host to PCI with no visible presence on the PCI side. Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr_pci.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 3d5e50a1e..c06afacbb 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -202,25 +202,6 @@ static int spapr_phb_init(SysBusDevice *s) return 0; } -static int spapr_main_pci_host_init(PCIDevice *d) -{ - return 0; -} - -static void spapr_main_pci_host_class_init(ObjectClass *klass, void *data) -{ - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->init = spapr_main_pci_host_init; -} - -static TypeInfo spapr_main_pci_host_info = { - .name = "spapr-pci-host-bridge-pci", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCIDevice), - .class_init = spapr_main_pci_host_class_init, -}; - static void spapr_phb_class_init(ObjectClass *klass, void *data) { SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); @@ -238,7 +219,6 @@ static TypeInfo spapr_phb_info = { static void spapr_register_types(void) { type_register_static(&spapr_phb_info); - type_register_static(&spapr_main_pci_host_info); } type_init(spapr_register_types) -- cgit v1.2.3 From 2e06214f22e080be4a8a17b0fae3b4c03b0aa3ea Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Sat, 3 Mar 2012 06:36:36 +0000 Subject: PPC: Add PIR register to POWER7 CPU The POWER7 emulation is missing the Processor Identification Register, mandatory in recent POWER CPUs, that is required for SMP on at least some operating systems (e.g. FreeBSD) to function properly. This patch copies the existing PIR code from the other CPUs that implement it. Signed-off-by: Nathan Whitehorn Signed-off-by: Alexander Graf --- target-ppc/translate_init.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index c707959e2..5a958b931 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -6588,6 +6588,11 @@ static void init_proc_POWER7 (CPUPPCState *env) gen_spr_7xx(env); /* Time base */ gen_tbl(env); + /* Processor identification */ + spr_register(env, SPR_PIR, "PIR", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_pir, + 0x00000000); #if !defined(CONFIG_USER_ONLY) /* PURR & SPURR: Hack - treat these as aliases for the TB for now */ spr_register(env, SPR_PURR, "PURR", -- cgit v1.2.3 From eb6ea4b22e89d4c6ed510c7cfcd33d15be92733b Mon Sep 17 00:00:00 2001 From: Nathan Whitehorn Date: Fri, 9 Mar 2012 04:30:41 +0000 Subject: PPC: Fix large page support in TCG Fix large page support in TCG. The old code would overwrite the large page table entry with the fake 4 KB one generated here whenever the ref/change bits were updated, causing it to point to the wrong area of memory. Signed-off-by: Nathan Whitehorn Acked-by: David Gibson [agraf: fix whitespace, braces] Signed-off-by: Alexander Graf --- target-ppc/helper.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/target-ppc/helper.c b/target-ppc/helper.c index bd711b6e2..39dcc273e 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -591,12 +591,6 @@ static inline int _find_pte(CPUPPCState *env, mmu_ctx_t *ctx, int is_64b, int h, pte1 = ldq_phys(env->htab_base + pteg_off + (i * 16) + 8); } - /* We have a TLB that saves 4K pages, so let's - * split a huge page to 4k chunks */ - if (target_page_bits != TARGET_PAGE_BITS) - pte1 |= (ctx->eaddr & (( 1 << target_page_bits ) - 1)) - & TARGET_PAGE_MASK; - r = pte64_check(ctx, pte0, pte1, h, rw, type); LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " " TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n", @@ -672,6 +666,12 @@ static inline int _find_pte(CPUPPCState *env, mmu_ctx_t *ctx, int is_64b, int h, } } + /* We have a TLB that saves 4K pages, so let's + * split a huge page to 4k chunks */ + if (target_page_bits != TARGET_PAGE_BITS) { + ctx->raddr |= (ctx->eaddr & ((1 << target_page_bits) - 1)) + & TARGET_PAGE_MASK; + } return ret; } -- cgit v1.2.3 From d07fee7e8ad9d3611404fa145270d3b885b2772a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 7 Mar 2012 15:12:21 +0000 Subject: pseries: Add support for level interrupts to XICS The pseries "xics" interrupt controller, like most interrupt controllers can support both message (i.e. edge sensitive) interrupts and level sensitive interrupts, but it needs to know which are which. When I implemented the xics emulation for qemu, the only devices we supported were the PAPR virtual IO devices. These devices only use message interrupts, so they were the only ones I implemented in xics. Since then, however, we have added support for PCI devices, which use level sensitive interrupts. It turns out the message interrupt logic still actually works most of the time for these, but there are circumstances where we can lost interrupts due to the incorrect interrupt logic. This patch, therefore, implements the correct xics level-sensitive interrupt logic. The type of the interrupt is set when a device allocates a new xics interrupt. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.c | 5 ++- hw/spapr.h | 13 +++++- hw/spapr_pci.c | 2 +- hw/spapr_vio.c | 2 +- hw/xics.c | 125 ++++++++++++++++++++++++++++++++++++++++++--------------- hw/xics.h | 8 +++- 6 files changed, 117 insertions(+), 38 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 3719e0e4a..bfaf260d5 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -83,7 +83,8 @@ sPAPREnvironment *spapr; -qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num) +qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num, + enum xics_irq_type type) { uint32_t irq; qemu_irq qirq; @@ -95,7 +96,7 @@ qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num) irq = spapr->next_irq++; } - qirq = xics_find_qirq(spapr->icp, irq); + qirq = xics_assign_irq(spapr->icp, irq, type); if (!qirq) { return NULL; } diff --git a/hw/spapr.h b/hw/spapr.h index a41641fdd..11160b02d 100644 --- a/hw/spapr.h +++ b/hw/spapr.h @@ -286,7 +286,18 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn); target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode, target_ulong *args); -qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num); +qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num, + enum xics_irq_type type); + +static inline qemu_irq spapr_allocate_msi(uint32_t hint, uint32_t *irq_num) +{ + return spapr_allocate_irq(hint, irq_num, XICS_MSI); +} + +static inline qemu_irq spapr_allocate_lsi(uint32_t hint, uint32_t *irq_num) +{ + return spapr_allocate_irq(hint, irq_num, XICS_LSI); +} static inline uint32_t rtas_ld(target_ulong phys, int n) { diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index c06afacbb..233250fac 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -190,7 +190,7 @@ static int spapr_phb_init(SysBusDevice *s) qemu_irq qirq; uint32_t num; - qirq = spapr_allocate_irq(0, &num); + qirq = spapr_allocate_lsi(0, &num); if (!qirq) { return -1; } diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index 2fb3cee26..dbf5a9017 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -670,7 +670,7 @@ static int spapr_vio_busdev_init(DeviceState *qdev) dev->qdev.id = id; } - dev->qirq = spapr_allocate_irq(dev->vio_irq_num, &dev->vio_irq_num); + dev->qirq = spapr_allocate_msi(dev->vio_irq_num, &dev->vio_irq_num); if (!dev->qirq) { return -1; } diff --git a/hw/xics.c b/hw/xics.c index f7963f309..668a0d648 100644 --- a/hw/xics.c +++ b/hw/xics.c @@ -132,9 +132,9 @@ static void icp_eoi(struct icp_state *icp, int server, uint32_t xirr) { struct icp_server_state *ss = icp->ss + server; - ics_eoi(icp->ics, xirr & XISR_MASK); /* Send EOI -> ICS */ ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK); + ics_eoi(icp->ics, xirr & XISR_MASK); if (!XISR(ss)) { icp_resend(icp, server); } @@ -165,8 +165,9 @@ struct ics_irq_state { int server; uint8_t priority; uint8_t saved_priority; - /* int pending:1; */ - /* int presented:1; */ + enum xics_irq_type type; + int asserted:1; + int sent:1; int rejected:1; int masked_pending:1; }; @@ -185,9 +186,32 @@ static int ics_valid_irq(struct ics_state *ics, uint32_t nr) && (nr < (ics->offset + ics->nr_irqs)); } -static void ics_set_irq_msi(void *opaque, int srcno, int val) +static void resend_msi(struct ics_state *ics, int srcno) +{ + struct ics_irq_state *irq = ics->irqs + srcno; + + /* FIXME: filter by server#? */ + if (irq->rejected) { + irq->rejected = 0; + if (irq->priority != 0xff) { + icp_irq(ics->icp, irq->server, srcno + ics->offset, + irq->priority); + } + } +} + +static void resend_lsi(struct ics_state *ics, int srcno) +{ + struct ics_irq_state *irq = ics->irqs + srcno; + + if ((irq->priority != 0xff) && irq->asserted && !irq->sent) { + irq->sent = 1; + icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority); + } +} + +static void set_irq_msi(struct ics_state *ics, int srcno, int val) { - struct ics_state *ics = (struct ics_state *)opaque; struct ics_irq_state *irq = ics->irqs + srcno; if (val) { @@ -200,71 +224,108 @@ static void ics_set_irq_msi(void *opaque, int srcno, int val) } } -static void ics_reject_msi(struct ics_state *ics, int nr) +static void set_irq_lsi(struct ics_state *ics, int srcno, int val) { - struct ics_irq_state *irq = ics->irqs + nr - ics->offset; + struct ics_irq_state *irq = ics->irqs + srcno; - irq->rejected = 1; + irq->asserted = val; + resend_lsi(ics, srcno); } -static void ics_resend_msi(struct ics_state *ics) +static void ics_set_irq(void *opaque, int srcno, int val) { - int i; + struct ics_state *ics = (struct ics_state *)opaque; + struct ics_irq_state *irq = ics->irqs + srcno; - for (i = 0; i < ics->nr_irqs; i++) { - struct ics_irq_state *irq = ics->irqs + i; + if (irq->type == XICS_LSI) { + set_irq_lsi(ics, srcno, val); + } else { + set_irq_msi(ics, srcno, val); + } +} - /* FIXME: filter by server#? */ - if (irq->rejected) { - irq->rejected = 0; - if (irq->priority != 0xff) { - icp_irq(ics->icp, irq->server, i + ics->offset, irq->priority); - } - } +static void write_xive_msi(struct ics_state *ics, int srcno) +{ + struct ics_irq_state *irq = ics->irqs + srcno; + + if (!irq->masked_pending || (irq->priority == 0xff)) { + return; } + + irq->masked_pending = 0; + icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority); } -static void ics_write_xive_msi(struct ics_state *ics, int nr, int server, - uint8_t priority) +static void write_xive_lsi(struct ics_state *ics, int srcno) { - struct ics_irq_state *irq = ics->irqs + nr - ics->offset; + resend_lsi(ics, srcno); +} + +static void ics_write_xive(struct ics_state *ics, int nr, int server, + uint8_t priority) +{ + int srcno = nr - ics->offset; + struct ics_irq_state *irq = ics->irqs + srcno; irq->server = server; irq->priority = priority; - if (!irq->masked_pending || (priority == 0xff)) { - return; + if (irq->type == XICS_LSI) { + write_xive_lsi(ics, srcno); + } else { + write_xive_msi(ics, srcno); } - - irq->masked_pending = 0; - icp_irq(ics->icp, server, nr, priority); } static void ics_reject(struct ics_state *ics, int nr) { - ics_reject_msi(ics, nr); + struct ics_irq_state *irq = ics->irqs + nr - ics->offset; + + irq->rejected = 1; /* Irrelevant but harmless for LSI */ + irq->sent = 0; /* Irrelevant but harmless for MSI */ } static void ics_resend(struct ics_state *ics) { - ics_resend_msi(ics); + int i; + + for (i = 0; i < ics->nr_irqs; i++) { + struct ics_irq_state *irq = ics->irqs + i; + + /* FIXME: filter by server#? */ + if (irq->type == XICS_LSI) { + resend_lsi(ics, i); + } else { + resend_msi(ics, i); + } + } } static void ics_eoi(struct ics_state *ics, int nr) { + int srcno = nr - ics->offset; + struct ics_irq_state *irq = ics->irqs + srcno; + + if (irq->type == XICS_LSI) { + irq->sent = 0; + } } /* * Exported functions */ -qemu_irq xics_find_qirq(struct icp_state *icp, int irq) +qemu_irq xics_assign_irq(struct icp_state *icp, int irq, + enum xics_irq_type type) { if ((irq < icp->ics->offset) || (irq >= (icp->ics->offset + icp->ics->nr_irqs))) { return NULL; } + assert((type == XICS_MSI) || (type == XICS_LSI)); + + icp->ics->irqs[irq - icp->ics->offset].type = type; return icp->ics->qirqs[irq - icp->ics->offset]; } @@ -332,7 +393,7 @@ static void rtas_set_xive(sPAPREnvironment *spapr, uint32_t token, return; } - ics_write_xive_msi(ics, nr, server, priority); + ics_write_xive(ics, nr, server, priority); rtas_st(rets, 0, 0); /* Success */ } @@ -477,7 +538,7 @@ struct icp_state *xics_system_init(int nr_irqs) ics->irqs[i].saved_priority = 0xff; } - ics->qirqs = qemu_allocate_irqs(ics_set_irq_msi, ics, nr_irqs); + ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, nr_irqs); spapr_register_hypercall(H_CPPR, h_cppr); spapr_register_hypercall(H_IPI, h_ipi); diff --git a/hw/xics.h b/hw/xics.h index 83c118259..208015939 100644 --- a/hw/xics.h +++ b/hw/xics.h @@ -31,7 +31,13 @@ struct icp_state; -qemu_irq xics_find_qirq(struct icp_state *icp, int irq); +enum xics_irq_type { + XICS_MSI, /* Message-signalled (edge) interrupt */ + XICS_LSI, /* Level-signalled interrupt */ +}; + +qemu_irq xics_assign_irq(struct icp_state *icp, int irq, + enum xics_irq_type type); struct icp_state *xics_system_init(int nr_irqs); -- cgit v1.2.3 From 6bbc5ed163d0eb8e3268ec81742a0d4f4f0bfc22 Mon Sep 17 00:00:00 2001 From: Meador Inge Date: Thu, 23 Feb 2012 03:44:14 +0000 Subject: ppc: Correctly define POWERPC_INSNS2_DEFAULT 'POWERPC_INSNS2_DEFAULT' was defined incorrectly which was causing the opcode table creation code to erroneously register 'eieio' and 'mbar' for the "default" processor: ** ERROR: opcode 1a already assigned in opcode table 16 *** ERROR: unable to insert opcode [1f-16-1a] *** ERROR initializing PowerPC instruction 0x1f 0x16 0x1a Signed-off-by: Meador Inge Signed-off-by: Alexander Graf --- target-ppc/translate_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 5a958b931..367eefaf9 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -6718,7 +6718,7 @@ static void init_proc_620 (CPUPPCState *env) #if defined (TARGET_PPC64) && 0 // XXX: TODO #define CPU_POWERPC_DEFAULT CPU_POWERPC_PPC64 #define POWERPC_INSNS_DEFAULT POWERPC_INSNS_PPC64 -#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS_PPC64 +#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS2_PPC64 #define POWERPC_MSRM_DEFAULT POWERPC_MSRM_PPC64 #define POWERPC_MMU_DEFAULT POWERPC_MMU_PPC64 #define POWERPC_EXCP_DEFAULT POWERPC_EXCP_PPC64 @@ -6730,7 +6730,7 @@ static void init_proc_620 (CPUPPCState *env) #else #define CPU_POWERPC_DEFAULT CPU_POWERPC_PPC32 #define POWERPC_INSNS_DEFAULT POWERPC_INSNS_PPC32 -#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS_PPC32 +#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS2_PPC32 #define POWERPC_MSRM_DEFAULT POWERPC_MSRM_PPC32 #define POWERPC_MMU_DEFAULT POWERPC_MMU_PPC32 #define POWERPC_EXCP_DEFAULT POWERPC_EXCP_PPC32 -- cgit v1.2.3 From 92e4b519e0808948ae4bc710fb1db7d3cc2245a1 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 7 Mar 2012 14:41:09 +0000 Subject: kvm: Comparison with ioctl number macros needs to be unsigned In kvm-all.c we store an ioctl cmd number in the irqchip_inject_ioctl field of KVMState, which has type 'int'. This seems to make sense since the ioctl() man page says that the cmd parameter has type int. However, the kernel treats ioctl numbers as unsigned - sys_ioctl() takes an unsigned int, and the macros which generate ioctl numbers expand to unsigned expressions. Furthermore, some ioctls (IOC_READ ioctls on x86 and IOC_WRITE ioctls on powerpc) have bit 31 set, and so would be negative if interpreted as an int. This has the surprising and compile-breaking consequence that in kvm_irqchip_set_irq() where we do: return (s->irqchip_inject_ioctl == KVM_IRQ_LINE) ? 1 : event.status; We will get a "comparison is always false due to limited range of data type" warning from gcc if KVM_IRQ_LINE is one of the bit-31-set ioctls, which it is on powerpc. So, despite the fact that the man page and posix say ioctl numbers are signed, they're actually unsigned. The kernel uses unsigned, the glibc header uses unsigned long, and FreeBSD, NetBSD and OSX also use unsigned long ioctl numbers in the code. Therefore, this patch changes the variable to be unsigned, fixing the compile. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- kvm-all.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kvm-all.c b/kvm-all.c index 42e5e23d5..ba2cee10f 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -79,7 +79,10 @@ struct KVMState int pit_state2; int xsave, xcrs; int many_ioeventfds; - int irqchip_inject_ioctl; + /* The man page (and posix) say ioctl numbers are signed int, but + * they're not. Linux, glibc and *BSD all treat ioctl numbers as + * unsigned, and treating them as signed here can break things */ + unsigned irqchip_inject_ioctl; #ifdef KVM_CAP_IRQ_ROUTING struct kvm_irq_routing *irq_routes; int nr_allocated_irq_routes; -- cgit v1.2.3 From 29979a8d2596d33b474c11efb376ed47ba1d44d3 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 14 Mar 2012 00:13:22 +0100 Subject: PPC: KVM: Synchronize regs on CPU dump When we dump the CPU registers, there's a certain chance they haven't been synchronized with KVM yet, so we have to manually trigger that. This aligns the code with x86 and fixes a bug where the register state was bogus on invalid/unknown kvm exit reasons. Reported-by: Benjamin Herrenschmidt Signed-off-by: Alexander Graf --- target-ppc/translate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 4722a0902..c9a503a1d 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -9319,6 +9319,8 @@ void cpu_dump_state (CPUPPCState *env, FILE *f, fprintf_function cpu_fprintf, int i; + cpu_synchronize_state(env); + cpu_fprintf(f, "NIP " TARGET_FMT_lx " LR " TARGET_FMT_lx " CTR " TARGET_FMT_lx " XER " TARGET_FMT_lx "\n", env->nip, env->lr, env->ctr, env->xer); -- cgit v1.2.3 From 298a971024534e9ab6c7b57845bbbd8188867d7a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 12 Mar 2012 17:50:24 +0000 Subject: pseries: Configure PCI bridge using properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, the function spapr_create_phb() uses its parameters to initialize the correct memory windows for the new PCI Host Bridge (PHB). This is not the way things are supposed to be done with qdevs, and means you can't create extra PHBs easily using -device. Since pSeries machines can and do have many PHBs with various configurations, this is a real limitation, not just a theoretical. This patch, therefore, alters the PHB initialization code to use qdev properties to set these parameters of the new bridge, moving most of the code from spapr_create_phb() to spapr_phb_init(). While we're at it, we change the naming of each PCI bus and its associated memory regions to be less arbitrary and make it easier to relate the guest and qemu views of memory to each other. Signed-off-by: Alexey Kardashevskiy Signed-off-by: David Gibson Reviewed-by: Andreas Färber Signed-off-by: Alexander Graf --- hw/spapr_pci.c | 166 +++++++++++++++++++++++++++++++-------------------------- hw/spapr_pci.h | 4 +- 2 files changed, 94 insertions(+), 76 deletions(-) diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 233250fac..e7ef551c1 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -180,49 +180,6 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level) qemu_set_irq(phb->lsi_table[irq_num].qirq, level); } -static int spapr_phb_init(SysBusDevice *s) -{ - sPAPRPHBState *phb = FROM_SYSBUS(sPAPRPHBState, s); - int i; - - /* Initialize the LSI table */ - for (i = 0; i < SPAPR_PCI_NUM_LSI; i++) { - qemu_irq qirq; - uint32_t num; - - qirq = spapr_allocate_lsi(0, &num); - if (!qirq) { - return -1; - } - - phb->lsi_table[i].dt_irq = num; - phb->lsi_table[i].qirq = qirq; - } - - return 0; -} - -static void spapr_phb_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); - - sdc->init = spapr_phb_init; -} - -static TypeInfo spapr_phb_info = { - .name = "spapr-pci-host-bridge", - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(sPAPRPHBState), - .class_init = spapr_phb_class_init, -}; - -static void spapr_register_types(void) -{ - type_register_static(&spapr_phb_info); -} - -type_init(spapr_register_types) - static uint64_t spapr_io_read(void *opaque, target_phys_addr_t addr, unsigned size) { @@ -260,35 +217,29 @@ static const MemoryRegionOps spapr_io_ops = { .write = spapr_io_write }; -void spapr_create_phb(sPAPREnvironment *spapr, - const char *busname, uint64_t buid, - uint64_t mem_win_addr, uint64_t mem_win_size, - uint64_t io_win_addr) +/* + * PHB PCI device + */ +static int spapr_phb_init(SysBusDevice *s) { - DeviceState *dev; - SysBusDevice *s; - sPAPRPHBState *phb; + sPAPRPHBState *phb = FROM_SYSBUS(sPAPRPHBState, s); + char *namebuf; + int i; PCIBus *bus; - char namebuf[strlen(busname)+11]; - dev = qdev_create(NULL, "spapr-pci-host-bridge"); - qdev_init_nofail(dev); - s = sysbus_from_qdev(dev); - phb = FROM_SYSBUS(sPAPRPHBState, s); + phb->dtbusname = g_strdup_printf("pci@%" PRIx64, phb->buid); + namebuf = alloca(strlen(phb->dtbusname) + 32); - phb->mem_win_addr = mem_win_addr; - - sprintf(namebuf, "%s-mem", busname); + /* Initialize memory regions */ + sprintf(namebuf, "%s.mmio", phb->dtbusname); memory_region_init(&phb->memspace, namebuf, INT64_MAX); - sprintf(namebuf, "%s-memwindow", busname); + sprintf(namebuf, "%s.mmio-alias", phb->dtbusname); memory_region_init_alias(&phb->memwindow, namebuf, &phb->memspace, - SPAPR_PCI_MEM_WIN_BUS_OFFSET, mem_win_size); - memory_region_add_subregion(get_system_memory(), mem_win_addr, + SPAPR_PCI_MEM_WIN_BUS_OFFSET, phb->mem_win_size); + memory_region_add_subregion(get_system_memory(), phb->mem_win_addr, &phb->memwindow); - phb->io_win_addr = io_win_addr; - /* On ppc, we only have MMIO no specific IO space from the CPU * perspective. In theory we ought to be able to embed the PCI IO * memory region direction in the system memory space. However, @@ -297,33 +248,92 @@ void spapr_create_phb(sPAPREnvironment *spapr, * system io address space. This hack to bounce things via * system_io works around the problem until all the users of * old_portion are updated */ - sprintf(namebuf, "%s-io", busname); + sprintf(namebuf, "%s.io", phb->dtbusname); memory_region_init(&phb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE); /* FIXME: fix to support multiple PHBs */ memory_region_add_subregion(get_system_io(), 0, &phb->iospace); - sprintf(namebuf, "%s-iowindow", busname); + sprintf(namebuf, "%s.io-alias", phb->dtbusname); memory_region_init_io(&phb->iowindow, &spapr_io_ops, phb, namebuf, SPAPR_PCI_IO_WIN_SIZE); - memory_region_add_subregion(get_system_memory(), io_win_addr, + memory_region_add_subregion(get_system_memory(), phb->io_win_addr, &phb->iowindow); - phb->host_state.bus = bus = pci_register_bus(&phb->busdev.qdev, busname, - pci_spapr_set_irq, - pci_spapr_map_irq, - phb, - &phb->memspace, &phb->iospace, - PCI_DEVFN(0, 0), - SPAPR_PCI_NUM_LSI); + bus = pci_register_bus(&phb->busdev.qdev, + phb->busname ? phb->busname : phb->dtbusname, + pci_spapr_set_irq, pci_spapr_map_irq, phb, + &phb->memspace, &phb->iospace, + PCI_DEVFN(0, 0), SPAPR_PCI_NUM_LSI); + phb->host_state.bus = bus; + + QLIST_INSERT_HEAD(&spapr->phbs, phb, list); + + /* Initialize the LSI table */ + for (i = 0; i < SPAPR_PCI_NUM_LSI; i++) { + qemu_irq qirq; + uint32_t num; + + qirq = spapr_allocate_lsi(0, &num); + if (!qirq) { + return -1; + } + + phb->lsi_table[i].dt_irq = num; + phb->lsi_table[i].qirq = qirq; + } + + return 0; +} + +static Property spapr_phb_properties[] = { + DEFINE_PROP_HEX64("buid", sPAPRPHBState, buid, 0), + DEFINE_PROP_STRING("busname", sPAPRPHBState, busname), + DEFINE_PROP_HEX64("mem_win_addr", sPAPRPHBState, mem_win_addr, 0), + DEFINE_PROP_HEX64("mem_win_size", sPAPRPHBState, mem_win_size, 0x20000000), + DEFINE_PROP_HEX64("io_win_addr", sPAPRPHBState, io_win_addr, 0), + DEFINE_PROP_HEX64("io_win_size", sPAPRPHBState, io_win_size, 0x10000), + DEFINE_PROP_END_OF_LIST(), +}; + +static void spapr_phb_class_init(ObjectClass *klass, void *data) +{ + SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + sdc->init = spapr_phb_init; + dc->props = spapr_phb_properties; spapr_rtas_register("read-pci-config", rtas_read_pci_config); spapr_rtas_register("write-pci-config", rtas_write_pci_config); spapr_rtas_register("ibm,read-pci-config", rtas_ibm_read_pci_config); spapr_rtas_register("ibm,write-pci-config", rtas_ibm_write_pci_config); +} - QLIST_INSERT_HEAD(&spapr->phbs, phb, list); +static TypeInfo spapr_phb_info = { + .name = "spapr-pci-host-bridge", + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(sPAPRPHBState), + .class_init = spapr_phb_class_init, +}; + +void spapr_create_phb(sPAPREnvironment *spapr, + const char *busname, uint64_t buid, + uint64_t mem_win_addr, uint64_t mem_win_size, + uint64_t io_win_addr) +{ + DeviceState *dev; + + dev = qdev_create(NULL, spapr_phb_info.name); - /* pci_bus_set_mem_base(bus, mem_va_start - SPAPR_PCI_MEM_BAR_START); */ + if (busname) { + qdev_prop_set_string(dev, "busname", g_strdup(busname)); + } + qdev_prop_set_uint64(dev, "buid", buid); + qdev_prop_set_uint64(dev, "mem_win_addr", mem_win_addr); + qdev_prop_set_uint64(dev, "mem_win_size", mem_win_size); + qdev_prop_set_uint64(dev, "io_win_addr", io_win_addr); + + qdev_init_nofail(dev); } /* Macros to operate with address in OF binding to PCI */ @@ -415,3 +425,9 @@ int spapr_populate_pci_devices(sPAPRPHBState *phb, return 0; } + +static void register_types(void) +{ + type_register_static(&spapr_phb_info); +} +type_init(register_types) diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h index 213340c91..039f85bd4 100644 --- a/hw/spapr_pci.h +++ b/hw/spapr_pci.h @@ -33,9 +33,11 @@ typedef struct sPAPRPHBState { PCIHostState host_state; uint64_t buid; + char *busname; + char *dtbusname; MemoryRegion memspace, iospace; - target_phys_addr_t mem_win_addr, io_win_addr; + target_phys_addr_t mem_win_addr, mem_win_size, io_win_addr, io_win_size; MemoryRegion memwindow, iowindow; struct { -- cgit v1.2.3 From 38ae51a804a6ad2baec3e45ecb1571583b312441 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Wed, 14 Mar 2012 20:17:07 +0100 Subject: PPC: Fix openpic with relative memregions After commit 5312bd8b3152 we got memory region relative offsets into our mmio callbacks instead of page boundary based offsets. This broke the OpenPIC emulation which expected offsets to be on page boundary and substracted its region offset manually. This patch gets rid of that manual substraction and lets the memory api do its magic instead. Signed-off-by: Alexander Graf --- hw/openpic.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/hw/openpic.c b/hw/openpic.c index 280b7a9bb..58ef871f6 100644 --- a/hw/openpic.c +++ b/hw/openpic.c @@ -713,7 +713,7 @@ static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val) DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); if (addr & 0xF) return; - addr -= 0x1100; + addr -= 0x10; addr &= 0xFFFF; idx = (addr & 0xFFF0) >> 6; addr = addr & 0x30; @@ -746,7 +746,7 @@ static uint32_t openpic_timer_read (void *opaque, uint32_t addr) retval = 0xFFFFFFFF; if (addr & 0xF) return retval; - addr -= 0x1100; + addr -= 0x10; addr &= 0xFFFF; idx = (addr & 0xFFF0) >> 6; addr = addr & 0x30; @@ -1361,7 +1361,6 @@ static void mpic_src_ext_write (void *opaque, target_phys_addr_t addr, if (addr & 0xF) return; - addr -= MPIC_EXT_REG_START & (OPENPIC_PAGE_SIZE - 1); if (addr < MPIC_EXT_REG_SIZE) { idx += (addr & 0xFFF0) >> 5; if (addr & 0x10) { @@ -1385,7 +1384,6 @@ static uint32_t mpic_src_ext_read (void *opaque, target_phys_addr_t addr) if (addr & 0xF) return retval; - addr -= MPIC_EXT_REG_START & (OPENPIC_PAGE_SIZE - 1); if (addr < MPIC_EXT_REG_SIZE) { idx += (addr & 0xFFF0) >> 5; if (addr & 0x10) { @@ -1411,7 +1409,6 @@ static void mpic_src_int_write (void *opaque, target_phys_addr_t addr, if (addr & 0xF) return; - addr -= MPIC_INT_REG_START & (OPENPIC_PAGE_SIZE - 1); if (addr < MPIC_INT_REG_SIZE) { idx += (addr & 0xFFF0) >> 5; if (addr & 0x10) { @@ -1435,7 +1432,6 @@ static uint32_t mpic_src_int_read (void *opaque, target_phys_addr_t addr) if (addr & 0xF) return retval; - addr -= MPIC_INT_REG_START & (OPENPIC_PAGE_SIZE - 1); if (addr < MPIC_INT_REG_SIZE) { idx += (addr & 0xFFF0) >> 5; if (addr & 0x10) { @@ -1461,7 +1457,6 @@ static void mpic_src_msg_write (void *opaque, target_phys_addr_t addr, if (addr & 0xF) return; - addr -= MPIC_MSG_REG_START & (OPENPIC_PAGE_SIZE - 1); if (addr < MPIC_MSG_REG_SIZE) { idx += (addr & 0xFFF0) >> 5; if (addr & 0x10) { @@ -1485,7 +1480,6 @@ static uint32_t mpic_src_msg_read (void *opaque, target_phys_addr_t addr) if (addr & 0xF) return retval; - addr -= MPIC_MSG_REG_START & (OPENPIC_PAGE_SIZE - 1); if (addr < MPIC_MSG_REG_SIZE) { idx += (addr & 0xFFF0) >> 5; if (addr & 0x10) { @@ -1511,7 +1505,6 @@ static void mpic_src_msi_write (void *opaque, target_phys_addr_t addr, if (addr & 0xF) return; - addr -= MPIC_MSI_REG_START & (OPENPIC_PAGE_SIZE - 1); if (addr < MPIC_MSI_REG_SIZE) { idx += (addr & 0xFFF0) >> 5; if (addr & 0x10) { @@ -1534,7 +1527,6 @@ static uint32_t mpic_src_msi_read (void *opaque, target_phys_addr_t addr) if (addr & 0xF) return retval; - addr -= MPIC_MSI_REG_START & (OPENPIC_PAGE_SIZE - 1); if (addr < MPIC_MSI_REG_SIZE) { idx += (addr & 0xFFF0) >> 5; if (addr & 0x10) { -- cgit v1.2.3