All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.