Currently, the following instructions are translated:
- CACHE (indexed)
- CACHE (va based): translated to a synci, overkill on D-CACHE operations, but
still much faster than a trap.
- mfc0/mtc0: the virtual COP0 registers for the guest are implemented as 2-D
array
[COP#][SEL] and this is mapped into the guest kernel address space @ VA 0x0.
mfc0/mtc0 operations are transformed to load/stores.
Signed-off-by: Sanjay Lal sanj...@kymasys.com
---
arch/mips/kvm/kvm_mips_comm.h | 24 +++
arch/mips/kvm/kvm_mips_commpage.c | 38 ++
arch/mips/kvm/kvm_mips_dyntrans.c | 142 ++
3 files changed, 204 insertions(+)
create mode 100644 arch/mips/kvm/kvm_mips_comm.h
create mode 100644 arch/mips/kvm/kvm_mips_commpage.c
create mode 100644 arch/mips/kvm/kvm_mips_dyntrans.c
diff --git a/arch/mips/kvm/kvm_mips_comm.h b/arch/mips/kvm/kvm_mips_comm.h
new file mode 100644
index 000..02073db
--- /dev/null
+++ b/arch/mips/kvm/kvm_mips_comm.h
@@ -0,0 +1,24 @@
+/*
+* This file is subject to the terms and conditions of the GNU General Public
+* License. See the file COPYING in the main directory of this archive
+* for more details.
+*
+* KVM/MIPS commpage: mapped into guest kernel @ VA: 0x0 to support dynamic
translation
+*
+* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+* Authors: Sanjay Lal sanj...@kymasys.com
+*/
+
+#ifndef __KVM_MIPS_COMMPAGE_H__
+#define __KVM_MIPS_COMMPAGE_H__
+
+struct kvm_mips_commpage {
+struct mips_coproc cop0;/* COP0 state is mapped into Guest kernel via
commpage */
+};
+
+#define KVM_MIPS_COMM_EIDI_OFFSET 0x0
+
+extern void kvm_mips_commpage_init (struct kvm_vcpu *vcpu);
+
+#endif /* __KVM_MIPS_COMMPAGE_H__ */
+
diff --git a/arch/mips/kvm/kvm_mips_commpage.c
b/arch/mips/kvm/kvm_mips_commpage.c
new file mode 100644
index 000..5a4b21f
--- /dev/null
+++ b/arch/mips/kvm/kvm_mips_commpage.c
@@ -0,0 +1,38 @@
+/*
+* This file is subject to the terms and conditions of the GNU General Public
+* License. See the file COPYING in the main directory of this archive
+* for more details.
+*
+* commpage, currently used for Virtual COP0 registers. Mapped into the guest
kernel
+* aspace @ 0x0.
+*
+* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+* Authors: Sanjay Lal sanj...@kymasys.com
+*/
+
+#include linux/errno.h
+#include linux/err.h
+#include linux/module.h
+#include linux/vmalloc.h
+#include linux/fs.h
+#include linux/bootmem.h
+#include asm/page.h
+#include asm/cacheflush.h
+#include asm/mmu_context.h
+
+#include linux/kvm_host.h
+
+#include kvm_mips_comm.h
+
+void
+kvm_mips_commpage_init (struct kvm_vcpu *vcpu)
+{
+struct kvm_mips_commpage *page = vcpu-arch.kseg0_commpage;
+memset (page, 0, sizeof(struct kvm_mips_commpage));
+
+/* Specific init values for fields */
+vcpu-arch.cop0 = page-cop0;
+memset(vcpu-arch.cop0, 0, sizeof(struct mips_coproc));
+
+return;
+}
diff --git a/arch/mips/kvm/kvm_mips_dyntrans.c
b/arch/mips/kvm/kvm_mips_dyntrans.c
new file mode 100644
index 000..2cbbdde
--- /dev/null
+++ b/arch/mips/kvm/kvm_mips_dyntrans.c
@@ -0,0 +1,142 @@
+/*
+* This file is subject to the terms and conditions of the GNU General Public
+* License. See the file COPYING in the main directory of this archive
+* for more details.
+*
+* KVM/MIPS: Dynamic translation for privileged instructions, reduces traps.
+*
+* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+* Authors: Sanjay Lal sanj...@kymasys.com
+*/
+
+#include linux/errno.h
+#include linux/err.h
+#include linux/kvm_host.h
+#include linux/module.h
+#include linux/vmalloc.h
+#include linux/fs.h
+#include linux/bootmem.h
+
+#include kvm_mips_comm.h
+
+#define SYNCI_TEMPLATE 0x041f
+#define SYNCI_BASE(x) (((x) 21) 0x1f)
+#define SYNCI_OFFSET((x) 0x)
+
+#define LW_TEMPLATE 0x8c00
+#define CLEAR_TEMPLATE 0x0020
+#define SW_TEMPLATE 0xac00
+
+int
+kvm_mips_trans_cache_index (uint32_t inst, uint32_t __user *opc, struct
kvm_vcpu *vcpu)
+{
+int result = 0;
+ulong kseg0_opc;
+uint32_t synci_inst = 0x0;
+
+/* Replace the CACHE instruction, with a NOP */
+kseg0_opc = CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa (vcpu,
(ulong) opc));
+memcpy((void *) kseg0_opc, (void *)synci_inst, sizeof(uint32_t));
+mips32_SyncICache(kseg0_opc, 32);
+
+return (result);
+}
+
+/*
+ * Address based CACHE instructions are transformed into synci(s). A little
heavy
+ * for just D-cache invalidates, but avoids an expensive trap
+ */
+int
+kvm_mips_trans_cache_va (uint32_t inst, uint32_t __user *opc, struct kvm_vcpu
*vcpu)
+{
+int result = 0;
+ulong kseg0_opc;
+uint32_t synci_inst = SYNCI_TEMPLATE, base, offset;
+
+base = (inst 21) 0x1f;
+offset = inst 0x;
+synci_inst |= (base 21);
+synci_inst |= offset;
+
+kseg0_opc = CKSEG0ADDR(kvm_mips_translate_guest_kseg0_to_hpa (vcpu,
(ulong) opc));
+