qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PULL 00/14] Linux user for 6.0 patches
@ 2020-12-18 10:23 Laurent Vivier
  2020-12-18 10:23 ` [PULL 01/14] linux-user/mmap.c: check range of mremap result in target address space Laurent Vivier
                   ` (14 more replies)
  0 siblings, 15 replies; 16+ messages in thread
From: Laurent Vivier @ 2020-12-18 10:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Laurent Vivier

The following changes since commit af3f37319cb1e1ca0c42842ecdbd1bcfc64a4b6f:

  Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' int=
o staging (2020-12-15 21:24:31 +0000)

are available in the Git repository at:

  git://github.com/vivier/qemu.git tags/linux-user-for-6.0-pull-request

for you to fetch changes up to 7a5805a08f942325b373643099f784cdac65c9ea:

  linux-user/sparc: Handle tstate in sparc64_get/set_context() (2020-12-18 11=
:23:29 +0100)

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

----------------------------------------------------------------

Andreas Schwab (1):
  linux-user: Implement copy_file_range

Peter Maydell (4):
  linux-user/sparc: Correct sparc64_get/set_context() FPU handling
  linux-user/sparc: Remove unneeded checks of 'err' from
    sparc64_get_context()
  linux-user/sparc: Don't restore %g7 in sparc64_set_context()
  linux-user/sparc: Handle tstate in sparc64_get/set_context()

Philippe Mathieu-Daud=C3=A9 (7):
  linux-user/elfload: Move GET_FEATURE macro out of get_elf_hwcap() body
  linux-user/elfload: Rename MIPS GET_FEATURE() as GET_FEATURE_INSN()
  linux-user/elfload: Introduce MIPS GET_FEATURE_REG_SET() macro
  linux-user/elfload: Introduce MIPS GET_FEATURE_REG_EQU() macro
  linux-user/elfload: Update HWCAP bits from linux 5.7
  linux-user: Add support for MIPS Loongson 2F/3A
  docs/user: Display linux-user binaries nicely

Shu-Chun Weng (1):
  linux-user: Add most IFTUN ioctls

Tobias Koch (1):
  linux-user/mmap.c: check range of mremap result in target address
    space

 docs/user/main.rst          | 99 +++++++++++++++++++++----------------
 linux-user/elfload.c        | 43 +++++++++++++---
 linux-user/ioctls.h         | 46 +++++++++++++++++
 linux-user/mmap.c           | 21 ++++----
 linux-user/sparc/signal.c   | 87 +++++++++++++++++---------------
 linux-user/syscall.c        | 79 +++++++++++++++++++++++++++++
 linux-user/syscall_defs.h   | 32 ++++++++++++
 target/mips/cpu.h           |  1 +
 target/sparc/cpu.h          | 28 +++++++++--
 target/sparc/int64_helper.c |  5 +-
 10 files changed, 333 insertions(+), 108 deletions(-)

--=20
2.29.2



^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PULL 01/14] linux-user/mmap.c: check range of mremap result in target address space
  2020-12-18 10:23 [PULL 00/14] Linux user for 6.0 patches Laurent Vivier
@ 2020-12-18 10:23 ` Laurent Vivier
  2020-12-18 10:23 ` [PULL 02/14] linux-user/elfload: Move GET_FEATURE macro out of get_elf_hwcap() body Laurent Vivier
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Laurent Vivier @ 2020-12-18 10:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Tobias Koch, Laurent Vivier

From: Tobias Koch <tobias.koch@nonterra.com>

If mremap succeeds, an additional check is performed to ensure that the
new address range fits into the target address space. This check was
previously perfomed in host address space, with the upper bound fixed to
abi_ulong.

This patch replaces the static check with a call to `guest_range_valid`,
performing the range check against the actual size of the target address
space. It also moves the corresponding block to prevent it from being
called incorrectly when the mapping itself fails.

Signed-off-by: Tobias Koch <tobias.koch@nonterra.com>
Message-Id: <20201028213833.26592-1-tobias.koch@nonterra.com>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/mmap.c | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 00c05e6a0f19..810653c50357 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -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) {
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 02/14] linux-user/elfload: Move GET_FEATURE macro out of get_elf_hwcap() body
  2020-12-18 10:23 [PULL 00/14] Linux user for 6.0 patches Laurent Vivier
  2020-12-18 10:23 ` [PULL 01/14] linux-user/mmap.c: check range of mremap result in target address space Laurent Vivier
@ 2020-12-18 10:23 ` Laurent Vivier
  2020-12-18 10:23 ` [PULL 03/14] linux-user/elfload: Rename MIPS GET_FEATURE() as GET_FEATURE_INSN() Laurent Vivier
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Laurent Vivier @ 2020-12-18 10:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Richard Henderson, Philippe Mathieu-Daudé, Laurent Vivier

From: Philippe Mathieu-Daudé <f4bug@amsat.org>

As we are going to add more macros, keep the function body clear.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20201214003215.344522-2-f4bug@amsat.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/elfload.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 0b02a926025e..aae28fd929dc 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -989,22 +989,22 @@ enum {
 
 #define ELF_HWCAP get_elf_hwcap()
 
+#define GET_FEATURE(_flag, _hwcap) \
+    do { if (cpu->env.insn_flags & (_flag)) { 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
-
     return hwcaps;
 }
 
+#undef GET_FEATURE
+
 #endif /* TARGET_MIPS */
 
 #ifdef TARGET_MICROBLAZE
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 03/14] linux-user/elfload: Rename MIPS GET_FEATURE() as GET_FEATURE_INSN()
  2020-12-18 10:23 [PULL 00/14] Linux user for 6.0 patches Laurent Vivier
  2020-12-18 10:23 ` [PULL 01/14] linux-user/mmap.c: check range of mremap result in target address space Laurent Vivier
  2020-12-18 10:23 ` [PULL 02/14] linux-user/elfload: Move GET_FEATURE macro out of get_elf_hwcap() body Laurent Vivier
@ 2020-12-18 10:23 ` Laurent Vivier
  2020-12-18 10:23 ` [PULL 04/14] linux-user/elfload: Introduce MIPS GET_FEATURE_REG_SET() macro Laurent Vivier
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Laurent Vivier @ 2020-12-18 10:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Richard Henderson, Philippe Mathieu-Daudé, Laurent Vivier

From: Philippe Mathieu-Daudé <f4bug@amsat.org>

We want to add macros similar to GET_FEATURE().
As this one use the 'insn_flags' field, rename it
GET_FEATURE_INSN().

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20201214003215.344522-3-f4bug@amsat.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/elfload.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index aae28fd929dc..0e1d7e7677c8 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -989,7 +989,7 @@ enum {
 
 #define ELF_HWCAP get_elf_hwcap()
 
-#define GET_FEATURE(_flag, _hwcap) \
+#define GET_FEATURE_INSN(_flag, _hwcap) \
     do { if (cpu->env.insn_flags & (_flag)) { hwcaps |= _hwcap; } } while (0)
 
 static uint32_t get_elf_hwcap(void)
@@ -997,13 +997,13 @@ static uint32_t get_elf_hwcap(void)
     MIPSCPU *cpu = MIPS_CPU(thread_cpu);
     uint32_t hwcaps = 0;
 
-    GET_FEATURE(ISA_MIPS32R6 | ISA_MIPS64R6, HWCAP_MIPS_R6);
-    GET_FEATURE(ASE_MSA, HWCAP_MIPS_MSA);
+    GET_FEATURE_INSN(ISA_MIPS32R6 | ISA_MIPS64R6, HWCAP_MIPS_R6);
+    GET_FEATURE_INSN(ASE_MSA, HWCAP_MIPS_MSA);
 
     return hwcaps;
 }
 
-#undef GET_FEATURE
+#undef GET_FEATURE_INSN
 
 #endif /* TARGET_MIPS */
 
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 04/14] linux-user/elfload: Introduce MIPS GET_FEATURE_REG_SET() macro
  2020-12-18 10:23 [PULL 00/14] Linux user for 6.0 patches Laurent Vivier
                   ` (2 preceding siblings ...)
  2020-12-18 10:23 ` [PULL 03/14] linux-user/elfload: Rename MIPS GET_FEATURE() as GET_FEATURE_INSN() Laurent Vivier
@ 2020-12-18 10:23 ` Laurent Vivier
  2020-12-18 10:23 ` [PULL 05/14] linux-user/elfload: Introduce MIPS GET_FEATURE_REG_EQU() macro Laurent Vivier
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Laurent Vivier @ 2020-12-18 10:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Richard Henderson, Philippe Mathieu-Daudé, Laurent Vivier

From: Philippe Mathieu-Daudé <f4bug@amsat.org>

ISA features are usually denoted in read-only bits from
CPU registers. Add the GET_FEATURE_REG_SET() macro which
checks if a CPU register has bits set.

Use the macro to check for MSA (which sets the MSAP bit of
the Config3 register when the ASE implementation is present).

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20201214003215.344522-4-f4bug@amsat.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/elfload.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 0e1d7e7677c8..b7c6d30723a3 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -992,17 +992,21 @@ enum {
 #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)
+
 static uint32_t get_elf_hwcap(void)
 {
     MIPSCPU *cpu = MIPS_CPU(thread_cpu);
     uint32_t hwcaps = 0;
 
     GET_FEATURE_INSN(ISA_MIPS32R6 | ISA_MIPS64R6, HWCAP_MIPS_R6);
-    GET_FEATURE_INSN(ASE_MSA, HWCAP_MIPS_MSA);
+    GET_FEATURE_REG_SET(CP0_Config3, 1 << CP0C3_MSAP, HWCAP_MIPS_MSA);
 
     return hwcaps;
 }
 
+#undef GET_FEATURE_REG_SET
 #undef GET_FEATURE_INSN
 
 #endif /* TARGET_MIPS */
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 05/14] linux-user/elfload: Introduce MIPS GET_FEATURE_REG_EQU() macro
  2020-12-18 10:23 [PULL 00/14] Linux user for 6.0 patches Laurent Vivier
                   ` (3 preceding siblings ...)
  2020-12-18 10:23 ` [PULL 04/14] linux-user/elfload: Introduce MIPS GET_FEATURE_REG_SET() macro Laurent Vivier
@ 2020-12-18 10:23 ` Laurent Vivier
  2020-12-18 10:23 ` [PULL 06/14] linux-user/elfload: Update HWCAP bits from linux 5.7 Laurent Vivier
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Laurent Vivier @ 2020-12-18 10:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Richard Henderson, Philippe Mathieu-Daudé, Laurent Vivier

From: Philippe Mathieu-Daudé <f4bug@amsat.org>

ISA features are usually denoted in read-only bits from
CPU registers. Add the GET_FEATURE_REG_EQU() macro which
checks if a CPU register has bits set to a specific value.

Use the macro to check the 'Architecture Revision' level
of the Config0 register, which is '2' when the Release 6
ISA is implemented.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20201214003215.344522-5-f4bug@amsat.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/elfload.c | 12 +++++++++++-
 target/mips/cpu.h    |  1 +
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index b7c6d30723a3..8f943f93ba75 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -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"
@@ -995,17 +996,26 @@ enum {
 #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;
 
-    GET_FEATURE_INSN(ISA_MIPS32R6 | ISA_MIPS64R6, HWCAP_MIPS_R6);
+    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);
 
     return hwcaps;
 }
 
+#undef GET_FEATURE_REG_EQU
 #undef GET_FEATURE_REG_SET
 #undef GET_FEATURE_INSN
 
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 3ac21d0e9c07..4cbc31c3e8d2 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -844,6 +844,7 @@ struct CPUMIPSState {
 #define CP0C0_MT   7     /*  9..7  */
 #define CP0C0_VI   3
 #define CP0C0_K0   0     /*  2..0  */
+#define CP0C0_AR_LENGTH 3
     int32_t CP0_Config1;
 #define CP0C1_M    31
 #define CP0C1_MMU  25    /* 30..25 */
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 06/14] linux-user/elfload: Update HWCAP bits from linux 5.7
  2020-12-18 10:23 [PULL 00/14] Linux user for 6.0 patches Laurent Vivier
                   ` (4 preceding siblings ...)
  2020-12-18 10:23 ` [PULL 05/14] linux-user/elfload: Introduce MIPS GET_FEATURE_REG_EQU() macro Laurent Vivier
@ 2020-12-18 10:23 ` Laurent Vivier
  2020-12-18 10:24 ` [PULL 07/14] linux-user: Add support for MIPS Loongson 2F/3A Laurent Vivier
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Laurent Vivier @ 2020-12-18 10:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: Richard Henderson, Philippe Mathieu-Daudé, Laurent Vivier

From: Philippe Mathieu-Daudé <f4bug@amsat.org>

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20201214003215.344522-6-f4bug@amsat.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/elfload.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 8f943f93ba75..0836e72b5ac3 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -986,6 +986,19 @@ 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()
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 07/14] linux-user: Add support for MIPS Loongson 2F/3A
  2020-12-18 10:23 [PULL 00/14] Linux user for 6.0 patches Laurent Vivier
                   ` (5 preceding siblings ...)
  2020-12-18 10:23 ` [PULL 06/14] linux-user/elfload: Update HWCAP bits from linux 5.7 Laurent Vivier
@ 2020-12-18 10:24 ` Laurent Vivier
  2020-12-18 10:24 ` [PULL 08/14] docs/user: Display linux-user binaries nicely Laurent Vivier
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Laurent Vivier @ 2020-12-18 10:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: Richard Henderson, Philippe Mathieu-Daudé, Laurent Vivier

From: Philippe Mathieu-Daudé <f4bug@amsat.org>

Userland ELF binaries using Loongson SIMD instructions have the
HWCAP_LOONGSON_MMI bit set [1].
Binaries compiled for Loongson 3A [2] have the HWCAP_LOONGSON_EXT
bit set for the LQ / SQ instructions.

[1] commit 8e2d5831e4b ("target/mips: Legalize Loongson insn flags")
[2] commit af868995e1b ("target/mips: Add Loongson-3 CPU definition")

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20201214003215.344522-7-f4bug@amsat.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/elfload.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 0836e72b5ac3..a64050713f28 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1024,6 +1024,8 @@ static uint32_t get_elf_hwcap(void)
     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;
 }
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 08/14] docs/user: Display linux-user binaries nicely
  2020-12-18 10:23 [PULL 00/14] Linux user for 6.0 patches Laurent Vivier
                   ` (6 preceding siblings ...)
  2020-12-18 10:24 ` [PULL 07/14] linux-user: Add support for MIPS Loongson 2F/3A Laurent Vivier
@ 2020-12-18 10:24 ` Laurent Vivier
  2020-12-18 10:24 ` [PULL 09/14] linux-user: Implement copy_file_range Laurent Vivier
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Laurent Vivier @ 2020-12-18 10:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Laurent Vivier

From: Philippe Mathieu-Daudé <f4bug@amsat.org>

linux-user binaries are displayed altogether. Use the '*'
character to force displaying them as bullet list (one list
per architecture).

Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20201119160838.1981709-1-f4bug@amsat.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 docs/user/main.rst | 99 ++++++++++++++++++++++++++--------------------
 1 file changed, 56 insertions(+), 43 deletions(-)

diff --git a/docs/user/main.rst b/docs/user/main.rst
index bd99b0fdbe9b..8dfe232a3af1 100644
--- a/docs/user/main.rst
+++ b/docs/user/main.rst
@@ -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
 -----------------------
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 09/14] linux-user: Implement copy_file_range
  2020-12-18 10:23 [PULL 00/14] Linux user for 6.0 patches Laurent Vivier
                   ` (7 preceding siblings ...)
  2020-12-18 10:24 ` [PULL 08/14] docs/user: Display linux-user binaries nicely Laurent Vivier
@ 2020-12-18 10:24 ` Laurent Vivier
  2020-12-18 10:24 ` [PULL 10/14] linux-user: Add most IFTUN ioctls Laurent Vivier
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Laurent Vivier @ 2020-12-18 10:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Schwab, Laurent Vivier

From: Andreas Schwab <schwab@suse.de>

Signed-off-by: Andreas Schwab <schwab@suse.de>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <mvm361eer3n.fsf@suse.de>
[lv: copy back offset only if there is no error]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/syscall.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 7bf99beb1814..6091a449fbf0 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -813,6 +813,12 @@ safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr,
 safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr,
               size_t, len, unsigned *, prio, const struct timespec *, timeout)
 #endif
+#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
+safe_syscall6(ssize_t, copy_file_range, int, infd, loff_t *, pinoff,
+              int, outfd, loff_t *, poutoff, size_t, length,
+              unsigned int, flags)
+#endif
+
 /* We do ioctl like this rather than via safe_syscall3 to preserve the
  * "third argument might be integer or pointer or not present" behaviour of
  * the libc function.
@@ -13065,6 +13071,42 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
         return get_errno(membarrier(arg1, arg2));
 #endif
 
+#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
+    case TARGET_NR_copy_file_range:
+        {
+            loff_t inoff, outoff;
+            loff_t *pinoff = NULL, *poutoff = NULL;
+
+            if (arg2) {
+                if (get_user_u64(inoff, arg2)) {
+                    return -TARGET_EFAULT;
+                }
+                pinoff = &inoff;
+            }
+            if (arg4) {
+                if (get_user_u64(outoff, arg4)) {
+                    return -TARGET_EFAULT;
+                }
+                poutoff = &outoff;
+            }
+            ret = get_errno(safe_copy_file_range(arg1, pinoff, arg3, poutoff,
+                                                 arg5, arg6));
+            if (!is_error(ret) && ret > 0) {
+                if (arg2) {
+                    if (put_user_u64(inoff, arg2)) {
+                        return -TARGET_EFAULT;
+                    }
+                }
+                if (arg4) {
+                    if (put_user_u64(outoff, arg4)) {
+                        return -TARGET_EFAULT;
+                    }
+                }
+            }
+        }
+        return ret;
+#endif
+
     default:
         qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
         return -TARGET_ENOSYS;
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 10/14] linux-user: Add most IFTUN ioctls
  2020-12-18 10:23 [PULL 00/14] Linux user for 6.0 patches Laurent Vivier
                   ` (8 preceding siblings ...)
  2020-12-18 10:24 ` [PULL 09/14] linux-user: Implement copy_file_range Laurent Vivier
@ 2020-12-18 10:24 ` Laurent Vivier
  2020-12-18 10:24 ` [PULL 11/14] linux-user/sparc: Correct sparc64_get/set_context() FPU handling Laurent Vivier
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Laurent Vivier @ 2020-12-18 10:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: Josh Kunz, Shu-Chun Weng, Laurent Vivier

From: Shu-Chun Weng <scw@google.com>

The three options handling `struct sock_fprog` (TUNATTACHFILTER,
TUNDETACHFILTER, and TUNGETFILTER) are not implemented. Linux kernel
keeps a user space pointer in them which we cannot correctly handle.

Signed-off-by: Josh Kunz <jkz@google.com>
Signed-off-by: Shu-Chun Weng <scw@google.com>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20200929014801.655524-1-scw@google.com>
[lv: use 0 size in unlock_user()]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/ioctls.h       | 46 +++++++++++++++++++++++++++++++++++++++
 linux-user/syscall.c      | 37 +++++++++++++++++++++++++++++++
 linux-user/syscall_defs.h | 32 +++++++++++++++++++++++++++
 3 files changed, 115 insertions(+)

diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 8efb4d38c014..661b5daa9fd8 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -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
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 6091a449fbf0..d182890ff04a 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -56,6 +56,7 @@
 #include <linux/wireless.h>
 #include <linux/icmp.h>
 #include <linux/icmpv6.h>
+#include <linux/if_tun.h>
 #include <linux/errqueue.h>
 #include <linux/random.h>
 #ifdef CONFIG_TIMERFD
@@ -5709,6 +5710,42 @@ static abi_long do_ioctl_drm_i915(const IOCTLEntry *ie, uint8_t *buf_temp,
 
 #endif
 
+static abi_long do_ioctl_TUNSETTXFILTER(const IOCTLEntry *ie, uint8_t *buf_temp,
+                                        int fd, int cmd, abi_long arg)
+{
+    struct tun_filter *filter = (struct tun_filter *)buf_temp;
+    struct tun_filter *target_filter;
+    char *target_addr;
+
+    assert(ie->access == IOC_W);
+
+    target_filter = lock_user(VERIFY_READ, arg, sizeof(*target_filter), 1);
+    if (!target_filter) {
+        return -TARGET_EFAULT;
+    }
+    filter->flags = tswap16(target_filter->flags);
+    filter->count = tswap16(target_filter->count);
+    unlock_user(target_filter, arg, 0);
+
+    if (filter->count) {
+        if (offsetof(struct tun_filter, addr) + filter->count * ETH_ALEN >
+            MAX_STRUCT_SIZE) {
+            return -TARGET_EFAULT;
+        }
+
+        target_addr = lock_user(VERIFY_READ,
+                                arg + offsetof(struct tun_filter, addr),
+                                filter->count * ETH_ALEN, 1);
+        if (!target_addr) {
+            return -TARGET_EFAULT;
+        }
+        memcpy(filter->addr, target_addr, filter->count * ETH_ALEN);
+        unlock_user(target_addr, arg + offsetof(struct tun_filter, addr), 0);
+    }
+
+    return get_errno(safe_ioctl(fd, ie->host_cmd, filter));
+}
+
 IOCTLEntry ioctl_entries[] = {
 #define IOCTL(cmd, access, ...) \
     { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } },
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index b934d0b60676..a00bfc2647c7 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -929,6 +929,38 @@ struct target_rtc_pll_info {
 
 #define TARGET_SIOCGIWNAME     0x8B01          /* get name == wireless protocol */
 
+/* From <linux/if_tun.h> */
+
+#define TARGET_TUNSETDEBUG        TARGET_IOW('T', 201, int)
+#define TARGET_TUNSETIFF          TARGET_IOW('T', 202, int)
+#define TARGET_TUNSETPERSIST      TARGET_IOW('T', 203, int)
+#define TARGET_TUNSETOWNER        TARGET_IOW('T', 204, int)
+#define TARGET_TUNSETLINK         TARGET_IOW('T', 205, int)
+#define TARGET_TUNSETGROUP        TARGET_IOW('T', 206, int)
+#define TARGET_TUNGETFEATURES     TARGET_IOR('T', 207, unsigned int)
+#define TARGET_TUNSETOFFLOAD      TARGET_IOW('T', 208, unsigned int)
+#define TARGET_TUNSETTXFILTER     TARGET_IOW('T', 209, unsigned int)
+#define TARGET_TUNGETIFF          TARGET_IOR('T', 210, unsigned int)
+#define TARGET_TUNGETSNDBUF       TARGET_IOR('T', 211, int)
+#define TARGET_TUNSETSNDBUF       TARGET_IOW('T', 212, int)
+/*
+ * TUNATTACHFILTER and TUNDETACHFILTER are not supported. Linux kernel keeps a
+ * user pointer in TUNATTACHFILTER, which we are not able to correctly handle.
+ */
+#define TARGET_TUNGETVNETHDRSZ    TARGET_IOR('T', 215, int)
+#define TARGET_TUNSETVNETHDRSZ    TARGET_IOW('T', 216, int)
+#define TARGET_TUNSETQUEUE        TARGET_IOW('T', 217, int)
+#define TARGET_TUNSETIFINDEX      TARGET_IOW('T', 218, unsigned int)
+/* TUNGETFILTER is not supported: see TUNATTACHFILTER. */
+#define TARGET_TUNSETVNETLE       TARGET_IOW('T', 220, int)
+#define TARGET_TUNGETVNETLE       TARGET_IOR('T', 221, int)
+#define TARGET_TUNSETVNETBE       TARGET_IOW('T', 222, int)
+#define TARGET_TUNGETVNETBE       TARGET_IOR('T', 223, int)
+#define TARGET_TUNSETSTEERINGEBPF TARGET_IOR('T', 224, int)
+#define TARGET_TUNSETFILTEREBPF   TARGET_IOR('T', 225, int)
+#define TARGET_TUNSETCARRIER      TARGET_IOW('T', 226, int)
+#define TARGET_TUNGETDEVNETNS     TARGET_IO('T', 227)
+
 /* From <linux/random.h> */
 
 #define TARGET_RNDGETENTCNT    TARGET_IOR('R', 0x00, int)
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 11/14] linux-user/sparc: Correct sparc64_get/set_context() FPU handling
  2020-12-18 10:23 [PULL 00/14] Linux user for 6.0 patches Laurent Vivier
                   ` (9 preceding siblings ...)
  2020-12-18 10:24 ` [PULL 10/14] linux-user: Add most IFTUN ioctls Laurent Vivier
@ 2020-12-18 10:24 ` Laurent Vivier
  2020-12-18 10:24 ` [PULL 12/14] linux-user/sparc: Remove unneeded checks of 'err' from sparc64_get_context() Laurent Vivier
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Laurent Vivier @ 2020-12-18 10:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Richard Henderson, Laurent Vivier

From: Peter Maydell <peter.maydell@linaro.org>

The handling of the FPU state in sparc64_get_context() and
sparc64_set_context() is not the same as what the kernel actually
does: we unconditionally read and write the FP registers and the
FSR, GSR and FPRS, but the kernel logic is more complicated:
 * in get_context the kernel has code for saving FPU registers,
   but it is hidden inside an "if (fenab) condition and the
   fenab flag is always set to 0 (inside an "#if 1" which has
   been in the kernel for over 15 years). So the effect is that
   the FPU state part is always written as zeroes.
 * in set_context the kernel looks at the fenab field in the
   structure from the guest, and only restores the state if
   it is set; it also looks at the structure's FPRS to see
   whether either the upper or lower or both halves of the
   register file have valid data.

Bring our implementations into line with the kernel:
 * in get_context:
    - clear the entire target_ucontext at the top of the
      function (as the kernel does)
    - then don't write the FPU state, so those fields remain zero
    - this fixes Coverity issue CID 1432305 by deleting the code
      it was complaining about
 * in set_context:
    - check the fenab and the fpsr to decide which parts of
      the FPU data to restore, if any
    - instead of setting the FPU registers by doing two
      32-bit loads and filling in the .upper and .lower parts
      of the CPU_Double union separately, just do a 64-bit
      load of the whole register at once. This fixes Coverity
      issue CID 1432303 because we now access the dregs[] part
      of the mcfpu_fregs union rather than the sregs[] part
      (which is not large enough to actually cover the whole of
      the data, so we were accessing off the end of sregs[])

We change both functions in a single commit to avoid potentially
breaking bisection.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20201106152738.26026-2-peter.maydell@linaro.org>
[lv: fix FPRS_DU loop s/31/32/]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/sparc/signal.c | 74 +++++++++++++++++++++++----------------
 target/sparc/cpu.h        |  4 ++-
 2 files changed, 46 insertions(+), 32 deletions(-)

diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c
index d12adc8e6ff9..0057b48fad93 100644
--- a/linux-user/sparc/signal.c
+++ b/linux-user/sparc/signal.c
@@ -402,8 +402,10 @@ void sparc64_set_context(CPUSPARCState *env)
     abi_ulong ucp_addr;
     struct target_ucontext *ucp;
     target_mc_gregset_t *grp;
+    target_mc_fpu_t *fpup;
     abi_ulong pc, npc, tstate;
     unsigned int i;
+    unsigned char fenab;
 
     ucp_addr = env->regwptr[WREG_O0];
     if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
@@ -467,26 +469,42 @@ void sparc64_set_context(CPUSPARCState *env)
     __get_user(env->regwptr[WREG_FP], &(ucp->tuc_mcontext.mc_fp));
     __get_user(env->regwptr[WREG_I7], &(ucp->tuc_mcontext.mc_i7));
 
-    /* FIXME this does not match how the kernel handles the FPU in
-     * its sparc64_set_context implementation. In particular the FPU
-     * is only restored if fenab is non-zero in:
-     *   __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab));
-     */
-    __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
-    {
-        uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
-        for (i = 0; i < 64; i++, src++) {
-            if (i & 1) {
-                __get_user(env->fpr[i/2].l.lower, src);
-            } else {
-                __get_user(env->fpr[i/2].l.upper, src);
+    fpup = &ucp->tuc_mcontext.mc_fpregs;
+
+    __get_user(fenab, &(fpup->mcfpu_enab));
+    if (fenab) {
+        abi_ulong fprs;
+
+        /*
+         * We use the FPRS from the guest only in deciding whether
+         * to restore the upper, lower, or both banks of the FPU regs.
+         * The kernel here writes the FPU register data into the
+         * process's current_thread_info state and unconditionally
+         * clears FPRS and TSTATE_PEF: this disables the FPU so that the
+         * next FPU-disabled trap will copy the data out of
+         * current_thread_info and into the real FPU registers.
+         * QEMU doesn't need to handle lazy-FPU-state-restoring like that,
+         * so we always load the data directly into the FPU registers
+         * and leave FPRS and TSTATE_PEF alone (so the FPU stays enabled).
+         * Note that because we (and the kernel) always write zeroes for
+         * the fenab and fprs in sparc64_get_context() none of this code
+         * will execute unless the guest manually constructed or changed
+         * the context structure.
+         */
+        __get_user(fprs, &(fpup->mcfpu_fprs));
+        if (fprs & FPRS_DL) {
+            for (i = 0; i < 16; i++) {
+                __get_user(env->fpr[i].ll, &(fpup->mcfpu_fregs.dregs[i]));
+            }
+        }
+        if (fprs & FPRS_DU) {
+            for (i = 16; i < 32; i++) {
+                __get_user(env->fpr[i].ll, &(fpup->mcfpu_fregs.dregs[i]));
             }
         }
+        __get_user(env->fsr, &(fpup->mcfpu_fsr));
+        __get_user(env->gsr, &(fpup->mcfpu_gsr));
     }
-    __get_user(env->fsr,
-               &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
-    __get_user(env->gsr,
-               &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr));
     unlock_user_struct(ucp, ucp_addr, 0);
     return;
 do_sigsegv:
@@ -509,7 +527,9 @@ void sparc64_get_context(CPUSPARCState *env)
     if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
         goto do_sigsegv;
     }
-    
+
+    memset(ucp, 0, sizeof(*ucp));
+
     mcp = &ucp->tuc_mcontext;
     grp = &mcp->mc_gregs;
 
@@ -572,19 +592,11 @@ void sparc64_get_context(CPUSPARCState *env)
     __put_user(env->regwptr[WREG_FP], &(mcp->mc_fp));
     __put_user(env->regwptr[WREG_I7], &(mcp->mc_i7));
 
-    {
-        uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
-        for (i = 0; i < 64; i++, dst++) {
-            if (i & 1) {
-                __put_user(env->fpr[i/2].l.lower, dst);
-            } else {
-                __put_user(env->fpr[i/2].l.upper, dst);
-            }
-        }
-    }
-    __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
-    __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));
-    __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs));
+    /*
+     * We don't write out the FPU state. This matches the kernel's
+     * implementation (which has the code for doing this but
+     * hidden behind an "if (fenab)" where fenab is always 0).
+     */
 
     if (err)
         goto do_sigsegv;
diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index b9369398f24b..277254732b93 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -156,7 +156,9 @@ enum {
 #define PS_IE    (1<<1)
 #define PS_AG    (1<<0) /* v9, zero on UA2007 */
 
-#define FPRS_FEF (1<<2)
+#define FPRS_DL (1 << 0)
+#define FPRS_DU (1 << 1)
+#define FPRS_FEF (1 << 2)
 
 #define HS_PRIV  (1<<2)
 #endif
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 12/14] linux-user/sparc: Remove unneeded checks of 'err' from sparc64_get_context()
  2020-12-18 10:23 [PULL 00/14] Linux user for 6.0 patches Laurent Vivier
                   ` (10 preceding siblings ...)
  2020-12-18 10:24 ` [PULL 11/14] linux-user/sparc: Correct sparc64_get/set_context() FPU handling Laurent Vivier
@ 2020-12-18 10:24 ` Laurent Vivier
  2020-12-18 10:24 ` [PULL 13/14] linux-user/sparc: Don't restore %g7 in sparc64_set_context() Laurent Vivier
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Laurent Vivier @ 2020-12-18 10:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Richard Henderson, Laurent Vivier

From: Peter Maydell <peter.maydell@linaro.org>

Unlike the kernel macros, our __get_user() and __put_user() do not
return a failure code.  Kernel code typically has a style of
  err |= __get_user(...); err |= __get_user(...);
and then checking err at the end.  In sparc64_get_context() our
version of the code dropped the accumulating into err but left the
"if (err) goto do_sigsegv" checks, which will never be taken. Delete
unnecessary if()s.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20201106152738.26026-3-peter.maydell@linaro.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/sparc/signal.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c
index 0057b48fad93..58b48afe29c9 100644
--- a/linux-user/sparc/signal.c
+++ b/linux-user/sparc/signal.c
@@ -555,8 +555,6 @@ void sparc64_get_context(CPUSPARCState *env)
         for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) {
             __put_user(*src, dst);
         }
-        if (err)
-            goto do_sigsegv;
     }
 
     /* XXX: tstate must be saved properly */
@@ -598,8 +596,6 @@ void sparc64_get_context(CPUSPARCState *env)
      * hidden behind an "if (fenab)" where fenab is always 0).
      */
 
-    if (err)
-        goto do_sigsegv;
     unlock_user_struct(ucp, ucp_addr, 1);
     return;
 do_sigsegv:
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 13/14] linux-user/sparc: Don't restore %g7 in sparc64_set_context()
  2020-12-18 10:23 [PULL 00/14] Linux user for 6.0 patches Laurent Vivier
                   ` (11 preceding siblings ...)
  2020-12-18 10:24 ` [PULL 12/14] linux-user/sparc: Remove unneeded checks of 'err' from sparc64_get_context() Laurent Vivier
@ 2020-12-18 10:24 ` Laurent Vivier
  2020-12-18 10:24 ` [PULL 14/14] linux-user/sparc: Handle tstate in sparc64_get/set_context() Laurent Vivier
  2020-12-31 15:54 ` [PULL 00/14] Linux user for 6.0 patches Peter Maydell
  14 siblings, 0 replies; 16+ messages in thread
From: Laurent Vivier @ 2020-12-18 10:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Richard Henderson, Laurent Vivier

From: Peter Maydell <peter.maydell@linaro.org>

The kernel does not restore the g7 register in sparc64_set_context();
neither should we. (We still save it in sparc64_get_context().)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20201106152738.26026-4-peter.maydell@linaro.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/sparc/signal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c
index 58b48afe29c9..d92e096cafa7 100644
--- a/linux-user/sparc/signal.c
+++ b/linux-user/sparc/signal.c
@@ -447,7 +447,7 @@ void sparc64_set_context(CPUSPARCState *env)
     __get_user(env->gregs[4], (&(*grp)[SPARC_MC_G4]));
     __get_user(env->gregs[5], (&(*grp)[SPARC_MC_G5]));
     __get_user(env->gregs[6], (&(*grp)[SPARC_MC_G6]));
-    __get_user(env->gregs[7], (&(*grp)[SPARC_MC_G7]));
+    /* Skip g7 as that's the thread register in userspace */
 
     /*
      * Note that unlike the kernel, we didn't need to mess with the
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PULL 14/14] linux-user/sparc: Handle tstate in sparc64_get/set_context()
  2020-12-18 10:23 [PULL 00/14] Linux user for 6.0 patches Laurent Vivier
                   ` (12 preceding siblings ...)
  2020-12-18 10:24 ` [PULL 13/14] linux-user/sparc: Don't restore %g7 in sparc64_set_context() Laurent Vivier
@ 2020-12-18 10:24 ` Laurent Vivier
  2020-12-31 15:54 ` [PULL 00/14] Linux user for 6.0 patches Peter Maydell
  14 siblings, 0 replies; 16+ messages in thread
From: Laurent Vivier @ 2020-12-18 10:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Maydell, Richard Henderson, Laurent Vivier

From: Peter Maydell <peter.maydell@linaro.org>

Correctly implement save/restore of the tstate field in
sparc64_get_context() and sparc64_set_context():
 * Don't use the CWP value from the guest in set_context
 * Construct and save a tstate value rather than leaving
   it as zero in get_context

To do this we factor out the "calculate TSTATE value from CPU state"
code from sparc_cpu_do_interrupt() into its own sparc64_tstate()
function; that in turn requires us to move some of the function
prototypes out from inside a CPU_NO_IO_DEFS ifdef guard.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20201106152738.26026-5-peter.maydell@linaro.org>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
---
 linux-user/sparc/signal.c   |  7 +++----
 target/sparc/cpu.h          | 24 ++++++++++++++++++++----
 target/sparc/int64_helper.c |  5 +----
 3 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/linux-user/sparc/signal.c b/linux-user/sparc/signal.c
index d92e096cafa7..d27b7a3af79d 100644
--- a/linux-user/sparc/signal.c
+++ b/linux-user/sparc/signal.c
@@ -438,9 +438,9 @@ void sparc64_set_context(CPUSPARCState *env)
     env->npc = npc;
     __get_user(env->y, &((*grp)[SPARC_MC_Y]));
     __get_user(tstate, &((*grp)[SPARC_MC_TSTATE]));
+    /* Honour TSTATE_ASI, TSTATE_ICC and TSTATE_XCC only */
     env->asi = (tstate >> 24) & 0xff;
-    cpu_put_ccr(env, tstate >> 32);
-    cpu_put_cwp64(env, tstate & 0x1f);
+    cpu_put_ccr(env, (tstate >> 32) & 0xff);
     __get_user(env->gregs[1], (&(*grp)[SPARC_MC_G1]));
     __get_user(env->gregs[2], (&(*grp)[SPARC_MC_G2]));
     __get_user(env->gregs[3], (&(*grp)[SPARC_MC_G3]));
@@ -557,8 +557,7 @@ void sparc64_get_context(CPUSPARCState *env)
         }
     }
 
-    /* XXX: tstate must be saved properly */
-    //    __put_user(env->tstate, &((*grp)[SPARC_MC_TSTATE]));
+    __put_user(sparc64_tstate(env), &((*grp)[SPARC_MC_TSTATE]));
     __put_user(env->pc, &((*grp)[SPARC_MC_PC]));
     __put_user(env->npc, &((*grp)[SPARC_MC_NPC]));
     __put_user(env->y, &((*grp)[SPARC_MC_Y]));
diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index 277254732b93..4b2290650be4 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -608,10 +608,6 @@ target_ulong cpu_get_psr(CPUSPARCState *env1);
 void cpu_put_psr(CPUSPARCState *env1, target_ulong val);
 void cpu_put_psr_raw(CPUSPARCState *env1, target_ulong val);
 #ifdef TARGET_SPARC64
-target_ulong cpu_get_ccr(CPUSPARCState *env1);
-void cpu_put_ccr(CPUSPARCState *env1, target_ulong val);
-target_ulong cpu_get_cwp64(CPUSPARCState *env1);
-void cpu_put_cwp64(CPUSPARCState *env1, int cwp);
 void cpu_change_pstate(CPUSPARCState *env1, uint32_t new_pstate);
 void cpu_gl_switch_gregs(CPUSPARCState *env, uint32_t new_gl);
 #endif
@@ -829,4 +825,24 @@ static inline bool tb_am_enabled(int tb_flags)
 #endif
 }
 
+#ifdef TARGET_SPARC64
+/* win_helper.c */
+target_ulong cpu_get_ccr(CPUSPARCState *env1);
+void cpu_put_ccr(CPUSPARCState *env1, target_ulong val);
+target_ulong cpu_get_cwp64(CPUSPARCState *env1);
+void cpu_put_cwp64(CPUSPARCState *env1, int cwp);
+
+static inline uint64_t sparc64_tstate(CPUSPARCState *env)
+{
+    uint64_t tstate = (cpu_get_ccr(env) << 32) |
+        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
+        cpu_get_cwp64(env);
+
+    if (env->def.features & CPU_FEATURE_GL) {
+        tstate |= (env->gl & 7ULL) << 40;
+    }
+    return tstate;
+}
+#endif
+
 #endif
diff --git a/target/sparc/int64_helper.c b/target/sparc/int64_helper.c
index ba95bf228cc4..7fb8ab211ca8 100644
--- a/target/sparc/int64_helper.c
+++ b/target/sparc/int64_helper.c
@@ -131,9 +131,7 @@ void sparc_cpu_do_interrupt(CPUState *cs)
     }
     tsptr = cpu_tsptr(env);
 
-    tsptr->tstate = (cpu_get_ccr(env) << 32) |
-        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
-        cpu_get_cwp64(env);
+    tsptr->tstate = sparc64_tstate(env);
     tsptr->tpc = env->pc;
     tsptr->tnpc = env->npc;
     tsptr->tt = intno;
@@ -148,7 +146,6 @@ void sparc_cpu_do_interrupt(CPUState *cs)
     }
 
     if (env->def.features & CPU_FEATURE_GL) {
-        tsptr->tstate |= (env->gl & 7ULL) << 40;
         cpu_gl_switch_gregs(env, env->gl + 1);
         env->gl++;
     }
-- 
2.29.2



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PULL 00/14] Linux user for 6.0 patches
  2020-12-18 10:23 [PULL 00/14] Linux user for 6.0 patches Laurent Vivier
                   ` (13 preceding siblings ...)
  2020-12-18 10:24 ` [PULL 14/14] linux-user/sparc: Handle tstate in sparc64_get/set_context() Laurent Vivier
@ 2020-12-31 15:54 ` Peter Maydell
  14 siblings, 0 replies; 16+ messages in thread
From: Peter Maydell @ 2020-12-31 15:54 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: QEMU Developers

On Fri, 18 Dec 2020 at 10:26, Laurent Vivier <laurent@vivier.eu> wrote:
>
> The following changes since commit af3f37319cb1e1ca0c42842ecdbd1bcfc64a4b6f:
>
>   Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' int=
> o staging (2020-12-15 21:24:31 +0000)
>
> are available in the Git repository at:
>
>   git://github.com/vivier/qemu.git tags/linux-user-for-6.0-pull-request
>
> for you to fetch changes up to 7a5805a08f942325b373643099f784cdac65c9ea:
>
>   linux-user/sparc: Handle tstate in sparc64_get/set_context() (2020-12-18 11=
> :23:29 +0100)
>
> ----------------------------------------------------------------
> Add MIPS Loongson 2F/3A
> sparc64 bug fix
> Implement copy_file_range
> Add most IFTUN ioctls
> Fix mremap


Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/6.0
for any user-visible changes.

-- PMM


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2020-12-31 15:56 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-18 10:23 [PULL 00/14] Linux user for 6.0 patches Laurent Vivier
2020-12-18 10:23 ` [PULL 01/14] linux-user/mmap.c: check range of mremap result in target address space Laurent Vivier
2020-12-18 10:23 ` [PULL 02/14] linux-user/elfload: Move GET_FEATURE macro out of get_elf_hwcap() body Laurent Vivier
2020-12-18 10:23 ` [PULL 03/14] linux-user/elfload: Rename MIPS GET_FEATURE() as GET_FEATURE_INSN() Laurent Vivier
2020-12-18 10:23 ` [PULL 04/14] linux-user/elfload: Introduce MIPS GET_FEATURE_REG_SET() macro Laurent Vivier
2020-12-18 10:23 ` [PULL 05/14] linux-user/elfload: Introduce MIPS GET_FEATURE_REG_EQU() macro Laurent Vivier
2020-12-18 10:23 ` [PULL 06/14] linux-user/elfload: Update HWCAP bits from linux 5.7 Laurent Vivier
2020-12-18 10:24 ` [PULL 07/14] linux-user: Add support for MIPS Loongson 2F/3A Laurent Vivier
2020-12-18 10:24 ` [PULL 08/14] docs/user: Display linux-user binaries nicely Laurent Vivier
2020-12-18 10:24 ` [PULL 09/14] linux-user: Implement copy_file_range Laurent Vivier
2020-12-18 10:24 ` [PULL 10/14] linux-user: Add most IFTUN ioctls Laurent Vivier
2020-12-18 10:24 ` [PULL 11/14] linux-user/sparc: Correct sparc64_get/set_context() FPU handling Laurent Vivier
2020-12-18 10:24 ` [PULL 12/14] linux-user/sparc: Remove unneeded checks of 'err' from sparc64_get_context() Laurent Vivier
2020-12-18 10:24 ` [PULL 13/14] linux-user/sparc: Don't restore %g7 in sparc64_set_context() Laurent Vivier
2020-12-18 10:24 ` [PULL 14/14] linux-user/sparc: Handle tstate in sparc64_get/set_context() Laurent Vivier
2020-12-31 15:54 ` [PULL 00/14] Linux user for 6.0 patches Peter Maydell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).