Skip to content

Commit

Permalink
Merge tag 'pull-misc-20240408' of https://gitlab.com/rth7680/qemu int…
Browse files Browse the repository at this point in the history
…o staging

util/bufferiszero: Optimizations and cleanups, esp code removal
target/m68k: Semihosting for non-coldfire cpus
target/m68k: Fix fp accrued exception reporting
target/hppa: Fix IIAOQ, IIASQ for pa2.0
target/sh4: Fixes to mac.l and mac.w saturation
target/sh4: Fixes to illegal delay slot reporting
linux-user: Cleanups for do_setsockopt
linux-user: Add FITRIM ioctl
linux-user: Fix waitid return of siginfo_t and rusage
tcg/optimize: Do not attempt to constant fold neg_vec
accel/tcg: Improve can_do_io management, mmio bug fix

# -----BEGIN PGP SIGNATURE-----
#
# iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmYULZgdHHJpY2hhcmQu
# aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV+gIAgAqhtlPsZbnoXwqCNs
# fafa/lTvpZYHl2kMJVRYtMmU661HD2HGARe3XCc7/5ZldvEXeQKPde9VrhmasIe8
# EChS3xh1U3J2zEUbnHHgnC9DDVE7uvG0lTazXQRe6WESTaRuBz5d6a0GZtSkH6F4
# AFp0lyKAxX4cn07aBFg0MJ/oPe21Ay9tTQv+5Ox2JOSvaK+FbW7hXisyReF5MVwq
# WPQSELCSppdowxAcsHCD5Q8t/nwGfBbHKOjxLJCgf9xX1+9Wv3Ab8kMjRqaJWdXu
# CvvJ/DigLZiHWbU2TxR2dPOIFSNZOIJY/BJ92aCHw7q9a4Ii2tkTPoJoM/qqlBq8
# 0oLPXg==
# =00NK
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 08 Apr 2024 18:47:04 BST
# gpg:                using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F
# gpg:                issuer "richard.henderson@linaro.org"
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full]
# Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A  05C0 64DF 38E8 AF7E 215F

* tag 'pull-misc-20240408' of https://gitlab.com/rth7680/qemu: (35 commits)
  util/bufferiszero: Simplify test_buffer_is_zero_next_accel
  util/bufferiszero: Introduce biz_accel_fn typedef
  util/bufferiszero: Improve scalar variant
  util/bufferiszero: Optimize SSE2 and AVX2 variants
  util/bufferiszero: Remove useless prefetches
  util/bufferiszero: Reorganize for early test for acceleration
  util/bufferiszero: Remove AVX512 variant
  util/bufferiszero: Remove SSE4.1 variant
  accel/tcg: Improve can_do_io management
  target/s390x: Use insn_start from DisasContextBase
  target/riscv: Use insn_start from DisasContextBase
  target/microblaze: Use insn_start from DisasContextBase
  target/i386: Preserve DisasContextBase.insn_start across rewind
  target/hppa: Use insn_start from DisasContextBase
  target/arm: Use insn_start from DisasContextBase
  accel/tcg: Add insn_start to DisasContextBase
  tcg: Add TCGContext.emit_before_op
  target/m68k: Support semihosting on non-ColdFire targets
  target/m68k: Perform the semihosting test during translate
  target/m68k: Pass semihosting arg to exit
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Apr 9, 2024
2 parents bc0cd4a + 50dbeda commit e8cb49c
Show file tree
Hide file tree
Showing 39 changed files with 691 additions and 391 deletions.
47 changes: 25 additions & 22 deletions accel/tcg/translator.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,14 @@

static void set_can_do_io(DisasContextBase *db, bool val)
{
if (db->saved_can_do_io != val) {
db->saved_can_do_io = val;

QEMU_BUILD_BUG_ON(sizeof_field(CPUState, neg.can_do_io) != 1);
tcg_gen_st8_i32(tcg_constant_i32(val), tcg_env,
offsetof(ArchCPU, parent_obj.neg.can_do_io) -
offsetof(ArchCPU, env));
}
QEMU_BUILD_BUG_ON(sizeof_field(CPUState, neg.can_do_io) != 1);
tcg_gen_st8_i32(tcg_constant_i32(val), tcg_env,
offsetof(ArchCPU, parent_obj.neg.can_do_io) -
offsetof(ArchCPU, env));
}

bool translator_io_start(DisasContextBase *db)
{
set_can_do_io(db, true);

/*
* Ensure that this instruction will be the last in the TB.
* The target may override this to something more forceful.
Expand Down Expand Up @@ -84,13 +78,6 @@ static TCGOp *gen_tb_start(DisasContextBase *db, uint32_t cflags)
- offsetof(ArchCPU, env));
}

/*
* cpu->neg.can_do_io is set automatically here at the beginning of
* each translation block. The cost is minimal, plus it would be
* very easy to forget doing it in the translator.
*/
set_can_do_io(db, db->max_insns == 1);

return icount_start_insn;
}

Expand Down Expand Up @@ -129,6 +116,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
{
uint32_t cflags = tb_cflags(tb);
TCGOp *icount_start_insn;
TCGOp *first_insn_start = NULL;
bool plugin_enabled;

/* Initialize DisasContext */
Expand All @@ -139,7 +127,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
db->num_insns = 0;
db->max_insns = *max_insns;
db->singlestep_enabled = cflags & CF_SINGLE_STEP;
db->saved_can_do_io = -1;
db->insn_start = NULL;
db->host_addr[0] = host_pc;
db->host_addr[1] = NULL;

Expand All @@ -157,6 +145,10 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
while (true) {
*max_insns = ++db->num_insns;
ops->insn_start(db, cpu);
db->insn_start = tcg_last_op();
if (first_insn_start == NULL) {
first_insn_start = db->insn_start;
}
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */

if (plugin_enabled) {
Expand All @@ -169,10 +161,6 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
* done next -- either exiting this loop or locate the start of
* the next instruction.
*/
if (db->num_insns == db->max_insns) {
/* Accept I/O on the last instruction. */
set_can_do_io(db, true);
}
ops->translate_insn(db, cpu);

/*
Expand Down Expand Up @@ -205,6 +193,21 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
ops->tb_stop(db, cpu);
gen_tb_end(tb, cflags, icount_start_insn, db->num_insns);

/*
* Manage can_do_io for the translation block: set to false before
* the first insn and set to true before the last insn.
*/
if (db->num_insns == 1) {
tcg_debug_assert(first_insn_start == db->insn_start);
} else {
tcg_debug_assert(first_insn_start != db->insn_start);
tcg_ctx->emit_before_op = first_insn_start;
set_can_do_io(db, false);
}
tcg_ctx->emit_before_op = db->insn_start;
set_can_do_io(db, true);
tcg_ctx->emit_before_op = NULL;

if (plugin_enabled) {
plugin_gen_tb_end(cpu, db->num_insns);
}
Expand Down
4 changes: 3 additions & 1 deletion include/exec/translator.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ typedef enum DisasJumpType {
* @singlestep_enabled: "Hardware" single stepping enabled.
* @saved_can_do_io: Known value of cpu->neg.can_do_io, or -1 for unknown.
* @plugin_enabled: TCG plugin enabled in this TB.
* @insn_start: The last op emitted by the insn_start hook,
* which is expected to be INDEX_op_insn_start.
*
* Architecture-agnostic disassembly context.
*/
Expand All @@ -85,8 +87,8 @@ typedef struct DisasContextBase {
int num_insns;
int max_insns;
bool singlestep_enabled;
int8_t saved_can_do_io;
bool plugin_enabled;
struct TCGOp *insn_start;
void *host_addr[2];
} DisasContextBase;

Expand Down
32 changes: 31 additions & 1 deletion include/qemu/cutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,39 @@ char *freq_to_str(uint64_t freq_hz);
/* used to print char* safely */
#define STR_OR_NULL(str) ((str) ? (str) : "null")

bool buffer_is_zero(const void *buf, size_t len);
/*
* Check if a buffer is all zeroes.
*/

bool buffer_is_zero_ool(const void *vbuf, size_t len);
bool buffer_is_zero_ge256(const void *vbuf, size_t len);
bool test_buffer_is_zero_next_accel(void);

static inline bool buffer_is_zero_sample3(const char *buf, size_t len)
{
/*
* For any reasonably sized buffer, these three samples come from
* three different cachelines. In qemu-img usage, we find that
* each byte eliminates more than half of all buffer testing.
* It is therefore critical to performance that the byte tests
* short-circuit, so that we do not pull in additional cache lines.
* Do not "optimize" this to !(a | b | c).
*/
return !buf[0] && !buf[len - 1] && !buf[len / 2];
}

#ifdef __OPTIMIZE__
static inline bool buffer_is_zero(const void *buf, size_t len)
{
return (__builtin_constant_p(len) && len >= 256
? buffer_is_zero_sample3(buf, len) &&
buffer_is_zero_ge256(buf, len)
: buffer_is_zero_ool(buf, len));
}
#else
#define buffer_is_zero buffer_is_zero_ool
#endif

/*
* Implementation of ULEB128 (http://en.wikipedia.org/wiki/LEB128)
* Input is limited to 14-bit numbers
Expand Down
6 changes: 6 additions & 0 deletions include/tcg/tcg.h
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,12 @@ struct TCGContext {
QTAILQ_HEAD(, TCGOp) ops, free_ops;
QSIMPLEQ_HEAD(, TCGLabel) labels;

/*
* When clear, new ops are added to the tail of @ops.
* When set, new ops are added in front of @emit_before_op.
*/
TCGOp *emit_before_op;

/* Tells which temporary holds a given register.
It does not take into account fixed registers */
TCGTemp *reg_to_temp[TCG_TARGET_NB_REGS];
Expand Down
3 changes: 3 additions & 0 deletions linux-user/ioctls.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@
#ifdef FITHAW
IOCTL(FITHAW, IOC_W | IOC_R, TYPE_INT)
#endif
#ifdef FITRIM
IOCTL(FITRIM, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_fstrim_range)))
#endif

IOCTL(FIGETBSZ, IOC_R, MK_PTR(TYPE_LONG))
#ifdef CONFIG_FIEMAP
Expand Down
6 changes: 1 addition & 5 deletions linux-user/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -928,11 +928,7 @@ int main(int argc, char **argv, char **envp)
* Prepare copy of argv vector for target.
*/
target_argc = argc - optind;
target_argv = calloc(target_argc + 1, sizeof (char *));
if (target_argv == NULL) {
(void) fprintf(stderr, "Unable to allocate memory for target_argv\n");
exit(EXIT_FAILURE);
}
target_argv = g_new0(char *, target_argc + 1);

/*
* If argv0 is specified (using '-0' switch) we replace
Expand Down
95 changes: 49 additions & 46 deletions linux-user/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -1615,24 +1615,6 @@ static abi_long do_pipe(CPUArchState *cpu_env, abi_ulong pipedes,
return get_errno(ret);
}

static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
abi_ulong target_addr,
socklen_t len)
{
struct target_ip_mreqn *target_smreqn;

target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
if (!target_smreqn)
return -TARGET_EFAULT;
mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
if (len == sizeof(struct target_ip_mreqn))
mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex);
unlock_user(target_smreqn, target_addr, 0);

return 0;
}

static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr,
abi_ulong target_addr,
socklen_t len)
Expand Down Expand Up @@ -2067,8 +2049,6 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
{
abi_long ret;
int val;
struct ip_mreqn *ip_mreq;
struct ip_mreq_source *ip_mreq_source;

switch(level) {
case SOL_TCP:
Expand Down Expand Up @@ -2111,19 +2091,40 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
break;
case IP_ADD_MEMBERSHIP:
case IP_DROP_MEMBERSHIP:
{
struct ip_mreqn ip_mreq;
struct target_ip_mreqn *target_smreqn;

QEMU_BUILD_BUG_ON(sizeof(struct ip_mreq) !=
sizeof(struct target_ip_mreq));

if (optlen < sizeof (struct target_ip_mreq) ||
optlen > sizeof (struct target_ip_mreqn))
optlen > sizeof (struct target_ip_mreqn)) {
return -TARGET_EINVAL;
}

ip_mreq = (struct ip_mreqn *) alloca(optlen);
target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
break;
target_smreqn = lock_user(VERIFY_READ, optval_addr, optlen, 1);
if (!target_smreqn) {
return -TARGET_EFAULT;
}
ip_mreq.imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
ip_mreq.imr_address.s_addr = target_smreqn->imr_address.s_addr;
if (optlen == sizeof(struct target_ip_mreqn)) {
ip_mreq.imr_ifindex = tswapal(target_smreqn->imr_ifindex);
optlen = sizeof(struct ip_mreqn);
}
unlock_user(target_smreqn, optval_addr, 0);

ret = get_errno(setsockopt(sockfd, level, optname, &ip_mreq, optlen));
break;
}
case IP_BLOCK_SOURCE:
case IP_UNBLOCK_SOURCE:
case IP_ADD_SOURCE_MEMBERSHIP:
case IP_DROP_SOURCE_MEMBERSHIP:
{
struct ip_mreq_source *ip_mreq_source;

if (optlen != sizeof (struct target_ip_mreq_source))
return -TARGET_EINVAL;

Expand All @@ -2134,7 +2135,7 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
unlock_user (ip_mreq_source, optval_addr, 0);
break;

}
default:
goto unimplemented;
}
Expand Down Expand Up @@ -2277,18 +2278,13 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
switch (optname) {
case ALG_SET_KEY:
{
char *alg_key = g_malloc(optlen);

char *alg_key = lock_user(VERIFY_READ, optval_addr, optlen, 1);
if (!alg_key) {
return -TARGET_ENOMEM;
}
if (copy_from_user(alg_key, optval_addr, optlen)) {
g_free(alg_key);
return -TARGET_EFAULT;
}
ret = get_errno(setsockopt(sockfd, level, optname,
alg_key, optlen));
g_free(alg_key);
unlock_user(alg_key, optval_addr, optlen);
break;
}
case ALG_SET_AEAD_AUTHSIZE:
Expand All @@ -2305,12 +2301,10 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
case TARGET_SOL_SOCKET:
switch (optname) {
case TARGET_SO_RCVTIMEO:
case TARGET_SO_SNDTIMEO:
{
struct timeval tv;

optname = SO_RCVTIMEO;

set_timeout:
if (optlen != sizeof(struct target_timeval)) {
return -TARGET_EINVAL;
}
Expand All @@ -2319,13 +2313,12 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
return -TARGET_EFAULT;
}

ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
ret = get_errno(setsockopt(sockfd, SOL_SOCKET,
optname == TARGET_SO_RCVTIMEO ?
SO_RCVTIMEO : SO_SNDTIMEO,
&tv, sizeof(tv)));
return ret;
}
case TARGET_SO_SNDTIMEO:
optname = SO_SNDTIMEO;
goto set_timeout;
case TARGET_SO_ATTACH_FILTER:
{
struct target_sock_fprog *tfprog;
Expand Down Expand Up @@ -9272,14 +9265,24 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
#ifdef TARGET_NR_waitid
case TARGET_NR_waitid:
{
struct rusage ru;
siginfo_t info;
info.si_pid = 0;
ret = get_errno(safe_waitid(arg1, arg2, &info, arg4, NULL));
if (!is_error(ret) && arg3 && info.si_pid != 0) {
if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))

ret = get_errno(safe_waitid(arg1, arg2, (arg3 ? &info : NULL),
arg4, (arg5 ? &ru : NULL)));
if (!is_error(ret)) {
if (arg3) {
p = lock_user(VERIFY_WRITE, arg3,
sizeof(target_siginfo_t), 0);
if (!p) {
return -TARGET_EFAULT;
}
host_to_target_siginfo(p, &info);
unlock_user(p, arg3, sizeof(target_siginfo_t));
}
if (arg5 && host_to_target_rusage(arg5, &ru)) {
return -TARGET_EFAULT;
host_to_target_siginfo(p, &info);
unlock_user(p, arg3, sizeof(target_siginfo_t));
}
}
}
return ret;
Expand Down
1 change: 1 addition & 0 deletions linux-user/syscall_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,7 @@ struct target_rtc_pll_info {

#define TARGET_FIFREEZE TARGET_IOWR('X', 119, abi_int)
#define TARGET_FITHAW TARGET_IOWR('X', 120, abi_int)
#define TARGET_FITRIM TARGET_IOWR('X', 121, struct fstrim_range)

/*
* Note that the ioctl numbers for FS_IOC_<GET|SET><FLAGS|VERSION>
Expand Down
5 changes: 5 additions & 0 deletions linux-user/syscall_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,11 @@ STRUCT(file_clone_range,
TYPE_ULONGLONG, /* src_length */
TYPE_ULONGLONG) /* dest_offset */

STRUCT(fstrim_range,
TYPE_ULONGLONG, /* start */
TYPE_ULONGLONG, /* len */
TYPE_ULONGLONG) /* minlen */

STRUCT(fiemap_extent,
TYPE_ULONGLONG, /* fe_logical */
TYPE_ULONGLONG, /* fe_physical */
Expand Down
2 changes: 1 addition & 1 deletion target/arm/tcg/translate-a64.c
Original file line number Diff line number Diff line change
Expand Up @@ -14179,7 +14179,7 @@ static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
pc_arg &= ~TARGET_PAGE_MASK;
}
tcg_gen_insn_start(pc_arg, 0, 0);
dc->insn_start = tcg_last_op();
dc->insn_start_updated = false;
}

static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
Expand Down

0 comments on commit e8cb49c

Please sign in to comment.