Pull RISC-V updates from Palmer Dabbelt: - Support for the T-Head PMU via the perf subsystem - ftrace support for rv32 - Support for non-volatile memory devices - Various fixes and cleanups * tag 'riscv-for-linus-6.2-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: (52 commits) Documentation: RISC-V: patch-acceptance: s/implementor/implementer Documentation: RISC-V: Mention the UEFI Standards Documentation: RISC-V: Allow patches for non-standard behavior Documentation: RISC-V: Fix a typo in patch-acceptance riscv: Fixup compile error with !MMU riscv: Fix P4D_SHIFT definition for 3-level page table mode riscv: Apply a static assert to riscv_isa_ext_id RISC-V: Add some comments about the shadow and overflow stacks RISC-V: Align the shadow stack RISC-V: Ensure Zicbom has a valid block size RISC-V: Introduce riscv_isa_extension_check RISC-V: Improve use of isa2hwcap[] riscv: Don't duplicate _ALTERNATIVE_CFG* macros riscv: alternatives: Drop the underscores from the assembly macro names riscv: alternatives: Don't name unused macro parameters riscv: Don't duplicate __ALTERNATIVE_CFG in __ALTERNATIVE_CFG_2 riscv: mm: call best_map_size many times during linear-mapping riscv: Move cast inside kernel_mapping_[pv]a_to_[vp]a riscv: Fix crash during early errata patching riscv: boot: add zstd support ...
Unified · Split
| @@ -595,3 +595,32 @@ X2TLB · 594 unmodified lines | ||
| 595 | 595 | ----- |
| 596 | 596 | |
| 597 | 597 | Indicates whether the crashed kernel enabled SH extended mode. |
| 598 | + | |
| 599 | +RISCV64 | |
| 600 | +======= | |
| 601 | + | |
| 602 | +VA_BITS | |
| 603 | +------- | |
| 604 | + | |
| 605 | +The maximum number of bits for virtual addresses. Used to compute the | |
| 606 | +virtual memory ranges. | |
| 607 | + | |
| 608 | +PAGE_OFFSET | |
| 609 | +----------- | |
| 610 | + | |
| 611 | +Indicates the virtual kernel start address of the direct-mapped RAM region. | |
| 612 | + | |
| 613 | +phys_ram_base | |
| 614 | +------------- | |
| 615 | + | |
| 616 | +Indicates the start physical RAM address. | |
| 617 | + | |
| 618 | +MODULES_VADDR|MODULES_END|VMALLOC_START|VMALLOC_END|VMEMMAP_START|VMEMMAP_END|KERNEL_LINK_ADDR | |
| 619 | +---------------------------------------------------------------------------------------------- | |
| 620 | + | |
| 621 | +Used to get the correct ranges: | |
| 622 | + | |
| 623 | + * MODULES_VADDR ~ MODULES_END : Kernel module space. | |
| 624 | + * VMALLOC_START ~ VMALLOC_END : vmalloc() / ioremap() space. | |
| 625 | + * VMEMMAP_START ~ VMEMMAP_END : vmemmap space, used for struct page array. | |
| 626 | + * KERNEL_LINK_ADDR : start address of Kernel link and BPF | |
| @@ -21,7 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | | openrisc: | TODO | |
| 22 | 22 | | parisc: | TODO | |
| 23 | 23 | | powerpc: | ok | |
| 24 | − | riscv: | TODO | | |
| 24 | + | riscv: | ok | | |
| 25 | 25 | | s390: | TODO | |
| 26 | 26 | | sh: | TODO | |
| 27 | 27 | | sparc: | TODO | |
| @@ -20,16 +20,22 @@ Submit Checklist Addendum · 19 unmodified lines | ||
| 20 | 20 | ------------------------- |
| 21 | 21 | We'll only accept patches for new modules or extensions if the |
| 22 | 22 | specifications for those modules or extensions are listed as being |
| 23 | −"Frozen" or "Ratified" by the RISC-V Foundation. (Developers may, of | |
| 24 | −course, maintain their own Linux kernel trees that contain code for | |
| 25 | −any draft extensions that they wish.) | |
| 23 | +unlikely to be incompatibly changed in the future. For | |
| 24 | +specifications from the RISC-V foundation this means "Frozen" or | |
| 25 | +"Ratified", for the UEFI forum specifications this means a published | |
| 26 | +ECR. (Developers may, of course, maintain their own Linux kernel trees | |
| 27 | +that contain code for any draft extensions that they wish.) | |
| 26 | 28 | |
| 27 | −Additionally, the RISC-V specification allows implementors to create | |
| 29 | +Additionally, the RISC-V specification allows implementers to create | |
| 28 | 30 | their own custom extensions. These custom extensions aren't required |
| 29 | 31 | to go through any review or ratification process by the RISC-V |
| 30 | 32 | Foundation. To avoid the maintenance complexity and potential |
| 31 | 33 | performance impact of adding kernel code for implementor-specific |
| 32 | −RISC-V extensions, we'll only to accept patches for extensions that | |
| 33 | −have been officially frozen or ratified by the RISC-V Foundation. | |
| 34 | −(Implementors, may, of course, maintain their own Linux kernel trees | |
| 35 | −containing code for any custom extensions that they wish.) | |
| 34 | +RISC-V extensions, we'll only consider patches for extensions that either: | |
| 35 | + | |
| 36 | +- Have been officially frozen or ratified by the RISC-V Foundation, or | |
| 37 | +- Have been implemented in hardware that is widely available, per standard | |
| 38 | + Linux practice. | |
| 39 | + | |
| 40 | +(Implementers, may, of course, maintain their own Linux kernel trees containing | |
| 41 | +code for any custom extensions that they wish.) | |
| @@ -25,6 +25,7 @@ config RISCV · 24 unmodified lines | ||
| 25 | 25 | select ARCH_HAS_GIGANTIC_PAGE |
| 26 | 26 | select ARCH_HAS_KCOV |
| 27 | 27 | select ARCH_HAS_MMIOWB |
| 28 | + select ARCH_HAS_PMEM_API | |
| 28 | 29 | select ARCH_HAS_PTE_SPECIAL |
| 29 | 30 | select ARCH_HAS_SET_DIRECT_MAP if MMU |
| 30 | 31 | select ARCH_HAS_SET_MEMORY if MMU |
| @@ -72,6 +73,8 @@ config RISCV · 41 unmodified lines | ||
| 72 | 73 | select GENERIC_VDSO_TIME_NS if HAVE_GENERIC_VDSO |
| 73 | 74 | select HARDIRQS_SW_RESEND |
| 74 | 75 | select HAVE_ARCH_AUDITSYSCALL |
| 76 | + select HAVE_ARCH_HUGE_VMALLOC if HAVE_ARCH_HUGE_VMAP | |
| 77 | + select HAVE_ARCH_HUGE_VMAP if MMU && 64BIT && !XIP_KERNEL | |
| 75 | 78 | select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL |
| 76 | 79 | select HAVE_ARCH_JUMP_LABEL_RELATIVE if !XIP_KERNEL |
| 77 | 80 | select HAVE_ARCH_KASAN if MMU && 64BIT |
| @@ -99,6 +102,7 @@ config RISCV · 21 unmodified lines | ||
| 99 | 102 | select HAVE_KPROBES if !XIP_KERNEL |
| 100 | 103 | select HAVE_KPROBES_ON_FTRACE if !XIP_KERNEL |
| 101 | 104 | select HAVE_KRETPROBES if !XIP_KERNEL |
| 105 | + select HAVE_RETHOOK if !XIP_KERNEL | |
| 102 | 106 | select HAVE_MOVE_PMD |
| 103 | 107 | select HAVE_MOVE_PUD |
| 104 | 108 | select HAVE_PCI |
| @@ -123,12 +127,18 @@ config RISCV · 18 unmodified lines | ||
| 123 | 127 | select PCI_MSI if PCI |
| 124 | 128 | select RISCV_INTC |
| 125 | 129 | select RISCV_TIMER if RISCV_SBI |
| 130 | + select SIFIVE_PLIC | |
| 126 | 131 | select SPARSE_IRQ |
| 127 | 132 | select SYSCTL_EXCEPTION_TRACE |
| 128 | 133 | select THREAD_INFO_IN_TASK |
| 129 | 134 | select TRACE_IRQFLAGS_SUPPORT |
| 130 | 135 | select UACCESS_MEMCPY if !MMU |
| 131 | 136 | select ZONE_DMA32 if 64BIT |
| 137 | + select HAVE_DYNAMIC_FTRACE if !XIP_KERNEL && MMU && $(cc-option,-fpatchable-function-entry=8) | |
| 138 | + select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE | |
| 139 | + select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL | |
| 140 | + select HAVE_FUNCTION_GRAPH_TRACER | |
| 141 | + select HAVE_FUNCTION_TRACER if !XIP_KERNEL | |
| 132 | 142 | |
| 133 | 143 | config ARCH_MMAP_RND_BITS_MIN |
| 134 | 144 | default 18 if 64BIT |
| @@ -274,11 +284,6 @@ config ARCH_RV64I · 139 unmodified lines | ||
| 274 | 284 | bool "RV64I" |
| 275 | 285 | select 64BIT |
| 276 | 286 | select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 |
| 277 | − select HAVE_DYNAMIC_FTRACE if !XIP_KERNEL && MMU && $(cc-option,-fpatchable-function-entry=8) | |
| 278 | − select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE | |
| 279 | − select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL | |
| 280 | − select HAVE_FUNCTION_GRAPH_TRACER | |
| 281 | − select HAVE_FUNCTION_TRACER if !XIP_KERNEL | |
| 282 | 287 | select SWIOTLB if MMU |
| 283 | 288 | |
| 284 | 289 | endchoice |
| @@ -502,7 +507,7 @@ config KEXEC_FILE · 217 unmodified lines | ||
| 502 | 507 | select KEXEC_CORE |
| 503 | 508 | select KEXEC_ELF |
| 504 | 509 | select HAVE_IMA_KEXEC if IMA |
| 505 | − depends on 64BIT | |
| 510 | + depends on 64BIT && MMU | |
| 506 | 511 | help |
| 507 | 512 | This is new version of kexec system call. This system call is |
| 508 | 513 | file based and takes file descriptors as system call argument |
| @@ -691,6 +696,8 @@ menu "CPU Power Management" · 182 unmodified lines | ||
| 691 | 696 | |
| 692 | 697 | source "drivers/cpuidle/Kconfig" |
| 693 | 698 | |
| 699 | +source "drivers/cpufreq/Kconfig" | |
| 700 | + | |
| 694 | 701 | endmenu # "CPU Power Management" |
| 695 | 702 | |
| 696 | 703 | source "arch/riscv/kvm/Kconfig" |
| @@ -66,4 +66,17 @@ config ERRATA_THEAD_CMO · 65 unmodified lines | ||
| 66 | 66 | |
| 67 | 67 | If you don't know what to do here, say "Y". |
| 68 | 68 | |
| 69 | +config ERRATA_THEAD_PMU | |
| 70 | + bool "Apply T-Head PMU errata" | |
| 71 | + depends on ERRATA_THEAD && RISCV_PMU_SBI | |
| 72 | + default y | |
| 73 | + help | |
| 74 | + The T-Head C9xx cores implement a PMU overflow extension very | |
| 75 | + similar to the core SSCOFPMF extension. | |
| 76 | + | |
| 77 | + This will apply the overflow errata to handle the non-standard | |
| 78 | + behaviour via the regular SBI PMU driver and interface. | |
| 79 | + | |
| 80 | + If you don't know what to do here, say "Y". | |
| 81 | + | |
| 69 | 82 | endmenu # "CPU errata selection" |
| @@ -3,7 +3,6 @@ menu "SoC selection" · 2 unmodified lines | ||
| 3 | 3 | config SOC_MICROCHIP_POLARFIRE |
| 4 | 4 | bool "Microchip PolarFire SoCs" |
| 5 | 5 | select MCHP_CLK_MPFS |
| 6 | − select SIFIVE_PLIC | |
| 7 | 6 | help |
| 8 | 7 | This enables support for Microchip PolarFire SoC platforms. |
| 9 | 8 | |
| @@ -18,7 +17,6 @@ config SOC_SIFIVE · 8 unmodified lines | ||
| 18 | 17 | select SERIAL_SIFIVE_CONSOLE if TTY |
| 19 | 18 | select CLK_SIFIVE |
| 20 | 19 | select CLK_SIFIVE_PRCI |
| 21 | − select SIFIVE_PLIC | |
| 22 | 20 | select ERRATA_SIFIVE if !XIP_KERNEL |
| 23 | 21 | help |
| 24 | 22 | This enables support for SiFive SoC platform hardware. |
| @@ -27,7 +25,6 @@ config SOC_STARFIVE · 2 unmodified lines | ||
| 27 | 25 | bool "StarFive SoCs" |
| 28 | 26 | select PINCTRL |
| 29 | 27 | select RESET_CONTROLLER |
| 30 | − select SIFIVE_PLIC | |
| 31 | 28 | help |
| 32 | 29 | This enables support for StarFive SoC platform hardware. |
| 33 | 30 | |
| @@ -39,7 +36,6 @@ config SOC_VIRT · 5 unmodified lines | ||
| 39 | 36 | select POWER_RESET_SYSCON_POWEROFF |
| 40 | 37 | select GOLDFISH |
| 41 | 38 | select RTC_DRV_GOLDFISH if RTC_CLASS |
| 42 | − select SIFIVE_PLIC | |
| 43 | 39 | select PM_GENERIC_DOMAINS if PM |
| 44 | 40 | select PM_GENERIC_DOMAINS_OF if PM && OF |
| 45 | 41 | select RISCV_SBI_CPUIDLE if CPU_IDLE && RISCV_SBI |
| @@ -52,7 +48,6 @@ config SOC_CANAAN · 6 unmodified lines | ||
| 52 | 48 | select CLINT_TIMER if RISCV_M_MODE |
| 53 | 49 | select SERIAL_SIFIVE if TTY |
| 54 | 50 | select SERIAL_SIFIVE_CONSOLE if TTY |
| 55 | − select SIFIVE_PLIC | |
| 56 | 51 | select ARCH_HAS_RESET_CONTROLLER |
| 57 | 52 | select PINCTRL |
| 58 | 53 | select COMMON_CLK |
| @@ -56,6 +56,9 @@ $(obj)/Image.lzma: $(obj)/Image FORCE · 55 unmodified lines | ||
| 56 | 56 | $(obj)/Image.lzo: $(obj)/Image FORCE |
| 57 | 57 | $(call if_changed,lzo) |
| 58 | 58 | |
| 59 | +$(obj)/Image.zst: $(obj)/Image FORCE | |
| 60 | + $(call if_changed,zstd) | |
| 61 | + | |
| 59 | 62 | $(obj)/loader.bin: $(obj)/loader FORCE |
| 60 | 63 | $(call if_changed,objcopy) |
| 61 | 64 | |
| @@ -39,6 +39,7 @@ CONFIG_KVM=m · 38 unmodified lines | ||
| 39 | 39 | CONFIG_JUMP_LABEL=y |
| 40 | 40 | CONFIG_MODULES=y |
| 41 | 41 | CONFIG_MODULE_UNLOAD=y |
| 42 | +CONFIG_SPARSEMEM_MANUAL=y | |
| 42 | 43 | CONFIG_BLK_DEV_THROTTLING=y |
| 43 | 44 | CONFIG_NET=y |
| 44 | 45 | CONFIG_PACKET=y |
| @@ -123,6 +124,7 @@ CONFIG_MICROSEMI_PHY=y · 78 unmodified lines | ||
| 123 | 124 | CONFIG_INPUT_MOUSEDEV=y |
| 124 | 125 | CONFIG_SERIAL_8250=y |
| 125 | 126 | CONFIG_SERIAL_8250_CONSOLE=y |
| 127 | +CONFIG_SERIAL_8250_DW=y | |
| 126 | 128 | CONFIG_SERIAL_OF_PLATFORM=y |
| 127 | 129 | CONFIG_SERIAL_SH_SCI=y |
| 128 | 130 | CONFIG_VIRTIO_CONSOLE=y |
| @@ -162,6 +164,7 @@ CONFIG_RPMSG_CHAR=y · 33 unmodified lines | ||
| 162 | 164 | CONFIG_RPMSG_CTRL=y |
| 163 | 165 | CONFIG_RPMSG_VIRTIO=y |
| 164 | 166 | CONFIG_ARCH_R9A07G043=y |
| 167 | +CONFIG_LIBNVDIMM=y | |
| 165 | 168 | CONFIG_EXT4_FS=y |
| 166 | 169 | CONFIG_EXT4_FS_POSIX_ACL=y |
| 167 | 170 | CONFIG_EXT4_FS_SECURITY=y |
| @@ -47,6 +47,22 @@ static bool errata_probe_cmo(unsigned int stage, · 46 unmodified lines | ||
| 47 | 47 | return true; |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | +static bool errata_probe_pmu(unsigned int stage, | |
| 51 | + unsigned long arch_id, unsigned long impid) | |
| 52 | +{ | |
| 53 | + if (!IS_ENABLED(CONFIG_ERRATA_THEAD_PMU)) | |
| 54 | + return false; | |
| 55 | + | |
| 56 | + /* target-c9xx cores report arch_id and impid as 0 */ | |
| 57 | + if (arch_id != 0 || impid != 0) | |
| 58 | + return false; | |
| 59 | + | |
| 60 | + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT) | |
| 61 | + return false; | |
| 62 | + | |
| 63 | + return true; | |
| 64 | +} | |
| 65 | + | |
| 50 | 66 | static u32 thead_errata_probe(unsigned int stage, |
| 51 | 67 | unsigned long archid, unsigned long impid) |
| 52 | 68 | { |
| @@ -58,6 +74,9 @@ static u32 thead_errata_probe(unsigned int stage, · 5 unmodified lines | ||
| 58 | 74 | if (errata_probe_cmo(stage, archid, impid)) |
| 59 | 75 | cpu_req_errata |= BIT(ERRATA_THEAD_CMO); |
| 60 | 76 | |
| 77 | + if (errata_probe_pmu(stage, archid, impid)) | |
| 78 | + cpu_req_errata |= BIT(ERRATA_THEAD_PMU); | |
| 79 | + | |
| 61 | 80 | return cpu_req_errata; |
| 62 | 81 | } |
| 63 | 82 | |
| @@ -33,7 +33,7 @@ · 32 unmodified lines | ||
| 33 | 33 | .endif |
| 34 | 34 | .endm |
| 35 | 35 | |
| 36 | −.macro __ALTERNATIVE_CFG old_c, new_c, vendor_id, errata_id, enable | |
| 36 | +.macro ALTERNATIVE_CFG old_c, new_c, vendor_id, errata_id, enable | |
| 37 | 37 | 886 : |
| 38 | 38 | .option push |
| 39 | 39 | .option norvc |
| @@ -44,30 +44,14 @@ · 4 unmodified lines | ||
| 44 | 44 | ALT_NEW_CONTENT \vendor_id, \errata_id, \enable, \new_c |
| 45 | 45 | .endm |
| 46 | 46 | |
| 47 | −#define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, CONFIG_k) \ | |
| 48 | − __ALTERNATIVE_CFG old_c, new_c, vendor_id, errata_id, IS_ENABLED(CONFIG_k) | |
| 49 | − | |
| 50 | −.macro __ALTERNATIVE_CFG_2 old_c, new_c_1, vendor_id_1, errata_id_1, enable_1, \ | |
| 51 | − new_c_2, vendor_id_2, errata_id_2, enable_2 | |
| 52 | −886 : | |
| 53 | − .option push | |
| 54 | − .option norvc | |
| 55 | − .option norelax | |
| 56 | − \old_c | |
| 57 | − .option pop | |
| 58 | −887 : | |
| 59 | − ALT_NEW_CONTENT \vendor_id_1, \errata_id_1, \enable_1, \new_c_1 | |
| 47 | +.macro ALTERNATIVE_CFG_2 old_c, new_c_1, vendor_id_1, errata_id_1, enable_1, \ | |
| 48 | + new_c_2, vendor_id_2, errata_id_2, enable_2 | |
| 49 | + ALTERNATIVE_CFG \old_c, \new_c_1, \vendor_id_1, \errata_id_1, \enable_1 | |
| 60 | 50 | ALT_NEW_CONTENT \vendor_id_2, \errata_id_2, \enable_2, \new_c_2 |
| 61 | 51 | .endm |
| 62 | 52 | |
| 63 | −#define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, \ | |
| 64 | − CONFIG_k_1, \ | |
| 65 | − new_c_2, vendor_id_2, errata_id_2, \ | |
| 66 | − CONFIG_k_2) \ | |
| 67 | − __ALTERNATIVE_CFG_2 old_c, new_c_1, vendor_id_1, errata_id_1, \ | |
| 68 | − IS_ENABLED(CONFIG_k_1), \ | |
| 69 | − new_c_2, vendor_id_2, errata_id_2, \ | |
| 70 | − IS_ENABLED(CONFIG_k_2) | |
| 53 | +#define __ALTERNATIVE_CFG(...) ALTERNATIVE_CFG __VA_ARGS__ | |
| 54 | +#define __ALTERNATIVE_CFG_2(...) ALTERNATIVE_CFG_2 __VA_ARGS__ | |
| 71 | 55 | |
| 72 | 56 | #else /* !__ASSEMBLY__ */ |
| 73 | 57 | |
| @@ -109,63 +93,44 @@ · 35 unmodified lines | ||
| 109 | 93 | "887 :\n" \ |
| 110 | 94 | ALT_NEW_CONTENT(vendor_id, errata_id, enable, new_c) |
| 111 | 95 | |
| 112 | −#define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, CONFIG_k) \ | |
| 113 | − __ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, IS_ENABLED(CONFIG_k)) | |
| 114 | − | |
| 115 | −#define __ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, \ | |
| 116 | − enable_1, \ | |
| 117 | − new_c_2, vendor_id_2, errata_id_2, \ | |
| 118 | − enable_2) \ | |
| 119 | − "886 :\n" \ | |
| 120 | − ".option push\n" \ | |
| 121 | − ".option norvc\n" \ | |
| 122 | − ".option norelax\n" \ | |
| 123 | − old_c "\n" \ | |
| 124 | − ".option pop\n" \ | |
| 125 | − "887 :\n" \ | |
| 126 | − ALT_NEW_CONTENT(vendor_id_1, errata_id_1, enable_1, new_c_1) \ | |
| 96 | +#define __ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, enable_1, \ | |
| 97 | + new_c_2, vendor_id_2, errata_id_2, enable_2) \ | |
| 98 | + __ALTERNATIVE_CFG(old_c, new_c_1, vendor_id_1, errata_id_1, enable_1) \ | |
| 127 | 99 | ALT_NEW_CONTENT(vendor_id_2, errata_id_2, enable_2, new_c_2) |
| 128 | 100 | |
| 129 | −#define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, \ | |
| 130 | − CONFIG_k_1, \ | |
| 131 | − new_c_2, vendor_id_2, errata_id_2, \ | |
| 132 | − CONFIG_k_2) \ | |
| 133 | − __ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, \ | |
| 134 | − IS_ENABLED(CONFIG_k_1), \ | |
| 135 | − new_c_2, vendor_id_2, errata_id_2, \ | |
| 136 | − IS_ENABLED(CONFIG_k_2)) | |
| 137 | − | |
| 138 | 101 | #endif /* __ASSEMBLY__ */ |
| 139 | 102 | |
| 103 | +#define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, CONFIG_k) \ | |
| 104 | + __ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, IS_ENABLED(CONFIG_k)) | |
| 105 | + | |
| 106 | +#define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, CONFIG_k_1, \ | |
| 107 | + new_c_2, vendor_id_2, errata_id_2, CONFIG_k_2) \ | |
| 108 | + __ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, IS_ENABLED(CONFIG_k_1), \ | |
| 109 | + new_c_2, vendor_id_2, errata_id_2, IS_ENABLED(CONFIG_k_2)) | |
| 110 | + | |
| 140 | 111 | #else /* CONFIG_RISCV_ALTERNATIVE */ |
| 141 | 112 | #ifdef __ASSEMBLY__ |
| 142 | 113 | |
| 143 | −.macro __ALTERNATIVE_CFG old_c | |
| 114 | +.macro ALTERNATIVE_CFG old_c | |
| 144 | 115 | \old_c |
| 145 | 116 | .endm |
| 146 | 117 | |
| 147 | −#define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, CONFIG_k) \ | |
| 148 | − __ALTERNATIVE_CFG old_c | |
| 118 | +#define _ALTERNATIVE_CFG(old_c, ...) \ | |
| 119 | + ALTERNATIVE_CFG old_c | |
| 149 | 120 | |
| 150 | −#define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, \ | |
| 151 | − CONFIG_k_1, \ | |
| 152 | − new_c_2, vendor_id_2, errata_id_2, \ | |
| 153 | − CONFIG_k_2) \ | |
| 154 | − __ALTERNATIVE_CFG old_c | |
| 121 | +#define _ALTERNATIVE_CFG_2(old_c, ...) \ | |
| 122 | + ALTERNATIVE_CFG old_c | |
| 155 | 123 | |
| 156 | 124 | #else /* !__ASSEMBLY__ */ |
| 157 | 125 | |
| 158 | −#define __ALTERNATIVE_CFG(old_c) \ | |
| 126 | +#define __ALTERNATIVE_CFG(old_c) \ | |
| 159 | 127 | old_c "\n" |
| 160 | 128 | |
| 161 | −#define _ALTERNATIVE_CFG(old_c, new_c, vendor_id, errata_id, CONFIG_k) \ | |
| 129 | +#define _ALTERNATIVE_CFG(old_c, ...) \ | |
| 162 | 130 | __ALTERNATIVE_CFG(old_c) |
| 163 | 131 | |
| 164 | −#define _ALTERNATIVE_CFG_2(old_c, new_c_1, vendor_id_1, errata_id_1, \ | |
| 165 | − CONFIG_k_1, \ | |
| 166 | − new_c_2, vendor_id_2, errata_id_2, \ | |
| 167 | − CONFIG_k_2) \ | |
| 168 | − __ALTERNATIVE_CFG(old_c) | |
| 132 | +#define _ALTERNATIVE_CFG_2(old_c, ...) \ | |
| 133 | + __ALTERNATIVE_CFG(old_c) | |
| 169 | 134 | |
| 170 | 135 | #endif /* __ASSEMBLY__ */ |
| 171 | 136 | #endif /* CONFIG_RISCV_ALTERNATIVE */ |
| @@ -193,13 +158,9 @@ · 21 unmodified lines | ||
| 193 | 158 | * on the following sample code and then replace ALTERNATIVE() with |
| 194 | 159 | * ALTERNATIVE_2() to append its customized content. |
| 195 | 160 | */ |
| 196 | −#define ALTERNATIVE_2(old_content, new_content_1, vendor_id_1, \ | |
| 197 | − errata_id_1, CONFIG_k_1, \ | |
| 198 | − new_content_2, vendor_id_2, \ | |
| 199 | − errata_id_2, CONFIG_k_2) \ | |
| 200 | − _ALTERNATIVE_CFG_2(old_content, new_content_1, vendor_id_1, \ | |
| 201 | − errata_id_1, CONFIG_k_1, \ | |
| 202 | − new_content_2, vendor_id_2, \ | |
| 203 | − errata_id_2, CONFIG_k_2) | |
| 161 | +#define ALTERNATIVE_2(old_content, new_content_1, vendor_id_1, errata_id_1, CONFIG_k_1, \ | |
| 162 | + new_content_2, vendor_id_2, errata_id_2, CONFIG_k_2) \ | |
| 163 | + _ALTERNATIVE_CFG_2(old_content, new_content_1, vendor_id_1, errata_id_1, CONFIG_k_1, \ | |
| 164 | + new_content_2, vendor_id_2, errata_id_2, CONFIG_k_2) | |
| 204 | 165 | |
| 205 | 166 | #endif |
| @@ -17,6 +17,13 @@ static inline void local_flush_icache_all(void) · 16 unmodified lines | ||
| 17 | 17 | |
| 18 | 18 | static inline void flush_dcache_page(struct page *page) |
| 19 | 19 | { |
| 20 | + /* | |
| 21 | + * HugeTLB pages are always fully mapped and only head page will be | |
| 22 | + * set PG_dcache_clean (see comments in flush_icache_pte()). | |
| 23 | + */ | |
| 24 | + if (PageHuge(page)) | |
| 25 | + page = compound_head(page); | |
| 26 | + | |
| 20 | 27 | if (test_bit(PG_dcache_clean, &page->flags)) |
| 21 | 28 | clear_bit(PG_dcache_clean, &page->flags); |
| 22 | 29 | } |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | #define ASM_ERRATA_LIST_H |
| 7 | 7 | |
| 8 | 8 | #include <asm/alternative.h> |
| 9 | +#include <asm/csr.h> | |
| 9 | 10 | #include <asm/vendorid_list.h> |
| 10 | 11 | |
| 11 | 12 | #ifdef CONFIG_ERRATA_SIFIVE |
| @@ -17,7 +18,8 @@ · 5 unmodified lines | ||
| 17 | 18 | #ifdef CONFIG_ERRATA_THEAD |
| 18 | 19 | #define ERRATA_THEAD_PBMT 0 |
| 19 | 20 | #define ERRATA_THEAD_CMO 1 |
| 20 | −#define ERRATA_THEAD_NUMBER 2 | |
| 21 | +#define ERRATA_THEAD_PMU 2 | |
| 22 | +#define ERRATA_THEAD_NUMBER 3 | |
| 21 | 23 | #endif |
| 22 | 24 | |
| 23 | 25 | #define CPUFEATURE_SVPBMT 0 |
| @@ -142,6 +144,18 @@ asm volatile(ALTERNATIVE_2( \ · 118 unmodified lines | ||
| 142 | 144 | "r"((unsigned long)(_start) + (_size)) \ |
| 143 | 145 | : "a0") |
| 144 | 146 | |
| 147 | +#define THEAD_C9XX_RV_IRQ_PMU 17 | |
| 148 | +#define THEAD_C9XX_CSR_SCOUNTEROF 0x5c5 | |
| 149 | + | |
| 150 | +#define ALT_SBI_PMU_OVERFLOW(__ovl) \ | |
| 151 | +asm volatile(ALTERNATIVE( \ | |
| 152 | + "csrr %0, " __stringify(CSR_SSCOUNTOVF), \ | |
| 153 | + "csrr %0, " __stringify(THEAD_C9XX_CSR_SCOUNTEROF), \ | |
| 154 | + THEAD_VENDOR_ID, ERRATA_THEAD_PMU, \ | |
| 155 | + CONFIG_ERRATA_THEAD_PMU) \ | |
| 156 | + : "=r" (__ovl) : \ | |
| 157 | + : "memory") | |
| 158 | + | |
| 145 | 159 | #endif /* __ASSEMBLY__ */ |
| 146 | 160 | |
| 147 | 161 | #endif |
| @@ -5,4 +5,10 @@ · 4 unmodified lines | ||
| 5 | 5 | #include <asm-generic/hugetlb.h> |
| 6 | 6 | #include <asm/page.h> |
| 7 | 7 | |
| 8 | +static inline void arch_clear_hugepage_flags(struct page *page) | |
| 9 | +{ | |
| 10 | + clear_bit(PG_dcache_clean, &page->flags); | |
| 11 | +} | |
| 12 | +#define arch_clear_hugepage_flags arch_clear_hugepage_flags | |
| 13 | + | |
| 8 | 14 | #endif /* _ASM_RISCV_HUGETLB_H */ |
| @@ -59,8 +59,9 @@ enum riscv_isa_ext_id { · 58 unmodified lines | ||
| 59 | 59 | RISCV_ISA_EXT_ZIHINTPAUSE, |
| 60 | 60 | RISCV_ISA_EXT_SSTC, |
| 61 | 61 | RISCV_ISA_EXT_SVINVAL, |
| 62 | − RISCV_ISA_EXT_ID_MAX = RISCV_ISA_EXT_MAX, | |
| 62 | + RISCV_ISA_EXT_ID_MAX | |
| 63 | 63 | }; |
| 64 | +static_assert(RISCV_ISA_EXT_ID_MAX <= RISCV_ISA_EXT_MAX); | |
| 64 | 65 | |
| 65 | 66 | /* |
| 66 | 67 | * This enum represents the logical ID for each RISC-V ISA extension static |
| @@ -135,4 +135,9 @@ __io_writes_outs(outs, u64, q, __io_pbr(), __io_paw()) · 134 unmodified lines | ||
| 135 | 135 | |
| 136 | 136 | #include <asm-generic/io.h> |
| 137 | 137 | |
| 138 | +#ifdef CONFIG_MMU | |
| 139 | +#define arch_memremap_wb(addr, size) \ | |
| 140 | + ((__force void *)ioremap_prot((addr), (size), _PAGE_KERNEL)) | |
| 141 | +#endif | |
| 142 | + | |
| 138 | 143 | #endif /* _ASM_RISCV_IO_H */ |
| @@ -39,6 +39,7 @@ crash_setup_regs(struct pt_regs *newregs, · 38 unmodified lines | ||
| 39 | 39 | #define ARCH_HAS_KIMAGE_ARCH |
| 40 | 40 | |
| 41 | 41 | struct kimage_arch { |
| 42 | + void *fdt; /* For CONFIG_KEXEC_FILE */ | |
| 42 | 43 | unsigned long fdt_addr; |
| 43 | 44 | }; |
| 44 | 45 | |
| @@ -62,6 +63,10 @@ int arch_kexec_apply_relocations_add(struct purgatory_info *pi, · 17 unmodified lines | ||
| 62 | 63 | const Elf_Shdr *relsec, |
| 63 | 64 | const Elf_Shdr *symtab); |
| 64 | 65 | #define arch_kexec_apply_relocations_add arch_kexec_apply_relocations_add |
| 66 | + | |
| 67 | +struct kimage; | |
| 68 | +int arch_kimage_file_post_load_cleanup(struct kimage *image); | |
| 69 | +#define arch_kimage_file_post_load_cleanup arch_kimage_file_post_load_cleanup | |
| 65 | 70 | #endif |
| 66 | 71 | |
| 67 | 72 | #endif |
| @@ -40,8 +40,6 @@ void arch_remove_kprobe(struct kprobe *p); · 39 unmodified lines | ||
| 40 | 40 | int kprobe_fault_handler(struct pt_regs *regs, unsigned int trapnr); |
| 41 | 41 | bool kprobe_breakpoint_handler(struct pt_regs *regs); |
| 42 | 42 | bool kprobe_single_step_handler(struct pt_regs *regs); |
| 43 | −void __kretprobe_trampoline(void); | |
| 44 | −void __kprobes *trampoline_probe_handler(struct pt_regs *regs); | |
| 45 | 43 | |
| 46 | 44 | #endif /* CONFIG_KPROBES */ |
| 47 | 45 | #endif /* _ASM_RISCV_KPROBES_H */ |
| @@ -19,6 +19,8 @@ typedef struct { · 18 unmodified lines | ||
| 19 | 19 | #ifdef CONFIG_SMP |
| 20 | 20 | /* A local icache flush is needed before user execution can resume. */ |
| 21 | 21 | cpumask_t icache_stale_mask; |
| 22 | + /* A local tlb flush is needed before user execution can resume. */ | |
| 23 | + cpumask_t tlb_stale_mask; | |
| 22 | 24 | #endif |
| 23 | 25 | } mm_context_t; |
| 24 | 26 | |
| @@ -123,20 +123,20 @@ extern phys_addr_t phys_ram_base; · 122 unmodified lines | ||
| 123 | 123 | ((x) >= PAGE_OFFSET && (!IS_ENABLED(CONFIG_64BIT) || (x) < PAGE_OFFSET + KERN_VIRT_SIZE)) |
| 124 | 124 | |
| 125 | 125 | #define linear_mapping_pa_to_va(x) ((void *)((unsigned long)(x) + kernel_map.va_pa_offset)) |
| 126 | −#define kernel_mapping_pa_to_va(y) ({ \ | |
| 127 | − unsigned long _y = y; \ | |
| 128 | − (IS_ENABLED(CONFIG_XIP_KERNEL) && _y < phys_ram_base) ? \ | |
| 129 | − (void *)((unsigned long)(_y) + kernel_map.va_kernel_xip_pa_offset) : \ | |
| 130 | − (void *)((unsigned long)(_y) + kernel_map.va_kernel_pa_offset + XIP_OFFSET); \ | |
| 126 | +#define kernel_mapping_pa_to_va(y) ({ \ | |
| 127 | + unsigned long _y = (unsigned long)(y); \ | |
| 128 | + (IS_ENABLED(CONFIG_XIP_KERNEL) && _y < phys_ram_base) ? \ | |
| 129 | + (void *)(_y + kernel_map.va_kernel_xip_pa_offset) : \ | |
| 130 | + (void *)(_y + kernel_map.va_kernel_pa_offset + XIP_OFFSET); \ | |
| 131 | 131 | }) |
| 132 | 132 | #define __pa_to_va_nodebug(x) linear_mapping_pa_to_va(x) |
| 133 | 133 | |
| 134 | 134 | #define linear_mapping_va_to_pa(x) ((unsigned long)(x) - kernel_map.va_pa_offset) |
| 135 | 135 | #define kernel_mapping_va_to_pa(y) ({ \ |
| 136 | − unsigned long _y = y; \ | |
| 137 | − (IS_ENABLED(CONFIG_XIP_KERNEL) && _y < kernel_map.virt_addr + XIP_OFFSET) ? \ | |
| 138 | − ((unsigned long)(_y) - kernel_map.va_kernel_xip_pa_offset) : \ | |
| 139 | − ((unsigned long)(_y) - kernel_map.va_kernel_pa_offset - XIP_OFFSET); \ | |
| 136 | + unsigned long _y = (unsigned long)(y); \ | |
| 137 | + (IS_ENABLED(CONFIG_XIP_KERNEL) && _y < kernel_map.virt_addr + XIP_OFFSET) ? \ | |
| 138 | + (_y - kernel_map.va_kernel_xip_pa_offset) : \ | |
| 139 | + (_y - kernel_map.va_kernel_pa_offset - XIP_OFFSET); \ | |
| 140 | 140 | }) |
| 141 | 141 | |
| 142 | 142 | #define __va_to_pa_nodebug(x) ({ \ |
| @@ -25,7 +25,11 @@ extern bool pgtable_l5_enabled; · 24 unmodified lines | ||
| 25 | 25 | #define PGDIR_MASK (~(PGDIR_SIZE - 1)) |
| 26 | 26 | |
| 27 | 27 | /* p4d is folded into pgd in case of 4-level page table */ |
| 28 | −#define P4D_SHIFT 39 | |
| 28 | +#define P4D_SHIFT_L3 30 | |
| 29 | +#define P4D_SHIFT_L4 39 | |
| 30 | +#define P4D_SHIFT_L5 39 | |
| 31 | +#define P4D_SHIFT (pgtable_l5_enabled ? P4D_SHIFT_L5 : \ | |
| 32 | + (pgtable_l4_enabled ? P4D_SHIFT_L4 : P4D_SHIFT_L3)) | |
| 29 | 33 | #define P4D_SIZE (_AC(1, UL) << P4D_SHIFT) |
| 30 | 34 | #define P4D_MASK (~(P4D_SIZE - 1)) |
| 31 | 35 | |
| @@ -415,9 +415,12 @@ static inline void update_mmu_cache(struct vm_area_struct *vma, · 414 unmodified lines | ||
| 415 | 415 | * Relying on flush_tlb_fix_spurious_fault would suffice, but |
| 416 | 416 | * the extra traps reduce performance. So, eagerly SFENCE.VMA. |
| 417 | 417 | */ |
| 418 | − local_flush_tlb_page(address); | |
| 418 | + flush_tlb_page(vma, address); | |
| 419 | 419 | } |
| 420 | 420 | |
| 421 | +#define __HAVE_ARCH_UPDATE_MMU_TLB | |
| 422 | +#define update_mmu_tlb update_mmu_cache | |
| 423 | + | |
| 421 | 424 | static inline void update_mmu_cache_pmd(struct vm_area_struct *vma, |
| 422 | 425 | unsigned long address, pmd_t *pmdp) |
| 423 | 426 | { |
| @@ -327,4 +327,9 @@ int sbi_err_map_linux_errno(int err); · 326 unmodified lines | ||
| 327 | 327 | static inline int sbi_remote_fence_i(const struct cpumask *cpu_mask) { return -1; } |
| 328 | 328 | static inline void sbi_init(void) {} |
| 329 | 329 | #endif /* CONFIG_RISCV_SBI */ |
| 330 | + | |
| 331 | +unsigned long riscv_cached_mvendorid(unsigned int cpu_id); | |
| 332 | +unsigned long riscv_cached_marchid(unsigned int cpu_id); | |
| 333 | +unsigned long riscv_cached_mimpid(unsigned int cpu_id); | |
| 334 | + | |
| 330 | 335 | #endif /* _ASM_RISCV_SBI_H */ |
| @@ -22,6 +22,24 @@ static inline void local_flush_tlb_page(unsigned long addr) · 21 unmodified lines | ||
| 22 | 22 | { |
| 23 | 23 | ALT_FLUSH_TLB_PAGE(__asm__ __volatile__ ("sfence.vma %0" : : "r" (addr) : "memory")); |
| 24 | 24 | } |
| 25 | + | |
| 26 | +static inline void local_flush_tlb_all_asid(unsigned long asid) | |
| 27 | +{ | |
| 28 | + __asm__ __volatile__ ("sfence.vma x0, %0" | |
| 29 | + : | |
| 30 | + : "r" (asid) | |
| 31 | + : "memory"); | |
| 32 | +} | |
| 33 | + | |
| 34 | +static inline void local_flush_tlb_page_asid(unsigned long addr, | |
| 35 | + unsigned long asid) | |
| 36 | +{ | |
| 37 | + __asm__ __volatile__ ("sfence.vma %0, %1" | |
| 38 | + : | |
| 39 | + : "r" (addr), "r" (asid) | |
| 40 | + : "memory"); | |
| 41 | +} | |
| 42 | + | |
| 25 | 43 | #else /* CONFIG_MMU */ |
| 26 | 44 | #define local_flush_tlb_all() do { } while (0) |
| 27 | 45 | #define local_flush_tlb_page(addr) do { } while (0) |
| @@ -10,7 +10,7 @@ · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | /* |
| 12 | 12 | * All systems with an MMU have a VDSO, but systems without an MMU don't |
| 13 | − * support shared libraries and therefor don't have one. | |
| 13 | + * support shared libraries and therefore don't have one. | |
| 14 | 14 | */ |
| 15 | 15 | #ifdef CONFIG_MMU |
| 16 | 16 | |
| @@ -1,4 +1,22 @@ | ||
| 1 | 1 | #ifndef _ASM_RISCV_VMALLOC_H |
| 2 | 2 | #define _ASM_RISCV_VMALLOC_H |
| 3 | 3 | |
| 4 | +#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP | |
| 5 | + | |
| 6 | +#define IOREMAP_MAX_ORDER (PUD_SHIFT) | |
| 7 | + | |
| 8 | +#define arch_vmap_pud_supported arch_vmap_pud_supported | |
| 9 | +static inline bool arch_vmap_pud_supported(pgprot_t prot) | |
| 10 | +{ | |
| 11 | + return true; | |
| 12 | +} | |
| 13 | + | |
| 14 | +#define arch_vmap_pmd_supported arch_vmap_pmd_supported | |
| 15 | +static inline bool arch_vmap_pmd_supported(pgprot_t prot) | |
| 16 | +{ | |
| 17 | + return true; | |
| 18 | +} | |
| 19 | + | |
| 20 | +#endif | |
| 21 | + | |
| 4 | 22 | #endif /* _ASM_RISCV_VMALLOC_H */ |
| @@ -15,19 +15,23 @@ struct ucontext { · 14 unmodified lines | ||
| 15 | 15 | struct ucontext *uc_link; |
| 16 | 16 | stack_t uc_stack; |
| 17 | 17 | sigset_t uc_sigmask; |
| 18 | − /* There's some padding here to allow sigset_t to be expanded in the | |
| 18 | + /* | |
| 19 | + * There's some padding here to allow sigset_t to be expanded in the | |
| 19 | 20 | * future. Though this is unlikely, other architectures put uc_sigmask |
| 20 | 21 | * at the end of this structure and explicitly state it can be |
| 21 | − * expanded, so we didn't want to box ourselves in here. */ | |
| 22 | + * expanded, so we didn't want to box ourselves in here. | |
| 23 | + */ | |
| 22 | 24 | __u8 __unused[1024 / 8 - sizeof(sigset_t)]; |
| 23 | − /* We can't put uc_sigmask at the end of this structure because we need | |
| 25 | + /* | |
| 26 | + * We can't put uc_sigmask at the end of this structure because we need | |
| 24 | 27 | * to be able to expand sigcontext in the future. For example, the |
| 25 | 28 | * vector ISA extension will almost certainly add ISA state. We want |
| 26 | 29 | * to ensure all user-visible ISA state can be saved and restored via a |
| 27 | 30 | * ucontext, so we're putting this at the end in order to allow for |
| 28 | 31 | * infinite extensibility. Since we know this will be extended and we |
| 29 | 32 | * assume sigset_t won't be extended an extreme amount, we're |
| 30 | − * prioritizing this. */ | |
| 33 | + * prioritizing this. | |
| 34 | + */ | |
| 31 | 35 | struct sigcontext uc_mcontext; |
| 32 | 36 | }; |
| 33 | 37 | |
| @@ -81,6 +81,7 @@ obj-$(CONFIG_KGDB) += kgdb.o · 80 unmodified lines | ||
| 81 | 81 | obj-$(CONFIG_KEXEC_CORE) += kexec_relocate.o crash_save_regs.o machine_kexec.o |
| 82 | 82 | obj-$(CONFIG_KEXEC_FILE) += elf_kexec.o machine_kexec_file.o |
| 83 | 83 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o |
| 84 | +obj-$(CONFIG_CRASH_CORE) += crash_core.o | |
| 84 | 85 | |
| 85 | 86 | obj-$(CONFIG_JUMP_LABEL) += jump_label.o |
| 86 | 87 | |
| @@ -70,8 +70,6 @@ int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid) · 69 unmodified lines | ||
| 70 | 70 | return -1; |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | −#ifdef CONFIG_PROC_FS | |
| 74 | − | |
| 75 | 73 | struct riscv_cpuinfo { |
| 76 | 74 | unsigned long mvendorid; |
| 77 | 75 | unsigned long marchid; |
| @@ -79,6 +77,30 @@ struct riscv_cpuinfo { · 1 unmodified line | ||
| 79 | 77 | }; |
| 80 | 78 | static DEFINE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo); |
| 81 | 79 | |
| 80 | +unsigned long riscv_cached_mvendorid(unsigned int cpu_id) | |
| 81 | +{ | |
| 82 | + struct riscv_cpuinfo *ci = per_cpu_ptr(&riscv_cpuinfo, cpu_id); | |
| 83 | + | |
| 84 | + return ci->mvendorid; | |
| 85 | +} | |
| 86 | +EXPORT_SYMBOL(riscv_cached_mvendorid); | |
| 87 | + | |
| 88 | +unsigned long riscv_cached_marchid(unsigned int cpu_id) | |
| 89 | +{ | |
| 90 | + struct riscv_cpuinfo *ci = per_cpu_ptr(&riscv_cpuinfo, cpu_id); | |
| 91 | + | |
| 92 | + return ci->marchid; | |
| 93 | +} | |
| 94 | +EXPORT_SYMBOL(riscv_cached_marchid); | |
| 95 | + | |
| 96 | +unsigned long riscv_cached_mimpid(unsigned int cpu_id) | |
| 97 | +{ | |
| 98 | + struct riscv_cpuinfo *ci = per_cpu_ptr(&riscv_cpuinfo, cpu_id); | |
| 99 | + | |
| 100 | + return ci->mimpid; | |
| 101 | +} | |
| 102 | +EXPORT_SYMBOL(riscv_cached_mimpid); | |
| 103 | + | |
| 82 | 104 | static int riscv_cpuinfo_starting(unsigned int cpu) |
| 83 | 105 | { |
| 84 | 106 | struct riscv_cpuinfo *ci = this_cpu_ptr(&riscv_cpuinfo); |
| @@ -113,7 +135,9 @@ static int __init riscv_cpuinfo_init(void) · 28 unmodified lines | ||
| 113 | 135 | |
| 114 | 136 | return 0; |
| 115 | 137 | } |
| 116 | −device_initcall(riscv_cpuinfo_init); | |
| 138 | +arch_initcall(riscv_cpuinfo_init); | |
| 139 | + | |
| 140 | +#ifdef CONFIG_PROC_FS | |
| 117 | 141 | |
| 118 | 142 | #define __RISCV_ISA_EXT_DATA(UPROP, EXTID) \ |
| 119 | 143 | { \ |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <linux/bitmap.h> |
| 10 | 10 | #include <linux/ctype.h> |
| 11 | 11 | #include <linux/libfdt.h> |
| 12 | +#include <linux/log2.h> | |
| 12 | 13 | #include <linux/module.h> |
| 13 | 14 | #include <linux/of.h> |
| 14 | 15 | #include <asm/alternative.h> |
| @@ -68,21 +69,38 @@ bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit) · 53 unmodified lines | ||
| 68 | 69 | } |
| 69 | 70 | EXPORT_SYMBOL_GPL(__riscv_isa_extension_available); |
| 70 | 71 | |
| 72 | +static bool riscv_isa_extension_check(int id) | |
| 73 | +{ | |
| 74 | + switch (id) { | |
| 75 | + case RISCV_ISA_EXT_ZICBOM: | |
| 76 | + if (!riscv_cbom_block_size) { | |
| 77 | + pr_err("Zicbom detected in ISA string, but no cbom-block-size found\n"); | |
| 78 | + return false; | |
| 79 | + } else if (!is_power_of_2(riscv_cbom_block_size)) { | |
| 80 | + pr_err("cbom-block-size present, but is not a power-of-2\n"); | |
| 81 | + return false; | |
| 82 | + } | |
| 83 | + return true; | |
| 84 | + } | |
| 85 | + | |
| 86 | + return true; | |
| 87 | +} | |
| 88 | + | |
| 71 | 89 | void __init riscv_fill_hwcap(void) |
| 72 | 90 | { |
| 73 | 91 | struct device_node *node; |
| 74 | 92 | const char *isa; |
| 75 | 93 | char print_str[NUM_ALPHA_EXTS + 1]; |
| 76 | 94 | int i, j, rc; |
| 77 | − static unsigned long isa2hwcap[256] = {0}; | |
| 95 | + unsigned long isa2hwcap[26] = {0}; | |
| 78 | 96 | unsigned long hartid; |
| 79 | 97 | |
| 80 | − isa2hwcap['i'] = isa2hwcap['I'] = COMPAT_HWCAP_ISA_I; | |
| 81 | − isa2hwcap['m'] = isa2hwcap['M'] = COMPAT_HWCAP_ISA_M; | |
| 82 | − isa2hwcap['a'] = isa2hwcap['A'] = COMPAT_HWCAP_ISA_A; | |
| 83 | − isa2hwcap['f'] = isa2hwcap['F'] = COMPAT_HWCAP_ISA_F; | |
| 84 | − isa2hwcap['d'] = isa2hwcap['D'] = COMPAT_HWCAP_ISA_D; | |
| 85 | − isa2hwcap['c'] = isa2hwcap['C'] = COMPAT_HWCAP_ISA_C; | |
| 98 | + isa2hwcap['i' - 'a'] = COMPAT_HWCAP_ISA_I; | |
| 99 | + isa2hwcap['m' - 'a'] = COMPAT_HWCAP_ISA_M; | |
| 100 | + isa2hwcap['a' - 'a'] = COMPAT_HWCAP_ISA_A; | |
| 101 | + isa2hwcap['f' - 'a'] = COMPAT_HWCAP_ISA_F; | |
| 102 | + isa2hwcap['d' - 'a'] = COMPAT_HWCAP_ISA_D; | |
| 103 | + isa2hwcap['c' - 'a'] = COMPAT_HWCAP_ISA_C; | |
| 86 | 104 | |
| 87 | 105 | elf_hwcap = 0; |
| 88 | 106 | |
| @@ -189,15 +207,20 @@ void __init riscv_fill_hwcap(void) · 100 unmodified lines | ||
| 189 | 207 | #define SET_ISA_EXT_MAP(name, bit) \ |
| 190 | 208 | do { \ |
| 191 | 209 | if ((ext_end - ext == sizeof(name) - 1) && \ |
| 192 | − !memcmp(ext, name, sizeof(name) - 1)) \ | |
| 210 | + !memcmp(ext, name, sizeof(name) - 1) && \ | |
| 211 | + riscv_isa_extension_check(bit)) \ | |
| 193 | 212 | set_bit(bit, this_isa); \ |
| 194 | 213 | } while (false) \ |
| 195 | 214 | |
| 196 | 215 | if (unlikely(ext_err)) |
| 197 | 216 | continue; |
| 198 | 217 | if (!ext_long) { |
| 199 | − this_hwcap |= isa2hwcap[(unsigned char)(*ext)]; | |
| 200 | − set_bit(*ext - 'a', this_isa); | |
| 218 | + int nr = *ext - 'a'; | |
| 219 | + | |
| 220 | + if (riscv_isa_extension_check(nr)) { | |
| 221 | + this_hwcap |= isa2hwcap[nr]; | |
| 222 | + set_bit(nr, this_isa); | |
| 223 | + } | |
| 201 | 224 | } else { |
| 202 | 225 | SET_ISA_EXT_MAP("sscofpmf", RISCV_ISA_EXT_SSCOFPMF); |
| 203 | 226 | SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT); |
| @@ -0,0 +1,21 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-only | |
| 2 | + | |
| 3 | +#include <linux/crash_core.h> | |
| 4 | +#include <linux/pagemap.h> | |
| 5 | + | |
| 6 | +void arch_crash_save_vmcoreinfo(void) | |
| 7 | +{ | |
| 8 | + VMCOREINFO_NUMBER(VA_BITS); | |
| 9 | + VMCOREINFO_NUMBER(phys_ram_base); | |
| 10 | + | |
| 11 | + vmcoreinfo_append_str("NUMBER(PAGE_OFFSET)=0x%lx\n", PAGE_OFFSET); | |
| 12 | + vmcoreinfo_append_str("NUMBER(VMALLOC_START)=0x%lx\n", VMALLOC_START); | |
| 13 | + vmcoreinfo_append_str("NUMBER(VMALLOC_END)=0x%lx\n", VMALLOC_END); | |
| 14 | + vmcoreinfo_append_str("NUMBER(VMEMMAP_START)=0x%lx\n", VMEMMAP_START); | |
| 15 | + vmcoreinfo_append_str("NUMBER(VMEMMAP_END)=0x%lx\n", VMEMMAP_END); | |
| 16 | +#ifdef CONFIG_64BIT | |
| 17 | + vmcoreinfo_append_str("NUMBER(MODULES_VADDR)=0x%lx\n", MODULES_VADDR); | |
| 18 | + vmcoreinfo_append_str("NUMBER(MODULES_END)=0x%lx\n", MODULES_END); | |
| 19 | +#endif | |
| 20 | + vmcoreinfo_append_str("NUMBER(KERNEL_LINK_ADDR)=0x%lx\n", KERNEL_LINK_ADDR); | |
| 21 | +} | |
| @@ -21,6 +21,18 @@ · 20 unmodified lines | ||
| 21 | 21 | #include <linux/memblock.h> |
| 22 | 22 | #include <asm/setup.h> |
| 23 | 23 | |
| 24 | +int arch_kimage_file_post_load_cleanup(struct kimage *image) | |
| 25 | +{ | |
| 26 | + kvfree(image->arch.fdt); | |
| 27 | + image->arch.fdt = NULL; | |
| 28 | + | |
| 29 | + vfree(image->elf_headers); | |
| 30 | + image->elf_headers = NULL; | |
| 31 | + image->elf_headers_sz = 0; | |
| 32 | + | |
| 33 | + return kexec_image_post_load_cleanup_default(image); | |
| 34 | +} | |
| 35 | + | |
| 24 | 36 | static int riscv_kexec_elf_load(struct kimage *image, struct elfhdr *ehdr, |
| 25 | 37 | struct kexec_elf_info *elf_info, unsigned long old_pbase, |
| 26 | 38 | unsigned long new_pbase) |
| @@ -298,6 +310,8 @@ static void *elf_kexec_load(struct kimage *image, char *kernel_buf, · 271 unmodified lines | ||
| 298 | 310 | pr_err("Error add DTB kbuf ret=%d\n", ret); |
| 299 | 311 | goto out_free_fdt; |
| 300 | 312 | } |
| 313 | + /* Cache the fdt buffer address for memory cleanup */ | |
| 314 | + image->arch.fdt = fdt; | |
| 301 | 315 | pr_notice("Loaded device tree at 0x%lx\n", kbuf.mem); |
| 302 | 316 | goto out; |
| 303 | 317 | |
| @@ -248,7 +248,7 @@ ret_from_syscall_rejected: · 247 unmodified lines | ||
| 248 | 248 | andi t0, t0, _TIF_SYSCALL_WORK |
| 249 | 249 | bnez t0, handle_syscall_trace_exit |
| 250 | 250 | |
| 251 | −ret_from_exception: | |
| 251 | +SYM_CODE_START_NOALIGN(ret_from_exception) | |
| 252 | 252 | REG_L s0, PT_STATUS(sp) |
| 253 | 253 | csrc CSR_STATUS, SR_IE |
| 254 | 254 | #ifdef CONFIG_TRACE_IRQFLAGS |
| @@ -262,13 +262,13 @@ ret_from_exception: · 7 unmodified lines | ||
| 262 | 262 | andi s0, s0, SR_SPP |
| 263 | 263 | #endif |
| 264 | 264 | bnez s0, resume_kernel |
| 265 | +SYM_CODE_END(ret_from_exception) | |
| 265 | 266 | |
| 266 | −resume_userspace: | |
| 267 | 267 | /* Interrupts must be disabled here so flags are checked atomically */ |
| 268 | 268 | REG_L s0, TASK_TI_FLAGS(tp) /* current_thread_info->flags */ |
| 269 | 269 | andi s1, s0, _TIF_WORK_MASK |
| 270 | − bnez s1, work_pending | |
| 271 | − | |
| 270 | + bnez s1, resume_userspace_slow | |
| 271 | +resume_userspace: | |
| 272 | 272 | #ifdef CONFIG_CONTEXT_TRACKING_USER |
| 273 | 273 | call user_enter_callable |
| 274 | 274 | #endif |
| @@ -368,19 +368,12 @@ resume_kernel: · 93 unmodified lines | ||
| 368 | 368 | j restore_all |
| 369 | 369 | #endif |
| 370 | 370 | |
| 371 | −work_pending: | |
| 371 | +resume_userspace_slow: | |
| 372 | 372 | /* Enter slow path for supplementary processing */ |
| 373 | − la ra, ret_from_exception | |
| 374 | − andi s1, s0, _TIF_NEED_RESCHED | |
| 375 | − bnez s1, work_resched | |
| 376 | −work_notifysig: | |
| 377 | − /* Handle pending signals and notify-resume requests */ | |
| 378 | − csrs CSR_STATUS, SR_IE /* Enable interrupts for do_notify_resume() */ | |
| 379 | 373 | move a0, sp /* pt_regs */ |
| 380 | 374 | move a1, s0 /* current_thread_info->flags */ |
| 381 | − tail do_notify_resume | |
| 382 | −work_resched: | |
| 383 | − tail schedule | |
| 375 | + call do_work_pending | |
| 376 | + j resume_userspace | |
| 384 | 377 | |
| 385 | 378 | /* Slow paths for ptrace. */ |
| 386 | 379 | handle_syscall_trace_enter: |
| @@ -15,8 +15,8 @@ · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | .macro SAVE_ABI_STATE |
| 17 | 17 | addi sp, sp, -16 |
| 18 | − sd s0, 0(sp) | |
| 19 | − sd ra, 8(sp) | |
| 18 | + REG_S s0, 0*SZREG(sp) | |
| 19 | + REG_S ra, 1*SZREG(sp) | |
| 20 | 20 | addi s0, sp, 16 |
| 21 | 21 | .endm |
| 22 | 22 | |
| @@ -25,24 +25,26 @@ · 2 unmodified lines | ||
| 25 | 25 | * register if a0 was not saved. |
| 26 | 26 | */ |
| 27 | 27 | .macro SAVE_RET_ABI_STATE |
| 28 | − addi sp, sp, -32 | |
| 29 | − sd s0, 16(sp) | |
| 30 | − sd ra, 24(sp) | |
| 31 | − sd a0, 8(sp) | |
| 32 | − addi s0, sp, 32 | |
| 28 | + addi sp, sp, -4*SZREG | |
| 29 | + REG_S s0, 2*SZREG(sp) | |
| 30 | + REG_S ra, 3*SZREG(sp) | |
| 31 | + REG_S a0, 1*SZREG(sp) | |
| 32 | + REG_S a1, 0*SZREG(sp) | |
| 33 | + addi s0, sp, 4*SZREG | |
| 33 | 34 | .endm |
| 34 | 35 | |
| 35 | 36 | .macro RESTORE_ABI_STATE |
| 36 | − ld ra, 8(sp) | |
| 37 | − ld s0, 0(sp) | |
| 37 | + REG_L ra, 1*SZREG(sp) | |
| 38 | + REG_L s0, 0*SZREG(sp) | |
| 38 | 39 | addi sp, sp, 16 |
| 39 | 40 | .endm |
| 40 | 41 | |
| 41 | 42 | .macro RESTORE_RET_ABI_STATE |
| 42 | − ld ra, 24(sp) | |
| 43 | − ld s0, 16(sp) | |
| 44 | − ld a0, 8(sp) | |
| 45 | − addi sp, sp, 32 | |
| 43 | + REG_L ra, 3*SZREG(sp) | |
| 44 | + REG_L s0, 2*SZREG(sp) | |
| 45 | + REG_L a0, 1*SZREG(sp) | |
| 46 | + REG_L a1, 0*SZREG(sp) | |
| 47 | + addi sp, sp, 4*SZREG | |
| 46 | 48 | .endm |
| 47 | 49 | |
| 48 | 50 | ENTRY(ftrace_stub) |
| @@ -71,9 +73,9 @@ ENTRY(return_to_handler) · 22 unmodified lines | ||
| 71 | 73 | mv a0, t6 |
| 72 | 74 | #endif |
| 73 | 75 | call ftrace_return_to_handler |
| 74 | − mv a1, a0 | |
| 76 | + mv a2, a0 | |
| 75 | 77 | RESTORE_RET_ABI_STATE |
| 76 | − jalr a1 | |
| 78 | + jalr a2 | |
| 77 | 79 | ENDPROC(return_to_handler) |
| 78 | 80 | #endif |
| 79 | 81 | |
| @@ -82,16 +84,16 @@ ENTRY(MCOUNT_NAME) · 2 unmodified lines | ||
| 82 | 84 | la t4, ftrace_stub |
| 83 | 85 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
| 84 | 86 | la t0, ftrace_graph_return |
| 85 | − ld t1, 0(t0) | |
| 87 | + REG_L t1, 0(t0) | |
| 86 | 88 | bne t1, t4, do_ftrace_graph_caller |
| 87 | 89 | |
| 88 | 90 | la t3, ftrace_graph_entry |
| 89 | − ld t2, 0(t3) | |
| 91 | + REG_L t2, 0(t3) | |
| 90 | 92 | la t6, ftrace_graph_entry_stub |
| 91 | 93 | bne t2, t6, do_ftrace_graph_caller |
| 92 | 94 | #endif |
| 93 | 95 | la t3, ftrace_trace_function |
| 94 | − ld t5, 0(t3) | |
| 96 | + REG_L t5, 0(t3) | |
| 95 | 97 | bne t5, t4, do_trace |
| 96 | 98 | ret |
| 97 | 99 | |
| @@ -101,10 +103,10 @@ ENTRY(MCOUNT_NAME) · 3 unmodified lines | ||
| 101 | 103 | * prepare_to_return(&ra_to_caller_of_caller, ra_to_caller) |
| 102 | 104 | */ |
| 103 | 105 | do_ftrace_graph_caller: |
| 104 | − addi a0, s0, -8 | |
| 106 | + addi a0, s0, -SZREG | |
| 105 | 107 | mv a1, ra |
| 106 | 108 | #ifdef HAVE_FUNCTION_GRAPH_FP_TEST |
| 107 | − ld a2, -16(s0) | |
| 109 | + REG_L a2, -2*SZREG(s0) | |
| 108 | 110 | #endif |
| 109 | 111 | SAVE_ABI_STATE |
| 110 | 112 | call prepare_ftrace_return |
| @@ -117,7 +119,7 @@ do_ftrace_graph_caller: · 6 unmodified lines | ||
| 117 | 119 | * (*ftrace_trace_function)(ra_to_caller, ra_to_caller_of_caller) |
| 118 | 120 | */ |
| 119 | 121 | do_trace: |
| 120 | − ld a1, -8(s0) | |
| 122 | + REG_L a1, -SZREG(s0) | |
| 121 | 123 | mv a0, ra |
| 122 | 124 | |
| 123 | 125 | SAVE_ABI_STATE |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | obj-$(CONFIG_KPROBES) += kprobes.o decode-insn.o simulate-insn.o |
| 3 | −obj-$(CONFIG_KPROBES) += kprobes_trampoline.o | |
| 3 | +obj-$(CONFIG_RETHOOK) += rethook.o rethook_trampoline.o | |
| 4 | 4 | obj-$(CONFIG_KPROBES_ON_FTRACE) += ftrace.o |
| 5 | 5 | obj-$(CONFIG_UPROBES) += uprobes.o decode-insn.o simulate-insn.o |
| 6 | 6 | CFLAGS_REMOVE_simulate-insn.o = $(CC_FLAGS_FTRACE) |
| @@ -345,19 +345,6 @@ int __init arch_populate_kprobe_blacklist(void) · 344 unmodified lines | ||
| 345 | 345 | return ret; |
| 346 | 346 | } |
| 347 | 347 | |
| 348 | −void __kprobes __used *trampoline_probe_handler(struct pt_regs *regs) | |
| 349 | −{ | |
| 350 | − return (void *)kretprobe_trampoline_handler(regs, NULL); | |
| 351 | −} | |
| 352 | − | |
| 353 | −void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, | |
| 354 | − struct pt_regs *regs) | |
| 355 | −{ | |
| 356 | − ri->ret_addr = (kprobe_opcode_t *)regs->ra; | |
| 357 | − ri->fp = NULL; | |
| 358 | − regs->ra = (unsigned long) &__kretprobe_trampoline; | |
| 359 | −} | |
| 360 | − | |
| 361 | 348 | int __kprobes arch_trampoline_kprobe(struct kprobe *p) |
| 362 | 349 | { |
| 363 | 350 | return 0; |
| @@ -0,0 +1,27 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-only | |
| 2 | +/* | |
| 3 | + * Generic return hook for riscv. | |
| 4 | + */ | |
| 5 | + | |
| 6 | +#include <linux/kprobes.h> | |
| 7 | +#include <linux/rethook.h> | |
| 8 | +#include "rethook.h" | |
| 9 | + | |
| 10 | +/* This is called from arch_rethook_trampoline() */ | |
| 11 | +unsigned long __used arch_rethook_trampoline_callback(struct pt_regs *regs) | |
| 12 | +{ | |
| 13 | + return rethook_trampoline_handler(regs, regs->s0); | |
| 14 | +} | |
| 15 | + | |
| 16 | +NOKPROBE_SYMBOL(arch_rethook_trampoline_callback); | |
| 17 | + | |
| 18 | +void arch_rethook_prepare(struct rethook_node *rhn, struct pt_regs *regs, bool mcount) | |
| 19 | +{ | |
| 20 | + rhn->ret_addr = regs->ra; | |
| 21 | + rhn->frame = regs->s0; | |
| 22 | + | |
| 23 | + /* replace return addr with trampoline */ | |
| 24 | + regs->ra = (unsigned long)arch_rethook_trampoline; | |
| 25 | +} | |
| 26 | + | |
| 27 | +NOKPROBE_SYMBOL(arch_rethook_prepare); | |
| @@ -0,0 +1,8 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ | |
| 2 | +#ifndef __RISCV_RETHOOK_H | |
| 3 | +#define __RISCV_RETHOOK_H | |
| 4 | + | |
| 5 | +unsigned long arch_rethook_trampoline_callback(struct pt_regs *regs); | |
| 6 | +void arch_rethook_prepare(struct rethook_node *rhn, struct pt_regs *regs, bool mcount); | |
| 7 | + | |
| 8 | +#endif | |
| @@ -75,13 +75,13 @@ · 74 unmodified lines | ||
| 75 | 75 | REG_L x31, PT_T6(sp) |
| 76 | 76 | .endm |
| 77 | 77 | |
| 78 | −ENTRY(__kretprobe_trampoline) | |
| 78 | +ENTRY(arch_rethook_trampoline) | |
| 79 | 79 | addi sp, sp, -(PT_SIZE_ON_STACK) |
| 80 | 80 | save_all_base_regs |
| 81 | 81 | |
| 82 | 82 | move a0, sp /* pt_regs */ |
| 83 | 83 | |
| 84 | − call trampoline_probe_handler | |
| 84 | + call arch_rethook_trampoline_callback | |
| 85 | 85 | |
| 86 | 86 | /* use the result as the return-address */ |
| 87 | 87 | move ra, a0 |
| @@ -90,4 +90,4 @@ ENTRY(__kretprobe_trampoline) · 2 unmodified lines | ||
| 90 | 90 | addi sp, sp, PT_SIZE_ON_STACK |
| 91 | 91 | |
| 92 | 92 | ret |
| 93 | −ENDPROC(__kretprobe_trampoline) | |
| 93 | +ENDPROC(arch_rethook_trampoline) | |
| @@ -313,19 +313,27 @@ static void do_signal(struct pt_regs *regs) · 312 unmodified lines | ||
| 313 | 313 | } |
| 314 | 314 | |
| 315 | 315 | /* |
| 316 | − * notification of userspace execution resumption | |
| 317 | − * - triggered by the _TIF_WORK_MASK flags | |
| 316 | + * Handle any pending work on the resume-to-userspace path, as indicated by | |
| 317 | + * _TIF_WORK_MASK. Entered from assembly with IRQs off. | |
| 318 | 318 | */ |
| 319 | −asmlinkage __visible void do_notify_resume(struct pt_regs *regs, | |
| 320 | − unsigned long thread_info_flags) | |
| 319 | +asmlinkage __visible void do_work_pending(struct pt_regs *regs, | |
| 320 | + unsigned long thread_info_flags) | |
| 321 | 321 | { |
| 322 | − if (thread_info_flags & _TIF_UPROBE) | |
| 323 | − uprobe_notify_resume(regs); | |
| 324 | − | |
| 325 | − /* Handle pending signal delivery */ | |
| 326 | − if (thread_info_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) | |
| 327 | − do_signal(regs); | |
| 328 | − | |
| 329 | − if (thread_info_flags & _TIF_NOTIFY_RESUME) | |
| 330 | − resume_user_mode_work(regs); | |
| 322 | + do { | |
| 323 | + if (thread_info_flags & _TIF_NEED_RESCHED) { | |
| 324 | + schedule(); | |
| 325 | + } else { | |
| 326 | + local_irq_enable(); | |
| 327 | + if (thread_info_flags & _TIF_UPROBE) | |
| 328 | + uprobe_notify_resume(regs); | |
| 329 | + /* Handle pending signal delivery */ | |
| 330 | + if (thread_info_flags & (_TIF_SIGPENDING | | |
| 331 | + _TIF_NOTIFY_SIGNAL)) | |
| 332 | + do_signal(regs); | |
| 333 | + if (thread_info_flags & _TIF_NOTIFY_RESUME) | |
| 334 | + resume_user_mode_work(regs); | |
| 335 | + } | |
| 336 | + local_irq_disable(); | |
| 337 | + thread_info_flags = read_thread_flags(); | |
| 338 | + } while (thread_info_flags & _TIF_WORK_MASK); | |
| 331 | 339 | } |
| @@ -16,6 +16,8 @@ · 15 unmodified lines | ||
| 16 | 16 | |
| 17 | 17 | #ifdef CONFIG_FRAME_POINTER |
| 18 | 18 | |
| 19 | +extern asmlinkage void ret_from_exception(void); | |
| 20 | + | |
| 19 | 21 | void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, |
| 20 | 22 | bool (*fn)(void *, unsigned long), void *arg) |
| 21 | 23 | { |
| @@ -58,7 +60,14 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs, · 36 unmodified lines | ||
| 58 | 60 | } else { |
| 59 | 61 | fp = frame->fp; |
| 60 | 62 | pc = ftrace_graph_ret_addr(current, NULL, frame->ra, |
| 61 | − (unsigned long *)(fp - 8)); | |
| 63 | + &frame->ra); | |
| 64 | + if (pc == (unsigned long)ret_from_exception) { | |
| 65 | + if (unlikely(!__kernel_text_address(pc) || !fn(arg, pc))) | |
| 66 | + break; | |
| 67 | + | |
| 68 | + pc = ((struct pt_regs *)sp)->epc; | |
| 69 | + fp = ((struct pt_regs *)sp)->s0; | |
| 70 | + } | |
| 62 | 71 | } |
| 63 | 72 | |
| 64 | 73 | } |
| @@ -208,18 +208,18 @@ int is_valid_bugaddr(unsigned long pc) · 207 unmodified lines | ||
| 208 | 208 | #endif /* CONFIG_GENERIC_BUG */ |
| 209 | 209 | |
| 210 | 210 | #ifdef CONFIG_VMAP_STACK |
| 211 | +/* | |
| 212 | + * Extra stack space that allows us to provide panic messages when the kernel | |
| 213 | + * has overflowed its stack. | |
| 214 | + */ | |
| 211 | 215 | static DEFINE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], |
| 212 | 216 | overflow_stack)__aligned(16); |
| 213 | 217 | /* |
| 214 | − * shadow stack, handled_ kernel_ stack_ overflow(in kernel/entry.S) is used | |
| 215 | − * to get per-cpu overflow stack(get_overflow_stack). | |
| 218 | + * A temporary stack for use by handle_kernel_stack_overflow. This is used so | |
| 219 | + * we can call into C code to get the per-hart overflow stack. Usage of this | |
| 220 | + * stack must be protected by spin_shadow_stack. | |
| 216 | 221 | */ |
| 217 | −long shadow_stack[SHADOW_OVERFLOW_STACK_SIZE/sizeof(long)]; | |
| 218 | −asmlinkage unsigned long get_overflow_stack(void) | |
| 219 | −{ | |
| 220 | − return (unsigned long)this_cpu_ptr(overflow_stack) + | |
| 221 | − OVERFLOW_STACK_SIZE; | |
| 222 | −} | |
| 222 | +long shadow_stack[SHADOW_OVERFLOW_STACK_SIZE/sizeof(long)] __aligned(16); | |
| 223 | 223 | |
| 224 | 224 | /* |
| 225 | 225 | * A pseudo spinlock to protect the shadow stack from being used by multiple |
| @@ -230,6 +230,12 @@ asmlinkage unsigned long get_overflow_stack(void) · 4 unmodified lines | ||
| 230 | 230 | */ |
| 231 | 231 | unsigned long spin_shadow_stack; |
| 232 | 232 | |
| 233 | +asmlinkage unsigned long get_overflow_stack(void) | |
| 234 | +{ | |
| 235 | + return (unsigned long)this_cpu_ptr(overflow_stack) + | |
| 236 | + OVERFLOW_STACK_SIZE; | |
| 237 | +} | |
| 238 | + | |
| 233 | 239 | asmlinkage void handle_bad_stack(struct pt_regs *regs) |
| 234 | 240 | { |
| 235 | 241 | unsigned long tsk_stk = (unsigned long)current->stack; |
| @@ -13,6 +13,8 @@ obj-y += extable.o · 12 unmodified lines | ||
| 13 | 13 | obj-$(CONFIG_MMU) += fault.o pageattr.o |
| 14 | 14 | obj-y += cacheflush.o |
| 15 | 15 | obj-y += context.o |
| 16 | +obj-y += pgtable.o | |
| 17 | +obj-y += pmem.o | |
| 16 | 18 | |
| 17 | 19 | ifeq ($(CONFIG_MMU),y) |
| 18 | 20 | obj-$(CONFIG_SMP) += tlbflush.o |
| @@ -83,6 +83,13 @@ void flush_icache_pte(pte_t pte) · 82 unmodified lines | ||
| 83 | 83 | { |
| 84 | 84 | struct page *page = pte_page(pte); |
| 85 | 85 | |
| 86 | + /* | |
| 87 | + * HugeTLB pages are always fully mapped, so only setting head page's | |
| 88 | + * PG_dcache_clean flag is enough. | |
| 89 | + */ | |
| 90 | + if (PageHuge(page)) | |
| 91 | + page = compound_head(page); | |
| 92 | + | |
| 86 | 93 | if (!test_and_set_bit(PG_dcache_clean, &page->flags)) |
| 87 | 94 | flush_icache_all(); |
| 88 | 95 | } |
| @@ -196,6 +196,16 @@ switch_mm_fast: · 195 unmodified lines | ||
| 196 | 196 | |
| 197 | 197 | if (need_flush_tlb) |
| 198 | 198 | local_flush_tlb_all(); |
| 199 | +#ifdef CONFIG_SMP | |
| 200 | + else { | |
| 201 | + cpumask_t *mask = &mm->context.tlb_stale_mask; | |
| 202 | + | |
| 203 | + if (cpumask_test_cpu(cpu, mask)) { | |
| 204 | + cpumask_clear_cpu(cpu, mask); | |
| 205 | + local_flush_tlb_all_asid(cntx & asid_mask); | |
| 206 | + } | |
| 207 | + } | |
| 208 | +#endif | |
| 199 | 209 | } |
| 200 | 210 | |
| 201 | 211 | static void set_mm_noasid(struct mm_struct *mm) |
| @@ -672,10 +672,11 @@ void __init create_pgd_mapping(pgd_t *pgdp, · 671 unmodified lines | ||
| 672 | 672 | static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size) |
| 673 | 673 | { |
| 674 | 674 | /* Upgrade to PMD_SIZE mappings whenever possible */ |
| 675 | − if ((base & (PMD_SIZE - 1)) || (size & (PMD_SIZE - 1))) | |
| 676 | − return PAGE_SIZE; | |
| 675 | + base &= PMD_SIZE - 1; | |
| 676 | + if (!base && size >= PMD_SIZE) | |
| 677 | + return PMD_SIZE; | |
| 677 | 678 | |
| 678 | − return PMD_SIZE; | |
| 679 | + return PAGE_SIZE; | |
| 679 | 680 | } |
| 680 | 681 | |
| 681 | 682 | #ifdef CONFIG_XIP_KERNEL |
| @@ -926,15 +927,15 @@ static void __init pt_ops_set_early(void) · 244 unmodified lines | ||
| 926 | 927 | */ |
| 927 | 928 | static void __init pt_ops_set_fixmap(void) |
| 928 | 929 | { |
| 929 | − pt_ops.alloc_pte = kernel_mapping_pa_to_va((uintptr_t)alloc_pte_fixmap); | |
| 930 | − pt_ops.get_pte_virt = kernel_mapping_pa_to_va((uintptr_t)get_pte_virt_fixmap); | |
| 930 | + pt_ops.alloc_pte = kernel_mapping_pa_to_va(alloc_pte_fixmap); | |
| 931 | + pt_ops.get_pte_virt = kernel_mapping_pa_to_va(get_pte_virt_fixmap); | |
| 931 | 932 | #ifndef __PAGETABLE_PMD_FOLDED |
| 932 | − pt_ops.alloc_pmd = kernel_mapping_pa_to_va((uintptr_t)alloc_pmd_fixmap); | |
| 933 | − pt_ops.get_pmd_virt = kernel_mapping_pa_to_va((uintptr_t)get_pmd_virt_fixmap); | |
| 934 | − pt_ops.alloc_pud = kernel_mapping_pa_to_va((uintptr_t)alloc_pud_fixmap); | |
| 935 | − pt_ops.get_pud_virt = kernel_mapping_pa_to_va((uintptr_t)get_pud_virt_fixmap); | |
| 936 | − pt_ops.alloc_p4d = kernel_mapping_pa_to_va((uintptr_t)alloc_p4d_fixmap); | |
| 937 | − pt_ops.get_p4d_virt = kernel_mapping_pa_to_va((uintptr_t)get_p4d_virt_fixmap); | |
| 933 | + pt_ops.alloc_pmd = kernel_mapping_pa_to_va(alloc_pmd_fixmap); | |
| 934 | + pt_ops.get_pmd_virt = kernel_mapping_pa_to_va(get_pmd_virt_fixmap); | |
| 935 | + pt_ops.alloc_pud = kernel_mapping_pa_to_va(alloc_pud_fixmap); | |
| 936 | + pt_ops.get_pud_virt = kernel_mapping_pa_to_va(get_pud_virt_fixmap); | |
| 937 | + pt_ops.alloc_p4d = kernel_mapping_pa_to_va(alloc_p4d_fixmap); | |
| 938 | + pt_ops.get_p4d_virt = kernel_mapping_pa_to_va(get_p4d_virt_fixmap); | |
| 938 | 939 | #endif |
| 939 | 940 | } |
| 940 | 941 | |
| @@ -1110,9 +1111,9 @@ static void __init setup_vm_final(void) · 169 unmodified lines | ||
| 1110 | 1111 | if (end >= __pa(PAGE_OFFSET) + memory_limit) |
| 1111 | 1112 | end = __pa(PAGE_OFFSET) + memory_limit; |
| 1112 | 1113 | |
| 1113 | − map_size = best_map_size(start, end - start); | |
| 1114 | 1114 | for (pa = start; pa < end; pa += map_size) { |
| 1115 | 1115 | va = (uintptr_t)__va(pa); |
| 1116 | + map_size = best_map_size(pa, end - pa); | |
| 1116 | 1117 | |
| 1117 | 1118 | create_pgd_mapping(swapper_pg_dir, va, pa, map_size, |
| 1118 | 1119 | pgprot_from_va(va)); |
| @@ -0,0 +1,83 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 2 | + | |
| 3 | +#include <asm/pgalloc.h> | |
| 4 | +#include <linux/gfp.h> | |
| 5 | +#include <linux/kernel.h> | |
| 6 | +#include <linux/pgtable.h> | |
| 7 | + | |
| 8 | +#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP | |
| 9 | +int p4d_set_huge(p4d_t *p4d, phys_addr_t addr, pgprot_t prot) | |
| 10 | +{ | |
| 11 | + return 0; | |
| 12 | +} | |
| 13 | + | |
| 14 | +void p4d_clear_huge(p4d_t *p4d) | |
| 15 | +{ | |
| 16 | +} | |
| 17 | + | |
| 18 | +int pud_set_huge(pud_t *pud, phys_addr_t phys, pgprot_t prot) | |
| 19 | +{ | |
| 20 | + pud_t new_pud = pfn_pud(__phys_to_pfn(phys), prot); | |
| 21 | + | |
| 22 | + set_pud(pud, new_pud); | |
| 23 | + return 1; | |
| 24 | +} | |
| 25 | + | |
| 26 | +int pud_clear_huge(pud_t *pud) | |
| 27 | +{ | |
| 28 | + if (!pud_leaf(READ_ONCE(*pud))) | |
| 29 | + return 0; | |
| 30 | + pud_clear(pud); | |
| 31 | + return 1; | |
| 32 | +} | |
| 33 | + | |
| 34 | +int pud_free_pmd_page(pud_t *pud, unsigned long addr) | |
| 35 | +{ | |
| 36 | + pmd_t *pmd = pud_pgtable(*pud); | |
| 37 | + int i; | |
| 38 | + | |
| 39 | + pud_clear(pud); | |
| 40 | + | |
| 41 | + flush_tlb_kernel_range(addr, addr + PUD_SIZE); | |
| 42 | + | |
| 43 | + for (i = 0; i < PTRS_PER_PMD; i++) { | |
| 44 | + if (!pmd_none(pmd[i])) { | |
| 45 | + pte_t *pte = (pte_t *)pmd_page_vaddr(pmd[i]); | |
| 46 | + | |
| 47 | + pte_free_kernel(NULL, pte); | |
| 48 | + } | |
| 49 | + } | |
| 50 | + | |
| 51 | + pmd_free(NULL, pmd); | |
| 52 | + | |
| 53 | + return 1; | |
| 54 | +} | |
| 55 | + | |
| 56 | +int pmd_set_huge(pmd_t *pmd, phys_addr_t phys, pgprot_t prot) | |
| 57 | +{ | |
| 58 | + pmd_t new_pmd = pfn_pmd(__phys_to_pfn(phys), prot); | |
| 59 | + | |
| 60 | + set_pmd(pmd, new_pmd); | |
| 61 | + return 1; | |
| 62 | +} | |
| 63 | + | |
| 64 | +int pmd_clear_huge(pmd_t *pmd) | |
| 65 | +{ | |
| 66 | + if (!pmd_leaf(READ_ONCE(*pmd))) | |
| 67 | + return 0; | |
| 68 | + pmd_clear(pmd); | |
| 69 | + return 1; | |
| 70 | +} | |
| 71 | + | |
| 72 | +int pmd_free_pte_page(pmd_t *pmd, unsigned long addr) | |
| 73 | +{ | |
| 74 | + pte_t *pte = (pte_t *)pmd_page_vaddr(*pmd); | |
| 75 | + | |
| 76 | + pmd_clear(pmd); | |
| 77 | + | |
| 78 | + flush_tlb_kernel_range(addr, addr + PMD_SIZE); | |
| 79 | + pte_free_kernel(NULL, pte); | |
| 80 | + return 1; | |
| 81 | +} | |
| 82 | + | |
| 83 | +#endif /* CONFIG_HAVE_ARCH_HUGE_VMAP */ | |
| @@ -22,7 +22,7 @@ EXPORT_SYMBOL(__virt_to_phys); · 21 unmodified lines | ||
| 22 | 22 | phys_addr_t __phys_addr_symbol(unsigned long x) |
| 23 | 23 | { |
| 24 | 24 | unsigned long kernel_start = kernel_map.virt_addr; |
| 25 | − unsigned long kernel_end = (unsigned long)_end; | |
| 25 | + unsigned long kernel_end = kernel_start + kernel_map.size; | |
| 26 | 26 | |
| 27 | 27 | /* |
| 28 | 28 | * Boundary checking aginst the kernel image mapping. |
| @@ -0,0 +1,21 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 2 | +/* | |
| 3 | + * Copyright (C) 2022 Ventana Micro Systems Inc. | |
| 4 | + */ | |
| 5 | + | |
| 6 | +#include <linux/export.h> | |
| 7 | +#include <linux/libnvdimm.h> | |
| 8 | + | |
| 9 | +#include <asm/cacheflush.h> | |
| 10 | + | |
| 11 | +void arch_wb_cache_pmem(void *addr, size_t size) | |
| 12 | +{ | |
| 13 | + ALT_CMO_OP(clean, addr, size, riscv_cbom_block_size); | |
| 14 | +} | |
| 15 | +EXPORT_SYMBOL_GPL(arch_wb_cache_pmem); | |
| 16 | + | |
| 17 | +void arch_invalidate_pmem(void *addr, size_t size) | |
| 18 | +{ | |
| 19 | + ALT_CMO_OP(inval, addr, size, riscv_cbom_block_size); | |
| 20 | +} | |
| 21 | +EXPORT_SYMBOL_GPL(arch_invalidate_pmem); | |
| @@ -5,23 +5,7 @@ · 4 unmodified lines | ||
| 5 | 5 | #include <linux/sched.h> |
| 6 | 6 | #include <asm/sbi.h> |
| 7 | 7 | #include <asm/mmu_context.h> |
| 8 | − | |
| 9 | −static inline void local_flush_tlb_all_asid(unsigned long asid) | |
| 10 | −{ | |
| 11 | − __asm__ __volatile__ ("sfence.vma x0, %0" | |
| 12 | − : | |
| 13 | − : "r" (asid) | |
| 14 | − : "memory"); | |
| 15 | −} | |
| 16 | − | |
| 17 | −static inline void local_flush_tlb_page_asid(unsigned long addr, | |
| 18 | − unsigned long asid) | |
| 19 | −{ | |
| 20 | − __asm__ __volatile__ ("sfence.vma %0, %1" | |
| 21 | − : | |
| 22 | − : "r" (addr), "r" (asid) | |
| 23 | − : "memory"); | |
| 24 | −} | |
| 8 | +#include <asm/tlbflush.h> | |
| 25 | 9 | |
| 26 | 10 | void flush_tlb_all(void) |
| 27 | 11 | { |
| @@ -31,6 +15,7 @@ void flush_tlb_all(void) · 3 unmodified lines | ||
| 31 | 15 | static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start, |
| 32 | 16 | unsigned long size, unsigned long stride) |
| 33 | 17 | { |
| 18 | + struct cpumask *pmask = &mm->context.tlb_stale_mask; | |
| 34 | 19 | struct cpumask *cmask = mm_cpumask(mm); |
| 35 | 20 | unsigned int cpuid; |
| 36 | 21 | bool broadcast; |
| @@ -44,6 +29,15 @@ static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start, · 7 unmodified lines | ||
| 44 | 29 | if (static_branch_unlikely(&use_asid_allocator)) { |
| 45 | 30 | unsigned long asid = atomic_long_read(&mm->context.id); |
| 46 | 31 | |
| 32 | + /* | |
| 33 | + * TLB will be immediately flushed on harts concurrently | |
| 34 | + * executing this MM context. TLB flush on other harts | |
| 35 | + * is deferred until this MM context migrates there. | |
| 36 | + */ | |
| 37 | + cpumask_setall(pmask); | |
| 38 | + cpumask_clear_cpu(cpuid, pmask); | |
| 39 | + cpumask_andnot(pmask, pmask, cmask); | |
| 40 | + | |
| 47 | 41 | if (broadcast) { |
| 48 | 42 | sbi_remote_sfence_vma_asid(cmask, start, size, asid); |
| 49 | 43 | } else if (size <= stride) { |
| @@ -538,31 +538,14 @@ config TI_PRUSS_INTC · 537 unmodified lines | ||
| 538 | 538 | different processors within the SoC. |
| 539 | 539 | |
| 540 | 540 | config RISCV_INTC |
| 541 | − bool "RISC-V Local Interrupt Controller" | |
| 541 | + bool | |
| 542 | 542 | depends on RISCV |
| 543 | − default y | |
| 544 | − help | |
| 545 | − This enables support for the per-HART local interrupt controller | |
| 546 | − found in standard RISC-V systems. The per-HART local interrupt | |
| 547 | − controller handles timer interrupts, software interrupts, and | |
| 548 | − hardware interrupts. Without a per-HART local interrupt controller, | |
| 549 | − a RISC-V system will be unable to handle any interrupts. | |
| 550 | − | |
| 551 | − If you don't know what to do here, say Y. | |
| 552 | 543 | |
| 553 | 544 | config SIFIVE_PLIC |
| 554 | − bool "SiFive Platform-Level Interrupt Controller" | |
| 545 | + bool | |
| 555 | 546 | depends on RISCV |
| 556 | 547 | select IRQ_DOMAIN_HIERARCHY |
| 557 | 548 | select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP |
| 558 | − help | |
| 559 | − This enables support for the PLIC chip found in SiFive (and | |
| 560 | − potentially other) RISC-V systems. The PLIC controls devices | |
| 561 | − interrupts and connects them to each core's local interrupt | |
| 562 | − controller. Aside from timer and software interrupts, all other | |
| 563 | − interrupt sources are subordinate to the PLIC. | |
| 564 | − | |
| 565 | − If you don't know what to do here, say Y. | |
| 566 | 549 | |
| 567 | 550 | config EXYNOS_IRQ_COMBINER |
| 568 | 551 | bool "Samsung Exynos IRQ combiner support" if COMPILE_TEST |
| @@ -20,6 +20,7 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <linux/cpu_pm.h> |
| 21 | 21 | #include <linux/sched/clock.h> |
| 22 | 22 | |
| 23 | +#include <asm/errata_list.h> | |
| 23 | 24 | #include <asm/sbi.h> |
| 24 | 25 | #include <asm/hwcap.h> |
| 25 | 26 | |
| @@ -47,6 +48,8 @@ static const struct attribute_group *riscv_pmu_attr_groups[] = { · 21 unmodified lines | ||
| 47 | 48 | * per_cpu in case of harts with different pmu counters |
| 48 | 49 | */ |
| 49 | 50 | static union sbi_pmu_ctr_info *pmu_ctr_list; |
| 51 | +static bool riscv_pmu_use_irq; | |
| 52 | +static unsigned int riscv_pmu_irq_num; | |
| 50 | 53 | static unsigned int riscv_pmu_irq; |
| 51 | 54 | |
| 52 | 55 | struct sbi_pmu_event_data { |
| @@ -580,7 +583,7 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev) · 527 unmodified lines | ||
| 580 | 583 | fidx = find_first_bit(cpu_hw_evt->used_hw_ctrs, RISCV_MAX_COUNTERS); |
| 581 | 584 | event = cpu_hw_evt->events[fidx]; |
| 582 | 585 | if (!event) { |
| 583 | − csr_clear(CSR_SIP, SIP_LCOFIP); | |
| 586 | + csr_clear(CSR_SIP, BIT(riscv_pmu_irq_num)); | |
| 584 | 587 | return IRQ_NONE; |
| 585 | 588 | } |
| 586 | 589 | |
| @@ -588,13 +591,13 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev) · 1 unmodified line | ||
| 588 | 591 | pmu_sbi_stop_hw_ctrs(pmu); |
| 589 | 592 | |
| 590 | 593 | /* Overflow status register should only be read after counter are stopped */ |
| 591 | − overflow = csr_read(CSR_SSCOUNTOVF); | |
| 594 | + ALT_SBI_PMU_OVERFLOW(overflow); | |
| 592 | 595 | |
| 593 | 596 | /* |
| 594 | 597 | * Overflow interrupt pending bit should only be cleared after stopping |
| 595 | 598 | * all the counters to avoid any race condition. |
| 596 | 599 | */ |
| 597 | − csr_clear(CSR_SIP, SIP_LCOFIP); | |
| 600 | + csr_clear(CSR_SIP, BIT(riscv_pmu_irq_num)); | |
| 598 | 601 | |
| 599 | 602 | /* No overflow bit is set */ |
| 600 | 603 | if (!overflow) |
| @@ -661,10 +664,10 @@ static int pmu_sbi_starting_cpu(unsigned int cpu, struct hlist_node *node) · 60 unmodified lines | ||
| 661 | 664 | /* Stop all the counters so that they can be enabled from perf */ |
| 662 | 665 | pmu_sbi_stop_all(pmu); |
| 663 | 666 | |
| 664 | − if (riscv_isa_extension_available(NULL, SSCOFPMF)) { | |
| 667 | + if (riscv_pmu_use_irq) { | |
| 665 | 668 | cpu_hw_evt->irq = riscv_pmu_irq; |
| 666 | − csr_clear(CSR_IP, BIT(RV_IRQ_PMU)); | |
| 667 | − csr_set(CSR_IE, BIT(RV_IRQ_PMU)); | |
| 669 | + csr_clear(CSR_IP, BIT(riscv_pmu_irq_num)); | |
| 670 | + csr_set(CSR_IE, BIT(riscv_pmu_irq_num)); | |
| 668 | 671 | enable_percpu_irq(riscv_pmu_irq, IRQ_TYPE_NONE); |
| 669 | 672 | } |
| 670 | 673 | |
| @@ -673,9 +676,9 @@ static int pmu_sbi_starting_cpu(unsigned int cpu, struct hlist_node *node) · 2 unmodified lines | ||
| 673 | 676 | |
| 674 | 677 | static int pmu_sbi_dying_cpu(unsigned int cpu, struct hlist_node *node) |
| 675 | 678 | { |
| 676 | − if (riscv_isa_extension_available(NULL, SSCOFPMF)) { | |
| 679 | + if (riscv_pmu_use_irq) { | |
| 677 | 680 | disable_percpu_irq(riscv_pmu_irq); |
| 678 | − csr_clear(CSR_IE, BIT(RV_IRQ_PMU)); | |
| 681 | + csr_clear(CSR_IE, BIT(riscv_pmu_irq_num)); | |
| 679 | 682 | } |
| 680 | 683 | |
| 681 | 684 | /* Disable all counters access for user mode now */ |
| @@ -691,7 +694,18 @@ static int pmu_sbi_setup_irqs(struct riscv_pmu *pmu, struct platform_device *pde · 9 unmodified lines | ||
| 691 | 694 | struct device_node *cpu, *child; |
| 692 | 695 | struct irq_domain *domain = NULL; |
| 693 | 696 | |
| 694 | − if (!riscv_isa_extension_available(NULL, SSCOFPMF)) | |
| 697 | + if (riscv_isa_extension_available(NULL, SSCOFPMF)) { | |
| 698 | + riscv_pmu_irq_num = RV_IRQ_PMU; | |
| 699 | + riscv_pmu_use_irq = true; | |
| 700 | + } else if (IS_ENABLED(CONFIG_ERRATA_THEAD_PMU) && | |
| 701 | + riscv_cached_mvendorid(0) == THEAD_VENDOR_ID && | |
| 702 | + riscv_cached_marchid(0) == 0 && | |
| 703 | + riscv_cached_mimpid(0) == 0) { | |
| 704 | + riscv_pmu_irq_num = THEAD_C9XX_RV_IRQ_PMU; | |
| 705 | + riscv_pmu_use_irq = true; | |
| 706 | + } | |
| 707 | + | |
| 708 | + if (!riscv_pmu_use_irq) | |
| 695 | 709 | return -EOPNOTSUPP; |
| 696 | 710 | |
| 697 | 711 | for_each_of_cpu_node(cpu) { |
| @@ -713,7 +727,7 @@ static int pmu_sbi_setup_irqs(struct riscv_pmu *pmu, struct platform_device *pde · 15 unmodified lines | ||
| 713 | 727 | return -ENODEV; |
| 714 | 728 | } |
| 715 | 729 | |
| 716 | − riscv_pmu_irq = irq_create_mapping(domain, RV_IRQ_PMU); | |
| 730 | + riscv_pmu_irq = irq_create_mapping(domain, riscv_pmu_irq_num); | |
| 717 | 731 | if (!riscv_pmu_irq) { |
| 718 | 732 | pr_err("Failed to map PMU interrupt for node\n"); |
| 719 | 733 | return -ENODEV; |
| @@ -38,7 +38,6 @@ arch/powerpc/kernel/entry_64.o · 37 unmodified lines | ||
| 38 | 38 | arch/powerpc/kernel/fpu.o |
| 39 | 39 | arch/powerpc/kernel/vector.o |
| 40 | 40 | arch/powerpc/kernel/prom_init.o |
| 41 | −arch/riscv/kernel/head.o | |
| 42 | 41 | arch/s390/kernel/head64.o |
| 43 | 42 | arch/sh/kernel/head_32.o |
| 44 | 43 | arch/sparc/kernel/head_32.o |