ARM: KVM: Add CP15 save/restore code
authorMarc Zyngier <marc.zyngier@arm.com>
Sun, 3 Jan 2016 12:55:01 +0000 (12:55 +0000)
committerMarc Zyngier <marc.zyngier@arm.com>
Mon, 29 Feb 2016 18:34:13 +0000 (18:34 +0000)
Concert the CP15 save/restore code to C.

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
arch/arm/kvm/hyp/Makefile
arch/arm/kvm/hyp/cp15-sr.c [new file with mode: 0644]
arch/arm/kvm/hyp/hyp.h

index 36c760d..9f96fcb 100644 (file)
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_KVM_ARM_HOST) += tlb.o
+obj-$(CONFIG_KVM_ARM_HOST) += cp15-sr.o
diff --git a/arch/arm/kvm/hyp/cp15-sr.c b/arch/arm/kvm/hyp/cp15-sr.c
new file mode 100644 (file)
index 0000000..732abbc
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Original code:
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.com>
+ *
+ * Mostly rewritten in C by Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hyp.h"
+
+static u64 *cp15_64(struct kvm_cpu_context *ctxt, int idx)
+{
+       return (u64 *)(ctxt->cp15 + idx);
+}
+
+void __hyp_text __sysreg_save_state(struct kvm_cpu_context *ctxt)
+{
+       ctxt->cp15[c0_MPIDR]            = read_sysreg(VMPIDR);
+       ctxt->cp15[c0_CSSELR]           = read_sysreg(CSSELR);
+       ctxt->cp15[c1_SCTLR]            = read_sysreg(SCTLR);
+       ctxt->cp15[c1_CPACR]            = read_sysreg(CPACR);
+       *cp15_64(ctxt, c2_TTBR0)        = read_sysreg(TTBR0);
+       *cp15_64(ctxt, c2_TTBR1)        = read_sysreg(TTBR1);
+       ctxt->cp15[c2_TTBCR]            = read_sysreg(TTBCR);
+       ctxt->cp15[c3_DACR]             = read_sysreg(DACR);
+       ctxt->cp15[c5_DFSR]             = read_sysreg(DFSR);
+       ctxt->cp15[c5_IFSR]             = read_sysreg(IFSR);
+       ctxt->cp15[c5_ADFSR]            = read_sysreg(ADFSR);
+       ctxt->cp15[c5_AIFSR]            = read_sysreg(AIFSR);
+       ctxt->cp15[c6_DFAR]             = read_sysreg(DFAR);
+       ctxt->cp15[c6_IFAR]             = read_sysreg(IFAR);
+       *cp15_64(ctxt, c7_PAR)          = read_sysreg(PAR);
+       ctxt->cp15[c10_PRRR]            = read_sysreg(PRRR);
+       ctxt->cp15[c10_NMRR]            = read_sysreg(NMRR);
+       ctxt->cp15[c10_AMAIR0]          = read_sysreg(AMAIR0);
+       ctxt->cp15[c10_AMAIR1]          = read_sysreg(AMAIR1);
+       ctxt->cp15[c12_VBAR]            = read_sysreg(VBAR);
+       ctxt->cp15[c13_CID]             = read_sysreg(CID);
+       ctxt->cp15[c13_TID_URW]         = read_sysreg(TID_URW);
+       ctxt->cp15[c13_TID_URO]         = read_sysreg(TID_URO);
+       ctxt->cp15[c13_TID_PRIV]        = read_sysreg(TID_PRIV);
+       ctxt->cp15[c14_CNTKCTL]         = read_sysreg(CNTKCTL);
+}
+
+void __hyp_text __sysreg_restore_state(struct kvm_cpu_context *ctxt)
+{
+       write_sysreg(ctxt->cp15[c0_MPIDR],      VMPIDR);
+       write_sysreg(ctxt->cp15[c0_CSSELR],     CSSELR);
+       write_sysreg(ctxt->cp15[c1_SCTLR],      SCTLR);
+       write_sysreg(ctxt->cp15[c1_CPACR],      CPACR);
+       write_sysreg(*cp15_64(ctxt, c2_TTBR0),  TTBR0);
+       write_sysreg(*cp15_64(ctxt, c2_TTBR1),  TTBR1);
+       write_sysreg(ctxt->cp15[c2_TTBCR],      TTBCR);
+       write_sysreg(ctxt->cp15[c3_DACR],       DACR);
+       write_sysreg(ctxt->cp15[c5_DFSR],       DFSR);
+       write_sysreg(ctxt->cp15[c5_IFSR],       IFSR);
+       write_sysreg(ctxt->cp15[c5_ADFSR],      ADFSR);
+       write_sysreg(ctxt->cp15[c5_AIFSR],      AIFSR);
+       write_sysreg(ctxt->cp15[c6_DFAR],       DFAR);
+       write_sysreg(ctxt->cp15[c6_IFAR],       IFAR);
+       write_sysreg(*cp15_64(ctxt, c7_PAR),    PAR);
+       write_sysreg(ctxt->cp15[c10_PRRR],      PRRR);
+       write_sysreg(ctxt->cp15[c10_NMRR],      NMRR);
+       write_sysreg(ctxt->cp15[c10_AMAIR0],    AMAIR0);
+       write_sysreg(ctxt->cp15[c10_AMAIR1],    AMAIR1);
+       write_sysreg(ctxt->cp15[c12_VBAR],      VBAR);
+       write_sysreg(ctxt->cp15[c13_CID],       CID);
+       write_sysreg(ctxt->cp15[c13_TID_URW],   TID_URW);
+       write_sysreg(ctxt->cp15[c13_TID_URO],   TID_URO);
+       write_sysreg(ctxt->cp15[c13_TID_PRIV],  TID_PRIV);
+       write_sysreg(ctxt->cp15[c14_CNTKCTL],   CNTKCTL);
+}
index 5808bbd..ab2cb82 100644 (file)
 })
 #define read_sysreg(...)               __read_sysreg(__VA_ARGS__)
 
+#define TTBR0          __ACCESS_CP15_64(0, c2)
+#define TTBR1          __ACCESS_CP15_64(1, c2)
 #define VTTBR          __ACCESS_CP15_64(6, c2)
+#define PAR            __ACCESS_CP15_64(0, c7)
+#define CSSELR         __ACCESS_CP15(c0, 2, c0, 0)
+#define VMPIDR         __ACCESS_CP15(c0, 4, c0, 5)
+#define SCTLR          __ACCESS_CP15(c1, 0, c0, 0)
+#define CPACR          __ACCESS_CP15(c1, 0, c0, 2)
+#define TTBCR          __ACCESS_CP15(c2, 0, c0, 2)
+#define DACR           __ACCESS_CP15(c3, 0, c0, 0)
+#define DFSR           __ACCESS_CP15(c5, 0, c0, 0)
+#define IFSR           __ACCESS_CP15(c5, 0, c0, 1)
+#define ADFSR          __ACCESS_CP15(c5, 0, c1, 0)
+#define AIFSR          __ACCESS_CP15(c5, 0, c1, 1)
+#define DFAR           __ACCESS_CP15(c6, 0, c0, 0)
+#define IFAR           __ACCESS_CP15(c6, 0, c0, 2)
 #define ICIALLUIS      __ACCESS_CP15(c7, 0, c1, 0)
 #define TLBIALLIS      __ACCESS_CP15(c8, 0, c3, 0)
 #define TLBIALLNSNHIS  __ACCESS_CP15(c8, 4, c3, 4)
+#define PRRR           __ACCESS_CP15(c10, 0, c2, 0)
+#define NMRR           __ACCESS_CP15(c10, 0, c2, 1)
+#define AMAIR0         __ACCESS_CP15(c10, 0, c3, 0)
+#define AMAIR1         __ACCESS_CP15(c10, 0, c3, 1)
+#define VBAR           __ACCESS_CP15(c12, 0, c0, 0)
+#define CID            __ACCESS_CP15(c13, 0, c0, 1)
+#define TID_URW                __ACCESS_CP15(c13, 0, c0, 2)
+#define TID_URO                __ACCESS_CP15(c13, 0, c0, 3)
+#define TID_PRIV       __ACCESS_CP15(c13, 0, c0, 4)
+#define CNTKCTL                __ACCESS_CP15(c14, 0, c1, 0)
+
+void __sysreg_save_state(struct kvm_cpu_context *ctxt);
+void __sysreg_restore_state(struct kvm_cpu_context *ctxt);
 
 #endif /* __ARM_KVM_HYP_H__ */