aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/kvm_main.c
diff options
context:
space:
mode:
authorHollis Blanchard <hollisb@us.ibm.com>2007-10-31 18:24:24 -0400
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:53:00 -0500
commit8776e5194f7bb847906e3561c4dba12ed66ebfb6 (patch)
treea6c23e44a89873abf711b73dfd7444673d5b6d1b /drivers/kvm/kvm_main.c
parent417bc3041f5e66df1ce7f03d8fc481c3b12f250a (diff)
KVM: Portability: Move x86 instruction emulation code to x86.c
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/kvm_main.c')
-rw-r--r--drivers/kvm/kvm_main.c177
1 files changed, 1 insertions, 176 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index 58a5f399ad85..57573ebf02ba 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -789,7 +789,7 @@ void mark_page_dirty(struct kvm *kvm, gfn_t gfn)
789/* 789/*
790 * The vCPU has executed a HLT instruction with in-kernel mode enabled. 790 * The vCPU has executed a HLT instruction with in-kernel mode enabled.
791 */ 791 */
792static void kvm_vcpu_block(struct kvm_vcpu *vcpu) 792void kvm_vcpu_block(struct kvm_vcpu *vcpu)
793{ 793{
794 DECLARE_WAITQUEUE(wait, current); 794 DECLARE_WAITQUEUE(wait, current);
795 795
@@ -812,144 +812,6 @@ static void kvm_vcpu_block(struct kvm_vcpu *vcpu)
812 remove_wait_queue(&vcpu->wq, &wait); 812 remove_wait_queue(&vcpu->wq, &wait);
813} 813}
814 814
815int kvm_emulate_halt(struct kvm_vcpu *vcpu)
816{
817 ++vcpu->stat.halt_exits;
818 if (irqchip_in_kernel(vcpu->kvm)) {
819 vcpu->mp_state = VCPU_MP_STATE_HALTED;
820 kvm_vcpu_block(vcpu);
821 if (vcpu->mp_state != VCPU_MP_STATE_RUNNABLE)
822 return -EINTR;
823 return 1;
824 } else {
825 vcpu->run->exit_reason = KVM_EXIT_HLT;
826 return 0;
827 }
828}
829EXPORT_SYMBOL_GPL(kvm_emulate_halt);
830
831int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
832{
833 unsigned long nr, a0, a1, a2, a3, ret;
834
835 kvm_x86_ops->cache_regs(vcpu);
836
837 nr = vcpu->regs[VCPU_REGS_RAX];
838 a0 = vcpu->regs[VCPU_REGS_RBX];
839 a1 = vcpu->regs[VCPU_REGS_RCX];
840 a2 = vcpu->regs[VCPU_REGS_RDX];
841 a3 = vcpu->regs[VCPU_REGS_RSI];
842
843 if (!is_long_mode(vcpu)) {
844 nr &= 0xFFFFFFFF;
845 a0 &= 0xFFFFFFFF;
846 a1 &= 0xFFFFFFFF;
847 a2 &= 0xFFFFFFFF;
848 a3 &= 0xFFFFFFFF;
849 }
850
851 switch (nr) {
852 default:
853 ret = -KVM_ENOSYS;
854 break;
855 }
856 vcpu->regs[VCPU_REGS_RAX] = ret;
857 kvm_x86_ops->decache_regs(vcpu);
858 return 0;
859}
860EXPORT_SYMBOL_GPL(kvm_emulate_hypercall);
861
862int kvm_fix_hypercall(struct kvm_vcpu *vcpu)
863{
864 char instruction[3];
865 int ret = 0;
866
867 mutex_lock(&vcpu->kvm->lock);
868
869 /*
870 * Blow out the MMU to ensure that no other VCPU has an active mapping
871 * to ensure that the updated hypercall appears atomically across all
872 * VCPUs.
873 */
874 kvm_mmu_zap_all(vcpu->kvm);
875
876 kvm_x86_ops->cache_regs(vcpu);
877 kvm_x86_ops->patch_hypercall(vcpu, instruction);
878 if (emulator_write_emulated(vcpu->rip, instruction, 3, vcpu)
879 != X86EMUL_CONTINUE)
880 ret = -EFAULT;
881
882 mutex_unlock(&vcpu->kvm->lock);
883
884 return ret;
885}
886
887static u64 mk_cr_64(u64 curr_cr, u32 new_val)
888{
889 return (curr_cr & ~((1ULL << 32) - 1)) | new_val;
890}
891
892void realmode_lgdt(struct kvm_vcpu *vcpu, u16 limit, unsigned long base)
893{
894 struct descriptor_table dt = { limit, base };
895
896 kvm_x86_ops->set_gdt(vcpu, &dt);
897}
898
899void realmode_lidt(struct kvm_vcpu *vcpu, u16 limit, unsigned long base)
900{
901 struct descriptor_table dt = { limit, base };
902
903 kvm_x86_ops->set_idt(vcpu, &dt);
904}
905
906void realmode_lmsw(struct kvm_vcpu *vcpu, unsigned long msw,
907 unsigned long *rflags)
908{
909 lmsw(vcpu, msw);
910 *rflags = kvm_x86_ops->get_rflags(vcpu);
911}
912
913unsigned long realmode_get_cr(struct kvm_vcpu *vcpu, int cr)
914{
915 kvm_x86_ops->decache_cr4_guest_bits(vcpu);
916 switch (cr) {
917 case 0:
918 return vcpu->cr0;
919 case 2:
920 return vcpu->cr2;
921 case 3:
922 return vcpu->cr3;
923 case 4:
924 return vcpu->cr4;
925 default:
926 vcpu_printf(vcpu, "%s: unexpected cr %u\n", __FUNCTION__, cr);
927 return 0;
928 }
929}
930
931void realmode_set_cr(struct kvm_vcpu *vcpu, int cr, unsigned long val,
932 unsigned long *rflags)
933{
934 switch (cr) {
935 case 0:
936 set_cr0(vcpu, mk_cr_64(vcpu->cr0, val));
937 *rflags = kvm_x86_ops->get_rflags(vcpu);
938 break;
939 case 2:
940 vcpu->cr2 = val;
941 break;
942 case 3:
943 set_cr3(vcpu, val);
944 break;
945 case 4:
946 set_cr4(vcpu, mk_cr_64(vcpu->cr4, val));
947 break;
948 default:
949 vcpu_printf(vcpu, "%s: unexpected cr %u\n", __FUNCTION__, cr);
950 }
951}
952
953void kvm_resched(struct kvm_vcpu *vcpu) 815void kvm_resched(struct kvm_vcpu *vcpu)
954{ 816{
955 if (!need_resched()) 817 if (!need_resched())
@@ -958,43 +820,6 @@ void kvm_resched(struct kvm_vcpu *vcpu)
958} 820}
959EXPORT_SYMBOL_GPL(kvm_resched); 821EXPORT_SYMBOL_GPL(kvm_resched);
960 822
961void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
962{
963 int i;
964 u32 function;
965 struct kvm_cpuid_entry *e, *best;
966
967 kvm_x86_ops->cache_regs(vcpu);
968 function = vcpu->regs[VCPU_REGS_RAX];
969 vcpu->regs[VCPU_REGS_RAX] = 0;
970 vcpu->regs[VCPU_REGS_RBX] = 0;
971 vcpu->regs[VCPU_REGS_RCX] = 0;
972 vcpu->regs[VCPU_REGS_RDX] = 0;
973 best = NULL;
974 for (i = 0; i < vcpu->cpuid_nent; ++i) {
975 e = &vcpu->cpuid_entries[i];
976 if (e->function == function) {
977 best = e;
978 break;
979 }
980 /*
981 * Both basic or both extended?
982 */
983 if (((e->function ^ function) & 0x80000000) == 0)
984 if (!best || e->function > best->function)
985 best = e;
986 }
987 if (best) {
988 vcpu->regs[VCPU_REGS_RAX] = best->eax;
989 vcpu->regs[VCPU_REGS_RBX] = best->ebx;
990 vcpu->regs[VCPU_REGS_RCX] = best->ecx;
991 vcpu->regs[VCPU_REGS_RDX] = best->edx;
992 }
993 kvm_x86_ops->decache_regs(vcpu);
994 kvm_x86_ops->skip_emulated_instruction(vcpu);
995}
996EXPORT_SYMBOL_GPL(kvm_emulate_cpuid);
997
998/* 823/*
999 * Check if userspace requested an interrupt window, and that the 824 * Check if userspace requested an interrupt window, and that the
1000 * interrupt window is open. 825 * interrupt window is open.