x86/apic: remove apic_ops

All supported Xen instances by FreeBSD provide a local APIC
implementation, so there's no need to replace the native local APIC
implementation anymore.

Leave just the ipi_vectored hook in order to be able to override it
with an implementation based on event channels if the underlying local
APIC is not virtualized by hardware. Note the hook cannot use ifuncs,
because at the point where ifuncs are resolved the kernel doesn't yet
know whether it will benefit from using the optimization.

Sponsored by: Citrix Systems R&D
Reviewed by: kib
Differential revision: https://reviews.freebsd.org/D33917
This commit is contained in:
Roger Pau Monné 2022-01-13 14:48:32 +01:00
parent 2450da6776
commit e0516c7553
4 changed files with 109 additions and 687 deletions

View File

@ -335,4 +335,4 @@ x86/x86/ucode.c standard
x86/x86/delay.c standard
x86/xen/hvm.c optional xenhvm
x86/xen/xen_intr.c optional xenhvm
x86/xen/xen_apic.c optional xenhvm
x86/xen/xen_apic.c optional xenhvm smp

View File

@ -190,6 +190,9 @@ inthand_t
extern vm_paddr_t lapic_paddr;
extern int *apic_cpuids;
/* Allow to replace the lapic_ipi_vectored implementation. */
extern void (*ipi_vectored)(u_int, int);
void apic_register_enumerator(struct apic_enumerator *enumerator);
void *ioapic_create(vm_paddr_t addr, int32_t apic_id, int intbase);
int ioapic_disable_pin(void *cookie, u_int pin);
@ -204,286 +207,48 @@ int ioapic_set_triggermode(void *cookie, u_int pin,
enum intr_trigger trigger);
int ioapic_set_smi(void *cookie, u_int pin);
/*
* Struct containing pointers to APIC functions whose
* implementation is run time selectable.
*/
struct apic_ops {
void (*create)(u_int, int);
void (*init)(vm_paddr_t);
void (*xapic_mode)(void);
bool (*is_x2apic)(void);
void (*setup)(int);
void (*dump)(const char *);
void (*disable)(void);
void (*eoi)(void);
int (*id)(void);
int (*intr_pending)(u_int);
void (*set_logical_id)(u_int, u_int, u_int);
u_int (*cpuid)(u_int);
/* Vectors */
u_int (*alloc_vector)(u_int, u_int);
u_int (*alloc_vectors)(u_int, u_int *, u_int, u_int);
void (*enable_vector)(u_int, u_int);
void (*disable_vector)(u_int, u_int);
void (*free_vector)(u_int, u_int, u_int);
/* Timer */
void (*calibrate_timer)(void);
/* PMC */
int (*enable_pmc)(void);
void (*disable_pmc)(void);
void (*reenable_pmc)(void);
/* CMC */
void (*enable_cmc)(void);
/* AMD ELVT */
int (*enable_mca_elvt)(void);
/* IPI */
void (*ipi_raw)(register_t, u_int);
void (*ipi_vectored)(u_int, int);
int (*ipi_wait)(int);
int (*ipi_alloc)(inthand_t *ipifunc);
void (*ipi_free)(int vector);
/* LVT */
int (*set_lvt_mask)(u_int, u_int, u_char);
int (*set_lvt_mode)(u_int, u_int, u_int32_t);
int (*set_lvt_polarity)(u_int, u_int, enum intr_polarity);
int (*set_lvt_triggermode)(u_int, u_int, enum intr_trigger);
};
extern struct apic_ops apic_ops;
static inline void
lapic_create(u_int apic_id, int boot_cpu)
{
apic_ops.create(apic_id, boot_cpu);
}
static inline void
lapic_init(vm_paddr_t addr)
{
apic_ops.init(addr);
}
static inline void
lapic_xapic_mode(void)
{
apic_ops.xapic_mode();
}
static inline bool
lapic_is_x2apic(void)
{
return (apic_ops.is_x2apic());
}
static inline void
lapic_setup(int boot)
{
apic_ops.setup(boot);
}
static inline void
lapic_dump(const char *str)
{
apic_ops.dump(str);
}
static inline void
lapic_disable(void)
{
apic_ops.disable();
}
static inline void
lapic_eoi(void)
{
apic_ops.eoi();
}
static inline int
lapic_id(void)
{
return (apic_ops.id());
}
static inline int
lapic_intr_pending(u_int vector)
{
return (apic_ops.intr_pending(vector));
}
void lapic_create(u_int apic_id, int boot_cpu);
void lapic_init(vm_paddr_t addr);
void lapic_xapic_mode(void);
bool lapic_is_x2apic(void);
void lapic_setup(int boot);
void lapic_dump(const char *str);
void lapic_disable(void);
void lapic_eoi(void);
int lapic_id(void);
int lapic_intr_pending(u_int vector);
/* XXX: UNUSED */
static inline void
lapic_set_logical_id(u_int apic_id, u_int cluster, u_int cluster_id)
{
apic_ops.set_logical_id(apic_id, cluster, cluster_id);
}
static inline u_int
apic_cpuid(u_int apic_id)
{
return (apic_ops.cpuid(apic_id));
}
static inline u_int
apic_alloc_vector(u_int apic_id, u_int irq)
{
return (apic_ops.alloc_vector(apic_id, irq));
}
static inline u_int
apic_alloc_vectors(u_int apic_id, u_int *irqs, u_int count, u_int align)
{
return (apic_ops.alloc_vectors(apic_id, irqs, count, align));
}
static inline void
apic_enable_vector(u_int apic_id, u_int vector)
{
apic_ops.enable_vector(apic_id, vector);
}
static inline void
apic_disable_vector(u_int apic_id, u_int vector)
{
apic_ops.disable_vector(apic_id, vector);
}
static inline void
apic_free_vector(u_int apic_id, u_int vector, u_int irq)
{
apic_ops.free_vector(apic_id, vector, irq);
}
static inline void
lapic_calibrate_timer(void)
{
apic_ops.calibrate_timer();
}
static inline int
lapic_enable_pmc(void)
{
return (apic_ops.enable_pmc());
}
static inline void
lapic_disable_pmc(void)
{
apic_ops.disable_pmc();
}
static inline void
lapic_reenable_pmc(void)
{
apic_ops.reenable_pmc();
}
static inline void
lapic_enable_cmc(void)
{
apic_ops.enable_cmc();
}
static inline int
lapic_enable_mca_elvt(void)
{
return (apic_ops.enable_mca_elvt());
}
static inline void
lapic_ipi_raw(register_t icrlo, u_int dest)
{
apic_ops.ipi_raw(icrlo, dest);
}
void lapic_set_logical_id(u_int apic_id, u_int cluster, u_int cluster_id);
u_int apic_cpuid(u_int apic_id);
u_int apic_alloc_vector(u_int apic_id, u_int irq);
u_int apic_alloc_vectors(u_int apic_id, u_int *irqs, u_int count, u_int align);
void apic_enable_vector(u_int apic_id, u_int vector);
void apic_disable_vector(u_int apic_id, u_int vector);
void apic_free_vector(u_int apic_id, u_int vector, u_int irq);
void lapic_calibrate_timer(void);
int lapic_enable_pmc(void);
void lapic_disable_pmc(void);
void lapic_reenable_pmc(void);
void lapic_enable_cmc(void);
int lapic_enable_mca_elvt(void);
void lapic_ipi_raw(register_t icrlo, u_int dest);
static inline void
lapic_ipi_vectored(u_int vector, int dest)
{
apic_ops.ipi_vectored(vector, dest);
}
static inline int
lapic_ipi_wait(int delay)
{
return (apic_ops.ipi_wait(delay));
}
static inline int
lapic_ipi_alloc(inthand_t *ipifunc)
{
return (apic_ops.ipi_alloc(ipifunc));
}
static inline void
lapic_ipi_free(int vector)
{
return (apic_ops.ipi_free(vector));
}
static inline int
lapic_set_lvt_mask(u_int apic_id, u_int lvt, u_char masked)
{
return (apic_ops.set_lvt_mask(apic_id, lvt, masked));
}
static inline int
lapic_set_lvt_mode(u_int apic_id, u_int lvt, u_int32_t mode)
{
return (apic_ops.set_lvt_mode(apic_id, lvt, mode));
}
static inline int
lapic_set_lvt_polarity(u_int apic_id, u_int lvt, enum intr_polarity pol)
{
return (apic_ops.set_lvt_polarity(apic_id, lvt, pol));
}
static inline int
lapic_set_lvt_triggermode(u_int apic_id, u_int lvt, enum intr_trigger trigger)
{
return (apic_ops.set_lvt_triggermode(apic_id, lvt, trigger));
ipi_vectored(vector, dest);
}
int lapic_ipi_wait(int delay);
int lapic_ipi_alloc(inthand_t *ipifunc);
void lapic_ipi_free(int vector);
int lapic_set_lvt_mask(u_int apic_id, u_int lvt, u_char masked);
int lapic_set_lvt_mode(u_int apic_id, u_int lvt, u_int32_t mode);
int lapic_set_lvt_polarity(u_int apic_id, u_int lvt,
enum intr_polarity pol);
int lapic_set_lvt_triggermode(u_int apic_id, u_int lvt,
enum intr_trigger trigger);
void lapic_handle_cmc(void);
void lapic_handle_error(void);
void lapic_handle_intr(int vector, struct trapframe *frame);

View File

@ -319,7 +319,7 @@ lapic_write_self_ipi(uint32_t vector)
#endif /* SMP */
static void
native_lapic_enable_x2apic(void)
lapic_enable_x2apic(void)
{
uint64_t apic_base;
@ -328,8 +328,8 @@ native_lapic_enable_x2apic(void)
wrmsr(MSR_APICBASE, apic_base);
}
static bool
native_lapic_is_x2apic(void)
bool
lapic_is_x2apic(void)
{
uint64_t apic_base;
@ -355,84 +355,6 @@ static void lapic_set_tpr(u_int vector);
struct pic lapic_pic = { .pic_resume = lapic_resume };
/* Forward declarations for apic_ops */
static void native_lapic_create(u_int apic_id, int boot_cpu);
static void native_lapic_init(vm_paddr_t addr);
static void native_lapic_xapic_mode(void);
static void native_lapic_setup(int boot);
static void native_lapic_dump(const char *str);
static void native_lapic_disable(void);
static void native_lapic_eoi(void);
static int native_lapic_id(void);
static int native_lapic_intr_pending(u_int vector);
static u_int native_apic_cpuid(u_int apic_id);
static u_int native_apic_alloc_vector(u_int apic_id, u_int irq);
static u_int native_apic_alloc_vectors(u_int apic_id, u_int *irqs,
u_int count, u_int align);
static void native_apic_disable_vector(u_int apic_id, u_int vector);
static void native_apic_enable_vector(u_int apic_id, u_int vector);
static void native_apic_free_vector(u_int apic_id, u_int vector, u_int irq);
static void native_lapic_set_logical_id(u_int apic_id, u_int cluster,
u_int cluster_id);
static void native_lapic_calibrate_timer(void);
static int native_lapic_enable_pmc(void);
static void native_lapic_disable_pmc(void);
static void native_lapic_reenable_pmc(void);
static void native_lapic_enable_cmc(void);
static int native_lapic_enable_mca_elvt(void);
static int native_lapic_set_lvt_mask(u_int apic_id, u_int lvt,
u_char masked);
static int native_lapic_set_lvt_mode(u_int apic_id, u_int lvt,
uint32_t mode);
static int native_lapic_set_lvt_polarity(u_int apic_id, u_int lvt,
enum intr_polarity pol);
static int native_lapic_set_lvt_triggermode(u_int apic_id, u_int lvt,
enum intr_trigger trigger);
#ifdef SMP
static void native_lapic_ipi_raw(register_t icrlo, u_int dest);
static void native_lapic_ipi_vectored(u_int vector, int dest);
static int native_lapic_ipi_wait(int delay);
#endif /* SMP */
static int native_lapic_ipi_alloc(inthand_t *ipifunc);
static void native_lapic_ipi_free(int vector);
struct apic_ops apic_ops = {
.create = native_lapic_create,
.init = native_lapic_init,
.xapic_mode = native_lapic_xapic_mode,
.is_x2apic = native_lapic_is_x2apic,
.setup = native_lapic_setup,
.dump = native_lapic_dump,
.disable = native_lapic_disable,
.eoi = native_lapic_eoi,
.id = native_lapic_id,
.intr_pending = native_lapic_intr_pending,
.set_logical_id = native_lapic_set_logical_id,
.cpuid = native_apic_cpuid,
.alloc_vector = native_apic_alloc_vector,
.alloc_vectors = native_apic_alloc_vectors,
.enable_vector = native_apic_enable_vector,
.disable_vector = native_apic_disable_vector,
.free_vector = native_apic_free_vector,
.calibrate_timer = native_lapic_calibrate_timer,
.enable_pmc = native_lapic_enable_pmc,
.disable_pmc = native_lapic_disable_pmc,
.reenable_pmc = native_lapic_reenable_pmc,
.enable_cmc = native_lapic_enable_cmc,
.enable_mca_elvt = native_lapic_enable_mca_elvt,
#ifdef SMP
.ipi_raw = native_lapic_ipi_raw,
.ipi_vectored = native_lapic_ipi_vectored,
.ipi_wait = native_lapic_ipi_wait,
#endif
.ipi_alloc = native_lapic_ipi_alloc,
.ipi_free = native_lapic_ipi_free,
.set_lvt_mask = native_lapic_set_lvt_mask,
.set_lvt_mode = native_lapic_set_lvt_mode,
.set_lvt_polarity = native_lapic_set_lvt_polarity,
.set_lvt_triggermode = native_lapic_set_lvt_triggermode,
};
static uint32_t
lvt_mode_impl(struct lapic *la, struct lvt *lvt, u_int pin, uint32_t value)
{
@ -502,8 +424,8 @@ elvt_mode(struct lapic *la, u_int idx, uint32_t value)
/*
* Map the local APIC and setup necessary interrupt vectors.
*/
static void
native_lapic_init(vm_paddr_t addr)
void
lapic_init(vm_paddr_t addr)
{
#ifdef SMP
uint64_t r, r1, r2, rx;
@ -526,7 +448,7 @@ native_lapic_init(vm_paddr_t addr)
lapic_paddr = addr;
lapic_map = pmap_mapdev(addr, PAGE_SIZE);
if (x2apic_mode) {
native_lapic_enable_x2apic();
lapic_enable_x2apic();
lapic_map = NULL;
}
@ -614,7 +536,7 @@ native_lapic_init(vm_paddr_t addr)
* Calibrate the busy loop waiting for IPI ack in xAPIC mode.
* lapic_ipi_wait_mult contains the number of iterations which
* approximately delay execution for 1 microsecond (the
* argument to native_lapic_ipi_wait() is in microseconds).
* argument to lapic_ipi_wait() is in microseconds).
*
* We assume that TSC is present and already measured.
* Possible TSC frequency jumps are irrelevant to the
@ -646,8 +568,8 @@ native_lapic_init(vm_paddr_t addr)
/*
* Create a local APIC instance.
*/
static void
native_lapic_create(u_int apic_id, int boot_cpu)
void
lapic_create(u_int apic_id, int boot_cpu)
{
int i;
@ -722,8 +644,8 @@ amd_read_elvt_count(void)
/*
* Dump contents of local APIC registers
*/
static void
native_lapic_dump(const char* str)
void
lapic_dump(const char* str)
{
uint32_t version;
uint32_t maxlvt;
@ -761,19 +683,19 @@ native_lapic_dump(const char* str)
}
}
static void
native_lapic_xapic_mode(void)
void
lapic_xapic_mode(void)
{
register_t saveintr;
saveintr = intr_disable();
if (x2apic_mode)
native_lapic_enable_x2apic();
lapic_enable_x2apic();
intr_restore(saveintr);
}
static void
native_lapic_setup(int boot)
void
lapic_setup(int boot)
{
struct lapic *la;
uint32_t version;
@ -863,7 +785,7 @@ native_lapic_setup(int boot)
}
static void
native_lapic_intrcnt(void *dummy __unused)
lapic_intrcnt(void *dummy __unused)
{
struct pcpu *pc;
struct lapic *la;
@ -882,11 +804,10 @@ native_lapic_intrcnt(void *dummy __unused)
intrcnt_add(buf, &la->la_timer_count);
}
}
SYSINIT(native_lapic_intrcnt, SI_SUB_INTR, SI_ORDER_MIDDLE, native_lapic_intrcnt,
NULL);
SYSINIT(lapic_intrcnt, SI_SUB_INTR, SI_ORDER_MIDDLE, lapic_intrcnt, NULL);
static void
native_lapic_reenable_pmc(void)
void
lapic_reenable_pmc(void)
{
#ifdef HWPMC_HOOKS
uint32_t value;
@ -909,8 +830,8 @@ lapic_update_pmc(void *dummy)
}
#endif
static void
native_lapic_calibrate_timer(void)
void
lapic_calibrate_timer(void)
{
struct lapic *la;
register_t intr;
@ -934,8 +855,8 @@ native_lapic_calibrate_timer(void)
}
}
static int
native_lapic_enable_pmc(void)
int
lapic_enable_pmc(void)
{
#ifdef HWPMC_HOOKS
u_int32_t maxlvt;
@ -975,8 +896,8 @@ native_lapic_enable_pmc(void)
#endif
}
static void
native_lapic_disable_pmc(void)
void
lapic_disable_pmc(void)
{
#ifdef HWPMC_HOOKS
u_int32_t maxlvt;
@ -1131,8 +1052,8 @@ lapic_et_stop(struct eventtimer *et)
return (0);
}
static void
native_lapic_disable(void)
void
lapic_disable(void)
{
uint32_t value;
@ -1164,8 +1085,8 @@ lapic_resume(struct pic *pic, bool suspend_cancelled)
lapic_setup(0);
}
static int
native_lapic_id(void)
int
lapic_id(void)
{
uint32_t v;
@ -1176,8 +1097,8 @@ native_lapic_id(void)
return (v);
}
static int
native_lapic_intr_pending(u_int vector)
int
lapic_intr_pending(u_int vector)
{
uint32_t irr;
@ -1192,8 +1113,8 @@ native_lapic_intr_pending(u_int vector)
return (irr & 1 << (vector % 32));
}
static void
native_lapic_set_logical_id(u_int apic_id, u_int cluster, u_int cluster_id)
void
lapic_set_logical_id(u_int apic_id, u_int cluster, u_int cluster_id)
{
struct lapic *la;
@ -1208,8 +1129,8 @@ native_lapic_set_logical_id(u_int apic_id, u_int cluster, u_int cluster_id)
la->la_cluster_id = cluster_id;
}
static int
native_lapic_set_lvt_mask(u_int apic_id, u_int pin, u_char masked)
int
lapic_set_lvt_mask(u_int apic_id, u_int pin, u_char masked)
{
if (pin > APIC_LVT_MAX)
@ -1231,8 +1152,8 @@ native_lapic_set_lvt_mask(u_int apic_id, u_int pin, u_char masked)
return (0);
}
static int
native_lapic_set_lvt_mode(u_int apic_id, u_int pin, u_int32_t mode)
int
lapic_set_lvt_mode(u_int apic_id, u_int pin, u_int32_t mode)
{
struct lvt *lvt;
@ -1287,8 +1208,8 @@ native_lapic_set_lvt_mode(u_int apic_id, u_int pin, u_int32_t mode)
return (0);
}
static int
native_lapic_set_lvt_polarity(u_int apic_id, u_int pin, enum intr_polarity pol)
int
lapic_set_lvt_polarity(u_int apic_id, u_int pin, enum intr_polarity pol)
{
if (pin > APIC_LVT_MAX || pol == INTR_POLARITY_CONFORM)
@ -1312,8 +1233,8 @@ native_lapic_set_lvt_polarity(u_int apic_id, u_int pin, enum intr_polarity pol)
return (0);
}
static int
native_lapic_set_lvt_triggermode(u_int apic_id, u_int pin,
int
lapic_set_lvt_triggermode(u_int apic_id, u_int pin,
enum intr_trigger trigger)
{
@ -1356,8 +1277,8 @@ lapic_set_tpr(u_int vector)
#endif
}
static void
native_lapic_eoi(void)
void
lapic_eoi(void)
{
lapic_write32_nofence(LAPIC_EOI, 0);
@ -1519,8 +1440,8 @@ lapic_handle_cmc(void)
* is called prior to lapic_setup() during boot, this just needs to unmask
* this CPU's LVT_CMCI entry.
*/
static void
native_lapic_enable_cmc(void)
void
lapic_enable_cmc(void)
{
u_int apic_id;
@ -1535,8 +1456,8 @@ native_lapic_enable_cmc(void)
lapics[apic_id].la_lvts[APIC_LVT_CMCI].lvt_active = 1;
}
static int
native_lapic_enable_mca_elvt(void)
int
lapic_enable_mca_elvt(void)
{
u_int apic_id;
uint32_t value;
@ -1583,8 +1504,8 @@ lapic_handle_error(void)
lapic_eoi();
}
static u_int
native_apic_cpuid(u_int apic_id)
u_int
apic_cpuid(u_int apic_id)
{
#ifdef SMP
return apic_cpuids[apic_id];
@ -1594,8 +1515,8 @@ native_apic_cpuid(u_int apic_id)
}
/* Request a free IDT vector to be used by the specified IRQ. */
static u_int
native_apic_alloc_vector(u_int apic_id, u_int irq)
u_int
apic_alloc_vector(u_int apic_id, u_int irq)
{
u_int vector;
@ -1623,8 +1544,8 @@ native_apic_alloc_vector(u_int apic_id, u_int irq)
* aligned on a boundary of 'align'. If the request cannot be
* satisfied, 0 is returned.
*/
static u_int
native_apic_alloc_vectors(u_int apic_id, u_int *irqs, u_int count, u_int align)
u_int
apic_alloc_vectors(u_int apic_id, u_int *irqs, u_int count, u_int align)
{
u_int first, run, vector;
@ -1682,8 +1603,8 @@ native_apic_alloc_vectors(u_int apic_id, u_int *irqs, u_int count, u_int align)
* which do not have the vector configured would report spurious interrupts
* should it fire.
*/
static void
native_apic_enable_vector(u_int apic_id, u_int vector)
void
apic_enable_vector(u_int apic_id, u_int vector)
{
KASSERT(vector != IDT_SYSCALL, ("Attempt to overwrite syscall entry"));
@ -1697,8 +1618,8 @@ native_apic_enable_vector(u_int apic_id, u_int vector)
SDT_APIC, SEL_KPL, GSEL_APIC);
}
static void
native_apic_disable_vector(u_int apic_id, u_int vector)
void
apic_disable_vector(u_int apic_id, u_int vector)
{
KASSERT(vector != IDT_SYSCALL, ("Attempt to overwrite syscall entry"));
@ -1719,8 +1640,8 @@ native_apic_disable_vector(u_int apic_id, u_int vector)
}
/* Release an APIC vector when it's no longer in use. */
static void
native_apic_free_vector(u_int apic_id, u_int vector, u_int irq)
void
apic_free_vector(u_int apic_id, u_int vector, u_int irq)
{
struct thread *td;
@ -2057,8 +1978,8 @@ SYSINIT(apic_setup_io, SI_SUB_INTR, SI_ORDER_THIRD, apic_setup_io, NULL);
* Wait delay microseconds for IPI to be sent. If delay is -1, we
* wait forever.
*/
static int
native_lapic_ipi_wait(int delay)
int
lapic_ipi_wait(int delay)
{
uint64_t rx;
@ -2075,8 +1996,8 @@ native_lapic_ipi_wait(int delay)
return (0);
}
static void
native_lapic_ipi_raw(register_t icrlo, u_int dest)
void
lapic_ipi_raw(register_t icrlo, u_int dest)
{
uint32_t icrhi;
@ -2184,6 +2105,7 @@ native_lapic_ipi_vectored(u_int vector, int dest)
#endif /* DETECT_DEADLOCK */
}
void (*ipi_vectored)(u_int, int) = &native_lapic_ipi_vectored;
#endif /* SMP */
/*
@ -2199,8 +2121,8 @@ native_lapic_ipi_vectored(u_int vector, int dest)
* explicit 'mfence' before the ICR MSR is written. Therefore in both cases
* the IDT slot update is globally visible before the IPI is delivered.
*/
static int
native_lapic_ipi_alloc(inthand_t *ipifunc)
int
lapic_ipi_alloc(inthand_t *ipifunc)
{
struct gate_descriptor *ip;
long func;
@ -2228,8 +2150,8 @@ native_lapic_ipi_alloc(inthand_t *ipifunc)
return (vector);
}
static void
native_lapic_ipi_free(int vector)
void
lapic_ipi_free(int vector)
{
struct gate_descriptor *ip;
long func __diagused;

View File

@ -57,13 +57,7 @@ __FBSDID("$FreeBSD$");
#include <xen/interface/arch-x86/cpuid.h>
#include <xen/interface/vcpu.h>
/*--------------------------------- Macros -----------------------------------*/
#define XEN_APIC_UNSUPPORTED \
panic("%s: not available in Xen PV port.", __func__)
/*--------------------------- Forward Declarations ---------------------------*/
#ifdef SMP
static driver_filter_t xen_smp_rendezvous_action;
#ifdef __amd64__
static driver_filter_t xen_invlop;
@ -77,13 +71,11 @@ static driver_filter_t xen_ipi_bitmap_handler;
static driver_filter_t xen_cpustop_handler;
static driver_filter_t xen_cpususpend_handler;
static driver_filter_t xen_ipi_swi_handler;
#endif
/*---------------------------------- Macros ----------------------------------*/
#define IPI_TO_IDX(ipi) ((ipi) - APIC_IPI_INTS)
/*--------------------------------- Xen IPIs ---------------------------------*/
#ifdef SMP
struct xen_ipi_handler
{
driver_filter_t *filter;
@ -106,7 +98,6 @@ static struct xen_ipi_handler xen_ipis[] =
[IPI_TO_IDX(IPI_SUSPEND)] = { xen_cpususpend_handler, "sp" },
[IPI_TO_IDX(IPI_SWI)] = { xen_ipi_swi_handler, "sw" },
};
#endif
/*
* Save previous (native) handler as a fallback. Xen < 4.7 doesn't support
@ -117,170 +108,10 @@ static struct xen_ipi_handler xen_ipis[] =
void (*native_ipi_vectored)(u_int, int);
/*------------------------------- Per-CPU Data -------------------------------*/
#ifdef SMP
DPCPU_DEFINE(xen_intr_handle_t, ipi_handle[nitems(xen_ipis)]);
#endif
/*------------------------------- Xen PV APIC --------------------------------*/
static void
xen_pv_lapic_create(u_int apic_id, int boot_cpu)
{
#ifdef SMP
cpu_add(apic_id, boot_cpu);
#endif
}
static void
xen_pv_lapic_init(vm_paddr_t addr)
{
}
static void
xen_pv_lapic_setup(int boot)
{
}
static void
xen_pv_lapic_dump(const char *str)
{
printf("cpu%d %s XEN PV LAPIC\n", PCPU_GET(cpuid), str);
}
static void
xen_pv_lapic_disable(void)
{
}
static bool
xen_pv_lapic_is_x2apic(void)
{
return (false);
}
static void
xen_pv_lapic_eoi(void)
{
XEN_APIC_UNSUPPORTED;
}
static int
xen_pv_lapic_id(void)
{
return (PCPU_GET(apic_id));
}
static int
xen_pv_lapic_intr_pending(u_int vector)
{
XEN_APIC_UNSUPPORTED;
return (0);
}
static u_int
xen_pv_apic_cpuid(u_int apic_id)
{
#ifdef SMP
return (apic_cpuids[apic_id]);
#else
return (0);
#endif
}
static u_int
xen_pv_apic_alloc_vector(u_int apic_id, u_int irq)
{
XEN_APIC_UNSUPPORTED;
return (0);
}
static u_int
xen_pv_apic_alloc_vectors(u_int apic_id, u_int *irqs, u_int count, u_int align)
{
XEN_APIC_UNSUPPORTED;
return (0);
}
static void
xen_pv_apic_disable_vector(u_int apic_id, u_int vector)
{
XEN_APIC_UNSUPPORTED;
}
static void
xen_pv_apic_enable_vector(u_int apic_id, u_int vector)
{
XEN_APIC_UNSUPPORTED;
}
static void
xen_pv_apic_free_vector(u_int apic_id, u_int vector, u_int irq)
{
XEN_APIC_UNSUPPORTED;
}
static void
xen_pv_lapic_calibrate_timer(void)
{
}
static void
xen_pv_lapic_set_logical_id(u_int apic_id, u_int cluster, u_int cluster_id)
{
XEN_APIC_UNSUPPORTED;
}
static int
xen_pv_lapic_enable_pmc(void)
{
XEN_APIC_UNSUPPORTED;
return (0);
}
static void
xen_pv_lapic_disable_pmc(void)
{
XEN_APIC_UNSUPPORTED;
}
static void
xen_pv_lapic_reenable_pmc(void)
{
XEN_APIC_UNSUPPORTED;
}
static void
xen_pv_lapic_enable_cmc(void)
{
}
#ifdef SMP
static void
xen_pv_lapic_ipi_raw(register_t icrlo, u_int dest)
{
XEN_APIC_UNSUPPORTED;
}
#define PCPU_ID_GET(id, field) (pcpu_find(id)->pc_##field)
static int
send_nmi(int dest)
@ -381,101 +212,6 @@ xen_pv_lapic_ipi_vectored(u_int vector, int dest)
}
}
static int
xen_pv_lapic_ipi_wait(int delay)
{
XEN_APIC_UNSUPPORTED;
return (0);
}
#endif /* SMP */
static int
xen_pv_lapic_ipi_alloc(inthand_t *ipifunc)
{
XEN_APIC_UNSUPPORTED;
return (-1);
}
static void
xen_pv_lapic_ipi_free(int vector)
{
XEN_APIC_UNSUPPORTED;
}
static int
xen_pv_lapic_set_lvt_mask(u_int apic_id, u_int lvt, u_char masked)
{
XEN_APIC_UNSUPPORTED;
return (0);
}
static int
xen_pv_lapic_set_lvt_mode(u_int apic_id, u_int lvt, uint32_t mode)
{
XEN_APIC_UNSUPPORTED;
return (0);
}
static int
xen_pv_lapic_set_lvt_polarity(u_int apic_id, u_int lvt, enum intr_polarity pol)
{
XEN_APIC_UNSUPPORTED;
return (0);
}
static int
xen_pv_lapic_set_lvt_triggermode(u_int apic_id, u_int lvt,
enum intr_trigger trigger)
{
XEN_APIC_UNSUPPORTED;
return (0);
}
/* Xen apic_ops implementation */
struct apic_ops xen_apic_ops = {
.create = xen_pv_lapic_create,
.init = xen_pv_lapic_init,
.xapic_mode = xen_pv_lapic_disable,
.is_x2apic = xen_pv_lapic_is_x2apic,
.setup = xen_pv_lapic_setup,
.dump = xen_pv_lapic_dump,
.disable = xen_pv_lapic_disable,
.eoi = xen_pv_lapic_eoi,
.id = xen_pv_lapic_id,
.intr_pending = xen_pv_lapic_intr_pending,
.set_logical_id = xen_pv_lapic_set_logical_id,
.cpuid = xen_pv_apic_cpuid,
.alloc_vector = xen_pv_apic_alloc_vector,
.alloc_vectors = xen_pv_apic_alloc_vectors,
.enable_vector = xen_pv_apic_enable_vector,
.disable_vector = xen_pv_apic_disable_vector,
.free_vector = xen_pv_apic_free_vector,
.calibrate_timer = xen_pv_lapic_calibrate_timer,
.enable_pmc = xen_pv_lapic_enable_pmc,
.disable_pmc = xen_pv_lapic_disable_pmc,
.reenable_pmc = xen_pv_lapic_reenable_pmc,
.enable_cmc = xen_pv_lapic_enable_cmc,
#ifdef SMP
.ipi_raw = xen_pv_lapic_ipi_raw,
.ipi_vectored = xen_pv_lapic_ipi_vectored,
.ipi_wait = xen_pv_lapic_ipi_wait,
#endif
.ipi_alloc = xen_pv_lapic_ipi_alloc,
.ipi_free = xen_pv_lapic_ipi_free,
.set_lvt_mask = xen_pv_lapic_set_lvt_mask,
.set_lvt_mode = xen_pv_lapic_set_lvt_mode,
.set_lvt_polarity = xen_pv_lapic_set_lvt_polarity,
.set_lvt_triggermode = xen_pv_lapic_set_lvt_triggermode,
};
#ifdef SMP
/*---------------------------- XEN PV IPI Handlers ---------------------------*/
/*
* These are C clones of the ASM functions found in apic_vector.
@ -623,10 +359,9 @@ xen_setup_cpus(void)
xen_cpu_ipi_init(i);
/* Set the xen pv ipi ops to replace the native ones */
native_ipi_vectored = apic_ops.ipi_vectored;
apic_ops.ipi_vectored = xen_pv_lapic_ipi_vectored;
ipi_vectored = xen_pv_lapic_ipi_vectored;
native_ipi_vectored = ipi_vectored;
}
/* Switch to using PV IPIs as soon as the vcpu_id is set. */
SYSINIT(xen_setup_cpus, SI_SUB_SMP, SI_ORDER_SECOND, xen_setup_cpus, NULL);
#endif /* SMP */