linux/arch/arm64/kvm/hyp/debug-sr.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2015 - ARM Ltd
   3 * Author: Marc Zyngier <marc.zyngier@arm.com>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License version 2 as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16 */
  17
  18#include <linux/compiler.h>
  19#include <linux/kvm_host.h>
  20
  21#include <asm/kvm_asm.h>
  22#include <asm/kvm_mmu.h>
  23
  24#include "hyp.h"
  25
  26#define read_debug(r,n)         read_sysreg(r##n##_el1)
  27#define write_debug(v,r,n)      write_sysreg(v, r##n##_el1)
  28
  29#define save_debug(ptr,reg,nr)                                          \
  30        switch (nr) {                                                   \
  31        case 15:        ptr[15] = read_debug(reg, 15);                  \
  32        case 14:        ptr[14] = read_debug(reg, 14);                  \
  33        case 13:        ptr[13] = read_debug(reg, 13);                  \
  34        case 12:        ptr[12] = read_debug(reg, 12);                  \
  35        case 11:        ptr[11] = read_debug(reg, 11);                  \
  36        case 10:        ptr[10] = read_debug(reg, 10);                  \
  37        case 9:         ptr[9] = read_debug(reg, 9);                    \
  38        case 8:         ptr[8] = read_debug(reg, 8);                    \
  39        case 7:         ptr[7] = read_debug(reg, 7);                    \
  40        case 6:         ptr[6] = read_debug(reg, 6);                    \
  41        case 5:         ptr[5] = read_debug(reg, 5);                    \
  42        case 4:         ptr[4] = read_debug(reg, 4);                    \
  43        case 3:         ptr[3] = read_debug(reg, 3);                    \
  44        case 2:         ptr[2] = read_debug(reg, 2);                    \
  45        case 1:         ptr[1] = read_debug(reg, 1);                    \
  46        default:        ptr[0] = read_debug(reg, 0);                    \
  47        }
  48
  49#define restore_debug(ptr,reg,nr)                                       \
  50        switch (nr) {                                                   \
  51        case 15:        write_debug(ptr[15], reg, 15);                  \
  52        case 14:        write_debug(ptr[14], reg, 14);                  \
  53        case 13:        write_debug(ptr[13], reg, 13);                  \
  54        case 12:        write_debug(ptr[12], reg, 12);                  \
  55        case 11:        write_debug(ptr[11], reg, 11);                  \
  56        case 10:        write_debug(ptr[10], reg, 10);                  \
  57        case 9:         write_debug(ptr[9], reg, 9);                    \
  58        case 8:         write_debug(ptr[8], reg, 8);                    \
  59        case 7:         write_debug(ptr[7], reg, 7);                    \
  60        case 6:         write_debug(ptr[6], reg, 6);                    \
  61        case 5:         write_debug(ptr[5], reg, 5);                    \
  62        case 4:         write_debug(ptr[4], reg, 4);                    \
  63        case 3:         write_debug(ptr[3], reg, 3);                    \
  64        case 2:         write_debug(ptr[2], reg, 2);                    \
  65        case 1:         write_debug(ptr[1], reg, 1);                    \
  66        default:        write_debug(ptr[0], reg, 0);                    \
  67        }
  68
  69void __hyp_text __debug_save_state(struct kvm_vcpu *vcpu,
  70                                   struct kvm_guest_debug_arch *dbg,
  71                                   struct kvm_cpu_context *ctxt)
  72{
  73        u64 aa64dfr0;
  74        int brps, wrps;
  75
  76        if (!(vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY))
  77                return;
  78
  79        aa64dfr0 = read_sysreg(id_aa64dfr0_el1);
  80        brps = (aa64dfr0 >> 12) & 0xf;
  81        wrps = (aa64dfr0 >> 20) & 0xf;
  82
  83        save_debug(dbg->dbg_bcr, dbgbcr, brps);
  84        save_debug(dbg->dbg_bvr, dbgbvr, brps);
  85        save_debug(dbg->dbg_wcr, dbgwcr, wrps);
  86        save_debug(dbg->dbg_wvr, dbgwvr, wrps);
  87
  88        ctxt->sys_regs[MDCCINT_EL1] = read_sysreg(mdccint_el1);
  89}
  90
  91void __hyp_text __debug_restore_state(struct kvm_vcpu *vcpu,
  92                                      struct kvm_guest_debug_arch *dbg,
  93                                      struct kvm_cpu_context *ctxt)
  94{
  95        u64 aa64dfr0;
  96        int brps, wrps;
  97
  98        if (!(vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY))
  99                return;
 100
 101        aa64dfr0 = read_sysreg(id_aa64dfr0_el1);
 102
 103        brps = (aa64dfr0 >> 12) & 0xf;
 104        wrps = (aa64dfr0 >> 20) & 0xf;
 105
 106        restore_debug(dbg->dbg_bcr, dbgbcr, brps);
 107        restore_debug(dbg->dbg_bvr, dbgbvr, brps);
 108        restore_debug(dbg->dbg_wcr, dbgwcr, wrps);
 109        restore_debug(dbg->dbg_wvr, dbgwvr, wrps);
 110
 111        write_sysreg(ctxt->sys_regs[MDCCINT_EL1], mdccint_el1);
 112}
 113
 114void __hyp_text __debug_cond_save_host_state(struct kvm_vcpu *vcpu)
 115{
 116        /* If any of KDE, MDE or KVM_ARM64_DEBUG_DIRTY is set, perform
 117         * a full save/restore cycle. */
 118        if ((vcpu->arch.ctxt.sys_regs[MDSCR_EL1] & DBG_MDSCR_KDE) ||
 119            (vcpu->arch.ctxt.sys_regs[MDSCR_EL1] & DBG_MDSCR_MDE))
 120                vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
 121
 122        __debug_save_state(vcpu, &vcpu->arch.host_debug_state,
 123                           kern_hyp_va(vcpu->arch.host_cpu_context));
 124}
 125
 126void __hyp_text __debug_cond_restore_host_state(struct kvm_vcpu *vcpu)
 127{
 128        __debug_restore_state(vcpu, &vcpu->arch.host_debug_state,
 129                              kern_hyp_va(vcpu->arch.host_cpu_context));
 130
 131        if (vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY)
 132                vcpu->arch.debug_flags &= ~KVM_ARM64_DEBUG_DIRTY;
 133}
 134
 135static u32 __hyp_text __debug_read_mdcr_el2(void)
 136{
 137        return read_sysreg(mdcr_el2);
 138}
 139
 140__alias(__debug_read_mdcr_el2) u32 __kvm_get_mdcr_el2(void);
 141