All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] linux-user: MIPS set cpu to r6 CPU if binary is R6
@ 2017-12-19 11:50 YunQiang Su
  2017-12-23 16:34 ` Laurent Vivier
  2018-01-08 23:34 ` Laurent Vivier
  0 siblings, 2 replies; 6+ messages in thread
From: YunQiang Su @ 2017-12-19 11:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: 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		0x40000000	/* -mips5 code.  */
 #define EF_MIPS_ARCH_32		0x50000000	/* MIPS32 code.  */
 #define EF_MIPS_ARCH_64		0x60000000	/* MIPS64 code.  */
+#define EF_MIPS_ARCH_32R2       0x70000000      /* MIPS32r2 code.  */
+#define EF_MIPS_ARCH_64R2       0x80000000      /* MIPS64r2 code.  */
+#define EF_MIPS_ARCH_32R6       0x90000000      /* MIPS32r6 code.  */
+#define EF_MIPS_ARCH_64R6       0xa0000000      /* MIPS64r6 code.  */
 
 /* The ABI of a file. */
 #define EF_MIPS_ABI_O32		0x00001000	/* 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

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

* Re: [Qemu-devel] [PATCH] linux-user: MIPS set cpu to r6 CPU if binary is R6
  2017-12-19 11:50 [Qemu-devel] [PATCH] linux-user: MIPS set cpu to r6 CPU if binary is R6 YunQiang Su
@ 2017-12-23 16:34 ` Laurent Vivier
  2017-12-24 14:43   ` YunQiang Su
  2018-01-08 23:34 ` Laurent Vivier
  1 sibling, 1 reply; 6+ messages in thread
From: Laurent Vivier @ 2017-12-23 16:34 UTC (permalink / raw)
  To: YunQiang Su; +Cc: qemu-devel

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		0x40000000	/* -mips5 code.  */
>  #define EF_MIPS_ARCH_32		0x50000000	/* MIPS32 code.  */
>  #define EF_MIPS_ARCH_64		0x60000000	/* MIPS64 code.  */
> +#define EF_MIPS_ARCH_32R2       0x70000000      /* MIPS32r2 code.  */
> +#define EF_MIPS_ARCH_64R2       0x80000000      /* MIPS64r2 code.  */
> +#define EF_MIPS_ARCH_32R6       0x90000000      /* MIPS32r6 code.  */
> +#define EF_MIPS_ARCH_64R6       0xa0000000      /* MIPS64r6 code.  */
>  
>  /* The ABI of a file. */
>  #define EF_MIPS_ABI_O32		0x00001000	/* 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

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

* Re: [Qemu-devel] [PATCH] linux-user: MIPS set cpu to r6 CPU if binary is R6
  2017-12-23 16:34 ` Laurent Vivier
@ 2017-12-24 14:43   ` YunQiang Su
  0 siblings, 0 replies; 6+ messages in thread
From: YunQiang Su @ 2017-12-24 14:43 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: qemu-devel

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 <laurent@vivier.eu> 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               0x40000000      /* -mips5 code.  */
>>  #define EF_MIPS_ARCH_32              0x50000000      /* MIPS32 code.  */
>>  #define EF_MIPS_ARCH_64              0x60000000      /* MIPS64 code.  */
>> +#define EF_MIPS_ARCH_32R2       0x70000000      /* MIPS32r2 code.  */
>> +#define EF_MIPS_ARCH_64R2       0x80000000      /* MIPS64r2 code.  */
>> +#define EF_MIPS_ARCH_32R6       0x90000000      /* MIPS32r6 code.  */
>> +#define EF_MIPS_ARCH_64R6       0xa0000000      /* MIPS64r6 code.  */
>>
>>  /* The ABI of a file. */
>>  #define EF_MIPS_ABI_O32              0x00001000      /* 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

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

* Re: [Qemu-devel] [PATCH] linux-user: MIPS set cpu to r6 CPU if binary is R6
  2017-12-19 11:50 [Qemu-devel] [PATCH] linux-user: MIPS set cpu to r6 CPU if binary is R6 YunQiang Su
  2017-12-23 16:34 ` Laurent Vivier
@ 2018-01-08 23:34 ` Laurent Vivier
  2018-01-09 15:39   ` Richard Henderson
  1 sibling, 1 reply; 6+ messages in thread
From: Laurent Vivier @ 2018-01-08 23:34 UTC (permalink / raw)
  To: Peter Maydell, Riku Voipio; +Cc: YunQiang Su, qemu-devel

Peter, Riku,

what do you think of the idea of using the ELF header to select the CPU
to emulate?

Thanks,
Laurent

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		0x40000000	/* -mips5 code.  */
>  #define EF_MIPS_ARCH_32		0x50000000	/* MIPS32 code.  */
>  #define EF_MIPS_ARCH_64		0x60000000	/* MIPS64 code.  */
> +#define EF_MIPS_ARCH_32R2       0x70000000      /* MIPS32r2 code.  */
> +#define EF_MIPS_ARCH_64R2       0x80000000      /* MIPS64r2 code.  */
> +#define EF_MIPS_ARCH_32R6       0x90000000      /* MIPS32r6 code.  */
> +#define EF_MIPS_ARCH_64R6       0xa0000000      /* MIPS64r6 code.  */
>  
>  /* The ABI of a file. */
>  #define EF_MIPS_ABI_O32		0x00001000	/* 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);
> 

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

* Re: [Qemu-devel] [PATCH] linux-user: MIPS set cpu to r6 CPU if binary is R6
  2018-01-08 23:34 ` Laurent Vivier
@ 2018-01-09 15:39   ` Richard Henderson
  2018-01-24 13:00     ` Yunqiang Su
  0 siblings, 1 reply; 6+ messages in thread
From: Richard Henderson @ 2018-01-09 15:39 UTC (permalink / raw)
  To: Laurent Vivier, Peter Maydell, Riku Voipio; +Cc: YunQiang Su, qemu-devel

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~

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

* Re: [Qemu-devel] [PATCH] linux-user: MIPS set cpu to r6 CPU if binary is R6
  2018-01-09 15:39   ` Richard Henderson
@ 2018-01-24 13:00     ` Yunqiang Su
  0 siblings, 0 replies; 6+ messages in thread
From: Yunqiang Su @ 2018-01-24 13:00 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Laurent Vivier, Peter Maydell, Riku Voipio, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 449 bytes --]

Signed-off-by: YunQiang Su <syq@debian.org>

On Tue, Jan 9, 2018 at 11:39 PM, Richard Henderson <richard.henderson@linaro.org> 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~


[-- Attachment #2: Message signed with OpenPGP --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

end of thread, other threads:[~2018-01-24 13:01 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-19 11:50 [Qemu-devel] [PATCH] linux-user: MIPS set cpu to r6 CPU if binary is R6 YunQiang Su
2017-12-23 16:34 ` Laurent Vivier
2017-12-24 14:43   ` YunQiang Su
2018-01-08 23:34 ` Laurent Vivier
2018-01-09 15:39   ` Richard Henderson
2018-01-24 13:00     ` Yunqiang Su

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.