Commit f08b9c2f authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86/apic changes from Ingo Molnar:
 "Most of the changes are about helping virtualized guest kernels
  achieve better performance."

Fix up trivial conflicts with the iommu updates to arch/x86/kernel/apic/io_apic.c

* 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/apic: Implement EIO micro-optimization
  x86/apic: Add apic->eoi_write() callback
  x86/apic: Use symbolic APIC_EOI_ACK
  x86/apic: Fix typo EIO_ACK -> EOI_ACK and document it
  x86/xen/apic: Add missing #include <xen/xen.h>
  x86/apic: Only compile local function if used with !CONFIG_GENERIC_PENDING_IRQ
  x86/apic: Fix UP boot crash
  x86: Conditionally update time when ack-ing pending irqs
  xen/apic: implement io apic read with hypercall
  Revert "xen/x86: Workaround 'x86/ioapic: Add register level checks to detect bogus io-apic entries'"
  xen/x86: Implement x86_apic_ops
  x86/apic: Replace io_apic_ops with x86_io_apic_ops.
parents d79ee93d 0ab711ae
...@@ -138,6 +138,11 @@ static inline void native_apic_msr_write(u32 reg, u32 v) ...@@ -138,6 +138,11 @@ static inline void native_apic_msr_write(u32 reg, u32 v)
wrmsr(APIC_BASE_MSR + (reg >> 4), v, 0); wrmsr(APIC_BASE_MSR + (reg >> 4), v, 0);
} }
static inline void native_apic_msr_eoi_write(u32 reg, u32 v)
{
wrmsr(APIC_BASE_MSR + (APIC_EOI >> 4), APIC_EOI_ACK, 0);
}
static inline u32 native_apic_msr_read(u32 reg) static inline u32 native_apic_msr_read(u32 reg)
{ {
u64 msr; u64 msr;
...@@ -351,6 +356,14 @@ struct apic { ...@@ -351,6 +356,14 @@ struct apic {
/* apic ops */ /* apic ops */
u32 (*read)(u32 reg); u32 (*read)(u32 reg);
void (*write)(u32 reg, u32 v); void (*write)(u32 reg, u32 v);
/*
* ->eoi_write() has the same signature as ->write().
*
* Drivers can support both ->eoi_write() and ->write() by passing the same
* callback value. Kernel can override ->eoi_write() and fall back
* on write for EOI.
*/
void (*eoi_write)(u32 reg, u32 v);
u64 (*icr_read)(void); u64 (*icr_read)(void);
void (*icr_write)(u32 low, u32 high); void (*icr_write)(u32 low, u32 high);
void (*wait_icr_idle)(void); void (*wait_icr_idle)(void);
...@@ -426,6 +439,11 @@ static inline void apic_write(u32 reg, u32 val) ...@@ -426,6 +439,11 @@ static inline void apic_write(u32 reg, u32 val)
apic->write(reg, val); apic->write(reg, val);
} }
static inline void apic_eoi(void)
{
apic->eoi_write(APIC_EOI, APIC_EOI_ACK);
}
static inline u64 apic_icr_read(void) static inline u64 apic_icr_read(void)
{ {
return apic->icr_read(); return apic->icr_read();
...@@ -450,6 +468,7 @@ static inline u32 safe_apic_wait_icr_idle(void) ...@@ -450,6 +468,7 @@ static inline u32 safe_apic_wait_icr_idle(void)
static inline u32 apic_read(u32 reg) { return 0; } static inline u32 apic_read(u32 reg) { return 0; }
static inline void apic_write(u32 reg, u32 val) { } static inline void apic_write(u32 reg, u32 val) { }
static inline void apic_eoi(void) { }
static inline u64 apic_icr_read(void) { return 0; } static inline u64 apic_icr_read(void) { return 0; }
static inline void apic_icr_write(u32 low, u32 high) { } static inline void apic_icr_write(u32 low, u32 high) { }
static inline void apic_wait_icr_idle(void) { } static inline void apic_wait_icr_idle(void) { }
...@@ -463,9 +482,7 @@ static inline void ack_APIC_irq(void) ...@@ -463,9 +482,7 @@ static inline void ack_APIC_irq(void)
* ack_APIC_irq() actually gets compiled as a single instruction * ack_APIC_irq() actually gets compiled as a single instruction
* ... yummie. * ... yummie.
*/ */
apic_eoi();
/* Docs say use 0 for future compatibility */
apic_write(APIC_EOI, 0);
} }
static inline unsigned default_get_apic_id(unsigned long x) static inline unsigned default_get_apic_id(unsigned long x)
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#define APIC_ARBPRI_MASK 0xFFu #define APIC_ARBPRI_MASK 0xFFu
#define APIC_PROCPRI 0xA0 #define APIC_PROCPRI 0xA0
#define APIC_EOI 0xB0 #define APIC_EOI 0xB0
#define APIC_EIO_ACK 0x0 #define APIC_EOI_ACK 0x0 /* Docs say 0 for future compat. */
#define APIC_RRR 0xC0 #define APIC_RRR 0xC0
#define APIC_LDR 0xD0 #define APIC_LDR 0xD0
#define APIC_LDR_MASK (0xFFu << 24) #define APIC_LDR_MASK (0xFFu << 24)
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#include <asm/mpspec.h> #include <asm/mpspec.h>
#include <asm/apicdef.h> #include <asm/apicdef.h>
#include <asm/irq_vectors.h> #include <asm/irq_vectors.h>
#include <asm/x86_init.h>
/* /*
* Intel IO-APIC support for SMP and UP systems. * Intel IO-APIC support for SMP and UP systems.
* *
...@@ -21,15 +21,6 @@ ...@@ -21,15 +21,6 @@
#define IO_APIC_REDIR_LEVEL_TRIGGER (1 << 15) #define IO_APIC_REDIR_LEVEL_TRIGGER (1 << 15)
#define IO_APIC_REDIR_MASKED (1 << 16) #define IO_APIC_REDIR_MASKED (1 << 16)
struct io_apic_ops {
void (*init) (void);
unsigned int (*read) (unsigned int apic, unsigned int reg);
void (*write) (unsigned int apic, unsigned int reg, unsigned int value);
void (*modify)(unsigned int apic, unsigned int reg, unsigned int value);
};
void __init set_io_apic_ops(const struct io_apic_ops *);
/* /*
* The structure of the IO-APIC: * The structure of the IO-APIC:
*/ */
...@@ -156,7 +147,6 @@ struct io_apic_irq_attr; ...@@ -156,7 +147,6 @@ struct io_apic_irq_attr;
extern int io_apic_set_pci_routing(struct device *dev, int irq, extern int io_apic_set_pci_routing(struct device *dev, int irq,
struct io_apic_irq_attr *irq_attr); struct io_apic_irq_attr *irq_attr);
void setup_IO_APIC_irq_extra(u32 gsi); void setup_IO_APIC_irq_extra(u32 gsi);
extern void ioapic_and_gsi_init(void);
extern void ioapic_insert_resources(void); extern void ioapic_insert_resources(void);
int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr); int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr);
...@@ -185,12 +175,29 @@ extern void mp_save_irq(struct mpc_intsrc *m); ...@@ -185,12 +175,29 @@ extern void mp_save_irq(struct mpc_intsrc *m);
extern void disable_ioapic_support(void); extern void disable_ioapic_support(void);
extern void __init native_io_apic_init_mappings(void);
extern unsigned int native_io_apic_read(unsigned int apic, unsigned int reg);
extern void native_io_apic_write(unsigned int apic, unsigned int reg, unsigned int val);
extern void native_io_apic_modify(unsigned int apic, unsigned int reg, unsigned int val);
static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
{
return x86_io_apic_ops.read(apic, reg);
}
static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
{
x86_io_apic_ops.write(apic, reg, value);
}
static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
{
x86_io_apic_ops.modify(apic, reg, value);
}
#else /* !CONFIG_X86_IO_APIC */ #else /* !CONFIG_X86_IO_APIC */
#define io_apic_assign_pci_irqs 0 #define io_apic_assign_pci_irqs 0
#define setup_ioapic_ids_from_mpc x86_init_noop #define setup_ioapic_ids_from_mpc x86_init_noop
static const int timer_through_8259 = 0; static const int timer_through_8259 = 0;
static inline void ioapic_and_gsi_init(void) { }
static inline void ioapic_insert_resources(void) { } static inline void ioapic_insert_resources(void) { }
#define gsi_top (NR_IRQS_LEGACY) #define gsi_top (NR_IRQS_LEGACY)
static inline int mp_find_ioapic(u32 gsi) { return 0; } static inline int mp_find_ioapic(u32 gsi) { return 0; }
...@@ -212,6 +219,10 @@ static inline int restore_ioapic_entries(void) ...@@ -212,6 +219,10 @@ static inline int restore_ioapic_entries(void)
static inline void mp_save_irq(struct mpc_intsrc *m) { }; static inline void mp_save_irq(struct mpc_intsrc *m) { };
static inline void disable_ioapic_support(void) { } static inline void disable_ioapic_support(void) { }
#define native_io_apic_init_mappings NULL
#define native_io_apic_read NULL
#define native_io_apic_write NULL
#define native_io_apic_modify NULL
#endif #endif
#endif /* _ASM_X86_IO_APIC_H */ #endif /* _ASM_X86_IO_APIC_H */
...@@ -188,11 +188,18 @@ struct x86_msi_ops { ...@@ -188,11 +188,18 @@ struct x86_msi_ops {
void (*restore_msi_irqs)(struct pci_dev *dev, int irq); void (*restore_msi_irqs)(struct pci_dev *dev, int irq);
}; };
struct x86_io_apic_ops {
void (*init) (void);
unsigned int (*read) (unsigned int apic, unsigned int reg);
void (*write) (unsigned int apic, unsigned int reg, unsigned int value);
void (*modify)(unsigned int apic, unsigned int reg, unsigned int value);
};
extern struct x86_init_ops x86_init; extern struct x86_init_ops x86_init;
extern struct x86_cpuinit_ops x86_cpuinit; extern struct x86_cpuinit_ops x86_cpuinit;
extern struct x86_platform_ops x86_platform; extern struct x86_platform_ops x86_platform;
extern struct x86_msi_ops x86_msi; extern struct x86_msi_ops x86_msi;
extern struct x86_io_apic_ops x86_io_apic_ops;
extern void x86_init_noop(void); extern void x86_init_noop(void);
extern void x86_init_uint_noop(unsigned int unused); extern void x86_init_uint_noop(unsigned int unused);
......
...@@ -1326,11 +1326,13 @@ void __cpuinit setup_local_APIC(void) ...@@ -1326,11 +1326,13 @@ void __cpuinit setup_local_APIC(void)
acked); acked);
break; break;
} }
if (cpu_has_tsc) { if (queued) {
rdtscll(ntsc); if (cpu_has_tsc) {
max_loops = (cpu_khz << 10) - (ntsc - tsc); rdtscll(ntsc);
} else max_loops = (cpu_khz << 10) - (ntsc - tsc);
max_loops--; } else
max_loops--;
}
} while (queued && max_loops > 0); } while (queued && max_loops > 0);
WARN_ON(max_loops <= 0); WARN_ON(max_loops <= 0);
......
...@@ -227,6 +227,7 @@ static struct apic apic_flat = { ...@@ -227,6 +227,7 @@ static struct apic apic_flat = {
.read = native_apic_mem_read, .read = native_apic_mem_read,
.write = native_apic_mem_write, .write = native_apic_mem_write,
.eoi_write = native_apic_mem_write,
.icr_read = native_apic_icr_read, .icr_read = native_apic_icr_read,
.icr_write = native_apic_icr_write, .icr_write = native_apic_icr_write,
.wait_icr_idle = native_apic_wait_icr_idle, .wait_icr_idle = native_apic_wait_icr_idle,
...@@ -386,6 +387,7 @@ static struct apic apic_physflat = { ...@@ -386,6 +387,7 @@ static struct apic apic_physflat = {
.read = native_apic_mem_read, .read = native_apic_mem_read,
.write = native_apic_mem_write, .write = native_apic_mem_write,
.eoi_write = native_apic_mem_write,
.icr_read = native_apic_icr_read, .icr_read = native_apic_icr_read,
.icr_write = native_apic_icr_write, .icr_write = native_apic_icr_write,
.wait_icr_idle = native_apic_wait_icr_idle, .wait_icr_idle = native_apic_wait_icr_idle,
......
...@@ -181,6 +181,7 @@ struct apic apic_noop = { ...@@ -181,6 +181,7 @@ struct apic apic_noop = {
.read = noop_apic_read, .read = noop_apic_read,
.write = noop_apic_write, .write = noop_apic_write,
.eoi_write = noop_apic_write,
.icr_read = noop_apic_icr_read, .icr_read = noop_apic_icr_read,
.icr_write = noop_apic_icr_write, .icr_write = noop_apic_icr_write,
.wait_icr_idle = noop_apic_wait_icr_idle, .wait_icr_idle = noop_apic_wait_icr_idle,
......
...@@ -295,6 +295,7 @@ static struct apic apic_numachip __refconst = { ...@@ -295,6 +295,7 @@ static struct apic apic_numachip __refconst = {
.read = native_apic_mem_read, .read = native_apic_mem_read,
.write = native_apic_mem_write, .write = native_apic_mem_write,
.eoi_write = native_apic_mem_write,
.icr_read = native_apic_icr_read, .icr_read = native_apic_icr_read,
.icr_write = native_apic_icr_write, .icr_write = native_apic_icr_write,
.wait_icr_idle = native_apic_wait_icr_idle, .wait_icr_idle = native_apic_wait_icr_idle,
......
...@@ -248,6 +248,7 @@ static struct apic apic_bigsmp = { ...@@ -248,6 +248,7 @@ static struct apic apic_bigsmp = {
.read = native_apic_mem_read, .read = native_apic_mem_read,
.write = native_apic_mem_write, .write = native_apic_mem_write,
.eoi_write = native_apic_mem_write,
.icr_read = native_apic_icr_read, .icr_read = native_apic_icr_read,
.icr_write = native_apic_icr_write, .icr_write = native_apic_icr_write,
.wait_icr_idle = native_apic_wait_icr_idle, .wait_icr_idle = native_apic_wait_icr_idle,
......
...@@ -678,6 +678,7 @@ static struct apic __refdata apic_es7000_cluster = { ...@@ -678,6 +678,7 @@ static struct apic __refdata apic_es7000_cluster = {
.read = native_apic_mem_read, .read = native_apic_mem_read,
.write = native_apic_mem_write, .write = native_apic_mem_write,
.eoi_write = native_apic_mem_write,
.icr_read = native_apic_icr_read, .icr_read = native_apic_icr_read,
.icr_write = native_apic_icr_write, .icr_write = native_apic_icr_write,
.wait_icr_idle = native_apic_wait_icr_idle, .wait_icr_idle = native_apic_wait_icr_idle,
...@@ -742,6 +743,7 @@ static struct apic __refdata apic_es7000 = { ...@@ -742,6 +743,7 @@ static struct apic __refdata apic_es7000 = {
.read = native_apic_mem_read, .read = native_apic_mem_read,
.write = native_apic_mem_write, .write = native_apic_mem_write,
.eoi_write = native_apic_mem_write,
.icr_read = native_apic_icr_read, .icr_read = native_apic_icr_read,
.icr_write = native_apic_icr_write, .icr_write = native_apic_icr_write,
.wait_icr_idle = native_apic_wait_icr_idle, .wait_icr_idle = native_apic_wait_icr_idle,
......
...@@ -68,24 +68,6 @@ ...@@ -68,24 +68,6 @@
#define for_each_irq_pin(entry, head) \ #define for_each_irq_pin(entry, head) \
for (entry = head; entry; entry = entry->next) for (entry = head; entry; entry = entry->next)
static void __init __ioapic_init_mappings(void);
static unsigned int __io_apic_read (unsigned int apic, unsigned int reg);
static void __io_apic_write (unsigned int apic, unsigned int reg, unsigned int val);
static void __io_apic_modify(unsigned int apic, unsigned int reg, unsigned int val);
static struct io_apic_ops io_apic_ops = {
.init = __ioapic_init_mappings,
.read = __io_apic_read,
.write = __io_apic_write,
.modify = __io_apic_modify,
};
void __init set_io_apic_ops(const struct io_apic_ops *ops)
{
io_apic_ops = *ops;
}
#ifdef CONFIG_IRQ_REMAP #ifdef CONFIG_IRQ_REMAP
static void irq_remap_modify_chip_defaults(struct irq_chip *chip); static void irq_remap_modify_chip_defaults(struct irq_chip *chip);
static inline bool irq_remapped(struct irq_cfg *cfg) static inline bool irq_remapped(struct irq_cfg *cfg)
...@@ -329,21 +311,6 @@ static void free_irq_at(unsigned int at, struct irq_cfg *cfg) ...@@ -329,21 +311,6 @@ static void free_irq_at(unsigned int at, struct irq_cfg *cfg)
irq_free_desc(at); irq_free_desc(at);
} }
static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
{
return io_apic_ops.read(apic, reg);
}
static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
{
io_apic_ops.write(apic, reg, value);
}
static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
{
io_apic_ops.modify(apic, reg, value);
}
struct io_apic { struct io_apic {
unsigned int index; unsigned int index;
...@@ -365,14 +332,14 @@ static inline void io_apic_eoi(unsigned int apic, unsigned int vector) ...@@ -365,14 +332,14 @@ static inline void io_apic_eoi(unsigned int apic, unsigned int vector)
writel(vector, &io_apic->eoi); writel(vector, &io_apic->eoi);
} }
static unsigned int __io_apic_read(unsigned int apic, unsigned int reg) unsigned int native_io_apic_read(unsigned int apic, unsigned int reg)
{ {
struct io_apic __iomem *io_apic = io_apic_base(apic); struct io_apic __iomem *io_apic = io_apic_base(apic);
writel(reg, &io_apic->index); writel(reg, &io_apic->index);
return readl(&io_apic->data); return readl(&io_apic->data);
} }
static void __io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) void native_io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
{ {
struct io_apic __iomem *io_apic = io_apic_base(apic); struct io_apic __iomem *io_apic = io_apic_base(apic);
...@@ -386,7 +353,7 @@ static void __io_apic_write(unsigned int apic, unsigned int reg, unsigned int va ...@@ -386,7 +353,7 @@ static void __io_apic_write(unsigned int apic, unsigned int reg, unsigned int va
* *
* Older SiS APIC requires we rewrite the index register * Older SiS APIC requires we rewrite the index register
*/ */
static void __io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) void native_io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
{ {
struct io_apic __iomem *io_apic = io_apic_base(apic); struct io_apic __iomem *io_apic = io_apic_base(apic);
...@@ -395,29 +362,6 @@ static void __io_apic_modify(unsigned int apic, unsigned int reg, unsigned int v ...@@ -395,29 +362,6 @@ static void __io_apic_modify(unsigned int apic, unsigned int reg, unsigned int v
writel(value, &io_apic->data); writel(value, &io_apic->data);
} }
static bool io_apic_level_ack_pending(struct irq_cfg *cfg)
{
struct irq_pin_list *entry;
unsigned long flags;
raw_spin_lock_irqsave(&ioapic_lock, flags);
for_each_irq_pin(entry, cfg->irq_2_pin) {
unsigned int reg;
int pin;
pin = entry->pin;
reg = io_apic_read(entry->apic, 0x10 + pin*2);
/* Is the remote IRR bit set? */
if (reg & IO_APIC_REDIR_REMOTE_IRR) {
raw_spin_unlock_irqrestore(&ioapic_lock, flags);
return true;
}
}
raw_spin_unlock_irqrestore(&ioapic_lock, flags);
return false;
}
union entry_union { union entry_union {
struct { u32 w1, w2; }; struct { u32 w1, w2; };
struct IO_APIC_route_entry entry; struct IO_APIC_route_entry entry;
...@@ -2439,6 +2383,29 @@ static void ack_apic_edge(struct irq_data *data) ...@@ -2439,6 +2383,29 @@ static void ack_apic_edge(struct irq_data *data)
atomic_t irq_mis_count; atomic_t irq_mis_count;
#ifdef CONFIG_GENERIC_PENDING_IRQ #ifdef CONFIG_GENERIC_PENDING_IRQ
static bool io_apic_level_ack_pending(struct irq_cfg *cfg)
{
struct irq_pin_list *entry;
unsigned long flags;
raw_spin_lock_irqsave(&ioapic_lock, flags);
for_each_irq_pin(entry, cfg->irq_2_pin) {
unsigned int reg;
int pin;
pin = entry->pin;
reg = io_apic_read(entry->apic, 0x10 + pin*2);
/* Is the remote IRR bit set? */
if (reg & IO_APIC_REDIR_REMOTE_IRR) {
raw_spin_unlock_irqrestore(&ioapic_lock, flags);
return true;
}
}
raw_spin_unlock_irqrestore(&ioapic_lock, flags);
return false;
}
static inline bool ioapic_irqd_mask(struct irq_data *data, struct irq_cfg *cfg) static inline bool ioapic_irqd_mask(struct irq_data *data, struct irq_cfg *cfg)
{ {
/* If we are moving the irq we need to mask it */ /* If we are moving the irq we need to mask it */
...@@ -3756,12 +3723,7 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics) ...@@ -3756,12 +3723,7 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics)
return res; return res;
} }
void __init ioapic_and_gsi_init(void) void __init native_io_apic_init_mappings(void)
{
io_apic_ops.init();
}
static void __init __ioapic_init_mappings(void)
{ {
unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
struct resource *ioapic_res; struct resource *ioapic_res;
......
...@@ -530,6 +530,7 @@ static struct apic __refdata apic_numaq = { ...@@ -530,6 +530,7 @@ static struct apic __refdata apic_numaq = {
.read = native_apic_mem_read, .read = native_apic_mem_read,
.write = native_apic_mem_write, .write = native_apic_mem_write,
.eoi_write = native_apic_mem_write,
.icr_read = native_apic_icr_read, .icr_read = native_apic_icr_read,
.icr_write = native_apic_icr_write, .icr_write = native_apic_icr_write,
.wait_icr_idle = native_apic_wait_icr_idle, .wait_icr_idle = native_apic_wait_icr_idle,
......
...@@ -142,6 +142,7 @@ static struct apic apic_default = { ...@@ -142,6 +142,7 @@ static struct apic apic_default = {
.read = native_apic_mem_read, .read = native_apic_mem_read,
.write = native_apic_mem_write, .write = native_apic_mem_write,
.eoi_write = native_apic_mem_write,
.icr_read = native_apic_icr_read, .icr_read = native_apic_icr_read,
.icr_write = native_apic_icr_write, .icr_write = native_apic_icr_write,
.wait_icr_idle = native_apic_wait_icr_idle, .wait_icr_idle = native_apic_wait_icr_idle,
......
...@@ -546,6 +546,7 @@ static struct apic apic_summit = { ...@@ -546,6 +546,7 @@ static struct apic apic_summit = {
.read = native_apic_mem_read, .read = native_apic_mem_read,
.write = native_apic_mem_write, .write = native_apic_mem_write,
.eoi_write = native_apic_mem_write,
.icr_read = native_apic_icr_read, .icr_read = native_apic_icr_read,
.icr_write = native_apic_icr_write, .icr_write = native_apic_icr_write,
.wait_icr_idle = native_apic_wait_icr_idle, .wait_icr_idle = native_apic_wait_icr_idle,
......
...@@ -260,6 +260,7 @@ static struct apic apic_x2apic_cluster = { ...@@ -260,6 +260,7 @@ static struct apic apic_x2apic_cluster = {
.read = native_apic_msr_read, .read = native_apic_msr_read,
.write = native_apic_msr_write, .write = native_apic_msr_write,
.eoi_write = native_apic_msr_eoi_write,
.icr_read = native_x2apic_icr_read, .icr_read = native_x2apic_icr_read,
.icr_write = native_x2apic_icr_write, .icr_write = native_x2apic_icr_write,
.wait_icr_idle = native_x2apic_wait_icr_idle, .wait_icr_idle = native_x2apic_wait_icr_idle,
......
...@@ -172,6 +172,7 @@ static struct apic apic_x2apic_phys = { ...@@ -172,6 +172,7 @@ static struct apic apic_x2apic_phys = {
.read = native_apic_msr_read, .read = native_apic_msr_read,
.write = native_apic_msr_write, .write = native_apic_msr_write,
.eoi_write = native_apic_msr_eoi_write,
.icr_read = native_x2apic_icr_read, .icr_read = native_x2apic_icr_read,
.icr_write = native_x2apic_icr_write, .icr_write = native_x2apic_icr_write,
.wait_icr_idle = native_x2apic_wait_icr_idle, .wait_icr_idle = native_x2apic_wait_icr_idle,
......
...@@ -404,6 +404,7 @@ static struct apic __refdata apic_x2apic_uv_x = { ...@@ -404,6 +404,7 @@ static struct apic __refdata apic_x2apic_uv_x = {
.read = native_apic_msr_read, .read = native_apic_msr_read,
.write = native_apic_msr_write, .write = native_apic_msr_write,
.eoi_write = native_apic_msr_eoi_write,
.icr_read = native_x2apic_icr_read, .icr_read = native_x2apic_icr_read,
.icr_write = native_x2apic_icr_write, .icr_write = native_x2apic_icr_write,
.wait_icr_idle = native_x2apic_wait_icr_idle, .wait_icr_idle = native_x2apic_wait_icr_idle,
......
...@@ -1012,7 +1012,8 @@ void __init setup_arch(char **cmdline_p) ...@@ -1012,7 +1012,8 @@ void __init setup_arch(char **cmdline_p)
init_cpu_to_node(); init_cpu_to_node();
init_apic_mappings(); init_apic_mappings();
ioapic_and_gsi_init(); if (x86_io_apic_ops.init)
x86_io_apic_ops.init();
kvm_guest_init(); kvm_guest_init();
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <asm/e820.h> #include <asm/e820.h>
#include <asm/time.h> #include <asm/time.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/io_apic.h>
#include <asm/pat.h> #include <asm/pat.h>
#include <asm/tsc.h> #include <asm/tsc.h>
#include <asm/iommu.h> #include <asm/iommu.h>
...@@ -119,3 +120,10 @@ struct x86_msi_ops x86_msi = { ...@@ -119,3 +120,10 @@ struct x86_msi_ops x86_msi = {
.teardown_msi_irqs = default_teardown_msi_irqs, .teardown_msi_irqs = default_teardown_msi_irqs,
.restore_msi_irqs = default_restore_msi_irqs, .restore_msi_irqs = default_restore_msi_irqs,
}; };
struct x86_io_apic_ops x86_io_apic_ops = {
.init = native_io_apic_init_mappings,
.read = native_io_apic_read,
.write = native_io_apic_write,
.modify = native_io_apic_modify,
};
...@@ -445,7 +445,7 @@ static void ack_cobalt_irq(struct irq_data *data) ...@@ -445,7 +445,7 @@ static void ack_cobalt_irq(struct irq_data *data)
spin_lock_irqsave(&cobalt_lock, flags); spin_lock_irqsave(&cobalt_lock, flags);
disable_cobalt_irq(data); disable_cobalt_irq(data);
apic_write(APIC_EOI, APIC_EIO_ACK); apic_write(APIC_EOI, APIC_EOI_ACK);
spin_unlock_irqrestore(&cobalt_lock, flags); spin_unlock_irqrestore(&cobalt_lock, flags);
} }
......
...@@ -20,5 +20,5 @@ obj-$(CONFIG_EVENT_TRACING) += trace.o ...@@ -20,5 +20,5 @@ obj-$(CONFIG_EVENT_TRACING) += trace.o
obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o
obj-$(CONFIG_XEN_DOM0) += vga.o obj-$(CONFIG_XEN_DOM0) += apic.o vga.o
obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o
#include <linux/init.h>
#include <asm/x86_init.h>
#include <asm/apic.h>
#include <asm/xen/hypercall.h>
#include <xen/xen.h>
#include <xen/interface/physdev.h>
unsigned int xen_io_apic_read(unsigned apic, unsigned reg)
{
struct physdev_apic apic_op;
int ret;
apic_op.apic_physbase = mpc_ioapic_addr(apic);
apic_op.reg = reg;
ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
if (!ret)
return apic_op.value;
/* fallback to return an emulated IO_APIC values */
if (reg == 0x1)
return 0x00170020;
else if (reg == 0x0)
return apic << 24;
return 0xfd;
}
void __init xen_init_apic(void)
{
x86_io_apic_ops.read = xen_io_apic_read;
}
...@@ -1396,6 +1396,8 @@ asmlinkage void __init xen_start_kernel(void) ...@@ -1396,6 +1396,8 @@ asmlinkage void __init xen_start_kernel(void)
xen_start_info->console.domU.mfn = 0; xen_start_info->console.domU.mfn = 0;
xen_start_info->console.domU.evtchn = 0; xen_start_info->console.domU.evtchn = 0;
xen_init_apic();
/* Make sure ACS will be enabled */ /* Make sure ACS will be enabled */
pci_request_acs(); pci_request_acs();
} }
......
...@@ -1864,7 +1864,6 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd, ...@@ -1864,7 +1864,6 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd,
#endif /* CONFIG_X86_64 */ #endif /* CONFIG_X86_64 */
static unsigned char dummy_mapping[PAGE_SIZE] __page_aligned_bss; static unsigned char dummy_mapping[PAGE_SIZE] __page_aligned_bss;
static unsigned char fake_ioapic_mapping[PAGE_SIZE] __page_aligned_bss;
static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot) static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
{ {
...@@ -1905,7 +1904,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot) ...@@ -1905,7 +1904,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
* We just don't map the IO APIC - all access is via * We just don't map the IO APIC - all access is via
* hypercalls. Keep the address in the pte for reference. * hypercalls. Keep the address in the pte for reference.
*/ */
pte = pfn_pte(PFN_DOWN(__pa(fake_ioapic_mapping)), PAGE_KERNEL); pte = pfn_pte(PFN_DOWN(__pa(dummy_mapping)), PAGE_KERNEL);
break; break;
#endif #endif
...@@ -2070,7 +2069,6 @@ void __init xen_init_mmu_ops(void) ...@@ -2070,7 +2069,6 @@ void __init xen_init_mmu_ops(void)
pv_mmu_ops = xen_mmu_ops; pv_mmu_ops = xen_mmu_ops;
memset(dummy_mapping, 0xff, PAGE_SIZE); memset(dummy_mapping, 0xff, PAGE_SIZE);
memset(fake_ioapic_mapping, 0xfd, PAGE_SIZE);
} }
/* Protected by xen_reservation_lock. */ /* Protected by xen_reservation_lock. */
......
...@@ -92,11 +92,15 @@ struct dom0_vga_console_info; ...@@ -92,11 +92,15 @@ struct dom0_vga_console_info;
#ifdef CONFIG_XEN_DOM0 #ifdef CONFIG_XEN_DOM0
void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size); void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size);
void __init xen_init_apic(void);
#else #else
static inline void __init xen_init_vga(const struct dom0_vga_console_info *info, static inline void __init xen_init_vga(const struct dom0_vga_console_info *info,
size_t size) size_t size)
{ {
} }
static inline void __init xen_init_apic(void)
{
}
#endif #endif
/* Declare an asm function, along with symbols needed to make it /* Declare an asm function, along with symbols needed to make it
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment