linux-user pull request 20230512-v4
add open_tree(), move_mount() add /proc/cpuinfo for riscv fixes and cleanup -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAmRkiZISHGxhdXJlbnRA dml2aWVyLmV1AAoJEPMMOL0/L748FdIP/RC1JaCftkP7ajAstNbZLMLegMxjUYHV TrdhsMOsm804ZmLgTqqfS3bJ080mIHup0xUnHBckcEtUcwaz54cJ1BAR2WlM3/8A t3fHMt3PDkh3OPd/3AnmpLE8XRh7yBztirPYfZc6SKqnFzT0TZrwBoQnwprEnZ5r c0gbrgLZLunZhrWU1BbQmuIufW1qDoQo4PzwnyZeux1fHA1/v/dx3wgSLpv3V4k6 x0Kj8TvtMUU4/io2RqYF4jKopfhwsh0jnr9rlOmydOExalKq1VbRptJI2UC4KVOY MZuApF1EaZfrW+v/WSlvmzaZ/zRzP1L0X3Xh0wB4J9Rj3057/elXr6bi+R+rM46p xGTcti9ahWKP2J4/xrazRw2lfPsLcw/YbqVGG79AX1xLJPCiWq6lamzc/g3ptFnx F/RRETe65z7apzF/nzU7SDOsMdN5p4/fMb1SysLuAov5OepNVjNVWyiTgqOHB5uC ye+lOYkkvk+qRdMbls/fIcjDQ3C4AjoBWj4QlgRc0/Qf6ac4TkVjzPa70Y6eyzzS LEV9D4fXD8EZgYWENNGmbbKPNbtfqc9uR6gXdgkEsKDx/rf5IMf1d6r1C99dhB3A nbu0JpFKKY2lhD2oGVPDE3UQMW9DXXhZpDApUBsLNiEwfuoXZee+apH+6jc8tbn6 r+8LFB1mM9os =NfIV -----END PGP SIGNATURE----- Merge tag 'linux-user-for-8.1-pull-request' of https://github.com/vivier/qemu into staging linux-user pull request 20230512-v4 add open_tree(), move_mount() add /proc/cpuinfo for riscv fixes and cleanup # -----BEGIN PGP SIGNATURE----- # # iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAmRkiZISHGxhdXJlbnRA # dml2aWVyLmV1AAoJEPMMOL0/L748FdIP/RC1JaCftkP7ajAstNbZLMLegMxjUYHV # TrdhsMOsm804ZmLgTqqfS3bJ080mIHup0xUnHBckcEtUcwaz54cJ1BAR2WlM3/8A # t3fHMt3PDkh3OPd/3AnmpLE8XRh7yBztirPYfZc6SKqnFzT0TZrwBoQnwprEnZ5r # c0gbrgLZLunZhrWU1BbQmuIufW1qDoQo4PzwnyZeux1fHA1/v/dx3wgSLpv3V4k6 # x0Kj8TvtMUU4/io2RqYF4jKopfhwsh0jnr9rlOmydOExalKq1VbRptJI2UC4KVOY # MZuApF1EaZfrW+v/WSlvmzaZ/zRzP1L0X3Xh0wB4J9Rj3057/elXr6bi+R+rM46p # xGTcti9ahWKP2J4/xrazRw2lfPsLcw/YbqVGG79AX1xLJPCiWq6lamzc/g3ptFnx # F/RRETe65z7apzF/nzU7SDOsMdN5p4/fMb1SysLuAov5OepNVjNVWyiTgqOHB5uC # ye+lOYkkvk+qRdMbls/fIcjDQ3C4AjoBWj4QlgRc0/Qf6ac4TkVjzPa70Y6eyzzS # LEV9D4fXD8EZgYWENNGmbbKPNbtfqc9uR6gXdgkEsKDx/rf5IMf1d6r1C99dhB3A # nbu0JpFKKY2lhD2oGVPDE3UQMW9DXXhZpDApUBsLNiEwfuoXZee+apH+6jc8tbn6 # r+8LFB1mM9os # =NfIV # -----END PGP SIGNATURE----- # gpg: Signature made Wed 17 May 2023 01:00:18 AM PDT # gpg: using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C # gpg: issuer "laurent@vivier.eu" # gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [undefined] # gpg: aka "Laurent Vivier <laurent@vivier.eu>" [undefined] # gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C * tag 'linux-user-for-8.1-pull-request' of https://github.com/vivier/qemu: linux-user: fix getgroups/setgroups allocations linux-user: Fix mips fp64 executables loading linux-user: Don't require PROT_READ for mincore linux-user: Add new flag VERIFY_NONE linux-user/main: Use list_cpus() instead of cpu_list() linux-user: Add open_tree() syscall linux-user: Add move_mount() syscall linux-user: report ENOTTY for unknown ioctls linux-user: Emulate /proc/cpuinfo output for riscv Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
19200a0edf
@ -359,10 +359,7 @@ static void handle_arg_cpu(const char *arg)
|
||||
{
|
||||
cpu_model = strdup(arg);
|
||||
if (cpu_model == NULL || is_help_option(cpu_model)) {
|
||||
/* XXX: implement xxx_cpu_list for targets that still miss it */
|
||||
#if defined(cpu_list)
|
||||
cpu_list();
|
||||
#endif
|
||||
list_cpus();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
@ -290,7 +290,10 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
|
||||
env->CP0_Status |= (1 << CP0St_FR);
|
||||
env->hflags |= MIPS_HFLAG_F64;
|
||||
}
|
||||
} else if (!prog_req.fre && !prog_req.frdefault &&
|
||||
} else if (prog_req.fr1) {
|
||||
env->CP0_Status |= (1 << CP0St_FR);
|
||||
env->hflags |= MIPS_HFLAG_F64;
|
||||
} else if (!prog_req.fre && !prog_req.frdefault &&
|
||||
!prog_req.fr1 && !prog_req.single && !prog_req.soft) {
|
||||
fprintf(stderr, "qemu: Can't find a matching FPU mode\n");
|
||||
exit(1);
|
||||
|
@ -168,6 +168,7 @@ abi_long do_brk(abi_ulong new_brk);
|
||||
|
||||
/* user access */
|
||||
|
||||
#define VERIFY_NONE 0
|
||||
#define VERIFY_READ PAGE_READ
|
||||
#define VERIFY_WRITE (PAGE_READ | PAGE_WRITE)
|
||||
|
||||
|
@ -5747,7 +5747,7 @@ static abi_long do_ioctl(int fd, int cmd, abi_long arg)
|
||||
if (ie->target_cmd == 0) {
|
||||
qemu_log_mask(
|
||||
LOG_UNIMP, "Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
|
||||
return -TARGET_ENOSYS;
|
||||
return -TARGET_ENOTTY;
|
||||
}
|
||||
if (ie->target_cmd == cmd)
|
||||
break;
|
||||
@ -5759,7 +5759,7 @@ static abi_long do_ioctl(int fd, int cmd, abi_long arg)
|
||||
} else if (!ie->host_cmd) {
|
||||
/* Some architectures define BSD ioctls in their headers
|
||||
that are not implemented in Linux. */
|
||||
return -TARGET_ENOSYS;
|
||||
return -TARGET_ENOTTY;
|
||||
}
|
||||
|
||||
switch(arg_type[0]) {
|
||||
@ -5817,7 +5817,7 @@ static abi_long do_ioctl(int fd, int cmd, abi_long arg)
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"Unsupported ioctl type: cmd=0x%04lx type=%d\n",
|
||||
(long)cmd, arg_type[0]);
|
||||
ret = -TARGET_ENOSYS;
|
||||
ret = -TARGET_ENOTTY;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
@ -8231,7 +8231,8 @@ void target_exception_dump(CPUArchState *env, const char *fmt, int code)
|
||||
}
|
||||
|
||||
#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN || \
|
||||
defined(TARGET_SPARC) || defined(TARGET_M68K) || defined(TARGET_HPPA)
|
||||
defined(TARGET_SPARC) || defined(TARGET_M68K) || defined(TARGET_HPPA) || \
|
||||
defined(TARGET_RISCV)
|
||||
static int is_proc(const char *filename, const char *entry)
|
||||
{
|
||||
return strcmp(filename, entry) == 0;
|
||||
@ -8309,6 +8310,35 @@ static int open_cpuinfo(CPUArchState *cpu_env, int fd)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_RISCV)
|
||||
static int open_cpuinfo(CPUArchState *cpu_env, int fd)
|
||||
{
|
||||
int i;
|
||||
int num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
RISCVCPU *cpu = env_archcpu(cpu_env);
|
||||
const RISCVCPUConfig *cfg = riscv_cpu_cfg((CPURISCVState *) cpu_env);
|
||||
char *isa_string = riscv_isa_string(cpu);
|
||||
const char *mmu;
|
||||
|
||||
if (cfg->mmu) {
|
||||
mmu = (cpu_env->xl == MXL_RV32) ? "sv32" : "sv48";
|
||||
} else {
|
||||
mmu = "none";
|
||||
}
|
||||
|
||||
for (i = 0; i < num_cpus; i++) {
|
||||
dprintf(fd, "processor\t: %d\n", i);
|
||||
dprintf(fd, "hart\t\t: %d\n", i);
|
||||
dprintf(fd, "isa\t\t: %s\n", isa_string);
|
||||
dprintf(fd, "mmu\t\t: %s\n", mmu);
|
||||
dprintf(fd, "uarch\t\t: qemu\n\n");
|
||||
}
|
||||
|
||||
g_free(isa_string);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_M68K)
|
||||
static int open_hardware(CPUArchState *cpu_env, int fd)
|
||||
{
|
||||
@ -8333,7 +8363,7 @@ static int do_openat(CPUArchState *cpu_env, int dirfd, const char *pathname, int
|
||||
#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN
|
||||
{ "/proc/net/route", open_net_route, is_proc },
|
||||
#endif
|
||||
#if defined(TARGET_SPARC) || defined(TARGET_HPPA)
|
||||
#if defined(TARGET_SPARC) || defined(TARGET_HPPA) || defined(TARGET_RISCV)
|
||||
{ "/proc/cpuinfo", open_cpuinfo, is_proc },
|
||||
#endif
|
||||
#if defined(TARGET_M68K)
|
||||
@ -8746,6 +8776,18 @@ static int do_getdents64(abi_long dirfd, abi_long arg2, abi_long count)
|
||||
_syscall2(int, pivot_root, const char *, new_root, const char *, put_old)
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_open_tree) && defined(__NR_open_tree)
|
||||
#define __NR_sys_open_tree __NR_open_tree
|
||||
_syscall3(int, sys_open_tree, int, __dfd, const char *, __filename,
|
||||
unsigned int, __flags)
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_move_mount) && defined(__NR_move_mount)
|
||||
#define __NR_sys_move_mount __NR_move_mount
|
||||
_syscall5(int, sys_move_mount, int, __from_dfd, const char *, __from_pathname,
|
||||
int, __to_dfd, const char *, __to_pathname, unsigned int, flag)
|
||||
#endif
|
||||
|
||||
/* This is an internal helper for do_syscall so that it is easier
|
||||
* to have a single return point, so that actions, such as logging
|
||||
* of syscall results, can be performed.
|
||||
@ -9139,6 +9181,60 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
|
||||
unlock_user(p, arg1, 0);
|
||||
return ret;
|
||||
#endif
|
||||
#if defined(TARGET_NR_move_mount) && defined(__NR_move_mount)
|
||||
case TARGET_NR_move_mount:
|
||||
{
|
||||
void *p2, *p4;
|
||||
|
||||
if (!arg2 || !arg4) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
|
||||
p2 = lock_user_string(arg2);
|
||||
if (!p2) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
|
||||
p4 = lock_user_string(arg4);
|
||||
if (!p4) {
|
||||
unlock_user(p2, arg2, 0);
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
ret = get_errno(sys_move_mount(arg1, p2, arg3, p4, arg5));
|
||||
|
||||
unlock_user(p2, arg2, 0);
|
||||
unlock_user(p4, arg4, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#if defined(TARGET_NR_open_tree) && defined(__NR_open_tree)
|
||||
case TARGET_NR_open_tree:
|
||||
{
|
||||
void *p2;
|
||||
int host_flags;
|
||||
|
||||
if (!arg2) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
|
||||
p2 = lock_user_string(arg2);
|
||||
if (!p2) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
|
||||
host_flags = arg3 & ~TARGET_O_CLOEXEC;
|
||||
if (arg3 & TARGET_O_CLOEXEC) {
|
||||
host_flags |= O_CLOEXEC;
|
||||
}
|
||||
|
||||
ret = get_errno(sys_open_tree(arg1, p2, host_flags));
|
||||
|
||||
unlock_user(p2, arg2, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#ifdef TARGET_NR_stime /* not on alpha */
|
||||
case TARGET_NR_stime:
|
||||
{
|
||||
@ -11475,39 +11571,58 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
|
||||
{
|
||||
int gidsetsize = arg1;
|
||||
target_id *target_grouplist;
|
||||
gid_t *grouplist;
|
||||
g_autofree gid_t *grouplist = NULL;
|
||||
int i;
|
||||
|
||||
grouplist = alloca(gidsetsize * sizeof(gid_t));
|
||||
ret = get_errno(getgroups(gidsetsize, grouplist));
|
||||
if (gidsetsize == 0)
|
||||
return ret;
|
||||
if (!is_error(ret)) {
|
||||
target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0);
|
||||
if (!target_grouplist)
|
||||
return -TARGET_EFAULT;
|
||||
for(i = 0;i < ret; i++)
|
||||
target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
|
||||
unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id));
|
||||
if (gidsetsize > NGROUPS_MAX) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
if (gidsetsize > 0) {
|
||||
grouplist = g_try_new(gid_t, gidsetsize);
|
||||
if (!grouplist) {
|
||||
return -TARGET_ENOMEM;
|
||||
}
|
||||
}
|
||||
ret = get_errno(getgroups(gidsetsize, grouplist));
|
||||
if (!is_error(ret) && gidsetsize > 0) {
|
||||
target_grouplist = lock_user(VERIFY_WRITE, arg2,
|
||||
gidsetsize * sizeof(target_id), 0);
|
||||
if (!target_grouplist) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
for (i = 0; i < ret; i++) {
|
||||
target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
|
||||
}
|
||||
unlock_user(target_grouplist, arg2,
|
||||
gidsetsize * sizeof(target_id));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
case TARGET_NR_setgroups:
|
||||
{
|
||||
int gidsetsize = arg1;
|
||||
target_id *target_grouplist;
|
||||
gid_t *grouplist = NULL;
|
||||
g_autofree gid_t *grouplist = NULL;
|
||||
int i;
|
||||
if (gidsetsize) {
|
||||
grouplist = alloca(gidsetsize * sizeof(gid_t));
|
||||
target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1);
|
||||
|
||||
if (gidsetsize > NGROUPS_MAX || gidsetsize < 0) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
if (gidsetsize > 0) {
|
||||
grouplist = g_try_new(gid_t, gidsetsize);
|
||||
if (!grouplist) {
|
||||
return -TARGET_ENOMEM;
|
||||
}
|
||||
target_grouplist = lock_user(VERIFY_READ, arg2,
|
||||
gidsetsize * sizeof(target_id), 1);
|
||||
if (!target_grouplist) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
for (i = 0; i < gidsetsize; i++) {
|
||||
grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
|
||||
}
|
||||
unlock_user(target_grouplist, arg2, 0);
|
||||
unlock_user(target_grouplist, arg2,
|
||||
gidsetsize * sizeof(target_id));
|
||||
}
|
||||
return get_errno(setgroups(gidsetsize, grouplist));
|
||||
}
|
||||
@ -11792,41 +11907,59 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
|
||||
{
|
||||
int gidsetsize = arg1;
|
||||
uint32_t *target_grouplist;
|
||||
gid_t *grouplist;
|
||||
g_autofree gid_t *grouplist = NULL;
|
||||
int i;
|
||||
|
||||
grouplist = alloca(gidsetsize * sizeof(gid_t));
|
||||
if (gidsetsize > NGROUPS_MAX) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
if (gidsetsize > 0) {
|
||||
grouplist = g_try_new(gid_t, gidsetsize);
|
||||
if (!grouplist) {
|
||||
return -TARGET_ENOMEM;
|
||||
}
|
||||
}
|
||||
ret = get_errno(getgroups(gidsetsize, grouplist));
|
||||
if (gidsetsize == 0)
|
||||
return ret;
|
||||
if (!is_error(ret)) {
|
||||
target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
|
||||
if (!is_error(ret) && gidsetsize > 0) {
|
||||
target_grouplist = lock_user(VERIFY_WRITE, arg2,
|
||||
gidsetsize * 4, 0);
|
||||
if (!target_grouplist) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
for(i = 0;i < ret; i++)
|
||||
for (i = 0; i < ret; i++) {
|
||||
target_grouplist[i] = tswap32(grouplist[i]);
|
||||
}
|
||||
unlock_user(target_grouplist, arg2, gidsetsize * 4);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
#endif
|
||||
#ifdef TARGET_NR_setgroups32
|
||||
case TARGET_NR_setgroups32:
|
||||
{
|
||||
int gidsetsize = arg1;
|
||||
uint32_t *target_grouplist;
|
||||
gid_t *grouplist;
|
||||
g_autofree gid_t *grouplist = NULL;
|
||||
int i;
|
||||
|
||||
grouplist = alloca(gidsetsize * sizeof(gid_t));
|
||||
target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
|
||||
if (!target_grouplist) {
|
||||
return -TARGET_EFAULT;
|
||||
if (gidsetsize > NGROUPS_MAX || gidsetsize < 0) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
if (gidsetsize > 0) {
|
||||
grouplist = g_try_new(gid_t, gidsetsize);
|
||||
if (!grouplist) {
|
||||
return -TARGET_ENOMEM;
|
||||
}
|
||||
target_grouplist = lock_user(VERIFY_READ, arg2,
|
||||
gidsetsize * 4, 1);
|
||||
if (!target_grouplist) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
for (i = 0; i < gidsetsize; i++) {
|
||||
grouplist[i] = tswap32(target_grouplist[i]);
|
||||
}
|
||||
unlock_user(target_grouplist, arg2, 0);
|
||||
}
|
||||
for(i = 0;i < gidsetsize; i++)
|
||||
grouplist[i] = tswap32(target_grouplist[i]);
|
||||
unlock_user(target_grouplist, arg2, 0);
|
||||
return get_errno(setgroups(gidsetsize, grouplist));
|
||||
}
|
||||
#endif
|
||||
@ -11897,7 +12030,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
|
||||
#ifdef TARGET_NR_mincore
|
||||
case TARGET_NR_mincore:
|
||||
{
|
||||
void *a = lock_user(VERIFY_READ, arg1, arg2, 0);
|
||||
void *a = lock_user(VERIFY_NONE, arg1, arg2, 0);
|
||||
if (!a) {
|
||||
return -TARGET_ENOMEM;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user