summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2011-06-08 14:40:08 -0700
committerRobert Mustacchi <rm@joyent.com>2011-06-08 14:40:08 -0700
commit27b148dd0083b94a2c6a46dfd46c02eb557cc9e3 (patch)
tree9770371aab2d4f5ca9a3d4331f370936fd31ce02
parentfc81a7032577914bac149316323d225e6c268a18 (diff)
downloadillumos-kvm-27b148dd0083b94a2c6a46dfd46c02eb557cc9e3.tar.gz
HVM-335 kvm_subr.c has reached the end of the line
-rw-r--r--Makefile10
-rw-r--r--kvm.c91
-rw-r--r--kvm_mmu.c46
-rw-r--r--kvm_subr.c496
-rw-r--r--kvm_x86.c330
-rw-r--r--msr.h9
6 files changed, 465 insertions, 517 deletions
diff --git a/Makefile b/Makefile
index 7ab63d3..106d2ae 100644
--- a/Makefile
+++ b/Makefile
@@ -20,11 +20,10 @@ HEADERS= \
kvm.h \
kvm_bitops.h
-kvm: kvm.c kvm_x86.c kvm_emulate.c kvm.h kvm_x86host.h msr.h kvm_bitops.h kvm_subr.c kvm_irq.c kvm_i8254.c kvm_lapic.c kvm_mmu.c kvm_iodev.c kvm_ioapic.c kvm_vmx.c kvm_i8259.c kvm_coalesced_mmio.c kvm_irq_comm.c kvm_cache_regs.c kvm_bitops.c
+kvm: kvm.c kvm_x86.c kvm_emulate.c kvm.h kvm_x86host.h msr.h kvm_bitops.h kvm_irq.c kvm_i8254.c kvm_lapic.c kvm_mmu.c kvm_iodev.c kvm_ioapic.c kvm_vmx.c kvm_i8259.c kvm_coalesced_mmio.c kvm_irq_comm.c kvm_cache_regs.c kvm_bitops.c
$(CC) $(CFLAGS) $(INCLUDEDIR) kvm.c
$(CC) $(CFLAGS) $(INCLUDEDIR) kvm_x86.c
$(CC) $(CFLAGS) $(INCLUDEDIR) kvm_emulate.c
- $(CC) $(CFLAGS) $(INCLUDEDIR) kvm_subr.c
$(CC) $(CFLAGS) $(INCLUDEDIR) kvm_irq.c
$(CC) $(CFLAGS) $(INCLUDEDIR) kvm_i8254.c
$(CC) $(CFLAGS) $(INCLUDEDIR) kvm_lapic.c
@@ -40,7 +39,6 @@ kvm: kvm.c kvm_x86.c kvm_emulate.c kvm.h kvm_x86host.h msr.h kvm_bitops.h kvm_su
$(CTFCONVERT) -i -L VERSION kvm.o
$(CTFCONVERT) -i -L VERSION kvm_x86.o
$(CTFCONVERT) -i -L VERSION kvm_emulate.o
- $(CTFCONVERT) -i -L VERSION kvm_subr.o
$(CTFCONVERT) -i -L VERSION kvm_irq.o
$(CTFCONVERT) -i -L VERSION kvm_i8254.o
$(CTFCONVERT) -i -L VERSION kvm_lapic.o
@@ -53,8 +51,8 @@ kvm: kvm.c kvm_x86.c kvm_emulate.c kvm.h kvm_x86host.h msr.h kvm_bitops.h kvm_su
$(CTFCONVERT) -i -L VERSION kvm_irq_comm.o
$(CTFCONVERT) -i -L VERSION kvm_cache_regs.o
$(CTFCONVERT) -i -L VERSION kvm_bitops.o
- $(LD) -r -o kvm kvm.o kvm_x86.o kvm_emulate.o kvm_subr.o kvm_irq.o kvm_i8254.o kvm_lapic.o kvm_mmu.o kvm_iodev.o kvm_ioapic.o kvm_vmx.o kvm_i8259.o kvm_coalesced_mmio.o kvm_irq_comm.o kvm_cache_regs.o kvm_bitops.o
- $(CTFMERGE) -L VERSION -o kvm kvm.o kvm_x86.o kvm_emulate.o kvm_subr.o kvm_irq.o kvm_i8254.o kvm_lapic.o kvm_mmu.o kvm_iodev.o kvm_ioapic.o kvm_vmx.o kvm_i8259.o kvm_coalesced_mmio.o kvm_irq_comm.o kvm_cache_regs.o kvm_bitops.o
+ $(LD) -r -o kvm kvm.o kvm_x86.o kvm_emulate.o kvm_irq.o kvm_i8254.o kvm_lapic.o kvm_mmu.o kvm_iodev.o kvm_ioapic.o kvm_vmx.o kvm_i8259.o kvm_coalesced_mmio.o kvm_irq_comm.o kvm_cache_regs.o kvm_bitops.o
+ $(CTFMERGE) -L VERSION -o kvm kvm.o kvm_x86.o kvm_emulate.o kvm_irq.o kvm_i8254.o kvm_lapic.o kvm_mmu.o kvm_iodev.o kvm_ioapic.o kvm_vmx.o kvm_i8259.o kvm_coalesced_mmio.o kvm_irq_comm.o kvm_cache_regs.o kvm_bitops.o
kvm.so: kvm_mdb.c
gcc -m64 -shared \
@@ -67,7 +65,7 @@ install: kvm
@pfexec cp kvm.conf /usr/kernel/drv
check:
- @$(CSTYLE) kvm.c kvm_mdb.c kvm_emulate.c kvm_x86.c kvm_irq.c kvm_lapic.c kvm_i8254.c kvm_mmu.c kvm_iodev.c kvm_subr.c kvm_ioapic.c kvm_vmx.c kvm_i8259.c kvm_coalesced_mmio.c kvm_irq_comm.c kvm_cache_regs.c kvm_bitops.c $(HEADERS)
+ @$(CSTYLE) kvm.c kvm_mdb.c kvm_emulate.c kvm_x86.c kvm_irq.c kvm_lapic.c kvm_i8254.c kvm_mmu.c kvm_iodev.c kvm_ioapic.c kvm_vmx.c kvm_i8259.c kvm_coalesced_mmio.c kvm_irq_comm.c kvm_cache_regs.c kvm_bitops.c $(HEADERS)
@./tools/xxxcheck kvm_x86.c kvm.c kvm_irq.c kvm_lapic.c kvm_i8254.c kvm_mmu.c kvm_iodev.c kvm_ioapic.c kvm_vmx.c kvm_i8259.c kvm_coalesced_mmio.c kvm_irq_comm.c kvm_cache_regs.c kvm_bitops.c
load: install
diff --git a/kvm.c b/kvm.c
index 4f8f5d1..3d8b0dc 100644
--- a/kvm.c
+++ b/kvm.c
@@ -96,6 +96,34 @@ static kmutex_t kvm_lock;
static int ignore_msrs = 0;
static unsigned long empty_zero_page[PAGESIZE / sizeof (unsigned long)];
+int
+kvm_xcall_func(kvm_xcall_t func, void *arg)
+{
+ if (func != NULL)
+ (*func)(arg);
+
+ return (0);
+}
+
+void
+kvm_xcall(processorid_t cpu, kvm_xcall_t func, void *arg)
+{
+ cpuset_t set;
+
+ CPUSET_ZERO(set);
+
+ if (cpu == KVM_CPUALL) {
+ CPUSET_ALL(set);
+ } else {
+ CPUSET_ADD(set, cpu);
+ }
+
+ kpreempt_disable();
+ xc_sync((xc_arg_t)func, (xc_arg_t)arg, 0, CPUSET2BV(set),
+ (xc_func_t) kvm_xcall_func);
+ kpreempt_enable();
+}
+
void
kvm_user_return_notifier_register(struct kvm_vcpu *vcpu,
struct kvm_user_return_notifier *urn)
@@ -143,6 +171,12 @@ kvm_ctx_restore(void *arg)
kvm_arch_vcpu_load(vcpu, cpu);
}
+void
+kvm_migrate_timers(struct kvm_vcpu *vcpu)
+{
+ set_bit(KVM_REQ_MIGRATE_TIMER, &vcpu->requests);
+}
+
#ifdef XXX_KVM_DECLARATION
#define pfn_valid(pfn) ((pfn < physmax) && (pfn != PFN_INVALID))
#else
@@ -181,6 +215,17 @@ vcpu_load(struct kvm_vcpu *vcpu)
kpreempt_enable();
}
+struct kvm_vcpu *
+kvm_get_vcpu(struct kvm *kvm, int i)
+{
+#ifdef XXX
+ smp_rmb();
+#else
+ XXX_KVM_PROBE;
+#endif
+ return (kvm->vcpus[i]);
+}
+
void
vcpu_put(struct kvm_vcpu *vcpu)
{
@@ -480,13 +525,18 @@ kvm_free_physmem(struct kvm *kvm)
kmem_free(kvm->memslots, sizeof (struct kvm_memslots));
}
-
void
kvm_get_kvm(struct kvm *kvm)
{
atomic_inc_32(&kvm->users_count);
}
+unsigned long
+kvm_dirty_bitmap_bytes(struct kvm_memory_slot *memslot)
+{
+ return (BT_SIZEOFMAP(memslot->npages));
+}
+
/*
* Allocate some memory and give it an address in the guest physical address
* space.
@@ -1149,6 +1199,12 @@ mark_page_dirty(struct kvm *kvm, gfn_t gfn)
}
}
+int
+kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu)
+{
+ return (vcpu->kvm->bsp_vcpu_id == vcpu->vcpu_id);
+}
+
/*
* The vCPU has executed a HLT instruction with in-kernel mode enabled.
*/
@@ -1659,6 +1715,39 @@ kvm_guest_enter(void)
#endif
}
+/*
+ * Find the first cleared bit in a memory region.
+ */
+unsigned long
+find_first_zero_bit(const unsigned long *addr, unsigned long size)
+{
+ const unsigned long *p = addr;
+ unsigned long result = 0;
+ unsigned long tmp;
+
+ while (size & ~(64-1)) {
+ if (~(tmp = *(p++)))
+ goto found;
+ result += 64;
+ size -= 64;
+ }
+ if (!size)
+ return (result);
+
+ tmp = (*p) | (~0UL << size);
+ if (tmp == ~0UL) /* Are any bits zero? */
+ return (result + size); /* Nope. */
+found:
+ return (result + ffz(tmp));
+}
+
+int
+zero_constructor(void *buf, void *arg, int tags)
+{
+ bzero(buf, (size_t)arg);
+ return (0);
+}
+
static int
kvm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
diff --git a/kvm_mmu.c b/kvm_mmu.c
index 5fa5a15..93827b7 100644
--- a/kvm_mmu.c
+++ b/kvm_mmu.c
@@ -3028,3 +3028,49 @@ kvm_avlmmucmp(const void *arg1, const void *arg2)
ASSERT(mp1->kmp_avlspt == mp2->kmp_avlspt);
return (0);
}
+
+inline page_t *
+compound_head(page_t *page)
+{
+ /* XXX - linux links page_t together. */
+ return (page);
+}
+
+inline void
+get_page(page_t *page)
+{
+ page = compound_head(page);
+}
+
+page_t *
+pfn_to_page(pfn_t pfn)
+{
+ return (page_numtopp_nolock(pfn));
+}
+
+page_t *
+alloc_page(size_t size, int flag)
+{
+ caddr_t page_addr;
+ pfn_t pfn;
+ page_t *pp;
+
+ if ((page_addr = kmem_zalloc(size, flag)) == NULL)
+ return ((page_t *)NULL);
+
+ pp = page_numtopp_nolock(hat_getpfnum(kas.a_hat, page_addr));
+ return (pp);
+}
+
+/*
+ * Often times we have pages that correspond to addresses that are in a users
+ * virtual address space. Rather than trying to constantly map them in and out
+ * of our address space we instead go through and use the kpm segment to
+ * facilitate this for us. This always returns an address that is always in the
+ * kernel's virtual address space.
+ */
+caddr_t
+page_address(page_t *page)
+{
+ return (hat_kpm_mapin_pfn(page->p_pagenum));
+}
diff --git a/kvm_subr.c b/kvm_subr.c
deleted file mode 100644
index 845fb5f..0000000
--- a/kvm_subr.c
+++ /dev/null
@@ -1,496 +0,0 @@
-#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 "kvm_bitops.h"
-#include "msr.h"
-#include "kvm_vmx.h"
-#include "irqflags.h"
-#include "kvm_iodev.h"
-#include "kvm_x86impl.h"
-#include "kvm_host.h"
-#include "kvm_x86host.h"
-#include "kvm.h"
-
-extern int lwp_sigmask(int, uint_t, uint_t, uint_t, uint_t);
-
-unsigned long
-kvm_dirty_bitmap_bytes(struct kvm_memory_slot *memslot)
-{
- return (BT_SIZEOFMAP(memslot->npages));
-}
-
-struct kvm_vcpu *
-kvm_get_vcpu(struct kvm *kvm, int i)
-{
-#ifdef XXX
- smp_rmb();
-#endif
- 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);
-}
-
-void
-kvm_sigprocmask(int how, sigset_t *setp, sigset_t *osetp)
-{
- k_sigset_t kset;
-
- ASSERT(how == SIG_SETMASK);
- ASSERT(setp != NULL);
-
- sigutok(setp, &kset);
-
- if (osetp != NULL)
- sigktou(&curthread->t_hold, osetp);
-
- (void) lwp_sigmask(SIG_SETMASK,
- kset.__sigbits[0], kset.__sigbits[1], kset.__sigbits[2], 0);
-}
-
-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));
-}
-
-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);
-}
-
-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));
-}
-
-int
-kvm_xcall_func(kvm_xcall_t func, void *arg)
-{
- if (func != NULL)
- (*func)(arg);
-
- return (0);
-}
-
-void
-kvm_xcall(processorid_t cpu, kvm_xcall_t func, void *arg)
-{
- cpuset_t set;
-
- CPUSET_ZERO(set);
-
- if (cpu == KVM_CPUALL) {
- CPUSET_ALL(set);
- } else {
- CPUSET_ADD(set, cpu);
- }
-
- kpreempt_disable();
- xc_sync((xc_arg_t)func, (xc_arg_t)arg, 0, CPUSET2BV(set),
- (xc_func_t) kvm_xcall_func);
- kpreempt_enable();
-}
-
-
-
-unsigned short
-kvm_read_fs(void)
-{
- unsigned short seg;
- __asm__("mov %%fs, %0" : "=g"(seg));
- return (seg);
-}
-
-unsigned short
-kvm_read_gs(void)
-{
- unsigned short seg;
- __asm__("mov %%gs, %0" : "=g"(seg));
- return (seg);
-}
-
-unsigned short
-kvm_read_ldt(void)
-{
- unsigned short ldt;
- __asm__("sldt %0" : "=g"(ldt));
- return (ldt);
-}
-
-void
-kvm_load_fs(unsigned short sel)
-{
- __asm__("mov %0, %%fs" : : "rm"(sel));
-}
-
-void
-kvm_load_gs(unsigned short sel)
-{
- __asm__("mov %0, %%gs" : : "rm"(sel));
-}
-
-void
-kvm_load_ldt(unsigned short sel)
-{
- __asm__("lldt %0" : : "rm"(sel));
-}
-
-
-void
-kvm_get_idt(struct descriptor_table *table)
-{
- __asm__("sidt %0" : "=m"(*table));
-}
-
-void
-kvm_get_gdt(struct descriptor_table *table)
-{
- __asm__("sgdt %0" : "=m"(*table));
-}
-
-/*
- * Find the first cleared bit in a memory region.
- */
-unsigned long
-find_first_zero_bit(const unsigned long *addr, unsigned long size)
-{
- const unsigned long *p = addr;
- unsigned long result = 0;
- unsigned long tmp;
-
- while (size & ~(64-1)) {
- if (~(tmp = *(p++)))
- goto found;
- result += 64;
- size -= 64;
- }
- if (!size)
- return (result);
-
- tmp = (*p) | (~0UL << size);
- if (tmp == ~0UL) /* Are any bits zero? */
- return (result + size); /* Nope. */
-found:
- return (result + ffz(tmp));
-}
-
-int
-zero_constructor(void *buf, void *arg, int tags)
-{
- bzero(buf, (size_t)arg);
- return (0);
-}
-
-/*
- * Volatile isn't enough to prevent the compiler from reordering the
- * read/write functions for the control registers and messing everything up.
- * A memory clobber would solve the problem, but would prevent reordering of
- * all loads stores around it, which can hurt performance. Solution is to
- * use a variable and mimic reads and writes to it to enforce serialization
- */
-static unsigned long __force_order;
-
-unsigned long
-native_read_cr0(void)
-{
- unsigned long val;
- __asm__ volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order));
- return (val);
-}
-
-unsigned long
-native_read_cr4(void)
-{
- unsigned long val;
- __asm__ volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order));
- return (val);
-}
-
-unsigned long
-native_read_cr3(void)
-{
- unsigned long val;
- __asm__ volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order));
- return (val);
-}
-
-inline unsigned long
-get_desc_limit(const struct desc_struct *desc)
-{
- return (desc->c.b.limit0 | (desc->c.b.limit << 16));
-}
-
-unsigned long
-get_desc_base(const struct desc_struct *desc)
-{
- return (unsigned)(desc->c.b.base0 | ((desc->c.b.base1) << 16) |
- ((desc->c.b.base2) << 24));
-}
-
-inline page_t *
-compound_head(page_t *page)
-{
- /* XXX - linux links page_t together. */
- return (page);
-}
-
-inline void
-get_page(page_t *page)
-{
- page = compound_head(page);
-}
-
-
-page_t *
-pfn_to_page(pfn_t pfn)
-{
- return (page_numtopp_nolock(pfn));
-}
-
-
-inline void
-kvm_clear_exception_queue(struct kvm_vcpu *vcpu)
-{
- vcpu->arch.exception.pending = 0;
-}
-
-inline void
-kvm_queue_interrupt(struct kvm_vcpu *vcpu, uint8_t vector, int soft)
-{
- vcpu->arch.interrupt.pending = 1;
- vcpu->arch.interrupt.soft = soft;
- vcpu->arch.interrupt.nr = vector;
-}
-
-inline void
-kvm_clear_interrupt_queue(struct kvm_vcpu *vcpu)
-{
- vcpu->arch.interrupt.pending = 0;
-}
-
-int
-kvm_event_needs_reinjection(struct kvm_vcpu *vcpu)
-{
- return (vcpu->arch.exception.pending || vcpu->arch.interrupt.pending ||
- vcpu->arch.nmi_injected);
-}
-
-inline int
-kvm_exception_is_soft(unsigned int nr)
-{
- return (nr == BP_VECTOR) || (nr == OF_VECTOR);
-}
-
-inline int
-is_protmode(struct kvm_vcpu *vcpu)
-{
- return (kvm_read_cr0_bits(vcpu, X86_CR0_PE));
-}
-
-int
-is_long_mode(struct kvm_vcpu *vcpu)
-{
-#ifdef CONFIG_X86_64
- return (vcpu->arch.efer & EFER_LMA);
-#else
- return (0);
-#endif
-}
-
-inline int
-is_pae(struct kvm_vcpu *vcpu)
-{
- return (kvm_read_cr4_bits(vcpu, X86_CR4_PAE));
-}
-
-int
-is_pse(struct kvm_vcpu *vcpu)
-{
- return (kvm_read_cr4_bits(vcpu, X86_CR4_PSE));
-}
-
-int
-is_paging(struct kvm_vcpu *vcpu)
-{
- return (kvm_read_cr0_bits(vcpu, X86_CR0_PG));
-}
-
-uint64_t
-native_read_msr_safe(unsigned int msr, int *err)
-{
- DECLARE_ARGS(val, low, high);
- uint64_t ret = 0;
- on_trap_data_t otd;
-
- if (on_trap(&otd, OT_DATA_ACCESS) == 0) {
- ret = native_read_msr(msr);
- *err = 0;
- } else {
- *err = EINVAL; /* XXX probably not right... */
- }
- no_trap();
-
- return (ret);
-}
-
-/* Can be uninlined because referenced by paravirt */
-int
-native_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
-{
- int err = 0;
- on_trap_data_t otd;
-
- if (on_trap(&otd, OT_DATA_ACCESS) == 0) {
- native_write_msr(msr, low, high);
- } else {
- err = EINVAL; /* XXX probably not right... */
- }
- no_trap();
-
- return (err);
-}
-
-
-/* XXX Where should this live */
-page_t *
-alloc_page(size_t size, int flag)
-{
- caddr_t page_addr;
- pfn_t pfn;
- page_t *pp;
-
- if ((page_addr = kmem_zalloc(size, flag)) == NULL)
- return ((page_t *)NULL);
-
- pp = page_numtopp_nolock(hat_getpfnum(kas.a_hat, page_addr));
- return (pp);
-}
-
-int
-kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu)
-{
- return (vcpu->kvm->bsp_vcpu_id == vcpu->vcpu_id);
-}
-
-/*
- * Often times we have pages that correspond to addresses that are in a users
- * virtual address space. Rather than trying to constantly map them in and out
- * of our address space we instead go through and use the kpm segment to
- * facilitate this for us. This always returns an address that is always in the
- * kernel's virtual address space.
- */
-caddr_t
-page_address(page_t *page)
-{
- return (hat_kpm_mapin_pfn(page->p_pagenum));
-}
-
-uint32_t
-bit(int bitno)
-{
- return (1 << (bitno & 31));
-}
diff --git a/kvm_x86.c b/kvm_x86.c
index f5a3f9c..0b86d96 100644
--- a/kvm_x86.c
+++ b/kvm_x86.c
@@ -39,9 +39,16 @@
/* XXX These don't belong here! */
extern caddr_t smmap64(caddr_t addr, size_t len, int prot, int flags,
int fd, off_t pos);
+extern int lwp_sigmask(int, uint_t, uint_t, uint_t, uint_t);
static unsigned long empty_zero_page[PAGESIZE / sizeof (unsigned long)];
+/*
+ * Globals
+ */
+struct kvm_x86_ops *kvm_x86_ops;
+int ignore_msrs = 0;
+
#define MAX_IO_MSRS 256
#define CR0_RESERVED_BITS \
(~(unsigned long)(X86_CR0_PE | X86_CR0_MP | X86_CR0_EM | X86_CR0_TS \
@@ -67,11 +74,24 @@ static uint64_t efer_reserved_bits = 0xfffffffffffffffeULL;
#endif
static void update_cr8_intercept(struct kvm_vcpu *);
+static struct kvm_shared_msrs_global shared_msrs_global;
-struct kvm_x86_ops *kvm_x86_ops;
-int ignore_msrs = 0;
+void
+kvm_sigprocmask(int how, sigset_t *setp, sigset_t *osetp)
+{
+ k_sigset_t kset;
-static struct kvm_shared_msrs_global shared_msrs_global;
+ ASSERT(how == SIG_SETMASK);
+ ASSERT(setp != NULL);
+
+ sigutok(setp, &kset);
+
+ if (osetp != NULL)
+ sigktou(&curthread->t_hold, osetp);
+
+ (void) lwp_sigmask(SIG_SETMASK,
+ kset.__sigbits[0], kset.__sigbits[1], kset.__sigbits[2], 0);
+}
static void
kvm_on_user_return(struct kvm_vcpu *vcpu, struct kvm_user_return_notifier *urn)
@@ -293,6 +313,12 @@ kvm_inject_nmi(struct kvm_vcpu *vcpu)
}
void
+kvm_inject_gp(struct kvm_vcpu *vcpu, uint32_t error_code)
+{
+ kvm_queue_exception_e(vcpu, GP_VECTOR, error_code);
+}
+
+void
kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, uint32_t error_code)
{
kvm_multiple_exception(vcpu, nr, 1, error_code);
@@ -4600,6 +4626,24 @@ typedef struct fxsave {
#endif
} fxsave_t;
+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");
+}
+
int
kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
{
@@ -5248,8 +5292,284 @@ kvm_va2pa(caddr_t va)
return (pa);
}
+uint32_t
+get_rdx_init_val(void)
+{
+ return (0x600); /* P6 family */
+}
+
+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
-kvm_migrate_timers(struct kvm_vcpu *vcpu)
+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));
+}
+
+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);
+}
+
+unsigned long
+read_msr(unsigned long msr)
+{
+ uint64_t value;
+
+ rdmsrl(msr, value);
+ return (value);
+}
+
+uint64_t
+native_read_msr_safe(unsigned int msr, int *err)
+{
+ DECLARE_ARGS(val, low, high);
+ uint64_t ret = 0;
+ on_trap_data_t otd;
+
+ if (on_trap(&otd, OT_DATA_ACCESS) == 0) {
+ ret = native_read_msr(msr);
+ *err = 0;
+ } else {
+ *err = EINVAL; /* XXX probably not right... */
+ }
+ no_trap();
+
+ return (ret);
+}
+
+/* Can be uninlined because referenced by paravirt */
+int
+native_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
+{
+ int err = 0;
+ on_trap_data_t otd;
+
+ if (on_trap(&otd, OT_DATA_ACCESS) == 0) {
+ native_write_msr(msr, low, high);
+ } else {
+ err = EINVAL; /* XXX probably not right... */
+ }
+ no_trap();
+
+ return (err);
+}
+
+unsigned long
+kvm_read_tr_base(void)
+{
+ unsigned short tr;
+ __asm__("str %0" : "=g"(tr));
+ return (segment_base(tr));
+}
+
+unsigned short
+kvm_read_fs(void)
+{
+ unsigned short seg;
+ __asm__("mov %%fs, %0" : "=g"(seg));
+ return (seg);
+}
+
+unsigned short
+kvm_read_gs(void)
+{
+ unsigned short seg;
+ __asm__("mov %%gs, %0" : "=g"(seg));
+ return (seg);
+}
+
+unsigned short
+kvm_read_ldt(void)
+{
+ unsigned short ldt;
+ __asm__("sldt %0" : "=g"(ldt));
+ return (ldt);
+}
+
+void
+kvm_load_fs(unsigned short sel)
+{
+ __asm__("mov %0, %%fs" : : "rm"(sel));
+}
+
+void
+kvm_load_gs(unsigned short sel)
+{
+ __asm__("mov %0, %%gs" : : "rm"(sel));
+}
+
+void
+kvm_load_ldt(unsigned short sel)
+{
+ __asm__("lldt %0" : : "rm"(sel));
+}
+
+
+void
+kvm_get_idt(struct descriptor_table *table)
+{
+ __asm__("sidt %0" : "=m"(*table));
+}
+
+void
+kvm_get_gdt(struct descriptor_table *table)
+{
+ __asm__("sgdt %0" : "=m"(*table));
+}
+
+/*
+ * Volatile isn't enough to prevent the compiler from reordering the
+ * read/write functions for the control registers and messing everything up.
+ * A memory clobber would solve the problem, but would prevent reordering of
+ * all loads stores around it, which can hurt performance. Solution is to
+ * use a variable and mimic reads and writes to it to enforce serialization
+ */
+static unsigned long __force_order;
+
+unsigned long
+native_read_cr0(void)
+{
+ unsigned long val;
+ __asm__ volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order));
+ return (val);
+}
+
+unsigned long
+native_read_cr4(void)
+{
+ unsigned long val;
+ __asm__ volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order));
+ return (val);
+}
+
+unsigned long
+native_read_cr3(void)
+{
+ unsigned long val;
+ __asm__ volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order));
+ return (val);
+}
+
+inline unsigned long
+get_desc_limit(const struct desc_struct *desc)
+{
+ return (desc->c.b.limit0 | (desc->c.b.limit << 16));
+}
+
+unsigned long
+get_desc_base(const struct desc_struct *desc)
+{
+ return (unsigned)(desc->c.b.base0 | ((desc->c.b.base1) << 16) |
+ ((desc->c.b.base2) << 24));
+}
+
+inline void
+kvm_clear_exception_queue(struct kvm_vcpu *vcpu)
+{
+ vcpu->arch.exception.pending = 0;
+}
+
+inline void
+kvm_queue_interrupt(struct kvm_vcpu *vcpu, uint8_t vector, int soft)
+{
+ vcpu->arch.interrupt.pending = 1;
+ vcpu->arch.interrupt.soft = soft;
+ vcpu->arch.interrupt.nr = vector;
+}
+
+inline void
+kvm_clear_interrupt_queue(struct kvm_vcpu *vcpu)
+{
+ vcpu->arch.interrupt.pending = 0;
+}
+
+int
+kvm_event_needs_reinjection(struct kvm_vcpu *vcpu)
+{
+ return (vcpu->arch.exception.pending || vcpu->arch.interrupt.pending ||
+ vcpu->arch.nmi_injected);
+}
+
+inline int
+kvm_exception_is_soft(unsigned int nr)
+{
+ return (nr == BP_VECTOR) || (nr == OF_VECTOR);
+}
+
+inline int
+is_protmode(struct kvm_vcpu *vcpu)
+{
+ return (kvm_read_cr0_bits(vcpu, X86_CR0_PE));
+}
+
+int
+is_long_mode(struct kvm_vcpu *vcpu)
+{
+#ifdef CONFIG_X86_64
+ return (vcpu->arch.efer & EFER_LMA);
+#else
+ return (0);
+#endif
+}
+
+inline int
+is_pae(struct kvm_vcpu *vcpu)
+{
+ return (kvm_read_cr4_bits(vcpu, X86_CR4_PAE));
+}
+
+int
+is_pse(struct kvm_vcpu *vcpu)
+{
+ return (kvm_read_cr4_bits(vcpu, X86_CR4_PSE));
+}
+
+int
+is_paging(struct kvm_vcpu *vcpu)
+{
+ return (kvm_read_cr0_bits(vcpu, X86_CR0_PG));
+}
+
+uint32_t
+bit(int bitno)
{
- set_bit(KVM_REQ_MIGRATE_TIMER, &vcpu->requests);
+ return (1 << (bitno & 31));
}
diff --git a/msr.h b/msr.h
index fe833d0..ad29331 100644
--- a/msr.h
+++ b/msr.h
@@ -132,15 +132,6 @@ do { \
(high) = (uint32_t)(_l >> 32); \
} while (0)
-#define rdtscp(low, high, aux) \
-do { \
- unsigned long long _val = native_read_tscp(&(aux)); \
- (low) = (uint32_t)_val; \
- (high) = (uint32_t)(_val >> 32); \
-} while (0)
-
-#define rdtscpll(val, aux) (val) = native_read_tscp(&(aux))
-
#endif /* !CONFIG_PARAVIRT */