linux-user pull request 20220106
update netlink entries nios2 fixes /proc/self/maps fixes set/getscheduler update prctl cleanup and fixes target_signal.h cleanup and some trivial fixes -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAmHWx0MSHGxhdXJlbnRA dml2aWVyLmV1AAoJEPMMOL0/L748/OcP/jLSX6rPSMUC2RaPuVU7mF2r6tNO+tXi FYPxBkYg9oelkIqVjB+PMm0DREvKsu12EJDvNyVUwOtEKkJqtuDWHO5gAP4pnm5v amtsdsIhJuOJL446aS/acb2kzodWEuwJkpxZneFqTYDPhnkWGqHoWBJKwetH8RoZ zuXlPsJN9Qpp35llrrLpZsNxowGCPT4R54iamCG3tfgpeKKj0VQlNJRzXyCo+UpK ts4+akf0i7xxzxraTkV2cokzuP3ZGxUq3aSKAtTEzyGG/IkXsVEDAZ4Y22F2JcST 4xKgeyk7BQ0EToyL44EirgDkAAxqV2kZGUeuYcHJsf6HXOY6beNEVN4iQuh+vod2 zlldGtoWy2VCxQS8k+8z4irbQBYE3qXTQ71jZtQcv2fwQUh8lCKQhkSQK294pkSB y3gDPeowMj6Vb9jdoi3E/5YWdO0s/97i6OgKzoNE98xU4G4Gdle4/suiKiIahSOo qSKeBk5hk9JWuTuVTCsLFiq7lBe2TUYVRT9o6Lac0zu/glZVLA9F18mVQSJUHqqb 77c45yDuC6wFJFNMmt/2SkBlS9kZn6yPAfMH9k3ICocibmwvjkJdu7fUDnTgR/wc wM4H3JtT6l+aMhvxhLWMu5Hv/8uMqF4+jY25xAVBEnXwhDDGrF2/T9wORj8ljk8d gAuXE/VLZvkm =OYdy -----END PGP SIGNATURE----- Merge tag 'linux-user-for-7.0-pull-request' of https://gitlab.com/laurent_vivier/qemu into staging linux-user pull request 20220106 update netlink entries nios2 fixes /proc/self/maps fixes set/getscheduler update prctl cleanup and fixes target_signal.h cleanup and some trivial fixes # gpg: Signature made Thu 06 Jan 2022 02:41:07 AM PST # gpg: using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C # gpg: issuer "laurent@vivier.eu" # gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [undefined] # gpg: aka "Laurent Vivier <laurent@vivier.eu>" [undefined] # gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C * tag 'linux-user-for-7.0-pull-request' of https://gitlab.com/laurent_vivier/qemu: (27 commits) linux-user: netlink: update IFLA_BRPORT entries linux-user: netlink: Add IFLA_VFINFO_LIST linux-user: netlink: update IFLA entries linux-user/syscall.c: malloc to g_try_malloc linux-user/nios2: Use set_sigmask in do_rt_sigreturn linux-user/nios2: Fix sigmask in setup_rt_frame linux-user/nios2: Fix EA vs PC confusion linux-user/nios2: Map a real kuser page linux-user/elfload: Rename ARM_COMMPAGE to HI_COMMPAGE linux-user/nios2: Fixes for signal frame setup linux-user/nios2: Properly emulate EXCP_TRAP linux-user/syscall.c: fix missed flag for shared memory in open_self_maps linux-user: call set/getscheduler set/getparam directly linux-user: add sched_getattr support linux-user/signal: Map exit signals in SIGCHLD siginfo_t target/sh4: Implement prctl_unalign_sigbus target/hppa: Implement prctl_unalign_sigbus target/alpha: Implement prctl_unalign_sigbus linux-user: Add code for PR_GET/SET_UNALIGN linux-user: Disable more prctl subcodes ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
41fb4c14ee
20
cpu.c
20
cpu.c
|
@ -174,13 +174,23 @@ void cpu_exec_unrealizefn(CPUState *cpu)
|
||||||
cpu_list_remove(cpu);
|
cpu_list_remove(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This can't go in hw/core/cpu.c because that file is compiled only
|
||||||
|
* once for both user-mode and system builds.
|
||||||
|
*/
|
||||||
static Property cpu_common_props[] = {
|
static Property cpu_common_props[] = {
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
/*
|
/*
|
||||||
* Create a memory property for softmmu CPU object,
|
* Create a property for the user-only object, so users can
|
||||||
* so users can wire up its memory. (This can't go in hw/core/cpu.c
|
* adjust prctl(PR_SET_UNALIGN) from the command-line.
|
||||||
* because that file is compiled only once for both user-mode
|
* Has no effect if the target does not support the feature.
|
||||||
* and system builds.) The default if no link is set up is to use
|
*/
|
||||||
|
DEFINE_PROP_BOOL("prctl-unalign-sigbus", CPUState,
|
||||||
|
prctl_unalign_sigbus, false),
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* Create a memory property for softmmu CPU object, so users can
|
||||||
|
* wire up its memory. The default if no link is set up is to use
|
||||||
* the system address space.
|
* the system address space.
|
||||||
*/
|
*/
|
||||||
DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION,
|
DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION,
|
||||||
|
|
|
@ -413,6 +413,9 @@ struct CPUState {
|
||||||
|
|
||||||
bool ignore_memory_transaction_failures;
|
bool ignore_memory_transaction_failures;
|
||||||
|
|
||||||
|
/* Used for user-only emulation of prctl(PR_SET_UNALIGN). */
|
||||||
|
bool prctl_unalign_sigbus;
|
||||||
|
|
||||||
struct hax_vcpu_state *hax_vcpu;
|
struct hax_vcpu_state *hax_vcpu;
|
||||||
|
|
||||||
struct hvf_vcpu_state *hvf;
|
struct hvf_vcpu_state *hvf;
|
||||||
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
/*
|
||||||
|
* AArch64 specific prctl functions for linux-user
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
#ifndef AARCH64_TARGET_PRCTL_H
|
||||||
|
#define AARCH64_TARGET_PRCTL_H
|
||||||
|
|
||||||
|
static abi_long do_prctl_get_vl(CPUArchState *env)
|
||||||
|
{
|
||||||
|
ARMCPU *cpu = env_archcpu(env);
|
||||||
|
if (cpu_isar_feature(aa64_sve, cpu)) {
|
||||||
|
return ((cpu->env.vfp.zcr_el[1] & 0xf) + 1) * 16;
|
||||||
|
}
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
}
|
||||||
|
#define do_prctl_get_vl do_prctl_get_vl
|
||||||
|
|
||||||
|
static abi_long do_prctl_set_vl(CPUArchState *env, abi_long arg2)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We cannot support either PR_SVE_SET_VL_ONEXEC or PR_SVE_VL_INHERIT.
|
||||||
|
* Note the kernel definition of sve_vl_valid allows for VQ=512,
|
||||||
|
* i.e. VL=8192, even though the current architectural maximum is VQ=16.
|
||||||
|
*/
|
||||||
|
if (cpu_isar_feature(aa64_sve, env_archcpu(env))
|
||||||
|
&& arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
|
||||||
|
ARMCPU *cpu = env_archcpu(env);
|
||||||
|
uint32_t vq, old_vq;
|
||||||
|
|
||||||
|
old_vq = (env->vfp.zcr_el[1] & 0xf) + 1;
|
||||||
|
vq = MAX(arg2 / 16, 1);
|
||||||
|
vq = MIN(vq, cpu->sve_max_vq);
|
||||||
|
|
||||||
|
if (vq < old_vq) {
|
||||||
|
aarch64_sve_narrow_vq(env, vq);
|
||||||
|
}
|
||||||
|
env->vfp.zcr_el[1] = vq - 1;
|
||||||
|
arm_rebuild_hflags(env);
|
||||||
|
return vq * 16;
|
||||||
|
}
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
}
|
||||||
|
#define do_prctl_set_vl do_prctl_set_vl
|
||||||
|
|
||||||
|
static abi_long do_prctl_reset_keys(CPUArchState *env, abi_long arg2)
|
||||||
|
{
|
||||||
|
ARMCPU *cpu = env_archcpu(env);
|
||||||
|
|
||||||
|
if (cpu_isar_feature(aa64_pauth, cpu)) {
|
||||||
|
int all = (PR_PAC_APIAKEY | PR_PAC_APIBKEY |
|
||||||
|
PR_PAC_APDAKEY | PR_PAC_APDBKEY | PR_PAC_APGAKEY);
|
||||||
|
int ret = 0;
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
|
if (arg2 == 0) {
|
||||||
|
arg2 = all;
|
||||||
|
} else if (arg2 & ~all) {
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
}
|
||||||
|
if (arg2 & PR_PAC_APIAKEY) {
|
||||||
|
ret |= qemu_guest_getrandom(&env->keys.apia,
|
||||||
|
sizeof(ARMPACKey), &err);
|
||||||
|
}
|
||||||
|
if (arg2 & PR_PAC_APIBKEY) {
|
||||||
|
ret |= qemu_guest_getrandom(&env->keys.apib,
|
||||||
|
sizeof(ARMPACKey), &err);
|
||||||
|
}
|
||||||
|
if (arg2 & PR_PAC_APDAKEY) {
|
||||||
|
ret |= qemu_guest_getrandom(&env->keys.apda,
|
||||||
|
sizeof(ARMPACKey), &err);
|
||||||
|
}
|
||||||
|
if (arg2 & PR_PAC_APDBKEY) {
|
||||||
|
ret |= qemu_guest_getrandom(&env->keys.apdb,
|
||||||
|
sizeof(ARMPACKey), &err);
|
||||||
|
}
|
||||||
|
if (arg2 & PR_PAC_APGAKEY) {
|
||||||
|
ret |= qemu_guest_getrandom(&env->keys.apga,
|
||||||
|
sizeof(ARMPACKey), &err);
|
||||||
|
}
|
||||||
|
if (ret != 0) {
|
||||||
|
/*
|
||||||
|
* Some unknown failure in the crypto. The best
|
||||||
|
* we can do is log it and fail the syscall.
|
||||||
|
* The real syscall cannot fail this way.
|
||||||
|
*/
|
||||||
|
qemu_log_mask(LOG_UNIMP, "PR_PAC_RESET_KEYS: Crypto failure: %s",
|
||||||
|
error_get_pretty(err));
|
||||||
|
error_free(err);
|
||||||
|
return -TARGET_EIO;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
}
|
||||||
|
#define do_prctl_reset_keys do_prctl_reset_keys
|
||||||
|
|
||||||
|
static abi_long do_prctl_set_tagged_addr_ctrl(CPUArchState *env, abi_long arg2)
|
||||||
|
{
|
||||||
|
abi_ulong valid_mask = PR_TAGGED_ADDR_ENABLE;
|
||||||
|
ARMCPU *cpu = env_archcpu(env);
|
||||||
|
|
||||||
|
if (cpu_isar_feature(aa64_mte, cpu)) {
|
||||||
|
valid_mask |= PR_MTE_TCF_MASK;
|
||||||
|
valid_mask |= PR_MTE_TAG_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg2 & ~valid_mask) {
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
}
|
||||||
|
env->tagged_addr_enable = arg2 & PR_TAGGED_ADDR_ENABLE;
|
||||||
|
|
||||||
|
if (cpu_isar_feature(aa64_mte, cpu)) {
|
||||||
|
switch (arg2 & PR_MTE_TCF_MASK) {
|
||||||
|
case PR_MTE_TCF_NONE:
|
||||||
|
case PR_MTE_TCF_SYNC:
|
||||||
|
case PR_MTE_TCF_ASYNC:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write PR_MTE_TCF to SCTLR_EL1[TCF0].
|
||||||
|
* Note that the syscall values are consistent with hw.
|
||||||
|
*/
|
||||||
|
env->cp15.sctlr_el[1] =
|
||||||
|
deposit64(env->cp15.sctlr_el[1], 38, 2, arg2 >> PR_MTE_TCF_SHIFT);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write PR_MTE_TAG to GCR_EL1[Exclude].
|
||||||
|
* Note that the syscall uses an include mask,
|
||||||
|
* and hardware uses an exclude mask -- invert.
|
||||||
|
*/
|
||||||
|
env->cp15.gcr_el1 =
|
||||||
|
deposit64(env->cp15.gcr_el1, 0, 16, ~arg2 >> PR_MTE_TAG_SHIFT);
|
||||||
|
arm_rebuild_hflags(env);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#define do_prctl_set_tagged_addr_ctrl do_prctl_set_tagged_addr_ctrl
|
||||||
|
|
||||||
|
static abi_long do_prctl_get_tagged_addr_ctrl(CPUArchState *env)
|
||||||
|
{
|
||||||
|
ARMCPU *cpu = env_archcpu(env);
|
||||||
|
abi_long ret = 0;
|
||||||
|
|
||||||
|
if (env->tagged_addr_enable) {
|
||||||
|
ret |= PR_TAGGED_ADDR_ENABLE;
|
||||||
|
}
|
||||||
|
if (cpu_isar_feature(aa64_mte, cpu)) {
|
||||||
|
/* See do_prctl_set_tagged_addr_ctrl. */
|
||||||
|
ret |= extract64(env->cp15.sctlr_el[1], 38, 2) << PR_MTE_TCF_SHIFT;
|
||||||
|
ret = deposit64(ret, PR_MTE_TAG_SHIFT, 16, ~env->cp15.gcr_el1);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#define do_prctl_get_tagged_addr_ctrl do_prctl_get_tagged_addr_ctrl
|
||||||
|
|
||||||
|
#endif /* AARCH64_TARGET_PRCTL_H */
|
|
@ -1,24 +1,6 @@
|
||||||
#ifndef AARCH64_TARGET_SIGNAL_H
|
#ifndef AARCH64_TARGET_SIGNAL_H
|
||||||
#define AARCH64_TARGET_SIGNAL_H
|
#define AARCH64_TARGET_SIGNAL_H
|
||||||
|
|
||||||
/* this struct defines a stack used during syscall handling */
|
|
||||||
|
|
||||||
typedef struct target_sigaltstack {
|
|
||||||
abi_ulong ss_sp;
|
|
||||||
abi_int ss_flags;
|
|
||||||
abi_ulong ss_size;
|
|
||||||
} target_stack_t;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* sigaltstack controls
|
|
||||||
*/
|
|
||||||
#define TARGET_SS_ONSTACK 1
|
|
||||||
#define TARGET_SS_DISABLE 2
|
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_SIGSTKSZ 8192
|
|
||||||
|
|
||||||
#include "../generic/signal.h"
|
#include "../generic/signal.h"
|
||||||
|
|
||||||
#define TARGET_SEGV_MTEAERR 8 /* Asynchronous ARM MTE error */
|
#define TARGET_SEGV_MTEAERR 8 /* Asynchronous ARM MTE error */
|
||||||
|
|
|
@ -15,32 +15,8 @@ struct target_pt_regs {
|
||||||
#endif
|
#endif
|
||||||
#define UNAME_MINIMUM_RELEASE "3.8.0"
|
#define UNAME_MINIMUM_RELEASE "3.8.0"
|
||||||
#define TARGET_CLONE_BACKWARDS
|
#define TARGET_CLONE_BACKWARDS
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_MCL_CURRENT 1
|
#define TARGET_MCL_CURRENT 1
|
||||||
#define TARGET_MCL_FUTURE 2
|
#define TARGET_MCL_FUTURE 2
|
||||||
#define TARGET_MCL_ONFAULT 4
|
#define TARGET_MCL_ONFAULT 4
|
||||||
|
|
||||||
#define TARGET_PR_SVE_SET_VL 50
|
|
||||||
#define TARGET_PR_SVE_GET_VL 51
|
|
||||||
|
|
||||||
#define TARGET_PR_PAC_RESET_KEYS 54
|
|
||||||
# define TARGET_PR_PAC_APIAKEY (1 << 0)
|
|
||||||
# define TARGET_PR_PAC_APIBKEY (1 << 1)
|
|
||||||
# define TARGET_PR_PAC_APDAKEY (1 << 2)
|
|
||||||
# define TARGET_PR_PAC_APDBKEY (1 << 3)
|
|
||||||
# define TARGET_PR_PAC_APGAKEY (1 << 4)
|
|
||||||
|
|
||||||
#define TARGET_PR_SET_TAGGED_ADDR_CTRL 55
|
|
||||||
#define TARGET_PR_GET_TAGGED_ADDR_CTRL 56
|
|
||||||
# define TARGET_PR_TAGGED_ADDR_ENABLE (1UL << 0)
|
|
||||||
/* MTE tag check fault modes */
|
|
||||||
# define TARGET_PR_MTE_TCF_SHIFT 1
|
|
||||||
# define TARGET_PR_MTE_TCF_NONE (0UL << TARGET_PR_MTE_TCF_SHIFT)
|
|
||||||
# define TARGET_PR_MTE_TCF_SYNC (1UL << TARGET_PR_MTE_TCF_SHIFT)
|
|
||||||
# define TARGET_PR_MTE_TCF_ASYNC (2UL << TARGET_PR_MTE_TCF_SHIFT)
|
|
||||||
# define TARGET_PR_MTE_TCF_MASK (3UL << TARGET_PR_MTE_TCF_SHIFT)
|
|
||||||
/* MTE tag inclusion mask */
|
|
||||||
# define TARGET_PR_MTE_TAG_SHIFT 3
|
|
||||||
# define TARGET_PR_MTE_TAG_MASK (0xffffUL << TARGET_PR_MTE_TAG_SHIFT)
|
|
||||||
|
|
||||||
#endif /* AARCH64_TARGET_SYSCALL_H */
|
#endif /* AARCH64_TARGET_SYSCALL_H */
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
#include "../generic/target_prctl_unalign.h"
|
|
@ -62,7 +62,6 @@ typedef struct target_sigaltstack {
|
||||||
#define TARGET_SA_SIGINFO 0x00000040
|
#define TARGET_SA_SIGINFO 0x00000040
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 4096
|
#define TARGET_MINSIGSTKSZ 4096
|
||||||
#define TARGET_SIGSTKSZ 16384
|
|
||||||
|
|
||||||
/* From <asm/gentrap.h>. */
|
/* From <asm/gentrap.h>. */
|
||||||
#define TARGET_GEN_INTOVF -1 /* integer overflow */
|
#define TARGET_GEN_INTOVF -1 /* integer overflow */
|
||||||
|
|
|
@ -63,7 +63,6 @@ struct target_pt_regs {
|
||||||
#define TARGET_UAC_NOPRINT 1
|
#define TARGET_UAC_NOPRINT 1
|
||||||
#define TARGET_UAC_NOFIX 2
|
#define TARGET_UAC_NOFIX 2
|
||||||
#define TARGET_UAC_SIGBUS 4
|
#define TARGET_UAC_SIGBUS 4
|
||||||
#define TARGET_MINSIGSTKSZ 4096
|
|
||||||
#define TARGET_MCL_CURRENT 0x2000
|
#define TARGET_MCL_CURRENT 0x2000
|
||||||
#define TARGET_MCL_FUTURE 0x4000
|
#define TARGET_MCL_FUTURE 0x4000
|
||||||
#define TARGET_MCL_ONFAULT 0x8000
|
#define TARGET_MCL_ONFAULT 0x8000
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/* No special prctl support required. */
|
|
@ -1,24 +1,6 @@
|
||||||
#ifndef ARM_TARGET_SIGNAL_H
|
#ifndef ARM_TARGET_SIGNAL_H
|
||||||
#define ARM_TARGET_SIGNAL_H
|
#define ARM_TARGET_SIGNAL_H
|
||||||
|
|
||||||
/* this struct defines a stack used during syscall handling */
|
|
||||||
|
|
||||||
typedef struct target_sigaltstack {
|
|
||||||
abi_ulong ss_sp;
|
|
||||||
abi_int ss_flags;
|
|
||||||
abi_ulong ss_size;
|
|
||||||
} target_stack_t;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* sigaltstack controls
|
|
||||||
*/
|
|
||||||
#define TARGET_SS_ONSTACK 1
|
|
||||||
#define TARGET_SS_DISABLE 2
|
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_SIGSTKSZ 8192
|
|
||||||
|
|
||||||
#include "../generic/signal.h"
|
#include "../generic/signal.h"
|
||||||
|
|
||||||
#define TARGET_ARCH_HAS_SETUP_FRAME
|
#define TARGET_ARCH_HAS_SETUP_FRAME
|
||||||
|
|
|
@ -27,7 +27,6 @@ struct target_pt_regs {
|
||||||
|
|
||||||
#define TARGET_CLONE_BACKWARDS
|
#define TARGET_CLONE_BACKWARDS
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_MCL_CURRENT 1
|
#define TARGET_MCL_CURRENT 1
|
||||||
#define TARGET_MCL_FUTURE 2
|
#define TARGET_MCL_FUTURE 2
|
||||||
#define TARGET_MCL_ONFAULT 4
|
#define TARGET_MCL_ONFAULT 4
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/* No special prctl support required. */
|
|
@ -1,24 +1,6 @@
|
||||||
#ifndef CRIS_TARGET_SIGNAL_H
|
#ifndef CRIS_TARGET_SIGNAL_H
|
||||||
#define CRIS_TARGET_SIGNAL_H
|
#define CRIS_TARGET_SIGNAL_H
|
||||||
|
|
||||||
/* this struct defines a stack used during syscall handling */
|
|
||||||
|
|
||||||
typedef struct target_sigaltstack {
|
|
||||||
abi_ulong ss_sp;
|
|
||||||
abi_int ss_flags;
|
|
||||||
abi_ulong ss_size;
|
|
||||||
} target_stack_t;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* sigaltstack controls
|
|
||||||
*/
|
|
||||||
#define TARGET_SS_ONSTACK 1
|
|
||||||
#define TARGET_SS_DISABLE 2
|
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_SIGSTKSZ 8192
|
|
||||||
|
|
||||||
#include "../generic/signal.h"
|
#include "../generic/signal.h"
|
||||||
|
|
||||||
#define TARGET_ARCH_HAS_SETUP_FRAME
|
#define TARGET_ARCH_HAS_SETUP_FRAME
|
||||||
|
|
|
@ -39,7 +39,6 @@ struct target_pt_regs {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TARGET_CLONE_BACKWARDS2
|
#define TARGET_CLONE_BACKWARDS2
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_MCL_CURRENT 1
|
#define TARGET_MCL_CURRENT 1
|
||||||
#define TARGET_MCL_FUTURE 2
|
#define TARGET_MCL_FUTURE 2
|
||||||
#define TARGET_MCL_ONFAULT 4
|
#define TARGET_MCL_ONFAULT 4
|
||||||
|
|
|
@ -390,11 +390,11 @@ enum {
|
||||||
|
|
||||||
/* The commpage only exists for 32 bit kernels */
|
/* The commpage only exists for 32 bit kernels */
|
||||||
|
|
||||||
#define ARM_COMMPAGE (intptr_t)0xffff0f00u
|
#define HI_COMMPAGE (intptr_t)0xffff0f00u
|
||||||
|
|
||||||
static bool init_guest_commpage(void)
|
static bool init_guest_commpage(void)
|
||||||
{
|
{
|
||||||
void *want = g2h_untagged(ARM_COMMPAGE & -qemu_host_page_size);
|
void *want = g2h_untagged(HI_COMMPAGE & -qemu_host_page_size);
|
||||||
void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE,
|
void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE,
|
||||||
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
|
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
|
||||||
|
|
||||||
|
@ -1099,6 +1099,47 @@ static void init_thread(struct target_pt_regs *regs, struct image_info *infop)
|
||||||
regs->estatus = 0x3;
|
regs->estatus = 0x3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define LO_COMMPAGE TARGET_PAGE_SIZE
|
||||||
|
|
||||||
|
static bool init_guest_commpage(void)
|
||||||
|
{
|
||||||
|
static const uint8_t kuser_page[4 + 2 * 64] = {
|
||||||
|
/* __kuser_helper_version */
|
||||||
|
[0x00] = 0x02, 0x00, 0x00, 0x00,
|
||||||
|
|
||||||
|
/* __kuser_cmpxchg */
|
||||||
|
[0x04] = 0x3a, 0x6c, 0x3b, 0x00, /* trap 16 */
|
||||||
|
0x3a, 0x28, 0x00, 0xf8, /* ret */
|
||||||
|
|
||||||
|
/* __kuser_sigtramp */
|
||||||
|
[0x44] = 0xc4, 0x22, 0x80, 0x00, /* movi r2, __NR_rt_sigreturn */
|
||||||
|
0x3a, 0x68, 0x3b, 0x00, /* trap 0 */
|
||||||
|
};
|
||||||
|
|
||||||
|
void *want = g2h_untagged(LO_COMMPAGE & -qemu_host_page_size);
|
||||||
|
void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE,
|
||||||
|
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
|
||||||
|
|
||||||
|
if (addr == MAP_FAILED) {
|
||||||
|
perror("Allocating guest commpage");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (addr != want) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(addr, kuser_page, sizeof(kuser_page));
|
||||||
|
|
||||||
|
if (mprotect(addr, qemu_host_page_size, PROT_READ)) {
|
||||||
|
perror("Protecting guest commpage");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
page_set_flags(LO_COMMPAGE, LO_COMMPAGE + TARGET_PAGE_SIZE,
|
||||||
|
PAGE_READ | PAGE_EXEC | PAGE_VALID);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#define ELF_EXEC_PAGESIZE 4096
|
#define ELF_EXEC_PAGESIZE 4096
|
||||||
|
|
||||||
#define USE_ELF_CORE_DUMP
|
#define USE_ELF_CORE_DUMP
|
||||||
|
@ -2160,8 +2201,13 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ARM_COMMPAGE
|
#if defined(HI_COMMPAGE)
|
||||||
#define ARM_COMMPAGE 0
|
#define LO_COMMPAGE 0
|
||||||
|
#elif defined(LO_COMMPAGE)
|
||||||
|
#define HI_COMMPAGE 0
|
||||||
|
#else
|
||||||
|
#define HI_COMMPAGE 0
|
||||||
|
#define LO_COMMPAGE 0
|
||||||
#define init_guest_commpage() true
|
#define init_guest_commpage() true
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2361,7 +2407,7 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
loaddr &= -align;
|
loaddr &= -align;
|
||||||
if (ARM_COMMPAGE) {
|
if (HI_COMMPAGE) {
|
||||||
/*
|
/*
|
||||||
* Extend the allocation to include the commpage.
|
* Extend the allocation to include the commpage.
|
||||||
* For a 64-bit host, this is just 4GiB; for a 32-bit host we
|
* For a 64-bit host, this is just 4GiB; for a 32-bit host we
|
||||||
|
@ -2372,14 +2418,16 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr,
|
||||||
if (sizeof(uintptr_t) == 8 || loaddr >= 0x80000000u) {
|
if (sizeof(uintptr_t) == 8 || loaddr >= 0x80000000u) {
|
||||||
hiaddr = (uintptr_t) 4 << 30;
|
hiaddr = (uintptr_t) 4 << 30;
|
||||||
} else {
|
} else {
|
||||||
offset = -(ARM_COMMPAGE & -align);
|
offset = -(HI_COMMPAGE & -align);
|
||||||
}
|
}
|
||||||
|
} else if (LO_COMMPAGE) {
|
||||||
|
loaddr = MIN(loaddr, LO_COMMPAGE & -align);
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = pgb_find_hole(loaddr, hiaddr - loaddr, align, offset);
|
addr = pgb_find_hole(loaddr, hiaddr - loaddr, align, offset);
|
||||||
if (addr == -1) {
|
if (addr == -1) {
|
||||||
/*
|
/*
|
||||||
* If ARM_COMMPAGE, there *might* be a non-consecutive allocation
|
* If HI_COMMPAGE, there *might* be a non-consecutive allocation
|
||||||
* that can satisfy both. But as the normal arm32 link base address
|
* that can satisfy both. But as the normal arm32 link base address
|
||||||
* is ~32k, and we extend down to include the commpage, making the
|
* is ~32k, and we extend down to include the commpage, making the
|
||||||
* overhead only ~96k, this is unlikely.
|
* overhead only ~96k, this is unlikely.
|
||||||
|
@ -2400,7 +2448,7 @@ static void pgb_dynamic(const char *image_name, long align)
|
||||||
* All we need is a commpage that satisfies align.
|
* All we need is a commpage that satisfies align.
|
||||||
* If we do not need a commpage, leave guest_base == 0.
|
* If we do not need a commpage, leave guest_base == 0.
|
||||||
*/
|
*/
|
||||||
if (ARM_COMMPAGE) {
|
if (HI_COMMPAGE) {
|
||||||
uintptr_t addr, commpage;
|
uintptr_t addr, commpage;
|
||||||
|
|
||||||
/* 64-bit hosts should have used reserved_va. */
|
/* 64-bit hosts should have used reserved_va. */
|
||||||
|
@ -2410,7 +2458,7 @@ static void pgb_dynamic(const char *image_name, long align)
|
||||||
* By putting the commpage at the first hole, that puts guest_base
|
* By putting the commpage at the first hole, that puts guest_base
|
||||||
* just above that, and maximises the positive guest addresses.
|
* just above that, and maximises the positive guest addresses.
|
||||||
*/
|
*/
|
||||||
commpage = ARM_COMMPAGE & -align;
|
commpage = HI_COMMPAGE & -align;
|
||||||
addr = pgb_find_hole(commpage, -commpage, align, 0);
|
addr = pgb_find_hole(commpage, -commpage, align, 0);
|
||||||
assert(addr != -1);
|
assert(addr != -1);
|
||||||
guest_base = addr;
|
guest_base = addr;
|
||||||
|
|
|
@ -138,6 +138,9 @@ enum {
|
||||||
QEMU_IFLA_PROP_LIST,
|
QEMU_IFLA_PROP_LIST,
|
||||||
QEMU_IFLA_ALT_IFNAME,
|
QEMU_IFLA_ALT_IFNAME,
|
||||||
QEMU_IFLA_PERM_ADDRESS,
|
QEMU_IFLA_PERM_ADDRESS,
|
||||||
|
QEMU_IFLA_PROTO_DOWN_REASON,
|
||||||
|
QEMU_IFLA_PARENT_DEV_NAME,
|
||||||
|
QEMU_IFLA_PARENT_DEV_BUS_NAME,
|
||||||
QEMU___IFLA_MAX
|
QEMU___IFLA_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -179,6 +182,8 @@ enum {
|
||||||
QEMU_IFLA_BRPORT_BACKUP_PORT,
|
QEMU_IFLA_BRPORT_BACKUP_PORT,
|
||||||
QEMU_IFLA_BRPORT_MRP_RING_OPEN,
|
QEMU_IFLA_BRPORT_MRP_RING_OPEN,
|
||||||
QEMU_IFLA_BRPORT_MRP_IN_OPEN,
|
QEMU_IFLA_BRPORT_MRP_IN_OPEN,
|
||||||
|
QEMU_IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT,
|
||||||
|
QEMU_IFLA_BRPORT_MCAST_EHT_HOSTS_CNT,
|
||||||
QEMU___IFLA_BRPORT_MAX
|
QEMU___IFLA_BRPORT_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -268,6 +273,37 @@ enum {
|
||||||
QEMU___RTA_MAX
|
QEMU___RTA_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
QEMU_IFLA_VF_STATS_RX_PACKETS,
|
||||||
|
QEMU_IFLA_VF_STATS_TX_PACKETS,
|
||||||
|
QEMU_IFLA_VF_STATS_RX_BYTES,
|
||||||
|
QEMU_IFLA_VF_STATS_TX_BYTES,
|
||||||
|
QEMU_IFLA_VF_STATS_BROADCAST,
|
||||||
|
QEMU_IFLA_VF_STATS_MULTICAST,
|
||||||
|
QEMU_IFLA_VF_STATS_PAD,
|
||||||
|
QEMU_IFLA_VF_STATS_RX_DROPPED,
|
||||||
|
QEMU_IFLA_VF_STATS_TX_DROPPED,
|
||||||
|
QEMU__IFLA_VF_STATS_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
QEMU_IFLA_VF_UNSPEC,
|
||||||
|
QEMU_IFLA_VF_MAC,
|
||||||
|
QEMU_IFLA_VF_VLAN,
|
||||||
|
QEMU_IFLA_VF_TX_RATE,
|
||||||
|
QEMU_IFLA_VF_SPOOFCHK,
|
||||||
|
QEMU_IFLA_VF_LINK_STATE,
|
||||||
|
QEMU_IFLA_VF_RATE,
|
||||||
|
QEMU_IFLA_VF_RSS_QUERY_EN,
|
||||||
|
QEMU_IFLA_VF_STATS,
|
||||||
|
QEMU_IFLA_VF_TRUST,
|
||||||
|
QEMU_IFLA_VF_IB_NODE_GUID,
|
||||||
|
QEMU_IFLA_VF_IB_PORT_GUID,
|
||||||
|
QEMU_IFLA_VF_VLAN_LIST,
|
||||||
|
QEMU_IFLA_VF_BROADCAST,
|
||||||
|
QEMU__IFLA_VF_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
TargetFdTrans **target_fd_trans;
|
TargetFdTrans **target_fd_trans;
|
||||||
QemuMutex target_fd_trans_lock;
|
QemuMutex target_fd_trans_lock;
|
||||||
unsigned int target_fd_max;
|
unsigned int target_fd_max;
|
||||||
|
@ -573,6 +609,8 @@ static abi_long host_to_target_slave_data_bridge_nlattr(struct nlattr *nlattr,
|
||||||
/* uin32_t */
|
/* uin32_t */
|
||||||
case QEMU_IFLA_BRPORT_COST:
|
case QEMU_IFLA_BRPORT_COST:
|
||||||
case QEMU_IFLA_BRPORT_BACKUP_PORT:
|
case QEMU_IFLA_BRPORT_BACKUP_PORT:
|
||||||
|
case QEMU_IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT:
|
||||||
|
case QEMU_IFLA_BRPORT_MCAST_EHT_HOSTS_CNT:
|
||||||
u32 = NLA_DATA(nlattr);
|
u32 = NLA_DATA(nlattr);
|
||||||
*u32 = tswap32(*u32);
|
*u32 = tswap32(*u32);
|
||||||
break;
|
break;
|
||||||
|
@ -805,6 +843,145 @@ static abi_long host_to_target_data_xdp_nlattr(struct nlattr *nlattr,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static abi_long host_to_target_data_vlan_list_nlattr(struct nlattr *nlattr,
|
||||||
|
void *context)
|
||||||
|
{
|
||||||
|
struct ifla_vf_vlan_info *vlan_info;
|
||||||
|
|
||||||
|
switch (nlattr->nla_type) {
|
||||||
|
/* struct ifla_vf_vlan_info */
|
||||||
|
case IFLA_VF_VLAN_INFO:
|
||||||
|
vlan_info = NLA_DATA(nlattr);
|
||||||
|
vlan_info->vf = tswap32(vlan_info->vf);
|
||||||
|
vlan_info->vlan = tswap32(vlan_info->vlan);
|
||||||
|
vlan_info->qos = tswap32(vlan_info->qos);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qemu_log_mask(LOG_UNIMP, "Unknown host VLAN LIST type: %d\n",
|
||||||
|
nlattr->nla_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static abi_long host_to_target_data_vf_stats_nlattr(struct nlattr *nlattr,
|
||||||
|
void *context)
|
||||||
|
{
|
||||||
|
uint64_t *u64;
|
||||||
|
|
||||||
|
switch (nlattr->nla_type) {
|
||||||
|
/* uint64_t */
|
||||||
|
case QEMU_IFLA_VF_STATS_RX_PACKETS:
|
||||||
|
case QEMU_IFLA_VF_STATS_TX_PACKETS:
|
||||||
|
case QEMU_IFLA_VF_STATS_RX_BYTES:
|
||||||
|
case QEMU_IFLA_VF_STATS_TX_BYTES:
|
||||||
|
case QEMU_IFLA_VF_STATS_BROADCAST:
|
||||||
|
case QEMU_IFLA_VF_STATS_MULTICAST:
|
||||||
|
case QEMU_IFLA_VF_STATS_PAD:
|
||||||
|
case QEMU_IFLA_VF_STATS_RX_DROPPED:
|
||||||
|
case QEMU_IFLA_VF_STATS_TX_DROPPED:
|
||||||
|
u64 = NLA_DATA(nlattr);
|
||||||
|
*u64 = tswap64(*u64);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qemu_log_mask(LOG_UNIMP, "Unknown host VF STATS type: %d\n",
|
||||||
|
nlattr->nla_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static abi_long host_to_target_data_vfinfo_nlattr(struct nlattr *nlattr,
|
||||||
|
void *context)
|
||||||
|
{
|
||||||
|
struct ifla_vf_mac *mac;
|
||||||
|
struct ifla_vf_vlan *vlan;
|
||||||
|
struct ifla_vf_vlan_info *vlan_info;
|
||||||
|
struct ifla_vf_spoofchk *spoofchk;
|
||||||
|
struct ifla_vf_rate *rate;
|
||||||
|
struct ifla_vf_link_state *link_state;
|
||||||
|
struct ifla_vf_rss_query_en *rss_query_en;
|
||||||
|
struct ifla_vf_trust *trust;
|
||||||
|
struct ifla_vf_guid *guid;
|
||||||
|
|
||||||
|
switch (nlattr->nla_type) {
|
||||||
|
/* struct ifla_vf_mac */
|
||||||
|
case QEMU_IFLA_VF_MAC:
|
||||||
|
mac = NLA_DATA(nlattr);
|
||||||
|
mac->vf = tswap32(mac->vf);
|
||||||
|
break;
|
||||||
|
/* struct ifla_vf_broadcast */
|
||||||
|
case QEMU_IFLA_VF_BROADCAST:
|
||||||
|
break;
|
||||||
|
/* struct struct ifla_vf_vlan */
|
||||||
|
case QEMU_IFLA_VF_VLAN:
|
||||||
|
vlan = NLA_DATA(nlattr);
|
||||||
|
vlan->vf = tswap32(vlan->vf);
|
||||||
|
vlan->vlan = tswap32(vlan->vlan);
|
||||||
|
vlan->qos = tswap32(vlan->qos);
|
||||||
|
break;
|
||||||
|
/* struct ifla_vf_vlan_info */
|
||||||
|
case QEMU_IFLA_VF_TX_RATE:
|
||||||
|
vlan_info = NLA_DATA(nlattr);
|
||||||
|
vlan_info->vf = tswap32(vlan_info->vf);
|
||||||
|
vlan_info->vlan = tswap32(vlan_info->vlan);
|
||||||
|
vlan_info->qos = tswap32(vlan_info->qos);
|
||||||
|
break;
|
||||||
|
/* struct ifla_vf_spoofchk */
|
||||||
|
case QEMU_IFLA_VF_SPOOFCHK:
|
||||||
|
spoofchk = NLA_DATA(nlattr);
|
||||||
|
spoofchk->vf = tswap32(spoofchk->vf);
|
||||||
|
spoofchk->setting = tswap32(spoofchk->setting);
|
||||||
|
break;
|
||||||
|
/* struct ifla_vf_rate */
|
||||||
|
case QEMU_IFLA_VF_RATE:
|
||||||
|
rate = NLA_DATA(nlattr);
|
||||||
|
rate->vf = tswap32(rate->vf);
|
||||||
|
rate->min_tx_rate = tswap32(rate->min_tx_rate);
|
||||||
|
rate->max_tx_rate = tswap32(rate->max_tx_rate);
|
||||||
|
break;
|
||||||
|
/* struct ifla_vf_link_state */
|
||||||
|
case QEMU_IFLA_VF_LINK_STATE:
|
||||||
|
link_state = NLA_DATA(nlattr);
|
||||||
|
link_state->vf = tswap32(link_state->vf);
|
||||||
|
link_state->link_state = tswap32(link_state->link_state);
|
||||||
|
break;
|
||||||
|
/* struct ifla_vf_rss_query_en */
|
||||||
|
case QEMU_IFLA_VF_RSS_QUERY_EN:
|
||||||
|
rss_query_en = NLA_DATA(nlattr);
|
||||||
|
rss_query_en->vf = tswap32(rss_query_en->vf);
|
||||||
|
rss_query_en->setting = tswap32(rss_query_en->setting);
|
||||||
|
break;
|
||||||
|
/* struct ifla_vf_trust */
|
||||||
|
case QEMU_IFLA_VF_TRUST:
|
||||||
|
trust = NLA_DATA(nlattr);
|
||||||
|
trust->vf = tswap32(trust->vf);
|
||||||
|
trust->setting = tswap32(trust->setting);
|
||||||
|
break;
|
||||||
|
/* struct ifla_vf_guid */
|
||||||
|
case QEMU_IFLA_VF_IB_NODE_GUID:
|
||||||
|
case QEMU_IFLA_VF_IB_PORT_GUID:
|
||||||
|
guid = NLA_DATA(nlattr);
|
||||||
|
guid->vf = tswap32(guid->vf);
|
||||||
|
guid->guid = tswap32(guid->guid);
|
||||||
|
break;
|
||||||
|
/* nested */
|
||||||
|
case QEMU_IFLA_VF_VLAN_LIST:
|
||||||
|
return host_to_target_for_each_nlattr(RTA_DATA(nlattr), nlattr->nla_len,
|
||||||
|
NULL,
|
||||||
|
host_to_target_data_vlan_list_nlattr);
|
||||||
|
case QEMU_IFLA_VF_STATS:
|
||||||
|
return host_to_target_for_each_nlattr(RTA_DATA(nlattr), nlattr->nla_len,
|
||||||
|
NULL,
|
||||||
|
host_to_target_data_vf_stats_nlattr);
|
||||||
|
default:
|
||||||
|
qemu_log_mask(LOG_UNIMP, "Unknown host VFINFO type: %d\n",
|
||||||
|
nlattr->nla_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr)
|
static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr)
|
||||||
{
|
{
|
||||||
uint32_t *u32;
|
uint32_t *u32;
|
||||||
|
@ -818,9 +995,12 @@ static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr)
|
||||||
case QEMU_IFLA_ADDRESS:
|
case QEMU_IFLA_ADDRESS:
|
||||||
case QEMU_IFLA_BROADCAST:
|
case QEMU_IFLA_BROADCAST:
|
||||||
case QEMU_IFLA_PERM_ADDRESS:
|
case QEMU_IFLA_PERM_ADDRESS:
|
||||||
|
case QEMU_IFLA_PHYS_PORT_ID:
|
||||||
/* string */
|
/* string */
|
||||||
case QEMU_IFLA_IFNAME:
|
case QEMU_IFLA_IFNAME:
|
||||||
case QEMU_IFLA_QDISC:
|
case QEMU_IFLA_QDISC:
|
||||||
|
case QEMU_IFLA_PARENT_DEV_NAME:
|
||||||
|
case QEMU_IFLA_PARENT_DEV_BUS_NAME:
|
||||||
break;
|
break;
|
||||||
/* uin8_t */
|
/* uin8_t */
|
||||||
case QEMU_IFLA_OPERSTATE:
|
case QEMU_IFLA_OPERSTATE:
|
||||||
|
@ -939,6 +1119,10 @@ static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr)
|
||||||
return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len,
|
return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len,
|
||||||
NULL,
|
NULL,
|
||||||
host_to_target_data_xdp_nlattr);
|
host_to_target_data_xdp_nlattr);
|
||||||
|
case QEMU_IFLA_VFINFO_LIST:
|
||||||
|
return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len,
|
||||||
|
NULL,
|
||||||
|
host_to_target_data_vfinfo_nlattr);
|
||||||
default:
|
default:
|
||||||
qemu_log_mask(LOG_UNIMP, "Unknown host QEMU_IFLA type: %d\n",
|
qemu_log_mask(LOG_UNIMP, "Unknown host QEMU_IFLA type: %d\n",
|
||||||
rtattr->rta_type);
|
rtattr->rta_type);
|
||||||
|
|
|
@ -55,6 +55,21 @@
|
||||||
#define TARGET_SIG_UNBLOCK 1 /* for unblocking signals */
|
#define TARGET_SIG_UNBLOCK 1 /* for unblocking signals */
|
||||||
#define TARGET_SIG_SETMASK 2 /* for setting the signal mask */
|
#define TARGET_SIG_SETMASK 2 /* for setting the signal mask */
|
||||||
|
|
||||||
|
/* this struct defines a stack used during syscall handling */
|
||||||
|
typedef struct target_sigaltstack {
|
||||||
|
abi_ulong ss_sp;
|
||||||
|
abi_int ss_flags;
|
||||||
|
abi_ulong ss_size;
|
||||||
|
} target_stack_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sigaltstack controls
|
||||||
|
*/
|
||||||
|
#define TARGET_SS_ONSTACK 1
|
||||||
|
#define TARGET_SS_DISABLE 2
|
||||||
|
|
||||||
|
#define TARGET_MINSIGSTKSZ 2048
|
||||||
|
|
||||||
/* bit-flags */
|
/* bit-flags */
|
||||||
#define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */
|
#define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */
|
||||||
/* mask for all SS_xxx flags */
|
/* mask for all SS_xxx flags */
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Generic prctl unalign functions for linux-user
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
#ifndef GENERIC_TARGET_PRCTL_UNALIGN_H
|
||||||
|
#define GENERIC_TARGET_PRCTL_UNALIGN_H
|
||||||
|
|
||||||
|
static abi_long do_prctl_get_unalign(CPUArchState *env, target_long arg2)
|
||||||
|
{
|
||||||
|
CPUState *cs = env_cpu(env);
|
||||||
|
uint32_t res = PR_UNALIGN_NOPRINT;
|
||||||
|
if (cs->prctl_unalign_sigbus) {
|
||||||
|
res |= PR_UNALIGN_SIGBUS;
|
||||||
|
}
|
||||||
|
return put_user_u32(res, arg2);
|
||||||
|
}
|
||||||
|
#define do_prctl_get_unalign do_prctl_get_unalign
|
||||||
|
|
||||||
|
static abi_long do_prctl_set_unalign(CPUArchState *env, target_long arg2)
|
||||||
|
{
|
||||||
|
env_cpu(env)->prctl_unalign_sigbus = arg2 & PR_UNALIGN_SIGBUS;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#define do_prctl_set_unalign do_prctl_set_unalign
|
||||||
|
|
||||||
|
#endif /* GENERIC_TARGET_PRCTL_UNALIGN_H */
|
|
@ -0,0 +1 @@
|
||||||
|
/* No special prctl support required. */
|
|
@ -18,17 +18,6 @@
|
||||||
#ifndef HEXAGON_TARGET_SIGNAL_H
|
#ifndef HEXAGON_TARGET_SIGNAL_H
|
||||||
#define HEXAGON_TARGET_SIGNAL_H
|
#define HEXAGON_TARGET_SIGNAL_H
|
||||||
|
|
||||||
typedef struct target_sigaltstack {
|
|
||||||
abi_ulong ss_sp;
|
|
||||||
abi_int ss_flags;
|
|
||||||
abi_ulong ss_size;
|
|
||||||
} target_stack_t;
|
|
||||||
|
|
||||||
#define TARGET_SS_ONSTACK 1
|
|
||||||
#define TARGET_SS_DISABLE 2
|
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
|
|
||||||
#include "../generic/signal.h"
|
#include "../generic/signal.h"
|
||||||
|
|
||||||
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
|
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
#include "../generic/target_prctl_unalign.h"
|
|
@ -64,7 +64,6 @@ typedef struct target_sigaltstack {
|
||||||
#define TARGET_SA_NOCLDWAIT 0x00000080
|
#define TARGET_SA_NOCLDWAIT 0x00000080
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
#define TARGET_MINSIGSTKSZ 2048
|
||||||
#define TARGET_SIGSTKSZ 8192
|
|
||||||
|
|
||||||
/* bit-flags */
|
/* bit-flags */
|
||||||
#define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */
|
#define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */
|
||||||
|
|
|
@ -22,7 +22,6 @@ struct target_pt_regs {
|
||||||
#define UNAME_MACHINE "parisc"
|
#define UNAME_MACHINE "parisc"
|
||||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||||
#define TARGET_CLONE_BACKWARDS
|
#define TARGET_CLONE_BACKWARDS
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_MCL_CURRENT 1
|
#define TARGET_MCL_CURRENT 1
|
||||||
#define TARGET_MCL_FUTURE 2
|
#define TARGET_MCL_FUTURE 2
|
||||||
#define TARGET_MCL_ONFAULT 4
|
#define TARGET_MCL_ONFAULT 4
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/* No special prctl support required. */
|
|
@ -1,24 +1,6 @@
|
||||||
#ifndef I386_TARGET_SIGNAL_H
|
#ifndef I386_TARGET_SIGNAL_H
|
||||||
#define I386_TARGET_SIGNAL_H
|
#define I386_TARGET_SIGNAL_H
|
||||||
|
|
||||||
/* this struct defines a stack used during syscall handling */
|
|
||||||
|
|
||||||
typedef struct target_sigaltstack {
|
|
||||||
abi_ulong ss_sp;
|
|
||||||
abi_int ss_flags;
|
|
||||||
abi_ulong ss_size;
|
|
||||||
} target_stack_t;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* sigaltstack controls
|
|
||||||
*/
|
|
||||||
#define TARGET_SS_ONSTACK 1
|
|
||||||
#define TARGET_SS_DISABLE 2
|
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_SIGSTKSZ 8192
|
|
||||||
|
|
||||||
#include "../generic/signal.h"
|
#include "../generic/signal.h"
|
||||||
|
|
||||||
#define TARGET_ARCH_HAS_SETUP_FRAME
|
#define TARGET_ARCH_HAS_SETUP_FRAME
|
||||||
|
|
|
@ -150,7 +150,6 @@ struct target_vm86plus_struct {
|
||||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||||
|
|
||||||
#define TARGET_CLONE_BACKWARDS
|
#define TARGET_CLONE_BACKWARDS
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_MCL_CURRENT 1
|
#define TARGET_MCL_CURRENT 1
|
||||||
#define TARGET_MCL_FUTURE 2
|
#define TARGET_MCL_FUTURE 2
|
||||||
#define TARGET_MCL_ONFAULT 4
|
#define TARGET_MCL_ONFAULT 4
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/* No special prctl support required. */
|
|
@ -1,24 +1,6 @@
|
||||||
#ifndef M68K_TARGET_SIGNAL_H
|
#ifndef M68K_TARGET_SIGNAL_H
|
||||||
#define M68K_TARGET_SIGNAL_H
|
#define M68K_TARGET_SIGNAL_H
|
||||||
|
|
||||||
/* this struct defines a stack used during syscall handling */
|
|
||||||
|
|
||||||
typedef struct target_sigaltstack {
|
|
||||||
abi_ulong ss_sp;
|
|
||||||
abi_int ss_flags;
|
|
||||||
abi_ulong ss_size;
|
|
||||||
} target_stack_t;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* sigaltstack controls
|
|
||||||
*/
|
|
||||||
#define TARGET_SS_ONSTACK 1
|
|
||||||
#define TARGET_SS_DISABLE 2
|
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_SIGSTKSZ 8192
|
|
||||||
|
|
||||||
#include "../generic/signal.h"
|
#include "../generic/signal.h"
|
||||||
|
|
||||||
#define TARGET_ARCH_HAS_SETUP_FRAME
|
#define TARGET_ARCH_HAS_SETUP_FRAME
|
||||||
|
|
|
@ -20,7 +20,6 @@ struct target_pt_regs {
|
||||||
#define UNAME_MACHINE "m68k"
|
#define UNAME_MACHINE "m68k"
|
||||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_MCL_CURRENT 1
|
#define TARGET_MCL_CURRENT 1
|
||||||
#define TARGET_MCL_FUTURE 2
|
#define TARGET_MCL_FUTURE 2
|
||||||
#define TARGET_MCL_ONFAULT 4
|
#define TARGET_MCL_ONFAULT 4
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/* No special prctl support required. */
|
|
@ -1,24 +1,6 @@
|
||||||
#ifndef MICROBLAZE_TARGET_SIGNAL_H
|
#ifndef MICROBLAZE_TARGET_SIGNAL_H
|
||||||
#define MICROBLAZE_TARGET_SIGNAL_H
|
#define MICROBLAZE_TARGET_SIGNAL_H
|
||||||
|
|
||||||
/* this struct defines a stack used during syscall handling */
|
|
||||||
|
|
||||||
typedef struct target_sigaltstack {
|
|
||||||
abi_ulong ss_sp;
|
|
||||||
abi_int ss_flags;
|
|
||||||
abi_ulong ss_size;
|
|
||||||
} target_stack_t;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* sigaltstack controls
|
|
||||||
*/
|
|
||||||
#define TARGET_SS_ONSTACK 1
|
|
||||||
#define TARGET_SS_DISABLE 2
|
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_SIGSTKSZ 8192
|
|
||||||
|
|
||||||
#include "../generic/signal.h"
|
#include "../generic/signal.h"
|
||||||
|
|
||||||
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
|
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
|
||||||
|
|
|
@ -49,7 +49,6 @@ struct target_pt_regs {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TARGET_CLONE_BACKWARDS
|
#define TARGET_CLONE_BACKWARDS
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_MCL_CURRENT 1
|
#define TARGET_MCL_CURRENT 1
|
||||||
#define TARGET_MCL_FUTURE 2
|
#define TARGET_MCL_FUTURE 2
|
||||||
#define TARGET_MCL_ONFAULT 4
|
#define TARGET_MCL_ONFAULT 4
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* MIPS specific prctl functions for linux-user
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
#ifndef MIPS_TARGET_PRCTL_H
|
||||||
|
#define MIPS_TARGET_PRCTL_H
|
||||||
|
|
||||||
|
static abi_long do_prctl_get_fp_mode(CPUArchState *env)
|
||||||
|
{
|
||||||
|
abi_long ret = 0;
|
||||||
|
|
||||||
|
if (env->CP0_Status & (1 << CP0St_FR)) {
|
||||||
|
ret |= PR_FP_MODE_FR;
|
||||||
|
}
|
||||||
|
if (env->CP0_Config5 & (1 << CP0C5_FRE)) {
|
||||||
|
ret |= PR_FP_MODE_FRE;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#define do_prctl_get_fp_mode do_prctl_get_fp_mode
|
||||||
|
|
||||||
|
static abi_long do_prctl_set_fp_mode(CPUArchState *env, abi_long arg2)
|
||||||
|
{
|
||||||
|
bool old_fr = env->CP0_Status & (1 << CP0St_FR);
|
||||||
|
bool old_fre = env->CP0_Config5 & (1 << CP0C5_FRE);
|
||||||
|
bool new_fr = arg2 & PR_FP_MODE_FR;
|
||||||
|
bool new_fre = arg2 & PR_FP_MODE_FRE;
|
||||||
|
const unsigned int known_bits = PR_FP_MODE_FR | PR_FP_MODE_FRE;
|
||||||
|
|
||||||
|
/* If nothing to change, return right away, successfully. */
|
||||||
|
if (old_fr == new_fr && old_fre == new_fre) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Check the value is valid */
|
||||||
|
if (arg2 & ~known_bits) {
|
||||||
|
return -TARGET_EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
/* Setting FRE without FR is not supported. */
|
||||||
|
if (new_fre && !new_fr) {
|
||||||
|
return -TARGET_EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
if (new_fr && !(env->active_fpu.fcr0 & (1 << FCR0_F64))) {
|
||||||
|
/* FR1 is not supported */
|
||||||
|
return -TARGET_EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
if (!new_fr && (env->active_fpu.fcr0 & (1 << FCR0_F64))
|
||||||
|
&& !(env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
|
||||||
|
/* cannot set FR=0 */
|
||||||
|
return -TARGET_EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
if (new_fre && !(env->active_fpu.fcr0 & (1 << FCR0_FREP))) {
|
||||||
|
/* Cannot set FRE=1 */
|
||||||
|
return -TARGET_EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i;
|
||||||
|
fpr_t *fpr = env->active_fpu.fpr;
|
||||||
|
for (i = 0; i < 32 ; i += 2) {
|
||||||
|
if (!old_fr && new_fr) {
|
||||||
|
fpr[i].w[!FP_ENDIAN_IDX] = fpr[i + 1].w[FP_ENDIAN_IDX];
|
||||||
|
} else if (old_fr && !new_fr) {
|
||||||
|
fpr[i + 1].w[FP_ENDIAN_IDX] = fpr[i].w[!FP_ENDIAN_IDX];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_fr) {
|
||||||
|
env->CP0_Status |= (1 << CP0St_FR);
|
||||||
|
env->hflags |= MIPS_HFLAG_F64;
|
||||||
|
} else {
|
||||||
|
env->CP0_Status &= ~(1 << CP0St_FR);
|
||||||
|
env->hflags &= ~MIPS_HFLAG_F64;
|
||||||
|
}
|
||||||
|
if (new_fre) {
|
||||||
|
env->CP0_Config5 |= (1 << CP0C5_FRE);
|
||||||
|
if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
|
||||||
|
env->hflags |= MIPS_HFLAG_FRE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
env->CP0_Config5 &= ~(1 << CP0C5_FRE);
|
||||||
|
env->hflags &= ~MIPS_HFLAG_FRE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#define do_prctl_set_fp_mode do_prctl_set_fp_mode
|
||||||
|
|
||||||
|
#endif /* MIPS_TARGET_PRCTL_H */
|
|
@ -67,7 +67,6 @@ typedef struct target_sigaltstack {
|
||||||
#define TARGET_SA_RESTORER 0x04000000 /* Only for O32 */
|
#define TARGET_SA_RESTORER 0x04000000 /* Only for O32 */
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
#define TARGET_MINSIGSTKSZ 2048
|
||||||
#define TARGET_SIGSTKSZ 8192
|
|
||||||
|
|
||||||
#if defined(TARGET_ABI_MIPSO32)
|
#if defined(TARGET_ABI_MIPSO32)
|
||||||
/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
|
/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
|
||||||
|
|
|
@ -24,7 +24,6 @@ struct target_pt_regs {
|
||||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||||
|
|
||||||
#define TARGET_CLONE_BACKWARDS
|
#define TARGET_CLONE_BACKWARDS
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_MCL_CURRENT 1
|
#define TARGET_MCL_CURRENT 1
|
||||||
#define TARGET_MCL_FUTURE 2
|
#define TARGET_MCL_FUTURE 2
|
||||||
#define TARGET_MCL_ONFAULT 4
|
#define TARGET_MCL_ONFAULT 4
|
||||||
|
@ -36,10 +35,4 @@ static inline abi_ulong target_shmlba(CPUMIPSState *env)
|
||||||
return 0x40000;
|
return 0x40000;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MIPS-specific prctl() options */
|
|
||||||
#define TARGET_PR_SET_FP_MODE 45
|
|
||||||
#define TARGET_PR_GET_FP_MODE 46
|
|
||||||
#define TARGET_PR_FP_MODE_FR (1 << 0)
|
|
||||||
#define TARGET_PR_FP_MODE_FRE (1 << 1)
|
|
||||||
|
|
||||||
#endif /* MIPS_TARGET_SYSCALL_H */
|
#endif /* MIPS_TARGET_SYSCALL_H */
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
#include "../mips/target_prctl.h"
|
|
@ -65,7 +65,6 @@ typedef struct target_sigaltstack {
|
||||||
#define TARGET_SA_RESETHAND 0x80000000
|
#define TARGET_SA_RESETHAND 0x80000000
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
#define TARGET_MINSIGSTKSZ 2048
|
||||||
#define TARGET_SIGSTKSZ 8192
|
|
||||||
|
|
||||||
/* bit-flags */
|
/* bit-flags */
|
||||||
#define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */
|
#define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */
|
||||||
|
|
|
@ -21,7 +21,6 @@ struct target_pt_regs {
|
||||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||||
|
|
||||||
#define TARGET_CLONE_BACKWARDS
|
#define TARGET_CLONE_BACKWARDS
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_MCL_CURRENT 1
|
#define TARGET_MCL_CURRENT 1
|
||||||
#define TARGET_MCL_FUTURE 2
|
#define TARGET_MCL_FUTURE 2
|
||||||
#define TARGET_MCL_ONFAULT 4
|
#define TARGET_MCL_ONFAULT 4
|
||||||
|
@ -33,10 +32,4 @@ static inline abi_ulong target_shmlba(CPUMIPSState *env)
|
||||||
return 0x40000;
|
return 0x40000;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MIPS-specific prctl() options */
|
|
||||||
#define TARGET_PR_SET_FP_MODE 45
|
|
||||||
#define TARGET_PR_GET_FP_MODE 46
|
|
||||||
#define TARGET_PR_FP_MODE_FR (1 << 0)
|
|
||||||
#define TARGET_PR_FP_MODE_FRE (1 << 1)
|
|
||||||
|
|
||||||
#endif /* MIPS64_TARGET_SYSCALL_H */
|
#endif /* MIPS64_TARGET_SYSCALL_H */
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
void cpu_loop(CPUNios2State *env)
|
void cpu_loop(CPUNios2State *env)
|
||||||
{
|
{
|
||||||
CPUState *cs = env_cpu(env);
|
CPUState *cs = env_cpu(env);
|
||||||
Nios2CPU *cpu = NIOS2_CPU(cs);
|
|
||||||
target_siginfo_t info;
|
target_siginfo_t info;
|
||||||
int trapnr, ret;
|
int trapnr, ret;
|
||||||
|
|
||||||
|
@ -39,9 +38,10 @@ void cpu_loop(CPUNios2State *env)
|
||||||
case EXCP_INTERRUPT:
|
case EXCP_INTERRUPT:
|
||||||
/* just indicate that signals should be handled asap */
|
/* just indicate that signals should be handled asap */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXCP_TRAP:
|
case EXCP_TRAP:
|
||||||
if (env->regs[R_AT] == 0) {
|
switch (env->error_code) {
|
||||||
abi_long ret;
|
case 0:
|
||||||
qemu_log_mask(CPU_LOG_INT, "\nSyscall\n");
|
qemu_log_mask(CPU_LOG_INT, "\nSyscall\n");
|
||||||
|
|
||||||
ret = do_syscall(env, env->regs[2],
|
ret = do_syscall(env, env->regs[2],
|
||||||
|
@ -55,26 +55,56 @@ void cpu_loop(CPUNios2State *env)
|
||||||
|
|
||||||
env->regs[2] = abs(ret);
|
env->regs[2] = abs(ret);
|
||||||
/* Return value is 0..4096 */
|
/* Return value is 0..4096 */
|
||||||
env->regs[7] = (ret > 0xfffffffffffff000ULL);
|
env->regs[7] = ret > 0xfffff000u;
|
||||||
env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
|
|
||||||
env->regs[CR_STATUS] &= ~0x3;
|
|
||||||
env->regs[R_EA] = env->regs[R_PC] + 4;
|
|
||||||
env->regs[R_PC] += 4;
|
env->regs[R_PC] += 4;
|
||||||
break;
|
break;
|
||||||
} else {
|
|
||||||
qemu_log_mask(CPU_LOG_INT, "\nTrap\n");
|
|
||||||
|
|
||||||
env->regs[CR_ESTATUS] = env->regs[CR_STATUS];
|
case 1:
|
||||||
env->regs[CR_STATUS] &= ~0x3;
|
qemu_log_mask(CPU_LOG_INT, "\nTrap 1\n");
|
||||||
env->regs[R_EA] = env->regs[R_PC] + 4;
|
force_sig_fault(TARGET_SIGUSR1, 0, env->regs[R_PC]);
|
||||||
env->regs[R_PC] = cpu->exception_addr;
|
break;
|
||||||
|
case 2:
|
||||||
|
qemu_log_mask(CPU_LOG_INT, "\nTrap 2\n");
|
||||||
|
force_sig_fault(TARGET_SIGUSR2, 0, env->regs[R_PC]);
|
||||||
|
break;
|
||||||
|
case 31:
|
||||||
|
qemu_log_mask(CPU_LOG_INT, "\nTrap 31\n");
|
||||||
|
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->regs[R_PC]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qemu_log_mask(CPU_LOG_INT, "\nTrap %d\n", env->error_code);
|
||||||
|
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLTRP,
|
||||||
|
env->regs[R_PC]);
|
||||||
|
break;
|
||||||
|
|
||||||
info.si_signo = TARGET_SIGTRAP;
|
case 16: /* QEMU specific, for __kuser_cmpxchg */
|
||||||
info.si_errno = 0;
|
{
|
||||||
info.si_code = TARGET_TRAP_BRKPT;
|
abi_ptr g = env->regs[4];
|
||||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
uint32_t *h, n, o;
|
||||||
|
|
||||||
|
if (g & 0x3) {
|
||||||
|
force_sig_fault(TARGET_SIGBUS, TARGET_BUS_ADRALN, g);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret = page_get_flags(g);
|
||||||
|
if (!(ret & PAGE_VALID)) {
|
||||||
|
force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, g);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!(ret & PAGE_READ) || !(ret & PAGE_WRITE)) {
|
||||||
|
force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_ACCERR, g);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
h = g2h(cs, g);
|
||||||
|
o = env->regs[5];
|
||||||
|
n = env->regs[6];
|
||||||
|
env->regs[2] = qatomic_cmpxchg(h, o, n) - o;
|
||||||
|
env->regs[R_PC] += 4;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case EXCP_DEBUG:
|
case EXCP_DEBUG:
|
||||||
info.si_signo = TARGET_SIGTRAP;
|
info.si_signo = TARGET_SIGTRAP;
|
||||||
info.si_errno = 0;
|
info.si_errno = 0;
|
||||||
|
@ -82,29 +112,7 @@ void cpu_loop(CPUNios2State *env)
|
||||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||||
break;
|
break;
|
||||||
case 0xaa:
|
case 0xaa:
|
||||||
switch (env->regs[R_PC]) {
|
{
|
||||||
/*case 0x1000:*/ /* TODO:__kuser_helper_version */
|
|
||||||
case 0x1004: /* __kuser_cmpxchg */
|
|
||||||
start_exclusive();
|
|
||||||
if (env->regs[4] & 0x3) {
|
|
||||||
goto kuser_fail;
|
|
||||||
}
|
|
||||||
ret = get_user_u32(env->regs[2], env->regs[4]);
|
|
||||||
if (ret) {
|
|
||||||
end_exclusive();
|
|
||||||
goto kuser_fail;
|
|
||||||
}
|
|
||||||
env->regs[2] -= env->regs[5];
|
|
||||||
if (env->regs[2] == 0) {
|
|
||||||
put_user_u32(env->regs[6], env->regs[4]);
|
|
||||||
}
|
|
||||||
end_exclusive();
|
|
||||||
env->regs[R_PC] = env->regs[R_RA];
|
|
||||||
break;
|
|
||||||
/*case 0x1040:*/ /* TODO:__kuser_sigtramp */
|
|
||||||
default:
|
|
||||||
;
|
|
||||||
kuser_fail:
|
|
||||||
info.si_signo = TARGET_SIGSEGV;
|
info.si_signo = TARGET_SIGSEGV;
|
||||||
info.si_errno = 0;
|
info.si_errno = 0;
|
||||||
/* TODO: check env->error_code */
|
/* TODO: check env->error_code */
|
||||||
|
@ -147,9 +155,6 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
|
||||||
env->regs[R_SP] = regs->sp;
|
env->regs[R_SP] = regs->sp;
|
||||||
env->regs[R_GP] = regs->gp;
|
env->regs[R_GP] = regs->gp;
|
||||||
env->regs[CR_ESTATUS] = regs->estatus;
|
env->regs[CR_ESTATUS] = regs->estatus;
|
||||||
env->regs[R_EA] = regs->ea;
|
|
||||||
/* TODO: unsigned long orig_r7; */
|
|
||||||
|
|
||||||
/* Emulate eret when starting thread. */
|
|
||||||
env->regs[R_PC] = regs->ea;
|
env->regs[R_PC] = regs->ea;
|
||||||
|
/* TODO: unsigned long orig_r7; */
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ struct target_rt_sigframe {
|
||||||
struct target_ucontext uc;
|
struct target_ucontext uc;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
|
static void rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
|
||||||
{
|
{
|
||||||
unsigned long *gregs = uc->tuc_mcontext.gregs;
|
unsigned long *gregs = uc->tuc_mcontext.gregs;
|
||||||
|
|
||||||
|
@ -73,10 +73,8 @@ static int rt_setup_ucontext(struct target_ucontext *uc, CPUNios2State *env)
|
||||||
__put_user(env->regs[R_RA], &gregs[23]);
|
__put_user(env->regs[R_RA], &gregs[23]);
|
||||||
__put_user(env->regs[R_FP], &gregs[24]);
|
__put_user(env->regs[R_FP], &gregs[24]);
|
||||||
__put_user(env->regs[R_GP], &gregs[25]);
|
__put_user(env->regs[R_GP], &gregs[25]);
|
||||||
__put_user(env->regs[R_EA], &gregs[27]);
|
__put_user(env->regs[R_PC], &gregs[27]);
|
||||||
__put_user(env->regs[R_SP], &gregs[28]);
|
__put_user(env->regs[R_SP], &gregs[28]);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
|
static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
|
||||||
|
@ -124,7 +122,7 @@ static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
|
||||||
__get_user(env->regs[R_GP], &gregs[25]);
|
__get_user(env->regs[R_GP], &gregs[25]);
|
||||||
/* Not really necessary no user settable bits */
|
/* Not really necessary no user settable bits */
|
||||||
__get_user(temp, &gregs[26]);
|
__get_user(temp, &gregs[26]);
|
||||||
__get_user(env->regs[R_EA], &gregs[27]);
|
__get_user(env->regs[R_PC], &gregs[27]);
|
||||||
|
|
||||||
__get_user(env->regs[R_RA], &gregs[23]);
|
__get_user(env->regs[R_RA], &gregs[23]);
|
||||||
__get_user(env->regs[R_SP], &gregs[28]);
|
__get_user(env->regs[R_SP], &gregs[28]);
|
||||||
|
@ -135,8 +133,8 @@ static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
|
static abi_ptr get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
|
||||||
size_t frame_size)
|
size_t frame_size)
|
||||||
{
|
{
|
||||||
unsigned long usp;
|
unsigned long usp;
|
||||||
|
|
||||||
|
@ -144,7 +142,7 @@ static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env,
|
||||||
usp = target_sigsp(get_sp_from_cpustate(env), ka);
|
usp = target_sigsp(get_sp_from_cpustate(env), ka);
|
||||||
|
|
||||||
/* Verify, is it 32 or 64 bit aligned */
|
/* Verify, is it 32 or 64 bit aligned */
|
||||||
return (void *)((usp - frame_size) & -8UL);
|
return (usp - frame_size) & -8;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_rt_frame(int sig, struct target_sigaction *ka,
|
void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||||
|
@ -153,26 +151,24 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||||
CPUNios2State *env)
|
CPUNios2State *env)
|
||||||
{
|
{
|
||||||
struct target_rt_sigframe *frame;
|
struct target_rt_sigframe *frame;
|
||||||
int i, err = 0;
|
abi_ptr frame_addr;
|
||||||
|
int i;
|
||||||
|
|
||||||
frame = get_sigframe(ka, env, sizeof(*frame));
|
frame_addr = get_sigframe(ka, env, sizeof(*frame));
|
||||||
|
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
|
||||||
if (ka->sa_flags & SA_SIGINFO) {
|
force_sigsegv(sig);
|
||||||
tswap_siginfo(&frame->info, info);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tswap_siginfo(&frame->info, info);
|
||||||
|
|
||||||
/* Create the ucontext. */
|
/* Create the ucontext. */
|
||||||
__put_user(0, &frame->uc.tuc_flags);
|
__put_user(0, &frame->uc.tuc_flags);
|
||||||
__put_user(0, &frame->uc.tuc_link);
|
__put_user(0, &frame->uc.tuc_link);
|
||||||
target_save_altstack(&frame->uc.tuc_stack, env);
|
target_save_altstack(&frame->uc.tuc_stack, env);
|
||||||
err |= rt_setup_ucontext(&frame->uc, env);
|
rt_setup_ucontext(&frame->uc, env);
|
||||||
for (i = 0; i < TARGET_NSIG_WORDS; i++) {
|
for (i = 0; i < TARGET_NSIG_WORDS; i++) {
|
||||||
__put_user((abi_ulong)set->sig[i],
|
__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
|
||||||
(abi_ulong *)&frame->uc.tuc_sigmask.sig[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
goto give_sigsegv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up to return from userspace; jump to fixed address sigreturn
|
/* Set up to return from userspace; jump to fixed address sigreturn
|
||||||
|
@ -180,19 +176,13 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||||
env->regs[R_RA] = (unsigned long) (0x1044);
|
env->regs[R_RA] = (unsigned long) (0x1044);
|
||||||
|
|
||||||
/* Set up registers for signal handler */
|
/* Set up registers for signal handler */
|
||||||
env->regs[R_SP] = (unsigned long) frame;
|
env->regs[R_SP] = frame_addr;
|
||||||
env->regs[4] = (unsigned long) sig;
|
env->regs[4] = sig;
|
||||||
env->regs[5] = (unsigned long) &frame->info;
|
env->regs[5] = frame_addr + offsetof(struct target_rt_sigframe, info);
|
||||||
env->regs[6] = (unsigned long) &frame->uc;
|
env->regs[6] = frame_addr + offsetof(struct target_rt_sigframe, uc);
|
||||||
env->regs[R_EA] = (unsigned long) ka->_sa_handler;
|
env->regs[R_PC] = ka->_sa_handler;
|
||||||
return;
|
|
||||||
|
|
||||||
give_sigsegv:
|
unlock_user_struct(frame, frame_addr, 1);
|
||||||
if (sig == TARGET_SIGSEGV) {
|
|
||||||
ka->_sa_handler = TARGET_SIG_DFL;
|
|
||||||
}
|
|
||||||
force_sigsegv(sig);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long do_sigreturn(CPUNios2State *env)
|
long do_sigreturn(CPUNios2State *env)
|
||||||
|
@ -215,7 +205,7 @@ long do_rt_sigreturn(CPUNios2State *env)
|
||||||
}
|
}
|
||||||
|
|
||||||
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
|
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
|
||||||
do_sigprocmask(SIG_SETMASK, &set, NULL);
|
set_sigmask(&set);
|
||||||
|
|
||||||
if (rt_restore_ucontext(env, &frame->uc, &rval)) {
|
if (rt_restore_ucontext(env, &frame->uc, &rval)) {
|
||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/* No special prctl support required. */
|
|
@ -1,22 +1,6 @@
|
||||||
#ifndef NIOS2_TARGET_SIGNAL_H
|
#ifndef NIOS2_TARGET_SIGNAL_H
|
||||||
#define NIOS2_TARGET_SIGNAL_H
|
#define NIOS2_TARGET_SIGNAL_H
|
||||||
|
|
||||||
/* this struct defines a stack used during syscall handling */
|
|
||||||
|
|
||||||
typedef struct target_sigaltstack {
|
|
||||||
abi_ulong ss_sp;
|
|
||||||
abi_int ss_flags;
|
|
||||||
abi_ulong ss_size;
|
|
||||||
} target_stack_t;
|
|
||||||
|
|
||||||
|
|
||||||
/* sigaltstack controls */
|
|
||||||
#define TARGET_SS_ONSTACK 1
|
|
||||||
#define TARGET_SS_DISABLE 2
|
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_SIGSTKSZ 8192
|
|
||||||
|
|
||||||
#include "../generic/signal.h"
|
#include "../generic/signal.h"
|
||||||
|
|
||||||
/* Nios2 uses a fixed address on the kuser page for sigreturn. */
|
/* Nios2 uses a fixed address on the kuser page for sigreturn. */
|
||||||
|
|
|
@ -30,7 +30,6 @@ struct target_pt_regs {
|
||||||
unsigned long orig_r7;
|
unsigned long orig_r7;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_MCL_CURRENT 1
|
#define TARGET_MCL_CURRENT 1
|
||||||
#define TARGET_MCL_FUTURE 2
|
#define TARGET_MCL_FUTURE 2
|
||||||
#define TARGET_MCL_ONFAULT 4
|
#define TARGET_MCL_ONFAULT 4
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/* No special prctl support required. */
|
|
@ -1,29 +1,6 @@
|
||||||
#ifndef OPENRISC_TARGET_SIGNAL_H
|
#ifndef OPENRISC_TARGET_SIGNAL_H
|
||||||
#define OPENRISC_TARGET_SIGNAL_H
|
#define OPENRISC_TARGET_SIGNAL_H
|
||||||
|
|
||||||
/* this struct defines a stack used during syscall handling */
|
|
||||||
|
|
||||||
typedef struct target_sigaltstack {
|
|
||||||
abi_long ss_sp;
|
|
||||||
abi_int ss_flags;
|
|
||||||
abi_ulong ss_size;
|
|
||||||
} target_stack_t;
|
|
||||||
|
|
||||||
/* sigaltstack controls */
|
|
||||||
#define TARGET_SS_ONSTACK 1
|
|
||||||
#define TARGET_SS_DISABLE 2
|
|
||||||
|
|
||||||
#define TARGET_SA_NOCLDSTOP 0x00000001
|
|
||||||
#define TARGET_SA_NOCLDWAIT 0x00000002
|
|
||||||
#define TARGET_SA_SIGINFO 0x00000004
|
|
||||||
#define TARGET_SA_ONSTACK 0x08000000
|
|
||||||
#define TARGET_SA_RESTART 0x10000000
|
|
||||||
#define TARGET_SA_NODEFER 0x40000000
|
|
||||||
#define TARGET_SA_RESETHAND 0x80000000
|
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_SIGSTKSZ 8192
|
|
||||||
|
|
||||||
#include "../generic/signal.h"
|
#include "../generic/signal.h"
|
||||||
|
|
||||||
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
|
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
|
||||||
|
|
|
@ -15,7 +15,6 @@ struct target_pt_regs {
|
||||||
#define UNAME_MACHINE "openrisc"
|
#define UNAME_MACHINE "openrisc"
|
||||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_MCL_CURRENT 1
|
#define TARGET_MCL_CURRENT 1
|
||||||
#define TARGET_MCL_FUTURE 2
|
#define TARGET_MCL_FUTURE 2
|
||||||
#define TARGET_MCL_ONFAULT 4
|
#define TARGET_MCL_ONFAULT 4
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/* No special prctl support required. */
|
|
@ -1,24 +1,6 @@
|
||||||
#ifndef PPC_TARGET_SIGNAL_H
|
#ifndef PPC_TARGET_SIGNAL_H
|
||||||
#define PPC_TARGET_SIGNAL_H
|
#define PPC_TARGET_SIGNAL_H
|
||||||
|
|
||||||
/* this struct defines a stack used during syscall handling */
|
|
||||||
|
|
||||||
typedef struct target_sigaltstack {
|
|
||||||
abi_ulong ss_sp;
|
|
||||||
abi_int ss_flags;
|
|
||||||
abi_ulong ss_size;
|
|
||||||
} target_stack_t;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* sigaltstack controls
|
|
||||||
*/
|
|
||||||
#define TARGET_SS_ONSTACK 1
|
|
||||||
#define TARGET_SS_DISABLE 2
|
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_SIGSTKSZ 8192
|
|
||||||
|
|
||||||
#include "../generic/signal.h"
|
#include "../generic/signal.h"
|
||||||
|
|
||||||
#if !defined(TARGET_PPC64)
|
#if !defined(TARGET_PPC64)
|
||||||
|
|
|
@ -71,7 +71,6 @@ struct target_revectored_struct {
|
||||||
|
|
||||||
#define TARGET_CLONE_BACKWARDS
|
#define TARGET_CLONE_BACKWARDS
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_MCL_CURRENT 0x2000
|
#define TARGET_MCL_CURRENT 0x2000
|
||||||
#define TARGET_MCL_FUTURE 0x4000
|
#define TARGET_MCL_FUTURE 0x4000
|
||||||
#define TARGET_MCL_ONFAULT 0x8000
|
#define TARGET_MCL_ONFAULT 0x8000
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/* No special prctl support required. */
|
|
@ -1,18 +1,6 @@
|
||||||
#ifndef RISCV_TARGET_SIGNAL_H
|
#ifndef RISCV_TARGET_SIGNAL_H
|
||||||
#define RISCV_TARGET_SIGNAL_H
|
#define RISCV_TARGET_SIGNAL_H
|
||||||
|
|
||||||
typedef struct target_sigaltstack {
|
|
||||||
abi_ulong ss_sp;
|
|
||||||
abi_int ss_flags;
|
|
||||||
abi_ulong ss_size;
|
|
||||||
} target_stack_t;
|
|
||||||
|
|
||||||
#define TARGET_SS_ONSTACK 1
|
|
||||||
#define TARGET_SS_DISABLE 2
|
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_SIGSTKSZ 8192
|
|
||||||
|
|
||||||
#include "../generic/signal.h"
|
#include "../generic/signal.h"
|
||||||
|
|
||||||
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
|
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
|
||||||
|
|
|
@ -51,7 +51,6 @@ struct target_pt_regs {
|
||||||
#define UNAME_MINIMUM_RELEASE "4.15.0"
|
#define UNAME_MINIMUM_RELEASE "4.15.0"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_MCL_CURRENT 1
|
#define TARGET_MCL_CURRENT 1
|
||||||
#define TARGET_MCL_FUTURE 2
|
#define TARGET_MCL_FUTURE 2
|
||||||
#define TARGET_MCL_ONFAULT 4
|
#define TARGET_MCL_ONFAULT 4
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/* No special prctl support required. */
|
|
@ -1,21 +1,6 @@
|
||||||
#ifndef S390X_TARGET_SIGNAL_H
|
#ifndef S390X_TARGET_SIGNAL_H
|
||||||
#define S390X_TARGET_SIGNAL_H
|
#define S390X_TARGET_SIGNAL_H
|
||||||
|
|
||||||
typedef struct target_sigaltstack {
|
|
||||||
abi_ulong ss_sp;
|
|
||||||
abi_int ss_flags;
|
|
||||||
abi_ulong ss_size;
|
|
||||||
} target_stack_t;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* sigaltstack controls
|
|
||||||
*/
|
|
||||||
#define TARGET_SS_ONSTACK 1
|
|
||||||
#define TARGET_SS_DISABLE 2
|
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_SIGSTKSZ 8192
|
|
||||||
|
|
||||||
#include "../generic/signal.h"
|
#include "../generic/signal.h"
|
||||||
|
|
||||||
#define TARGET_ARCH_HAS_SETUP_FRAME
|
#define TARGET_ARCH_HAS_SETUP_FRAME
|
||||||
|
|
|
@ -27,7 +27,6 @@ struct target_pt_regs {
|
||||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||||
|
|
||||||
#define TARGET_CLONE_BACKWARDS2
|
#define TARGET_CLONE_BACKWARDS2
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_MCL_CURRENT 1
|
#define TARGET_MCL_CURRENT 1
|
||||||
#define TARGET_MCL_FUTURE 2
|
#define TARGET_MCL_FUTURE 2
|
||||||
#define TARGET_MCL_ONFAULT 4
|
#define TARGET_MCL_ONFAULT 4
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
#include "../generic/target_prctl_unalign.h"
|
|
@ -1,24 +1,6 @@
|
||||||
#ifndef SH4_TARGET_SIGNAL_H
|
#ifndef SH4_TARGET_SIGNAL_H
|
||||||
#define SH4_TARGET_SIGNAL_H
|
#define SH4_TARGET_SIGNAL_H
|
||||||
|
|
||||||
/* this struct defines a stack used during syscall handling */
|
|
||||||
|
|
||||||
typedef struct target_sigaltstack {
|
|
||||||
abi_ulong ss_sp;
|
|
||||||
abi_int ss_flags;
|
|
||||||
abi_ulong ss_size;
|
|
||||||
} target_stack_t;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* sigaltstack controls
|
|
||||||
*/
|
|
||||||
#define TARGET_SS_ONSTACK 1
|
|
||||||
#define TARGET_SS_DISABLE 2
|
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_SIGSTKSZ 8192
|
|
||||||
|
|
||||||
#include "../generic/signal.h"
|
#include "../generic/signal.h"
|
||||||
|
|
||||||
#define TARGET_ARCH_HAS_SETUP_FRAME
|
#define TARGET_ARCH_HAS_SETUP_FRAME
|
||||||
|
|
|
@ -15,7 +15,6 @@ struct target_pt_regs {
|
||||||
#define UNAME_MACHINE "sh4"
|
#define UNAME_MACHINE "sh4"
|
||||||
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
#define UNAME_MINIMUM_RELEASE "2.6.32"
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_MCL_CURRENT 1
|
#define TARGET_MCL_CURRENT 1
|
||||||
#define TARGET_MCL_FUTURE 2
|
#define TARGET_MCL_FUTURE 2
|
||||||
#define TARGET_MCL_ONFAULT 4
|
#define TARGET_MCL_ONFAULT 4
|
||||||
|
|
|
@ -258,7 +258,6 @@ int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(TARGET_NIOS2)
|
|
||||||
/* Just set the guest's signal mask to the specified value; the
|
/* Just set the guest's signal mask to the specified value; the
|
||||||
* caller is assumed to have called block_signals() already.
|
* caller is assumed to have called block_signals() already.
|
||||||
*/
|
*/
|
||||||
|
@ -268,7 +267,6 @@ void set_sigmask(const sigset_t *set)
|
||||||
|
|
||||||
ts->signal_mask = *set;
|
ts->signal_mask = *set;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* sigaltstack management */
|
/* sigaltstack management */
|
||||||
|
|
||||||
|
@ -406,7 +404,12 @@ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
|
||||||
case TARGET_SIGCHLD:
|
case TARGET_SIGCHLD:
|
||||||
tinfo->_sifields._sigchld._pid = info->si_pid;
|
tinfo->_sifields._sigchld._pid = info->si_pid;
|
||||||
tinfo->_sifields._sigchld._uid = info->si_uid;
|
tinfo->_sifields._sigchld._uid = info->si_uid;
|
||||||
tinfo->_sifields._sigchld._status = info->si_status;
|
if (si_code == CLD_EXITED)
|
||||||
|
tinfo->_sifields._sigchld._status = info->si_status;
|
||||||
|
else
|
||||||
|
tinfo->_sifields._sigchld._status
|
||||||
|
= host_to_target_signal(info->si_status & 0x7f)
|
||||||
|
| (info->si_status & ~0x7f);
|
||||||
tinfo->_sifields._sigchld._utime = info->si_utime;
|
tinfo->_sifields._sigchld._utime = info->si_utime;
|
||||||
tinfo->_sifields._sigchld._stime = info->si_stime;
|
tinfo->_sifields._sigchld._stime = info->si_stime;
|
||||||
si_type = QEMU_SI_CHLD;
|
si_type = QEMU_SI_CHLD;
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/* No special prctl support required. */
|
|
@ -65,7 +65,6 @@ typedef struct target_sigaltstack {
|
||||||
#define TARGET_ARCH_HAS_KA_RESTORER 1
|
#define TARGET_ARCH_HAS_KA_RESTORER 1
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 4096
|
#define TARGET_MINSIGSTKSZ 4096
|
||||||
#define TARGET_SIGSTKSZ 16384
|
|
||||||
|
|
||||||
#ifdef TARGET_ABI32
|
#ifdef TARGET_ABI32
|
||||||
#define TARGET_ARCH_HAS_SETUP_FRAME
|
#define TARGET_ARCH_HAS_SETUP_FRAME
|
||||||
|
|
|
@ -34,7 +34,6 @@ struct target_pt_regs {
|
||||||
* and copy_thread().
|
* and copy_thread().
|
||||||
*/
|
*/
|
||||||
#define TARGET_CLONE_BACKWARDS
|
#define TARGET_CLONE_BACKWARDS
|
||||||
#define TARGET_MINSIGSTKSZ 4096
|
|
||||||
#define TARGET_MCL_CURRENT 0x2000
|
#define TARGET_MCL_CURRENT 0x2000
|
||||||
#define TARGET_MCL_FUTURE 0x4000
|
#define TARGET_MCL_FUTURE 0x4000
|
||||||
#define TARGET_MCL_ONFAULT 0x8000
|
#define TARGET_MCL_ONFAULT 0x8000
|
||||||
|
|
|
@ -340,6 +340,36 @@ _syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
|
||||||
#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
|
#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
|
||||||
_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
|
_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
|
||||||
unsigned long *, user_mask_ptr);
|
unsigned long *, user_mask_ptr);
|
||||||
|
/* sched_attr is not defined in glibc */
|
||||||
|
struct sched_attr {
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t sched_policy;
|
||||||
|
uint64_t sched_flags;
|
||||||
|
int32_t sched_nice;
|
||||||
|
uint32_t sched_priority;
|
||||||
|
uint64_t sched_runtime;
|
||||||
|
uint64_t sched_deadline;
|
||||||
|
uint64_t sched_period;
|
||||||
|
uint32_t sched_util_min;
|
||||||
|
uint32_t sched_util_max;
|
||||||
|
};
|
||||||
|
#define __NR_sys_sched_getattr __NR_sched_getattr
|
||||||
|
_syscall4(int, sys_sched_getattr, pid_t, pid, struct sched_attr *, attr,
|
||||||
|
unsigned int, size, unsigned int, flags);
|
||||||
|
#define __NR_sys_sched_setattr __NR_sched_setattr
|
||||||
|
_syscall3(int, sys_sched_setattr, pid_t, pid, struct sched_attr *, attr,
|
||||||
|
unsigned int, flags);
|
||||||
|
#define __NR_sys_sched_getscheduler __NR_sched_getscheduler
|
||||||
|
_syscall1(int, sys_sched_getscheduler, pid_t, pid);
|
||||||
|
#define __NR_sys_sched_setscheduler __NR_sched_setscheduler
|
||||||
|
_syscall3(int, sys_sched_setscheduler, pid_t, pid, int, policy,
|
||||||
|
const struct sched_param *, param);
|
||||||
|
#define __NR_sys_sched_getparam __NR_sched_getparam
|
||||||
|
_syscall2(int, sys_sched_getparam, pid_t, pid,
|
||||||
|
struct sched_param *, param);
|
||||||
|
#define __NR_sys_sched_setparam __NR_sched_setparam
|
||||||
|
_syscall2(int, sys_sched_setparam, pid_t, pid,
|
||||||
|
const struct sched_param *, param);
|
||||||
#define __NR_sys_getcpu __NR_getcpu
|
#define __NR_sys_getcpu __NR_getcpu
|
||||||
_syscall3(int, sys_getcpu, unsigned *, cpu, unsigned *, node, void *, tcache);
|
_syscall3(int, sys_getcpu, unsigned *, cpu, unsigned *, node, void *, tcache);
|
||||||
_syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd,
|
_syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd,
|
||||||
|
@ -558,6 +588,24 @@ const char *target_strerror(int err)
|
||||||
return strerror(target_to_host_errno(err));
|
return strerror(target_to_host_errno(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int check_zeroed_user(abi_long addr, size_t ksize, size_t usize)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint8_t b;
|
||||||
|
if (usize <= ksize) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
for (i = ksize; i < usize; i++) {
|
||||||
|
if (get_user_u8(b, addr + i)) {
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
}
|
||||||
|
if (b != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
#define safe_syscall0(type, name) \
|
#define safe_syscall0(type, name) \
|
||||||
static type safe_##name(void) \
|
static type safe_##name(void) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -4867,7 +4915,7 @@ static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||||
* We can't fit all the extents into the fixed size buffer.
|
* We can't fit all the extents into the fixed size buffer.
|
||||||
* Allocate one that is large enough and use it instead.
|
* Allocate one that is large enough and use it instead.
|
||||||
*/
|
*/
|
||||||
host_ifconf = malloc(outbufsz);
|
host_ifconf = g_try_malloc(outbufsz);
|
||||||
if (!host_ifconf) {
|
if (!host_ifconf) {
|
||||||
return -TARGET_ENOMEM;
|
return -TARGET_ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -4915,7 +4963,7 @@ static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (free_buf) {
|
if (free_buf) {
|
||||||
free(host_ifconf);
|
g_free(host_ifconf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -6294,9 +6342,216 @@ abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif /* defined(TARGET_ABI32 */
|
#endif /* defined(TARGET_ABI32 */
|
||||||
|
|
||||||
#endif /* defined(TARGET_I386) */
|
#endif /* defined(TARGET_I386) */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These constants are generic. Supply any that are missing from the host.
|
||||||
|
*/
|
||||||
|
#ifndef PR_SET_NAME
|
||||||
|
# define PR_SET_NAME 15
|
||||||
|
# define PR_GET_NAME 16
|
||||||
|
#endif
|
||||||
|
#ifndef PR_SET_FP_MODE
|
||||||
|
# define PR_SET_FP_MODE 45
|
||||||
|
# define PR_GET_FP_MODE 46
|
||||||
|
# define PR_FP_MODE_FR (1 << 0)
|
||||||
|
# define PR_FP_MODE_FRE (1 << 1)
|
||||||
|
#endif
|
||||||
|
#ifndef PR_SVE_SET_VL
|
||||||
|
# define PR_SVE_SET_VL 50
|
||||||
|
# define PR_SVE_GET_VL 51
|
||||||
|
# define PR_SVE_VL_LEN_MASK 0xffff
|
||||||
|
# define PR_SVE_VL_INHERIT (1 << 17)
|
||||||
|
#endif
|
||||||
|
#ifndef PR_PAC_RESET_KEYS
|
||||||
|
# define PR_PAC_RESET_KEYS 54
|
||||||
|
# define PR_PAC_APIAKEY (1 << 0)
|
||||||
|
# define PR_PAC_APIBKEY (1 << 1)
|
||||||
|
# define PR_PAC_APDAKEY (1 << 2)
|
||||||
|
# define PR_PAC_APDBKEY (1 << 3)
|
||||||
|
# define PR_PAC_APGAKEY (1 << 4)
|
||||||
|
#endif
|
||||||
|
#ifndef PR_SET_TAGGED_ADDR_CTRL
|
||||||
|
# define PR_SET_TAGGED_ADDR_CTRL 55
|
||||||
|
# define PR_GET_TAGGED_ADDR_CTRL 56
|
||||||
|
# define PR_TAGGED_ADDR_ENABLE (1UL << 0)
|
||||||
|
#endif
|
||||||
|
#ifndef PR_MTE_TCF_SHIFT
|
||||||
|
# define PR_MTE_TCF_SHIFT 1
|
||||||
|
# define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT)
|
||||||
|
# define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
|
||||||
|
# define PR_MTE_TCF_ASYNC (2UL << PR_MTE_TCF_SHIFT)
|
||||||
|
# define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT)
|
||||||
|
# define PR_MTE_TAG_SHIFT 3
|
||||||
|
# define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
|
||||||
|
#endif
|
||||||
|
#ifndef PR_SET_IO_FLUSHER
|
||||||
|
# define PR_SET_IO_FLUSHER 57
|
||||||
|
# define PR_GET_IO_FLUSHER 58
|
||||||
|
#endif
|
||||||
|
#ifndef PR_SET_SYSCALL_USER_DISPATCH
|
||||||
|
# define PR_SET_SYSCALL_USER_DISPATCH 59
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "target_prctl.h"
|
||||||
|
|
||||||
|
static abi_long do_prctl_inval0(CPUArchState *env)
|
||||||
|
{
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2)
|
||||||
|
{
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef do_prctl_get_fp_mode
|
||||||
|
#define do_prctl_get_fp_mode do_prctl_inval0
|
||||||
|
#endif
|
||||||
|
#ifndef do_prctl_set_fp_mode
|
||||||
|
#define do_prctl_set_fp_mode do_prctl_inval1
|
||||||
|
#endif
|
||||||
|
#ifndef do_prctl_get_vl
|
||||||
|
#define do_prctl_get_vl do_prctl_inval0
|
||||||
|
#endif
|
||||||
|
#ifndef do_prctl_set_vl
|
||||||
|
#define do_prctl_set_vl do_prctl_inval1
|
||||||
|
#endif
|
||||||
|
#ifndef do_prctl_reset_keys
|
||||||
|
#define do_prctl_reset_keys do_prctl_inval1
|
||||||
|
#endif
|
||||||
|
#ifndef do_prctl_set_tagged_addr_ctrl
|
||||||
|
#define do_prctl_set_tagged_addr_ctrl do_prctl_inval1
|
||||||
|
#endif
|
||||||
|
#ifndef do_prctl_get_tagged_addr_ctrl
|
||||||
|
#define do_prctl_get_tagged_addr_ctrl do_prctl_inval0
|
||||||
|
#endif
|
||||||
|
#ifndef do_prctl_get_unalign
|
||||||
|
#define do_prctl_get_unalign do_prctl_inval1
|
||||||
|
#endif
|
||||||
|
#ifndef do_prctl_set_unalign
|
||||||
|
#define do_prctl_set_unalign do_prctl_inval1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
|
||||||
|
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||||
|
{
|
||||||
|
abi_long ret;
|
||||||
|
|
||||||
|
switch (option) {
|
||||||
|
case PR_GET_PDEATHSIG:
|
||||||
|
{
|
||||||
|
int deathsig;
|
||||||
|
ret = get_errno(prctl(PR_GET_PDEATHSIG, &deathsig,
|
||||||
|
arg3, arg4, arg5));
|
||||||
|
if (!is_error(ret) && arg2 && put_user_s32(deathsig, arg2)) {
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
case PR_GET_NAME:
|
||||||
|
{
|
||||||
|
void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
|
||||||
|
if (!name) {
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
}
|
||||||
|
ret = get_errno(prctl(PR_GET_NAME, (uintptr_t)name,
|
||||||
|
arg3, arg4, arg5));
|
||||||
|
unlock_user(name, arg2, 16);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
case PR_SET_NAME:
|
||||||
|
{
|
||||||
|
void *name = lock_user(VERIFY_READ, arg2, 16, 1);
|
||||||
|
if (!name) {
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
}
|
||||||
|
ret = get_errno(prctl(PR_SET_NAME, (uintptr_t)name,
|
||||||
|
arg3, arg4, arg5));
|
||||||
|
unlock_user(name, arg2, 0);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
case PR_GET_FP_MODE:
|
||||||
|
return do_prctl_get_fp_mode(env);
|
||||||
|
case PR_SET_FP_MODE:
|
||||||
|
return do_prctl_set_fp_mode(env, arg2);
|
||||||
|
case PR_SVE_GET_VL:
|
||||||
|
return do_prctl_get_vl(env);
|
||||||
|
case PR_SVE_SET_VL:
|
||||||
|
return do_prctl_set_vl(env, arg2);
|
||||||
|
case PR_PAC_RESET_KEYS:
|
||||||
|
if (arg3 || arg4 || arg5) {
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
}
|
||||||
|
return do_prctl_reset_keys(env, arg2);
|
||||||
|
case PR_SET_TAGGED_ADDR_CTRL:
|
||||||
|
if (arg3 || arg4 || arg5) {
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
}
|
||||||
|
return do_prctl_set_tagged_addr_ctrl(env, arg2);
|
||||||
|
case PR_GET_TAGGED_ADDR_CTRL:
|
||||||
|
if (arg2 || arg3 || arg4 || arg5) {
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
}
|
||||||
|
return do_prctl_get_tagged_addr_ctrl(env);
|
||||||
|
|
||||||
|
case PR_GET_UNALIGN:
|
||||||
|
return do_prctl_get_unalign(env, arg2);
|
||||||
|
case PR_SET_UNALIGN:
|
||||||
|
return do_prctl_set_unalign(env, arg2);
|
||||||
|
|
||||||
|
case PR_GET_DUMPABLE:
|
||||||
|
case PR_SET_DUMPABLE:
|
||||||
|
case PR_GET_KEEPCAPS:
|
||||||
|
case PR_SET_KEEPCAPS:
|
||||||
|
case PR_GET_TIMING:
|
||||||
|
case PR_SET_TIMING:
|
||||||
|
case PR_GET_TIMERSLACK:
|
||||||
|
case PR_SET_TIMERSLACK:
|
||||||
|
case PR_MCE_KILL:
|
||||||
|
case PR_MCE_KILL_GET:
|
||||||
|
case PR_GET_NO_NEW_PRIVS:
|
||||||
|
case PR_SET_NO_NEW_PRIVS:
|
||||||
|
case PR_GET_IO_FLUSHER:
|
||||||
|
case PR_SET_IO_FLUSHER:
|
||||||
|
/* Some prctl options have no pointer arguments and we can pass on. */
|
||||||
|
return get_errno(prctl(option, arg2, arg3, arg4, arg5));
|
||||||
|
|
||||||
|
case PR_GET_CHILD_SUBREAPER:
|
||||||
|
case PR_SET_CHILD_SUBREAPER:
|
||||||
|
case PR_GET_SPECULATION_CTRL:
|
||||||
|
case PR_SET_SPECULATION_CTRL:
|
||||||
|
case PR_GET_TID_ADDRESS:
|
||||||
|
/* TODO */
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
|
||||||
|
case PR_GET_FPEXC:
|
||||||
|
case PR_SET_FPEXC:
|
||||||
|
/* Was used for SPE on PowerPC. */
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
|
||||||
|
case PR_GET_ENDIAN:
|
||||||
|
case PR_SET_ENDIAN:
|
||||||
|
case PR_GET_FPEMU:
|
||||||
|
case PR_SET_FPEMU:
|
||||||
|
case PR_SET_MM:
|
||||||
|
case PR_GET_SECCOMP:
|
||||||
|
case PR_SET_SECCOMP:
|
||||||
|
case PR_SET_SYSCALL_USER_DISPATCH:
|
||||||
|
case PR_GET_THP_DISABLE:
|
||||||
|
case PR_SET_THP_DISABLE:
|
||||||
|
case PR_GET_TSC:
|
||||||
|
case PR_SET_TSC:
|
||||||
|
/* Disable to prevent the target disabling stuff we need. */
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
|
||||||
|
default:
|
||||||
|
qemu_log_mask(LOG_UNIMP, "Unsupported prctl: " TARGET_ABI_FMT_ld "\n",
|
||||||
|
option);
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define NEW_STACK_SIZE 0x40000
|
#define NEW_STACK_SIZE 0x40000
|
||||||
|
|
||||||
|
|
||||||
|
@ -7790,7 +8045,7 @@ static int open_self_maps(void *cpu_env, int fd)
|
||||||
(flags & PAGE_READ) ? 'r' : '-',
|
(flags & PAGE_READ) ? 'r' : '-',
|
||||||
(flags & PAGE_WRITE_ORG) ? 'w' : '-',
|
(flags & PAGE_WRITE_ORG) ? 'w' : '-',
|
||||||
(flags & PAGE_EXEC) ? 'x' : '-',
|
(flags & PAGE_EXEC) ? 'x' : '-',
|
||||||
e->is_priv ? 'p' : '-',
|
e->is_priv ? 'p' : 's',
|
||||||
(uint64_t) e->offset, e->dev, e->inode);
|
(uint64_t) e->offset, e->dev, e->inode);
|
||||||
if (path) {
|
if (path) {
|
||||||
dprintf(fd, "%*s%s\n", 73 - count, "", path);
|
dprintf(fd, "%*s%s\n", 73 - count, "", path);
|
||||||
|
@ -10550,30 +10805,32 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
||||||
return ret;
|
return ret;
|
||||||
case TARGET_NR_sched_setparam:
|
case TARGET_NR_sched_setparam:
|
||||||
{
|
{
|
||||||
struct sched_param *target_schp;
|
struct target_sched_param *target_schp;
|
||||||
struct sched_param schp;
|
struct sched_param schp;
|
||||||
|
|
||||||
if (arg2 == 0) {
|
if (arg2 == 0) {
|
||||||
return -TARGET_EINVAL;
|
return -TARGET_EINVAL;
|
||||||
}
|
}
|
||||||
if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
|
if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1)) {
|
||||||
return -TARGET_EFAULT;
|
return -TARGET_EFAULT;
|
||||||
|
}
|
||||||
schp.sched_priority = tswap32(target_schp->sched_priority);
|
schp.sched_priority = tswap32(target_schp->sched_priority);
|
||||||
unlock_user_struct(target_schp, arg2, 0);
|
unlock_user_struct(target_schp, arg2, 0);
|
||||||
return get_errno(sched_setparam(arg1, &schp));
|
return get_errno(sys_sched_setparam(arg1, &schp));
|
||||||
}
|
}
|
||||||
case TARGET_NR_sched_getparam:
|
case TARGET_NR_sched_getparam:
|
||||||
{
|
{
|
||||||
struct sched_param *target_schp;
|
struct target_sched_param *target_schp;
|
||||||
struct sched_param schp;
|
struct sched_param schp;
|
||||||
|
|
||||||
if (arg2 == 0) {
|
if (arg2 == 0) {
|
||||||
return -TARGET_EINVAL;
|
return -TARGET_EINVAL;
|
||||||
}
|
}
|
||||||
ret = get_errno(sched_getparam(arg1, &schp));
|
ret = get_errno(sys_sched_getparam(arg1, &schp));
|
||||||
if (!is_error(ret)) {
|
if (!is_error(ret)) {
|
||||||
if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
|
if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0)) {
|
||||||
return -TARGET_EFAULT;
|
return -TARGET_EFAULT;
|
||||||
|
}
|
||||||
target_schp->sched_priority = tswap32(schp.sched_priority);
|
target_schp->sched_priority = tswap32(schp.sched_priority);
|
||||||
unlock_user_struct(target_schp, arg2, 1);
|
unlock_user_struct(target_schp, arg2, 1);
|
||||||
}
|
}
|
||||||
|
@ -10581,19 +10838,106 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
||||||
return ret;
|
return ret;
|
||||||
case TARGET_NR_sched_setscheduler:
|
case TARGET_NR_sched_setscheduler:
|
||||||
{
|
{
|
||||||
struct sched_param *target_schp;
|
struct target_sched_param *target_schp;
|
||||||
struct sched_param schp;
|
struct sched_param schp;
|
||||||
if (arg3 == 0) {
|
if (arg3 == 0) {
|
||||||
return -TARGET_EINVAL;
|
return -TARGET_EINVAL;
|
||||||
}
|
}
|
||||||
if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
|
if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1)) {
|
||||||
return -TARGET_EFAULT;
|
return -TARGET_EFAULT;
|
||||||
|
}
|
||||||
schp.sched_priority = tswap32(target_schp->sched_priority);
|
schp.sched_priority = tswap32(target_schp->sched_priority);
|
||||||
unlock_user_struct(target_schp, arg3, 0);
|
unlock_user_struct(target_schp, arg3, 0);
|
||||||
return get_errno(sched_setscheduler(arg1, arg2, &schp));
|
return get_errno(sys_sched_setscheduler(arg1, arg2, &schp));
|
||||||
}
|
}
|
||||||
case TARGET_NR_sched_getscheduler:
|
case TARGET_NR_sched_getscheduler:
|
||||||
return get_errno(sched_getscheduler(arg1));
|
return get_errno(sys_sched_getscheduler(arg1));
|
||||||
|
case TARGET_NR_sched_getattr:
|
||||||
|
{
|
||||||
|
struct target_sched_attr *target_scha;
|
||||||
|
struct sched_attr scha;
|
||||||
|
if (arg2 == 0) {
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
}
|
||||||
|
if (arg3 > sizeof(scha)) {
|
||||||
|
arg3 = sizeof(scha);
|
||||||
|
}
|
||||||
|
ret = get_errno(sys_sched_getattr(arg1, &scha, arg3, arg4));
|
||||||
|
if (!is_error(ret)) {
|
||||||
|
target_scha = lock_user(VERIFY_WRITE, arg2, arg3, 0);
|
||||||
|
if (!target_scha) {
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
}
|
||||||
|
target_scha->size = tswap32(scha.size);
|
||||||
|
target_scha->sched_policy = tswap32(scha.sched_policy);
|
||||||
|
target_scha->sched_flags = tswap64(scha.sched_flags);
|
||||||
|
target_scha->sched_nice = tswap32(scha.sched_nice);
|
||||||
|
target_scha->sched_priority = tswap32(scha.sched_priority);
|
||||||
|
target_scha->sched_runtime = tswap64(scha.sched_runtime);
|
||||||
|
target_scha->sched_deadline = tswap64(scha.sched_deadline);
|
||||||
|
target_scha->sched_period = tswap64(scha.sched_period);
|
||||||
|
if (scha.size > offsetof(struct sched_attr, sched_util_min)) {
|
||||||
|
target_scha->sched_util_min = tswap32(scha.sched_util_min);
|
||||||
|
target_scha->sched_util_max = tswap32(scha.sched_util_max);
|
||||||
|
}
|
||||||
|
unlock_user(target_scha, arg2, arg3);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
case TARGET_NR_sched_setattr:
|
||||||
|
{
|
||||||
|
struct target_sched_attr *target_scha;
|
||||||
|
struct sched_attr scha;
|
||||||
|
uint32_t size;
|
||||||
|
int zeroed;
|
||||||
|
if (arg2 == 0) {
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
}
|
||||||
|
if (get_user_u32(size, arg2)) {
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
}
|
||||||
|
if (!size) {
|
||||||
|
size = offsetof(struct target_sched_attr, sched_util_min);
|
||||||
|
}
|
||||||
|
if (size < offsetof(struct target_sched_attr, sched_util_min)) {
|
||||||
|
if (put_user_u32(sizeof(struct target_sched_attr), arg2)) {
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
}
|
||||||
|
return -TARGET_E2BIG;
|
||||||
|
}
|
||||||
|
|
||||||
|
zeroed = check_zeroed_user(arg2, sizeof(struct target_sched_attr), size);
|
||||||
|
if (zeroed < 0) {
|
||||||
|
return zeroed;
|
||||||
|
} else if (zeroed == 0) {
|
||||||
|
if (put_user_u32(sizeof(struct target_sched_attr), arg2)) {
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
}
|
||||||
|
return -TARGET_E2BIG;
|
||||||
|
}
|
||||||
|
if (size > sizeof(struct target_sched_attr)) {
|
||||||
|
size = sizeof(struct target_sched_attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
target_scha = lock_user(VERIFY_READ, arg2, size, 1);
|
||||||
|
if (!target_scha) {
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
}
|
||||||
|
scha.size = size;
|
||||||
|
scha.sched_policy = tswap32(target_scha->sched_policy);
|
||||||
|
scha.sched_flags = tswap64(target_scha->sched_flags);
|
||||||
|
scha.sched_nice = tswap32(target_scha->sched_nice);
|
||||||
|
scha.sched_priority = tswap32(target_scha->sched_priority);
|
||||||
|
scha.sched_runtime = tswap64(target_scha->sched_runtime);
|
||||||
|
scha.sched_deadline = tswap64(target_scha->sched_deadline);
|
||||||
|
scha.sched_period = tswap64(target_scha->sched_period);
|
||||||
|
if (size > offsetof(struct target_sched_attr, sched_util_min)) {
|
||||||
|
scha.sched_util_min = tswap32(target_scha->sched_util_min);
|
||||||
|
scha.sched_util_max = tswap32(target_scha->sched_util_max);
|
||||||
|
}
|
||||||
|
unlock_user(target_scha, arg2, 0);
|
||||||
|
return get_errno(sys_sched_setattr(arg1, &scha, arg3));
|
||||||
|
}
|
||||||
case TARGET_NR_sched_yield:
|
case TARGET_NR_sched_yield:
|
||||||
return get_errno(sched_yield());
|
return get_errno(sched_yield());
|
||||||
case TARGET_NR_sched_get_priority_max:
|
case TARGET_NR_sched_get_priority_max:
|
||||||
|
@ -10635,290 +10979,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
||||||
return ret;
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
case TARGET_NR_prctl:
|
case TARGET_NR_prctl:
|
||||||
switch (arg1) {
|
return do_prctl(cpu_env, arg1, arg2, arg3, arg4, arg5);
|
||||||
case PR_GET_PDEATHSIG:
|
|
||||||
{
|
|
||||||
int deathsig;
|
|
||||||
ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
|
|
||||||
if (!is_error(ret) && arg2
|
|
||||||
&& put_user_s32(deathsig, arg2)) {
|
|
||||||
return -TARGET_EFAULT;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#ifdef PR_GET_NAME
|
|
||||||
case PR_GET_NAME:
|
|
||||||
{
|
|
||||||
void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
|
|
||||||
if (!name) {
|
|
||||||
return -TARGET_EFAULT;
|
|
||||||
}
|
|
||||||
ret = get_errno(prctl(arg1, (unsigned long)name,
|
|
||||||
arg3, arg4, arg5));
|
|
||||||
unlock_user(name, arg2, 16);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
case PR_SET_NAME:
|
|
||||||
{
|
|
||||||
void *name = lock_user(VERIFY_READ, arg2, 16, 1);
|
|
||||||
if (!name) {
|
|
||||||
return -TARGET_EFAULT;
|
|
||||||
}
|
|
||||||
ret = get_errno(prctl(arg1, (unsigned long)name,
|
|
||||||
arg3, arg4, arg5));
|
|
||||||
unlock_user(name, arg2, 0);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef TARGET_MIPS
|
|
||||||
case TARGET_PR_GET_FP_MODE:
|
|
||||||
{
|
|
||||||
CPUMIPSState *env = ((CPUMIPSState *)cpu_env);
|
|
||||||
ret = 0;
|
|
||||||
if (env->CP0_Status & (1 << CP0St_FR)) {
|
|
||||||
ret |= TARGET_PR_FP_MODE_FR;
|
|
||||||
}
|
|
||||||
if (env->CP0_Config5 & (1 << CP0C5_FRE)) {
|
|
||||||
ret |= TARGET_PR_FP_MODE_FRE;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
case TARGET_PR_SET_FP_MODE:
|
|
||||||
{
|
|
||||||
CPUMIPSState *env = ((CPUMIPSState *)cpu_env);
|
|
||||||
bool old_fr = env->CP0_Status & (1 << CP0St_FR);
|
|
||||||
bool old_fre = env->CP0_Config5 & (1 << CP0C5_FRE);
|
|
||||||
bool new_fr = arg2 & TARGET_PR_FP_MODE_FR;
|
|
||||||
bool new_fre = arg2 & TARGET_PR_FP_MODE_FRE;
|
|
||||||
|
|
||||||
const unsigned int known_bits = TARGET_PR_FP_MODE_FR |
|
|
||||||
TARGET_PR_FP_MODE_FRE;
|
|
||||||
|
|
||||||
/* If nothing to change, return right away, successfully. */
|
|
||||||
if (old_fr == new_fr && old_fre == new_fre) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* Check the value is valid */
|
|
||||||
if (arg2 & ~known_bits) {
|
|
||||||
return -TARGET_EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
/* Setting FRE without FR is not supported. */
|
|
||||||
if (new_fre && !new_fr) {
|
|
||||||
return -TARGET_EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
if (new_fr && !(env->active_fpu.fcr0 & (1 << FCR0_F64))) {
|
|
||||||
/* FR1 is not supported */
|
|
||||||
return -TARGET_EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
if (!new_fr && (env->active_fpu.fcr0 & (1 << FCR0_F64))
|
|
||||||
&& !(env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
|
|
||||||
/* cannot set FR=0 */
|
|
||||||
return -TARGET_EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
if (new_fre && !(env->active_fpu.fcr0 & (1 << FCR0_FREP))) {
|
|
||||||
/* Cannot set FRE=1 */
|
|
||||||
return -TARGET_EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i;
|
|
||||||
fpr_t *fpr = env->active_fpu.fpr;
|
|
||||||
for (i = 0; i < 32 ; i += 2) {
|
|
||||||
if (!old_fr && new_fr) {
|
|
||||||
fpr[i].w[!FP_ENDIAN_IDX] = fpr[i + 1].w[FP_ENDIAN_IDX];
|
|
||||||
} else if (old_fr && !new_fr) {
|
|
||||||
fpr[i + 1].w[FP_ENDIAN_IDX] = fpr[i].w[!FP_ENDIAN_IDX];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new_fr) {
|
|
||||||
env->CP0_Status |= (1 << CP0St_FR);
|
|
||||||
env->hflags |= MIPS_HFLAG_F64;
|
|
||||||
} else {
|
|
||||||
env->CP0_Status &= ~(1 << CP0St_FR);
|
|
||||||
env->hflags &= ~MIPS_HFLAG_F64;
|
|
||||||
}
|
|
||||||
if (new_fre) {
|
|
||||||
env->CP0_Config5 |= (1 << CP0C5_FRE);
|
|
||||||
if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
|
|
||||||
env->hflags |= MIPS_HFLAG_FRE;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
env->CP0_Config5 &= ~(1 << CP0C5_FRE);
|
|
||||||
env->hflags &= ~MIPS_HFLAG_FRE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* MIPS */
|
|
||||||
#ifdef TARGET_AARCH64
|
|
||||||
case TARGET_PR_SVE_SET_VL:
|
|
||||||
/*
|
|
||||||
* We cannot support either PR_SVE_SET_VL_ONEXEC or
|
|
||||||
* PR_SVE_VL_INHERIT. Note the kernel definition
|
|
||||||
* of sve_vl_valid allows for VQ=512, i.e. VL=8192,
|
|
||||||
* even though the current architectural maximum is VQ=16.
|
|
||||||
*/
|
|
||||||
ret = -TARGET_EINVAL;
|
|
||||||
if (cpu_isar_feature(aa64_sve, env_archcpu(cpu_env))
|
|
||||||
&& arg2 >= 0 && arg2 <= 512 * 16 && !(arg2 & 15)) {
|
|
||||||
CPUARMState *env = cpu_env;
|
|
||||||
ARMCPU *cpu = env_archcpu(env);
|
|
||||||
uint32_t vq, old_vq;
|
|
||||||
|
|
||||||
old_vq = (env->vfp.zcr_el[1] & 0xf) + 1;
|
|
||||||
vq = MAX(arg2 / 16, 1);
|
|
||||||
vq = MIN(vq, cpu->sve_max_vq);
|
|
||||||
|
|
||||||
if (vq < old_vq) {
|
|
||||||
aarch64_sve_narrow_vq(env, vq);
|
|
||||||
}
|
|
||||||
env->vfp.zcr_el[1] = vq - 1;
|
|
||||||
arm_rebuild_hflags(env);
|
|
||||||
ret = vq * 16;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
case TARGET_PR_SVE_GET_VL:
|
|
||||||
ret = -TARGET_EINVAL;
|
|
||||||
{
|
|
||||||
ARMCPU *cpu = env_archcpu(cpu_env);
|
|
||||||
if (cpu_isar_feature(aa64_sve, cpu)) {
|
|
||||||
ret = ((cpu->env.vfp.zcr_el[1] & 0xf) + 1) * 16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
case TARGET_PR_PAC_RESET_KEYS:
|
|
||||||
{
|
|
||||||
CPUARMState *env = cpu_env;
|
|
||||||
ARMCPU *cpu = env_archcpu(env);
|
|
||||||
|
|
||||||
if (arg3 || arg4 || arg5) {
|
|
||||||
return -TARGET_EINVAL;
|
|
||||||
}
|
|
||||||
if (cpu_isar_feature(aa64_pauth, cpu)) {
|
|
||||||
int all = (TARGET_PR_PAC_APIAKEY | TARGET_PR_PAC_APIBKEY |
|
|
||||||
TARGET_PR_PAC_APDAKEY | TARGET_PR_PAC_APDBKEY |
|
|
||||||
TARGET_PR_PAC_APGAKEY);
|
|
||||||
int ret = 0;
|
|
||||||
Error *err = NULL;
|
|
||||||
|
|
||||||
if (arg2 == 0) {
|
|
||||||
arg2 = all;
|
|
||||||
} else if (arg2 & ~all) {
|
|
||||||
return -TARGET_EINVAL;
|
|
||||||
}
|
|
||||||
if (arg2 & TARGET_PR_PAC_APIAKEY) {
|
|
||||||
ret |= qemu_guest_getrandom(&env->keys.apia,
|
|
||||||
sizeof(ARMPACKey), &err);
|
|
||||||
}
|
|
||||||
if (arg2 & TARGET_PR_PAC_APIBKEY) {
|
|
||||||
ret |= qemu_guest_getrandom(&env->keys.apib,
|
|
||||||
sizeof(ARMPACKey), &err);
|
|
||||||
}
|
|
||||||
if (arg2 & TARGET_PR_PAC_APDAKEY) {
|
|
||||||
ret |= qemu_guest_getrandom(&env->keys.apda,
|
|
||||||
sizeof(ARMPACKey), &err);
|
|
||||||
}
|
|
||||||
if (arg2 & TARGET_PR_PAC_APDBKEY) {
|
|
||||||
ret |= qemu_guest_getrandom(&env->keys.apdb,
|
|
||||||
sizeof(ARMPACKey), &err);
|
|
||||||
}
|
|
||||||
if (arg2 & TARGET_PR_PAC_APGAKEY) {
|
|
||||||
ret |= qemu_guest_getrandom(&env->keys.apga,
|
|
||||||
sizeof(ARMPACKey), &err);
|
|
||||||
}
|
|
||||||
if (ret != 0) {
|
|
||||||
/*
|
|
||||||
* Some unknown failure in the crypto. The best
|
|
||||||
* we can do is log it and fail the syscall.
|
|
||||||
* The real syscall cannot fail this way.
|
|
||||||
*/
|
|
||||||
qemu_log_mask(LOG_UNIMP,
|
|
||||||
"PR_PAC_RESET_KEYS: Crypto failure: %s",
|
|
||||||
error_get_pretty(err));
|
|
||||||
error_free(err);
|
|
||||||
return -TARGET_EIO;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -TARGET_EINVAL;
|
|
||||||
case TARGET_PR_SET_TAGGED_ADDR_CTRL:
|
|
||||||
{
|
|
||||||
abi_ulong valid_mask = TARGET_PR_TAGGED_ADDR_ENABLE;
|
|
||||||
CPUARMState *env = cpu_env;
|
|
||||||
ARMCPU *cpu = env_archcpu(env);
|
|
||||||
|
|
||||||
if (cpu_isar_feature(aa64_mte, cpu)) {
|
|
||||||
valid_mask |= TARGET_PR_MTE_TCF_MASK;
|
|
||||||
valid_mask |= TARGET_PR_MTE_TAG_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((arg2 & ~valid_mask) || arg3 || arg4 || arg5) {
|
|
||||||
return -TARGET_EINVAL;
|
|
||||||
}
|
|
||||||
env->tagged_addr_enable = arg2 & TARGET_PR_TAGGED_ADDR_ENABLE;
|
|
||||||
|
|
||||||
if (cpu_isar_feature(aa64_mte, cpu)) {
|
|
||||||
switch (arg2 & TARGET_PR_MTE_TCF_MASK) {
|
|
||||||
case TARGET_PR_MTE_TCF_NONE:
|
|
||||||
case TARGET_PR_MTE_TCF_SYNC:
|
|
||||||
case TARGET_PR_MTE_TCF_ASYNC:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Write PR_MTE_TCF to SCTLR_EL1[TCF0].
|
|
||||||
* Note that the syscall values are consistent with hw.
|
|
||||||
*/
|
|
||||||
env->cp15.sctlr_el[1] =
|
|
||||||
deposit64(env->cp15.sctlr_el[1], 38, 2,
|
|
||||||
arg2 >> TARGET_PR_MTE_TCF_SHIFT);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Write PR_MTE_TAG to GCR_EL1[Exclude].
|
|
||||||
* Note that the syscall uses an include mask,
|
|
||||||
* and hardware uses an exclude mask -- invert.
|
|
||||||
*/
|
|
||||||
env->cp15.gcr_el1 =
|
|
||||||
deposit64(env->cp15.gcr_el1, 0, 16,
|
|
||||||
~arg2 >> TARGET_PR_MTE_TAG_SHIFT);
|
|
||||||
arm_rebuild_hflags(env);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
case TARGET_PR_GET_TAGGED_ADDR_CTRL:
|
|
||||||
{
|
|
||||||
abi_long ret = 0;
|
|
||||||
CPUARMState *env = cpu_env;
|
|
||||||
ARMCPU *cpu = env_archcpu(env);
|
|
||||||
|
|
||||||
if (arg2 || arg3 || arg4 || arg5) {
|
|
||||||
return -TARGET_EINVAL;
|
|
||||||
}
|
|
||||||
if (env->tagged_addr_enable) {
|
|
||||||
ret |= TARGET_PR_TAGGED_ADDR_ENABLE;
|
|
||||||
}
|
|
||||||
if (cpu_isar_feature(aa64_mte, cpu)) {
|
|
||||||
/* See above. */
|
|
||||||
ret |= (extract64(env->cp15.sctlr_el[1], 38, 2)
|
|
||||||
<< TARGET_PR_MTE_TCF_SHIFT);
|
|
||||||
ret = deposit64(ret, TARGET_PR_MTE_TAG_SHIFT, 16,
|
|
||||||
~env->cp15.gcr_el1);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif /* AARCH64 */
|
|
||||||
case PR_GET_SECCOMP:
|
|
||||||
case PR_SET_SECCOMP:
|
|
||||||
/* Disable seccomp to prevent the target disabling syscalls we
|
|
||||||
* need. */
|
|
||||||
return -TARGET_EINVAL;
|
|
||||||
default:
|
|
||||||
/* Most prctl options have no pointer arguments */
|
|
||||||
return get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
#ifdef TARGET_NR_arch_prctl
|
#ifdef TARGET_NR_arch_prctl
|
||||||
case TARGET_NR_arch_prctl:
|
case TARGET_NR_arch_prctl:
|
||||||
|
|
|
@ -2133,7 +2133,8 @@ struct target_stat64 {
|
||||||
abi_ulong __unused5;
|
abi_ulong __unused5;
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif defined(TARGET_OPENRISC) || defined(TARGET_NIOS2) || defined(TARGET_RISCV)
|
#elif defined(TARGET_OPENRISC) || defined(TARGET_NIOS2) \
|
||||||
|
|| defined(TARGET_RISCV) || defined(TARGET_HEXAGON)
|
||||||
|
|
||||||
/* These are the asm-generic versions of the stat and stat64 structures */
|
/* These are the asm-generic versions of the stat and stat64 structures */
|
||||||
|
|
||||||
|
@ -2244,31 +2245,6 @@ struct target_stat64 {
|
||||||
uint64_t st_ino;
|
uint64_t st_ino;
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif defined(TARGET_HEXAGON)
|
|
||||||
|
|
||||||
struct target_stat {
|
|
||||||
unsigned long long st_dev;
|
|
||||||
unsigned long long st_ino;
|
|
||||||
unsigned int st_mode;
|
|
||||||
unsigned int st_nlink;
|
|
||||||
unsigned int st_uid;
|
|
||||||
unsigned int st_gid;
|
|
||||||
unsigned long long st_rdev;
|
|
||||||
target_ulong __pad1;
|
|
||||||
long long st_size;
|
|
||||||
target_long st_blksize;
|
|
||||||
int __pad2;
|
|
||||||
long long st_blocks;
|
|
||||||
|
|
||||||
target_long target_st_atime;
|
|
||||||
target_long target_st_atime_nsec;
|
|
||||||
target_long target_st_mtime;
|
|
||||||
target_long target_st_mtime_nsec;
|
|
||||||
target_long target_st_ctime;
|
|
||||||
target_long target_st_ctime_nsec;
|
|
||||||
int __unused[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error unsupported CPU
|
#error unsupported CPU
|
||||||
#endif
|
#endif
|
||||||
|
@ -2914,4 +2890,22 @@ struct target_statx {
|
||||||
/* 0x100 */
|
/* 0x100 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* from kernel's include/linux/sched/types.h */
|
||||||
|
struct target_sched_attr {
|
||||||
|
abi_uint size;
|
||||||
|
abi_uint sched_policy;
|
||||||
|
abi_ullong sched_flags;
|
||||||
|
abi_int sched_nice;
|
||||||
|
abi_uint sched_priority;
|
||||||
|
abi_ullong sched_runtime;
|
||||||
|
abi_ullong sched_deadline;
|
||||||
|
abi_ullong sched_period;
|
||||||
|
abi_uint sched_util_min;
|
||||||
|
abi_uint sched_util_max;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct target_sched_param {
|
||||||
|
abi_int sched_priority;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -64,7 +64,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||||
abi_long arg5, abi_long arg6, abi_long arg7,
|
abi_long arg5, abi_long arg6, abi_long arg7,
|
||||||
abi_long arg8);
|
abi_long arg8);
|
||||||
extern __thread CPUState *thread_cpu;
|
extern __thread CPUState *thread_cpu;
|
||||||
void cpu_loop(CPUArchState *env);
|
void QEMU_NORETURN cpu_loop(CPUArchState *env);
|
||||||
const char *target_strerror(int err);
|
const char *target_strerror(int err);
|
||||||
int get_osversion(void);
|
int get_osversion(void);
|
||||||
void init_qemu_uname_release(void);
|
void init_qemu_uname_release(void);
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/* No special prctl support required. */
|
|
@ -1,24 +1,6 @@
|
||||||
#ifndef X86_64_TARGET_SIGNAL_H
|
#ifndef X86_64_TARGET_SIGNAL_H
|
||||||
#define X86_64_TARGET_SIGNAL_H
|
#define X86_64_TARGET_SIGNAL_H
|
||||||
|
|
||||||
/* this struct defines a stack used during syscall handling */
|
|
||||||
|
|
||||||
typedef struct target_sigaltstack {
|
|
||||||
abi_ulong ss_sp;
|
|
||||||
abi_int ss_flags;
|
|
||||||
abi_ulong ss_size;
|
|
||||||
} target_stack_t;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* sigaltstack controls
|
|
||||||
*/
|
|
||||||
#define TARGET_SS_ONSTACK 1
|
|
||||||
#define TARGET_SS_DISABLE 2
|
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_SIGSTKSZ 8192
|
|
||||||
|
|
||||||
#include "../generic/signal.h"
|
#include "../generic/signal.h"
|
||||||
|
|
||||||
/* For x86_64, use of SA_RESTORER is mandatory. */
|
/* For x86_64, use of SA_RESTORER is mandatory. */
|
||||||
|
|
|
@ -100,7 +100,6 @@ struct target_msqid64_ds {
|
||||||
#define TARGET_ARCH_SET_FS 0x1002
|
#define TARGET_ARCH_SET_FS 0x1002
|
||||||
#define TARGET_ARCH_GET_FS 0x1003
|
#define TARGET_ARCH_GET_FS 0x1003
|
||||||
#define TARGET_ARCH_GET_GS 0x1004
|
#define TARGET_ARCH_GET_GS 0x1004
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_MCL_CURRENT 1
|
#define TARGET_MCL_CURRENT 1
|
||||||
#define TARGET_MCL_FUTURE 2
|
#define TARGET_MCL_FUTURE 2
|
||||||
#define TARGET_MCL_ONFAULT 4
|
#define TARGET_MCL_ONFAULT 4
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/* No special prctl support required. */
|
|
@ -1,23 +1,6 @@
|
||||||
#ifndef XTENSA_TARGET_SIGNAL_H
|
#ifndef XTENSA_TARGET_SIGNAL_H
|
||||||
#define XTENSA_TARGET_SIGNAL_H
|
#define XTENSA_TARGET_SIGNAL_H
|
||||||
|
|
||||||
/* this struct defines a stack used during syscall handling */
|
|
||||||
|
|
||||||
typedef struct target_sigaltstack {
|
|
||||||
abi_ulong ss_sp;
|
|
||||||
abi_int ss_flags;
|
|
||||||
abi_ulong ss_size;
|
|
||||||
} target_stack_t;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* sigaltstack controls
|
|
||||||
*/
|
|
||||||
#define TARGET_SS_ONSTACK 1
|
|
||||||
#define TARGET_SS_DISABLE 2
|
|
||||||
|
|
||||||
#define TARGET_MINSIGSTKSZ 2048
|
|
||||||
#define TARGET_SIGSTKSZ 8192
|
|
||||||
|
|
||||||
#include "../generic/signal.h"
|
#include "../generic/signal.h"
|
||||||
|
|
||||||
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
|
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
|
||||||
|
|
|
@ -340,7 +340,9 @@ PERSISTENT=no
|
||||||
PRESERVE_ARG0=no
|
PRESERVE_ARG0=no
|
||||||
QEMU_SUFFIX=""
|
QEMU_SUFFIX=""
|
||||||
|
|
||||||
options=$(getopt -o ds:Q:S:e:hc:p:g: -l debian,systemd:,qemu-path:,qemu-suffix:,exportdir:,help,credential:,persistent:,preserve-argv0: -- "$@")
|
_longopts="debian,systemd:,qemu-path:,qemu-suffix:,exportdir:,help,credential:,\
|
||||||
|
persistent:,preserve-argv0:"
|
||||||
|
options=$(getopt -o ds:Q:S:e:hc:p:g:F: -l ${_longopts} -- "$@")
|
||||||
eval set -- "$options"
|
eval set -- "$options"
|
||||||
|
|
||||||
while true ; do
|
while true ; do
|
||||||
|
|
|
@ -383,6 +383,8 @@ enum {
|
||||||
#define ENV_FLAG_TB_MASK \
|
#define ENV_FLAG_TB_MASK \
|
||||||
(ENV_FLAG_PAL_MODE | ENV_FLAG_PS_USER | ENV_FLAG_FEN)
|
(ENV_FLAG_PAL_MODE | ENV_FLAG_PS_USER | ENV_FLAG_FEN)
|
||||||
|
|
||||||
|
#define TB_FLAG_UNALIGN (1u << 1)
|
||||||
|
|
||||||
static inline int cpu_mmu_index(CPUAlphaState *env, bool ifetch)
|
static inline int cpu_mmu_index(CPUAlphaState *env, bool ifetch)
|
||||||
{
|
{
|
||||||
int ret = env->flags & ENV_FLAG_PS_USER ? MMU_USER_IDX : MMU_KERNEL_IDX;
|
int ret = env->flags & ENV_FLAG_PS_USER ? MMU_USER_IDX : MMU_KERNEL_IDX;
|
||||||
|
@ -470,6 +472,9 @@ static inline void cpu_get_tb_cpu_state(CPUAlphaState *env, target_ulong *pc,
|
||||||
*pc = env->pc;
|
*pc = env->pc;
|
||||||
*cs_base = 0;
|
*cs_base = 0;
|
||||||
*pflags = env->flags & ENV_FLAG_TB_MASK;
|
*pflags = env->flags & ENV_FLAG_TB_MASK;
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
*pflags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
|
|
@ -45,7 +45,9 @@ typedef struct DisasContext DisasContext;
|
||||||
struct DisasContext {
|
struct DisasContext {
|
||||||
DisasContextBase base;
|
DisasContextBase base;
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
MemOp unalign;
|
||||||
|
#else
|
||||||
uint64_t palbr;
|
uint64_t palbr;
|
||||||
#endif
|
#endif
|
||||||
uint32_t tbflags;
|
uint32_t tbflags;
|
||||||
|
@ -68,6 +70,12 @@ struct DisasContext {
|
||||||
TCGv sink;
|
TCGv sink;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
#define UNALIGN(C) (C)->unalign
|
||||||
|
#else
|
||||||
|
#define UNALIGN(C) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Target-specific return values from translate_one, indicating the
|
/* Target-specific return values from translate_one, indicating the
|
||||||
state of the TB. Note that DISAS_NEXT indicates that we are not
|
state of the TB. Note that DISAS_NEXT indicates that we are not
|
||||||
exiting the TB. */
|
exiting the TB. */
|
||||||
|
@ -270,7 +278,7 @@ static inline DisasJumpType gen_invalid(DisasContext *ctx)
|
||||||
static void gen_ldf(DisasContext *ctx, TCGv dest, TCGv addr)
|
static void gen_ldf(DisasContext *ctx, TCGv dest, TCGv addr)
|
||||||
{
|
{
|
||||||
TCGv_i32 tmp32 = tcg_temp_new_i32();
|
TCGv_i32 tmp32 = tcg_temp_new_i32();
|
||||||
tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL);
|
tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
|
||||||
gen_helper_memory_to_f(dest, tmp32);
|
gen_helper_memory_to_f(dest, tmp32);
|
||||||
tcg_temp_free_i32(tmp32);
|
tcg_temp_free_i32(tmp32);
|
||||||
}
|
}
|
||||||
|
@ -278,7 +286,7 @@ static void gen_ldf(DisasContext *ctx, TCGv dest, TCGv addr)
|
||||||
static void gen_ldg(DisasContext *ctx, TCGv dest, TCGv addr)
|
static void gen_ldg(DisasContext *ctx, TCGv dest, TCGv addr)
|
||||||
{
|
{
|
||||||
TCGv tmp = tcg_temp_new();
|
TCGv tmp = tcg_temp_new();
|
||||||
tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_LEQ);
|
tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_LEQ | UNALIGN(ctx));
|
||||||
gen_helper_memory_to_g(dest, tmp);
|
gen_helper_memory_to_g(dest, tmp);
|
||||||
tcg_temp_free(tmp);
|
tcg_temp_free(tmp);
|
||||||
}
|
}
|
||||||
|
@ -286,14 +294,14 @@ static void gen_ldg(DisasContext *ctx, TCGv dest, TCGv addr)
|
||||||
static void gen_lds(DisasContext *ctx, TCGv dest, TCGv addr)
|
static void gen_lds(DisasContext *ctx, TCGv dest, TCGv addr)
|
||||||
{
|
{
|
||||||
TCGv_i32 tmp32 = tcg_temp_new_i32();
|
TCGv_i32 tmp32 = tcg_temp_new_i32();
|
||||||
tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL);
|
tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
|
||||||
gen_helper_memory_to_s(dest, tmp32);
|
gen_helper_memory_to_s(dest, tmp32);
|
||||||
tcg_temp_free_i32(tmp32);
|
tcg_temp_free_i32(tmp32);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_ldt(DisasContext *ctx, TCGv dest, TCGv addr)
|
static void gen_ldt(DisasContext *ctx, TCGv dest, TCGv addr)
|
||||||
{
|
{
|
||||||
tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_LEQ);
|
tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_LEQ | UNALIGN(ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_load_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
|
static void gen_load_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
|
||||||
|
@ -324,6 +332,8 @@ static void gen_load_int(DisasContext *ctx, int ra, int rb, int32_t disp16,
|
||||||
tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
|
tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
|
||||||
if (clear) {
|
if (clear) {
|
||||||
tcg_gen_andi_i64(addr, addr, ~0x7);
|
tcg_gen_andi_i64(addr, addr, ~0x7);
|
||||||
|
} else if (!locked) {
|
||||||
|
op |= UNALIGN(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = ctx->ir[ra];
|
dest = ctx->ir[ra];
|
||||||
|
@ -340,7 +350,7 @@ static void gen_stf(DisasContext *ctx, TCGv src, TCGv addr)
|
||||||
{
|
{
|
||||||
TCGv_i32 tmp32 = tcg_temp_new_i32();
|
TCGv_i32 tmp32 = tcg_temp_new_i32();
|
||||||
gen_helper_f_to_memory(tmp32, addr);
|
gen_helper_f_to_memory(tmp32, addr);
|
||||||
tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL);
|
tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
|
||||||
tcg_temp_free_i32(tmp32);
|
tcg_temp_free_i32(tmp32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +358,7 @@ static void gen_stg(DisasContext *ctx, TCGv src, TCGv addr)
|
||||||
{
|
{
|
||||||
TCGv tmp = tcg_temp_new();
|
TCGv tmp = tcg_temp_new();
|
||||||
gen_helper_g_to_memory(tmp, src);
|
gen_helper_g_to_memory(tmp, src);
|
||||||
tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_LEQ);
|
tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_LEQ | UNALIGN(ctx));
|
||||||
tcg_temp_free(tmp);
|
tcg_temp_free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,13 +366,13 @@ static void gen_sts(DisasContext *ctx, TCGv src, TCGv addr)
|
||||||
{
|
{
|
||||||
TCGv_i32 tmp32 = tcg_temp_new_i32();
|
TCGv_i32 tmp32 = tcg_temp_new_i32();
|
||||||
gen_helper_s_to_memory(tmp32, src);
|
gen_helper_s_to_memory(tmp32, src);
|
||||||
tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL);
|
tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
|
||||||
tcg_temp_free_i32(tmp32);
|
tcg_temp_free_i32(tmp32);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_stt(DisasContext *ctx, TCGv src, TCGv addr)
|
static void gen_stt(DisasContext *ctx, TCGv src, TCGv addr)
|
||||||
{
|
{
|
||||||
tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, MO_LEQ);
|
tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, MO_LEQ | UNALIGN(ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_store_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
|
static void gen_store_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
|
||||||
|
@ -383,6 +393,8 @@ static void gen_store_int(DisasContext *ctx, int ra, int rb, int32_t disp16,
|
||||||
tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
|
tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
|
||||||
if (clear) {
|
if (clear) {
|
||||||
tcg_gen_andi_i64(addr, addr, ~0x7);
|
tcg_gen_andi_i64(addr, addr, ~0x7);
|
||||||
|
} else {
|
||||||
|
op |= UNALIGN(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
src = load_gpr(ctx, ra);
|
src = load_gpr(ctx, ra);
|
||||||
|
@ -2942,6 +2954,7 @@ static void alpha_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
|
||||||
|
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
ctx->ir = cpu_std_ir;
|
ctx->ir = cpu_std_ir;
|
||||||
|
ctx->unalign = (ctx->tbflags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN);
|
||||||
#else
|
#else
|
||||||
ctx->palbr = env->palbr;
|
ctx->palbr = env->palbr;
|
||||||
ctx->ir = (ctx->tbflags & ENV_FLAG_PAL_MODE ? cpu_pal_ir : cpu_std_ir);
|
ctx->ir = (ctx->tbflags & ENV_FLAG_PAL_MODE ? cpu_pal_ir : cpu_std_ir);
|
||||||
|
|
|
@ -259,12 +259,14 @@ static inline target_ulong hppa_form_gva(CPUHPPAState *env, uint64_t spc,
|
||||||
return hppa_form_gva_psw(env->psw, spc, off);
|
return hppa_form_gva_psw(env->psw, spc, off);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Since PSW_{I,CB} will never need to be in tb->flags, reuse them.
|
/*
|
||||||
|
* Since PSW_{I,CB} will never need to be in tb->flags, reuse them.
|
||||||
* TB_FLAG_SR_SAME indicates that SR4 through SR7 all contain the
|
* TB_FLAG_SR_SAME indicates that SR4 through SR7 all contain the
|
||||||
* same value.
|
* same value.
|
||||||
*/
|
*/
|
||||||
#define TB_FLAG_SR_SAME PSW_I
|
#define TB_FLAG_SR_SAME PSW_I
|
||||||
#define TB_FLAG_PRIV_SHIFT 8
|
#define TB_FLAG_PRIV_SHIFT 8
|
||||||
|
#define TB_FLAG_UNALIGN 0x400
|
||||||
|
|
||||||
static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, target_ulong *pc,
|
static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, target_ulong *pc,
|
||||||
target_ulong *cs_base,
|
target_ulong *cs_base,
|
||||||
|
@ -279,6 +281,7 @@ static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, target_ulong *pc,
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
*pc = env->iaoq_f & -4;
|
*pc = env->iaoq_f & -4;
|
||||||
*cs_base = env->iaoq_b & -4;
|
*cs_base = env->iaoq_b & -4;
|
||||||
|
flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus;
|
||||||
#else
|
#else
|
||||||
/* ??? E, T, H, L, B, P bits need to be here, when implemented. */
|
/* ??? E, T, H, L, B, P bits need to be here, when implemented. */
|
||||||
flags |= env->psw & (PSW_W | PSW_C | PSW_D);
|
flags |= env->psw & (PSW_W | PSW_C | PSW_D);
|
||||||
|
|
|
@ -274,8 +274,18 @@ typedef struct DisasContext {
|
||||||
int mmu_idx;
|
int mmu_idx;
|
||||||
int privilege;
|
int privilege;
|
||||||
bool psw_n_nonzero;
|
bool psw_n_nonzero;
|
||||||
|
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
MemOp unalign;
|
||||||
|
#endif
|
||||||
} DisasContext;
|
} DisasContext;
|
||||||
|
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
#define UNALIGN(C) (C)->unalign
|
||||||
|
#else
|
||||||
|
#define UNALIGN(C) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Note that ssm/rsm instructions number PSW_W and PSW_E differently. */
|
/* Note that ssm/rsm instructions number PSW_W and PSW_E differently. */
|
||||||
static int expand_sm_imm(DisasContext *ctx, int val)
|
static int expand_sm_imm(DisasContext *ctx, int val)
|
||||||
{
|
{
|
||||||
|
@ -1475,7 +1485,7 @@ static void do_load_32(DisasContext *ctx, TCGv_i32 dest, unsigned rb,
|
||||||
|
|
||||||
form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
|
form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
|
||||||
ctx->mmu_idx == MMU_PHYS_IDX);
|
ctx->mmu_idx == MMU_PHYS_IDX);
|
||||||
tcg_gen_qemu_ld_reg(dest, addr, ctx->mmu_idx, mop);
|
tcg_gen_qemu_ld_reg(dest, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
|
||||||
if (modify) {
|
if (modify) {
|
||||||
save_gpr(ctx, rb, ofs);
|
save_gpr(ctx, rb, ofs);
|
||||||
}
|
}
|
||||||
|
@ -1493,7 +1503,7 @@ static void do_load_64(DisasContext *ctx, TCGv_i64 dest, unsigned rb,
|
||||||
|
|
||||||
form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
|
form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
|
||||||
ctx->mmu_idx == MMU_PHYS_IDX);
|
ctx->mmu_idx == MMU_PHYS_IDX);
|
||||||
tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop);
|
tcg_gen_qemu_ld_i64(dest, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
|
||||||
if (modify) {
|
if (modify) {
|
||||||
save_gpr(ctx, rb, ofs);
|
save_gpr(ctx, rb, ofs);
|
||||||
}
|
}
|
||||||
|
@ -1511,7 +1521,7 @@ static void do_store_32(DisasContext *ctx, TCGv_i32 src, unsigned rb,
|
||||||
|
|
||||||
form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
|
form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
|
||||||
ctx->mmu_idx == MMU_PHYS_IDX);
|
ctx->mmu_idx == MMU_PHYS_IDX);
|
||||||
tcg_gen_qemu_st_i32(src, addr, ctx->mmu_idx, mop);
|
tcg_gen_qemu_st_i32(src, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
|
||||||
if (modify) {
|
if (modify) {
|
||||||
save_gpr(ctx, rb, ofs);
|
save_gpr(ctx, rb, ofs);
|
||||||
}
|
}
|
||||||
|
@ -1529,7 +1539,7 @@ static void do_store_64(DisasContext *ctx, TCGv_i64 src, unsigned rb,
|
||||||
|
|
||||||
form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
|
form_gva(ctx, &addr, &ofs, rb, rx, scale, disp, sp, modify,
|
||||||
ctx->mmu_idx == MMU_PHYS_IDX);
|
ctx->mmu_idx == MMU_PHYS_IDX);
|
||||||
tcg_gen_qemu_st_i64(src, addr, ctx->mmu_idx, mop);
|
tcg_gen_qemu_st_i64(src, addr, ctx->mmu_idx, mop | UNALIGN(ctx));
|
||||||
if (modify) {
|
if (modify) {
|
||||||
save_gpr(ctx, rb, ofs);
|
save_gpr(ctx, rb, ofs);
|
||||||
}
|
}
|
||||||
|
@ -4107,6 +4117,7 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
|
||||||
ctx->mmu_idx = MMU_USER_IDX;
|
ctx->mmu_idx = MMU_USER_IDX;
|
||||||
ctx->iaoq_f = ctx->base.pc_first | MMU_USER_IDX;
|
ctx->iaoq_f = ctx->base.pc_first | MMU_USER_IDX;
|
||||||
ctx->iaoq_b = ctx->base.tb->cs_base | MMU_USER_IDX;
|
ctx->iaoq_b = ctx->base.tb->cs_base | MMU_USER_IDX;
|
||||||
|
ctx->unalign = (ctx->tb_flags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN);
|
||||||
#else
|
#else
|
||||||
ctx->privilege = (ctx->tb_flags >> TB_FLAG_PRIV_SHIFT) & 3;
|
ctx->privilege = (ctx->tb_flags >> TB_FLAG_PRIV_SHIFT) & 3;
|
||||||
ctx->mmu_idx = (ctx->tb_flags & PSW_D ? ctx->privilege : MMU_PHYS_IDX);
|
ctx->mmu_idx = (ctx->tb_flags & PSW_D ? ctx->privilege : MMU_PHYS_IDX);
|
||||||
|
|
|
@ -160,9 +160,9 @@ struct CPUNios2State {
|
||||||
|
|
||||||
#if !defined(CONFIG_USER_ONLY)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
Nios2MMU mmu;
|
Nios2MMU mmu;
|
||||||
|
|
||||||
uint32_t irq_pending;
|
uint32_t irq_pending;
|
||||||
#endif
|
#endif
|
||||||
|
int error_code;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -636,6 +636,21 @@ static void divu(DisasContext *dc, uint32_t code, uint32_t flags)
|
||||||
tcg_temp_free(t0);
|
tcg_temp_free(t0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void trap(DisasContext *dc, uint32_t code, uint32_t flags)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
/*
|
||||||
|
* The imm5 field is not stored anywhere on real hw; the kernel
|
||||||
|
* has to load the insn and extract the field. But we can make
|
||||||
|
* things easier for cpu_loop if we pop this into env->error_code.
|
||||||
|
*/
|
||||||
|
R_TYPE(instr, code);
|
||||||
|
tcg_gen_st_i32(tcg_constant_i32(instr.imm5), cpu_env,
|
||||||
|
offsetof(CPUNios2State, error_code));
|
||||||
|
#endif
|
||||||
|
t_gen_helper_raise_exception(dc, EXCP_TRAP);
|
||||||
|
}
|
||||||
|
|
||||||
static const Nios2Instruction r_type_instructions[] = {
|
static const Nios2Instruction r_type_instructions[] = {
|
||||||
INSTRUCTION_ILLEGAL(),
|
INSTRUCTION_ILLEGAL(),
|
||||||
INSTRUCTION(eret), /* eret */
|
INSTRUCTION(eret), /* eret */
|
||||||
|
@ -682,7 +697,7 @@ static const Nios2Instruction r_type_instructions[] = {
|
||||||
INSTRUCTION_ILLEGAL(),
|
INSTRUCTION_ILLEGAL(),
|
||||||
INSTRUCTION_ILLEGAL(),
|
INSTRUCTION_ILLEGAL(),
|
||||||
INSTRUCTION_ILLEGAL(),
|
INSTRUCTION_ILLEGAL(),
|
||||||
INSTRUCTION_FLG(gen_excp, EXCP_TRAP), /* trap */
|
INSTRUCTION(trap), /* trap */
|
||||||
INSTRUCTION(wrctl), /* wrctl */
|
INSTRUCTION(wrctl), /* wrctl */
|
||||||
INSTRUCTION_ILLEGAL(),
|
INSTRUCTION_ILLEGAL(),
|
||||||
INSTRUCTION_FLG(gen_cmpxx, TCG_COND_LTU), /* cmpltu */
|
INSTRUCTION_FLG(gen_cmpxx, TCG_COND_LTU), /* cmpltu */
|
||||||
|
@ -780,15 +795,6 @@ static void nios2_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
|
||||||
dc->base.pc_next = pc + 4;
|
dc->base.pc_next = pc + 4;
|
||||||
|
|
||||||
/* Decode an instruction */
|
/* Decode an instruction */
|
||||||
|
|
||||||
#if defined(CONFIG_USER_ONLY)
|
|
||||||
/* FIXME: Is this needed ? */
|
|
||||||
if (pc >= 0x1000 && pc < 0x2000) {
|
|
||||||
t_gen_helper_raise_exception(dc, 0xaa);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
code = cpu_ldl_code(env, pc);
|
code = cpu_ldl_code(env, pc);
|
||||||
op = get_opcode(code);
|
op = get_opcode(code);
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,7 @@
|
||||||
#define DELAY_SLOT_RTE (1 << 2)
|
#define DELAY_SLOT_RTE (1 << 2)
|
||||||
|
|
||||||
#define TB_FLAG_PENDING_MOVCA (1 << 3)
|
#define TB_FLAG_PENDING_MOVCA (1 << 3)
|
||||||
|
#define TB_FLAG_UNALIGN (1 << 4)
|
||||||
|
|
||||||
#define GUSA_SHIFT 4
|
#define GUSA_SHIFT 4
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
@ -373,6 +374,9 @@ static inline void cpu_get_tb_cpu_state(CPUSH4State *env, target_ulong *pc,
|
||||||
| (env->sr & ((1u << SR_MD) | (1u << SR_RB))) /* Bits 29-30 */
|
| (env->sr & ((1u << SR_MD) | (1u << SR_RB))) /* Bits 29-30 */
|
||||||
| (env->sr & (1u << SR_FD)) /* Bit 15 */
|
| (env->sr & (1u << SR_FD)) /* Bit 15 */
|
||||||
| (env->movcal_backup ? TB_FLAG_PENDING_MOVCA : 0); /* Bit 3 */
|
| (env->movcal_backup ? TB_FLAG_PENDING_MOVCA : 0); /* Bit 3 */
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
*flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SH4_CPU_H */
|
#endif /* SH4_CPU_H */
|
||||||
|
|
|
@ -50,8 +50,10 @@ typedef struct DisasContext {
|
||||||
|
|
||||||
#if defined(CONFIG_USER_ONLY)
|
#if defined(CONFIG_USER_ONLY)
|
||||||
#define IS_USER(ctx) 1
|
#define IS_USER(ctx) 1
|
||||||
|
#define UNALIGN(C) (ctx->tbflags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN)
|
||||||
#else
|
#else
|
||||||
#define IS_USER(ctx) (!(ctx->tbflags & (1u << SR_MD)))
|
#define IS_USER(ctx) (!(ctx->tbflags & (1u << SR_MD)))
|
||||||
|
#define UNALIGN(C) 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Target-specific values for ctx->base.is_jmp. */
|
/* Target-specific values for ctx->base.is_jmp. */
|
||||||
|
@ -495,7 +497,8 @@ static void _decode_opc(DisasContext * ctx)
|
||||||
{
|
{
|
||||||
TCGv addr = tcg_temp_new();
|
TCGv addr = tcg_temp_new();
|
||||||
tcg_gen_addi_i32(addr, REG(B11_8), B3_0 * 4);
|
tcg_gen_addi_i32(addr, REG(B11_8), B3_0 * 4);
|
||||||
tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL);
|
tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx,
|
||||||
|
MO_TEUL | UNALIGN(ctx));
|
||||||
tcg_temp_free(addr);
|
tcg_temp_free(addr);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -503,7 +506,8 @@ static void _decode_opc(DisasContext * ctx)
|
||||||
{
|
{
|
||||||
TCGv addr = tcg_temp_new();
|
TCGv addr = tcg_temp_new();
|
||||||
tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 4);
|
tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 4);
|
||||||
tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL);
|
tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx,
|
||||||
|
MO_TESL | UNALIGN(ctx));
|
||||||
tcg_temp_free(addr);
|
tcg_temp_free(addr);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -558,19 +562,23 @@ static void _decode_opc(DisasContext * ctx)
|
||||||
tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_UB);
|
tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_UB);
|
||||||
return;
|
return;
|
||||||
case 0x2001: /* mov.w Rm,@Rn */
|
case 0x2001: /* mov.w Rm,@Rn */
|
||||||
tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUW);
|
tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx,
|
||||||
|
MO_TEUW | UNALIGN(ctx));
|
||||||
return;
|
return;
|
||||||
case 0x2002: /* mov.l Rm,@Rn */
|
case 0x2002: /* mov.l Rm,@Rn */
|
||||||
tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx, MO_TEUL);
|
tcg_gen_qemu_st_i32(REG(B7_4), REG(B11_8), ctx->memidx,
|
||||||
|
MO_TEUL | UNALIGN(ctx));
|
||||||
return;
|
return;
|
||||||
case 0x6000: /* mov.b @Rm,Rn */
|
case 0x6000: /* mov.b @Rm,Rn */
|
||||||
tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB);
|
tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_SB);
|
||||||
return;
|
return;
|
||||||
case 0x6001: /* mov.w @Rm,Rn */
|
case 0x6001: /* mov.w @Rm,Rn */
|
||||||
tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW);
|
tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx,
|
||||||
|
MO_TESW | UNALIGN(ctx));
|
||||||
return;
|
return;
|
||||||
case 0x6002: /* mov.l @Rm,Rn */
|
case 0x6002: /* mov.l @Rm,Rn */
|
||||||
tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL);
|
tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx,
|
||||||
|
MO_TESL | UNALIGN(ctx));
|
||||||
return;
|
return;
|
||||||
case 0x2004: /* mov.b Rm,@-Rn */
|
case 0x2004: /* mov.b Rm,@-Rn */
|
||||||
{
|
{
|
||||||
|
@ -586,7 +594,8 @@ static void _decode_opc(DisasContext * ctx)
|
||||||
{
|
{
|
||||||
TCGv addr = tcg_temp_new();
|
TCGv addr = tcg_temp_new();
|
||||||
tcg_gen_subi_i32(addr, REG(B11_8), 2);
|
tcg_gen_subi_i32(addr, REG(B11_8), 2);
|
||||||
tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUW);
|
tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx,
|
||||||
|
MO_TEUW | UNALIGN(ctx));
|
||||||
tcg_gen_mov_i32(REG(B11_8), addr);
|
tcg_gen_mov_i32(REG(B11_8), addr);
|
||||||
tcg_temp_free(addr);
|
tcg_temp_free(addr);
|
||||||
}
|
}
|
||||||
|
@ -595,7 +604,8 @@ static void _decode_opc(DisasContext * ctx)
|
||||||
{
|
{
|
||||||
TCGv addr = tcg_temp_new();
|
TCGv addr = tcg_temp_new();
|
||||||
tcg_gen_subi_i32(addr, REG(B11_8), 4);
|
tcg_gen_subi_i32(addr, REG(B11_8), 4);
|
||||||
tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL);
|
tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx,
|
||||||
|
MO_TEUL | UNALIGN(ctx));
|
||||||
tcg_gen_mov_i32(REG(B11_8), addr);
|
tcg_gen_mov_i32(REG(B11_8), addr);
|
||||||
tcg_temp_free(addr);
|
tcg_temp_free(addr);
|
||||||
}
|
}
|
||||||
|
@ -606,12 +616,14 @@ static void _decode_opc(DisasContext * ctx)
|
||||||
tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 1);
|
tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 1);
|
||||||
return;
|
return;
|
||||||
case 0x6005: /* mov.w @Rm+,Rn */
|
case 0x6005: /* mov.w @Rm+,Rn */
|
||||||
tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESW);
|
tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx,
|
||||||
|
MO_TESW | UNALIGN(ctx));
|
||||||
if ( B11_8 != B7_4 )
|
if ( B11_8 != B7_4 )
|
||||||
tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
|
tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 2);
|
||||||
return;
|
return;
|
||||||
case 0x6006: /* mov.l @Rm+,Rn */
|
case 0x6006: /* mov.l @Rm+,Rn */
|
||||||
tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx, MO_TESL);
|
tcg_gen_qemu_ld_i32(REG(B11_8), REG(B7_4), ctx->memidx,
|
||||||
|
MO_TESL | UNALIGN(ctx));
|
||||||
if ( B11_8 != B7_4 )
|
if ( B11_8 != B7_4 )
|
||||||
tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
|
tcg_gen_addi_i32(REG(B7_4), REG(B7_4), 4);
|
||||||
return;
|
return;
|
||||||
|
@ -627,7 +639,8 @@ static void _decode_opc(DisasContext * ctx)
|
||||||
{
|
{
|
||||||
TCGv addr = tcg_temp_new();
|
TCGv addr = tcg_temp_new();
|
||||||
tcg_gen_add_i32(addr, REG(B11_8), REG(0));
|
tcg_gen_add_i32(addr, REG(B11_8), REG(0));
|
||||||
tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUW);
|
tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx,
|
||||||
|
MO_TEUW | UNALIGN(ctx));
|
||||||
tcg_temp_free(addr);
|
tcg_temp_free(addr);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -635,7 +648,8 @@ static void _decode_opc(DisasContext * ctx)
|
||||||
{
|
{
|
||||||
TCGv addr = tcg_temp_new();
|
TCGv addr = tcg_temp_new();
|
||||||
tcg_gen_add_i32(addr, REG(B11_8), REG(0));
|
tcg_gen_add_i32(addr, REG(B11_8), REG(0));
|
||||||
tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx, MO_TEUL);
|
tcg_gen_qemu_st_i32(REG(B7_4), addr, ctx->memidx,
|
||||||
|
MO_TEUL | UNALIGN(ctx));
|
||||||
tcg_temp_free(addr);
|
tcg_temp_free(addr);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -651,7 +665,8 @@ static void _decode_opc(DisasContext * ctx)
|
||||||
{
|
{
|
||||||
TCGv addr = tcg_temp_new();
|
TCGv addr = tcg_temp_new();
|
||||||
tcg_gen_add_i32(addr, REG(B7_4), REG(0));
|
tcg_gen_add_i32(addr, REG(B7_4), REG(0));
|
||||||
tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESW);
|
tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx,
|
||||||
|
MO_TESW | UNALIGN(ctx));
|
||||||
tcg_temp_free(addr);
|
tcg_temp_free(addr);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -659,7 +674,8 @@ static void _decode_opc(DisasContext * ctx)
|
||||||
{
|
{
|
||||||
TCGv addr = tcg_temp_new();
|
TCGv addr = tcg_temp_new();
|
||||||
tcg_gen_add_i32(addr, REG(B7_4), REG(0));
|
tcg_gen_add_i32(addr, REG(B7_4), REG(0));
|
||||||
tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx, MO_TESL);
|
tcg_gen_qemu_ld_i32(REG(B11_8), addr, ctx->memidx,
|
||||||
|
MO_TESL | UNALIGN(ctx));
|
||||||
tcg_temp_free(addr);
|
tcg_temp_free(addr);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -1253,7 +1269,8 @@ static void _decode_opc(DisasContext * ctx)
|
||||||
{
|
{
|
||||||
TCGv addr = tcg_temp_new();
|
TCGv addr = tcg_temp_new();
|
||||||
tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
|
tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
|
||||||
tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx, MO_TEUW);
|
tcg_gen_qemu_st_i32(REG(0), addr, ctx->memidx,
|
||||||
|
MO_TEUW | UNALIGN(ctx));
|
||||||
tcg_temp_free(addr);
|
tcg_temp_free(addr);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -1269,7 +1286,8 @@ static void _decode_opc(DisasContext * ctx)
|
||||||
{
|
{
|
||||||
TCGv addr = tcg_temp_new();
|
TCGv addr = tcg_temp_new();
|
||||||
tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
|
tcg_gen_addi_i32(addr, REG(B7_4), B3_0 * 2);
|
||||||
tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx, MO_TESW);
|
tcg_gen_qemu_ld_i32(REG(0), addr, ctx->memidx,
|
||||||
|
MO_TESW | UNALIGN(ctx));
|
||||||
tcg_temp_free(addr);
|
tcg_temp_free(addr);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue