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#include <linux/highmem.h>
23
24#include <asm/bug.h>
25#include <asm/paravirt.h>
26#include <asm/desc.h>
27#include <asm/setup.h>
28#include <asm/arch_hooks.h>
29#include <asm/time.h>
30#include <asm/irq.h>
31#include <asm/delay.h>
32#include <asm/fixmap.h>
33#include <asm/apic.h>
34#include <asm/tlbflush.h>
35#include <asm/timer.h>
36
37/* nop stub */
38void _paravirt_nop(void)
39{
40}
41
42static void __init default_banner(void)
43{
44	printk(KERN_INFO "Booting paravirtualized kernel on %s\n",
45	       paravirt_ops.name);
46}
47
48char *memory_setup(void)
49{
50	return paravirt_ops.memory_setup();
51}
52
53/* Simple instruction patching code. */
54#define DEF_NATIVE(name, code)					\
55	extern const char start_##name[], end_##name[];		\
56	asm("start_" #name ": " code "; end_" #name ":")
57
58DEF_NATIVE(irq_disable, "cli");
59DEF_NATIVE(irq_enable, "sti");
60DEF_NATIVE(restore_fl, "push %eax; popf");
61DEF_NATIVE(save_fl, "pushf; pop %eax");
62DEF_NATIVE(iret, "iret");
63DEF_NATIVE(irq_enable_sysexit, "sti; sysexit");
64DEF_NATIVE(read_cr2, "mov %cr2, %eax");
65DEF_NATIVE(write_cr3, "mov %eax, %cr3");
66DEF_NATIVE(read_cr3, "mov %cr3, %eax");
67DEF_NATIVE(clts, "clts");
68DEF_NATIVE(read_tsc, "rdtsc");
69
70DEF_NATIVE(ud2a, "ud2a");
71
72static unsigned native_patch(u8 type, u16 clobbers, void *insns, unsigned len)
73{
74	const unsigned char *start, *end;
75	unsigned ret;
76
77	switch(type) {
78#define SITE(x)	case PARAVIRT_PATCH(x):	start = start_##x; end = end_##x; goto patch_site
79		SITE(irq_disable);
80		SITE(irq_enable);
81		SITE(restore_fl);
82		SITE(save_fl);
83		SITE(iret);
84		SITE(irq_enable_sysexit);
85		SITE(read_cr2);
86		SITE(read_cr3);
87		SITE(write_cr3);
88		SITE(clts);
89		SITE(read_tsc);
90#undef SITE
91
92	patch_site:
93		ret = paravirt_patch_insns(insns, len, start, end);
94		break;
95
96	case PARAVIRT_PATCH(make_pgd):
97	case PARAVIRT_PATCH(make_pte):
98	case PARAVIRT_PATCH(pgd_val):
99	case PARAVIRT_PATCH(pte_val):
100#ifdef CONFIG_X86_PAE
101	case PARAVIRT_PATCH(make_pmd):
102	case PARAVIRT_PATCH(pmd_val):
103#endif
104		/* These functions end up returning exactly what
105		   they're passed, in the same registers. */
106		ret = paravirt_patch_nop();
107		break;
108
109	default:
110		ret = paravirt_patch_default(type, clobbers, insns, len);
111		break;
112	}
113
114	return ret;
115}
116
117unsigned paravirt_patch_nop(void)
118{
119	return 0;
120}
121
122unsigned paravirt_patch_ignore(unsigned len)
123{
124	return len;
125}
126
127unsigned paravirt_patch_call(void *target, u16 tgt_clobbers,
128			     void *site, u16 site_clobbers,
129			     unsigned len)
130{
131	unsigned char *call = site;
132	unsigned long delta = (unsigned long)target - (unsigned long)(call+5);
133
134	if (tgt_clobbers & ~site_clobbers)
135		return len;	/* target would clobber too much for this site */
136	if (len < 5)
137		return len;	/* call too long for patch site */
138
139	*call++ = 0xe8;		/* call */
140	*(unsigned long *)call = delta;
141
142	return 5;
143}
144
145unsigned paravirt_patch_jmp(void *target, void *site, unsigned len)
146{
147	unsigned char *jmp = site;
148	unsigned long delta = (unsigned long)target - (unsigned long)(jmp+5);
149
150	if (len < 5)
151		return len;	/* call too long for patch site */
152
153	*jmp++ = 0xe9;		/* jmp */
154	*(unsigned long *)jmp = delta;
155
156	return 5;
157}
158
159unsigned paravirt_patch_default(u8 type, u16 clobbers, void *site, unsigned len)
160{
161	void *opfunc = *((void **)&paravirt_ops + type);
162	unsigned ret;
163
164	if (opfunc == NULL)
165		/* If there's no function, patch it with a ud2a (BUG) */
166		ret = paravirt_patch_insns(site, len, start_ud2a, end_ud2a);
167	else if (opfunc == paravirt_nop)
168		/* If the operation is a nop, then nop the callsite */
169		ret = paravirt_patch_nop();
170	else if (type == PARAVIRT_PATCH(iret) ||
171		 type == PARAVIRT_PATCH(irq_enable_sysexit))
172		/* If operation requires a jmp, then jmp */
173		ret = paravirt_patch_jmp(opfunc, site, len);
174	else
175		/* Otherwise call the function; assume target could
176		   clobber any caller-save reg */
177		ret = paravirt_patch_call(opfunc, CLBR_ANY,
178					  site, clobbers, len);
179
180	return ret;
181}
182
183unsigned paravirt_patch_insns(void *site, unsigned len,
184			      const char *start, const char *end)
185{
186	unsigned insn_len = end - start;
187
188	if (insn_len > len || start == NULL)
189		insn_len = len;
190	else
191		memcpy(site, start, insn_len);
192
193	return insn_len;
194}
195
196void init_IRQ(void)
197{
198	paravirt_ops.init_IRQ();
199}
200
201static void native_flush_tlb(void)
202{
203	__native_flush_tlb();
204}
205
206/*
207 * Global pages have to be flushed a bit differently. Not a real
208 * performance problem because this does not happen often.
209 */
210static void native_flush_tlb_global(void)
211{
212	__native_flush_tlb_global();
213}
214
215static void native_flush_tlb_single(unsigned long addr)
216{
217	__native_flush_tlb_single(addr);
218}
219
220/* These are in entry.S */
221extern void native_iret(void);
222extern void native_irq_enable_sysexit(void);
223
224static int __init print_banner(void)
225{
226	paravirt_ops.banner();
227	return 0;
228}
229core_initcall(print_banner);
230
231struct paravirt_ops paravirt_ops = {
232	.name = "bare hardware",
233	.paravirt_enabled = 0,
234	.kernel_rpl = 0,
235	.shared_kernel_pmd = 1,	/* Only used when CONFIG_X86_PAE is set */
236
237 	.patch = native_patch,
238	.banner = default_banner,
239	.arch_setup = paravirt_nop,
240	.memory_setup = machine_specific_memory_setup,
241	.get_wallclock = native_get_wallclock,
242	.set_wallclock = native_set_wallclock,
243	.time_init = hpet_time_init,
244	.init_IRQ = native_init_IRQ,
245
246	.cpuid = native_cpuid,
247	.get_debugreg = native_get_debugreg,
248	.set_debugreg = native_set_debugreg,
249	.clts = native_clts,
250	.read_cr0 = native_read_cr0,
251	.write_cr0 = native_write_cr0,
252	.read_cr2 = native_read_cr2,
253	.write_cr2 = native_write_cr2,
254	.read_cr3 = native_read_cr3,
255	.write_cr3 = native_write_cr3,
256	.read_cr4 = native_read_cr4,
257	.read_cr4_safe = native_read_cr4_safe,
258	.write_cr4 = native_write_cr4,
259	.save_fl = native_save_fl,
260	.restore_fl = native_restore_fl,
261	.irq_disable = native_irq_disable,
262	.irq_enable = native_irq_enable,
263	.safe_halt = native_safe_halt,
264	.halt = native_halt,
265	.wbinvd = native_wbinvd,
266	.read_msr = native_read_msr_safe,
267	.write_msr = native_write_msr_safe,
268	.read_tsc = native_read_tsc,
269	.read_pmc = native_read_pmc,
270	.get_scheduled_cycles = native_read_tsc,
271	.get_cpu_khz = native_calculate_cpu_khz,
272	.load_tr_desc = native_load_tr_desc,
273	.set_ldt = native_set_ldt,
274	.load_gdt = native_load_gdt,
275	.load_idt = native_load_idt,
276	.store_gdt = native_store_gdt,
277	.store_idt = native_store_idt,
278	.store_tr = native_store_tr,
279	.load_tls = native_load_tls,
280	.write_ldt_entry = write_dt_entry,
281	.write_gdt_entry = write_dt_entry,
282	.write_idt_entry = write_dt_entry,
283	.load_esp0 = native_load_esp0,
284
285	.set_iopl_mask = native_set_iopl_mask,
286	.io_delay = native_io_delay,
287
288#ifdef CONFIG_X86_LOCAL_APIC
289	.apic_write = native_apic_write,
290	.apic_write_atomic = native_apic_write_atomic,
291	.apic_read = native_apic_read,
292	.setup_boot_clock = setup_boot_APIC_clock,
293	.setup_secondary_clock = setup_secondary_APIC_clock,
294	.startup_ipi_hook = paravirt_nop,
295#endif
296	.set_lazy_mode = paravirt_nop,
297
298	.pagetable_setup_start = native_pagetable_setup_start,
299	.pagetable_setup_done = native_pagetable_setup_done,
300
301	.flush_tlb_user = native_flush_tlb,
302	.flush_tlb_kernel = native_flush_tlb_global,
303	.flush_tlb_single = native_flush_tlb_single,
304	.flush_tlb_others = native_flush_tlb_others,
305
306	.alloc_pt = paravirt_nop,
307	.alloc_pd = paravirt_nop,
308	.alloc_pd_clone = paravirt_nop,
309	.release_pt = paravirt_nop,
310	.release_pd = paravirt_nop,
311
312	.set_pte = native_set_pte,
313	.set_pte_at = native_set_pte_at,
314	.set_pmd = native_set_pmd,
315	.pte_update = paravirt_nop,
316	.pte_update_defer = paravirt_nop,
317
318#ifdef CONFIG_HIGHPTE
319	.kmap_atomic_pte = kmap_atomic,
320#endif
321
322#ifdef CONFIG_X86_PAE
323	.set_pte_atomic = native_set_pte_atomic,
324	.set_pte_present = native_set_pte_present,
325	.set_pud = native_set_pud,
326	.pte_clear = native_pte_clear,
327	.pmd_clear = native_pmd_clear,
328
329	.pmd_val = native_pmd_val,
330	.make_pmd = native_make_pmd,
331#endif
332
333	.pte_val = native_pte_val,
334	.pgd_val = native_pgd_val,
335
336	.make_pte = native_make_pte,
337	.make_pgd = native_make_pgd,
338
339	.irq_enable_sysexit = native_irq_enable_sysexit,
340	.iret = native_iret,
341
342	.dup_mmap = paravirt_nop,
343	.exit_mmap = paravirt_nop,
344	.activate_mm = paravirt_nop,
345};
346
347EXPORT_SYMBOL(paravirt_ops);
348