@@ -315,6 +315,8 @@ struct apic {
/* wakeup secondary CPU using 64-bit wakeup point */
int (*wakeup_secondary_cpu_64)(u32 apicid, unsigned long start_eip);
+ void (*update_vector)(unsigned int cpu, unsigned int vector, bool set);
+
char *name;
};
@@ -174,6 +174,8 @@ static void apic_update_vector(struct irq_data *irqd, unsigned int newvec,
apicd->prev_cpu = apicd->cpu;
WARN_ON_ONCE(apicd->cpu == newcpu);
} else {
+ if (apic->update_vector)
+ apic->update_vector(apicd->cpu, apicd->vector, false);
irq_matrix_free(vector_matrix, apicd->cpu, apicd->vector,
managed);
}
@@ -183,6 +185,8 @@ static void apic_update_vector(struct irq_data *irqd, unsigned int newvec,
apicd->cpu = newcpu;
BUG_ON(!IS_ERR_OR_NULL(per_cpu(vector_irq, newcpu)[newvec]));
per_cpu(vector_irq, newcpu)[newvec] = desc;
+ if (apic->update_vector)
+ apic->update_vector(apicd->cpu, apicd->vector, true);
}
static void vector_assign_managed_shutdown(struct irq_data *irqd)
@@ -528,11 +532,15 @@ static bool vector_configure_legacy(unsigned int virq, struct irq_data *irqd,
if (irqd_is_activated(irqd)) {
trace_vector_setup(virq, true, 0);
apic_update_irq_cfg(irqd, apicd->vector, apicd->cpu);
+ if (apic->update_vector)
+ apic->update_vector(apicd->cpu, apicd->vector, true);
} else {
/* Release the vector */
apicd->can_reserve = true;
irqd_set_can_reserve(irqd);
clear_irq_vector(irqd);
+ if (apic->update_vector)
+ apic->update_vector(apicd->cpu, apicd->vector, false);
realloc = true;
}
raw_spin_unlock_irqrestore(&vector_lock, flags);
@@ -19,6 +19,9 @@
#include "local.h"
+#define VEC_POS(v) ((v) & (32 - 1))
+#define REG_POS(v) (((v) >> 5) << 4)
+
static DEFINE_PER_CPU(void *, apic_backing_page);
static DEFINE_PER_CPU(bool, savic_setup_done);
@@ -199,6 +202,22 @@ static void x2apic_savic_send_IPI_mask_allbutself(const struct cpumask *mask, in
__send_IPI_mask(mask, vector, APIC_DEST_ALLBUT);
}
+static void x2apic_savic_update_vector(unsigned int cpu, unsigned int vector, bool set)
+{
+ void *backing_page;
+ unsigned long *reg;
+ int reg_off;
+
+ backing_page = per_cpu(apic_backing_page, cpu);
+ reg_off = SAVIC_ALLOWED_IRR_OFFSET + REG_POS(vector);
+ reg = (unsigned long *)((char *)backing_page + reg_off);
+
+ if (set)
+ test_and_set_bit(VEC_POS(vector), reg);
+ else
+ test_and_clear_bit(VEC_POS(vector), reg);
+}
+
static void init_backing_page(void *backing_page)
{
u32 hv_apic_id;
@@ -313,6 +332,8 @@ static struct apic apic_x2apic_savic __ro_after_init = {
.eoi = native_apic_msr_eoi,
.icr_read = native_x2apic_icr_read,
.icr_write = native_x2apic_icr_write,
+
+ .update_vector = x2apic_savic_update_vector,
};
apic_driver(apic_x2apic_savic);