diff options
Diffstat (limited to 'arch/powerpc/kvm/book3s_hv_rmhandlers.S')
-rw-r--r-- | arch/powerpc/kvm/book3s_hv_rmhandlers.S | 92 |
1 files changed, 54 insertions, 38 deletions
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index b70bf22a3ff3..d595033bd449 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <asm/hvcall.h> | 26 | #include <asm/hvcall.h> |
27 | #include <asm/asm-offsets.h> | 27 | #include <asm/asm-offsets.h> |
28 | #include <asm/exception-64s.h> | 28 | #include <asm/exception-64s.h> |
29 | #include <asm/kvm_book3s_asm.h> | ||
29 | 30 | ||
30 | /***************************************************************************** | 31 | /***************************************************************************** |
31 | * * | 32 | * * |
@@ -82,6 +83,7 @@ _GLOBAL(kvmppc_hv_entry_trampoline) | |||
82 | 83 | ||
83 | #define XICS_XIRR 4 | 84 | #define XICS_XIRR 4 |
84 | #define XICS_QIRR 0xc | 85 | #define XICS_QIRR 0xc |
86 | #define XICS_IPI 2 /* interrupt source # for IPIs */ | ||
85 | 87 | ||
86 | /* | 88 | /* |
87 | * We come in here when wakened from nap mode on a secondary hw thread. | 89 | * We come in here when wakened from nap mode on a secondary hw thread. |
@@ -94,26 +96,54 @@ kvm_start_guest: | |||
94 | subi r1,r1,STACK_FRAME_OVERHEAD | 96 | subi r1,r1,STACK_FRAME_OVERHEAD |
95 | ld r2,PACATOC(r13) | 97 | ld r2,PACATOC(r13) |
96 | 98 | ||
97 | /* were we napping due to cede? */ | 99 | li r0,KVM_HWTHREAD_IN_KVM |
98 | lbz r0,HSTATE_NAPPING(r13) | 100 | stb r0,HSTATE_HWTHREAD_STATE(r13) |
99 | cmpwi r0,0 | ||
100 | bne kvm_end_cede | ||
101 | 101 | ||
102 | /* get vcpu pointer */ | 102 | /* NV GPR values from power7_idle() will no longer be valid */ |
103 | ld r4, HSTATE_KVM_VCPU(r13) | 103 | li r0,1 |
104 | stb r0,PACA_NAPSTATELOST(r13) | ||
104 | 105 | ||
105 | /* We got here with an IPI; clear it */ | 106 | /* get vcpu pointer, NULL if we have no vcpu to run */ |
106 | ld r5, HSTATE_XICS_PHYS(r13) | 107 | ld r4,HSTATE_KVM_VCPU(r13) |
107 | li r0, 0xff | 108 | cmpdi cr1,r4,0 |
108 | li r6, XICS_QIRR | 109 | |
109 | li r7, XICS_XIRR | 110 | /* Check the wake reason in SRR1 to see why we got here */ |
110 | lwzcix r8, r5, r7 /* ack the interrupt */ | 111 | mfspr r3,SPRN_SRR1 |
112 | rlwinm r3,r3,44-31,0x7 /* extract wake reason field */ | ||
113 | cmpwi r3,4 /* was it an external interrupt? */ | ||
114 | bne 27f | ||
115 | |||
116 | /* | ||
117 | * External interrupt - for now assume it is an IPI, since we | ||
118 | * should never get any other interrupts sent to offline threads. | ||
119 | * Only do this for secondary threads. | ||
120 | */ | ||
121 | beq cr1,25f | ||
122 | lwz r3,VCPU_PTID(r4) | ||
123 | cmpwi r3,0 | ||
124 | beq 27f | ||
125 | 25: ld r5,HSTATE_XICS_PHYS(r13) | ||
126 | li r0,0xff | ||
127 | li r6,XICS_QIRR | ||
128 | li r7,XICS_XIRR | ||
129 | lwzcix r8,r5,r7 /* get and ack the interrupt */ | ||
111 | sync | 130 | sync |
112 | stbcix r0, r5, r6 /* clear it */ | 131 | clrldi. r9,r8,40 /* get interrupt source ID. */ |
113 | stwcix r8, r5, r7 /* EOI it */ | 132 | beq 27f /* none there? */ |
133 | cmpwi r9,XICS_IPI | ||
134 | bne 26f | ||
135 | stbcix r0,r5,r6 /* clear IPI */ | ||
136 | 26: stwcix r8,r5,r7 /* EOI the interrupt */ | ||
114 | 137 | ||
115 | /* NV GPR values from power7_idle() will no longer be valid */ | 138 | 27: /* XXX should handle hypervisor maintenance interrupts etc. here */ |
116 | stb r0, PACA_NAPSTATELOST(r13) | 139 | |
140 | /* if we have no vcpu to run, go back to sleep */ | ||
141 | beq cr1,kvm_no_guest | ||
142 | |||
143 | /* were we napping due to cede? */ | ||
144 | lbz r0,HSTATE_NAPPING(r13) | ||
145 | cmpwi r0,0 | ||
146 | bne kvm_end_cede | ||
117 | 147 | ||
118 | .global kvmppc_hv_entry | 148 | .global kvmppc_hv_entry |
119 | kvmppc_hv_entry: | 149 | kvmppc_hv_entry: |
@@ -1445,8 +1475,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206) | |||
1445 | * Take a nap until a decrementer or external interrupt occurs, | 1475 | * Take a nap until a decrementer or external interrupt occurs, |
1446 | * with PECE1 (wake on decr) and PECE0 (wake on external) set in LPCR | 1476 | * with PECE1 (wake on decr) and PECE0 (wake on external) set in LPCR |
1447 | */ | 1477 | */ |
1448 | li r0,0x80 | 1478 | li r0,1 |
1449 | stb r0,PACAPROCSTART(r13) | 1479 | stb r0,HSTATE_HWTHREAD_REQ(r13) |
1450 | mfspr r5,SPRN_LPCR | 1480 | mfspr r5,SPRN_LPCR |
1451 | ori r5,r5,LPCR_PECE0 | LPCR_PECE1 | 1481 | ori r5,r5,LPCR_PECE0 | LPCR_PECE1 |
1452 | mtspr SPRN_LPCR,r5 | 1482 | mtspr SPRN_LPCR,r5 |
@@ -1463,26 +1493,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206) | |||
1463 | kvm_end_cede: | 1493 | kvm_end_cede: |
1464 | /* Woken by external or decrementer interrupt */ | 1494 | /* Woken by external or decrementer interrupt */ |
1465 | ld r1, HSTATE_HOST_R1(r13) | 1495 | ld r1, HSTATE_HOST_R1(r13) |
1466 | ld r2, PACATOC(r13) | ||
1467 | 1496 | ||
1468 | /* If we're a secondary thread and we got here by an IPI, ack it */ | ||
1469 | ld r4,HSTATE_KVM_VCPU(r13) | ||
1470 | lwz r3,VCPU_PTID(r4) | ||
1471 | cmpwi r3,0 | ||
1472 | beq 27f | ||
1473 | mfspr r3,SPRN_SRR1 | ||
1474 | rlwinm r3,r3,44-31,0x7 /* extract wake reason field */ | ||
1475 | cmpwi r3,4 /* was it an external interrupt? */ | ||
1476 | bne 27f | ||
1477 | ld r5, HSTATE_XICS_PHYS(r13) | ||
1478 | li r0,0xff | ||
1479 | li r6,XICS_QIRR | ||
1480 | li r7,XICS_XIRR | ||
1481 | lwzcix r8,r5,r7 /* ack the interrupt */ | ||
1482 | sync | ||
1483 | stbcix r0,r5,r6 /* clear it */ | ||
1484 | stwcix r8,r5,r7 /* EOI it */ | ||
1485 | 27: | ||
1486 | /* load up FP state */ | 1497 | /* load up FP state */ |
1487 | bl kvmppc_load_fp | 1498 | bl kvmppc_load_fp |
1488 | 1499 | ||
@@ -1580,12 +1591,17 @@ secondary_nap: | |||
1580 | stwcx. r3, 0, r4 | 1591 | stwcx. r3, 0, r4 |
1581 | bne 51b | 1592 | bne 51b |
1582 | 1593 | ||
1594 | kvm_no_guest: | ||
1595 | li r0, KVM_HWTHREAD_IN_NAP | ||
1596 | stb r0, HSTATE_HWTHREAD_STATE(r13) | ||
1597 | li r0, 0 | ||
1598 | std r0, HSTATE_KVM_VCPU(r13) | ||
1599 | |||
1583 | li r3, LPCR_PECE0 | 1600 | li r3, LPCR_PECE0 |
1584 | mfspr r4, SPRN_LPCR | 1601 | mfspr r4, SPRN_LPCR |
1585 | rlwimi r4, r3, 0, LPCR_PECE0 | LPCR_PECE1 | 1602 | rlwimi r4, r3, 0, LPCR_PECE0 | LPCR_PECE1 |
1586 | mtspr SPRN_LPCR, r4 | 1603 | mtspr SPRN_LPCR, r4 |
1587 | isync | 1604 | isync |
1588 | li r0, 0 | ||
1589 | std r0, HSTATE_SCRATCH0(r13) | 1605 | std r0, HSTATE_SCRATCH0(r13) |
1590 | ptesync | 1606 | ptesync |
1591 | ld r0, HSTATE_SCRATCH0(r13) | 1607 | ld r0, HSTATE_SCRATCH0(r13) |