diff options
Diffstat (limited to 'linux-user')
68 files changed, 1008 insertions, 729 deletions
diff --git a/linux-user/aarch64/target_prctl.h b/linux-user/aarch64/target_prctl.h new file mode 100644 index 0000000000..3f5a5d3933 --- /dev/null +++ b/linux-user/aarch64/target_prctl.h @@ -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 */ diff --git a/linux-user/aarch64/target_signal.h b/linux-user/aarch64/target_signal.h index 7580d99403..40e399d990 100644 --- a/linux-user/aarch64/target_signal.h +++ b/linux-user/aarch64/target_signal.h @@ -1,24 +1,6 @@ #ifndef 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" #define TARGET_SEGV_MTEAERR 8 /* Asynchronous ARM MTE error */ diff --git a/linux-user/aarch64/target_syscall.h b/linux-user/aarch64/target_syscall.h index 76f6c3391d..a98f568ab4 100644 --- a/linux-user/aarch64/target_syscall.h +++ b/linux-user/aarch64/target_syscall.h @@ -15,32 +15,8 @@ struct target_pt_regs { #endif #define UNAME_MINIMUM_RELEASE "3.8.0" #define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #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 */ diff --git a/linux-user/alpha/target_prctl.h b/linux-user/alpha/target_prctl.h new file mode 100644 index 0000000000..5629ddbf39 --- /dev/null +++ b/linux-user/alpha/target_prctl.h @@ -0,0 +1 @@ +#include "../generic/target_prctl_unalign.h" diff --git a/linux-user/alpha/target_signal.h b/linux-user/alpha/target_signal.h index 0b6a39de65..bbb06e5463 100644 --- a/linux-user/alpha/target_signal.h +++ b/linux-user/alpha/target_signal.h @@ -62,7 +62,6 @@ typedef struct target_sigaltstack { #define TARGET_SA_SIGINFO 0x00000040 #define TARGET_MINSIGSTKSZ 4096 -#define TARGET_SIGSTKSZ 16384 /* From <asm/gentrap.h>. */ #define TARGET_GEN_INTOVF -1 /* integer overflow */ diff --git a/linux-user/alpha/target_syscall.h b/linux-user/alpha/target_syscall.h index 03091bf0a8..fda3a49f29 100644 --- a/linux-user/alpha/target_syscall.h +++ b/linux-user/alpha/target_syscall.h @@ -63,7 +63,6 @@ struct target_pt_regs { #define TARGET_UAC_NOPRINT 1 #define TARGET_UAC_NOFIX 2 #define TARGET_UAC_SIGBUS 4 -#define TARGET_MINSIGSTKSZ 4096 #define TARGET_MCL_CURRENT 0x2000 #define TARGET_MCL_FUTURE 0x4000 #define TARGET_MCL_ONFAULT 0x8000 diff --git a/linux-user/arm/target_prctl.h b/linux-user/arm/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/arm/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/arm/target_signal.h b/linux-user/arm/target_signal.h index 1e7fb0cecb..0e6351d9f7 100644 --- a/linux-user/arm/target_signal.h +++ b/linux-user/arm/target_signal.h @@ -1,24 +1,6 @@ #ifndef 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" #define TARGET_ARCH_HAS_SETUP_FRAME diff --git a/linux-user/arm/target_syscall.h b/linux-user/arm/target_syscall.h index e870ed7a54..f04f9c9e3d 100644 --- a/linux-user/arm/target_syscall.h +++ b/linux-user/arm/target_syscall.h @@ -27,7 +27,6 @@ struct target_pt_regs { #define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/cris/target_prctl.h b/linux-user/cris/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/cris/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/cris/target_signal.h b/linux-user/cris/target_signal.h index 83a5155507..ab0653fcdc 100644 --- a/linux-user/cris/target_signal.h +++ b/linux-user/cris/target_signal.h @@ -1,24 +1,6 @@ #ifndef 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" #define TARGET_ARCH_HAS_SETUP_FRAME diff --git a/linux-user/cris/target_syscall.h b/linux-user/cris/target_syscall.h index 19e1281403..0b5ebf1f02 100644 --- a/linux-user/cris/target_syscall.h +++ b/linux-user/cris/target_syscall.h @@ -39,7 +39,6 @@ struct target_pt_regs { }; #define TARGET_CLONE_BACKWARDS2 -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 767f54c76d..329b2375ef 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -390,11 +390,11 @@ enum { /* 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) { - 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, 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; } +#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 USE_ELF_CORE_DUMP @@ -2160,8 +2201,13 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, return sp; } -#ifndef ARM_COMMPAGE -#define ARM_COMMPAGE 0 +#if defined(HI_COMMPAGE) +#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 #endif @@ -2361,7 +2407,7 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr, } loaddr &= -align; - if (ARM_COMMPAGE) { + if (HI_COMMPAGE) { /* * Extend the allocation to include the commpage. * 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) { hiaddr = (uintptr_t) 4 << 30; } 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); 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 * is ~32k, and we extend down to include the commpage, making the * 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. * If we do not need a commpage, leave guest_base == 0. */ - if (ARM_COMMPAGE) { + if (HI_COMMPAGE) { uintptr_t addr, commpage; /* 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 * 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); assert(addr != -1); guest_base = addr; diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c index 6941089959..a17d05c079 100644 --- a/linux-user/fd-trans.c +++ b/linux-user/fd-trans.c @@ -138,6 +138,9 @@ enum { QEMU_IFLA_PROP_LIST, QEMU_IFLA_ALT_IFNAME, QEMU_IFLA_PERM_ADDRESS, + QEMU_IFLA_PROTO_DOWN_REASON, + QEMU_IFLA_PARENT_DEV_NAME, + QEMU_IFLA_PARENT_DEV_BUS_NAME, QEMU___IFLA_MAX }; @@ -179,6 +182,8 @@ enum { QEMU_IFLA_BRPORT_BACKUP_PORT, QEMU_IFLA_BRPORT_MRP_RING_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 }; @@ -268,6 +273,37 @@ enum { 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; QemuMutex target_fd_trans_lock; unsigned int target_fd_max; @@ -573,6 +609,8 @@ static abi_long host_to_target_slave_data_bridge_nlattr(struct nlattr *nlattr, /* uin32_t */ case QEMU_IFLA_BRPORT_COST: 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 = tswap32(*u32); break; @@ -805,6 +843,145 @@ static abi_long host_to_target_data_xdp_nlattr(struct nlattr *nlattr, 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) { 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_BROADCAST: case QEMU_IFLA_PERM_ADDRESS: + case QEMU_IFLA_PHYS_PORT_ID: /* string */ case QEMU_IFLA_IFNAME: case QEMU_IFLA_QDISC: + case QEMU_IFLA_PARENT_DEV_NAME: + case QEMU_IFLA_PARENT_DEV_BUS_NAME: break; /* uin8_t */ 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, NULL, 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: qemu_log_mask(LOG_UNIMP, "Unknown host QEMU_IFLA type: %d\n", rtattr->rta_type); diff --git a/linux-user/generic/signal.h b/linux-user/generic/signal.h index 943bc1a1e2..6fd05b77bb 100644 --- a/linux-user/generic/signal.h +++ b/linux-user/generic/signal.h @@ -55,6 +55,21 @@ #define TARGET_SIG_UNBLOCK 1 /* for unblocking signals */ #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 */ #define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */ /* mask for all SS_xxx flags */ diff --git a/linux-user/generic/target_prctl_unalign.h b/linux-user/generic/target_prctl_unalign.h new file mode 100644 index 0000000000..bc3b83af2a --- /dev/null +++ b/linux-user/generic/target_prctl_unalign.h @@ -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 */ diff --git a/linux-user/hexagon/target_prctl.h b/linux-user/hexagon/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/hexagon/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/hexagon/target_signal.h b/linux-user/hexagon/target_signal.h index 9e0223d322..193abac340 100644 --- a/linux-user/hexagon/target_signal.h +++ b/linux-user/hexagon/target_signal.h @@ -18,17 +18,6 @@ #ifndef 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" #define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1 diff --git a/linux-user/hppa/target_prctl.h b/linux-user/hppa/target_prctl.h new file mode 100644 index 0000000000..5629ddbf39 --- /dev/null +++ b/linux-user/hppa/target_prctl.h @@ -0,0 +1 @@ +#include "../generic/target_prctl_unalign.h" diff --git a/linux-user/hppa/target_signal.h b/linux-user/hppa/target_signal.h index d558119ee7..af6c2fce58 100644 --- a/linux-user/hppa/target_signal.h +++ b/linux-user/hppa/target_signal.h @@ -64,7 +64,6 @@ typedef struct target_sigaltstack { #define TARGET_SA_NOCLDWAIT 0x00000080 #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 /* bit-flags */ #define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */ diff --git a/linux-user/hppa/target_syscall.h b/linux-user/hppa/target_syscall.h index 0018bcb5c4..4b382c1fcf 100644 --- a/linux-user/hppa/target_syscall.h +++ b/linux-user/hppa/target_syscall.h @@ -22,7 +22,6 @@ struct target_pt_regs { #define UNAME_MACHINE "parisc" #define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/i386/target_prctl.h b/linux-user/i386/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/i386/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/i386/target_signal.h b/linux-user/i386/target_signal.h index 64d09f2e75..9315cba241 100644 --- a/linux-user/i386/target_signal.h +++ b/linux-user/i386/target_signal.h @@ -1,24 +1,6 @@ #ifndef 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" #define TARGET_ARCH_HAS_SETUP_FRAME diff --git a/linux-user/i386/target_syscall.h b/linux-user/i386/target_syscall.h index ed356b3908..aaade06b13 100644 --- a/linux-user/i386/target_syscall.h +++ b/linux-user/i386/target_syscall.h @@ -150,7 +150,6 @@ struct target_vm86plus_struct { #define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/m68k/target_prctl.h b/linux-user/m68k/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/m68k/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/m68k/target_signal.h b/linux-user/m68k/target_signal.h index 94157bf1f4..6e0f4b74e3 100644 --- a/linux-user/m68k/target_signal.h +++ b/linux-user/m68k/target_signal.h @@ -1,24 +1,6 @@ #ifndef 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" #define TARGET_ARCH_HAS_SETUP_FRAME diff --git a/linux-user/m68k/target_syscall.h b/linux-user/m68k/target_syscall.h index 23359a6299..8d4ddbd76c 100644 --- a/linux-user/m68k/target_syscall.h +++ b/linux-user/m68k/target_syscall.h @@ -20,7 +20,6 @@ struct target_pt_regs { #define UNAME_MACHINE "m68k" #define UNAME_MINIMUM_RELEASE "2.6.32" -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/microblaze/target_prctl.h b/linux-user/microblaze/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/microblaze/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/microblaze/target_signal.h b/linux-user/microblaze/target_signal.h index e8b510f6b1..7dc5c45f00 100644 --- a/linux-user/microblaze/target_signal.h +++ b/linux-user/microblaze/target_signal.h @@ -1,24 +1,6 @@ #ifndef 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" #define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1 diff --git a/linux-user/microblaze/target_syscall.h b/linux-user/microblaze/target_syscall.h index 7f653db34f..43362a1664 100644 --- a/linux-user/microblaze/target_syscall.h +++ b/linux-user/microblaze/target_syscall.h @@ -49,7 +49,6 @@ struct target_pt_regs { }; #define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/mips/target_prctl.h b/linux-user/mips/target_prctl.h new file mode 100644 index 0000000000..e028333db9 --- /dev/null +++ b/linux-user/mips/target_prctl.h @@ -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 */ diff --git a/linux-user/mips/target_signal.h b/linux-user/mips/target_signal.h index 780a4ddf29..fa542c1f4e 100644 --- a/linux-user/mips/target_signal.h +++ b/linux-user/mips/target_signal.h @@ -67,7 +67,6 @@ typedef struct target_sigaltstack { #define TARGET_SA_RESTORER 0x04000000 /* Only for O32 */ #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 #if defined(TARGET_ABI_MIPSO32) /* compare linux/arch/mips/kernel/signal.c:setup_frame() */ diff --git a/linux-user/mips/target_syscall.h b/linux-user/mips/target_syscall.h index f59057493a..08ead67810 100644 --- a/linux-user/mips/target_syscall.h +++ b/linux-user/mips/target_syscall.h @@ -24,7 +24,6 @@ struct target_pt_regs { #define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 @@ -36,10 +35,4 @@ static inline abi_ulong target_shmlba(CPUMIPSState *env) 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 */ diff --git a/linux-user/mips64/target_prctl.h b/linux-user/mips64/target_prctl.h new file mode 100644 index 0000000000..18da9ae619 --- /dev/null +++ b/linux-user/mips64/target_prctl.h @@ -0,0 +1 @@ +#include "../mips/target_prctl.h" diff --git a/linux-user/mips64/target_signal.h b/linux-user/mips64/target_signal.h index 275e9b7f9a..b05098f7f6 100644 --- a/linux-user/mips64/target_signal.h +++ b/linux-user/mips64/target_signal.h @@ -65,7 +65,6 @@ typedef struct target_sigaltstack { #define TARGET_SA_RESETHAND 0x80000000 #define TARGET_MINSIGSTKSZ 2048 -#define TARGET_SIGSTKSZ 8192 /* bit-flags */ #define TARGET_SS_AUTODISARM (1U << 31) /* disable sas during sighandling */ diff --git a/linux-user/mips64/target_syscall.h b/linux-user/mips64/target_syscall.h index cd1e1b4969..358dc2d64c 100644 --- a/linux-user/mips64/target_syscall.h +++ b/linux-user/mips64/target_syscall.h @@ -21,7 +21,6 @@ struct target_pt_regs { #define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 @@ -33,10 +32,4 @@ static inline abi_ulong target_shmlba(CPUMIPSState *env) 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 */ diff --git a/linux-user/nios2/cpu_loop.c b/linux-user/nios2/cpu_loop.c index 34290fb3b5..1e93ef34e6 100644 --- a/linux-user/nios2/cpu_loop.c +++ b/linux-user/nios2/cpu_loop.c @@ -26,7 +26,6 @@ void cpu_loop(CPUNios2State *env) { CPUState *cs = env_cpu(env); - Nios2CPU *cpu = NIOS2_CPU(cs); target_siginfo_t info; int trapnr, ret; @@ -39,9 +38,10 @@ void cpu_loop(CPUNios2State *env) case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ break; + case EXCP_TRAP: - if (env->regs[R_AT] == 0) { - abi_long ret; + switch (env->error_code) { + case 0: qemu_log_mask(CPU_LOG_INT, "\nSyscall\n"); ret = do_syscall(env, env->regs[2], @@ -55,26 +55,56 @@ void cpu_loop(CPUNios2State *env) env->regs[2] = abs(ret); /* Return value is 0..4096 */ - env->regs[7] = (ret > 0xfffffffffffff000ULL); - env->regs[CR_ESTATUS] = env->regs[CR_STATUS]; - env->regs[CR_STATUS] &= ~0x3; - env->regs[R_EA] = env->regs[R_PC] + 4; + env->regs[7] = ret > 0xfffff000u; env->regs[R_PC] += 4; break; - } else { - qemu_log_mask(CPU_LOG_INT, "\nTrap\n"); - 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] = cpu->exception_addr; + case 1: + qemu_log_mask(CPU_LOG_INT, "\nTrap 1\n"); + force_sig_fault(TARGET_SIGUSR1, 0, env->regs[R_PC]); + 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; + + case 16: /* QEMU specific, for __kuser_cmpxchg */ + { + abi_ptr g = env->regs[4]; + uint32_t *h, n, o; - info.si_signo = TARGET_SIGTRAP; - info.si_errno = 0; - info.si_code = TARGET_TRAP_BRKPT; - queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); + 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; + case EXCP_DEBUG: info.si_signo = TARGET_SIGTRAP; info.si_errno = 0; @@ -82,29 +112,7 @@ void cpu_loop(CPUNios2State *env) queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); break; 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_errno = 0; /* 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_GP] = regs->gp; 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; + /* TODO: unsigned long orig_r7; */ } diff --git a/linux-user/nios2/signal.c b/linux-user/nios2/signal.c index a77e8a40f4..517cd39270 100644 --- a/linux-user/nios2/signal.c +++ b/linux-user/nios2/signal.c @@ -42,7 +42,7 @@ struct target_rt_sigframe { 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; @@ -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_FP], &gregs[24]); __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]); - - return 0; } 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]); /* Not really necessary no user settable bits */ __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_SP], &gregs[28]); @@ -135,8 +133,8 @@ static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc, return 0; } -static void *get_sigframe(struct target_sigaction *ka, CPUNios2State *env, - size_t frame_size) +static abi_ptr get_sigframe(struct target_sigaction *ka, CPUNios2State *env, + size_t frame_size) { 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); /* 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, @@ -153,26 +151,24 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, CPUNios2State *env) { struct target_rt_sigframe *frame; - int i, err = 0; + abi_ptr frame_addr; + int i; - frame = get_sigframe(ka, env, sizeof(*frame)); - - if (ka->sa_flags & SA_SIGINFO) { - tswap_siginfo(&frame->info, info); + frame_addr = get_sigframe(ka, env, sizeof(*frame)); + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { + force_sigsegv(sig); + return; } + tswap_siginfo(&frame->info, info); + /* Create the ucontext. */ __put_user(0, &frame->uc.tuc_flags); __put_user(0, &frame->uc.tuc_link); 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++) { - __put_user((abi_ulong)set->sig[i], - (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]); - } - - if (err) { - goto give_sigsegv; + __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); } /* 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); /* Set up registers for signal handler */ - env->regs[R_SP] = (unsigned long) frame; - env->regs[4] = (unsigned long) sig; - env->regs[5] = (unsigned long) &frame->info; - env->regs[6] = (unsigned long) &frame->uc; - env->regs[R_EA] = (unsigned long) ka->_sa_handler; - return; - -give_sigsegv: - if (sig == TARGET_SIGSEGV) { - ka->_sa_handler = TARGET_SIG_DFL; - } - force_sigsegv(sig); - return; + env->regs[R_SP] = frame_addr; + env->regs[4] = sig; + env->regs[5] = frame_addr + offsetof(struct target_rt_sigframe, info); + env->regs[6] = frame_addr + offsetof(struct target_rt_sigframe, uc); + env->regs[R_PC] = ka->_sa_handler; + + unlock_user_struct(frame, frame_addr, 1); } long do_sigreturn(CPUNios2State *env) @@ -215,7 +205,7 @@ long do_rt_sigreturn(CPUNios2State *env) } 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)) { goto badframe; diff --git a/linux-user/nios2/target_prctl.h b/linux-user/nios2/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/nios2/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/nios2/target_signal.h b/linux-user/nios2/target_signal.h index fe266c4c51..46ca5948ce 100644 --- a/linux-user/nios2/target_signal.h +++ b/linux-user/nios2/target_signal.h @@ -1,22 +1,6 @@ #ifndef 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" /* Nios2 uses a fixed address on the kuser page for sigreturn. */ diff --git a/linux-user/nios2/target_syscall.h b/linux-user/nios2/target_syscall.h index 78006c24d4..561b28d281 100644 --- a/linux-user/nios2/target_syscall.h +++ b/linux-user/nios2/target_syscall.h @@ -30,7 +30,6 @@ struct target_pt_regs { unsigned long orig_r7; }; -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/openrisc/target_prctl.h b/linux-user/openrisc/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/openrisc/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/openrisc/target_signal.h b/linux-user/openrisc/target_signal.h index 077ec3d5e8..5b9d40974a 100644 --- a/linux-user/openrisc/target_signal.h +++ b/linux-user/openrisc/target_signal.h @@ -1,29 +1,6 @@ #ifndef 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" #define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1 diff --git a/linux-user/openrisc/target_syscall.h b/linux-user/openrisc/target_syscall.h index ef0d89a551..7fe5b73d3b 100644 --- a/linux-user/openrisc/target_syscall.h +++ b/linux-user/openrisc/target_syscall.h @@ -15,7 +15,6 @@ struct target_pt_regs { #define UNAME_MACHINE "openrisc" #define UNAME_MINIMUM_RELEASE "2.6.32" -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/ppc/target_prctl.h b/linux-user/ppc/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/ppc/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/ppc/target_signal.h b/linux-user/ppc/target_signal.h index 82184ab8f2..5be24e152b 100644 --- a/linux-user/ppc/target_signal.h +++ b/linux-user/ppc/target_signal.h @@ -1,24 +1,6 @@ #ifndef 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" #if !defined(TARGET_PPC64) diff --git a/linux-user/ppc/target_syscall.h b/linux-user/ppc/target_syscall.h index b9c4b813d3..8b364697d4 100644 --- a/linux-user/ppc/target_syscall.h +++ b/linux-user/ppc/target_syscall.h @@ -71,7 +71,6 @@ struct target_revectored_struct { #define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 0x2000 #define TARGET_MCL_FUTURE 0x4000 #define TARGET_MCL_ONFAULT 0x8000 diff --git a/linux-user/riscv/target_prctl.h b/linux-user/riscv/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/riscv/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/riscv/target_signal.h b/linux-user/riscv/target_signal.h index 3e36fddc9d..6c0470f0bc 100644 --- a/linux-user/riscv/target_signal.h +++ b/linux-user/riscv/target_signal.h @@ -1,18 +1,6 @@ #ifndef 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" #define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1 diff --git a/linux-user/riscv/target_syscall.h b/linux-user/riscv/target_syscall.h index 9b13161324..7601f10c28 100644 --- a/linux-user/riscv/target_syscall.h +++ b/linux-user/riscv/target_syscall.h @@ -51,7 +51,6 @@ struct target_pt_regs { #define UNAME_MINIMUM_RELEASE "4.15.0" #endif -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/s390x/target_prctl.h b/linux-user/s390x/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/s390x/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/s390x/target_signal.h b/linux-user/s390x/target_signal.h index 64f5f42201..41e0e34a55 100644 --- a/linux-user/s390x/target_signal.h +++ b/linux-user/s390x/target_signal.h @@ -1,21 +1,6 @@ #ifndef 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" #define TARGET_ARCH_HAS_SETUP_FRAME diff --git a/linux-user/s390x/target_syscall.h b/linux-user/s390x/target_syscall.h index 94f84178db..4018988a25 100644 --- a/linux-user/s390x/target_syscall.h +++ b/linux-user/s390x/target_syscall.h @@ -27,7 +27,6 @@ struct target_pt_regs { #define UNAME_MINIMUM_RELEASE "2.6.32" #define TARGET_CLONE_BACKWARDS2 -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/sh4/target_prctl.h b/linux-user/sh4/target_prctl.h new file mode 100644 index 0000000000..5629ddbf39 --- /dev/null +++ b/linux-user/sh4/target_prctl.h @@ -0,0 +1 @@ +#include "../generic/target_prctl_unalign.h" diff --git a/linux-user/sh4/target_signal.h b/linux-user/sh4/target_signal.h index 04069cba66..eee6a1a7cd 100644 --- a/linux-user/sh4/target_signal.h +++ b/linux-user/sh4/target_signal.h @@ -1,24 +1,6 @@ #ifndef 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" #define TARGET_ARCH_HAS_SETUP_FRAME diff --git a/linux-user/sh4/target_syscall.h b/linux-user/sh4/target_syscall.h index c1437adafe..148398855d 100644 --- a/linux-user/sh4/target_syscall.h +++ b/linux-user/sh4/target_syscall.h @@ -15,7 +15,6 @@ struct target_pt_regs { #define UNAME_MACHINE "sh4" #define UNAME_MINIMUM_RELEASE "2.6.32" -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/signal.c b/linux-user/signal.c index 510db73c34..f813b4f18e 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -258,7 +258,6 @@ int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) return 0; } -#if !defined(TARGET_NIOS2) /* Just set the guest's signal mask to the specified value; the * caller is assumed to have called block_signals() already. */ @@ -268,7 +267,6 @@ void set_sigmask(const sigset_t *set) ts->signal_mask = *set; } -#endif /* sigaltstack management */ @@ -406,7 +404,12 @@ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, case TARGET_SIGCHLD: tinfo->_sifields._sigchld._pid = info->si_pid; 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._stime = info->si_stime; si_type = QEMU_SI_CHLD; diff --git a/linux-user/sparc/target_prctl.h b/linux-user/sparc/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/sparc/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/sparc/target_signal.h b/linux-user/sparc/target_signal.h index e661ddd6ab..87757f0c4e 100644 --- a/linux-user/sparc/target_signal.h +++ b/linux-user/sparc/target_signal.h @@ -65,7 +65,6 @@ typedef struct target_sigaltstack { #define TARGET_ARCH_HAS_KA_RESTORER 1 #define TARGET_MINSIGSTKSZ 4096 -#define TARGET_SIGSTKSZ 16384 #ifdef TARGET_ABI32 #define TARGET_ARCH_HAS_SETUP_FRAME diff --git a/linux-user/sparc/target_syscall.h b/linux-user/sparc/target_syscall.h index 087b39d39c..be77e44eb8 100644 --- a/linux-user/sparc/target_syscall.h +++ b/linux-user/sparc/target_syscall.h @@ -34,7 +34,6 @@ struct target_pt_regs { * and copy_thread(). */ #define TARGET_CLONE_BACKWARDS -#define TARGET_MINSIGSTKSZ 4096 #define TARGET_MCL_CURRENT 0x2000 #define TARGET_MCL_FUTURE 0x4000 #define TARGET_MCL_ONFAULT 0x8000 diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 56a3e17183..ce9d64896c 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -340,6 +340,36 @@ _syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len, #define __NR_sys_sched_setaffinity __NR_sched_setaffinity _syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len, 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 _syscall3(int, sys_getcpu, unsigned *, cpu, unsigned *, node, void *, tcache); _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)); } +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) \ 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. * Allocate one that is large enough and use it instead. */ - host_ifconf = malloc(outbufsz); + host_ifconf = g_try_malloc(outbufsz); if (!host_ifconf) { return -TARGET_ENOMEM; } @@ -4915,7 +4963,7 @@ static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp, } if (free_buf) { - free(host_ifconf); + g_free(host_ifconf); } return ret; @@ -6294,9 +6342,216 @@ abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr) return ret; } #endif /* defined(TARGET_ABI32 */ - #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 @@ -7790,7 +8045,7 @@ static int open_self_maps(void *cpu_env, int fd) (flags & PAGE_READ) ? 'r' : '-', (flags & PAGE_WRITE_ORG) ? 'w' : '-', (flags & PAGE_EXEC) ? 'x' : '-', - e->is_priv ? 'p' : '-', + e->is_priv ? 'p' : 's', (uint64_t) e->offset, e->dev, e->inode); if (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; case TARGET_NR_sched_setparam: { - struct sched_param *target_schp; + struct target_sched_param *target_schp; struct sched_param schp; if (arg2 == 0) { 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; + } schp.sched_priority = tswap32(target_schp->sched_priority); 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: { - struct sched_param *target_schp; + struct target_sched_param *target_schp; struct sched_param schp; if (arg2 == 0) { return -TARGET_EINVAL; } - ret = get_errno(sched_getparam(arg1, &schp)); + ret = get_errno(sys_sched_getparam(arg1, &schp)); 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; + } target_schp->sched_priority = tswap32(schp.sched_priority); 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; case TARGET_NR_sched_setscheduler: { - struct sched_param *target_schp; + struct target_sched_param *target_schp; struct sched_param schp; if (arg3 == 0) { 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; + } schp.sched_priority = tswap32(target_schp->sched_priority); 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: - 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: return get_errno(sched_yield()); 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; #endif case TARGET_NR_prctl: - switch (arg1) { - 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)); - } + return do_prctl(cpu_env, arg1, arg2, arg3, arg4, arg5); break; #ifdef TARGET_NR_arch_prctl case TARGET_NR_arch_prctl: diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 0b13975937..cca561f622 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -2133,7 +2133,8 @@ struct target_stat64 { 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 */ @@ -2244,31 +2245,6 @@ struct target_stat64 { 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 #error unsupported CPU #endif @@ -2914,4 +2890,22 @@ struct target_statx { /* 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 diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h index f71f372829..a8fdd6933b 100644 --- a/linux-user/user-internals.h +++ b/linux-user/user-internals.h @@ -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 arg8); extern __thread CPUState *thread_cpu; -void cpu_loop(CPUArchState *env); +void QEMU_NORETURN cpu_loop(CPUArchState *env); const char *target_strerror(int err); int get_osversion(void); void init_qemu_uname_release(void); diff --git a/linux-user/x86_64/target_prctl.h b/linux-user/x86_64/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/x86_64/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/x86_64/target_signal.h b/linux-user/x86_64/target_signal.h index 4673c5a886..9d9717406f 100644 --- a/linux-user/x86_64/target_signal.h +++ b/linux-user/x86_64/target_signal.h @@ -1,24 +1,6 @@ #ifndef 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" /* For x86_64, use of SA_RESTORER is mandatory. */ diff --git a/linux-user/x86_64/target_syscall.h b/linux-user/x86_64/target_syscall.h index 3ecccb72be..fb558345d3 100644 --- a/linux-user/x86_64/target_syscall.h +++ b/linux-user/x86_64/target_syscall.h @@ -100,7 +100,6 @@ struct target_msqid64_ds { #define TARGET_ARCH_SET_FS 0x1002 #define TARGET_ARCH_GET_FS 0x1003 #define TARGET_ARCH_GET_GS 0x1004 -#define TARGET_MINSIGSTKSZ 2048 #define TARGET_MCL_CURRENT 1 #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 diff --git a/linux-user/xtensa/target_prctl.h b/linux-user/xtensa/target_prctl.h new file mode 100644 index 0000000000..eb53b31ad5 --- /dev/null +++ b/linux-user/xtensa/target_prctl.h @@ -0,0 +1 @@ +/* No special prctl support required. */ diff --git a/linux-user/xtensa/target_signal.h b/linux-user/xtensa/target_signal.h index 1c7ee73154..e4b1bea5cb 100644 --- a/linux-user/xtensa/target_signal.h +++ b/linux-user/xtensa/target_signal.h @@ -1,23 +1,6 @@ #ifndef 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" #define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1 |