Add several floppy drive ioctl,
xtensa call0 ABI support, arm MAX_RESERVED_VA for M-profile, aarch64 AT_HWCAP2, qOffsets' query for ELF, memfd_create, and some code cleanup -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAl14mM0SHGxhdXJlbnRA dml2aWVyLmV1AAoJEPMMOL0/L748M0YP/AqGvgbjE8Mz4DBdTiYdLd+Wm7OEVgf0 mXeESyLjt7JH+/VstkMaRKFYhTXa4nXJQclFcAtSaUqZv70HoGTQPCL6Ld60qQIQ MTPGPNNz4d5AQKSbc9QQWZTZRDjJcczLkcgEbAuTHor2q4AMnNMBtOM1/KqXjK8l 4+UYPe/OesKk3serMv5U4vfP79D1GiN2rHYyKz5+n9LLiHEn+A+D3NJ+gYj/jDSq z5Mg/GvzSCjrwCHQBKoOy3oUCe0MXY5FTq/ZUvX+PZV61fItlAbrEYGvOuRpJ8uo JWZcEf7d/YEhG91dfMEZfwtIC5fM0GnXHsB1wVf/E7bkk2fWGHJ660l3eUmE8qnm AQJ8T46HMWlYyQUqhESNM0P8/Lo5ZIEX23Q1hmn5Jw/hBlOsTNn0r2zrOzSkHjNQ 9MPMsm7xzQIHP1zH4l1VoDuily9DEXoYye4ORJYd7kD5KBdbR4cksnkZhuVig5zU 6FSRf4mafVFVoz16DTk2eDa4/7xSztB7UrWI11rTTA6ccPnhTL/ALrGKBrMc6adp XEVHz54JbHm+svReZvZb5w0pmbplNYMGmp9gT7B3U514iWxFrCKkJPW3vhoKxtve D03JnFiYVu5KupIDhAtrmSvto+AzHKGk2aVip+N5Q6t1UWufl3jbsD8JJJ6SmnjP lFYEPSLuCjbU =n81A -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-4.2-pull-request' into staging Add several floppy drive ioctl, xtensa call0 ABI support, arm MAX_RESERVED_VA for M-profile, aarch64 AT_HWCAP2, qOffsets' query for ELF, memfd_create, and some code cleanup # gpg: Signature made Wed 11 Sep 2019 07:48:45 BST # gpg: using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C # gpg: issuer "laurent@vivier.eu" # gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full] # gpg: aka "Laurent Vivier <laurent@vivier.eu>" [full] # gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full] # Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C * remotes/vivier2/tags/linux-user-for-4.2-pull-request: linux-user: Add support for FDRESET, FDRAWCMD, FDTWADDLE, and FDEJECT ioctls linux-user: Add support for FDMSGON and FDMSGOFF ioctls linux-user: Add support for FDFLUSH ioctl linux-user: Add support for FIOGETOWN and FIOSETOWN ioctls linux-user: Add support for RNDRESEEDCRNG ioctl linux-user: drop redundant handling of environment variables target/xtensa: linux-user: add call0 ABI support linux-user: Support gdb 'qOffsets' query for ELF linux-user/arm: Adjust MAX_RESERVED_VA for M-profile linux-user: Pass CPUState to MAX_RESERVED_VA linux-user: add memfd_create linux-user: fail and report on bad dfilter specs linux-user: erroneous fd_trans_unregister call linux-user: Add AT_HWCAP2 for aarch64-linux-user linux-user: remove useless variable Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
a30cb4b1f2
@ -32,6 +32,10 @@
|
||||
#define MFD_HUGE_SHIFT 26
|
||||
#endif
|
||||
|
||||
#if defined CONFIG_LINUX && !defined CONFIG_MEMFD
|
||||
int memfd_create(const char *name, unsigned int flags);
|
||||
#endif
|
||||
|
||||
int qemu_memfd_create(const char *name, size_t size, bool hugetlb,
|
||||
uint64_t hugetlbsize, unsigned int seals, Error **errp);
|
||||
bool qemu_memfd_alloc_check(void);
|
||||
|
@ -19,9 +19,27 @@
|
||||
#ifndef ARM_TARGET_CPU_H
|
||||
#define ARM_TARGET_CPU_H
|
||||
|
||||
/* We need to be able to map the commpage.
|
||||
See validate_guest_space in linux-user/elfload.c. */
|
||||
#define MAX_RESERVED_VA 0xffff0000ul
|
||||
static inline unsigned long arm_max_reserved_va(CPUState *cs)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(cs);
|
||||
|
||||
if (arm_feature(&cpu->env, ARM_FEATURE_M)) {
|
||||
/*
|
||||
* There are magic return addresses above 0xfe000000,
|
||||
* and in general a lot of M-profile system stuff in
|
||||
* the high addresses. Restrict linux-user to the
|
||||
* cached write-back RAM in the system map.
|
||||
*/
|
||||
return 0x80000000ul;
|
||||
} else {
|
||||
/*
|
||||
* We need to be able to map the commpage.
|
||||
* See validate_guest_space in linux-user/elfload.c.
|
||||
*/
|
||||
return 0xffff0000ul;
|
||||
}
|
||||
}
|
||||
#define MAX_RESERVED_VA arm_max_reserved_va
|
||||
|
||||
static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp)
|
||||
{
|
||||
|
@ -607,9 +607,23 @@ enum {
|
||||
ARM_HWCAP_A64_SB = 1 << 29,
|
||||
ARM_HWCAP_A64_PACA = 1 << 30,
|
||||
ARM_HWCAP_A64_PACG = 1UL << 31,
|
||||
|
||||
ARM_HWCAP2_A64_DCPODP = 1 << 0,
|
||||
ARM_HWCAP2_A64_SVE2 = 1 << 1,
|
||||
ARM_HWCAP2_A64_SVEAES = 1 << 2,
|
||||
ARM_HWCAP2_A64_SVEPMULL = 1 << 3,
|
||||
ARM_HWCAP2_A64_SVEBITPERM = 1 << 4,
|
||||
ARM_HWCAP2_A64_SVESHA3 = 1 << 5,
|
||||
ARM_HWCAP2_A64_SVESM4 = 1 << 6,
|
||||
ARM_HWCAP2_A64_FLAGM2 = 1 << 7,
|
||||
ARM_HWCAP2_A64_FRINT = 1 << 8,
|
||||
};
|
||||
|
||||
#define ELF_HWCAP get_elf_hwcap()
|
||||
#define ELF_HWCAP get_elf_hwcap()
|
||||
#define ELF_HWCAP2 get_elf_hwcap2()
|
||||
|
||||
#define GET_FEATURE_ID(feat, hwcap) \
|
||||
do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0)
|
||||
|
||||
static uint32_t get_elf_hwcap(void)
|
||||
{
|
||||
@ -621,8 +635,6 @@ static uint32_t get_elf_hwcap(void)
|
||||
hwcaps |= ARM_HWCAP_A64_CPUID;
|
||||
|
||||
/* probe for the extra features */
|
||||
#define GET_FEATURE_ID(feat, hwcap) \
|
||||
do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0)
|
||||
|
||||
GET_FEATURE_ID(aa64_aes, ARM_HWCAP_A64_AES);
|
||||
GET_FEATURE_ID(aa64_pmull, ARM_HWCAP_A64_PMULL);
|
||||
@ -645,11 +657,22 @@ static uint32_t get_elf_hwcap(void)
|
||||
GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB);
|
||||
GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM);
|
||||
|
||||
#undef GET_FEATURE_ID
|
||||
return hwcaps;
|
||||
}
|
||||
|
||||
static uint32_t get_elf_hwcap2(void)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(thread_cpu);
|
||||
uint32_t hwcaps = 0;
|
||||
|
||||
GET_FEATURE_ID(aa64_condm_5, ARM_HWCAP2_A64_FLAGM2);
|
||||
GET_FEATURE_ID(aa64_frint, ARM_HWCAP2_A64_FRINT);
|
||||
|
||||
return hwcaps;
|
||||
}
|
||||
|
||||
#undef GET_FEATURE_ID
|
||||
|
||||
#endif /* not TARGET_AARCH64 */
|
||||
#endif /* TARGET_ARM */
|
||||
|
||||
@ -2380,6 +2403,8 @@ static void load_elf_image(const char *image_name, int image_fd,
|
||||
}
|
||||
|
||||
info->load_bias = load_bias;
|
||||
info->code_offset = load_bias;
|
||||
info->data_offset = load_bias;
|
||||
info->load_addr = load_addr;
|
||||
info->entry = ehdr->e_entry + load_bias;
|
||||
info->start_code = -1;
|
||||
|
@ -112,6 +112,14 @@
|
||||
IOCTL(BLKZEROOUT, IOC_W, MK_PTR(MK_ARRAY(TYPE_ULONGLONG, 2)))
|
||||
#endif
|
||||
|
||||
IOCTL(FDMSGON, 0, TYPE_NULL)
|
||||
IOCTL(FDMSGOFF, 0, TYPE_NULL)
|
||||
IOCTL(FDFLUSH, 0, TYPE_NULL)
|
||||
IOCTL(FDRESET, 0, TYPE_NULL)
|
||||
IOCTL(FDRAWCMD, 0, TYPE_NULL)
|
||||
IOCTL(FDTWADDLE, 0, TYPE_NULL)
|
||||
IOCTL(FDEJECT, 0, TYPE_NULL)
|
||||
|
||||
#ifdef FIBMAP
|
||||
IOCTL(FIBMAP, IOC_W | IOC_R, MK_PTR(TYPE_LONG))
|
||||
#endif
|
||||
@ -177,6 +185,8 @@
|
||||
#endif
|
||||
#endif /* CONFIG_USBFS */
|
||||
|
||||
IOCTL(FIOGETOWN, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(FIOSETOWN, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(SIOCATMARK, IOC_R, MK_PTR(TYPE_INT))
|
||||
IOCTL(SIOCGIFNAME, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_int_ifreq)))
|
||||
IOCTL(SIOCGIFFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
|
||||
@ -246,6 +256,9 @@
|
||||
IOCTL(RNDADDTOENTCNT, IOC_W, MK_PTR(TYPE_INT))
|
||||
IOCTL(RNDZAPENTCNT, 0, TYPE_NULL)
|
||||
IOCTL(RNDCLEARPOOL, 0, TYPE_NULL)
|
||||
#ifdef RNDRESEEDCRNG
|
||||
IOCTL(RNDRESEEDCRNG, 0, TYPE_NULL)
|
||||
#endif
|
||||
|
||||
IOCTL(CDROMPAUSE, 0, TYPE_NULL)
|
||||
IOCTL(CDROMSTART, 0, TYPE_NULL)
|
||||
|
@ -49,7 +49,6 @@
|
||||
char *exec_path;
|
||||
|
||||
int singlestep;
|
||||
static const char *filename;
|
||||
static const char *argv0;
|
||||
static int gdbstub_port;
|
||||
static envlist_t *envlist;
|
||||
@ -78,12 +77,12 @@ int have_guest_base;
|
||||
(TARGET_LONG_BITS == 32 || defined(TARGET_ABI32))
|
||||
/* There are a number of places where we assign reserved_va to a variable
|
||||
of type abi_ulong and expect it to fit. Avoid the last page. */
|
||||
# define MAX_RESERVED_VA (0xfffffffful & TARGET_PAGE_MASK)
|
||||
# define MAX_RESERVED_VA(CPU) (0xfffffffful & TARGET_PAGE_MASK)
|
||||
# else
|
||||
# define MAX_RESERVED_VA (1ul << TARGET_VIRT_ADDR_SPACE_BITS)
|
||||
# define MAX_RESERVED_VA(CPU) (1ul << TARGET_VIRT_ADDR_SPACE_BITS)
|
||||
# endif
|
||||
# else
|
||||
# define MAX_RESERVED_VA 0
|
||||
# define MAX_RESERVED_VA(CPU) 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@ -236,7 +235,7 @@ static void handle_arg_log(const char *arg)
|
||||
|
||||
static void handle_arg_dfilter(const char *arg)
|
||||
{
|
||||
qemu_set_dfilter_ranges(arg, NULL);
|
||||
qemu_set_dfilter_ranges(arg, &error_fatal);
|
||||
}
|
||||
|
||||
static void handle_arg_log_filename(const char *arg)
|
||||
@ -357,8 +356,7 @@ static void handle_arg_reserved_va(const char *arg)
|
||||
unsigned long unshifted = reserved_va;
|
||||
p++;
|
||||
reserved_va <<= shift;
|
||||
if (reserved_va >> shift != unshifted
|
||||
|| (MAX_RESERVED_VA && reserved_va > MAX_RESERVED_VA)) {
|
||||
if (reserved_va >> shift != unshifted) {
|
||||
fprintf(stderr, "Reserved virtual address too big\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@ -393,6 +391,13 @@ static void handle_arg_trace(const char *arg)
|
||||
trace_file = trace_opt_parse(arg);
|
||||
}
|
||||
|
||||
#if defined(TARGET_XTENSA)
|
||||
static void handle_arg_abi_call0(const char *arg)
|
||||
{
|
||||
xtensa_set_abi_call0();
|
||||
}
|
||||
#endif
|
||||
|
||||
struct qemu_argument {
|
||||
const char *argv;
|
||||
const char *env;
|
||||
@ -446,6 +451,10 @@ static const struct qemu_argument arg_table[] = {
|
||||
"", "[[enable=]<pattern>][,events=<file>][,file=<file>]"},
|
||||
{"version", "QEMU_VERSION", false, handle_arg_version,
|
||||
"", "display version information and exit"},
|
||||
#if defined(TARGET_XTENSA)
|
||||
{"xtensa-abi-call0", "QEMU_XTENSA_ABI_CALL0", false, handle_arg_abi_call0,
|
||||
"", "assume CALL0 Xtensa ABI"},
|
||||
#endif
|
||||
{NULL, NULL, false, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
@ -586,7 +595,6 @@ static int parse_args(int argc, char **argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
filename = argv[optind];
|
||||
exec_path = argv[optind];
|
||||
|
||||
return optind;
|
||||
@ -607,6 +615,7 @@ int main(int argc, char **argv, char **envp)
|
||||
int i;
|
||||
int ret;
|
||||
int execfd;
|
||||
unsigned long max_reserved_va;
|
||||
|
||||
error_init(argv[0]);
|
||||
module_call_init(MODULE_INIT_TRACE);
|
||||
@ -657,9 +666,9 @@ int main(int argc, char **argv, char **envp)
|
||||
|
||||
execfd = qemu_getauxval(AT_EXECFD);
|
||||
if (execfd == 0) {
|
||||
execfd = open(filename, O_RDONLY);
|
||||
execfd = open(exec_path, O_RDONLY);
|
||||
if (execfd < 0) {
|
||||
printf("Error while loading %s: %s\n", filename, strerror(errno));
|
||||
printf("Error while loading %s: %s\n", exec_path, strerror(errno));
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@ -672,31 +681,31 @@ int main(int argc, char **argv, char **envp)
|
||||
/* init tcg before creating CPUs and to get qemu_host_page_size */
|
||||
tcg_exec_init(0);
|
||||
|
||||
/* Reserving *too* much vm space via mmap can run into problems
|
||||
with rlimits, oom due to page table creation, etc. We will still try it,
|
||||
if directed by the command-line option, but not by default. */
|
||||
if (HOST_LONG_BITS == 64 &&
|
||||
TARGET_VIRT_ADDR_SPACE_BITS <= 32 &&
|
||||
reserved_va == 0) {
|
||||
/* reserved_va must be aligned with the host page size
|
||||
* as it is used with mmap()
|
||||
*/
|
||||
reserved_va = MAX_RESERVED_VA & qemu_host_page_mask;
|
||||
}
|
||||
|
||||
cpu = cpu_create(cpu_type);
|
||||
env = cpu->env_ptr;
|
||||
cpu_reset(cpu);
|
||||
|
||||
thread_cpu = cpu;
|
||||
|
||||
if (getenv("QEMU_STRACE")) {
|
||||
do_strace = 1;
|
||||
/*
|
||||
* Reserving too much vm space via mmap can run into problems
|
||||
* with rlimits, oom due to page table creation, etc. We will
|
||||
* still try it, if directed by the command-line option, but
|
||||
* not by default.
|
||||
*/
|
||||
max_reserved_va = MAX_RESERVED_VA(cpu);
|
||||
if (reserved_va != 0) {
|
||||
if (max_reserved_va && reserved_va > max_reserved_va) {
|
||||
fprintf(stderr, "Reserved virtual address too big\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32) {
|
||||
/*
|
||||
* reserved_va must be aligned with the host page size
|
||||
* as it is used with mmap()
|
||||
*/
|
||||
reserved_va = max_reserved_va & qemu_host_page_mask;
|
||||
}
|
||||
|
||||
if (seed_optarg == NULL) {
|
||||
seed_optarg = getenv("QEMU_RAND_SEED");
|
||||
}
|
||||
{
|
||||
Error *err = NULL;
|
||||
if (seed_optarg != NULL) {
|
||||
@ -784,10 +793,10 @@ int main(int argc, char **argv, char **envp)
|
||||
cpu->opaque = ts;
|
||||
task_settid(ts);
|
||||
|
||||
ret = loader_exec(execfd, filename, target_argv, target_environ, regs,
|
||||
ret = loader_exec(execfd, exec_path, target_argv, target_environ, regs,
|
||||
info, &bprm);
|
||||
if (ret != 0) {
|
||||
printf("Error while loading %s: %s\n", filename, strerror(-ret));
|
||||
printf("Error while loading %s: %s\n", exec_path, strerror(-ret));
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/path.h"
|
||||
#include "qemu/memfd.h"
|
||||
#include "qemu/queue.h"
|
||||
#include <elf.h>
|
||||
#include <endian.h>
|
||||
@ -88,6 +89,7 @@
|
||||
#include <linux/kd.h>
|
||||
#include <linux/mtio.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/fd.h>
|
||||
#if defined(CONFIG_FIEMAP)
|
||||
#include <linux/fiemap.h>
|
||||
#endif
|
||||
@ -11847,7 +11849,6 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
||||
timer_t htimer = g_posix_timers[timerid];
|
||||
ret = get_errno(timer_getoverrun(htimer));
|
||||
}
|
||||
fd_trans_unregister(ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@ -11939,6 +11940,17 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
||||
/* PowerPC specific. */
|
||||
return do_swapcontext(cpu_env, arg1, arg2, arg3);
|
||||
#endif
|
||||
#ifdef TARGET_NR_memfd_create
|
||||
case TARGET_NR_memfd_create:
|
||||
p = lock_user_string(arg1);
|
||||
if (!p) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
ret = get_errno(memfd_create(p, arg2));
|
||||
fd_trans_unregister(ret);
|
||||
unlock_user(p, arg1, 0);
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
|
||||
|
@ -758,10 +758,14 @@ struct target_pollfd {
|
||||
|
||||
#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SH4) || \
|
||||
defined(TARGET_XTENSA)
|
||||
#define TARGET_FIOGETOWN TARGET_IOR('f', 123, int)
|
||||
#define TARGET_FIOSETOWN TARGET_IOW('f', 124, int)
|
||||
#define TARGET_SIOCATMARK TARGET_IOR('s', 7, int)
|
||||
#define TARGET_SIOCSPGRP TARGET_IOW('s', 8, pid_t)
|
||||
#define TARGET_SIOCGPGRP TARGET_IOR('s', 9, pid_t)
|
||||
#else
|
||||
#define TARGET_FIOGETOWN 0x8903
|
||||
#define TARGET_FIOSETOWN 0x8901
|
||||
#define TARGET_SIOCATMARK 0x8905
|
||||
#define TARGET_SIOCSPGRP 0x8902
|
||||
#define TARGET_SIOCGPGRP 0x8904
|
||||
@ -850,6 +854,7 @@ struct target_pollfd {
|
||||
#define TARGET_RNDADDTOENTCNT TARGET_IOW('R', 0x01, int)
|
||||
#define TARGET_RNDZAPENTCNT TARGET_IO('R', 0x04)
|
||||
#define TARGET_RNDCLEARPOOL TARGET_IO('R', 0x06)
|
||||
#define TARGET_RNDRESEEDCRNG TARGET_IO('R', 0x07)
|
||||
|
||||
/* From <linux/fs.h> */
|
||||
|
||||
@ -883,6 +888,16 @@ struct target_pollfd {
|
||||
#define TARGET_BLKROTATIONAL TARGET_IO(0x12, 126)
|
||||
#define TARGET_BLKZEROOUT TARGET_IO(0x12, 127)
|
||||
|
||||
/* From <linux/fd.h> */
|
||||
|
||||
#define TARGET_FDMSGON TARGET_IO(2, 0x45)
|
||||
#define TARGET_FDMSGOFF TARGET_IO(2, 0x46)
|
||||
#define TARGET_FDFLUSH TARGET_IO(2, 0x4b)
|
||||
#define TARGET_FDRESET TARGET_IO(2, 0x54)
|
||||
#define TARGET_FDRAWCMD TARGET_IO(2, 0x58)
|
||||
#define TARGET_FDTWADDLE TARGET_IO(2, 0x59)
|
||||
#define TARGET_FDEJECT TARGET_IO(2, 0x5a)
|
||||
|
||||
#define TARGET_FIBMAP TARGET_IO(0x00,1) /* bmap access */
|
||||
#define TARGET_FIGETBSZ TARGET_IO(0x00,2) /* get the block size used for bmap */
|
||||
|
||||
|
@ -134,6 +134,8 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
abi_ulong frame_addr;
|
||||
struct target_rt_sigframe *frame;
|
||||
uint32_t ra;
|
||||
bool abi_call0;
|
||||
unsigned base;
|
||||
int i;
|
||||
|
||||
frame_addr = get_sigframe(ka, env, sizeof(*frame));
|
||||
@ -182,20 +184,27 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
__put_user(0x00, &frame->retcode[5]);
|
||||
#endif
|
||||
}
|
||||
env->sregs[PS] = PS_UM | (3 << PS_RING_SHIFT);
|
||||
if (xtensa_option_enabled(env->config, XTENSA_OPTION_WINDOWED_REGISTER)) {
|
||||
env->sregs[PS] |= PS_WOE | (1 << PS_CALLINC_SHIFT);
|
||||
}
|
||||
memset(env->regs, 0, sizeof(env->regs));
|
||||
env->pc = ka->_sa_handler;
|
||||
env->regs[1] = frame_addr;
|
||||
env->sregs[WINDOW_BASE] = 0;
|
||||
env->sregs[WINDOW_START] = 1;
|
||||
|
||||
env->regs[4] = (ra & 0x3fffffff) | 0x40000000;
|
||||
env->regs[6] = sig;
|
||||
env->regs[7] = frame_addr + offsetof(struct target_rt_sigframe, info);
|
||||
env->regs[8] = frame_addr + offsetof(struct target_rt_sigframe, uc);
|
||||
abi_call0 = (env->sregs[PS] & PS_WOE) == 0;
|
||||
env->sregs[PS] = PS_UM | (3 << PS_RING_SHIFT);
|
||||
|
||||
if (abi_call0) {
|
||||
base = 0;
|
||||
env->regs[base] = ra;
|
||||
} else {
|
||||
env->sregs[PS] |= PS_WOE | (1 << PS_CALLINC_SHIFT);
|
||||
base = 4;
|
||||
env->regs[base] = (ra & 0x3fffffff) | 0x40000000;
|
||||
}
|
||||
env->regs[base + 2] = sig;
|
||||
env->regs[base + 3] = frame_addr + offsetof(struct target_rt_sigframe,
|
||||
info);
|
||||
env->regs[base + 4] = frame_addr + offsetof(struct target_rt_sigframe, uc);
|
||||
unlock_user_struct(frame, frame_addr, 1);
|
||||
return;
|
||||
|
||||
|
@ -53,6 +53,20 @@ static bool xtensa_cpu_has_work(CPUState *cs)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
static bool abi_call0;
|
||||
|
||||
void xtensa_set_abi_call0(void)
|
||||
{
|
||||
abi_call0 = true;
|
||||
}
|
||||
|
||||
bool xtensa_abi_call0(void)
|
||||
{
|
||||
return abi_call0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* CPUClass::reset() */
|
||||
static void xtensa_cpu_reset(CPUState *s)
|
||||
{
|
||||
@ -70,10 +84,12 @@ static void xtensa_cpu_reset(CPUState *s)
|
||||
XTENSA_OPTION_INTERRUPT) ? 0x1f : 0x10;
|
||||
env->pending_irq_level = 0;
|
||||
#else
|
||||
env->sregs[PS] =
|
||||
(xtensa_option_enabled(env->config,
|
||||
XTENSA_OPTION_WINDOWED_REGISTER) ? PS_WOE : 0) |
|
||||
PS_UM | (3 << PS_RING_SHIFT);
|
||||
env->sregs[PS] = PS_UM | (3 << PS_RING_SHIFT);
|
||||
if (xtensa_option_enabled(env->config,
|
||||
XTENSA_OPTION_WINDOWED_REGISTER) &&
|
||||
!xtensa_abi_call0()) {
|
||||
env->sregs[PS] |= PS_WOE;
|
||||
}
|
||||
#endif
|
||||
env->sregs[VECBASE] = env->config->vecbase;
|
||||
env->sregs[IBREAKENABLE] = 0;
|
||||
|
@ -673,6 +673,9 @@ static inline MemoryRegion *xtensa_get_er_region(CPUXtensaState *env)
|
||||
{
|
||||
return env->system_er;
|
||||
}
|
||||
#else
|
||||
void xtensa_set_abi_call0(void);
|
||||
bool xtensa_abi_call0(void);
|
||||
#endif
|
||||
|
||||
static inline uint32_t xtensa_replicate_windowstart(CPUXtensaState *env)
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include <sys/syscall.h>
|
||||
#include <asm/unistd.h>
|
||||
|
||||
static int memfd_create(const char *name, unsigned int flags)
|
||||
int memfd_create(const char *name, unsigned int flags)
|
||||
{
|
||||
#ifdef __NR_memfd_create
|
||||
return syscall(__NR_memfd_create, name, flags);
|
||||
|
Loading…
Reference in New Issue
Block a user