aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/xen/enlighten.c
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@xensource.com>2007-07-17 21:37:07 -0400
committerJeremy Fitzhardinge <jeremy@goop.org>2007-07-18 11:47:45 -0400
commit6487673b8a858f99a5348e1078b3f5aec700f9e0 (patch)
tree2c96da8fde879561f36678691ef997f3fdb7b3f0 /arch/i386/xen/enlighten.c
parent60223a326fc8fa6e90e2c3fd28ae6de4a311d731 (diff)
xen: Attempt to patch inline versions of common operations
This patchs adds the mechanism to allow us to patch inline versions of common operations. The implementations of the direct-access versions save_fl, restore_fl, irq_enable and irq_disable are now in assembler, and the same code is used for both out of line and inline uses. Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Cc: Chris Wright <chrisw@sous-sol.org> Cc: Keir Fraser <keir@xensource.com>
Diffstat (limited to 'arch/i386/xen/enlighten.c')
-rw-r--r--arch/i386/xen/enlighten.c107
1 files changed, 54 insertions, 53 deletions
diff --git a/arch/i386/xen/enlighten.c b/arch/i386/xen/enlighten.c
index e33fa0990eda..4fa62a4cb7cc 100644
--- a/arch/i386/xen/enlighten.c
+++ b/arch/i386/xen/enlighten.c
@@ -115,6 +115,7 @@ static void __init xen_vcpu_setup(int cpu)
115 /* This cpu is using the registered vcpu info, even if 115 /* This cpu is using the registered vcpu info, even if
116 later ones fail to. */ 116 later ones fail to. */
117 per_cpu(xen_vcpu, cpu) = vcpup; 117 per_cpu(xen_vcpu, cpu) = vcpup;
118
118 printk(KERN_DEBUG "cpu %d using vcpu_info at %p\n", 119 printk(KERN_DEBUG "cpu %d using vcpu_info at %p\n",
119 cpu, vcpup); 120 cpu, vcpup);
120 } 121 }
@@ -177,20 +178,6 @@ static unsigned long xen_save_fl(void)
177 return (-flags) & X86_EFLAGS_IF; 178 return (-flags) & X86_EFLAGS_IF;
178} 179}
179 180
180static unsigned long xen_save_fl_direct(void)
181{
182 unsigned long flags;
183
184 /* flag has opposite sense of mask */
185 flags = !x86_read_percpu(xen_vcpu_info.evtchn_upcall_mask);
186
187 /* convert to IF type flag
188 -0 -> 0x00000000
189 -1 -> 0xffffffff
190 */
191 return (-flags) & X86_EFLAGS_IF;
192}
193
194static void xen_restore_fl(unsigned long flags) 181static void xen_restore_fl(unsigned long flags)
195{ 182{
196 struct vcpu_info *vcpu; 183 struct vcpu_info *vcpu;
@@ -217,25 +204,6 @@ static void xen_restore_fl(unsigned long flags)
217 } 204 }
218} 205}
219 206
220static void xen_restore_fl_direct(unsigned long flags)
221{
222 /* convert from IF type flag */
223 flags = !(flags & X86_EFLAGS_IF);
224
225 /* This is an atomic update, so no need to worry about
226 preemption. */
227 x86_write_percpu(xen_vcpu_info.evtchn_upcall_mask, flags);
228
229 /* If we get preempted here, then any pending event will be
230 handled anyway. */
231
232 if (flags == 0) {
233 barrier(); /* unmask then check (avoid races) */
234 if (unlikely(x86_read_percpu(xen_vcpu_info.evtchn_upcall_pending)))
235 force_evtchn_callback();
236 }
237}
238
239static void xen_irq_disable(void) 207static void xen_irq_disable(void)
240{ 208{
241 /* There's a one instruction preempt window here. We need to 209 /* There's a one instruction preempt window here. We need to
@@ -246,12 +214,6 @@ static void xen_irq_disable(void)
246 preempt_enable_no_resched(); 214 preempt_enable_no_resched();
247} 215}
248 216
249static void xen_irq_disable_direct(void)
250{
251 /* Atomic update, so preemption not a concern. */
252 x86_write_percpu(xen_vcpu_info.evtchn_upcall_mask, 1);
253}
254
255static void xen_irq_enable(void) 217static void xen_irq_enable(void)
256{ 218{
257 struct vcpu_info *vcpu; 219 struct vcpu_info *vcpu;
@@ -272,19 +234,6 @@ static void xen_irq_enable(void)
272 force_evtchn_callback(); 234 force_evtchn_callback();
273} 235}
274 236
275static void xen_irq_enable_direct(void)
276{
277 /* Atomic update, so preemption not a concern. */
278 x86_write_percpu(xen_vcpu_info.evtchn_upcall_mask, 0);
279
280 /* Doesn't matter if we get preempted here, because any
281 pending event will get dealt with anyway. */
282
283 barrier(); /* unmask then check (avoid races) */
284 if (unlikely(x86_read_percpu(xen_vcpu_info.evtchn_upcall_pending)))
285 force_evtchn_callback();
286}
287
288static void xen_safe_halt(void) 237static void xen_safe_halt(void)
289{ 238{
290 /* Blocking includes an implicit local_irq_enable(). */ 239 /* Blocking includes an implicit local_irq_enable(). */
@@ -892,6 +841,57 @@ void __init xen_setup_vcpu_info_placement(void)
892 } 841 }
893} 842}
894 843
844static unsigned xen_patch(u8 type, u16 clobbers, void *insns, unsigned len)
845{
846 char *start, *end, *reloc;
847 unsigned ret;
848
849 start = end = reloc = NULL;
850
851#define SITE(x) \
852 case PARAVIRT_PATCH(x): \
853 if (have_vcpu_info_placement) { \
854 start = (char *)xen_##x##_direct; \
855 end = xen_##x##_direct_end; \
856 reloc = xen_##x##_direct_reloc; \
857 } \
858 goto patch_site
859
860 switch (type) {
861 SITE(irq_enable);
862 SITE(irq_disable);
863 SITE(save_fl);
864 SITE(restore_fl);
865#undef SITE
866
867 patch_site:
868 if (start == NULL || (end-start) > len)
869 goto default_patch;
870
871 ret = paravirt_patch_insns(insns, len, start, end);
872
873 /* Note: because reloc is assigned from something that
874 appears to be an array, gcc assumes it's non-null,
875 but doesn't know its relationship with start and
876 end. */
877 if (reloc > start && reloc < end) {
878 int reloc_off = reloc - start;
879 long *relocp = (long *)(insns + reloc_off);
880 long delta = start - (char *)insns;
881
882 *relocp += delta;
883 }
884 break;
885
886 default_patch:
887 default:
888 ret = paravirt_patch_default(type, clobbers, insns, len);
889 break;
890 }
891
892 return ret;
893}
894
895static const struct paravirt_ops xen_paravirt_ops __initdata = { 895static const struct paravirt_ops xen_paravirt_ops __initdata = {
896 .paravirt_enabled = 1, 896 .paravirt_enabled = 1,
897 .shared_kernel_pmd = 0, 897 .shared_kernel_pmd = 0,
@@ -899,7 +899,7 @@ static const struct paravirt_ops xen_paravirt_ops __initdata = {
899 .name = "Xen", 899 .name = "Xen",
900 .banner = xen_banner, 900 .banner = xen_banner,
901 901
902 .patch = paravirt_patch_default, 902 .patch = xen_patch,
903 903
904 .memory_setup = xen_memory_setup, 904 .memory_setup = xen_memory_setup,
905 .arch_setup = xen_arch_setup, 905 .arch_setup = xen_arch_setup,
@@ -1076,6 +1076,7 @@ static const struct machine_ops __initdata xen_machine_ops = {
1076 .emergency_restart = xen_emergency_restart, 1076 .emergency_restart = xen_emergency_restart,
1077}; 1077};
1078 1078
1079
1079/* First C function to be called on Xen boot */ 1080/* First C function to be called on Xen boot */
1080asmlinkage void __init xen_start_kernel(void) 1081asmlinkage void __init xen_start_kernel(void)
1081{ 1082{