diff mbox

[v2,2/8] linux-user: arm: set CPSR.E correctly for BE8 mode

Message ID 1401392813-29645-3-git-send-email-pbonzini@redhat.com
State New
Headers show

Commit Message

Paolo Bonzini May 29, 2014, 7:46 p.m. UTC
Set it on startup and in signal handler frames.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 linux-user/main.c   | 1 +
 linux-user/signal.c | 5 +++++
 2 files changed, 6 insertions(+)

Comments

Peter Maydell May 29, 2014, 8:38 p.m. UTC | #1
On 29 May 2014 20:46, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Set it on startup and in signal handler frames.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  linux-user/main.c   | 1 +
>  linux-user/signal.c | 5 +++++
>  2 files changed, 6 insertions(+)
>
> diff --git a/linux-user/main.c b/linux-user/main.c
> index 882186e..2a04446 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -4191,6 +4191,7 @@ int main(int argc, char **argv, char **envp)
>          if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
>              && (info->elf_flags & EF_ARM_BE8)) {
>              env->bswap_code = 1;
> +            env->uncached_cpsr |= CPSR_E;
>          }
>      }
>  #elif defined(TARGET_UNICORE32)
> diff --git a/linux-user/signal.c b/linux-user/signal.c
> index c652829..048ffac 100644
> --- a/linux-user/signal.c
> +++ b/linux-user/signal.c
> @@ -1633,6 +1633,11 @@ setup_return(CPUARMState *env, struct target_sigaction *ka,
>      } else {
>          cpsr &= ~CPSR_T;
>      }
> +#ifdef TARGET_WORDS_BIGENDIAN
> +    cpsr |= CPSR_E;

This is wrong for BE32, where CPSR_E doesn't exist and both code
and data accesses are big-endian.

> +#else
> +    cpsr &= ~CPSR_E;
> +#endif
>
>      if (ka->sa_flags & TARGET_SA_RESTORER) {
>          retcode = ka->sa_restorer;
> --
> 1.9.3

thanks
-- PMM
Paolo Bonzini May 30, 2014, 6:46 a.m. UTC | #2
Il 29/05/2014 22:38, Peter Maydell ha scritto:
>> > +#ifdef TARGET_WORDS_BIGENDIAN
>> > +    cpsr |= CPSR_E;
> This is wrong for BE32, where CPSR_E doesn't exist and both code
> and data accesses are big-endian.
>

Is it okay for simplicity to treat CPSR.E = 1 as "big-endian code, 
little-endian data" in BE32 mode?  The architecture manual leaves it 
undefined.

Paolo
Peter Maydell May 30, 2014, 8:26 a.m. UTC | #3
On 30 May 2014 07:46, Paolo Bonzini <pbonzini@redhat.com> wrote:
> Il 29/05/2014 22:38, Peter Maydell ha scritto:
>
>>> > +#ifdef TARGET_WORDS_BIGENDIAN
>>> > +    cpsr |= CPSR_E;
>>
>> This is wrong for BE32, where CPSR_E doesn't exist and both code
>> and data accesses are big-endian.
>>
>
> Is it okay for simplicity to treat CPSR.E = 1 as "big-endian code,
> little-endian data" in BE32 mode?  The architecture manual leaves it
> undefined.

Actually the ARM ARM does define it: (DDI0406C.c section D12.6.1)
"When SCTLR.B is set, SCTLR.EE and CPSR.E must be clear, or else
the endianness behaviour is UNPREDICTABLE."

So if the guest does set CPSR.E in a BE32 binary you can do
whatever's convenient as long as it's not a security hole,
basically.

thanks
-- PMM
diff mbox

Patch

diff --git a/linux-user/main.c b/linux-user/main.c
index 882186e..2a04446 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -4191,6 +4191,7 @@  int main(int argc, char **argv, char **envp)
         if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4
             && (info->elf_flags & EF_ARM_BE8)) {
             env->bswap_code = 1;
+            env->uncached_cpsr |= CPSR_E;
         }
     }
 #elif defined(TARGET_UNICORE32)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index c652829..048ffac 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1633,6 +1633,11 @@  setup_return(CPUARMState *env, struct target_sigaction *ka,
     } else {
         cpsr &= ~CPSR_T;
     }
+#ifdef TARGET_WORDS_BIGENDIAN
+    cpsr |= CPSR_E;
+#else
+    cpsr &= ~CPSR_E;
+#endif
 
     if (ka->sa_flags & TARGET_SA_RESTORER) {
         retcode = ka->sa_restorer;