• Mark Rutland's avatar
    arm64: Avoid cpus_have_const_cap() for ARM64_HAS_EPAN · 4e00f1d9
    Mark Rutland authored
    We use cpus_have_const_cap() to check for ARM64_HAS_EPAN but this is not
    necessary and alternative_has_cap() or cpus_have_cap() would be
    preferable.
    
    For historical reasons, cpus_have_const_cap() is more complicated than
    it needs to be. Before cpucaps are finalized, it will perform a bitmap
    test of the system_cpucaps bitmap, and once cpucaps are finalized it
    will use an alternative branch. This used to be necessary to handle some
    race conditions in the window between cpucap detection and the
    subsequent patching of alternatives and static branches, where different
    branches could be out-of-sync with one another (or w.r.t. alternative
    sequences). Now that we use alternative branches instead of static
    branches, these are all patched atomically w.r.t. one another, and there
    are only a handful of cases that need special care in the window between
    cpucap detection and alternative patching.
    
    Due to the above, it would be nice to remove cpus_have_const_cap(), and
    migrate callers over to alternative_has_cap_*(), cpus_have_final_cap(),
    or cpus_have_cap() depending on when their requirements. This will
    remove redundant instructions and improve code generation, and will make
    it easier to determine how each callsite will behave before, during, and
    after alternative patching.
    
    The ARM64_HAS_EPAN cpucap is used to affect two things:
    
    1) The permision bits used for userspace executable mappings, which are
       chosen by adjust_protection_map(), which is an arch_initcall. This is
       called after the ARM64_HAS_EPAN cpucap has been detected and
       alternatives have been patched, and before any userspace translation
       tables exist.
    
    2) The handling of faults taken from (user or kernel) accesses to
       userspace executable mappings in do_page_fault(). Userspace
       translation tables are created after adjust_protection_map() is
       called, and hence after the ARM64_HAS_EPAN cpucap has been detected
       and alternatives have been patched.
    
    Neither of these run until after ARM64_HAS_EPAN cpucap has been detected
    and alternatives have been patched, and hence there's no need to use
    cpus_have_const_cap(). Since adjust_protection_map() is only executed
    once at boot time it would be best for it to use cpus_have_cap(), and
    since do_page_fault() is executed frequently it would be best for it to
    use alternatives_have_cap_unlikely().
    
    This patch replaces the uses of cpus_have_const_cap() with
    cpus_have_cap() and alternative_has_cap_unlikely(), which will avoid
    generating redundant code, and should be better for all subsequent calls
    at runtime. The ARM64_HAS_EPAN cpucap is added to cpucap_is_possible()
    so that code can be elided entirely when this is not possible.
    Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
    Cc: James Morse <james.morse@arm.com>
    Cc: Vladimir Murzin <vladimir.murzin@arm.com>
    Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
    Cc: Will Deacon <will@kernel.org>
    Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
    4e00f1d9
mmap.c 3.19 KB