diff options
-rw-r--r-- | Makefile | 16 | ||||
-rw-r--r-- | kvm.h | 57 | ||||
-rw-r--r-- | kvm_mdb.c | 242 | ||||
-rw-r--r-- | kvm_subr.c | 167 | ||||
-rw-r--r-- | kvm_x86host.h | 47 | ||||
-rw-r--r-- | msr.h | 238 |
6 files changed, 450 insertions, 317 deletions
@@ -12,16 +12,25 @@ DESTDIR= CFLAGS += -DCONFIG_HAVE_KVM_IRQCHIP -D__KVM_HAVE_IOAPIC -DCONFIG_X86_64 -D_KERNEL -D_MACHDEP -Dx86 -DDEBUG -c -g -DCONFIG_SOLARIS -DCONFIG_KVM_MMIO -DCONFIG_KVM_APIC_ARCHITECTURE -O2 -fident -finline -fno-inline-functions -fno-builtin -fno-asm -nodefaultlibs -D__sun -O -D_ASM_INLINES -ffreestanding -Wall -Wno-unknown-pragmas -Wno-missing-braces -Wno-sign-compare -Wno-parentheses -Wno-uninitialized -Wno-implicit-function-declaration -Wno-unused -Wno-trigraphs -Wno-char-subscripts -Wno-switch -gdwarf-2 -std=gnu99 -fno-dwarf2-indirect-strings -Werror -DDIS_MEM -D_KERNEL -ffreestanding -D_SYSCALL32 -D_DDI_STRICT -Di86pc -D_MACHDEP -DOPTERON_ERRATUM_88 -DOPTERON_ERRATUM_91 -DOPTERON_ERRATUM_93 -DOPTERON_ERRATUM_95 -DOPTERON_ERRATUM_99 -DOPTERON_ERRATUM_100 -DOPTERON_ERRATUM_101 -DOPTERON_ERRATUM_108 -DOPTERON_ERRATUM_109 -DOPTERON_ERRATUM_121 -DOPTERON_ERRATUM_122 -DOPTERON_ERRATUM_123 -DOPTERON_ERRATUM_131 -DOPTERON_WORKAROUND_6336786 -DOPTERON_WORKAROUND_6323525 -DOPTERON_ERRATUM_172 -DOPTERON_ERRATUM_298 -I$(KERNEL_SOURCE)/usr/src/uts/common -nostdinc -c -DUTS_RELEASE="5.11" -DUTS_VERSION="joyent.147" -DUTS_PLATFORM="i86pc" -mno-red-zone INCLUDEDIR= -I $(KERNEL_SOURCE)/usr/src/uts/intel -I $(KERNEL_SOURCE)/usr/src/uts/i86pc -I $(KERNEL_SOURCE)/usr/src/uts/common +CSTYLE=$(KERNEL_SOURCE)/usr/src/tools/scripts/cstyle -kvm: kvm.c kvm_x86.c emulate.c kvm.h kvm_x86host.h msr.h bitops.h +all: kvm kvm.so + +kvm: kvm.c kvm_x86.c emulate.c kvm.h kvm_x86host.h msr.h bitops.h kvm_subr.c $(CC) $(CFLAGS) $(INCLUDEDIR) kvm.c $(CC) $(CFLAGS) $(INCLUDEDIR) kvm_x86.c $(CC) $(CFLAGS) $(INCLUDEDIR) emulate.c + $(CC) $(CFLAGS) $(INCLUDEDIR) kvm_subr.c $(CTFCONVERT) -i -L VERSION kvm.o $(CTFCONVERT) -i -L VERSION kvm_x86.o $(CTFCONVERT) -i -L VERSION emulate.o - $(LD) -r -o kvm kvm.o kvm_x86.o emulate.o - $(CTFMERGE) -L VERSION -o kvm kvm.o kvm_x86.o emulate.o + $(CTFCONVERT) -i -L VERSION kvm_subr.o + $(LD) -r -o kvm kvm.o kvm_x86.o emulate.o kvm_subr.o + $(CTFMERGE) -L VERSION -o kvm kvm.o kvm_x86.o emulate.o kvm_subr.o + +kvm.so: kvm_mdb.c + gcc -m64 -shared \ + -fPIC $(CFLAGS) $(INCLUDEDIR) -I/usr/include -o $@ kvm_mdb.c install: kvm @echo "==> Installing kvm module" @@ -30,6 +39,7 @@ install: kvm @pfexec cp kvm.conf /usr/kernel/drv check: + @$(CSTYLE) kvm_mdb.c @./tools/xxxcheck kvm_x86.c kvm.c load: install @@ -1902,19 +1902,13 @@ struct vcpu_vmx { char rdtscp_enabled; }; -static struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i) -{ -#ifdef XXX - smp_rmb(); -#endif /*XXX*/ - return kvm->vcpus[i]; -} - #define kvm_for_each_vcpu(idx, vcpup, kvm) \ for (idx = 0, vcpup = kvm_get_vcpu(kvm, idx); \ idx < kvm->online_vcpus && vcpup; /* XXX - need protection */ \ vcpup = kvm_get_vcpu(kvm, ++idx)) +extern struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i); + #ifdef XXX struct kvm_irq_mask_notifier { void (*func)(struct kvm_irq_mask_notifier *kimn, bool masked); @@ -2060,13 +2054,8 @@ struct preempt_notifier { void preempt_notifier_register(struct preempt_notifier *notifier); void preempt_notifier_unregister(struct preempt_notifier *notifier); - -static void preempt_notifier_init(struct preempt_notifier *notifier, - struct preempt_ops *ops) -{ - INIT_HLIST_NODE(¬ifier->link); - notifier->ops = ops; -} +void preempt_notifier_init(struct preempt_notifier *notifier, + struct preempt_ops *ops); #endif /*XXX*/ #endif /*CONFIG_PREEMPT_NOTIFIERS*/ @@ -2096,12 +2085,7 @@ int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, struct kvm_io_device *dev); -static unsigned long kvm_dirty_bitmap_bytes(struct kvm_memory_slot *memslot) -{ - /* XXX */ - /* return ALIGN(memslot->npages, BITS_PER_LONG) / 8; */ - return ((BT_BITOUL(memslot->npages)) / 8); -} +extern unsigned long kvm_dirty_bitmap_bytes(struct kvm_memory_slot *memslot); int kvm_set_memory_region(struct kvm *kvm, struct kvm_userspace_memory_region *mem, @@ -2241,7 +2225,6 @@ void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask); #endif /*XXX*/ -#ifdef CONFIG_IOMMU_API int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot); int kvm_iommu_map_guest(struct kvm *kvm); int kvm_iommu_unmap_guest(struct kvm *kvm); @@ -2249,36 +2232,6 @@ int kvm_assign_device(struct kvm *kvm, struct kvm_assigned_dev_kernel *assigned_dev); int kvm_deassign_device(struct kvm *kvm, struct kvm_assigned_dev_kernel *assigned_dev); -#else /* CONFIG_IOMMU_API */ -static int kvm_iommu_map_pages(struct kvm *kvm, - gfn_t base_gfn, - unsigned long npages) -{ - return 0; -} - -static int kvm_iommu_map_guest(struct kvm *kvm) -{ - return -ENODEV; -} - -static int kvm_iommu_unmap_guest(struct kvm *kvm) -{ - return 0; -} - -static int kvm_assign_device(struct kvm *kvm, - struct kvm_assigned_dev_kernel *assigned_dev) -{ - return 0; -} - -static int kvm_deassign_device(struct kvm *kvm, - struct kvm_assigned_dev_kernel *assigned_dev) -{ - return 0; -} -#endif /* CONFIG_IOMMU_API */ #define for_each_unsync_children(bitmap, idx) \ for (idx = bt_getlowbit(bitmap, 0, 512); \ diff --git a/kvm_mdb.c b/kvm_mdb.c new file mode 100644 index 0000000..015a6b8 --- /dev/null +++ b/kvm_mdb.c @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2011, Joyent, Inc. All rights reserved. + */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/uio.h> +#include <sys/buf.h> +#include <sys/modctl.h> +#include <sys/open.h> +#include <sys/kmem.h> +#include <sys/poll.h> +#include <sys/conf.h> +#include <sys/cmn_err.h> +#include <sys/stat.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include <sys/atomic.h> +#include <sys/spl.h> +#include <sys/cpuvar.h> +#include <sys/segments.h> +#include <sys/mdb_modapi.h> + +#include "msr.h" +#include "vmx.h" +#include "irqflags.h" +#include "iodev.h" +#include "kvm_host.h" +#include "kvm_x86host.h" +#include "kvm.h" + +int +kvm_mdb_memory_slot_init(mdb_walk_state_t *wsp) +{ + struct kvm_memslots *memslots; + struct kvm kvm; + uintptr_t addr; + + if (wsp->walk_addr == NULL) { + mdb_warn("kvm_memory_slot does not support global walks"); + return (WALK_ERR); + } + + if (mdb_vread(&kvm, sizeof (kvm), wsp->walk_addr) == -1) { + mdb_warn("couldn't read kvm at %p", wsp->walk_addr); + return (DCMD_ERR); + } + + addr = (uintptr_t)kvm.memslots; + memslots = mdb_alloc(sizeof (struct kvm_memslots), UM_SLEEP | UM_GC); + + if (mdb_vread(memslots, sizeof (struct kvm_memslots), addr) == -1) { + mdb_warn("couldn't read memslots at %p", addr); + return (DCMD_ERR); + } + + wsp->walk_addr = addr + offsetof(struct kvm_memslots, memslots); + wsp->walk_arg = 0; + wsp->walk_data = memslots; + + return (WALK_NEXT); +} + +int +kvm_mdb_memory_slot_step(mdb_walk_state_t *wsp) +{ + struct kvm_memslots *memslots = wsp->walk_data; + uintptr_t ndx = (uintptr_t)wsp->walk_arg; + + if (ndx >= KVM_MEMORY_SLOTS) + return (WALK_DONE); + + wsp->walk_arg = (void *)(ndx + 1); + + return (wsp->walk_callback(wsp->walk_addr + + ndx * sizeof (struct kvm_memory_slot), &memslots->memslots[ndx], + wsp->walk_cbdata)); +} + +int +kvm_mdb_mem_alias_init(mdb_walk_state_t *wsp) +{ + struct kvm_mem_aliases *aliases; + struct kvm kvm; + uintptr_t addr; + + if (wsp->walk_addr == NULL) { + mdb_warn("kvm_mem_alias does not support global walks"); + return (WALK_ERR); + } + + if (mdb_vread(&kvm, sizeof (kvm), wsp->walk_addr) == -1) { + mdb_warn("couldn't read kvm at %p", wsp->walk_addr); + return (DCMD_ERR); + } + + addr = (uintptr_t)kvm.arch.aliases; + aliases = mdb_alloc(sizeof (struct kvm_mem_aliases), UM_SLEEP | UM_GC); + + if (mdb_vread(aliases, sizeof (struct kvm_mem_aliases), addr) == -1) { + mdb_warn("couldn't read aliases at %p", addr); + return (DCMD_ERR); + } + + wsp->walk_addr = addr + offsetof(struct kvm_mem_aliases, aliases); + wsp->walk_arg = 0; + wsp->walk_data = aliases; + + return (WALK_NEXT); +} + +int +kvm_mdb_mem_alias_step(mdb_walk_state_t *wsp) +{ + struct kvm_mem_aliases *aliases = wsp->walk_data; + uintptr_t ndx = (uintptr_t)wsp->walk_arg; + + if (ndx >= aliases->naliases) + return (WALK_DONE); + + wsp->walk_arg = (void *)(ndx + 1); + + return (wsp->walk_callback(wsp->walk_addr + + ndx * sizeof (struct kvm_mem_alias), &aliases->aliases[ndx], + wsp->walk_cbdata)); +} + +static int +kvm_mdb_gpa2qva_walk_alias(uintptr_t addr, + const struct kvm_mem_alias *alias, uintptr_t *gfn) +{ + if (alias->flags & KVM_ALIAS_INVALID) + return (WALK_NEXT); + + if (*gfn < alias->base_gfn || *gfn >= alias->base_gfn + alias->npages) + return (WALK_NEXT); + + *gfn = alias->target_gfn + *gfn - alias->base_gfn; + + return (WALK_DONE); +} + +static int +kvm_mdb_gpa2qva_walk_slot(uintptr_t addr, + const struct kvm_memory_slot *memslot, uintptr_t *gpa) +{ + uintptr_t gfn = *gpa >> PAGESHIFT; + + if (gfn < memslot->base_gfn) + return (WALK_NEXT); + + if (gfn >= memslot->base_gfn + memslot->npages) + return (WALK_NEXT); + + mdb_printf("%p\n", memslot->userspace_addr + + ((gfn - memslot->base_gfn) << PAGESHIFT) + (*gpa & PAGEOFFSET)); + + *gpa = -1; + + return (WALK_DONE); +} + +static int +kvm_mdb_gpa2qva(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) +{ + struct kvm kvm; + uintptr_t gpa = addr, gfn, kaddr; + int i; + + if (!(flags & DCMD_ADDRSPEC) || argc < 1) + return (DCMD_USAGE); + + switch (argv[0].a_type) { + case MDB_TYPE_STRING: + kaddr = mdb_strtoull(argv[0].a_un.a_str); + break; + + case MDB_TYPE_IMMEDIATE: + kaddr = argv[0].a_un.a_val; + break; + + default: + return (DCMD_USAGE); + } + + if (mdb_vread(&kvm, sizeof (kvm), kaddr) == -1) { + mdb_warn("couldn't read kvm at %p", kaddr); + return (DCMD_ERR); + } + + gfn = gpa >> PAGESHIFT; + + /* + * First unalias our guest PFN... + */ + if (mdb_pwalk("kvm_mem_alias", + (mdb_walk_cb_t)kvm_mdb_gpa2qva_walk_alias, &gfn, kaddr) == -1) { + mdb_warn("failed to walk 'kvm_memory_slot' for %p", kaddr); + return (DCMD_ERR); + } + + gpa = (gfn << PAGESHIFT) | (gpa & PAGEOFFSET); + + /* + * Now walk memory slots looking for a match. + */ + if (mdb_pwalk("kvm_memory_slot", + (mdb_walk_cb_t)kvm_mdb_gpa2qva_walk_slot, &gpa, kaddr) == -1) { + mdb_warn("failed to walk 'kvm_memory_slot' for %p", kaddr); + return (DCMD_ERR); + } + + if (gpa != -1) { + mdb_warn("0x%p is unknown for kvm 0x%p", addr, kaddr); + return (DCMD_ERR); + } + + return (DCMD_OK); +} + +static const mdb_dcmd_t dcmds[] = { + { "kvm_gpa2qva", "?[address of kvm]", "translate a guest physical " + "to a QEMU virtual address", kvm_mdb_gpa2qva }, + { NULL } +}; + +static const mdb_walker_t walkers[] = { + { "kvm_memory_slot", "walk kvm_memory_slot structures for a given kvm", + kvm_mdb_memory_slot_init, kvm_mdb_memory_slot_step }, + { "kvm_mem_alias", "walk kvm_mem_alias structures for a given kvm", + kvm_mdb_mem_alias_init, kvm_mdb_mem_alias_step }, + { NULL } +}; + +static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers }; + +const mdb_modinfo_t * +_mdb_init(void) +{ + return (&modinfo); +} diff --git a/kvm_subr.c b/kvm_subr.c new file mode 100644 index 0000000..c9c646a --- /dev/null +++ b/kvm_subr.c @@ -0,0 +1,167 @@ +#include <sys/types.h> +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/uio.h> +#include <sys/buf.h> +#include <sys/modctl.h> +#include <sys/open.h> +#include <sys/kmem.h> +#include <sys/poll.h> +#include <sys/conf.h> +#include <sys/cmn_err.h> +#include <sys/stat.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include <sys/atomic.h> +#include <sys/spl.h> +#include <sys/cpuvar.h> +#include <sys/segments.h> + +#include "msr.h" +#include "vmx.h" +#include "irqflags.h" +#include "iodev.h" +#include "kvm_host.h" +#include "kvm_x86host.h" +#include "kvm.h" + +unsigned long +kvm_dirty_bitmap_bytes(struct kvm_memory_slot *memslot) +{ + /* XXX */ + /* return ALIGN(memslot->npages, BITS_PER_LONG) / 8; */ + return ((BT_BITOUL(memslot->npages)) / 8); +} + +struct kvm_vcpu * +kvm_get_vcpu(struct kvm *kvm, int i) +{ +#ifdef XXX + smp_rmb(); +#endif /*XXX*/ + return kvm->vcpus[i]; +} + +void +kvm_fx_save(struct i387_fxsave_struct *image) +{ + __asm__("fxsave (%0)":: "r" (image)); +} + +void +kvm_fx_restore(struct i387_fxsave_struct *image) +{ + __asm__("fxrstor (%0)":: "r" (image)); +} + +void +kvm_fx_finit(void) +{ + __asm__("finit"); +} + +uint32_t +get_rdx_init_val(void) +{ + return 0x600; /* P6 family */ +} + +void +kvm_inject_gp(struct kvm_vcpu *vcpu, uint32_t error_code) +{ + kvm_queue_exception_e(vcpu, GP_VECTOR, error_code); +} + +unsigned long long +native_read_tscp(unsigned int *aux) +{ + unsigned long low, high; + __asm__ volatile(".byte 0x0f,0x01,0xf9" + : "=a" (low), "=d" (high), "=c" (*aux)); + return low | ((uint64_t)high << 32); +} + +unsigned long long +native_read_msr(unsigned int msr) +{ + DECLARE_ARGS(val, low, high); + + __asm__ volatile("rdmsr" : EAX_EDX_RET(val, low, high) : "c" (msr)); + return EAX_EDX_VAL(val, low, high); +} + +void +native_write_msr(unsigned int msr, unsigned low, unsigned high) +{ + __asm__ volatile("wrmsr" : : "c" (msr), + "a"(low), "d" (high) : "memory"); +} + +unsigned long long +__native_read_tsc(void) +{ + DECLARE_ARGS(val, low, high); + + __asm__ volatile("rdtsc" : EAX_EDX_RET(val, low, high)); + + return EAX_EDX_VAL(val, low, high); +} + +unsigned long long +native_read_pmc(int counter) +{ + DECLARE_ARGS(val, low, high); + + __asm__ volatile("rdpmc" : EAX_EDX_RET(val, low, high) : "c" (counter)); + return EAX_EDX_VAL(val, low, high); +} + +void wrmsr(unsigned msr, unsigned low, unsigned high) +{ + native_write_msr(msr, low, high); +} + +int +wrmsr_safe(unsigned msr, unsigned low, unsigned high) +{ + return (native_write_msr_safe(msr, low, high)); +} + +int +rdmsrl_safe(unsigned msr, unsigned long long *p) +{ + int err; + + *p = native_read_msr_safe(msr, &err); + return (err); +} + +int +rdmsr_on_cpu(unsigned int cpu, uint32_t msr_no, uint32_t *l, uint32_t *h) +{ + rdmsr(msr_no, *l, *h); + return 0; +} + +int +wrmsr_on_cpu(unsigned int cpu, uint32_t msr_no, uint32_t l, uint32_t h) +{ + wrmsr(msr_no, l, h); + return 0; +} + +unsigned long read_msr(unsigned long msr) +{ + uint64_t value; + + rdmsrl(msr, value); + return (value); +} + +unsigned long kvm_read_tr_base(void) +{ + unsigned short tr; + __asm__("str %0" : "=g"(tr)); + return segment_base(tr); +} + diff --git a/kvm_x86host.h b/kvm_x86host.h index dc8e268..4b65f4b 100644 --- a/kvm_x86host.h +++ b/kvm_x86host.h @@ -900,48 +900,15 @@ static unsigned long get_desc_base(const struct desc_struct *desc) } extern unsigned long segment_base(uint16_t selector); +extern unsigned long kvm_read_tr_base(void); -static unsigned long kvm_read_tr_base(void) -{ - unsigned short tr; - __asm__("str %0" : "=g"(tr)); - return segment_base(tr); -} - -#ifdef CONFIG_X86_64 -static unsigned long read_msr(unsigned long msr) -{ - uint64_t value; - - rdmsrl(msr, value); - return value; -} -#endif - -static void kvm_fx_save(struct i387_fxsave_struct *image) -{ - __asm__("fxsave (%0)":: "r" (image)); -} +extern unsigned long read_msr(unsigned long msr); -static void kvm_fx_restore(struct i387_fxsave_struct *image) -{ - __asm__("fxrstor (%0)":: "r" (image)); -} - -static void kvm_fx_finit(void) -{ - __asm__("finit"); -} - -static uint32_t get_rdx_init_val(void) -{ - return 0x600; /* P6 family */ -} - -static void kvm_inject_gp(struct kvm_vcpu *vcpu, uint32_t error_code) -{ - kvm_queue_exception_e(vcpu, GP_VECTOR, error_code); -} +extern void kvm_fx_save(struct i387_fxsave_struct *image); +extern void kvm_fx_restore(struct i387_fxsave_struct *image); +extern void kvm_fx_finit(void); +extern uint32_t get_rdx_init_val(void); +extern void kvm_inject_gp(struct kvm_vcpu *vcpu, uint32_t error_code); #define TSS_IOPB_BASE_OFFSET 0x66 #define TSS_BASE_SIZE 0x68 @@ -41,13 +41,7 @@ struct msr_regs_info { int err; }; -static unsigned long long native_read_tscp(unsigned int *aux) -{ - unsigned long low, high; - __asm__ volatile(".byte 0x0f,0x01,0xf9" - : "=a" (low), "=d" (high), "=c" (*aux)); - return low | ((uint64_t)high << 32); -} +extern unsigned long long native_read_tscp(unsigned int *aux); /* * both i386 and x86_64 returns 64-bit value in edx:eax, but gcc's "A" @@ -67,38 +61,13 @@ static unsigned long long native_read_tscp(unsigned int *aux) #define EAX_EDX_RET(val, low, high) "=A" (val) #endif -#ifndef XXX -/* change to function, i.e., not inline. want to dtrace this */ -/* doing this for most read/write msr inlines */ -static unsigned long long native_read_msr(unsigned int msr) -#else -static unsigned long long native_read_msr(unsigned int msr) -#endif /*XXX*/ -{ - DECLARE_ARGS(val, low, high); - - __asm__ volatile("rdmsr" : EAX_EDX_RET(val, low, high) : "c" (msr)); - return EAX_EDX_VAL(val, low, high); -} - - -extern uint64_t native_read_msr_safe(unsigned int msr, - int *err); +extern unsigned long long native_read_msr(unsigned int msr); +extern uint64_t native_read_msr_safe(unsigned int msr, int *err); extern int native_write_msr_safe(unsigned int msr, unsigned low, unsigned high); - -#ifndef XXX -static void native_write_msr(unsigned int msr, - unsigned low, unsigned high) -#else -static void native_write_msr(unsigned int msr, - unsigned low, unsigned high) -#endif /*XXX*/ -{ - __asm__ volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high) : "memory"); -} - +extern void native_write_msr(unsigned int msr, + unsigned low, unsigned high); extern unsigned long long native_read_tsc(void); @@ -107,22 +76,8 @@ extern int native_rdmsr_safe_regs(uint32_t regs[8]); extern int native_wrmsr_safe_regs(uint32_t regs[8]); #endif /*NOTNOW*/ -static unsigned long long __native_read_tsc(void) -{ - DECLARE_ARGS(val, low, high); - - __asm__ volatile("rdtsc" : EAX_EDX_RET(val, low, high)); - - return EAX_EDX_VAL(val, low, high); -} - -static unsigned long long native_read_pmc(int counter) -{ - DECLARE_ARGS(val, low, high); - - __asm__ volatile("rdpmc" : EAX_EDX_RET(val, low, high) : "c" (counter)); - return EAX_EDX_VAL(val, low, high); -} +extern unsigned long long __native_read_tsc(void); +extern unsigned long long native_read_pmc(int counter); #ifdef CONFIG_PARAVIRT #include <asm/paravirt.h> @@ -144,14 +99,7 @@ do { \ (val2) = (uint32_t)(__val >> 32); \ } while (0) -#ifndef XXX -static void wrmsr(unsigned msr, unsigned low, unsigned high) -#else -static void wrmsr(unsigned msr, unsigned low, unsigned high) -#endif /*XXX*/ -{ - native_write_msr(msr, low, high); -} +extern void wrmsr(unsigned msr, unsigned low, unsigned high); #define rdmsrl(msr, val) \ ((val) = native_read_msr((msr))) @@ -159,16 +107,9 @@ static void wrmsr(unsigned msr, unsigned low, unsigned high) #define wrmsrl(msr, val) \ native_write_msr((msr), (uint32_t)((uint64_t)(val)), (uint32_t)((uint64_t)(val) >> 32)) -#ifndef XXX /* see comment above for wrmsr() */ /* wrmsr with exception handling */ -static int wrmsr_safe(unsigned msr, unsigned low, unsigned high) -#else -static int wrmsr_safe(unsigned msr, unsigned low, unsigned high) -#endif /*XXX*/ -{ - return native_write_msr_safe(msr, low, high); -} +extern int wrmsr_safe(unsigned msr, unsigned low, unsigned high); /* rdmsr with exception handling */ #define rdmsr_safe(msr, p1, p2) \ @@ -180,75 +121,10 @@ static int wrmsr_safe(unsigned msr, unsigned low, unsigned high) __err; \ }) -#ifndef XXX -static int rdmsrl_safe(unsigned msr, unsigned long long *p) -#else -static int rdmsrl_safe(unsigned msr, unsigned long long *p) -#endif /*XXX*/ -{ - int err; - - *p = native_read_msr_safe(msr, &err); - return err; -} - -#ifdef NOTNOW -#ifndef XXX -static int rdmsrl_amd_safe(unsigned msr, unsigned long long *p) -#else -static int rdmsrl_amd_safe(unsigned msr, unsigned long long *p) -#endif /*XXX*/ -{ - uint32_t gprs[8] = { 0 }; - int err; - - gprs[1] = msr; - gprs[7] = 0x9c5a203a; - - err = native_rdmsr_safe_regs(gprs); - - *p = gprs[0] | ((uint64_t)gprs[2] << 32); - - return err; -} - -#ifndef XXX -static int wrmsrl_amd_safe(unsigned msr, unsigned long long val) -#else -static int wrmsrl_amd_safe(unsigned msr, unsigned long long val) -#endif /*XXX*/ -{ - uint32_t gprs[8] = { 0 }; - - gprs[0] = (uint32_t)val; - gprs[1] = msr; - gprs[2] = val >> 32; - gprs[7] = 0x9c5a203a; - - return native_wrmsr_safe_regs(gprs); -} -#endif /*NOTNOW*/ +extern int rdmsrl_safe(unsigned msr, unsigned long long *p); -#ifdef NOTNOW -#ifndef XXX -/* wtf are native_rdmsr_safe_regs/native_wrmsr_safe_regs??? */ -/* possibly built from paravirt.c..., but we don't use them */ -static int rdmsr_safe_regs(uint32_t regs[8]) -#else -static int rdmsr_safe_regs(uint32_t regs[8]) -#endif /*XXX*/ -{ - return native_rdmsr_safe_regs(regs); -} -#ifndef XXX -static int wrmsr_safe_regs(uint32_t regs[8]) -#else -static int wrmsr_safe_regs(uint32_t regs[8]) -#endif /*XXX*/ -{ - return native_wrmsr_safe_regs(regs); -} -#endif /*NOTNOW*/ +extern int rdmsrl_amd_safe(unsigned msr, unsigned long long *p); +extern int wrmsrl_amd_safe(unsigned msr, unsigned long long val); #define rdtscl(low) \ ((low) = (uint32_t)__native_read_tsc()) @@ -285,93 +161,11 @@ do { \ struct msr *msrs_alloc(void); void msrs_free(struct msr *msrs); -#ifdef CONFIG_SMP -int rdmsr_on_cpu(unsigned int cpu, uint32_t msr_no, uint32_t *l, uint32_t *h); -int wrmsr_on_cpu(unsigned int cpu, uint32_t msr_no, uint32_t l, uint32_t h); -#ifdef XXX -void rdmsr_on_cpus(const struct cpumask *mask, uint32_t msr_no, struct msr *msrs); -void wrmsr_on_cpus(const struct cpumask *mask, uint32_t msr_no, struct msr *msrs); -#endif /*XXX*/ -int rdmsr_safe_on_cpu(unsigned int cpu, uint32_t msr_no, uint32_t *l, uint32_t *h); -int wrmsr_safe_on_cpu(unsigned int cpu, uint32_t msr_no, uint32_t l, uint32_t h); -#ifdef XXX -int rdmsr_safe_regs_on_cpu(unsigned int cpu, uint32_t regs[8]); -int wrmsr_safe_regs_on_cpu(unsigned int cpu, uint32_t regs[8]); -#endif /*XXX*/ -#else /* CONFIG_SMP */ -#ifndef XXX -static int rdmsr_on_cpu(unsigned int cpu, uint32_t msr_no, uint32_t *l, uint32_t *h) -#else -static int rdmsr_on_cpu(unsigned int cpu, uint32_t msr_no, uint32_t *l, uint32_t *h) -#endif /*XXX*/ -{ - rdmsr(msr_no, *l, *h); - return 0; -} +extern int rdmsr_on_cpu(unsigned int cpu, + uint32_t msr_no, uint32_t *l, uint32_t *h); +extern int wrmsr_on_cpu(unsigned int cpu, + uint32_t msr_no, uint32_t l, uint32_t h); -#ifndef XXX -static int wrmsr_on_cpu(unsigned int cpu, uint32_t msr_no, uint32_t l, uint32_t h) -#else -static int wrmsr_on_cpu(unsigned int cpu, uint32_t msr_no, uint32_t l, uint32_t h) -#endif /*XXX*/ -{ - wrmsr(msr_no, l, h); - return 0; -} -#ifdef XXX -static void rdmsr_on_cpus(const struct cpumask *m, uint32_t msr_no, - struct msr *msrs) -{ - rdmsr_on_cpu(0, msr_no, &(msrs[0].l), &(msrs[0].h)); -} - -static void wrmsr_on_cpus(const struct cpumask *m, uint32_t msr_no, - struct msr *msrs) -{ - wrmsr_on_cpu(0, msr_no, msrs[0].l, msrs[0].h); -} -#endif /*XXX*/ - -#ifndef XXX -static int rdmsr_safe_on_cpu(unsigned int cpu, uint32_t msr_no, - uint32_t *l, uint32_t *h) -#else -static int rdmsr_safe_on_cpu(unsigned int cpu, uint32_t msr_no, - uint32_t *l, uint32_t *h) -#endif /*XXX*/ -{ - return rdmsr_safe(msr_no, l, h); -} - -#ifndef XXX -static int wrmsr_safe_on_cpu(unsigned int cpu, uint32_t msr_no, uint32_t l, uint32_t h) -#else -static int wrmsr_safe_on_cpu(unsigned int cpu, uint32_t msr_no, uint32_t l, uint32_t h) -#endif /*XXX*/ -{ - return wrmsr_safe(msr_no, l, h); -} - -#ifdef NOTNOW -#ifndef XXX -static int rdmsr_safe_regs_on_cpu(unsigned int cpu, uint32_t regs[8]) -#else -static int rdmsr_safe_regs_on_cpu(unsigned int cpu, uint32_t regs[8]) -#endif /*XXX*/ -{ - return rdmsr_safe_regs(regs); -} - -#ifndef XXX -static int wrmsr_safe_regs_on_cpu(unsigned int cpu, uint32_t regs[8]) -#else -static int wrmsr_safe_regs_on_cpu(unsigned int cpu, uint32_t regs[8]) -#endif /*XXX*/ -{ - return wrmsr_safe_regs(regs); -} -#endif /*NOTNOW*/ -#endif /* CONFIG_SMP */ #endif /* _KERNEL */ #endif /* __ASSEMBLY__ */ #endif /* _ASM_X86_MSR_H */ |