diff options
Diffstat (limited to 'arch/x86/kernel/vsmp_64.c')
-rw-r--r-- | arch/x86/kernel/vsmp_64.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/arch/x86/kernel/vsmp_64.c b/arch/x86/kernel/vsmp_64.c index fdf9fba6ba9c..b93ed66c754f 100644 --- a/arch/x86/kernel/vsmp_64.c +++ b/arch/x86/kernel/vsmp_64.c | |||
@@ -8,6 +8,8 @@ | |||
8 | * | 8 | * |
9 | * Ravikiran Thirumalai <kiran@scalemp.com>, | 9 | * Ravikiran Thirumalai <kiran@scalemp.com>, |
10 | * Shai Fultheim <shai@scalemp.com> | 10 | * Shai Fultheim <shai@scalemp.com> |
11 | * Paravirt ops integration: Glauber de Oliveira Costa <gcosta@redhat.com>, | ||
12 | * Ravikiran Thirumalai <kiran@scalemp.com> | ||
11 | */ | 13 | */ |
12 | 14 | ||
13 | #include <linux/init.h> | 15 | #include <linux/init.h> |
@@ -15,6 +17,60 @@ | |||
15 | #include <linux/pci_regs.h> | 17 | #include <linux/pci_regs.h> |
16 | #include <asm/pci-direct.h> | 18 | #include <asm/pci-direct.h> |
17 | #include <asm/io.h> | 19 | #include <asm/io.h> |
20 | #include <asm/paravirt.h> | ||
21 | |||
22 | /* | ||
23 | * Interrupt control on vSMPowered systems: | ||
24 | * ~AC is a shadow of IF. If IF is 'on' AC should be 'off' | ||
25 | * and vice versa. | ||
26 | */ | ||
27 | |||
28 | static unsigned long vsmp_save_fl(void) | ||
29 | { | ||
30 | unsigned long flags = native_save_fl(); | ||
31 | |||
32 | if (!(flags & X86_EFLAGS_IF) || (flags & X86_EFLAGS_AC)) | ||
33 | flags &= ~X86_EFLAGS_IF; | ||
34 | return flags; | ||
35 | } | ||
36 | |||
37 | static void vsmp_restore_fl(unsigned long flags) | ||
38 | { | ||
39 | if (flags & X86_EFLAGS_IF) | ||
40 | flags &= ~X86_EFLAGS_AC; | ||
41 | else | ||
42 | flags |= X86_EFLAGS_AC; | ||
43 | native_restore_fl(flags); | ||
44 | } | ||
45 | |||
46 | static void vsmp_irq_disable(void) | ||
47 | { | ||
48 | unsigned long flags = native_save_fl(); | ||
49 | |||
50 | native_restore_fl((flags & ~X86_EFLAGS_IF) | X86_EFLAGS_AC); | ||
51 | } | ||
52 | |||
53 | static void vsmp_irq_enable(void) | ||
54 | { | ||
55 | unsigned long flags = native_save_fl(); | ||
56 | |||
57 | native_restore_fl((flags | X86_EFLAGS_IF) & (~X86_EFLAGS_AC)); | ||
58 | } | ||
59 | |||
60 | static unsigned __init vsmp_patch(u8 type, u16 clobbers, void *ibuf, | ||
61 | unsigned long addr, unsigned len) | ||
62 | { | ||
63 | switch (type) { | ||
64 | case PARAVIRT_PATCH(pv_irq_ops.irq_enable): | ||
65 | case PARAVIRT_PATCH(pv_irq_ops.irq_disable): | ||
66 | case PARAVIRT_PATCH(pv_irq_ops.save_fl): | ||
67 | case PARAVIRT_PATCH(pv_irq_ops.restore_fl): | ||
68 | return paravirt_patch_default(type, clobbers, ibuf, addr, len); | ||
69 | default: | ||
70 | return native_patch(type, clobbers, ibuf, addr, len); | ||
71 | } | ||
72 | |||
73 | } | ||
18 | 74 | ||
19 | void __init vsmp_init(void) | 75 | void __init vsmp_init(void) |
20 | { | 76 | { |