Pull arm64 updates from Catalin Marinas: - arm64 support for syscall emulation via PTRACE_SYSEMU{,_SINGLESTEP} - Wire up VM_FLUSH_RESET_PERMS for arm64, allowing the core code to manage the permissions of executable vmalloc regions more strictly - Slight performance improvement by keeping softirqs enabled while touching the FPSIMD/SVE state (kernel_neon_begin/end) - Expose a couple of ARMv8.5 features to user (HWCAP): CondM (new XAFLAG and AXFLAG instructions for floating point comparison flags manipulation) and FRINT (rounding floating point numbers to integers) - Re-instate ARM64_PSEUDO_NMI support which was previously marked as BROKEN due to some bugs (now fixed) - Improve parking of stopped CPUs and implement an arm64-specific panic_smp_self_stop() to avoid warning on not being able to stop secondary CPUs during panic - perf: enable the ARM Statistical Profiling Extensions (SPE) on ACPI platforms - perf: DDR performance monitor support for iMX8QXP - cache_line_size() can now be set from DT or ACPI/PPTT if provided to cope with a system cache info not exposed via the CPUID registers - Avoid warning on hardware cache line size greater than ARCH_DMA_MINALIGN if the system is fully coherent - arm64 do_page_fault() and hugetlb cleanups - Refactor set_pte_at() to avoid redundant READ_ONCE(*ptep) - Ignore ACPI 5.1 FADTs reported as 5.0 (infer from the 'arm_boot_flags' introduced in 5.1) - CONFIG_RANDOMIZE_BASE now enabled in defconfig - Allow the selection of ARM64_MODULE_PLTS, currently only done via RANDOMIZE_BASE (and an erratum workaround), allowing modules to spill over into the vmalloc area - Make ZONE_DMA32 configurable * tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: (54 commits) perf: arm_spe: Enable ACPI/Platform automatic module loading arm_pmu: acpi: spe: Add initial MADT/SPE probing ACPI/PPTT: Add function to return ACPI 6.3 Identical tokens ACPI/PPTT: Modify node flag detection to find last IDENTICAL x86/entry: Simplify _TIF_SYSCALL_EMU handling arm64: rename dump_instr as dump_kernel_instr arm64/mm: Drop [PTE|PMD]_TYPE_FAULT arm64: Implement panic_smp_self_stop() arm64: Improve parking of stopped CPUs arm64: Expose FRINT capabilities to userspace arm64: Expose ARMv8.5 CondM capability to userspace arm64: defconfig: enable CONFIG_RANDOMIZE_BASE arm64: ARM64_MODULES_PLTS must depend on MODULES arm64: bpf: do not allocate executable memory arm64/kprobes: set VM_FLUSH_RESET_PERMS on kprobe instruction pages arm64/mm: wire up CONFIG_ARCH_HAS_SET_DIRECT_MAP arm64: module: create module allocations without exec permissions arm64: Allow user selection of ARM64_MODULE_PLTS acpi/arm64: ignore 5.1 FADTs that are reported as 5.0 arm64: Allow selecting Pseudo-NMI again ...
Unified · Split
| @@ -207,6 +207,10 @@ HWCAP_FLAGM · 206 unmodified lines | |||
| 207 | 207 | ||
| 208 | Functionality implied by ID_AA64ISAR0_EL1.TS == 0b0001. | 208 | Functionality implied by ID_AA64ISAR0_EL1.TS == 0b0001. |
| 209 | 209 | ||
| 210 | HWCAP2_FLAGM2 | ||
| 211 | |||
| 212 | Functionality implied by ID_AA64ISAR0_EL1.TS == 0b0010. | ||
| 213 | |||
| 210 | HWCAP_SSBS | 214 | HWCAP_SSBS |
| 211 | 215 | ||
| 212 | Functionality implied by ID_AA64PFR1_EL1.SSBS == 0b0010. | 216 | Functionality implied by ID_AA64PFR1_EL1.SSBS == 0b0010. |
| @@ -223,6 +227,10 @@ HWCAP_PACG · 10 unmodified lines | |||
| 223 | ID_AA64ISAR1_EL1.GPI == 0b0001, as described by | 227 | ID_AA64ISAR1_EL1.GPI == 0b0001, as described by |
| 224 | Documentation/arm64/pointer-authentication.txt. | 228 | Documentation/arm64/pointer-authentication.txt. |
| 225 | 229 | ||
| 230 | HWCAP2_FRINT | ||
| 231 | |||
| 232 | Functionality implied by ID_AA64ISAR1_EL1.FRINTTS == 0b0001. | ||
| 233 | |||
| 226 | 234 | ||
| 227 | 4. Unused AT_HWCAP bits | 235 | 4. Unused AT_HWCAP bits |
| 228 | ----------------------- | 236 | ----------------------- |
| @@ -0,0 +1,21 @@ | |||
| 1 | * Freescale(NXP) IMX8 DDR performance monitor | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | |||
| 5 | - compatible: should be one of: | ||
| 6 | "fsl,imx8-ddr-pmu" | ||
| 7 | "fsl,imx8m-ddr-pmu" | ||
| 8 | |||
| 9 | - reg: physical address and size | ||
| 10 | |||
| 11 | - interrupts: single interrupt | ||
| 12 | generated by the control block | ||
| 13 | |||
| 14 | Example: | ||
| 15 | |||
| 16 | ddr-pmu@5c020000 { | ||
| 17 | compatible = "fsl,imx8-ddr-pmu"; | ||
| 18 | reg = <0x5c020000 0x10000>; | ||
| 19 | interrupt-parent = <&gic>; | ||
| 20 | interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>; | ||
| 21 | }; | ||
| @@ -6337,6 +6337,13 @@ L: linux-i2c@vger.kernel.org · 6336 unmodified lines | |||
| 6337 | S: Maintained | 6337 | S: Maintained |
| 6338 | F: drivers/i2c/busses/i2c-cpm.c | 6338 | F: drivers/i2c/busses/i2c-cpm.c |
| 6339 | 6339 | ||
| 6340 | FREESCALE IMX DDR PMU DRIVER | ||
| 6341 | M: Frank Li <Frank.li@nxp.com> | ||
| 6342 | L: linux-arm-kernel@lists.infradead.org | ||
| 6343 | S: Maintained | ||
| 6344 | F: drivers/perf/fsl_imx8_ddr_perf.c | ||
| 6345 | F: Documentation/devicetree/bindings/perf/fsl-imx-ddr.txt | ||
| 6346 | |||
| 6340 | FREESCALE IMX LPI2C DRIVER | 6347 | FREESCALE IMX LPI2C DRIVER |
| 6341 | M: Dong Aisheng <aisheng.dong@nxp.com> | 6348 | M: Dong Aisheng <aisheng.dong@nxp.com> |
| 6342 | L: linux-i2c@vger.kernel.org | 6349 | L: linux-i2c@vger.kernel.org |
| @@ -26,6 +26,7 @@ config ARM64 · 25 unmodified lines | |||
| 26 | select ARCH_HAS_MEMBARRIER_SYNC_CORE | 26 | select ARCH_HAS_MEMBARRIER_SYNC_CORE |
| 27 | select ARCH_HAS_PTE_SPECIAL | 27 | select ARCH_HAS_PTE_SPECIAL |
| 28 | select ARCH_HAS_SETUP_DMA_OPS | 28 | select ARCH_HAS_SETUP_DMA_OPS |
| 29 | select ARCH_HAS_SET_DIRECT_MAP | ||
| 29 | select ARCH_HAS_SET_MEMORY | 30 | select ARCH_HAS_SET_MEMORY |
| 30 | select ARCH_HAS_STRICT_KERNEL_RWX | 31 | select ARCH_HAS_STRICT_KERNEL_RWX |
| 31 | select ARCH_HAS_STRICT_MODULE_RWX | 32 | select ARCH_HAS_STRICT_MODULE_RWX |
| @@ -260,7 +261,8 @@ config GENERIC_CALIBRATE_DELAY · 228 unmodified lines | |||
| 260 | def_bool y | 261 | def_bool y |
| 261 | 262 | ||
| 262 | config ZONE_DMA32 | 263 | config ZONE_DMA32 |
| 263 | def_bool y | 264 | bool "Support DMA32 zone" if EXPERT |
| 265 | default y | ||
| 264 | 266 | ||
| 265 | config HAVE_GENERIC_GUP | 267 | config HAVE_GENERIC_GUP |
| 266 | def_bool y | 268 | def_bool y |
| @@ -933,7 +935,6 @@ config PARAVIRT · 666 unmodified lines | |||
| 933 | config PARAVIRT_TIME_ACCOUNTING | 935 | config PARAVIRT_TIME_ACCOUNTING |
| 934 | bool "Paravirtual steal time accounting" | 936 | bool "Paravirtual steal time accounting" |
| 935 | select PARAVIRT | 937 | select PARAVIRT |
| 936 | default n | ||
| 937 | help | 938 | help |
| 938 | Select this option to enable fine granularity task steal time | 939 | Select this option to enable fine granularity task steal time |
| 939 | accounting. Time spent executing other tasks in parallel with | 940 | accounting. Time spent executing other tasks in parallel with |
| @@ -1418,12 +1419,27 @@ config ARM64_SVE · 478 unmodified lines | |||
| 1418 | KVM in the same kernel image. | 1419 | KVM in the same kernel image. |
| 1419 | 1420 | ||
| 1420 | config ARM64_MODULE_PLTS | 1421 | config ARM64_MODULE_PLTS |
| 1421 | bool | 1422 | bool "Use PLTs to allow module memory to spill over into vmalloc area" |
| 1423 | depends on MODULES | ||
| 1422 | select HAVE_MOD_ARCH_SPECIFIC | 1424 | select HAVE_MOD_ARCH_SPECIFIC |
| 1425 | help | ||
| 1426 | Allocate PLTs when loading modules so that jumps and calls whose | ||
| 1427 | targets are too far away for their relative offsets to be encoded | ||
| 1428 | in the instructions themselves can be bounced via veneers in the | ||
| 1429 | module's PLT. This allows modules to be allocated in the generic | ||
| 1430 | vmalloc area after the dedicated module memory area has been | ||
| 1431 | exhausted. | ||
| 1432 | |||
| 1433 | When running with address space randomization (KASLR), the module | ||
| 1434 | region itself may be too far away for ordinary relative jumps and | ||
| 1435 | calls, and so in that case, module PLTs are required and cannot be | ||
| 1436 | disabled. | ||
| 1437 | |||
| 1438 | Specific errata workaround(s) might also force module PLTs to be | ||
| 1439 | enabled (ARM64_ERRATUM_843419). | ||
| 1423 | 1440 | ||
| 1424 | config ARM64_PSEUDO_NMI | 1441 | config ARM64_PSEUDO_NMI |
| 1425 | bool "Support for NMI-like interrupts" | 1442 | bool "Support for NMI-like interrupts" |
| 1426 | depends on BROKEN # 1556553607-46531-1-git-send-email-julien.thierry@arm.com | ||
| 1427 | select CONFIG_ARM_GIC_V3 | 1443 | select CONFIG_ARM_GIC_V3 |
| 1428 | help | 1444 | help |
| 1429 | Adds support for mimicking Non-Maskable Interrupts through the use of | 1445 | Adds support for mimicking Non-Maskable Interrupts through the use of |
| @@ -1436,6 +1452,17 @@ config ARM64_PSEUDO_NMI · 6 unmodified lines | |||
| 1436 | 1452 | ||
| 1437 | If unsure, say N | 1453 | If unsure, say N |
| 1438 | 1454 | ||
| 1455 | if ARM64_PSEUDO_NMI | ||
| 1456 | config ARM64_DEBUG_PRIORITY_MASKING | ||
| 1457 | bool "Debug interrupt priority masking" | ||
| 1458 | help | ||
| 1459 | This adds runtime checks to functions enabling/disabling | ||
| 1460 | interrupts when using priority masking. The additional checks verify | ||
| 1461 | the validity of ICC_PMR_EL1 when calling concerned functions. | ||
| 1462 | |||
| 1463 | If unsure, say N | ||
| 1464 | endif | ||
| 1465 | |||
| 1439 | config RELOCATABLE | 1466 | config RELOCATABLE |
| 1440 | bool | 1467 | bool |
| 1441 | help | 1468 | help |
| @@ -68,6 +68,7 @@ CONFIG_KEXEC=y · 67 unmodified lines | |||
| 68 | CONFIG_CRASH_DUMP=y | 68 | CONFIG_CRASH_DUMP=y |
| 69 | CONFIG_XEN=y | 69 | CONFIG_XEN=y |
| 70 | CONFIG_COMPAT=y | 70 | CONFIG_COMPAT=y |
| 71 | CONFIG_RANDOMIZE_BASE=y | ||
| 71 | CONFIG_HIBERNATION=y | 72 | CONFIG_HIBERNATION=y |
| 72 | CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y | 73 | CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y |
| 73 | CONFIG_ARM_CPUIDLE=y | 74 | CONFIG_ARM_CPUIDLE=y |
| @@ -38,6 +38,9 @@ · 37 unmodified lines | |||
| 38 | (!(entry) || (entry)->header.length < ACPI_MADT_GICC_MIN_LENGTH || \ | 38 | (!(entry) || (entry)->header.length < ACPI_MADT_GICC_MIN_LENGTH || \ |
| 39 | (unsigned long)(entry) + (entry)->header.length > (end)) | 39 | (unsigned long)(entry) + (entry)->header.length > (end)) |
| 40 | 40 | ||
| 41 | #define ACPI_MADT_GICC_SPE (ACPI_OFFSET(struct acpi_madt_generic_interrupt, \ | ||
| 42 | spe_interrupt) + sizeof(u16)) | ||
| 43 | |||
| 41 | /* Basic configuration for ACPI */ | 44 | /* Basic configuration for ACPI */ |
| 42 | #ifdef CONFIG_ACPI | 45 | #ifdef CONFIG_ACPI |
| 43 | pgprot_t __acpi_get_mem_attribute(phys_addr_t addr); | 46 | pgprot_t __acpi_get_mem_attribute(phys_addr_t addr); |
| @@ -152,7 +152,9 @@ static inline bool gic_prio_masking_enabled(void) · 151 unmodified lines | |||
| 152 | 152 | ||
| 153 | static inline void gic_pmr_mask_irqs(void) | 153 | static inline void gic_pmr_mask_irqs(void) |
| 154 | { | 154 | { |
| 155 | BUILD_BUG_ON(GICD_INT_DEF_PRI <= GIC_PRIO_IRQOFF); | 155 | BUILD_BUG_ON(GICD_INT_DEF_PRI < (GIC_PRIO_IRQOFF | |
| 156 | GIC_PRIO_PSR_I_SET)); | ||
| 157 | BUILD_BUG_ON(GICD_INT_DEF_PRI >= GIC_PRIO_IRQON); | ||
| 156 | gic_write_pmr(GIC_PRIO_IRQOFF); | 158 | gic_write_pmr(GIC_PRIO_IRQOFF); |
| 157 | } | 159 | } |
| 158 | 160 | ||
| @@ -80,12 +80,15 @@ static inline u32 cache_type_cwg(void) · 79 unmodified lines | |||
| 80 | 80 | ||
| 81 | #define __read_mostly __attribute__((__section__(".data..read_mostly"))) | 81 | #define __read_mostly __attribute__((__section__(".data..read_mostly"))) |
| 82 | 82 | ||
| 83 | static inline int cache_line_size(void) | 83 | static inline int cache_line_size_of_cpu(void) |
| 84 | { | 84 | { |
| 85 | u32 cwg = cache_type_cwg(); | 85 | u32 cwg = cache_type_cwg(); |
| 86 | |||
| 86 | return cwg ? 4 << cwg : ARCH_DMA_MINALIGN; | 87 | return cwg ? 4 << cwg : ARCH_DMA_MINALIGN; |
| 87 | } | 88 | } |
| 88 | 89 | ||
| 90 | int cache_line_size(void); | ||
| 91 | |||
| 89 | /* | 92 | /* |
| 90 | * Read the effective value of CTR_EL0. | 93 | * Read the effective value of CTR_EL0. |
| 91 | * | 94 | * |
| @@ -176,4 +176,7 @@ static inline void flush_cache_vunmap(unsigned long start, unsigned long end) · 175 unmodified lines | |||
| 176 | 176 | ||
| 177 | int set_memory_valid(unsigned long addr, int numpages, int enable); | 177 | int set_memory_valid(unsigned long addr, int numpages, int enable); |
| 178 | 178 | ||
| 179 | int set_direct_map_invalid_noflush(struct page *page); | ||
| 180 | int set_direct_map_default_noflush(struct page *page); | ||
| 181 | |||
| 179 | #endif | 182 | #endif |
| @@ -614,6 +614,12 @@ static inline bool system_uses_irq_prio_masking(void) · 613 unmodified lines | |||
| 614 | cpus_have_const_cap(ARM64_HAS_IRQ_PRIO_MASKING); | 614 | cpus_have_const_cap(ARM64_HAS_IRQ_PRIO_MASKING); |
| 615 | } | 615 | } |
| 616 | 616 | ||
| 617 | static inline bool system_has_prio_mask_debugging(void) | ||
| 618 | { | ||
| 619 | return IS_ENABLED(CONFIG_ARM64_DEBUG_PRIORITY_MASKING) && | ||
| 620 | system_uses_irq_prio_masking(); | ||
| 621 | } | ||
| 622 | |||
| 617 | #define ARM64_SSBD_UNKNOWN -1 | 623 | #define ARM64_SSBD_UNKNOWN -1 |
| 618 | #define ARM64_SSBD_FORCE_DISABLE 0 | 624 | #define ARM64_SSBD_FORCE_DISABLE 0 |
| 619 | #define ARM64_SSBD_KERNEL 1 | 625 | #define ARM64_SSBD_KERNEL 1 |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | 7 | ||
| 8 | #include <linux/irqflags.h> | 8 | #include <linux/irqflags.h> |
| 9 | 9 | ||
| 10 | #include <asm/arch_gicv3.h> | ||
| 10 | #include <asm/cpufeature.h> | 11 | #include <asm/cpufeature.h> |
| 11 | 12 | ||
| 12 | #define DAIF_PROCCTX 0 | 13 | #define DAIF_PROCCTX 0 |
| @@ -16,11 +17,20 @@ · 3 unmodified lines | |||
| 16 | /* mask/save/unmask/restore all exceptions, including interrupts. */ | 17 | /* mask/save/unmask/restore all exceptions, including interrupts. */ |
| 17 | static inline void local_daif_mask(void) | 18 | static inline void local_daif_mask(void) |
| 18 | { | 19 | { |
| 20 | WARN_ON(system_has_prio_mask_debugging() && | ||
| 21 | (read_sysreg_s(SYS_ICC_PMR_EL1) == (GIC_PRIO_IRQOFF | | ||
| 22 | GIC_PRIO_PSR_I_SET))); | ||
| 23 | |||
| 19 | asm volatile( | 24 | asm volatile( |
| 20 | "msr daifset, #0xf // local_daif_mask\n" | 25 | "msr daifset, #0xf // local_daif_mask\n" |
| 21 | : | 26 | : |
| 22 | : | 27 | : |
| 23 | : "memory"); | 28 | : "memory"); |
| 29 | |||
| 30 | /* Don't really care for a dsb here, we don't intend to enable IRQs */ | ||
| 31 | if (system_uses_irq_prio_masking()) | ||
| 32 | gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET); | ||
| 33 | |||
| 24 | trace_hardirqs_off(); | 34 | trace_hardirqs_off(); |
| 25 | } | 35 | } |
| 26 | 36 | ||
| @@ -32,7 +42,7 @@ static inline unsigned long local_daif_save(void) · 5 unmodified lines | |||
| 32 | 42 | ||
| 33 | if (system_uses_irq_prio_masking()) { | 43 | if (system_uses_irq_prio_masking()) { |
| 34 | /* If IRQs are masked with PMR, reflect it in the flags */ | 44 | /* If IRQs are masked with PMR, reflect it in the flags */ |
| 35 | if (read_sysreg_s(SYS_ICC_PMR_EL1) <= GIC_PRIO_IRQOFF) | 45 | if (read_sysreg_s(SYS_ICC_PMR_EL1) != GIC_PRIO_IRQON) |
| 36 | flags |= PSR_I_BIT; | 46 | flags |= PSR_I_BIT; |
| 37 | } | 47 | } |
| 38 | 48 | ||
| @@ -45,39 +55,50 @@ static inline void local_daif_restore(unsigned long flags) · 6 unmodified lines | |||
| 45 | { | 55 | { |
| 46 | bool irq_disabled = flags & PSR_I_BIT; | 56 | bool irq_disabled = flags & PSR_I_BIT; |
| 47 | 57 | ||
| 58 | WARN_ON(system_has_prio_mask_debugging() && | ||
| 59 | !(read_sysreg(daif) & PSR_I_BIT)); | ||
| 60 | |||
| 48 | if (!irq_disabled) { | 61 | if (!irq_disabled) { |
| 49 | trace_hardirqs_on(); | 62 | trace_hardirqs_on(); |
| 50 | 63 | ||
| 51 | if (system_uses_irq_prio_masking()) | ||
| 52 | arch_local_irq_enable(); | ||
| 53 | } else if (!(flags & PSR_A_BIT)) { | ||
| 54 | /* | ||
| 55 | * If interrupts are disabled but we can take | ||
| 56 | * asynchronous errors, we can take NMIs | ||
| 57 | */ | ||
| 58 | if (system_uses_irq_prio_masking()) { | 64 | if (system_uses_irq_prio_masking()) { |
| 59 | flags &= ~PSR_I_BIT; | 65 | gic_write_pmr(GIC_PRIO_IRQON); |
| 66 | dsb(sy); | ||
| 67 | } | ||
| 68 | } else if (system_uses_irq_prio_masking()) { | ||
| 69 | u64 pmr; | ||
| 70 | |||
| 71 | if (!(flags & PSR_A_BIT)) { | ||
| 60 | /* | 72 | /* |
| 61 | * There has been concern that the write to daif | 73 | * If interrupts are disabled but we can take |
| 62 | * might be reordered before this write to PMR. | 74 | * asynchronous errors, we can take NMIs |
| 63 | * From the ARM ARM DDI 0487D.a, section D1.7.1 | ||
| 64 | * "Accessing PSTATE fields": | ||
| 65 | * Writes to the PSTATE fields have side-effects on | ||
| 66 | * various aspects of the PE operation. All of these | ||
| 67 | * side-effects are guaranteed: | ||
| 68 | * - Not to be visible to earlier instructions in | ||
| 69 | * the execution stream. | ||
| 70 | * - To be visible to later instructions in the | ||
| 71 | * execution stream | ||
| 72 | * | ||
| 73 | * Also, writes to PMR are self-synchronizing, so no | ||
| 74 | * interrupts with a lower priority than PMR is signaled | ||
| 75 | * to the PE after the write. | ||
| 76 | * | ||
| 77 | * So we don't need additional synchronization here. | ||
| 78 | */ | 75 | */ |
| 79 | arch_local_irq_disable(); | 76 | flags &= ~PSR_I_BIT; |
| 77 | pmr = GIC_PRIO_IRQOFF; | ||
| 78 | } else { | ||
| 79 | pmr = GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET; | ||
| 80 | } | 80 | } |
| 81 | |||
| 82 | /* | ||
| 83 | * There has been concern that the write to daif | ||
| 84 | * might be reordered before this write to PMR. | ||
| 85 | * From the ARM ARM DDI 0487D.a, section D1.7.1 | ||
| 86 | * "Accessing PSTATE fields": | ||
| 87 | * Writes to the PSTATE fields have side-effects on | ||
| 88 | * various aspects of the PE operation. All of these | ||
| 89 | * side-effects are guaranteed: | ||
| 90 | * - Not to be visible to earlier instructions in | ||
| 91 | * the execution stream. | ||
| 92 | * - To be visible to later instructions in the | ||
| 93 | * execution stream | ||
| 94 | * | ||
| 95 | * Also, writes to PMR are self-synchronizing, so no | ||
| 96 | * interrupts with a lower priority than PMR is signaled | ||
| 97 | * to the PE after the write. | ||
| 98 | * | ||
| 99 | * So we don't need additional synchronization here. | ||
| 100 | */ | ||
| 101 | gic_write_pmr(pmr); | ||
| 81 | } | 102 | } |
| 82 | 103 | ||
| 83 | write_sysreg(flags, daif); | 104 | write_sysreg(flags, daif); |
| @@ -37,8 +37,6 @@ struct task_struct; · 36 unmodified lines | |||
| 37 | extern void fpsimd_save_state(struct user_fpsimd_state *state); | 37 | extern void fpsimd_save_state(struct user_fpsimd_state *state); |
| 38 | extern void fpsimd_load_state(struct user_fpsimd_state *state); | 38 | extern void fpsimd_load_state(struct user_fpsimd_state *state); |
| 39 | 39 | ||
| 40 | extern void fpsimd_save(void); | ||
| 41 | |||
| 42 | extern void fpsimd_thread_switch(struct task_struct *next); | 40 | extern void fpsimd_thread_switch(struct task_struct *next); |
| 43 | extern void fpsimd_flush_thread(void); | 41 | extern void fpsimd_flush_thread(void); |
| 44 | 42 | ||
| @@ -52,8 +50,7 @@ extern void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *state, · 7 unmodified lines | |||
| 52 | void *sve_state, unsigned int sve_vl); | 50 | void *sve_state, unsigned int sve_vl); |
| 53 | 51 | ||
| 54 | extern void fpsimd_flush_task_state(struct task_struct *target); | 52 | extern void fpsimd_flush_task_state(struct task_struct *target); |
| 55 | extern void fpsimd_flush_cpu_state(void); | 53 | extern void fpsimd_save_and_flush_cpu_state(void); |
| 56 | extern void sve_flush_cpu_state(void); | ||
| 57 | 54 | ||
| 58 | /* Maximum VL that SVE VL-agnostic software can transparently support */ | 55 | /* Maximum VL that SVE VL-agnostic software can transparently support */ |
| 59 | #define SVE_VL_ARCH_MAX 0x100 | 56 | #define SVE_VL_ARCH_MAX 0x100 |
| @@ -84,6 +84,8 @@ · 83 unmodified lines | |||
| 84 | #define KERNEL_HWCAP_SVEBITPERM __khwcap2_feature(SVEBITPERM) | 84 | #define KERNEL_HWCAP_SVEBITPERM __khwcap2_feature(SVEBITPERM) |
| 85 | #define KERNEL_HWCAP_SVESHA3 __khwcap2_feature(SVESHA3) | 85 | #define KERNEL_HWCAP_SVESHA3 __khwcap2_feature(SVESHA3) |
| 86 | #define KERNEL_HWCAP_SVESM4 __khwcap2_feature(SVESM4) | 86 | #define KERNEL_HWCAP_SVESM4 __khwcap2_feature(SVESM4) |
| 87 | #define KERNEL_HWCAP_FLAGM2 __khwcap2_feature(FLAGM2) | ||
| 88 | #define KERNEL_HWCAP_FRINT __khwcap2_feature(FRINT) | ||
| 87 | 89 | ||
| 88 | /* | 90 | /* |
| 89 | * This yields a mask that user programs can use to figure out what | 91 | * This yields a mask that user programs can use to figure out what |
| @@ -29,6 +29,12 @@ · 28 unmodified lines | |||
| 29 | */ | 29 | */ |
| 30 | static inline void arch_local_irq_enable(void) | 30 | static inline void arch_local_irq_enable(void) |
| 31 | { | 31 | { |
| 32 | if (system_has_prio_mask_debugging()) { | ||
| 33 | u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1); | ||
| 34 | |||
| 35 | WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF); | ||
| 36 | } | ||
| 37 | |||
| 32 | asm volatile(ALTERNATIVE( | 38 | asm volatile(ALTERNATIVE( |
| 33 | "msr daifclr, #2 // arch_local_irq_enable\n" | 39 | "msr daifclr, #2 // arch_local_irq_enable\n" |
| 34 | "nop", | 40 | "nop", |
| @@ -42,6 +48,12 @@ static inline void arch_local_irq_enable(void) · 7 unmodified lines | |||
| 42 | 48 | ||
| 43 | static inline void arch_local_irq_disable(void) | 49 | static inline void arch_local_irq_disable(void) |
| 44 | { | 50 | { |
| 51 | if (system_has_prio_mask_debugging()) { | ||
| 52 | u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1); | ||
| 53 | |||
| 54 | WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF); | ||
| 55 | } | ||
| 56 | |||
| 45 | asm volatile(ALTERNATIVE( | 57 | asm volatile(ALTERNATIVE( |
| 46 | "msr daifset, #2 // arch_local_irq_disable", | 58 | "msr daifset, #2 // arch_local_irq_disable", |
| 47 | __msr_s(SYS_ICC_PMR_EL1, "%0"), | 59 | __msr_s(SYS_ICC_PMR_EL1, "%0"), |
| @@ -56,43 +68,46 @@ static inline void arch_local_irq_disable(void) · 8 unmodified lines | |||
| 56 | */ | 68 | */ |
| 57 | static inline unsigned long arch_local_save_flags(void) | 69 | static inline unsigned long arch_local_save_flags(void) |
| 58 | { | 70 | { |
| 59 | unsigned long daif_bits; | ||
| 60 | unsigned long flags; | 71 | unsigned long flags; |
| 61 | 72 | ||
| 62 | daif_bits = read_sysreg(daif); | ||
| 63 | |||
| 64 | /* | ||
| 65 | * The asm is logically equivalent to: | ||
| 66 | * | ||
| 67 | * if (system_uses_irq_prio_masking()) | ||
| 68 | * flags = (daif_bits & PSR_I_BIT) ? | ||
| 69 | * GIC_PRIO_IRQOFF : | ||
| 70 | * read_sysreg_s(SYS_ICC_PMR_EL1); | ||
| 71 | * else | ||
| 72 | * flags = daif_bits; | ||
| 73 | */ | ||
| 74 | asm volatile(ALTERNATIVE( | 73 | asm volatile(ALTERNATIVE( |
| 75 | "mov %0, %1\n" | 74 | "mrs %0, daif", |
| 76 | "nop\n" | 75 | __mrs_s("%0", SYS_ICC_PMR_EL1), |
| 77 | "nop", | 76 | ARM64_HAS_IRQ_PRIO_MASKING) |
| 78 | __mrs_s("%0", SYS_ICC_PMR_EL1) | 77 | : "=&r" (flags) |
| 79 | "ands %1, %1, " __stringify(PSR_I_BIT) "\n" | 78 | : |
| 80 | "csel %0, %0, %2, eq", | ||
| 81 | ARM64_HAS_IRQ_PRIO_MASKING) | ||
| 82 | : "=&r" (flags), "+r" (daif_bits) | ||
| 83 | : "r" ((unsigned long) GIC_PRIO_IRQOFF) | ||
| 84 | : "memory"); | 79 | : "memory"); |
| 85 | 80 | ||
| 86 | return flags; | 81 | return flags; |
| 87 | } | 82 | } |
| 88 | 83 | ||
| 84 | static inline int arch_irqs_disabled_flags(unsigned long flags) | ||
| 85 | { | ||
| 86 | int res; | ||
| 87 | |||
| 88 | asm volatile(ALTERNATIVE( | ||
| 89 | "and %w0, %w1, #" __stringify(PSR_I_BIT), | ||
| 90 | "eor %w0, %w1, #" __stringify(GIC_PRIO_IRQON), | ||
| 91 | ARM64_HAS_IRQ_PRIO_MASKING) | ||
| 92 | : "=&r" (res) | ||
| 93 | : "r" ((int) flags) | ||
| 94 | : "memory"); | ||
| 95 | |||
| 96 | return res; | ||
| 97 | } | ||
| 98 | |||
| 89 | static inline unsigned long arch_local_irq_save(void) | 99 | static inline unsigned long arch_local_irq_save(void) |
| 90 | { | 100 | { |
| 91 | unsigned long flags; | 101 | unsigned long flags; |
| 92 | 102 | ||
| 93 | flags = arch_local_save_flags(); | 103 | flags = arch_local_save_flags(); |
| 94 | 104 | ||
| 95 | arch_local_irq_disable(); | 105 | /* |
| 106 | * There are too many states with IRQs disabled, just keep the current | ||
| 107 | * state if interrupts are already disabled/masked. | ||
| 108 | */ | ||
| 109 | if (!arch_irqs_disabled_flags(flags)) | ||
| 110 | arch_local_irq_disable(); | ||
| 96 | 111 | ||
| 97 | return flags; | 112 | return flags; |
| 98 | } | 113 | } |
| @@ -108,26 +123,10 @@ static inline void arch_local_irq_restore(unsigned long flags) · 9 unmodified lines | |||
| 108 | __msr_s(SYS_ICC_PMR_EL1, "%0") | 123 | __msr_s(SYS_ICC_PMR_EL1, "%0") |
| 109 | "dsb sy", | 124 | "dsb sy", |
| 110 | ARM64_HAS_IRQ_PRIO_MASKING) | 125 | ARM64_HAS_IRQ_PRIO_MASKING) |
| 111 | : "+r" (flags) | ||
| 112 | : | 126 | : |
| 127 | : "r" (flags) | ||
| 113 | : "memory"); | 128 | : "memory"); |
| 114 | } | 129 | } |
| 115 | 130 | ||
| 116 | static inline int arch_irqs_disabled_flags(unsigned long flags) | ||
| 117 | { | ||
| 118 | int res; | ||
| 119 | |||
| 120 | asm volatile(ALTERNATIVE( | ||
| 121 | "and %w0, %w1, #" __stringify(PSR_I_BIT) "\n" | ||
| 122 | "nop", | ||
| 123 | "cmp %w1, #" __stringify(GIC_PRIO_IRQOFF) "\n" | ||
| 124 | "cset %w0, ls", | ||
| 125 | ARM64_HAS_IRQ_PRIO_MASKING) | ||
| 126 | : "=&r" (res) | ||
| 127 | : "r" ((int) flags) | ||
| 128 | : "memory"); | ||
| 129 | |||
| 130 | return res; | ||
| 131 | } | ||
| 132 | #endif | 131 | #endif |
| 133 | #endif | 132 | #endif |
| @@ -597,11 +597,12 @@ static inline void kvm_arm_vhe_guest_enter(void) · 596 unmodified lines | |||
| 597 | * will not signal the CPU of interrupts of lower priority, and the | 597 | * will not signal the CPU of interrupts of lower priority, and the |
| 598 | * only way to get out will be via guest exceptions. | 598 | * only way to get out will be via guest exceptions. |
| 599 | * Naturally, we want to avoid this. | 599 | * Naturally, we want to avoid this. |
| 600 | * | ||
| 601 | * local_daif_mask() already sets GIC_PRIO_PSR_I_SET, we just need a | ||
| 602 | * dsb to ensure the redistributor is forwards EL2 IRQs to the CPU. | ||
| 600 | */ | 603 | */ |
| 601 | if (system_uses_irq_prio_masking()) { | 604 | if (system_uses_irq_prio_masking()) |
| 602 | gic_write_pmr(GIC_PRIO_IRQON); | ||
| 603 | dsb(sy); | 605 | dsb(sy); |
| 604 | } | ||
| 605 | } | 606 | } |
| 606 | 607 | ||
| 607 | static inline void kvm_arm_vhe_guest_exit(void) | 608 | static inline void kvm_arm_vhe_guest_exit(void) |
| @@ -115,7 +115,6 @@ · 114 unmodified lines | |||
| 115 | * Level 2 descriptor (PMD). | 115 | * Level 2 descriptor (PMD). |
| 116 | */ | 116 | */ |
| 117 | #define PMD_TYPE_MASK (_AT(pmdval_t, 3) << 0) | 117 | #define PMD_TYPE_MASK (_AT(pmdval_t, 3) << 0) |
| 118 | #define PMD_TYPE_FAULT (_AT(pmdval_t, 0) << 0) | ||
| 119 | #define PMD_TYPE_TABLE (_AT(pmdval_t, 3) << 0) | 118 | #define PMD_TYPE_TABLE (_AT(pmdval_t, 3) << 0) |
| 120 | #define PMD_TYPE_SECT (_AT(pmdval_t, 1) << 0) | 119 | #define PMD_TYPE_SECT (_AT(pmdval_t, 1) << 0) |
| 121 | #define PMD_TABLE_BIT (_AT(pmdval_t, 1) << 1) | 120 | #define PMD_TABLE_BIT (_AT(pmdval_t, 1) << 1) |
| @@ -142,8 +141,8 @@ · 20 unmodified lines | |||
| 142 | /* | 141 | /* |
| 143 | * Level 3 descriptor (PTE). | 142 | * Level 3 descriptor (PTE). |
| 144 | */ | 143 | */ |
| 144 | #define PTE_VALID (_AT(pteval_t, 1) << 0) | ||
| 145 | #define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0) | 145 | #define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0) |
| 146 | #define PTE_TYPE_FAULT (_AT(pteval_t, 0) << 0) | ||
| 147 | #define PTE_TYPE_PAGE (_AT(pteval_t, 3) << 0) | 146 | #define PTE_TYPE_PAGE (_AT(pteval_t, 3) << 0) |
| 148 | #define PTE_TABLE_BIT (_AT(pteval_t, 1) << 1) | 147 | #define PTE_TABLE_BIT (_AT(pteval_t, 1) << 1) |
| 149 | #define PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */ | 148 | #define PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */ |
| @@ -13,7 +13,6 @@ · 12 unmodified lines | |||
| 13 | /* | 13 | /* |
| 14 | * Software defined PTE bits definition. | 14 | * Software defined PTE bits definition. |
| 15 | */ | 15 | */ |
| 16 | #define PTE_VALID (_AT(pteval_t, 1) << 0) | ||
| 17 | #define PTE_WRITE (PTE_DBM) /* same as DBM (51) */ | 16 | #define PTE_WRITE (PTE_DBM) /* same as DBM (51) */ |
| 18 | #define PTE_DIRTY (_AT(pteval_t, 1) << 55) | 17 | #define PTE_DIRTY (_AT(pteval_t, 1) << 55) |
| 19 | #define PTE_SPECIAL (_AT(pteval_t, 1) << 56) | 18 | #define PTE_SPECIAL (_AT(pteval_t, 1) << 56) |
| @@ -235,29 +235,42 @@ extern void __sync_icache_dcache(pte_t pteval); · 234 unmodified lines | |||
| 235 | * | 235 | * |
| 236 | * PTE_DIRTY || (PTE_WRITE && !PTE_RDONLY) | 236 | * PTE_DIRTY || (PTE_WRITE && !PTE_RDONLY) |
| 237 | */ | 237 | */ |
| 238 | static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | 238 | |
| 239 | pte_t *ptep, pte_t pte) | 239 | static inline void __check_racy_pte_update(struct mm_struct *mm, pte_t *ptep, |
| 240 | pte_t pte) | ||
| 240 | { | 241 | { |
| 241 | pte_t old_pte; | 242 | pte_t old_pte; |
| 242 | 243 | ||
| 243 | if (pte_present(pte) && pte_user_exec(pte) && !pte_special(pte)) | 244 | if (!IS_ENABLED(CONFIG_DEBUG_VM)) |
| 244 | __sync_icache_dcache(pte); | 245 | return; |
| 246 | |||
| 247 | old_pte = READ_ONCE(*ptep); | ||
| 248 | |||
| 249 | if (!pte_valid(old_pte) || !pte_valid(pte)) | ||
| 250 | return; | ||
| 251 | if (mm != current->active_mm && atomic_read(&mm->mm_users) <= 1) | ||
| 252 | return; | ||
| 245 | 253 | ||
| 246 | /* | 254 | /* |
| 247 | * If the existing pte is valid, check for potential race with | 255 | * Check for potential race with hardware updates of the pte |
| 248 | * hardware updates of the pte (ptep_set_access_flags safely changes | 256 | * (ptep_set_access_flags safely changes valid ptes without going |
| 249 | * valid ptes without going through an invalid entry). | 257 | * through an invalid entry). |
| 250 | */ | 258 | */ |
| 251 | old_pte = READ_ONCE(*ptep); | 259 | VM_WARN_ONCE(!pte_young(pte), |
| 252 | if (IS_ENABLED(CONFIG_DEBUG_VM) && pte_valid(old_pte) && pte_valid(pte) && | 260 | "%s: racy access flag clearing: 0x%016llx -> 0x%016llx", |
| 253 | (mm == current->active_mm || atomic_read(&mm->mm_users) > 1)) { | 261 | __func__, pte_val(old_pte), pte_val(pte)); |
| 254 | VM_WARN_ONCE(!pte_young(pte), | 262 | VM_WARN_ONCE(pte_write(old_pte) && !pte_dirty(pte), |
| 255 | "%s: racy access flag clearing: 0x%016llx -> 0x%016llx", | 263 | "%s: racy dirty state clearing: 0x%016llx -> 0x%016llx", |
| 256 | __func__, pte_val(old_pte), pte_val(pte)); | 264 | __func__, pte_val(old_pte), pte_val(pte)); |
| 257 | VM_WARN_ONCE(pte_write(old_pte) && !pte_dirty(pte), | 265 | } |
| 258 | "%s: racy dirty state clearing: 0x%016llx -> 0x%016llx", | 266 | |
| 259 | __func__, pte_val(old_pte), pte_val(pte)); | 267 | static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, |
| 260 | } | 268 | pte_t *ptep, pte_t pte) |
| 269 | { | ||
| 270 | if (pte_present(pte) && pte_user_exec(pte) && !pte_special(pte)) | ||
| 271 | __sync_icache_dcache(pte); | ||
| 272 | |||
| 273 | __check_racy_pte_update(mm, ptep, pte); | ||
| 261 | 274 | ||
| 262 | set_pte(ptep, pte); | 275 | set_pte(ptep, pte); |
| 263 | } | 276 | } |
| @@ -324,9 +337,14 @@ static inline pmd_t pte_pmd(pte_t pte) · 60 unmodified lines | |||
| 324 | return __pmd(pte_val(pte)); | 337 | return __pmd(pte_val(pte)); |
| 325 | } | 338 | } |
| 326 | 339 | ||
| 327 | static inline pgprot_t mk_sect_prot(pgprot_t prot) | 340 | static inline pgprot_t mk_pud_sect_prot(pgprot_t prot) |
| 341 | { | ||
| 342 | return __pgprot((pgprot_val(prot) & ~PUD_TABLE_BIT) | PUD_TYPE_SECT); | ||
| 343 | } | ||
| 344 | |||
| 345 | static inline pgprot_t mk_pmd_sect_prot(pgprot_t prot) | ||
| 328 | { | 346 | { |
| 329 | return __pgprot(pgprot_val(prot) & ~PTE_TABLE_BIT); | 347 | return __pgprot((pgprot_val(prot) & ~PMD_TABLE_BIT) | PMD_TYPE_SECT); |
| 330 | } | 348 | } |
| 331 | 349 | ||
| 332 | #ifdef CONFIG_NUMA_BALANCING | 350 | #ifdef CONFIG_NUMA_BALANCING |
| @@ -24,9 +24,15 @@ · 23 unmodified lines | |||
| 24 | * means masking more IRQs (or at least that the same IRQs remain masked). | 24 | * means masking more IRQs (or at least that the same IRQs remain masked). |
| 25 | * | 25 | * |
| 26 | * To mask interrupts, we clear the most significant bit of PMR. | 26 | * To mask interrupts, we clear the most significant bit of PMR. |
| 27 | * | ||
| 28 | * Some code sections either automatically switch back to PSR.I or explicitly | ||
| 29 | * require to not use priority masking. If bit GIC_PRIO_PSR_I_SET is included | ||
| 30 | * in the the priority mask, it indicates that PSR.I should be set and | ||
| 31 | * interrupt disabling temporarily does not rely on IRQ priorities. | ||
| 27 | */ | 32 | */ |
| 28 | #define GIC_PRIO_IRQON 0xf0 | 33 | #define GIC_PRIO_IRQON 0xc0 |
| 29 | #define GIC_PRIO_IRQOFF (GIC_PRIO_IRQON & ~0x80) | 34 | #define GIC_PRIO_IRQOFF (GIC_PRIO_IRQON & ~0x80) |
| 35 | #define GIC_PRIO_PSR_I_SET (1 << 4) | ||
| 30 | 36 | ||
| 31 | /* Additional SPSR bits not exposed in the UABI */ | 37 | /* Additional SPSR bits not exposed in the UABI */ |
| 32 | #define PSR_IL_BIT (1 << 20) | 38 | #define PSR_IL_BIT (1 << 20) |
| @@ -12,9 +12,9 @@ · 11 unmodified lines | |||
| 12 | #include <linux/preempt.h> | 12 | #include <linux/preempt.h> |
| 13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
| 14 | 14 | ||
| 15 | #ifdef CONFIG_KERNEL_MODE_NEON | 15 | DECLARE_PER_CPU(bool, fpsimd_context_busy); |
| 16 | 16 | ||
| 17 | DECLARE_PER_CPU(bool, kernel_neon_busy); | 17 | #ifdef CONFIG_KERNEL_MODE_NEON |
| 18 | 18 | ||
| 19 | /* | 19 | /* |
| 20 | * may_use_simd - whether it is allowable at this time to issue SIMD | 20 | * may_use_simd - whether it is allowable at this time to issue SIMD |
| @@ -26,15 +26,15 @@ DECLARE_PER_CPU(bool, kernel_neon_busy); · 5 unmodified lines | |||
| 26 | static __must_check inline bool may_use_simd(void) | 26 | static __must_check inline bool may_use_simd(void) |
| 27 | { | 27 | { |
| 28 | /* | 28 | /* |
| 29 | * kernel_neon_busy is only set while preemption is disabled, | 29 | * fpsimd_context_busy is only set while preemption is disabled, |
| 30 | * and is clear whenever preemption is enabled. Since | 30 | * and is clear whenever preemption is enabled. Since |
| 31 | * this_cpu_read() is atomic w.r.t. preemption, kernel_neon_busy | 31 | * this_cpu_read() is atomic w.r.t. preemption, fpsimd_context_busy |
| 32 | * cannot change under our feet -- if it's set we cannot be | 32 | * cannot change under our feet -- if it's set we cannot be |
| 33 | * migrated, and if it's clear we cannot be migrated to a CPU | 33 | * migrated, and if it's clear we cannot be migrated to a CPU |
| 34 | * where it is set. | 34 | * where it is set. |
| 35 | */ | 35 | */ |
| 36 | return !in_irq() && !irqs_disabled() && !in_nmi() && | 36 | return !in_irq() && !irqs_disabled() && !in_nmi() && |
| 37 | !this_cpu_read(kernel_neon_busy); | 37 | !this_cpu_read(fpsimd_context_busy); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | #else /* ! CONFIG_KERNEL_MODE_NEON */ | 40 | #else /* ! CONFIG_KERNEL_MODE_NEON */ |
| @@ -549,6 +549,7 @@ · 548 unmodified lines | |||
| 549 | 549 | ||
| 550 | /* id_aa64isar1 */ | 550 | /* id_aa64isar1 */ |
| 551 | #define ID_AA64ISAR1_SB_SHIFT 36 | 551 | #define ID_AA64ISAR1_SB_SHIFT 36 |
| 552 | #define ID_AA64ISAR1_FRINTTS_SHIFT 32 | ||
| 552 | #define ID_AA64ISAR1_GPI_SHIFT 28 | 553 | #define ID_AA64ISAR1_GPI_SHIFT 28 |
| 553 | #define ID_AA64ISAR1_GPA_SHIFT 24 | 554 | #define ID_AA64ISAR1_GPA_SHIFT 24 |
| 554 | #define ID_AA64ISAR1_LRCPC_SHIFT 20 | 555 | #define ID_AA64ISAR1_LRCPC_SHIFT 20 |
| @@ -65,6 +65,7 @@ void arch_release_task_struct(struct task_struct *tsk); · 64 unmodified lines | |||
| 65 | * TIF_SYSCALL_TRACEPOINT - syscall tracepoint for ftrace | 65 | * TIF_SYSCALL_TRACEPOINT - syscall tracepoint for ftrace |
| 66 | * TIF_SYSCALL_AUDIT - syscall auditing | 66 | * TIF_SYSCALL_AUDIT - syscall auditing |
| 67 | * TIF_SECCOMP - syscall secure computing | 67 | * TIF_SECCOMP - syscall secure computing |
| 68 | * TIF_SYSCALL_EMU - syscall emulation active | ||
| 68 | * TIF_SIGPENDING - signal pending | 69 | * TIF_SIGPENDING - signal pending |
| 69 | * TIF_NEED_RESCHED - rescheduling necessary | 70 | * TIF_NEED_RESCHED - rescheduling necessary |
| 70 | * TIF_NOTIFY_RESUME - callback before returning to user | 71 | * TIF_NOTIFY_RESUME - callback before returning to user |
| @@ -80,6 +81,7 @@ void arch_release_task_struct(struct task_struct *tsk); · 9 unmodified lines | |||
| 80 | #define TIF_SYSCALL_AUDIT 9 | 81 | #define TIF_SYSCALL_AUDIT 9 |
| 81 | #define TIF_SYSCALL_TRACEPOINT 10 | 82 | #define TIF_SYSCALL_TRACEPOINT 10 |
| 82 | #define TIF_SECCOMP 11 | 83 | #define TIF_SECCOMP 11 |
| 84 | #define TIF_SYSCALL_EMU 12 | ||
| 83 | #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ | 85 | #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ |
| 84 | #define TIF_FREEZE 19 | 86 | #define TIF_FREEZE 19 |
| 85 | #define TIF_RESTORE_SIGMASK 20 | 87 | #define TIF_RESTORE_SIGMASK 20 |
| @@ -98,6 +100,7 @@ void arch_release_task_struct(struct task_struct *tsk); · 12 unmodified lines | |||
| 98 | #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) | 100 | #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) |
| 99 | #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) | 101 | #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) |
| 100 | #define _TIF_SECCOMP (1 << TIF_SECCOMP) | 102 | #define _TIF_SECCOMP (1 << TIF_SECCOMP) |
| 103 | #define _TIF_SYSCALL_EMU (1 << TIF_SYSCALL_EMU) | ||
| 101 | #define _TIF_UPROBE (1 << TIF_UPROBE) | 104 | #define _TIF_UPROBE (1 << TIF_UPROBE) |
| 102 | #define _TIF_FSCHECK (1 << TIF_FSCHECK) | 105 | #define _TIF_FSCHECK (1 << TIF_FSCHECK) |
| 103 | #define _TIF_32BIT (1 << TIF_32BIT) | 106 | #define _TIF_32BIT (1 << TIF_32BIT) |
| @@ -109,7 +112,7 @@ void arch_release_task_struct(struct task_struct *tsk); · 5 unmodified lines | |||
| 109 | 112 | ||
| 110 | #define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ | 113 | #define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ |
| 111 | _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \ | 114 | _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \ |
| 112 | _TIF_NOHZ) | 115 | _TIF_NOHZ | _TIF_SYSCALL_EMU) |
| 113 | 116 | ||
| 114 | #define INIT_THREAD_INFO(tsk) \ | 117 | #define INIT_THREAD_INFO(tsk) \ |
| 115 | { \ | 118 | { \ |
| @@ -63,5 +63,7 @@ · 62 unmodified lines | |||
| 63 | #define HWCAP2_SVEBITPERM (1 << 4) | 63 | #define HWCAP2_SVEBITPERM (1 << 4) |
| 64 | #define HWCAP2_SVESHA3 (1 << 5) | 64 | #define HWCAP2_SVESHA3 (1 << 5) |
| 65 | #define HWCAP2_SVESM4 (1 << 6) | 65 | #define HWCAP2_SVESM4 (1 << 6) |
| 66 | #define HWCAP2_FLAGM2 (1 << 7) | ||
| 67 | #define HWCAP2_FRINT (1 << 8) | ||
| 66 | 68 | ||
| 67 | #endif /* _UAPI__ASM_HWCAP_H */ | 69 | #endif /* _UAPI__ASM_HWCAP_H */ |
| @@ -62,6 +62,9 @@ · 61 unmodified lines | |||
| 62 | #define PSR_x 0x0000ff00 /* Extension */ | 62 | #define PSR_x 0x0000ff00 /* Extension */ |
| 63 | #define PSR_c 0x000000ff /* Control */ | 63 | #define PSR_c 0x000000ff /* Control */ |
| 64 | 64 | ||
| 65 | /* syscall emulation path in ptrace */ | ||
| 66 | #define PTRACE_SYSEMU 31 | ||
| 67 | #define PTRACE_SYSEMU_SINGLESTEP 32 | ||
| 65 | 68 | ||
| 66 | #ifndef __ASSEMBLY__ | 69 | #ifndef __ASSEMBLY__ |
| 67 | 70 | ||
| @@ -152,10 +152,14 @@ static int __init acpi_fadt_sanity_check(void) · 151 unmodified lines | |||
| 152 | */ | 152 | */ |
| 153 | if (table->revision < 5 || | 153 | if (table->revision < 5 || |
| 154 | (table->revision == 5 && fadt->minor_revision < 1)) { | 154 | (table->revision == 5 && fadt->minor_revision < 1)) { |
| 155 | pr_err("Unsupported FADT revision %d.%d, should be 5.1+\n", | 155 | pr_err(FW_BUG "Unsupported FADT revision %d.%d, should be 5.1+\n", |
| 156 | table->revision, fadt->minor_revision); | 156 | table->revision, fadt->minor_revision); |
| 157 | ret = -EINVAL; | 157 | |
| 158 | goto out; | 158 | if (!fadt->arm_boot_flags) { |
| 159 | ret = -EINVAL; | ||
| 160 | goto out; | ||
| 161 | } | ||
| 162 | pr_err("FADT has ARM boot flags set, assuming 5.1\n"); | ||
| 159 | } | 163 | } |
| 160 | 164 | ||
| 161 | if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) { | 165 | if (!(fadt->flags & ACPI_FADT_HW_REDUCED)) { |
| @@ -17,6 +17,15 @@ · 16 unmodified lines | |||
| 17 | #define CLIDR_CTYPE(clidr, level) \ | 17 | #define CLIDR_CTYPE(clidr, level) \ |
| 18 | (((clidr) & CLIDR_CTYPE_MASK(level)) >> CLIDR_CTYPE_SHIFT(level)) | 18 | (((clidr) & CLIDR_CTYPE_MASK(level)) >> CLIDR_CTYPE_SHIFT(level)) |
| 19 | 19 | ||
| 20 | int cache_line_size(void) | ||
| 21 | { | ||
| 22 | if (coherency_max_size != 0) | ||
| 23 | return coherency_max_size; | ||
| 24 | |||
| 25 | return cache_line_size_of_cpu(); | ||
| 26 | } | ||
| 27 | EXPORT_SYMBOL_GPL(cache_line_size); | ||
| 28 | |||
| 20 | static inline enum cache_type get_cache_type(int level) | 29 | static inline enum cache_type get_cache_type(int level) |
| 21 | { | 30 | { |
| 22 | u64 clidr; | 31 | u64 clidr; |
| @@ -1184,14 +1184,14 @@ static struct undef_hook ssbs_emulation_hook = { · 1183 unmodified lines | |||
| 1184 | static void cpu_enable_ssbs(const struct arm64_cpu_capabilities *__unused) | 1184 | static void cpu_enable_ssbs(const struct arm64_cpu_capabilities *__unused) |
| 1185 | { | 1185 | { |
| 1186 | static bool undef_hook_registered = false; | 1186 | static bool undef_hook_registered = false; |
| 1187 | static DEFINE_SPINLOCK(hook_lock); | 1187 | static DEFINE_RAW_SPINLOCK(hook_lock); |
| 1188 | 1188 | ||
| 1189 | spin_lock(&hook_lock); | 1189 | raw_spin_lock(&hook_lock); |
| 1190 | if (!undef_hook_registered) { | 1190 | if (!undef_hook_registered) { |
| 1191 | register_undef_hook(&ssbs_emulation_hook); | 1191 | register_undef_hook(&ssbs_emulation_hook); |
| 1192 | undef_hook_registered = true; | 1192 | undef_hook_registered = true; |
| 1193 | } | 1193 | } |
| 1194 | spin_unlock(&hook_lock); | 1194 | raw_spin_unlock(&hook_lock); |
| 1195 | 1195 | ||
| 1196 | if (arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE) { | 1196 | if (arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE) { |
| 1197 | sysreg_clear_set(sctlr_el1, 0, SCTLR_ELx_DSSBS); | 1197 | sysreg_clear_set(sctlr_el1, 0, SCTLR_ELx_DSSBS); |
| @@ -1618,6 +1618,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { · 420 unmodified lines | |||
| 1618 | HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_DP_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_ASIMDDP), | 1618 | HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_DP_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_ASIMDDP), |
| 1619 | HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_FHM_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_ASIMDFHM), | 1619 | HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_FHM_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_ASIMDFHM), |
| 1620 | HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_TS_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_FLAGM), | 1620 | HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_TS_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_FLAGM), |
| 1621 | HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_TS_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, KERNEL_HWCAP_FLAGM2), | ||
| 1621 | HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, KERNEL_HWCAP_FP), | 1622 | HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, KERNEL_HWCAP_FP), |
| 1622 | HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_FPHP), | 1623 | HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_FPHP), |
| 1623 | HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, KERNEL_HWCAP_ASIMD), | 1624 | HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, KERNEL_HWCAP_ASIMD), |
| @@ -1629,6 +1630,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { · 5 unmodified lines | |||
| 1629 | HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_FCMA_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_FCMA), | 1630 | HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_FCMA_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_FCMA), |
| 1630 | HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_LRCPC_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_LRCPC), | 1631 | HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_LRCPC_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_LRCPC), |
| 1631 | HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_LRCPC_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, KERNEL_HWCAP_ILRCPC), | 1632 | HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_LRCPC_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, KERNEL_HWCAP_ILRCPC), |
| 1633 | HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_FRINTTS_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_FRINT), | ||
| 1632 | HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_SB_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_SB), | 1634 | HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_SB_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_SB), |
| 1633 | HWCAP_CAP(SYS_ID_AA64MMFR2_EL1, ID_AA64MMFR2_AT_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_USCAT), | 1635 | HWCAP_CAP(SYS_ID_AA64MMFR2_EL1, ID_AA64MMFR2_AT_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_USCAT), |
| 1634 | #ifdef CONFIG_ARM64_SVE | 1636 | #ifdef CONFIG_ARM64_SVE |
| @@ -82,6 +82,8 @@ static const char *const hwcap_str[] = { · 81 unmodified lines | |||
| 82 | "svebitperm", | 82 | "svebitperm", |
| 83 | "svesha3", | 83 | "svesha3", |
| 84 | "svesm4", | 84 | "svesm4", |
| 85 | "flagm2", | ||
| 86 | "frint", | ||
| 85 | NULL | 87 | NULL |
| 86 | }; | 88 | }; |
| 87 | 89 | ||
| @@ -247,6 +247,7 @@ alternative_else_nop_endif · 246 unmodified lines | |||
| 247 | /* | 247 | /* |
| 248 | * Registers that may be useful after this macro is invoked: | 248 | * Registers that may be useful after this macro is invoked: |
| 249 | * | 249 | * |
| 250 | * x20 - ICC_PMR_EL1 | ||
| 250 | * x21 - aborted SP | 251 | * x21 - aborted SP |
| 251 | * x22 - aborted PC | 252 | * x22 - aborted PC |
| 252 | * x23 - aborted PSTATE | 253 | * x23 - aborted PSTATE |
| @@ -424,6 +425,38 @@ tsk .req x28 // current thread_info · 171 unmodified lines | |||
| 424 | irq_stack_exit | 425 | irq_stack_exit |
| 425 | .endm | 426 | .endm |
| 426 | 427 | ||
| 428 | #ifdef CONFIG_ARM64_PSEUDO_NMI | ||
| 429 | /* | ||
| 430 | * Set res to 0 if irqs were unmasked in interrupted context. | ||
| 431 | * Otherwise set res to non-0 value. | ||
| 432 | */ | ||
| 433 | .macro test_irqs_unmasked res:req, pmr:req | ||
| 434 | alternative_if ARM64_HAS_IRQ_PRIO_MASKING | ||
| 435 | sub \res, \pmr, #GIC_PRIO_IRQON | ||
| 436 | alternative_else | ||
| 437 | mov \res, xzr | ||
| 438 | alternative_endif | ||
| 439 | .endm | ||
| 440 | #endif | ||
| 441 | |||
| 442 | .macro gic_prio_kentry_setup, tmp:req | ||
| 443 | #ifdef CONFIG_ARM64_PSEUDO_NMI | ||
| 444 | alternative_if ARM64_HAS_IRQ_PRIO_MASKING | ||
| 445 | mov \tmp, #(GIC_PRIO_PSR_I_SET | GIC_PRIO_IRQON) | ||
| 446 | msr_s SYS_ICC_PMR_EL1, \tmp | ||
| 447 | alternative_else_nop_endif | ||
| 448 | #endif | ||
| 449 | .endm | ||
| 450 | |||
| 451 | .macro gic_prio_irq_setup, pmr:req, tmp:req | ||
| 452 | #ifdef CONFIG_ARM64_PSEUDO_NMI | ||
| 453 | alternative_if ARM64_HAS_IRQ_PRIO_MASKING | ||
| 454 | orr \tmp, \pmr, #GIC_PRIO_PSR_I_SET | ||
| 455 | msr_s SYS_ICC_PMR_EL1, \tmp | ||
| 456 | alternative_else_nop_endif | ||
| 457 | #endif | ||
| 458 | .endm | ||
| 459 | |||
| 427 | .text | 460 | .text |
| 428 | 461 | ||
| 429 | /* | 462 | /* |
| @@ -602,6 +635,7 @@ el1_dbg: · 172 unmodified lines | |||
| 602 | cmp x24, #ESR_ELx_EC_BRK64 // if BRK64 | 635 | cmp x24, #ESR_ELx_EC_BRK64 // if BRK64 |
| 603 | cinc x24, x24, eq // set bit '0' | 636 | cinc x24, x24, eq // set bit '0' |
| 604 | tbz x24, #0, el1_inv // EL1 only | 637 | tbz x24, #0, el1_inv // EL1 only |
| 638 | gic_prio_kentry_setup tmp=x3 | ||
| 605 | mrs x0, far_el1 | 639 | mrs x0, far_el1 |
| 606 | mov x2, sp // struct pt_regs | 640 | mov x2, sp // struct pt_regs |
| 607 | bl do_debug_exception | 641 | bl do_debug_exception |
| @@ -619,20 +653,18 @@ ENDPROC(el1_sync) · 11 unmodified lines | |||
| 619 | .align 6 | 653 | .align 6 |
| 620 | el1_irq: | 654 | el1_irq: |
| 621 | kernel_entry 1 | 655 | kernel_entry 1 |
| 656 | gic_prio_irq_setup pmr=x20, tmp=x1 | ||
| 622 | enable_da_f | 657 | enable_da_f |
| 623 | #ifdef CONFIG_TRACE_IRQFLAGS | 658 | |
| 624 | #ifdef CONFIG_ARM64_PSEUDO_NMI | 659 | #ifdef CONFIG_ARM64_PSEUDO_NMI |
| 625 | alternative_if ARM64_HAS_IRQ_PRIO_MASKING | 660 | test_irqs_unmasked res=x0, pmr=x20 |
| 626 | ldr x20, [sp, #S_PMR_SAVE] | 661 | cbz x0, 1f |
| 627 | alternative_else | 662 | bl asm_nmi_enter |
| 628 | mov x20, #GIC_PRIO_IRQON | 663 | 1: |
| 629 | alternative_endif | ||
| 630 | cmp x20, #GIC_PRIO_IRQOFF | ||
| 631 | /* Irqs were disabled, don't trace */ | ||
| 632 | b.ls 1f | ||
| 633 | #endif | 664 | #endif |
| 665 | |||
| 666 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
| 634 | bl trace_hardirqs_off | 667 | bl trace_hardirqs_off |
| 635 | 1: | ||
| 636 | #endif | 668 | #endif |
| 637 | 669 | ||
| 638 | irq_handler | 670 | irq_handler |
| @@ -651,14 +683,23 @@ alternative_else_nop_endif · 12 unmodified lines | |||
| 651 | bl preempt_schedule_irq // irq en/disable is done inside | 683 | bl preempt_schedule_irq // irq en/disable is done inside |
| 652 | 1: | 684 | 1: |
| 653 | #endif | 685 | #endif |
| 654 | #ifdef CONFIG_TRACE_IRQFLAGS | 686 | |
| 655 | #ifdef CONFIG_ARM64_PSEUDO_NMI | 687 | #ifdef CONFIG_ARM64_PSEUDO_NMI |
| 656 | /* | 688 | /* |
| 657 | * if IRQs were disabled when we received the interrupt, we have an NMI | 689 | * When using IRQ priority masking, we can get spurious interrupts while |
| 658 | * and we are not re-enabling interrupt upon eret. Skip tracing. | 690 | * PMR is set to GIC_PRIO_IRQOFF. An NMI might also have occurred in a |
| 691 | * section with interrupts disabled. Skip tracing in those cases. | ||
| 659 | */ | 692 | */ |
| 660 | cmp x20, #GIC_PRIO_IRQOFF | 693 | test_irqs_unmasked res=x0, pmr=x20 |
| 661 | b.ls 1f | 694 | cbz x0, 1f |
| 695 | bl asm_nmi_exit | ||
| 696 | 1: | ||
| 697 | #endif | ||
| 698 | |||
| 699 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
| 700 | #ifdef CONFIG_ARM64_PSEUDO_NMI | ||
| 701 | test_irqs_unmasked res=x0, pmr=x20 | ||
| 702 | cbnz x0, 1f | ||
| 662 | #endif | 703 | #endif |
| 663 | bl trace_hardirqs_on | 704 | bl trace_hardirqs_on |
| 664 | 1: | 705 | 1: |
| @@ -776,6 +817,7 @@ el0_ia: · 111 unmodified lines | |||
| 776 | * Instruction abort handling | 817 | * Instruction abort handling |
| 777 | */ | 818 | */ |
| 778 | mrs x26, far_el1 | 819 | mrs x26, far_el1 |
| 820 | gic_prio_kentry_setup tmp=x0 | ||
| 779 | enable_da_f | 821 | enable_da_f |
| 780 | #ifdef CONFIG_TRACE_IRQFLAGS | 822 | #ifdef CONFIG_TRACE_IRQFLAGS |
| 781 | bl trace_hardirqs_off | 823 | bl trace_hardirqs_off |
| @@ -821,6 +863,7 @@ el0_sp_pc: · 39 unmodified lines | |||
| 821 | * Stack or PC alignment exception handling | 863 | * Stack or PC alignment exception handling |
| 822 | */ | 864 | */ |
| 823 | mrs x26, far_el1 | 865 | mrs x26, far_el1 |
| 866 | gic_prio_kentry_setup tmp=x0 | ||
| 824 | enable_da_f | 867 | enable_da_f |
| 825 | #ifdef CONFIG_TRACE_IRQFLAGS | 868 | #ifdef CONFIG_TRACE_IRQFLAGS |
| 826 | bl trace_hardirqs_off | 869 | bl trace_hardirqs_off |
| @@ -855,11 +898,12 @@ el0_dbg: · 28 unmodified lines | |||
| 855 | * Debug exception handling | 898 | * Debug exception handling |
| 856 | */ | 899 | */ |
| 857 | tbnz x24, #0, el0_inv // EL0 only | 900 | tbnz x24, #0, el0_inv // EL0 only |
| 901 | gic_prio_kentry_setup tmp=x3 | ||
| 858 | mrs x0, far_el1 | 902 | mrs x0, far_el1 |
| 859 | mov x1, x25 | 903 | mov x1, x25 |
| 860 | mov x2, sp | 904 | mov x2, sp |
| 861 | bl do_debug_exception | 905 | bl do_debug_exception |
| 862 | enable_daif | 906 | enable_da_f |
| 863 | ct_user_exit | 907 | ct_user_exit |
| 864 | b ret_to_user | 908 | b ret_to_user |
| 865 | el0_inv: | 909 | el0_inv: |
| @@ -876,7 +920,9 @@ ENDPROC(el0_sync) · 10 unmodified lines | |||
| 876 | el0_irq: | 920 | el0_irq: |
| 877 | kernel_entry 0 | 921 | kernel_entry 0 |
| 878 | el0_irq_naked: | 922 | el0_irq_naked: |
| 923 | gic_prio_irq_setup pmr=x20, tmp=x0 | ||
| 879 | enable_da_f | 924 | enable_da_f |
| 925 | |||
| 880 | #ifdef CONFIG_TRACE_IRQFLAGS | 926 | #ifdef CONFIG_TRACE_IRQFLAGS |
| 881 | bl trace_hardirqs_off | 927 | bl trace_hardirqs_off |
| 882 | #endif | 928 | #endif |
| @@ -898,6 +944,7 @@ ENDPROC(el0_irq) · 15 unmodified lines | |||
| 898 | el1_error: | 944 | el1_error: |
| 899 | kernel_entry 1 | 945 | kernel_entry 1 |
| 900 | mrs x1, esr_el1 | 946 | mrs x1, esr_el1 |
| 947 | gic_prio_kentry_setup tmp=x2 | ||
| 901 | enable_dbg | 948 | enable_dbg |
| 902 | mov x0, sp | 949 | mov x0, sp |
| 903 | bl do_serror | 950 | bl do_serror |
| @@ -908,10 +955,11 @@ el0_error: · 4 unmodified lines | |||
| 908 | kernel_entry 0 | 955 | kernel_entry 0 |
| 909 | el0_error_naked: | 956 | el0_error_naked: |
| 910 | mrs x1, esr_el1 | 957 | mrs x1, esr_el1 |
| 958 | gic_prio_kentry_setup tmp=x2 | ||
| 911 | enable_dbg | 959 | enable_dbg |
| 912 | mov x0, sp | 960 | mov x0, sp |
| 913 | bl do_serror | 961 | bl do_serror |
| 914 | enable_daif | 962 | enable_da_f |
| 915 | ct_user_exit | 963 | ct_user_exit |
| 916 | b ret_to_user | 964 | b ret_to_user |
| 917 | ENDPROC(el0_error) | 965 | ENDPROC(el0_error) |
| @@ -932,6 +980,7 @@ work_pending: · 14 unmodified lines | |||
| 932 | */ | 980 | */ |
| 933 | ret_to_user: | 981 | ret_to_user: |
| 934 | disable_daif | 982 | disable_daif |
| 983 | gic_prio_kentry_setup tmp=x3 | ||
| 935 | ldr x1, [tsk, #TSK_TI_FLAGS] | 984 | ldr x1, [tsk, #TSK_TI_FLAGS] |
| 936 | and x2, x1, #_TIF_WORK_MASK | 985 | and x2, x1, #_TIF_WORK_MASK |
| 937 | cbnz x2, work_pending | 986 | cbnz x2, work_pending |
| @@ -948,6 +997,7 @@ ENDPROC(ret_to_user) · 10 unmodified lines | |||
| 948 | */ | 997 | */ |
| 949 | .align 6 | 998 | .align 6 |
| 950 | el0_svc: | 999 | el0_svc: |
| 1000 | gic_prio_kentry_setup tmp=x1 | ||
| 951 | mov x0, sp | 1001 | mov x0, sp |
| 952 | bl el0_svc_handler | 1002 | bl el0_svc_handler |
| 953 | b ret_to_user | 1003 | b ret_to_user |
| @@ -82,7 +82,8 @@ · 81 unmodified lines | |||
| 82 | * To prevent this from racing with the manipulation of the task's FPSIMD state | 82 | * To prevent this from racing with the manipulation of the task's FPSIMD state |
| 83 | * from task context and thereby corrupting the state, it is necessary to | 83 | * from task context and thereby corrupting the state, it is necessary to |
| 84 | * protect any manipulation of a task's fpsimd_state or TIF_FOREIGN_FPSTATE | 84 | * protect any manipulation of a task's fpsimd_state or TIF_FOREIGN_FPSTATE |
| 85 | * flag with local_bh_disable() unless softirqs are already masked. | 85 | * flag with {, __}get_cpu_fpsimd_context(). This will still allow softirqs to |
| 86 | * run but prevent them to use FPSIMD. | ||
| 86 | * | 87 | * |
| 87 | * For a certain task, the sequence may look something like this: | 88 | * For a certain task, the sequence may look something like this: |
| 88 | * - the task gets scheduled in; if both the task's fpsimd_cpu field | 89 | * - the task gets scheduled in; if both the task's fpsimd_cpu field |
| @@ -145,6 +146,56 @@ extern void __percpu *efi_sve_state; · 56 unmodified lines | |||
| 145 | 146 | ||
| 146 | #endif /* ! CONFIG_ARM64_SVE */ | 147 | #endif /* ! CONFIG_ARM64_SVE */ |
| 147 | 148 | ||
| 149 | DEFINE_PER_CPU(bool, fpsimd_context_busy); | ||
| 150 | EXPORT_PER_CPU_SYMBOL(fpsimd_context_busy); | ||
| 151 | |||
| 152 | static void __get_cpu_fpsimd_context(void) | ||
| 153 | { | ||
| 154 | bool busy = __this_cpu_xchg(fpsimd_context_busy, true); | ||
| 155 | |||
| 156 | WARN_ON(busy); | ||
| 157 | } | ||
| 158 | |||
| 159 | /* | ||
| 160 | * Claim ownership of the CPU FPSIMD context for use by the calling context. | ||
| 161 | * | ||
| 162 | * The caller may freely manipulate the FPSIMD context metadata until | ||
| 163 | * put_cpu_fpsimd_context() is called. | ||
| 164 | * | ||
| 165 | * The double-underscore version must only be called if you know the task | ||
| 166 | * can't be preempted. | ||
| 167 | */ | ||
| 168 | static void get_cpu_fpsimd_context(void) | ||
| 169 | { | ||
| 170 | preempt_disable(); | ||
| 171 | __get_cpu_fpsimd_context(); | ||
| 172 | } | ||
| 173 | |||
| 174 | static void __put_cpu_fpsimd_context(void) | ||
| 175 | { | ||
| 176 | bool busy = __this_cpu_xchg(fpsimd_context_busy, false); | ||
| 177 | |||
| 178 | WARN_ON(!busy); /* No matching get_cpu_fpsimd_context()? */ | ||
| 179 | } | ||
| 180 | |||
| 181 | /* | ||
| 182 | * Release the CPU FPSIMD context. | ||
| 183 | * | ||
| 184 | * Must be called from a context in which get_cpu_fpsimd_context() was | ||
| 185 | * previously called, with no call to put_cpu_fpsimd_context() in the | ||
| 186 | * meantime. | ||
| 187 | */ | ||
| 188 | static void put_cpu_fpsimd_context(void) | ||
| 189 | { | ||
| 190 | __put_cpu_fpsimd_context(); | ||
| 191 | preempt_enable(); | ||
| 192 | } | ||
| 193 | |||
| 194 | static bool have_cpu_fpsimd_context(void) | ||
| 195 | { | ||
| 196 | return !preemptible() && __this_cpu_read(fpsimd_context_busy); | ||
| 197 | } | ||
| 198 | |||
| 148 | /* | 199 | /* |
| 149 | * Call __sve_free() directly only if you know task can't be scheduled | 200 | * Call __sve_free() directly only if you know task can't be scheduled |
| 150 | * or preempted. | 201 | * or preempted. |
| @@ -215,12 +266,10 @@ static void sve_free(struct task_struct *task) · 64 unmodified lines | |||
| 215 | * This function should be called only when the FPSIMD/SVE state in | 266 | * This function should be called only when the FPSIMD/SVE state in |
| 216 | * thread_struct is known to be up to date, when preparing to enter | 267 | * thread_struct is known to be up to date, when preparing to enter |
| 217 | * userspace. | 268 | * userspace. |
| 218 | * | ||
| 219 | * Softirqs (and preemption) must be disabled. | ||
| 220 | */ | 269 | */ |
| 221 | static void task_fpsimd_load(void) | 270 | static void task_fpsimd_load(void) |
| 222 | { | 271 | { |
| 223 | WARN_ON(!in_softirq() && !irqs_disabled()); | 272 | WARN_ON(!have_cpu_fpsimd_context()); |
| 224 | 273 | ||
| 225 | if (system_supports_sve() && test_thread_flag(TIF_SVE)) | 274 | if (system_supports_sve() && test_thread_flag(TIF_SVE)) |
| 226 | sve_load_state(sve_pffr(¤t->thread), | 275 | sve_load_state(sve_pffr(¤t->thread), |
| @@ -233,16 +282,14 @@ static void task_fpsimd_load(void) · 6 unmodified lines | |||
| 233 | /* | 282 | /* |
| 234 | * Ensure FPSIMD/SVE storage in memory for the loaded context is up to | 283 | * Ensure FPSIMD/SVE storage in memory for the loaded context is up to |
| 235 | * date with respect to the CPU registers. | 284 | * date with respect to the CPU registers. |
| 236 | * | ||
| 237 | * Softirqs (and preemption) must be disabled. | ||
| 238 | */ | 285 | */ |
| 239 | void fpsimd_save(void) | 286 | static void fpsimd_save(void) |
| 240 | { | 287 | { |
| 241 | struct fpsimd_last_state_struct const *last = | 288 | struct fpsimd_last_state_struct const *last = |
| 242 | this_cpu_ptr(&fpsimd_last_state); | 289 | this_cpu_ptr(&fpsimd_last_state); |
| 243 | /* set by fpsimd_bind_task_to_cpu() or fpsimd_bind_state_to_cpu() */ | 290 | /* set by fpsimd_bind_task_to_cpu() or fpsimd_bind_state_to_cpu() */ |
| 244 | 291 | ||
| 245 | WARN_ON(!in_softirq() && !irqs_disabled()); | 292 | WARN_ON(!have_cpu_fpsimd_context()); |
| 246 | 293 | ||
| 247 | if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) { | 294 | if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) { |
| 248 | if (system_supports_sve() && test_thread_flag(TIF_SVE)) { | 295 | if (system_supports_sve() && test_thread_flag(TIF_SVE)) { |
| @@ -364,7 +411,8 @@ static __uint128_t arm64_cpu_to_le128(__uint128_t x) · 115 unmodified lines | |||
| 364 | * task->thread.sve_state. | 411 | * task->thread.sve_state. |
| 365 | * | 412 | * |
| 366 | * Task can be a non-runnable task, or current. In the latter case, | 413 | * Task can be a non-runnable task, or current. In the latter case, |
| 367 | * softirqs (and preemption) must be disabled. | 414 | * the caller must have ownership of the cpu FPSIMD context before calling |
| 415 | * this function. | ||
| 368 | * task->thread.sve_state must point to at least sve_state_size(task) | 416 | * task->thread.sve_state must point to at least sve_state_size(task) |
| 369 | * bytes of allocated kernel memory. | 417 | * bytes of allocated kernel memory. |
| 370 | * task->thread.uw.fpsimd_state must be up to date before calling this | 418 | * task->thread.uw.fpsimd_state must be up to date before calling this |
| @@ -393,7 +441,8 @@ static void fpsimd_to_sve(struct task_struct *task) · 22 unmodified lines | |||
| 393 | * task->thread.uw.fpsimd_state. | 441 | * task->thread.uw.fpsimd_state. |
| 394 | * | 442 | * |
| 395 | * Task can be a non-runnable task, or current. In the latter case, | 443 | * Task can be a non-runnable task, or current. In the latter case, |
| 396 | * softirqs (and preemption) must be disabled. | 444 | * the caller must have ownership of the cpu FPSIMD context before calling |
| 445 | * this function. | ||
| 397 | * task->thread.sve_state must point to at least sve_state_size(task) | 446 | * task->thread.sve_state must point to at least sve_state_size(task) |
| 398 | * bytes of allocated kernel memory. | 447 | * bytes of allocated kernel memory. |
| 399 | * task->thread.sve_state must be up to date before calling this function. | 448 | * task->thread.sve_state must be up to date before calling this function. |
| @@ -557,7 +606,7 @@ int sve_set_vector_length(struct task_struct *task, · 157 unmodified lines | |||
| 557 | * non-SVE thread. | 606 | * non-SVE thread. |
| 558 | */ | 607 | */ |
| 559 | if (task == current) { | 608 | if (task == current) { |
| 560 | local_bh_disable(); | 609 | get_cpu_fpsimd_context(); |
| 561 | 610 | ||
| 562 | fpsimd_save(); | 611 | fpsimd_save(); |
| 563 | } | 612 | } |
| @@ -567,7 +616,7 @@ int sve_set_vector_length(struct task_struct *task, · 3 unmodified lines | |||
| 567 | sve_to_fpsimd(task); | 616 | sve_to_fpsimd(task); |
| 568 | 617 | ||
| 569 | if (task == current) | 618 | if (task == current) |
| 570 | local_bh_enable(); | 619 | put_cpu_fpsimd_context(); |
| 571 | 620 | ||
| 572 | /* | 621 | /* |
| 573 | * Force reallocation of task SVE state to the correct size | 622 | * Force reallocation of task SVE state to the correct size |
| @@ -880,7 +929,7 @@ asmlinkage void do_sve_acc(unsigned int esr, struct pt_regs *regs) · 306 unmodified lines | |||
| 880 | 929 | ||
| 881 | sve_alloc(current); | 930 | sve_alloc(current); |
| 882 | 931 | ||
| 883 | local_bh_disable(); | 932 | get_cpu_fpsimd_context(); |
| 884 | 933 | ||
| 885 | fpsimd_save(); | 934 | fpsimd_save(); |
| 886 | 935 | ||
| @@ -891,7 +940,7 @@ asmlinkage void do_sve_acc(unsigned int esr, struct pt_regs *regs) · 4 unmodified lines | |||
| 891 | if (test_and_set_thread_flag(TIF_SVE)) | 940 | if (test_and_set_thread_flag(TIF_SVE)) |
| 892 | WARN_ON(1); /* SVE access shouldn't have trapped */ | 941 | WARN_ON(1); /* SVE access shouldn't have trapped */ |
| 893 | 942 | ||
| 894 | local_bh_enable(); | 943 | put_cpu_fpsimd_context(); |
| 895 | } | 944 | } |
| 896 | 945 | ||
| 897 | /* | 946 | /* |
| @@ -935,6 +984,8 @@ void fpsimd_thread_switch(struct task_struct *next) · 37 unmodified lines | |||
| 935 | if (!system_supports_fpsimd()) | 984 | if (!system_supports_fpsimd()) |
| 936 | return; | 985 | return; |
| 937 | 986 | ||
| 987 | __get_cpu_fpsimd_context(); | ||
| 988 | |||
| 938 | /* Save unsaved fpsimd state, if any: */ | 989 | /* Save unsaved fpsimd state, if any: */ |
| 939 | fpsimd_save(); | 990 | fpsimd_save(); |
| 940 | 991 | ||
| @@ -949,6 +1000,8 @@ void fpsimd_thread_switch(struct task_struct *next) · 8 unmodified lines | |||
| 949 | 1000 | ||
| 950 | update_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE, | 1001 | update_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE, |
| 951 | wrong_task || wrong_cpu); | 1002 | wrong_task || wrong_cpu); |
| 1003 | |||
| 1004 | __put_cpu_fpsimd_context(); | ||
| 952 | } | 1005 | } |
| 953 | 1006 | ||
| 954 | void fpsimd_flush_thread(void) | 1007 | void fpsimd_flush_thread(void) |
| @@ -958,7 +1011,7 @@ void fpsimd_flush_thread(void) · 3 unmodified lines | |||
| 958 | if (!system_supports_fpsimd()) | 1011 | if (!system_supports_fpsimd()) |
| 959 | return; | 1012 | return; |
| 960 | 1013 | ||
| 961 | local_bh_disable(); | 1014 | get_cpu_fpsimd_context(); |
| 962 | 1015 | ||
| 963 | fpsimd_flush_task_state(current); | 1016 | fpsimd_flush_task_state(current); |
| 964 | memset(¤t->thread.uw.fpsimd_state, 0, | 1017 | memset(¤t->thread.uw.fpsimd_state, 0, |
| @@ -999,7 +1052,7 @@ void fpsimd_flush_thread(void) · 34 unmodified lines | |||
| 999 | current->thread.sve_vl_onexec = 0; | 1052 | current->thread.sve_vl_onexec = 0; |
| 1000 | } | 1053 | } |
| 1001 | 1054 | ||
| 1002 | local_bh_enable(); | 1055 | put_cpu_fpsimd_context(); |
| 1003 | } | 1056 | } |
| 1004 | 1057 | ||
| 1005 | /* | 1058 | /* |
| @@ -1011,9 +1064,9 @@ void fpsimd_preserve_current_state(void) · 5 unmodified lines | |||
| 1011 | if (!system_supports_fpsimd()) | 1064 | if (!system_supports_fpsimd()) |
| 1012 | return; | 1065 | return; |
| 1013 | 1066 | ||
| 1014 | local_bh_disable(); | 1067 | get_cpu_fpsimd_context(); |
| 1015 | fpsimd_save(); | 1068 | fpsimd_save(); |
| 1016 | local_bh_enable(); | 1069 | put_cpu_fpsimd_context(); |
| 1017 | } | 1070 | } |
| 1018 | 1071 | ||
| 1019 | /* | 1072 | /* |
| @@ -1030,7 +1083,8 @@ void fpsimd_signal_preserve_current_state(void) · 10 unmodified lines | |||
| 1030 | 1083 | ||
| 1031 | /* | 1084 | /* |
| 1032 | * Associate current's FPSIMD context with this cpu | 1085 | * Associate current's FPSIMD context with this cpu |
| 1033 | * Preemption must be disabled when calling this function. | 1086 | * The caller must have ownership of the cpu FPSIMD context before calling |
| 1087 | * this function. | ||
| 1034 | */ | 1088 | */ |
| 1035 | void fpsimd_bind_task_to_cpu(void) | 1089 | void fpsimd_bind_task_to_cpu(void) |
| 1036 | { | 1090 | { |
| @@ -1076,14 +1130,14 @@ void fpsimd_restore_current_state(void) · 39 unmodified lines | |||
| 1076 | if (!system_supports_fpsimd()) | 1130 | if (!system_supports_fpsimd()) |
| 1077 | return; | 1131 | return; |
| 1078 | 1132 | ||
| 1079 | local_bh_disable(); | 1133 | get_cpu_fpsimd_context(); |
| 1080 | 1134 | ||
| 1081 | if (test_and_clear_thread_flag(TIF_FOREIGN_FPSTATE)) { | 1135 | if (test_and_clear_thread_flag(TIF_FOREIGN_FPSTATE)) { |
| 1082 | task_fpsimd_load(); | 1136 | task_fpsimd_load(); |
| 1083 | fpsimd_bind_task_to_cpu(); | 1137 | fpsimd_bind_task_to_cpu(); |
| 1084 | } | 1138 | } |
| 1085 | 1139 | ||
| 1086 | local_bh_enable(); | 1140 | put_cpu_fpsimd_context(); |
| 1087 | } | 1141 | } |
| 1088 | 1142 | ||
| 1089 | /* | 1143 | /* |
| @@ -1096,7 +1150,7 @@ void fpsimd_update_current_state(struct user_fpsimd_state const *state) · 6 unmodified lines | |||
| 1096 | if (!system_supports_fpsimd()) | 1150 | if (!system_supports_fpsimd()) |
| 1097 | return; | 1151 | return; |
| 1098 | 1152 | ||
| 1099 | local_bh_disable(); | 1153 | get_cpu_fpsimd_context(); |
| 1100 | 1154 | ||
| 1101 | current->thread.uw.fpsimd_state = *state; | 1155 | current->thread.uw.fpsimd_state = *state; |
| 1102 | if (system_supports_sve() && test_thread_flag(TIF_SVE)) | 1156 | if (system_supports_sve() && test_thread_flag(TIF_SVE)) |
| @@ -1107,7 +1161,7 @@ void fpsimd_update_current_state(struct user_fpsimd_state const *state) · 4 unmodified lines | |||
| 1107 | 1161 | ||
| 1108 | clear_thread_flag(TIF_FOREIGN_FPSTATE); | 1162 | clear_thread_flag(TIF_FOREIGN_FPSTATE); |
| 1109 | 1163 | ||
| 1110 | local_bh_enable(); | 1164 | put_cpu_fpsimd_context(); |
| 1111 | } | 1165 | } |
| 1112 | 1166 | ||
| 1113 | /* | 1167 | /* |
| @@ -1133,18 +1187,29 @@ void fpsimd_flush_task_state(struct task_struct *t) · 19 unmodified lines | |||
| 1133 | 1187 | ||
| 1134 | /* | 1188 | /* |
| 1135 | * Invalidate any task's FPSIMD state that is present on this cpu. | 1189 | * Invalidate any task's FPSIMD state that is present on this cpu. |
| 1136 | * This function must be called with softirqs disabled. | 1190 | * The FPSIMD context should be acquired with get_cpu_fpsimd_context() |
| 1191 | * before calling this function. | ||
| 1137 | */ | 1192 | */ |
| 1138 | void fpsimd_flush_cpu_state(void) | 1193 | static void fpsimd_flush_cpu_state(void) |
| 1139 | { | 1194 | { |
| 1140 | __this_cpu_write(fpsimd_last_state.st, NULL); | 1195 | __this_cpu_write(fpsimd_last_state.st, NULL); |
| 1141 | set_thread_flag(TIF_FOREIGN_FPSTATE); | 1196 | set_thread_flag(TIF_FOREIGN_FPSTATE); |
| 1142 | } | 1197 | } |
| 1143 | 1198 | ||
| 1144 | #ifdef CONFIG_KERNEL_MODE_NEON | 1199 | /* |
| 1200 | * Save the FPSIMD state to memory and invalidate cpu view. | ||
| 1201 | * This function must be called with preemption disabled. | ||
| 1202 | */ | ||
| 1203 | void fpsimd_save_and_flush_cpu_state(void) | ||
| 1204 | { | ||
| 1205 | WARN_ON(preemptible()); | ||
| 1206 | __get_cpu_fpsimd_context(); | ||
| 1207 | fpsimd_save(); | ||
| 1208 | fpsimd_flush_cpu_state(); | ||
| 1209 | __put_cpu_fpsimd_context(); | ||
| 1210 | } | ||
| 1145 | 1211 | ||
| 1146 | DEFINE_PER_CPU(bool, kernel_neon_busy); | 1212 | #ifdef CONFIG_KERNEL_MODE_NEON |
| 1147 | EXPORT_PER_CPU_SYMBOL(kernel_neon_busy); | ||
| 1148 | 1213 | ||
| 1149 | /* | 1214 | /* |
| 1150 | * Kernel-side NEON support functions | 1215 | * Kernel-side NEON support functions |
| @@ -1170,19 +1235,13 @@ void kernel_neon_begin(void) · 19 unmodified lines | |||
| 1170 | 1235 | ||
| 1171 | BUG_ON(!may_use_simd()); | 1236 | BUG_ON(!may_use_simd()); |
| 1172 | 1237 | ||
| 1173 | local_bh_disable(); | 1238 | get_cpu_fpsimd_context(); |
| 1174 | |||
| 1175 | __this_cpu_write(kernel_neon_busy, true); | ||
| 1176 | 1239 | ||
| 1177 | /* Save unsaved fpsimd state, if any: */ | 1240 | /* Save unsaved fpsimd state, if any: */ |
| 1178 | fpsimd_save(); | 1241 | fpsimd_save(); |
| 1179 | 1242 | ||
| 1180 | /* Invalidate any task state remaining in the fpsimd regs: */ | 1243 | /* Invalidate any task state remaining in the fpsimd regs: */ |
| 1181 | fpsimd_flush_cpu_state(); | 1244 | fpsimd_flush_cpu_state(); |
| 1182 | |||
| 1183 | preempt_disable(); | ||
| 1184 | |||
| 1185 | local_bh_enable(); | ||
| 1186 | } | 1245 | } |
| 1187 | EXPORT_SYMBOL(kernel_neon_begin); | 1246 | EXPORT_SYMBOL(kernel_neon_begin); |
| 1188 | 1247 | ||
| @@ -1197,15 +1256,10 @@ EXPORT_SYMBOL(kernel_neon_begin); · 8 unmodified lines | |||
| 1197 | */ | 1256 | */ |
| 1198 | void kernel_neon_end(void) | 1257 | void kernel_neon_end(void) |
| 1199 | { | 1258 | { |
| 1200 | bool busy; | ||
| 1201 | |||
| 1202 | if (!system_supports_fpsimd()) | 1259 | if (!system_supports_fpsimd()) |
| 1203 | return; | 1260 | return; |
| 1204 | 1261 | ||
| 1205 | busy = __this_cpu_xchg(kernel_neon_busy, false); | 1262 | put_cpu_fpsimd_context(); |
| 1206 | WARN_ON(!busy); /* No matching kernel_neon_begin()? */ | ||
| 1207 | |||
| 1208 | preempt_enable(); | ||
| 1209 | } | 1263 | } |
| 1210 | EXPORT_SYMBOL(kernel_neon_end); | 1264 | EXPORT_SYMBOL(kernel_neon_end); |
| 1211 | 1265 | ||
| @@ -1297,8 +1351,7 @@ static int fpsimd_cpu_pm_notifier(struct notifier_block *self, · 85 unmodified lines | |||
| 1297 | { | 1351 | { |
| 1298 | switch (cmd) { | 1352 | switch (cmd) { |
| 1299 | case CPU_PM_ENTER: | 1353 | case CPU_PM_ENTER: |
| 1300 | fpsimd_save(); | 1354 | fpsimd_save_and_flush_cpu_state(); |
| 1301 | fpsimd_flush_cpu_state(); | ||
| 1302 | break; | 1355 | break; |
| 1303 | case CPU_PM_EXIT: | 1356 | case CPU_PM_EXIT: |
| 1304 | break; | 1357 | break; |
| @@ -16,8 +16,10 @@ · 15 unmodified lines | |||
| 16 | #include <linux/smp.h> | 16 | #include <linux/smp.h> |
| 17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 18 | #include <linux/irqchip.h> | 18 | #include <linux/irqchip.h> |
| 19 | #include <linux/kprobes.h> | ||
| 19 | #include <linux/seq_file.h> | 20 | #include <linux/seq_file.h> |
| 20 | #include <linux/vmalloc.h> | 21 | #include <linux/vmalloc.h> |
| 22 | #include <asm/daifflags.h> | ||
| 21 | #include <asm/vmap_stack.h> | 23 | #include <asm/vmap_stack.h> |
| 22 | 24 | ||
| 23 | unsigned long irq_err_count; | 25 | unsigned long irq_err_count; |
| @@ -64,4 +66,28 @@ void __init init_IRQ(void) · 40 unmodified lines | |||
| 64 | irqchip_init(); | 66 | irqchip_init(); |
| 65 | if (!handle_arch_irq) | 67 | if (!handle_arch_irq) |
| 66 | panic("No interrupt controller found."); | 68 | panic("No interrupt controller found."); |
| 69 | |||
| 70 | if (system_uses_irq_prio_masking()) { | ||
| 71 | /* | ||
| 72 | * Now that we have a stack for our IRQ handler, set | ||
| 73 | * the PMR/PSR pair to a consistent state. | ||
| 74 | */ | ||
| 75 | WARN_ON(read_sysreg(daif) & PSR_A_BIT); | ||
| 76 | local_daif_restore(DAIF_PROCCTX_NOIRQ); | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | /* | ||
| 81 | * Stubs to make nmi_enter/exit() code callable from ASM | ||
| 82 | */ | ||
| 83 | asmlinkage void notrace asm_nmi_enter(void) | ||
| 84 | { | ||
| 85 | nmi_enter(); | ||
| 86 | } | ||
| 87 | NOKPROBE_SYMBOL(asm_nmi_enter); | ||
| 88 | |||
| 89 | asmlinkage void notrace asm_nmi_exit(void) | ||
| 90 | { | ||
| 91 | nmi_exit(); | ||
| 67 | } | 92 | } |
| 93 | NOKPROBE_SYMBOL(asm_nmi_exit); | ||
| @@ -34,7 +34,7 @@ void *module_alloc(unsigned long size) · 33 unmodified lines | |||
| 34 | module_alloc_end = MODULES_END; | 34 | module_alloc_end = MODULES_END; |
| 35 | 35 | ||
| 36 | p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base, | 36 | p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base, |
| 37 | module_alloc_end, gfp_mask, PAGE_KERNEL_EXEC, 0, | 37 | module_alloc_end, gfp_mask, PAGE_KERNEL, 0, |
| 38 | NUMA_NO_NODE, __builtin_return_address(0)); | 38 | NUMA_NO_NODE, __builtin_return_address(0)); |
| 39 | 39 | ||
| 40 | if (!p && IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) && | 40 | if (!p && IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) && |
| @@ -50,7 +50,7 @@ void *module_alloc(unsigned long size) · 9 unmodified lines | |||
| 50 | */ | 50 | */ |
| 51 | p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base, | 51 | p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base, |
| 52 | module_alloc_base + SZ_2G, GFP_KERNEL, | 52 | module_alloc_base + SZ_2G, GFP_KERNEL, |
| 53 | PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, | 53 | PAGE_KERNEL, 0, NUMA_NO_NODE, |
| 54 | __builtin_return_address(0)); | 54 | __builtin_return_address(0)); |
| 55 | 55 | ||
| 56 | if (p && (kasan_module_alloc(p, size) < 0)) { | 56 | if (p && (kasan_module_alloc(p, size) < 0)) { |
| @@ -122,8 +122,10 @@ void *alloc_insn_page(void) · 121 unmodified lines | |||
| 122 | void *page; | 122 | void *page; |
| 123 | 123 | ||
| 124 | page = vmalloc_exec(PAGE_SIZE); | 124 | page = vmalloc_exec(PAGE_SIZE); |
| 125 | if (page) | 125 | if (page) { |
| 126 | set_memory_ro((unsigned long)page, 1); | 126 | set_memory_ro((unsigned long)page, 1); |
| 127 | set_vm_flush_reset_perms(page); | ||
| 128 | } | ||
| 127 | 129 | ||
| 128 | return page; | 130 | return page; |
| 129 | } | 131 | } |
| @@ -83,7 +83,7 @@ static void __cpu_do_idle_irqprio(void) · 82 unmodified lines | |||
| 83 | * be raised. | 83 | * be raised. |
| 84 | */ | 84 | */ |
| 85 | pmr = gic_read_pmr(); | 85 | pmr = gic_read_pmr(); |
| 86 | gic_write_pmr(GIC_PRIO_IRQON); | 86 | gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET); |
| 87 | 87 | ||
| 88 | __cpu_do_idle(); | 88 | __cpu_do_idle(); |
| 89 | 89 | ||
| @@ -1808,8 +1808,12 @@ static void tracehook_report_syscall(struct pt_regs *regs, · 1807 unmodified lines | |||
| 1808 | 1808 | ||
| 1809 | int syscall_trace_enter(struct pt_regs *regs) | 1809 | int syscall_trace_enter(struct pt_regs *regs) |
| 1810 | { | 1810 | { |
| 1811 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | 1811 | if (test_thread_flag(TIF_SYSCALL_TRACE) || |
| 1812 | test_thread_flag(TIF_SYSCALL_EMU)) { | ||
| 1812 | tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER); | 1813 | tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER); |
| 1814 | if (!in_syscall(regs) || test_thread_flag(TIF_SYSCALL_EMU)) | ||
| 1815 | return -1; | ||
| 1816 | } | ||
| 1813 | 1817 | ||
| 1814 | /* Do the secure computing after ptrace; failures should be fast. */ | 1818 | /* Do the secure computing after ptrace; failures should be fast. */ |
| 1815 | if (secure_computing(NULL) == -1) | 1819 | if (secure_computing(NULL) == -1) |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | * aff0 = mpidr_masked & 0xff; | 27 | * aff0 = mpidr_masked & 0xff; |
| 28 | * aff1 = mpidr_masked & 0xff00; | 28 | * aff1 = mpidr_masked & 0xff00; |
| 29 | * aff2 = mpidr_masked & 0xff0000; | 29 | * aff2 = mpidr_masked & 0xff0000; |
| 30 | * aff2 = mpidr_masked & 0xff00000000; | 30 | * aff3 = mpidr_masked & 0xff00000000; |
| 31 | * dst = (aff0 >> rs0 | aff1 >> rs1 | aff2 >> rs2 | aff3 >> rs3); | 31 | * dst = (aff0 >> rs0 | aff1 >> rs1 | aff2 >> rs2 | aff3 >> rs3); |
| 32 | *} | 32 | *} |
| 33 | * Input registers: rs0, rs1, rs2, rs3, mpidr, mask | 33 | * Input registers: rs0, rs1, rs2, rs3, mpidr, mask |
| @@ -181,11 +181,7 @@ static void init_gic_priority_masking(void) · 180 unmodified lines | |||
| 181 | 181 | ||
| 182 | WARN_ON(!(cpuflags & PSR_I_BIT)); | 182 | WARN_ON(!(cpuflags & PSR_I_BIT)); |
| 183 | 183 | ||
| 184 | gic_write_pmr(GIC_PRIO_IRQOFF); | 184 | gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET); |
| 185 | |||
| 186 | /* We can only unmask PSR.I if we can take aborts */ | ||
| 187 | if (!(cpuflags & PSR_A_BIT)) | ||
| 188 | write_sysreg(cpuflags & ~PSR_I_BIT, daif); | ||
| 189 | } | 185 | } |
| 190 | 186 | ||
| 191 | /* | 187 | /* |
| @@ -834,18 +830,23 @@ void arch_irq_work_raise(void) · 642 unmodified lines | |||
| 834 | } | 830 | } |
| 835 | #endif | 831 | #endif |
| 836 | 832 | ||
| 837 | /* | 833 | static void local_cpu_stop(void) |
| 838 | * ipi_cpu_stop - handle IPI from smp_send_stop() | ||
| 839 | */ | ||
| 840 | static void ipi_cpu_stop(unsigned int cpu) | ||
| 841 | { | 834 | { |
| 842 | set_cpu_online(cpu, false); | 835 | set_cpu_online(smp_processor_id(), false); |
| 843 | 836 | ||
| 844 | local_daif_mask(); | 837 | local_daif_mask(); |
| 845 | sdei_mask_local_cpu(); | 838 | sdei_mask_local_cpu(); |
| 839 | cpu_park_loop(); | ||
| 840 | } | ||
| 846 | 841 | ||
| 847 | while (1) | 842 | /* |
| 848 | cpu_relax(); | 843 | * We need to implement panic_smp_self_stop() for parallel panic() calls, so |
| 844 | * that cpu_online_mask gets correctly updated and smp_send_stop() can skip | ||
| 845 | * CPUs that have already stopped themselves. | ||
| 846 | */ | ||
| 847 | void panic_smp_self_stop(void) | ||
| 848 | { | ||
| 849 | local_cpu_stop(); | ||
| 849 | } | 850 | } |
| 850 | 851 | ||
| 851 | #ifdef CONFIG_KEXEC_CORE | 852 | #ifdef CONFIG_KEXEC_CORE |
| @@ -898,7 +899,7 @@ void handle_IPI(int ipinr, struct pt_regs *regs) · 46 unmodified lines | |||
| 898 | 899 | ||
| 899 | case IPI_CPU_STOP: | 900 | case IPI_CPU_STOP: |
| 900 | irq_enter(); | 901 | irq_enter(); |
| 901 | ipi_cpu_stop(cpu); | 902 | local_cpu_stop(); |
| 902 | irq_exit(); | 903 | irq_exit(); |
| 903 | break; | 904 | break; |
| 904 | 905 | ||
| @@ -55,16 +55,19 @@ static void dump_backtrace_entry(unsigned long where) · 54 unmodified lines | |||
| 55 | printk(" %pS\n", (void *)where); | 55 | printk(" %pS\n", (void *)where); |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | static void __dump_instr(const char *lvl, struct pt_regs *regs) | 58 | static void dump_kernel_instr(const char *lvl, struct pt_regs *regs) |
| 59 | { | 59 | { |
| 60 | unsigned long addr = instruction_pointer(regs); | 60 | unsigned long addr = instruction_pointer(regs); |
| 61 | char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str; | 61 | char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str; |
| 62 | int i; | 62 | int i; |
| 63 | 63 | ||
| 64 | if (user_mode(regs)) | ||
| 65 | return; | ||
| 66 | |||
| 64 | for (i = -4; i < 1; i++) { | 67 | for (i = -4; i < 1; i++) { |
| 65 | unsigned int val, bad; | 68 | unsigned int val, bad; |
| 66 | 69 | ||
| 67 | bad = get_user(val, &((u32 *)addr)[i]); | 70 | bad = aarch64_insn_read(&((u32 *)addr)[i], &val); |
| 68 | 71 | ||
| 69 | if (!bad) | 72 | if (!bad) |
| 70 | p += sprintf(p, i == 0 ? "(%08x) " : "%08x ", val); | 73 | p += sprintf(p, i == 0 ? "(%08x) " : "%08x ", val); |
| @@ -73,19 +76,8 @@ static void __dump_instr(const char *lvl, struct pt_regs *regs) · 2 unmodified lines | |||
| 73 | break; | 76 | break; |
| 74 | } | 77 | } |
| 75 | } | 78 | } |
| 76 | printk("%sCode: %s\n", lvl, str); | ||
| 77 | } | ||
| 78 | 79 | ||
| 79 | static void dump_instr(const char *lvl, struct pt_regs *regs) | 80 | printk("%sCode: %s\n", lvl, str); |
| 80 | { | ||
| 81 | if (!user_mode(regs)) { | ||
| 82 | mm_segment_t fs = get_fs(); | ||
| 83 | set_fs(KERNEL_DS); | ||
| 84 | __dump_instr(lvl, regs); | ||
| 85 | set_fs(fs); | ||
| 86 | } else { | ||
| 87 | __dump_instr(lvl, regs); | ||
| 88 | } | ||
| 89 | } | 81 | } |
| 90 | 82 | ||
| 91 | void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) | 83 | void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) |
| @@ -171,8 +163,7 @@ static int __die(const char *str, int err, struct pt_regs *regs) · 79 unmodified lines | |||
| 171 | print_modules(); | 163 | print_modules(); |
| 172 | show_regs(regs); | 164 | show_regs(regs); |
| 173 | 165 | ||
| 174 | if (!user_mode(regs)) | 166 | dump_kernel_instr(KERN_EMERG, regs); |
| 175 | dump_instr(KERN_EMERG, regs); | ||
| 176 | 167 | ||
| 177 | return ret; | 168 | return ret; |
| 178 | } | 169 | } |
| @@ -112,9 +112,7 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) · 111 unmodified lines | |||
| 112 | if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) { | 112 | if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) { |
| 113 | u64 *guest_zcr = &vcpu->arch.ctxt.sys_regs[ZCR_EL1]; | 113 | u64 *guest_zcr = &vcpu->arch.ctxt.sys_regs[ZCR_EL1]; |
| 114 | 114 | ||
| 115 | /* Clean guest FP state to memory and invalidate cpu view */ | 115 | fpsimd_save_and_flush_cpu_state(); |
| 116 | fpsimd_save(); | ||
| 117 | fpsimd_flush_cpu_state(); | ||
| 118 | 116 | ||
| 119 | if (guest_has_sve) | 117 | if (guest_has_sve) |
| 120 | *guest_zcr = read_sysreg_s(SYS_ZCR_EL12); | 118 | *guest_zcr = read_sysreg_s(SYS_ZCR_EL12); |
| @@ -604,7 +604,7 @@ int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu) · 603 unmodified lines | |||
| 604 | * Naturally, we want to avoid this. | 604 | * Naturally, we want to avoid this. |
| 605 | */ | 605 | */ |
| 606 | if (system_uses_irq_prio_masking()) { | 606 | if (system_uses_irq_prio_masking()) { |
| 607 | gic_write_pmr(GIC_PRIO_IRQON); | 607 | gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET); |
| 608 | dsb(sy); | 608 | dsb(sy); |
| 609 | } | 609 | } |
| 610 | 610 | ||
| @@ -80,10 +80,6 @@ static int __swiotlb_mmap_pfn(struct vm_area_struct *vma, · 79 unmodified lines | |||
| 80 | 80 | ||
| 81 | static int __init arm64_dma_init(void) | 81 | static int __init arm64_dma_init(void) |
| 82 | { | 82 | { |
| 83 | WARN_TAINT(ARCH_DMA_MINALIGN < cache_line_size(), | ||
| 84 | TAINT_CPU_OUT_OF_SPEC, | ||
| 85 | "ARCH_DMA_MINALIGN smaller than CTR_EL0.CWG (%d < %d)", | ||
| 86 | ARCH_DMA_MINALIGN, cache_line_size()); | ||
| 87 | return dma_atomic_pool_init(GFP_DMA32, __pgprot(PROT_NORMAL_NC)); | 83 | return dma_atomic_pool_init(GFP_DMA32, __pgprot(PROT_NORMAL_NC)); |
| 88 | } | 84 | } |
| 89 | arch_initcall(arm64_dma_init); | 85 | arch_initcall(arm64_dma_init); |
| @@ -461,6 +457,14 @@ static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, · 371 unmodified lines | |||
| 461 | void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, | 457 | void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, |
| 462 | const struct iommu_ops *iommu, bool coherent) | 458 | const struct iommu_ops *iommu, bool coherent) |
| 463 | { | 459 | { |
| 460 | int cls = cache_line_size_of_cpu(); | ||
| 461 | |||
| 462 | WARN_TAINT(!coherent && cls > ARCH_DMA_MINALIGN, | ||
| 463 | TAINT_CPU_OUT_OF_SPEC, | ||
| 464 | "%s %s: ARCH_DMA_MINALIGN smaller than CTR_EL0.CWG (%d < %d)", | ||
| 465 | dev_driver_string(dev), dev_name(dev), | ||
| 466 | ARCH_DMA_MINALIGN, cls); | ||
| 467 | |||
| 464 | dev->dma_coherent = coherent; | 468 | dev->dma_coherent = coherent; |
| 465 | __iommu_setup_dma_ops(dev, dma_base, size, iommu); | 469 | __iommu_setup_dma_ops(dev, dma_base, size, iommu); |
| 466 | 470 | ||
| @@ -384,40 +384,31 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re · 383 unmodified lines | |||
| 384 | #define VM_FAULT_BADACCESS 0x020000 | 384 | #define VM_FAULT_BADACCESS 0x020000 |
| 385 | 385 | ||
| 386 | static vm_fault_t __do_page_fault(struct mm_struct *mm, unsigned long addr, | 386 | static vm_fault_t __do_page_fault(struct mm_struct *mm, unsigned long addr, |
| 387 | unsigned int mm_flags, unsigned long vm_flags, | 387 | unsigned int mm_flags, unsigned long vm_flags) |
| 388 | struct task_struct *tsk) | ||
| 389 | { | 388 | { |
| 390 | struct vm_area_struct *vma; | 389 | struct vm_area_struct *vma = find_vma(mm, addr); |
| 391 | vm_fault_t fault; | ||
| 392 | 390 | ||
| 393 | vma = find_vma(mm, addr); | ||
| 394 | fault = VM_FAULT_BADMAP; | ||
| 395 | if (unlikely(!vma)) | 391 | if (unlikely(!vma)) |
| 396 | goto out; | 392 | return VM_FAULT_BADMAP; |
| 397 | if (unlikely(vma->vm_start > addr)) | ||
| 398 | goto check_stack; | ||
| 399 | 393 | ||
| 400 | /* | 394 | /* |
| 401 | * Ok, we have a good vm_area for this memory access, so we can handle | 395 | * Ok, we have a good vm_area for this memory access, so we can handle |
| 402 | * it. | 396 | * it. |
| 403 | */ | 397 | */ |
| 404 | good_area: | 398 | if (unlikely(vma->vm_start > addr)) { |
| 399 | if (!(vma->vm_flags & VM_GROWSDOWN)) | ||
| 400 | return VM_FAULT_BADMAP; | ||
| 401 | if (expand_stack(vma, addr)) | ||
| 402 | return VM_FAULT_BADMAP; | ||
| 403 | } | ||
| 404 | |||
| 405 | /* | 405 | /* |
| 406 | * Check that the permissions on the VMA allow for the fault which | 406 | * Check that the permissions on the VMA allow for the fault which |
| 407 | * occurred. | 407 | * occurred. |
| 408 | */ | 408 | */ |
| 409 | if (!(vma->vm_flags & vm_flags)) { | 409 | if (!(vma->vm_flags & vm_flags)) |
| 410 | fault = VM_FAULT_BADACCESS; | 410 | return VM_FAULT_BADACCESS; |
| 411 | goto out; | ||
| 412 | } | ||
| 413 | |||
| 414 | return handle_mm_fault(vma, addr & PAGE_MASK, mm_flags); | 411 | return handle_mm_fault(vma, addr & PAGE_MASK, mm_flags); |
| 415 | |||
| 416 | check_stack: | ||
| 417 | if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr)) | ||
| 418 | goto good_area; | ||
| 419 | out: | ||
| 420 | return fault; | ||
| 421 | } | 412 | } |
| 422 | 413 | ||
| 423 | static bool is_el0_instruction_abort(unsigned int esr) | 414 | static bool is_el0_instruction_abort(unsigned int esr) |
| @@ -425,12 +416,20 @@ static bool is_el0_instruction_abort(unsigned int esr) · 1 unmodified line | |||
| 425 | return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_LOW; | 416 | return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_LOW; |
| 426 | } | 417 | } |
| 427 | 418 | ||
| 419 | /* | ||
| 420 | * Note: not valid for EL1 DC IVAC, but we never use that such that it | ||
| 421 | * should fault. EL0 cannot issue DC IVAC (undef). | ||
| 422 | */ | ||
| 423 | static bool is_write_abort(unsigned int esr) | ||
| 424 | { | ||
| 425 | return (esr & ESR_ELx_WNR) && !(esr & ESR_ELx_CM); | ||
| 426 | } | ||
| 427 | |||
| 428 | static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, | 428 | static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, |
| 429 | struct pt_regs *regs) | 429 | struct pt_regs *regs) |
| 430 | { | 430 | { |
| 431 | const struct fault_info *inf; | 431 | const struct fault_info *inf; |
| 432 | struct task_struct *tsk; | 432 | struct mm_struct *mm = current->mm; |
| 433 | struct mm_struct *mm; | ||
| 434 | vm_fault_t fault, major = 0; | 433 | vm_fault_t fault, major = 0; |
| 435 | unsigned long vm_flags = VM_READ | VM_WRITE; | 434 | unsigned long vm_flags = VM_READ | VM_WRITE; |
| 436 | unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; | 435 | unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; |
| @@ -438,9 +437,6 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, · 1 unmodified line | |||
| 438 | if (notify_page_fault(regs, esr)) | 437 | if (notify_page_fault(regs, esr)) |
| 439 | return 0; | 438 | return 0; |
| 440 | 439 | ||
| 441 | tsk = current; | ||
| 442 | mm = tsk->mm; | ||
| 443 | |||
| 444 | /* | 440 | /* |
| 445 | * If we're in an interrupt or have no user context, we must not take | 441 | * If we're in an interrupt or have no user context, we must not take |
| 446 | * the fault. | 442 | * the fault. |
| @@ -453,7 +449,8 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, · 6 unmodified lines | |||
| 453 | 449 | ||
| 454 | if (is_el0_instruction_abort(esr)) { | 450 | if (is_el0_instruction_abort(esr)) { |
| 455 | vm_flags = VM_EXEC; | 451 | vm_flags = VM_EXEC; |
| 456 | } else if ((esr & ESR_ELx_WNR) && !(esr & ESR_ELx_CM)) { | 452 | mm_flags |= FAULT_FLAG_INSTRUCTION; |
| 453 | } else if (is_write_abort(esr)) { | ||
| 457 | vm_flags = VM_WRITE; | 454 | vm_flags = VM_WRITE; |
| 458 | mm_flags |= FAULT_FLAG_WRITE; | 455 | mm_flags |= FAULT_FLAG_WRITE; |
| 459 | } | 456 | } |
| @@ -492,12 +489,14 @@ retry: · 32 unmodified lines | |||
| 492 | */ | 489 | */ |
| 493 | might_sleep(); | 490 | might_sleep(); |
| 494 | #ifdef CONFIG_DEBUG_VM | 491 | #ifdef CONFIG_DEBUG_VM |
| 495 | if (!user_mode(regs) && !search_exception_tables(regs->pc)) | 492 | if (!user_mode(regs) && !search_exception_tables(regs->pc)) { |
| 493 | up_read(&mm->mmap_sem); | ||
| 496 | goto no_context; | 494 | goto no_context; |
| 495 | } | ||
| 497 | #endif | 496 | #endif |
| 498 | } | 497 | } |
| 499 | 498 | ||
| 500 | fault = __do_page_fault(mm, addr, mm_flags, vm_flags, tsk); | 499 | fault = __do_page_fault(mm, addr, mm_flags, vm_flags); |
| 501 | major |= fault & VM_FAULT_MAJOR; | 500 | major |= fault & VM_FAULT_MAJOR; |
| 502 | 501 | ||
| 503 | if (fault & VM_FAULT_RETRY) { | 502 | if (fault & VM_FAULT_RETRY) { |
| @@ -537,11 +536,11 @@ retry: · 33 unmodified lines | |||
| 537 | * that point. | 536 | * that point. |
| 538 | */ | 537 | */ |
| 539 | if (major) { | 538 | if (major) { |
| 540 | tsk->maj_flt++; | 539 | current->maj_flt++; |
| 541 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, | 540 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, |
| 542 | addr); | 541 | addr); |
| 543 | } else { | 542 | } else { |
| 544 | tsk->min_flt++; | 543 | current->min_flt++; |
| 545 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, | 544 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, |
| 546 | addr); | 545 | addr); |
| 547 | } | 546 | } |
| @@ -228,7 +228,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, · 227 unmodified lines | |||
| 228 | 228 | ||
| 229 | if (sz == PUD_SIZE) { | 229 | if (sz == PUD_SIZE) { |
| 230 | ptep = (pte_t *)pudp; | 230 | ptep = (pte_t *)pudp; |
| 231 | } else if (sz == (PAGE_SIZE * CONT_PTES)) { | 231 | } else if (sz == (CONT_PTE_SIZE)) { |
| 232 | pmdp = pmd_alloc(mm, pudp, addr); | 232 | pmdp = pmd_alloc(mm, pudp, addr); |
| 233 | 233 | ||
| 234 | WARN_ON(addr & (sz - 1)); | 234 | WARN_ON(addr & (sz - 1)); |
| @@ -246,7 +246,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, · 11 unmodified lines | |||
| 246 | ptep = huge_pmd_share(mm, addr, pudp); | 246 | ptep = huge_pmd_share(mm, addr, pudp); |
| 247 | else | 247 | else |
| 248 | ptep = (pte_t *)pmd_alloc(mm, pudp, addr); | 248 | ptep = (pte_t *)pmd_alloc(mm, pudp, addr); |
| 249 | } else if (sz == (PMD_SIZE * CONT_PMDS)) { | 249 | } else if (sz == (CONT_PMD_SIZE)) { |
| 250 | pmdp = pmd_alloc(mm, pudp, addr); | 250 | pmdp = pmd_alloc(mm, pudp, addr); |
| 251 | WARN_ON(addr & (sz - 1)); | 251 | WARN_ON(addr & (sz - 1)); |
| 252 | return (pte_t *)pmdp; | 252 | return (pte_t *)pmdp; |
| @@ -454,9 +454,9 @@ static int __init hugetlbpage_init(void) · 201 unmodified lines | |||
| 454 | #ifdef CONFIG_ARM64_4K_PAGES | 454 | #ifdef CONFIG_ARM64_4K_PAGES |
| 455 | add_huge_page_size(PUD_SIZE); | 455 | add_huge_page_size(PUD_SIZE); |
| 456 | #endif | 456 | #endif |
| 457 | add_huge_page_size(PMD_SIZE * CONT_PMDS); | 457 | add_huge_page_size(CONT_PMD_SIZE); |
| 458 | add_huge_page_size(PMD_SIZE); | 458 | add_huge_page_size(PMD_SIZE); |
| 459 | add_huge_page_size(PAGE_SIZE * CONT_PTES); | 459 | add_huge_page_size(CONT_PTE_SIZE); |
| 460 | 460 | ||
| 461 | return 0; | 461 | return 0; |
| 462 | } | 462 | } |
| @@ -470,9 +470,9 @@ static __init int setup_hugepagesz(char *opt) · 7 unmodified lines | |||
| 470 | #ifdef CONFIG_ARM64_4K_PAGES | 470 | #ifdef CONFIG_ARM64_4K_PAGES |
| 471 | case PUD_SIZE: | 471 | case PUD_SIZE: |
| 472 | #endif | 472 | #endif |
| 473 | case PMD_SIZE * CONT_PMDS: | 473 | case CONT_PMD_SIZE: |
| 474 | case PMD_SIZE: | 474 | case PMD_SIZE: |
| 475 | case PAGE_SIZE * CONT_PTES: | 475 | case CONT_PTE_SIZE: |
| 476 | add_huge_page_size(ps); | 476 | add_huge_page_size(ps); |
| 477 | return 1; | 477 | return 1; |
| 478 | } | 478 | } |
| @@ -180,8 +180,9 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max) · 179 unmodified lines | |||
| 180 | { | 180 | { |
| 181 | unsigned long max_zone_pfns[MAX_NR_ZONES] = {0}; | 181 | unsigned long max_zone_pfns[MAX_NR_ZONES] = {0}; |
| 182 | 182 | ||
| 183 | if (IS_ENABLED(CONFIG_ZONE_DMA32)) | 183 | #ifdef CONFIG_ZONE_DMA32 |
| 184 | max_zone_pfns[ZONE_DMA32] = PFN_DOWN(max_zone_dma_phys()); | 184 | max_zone_pfns[ZONE_DMA32] = PFN_DOWN(max_zone_dma_phys()); |
| 185 | #endif | ||
| 185 | max_zone_pfns[ZONE_NORMAL] = max; | 186 | max_zone_pfns[ZONE_NORMAL] = max; |
| 186 | 187 | ||
| 187 | free_area_init_nodes(max_zone_pfns); | 188 | free_area_init_nodes(max_zone_pfns); |
| @@ -765,7 +765,7 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node, · 764 unmodified lines | |||
| 765 | 765 | ||
| 766 | return 0; | 766 | return 0; |
| 767 | } | 767 | } |
| 768 | #endif /* CONFIG_ARM64_64K_PAGES */ | 768 | #endif /* !ARM64_SWAPPER_USES_SECTION_MAPS */ |
| 769 | void vmemmap_free(unsigned long start, unsigned long end, | 769 | void vmemmap_free(unsigned long start, unsigned long end, |
| 770 | struct vmem_altmap *altmap) | 770 | struct vmem_altmap *altmap) |
| 771 | { | 771 | { |
| @@ -960,32 +960,28 @@ int __init arch_ioremap_pmd_supported(void) · 188 unmodified lines | |||
| 960 | 960 | ||
| 961 | int pud_set_huge(pud_t *pudp, phys_addr_t phys, pgprot_t prot) | 961 | int pud_set_huge(pud_t *pudp, phys_addr_t phys, pgprot_t prot) |
| 962 | { | 962 | { |
| 963 | pgprot_t sect_prot = __pgprot(PUD_TYPE_SECT | | 963 | pud_t new_pud = pfn_pud(__phys_to_pfn(phys), mk_pud_sect_prot(prot)); |
| 964 | pgprot_val(mk_sect_prot(prot))); | ||
| 965 | pud_t new_pud = pfn_pud(__phys_to_pfn(phys), sect_prot); | ||
| 966 | 964 | ||
| 967 | /* Only allow permission changes for now */ | 965 | /* Only allow permission changes for now */ |
| 968 | if (!pgattr_change_is_safe(READ_ONCE(pud_val(*pudp)), | 966 | if (!pgattr_change_is_safe(READ_ONCE(pud_val(*pudp)), |
| 969 | pud_val(new_pud))) | 967 | pud_val(new_pud))) |
| 970 | return 0; | 968 | return 0; |
| 971 | 969 | ||
| 972 | BUG_ON(phys & ~PUD_MASK); | 970 | VM_BUG_ON(phys & ~PUD_MASK); |
| 973 | set_pud(pudp, new_pud); | 971 | set_pud(pudp, new_pud); |
| 974 | return 1; | 972 | return 1; |
| 975 | } | 973 | } |
| 976 | 974 | ||
| 977 | int pmd_set_huge(pmd_t *pmdp, phys_addr_t phys, pgprot_t prot) | 975 | int pmd_set_huge(pmd_t *pmdp, phys_addr_t phys, pgprot_t prot) |
| 978 | { | 976 | { |
| 979 | pgprot_t sect_prot = __pgprot(PMD_TYPE_SECT | | 977 | pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), mk_pmd_sect_prot(prot)); |
| 980 | pgprot_val(mk_sect_prot(prot))); | ||
| 981 | pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), sect_prot); | ||
| 982 | 978 | ||
| 983 | /* Only allow permission changes for now */ | 979 | /* Only allow permission changes for now */ |
| 984 | if (!pgattr_change_is_safe(READ_ONCE(pmd_val(*pmdp)), | 980 | if (!pgattr_change_is_safe(READ_ONCE(pmd_val(*pmdp)), |
| 985 | pmd_val(new_pmd))) | 981 | pmd_val(new_pmd))) |
| 986 | return 0; | 982 | return 0; |
| 987 | 983 | ||
| 988 | BUG_ON(phys & ~PMD_MASK); | 984 | VM_BUG_ON(phys & ~PMD_MASK); |
| 989 | set_pmd(pmdp, new_pmd); | 985 | set_pmd(pmdp, new_pmd); |
| 990 | return 1; | 986 | return 1; |
| 991 | } | 987 | } |
| @@ -151,17 +151,48 @@ int set_memory_valid(unsigned long addr, int numpages, int enable) · 150 unmodified lines | |||
| 151 | __pgprot(PTE_VALID)); | 151 | __pgprot(PTE_VALID)); |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | #ifdef CONFIG_DEBUG_PAGEALLOC | 154 | int set_direct_map_invalid_noflush(struct page *page) |
| 155 | { | ||
| 156 | struct page_change_data data = { | ||
| 157 | .set_mask = __pgprot(0), | ||
| 158 | .clear_mask = __pgprot(PTE_VALID), | ||
| 159 | }; | ||
| 160 | |||
| 161 | if (!rodata_full) | ||
| 162 | return 0; | ||
| 163 | |||
| 164 | return apply_to_page_range(&init_mm, | ||
| 165 | (unsigned long)page_address(page), | ||
| 166 | PAGE_SIZE, change_page_range, &data); | ||
| 167 | } | ||
| 168 | |||
| 169 | int set_direct_map_default_noflush(struct page *page) | ||
| 170 | { | ||
| 171 | struct page_change_data data = { | ||
| 172 | .set_mask = __pgprot(PTE_VALID | PTE_WRITE), | ||
| 173 | .clear_mask = __pgprot(PTE_RDONLY), | ||
| 174 | }; | ||
| 175 | |||
| 176 | if (!rodata_full) | ||
| 177 | return 0; | ||
| 178 | |||
| 179 | return apply_to_page_range(&init_mm, | ||
| 180 | (unsigned long)page_address(page), | ||
| 181 | PAGE_SIZE, change_page_range, &data); | ||
| 182 | } | ||
| 183 | |||
| 155 | void __kernel_map_pages(struct page *page, int numpages, int enable) | 184 | void __kernel_map_pages(struct page *page, int numpages, int enable) |
| 156 | { | 185 | { |
| 186 | if (!debug_pagealloc_enabled() && !rodata_full) | ||
| 187 | return; | ||
| 188 | |||
| 157 | set_memory_valid((unsigned long)page_address(page), numpages, enable); | 189 | set_memory_valid((unsigned long)page_address(page), numpages, enable); |
| 158 | } | 190 | } |
| 159 | #ifdef CONFIG_HIBERNATION | 191 | |
| 160 | /* | 192 | /* |
| 161 | * When built with CONFIG_DEBUG_PAGEALLOC and CONFIG_HIBERNATION, this function | 193 | * This function is used to determine if a linear map page has been marked as |
| 162 | * is used to determine if a linear map page has been marked as not-valid by | 194 | * not-valid. Walk the page table and check the PTE_VALID bit. This is based |
| 163 | * CONFIG_DEBUG_PAGEALLOC. Walk the page table and check the PTE_VALID bit. | 195 | * on kern_addr_valid(), which almost does what we need. |
| 164 | * This is based on kern_addr_valid(), which almost does what we need. | ||
| 165 | * | 196 | * |
| 166 | * Because this is only called on the kernel linear map, p?d_sect() implies | 197 | * Because this is only called on the kernel linear map, p?d_sect() implies |
| 167 | * p?d_present(). When debug_pagealloc is enabled, sections mappings are | 198 | * p?d_present(). When debug_pagealloc is enabled, sections mappings are |
| @@ -175,6 +206,9 @@ bool kernel_page_present(struct page *page) · 7 unmodified lines | |||
| 175 | pte_t *ptep; | 206 | pte_t *ptep; |
| 176 | unsigned long addr = (unsigned long)page_address(page); | 207 | unsigned long addr = (unsigned long)page_address(page); |
| 177 | 208 | ||
| 209 | if (!debug_pagealloc_enabled() && !rodata_full) | ||
| 210 | return true; | ||
| 211 | |||
| 178 | pgdp = pgd_offset_k(addr); | 212 | pgdp = pgd_offset_k(addr); |
| 179 | if (pgd_none(READ_ONCE(*pgdp))) | 213 | if (pgd_none(READ_ONCE(*pgdp))) |
| 180 | return false; | 214 | return false; |
| @@ -196,5 +230,3 @@ bool kernel_page_present(struct page *page) · 15 unmodified lines | |||
| 196 | ptep = pte_offset_kernel(pmdp, addr); | 230 | ptep = pte_offset_kernel(pmdp, addr); |
| 197 | return pte_valid(READ_ONCE(*ptep)); | 231 | return pte_valid(READ_ONCE(*ptep)); |
| 198 | } | 232 | } |
| 199 | #endif /* CONFIG_HIBERNATION */ | ||
| 200 | #endif /* CONFIG_DEBUG_PAGEALLOC */ | ||
| @@ -970,7 +970,7 @@ void *bpf_jit_alloc_exec(unsigned long size) · 969 unmodified lines | |||
| 970 | { | 970 | { |
| 971 | return __vmalloc_node_range(size, PAGE_SIZE, BPF_JIT_REGION_START, | 971 | return __vmalloc_node_range(size, PAGE_SIZE, BPF_JIT_REGION_START, |
| 972 | BPF_JIT_REGION_END, GFP_KERNEL, | 972 | BPF_JIT_REGION_END, GFP_KERNEL, |
| 973 | PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, | 973 | PAGE_KERNEL, 0, NUMA_NO_NODE, |
| 974 | __builtin_return_address(0)); | 974 | __builtin_return_address(0)); |
| 975 | } | 975 | } |
| 976 | 976 | ||
| @@ -2521,7 +2521,6 @@ void ptrace_disable(struct task_struct *child) · 2520 unmodified lines | |||
| 2521 | { | 2521 | { |
| 2522 | /* make sure the single step bit is not set. */ | 2522 | /* make sure the single step bit is not set. */ |
| 2523 | user_disable_single_step(child); | 2523 | user_disable_single_step(child); |
| 2524 | clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); | ||
| 2525 | } | 2524 | } |
| 2526 | 2525 | ||
| 2527 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 2526 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
| @@ -72,23 +72,18 @@ static long syscall_trace_enter(struct pt_regs *regs) · 71 unmodified lines | |||
| 72 | 72 | ||
| 73 | struct thread_info *ti = current_thread_info(); | 73 | struct thread_info *ti = current_thread_info(); |
| 74 | unsigned long ret = 0; | 74 | unsigned long ret = 0; |
| 75 | bool emulated = false; | ||
| 76 | u32 work; | 75 | u32 work; |
| 77 | 76 | ||
| 78 | if (IS_ENABLED(CONFIG_DEBUG_ENTRY)) | 77 | if (IS_ENABLED(CONFIG_DEBUG_ENTRY)) |
| 79 | BUG_ON(regs != task_pt_regs(current)); | 78 | BUG_ON(regs != task_pt_regs(current)); |
| 80 | 79 | ||
| 81 | work = READ_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY; | 80 | work = READ_ONCE(ti->flags); |
| 82 | 81 | ||
| 83 | if (unlikely(work & _TIF_SYSCALL_EMU)) | 82 | if (work & (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_EMU)) { |
| 84 | emulated = true; | 83 | ret = tracehook_report_syscall_entry(regs); |
| 85 | 84 | if (ret || (work & _TIF_SYSCALL_EMU)) | |
| 86 | if ((emulated || (work & _TIF_SYSCALL_TRACE)) && | 85 | return -1L; |
| 87 | tracehook_report_syscall_entry(regs)) | 86 | } |
| 88 | return -1L; | ||
| 89 | |||
| 90 | if (emulated) | ||
| 91 | return -1L; | ||
| 92 | 87 | ||
| 93 | #ifdef CONFIG_SECCOMP | 88 | #ifdef CONFIG_SECCOMP |
| 94 | /* | 89 | /* |
| @@ -747,9 +747,6 @@ static int ioperm_get(struct task_struct *target, · 746 unmodified lines | |||
| 747 | void ptrace_disable(struct task_struct *child) | 747 | void ptrace_disable(struct task_struct *child) |
| 748 | { | 748 | { |
| 749 | user_disable_single_step(child); | 749 | user_disable_single_step(child); |
| 750 | #ifdef TIF_SYSCALL_EMU | ||
| 751 | clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); | ||
| 752 | #endif | ||
| 753 | } | 750 | } |
| 754 | 751 | ||
| 755 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION | 752 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION |
| @@ -432,17 +432,40 @@ static void cache_setup_acpi_cpu(struct acpi_table_header *table, · 431 unmodified lines | |||
| 432 | } | 432 | } |
| 433 | } | 433 | } |
| 434 | 434 | ||
| 435 | static bool flag_identical(struct acpi_table_header *table_hdr, | ||
| 436 | struct acpi_pptt_processor *cpu) | ||
| 437 | { | ||
| 438 | struct acpi_pptt_processor *next; | ||
| 439 | |||
| 440 | /* heterogeneous machines must use PPTT revision > 1 */ | ||
| 441 | if (table_hdr->revision < 2) | ||
| 442 | return false; | ||
| 443 | |||
| 444 | /* Locate the last node in the tree with IDENTICAL set */ | ||
| 445 | if (cpu->flags & ACPI_PPTT_ACPI_IDENTICAL) { | ||
| 446 | next = fetch_pptt_node(table_hdr, cpu->parent); | ||
| 447 | if (!(next && next->flags & ACPI_PPTT_ACPI_IDENTICAL)) | ||
| 448 | return true; | ||
| 449 | } | ||
| 450 | |||
| 451 | return false; | ||
| 452 | } | ||
| 453 | |||
| 435 | /* Passing level values greater than this will result in search termination */ | 454 | /* Passing level values greater than this will result in search termination */ |
| 436 | #define PPTT_ABORT_PACKAGE 0xFF | 455 | #define PPTT_ABORT_PACKAGE 0xFF |
| 437 | 456 | ||
| 438 | static struct acpi_pptt_processor *acpi_find_processor_package_id(struct acpi_table_header *table_hdr, | 457 | static struct acpi_pptt_processor *acpi_find_processor_tag(struct acpi_table_header *table_hdr, |
| 439 | struct acpi_pptt_processor *cpu, | 458 | struct acpi_pptt_processor *cpu, |
| 440 | int level, int flag) | 459 | int level, int flag) |
| 441 | { | 460 | { |
| 442 | struct acpi_pptt_processor *prev_node; | 461 | struct acpi_pptt_processor *prev_node; |
| 443 | 462 | ||
| 444 | while (cpu && level) { | 463 | while (cpu && level) { |
| 445 | if (cpu->flags & flag) | 464 | /* special case the identical flag to find last identical */ |
| 465 | if (flag == ACPI_PPTT_ACPI_IDENTICAL) { | ||
| 466 | if (flag_identical(table_hdr, cpu)) | ||
| 467 | break; | ||
| 468 | } else if (cpu->flags & flag) | ||
| 446 | break; | 469 | break; |
| 447 | pr_debug("level %d\n", level); | 470 | pr_debug("level %d\n", level); |
| 448 | prev_node = fetch_pptt_node(table_hdr, cpu->parent); | 471 | prev_node = fetch_pptt_node(table_hdr, cpu->parent); |
| @@ -480,8 +503,8 @@ static int topology_get_acpi_cpu_tag(struct acpi_table_header *table, · 31 unmodified lines | |||
| 480 | 503 | ||
| 481 | cpu_node = acpi_find_processor_node(table, acpi_cpu_id); | 504 | cpu_node = acpi_find_processor_node(table, acpi_cpu_id); |
| 482 | if (cpu_node) { | 505 | if (cpu_node) { |
| 483 | cpu_node = acpi_find_processor_package_id(table, cpu_node, | 506 | cpu_node = acpi_find_processor_tag(table, cpu_node, |
| 484 | level, flag); | 507 | level, flag); |
| 485 | /* | 508 | /* |
| 486 | * As per specification if the processor structure represents | 509 | * As per specification if the processor structure represents |
| 487 | * an actual processor, then ACPI processor ID must be valid. | 510 | * an actual processor, then ACPI processor ID must be valid. |
| @@ -660,3 +683,29 @@ int find_acpi_cpu_topology_package(unsigned int cpu) · 172 unmodified lines | |||
| 660 | return find_acpi_cpu_topology_tag(cpu, PPTT_ABORT_PACKAGE, | 683 | return find_acpi_cpu_topology_tag(cpu, PPTT_ABORT_PACKAGE, |
| 661 | ACPI_PPTT_PHYSICAL_PACKAGE); | 684 | ACPI_PPTT_PHYSICAL_PACKAGE); |
| 662 | } | 685 | } |
| 686 | |||
| 687 | /** | ||
| 688 | * find_acpi_cpu_topology_hetero_id() - Get a core architecture tag | ||
| 689 | * @cpu: Kernel logical CPU number | ||
| 690 | * | ||
| 691 | * Determine a unique heterogeneous tag for the given CPU. CPUs with the same | ||
| 692 | * implementation should have matching tags. | ||
| 693 | * | ||
| 694 | * The returned tag can be used to group peers with identical implementation. | ||
| 695 | * | ||
| 696 | * The search terminates when a level is found with the identical implementation | ||
| 697 | * flag set or we reach a root node. | ||
| 698 | * | ||
| 699 | * Due to limitations in the PPTT data structure, there may be rare situations | ||
| 700 | * where two cores in a heterogeneous machine may be identical, but won't have | ||
| 701 | * the same tag. | ||
| 702 | * | ||
| 703 | * Return: -ENOENT if the PPTT doesn't exist, or the CPU cannot be found. | ||
| 704 | * Otherwise returns a value which represents a group of identical cores | ||
| 705 | * similar to this CPU. | ||
| 706 | */ | ||
| 707 | int find_acpi_cpu_topology_hetero_id(unsigned int cpu) | ||
| 708 | { | ||
| 709 | return find_acpi_cpu_topology_tag(cpu, PPTT_ABORT_PACKAGE, | ||
| 710 | ACPI_PPTT_ACPI_IDENTICAL); | ||
| 711 | } | ||
| @@ -213,6 +213,8 @@ int __weak cache_setup_acpi(unsigned int cpu) · 212 unmodified lines | |||
| 213 | return -ENOTSUPP; | 213 | return -ENOTSUPP; |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | unsigned int coherency_max_size; | ||
| 217 | |||
| 216 | static int cache_shared_cpu_map_setup(unsigned int cpu) | 218 | static int cache_shared_cpu_map_setup(unsigned int cpu) |
| 217 | { | 219 | { |
| 218 | struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); | 220 | struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); |
| @@ -251,6 +253,9 @@ static int cache_shared_cpu_map_setup(unsigned int cpu) · 32 unmodified lines | |||
| 251 | cpumask_set_cpu(i, &this_leaf->shared_cpu_map); | 253 | cpumask_set_cpu(i, &this_leaf->shared_cpu_map); |
| 252 | } | 254 | } |
| 253 | } | 255 | } |
| 256 | /* record the maximum cache line size */ | ||
| 257 | if (this_leaf->coherency_line_size > coherency_max_size) | ||
| 258 | coherency_max_size = this_leaf->coherency_line_size; | ||
| 254 | } | 259 | } |
| 255 | 260 | ||
| 256 | return 0; | 261 | return 0; |
| @@ -461,8 +461,12 @@ static void gic_deactivate_unhandled(u32 irqnr) · 460 unmodified lines | |||
| 461 | 461 | ||
| 462 | static inline void gic_handle_nmi(u32 irqnr, struct pt_regs *regs) | 462 | static inline void gic_handle_nmi(u32 irqnr, struct pt_regs *regs) |
| 463 | { | 463 | { |
| 464 | bool irqs_enabled = interrupts_enabled(regs); | ||
| 464 | int err; | 465 | int err; |
| 465 | 466 | ||
| 467 | if (irqs_enabled) | ||
| 468 | nmi_enter(); | ||
| 469 | |||
| 466 | if (static_branch_likely(&supports_deactivate_key)) | 470 | if (static_branch_likely(&supports_deactivate_key)) |
| 467 | gic_write_eoir(irqnr); | 471 | gic_write_eoir(irqnr); |
| 468 | /* | 472 | /* |
| @@ -474,6 +478,9 @@ static inline void gic_handle_nmi(u32 irqnr, struct pt_regs *regs) · 5 unmodified lines | |||
| 474 | err = handle_domain_nmi(gic_data.domain, irqnr, regs); | 478 | err = handle_domain_nmi(gic_data.domain, irqnr, regs); |
| 475 | if (err) | 479 | if (err) |
| 476 | gic_deactivate_unhandled(irqnr); | 480 | gic_deactivate_unhandled(irqnr); |
| 481 | |||
| 482 | if (irqs_enabled) | ||
| 483 | nmi_exit(); | ||
| 477 | } | 484 | } |
| 478 | 485 | ||
| 479 | static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) | 486 | static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) |
| @@ -71,6 +71,14 @@ config ARM_DSU_PMU · 70 unmodified lines | |||
| 71 | system, control logic. The PMU allows counting various events related | 71 | system, control logic. The PMU allows counting various events related |
| 72 | to DSU. | 72 | to DSU. |
| 73 | 73 | ||
| 74 | config FSL_IMX8_DDR_PMU | ||
| 75 | tristate "Freescale i.MX8 DDR perf monitor" | ||
| 76 | depends on ARCH_MXC | ||
| 77 | help | ||
| 78 | Provides support for the DDR performance monitor in i.MX8, which | ||
| 79 | can give information about memory throughput and other related | ||
| 80 | events. | ||
| 81 | |||
| 74 | config HISI_PMU | 82 | config HISI_PMU |
| 75 | bool "HiSilicon SoC PMU" | 83 | bool "HiSilicon SoC PMU" |
| 76 | depends on ARM64 && ACPI | 84 | depends on ARM64 && ACPI |
| @@ -5,6 +5,7 @@ obj-$(CONFIG_ARM_DSU_PMU) += arm_dsu_pmu.o · 4 unmodified lines | |||
| 5 | obj-$(CONFIG_ARM_PMU) += arm_pmu.o arm_pmu_platform.o | 5 | obj-$(CONFIG_ARM_PMU) += arm_pmu.o arm_pmu_platform.o |
| 6 | obj-$(CONFIG_ARM_PMU_ACPI) += arm_pmu_acpi.o | 6 | obj-$(CONFIG_ARM_PMU_ACPI) += arm_pmu_acpi.o |
| 7 | obj-$(CONFIG_ARM_SMMU_V3_PMU) += arm_smmuv3_pmu.o | 7 | obj-$(CONFIG_ARM_SMMU_V3_PMU) += arm_smmuv3_pmu.o |
| 8 | obj-$(CONFIG_FSL_IMX8_DDR_PMU) += fsl_imx8_ddr_perf.o | ||
| 8 | obj-$(CONFIG_HISI_PMU) += hisilicon/ | 9 | obj-$(CONFIG_HISI_PMU) += hisilicon/ |
| 9 | obj-$(CONFIG_QCOM_L2_PMU) += qcom_l2_pmu.o | 10 | obj-$(CONFIG_QCOM_L2_PMU) += qcom_l2_pmu.o |
| 10 | obj-$(CONFIG_QCOM_L3_PMU) += qcom_l3_pmu.o | 11 | obj-$(CONFIG_QCOM_L3_PMU) += qcom_l3_pmu.o |
| @@ -71,6 +71,76 @@ static void arm_pmu_acpi_unregister_irq(int cpu) · 70 unmodified lines | |||
| 71 | acpi_unregister_gsi(gsi); | 71 | acpi_unregister_gsi(gsi); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | #if IS_ENABLED(CONFIG_ARM_SPE_PMU) | ||
| 75 | static struct resource spe_resources[] = { | ||
| 76 | { | ||
| 77 | /* irq */ | ||
| 78 | .flags = IORESOURCE_IRQ, | ||
| 79 | } | ||
| 80 | }; | ||
| 81 | |||
| 82 | static struct platform_device spe_dev = { | ||
| 83 | .name = ARMV8_SPE_PDEV_NAME, | ||
| 84 | .id = -1, | ||
| 85 | .resource = spe_resources, | ||
| 86 | .num_resources = ARRAY_SIZE(spe_resources) | ||
| 87 | }; | ||
| 88 | |||
| 89 | /* | ||
| 90 | * For lack of a better place, hook the normal PMU MADT walk | ||
| 91 | * and create a SPE device if we detect a recent MADT with | ||
| 92 | * a homogeneous PPI mapping. | ||
| 93 | */ | ||
| 94 | static void arm_spe_acpi_register_device(void) | ||
| 95 | { | ||
| 96 | int cpu, hetid, irq, ret; | ||
| 97 | bool first = true; | ||
| 98 | u16 gsi = 0; | ||
| 99 | |||
| 100 | /* | ||
| 101 | * Sanity check all the GICC tables for the same interrupt number. | ||
| 102 | * For now, we only support homogeneous ACPI/SPE machines. | ||
| 103 | */ | ||
| 104 | for_each_possible_cpu(cpu) { | ||
| 105 | struct acpi_madt_generic_interrupt *gicc; | ||
| 106 | |||
| 107 | gicc = acpi_cpu_get_madt_gicc(cpu); | ||
| 108 | if (gicc->header.length < ACPI_MADT_GICC_SPE) | ||
| 109 | return; | ||
| 110 | |||
| 111 | if (first) { | ||
| 112 | gsi = gicc->spe_interrupt; | ||
| 113 | if (!gsi) | ||
| 114 | return; | ||
| 115 | hetid = find_acpi_cpu_topology_hetero_id(cpu); | ||
| 116 | first = false; | ||
| 117 | } else if ((gsi != gicc->spe_interrupt) || | ||
| 118 | (hetid != find_acpi_cpu_topology_hetero_id(cpu))) { | ||
| 119 | pr_warn("ACPI: SPE must be homogeneous\n"); | ||
| 120 | return; | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | irq = acpi_register_gsi(NULL, gsi, ACPI_LEVEL_SENSITIVE, | ||
| 125 | ACPI_ACTIVE_HIGH); | ||
| 126 | if (irq < 0) { | ||
| 127 | pr_warn("ACPI: SPE Unable to register interrupt: %d\n", gsi); | ||
| 128 | return; | ||
| 129 | } | ||
| 130 | |||
| 131 | spe_resources[0].start = irq; | ||
| 132 | ret = platform_device_register(&spe_dev); | ||
| 133 | if (ret < 0) { | ||
| 134 | pr_warn("ACPI: SPE: Unable to register device\n"); | ||
| 135 | acpi_unregister_gsi(gsi); | ||
| 136 | } | ||
| 137 | } | ||
| 138 | #else | ||
| 139 | static inline void arm_spe_acpi_register_device(void) | ||
| 140 | { | ||
| 141 | } | ||
| 142 | #endif /* CONFIG_ARM_SPE_PMU */ | ||
| 143 | |||
| 74 | static int arm_pmu_acpi_parse_irqs(void) | 144 | static int arm_pmu_acpi_parse_irqs(void) |
| 75 | { | 145 | { |
| 76 | int irq, cpu, irq_cpu, err; | 146 | int irq, cpu, irq_cpu, err; |
| @@ -276,6 +346,8 @@ static int arm_pmu_acpi_init(void) · 199 unmodified lines | |||
| 276 | if (acpi_disabled) | 346 | if (acpi_disabled) |
| 277 | return 0; | 347 | return 0; |
| 278 | 348 | ||
| 349 | arm_spe_acpi_register_device(); | ||
| 350 | |||
| 279 | ret = arm_pmu_acpi_parse_irqs(); | 351 | ret = arm_pmu_acpi_parse_irqs(); |
| 280 | if (ret) | 352 | if (ret) |
| 281 | return ret; | 353 | return ret; |
| @@ -27,6 +27,7 @@ · 26 unmodified lines | |||
| 27 | #include <linux/of_address.h> | 27 | #include <linux/of_address.h> |
| 28 | #include <linux/of_device.h> | 28 | #include <linux/of_device.h> |
| 29 | #include <linux/perf_event.h> | 29 | #include <linux/perf_event.h> |
| 30 | #include <linux/perf/arm_pmu.h> | ||
| 30 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
| 31 | #include <linux/printk.h> | 32 | #include <linux/printk.h> |
| 32 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
| @@ -1157,7 +1158,13 @@ static const struct of_device_id arm_spe_pmu_of_match[] = { · 1124 unmodified lines | |||
| 1157 | }; | 1158 | }; |
| 1158 | MODULE_DEVICE_TABLE(of, arm_spe_pmu_of_match); | 1159 | MODULE_DEVICE_TABLE(of, arm_spe_pmu_of_match); |
| 1159 | 1160 | ||
| 1160 | static int arm_spe_pmu_device_dt_probe(struct platform_device *pdev) | 1161 | static const struct platform_device_id arm_spe_match[] = { |
| 1162 | { ARMV8_SPE_PDEV_NAME, 0}, | ||
| 1163 | { } | ||
| 1164 | }; | ||
| 1165 | MODULE_DEVICE_TABLE(platform, arm_spe_match); | ||
| 1166 | |||
| 1167 | static int arm_spe_pmu_device_probe(struct platform_device *pdev) | ||
| 1161 | { | 1168 | { |
| 1162 | int ret; | 1169 | int ret; |
| 1163 | struct arm_spe_pmu *spe_pmu; | 1170 | struct arm_spe_pmu *spe_pmu; |
| @@ -1217,11 +1224,12 @@ static int arm_spe_pmu_device_remove(struct platform_device *pdev) · 53 unmodified lines | |||
| 1217 | } | 1224 | } |
| 1218 | 1225 | ||
| 1219 | static struct platform_driver arm_spe_pmu_driver = { | 1226 | static struct platform_driver arm_spe_pmu_driver = { |
| 1227 | .id_table = arm_spe_match, | ||
| 1220 | .driver = { | 1228 | .driver = { |
| 1221 | .name = DRVNAME, | 1229 | .name = DRVNAME, |
| 1222 | .of_match_table = of_match_ptr(arm_spe_pmu_of_match), | 1230 | .of_match_table = of_match_ptr(arm_spe_pmu_of_match), |
| 1223 | }, | 1231 | }, |
| 1224 | .probe = arm_spe_pmu_device_dt_probe, | 1232 | .probe = arm_spe_pmu_device_probe, |
| 1225 | .remove = arm_spe_pmu_device_remove, | 1233 | .remove = arm_spe_pmu_device_remove, |
| 1226 | }; | 1234 | }; |
| 1227 | 1235 | ||
| @@ -0,0 +1,554 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Copyright 2017 NXP | ||
| 4 | * Copyright 2016 Freescale Semiconductor, Inc. | ||
| 5 | */ | ||
| 6 | |||
| 7 | #include <linux/bitfield.h> | ||
| 8 | #include <linux/init.h> | ||
| 9 | #include <linux/interrupt.h> | ||
| 10 | #include <linux/io.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/of.h> | ||
| 13 | #include <linux/of_address.h> | ||
| 14 | #include <linux/of_device.h> | ||
| 15 | #include <linux/of_irq.h> | ||
| 16 | #include <linux/perf_event.h> | ||
| 17 | #include <linux/slab.h> | ||
| 18 | |||
| 19 | #define COUNTER_CNTL 0x0 | ||
| 20 | #define COUNTER_READ 0x20 | ||
| 21 | |||
| 22 | #define COUNTER_DPCR1 0x30 | ||
| 23 | |||
| 24 | #define CNTL_OVER 0x1 | ||
| 25 | #define CNTL_CLEAR 0x2 | ||
| 26 | #define CNTL_EN 0x4 | ||
| 27 | #define CNTL_EN_MASK 0xFFFFFFFB | ||
| 28 | #define CNTL_CLEAR_MASK 0xFFFFFFFD | ||
| 29 | #define CNTL_OVER_MASK 0xFFFFFFFE | ||
| 30 | |||
| 31 | #define CNTL_CSV_SHIFT 24 | ||
| 32 | #define CNTL_CSV_MASK (0xFF << CNTL_CSV_SHIFT) | ||
| 33 | |||
| 34 | #define EVENT_CYCLES_ID 0 | ||
| 35 | #define EVENT_CYCLES_COUNTER 0 | ||
| 36 | #define NUM_COUNTERS 4 | ||
| 37 | |||
| 38 | #define to_ddr_pmu(p) container_of(p, struct ddr_pmu, pmu) | ||
| 39 | |||
| 40 | #define DDR_PERF_DEV_NAME "imx8_ddr" | ||
| 41 | #define DDR_CPUHP_CB_NAME DDR_PERF_DEV_NAME "_perf_pmu" | ||
| 42 | |||
| 43 | static DEFINE_IDA(ddr_ida); | ||
| 44 | |||
| 45 | static const struct of_device_id imx_ddr_pmu_dt_ids[] = { | ||
| 46 | { .compatible = "fsl,imx8-ddr-pmu",}, | ||
| 47 | { .compatible = "fsl,imx8m-ddr-pmu",}, | ||
| 48 | { /* sentinel */ } | ||
| 49 | }; | ||
| 50 | |||
| 51 | struct ddr_pmu { | ||
| 52 | struct pmu pmu; | ||
| 53 | void __iomem *base; | ||
| 54 | unsigned int cpu; | ||
| 55 | struct hlist_node node; | ||
| 56 | struct device *dev; | ||
| 57 | struct perf_event *events[NUM_COUNTERS]; | ||
| 58 | int active_events; | ||
| 59 | enum cpuhp_state cpuhp_state; | ||
| 60 | int irq; | ||
| 61 | int id; | ||
| 62 | }; | ||
| 63 | |||
| 64 | static ssize_t ddr_perf_cpumask_show(struct device *dev, | ||
| 65 | struct device_attribute *attr, char *buf) | ||
| 66 | { | ||
| 67 | struct ddr_pmu *pmu = dev_get_drvdata(dev); | ||
| 68 | |||
| 69 | return cpumap_print_to_pagebuf(true, buf, cpumask_of(pmu->cpu)); | ||
| 70 | } | ||
| 71 | |||
| 72 | static struct device_attribute ddr_perf_cpumask_attr = | ||
| 73 | __ATTR(cpumask, 0444, ddr_perf_cpumask_show, NULL); | ||
| 74 | |||
| 75 | static struct attribute *ddr_perf_cpumask_attrs[] = { | ||
| 76 | &ddr_perf_cpumask_attr.attr, | ||
| 77 | NULL, | ||
| 78 | }; | ||
| 79 | |||
| 80 | static struct attribute_group ddr_perf_cpumask_attr_group = { | ||
| 81 | .attrs = ddr_perf_cpumask_attrs, | ||
| 82 | }; | ||
| 83 | |||
| 84 | static ssize_t | ||
| 85 | ddr_pmu_event_show(struct device *dev, struct device_attribute *attr, | ||
| 86 | char *page) | ||
| 87 | { | ||
| 88 | struct perf_pmu_events_attr *pmu_attr; | ||
| 89 | |||
| 90 | pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr); | ||
| 91 | return sprintf(page, "event=0x%02llx\n", pmu_attr->id); | ||
| 92 | } | ||
| 93 | |||
| 94 | #define IMX8_DDR_PMU_EVENT_ATTR(_name, _id) \ | ||
| 95 | (&((struct perf_pmu_events_attr[]) { \ | ||
| 96 | { .attr = __ATTR(_name, 0444, ddr_pmu_event_show, NULL),\ | ||
| 97 | .id = _id, } \ | ||
| 98 | })[0].attr.attr) | ||
| 99 | |||
| 100 | static struct attribute *ddr_perf_events_attrs[] = { | ||
| 101 | IMX8_DDR_PMU_EVENT_ATTR(cycles, EVENT_CYCLES_ID), | ||
| 102 | IMX8_DDR_PMU_EVENT_ATTR(selfresh, 0x01), | ||
| 103 | IMX8_DDR_PMU_EVENT_ATTR(read-accesses, 0x04), | ||
| 104 | IMX8_DDR_PMU_EVENT_ATTR(write-accesses, 0x05), | ||
| 105 | IMX8_DDR_PMU_EVENT_ATTR(read-queue-depth, 0x08), | ||
| 106 | IMX8_DDR_PMU_EVENT_ATTR(write-queue-depth, 0x09), | ||
| 107 | IMX8_DDR_PMU_EVENT_ATTR(lp-read-credit-cnt, 0x10), | ||
| 108 | IMX8_DDR_PMU_EVENT_ATTR(hp-read-credit-cnt, 0x11), | ||
| 109 | IMX8_DDR_PMU_EVENT_ATTR(write-credit-cnt, 0x12), | ||
| 110 | IMX8_DDR_PMU_EVENT_ATTR(read-command, 0x20), | ||
| 111 | IMX8_DDR_PMU_EVENT_ATTR(write-command, 0x21), | ||
| 112 | IMX8_DDR_PMU_EVENT_ATTR(read-modify-write-command, 0x22), | ||
| 113 | IMX8_DDR_PMU_EVENT_ATTR(hp-read, 0x23), | ||
| 114 | IMX8_DDR_PMU_EVENT_ATTR(hp-req-nocredit, 0x24), | ||
| 115 | IMX8_DDR_PMU_EVENT_ATTR(hp-xact-credit, 0x25), | ||
| 116 | IMX8_DDR_PMU_EVENT_ATTR(lp-req-nocredit, 0x26), | ||
| 117 | IMX8_DDR_PMU_EVENT_ATTR(lp-xact-credit, 0x27), | ||
| 118 | IMX8_DDR_PMU_EVENT_ATTR(wr-xact-credit, 0x29), | ||
| 119 | IMX8_DDR_PMU_EVENT_ATTR(read-cycles, 0x2a), | ||
| 120 | IMX8_DDR_PMU_EVENT_ATTR(write-cycles, 0x2b), | ||
| 121 | IMX8_DDR_PMU_EVENT_ATTR(read-write-transition, 0x30), | ||
| 122 | IMX8_DDR_PMU_EVENT_ATTR(precharge, 0x31), | ||
| 123 | IMX8_DDR_PMU_EVENT_ATTR(activate, 0x32), | ||
| 124 | IMX8_DDR_PMU_EVENT_ATTR(load-mode, 0x33), | ||
| 125 | IMX8_DDR_PMU_EVENT_ATTR(perf-mwr, 0x34), | ||
| 126 | IMX8_DDR_PMU_EVENT_ATTR(read, 0x35), | ||
| 127 | IMX8_DDR_PMU_EVENT_ATTR(read-activate, 0x36), | ||
| 128 | IMX8_DDR_PMU_EVENT_ATTR(refresh, 0x37), | ||
| 129 | IMX8_DDR_PMU_EVENT_ATTR(write, 0x38), | ||
| 130 | IMX8_DDR_PMU_EVENT_ATTR(raw-hazard, 0x39), | ||
| 131 | NULL, | ||
| 132 | }; | ||
| 133 | |||
| 134 | static struct attribute_group ddr_perf_events_attr_group = { | ||
| 135 | .name = "events", | ||
| 136 | .attrs = ddr_perf_events_attrs, | ||
| 137 | }; | ||
| 138 | |||
| 139 | PMU_FORMAT_ATTR(event, "config:0-7"); | ||
| 140 | |||
| 141 | static struct attribute *ddr_perf_format_attrs[] = { | ||
| 142 | &format_attr_event.attr, | ||
| 143 | NULL, | ||
| 144 | }; | ||
| 145 | |||
| 146 | static struct attribute_group ddr_perf_format_attr_group = { | ||
| 147 | .name = "format", | ||
| 148 | .attrs = ddr_perf_format_attrs, | ||
| 149 | }; | ||
| 150 | |||
| 151 | static const struct attribute_group *attr_groups[] = { | ||
| 152 | &ddr_perf_events_attr_group, | ||
| 153 | &ddr_perf_format_attr_group, | ||
| 154 | &ddr_perf_cpumask_attr_group, | ||
| 155 | NULL, | ||
| 156 | }; | ||
| 157 | |||
| 158 | static u32 ddr_perf_alloc_counter(struct ddr_pmu *pmu, int event) | ||
| 159 | { | ||
| 160 | int i; | ||
| 161 | |||
| 162 | /* | ||
| 163 | * Always map cycle event to counter 0 | ||
| 164 | * Cycles counter is dedicated for cycle event | ||
| 165 | * can't used for the other events | ||
| 166 | */ | ||
| 167 | if (event == EVENT_CYCLES_ID) { | ||
| 168 | if (pmu->events[EVENT_CYCLES_COUNTER] == NULL) | ||
| 169 | return EVENT_CYCLES_COUNTER; | ||
| 170 | else | ||
| 171 | return -ENOENT; | ||
| 172 | } | ||
| 173 | |||
| 174 | for (i = 1; i < NUM_COUNTERS; i++) { | ||
| 175 | if (pmu->events[i] == NULL) | ||
| 176 | return i; | ||
| 177 | } | ||
| 178 | |||
| 179 | return -ENOENT; | ||
| 180 | } | ||
| 181 | |||
| 182 | static void ddr_perf_free_counter(struct ddr_pmu *pmu, int counter) | ||
| 183 | { | ||
| 184 | pmu->events[counter] = NULL; | ||
| 185 | } | ||
| 186 | |||
| 187 | static u32 ddr_perf_read_counter(struct ddr_pmu *pmu, int counter) | ||
| 188 | { | ||
| 189 | return readl_relaxed(pmu->base + COUNTER_READ + counter * 4); | ||
| 190 | } | ||
| 191 | |||
| 192 | static int ddr_perf_event_init(struct perf_event *event) | ||
| 193 | { | ||
| 194 | struct ddr_pmu *pmu = to_ddr_pmu(event->pmu); | ||
| 195 | struct hw_perf_event *hwc = &event->hw; | ||
| 196 | struct perf_event *sibling; | ||
| 197 | |||
| 198 | if (event->attr.type != event->pmu->type) | ||
| 199 | return -ENOENT; | ||
| 200 | |||
| 201 | if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK) | ||
| 202 | return -EOPNOTSUPP; | ||
| 203 | |||
| 204 | if (event->cpu < 0) { | ||
| 205 | dev_warn(pmu->dev, "Can't provide per-task data!\n"); | ||
| 206 | return -EOPNOTSUPP; | ||
| 207 | } | ||
| 208 | |||
| 209 | /* | ||
| 210 | * We must NOT create groups containing mixed PMUs, although software | ||
| 211 | * events are acceptable (for example to create a CCN group | ||
| 212 | * periodically read when a hrtimer aka cpu-clock leader triggers). | ||
| 213 | */ | ||
| 214 | if (event->group_leader->pmu != event->pmu && | ||
| 215 | !is_software_event(event->group_leader)) | ||
| 216 | return -EINVAL; | ||
| 217 | |||
| 218 | for_each_sibling_event(sibling, event->group_leader) { | ||
| 219 | if (sibling->pmu != event->pmu && | ||
| 220 | !is_software_event(sibling)) | ||
| 221 | return -EINVAL; | ||
| 222 | } | ||
| 223 | |||
| 224 | event->cpu = pmu->cpu; | ||
| 225 | hwc->idx = -1; | ||
| 226 | |||
| 227 | return 0; | ||
| 228 | } | ||
| 229 | |||
| 230 | |||
| 231 | static void ddr_perf_event_update(struct perf_event *event) | ||
| 232 | { | ||
| 233 | struct ddr_pmu *pmu = to_ddr_pmu(event->pmu); | ||
| 234 | struct hw_perf_event *hwc = &event->hw; | ||
| 235 | u64 delta, prev_raw_count, new_raw_count; | ||
| 236 | int counter = hwc->idx; | ||
| 237 | |||
| 238 | do { | ||
| 239 | prev_raw_count = local64_read(&hwc->prev_count); | ||
| 240 | new_raw_count = ddr_perf_read_counter(pmu, counter); | ||
| 241 | } while (local64_cmpxchg(&hwc->prev_count, prev_raw_count, | ||
| 242 | new_raw_count) != prev_raw_count); | ||
| 243 | |||
| 244 | delta = (new_raw_count - prev_raw_count) & 0xFFFFFFFF; | ||
| 245 | |||
| 246 | local64_add(delta, &event->count); | ||
| 247 | } | ||
| 248 | |||
| 249 | static void ddr_perf_counter_enable(struct ddr_pmu *pmu, int config, | ||
| 250 | int counter, bool enable) | ||
| 251 | { | ||
| 252 | u8 reg = counter * 4 + COUNTER_CNTL; | ||
| 253 | int val; | ||
| 254 | |||
| 255 | if (enable) { | ||
| 256 | /* | ||
| 257 | * must disable first, then enable again | ||
| 258 | * otherwise, cycle counter will not work | ||
| 259 | * if previous state is enabled. | ||
| 260 | */ | ||
| 261 | writel(0, pmu->base + reg); | ||
| 262 | val = CNTL_EN | CNTL_CLEAR; | ||
| 263 | val |= FIELD_PREP(CNTL_CSV_MASK, config); | ||
| 264 | writel(val, pmu->base + reg); | ||
| 265 | } else { | ||
| 266 | /* Disable counter */ | ||
| 267 | writel(0, pmu->base + reg); | ||
| 268 | } | ||
| 269 | } | ||
| 270 | |||
| 271 | static void ddr_perf_event_start(struct perf_event *event, int flags) | ||
| 272 | { | ||
| 273 | struct ddr_pmu *pmu = to_ddr_pmu(event->pmu); | ||
| 274 | struct hw_perf_event *hwc = &event->hw; | ||
| 275 | int counter = hwc->idx; | ||
| 276 | |||
| 277 | local64_set(&hwc->prev_count, 0); | ||
| 278 | |||
| 279 | ddr_perf_counter_enable(pmu, event->attr.config, counter, true); | ||
| 280 | |||
| 281 | hwc->state = 0; | ||
| 282 | } | ||
| 283 | |||
| 284 | static int ddr_perf_event_add(struct perf_event *event, int flags) | ||
| 285 | { | ||
| 286 | struct ddr_pmu *pmu = to_ddr_pmu(event->pmu); | ||
| 287 | struct hw_perf_event *hwc = &event->hw; | ||
| 288 | int counter; | ||
| 289 | int cfg = event->attr.config; | ||
| 290 | |||
| 291 | counter = ddr_perf_alloc_counter(pmu, cfg); | ||
| 292 | if (counter < 0) { | ||
| 293 | dev_dbg(pmu->dev, "There are not enough counters\n"); | ||
| 294 | return -EOPNOTSUPP; | ||
| 295 | } | ||
| 296 | |||
| 297 | pmu->events[counter] = event; | ||
| 298 | pmu->active_events++; | ||
| 299 | hwc->idx = counter; | ||
| 300 | |||
| 301 | hwc->state |= PERF_HES_STOPPED; | ||
| 302 | |||
| 303 | if (flags & PERF_EF_START) | ||
| 304 | ddr_perf_event_start(event, flags); | ||
| 305 | |||
| 306 | return 0; | ||
| 307 | } | ||
| 308 | |||
| 309 | static void ddr_perf_event_stop(struct perf_event *event, int flags) | ||
| 310 | { | ||
| 311 | struct ddr_pmu *pmu = to_ddr_pmu(event->pmu); | ||
| 312 | struct hw_perf_event *hwc = &event->hw; | ||
| 313 | int counter = hwc->idx; | ||
| 314 | |||
| 315 | ddr_perf_counter_enable(pmu, event->attr.config, counter, false); | ||
| 316 | ddr_perf_event_update(event); | ||
| 317 | |||
| 318 | hwc->state |= PERF_HES_STOPPED; | ||
| 319 | } | ||
| 320 | |||
| 321 | static void ddr_perf_event_del(struct perf_event *event, int flags) | ||
| 322 | { | ||
| 323 | struct ddr_pmu *pmu = to_ddr_pmu(event->pmu); | ||
| 324 | struct hw_perf_event *hwc = &event->hw; | ||
| 325 | int counter = hwc->idx; | ||
| 326 | |||
| 327 | ddr_perf_event_stop(event, PERF_EF_UPDATE); | ||
| 328 | |||
| 329 | ddr_perf_free_counter(pmu, counter); | ||
| 330 | pmu->active_events--; | ||
| 331 | hwc->idx = -1; | ||
| 332 | } | ||
| 333 | |||
| 334 | static void ddr_perf_pmu_enable(struct pmu *pmu) | ||
| 335 | { | ||
| 336 | struct ddr_pmu *ddr_pmu = to_ddr_pmu(pmu); | ||
| 337 | |||
| 338 | /* enable cycle counter if cycle is not active event list */ | ||
| 339 | if (ddr_pmu->events[EVENT_CYCLES_COUNTER] == NULL) | ||
| 340 | ddr_perf_counter_enable(ddr_pmu, | ||
| 341 | EVENT_CYCLES_ID, | ||
| 342 | EVENT_CYCLES_COUNTER, | ||
| 343 | true); | ||
| 344 | } | ||
| 345 | |||
| 346 | static void ddr_perf_pmu_disable(struct pmu *pmu) | ||
| 347 | { | ||
| 348 | struct ddr_pmu *ddr_pmu = to_ddr_pmu(pmu); | ||
| 349 | |||
| 350 | if (ddr_pmu->events[EVENT_CYCLES_COUNTER] == NULL) | ||
| 351 | ddr_perf_counter_enable(ddr_pmu, | ||
| 352 | EVENT_CYCLES_ID, | ||
| 353 | EVENT_CYCLES_COUNTER, | ||
| 354 | false); | ||
| 355 | } | ||
| 356 | |||
| 357 | static int ddr_perf_init(struct ddr_pmu *pmu, void __iomem *base, | ||
| 358 | struct device *dev) | ||
| 359 | { | ||
| 360 | *pmu = (struct ddr_pmu) { | ||
| 361 | .pmu = (struct pmu) { | ||
| 362 | .capabilities = PERF_PMU_CAP_NO_EXCLUDE, | ||
| 363 | .task_ctx_nr = perf_invalid_context, | ||
| 364 | .attr_groups = attr_groups, | ||
| 365 | .event_init = ddr_perf_event_init, | ||
| 366 | .add = ddr_perf_event_add, | ||
| 367 | .del = ddr_perf_event_del, | ||
| 368 | .start = ddr_perf_event_start, | ||
| 369 | .stop = ddr_perf_event_stop, | ||
| 370 | .read = ddr_perf_event_update, | ||
| 371 | .pmu_enable = ddr_perf_pmu_enable, | ||
| 372 | .pmu_disable = ddr_perf_pmu_disable, | ||
| 373 | }, | ||
| 374 | .base = base, | ||
| 375 | .dev = dev, | ||
| 376 | }; | ||
| 377 | |||
| 378 | pmu->id = ida_simple_get(&ddr_ida, 0, 0, GFP_KERNEL); | ||
| 379 | return pmu->id; | ||
| 380 | } | ||
| 381 | |||
| 382 | static irqreturn_t ddr_perf_irq_handler(int irq, void *p) | ||
| 383 | { | ||
| 384 | int i; | ||
| 385 | struct ddr_pmu *pmu = (struct ddr_pmu *) p; | ||
| 386 | struct perf_event *event, *cycle_event = NULL; | ||
| 387 | |||
| 388 | /* all counter will stop if cycle counter disabled */ | ||
| 389 | ddr_perf_counter_enable(pmu, | ||
| 390 | EVENT_CYCLES_ID, | ||
| 391 | EVENT_CYCLES_COUNTER, | ||
| 392 | false); | ||
| 393 | /* | ||
| 394 | * When the cycle counter overflows, all counters are stopped, | ||
| 395 | * and an IRQ is raised. If any other counter overflows, it | ||
| 396 | * continues counting, and no IRQ is raised. | ||
| 397 | * | ||
| 398 | * Cycles occur at least 4 times as often as other events, so we | ||
| 399 | * can update all events on a cycle counter overflow and not | ||
| 400 | * lose events. | ||
| 401 | * | ||
| 402 | */ | ||
| 403 | for (i = 0; i < NUM_COUNTERS; i++) { | ||
| 404 | |||
| 405 | if (!pmu->events[i]) | ||
| 406 | continue; | ||
| 407 | |||
| 408 | event = pmu->events[i]; | ||
| 409 | |||
| 410 | ddr_perf_event_update(event); | ||
| 411 | |||
| 412 | if (event->hw.idx == EVENT_CYCLES_COUNTER) | ||
| 413 | cycle_event = event; | ||
| 414 | } | ||
| 415 | |||
| 416 | ddr_perf_counter_enable(pmu, | ||
| 417 | EVENT_CYCLES_ID, | ||
| 418 | EVENT_CYCLES_COUNTER, | ||
| 419 | true); | ||
| 420 | if (cycle_event) | ||
| 421 | ddr_perf_event_update(cycle_event); | ||
| 422 | |||
| 423 | return IRQ_HANDLED; | ||
| 424 | } | ||
| 425 | |||
| 426 | static int ddr_perf_offline_cpu(unsigned int cpu, struct hlist_node *node) | ||
| 427 | { | ||
| 428 | struct ddr_pmu *pmu = hlist_entry_safe(node, struct ddr_pmu, node); | ||
| 429 | int target; | ||
| 430 | |||
| 431 | if (cpu != pmu->cpu) | ||
| 432 | return 0; | ||
| 433 | |||
| 434 | target = cpumask_any_but(cpu_online_mask, cpu); | ||
| 435 | if (target >= nr_cpu_ids) | ||
| 436 | return 0; | ||
| 437 | |||
| 438 | perf_pmu_migrate_context(&pmu->pmu, cpu, target); | ||
| 439 | pmu->cpu = target; | ||
| 440 | |||
| 441 | WARN_ON(irq_set_affinity_hint(pmu->irq, cpumask_of(pmu->cpu))); | ||
| 442 | |||
| 443 | return 0; | ||
| 444 | } | ||
| 445 | |||
| 446 | static int ddr_perf_probe(struct platform_device *pdev) | ||
| 447 | { | ||
| 448 | struct ddr_pmu *pmu; | ||
| 449 | struct device_node *np; | ||
| 450 | void __iomem *base; | ||
| 451 | char *name; | ||
| 452 | int num; | ||
| 453 | int ret; | ||
| 454 | int irq; | ||
| 455 | |||
| 456 | base = devm_platform_ioremap_resource(pdev, 0); | ||
| 457 | if (IS_ERR(base)) | ||
| 458 | return PTR_ERR(base); | ||
| 459 | |||
| 460 | np = pdev->dev.of_node; | ||
| 461 | |||
| 462 | pmu = devm_kzalloc(&pdev->dev, sizeof(*pmu), GFP_KERNEL); | ||
| 463 | if (!pmu) | ||
| 464 | return -ENOMEM; | ||
| 465 | |||
| 466 | num = ddr_perf_init(pmu, base, &pdev->dev); | ||
| 467 | |||
| 468 | platform_set_drvdata(pdev, pmu); | ||
| 469 | |||
| 470 | name = devm_kasprintf(&pdev->dev, GFP_KERNEL, DDR_PERF_DEV_NAME "%d", | ||
| 471 | num); | ||
| 472 | if (!name) | ||
| 473 | return -ENOMEM; | ||
| 474 | |||
| 475 | pmu->cpu = raw_smp_processor_id(); | ||
| 476 | ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, | ||
| 477 | DDR_CPUHP_CB_NAME, | ||
| 478 | NULL, | ||
| 479 | ddr_perf_offline_cpu); | ||
| 480 | |||
| 481 | if (ret < 0) { | ||
| 482 | dev_err(&pdev->dev, "cpuhp_setup_state_multi failed\n"); | ||
| 483 | goto ddr_perf_err; | ||
| 484 | } | ||
| 485 | |||
| 486 | pmu->cpuhp_state = ret; | ||
| 487 | |||
| 488 | /* Register the pmu instance for cpu hotplug */ | ||
| 489 | cpuhp_state_add_instance_nocalls(pmu->cpuhp_state, &pmu->node); | ||
| 490 | |||
| 491 | /* Request irq */ | ||
| 492 | irq = of_irq_get(np, 0); | ||
| 493 | if (irq < 0) { | ||
| 494 | dev_err(&pdev->dev, "Failed to get irq: %d", irq); | ||
| 495 | ret = irq; | ||
| 496 | goto ddr_perf_err; | ||
| 497 | } | ||
| 498 | |||
| 499 | ret = devm_request_irq(&pdev->dev, irq, | ||
| 500 | ddr_perf_irq_handler, | ||
| 501 | IRQF_NOBALANCING | IRQF_NO_THREAD, | ||
| 502 | DDR_CPUHP_CB_NAME, | ||
| 503 | pmu); | ||
| 504 | if (ret < 0) { | ||
| 505 | dev_err(&pdev->dev, "Request irq failed: %d", ret); | ||
| 506 | goto ddr_perf_err; | ||
| 507 | } | ||
| 508 | |||
| 509 | pmu->irq = irq; | ||
| 510 | ret = irq_set_affinity_hint(pmu->irq, cpumask_of(pmu->cpu)); | ||
| 511 | if (ret) { | ||
| 512 | dev_err(pmu->dev, "Failed to set interrupt affinity!\n"); | ||
| 513 | goto ddr_perf_err; | ||
| 514 | } | ||
| 515 | |||
| 516 | ret = perf_pmu_register(&pmu->pmu, name, -1); | ||
| 517 | if (ret) | ||
| 518 | goto ddr_perf_err; | ||
| 519 | |||
| 520 | return 0; | ||
| 521 | |||
| 522 | ddr_perf_err: | ||
| 523 | if (pmu->cpuhp_state) | ||
| 524 | cpuhp_state_remove_instance_nocalls(pmu->cpuhp_state, &pmu->node); | ||
| 525 | |||
| 526 | ida_simple_remove(&ddr_ida, pmu->id); | ||
| 527 | dev_warn(&pdev->dev, "i.MX8 DDR Perf PMU failed (%d), disabled\n", ret); | ||
| 528 | return ret; | ||
| 529 | } | ||
| 530 | |||
| 531 | static int ddr_perf_remove(struct platform_device *pdev) | ||
| 532 | { | ||
| 533 | struct ddr_pmu *pmu = platform_get_drvdata(pdev); | ||
| 534 | |||
| 535 | cpuhp_state_remove_instance_nocalls(pmu->cpuhp_state, &pmu->node); | ||
| 536 | irq_set_affinity_hint(pmu->irq, NULL); | ||
| 537 | |||
| 538 | perf_pmu_unregister(&pmu->pmu); | ||
| 539 | |||
| 540 | ida_simple_remove(&ddr_ida, pmu->id); | ||
| 541 | return 0; | ||
| 542 | } | ||
| 543 | |||
| 544 | static struct platform_driver imx_ddr_pmu_driver = { | ||
| 545 | .driver = { | ||
| 546 | .name = "imx-ddr-pmu", | ||
| 547 | .of_match_table = imx_ddr_pmu_dt_ids, | ||
| 548 | }, | ||
| 549 | .probe = ddr_perf_probe, | ||
| 550 | .remove = ddr_perf_remove, | ||
| 551 | }; | ||
| 552 | |||
| 553 | module_platform_driver(imx_ddr_pmu_driver); | ||
| 554 | MODULE_LICENSE("GPL v2"); | ||
| @@ -1303,6 +1303,7 @@ static inline int lpit_read_residency_count_address(u64 *address) · 1302 unmodified lines | |||
| 1303 | #ifdef CONFIG_ACPI_PPTT | 1303 | #ifdef CONFIG_ACPI_PPTT |
| 1304 | int find_acpi_cpu_topology(unsigned int cpu, int level); | 1304 | int find_acpi_cpu_topology(unsigned int cpu, int level); |
| 1305 | int find_acpi_cpu_topology_package(unsigned int cpu); | 1305 | int find_acpi_cpu_topology_package(unsigned int cpu); |
| 1306 | int find_acpi_cpu_topology_hetero_id(unsigned int cpu); | ||
| 1306 | int find_acpi_cpu_cache_topology(unsigned int cpu, int level); | 1307 | int find_acpi_cpu_cache_topology(unsigned int cpu, int level); |
| 1307 | #else | 1308 | #else |
| 1308 | static inline int find_acpi_cpu_topology(unsigned int cpu, int level) | 1309 | static inline int find_acpi_cpu_topology(unsigned int cpu, int level) |
| @@ -1313,6 +1314,10 @@ static inline int find_acpi_cpu_topology_package(unsigned int cpu) · 4 unmodified lines | |||
| 1313 | { | 1314 | { |
| 1314 | return -EINVAL; | 1315 | return -EINVAL; |
| 1315 | } | 1316 | } |
| 1317 | static inline int find_acpi_cpu_topology_hetero_id(unsigned int cpu) | ||
| 1318 | { | ||
| 1319 | return -EINVAL; | ||
| 1320 | } | ||
| 1316 | static inline int find_acpi_cpu_cache_topology(unsigned int cpu, int level) | 1321 | static inline int find_acpi_cpu_cache_topology(unsigned int cpu, int level) |
| 1317 | { | 1322 | { |
| 1318 | return -EINVAL; | 1323 | return -EINVAL; |
| @@ -17,6 +17,8 @@ enum cache_type { · 16 unmodified lines | |||
| 17 | CACHE_TYPE_UNIFIED = BIT(2), | 17 | CACHE_TYPE_UNIFIED = BIT(2), |
| 18 | }; | 18 | }; |
| 19 | 19 | ||
| 20 | extern unsigned int coherency_max_size; | ||
| 21 | |||
| 20 | /** | 22 | /** |
| 21 | * struct cacheinfo - represent a cache leaf node | 23 | * struct cacheinfo - represent a cache leaf node |
| 22 | * @id: This cache's id. It is unique among caches with the same (type, level). | 24 | * @id: This cache's id. It is unique among caches with the same (type, level). |
| @@ -171,4 +171,6 @@ void armpmu_free_irq(int irq, int cpu); · 170 unmodified lines | |||
| 171 | 171 | ||
| 172 | #endif /* CONFIG_ARM_PMU */ | 172 | #endif /* CONFIG_ARM_PMU */ |
| 173 | 173 | ||
| 174 | #define ARMV8_SPE_PDEV_NAME "arm,spe-v1" | ||
| 175 | |||
| 174 | #endif /* __ARM_PMU_H__ */ | 176 | #endif /* __ARM_PMU_H__ */ |
| @@ -680,6 +680,8 @@ int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq, · 679 unmodified lines | |||
| 680 | * @hwirq: The HW irq number to convert to a logical one | 680 | * @hwirq: The HW irq number to convert to a logical one |
| 681 | * @regs: Register file coming from the low-level handling code | 681 | * @regs: Register file coming from the low-level handling code |
| 682 | * | 682 | * |
| 683 | * This function must be called from an NMI context. | ||
| 684 | * | ||
| 683 | * Returns: 0 on success, or -EINVAL if conversion has failed | 685 | * Returns: 0 on success, or -EINVAL if conversion has failed |
| 684 | */ | 686 | */ |
| 685 | int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq, | 687 | int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq, |
| @@ -689,7 +691,10 @@ int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq, · 3 unmodified lines | |||
| 689 | unsigned int irq; | 691 | unsigned int irq; |
| 690 | int ret = 0; | 692 | int ret = 0; |
| 691 | 693 | ||
| 692 | nmi_enter(); | 694 | /* |
| 695 | * NMI context needs to be setup earlier in order to deal with tracing. | ||
| 696 | */ | ||
| 697 | WARN_ON(!in_nmi()); | ||
| 693 | 698 | ||
| 694 | irq = irq_find_mapping(domain, hwirq); | 699 | irq = irq_find_mapping(domain, hwirq); |
| 695 | 700 | ||
| @@ -702,7 +707,6 @@ int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq, · 6 unmodified lines | |||
| 702 | else | 707 | else |
| 703 | ret = -EINVAL; | 708 | ret = -EINVAL; |
| 704 | 709 | ||
| 705 | nmi_exit(); | ||
| 706 | set_irq_regs(old_regs); | 710 | set_irq_regs(old_regs); |
| 707 | return ret; | 711 | return ret; |
| 708 | } | 712 | } |
| @@ -116,6 +116,9 @@ void __ptrace_unlink(struct task_struct *child) · 115 unmodified lines | |||
| 116 | BUG_ON(!child->ptrace); | 116 | BUG_ON(!child->ptrace); |
| 117 | 117 | ||
| 118 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 118 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
| 119 | #ifdef TIF_SYSCALL_EMU | ||
| 120 | clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); | ||
| 121 | #endif | ||
| 119 | 122 | ||
| 120 | child->parent = child->real_parent; | 123 | child->parent = child->real_parent; |
| 121 | list_del_init(&child->ptrace_entry); | 124 | list_del_init(&child->ptrace_entry); |
| @@ -2128,17 +2128,6 @@ static void vm_remove_mappings(struct vm_struct *area, int deallocate_pages) · 2127 unmodified lines | |||
| 2128 | int flush_dmap = 0; | 2128 | int flush_dmap = 0; |
| 2129 | int i; | 2129 | int i; |
| 2130 | 2130 | ||
| 2131 | /* | ||
| 2132 | * The below block can be removed when all architectures that have | ||
| 2133 | * direct map permissions also have set_direct_map_() implementations. | ||
| 2134 | * This is concerned with resetting the direct map any an vm alias with | ||
| 2135 | * execute permissions, without leaving a RW+X window. | ||
| 2136 | */ | ||
| 2137 | if (flush_reset && !IS_ENABLED(CONFIG_ARCH_HAS_SET_DIRECT_MAP)) { | ||
| 2138 | set_memory_nx((unsigned long)area->addr, area->nr_pages); | ||
| 2139 | set_memory_rw((unsigned long)area->addr, area->nr_pages); | ||
| 2140 | } | ||
| 2141 | |||
| 2142 | remove_vm_area(area->addr); | 2131 | remove_vm_area(area->addr); |
| 2143 | 2132 | ||
| 2144 | /* If this is not VM_FLUSH_RESET_PERMS memory, no need for the below. */ | 2133 | /* If this is not VM_FLUSH_RESET_PERMS memory, no need for the below. */ |