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:
parent
2450da6776
commit
e0516c7553
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user