diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2006-12-06 20:14:07 -0500 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-12-06 20:14:07 -0500 |
commit | d3561b7fa0fb0fc583bab0eeda32bec9e4c4056d (patch) | |
tree | 39d835965878622d052ef3b3c7b759d83b6bc327 | |
parent | db91b882aabd0b3b55a87cbfb344f2798bb740b4 (diff) |
[PATCH] paravirt: header and stubs for paravirtualisation
Create a paravirt.h header for all the critical operations which need to be
replaced with hypervisor calls, and include that instead of defining native
operations, when CONFIG_PARAVIRT.
This patch does the dumbest possible replacement of paravirtualized
instructions: calls through a "paravirt_ops" structure. Currently these are
function implementations of native hardware: hypervisors will override the ops
structure with their own variants.
All the pv-ops functions are declared "fastcall" so that a specific
register-based ABI is used, to make inlining assember easier.
And:
+From: Andy Whitcroft <apw@shadowen.org>
The paravirt ops introduce a 'weak' attribute onto memory_setup().
Code ordering leads to the following warnings on x86:
arch/i386/kernel/setup.c:651: warning: weak declaration of
`memory_setup' after first use results in unspecified behavior
Move memory_setup() to avoid this.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: Andi Kleen <ak@suse.de>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: Zachary Amsden <zach@vmware.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Andy Whitcroft <apw@shadowen.org>
27 files changed, 890 insertions, 58 deletions
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index 1f0f7b60995e..bb1fa061c6cf 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig | |||
@@ -182,6 +182,17 @@ config X86_ES7000 | |||
182 | 182 | ||
183 | endchoice | 183 | endchoice |
184 | 184 | ||
185 | config PARAVIRT | ||
186 | bool "Paravirtualization support (EXPERIMENTAL)" | ||
187 | depends on EXPERIMENTAL | ||
188 | help | ||
189 | Paravirtualization is a way of running multiple instances of | ||
190 | Linux on the same machine, under a hypervisor. This option | ||
191 | changes the kernel so it can modify itself when it is run | ||
192 | under a hypervisor, improving performance significantly. | ||
193 | However, when run without a hypervisor the kernel is | ||
194 | theoretically slower. If in doubt, say N. | ||
195 | |||
185 | config ACPI_SRAT | 196 | config ACPI_SRAT |
186 | bool | 197 | bool |
187 | default y | 198 | default y |
diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c index dc1538931555..c6798c75c67d 100644 --- a/arch/i386/boot/compressed/misc.c +++ b/arch/i386/boot/compressed/misc.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 | 9 | * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #undef CONFIG_PARAVIRT | ||
12 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> |
13 | #include <linux/vmalloc.h> | 14 | #include <linux/vmalloc.h> |
14 | #include <linux/screen_info.h> | 15 | #include <linux/screen_info.h> |
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index f614854bd71f..406612136049 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile | |||
@@ -39,6 +39,7 @@ obj-$(CONFIG_VM86) += vm86.o | |||
39 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 39 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
40 | obj-$(CONFIG_HPET_TIMER) += hpet.o | 40 | obj-$(CONFIG_HPET_TIMER) += hpet.o |
41 | obj-$(CONFIG_K8_NB) += k8.o | 41 | obj-$(CONFIG_K8_NB) += k8.o |
42 | obj-$(CONFIG_PARAVIRT) += paravirt.o | ||
42 | 43 | ||
43 | EXTRA_AFLAGS := -traditional | 44 | EXTRA_AFLAGS := -traditional |
44 | 45 | ||
diff --git a/arch/i386/kernel/asm-offsets.c b/arch/i386/kernel/asm-offsets.c index 0666eb0ed7bc..1b2f3cd33270 100644 --- a/arch/i386/kernel/asm-offsets.c +++ b/arch/i386/kernel/asm-offsets.c | |||
@@ -101,4 +101,14 @@ void foo(void) | |||
101 | BLANK(); | 101 | BLANK(); |
102 | OFFSET(PDA_cpu, i386_pda, cpu_number); | 102 | OFFSET(PDA_cpu, i386_pda, cpu_number); |
103 | OFFSET(PDA_pcurrent, i386_pda, pcurrent); | 103 | OFFSET(PDA_pcurrent, i386_pda, pcurrent); |
104 | |||
105 | #ifdef CONFIG_PARAVIRT | ||
106 | BLANK(); | ||
107 | OFFSET(PARAVIRT_enabled, paravirt_ops, paravirt_enabled); | ||
108 | OFFSET(PARAVIRT_irq_disable, paravirt_ops, irq_disable); | ||
109 | OFFSET(PARAVIRT_irq_enable, paravirt_ops, irq_enable); | ||
110 | OFFSET(PARAVIRT_irq_enable_sysexit, paravirt_ops, irq_enable_sysexit); | ||
111 | OFFSET(PARAVIRT_iret, paravirt_ops, iret); | ||
112 | OFFSET(PARAVIRT_read_cr0, paravirt_ops, read_cr0); | ||
113 | #endif | ||
104 | } | 114 | } |
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 0220bc8cbb43..d274612e05cd 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S | |||
@@ -62,13 +62,6 @@ DF_MASK = 0x00000400 | |||
62 | NT_MASK = 0x00004000 | 62 | NT_MASK = 0x00004000 |
63 | VM_MASK = 0x00020000 | 63 | VM_MASK = 0x00020000 |
64 | 64 | ||
65 | /* These are replaces for paravirtualization */ | ||
66 | #define DISABLE_INTERRUPTS cli | ||
67 | #define ENABLE_INTERRUPTS sti | ||
68 | #define ENABLE_INTERRUPTS_SYSEXIT sti; sysexit | ||
69 | #define INTERRUPT_RETURN iret | ||
70 | #define GET_CR0_INTO_EAX movl %cr0, %eax | ||
71 | |||
72 | #ifdef CONFIG_PREEMPT | 65 | #ifdef CONFIG_PREEMPT |
73 | #define preempt_stop DISABLE_INTERRUPTS; TRACE_IRQS_OFF | 66 | #define preempt_stop DISABLE_INTERRUPTS; TRACE_IRQS_OFF |
74 | #else | 67 | #else |
@@ -416,6 +409,20 @@ ldt_ss: | |||
416 | jnz restore_nocheck | 409 | jnz restore_nocheck |
417 | testl $0x00400000, %eax # returning to 32bit stack? | 410 | testl $0x00400000, %eax # returning to 32bit stack? |
418 | jnz restore_nocheck # allright, normal return | 411 | jnz restore_nocheck # allright, normal return |
412 | |||
413 | #ifdef CONFIG_PARAVIRT | ||
414 | /* | ||
415 | * The kernel can't run on a non-flat stack if paravirt mode | ||
416 | * is active. Rather than try to fixup the high bits of | ||
417 | * ESP, bypass this code entirely. This may break DOSemu | ||
418 | * and/or Wine support in a paravirt VM, although the option | ||
419 | * is still available to implement the setting of the high | ||
420 | * 16-bits in the INTERRUPT_RETURN paravirt-op. | ||
421 | */ | ||
422 | cmpl $0, paravirt_ops+PARAVIRT_enabled | ||
423 | jne restore_nocheck | ||
424 | #endif | ||
425 | |||
419 | /* If returning to userspace with 16bit stack, | 426 | /* If returning to userspace with 16bit stack, |
420 | * try to fix the higher word of ESP, as the CPU | 427 | * try to fix the higher word of ESP, as the CPU |
421 | * won't restore it. | 428 | * won't restore it. |
@@ -833,6 +840,19 @@ nmi_espfix_stack: | |||
833 | .previous | 840 | .previous |
834 | KPROBE_END(nmi) | 841 | KPROBE_END(nmi) |
835 | 842 | ||
843 | #ifdef CONFIG_PARAVIRT | ||
844 | ENTRY(native_iret) | ||
845 | 1: iret | ||
846 | .section __ex_table,"a" | ||
847 | .align 4 | ||
848 | .long 1b,iret_exc | ||
849 | .previous | ||
850 | |||
851 | ENTRY(native_irq_enable_sysexit) | ||
852 | sti | ||
853 | sysexit | ||
854 | #endif | ||
855 | |||
836 | KPROBE_ENTRY(int3) | 856 | KPROBE_ENTRY(int3) |
837 | RING0_INT_FRAME | 857 | RING0_INT_FRAME |
838 | pushl $-1 # mark this as an int | 858 | pushl $-1 # mark this as an int |
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c index 62996cd17084..c8d45821c788 100644 --- a/arch/i386/kernel/i8259.c +++ b/arch/i386/kernel/i8259.c | |||
@@ -381,7 +381,10 @@ void __init init_ISA_irqs (void) | |||
381 | } | 381 | } |
382 | } | 382 | } |
383 | 383 | ||
384 | void __init init_IRQ(void) | 384 | /* Overridden in paravirt.c */ |
385 | void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ"))); | ||
386 | |||
387 | void __init native_init_IRQ(void) | ||
385 | { | 388 | { |
386 | int i; | 389 | int i; |
387 | 390 | ||
diff --git a/arch/i386/kernel/paravirt.c b/arch/i386/kernel/paravirt.c new file mode 100644 index 000000000000..478192cd4b90 --- /dev/null +++ b/arch/i386/kernel/paravirt.c | |||
@@ -0,0 +1,404 @@ | |||
1 | /* Paravirtualization interfaces | ||
2 | Copyright (C) 2006 Rusty Russell IBM Corporation | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2 of the License, or | ||
7 | (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/efi.h> | ||
21 | #include <linux/bcd.h> | ||
22 | |||
23 | #include <asm/bug.h> | ||
24 | #include <asm/paravirt.h> | ||
25 | #include <asm/desc.h> | ||
26 | #include <asm/setup.h> | ||
27 | #include <asm/arch_hooks.h> | ||
28 | #include <asm/time.h> | ||
29 | #include <asm/irq.h> | ||
30 | #include <asm/delay.h> | ||
31 | |||
32 | /* nop stub */ | ||
33 | static void native_nop(void) | ||
34 | { | ||
35 | } | ||
36 | |||
37 | static void __init default_banner(void) | ||
38 | { | ||
39 | printk(KERN_INFO "Booting paravirtualized kernel on %s\n", | ||
40 | paravirt_ops.name); | ||
41 | } | ||
42 | |||
43 | char *memory_setup(void) | ||
44 | { | ||
45 | return paravirt_ops.memory_setup(); | ||
46 | } | ||
47 | |||
48 | static fastcall unsigned long native_get_debugreg(int regno) | ||
49 | { | ||
50 | unsigned long val = 0; /* Damn you, gcc! */ | ||
51 | |||
52 | switch (regno) { | ||
53 | case 0: | ||
54 | asm("movl %%db0, %0" :"=r" (val)); break; | ||
55 | case 1: | ||
56 | asm("movl %%db1, %0" :"=r" (val)); break; | ||
57 | case 2: | ||
58 | asm("movl %%db2, %0" :"=r" (val)); break; | ||
59 | case 3: | ||
60 | asm("movl %%db3, %0" :"=r" (val)); break; | ||
61 | case 6: | ||
62 | asm("movl %%db6, %0" :"=r" (val)); break; | ||
63 | case 7: | ||
64 | asm("movl %%db7, %0" :"=r" (val)); break; | ||
65 | default: | ||
66 | BUG(); | ||
67 | } | ||
68 | return val; | ||
69 | } | ||
70 | |||
71 | static fastcall void native_set_debugreg(int regno, unsigned long value) | ||
72 | { | ||
73 | switch (regno) { | ||
74 | case 0: | ||
75 | asm("movl %0,%%db0" : /* no output */ :"r" (value)); | ||
76 | break; | ||
77 | case 1: | ||
78 | asm("movl %0,%%db1" : /* no output */ :"r" (value)); | ||
79 | break; | ||
80 | case 2: | ||
81 | asm("movl %0,%%db2" : /* no output */ :"r" (value)); | ||
82 | break; | ||
83 | case 3: | ||
84 | asm("movl %0,%%db3" : /* no output */ :"r" (value)); | ||
85 | break; | ||
86 | case 6: | ||
87 | asm("movl %0,%%db6" : /* no output */ :"r" (value)); | ||
88 | break; | ||
89 | case 7: | ||
90 | asm("movl %0,%%db7" : /* no output */ :"r" (value)); | ||
91 | break; | ||
92 | default: | ||
93 | BUG(); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | void init_IRQ(void) | ||
98 | { | ||
99 | paravirt_ops.init_IRQ(); | ||
100 | } | ||
101 | |||
102 | static fastcall void native_clts(void) | ||
103 | { | ||
104 | asm volatile ("clts"); | ||
105 | } | ||
106 | |||
107 | static fastcall unsigned long native_read_cr0(void) | ||
108 | { | ||
109 | unsigned long val; | ||
110 | asm volatile("movl %%cr0,%0\n\t" :"=r" (val)); | ||
111 | return val; | ||
112 | } | ||
113 | |||
114 | static fastcall void native_write_cr0(unsigned long val) | ||
115 | { | ||
116 | asm volatile("movl %0,%%cr0": :"r" (val)); | ||
117 | } | ||
118 | |||
119 | static fastcall unsigned long native_read_cr2(void) | ||
120 | { | ||
121 | unsigned long val; | ||
122 | asm volatile("movl %%cr2,%0\n\t" :"=r" (val)); | ||
123 | return val; | ||
124 | } | ||
125 | |||
126 | static fastcall void native_write_cr2(unsigned long val) | ||
127 | { | ||
128 | asm volatile("movl %0,%%cr2": :"r" (val)); | ||
129 | } | ||
130 | |||
131 | static fastcall unsigned long native_read_cr3(void) | ||
132 | { | ||
133 | unsigned long val; | ||
134 | asm volatile("movl %%cr3,%0\n\t" :"=r" (val)); | ||
135 | return val; | ||
136 | } | ||
137 | |||
138 | static fastcall void native_write_cr3(unsigned long val) | ||
139 | { | ||
140 | asm volatile("movl %0,%%cr3": :"r" (val)); | ||
141 | } | ||
142 | |||
143 | static fastcall unsigned long native_read_cr4(void) | ||
144 | { | ||
145 | unsigned long val; | ||
146 | asm volatile("movl %%cr4,%0\n\t" :"=r" (val)); | ||
147 | return val; | ||
148 | } | ||
149 | |||
150 | static fastcall unsigned long native_read_cr4_safe(void) | ||
151 | { | ||
152 | unsigned long val; | ||
153 | /* This could fault if %cr4 does not exist */ | ||
154 | asm("1: movl %%cr4, %0 \n" | ||
155 | "2: \n" | ||
156 | ".section __ex_table,\"a\" \n" | ||
157 | ".long 1b,2b \n" | ||
158 | ".previous \n" | ||
159 | : "=r" (val): "0" (0)); | ||
160 | return val; | ||
161 | } | ||
162 | |||
163 | static fastcall void native_write_cr4(unsigned long val) | ||
164 | { | ||
165 | asm volatile("movl %0,%%cr4": :"r" (val)); | ||
166 | } | ||
167 | |||
168 | static fastcall unsigned long native_save_fl(void) | ||
169 | { | ||
170 | unsigned long f; | ||
171 | asm volatile("pushfl ; popl %0":"=g" (f): /* no input */); | ||
172 | return f; | ||
173 | } | ||
174 | |||
175 | static fastcall void native_restore_fl(unsigned long f) | ||
176 | { | ||
177 | asm volatile("pushl %0 ; popfl": /* no output */ | ||
178 | :"g" (f) | ||
179 | :"memory", "cc"); | ||
180 | } | ||
181 | |||
182 | static fastcall void native_irq_disable(void) | ||
183 | { | ||
184 | asm volatile("cli": : :"memory"); | ||
185 | } | ||
186 | |||
187 | static fastcall void native_irq_enable(void) | ||
188 | { | ||
189 | asm volatile("sti": : :"memory"); | ||
190 | } | ||
191 | |||
192 | static fastcall void native_safe_halt(void) | ||
193 | { | ||
194 | asm volatile("sti; hlt": : :"memory"); | ||
195 | } | ||
196 | |||
197 | static fastcall void native_halt(void) | ||
198 | { | ||
199 | asm volatile("hlt": : :"memory"); | ||
200 | } | ||
201 | |||
202 | static fastcall void native_wbinvd(void) | ||
203 | { | ||
204 | asm volatile("wbinvd": : :"memory"); | ||
205 | } | ||
206 | |||
207 | static fastcall unsigned long long native_read_msr(unsigned int msr, int *err) | ||
208 | { | ||
209 | unsigned long long val; | ||
210 | |||
211 | asm volatile("2: rdmsr ; xorl %0,%0\n" | ||
212 | "1:\n\t" | ||
213 | ".section .fixup,\"ax\"\n\t" | ||
214 | "3: movl %3,%0 ; jmp 1b\n\t" | ||
215 | ".previous\n\t" | ||
216 | ".section __ex_table,\"a\"\n" | ||
217 | " .align 4\n\t" | ||
218 | " .long 2b,3b\n\t" | ||
219 | ".previous" | ||
220 | : "=r" (*err), "=A" (val) | ||
221 | : "c" (msr), "i" (-EFAULT)); | ||
222 | |||
223 | return val; | ||
224 | } | ||
225 | |||
226 | static fastcall int native_write_msr(unsigned int msr, unsigned long long val) | ||
227 | { | ||
228 | int err; | ||
229 | asm volatile("2: wrmsr ; xorl %0,%0\n" | ||
230 | "1:\n\t" | ||
231 | ".section .fixup,\"ax\"\n\t" | ||
232 | "3: movl %4,%0 ; jmp 1b\n\t" | ||
233 | ".previous\n\t" | ||
234 | ".section __ex_table,\"a\"\n" | ||
235 | " .align 4\n\t" | ||
236 | " .long 2b,3b\n\t" | ||
237 | ".previous" | ||
238 | : "=a" (err) | ||
239 | : "c" (msr), "0" ((u32)val), "d" ((u32)(val>>32)), | ||
240 | "i" (-EFAULT)); | ||
241 | return err; | ||
242 | } | ||
243 | |||
244 | static fastcall unsigned long long native_read_tsc(void) | ||
245 | { | ||
246 | unsigned long long val; | ||
247 | asm volatile("rdtsc" : "=A" (val)); | ||
248 | return val; | ||
249 | } | ||
250 | |||
251 | static fastcall unsigned long long native_read_pmc(void) | ||
252 | { | ||
253 | unsigned long long val; | ||
254 | asm volatile("rdpmc" : "=A" (val)); | ||
255 | return val; | ||
256 | } | ||
257 | |||
258 | static fastcall void native_load_tr_desc(void) | ||
259 | { | ||
260 | asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8)); | ||
261 | } | ||
262 | |||
263 | static fastcall void native_load_gdt(const struct Xgt_desc_struct *dtr) | ||
264 | { | ||
265 | asm volatile("lgdt %0"::"m" (*dtr)); | ||
266 | } | ||
267 | |||
268 | static fastcall void native_load_idt(const struct Xgt_desc_struct *dtr) | ||
269 | { | ||
270 | asm volatile("lidt %0"::"m" (*dtr)); | ||
271 | } | ||
272 | |||
273 | static fastcall void native_store_gdt(struct Xgt_desc_struct *dtr) | ||
274 | { | ||
275 | asm ("sgdt %0":"=m" (*dtr)); | ||
276 | } | ||
277 | |||
278 | static fastcall void native_store_idt(struct Xgt_desc_struct *dtr) | ||
279 | { | ||
280 | asm ("sidt %0":"=m" (*dtr)); | ||
281 | } | ||
282 | |||
283 | static fastcall unsigned long native_store_tr(void) | ||
284 | { | ||
285 | unsigned long tr; | ||
286 | asm ("str %0":"=r" (tr)); | ||
287 | return tr; | ||
288 | } | ||
289 | |||
290 | static fastcall void native_load_tls(struct thread_struct *t, unsigned int cpu) | ||
291 | { | ||
292 | #define C(i) get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i] | ||
293 | C(0); C(1); C(2); | ||
294 | #undef C | ||
295 | } | ||
296 | |||
297 | static inline void native_write_dt_entry(void *dt, int entry, u32 entry_low, u32 entry_high) | ||
298 | { | ||
299 | u32 *lp = (u32 *)((char *)dt + entry*8); | ||
300 | lp[0] = entry_low; | ||
301 | lp[1] = entry_high; | ||
302 | } | ||
303 | |||
304 | static fastcall void native_write_ldt_entry(void *dt, int entrynum, u32 low, u32 high) | ||
305 | { | ||
306 | native_write_dt_entry(dt, entrynum, low, high); | ||
307 | } | ||
308 | |||
309 | static fastcall void native_write_gdt_entry(void *dt, int entrynum, u32 low, u32 high) | ||
310 | { | ||
311 | native_write_dt_entry(dt, entrynum, low, high); | ||
312 | } | ||
313 | |||
314 | static fastcall void native_write_idt_entry(void *dt, int entrynum, u32 low, u32 high) | ||
315 | { | ||
316 | native_write_dt_entry(dt, entrynum, low, high); | ||
317 | } | ||
318 | |||
319 | static fastcall void native_load_esp0(struct tss_struct *tss, | ||
320 | struct thread_struct *thread) | ||
321 | { | ||
322 | tss->esp0 = thread->esp0; | ||
323 | |||
324 | /* This can only happen when SEP is enabled, no need to test "SEP"arately */ | ||
325 | if (unlikely(tss->ss1 != thread->sysenter_cs)) { | ||
326 | tss->ss1 = thread->sysenter_cs; | ||
327 | wrmsr(MSR_IA32_SYSENTER_CS, thread->sysenter_cs, 0); | ||
328 | } | ||
329 | } | ||
330 | |||
331 | static fastcall void native_io_delay(void) | ||
332 | { | ||
333 | asm volatile("outb %al,$0x80"); | ||
334 | } | ||
335 | |||
336 | /* These are in entry.S */ | ||
337 | extern fastcall void native_iret(void); | ||
338 | extern fastcall void native_irq_enable_sysexit(void); | ||
339 | |||
340 | static int __init print_banner(void) | ||
341 | { | ||
342 | paravirt_ops.banner(); | ||
343 | return 0; | ||
344 | } | ||
345 | core_initcall(print_banner); | ||
346 | |||
347 | struct paravirt_ops paravirt_ops = { | ||
348 | .name = "bare hardware", | ||
349 | .paravirt_enabled = 0, | ||
350 | .kernel_rpl = 0, | ||
351 | |||
352 | .banner = default_banner, | ||
353 | .arch_setup = native_nop, | ||
354 | .memory_setup = machine_specific_memory_setup, | ||
355 | .get_wallclock = native_get_wallclock, | ||
356 | .set_wallclock = native_set_wallclock, | ||
357 | .time_init = time_init_hook, | ||
358 | .init_IRQ = native_init_IRQ, | ||
359 | |||
360 | .cpuid = native_cpuid, | ||
361 | .get_debugreg = native_get_debugreg, | ||
362 | .set_debugreg = native_set_debugreg, | ||
363 | .clts = native_clts, | ||
364 | .read_cr0 = native_read_cr0, | ||
365 | .write_cr0 = native_write_cr0, | ||
366 | .read_cr2 = native_read_cr2, | ||
367 | .write_cr2 = native_write_cr2, | ||
368 | .read_cr3 = native_read_cr3, | ||
369 | .write_cr3 = native_write_cr3, | ||
370 | .read_cr4 = native_read_cr4, | ||
371 | .read_cr4_safe = native_read_cr4_safe, | ||
372 | .write_cr4 = native_write_cr4, | ||
373 | .save_fl = native_save_fl, | ||
374 | .restore_fl = native_restore_fl, | ||
375 | .irq_disable = native_irq_disable, | ||
376 | .irq_enable = native_irq_enable, | ||
377 | .safe_halt = native_safe_halt, | ||
378 | .halt = native_halt, | ||
379 | .wbinvd = native_wbinvd, | ||
380 | .read_msr = native_read_msr, | ||
381 | .write_msr = native_write_msr, | ||
382 | .read_tsc = native_read_tsc, | ||
383 | .read_pmc = native_read_pmc, | ||
384 | .load_tr_desc = native_load_tr_desc, | ||
385 | .set_ldt = native_set_ldt, | ||
386 | .load_gdt = native_load_gdt, | ||
387 | .load_idt = native_load_idt, | ||
388 | .store_gdt = native_store_gdt, | ||
389 | .store_idt = native_store_idt, | ||
390 | .store_tr = native_store_tr, | ||
391 | .load_tls = native_load_tls, | ||
392 | .write_ldt_entry = native_write_ldt_entry, | ||
393 | .write_gdt_entry = native_write_gdt_entry, | ||
394 | .write_idt_entry = native_write_idt_entry, | ||
395 | .load_esp0 = native_load_esp0, | ||
396 | |||
397 | .set_iopl_mask = native_set_iopl_mask, | ||
398 | .io_delay = native_io_delay, | ||
399 | .const_udelay = __const_udelay, | ||
400 | |||
401 | .irq_enable_sysexit = native_irq_enable_sysexit, | ||
402 | .iret = native_iret, | ||
403 | }; | ||
404 | EXPORT_SYMBOL(paravirt_ops); | ||
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index e5bb87aa5a45..695d53fd14de 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c | |||
@@ -495,6 +495,12 @@ static void set_mca_bus(int x) | |||
495 | static void set_mca_bus(int x) { } | 495 | static void set_mca_bus(int x) { } |
496 | #endif | 496 | #endif |
497 | 497 | ||
498 | /* Overridden in paravirt.c if CONFIG_PARAVIRT */ | ||
499 | char * __attribute__((weak)) memory_setup(void) | ||
500 | { | ||
501 | return machine_specific_memory_setup(); | ||
502 | } | ||
503 | |||
498 | /* | 504 | /* |
499 | * Determine if we were loaded by an EFI loader. If so, then we have also been | 505 | * Determine if we were loaded by an EFI loader. If so, then we have also been |
500 | * passed the efi memmap, systab, etc., so we should use these data structures | 506 | * passed the efi memmap, systab, etc., so we should use these data structures |
@@ -547,7 +553,7 @@ void __init setup_arch(char **cmdline_p) | |||
547 | efi_init(); | 553 | efi_init(); |
548 | else { | 554 | else { |
549 | printk(KERN_INFO "BIOS-provided physical RAM map:\n"); | 555 | printk(KERN_INFO "BIOS-provided physical RAM map:\n"); |
550 | print_memory_map(machine_specific_memory_setup()); | 556 | print_memory_map(memory_setup()); |
551 | } | 557 | } |
552 | 558 | ||
553 | copy_edd(); | 559 | copy_edd(); |
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 095636620fa2..cd7de9c9654b 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c | |||
@@ -33,6 +33,11 @@ | |||
33 | * Dave Jones : Report invalid combinations of Athlon CPUs. | 33 | * Dave Jones : Report invalid combinations of Athlon CPUs. |
34 | * Rusty Russell : Hacked into shape for new "hotplug" boot process. */ | 34 | * Rusty Russell : Hacked into shape for new "hotplug" boot process. */ |
35 | 35 | ||
36 | |||
37 | /* SMP boot always wants to use real time delay to allow sufficient time for | ||
38 | * the APs to come online */ | ||
39 | #define USE_REAL_TIME_DELAY | ||
40 | |||
36 | #include <linux/module.h> | 41 | #include <linux/module.h> |
37 | #include <linux/init.h> | 42 | #include <linux/init.h> |
38 | #include <linux/kernel.h> | 43 | #include <linux/kernel.h> |
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index 78af572fd17c..c505b16c0990 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include <asm/uaccess.h> | 56 | #include <asm/uaccess.h> |
57 | #include <asm/processor.h> | 57 | #include <asm/processor.h> |
58 | #include <asm/timer.h> | 58 | #include <asm/timer.h> |
59 | #include <asm/time.h> | ||
59 | 60 | ||
60 | #include "mach_time.h" | 61 | #include "mach_time.h" |
61 | 62 | ||
@@ -116,10 +117,7 @@ static int set_rtc_mmss(unsigned long nowtime) | |||
116 | /* gets recalled with irq locally disabled */ | 117 | /* gets recalled with irq locally disabled */ |
117 | /* XXX - does irqsave resolve this? -johnstul */ | 118 | /* XXX - does irqsave resolve this? -johnstul */ |
118 | spin_lock_irqsave(&rtc_lock, flags); | 119 | spin_lock_irqsave(&rtc_lock, flags); |
119 | if (efi_enabled) | 120 | retval = set_wallclock(nowtime); |
120 | retval = efi_set_rtc_mmss(nowtime); | ||
121 | else | ||
122 | retval = mach_set_rtc_mmss(nowtime); | ||
123 | spin_unlock_irqrestore(&rtc_lock, flags); | 121 | spin_unlock_irqrestore(&rtc_lock, flags); |
124 | 122 | ||
125 | return retval; | 123 | return retval; |
@@ -223,10 +221,7 @@ unsigned long get_cmos_time(void) | |||
223 | 221 | ||
224 | spin_lock_irqsave(&rtc_lock, flags); | 222 | spin_lock_irqsave(&rtc_lock, flags); |
225 | 223 | ||
226 | if (efi_enabled) | 224 | retval = get_wallclock(); |
227 | retval = efi_get_time(); | ||
228 | else | ||
229 | retval = mach_get_cmos_time(); | ||
230 | 225 | ||
231 | spin_unlock_irqrestore(&rtc_lock, flags); | 226 | spin_unlock_irqrestore(&rtc_lock, flags); |
232 | 227 | ||
@@ -370,7 +365,7 @@ static void __init hpet_time_init(void) | |||
370 | printk("Using HPET for base-timer\n"); | 365 | printk("Using HPET for base-timer\n"); |
371 | } | 366 | } |
372 | 367 | ||
373 | time_init_hook(); | 368 | do_time_init(); |
374 | } | 369 | } |
375 | #endif | 370 | #endif |
376 | 371 | ||
@@ -392,5 +387,5 @@ void __init time_init(void) | |||
392 | 387 | ||
393 | do_settimeofday(&ts); | 388 | do_settimeofday(&ts); |
394 | 389 | ||
395 | time_init_hook(); | 390 | do_time_init(); |
396 | } | 391 | } |
diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c index 5a1abeff033b..2c15500f8713 100644 --- a/arch/i386/power/cpu.c +++ b/arch/i386/power/cpu.c | |||
@@ -26,8 +26,8 @@ void __save_processor_state(struct saved_context *ctxt) | |||
26 | /* | 26 | /* |
27 | * descriptor tables | 27 | * descriptor tables |
28 | */ | 28 | */ |
29 | store_gdt(&ctxt->gdt_limit); | 29 | store_gdt(&ctxt->gdt); |
30 | store_idt(&ctxt->idt_limit); | 30 | store_idt(&ctxt->idt); |
31 | store_tr(ctxt->tr); | 31 | store_tr(ctxt->tr); |
32 | 32 | ||
33 | /* | 33 | /* |
@@ -99,8 +99,8 @@ void __restore_processor_state(struct saved_context *ctxt) | |||
99 | * now restore the descriptor tables to their proper values | 99 | * now restore the descriptor tables to their proper values |
100 | * ltr is done i fix_processor_context(). | 100 | * ltr is done i fix_processor_context(). |
101 | */ | 101 | */ |
102 | load_gdt(&ctxt->gdt_limit); | 102 | load_gdt(&ctxt->gdt); |
103 | load_idt(&ctxt->idt_limit); | 103 | load_idt(&ctxt->idt); |
104 | 104 | ||
105 | /* | 105 | /* |
106 | * segment registers | 106 | * segment registers |
diff --git a/drivers/net/de600.c b/drivers/net/de600.c index 690bb40b353d..8396e411f1ce 100644 --- a/drivers/net/de600.c +++ b/drivers/net/de600.c | |||
@@ -43,7 +43,6 @@ static const char version[] = "de600.c: $Revision: 1.41-2.5 $, Bjorn Ekwall (bj | |||
43 | * modify the following "#define": (see <asm/io.h> for more info) | 43 | * modify the following "#define": (see <asm/io.h> for more info) |
44 | #define REALLY_SLOW_IO | 44 | #define REALLY_SLOW_IO |
45 | */ | 45 | */ |
46 | #define SLOW_IO_BY_JUMPING /* Looks "better" than dummy write to port 0x80 :-) */ | ||
47 | 46 | ||
48 | /* use 0 for production, 1 for verification, >2 for debug */ | 47 | /* use 0 for production, 1 for verification, >2 for debug */ |
49 | #ifdef DE600_DEBUG | 48 | #ifdef DE600_DEBUG |
diff --git a/include/asm-i386/delay.h b/include/asm-i386/delay.h index 9ae5e3782ed8..32d6678d0bbf 100644 --- a/include/asm-i386/delay.h +++ b/include/asm-i386/delay.h | |||
@@ -16,6 +16,13 @@ extern void __ndelay(unsigned long nsecs); | |||
16 | extern void __const_udelay(unsigned long usecs); | 16 | extern void __const_udelay(unsigned long usecs); |
17 | extern void __delay(unsigned long loops); | 17 | extern void __delay(unsigned long loops); |
18 | 18 | ||
19 | #if defined(CONFIG_PARAVIRT) && !defined(USE_REAL_TIME_DELAY) | ||
20 | #define udelay(n) paravirt_ops.const_udelay((n) * 0x10c7ul) | ||
21 | |||
22 | #define ndelay(n) paravirt_ops.const_udelay((n) * 5ul) | ||
23 | |||
24 | #else /* !PARAVIRT || USE_REAL_TIME_DELAY */ | ||
25 | |||
19 | /* 0x10c7 is 2**32 / 1000000 (rounded up) */ | 26 | /* 0x10c7 is 2**32 / 1000000 (rounded up) */ |
20 | #define udelay(n) (__builtin_constant_p(n) ? \ | 27 | #define udelay(n) (__builtin_constant_p(n) ? \ |
21 | ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \ | 28 | ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c7ul)) : \ |
@@ -25,6 +32,7 @@ extern void __delay(unsigned long loops); | |||
25 | #define ndelay(n) (__builtin_constant_p(n) ? \ | 32 | #define ndelay(n) (__builtin_constant_p(n) ? \ |
26 | ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \ | 33 | ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \ |
27 | __ndelay(n)) | 34 | __ndelay(n)) |
35 | #endif | ||
28 | 36 | ||
29 | void use_tsc_delay(void); | 37 | void use_tsc_delay(void); |
30 | 38 | ||
diff --git a/include/asm-i386/desc.h b/include/asm-i386/desc.h index 6cf2ac2bfde7..f19820f0834f 100644 --- a/include/asm-i386/desc.h +++ b/include/asm-i386/desc.h | |||
@@ -55,6 +55,9 @@ static inline void pack_gate(__u32 *a, __u32 *b, | |||
55 | #define DESCTYPE_DPL3 0x60 /* DPL-3 */ | 55 | #define DESCTYPE_DPL3 0x60 /* DPL-3 */ |
56 | #define DESCTYPE_S 0x10 /* !system */ | 56 | #define DESCTYPE_S 0x10 /* !system */ |
57 | 57 | ||
58 | #ifdef CONFIG_PARAVIRT | ||
59 | #include <asm/paravirt.h> | ||
60 | #else | ||
58 | #define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8)) | 61 | #define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8)) |
59 | 62 | ||
60 | #define load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr)) | 63 | #define load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr)) |
@@ -105,7 +108,11 @@ static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const vo | |||
105 | write_gdt_entry(get_cpu_gdt_table(cpu), entry, a, b); | 108 | write_gdt_entry(get_cpu_gdt_table(cpu), entry, a, b); |
106 | } | 109 | } |
107 | 110 | ||
108 | static inline void set_ldt(void *addr, unsigned int entries) | 111 | #define set_ldt native_set_ldt |
112 | #endif /* CONFIG_PARAVIRT */ | ||
113 | |||
114 | static inline fastcall void native_set_ldt(const void *addr, | ||
115 | unsigned int entries) | ||
109 | { | 116 | { |
110 | if (likely(entries == 0)) | 117 | if (likely(entries == 0)) |
111 | __asm__ __volatile__("lldt %w0"::"q" (0)); | 118 | __asm__ __volatile__("lldt %w0"::"q" (0)); |
diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h index 68df0dc3ab8f..86ff5e83be2f 100644 --- a/include/asm-i386/io.h +++ b/include/asm-i386/io.h | |||
@@ -256,11 +256,11 @@ static inline void flush_write_buffers(void) | |||
256 | 256 | ||
257 | #endif /* __KERNEL__ */ | 257 | #endif /* __KERNEL__ */ |
258 | 258 | ||
259 | #ifdef SLOW_IO_BY_JUMPING | 259 | #if defined(CONFIG_PARAVIRT) |
260 | #define __SLOW_DOWN_IO "jmp 1f; 1: jmp 1f; 1:" | 260 | #include <asm/paravirt.h> |
261 | #else | 261 | #else |
262 | |||
262 | #define __SLOW_DOWN_IO "outb %%al,$0x80;" | 263 | #define __SLOW_DOWN_IO "outb %%al,$0x80;" |
263 | #endif | ||
264 | 264 | ||
265 | static inline void slow_down_io(void) { | 265 | static inline void slow_down_io(void) { |
266 | __asm__ __volatile__( | 266 | __asm__ __volatile__( |
@@ -271,6 +271,8 @@ static inline void slow_down_io(void) { | |||
271 | : : ); | 271 | : : ); |
272 | } | 272 | } |
273 | 273 | ||
274 | #endif | ||
275 | |||
274 | #ifdef CONFIG_X86_NUMAQ | 276 | #ifdef CONFIG_X86_NUMAQ |
275 | extern void *xquad_portio; /* Where the IO area was mapped */ | 277 | extern void *xquad_portio; /* Where the IO area was mapped */ |
276 | #define XQUAD_PORT_ADDR(port, quad) (xquad_portio + (XQUAD_PORTIO_QUAD*quad) + port) | 278 | #define XQUAD_PORT_ADDR(port, quad) (xquad_portio + (XQUAD_PORTIO_QUAD*quad) + port) |
diff --git a/include/asm-i386/irq.h b/include/asm-i386/irq.h index 331726b41128..9e15ce0006eb 100644 --- a/include/asm-i386/irq.h +++ b/include/asm-i386/irq.h | |||
@@ -41,4 +41,7 @@ extern int irqbalance_disable(char *str); | |||
41 | extern void fixup_irqs(cpumask_t map); | 41 | extern void fixup_irqs(cpumask_t map); |
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | void init_IRQ(void); | ||
45 | void __init native_init_IRQ(void); | ||
46 | |||
44 | #endif /* _ASM_IRQ_H */ | 47 | #endif /* _ASM_IRQ_H */ |
diff --git a/include/asm-i386/irqflags.h b/include/asm-i386/irqflags.h index e1bdb97c07fa..9ce01f3fb7bc 100644 --- a/include/asm-i386/irqflags.h +++ b/include/asm-i386/irqflags.h | |||
@@ -10,6 +10,9 @@ | |||
10 | #ifndef _ASM_IRQFLAGS_H | 10 | #ifndef _ASM_IRQFLAGS_H |
11 | #define _ASM_IRQFLAGS_H | 11 | #define _ASM_IRQFLAGS_H |
12 | 12 | ||
13 | #ifdef CONFIG_PARAVIRT | ||
14 | #include <asm/paravirt.h> | ||
15 | #else | ||
13 | #ifndef __ASSEMBLY__ | 16 | #ifndef __ASSEMBLY__ |
14 | 17 | ||
15 | static inline unsigned long __raw_local_save_flags(void) | 18 | static inline unsigned long __raw_local_save_flags(void) |
@@ -25,9 +28,6 @@ static inline unsigned long __raw_local_save_flags(void) | |||
25 | return flags; | 28 | return flags; |
26 | } | 29 | } |
27 | 30 | ||
28 | #define raw_local_save_flags(flags) \ | ||
29 | do { (flags) = __raw_local_save_flags(); } while (0) | ||
30 | |||
31 | static inline void raw_local_irq_restore(unsigned long flags) | 31 | static inline void raw_local_irq_restore(unsigned long flags) |
32 | { | 32 | { |
33 | __asm__ __volatile__( | 33 | __asm__ __volatile__( |
@@ -66,18 +66,6 @@ static inline void halt(void) | |||
66 | __asm__ __volatile__("hlt": : :"memory"); | 66 | __asm__ __volatile__("hlt": : :"memory"); |
67 | } | 67 | } |
68 | 68 | ||
69 | static inline int raw_irqs_disabled_flags(unsigned long flags) | ||
70 | { | ||
71 | return !(flags & (1 << 9)); | ||
72 | } | ||
73 | |||
74 | static inline int raw_irqs_disabled(void) | ||
75 | { | ||
76 | unsigned long flags = __raw_local_save_flags(); | ||
77 | |||
78 | return raw_irqs_disabled_flags(flags); | ||
79 | } | ||
80 | |||
81 | /* | 69 | /* |
82 | * For spinlocks, etc: | 70 | * For spinlocks, etc: |
83 | */ | 71 | */ |
@@ -90,9 +78,33 @@ static inline unsigned long __raw_local_irq_save(void) | |||
90 | return flags; | 78 | return flags; |
91 | } | 79 | } |
92 | 80 | ||
81 | #else | ||
82 | #define DISABLE_INTERRUPTS cli | ||
83 | #define ENABLE_INTERRUPTS sti | ||
84 | #define ENABLE_INTERRUPTS_SYSEXIT sti; sysexit | ||
85 | #define INTERRUPT_RETURN iret | ||
86 | #define GET_CR0_INTO_EAX movl %cr0, %eax | ||
87 | #endif /* __ASSEMBLY__ */ | ||
88 | #endif /* CONFIG_PARAVIRT */ | ||
89 | |||
90 | #ifndef __ASSEMBLY__ | ||
91 | #define raw_local_save_flags(flags) \ | ||
92 | do { (flags) = __raw_local_save_flags(); } while (0) | ||
93 | |||
93 | #define raw_local_irq_save(flags) \ | 94 | #define raw_local_irq_save(flags) \ |
94 | do { (flags) = __raw_local_irq_save(); } while (0) | 95 | do { (flags) = __raw_local_irq_save(); } while (0) |
95 | 96 | ||
97 | static inline int raw_irqs_disabled_flags(unsigned long flags) | ||
98 | { | ||
99 | return !(flags & (1 << 9)); | ||
100 | } | ||
101 | |||
102 | static inline int raw_irqs_disabled(void) | ||
103 | { | ||
104 | unsigned long flags = __raw_local_save_flags(); | ||
105 | |||
106 | return raw_irqs_disabled_flags(flags); | ||
107 | } | ||
96 | #endif /* __ASSEMBLY__ */ | 108 | #endif /* __ASSEMBLY__ */ |
97 | 109 | ||
98 | /* | 110 | /* |
diff --git a/include/asm-i386/mach-default/setup_arch.h b/include/asm-i386/mach-default/setup_arch.h index fb42099e7bd4..605e3ccb991b 100644 --- a/include/asm-i386/mach-default/setup_arch.h +++ b/include/asm-i386/mach-default/setup_arch.h | |||
@@ -2,4 +2,6 @@ | |||
2 | 2 | ||
3 | /* no action for generic */ | 3 | /* no action for generic */ |
4 | 4 | ||
5 | #ifndef ARCH_SETUP | ||
5 | #define ARCH_SETUP | 6 | #define ARCH_SETUP |
7 | #endif | ||
diff --git a/include/asm-i386/msr.h b/include/asm-i386/msr.h index 1820d9d73af3..5679d4993072 100644 --- a/include/asm-i386/msr.h +++ b/include/asm-i386/msr.h | |||
@@ -1,6 +1,10 @@ | |||
1 | #ifndef __ASM_MSR_H | 1 | #ifndef __ASM_MSR_H |
2 | #define __ASM_MSR_H | 2 | #define __ASM_MSR_H |
3 | 3 | ||
4 | #ifdef CONFIG_PARAVIRT | ||
5 | #include <asm/paravirt.h> | ||
6 | #else | ||
7 | |||
4 | /* | 8 | /* |
5 | * Access to machine-specific registers (available on 586 and better only) | 9 | * Access to machine-specific registers (available on 586 and better only) |
6 | * Note: the rd* operations modify the parameters directly (without using | 10 | * Note: the rd* operations modify the parameters directly (without using |
@@ -77,6 +81,7 @@ static inline void wrmsrl (unsigned long msr, unsigned long long val) | |||
77 | __asm__ __volatile__("rdpmc" \ | 81 | __asm__ __volatile__("rdpmc" \ |
78 | : "=a" (low), "=d" (high) \ | 82 | : "=a" (low), "=d" (high) \ |
79 | : "c" (counter)) | 83 | : "c" (counter)) |
84 | #endif /* !CONFIG_PARAVIRT */ | ||
80 | 85 | ||
81 | /* symbolic names for some interesting MSRs */ | 86 | /* symbolic names for some interesting MSRs */ |
82 | /* Intel defined MSRs. */ | 87 | /* Intel defined MSRs. */ |
diff --git a/include/asm-i386/paravirt.h b/include/asm-i386/paravirt.h new file mode 100644 index 000000000000..a7551a44686f --- /dev/null +++ b/include/asm-i386/paravirt.h | |||
@@ -0,0 +1,281 @@ | |||
1 | #ifndef __ASM_PARAVIRT_H | ||
2 | #define __ASM_PARAVIRT_H | ||
3 | /* Various instructions on x86 need to be replaced for | ||
4 | * para-virtualization: those hooks are defined here. */ | ||
5 | #include <linux/linkage.h> | ||
6 | |||
7 | #ifdef CONFIG_PARAVIRT | ||
8 | #ifndef __ASSEMBLY__ | ||
9 | struct thread_struct; | ||
10 | struct Xgt_desc_struct; | ||
11 | struct tss_struct; | ||
12 | struct paravirt_ops | ||
13 | { | ||
14 | unsigned int kernel_rpl; | ||
15 | int paravirt_enabled; | ||
16 | const char *name; | ||
17 | |||
18 | void (*arch_setup)(void); | ||
19 | char *(*memory_setup)(void); | ||
20 | void (*init_IRQ)(void); | ||
21 | |||
22 | void (*banner)(void); | ||
23 | |||
24 | unsigned long (*get_wallclock)(void); | ||
25 | int (*set_wallclock)(unsigned long); | ||
26 | void (*time_init)(void); | ||
27 | |||
28 | /* All the function pointers here are declared as "fastcall" | ||
29 | so that we get a specific register-based calling | ||
30 | convention. This makes it easier to implement inline | ||
31 | assembler replacements. */ | ||
32 | |||
33 | void (fastcall *cpuid)(unsigned int *eax, unsigned int *ebx, | ||
34 | unsigned int *ecx, unsigned int *edx); | ||
35 | |||
36 | unsigned long (fastcall *get_debugreg)(int regno); | ||
37 | void (fastcall *set_debugreg)(int regno, unsigned long value); | ||
38 | |||
39 | void (fastcall *clts)(void); | ||
40 | |||
41 | unsigned long (fastcall *read_cr0)(void); | ||
42 | void (fastcall *write_cr0)(unsigned long); | ||
43 | |||
44 | unsigned long (fastcall *read_cr2)(void); | ||
45 | void (fastcall *write_cr2)(unsigned long); | ||
46 | |||
47 | unsigned long (fastcall *read_cr3)(void); | ||
48 | void (fastcall *write_cr3)(unsigned long); | ||
49 | |||
50 | unsigned long (fastcall *read_cr4_safe)(void); | ||
51 | unsigned long (fastcall *read_cr4)(void); | ||
52 | void (fastcall *write_cr4)(unsigned long); | ||
53 | |||
54 | unsigned long (fastcall *save_fl)(void); | ||
55 | void (fastcall *restore_fl)(unsigned long); | ||
56 | void (fastcall *irq_disable)(void); | ||
57 | void (fastcall *irq_enable)(void); | ||
58 | void (fastcall *safe_halt)(void); | ||
59 | void (fastcall *halt)(void); | ||
60 | void (fastcall *wbinvd)(void); | ||
61 | |||
62 | /* err = 0/-EFAULT. wrmsr returns 0/-EFAULT. */ | ||
63 | u64 (fastcall *read_msr)(unsigned int msr, int *err); | ||
64 | int (fastcall *write_msr)(unsigned int msr, u64 val); | ||
65 | |||
66 | u64 (fastcall *read_tsc)(void); | ||
67 | u64 (fastcall *read_pmc)(void); | ||
68 | |||
69 | void (fastcall *load_tr_desc)(void); | ||
70 | void (fastcall *load_gdt)(const struct Xgt_desc_struct *); | ||
71 | void (fastcall *load_idt)(const struct Xgt_desc_struct *); | ||
72 | void (fastcall *store_gdt)(struct Xgt_desc_struct *); | ||
73 | void (fastcall *store_idt)(struct Xgt_desc_struct *); | ||
74 | void (fastcall *set_ldt)(const void *desc, unsigned entries); | ||
75 | unsigned long (fastcall *store_tr)(void); | ||
76 | void (fastcall *load_tls)(struct thread_struct *t, unsigned int cpu); | ||
77 | void (fastcall *write_ldt_entry)(void *dt, int entrynum, | ||
78 | u32 low, u32 high); | ||
79 | void (fastcall *write_gdt_entry)(void *dt, int entrynum, | ||
80 | u32 low, u32 high); | ||
81 | void (fastcall *write_idt_entry)(void *dt, int entrynum, | ||
82 | u32 low, u32 high); | ||
83 | void (fastcall *load_esp0)(struct tss_struct *tss, | ||
84 | struct thread_struct *thread); | ||
85 | |||
86 | void (fastcall *set_iopl_mask)(unsigned mask); | ||
87 | |||
88 | void (fastcall *io_delay)(void); | ||
89 | void (*const_udelay)(unsigned long loops); | ||
90 | |||
91 | /* These two are jmp to, not actually called. */ | ||
92 | void (fastcall *irq_enable_sysexit)(void); | ||
93 | void (fastcall *iret)(void); | ||
94 | }; | ||
95 | |||
96 | extern struct paravirt_ops paravirt_ops; | ||
97 | |||
98 | #define paravirt_enabled() (paravirt_ops.paravirt_enabled) | ||
99 | |||
100 | static inline void load_esp0(struct tss_struct *tss, | ||
101 | struct thread_struct *thread) | ||
102 | { | ||
103 | paravirt_ops.load_esp0(tss, thread); | ||
104 | } | ||
105 | |||
106 | #define ARCH_SETUP paravirt_ops.arch_setup(); | ||
107 | static inline unsigned long get_wallclock(void) | ||
108 | { | ||
109 | return paravirt_ops.get_wallclock(); | ||
110 | } | ||
111 | |||
112 | static inline int set_wallclock(unsigned long nowtime) | ||
113 | { | ||
114 | return paravirt_ops.set_wallclock(nowtime); | ||
115 | } | ||
116 | |||
117 | static inline void do_time_init(void) | ||
118 | { | ||
119 | return paravirt_ops.time_init(); | ||
120 | } | ||
121 | |||
122 | /* The paravirtualized CPUID instruction. */ | ||
123 | static inline void __cpuid(unsigned int *eax, unsigned int *ebx, | ||
124 | unsigned int *ecx, unsigned int *edx) | ||
125 | { | ||
126 | paravirt_ops.cpuid(eax, ebx, ecx, edx); | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * These special macros can be used to get or set a debugging register | ||
131 | */ | ||
132 | #define get_debugreg(var, reg) var = paravirt_ops.get_debugreg(reg) | ||
133 | #define set_debugreg(val, reg) paravirt_ops.set_debugreg(reg, val) | ||
134 | |||
135 | #define clts() paravirt_ops.clts() | ||
136 | |||
137 | #define read_cr0() paravirt_ops.read_cr0() | ||
138 | #define write_cr0(x) paravirt_ops.write_cr0(x) | ||
139 | |||
140 | #define read_cr2() paravirt_ops.read_cr2() | ||
141 | #define write_cr2(x) paravirt_ops.write_cr2(x) | ||
142 | |||
143 | #define read_cr3() paravirt_ops.read_cr3() | ||
144 | #define write_cr3(x) paravirt_ops.write_cr3(x) | ||
145 | |||
146 | #define read_cr4() paravirt_ops.read_cr4() | ||
147 | #define read_cr4_safe(x) paravirt_ops.read_cr4_safe() | ||
148 | #define write_cr4(x) paravirt_ops.write_cr4(x) | ||
149 | |||
150 | static inline unsigned long __raw_local_save_flags(void) | ||
151 | { | ||
152 | return paravirt_ops.save_fl(); | ||
153 | } | ||
154 | |||
155 | static inline void raw_local_irq_restore(unsigned long flags) | ||
156 | { | ||
157 | return paravirt_ops.restore_fl(flags); | ||
158 | } | ||
159 | |||
160 | static inline void raw_local_irq_disable(void) | ||
161 | { | ||
162 | paravirt_ops.irq_disable(); | ||
163 | } | ||
164 | |||
165 | static inline void raw_local_irq_enable(void) | ||
166 | { | ||
167 | paravirt_ops.irq_enable(); | ||
168 | } | ||
169 | |||
170 | static inline unsigned long __raw_local_irq_save(void) | ||
171 | { | ||
172 | unsigned long flags = paravirt_ops.save_fl(); | ||
173 | |||
174 | paravirt_ops.irq_disable(); | ||
175 | |||
176 | return flags; | ||
177 | } | ||
178 | |||
179 | static inline void raw_safe_halt(void) | ||
180 | { | ||
181 | paravirt_ops.safe_halt(); | ||
182 | } | ||
183 | |||
184 | static inline void halt(void) | ||
185 | { | ||
186 | paravirt_ops.safe_halt(); | ||
187 | } | ||
188 | #define wbinvd() paravirt_ops.wbinvd() | ||
189 | |||
190 | #define get_kernel_rpl() (paravirt_ops.kernel_rpl) | ||
191 | |||
192 | #define rdmsr(msr,val1,val2) do { \ | ||
193 | int _err; \ | ||
194 | u64 _l = paravirt_ops.read_msr(msr,&_err); \ | ||
195 | val1 = (u32)_l; \ | ||
196 | val2 = _l >> 32; \ | ||
197 | } while(0) | ||
198 | |||
199 | #define wrmsr(msr,val1,val2) do { \ | ||
200 | u64 _l = ((u64)(val2) << 32) | (val1); \ | ||
201 | paravirt_ops.write_msr((msr), _l); \ | ||
202 | } while(0) | ||
203 | |||
204 | #define rdmsrl(msr,val) do { \ | ||
205 | int _err; \ | ||
206 | val = paravirt_ops.read_msr((msr),&_err); \ | ||
207 | } while(0) | ||
208 | |||
209 | #define wrmsrl(msr,val) (paravirt_ops.write_msr((msr),(val))) | ||
210 | #define wrmsr_safe(msr,a,b) ({ \ | ||
211 | u64 _l = ((u64)(b) << 32) | (a); \ | ||
212 | paravirt_ops.write_msr((msr),_l); \ | ||
213 | }) | ||
214 | |||
215 | /* rdmsr with exception handling */ | ||
216 | #define rdmsr_safe(msr,a,b) ({ \ | ||
217 | int _err; \ | ||
218 | u64 _l = paravirt_ops.read_msr(msr,&_err); \ | ||
219 | (*a) = (u32)_l; \ | ||
220 | (*b) = _l >> 32; \ | ||
221 | _err; }) | ||
222 | |||
223 | #define rdtsc(low,high) do { \ | ||
224 | u64 _l = paravirt_ops.read_tsc(); \ | ||
225 | low = (u32)_l; \ | ||
226 | high = _l >> 32; \ | ||
227 | } while(0) | ||
228 | |||
229 | #define rdtscl(low) do { \ | ||
230 | u64 _l = paravirt_ops.read_tsc(); \ | ||
231 | low = (int)_l; \ | ||
232 | } while(0) | ||
233 | |||
234 | #define rdtscll(val) (val = paravirt_ops.read_tsc()) | ||
235 | |||
236 | #define write_tsc(val1,val2) wrmsr(0x10, val1, val2) | ||
237 | |||
238 | #define rdpmc(counter,low,high) do { \ | ||
239 | u64 _l = paravirt_ops.read_pmc(); \ | ||
240 | low = (u32)_l; \ | ||
241 | high = _l >> 32; \ | ||
242 | } while(0) | ||
243 | |||
244 | #define load_TR_desc() (paravirt_ops.load_tr_desc()) | ||
245 | #define load_gdt(dtr) (paravirt_ops.load_gdt(dtr)) | ||
246 | #define load_idt(dtr) (paravirt_ops.load_idt(dtr)) | ||
247 | #define set_ldt(addr, entries) (paravirt_ops.set_ldt((addr), (entries))) | ||
248 | #define store_gdt(dtr) (paravirt_ops.store_gdt(dtr)) | ||
249 | #define store_idt(dtr) (paravirt_ops.store_idt(dtr)) | ||
250 | #define store_tr(tr) ((tr) = paravirt_ops.store_tr()) | ||
251 | #define load_TLS(t,cpu) (paravirt_ops.load_tls((t),(cpu))) | ||
252 | #define write_ldt_entry(dt, entry, low, high) \ | ||
253 | (paravirt_ops.write_ldt_entry((dt), (entry), (low), (high))) | ||
254 | #define write_gdt_entry(dt, entry, low, high) \ | ||
255 | (paravirt_ops.write_gdt_entry((dt), (entry), (low), (high))) | ||
256 | #define write_idt_entry(dt, entry, low, high) \ | ||
257 | (paravirt_ops.write_idt_entry((dt), (entry), (low), (high))) | ||
258 | #define set_iopl_mask(mask) (paravirt_ops.set_iopl_mask(mask)) | ||
259 | |||
260 | /* The paravirtualized I/O functions */ | ||
261 | static inline void slow_down_io(void) { | ||
262 | paravirt_ops.io_delay(); | ||
263 | #ifdef REALLY_SLOW_IO | ||
264 | paravirt_ops.io_delay(); | ||
265 | paravirt_ops.io_delay(); | ||
266 | paravirt_ops.io_delay(); | ||
267 | #endif | ||
268 | } | ||
269 | |||
270 | #define CLI_STRING "pushl %eax; pushl %ecx; pushl %edx; call *paravirt_ops+PARAVIRT_irq_disable; popl %edx; popl %ecx; popl %eax" | ||
271 | #define STI_STRING "pushl %eax; pushl %ecx; pushl %edx; call *paravirt_ops+PARAVIRT_irq_enable; popl %edx; popl %ecx; popl %eax" | ||
272 | #else /* __ASSEMBLY__ */ | ||
273 | |||
274 | #define INTERRUPT_RETURN jmp *%cs:paravirt_ops+PARAVIRT_iret | ||
275 | #define DISABLE_INTERRUPTS pushl %eax; pushl %ecx; pushl %edx; call *paravirt_ops+PARAVIRT_irq_disable; popl %edx; popl %ecx; popl %eax | ||
276 | #define ENABLE_INTERRUPTS pushl %eax; pushl %ecx; pushl %edx; call *%cs:paravirt_ops+PARAVIRT_irq_enable; popl %edx; popl %ecx; popl %eax | ||
277 | #define ENABLE_INTERRUPTS_SYSEXIT jmp *%cs:paravirt_ops+PARAVIRT_irq_enable_sysexit | ||
278 | #define GET_CR0_INTO_EAX call *paravirt_ops+PARAVIRT_read_cr0 | ||
279 | #endif /* __ASSEMBLY__ */ | ||
280 | #endif /* CONFIG_PARAVIRT */ | ||
281 | #endif /* __ASM_PARAVIRT_H */ | ||
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index 98fa73b71760..6c2c4457be0a 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h | |||
@@ -144,8 +144,8 @@ static inline void detect_ht(struct cpuinfo_x86 *c) {} | |||
144 | #define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */ | 144 | #define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */ |
145 | #define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */ | 145 | #define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */ |
146 | 146 | ||
147 | static inline void __cpuid(unsigned int *eax, unsigned int *ebx, | 147 | static inline fastcall void native_cpuid(unsigned int *eax, unsigned int *ebx, |
148 | unsigned int *ecx, unsigned int *edx) | 148 | unsigned int *ecx, unsigned int *edx) |
149 | { | 149 | { |
150 | /* ecx is often an input as well as an output. */ | 150 | /* ecx is often an input as well as an output. */ |
151 | __asm__("cpuid" | 151 | __asm__("cpuid" |
@@ -491,6 +491,12 @@ struct thread_struct { | |||
491 | .io_bitmap = { [ 0 ... IO_BITMAP_LONGS] = ~0 }, \ | 491 | .io_bitmap = { [ 0 ... IO_BITMAP_LONGS] = ~0 }, \ |
492 | } | 492 | } |
493 | 493 | ||
494 | #ifdef CONFIG_PARAVIRT | ||
495 | #include <asm/paravirt.h> | ||
496 | #else | ||
497 | #define paravirt_enabled() 0 | ||
498 | #define __cpuid native_cpuid | ||
499 | |||
494 | static inline void load_esp0(struct tss_struct *tss, struct thread_struct *thread) | 500 | static inline void load_esp0(struct tss_struct *tss, struct thread_struct *thread) |
495 | { | 501 | { |
496 | tss->esp0 = thread->esp0; | 502 | tss->esp0 = thread->esp0; |
@@ -524,10 +530,13 @@ static inline void load_esp0(struct tss_struct *tss, struct thread_struct *threa | |||
524 | : /* no output */ \ | 530 | : /* no output */ \ |
525 | :"r" (value)) | 531 | :"r" (value)) |
526 | 532 | ||
533 | #define set_iopl_mask native_set_iopl_mask | ||
534 | #endif /* CONFIG_PARAVIRT */ | ||
535 | |||
527 | /* | 536 | /* |
528 | * Set IOPL bits in EFLAGS from given mask | 537 | * Set IOPL bits in EFLAGS from given mask |
529 | */ | 538 | */ |
530 | static inline void set_iopl_mask(unsigned mask) | 539 | static fastcall inline void native_set_iopl_mask(unsigned mask) |
531 | { | 540 | { |
532 | unsigned int reg; | 541 | unsigned int reg; |
533 | __asm__ __volatile__ ("pushfl;" | 542 | __asm__ __volatile__ ("pushfl;" |
diff --git a/include/asm-i386/segment.h b/include/asm-i386/segment.h index 5bdda79b6b53..3c796af33776 100644 --- a/include/asm-i386/segment.h +++ b/include/asm-i386/segment.h | |||
@@ -131,5 +131,7 @@ | |||
131 | #define SEGMENT_LDT 0x4 | 131 | #define SEGMENT_LDT 0x4 |
132 | #define SEGMENT_GDT 0x0 | 132 | #define SEGMENT_GDT 0x0 |
133 | 133 | ||
134 | #ifndef CONFIG_PARAVIRT | ||
134 | #define get_kernel_rpl() 0 | 135 | #define get_kernel_rpl() 0 |
135 | #endif | 136 | #endif |
137 | #endif | ||
diff --git a/include/asm-i386/setup.h b/include/asm-i386/setup.h index 2734909eff84..9930c5a355fc 100644 --- a/include/asm-i386/setup.h +++ b/include/asm-i386/setup.h | |||
@@ -70,6 +70,7 @@ extern unsigned char boot_params[PARAM_SIZE]; | |||
70 | struct e820entry; | 70 | struct e820entry; |
71 | 71 | ||
72 | char * __init machine_specific_memory_setup(void); | 72 | char * __init machine_specific_memory_setup(void); |
73 | char *memory_setup(void); | ||
73 | 74 | ||
74 | int __init copy_e820_map(struct e820entry * biosmap, int nr_map); | 75 | int __init copy_e820_map(struct e820entry * biosmap, int nr_map); |
75 | int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map); | 76 | int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map); |
diff --git a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h index c18b71fae6b3..dea60709db29 100644 --- a/include/asm-i386/spinlock.h +++ b/include/asm-i386/spinlock.h | |||
@@ -7,8 +7,12 @@ | |||
7 | #include <asm/processor.h> | 7 | #include <asm/processor.h> |
8 | #include <linux/compiler.h> | 8 | #include <linux/compiler.h> |
9 | 9 | ||
10 | #ifdef CONFIG_PARAVIRT | ||
11 | #include <asm/paravirt.h> | ||
12 | #else | ||
10 | #define CLI_STRING "cli" | 13 | #define CLI_STRING "cli" |
11 | #define STI_STRING "sti" | 14 | #define STI_STRING "sti" |
15 | #endif /* CONFIG_PARAVIRT */ | ||
12 | 16 | ||
13 | /* | 17 | /* |
14 | * Your basic SMP spinlocks, allowing only a single CPU anywhere | 18 | * Your basic SMP spinlocks, allowing only a single CPU anywhere |
diff --git a/include/asm-i386/suspend.h b/include/asm-i386/suspend.h index 08be1e5009d4..30361526d568 100644 --- a/include/asm-i386/suspend.h +++ b/include/asm-i386/suspend.h | |||
@@ -23,12 +23,8 @@ arch_prepare_suspend(void) | |||
23 | struct saved_context { | 23 | struct saved_context { |
24 | u16 es, fs, gs, ss; | 24 | u16 es, fs, gs, ss; |
25 | unsigned long cr0, cr2, cr3, cr4; | 25 | unsigned long cr0, cr2, cr3, cr4; |
26 | u16 gdt_pad; | 26 | struct Xgt_desc_struct gdt; |
27 | u16 gdt_limit; | 27 | struct Xgt_desc_struct idt; |
28 | unsigned long gdt_base; | ||
29 | u16 idt_pad; | ||
30 | u16 idt_limit; | ||
31 | unsigned long idt_base; | ||
32 | u16 ldt; | 28 | u16 ldt; |
33 | u16 tss; | 29 | u16 tss; |
34 | unsigned long tr; | 30 | unsigned long tr; |
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h index a6dabbcd6e6a..a6d20d9a1a30 100644 --- a/include/asm-i386/system.h +++ b/include/asm-i386/system.h | |||
@@ -88,6 +88,9 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t" \ | |||
88 | #define savesegment(seg, value) \ | 88 | #define savesegment(seg, value) \ |
89 | asm volatile("mov %%" #seg ",%0":"=rm" (value)) | 89 | asm volatile("mov %%" #seg ",%0":"=rm" (value)) |
90 | 90 | ||
91 | #ifdef CONFIG_PARAVIRT | ||
92 | #include <asm/paravirt.h> | ||
93 | #else | ||
91 | #define read_cr0() ({ \ | 94 | #define read_cr0() ({ \ |
92 | unsigned int __dummy; \ | 95 | unsigned int __dummy; \ |
93 | __asm__ __volatile__( \ | 96 | __asm__ __volatile__( \ |
@@ -139,17 +142,18 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t" \ | |||
139 | #define write_cr4(x) \ | 142 | #define write_cr4(x) \ |
140 | __asm__ __volatile__("movl %0,%%cr4": :"r" (x)) | 143 | __asm__ __volatile__("movl %0,%%cr4": :"r" (x)) |
141 | 144 | ||
142 | /* | 145 | #define wbinvd() \ |
143 | * Clear and set 'TS' bit respectively | 146 | __asm__ __volatile__ ("wbinvd": : :"memory") |
144 | */ | 147 | |
148 | /* Clear the 'TS' bit */ | ||
145 | #define clts() __asm__ __volatile__ ("clts") | 149 | #define clts() __asm__ __volatile__ ("clts") |
150 | #endif/* CONFIG_PARAVIRT */ | ||
151 | |||
152 | /* Set the 'TS' bit */ | ||
146 | #define stts() write_cr0(8 | read_cr0()) | 153 | #define stts() write_cr0(8 | read_cr0()) |
147 | 154 | ||
148 | #endif /* __KERNEL__ */ | 155 | #endif /* __KERNEL__ */ |
149 | 156 | ||
150 | #define wbinvd() \ | ||
151 | __asm__ __volatile__ ("wbinvd": : :"memory") | ||
152 | |||
153 | static inline unsigned long get_limit(unsigned long segment) | 157 | static inline unsigned long get_limit(unsigned long segment) |
154 | { | 158 | { |
155 | unsigned long __limit; | 159 | unsigned long __limit; |
diff --git a/include/asm-i386/time.h b/include/asm-i386/time.h new file mode 100644 index 000000000000..ea8065af825a --- /dev/null +++ b/include/asm-i386/time.h | |||
@@ -0,0 +1,41 @@ | |||
1 | #ifndef _ASMi386_TIME_H | ||
2 | #define _ASMi386_TIME_H | ||
3 | |||
4 | #include <linux/efi.h> | ||
5 | #include "mach_time.h" | ||
6 | |||
7 | static inline unsigned long native_get_wallclock(void) | ||
8 | { | ||
9 | unsigned long retval; | ||
10 | |||
11 | if (efi_enabled) | ||
12 | retval = efi_get_time(); | ||
13 | else | ||
14 | retval = mach_get_cmos_time(); | ||
15 | |||
16 | return retval; | ||
17 | } | ||
18 | |||
19 | static inline int native_set_wallclock(unsigned long nowtime) | ||
20 | { | ||
21 | int retval; | ||
22 | |||
23 | if (efi_enabled) | ||
24 | retval = efi_set_rtc_mmss(nowtime); | ||
25 | else | ||
26 | retval = mach_set_rtc_mmss(nowtime); | ||
27 | |||
28 | return retval; | ||
29 | } | ||
30 | |||
31 | #ifdef CONFIG_PARAVIRT | ||
32 | #include <asm/paravirt.h> | ||
33 | #else /* !CONFIG_PARAVIRT */ | ||
34 | |||
35 | #define get_wallclock() native_get_wallclock() | ||
36 | #define set_wallclock(x) native_set_wallclock(x) | ||
37 | #define do_time_init() time_init_hook() | ||
38 | |||
39 | #endif /* CONFIG_PARAVIRT */ | ||
40 | |||
41 | #endif | ||