Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-6.0…
Browse files Browse the repository at this point in the history
…-pull-request' into staging

Add MIPS Loongson 2F/3A
sparc64 bug fix
Implement copy_file_range
Add most IFTUN ioctls
Fix mremap

# gpg: Signature made Fri 18 Dec 2020 10:23:43 GMT
# 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-6.0-pull-request:
  linux-user/sparc: Handle tstate in sparc64_get/set_context()
  linux-user/sparc: Don't restore %g7 in sparc64_set_context()
  linux-user/sparc: Remove unneeded checks of 'err' from sparc64_get_context()
  linux-user/sparc: Correct sparc64_get/set_context() FPU handling
  linux-user: Add most IFTUN ioctls
  linux-user: Implement copy_file_range
  docs/user: Display linux-user binaries nicely
  linux-user: Add support for MIPS Loongson 2F/3A
  linux-user/elfload: Update HWCAP bits from linux 5.7
  linux-user/elfload: Introduce MIPS GET_FEATURE_REG_EQU() macro
  linux-user/elfload: Introduce MIPS GET_FEATURE_REG_SET() macro
  linux-user/elfload: Rename MIPS GET_FEATURE() as GET_FEATURE_INSN()
  linux-user/elfload: Move GET_FEATURE macro out of get_elf_hwcap() body
  linux-user/mmap.c: check range of mremap result in target address space

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Dec 31, 2020
2 parents 65a3c59 + 7a5805a commit 091774b
Show file tree
Hide file tree
Showing 10 changed files with 333 additions and 108 deletions.
99 changes: 56 additions & 43 deletions docs/user/main.rst
Expand Up @@ -170,68 +170,81 @@ QEMU_STRACE
Other binaries
~~~~~~~~~~~~~~

user mode (Alpha)
``qemu-alpha`` TODO.
- user mode (Alpha)

user mode (Arm)
``qemu-armeb`` TODO.
* ``qemu-alpha`` TODO.

user mode (Arm)
``qemu-arm`` is also capable of running Arm \"Angel\" semihosted ELF
binaries (as implemented by the arm-elf and arm-eabi Newlib/GDB
configurations), and arm-uclinux bFLT format binaries.
- user mode (Arm)

user mode (ColdFire)
user mode (M68K)
``qemu-m68k`` is capable of running semihosted binaries using the BDM
(m5xxx-ram-hosted.ld) or m68k-sim (sim.ld) syscall interfaces, and
coldfire uClinux bFLT format binaries.
* ``qemu-armeb`` TODO.

The binary format is detected automatically.
* ``qemu-arm`` is also capable of running Arm \"Angel\" semihosted ELF
binaries (as implemented by the arm-elf and arm-eabi Newlib/GDB
configurations), and arm-uclinux bFLT format binaries.

user mode (Cris)
``qemu-cris`` TODO.
- user mode (ColdFire)

user mode (i386)
``qemu-i386`` TODO. ``qemu-x86_64`` TODO.
- user mode (M68K)

user mode (Microblaze)
``qemu-microblaze`` TODO.
* ``qemu-m68k`` is capable of running semihosted binaries using the BDM
(m5xxx-ram-hosted.ld) or m68k-sim (sim.ld) syscall interfaces, and
coldfire uClinux bFLT format binaries.

user mode (MIPS)
``qemu-mips`` executes 32-bit big endian MIPS binaries (MIPS O32 ABI).
The binary format is detected automatically.

``qemu-mipsel`` executes 32-bit little endian MIPS binaries (MIPS O32
ABI).
- user mode (Cris)

``qemu-mips64`` executes 64-bit big endian MIPS binaries (MIPS N64 ABI).
* ``qemu-cris`` TODO.

``qemu-mips64el`` executes 64-bit little endian MIPS binaries (MIPS N64
ABI).
- user mode (i386)

``qemu-mipsn32`` executes 32-bit big endian MIPS binaries (MIPS N32
ABI).
* ``qemu-i386`` TODO.
* ``qemu-x86_64`` TODO.

``qemu-mipsn32el`` executes 32-bit little endian MIPS binaries (MIPS N32
ABI).
- user mode (Microblaze)

user mode (NiosII)
``qemu-nios2`` TODO.
* ``qemu-microblaze`` TODO.

user mode (PowerPC)
``qemu-ppc64abi32`` TODO. ``qemu-ppc64`` TODO. ``qemu-ppc`` TODO.
- user mode (MIPS)

user mode (SH4)
``qemu-sh4eb`` TODO. ``qemu-sh4`` TODO.
* ``qemu-mips`` executes 32-bit big endian MIPS binaries (MIPS O32 ABI).

user mode (SPARC)
``qemu-sparc`` can execute Sparc32 binaries (Sparc32 CPU, 32 bit ABI).
* ``qemu-mipsel`` executes 32-bit little endian MIPS binaries (MIPS O32 ABI).

``qemu-sparc32plus`` can execute Sparc32 and SPARC32PLUS binaries
(Sparc64 CPU, 32 bit ABI).
* ``qemu-mips64`` executes 64-bit big endian MIPS binaries (MIPS N64 ABI).

``qemu-sparc64`` can execute some Sparc64 (Sparc64 CPU, 64 bit ABI) and
SPARC32PLUS binaries (Sparc64 CPU, 32 bit ABI).
* ``qemu-mips64el`` executes 64-bit little endian MIPS binaries (MIPS N64
ABI).

* ``qemu-mipsn32`` executes 32-bit big endian MIPS binaries (MIPS N32 ABI).

* ``qemu-mipsn32el`` executes 32-bit little endian MIPS binaries (MIPS N32
ABI).

- user mode (NiosII)

* ``qemu-nios2`` TODO.

- user mode (PowerPC)

* ``qemu-ppc64abi32`` TODO.
* ``qemu-ppc64`` TODO.
* ``qemu-ppc`` TODO.

- user mode (SH4)

* ``qemu-sh4eb`` TODO.
* ``qemu-sh4`` TODO.

- user mode (SPARC)

* ``qemu-sparc`` can execute Sparc32 binaries (Sparc32 CPU, 32 bit ABI).

* ``qemu-sparc32plus`` can execute Sparc32 and SPARC32PLUS binaries
(Sparc64 CPU, 32 bit ABI).

* ``qemu-sparc64`` can execute some Sparc64 (Sparc64 CPU, 64 bit ABI) and
SPARC32PLUS binaries (Sparc64 CPU, 32 bit ABI).

BSD User space emulator
-----------------------
Expand Down
43 changes: 36 additions & 7 deletions linux-user/elfload.c
Expand Up @@ -7,6 +7,7 @@

#include "qemu.h"
#include "disas/disas.h"
#include "qemu/bitops.h"
#include "qemu/path.h"
#include "qemu/queue.h"
#include "qemu/guest-random.h"
Expand Down Expand Up @@ -985,26 +986,54 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMIPSState *e
enum {
HWCAP_MIPS_R6 = (1 << 0),
HWCAP_MIPS_MSA = (1 << 1),
HWCAP_MIPS_CRC32 = (1 << 2),
HWCAP_MIPS_MIPS16 = (1 << 3),
HWCAP_MIPS_MDMX = (1 << 4),
HWCAP_MIPS_MIPS3D = (1 << 5),
HWCAP_MIPS_SMARTMIPS = (1 << 6),
HWCAP_MIPS_DSP = (1 << 7),
HWCAP_MIPS_DSP2 = (1 << 8),
HWCAP_MIPS_DSP3 = (1 << 9),
HWCAP_MIPS_MIPS16E2 = (1 << 10),
HWCAP_LOONGSON_MMI = (1 << 11),
HWCAP_LOONGSON_EXT = (1 << 12),
HWCAP_LOONGSON_EXT2 = (1 << 13),
HWCAP_LOONGSON_CPUCFG = (1 << 14),
};

#define ELF_HWCAP get_elf_hwcap()

#define GET_FEATURE_INSN(_flag, _hwcap) \
do { if (cpu->env.insn_flags & (_flag)) { hwcaps |= _hwcap; } } while (0)

#define GET_FEATURE_REG_SET(_reg, _mask, _hwcap) \
do { if (cpu->env._reg & (_mask)) { hwcaps |= _hwcap; } } while (0)

#define GET_FEATURE_REG_EQU(_reg, _start, _length, _val, _hwcap) \
do { \
if (extract32(cpu->env._reg, (_start), (_length)) == (_val)) { \
hwcaps |= _hwcap; \
} \
} while (0)

static uint32_t get_elf_hwcap(void)
{
MIPSCPU *cpu = MIPS_CPU(thread_cpu);
uint32_t hwcaps = 0;

#define GET_FEATURE(flag, hwcap) \
do { if (cpu->env.insn_flags & (flag)) { hwcaps |= hwcap; } } while (0)

GET_FEATURE(ISA_MIPS32R6 | ISA_MIPS64R6, HWCAP_MIPS_R6);
GET_FEATURE(ASE_MSA, HWCAP_MIPS_MSA);

#undef GET_FEATURE
GET_FEATURE_REG_EQU(CP0_Config0, CP0C0_AR, CP0C0_AR_LENGTH,
2, HWCAP_MIPS_R6);
GET_FEATURE_REG_SET(CP0_Config3, 1 << CP0C3_MSAP, HWCAP_MIPS_MSA);
GET_FEATURE_INSN(ASE_LMMI, HWCAP_LOONGSON_MMI);
GET_FEATURE_INSN(ASE_LEXT, HWCAP_LOONGSON_EXT);

return hwcaps;
}

#undef GET_FEATURE_REG_EQU
#undef GET_FEATURE_REG_SET
#undef GET_FEATURE_INSN

#endif /* TARGET_MIPS */

#ifdef TARGET_MICROBLAZE
Expand Down
46 changes: 46 additions & 0 deletions linux-user/ioctls.h
Expand Up @@ -720,3 +720,49 @@
IOCTL(KCOV_DISABLE, 0, TYPE_NULL)
IOCTL(KCOV_INIT_TRACE, IOC_R, TYPE_ULONG)
#endif

IOCTL(TUNSETDEBUG, IOC_W, TYPE_INT)
IOCTL(TUNSETIFF, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
IOCTL(TUNSETPERSIST, IOC_W, TYPE_INT)
IOCTL(TUNSETOWNER, IOC_W, TYPE_INT)
IOCTL(TUNSETLINK, IOC_W, TYPE_INT)
IOCTL(TUNSETGROUP, IOC_W, TYPE_INT)
IOCTL(TUNGETFEATURES, IOC_R, MK_PTR(TYPE_INT))
IOCTL(TUNSETOFFLOAD, IOC_W, TYPE_LONG)
IOCTL_SPECIAL(TUNSETTXFILTER, IOC_W, do_ioctl_TUNSETTXFILTER,
/*
* We can't represent `struct tun_filter` in thunk so leaving
* it uninterpreted. do_ioctl_TUNSETTXFILTER will do the
* conversion.
*/
TYPE_PTRVOID)
IOCTL(TUNGETIFF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
IOCTL(TUNGETSNDBUF, IOC_R, MK_PTR(TYPE_INT))
IOCTL(TUNSETSNDBUF, IOC_W, MK_PTR(TYPE_INT))
/*
* TUNATTACHFILTER and TUNDETACHFILTER are not supported. Linux kernel keeps a
* user pointer in TUNATTACHFILTER, which we are not able to correctly handle.
*/
IOCTL(TUNGETVNETHDRSZ, IOC_R, MK_PTR(TYPE_INT))
IOCTL(TUNSETVNETHDRSZ, IOC_W, MK_PTR(TYPE_INT))
IOCTL(TUNSETQUEUE, IOC_W, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
IOCTL(TUNSETIFINDEX , IOC_W, MK_PTR(TYPE_INT))
/* TUNGETFILTER is not supported: see TUNATTACHFILTER. */
IOCTL(TUNSETVNETLE, IOC_W, MK_PTR(TYPE_INT))
IOCTL(TUNGETVNETLE, IOC_R, MK_PTR(TYPE_INT))
#ifdef TUNSETVNETBE
IOCTL(TUNSETVNETBE, IOC_W, MK_PTR(TYPE_INT))
IOCTL(TUNGETVNETBE, IOC_R, MK_PTR(TYPE_INT))
#endif
#ifdef TUNSETSTEERINGEBPF
IOCTL(TUNSETSTEERINGEBPF, IOC_W, MK_PTR(TYPE_INT))
#endif
#ifdef TUNSETFILTEREBPF
IOCTL(TUNSETFILTEREBPF, IOC_W, MK_PTR(TYPE_INT))
#endif
#ifdef TUNSETCARRIER
IOCTL(TUNSETCARRIER, IOC_W, MK_PTR(TYPE_INT))
#endif
#ifdef TUNGETDEVNETNS
IOCTL(TUNGETDEVNETNS, IOC_R, TYPE_NULL)
#endif
21 changes: 12 additions & 9 deletions linux-user/mmap.c
Expand Up @@ -767,20 +767,23 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
}
if (prot == 0) {
host_addr = mremap(g2h(old_addr), old_size, new_size, flags);
if (host_addr != MAP_FAILED && reserved_va && old_size > new_size) {
mmap_reserve(old_addr + old_size, old_size - new_size);

if (host_addr != MAP_FAILED) {
/* Check if address fits target address space */
if (!guest_range_valid(h2g(host_addr), new_size)) {
/* Revert mremap() changes */
host_addr = mremap(g2h(old_addr), new_size, old_size,
flags);
errno = ENOMEM;
host_addr = MAP_FAILED;
} else if (reserved_va && old_size > new_size) {
mmap_reserve(old_addr + old_size, old_size - new_size);
}
}
} else {
errno = ENOMEM;
host_addr = MAP_FAILED;
}
/* Check if address fits target address space */
if ((unsigned long)host_addr + new_size > (abi_ulong)-1) {
/* Revert mremap() changes */
host_addr = mremap(g2h(old_addr), new_size, old_size, flags);
errno = ENOMEM;
host_addr = MAP_FAILED;
}
}

if (host_addr == MAP_FAILED) {
Expand Down

0 comments on commit 091774b

Please sign in to comment.