diff options
33 files changed, 342 insertions, 206 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 62e76833da..7d17f83868 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -175,9 +175,12 @@ S: Maintained F: target-ppc/kvm.c S390 +M: Christian Borntraeger <borntraeger@de.ibm.com> +M: Cornelia Huck <cornelia.huck@de.ibm.com> M: Alexander Graf <agraf@suse.de> S: Maintained F: target-s390x/kvm.c +F: hw/intc/s390_flic.[hc] X86 M: Marcelo Tosatti <mtosatti@redhat.com> @@ -493,10 +496,13 @@ F: hw/s390x/s390-*.c S390 Virtio-ccw M: Cornelia Huck <cornelia.huck@de.ibm.com> +M: Christian Borntraeger <borntraeger@de.ibm.com> M: Alexander Graf <agraf@suse.de> S: Supported F: hw/s390x/s390-virtio-ccw.c F: hw/s390x/css.[hc] +F: hw/s390x/sclp*.[hc] +F: hw/s390x/ipl*.[hc] T: git git://github.com/cohuck/qemu virtio-ccw-upstr UniCore32 Machines @@ -627,6 +633,7 @@ F: hw/block/virtio-blk.c virtio-ccw M: Cornelia Huck <cornelia.huck@de.ibm.com> +M: Christian Borntraeger <borntraeger@de.ibm.com> S: Supported F: hw/s390x/virtio-ccw.[hc] T: git git://github.com/cohuck/qemu virtio-ccw-upstr diff --git a/arch_init.c b/arch_init.c index fe1727922c..60c975db2b 100644 --- a/arch_init.c +++ b/arch_init.c @@ -164,8 +164,9 @@ static struct { uint8_t *encoded_buf; /* buffer for storing page content */ uint8_t *current_buf; - /* Cache for XBZRLE */ + /* Cache for XBZRLE, Protected by lock. */ PageCache *cache; + QemuMutex lock; } XBZRLE = { .encoded_buf = NULL, .current_buf = NULL, @@ -174,16 +175,52 @@ static struct { /* buffer used for XBZRLE decoding */ static uint8_t *xbzrle_decoded_buf; +static void XBZRLE_cache_lock(void) +{ + if (migrate_use_xbzrle()) + qemu_mutex_lock(&XBZRLE.lock); +} + +static void XBZRLE_cache_unlock(void) +{ + if (migrate_use_xbzrle()) + qemu_mutex_unlock(&XBZRLE.lock); +} + int64_t xbzrle_cache_resize(int64_t new_size) { + PageCache *new_cache, *cache_to_free; + if (new_size < TARGET_PAGE_SIZE) { return -1; } + /* no need to lock, the current thread holds qemu big lock */ if (XBZRLE.cache != NULL) { - return cache_resize(XBZRLE.cache, new_size / TARGET_PAGE_SIZE) * - TARGET_PAGE_SIZE; + /* check XBZRLE.cache again later */ + if (pow2floor(new_size) == migrate_xbzrle_cache_size()) { + return pow2floor(new_size); + } + new_cache = cache_init(new_size / TARGET_PAGE_SIZE, + TARGET_PAGE_SIZE); + if (!new_cache) { + DPRINTF("Error creating cache\n"); + return -1; + } + + XBZRLE_cache_lock(); + /* the XBZRLE.cache may have be destroyed, check it again */ + if (XBZRLE.cache != NULL) { + cache_to_free = XBZRLE.cache; + XBZRLE.cache = new_cache; + } else { + cache_to_free = new_cache; + } + XBZRLE_cache_unlock(); + + cache_fini(cache_to_free); } + return pow2floor(new_size); } @@ -539,6 +576,8 @@ static int ram_save_block(QEMUFile *f, bool last_stage) ret = ram_control_save_page(f, block->offset, offset, TARGET_PAGE_SIZE, &bytes_sent); + XBZRLE_cache_lock(); + current_addr = block->offset + offset; if (ret != RAM_SAVE_CONTROL_NOT_SUPP) { if (ret != RAM_SAVE_CONTROL_DELAYED) { @@ -587,6 +626,7 @@ static int ram_save_block(QEMUFile *f, bool last_stage) acct_info.norm_pages++; } + XBZRLE_cache_unlock(); /* if page is unmodified, continue to the next */ if (bytes_sent > 0) { last_sent_block = block; @@ -654,6 +694,7 @@ static void migration_end(void) migration_bitmap = NULL; } + XBZRLE_cache_lock(); if (XBZRLE.cache) { cache_fini(XBZRLE.cache); g_free(XBZRLE.cache); @@ -663,6 +704,7 @@ static void migration_end(void) XBZRLE.encoded_buf = NULL; XBZRLE.current_buf = NULL; } + XBZRLE_cache_unlock(); } static void ram_migration_cancel(void *opaque) @@ -693,13 +735,17 @@ static int ram_save_setup(QEMUFile *f, void *opaque) dirty_rate_high_cnt = 0; if (migrate_use_xbzrle()) { + qemu_mutex_lock_iothread(); XBZRLE.cache = cache_init(migrate_xbzrle_cache_size() / TARGET_PAGE_SIZE, TARGET_PAGE_SIZE); if (!XBZRLE.cache) { + qemu_mutex_unlock_iothread(); DPRINTF("Error creating cache\n"); return -1; } + qemu_mutex_init(&XBZRLE.lock); + qemu_mutex_unlock_iothread(); /* We prefer not to abort if there is no memory */ XBZRLE.encoded_buf = g_try_malloc0(TARGET_PAGE_SIZE); @@ -4968,6 +4968,12 @@ for i in $ARCH $TARGET_BASE_ARCH ; do echo "CONFIG_ALPHA_DIS=y" >> $config_target_mak echo "CONFIG_ALPHA_DIS=y" >> config-all-disas.mak ;; + aarch64) + if test -n "${cxx}"; then + echo "CONFIG_ARM_A64_DIS=y" >> $config_target_mak + echo "CONFIG_ARM_A64_DIS=y" >> config-all-disas.mak + fi + ;; arm) echo "CONFIG_ARM_DIS=y" >> $config_target_mak echo "CONFIG_ARM_DIS=y" >> config-all-disas.mak diff --git a/linux-user/alpha/syscall.h b/linux-user/alpha/syscall.h index 15a0100335..ed13d9a718 100644 --- a/linux-user/alpha/syscall.h +++ b/linux-user/alpha/syscall.h @@ -39,6 +39,7 @@ struct target_pt_regs { }; #define UNAME_MACHINE "alpha" +#define UNAME_MINIMUM_RELEASE "2.6.32" #undef TARGET_EDEADLK #define TARGET_EDEADLK 11 diff --git a/linux-user/arm/syscall.h b/linux-user/arm/syscall.h index 73f29314f6..ce2c2a8ed0 100644 --- a/linux-user/arm/syscall.h +++ b/linux-user/arm/syscall.h @@ -40,5 +40,6 @@ struct target_pt_regs { #else #define UNAME_MACHINE "armv5tel" #endif +#define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_CLONE_BACKWARDS diff --git a/linux-user/cris/syscall.h b/linux-user/cris/syscall.h index 832ee64bd8..f5783c0557 100644 --- a/linux-user/cris/syscall.h +++ b/linux-user/cris/syscall.h @@ -1,8 +1,8 @@ #ifndef CRIS_SYSCALL_H #define CRIS_SYSCALL_H 1 - #define UNAME_MACHINE "cris" +#define UNAME_MINIMUM_RELEASE "2.6.32" /* pt_regs not only specifices the format in the user-struct during * ptrace but is also the frame format used in the kernel prologue/epilogues diff --git a/linux-user/i386/syscall.h b/linux-user/i386/syscall.h index 12b8c3b672..9bfc1ad8f7 100644 --- a/linux-user/i386/syscall.h +++ b/linux-user/i386/syscall.h @@ -144,5 +144,6 @@ struct target_vm86plus_struct { }; #define UNAME_MACHINE "i686" +#define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_CLONE_BACKWARDS diff --git a/linux-user/m68k/syscall.h b/linux-user/m68k/syscall.h index 26187930db..889eaf7323 100644 --- a/linux-user/m68k/syscall.h +++ b/linux-user/m68k/syscall.h @@ -15,7 +15,7 @@ struct target_pt_regs { uint16_t __fill; }; - #define UNAME_MACHINE "m68k" +#define UNAME_MINIMUM_RELEASE "2.6.32" void do_m68k_simcall(CPUM68KState *, int); diff --git a/linux-user/main.c b/linux-user/main.c index be9491bc7d..dee10841c3 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -2400,6 +2400,10 @@ static int do_break(CPUMIPSState *env, target_siginfo_t *info, ret = 0; break; default: + info->si_signo = TARGET_SIGTRAP; + info->si_errno = 0; + queue_signal(env, info->si_signo, &*info); + ret = 0; break; } diff --git a/linux-user/microblaze/syscall.h b/linux-user/microblaze/syscall.h index d550989d5e..5b5f6b447d 100644 --- a/linux-user/microblaze/syscall.h +++ b/linux-user/microblaze/syscall.h @@ -1,8 +1,8 @@ #ifndef MICROBLAZE_SYSCALLS_H #define MICROBLAZE_SYSCALLS_H 1 - #define UNAME_MACHINE "microblaze" +#define UNAME_MINIMUM_RELEASE "2.6.32" /* We use microblaze_reg_t to keep things similar to the kernel sources. */ typedef uint32_t microblaze_reg_t; diff --git a/linux-user/mips/syscall.h b/linux-user/mips/syscall.h index 9d437d918b..5bc56962a4 100644 --- a/linux-user/mips/syscall.h +++ b/linux-user/mips/syscall.h @@ -225,5 +225,6 @@ struct target_pt_regs { #define TARGET_QEMU_ESIGRETURN 255 #define UNAME_MACHINE "mips" +#define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_CLONE_BACKWARDS diff --git a/linux-user/mips64/syscall.h b/linux-user/mips64/syscall.h index 1710f766e2..a7f5a5802a 100644 --- a/linux-user/mips64/syscall.h +++ b/linux-user/mips64/syscall.h @@ -222,5 +222,6 @@ struct target_pt_regs { #define TARGET_QEMU_ESIGRETURN 255 #define UNAME_MACHINE "mips64" +#define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_CLONE_BACKWARDS diff --git a/linux-user/openrisc/syscall.h b/linux-user/openrisc/syscall.h index bdbb577fc3..c3b36da83c 100644 --- a/linux-user/openrisc/syscall.h +++ b/linux-user/openrisc/syscall.h @@ -22,3 +22,4 @@ struct target_pt_regs { }; #define UNAME_MACHINE "openrisc" +#define UNAME_MINIMUM_RELEASE "2.6.32" diff --git a/linux-user/ppc/syscall.h b/linux-user/ppc/syscall.h index ba36acbc33..6514c637a5 100644 --- a/linux-user/ppc/syscall.h +++ b/linux-user/ppc/syscall.h @@ -62,5 +62,6 @@ struct target_revectored_struct { #else #define UNAME_MACHINE "ppc" #endif +#define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_CLONE_BACKWARDS diff --git a/linux-user/s390x/syscall.h b/linux-user/s390x/syscall.h index e5ce30b667..aaad512d4d 100644 --- a/linux-user/s390x/syscall.h +++ b/linux-user/s390x/syscall.h @@ -21,5 +21,6 @@ struct target_pt_regs { }; #define UNAME_MACHINE "s390x" +#define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_CLONE_BACKWARDS2 diff --git a/linux-user/sh4/syscall.h b/linux-user/sh4/syscall.h index 014bf58fc3..ccd2216e38 100644 --- a/linux-user/sh4/syscall.h +++ b/linux-user/sh4/syscall.h @@ -10,3 +10,4 @@ struct target_pt_regs { }; #define UNAME_MACHINE "sh4" +#define UNAME_MINIMUM_RELEASE "2.6.32" diff --git a/linux-user/signal.c b/linux-user/signal.c index 04638e2ead..c8a1da0749 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -1233,8 +1233,14 @@ static int target_restore_sigframe(CPUARMState *env, return 1; } - for (i = 0; i < 32 * 2; i++) { - __get_user(env->vfp.regs[i], &aux->fpsimd.vregs[i]); + for (i = 0; i < 32; i++) { +#ifdef TARGET_WORDS_BIGENDIAN + __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]); + __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]); +#else + __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]); + __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]); +#endif } __get_user(fpsr, &aux->fpsimd.fpsr); vfp_set_fpsr(env, fpsr); @@ -1267,7 +1273,7 @@ static void target_setup_frame(int usig, struct target_sigaction *ka, CPUARMState *env) { struct target_rt_sigframe *frame; - abi_ulong frame_addr; + abi_ulong frame_addr, return_addr; frame_addr = get_sigframe(ka, env); if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { @@ -1284,15 +1290,19 @@ static void target_setup_frame(int usig, struct target_sigaction *ka, __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size); target_setup_sigframe(frame, env, set); - /* mov x8,#__NR_rt_sigreturn; svc #0 */ - __put_user(0xd2801168, &frame->tramp[0]); - __put_user(0xd4000001, &frame->tramp[1]); + if (ka->sa_flags & TARGET_SA_RESTORER) { + return_addr = ka->sa_restorer; + } else { + /* mov x8,#__NR_rt_sigreturn; svc #0 */ + __put_user(0xd2801168, &frame->tramp[0]); + __put_user(0xd4000001, &frame->tramp[1]); + return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp); + } env->xregs[0] = usig; env->xregs[31] = frame_addr; env->xregs[29] = env->xregs[31] + offsetof(struct target_rt_sigframe, fp); env->pc = ka->_sa_handler; - env->xregs[30] = env->xregs[31] + - offsetof(struct target_rt_sigframe, tramp); + env->xregs[30] = return_addr; if (info) { if (copy_siginfo_to_user(&frame->info, info)) { goto give_sigsegv; diff --git a/linux-user/sparc/syscall.h b/linux-user/sparc/syscall.h index 4cd64bf41d..9549ea0a2f 100644 --- a/linux-user/sparc/syscall.h +++ b/linux-user/sparc/syscall.h @@ -7,6 +7,7 @@ struct target_pt_regs { }; #define UNAME_MACHINE "sun4" +#define UNAME_MINIMUM_RELEASE "2.6.32" /* SPARC kernels don't define this in their Kconfig, but they have the * same ABI as if they did, implemented by sparc-specific code which fishes diff --git a/linux-user/sparc64/syscall.h b/linux-user/sparc64/syscall.h index e60bf311c0..82b1680cb6 100644 --- a/linux-user/sparc64/syscall.h +++ b/linux-user/sparc64/syscall.h @@ -8,6 +8,7 @@ struct target_pt_regs { }; #define UNAME_MACHINE "sun4u" +#define UNAME_MINIMUM_RELEASE "2.6.32" /* SPARC kernels don't define this in their Kconfig, but they have the * same ABI as if they did, implemented by sparc-specific code which fishes diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1407b7a546..e2c10cc0bd 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1904,23 +1904,16 @@ static abi_long do_connect(int sockfd, abi_ulong target_addr, return get_errno(connect(sockfd, addr, addrlen)); } -/* do_sendrecvmsg() Must return target values and target errnos. */ -static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, - int flags, int send) +/* do_sendrecvmsg_locked() Must return target values and target errnos. */ +static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp, + int flags, int send) { abi_long ret, len; - struct target_msghdr *msgp; struct msghdr msg; int count; struct iovec *vec; abi_ulong target_vec; - /* FIXME */ - if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE, - msgp, - target_msg, - send ? 1 : 0)) - return -TARGET_EFAULT; if (msgp->msg_name) { msg.msg_namelen = tswap32(msgp->msg_namelen); msg.msg_name = alloca(msg.msg_namelen); @@ -1975,10 +1968,75 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, out: unlock_iovec(vec, target_vec, count, !send); out2: + return ret; +} + +static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, + int flags, int send) +{ + abi_long ret; + struct target_msghdr *msgp; + + if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE, + msgp, + target_msg, + send ? 1 : 0)) { + return -TARGET_EFAULT; + } + ret = do_sendrecvmsg_locked(fd, msgp, flags, send); unlock_user_struct(msgp, target_msg, send ? 0 : 1); return ret; } +#ifdef TARGET_NR_sendmmsg +/* We don't rely on the C library to have sendmmsg/recvmmsg support, + * so it might not have this *mmsg-specific flag either. + */ +#ifndef MSG_WAITFORONE +#define MSG_WAITFORONE 0x10000 +#endif + +static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec, + unsigned int vlen, unsigned int flags, + int send) +{ + struct target_mmsghdr *mmsgp; + abi_long ret = 0; + int i; + + if (vlen > UIO_MAXIOV) { + vlen = UIO_MAXIOV; + } + + mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1); + if (!mmsgp) { + return -TARGET_EFAULT; + } + + for (i = 0; i < vlen; i++) { + ret = do_sendrecvmsg_locked(fd, &mmsgp[i].msg_hdr, flags, send); + if (is_error(ret)) { + break; + } + mmsgp[i].msg_len = tswap32(ret); + /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */ + if (flags & MSG_WAITFORONE) { + flags |= MSG_DONTWAIT; + } + } + + unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i); + + /* Return number of datagrams sent if we sent any at all; + * otherwise return the error. + */ + if (i) { + return i; + } + return ret; +} +#endif + /* If we don't have a system accept4() then just call accept. * The callsites to do_accept4() will ensure that they don't * pass a non-zero flags argument in this config. @@ -4528,6 +4586,9 @@ static inline int tswapid(int id) { return tswap16(id); } + +#define put_user_id(x, gaddr) put_user_u16(x, gaddr) + #else /* !USE_UID16 */ static inline int high2lowuid(int uid) { @@ -4549,6 +4610,9 @@ static inline int tswapid(int id) { return tswap32(id); } + +#define put_user_id(x, gaddr) put_user_u32(x, gaddr) + #endif /* USE_UID16 */ void syscall_init(void) @@ -6121,11 +6185,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, puts = NULL; } ret = get_errno(sigtimedwait(&set, &uinfo, puts)); - if (!is_error(ret) && arg2) { - if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0))) - goto efault; - host_to_target_siginfo(p, &uinfo); - unlock_user(p, arg2, sizeof(target_siginfo_t)); + if (!is_error(ret)) { + if (arg2) { + p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), + 0); + if (!p) { + goto efault; + } + host_to_target_siginfo(p, &uinfo); + unlock_user(p, arg2, sizeof(target_siginfo_t)); + } + ret = host_to_target_signal(ret); } } break; @@ -6710,6 +6780,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = do_sendrecvmsg(arg1, arg2, arg3, 1); break; #endif +#ifdef TARGET_NR_sendmmsg + case TARGET_NR_sendmmsg: + ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1); + break; + case TARGET_NR_recvmmsg: + ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0); + break; +#endif #ifdef TARGET_NR_sendto case TARGET_NR_sendto: ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6); @@ -7805,9 +7883,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, uid_t ruid, euid, suid; ret = get_errno(getresuid(&ruid, &euid, &suid)); if (!is_error(ret)) { - if (put_user_u16(high2lowuid(ruid), arg1) - || put_user_u16(high2lowuid(euid), arg2) - || put_user_u16(high2lowuid(suid), arg3)) + if (put_user_id(high2lowuid(ruid), arg1) + || put_user_id(high2lowuid(euid), arg2) + || put_user_id(high2lowuid(suid), arg3)) goto efault; } } @@ -7826,9 +7904,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, gid_t rgid, egid, sgid; ret = get_errno(getresgid(&rgid, &egid, &sgid)); if (!is_error(ret)) { - if (put_user_u16(high2lowgid(rgid), arg1) - || put_user_u16(high2lowgid(egid), arg2) - || put_user_u16(high2lowgid(sgid), arg3)) + if (put_user_id(high2lowgid(rgid), arg1) + || put_user_id(high2lowgid(egid), arg2) + || put_user_id(high2lowgid(sgid), arg3)) goto efault; } } diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 3c8869e073..732c9e3dbb 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -53,7 +53,8 @@ #define TARGET_IOC_NRBITS 8 #define TARGET_IOC_TYPEBITS 8 -#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \ +#if defined(TARGET_I386) || (defined(TARGET_ARM) && defined(TARGET_ABI32)) \ + || defined(TARGET_SPARC) \ || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS) /* 16 bit uid wrappers emulation */ #define USE_UID16 @@ -239,6 +240,10 @@ __target_cmsg_nxthdr (struct target_msghdr *__mhdr, struct target_cmsghdr *__cms return __cmsg; } +struct target_mmsghdr { + struct target_msghdr msg_hdr; /* Message header */ + unsigned int msg_len; /* Number of bytes transmitted */ +}; struct target_rusage { struct target_timeval ru_utime; /* user time used */ diff --git a/linux-user/unicore32/syscall.h b/linux-user/unicore32/syscall.h index 010cdd896e..f7e55254cf 100644 --- a/linux-user/unicore32/syscall.h +++ b/linux-user/unicore32/syscall.h @@ -51,5 +51,6 @@ struct target_pt_regs { #define UC32_SYSCALL_NR_set_tls (UC32_SYSCALL_ARCH_BASE + 5) #define UNAME_MACHINE "UniCore-II" +#define UNAME_MINIMUM_RELEASE "2.6.32" #endif /* __UC32_SYSCALL_H__ */ diff --git a/linux-user/x86_64/syscall.h b/linux-user/x86_64/syscall.h index 81314cfae6..e03b5a0cfc 100644 --- a/linux-user/x86_64/syscall.h +++ b/linux-user/x86_64/syscall.h @@ -91,6 +91,7 @@ struct target_msqid64_ds { }; #define UNAME_MACHINE "x86_64" +#define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_ARCH_SET_GS 0x1001 #define TARGET_ARCH_SET_FS 0x1002 diff --git a/pc-bios/README b/pc-bios/README index 5914200b23..2bb6357ea6 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -12,7 +12,7 @@ 1275-1994 (referred to as Open Firmware) compliant firmware. The included images for PowerPC (for 32 and 64 bit PPC CPUs), Sparc32 (including QEMU,tcx.bin and QEMU,cgthree.bin) and Sparc64 are built - from OpenBIOS SVN revision 1246. + from OpenBIOS SVN revision 1280. - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc Binary files differindex f4a3a396c4..8a213894be 100644 --- a/pc-bios/openbios-ppc +++ b/pc-bios/openbios-ppc diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32 Binary files differindex bb7cdfb4ec..d4d00e501f 100644 --- a/pc-bios/openbios-sparc32 +++ b/pc-bios/openbios-sparc32 diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64 Binary files differindex 46b4fddd08..4182052d65 100644 --- a/pc-bios/openbios-sparc64 +++ b/pc-bios/openbios-sparc64 diff --git a/qemu-file.c b/qemu-file.c index f074af15c3..e5ec798e0b 100644 --- a/qemu-file.c +++ b/qemu-file.c @@ -105,7 +105,7 @@ static int stdio_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, res = fwrite(buf, 1, size, s->stdio_file); if (res != size) { - return -EIO; /* fake errno value */ + return -errno; } return res; } diff --git a/roms/openbios b/roms/openbios -Subproject 888126272f92294b0da45158393f1b862742cf6 +Subproject 1ac3fb92c109f5545d373a0576b87750c53cce1 @@ -527,13 +527,13 @@ int qemu_savevm_state_iterate(QEMUFile *f) if (qemu_file_rate_limit(f)) { return 0; } - trace_savevm_section_start(); + trace_savevm_section_start(se->idstr, se->section_id); /* Section type */ qemu_put_byte(f, QEMU_VM_SECTION_PART); qemu_put_be32(f, se->section_id); ret = se->ops->save_live_iterate(f, se->opaque); - trace_savevm_section_end(se->section_id); + trace_savevm_section_end(se->idstr, se->section_id); if (ret < 0) { qemu_file_set_error(f, ret); @@ -565,13 +565,13 @@ void qemu_savevm_state_complete(QEMUFile *f) continue; } } - trace_savevm_section_start(); + trace_savevm_section_start(se->idstr, se->section_id); /* Section type */ qemu_put_byte(f, QEMU_VM_SECTION_END); qemu_put_be32(f, se->section_id); ret = se->ops->save_live_complete(f, se->opaque); - trace_savevm_section_end(se->section_id); + trace_savevm_section_end(se->idstr, se->section_id); if (ret < 0) { qemu_file_set_error(f, ret); return; @@ -584,7 +584,7 @@ void qemu_savevm_state_complete(QEMUFile *f) if ((!se->ops || !se->ops->save_state) && !se->vmsd) { continue; } - trace_savevm_section_start(); + trace_savevm_section_start(se->idstr, se->section_id); /* Section type */ qemu_put_byte(f, QEMU_VM_SECTION_FULL); qemu_put_be32(f, se->section_id); @@ -598,7 +598,7 @@ void qemu_savevm_state_complete(QEMUFile *f) qemu_put_be32(f, se->version_id); vmstate_save(f, se); - trace_savevm_section_end(se->section_id); + trace_savevm_section_end(se->idstr, se->section_id); } qemu_put_byte(f, QEMU_VM_EOF); diff --git a/tcg/aarch64/tcg-target.c b/tcg/aarch64/tcg-target.c index 04d7ae328d..f43eb676bf 100644 --- a/tcg/aarch64/tcg-target.c +++ b/tcg/aarch64/tcg-target.c @@ -13,6 +13,11 @@ #include "tcg-be-ldst.h" #include "qemu/bitops.h" +/* We're going to re-use TCGType in setting of the SF bit, which controls + the size of the operation performed. If we know the values match, it + makes things much cleaner. */ +QEMU_BUILD_BUG_ON(TCG_TYPE_I32 != 0 || TCG_TYPE_I64 != 1); + #ifndef NDEBUG static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { "%x0", "%x1", "%x2", "%x3", "%x4", "%x5", "%x6", "%x7", @@ -66,24 +71,22 @@ static const int tcg_target_call_oarg_regs[1] = { # endif #endif -static inline void reloc_pc26(void *code_ptr, tcg_target_long target) +static inline void reloc_pc26(void *code_ptr, intptr_t target) { - tcg_target_long offset; uint32_t insn; - offset = (target - (tcg_target_long)code_ptr) / 4; + intptr_t offset = (target - (intptr_t)code_ptr) / 4; /* read instruction, mask away previous PC_REL26 parameter contents, set the proper offset, then write back the instruction. */ - insn = *(uint32_t *)code_ptr; + uint32_t insn = *(uint32_t *)code_ptr; insn = deposit32(insn, 0, 26, offset); *(uint32_t *)code_ptr = insn; } -static inline void reloc_pc19(void *code_ptr, tcg_target_long target) +static inline void reloc_pc19(void *code_ptr, intptr_t target) { - tcg_target_long offset; uint32_t insn; - offset = (target - (tcg_target_long)code_ptr) / 4; + intptr_t offset = (target - (intptr_t)code_ptr) / 4; /* read instruction, mask away previous PC_REL19 parameter contents, set the proper offset, then write back the instruction. */ - insn = *(uint32_t *)code_ptr; + uint32_t insn = *(uint32_t *)code_ptr; insn = deposit32(insn, 5, 19, offset); *(uint32_t *)code_ptr = insn; } @@ -302,18 +305,8 @@ static inline void tcg_out_ldst_9(TCGContext *s, TCGReg rd, TCGReg rn, tcg_target_long offset) { /* use LDUR with BASE register with 9bit signed unscaled offset */ - unsigned int mod, off; - - if (offset < 0) { - off = (256 + offset); - mod = 0x1; - } else { - off = offset; - mod = 0x0; - } - - mod |= op_type; - tcg_out32(s, op_data << 24 | mod << 20 | off << 12 | rn << 5 | rd); + tcg_out32(s, op_data << 24 | op_type << 20 + | (offset & 0x1ff) << 12 | rn << 5 | rd); } /* tcg_out_ldst_12 expects a scaled unsigned immediate offset */ @@ -327,7 +320,8 @@ static inline void tcg_out_ldst_12(TCGContext *s, | op_type << 20 | scaled_uimm << 10 | rn << 5 | rd); } -static inline void tcg_out_movr(TCGContext *s, int ext, TCGReg rd, TCGReg src) +static inline void tcg_out_movr(TCGContext *s, TCGType ext, + TCGReg rd, TCGReg src) { /* register to register move using MOV (shifted register with no shift) */ /* using MOV 0x2a0003e0 | (shift).. */ @@ -408,7 +402,8 @@ static inline void tcg_out_ldst(TCGContext *s, enum aarch64_ldst_op_data data, } /* mov alias implemented with add immediate, useful to move to/from SP */ -static inline void tcg_out_movr_sp(TCGContext *s, int ext, TCGReg rd, TCGReg rn) +static inline void tcg_out_movr_sp(TCGContext *s, TCGType ext, + TCGReg rd, TCGReg rn) { /* using ADD 0x11000000 | (ext) | rn << 5 | rd */ unsigned int base = ext ? 0x91000000 : 0x11000000; @@ -438,7 +433,7 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, } static inline void tcg_out_arith(TCGContext *s, enum aarch64_arith_opc opc, - int ext, TCGReg rd, TCGReg rn, TCGReg rm, + TCGType ext, TCGReg rd, TCGReg rn, TCGReg rm, int shift_imm) { /* Using shifted register arithmetic operations */ @@ -454,7 +449,7 @@ static inline void tcg_out_arith(TCGContext *s, enum aarch64_arith_opc opc, tcg_out32(s, base | rm << 16 | shift | rn << 5 | rd); } -static inline void tcg_out_mul(TCGContext *s, int ext, +static inline void tcg_out_mul(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, TCGReg rm) { /* Using MADD 0x1b000000 with Ra = wzr alias MUL 0x1b007c00 */ @@ -463,7 +458,7 @@ static inline void tcg_out_mul(TCGContext *s, int ext, } static inline void tcg_out_shiftrot_reg(TCGContext *s, - enum aarch64_srr_opc opc, int ext, + enum aarch64_srr_opc opc, TCGType ext, TCGReg rd, TCGReg rn, TCGReg rm) { /* using 2-source data processing instructions 0x1ac02000 */ @@ -471,23 +466,23 @@ static inline void tcg_out_shiftrot_reg(TCGContext *s, tcg_out32(s, base | rm << 16 | opc << 8 | rn << 5 | rd); } -static inline void tcg_out_ubfm(TCGContext *s, int ext, TCGReg rd, TCGReg rn, - unsigned int a, unsigned int b) +static inline void tcg_out_ubfm(TCGContext *s, TCGType ext, TCGReg rd, + TCGReg rn, unsigned int a, unsigned int b) { /* Using UBFM 0x53000000 Wd, Wn, a, b */ unsigned int base = ext ? 0xd3400000 : 0x53000000; tcg_out32(s, base | a << 16 | b << 10 | rn << 5 | rd); } -static inline void tcg_out_sbfm(TCGContext *s, int ext, TCGReg rd, TCGReg rn, - unsigned int a, unsigned int b) +static inline void tcg_out_sbfm(TCGContext *s, TCGType ext, TCGReg rd, + TCGReg rn, unsigned int a, unsigned int b) { /* Using SBFM 0x13000000 Wd, Wn, a, b */ unsigned int base = ext ? 0x93400000 : 0x13000000; tcg_out32(s, base | a << 16 | b << 10 | rn << 5 | rd); } -static inline void tcg_out_extr(TCGContext *s, int ext, TCGReg rd, +static inline void tcg_out_extr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, TCGReg rm, unsigned int a) { /* Using EXTR 0x13800000 Wd, Wn, Wm, a */ @@ -495,7 +490,7 @@ static inline void tcg_out_extr(TCGContext *s, int ext, TCGReg rd, tcg_out32(s, base | rm << 16 | a << 10 | rn << 5 | rd); } -static inline void tcg_out_shl(TCGContext *s, int ext, +static inline void tcg_out_shl(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, unsigned int m) { int bits, max; @@ -504,28 +499,28 @@ static inline void tcg_out_shl(TCGContext *s, int ext, tcg_out_ubfm(s, ext, rd, rn, bits - (m & max), max - (m & max)); } -static inline void tcg_out_shr(TCGContext *s, int ext, +static inline void tcg_out_shr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, unsigned int m) { int max = ext ? 63 : 31; tcg_out_ubfm(s, ext, rd, rn, m & max, max); } -static inline void tcg_out_sar(TCGContext *s, int ext, +static inline void tcg_out_sar(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, unsigned int m) { int max = ext ? 63 : 31; tcg_out_sbfm(s, ext, rd, rn, m & max, max); } -static inline void tcg_out_rotr(TCGContext *s, int ext, +static inline void tcg_out_rotr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, unsigned int m) { int max = ext ? 63 : 31; tcg_out_extr(s, ext, rd, rn, rn, m & max); } -static inline void tcg_out_rotl(TCGContext *s, int ext, +static inline void tcg_out_rotl(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, unsigned int m) { int bits, max; @@ -534,24 +529,23 @@ static inline void tcg_out_rotl(TCGContext *s, int ext, tcg_out_extr(s, ext, rd, rn, rn, bits - (m & max)); } -static inline void tcg_out_cmp(TCGContext *s, int ext, TCGReg rn, TCGReg rm, - int shift_imm) +static void tcg_out_cmp(TCGContext *s, TCGType ext, TCGReg rn, TCGReg rm) { /* Using CMP alias SUBS wzr, Wn, Wm */ - tcg_out_arith(s, ARITH_SUBS, ext, TCG_REG_XZR, rn, rm, shift_imm); + tcg_out_arith(s, ARITH_SUBS, ext, TCG_REG_XZR, rn, rm, 0); } -static inline void tcg_out_cset(TCGContext *s, int ext, TCGReg rd, TCGCond c) +static inline void tcg_out_cset(TCGContext *s, TCGType ext, + TCGReg rd, TCGCond c) { /* Using CSET alias of CSINC 0x1a800400 Xd, XZR, XZR, invert(cond) */ unsigned int base = ext ? 0x9a9f07e0 : 0x1a9f07e0; tcg_out32(s, base | tcg_cond_to_aarch64[tcg_invert_cond(c)] << 12 | rd); } -static inline void tcg_out_goto(TCGContext *s, tcg_target_long target) +static inline void tcg_out_goto(TCGContext *s, intptr_t target) { - tcg_target_long offset; - offset = (target - (tcg_target_long)s->code_ptr) / 4; + intptr_t offset = (target - (intptr_t)s->code_ptr) / 4; if (offset < -0x02000000 || offset >= 0x02000000) { /* out of 26bit range */ @@ -582,11 +576,9 @@ static inline void tcg_out_goto_cond_noaddr(TCGContext *s, TCGCond c) tcg_out32(s, insn); } -static inline void tcg_out_goto_cond(TCGContext *s, TCGCond c, - tcg_target_long target) +static inline void tcg_out_goto_cond(TCGContext *s, TCGCond c, intptr_t target) { - tcg_target_long offset; - offset = (target - (tcg_target_long)s->code_ptr) / 4; + intptr_t offset = (target - (intptr_t)s->code_ptr) / 4; if (offset < -0x40000 || offset >= 0x40000) { /* out of 19bit range */ @@ -607,11 +599,9 @@ static inline void tcg_out_gotor(TCGContext *s, TCGReg reg) tcg_out32(s, 0xd61f0000 | reg << 5); } -static inline void tcg_out_call(TCGContext *s, tcg_target_long target) +static inline void tcg_out_call(TCGContext *s, intptr_t target) { - tcg_target_long offset; - - offset = (target - (tcg_target_long)s->code_ptr) / 4; + intptr_t offset = (target - (intptr_t)s->code_ptr) / 4; if (offset < -0x02000000 || offset >= 0x02000000) { /* out of 26bit rng */ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, target); @@ -638,7 +628,7 @@ aarch64_limm(unsigned int m, unsigned int r) to test a 32bit reg against 0xff000000, pass M = 8, R = 8. to test a 32bit reg against 0xff0000ff, pass M = 16, R = 8. */ -static inline void tcg_out_tst(TCGContext *s, int ext, TCGReg rn, +static inline void tcg_out_tst(TCGContext *s, TCGType ext, TCGReg rn, unsigned int m, unsigned int r) { /* using TST alias of ANDS XZR, Xn,#bimm64 0x7200001f */ @@ -647,8 +637,8 @@ static inline void tcg_out_tst(TCGContext *s, int ext, TCGReg rn, } /* and a register with a bit pattern, similarly to TST, no flags change */ -static inline void tcg_out_andi(TCGContext *s, int ext, TCGReg rd, TCGReg rn, - unsigned int m, unsigned int r) +static inline void tcg_out_andi(TCGContext *s, TCGType ext, TCGReg rd, + TCGReg rn, unsigned int m, unsigned int r) { /* using AND 0x12000000 */ unsigned int base = ext ? 0x92400000 : 0x12000000; @@ -663,9 +653,8 @@ static inline void tcg_out_ret(TCGContext *s) void aarch64_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr) { - tcg_target_long target, offset; - target = (tcg_target_long)addr; - offset = (target - (tcg_target_long)jmp_addr) / 4; + intptr_t target = addr; + intptr_t offset = (target - (intptr_t)jmp_addr) / 4; if (offset < -0x02000000 || offset >= 0x02000000) { /* out of 26bit range */ @@ -701,21 +690,23 @@ static inline void tcg_out_goto_label_cond(TCGContext *s, } } -static inline void tcg_out_rev(TCGContext *s, int ext, TCGReg rd, TCGReg rm) +static inline void tcg_out_rev(TCGContext *s, TCGType ext, + TCGReg rd, TCGReg rm) { /* using REV 0x5ac00800 */ unsigned int base = ext ? 0xdac00c00 : 0x5ac00800; tcg_out32(s, base | rm << 5 | rd); } -static inline void tcg_out_rev16(TCGContext *s, int ext, TCGReg rd, TCGReg rm) +static inline void tcg_out_rev16(TCGContext *s, TCGType ext, + TCGReg rd, TCGReg rm) { /* using REV16 0x5ac00400 */ unsigned int base = ext ? 0xdac00400 : 0x5ac00400; tcg_out32(s, base | rm << 5 | rd); } -static inline void tcg_out_sxt(TCGContext *s, int ext, int s_bits, +static inline void tcg_out_sxt(TCGContext *s, TCGType ext, int s_bits, TCGReg rd, TCGReg rn) { /* using ALIASes SXTB 0x13001c00, SXTH 0x13003c00, SXTW 0x93407c00 @@ -733,7 +724,7 @@ static inline void tcg_out_uxt(TCGContext *s, int s_bits, tcg_out_ubfm(s, 0, rd, rn, 0, bits); } -static inline void tcg_out_addi(TCGContext *s, int ext, +static inline void tcg_out_addi(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, unsigned int aimm) { /* add immediate aimm unsigned 12bit value (with LSL 0 or 12) */ @@ -753,7 +744,7 @@ static inline void tcg_out_addi(TCGContext *s, int ext, tcg_out32(s, base | aimm | (rn << 5) | rd); } -static inline void tcg_out_subi(TCGContext *s, int ext, +static inline void tcg_out_subi(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, unsigned int aimm) { /* sub immediate aimm unsigned 12bit value (with LSL 0 or 12) */ @@ -773,11 +764,6 @@ static inline void tcg_out_subi(TCGContext *s, int ext, tcg_out32(s, base | aimm | (rn << 5) | rd); } -static inline void tcg_out_nop(TCGContext *s) -{ - tcg_out32(s, 0xd503201f); -} - #ifdef CONFIG_SOFTMMU /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr, * int mmu_idx, uintptr_t ra) @@ -801,7 +787,8 @@ static const void * const qemu_st_helpers[4] = { static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) { - reloc_pc19(lb->label_ptr[0], (tcg_target_long)s->code_ptr); + reloc_pc19(lb->label_ptr[0], (intptr_t)s->code_ptr); + tcg_out_movr(s, 1, TCG_REG_X0, TCG_AREG0); tcg_out_movr(s, (TARGET_LONG_BITS == 64), TCG_REG_X1, lb->addrlo_reg); tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X2, lb->mem_index); @@ -815,23 +802,21 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) tcg_out_movr(s, 1, lb->datalo_reg, TCG_REG_X0); } - tcg_out_goto(s, (tcg_target_long)lb->raddr); + tcg_out_goto(s, (intptr_t)lb->raddr); } static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb) { - reloc_pc19(lb->label_ptr[0], (tcg_target_long)s->code_ptr); + reloc_pc19(lb->label_ptr[0], (intptr_t)s->code_ptr); tcg_out_movr(s, 1, TCG_REG_X0, TCG_AREG0); tcg_out_movr(s, (TARGET_LONG_BITS == 64), TCG_REG_X1, lb->addrlo_reg); tcg_out_movr(s, 1, TCG_REG_X2, lb->datalo_reg); tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X3, lb->mem_index); - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_X4, (tcg_target_long)lb->raddr); + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_X4, (intptr_t)lb->raddr); tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, - (tcg_target_long)qemu_st_helpers[lb->opc & 3]); + (intptr_t)qemu_st_helpers[lb->opc & 3]); tcg_out_callr(s, TCG_REG_TMP); - - tcg_out_nop(s); tcg_out_goto(s, (tcg_target_long)lb->raddr); } @@ -893,7 +878,7 @@ static void tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg, (is_read ? offsetof(CPUTLBEntry, addr_read) : offsetof(CPUTLBEntry, addr_write))); /* Perform the address comparison. */ - tcg_out_cmp(s, (TARGET_LONG_BITS == 64), TCG_REG_X0, TCG_REG_X3, 0); + tcg_out_cmp(s, (TARGET_LONG_BITS == 64), TCG_REG_X0, TCG_REG_X3); *label_ptr = s->code_ptr; /* If not equal, we jump to the slow path. */ tcg_out_goto_cond_noaddr(s, TCG_COND_NE); @@ -1088,16 +1073,23 @@ static inline void tcg_out_load_pair(TCGContext *s, TCGReg addr, } static void tcg_out_op(TCGContext *s, TCGOpcode opc, - const TCGArg *args, const int *const_args) + const TCGArg args[TCG_MAX_OP_ARGS], + const int const_args[TCG_MAX_OP_ARGS]) { - /* ext will be set in the switch below, which will fall through to the - common code. It triggers the use of extended regs where appropriate. */ - int ext = 0; + /* 99% of the time, we can signal the use of extension registers + by looking to see if the opcode handles 64-bit data. */ + TCGType ext = (tcg_op_defs[opc].flags & TCG_OPF_64BIT) != 0; + + /* Hoist the loads of the most common arguments. */ + TCGArg a0 = args[0]; + TCGArg a1 = args[1]; + TCGArg a2 = args[2]; + int c2 = const_args[2]; switch (opc) { case INDEX_op_exit_tb: - tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, args[0]); - tcg_out_goto(s, (tcg_target_long)tb_ret_addr); + tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, a0); + tcg_out_goto(s, (intptr_t)tb_ret_addr); break; case INDEX_op_goto_tb: @@ -1105,23 +1097,23 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, #error "USE_DIRECT_JUMP required for aarch64" #endif assert(s->tb_jmp_offset != NULL); /* consistency for USE_DIRECT_JUMP */ - s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf; + s->tb_jmp_offset[a0] = s->code_ptr - s->code_buf; /* actual branch destination will be patched by aarch64_tb_set_jmp_target later, beware retranslation. */ tcg_out_goto_noaddr(s); - s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; + s->tb_next_offset[a0] = s->code_ptr - s->code_buf; break; case INDEX_op_call: if (const_args[0]) { - tcg_out_call(s, args[0]); + tcg_out_call(s, a0); } else { - tcg_out_callr(s, args[0]); + tcg_out_callr(s, a0); } break; case INDEX_op_br: - tcg_out_goto_label(s, args[0]); + tcg_out_goto_label(s, a0); break; case INDEX_op_ld_i32: @@ -1144,123 +1136,95 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_st16_i64: case INDEX_op_st32_i64: tcg_out_ldst(s, aarch64_ldst_get_data(opc), aarch64_ldst_get_type(opc), - args[0], args[1], args[2]); - break; - - case INDEX_op_mov_i64: - ext = 1; /* fall through */ - case INDEX_op_mov_i32: - tcg_out_movr(s, ext, args[0], args[1]); - break; - - case INDEX_op_movi_i64: - tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]); - break; - case INDEX_op_movi_i32: - tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]); + a0, a1, a2); break; case INDEX_op_add_i64: - ext = 1; /* fall through */ case INDEX_op_add_i32: - tcg_out_arith(s, ARITH_ADD, ext, args[0], args[1], args[2], 0); + tcg_out_arith(s, ARITH_ADD, ext, a0, a1, a2, 0); break; case INDEX_op_sub_i64: - ext = 1; /* fall through */ case INDEX_op_sub_i32: - tcg_out_arith(s, ARITH_SUB, ext, args[0], args[1], args[2], 0); + tcg_out_arith(s, ARITH_SUB, ext, a0, a1, a2, 0); break; case INDEX_op_and_i64: - ext = 1; /* fall through */ case INDEX_op_and_i32: - tcg_out_arith(s, ARITH_AND, ext, args[0], args[1], args[2], 0); + tcg_out_arith(s, ARITH_AND, ext, a0, a1, a2, 0); break; case INDEX_op_or_i64: - ext = 1; /* fall through */ case INDEX_op_or_i32: - tcg_out_arith(s, ARITH_OR, ext, args[0], args[1], args[2], 0); + tcg_out_arith(s, ARITH_OR, ext, a0, a1, a2, 0); break; case INDEX_op_xor_i64: - ext = 1; /* fall through */ case INDEX_op_xor_i32: - tcg_out_arith(s, ARITH_XOR, ext, args[0], args[1], args[2], 0); + tcg_out_arith(s, ARITH_XOR, ext, a0, a1, a2, 0); break; case INDEX_op_mul_i64: - ext = 1; /* fall through */ case INDEX_op_mul_i32: - tcg_out_mul(s, ext, args[0], args[1], args[2]); + tcg_out_mul(s, ext, a0, a1, a2); break; case INDEX_op_shl_i64: - ext = 1; /* fall through */ case INDEX_op_shl_i32: - if (const_args[2]) { /* LSL / UBFM Wd, Wn, (32 - m) */ - tcg_out_shl(s, ext, args[0], args[1], args[2]); + if (c2) { /* LSL / UBFM Wd, Wn, (32 - m) */ + tcg_out_shl(s, ext, a0, a1, a2); } else { /* LSL / LSLV */ - tcg_out_shiftrot_reg(s, SRR_SHL, ext, args[0], args[1], args[2]); + tcg_out_shiftrot_reg(s, SRR_SHL, ext, a0, a1, a2); } break; case INDEX_op_shr_i64: - ext = 1; /* fall through */ case INDEX_op_shr_i32: - if (const_args[2]) { /* LSR / UBFM Wd, Wn, m, 31 */ - tcg_out_shr(s, ext, args[0], args[1], args[2]); + if (c2) { /* LSR / UBFM Wd, Wn, m, 31 */ + tcg_out_shr(s, ext, a0, a1, a2); } else { /* LSR / LSRV */ - tcg_out_shiftrot_reg(s, SRR_SHR, ext, args[0], args[1], args[2]); + tcg_out_shiftrot_reg(s, SRR_SHR, ext, a0, a1, a2); } break; case INDEX_op_sar_i64: - ext = 1; /* fall through */ case INDEX_op_sar_i32: - if (const_args[2]) { /* ASR / SBFM Wd, Wn, m, 31 */ - tcg_out_sar(s, ext, args[0], args[1], args[2]); + if (c2) { /* ASR / SBFM Wd, Wn, m, 31 */ + tcg_out_sar(s, ext, a0, a1, a2); } else { /* ASR / ASRV */ - tcg_out_shiftrot_reg(s, SRR_SAR, ext, args[0], args[1], args[2]); + tcg_out_shiftrot_reg(s, SRR_SAR, ext, a0, a1, a2); } break; case INDEX_op_rotr_i64: - ext = 1; /* fall through */ case INDEX_op_rotr_i32: - if (const_args[2]) { /* ROR / EXTR Wd, Wm, Wm, m */ - tcg_out_rotr(s, ext, args[0], args[1], args[2]); + if (c2) { /* ROR / EXTR Wd, Wm, Wm, m */ + tcg_out_rotr(s, ext, a0, a1, a2); } else { /* ROR / RORV */ - tcg_out_shiftrot_reg(s, SRR_ROR, ext, args[0], args[1], args[2]); + tcg_out_shiftrot_reg(s, SRR_ROR, ext, a0, a1, a2); } break; case INDEX_op_rotl_i64: - ext = 1; /* fall through */ case INDEX_op_rotl_i32: /* same as rotate right by (32 - m) */ - if (const_args[2]) { /* ROR / EXTR Wd, Wm, Wm, 32 - m */ - tcg_out_rotl(s, ext, args[0], args[1], args[2]); + if (c2) { /* ROR / EXTR Wd, Wm, Wm, 32 - m */ + tcg_out_rotl(s, ext, a0, a1, a2); } else { - tcg_out_arith(s, ARITH_SUB, 0, - TCG_REG_TMP, TCG_REG_XZR, args[2], 0); - tcg_out_shiftrot_reg(s, SRR_ROR, ext, - args[0], args[1], TCG_REG_TMP); + tcg_out_arith(s, ARITH_SUB, 0, TCG_REG_TMP, TCG_REG_XZR, a2, 0); + tcg_out_shiftrot_reg(s, SRR_ROR, ext, a0, a1, TCG_REG_TMP); } break; case INDEX_op_brcond_i64: - ext = 1; /* fall through */ - case INDEX_op_brcond_i32: /* CMP 0, 1, cond(2), label 3 */ - tcg_out_cmp(s, ext, args[0], args[1], 0); - tcg_out_goto_label_cond(s, args[2], args[3]); + case INDEX_op_brcond_i32: + tcg_out_cmp(s, ext, a0, a1); + tcg_out_goto_label_cond(s, a2, args[3]); break; case INDEX_op_setcond_i64: - ext = 1; /* fall through */ case INDEX_op_setcond_i32: - tcg_out_cmp(s, ext, args[1], args[2], 0); - tcg_out_cset(s, 0, args[0], args[3]); + tcg_out_cmp(s, ext, a1, a2); + tcg_out_cset(s, 0, a0, args[3]); break; case INDEX_op_qemu_ld8u: @@ -1300,44 +1264,50 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, tcg_out_qemu_st(s, args, 3); break; - case INDEX_op_bswap64_i64: - ext = 1; /* fall through */ case INDEX_op_bswap32_i64: + /* Despite the _i64, this is a 32-bit bswap. */ + ext = 0; + /* FALLTHRU */ + case INDEX_op_bswap64_i64: case INDEX_op_bswap32_i32: - tcg_out_rev(s, ext, args[0], args[1]); + tcg_out_rev(s, ext, a0, a1); break; case INDEX_op_bswap16_i64: case INDEX_op_bswap16_i32: - tcg_out_rev16(s, 0, args[0], args[1]); + tcg_out_rev16(s, 0, a0, a1); break; case INDEX_op_ext8s_i64: - ext = 1; /* fall through */ case INDEX_op_ext8s_i32: - tcg_out_sxt(s, ext, 0, args[0], args[1]); + tcg_out_sxt(s, ext, 0, a0, a1); break; case INDEX_op_ext16s_i64: - ext = 1; /* fall through */ case INDEX_op_ext16s_i32: - tcg_out_sxt(s, ext, 1, args[0], args[1]); + tcg_out_sxt(s, ext, 1, a0, a1); break; case INDEX_op_ext32s_i64: - tcg_out_sxt(s, 1, 2, args[0], args[1]); + tcg_out_sxt(s, 1, 2, a0, a1); break; case INDEX_op_ext8u_i64: case INDEX_op_ext8u_i32: - tcg_out_uxt(s, 0, args[0], args[1]); + tcg_out_uxt(s, 0, a0, a1); break; case INDEX_op_ext16u_i64: case INDEX_op_ext16u_i32: - tcg_out_uxt(s, 1, args[0], args[1]); + tcg_out_uxt(s, 1, a0, a1); break; case INDEX_op_ext32u_i64: - tcg_out_movr(s, 0, args[0], args[1]); + tcg_out_movr(s, 0, a0, a1); break; + case INDEX_op_mov_i64: + case INDEX_op_mov_i32: + case INDEX_op_movi_i64: + case INDEX_op_movi_i32: + /* Always implemented with tcg_out_mov/i, never with tcg_out_op. */ default: - tcg_abort(); /* opcode not implemented */ + /* Opcode not implemented. */ + tcg_abort(); } } @@ -1441,12 +1411,6 @@ static const TCGTargetOpDef aarch64_op_defs[] = { static void tcg_target_init(TCGContext *s) { -#if !defined(CONFIG_USER_ONLY) - /* fail safe */ - if ((1ULL << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry)) { - tcg_abort(); - } -#endif tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff); tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff); diff --git a/trace-events b/trace-events index aec420292c..002c2604d8 100644 --- a/trace-events +++ b/trace-events @@ -486,6 +486,7 @@ runstate_set(int new_state) "new state %d" g_malloc(size_t size, void *ptr) "size %zu ptr %p" g_realloc(void *ptr, size_t size, void *newptr) "ptr %p size %zu newptr %p" g_free(void *ptr) "ptr %p" +system_wakeup_request(int reason) "reason=%d" # block/qcow2.c qcow2_writev_start_req(void *co, int64_t sector, int nb_sectors) "co %p sector %" PRIx64 " nb_sectors %d" @@ -1039,8 +1040,8 @@ vmware_scratch_write(uint32_t index, uint32_t value) "index %d, value 0x%x" vmware_setmode(uint32_t w, uint32_t h, uint32_t bpp) "%dx%d @ %d bpp" # savevm.c -savevm_section_start(void) "" -savevm_section_end(unsigned int section_id) "section_id %u" +savevm_section_start(const char *id, unsigned int section_id) "%s, section_id %u" +savevm_section_end(const char *id, unsigned int section_id) "%s, section_id %u" # arch_init.c migration_bitmap_sync_start(void) "" @@ -1879,6 +1879,8 @@ void qemu_register_suspend_notifier(Notifier *notifier) void qemu_system_wakeup_request(WakeupReason reason) { + trace_system_wakeup_request(reason); + if (!runstate_check(RUN_STATE_SUSPENDED)) { return; } |