diff mbox

[v2,2/6] Infer endianness from SCTLR reset value.

Message ID 9b13837a216eb358896a11709e7b4befdd5083db.1481121503.git.julian@codesourcery.com
State New
Headers show

Commit Message

Julian Brown Dec. 7, 2016, 2:48 p.m. UTC
This patch uses the reset value of the SCTLR register (e.g. as modified
by the "cfgend" parameter introduced by the previous patch) to set the
endianness used by QEMU when invoked with a null kernel, e.g. from GDB:

  (gdb) target remote | qemu-arm-system [options] -cpu=cortex-a15,cfgend=yes \
          -kernel /dev/null
  (gdb) load
  (gdb) [...]

In this scenario, the usual method of probing the kernel binary for the
correct endianness to use will not work.

Signed-off-by: Julian Brown <julian@codesourcery.com>
---
 hw/arm/boot.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

Comments

Peter Maydell Jan. 5, 2017, 5:29 p.m. UTC | #1
On 7 December 2016 at 14:48, Julian Brown <julian@codesourcery.com> wrote:
> This patch uses the reset value of the SCTLR register (e.g. as modified
> by the "cfgend" parameter introduced by the previous patch) to set the
> endianness used by QEMU when invoked with a null kernel, e.g. from GDB:
>
>   (gdb) target remote | qemu-arm-system [options] -cpu=cortex-a15,cfgend=yes \
>           -kernel /dev/null
>   (gdb) load
>   (gdb) [...]
>
> In this scenario, the usual method of probing the kernel binary for the
> correct endianness to use will not work.
>
> Signed-off-by: Julian Brown <julian@codesourcery.com>
> ---
>  hw/arm/boot.c | 16 +++++++++++++++-
>  1 file changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/hw/arm/boot.c b/hw/arm/boot.c
> index 942416d..68a6574 100644
> --- a/hw/arm/boot.c
> +++ b/hw/arm/boot.c
> @@ -894,7 +894,21 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
>          entry = info->loader_start + kernel_load_offset;
>          kernel_size = load_image_targphys(info->kernel_filename, entry,
>                                            info->ram_size - kernel_load_offset);
> -        is_linux = 1;
> +        if (kernel_size > 0) {
> +            is_linux = 1;
> +        } else {
> +            /* We've been launched with a kernel of /dev/null or similar.
> +             * Infer endianness from the reset value of the SCTLR for this
> +             * CPU/board.  (This can be altered using the cfgend parameter.)
> +             */
> +            if (!arm_feature(&cpu->env, ARM_FEATURE_V7) &&
> +                (cpu->reset_sctlr & SCTLR_B) != 0)
> +                info->endianness = ARM_ENDIANNESS_BE32;
> +            else if ((cpu->reset_sctlr & SCTLR_EE) != 0)
> +                info->endianness = ARM_ENDIANNESS_BE8;
> +            else
> +                info->endianness = ARM_ENDIANNESS_LE;
> +        }
>      }
>      if (kernel_size < 0) {
>          fprintf(stderr, "qemu: could not load kernel '%s'\n",
> --
> 2.8.1

This is pretty obscure magic behaviour -- feed -kernel a zero
length file and get magic register setting behaviour ?
I think passing an empty file ought to either
 (a) just be an error, or
 (b) behave like passing a 1 byte file, which is what we
     do currently (ie treat it like a raw Linux kernel image)

If you're starting QEMU from GDB in system mode and not giving
it an image file, then I think the expectation would be that
you get the CPU as it would come out of reset in hardware.

Also, this looks a bit odd -- the purpose of the info->endianness
flag is to mess with the SCTLR values, but here we're setting
info->endianness based on the SCTLR values, which seems
circular. Why aren't the SCTLR values just right to start with?

thanks
-- PMM
diff mbox

Patch

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 942416d..68a6574 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -894,7 +894,21 @@  static void arm_load_kernel_notify(Notifier *notifier, void *data)
         entry = info->loader_start + kernel_load_offset;
         kernel_size = load_image_targphys(info->kernel_filename, entry,
                                           info->ram_size - kernel_load_offset);
-        is_linux = 1;
+        if (kernel_size > 0) {
+            is_linux = 1;
+        } else {
+            /* We've been launched with a kernel of /dev/null or similar.
+             * Infer endianness from the reset value of the SCTLR for this
+             * CPU/board.  (This can be altered using the cfgend parameter.)
+             */
+            if (!arm_feature(&cpu->env, ARM_FEATURE_V7) &&
+                (cpu->reset_sctlr & SCTLR_B) != 0)
+                info->endianness = ARM_ENDIANNESS_BE32;
+            else if ((cpu->reset_sctlr & SCTLR_EE) != 0)
+                info->endianness = ARM_ENDIANNESS_BE8;
+            else
+                info->endianness = ARM_ENDIANNESS_LE;
+        }
     }
     if (kernel_size < 0) {
         fprintf(stderr, "qemu: could not load kernel '%s'\n",