From d43b45e220ae82081e389ae113f6f03d9294fdcf Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 1 Nov 2011 16:49:05 +0000 Subject: [PATCH 01/27] pseries: Fix initialization of sPAPREnvironment structure Since we added PCI support to the pseries machine, we include a qlist of PCI host bridges in the sPAPREnvironment structure. However this list was never properly initialized it. Somehow we got away with this until some other recent change broke it, and we now segfault immediately on startup. This patch adds the required QLIST_INIT(), and while we're at it makes sure we initialize the rest of the sPAPREnvironment structure to 0, to avoid future nasty surprises. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/spapr.c b/hw/spapr.c index bdaa938b6..40cfc9be1 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -407,7 +407,9 @@ static void ppc_spapr_init(ram_addr_t ram_size, long pteg_shift = 17; char *filename; - spapr = g_malloc(sizeof(*spapr)); + spapr = g_malloc0(sizeof(*spapr)); + QLIST_INIT(&spapr->phbs); + cpu_ppc_hypercall = emulate_spapr_hypercall; /* Allocate RMA if necessary */ From 9df3b45dd4e6e5a856a08e5c7799a3434e9e5ccf Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 30 Oct 2011 19:57:33 +0000 Subject: [PATCH 02/27] tcg-ppc64: Fix compile errors for userspace only builds with gcc 4.6 tcg/ppc64/tcg-target.c has a couple of places where variables are set unconditionally, but otherwise used only for softmmu builds, not userspace only builds. This causes compiler warnings (which are fatal by default) when compiling for a ppc64 host with gcc 4.6. This patch fixes the problem by moving the code which defines and sets the variables into the CONFIG_SOFTMMU guarded regions. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- tcg/ppc64/tcg-target.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c index 3d24cd4da..41f1e85cc 100644 --- a/tcg/ppc64/tcg-target.c +++ b/tcg/ppc64/tcg-target.c @@ -616,18 +616,19 @@ static void tcg_out_tlb_read (TCGContext *s, int r0, int r1, int r2, static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) { - int addr_reg, data_reg, r0, r1, rbase, mem_index, s_bits, bswap; + int addr_reg, data_reg, r0, r1, rbase, bswap; #ifdef CONFIG_SOFTMMU - int r2; + int r2, mem_index, s_bits; void *label1_ptr, *label2_ptr; #endif data_reg = *args++; addr_reg = *args++; + +#ifdef CONFIG_SOFTMMU mem_index = *args; s_bits = opc & 3; -#ifdef CONFIG_SOFTMMU r0 = 3; r1 = 4; r2 = 0; @@ -763,17 +764,18 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc) static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc) { - int addr_reg, r0, r1, rbase, data_reg, mem_index, bswap; + int addr_reg, r0, r1, rbase, data_reg, bswap; #ifdef CONFIG_SOFTMMU - int r2; + int r2, mem_index; void *label1_ptr, *label2_ptr; #endif data_reg = *args++; addr_reg = *args++; - mem_index = *args; #ifdef CONFIG_SOFTMMU + mem_index = *args; + r0 = 3; r1 = 4; r2 = 0; From ee2b39946312952f5aa99cf9b7bab238cd5b6329 Mon Sep 17 00:00:00 2001 From: Sebastian Bauer Date: Wed, 10 Aug 2011 01:41:48 +0000 Subject: [PATCH 03/27] PPC: Fix for the gdb single step problem on an rfi instruction When using gdb to single step a ppc interrupt routine, the execution flow passes the rfi instruction without actually returning from the interrupt. The patch fixes this by avoiding to update the nip when the debug exception is raised and a previous POWERPC_EXCP_SYNC was set. The latter is the case only, if code for rfi or a related instruction was generated. Signed-off-by: Sebastian Bauer Signed-off-by: Alexander Graf --- target-ppc/translate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 99e995c7b..66eae3020 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -298,8 +298,10 @@ static inline void gen_debug_exception(DisasContext *ctx) { TCGv_i32 t0; - if (ctx->exception != POWERPC_EXCP_BRANCH) + if ((ctx->exception != POWERPC_EXCP_BRANCH) && + (ctx->exception != POWERPC_EXCP_SYNC)) { gen_update_nip(ctx, ctx->nip); + } t0 = tcg_const_i32(EXCP_DEBUG); gen_helper_raise_exception(t0); tcg_temp_free_i32(t0); From 27b5979d9d5dbc5f2ef21a96481f766bf3959b57 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 14 Jul 2011 11:44:11 +0200 Subject: [PATCH 04/27] s390x: add ldeb instruction While running perl, we encountered the ldeb instruction to be used, so we implement it :). Signed-off-by: Alexander Graf --- target-s390x/helpers.h | 1 + target-s390x/op_helper.c | 9 +++++++++ target-s390x/translate.c | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/target-s390x/helpers.h b/target-s390x/helpers.h index 6ca48ebe0..01c8d0ea8 100644 --- a/target-s390x/helpers.h +++ b/target-s390x/helpers.h @@ -102,6 +102,7 @@ DEF_HELPER_3(madb, void, i32, i64, i32) DEF_HELPER_3(maebr, void, i32, i32, i32) DEF_HELPER_3(madbr, void, i32, i32, i32) DEF_HELPER_3(msdbr, void, i32, i32, i32) +DEF_HELPER_2(ldeb, void, i32, i64) DEF_HELPER_2(lxdb, void, i32, i64) DEF_HELPER_FLAGS_2(tceb, TCG_CALL_PURE, i32, i32, i64) DEF_HELPER_FLAGS_2(tcdb, TCG_CALL_PURE, i32, i32, i64) diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c index cd5767815..e5941187a 100644 --- a/target-s390x/op_helper.c +++ b/target-s390x/op_helper.c @@ -1631,6 +1631,15 @@ void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2) &env->fpu_status); } +/* convert 32-bit float to 64-bit float */ +void HELPER(ldeb)(uint32_t f1, uint64_t a2) +{ + uint32_t v2; + v2 = ldl(a2); + env->fregs[f1].d = float32_to_float64(v2, + &env->fpu_status); +} + /* convert 64-bit float to 128-bit float */ void HELPER(lxdb)(uint32_t f1, uint64_t a2) { diff --git a/target-s390x/translate.c b/target-s390x/translate.c index 6a22fded5..ee1567218 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -2214,6 +2214,10 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2, addr = get_address(s, x2, b2, d2); tmp_r1 = tcg_const_i32(r1); switch (op) { + case 0x4: /* LDEB R1,D2(X2,B2) [RXE] */ + potential_page_fault(s); + gen_helper_ldeb(tmp_r1, addr); + break; case 0x5: /* LXDB R1,D2(X2,B2) [RXE] */ potential_page_fault(s); gen_helper_lxdb(tmp_r1, addr); From 09ed75f7848522f5d6f7ccca4bc9d0ab76006142 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 14 Jul 2011 11:45:07 +0200 Subject: [PATCH 05/27] s390x: make ipte 31-bit aware When running 31-bit code we can potentially map the same virtual address twice - once as 0x0yyyyyyy and once as 0x8yyyyyyy, because the upper bit gets ignored. This also should be reflected in the tlb invalidation path, so we really invalidate also the transparently created tlb entries. Signed-off-by: Alexander Graf --- target-s390x/op_helper.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c index e5941187a..2f46bdd0f 100644 --- a/target-s390x/op_helper.c +++ b/target-s390x/op_helper.c @@ -2950,6 +2950,13 @@ void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr) /* XXX we exploit the fact that Linux passes the exact virtual address here - it's not obliged to! */ tlb_flush_page(env, page); + + /* XXX 31-bit hack */ + if (page & 0x80000000) { + tlb_flush_page(env, page & ~0x80000000); + } else { + tlb_flush_page(env, page | 0x80000000); + } } /* flush local tlb */ From b995913853b98812845b1b82ac5f61ab31d2d7b0 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 14 Jul 2011 11:49:08 +0200 Subject: [PATCH 06/27] s390x: update R and C bits in storage key When the s390x maps a page or writes happen to a page, the R and C bits get updated. The easiest way to implement this in qemu is to simply update them whenever we map a TLB translation and act according to the permissions. Signed-off-by: Alexander Graf --- target-s390x/cpu.h | 4 ++++ target-s390x/helper.c | 12 ++++++++++++ target-s390x/op_helper.c | 1 - 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index e192b50c7..95abe595b 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -819,6 +819,10 @@ struct sysib_322 { #define _PAGE_RO 0x200 /* HW read-only bit */ #define _PAGE_INVALID 0x400 /* HW invalid bit */ +#define SK_C (0x1 << 1) +#define SK_R (0x1 << 2) +#define SK_F (0x1 << 3) +#define SK_ACC_MASK (0xf << 4) /* EBCDIC handling */ diff --git a/target-s390x/helper.c b/target-s390x/helper.c index 96dd867d7..414510451 100644 --- a/target-s390x/helper.c +++ b/target-s390x/helper.c @@ -348,6 +348,7 @@ int mmu_translate(CPUState *env, target_ulong vaddr, int rw, uint64_t asc, target_ulong *raddr, int *flags) { int r = -1; + uint8_t *sk; *flags = PAGE_READ | PAGE_WRITE | PAGE_EXEC; vaddr &= TARGET_PAGE_MASK; @@ -390,6 +391,17 @@ out: *raddr = *raddr + env->psa; } + if (*raddr <= ram_size) { + sk = &env->storage_keys[*raddr / TARGET_PAGE_SIZE]; + if (*flags & PAGE_READ) { + *sk |= SK_R; + } + + if (*flags & PAGE_WRITE) { + *sk |= SK_C; + } + } + return r; } diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c index 2f46bdd0f..440e871e9 100644 --- a/target-s390x/op_helper.c +++ b/target-s390x/op_helper.c @@ -2761,7 +2761,6 @@ uint64_t HELPER(iske)(uint64_t r2) return 0; } - /* XXX maybe use qemu's internal keys? */ return env->storage_keys[addr / TARGET_PAGE_SIZE]; } From 17bb18ce16b45e61248c5238074fa9cf8bc547bf Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 14 Jul 2011 11:50:33 +0200 Subject: [PATCH 07/27] s390x: implement rrbe instruction properly The rrbe instruction resets the reference bit in the given storage key. So far, we merely made it a nop and also returned an invalid CC value, so that the kernel never knew if a page actually got accessed. This patch implements it properly, flushing the R bit and returning the correct CC value. Signed-off-by: Alexander Graf --- target-s390x/op_helper.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c index 440e871e9..364b1004e 100644 --- a/target-s390x/op_helper.c +++ b/target-s390x/op_helper.c @@ -2779,14 +2779,15 @@ void HELPER(sske)(uint32_t r1, uint64_t r2) /* reset reference bit extended */ uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2) { + uint8_t re; + uint8_t key; if (r2 > ram_size) { return 0; } - /* XXX implement */ -#if 0 - env->storage_keys[r2 / TARGET_PAGE_SIZE] &= ~SK_REFERENCED; -#endif + key = env->storage_keys[r2 / TARGET_PAGE_SIZE]; + re = key & (SK_R | SK_C); + env->storage_keys[r2 / TARGET_PAGE_SIZE] = (key & ~SK_R); /* * cc @@ -2796,7 +2797,8 @@ uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2) * 2 Reference bit one; change bit zero * 3 Reference bit one; change bit one */ - return 0; + + return re >> 1; } /* compare and swap and purge */ From 1864b94abb20fec2fbc4b99c764bc427141d79f0 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 14 Jul 2011 11:52:08 +0200 Subject: [PATCH 08/27] s390x: implement SIGP restart and shutdown An s390x OS does reboot and shutdown triggers through hypercalls that we didn't implement on the TCG backend yet. That means that so far we couldn't shut down virtual machines for example, having them hang on shutdown when not using KVM. With this patch, this restriction is gone. We can now shut down and reboot s390x virtual machines even when using the TCG backend. Signed-off-by: Alexander Graf --- target-s390x/op_helper.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c index 364b1004e..137bae74a 100644 --- a/target-s390x/op_helper.c +++ b/target-s390x/op_helper.c @@ -29,6 +29,10 @@ #include #endif +#if !defined (CONFIG_USER_ONLY) +#include "sysemu.h" +#endif + /*****************************************************************************/ /* Softmmu support */ #if !defined (CONFIG_USER_ONLY) @@ -2901,6 +2905,16 @@ uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr) env->regs[r1] &= 0xffffffff00000000ULL; cc = 1; break; +#if !defined (CONFIG_USER_ONLY) + case SIGP_RESTART: + qemu_system_reset_request(); + cpu_loop_exit(env); + break; + case SIGP_STOP: + qemu_system_shutdown_request(); + cpu_loop_exit(env); + break; +#endif default: /* unknown sigp */ fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code); From e9d86b760cca52dc35c7716873c342eb03c22b61 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Wed, 14 Sep 2011 22:22:19 +0000 Subject: [PATCH 09/27] s390: fix reset hypercall to reset the status This patch fixes the reset hypercall which is supposed to also reset the device status in device memory. This fixes the following bug: [root@localhost driver]# echo virtio0 > unbind [ 35.056966] ------------[ cut here ]------------ [ 35.057054] kernel BUG at drivers/virtio/virtio.c:157! [ 35.057113] illegal operation: 0001 [#1] SMP [ 35.057181] Modules linked in: [ 35.057243] CPU: 0 Not tainted 3.0.0-rc1-00180-g0792644-dirty #51 [ 35.057323] Process bash (pid: 497, task: 000000003e58c538, ksp: 000000003ef43978) [ 35.057409] Krnl PSW : 0704100180000000 00000000003d46f8 (virtio_check_driver_offered_feature+0x0/0x38) [ 35.057528] R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:0 CC:1 PM:0 EA:3 [ 35.057616] Krnl GPRS: 0000000000000000 0000000040000000 0000000000000007 0000000000000000 [ 35.057716] 00000000003b3be4 0000000000000001 000000003ef4d380 000000003f1cff00 [ 35.057805] 000000003ef43f18 00000000005ca620 0000000000000008 0000000000838e88 [ 35.057919] 000000000083c860 000000003f7c2e00 00000000003d46b0 000000003ef43d10 [ 35.058027] Krnl Code: 00000000003d46e8: f0b00004ebcf srp 4(12,%r0),3023(%r14),0 [ 35.058115] 00000000003d46ee: f0a0000407f4 srp 4(11,%r0),2036,0 [ 35.058207] 00000000003d46f4: a7f40001 brc 15,3d46f6 [ 35.058295] >00000000003d46f8: e31020900004 lg %r1,144(%r2) [ 35.058383] 00000000003d46fe: bf2f1080 icm %r2,15,128(%r1) [ 35.058470] 00000000003d4702: a784000d brc 8,3d471c [ 35.058557] 00000000003d4706: e32010780004 lg %r2,120(%r1) [ 35.058645] 00000000003d470c: 59302000 c %r3,0(%r2) [ 35.058748] Call Trace: [ 35.058777] ([<00000000003d469e>] virtio_dev_remove+0x36/0x90) [ 35.058852] [<00000000003f3a40>] __device_release_driver+0x7c/0xec [ 35.058936] [<00000000003f3ae8>] device_release_driver+0x38/0x48 [ 35.059023] [<00000000003f2a98>] driver_unbind+0xa4/0xc4 [ 35.059111] [<00000000002acb70>] sysfs_write_file+0xe8/0x19c [ 35.059226] [<000000000022e7a4>] vfs_write+0xb0/0x18c [ 35.059317] [<000000000022eb18>] SyS_write+0x58/0xb4 [ 35.059398] [<000000000057e674>] sysc_noemu+0x16/0x1c [ 35.059475] [<000003fffd44b6c0>] 0x3fffd44b6c0 [ 35.059531] Last Breaking-Event-Address: [ 35.059576] [<00000000003d46f4>] virtio_dev_remove+0x8c/0x90 [ 35.059646] [ 35.059661] ---[ end trace 9b1959188f21ee11 ]--- Signed-off-by: Christian Borntraeger Signed-off-by: Alexander Graf --- hw/s390-virtio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index 60c66e92c..003d5ab98 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -97,6 +97,7 @@ int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall) dev = s390_virtio_bus_find_mem(s390_bus, mem); virtio_reset(dev->vdev); + stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0); s390_virtio_device_sync(dev); break; } From 13449a6e0ecf6c73e34657100566a471f0c26bbb Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Fri, 23 Sep 2011 03:38:12 +0000 Subject: [PATCH 10/27] s390: fix short kernel command lines The default kernel command line for s390 is "root=/dev/ram0 ro" When overriding this line, we have to ensure to also copy the \0 to avoid false lines, for example, -append "root=/dev/vda" will result in "root=/dev/vda0 ro" with the current code. Signed-off-by: Christian Borntraeger Signed-off-by: Alexander Graf --- hw/s390-virtio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index 003d5ab98..ee850f055 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -230,7 +230,7 @@ static void s390_init(ram_addr_t my_ram_size, if (kernel_cmdline) { cpu_physical_memory_write(KERN_PARM_AREA, kernel_cmdline, - strlen(kernel_cmdline)); + strlen(kernel_cmdline) + 1); } /* Create VirtIO network adapters */ From 854e42f3e8d3dcaf35b018cf56618fbcd15082d9 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Tue, 4 Oct 2011 05:20:59 +0000 Subject: [PATCH 11/27] s390: Fix cpu shutdown for KVM On s390 a shutdown is the state of all CPUs being either stopped or disabled (for interrupts) waiting. We have to track the overall number of running CPUs to call the shutdown sequence accordingly. This patch implements the counting and shutdown handling for the kvm path in qemu. Lets also wrap changes to env->halted and env->exception_index. Signed-off-by: Christian Borntraeger Signed-off-by: Alexander Graf --- hw/s390-virtio.c | 32 ++++++++++++++++++++++++++++++-- target-s390x/cpu.h | 2 ++ target-s390x/kvm.c | 19 +++++++------------ 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index ee850f055..37945d5d8 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -121,6 +121,34 @@ int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall) return r; } +/* + * The number of running CPUs. On s390 a shutdown is the state of all CPUs + * being either stopped or disabled (for interrupts) waiting. We have to + * track this number to call the shutdown sequence accordingly. This + * number is modified either on startup or while holding the big qemu lock. + */ +static unsigned s390_running_cpus; + +void s390_add_running_cpu(CPUState *env) +{ + if (env->halted) { + s390_running_cpus++; + env->halted = 0; + env->exception_index = -1; + } +} + +unsigned s390_del_running_cpu(CPUState *env) +{ + if (env->halted == 0) { + assert(s390_running_cpus >= 1); + s390_running_cpus--; + env->halted = 1; + env->exception_index = EXCP_HLT; + } + return s390_running_cpus; +} + /* PC hardware initialisation */ static void s390_init(ram_addr_t my_ram_size, const char *boot_device, @@ -179,8 +207,8 @@ static void s390_init(ram_addr_t my_ram_size, tmp_env->storage_keys = storage_keys; } - env->halted = 0; - env->exception_index = 0; + /* One CPU has to run */ + s390_add_running_cpu(env); if (kernel_filename) { kernel_size = load_image(kernel_filename, qemu_get_ram_ptr(0)); diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 95abe595b..a66aa0166 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -309,6 +309,8 @@ static inline void kvm_s390_interrupt_internal(CPUState *env, int type, } #endif CPUState *s390_cpu_addr2state(uint16_t cpu_addr); +void s390_add_running_cpu(CPUState *env); +unsigned s390_del_running_cpu(CPUState *env); /* from s390-virtio-bus */ extern const target_phys_addr_t virtio_size; diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 4beb794cc..40b0ab192 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -185,8 +185,7 @@ void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm, return; } - env->halted = 0; - env->exception_index = -1; + s390_add_running_cpu(env); qemu_cpu_kick(env); kvmint.type = type; @@ -299,8 +298,7 @@ static int handle_diag(CPUState *env, struct kvm_run *run, int ipb_code) static int s390_cpu_restart(CPUState *env) { kvm_s390_interrupt(env, KVM_S390_RESTART, 0); - env->halted = 0; - env->exception_index = -1; + s390_add_running_cpu(env); qemu_cpu_kick(env); dprintf("DONE: SIGP cpu restart: %p\n", env); return 0; @@ -425,17 +423,16 @@ static int handle_intercept(CPUState *env) r = handle_instruction(env, run); break; case ICPT_WAITPSW: - /* XXX What to do on system shutdown? */ - env->halted = 1; - env->exception_index = EXCP_HLT; + case ICPT_CPU_STOP: + if (s390_del_running_cpu(env) == 0) { + qemu_system_shutdown_request(); + } + r = EXCP_HALTED; break; case ICPT_SOFT_INTERCEPT: fprintf(stderr, "KVM unimplemented icpt SOFT\n"); exit(1); break; - case ICPT_CPU_STOP: - qemu_system_shutdown_request(); - break; case ICPT_IO: fprintf(stderr, "KVM unimplemented icpt IO\n"); exit(1); @@ -468,8 +465,6 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run) if (ret == 0) { ret = EXCP_INTERRUPT; - } else if (ret > 0) { - ret = 0; } return ret; } From ef81522bc18e234485282a6fa01671d1960bc0f2 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 7 Oct 2011 09:51:50 +0200 Subject: [PATCH 12/27] s390x: Add shutdown for TCG s390-virtio machine Now that we have code in place to do refcounting of online CPUs, we can drag the TCG code along and implement shutdown for that one too, so it doesn't feel left out by its KVM counterpart. Signed-off-by: Alexander Graf --- target-s390x/cpu.h | 9 +++++++++ target-s390x/helper.c | 15 ++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index a66aa0166..202c098ee 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -315,6 +315,15 @@ unsigned s390_del_running_cpu(CPUState *env); /* from s390-virtio-bus */ extern const target_phys_addr_t virtio_size; +#else +static inline void s390_add_running_cpu(CPUState *env) +{ +} + +static inline unsigned s390_del_running_cpu(CPUState *env) +{ + return 0; +} #endif void cpu_lock(void); void cpu_unlock(void); diff --git a/target-s390x/helper.c b/target-s390x/helper.c index 414510451..10cc9dd5f 100644 --- a/target-s390x/helper.c +++ b/target-s390x/helper.c @@ -26,6 +26,9 @@ #include "gdbstub.h" #include "qemu-common.h" #include "qemu-timer.h" +#ifndef CONFIG_USER_ONLY +#include "sysemu.h" +#endif //#define DEBUG_S390 //#define DEBUG_S390_PTE @@ -131,6 +134,7 @@ void cpu_reset(CPUS390XState *env) memset(env, 0, offsetof(CPUS390XState, breakpoints)); /* FIXME: reset vector? */ tlb_flush(env, 1); + s390_add_running_cpu(env); } #ifndef CONFIG_USER_ONLY @@ -466,11 +470,15 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong vaddr) void load_psw(CPUState *env, uint64_t mask, uint64_t addr) { if (mask & PSW_MASK_WAIT) { + if (!(mask & (PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK))) { + if (s390_del_running_cpu(env) == 0) { +#ifndef CONFIG_USER_ONLY + qemu_system_shutdown_request(); +#endif + } + } env->halted = 1; env->exception_index = EXCP_HLT; - if (!(mask & (PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK))) { - /* XXX disabled wait state - CPU is dead */ - } } env->psw.addr = addr; @@ -599,6 +607,7 @@ void do_interrupt (CPUState *env) qemu_log("%s: %d at pc=%" PRIx64 "\n", __FUNCTION__, env->exception_index, env->psw.addr); + s390_add_running_cpu(env); /* handle external interrupts */ if ((env->psw.mask & PSW_MASK_EXT) && env->exception_index == -1) { From 771142c2a7d67d491962fdf8e94d27513849d5b3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 9 Nov 2011 08:03:33 +0000 Subject: [PATCH 13/27] tcg: Standardize on TCGReg as the enum for hard registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most targets did not name the enum; tci used TCGRegister. Signed-off-by: Richard Henderson Reviewed-by: Andreas Färber Reviewed-by: Stefan Weil Signed-off-by: Alexander Graf --- tcg/arm/tcg-target.h | 4 ++-- tcg/hppa/tcg-target.h | 4 ++-- tcg/i386/tcg-target.h | 4 ++-- tcg/ia64/tcg-target.h | 4 ++-- tcg/mips/tcg-target.h | 4 ++-- tcg/ppc/tcg-target.h | 4 ++-- tcg/ppc64/tcg-target.h | 4 ++-- tcg/sparc/tcg-target.h | 4 ++-- tcg/tci/tcg-target.h | 2 +- tci.c | 38 +++++++++++++++++++------------------- 10 files changed, 36 insertions(+), 36 deletions(-) diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index 33afd9789..48586c3e6 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -27,7 +27,7 @@ #undef TCG_TARGET_WORDS_BIGENDIAN #undef TCG_TARGET_STACK_GROWSUP -enum { +typedef enum { TCG_REG_R0 = 0, TCG_REG_R1, TCG_REG_R2, @@ -44,7 +44,7 @@ enum { TCG_REG_R13, TCG_REG_R14, TCG_REG_PC, -}; +} TCGReg; #define TCG_TARGET_NB_REGS 16 diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h index ec9a7bf25..7f3c4cc3e 100644 --- a/tcg/hppa/tcg-target.h +++ b/tcg/hppa/tcg-target.h @@ -32,7 +32,7 @@ #define TCG_TARGET_NB_REGS 32 -enum { +typedef enum { TCG_REG_R0 = 0, TCG_REG_R1, TCG_REG_RP, @@ -65,7 +65,7 @@ enum { TCG_REG_RET1, TCG_REG_SP, TCG_REG_R31, -}; +} TCGReg; #define TCG_CT_CONST_0 0x0100 #define TCG_CT_CONST_S5 0x0200 diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h index b9c9d4e8c..7756e7b03 100644 --- a/tcg/i386/tcg-target.h +++ b/tcg/i386/tcg-target.h @@ -36,7 +36,7 @@ # define TCG_TARGET_NB_REGS 8 #endif -enum { +typedef enum { TCG_REG_EAX = 0, TCG_REG_ECX, TCG_REG_EDX, @@ -64,7 +64,7 @@ enum { TCG_REG_RBP = TCG_REG_EBP, TCG_REG_RSI = TCG_REG_ESI, TCG_REG_RDI = TCG_REG_EDI, -}; +} TCGReg; #define TCG_CT_CONST_S32 0x100 #define TCG_CT_CONST_U32 0x200 diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h index 578cf2954..c38808900 100644 --- a/tcg/ia64/tcg-target.h +++ b/tcg/ia64/tcg-target.h @@ -26,7 +26,7 @@ /* We only map the first 64 registers */ #define TCG_TARGET_NB_REGS 64 -enum { +typedef enum { TCG_REG_R0 = 0, TCG_REG_R1, TCG_REG_R2, @@ -91,7 +91,7 @@ enum { TCG_REG_R61, TCG_REG_R62, TCG_REG_R63, -}; +} TCGReg; #define TCG_CT_CONST_ZERO 0x100 #define TCG_CT_CONST_S22 0x200 diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index e2a2571f9..477bc38b0 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -31,7 +31,7 @@ #define TCG_TARGET_NB_REGS 32 -enum { +typedef enum { TCG_REG_ZERO = 0, TCG_REG_AT, TCG_REG_V0, @@ -64,7 +64,7 @@ enum { TCG_REG_SP, TCG_REG_FP, TCG_REG_RA, -}; +} TCGReg; #define TCG_CT_CONST_ZERO 0x100 #define TCG_CT_CONST_U16 0x200 diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h index 25a6ea4ed..3f22aaac9 100644 --- a/tcg/ppc/tcg-target.h +++ b/tcg/ppc/tcg-target.h @@ -26,7 +26,7 @@ #define TCG_TARGET_WORDS_BIGENDIAN #define TCG_TARGET_NB_REGS 32 -enum { +typedef enum { TCG_REG_R0 = 0, TCG_REG_R1, TCG_REG_R2, @@ -59,7 +59,7 @@ enum { TCG_REG_R29, TCG_REG_R30, TCG_REG_R31 -}; +} TCGReg; /* used for function call generation */ #define TCG_REG_CALL_STACK TCG_REG_R1 diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h index 8d1fb738e..97eec0843 100644 --- a/tcg/ppc64/tcg-target.h +++ b/tcg/ppc64/tcg-target.h @@ -26,7 +26,7 @@ #define TCG_TARGET_WORDS_BIGENDIAN #define TCG_TARGET_NB_REGS 32 -enum { +typedef enum { TCG_REG_R0 = 0, TCG_REG_R1, TCG_REG_R2, @@ -59,7 +59,7 @@ enum { TCG_REG_R29, TCG_REG_R30, TCG_REG_R31 -}; +} TCGReg; /* used for function call generation */ #define TCG_REG_CALL_STACK TCG_REG_R1 diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h index 1464ef40c..c3fe13111 100644 --- a/tcg/sparc/tcg-target.h +++ b/tcg/sparc/tcg-target.h @@ -27,7 +27,7 @@ #define TCG_TARGET_NB_REGS 32 -enum { +typedef enum { TCG_REG_G0 = 0, TCG_REG_G1, TCG_REG_G2, @@ -60,7 +60,7 @@ enum { TCG_REG_I5, TCG_REG_I6, TCG_REG_I7, -}; +} TCGReg; #define TCG_CT_CONST_S11 0x100 #define TCG_CT_CONST_S13 0x200 diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h index 81ded8695..cb5858c9c 100644 --- a/tcg/tci/tcg-target.h +++ b/tcg/tci/tcg-target.h @@ -150,7 +150,7 @@ typedef enum { #endif /* Special value UINT8_MAX is used by TCI to encode constant values. */ TCG_CONST = UINT8_MAX -} TCGRegister; +} TCGReg; void tci_disas(uint8_t opc); diff --git a/tci.c b/tci.c index f17785dc9..a20a7142e 100644 --- a/tci.c +++ b/tci.c @@ -63,90 +63,90 @@ void *tci_tb_ptr; static tcg_target_ulong tci_reg[TCG_TARGET_NB_REGS]; -static tcg_target_ulong tci_read_reg(TCGRegister index) +static tcg_target_ulong tci_read_reg(TCGReg index) { assert(index < ARRAY_SIZE(tci_reg)); return tci_reg[index]; } #if TCG_TARGET_HAS_ext8s_i32 || TCG_TARGET_HAS_ext8s_i64 -static int8_t tci_read_reg8s(TCGRegister index) +static int8_t tci_read_reg8s(TCGReg index) { return (int8_t)tci_read_reg(index); } #endif #if TCG_TARGET_HAS_ext16s_i32 || TCG_TARGET_HAS_ext16s_i64 -static int16_t tci_read_reg16s(TCGRegister index) +static int16_t tci_read_reg16s(TCGReg index) { return (int16_t)tci_read_reg(index); } #endif #if TCG_TARGET_REG_BITS == 64 -static int32_t tci_read_reg32s(TCGRegister index) +static int32_t tci_read_reg32s(TCGReg index) { return (int32_t)tci_read_reg(index); } #endif -static uint8_t tci_read_reg8(TCGRegister index) +static uint8_t tci_read_reg8(TCGReg index) { return (uint8_t)tci_read_reg(index); } -static uint16_t tci_read_reg16(TCGRegister index) +static uint16_t tci_read_reg16(TCGReg index) { return (uint16_t)tci_read_reg(index); } -static uint32_t tci_read_reg32(TCGRegister index) +static uint32_t tci_read_reg32(TCGReg index) { return (uint32_t)tci_read_reg(index); } #if TCG_TARGET_REG_BITS == 64 -static uint64_t tci_read_reg64(TCGRegister index) +static uint64_t tci_read_reg64(TCGReg index) { return tci_read_reg(index); } #endif -static void tci_write_reg(TCGRegister index, tcg_target_ulong value) +static void tci_write_reg(TCGReg index, tcg_target_ulong value) { assert(index < ARRAY_SIZE(tci_reg)); assert(index != TCG_AREG0); tci_reg[index] = value; } -static void tci_write_reg8s(TCGRegister index, int8_t value) +static void tci_write_reg8s(TCGReg index, int8_t value) { tci_write_reg(index, value); } -static void tci_write_reg16s(TCGRegister index, int16_t value) +static void tci_write_reg16s(TCGReg index, int16_t value) { tci_write_reg(index, value); } #if TCG_TARGET_REG_BITS == 64 -static void tci_write_reg32s(TCGRegister index, int32_t value) +static void tci_write_reg32s(TCGReg index, int32_t value) { tci_write_reg(index, value); } #endif -static void tci_write_reg8(TCGRegister index, uint8_t value) +static void tci_write_reg8(TCGReg index, uint8_t value) { tci_write_reg(index, value); } -static void tci_write_reg16(TCGRegister index, uint16_t value) +static void tci_write_reg16(TCGReg index, uint16_t value) { tci_write_reg(index, value); } -static void tci_write_reg32(TCGRegister index, uint32_t value) +static void tci_write_reg32(TCGReg index, uint32_t value) { tci_write_reg(index, value); } @@ -159,7 +159,7 @@ static void tci_write_reg64(uint32_t high_index, uint32_t low_index, tci_write_reg(high_index, value >> 32); } #elif TCG_TARGET_REG_BITS == 64 -static void tci_write_reg64(TCGRegister index, uint64_t value) +static void tci_write_reg64(TCGReg index, uint64_t value) { tci_write_reg(index, value); } @@ -290,7 +290,7 @@ static target_ulong tci_read_ulong(uint8_t **tb_ptr) static tcg_target_ulong tci_read_ri(uint8_t **tb_ptr) { tcg_target_ulong value; - TCGRegister r = **tb_ptr; + TCGReg r = **tb_ptr; *tb_ptr += 1; if (r == TCG_CONST) { value = tci_read_i(tb_ptr); @@ -304,7 +304,7 @@ static tcg_target_ulong tci_read_ri(uint8_t **tb_ptr) static uint32_t tci_read_ri32(uint8_t **tb_ptr) { uint32_t value; - TCGRegister r = **tb_ptr; + TCGReg r = **tb_ptr; *tb_ptr += 1; if (r == TCG_CONST) { value = tci_read_i32(tb_ptr); @@ -326,7 +326,7 @@ static uint64_t tci_read_ri64(uint8_t **tb_ptr) static uint64_t tci_read_ri64(uint8_t **tb_ptr) { uint64_t value; - TCGRegister r = **tb_ptr; + TCGReg r = **tb_ptr; *tb_ptr += 1; if (r == TCG_CONST) { value = tci_read_i64(tb_ptr); From 2a534aff30b29f7e504451c6ed04658e850144ba Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 9 Nov 2011 08:03:34 +0000 Subject: [PATCH 14/27] tcg: Use TCGReg for standard tcg-target entry points. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Including tcg_out_ld, tcg_out_st, tcg_out_mov, tcg_out_movi. Signed-off-by: Richard Henderson Reviewed-by: Andreas Färber Reviewed-by: Stefan Weil Signed-off-by: Alexander Graf --- tcg/arm/tcg-target.c | 13 +++++++------ tcg/hppa/tcg-target.c | 12 ++++++------ tcg/i386/tcg-target.c | 13 +++++++------ tcg/ia64/tcg-target.c | 12 ++++++------ tcg/mips/tcg-target.c | 13 +++++++------ tcg/ppc/tcg-target.c | 8 ++++---- tcg/ppc64/tcg-target.c | 8 ++++---- tcg/sparc/tcg-target.c | 13 +++++++------ tcg/tcg.c | 8 ++++---- tcg/tci/tcg-target.c | 8 ++++---- 10 files changed, 56 insertions(+), 52 deletions(-) diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index ce4760d23..e05a64f75 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -1808,25 +1808,26 @@ static void tcg_target_init(TCGContext *s) CPU_TEMP_BUF_NLONGS * sizeof(long)); } -static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg, - int arg1, tcg_target_long arg2) +static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, + TCGReg arg1, tcg_target_long arg2) { tcg_out_ld32u(s, COND_AL, arg, arg1, arg2); } -static inline void tcg_out_st(TCGContext *s, TCGType type, int arg, - int arg1, tcg_target_long arg2) +static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, + TCGReg arg1, tcg_target_long arg2) { tcg_out_st32(s, COND_AL, arg, arg1, arg2); } -static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg) +static inline void tcg_out_mov(TCGContext *s, TCGType type, + TCGReg ret, TCGReg arg) { tcg_out_dat_reg(s, COND_AL, ARITH_MOV, ret, 0, arg, SHIFT_IMM_LSL(0)); } static inline void tcg_out_movi(TCGContext *s, TCGType type, - int ret, tcg_target_long arg) + TCGReg ret, tcg_target_long arg) { tcg_out_movi32(s, COND_AL, ret, arg); } diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c index 71d9677ab..59d4d12ba 100644 --- a/tcg/hppa/tcg-target.c +++ b/tcg/hppa/tcg-target.c @@ -338,7 +338,7 @@ static int tcg_target_const_match(tcg_target_long val, /* supplied by libgcc */ extern void *__canonicalize_funcptr_for_compare(void *); -static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg) +static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) { /* PA1.1 defines COPY as OR r,0,t; PA2.0 defines COPY as LDO 0(r),t but hppa-dis.c is unaware of this definition */ @@ -349,7 +349,7 @@ static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg) } static void tcg_out_movi(TCGContext *s, TCGType type, - int ret, tcg_target_long arg) + TCGReg ret, tcg_target_long arg) { if (check_fit_tl(arg, 14)) { tcg_out32(s, INSN_LDO | INSN_R1(ret) @@ -393,15 +393,15 @@ static void tcg_out_ldst(TCGContext *s, int ret, int addr, } /* This function is required by tcg.c. */ -static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret, - int arg1, tcg_target_long arg2) +static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, + TCGReg arg1, tcg_target_long arg2) { tcg_out_ldst(s, ret, arg1, arg2, INSN_LDW); } /* This function is required by tcg.c. */ -static inline void tcg_out_st(TCGContext *s, TCGType type, int ret, - int arg1, tcg_target_long arg2) +static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg ret, + TCGReg arg1, tcg_target_long arg2) { tcg_out_ldst(s, ret, arg1, arg2, INSN_STW); } diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 3069e53bc..dc81572c0 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -518,7 +518,8 @@ static inline void tgen_arithr(TCGContext *s, int subop, int dest, int src) tcg_out_modrm(s, OPC_ARITH_GvEv + (subop << 3) + ext, dest, src); } -static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg) +static inline void tcg_out_mov(TCGContext *s, TCGType type, + TCGReg ret, TCGReg arg) { if (arg != ret) { int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0); @@ -527,7 +528,7 @@ static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg) } static void tcg_out_movi(TCGContext *s, TCGType type, - int ret, tcg_target_long arg) + TCGReg ret, tcg_target_long arg) { if (arg == 0) { tgen_arithr(s, ARITH_XOR, ret, ret); @@ -568,15 +569,15 @@ static inline void tcg_out_pop(TCGContext *s, int reg) tcg_out_opc(s, OPC_POP_r32 + LOWREGMASK(reg), 0, reg, 0); } -static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret, - int arg1, tcg_target_long arg2) +static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, + TCGReg arg1, tcg_target_long arg2) { int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0); tcg_out_modrm_offset(s, opc, ret, arg1, arg2); } -static inline void tcg_out_st(TCGContext *s, TCGType type, int arg, - int arg1, tcg_target_long arg2) +static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, + TCGReg arg1, tcg_target_long arg2) { int opc = OPC_MOVL_EvGv + (type == TCG_TYPE_I64 ? P_REXW : 0); tcg_out_modrm_offset(s, opc, arg, arg1, arg2); diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c index bb22b9abe..e3de79fdb 100644 --- a/tcg/ia64/tcg-target.c +++ b/tcg/ia64/tcg-target.c @@ -830,7 +830,7 @@ static inline void tcg_out_bundle(TCGContext *s, int template, } static inline void tcg_out_mov(TCGContext *s, TCGType type, - TCGArg ret, TCGArg arg) + TCGReg ret, TCGReg arg) { tcg_out_bundle(s, mmI, tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), @@ -839,7 +839,7 @@ static inline void tcg_out_mov(TCGContext *s, TCGType type, } static inline void tcg_out_movi(TCGContext *s, TCGType type, - TCGArg reg, tcg_target_long arg) + TCGReg reg, tcg_target_long arg) { tcg_out_bundle(s, mLX, tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0), @@ -972,8 +972,8 @@ static inline void tcg_out_st_rel(TCGContext *s, uint64_t opc_m4, TCGArg arg, } } -static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGArg arg, - TCGArg arg1, tcg_target_long arg2) +static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, + TCGReg arg1, tcg_target_long arg2) { if (type == TCG_TYPE_I32) { tcg_out_ld_rel(s, OPC_LD4_M1, arg, arg1, arg2); @@ -982,8 +982,8 @@ static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGArg arg, } } -static inline void tcg_out_st(TCGContext *s, TCGType type, TCGArg arg, - TCGArg arg1, tcg_target_long arg2) +static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, + TCGReg arg1, tcg_target_long arg2) { if (type == TCG_TYPE_I32) { tcg_out_st_rel(s, OPC_ST4_M4, arg, arg1, arg2); diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index a33d21fd0..c5c32825f 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -379,13 +379,14 @@ static inline void tcg_out_nop(TCGContext *s) tcg_out32(s, 0); } -static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg) +static inline void tcg_out_mov(TCGContext *s, TCGType type, + TCGReg ret, TCGReg arg) { tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO); } static inline void tcg_out_movi(TCGContext *s, TCGType type, - int reg, int32_t arg) + TCGReg reg, tcg_target_long arg) { if (arg == (int16_t)arg) { tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg); @@ -480,14 +481,14 @@ static inline void tcg_out_ldst(TCGContext *s, int opc, int arg, } } -static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg, - int arg1, tcg_target_long arg2) +static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, + TCGReg arg1, tcg_target_long arg2) { tcg_out_ldst(s, OPC_LW, arg, arg1, arg2); } -static inline void tcg_out_st(TCGContext *s, TCGType type, int arg, - int arg1, tcg_target_long arg2) +static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, + TCGReg arg1, tcg_target_long arg2) { tcg_out_ldst(s, OPC_SW, arg, arg1, arg2); } diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index 87cc1177f..f5d9bf3b0 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -436,13 +436,13 @@ static const uint32_t tcg_to_bc[10] = { [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE, }; -static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg) +static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) { tcg_out32 (s, OR | SAB (arg, ret, arg)); } static void tcg_out_movi(TCGContext *s, TCGType type, - int ret, tcg_target_long arg) + TCGReg ret, tcg_target_long arg) { if (arg == (int16_t) arg) tcg_out32 (s, ADDI | RT (ret) | RA (0) | (arg & 0xffff)); @@ -961,13 +961,13 @@ static void tcg_target_qemu_prologue (TCGContext *s) tcg_out32 (s, BCLR | BO_ALWAYS); } -static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1, +static void tcg_out_ld (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, tcg_target_long arg2) { tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX); } -static void tcg_out_st (TCGContext *s, TCGType type, int arg, int arg1, +static void tcg_out_st (TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, tcg_target_long arg2) { tcg_out_ldst (s, arg, arg1, arg2, STW, STWX); diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c index 3d24cd4da..480097719 100644 --- a/tcg/ppc64/tcg-target.c +++ b/tcg/ppc64/tcg-target.c @@ -435,7 +435,7 @@ static const uint32_t tcg_to_bc[10] = { [TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE, }; -static void tcg_out_mov (TCGContext *s, TCGType type, int ret, int arg) +static void tcg_out_mov (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) { tcg_out32 (s, OR | SAB (arg, ret, arg)); } @@ -459,7 +459,7 @@ static void tcg_out_movi32 (TCGContext *s, int ret, int32_t arg) } static void tcg_out_movi (TCGContext *s, TCGType type, - int ret, tcg_target_long arg) + TCGReg ret, tcg_target_long arg) { int32_t arg32 = arg; arg = type == TCG_TYPE_I32 ? arg & 0xffffffff : arg; @@ -930,7 +930,7 @@ static void tcg_target_qemu_prologue (TCGContext *s) tcg_out32 (s, BCLR | BO_ALWAYS); } -static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1, +static void tcg_out_ld (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, tcg_target_long arg2) { if (type == TCG_TYPE_I32) @@ -939,7 +939,7 @@ static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1, tcg_out_ldsta (s, ret, arg1, arg2, LD, LDX); } -static void tcg_out_st (TCGContext *s, TCGType type, int arg, int arg1, +static void tcg_out_st (TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, tcg_target_long arg2) { if (type == TCG_TYPE_I32) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index fc3fd7ffc..b96312b3b 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -306,7 +306,8 @@ static void tcg_out_arithc(TCGContext *s, int rd, int rs1, | (val2const ? INSN_IMM13(val2) : INSN_RS2(val2))); } -static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg) +static inline void tcg_out_mov(TCGContext *s, TCGType type, + TCGReg ret, TCGReg arg) { tcg_out_arith(s, ret, arg, TCG_REG_G0, ARITH_OR); } @@ -333,7 +334,7 @@ static inline void tcg_out_movi_imm32(TCGContext *s, int ret, uint32_t arg) } static inline void tcg_out_movi(TCGContext *s, TCGType type, - int ret, tcg_target_long arg) + TCGReg ret, tcg_target_long arg) { /* All 32-bit constants, as well as 64-bit constants with no high bits set go through movi_imm32. */ @@ -398,8 +399,8 @@ static inline void tcg_out_ldst_asi(TCGContext *s, int ret, int addr, INSN_ASI(asi) | INSN_RS2(addr)); } -static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret, - int arg1, tcg_target_long arg2) +static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, + TCGReg arg1, tcg_target_long arg2) { if (type == TCG_TYPE_I32) tcg_out_ldst(s, ret, arg1, arg2, LDUW); @@ -407,8 +408,8 @@ static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret, tcg_out_ldst(s, ret, arg1, arg2, LDX); } -static inline void tcg_out_st(TCGContext *s, TCGType type, int arg, - int arg1, tcg_target_long arg2) +static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, + TCGReg arg1, tcg_target_long arg2) { if (type == TCG_TYPE_I32) tcg_out_ldst(s, arg, arg1, arg2, STW); diff --git a/tcg/tcg.c b/tcg/tcg.c index 6b27d7bfa..77bd6ef74 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -71,14 +71,14 @@ static void patch_reloc(uint8_t *code_ptr, int type, /* Forward declarations for functions declared and used in tcg-target.c. */ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str); -static void tcg_out_ld(TCGContext *s, TCGType type, int ret, int arg1, +static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, tcg_target_long arg2); -static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg); +static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg); static void tcg_out_movi(TCGContext *s, TCGType type, - int ret, tcg_target_long arg); + TCGReg ret, tcg_target_long arg); static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, const int *const_args); -static void tcg_out_st(TCGContext *s, TCGType type, int arg, int arg1, +static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, tcg_target_long arg2); static int tcg_target_const_match(tcg_target_long val, const TCGArgConstraint *arg_ct); diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c index e373e2a70..942910e14 100644 --- a/tcg/tci/tcg-target.c +++ b/tcg/tci/tcg-target.c @@ -495,7 +495,7 @@ static void tci_out_label(TCGContext *s, TCGArg arg) } } -static void tcg_out_ld(TCGContext *s, TCGType type, int ret, int arg1, +static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, tcg_target_long arg2) { uint8_t *old_code_ptr = s->code_ptr; @@ -519,7 +519,7 @@ static void tcg_out_ld(TCGContext *s, TCGType type, int ret, int arg1, old_code_ptr[1] = s->code_ptr - old_code_ptr; } -static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg) +static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) { uint8_t *old_code_ptr = s->code_ptr; assert(ret != arg); @@ -534,7 +534,7 @@ static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg) } static void tcg_out_movi(TCGContext *s, TCGType type, - int t0, tcg_target_long arg) + TCGReg t0, tcg_target_long arg) { uint8_t *old_code_ptr = s->code_ptr; uint32_t arg32 = arg; @@ -834,7 +834,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, old_code_ptr[1] = s->code_ptr - old_code_ptr; } -static void tcg_out_st(TCGContext *s, TCGType type, int arg, int arg1, +static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1, tcg_target_long arg2) { uint8_t *old_code_ptr = s->code_ptr; From 326384d5b6dcea69ca44695ee807f8b50234ab71 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 10 Nov 2011 01:59:23 +0100 Subject: [PATCH 15/27] s390x: initialize virtio dev region MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When running the s390x virtio machine we can potentially use uninitialized memory for the virtio device backing ram. That can lead to weird breakge. So let's better initialize it to 0 properly. Reported-by: Andreas Färber Signed-off-by: Alexander Graf --- v1 -> v2: - use target_phys_addr_t --- hw/s390-virtio.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c index 37945d5d8..61b67e8c3 100644 --- a/hw/s390-virtio.c +++ b/hw/s390-virtio.c @@ -165,6 +165,9 @@ static void s390_init(ram_addr_t my_ram_size, ram_addr_t initrd_size = 0; int shift = 0; uint8_t *storage_keys; + void *virtio_region; + target_phys_addr_t virtio_region_len; + target_phys_addr_t virtio_region_start; int i; /* s390x ram size detection needs a 16bit multiplier + an increment. So @@ -184,6 +187,15 @@ static void s390_init(ram_addr_t my_ram_size, memory_region_init_ram(ram, NULL, "s390.ram", my_ram_size); memory_region_add_subregion(sysmem, 0, ram); + /* clear virtio region */ + virtio_region_len = my_ram_size - ram_size; + virtio_region_start = ram_size; + virtio_region = cpu_physical_memory_map(virtio_region_start, + &virtio_region_len, true); + memset(virtio_region, 0, virtio_region_len); + cpu_physical_memory_unmap(virtio_region, virtio_region_len, 1, + virtio_region_len); + /* allocate storage keys */ storage_keys = g_malloc0(my_ram_size / TARGET_PAGE_SIZE); From 92c93a816a8c04071264f9fb47cbc90a5e1ae5d8 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 13 Nov 2011 17:18:57 +0000 Subject: [PATCH 16/27] pseries: Correct RAM size check for SLOF The SLOF firmware used on the pseries machine needs a reasonable amount of (guest) RAM in order to run, so we have a check in the machine init function to check that this is available. However, SLOF runs in real mode (MMU off) which means it can only actually access the RMA (Real Mode Area), not all of RAM. In many cases the RMA is the same as all RAM, but when running with Book3S HV KVM on PowerPC 970, the RMA must be especially allocated to be (host) physically contiguous. In this case, the RMA size is determined by what the host admin allocated at boot time, and will usually be less than the whole guest RAM size. This patch corrects the test to see if SLOF has enough memory for this case. In addition, more recent versions of SLOF that were committed earlier don't need quite as much memory as earlier versions. Therefore, this patch also reduces the amount of RAM we require to run SLOF. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/spapr.c b/hw/spapr.c index 40cfc9be1..2b901f105 100644 --- a/hw/spapr.c +++ b/hw/spapr.c @@ -57,7 +57,7 @@ #define FW_MAX_SIZE 0x400000 #define FW_FILE_NAME "slof.bin" -#define MIN_RAM_SLOF 512UL +#define MIN_RMA_SLOF 128UL #define TIMEBASE_FREQ 512000000ULL @@ -562,9 +562,9 @@ static void ppc_spapr_init(ram_addr_t ram_size, spapr->entry_point = KERNEL_LOAD_ADDR; } else { - if (ram_size < (MIN_RAM_SLOF << 20)) { + if (rma_size < (MIN_RMA_SLOF << 20)) { fprintf(stderr, "qemu: pSeries SLOF firmware requires >= " - "%ldM guest RAM\n", MIN_RAM_SLOF); + "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF); exit(1); } filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME); From 5435352ce6abfb8a7540ae7d47e981d329120cca Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 13 Nov 2011 17:18:58 +0000 Subject: [PATCH 17/27] pseries: Fix buggy spapr_vio_find_by_reg() The spapr_vio_find_by_reg() function in hw/spapr_vio.c is supposed to find the device structure for a PAPR virtual IO device with the given reg value, and return NULL if none exists. It does the first ok, but if no device with that reg exists, it just returns the last device traversed in the list. This patch fixes it. Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr_vio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index 25cfc9d91..b7b3ddd11 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -66,11 +66,11 @@ VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg) QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) { dev = (VIOsPAPRDevice *)qdev; if (dev->reg == reg) { - break; + return dev; } } - return dev; + return NULL; } #ifdef CONFIG_FDT From 57285302af51a8bae334c03e1f8243e935373953 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Sun, 13 Nov 2011 17:18:59 +0000 Subject: [PATCH 18/27] pseries: Check we have a chardev in spapr_vty_init() If qemu is run like: qemu-system-ppc64 -nodefaults -device spapr-vty We end up in spapr_vty_init() with dev->chardev == NULL. Currently that leads to a segfault because we unconditionally call qemu_chr_add_handlers(). Although we could make that call conditional, I think a spapr-vty without a chardev is basically useless so fail the init. This is similar to what the serial code does for example. Signed-off-by: Michael Ellerman Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr_vty.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c index a9d4b035e..f4f3ee32a 100644 --- a/hw/spapr_vty.c +++ b/hw/spapr_vty.c @@ -58,6 +58,11 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev) { VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev; + if (!dev->chardev) { + fprintf(stderr, "spapr-vty: Can't create vty without a chardev!\n"); + exit(1); + } + qemu_chr_add_handlers(dev->chardev, vty_can_receive, vty_receive, NULL, dev); From 5afdec404e73a578c37221b9ea226d582814acb5 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Sun, 13 Nov 2011 17:19:00 +0000 Subject: [PATCH 19/27] pseries: Default reg for vty should be SPAPR_VTY_BASE_ADDRESS In commit b4a78527359a4540d84d4cdf629d01cbb262f698 ("Place pseries vty devices at addresses more similar to existing machines"), we changed the default reg for the vty to 0x30000000, however we didn't update the default value for a user specified vty device. Fix that. Signed-off-by: Michael Ellerman Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr_vty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c index f4f3ee32a..815039501 100644 --- a/hw/spapr_vty.c +++ b/hw/spapr_vty.c @@ -145,7 +145,7 @@ static VIOsPAPRDeviceInfo spapr_vty = { .qdev.name = "spapr-vty", .qdev.size = sizeof(VIOsPAPRVTYDevice), .qdev.props = (Property[]) { - DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, 0, 0), + DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, SPAPR_VTY_BASE_ADDRESS, 0), DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev), DEFINE_PROP_END_OF_LIST(), }, From 3feef8ad17af7307373b9e88b9d7ecb98eeb99da Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sun, 13 Nov 2011 17:19:01 +0000 Subject: [PATCH 20/27] pseries: Allow kernel's early debug output to work The PAPR specification defines a virtual TTY/console interface for guest OSes to use via the H_PUT_TERM_CHAR and H_GET_TERM_CHAR hypercalls. There can be multiple virtual ttys, so these take a "termno" parameter. This encodes which vty to use as the 'reg' property on the device tree node associated with that vty. However, with the early debug options enabled, the Linux kernel will attempt debugging output through the vty very early, before it has read the device tree. In this case it always uses a termno of 0. This works on the existing PowerVM hypervisor, so we assume there must be a hack / feature in there which interprets termno==0 to mean the default primary console. To help with debugging kernels, including existing distribution kernels, this patch implements a similar feature / hack in qemu. If termno==0 is supplied to H_{GET,PUT}_TERM_CHAR, they use the first available vty device instead. We need to be careful in the case that the user has manually created an spapr-vty at address 0. So first we search for the specified reg and only if that doesn't match do we fall back. Signed-off-by: Michael Ellerman Signed-off-by: David Gibson Signed-off-by: Alexander Graf --- hw/spapr_vty.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c index 815039501..f23cc3623 100644 --- a/hw/spapr_vty.c +++ b/hw/spapr_vty.c @@ -69,6 +69,9 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev) return 0; } +/* Forward declaration */ +static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg); + static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { @@ -76,9 +79,10 @@ static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr, target_ulong len = args[1]; target_ulong char0_7 = args[2]; target_ulong char8_15 = args[3]; - VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg); + VIOsPAPRDevice *sdev; uint8_t buf[16]; + sdev = vty_lookup(spapr, reg); if (!sdev) { return H_PARAMETER; } @@ -102,9 +106,10 @@ static target_ulong h_get_term_char(CPUState *env, sPAPREnvironment *spapr, target_ulong *len = args + 0; target_ulong *char0_7 = args + 1; target_ulong *char8_15 = args + 2; - VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg); + VIOsPAPRDevice *sdev; uint8_t buf[16]; + sdev = vty_lookup(spapr, reg); if (!sdev) { return H_PARAMETER; } @@ -151,6 +156,29 @@ static VIOsPAPRDeviceInfo spapr_vty = { }, }; +static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg) +{ + VIOsPAPRDevice *sdev; + + sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg); + if (!sdev && reg == 0) { + DeviceState *qdev; + + /* Hack for kernel early debug, which always specifies reg==0. + * We search all VIO devices, and grab the first available vty + * device. This attempts to mimic existing PowerVM behaviour + * (early debug does work there, despite having no vty with + * reg==0. */ + QTAILQ_FOREACH(qdev, &spapr->vio_bus->bus.children, sibling) { + if (qdev->info == &spapr_vty.qdev) { + return DO_UPCAST(VIOsPAPRDevice, qdev, qdev); + } + } + } + + return sdev; +} + static void spapr_vty_register(void) { spapr_vio_bus_register_withprop(&spapr_vty); From 1e34d859d01a408dc8479b1858bb103aa3b4f9a7 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 15 Nov 2011 18:53:13 +0000 Subject: [PATCH 21/27] pseries: Fix qdev.id handling in the VIO bus code When the user creates a device on the command line with -device, they can specify the id, using id=foo. Currently the VIO bus code overwrites this id with it's own value. We should only set qdev.id if it is not already set by the user. The device tree code uses qdev.id for the device tree node name, however we can't rely on the user specifiying the id using proper device tree syntax, ie. device@reg. So separate the device tree node name from the qdev.id, but use the same syntax, so they will match by default. Signed-off-by: Michael Ellerman Signed-off-by: Alexander Graf --- hw/spapr_vio.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index b7b3ddd11..2dcc0361e 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -73,20 +73,39 @@ VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg) return NULL; } +static char *vio_format_dev_name(VIOsPAPRDevice *dev) +{ + VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)dev->qdev.info; + char *name; + + /* Device tree style name device@reg */ + if (asprintf(&name, "%s@%x", info->dt_name, dev->reg) < 0) { + return NULL; + } + + return name; +} + #ifdef CONFIG_FDT static int vio_make_devnode(VIOsPAPRDevice *dev, void *fdt) { VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)dev->qdev.info; - int vdevice_off, node_off; - int ret; + int vdevice_off, node_off, ret; + char *dt_name; vdevice_off = fdt_path_offset(fdt, "/vdevice"); if (vdevice_off < 0) { return vdevice_off; } - node_off = fdt_add_subnode(fdt, vdevice_off, dev->qdev.id); + dt_name = vio_format_dev_name(dev); + if (!dt_name) { + return -ENOMEM; + } + + node_off = fdt_add_subnode(fdt, vdevice_off, dt_name); + free(dt_name); if (node_off < 0) { return node_off; } @@ -608,12 +627,15 @@ static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo) VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev; char *id; - if (asprintf(&id, "%s@%x", info->dt_name, dev->reg) < 0) { - return -1; + /* Don't overwrite ids assigned on the command line */ + if (!dev->qdev.id) { + id = vio_format_dev_name(dev); + if (!id) { + return -1; + } + dev->qdev.id = id; } - dev->qdev.id = id; - dev->qirq = spapr_allocate_irq(dev->vio_irq_num, &dev->vio_irq_num); if (!dev->qirq) { return -1; From 15d4a723381bb57dc31007ca46661f42eb67a100 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 18 Nov 2011 18:16:20 +0100 Subject: [PATCH 22/27] fmodaudio: Remove unused variable 'bits16' (reported by cppcheck) The variable is assigned a value which is never used, so remove variable and assignment. Signed-off-by: Stefan Weil Signed-off-by: malc --- audio/fmodaudio.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/audio/fmodaudio.c b/audio/fmodaudio.c index c34cf5356..fabf84dd3 100644 --- a/audio/fmodaudio.c +++ b/audio/fmodaudio.c @@ -343,7 +343,7 @@ static void fmod_fini_out (HWVoiceOut *hw) static int fmod_init_out (HWVoiceOut *hw, struct audsettings *as) { - int bits16, mode, channel; + int mode, channel; FMODVoiceOut *fmd = (FMODVoiceOut *) hw; struct audsettings obt_as = *as; @@ -374,7 +374,6 @@ static int fmod_init_out (HWVoiceOut *hw, struct audsettings *as) /* FMOD always operates on little endian frames? */ obt_as.endianness = 0; audio_pcm_init_info (&hw->info, &obt_as); - bits16 = (mode & FSOUND_16BITS) != 0; hw->samples = conf.nb_samples; return 0; } @@ -405,7 +404,7 @@ static int fmod_ctl_out (HWVoiceOut *hw, int cmd, ...) static int fmod_init_in (HWVoiceIn *hw, struct audsettings *as) { - int bits16, mode; + int mode; FMODVoiceIn *fmd = (FMODVoiceIn *) hw; struct audsettings obt_as = *as; @@ -432,7 +431,6 @@ static int fmod_init_in (HWVoiceIn *hw, struct audsettings *as) /* FMOD always operates on little endian frames? */ obt_as.endianness = 0; audio_pcm_init_info (&hw->info, &obt_as); - bits16 = (mode & FSOUND_16BITS) != 0; hw->samples = conf.nb_samples; return 0; } From b08d26b76d51fb2695912373ded53b628ec96320 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 9 Nov 2011 10:03:35 -0800 Subject: [PATCH 23/27] tcg-sparc: Fix set-but-not used warnings. In both cases, val is computed, but then not used in the subsequent line, which then re-computes the quantity in a different type (int32_t vs unsigned long). Keep the computation type that's been working so far. Signed-off-by: Richard Henderson Signed-off-by: Blue Swirl --- tcg/sparc/tcg-target.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index b96312b3b..5cd5a3b6f 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -473,11 +473,9 @@ static inline void tcg_out_nop(TCGContext *s) static void tcg_out_branch_i32(TCGContext *s, int opc, int label_index) { - int32_t val; TCGLabel *l = &s->labels[label_index]; if (l->has_value) { - val = l->u.value - (tcg_target_long)s->code_ptr; tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2) | INSN_OFF22(l->u.value - (unsigned long)s->code_ptr))); } else { @@ -489,11 +487,9 @@ static void tcg_out_branch_i32(TCGContext *s, int opc, int label_index) #if TCG_TARGET_REG_BITS == 64 static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index) { - int32_t val; TCGLabel *l = &s->labels[label_index]; if (l->has_value) { - val = l->u.value - (tcg_target_long)s->code_ptr; tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x1) | (0x5 << 19) | INSN_OFF19(l->u.value - (unsigned long)s->code_ptr))); From 9643c25f8d67646857159d6fc021b07e7a659192 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Tue, 18 Oct 2011 22:25:38 +0200 Subject: [PATCH 24/27] gdbstub: Fix memory leak cppcheck report: gdbstub.c:1781: error: Memory leak: s Rearranging of the code avoids the leak. v2: Replace the g_malloc0() by g_new0() (suggested by Stuart Brady). Signed-off-by: Stefan Weil Signed-off-by: Blue Swirl --- gdbstub.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/gdbstub.c b/gdbstub.c index a25f40443..640cf4ee2 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -1781,12 +1781,6 @@ void gdb_register_coprocessor(CPUState * env, GDBRegisterState **p; static int last_reg = NUM_CORE_REGS; - s = (GDBRegisterState *)g_malloc0(sizeof(GDBRegisterState)); - s->base_reg = last_reg; - s->num_regs = num_regs; - s->get_reg = get_reg; - s->set_reg = set_reg; - s->xml = xml; p = &env->gdb_regs; while (*p) { /* Check for duplicates. */ @@ -1794,6 +1788,14 @@ void gdb_register_coprocessor(CPUState * env, return; p = &(*p)->next; } + + s = g_new0(GDBRegisterState, 1); + s->base_reg = last_reg; + s->num_regs = num_regs; + s->get_reg = get_reg; + s->set_reg = set_reg; + s->xml = xml; + /* Add to end of list. */ last_reg += num_regs; *p = s; From 96d922a654f4b5a806af43d6dc6fa7c1becbbac6 Mon Sep 17 00:00:00 2001 From: Fabien Chouteau Date: Thu, 3 Nov 2011 16:10:04 +0100 Subject: [PATCH 25/27] Improve "ta 0" shutdown This patch replace the previous implementation with this simplified and more complete version (no shutdown when psret == 1). Signed-off-by: Fabien Chouteau Signed-off-by: Blue Swirl --- target-sparc/helper.c | 7 ------- target-sparc/helper.h | 1 - target-sparc/int32_helper.c | 10 ++++++++-- target-sparc/translate.c | 9 +-------- 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/target-sparc/helper.c b/target-sparc/helper.c index 18609c449..037a72ce4 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -34,13 +34,6 @@ void helper_debug(CPUState *env) cpu_loop_exit(env); } -void helper_shutdown(void) -{ -#if !defined(CONFIG_USER_ONLY) - qemu_system_shutdown_request(); -#endif -} - #ifdef TARGET_SPARC64 target_ulong helper_popc(target_ulong val) { diff --git a/target-sparc/helper.h b/target-sparc/helper.h index faaf8dc7a..1f67b0806 100644 --- a/target-sparc/helper.h +++ b/target-sparc/helper.h @@ -79,7 +79,6 @@ DEF_HELPER_1(fcmpeq_fcc2, void, env) DEF_HELPER_1(fcmpeq_fcc3, void, env) #endif DEF_HELPER_2(raise_exception, void, env, int) -DEF_HELPER_0(shutdown, void) #define F_HELPER_0_1(name) DEF_HELPER_1(f ## name, void, env) DEF_HELPER_3(faddd, f64, env, f64, f64) diff --git a/target-sparc/int32_helper.c b/target-sparc/int32_helper.c index 3a749bf5d..ac9d01ecb 100644 --- a/target-sparc/int32_helper.c +++ b/target-sparc/int32_helper.c @@ -19,6 +19,7 @@ #include "cpu.h" #include "trace.h" +#include "sysemu.h" //#define DEBUG_PCALL @@ -100,8 +101,13 @@ void do_interrupt(CPUState *env) #endif #if !defined(CONFIG_USER_ONLY) if (env->psret == 0) { - cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", - env->exception_index); + if (env->exception_index == 0x80 && + env->def->features & CPU_FEATURE_TA0_SHUTDOWN) { + qemu_system_shutdown_request(); + } else { + cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", + env->exception_index); + } return; } #endif diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 93185402f..d26111209 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -2518,15 +2518,8 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK); tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP); tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst); + gen_helper_raise_exception(cpu_env, cpu_tmp32); - if (rs2 == 0 && - dc->def->features & CPU_FEATURE_TA0_SHUTDOWN) { - - gen_helper_shutdown(); - - } else { - gen_helper_raise_exception(cpu_env, cpu_tmp32); - } } else if (cond != 0) { TCGv r_cond = tcg_temp_new(); int l1; From 725e14e91f80b6b2c07b75b66b7b042a9fa9340c Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 16 Nov 2011 19:41:56 +0100 Subject: [PATCH 26/27] loader: Fix read_targphys() to behave when read() fails Happily passes (size_t)-1 to rom_add_blob_fixed(), which promptly dies attempting to malloc that much. Spotted by Coverity. Bonus fix for ROMs larger than INT_MAX bytes: return ssize_t instead of int. Bug can't bite, because the only user load_aout() limits ROM size to an int value. Signed-off-by: Markus Armbruster Signed-off-by: Blue Swirl --- hw/loader.c | 9 +++++---- hw/loader.h | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/hw/loader.c b/hw/loader.c index 5676c1821..9bbcddd42 100644 --- a/hw/loader.c +++ b/hw/loader.c @@ -85,11 +85,11 @@ int load_image(const char *filename, uint8_t *addr) } /* read()-like version */ -int read_targphys(const char *name, - int fd, target_phys_addr_t dst_addr, size_t nbytes) +ssize_t read_targphys(const char *name, + int fd, target_phys_addr_t dst_addr, size_t nbytes) { uint8_t *buf; - size_t did; + ssize_t did; buf = g_malloc(nbytes); did = read(fd, buf, nbytes); @@ -176,7 +176,8 @@ static void bswap_ahdr(struct exec *e) int load_aout(const char *filename, target_phys_addr_t addr, int max_sz, int bswap_needed, target_phys_addr_t target_page_size) { - int fd, size, ret; + int fd; + ssize_t size, ret; struct exec e; uint32_t magic; diff --git a/hw/loader.h b/hw/loader.h index fc6bdff6b..fbcaba9f0 100644 --- a/hw/loader.h +++ b/hw/loader.h @@ -14,8 +14,8 @@ int load_aout(const char *filename, target_phys_addr_t addr, int max_sz, int load_uimage(const char *filename, target_phys_addr_t *ep, target_phys_addr_t *loadaddr, int *is_linux); -int read_targphys(const char *name, - int fd, target_phys_addr_t dst_addr, size_t nbytes); +ssize_t read_targphys(const char *name, + int fd, target_phys_addr_t dst_addr, size_t nbytes); void pstrcpy_targphys(const char *name, target_phys_addr_t dest, int buf_size, const char *source); From bc4268998d154b9b3cc86a7b6bd932cc974591c9 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 13 Nov 2011 11:11:52 +0000 Subject: [PATCH 27/27] x86: fix pcmpestrm and pcmpistrm Fix obvious typos (decrement and off-by-one error) in pcmpestrm and pcmpistrm which resulted in infinite loop. Reported by Frank Mehnert, spotted also by Coverity (bug 84752853). Reported-by: Frank Mehnert Signed-off-by: Blue Swirl --- target-i386/ops_sse.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h index aa41d2596..47dde78f8 100644 --- a/target-i386/ops_sse.h +++ b/target-i386/ops_sse.h @@ -1996,11 +1996,13 @@ void glue(helper_pcmpestrm, SUFFIX) (Reg *d, Reg *s, uint32_t ctrl) if ((ctrl >> 6) & 1) { if (ctrl & 1) - for (i = 0; i <= 8; i--, res >>= 1) + for (i = 0; i < 8; i++, res >>= 1) { d->W(i) = (res & 1) ? ~0 : 0; + } else - for (i = 0; i <= 16; i--, res >>= 1) + for (i = 0; i < 16; i++, res >>= 1) { d->B(i) = (res & 1) ? ~0 : 0; + } } else { d->Q(1) = 0; d->Q(0) = res; @@ -2028,11 +2030,13 @@ void glue(helper_pcmpistrm, SUFFIX) (Reg *d, Reg *s, uint32_t ctrl) if ((ctrl >> 6) & 1) { if (ctrl & 1) - for (i = 0; i <= 8; i--, res >>= 1) + for (i = 0; i < 8; i++, res >>= 1) { d->W(i) = (res & 1) ? ~0 : 0; + } else - for (i = 0; i <= 16; i--, res >>= 1) + for (i = 0; i < 16; i++, res >>= 1) { d->B(i) = (res & 1) ? ~0 : 0; + } } else { d->Q(1) = 0; d->Q(0) = res;