* [PATCH hyperv-next] arch/x86: Provide the CPU number in the wakeup AP callback
@ 2025-04-28 22:59 Roman Kisel
2025-04-30 1:48 ` kernel test robot
2025-04-30 4:05 ` Michael Kelley
0 siblings, 2 replies; 4+ messages in thread
From: Roman Kisel @ 2025-04-28 22:59 UTC (permalink / raw)
To: ardb, bp, dave.hansen, decui, dimitri.sivanich, haiyangz, hpa,
imran.f.khan, jacob.jun.pan, jgross, justin.ernst, kprateek.nayak,
kyle.meyer, kys, lenb, mingo, nikunj, papaluri, perry.yuan,
peterz, rafael, romank, russ.anderson, steve.wahl, tglx,
thomas.lendacky, tim.c.chen, tony.luck, wei.liu, xin, yuehaibing,
linux-acpi, linux-hyperv, linux-kernel, x86
Cc: apais, benhill, bperkins, sunilmut
When starting APs, confidential guests and paravisor guests
need to know the CPU number, and the pattern of using the linear
search has emerged in several places. With N processors that leads
to the O(N^2) time complexity.
Provide the CPU number in the AP wake up callback so that one can
get the CPU number in constant time.
Suggested-by: Michael Kelley <mhklinux@outlook.com>
Signed-off-by: Roman Kisel <romank@linux.microsoft.com>
---
arch/x86/coco/sev/core.c | 18 ++++++++----------
arch/x86/hyperv/hv_vtl.c | 17 +++++++----------
arch/x86/hyperv/ivm.c | 8 +++++++-
arch/x86/include/asm/apic.h | 14 ++++++++++----
arch/x86/include/asm/mshyperv.h | 5 +++--
arch/x86/kernel/acpi/madt_wakeup.c | 8 +++++++-
arch/x86/kernel/apic/apic_noop.c | 2 +-
arch/x86/kernel/apic/x2apic_uv_x.c | 7 ++++++-
arch/x86/kernel/smpboot.c | 19 +++++++++++++++----
9 files changed, 64 insertions(+), 34 deletions(-)
diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
index 82492efc5d94..063f176854fd 100644
--- a/arch/x86/coco/sev/core.c
+++ b/arch/x86/coco/sev/core.c
@@ -1179,17 +1179,24 @@ static void snp_cleanup_vmsa(struct sev_es_save_area *vmsa, int apic_id)
free_page((unsigned long)vmsa);
}
-static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip)
+static int wakeup_cpu_via_vmgexit(struct wakeup_secondary_cpu_data *wakeup)
{
struct sev_es_save_area *cur_vmsa, *vmsa;
struct ghcb_state state;
+ unsigned long start_ip;
struct svsm_ca *caa;
unsigned long flags;
struct ghcb *ghcb;
u8 sipi_vector;
int cpu, ret;
+ u32 apic_id;
u64 cr4;
+
+ cpu = wakeup->cpu;
+ apic_id = wakeup->apicid;
+ start_ip = wakeup->start_ip;
+
/*
* The hypervisor SNP feature support check has happened earlier, just check
* the AP_CREATION one here.
@@ -1208,15 +1215,6 @@ static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip)
/* Override start_ip with known protected guest start IP */
start_ip = real_mode_header->sev_es_trampoline_start;
-
- /* Find the logical CPU for the APIC ID */
- for_each_present_cpu(cpu) {
- if (arch_match_cpu_phys_id(cpu, apic_id))
- break;
- }
- if (cpu >= nr_cpu_ids)
- return -EINVAL;
-
cur_vmsa = per_cpu(sev_vmsa, cpu);
/*
diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c
index 582fe820e29c..7ed3c639d612 100644
--- a/arch/x86/hyperv/hv_vtl.c
+++ b/arch/x86/hyperv/hv_vtl.c
@@ -237,17 +237,14 @@ static int hv_vtl_apicid_to_vp_id(u32 apic_id)
return ret;
}
-static int hv_vtl_wakeup_secondary_cpu(u32 apicid, unsigned long start_eip)
+static int hv_vtl_wakeup_secondary_cpu(struct wakeup_secondary_cpu_data *wakeup)
{
- int vp_id, cpu;
+ unsigned long start_ip;
+ u32 apicid;
+ int vp_id;
- /* Find the logical CPU for the APIC ID */
- for_each_present_cpu(cpu) {
- if (arch_match_cpu_phys_id(cpu, apicid))
- break;
- }
- if (cpu >= nr_cpu_ids)
- return -EINVAL;
+ apicid = wakeup->apicid;
+ start_ip = wakeup->start_ip;
pr_debug("Bringing up CPU with APIC ID %d in VTL2...\n", apicid);
vp_id = hv_vtl_apicid_to_vp_id(apicid);
@@ -261,7 +258,7 @@ static int hv_vtl_wakeup_secondary_cpu(u32 apicid, unsigned long start_eip)
return -EINVAL;
}
- return hv_vtl_bringup_vcpu(vp_id, cpu, start_eip);
+ return hv_vtl_bringup_vcpu(vp_id, wakeup->cpu, start_ip);
}
int __init hv_vtl_early_init(void)
diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c
index c0039a90e9e0..6037cabc1ae0 100644
--- a/arch/x86/hyperv/ivm.c
+++ b/arch/x86/hyperv/ivm.c
@@ -9,6 +9,7 @@
#include <linux/bitfield.h>
#include <linux/types.h>
#include <linux/slab.h>
+#include <asm/apic.h>
#include <asm/svm.h>
#include <asm/sev.h>
#include <asm/io.h>
@@ -288,7 +289,7 @@ static void snp_cleanup_vmsa(struct sev_es_save_area *vmsa)
free_page((unsigned long)vmsa);
}
-int hv_snp_boot_ap(u32 cpu, unsigned long start_ip)
+int hv_snp_boot_ap(struct wakeup_secondary_cpu_data *wakeup)
{
struct sev_es_save_area *vmsa = (struct sev_es_save_area *)
__get_free_page(GFP_KERNEL | __GFP_ZERO);
@@ -296,11 +297,16 @@ int hv_snp_boot_ap(u32 cpu, unsigned long start_ip)
struct desc_ptr gdtr;
u64 ret, retry = 5;
struct hv_enable_vp_vtl *start_vp_input;
+ unsigned long start_ip;
unsigned long flags;
+ u32 cpu;
if (!vmsa)
return -ENOMEM;
+ cpu = wakeup->cpu;
+ start_ip = wakeup->apicid;
+
native_store_gdt(&gdtr);
vmsa->gdtr.base = gdtr.address;
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index f21ff1932699..7e660125f749 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -262,6 +262,12 @@ extern void __init check_x2apic(void);
struct irq_data;
+struct wakeup_secondary_cpu_data {
+ int cpu;
+ u32 apicid;
+ unsigned long start_ip;
+};
+
/*
* Copyright 2004 James Cleverdon, IBM.
*
@@ -313,9 +319,9 @@ struct apic {
u32 (*get_apic_id)(u32 id);
/* wakeup_secondary_cpu */
- int (*wakeup_secondary_cpu)(u32 apicid, unsigned long start_eip);
+ int (*wakeup_secondary_cpu)(struct wakeup_secondary_cpu_data *data);
/* wakeup secondary CPU using 64-bit wakeup point */
- int (*wakeup_secondary_cpu_64)(u32 apicid, unsigned long start_eip);
+ int (*wakeup_secondary_cpu_64)(struct wakeup_secondary_cpu_data *data);
char *name;
};
@@ -333,8 +339,8 @@ struct apic_override {
void (*send_IPI_self)(int vector);
u64 (*icr_read)(void);
void (*icr_write)(u32 low, u32 high);
- int (*wakeup_secondary_cpu)(u32 apicid, unsigned long start_eip);
- int (*wakeup_secondary_cpu_64)(u32 apicid, unsigned long start_eip);
+ int (*wakeup_secondary_cpu)(struct wakeup_secondary_cpu_data *data);
+ int (*wakeup_secondary_cpu_64)(struct wakeup_secondary_cpu_data *data);
};
/*
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 07aadf0e839f..62c64778ad01 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -6,6 +6,7 @@
#include <linux/nmi.h>
#include <linux/msi.h>
#include <linux/io.h>
+#include <asm/apic.h>
#include <asm/nospec-branch.h>
#include <asm/paravirt.h>
#include <hyperv/hvhdk.h>
@@ -268,11 +269,11 @@ int hv_unmap_ioapic_interrupt(int ioapic_id, struct hv_interrupt_entry *entry);
#ifdef CONFIG_AMD_MEM_ENCRYPT
bool hv_ghcb_negotiate_protocol(void);
void __noreturn hv_ghcb_terminate(unsigned int set, unsigned int reason);
-int hv_snp_boot_ap(u32 cpu, unsigned long start_ip);
+int hv_snp_boot_ap(struct wakeup_secondary_cpu_data *wakeup);
#else
static inline bool hv_ghcb_negotiate_protocol(void) { return false; }
static inline void hv_ghcb_terminate(unsigned int set, unsigned int reason) {}
-static inline int hv_snp_boot_ap(u32 cpu, unsigned long start_ip) { return 0; }
+static inline int hv_snp_boot_ap(struct wakeup_secondary_cpu_data *wakeup) { return 0; }
#endif
#if defined(CONFIG_AMD_MEM_ENCRYPT) || defined(CONFIG_INTEL_TDX_GUEST)
diff --git a/arch/x86/kernel/acpi/madt_wakeup.c b/arch/x86/kernel/acpi/madt_wakeup.c
index d5ef6215583b..5de1bd4e49ed 100644
--- a/arch/x86/kernel/acpi/madt_wakeup.c
+++ b/arch/x86/kernel/acpi/madt_wakeup.c
@@ -169,8 +169,14 @@ static int __init acpi_mp_setup_reset(u64 reset_vector)
return 0;
}
-static int acpi_wakeup_cpu(u32 apicid, unsigned long start_ip)
+static int acpi_wakeup_cpu(struct wakeup_secondary_cpu_data *wakeup)
{
+ unsigned long start_ip;
+ u32 apicid;
+
+ start_ip = wakeup->start_ip;
+ apicid = wakeup->apicid;
+
if (!acpi_mp_wake_mailbox_paddr) {
pr_warn_once("No MADT mailbox: cannot bringup secondary CPUs. Booting with kexec?\n");
return -EOPNOTSUPP;
diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c
index b5bb7a2e8340..dd4ba29042f9 100644
--- a/arch/x86/kernel/apic/apic_noop.c
+++ b/arch/x86/kernel/apic/apic_noop.c
@@ -27,7 +27,7 @@ static void noop_send_IPI_allbutself(int vector) { }
static void noop_send_IPI_all(int vector) { }
static void noop_send_IPI_self(int vector) { }
static void noop_apic_icr_write(u32 low, u32 id) { }
-static int noop_wakeup_secondary_cpu(u32 apicid, unsigned long start_eip) { return -1; }
+static int noop_wakeup_secondary_cpu(struct wakeup_secondary_cpu_data *data) { return -1; }
static u64 noop_apic_icr_read(void) { return 0; }
static u32 noop_get_apic_id(u32 apicid) { return 0; }
static void noop_apic_eoi(void) { }
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 7fef504ca508..b76f865c31ef 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -667,11 +667,16 @@ static __init void build_uv_gr_table(void)
}
}
-static int uv_wakeup_secondary(u32 phys_apicid, unsigned long start_rip)
+static int uv_wakeup_secondary(struct wakeup_secondary_cpu_data *wakeup)
{
+ unsigned long start_rip;
unsigned long val;
+ u32 phys_apicid;
int pnode;
+ phys_apicid = wakeup->apicid;
+ start_rip = wakeup->start_ip;
+
pnode = uv_apicid_to_pnode(phys_apicid);
val = (1UL << UVH_IPI_INT_SEND_SHFT) |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index c10850ae6f09..341620f1e1fe 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -715,8 +715,14 @@ static void send_init_sequence(u32 phys_apicid)
/*
* Wake up AP by INIT, INIT, STARTUP sequence.
*/
-static int wakeup_secondary_cpu_via_init(u32 phys_apicid, unsigned long start_eip)
+static int wakeup_secondary_cpu_via_init(struct wakeup_secondary_cpu_data *wakeup)
{
+ unsigned long start_eip;
+ u32 phys_apicid;
+
+ start_eip = wakeup->start_ip;
+ phys_apicid = wakeup->apicid;
+
unsigned long send_status = 0, accept_status = 0;
int num_starts, j, maxlvt;
@@ -865,6 +871,7 @@ int common_cpu_up(unsigned int cpu, struct task_struct *idle)
static int do_boot_cpu(u32 apicid, int cpu, struct task_struct *idle)
{
unsigned long start_ip = real_mode_header->trampoline_start;
+ struct wakeup_secondary_cpu_data wakeup;
int ret;
#ifdef CONFIG_X86_64
@@ -906,6 +913,10 @@ static int do_boot_cpu(u32 apicid, int cpu, struct task_struct *idle)
}
}
+ wakeup.cpu = cpu;
+ wakeup.apicid = apicid;
+ wakeup.start_ip = start_ip;
+
smp_mb();
/*
@@ -916,11 +927,11 @@ static int do_boot_cpu(u32 apicid, int cpu, struct task_struct *idle)
* - Use an INIT boot APIC message
*/
if (apic->wakeup_secondary_cpu_64)
- ret = apic->wakeup_secondary_cpu_64(apicid, start_ip);
+ ret = apic->wakeup_secondary_cpu_64(&wakeup);
else if (apic->wakeup_secondary_cpu)
- ret = apic->wakeup_secondary_cpu(apicid, start_ip);
+ ret = apic->wakeup_secondary_cpu(&wakeup);
else
- ret = wakeup_secondary_cpu_via_init(apicid, start_ip);
+ ret = wakeup_secondary_cpu_via_init(&wakeup);
/* If the wakeup mechanism failed, cleanup the warm reset vector */
if (ret)
base-commit: 628cc040b3a2980df6032766e8ef0688e981ab95
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH hyperv-next] arch/x86: Provide the CPU number in the wakeup AP callback
2025-04-28 22:59 [PATCH hyperv-next] arch/x86: Provide the CPU number in the wakeup AP callback Roman Kisel
@ 2025-04-30 1:48 ` kernel test robot
2025-04-30 4:05 ` Michael Kelley
1 sibling, 0 replies; 4+ messages in thread
From: kernel test robot @ 2025-04-30 1:48 UTC (permalink / raw)
To: Roman Kisel, ardb, bp, dave.hansen, decui, dimitri.sivanich,
haiyangz, hpa, imran.f.khan, jacob.jun.pan, jgross, justin.ernst,
kprateek.nayak, kyle.meyer, kys, lenb, mingo, nikunj, papaluri,
perry.yuan, rafael, russ.anderson, steve.wahl, tglx,
thomas.lendacky, tim.c.chen, tony.luck, wei.liu, xin
Cc: llvm, oe-kbuild-all
Hi Roman,
kernel test robot noticed the following build warnings:
[auto build test WARNING on 628cc040b3a2980df6032766e8ef0688e981ab95]
url: https://github.com/intel-lab-lkp/linux/commits/Roman-Kisel/arch-x86-Provide-the-CPU-number-in-the-wakeup-AP-callback/20250429-070238
base: 628cc040b3a2980df6032766e8ef0688e981ab95
patch link: https://lore.kernel.org/r/20250428225948.810147-1-romank%40linux.microsoft.com
patch subject: [PATCH hyperv-next] arch/x86: Provide the CPU number in the wakeup AP callback
config: x86_64-buildonly-randconfig-006-20250430 (https://download.01.org/0day-ci/archive/20250430/202504300914.IDPnAX2v-lkp@intel.com/config)
compiler: clang version 20.1.2 (https://github.com/llvm/llvm-project 58df0ef89dd64126512e4ee27b4ac3fd8ddf6247)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250430/202504300914.IDPnAX2v-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202504300914.IDPnAX2v-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> arch/x86/hyperv/ivm.c:300:16: warning: variable 'start_ip' set but not used [-Wunused-but-set-variable]
300 | unsigned long start_ip;
| ^
1 warning generated.
vim +/start_ip +300 arch/x86/hyperv/ivm.c
291
292 int hv_snp_boot_ap(struct wakeup_secondary_cpu_data *wakeup)
293 {
294 struct sev_es_save_area *vmsa = (struct sev_es_save_area *)
295 __get_free_page(GFP_KERNEL | __GFP_ZERO);
296 struct sev_es_save_area *cur_vmsa;
297 struct desc_ptr gdtr;
298 u64 ret, retry = 5;
299 struct hv_enable_vp_vtl *start_vp_input;
> 300 unsigned long start_ip;
301 unsigned long flags;
302 u32 cpu;
303
304 if (!vmsa)
305 return -ENOMEM;
306
307 cpu = wakeup->cpu;
308 start_ip = wakeup->apicid;
309
310 native_store_gdt(&gdtr);
311
312 vmsa->gdtr.base = gdtr.address;
313 vmsa->gdtr.limit = gdtr.size;
314
315 asm volatile("movl %%es, %%eax;" : "=a" (vmsa->es.selector));
316 hv_populate_vmcb_seg(vmsa->es, vmsa->gdtr.base);
317
318 asm volatile("movl %%cs, %%eax;" : "=a" (vmsa->cs.selector));
319 hv_populate_vmcb_seg(vmsa->cs, vmsa->gdtr.base);
320
321 asm volatile("movl %%ss, %%eax;" : "=a" (vmsa->ss.selector));
322 hv_populate_vmcb_seg(vmsa->ss, vmsa->gdtr.base);
323
324 asm volatile("movl %%ds, %%eax;" : "=a" (vmsa->ds.selector));
325 hv_populate_vmcb_seg(vmsa->ds, vmsa->gdtr.base);
326
327 vmsa->efer = native_read_msr(MSR_EFER);
328
329 vmsa->cr4 = native_read_cr4();
330 vmsa->cr3 = __native_read_cr3();
331 vmsa->cr0 = native_read_cr0();
332
333 vmsa->xcr0 = 1;
334 vmsa->g_pat = HV_AP_INIT_GPAT_DEFAULT;
335 vmsa->rip = (u64)secondary_startup_64_no_verify;
336 vmsa->rsp = (u64)&ap_start_stack[PAGE_SIZE];
337
338 /*
339 * Set the SNP-specific fields for this VMSA:
340 * VMPL level
341 * SEV_FEATURES (matches the SEV STATUS MSR right shifted 2 bits)
342 */
343 vmsa->vmpl = 0;
344 vmsa->sev_features = sev_status >> 2;
345
346 ret = snp_set_vmsa(vmsa, true);
347 if (ret) {
348 pr_err("RMPADJUST(%llx) failed: %llx\n", (u64)vmsa, ret);
349 free_page((u64)vmsa);
350 return ret;
351 }
352
353 local_irq_save(flags);
354 start_vp_input = (struct hv_enable_vp_vtl *)ap_start_input_arg;
355 memset(start_vp_input, 0, sizeof(*start_vp_input));
356 start_vp_input->partition_id = -1;
357 start_vp_input->vp_index = cpu;
358 start_vp_input->target_vtl.target_vtl = ms_hyperv.vtl;
359 *(u64 *)&start_vp_input->vp_context = __pa(vmsa) | 1;
360
361 do {
362 ret = hv_do_hypercall(HVCALL_START_VP,
363 start_vp_input, NULL);
364 } while (hv_result(ret) == HV_STATUS_TIME_OUT && retry--);
365
366 local_irq_restore(flags);
367
368 if (!hv_result_success(ret)) {
369 pr_err("HvCallStartVirtualProcessor failed: %llx\n", ret);
370 snp_cleanup_vmsa(vmsa);
371 vmsa = NULL;
372 }
373
374 cur_vmsa = per_cpu(hv_sev_vmsa, cpu);
375 /* Free up any previous VMSA page */
376 if (cur_vmsa)
377 snp_cleanup_vmsa(cur_vmsa);
378
379 /* Record the current VMSA page */
380 per_cpu(hv_sev_vmsa, cpu) = vmsa;
381
382 return ret;
383 }
384
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [PATCH hyperv-next] arch/x86: Provide the CPU number in the wakeup AP callback
2025-04-28 22:59 [PATCH hyperv-next] arch/x86: Provide the CPU number in the wakeup AP callback Roman Kisel
2025-04-30 1:48 ` kernel test robot
@ 2025-04-30 4:05 ` Michael Kelley
2025-04-30 15:18 ` Roman Kisel
1 sibling, 1 reply; 4+ messages in thread
From: Michael Kelley @ 2025-04-30 4:05 UTC (permalink / raw)
To: Roman Kisel, ardb@kernel.org, bp@alien8.de,
dave.hansen@linux.intel.com, decui@microsoft.com,
dimitri.sivanich@hpe.com, haiyangz@microsoft.com, hpa@zytor.com,
imran.f.khan@oracle.com, jacob.jun.pan@linux.intel.com,
jgross@suse.com, justin.ernst@hpe.com, kprateek.nayak@amd.com,
kyle.meyer@hpe.com, kys@microsoft.com, lenb@kernel.org,
mingo@redhat.com, nikunj@amd.com, papaluri@amd.com,
perry.yuan@amd.com, peterz@infradead.org, rafael@kernel.org,
russ.anderson@hpe.com, steve.wahl@hpe.com, tglx@linutronix.de,
thomas.lendacky@amd.com, tim.c.chen@linux.intel.com,
tony.luck@intel.com, wei.liu@kernel.org, xin@zytor.com,
yuehaibing@huawei.com, linux-acpi@vger.kernel.org,
linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org,
x86@kernel.org
Cc: apais@microsoft.com, benhill@microsoft.com,
bperkins@microsoft.com, sunilmut@microsoft.com
From: Roman Kisel <romank@linux.microsoft.com> Sent: Monday, April 28, 2025 4:00 PM
>
> When starting APs, confidential guests and paravisor guests
> need to know the CPU number, and the pattern of using the linear
> search has emerged in several places. With N processors that leads
> to the O(N^2) time complexity.
>
> Provide the CPU number in the AP wake up callback so that one can
> get the CPU number in constant time.
This patch aligns with my original suggestion and brings the expected
benefit in runtime and in code simplification. But to me, introducing
struct wakeup_secondary_cpu_data seems a bit unnecessary. The
secondary wakeup functions currently have two arguments, and
increasing that to three arguments is not problematic. I usually see
structures introduced when the argument count gets into the 6 or
more range, and there are multiple call layers that need those same
arguments (such as the TLB flushing code, for example). In those
cases, adding a structure makes sense.
But in this case, quite a few lines of code get added to define local
variables and to pull values out of the structure and into those local
variables, all of which would be avoided if the three arguments just
remained as individual arguments. Adding a structure perhaps makes
it easier to add a 4th argument should the need arise, but that seems
unlikely and could be dealt with when and if it actually happened.
So I'd say drop the structure, and just pass "cpu" directly as a
3rd argument.
Michael
>
> Suggested-by: Michael Kelley <mhklinux@outlook.com>
> Signed-off-by: Roman Kisel <romank@linux.microsoft.com>
> ---
> arch/x86/coco/sev/core.c | 18 ++++++++----------
> arch/x86/hyperv/hv_vtl.c | 17 +++++++----------
> arch/x86/hyperv/ivm.c | 8 +++++++-
> arch/x86/include/asm/apic.h | 14 ++++++++++----
> arch/x86/include/asm/mshyperv.h | 5 +++--
> arch/x86/kernel/acpi/madt_wakeup.c | 8 +++++++-
> arch/x86/kernel/apic/apic_noop.c | 2 +-
> arch/x86/kernel/apic/x2apic_uv_x.c | 7 ++++++-
> arch/x86/kernel/smpboot.c | 19 +++++++++++++++----
> 9 files changed, 64 insertions(+), 34 deletions(-)
>
> diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
> index 82492efc5d94..063f176854fd 100644
> --- a/arch/x86/coco/sev/core.c
> +++ b/arch/x86/coco/sev/core.c
> @@ -1179,17 +1179,24 @@ static void snp_cleanup_vmsa(struct sev_es_save_area *vmsa, int apic_id)
> free_page((unsigned long)vmsa);
> }
>
> -static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip)
> +static int wakeup_cpu_via_vmgexit(struct wakeup_secondary_cpu_data *wakeup)
> {
> struct sev_es_save_area *cur_vmsa, *vmsa;
> struct ghcb_state state;
> + unsigned long start_ip;
> struct svsm_ca *caa;
> unsigned long flags;
> struct ghcb *ghcb;
> u8 sipi_vector;
> int cpu, ret;
> + u32 apic_id;
> u64 cr4;
>
> +
> + cpu = wakeup->cpu;
> + apic_id = wakeup->apicid;
> + start_ip = wakeup->start_ip;
> +
> /*
> * The hypervisor SNP feature support check has happened earlier, just check
> * the AP_CREATION one here.
> @@ -1208,15 +1215,6 @@ static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip)
>
> /* Override start_ip with known protected guest start IP */
> start_ip = real_mode_header->sev_es_trampoline_start;
> -
> - /* Find the logical CPU for the APIC ID */
> - for_each_present_cpu(cpu) {
> - if (arch_match_cpu_phys_id(cpu, apic_id))
> - break;
> - }
> - if (cpu >= nr_cpu_ids)
> - return -EINVAL;
> -
> cur_vmsa = per_cpu(sev_vmsa, cpu);
>
> /*
> diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c
> index 582fe820e29c..7ed3c639d612 100644
> --- a/arch/x86/hyperv/hv_vtl.c
> +++ b/arch/x86/hyperv/hv_vtl.c
> @@ -237,17 +237,14 @@ static int hv_vtl_apicid_to_vp_id(u32 apic_id)
> return ret;
> }
>
> -static int hv_vtl_wakeup_secondary_cpu(u32 apicid, unsigned long start_eip)
> +static int hv_vtl_wakeup_secondary_cpu(struct wakeup_secondary_cpu_data *wakeup)
> {
> - int vp_id, cpu;
> + unsigned long start_ip;
> + u32 apicid;
> + int vp_id;
>
> - /* Find the logical CPU for the APIC ID */
> - for_each_present_cpu(cpu) {
> - if (arch_match_cpu_phys_id(cpu, apicid))
> - break;
> - }
> - if (cpu >= nr_cpu_ids)
> - return -EINVAL;
> + apicid = wakeup->apicid;
> + start_ip = wakeup->start_ip;
>
> pr_debug("Bringing up CPU with APIC ID %d in VTL2...\n", apicid);
> vp_id = hv_vtl_apicid_to_vp_id(apicid);
> @@ -261,7 +258,7 @@ static int hv_vtl_wakeup_secondary_cpu(u32 apicid, unsigned long start_eip)
> return -EINVAL;
> }
>
> - return hv_vtl_bringup_vcpu(vp_id, cpu, start_eip);
> + return hv_vtl_bringup_vcpu(vp_id, wakeup->cpu, start_ip);
> }
>
> int __init hv_vtl_early_init(void)
> diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c
> index c0039a90e9e0..6037cabc1ae0 100644
> --- a/arch/x86/hyperv/ivm.c
> +++ b/arch/x86/hyperv/ivm.c
> @@ -9,6 +9,7 @@
> #include <linux/bitfield.h>
> #include <linux/types.h>
> #include <linux/slab.h>
> +#include <asm/apic.h>
> #include <asm/svm.h>
> #include <asm/sev.h>
> #include <asm/io.h>
> @@ -288,7 +289,7 @@ static void snp_cleanup_vmsa(struct sev_es_save_area *vmsa)
> free_page((unsigned long)vmsa);
> }
>
> -int hv_snp_boot_ap(u32 cpu, unsigned long start_ip)
> +int hv_snp_boot_ap(struct wakeup_secondary_cpu_data *wakeup)
> {
> struct sev_es_save_area *vmsa = (struct sev_es_save_area *)
> __get_free_page(GFP_KERNEL | __GFP_ZERO);
> @@ -296,11 +297,16 @@ int hv_snp_boot_ap(u32 cpu, unsigned long start_ip)
> struct desc_ptr gdtr;
> u64 ret, retry = 5;
> struct hv_enable_vp_vtl *start_vp_input;
> + unsigned long start_ip;
> unsigned long flags;
> + u32 cpu;
>
> if (!vmsa)
> return -ENOMEM;
>
> + cpu = wakeup->cpu;
> + start_ip = wakeup->apicid;
> +
> native_store_gdt(&gdtr);
>
> vmsa->gdtr.base = gdtr.address;
> diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
> index f21ff1932699..7e660125f749 100644
> --- a/arch/x86/include/asm/apic.h
> +++ b/arch/x86/include/asm/apic.h
> @@ -262,6 +262,12 @@ extern void __init check_x2apic(void);
>
> struct irq_data;
>
> +struct wakeup_secondary_cpu_data {
> + int cpu;
> + u32 apicid;
> + unsigned long start_ip;
> +};
> +
> /*
> * Copyright 2004 James Cleverdon, IBM.
> *
> @@ -313,9 +319,9 @@ struct apic {
> u32 (*get_apic_id)(u32 id);
>
> /* wakeup_secondary_cpu */
> - int (*wakeup_secondary_cpu)(u32 apicid, unsigned long start_eip);
> + int (*wakeup_secondary_cpu)(struct wakeup_secondary_cpu_data *data);
> /* wakeup secondary CPU using 64-bit wakeup point */
> - int (*wakeup_secondary_cpu_64)(u32 apicid, unsigned long start_eip);
> + int (*wakeup_secondary_cpu_64)(struct wakeup_secondary_cpu_data *data);
>
> char *name;
> };
> @@ -333,8 +339,8 @@ struct apic_override {
> void (*send_IPI_self)(int vector);
> u64 (*icr_read)(void);
> void (*icr_write)(u32 low, u32 high);
> - int (*wakeup_secondary_cpu)(u32 apicid, unsigned long start_eip);
> - int (*wakeup_secondary_cpu_64)(u32 apicid, unsigned long start_eip);
> + int (*wakeup_secondary_cpu)(struct wakeup_secondary_cpu_data *data);
> + int (*wakeup_secondary_cpu_64)(struct wakeup_secondary_cpu_data *data);
> };
>
> /*
> diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
> index 07aadf0e839f..62c64778ad01 100644
> --- a/arch/x86/include/asm/mshyperv.h
> +++ b/arch/x86/include/asm/mshyperv.h
> @@ -6,6 +6,7 @@
> #include <linux/nmi.h>
> #include <linux/msi.h>
> #include <linux/io.h>
> +#include <asm/apic.h>
> #include <asm/nospec-branch.h>
> #include <asm/paravirt.h>
> #include <hyperv/hvhdk.h>
> @@ -268,11 +269,11 @@ int hv_unmap_ioapic_interrupt(int ioapic_id, struct
> hv_interrupt_entry *entry);
> #ifdef CONFIG_AMD_MEM_ENCRYPT
> bool hv_ghcb_negotiate_protocol(void);
> void __noreturn hv_ghcb_terminate(unsigned int set, unsigned int reason);
> -int hv_snp_boot_ap(u32 cpu, unsigned long start_ip);
> +int hv_snp_boot_ap(struct wakeup_secondary_cpu_data *wakeup);
> #else
> static inline bool hv_ghcb_negotiate_protocol(void) { return false; }
> static inline void hv_ghcb_terminate(unsigned int set, unsigned int reason) {}
> -static inline int hv_snp_boot_ap(u32 cpu, unsigned long start_ip) { return 0; }
> +static inline int hv_snp_boot_ap(struct wakeup_secondary_cpu_data *wakeup) {
> return 0; }
> #endif
>
> #if defined(CONFIG_AMD_MEM_ENCRYPT) || defined(CONFIG_INTEL_TDX_GUEST)
> diff --git a/arch/x86/kernel/acpi/madt_wakeup.c
> b/arch/x86/kernel/acpi/madt_wakeup.c
> index d5ef6215583b..5de1bd4e49ed 100644
> --- a/arch/x86/kernel/acpi/madt_wakeup.c
> +++ b/arch/x86/kernel/acpi/madt_wakeup.c
> @@ -169,8 +169,14 @@ static int __init acpi_mp_setup_reset(u64 reset_vector)
> return 0;
> }
>
> -static int acpi_wakeup_cpu(u32 apicid, unsigned long start_ip)
> +static int acpi_wakeup_cpu(struct wakeup_secondary_cpu_data *wakeup)
> {
> + unsigned long start_ip;
> + u32 apicid;
> +
> + start_ip = wakeup->start_ip;
> + apicid = wakeup->apicid;
> +
> if (!acpi_mp_wake_mailbox_paddr) {
> pr_warn_once("No MADT mailbox: cannot bringup secondary CPUs. Booting with kexec?\n");
> return -EOPNOTSUPP;
> diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c
> index b5bb7a2e8340..dd4ba29042f9 100644
> --- a/arch/x86/kernel/apic/apic_noop.c
> +++ b/arch/x86/kernel/apic/apic_noop.c
> @@ -27,7 +27,7 @@ static void noop_send_IPI_allbutself(int vector) { }
> static void noop_send_IPI_all(int vector) { }
> static void noop_send_IPI_self(int vector) { }
> static void noop_apic_icr_write(u32 low, u32 id) { }
> -static int noop_wakeup_secondary_cpu(u32 apicid, unsigned long start_eip) { return -1; }
> +static int noop_wakeup_secondary_cpu(struct wakeup_secondary_cpu_data *data) { return -1; }
> static u64 noop_apic_icr_read(void) { return 0; }
> static u32 noop_get_apic_id(u32 apicid) { return 0; }
> static void noop_apic_eoi(void) { }
> diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
> index 7fef504ca508..b76f865c31ef 100644
> --- a/arch/x86/kernel/apic/x2apic_uv_x.c
> +++ b/arch/x86/kernel/apic/x2apic_uv_x.c
> @@ -667,11 +667,16 @@ static __init void build_uv_gr_table(void)
> }
> }
>
> -static int uv_wakeup_secondary(u32 phys_apicid, unsigned long start_rip)
> +static int uv_wakeup_secondary(struct wakeup_secondary_cpu_data *wakeup)
> {
> + unsigned long start_rip;
> unsigned long val;
> + u32 phys_apicid;
> int pnode;
>
> + phys_apicid = wakeup->apicid;
> + start_rip = wakeup->start_ip;
> +
> pnode = uv_apicid_to_pnode(phys_apicid);
>
> val = (1UL << UVH_IPI_INT_SEND_SHFT) |
> diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
> index c10850ae6f09..341620f1e1fe 100644
> --- a/arch/x86/kernel/smpboot.c
> +++ b/arch/x86/kernel/smpboot.c
> @@ -715,8 +715,14 @@ static void send_init_sequence(u32 phys_apicid)
> /*
> * Wake up AP by INIT, INIT, STARTUP sequence.
> */
> -static int wakeup_secondary_cpu_via_init(u32 phys_apicid, unsigned long start_eip)
> +static int wakeup_secondary_cpu_via_init(struct wakeup_secondary_cpu_data *wakeup)
> {
> + unsigned long start_eip;
> + u32 phys_apicid;
> +
> + start_eip = wakeup->start_ip;
> + phys_apicid = wakeup->apicid;
> +
> unsigned long send_status = 0, accept_status = 0;
> int num_starts, j, maxlvt;
>
> @@ -865,6 +871,7 @@ int common_cpu_up(unsigned int cpu, struct task_struct *idle)
> static int do_boot_cpu(u32 apicid, int cpu, struct task_struct *idle)
> {
> unsigned long start_ip = real_mode_header->trampoline_start;
> + struct wakeup_secondary_cpu_data wakeup;
> int ret;
>
> #ifdef CONFIG_X86_64
> @@ -906,6 +913,10 @@ static int do_boot_cpu(u32 apicid, int cpu, struct task_struct *idle)
> }
> }
>
> + wakeup.cpu = cpu;
> + wakeup.apicid = apicid;
> + wakeup.start_ip = start_ip;
> +
> smp_mb();
>
> /*
> @@ -916,11 +927,11 @@ static int do_boot_cpu(u32 apicid, int cpu, struct task_struct *idle)
> * - Use an INIT boot APIC message
> */
> if (apic->wakeup_secondary_cpu_64)
> - ret = apic->wakeup_secondary_cpu_64(apicid, start_ip);
> + ret = apic->wakeup_secondary_cpu_64(&wakeup);
> else if (apic->wakeup_secondary_cpu)
> - ret = apic->wakeup_secondary_cpu(apicid, start_ip);
> + ret = apic->wakeup_secondary_cpu(&wakeup);
> else
> - ret = wakeup_secondary_cpu_via_init(apicid, start_ip);
> + ret = wakeup_secondary_cpu_via_init(&wakeup);
>
> /* If the wakeup mechanism failed, cleanup the warm reset vector */
> if (ret)
>
> base-commit: 628cc040b3a2980df6032766e8ef0688e981ab95
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH hyperv-next] arch/x86: Provide the CPU number in the wakeup AP callback
2025-04-30 4:05 ` Michael Kelley
@ 2025-04-30 15:18 ` Roman Kisel
0 siblings, 0 replies; 4+ messages in thread
From: Roman Kisel @ 2025-04-30 15:18 UTC (permalink / raw)
To: Michael Kelley
Cc: apais@microsoft.com, benhill@microsoft.com,
bperkins@microsoft.com, sunilmut@microsoft.com, ardb@kernel.org,
bp@alien8.de, dave.hansen@linux.intel.com, decui@microsoft.com,
dimitri.sivanich@hpe.com, haiyangz@microsoft.com, hpa@zytor.com,
imran.f.khan@oracle.com, jacob.jun.pan@linux.intel.com,
jgross@suse.com, justin.ernst@hpe.com, kprateek.nayak@amd.com,
kyle.meyer@hpe.com, kys@microsoft.com, lenb@kernel.org,
mingo@redhat.com, nikunj@amd.com, papaluri@amd.com,
perry.yuan@amd.com, peterz@infradead.org, rafael@kernel.org,
russ.anderson@hpe.com, steve.wahl@hpe.com, tglx@linutronix.de,
thomas.lendacky@amd.com, tim.c.chen@linux.intel.com,
tony.luck@intel.com, wei.liu@kernel.org, xin@zytor.com,
yuehaibing@huawei.com, linux-acpi@vger.kernel.org,
linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org,
x86@kernel.org
On 4/29/2025 9:05 PM, Michael Kelley wrote:
> From: Roman Kisel <romank@linux.microsoft.com> Sent: Monday, April 28, 2025 4:00 PM
>>
>> When starting APs, confidential guests and paravisor guests
>> need to know the CPU number, and the pattern of using the linear
>> search has emerged in several places. With N processors that leads
>> to the O(N^2) time complexity.
>>
>> Provide the CPU number in the AP wake up callback so that one can
>> get the CPU number in constant time.
>
> This patch aligns with my original suggestion and brings the expected
> benefit in runtime and in code simplification. But to me, introducing
> struct wakeup_secondary_cpu_data seems a bit unnecessary. The
> secondary wakeup functions currently have two arguments, and
> increasing that to three arguments is not problematic. I usually see
> structures introduced when the argument count gets into the 6 or
> more range, and there are multiple call layers that need those same
> arguments (such as the TLB flushing code, for example). In those
> cases, adding a structure makes sense.
>
> But in this case, quite a few lines of code get added to define local
> variables and to pull values out of the structure and into those local
> variables, all of which would be avoided if the three arguments just
> remained as individual arguments. Adding a structure perhaps makes
> it easier to add a 4th argument should the need arise, but that seems
> unlikely and could be dealt with when and if it actually happened.
>
> So I'd say drop the structure, and just pass "cpu" directly as a
> 3rd argument.
Yep, I designed that to be future-proof :D
I do agree with your take on that: likely too much for now, and it's too
early to invest in that. I'll drop the structure, thanks for the
discussion!
>
> Michael
>
>>
>> Suggested-by: Michael Kelley <mhklinux@outlook.com>
>> Signed-off-by: Roman Kisel <romank@linux.microsoft.com>
>> ---
>> arch/x86/coco/sev/core.c | 18 ++++++++----------
>> arch/x86/hyperv/hv_vtl.c | 17 +++++++----------
>> arch/x86/hyperv/ivm.c | 8 +++++++-
>> arch/x86/include/asm/apic.h | 14 ++++++++++----
>> arch/x86/include/asm/mshyperv.h | 5 +++--
>> arch/x86/kernel/acpi/madt_wakeup.c | 8 +++++++-
>> arch/x86/kernel/apic/apic_noop.c | 2 +-
>> arch/x86/kernel/apic/x2apic_uv_x.c | 7 ++++++-
>> arch/x86/kernel/smpboot.c | 19 +++++++++++++++----
>> 9 files changed, 64 insertions(+), 34 deletions(-)
>>
>> diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c
>> index 82492efc5d94..063f176854fd 100644
>> --- a/arch/x86/coco/sev/core.c
>> +++ b/arch/x86/coco/sev/core.c
>> @@ -1179,17 +1179,24 @@ static void snp_cleanup_vmsa(struct sev_es_save_area *vmsa, int apic_id)
>> free_page((unsigned long)vmsa);
>> }
>>
>> -static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip)
>> +static int wakeup_cpu_via_vmgexit(struct wakeup_secondary_cpu_data *wakeup)
>> {
>> struct sev_es_save_area *cur_vmsa, *vmsa;
>> struct ghcb_state state;
>> + unsigned long start_ip;
>> struct svsm_ca *caa;
>> unsigned long flags;
>> struct ghcb *ghcb;
>> u8 sipi_vector;
>> int cpu, ret;
>> + u32 apic_id;
>> u64 cr4;
>>
>> +
>> + cpu = wakeup->cpu;
>> + apic_id = wakeup->apicid;
>> + start_ip = wakeup->start_ip;
>> +
>> /*
>> * The hypervisor SNP feature support check has happened earlier, just check
>> * the AP_CREATION one here.
>> @@ -1208,15 +1215,6 @@ static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip)
>>
>> /* Override start_ip with known protected guest start IP */
>> start_ip = real_mode_header->sev_es_trampoline_start;
>> -
>> - /* Find the logical CPU for the APIC ID */
>> - for_each_present_cpu(cpu) {
>> - if (arch_match_cpu_phys_id(cpu, apic_id))
>> - break;
>> - }
>> - if (cpu >= nr_cpu_ids)
>> - return -EINVAL;
>> -
>> cur_vmsa = per_cpu(sev_vmsa, cpu);
>>
>> /*
>> diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c
>> index 582fe820e29c..7ed3c639d612 100644
>> --- a/arch/x86/hyperv/hv_vtl.c
>> +++ b/arch/x86/hyperv/hv_vtl.c
>> @@ -237,17 +237,14 @@ static int hv_vtl_apicid_to_vp_id(u32 apic_id)
>> return ret;
>> }
>>
>> -static int hv_vtl_wakeup_secondary_cpu(u32 apicid, unsigned long start_eip)
>> +static int hv_vtl_wakeup_secondary_cpu(struct wakeup_secondary_cpu_data *wakeup)
>> {
>> - int vp_id, cpu;
>> + unsigned long start_ip;
>> + u32 apicid;
>> + int vp_id;
>>
>> - /* Find the logical CPU for the APIC ID */
>> - for_each_present_cpu(cpu) {
>> - if (arch_match_cpu_phys_id(cpu, apicid))
>> - break;
>> - }
>> - if (cpu >= nr_cpu_ids)
>> - return -EINVAL;
>> + apicid = wakeup->apicid;
>> + start_ip = wakeup->start_ip;
>>
>> pr_debug("Bringing up CPU with APIC ID %d in VTL2...\n", apicid);
>> vp_id = hv_vtl_apicid_to_vp_id(apicid);
>> @@ -261,7 +258,7 @@ static int hv_vtl_wakeup_secondary_cpu(u32 apicid, unsigned long start_eip)
>> return -EINVAL;
>> }
>>
>> - return hv_vtl_bringup_vcpu(vp_id, cpu, start_eip);
>> + return hv_vtl_bringup_vcpu(vp_id, wakeup->cpu, start_ip);
>> }
>>
>> int __init hv_vtl_early_init(void)
>> diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c
>> index c0039a90e9e0..6037cabc1ae0 100644
>> --- a/arch/x86/hyperv/ivm.c
>> +++ b/arch/x86/hyperv/ivm.c
>> @@ -9,6 +9,7 @@
>> #include <linux/bitfield.h>
>> #include <linux/types.h>
>> #include <linux/slab.h>
>> +#include <asm/apic.h>
>> #include <asm/svm.h>
>> #include <asm/sev.h>
>> #include <asm/io.h>
>> @@ -288,7 +289,7 @@ static void snp_cleanup_vmsa(struct sev_es_save_area *vmsa)
>> free_page((unsigned long)vmsa);
>> }
>>
>> -int hv_snp_boot_ap(u32 cpu, unsigned long start_ip)
>> +int hv_snp_boot_ap(struct wakeup_secondary_cpu_data *wakeup)
>> {
>> struct sev_es_save_area *vmsa = (struct sev_es_save_area *)
>> __get_free_page(GFP_KERNEL | __GFP_ZERO);
>> @@ -296,11 +297,16 @@ int hv_snp_boot_ap(u32 cpu, unsigned long start_ip)
>> struct desc_ptr gdtr;
>> u64 ret, retry = 5;
>> struct hv_enable_vp_vtl *start_vp_input;
>> + unsigned long start_ip;
>> unsigned long flags;
>> + u32 cpu;
>>
>> if (!vmsa)
>> return -ENOMEM;
>>
>> + cpu = wakeup->cpu;
>> + start_ip = wakeup->apicid;
>> +
>> native_store_gdt(&gdtr);
>>
>> vmsa->gdtr.base = gdtr.address;
>> diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
>> index f21ff1932699..7e660125f749 100644
>> --- a/arch/x86/include/asm/apic.h
>> +++ b/arch/x86/include/asm/apic.h
>> @@ -262,6 +262,12 @@ extern void __init check_x2apic(void);
>>
>> struct irq_data;
>>
>> +struct wakeup_secondary_cpu_data {
>> + int cpu;
>> + u32 apicid;
>> + unsigned long start_ip;
>> +};
>> +
>> /*
>> * Copyright 2004 James Cleverdon, IBM.
>> *
>> @@ -313,9 +319,9 @@ struct apic {
>> u32 (*get_apic_id)(u32 id);
>>
>> /* wakeup_secondary_cpu */
>> - int (*wakeup_secondary_cpu)(u32 apicid, unsigned long start_eip);
>> + int (*wakeup_secondary_cpu)(struct wakeup_secondary_cpu_data *data);
>> /* wakeup secondary CPU using 64-bit wakeup point */
>> - int (*wakeup_secondary_cpu_64)(u32 apicid, unsigned long start_eip);
>> + int (*wakeup_secondary_cpu_64)(struct wakeup_secondary_cpu_data *data);
>>
>> char *name;
>> };
>> @@ -333,8 +339,8 @@ struct apic_override {
>> void (*send_IPI_self)(int vector);
>> u64 (*icr_read)(void);
>> void (*icr_write)(u32 low, u32 high);
>> - int (*wakeup_secondary_cpu)(u32 apicid, unsigned long start_eip);
>> - int (*wakeup_secondary_cpu_64)(u32 apicid, unsigned long start_eip);
>> + int (*wakeup_secondary_cpu)(struct wakeup_secondary_cpu_data *data);
>> + int (*wakeup_secondary_cpu_64)(struct wakeup_secondary_cpu_data *data);
>> };
>>
>> /*
>> diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
>> index 07aadf0e839f..62c64778ad01 100644
>> --- a/arch/x86/include/asm/mshyperv.h
>> +++ b/arch/x86/include/asm/mshyperv.h
>> @@ -6,6 +6,7 @@
>> #include <linux/nmi.h>
>> #include <linux/msi.h>
>> #include <linux/io.h>
>> +#include <asm/apic.h>
>> #include <asm/nospec-branch.h>
>> #include <asm/paravirt.h>
>> #include <hyperv/hvhdk.h>
>> @@ -268,11 +269,11 @@ int hv_unmap_ioapic_interrupt(int ioapic_id, struct
>> hv_interrupt_entry *entry);
>> #ifdef CONFIG_AMD_MEM_ENCRYPT
>> bool hv_ghcb_negotiate_protocol(void);
>> void __noreturn hv_ghcb_terminate(unsigned int set, unsigned int reason);
>> -int hv_snp_boot_ap(u32 cpu, unsigned long start_ip);
>> +int hv_snp_boot_ap(struct wakeup_secondary_cpu_data *wakeup);
>> #else
>> static inline bool hv_ghcb_negotiate_protocol(void) { return false; }
>> static inline void hv_ghcb_terminate(unsigned int set, unsigned int reason) {}
>> -static inline int hv_snp_boot_ap(u32 cpu, unsigned long start_ip) { return 0; }
>> +static inline int hv_snp_boot_ap(struct wakeup_secondary_cpu_data *wakeup) {
>> return 0; }
>> #endif
>>
>> #if defined(CONFIG_AMD_MEM_ENCRYPT) || defined(CONFIG_INTEL_TDX_GUEST)
>> diff --git a/arch/x86/kernel/acpi/madt_wakeup.c
>> b/arch/x86/kernel/acpi/madt_wakeup.c
>> index d5ef6215583b..5de1bd4e49ed 100644
>> --- a/arch/x86/kernel/acpi/madt_wakeup.c
>> +++ b/arch/x86/kernel/acpi/madt_wakeup.c
>> @@ -169,8 +169,14 @@ static int __init acpi_mp_setup_reset(u64 reset_vector)
>> return 0;
>> }
>>
>> -static int acpi_wakeup_cpu(u32 apicid, unsigned long start_ip)
>> +static int acpi_wakeup_cpu(struct wakeup_secondary_cpu_data *wakeup)
>> {
>> + unsigned long start_ip;
>> + u32 apicid;
>> +
>> + start_ip = wakeup->start_ip;
>> + apicid = wakeup->apicid;
>> +
>> if (!acpi_mp_wake_mailbox_paddr) {
>> pr_warn_once("No MADT mailbox: cannot bringup secondary CPUs. Booting with kexec?\n");
>> return -EOPNOTSUPP;
>> diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c
>> index b5bb7a2e8340..dd4ba29042f9 100644
>> --- a/arch/x86/kernel/apic/apic_noop.c
>> +++ b/arch/x86/kernel/apic/apic_noop.c
>> @@ -27,7 +27,7 @@ static void noop_send_IPI_allbutself(int vector) { }
>> static void noop_send_IPI_all(int vector) { }
>> static void noop_send_IPI_self(int vector) { }
>> static void noop_apic_icr_write(u32 low, u32 id) { }
>> -static int noop_wakeup_secondary_cpu(u32 apicid, unsigned long start_eip) { return -1; }
>> +static int noop_wakeup_secondary_cpu(struct wakeup_secondary_cpu_data *data) { return -1; }
>> static u64 noop_apic_icr_read(void) { return 0; }
>> static u32 noop_get_apic_id(u32 apicid) { return 0; }
>> static void noop_apic_eoi(void) { }
>> diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
>> index 7fef504ca508..b76f865c31ef 100644
>> --- a/arch/x86/kernel/apic/x2apic_uv_x.c
>> +++ b/arch/x86/kernel/apic/x2apic_uv_x.c
>> @@ -667,11 +667,16 @@ static __init void build_uv_gr_table(void)
>> }
>> }
>>
>> -static int uv_wakeup_secondary(u32 phys_apicid, unsigned long start_rip)
>> +static int uv_wakeup_secondary(struct wakeup_secondary_cpu_data *wakeup)
>> {
>> + unsigned long start_rip;
>> unsigned long val;
>> + u32 phys_apicid;
>> int pnode;
>>
>> + phys_apicid = wakeup->apicid;
>> + start_rip = wakeup->start_ip;
>> +
>> pnode = uv_apicid_to_pnode(phys_apicid);
>>
>> val = (1UL << UVH_IPI_INT_SEND_SHFT) |
>> diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
>> index c10850ae6f09..341620f1e1fe 100644
>> --- a/arch/x86/kernel/smpboot.c
>> +++ b/arch/x86/kernel/smpboot.c
>> @@ -715,8 +715,14 @@ static void send_init_sequence(u32 phys_apicid)
>> /*
>> * Wake up AP by INIT, INIT, STARTUP sequence.
>> */
>> -static int wakeup_secondary_cpu_via_init(u32 phys_apicid, unsigned long start_eip)
>> +static int wakeup_secondary_cpu_via_init(struct wakeup_secondary_cpu_data *wakeup)
>> {
>> + unsigned long start_eip;
>> + u32 phys_apicid;
>> +
>> + start_eip = wakeup->start_ip;
>> + phys_apicid = wakeup->apicid;
>> +
>> unsigned long send_status = 0, accept_status = 0;
>> int num_starts, j, maxlvt;
>>
>> @@ -865,6 +871,7 @@ int common_cpu_up(unsigned int cpu, struct task_struct *idle)
>> static int do_boot_cpu(u32 apicid, int cpu, struct task_struct *idle)
>> {
>> unsigned long start_ip = real_mode_header->trampoline_start;
>> + struct wakeup_secondary_cpu_data wakeup;
>> int ret;
>>
>> #ifdef CONFIG_X86_64
>> @@ -906,6 +913,10 @@ static int do_boot_cpu(u32 apicid, int cpu, struct task_struct *idle)
>> }
>> }
>>
>> + wakeup.cpu = cpu;
>> + wakeup.apicid = apicid;
>> + wakeup.start_ip = start_ip;
>> +
>> smp_mb();
>>
>> /*
>> @@ -916,11 +927,11 @@ static int do_boot_cpu(u32 apicid, int cpu, struct task_struct *idle)
>> * - Use an INIT boot APIC message
>> */
>> if (apic->wakeup_secondary_cpu_64)
>> - ret = apic->wakeup_secondary_cpu_64(apicid, start_ip);
>> + ret = apic->wakeup_secondary_cpu_64(&wakeup);
>> else if (apic->wakeup_secondary_cpu)
>> - ret = apic->wakeup_secondary_cpu(apicid, start_ip);
>> + ret = apic->wakeup_secondary_cpu(&wakeup);
>> else
>> - ret = wakeup_secondary_cpu_via_init(apicid, start_ip);
>> + ret = wakeup_secondary_cpu_via_init(&wakeup);
>>
>> /* If the wakeup mechanism failed, cleanup the warm reset vector */
>> if (ret)
>>
>> base-commit: 628cc040b3a2980df6032766e8ef0688e981ab95
>> --
>> 2.43.0
>>
>
--
Thank you,
Roman
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-04-30 15:18 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-28 22:59 [PATCH hyperv-next] arch/x86: Provide the CPU number in the wakeup AP callback Roman Kisel
2025-04-30 1:48 ` kernel test robot
2025-04-30 4:05 ` Michael Kelley
2025-04-30 15:18 ` Roman Kisel
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.