vz.c (273819a6a5ab493500c14889b161bf5bc2265736) vz.c (d42a008f86ba3d715d31788fc5143a4de5685d33)
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * KVM/MIPS: Support for hardware virtualization extensions
7 *
8 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.

--- 120 unchanged lines hidden (view full) ---

129/*
130 * VZ optionally allows these additional Config bits to be written by root:
131 * Config: M, [MT]
132 * Config1: M, [MMUSize-1, C2, MD, PC, WR, CA], FP
133 * Config2: M
134 * Config3: M, MSAP, [BPG], ULRI, [DSP2P, DSPP], CTXTC, [ITL, LPA, VEIC,
135 * VInt, SP, CDMM, MT, SM, TL]
136 * Config4: M, [VTLBSizeExt, MMUSizeExt]
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * KVM/MIPS: Support for hardware virtualization extensions
7 *
8 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.

--- 120 unchanged lines hidden (view full) ---

129/*
130 * VZ optionally allows these additional Config bits to be written by root:
131 * Config: M, [MT]
132 * Config1: M, [MMUSize-1, C2, MD, PC, WR, CA], FP
133 * Config2: M
134 * Config3: M, MSAP, [BPG], ULRI, [DSP2P, DSPP], CTXTC, [ITL, LPA, VEIC,
135 * VInt, SP, CDMM, MT, SM, TL]
136 * Config4: M, [VTLBSizeExt, MMUSizeExt]
137 * Config5: [MRP]
137 * Config5: MRP
138 */
139
140static inline unsigned int kvm_vz_config_user_wrmask(struct kvm_vcpu *vcpu)
141{
142 return kvm_vz_config_guest_wrmask(vcpu) | MIPS_CONF_M;
143}
144
145static inline unsigned int kvm_vz_config1_user_wrmask(struct kvm_vcpu *vcpu)

--- 26 unchanged lines hidden (view full) ---

172
173static inline unsigned int kvm_vz_config4_user_wrmask(struct kvm_vcpu *vcpu)
174{
175 return kvm_vz_config4_guest_wrmask(vcpu) | MIPS_CONF_M;
176}
177
178static inline unsigned int kvm_vz_config5_user_wrmask(struct kvm_vcpu *vcpu)
179{
138 */
139
140static inline unsigned int kvm_vz_config_user_wrmask(struct kvm_vcpu *vcpu)
141{
142 return kvm_vz_config_guest_wrmask(vcpu) | MIPS_CONF_M;
143}
144
145static inline unsigned int kvm_vz_config1_user_wrmask(struct kvm_vcpu *vcpu)

--- 26 unchanged lines hidden (view full) ---

172
173static inline unsigned int kvm_vz_config4_user_wrmask(struct kvm_vcpu *vcpu)
174{
175 return kvm_vz_config4_guest_wrmask(vcpu) | MIPS_CONF_M;
176}
177
178static inline unsigned int kvm_vz_config5_user_wrmask(struct kvm_vcpu *vcpu)
179{
180 return kvm_vz_config5_guest_wrmask(vcpu);
180 return kvm_vz_config5_guest_wrmask(vcpu) | MIPS_CONF5_MRP;
181}
182
183static gpa_t kvm_vz_gva_to_gpa_cb(gva_t gva)
184{
185 /* VZ guest has already converted gva to gpa */
186 return gva;
187}
188

--- 491 unchanged lines hidden (view full) ---

680 kvm_err("Exception Code: %d not handled @ PC: %p, inst: 0x%08x BadVaddr: %#lx Status: %#x\n",
681 exccode, opc, inst, badvaddr,
682 read_gc0_status());
683 kvm_arch_vcpu_dump_regs(vcpu);
684 vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
685 return RESUME_HOST;
686}
687
181}
182
183static gpa_t kvm_vz_gva_to_gpa_cb(gva_t gva)
184{
185 /* VZ guest has already converted gva to gpa */
186 return gva;
187}
188

--- 491 unchanged lines hidden (view full) ---

680 kvm_err("Exception Code: %d not handled @ PC: %p, inst: 0x%08x BadVaddr: %#lx Status: %#x\n",
681 exccode, opc, inst, badvaddr,
682 read_gc0_status());
683 kvm_arch_vcpu_dump_regs(vcpu);
684 vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
685 return RESUME_HOST;
686}
687
688static unsigned long mips_process_maar(unsigned int op, unsigned long val)
689{
690 /* Mask off unused bits */
691 unsigned long mask = 0xfffff000 | MIPS_MAAR_S | MIPS_MAAR_VL;
692
693 if (read_gc0_pagegrain() & PG_ELPA)
694 mask |= 0x00ffffff00000000ull;
695 if (cpu_guest_has_mvh)
696 mask |= MIPS_MAAR_VH;
697
698 /* Set or clear VH */
699 if (op == mtc_op) {
700 /* clear VH */
701 val &= ~MIPS_MAAR_VH;
702 } else if (op == dmtc_op) {
703 /* set VH to match VL */
704 val &= ~MIPS_MAAR_VH;
705 if (val & MIPS_MAAR_VL)
706 val |= MIPS_MAAR_VH;
707 }
708
709 return val & mask;
710}
711
712static void kvm_write_maari(struct kvm_vcpu *vcpu, unsigned long val)
713{
714 struct mips_coproc *cop0 = vcpu->arch.cop0;
715
716 val &= MIPS_MAARI_INDEX;
717 if (val == MIPS_MAARI_INDEX)
718 kvm_write_sw_gc0_maari(cop0, ARRAY_SIZE(vcpu->arch.maar) - 1);
719 else if (val < ARRAY_SIZE(vcpu->arch.maar))
720 kvm_write_sw_gc0_maari(cop0, val);
721}
722
688static enum emulation_result kvm_vz_gpsi_cop0(union mips_instruction inst,
689 u32 *opc, u32 cause,
690 struct kvm_run *run,
691 struct kvm_vcpu *vcpu)
692{
693 struct mips_coproc *cop0 = vcpu->arch.cop0;
694 enum emulation_result er = EMULATE_DONE;
695 u32 rt, rd, sel;

--- 36 unchanged lines hidden (view full) ---

732 val = read_gc0_compare();
733 } else if (rd == MIPS_CP0_LLADDR &&
734 sel == 0) { /* LLAddr */
735 if (cpu_guest_has_rw_llb)
736 val = read_gc0_lladdr() &
737 MIPS_LLADDR_LLB;
738 else
739 val = 0;
723static enum emulation_result kvm_vz_gpsi_cop0(union mips_instruction inst,
724 u32 *opc, u32 cause,
725 struct kvm_run *run,
726 struct kvm_vcpu *vcpu)
727{
728 struct mips_coproc *cop0 = vcpu->arch.cop0;
729 enum emulation_result er = EMULATE_DONE;
730 u32 rt, rd, sel;

--- 36 unchanged lines hidden (view full) ---

767 val = read_gc0_compare();
768 } else if (rd == MIPS_CP0_LLADDR &&
769 sel == 0) { /* LLAddr */
770 if (cpu_guest_has_rw_llb)
771 val = read_gc0_lladdr() &
772 MIPS_LLADDR_LLB;
773 else
774 val = 0;
775 } else if (rd == MIPS_CP0_LLADDR &&
776 sel == 1 && /* MAAR */
777 cpu_guest_has_maar &&
778 !cpu_guest_has_dyn_maar) {
779 /* MAARI must be in range */
780 BUG_ON(kvm_read_sw_gc0_maari(cop0) >=
781 ARRAY_SIZE(vcpu->arch.maar));
782 val = vcpu->arch.maar[
783 kvm_read_sw_gc0_maari(cop0)];
740 } else if ((rd == MIPS_CP0_PRID &&
741 (sel == 0 || /* PRid */
742 sel == 2 || /* CDMMBase */
743 sel == 3)) || /* CMGCRBase */
744 (rd == MIPS_CP0_STATUS &&
745 (sel == 2 || /* SRSCtl */
746 sel == 3)) || /* SRSMap */
747 (rd == MIPS_CP0_CONFIG &&
748 (sel == 7)) || /* Config7 */
784 } else if ((rd == MIPS_CP0_PRID &&
785 (sel == 0 || /* PRid */
786 sel == 2 || /* CDMMBase */
787 sel == 3)) || /* CMGCRBase */
788 (rd == MIPS_CP0_STATUS &&
789 (sel == 2 || /* SRSCtl */
790 sel == 3)) || /* SRSMap */
791 (rd == MIPS_CP0_CONFIG &&
792 (sel == 7)) || /* Config7 */
793 (rd == MIPS_CP0_LLADDR &&
794 (sel == 2) && /* MAARI */
795 cpu_guest_has_maar &&
796 !cpu_guest_has_dyn_maar) ||
749 (rd == MIPS_CP0_ERRCTL &&
750 (sel == 0))) { /* ErrCtl */
751 val = cop0->reg[rd][sel];
752 } else {
753 val = 0;
754 er = EMULATE_FAIL;
755 }
756

--- 31 unchanged lines hidden (view full) ---

788 sel == 0) { /* LLAddr */
789 /*
790 * P5600 generates GPSI on guest MTC0 LLAddr.
791 * Only allow the guest to clear LLB.
792 */
793 if (cpu_guest_has_rw_llb &&
794 !(val & MIPS_LLADDR_LLB))
795 write_gc0_lladdr(0);
797 (rd == MIPS_CP0_ERRCTL &&
798 (sel == 0))) { /* ErrCtl */
799 val = cop0->reg[rd][sel];
800 } else {
801 val = 0;
802 er = EMULATE_FAIL;
803 }
804

--- 31 unchanged lines hidden (view full) ---

836 sel == 0) { /* LLAddr */
837 /*
838 * P5600 generates GPSI on guest MTC0 LLAddr.
839 * Only allow the guest to clear LLB.
840 */
841 if (cpu_guest_has_rw_llb &&
842 !(val & MIPS_LLADDR_LLB))
843 write_gc0_lladdr(0);
844 } else if (rd == MIPS_CP0_LLADDR &&
845 sel == 1 && /* MAAR */
846 cpu_guest_has_maar &&
847 !cpu_guest_has_dyn_maar) {
848 val = mips_process_maar(inst.c0r_format.rs,
849 val);
850
851 /* MAARI must be in range */
852 BUG_ON(kvm_read_sw_gc0_maari(cop0) >=
853 ARRAY_SIZE(vcpu->arch.maar));
854 vcpu->arch.maar[kvm_read_sw_gc0_maari(cop0)] =
855 val;
856 } else if (rd == MIPS_CP0_LLADDR &&
857 (sel == 2) && /* MAARI */
858 cpu_guest_has_maar &&
859 !cpu_guest_has_dyn_maar) {
860 kvm_write_maari(vcpu, val);
796 } else if (rd == MIPS_CP0_ERRCTL &&
797 (sel == 0)) { /* ErrCtl */
798 /* ignore the written value */
799 } else {
800 er = EMULATE_FAIL;
801 }
802 break;
803

--- 632 unchanged lines hidden (view full) ---

1436 if (cpu_guest_has_badinstrp)
1437 ++ret;
1438 if (cpu_guest_has_contextconfig)
1439 ret += ARRAY_SIZE(kvm_vz_get_one_regs_contextconfig);
1440 if (cpu_guest_has_segments)
1441 ret += ARRAY_SIZE(kvm_vz_get_one_regs_segments);
1442 if (cpu_guest_has_htw)
1443 ret += ARRAY_SIZE(kvm_vz_get_one_regs_htw);
861 } else if (rd == MIPS_CP0_ERRCTL &&
862 (sel == 0)) { /* ErrCtl */
863 /* ignore the written value */
864 } else {
865 er = EMULATE_FAIL;
866 }
867 break;
868

--- 632 unchanged lines hidden (view full) ---

1501 if (cpu_guest_has_badinstrp)
1502 ++ret;
1503 if (cpu_guest_has_contextconfig)
1504 ret += ARRAY_SIZE(kvm_vz_get_one_regs_contextconfig);
1505 if (cpu_guest_has_segments)
1506 ret += ARRAY_SIZE(kvm_vz_get_one_regs_segments);
1507 if (cpu_guest_has_htw)
1508 ret += ARRAY_SIZE(kvm_vz_get_one_regs_htw);
1509 if (cpu_guest_has_maar && !cpu_guest_has_dyn_maar)
1510 ret += 1 + ARRAY_SIZE(vcpu->arch.maar);
1444 ret += __arch_hweight8(cpu_data[0].guest.kscratch_mask);
1445
1446 return ret;
1447}
1448
1449static int kvm_vz_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices)
1450{
1451 u64 index;

--- 35 unchanged lines hidden (view full) ---

1487 indices += ARRAY_SIZE(kvm_vz_get_one_regs_segments);
1488 }
1489 if (cpu_guest_has_htw) {
1490 if (copy_to_user(indices, kvm_vz_get_one_regs_htw,
1491 sizeof(kvm_vz_get_one_regs_htw)))
1492 return -EFAULT;
1493 indices += ARRAY_SIZE(kvm_vz_get_one_regs_htw);
1494 }
1511 ret += __arch_hweight8(cpu_data[0].guest.kscratch_mask);
1512
1513 return ret;
1514}
1515
1516static int kvm_vz_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices)
1517{
1518 u64 index;

--- 35 unchanged lines hidden (view full) ---

1554 indices += ARRAY_SIZE(kvm_vz_get_one_regs_segments);
1555 }
1556 if (cpu_guest_has_htw) {
1557 if (copy_to_user(indices, kvm_vz_get_one_regs_htw,
1558 sizeof(kvm_vz_get_one_regs_htw)))
1559 return -EFAULT;
1560 indices += ARRAY_SIZE(kvm_vz_get_one_regs_htw);
1561 }
1562 if (cpu_guest_has_maar && !cpu_guest_has_dyn_maar) {
1563 for (i = 0; i < ARRAY_SIZE(vcpu->arch.maar); ++i) {
1564 index = KVM_REG_MIPS_CP0_MAAR(i);
1565 if (copy_to_user(indices, &index, sizeof(index)))
1566 return -EFAULT;
1567 ++indices;
1568 }
1569
1570 index = KVM_REG_MIPS_CP0_MAARI;
1571 if (copy_to_user(indices, &index, sizeof(index)))
1572 return -EFAULT;
1573 ++indices;
1574 }
1495 for (i = 0; i < 6; ++i) {
1496 if (!cpu_guest_has_kscr(i + 2))
1497 continue;
1498
1499 if (copy_to_user(indices, &kvm_vz_get_one_regs_kscratch[i],
1500 sizeof(kvm_vz_get_one_regs_kscratch[i])))
1501 return -EFAULT;
1502 ++indices;

--- 181 unchanged lines hidden (view full) ---

1684 return -EINVAL;
1685 *v = read_gc0_config4();
1686 break;
1687 case KVM_REG_MIPS_CP0_CONFIG5:
1688 if (!cpu_guest_has_conf5)
1689 return -EINVAL;
1690 *v = read_gc0_config5();
1691 break;
1575 for (i = 0; i < 6; ++i) {
1576 if (!cpu_guest_has_kscr(i + 2))
1577 continue;
1578
1579 if (copy_to_user(indices, &kvm_vz_get_one_regs_kscratch[i],
1580 sizeof(kvm_vz_get_one_regs_kscratch[i])))
1581 return -EFAULT;
1582 ++indices;

--- 181 unchanged lines hidden (view full) ---

1764 return -EINVAL;
1765 *v = read_gc0_config4();
1766 break;
1767 case KVM_REG_MIPS_CP0_CONFIG5:
1768 if (!cpu_guest_has_conf5)
1769 return -EINVAL;
1770 *v = read_gc0_config5();
1771 break;
1772 case KVM_REG_MIPS_CP0_MAAR(0) ... KVM_REG_MIPS_CP0_MAAR(0x3f):
1773 if (!cpu_guest_has_maar || cpu_guest_has_dyn_maar)
1774 return -EINVAL;
1775 idx = reg->id - KVM_REG_MIPS_CP0_MAAR(0);
1776 if (idx >= ARRAY_SIZE(vcpu->arch.maar))
1777 return -EINVAL;
1778 *v = vcpu->arch.maar[idx];
1779 break;
1780 case KVM_REG_MIPS_CP0_MAARI:
1781 if (!cpu_guest_has_maar || cpu_guest_has_dyn_maar)
1782 return -EINVAL;
1783 *v = kvm_read_sw_gc0_maari(vcpu->arch.cop0);
1784 break;
1692#ifdef CONFIG_64BIT
1693 case KVM_REG_MIPS_CP0_XCONTEXT:
1694 *v = read_gc0_xcontext();
1695 break;
1696#endif
1697 case KVM_REG_MIPS_CP0_ERROREPC:
1698 *v = (long)read_gc0_errorepc();
1699 break;

--- 233 unchanged lines hidden (view full) ---

1933 break;
1934 cur = read_gc0_config5();
1935 change = (cur ^ v) & kvm_vz_config5_user_wrmask(vcpu);
1936 if (change) {
1937 v = cur ^ change;
1938 write_gc0_config5(v);
1939 }
1940 break;
1785#ifdef CONFIG_64BIT
1786 case KVM_REG_MIPS_CP0_XCONTEXT:
1787 *v = read_gc0_xcontext();
1788 break;
1789#endif
1790 case KVM_REG_MIPS_CP0_ERROREPC:
1791 *v = (long)read_gc0_errorepc();
1792 break;

--- 233 unchanged lines hidden (view full) ---

2026 break;
2027 cur = read_gc0_config5();
2028 change = (cur ^ v) & kvm_vz_config5_user_wrmask(vcpu);
2029 if (change) {
2030 v = cur ^ change;
2031 write_gc0_config5(v);
2032 }
2033 break;
2034 case KVM_REG_MIPS_CP0_MAAR(0) ... KVM_REG_MIPS_CP0_MAAR(0x3f):
2035 if (!cpu_guest_has_maar || cpu_guest_has_dyn_maar)
2036 return -EINVAL;
2037 idx = reg->id - KVM_REG_MIPS_CP0_MAAR(0);
2038 if (idx >= ARRAY_SIZE(vcpu->arch.maar))
2039 return -EINVAL;
2040 vcpu->arch.maar[idx] = mips_process_maar(dmtc_op, v);
2041 break;
2042 case KVM_REG_MIPS_CP0_MAARI:
2043 if (!cpu_guest_has_maar || cpu_guest_has_dyn_maar)
2044 return -EINVAL;
2045 kvm_write_maari(vcpu, v);
2046 break;
1941#ifdef CONFIG_64BIT
1942 case KVM_REG_MIPS_CP0_XCONTEXT:
1943 write_gc0_xcontext(v);
1944 break;
1945#endif
1946 case KVM_REG_MIPS_CP0_ERROREPC:
1947 write_gc0_errorepc(v);
1948 break;

--- 881 unchanged lines hidden ---
2047#ifdef CONFIG_64BIT
2048 case KVM_REG_MIPS_CP0_XCONTEXT:
2049 write_gc0_xcontext(v);
2050 break;
2051#endif
2052 case KVM_REG_MIPS_CP0_ERROREPC:
2053 write_gc0_errorepc(v);
2054 break;

--- 881 unchanged lines hidden ---