I'd expect (1) higher-level additions to paravirt_ops, and (2) binary patching similar to the VMI patches for interrupt operations. Name: Function Call Abstraction for Paravirtualization Status: Booted on 2.6.16-rc2-git7 Depends: Paravirt/abstract-sensitive.patch.gz Signed-off-by: Rusty Russell <rusty@xxxxxxxxxxxxxxx> 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. diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .10486-linux-2.6.17-rc2-git7/arch/i386/Kconfig .10486-linux-2.6.17-rc2-git7.updated/arch/i386/Kconfig --- .10486-linux-2.6.17-rc2-git7/arch/i386/Kconfig 2006-04-21 12:05:02.000000000 +1000 +++ .10486-linux-2.6.17-rc2-git7.updated/arch/i386/Kconfig 2006-05-03 19:21:43.000000000 +1000 @@ -169,6 +169,17 @@ config X86_ES7000 endchoice +config PARAVIRT + bool "Paravirtualization support (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + Paravirtualization is a way of running multiple instances of + Linux on the same machine, under a hypervisor. This option + changes the kernel so it can modify itself when it is run + under a hypervisor, improving performance significantly. + However, when run without a hypervisor the kernel is + marginally slower. If in doubt, say N. + config ACPI_SRAT bool default y diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .10486-linux-2.6.17-rc2-git7/arch/i386/kernel/Makefile .10486-linux-2.6.17-rc2-git7.updated/arch/i386/kernel/Makefile --- .10486-linux-2.6.17-rc2-git7/arch/i386/kernel/Makefile 2006-04-21 12:05:02.000000000 +1000 +++ .10486-linux-2.6.17-rc2-git7.updated/arch/i386/kernel/Makefile 2006-05-03 19:21:43.000000000 +1000 @@ -37,6 +37,7 @@ obj-$(CONFIG_EFI) += efi.o efi_stub.o obj-$(CONFIG_DOUBLEFAULT) += doublefault.o obj-$(CONFIG_VM86) += vm86.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o +obj-$(CONFIG_PARAVIRT) += paravirt.o EXTRA_AFLAGS := -traditional diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .10486-linux-2.6.17-rc2-git7/arch/i386/kernel/asm-offsets.c .10486-linux-2.6.17-rc2-git7.updated/arch/i386/kernel/asm-offsets.c --- .10486-linux-2.6.17-rc2-git7/arch/i386/kernel/asm-offsets.c 2005-07-15 04:38:36.000000000 +1000 +++ .10486-linux-2.6.17-rc2-git7.updated/arch/i386/kernel/asm-offsets.c 2006-05-03 19:21:43.000000000 +1000 @@ -13,6 +13,7 @@ #include <asm/fixmap.h> #include <asm/processor.h> #include <asm/thread_info.h> +#include <asm/paravirt.h> #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) @@ -69,4 +70,15 @@ void foo(void) DEFINE(PAGE_SIZE_asm, PAGE_SIZE); DEFINE(VSYSCALL_BASE, __fix_to_virt(FIX_VSYSCALL)); + +#ifdef CONFIG_PARAVIRT + OFFSET(PARAVIRT_irq_disable, paravirt_ops, irq_disable); + OFFSET(PARAVIRT_irq_enable, paravirt_ops, irq_enable); + OFFSET(PARAVIRT_irq_enable_sysexit, paravirt_ops, irq_enable_sysexit); + OFFSET(PARAVIRT_iret, paravirt_ops, iret); + OFFSET(PARAVIRT_read_cr0, paravirt_ops, read_cr0); + OFFSET(PARAVIRT_read_msr, paravirt_ops, read_msr); + OFFSET(PARAVIRT_write_msr, paravirt_ops, write_msr); + OFFSET(PARAVIRT_cpuid, paravirt_ops, cpuid); +#endif } diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .10486-linux-2.6.17-rc2-git7/arch/i386/kernel/entry.S .10486-linux-2.6.17-rc2-git7.updated/arch/i386/kernel/entry.S --- .10486-linux-2.6.17-rc2-git7/arch/i386/kernel/entry.S 2006-05-03 19:21:43.000000000 +1000 +++ .10486-linux-2.6.17-rc2-git7.updated/arch/i386/kernel/entry.S 2006-05-03 19:21:44.000000000 +1000 @@ -592,6 +592,16 @@ nmi_16bit_stack: .align 4 .long 1b,iret_exc .previous + + +#ifdef CONFIG_PARAVIRT +ENTRY(nopara_iret) + iret + +ENTRY(nopara_irq_enable_sysexit) + sti + sysexit +#endif KPROBE_ENTRY(int3) pushl $-1 # mark this as an int diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .10486-linux-2.6.17-rc2-git7/arch/i386/kernel/paravirt.c .10486-linux-2.6.17-rc2-git7.updated/arch/i386/kernel/paravirt.c --- .10486-linux-2.6.17-rc2-git7/arch/i386/kernel/paravirt.c 1970-01-01 10:00:00.000000000 +1000 +++ .10486-linux-2.6.17-rc2-git7.updated/arch/i386/kernel/paravirt.c 2006-05-03 19:21:44.000000000 +1000 @@ -0,0 +1,382 @@ +/* Paravirtualization interfaces + Copyright (C) 2006 Rusty Russell IBM Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include <linux/errno.h> +#include <linux/module.h> +#include <asm/bug.h> +#include <asm/paravirt.h> +#include <asm/desc.h> + +static void nopara_cpuid(unsigned int *eax, unsigned int *ebx, + unsigned int *ecx, unsigned int *edx) +{ + __asm__("cpuid" + : "=a" (*eax), + "=b" (*ebx), + "=c" (*ecx), + "=d" (*edx) + : "0" (*eax), "2" (*ecx)); +} + +static unsigned int nopara_get_debugreg(int regno) +{ + unsigned int val = 0; /* Damn you, gcc! */ + + switch (regno) { + case 0: + __asm__("movl %%db0, %0" :"=r" (val)); break; + case 1: + __asm__("movl %%db1, %0" :"=r" (val)); break; + case 2: + __asm__("movl %%db2, %0" :"=r" (val)); break; + case 3: + __asm__("movl %%db3, %0" :"=r" (val)); break; + case 4: + __asm__("movl %%db4, %0" :"=r" (val)); break; + case 5: + __asm__("movl %%db5, %0" :"=r" (val)); break; + case 6: + __asm__("movl %%db6, %0" :"=r" (val)); break; + case 7: + __asm__("movl %%db7, %0" :"=r" (val)); break; + default: + BUG(); + } + return val; +} + +static void nopara_set_debugreg(int regno, unsigned int value) +{ + switch (regno) { + case 0: + __asm__("movl %0,%%db0" : /* no output */ :"r" (value)); + break; + case 1: + __asm__("movl %0,%%db1" : /* no output */ :"r" (value)); + break; + case 2: + __asm__("movl %0,%%db2" : /* no output */ :"r" (value)); + break; + case 3: + __asm__("movl %0,%%db3" : /* no output */ :"r" (value)); + break; + case 4: + __asm__("movl %0,%%db4" : /* no output */ :"r" (value)); + break; + case 5: + __asm__("movl %0,%%db5" : /* no output */ :"r" (value)); + break; + case 6: + __asm__("movl %0,%%db6" : /* no output */ :"r" (value)); + break; + case 7: + __asm__("movl %0,%%db7" : /* no output */ :"r" (value)); + break; + default: + BUG(); + } +} + +static void nopara_sync_core(void) +{ + unsigned int eax = 1, ebx, ecx, edx; + nopara_cpuid(&eax, &ebx, &ecx, &edx); +} + +static void nopara_clts(void) +{ + __asm__ __volatile__ ("clts"); +} + +static unsigned int nopara_read_cr0(void) +{ + unsigned int val; + __asm__ __volatile__("movl %%cr0,%0\n\t" :"=r" (val)); + return val; +} + +static void nopara_write_cr0(unsigned int val) +{ + __asm__ __volatile__("movl %0,%%cr0": :"r" (val)); +} + +static unsigned int nopara_read_cr2(void) +{ + unsigned int val; + __asm__ __volatile__("movl %%cr2,%0\n\t" :"=r" (val)); + return val; +} + +static void nopara_write_cr2(unsigned int val) +{ + __asm__ __volatile__("movl %0,%%cr2": :"r" (val)); +} + +static unsigned int nopara_read_cr3(void) +{ + unsigned int val; + __asm__ __volatile__("movl %%cr3,%0\n\t" :"=r" (val)); + return val; +} + +static void nopara_write_cr3(unsigned int val) +{ + __asm__ __volatile__("movl %0,%%cr3": :"r" (val)); +} + +static unsigned int nopara_read_cr4(void) +{ + unsigned int val; + __asm__ __volatile__("movl %%cr4,%0\n\t" :"=r" (val)); + return val; +} + +static unsigned int nopara_read_cr4_safe(void) +{ + unsigned int val; + /* This could fault if %cr4 does not exist */ + __asm__("1: movl %%cr4, %0 \n" + "2: \n" + ".section __ex_table,\"a\" \n" + ".long 1b,2b \n" + ".previous \n" + : "=r" (val): "0" (0)); + return val; +} + +static void nopara_write_cr4(unsigned int val) +{ + __asm__ __volatile__("movl %0,%%cr4": :"r" (val)); +} + +static unsigned long nopara_save_fl(void) +{ + unsigned long f; + __asm__ __volatile__("pushfl ; popl %0":"=g" (f): /* no input */); + return f; +} + +static void nopara_restore_fl(unsigned long f) +{ + __asm__ __volatile__("pushl %0 ; popfl": /* no output */ + :"g" (f) + :"memory", "cc"); +} + +static void nopara_irq_disable(void) +{ + __asm__ __volatile__("cli": : :"memory"); +} + +static void nopara_irq_enable(void) +{ + __asm__ __volatile__("sti": : :"memory"); +} + +static void nopara_safe_halt(void) +{ + __asm__ __volatile__("sti; hlt": : :"memory"); +} + +static void nopara_halt(void) +{ + __asm__ __volatile__("hlt": : :"memory"); +} + +static void nopara_wbinvd(void) +{ + __asm__ __volatile__("wbinvd": : :"memory"); +} + +static unsigned long long nopara_read_msr(unsigned int msr, int *err) +{ + unsigned long long val; + + asm volatile("2: rdmsr ; xorl %0,%0\n" + "1:\n\t" + ".section .fixup,\"ax\"\n\t" + "3: movl %3,%0 ; jmp 1b\n\t" + ".previous\n\t" + ".section __ex_table,\"a\"\n" + " .align 4\n\t" + " .long 2b,3b\n\t" + ".previous" + : "=r" (*err), "=A" (val) + : "c" (msr), "i" (-EFAULT)); + + return val; +} + +static int nopara_write_msr(unsigned int msr, unsigned long long val) +{ + int err; + asm volatile("2: wrmsr ; xorl %0,%0\n" + "1:\n\t" + ".section .fixup,\"ax\"\n\t" + "3: movl %3,%0 ; jmp 1b\n\t" + ".previous\n\t" + ".section __ex_table,\"a\"\n" + " .align 4\n\t" + " .long 2b,3b\n\t" + ".previous" + : "=a" (err) + : "c" (msr), "0" ((int)val), "d" ((int)(val>>32)), + "i" (-EFAULT)); + return err; +} + +static unsigned long long nopara_read_tsc(void) +{ + unsigned long long val; + __asm__ __volatile__("rdtsc" : "=A" (val)); + return val; +} + +static unsigned long long nopara_read_pmc(void) +{ + unsigned long long val; + __asm__ __volatile__("rdpmc" : "=A" (val)); + return val; +} + +static void nopara_load_tr_desc(void) +{ + __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8)); +} + +static void nopara_load_ldt_desc(void) +{ + __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8)); +} + +static void nopara_load_gdt(const struct Xgt_desc_struct *dtr) +{ + __asm__ __volatile("lgdt %0"::"m" (*dtr)); +} + +static void nopara_load_idt(const struct Xgt_desc_struct *dtr) +{ + __asm__ __volatile("lidt %0"::"m" (*dtr)); +} + +static void nopara_store_gdt(struct Xgt_desc_struct *dtr) +{ + __asm__ ("sgdt %0":"=m" (*dtr)); +} + +static void nopara_store_idt(struct Xgt_desc_struct *dtr) +{ + __asm__ ("sidt %0":"=m" (*dtr)); +} + +static unsigned long nopara_store_tr(void) +{ + unsigned long tr; + __asm__ ("str %0":"=m" (tr)); + return tr; +} + +static void nopara_load_tls(struct thread_struct *t, unsigned int cpu) +{ +#define C(i) get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i] + C(0); C(1); C(2); +#undef C +} + +static inline void write_dt_entry(void *dt, int entry, __u32 entry_a, __u32 entry_b) +{ + __u32 *lp = (__u32 *)((char *)dt + entry*8); + *lp = entry_a; + *(lp+1) = entry_b; +} + +static void nopara_write_ldt_entry(void *dt, int entrynum, u64 entry) +{ + write_dt_entry(dt, entrynum, entry >> 32, entry); +} + +static void nopara_write_gdt_entry(void *dt, int entrynum, u64 entry) +{ + write_dt_entry(dt, entrynum, entry >> 32, entry); +} + +static void nopara_write_idt_entry(void *dt, int entrynum, u64 entry) +{ + write_dt_entry(dt, entrynum, entry >> 32, entry); +} + +static void nopara_set_iopl_mask(unsigned mask) +{ + unsigned int reg; + __asm__ __volatile__ ("pushfl;" + "popl %0;" + "andl %1, %0;" + "orl %2, %0;" + "pushl %0;" + "popfl" + : "=&r" (reg) + : "i" (~X86_EFLAGS_IOPL), "r" (mask)); +} + +/* These are in entry.S */ +extern void nopara_iret(void); +extern void nopara_irq_enable_sysexit(void); + +struct paravirt_ops paravirt_ops = { + .kernel_rpl = 0, + .cpuid = nopara_cpuid, + .get_debugreg = nopara_get_debugreg, + .set_debugreg = nopara_set_debugreg, + .sync_core = nopara_sync_core, + .clts = nopara_clts, + .read_cr0 = nopara_read_cr0, + .write_cr0 = nopara_write_cr0, + .read_cr2 = nopara_read_cr2, + .write_cr2 = nopara_write_cr2, + .read_cr3 = nopara_read_cr3, + .write_cr3 = nopara_write_cr3, + .read_cr4 = nopara_read_cr4, + .read_cr4_safe = nopara_read_cr4_safe, + .write_cr4 = nopara_write_cr4, + .save_fl = nopara_save_fl, + .restore_fl = nopara_restore_fl, + .irq_disable = nopara_irq_disable, + .irq_enable = nopara_irq_enable, + .safe_halt = nopara_safe_halt, + .halt = nopara_halt, + .wbinvd = nopara_wbinvd, + .read_msr = nopara_read_msr, + .write_msr = nopara_write_msr, + .read_tsc = nopara_read_tsc, + .read_pmc = nopara_read_pmc, + .load_tr_desc = nopara_load_tr_desc, + .load_ldt_desc = nopara_load_ldt_desc, + .load_gdt = nopara_load_gdt, + .load_idt = nopara_load_idt, + .store_gdt = nopara_store_gdt, + .store_idt = nopara_store_idt, + .store_tr = nopara_store_tr, + .load_tls = nopara_load_tls, + .write_ldt_entry = nopara_write_ldt_entry, + .write_gdt_entry = nopara_write_gdt_entry, + .write_idt_entry = nopara_write_idt_entry, + + .set_iopl_mask = nopara_set_iopl_mask, + .irq_enable_sysexit = nopara_irq_enable_sysexit, + .iret = nopara_iret, +}; +EXPORT_SYMBOL_GPL(paravirt_ops); diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .10486-linux-2.6.17-rc2-git7/include/asm-i386/msr.h .10486-linux-2.6.17-rc2-git7.updated/include/asm-i386/msr.h --- .10486-linux-2.6.17-rc2-git7/include/asm-i386/msr.h 2006-03-23 12:43:10.000000000 +1100 +++ .10486-linux-2.6.17-rc2-git7.updated/include/asm-i386/msr.h 2006-05-03 19:21:44.000000000 +1000 @@ -1,6 +1,10 @@ #ifndef __ASM_MSR_H #define __ASM_MSR_H +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#else + /* * Access to machine-specific registers (available on 586 and better only) * Note: the rd* operations modify the parameters directly (without using @@ -77,6 +81,7 @@ static inline void wrmsrl (unsigned long __asm__ __volatile__("rdpmc" \ : "=a" (low), "=d" (high) \ : "c" (counter)) +#endif /* !CONFIG_PARAVIRT */ /* symbolic names for some interesting MSRs */ /* Intel defined MSRs. */ diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .10486-linux-2.6.17-rc2-git7/include/asm-i386/paravirt.h .10486-linux-2.6.17-rc2-git7.updated/include/asm-i386/paravirt.h --- .10486-linux-2.6.17-rc2-git7/include/asm-i386/paravirt.h 2006-05-03 19:21:43.000000000 +1000 +++ .10486-linux-2.6.17-rc2-git7.updated/include/asm-i386/paravirt.h 2006-05-03 19:21:44.000000000 +1000 @@ -2,6 +2,214 @@ #define __ASM_PARAVIRT_H /* Various instructions on x86 need to be replaced for * para-virtualization: those hooks are defined here. */ +#include <linux/config.h> + +#ifndef CONFIG_PARAVIRT #include <asm/no_paravirt.h> +#else + +#ifndef __ASSEMBLY__ +struct thread_struct; +struct Xgt_desc_struct; +struct paravirt_ops +{ + unsigned int kernel_rpl; + + void (*cpuid)(unsigned int *eax, unsigned int *ebx, + unsigned int *ecx, unsigned int *edx); + + unsigned int (*get_debugreg)(int regno); + void (*set_debugreg)(int regno, unsigned int value); + + void (*sync_core)(void); + + void (*clts)(void); + + unsigned int (*read_cr0)(void); + void (*write_cr0)(unsigned int); + + unsigned int (*read_cr2)(void); + void (*write_cr2)(unsigned int); + + unsigned int (*read_cr3)(void); + void (*write_cr3)(unsigned int); + + unsigned int (*read_cr4_safe)(void); + unsigned int (*read_cr4)(void); + void (*write_cr4)(unsigned int); + + unsigned long (*save_fl)(void); + void (*restore_fl)(unsigned long); + void (*irq_disable)(void); + void (*irq_enable)(void); + void (*safe_halt)(void); + void (*halt)(void); + void (*wbinvd)(void); + + /* err = 0/-EFAULT. wrmsr returns 0/-EFAULT. */ + unsigned long long (*read_msr)(unsigned int msr, int *err); + int (*write_msr)(unsigned int msr, unsigned long long val); + + unsigned long long (*read_tsc)(void); + unsigned long long (*read_pmc)(void); + + void (*load_tr_desc)(void); + void (*load_ldt_desc)(void); + void (*load_gdt)(const struct Xgt_desc_struct *); + void (*load_idt)(const struct Xgt_desc_struct *); + void (*store_gdt)(struct Xgt_desc_struct *); + void (*store_idt)(struct Xgt_desc_struct *); + unsigned long (*store_tr)(void); + void (*load_tls)(struct thread_struct *t, unsigned int cpu); + void (*write_ldt_entry)(void *dt, int entrynum, u64 entry); + void (*write_gdt_entry)(void *dt, int entrynum, u64 entry); + void (*write_idt_entry)(void *dt, int entrynum, u64 entry); + + void (*set_iopl_mask)(unsigned mask); + + /* These two are jmp to, not actually called. */ + void (*irq_enable_sysexit)(void); + void (*iret)(void); +}; + +extern struct paravirt_ops paravirt_ops; + +/* The non-paravirtualized CPUID instruction. */ +static inline void __cpuid(unsigned int *eax, unsigned int *ebx, + unsigned int *ecx, unsigned int *edx) +{ + paravirt_ops.cpuid(eax, ebx, ecx, edx); +} + +/* + * These special macros can be used to get or set a debugging register + */ +#define get_debugreg(var, reg) var = paravirt_ops.get_debugreg(reg) +#define set_debugreg(val, reg) paravirt_ops.set_debugreg(reg, val) + +/* Stop speculative execution */ +static inline void sync_core(void) +{ + paravirt_ops.sync_core(); +} + +#define clts() paravirt_ops.clts() + +#define read_cr0() paravirt_ops.read_cr0() +#define write_cr0(x) paravirt_ops.write_cr0(x) + +#define read_cr2() paravirt_ops.read_cr2() +#define write_cr2(x) paravirt_ops.write_cr2(x) + +#define read_cr3() paravirt_ops.read_cr3() +#define write_cr3(x) paravirt_ops.write_cr3(x) + +#define read_cr4() paravirt_ops.read_cr4() +#define read_cr4_safe(x) paravirt_ops.read_cr4_safe() +#define write_cr4(x) paravirt_ops.write_cr4(x) + +#define __local_save_flags() paravirt_ops.save_fl() +#define __local_irq_restore(f) paravirt_ops.restore_fl(f) +#define local_irq_disable() paravirt_ops.irq_disable() +#define local_irq_enable() paravirt_ops.irq_enable() +#define safe_halt() paravirt_ops.safe_halt() +#define halt() paravirt_ops.halt() +#define wbinvd() paravirt_ops.wbinvd() + +#define get_kernel_rpl() (paravirt_ops.kernel_rpl) + +#define rdmsr(msr,val1,val2) do { \ + int _err; \ + unsigned long long _l = paravirt_ops.read_msr(msr,&_err); \ + val1 = (int)_l; \ + val2 = _l >> 32; \ +} while(0) + +#define wrmsr(msr,val1,val2) do { \ + unsigned long long _l = ((long long)(val2) << 32) | (val1); \ + paravirt_ops.write_msr((msr), _l); \ +} while(0) + +#define rdmsrl(msr,val) do { \ + int _err; \ + val = paravirt_ops.read_msr((msr),&_err); \ +} while(0) +#define wrmsrl(msr,val) (paravirt_ops.write_msr((msr),(val))) +#define wrmsr_safe(msr,a,b) ({ \ + unsigned long long _l = ((long long)(a) << 32) | (b); \ + paravirt_ops.write_msr((msr),_l); \ +}) + +/* rdmsr with exception handling */ +#define rdmsr_safe(msr,a,b) ({ \ + int _err; \ + unsigned long long _l = paravirt_ops.read_msr(msr,&_err); \ + (*a) = (int)_l; \ + (*b) = _l >> 32; \ + _err; }) + +#define rdtsc(low,high) do { \ + unsigned long long _l = paravirt_ops.read_tsc(); \ + low = (int)_l; \ + high = _l >> 32; \ +} while(0) + +#define rdtscl(low) do { \ + unsigned long long _l = paravirt_ops.read_tsc(); \ + low = (int)_l; \ +} while(0) + +#define rdtscll(val) (val = paravirt_ops.read_tsc()) + +#define write_tsc(val1,val2) wrmsr(0x10, val1, val2) + +#define rdpmc(counter,low,high) do { \ + unsigned long long _l = paravirt_ops.read_pmc(); \ + low = (int)_l; \ + high = _l >> 32; \ +} while(0) + +#define load_TR_desc() (paravirt_ops.load_tr_desc()) +#define load_LDT_desc() (paravirt_ops.load_ldt_desc()) +#define load_gdt(dtr) (paravirt_ops.load_gdt(dtr)) +#define load_idt(dtr) (paravirt_ops.load_idt(dtr)) +#define store_gdt(dtr) (paravirt_ops.store_gdt(dtr)) +#define store_idt(dtr) (paravirt_ops.store_idt(dtr)) +#define store_tr(tr) ((tr) = paravirt_ops.store_tr()) +#define load_TLS(t,cpu) (paravirt_ops.load_tls((t),(cpu))) +#define write_ldt_entry(dt, entry, a, b) (paravirt_ops.write_ldt_entry((dt), (entry), ((u64)a) << 32 | b)) +#define write_gdt_entry(dt, entry, a, b) (paravirt_ops.write_gdt_entry((dt), (entry), ((u64)a) << 32 | b)) +#define write_idt_entry(dt, entry, a, b) (paravirt_ops.write_idt_entry((dt), (entry), ((u64)a) << 32 | b)) +#define set_iopl_mask(mask) (paravirt_ops.set_iopl_mask(mask)) +#else /* ... __ASSEMBLY__ */ + +#define IRET jmp *paravirt_ops+PARAVIRT_iret +#define CLI pushl %eax; pushl %ecx; pushl %edx; call *paravirt_ops+PARAVIRT_irq_disable; popl %edx; popl %ecx; popl %eax +#define STI pushl %eax; pushl %ecx; pushl %edx; call *paravirt_ops+PARAVIRT_irq_enable; popl %edx; popl %ecx; popl %eax +#define STI_SYSEXIT jmp *paravirt_ops+PARAVIRT_irq_enable_sysexit +#define GET_CR0 pushl %ecx; pushl %edx; call *paravirt_ops+PARAVIRT_read_cr0; popl %edx; popl %ecx +#define RDMSR pushl %ecx; pushl %edx; pushl %ecx; call *paravirt_ops+PARAVIRT_read_msr; addl $4, %esp; popl %edx; popl %ecx +#define WRMSR pushl %eax; pushl %ecx; pushl %edx; pushl %eax; pushl %ecx; call *paravirt_ops+PARAVIRT_write_msr; addl $8, %esp; popl %edx; popl %ecx +#define CPUID pushl %edx; pushl %ecx; pushl %ebx; pushl %eax; leal $16(%esp), %eax; pushl %eax; leal $16(%esp), %eax; pushl %eax; leal $16(%esp), %eax; pushl %eax; leal $16(%esp), %eax; pushl %eax; call *paravirt_ops+PARAVIRT_cpuid; addl $16; popl %eax; popl %ebx; popl %ecx; popl %edx + +#define COMPARE_SEGMENT_STACK(segment, offset) \ + pushl %eax; \ + mov offset+4(%esp), %eax; \ + andl $~SEGMENT_RPL_MASK, %eax; \ + cmpw $segment,%ax; \ + popl %eax + +#define COMPARE_SEGMENT_REG(segment, reg) \ + pushl %eax; \ + mov reg, %eax; \ + andl $~SEGMENT_RPL_MASK, %eax; \ + cmpw $segment,%ax; \ + popl %eax +#endif /* __ASSEMBLY__ */ + +#define CLI_STRING "pushl %eax; pushl %ecx; pushl %edx; call *paravirt_ops+PARAVIRT_irq_disable; popl %edx; popl %ecx; popl %eax" +#define STI_STRING "pushl %eax; pushl %ecx; pushl %edx; call *paravirt_ops+PARAVIRT_irq_enable; popl %edx; popl %ecx; popl %eax" + +#endif /* PARAVIRT */ #endif /* __ASM_PARAVIRT_H */ diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .10486-linux-2.6.17-rc2-git7/include/asm-i386/paravirt_desc.h .10486-linux-2.6.17-rc2-git7.updated/include/asm-i386/paravirt_desc.h --- .10486-linux-2.6.17-rc2-git7/include/asm-i386/paravirt_desc.h 2006-05-03 19:21:43.000000000 +1000 +++ .10486-linux-2.6.17-rc2-git7.updated/include/asm-i386/paravirt_desc.h 2006-05-03 19:21:44.000000000 +1000 @@ -1,6 +1,11 @@ #ifndef __ASM_PARAVIRT_DESC_H #define __ASM_PARAVIRT_DESC_H /* A separate header because they need processor.h, which needs paravirt.h */ +#include <linux/config.h> +#ifndef CONFIG_PARAVIRT #include <asm/no_paravirt_desc.h> +#else +#include <asm/paravirt.h> +#endif #endif /* __ASM_PARAVIRT_DESC_H */ -- ccontrol: http://ccontrol.ozlabs.org