Skip to content
  • Dave Martin's avatar
    arm64: syscallno is secretly an int, make it official · 35d0e6fb
    Dave Martin authored
    
    
    The upper 32 bits of the syscallno field in thread_struct are
    handled inconsistently, being sometimes zero extended and sometimes
    sign-extended.  In fact, only the lower 32 bits seem to have any
    real significance for the behaviour of the code: it's been OK to
    handle the upper bits inconsistently because they don't matter.
    
    Currently, the only place I can find where those bits are
    significant is in calling trace_sys_enter(), which may be
    unintentional: for example, if a compat tracer attempts to cancel a
    syscall by passing -1 to (COMPAT_)PTRACE_SET_SYSCALL at the
    syscall-enter-stop, it will be traced as syscall 4294967295
    rather than -1 as might be expected (and as occurs for a native
    tracer doing the same thing).  Elsewhere, reads of syscallno cast
    it to an int or truncate it.
    
    There's also a conspicuous amount of code and casting to bodge
    around the fact that although semantically an int, syscallno is
    stored as a u64.
    
    Let's not pretend any more.
    
    In order to preserve the stp x instruction that stores the syscall
    number in entry.S, this patch special-cases the layout of struct
    pt_regs for big endian so that the newly 32-bit syscallno field
    maps onto the low bits of the stored value.  This is not beautiful,
    but benchmarking of the getpid syscall on Juno suggests indicates a
    minor slowdown if the stp is split into an stp x and stp w.
    
    Signed-off-by: default avatarDave Martin <Dave.Martin@arm.com>
    Acked-by: default avatarWill Deacon <will.deacon@arm.com>
    Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
    35d0e6fb