Loading arch/arm/kvm/coproc.c +19 −7 Original line number Diff line number Diff line Loading @@ -146,7 +146,11 @@ static bool pm_fake(struct kvm_vcpu *vcpu, #define access_pmintenclr pm_fake /* Architected CP15 registers. * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 * CRn denotes the primary register number, but is copied to the CRm in the * user space API for 64-bit register access in line with the terminology used * in the ARM ARM. * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit * registers preceding 32-bit ones. */ static const struct coproc_reg cp15_regs[] = { /* CSSELR: swapped by interrupt.S. */ Loading @@ -154,8 +158,8 @@ static const struct coproc_reg cp15_regs[] = { NULL, reset_unknown, c0_CSSELR }, /* TTBR0/TTBR1: swapped by interrupt.S. */ { CRm( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 }, { CRm( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 }, { CRm64( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 }, { CRm64( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 }, /* TTBCR: swapped by interrupt.S. */ { CRn( 2), CRm( 0), Op1( 0), Op2( 2), is32, Loading @@ -182,7 +186,7 @@ static const struct coproc_reg cp15_regs[] = { NULL, reset_unknown, c6_IFAR }, /* PAR swapped by interrupt.S */ { CRn( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR }, { CRm64( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR }, /* * DC{C,I,CI}SW operations: Loading Loading @@ -399,12 +403,13 @@ static bool index_to_params(u64 id, struct coproc_params *params) | KVM_REG_ARM_OPC1_MASK)) return false; params->is_64bit = true; params->CRm = ((id & KVM_REG_ARM_CRM_MASK) /* CRm to CRn: see cp15_to_index for details */ params->CRn = ((id & KVM_REG_ARM_CRM_MASK) >> KVM_REG_ARM_CRM_SHIFT); params->Op1 = ((id & KVM_REG_ARM_OPC1_MASK) >> KVM_REG_ARM_OPC1_SHIFT); params->Op2 = 0; params->CRn = 0; params->CRm = 0; return true; default: return false; Loading Loading @@ -898,7 +903,14 @@ static u64 cp15_to_index(const struct coproc_reg *reg) if (reg->is_64) { val |= KVM_REG_SIZE_U64; val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT); val |= (reg->CRm << KVM_REG_ARM_CRM_SHIFT); /* * CRn always denotes the primary coproc. reg. nr. for the * in-kernel representation, but the user space API uses the * CRm for the encoding, because it is modelled after the * MRRC/MCRR instructions: see the ARM ARM rev. c page * B3-1445 */ val |= (reg->CRn << KVM_REG_ARM_CRM_SHIFT); } else { val |= KVM_REG_SIZE_U32; val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT); Loading arch/arm/kvm/coproc.h +3 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,8 @@ static inline int cmp_reg(const struct coproc_reg *i1, return -1; if (i1->CRn != i2->CRn) return i1->CRn - i2->CRn; if (i1->is_64 != i2->is_64) return i2->is_64 - i1->is_64; if (i1->CRm != i2->CRm) return i1->CRm - i2->CRm; if (i1->Op1 != i2->Op1) Loading @@ -145,6 +147,7 @@ static inline int cmp_reg(const struct coproc_reg *i1, #define CRn(_x) .CRn = _x #define CRm(_x) .CRm = _x #define CRm64(_x) .CRn = _x, .CRm = 0 #define Op1(_x) .Op1 = _x #define Op2(_x) .Op2 = _x #define is64 .is_64 = true Loading arch/arm/kvm/coproc_a15.c +5 −1 Original line number Diff line number Diff line Loading @@ -114,7 +114,11 @@ static bool access_l2ectlr(struct kvm_vcpu *vcpu, /* * A15-specific CP15 registers. * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 * CRn denotes the primary register number, but is copied to the CRm in the * user space API for 64-bit register access in line with the terminology used * in the ARM ARM. * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit * registers preceding 32-bit ones. */ static const struct coproc_reg a15_regs[] = { /* MPIDR: we use VMPIDR for guest access. */ Loading arch/arm/kvm/mmio.c +2 −1 Original line number Diff line number Diff line Loading @@ -63,7 +63,8 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, struct kvm_exit_mmio *mmio) { unsigned long rt, len; unsigned long rt; int len; bool is_write, sign_extend; if (kvm_vcpu_dabt_isextabt(vcpu)) { Loading arch/arm/kvm/mmu.c +15 −21 Original line number Diff line number Diff line Loading @@ -85,6 +85,12 @@ static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc) return p; } static bool page_empty(void *ptr) { struct page *ptr_page = virt_to_page(ptr); return page_count(ptr_page) == 1; } static void clear_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr) { pmd_t *pmd_table = pmd_offset(pud, 0); Loading @@ -103,12 +109,6 @@ static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr) put_page(virt_to_page(pmd)); } static bool pmd_empty(pmd_t *pmd) { struct page *pmd_page = virt_to_page(pmd); return page_count(pmd_page) == 1; } static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr) { if (pte_present(*pte)) { Loading @@ -118,12 +118,6 @@ static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr) } } static bool pte_empty(pte_t *pte) { struct page *pte_page = virt_to_page(pte); return page_count(pte_page) == 1; } static void unmap_range(struct kvm *kvm, pgd_t *pgdp, unsigned long long start, u64 size) { Loading @@ -132,37 +126,37 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp, pmd_t *pmd; pte_t *pte; unsigned long long addr = start, end = start + size; u64 range; u64 next; while (addr < end) { pgd = pgdp + pgd_index(addr); pud = pud_offset(pgd, addr); if (pud_none(*pud)) { addr += PUD_SIZE; addr = pud_addr_end(addr, end); continue; } pmd = pmd_offset(pud, addr); if (pmd_none(*pmd)) { addr += PMD_SIZE; addr = pmd_addr_end(addr, end); continue; } pte = pte_offset_kernel(pmd, addr); clear_pte_entry(kvm, pte, addr); range = PAGE_SIZE; next = addr + PAGE_SIZE; /* If we emptied the pte, walk back up the ladder */ if (pte_empty(pte)) { if (page_empty(pte)) { clear_pmd_entry(kvm, pmd, addr); range = PMD_SIZE; if (pmd_empty(pmd)) { next = pmd_addr_end(addr, end); if (page_empty(pmd) && !page_empty(pud)) { clear_pud_entry(kvm, pud, addr); range = PUD_SIZE; next = pud_addr_end(addr, end); } } addr += range; addr = next; } } Loading Loading
arch/arm/kvm/coproc.c +19 −7 Original line number Diff line number Diff line Loading @@ -146,7 +146,11 @@ static bool pm_fake(struct kvm_vcpu *vcpu, #define access_pmintenclr pm_fake /* Architected CP15 registers. * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 * CRn denotes the primary register number, but is copied to the CRm in the * user space API for 64-bit register access in line with the terminology used * in the ARM ARM. * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit * registers preceding 32-bit ones. */ static const struct coproc_reg cp15_regs[] = { /* CSSELR: swapped by interrupt.S. */ Loading @@ -154,8 +158,8 @@ static const struct coproc_reg cp15_regs[] = { NULL, reset_unknown, c0_CSSELR }, /* TTBR0/TTBR1: swapped by interrupt.S. */ { CRm( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 }, { CRm( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 }, { CRm64( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 }, { CRm64( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 }, /* TTBCR: swapped by interrupt.S. */ { CRn( 2), CRm( 0), Op1( 0), Op2( 2), is32, Loading @@ -182,7 +186,7 @@ static const struct coproc_reg cp15_regs[] = { NULL, reset_unknown, c6_IFAR }, /* PAR swapped by interrupt.S */ { CRn( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR }, { CRm64( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR }, /* * DC{C,I,CI}SW operations: Loading Loading @@ -399,12 +403,13 @@ static bool index_to_params(u64 id, struct coproc_params *params) | KVM_REG_ARM_OPC1_MASK)) return false; params->is_64bit = true; params->CRm = ((id & KVM_REG_ARM_CRM_MASK) /* CRm to CRn: see cp15_to_index for details */ params->CRn = ((id & KVM_REG_ARM_CRM_MASK) >> KVM_REG_ARM_CRM_SHIFT); params->Op1 = ((id & KVM_REG_ARM_OPC1_MASK) >> KVM_REG_ARM_OPC1_SHIFT); params->Op2 = 0; params->CRn = 0; params->CRm = 0; return true; default: return false; Loading Loading @@ -898,7 +903,14 @@ static u64 cp15_to_index(const struct coproc_reg *reg) if (reg->is_64) { val |= KVM_REG_SIZE_U64; val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT); val |= (reg->CRm << KVM_REG_ARM_CRM_SHIFT); /* * CRn always denotes the primary coproc. reg. nr. for the * in-kernel representation, but the user space API uses the * CRm for the encoding, because it is modelled after the * MRRC/MCRR instructions: see the ARM ARM rev. c page * B3-1445 */ val |= (reg->CRn << KVM_REG_ARM_CRM_SHIFT); } else { val |= KVM_REG_SIZE_U32; val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT); Loading
arch/arm/kvm/coproc.h +3 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,8 @@ static inline int cmp_reg(const struct coproc_reg *i1, return -1; if (i1->CRn != i2->CRn) return i1->CRn - i2->CRn; if (i1->is_64 != i2->is_64) return i2->is_64 - i1->is_64; if (i1->CRm != i2->CRm) return i1->CRm - i2->CRm; if (i1->Op1 != i2->Op1) Loading @@ -145,6 +147,7 @@ static inline int cmp_reg(const struct coproc_reg *i1, #define CRn(_x) .CRn = _x #define CRm(_x) .CRm = _x #define CRm64(_x) .CRn = _x, .CRm = 0 #define Op1(_x) .Op1 = _x #define Op2(_x) .Op2 = _x #define is64 .is_64 = true Loading
arch/arm/kvm/coproc_a15.c +5 −1 Original line number Diff line number Diff line Loading @@ -114,7 +114,11 @@ static bool access_l2ectlr(struct kvm_vcpu *vcpu, /* * A15-specific CP15 registers. * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 * CRn denotes the primary register number, but is copied to the CRm in the * user space API for 64-bit register access in line with the terminology used * in the ARM ARM. * Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit * registers preceding 32-bit ones. */ static const struct coproc_reg a15_regs[] = { /* MPIDR: we use VMPIDR for guest access. */ Loading
arch/arm/kvm/mmio.c +2 −1 Original line number Diff line number Diff line Loading @@ -63,7 +63,8 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run) static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, struct kvm_exit_mmio *mmio) { unsigned long rt, len; unsigned long rt; int len; bool is_write, sign_extend; if (kvm_vcpu_dabt_isextabt(vcpu)) { Loading
arch/arm/kvm/mmu.c +15 −21 Original line number Diff line number Diff line Loading @@ -85,6 +85,12 @@ static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc) return p; } static bool page_empty(void *ptr) { struct page *ptr_page = virt_to_page(ptr); return page_count(ptr_page) == 1; } static void clear_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr) { pmd_t *pmd_table = pmd_offset(pud, 0); Loading @@ -103,12 +109,6 @@ static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr) put_page(virt_to_page(pmd)); } static bool pmd_empty(pmd_t *pmd) { struct page *pmd_page = virt_to_page(pmd); return page_count(pmd_page) == 1; } static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr) { if (pte_present(*pte)) { Loading @@ -118,12 +118,6 @@ static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr) } } static bool pte_empty(pte_t *pte) { struct page *pte_page = virt_to_page(pte); return page_count(pte_page) == 1; } static void unmap_range(struct kvm *kvm, pgd_t *pgdp, unsigned long long start, u64 size) { Loading @@ -132,37 +126,37 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp, pmd_t *pmd; pte_t *pte; unsigned long long addr = start, end = start + size; u64 range; u64 next; while (addr < end) { pgd = pgdp + pgd_index(addr); pud = pud_offset(pgd, addr); if (pud_none(*pud)) { addr += PUD_SIZE; addr = pud_addr_end(addr, end); continue; } pmd = pmd_offset(pud, addr); if (pmd_none(*pmd)) { addr += PMD_SIZE; addr = pmd_addr_end(addr, end); continue; } pte = pte_offset_kernel(pmd, addr); clear_pte_entry(kvm, pte, addr); range = PAGE_SIZE; next = addr + PAGE_SIZE; /* If we emptied the pte, walk back up the ladder */ if (pte_empty(pte)) { if (page_empty(pte)) { clear_pmd_entry(kvm, pmd, addr); range = PMD_SIZE; if (pmd_empty(pmd)) { next = pmd_addr_end(addr, end); if (page_empty(pmd) && !page_empty(pud)) { clear_pud_entry(kvm, pud, addr); range = PUD_SIZE; next = pud_addr_end(addr, end); } } addr += range; addr = next; } } Loading