* for-next/52-bit-kva: (25 commits) Support for 52-bit virtual addressing in kernel space * for-next/cpu-topology: (9 commits) Move CPU topology parsing into core code and add support for ACPI 6.3 * for-next/error-injection: (2 commits) Support for function error injection via kprobes * for-next/perf: (8 commits) Support for i.MX8 DDR PMU and proper SMMUv3 group validation * for-next/psci-cpuidle: (7 commits) Move PSCI idle code into a new CPUidle driver * for-next/rng: (4 commits) Support for 'rng-seed' property being passed in the devicetree * for-next/smpboot: (3 commits) Reduce fragility of secondary CPU bringup in debug configurations * for-next/tbi: (10 commits) Introduce new syscall ABI with relaxed requirements for pointer tags * for-next/tlbi: (6 commits) Handle spurious page faults arising from kernel space
ac12cf810 parents f32c7a8 b333b0b d06fa5a 42d038c 3724e18 d55c5f2 dd753d9 ebef746 92af2b6 5c062ef89 files · +1971 −968Browse filesUnified · Split
| @@ -0,0 +1,52 @@ | ||
| 1 | +===================================================== | |
| 2 | +Freescale i.MX8 DDR Performance Monitoring Unit (PMU) | |
| 3 | +===================================================== | |
| 4 | + | |
| 5 | +There are no performance counters inside the DRAM controller, so performance | |
| 6 | +signals are brought out to the edge of the controller where a set of 4 x 32 bit | |
| 7 | +counters is implemented. This is controlled by the CSV modes programed in counter | |
| 8 | +control register which causes a large number of PERF signals to be generated. | |
| 9 | + | |
| 10 | +Selection of the value for each counter is done via the config registers. There | |
| 11 | +is one register for each counter. Counter 0 is special in that it always counts | |
| 12 | +“time” and when expired causes a lock on itself and the other counters and an | |
| 13 | +interrupt is raised. If any other counter overflows, it continues counting, and | |
| 14 | +no interrupt is raised. | |
| 15 | + | |
| 16 | +The "format" directory describes format of the config (event ID) and config1 | |
| 17 | +(AXI filtering) fields of the perf_event_attr structure, see /sys/bus/event_source/ | |
| 18 | +devices/imx8_ddr0/format/. The "events" directory describes the events types | |
| 19 | +hardware supported that can be used with perf tool, see /sys/bus/event_source/ | |
| 20 | +devices/imx8_ddr0/events/. | |
| 21 | + e.g.:: | |
| 22 | + perf stat -a -e imx8_ddr0/cycles/ cmd | |
| 23 | + perf stat -a -e imx8_ddr0/read/,imx8_ddr0/write/ cmd | |
| 24 | + | |
| 25 | +AXI filtering is only used by CSV modes 0x41 (axid-read) and 0x42 (axid-write) | |
| 26 | +to count reading or writing matches filter setting. Filter setting is various | |
| 27 | +from different DRAM controller implementations, which is distinguished by quirks | |
| 28 | +in the driver. | |
| 29 | + | |
| 30 | +* With DDR_CAP_AXI_ID_FILTER quirk. | |
| 31 | + Filter is defined with two configuration parts: | |
| 32 | + --AXI_ID defines AxID matching value. | |
| 33 | + --AXI_MASKING defines which bits of AxID are meaningful for the matching. | |
| 34 | + 0:corresponding bit is masked. | |
| 35 | + 1: corresponding bit is not masked, i.e. used to do the matching. | |
| 36 | + | |
| 37 | + AXI_ID and AXI_MASKING are mapped on DPCR1 register in performance counter. | |
| 38 | + When non-masked bits are matching corresponding AXI_ID bits then counter is | |
| 39 | + incremented. Perf counter is incremented if | |
| 40 | + AxID && AXI_MASKING == AXI_ID && AXI_MASKING | |
| 41 | + | |
| 42 | + This filter doesn't support filter different AXI ID for axid-read and axid-write | |
| 43 | + event at the same time as this filter is shared between counters. | |
| 44 | + e.g.:: | |
| 45 | + perf stat -a -e imx8_ddr0/axid-read,axi_mask=0xMMMM,axi_id=0xDDDD/ cmd | |
| 46 | + perf stat -a -e imx8_ddr0/axid-write,axi_mask=0xMMMM,axi_id=0xDDDD/ cmd | |
| 47 | + | |
| 48 | + NOTE: axi_mask is inverted in userspace(i.e. set bits are bits to mask), and | |
| 49 | + it will be reverted in driver automatically. so that the user can just specify | |
| 50 | + axi_id to monitor a specific id, rather than having to specify axi_mask. | |
| 51 | + e.g.:: | |
| 52 | + perf stat -a -e imx8_ddr0/axid-read,axi_id=0x12/ cmd, which will monitor ARID=0x12 | |
| @@ -16,6 +16,7 @@ ARM64 Architecture · 15 unmodified lines | ||
| 16 | 16 | pointer-authentication |
| 17 | 17 | silicon-errata |
| 18 | 18 | sve |
| 19 | + tagged-address-abi | |
| 19 | 20 | tagged-pointers |
| 20 | 21 | |
| 21 | 22 | .. only:: subproject and html |
| @@ -0,0 +1,27 @@ | ||
| 1 | +#!/bin/sh | |
| 2 | + | |
| 3 | +# Print out the KASAN_SHADOW_OFFSETS required to place the KASAN SHADOW | |
| 4 | +# start address at the mid-point of the kernel VA space | |
| 5 | + | |
| 6 | +print_kasan_offset () { | |
| 7 | + printf "%02d\t" $1 | |
| 8 | + printf "0x%08x00000000\n" $(( (0xffffffff & (-1 << ($1 - 1 - 32))) \ | |
| 9 | + + (1 << ($1 - 32 - $2)) \ | |
| 10 | + - (1 << (64 - 32 - $2)) )) | |
| 11 | +} | |
| 12 | + | |
| 13 | +echo KASAN_SHADOW_SCALE_SHIFT = 3 | |
| 14 | +printf "VABITS\tKASAN_SHADOW_OFFSET\n" | |
| 15 | +print_kasan_offset 48 3 | |
| 16 | +print_kasan_offset 47 3 | |
| 17 | +print_kasan_offset 42 3 | |
| 18 | +print_kasan_offset 39 3 | |
| 19 | +print_kasan_offset 36 3 | |
| 20 | +echo | |
| 21 | +echo KASAN_SHADOW_SCALE_SHIFT = 4 | |
| 22 | +printf "VABITS\tKASAN_SHADOW_OFFSET\n" | |
| 23 | +print_kasan_offset 48 4 | |
| 24 | +print_kasan_offset 47 4 | |
| 25 | +print_kasan_offset 42 4 | |
| 26 | +print_kasan_offset 39 4 | |
| 27 | +print_kasan_offset 36 4 | |
| @@ -14,6 +14,10 @@ with the 4KB page configuration, allowing 39-bit (512GB) or 48-bit · 13 unmodified lines | ||
| 14 | 14 | 64KB pages, only 2 levels of translation tables, allowing 42-bit (4TB) |
| 15 | 15 | virtual address, are used but the memory layout is the same. |
| 16 | 16 | |
| 17 | +ARMv8.2 adds optional support for Large Virtual Address space. This is | |
| 18 | +only available when running with a 64KB page size and expands the | |
| 19 | +number of descriptors in the first level of translation. | |
| 20 | + | |
| 17 | 21 | User addresses have bits 63:48 set to 0 while the kernel addresses have |
| 18 | 22 | the same bits set to 1. TTBRx selection is given by bit 63 of the |
| 19 | 23 | virtual address. The swapper_pg_dir contains only kernel (global) |
| @@ -22,40 +26,43 @@ The swapper_pg_dir address is written to TTBR1 and never written to · 2 unmodified lines | ||
| 22 | 26 | TTBR0. |
| 23 | 27 | |
| 24 | 28 | |
| 25 | −AArch64 Linux memory layout with 4KB pages + 3 levels:: | |
| 26 | − | |
| 27 | − Start End Size Use | |
| 28 | − ----------------------------------------------------------------------- | |
| 29 | − 0000000000000000 0000007fffffffff 512GB user | |
| 30 | − ffffff8000000000 ffffffffffffffff 512GB kernel | |
| 31 | − | |
| 32 | − | |
| 33 | −AArch64 Linux memory layout with 4KB pages + 4 levels:: | |
| 29 | +AArch64 Linux memory layout with 4KB pages + 4 levels (48-bit):: | |
| 34 | 30 | |
| 35 | 31 | Start End Size Use |
| 36 | 32 | ----------------------------------------------------------------------- |
| 37 | 33 | 0000000000000000 0000ffffffffffff 256TB user |
| 38 | − ffff000000000000 ffffffffffffffff 256TB kernel | |
| 39 | − | |
| 40 | − | |
| 41 | −AArch64 Linux memory layout with 64KB pages + 2 levels:: | |
| 34 | + ffff000000000000 ffff7fffffffffff 128TB kernel logical memory map | |
| 35 | + ffff800000000000 ffff9fffffffffff 32TB kasan shadow region | |
| 36 | + ffffa00000000000 ffffa00007ffffff 128MB bpf jit region | |
| 37 | + ffffa00008000000 ffffa0000fffffff 128MB modules | |
| 38 | + ffffa00010000000 fffffdffbffeffff ~93TB vmalloc | |
| 39 | + fffffdffbfff0000 fffffdfffe5f8fff ~998MB [guard region] | |
| 40 | + fffffdfffe5f9000 fffffdfffe9fffff 4124KB fixed mappings | |
| 41 | + fffffdfffea00000 fffffdfffebfffff 2MB [guard region] | |
| 42 | + fffffdfffec00000 fffffdffffbfffff 16MB PCI I/O space | |
| 43 | + fffffdffffc00000 fffffdffffdfffff 2MB [guard region] | |
| 44 | + fffffdffffe00000 ffffffffffdfffff 2TB vmemmap | |
| 45 | + ffffffffffe00000 ffffffffffffffff 2MB [guard region] | |
| 46 | + | |
| 47 | + | |
| 48 | +AArch64 Linux memory layout with 64KB pages + 3 levels (52-bit with HW support):: | |
| 42 | 49 | |
| 43 | 50 | Start End Size Use |
| 44 | 51 | ----------------------------------------------------------------------- |
| 45 | − 0000000000000000 000003ffffffffff 4TB user | |
| 46 | − fffffc0000000000 ffffffffffffffff 4TB kernel | |
| 47 | − | |
| 48 | − | |
| 49 | −AArch64 Linux memory layout with 64KB pages + 3 levels:: | |
| 50 | − | |
| 51 | − Start End Size Use | |
| 52 | − ----------------------------------------------------------------------- | |
| 53 | − 0000000000000000 0000ffffffffffff 256TB user | |
| 54 | − ffff000000000000 ffffffffffffffff 256TB kernel | |
| 55 | − | |
| 56 | − | |
| 57 | −For details of the virtual kernel memory layout please see the kernel | |
| 58 | −booting log. | |
| 52 | + 0000000000000000 000fffffffffffff 4PB user | |
| 53 | + fff0000000000000 fff7ffffffffffff 2PB kernel logical memory map | |
| 54 | + fff8000000000000 fffd9fffffffffff 1440TB [gap] | |
| 55 | + fffda00000000000 ffff9fffffffffff 512TB kasan shadow region | |
| 56 | + ffffa00000000000 ffffa00007ffffff 128MB bpf jit region | |
| 57 | + ffffa00008000000 ffffa0000fffffff 128MB modules | |
| 58 | + ffffa00010000000 fffff81ffffeffff ~88TB vmalloc | |
| 59 | + fffff81fffff0000 fffffc1ffe58ffff ~3TB [guard region] | |
| 60 | + fffffc1ffe590000 fffffc1ffe9fffff 4544KB fixed mappings | |
| 61 | + fffffc1ffea00000 fffffc1ffebfffff 2MB [guard region] | |
| 62 | + fffffc1ffec00000 fffffc1fffbfffff 16MB PCI I/O space | |
| 63 | + fffffc1fffc00000 fffffc1fffdfffff 2MB [guard region] | |
| 64 | + fffffc1fffe00000 ffffffffffdfffff 3968GB vmemmap | |
| 65 | + ffffffffffe00000 ffffffffffffffff 2MB [guard region] | |
| 59 | 66 | |
| 60 | 67 | |
| 61 | 68 | Translation table lookup with 4KB pages:: |
| @@ -83,7 +90,8 @@ Translation table lookup with 64KB pages:: · 21 unmodified lines | ||
| 83 | 90 | | | | | [15:0] in-page offset |
| 84 | 91 | | | | +----------> [28:16] L3 index |
| 85 | 92 | | | +--------------------------> [41:29] L2 index |
| 86 | − | +-------------------------------> [47:42] L1 index | |
| 93 | + | +-------------------------------> [47:42] L1 index (48-bit) | |
| 94 | + | [51:42] L1 index (52-bit) | |
| 87 | 95 | +-------------------------------------------------> [63] TTBR0/1 |
| 88 | 96 | |
| 89 | 97 | |
| @@ -96,3 +104,62 @@ ARM64_HARDEN_EL2_VECTORS is selected for particular CPUs. · 6 unmodified lines | ||
| 96 | 104 | |
| 97 | 105 | When using KVM with the Virtualization Host Extensions, no additional |
| 98 | 106 | mappings are created, since the host kernel runs directly in EL2. |
| 107 | + | |
| 108 | +52-bit VA support in the kernel | |
| 109 | +------------------------------- | |
| 110 | +If the ARMv8.2-LVA optional feature is present, and we are running | |
| 111 | +with a 64KB page size; then it is possible to use 52-bits of address | |
| 112 | +space for both userspace and kernel addresses. However, any kernel | |
| 113 | +binary that supports 52-bit must also be able to fall back to 48-bit | |
| 114 | +at early boot time if the hardware feature is not present. | |
| 115 | + | |
| 116 | +This fallback mechanism necessitates the kernel .text to be in the | |
| 117 | +higher addresses such that they are invariant to 48/52-bit VAs. Due | |
| 118 | +to the kasan shadow being a fraction of the entire kernel VA space, | |
| 119 | +the end of the kasan shadow must also be in the higher half of the | |
| 120 | +kernel VA space for both 48/52-bit. (Switching from 48-bit to 52-bit, | |
| 121 | +the end of the kasan shadow is invariant and dependent on ~0UL, | |
| 122 | +whilst the start address will "grow" towards the lower addresses). | |
| 123 | + | |
| 124 | +In order to optimise phys_to_virt and virt_to_phys, the PAGE_OFFSET | |
| 125 | +is kept constant at 0xFFF0000000000000 (corresponding to 52-bit), | |
| 126 | +this obviates the need for an extra variable read. The physvirt | |
| 127 | +offset and vmemmap offsets are computed at early boot to enable | |
| 128 | +this logic. | |
| 129 | + | |
| 130 | +As a single binary will need to support both 48-bit and 52-bit VA | |
| 131 | +spaces, the VMEMMAP must be sized large enough for 52-bit VAs and | |
| 132 | +also must be sized large enought to accommodate a fixed PAGE_OFFSET. | |
| 133 | + | |
| 134 | +Most code in the kernel should not need to consider the VA_BITS, for | |
| 135 | +code that does need to know the VA size the variables are | |
| 136 | +defined as follows: | |
| 137 | + | |
| 138 | +VA_BITS constant the *maximum* VA space size | |
| 139 | + | |
| 140 | +VA_BITS_MIN constant the *minimum* VA space size | |
| 141 | + | |
| 142 | +vabits_actual variable the *actual* VA space size | |
| 143 | + | |
| 144 | + | |
| 145 | +Maximum and minimum sizes can be useful to ensure that buffers are | |
| 146 | +sized large enough or that addresses are positioned close enough for | |
| 147 | +the "worst" case. | |
| 148 | + | |
| 149 | +52-bit userspace VAs | |
| 150 | +-------------------- | |
| 151 | +To maintain compatibility with software that relies on the ARMv8.0 | |
| 152 | +VA space maximum size of 48-bits, the kernel will, by default, | |
| 153 | +return virtual addresses to userspace from a 48-bit range. | |
| 154 | + | |
| 155 | +Software can "opt-in" to receiving VAs from a 52-bit space by | |
| 156 | +specifying an mmap hint parameter that is larger than 48-bit. | |
| 157 | +For example: | |
| 158 | + maybe_high_address = mmap(~0UL, size, prot, flags,...); | |
| 159 | + | |
| 160 | +It is also possible to build a debug kernel that returns addresses | |
| 161 | +from a 52-bit space by enabling the following kernel config options: | |
| 162 | + CONFIG_EXPERT=y && CONFIG_ARM64_FORCE_52BIT=y | |
| 163 | + | |
| 164 | +Note that this option is only intended for debugging applications | |
| 165 | +and should not be used in production. | |
| @@ -0,0 +1,156 @@ | ||
| 1 | +========================== | |
| 2 | +AArch64 TAGGED ADDRESS ABI | |
| 3 | +========================== | |
| 4 | + | |
| 5 | +Authors: Vincenzo Frascino <vincenzo.frascino@arm.com> | |
| 6 | + Catalin Marinas <catalin.marinas@arm.com> | |
| 7 | + | |
| 8 | +Date: 21 August 2019 | |
| 9 | + | |
| 10 | +This document describes the usage and semantics of the Tagged Address | |
| 11 | +ABI on AArch64 Linux. | |
| 12 | + | |
| 13 | +1. Introduction | |
| 14 | +--------------- | |
| 15 | + | |
| 16 | +On AArch64 the ``TCR_EL1.TBI0`` bit is set by default, allowing | |
| 17 | +userspace (EL0) to perform memory accesses through 64-bit pointers with | |
| 18 | +a non-zero top byte. This document describes the relaxation of the | |
| 19 | +syscall ABI that allows userspace to pass certain tagged pointers to | |
| 20 | +kernel syscalls. | |
| 21 | + | |
| 22 | +2. AArch64 Tagged Address ABI | |
| 23 | +----------------------------- | |
| 24 | + | |
| 25 | +From the kernel syscall interface perspective and for the purposes of | |
| 26 | +this document, a "valid tagged pointer" is a pointer with a potentially | |
| 27 | +non-zero top-byte that references an address in the user process address | |
| 28 | +space obtained in one of the following ways: | |
| 29 | + | |
| 30 | +- ``mmap()`` syscall where either: | |
| 31 | + | |
| 32 | + - flags have the ``MAP_ANONYMOUS`` bit set or | |
| 33 | + - the file descriptor refers to a regular file (including those | |
| 34 | + returned by ``memfd_create()``) or ``/dev/zero`` | |
| 35 | + | |
| 36 | +- ``brk()`` syscall (i.e. the heap area between the initial location of | |
| 37 | + the program break at process creation and its current location). | |
| 38 | + | |
| 39 | +- any memory mapped by the kernel in the address space of the process | |
| 40 | + during creation and with the same restrictions as for ``mmap()`` above | |
| 41 | + (e.g. data, bss, stack). | |
| 42 | + | |
| 43 | +The AArch64 Tagged Address ABI has two stages of relaxation depending | |
| 44 | +how the user addresses are used by the kernel: | |
| 45 | + | |
| 46 | +1. User addresses not accessed by the kernel but used for address space | |
| 47 | + management (e.g. ``mmap()``, ``mprotect()``, ``madvise()``). The use | |
| 48 | + of valid tagged pointers in this context is always allowed. | |
| 49 | + | |
| 50 | +2. User addresses accessed by the kernel (e.g. ``write()``). This ABI | |
| 51 | + relaxation is disabled by default and the application thread needs to | |
| 52 | + explicitly enable it via ``prctl()`` as follows: | |
| 53 | + | |
| 54 | + - ``PR_SET_TAGGED_ADDR_CTRL``: enable or disable the AArch64 Tagged | |
| 55 | + Address ABI for the calling thread. | |
| 56 | + | |
| 57 | + The ``(unsigned int) arg2`` argument is a bit mask describing the | |
| 58 | + control mode used: | |
| 59 | + | |
| 60 | + - ``PR_TAGGED_ADDR_ENABLE``: enable AArch64 Tagged Address ABI. | |
| 61 | + Default status is disabled. | |
| 62 | + | |
| 63 | + Arguments ``arg3``, ``arg4``, and ``arg5`` must be 0. | |
| 64 | + | |
| 65 | + - ``PR_GET_TAGGED_ADDR_CTRL``: get the status of the AArch64 Tagged | |
| 66 | + Address ABI for the calling thread. | |
| 67 | + | |
| 68 | + Arguments ``arg2``, ``arg3``, ``arg4``, and ``arg5`` must be 0. | |
| 69 | + | |
| 70 | + The ABI properties described above are thread-scoped, inherited on | |
| 71 | + clone() and fork() and cleared on exec(). | |
| 72 | + | |
| 73 | + Calling ``prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0)`` | |
| 74 | + returns ``-EINVAL`` if the AArch64 Tagged Address ABI is globally | |
| 75 | + disabled by ``sysctl abi.tagged_addr_disabled=1``. The default | |
| 76 | + ``sysctl abi.tagged_addr_disabled`` configuration is 0. | |
| 77 | + | |
| 78 | +When the AArch64 Tagged Address ABI is enabled for a thread, the | |
| 79 | +following behaviours are guaranteed: | |
| 80 | + | |
| 81 | +- All syscalls except the cases mentioned in section 3 can accept any | |
| 82 | + valid tagged pointer. | |
| 83 | + | |
| 84 | +- The syscall behaviour is undefined for invalid tagged pointers: it may | |
| 85 | + result in an error code being returned, a (fatal) signal being raised, | |
| 86 | + or other modes of failure. | |
| 87 | + | |
| 88 | +- The syscall behaviour for a valid tagged pointer is the same as for | |
| 89 | + the corresponding untagged pointer. | |
| 90 | + | |
| 91 | + | |
| 92 | +A definition of the meaning of tagged pointers on AArch64 can be found | |
| 93 | +in Documentation/arm64/tagged-pointers.rst. | |
| 94 | + | |
| 95 | +3. AArch64 Tagged Address ABI Exceptions | |
| 96 | +----------------------------------------- | |
| 97 | + | |
| 98 | +The following system call parameters must be untagged regardless of the | |
| 99 | +ABI relaxation: | |
| 100 | + | |
| 101 | +- ``prctl()`` other than pointers to user data either passed directly or | |
| 102 | + indirectly as arguments to be accessed by the kernel. | |
| 103 | + | |
| 104 | +- ``ioctl()`` other than pointers to user data either passed directly or | |
| 105 | + indirectly as arguments to be accessed by the kernel. | |
| 106 | + | |
| 107 | +- ``shmat()`` and ``shmdt()``. | |
| 108 | + | |
| 109 | +Any attempt to use non-zero tagged pointers may result in an error code | |
| 110 | +being returned, a (fatal) signal being raised, or other modes of | |
| 111 | +failure. | |
| 112 | + | |
| 113 | +4. Example of correct usage | |
| 114 | +--------------------------- | |
| 115 | +.. code-block:: c | |
| 116 | + | |
| 117 | + #include <stdlib.h> | |
| 118 | + #include <string.h> | |
| 119 | + #include <unistd.h> | |
| 120 | + #include <sys/mman.h> | |
| 121 | + #include <sys/prctl.h> | |
| 122 | + | |
| 123 | + #define PR_SET_TAGGED_ADDR_CTRL 55 | |
| 124 | + #define PR_TAGGED_ADDR_ENABLE (1UL << 0) | |
| 125 | + | |
| 126 | + #define TAG_SHIFT 56 | |
| 127 | + | |
| 128 | + int main(void) | |
| 129 | + { | |
| 130 | + int tbi_enabled = 0; | |
| 131 | + unsigned long tag = 0; | |
| 132 | + char *ptr; | |
| 133 | + | |
| 134 | + /* check/enable the tagged address ABI */ | |
| 135 | + if (!prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0)) | |
| 136 | + tbi_enabled = 1; | |
| 137 | + | |
| 138 | + /* memory allocation */ | |
| 139 | + ptr = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE, | |
| 140 | + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | |
| 141 | + if (ptr == MAP_FAILED) | |
| 142 | + return 1; | |
| 143 | + | |
| 144 | + /* set a non-zero tag if the ABI is available */ | |
| 145 | + if (tbi_enabled) | |
| 146 | + tag = rand() & 0xff; | |
| 147 | + ptr = (char *)((unsigned long)ptr | (tag << TAG_SHIFT)); | |
| 148 | + | |
| 149 | + /* memory access to a tagged address */ | |
| 150 | + strcpy(ptr, "tagged pointer\n"); | |
| 151 | + | |
| 152 | + /* syscall with a tagged pointer */ | |
| 153 | + write(1, ptr, strlen(ptr)); | |
| 154 | + | |
| 155 | + return 0; | |
| 156 | + } | |
| @@ -20,7 +20,9 @@ Passing tagged addresses to the kernel · 19 unmodified lines | ||
| 20 | 20 | -------------------------------------- |
| 21 | 21 | |
| 22 | 22 | All interpretation of userspace memory addresses by the kernel assumes |
| 23 | −an address tag of 0x00. | |
| 23 | +an address tag of 0x00, unless the application enables the AArch64 | |
| 24 | +Tagged Address ABI explicitly | |
| 25 | +(Documentation/arm64/tagged-address-abi.rst). | |
| 24 | 26 | |
| 25 | 27 | This includes, but is not limited to, addresses found in: |
| 26 | 28 | |
| @@ -33,13 +35,15 @@ This includes, but is not limited to, addresses found in: · 6 unmodified lines | ||
| 33 | 35 | - the frame pointer (x29) and frame records, e.g. when interpreting |
| 34 | 36 | them to generate a backtrace or call graph. |
| 35 | 37 | |
| 36 | −Using non-zero address tags in any of these locations may result in an | |
| 37 | −error code being returned, a (fatal) signal being raised, or other modes | |
| 38 | −of failure. | |
| 38 | +Using non-zero address tags in any of these locations when the | |
| 39 | +userspace application did not enable the AArch64 Tagged Address ABI may | |
| 40 | +result in an error code being returned, a (fatal) signal being raised, | |
| 41 | +or other modes of failure. | |
| 39 | 42 | |
| 40 | −For these reasons, passing non-zero address tags to the kernel via | |
| 41 | −system calls is forbidden, and using a non-zero address tag for sp is | |
| 42 | −strongly discouraged. | |
| 43 | +For these reasons, when the AArch64 Tagged Address ABI is disabled, | |
| 44 | +passing non-zero address tags to the kernel via system calls is | |
| 45 | +forbidden, and using a non-zero address tag for sp is strongly | |
| 46 | +discouraged. | |
| 43 | 47 | |
| 44 | 48 | Programs maintaining a frame pointer and frame records that use non-zero |
| 45 | 49 | address tags may suffer impaired or inaccurate debug and profiling |
| @@ -59,6 +63,9 @@ be preserved. · 13 unmodified lines | ||
| 59 | 63 | The architecture prevents the use of a tagged PC, so the upper byte will |
| 60 | 64 | be set to a sign-extension of bit 55 on exception return. |
| 61 | 65 | |
| 66 | +This behaviour is maintained when the AArch64 Tagged Address ABI is | |
| 67 | +enabled. | |
| 68 | + | |
| 62 | 69 | |
| 63 | 70 | Other considerations |
| 64 | 71 | -------------------- |
| @@ -1,21 +1,19 @@ | ||
| 1 | 1 | =========================================== |
| 2 | −ARM topology binding description | |
| 2 | +CPU topology binding description | |
| 3 | 3 | =========================================== |
| 4 | 4 | |
| 5 | 5 | =========================================== |
| 6 | 6 | 1 - Introduction |
| 7 | 7 | =========================================== |
| 8 | 8 | |
| 9 | −In an ARM system, the hierarchy of CPUs is defined through three entities that | |
| 9 | +In a SMP system, the hierarchy of CPUs is defined through three entities that | |
| 10 | 10 | are used to describe the layout of physical CPUs in the system: |
| 11 | 11 | |
| 12 | +- socket | |
| 12 | 13 | - cluster |
| 13 | 14 | - core |
| 14 | 15 | - thread |
| 15 | 16 | |
| 16 | −The cpu nodes (bindings defined in [1]) represent the devices that | |
| 17 | −correspond to physical CPUs and are to be mapped to the hierarchy levels. | |
| 18 | − | |
| 19 | 17 | The bottom hierarchy level sits at core or thread level depending on whether |
| 20 | 18 | symmetric multi-threading (SMT) is supported or not. |
| 21 | 19 | |
| @@ -24,33 +22,31 @@ threads existing in the system and map to the hierarchy level "thread" above. · 2 unmodified lines | ||
| 24 | 22 | In systems where SMT is not supported "cpu" nodes represent all cores present |
| 25 | 23 | in the system and map to the hierarchy level "core" above. |
| 26 | 24 | |
| 27 | −ARM topology bindings allow one to associate cpu nodes with hierarchical groups | |
| 25 | +CPU topology bindings allow one to associate cpu nodes with hierarchical groups | |
| 28 | 26 | corresponding to the system hierarchy; syntactically they are defined as device |
| 29 | 27 | tree nodes. |
| 30 | 28 | |
| 31 | −The remainder of this document provides the topology bindings for ARM, based | |
| 32 | −on the Devicetree Specification, available from: | |
| 29 | +Currently, only ARM/RISC-V intend to use this cpu topology binding but it may be | |
| 30 | +used for any other architecture as well. | |
| 33 | 31 | |
| 34 | −https://www.devicetree.org/specifications/ | |
| 32 | +The cpu nodes, as per bindings defined in [4], represent the devices that | |
| 33 | +correspond to physical CPUs and are to be mapped to the hierarchy levels. | |
| 35 | 34 | |
| 36 | −If not stated otherwise, whenever a reference to a cpu node phandle is made its | |
| 37 | −value must point to a cpu node compliant with the cpu node bindings as | |
| 38 | −documented in [1]. | |
| 39 | 35 | A topology description containing phandles to cpu nodes that are not compliant |
| 40 | −with bindings standardized in [1] is therefore considered invalid. | |
| 36 | +with bindings standardized in [4] is therefore considered invalid. | |
| 41 | 37 | |
| 42 | 38 | =========================================== |
| 43 | 39 | 2 - cpu-map node |
| 44 | 40 | =========================================== |
| 45 | 41 | |
| 46 | −The ARM CPU topology is defined within the cpu-map node, which is a direct | |
| 42 | +The ARM/RISC-V CPU topology is defined within the cpu-map node, which is a direct | |
| 47 | 43 | child of the cpus node and provides a container where the actual topology |
| 48 | 44 | nodes are listed. |
| 49 | 45 | |
| 50 | 46 | - cpu-map node |
| 51 | 47 | |
| 52 | − Usage: Optional - On ARM SMP systems provide CPUs topology to the OS. | |
| 53 | − ARM uniprocessor systems do not require a topology | |
| 48 | + Usage: Optional - On SMP systems provide CPUs topology to the OS. | |
| 49 | + Uniprocessor systems do not require a topology | |
| 54 | 50 | description and therefore should not define a |
| 55 | 51 | cpu-map node. |
| 56 | 52 | |
| @@ -63,21 +59,23 @@ nodes are listed. · 6 unmodified lines | ||
| 63 | 59 | |
| 64 | 60 | The cpu-map node's child nodes can be: |
| 65 | 61 | |
| 66 | − - one or more cluster nodes | |
| 62 | + - one or more cluster nodes or | |
| 63 | + - one or more socket nodes in a multi-socket system | |
| 67 | 64 | |
| 68 | 65 | Any other configuration is considered invalid. |
| 69 | 66 | |
| 70 | −The cpu-map node can only contain three types of child nodes: | |
| 67 | +The cpu-map node can only contain 4 types of child nodes: | |
| 71 | 68 | |
| 69 | +- socket node | |
| 72 | 70 | - cluster node |
| 73 | 71 | - core node |
| 74 | 72 | - thread node |
| 75 | 73 | |
| 76 | 74 | whose bindings are described in paragraph 3. |
| 77 | 75 | |
| 78 | −The nodes describing the CPU topology (cluster/core/thread) can only | |
| 79 | −be defined within the cpu-map node and every core/thread in the system | |
| 80 | −must be defined within the topology. Any other configuration is | |
| 76 | +The nodes describing the CPU topology (socket/cluster/core/thread) can | |
| 77 | +only be defined within the cpu-map node and every core/thread in the | |
| 78 | +system must be defined within the topology. Any other configuration is | |
| 81 | 79 | invalid and therefore must be ignored. |
| 82 | 80 | |
| 83 | 81 | =========================================== |
| @@ -85,26 +83,44 @@ invalid and therefore must be ignored. · 1 unmodified line | ||
| 85 | 83 | =========================================== |
| 86 | 84 | |
| 87 | 85 | cpu-map child nodes must follow a naming convention where the node name |
| 88 | −must be "clusterN", "coreN", "threadN" depending on the node type (ie | |
| 89 | −cluster/core/thread) (where N = {0, 1, ...} is the node number; nodes which | |
| 90 | −are siblings within a single common parent node must be given a unique and | |
| 86 | +must be "socketN", "clusterN", "coreN", "threadN" depending on the node type | |
| 87 | +(ie socket/cluster/core/thread) (where N = {0, 1, ...} is the node number; nodes | |
| 88 | +which are siblings within a single common parent node must be given a unique and | |
| 91 | 89 | sequential N value, starting from 0). |
| 92 | 90 | cpu-map child nodes which do not share a common parent node can have the same |
| 93 | 91 | name (ie same number N as other cpu-map child nodes at different device tree |
| 94 | 92 | levels) since name uniqueness will be guaranteed by the device tree hierarchy. |
| 95 | 93 | |
| 96 | 94 | =========================================== |
| 97 | −3 - cluster/core/thread node bindings | |
| 95 | +3 - socket/cluster/core/thread node bindings | |
| 98 | 96 | =========================================== |
| 99 | 97 | |
| 100 | −Bindings for cluster/cpu/thread nodes are defined as follows: | |
| 98 | +Bindings for socket/cluster/cpu/thread nodes are defined as follows: | |
| 99 | + | |
| 100 | +- socket node | |
| 101 | + | |
| 102 | + Description: must be declared within a cpu-map node, one node | |
| 103 | + per physical socket in the system. A system can | |
| 104 | + contain single or multiple physical socket. | |
| 105 | + The association of sockets and NUMA nodes is beyond | |
| 106 | + the scope of this bindings, please refer [2] for | |
| 107 | + NUMA bindings. | |
| 108 | + | |
| 109 | + This node is optional for a single socket system. | |
| 110 | + | |
| 111 | + The socket node name must be "socketN" as described in 2.1 above. | |
| 112 | + A socket node can not be a leaf node. | |
| 113 | + | |
| 114 | + A socket node's child nodes must be one or more cluster nodes. | |
| 115 | + | |
| 116 | + Any other configuration is considered invalid. | |
| 101 | 117 | |
| 102 | 118 | - cluster node |
| 103 | 119 | |
| 104 | 120 | Description: must be declared within a cpu-map node, one node |
| 105 | 121 | per cluster. A system can contain several layers of |
| 106 | − clustering and cluster nodes can be contained in parent | |
| 107 | − cluster nodes. | |
| 122 | + clustering within a single physical socket and cluster | |
| 123 | + nodes can be contained in parent cluster nodes. | |
| 108 | 124 | |
| 109 | 125 | The cluster node name must be "clusterN" as described in 2.1 above. |
| 110 | 126 | A cluster node can not be a leaf node. |
| @@ -164,90 +180,93 @@ Bindings for cluster/cpu/thread nodes are defined as follows: · 53 unmodified lines | ||
| 164 | 180 | 4 - Example dts |
| 165 | 181 | =========================================== |
| 166 | 182 | |
| 167 | −Example 1 (ARM 64-bit, 16-cpu system, two clusters of clusters): | |
| 183 | +Example 1 (ARM 64-bit, 16-cpu system, two clusters of clusters in a single | |
| 184 | +physical socket): | |
| 168 | 185 | |
| 169 | 186 | cpus { |
| 170 | 187 | #size-cells = <0>; |
| 171 | 188 | #address-cells = <2>; |
| 172 | 189 | |
| 173 | 190 | cpu-map { |
| 174 | − cluster0 { | |
| 191 | + socket0 { | |
| 175 | 192 | cluster0 { |
| 176 | − core0 { | |
| 177 | − thread0 { | |
| 178 | − cpu = <&CPU0>; | |
| 193 | + cluster0 { | |
| 194 | + core0 { | |
| 195 | + thread0 { | |
| 196 | + cpu = <&CPU0>; | |
| 197 | + }; | |
| 198 | + thread1 { | |
| 199 | + cpu = <&CPU1>; | |
| 200 | + }; | |
| 179 | 201 | }; |
| 180 | − thread1 { | |
| 181 | − cpu = <&CPU1>; | |
| 182 | − }; | |
| 183 | − }; | |
| 184 | 202 | |
| 185 | − core1 { | |
| 186 | − thread0 { | |
| 187 | − cpu = <&CPU2>; | |
| 188 | − }; | |
| 189 | − thread1 { | |
| 190 | − cpu = <&CPU3>; | |
| 203 | + core1 { | |
| 204 | + thread0 { | |
| 205 | + cpu = <&CPU2>; | |
| 206 | + }; | |
| 207 | + thread1 { | |
| 208 | + cpu = <&CPU3>; | |
| 209 | + }; | |
| 191 | 210 | }; |
| 192 | 211 | }; |
| 193 | − }; | |
| 194 | 212 | |
| 195 | − cluster1 { | |
| 196 | − core0 { | |
| 197 | − thread0 { | |
| 198 | − cpu = <&CPU4>; | |
| 199 | − }; | |
| 200 | − thread1 { | |
| 201 | − cpu = <&CPU5>; | |
| 213 | + cluster1 { | |
| 214 | + core0 { | |
| 215 | + thread0 { | |
| 216 | + cpu = <&CPU4>; | |
| 217 | + }; | |
| 218 | + thread1 { | |
| 219 | + cpu = <&CPU5>; | |
| 220 | + }; | |
| 202 | 221 | }; |
| 203 | − }; | |
| 204 | 222 | |
| 205 | − core1 { | |
| 206 | − thread0 { | |
| 207 | − cpu = <&CPU6>; | |
| 208 | − }; | |
| 209 | − thread1 { | |
| 210 | − cpu = <&CPU7>; | |
| 211 | − }; | |
| 212 | − }; | |
| 213 | − }; | |
| 214 | − }; | |
| 215 | − | |
| 216 | − cluster1 { | |
| 217 | − cluster0 { | |
| 218 | − core0 { | |
| 219 | − thread0 { | |
| 220 | − cpu = <&CPU8>; | |
| 221 | − }; | |
| 222 | − thread1 { | |
| 223 | − cpu = <&CPU9>; | |
| 224 | − }; | |
| 225 | − }; | |
| 226 | − core1 { | |
| 227 | − thread0 { | |
| 228 | − cpu = <&CPU10>; | |
| 229 | − }; | |
| 230 | − thread1 { | |
| 231 | − cpu = <&CPU11>; | |
| 223 | + core1 { | |
| 224 | + thread0 { | |
| 225 | + cpu = <&CPU6>; | |
| 226 | + }; | |
| 227 | + thread1 { | |
| 228 | + cpu = <&CPU7>; | |
| 229 | + }; | |
| 232 | 230 | }; |
| 233 | 231 | }; |
| 234 | 232 | }; |
| 235 | 233 | |
| 236 | 234 | cluster1 { |
| 237 | − core0 { | |
| 238 | − thread0 { | |
| 239 | − cpu = <&CPU12>; | |
| 235 | + cluster0 { | |
| 236 | + core0 { | |
| 237 | + thread0 { | |
| 238 | + cpu = <&CPU8>; | |
| 239 | + }; | |
| 240 | + thread1 { | |
| 241 | + cpu = <&CPU9>; | |
| 242 | + }; | |
| 240 | 243 | }; |
| 241 | − thread1 { | |
| 242 | − cpu = <&CPU13>; | |
| 244 | + core1 { | |
| 245 | + thread0 { | |
| 246 | + cpu = <&CPU10>; | |
| 247 | + }; | |
| 248 | + thread1 { | |
| 249 | + cpu = <&CPU11>; | |
| 250 | + }; | |
| 243 | 251 | }; |
| 244 | 252 | }; |
| 245 | − core1 { | |
| 246 | − thread0 { | |
| 247 | − cpu = <&CPU14>; | |
| 253 | + | |
| 254 | + cluster1 { | |
| 255 | + core0 { | |
| 256 | + thread0 { | |
| 257 | + cpu = <&CPU12>; | |
| 258 | + }; | |
| 259 | + thread1 { | |
| 260 | + cpu = <&CPU13>; | |
| 261 | + }; | |
| 248 | 262 | }; |
| 249 | − thread1 { | |
| 250 | − cpu = <&CPU15>; | |
| 263 | + core1 { | |
| 264 | + thread0 { | |
| 265 | + cpu = <&CPU14>; | |
| 266 | + }; | |
| 267 | + thread1 { | |
| 268 | + cpu = <&CPU15>; | |
| 269 | + }; | |
| 251 | 270 | }; |
| 252 | 271 | }; |
| 253 | 272 | }; |
| @@ -470,6 +489,65 @@ cpus { · 216 unmodified lines | ||
| 470 | 489 | }; |
| 471 | 490 | }; |
| 472 | 491 | |
| 492 | +Example 3: HiFive Unleashed (RISC-V 64 bit, 4 core system) | |
| 493 | + | |
| 494 | +{ | |
| 495 | + #address-cells = <2>; | |
| 496 | + #size-cells = <2>; | |
| 497 | + compatible = "sifive,fu540g", "sifive,fu500"; | |
| 498 | + model = "sifive,hifive-unleashed-a00"; | |
| 499 | + | |
| 500 | + ... | |
| 501 | + cpus { | |
| 502 | + #address-cells = <1>; | |
| 503 | + #size-cells = <0>; | |
| 504 | + cpu-map { | |
| 505 | + socket0 { | |
| 506 | + cluster0 { | |
| 507 | + core0 { | |
| 508 | + cpu = <&CPU1>; | |
| 509 | + }; | |
| 510 | + core1 { | |
| 511 | + cpu = <&CPU2>; | |
| 512 | + }; | |
| 513 | + core2 { | |
| 514 | + cpu0 = <&CPU2>; | |
| 515 | + }; | |
| 516 | + core3 { | |
| 517 | + cpu0 = <&CPU3>; | |
| 518 | + }; | |
| 519 | + }; | |
| 520 | + }; | |
| 521 | + }; | |
| 522 | + | |
| 523 | + CPU1: cpu@1 { | |
| 524 | + device_type = "cpu"; | |
| 525 | + compatible = "sifive,rocket0", "riscv"; | |
| 526 | + reg = <0x1>; | |
| 527 | + } | |
| 528 | + | |
| 529 | + CPU2: cpu@2 { | |
| 530 | + device_type = "cpu"; | |
| 531 | + compatible = "sifive,rocket0", "riscv"; | |
| 532 | + reg = <0x2>; | |
| 533 | + } | |
| 534 | + CPU3: cpu@3 { | |
| 535 | + device_type = "cpu"; | |
| 536 | + compatible = "sifive,rocket0", "riscv"; | |
| 537 | + reg = <0x3>; | |
| 538 | + } | |
| 539 | + CPU4: cpu@4 { | |
| 540 | + device_type = "cpu"; | |
| 541 | + compatible = "sifive,rocket0", "riscv"; | |
| 542 | + reg = <0x4>; | |
| 543 | + } | |
| 544 | + } | |
| 545 | +}; | |
| 473 | 546 | =============================================================================== |
| 474 | 547 | [1] ARM Linux kernel documentation |
| 475 | 548 | Documentation/devicetree/bindings/arm/cpus.yaml |
| 549 | +[2] Devicetree NUMA binding description | |
| 550 | + Documentation/devicetree/bindings/numa.txt | |
| 551 | +[3] RISC-V Linux kernel documentation | |
| 552 | + Documentation/devicetree/bindings/riscv/cpus.txt | |
| 553 | +[4] https://www.devicetree.org/specifications/ | |
| @@ -4290,6 +4290,14 @@ S: Supported · 4289 unmodified lines | ||
| 4290 | 4290 | F: drivers/cpuidle/cpuidle-exynos.c |
| 4291 | 4291 | F: arch/arm/mach-exynos/pm.c |
| 4292 | 4292 | |
| 4293 | +CPUIDLE DRIVER - ARM PSCI | |
| 4294 | +M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> | |
| 4295 | +M: Sudeep Holla <sudeep.holla@arm.com> | |
| 4296 | +L: linux-pm@vger.kernel.org | |
| 4297 | +L: linux-arm-kernel@lists.infradead.org | |
| 4298 | +S: Supported | |
| 4299 | +F: drivers/cpuidle/cpuidle-psci.c | |
| 4300 | + | |
| 4293 | 4301 | CPU IDLE TIME MANAGEMENT FRAMEWORK |
| 4294 | 4302 | M: "Rafael J. Wysocki" <rjw@rjwysocki.net> |
| 4295 | 4303 | M: Daniel Lezcano <daniel.lezcano@linaro.org> |
| @@ -6439,6 +6447,7 @@ M: Frank Li <Frank.li@nxp.com> · 2143 unmodified lines | ||
| 6439 | 6447 | L: linux-arm-kernel@lists.infradead.org |
| 6440 | 6448 | S: Maintained |
| 6441 | 6449 | F: drivers/perf/fsl_imx8_ddr_perf.c |
| 6450 | +F: Documentation/admin-guide/perf/imx-ddr.rst | |
| 6442 | 6451 | F: Documentation/devicetree/bindings/perf/fsl-imx-ddr.txt |
| 6443 | 6452 | |
| 6444 | 6453 | FREESCALE IMX LPI2C DRIVER |
| @@ -6724,6 +6733,13 @@ W: https://linuxtv.org · 279 unmodified lines | ||
| 6724 | 6733 | S: Maintained |
| 6725 | 6734 | F: drivers/media/radio/radio-gemtek* |
| 6726 | 6735 | |
| 6736 | +GENERIC ARCHITECTURE TOPOLOGY | |
| 6737 | +M: Sudeep Holla <sudeep.holla@arm.com> | |
| 6738 | +L: linux-kernel@vger.kernel.org | |
| 6739 | +S: Maintained | |
| 6740 | +F: drivers/base/arch_topology.c | |
| 6741 | +F: include/linux/arch_topology.h | |
| 6742 | + | |
| 6727 | 6743 | GENERIC GPIO I2C DRIVER |
| 6728 | 6744 | M: Wolfram Sang <wsa+renesas@sang-engineering.com> |
| 6729 | 6745 | S: Supported |
| @@ -5,26 +5,6 @@ · 4 unmodified lines | ||
| 5 | 5 | #ifdef CONFIG_ARM_CPU_TOPOLOGY |
| 6 | 6 | |
| 7 | 7 | #include <linux/cpumask.h> |
| 8 | − | |
| 9 | −struct cputopo_arm { | |
| 10 | − int thread_id; | |
| 11 | − int core_id; | |
| 12 | − int socket_id; | |
| 13 | − cpumask_t thread_sibling; | |
| 14 | − cpumask_t core_sibling; | |
| 15 | −}; | |
| 16 | − | |
| 17 | −extern struct cputopo_arm cpu_topology[NR_CPUS]; | |
| 18 | − | |
| 19 | −#define topology_physical_package_id(cpu) (cpu_topology[cpu].socket_id) | |
| 20 | −#define topology_core_id(cpu) (cpu_topology[cpu].core_id) | |
| 21 | −#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) | |
| 22 | −#define topology_sibling_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) | |
| 23 | − | |
| 24 | −void init_cpu_topology(void); | |
| 25 | −void store_cpu_topology(unsigned int cpuid); | |
| 26 | −const struct cpumask *cpu_coregroup_mask(int cpu); | |
| 27 | − | |
| 28 | 8 | #include <linux/arch_topology.h> |
| 29 | 9 | |
| 30 | 10 | /* Replace task scheduler's default frequency-invariant accounting */ |
| @@ -177,17 +177,6 @@ static inline void parse_dt_topology(void) {} · 176 unmodified lines | ||
| 177 | 177 | static inline void update_cpu_capacity(unsigned int cpuid) {} |
| 178 | 178 | #endif |
| 179 | 179 | |
| 180 | − /* | |
| 181 | − * cpu topology table | |
| 182 | − */ | |
| 183 | −struct cputopo_arm cpu_topology[NR_CPUS]; | |
| 184 | −EXPORT_SYMBOL_GPL(cpu_topology); | |
| 185 | − | |
| 186 | −const struct cpumask *cpu_coregroup_mask(int cpu) | |
| 187 | −{ | |
| 188 | − return &cpu_topology[cpu].core_sibling; | |
| 189 | −} | |
| 190 | − | |
| 191 | 180 | /* |
| 192 | 181 | * The current assumption is that we can power gate each core independently. |
| 193 | 182 | * This will be superseded by DT binding once available. |
| @@ -197,32 +186,6 @@ const struct cpumask *cpu_corepower_mask(int cpu) · 3 unmodified lines | ||
| 197 | 186 | return &cpu_topology[cpu].thread_sibling; |
| 198 | 187 | } |
| 199 | 188 | |
| 200 | −static void update_siblings_masks(unsigned int cpuid) | |
| 201 | −{ | |
| 202 | − struct cputopo_arm *cpu_topo, *cpuid_topo = &cpu_topology[cpuid]; | |
| 203 | − int cpu; | |
| 204 | − | |
| 205 | − /* update core and thread sibling masks */ | |
| 206 | − for_each_possible_cpu(cpu) { | |
| 207 | − cpu_topo = &cpu_topology[cpu]; | |
| 208 | − | |
| 209 | − if (cpuid_topo->socket_id != cpu_topo->socket_id) | |
| 210 | − continue; | |
| 211 | − | |
| 212 | − cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); | |
| 213 | − if (cpu != cpuid) | |
| 214 | − cpumask_set_cpu(cpu, &cpuid_topo->core_sibling); | |
| 215 | − | |
| 216 | − if (cpuid_topo->core_id != cpu_topo->core_id) | |
| 217 | − continue; | |
| 218 | − | |
| 219 | − cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling); | |
| 220 | − if (cpu != cpuid) | |
| 221 | − cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling); | |
| 222 | − } | |
| 223 | − smp_wmb(); | |
| 224 | −} | |
| 225 | − | |
| 226 | 189 | /* |
| 227 | 190 | * store_cpu_topology is called at boot when only one cpu is running |
| 228 | 191 | * and with the mutex cpu_hotplug.lock locked, when several cpus have booted, |
| @@ -230,7 +193,7 @@ static void update_siblings_masks(unsigned int cpuid) · 1 unmodified line | ||
| 230 | 193 | */ |
| 231 | 194 | void store_cpu_topology(unsigned int cpuid) |
| 232 | 195 | { |
| 233 | − struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid]; | |
| 196 | + struct cpu_topology *cpuid_topo = &cpu_topology[cpuid]; | |
| 234 | 197 | unsigned int mpidr; |
| 235 | 198 | |
| 236 | 199 | /* If the cpu topology has been already set, just return */ |
| @@ -250,12 +213,12 @@ void store_cpu_topology(unsigned int cpuid) · 13 unmodified lines | ||
| 250 | 213 | /* core performance interdependency */ |
| 251 | 214 | cpuid_topo->thread_id = MPIDR_AFFINITY_LEVEL(mpidr, 0); |
| 252 | 215 | cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 1); |
| 253 | − cpuid_topo->socket_id = MPIDR_AFFINITY_LEVEL(mpidr, 2); | |
| 216 | + cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 2); | |
| 254 | 217 | } else { |
| 255 | 218 | /* largely independent cores */ |
| 256 | 219 | cpuid_topo->thread_id = -1; |
| 257 | 220 | cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0); |
| 258 | − cpuid_topo->socket_id = MPIDR_AFFINITY_LEVEL(mpidr, 1); | |
| 221 | + cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 1); | |
| 259 | 222 | } |
| 260 | 223 | } else { |
| 261 | 224 | /* |
| @@ -265,7 +228,7 @@ void store_cpu_topology(unsigned int cpuid) · 3 unmodified lines | ||
| 265 | 228 | */ |
| 266 | 229 | cpuid_topo->thread_id = -1; |
| 267 | 230 | cpuid_topo->core_id = 0; |
| 268 | − cpuid_topo->socket_id = -1; | |
| 231 | + cpuid_topo->package_id = -1; | |
| 269 | 232 | } |
| 270 | 233 | |
| 271 | 234 | update_siblings_masks(cpuid); |
| @@ -275,7 +238,7 @@ void store_cpu_topology(unsigned int cpuid) · 3 unmodified lines | ||
| 275 | 238 | pr_info("CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", |
| 276 | 239 | cpuid, cpu_topology[cpuid].thread_id, |
| 277 | 240 | cpu_topology[cpuid].core_id, |
| 278 | − cpu_topology[cpuid].socket_id, mpidr); | |
| 241 | + cpu_topology[cpuid].package_id, mpidr); | |
| 279 | 242 | } |
| 280 | 243 | |
| 281 | 244 | static inline int cpu_corepower_flags(void) |
| @@ -298,18 +261,7 @@ static struct sched_domain_topology_level arm_topology[] = { · 16 unmodified lines | ||
| 298 | 261 | */ |
| 299 | 262 | void __init init_cpu_topology(void) |
| 300 | 263 | { |
| 301 | − unsigned int cpu; | |
| 302 | − | |
| 303 | − /* init core mask and capacity */ | |
| 304 | − for_each_possible_cpu(cpu) { | |
| 305 | − struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]); | |
| 306 | − | |
| 307 | − cpu_topo->thread_id = -1; | |
| 308 | − cpu_topo->core_id = -1; | |
| 309 | − cpu_topo->socket_id = -1; | |
| 310 | − cpumask_clear(&cpu_topo->core_sibling); | |
| 311 | − cpumask_clear(&cpu_topo->thread_sibling); | |
| 312 | − } | |
| 264 | + reset_cpu_topology(); | |
| 313 | 265 | smp_wmb(); |
| 314 | 266 | |
| 315 | 267 | parse_dt_topology(); |
| @@ -148,6 +148,7 @@ config ARM64 · 147 unmodified lines | ||
| 148 | 148 | select HAVE_FAST_GUP |
| 149 | 149 | select HAVE_FTRACE_MCOUNT_RECORD |
| 150 | 150 | select HAVE_FUNCTION_TRACER |
| 151 | + select HAVE_FUNCTION_ERROR_INJECTION | |
| 151 | 152 | select HAVE_FUNCTION_GRAPH_TRACER |
| 152 | 153 | select HAVE_GCC_PLUGINS |
| 153 | 154 | select HAVE_HW_BREAKPOINT if PERF_EVENTS |
| @@ -286,7 +287,7 @@ config PGTABLE_LEVELS · 132 unmodified lines | ||
| 286 | 287 | int |
| 287 | 288 | default 2 if ARM64_16K_PAGES && ARM64_VA_BITS_36 |
| 288 | 289 | default 2 if ARM64_64K_PAGES && ARM64_VA_BITS_42 |
| 289 | − default 3 if ARM64_64K_PAGES && (ARM64_VA_BITS_48 || ARM64_USER_VA_BITS_52) | |
| 290 | + default 3 if ARM64_64K_PAGES && (ARM64_VA_BITS_48 || ARM64_VA_BITS_52) | |
| 290 | 291 | default 3 if ARM64_4K_PAGES && ARM64_VA_BITS_39 |
| 291 | 292 | default 3 if ARM64_16K_PAGES && ARM64_VA_BITS_47 |
| 292 | 293 | default 4 if !ARM64_64K_PAGES && ARM64_VA_BITS_48 |
| @@ -297,6 +298,21 @@ config ARCH_SUPPORTS_UPROBES · 4 unmodified lines | ||
| 297 | 298 | config ARCH_PROC_KCORE_TEXT |
| 298 | 299 | def_bool y |
| 299 | 300 | |
| 301 | +config KASAN_SHADOW_OFFSET | |
| 302 | + hex | |
| 303 | + depends on KASAN | |
| 304 | + default 0xdfffa00000000000 if (ARM64_VA_BITS_48 || ARM64_VA_BITS_52) && !KASAN_SW_TAGS | |
| 305 | + default 0xdfffd00000000000 if ARM64_VA_BITS_47 && !KASAN_SW_TAGS | |
| 306 | + default 0xdffffe8000000000 if ARM64_VA_BITS_42 && !KASAN_SW_TAGS | |
| 307 | + default 0xdfffffd000000000 if ARM64_VA_BITS_39 && !KASAN_SW_TAGS | |
| 308 | + default 0xdffffffa00000000 if ARM64_VA_BITS_36 && !KASAN_SW_TAGS | |
| 309 | + default 0xefff900000000000 if (ARM64_VA_BITS_48 || ARM64_VA_BITS_52) && KASAN_SW_TAGS | |
| 310 | + default 0xefffc80000000000 if ARM64_VA_BITS_47 && KASAN_SW_TAGS | |
| 311 | + default 0xeffffe4000000000 if ARM64_VA_BITS_42 && KASAN_SW_TAGS | |
| 312 | + default 0xefffffc800000000 if ARM64_VA_BITS_39 && KASAN_SW_TAGS | |
| 313 | + default 0xeffffff900000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS | |
| 314 | + default 0xffffffffffffffff | |
| 315 | + | |
| 300 | 316 | source "arch/arm64/Kconfig.platforms" |
| 301 | 317 | |
| 302 | 318 | menu "Kernel Features" |
| @@ -744,13 +760,14 @@ config ARM64_VA_BITS_47 · 441 unmodified lines | ||
| 744 | 760 | config ARM64_VA_BITS_48 |
| 745 | 761 | bool "48-bit" |
| 746 | 762 | |
| 747 | −config ARM64_USER_VA_BITS_52 | |
| 748 | − bool "52-bit (user)" | |
| 763 | +config ARM64_VA_BITS_52 | |
| 764 | + bool "52-bit" | |
| 749 | 765 | depends on ARM64_64K_PAGES && (ARM64_PAN || !ARM64_SW_TTBR0_PAN) |
| 750 | 766 | help |
| 751 | 767 | Enable 52-bit virtual addressing for userspace when explicitly |
| 752 | − requested via a hint to mmap(). The kernel will continue to | |
| 753 | − use 48-bit virtual addresses for its own mappings. | |
| 768 | + requested via a hint to mmap(). The kernel will also use 52-bit | |
| 769 | + virtual addresses for its own mappings (provided HW support for | |
| 770 | + this feature is available, otherwise it reverts to 48-bit). | |
| 754 | 771 | |
| 755 | 772 | NOTE: Enabling 52-bit virtual addressing in conjunction with |
| 756 | 773 | ARMv8.3 Pointer Authentication will result in the PAC being |
| @@ -763,7 +780,7 @@ endchoice · 6 unmodified lines | ||
| 763 | 780 | |
| 764 | 781 | config ARM64_FORCE_52BIT |
| 765 | 782 | bool "Force 52-bit virtual addresses for userspace" |
| 766 | − depends on ARM64_USER_VA_BITS_52 && EXPERT | |
| 783 | + depends on ARM64_VA_BITS_52 && EXPERT | |
| 767 | 784 | help |
| 768 | 785 | For systems with 52-bit userspace VAs enabled, the kernel will attempt |
| 769 | 786 | to maintain compatibility with older software by providing 48-bit VAs |
| @@ -780,7 +797,8 @@ config ARM64_VA_BITS · 10 unmodified lines | ||
| 780 | 797 | default 39 if ARM64_VA_BITS_39 |
| 781 | 798 | default 42 if ARM64_VA_BITS_42 |
| 782 | 799 | default 47 if ARM64_VA_BITS_47 |
| 783 | − default 48 if ARM64_VA_BITS_48 || ARM64_USER_VA_BITS_52 | |
| 800 | + default 48 if ARM64_VA_BITS_48 | |
| 801 | + default 52 if ARM64_VA_BITS_52 | |
| 784 | 802 | |
| 785 | 803 | choice |
| 786 | 804 | prompt "Physical address space size" |
| @@ -1110,6 +1128,15 @@ config ARM64_SW_TTBR0_PAN · 323 unmodified lines | ||
| 1110 | 1128 | zeroed area and reserved ASID. The user access routines |
| 1111 | 1129 | restore the valid TTBR0_EL1 temporarily. |
| 1112 | 1130 | |
| 1131 | +config ARM64_TAGGED_ADDR_ABI | |
| 1132 | + bool "Enable the tagged user addresses syscall ABI" | |
| 1133 | + default y | |
| 1134 | + help | |
| 1135 | + When this option is enabled, user applications can opt in to a | |
| 1136 | + relaxed ABI via prctl() allowing tagged addresses to be passed | |
| 1137 | + to system calls as pointer arguments. For details, see | |
| 1138 | + Documentation/arm64/tagged-address-abi.txt. | |
| 1139 | + | |
| 1113 | 1140 | menuconfig COMPAT |
| 1114 | 1141 | bool "Kernel support for 32-bit EL0" |
| 1115 | 1142 | depends on ARM64_4K_PAGES || EXPERT |
| @@ -126,14 +126,6 @@ KBUILD_CFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT) · 125 unmodified lines | ||
| 126 | 126 | KBUILD_CPPFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT) |
| 127 | 127 | KBUILD_AFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT) |
| 128 | 128 | |
| 129 | −# KASAN_SHADOW_OFFSET = VA_START + (1 << (VA_BITS - KASAN_SHADOW_SCALE_SHIFT)) | |
| 130 | −# - (1 << (64 - KASAN_SHADOW_SCALE_SHIFT)) | |
| 131 | −# in 32-bit arithmetic | |
| 132 | −KASAN_SHADOW_OFFSET := $(shell printf "0x%08x00000000\n" $$(( \ | |
| 133 | − (0xffffffff & (-1 << ($(CONFIG_ARM64_VA_BITS) - 32))) \ | |
| 134 | − + (1 << ($(CONFIG_ARM64_VA_BITS) - 32 - $(KASAN_SHADOW_SCALE_SHIFT))) \ | |
| 135 | − - (1 << (64 - 32 - $(KASAN_SHADOW_SCALE_SHIFT))) )) ) | |
| 136 | − | |
| 137 | 129 | export TEXT_OFFSET GZFLAGS |
| 138 | 130 | |
| 139 | 131 | core-y += arch/arm64/ |
| @@ -338,6 +338,13 @@ alternative_endif · 337 unmodified lines | ||
| 338 | 338 | bfi \valreg, \t0sz, #TCR_T0SZ_OFFSET, #TCR_TxSZ_WIDTH |
| 339 | 339 | .endm |
| 340 | 340 | |
| 341 | +/* | |
| 342 | + * tcr_set_t1sz - update TCR.T1SZ | |
| 343 | + */ | |
| 344 | + .macro tcr_set_t1sz, valreg, t1sz | |
| 345 | + bfi \valreg, \t1sz, #TCR_T1SZ_OFFSET, #TCR_TxSZ_WIDTH | |
| 346 | + .endm | |
| 347 | + | |
| 341 | 348 | /* |
| 342 | 349 | * tcr_compute_pa_size - set TCR.(I)PS to the highest supported |
| 343 | 350 | * ID_AA64MMFR0_EL1.PARange value |
| @@ -527,9 +534,13 @@ USER(\label, ic ivau, \tmp2) // invalidate I line PoU · 183 unmodified lines | ||
| 527 | 534 | * In future this may be nop'ed out when dealing with 52-bit kernel VAs. |
| 528 | 535 | * ttbr: Value of ttbr to set, modified. |
| 529 | 536 | */ |
| 530 | − .macro offset_ttbr1, ttbr | |
| 531 | −#ifdef CONFIG_ARM64_USER_VA_BITS_52 | |
| 537 | + .macro offset_ttbr1, ttbr, tmp | |
| 538 | +#ifdef CONFIG_ARM64_VA_BITS_52 | |
| 539 | + mrs_s \tmp, SYS_ID_AA64MMFR2_EL1 | |
| 540 | + and \tmp, \tmp, #(0xf << ID_AA64MMFR2_LVA_SHIFT) | |
| 541 | + cbnz \tmp, .Lskipoffs_\@ | |
| 532 | 542 | orr \ttbr, \ttbr, #TTBR1_BADDR_4852_OFFSET |
| 543 | +.Lskipoffs_\@ : | |
| 533 | 544 | #endif |
| 534 | 545 | .endm |
| 535 | 546 | |
| @@ -539,7 +550,7 @@ USER(\label, ic ivau, \tmp2) // invalidate I line PoU · 3 unmodified lines | ||
| 539 | 550 | * to be nop'ed out when dealing with 52-bit kernel VAs. |
| 540 | 551 | */ |
| 541 | 552 | .macro restore_ttbr1, ttbr |
| 542 | −#ifdef CONFIG_ARM64_USER_VA_BITS_52 | |
| 553 | +#ifdef CONFIG_ARM64_VA_BITS_52 | |
| 543 | 554 | bic \ttbr, \ttbr, #TTBR1_BADDR_4852_OFFSET |
| 544 | 555 | #endif |
| 545 | 556 | .endm |
| @@ -23,6 +23,8 @@ · 22 unmodified lines | ||
| 23 | 23 | * @cpu_boot: Boots a cpu into the kernel. |
| 24 | 24 | * @cpu_postboot: Optionally, perform any post-boot cleanup or necesary |
| 25 | 25 | * synchronisation. Called from the cpu being booted. |
| 26 | + * @cpu_can_disable: Determines whether a CPU can be disabled based on | |
| 27 | + * mechanism-specific information. | |
| 26 | 28 | * @cpu_disable: Prepares a cpu to die. May fail for some mechanism-specific |
| 27 | 29 | * reason, which will cause the hot unplug to be aborted. Called |
| 28 | 30 | * from the cpu to be killed. |
| @@ -42,6 +44,7 @@ struct cpu_operations { · 13 unmodified lines | ||
| 42 | 44 | int (*cpu_boot)(unsigned int); |
| 43 | 45 | void (*cpu_postboot)(void); |
| 44 | 46 | #ifdef CONFIG_HOTPLUG_CPU |
| 47 | + bool (*cpu_can_disable)(unsigned int cpu); | |
| 45 | 48 | int (*cpu_disable)(unsigned int cpu); |
| 46 | 49 | void (*cpu_die)(unsigned int cpu); |
| 47 | 50 | int (*cpu_kill)(unsigned int cpu); |
| @@ -79,7 +79,7 @@ static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base) · 78 unmodified lines | ||
| 79 | 79 | |
| 80 | 80 | /* |
| 81 | 81 | * On arm64, we have to ensure that the initrd ends up in the linear region, |
| 82 | − * which is a 1 GB aligned region of size '1UL << (VA_BITS - 1)' that is | |
| 82 | + * which is a 1 GB aligned region of size '1UL << (VA_BITS_MIN - 1)' that is | |
| 83 | 83 | * guaranteed to cover the kernel Image. |
| 84 | 84 | * |
| 85 | 85 | * Since the EFI stub is part of the kernel Image, we can relax the |
| @@ -90,7 +90,7 @@ static inline unsigned long efi_get_max_fdt_addr(unsigned long dram_base) · 4 unmodified lines | ||
| 90 | 90 | static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base, |
| 91 | 91 | unsigned long image_addr) |
| 92 | 92 | { |
| 93 | − return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS - 1)); | |
| 93 | + return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS_MIN - 1)); | |
| 94 | 94 | } |
| 95 | 95 | |
| 96 | 96 | #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) |
| @@ -18,11 +18,8 @@ · 17 unmodified lines | ||
| 18 | 18 | * KASAN_SHADOW_START: beginning of the kernel virtual addresses. |
| 19 | 19 | * KASAN_SHADOW_END: KASAN_SHADOW_START + 1/N of kernel virtual addresses, |
| 20 | 20 | * where N = (1 << KASAN_SHADOW_SCALE_SHIFT). |
| 21 | − */ | |
| 22 | −#define KASAN_SHADOW_START (VA_START) | |
| 23 | −#define KASAN_SHADOW_END (KASAN_SHADOW_START + KASAN_SHADOW_SIZE) | |
| 24 | − | |
| 25 | −/* | |
| 21 | + * | |
| 22 | + * KASAN_SHADOW_OFFSET: | |
| 26 | 23 | * This value is used to map an address to the corresponding shadow |
| 27 | 24 | * address by the following formula: |
| 28 | 25 | * shadow_addr = (address >> KASAN_SHADOW_SCALE_SHIFT) + KASAN_SHADOW_OFFSET |
| @@ -33,8 +30,8 @@ · 4 unmodified lines | ||
| 33 | 30 | * KASAN_SHADOW_OFFSET = KASAN_SHADOW_END - |
| 34 | 31 | * (1ULL << (64 - KASAN_SHADOW_SCALE_SHIFT)) |
| 35 | 32 | */ |
| 36 | −#define KASAN_SHADOW_OFFSET (KASAN_SHADOW_END - (1ULL << \ | |
| 37 | − (64 - KASAN_SHADOW_SCALE_SHIFT))) | |
| 33 | +#define _KASAN_SHADOW_START(va) (KASAN_SHADOW_END - (1UL << ((va) - KASAN_SHADOW_SCALE_SHIFT))) | |
| 34 | +#define KASAN_SHADOW_START _KASAN_SHADOW_START(vabits_actual) | |
| 38 | 35 | |
| 39 | 36 | void kasan_init(void); |
| 40 | 37 | void kasan_copy_shadow(pgd_t *pgdir); |
| @@ -12,10 +12,10 @@ · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | #include <linux/compiler.h> |
| 14 | 14 | #include <linux/const.h> |
| 15 | +#include <linux/sizes.h> | |
| 15 | 16 | #include <linux/types.h> |
| 16 | 17 | #include <asm/bug.h> |
| 17 | 18 | #include <asm/page-def.h> |
| 18 | −#include <linux/sizes.h> | |
| 19 | 19 | |
| 20 | 20 | /* |
| 21 | 21 | * Size of the PCI I/O space. This must remain a power of two so that |
| @@ -26,37 +26,50 @@ · 4 unmodified lines | ||
| 26 | 26 | /* |
| 27 | 27 | * VMEMMAP_SIZE - allows the whole linear region to be covered by |
| 28 | 28 | * a struct page array |
| 29 | + * | |
| 30 | + * If we are configured with a 52-bit kernel VA then our VMEMMAP_SIZE | |
| 31 | + * needs to cover the memory region from the beginning of the 52-bit | |
| 32 | + * PAGE_OFFSET all the way to PAGE_END for 48-bit. This allows us to | |
| 33 | + * keep a constant PAGE_OFFSET and "fallback" to using the higher end | |
| 34 | + * of the VMEMMAP where 52-bit support is not available in hardware. | |
| 29 | 35 | */ |
| 30 | −#define VMEMMAP_SIZE (UL(1) << (VA_BITS - PAGE_SHIFT - 1 + STRUCT_PAGE_MAX_SHIFT)) | |
| 36 | +#define VMEMMAP_SIZE ((_PAGE_END(VA_BITS_MIN) - PAGE_OFFSET) \ | |
| 37 | + >> (PAGE_SHIFT - STRUCT_PAGE_MAX_SHIFT)) | |
| 31 | 38 | |
| 32 | 39 | /* |
| 33 | − * PAGE_OFFSET - the virtual address of the start of the linear map (top | |
| 34 | − * (VA_BITS - 1)) | |
| 35 | − * KIMAGE_VADDR - the virtual address of the start of the kernel image | |
| 40 | + * PAGE_OFFSET - the virtual address of the start of the linear map, at the | |
| 41 | + * start of the TTBR1 address space. | |
| 42 | + * PAGE_END - the end of the linear map, where all other kernel mappings begin. | |
| 43 | + * KIMAGE_VADDR - the virtual address of the start of the kernel image. | |
| 36 | 44 | * VA_BITS - the maximum number of bits for virtual addresses. |
| 37 | − * VA_START - the first kernel virtual address. | |
| 38 | 45 | */ |
| 39 | 46 | #define VA_BITS (CONFIG_ARM64_VA_BITS) |
| 40 | −#define VA_START (UL(0xffffffffffffffff) - \ | |
| 41 | − (UL(1) << VA_BITS) + 1) | |
| 42 | −#define PAGE_OFFSET (UL(0xffffffffffffffff) - \ | |
| 43 | − (UL(1) << (VA_BITS - 1)) + 1) | |
| 47 | +#define _PAGE_OFFSET(va) (-(UL(1) << (va))) | |
| 48 | +#define PAGE_OFFSET (_PAGE_OFFSET(VA_BITS)) | |
| 44 | 49 | #define KIMAGE_VADDR (MODULES_END) |
| 45 | −#define BPF_JIT_REGION_START (VA_START + KASAN_SHADOW_SIZE) | |
| 50 | +#define BPF_JIT_REGION_START (KASAN_SHADOW_END) | |
| 46 | 51 | #define BPF_JIT_REGION_SIZE (SZ_128M) |
| 47 | 52 | #define BPF_JIT_REGION_END (BPF_JIT_REGION_START + BPF_JIT_REGION_SIZE) |
| 48 | 53 | #define MODULES_END (MODULES_VADDR + MODULES_VSIZE) |
| 49 | 54 | #define MODULES_VADDR (BPF_JIT_REGION_END) |
| 50 | 55 | #define MODULES_VSIZE (SZ_128M) |
| 51 | −#define VMEMMAP_START (PAGE_OFFSET - VMEMMAP_SIZE) | |
| 56 | +#define VMEMMAP_START (-VMEMMAP_SIZE - SZ_2M) | |
| 52 | 57 | #define PCI_IO_END (VMEMMAP_START - SZ_2M) |
| 53 | 58 | #define PCI_IO_START (PCI_IO_END - PCI_IO_SIZE) |
| 54 | 59 | #define FIXADDR_TOP (PCI_IO_START - SZ_2M) |
| 55 | 60 | |
| 56 | −#define KERNEL_START _text | |
| 57 | −#define KERNEL_END _end | |
| 61 | +#if VA_BITS > 48 | |
| 62 | +#define VA_BITS_MIN (48) | |
| 63 | +#else | |
| 64 | +#define VA_BITS_MIN (VA_BITS) | |
| 65 | +#endif | |
| 66 | + | |
| 67 | +#define _PAGE_END(va) (-(UL(1) << ((va) - 1))) | |
| 58 | 68 | |
| 59 | −#ifdef CONFIG_ARM64_USER_VA_BITS_52 | |
| 69 | +#define KERNEL_START _text | |
| 70 | +#define KERNEL_END _end | |
| 71 | + | |
| 72 | +#ifdef CONFIG_ARM64_VA_BITS_52 | |
| 60 | 73 | #define MAX_USER_VA_BITS 52 |
| 61 | 74 | #else |
| 62 | 75 | #define MAX_USER_VA_BITS VA_BITS |
| @@ -68,12 +81,14 @@ · 5 unmodified lines | ||
| 68 | 81 | * significantly, so double the (minimum) stack size when they are in use. |
| 69 | 82 | */ |
| 70 | 83 | #ifdef CONFIG_KASAN |
| 71 | −#define KASAN_SHADOW_SIZE (UL(1) << (VA_BITS - KASAN_SHADOW_SCALE_SHIFT)) | |
| 84 | +#define KASAN_SHADOW_OFFSET _AC(CONFIG_KASAN_SHADOW_OFFSET, UL) | |
| 85 | +#define KASAN_SHADOW_END ((UL(1) << (64 - KASAN_SHADOW_SCALE_SHIFT)) \ | |
| 86 | + + KASAN_SHADOW_OFFSET) | |
| 72 | 87 | #define KASAN_THREAD_SHIFT 1 |
| 73 | 88 | #else |
| 74 | −#define KASAN_SHADOW_SIZE (0) | |
| 75 | 89 | #define KASAN_THREAD_SHIFT 0 |
| 76 | −#endif | |
| 90 | +#define KASAN_SHADOW_END (_PAGE_END(VA_BITS_MIN)) | |
| 91 | +#endif /* CONFIG_KASAN */ | |
| 77 | 92 | |
| 78 | 93 | #define MIN_THREAD_SHIFT (14 + KASAN_THREAD_SHIFT) |
| 79 | 94 | |
| @@ -117,14 +132,14 @@ · 37 unmodified lines | ||
| 117 | 132 | * 16 KB granule: 128 level 3 entries, with contiguous bit |
| 118 | 133 | * 64 KB granule: 32 level 3 entries, with contiguous bit |
| 119 | 134 | */ |
| 120 | −#define SEGMENT_ALIGN SZ_2M | |
| 135 | +#define SEGMENT_ALIGN SZ_2M | |
| 121 | 136 | #else |
| 122 | 137 | /* |
| 123 | 138 | * 4 KB granule: 16 level 3 entries, with contiguous bit |
| 124 | 139 | * 16 KB granule: 4 level 3 entries, without contiguous bit |
| 125 | 140 | * 64 KB granule: 1 level 3 entry |
| 126 | 141 | */ |
| 127 | −#define SEGMENT_ALIGN SZ_64K | |
| 142 | +#define SEGMENT_ALIGN SZ_64K | |
| 128 | 143 | #endif |
| 129 | 144 | |
| 130 | 145 | /* |
| @@ -157,10 +172,13 @@ · 26 unmodified lines | ||
| 157 | 172 | #endif |
| 158 | 173 | |
| 159 | 174 | #ifndef __ASSEMBLY__ |
| 175 | +extern u64 vabits_actual; | |
| 176 | +#define PAGE_END (_PAGE_END(vabits_actual)) | |
| 160 | 177 | |
| 161 | 178 | #include <linux/bitops.h> |
| 162 | 179 | #include <linux/mmdebug.h> |
| 163 | 180 | |
| 181 | +extern s64 physvirt_offset; | |
| 164 | 182 | extern s64 memstart_addr; |
| 165 | 183 | /* PHYS_OFFSET - the physical address of the start of memory. */ |
| 166 | 184 | #define PHYS_OFFSET ({ VM_BUG_ON(memstart_addr & 1); memstart_addr; }) |
| @@ -176,9 +194,6 @@ static inline unsigned long kaslr_offset(void) · 9 unmodified lines | ||
| 176 | 194 | return kimage_vaddr - KIMAGE_VADDR; |
| 177 | 195 | } |
| 178 | 196 | |
| 179 | −/* the actual size of a user virtual address */ | |
| 180 | −extern u64 vabits_user; | |
| 181 | − | |
| 182 | 197 | /* |
| 183 | 198 | * Allow all memory at the discovery stage. We will clip it later. |
| 184 | 199 | */ |
| @@ -201,24 +216,24 @@ extern u64 vabits_user; · 16 unmodified lines | ||
| 201 | 216 | * pass on to access_ok(), for instance. |
| 202 | 217 | */ |
| 203 | 218 | #define untagged_addr(addr) \ |
| 204 | − ((__typeof__(addr))sign_extend64((u64)(addr), 55)) | |
| 219 | + ((__force __typeof__(addr))sign_extend64((__force u64)(addr), 55)) | |
| 205 | 220 | |
| 206 | 221 | #ifdef CONFIG_KASAN_SW_TAGS |
| 207 | 222 | #define __tag_shifted(tag) ((u64)(tag) << 56) |
| 208 | −#define __tag_set(addr, tag) (__typeof__(addr))( \ | |
| 209 | − ((u64)(addr) & ~__tag_shifted(0xff)) | __tag_shifted(tag)) | |
| 210 | 223 | #define __tag_reset(addr) untagged_addr(addr) |
| 211 | 224 | #define __tag_get(addr) (__u8)((u64)(addr) >> 56) |
| 212 | 225 | #else |
| 226 | +#define __tag_shifted(tag) 0UL | |
| 227 | +#define __tag_reset(addr) (addr) | |
| 228 | +#define __tag_get(addr) 0 | |
| 229 | +#endif /* CONFIG_KASAN_SW_TAGS */ | |
| 230 | + | |
| 213 | 231 | static inline const void *__tag_set(const void *addr, u8 tag) |
| 214 | 232 | { |
| 215 | − return addr; | |
| 233 | + u64 __addr = (u64)addr & ~__tag_shifted(0xff); | |
| 234 | + return (const void *)(__addr | __tag_shifted(tag)); | |
| 216 | 235 | } |
| 217 | 236 | |
| 218 | −#define __tag_reset(addr) (addr) | |
| 219 | −#define __tag_get(addr) 0 | |
| 220 | −#endif | |
| 221 | − | |
| 222 | 237 | /* |
| 223 | 238 | * Physical vs virtual RAM address space conversion. These are |
| 224 | 239 | * private definitions which should NOT be used outside memory.h |
| @@ -227,19 +242,18 @@ static inline const void *__tag_set(const void *addr, u8 tag) · 2 unmodified lines | ||
| 227 | 242 | |
| 228 | 243 | |
| 229 | 244 | /* |
| 230 | − * The linear kernel range starts in the middle of the virtual adddress | |
| 245 | + * The linear kernel range starts at the bottom of the virtual address | |
| 231 | 246 | * space. Testing the top bit for the start of the region is a |
| 232 | − * sufficient check. | |
| 247 | + * sufficient check and avoids having to worry about the tag. | |
| 233 | 248 | */ |
| 234 | −#define __is_lm_address(addr) (!!((addr) & BIT(VA_BITS - 1))) | |
| 249 | +#define __is_lm_address(addr) (!(((u64)addr) & BIT(vabits_actual - 1))) | |
| 235 | 250 | |
| 236 | −#define __lm_to_phys(addr) (((addr) & ~PAGE_OFFSET) + PHYS_OFFSET) | |
| 251 | +#define __lm_to_phys(addr) (((addr) + physvirt_offset)) | |
| 237 | 252 | #define __kimg_to_phys(addr) ((addr) - kimage_voffset) |
| 238 | 253 | |
| 239 | 254 | #define __virt_to_phys_nodebug(x) ({ \ |
| 240 | − phys_addr_t __x = (phys_addr_t)(x); \ | |
| 241 | − __is_lm_address(__x) ? __lm_to_phys(__x) : \ | |
| 242 | − __kimg_to_phys(__x); \ | |
| 255 | + phys_addr_t __x = (phys_addr_t)(__tag_reset(x)); \ | |
| 256 | + __is_lm_address(__x) ? __lm_to_phys(__x) : __kimg_to_phys(__x); \ | |
| 243 | 257 | }) |
| 244 | 258 | |
| 245 | 259 | #define __pa_symbol_nodebug(x) __kimg_to_phys((phys_addr_t)(x)) |
| @@ -250,9 +264,9 @@ extern phys_addr_t __phys_addr_symbol(unsigned long x); · 4 unmodified lines | ||
| 250 | 264 | #else |
| 251 | 265 | #define __virt_to_phys(x) __virt_to_phys_nodebug(x) |
| 252 | 266 | #define __phys_addr_symbol(x) __pa_symbol_nodebug(x) |
| 253 | −#endif | |
| 267 | +#endif /* CONFIG_DEBUG_VIRTUAL */ | |
| 254 | 268 | |
| 255 | −#define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET) | PAGE_OFFSET) | |
| 269 | +#define __phys_to_virt(x) ((unsigned long)((x) - physvirt_offset)) | |
| 256 | 270 | #define __phys_to_kimg(x) ((unsigned long)((x) + kimage_voffset)) |
| 257 | 271 | |
| 258 | 272 | /* |
| @@ -286,41 +300,38 @@ static inline void *phys_to_virt(phys_addr_t x) · 27 unmodified lines | ||
| 286 | 300 | #define __pa_nodebug(x) __virt_to_phys_nodebug((unsigned long)(x)) |
| 287 | 301 | #define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x))) |
| 288 | 302 | #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) |
| 289 | −#define virt_to_pfn(x) __phys_to_pfn(__virt_to_phys((unsigned long)(x))) | |
| 290 | −#define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x)) | |
| 303 | +#define virt_to_pfn(x) __phys_to_pfn(__virt_to_phys((unsigned long)(x))) | |
| 304 | +#define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x)) | |
| 291 | 305 | |
| 292 | 306 | /* |
| 293 | − * virt_to_page(k) convert a _valid_ virtual address to struct page * | |
| 294 | − * virt_addr_valid(k) indicates whether a virtual address is valid | |
| 307 | + * virt_to_page(x) convert a _valid_ virtual address to struct page * | |
| 308 | + * virt_addr_valid(x) indicates whether a virtual address is valid | |
| 295 | 309 | */ |
| 296 | 310 | #define ARCH_PFN_OFFSET ((unsigned long)PHYS_PFN_OFFSET) |
| 297 | 311 | |
| 298 | 312 | #if !defined(CONFIG_SPARSEMEM_VMEMMAP) || defined(CONFIG_DEBUG_VIRTUAL) |
| 299 | −#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) | |
| 300 | −#define _virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) | |
| 313 | +#define virt_to_page(x) pfn_to_page(virt_to_pfn(x)) | |
| 301 | 314 | #else |
| 302 | −#define __virt_to_pgoff(kaddr) (((u64)(kaddr) & ~PAGE_OFFSET) / PAGE_SIZE * sizeof(struct page)) | |
| 303 | −#define __page_to_voff(kaddr) (((u64)(kaddr) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page)) | |
| 304 | − | |
| 305 | −#define page_to_virt(page) ({ \ | |
| 306 | − unsigned long __addr = \ | |
| 307 | − ((__page_to_voff(page)) | PAGE_OFFSET); \ | |
| 308 | − const void *__addr_tag = \ | |
| 309 | − __tag_set((void *)__addr, page_kasan_tag(page)); \ | |
| 310 | − ((void *)__addr_tag); \ | |
| 315 | +#define page_to_virt(x) ({ \ | |
| 316 | + __typeof__(x) __page = x; \ | |
| 317 | + u64 __idx = ((u64)__page - VMEMMAP_START) / sizeof(struct page);\ | |
| 318 | + u64 __addr = PAGE_OFFSET + (__idx * PAGE_SIZE); \ | |
| 319 | + (void *)__tag_set((const void *)__addr, page_kasan_tag(__page));\ | |
| 311 | 320 | }) |
| 312 | 321 | |
| 313 | −#define virt_to_page(vaddr) ((struct page *)((__virt_to_pgoff(vaddr)) | VMEMMAP_START)) | |
| 322 | +#define virt_to_page(x) ({ \ | |
| 323 | + u64 __idx = (__tag_reset((u64)x) - PAGE_OFFSET) / PAGE_SIZE; \ | |
| 324 | + u64 __addr = VMEMMAP_START + (__idx * sizeof(struct page)); \ | |
| 325 | + (struct page *)__addr; \ | |
| 326 | +}) | |
| 327 | +#endif /* !CONFIG_SPARSEMEM_VMEMMAP || CONFIG_DEBUG_VIRTUAL */ | |
| 314 | 328 | |
| 315 | −#define _virt_addr_valid(kaddr) pfn_valid((((u64)(kaddr) & ~PAGE_OFFSET) \ | |
| 316 | − + PHYS_OFFSET) >> PAGE_SHIFT) | |
| 317 | −#endif | |
| 318 | −#endif | |
| 329 | +#define virt_addr_valid(addr) ({ \ | |
| 330 | + __typeof__(addr) __addr = addr; \ | |
| 331 | + __is_lm_address(__addr) && pfn_valid(virt_to_pfn(__addr)); \ | |
| 332 | +}) | |
| 319 | 333 | |
| 320 | −#define _virt_addr_is_linear(kaddr) \ | |
| 321 | − (__tag_reset((u64)(kaddr)) >= PAGE_OFFSET) | |
| 322 | −#define virt_addr_valid(kaddr) \ | |
| 323 | − (_virt_addr_is_linear(kaddr) && _virt_addr_valid(kaddr)) | |
| 334 | +#endif /* !ASSEMBLY */ | |
| 324 | 335 | |
| 325 | 336 | /* |
| 326 | 337 | * Given that the GIC architecture permits ITS implementations that can only be |
| @@ -335,4 +346,4 @@ static inline void *phys_to_virt(phys_addr_t x) · 8 unmodified lines | ||
| 335 | 346 | |
| 336 | 347 | #include <asm-generic/memory_model.h> |
| 337 | 348 | |
| 338 | −#endif | |
| 349 | +#endif /* __ASM_MEMORY_H */ | |
| @@ -126,7 +126,7 @@ extern void init_mem_pgprot(void); · 125 unmodified lines | ||
| 126 | 126 | extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, |
| 127 | 127 | unsigned long virt, phys_addr_t size, |
| 128 | 128 | pgprot_t prot, bool page_mappings_only); |
| 129 | −extern void *fixmap_remap_fdt(phys_addr_t dt_phys); | |
| 129 | +extern void *fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot); | |
| 130 | 130 | extern void mark_linear_text_alias_ro(void); |
| 131 | 131 | |
| 132 | 132 | #define INIT_MM_CONTEXT(name) \ |
| @@ -63,7 +63,7 @@ extern u64 idmap_ptrs_per_pgd; · 62 unmodified lines | ||
| 63 | 63 | |
| 64 | 64 | static inline bool __cpu_uses_extended_idmap(void) |
| 65 | 65 | { |
| 66 | − if (IS_ENABLED(CONFIG_ARM64_USER_VA_BITS_52)) | |
| 66 | + if (IS_ENABLED(CONFIG_ARM64_VA_BITS_52)) | |
| 67 | 67 | return false; |
| 68 | 68 | |
| 69 | 69 | return unlikely(idmap_t0sz != TCR_T0SZ(VA_BITS)); |
| @@ -95,7 +95,7 @@ static inline void __cpu_set_tcr_t0sz(unsigned long t0sz) · 25 unmodified lines | ||
| 95 | 95 | isb(); |
| 96 | 96 | } |
| 97 | 97 | |
| 98 | −#define cpu_set_default_tcr_t0sz() __cpu_set_tcr_t0sz(TCR_T0SZ(VA_BITS)) | |
| 98 | +#define cpu_set_default_tcr_t0sz() __cpu_set_tcr_t0sz(TCR_T0SZ(vabits_actual)) | |
| 99 | 99 | #define cpu_set_idmap_tcr_t0sz() __cpu_set_tcr_t0sz(idmap_t0sz) |
| 100 | 100 | |
| 101 | 101 | /* |
| @@ -304,7 +304,7 @@ · 303 unmodified lines | ||
| 304 | 304 | #define TTBR_BADDR_MASK_52 (((UL(1) << 46) - 1) << 2) |
| 305 | 305 | #endif |
| 306 | 306 | |
| 307 | −#ifdef CONFIG_ARM64_USER_VA_BITS_52 | |
| 307 | +#ifdef CONFIG_ARM64_VA_BITS_52 | |
| 308 | 308 | /* Must be at least 64-byte aligned to prevent corruption of the TTBR */ |
| 309 | 309 | #define TTBR1_BADDR_4852_OFFSET (((UL(1) << (52 - PGDIR_SHIFT)) - \ |
| 310 | 310 | (UL(1) << (48 - PGDIR_SHIFT))) * 8) |
| @@ -21,9 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | * and fixed mappings |
| 22 | 22 | */ |
| 23 | 23 | #define VMALLOC_START (MODULES_END) |
| 24 | −#define VMALLOC_END (PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K) | |
| 25 | − | |
| 26 | −#define vmemmap ((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT)) | |
| 24 | +#define VMALLOC_END (- PUD_SIZE - VMEMMAP_SIZE - SZ_64K) | |
| 27 | 25 | |
| 28 | 26 | #define FIRST_USER_ADDRESS 0UL |
| 29 | 27 | |
| @@ -35,6 +33,8 @@ · 5 unmodified lines | ||
| 35 | 33 | #include <linux/mm_types.h> |
| 36 | 34 | #include <linux/sched.h> |
| 37 | 35 | |
| 36 | +extern struct page *vmemmap; | |
| 37 | + | |
| 38 | 38 | extern void __pte_error(const char *file, int line, unsigned long val); |
| 39 | 39 | extern void __pmd_error(const char *file, int line, unsigned long val); |
| 40 | 40 | extern void __pud_error(const char *file, int line, unsigned long val); |
| @@ -220,8 +220,10 @@ static inline void set_pte(pte_t *ptep, pte_t pte) · 179 unmodified lines | ||
| 220 | 220 | * Only if the new pte is valid and kernel, otherwise TLB maintenance |
| 221 | 221 | * or update_mmu_cache() have the necessary barriers. |
| 222 | 222 | */ |
| 223 | − if (pte_valid_not_user(pte)) | |
| 223 | + if (pte_valid_not_user(pte)) { | |
| 224 | 224 | dsb(ishst); |
| 225 | + isb(); | |
| 226 | + } | |
| 225 | 227 | } |
| 226 | 228 | |
| 227 | 229 | extern void __sync_icache_dcache(pte_t pteval); |
| @@ -481,8 +483,10 @@ static inline void set_pmd(pmd_t *pmdp, pmd_t pmd) · 253 unmodified lines | ||
| 481 | 483 | |
| 482 | 484 | WRITE_ONCE(*pmdp, pmd); |
| 483 | 485 | |
| 484 | − if (pmd_valid(pmd)) | |
| 486 | + if (pmd_valid(pmd)) { | |
| 485 | 487 | dsb(ishst); |
| 488 | + isb(); | |
| 489 | + } | |
| 486 | 490 | } |
| 487 | 491 | |
| 488 | 492 | static inline void pmd_clear(pmd_t *pmdp) |
| @@ -540,8 +544,10 @@ static inline void set_pud(pud_t *pudp, pud_t pud) · 51 unmodified lines | ||
| 540 | 544 | |
| 541 | 545 | WRITE_ONCE(*pudp, pud); |
| 542 | 546 | |
| 543 | − if (pud_valid(pud)) | |
| 547 | + if (pud_valid(pud)) { | |
| 544 | 548 | dsb(ishst); |
| 549 | + isb(); | |
| 550 | + } | |
| 545 | 551 | } |
| 546 | 552 | |
| 547 | 553 | static inline void pud_clear(pud_t *pudp) |
| @@ -599,6 +605,7 @@ static inline void set_pgd(pgd_t *pgdp, pgd_t pgd) · 51 unmodified lines | ||
| 599 | 605 | |
| 600 | 606 | WRITE_ONCE(*pgdp, pgd); |
| 601 | 607 | dsb(ishst); |
| 608 | + isb(); | |
| 602 | 609 | } |
| 603 | 610 | |
| 604 | 611 | static inline void pgd_clear(pgd_t *pgdp) |
| @@ -856,8 +863,8 @@ static inline void update_mmu_cache(struct vm_area_struct *vma, · 251 unmodified lines | ||
| 856 | 863 | |
| 857 | 864 | #define update_mmu_cache_pmd(vma, address, pmd) do { } while (0) |
| 858 | 865 | |
| 859 | −#define kc_vaddr_to_offset(v) ((v) & ~VA_START) | |
| 860 | −#define kc_offset_to_vaddr(o) ((o) | VA_START) | |
| 866 | +#define kc_vaddr_to_offset(v) ((v) & ~PAGE_END) | |
| 867 | +#define kc_offset_to_vaddr(o) ((o) | PAGE_END) | |
| 861 | 868 | |
| 862 | 869 | #ifdef CONFIG_ARM64_PA_BITS_52 |
| 863 | 870 | #define phys_to_ttbr(addr) (((addr) | ((addr) >> 46)) & TTBR_BADDR_MASK_52) |
| @@ -69,7 +69,7 @@ extern int ptrauth_prctl_reset_keys(struct task_struct *tsk, unsigned long arg); · 68 unmodified lines | ||
| 69 | 69 | * The EL0 pointer bits used by a pointer authentication code. |
| 70 | 70 | * This is dependent on TBI0 being enabled, or bits 63:56 would also apply. |
| 71 | 71 | */ |
| 72 | −#define ptrauth_user_pac_mask() GENMASK(54, vabits_user) | |
| 72 | +#define ptrauth_user_pac_mask() GENMASK(54, vabits_actual) | |
| 73 | 73 | |
| 74 | 74 | /* Only valid for EL0 TTBR0 instruction pointers */ |
| 75 | 75 | static inline unsigned long ptrauth_strip_insn_pac(unsigned long ptr) |
| @@ -41,8 +41,8 @@ · 40 unmodified lines | ||
| 41 | 41 | * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area. |
| 42 | 42 | */ |
| 43 | 43 | |
| 44 | −#define DEFAULT_MAP_WINDOW_64 (UL(1) << VA_BITS) | |
| 45 | −#define TASK_SIZE_64 (UL(1) << vabits_user) | |
| 44 | +#define DEFAULT_MAP_WINDOW_64 (UL(1) << VA_BITS_MIN) | |
| 45 | +#define TASK_SIZE_64 (UL(1) << vabits_actual) | |
| 46 | 46 | |
| 47 | 47 | #ifdef CONFIG_COMPAT |
| 48 | 48 | #if defined(CONFIG_ARM64_64K_PAGES) && defined(CONFIG_KUSER_HELPERS) |
| @@ -303,6 +303,14 @@ extern void __init minsigstksz_setup(void); · 254 unmodified lines | ||
| 303 | 303 | /* PR_PAC_RESET_KEYS prctl */ |
| 304 | 304 | #define PAC_RESET_KEYS(tsk, arg) ptrauth_prctl_reset_keys(tsk, arg) |
| 305 | 305 | |
| 306 | +#ifdef CONFIG_ARM64_TAGGED_ADDR_ABI | |
| 307 | +/* PR_{SET,GET}_TAGGED_ADDR_CTRL prctl */ | |
| 308 | +long set_tagged_addr_ctrl(unsigned long arg); | |
| 309 | +long get_tagged_addr_ctrl(void); | |
| 310 | +#define SET_TAGGED_ADDR_CTRL(arg) set_tagged_addr_ctrl(arg) | |
| 311 | +#define GET_TAGGED_ADDR_CTRL() get_tagged_addr_ctrl() | |
| 312 | +#endif | |
| 313 | + | |
| 306 | 314 | /* |
| 307 | 315 | * For CONFIG_GCC_PLUGIN_STACKLEAK |
| 308 | 316 | * |
| @@ -301,6 +301,11 @@ static inline unsigned long regs_return_value(struct pt_regs *regs) · 300 unmodified lines | ||
| 301 | 301 | return regs->regs[0]; |
| 302 | 302 | } |
| 303 | 303 | |
| 304 | +static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc) | |
| 305 | +{ | |
| 306 | + regs->regs[0] = rc; | |
| 307 | +} | |
| 308 | + | |
| 304 | 309 | /** |
| 305 | 310 | * regs_get_kernel_argument() - get Nth function argument in kernel |
| 306 | 311 | * @regs: pt_regs of that context |
| @@ -212,6 +212,9 @@ · 211 unmodified lines | ||
| 212 | 212 | #define SYS_FAR_EL1 sys_reg(3, 0, 6, 0, 0) |
| 213 | 213 | #define SYS_PAR_EL1 sys_reg(3, 0, 7, 4, 0) |
| 214 | 214 | |
| 215 | +#define SYS_PAR_EL1_F BIT(1) | |
| 216 | +#define SYS_PAR_EL1_FST GENMASK(6, 1) | |
| 217 | + | |
| 215 | 218 | /*** Statistical Profiling Extension ***/ |
| 216 | 219 | /* ID registers */ |
| 217 | 220 | #define SYS_PMSIDR_EL1 sys_reg(3, 0, 9, 9, 7) |
| @@ -77,6 +77,7 @@ void arch_release_task_struct(struct task_struct *tsk); · 76 unmodified lines | ||
| 77 | 77 | #define TIF_SVE 23 /* Scalable Vector Extension in use */ |
| 78 | 78 | #define TIF_SVE_VL_INHERIT 24 /* Inherit sve_vl_onexec across exec */ |
| 79 | 79 | #define TIF_SSBD 25 /* Wants SSB mitigation */ |
| 80 | +#define TIF_TAGGED_ADDR 26 /* Allow tagged user addresses */ | |
| 80 | 81 | |
| 81 | 82 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) |
| 82 | 83 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) |
| @@ -251,6 +251,7 @@ static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr) · 250 unmodified lines | ||
| 251 | 251 | dsb(ishst); |
| 252 | 252 | __tlbi(vaae1is, addr); |
| 253 | 253 | dsb(ish); |
| 254 | + isb(); | |
| 254 | 255 | } |
| 255 | 256 | #endif |
| 256 | 257 | |
| @@ -4,29 +4,6 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | #include <linux/cpumask.h> |
| 6 | 6 | |
| 7 | −struct cpu_topology { | |
| 8 | − int thread_id; | |
| 9 | − int core_id; | |
| 10 | − int package_id; | |
| 11 | − int llc_id; | |
| 12 | − cpumask_t thread_sibling; | |
| 13 | − cpumask_t core_sibling; | |
| 14 | − cpumask_t llc_sibling; | |
| 15 | −}; | |
| 16 | − | |
| 17 | −extern struct cpu_topology cpu_topology[NR_CPUS]; | |
| 18 | − | |
| 19 | −#define topology_physical_package_id(cpu) (cpu_topology[cpu].package_id) | |
| 20 | −#define topology_core_id(cpu) (cpu_topology[cpu].core_id) | |
| 21 | −#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) | |
| 22 | −#define topology_sibling_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) | |
| 23 | −#define topology_llc_cpumask(cpu) (&cpu_topology[cpu].llc_sibling) | |
| 24 | − | |
| 25 | −void init_cpu_topology(void); | |
| 26 | −void store_cpu_topology(unsigned int cpuid); | |
| 27 | −void remove_cpu_topology(unsigned int cpuid); | |
| 28 | −const struct cpumask *cpu_coregroup_mask(int cpu); | |
| 29 | − | |
| 30 | 7 | #ifdef CONFIG_NUMA |
| 31 | 8 | |
| 32 | 9 | struct pci_bus; |
| @@ -62,6 +62,10 @@ static inline unsigned long __range_ok(const void __user *addr, unsigned long si · 61 unmodified lines | ||
| 62 | 62 | { |
| 63 | 63 | unsigned long ret, limit = current_thread_info()->addr_limit; |
| 64 | 64 | |
| 65 | + if (IS_ENABLED(CONFIG_ARM64_TAGGED_ADDR_ABI) && | |
| 66 | + test_thread_flag(TIF_TAGGED_ADDR)) | |
| 67 | + addr = untagged_addr(addr); | |
| 68 | + | |
| 65 | 69 | __chk_user_ptr(addr); |
| 66 | 70 | asm volatile( |
| 67 | 71 | // A + B <= C + 1 for all A,B,C, in four easy steps: |
| @@ -215,7 +219,8 @@ static inline void uaccess_enable_not_uao(void) · 147 unmodified lines | ||
| 215 | 219 | |
| 216 | 220 | /* |
| 217 | 221 | * Sanitise a uaccess pointer such that it becomes NULL if above the |
| 218 | − * current addr_limit. | |
| 222 | + * current addr_limit. In case the pointer is tagged (has the top byte set), | |
| 223 | + * untag the pointer before checking. | |
| 219 | 224 | */ |
| 220 | 225 | #define uaccess_mask_ptr(ptr) (__typeof__(ptr))__uaccess_mask_ptr(ptr) |
| 221 | 226 | static inline void __user *__uaccess_mask_ptr(const void __user *ptr) |
| @@ -223,10 +228,11 @@ static inline void __user *__uaccess_mask_ptr(const void __user *ptr) · 1 unmodified line | ||
| 223 | 228 | void __user *safe_ptr; |
| 224 | 229 | |
| 225 | 230 | asm volatile( |
| 226 | − " bics xzr, %1, %2\n" | |
| 231 | + " bics xzr, %3, %2\n" | |
| 227 | 232 | " csel %0, %1, xzr, eq\n" |
| 228 | 233 | : "=&r" (safe_ptr) |
| 229 | − : "r" (ptr), "r" (current_thread_info()->addr_limit) | |
| 234 | + : "r" (ptr), "r" (current_thread_info()->addr_limit), | |
| 235 | + "r" (untagged_addr(ptr)) | |
| 230 | 236 | : "cc"); |
| 231 | 237 | |
| 232 | 238 | csdb(); |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/cpu_pm.h> |
| 12 | 12 | #include <linux/of.h> |
| 13 | 13 | #include <linux/of_device.h> |
| 14 | +#include <linux/psci.h> | |
| 14 | 15 | |
| 15 | 16 | #include <asm/cpuidle.h> |
| 16 | 17 | #include <asm/cpu_ops.h> |
| @@ -46,17 +47,58 @@ int arm_cpuidle_suspend(int index) · 29 unmodified lines | ||
| 46 | 47 | |
| 47 | 48 | #define ARM64_LPI_IS_RETENTION_STATE(arch_flags) (!(arch_flags)) |
| 48 | 49 | |
| 50 | +static int psci_acpi_cpu_init_idle(unsigned int cpu) | |
| 51 | +{ | |
| 52 | + int i, count; | |
| 53 | + struct acpi_lpi_state *lpi; | |
| 54 | + struct acpi_processor *pr = per_cpu(processors, cpu); | |
| 55 | + | |
| 56 | + /* | |
| 57 | + * If the PSCI cpu_suspend function hook has not been initialized | |
| 58 | + * idle states must not be enabled, so bail out | |
| 59 | + */ | |
| 60 | + if (!psci_ops.cpu_suspend) | |
| 61 | + return -EOPNOTSUPP; | |
| 62 | + | |
| 63 | + if (unlikely(!pr || !pr->flags.has_lpi)) | |
| 64 | + return -EINVAL; | |
| 65 | + | |
| 66 | + count = pr->power.count - 1; | |
| 67 | + if (count <= 0) | |
| 68 | + return -ENODEV; | |
| 69 | + | |
| 70 | + for (i = 0; i < count; i++) { | |
| 71 | + u32 state; | |
| 72 | + | |
| 73 | + lpi = &pr->power.lpi_states[i + 1]; | |
| 74 | + /* | |
| 75 | + * Only bits[31:0] represent a PSCI power_state while | |
| 76 | + * bits[63:32] must be 0x0 as per ARM ACPI FFH Specification | |
| 77 | + */ | |
| 78 | + state = lpi->address; | |
| 79 | + if (!psci_power_state_is_valid(state)) { | |
| 80 | + pr_warn("Invalid PSCI power state %#x\n", state); | |
| 81 | + return -EINVAL; | |
| 82 | + } | |
| 83 | + } | |
| 84 | + | |
| 85 | + return 0; | |
| 86 | +} | |
| 87 | + | |
| 49 | 88 | int acpi_processor_ffh_lpi_probe(unsigned int cpu) |
| 50 | 89 | { |
| 51 | − return arm_cpuidle_init(cpu); | |
| 90 | + return psci_acpi_cpu_init_idle(cpu); | |
| 52 | 91 | } |
| 53 | 92 | |
| 54 | 93 | int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi) |
| 55 | 94 | { |
| 95 | + u32 state = lpi->address; | |
| 96 | + | |
| 56 | 97 | if (ARM64_LPI_IS_RETENTION_STATE(lpi->arch_flags)) |
| 57 | − return CPU_PM_CPU_IDLE_ENTER_RETENTION(arm_cpuidle_suspend, | |
| 58 | − lpi->index); | |
| 98 | + return CPU_PM_CPU_IDLE_ENTER_RETENTION_PARAM(psci_cpu_suspend_enter, | |
| 99 | + lpi->index, state); | |
| 59 | 100 | else |
| 60 | − return CPU_PM_CPU_IDLE_ENTER(arm_cpuidle_suspend, lpi->index); | |
| 101 | + return CPU_PM_CPU_IDLE_ENTER_PARAM(psci_cpu_suspend_enter, | |
| 102 | + lpi->index, state); | |
| 61 | 103 | } |
| 62 | 104 | #endif |
| @@ -310,15 +310,15 @@ __create_page_tables: · 309 unmodified lines | ||
| 310 | 310 | adrp x0, idmap_pg_dir |
| 311 | 311 | adrp x3, __idmap_text_start // __pa(__idmap_text_start) |
| 312 | 312 | |
| 313 | −#ifdef CONFIG_ARM64_USER_VA_BITS_52 | |
| 313 | +#ifdef CONFIG_ARM64_VA_BITS_52 | |
| 314 | 314 | mrs_s x6, SYS_ID_AA64MMFR2_EL1 |
| 315 | 315 | and x6, x6, #(0xf << ID_AA64MMFR2_LVA_SHIFT) |
| 316 | 316 | mov x5, #52 |
| 317 | 317 | cbnz x6, 1f |
| 318 | 318 | #endif |
| 319 | − mov x5, #VA_BITS | |
| 319 | + mov x5, #VA_BITS_MIN | |
| 320 | 320 | 1: |
| 321 | − adr_l x6, vabits_user | |
| 321 | + adr_l x6, vabits_actual | |
| 322 | 322 | str x5, [x6] |
| 323 | 323 | dmb sy |
| 324 | 324 | dc ivac, x6 // Invalidate potentially stale cache line |
| @@ -726,14 +726,22 @@ __secondary_switched: · 401 unmodified lines | ||
| 726 | 726 | |
| 727 | 727 | adr_l x0, secondary_data |
| 728 | 728 | ldr x1, [x0, #CPU_BOOT_STACK] // get secondary_data.stack |
| 729 | + cbz x1, __secondary_too_slow | |
| 729 | 730 | mov sp, x1 |
| 730 | 731 | ldr x2, [x0, #CPU_BOOT_TASK] |
| 732 | + cbz x2, __secondary_too_slow | |
| 731 | 733 | msr sp_el0, x2 |
| 732 | 734 | mov x29, #0 |
| 733 | 735 | mov x30, #0 |
| 734 | 736 | b secondary_start_kernel |
| 735 | 737 | ENDPROC(__secondary_switched) |
| 736 | 738 | |
| 739 | +__secondary_too_slow: | |
| 740 | + wfe | |
| 741 | + wfi | |
| 742 | + b __secondary_too_slow | |
| 743 | +ENDPROC(__secondary_too_slow) | |
| 744 | + | |
| 737 | 745 | /* |
| 738 | 746 | * The booting CPU updates the failed status @__early_cpu_boot_status, |
| 739 | 747 | * with MMU turned off. |
| @@ -774,7 +782,7 @@ ENTRY(__enable_mmu) · 34 unmodified lines | ||
| 774 | 782 | phys_to_ttbr x1, x1 |
| 775 | 783 | phys_to_ttbr x2, x2 |
| 776 | 784 | msr ttbr0_el1, x2 // load TTBR0 |
| 777 | − offset_ttbr1 x1 | |
| 785 | + offset_ttbr1 x1, x3 | |
| 778 | 786 | msr ttbr1_el1, x1 // load TTBR1 |
| 779 | 787 | isb |
| 780 | 788 | msr sctlr_el1, x0 |
| @@ -791,8 +799,8 @@ ENTRY(__enable_mmu) · 10 unmodified lines | ||
| 791 | 799 | ENDPROC(__enable_mmu) |
| 792 | 800 | |
| 793 | 801 | ENTRY(__cpu_secondary_check52bitva) |
| 794 | −#ifdef CONFIG_ARM64_USER_VA_BITS_52 | |
| 795 | − ldr_l x0, vabits_user | |
| 802 | +#ifdef CONFIG_ARM64_VA_BITS_52 | |
| 803 | + ldr_l x0, vabits_actual | |
| 796 | 804 | cmp x0, #52 |
| 797 | 805 | b.ne 2f |
| 798 | 806 | |
| @@ -22,14 +22,14 @@ · 21 unmodified lines | ||
| 22 | 22 | * Even switching to our copied tables will cause a changed output address at |
| 23 | 23 | * each stage of the walk. |
| 24 | 24 | */ |
| 25 | −.macro break_before_make_ttbr_switch zero_page, page_table, tmp | |
| 25 | +.macro break_before_make_ttbr_switch zero_page, page_table, tmp, tmp2 | |
| 26 | 26 | phys_to_ttbr \tmp, \zero_page |
| 27 | 27 | msr ttbr1_el1, \tmp |
| 28 | 28 | isb |
| 29 | 29 | tlbi vmalle1 |
| 30 | 30 | dsb nsh |
| 31 | 31 | phys_to_ttbr \tmp, \page_table |
| 32 | − offset_ttbr1 \tmp | |
| 32 | + offset_ttbr1 \tmp, \tmp2 | |
| 33 | 33 | msr ttbr1_el1, \tmp |
| 34 | 34 | isb |
| 35 | 35 | .endm |
| @@ -70,7 +70,7 @@ ENTRY(swsusp_arch_suspend_exit) · 34 unmodified lines | ||
| 70 | 70 | * We execute from ttbr0, change ttbr1 to our copied linear map tables |
| 71 | 71 | * with a break-before-make via the zero page |
| 72 | 72 | */ |
| 73 | − break_before_make_ttbr_switch x5, x0, x6 | |
| 73 | + break_before_make_ttbr_switch x5, x0, x6, x8 | |
| 74 | 74 | |
| 75 | 75 | mov x21, x1 |
| 76 | 76 | mov x30, x2 |
| @@ -101,7 +101,7 @@ ENTRY(swsusp_arch_suspend_exit) · 24 unmodified lines | ||
| 101 | 101 | dsb ish /* wait for PoU cleaning to finish */ |
| 102 | 102 | |
| 103 | 103 | /* switch to the restored kernels page tables */ |
| 104 | − break_before_make_ttbr_switch x25, x21, x6 | |
| 104 | + break_before_make_ttbr_switch x25, x21, x6, x8 | |
| 105 | 105 | |
| 106 | 106 | ic ialluis |
| 107 | 107 | dsb ish |
| @@ -496,7 +496,7 @@ int swsusp_arch_resume(void) · 495 unmodified lines | ||
| 496 | 496 | rc = -ENOMEM; |
| 497 | 497 | goto out; |
| 498 | 498 | } |
| 499 | − rc = copy_page_tables(tmp_pg_dir, PAGE_OFFSET, 0); | |
| 499 | + rc = copy_page_tables(tmp_pg_dir, PAGE_OFFSET, PAGE_END); | |
| 500 | 500 | if (rc) |
| 501 | 501 | goto out; |
| 502 | 502 | |
| @@ -62,9 +62,6 @@ out: · 61 unmodified lines | ||
| 62 | 62 | return default_cmdline; |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | −extern void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, | |
| 66 | − pgprot_t prot); | |
| 67 | − | |
| 68 | 65 | /* |
| 69 | 66 | * This routine will be executed with the kernel mapped at its default virtual |
| 70 | 67 | * address, and if it returns successfully, the kernel will be remapped, and |
| @@ -93,7 +90,7 @@ u64 __init kaslr_early_init(u64 dt_phys) · 22 unmodified lines | ||
| 93 | 90 | * attempt at mapping the FDT in setup_machine() |
| 94 | 91 | */ |
| 95 | 92 | early_fixmap_init(); |
| 96 | − fdt = __fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL); | |
| 93 | + fdt = fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL); | |
| 97 | 94 | if (!fdt) |
| 98 | 95 | return 0; |
| 99 | 96 | |
| @@ -116,15 +113,15 @@ u64 __init kaslr_early_init(u64 dt_phys) · 16 unmodified lines | ||
| 116 | 113 | /* |
| 117 | 114 | * OK, so we are proceeding with KASLR enabled. Calculate a suitable |
| 118 | 115 | * kernel image offset from the seed. Let's place the kernel in the |
| 119 | − * middle half of the VMALLOC area (VA_BITS - 2), and stay clear of | |
| 116 | + * middle half of the VMALLOC area (VA_BITS_MIN - 2), and stay clear of | |
| 120 | 117 | * the lower and upper quarters to avoid colliding with other |
| 121 | 118 | * allocations. |
| 122 | 119 | * Even if we could randomize at page granularity for 16k and 64k pages, |
| 123 | 120 | * let's always round to 2 MB so we don't interfere with the ability to |
| 124 | 121 | * map using contiguous PTEs |
| 125 | 122 | */ |
| 126 | − mask = ((1UL << (VA_BITS - 2)) - 1) & ~(SZ_2M - 1); | |
| 127 | − offset = BIT(VA_BITS - 3) + (seed & mask); | |
| 123 | + mask = ((1UL << (VA_BITS_MIN - 2)) - 1) & ~(SZ_2M - 1); | |
| 124 | + offset = BIT(VA_BITS_MIN - 3) + (seed & mask); | |
| 128 | 125 | |
| 129 | 126 | /* use the top 16 bits to randomize the linear region */ |
| 130 | 127 | memstart_offset_seed = seed >> 48; |
| @@ -27,6 +27,8 @@ · 26 unmodified lines | ||
| 27 | 27 | #define FDT_PROP_INITRD_END "linux,initrd-end" |
| 28 | 28 | #define FDT_PROP_BOOTARGS "bootargs" |
| 29 | 29 | #define FDT_PROP_KASLR_SEED "kaslr-seed" |
| 30 | +#define FDT_PROP_RNG_SEED "rng-seed" | |
| 31 | +#define RNG_SEED_SIZE 128 | |
| 30 | 32 | |
| 31 | 33 | const struct kexec_file_ops * const kexec_file_loaders[] = { |
| 32 | 34 | &kexec_image_ops, |
| @@ -102,6 +104,19 @@ static int setup_dtb(struct kimage *image, · 69 unmodified lines | ||
| 102 | 104 | FDT_PROP_KASLR_SEED); |
| 103 | 105 | } |
| 104 | 106 | |
| 107 | + /* add rng-seed */ | |
| 108 | + if (rng_is_initialized()) { | |
| 109 | + u8 rng_seed[RNG_SEED_SIZE]; | |
| 110 | + get_random_bytes(rng_seed, RNG_SEED_SIZE); | |
| 111 | + ret = fdt_setprop(dtb, off, FDT_PROP_RNG_SEED, rng_seed, | |
| 112 | + RNG_SEED_SIZE); | |
| 113 | + if (ret) | |
| 114 | + goto out; | |
| 115 | + } else { | |
| 116 | + pr_notice("RNG is not initialised: omitting \"%s\" property\n", | |
| 117 | + FDT_PROP_RNG_SEED); | |
| 118 | + } | |
| 119 | + | |
| 105 | 120 | out: |
| 106 | 121 | if (ret) |
| 107 | 122 | return (ret == -FDT_ERR_NOSPACE) ? -ENOMEM : -EINVAL; |
| @@ -110,7 +125,8 @@ out: · 2 unmodified lines | ||
| 110 | 125 | } |
| 111 | 126 | |
| 112 | 127 | /* |
| 113 | − * More space needed so that we can add initrd, bootargs and kaslr-seed. | |
| 128 | + * More space needed so that we can add initrd, bootargs, kaslr-seed, and | |
| 129 | + * rng-seed. | |
| 114 | 130 | */ |
| 115 | 131 | #define DTB_EXTRA_SPACE 0x1000 |
| 116 | 132 | |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/of.h> |
| 20 | 20 | #include <linux/perf/arm_pmu.h> |
| 21 | 21 | #include <linux/platform_device.h> |
| 22 | +#include <linux/smp.h> | |
| 22 | 23 | |
| 23 | 24 | /* ARMv8 Cortex-A53 specific event types. */ |
| 24 | 25 | #define ARMV8_A53_PERFCTR_PREF_LINEFILL 0xC2 |
| @@ -157,7 +158,6 @@ armv8pmu_events_sysfs_show(struct device *dev, · 132 unmodified lines | ||
| 157 | 158 | return sprintf(page, "event=0x%03llx\n", pmu_attr->id); |
| 158 | 159 | } |
| 159 | 160 | |
| 160 | −#define ARMV8_EVENT_ATTR_RESOLVE(m) #m | |
| 161 | 161 | #define ARMV8_EVENT_ATTR(name, config) \ |
| 162 | 162 | PMU_EVENT_ATTR(name, armv8_event_attr_##name, \ |
| 163 | 163 | config, armv8pmu_events_sysfs_show) |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <linux/kernel.h> |
| 20 | 20 | #include <linux/mm.h> |
| 21 | 21 | #include <linux/stddef.h> |
| 22 | +#include <linux/sysctl.h> | |
| 22 | 23 | #include <linux/unistd.h> |
| 23 | 24 | #include <linux/user.h> |
| 24 | 25 | #include <linux/delay.h> |
| @@ -38,6 +39,7 @@ · 13 unmodified lines | ||
| 38 | 39 | #include <trace/events/power.h> |
| 39 | 40 | #include <linux/percpu.h> |
| 40 | 41 | #include <linux/thread_info.h> |
| 42 | +#include <linux/prctl.h> | |
| 41 | 43 | |
| 42 | 44 | #include <asm/alternative.h> |
| 43 | 45 | #include <asm/arch_gicv3.h> |
| @@ -307,11 +309,18 @@ static void tls_thread_flush(void) · 263 unmodified lines | ||
| 307 | 309 | } |
| 308 | 310 | } |
| 309 | 311 | |
| 312 | +static void flush_tagged_addr_state(void) | |
| 313 | +{ | |
| 314 | + if (IS_ENABLED(CONFIG_ARM64_TAGGED_ADDR_ABI)) | |
| 315 | + clear_thread_flag(TIF_TAGGED_ADDR); | |
| 316 | +} | |
| 317 | + | |
| 310 | 318 | void flush_thread(void) |
| 311 | 319 | { |
| 312 | 320 | fpsimd_flush_thread(); |
| 313 | 321 | tls_thread_flush(); |
| 314 | 322 | flush_ptrace_hw_breakpoint(current); |
| 323 | + flush_tagged_addr_state(); | |
| 315 | 324 | } |
| 316 | 325 | |
| 317 | 326 | void release_thread(struct task_struct *dead_task) |
| @@ -565,3 +574,70 @@ void arch_setup_new_exec(void) · 247 unmodified lines | ||
| 565 | 574 | |
| 566 | 575 | ptrauth_thread_init_user(current); |
| 567 | 576 | } |
| 577 | + | |
| 578 | +#ifdef CONFIG_ARM64_TAGGED_ADDR_ABI | |
| 579 | +/* | |
| 580 | + * Control the relaxed ABI allowing tagged user addresses into the kernel. | |
| 581 | + */ | |
| 582 | +static unsigned int tagged_addr_disabled; | |
| 583 | + | |
| 584 | +long set_tagged_addr_ctrl(unsigned long arg) | |
| 585 | +{ | |
| 586 | + if (is_compat_task()) | |
| 587 | + return -EINVAL; | |
| 588 | + if (arg & ~PR_TAGGED_ADDR_ENABLE) | |
| 589 | + return -EINVAL; | |
| 590 | + | |
| 591 | + /* | |
| 592 | + * Do not allow the enabling of the tagged address ABI if globally | |
| 593 | + * disabled via sysctl abi.tagged_addr_disabled. | |
| 594 | + */ | |
| 595 | + if (arg & PR_TAGGED_ADDR_ENABLE && tagged_addr_disabled) | |
| 596 | + return -EINVAL; | |
| 597 | + | |
| 598 | + update_thread_flag(TIF_TAGGED_ADDR, arg & PR_TAGGED_ADDR_ENABLE); | |
| 599 | + | |
| 600 | + return 0; | |
| 601 | +} | |
| 602 | + | |
| 603 | +long get_tagged_addr_ctrl(void) | |
| 604 | +{ | |
| 605 | + if (is_compat_task()) | |
| 606 | + return -EINVAL; | |
| 607 | + | |
| 608 | + if (test_thread_flag(TIF_TAGGED_ADDR)) | |
| 609 | + return PR_TAGGED_ADDR_ENABLE; | |
| 610 | + | |
| 611 | + return 0; | |
| 612 | +} | |
| 613 | + | |
| 614 | +/* | |
| 615 | + * Global sysctl to disable the tagged user addresses support. This control | |
| 616 | + * only prevents the tagged address ABI enabling via prctl() and does not | |
| 617 | + * disable it for tasks that already opted in to the relaxed ABI. | |
| 618 | + */ | |
| 619 | +static int zero; | |
| 620 | +static int one = 1; | |
| 621 | + | |
| 622 | +static struct ctl_table tagged_addr_sysctl_table[] = { | |
| 623 | + { | |
| 624 | + .procname = "tagged_addr_disabled", | |
| 625 | + .mode = 0644, | |
| 626 | + .data = &tagged_addr_disabled, | |
| 627 | + .maxlen = sizeof(int), | |
| 628 | + .proc_handler = proc_dointvec_minmax, | |
| 629 | + .extra1 = &zero, | |
| 630 | + .extra2 = &one, | |
| 631 | + }, | |
| 632 | + { } | |
| 633 | +}; | |
| 634 | + | |
| 635 | +static int __init tagged_addr_init(void) | |
| 636 | +{ | |
| 637 | + if (!register_sysctl("abi", tagged_addr_sysctl_table)) | |
| 638 | + return -EINVAL; | |
| 639 | + return 0; | |
| 640 | +} | |
| 641 | + | |
| 642 | +core_initcall(tagged_addr_init); | |
| 643 | +#endif /* CONFIG_ARM64_TAGGED_ADDR_ABI */ | |
| @@ -46,6 +46,11 @@ static int cpu_psci_cpu_boot(unsigned int cpu) · 45 unmodified lines | ||
| 46 | 46 | } |
| 47 | 47 | |
| 48 | 48 | #ifdef CONFIG_HOTPLUG_CPU |
| 49 | +static bool cpu_psci_cpu_can_disable(unsigned int cpu) | |
| 50 | +{ | |
| 51 | + return !psci_tos_resident_on(cpu); | |
| 52 | +} | |
| 53 | + | |
| 49 | 54 | static int cpu_psci_cpu_disable(unsigned int cpu) |
| 50 | 55 | { |
| 51 | 56 | /* Fail early if we don't have CPU_OFF support */ |
| @@ -105,14 +110,11 @@ static int cpu_psci_cpu_kill(unsigned int cpu) · 53 unmodified lines | ||
| 105 | 110 | |
| 106 | 111 | const struct cpu_operations cpu_psci_ops = { |
| 107 | 112 | .name = "psci", |
| 108 | −#ifdef CONFIG_CPU_IDLE | |
| 109 | − .cpu_init_idle = psci_cpu_init_idle, | |
| 110 | − .cpu_suspend = psci_cpu_suspend_enter, | |
| 111 | −#endif | |
| 112 | 113 | .cpu_init = cpu_psci_cpu_init, |
| 113 | 114 | .cpu_prepare = cpu_psci_cpu_prepare, |
| 114 | 115 | .cpu_boot = cpu_psci_cpu_boot, |
| 115 | 116 | #ifdef CONFIG_HOTPLUG_CPU |
| 117 | + .cpu_can_disable = cpu_psci_cpu_can_disable, | |
| 116 | 118 | .cpu_disable = cpu_psci_cpu_disable, |
| 117 | 119 | .cpu_die = cpu_psci_cpu_die, |
| 118 | 120 | .cpu_kill = cpu_psci_cpu_kill, |
| @@ -170,9 +170,13 @@ static void __init smp_build_mpidr_hash(void) · 169 unmodified lines | ||
| 170 | 170 | |
| 171 | 171 | static void __init setup_machine_fdt(phys_addr_t dt_phys) |
| 172 | 172 | { |
| 173 | − void *dt_virt = fixmap_remap_fdt(dt_phys); | |
| 173 | + int size; | |
| 174 | + void *dt_virt = fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL); | |
| 174 | 175 | const char *name; |
| 175 | 176 | |
| 177 | + if (dt_virt) | |
| 178 | + memblock_reserve(dt_phys, size); | |
| 179 | + | |
| 176 | 180 | if (!dt_virt || !early_init_dt_scan(dt_virt)) { |
| 177 | 181 | pr_crit("\n" |
| 178 | 182 | "Error: invalid device tree blob at physical address %pa (virtual address 0x%p)\n" |
| @@ -184,6 +188,9 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys) · 5 unmodified lines | ||
| 184 | 188 | cpu_relax(); |
| 185 | 189 | } |
| 186 | 190 | |
| 191 | + /* Early fixups are done, map the FDT as read-only now */ | |
| 192 | + fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL_RO); | |
| 193 | + | |
| 187 | 194 | name = of_flat_dt_get_machine_name(); |
| 188 | 195 | if (!name) |
| 189 | 196 | return; |
| @@ -357,6 +364,15 @@ void __init setup_arch(char **cmdline_p) · 167 unmodified lines | ||
| 357 | 364 | } |
| 358 | 365 | } |
| 359 | 366 | |
| 367 | +static inline bool cpu_can_disable(unsigned int cpu) | |
| 368 | +{ | |
| 369 | +#ifdef CONFIG_HOTPLUG_CPU | |
| 370 | + if (cpu_ops[cpu] && cpu_ops[cpu]->cpu_can_disable) | |
| 371 | + return cpu_ops[cpu]->cpu_can_disable(cpu); | |
| 372 | +#endif | |
| 373 | + return false; | |
| 374 | +} | |
| 375 | + | |
| 360 | 376 | static int __init topology_init(void) |
| 361 | 377 | { |
| 362 | 378 | int i; |
| @@ -366,7 +382,7 @@ static int __init topology_init(void) · 3 unmodified lines | ||
| 366 | 382 | |
| 367 | 383 | for_each_possible_cpu(i) { |
| 368 | 384 | struct cpu *cpu = &per_cpu(cpu_data.cpu, i); |
| 369 | − cpu->hotpluggable = 1; | |
| 385 | + cpu->hotpluggable = cpu_can_disable(i); | |
| 370 | 386 | register_cpu(cpu, i); |
| 371 | 387 | } |
| 372 | 388 | |
| @@ -123,7 +123,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) · 122 unmodified lines | ||
| 123 | 123 | * time out. |
| 124 | 124 | */ |
| 125 | 125 | wait_for_completion_timeout(&cpu_running, |
| 126 | − msecs_to_jiffies(1000)); | |
| 126 | + msecs_to_jiffies(5000)); | |
| 127 | 127 | |
| 128 | 128 | if (!cpu_online(cpu)) { |
| 129 | 129 | pr_crit("CPU%u: failed to come online\n", cpu); |
| @@ -136,6 +136,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) · 6 unmodified lines | ||
| 136 | 136 | |
| 137 | 137 | secondary_data.task = NULL; |
| 138 | 138 | secondary_data.stack = NULL; |
| 139 | + __flush_dcache_area(&secondary_data, sizeof(secondary_data)); | |
| 139 | 140 | status = READ_ONCE(secondary_data.status); |
| 140 | 141 | if (ret && status) { |
| 141 | 142 | |
| @@ -146,6 +147,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) · 4 unmodified lines | ||
| 146 | 147 | default: |
| 147 | 148 | pr_err("CPU%u: failed in unknown state : 0x%lx\n", |
| 148 | 149 | cpu, status); |
| 150 | + cpus_stuck_in_kernel++; | |
| 149 | 151 | break; |
| 150 | 152 | case CPU_KILL_ME: |
| 151 | 153 | if (!op_cpu_kill(cpu)) { |
| @@ -14,250 +14,13 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/acpi.h> |
| 15 | 15 | #include <linux/arch_topology.h> |
| 16 | 16 | #include <linux/cacheinfo.h> |
| 17 | −#include <linux/cpu.h> | |
| 18 | −#include <linux/cpumask.h> | |
| 19 | 17 | #include <linux/init.h> |
| 20 | 18 | #include <linux/percpu.h> |
| 21 | −#include <linux/node.h> | |
| 22 | −#include <linux/nodemask.h> | |
| 23 | −#include <linux/of.h> | |
| 24 | −#include <linux/sched.h> | |
| 25 | −#include <linux/sched/topology.h> | |
| 26 | −#include <linux/slab.h> | |
| 27 | −#include <linux/smp.h> | |
| 28 | −#include <linux/string.h> | |
| 29 | 19 | |
| 30 | 20 | #include <asm/cpu.h> |
| 31 | 21 | #include <asm/cputype.h> |
| 32 | 22 | #include <asm/topology.h> |
| 33 | 23 | |
| 34 | −static int __init get_cpu_for_node(struct device_node *node) | |
| 35 | −{ | |
| 36 | − struct device_node *cpu_node; | |
| 37 | − int cpu; | |
| 38 | − | |
| 39 | − cpu_node = of_parse_phandle(node, "cpu", 0); | |
| 40 | − if (!cpu_node) | |
| 41 | − return -1; | |
| 42 | − | |
| 43 | − cpu = of_cpu_node_to_id(cpu_node); | |
| 44 | − if (cpu >= 0) | |
| 45 | − topology_parse_cpu_capacity(cpu_node, cpu); | |
| 46 | − else | |
| 47 | − pr_crit("Unable to find CPU node for %pOF\n", cpu_node); | |
| 48 | − | |
| 49 | − of_node_put(cpu_node); | |
| 50 | − return cpu; | |
| 51 | −} | |
| 52 | − | |
| 53 | −static int __init parse_core(struct device_node *core, int package_id, | |
| 54 | − int core_id) | |
| 55 | −{ | |
| 56 | − char name[10]; | |
| 57 | − bool leaf = true; | |
| 58 | − int i = 0; | |
| 59 | − int cpu; | |
| 60 | − struct device_node *t; | |
| 61 | − | |
| 62 | − do { | |
| 63 | − snprintf(name, sizeof(name), "thread%d", i); | |
| 64 | − t = of_get_child_by_name(core, name); | |
| 65 | − if (t) { | |
| 66 | − leaf = false; | |
| 67 | − cpu = get_cpu_for_node(t); | |
| 68 | − if (cpu >= 0) { | |
| 69 | − cpu_topology[cpu].package_id = package_id; | |
| 70 | − cpu_topology[cpu].core_id = core_id; | |
| 71 | − cpu_topology[cpu].thread_id = i; | |
| 72 | − } else { | |
| 73 | − pr_err("%pOF: Can't get CPU for thread\n", | |
| 74 | − t); | |
| 75 | − of_node_put(t); | |
| 76 | − return -EINVAL; | |
| 77 | − } | |
| 78 | − of_node_put(t); | |
| 79 | − } | |
| 80 | − i++; | |
| 81 | − } while (t); | |
| 82 | − | |
| 83 | − cpu = get_cpu_for_node(core); | |
| 84 | − if (cpu >= 0) { | |
| 85 | − if (!leaf) { | |
| 86 | − pr_err("%pOF: Core has both threads and CPU\n", | |
| 87 | − core); | |
| 88 | − return -EINVAL; | |
| 89 | − } | |
| 90 | − | |
| 91 | − cpu_topology[cpu].package_id = package_id; | |
| 92 | − cpu_topology[cpu].core_id = core_id; | |
| 93 | − } else if (leaf) { | |
| 94 | − pr_err("%pOF: Can't get CPU for leaf core\n", core); | |
| 95 | − return -EINVAL; | |
| 96 | − } | |
| 97 | − | |
| 98 | − return 0; | |
| 99 | −} | |
| 100 | − | |
| 101 | −static int __init parse_cluster(struct device_node *cluster, int depth) | |
| 102 | −{ | |
| 103 | − char name[10]; | |
| 104 | − bool leaf = true; | |
| 105 | − bool has_cores = false; | |
| 106 | − struct device_node *c; | |
| 107 | − static int package_id __initdata; | |
| 108 | − int core_id = 0; | |
| 109 | − int i, ret; | |
| 110 | − | |
| 111 | − /* | |
| 112 | − * First check for child clusters; we currently ignore any | |
| 113 | − * information about the nesting of clusters and present the | |
| 114 | − * scheduler with a flat list of them. | |
| 115 | − */ | |
| 116 | − i = 0; | |
| 117 | − do { | |
| 118 | − snprintf(name, sizeof(name), "cluster%d", i); | |
| 119 | − c = of_get_child_by_name(cluster, name); | |
| 120 | − if (c) { | |
| 121 | − leaf = false; | |
| 122 | − ret = parse_cluster(c, depth + 1); | |
| 123 | − of_node_put(c); | |
| 124 | − if (ret != 0) | |
| 125 | − return ret; | |
| 126 | − } | |
| 127 | − i++; | |
| 128 | − } while (c); | |
| 129 | − | |
| 130 | − /* Now check for cores */ | |
| 131 | − i = 0; | |
| 132 | − do { | |
| 133 | − snprintf(name, sizeof(name), "core%d", i); | |
| 134 | − c = of_get_child_by_name(cluster, name); | |
| 135 | − if (c) { | |
| 136 | − has_cores = true; | |
| 137 | − | |
| 138 | − if (depth == 0) { | |
| 139 | − pr_err("%pOF: cpu-map children should be clusters\n", | |
| 140 | − c); | |
| 141 | − of_node_put(c); | |
| 142 | − return -EINVAL; | |
| 143 | − } | |
| 144 | − | |
| 145 | − if (leaf) { | |
| 146 | − ret = parse_core(c, package_id, core_id++); | |
| 147 | − } else { | |
| 148 | − pr_err("%pOF: Non-leaf cluster with core %s\n", | |
| 149 | − cluster, name); | |
| 150 | − ret = -EINVAL; | |
| 151 | − } | |
| 152 | − | |
| 153 | − of_node_put(c); | |
| 154 | − if (ret != 0) | |
| 155 | − return ret; | |
| 156 | − } | |
| 157 | − i++; | |
| 158 | − } while (c); | |
| 159 | − | |
| 160 | − if (leaf && !has_cores) | |
| 161 | − pr_warn("%pOF: empty cluster\n", cluster); | |
| 162 | − | |
| 163 | − if (leaf) | |
| 164 | − package_id++; | |
| 165 | − | |
| 166 | − return 0; | |
| 167 | −} | |
| 168 | − | |
| 169 | −static int __init parse_dt_topology(void) | |
| 170 | −{ | |
| 171 | − struct device_node *cn, *map; | |
| 172 | − int ret = 0; | |
| 173 | − int cpu; | |
| 174 | − | |
| 175 | − cn = of_find_node_by_path("/cpus"); | |
| 176 | − if (!cn) { | |
| 177 | − pr_err("No CPU information found in DT\n"); | |
| 178 | − return 0; | |
| 179 | − } | |
| 180 | − | |
| 181 | − /* | |
| 182 | − * When topology is provided cpu-map is essentially a root | |
| 183 | − * cluster with restricted subnodes. | |
| 184 | − */ | |
| 185 | − map = of_get_child_by_name(cn, "cpu-map"); | |
| 186 | − if (!map) | |
| 187 | − goto out; | |
| 188 | − | |
| 189 | − ret = parse_cluster(map, 0); | |
| 190 | − if (ret != 0) | |
| 191 | − goto out_map; | |
| 192 | − | |
| 193 | − topology_normalize_cpu_scale(); | |
| 194 | − | |
| 195 | − /* | |
| 196 | − * Check that all cores are in the topology; the SMP code will | |
| 197 | − * only mark cores described in the DT as possible. | |
| 198 | − */ | |
| 199 | − for_each_possible_cpu(cpu) | |
| 200 | − if (cpu_topology[cpu].package_id == -1) | |
| 201 | − ret = -EINVAL; | |
| 202 | − | |
| 203 | −out_map: | |
| 204 | − of_node_put(map); | |
| 205 | −out: | |
| 206 | − of_node_put(cn); | |
| 207 | − return ret; | |
| 208 | −} | |
| 209 | − | |
| 210 | −/* | |
| 211 | − * cpu topology table | |
| 212 | − */ | |
| 213 | −struct cpu_topology cpu_topology[NR_CPUS]; | |
| 214 | −EXPORT_SYMBOL_GPL(cpu_topology); | |
| 215 | − | |
| 216 | −const struct cpumask *cpu_coregroup_mask(int cpu) | |
| 217 | −{ | |
| 218 | − const cpumask_t *core_mask = cpumask_of_node(cpu_to_node(cpu)); | |
| 219 | − | |
| 220 | − /* Find the smaller of NUMA, core or LLC siblings */ | |
| 221 | − if (cpumask_subset(&cpu_topology[cpu].core_sibling, core_mask)) { | |
| 222 | − /* not numa in package, lets use the package siblings */ | |
| 223 | − core_mask = &cpu_topology[cpu].core_sibling; | |
| 224 | − } | |
| 225 | − if (cpu_topology[cpu].llc_id != -1) { | |
| 226 | − if (cpumask_subset(&cpu_topology[cpu].llc_sibling, core_mask)) | |
| 227 | − core_mask = &cpu_topology[cpu].llc_sibling; | |
| 228 | − } | |
| 229 | − | |
| 230 | − return core_mask; | |
| 231 | −} | |
| 232 | − | |
| 233 | −static void update_siblings_masks(unsigned int cpuid) | |
| 234 | −{ | |
| 235 | − struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid]; | |
| 236 | − int cpu; | |
| 237 | − | |
| 238 | − /* update core and thread sibling masks */ | |
| 239 | − for_each_online_cpu(cpu) { | |
| 240 | − cpu_topo = &cpu_topology[cpu]; | |
| 241 | − | |
| 242 | − if (cpuid_topo->llc_id == cpu_topo->llc_id) { | |
| 243 | − cpumask_set_cpu(cpu, &cpuid_topo->llc_sibling); | |
| 244 | − cpumask_set_cpu(cpuid, &cpu_topo->llc_sibling); | |
| 245 | − } | |
| 246 | − | |
| 247 | − if (cpuid_topo->package_id != cpu_topo->package_id) | |
| 248 | − continue; | |
| 249 | − | |
| 250 | − cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); | |
| 251 | − cpumask_set_cpu(cpu, &cpuid_topo->core_sibling); | |
| 252 | − | |
| 253 | − if (cpuid_topo->core_id != cpu_topo->core_id) | |
| 254 | − continue; | |
| 255 | − | |
| 256 | − cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling); | |
| 257 | − cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling); | |
| 258 | − } | |
| 259 | −} | |
| 260 | − | |
| 261 | 24 | void store_cpu_topology(unsigned int cpuid) |
| 262 | 25 | { |
| 263 | 26 | struct cpu_topology *cpuid_topo = &cpu_topology[cpuid]; |
| @@ -296,60 +59,31 @@ topology_populated: · 32 unmodified lines | ||
| 296 | 59 | update_siblings_masks(cpuid); |
| 297 | 60 | } |
| 298 | 61 | |
| 299 | −static void clear_cpu_topology(int cpu) | |
| 300 | −{ | |
| 301 | − struct cpu_topology *cpu_topo = &cpu_topology[cpu]; | |
| 302 | − | |
| 303 | − cpumask_clear(&cpu_topo->llc_sibling); | |
| 304 | − cpumask_set_cpu(cpu, &cpu_topo->llc_sibling); | |
| 305 | − | |
| 306 | − cpumask_clear(&cpu_topo->core_sibling); | |
| 307 | − cpumask_set_cpu(cpu, &cpu_topo->core_sibling); | |
| 308 | − cpumask_clear(&cpu_topo->thread_sibling); | |
| 309 | − cpumask_set_cpu(cpu, &cpu_topo->thread_sibling); | |
| 310 | −} | |
| 311 | − | |
| 312 | −static void __init reset_cpu_topology(void) | |
| 313 | −{ | |
| 314 | − unsigned int cpu; | |
| 315 | − | |
| 316 | − for_each_possible_cpu(cpu) { | |
| 317 | − struct cpu_topology *cpu_topo = &cpu_topology[cpu]; | |
| 318 | − | |
| 319 | − cpu_topo->thread_id = -1; | |
| 320 | − cpu_topo->core_id = 0; | |
| 321 | − cpu_topo->package_id = -1; | |
| 322 | − cpu_topo->llc_id = -1; | |
| 323 | − | |
| 324 | − clear_cpu_topology(cpu); | |
| 325 | − } | |
| 326 | −} | |
| 327 | − | |
| 328 | −void remove_cpu_topology(unsigned int cpu) | |
| 62 | +#ifdef CONFIG_ACPI | |
| 63 | +static bool __init acpi_cpu_is_threaded(int cpu) | |
| 329 | 64 | { |
| 330 | − int sibling; | |
| 65 | + int is_threaded = acpi_pptt_cpu_is_thread(cpu); | |
| 331 | 66 | |
| 332 | − for_each_cpu(sibling, topology_core_cpumask(cpu)) | |
| 333 | − cpumask_clear_cpu(cpu, topology_core_cpumask(sibling)); | |
| 334 | − for_each_cpu(sibling, topology_sibling_cpumask(cpu)) | |
| 335 | − cpumask_clear_cpu(cpu, topology_sibling_cpumask(sibling)); | |
| 336 | − for_each_cpu(sibling, topology_llc_cpumask(cpu)) | |
| 337 | − cpumask_clear_cpu(cpu, topology_llc_cpumask(sibling)); | |
| 67 | + /* | |
| 68 | + * if the PPTT doesn't have thread information, assume a homogeneous | |
| 69 | + * machine and return the current CPU's thread state. | |
| 70 | + */ | |
| 71 | + if (is_threaded < 0) | |
| 72 | + is_threaded = read_cpuid_mpidr() & MPIDR_MT_BITMASK; | |
| 338 | 73 | |
| 339 | − clear_cpu_topology(cpu); | |
| 74 | + return !!is_threaded; | |
| 340 | 75 | } |
| 341 | 76 | |
| 342 | −#ifdef CONFIG_ACPI | |
| 343 | 77 | /* |
| 344 | 78 | * Propagate the topology information of the processor_topology_node tree to the |
| 345 | 79 | * cpu_topology array. |
| 346 | 80 | */ |
| 347 | −static int __init parse_acpi_topology(void) | |
| 81 | +int __init parse_acpi_topology(void) | |
| 348 | 82 | { |
| 349 | − bool is_threaded; | |
| 350 | 83 | int cpu, topology_id; |
| 351 | 84 | |
| 352 | − is_threaded = read_cpuid_mpidr() & MPIDR_MT_BITMASK; | |
| 85 | + if (acpi_disabled) | |
| 86 | + return 0; | |
| 353 | 87 | |
| 354 | 88 | for_each_possible_cpu(cpu) { |
| 355 | 89 | int i, cache_id; |
| @@ -358,7 +92,7 @@ static int __init parse_acpi_topology(void) · 2 unmodified lines | ||
| 358 | 92 | if (topology_id < 0) |
| 359 | 93 | return topology_id; |
| 360 | 94 | |
| 361 | − if (is_threaded) { | |
| 95 | + if (acpi_cpu_is_threaded(cpu)) { | |
| 362 | 96 | cpu_topology[cpu].thread_id = topology_id; |
| 363 | 97 | topology_id = find_acpi_cpu_topology(cpu, 1); |
| 364 | 98 | cpu_topology[cpu].core_id = topology_id; |
| @@ -384,24 +118,6 @@ static int __init parse_acpi_topology(void) · 19 unmodified lines | ||
| 384 | 118 | |
| 385 | 119 | return 0; |
| 386 | 120 | } |
| 387 | − | |
| 388 | −#else | |
| 389 | −static inline int __init parse_acpi_topology(void) | |
| 390 | −{ | |
| 391 | − return -EINVAL; | |
| 392 | −} | |
| 393 | 121 | #endif |
| 394 | 122 | |
| 395 | −void __init init_cpu_topology(void) | |
| 396 | −{ | |
| 397 | − reset_cpu_topology(); | |
| 398 | 123 | |
| 399 | − /* | |
| 400 | − * Discard anything that was parsed if we hit an error so we | |
| 401 | − * don't use partial information. | |
| 402 | − */ | |
| 403 | − if (!acpi_disabled && parse_acpi_topology()) | |
| 404 | − reset_cpu_topology(); | |
| 405 | − else if (of_have_populated_dt() && parse_dt_topology()) | |
| 406 | − reset_cpu_topology(); | |
| 407 | −} | |
| @@ -264,7 +264,7 @@ static bool __hyp_text __translate_far_to_hpfar(u64 far, u64 *hpfar) · 263 unmodified lines | ||
| 264 | 264 | tmp = read_sysreg(par_el1); |
| 265 | 265 | write_sysreg(par, par_el1); |
| 266 | 266 | |
| 267 | − if (unlikely(tmp & 1)) | |
| 267 | + if (unlikely(tmp & SYS_PAR_EL1_F)) | |
| 268 | 268 | return false; /* Translation failed, back to guest */ |
| 269 | 269 | |
| 270 | 270 | /* Convert PAR to HPFAR format */ |
| @@ -29,25 +29,25 @@ static void compute_layout(void) · 28 unmodified lines | ||
| 29 | 29 | int kva_msb; |
| 30 | 30 | |
| 31 | 31 | /* Where is my RAM region? */ |
| 32 | − hyp_va_msb = idmap_addr & BIT(VA_BITS - 1); | |
| 33 | − hyp_va_msb ^= BIT(VA_BITS - 1); | |
| 32 | + hyp_va_msb = idmap_addr & BIT(vabits_actual - 1); | |
| 33 | + hyp_va_msb ^= BIT(vabits_actual - 1); | |
| 34 | 34 | |
| 35 | 35 | kva_msb = fls64((u64)phys_to_virt(memblock_start_of_DRAM()) ^ |
| 36 | 36 | (u64)(high_memory - 1)); |
| 37 | 37 | |
| 38 | − if (kva_msb == (VA_BITS - 1)) { | |
| 38 | + if (kva_msb == (vabits_actual - 1)) { | |
| 39 | 39 | /* |
| 40 | 40 | * No space in the address, let's compute the mask so |
| 41 | − * that it covers (VA_BITS - 1) bits, and the region | |
| 41 | + * that it covers (vabits_actual - 1) bits, and the region | |
| 42 | 42 | * bit. The tag stays set to zero. |
| 43 | 43 | */ |
| 44 | − va_mask = BIT(VA_BITS - 1) - 1; | |
| 44 | + va_mask = BIT(vabits_actual - 1) - 1; | |
| 45 | 45 | va_mask |= hyp_va_msb; |
| 46 | 46 | } else { |
| 47 | 47 | /* |
| 48 | 48 | * We do have some free bits to insert a random tag. |
| 49 | 49 | * Hyp VAs are now created from kernel linear map VAs |
| 50 | − * using the following formula (with V == VA_BITS): | |
| 50 | + * using the following formula (with V == vabits_actual): | |
| 51 | 51 | * |
| 52 | 52 | * 63 ... V | V-1 | V-2 .. tag_lsb | tag_lsb - 1 .. 0 |
| 53 | 53 | * --------------------------------------------------------- |
| @@ -55,7 +55,7 @@ static void compute_layout(void) · 1 unmodified line | ||
| 55 | 55 | */ |
| 56 | 56 | tag_lsb = kva_msb; |
| 57 | 57 | va_mask = GENMASK_ULL(tag_lsb - 1, 0); |
| 58 | − tag_val = get_random_long() & GENMASK_ULL(VA_BITS - 2, tag_lsb); | |
| 58 | + tag_val = get_random_long() & GENMASK_ULL(vabits_actual - 2, tag_lsb); | |
| 59 | 59 | tag_val |= hyp_va_msb; |
| 60 | 60 | tag_val >>= tag_lsb; |
| 61 | 61 | } |
| @@ -33,3 +33,5 @@ UBSAN_SANITIZE_atomic_ll_sc.o := n · 32 unmodified lines | ||
| 33 | 33 | lib-$(CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE) += uaccess_flushcache.o |
| 34 | 34 | |
| 35 | 35 | obj-$(CONFIG_CRC32) += crc32.o |
| 36 | + | |
| 37 | +obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o | |
| @@ -0,0 +1,18 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 2 | + | |
| 3 | +#include <linux/error-injection.h> | |
| 4 | +#include <linux/kprobes.h> | |
| 5 | + | |
| 6 | +void override_function_with_return(struct pt_regs *regs) | |
| 7 | +{ | |
| 8 | + /* | |
| 9 | + * 'regs' represents the state on entry of a predefined function in | |
| 10 | + * the kernel/module and which is captured on a kprobe. | |
| 11 | + * | |
| 12 | + * When kprobe returns back from exception it will override the end | |
| 13 | + * of probed function and directly return to the predefined | |
| 14 | + * function's caller. | |
| 15 | + */ | |
| 16 | + instruction_pointer_set(regs, procedure_link_pointer(regs)); | |
| 17 | +} | |
| 18 | +NOKPROBE_SYMBOL(override_function_with_return); | |
| @@ -25,9 +25,20 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <asm/pgtable-hwdef.h> |
| 26 | 26 | #include <asm/ptdump.h> |
| 27 | 27 | |
| 28 | −static const struct addr_marker address_markers[] = { | |
| 28 | + | |
| 29 | +enum address_markers_idx { | |
| 30 | + PAGE_OFFSET_NR = 0, | |
| 31 | + PAGE_END_NR, | |
| 29 | 32 | #ifdef CONFIG_KASAN |
| 30 | − { KASAN_SHADOW_START, "Kasan shadow start" }, | |
| 33 | + KASAN_START_NR, | |
| 34 | +#endif | |
| 35 | +}; | |
| 36 | + | |
| 37 | +static struct addr_marker address_markers[] = { | |
| 38 | + { PAGE_OFFSET, "Linear Mapping start" }, | |
| 39 | + { 0 /* PAGE_END */, "Linear Mapping end" }, | |
| 40 | +#ifdef CONFIG_KASAN | |
| 41 | + { 0 /* KASAN_SHADOW_START */, "Kasan shadow start" }, | |
| 31 | 42 | { KASAN_SHADOW_END, "Kasan shadow end" }, |
| 32 | 43 | #endif |
| 33 | 44 | { MODULES_VADDR, "Modules start" }, |
| @@ -42,7 +53,6 @@ static const struct addr_marker address_markers[] = { · 8 unmodified lines | ||
| 42 | 53 | { VMEMMAP_START, "vmemmap start" }, |
| 43 | 54 | { VMEMMAP_START + VMEMMAP_SIZE, "vmemmap end" }, |
| 44 | 55 | #endif |
| 45 | − { PAGE_OFFSET, "Linear mapping" }, | |
| 46 | 56 | { -1, NULL }, |
| 47 | 57 | }; |
| 48 | 58 | |
| @@ -376,7 +386,7 @@ static void ptdump_initialize(void) · 327 unmodified lines | ||
| 376 | 386 | static struct ptdump_info kernel_ptdump_info = { |
| 377 | 387 | .mm = &init_mm, |
| 378 | 388 | .markers = address_markers, |
| 379 | − .base_addr = VA_START, | |
| 389 | + .base_addr = PAGE_OFFSET, | |
| 380 | 390 | }; |
| 381 | 391 | |
| 382 | 392 | void ptdump_check_wx(void) |
| @@ -390,7 +400,7 @@ void ptdump_check_wx(void) · 7 unmodified lines | ||
| 390 | 400 | .check_wx = true, |
| 391 | 401 | }; |
| 392 | 402 | |
| 393 | − walk_pgd(&st, &init_mm, VA_START); | |
| 403 | + walk_pgd(&st, &init_mm, PAGE_OFFSET); | |
| 394 | 404 | note_page(&st, 0, 0, 0); |
| 395 | 405 | if (st.wx_pages || st.uxn_pages) |
| 396 | 406 | pr_warn("Checked W+X mappings: FAILED, %lu W+X pages found, %lu non-UXN pages found\n", |
| @@ -401,6 +411,10 @@ void ptdump_check_wx(void) · 4 unmodified lines | ||
| 401 | 411 | |
| 402 | 412 | static int ptdump_init(void) |
| 403 | 413 | { |
| 414 | + address_markers[PAGE_END_NR].start_address = PAGE_END; | |
| 415 | +#ifdef CONFIG_KASAN | |
| 416 | + address_markers[KASAN_START_NR].start_address = KASAN_SHADOW_START; | |
| 417 | +#endif | |
| 404 | 418 | ptdump_initialize(); |
| 405 | 419 | ptdump_debugfs_register(&kernel_ptdump_info, "kernel_page_tables"); |
| 406 | 420 | return 0; |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | 10 | #include <linux/acpi.h> |
| 11 | +#include <linux/bitfield.h> | |
| 11 | 12 | #include <linux/extable.h> |
| 12 | 13 | #include <linux/signal.h> |
| 13 | 14 | #include <linux/mm.h> |
| @@ -109,7 +110,7 @@ static inline bool is_ttbr0_addr(unsigned long addr) · 95 unmodified lines | ||
| 109 | 110 | static inline bool is_ttbr1_addr(unsigned long addr) |
| 110 | 111 | { |
| 111 | 112 | /* TTBR1 addresses may have a tag if KASAN_SW_TAGS is in use */ |
| 112 | − return arch_kasan_reset_tag(addr) >= VA_START; | |
| 113 | + return arch_kasan_reset_tag(addr) >= PAGE_OFFSET; | |
| 113 | 114 | } |
| 114 | 115 | |
| 115 | 116 | /* |
| @@ -138,10 +139,9 @@ static void show_pte(unsigned long addr) · 22 unmodified lines | ||
| 138 | 139 | return; |
| 139 | 140 | } |
| 140 | 141 | |
| 141 | − pr_alert("%s pgtable: %luk pages, %u-bit VAs, pgdp=%016lx\n", | |
| 142 | + pr_alert("%s pgtable: %luk pages, %llu-bit VAs, pgdp=%016lx\n", | |
| 142 | 143 | mm == &init_mm ? "swapper" : "user", PAGE_SIZE / SZ_1K, |
| 143 | − mm == &init_mm ? VA_BITS : (int)vabits_user, | |
| 144 | − (unsigned long)virt_to_phys(mm->pgd)); | |
| 144 | + vabits_actual, (unsigned long)virt_to_phys(mm->pgd)); | |
| 145 | 145 | pgdp = pgd_offset(mm, addr); |
| 146 | 146 | pgd = READ_ONCE(*pgdp); |
| 147 | 147 | pr_alert("[%016lx] pgd=%016llx", addr, pgd_val(pgd)); |
| @@ -242,6 +242,34 @@ static inline bool is_el1_permission_fault(unsigned long addr, unsigned int esr, · 94 unmodified lines | ||
| 242 | 242 | return false; |
| 243 | 243 | } |
| 244 | 244 | |
| 245 | +static bool __kprobes is_spurious_el1_translation_fault(unsigned long addr, | |
| 246 | + unsigned int esr, | |
| 247 | + struct pt_regs *regs) | |
| 248 | +{ | |
| 249 | + unsigned long flags; | |
| 250 | + u64 par, dfsc; | |
| 251 | + | |
| 252 | + if (ESR_ELx_EC(esr) != ESR_ELx_EC_DABT_CUR || | |
| 253 | + (esr & ESR_ELx_FSC_TYPE) != ESR_ELx_FSC_FAULT) | |
| 254 | + return false; | |
| 255 | + | |
| 256 | + local_irq_save(flags); | |
| 257 | + asm volatile("at s1e1r, %0" :: "r" (addr)); | |
| 258 | + isb(); | |
| 259 | + par = read_sysreg(par_el1); | |
| 260 | + local_irq_restore(flags); | |
| 261 | + | |
| 262 | + if (!(par & SYS_PAR_EL1_F)) | |
| 263 | + return false; | |
| 264 | + | |
| 265 | + /* | |
| 266 | + * If we got a different type of fault from the AT instruction, | |
| 267 | + * treat the translation fault as spurious. | |
| 268 | + */ | |
| 269 | + dfsc = FIELD_PREP(SYS_PAR_EL1_FST, par); | |
| 270 | + return (dfsc & ESR_ELx_FSC_TYPE) != ESR_ELx_FSC_FAULT; | |
| 271 | +} | |
| 272 | + | |
| 245 | 273 | static void die_kernel_fault(const char *msg, unsigned long addr, |
| 246 | 274 | unsigned int esr, struct pt_regs *regs) |
| 247 | 275 | { |
| @@ -270,6 +298,10 @@ static void __do_kernel_fault(unsigned long addr, unsigned int esr, · 22 unmodified lines | ||
| 270 | 298 | if (!is_el1_instruction_abort(esr) && fixup_exception(regs)) |
| 271 | 299 | return; |
| 272 | 300 | |
| 301 | + if (WARN_RATELIMIT(is_spurious_el1_translation_fault(addr, esr, regs), | |
| 302 | + "Ignoring spurious kernel translation fault at virtual address %016lx\n", addr)) | |
| 303 | + return; | |
| 304 | + | |
| 273 | 305 | if (is_el1_permission_fault(addr, esr, regs)) { |
| 274 | 306 | if (esr & ESR_ELx_WNR) |
| 275 | 307 | msg = "write to read-only memory"; |
| @@ -50,6 +50,12 @@ · 49 unmodified lines | ||
| 50 | 50 | s64 memstart_addr __ro_after_init = -1; |
| 51 | 51 | EXPORT_SYMBOL(memstart_addr); |
| 52 | 52 | |
| 53 | +s64 physvirt_offset __ro_after_init; | |
| 54 | +EXPORT_SYMBOL(physvirt_offset); | |
| 55 | + | |
| 56 | +struct page *vmemmap __ro_after_init; | |
| 57 | +EXPORT_SYMBOL(vmemmap); | |
| 58 | + | |
| 53 | 59 | phys_addr_t arm64_dma_phys_limit __ro_after_init; |
| 54 | 60 | |
| 55 | 61 | #ifdef CONFIG_KEXEC_CORE |
| @@ -301,7 +307,7 @@ static void __init fdt_enforce_memory_region(void) · 245 unmodified lines | ||
| 301 | 307 | |
| 302 | 308 | void __init arm64_memblock_init(void) |
| 303 | 309 | { |
| 304 | − const s64 linear_region_size = -(s64)PAGE_OFFSET; | |
| 310 | + const s64 linear_region_size = BIT(vabits_actual - 1); | |
| 305 | 311 | |
| 306 | 312 | /* Handle linux,usable-memory-range property */ |
| 307 | 313 | fdt_enforce_memory_region(); |
| @@ -309,19 +315,26 @@ void __init arm64_memblock_init(void) · 1 unmodified line | ||
| 309 | 315 | /* Remove memory above our supported physical address size */ |
| 310 | 316 | memblock_remove(1ULL << PHYS_MASK_SHIFT, ULLONG_MAX); |
| 311 | 317 | |
| 312 | − /* | |
| 313 | − * Ensure that the linear region takes up exactly half of the kernel | |
| 314 | − * virtual address space. This way, we can distinguish a linear address | |
| 315 | − * from a kernel/module/vmalloc address by testing a single bit. | |
| 316 | − */ | |
| 317 | − BUILD_BUG_ON(linear_region_size != BIT(VA_BITS - 1)); | |
| 318 | − | |
| 319 | 318 | /* |
| 320 | 319 | * Select a suitable value for the base of physical memory. |
| 321 | 320 | */ |
| 322 | 321 | memstart_addr = round_down(memblock_start_of_DRAM(), |
| 323 | 322 | ARM64_MEMSTART_ALIGN); |
| 324 | 323 | |
| 324 | + physvirt_offset = PHYS_OFFSET - PAGE_OFFSET; | |
| 325 | + | |
| 326 | + vmemmap = ((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT)); | |
| 327 | + | |
| 328 | + /* | |
| 329 | + * If we are running with a 52-bit kernel VA config on a system that | |
| 330 | + * does not support it, we have to offset our vmemmap and physvirt_offset | |
| 331 | + * s.t. we avoid the 52-bit portion of the direct linear map | |
| 332 | + */ | |
| 333 | + if (IS_ENABLED(CONFIG_ARM64_VA_BITS_52) && (vabits_actual != 52)) { | |
| 334 | + vmemmap += (_PAGE_OFFSET(48) - _PAGE_OFFSET(52)) >> PAGE_SHIFT; | |
| 335 | + physvirt_offset = PHYS_OFFSET - _PAGE_OFFSET(48); | |
| 336 | + } | |
| 337 | + | |
| 325 | 338 | /* |
| 326 | 339 | * Remove the memory that we will not be able to cover with the |
| 327 | 340 | * linear mapping. Take care not to clip the kernel which may be |
| @@ -156,7 +156,8 @@ asmlinkage void __init kasan_early_init(void) · 155 unmodified lines | ||
| 156 | 156 | { |
| 157 | 157 | BUILD_BUG_ON(KASAN_SHADOW_OFFSET != |
| 158 | 158 | KASAN_SHADOW_END - (1UL << (64 - KASAN_SHADOW_SCALE_SHIFT))); |
| 159 | − BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_START, PGDIR_SIZE)); | |
| 159 | + BUILD_BUG_ON(!IS_ALIGNED(_KASAN_SHADOW_START(VA_BITS), PGDIR_SIZE)); | |
| 160 | + BUILD_BUG_ON(!IS_ALIGNED(_KASAN_SHADOW_START(VA_BITS_MIN), PGDIR_SIZE)); | |
| 160 | 161 | BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_END, PGDIR_SIZE)); |
| 161 | 162 | kasan_pgd_populate(KASAN_SHADOW_START, KASAN_SHADOW_END, NUMA_NO_NODE, |
| 162 | 163 | true); |
| @@ -225,10 +226,10 @@ void __init kasan_init(void) · 62 unmodified lines | ||
| 225 | 226 | kasan_map_populate(kimg_shadow_start, kimg_shadow_end, |
| 226 | 227 | early_pfn_to_nid(virt_to_pfn(lm_alias(_text)))); |
| 227 | 228 | |
| 228 | − kasan_populate_early_shadow((void *)KASAN_SHADOW_START, | |
| 229 | − (void *)mod_shadow_start); | |
| 229 | + kasan_populate_early_shadow(kasan_mem_to_shadow((void *)PAGE_END), | |
| 230 | + (void *)mod_shadow_start); | |
| 230 | 231 | kasan_populate_early_shadow((void *)kimg_shadow_end, |
| 231 | − kasan_mem_to_shadow((void *)PAGE_OFFSET)); | |
| 232 | + (void *)KASAN_SHADOW_END); | |
| 232 | 233 | |
| 233 | 234 | if (kimg_shadow_start > mod_shadow_end) |
| 234 | 235 | kasan_populate_early_shadow((void *)mod_shadow_end, |
| @@ -40,8 +40,9 @@ · 39 unmodified lines | ||
| 40 | 40 | |
| 41 | 41 | u64 idmap_t0sz = TCR_T0SZ(VA_BITS); |
| 42 | 42 | u64 idmap_ptrs_per_pgd = PTRS_PER_PGD; |
| 43 | −u64 vabits_user __ro_after_init; | |
| 44 | −EXPORT_SYMBOL(vabits_user); | |
| 43 | + | |
| 44 | +u64 __section(".mmuoff.data.write") vabits_actual; | |
| 45 | +EXPORT_SYMBOL(vabits_actual); | |
| 45 | 46 | |
| 46 | 47 | u64 kimage_voffset __ro_after_init; |
| 47 | 48 | EXPORT_SYMBOL(kimage_voffset); |
| @@ -398,7 +399,7 @@ static phys_addr_t pgd_pgtable_alloc(int shift) · 350 unmodified lines | ||
| 398 | 399 | static void __init create_mapping_noalloc(phys_addr_t phys, unsigned long virt, |
| 399 | 400 | phys_addr_t size, pgprot_t prot) |
| 400 | 401 | { |
| 401 | − if (virt < VMALLOC_START) { | |
| 402 | + if ((virt >= PAGE_END) && (virt < VMALLOC_START)) { | |
| 402 | 403 | pr_warn("BUG: not creating mapping for %pa at 0x%016lx - outside kernel range\n", |
| 403 | 404 | &phys, virt); |
| 404 | 405 | return; |
| @@ -425,7 +426,7 @@ void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, · 20 unmodified lines | ||
| 425 | 426 | static void update_mapping_prot(phys_addr_t phys, unsigned long virt, |
| 426 | 427 | phys_addr_t size, pgprot_t prot) |
| 427 | 428 | { |
| 428 | − if (virt < VMALLOC_START) { | |
| 429 | + if ((virt >= PAGE_END) && (virt < VMALLOC_START)) { | |
| 429 | 430 | pr_warn("BUG: not updating mapping for %pa at 0x%016lx - outside kernel range\n", |
| 430 | 431 | &phys, virt); |
| 431 | 432 | return; |
| @@ -646,6 +647,8 @@ static void __init map_kernel(pgd_t *pgdp) · 214 unmodified lines | ||
| 646 | 647 | set_pgd(pgd_offset_raw(pgdp, FIXADDR_START), |
| 647 | 648 | READ_ONCE(*pgd_offset_k(FIXADDR_START))); |
| 648 | 649 | } else if (CONFIG_PGTABLE_LEVELS > 3) { |
| 650 | + pgd_t *bm_pgdp; | |
| 651 | + pud_t *bm_pudp; | |
| 649 | 652 | /* |
| 650 | 653 | * The fixmap shares its top level pgd entry with the kernel |
| 651 | 654 | * mapping. This can really only occur when we are running |
| @@ -653,9 +656,9 @@ static void __init map_kernel(pgd_t *pgdp) · 1 unmodified line | ||
| 653 | 656 | * entry instead. |
| 654 | 657 | */ |
| 655 | 658 | BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES)); |
| 656 | − pud_populate(&init_mm, | |
| 657 | − pud_set_fixmap_offset(pgdp, FIXADDR_START), | |
| 658 | − lm_alias(bm_pmd)); | |
| 659 | + bm_pgdp = pgd_offset_raw(pgdp, FIXADDR_START); | |
| 660 | + bm_pudp = pud_set_fixmap_offset(bm_pgdp, FIXADDR_START); | |
| 661 | + pud_populate(&init_mm, bm_pudp, lm_alias(bm_pmd)); | |
| 659 | 662 | pud_clear_fixmap(); |
| 660 | 663 | } else { |
| 661 | 664 | BUG(); |
| @@ -876,7 +879,7 @@ void __set_fixmap(enum fixed_addresses idx, · 214 unmodified lines | ||
| 876 | 879 | } |
| 877 | 880 | } |
| 878 | 881 | |
| 879 | −void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot) | |
| 882 | +void *__init fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot) | |
| 880 | 883 | { |
| 881 | 884 | const u64 dt_virt_base = __fix_to_virt(FIX_FDT); |
| 882 | 885 | int offset; |
| @@ -929,19 +932,6 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot) · 46 unmodified lines | ||
| 929 | 932 | return dt_virt; |
| 930 | 933 | } |
| 931 | 934 | |
| 932 | −void *__init fixmap_remap_fdt(phys_addr_t dt_phys) | |
| 933 | −{ | |
| 934 | − void *dt_virt; | |
| 935 | − int size; | |
| 936 | − | |
| 937 | − dt_virt = __fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL_RO); | |
| 938 | − if (!dt_virt) | |
| 939 | − return NULL; | |
| 940 | − | |
| 941 | − memblock_reserve(dt_phys, size); | |
| 942 | − return dt_virt; | |
| 943 | −} | |
| 944 | − | |
| 945 | 935 | int __init arch_ioremap_p4d_supported(void) |
| 946 | 936 | { |
| 947 | 937 | return 0; |
| @@ -168,7 +168,7 @@ ENDPROC(cpu_do_switch_mm) · 167 unmodified lines | ||
| 168 | 168 | .macro __idmap_cpu_set_reserved_ttbr1, tmp1, tmp2 |
| 169 | 169 | adrp \tmp1, empty_zero_page |
| 170 | 170 | phys_to_ttbr \tmp2, \tmp1 |
| 171 | − offset_ttbr1 \tmp2 | |
| 171 | + offset_ttbr1 \tmp2, \tmp1 | |
| 172 | 172 | msr ttbr1_el1, \tmp2 |
| 173 | 173 | isb |
| 174 | 174 | tlbi vmalle1 |
| @@ -187,7 +187,7 @@ ENTRY(idmap_cpu_replace_ttbr1) · 12 unmodified lines | ||
| 187 | 187 | |
| 188 | 188 | __idmap_cpu_set_reserved_ttbr1 x1, x3 |
| 189 | 189 | |
| 190 | − offset_ttbr1 x0 | |
| 190 | + offset_ttbr1 x0, x3 | |
| 191 | 191 | msr ttbr1_el1, x0 |
| 192 | 192 | isb |
| 193 | 193 | |
| @@ -371,7 +371,7 @@ __idmap_kpti_secondary: · 177 unmodified lines | ||
| 371 | 371 | cbnz w18, 1b |
| 372 | 372 | |
| 373 | 373 | /* All done, act like nothing happened */ |
| 374 | − offset_ttbr1 swapper_ttb | |
| 374 | + offset_ttbr1 swapper_ttb, x18 | |
| 375 | 375 | msr ttbr1_el1, swapper_ttb |
| 376 | 376 | isb |
| 377 | 377 | ret |
| @@ -447,10 +447,11 @@ ENTRY(__cpu_setup) · 69 unmodified lines | ||
| 447 | 447 | TCR_TBI0 | TCR_A1 | TCR_KASAN_FLAGS |
| 448 | 448 | tcr_clear_errata_bits x10, x9, x5 |
| 449 | 449 | |
| 450 | −#ifdef CONFIG_ARM64_USER_VA_BITS_52 | |
| 451 | − ldr_l x9, vabits_user | |
| 450 | +#ifdef CONFIG_ARM64_VA_BITS_52 | |
| 451 | + ldr_l x9, vabits_actual | |
| 452 | 452 | sub x9, xzr, x9 |
| 453 | 453 | add x9, x9, #64 |
| 454 | + tcr_set_t1sz x10, x9 | |
| 454 | 455 | #else |
| 455 | 456 | ldr_l x9, idmap_t0sz |
| 456 | 457 | #endif |
| @@ -1,13 +0,0 @@ | ||
| 1 | −/* SPDX-License-Identifier: GPL-2.0+ */ | |
| 2 | − | |
| 3 | −#ifndef _ASM_ERROR_INJECTION_H | |
| 4 | −#define _ASM_ERROR_INJECTION_H | |
| 5 | − | |
| 6 | −#include <linux/compiler.h> | |
| 7 | −#include <linux/linkage.h> | |
| 8 | −#include <asm/ptrace.h> | |
| 9 | −#include <asm-generic/error-injection.h> | |
| 10 | − | |
| 11 | −void override_function_with_return(struct pt_regs *regs); | |
| 12 | − | |
| 13 | −#endif /* _ASM_ERROR_INJECTION_H */ | |
| @@ -48,6 +48,7 @@ config RISCV · 47 unmodified lines | ||
| 48 | 48 | select PCI_MSI if PCI |
| 49 | 49 | select RISCV_TIMER |
| 50 | 50 | select GENERIC_IRQ_MULTI_HANDLER |
| 51 | + select GENERIC_ARCH_TOPOLOGY if SMP | |
| 51 | 52 | select ARCH_HAS_PTE_SPECIAL |
| 52 | 53 | select ARCH_HAS_MMIOWB |
| 53 | 54 | select HAVE_EBPF_JIT if 64BIT |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | * Copyright (C) 2017 SiFive |
| 9 | 9 | */ |
| 10 | 10 | |
| 11 | +#include <linux/arch_topology.h> | |
| 11 | 12 | #include <linux/module.h> |
| 12 | 13 | #include <linux/init.h> |
| 13 | 14 | #include <linux/kernel.h> |
| @@ -35,6 +36,7 @@ static DECLARE_COMPLETION(cpu_running); · 21 unmodified lines | ||
| 35 | 36 | |
| 36 | 37 | void __init smp_prepare_boot_cpu(void) |
| 37 | 38 | { |
| 39 | + init_cpu_topology(); | |
| 38 | 40 | } |
| 39 | 41 | |
| 40 | 42 | void __init smp_prepare_cpus(unsigned int max_cpus) |
| @@ -138,6 +140,7 @@ asmlinkage void __init smp_callin(void) · 97 unmodified lines | ||
| 138 | 140 | |
| 139 | 141 | trap_init(); |
| 140 | 142 | notify_cpu_starting(smp_processor_id()); |
| 143 | + update_siblings_masks(smp_processor_id()); | |
| 141 | 144 | set_cpu_online(smp_processor_id(), 1); |
| 142 | 145 | /* |
| 143 | 146 | * Remote TLB flushes are ignored while the CPU is offline, so emit |
| @@ -1,13 +0,0 @@ | ||
| 1 | −/* SPDX-License-Identifier: GPL-2.0 */ | |
| 2 | −#ifndef _ASM_ERROR_INJECTION_H | |
| 3 | −#define _ASM_ERROR_INJECTION_H | |
| 4 | − | |
| 5 | −#include <linux/compiler.h> | |
| 6 | −#include <linux/linkage.h> | |
| 7 | −#include <asm/ptrace.h> | |
| 8 | −#include <asm-generic/error-injection.h> | |
| 9 | − | |
| 10 | −asmlinkage void just_return_func(void); | |
| 11 | −void override_function_with_return(struct pt_regs *regs); | |
| 12 | − | |
| 13 | −#endif /* _ASM_ERROR_INJECTION_H */ | |
| @@ -540,6 +540,44 @@ static int find_acpi_cpu_topology_tag(unsigned int cpu, int level, int flag) · 539 unmodified lines | ||
| 540 | 540 | return retval; |
| 541 | 541 | } |
| 542 | 542 | |
| 543 | +/** | |
| 544 | + * check_acpi_cpu_flag() - Determine if CPU node has a flag set | |
| 545 | + * @cpu: Kernel logical CPU number | |
| 546 | + * @rev: The minimum PPTT revision defining the flag | |
| 547 | + * @flag: The flag itself | |
| 548 | + * | |
| 549 | + * Check the node representing a CPU for a given flag. | |
| 550 | + * | |
| 551 | + * Return: -ENOENT if the PPTT doesn't exist, the CPU cannot be found or | |
| 552 | + * the table revision isn't new enough. | |
| 553 | + * 1, any passed flag set | |
| 554 | + * 0, flag unset | |
| 555 | + */ | |
| 556 | +static int check_acpi_cpu_flag(unsigned int cpu, int rev, u32 flag) | |
| 557 | +{ | |
| 558 | + struct acpi_table_header *table; | |
| 559 | + acpi_status status; | |
| 560 | + u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu); | |
| 561 | + struct acpi_pptt_processor *cpu_node = NULL; | |
| 562 | + int ret = -ENOENT; | |
| 563 | + | |
| 564 | + status = acpi_get_table(ACPI_SIG_PPTT, 0, &table); | |
| 565 | + if (ACPI_FAILURE(status)) { | |
| 566 | + acpi_pptt_warn_missing(); | |
| 567 | + return ret; | |
| 568 | + } | |
| 569 | + | |
| 570 | + if (table->revision >= rev) | |
| 571 | + cpu_node = acpi_find_processor_node(table, acpi_cpu_id); | |
| 572 | + | |
| 573 | + if (cpu_node) | |
| 574 | + ret = (cpu_node->flags & flag) != 0; | |
| 575 | + | |
| 576 | + acpi_put_table(table); | |
| 577 | + | |
| 578 | + return ret; | |
| 579 | +} | |
| 580 | + | |
| 543 | 581 | /** |
| 544 | 582 | * acpi_find_last_cache_level() - Determines the number of cache levels for a PE |
| 545 | 583 | * @cpu: Kernel logical CPU number |
| @@ -604,6 +642,20 @@ int cache_setup_acpi(unsigned int cpu) · 58 unmodified lines | ||
| 604 | 642 | return status; |
| 605 | 643 | } |
| 606 | 644 | |
| 645 | +/** | |
| 646 | + * acpi_pptt_cpu_is_thread() - Determine if CPU is a thread | |
| 647 | + * @cpu: Kernel logical CPU number | |
| 648 | + * | |
| 649 | + * Return: 1, a thread | |
| 650 | + * 0, not a thread | |
| 651 | + * -ENOENT ,if the PPTT doesn't exist, the CPU cannot be found or | |
| 652 | + * the table revision isn't new enough. | |
| 653 | + */ | |
| 654 | +int acpi_pptt_cpu_is_thread(unsigned int cpu) | |
| 655 | +{ | |
| 656 | + return check_acpi_cpu_flag(cpu, 2, ACPI_PPTT_ACPI_PROCESSOR_IS_THREAD); | |
| 657 | +} | |
| 658 | + | |
| 607 | 659 | /** |
| 608 | 660 | * find_acpi_cpu_topology() - Determine a unique topology value for a given CPU |
| 609 | 661 | * @cpu: Kernel logical CPU number |
| @@ -664,7 +716,6 @@ int find_acpi_cpu_cache_topology(unsigned int cpu, int level) · 54 unmodified lines | ||
| 664 | 716 | return ret; |
| 665 | 717 | } |
| 666 | 718 | |
| 667 | − | |
| 668 | 719 | /** |
| 669 | 720 | * find_acpi_cpu_topology_package() - Determine a unique CPU package value |
| 670 | 721 | * @cpu: Kernel logical CPU number |
| @@ -202,7 +202,7 @@ config GENERIC_ARCH_TOPOLOGY · 201 unmodified lines | ||
| 202 | 202 | help |
| 203 | 203 | Enable support for architectures common topology code: e.g., parsing |
| 204 | 204 | CPU capacity information from DT, usage of such information for |
| 205 | − appropriate scaling, sysfs interface for changing capacity values at | |
| 205 | + appropriate scaling, sysfs interface for reading capacity values at | |
| 206 | 206 | runtime. |
| 207 | 207 | |
| 208 | 208 | endmenu |
| @@ -15,6 +15,11 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/string.h> |
| 16 | 16 | #include <linux/sched/topology.h> |
| 17 | 17 | #include <linux/cpuset.h> |
| 18 | +#include <linux/cpumask.h> | |
| 19 | +#include <linux/init.h> | |
| 20 | +#include <linux/percpu.h> | |
| 21 | +#include <linux/sched.h> | |
| 22 | +#include <linux/smp.h> | |
| 18 | 23 | |
| 19 | 24 | DEFINE_PER_CPU(unsigned long, freq_scale) = SCHED_CAPACITY_SCALE; |
| 20 | 25 | |
| @@ -241,3 +246,296 @@ static void parsing_done_workfn(struct work_struct *work) · 220 unmodified lines | ||
| 241 | 246 | #else |
| 242 | 247 | core_initcall(free_raw_capacity); |
| 243 | 248 | #endif |
| 249 | + | |
| 250 | +#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV) | |
| 251 | +static int __init get_cpu_for_node(struct device_node *node) | |
| 252 | +{ | |
| 253 | + struct device_node *cpu_node; | |
| 254 | + int cpu; | |
| 255 | + | |
| 256 | + cpu_node = of_parse_phandle(node, "cpu", 0); | |
| 257 | + if (!cpu_node) | |
| 258 | + return -1; | |
| 259 | + | |
| 260 | + cpu = of_cpu_node_to_id(cpu_node); | |
| 261 | + if (cpu >= 0) | |
| 262 | + topology_parse_cpu_capacity(cpu_node, cpu); | |
| 263 | + else | |
| 264 | + pr_crit("Unable to find CPU node for %pOF\n", cpu_node); | |
| 265 | + | |
| 266 | + of_node_put(cpu_node); | |
| 267 | + return cpu; | |
| 268 | +} | |
| 269 | + | |
| 270 | +static int __init parse_core(struct device_node *core, int package_id, | |
| 271 | + int core_id) | |
| 272 | +{ | |
| 273 | + char name[10]; | |
| 274 | + bool leaf = true; | |
| 275 | + int i = 0; | |
| 276 | + int cpu; | |
| 277 | + struct device_node *t; | |
| 278 | + | |
| 279 | + do { | |
| 280 | + snprintf(name, sizeof(name), "thread%d", i); | |
| 281 | + t = of_get_child_by_name(core, name); | |
| 282 | + if (t) { | |
| 283 | + leaf = false; | |
| 284 | + cpu = get_cpu_for_node(t); | |
| 285 | + if (cpu >= 0) { | |
| 286 | + cpu_topology[cpu].package_id = package_id; | |
| 287 | + cpu_topology[cpu].core_id = core_id; | |
| 288 | + cpu_topology[cpu].thread_id = i; | |
| 289 | + } else { | |
| 290 | + pr_err("%pOF: Can't get CPU for thread\n", | |
| 291 | + t); | |
| 292 | + of_node_put(t); | |
| 293 | + return -EINVAL; | |
| 294 | + } | |
| 295 | + of_node_put(t); | |
| 296 | + } | |
| 297 | + i++; | |
| 298 | + } while (t); | |
| 299 | + | |
| 300 | + cpu = get_cpu_for_node(core); | |
| 301 | + if (cpu >= 0) { | |
| 302 | + if (!leaf) { | |
| 303 | + pr_err("%pOF: Core has both threads and CPU\n", | |
| 304 | + core); | |
| 305 | + return -EINVAL; | |
| 306 | + } | |
| 307 | + | |
| 308 | + cpu_topology[cpu].package_id = package_id; | |
| 309 | + cpu_topology[cpu].core_id = core_id; | |
| 310 | + } else if (leaf) { | |
| 311 | + pr_err("%pOF: Can't get CPU for leaf core\n", core); | |
| 312 | + return -EINVAL; | |
| 313 | + } | |
| 314 | + | |
| 315 | + return 0; | |
| 316 | +} | |
| 317 | + | |
| 318 | +static int __init parse_cluster(struct device_node *cluster, int depth) | |
| 319 | +{ | |
| 320 | + char name[10]; | |
| 321 | + bool leaf = true; | |
| 322 | + bool has_cores = false; | |
| 323 | + struct device_node *c; | |
| 324 | + static int package_id __initdata; | |
| 325 | + int core_id = 0; | |
| 326 | + int i, ret; | |
| 327 | + | |
| 328 | + /* | |
| 329 | + * First check for child clusters; we currently ignore any | |
| 330 | + * information about the nesting of clusters and present the | |
| 331 | + * scheduler with a flat list of them. | |
| 332 | + */ | |
| 333 | + i = 0; | |
| 334 | + do { | |
| 335 | + snprintf(name, sizeof(name), "cluster%d", i); | |
| 336 | + c = of_get_child_by_name(cluster, name); | |
| 337 | + if (c) { | |
| 338 | + leaf = false; | |
| 339 | + ret = parse_cluster(c, depth + 1); | |
| 340 | + of_node_put(c); | |
| 341 | + if (ret != 0) | |
| 342 | + return ret; | |
| 343 | + } | |
| 344 | + i++; | |
| 345 | + } while (c); | |
| 346 | + | |
| 347 | + /* Now check for cores */ | |
| 348 | + i = 0; | |
| 349 | + do { | |
| 350 | + snprintf(name, sizeof(name), "core%d", i); | |
| 351 | + c = of_get_child_by_name(cluster, name); | |
| 352 | + if (c) { | |
| 353 | + has_cores = true; | |
| 354 | + | |
| 355 | + if (depth == 0) { | |
| 356 | + pr_err("%pOF: cpu-map children should be clusters\n", | |
| 357 | + c); | |
| 358 | + of_node_put(c); | |
| 359 | + return -EINVAL; | |
| 360 | + } | |
| 361 | + | |
| 362 | + if (leaf) { | |
| 363 | + ret = parse_core(c, package_id, core_id++); | |
| 364 | + } else { | |
| 365 | + pr_err("%pOF: Non-leaf cluster with core %s\n", | |
| 366 | + cluster, name); | |
| 367 | + ret = -EINVAL; | |
| 368 | + } | |
| 369 | + | |
| 370 | + of_node_put(c); | |
| 371 | + if (ret != 0) | |
| 372 | + return ret; | |
| 373 | + } | |
| 374 | + i++; | |
| 375 | + } while (c); | |
| 376 | + | |
| 377 | + if (leaf && !has_cores) | |
| 378 | + pr_warn("%pOF: empty cluster\n", cluster); | |
| 379 | + | |
| 380 | + if (leaf) | |
| 381 | + package_id++; | |
| 382 | + | |
| 383 | + return 0; | |
| 384 | +} | |
| 385 | + | |
| 386 | +static int __init parse_dt_topology(void) | |
| 387 | +{ | |
| 388 | + struct device_node *cn, *map; | |
| 389 | + int ret = 0; | |
| 390 | + int cpu; | |
| 391 | + | |
| 392 | + cn = of_find_node_by_path("/cpus"); | |
| 393 | + if (!cn) { | |
| 394 | + pr_err("No CPU information found in DT\n"); | |
| 395 | + return 0; | |
| 396 | + } | |
| 397 | + | |
| 398 | + /* | |
| 399 | + * When topology is provided cpu-map is essentially a root | |
| 400 | + * cluster with restricted subnodes. | |
| 401 | + */ | |
| 402 | + map = of_get_child_by_name(cn, "cpu-map"); | |
| 403 | + if (!map) | |
| 404 | + goto out; | |
| 405 | + | |
| 406 | + ret = parse_cluster(map, 0); | |
| 407 | + if (ret != 0) | |
| 408 | + goto out_map; | |
| 409 | + | |
| 410 | + topology_normalize_cpu_scale(); | |
| 411 | + | |
| 412 | + /* | |
| 413 | + * Check that all cores are in the topology; the SMP code will | |
| 414 | + * only mark cores described in the DT as possible. | |
| 415 | + */ | |
| 416 | + for_each_possible_cpu(cpu) | |
| 417 | + if (cpu_topology[cpu].package_id == -1) | |
| 418 | + ret = -EINVAL; | |
| 419 | + | |
| 420 | +out_map: | |
| 421 | + of_node_put(map); | |
| 422 | +out: | |
| 423 | + of_node_put(cn); | |
| 424 | + return ret; | |
| 425 | +} | |
| 426 | +#endif | |
| 427 | + | |
| 428 | +/* | |
| 429 | + * cpu topology table | |
| 430 | + */ | |
| 431 | +struct cpu_topology cpu_topology[NR_CPUS]; | |
| 432 | +EXPORT_SYMBOL_GPL(cpu_topology); | |
| 433 | + | |
| 434 | +const struct cpumask *cpu_coregroup_mask(int cpu) | |
| 435 | +{ | |
| 436 | + const cpumask_t *core_mask = cpumask_of_node(cpu_to_node(cpu)); | |
| 437 | + | |
| 438 | + /* Find the smaller of NUMA, core or LLC siblings */ | |
| 439 | + if (cpumask_subset(&cpu_topology[cpu].core_sibling, core_mask)) { | |
| 440 | + /* not numa in package, lets use the package siblings */ | |
| 441 | + core_mask = &cpu_topology[cpu].core_sibling; | |
| 442 | + } | |
| 443 | + if (cpu_topology[cpu].llc_id != -1) { | |
| 444 | + if (cpumask_subset(&cpu_topology[cpu].llc_sibling, core_mask)) | |
| 445 | + core_mask = &cpu_topology[cpu].llc_sibling; | |
| 446 | + } | |
| 447 | + | |
| 448 | + return core_mask; | |
| 449 | +} | |
| 450 | + | |
| 451 | +void update_siblings_masks(unsigned int cpuid) | |
| 452 | +{ | |
| 453 | + struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid]; | |
| 454 | + int cpu; | |
| 455 | + | |
| 456 | + /* update core and thread sibling masks */ | |
| 457 | + for_each_online_cpu(cpu) { | |
| 458 | + cpu_topo = &cpu_topology[cpu]; | |
| 459 | + | |
| 460 | + if (cpuid_topo->llc_id == cpu_topo->llc_id) { | |
| 461 | + cpumask_set_cpu(cpu, &cpuid_topo->llc_sibling); | |
| 462 | + cpumask_set_cpu(cpuid, &cpu_topo->llc_sibling); | |
| 463 | + } | |
| 464 | + | |
| 465 | + if (cpuid_topo->package_id != cpu_topo->package_id) | |
| 466 | + continue; | |
| 467 | + | |
| 468 | + cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); | |
| 469 | + cpumask_set_cpu(cpu, &cpuid_topo->core_sibling); | |
| 470 | + | |
| 471 | + if (cpuid_topo->core_id != cpu_topo->core_id) | |
| 472 | + continue; | |
| 473 | + | |
| 474 | + cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling); | |
| 475 | + cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling); | |
| 476 | + } | |
| 477 | +} | |
| 478 | + | |
| 479 | +static void clear_cpu_topology(int cpu) | |
| 480 | +{ | |
| 481 | + struct cpu_topology *cpu_topo = &cpu_topology[cpu]; | |
| 482 | + | |
| 483 | + cpumask_clear(&cpu_topo->llc_sibling); | |
| 484 | + cpumask_set_cpu(cpu, &cpu_topo->llc_sibling); | |
| 485 | + | |
| 486 | + cpumask_clear(&cpu_topo->core_sibling); | |
| 487 | + cpumask_set_cpu(cpu, &cpu_topo->core_sibling); | |
| 488 | + cpumask_clear(&cpu_topo->thread_sibling); | |
| 489 | + cpumask_set_cpu(cpu, &cpu_topo->thread_sibling); | |
| 490 | +} | |
| 491 | + | |
| 492 | +void __init reset_cpu_topology(void) | |
| 493 | +{ | |
| 494 | + unsigned int cpu; | |
| 495 | + | |
| 496 | + for_each_possible_cpu(cpu) { | |
| 497 | + struct cpu_topology *cpu_topo = &cpu_topology[cpu]; | |
| 498 | + | |
| 499 | + cpu_topo->thread_id = -1; | |
| 500 | + cpu_topo->core_id = -1; | |
| 501 | + cpu_topo->package_id = -1; | |
| 502 | + cpu_topo->llc_id = -1; | |
| 503 | + | |
| 504 | + clear_cpu_topology(cpu); | |
| 505 | + } | |
| 506 | +} | |
| 507 | + | |
| 508 | +void remove_cpu_topology(unsigned int cpu) | |
| 509 | +{ | |
| 510 | + int sibling; | |
| 511 | + | |
| 512 | + for_each_cpu(sibling, topology_core_cpumask(cpu)) | |
| 513 | + cpumask_clear_cpu(cpu, topology_core_cpumask(sibling)); | |
| 514 | + for_each_cpu(sibling, topology_sibling_cpumask(cpu)) | |
| 515 | + cpumask_clear_cpu(cpu, topology_sibling_cpumask(sibling)); | |
| 516 | + for_each_cpu(sibling, topology_llc_cpumask(cpu)) | |
| 517 | + cpumask_clear_cpu(cpu, topology_llc_cpumask(sibling)); | |
| 518 | + | |
| 519 | + clear_cpu_topology(cpu); | |
| 520 | +} | |
| 521 | + | |
| 522 | +__weak int __init parse_acpi_topology(void) | |
| 523 | +{ | |
| 524 | + return 0; | |
| 525 | +} | |
| 526 | + | |
| 527 | +#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV) | |
| 528 | +void __init init_cpu_topology(void) | |
| 529 | +{ | |
| 530 | + reset_cpu_topology(); | |
| 531 | + | |
| 532 | + /* | |
| 533 | + * Discard anything that was parsed if we hit an error so we | |
| 534 | + * don't use partial information. | |
| 535 | + */ | |
| 536 | + if (parse_acpi_topology()) | |
| 537 | + reset_cpu_topology(); | |
| 538 | + else if (of_have_populated_dt() && parse_dt_topology()) | |
| 539 | + reset_cpu_topology(); | |
| 540 | +} | |
| 541 | +#endif | |
| @@ -573,3 +573,12 @@ config RANDOM_TRUST_CPU · 572 unmodified lines | ||
| 573 | 573 | has not installed a hidden back door to compromise the CPU's |
| 574 | 574 | random number generation facilities. This can also be configured |
| 575 | 575 | at boot with "random.trust_cpu=on/off". |
| 576 | + | |
| 577 | +config RANDOM_TRUST_BOOTLOADER | |
| 578 | + bool "Trust the bootloader to initialize Linux's CRNG" | |
| 579 | + help | |
| 580 | + Some bootloaders can provide entropy to increase the kernel's initial | |
| 581 | + device randomness. Say Y here to assume the entropy provided by the | |
| 582 | + booloader is trustworthy so it will be added to the kernel's entropy | |
| 583 | + pool. Otherwise, say N here so it will be regarded as device input that | |
| 584 | + only mixes the entropy pool. | |
| @@ -2445,3 +2445,17 @@ void add_hwgenerator_randomness(const char *buffer, size_t count, · 2444 unmodified lines | ||
| 2445 | 2445 | credit_entropy_bits(poolp, entropy); |
| 2446 | 2446 | } |
| 2447 | 2447 | EXPORT_SYMBOL_GPL(add_hwgenerator_randomness); |
| 2448 | + | |
| 2449 | +/* Handle random seed passed by bootloader. | |
| 2450 | + * If the seed is trustworthy, it would be regarded as hardware RNGs. Otherwise | |
| 2451 | + * it would be regarded as device data. | |
| 2452 | + * The decision is controlled by CONFIG_RANDOM_TRUST_BOOTLOADER. | |
| 2453 | + */ | |
| 2454 | +void add_bootloader_randomness(const void *buf, unsigned int size) | |
| 2455 | +{ | |
| 2456 | + if (IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER)) | |
| 2457 | + add_hwgenerator_randomness(buf, size, size * 8); | |
| 2458 | + else | |
| 2459 | + add_device_randomness(buf, size); | |
| 2460 | +} | |
| 2461 | +EXPORT_SYMBOL_GPL(add_bootloader_randomness); | |
| @@ -13,6 +13,16 @@ config ARM_CPUIDLE · 12 unmodified lines | ||
| 13 | 13 | initialized by calling the CPU operations init idle hook |
| 14 | 14 | provided by architecture code. |
| 15 | 15 | |
| 16 | +config ARM_PSCI_CPUIDLE | |
| 17 | + bool "PSCI CPU idle Driver" | |
| 18 | + depends on ARM_PSCI_FW | |
| 19 | + select DT_IDLE_STATES | |
| 20 | + select CPU_IDLE_MULTIPLE_DRIVERS | |
| 21 | + help | |
| 22 | + Select this to enable PSCI firmware based CPUidle driver for ARM. | |
| 23 | + It provides an idle driver that is capable of detecting and | |
| 24 | + managing idle states through the PSCI firmware interface. | |
| 25 | + | |
| 16 | 26 | config ARM_BIG_LITTLE_CPUIDLE |
| 17 | 27 | bool "Support for ARM big.LITTLE processors" |
| 18 | 28 | depends on ARCH_VEXPRESS_TC2_PM || ARCH_EXYNOS |
| @@ -20,6 +20,7 @@ obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o · 19 unmodified lines | ||
| 20 | 20 | obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o |
| 21 | 21 | obj-$(CONFIG_ARM_EXYNOS_CPUIDLE) += cpuidle-exynos.o |
| 22 | 22 | obj-$(CONFIG_ARM_CPUIDLE) += cpuidle-arm.o |
| 23 | +obj-$(CONFIG_ARM_PSCI_CPUIDLE) += cpuidle-psci.o | |
| 23 | 24 | |
| 24 | 25 | ############################################################################### |
| 25 | 26 | # MIPS drivers |
| @@ -15,7 +15,6 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <linux/module.h> |
| 16 | 16 | #include <linux/of.h> |
| 17 | 17 | #include <linux/slab.h> |
| 18 | −#include <linux/topology.h> | |
| 19 | 18 | |
| 20 | 19 | #include <asm/cpuidle.h> |
| 21 | 20 | |
| @@ -106,11 +105,17 @@ static int __init arm_idle_init_cpu(int cpu) · 84 unmodified lines | ||
| 106 | 105 | ret = arm_cpuidle_init(cpu); |
| 107 | 106 | |
| 108 | 107 | /* |
| 109 | − * Allow the initialization to continue for other CPUs, if the reported | |
| 110 | − * failure is a HW misconfiguration/breakage (-ENXIO). | |
| 108 | + * Allow the initialization to continue for other CPUs, if the | |
| 109 | + * reported failure is a HW misconfiguration/breakage (-ENXIO). | |
| 110 | + * | |
| 111 | + * Some platforms do not support idle operations | |
| 112 | + * (arm_cpuidle_init() returning -EOPNOTSUPP), we should | |
| 113 | + * not flag this case as an error, it is a valid | |
| 114 | + * configuration. | |
| 111 | 115 | */ |
| 112 | 116 | if (ret) { |
| 113 | − pr_err("CPU %d failed to init idle CPU ops\n", cpu); | |
| 117 | + if (ret != -EOPNOTSUPP) | |
| 118 | + pr_err("CPU %d failed to init idle CPU ops\n", cpu); | |
| 114 | 119 | ret = ret == -ENXIO ? 0 : ret; |
| 115 | 120 | goto out_kfree_drv; |
| 116 | 121 | } |
| @@ -0,0 +1,236 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-only | |
| 2 | +/* | |
| 3 | + * PSCI CPU idle driver. | |
| 4 | + * | |
| 5 | + * Copyright (C) 2019 ARM Ltd. | |
| 6 | + * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> | |
| 7 | + */ | |
| 8 | + | |
| 9 | +#define pr_fmt(fmt) "CPUidle PSCI: " fmt | |
| 10 | + | |
| 11 | +#include <linux/cpuidle.h> | |
| 12 | +#include <linux/cpumask.h> | |
| 13 | +#include <linux/cpu_pm.h> | |
| 14 | +#include <linux/kernel.h> | |
| 15 | +#include <linux/module.h> | |
| 16 | +#include <linux/of.h> | |
| 17 | +#include <linux/of_device.h> | |
| 18 | +#include <linux/psci.h> | |
| 19 | +#include <linux/slab.h> | |
| 20 | + | |
| 21 | +#include <asm/cpuidle.h> | |
| 22 | + | |
| 23 | +#include "dt_idle_states.h" | |
| 24 | + | |
| 25 | +static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state); | |
| 26 | + | |
| 27 | +static int psci_enter_idle_state(struct cpuidle_device *dev, | |
| 28 | + struct cpuidle_driver *drv, int idx) | |
| 29 | +{ | |
| 30 | + u32 *state = __this_cpu_read(psci_power_state); | |
| 31 | + | |
| 32 | + return CPU_PM_CPU_IDLE_ENTER_PARAM(psci_cpu_suspend_enter, | |
| 33 | + idx, state[idx - 1]); | |
| 34 | +} | |
| 35 | + | |
| 36 | +static struct cpuidle_driver psci_idle_driver __initdata = { | |
| 37 | + .name = "psci_idle", | |
| 38 | + .owner = THIS_MODULE, | |
| 39 | + /* | |
| 40 | + * PSCI idle states relies on architectural WFI to | |
| 41 | + * be represented as state index 0. | |
| 42 | + */ | |
| 43 | + .states[0] = { | |
| 44 | + .enter = psci_enter_idle_state, | |
| 45 | + .exit_latency = 1, | |
| 46 | + .target_residency = 1, | |
| 47 | + .power_usage = UINT_MAX, | |
| 48 | + .name = "WFI", | |
| 49 | + .desc = "ARM WFI", | |
| 50 | + } | |
| 51 | +}; | |
| 52 | + | |
| 53 | +static const struct of_device_id psci_idle_state_match[] __initconst = { | |
| 54 | + { .compatible = "arm,idle-state", | |
| 55 | + .data = psci_enter_idle_state }, | |
| 56 | + { }, | |
| 57 | +}; | |
| 58 | + | |
| 59 | +static int __init psci_dt_parse_state_node(struct device_node *np, u32 *state) | |
| 60 | +{ | |
| 61 | + int err = of_property_read_u32(np, "arm,psci-suspend-param", state); | |
| 62 | + | |
| 63 | + if (err) { | |
| 64 | + pr_warn("%pOF missing arm,psci-suspend-param property\n", np); | |
| 65 | + return err; | |
| 66 | + } | |
| 67 | + | |
| 68 | + if (!psci_power_state_is_valid(*state)) { | |
| 69 | + pr_warn("Invalid PSCI power state %#x\n", *state); | |
| 70 | + return -EINVAL; | |
| 71 | + } | |
| 72 | + | |
| 73 | + return 0; | |
| 74 | +} | |
| 75 | + | |
| 76 | +static int __init psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu) | |
| 77 | +{ | |
| 78 | + int i, ret = 0, count = 0; | |
| 79 | + u32 *psci_states; | |
| 80 | + struct device_node *state_node; | |
| 81 | + | |
| 82 | + /* Count idle states */ | |
| 83 | + while ((state_node = of_parse_phandle(cpu_node, "cpu-idle-states", | |
| 84 | + count))) { | |
| 85 | + count++; | |
| 86 | + of_node_put(state_node); | |
| 87 | + } | |
| 88 | + | |
| 89 | + if (!count) | |
| 90 | + return -ENODEV; | |
| 91 | + | |
| 92 | + psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL); | |
| 93 | + if (!psci_states) | |
| 94 | + return -ENOMEM; | |
| 95 | + | |
| 96 | + for (i = 0; i < count; i++) { | |
| 97 | + state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i); | |
| 98 | + ret = psci_dt_parse_state_node(state_node, &psci_states[i]); | |
| 99 | + of_node_put(state_node); | |
| 100 | + | |
| 101 | + if (ret) | |
| 102 | + goto free_mem; | |
| 103 | + | |
| 104 | + pr_debug("psci-power-state %#x index %d\n", psci_states[i], i); | |
| 105 | + } | |
| 106 | + | |
| 107 | + /* Idle states parsed correctly, initialize per-cpu pointer */ | |
| 108 | + per_cpu(psci_power_state, cpu) = psci_states; | |
| 109 | + return 0; | |
| 110 | + | |
| 111 | +free_mem: | |
| 112 | + kfree(psci_states); | |
| 113 | + return ret; | |
| 114 | +} | |
| 115 | + | |
| 116 | +static __init int psci_cpu_init_idle(unsigned int cpu) | |
| 117 | +{ | |
| 118 | + struct device_node *cpu_node; | |
| 119 | + int ret; | |
| 120 | + | |
| 121 | + /* | |
| 122 | + * If the PSCI cpu_suspend function hook has not been initialized | |
| 123 | + * idle states must not be enabled, so bail out | |
| 124 | + */ | |
| 125 | + if (!psci_ops.cpu_suspend) | |
| 126 | + return -EOPNOTSUPP; | |
| 127 | + | |
| 128 | + cpu_node = of_cpu_device_node_get(cpu); | |
| 129 | + if (!cpu_node) | |
| 130 | + return -ENODEV; | |
| 131 | + | |
| 132 | + ret = psci_dt_cpu_init_idle(cpu_node, cpu); | |
| 133 | + | |
| 134 | + of_node_put(cpu_node); | |
| 135 | + | |
| 136 | + return ret; | |
| 137 | +} | |
| 138 | + | |
| 139 | +static int __init psci_idle_init_cpu(int cpu) | |
| 140 | +{ | |
| 141 | + struct cpuidle_driver *drv; | |
| 142 | + struct device_node *cpu_node; | |
| 143 | + const char *enable_method; | |
| 144 | + int ret = 0; | |
| 145 | + | |
| 146 | + cpu_node = of_cpu_device_node_get(cpu); | |
| 147 | + if (!cpu_node) | |
| 148 | + return -ENODEV; | |
| 149 | + | |
| 150 | + /* | |
| 151 | + * Check whether the enable-method for the cpu is PSCI, fail | |
| 152 | + * if it is not. | |
| 153 | + */ | |
| 154 | + enable_method = of_get_property(cpu_node, "enable-method", NULL); | |
| 155 | + if (!enable_method || (strcmp(enable_method, "psci"))) | |
| 156 | + ret = -ENODEV; | |
| 157 | + | |
| 158 | + of_node_put(cpu_node); | |
| 159 | + if (ret) | |
| 160 | + return ret; | |
| 161 | + | |
| 162 | + drv = kmemdup(&psci_idle_driver, sizeof(*drv), GFP_KERNEL); | |
| 163 | + if (!drv) | |
| 164 | + return -ENOMEM; | |
| 165 | + | |
| 166 | + drv->cpumask = (struct cpumask *)cpumask_of(cpu); | |
| 167 | + | |
| 168 | + /* | |
| 169 | + * Initialize idle states data, starting at index 1, since | |
| 170 | + * by default idle state 0 is the quiescent state reached | |
| 171 | + * by the cpu by executing the wfi instruction. | |
| 172 | + * | |
| 173 | + * If no DT idle states are detected (ret == 0) let the driver | |
| 174 | + * initialization fail accordingly since there is no reason to | |
| 175 | + * initialize the idle driver if only wfi is supported, the | |
| 176 | + * default archictectural back-end already executes wfi | |
| 177 | + * on idle entry. | |
| 178 | + */ | |
| 179 | + ret = dt_init_idle_driver(drv, psci_idle_state_match, 1); | |
| 180 | + if (ret <= 0) { | |
| 181 | + ret = ret ? : -ENODEV; | |
| 182 | + goto out_kfree_drv; | |
| 183 | + } | |
| 184 | + | |
| 185 | + /* | |
| 186 | + * Initialize PSCI idle states. | |
| 187 | + */ | |
| 188 | + ret = psci_cpu_init_idle(cpu); | |
| 189 | + if (ret) { | |
| 190 | + pr_err("CPU %d failed to PSCI idle\n", cpu); | |
| 191 | + goto out_kfree_drv; | |
| 192 | + } | |
| 193 | + | |
| 194 | + ret = cpuidle_register(drv, NULL); | |
| 195 | + if (ret) | |
| 196 | + goto out_kfree_drv; | |
| 197 | + | |
| 198 | + return 0; | |
| 199 | + | |
| 200 | +out_kfree_drv: | |
| 201 | + kfree(drv); | |
| 202 | + return ret; | |
| 203 | +} | |
| 204 | + | |
| 205 | +/* | |
| 206 | + * psci_idle_init - Initializes PSCI cpuidle driver | |
| 207 | + * | |
| 208 | + * Initializes PSCI cpuidle driver for all CPUs, if any CPU fails | |
| 209 | + * to register cpuidle driver then rollback to cancel all CPUs | |
| 210 | + * registration. | |
| 211 | + */ | |
| 212 | +static int __init psci_idle_init(void) | |
| 213 | +{ | |
| 214 | + int cpu, ret; | |
| 215 | + struct cpuidle_driver *drv; | |
| 216 | + struct cpuidle_device *dev; | |
| 217 | + | |
| 218 | + for_each_possible_cpu(cpu) { | |
| 219 | + ret = psci_idle_init_cpu(cpu); | |
| 220 | + if (ret) | |
| 221 | + goto out_fail; | |
| 222 | + } | |
| 223 | + | |
| 224 | + return 0; | |
| 225 | + | |
| 226 | +out_fail: | |
| 227 | + while (--cpu >= 0) { | |
| 228 | + dev = per_cpu(cpuidle_devices, cpu); | |
| 229 | + drv = cpuidle_get_cpu_driver(dev); | |
| 230 | + cpuidle_unregister(drv); | |
| 231 | + kfree(drv); | |
| 232 | + } | |
| 233 | + | |
| 234 | + return ret; | |
| 235 | +} | |
| 236 | +device_initcall(psci_idle_init); | |
| @@ -103,7 +103,7 @@ static inline bool psci_power_state_loses_context(u32 state) · 102 unmodified lines | ||
| 103 | 103 | return state & mask; |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | −static inline bool psci_power_state_is_valid(u32 state) | |
| 106 | +bool psci_power_state_is_valid(u32 state) | |
| 107 | 107 | { |
| 108 | 108 | const u32 valid_mask = psci_has_ext_power_state() ? |
| 109 | 109 | PSCI_1_0_EXT_POWER_STATE_MASK : |
| @@ -277,175 +277,24 @@ static int __init psci_features(u32 psci_func_id) · 167 unmodified lines | ||
| 277 | 277 | } |
| 278 | 278 | |
| 279 | 279 | #ifdef CONFIG_CPU_IDLE |
| 280 | −static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state); | |
| 281 | − | |
| 282 | −static int psci_dt_parse_state_node(struct device_node *np, u32 *state) | |
| 283 | −{ | |
| 284 | − int err = of_property_read_u32(np, "arm,psci-suspend-param", state); | |
| 285 | − | |
| 286 | − if (err) { | |
| 287 | − pr_warn("%pOF missing arm,psci-suspend-param property\n", np); | |
| 288 | − return err; | |
| 289 | − } | |
| 290 | − | |
| 291 | − if (!psci_power_state_is_valid(*state)) { | |
| 292 | − pr_warn("Invalid PSCI power state %#x\n", *state); | |
| 293 | − return -EINVAL; | |
| 294 | − } | |
| 295 | − | |
| 296 | − return 0; | |
| 297 | −} | |
| 298 | − | |
| 299 | −static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu) | |
| 300 | −{ | |
| 301 | − int i, ret = 0, count = 0; | |
| 302 | − u32 *psci_states; | |
| 303 | − struct device_node *state_node; | |
| 304 | − | |
| 305 | − /* Count idle states */ | |
| 306 | − while ((state_node = of_parse_phandle(cpu_node, "cpu-idle-states", | |
| 307 | − count))) { | |
| 308 | − count++; | |
| 309 | − of_node_put(state_node); | |
| 310 | − } | |
| 311 | − | |
| 312 | − if (!count) | |
| 313 | − return -ENODEV; | |
| 314 | − | |
| 315 | − psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL); | |
| 316 | − if (!psci_states) | |
| 317 | − return -ENOMEM; | |
| 318 | − | |
| 319 | − for (i = 0; i < count; i++) { | |
| 320 | − state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i); | |
| 321 | − ret = psci_dt_parse_state_node(state_node, &psci_states[i]); | |
| 322 | − of_node_put(state_node); | |
| 323 | − | |
| 324 | − if (ret) | |
| 325 | − goto free_mem; | |
| 326 | − | |
| 327 | − pr_debug("psci-power-state %#x index %d\n", psci_states[i], i); | |
| 328 | − } | |
| 329 | − | |
| 330 | − /* Idle states parsed correctly, initialize per-cpu pointer */ | |
| 331 | − per_cpu(psci_power_state, cpu) = psci_states; | |
| 332 | − return 0; | |
| 333 | − | |
| 334 | −free_mem: | |
| 335 | − kfree(psci_states); | |
| 336 | − return ret; | |
| 337 | −} | |
| 338 | − | |
| 339 | −#ifdef CONFIG_ACPI | |
| 340 | −#include <acpi/processor.h> | |
| 341 | − | |
| 342 | −static int __maybe_unused psci_acpi_cpu_init_idle(unsigned int cpu) | |
| 343 | −{ | |
| 344 | − int i, count; | |
| 345 | − u32 *psci_states; | |
| 346 | − struct acpi_lpi_state *lpi; | |
| 347 | − struct acpi_processor *pr = per_cpu(processors, cpu); | |
| 348 | − | |
| 349 | − if (unlikely(!pr || !pr->flags.has_lpi)) | |
| 350 | − return -EINVAL; | |
| 351 | − | |
| 352 | − count = pr->power.count - 1; | |
| 353 | − if (count <= 0) | |
| 354 | − return -ENODEV; | |
| 355 | − | |
| 356 | − psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL); | |
| 357 | − if (!psci_states) | |
| 358 | − return -ENOMEM; | |
| 359 | − | |
| 360 | − for (i = 0; i < count; i++) { | |
| 361 | − u32 state; | |
| 362 | − | |
| 363 | − lpi = &pr->power.lpi_states[i + 1]; | |
| 364 | − /* | |
| 365 | − * Only bits[31:0] represent a PSCI power_state while | |
| 366 | − * bits[63:32] must be 0x0 as per ARM ACPI FFH Specification | |
| 367 | − */ | |
| 368 | − state = lpi->address; | |
| 369 | − if (!psci_power_state_is_valid(state)) { | |
| 370 | − pr_warn("Invalid PSCI power state %#x\n", state); | |
| 371 | − kfree(psci_states); | |
| 372 | − return -EINVAL; | |
| 373 | − } | |
| 374 | − psci_states[i] = state; | |
| 375 | − } | |
| 376 | − /* Idle states parsed correctly, initialize per-cpu pointer */ | |
| 377 | − per_cpu(psci_power_state, cpu) = psci_states; | |
| 378 | − return 0; | |
| 379 | −} | |
| 380 | −#else | |
| 381 | −static int __maybe_unused psci_acpi_cpu_init_idle(unsigned int cpu) | |
| 382 | −{ | |
| 383 | − return -EINVAL; | |
| 384 | −} | |
| 385 | −#endif | |
| 386 | − | |
| 387 | −int psci_cpu_init_idle(unsigned int cpu) | |
| 388 | −{ | |
| 389 | − struct device_node *cpu_node; | |
| 390 | − int ret; | |
| 391 | − | |
| 392 | − /* | |
| 393 | − * If the PSCI cpu_suspend function hook has not been initialized | |
| 394 | − * idle states must not be enabled, so bail out | |
| 395 | − */ | |
| 396 | − if (!psci_ops.cpu_suspend) | |
| 397 | − return -EOPNOTSUPP; | |
| 398 | − | |
| 399 | − if (!acpi_disabled) | |
| 400 | − return psci_acpi_cpu_init_idle(cpu); | |
| 401 | − | |
| 402 | − cpu_node = of_get_cpu_node(cpu, NULL); | |
| 403 | − if (!cpu_node) | |
| 404 | − return -ENODEV; | |
| 405 | − | |
| 406 | − ret = psci_dt_cpu_init_idle(cpu_node, cpu); | |
| 407 | − | |
| 408 | − of_node_put(cpu_node); | |
| 409 | − | |
| 410 | − return ret; | |
| 411 | −} | |
| 412 | − | |
| 413 | −static int psci_suspend_finisher(unsigned long index) | |
| 280 | +static int psci_suspend_finisher(unsigned long state) | |
| 414 | 281 | { |
| 415 | − u32 *state = __this_cpu_read(psci_power_state); | |
| 282 | + u32 power_state = state; | |
| 416 | 283 | |
| 417 | − return psci_ops.cpu_suspend(state[index - 1], | |
| 418 | − __pa_symbol(cpu_resume)); | |
| 284 | + return psci_ops.cpu_suspend(power_state, __pa_symbol(cpu_resume)); | |
| 419 | 285 | } |
| 420 | 286 | |
| 421 | −int psci_cpu_suspend_enter(unsigned long index) | |
| 287 | +int psci_cpu_suspend_enter(u32 state) | |
| 422 | 288 | { |
| 423 | 289 | int ret; |
| 424 | − u32 *state = __this_cpu_read(psci_power_state); | |
| 425 | − /* | |
| 426 | − * idle state index 0 corresponds to wfi, should never be called | |
| 427 | − * from the cpu_suspend operations | |
| 428 | − */ | |
| 429 | − if (WARN_ON_ONCE(!index)) | |
| 430 | − return -EINVAL; | |
| 431 | 290 | |
| 432 | − if (!psci_power_state_loses_context(state[index - 1])) | |
| 433 | − ret = psci_ops.cpu_suspend(state[index - 1], 0); | |
| 291 | + if (!psci_power_state_loses_context(state)) | |
| 292 | + ret = psci_ops.cpu_suspend(state, 0); | |
| 434 | 293 | else |
| 435 | − ret = cpu_suspend(index, psci_suspend_finisher); | |
| 294 | + ret = cpu_suspend(state, psci_suspend_finisher); | |
| 436 | 295 | |
| 437 | 296 | return ret; |
| 438 | 297 | } |
| 439 | − | |
| 440 | −/* ARM specific CPU idle operations */ | |
| 441 | −#ifdef CONFIG_ARM | |
| 442 | −static const struct cpuidle_ops psci_cpuidle_ops __initconst = { | |
| 443 | − .suspend = psci_cpu_suspend_enter, | |
| 444 | − .init = psci_dt_cpu_init_idle, | |
| 445 | −}; | |
| 446 | − | |
| 447 | −CPUIDLE_METHOD_OF_DECLARE(psci, "psci", &psci_cpuidle_ops); | |
| 448 | −#endif | |
| 449 | 298 | #endif |
| 450 | 299 | |
| 451 | 300 | static int psci_system_suspend(unsigned long unused) |
| @@ -228,8 +228,11 @@ out_free_cpus: · 227 unmodified lines | ||
| 228 | 228 | |
| 229 | 229 | static void dummy_callback(struct timer_list *unused) {} |
| 230 | 230 | |
| 231 | −static int suspend_cpu(int index, bool broadcast) | |
| 231 | +static int suspend_cpu(struct cpuidle_device *dev, | |
| 232 | + struct cpuidle_driver *drv, int index) | |
| 232 | 233 | { |
| 234 | + struct cpuidle_state *state = &drv->states[index]; | |
| 235 | + bool broadcast = state->flags & CPUIDLE_FLAG_TIMER_STOP; | |
| 233 | 236 | int ret; |
| 234 | 237 | |
| 235 | 238 | arch_cpu_idle_enter(); |
| @@ -254,11 +257,7 @@ static int suspend_cpu(int index, bool broadcast) · 18 unmodified lines | ||
| 254 | 257 | } |
| 255 | 258 | } |
| 256 | 259 | |
| 257 | − /* | |
| 258 | − * Replicate the common ARM cpuidle enter function | |
| 259 | − * (arm_enter_idle_state). | |
| 260 | − */ | |
| 261 | − ret = CPU_PM_CPU_IDLE_ENTER(arm_cpuidle_suspend, index); | |
| 260 | + ret = state->enter(dev, drv, index); | |
| 262 | 261 | |
| 263 | 262 | if (broadcast) |
| 264 | 263 | tick_broadcast_exit(); |
| @@ -301,9 +300,8 @@ static int suspend_test_thread(void *arg) · 36 unmodified lines | ||
| 301 | 300 | * doesn't use PSCI). |
| 302 | 301 | */ |
| 303 | 302 | for (index = 1; index < drv->state_count; ++index) { |
| 304 | − struct cpuidle_state *state = &drv->states[index]; | |
| 305 | − bool broadcast = state->flags & CPUIDLE_FLAG_TIMER_STOP; | |
| 306 | 303 | int ret; |
| 304 | + struct cpuidle_state *state = &drv->states[index]; | |
| 307 | 305 | |
| 308 | 306 | /* |
| 309 | 307 | * Set the timer to wake this CPU up in some time (which |
| @@ -318,7 +316,7 @@ static int suspend_test_thread(void *arg) · 8 unmodified lines | ||
| 318 | 316 | /* IRQs must be disabled during suspend operations. */ |
| 319 | 317 | local_irq_disable(); |
| 320 | 318 | |
| 321 | − ret = suspend_cpu(index, broadcast); | |
| 319 | + ret = suspend_cpu(dev, drv, index); | |
| 322 | 320 | |
| 323 | 321 | /* |
| 324 | 322 | * We have woken up. Re-enable IRQs to handle any |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | #include <linux/debugfs.h> |
| 25 | 25 | #include <linux/serial_core.h> |
| 26 | 26 | #include <linux/sysfs.h> |
| 27 | +#include <linux/random.h> | |
| 27 | 28 | |
| 28 | 29 | #include <asm/setup.h> /* for COMMAND_LINE_SIZE */ |
| 29 | 30 | #include <asm/page.h> |
| @@ -1044,6 +1045,7 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, · 1014 unmodified lines | ||
| 1044 | 1045 | { |
| 1045 | 1046 | int l; |
| 1046 | 1047 | const char *p; |
| 1048 | + const void *rng_seed; | |
| 1047 | 1049 | |
| 1048 | 1050 | pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); |
| 1049 | 1051 | |
| @@ -1078,6 +1080,18 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, · 28 unmodified lines | ||
| 1078 | 1080 | |
| 1079 | 1081 | pr_debug("Command line is: %s\n", (char*)data); |
| 1080 | 1082 | |
| 1083 | + rng_seed = of_get_flat_dt_prop(node, "rng-seed", &l); | |
| 1084 | + if (rng_seed && l > 0) { | |
| 1085 | + add_bootloader_randomness(rng_seed, l); | |
| 1086 | + | |
| 1087 | + /* try to clear seed so it won't be found. */ | |
| 1088 | + fdt_nop_property(initial_boot_params, node, "rng-seed"); | |
| 1089 | + | |
| 1090 | + /* update CRC check value */ | |
| 1091 | + of_fdt_crc32 = crc32_be(~0, initial_boot_params, | |
| 1092 | + fdt_totalsize(initial_boot_params)); | |
| 1093 | + } | |
| 1094 | + | |
| 1081 | 1095 | /* break now */ |
| 1082 | 1096 | return 1; |
| 1083 | 1097 | } |
| @@ -113,8 +113,6 @@ struct smmu_pmu { · 112 unmodified lines | ||
| 113 | 113 | u64 counter_mask; |
| 114 | 114 | u32 options; |
| 115 | 115 | bool global_filter; |
| 116 | − u32 global_filter_span; | |
| 117 | − u32 global_filter_sid; | |
| 118 | 116 | }; |
| 119 | 117 | |
| 120 | 118 | #define to_smmu_pmu(p) (container_of(p, struct smmu_pmu, pmu)) |
| @@ -260,6 +258,19 @@ static void smmu_pmu_set_event_filter(struct perf_event *event, · 139 unmodified lines | ||
| 260 | 258 | smmu_pmu_set_smr(smmu_pmu, idx, sid); |
| 261 | 259 | } |
| 262 | 260 | |
| 261 | +static bool smmu_pmu_check_global_filter(struct perf_event *curr, | |
| 262 | + struct perf_event *new) | |
| 263 | +{ | |
| 264 | + if (get_filter_enable(new) != get_filter_enable(curr)) | |
| 265 | + return false; | |
| 266 | + | |
| 267 | + if (!get_filter_enable(new)) | |
| 268 | + return true; | |
| 269 | + | |
| 270 | + return get_filter_span(new) == get_filter_span(curr) && | |
| 271 | + get_filter_stream_id(new) == get_filter_stream_id(curr); | |
| 272 | +} | |
| 273 | + | |
| 263 | 274 | static int smmu_pmu_apply_event_filter(struct smmu_pmu *smmu_pmu, |
| 264 | 275 | struct perf_event *event, int idx) |
| 265 | 276 | { |
| @@ -279,17 +290,14 @@ static int smmu_pmu_apply_event_filter(struct smmu_pmu *smmu_pmu, · 13 unmodified lines | ||
| 279 | 290 | } |
| 280 | 291 | |
| 281 | 292 | /* Requested settings same as current global settings*/ |
| 282 | − if (span == smmu_pmu->global_filter_span && | |
| 283 | − sid == smmu_pmu->global_filter_sid) | |
| 293 | + idx = find_first_bit(smmu_pmu->used_counters, num_ctrs); | |
| 294 | + if (idx == num_ctrs || | |
| 295 | + smmu_pmu_check_global_filter(smmu_pmu->events[idx], event)) { | |
| 296 | + smmu_pmu_set_event_filter(event, 0, span, sid); | |
| 284 | 297 | return 0; |
| 298 | + } | |
| 285 | 299 | |
| 286 | − if (!bitmap_empty(smmu_pmu->used_counters, num_ctrs)) | |
| 287 | − return -EAGAIN; | |
| 288 | − | |
| 289 | − smmu_pmu_set_event_filter(event, 0, span, sid); | |
| 290 | − smmu_pmu->global_filter_span = span; | |
| 291 | − smmu_pmu->global_filter_sid = sid; | |
| 292 | − return 0; | |
| 300 | + return -EAGAIN; | |
| 293 | 301 | } |
| 294 | 302 | |
| 295 | 303 | static int smmu_pmu_get_event_idx(struct smmu_pmu *smmu_pmu, |
| @@ -312,6 +320,19 @@ static int smmu_pmu_get_event_idx(struct smmu_pmu *smmu_pmu, · 16 unmodified lines | ||
| 312 | 320 | return idx; |
| 313 | 321 | } |
| 314 | 322 | |
| 323 | +static bool smmu_pmu_events_compatible(struct perf_event *curr, | |
| 324 | + struct perf_event *new) | |
| 325 | +{ | |
| 326 | + if (new->pmu != curr->pmu) | |
| 327 | + return false; | |
| 328 | + | |
| 329 | + if (to_smmu_pmu(new->pmu)->global_filter && | |
| 330 | + !smmu_pmu_check_global_filter(curr, new)) | |
| 331 | + return false; | |
| 332 | + | |
| 333 | + return true; | |
| 334 | +} | |
| 335 | + | |
| 315 | 336 | /* |
| 316 | 337 | * Implementation of abstract pmu functionality required by |
| 317 | 338 | * the core perf events code. |
| @@ -323,6 +344,7 @@ static int smmu_pmu_event_init(struct perf_event *event) · 5 unmodified lines | ||
| 323 | 344 | struct smmu_pmu *smmu_pmu = to_smmu_pmu(event->pmu); |
| 324 | 345 | struct device *dev = smmu_pmu->dev; |
| 325 | 346 | struct perf_event *sibling; |
| 347 | + int group_num_events = 1; | |
| 326 | 348 | u16 event_id; |
| 327 | 349 | |
| 328 | 350 | if (event->attr.type != event->pmu->type) |
| @@ -347,18 +369,23 @@ static int smmu_pmu_event_init(struct perf_event *event) · 18 unmodified lines | ||
| 347 | 369 | } |
| 348 | 370 | |
| 349 | 371 | /* Don't allow groups with mixed PMUs, except for s/w events */ |
| 350 | − if (event->group_leader->pmu != event->pmu && | |
| 351 | − !is_software_event(event->group_leader)) { | |
| 352 | − dev_dbg(dev, "Can't create mixed PMU group\n"); | |
| 353 | − return -EINVAL; | |
| 372 | + if (!is_software_event(event->group_leader)) { | |
| 373 | + if (!smmu_pmu_events_compatible(event->group_leader, event)) | |
| 374 | + return -EINVAL; | |
| 375 | + | |
| 376 | + if (++group_num_events > smmu_pmu->num_counters) | |
| 377 | + return -EINVAL; | |
| 354 | 378 | } |
| 355 | 379 | |
| 356 | 380 | for_each_sibling_event(sibling, event->group_leader) { |
| 357 | − if (sibling->pmu != event->pmu && | |
| 358 | − !is_software_event(sibling)) { | |
| 359 | − dev_dbg(dev, "Can't create mixed PMU group\n"); | |
| 381 | + if (is_software_event(sibling)) | |
| 382 | + continue; | |
| 383 | + | |
| 384 | + if (!smmu_pmu_events_compatible(sibling, event)) | |
| 385 | + return -EINVAL; | |
| 386 | + | |
| 387 | + if (++group_num_events > smmu_pmu->num_counters) | |
| 360 | 388 | return -EINVAL; |
| 361 | − } | |
| 362 | 389 | } |
| 363 | 390 | |
| 364 | 391 | hwc->idx = -1; |
| @@ -35,6 +35,8 @@ · 34 unmodified lines | ||
| 35 | 35 | #define EVENT_CYCLES_COUNTER 0 |
| 36 | 36 | #define NUM_COUNTERS 4 |
| 37 | 37 | |
| 38 | +#define AXI_MASKING_REVERT 0xffff0000 /* AXI_MASKING(MSB 16bits) + AXI_ID(LSB 16bits) */ | |
| 39 | + | |
| 38 | 40 | #define to_ddr_pmu(p) container_of(p, struct ddr_pmu, pmu) |
| 39 | 41 | |
| 40 | 42 | #define DDR_PERF_DEV_NAME "imx8_ddr" |
| @@ -42,11 +44,25 @@ · 1 unmodified line | ||
| 42 | 44 | |
| 43 | 45 | static DEFINE_IDA(ddr_ida); |
| 44 | 46 | |
| 47 | +/* DDR Perf hardware feature */ | |
| 48 | +#define DDR_CAP_AXI_ID_FILTER 0x1 /* support AXI ID filter */ | |
| 49 | + | |
| 50 | +struct fsl_ddr_devtype_data { | |
| 51 | + unsigned int quirks; /* quirks needed for different DDR Perf core */ | |
| 52 | +}; | |
| 53 | + | |
| 54 | +static const struct fsl_ddr_devtype_data imx8_devtype_data; | |
| 55 | + | |
| 56 | +static const struct fsl_ddr_devtype_data imx8m_devtype_data = { | |
| 57 | + .quirks = DDR_CAP_AXI_ID_FILTER, | |
| 58 | +}; | |
| 59 | + | |
| 45 | 60 | static const struct of_device_id imx_ddr_pmu_dt_ids[] = { |
| 46 | − { .compatible = "fsl,imx8-ddr-pmu",}, | |
| 47 | − { .compatible = "fsl,imx8m-ddr-pmu",}, | |
| 61 | + { .compatible = "fsl,imx8-ddr-pmu", .data = &imx8_devtype_data}, | |
| 62 | + { .compatible = "fsl,imx8m-ddr-pmu", .data = &imx8m_devtype_data}, | |
| 48 | 63 | { /* sentinel */ } |
| 49 | 64 | }; |
| 65 | +MODULE_DEVICE_TABLE(of, imx_ddr_pmu_dt_ids); | |
| 50 | 66 | |
| 51 | 67 | struct ddr_pmu { |
| 52 | 68 | struct pmu pmu; |
| @@ -57,6 +73,7 @@ struct ddr_pmu { · 4 unmodified lines | ||
| 57 | 73 | struct perf_event *events[NUM_COUNTERS]; |
| 58 | 74 | int active_events; |
| 59 | 75 | enum cpuhp_state cpuhp_state; |
| 76 | + const struct fsl_ddr_devtype_data *devtype_data; | |
| 60 | 77 | int irq; |
| 61 | 78 | int id; |
| 62 | 79 | }; |
| @@ -128,6 +145,8 @@ static struct attribute *ddr_perf_events_attrs[] = { · 65 unmodified lines | ||
| 128 | 145 | IMX8_DDR_PMU_EVENT_ATTR(refresh, 0x37), |
| 129 | 146 | IMX8_DDR_PMU_EVENT_ATTR(write, 0x38), |
| 130 | 147 | IMX8_DDR_PMU_EVENT_ATTR(raw-hazard, 0x39), |
| 148 | + IMX8_DDR_PMU_EVENT_ATTR(axid-read, 0x41), | |
| 149 | + IMX8_DDR_PMU_EVENT_ATTR(axid-write, 0x42), | |
| 131 | 150 | NULL, |
| 132 | 151 | }; |
| 133 | 152 | |
| @@ -137,9 +156,13 @@ static struct attribute_group ddr_perf_events_attr_group = { · 3 unmodified lines | ||
| 137 | 156 | }; |
| 138 | 157 | |
| 139 | 158 | PMU_FORMAT_ATTR(event, "config:0-7"); |
| 159 | +PMU_FORMAT_ATTR(axi_id, "config1:0-15"); | |
| 160 | +PMU_FORMAT_ATTR(axi_mask, "config1:16-31"); | |
| 140 | 161 | |
| 141 | 162 | static struct attribute *ddr_perf_format_attrs[] = { |
| 142 | 163 | &format_attr_event.attr, |
| 164 | + &format_attr_axi_id.attr, | |
| 165 | + &format_attr_axi_mask.attr, | |
| 143 | 166 | NULL, |
| 144 | 167 | }; |
| 145 | 168 | |
| @@ -189,6 +212,26 @@ static u32 ddr_perf_read_counter(struct ddr_pmu *pmu, int counter) · 43 unmodified lines | ||
| 189 | 212 | return readl_relaxed(pmu->base + COUNTER_READ + counter * 4); |
| 190 | 213 | } |
| 191 | 214 | |
| 215 | +static bool ddr_perf_is_filtered(struct perf_event *event) | |
| 216 | +{ | |
| 217 | + return event->attr.config == 0x41 || event->attr.config == 0x42; | |
| 218 | +} | |
| 219 | + | |
| 220 | +static u32 ddr_perf_filter_val(struct perf_event *event) | |
| 221 | +{ | |
| 222 | + return event->attr.config1; | |
| 223 | +} | |
| 224 | + | |
| 225 | +static bool ddr_perf_filters_compatible(struct perf_event *a, | |
| 226 | + struct perf_event *b) | |
| 227 | +{ | |
| 228 | + if (!ddr_perf_is_filtered(a)) | |
| 229 | + return true; | |
| 230 | + if (!ddr_perf_is_filtered(b)) | |
| 231 | + return true; | |
| 232 | + return ddr_perf_filter_val(a) == ddr_perf_filter_val(b); | |
| 233 | +} | |
| 234 | + | |
| 192 | 235 | static int ddr_perf_event_init(struct perf_event *event) |
| 193 | 236 | { |
| 194 | 237 | struct ddr_pmu *pmu = to_ddr_pmu(event->pmu); |
| @@ -215,6 +258,15 @@ static int ddr_perf_event_init(struct perf_event *event) · 20 unmodified lines | ||
| 215 | 258 | !is_software_event(event->group_leader)) |
| 216 | 259 | return -EINVAL; |
| 217 | 260 | |
| 261 | + if (pmu->devtype_data->quirks & DDR_CAP_AXI_ID_FILTER) { | |
| 262 | + if (!ddr_perf_filters_compatible(event, event->group_leader)) | |
| 263 | + return -EINVAL; | |
| 264 | + for_each_sibling_event(sibling, event->group_leader) { | |
| 265 | + if (!ddr_perf_filters_compatible(event, sibling)) | |
| 266 | + return -EINVAL; | |
| 267 | + } | |
| 268 | + } | |
| 269 | + | |
| 218 | 270 | for_each_sibling_event(sibling, event->group_leader) { |
| 219 | 271 | if (sibling->pmu != event->pmu && |
| 220 | 272 | !is_software_event(sibling)) |
| @@ -287,6 +339,23 @@ static int ddr_perf_event_add(struct perf_event *event, int flags) · 66 unmodified lines | ||
| 287 | 339 | struct hw_perf_event *hwc = &event->hw; |
| 288 | 340 | int counter; |
| 289 | 341 | int cfg = event->attr.config; |
| 342 | + int cfg1 = event->attr.config1; | |
| 343 | + | |
| 344 | + if (pmu->devtype_data->quirks & DDR_CAP_AXI_ID_FILTER) { | |
| 345 | + int i; | |
| 346 | + | |
| 347 | + for (i = 1; i < NUM_COUNTERS; i++) { | |
| 348 | + if (pmu->events[i] && | |
| 349 | + !ddr_perf_filters_compatible(event, pmu->events[i])) | |
| 350 | + return -EINVAL; | |
| 351 | + } | |
| 352 | + | |
| 353 | + if (ddr_perf_is_filtered(event)) { | |
| 354 | + /* revert axi id masking(axi_mask) value */ | |
| 355 | + cfg1 ^= AXI_MASKING_REVERT; | |
| 356 | + writel(cfg1, pmu->base + COUNTER_DPCR1); | |
| 357 | + } | |
| 358 | + } | |
| 290 | 359 | |
| 291 | 360 | counter = ddr_perf_alloc_counter(pmu, cfg); |
| 292 | 361 | if (counter < 0) { |
| @@ -472,6 +541,8 @@ static int ddr_perf_probe(struct platform_device *pdev) · 179 unmodified lines | ||
| 472 | 541 | if (!name) |
| 473 | 542 | return -ENOMEM; |
| 474 | 543 | |
| 544 | + pmu->devtype_data = of_device_get_match_data(&pdev->dev); | |
| 545 | + | |
| 475 | 546 | pmu->cpu = raw_smp_processor_id(); |
| 476 | 547 | ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, |
| 477 | 548 | DDR_CPUHP_CB_NAME, |
| @@ -217,10 +217,8 @@ static int hisi_ddrc_pmu_init_irq(struct hisi_pmu *ddrc_pmu, · 216 unmodified lines | ||
| 217 | 217 | |
| 218 | 218 | /* Read and init IRQ */ |
| 219 | 219 | irq = platform_get_irq(pdev, 0); |
| 220 | − if (irq < 0) { | |
| 221 | − dev_err(&pdev->dev, "DDRC PMU get irq fail; irq:%d\n", irq); | |
| 220 | + if (irq < 0) | |
| 222 | 221 | return irq; |
| 223 | − } | |
| 224 | 222 | |
| 225 | 223 | ret = devm_request_irq(&pdev->dev, irq, hisi_ddrc_pmu_isr, |
| 226 | 224 | IRQF_NOBALANCING | IRQF_NO_THREAD, |
| @@ -207,10 +207,8 @@ static int hisi_hha_pmu_init_irq(struct hisi_pmu *hha_pmu, · 206 unmodified lines | ||
| 207 | 207 | |
| 208 | 208 | /* Read and init IRQ */ |
| 209 | 209 | irq = platform_get_irq(pdev, 0); |
| 210 | − if (irq < 0) { | |
| 211 | − dev_err(&pdev->dev, "HHA PMU get irq fail; irq:%d\n", irq); | |
| 210 | + if (irq < 0) | |
| 212 | 211 | return irq; |
| 213 | − } | |
| 214 | 212 | |
| 215 | 213 | ret = devm_request_irq(&pdev->dev, irq, hisi_hha_pmu_isr, |
| 216 | 214 | IRQF_NOBALANCING | IRQF_NO_THREAD, |
| @@ -206,10 +206,8 @@ static int hisi_l3c_pmu_init_irq(struct hisi_pmu *l3c_pmu, · 205 unmodified lines | ||
| 206 | 206 | |
| 207 | 207 | /* Read and init IRQ */ |
| 208 | 208 | irq = platform_get_irq(pdev, 0); |
| 209 | − if (irq < 0) { | |
| 210 | − dev_err(&pdev->dev, "L3C PMU get irq fail; irq:%d\n", irq); | |
| 209 | + if (irq < 0) | |
| 211 | 210 | return irq; |
| 212 | − } | |
| 213 | 211 | |
| 214 | 212 | ret = devm_request_irq(&pdev->dev, irq, hisi_l3c_pmu_isr, |
| 215 | 213 | IRQF_NOBALANCING | IRQF_NO_THREAD, |
| @@ -909,12 +909,8 @@ static int l2_cache_pmu_probe_cluster(struct device *dev, void *data) · 908 unmodified lines | ||
| 909 | 909 | cluster->cluster_id = fw_cluster_id; |
| 910 | 910 | |
| 911 | 911 | irq = platform_get_irq(sdev, 0); |
| 912 | − if (irq < 0) { | |
| 913 | − dev_err(&pdev->dev, | |
| 914 | − "Failed to get valid irq for cluster %ld\n", | |
| 915 | − fw_cluster_id); | |
| 912 | + if (irq < 0) | |
| 916 | 913 | return irq; |
| 917 | − } | |
| 918 | 914 | irq_set_status_flags(irq, IRQ_NOAUTOEN); |
| 919 | 915 | cluster->irq = irq; |
| 920 | 916 | |
| @@ -1901,10 +1901,8 @@ static int xgene_pmu_probe(struct platform_device *pdev) · 1900 unmodified lines | ||
| 1901 | 1901 | } |
| 1902 | 1902 | |
| 1903 | 1903 | irq = platform_get_irq(pdev, 0); |
| 1904 | − if (irq < 0) { | |
| 1905 | − dev_err(&pdev->dev, "No IRQ resource\n"); | |
| 1904 | + if (irq < 0) | |
| 1906 | 1905 | return -EINVAL; |
| 1907 | − } | |
| 1908 | 1906 | |
| 1909 | 1907 | rc = devm_request_irq(&pdev->dev, irq, xgene_pmu_isr, |
| 1910 | 1908 | IRQF_NOBALANCING | IRQF_NO_THREAD, |
| @@ -16,6 +16,8 @@ struct error_injection_entry { · 15 unmodified lines | ||
| 16 | 16 | int etype; |
| 17 | 17 | }; |
| 18 | 18 | |
| 19 | +struct pt_regs; | |
| 20 | + | |
| 19 | 21 | #ifdef CONFIG_FUNCTION_ERROR_INJECTION |
| 20 | 22 | /* |
| 21 | 23 | * Whitelist ganerating macro. Specify functions which can be |
| @@ -28,8 +30,12 @@ static struct error_injection_entry __used \ · 6 unmodified lines | ||
| 28 | 30 | .addr = (unsigned long)fname, \ |
| 29 | 31 | .etype = EI_ETYPE_##_etype, \ |
| 30 | 32 | }; |
| 33 | + | |
| 34 | +void override_function_with_return(struct pt_regs *regs); | |
| 31 | 35 | #else |
| 32 | 36 | #define ALLOW_ERROR_INJECTION(fname, _etype) |
| 37 | + | |
| 38 | +static inline void override_function_with_return(struct pt_regs *regs) { } | |
| 33 | 39 | #endif |
| 34 | 40 | #endif |
| 35 | 41 | |
| @@ -1302,11 +1302,16 @@ static inline int lpit_read_residency_count_address(u64 *address) · 1301 unmodified lines | ||
| 1302 | 1302 | #endif |
| 1303 | 1303 | |
| 1304 | 1304 | #ifdef CONFIG_ACPI_PPTT |
| 1305 | +int acpi_pptt_cpu_is_thread(unsigned int cpu); | |
| 1305 | 1306 | int find_acpi_cpu_topology(unsigned int cpu, int level); |
| 1306 | 1307 | int find_acpi_cpu_topology_package(unsigned int cpu); |
| 1307 | 1308 | int find_acpi_cpu_topology_hetero_id(unsigned int cpu); |
| 1308 | 1309 | int find_acpi_cpu_cache_topology(unsigned int cpu, int level); |
| 1309 | 1310 | #else |
| 1311 | +static inline int acpi_pptt_cpu_is_thread(unsigned int cpu) | |
| 1312 | +{ | |
| 1313 | + return -EINVAL; | |
| 1314 | +} | |
| 1310 | 1315 | static inline int find_acpi_cpu_topology(unsigned int cpu, int level) |
| 1311 | 1316 | { |
| 1312 | 1317 | return -EINVAL; |
| @@ -33,4 +33,30 @@ unsigned long topology_get_freq_scale(int cpu) · 32 unmodified lines | ||
| 33 | 33 | return per_cpu(freq_scale, cpu); |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | +struct cpu_topology { | |
| 37 | + int thread_id; | |
| 38 | + int core_id; | |
| 39 | + int package_id; | |
| 40 | + int llc_id; | |
| 41 | + cpumask_t thread_sibling; | |
| 42 | + cpumask_t core_sibling; | |
| 43 | + cpumask_t llc_sibling; | |
| 44 | +}; | |
| 45 | + | |
| 46 | +#ifdef CONFIG_GENERIC_ARCH_TOPOLOGY | |
| 47 | +extern struct cpu_topology cpu_topology[NR_CPUS]; | |
| 48 | + | |
| 49 | +#define topology_physical_package_id(cpu) (cpu_topology[cpu].package_id) | |
| 50 | +#define topology_core_id(cpu) (cpu_topology[cpu].core_id) | |
| 51 | +#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) | |
| 52 | +#define topology_sibling_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) | |
| 53 | +#define topology_llc_cpumask(cpu) (&cpu_topology[cpu].llc_sibling) | |
| 54 | +void init_cpu_topology(void); | |
| 55 | +void store_cpu_topology(unsigned int cpuid); | |
| 56 | +const struct cpumask *cpu_coregroup_mask(int cpu); | |
| 57 | +void update_siblings_masks(unsigned int cpu); | |
| 58 | +void remove_cpu_topology(unsigned int cpuid); | |
| 59 | +void reset_cpu_topology(void); | |
| 60 | +#endif | |
| 61 | + | |
| 36 | 62 | #endif /* _LINUX_ARCH_TOPOLOGY_H_ */ |
| @@ -256,7 +256,10 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov) · 255 unmodified lines | ||
| 256 | 256 | {return 0;} |
| 257 | 257 | #endif |
| 258 | 258 | |
| 259 | −#define __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, is_retention) \ | |
| 259 | +#define __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, \ | |
| 260 | + idx, \ | |
| 261 | + state, \ | |
| 262 | + is_retention) \ | |
| 260 | 263 | ({ \ |
| 261 | 264 | int __ret = 0; \ |
| 262 | 265 | \ |
| @@ -268,7 +271,7 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov) · 5 unmodified lines | ||
| 268 | 271 | if (!is_retention) \ |
| 269 | 272 | __ret = cpu_pm_enter(); \ |
| 270 | 273 | if (!__ret) { \ |
| 271 | − __ret = low_level_idle_enter(idx); \ | |
| 274 | + __ret = low_level_idle_enter(state); \ | |
| 272 | 275 | if (!is_retention) \ |
| 273 | 276 | cpu_pm_exit(); \ |
| 274 | 277 | } \ |
| @@ -277,9 +280,15 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov) · 2 unmodified lines | ||
| 277 | 280 | }) |
| 278 | 281 | |
| 279 | 282 | #define CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx) \ |
| 280 | − __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, 0) | |
| 283 | + __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, idx, 0) | |
| 281 | 284 | |
| 282 | 285 | #define CPU_PM_CPU_IDLE_ENTER_RETENTION(low_level_idle_enter, idx) \ |
| 283 | − __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, 1) | |
| 286 | + __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, idx, 1) | |
| 287 | + | |
| 288 | +#define CPU_PM_CPU_IDLE_ENTER_PARAM(low_level_idle_enter, idx, state) \ | |
| 289 | + __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, state, 0) | |
| 290 | + | |
| 291 | +#define CPU_PM_CPU_IDLE_ENTER_RETENTION_PARAM(low_level_idle_enter, idx, state) \ | |
| 292 | + __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, state, 1) | |
| 284 | 293 | |
| 285 | 294 | #endif /* _LINUX_CPUIDLE_H */ |
| @@ -2,16 +2,16 @@ · 1 unmodified line | ||
| 2 | 2 | #ifndef _LINUX_ERROR_INJECTION_H |
| 3 | 3 | #define _LINUX_ERROR_INJECTION_H |
| 4 | 4 | |
| 5 | −#ifdef CONFIG_FUNCTION_ERROR_INJECTION | |
| 5 | +#include <linux/compiler.h> | |
| 6 | +#include <asm-generic/error-injection.h> | |
| 6 | 7 | |
| 7 | −#include <asm/error-injection.h> | |
| 8 | +#ifdef CONFIG_FUNCTION_ERROR_INJECTION | |
| 8 | 9 | |
| 9 | 10 | extern bool within_error_injection_list(unsigned long addr); |
| 10 | 11 | extern int get_injectable_error_type(unsigned long addr); |
| 11 | 12 | |
| 12 | 13 | #else /* !CONFIG_FUNCTION_ERROR_INJECTION */ |
| 13 | 14 | |
| 14 | −#include <asm-generic/error-injection.h> | |
| 15 | 15 | static inline bool within_error_injection_list(unsigned long addr) |
| 16 | 16 | { |
| 17 | 17 | return false; |
| @@ -15,8 +15,8 @@ · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | bool psci_tos_resident_on(int cpu); |
| 17 | 17 | |
| 18 | −int psci_cpu_init_idle(unsigned int cpu); | |
| 19 | −int psci_cpu_suspend_enter(unsigned long index); | |
| 18 | +int psci_cpu_suspend_enter(u32 state); | |
| 19 | +bool psci_power_state_is_valid(u32 state); | |
| 20 | 20 | |
| 21 | 21 | enum psci_conduit { |
| 22 | 22 | PSCI_CONDUIT_NONE, |
| @@ -19,6 +19,7 @@ struct random_ready_callback { · 18 unmodified lines | ||
| 19 | 19 | }; |
| 20 | 20 | |
| 21 | 21 | extern void add_device_randomness(const void *, unsigned int); |
| 22 | +extern void add_bootloader_randomness(const void *, unsigned int); | |
| 22 | 23 | |
| 23 | 24 | #if defined(LATENT_ENTROPY_PLUGIN) && !defined(__CHECKER__) |
| 24 | 25 | static inline void add_latent_entropy(void) |
| @@ -27,6 +27,7 @@ · 26 unmodified lines | ||
| 27 | 27 | #ifndef _LINUX_TOPOLOGY_H |
| 28 | 28 | #define _LINUX_TOPOLOGY_H |
| 29 | 29 | |
| 30 | +#include <linux/arch_topology.h> | |
| 30 | 31 | #include <linux/cpumask.h> |
| 31 | 32 | #include <linux/bitops.h> |
| 32 | 33 | #include <linux/mmzone.h> |
| @@ -229,4 +229,9 @@ struct prctl_mm_map { · 228 unmodified lines | ||
| 229 | 229 | # define PR_PAC_APDBKEY (1UL << 3) |
| 230 | 230 | # define PR_PAC_APGAKEY (1UL << 4) |
| 231 | 231 | |
| 232 | +/* Tagged user address controls for arm64 */ | |
| 233 | +#define PR_SET_TAGGED_ADDR_CTRL 55 | |
| 234 | +#define PR_GET_TAGGED_ADDR_CTRL 56 | |
| 235 | +# define PR_TAGGED_ADDR_ENABLE (1UL << 0) | |
| 236 | + | |
| 232 | 237 | #endif /* _LINUX_PRCTL_H */ |
| @@ -124,6 +124,12 @@ · 123 unmodified lines | ||
| 124 | 124 | #ifndef PAC_RESET_KEYS |
| 125 | 125 | # define PAC_RESET_KEYS(a, b) (-EINVAL) |
| 126 | 126 | #endif |
| 127 | +#ifndef SET_TAGGED_ADDR_CTRL | |
| 128 | +# define SET_TAGGED_ADDR_CTRL(a) (-EINVAL) | |
| 129 | +#endif | |
| 130 | +#ifndef GET_TAGGED_ADDR_CTRL | |
| 131 | +# define GET_TAGGED_ADDR_CTRL() (-EINVAL) | |
| 132 | +#endif | |
| 127 | 133 | |
| 128 | 134 | /* |
| 129 | 135 | * this is where the system-wide overflow UID and GID are defined, for |
| @@ -2492,6 +2498,16 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, · 2362 unmodified lines | ||
| 2492 | 2498 | return -EINVAL; |
| 2493 | 2499 | error = PAC_RESET_KEYS(me, arg2); |
| 2494 | 2500 | break; |
| 2501 | + case PR_SET_TAGGED_ADDR_CTRL: | |
| 2502 | + if (arg3 || arg4 || arg5) | |
| 2503 | + return -EINVAL; | |
| 2504 | + error = SET_TAGGED_ADDR_CTRL(arg2); | |
| 2505 | + break; | |
| 2506 | + case PR_GET_TAGGED_ADDR_CTRL: | |
| 2507 | + if (arg2 || arg3 || arg4 || arg5) | |
| 2508 | + return -EINVAL; | |
| 2509 | + error = GET_TAGGED_ADDR_CTRL(); | |
| 2510 | + break; | |
| 2495 | 2511 | default: |
| 2496 | 2512 | error = -EINVAL; |
| 2497 | 2513 | break; |
| @@ -1,4 +1,9 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | +ifdef CONFIG_KASAN | |
| 3 | +CFLAGS_KASAN_NOSANITIZE := -fno-builtin | |
| 4 | +KASAN_SHADOW_OFFSET ?= $(CONFIG_KASAN_SHADOW_OFFSET) | |
| 5 | +endif | |
| 6 | + | |
| 2 | 7 | ifdef CONFIG_KASAN_GENERIC |
| 3 | 8 | |
| 4 | 9 | ifdef CONFIG_KASAN_INLINE |
| @@ -7,8 +12,6 @@ else · 2 unmodified lines | ||
| 7 | 12 | call_threshold := 0 |
| 8 | 13 | endif |
| 9 | 14 | |
| 10 | −KASAN_SHADOW_OFFSET ?= $(CONFIG_KASAN_SHADOW_OFFSET) | |
| 11 | − | |
| 12 | 15 | CFLAGS_KASAN_MINIMAL := -fsanitize=kernel-address |
| 13 | 16 | |
| 14 | 17 | cc-param = $(call cc-option, -mllvm -$(1), $(call cc-option, --param $(1))) |
| @@ -45,7 +48,3 @@ CFLAGS_KASAN := -fsanitize=kernel-hwaddress \ · 30 unmodified lines | ||
| 45 | 48 | $(instrumentation_flags) |
| 46 | 49 | |
| 47 | 50 | endif # CONFIG_KASAN_SW_TAGS |
| 48 | − | |
| 49 | −ifdef CONFIG_KASAN | |
| 50 | −CFLAGS_KASAN_NOSANITIZE := -fno-builtin | |
| 51 | −endif | |
| @@ -0,0 +1 @@ | ||
| 1 | +tags_test | |
| @@ -0,0 +1,11 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0 | |
| 2 | + | |
| 3 | +# ARCH can be overridden by the user for cross compiling | |
| 4 | +ARCH ?= $(shell uname -m 2>/dev/null || echo not) | |
| 5 | + | |
| 6 | +ifneq (,$(filter $(ARCH),aarch64 arm64)) | |
| 7 | +TEST_GEN_PROGS := tags_test | |
| 8 | +TEST_PROGS := run_tags_test.sh | |
| 9 | +endif | |
| 10 | + | |
| 11 | +include ../lib.mk | |
| @@ -0,0 +1,12 @@ | ||
| 1 | +#!/bin/sh | |
| 2 | +# SPDX-License-Identifier: GPL-2.0 | |
| 3 | + | |
| 4 | +echo "--------------------" | |
| 5 | +echo "running tags test" | |
| 6 | +echo "--------------------" | |
| 7 | +./tags_test | |
| 8 | +if [ $? -ne 0 ]; then | |
| 9 | + echo "[FAIL]" | |
| 10 | +else | |
| 11 | + echo "[PASS]" | |
| 12 | +fi | |
| @@ -0,0 +1,31 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 2 | + | |
| 3 | +#include <stdio.h> | |
| 4 | +#include <stdlib.h> | |
| 5 | +#include <unistd.h> | |
| 6 | +#include <stdint.h> | |
| 7 | +#include <sys/prctl.h> | |
| 8 | +#include <sys/utsname.h> | |
| 9 | + | |
| 10 | +#define SHIFT_TAG(tag) ((uint64_t)(tag) << 56) | |
| 11 | +#define SET_TAG(ptr, tag) (((uint64_t)(ptr) & ~SHIFT_TAG(0xff)) | \ | |
| 12 | + SHIFT_TAG(tag)) | |
| 13 | + | |
| 14 | +int main(void) | |
| 15 | +{ | |
| 16 | + static int tbi_enabled = 0; | |
| 17 | + unsigned long tag = 0; | |
| 18 | + struct utsname *ptr; | |
| 19 | + int err; | |
| 20 | + | |
| 21 | + if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0) == 0) | |
| 22 | + tbi_enabled = 1; | |
| 23 | + ptr = (struct utsname *)malloc(sizeof(*ptr)); | |
| 24 | + if (tbi_enabled) | |
| 25 | + tag = 0x42; | |
| 26 | + ptr = (struct utsname *)SET_TAG(ptr, tag); | |
| 27 | + err = uname(ptr); | |
| 28 | + free(ptr); | |
| 29 | + | |
| 30 | + return err; | |
| 31 | +} | |