[Qemu-devel] [Bug 1818483] Re: qemu user mode does not support binfmt_misc config with flags include "P"

2019-03-10 Thread YunQiang Su
@Peter Luyou and me are working on try to pass the info about whether P
flag is enabled or not by enviroment var or auxval. While we have not
found the right method to do it from binfmt_misc.

In fact, currently qemu trys to process the O flag, and it cannot work at all.
When you install qemu-user-static package from Debian/Ubuntu, the O flag is 
enabled,
while 
   execfd = qemu_getauxval(AT_EXECFD);
always return 0.

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1818483

Title:
  qemu user mode does not support binfmt_misc config with flags include
  "P"

Status in QEMU:
  New

Bug description:
  Hi Sir:
  During our test in chroot environment with qemu-user-static, we got some test 
cases failed because of program output warning with unexpected full path name.
  For example in test module "Devscripts"
  the test item for broken tarball expected the warning info:
  
  but the output was:
  
  the cause is the config file of binfmt_misc was set not to send argv0, for 
example:
  type command "tar" after chroot:
  ==
  lpeng@lpeng-VirtualBox:~/projects_lpeng/qemu/mips_2/sid$ sudo chroot .
  [sudo] password for lpeng: 
  root@lpeng-VirtualBox:/# tar
  /bin/tar: You must specify one of the '-Acdtrux', '--delete' or 
'--test-label' options
  Try '/bin/tar --help' or '/bin/tar --usage' for more information.
  root@lpeng-VirtualBox:/# 
  ===

  by adding output log in main()@qemu/Linux-user/main.c
  we found the original input command was changed, and qemu do not know that, 
we got the input args:
  argv_0/usr/bin/qemu-mips64el-static---
  argv_1/bin/tar---
  argv_2NULL---

  Next step we modified the flags=P in the corresponding config under folder 
/proc/sys/fs/binfmt_misc, then binfmt_misc sent argv[0] to qemu.
  But chroot could not start bash because in current qemu dose not consider 
about this unexpected one more"argv[0]"

  
  After modified qemu code temporary to handle the new argv list we got the 
input args, and from argv[2] is the original input command
  argv_0/usr/bin/qemu-mips64el-static---
  argv_1/bin/tar---
  argv_2tar---

  We need the original input from command line, so is it possible that let 
binfmt_misc to pass one more additional args or env to qemu as a token of the 
binfmt_misc flag, then qemu can judge how to parse the input args by it?
  looking forward your suggestions.

  Thanks
  luyou

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1818483/+subscriptions



[PATCH] mips: pass code of conditional trap

2024-06-20 Thread YunQiang Su
Linux and We use the code of conditional trap instructions to emit
signals other than simple SIGTRAP.  Currently, code 6 (overflow),
7 (div by zero) are supported. It means that if code 7 is used with
a conditional trap instruction, a SIGFPE instead of SIGTRAP will emit.

But when `gen_trap` we didn't pass the code as we use `generate_exception`,
which has no info about the code.  Let's introduce a new function
`generate_exception_code` for it.
---
 target/mips/tcg/translate.c | 8 +++-
 target/mips/tcg/translate.h | 1 +
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 333469b268..e680a1c2f2 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -1353,6 +1353,12 @@ void generate_exception(DisasContext *ctx, int excp)
 gen_helper_raise_exception(tcg_env, tcg_constant_i32(excp));
 }
 
+void generate_exception_with_code(DisasContext *ctx, int excp, int code)
+{
+gen_helper_raise_exception_err(tcg_env, tcg_constant_i32(excp),
+   tcg_constant_i32(code));
+}
+
 void generate_exception_end(DisasContext *ctx, int excp)
 {
 generate_exception_err(ctx, excp, 0);
@@ -4553,7 +4559,7 @@ static void gen_trap(DisasContext *ctx, uint32_t opc,
 if (ctx->hflags != ctx->saved_hflags) {
 tcg_gen_movi_i32(hflags, ctx->hflags);
 }
-generate_exception(ctx, EXCP_TRAP);
+generate_exception_with_code(ctx, EXCP_TRAP, code);
 gen_set_label(l1);
 }
 }
diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h
index 2b6646b339..e3d544b478 100644
--- a/target/mips/tcg/translate.h
+++ b/target/mips/tcg/translate.h
@@ -134,6 +134,7 @@ enum {
 } while (0)
 
 void generate_exception(DisasContext *ctx, int excp);
+void generate_exception_with_code(DisasContext *ctx, int excp, int code);
 void generate_exception_err(DisasContext *ctx, int excp, int err);
 void generate_exception_end(DisasContext *ctx, int excp);
 void generate_exception_break(DisasContext *ctx, int code);
-- 
2.39.3 (Apple Git-146)




Re: [PATCH] mips: pass code of conditional trap

2024-06-20 Thread YunQiang Su
Maciej W. Rozycki  于2024年6月21日周五 08:41写道:
>
> On Fri, 21 Jun 2024, YunQiang Su wrote:
>
> > Linux and We use the code of conditional trap instructions to emit
> > signals other than simple SIGTRAP.  Currently, code 6 (overflow),
> > 7 (div by zero) are supported. It means that if code 7 is used with
> > a conditional trap instruction, a SIGFPE instead of SIGTRAP will emit.
> >
> > But when `gen_trap` we didn't pass the code as we use `generate_exception`,
> > which has no info about the code.  Let's introduce a new function
> > `generate_exception_code` for it.
>
>  I haven't touched this stuff for ages, but AFAICT the code is already
> passed where applicable via the environment for `do_tr_or_bp' to handle,
> so I can't understand why your change is needed.
>

The error_code in env is always zero, as we need to set it here.

>  What problem are you trying to solve?
>

See the talk in GCC mailing list about testsuite/ubsan/overflow-div-3.c
Qemu emits SIGTRAP instead of SIGFPE, due to it didn't initialize the
code of conditional trap to env.

>   Maciej



Re: [PATCH] mips: pass code of conditional trap

2024-06-20 Thread YunQiang Su
Richard Henderson  于2024年6月21日周五 12:21写道:
>
> On 6/20/24 16:46, YunQiang Su wrote:
> > @@ -4553,7 +4559,7 @@ static void gen_trap(DisasContext *ctx, uint32_t opc,
> >   if (ctx->hflags != ctx->saved_hflags) {
> >   tcg_gen_movi_i32(hflags, ctx->hflags);
> >   }
> > -generate_exception(ctx, EXCP_TRAP);
> > +generate_exception_with_code(ctx, EXCP_TRAP, code);
> >   gen_set_label(l1);
> >   }
> >   }
>
> There are two instances within gen_trap, one of which *does* store into 
> error_code, but
> that gets overwritten by do_raise_exception_err.
>

Ohh, yes. There is another `generate_exception_end` if cond == 0.

> Search for EXCP_TRAP.
>
>
> r~



Re: [Qemu-devel] [PATCH v4 00/10] tcg mips64 and mips r6 improvements

2016-12-01 Thread YunQiang Su
On Thu, Dec 1, 2016 at 4:30 AM, Richard Henderson  wrote:
> On 11/30/2016 10:39 AM, Jin Guojie wrote:
>> Yesterday I  successfully got in touch with a Debian developer from imgtec. 
>> Welcome Su Yunqiang.
>> V4 patch can be tested on mips64 be hosts now.
>> The following guests on a mips64
>> big-endian host is OK:
>>   - Debian i386 with qemu-system-i386
>>   - Debian i386 with qemu-system-x86_64
>
> Excellent.
>
> Yunqiang, for the record is this mips64 or mips64r2?  If mips64r2, it might be

Jin gave me his new patch set. I tested it on R2.
All of the bellow work well.

(HOST)  (qemu-system)   (Debian ISO)
64eb  -> i386  ->   i386
64eb  -> x86_64 ->   i386
64eb  -> x86_64 ->   amd64
n32eb-> i386  ->   i386
n32eb-> x86_64 ->   i386
n32eb-> x86_64 ->   amd64
32eb  -> i386  ->   i386
32eb  -> x86_64 ->   i386
32eb  -> x86_64 ->   amd64

> helpful to re-test with use_mips32r2_instructions forced to 0 in
> tcg_target_detect_isa, since there are different paths selected based on that.

I will test for non-r2 today with these paris.

>
>> However, Debian amd64 with qemu-system-x86_64 fails to boot kernel.
>> A 'rep movsq' instruction is wrongly emulated.
>> I will fix this bug within one or two days.
>
> Excellent, thanks.
>
>> But even Su cannot provide an R6 machine.
>
> Ok, I guess we will just have to drop the R6 patches for now, until imgtec is
> able to provide feedback on them.
>
>
> r~



-- 
YunQiang Su



[Qemu-devel] [PATCH v5 00/10] tcg mips64 and mips r6 improvements

2016-12-01 Thread YunQiang Su
I tested this patch set on MIPS EB.

1) MIPS r2:

(HOST)  (qemu-system)   (Debian ISO)
64eb  -> i386  ->   i386
64eb  -> x86_64 ->   i386
64eb  -> x86_64 ->   amd64
n32eb-> i386  ->   i386
n32eb-> x86_64 ->   i386
n32eb-> x86_64 ->   amd64
32eb  -> i386  ->   i386
32eb  -> x86_64 ->   i386
32eb  -> x86_64 ->   amd64

2) On r2 CPU,  with disable
  use_movnz_instructions
  use_mips32_instructions
  use_mips32r2_instructions
See the attached file.

(HOST)  (qemu-system)   (Debian ISO)
64eb  -> i386  ->   i386
64eb  -> x86_64 ->   i386
64eb  -> x86_64 ->   amd64
n32eb-> i386  ->   i386
n32eb-> x86_64 ->   i386
n32eb-> x86_64 ->   amd64
32eb  -> i386  ->   i386
32eb  -> x86_64 ->   i386
32eb  -> x86_64 ->   amd64

If needed, I can also help to test other cases.


-- 
YunQiang Su
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index d352c97..d467dde 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -90,21 +90,24 @@ typedef enum {
 #if (defined(__mips_isa_rev) && (__mips_isa_rev >= 1)) || \
 defined(_MIPS_ARCH_LOONGSON2E) || defined(_MIPS_ARCH_LOONGSON2F) || \
 defined(_MIPS_ARCH_MIPS4)
-#define use_movnz_instructions  1
+//#define use_movnz_instructions  1
+extern bool use_movnz_instructions;
 #else
 extern bool use_movnz_instructions;
 #endif
 
 /* MIPS32 instruction set detection */
 #if defined(__mips_isa_rev) && (__mips_isa_rev >= 1)
-#define use_mips32_instructions  1
+//#define use_mips32_instructions  1
+extern bool use_mips32_instructions;
 #else
 extern bool use_mips32_instructions;
 #endif
 
 /* MIPS32R2 instruction set detection */
 #if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
-#define use_mips32r2_instructions  1
+//#define use_mips32r2_instructions  1
+extern bool use_mips32r2_instructions;
 #else
 extern bool use_mips32r2_instructions;
 #endif
diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c
index e6479e4..ab86b3b 100644
--- a/tcg/mips/tcg-target.inc.c
+++ b/tcg/mips/tcg-target.inc.c
@@ -2309,7 +2309,8 @@ static void tcg_target_detect_isa(void)
  "movz $zero, $zero, $zero\n"
  ".set pop\n"
  : : : );
-use_movnz_instructions = !got_sigill;
+//use_movnz_instructions = !got_sigill;
+use_movnz_instructions = 0;
 #endif
 
 /* Probe for MIPS32 instructions. As no subsetting is allowed
@@ -2322,7 +2323,8 @@ static void tcg_target_detect_isa(void)
  "mul $zero, $zero\n"
  ".set pop\n"
  : : : );
-use_mips32_instructions = !got_sigill;
+//use_mips32_instructions = !got_sigill;
+use_mips32_instructions = 0;
 #endif
 
 /* Probe for MIPS32r2 instructions if MIPS32 instructions are
@@ -2336,7 +2338,8 @@ static void tcg_target_detect_isa(void)
  "seb $zero, $zero\n"
  ".set pop\n"
  : : : );
-use_mips32r2_instructions = !got_sigill;
+//use_mips32r2_instructions = !got_sigill;
+use_mips32r2_instructions = 0;
 }
 #endif
 


Re: [Qemu-devel] [PATCH] linux-user: MIPS set cpu to r6 CPU if binary is R6

2018-01-24 Thread Yunqiang Su
Signed-off-by: YunQiang Su 

On Tue, Jan 9, 2018 at 11:39 PM, Richard Henderson 
 wrote:
> On 01/08/2018 03:34 PM, Laurent Vivier wrote:
>> Peter, Riku,
>> 
>> what do you think of the idea of using the ELF header to select the CPU
>> to emulate?
> 
> I think it's a good way to cut down on mistakes and reduce -- or at least not
> increase -- the number of binaries we build.
> 
> 
> r~



signature.asc
Description: Message signed with OpenPGP


Re: [Qemu-devel] [PATCH 3/3] linux-user: MIPS set cpu to r6 CPU if binary is R6

2018-01-16 Thread YunQiang Su
On Sat, Jan 13, 2018 at 10:48 PM, Laurent Vivier  wrote:
> From: YunQiang Su 
>
> So here we need to detect the version of binaries and set
> cpu_model for it.
>
> [lv: original patch modified to move code into get_cpu_model()]
> Signed-off-by: Laurent Vivier 
> ---
>
> Notes:
> YunQiang Su, please add your Signed-off-by that was
> missing in your original patch.

How to add Signed-off-by? Send a v2 for my version of patch?

>
>  include/elf.h |  4 
>  linux-user/main.c | 10 ++
>  2 files changed, 14 insertions(+)
>
> diff --git a/include/elf.h b/include/elf.h
> index e8a515ce3d..f2104809b1 100644
> --- a/include/elf.h
> +++ b/include/elf.h
> @@ -40,6 +40,10 @@ typedef int64_t  Elf64_Sxword;
>  #define EF_MIPS_ARCH_5 0x4000  /* -mips5 code.  */
>  #define EF_MIPS_ARCH_320x5000  /* MIPS32 code.  */
>  #define EF_MIPS_ARCH_640x6000  /* MIPS64 code.  */
> +#define EF_MIPS_ARCH_32R2   0x7000  /* MIPS32r2 code.  */
> +#define EF_MIPS_ARCH_64R2   0x8000  /* MIPS64r2 code.  */
> +#define EF_MIPS_ARCH_32R6   0x9000  /* MIPS32r6 code.  */
> +#define EF_MIPS_ARCH_64R6   0xa000  /* MIPS64r6 code.  */
>
>  /* The ABI of a file. */
>  #define EF_MIPS_ABI_O320x1000  /* O32 ABI.  */
> diff --git a/linux-user/main.c b/linux-user/main.c
> index 2fc2267fd4..3229ef079e 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -4285,9 +4285,19 @@ static const char *get_cpu_model(int fd)
>  return "Fujitsu MB86904";
>  #endif
>  #elif defined(TARGET_MIPS)
> +int ret;
> +uint32_t eflags;
> +
> +ret = get_elf_eflags(fd, &eflags);
>  #if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
> +if (ret == 0 && (eflags & EF_MIPS_ARCH_64R6) != 0) {
> +return "I6400";
> +}
>  return "5KEf";
>  #else
> +if (ret == 0 && (eflags & EF_MIPS_ARCH_32R6) != 0) {
> +return "mips32r6-generic";
> +}
>  return "24Kf";
>  #endif
>  #elif defined TARGET_OPENRISC
> --
> 2.14.3
>



[Qemu-devel] [PATCH] linux-user: Fix support MIPS o32 FP64 mode

2017-12-19 Thread YunQiang Su
MIPS o32 has a mode called FP64, who has 32 64Bit FPU registers.
To use it:
  add PR_GET_FP_MODE and PR_SET_FP_MODE options for prctl
  set CP0St_FR when binary as EF_MIPS_FP64

https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking
Signed-off-by: YunQiang Su 
---
 linux-user/main.c|  3 +++
 linux-user/syscall.c | 24 +
 target/mips/cpu.c| 59 
 target/mips/cpu.h|  9 
 4 files changed, 95 insertions(+)

diff --git a/linux-user/main.c b/linux-user/main.c
index 2fd2a143ed..f2b02a99a2 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -4750,6 +4750,9 @@ int main(int argc, char **argv, char **envp)
 }
 restore_snan_bit_mode(env);
 }
+if ((info->elf_flags & EF_MIPS_FP64) != 0) {
+env->CP0_Status |= (1 << CP0St_FR);
+}
 }
 #elif defined(TARGET_NIOS2)
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 11c9116c4a..664dacda33 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -10530,6 +10530,30 @@ abi_long do_syscall(void *cpu_env, int num, abi_long 
arg1,
  * need. */
 ret = -TARGET_EINVAL;
 break;
+#ifdef TARGET_MIPS
+case PR_GET_FP_MODE:
+{
+CPUMIPSState *env = ((CPUMIPSState *)cpu_env);
+ret = 0;
+if (env->CP0_Status & (1 << CP0St_FR)) {
+ret |= PR_FP_MODE_FR;
+}
+if (env->CP0_Config5 & (1 << CP0C5_FRE)) {
+ret |= PR_FP_MODE_FRE;
+}
+break;
+}
+case PR_SET_FP_MODE:
+{
+CPUMIPSState *env = ((CPUMIPSState *)cpu_env);
+ret = mips_prctl_set_fp_mode(env, arg2);
+if (ret < 0) {
+ret = -TARGET_EOPNOTSUPP;
+goto fail;
+}
+break;
+}
+#endif
 default:
 /* Most prctl options have no pointer arguments */
 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index 069f93560e..6cf1907f9c 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -246,4 +246,63 @@ static void mips_cpu_register_types(void)
 }
 }
 
+#ifdef CONFIG_USER_ONLY
+abi_long mips_prctl_set_fp_mode(CPUMIPSState *env, abi_long arg2)
+{
+abi_long ret;
+CPUState *other_cpu;
+bool old_fr = env->CP0_Status & (1 << CP0St_FR);
+bool new_fr = arg2 & PR_FP_MODE_FR;
+bool new_fre = arg2 & PR_FP_MODE_FRE;
+
+if (new_fr && !(env->active_fpu.fcr0 & (1 << FCR0_F64))) {
+/* FR1 is not supported */
+ret = -1;
+return ret;
+}
+
+if (!new_fr && (env->active_fpu.fcr0 & (1 << FCR0_F64))
+&& !(env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
+/* cannot set FR=0 */
+ret = -1;
+return ret;
+}
+
+if (new_fre && !(env->active_fpu.fcr0 & (1 << FCR0_FREP))) {
+/* Cannot set FRE=1 */
+ret = -1;
+return ret;
+}
+
+start_exclusive();
+CPU_FOREACH(other_cpu) {
+int i;
+MIPSCPU *cpu = MIPS_CPU(other_cpu);
+env = &cpu->env;
+for (i = 0; i < 32 ; i += 2) {
+fpr_t *fpr = env->active_fpu.fpr;
+if (!old_fr && new_fr) {
+fpr[i].w[!FP_ENDIAN_IDX] = fpr[i + 1].w[FP_ENDIAN_IDX];
+} else if (old_fr && !new_fr) {
+fpr[i + 1].w[FP_ENDIAN_IDX] = fpr[i].w[!FP_ENDIAN_IDX];
+}
+}
+if (new_fr) {
+env->CP0_Status |= (1 << CP0St_FR);
+} else {
+env->CP0_Status &= ~(1 << CP0St_FR);
+}
+if (new_fre) {
+env->CP0_Config5 |= (1 << CP0C5_FRE);
+} else {
+env->CP0_Config5 &= ~(1 << CP0C5_FRE);
+}
+compute_hflags(env);
+}
+end_exclusive();
+ret = 0;
+return ret;
+}
+#endif
+
 type_init(mips_cpu_register_types)
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 7f8ba5ff3e..b5d9aac6d0 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -769,4 +769,13 @@ static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, 
target_ulong *pc,
 MIPS_HFLAG_HWRENA_ULR);
 }
 
+/* prctl interface.  */
+#if defined(CONFIG_USER_ONLY)
+#define PR_SET_FP_MODE 45
+#define PR_GET_FP_MODE 46
+#define PR_FP_MODE_FR  (1 << 0)
+#define PR_FP_MODE_FRE (1 << 1)
+abi_long mips_prctl_set_fp_mode(CPUMIPSState *env, abi_long arg2);
+#endif
+
 #endif /* MIPS_CPU_H */
-- 
2.15.1




[Qemu-devel] [PATCH] linux-user: MIPS set cpu to r6 CPU if binary is R6

2017-12-19 Thread YunQiang Su
MIPS r6 is not just simple super set for pre-R6,
it also drops some instruction and even changes encoding for some.
But r6 binary has the same header for binfmt_misc.

So here we need to detect the version of binaries and set
cpu_model for it.
---
 include/elf.h|  4 
 linux-user/elfload.c | 36 
 linux-user/main.c| 15 +++
 linux-user/qemu.h|  1 +
 4 files changed, 56 insertions(+)

diff --git a/include/elf.h b/include/elf.h
index e8a515ce3d..f2104809b1 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -40,6 +40,10 @@ typedef int64_t  Elf64_Sxword;
 #define EF_MIPS_ARCH_5 0x4000  /* -mips5 code.  */
 #define EF_MIPS_ARCH_320x5000  /* MIPS32 code.  */
 #define EF_MIPS_ARCH_640x6000  /* MIPS64 code.  */
+#define EF_MIPS_ARCH_32R2   0x7000  /* MIPS32r2 code.  */
+#define EF_MIPS_ARCH_64R2   0x8000  /* MIPS64r2 code.  */
+#define EF_MIPS_ARCH_32R6   0x9000  /* MIPS32r6 code.  */
+#define EF_MIPS_ARCH_64R6   0xa000  /* MIPS64r6 code.  */
 
 /* The ABI of a file. */
 #define EF_MIPS_ABI_O320x1000  /* O32 ABI.  */
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 20f3d8c2c3..f9b8e028ca 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -2224,6 +2224,42 @@ static void load_elf_interp(const char *filename, struct 
image_info *info,
 exit(-1);
 }
 
+uint32_t get_elf_eflags(const char *filename)
+{
+int fd, retval;
+char bprm_buf[BPRM_BUF_SIZE];
+
+fd = open(path(filename), O_RDONLY);
+if (fd < 0) {
+return 0;
+}
+retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
+close(fd);
+if (retval < 0) {
+return 0;
+}
+if (retval < BPRM_BUF_SIZE) {
+memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
+}
+
+if (bprm_buf[0] != 0x7f
+ || bprm_buf[1] != 'E'
+ || bprm_buf[2] != 'L'
+ || bprm_buf[3] != 'F') {
+return 0;
+}
+
+struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
+if (!elf_check_ident(ehdr)) {
+return 0;
+}
+bswap_ehdr(ehdr);
+if (!elf_check_ehdr(ehdr)) {
+return 0;
+}
+return ehdr->e_flags;
+}
+
 static int symfind(const void *s0, const void *s1)
 {
 target_ulong addr = *(target_ulong *)s0;
diff --git a/linux-user/main.c b/linux-user/main.c
index 7c0bffeff6..b4626e5aa0 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -4287,6 +4287,21 @@ int main(int argc, char **argv, char **envp)
 }
 trace_init_file(trace_file);
 
+#if defined(TARGET_MIPS)
+if (cpu_model == NULL) {
+uint32_t eflags = get_elf_eflags(filename);
+#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
+if ((eflags & EF_MIPS_ARCH_64R6) != 0) {
+cpu_model = "I6400";
+}
+#else
+if ((eflags & EF_MIPS_ARCH_32R6) != 0) {
+cpu_model = "mips32r6-generic";
+}
+#endif
+}
+#endif
+
 /* Zero out regs */
 memset(regs, 0, sizeof(struct target_pt_regs));
 
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 4edd7d0c08..cf09110bf9 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -190,6 +190,7 @@ int loader_exec(int fdexec, const char *filename, char 
**argv, char **envp,
 
 int load_elf_binary(struct linux_binprm *bprm, struct image_info *info);
 int load_flt_binary(struct linux_binprm *bprm, struct image_info *info);
+uint32_t get_elf_eflags(const char *filename);
 
 abi_long memcpy_to_target(abi_ulong dest, const void *src,
   unsigned long len);
-- 
2.15.1




[Qemu-devel] [PATCH] linux-user: set P5600 as default for MIPS o32

2017-12-19 Thread YunQiang Su
P5600 supports MIPS32r5, and is supported by qemu.
The current 24Kf supports mips32r2 only, to execute r3/r5 binaries
we need P5600.

.CP1_fcr31_rw_bitmask for P5600 is also modified:
 to make FCR31_NAN2008 and FCR31_ABS2008 editable, otherwise
only NAN2008 binaries are supported.

Signed-off-by: YunQiang Su 
---
 linux-user/main.c| 2 +-
 target/mips/translate_init.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index f2b02a99a2..7c0bffeff6 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -4323,7 +4323,7 @@ int main(int argc, char **argv, char **envp)
 #if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
 cpu_model = "5KEf";
 #else
-cpu_model = "24Kf";
+cpu_model = "P5600";
 #endif
 #elif defined TARGET_OPENRISC
 cpu_model = "or1200";
diff --git a/target/mips/translate_init.c b/target/mips/translate_init.c
index c7ba6ee5f9..e3020619d2 100644
--- a/target/mips/translate_init.c
+++ b/target/mips/translate_init.c
@@ -404,7 +404,7 @@ const mips_def_t mips_defs[] =
 (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
 (1 << FCR0_D) | (1 << FCR0_S) | (0x03 << FCR0_PRID),
 .CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008),
-.CP1_fcr31_rw_bitmask = 0xFF83,
+.CP1_fcr31_rw_bitmask = 0xFF8F,
 .SEGBITS = 32,
 .PABITS = 40,
 .insn_flags = CPU_MIPS32R5 | ASE_MSA,
-- 
2.15.1




Re: [Qemu-devel] [PATCH] linux-user: MIPS set cpu to r6 CPU if binary is R6

2017-12-24 Thread YunQiang Su
should something like:

+int fd, retval;
+off_t cur_pos;
+bool is_execfd = true;
+char bprm_buf[BPRM_BUF_SIZE];
+
+fd = qemu_getauxval(AT_EXECFD);
+if (fd == 0){
+is_execfd = false;
+fd = open(path(filename), O_RDONLY);
+if (fd < 0) {
+return 0;
+}
+}else{
+cur_pos = lseek(fd, 0, SEEK_CUR);
+   if ((cur_pos < 0) || (lseek(fd, 0, SEEK_SET) != 0)){
+printf("Error while lseek in %s: %s\n", filename, strerror(errno));
+_exit(EXIT_FAILURE);
+   }
+}
+retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
+if (!is_execfd)
+close(fd);
+else {
+   if (lseek(fd, cur_pos, SEEK_SET) != cur_pos){
+printf("Error while lseek in %s: %s\n", filename, strerror(errno));
+_exit(EXIT_FAILURE);
+}
+}
+
+if (retval < 0) {
+return 0;
+}


works?

On Sun, Dec 24, 2017 at 12:34 AM, Laurent Vivier  wrote:
> Le 19/12/2017 à 12:50, YunQiang Su a écrit :
>> MIPS r6 is not just simple super set for pre-R6,
>> it also drops some instruction and even changes encoding for some.
>> But r6 binary has the same header for binfmt_misc.
>> So here we need to detect the version of binaries and set
>> cpu_model for it.
>> ---
>>  include/elf.h|  4 
>>  linux-user/elfload.c | 36 
>>  linux-user/main.c| 15 +++
>>  linux-user/qemu.h|  1 +
>>  4 files changed, 56 insertions(+)
>>
>> diff --git a/include/elf.h b/include/elf.h
>> index e8a515ce3d..f2104809b1 100644
>> --- a/include/elf.h
>> +++ b/include/elf.h
>> @@ -40,6 +40,10 @@ typedef int64_t  Elf64_Sxword;
>>  #define EF_MIPS_ARCH_5   0x4000  /* -mips5 code.  */
>>  #define EF_MIPS_ARCH_32  0x5000  /* MIPS32 code.  */
>>  #define EF_MIPS_ARCH_64  0x6000  /* MIPS64 code.  */
>> +#define EF_MIPS_ARCH_32R2   0x7000  /* MIPS32r2 code.  */
>> +#define EF_MIPS_ARCH_64R2   0x8000  /* MIPS64r2 code.  */
>> +#define EF_MIPS_ARCH_32R6   0x9000  /* MIPS32r6 code.  */
>> +#define EF_MIPS_ARCH_64R6   0xa000  /* MIPS64r6 code.  */
>>
>>  /* The ABI of a file. */
>>  #define EF_MIPS_ABI_O32  0x1000  /* O32 ABI.  */
>> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
>> index 20f3d8c2c3..f9b8e028ca 100644
>> --- a/linux-user/elfload.c
>> +++ b/linux-user/elfload.c
>> @@ -2224,6 +2224,42 @@ static void load_elf_interp(const char *filename, 
>> struct image_info *info,
>>  exit(-1);
>>  }
>>
>> +uint32_t get_elf_eflags(const char *filename)
>> +{
>> +int fd, retval;
>> +char bprm_buf[BPRM_BUF_SIZE];
>> +
>> +fd = open(path(filename), O_RDONLY);
>
> You can't do that with binfmt and credential ('C' flag) enabled (it
> implies 'O' flag, open-binary), because in this case the kernel opens
> the file and provides the file descriptor to QEMU. We need the 'C' flags
> to allow to execute binaries with the setuid flag (like "sudo") [1]
>
> See linux-user/main.c:
>
>4446 execfd = qemu_getauxval(AT_EXECFD);
>4447 if (execfd == 0) {
>4448 execfd = open(filename, O_RDONLY);
>4449 if (execfd < 0) {
>4450 printf("Error while loading %s: %s\n", filename,
> strerror(errno));
>4451 _exit(EXIT_FAILURE);
>4452 }
>4453 }
>
> Thanks,
> Laurent
> [1]
> https://github.com/torvalds/linux/blob/master/Documentation/admin-guide/binfmt-misc.rst



Re: [PATCH V13 2/9] meson.build: Re-enable KVM support for MIPS

2021-03-23 Thread YunQiang Su
Jiaxun Yang  于2021年3月24日周三 上午9:29写道:
>
>
>
> On Tue, Mar 23, 2021, at 9:56 PM, Philippe Mathieu-Daudé wrote:
> > Hi Huacai,
> >
> > We are going to tag QEMU v6.0-rc0 today.
> >
> > I only have access to a 64-bit MIPS in little-endian to
> > test KVM.
> >
> > Can you test the other configurations please?
> > - 32-bit BE
> > - 32-bit LE
> > - 64-bit BE
>

How to run the test? just run a VM with KVM support on these kernel?

> +syq
> As Loongson doesn't have Big-Endian processor and Loongson 3A won't run 32bit 
> kernel.
>
> Probably wecan test on boston or malta board?
>
> Thanks.
>
>
> >
> > Thanks!
> >
> > Phil.
> >
> >
> [...]
>
> --
> - Jiaxun



[Qemu-devel] [Bug 1818483] Re: qemu user mode does not support binfmt_misc config with flags include "P"

2019-04-03 Thread YunQiang Su
This patch is for linux kernel.

It will set the 3rd bit of AT_FLAGS, if P is set for binfmt_misc.

The major concern is that AT_FLAGS is never used, then, should we use it
here?

** Patch added: "binfmt_preserve_argv0.patch"
   
https://bugs.launchpad.net/qemu/+bug/1818483/+attachment/5252516/+files/binfmt_preserve_argv0.patch

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1818483

Title:
  qemu user mode does not support binfmt_misc config with flags include
  "P"

Status in QEMU:
  New

Bug description:
  Hi Sir:
  During our test in chroot environment with qemu-user-static, we got some test 
cases failed because of program output warning with unexpected full path name.
  For example in test module "Devscripts"
  the test item for broken tarball expected the warning info:
  
  but the output was:
  
  the cause is the config file of binfmt_misc was set not to send argv0, for 
example:
  type command "tar" after chroot:
  ==
  lpeng@lpeng-VirtualBox:~/projects_lpeng/qemu/mips_2/sid$ sudo chroot .
  [sudo] password for lpeng: 
  root@lpeng-VirtualBox:/# tar
  /bin/tar: You must specify one of the '-Acdtrux', '--delete' or 
'--test-label' options
  Try '/bin/tar --help' or '/bin/tar --usage' for more information.
  root@lpeng-VirtualBox:/# 
  ===

  by adding output log in main()@qemu/Linux-user/main.c
  we found the original input command was changed, and qemu do not know that, 
we got the input args:
  argv_0/usr/bin/qemu-mips64el-static---
  argv_1/bin/tar---
  argv_2NULL---

  Next step we modified the flags=P in the corresponding config under folder 
/proc/sys/fs/binfmt_misc, then binfmt_misc sent argv[0] to qemu.
  But chroot could not start bash because in current qemu dose not consider 
about this unexpected one more"argv[0]"

  
  After modified qemu code temporary to handle the new argv list we got the 
input args, and from argv[2] is the original input command
  argv_0/usr/bin/qemu-mips64el-static---
  argv_1/bin/tar---
  argv_2tar---

  We need the original input from command line, so is it possible that let 
binfmt_misc to pass one more additional args or env to qemu as a token of the 
binfmt_misc flag, then qemu can judge how to parse the input args by it?
  looking forward your suggestions.

  Thanks
  luyou

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1818483/+subscriptions



[Qemu-devel] [Bug 1818483] Re: qemu user mode does not support binfmt_misc config with flags include "P"

2019-04-03 Thread YunQiang Su
This patch is for qemu itself.

It test AT_FLAGS and determine whether it is start by binfmt_misc and
whether P flag is used.

** Patch added: "preserve-argv0.patch"
   
https://bugs.launchpad.net/qemu/+bug/1818483/+attachment/5252630/+files/preserve-argv0.patch

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1818483

Title:
  qemu user mode does not support binfmt_misc config with flags include
  "P"

Status in QEMU:
  New

Bug description:
  Hi Sir:
  During our test in chroot environment with qemu-user-static, we got some test 
cases failed because of program output warning with unexpected full path name.
  For example in test module "Devscripts"
  the test item for broken tarball expected the warning info:
  
  but the output was:
  
  the cause is the config file of binfmt_misc was set not to send argv0, for 
example:
  type command "tar" after chroot:
  ==
  lpeng@lpeng-VirtualBox:~/projects_lpeng/qemu/mips_2/sid$ sudo chroot .
  [sudo] password for lpeng: 
  root@lpeng-VirtualBox:/# tar
  /bin/tar: You must specify one of the '-Acdtrux', '--delete' or 
'--test-label' options
  Try '/bin/tar --help' or '/bin/tar --usage' for more information.
  root@lpeng-VirtualBox:/# 
  ===

  by adding output log in main()@qemu/Linux-user/main.c
  we found the original input command was changed, and qemu do not know that, 
we got the input args:
  argv_0/usr/bin/qemu-mips64el-static---
  argv_1/bin/tar---
  argv_2NULL---

  Next step we modified the flags=P in the corresponding config under folder 
/proc/sys/fs/binfmt_misc, then binfmt_misc sent argv[0] to qemu.
  But chroot could not start bash because in current qemu dose not consider 
about this unexpected one more"argv[0]"

  
  After modified qemu code temporary to handle the new argv list we got the 
input args, and from argv[2] is the original input command
  argv_0/usr/bin/qemu-mips64el-static---
  argv_1/bin/tar---
  argv_2tar---

  We need the original input from command line, so is it possible that let 
binfmt_misc to pass one more additional args or env to qemu as a token of the 
binfmt_misc flag, then qemu can judge how to parse the input args by it?
  looking forward your suggestions.

  Thanks
  luyou

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1818483/+subscriptions



[Qemu-devel] [PATCH] binfmt_misc: pass info about P flag by AT_FLAGS

2019-04-16 Thread YunQiang Su
From: YunQiang Su 

Currently program invoked by binfmt_misc cannot be aware about whether
P flag, aka preserve path is enabled.

Some applications like qemu need to know since it has 2 use case:
  1. call by hand, like: qemu-mipsel-static test.app OPTION
 so, qemu have to assume that P option is not enabled.
  2. call by binfmt_misc. If qemu cannot know about whether P flag is
 enabled, distribution's have to set qemu without P flag, and
 binfmt_misc call qemu like:
   qemu-mipsel-static /absolute/path/to/test.app OPTION
 even test.app is not called by absoulute path, like
   ./relative/path/to/test.app

This patch passes this information by the 3rd bits of unused AT_FLAGS.
Then, in qemu, we can get this info by:
   getauxval(AT_FLAGS) & (1<<3)

See: https://bugs.launchpad.net/qemu/+bug/1818483
Signed-off-by: YunQiang Su 
---
 fs/binfmt_elf.c | 6 +-
 fs/binfmt_elf_fdpic.c   | 9 +++--
 fs/binfmt_misc.c| 2 ++
 include/linux/binfmts.h | 4 
 4 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 09e76b25d833..30688fbad615 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -175,6 +175,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr 
*exec,
unsigned char k_rand_bytes[16];
int items;
elf_addr_t *elf_info;
+   elf_addr_t flags = 0;
int ei_index = 0;
const struct cred *cred = current_cred();
struct vm_area_struct *vma;
@@ -249,7 +250,10 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr 
*exec,
NEW_AUX_ENT(AT_PHENT, sizeof(struct elf_phdr));
NEW_AUX_ENT(AT_PHNUM, exec->e_phnum);
NEW_AUX_ENT(AT_BASE, interp_load_addr);
-   NEW_AUX_ENT(AT_FLAGS, 0);
+   if (bprm->interp_flags & BINPRM_FLAGS_PRESERVE_ARGV0) {
+   flags |= BINPRM_FLAGS_PRESERVE_ARGV0;
+   }
+   NEW_AUX_ENT(AT_FLAGS, flags);
NEW_AUX_ENT(AT_ENTRY, exec->e_entry);
NEW_AUX_ENT(AT_UID, from_kuid_munged(cred->user_ns, cred->uid));
NEW_AUX_ENT(AT_EUID, from_kuid_munged(cred->user_ns, cred->euid));
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index b53bb3729ac1..ba3385be00fb 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -46,7 +46,7 @@
 
 typedef char *elf_caddr_t;
 
-#if 0
+#if 1
 #define kdebug(fmt, ...) printk("FDPIC "fmt"\n" ,##__VA_ARGS__ )
 #else
 #define kdebug(fmt, ...) do {} while(0)
@@ -511,6 +511,7 @@ static int create_elf_fdpic_tables(struct linux_binprm 
*bprm,
char __user *u_platform, *u_base_platform, *p;
int loop;
int nr; /* reset for each csp adjustment */
+   unsigned long flags = 0;
 
 #ifdef CONFIG_MMU
/* In some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
@@ -651,7 +652,11 @@ static int create_elf_fdpic_tables(struct linux_binprm 
*bprm,
NEW_AUX_ENT(AT_PHENT,   sizeof(struct elf_phdr));
NEW_AUX_ENT(AT_PHNUM,   exec_params->hdr.e_phnum);
NEW_AUX_ENT(AT_BASE,interp_params->elfhdr_addr);
-   NEW_AUX_ENT(AT_FLAGS,   0);
+   if (bprm->interp_flags & BINPRM_FLAGS_PRESERVE_ARGV0) {
+   flags |= BINPRM_FLAGS_PRESERVE_ARGV0;
+   }
+   kdebug("AT_FLAGS %ld\n", flags);
+   NEW_AUX_ENT(AT_FLAGS,   flags);
NEW_AUX_ENT(AT_ENTRY,   exec_params->entry_addr);
NEW_AUX_ENT(AT_UID, (elf_addr_t) from_kuid_munged(cred->user_ns, 
cred->uid));
NEW_AUX_ENT(AT_EUID,(elf_addr_t) from_kuid_munged(cred->user_ns, 
cred->euid));
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index aa4a7a23ff99..46c509cd096e 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -156,6 +156,8 @@ static int load_misc_binary(struct linux_binprm *bprm)
retval = remove_arg_zero(bprm);
if (retval)
goto ret;
+   } else {
+   bprm->interp_flags |= BINPRM_FLAGS_PRESERVE_ARGV0;
}
 
if (fmt->flags & MISC_FMT_OPEN_BINARY) {
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 688ab0de7810..c082650a0310 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -77,6 +77,10 @@ struct linux_binprm {
 #define BINPRM_FLAGS_PATH_INACCESSIBLE_BIT 2
 #define BINPRM_FLAGS_PATH_INACCESSIBLE (1 << 
BINPRM_FLAGS_PATH_INACCESSIBLE_BIT)
 
+/* if preserve the argv0 for the interpreter  */
+#define BINPRM_FLAGS_PRESERVE_ARGV0_BIT 3
+#define BINPRM_FLAGS_PRESERVE_ARGV0 (1 << BINPRM_FLAGS_PRESERVE_ARGV0_BIT)
+
 /* Function parameter for binfmt->coredump */
 struct coredump_params {
const kernel_siginfo_t *siginfo;
-- 
2.20.1