Commit 2e64066d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'riscv-for-linus-6.1-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux

Pull RISC-V updates from Palmer Dabbelt:

 - Improvements to the CPU topology subsystem, which fix some issues
   where RISC-V would report bad topology information.

 - The default NR_CPUS has increased to XLEN, and the maximum
   configurable value is 512.

 - The CD-ROM filesystems have been enabled in the defconfig.

 - Support for THP_SWAP has been added for rv64 systems.

There are also a handful of cleanups and fixes throughout the tree.

* tag 'riscv-for-linus-6.1-mw1' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux:
  riscv: enable THP_SWAP for RV64
  RISC-V: Print SSTC in canonical order
  riscv: compat: s/failed/unsupported if compat mode isn't supported
  RISC-V: Increase range and default value of NR_CPUS
  cpuidle: riscv-sbi: Fix CPU_PM_CPU_IDLE_ENTER_xyz() macro usage
  perf: RISC-V: throttle perf events
  perf: RISC-V: exclude invalid pmu counters from SBI calls
  riscv: enable CD-ROM file systems in defconfig
  riscv: topology: fix default topology reporting
  arm64: topology: move store_cpu_topology() to shared code
parents 57c92724 87f81e66
...@@ -22,46 +22,6 @@ ...@@ -22,46 +22,6 @@
#include <asm/cputype.h> #include <asm/cputype.h>
#include <asm/topology.h> #include <asm/topology.h>
void store_cpu_topology(unsigned int cpuid)
{
struct cpu_topology *cpuid_topo = &cpu_topology[cpuid];
u64 mpidr;
if (cpuid_topo->package_id != -1)
goto topology_populated;
mpidr = read_cpuid_mpidr();
/* Uniprocessor systems can rely on default topology values */
if (mpidr & MPIDR_UP_BITMASK)
return;
/*
* This would be the place to create cpu topology based on MPIDR.
*
* However, it cannot be trusted to depict the actual topology; some
* pieces of the architecture enforce an artificial cap on Aff0 values
* (e.g. GICv3's ICC_SGI1R_EL1 limits it to 15), leading to an
* artificial cycling of Aff1, Aff2 and Aff3 values. IOW, these end up
* having absolutely no relationship to the actual underlying system
* topology, and cannot be reasonably used as core / package ID.
*
* If the MT bit is set, Aff0 *could* be used to define a thread ID, but
* we still wouldn't be able to obtain a sane core ID. This means we
* need to entirely ignore MPIDR for any topology deduction.
*/
cpuid_topo->thread_id = -1;
cpuid_topo->core_id = cpuid;
cpuid_topo->package_id = cpu_to_node(cpuid);
pr_debug("CPU%u: cluster %d core %d thread %d mpidr %#016llx\n",
cpuid, cpuid_topo->package_id, cpuid_topo->core_id,
cpuid_topo->thread_id, mpidr);
topology_populated:
update_siblings_masks(cpuid);
}
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
static bool __init acpi_cpu_is_threaded(int cpu) static bool __init acpi_cpu_is_threaded(int cpu)
{ {
......
...@@ -45,6 +45,7 @@ config RISCV ...@@ -45,6 +45,7 @@ config RISCV
select ARCH_WANT_FRAME_POINTERS select ARCH_WANT_FRAME_POINTERS
select ARCH_WANT_GENERAL_HUGETLB select ARCH_WANT_GENERAL_HUGETLB
select ARCH_WANT_HUGE_PMD_SHARE if 64BIT select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
select ARCH_WANTS_THP_SWAP if HAVE_ARCH_TRANSPARENT_HUGEPAGE
select BINFMT_FLAT_NO_DATA_START_OFFSET if !MMU select BINFMT_FLAT_NO_DATA_START_OFFSET if !MMU
select BUILDTIME_TABLE_SORT if MMU select BUILDTIME_TABLE_SORT if MMU
select CLONE_BACKWARDS select CLONE_BACKWARDS
...@@ -52,7 +53,7 @@ config RISCV ...@@ -52,7 +53,7 @@ config RISCV
select COMMON_CLK select COMMON_CLK
select CPU_PM if CPU_IDLE select CPU_PM if CPU_IDLE
select EDAC_SUPPORT select EDAC_SUPPORT
select GENERIC_ARCH_TOPOLOGY if SMP select GENERIC_ARCH_TOPOLOGY
select GENERIC_ATOMIC64 if !64BIT select GENERIC_ATOMIC64 if !64BIT
select GENERIC_CLOCKEVENTS_BROADCAST if SMP select GENERIC_CLOCKEVENTS_BROADCAST if SMP
select GENERIC_EARLY_IOREMAP select GENERIC_EARLY_IOREMAP
...@@ -309,10 +310,13 @@ config SMP ...@@ -309,10 +310,13 @@ config SMP
If you don't know what to do here, say N. If you don't know what to do here, say N.
config NR_CPUS config NR_CPUS
int "Maximum number of CPUs (2-32)" int "Maximum number of CPUs (2-512)"
range 2 32
depends on SMP depends on SMP
default "8" range 2 512 if !SBI_V01
range 2 32 if SBI_V01 && 32BIT
range 2 64 if SBI_V01 && 64BIT
default "32" if 32BIT
default "64" if 64BIT
config HOTPLUG_CPU config HOTPLUG_CPU
bool "Support for hot-pluggable CPUs" bool "Support for hot-pluggable CPUs"
......
...@@ -166,6 +166,9 @@ CONFIG_BTRFS_FS=m ...@@ -166,6 +166,9 @@ CONFIG_BTRFS_FS=m
CONFIG_BTRFS_FS_POSIX_ACL=y CONFIG_BTRFS_FS_POSIX_ACL=y
CONFIG_AUTOFS4_FS=y CONFIG_AUTOFS4_FS=y
CONFIG_OVERLAY_FS=m CONFIG_OVERLAY_FS=m
CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
CONFIG_MSDOS_FS=y CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y CONFIG_VFAT_FS=y
CONFIG_TMPFS=y CONFIG_TMPFS=y
......
...@@ -92,10 +92,10 @@ int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid) ...@@ -92,10 +92,10 @@ int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid)
*/ */
static struct riscv_isa_ext_data isa_ext_arr[] = { static struct riscv_isa_ext_data isa_ext_arr[] = {
__RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF), __RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF),
__RISCV_ISA_EXT_DATA(sstc, RISCV_ISA_EXT_SSTC),
__RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT), __RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT),
__RISCV_ISA_EXT_DATA(zicbom, RISCV_ISA_EXT_ZICBOM), __RISCV_ISA_EXT_DATA(zicbom, RISCV_ISA_EXT_ZICBOM),
__RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE), __RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE),
__RISCV_ISA_EXT_DATA(sstc, RISCV_ISA_EXT_SSTC),
__RISCV_ISA_EXT_DATA("", RISCV_ISA_EXT_MAX), __RISCV_ISA_EXT_DATA("", RISCV_ISA_EXT_MAX),
}; };
......
...@@ -105,7 +105,7 @@ static int __init compat_mode_detect(void) ...@@ -105,7 +105,7 @@ static int __init compat_mode_detect(void)
csr_write(CSR_STATUS, tmp); csr_write(CSR_STATUS, tmp);
pr_info("riscv: ELF compat mode %s", pr_info("riscv: ELF compat mode %s",
compat_mode_supported ? "supported" : "failed"); compat_mode_supported ? "supported" : "unsupported");
return 0; return 0;
} }
......
...@@ -49,6 +49,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) ...@@ -49,6 +49,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
unsigned int curr_cpuid; unsigned int curr_cpuid;
curr_cpuid = smp_processor_id(); curr_cpuid = smp_processor_id();
store_cpu_topology(curr_cpuid);
numa_store_cpu_info(curr_cpuid); numa_store_cpu_info(curr_cpuid);
numa_add_cpu(curr_cpuid); numa_add_cpu(curr_cpuid);
...@@ -162,9 +163,9 @@ asmlinkage __visible void smp_callin(void) ...@@ -162,9 +163,9 @@ asmlinkage __visible void smp_callin(void)
mmgrab(mm); mmgrab(mm);
current->active_mm = mm; current->active_mm = mm;
store_cpu_topology(curr_cpuid);
notify_cpu_starting(curr_cpuid); notify_cpu_starting(curr_cpuid);
numa_add_cpu(curr_cpuid); numa_add_cpu(curr_cpuid);
update_siblings_masks(curr_cpuid);
set_cpu_online(curr_cpuid, 1); set_cpu_online(curr_cpuid, 1);
/* /*
......
...@@ -841,4 +841,23 @@ void __init init_cpu_topology(void) ...@@ -841,4 +841,23 @@ void __init init_cpu_topology(void)
return; return;
} }
} }
void store_cpu_topology(unsigned int cpuid)
{
struct cpu_topology *cpuid_topo = &cpu_topology[cpuid];
if (cpuid_topo->package_id != -1)
goto topology_populated;
cpuid_topo->thread_id = -1;
cpuid_topo->core_id = cpuid;
cpuid_topo->package_id = cpu_to_node(cpuid);
pr_debug("CPU%u: package %d core %d thread %d\n",
cpuid, cpuid_topo->package_id, cpuid_topo->core_id,
cpuid_topo->thread_id);
topology_populated:
update_siblings_masks(cpuid);
}
#endif #endif
...@@ -97,8 +97,13 @@ static int sbi_cpuidle_enter_state(struct cpuidle_device *dev, ...@@ -97,8 +97,13 @@ static int sbi_cpuidle_enter_state(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int idx) struct cpuidle_driver *drv, int idx)
{ {
u32 *states = __this_cpu_read(sbi_cpuidle_data.states); u32 *states = __this_cpu_read(sbi_cpuidle_data.states);
u32 state = states[idx];
return CPU_PM_CPU_IDLE_ENTER_PARAM(sbi_suspend, idx, states[idx]); if (state & SBI_HSM_SUSP_NON_RET_BIT)
return CPU_PM_CPU_IDLE_ENTER_PARAM(sbi_suspend, idx, state);
else
return CPU_PM_CPU_IDLE_ENTER_RETENTION_PARAM(sbi_suspend,
idx, state);
} }
static int __sbi_enter_domain_idle_state(struct cpuidle_device *dev, static int __sbi_enter_domain_idle_state(struct cpuidle_device *dev,
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#define RISCV_PMU_LEGACY_CYCLE 0 #define RISCV_PMU_LEGACY_CYCLE 0
#define RISCV_PMU_LEGACY_INSTRET 1 #define RISCV_PMU_LEGACY_INSTRET 1
#define RISCV_PMU_LEGACY_NUM_CTR 2
static bool pmu_init_done; static bool pmu_init_done;
...@@ -83,7 +82,8 @@ static void pmu_legacy_init(struct riscv_pmu *pmu) ...@@ -83,7 +82,8 @@ static void pmu_legacy_init(struct riscv_pmu *pmu)
{ {
pr_info("Legacy PMU implementation is available\n"); pr_info("Legacy PMU implementation is available\n");
pmu->num_counters = RISCV_PMU_LEGACY_NUM_CTR; pmu->cmask = BIT(RISCV_PMU_LEGACY_CYCLE) |
BIT(RISCV_PMU_LEGACY_INSTRET);
pmu->ctr_start = pmu_legacy_ctr_start; pmu->ctr_start = pmu_legacy_ctr_start;
pmu->ctr_stop = NULL; pmu->ctr_stop = NULL;
pmu->event_map = pmu_legacy_event_map; pmu->event_map = pmu_legacy_event_map;
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/cpu_pm.h> #include <linux/cpu_pm.h>
#include <linux/sched/clock.h>
#include <asm/sbi.h> #include <asm/sbi.h>
#include <asm/hwcap.h> #include <asm/hwcap.h>
...@@ -271,7 +272,6 @@ static int pmu_sbi_ctr_get_idx(struct perf_event *event) ...@@ -271,7 +272,6 @@ static int pmu_sbi_ctr_get_idx(struct perf_event *event)
struct sbiret ret; struct sbiret ret;
int idx; int idx;
uint64_t cbase = 0; uint64_t cbase = 0;
uint64_t cmask = GENMASK_ULL(rvpmu->num_counters - 1, 0);
unsigned long cflags = 0; unsigned long cflags = 0;
if (event->attr.exclude_kernel) if (event->attr.exclude_kernel)
...@@ -281,11 +281,12 @@ static int pmu_sbi_ctr_get_idx(struct perf_event *event) ...@@ -281,11 +281,12 @@ static int pmu_sbi_ctr_get_idx(struct perf_event *event)
/* retrieve the available counter index */ /* retrieve the available counter index */
#if defined(CONFIG_32BIT) #if defined(CONFIG_32BIT)
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_CFG_MATCH, cbase, cmask, ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_CFG_MATCH, cbase,
cflags, hwc->event_base, hwc->config, hwc->config >> 32); rvpmu->cmask, cflags, hwc->event_base, hwc->config,
hwc->config >> 32);
#else #else
ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_CFG_MATCH, cbase, cmask, ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_CFG_MATCH, cbase,
cflags, hwc->event_base, hwc->config, 0); rvpmu->cmask, cflags, hwc->event_base, hwc->config, 0);
#endif #endif
if (ret.error) { if (ret.error) {
pr_debug("Not able to find a counter for event %lx config %llx\n", pr_debug("Not able to find a counter for event %lx config %llx\n",
...@@ -294,7 +295,7 @@ static int pmu_sbi_ctr_get_idx(struct perf_event *event) ...@@ -294,7 +295,7 @@ static int pmu_sbi_ctr_get_idx(struct perf_event *event)
} }
idx = ret.value; idx = ret.value;
if (idx >= rvpmu->num_counters || !pmu_ctr_list[idx].value) if (!test_bit(idx, &rvpmu->cmask) || !pmu_ctr_list[idx].value)
return -ENOENT; return -ENOENT;
/* Additional sanity check for the counter id */ /* Additional sanity check for the counter id */
...@@ -463,7 +464,7 @@ static int pmu_sbi_find_num_ctrs(void) ...@@ -463,7 +464,7 @@ static int pmu_sbi_find_num_ctrs(void)
return sbi_err_map_linux_errno(ret.error); return sbi_err_map_linux_errno(ret.error);
} }
static int pmu_sbi_get_ctrinfo(int nctr) static int pmu_sbi_get_ctrinfo(int nctr, unsigned long *mask)
{ {
struct sbiret ret; struct sbiret ret;
int i, num_hw_ctr = 0, num_fw_ctr = 0; int i, num_hw_ctr = 0, num_fw_ctr = 0;
...@@ -478,6 +479,9 @@ static int pmu_sbi_get_ctrinfo(int nctr) ...@@ -478,6 +479,9 @@ static int pmu_sbi_get_ctrinfo(int nctr)
if (ret.error) if (ret.error)
/* The logical counter ids are not expected to be contiguous */ /* The logical counter ids are not expected to be contiguous */
continue; continue;
*mask |= BIT(i);
cinfo.value = ret.value; cinfo.value = ret.value;
if (cinfo.type == SBI_PMU_CTR_TYPE_FW) if (cinfo.type == SBI_PMU_CTR_TYPE_FW)
num_fw_ctr++; num_fw_ctr++;
...@@ -498,7 +502,7 @@ static inline void pmu_sbi_stop_all(struct riscv_pmu *pmu) ...@@ -498,7 +502,7 @@ static inline void pmu_sbi_stop_all(struct riscv_pmu *pmu)
* which may include counters that are not enabled yet. * which may include counters that are not enabled yet.
*/ */
sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP, sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP,
0, GENMASK_ULL(pmu->num_counters - 1, 0), 0, 0, 0, 0); 0, pmu->cmask, 0, 0, 0, 0);
} }
static inline void pmu_sbi_stop_hw_ctrs(struct riscv_pmu *pmu) static inline void pmu_sbi_stop_hw_ctrs(struct riscv_pmu *pmu)
...@@ -567,6 +571,7 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev) ...@@ -567,6 +571,7 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev)
unsigned long overflow; unsigned long overflow;
unsigned long overflowed_ctrs = 0; unsigned long overflowed_ctrs = 0;
struct cpu_hw_events *cpu_hw_evt = dev; struct cpu_hw_events *cpu_hw_evt = dev;
u64 start_clock = sched_clock();
if (WARN_ON_ONCE(!cpu_hw_evt)) if (WARN_ON_ONCE(!cpu_hw_evt))
return IRQ_NONE; return IRQ_NONE;
...@@ -635,7 +640,9 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev) ...@@ -635,7 +640,9 @@ static irqreturn_t pmu_sbi_ovf_handler(int irq, void *dev)
perf_event_overflow(event, &data, regs); perf_event_overflow(event, &data, regs);
} }
} }
pmu_sbi_start_overflow_mask(pmu, overflowed_ctrs); pmu_sbi_start_overflow_mask(pmu, overflowed_ctrs);
perf_sample_event_took(sched_clock() - start_clock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -788,8 +795,9 @@ static void riscv_pmu_destroy(struct riscv_pmu *pmu) ...@@ -788,8 +795,9 @@ static void riscv_pmu_destroy(struct riscv_pmu *pmu)
static int pmu_sbi_device_probe(struct platform_device *pdev) static int pmu_sbi_device_probe(struct platform_device *pdev)
{ {
struct riscv_pmu *pmu = NULL; struct riscv_pmu *pmu = NULL;
int num_counters; unsigned long cmask = 0;
int ret = -ENODEV; int ret = -ENODEV;
int num_counters;
pr_info("SBI PMU extension is available\n"); pr_info("SBI PMU extension is available\n");
pmu = riscv_pmu_alloc(); pmu = riscv_pmu_alloc();
...@@ -803,7 +811,7 @@ static int pmu_sbi_device_probe(struct platform_device *pdev) ...@@ -803,7 +811,7 @@ static int pmu_sbi_device_probe(struct platform_device *pdev)
} }
/* cache all the information about counters now */ /* cache all the information about counters now */
if (pmu_sbi_get_ctrinfo(num_counters)) if (pmu_sbi_get_ctrinfo(num_counters, &cmask))
goto out_free; goto out_free;
ret = pmu_sbi_setup_irqs(pmu, pdev); ret = pmu_sbi_setup_irqs(pmu, pdev);
...@@ -812,8 +820,9 @@ static int pmu_sbi_device_probe(struct platform_device *pdev) ...@@ -812,8 +820,9 @@ static int pmu_sbi_device_probe(struct platform_device *pdev)
pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT; pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
pmu->pmu.capabilities |= PERF_PMU_CAP_NO_EXCLUDE; pmu->pmu.capabilities |= PERF_PMU_CAP_NO_EXCLUDE;
} }
pmu->pmu.attr_groups = riscv_pmu_attr_groups; pmu->pmu.attr_groups = riscv_pmu_attr_groups;
pmu->num_counters = num_counters; pmu->cmask = cmask;
pmu->ctr_start = pmu_sbi_ctr_start; pmu->ctr_start = pmu_sbi_ctr_start;
pmu->ctr_stop = pmu_sbi_ctr_stop; pmu->ctr_stop = pmu_sbi_ctr_stop;
pmu->event_map = pmu_sbi_event_map; pmu->event_map = pmu_sbi_event_map;
......
...@@ -45,7 +45,7 @@ struct riscv_pmu { ...@@ -45,7 +45,7 @@ struct riscv_pmu {
irqreturn_t (*handle_irq)(int irq_num, void *dev); irqreturn_t (*handle_irq)(int irq_num, void *dev);
int num_counters; unsigned long cmask;
u64 (*ctr_read)(struct perf_event *event); u64 (*ctr_read)(struct perf_event *event);
int (*ctr_get_idx)(struct perf_event *event); int (*ctr_get_idx)(struct perf_event *event);
int (*ctr_get_width)(int idx); int (*ctr_get_width)(int idx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment