* [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.