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:
Peter Maydell 2019-09-12 16:17:26 +01:00
commit a30cb4b1f2
11 changed files with 175 additions and 51 deletions

View File

@ -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);

View File

@ -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)
{

View File

@ -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;

View File

@ -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)

View File

@ -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);
}

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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);