• Mark Rutland's avatar
    arm64: sdei: explicitly simulate PAN/UAO entry · 2376e75c
    Mark Rutland authored
    In preparation for removing addr_limit and set_fs() we must decouple the
    SDEI PAN/UAO manipulation from the uaccess code, and explicitly
    reinitialize these as required.
    
    SDEI enters the kernel with a non-architectural exception, and prior to
    the most recent revision of the specification (ARM DEN 0054B), PSTATE
    bits (e.g. PAN, UAO) are not manipulated in the same way as for
    architectural exceptions. Notably, older versions of the spec can be
    read ambiguously as to whether PSTATE bits are inherited unchanged from
    the interrupted context or whether they are generated from scratch, with
    TF-A doing the latter.
    
    We have three cases to consider:
    
    1) The existing TF-A implementation of SDEI will clear PAN and clear UAO
       (along with other bits in PSTATE) when delivering an SDEI exception.
    
    2) In theory, implementations of SDEI prior to revision B could inherit
       PAN and UAO (along with other bits in PSTATE) unchanged from the
       interrupted context. However, in practice such implementations do not
       exist.
    
    3) Going forward, new implementations of SDEI must clear UAO, and
       depending on SCTLR_ELx.SPAN must either inherit or set PAN.
    
    As we can ignore (2) we can assume that upon SDEI entry, UAO is always
    clear, though PAN may be clear, inherited, or set per SCTLR_ELx.SPAN.
    Therefore, we must explicitly initialize PAN, but do not need to do
    anything for UAO.
    
    Considering what we need to do:
    
    * When set_fs() is removed, force_uaccess_begin() will have no HW
      side-effects. As this only clears UAO, which we can assume has already
      been cleared upon entry, this is not a problem. We do not need to add
      code to manipulate UAO explicitly.
    
    * PAN may be cleared upon entry (in case 1 above), so where a kernel is
      built to use PAN and this is supported by all CPUs, the kernel must
      set PAN upon entry to ensure expected behaviour.
    
    * PAN may be inherited from the interrupted context (in case 3 above),
      and so where a kernel is not built to use PAN or where PAN support is
      not uniform across CPUs, the kernel must clear PAN to ensure expected
      behaviour.
    
    This patch reworks the SDEI code accordingly, explicitly setting PAN to
    the expected state in all cases. To cater for the cases where the kernel
    does not use PAN or this is not uniformly supported by hardware we add a
    new cpu_has_pan() helper which can be used regardless of whether the
    kernel is built to use PAN.
    
    The existing system_uses_ttbr0_pan() is redefined in terms of
    system_uses_hw_pan() both for clarity and as a minor optimization when
    HW PAN is not selected.
    Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
    Reviewed-by: default avatarJames Morse <james.morse@arm.com>
    Cc: James Morse <james.morse@arm.com>
    Cc: Christoph Hellwig <hch@lst.de>
    Cc: Will Deacon <will@kernel.org>
    Link: https://lore.kernel.org/r/20201202131558.39270-3-mark.rutland@arm.comSigned-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
    2376e75c
sdei.c 6.77 KB