Commit 60791ef3 authored by Neeraj Upadhyay's avatar Neeraj Upadhyay Committed by Borislav Petkov (AMD)
Browse files

x86/apic: Add update_vector() callback for APIC drivers



Add an update_vector() callback to allow APIC drivers to perform driver
specific operations on external vector allocation/teardown on a CPU. This
callback will be used by the Secure AVIC APIC driver to configure the vectors
which a guest vCPU allows the hypervisor to send to it.

As system vectors have fixed vector assignments and are not dynamically
allocated, add an apic_update_vector() public API to facilitate
update_vector() callback invocation for them. This will be used for Secure
AVIC enabled guests to allow the hypervisor to inject system vectors which are
emulated by the hypervisor such as APIC timer vector and
HYPERVISOR_CALLBACK_VECTOR.

While at it, cleanup line break in apic_update_irq_cfg().

Co-developed-by: default avatarKishon Vijay Abraham I <kvijayab@amd.com>
Signed-off-by: default avatarKishon Vijay Abraham I <kvijayab@amd.com>
Signed-off-by: default avatarNeeraj Upadhyay <Neeraj.Upadhyay@amd.com>
Signed-off-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/20250828110255.208779-3-Neeraj.Upadhyay@amd.com
parent 45e2cef5
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -318,6 +318,8 @@ struct apic {
	/* wakeup secondary CPU using 64-bit wakeup point */
	int	(*wakeup_secondary_cpu_64)(u32 apicid, unsigned long start_eip, unsigned int cpu);

	void	(*update_vector)(unsigned int cpu, unsigned int vector, bool set);

	char	*name;
};

@@ -471,6 +473,12 @@ static __always_inline bool apic_id_valid(u32 apic_id)
	return apic_id <= apic->max_apic_id;
}

static __always_inline void apic_update_vector(unsigned int cpu, unsigned int vector, bool set)
{
	if (apic->update_vector)
		apic->update_vector(cpu, vector, set);
}

#else /* CONFIG_X86_LOCAL_APIC */

static inline u32 apic_read(u32 reg) { return 0; }
@@ -482,6 +490,7 @@ static inline void apic_wait_icr_idle(void) { }
static inline u32 safe_apic_wait_icr_idle(void) { return 0; }
static inline void apic_native_eoi(void) { WARN_ON_ONCE(1); }
static inline void apic_setup_apic_calls(void) { }
static inline void apic_update_vector(unsigned int cpu, unsigned int vector, bool set) { }

#define apic_update_callback(_callback, _fn) do { } while (0)

+17 −11
Original line number Diff line number Diff line
@@ -134,13 +134,20 @@ static void apic_update_irq_cfg(struct irq_data *irqd, unsigned int vector,

	apicd->hw_irq_cfg.vector = vector;
	apicd->hw_irq_cfg.dest_apicid = apic->calc_dest_apicid(cpu);

	apic_update_vector(cpu, vector, true);

	irq_data_update_effective_affinity(irqd, cpumask_of(cpu));
	trace_vector_config(irqd->irq, vector, cpu,
			    apicd->hw_irq_cfg.dest_apicid);
	trace_vector_config(irqd->irq, vector, cpu, apicd->hw_irq_cfg.dest_apicid);
}

static void apic_update_vector(struct irq_data *irqd, unsigned int newvec,
			       unsigned int newcpu)
static void apic_free_vector(unsigned int cpu, unsigned int vector, bool managed)
{
	apic_update_vector(cpu, vector, false);
	irq_matrix_free(vector_matrix, cpu, vector, managed);
}

static void chip_data_update(struct irq_data *irqd, unsigned int newvec, unsigned int newcpu)
{
	struct apic_chip_data *apicd = apic_chip_data(irqd);
	struct irq_desc *desc = irq_data_to_desc(irqd);
@@ -174,8 +181,7 @@ static void apic_update_vector(struct irq_data *irqd, unsigned int newvec,
		apicd->prev_cpu = apicd->cpu;
		WARN_ON_ONCE(apicd->cpu == newcpu);
	} else {
		irq_matrix_free(vector_matrix, apicd->cpu, apicd->vector,
				managed);
		apic_free_vector(apicd->cpu, apicd->vector, managed);
	}

setnew:
@@ -261,7 +267,7 @@ assign_vector_locked(struct irq_data *irqd, const struct cpumask *dest)
	trace_vector_alloc(irqd->irq, vector, resvd, vector);
	if (vector < 0)
		return vector;
	apic_update_vector(irqd, vector, cpu);
	chip_data_update(irqd, vector, cpu);

	return 0;
}
@@ -337,7 +343,7 @@ assign_managed_vector(struct irq_data *irqd, const struct cpumask *dest)
	trace_vector_alloc_managed(irqd->irq, vector, vector);
	if (vector < 0)
		return vector;
	apic_update_vector(irqd, vector, cpu);
	chip_data_update(irqd, vector, cpu);

	return 0;
}
@@ -357,7 +363,7 @@ static void clear_irq_vector(struct irq_data *irqd)
			   apicd->prev_cpu);

	per_cpu(vector_irq, apicd->cpu)[vector] = VECTOR_SHUTDOWN;
	irq_matrix_free(vector_matrix, apicd->cpu, vector, managed);
	apic_free_vector(apicd->cpu, vector, managed);
	apicd->vector = 0;

	/* Clean up move in progress */
@@ -366,7 +372,7 @@ static void clear_irq_vector(struct irq_data *irqd)
		return;

	per_cpu(vector_irq, apicd->prev_cpu)[vector] = VECTOR_SHUTDOWN;
	irq_matrix_free(vector_matrix, apicd->prev_cpu, vector, managed);
	apic_free_vector(apicd->prev_cpu, vector, managed);
	apicd->prev_vector = 0;
	apicd->move_in_progress = 0;
	hlist_del_init(&apicd->clist);
@@ -905,7 +911,7 @@ static void free_moved_vector(struct apic_chip_data *apicd)
	 *    affinity mask comes online.
	 */
	trace_vector_free_moved(apicd->irq, cpu, vector, managed);
	irq_matrix_free(vector_matrix, cpu, vector, managed);
	apic_free_vector(cpu, vector, managed);
	per_cpu(vector_irq, cpu)[vector] = VECTOR_UNUSED;
	hlist_del_init(&apicd->clist);
	apicd->prev_vector = 0;