Skip to content

Commit 366f03b

Browse files
kattisrinivasanKAGA-KOKO
authored andcommitted
X86/Hyper-V: Enhanced IPI enlightenment
Support enhanced IPI enlightenments (to target more than 64 CPUs). Signed-off-by: K. Y. Srinivasan <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Michael Kelley <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Link: https://lkml.kernel.org/r/[email protected]
1 parent 68bb7bf commit 366f03b

File tree

4 files changed

+89
-3
lines changed

4 files changed

+89
-3
lines changed

arch/x86/hyperv/hv_apic.c

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,40 @@ static void hv_apic_eoi_write(u32 reg, u32 val)
9393
/*
9494
* IPI implementation on Hyper-V.
9595
*/
96+
static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector)
97+
{
98+
struct ipi_arg_ex **arg;
99+
struct ipi_arg_ex *ipi_arg;
100+
unsigned long flags;
101+
int nr_bank = 0;
102+
int ret = 1;
103+
104+
local_irq_save(flags);
105+
arg = (struct ipi_arg_ex **)this_cpu_ptr(hyperv_pcpu_input_arg);
106+
107+
ipi_arg = *arg;
108+
if (unlikely(!ipi_arg))
109+
goto ipi_mask_ex_done;
110+
111+
ipi_arg->vector = vector;
112+
ipi_arg->reserved = 0;
113+
ipi_arg->vp_set.valid_bank_mask = 0;
114+
115+
if (!cpumask_equal(mask, cpu_present_mask)) {
116+
ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K;
117+
nr_bank = cpumask_to_vpset(&(ipi_arg->vp_set), mask);
118+
}
119+
if (!nr_bank)
120+
ipi_arg->vp_set.format = HV_GENERIC_SET_ALL;
121+
122+
ret = hv_do_rep_hypercall(HVCALL_SEND_IPI_EX, 0, nr_bank,
123+
ipi_arg, NULL);
124+
125+
ipi_mask_ex_done:
126+
local_irq_restore(flags);
127+
return ((ret == 0) ? true : false);
128+
}
129+
96130
static bool __send_ipi_mask(const struct cpumask *mask, int vector)
97131
{
98132
int cur_cpu, vcpu;
@@ -110,6 +144,9 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector)
110144
if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
111145
return false;
112146

147+
if ((ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED))
148+
return __send_ipi_mask_ex(mask, vector);
149+
113150
local_irq_save(flags);
114151
arg = (struct ipi_arg_non_ex **)this_cpu_ptr(hyperv_pcpu_input_arg);
115152

@@ -193,7 +230,10 @@ static void hv_send_ipi_self(int vector)
193230
void __init hv_apic_init(void)
194231
{
195232
if (ms_hyperv.hints & HV_X64_CLUSTER_IPI_RECOMMENDED) {
196-
pr_info("Hyper-V: Using IPI hypercalls\n");
233+
if ((ms_hyperv.hints & HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED))
234+
pr_info("Hyper-V: Using ext hypercalls for IPI\n");
235+
else
236+
pr_info("Hyper-V: Using IPI hypercalls\n");
197237
/*
198238
* Set the IPI entry points.
199239
*/

arch/x86/hyperv/mmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus,
239239
flush->hv_vp_set.valid_bank_mask = 0;
240240

241241
if (!cpumask_equal(cpus, cpu_present_mask)) {
242-
flush->hv_vp_set.format = HV_GENERIC_SET_SPARCE_4K;
242+
flush->hv_vp_set.format = HV_GENERIC_SET_SPARSE_4K;
243243
nr_bank = cpumask_to_vp_set(flush, cpus);
244244
}
245245

arch/x86/include/asm/hyperv-tlfs.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ struct hv_tsc_emulation_status {
344344
#define HVCALL_SEND_IPI 0x000b
345345
#define HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX 0x0013
346346
#define HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX 0x0014
347+
#define HVCALL_SEND_IPI_EX 0x0015
347348
#define HVCALL_POST_MESSAGE 0x005c
348349
#define HVCALL_SIGNAL_EVENT 0x005d
349350

@@ -369,7 +370,7 @@ struct hv_tsc_emulation_status {
369370
#define HV_FLUSH_USE_EXTENDED_RANGE_FORMAT BIT(3)
370371

371372
enum HV_GENERIC_SET_FORMAT {
372-
HV_GENERIC_SET_SPARCE_4K,
373+
HV_GENERIC_SET_SPARSE_4K,
373374
HV_GENERIC_SET_ALL,
374375
};
375376

@@ -721,4 +722,16 @@ struct ipi_arg_non_ex {
721722
u64 cpu_mask;
722723
};
723724

725+
struct hv_vpset {
726+
u64 format;
727+
u64 valid_bank_mask;
728+
u64 bank_contents[];
729+
};
730+
731+
struct ipi_arg_ex {
732+
u32 vector;
733+
u32 reserved;
734+
struct hv_vpset vp_set;
735+
};
736+
724737
#endif

arch/x86/include/asm/mshyperv.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,39 @@ static inline int hv_cpu_number_to_vp_number(int cpu_number)
259259
return hv_vp_index[cpu_number];
260260
}
261261

262+
static inline int cpumask_to_vpset(struct hv_vpset *vpset,
263+
const struct cpumask *cpus)
264+
{
265+
int cpu, vcpu, vcpu_bank, vcpu_offset, nr_bank = 1;
266+
267+
/* valid_bank_mask can represent up to 64 banks */
268+
if (hv_max_vp_index / 64 >= 64)
269+
return 0;
270+
271+
/*
272+
* Clear all banks up to the maximum possible bank as hv_flush_pcpu_ex
273+
* structs are not cleared between calls, we risk flushing unneeded
274+
* vCPUs otherwise.
275+
*/
276+
for (vcpu_bank = 0; vcpu_bank <= hv_max_vp_index / 64; vcpu_bank++)
277+
vpset->bank_contents[vcpu_bank] = 0;
278+
279+
/*
280+
* Some banks may end up being empty but this is acceptable.
281+
*/
282+
for_each_cpu(cpu, cpus) {
283+
vcpu = hv_cpu_number_to_vp_number(cpu);
284+
vcpu_bank = vcpu / 64;
285+
vcpu_offset = vcpu % 64;
286+
__set_bit(vcpu_offset, (unsigned long *)
287+
&vpset->bank_contents[vcpu_bank]);
288+
if (vcpu_bank >= nr_bank)
289+
nr_bank = vcpu_bank + 1;
290+
}
291+
vpset->valid_bank_mask = GENMASK_ULL(nr_bank - 1, 0);
292+
return nr_bank;
293+
}
294+
262295
void __init hyperv_init(void);
263296
void hyperv_setup_mmu_ops(void);
264297
void hyper_alloc_mmu(void);

0 commit comments

Comments
 (0)