Implement xen apic_ops to fix early crash in Xen Dom0 (rhbz 804347)
This commit is contained in:
parent
f1d2f5da9e
commit
46ad899861
19
kernel.spec
19
kernel.spec
@ -54,7 +54,7 @@ Summary: The Linux kernel
|
||||
# For non-released -rc kernels, this will be appended after the rcX and
|
||||
# gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
|
||||
#
|
||||
%global baserelease 5
|
||||
%global baserelease 6
|
||||
%global fedora_build %{baserelease}
|
||||
|
||||
# base_sublevel is the kernel version we're starting with and patching
|
||||
@ -770,6 +770,13 @@ Patch21305: mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch
|
||||
#rhbz 804957 CVE-2012-1568
|
||||
Patch21306: shlib_base_randomize.patch
|
||||
|
||||
Patch21350: x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch
|
||||
|
||||
#rhbz 804347
|
||||
Patch21351: x86-add-io_apic_ops-to-allow-interception.patch
|
||||
Patch21352: x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch
|
||||
Patch21353: xen-x86-Implement-x86_apic_ops.patch
|
||||
|
||||
Patch21400: unhandled-irqs-switch-to-polling.patch
|
||||
|
||||
Patch22000: weird-root-dentry-name-debug.patch
|
||||
@ -1489,6 +1496,13 @@ ApplyPatch unhandled-irqs-switch-to-polling.patch
|
||||
|
||||
ApplyPatch weird-root-dentry-name-debug.patch
|
||||
|
||||
ApplyPatch x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch
|
||||
|
||||
#rhbz 804347
|
||||
ApplyPatch x86-add-io_apic_ops-to-allow-interception.patch
|
||||
ApplyPatch x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch
|
||||
ApplyPatch xen-x86-Implement-x86_apic_ops.patch
|
||||
|
||||
#rhbz 803809 CVE-2012-1179
|
||||
ApplyPatch mm-thp-fix-pmd_bad-triggering.patch
|
||||
|
||||
@ -2334,6 +2348,9 @@ fi
|
||||
# '-' | |
|
||||
# '-'
|
||||
%changelog
|
||||
* Tue Mar 27 2012 Josh Boyer <jwboyer@redhat.com>
|
||||
- Implement xen apic_ops to fix early crash in Xen Dom0 (rhbz 804347)
|
||||
|
||||
* Fri Mar 23 2012 Dave Jones <davej@redhat.com> 3.3.0-5
|
||||
- Apply patches that should solve the bluetooth use-after-free oopses. (rhbz 806033)
|
||||
|
||||
|
135
x86-add-io_apic_ops-to-allow-interception.patch
Normal file
135
x86-add-io_apic_ops-to-allow-interception.patch
Normal file
@ -0,0 +1,135 @@
|
||||
From: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
|
||||
|
||||
Xen dom0 needs to paravirtualize IO operations to the IO APIC, so add
|
||||
a io_apic_ops for it to intercept. Do this as ops structure because
|
||||
there's at least some chance that another paravirtualized environment
|
||||
may want to intercept these.
|
||||
|
||||
[ Impact: indirect IO APIC access via io_apic_ops ]
|
||||
|
||||
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
|
||||
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
Acked-by: Suresh Siddha <suresh.b.siddha@intel.com>
|
||||
---
|
||||
arch/x86/include/asm/io_apic.h | 9 +++++++
|
||||
arch/x86/kernel/apic/io_apic.c | 50 +++++++++++++++++++++++++++++++++++++--
|
||||
2 files changed, 56 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
|
||||
index 690d1cc..190d8c2 100644
|
||||
--- a/arch/x86/include/asm/io_apic.h
|
||||
+++ b/arch/x86/include/asm/io_apic.h
|
||||
@@ -21,6 +21,15 @@
|
||||
#define IO_APIC_REDIR_LEVEL_TRIGGER (1 << 15)
|
||||
#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:
|
||||
*/
|
||||
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
|
||||
index fb07275..bf120234 100644
|
||||
--- a/arch/x86/kernel/apic/io_apic.c
|
||||
+++ b/arch/x86/kernel/apic/io_apic.c
|
||||
@@ -67,6 +67,25 @@
|
||||
#define for_each_irq_pin(entry, head) \
|
||||
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;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Is the SiS APIC rmw bug present ?
|
||||
* -1 = don't know, 0 = no, 1 = yes
|
||||
@@ -294,6 +313,24 @@ static void free_irq_at(unsigned int at, struct irq_cfg *cfg)
|
||||
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 {
|
||||
unsigned int index;
|
||||
unsigned int unused[3];
|
||||
@@ -314,14 +351,15 @@ static inline void io_apic_eoi(unsigned int apic, unsigned int vector)
|
||||
writel(vector, &io_apic->eoi);
|
||||
}
|
||||
|
||||
-static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
|
||||
+static unsigned int __io_apic_read(unsigned int apic, unsigned int reg)
|
||||
{
|
||||
struct io_apic __iomem *io_apic = io_apic_base(apic);
|
||||
writel(reg, &io_apic->index);
|
||||
return readl(&io_apic->data);
|
||||
}
|
||||
|
||||
-static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
|
||||
+static void __io_apic_write(unsigned int apic, unsigned int reg,
|
||||
+ unsigned int value)
|
||||
{
|
||||
struct io_apic __iomem *io_apic = io_apic_base(apic);
|
||||
writel(reg, &io_apic->index);
|
||||
@@ -334,7 +372,8 @@ static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned i
|
||||
*
|
||||
* Older SiS APIC requires we rewrite the index register
|
||||
*/
|
||||
-static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
|
||||
+static void __io_apic_modify(unsigned int apic, unsigned int reg,
|
||||
+ unsigned int value)
|
||||
{
|
||||
struct io_apic __iomem *io_apic = io_apic_base(apic);
|
||||
|
||||
@@ -3873,6 +3912,11 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics)
|
||||
|
||||
void __init ioapic_and_gsi_init(void)
|
||||
{
|
||||
+ io_apic_ops.init();
|
||||
+}
|
||||
+
|
||||
+static void __init __ioapic_init_mappings(void)
|
||||
+{
|
||||
unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
|
||||
struct resource *ioapic_res;
|
||||
int i;
|
||||
--
|
||||
1.7.7.5
|
||||
|
258
x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch
Normal file
258
x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch
Normal file
@ -0,0 +1,258 @@
|
||||
. which makes the code fit within the rest of the x86_ops functions.
|
||||
|
||||
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
[v1: Changed x86_apic -> x86_ioapic per Yinghai Lu <yinghai@kernel.org> suggestion]
|
||||
Acked-by: Suresh Siddha <suresh.b.siddha@intel.com>
|
||||
---
|
||||
arch/x86/include/asm/io_apic.h | 40 +++++++++++++++++++++--------
|
||||
arch/x86/include/asm/x86_init.h | 8 ++++++
|
||||
arch/x86/kernel/apic/io_apic.c | 54 ++++----------------------------------
|
||||
arch/x86/kernel/setup.c | 2 +-
|
||||
arch/x86/kernel/x86_init.c | 8 ++++++
|
||||
5 files changed, 52 insertions(+), 60 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
|
||||
index 190d8c2..ba1b11a 100644
|
||||
--- a/arch/x86/include/asm/io_apic.h
|
||||
+++ b/arch/x86/include/asm/io_apic.h
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <asm/mpspec.h>
|
||||
#include <asm/apicdef.h>
|
||||
#include <asm/irq_vectors.h>
|
||||
+#include <asm/x86_init.h>
|
||||
|
||||
/*
|
||||
* Intel IO-APIC support for SMP and UP systems.
|
||||
@@ -21,15 +22,6 @@
|
||||
#define IO_APIC_REDIR_LEVEL_TRIGGER (1 << 15)
|
||||
#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:
|
||||
*/
|
||||
@@ -156,7 +148,6 @@ struct io_apic_irq_attr;
|
||||
extern int io_apic_set_pci_routing(struct device *dev, int irq,
|
||||
struct io_apic_irq_attr *irq_attr);
|
||||
void setup_IO_APIC_irq_extra(u32 gsi);
|
||||
-extern void ioapic_and_gsi_init(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);
|
||||
@@ -185,12 +176,35 @@ extern void mp_save_irq(struct mpc_intsrc *m);
|
||||
|
||||
extern void disable_ioapic_support(void);
|
||||
|
||||
+
|
||||
+void __init native_ioapic_init_mappings(void);
|
||||
+unsigned int native_ioapic_read(unsigned int apic, unsigned int reg);
|
||||
+void native_ioapic_write(unsigned int apic, unsigned int reg,
|
||||
+ unsigned int val);
|
||||
+void native_ioapic_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_ioapic.read(apic, reg);
|
||||
+}
|
||||
+
|
||||
+static inline void io_apic_write(unsigned int apic, unsigned int reg,
|
||||
+ unsigned int value)
|
||||
+{
|
||||
+ x86_ioapic.write(apic, reg, value);
|
||||
+}
|
||||
+
|
||||
+static inline void io_apic_modify(unsigned int apic, unsigned int reg,
|
||||
+ unsigned int value)
|
||||
+{
|
||||
+ x86_ioapic.modify(apic, reg, value);
|
||||
+}
|
||||
#else /* !CONFIG_X86_IO_APIC */
|
||||
|
||||
#define io_apic_assign_pci_irqs 0
|
||||
#define setup_ioapic_ids_from_mpc x86_init_noop
|
||||
static const int timer_through_8259 = 0;
|
||||
-static inline void ioapic_and_gsi_init(void) { }
|
||||
static inline void ioapic_insert_resources(void) { }
|
||||
#define gsi_top (NR_IRQS_LEGACY)
|
||||
static inline int mp_find_ioapic(u32 gsi) { return 0; }
|
||||
@@ -212,6 +226,10 @@ static inline int restore_ioapic_entries(void)
|
||||
|
||||
static inline void mp_save_irq(struct mpc_intsrc *m) { };
|
||||
static inline void disable_ioapic_support(void) { }
|
||||
+#define native_ioapic_init_mappings NULL
|
||||
+#define native_ioapic_read NULL
|
||||
+#define native_ioapic_write NULL
|
||||
+#define native_ioapic_modify NULL
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_X86_IO_APIC_H */
|
||||
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
|
||||
index 517d476..a3730cc 100644
|
||||
--- a/arch/x86/include/asm/x86_init.h
|
||||
+++ b/arch/x86/include/asm/x86_init.h
|
||||
@@ -182,10 +182,18 @@ struct x86_msi_ops {
|
||||
void (*restore_msi_irqs)(struct pci_dev *dev, int irq);
|
||||
};
|
||||
|
||||
+struct x86_ioapic_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_cpuinit_ops x86_cpuinit;
|
||||
extern struct x86_platform_ops x86_platform;
|
||||
extern struct x86_msi_ops x86_msi;
|
||||
+extern struct x86_ioapic_ops x86_ioapic;
|
||||
|
||||
extern void x86_init_noop(void);
|
||||
extern void x86_init_uint_noop(unsigned int unused);
|
||||
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
|
||||
index bf120234..9a15d4b 100644
|
||||
--- a/arch/x86/kernel/apic/io_apic.c
|
||||
+++ b/arch/x86/kernel/apic/io_apic.c
|
||||
@@ -67,25 +67,6 @@
|
||||
#define for_each_irq_pin(entry, head) \
|
||||
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;
|
||||
-}
|
||||
-
|
||||
/*
|
||||
* Is the SiS APIC rmw bug present ?
|
||||
* -1 = don't know, 0 = no, 1 = yes
|
||||
@@ -313,24 +294,6 @@ static void free_irq_at(unsigned int at, struct irq_cfg *cfg)
|
||||
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 {
|
||||
unsigned int index;
|
||||
unsigned int unused[3];
|
||||
@@ -351,15 +314,15 @@ static inline void io_apic_eoi(unsigned int apic, unsigned int vector)
|
||||
writel(vector, &io_apic->eoi);
|
||||
}
|
||||
|
||||
-static unsigned int __io_apic_read(unsigned int apic, unsigned int reg)
|
||||
+unsigned int native_ioapic_read(unsigned int apic, unsigned int reg)
|
||||
{
|
||||
struct io_apic __iomem *io_apic = io_apic_base(apic);
|
||||
writel(reg, &io_apic->index);
|
||||
return readl(&io_apic->data);
|
||||
}
|
||||
|
||||
-static void __io_apic_write(unsigned int apic, unsigned int reg,
|
||||
- unsigned int value)
|
||||
+void native_ioapic_write(unsigned int apic, unsigned int reg,
|
||||
+ unsigned int value)
|
||||
{
|
||||
struct io_apic __iomem *io_apic = io_apic_base(apic);
|
||||
writel(reg, &io_apic->index);
|
||||
@@ -372,8 +335,8 @@ static void __io_apic_write(unsigned int apic, unsigned int reg,
|
||||
*
|
||||
* 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_ioapic_modify(unsigned int apic, unsigned int reg,
|
||||
+ unsigned int value)
|
||||
{
|
||||
struct io_apic __iomem *io_apic = io_apic_base(apic);
|
||||
|
||||
@@ -3910,12 +3873,7 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics)
|
||||
return res;
|
||||
}
|
||||
|
||||
-void __init ioapic_and_gsi_init(void)
|
||||
-{
|
||||
- io_apic_ops.init();
|
||||
-}
|
||||
-
|
||||
-static void __init __ioapic_init_mappings(void)
|
||||
+void __init native_ioapic_init_mappings(void)
|
||||
{
|
||||
unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
|
||||
struct resource *ioapic_res;
|
||||
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
|
||||
index d7d5099..7eaef1a 100644
|
||||
--- a/arch/x86/kernel/setup.c
|
||||
+++ b/arch/x86/kernel/setup.c
|
||||
@@ -1016,7 +1016,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
init_cpu_to_node();
|
||||
|
||||
init_apic_mappings();
|
||||
- ioapic_and_gsi_init();
|
||||
+ x86_ioapic.init();
|
||||
|
||||
kvm_guest_init();
|
||||
|
||||
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
|
||||
index 947a06c..df870d3 100644
|
||||
--- a/arch/x86/kernel/x86_init.c
|
||||
+++ b/arch/x86/kernel/x86_init.c
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <asm/e820.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/irq.h>
|
||||
+#include <asm/io_apic.h>
|
||||
#include <asm/pat.h>
|
||||
#include <asm/tsc.h>
|
||||
#include <asm/iommu.h>
|
||||
@@ -117,3 +118,10 @@ struct x86_msi_ops x86_msi = {
|
||||
.teardown_msi_irqs = default_teardown_msi_irqs,
|
||||
.restore_msi_irqs = default_restore_msi_irqs,
|
||||
};
|
||||
+
|
||||
+struct x86_ioapic_ops x86_ioapic = {
|
||||
+ .init = native_ioapic_init_mappings,
|
||||
+ .read = native_ioapic_read,
|
||||
+ .write = native_ioapic_write,
|
||||
+ .modify = native_ioapic_modify,
|
||||
+};
|
||||
--
|
||||
1.7.7.5
|
||||
|
@ -0,0 +1,93 @@
|
||||
On Tue, 2012-01-31 at 09:26 -0500, Josh Boyer wrote:
|
||||
> On Wed, Jan 25, 2012 at 06:15:35PM -0500, Josh Boyer wrote:
|
||||
> > On Wed, Jan 25, 2012 at 02:04:08PM -0800, Suresh Siddha wrote:
|
||||
> > > On Wed, 2012-01-25 at 08:49 -0500, Josh Boyer wrote:
|
||||
> > > > [ 0.000000] IOAPIC[1]: apic_id 2, version 255, address 0xfec28000, GSI 24-279
|
||||
> > >
|
||||
> > > This looks indeed like a bogus entry probably returning all 1's for
|
||||
> > > RTE's etc. Can you please send me a dmesg with "apic=verbose" boot
|
||||
> > > parameter?
|
||||
> >
|
||||
> > Here you go:
|
||||
> >
|
||||
> > https://bugzilla.redhat.com/attachment.cgi?id=557552
|
||||
>
|
||||
> Was this helpful at all? I've been watching lkml for a related patch
|
||||
> in case I was missed on CC but haven't seen anything as of yet.
|
||||
|
||||
Yes, it was helpful. Something like the appended patch should ignore the
|
||||
bogus io-apic entry all together. As I can't test this, can you or the
|
||||
reporter give the appended patch a try and ack please?
|
||||
|
||||
thanks,
|
||||
suresh
|
||||
---
|
||||
|
||||
From: Suresh Siddha <suresh.b.siddha@intel.com>
|
||||
Subject: x86, ioapic: add register checks for bogus io-apic entries
|
||||
|
||||
With the recent changes to clear_IO_APIC_pin() which tries to clear
|
||||
remoteIRR bit explicitly, some of the users started to see
|
||||
"Unable to reset IRR for apic .." messages.
|
||||
|
||||
Close look shows that these are related to bogus IO-APIC entries which
|
||||
return's all 1's for their io-apic registers. And the above mentioned error
|
||||
messages are benign. But kernel should have ignored such io-apic's in the
|
||||
first place.
|
||||
|
||||
Check if register 0, 1, 2 of the listed io-apic are all 1's and ignore
|
||||
such io-apic.
|
||||
|
||||
Reported-by: Álvaro Castillo <midgoon@gmail.com>
|
||||
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
|
||||
---
|
||||
arch/x86/kernel/apic/io_apic.c | 26 ++++++++++++++++++++++++++
|
||||
1 files changed, 26 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
|
||||
index fb07275..953e54d 100644
|
||||
--- a/arch/x86/kernel/apic/io_apic.c
|
||||
+++ b/arch/x86/kernel/apic/io_apic.c
|
||||
@@ -3979,6 +3979,26 @@ static __init int bad_ioapic(unsigned long address)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static __init int bad_ioapic_regs(int idx)
|
||||
+{
|
||||
+ union IO_APIC_reg_00 reg_00;
|
||||
+ union IO_APIC_reg_01 reg_01;
|
||||
+ union IO_APIC_reg_02 reg_02;
|
||||
+
|
||||
+ reg_00.raw = io_apic_read(idx, 0);
|
||||
+ reg_01.raw = io_apic_read(idx, 1);
|
||||
+ reg_02.raw = io_apic_read(idx, 2);
|
||||
+
|
||||
+ if (reg_00.raw == -1 && reg_01.raw == -1 && reg_02.raw == -1) {
|
||||
+ printk(KERN_WARNING
|
||||
+ "I/O APIC 0x%x regs return all ones, skipping!\n",
|
||||
+ mpc_ioapic_addr(idx));
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
|
||||
{
|
||||
int idx = 0;
|
||||
@@ -3995,6 +4015,12 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
|
||||
ioapics[idx].mp_config.apicaddr = address;
|
||||
|
||||
set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
|
||||
+
|
||||
+ if (bad_ioapic_regs(idx)) {
|
||||
+ clear_fixmap(FIX_IO_APIC_BASE_0 + idx);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
ioapics[idx].mp_config.apicid = io_apic_unique_id(id);
|
||||
ioapics[idx].mp_config.apicver = io_apic_get_version(idx);
|
||||
|
||||
|
||||
|
||||
|
85
xen-x86-Implement-x86_apic_ops.patch
Normal file
85
xen-x86-Implement-x86_apic_ops.patch
Normal file
@ -0,0 +1,85 @@
|
||||
Or rather just implement one different function as opposed
|
||||
to the native one : the read function.
|
||||
|
||||
We synthesize the values.
|
||||
|
||||
Acked-by: Suresh Siddha <suresh.b.siddha@intel.com>
|
||||
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
|
||||
---
|
||||
arch/x86/xen/Makefile | 2 +-
|
||||
arch/x86/xen/apic.c | 17 +++++++++++++++++
|
||||
arch/x86/xen/enlighten.c | 2 ++
|
||||
arch/x86/xen/xen-ops.h | 4 ++++
|
||||
4 files changed, 24 insertions(+), 1 deletions(-)
|
||||
create mode 100644 arch/x86/xen/apic.c
|
||||
|
||||
diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
|
||||
index add2c2d..96ab2c0 100644
|
||||
--- a/arch/x86/xen/Makefile
|
||||
+++ b/arch/x86/xen/Makefile
|
||||
@@ -20,5 +20,5 @@ obj-$(CONFIG_EVENT_TRACING) += trace.o
|
||||
obj-$(CONFIG_SMP) += smp.o
|
||||
obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.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
|
||||
diff --git a/arch/x86/xen/apic.c b/arch/x86/xen/apic.c
|
||||
new file mode 100644
|
||||
index 0000000..71ed91c
|
||||
--- /dev/null
|
||||
+++ b/arch/x86/xen/apic.c
|
||||
@@ -0,0 +1,17 @@
|
||||
+#include <linux/init.h>
|
||||
+#include <asm/x86_init.h>
|
||||
+
|
||||
+unsigned int xen_io_apic_read(unsigned apic, unsigned reg)
|
||||
+{
|
||||
+ if (reg == 0x1)
|
||||
+ return 0x00170020;
|
||||
+ else if (reg == 0x0)
|
||||
+ return apic << 24;
|
||||
+
|
||||
+ return 0xff;
|
||||
+}
|
||||
+
|
||||
+void __init xen_init_apic(void)
|
||||
+{
|
||||
+ x86_ioapic.read = xen_io_apic_read;
|
||||
+}
|
||||
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
|
||||
index 0732326..93a03195 100644
|
||||
--- a/arch/x86/xen/enlighten.c
|
||||
+++ b/arch/x86/xen/enlighten.c
|
||||
@@ -1377,6 +1377,8 @@ asmlinkage void __init xen_start_kernel(void)
|
||||
xen_start_info->console.domU.mfn = 0;
|
||||
xen_start_info->console.domU.evtchn = 0;
|
||||
|
||||
+ xen_init_apic();
|
||||
+
|
||||
/* Make sure ACS will be enabled */
|
||||
pci_request_acs();
|
||||
|
||||
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
|
||||
index b095739..45c0c06 100644
|
||||
--- a/arch/x86/xen/xen-ops.h
|
||||
+++ b/arch/x86/xen/xen-ops.h
|
||||
@@ -92,11 +92,15 @@ struct dom0_vga_console_info;
|
||||
|
||||
#ifdef CONFIG_XEN_DOM0
|
||||
void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size);
|
||||
+void __init xen_init_apic(void);
|
||||
#else
|
||||
static inline void __init xen_init_vga(const struct dom0_vga_console_info *info,
|
||||
size_t size)
|
||||
{
|
||||
}
|
||||
+static inline void __init xen_init_apic(void)
|
||||
+{
|
||||
+}
|
||||
#endif
|
||||
|
||||
/* Declare an asm function, along with symbols needed to make it
|
||||
--
|
||||
1.7.7.5
|
||||
|
Loading…
Reference in New Issue
Block a user