Am 02.11.2009 um 00:23 schrieb Michael Neuling <mikey@xxxxxxxxxxx>:
This is the really low level of guest entry/exit code.
Book3s_64 has an SLB, which stores all ESID -> VSID mappings we're
currently aware of.
The segments in the guest differ from the ones on the host, so we
need
to switch the SLB to tell the MMU that we're in a new context.
So we store a shadow of the guest's SLB in the PACA, switch to that
on
entry and only restore bolted entries on exit, leaving the rest to
the
Linux SLB fault handler.
That way we get a really clean way of switching the SLB.
Signed-off-by: Alexander Graf <agraf@xxxxxxx>
---
arch/powerpc/kvm/book3s_64_slb.S | 277 ++++++++++++++++++++++++++++
++++++++
++
1 files changed, 277 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/kvm/book3s_64_slb.S
diff --git a/arch/powerpc/kvm/book3s_64_slb.S b/arch/powerpc/kvm/
book3s_64_sl
b.S
new file mode 100644
index 0000000..00a8367
--- /dev/null
+++ b/arch/powerpc/kvm/book3s_64_slb.S
@@ -0,0 +1,277 @@
+/*
+ * This program is free software; you can redistribute it and/or
modify
+ * it under the terms of the GNU General Public License, version
2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
+ *
+ * Copyright SUSE Linux Products GmbH 2009
+ *
+ * Authors: Alexander Graf <agraf@xxxxxxx>
+ */
+
+/
***
***
*********************************************************************
***
+ *
*
+ * Entry code
*
+ *
*
+
***
***
*********************************************************************
**/
+
+.global kvmppc_handler_trampoline_enter
+kvmppc_handler_trampoline_enter:
+
+ /* Required state:
+ *
+ * MSR = ~IR|DR
+ * R13 = PACA
+ * R9 = guest IP
+ * R10 = guest MSR
+ * R11 = free
+ * R12 = free
+ * PACA[PACA_EXMC + EX_R9] = guest R9
+ * PACA[PACA_EXMC + EX_R10] = guest R10
+ * PACA[PACA_EXMC + EX_R11] = guest R11
+ * PACA[PACA_EXMC + EX_R12] = guest R12
+ * PACA[PACA_EXMC + EX_R13] = guest R13
+ * PACA[PACA_EXMC + EX_CCR] = guest CR
+ * PACA[PACA_EXMC + EX_R3] = guest XER
+ */
+
+ mtsrr0 r9
+ mtsrr1 r10
+
+ mtspr SPRN_SPRG_SCRATCH0, r0
+
+ /* Remove LPAR shadow entries */
+
+#if SLB_NUM_BOLTED == 3
You could alternatively check the persistent entry in the slb_shawdow
buffer. This would give you a run time check. Not sure what's best
though.
Well we're in the hot path here, so anything using as few registers as
possible and being simple is the best :-). I'd guess the more we are
clever at compile time the better.
+
+ ld r12, PACA_SLBSHADOWPTR(r13)
+ ld r10, 0x10(r12)
+ ld r11, 0x18(r12)
Can you define something in asm-offsets.c for these magic constants
0x10
and 0x18. Similarly below.
+ /* Invalid? Skip. */
+ rldicl. r0, r10, 37, 63
+ beq slb_entry_skip_1
+ xoris r9, r10, SLB_ESID_V@h
+ std r9, 0x10(r12)
+slb_entry_skip_1:
+ ld r9, 0x20(r12)
+ /* Invalid? Skip. */
+ rldicl. r0, r9, 37, 63
+ beq slb_entry_skip_2
+ xoris r9, r9, SLB_ESID_V@h
+ std r9, 0x20(r12)
+slb_entry_skip_2:
+ ld r9, 0x30(r12)
+ /* Invalid? Skip. */
+ rldicl. r0, r9, 37, 63
+ beq slb_entry_skip_3
+ xoris r9, r9, SLB_ESID_V@h
+ std r9, 0x30(r12)
Can these 3 be made into a macro?
Phew - dynamically generating jump points sounds rather hard. I can
give it a try...
+slb_entry_skip_3:
+
+#else
+#error unknown number of bolted entries
+#endif
+
+ /* Flush SLB */
+
+ slbia
+
+ /* r0 = esid & ESID_MASK */
+ rldicr r10, r10, 0, 35
+ /* r0 |= CLASS_BIT(VSID) */
+ rldic r12, r11, 56 - 36, 36
+ or r10, r10, r12
+ slbie r10
+
+ isync
+
+ /* Fill SLB with our shadow */
+
+ lbz r12, PACA_KVM_SLB_MAX(r13)
+ mulli r12, r12, 16
+ addi r12, r12, PACA_KVM_SLB
+ add r12, r12, r13
+
+ /* for (r11 = kvm_slb; r11 < kvm_slb + kvm_slb_size;
r11+=slb_entry) */
+ li r11, PACA_KVM_SLB
+ add r11, r11, r13
+
+slb_loop_enter:
+
+ ld r10, 0(r11)
+
+ rldicl. r0, r10, 37, 63
+ beq slb_loop_enter_skip
+
+ ld r9, 8(r11)
+ slbmte r9, r10
If you're updating the first 3 slbs, you need to make sure the slb
shadow is updated at the same time
Well - what happens if we don't? We'd get a segment fault when phyp
stole our entry! So what? Let it fault, see the mapping is already
there and get back in again :-).
(BTW dumb question: can we run this
under PHYP?)
Yes, I tested it on bare metal, phyp and a PS3.
Alex
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html