aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/book3s_hv_rmhandlers.S
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2011-06-28 20:22:05 -0400
committerAvi Kivity <avi@redhat.com>2011-07-12 06:16:55 -0400
commita8606e20e41a8149456bafdf76ad29d47672027c (patch)
treeb50699b3e41fa234b32b01cf5b79ba7bc2ff1f14 /arch/powerpc/kvm/book3s_hv_rmhandlers.S
parentde56a948b9182fbcf92cb8212f114de096c2d574 (diff)
KVM: PPC: Handle some PAPR hcalls in the kernel
This adds the infrastructure for handling PAPR hcalls in the kernel, either early in the guest exit path while we are still in real mode, or later once the MMU has been turned back on and we are in the full kernel context. The advantage of handling hcalls in real mode if possible is that we avoid two partition switches -- and this will become more important when we support SMT4 guests, since a partition switch means we have to pull all of the threads in the core out of the guest. The disadvantage is that we can only access the kernel linear mapping, not anything vmalloced or ioremapped, since the MMU is off. This also adds code to handle the following hcalls in real mode: H_ENTER Add an HPTE to the hashed page table H_REMOVE Remove an HPTE from the hashed page table H_READ Read HPTEs from the hashed page table H_PROTECT Change the protection bits in an HPTE H_BULK_REMOVE Remove up to 4 HPTEs from the hashed page table H_SET_DABR Set the data address breakpoint register Plus code to handle the following hcalls in the kernel: H_CEDE Idle the vcpu until an interrupt or H_PROD hcall arrives H_PROD Wake up a ceded vcpu H_REGISTER_VPA Register a virtual processor area (VPA) The code that runs in real mode has to be in the base kernel, not in the module, if KVM is compiled as a module. The real-mode code can only access the kernel linear mapping, not vmalloc or ioremap space. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc/kvm/book3s_hv_rmhandlers.S')
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S158
1 files changed, 155 insertions, 3 deletions
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 9af264840b9..319ff63b1f3 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -166,6 +166,14 @@ kvmppc_hv_entry:
166 /* Save R1 in the PACA */ 166 /* Save R1 in the PACA */
167 std r1, HSTATE_HOST_R1(r13) 167 std r1, HSTATE_HOST_R1(r13)
168 168
169 /* Increment yield count if they have a VPA */
170 ld r3, VCPU_VPA(r4)
171 cmpdi r3, 0
172 beq 25f
173 lwz r5, LPPACA_YIELDCOUNT(r3)
174 addi r5, r5, 1
175 stw r5, LPPACA_YIELDCOUNT(r3)
17625:
169 /* Load up DAR and DSISR */ 177 /* Load up DAR and DSISR */
170 ld r5, VCPU_DAR(r4) 178 ld r5, VCPU_DAR(r4)
171 lwz r6, VCPU_DSISR(r4) 179 lwz r6, VCPU_DSISR(r4)
@@ -401,6 +409,10 @@ kvmppc_interrupt:
401 cmpwi r3,0 409 cmpwi r3,0
402 bge ignore_hdec 410 bge ignore_hdec
4032: 4112:
412 /* See if this is something we can handle in real mode */
413 cmpwi r12,BOOK3S_INTERRUPT_SYSCALL
414 beq hcall_try_real_mode
415hcall_real_cont:
404 416
405 /* Check for mediated interrupts (could be done earlier really ...) */ 417 /* Check for mediated interrupts (could be done earlier really ...) */
406 cmpwi r12,BOOK3S_INTERRUPT_EXTERNAL 418 cmpwi r12,BOOK3S_INTERRUPT_EXTERNAL
@@ -579,13 +591,28 @@ hdec_soon:
579 std r5, VCPU_SPRG2(r9) 591 std r5, VCPU_SPRG2(r9)
580 std r6, VCPU_SPRG3(r9) 592 std r6, VCPU_SPRG3(r9)
581 593
582 /* Save PMU registers */ 594 /* Increment yield count if they have a VPA */
595 ld r8, VCPU_VPA(r9) /* do they have a VPA? */
596 cmpdi r8, 0
597 beq 25f
598 lwz r3, LPPACA_YIELDCOUNT(r8)
599 addi r3, r3, 1
600 stw r3, LPPACA_YIELDCOUNT(r8)
60125:
602 /* Save PMU registers if requested */
603 /* r8 and cr0.eq are live here */
583 li r3, 1 604 li r3, 1
584 sldi r3, r3, 31 /* MMCR0_FC (freeze counters) bit */ 605 sldi r3, r3, 31 /* MMCR0_FC (freeze counters) bit */
585 mfspr r4, SPRN_MMCR0 /* save MMCR0 */ 606 mfspr r4, SPRN_MMCR0 /* save MMCR0 */
586 mtspr SPRN_MMCR0, r3 /* freeze all counters, disable ints */ 607 mtspr SPRN_MMCR0, r3 /* freeze all counters, disable ints */
587 isync 608 isync
588 mfspr r5, SPRN_MMCR1 609 beq 21f /* if no VPA, save PMU stuff anyway */
610 lbz r7, LPPACA_PMCINUSE(r8)
611 cmpwi r7, 0 /* did they ask for PMU stuff to be saved? */
612 bne 21f
613 std r3, VCPU_MMCR(r9) /* if not, set saved MMCR0 to FC */
614 b 22f
61521: mfspr r5, SPRN_MMCR1
589 mfspr r6, SPRN_MMCRA 616 mfspr r6, SPRN_MMCRA
590 std r4, VCPU_MMCR(r9) 617 std r4, VCPU_MMCR(r9)
591 std r5, VCPU_MMCR + 8(r9) 618 std r5, VCPU_MMCR + 8(r9)
@@ -676,6 +703,125 @@ hdec_soon:
676 mfspr r7,SPRN_HDSISR 703 mfspr r7,SPRN_HDSISR
677 b 7b 704 b 7b
678 705
706/*
707 * Try to handle an hcall in real mode.
708 * Returns to the guest if we handle it, or continues on up to
709 * the kernel if we can't (i.e. if we don't have a handler for
710 * it, or if the handler returns H_TOO_HARD).
711 */
712 .globl hcall_try_real_mode
713hcall_try_real_mode:
714 ld r3,VCPU_GPR(r3)(r9)
715 andi. r0,r11,MSR_PR
716 bne hcall_real_cont
717 clrrdi r3,r3,2
718 cmpldi r3,hcall_real_table_end - hcall_real_table
719 bge hcall_real_cont
720 LOAD_REG_ADDR(r4, hcall_real_table)
721 lwzx r3,r3,r4
722 cmpwi r3,0
723 beq hcall_real_cont
724 add r3,r3,r4
725 mtctr r3
726 mr r3,r9 /* get vcpu pointer */
727 ld r4,VCPU_GPR(r4)(r9)
728 bctrl
729 cmpdi r3,H_TOO_HARD
730 beq hcall_real_fallback
731 ld r4,HSTATE_KVM_VCPU(r13)
732 std r3,VCPU_GPR(r3)(r4)
733 ld r10,VCPU_PC(r4)
734 ld r11,VCPU_MSR(r4)
735 b fast_guest_return
736
737 /* We've attempted a real mode hcall, but it's punted it back
738 * to userspace. We need to restore some clobbered volatiles
739 * before resuming the pass-it-to-qemu path */
740hcall_real_fallback:
741 li r12,BOOK3S_INTERRUPT_SYSCALL
742 ld r9, HSTATE_KVM_VCPU(r13)
743 ld r11, VCPU_MSR(r9)
744
745 b hcall_real_cont
746
747 .globl hcall_real_table
748hcall_real_table:
749 .long 0 /* 0 - unused */
750 .long .kvmppc_h_remove - hcall_real_table
751 .long .kvmppc_h_enter - hcall_real_table
752 .long .kvmppc_h_read - hcall_real_table
753 .long 0 /* 0x10 - H_CLEAR_MOD */
754 .long 0 /* 0x14 - H_CLEAR_REF */
755 .long .kvmppc_h_protect - hcall_real_table
756 .long 0 /* 0x1c - H_GET_TCE */
757 .long 0 /* 0x20 - H_SET_TCE */
758 .long 0 /* 0x24 - H_SET_SPRG0 */
759 .long .kvmppc_h_set_dabr - hcall_real_table
760 .long 0 /* 0x2c */
761 .long 0 /* 0x30 */
762 .long 0 /* 0x34 */
763 .long 0 /* 0x38 */
764 .long 0 /* 0x3c */
765 .long 0 /* 0x40 */
766 .long 0 /* 0x44 */
767 .long 0 /* 0x48 */
768 .long 0 /* 0x4c */
769 .long 0 /* 0x50 */
770 .long 0 /* 0x54 */
771 .long 0 /* 0x58 */
772 .long 0 /* 0x5c */
773 .long 0 /* 0x60 */
774 .long 0 /* 0x64 */
775 .long 0 /* 0x68 */
776 .long 0 /* 0x6c */
777 .long 0 /* 0x70 */
778 .long 0 /* 0x74 */
779 .long 0 /* 0x78 */
780 .long 0 /* 0x7c */
781 .long 0 /* 0x80 */
782 .long 0 /* 0x84 */
783 .long 0 /* 0x88 */
784 .long 0 /* 0x8c */
785 .long 0 /* 0x90 */
786 .long 0 /* 0x94 */
787 .long 0 /* 0x98 */
788 .long 0 /* 0x9c */
789 .long 0 /* 0xa0 */
790 .long 0 /* 0xa4 */
791 .long 0 /* 0xa8 */
792 .long 0 /* 0xac */
793 .long 0 /* 0xb0 */
794 .long 0 /* 0xb4 */
795 .long 0 /* 0xb8 */
796 .long 0 /* 0xbc */
797 .long 0 /* 0xc0 */
798 .long 0 /* 0xc4 */
799 .long 0 /* 0xc8 */
800 .long 0 /* 0xcc */
801 .long 0 /* 0xd0 */
802 .long 0 /* 0xd4 */
803 .long 0 /* 0xd8 */
804 .long 0 /* 0xdc */
805 .long 0 /* 0xe0 */
806 .long 0 /* 0xe4 */
807 .long 0 /* 0xe8 */
808 .long 0 /* 0xec */
809 .long 0 /* 0xf0 */
810 .long 0 /* 0xf4 */
811 .long 0 /* 0xf8 */
812 .long 0 /* 0xfc */
813 .long 0 /* 0x100 */
814 .long 0 /* 0x104 */
815 .long 0 /* 0x108 */
816 .long 0 /* 0x10c */
817 .long 0 /* 0x110 */
818 .long 0 /* 0x114 */
819 .long 0 /* 0x118 */
820 .long 0 /* 0x11c */
821 .long 0 /* 0x120 */
822 .long .kvmppc_h_bulk_remove - hcall_real_table
823hcall_real_table_end:
824
679ignore_hdec: 825ignore_hdec:
680 mr r4,r9 826 mr r4,r9
681 b fast_guest_return 827 b fast_guest_return
@@ -688,10 +834,16 @@ bounce_ext_interrupt:
688 LOAD_REG_IMMEDIATE(r11,MSR_SF | MSR_ME); 834 LOAD_REG_IMMEDIATE(r11,MSR_SF | MSR_ME);
689 b fast_guest_return 835 b fast_guest_return
690 836
837_GLOBAL(kvmppc_h_set_dabr)
838 std r4,VCPU_DABR(r3)
839 mtspr SPRN_DABR,r4
840 li r3,0
841 blr
842
691/* 843/*
692 * Save away FP, VMX and VSX registers. 844 * Save away FP, VMX and VSX registers.
693 * r3 = vcpu pointer 845 * r3 = vcpu pointer
694*/ 846 */
695_GLOBAL(kvmppc_save_fp) 847_GLOBAL(kvmppc_save_fp)
696 mfmsr r9 848 mfmsr r9
697 ori r8,r9,MSR_FP 849 ori r8,r9,MSR_FP