aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/book3s.c
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2010-07-29 08:47:43 -0400
committerAvi Kivity <avi@redhat.com>2010-10-24 04:50:43 -0400
commit666e7252a15b7fc4a116e65deaf6da5e4ce660e3 (patch)
treee7a56f03cb4e181eacd4f481fb3e6e038ad05b82 /arch/powerpc/kvm/book3s.c
parent96bc451a153297bf1f99ef2d633d512ea349ae7a (diff)
KVM: PPC: Convert MSR to shared page
One of the most obvious registers to share with the guest directly is the MSR. The MSR contains the "interrupts enabled" flag which the guest has to toggle in critical sections. So in order to bring the overhead of interrupt en- and disabling down, let's put msr into the shared page. Keep in mind that even though you can fully read its contents, writing to it doesn't always update all state. There are a few safe fields that don't require hypervisor interaction. See the documentation for a list of MSR bits that are safe to be set from inside the guest. Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc/kvm/book3s.c')
-rw-r--r--arch/powerpc/kvm/book3s.c65
1 files changed, 35 insertions, 30 deletions
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index b3385dd6f28d..2efe69240e1b 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -115,31 +115,31 @@ static u32 kvmppc_get_dec(struct kvm_vcpu *vcpu)
115 115
116static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu) 116static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
117{ 117{
118 vcpu->arch.shadow_msr = vcpu->arch.msr; 118 ulong smsr = vcpu->arch.shared->msr;
119
119 /* Guest MSR values */ 120 /* Guest MSR values */
120 vcpu->arch.shadow_msr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | 121 smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_DE;
121 MSR_BE | MSR_DE;
122 /* Process MSR values */ 122 /* Process MSR values */
123 vcpu->arch.shadow_msr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | 123 smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE;
124 MSR_EE;
125 /* External providers the guest reserved */ 124 /* External providers the guest reserved */
126 vcpu->arch.shadow_msr |= (vcpu->arch.msr & vcpu->arch.guest_owned_ext); 125 smsr |= (vcpu->arch.shared->msr & vcpu->arch.guest_owned_ext);
127 /* 64-bit Process MSR values */ 126 /* 64-bit Process MSR values */
128#ifdef CONFIG_PPC_BOOK3S_64 127#ifdef CONFIG_PPC_BOOK3S_64
129 vcpu->arch.shadow_msr |= MSR_ISF | MSR_HV; 128 smsr |= MSR_ISF | MSR_HV;
130#endif 129#endif
130 vcpu->arch.shadow_msr = smsr;
131} 131}
132 132
133void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr) 133void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
134{ 134{
135 ulong old_msr = vcpu->arch.msr; 135 ulong old_msr = vcpu->arch.shared->msr;
136 136
137#ifdef EXIT_DEBUG 137#ifdef EXIT_DEBUG
138 printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr); 138 printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr);
139#endif 139#endif
140 140
141 msr &= to_book3s(vcpu)->msr_mask; 141 msr &= to_book3s(vcpu)->msr_mask;
142 vcpu->arch.msr = msr; 142 vcpu->arch.shared->msr = msr;
143 kvmppc_recalc_shadow_msr(vcpu); 143 kvmppc_recalc_shadow_msr(vcpu);
144 144
145 if (msr & (MSR_WE|MSR_POW)) { 145 if (msr & (MSR_WE|MSR_POW)) {
@@ -149,21 +149,21 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr)
149 } 149 }
150 } 150 }
151 151
152 if ((vcpu->arch.msr & (MSR_PR|MSR_IR|MSR_DR)) != 152 if ((vcpu->arch.shared->msr & (MSR_PR|MSR_IR|MSR_DR)) !=
153 (old_msr & (MSR_PR|MSR_IR|MSR_DR))) { 153 (old_msr & (MSR_PR|MSR_IR|MSR_DR))) {
154 kvmppc_mmu_flush_segments(vcpu); 154 kvmppc_mmu_flush_segments(vcpu);
155 kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu)); 155 kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu));
156 } 156 }
157 157
158 /* Preload FPU if it's enabled */ 158 /* Preload FPU if it's enabled */
159 if (vcpu->arch.msr & MSR_FP) 159 if (vcpu->arch.shared->msr & MSR_FP)
160 kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP); 160 kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
161} 161}
162 162
163void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags) 163void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags)
164{ 164{
165 vcpu->arch.srr0 = kvmppc_get_pc(vcpu); 165 vcpu->arch.srr0 = kvmppc_get_pc(vcpu);
166 vcpu->arch.srr1 = vcpu->arch.msr | flags; 166 vcpu->arch.srr1 = vcpu->arch.shared->msr | flags;
167 kvmppc_set_pc(vcpu, to_book3s(vcpu)->hior + vec); 167 kvmppc_set_pc(vcpu, to_book3s(vcpu)->hior + vec);
168 vcpu->arch.mmu.reset_msr(vcpu); 168 vcpu->arch.mmu.reset_msr(vcpu);
169} 169}
@@ -254,11 +254,11 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
254 254
255 switch (priority) { 255 switch (priority) {
256 case BOOK3S_IRQPRIO_DECREMENTER: 256 case BOOK3S_IRQPRIO_DECREMENTER:
257 deliver = vcpu->arch.msr & MSR_EE; 257 deliver = vcpu->arch.shared->msr & MSR_EE;
258 vec = BOOK3S_INTERRUPT_DECREMENTER; 258 vec = BOOK3S_INTERRUPT_DECREMENTER;
259 break; 259 break;
260 case BOOK3S_IRQPRIO_EXTERNAL: 260 case BOOK3S_IRQPRIO_EXTERNAL:
261 deliver = vcpu->arch.msr & MSR_EE; 261 deliver = vcpu->arch.shared->msr & MSR_EE;
262 vec = BOOK3S_INTERRUPT_EXTERNAL; 262 vec = BOOK3S_INTERRUPT_EXTERNAL;
263 break; 263 break;
264 case BOOK3S_IRQPRIO_SYSTEM_RESET: 264 case BOOK3S_IRQPRIO_SYSTEM_RESET:
@@ -437,7 +437,7 @@ static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
437static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data, 437static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data,
438 struct kvmppc_pte *pte) 438 struct kvmppc_pte *pte)
439{ 439{
440 int relocated = (vcpu->arch.msr & (data ? MSR_DR : MSR_IR)); 440 int relocated = (vcpu->arch.shared->msr & (data ? MSR_DR : MSR_IR));
441 int r; 441 int r;
442 442
443 if (relocated) { 443 if (relocated) {
@@ -545,8 +545,8 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
545 int page_found = 0; 545 int page_found = 0;
546 struct kvmppc_pte pte; 546 struct kvmppc_pte pte;
547 bool is_mmio = false; 547 bool is_mmio = false;
548 bool dr = (vcpu->arch.msr & MSR_DR) ? true : false; 548 bool dr = (vcpu->arch.shared->msr & MSR_DR) ? true : false;
549 bool ir = (vcpu->arch.msr & MSR_IR) ? true : false; 549 bool ir = (vcpu->arch.shared->msr & MSR_IR) ? true : false;
550 u64 vsid; 550 u64 vsid;
551 551
552 relocated = data ? dr : ir; 552 relocated = data ? dr : ir;
@@ -563,7 +563,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
563 pte.vpage = eaddr >> 12; 563 pte.vpage = eaddr >> 12;
564 } 564 }
565 565
566 switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) { 566 switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) {
567 case 0: 567 case 0:
568 pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12)); 568 pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12));
569 break; 569 break;
@@ -571,7 +571,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
571 case MSR_IR: 571 case MSR_IR:
572 vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid); 572 vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid);
573 573
574 if ((vcpu->arch.msr & (MSR_DR|MSR_IR)) == MSR_DR) 574 if ((vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) == MSR_DR)
575 pte.vpage |= ((u64)VSID_REAL_DR << (SID_SHIFT - 12)); 575 pte.vpage |= ((u64)VSID_REAL_DR << (SID_SHIFT - 12));
576 else 576 else
577 pte.vpage |= ((u64)VSID_REAL_IR << (SID_SHIFT - 12)); 577 pte.vpage |= ((u64)VSID_REAL_IR << (SID_SHIFT - 12));
@@ -596,14 +596,16 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
596 /* Page not found in guest PTE entries */ 596 /* Page not found in guest PTE entries */
597 vcpu->arch.dear = kvmppc_get_fault_dar(vcpu); 597 vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
598 to_book3s(vcpu)->dsisr = to_svcpu(vcpu)->fault_dsisr; 598 to_book3s(vcpu)->dsisr = to_svcpu(vcpu)->fault_dsisr;
599 vcpu->arch.msr |= (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL); 599 vcpu->arch.shared->msr |=
600 (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
600 kvmppc_book3s_queue_irqprio(vcpu, vec); 601 kvmppc_book3s_queue_irqprio(vcpu, vec);
601 } else if (page_found == -EPERM) { 602 } else if (page_found == -EPERM) {
602 /* Storage protection */ 603 /* Storage protection */
603 vcpu->arch.dear = kvmppc_get_fault_dar(vcpu); 604 vcpu->arch.dear = kvmppc_get_fault_dar(vcpu);
604 to_book3s(vcpu)->dsisr = to_svcpu(vcpu)->fault_dsisr & ~DSISR_NOHPTE; 605 to_book3s(vcpu)->dsisr = to_svcpu(vcpu)->fault_dsisr & ~DSISR_NOHPTE;
605 to_book3s(vcpu)->dsisr |= DSISR_PROTFAULT; 606 to_book3s(vcpu)->dsisr |= DSISR_PROTFAULT;
606 vcpu->arch.msr |= (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL); 607 vcpu->arch.shared->msr |=
608 (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL);
607 kvmppc_book3s_queue_irqprio(vcpu, vec); 609 kvmppc_book3s_queue_irqprio(vcpu, vec);
608 } else if (page_found == -EINVAL) { 610 } else if (page_found == -EINVAL) {
609 /* Page not found in guest SLB */ 611 /* Page not found in guest SLB */
@@ -695,9 +697,11 @@ static int kvmppc_read_inst(struct kvm_vcpu *vcpu)
695 697
696 ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false); 698 ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false);
697 if (ret == -ENOENT) { 699 if (ret == -ENOENT) {
698 vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 33, 33, 1); 700 ulong msr = vcpu->arch.shared->msr;
699 vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 34, 36, 0); 701
700 vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 42, 47, 0); 702 msr = kvmppc_set_field(msr, 33, 33, 1);
703 msr = kvmppc_set_field(msr, 34, 36, 0);
704 vcpu->arch.shared->msr = kvmppc_set_field(msr, 42, 47, 0);
701 kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE); 705 kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE);
702 return EMULATE_AGAIN; 706 return EMULATE_AGAIN;
703 } 707 }
@@ -736,7 +740,7 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
736 if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE) 740 if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE)
737 return RESUME_GUEST; 741 return RESUME_GUEST;
738 742
739 if (!(vcpu->arch.msr & msr)) { 743 if (!(vcpu->arch.shared->msr & msr)) {
740 kvmppc_book3s_queue_irqprio(vcpu, exit_nr); 744 kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
741 return RESUME_GUEST; 745 return RESUME_GUEST;
742 } 746 }
@@ -804,7 +808,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
804 if ((exit_nr != 0x900) && (exit_nr != 0x500)) 808 if ((exit_nr != 0x900) && (exit_nr != 0x500))
805 printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | dar=0x%lx | msr=0x%lx\n", 809 printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | dar=0x%lx | msr=0x%lx\n",
806 exit_nr, kvmppc_get_pc(vcpu), kvmppc_get_fault_dar(vcpu), 810 exit_nr, kvmppc_get_pc(vcpu), kvmppc_get_fault_dar(vcpu),
807 vcpu->arch.msr); 811 vcpu->arch.shared->msr);
808#endif 812#endif
809 kvm_resched(vcpu); 813 kvm_resched(vcpu);
810 switch (exit_nr) { 814 switch (exit_nr) {
@@ -836,7 +840,8 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
836 kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL); 840 kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL);
837 r = RESUME_GUEST; 841 r = RESUME_GUEST;
838 } else { 842 } else {
839 vcpu->arch.msr |= to_svcpu(vcpu)->shadow_srr1 & 0x58000000; 843 vcpu->arch.shared->msr |=
844 to_svcpu(vcpu)->shadow_srr1 & 0x58000000;
840 kvmppc_book3s_queue_irqprio(vcpu, exit_nr); 845 kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
841 kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL); 846 kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL);
842 r = RESUME_GUEST; 847 r = RESUME_GUEST;
@@ -904,7 +909,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
904program_interrupt: 909program_interrupt:
905 flags = to_svcpu(vcpu)->shadow_srr1 & 0x1f0000ull; 910 flags = to_svcpu(vcpu)->shadow_srr1 & 0x1f0000ull;
906 911
907 if (vcpu->arch.msr & MSR_PR) { 912 if (vcpu->arch.shared->msr & MSR_PR) {
908#ifdef EXIT_DEBUG 913#ifdef EXIT_DEBUG
909 printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu)); 914 printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu));
910#endif 915#endif
@@ -1052,7 +1057,7 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
1052 regs->ctr = kvmppc_get_ctr(vcpu); 1057 regs->ctr = kvmppc_get_ctr(vcpu);
1053 regs->lr = kvmppc_get_lr(vcpu); 1058 regs->lr = kvmppc_get_lr(vcpu);
1054 regs->xer = kvmppc_get_xer(vcpu); 1059 regs->xer = kvmppc_get_xer(vcpu);
1055 regs->msr = vcpu->arch.msr; 1060 regs->msr = vcpu->arch.shared->msr;
1056 regs->srr0 = vcpu->arch.srr0; 1061 regs->srr0 = vcpu->arch.srr0;
1057 regs->srr1 = vcpu->arch.srr1; 1062 regs->srr1 = vcpu->arch.srr1;
1058 regs->pid = vcpu->arch.pid; 1063 regs->pid = vcpu->arch.pid;
@@ -1353,7 +1358,7 @@ int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
1353 local_irq_enable(); 1358 local_irq_enable();
1354 1359
1355 /* Preload FPU if it's enabled */ 1360 /* Preload FPU if it's enabled */
1356 if (vcpu->arch.msr & MSR_FP) 1361 if (vcpu->arch.shared->msr & MSR_FP)
1357 kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP); 1362 kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
1358 1363
1359 ret = __kvmppc_vcpu_entry(kvm_run, vcpu); 1364 ret = __kvmppc_vcpu_entry(kvm_run, vcpu);