RISC-V: Do not use cpumask data structure for hartid bitmap

Currently, SBI APIs accept a hartmask that is generated from struct
cpumask. Cpumask data structure can hold upto NR_CPUs value. Thus, it
is not the correct data structure for hartids as it can be higher
than NR_CPUs for platforms with sparse or discontguous hartids.

Remove all association between hartid mask and struct cpumask.

Reviewed-by: Anup Patel <anup@brainfault.org> (For Linux RISC-V changes)
Acked-by: Anup Patel <anup@brainfault.org> (For KVM RISC-V changes)
Signed-off-by: Atish Patra <atishp@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
Atish Patra 2022-01-20 01:09:18 -08:00 committed by Palmer Dabbelt
parent 2ffc48fc70
commit 26fb751ca3
No known key found for this signature in database
GPG Key ID: 2E1319F35FBB1889
11 changed files with 130 additions and 136 deletions

View File

@ -8,6 +8,7 @@
#define _ASM_RISCV_SBI_H #define _ASM_RISCV_SBI_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/cpumask.h>
#ifdef CONFIG_RISCV_SBI #ifdef CONFIG_RISCV_SBI
enum sbi_ext_id { enum sbi_ext_id {
@ -128,27 +129,27 @@ long sbi_get_mimpid(void);
void sbi_set_timer(uint64_t stime_value); void sbi_set_timer(uint64_t stime_value);
void sbi_shutdown(void); void sbi_shutdown(void);
void sbi_clear_ipi(void); void sbi_clear_ipi(void);
int sbi_send_ipi(const unsigned long *hart_mask); int sbi_send_ipi(const struct cpumask *cpu_mask);
int sbi_remote_fence_i(const unsigned long *hart_mask); int sbi_remote_fence_i(const struct cpumask *cpu_mask);
int sbi_remote_sfence_vma(const unsigned long *hart_mask, int sbi_remote_sfence_vma(const struct cpumask *cpu_mask,
unsigned long start, unsigned long start,
unsigned long size); unsigned long size);
int sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, int sbi_remote_sfence_vma_asid(const struct cpumask *cpu_mask,
unsigned long start, unsigned long start,
unsigned long size, unsigned long size,
unsigned long asid); unsigned long asid);
int sbi_remote_hfence_gvma(const unsigned long *hart_mask, int sbi_remote_hfence_gvma(const struct cpumask *cpu_mask,
unsigned long start, unsigned long start,
unsigned long size); unsigned long size);
int sbi_remote_hfence_gvma_vmid(const unsigned long *hart_mask, int sbi_remote_hfence_gvma_vmid(const struct cpumask *cpu_mask,
unsigned long start, unsigned long start,
unsigned long size, unsigned long size,
unsigned long vmid); unsigned long vmid);
int sbi_remote_hfence_vvma(const unsigned long *hart_mask, int sbi_remote_hfence_vvma(const struct cpumask *cpu_mask,
unsigned long start, unsigned long start,
unsigned long size); unsigned long size);
int sbi_remote_hfence_vvma_asid(const unsigned long *hart_mask, int sbi_remote_hfence_vvma_asid(const struct cpumask *cpu_mask,
unsigned long start, unsigned long start,
unsigned long size, unsigned long size,
unsigned long asid); unsigned long asid);
@ -183,7 +184,7 @@ static inline unsigned long sbi_mk_version(unsigned long major,
int sbi_err_map_linux_errno(int err); int sbi_err_map_linux_errno(int err);
#else /* CONFIG_RISCV_SBI */ #else /* CONFIG_RISCV_SBI */
static inline int sbi_remote_fence_i(const unsigned long *hart_mask) { return -1; } static inline int sbi_remote_fence_i(const struct cpumask *cpu_mask) { return -1; }
static inline void sbi_init(void) {} static inline void sbi_init(void) {}
#endif /* CONFIG_RISCV_SBI */ #endif /* CONFIG_RISCV_SBI */
#endif /* _ASM_RISCV_SBI_H */ #endif /* _ASM_RISCV_SBI_H */

View File

@ -92,8 +92,6 @@ static inline void riscv_clear_ipi(void)
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out);
#if defined(CONFIG_HOTPLUG_CPU) && (CONFIG_SMP) #if defined(CONFIG_HOTPLUG_CPU) && (CONFIG_SMP)
bool cpu_has_hotplug(unsigned int cpu); bool cpu_has_hotplug(unsigned int cpu);
#else #else

View File

@ -16,8 +16,8 @@ unsigned long sbi_spec_version __ro_after_init = SBI_SPEC_VERSION_DEFAULT;
EXPORT_SYMBOL(sbi_spec_version); EXPORT_SYMBOL(sbi_spec_version);
static void (*__sbi_set_timer)(uint64_t stime) __ro_after_init; static void (*__sbi_set_timer)(uint64_t stime) __ro_after_init;
static int (*__sbi_send_ipi)(const unsigned long *hart_mask) __ro_after_init; static int (*__sbi_send_ipi)(const struct cpumask *cpu_mask) __ro_after_init;
static int (*__sbi_rfence)(int fid, const unsigned long *hart_mask, static int (*__sbi_rfence)(int fid, const struct cpumask *cpu_mask,
unsigned long start, unsigned long size, unsigned long start, unsigned long size,
unsigned long arg4, unsigned long arg5) __ro_after_init; unsigned long arg4, unsigned long arg5) __ro_after_init;
@ -67,6 +67,30 @@ int sbi_err_map_linux_errno(int err)
EXPORT_SYMBOL(sbi_err_map_linux_errno); EXPORT_SYMBOL(sbi_err_map_linux_errno);
#ifdef CONFIG_RISCV_SBI_V01 #ifdef CONFIG_RISCV_SBI_V01
static unsigned long __sbi_v01_cpumask_to_hartmask(const struct cpumask *cpu_mask)
{
unsigned long cpuid, hartid;
unsigned long hmask = 0;
/*
* There is no maximum hartid concept in RISC-V and NR_CPUS must not be
* associated with hartid. As SBI v0.1 is only kept for backward compatibility
* and will be removed in the future, there is no point in supporting hartid
* greater than BITS_PER_LONG (32 for RV32 and 64 for RV64). Ideally, SBI v0.2
* should be used for platforms with hartid greater than BITS_PER_LONG.
*/
for_each_cpu(cpuid, cpu_mask) {
hartid = cpuid_to_hartid_map(cpuid);
if (hartid >= BITS_PER_LONG) {
pr_warn("Unable to send any request to hartid > BITS_PER_LONG for SBI v0.1\n");
break;
}
hmask |= 1 << hartid;
}
return hmask;
}
/** /**
* sbi_console_putchar() - Writes given character to the console device. * sbi_console_putchar() - Writes given character to the console device.
* @ch: The data to be written to the console. * @ch: The data to be written to the console.
@ -132,33 +156,44 @@ static void __sbi_set_timer_v01(uint64_t stime_value)
#endif #endif
} }
static int __sbi_send_ipi_v01(const unsigned long *hart_mask) static int __sbi_send_ipi_v01(const struct cpumask *cpu_mask)
{ {
sbi_ecall(SBI_EXT_0_1_SEND_IPI, 0, (unsigned long)hart_mask, unsigned long hart_mask;
if (!cpu_mask)
cpu_mask = cpu_online_mask;
hart_mask = __sbi_v01_cpumask_to_hartmask(cpu_mask);
sbi_ecall(SBI_EXT_0_1_SEND_IPI, 0, (unsigned long)(&hart_mask),
0, 0, 0, 0, 0); 0, 0, 0, 0, 0);
return 0; return 0;
} }
static int __sbi_rfence_v01(int fid, const unsigned long *hart_mask, static int __sbi_rfence_v01(int fid, const struct cpumask *cpu_mask,
unsigned long start, unsigned long size, unsigned long start, unsigned long size,
unsigned long arg4, unsigned long arg5) unsigned long arg4, unsigned long arg5)
{ {
int result = 0; int result = 0;
unsigned long hart_mask;
if (!cpu_mask)
cpu_mask = cpu_online_mask;
hart_mask = __sbi_v01_cpumask_to_hartmask(cpu_mask);
/* v0.2 function IDs are equivalent to v0.1 extension IDs */ /* v0.2 function IDs are equivalent to v0.1 extension IDs */
switch (fid) { switch (fid) {
case SBI_EXT_RFENCE_REMOTE_FENCE_I: case SBI_EXT_RFENCE_REMOTE_FENCE_I:
sbi_ecall(SBI_EXT_0_1_REMOTE_FENCE_I, 0, sbi_ecall(SBI_EXT_0_1_REMOTE_FENCE_I, 0,
(unsigned long)hart_mask, 0, 0, 0, 0, 0); (unsigned long)&hart_mask, 0, 0, 0, 0, 0);
break; break;
case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA: case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA:
sbi_ecall(SBI_EXT_0_1_REMOTE_SFENCE_VMA, 0, sbi_ecall(SBI_EXT_0_1_REMOTE_SFENCE_VMA, 0,
(unsigned long)hart_mask, start, size, (unsigned long)&hart_mask, start, size,
0, 0, 0); 0, 0, 0);
break; break;
case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID: case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID:
sbi_ecall(SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID, 0, sbi_ecall(SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID, 0,
(unsigned long)hart_mask, start, size, (unsigned long)&hart_mask, start, size,
arg4, 0, 0); arg4, 0, 0);
break; break;
default: default:
@ -180,7 +215,7 @@ static void __sbi_set_timer_v01(uint64_t stime_value)
sbi_major_version(), sbi_minor_version()); sbi_major_version(), sbi_minor_version());
} }
static int __sbi_send_ipi_v01(const unsigned long *hart_mask) static int __sbi_send_ipi_v01(const struct cpumask *cpu_mask)
{ {
pr_warn("IPI extension is not available in SBI v%lu.%lu\n", pr_warn("IPI extension is not available in SBI v%lu.%lu\n",
sbi_major_version(), sbi_minor_version()); sbi_major_version(), sbi_minor_version());
@ -188,7 +223,7 @@ static int __sbi_send_ipi_v01(const unsigned long *hart_mask)
return 0; return 0;
} }
static int __sbi_rfence_v01(int fid, const unsigned long *hart_mask, static int __sbi_rfence_v01(int fid, const struct cpumask *cpu_mask,
unsigned long start, unsigned long size, unsigned long start, unsigned long size,
unsigned long arg4, unsigned long arg5) unsigned long arg4, unsigned long arg5)
{ {
@ -212,37 +247,33 @@ static void __sbi_set_timer_v02(uint64_t stime_value)
#endif #endif
} }
static int __sbi_send_ipi_v02(const unsigned long *hart_mask) static int __sbi_send_ipi_v02(const struct cpumask *cpu_mask)
{ {
unsigned long hartid, hmask_val, hbase; unsigned long hartid, cpuid, hmask = 0, hbase = 0;
struct cpumask tmask;
struct sbiret ret = {0}; struct sbiret ret = {0};
int result; int result;
if (!hart_mask || !(*hart_mask)) { if (!cpu_mask)
riscv_cpuid_to_hartid_mask(cpu_online_mask, &tmask); cpu_mask = cpu_online_mask;
hart_mask = cpumask_bits(&tmask);
}
hmask_val = 0; for_each_cpu(cpuid, cpu_mask) {
hbase = 0; hartid = cpuid_to_hartid_map(cpuid);
for_each_set_bit(hartid, hart_mask, NR_CPUS) { if (hmask && ((hbase + BITS_PER_LONG) <= hartid)) {
if (hmask_val && ((hbase + BITS_PER_LONG) <= hartid)) {
ret = sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI, ret = sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI,
hmask_val, hbase, 0, 0, 0, 0); hmask, hbase, 0, 0, 0, 0);
if (ret.error) if (ret.error)
goto ecall_failed; goto ecall_failed;
hmask_val = 0; hmask = 0;
hbase = 0; hbase = 0;
} }
if (!hmask_val) if (!hmask)
hbase = hartid; hbase = hartid;
hmask_val |= 1UL << (hartid - hbase); hmask |= 1UL << (hartid - hbase);
} }
if (hmask_val) { if (hmask) {
ret = sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI, ret = sbi_ecall(SBI_EXT_IPI, SBI_EXT_IPI_SEND_IPI,
hmask_val, hbase, 0, 0, 0, 0); hmask, hbase, 0, 0, 0, 0);
if (ret.error) if (ret.error)
goto ecall_failed; goto ecall_failed;
} }
@ -252,11 +283,11 @@ static int __sbi_send_ipi_v02(const unsigned long *hart_mask)
ecall_failed: ecall_failed:
result = sbi_err_map_linux_errno(ret.error); result = sbi_err_map_linux_errno(ret.error);
pr_err("%s: hbase = [%lu] hmask = [0x%lx] failed (error [%d])\n", pr_err("%s: hbase = [%lu] hmask = [0x%lx] failed (error [%d])\n",
__func__, hbase, hmask_val, result); __func__, hbase, hmask, result);
return result; return result;
} }
static int __sbi_rfence_v02_call(unsigned long fid, unsigned long hmask_val, static int __sbi_rfence_v02_call(unsigned long fid, unsigned long hmask,
unsigned long hbase, unsigned long start, unsigned long hbase, unsigned long start,
unsigned long size, unsigned long arg4, unsigned long size, unsigned long arg4,
unsigned long arg5) unsigned long arg5)
@ -267,31 +298,31 @@ static int __sbi_rfence_v02_call(unsigned long fid, unsigned long hmask_val,
switch (fid) { switch (fid) {
case SBI_EXT_RFENCE_REMOTE_FENCE_I: case SBI_EXT_RFENCE_REMOTE_FENCE_I:
ret = sbi_ecall(ext, fid, hmask_val, hbase, 0, 0, 0, 0); ret = sbi_ecall(ext, fid, hmask, hbase, 0, 0, 0, 0);
break; break;
case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA: case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA:
ret = sbi_ecall(ext, fid, hmask_val, hbase, start, ret = sbi_ecall(ext, fid, hmask, hbase, start,
size, 0, 0); size, 0, 0);
break; break;
case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID: case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID:
ret = sbi_ecall(ext, fid, hmask_val, hbase, start, ret = sbi_ecall(ext, fid, hmask, hbase, start,
size, arg4, 0); size, arg4, 0);
break; break;
case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA: case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA:
ret = sbi_ecall(ext, fid, hmask_val, hbase, start, ret = sbi_ecall(ext, fid, hmask, hbase, start,
size, 0, 0); size, 0, 0);
break; break;
case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID: case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID:
ret = sbi_ecall(ext, fid, hmask_val, hbase, start, ret = sbi_ecall(ext, fid, hmask, hbase, start,
size, arg4, 0); size, arg4, 0);
break; break;
case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA: case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA:
ret = sbi_ecall(ext, fid, hmask_val, hbase, start, ret = sbi_ecall(ext, fid, hmask, hbase, start,
size, 0, 0); size, 0, 0);
break; break;
case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID: case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID:
ret = sbi_ecall(ext, fid, hmask_val, hbase, start, ret = sbi_ecall(ext, fid, hmask, hbase, start,
size, arg4, 0); size, arg4, 0);
break; break;
default: default:
@ -303,43 +334,39 @@ static int __sbi_rfence_v02_call(unsigned long fid, unsigned long hmask_val,
if (ret.error) { if (ret.error) {
result = sbi_err_map_linux_errno(ret.error); result = sbi_err_map_linux_errno(ret.error);
pr_err("%s: hbase = [%lu] hmask = [0x%lx] failed (error [%d])\n", pr_err("%s: hbase = [%lu] hmask = [0x%lx] failed (error [%d])\n",
__func__, hbase, hmask_val, result); __func__, hbase, hmask, result);
} }
return result; return result;
} }
static int __sbi_rfence_v02(int fid, const unsigned long *hart_mask, static int __sbi_rfence_v02(int fid, const struct cpumask *cpu_mask,
unsigned long start, unsigned long size, unsigned long start, unsigned long size,
unsigned long arg4, unsigned long arg5) unsigned long arg4, unsigned long arg5)
{ {
unsigned long hmask_val, hartid, hbase; unsigned long hartid, cpuid, hmask = 0, hbase = 0;
struct cpumask tmask;
int result; int result;
if (!hart_mask || !(*hart_mask)) { if (!cpu_mask)
riscv_cpuid_to_hartid_mask(cpu_online_mask, &tmask); cpu_mask = cpu_online_mask;
hart_mask = cpumask_bits(&tmask);
}
hmask_val = 0; for_each_cpu(cpuid, cpu_mask) {
hbase = 0; hartid = cpuid_to_hartid_map(cpuid);
for_each_set_bit(hartid, hart_mask, NR_CPUS) { if (hmask && ((hbase + BITS_PER_LONG) <= hartid)) {
if (hmask_val && ((hbase + BITS_PER_LONG) <= hartid)) { result = __sbi_rfence_v02_call(fid, hmask, hbase,
result = __sbi_rfence_v02_call(fid, hmask_val, hbase,
start, size, arg4, arg5); start, size, arg4, arg5);
if (result) if (result)
return result; return result;
hmask_val = 0; hmask = 0;
hbase = 0; hbase = 0;
} }
if (!hmask_val) if (!hmask)
hbase = hartid; hbase = hartid;
hmask_val |= 1UL << (hartid - hbase); hmask |= 1UL << (hartid - hbase);
} }
if (hmask_val) { if (hmask) {
result = __sbi_rfence_v02_call(fid, hmask_val, hbase, result = __sbi_rfence_v02_call(fid, hmask, hbase,
start, size, arg4, arg5); start, size, arg4, arg5);
if (result) if (result)
return result; return result;
@ -361,44 +388,44 @@ void sbi_set_timer(uint64_t stime_value)
/** /**
* sbi_send_ipi() - Send an IPI to any hart. * sbi_send_ipi() - Send an IPI to any hart.
* @hart_mask: A cpu mask containing all the target harts. * @cpu_mask: A cpu mask containing all the target harts.
* *
* Return: 0 on success, appropriate linux error code otherwise. * Return: 0 on success, appropriate linux error code otherwise.
*/ */
int sbi_send_ipi(const unsigned long *hart_mask) int sbi_send_ipi(const struct cpumask *cpu_mask)
{ {
return __sbi_send_ipi(hart_mask); return __sbi_send_ipi(cpu_mask);
} }
EXPORT_SYMBOL(sbi_send_ipi); EXPORT_SYMBOL(sbi_send_ipi);
/** /**
* sbi_remote_fence_i() - Execute FENCE.I instruction on given remote harts. * sbi_remote_fence_i() - Execute FENCE.I instruction on given remote harts.
* @hart_mask: A cpu mask containing all the target harts. * @cpu_mask: A cpu mask containing all the target harts.
* *
* Return: 0 on success, appropriate linux error code otherwise. * Return: 0 on success, appropriate linux error code otherwise.
*/ */
int sbi_remote_fence_i(const unsigned long *hart_mask) int sbi_remote_fence_i(const struct cpumask *cpu_mask)
{ {
return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_FENCE_I, return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_FENCE_I,
hart_mask, 0, 0, 0, 0); cpu_mask, 0, 0, 0, 0);
} }
EXPORT_SYMBOL(sbi_remote_fence_i); EXPORT_SYMBOL(sbi_remote_fence_i);
/** /**
* sbi_remote_sfence_vma() - Execute SFENCE.VMA instructions on given remote * sbi_remote_sfence_vma() - Execute SFENCE.VMA instructions on given remote
* harts for the specified virtual address range. * harts for the specified virtual address range.
* @hart_mask: A cpu mask containing all the target harts. * @cpu_mask: A cpu mask containing all the target harts.
* @start: Start of the virtual address * @start: Start of the virtual address
* @size: Total size of the virtual address range. * @size: Total size of the virtual address range.
* *
* Return: 0 on success, appropriate linux error code otherwise. * Return: 0 on success, appropriate linux error code otherwise.
*/ */
int sbi_remote_sfence_vma(const unsigned long *hart_mask, int sbi_remote_sfence_vma(const struct cpumask *cpu_mask,
unsigned long start, unsigned long start,
unsigned long size) unsigned long size)
{ {
return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA, return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
hart_mask, start, size, 0, 0); cpu_mask, start, size, 0, 0);
} }
EXPORT_SYMBOL(sbi_remote_sfence_vma); EXPORT_SYMBOL(sbi_remote_sfence_vma);
@ -406,38 +433,38 @@ EXPORT_SYMBOL(sbi_remote_sfence_vma);
* sbi_remote_sfence_vma_asid() - Execute SFENCE.VMA instructions on given * sbi_remote_sfence_vma_asid() - Execute SFENCE.VMA instructions on given
* remote harts for a virtual address range belonging to a specific ASID. * remote harts for a virtual address range belonging to a specific ASID.
* *
* @hart_mask: A cpu mask containing all the target harts. * @cpu_mask: A cpu mask containing all the target harts.
* @start: Start of the virtual address * @start: Start of the virtual address
* @size: Total size of the virtual address range. * @size: Total size of the virtual address range.
* @asid: The value of address space identifier (ASID). * @asid: The value of address space identifier (ASID).
* *
* Return: 0 on success, appropriate linux error code otherwise. * Return: 0 on success, appropriate linux error code otherwise.
*/ */
int sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, int sbi_remote_sfence_vma_asid(const struct cpumask *cpu_mask,
unsigned long start, unsigned long start,
unsigned long size, unsigned long size,
unsigned long asid) unsigned long asid)
{ {
return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID, return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
hart_mask, start, size, asid, 0); cpu_mask, start, size, asid, 0);
} }
EXPORT_SYMBOL(sbi_remote_sfence_vma_asid); EXPORT_SYMBOL(sbi_remote_sfence_vma_asid);
/** /**
* sbi_remote_hfence_gvma() - Execute HFENCE.GVMA instructions on given remote * sbi_remote_hfence_gvma() - Execute HFENCE.GVMA instructions on given remote
* harts for the specified guest physical address range. * harts for the specified guest physical address range.
* @hart_mask: A cpu mask containing all the target harts. * @cpu_mask: A cpu mask containing all the target harts.
* @start: Start of the guest physical address * @start: Start of the guest physical address
* @size: Total size of the guest physical address range. * @size: Total size of the guest physical address range.
* *
* Return: None * Return: None
*/ */
int sbi_remote_hfence_gvma(const unsigned long *hart_mask, int sbi_remote_hfence_gvma(const struct cpumask *cpu_mask,
unsigned long start, unsigned long start,
unsigned long size) unsigned long size)
{ {
return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA, return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA,
hart_mask, start, size, 0, 0); cpu_mask, start, size, 0, 0);
} }
EXPORT_SYMBOL_GPL(sbi_remote_hfence_gvma); EXPORT_SYMBOL_GPL(sbi_remote_hfence_gvma);
@ -445,38 +472,38 @@ EXPORT_SYMBOL_GPL(sbi_remote_hfence_gvma);
* sbi_remote_hfence_gvma_vmid() - Execute HFENCE.GVMA instructions on given * sbi_remote_hfence_gvma_vmid() - Execute HFENCE.GVMA instructions on given
* remote harts for a guest physical address range belonging to a specific VMID. * remote harts for a guest physical address range belonging to a specific VMID.
* *
* @hart_mask: A cpu mask containing all the target harts. * @cpu_mask: A cpu mask containing all the target harts.
* @start: Start of the guest physical address * @start: Start of the guest physical address
* @size: Total size of the guest physical address range. * @size: Total size of the guest physical address range.
* @vmid: The value of guest ID (VMID). * @vmid: The value of guest ID (VMID).
* *
* Return: 0 if success, Error otherwise. * Return: 0 if success, Error otherwise.
*/ */
int sbi_remote_hfence_gvma_vmid(const unsigned long *hart_mask, int sbi_remote_hfence_gvma_vmid(const struct cpumask *cpu_mask,
unsigned long start, unsigned long start,
unsigned long size, unsigned long size,
unsigned long vmid) unsigned long vmid)
{ {
return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID, return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID,
hart_mask, start, size, vmid, 0); cpu_mask, start, size, vmid, 0);
} }
EXPORT_SYMBOL(sbi_remote_hfence_gvma_vmid); EXPORT_SYMBOL(sbi_remote_hfence_gvma_vmid);
/** /**
* sbi_remote_hfence_vvma() - Execute HFENCE.VVMA instructions on given remote * sbi_remote_hfence_vvma() - Execute HFENCE.VVMA instructions on given remote
* harts for the current guest virtual address range. * harts for the current guest virtual address range.
* @hart_mask: A cpu mask containing all the target harts. * @cpu_mask: A cpu mask containing all the target harts.
* @start: Start of the current guest virtual address * @start: Start of the current guest virtual address
* @size: Total size of the current guest virtual address range. * @size: Total size of the current guest virtual address range.
* *
* Return: None * Return: None
*/ */
int sbi_remote_hfence_vvma(const unsigned long *hart_mask, int sbi_remote_hfence_vvma(const struct cpumask *cpu_mask,
unsigned long start, unsigned long start,
unsigned long size) unsigned long size)
{ {
return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA, return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA,
hart_mask, start, size, 0, 0); cpu_mask, start, size, 0, 0);
} }
EXPORT_SYMBOL(sbi_remote_hfence_vvma); EXPORT_SYMBOL(sbi_remote_hfence_vvma);
@ -485,20 +512,20 @@ EXPORT_SYMBOL(sbi_remote_hfence_vvma);
* remote harts for current guest virtual address range belonging to a specific * remote harts for current guest virtual address range belonging to a specific
* ASID. * ASID.
* *
* @hart_mask: A cpu mask containing all the target harts. * @cpu_mask: A cpu mask containing all the target harts.
* @start: Start of the current guest virtual address * @start: Start of the current guest virtual address
* @size: Total size of the current guest virtual address range. * @size: Total size of the current guest virtual address range.
* @asid: The value of address space identifier (ASID). * @asid: The value of address space identifier (ASID).
* *
* Return: None * Return: None
*/ */
int sbi_remote_hfence_vvma_asid(const unsigned long *hart_mask, int sbi_remote_hfence_vvma_asid(const struct cpumask *cpu_mask,
unsigned long start, unsigned long start,
unsigned long size, unsigned long size,
unsigned long asid) unsigned long asid)
{ {
return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID, return __sbi_rfence(SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID,
hart_mask, start, size, asid, 0); cpu_mask, start, size, asid, 0);
} }
EXPORT_SYMBOL(sbi_remote_hfence_vvma_asid); EXPORT_SYMBOL(sbi_remote_hfence_vvma_asid);
@ -591,11 +618,7 @@ long sbi_get_mimpid(void)
static void sbi_send_cpumask_ipi(const struct cpumask *target) static void sbi_send_cpumask_ipi(const struct cpumask *target)
{ {
struct cpumask hartid_mask; sbi_send_ipi(target);
riscv_cpuid_to_hartid_mask(target, &hartid_mask);
sbi_send_ipi(cpumask_bits(&hartid_mask));
} }
static const struct riscv_ipi_ops sbi_ipi_ops = { static const struct riscv_ipi_ops sbi_ipi_ops = {

View File

@ -59,16 +59,6 @@ atomic_t hart_lottery __section(".sdata")
unsigned long boot_cpu_hartid; unsigned long boot_cpu_hartid;
static DEFINE_PER_CPU(struct cpu, cpu_devices); static DEFINE_PER_CPU(struct cpu, cpu_devices);
void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out)
{
int cpu;
cpumask_clear(out);
for_each_cpu(cpu, in)
cpumask_set_cpu(cpuid_to_hartid_map(cpu), out);
}
EXPORT_SYMBOL_GPL(riscv_cpuid_to_hartid_mask);
/* /*
* Place kernel memory regions on the resource tree so that * Place kernel memory regions on the resource tree so that
* kexec-tools can retrieve them from /proc/iomem. While there * kexec-tools can retrieve them from /proc/iomem. While there

View File

@ -96,7 +96,7 @@ void __init setup_smp(void)
if (cpuid >= NR_CPUS) { if (cpuid >= NR_CPUS) {
pr_warn("Invalid cpuid [%d] for hartid [%d]\n", pr_warn("Invalid cpuid [%d] for hartid [%d]\n",
cpuid, hart); cpuid, hart);
break; continue;
} }
cpuid_to_hartid_map(cpuid) = hart; cpuid_to_hartid_map(cpuid) = hart;

View File

@ -114,7 +114,6 @@ static bool stage2_get_leaf_entry(struct kvm *kvm, gpa_t addr,
static void stage2_remote_tlb_flush(struct kvm *kvm, u32 level, gpa_t addr) static void stage2_remote_tlb_flush(struct kvm *kvm, u32 level, gpa_t addr)
{ {
struct cpumask hmask;
unsigned long size = PAGE_SIZE; unsigned long size = PAGE_SIZE;
struct kvm_vmid *vmid = &kvm->arch.vmid; struct kvm_vmid *vmid = &kvm->arch.vmid;
@ -127,8 +126,7 @@ static void stage2_remote_tlb_flush(struct kvm *kvm, u32 level, gpa_t addr)
* where the Guest/VM is running. * where the Guest/VM is running.
*/ */
preempt_disable(); preempt_disable();
riscv_cpuid_to_hartid_mask(cpu_online_mask, &hmask); sbi_remote_hfence_gvma_vmid(cpu_online_mask, addr, size,
sbi_remote_hfence_gvma_vmid(cpumask_bits(&hmask), addr, size,
READ_ONCE(vmid->vmid)); READ_ONCE(vmid->vmid));
preempt_enable(); preempt_enable();
} }

View File

@ -82,7 +82,7 @@ static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *run
{ {
int ret = 0; int ret = 0;
unsigned long i; unsigned long i;
struct cpumask cm, hm; struct cpumask cm;
struct kvm_vcpu *tmp; struct kvm_vcpu *tmp;
struct kvm_cpu_context *cp = &vcpu->arch.guest_context; struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
unsigned long hmask = cp->a0; unsigned long hmask = cp->a0;
@ -90,7 +90,6 @@ static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *run
unsigned long funcid = cp->a6; unsigned long funcid = cp->a6;
cpumask_clear(&cm); cpumask_clear(&cm);
cpumask_clear(&hm);
kvm_for_each_vcpu(i, tmp, vcpu->kvm) { kvm_for_each_vcpu(i, tmp, vcpu->kvm) {
if (hbase != -1UL) { if (hbase != -1UL) {
if (tmp->vcpu_id < hbase) if (tmp->vcpu_id < hbase)
@ -103,17 +102,15 @@ static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *run
cpumask_set_cpu(tmp->cpu, &cm); cpumask_set_cpu(tmp->cpu, &cm);
} }
riscv_cpuid_to_hartid_mask(&cm, &hm);
switch (funcid) { switch (funcid) {
case SBI_EXT_RFENCE_REMOTE_FENCE_I: case SBI_EXT_RFENCE_REMOTE_FENCE_I:
ret = sbi_remote_fence_i(cpumask_bits(&hm)); ret = sbi_remote_fence_i(&cm);
break; break;
case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA: case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA:
ret = sbi_remote_hfence_vvma(cpumask_bits(&hm), cp->a2, cp->a3); ret = sbi_remote_hfence_vvma(&cm, cp->a2, cp->a3);
break; break;
case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID: case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID:
ret = sbi_remote_hfence_vvma_asid(cpumask_bits(&hm), cp->a2, ret = sbi_remote_hfence_vvma_asid(&cm, cp->a2,
cp->a3, cp->a4); cp->a3, cp->a4);
break; break;
case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA: case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA:

View File

@ -38,7 +38,7 @@ static int kvm_sbi_ext_v01_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
int i, ret = 0; int i, ret = 0;
u64 next_cycle; u64 next_cycle;
struct kvm_vcpu *rvcpu; struct kvm_vcpu *rvcpu;
struct cpumask cm, hm; struct cpumask cm;
struct kvm *kvm = vcpu->kvm; struct kvm *kvm = vcpu->kvm;
struct kvm_cpu_context *cp = &vcpu->arch.guest_context; struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
@ -101,15 +101,12 @@ static int kvm_sbi_ext_v01_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
continue; continue;
cpumask_set_cpu(rvcpu->cpu, &cm); cpumask_set_cpu(rvcpu->cpu, &cm);
} }
riscv_cpuid_to_hartid_mask(&cm, &hm);
if (cp->a7 == SBI_EXT_0_1_REMOTE_FENCE_I) if (cp->a7 == SBI_EXT_0_1_REMOTE_FENCE_I)
ret = sbi_remote_fence_i(cpumask_bits(&hm)); ret = sbi_remote_fence_i(&cm);
else if (cp->a7 == SBI_EXT_0_1_REMOTE_SFENCE_VMA) else if (cp->a7 == SBI_EXT_0_1_REMOTE_SFENCE_VMA)
ret = sbi_remote_hfence_vvma(cpumask_bits(&hm), ret = sbi_remote_hfence_vvma(&cm, cp->a1, cp->a2);
cp->a1, cp->a2);
else else
ret = sbi_remote_hfence_vvma_asid(cpumask_bits(&hm), ret = sbi_remote_hfence_vvma_asid(&cm, cp->a1, cp->a2, cp->a3);
cp->a1, cp->a2, cp->a3);
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;

View File

@ -67,7 +67,6 @@ void kvm_riscv_stage2_vmid_update(struct kvm_vcpu *vcpu)
{ {
unsigned long i; unsigned long i;
struct kvm_vcpu *v; struct kvm_vcpu *v;
struct cpumask hmask;
struct kvm_vmid *vmid = &vcpu->kvm->arch.vmid; struct kvm_vmid *vmid = &vcpu->kvm->arch.vmid;
if (!kvm_riscv_stage2_vmid_ver_changed(vmid)) if (!kvm_riscv_stage2_vmid_ver_changed(vmid))
@ -102,8 +101,7 @@ void kvm_riscv_stage2_vmid_update(struct kvm_vcpu *vcpu)
* running, we force VM exits on all host CPUs using IPI and * running, we force VM exits on all host CPUs using IPI and
* flush all Guest TLBs. * flush all Guest TLBs.
*/ */
riscv_cpuid_to_hartid_mask(cpu_online_mask, &hmask); sbi_remote_hfence_gvma(cpu_online_mask, 0, 0);
sbi_remote_hfence_gvma(cpumask_bits(&hmask), 0, 0);
} }
vmid->vmid = vmid_next; vmid->vmid = vmid_next;

View File

@ -67,10 +67,7 @@ void flush_icache_mm(struct mm_struct *mm, bool local)
*/ */
smp_mb(); smp_mb();
} else if (IS_ENABLED(CONFIG_RISCV_SBI)) { } else if (IS_ENABLED(CONFIG_RISCV_SBI)) {
cpumask_t hartid_mask; sbi_remote_fence_i(&others);
riscv_cpuid_to_hartid_mask(&others, &hartid_mask);
sbi_remote_fence_i(cpumask_bits(&hartid_mask));
} else { } else {
on_each_cpu_mask(&others, ipi_remote_fence_i, NULL, 1); on_each_cpu_mask(&others, ipi_remote_fence_i, NULL, 1);
} }

View File

@ -32,7 +32,6 @@ static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start,
unsigned long size, unsigned long stride) unsigned long size, unsigned long stride)
{ {
struct cpumask *cmask = mm_cpumask(mm); struct cpumask *cmask = mm_cpumask(mm);
struct cpumask hmask;
unsigned int cpuid; unsigned int cpuid;
bool broadcast; bool broadcast;
@ -46,9 +45,7 @@ static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start,
unsigned long asid = atomic_long_read(&mm->context.id); unsigned long asid = atomic_long_read(&mm->context.id);
if (broadcast) { if (broadcast) {
riscv_cpuid_to_hartid_mask(cmask, &hmask); sbi_remote_sfence_vma_asid(cmask, start, size, asid);
sbi_remote_sfence_vma_asid(cpumask_bits(&hmask),
start, size, asid);
} else if (size <= stride) { } else if (size <= stride) {
local_flush_tlb_page_asid(start, asid); local_flush_tlb_page_asid(start, asid);
} else { } else {
@ -56,9 +53,7 @@ static void __sbi_tlb_flush_range(struct mm_struct *mm, unsigned long start,
} }
} else { } else {
if (broadcast) { if (broadcast) {
riscv_cpuid_to_hartid_mask(cmask, &hmask); sbi_remote_sfence_vma(cmask, start, size);
sbi_remote_sfence_vma(cpumask_bits(&hmask),
start, size);
} else if (size <= stride) { } else if (size <= stride) {
local_flush_tlb_page(start); local_flush_tlb_page(start);
} else { } else {