From: christoffer.dall@linaro.org (Christoffer Dall)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3 08/11] KVM: arm: implement dirty bit mechanism for debug registers
Date: Tue, 30 Jun 2015 11:20:20 +0200 [thread overview]
Message-ID: <20150630092020.GP11332@cbox> (raw)
In-Reply-To: <1434969694-7432-9-git-send-email-zhichao.huang@linaro.org>
On Mon, Jun 22, 2015 at 06:41:31PM +0800, Zhichao Huang wrote:
> The trapping code keeps track of the state of the debug registers,
> allowing for the switch code to implement a lazy switching strategy.
>
> Signed-off-by: Zhichao Huang <zhichao.huang@linaro.org>
> ---
> arch/arm/include/asm/kvm_asm.h | 3 +++
> arch/arm/include/asm/kvm_host.h | 3 +++
> arch/arm/kernel/asm-offsets.c | 1 +
> arch/arm/kvm/coproc.c | 39 ++++++++++++++++++++++++++++++++++++--
> arch/arm/kvm/interrupts_head.S | 42 +++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 86 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
> index ba65e05..4fb64cf 100644
> --- a/arch/arm/include/asm/kvm_asm.h
> +++ b/arch/arm/include/asm/kvm_asm.h
> @@ -64,6 +64,9 @@
> #define cp14_DBGDSCRext 65 /* Debug Status and Control external */
> #define NR_CP14_REGS 66 /* Number of regs (incl. invalid) */
>
> +#define KVM_ARM_DEBUG_DIRTY_SHIFT 0
> +#define KVM_ARM_DEBUG_DIRTY (1 << KVM_ARM_DEBUG_DIRTY_SHIFT)
> +
> #define ARM_EXCEPTION_RESET 0
> #define ARM_EXCEPTION_UNDEFINED 1
> #define ARM_EXCEPTION_SOFTWARE 2
> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> index 3d16820..09b54bf 100644
> --- a/arch/arm/include/asm/kvm_host.h
> +++ b/arch/arm/include/asm/kvm_host.h
> @@ -127,6 +127,9 @@ struct kvm_vcpu_arch {
> /* System control coprocessor (cp14) */
> u32 cp14[NR_CP14_REGS];
>
> + /* Debug state */
> + u32 debug_flags;
> +
> /*
> * Anything that is not used directly from assembly code goes
> * here.
> diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
> index 9158de0..e876109 100644
> --- a/arch/arm/kernel/asm-offsets.c
> +++ b/arch/arm/kernel/asm-offsets.c
> @@ -185,6 +185,7 @@ int main(void)
> DEFINE(VCPU_FIQ_REGS, offsetof(struct kvm_vcpu, arch.regs.fiq_regs));
> DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_pc));
> DEFINE(VCPU_CPSR, offsetof(struct kvm_vcpu, arch.regs.usr_regs.ARM_cpsr));
> + DEFINE(VCPU_DEBUG_FLAGS, offsetof(struct kvm_vcpu, arch.debug_flags));
> DEFINE(VCPU_HCR, offsetof(struct kvm_vcpu, arch.hcr));
> DEFINE(VCPU_IRQ_LINES, offsetof(struct kvm_vcpu, arch.irq_lines));
> DEFINE(VCPU_HSR, offsetof(struct kvm_vcpu, arch.fault.hsr));
> diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
> index eeee648..fc0c2ef 100644
> --- a/arch/arm/kvm/coproc.c
> +++ b/arch/arm/kvm/coproc.c
> @@ -220,14 +220,49 @@ bool access_vm_reg(struct kvm_vcpu *vcpu,
> return true;
> }
>
> +/*
> + * We want to avoid world-switching all the DBG registers all the
> + * time:
> + *
> + * - If we've touched any debug register, it is likely that we're
> + * going to touch more of them. It then makes sense to disable the
> + * traps and start doing the save/restore dance
> + * - If debug is active (ARM_DSCR_MDBGEN set), it is then mandatory
> + * to save/restore the registers, as the guest depends on them.
> + *
> + * For this, we use a DIRTY bit, indicating the guest has modified the
> + * debug registers, used as follow:
> + *
> + * On guest entry:
> + * - If the dirty bit is set (because we're coming back from trapping),
> + * disable the traps, save host registers, restore guest registers.
> + * - If debug is actively in use (ARM_DSCR_MDBGEN set),
> + * set the dirty bit, disable the traps, save host registers,
> + * restore guest registers.
> + * - Otherwise, enable the traps
> + *
> + * On guest exit:
> + * - If the dirty bit is set, save guest registers, restore host
> + * registers and clear the dirty bit. This ensure that the host can
> + * now use the debug registers.
> + *
> + * Notice:
> + * - For ARMv7, if the CONFIG_HAVE_HW_BREAKPOINT is set in the guest,
> + * debug is always actively in use (ARM_DSCR_MDBGEN set).
> + * We have to do the save/restore dance in this case, because the
> + * host and the guest might use their respective debug registers
> + * at any moment.
so doesn't this pretty much invalidate the whole saving/dirty effort?
Guests configured from for example multi_v7_defconfig will then act like
this and you will save/restore all these registers always.
Wouldn't a better approach be to enable trapping to hyp mode most of the
time, and simply clear the enabled bit of any host-used break- or
wathcpoints upon guest entry, perhaps maintaining a bitmap of which ones
must be re-set when exiting the guest, and thereby drastically reducing
the amount of save/restore code you'd have to perform.
Of course, you'd also have to keep track of whether the guest has any
breakpoints or watchpoints enabled for when you do the full save/restore
dance.
That would also avoid all issues surrounding accesses to DBGDSCRext
register I think.
> + */
> static bool trap_debug32(struct kvm_vcpu *vcpu,
> const struct coproc_params *p,
> const struct coproc_reg *r)
> {
> - if (p->is_write)
> + if (p->is_write) {
> vcpu->arch.cp14[r->reg] = *vcpu_reg(vcpu, p->Rt1);
> - else
> + vcpu->arch.debug_flags |= KVM_ARM_DEBUG_DIRTY;
> + } else {
> *vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp14[r->reg];
> + }
>
> return true;
> }
> diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S
> index a20b9ad..5662c39 100644
> --- a/arch/arm/kvm/interrupts_head.S
> +++ b/arch/arm/kvm/interrupts_head.S
> @@ -1,4 +1,6 @@
> #include <linux/irqchip/arm-gic.h>
> +#include <asm/hw_breakpoint.h>
> +#include <asm/kvm_asm.h>
> #include <asm/assembler.h>
>
> #define VCPU_USR_REG(_reg_nr) (VCPU_USR_REGS + (_reg_nr * 4))
> @@ -407,6 +409,46 @@ vcpu .req r0 @ vcpu pointer always in r0
> mcr p15, 2, r12, c0, c0, 0 @ CSSELR
> .endm
>
> +/* Assume vcpu pointer in vcpu reg, clobbers r5 */
> +.macro skip_debug_state target
> + ldr r5, [vcpu, #VCPU_DEBUG_FLAGS]
> + cmp r5, #KVM_ARM_DEBUG_DIRTY
> + bne \target
> +1:
> +.endm
> +
> +/* Compute debug state: If ARM_DSCR_MDBGEN or KVM_ARM_DEBUG_DIRTY
> + * is set, we do a full save/restore cycle and disable trapping.
> + *
> + * Assumes vcpu pointer in vcpu reg
> + *
> + * Clobbers r5, r6
> + */
> +.macro compute_debug_state target
> + // Check the state of MDSCR_EL1
> + ldr r5, [vcpu, #CP14_OFFSET(cp14_DBGDSCRext)]
> + and r6, r5, #ARM_DSCR_MDBGEN
> + cmp r6, #0
you can just do 'ands' here, or even tst and you don't have to touch r6.
> + beq 9998f // Nothing to see there
> +
> + // If ARM_DSCR_MDBGEN bit was set, we must set the flag
> + mov r5, #KVM_ARM_DEBUG_DIRTY
> + str r5, [vcpu, #VCPU_DEBUG_FLAGS]
> + b 9999f // Don't skip restore
> +
> +9998:
> + // Otherwise load the flags from memory in case we recently
> + // trapped
> + skip_debug_state \target
> +9999:
> +.endm
> +
> +/* Assume vcpu pointer in vcpu reg, clobbers r5 */
> +.macro clear_debug_dirty_bit
> + mov r5, #0
> + str r5, [vcpu, #VCPU_DEBUG_FLAGS]
> +.endm
> +
> /*
> * Save the VGIC CPU state into memory
> *
> --
> 1.7.12.4
>
Thanks,
-Christoffer
next prev parent reply other threads:[~2015-06-30 9:20 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-06-22 10:41 [PATCH v3 00/11] KVM: arm: debug infrastructure support Zhichao Huang
2015-06-22 10:41 ` [PATCH v3 01/11] KVM: arm: plug guest debug exploit Zhichao Huang
2015-06-29 15:49 ` Christoffer Dall
2015-07-01 7:04 ` zichao
2015-07-01 9:00 ` Christoffer Dall
2015-06-22 10:41 ` [PATCH v3 02/11] KVM: arm: rename pm_fake handler to trap_raz_wi Zhichao Huang
2015-06-30 13:20 ` Christoffer Dall
2015-06-22 10:41 ` [PATCH v3 03/11] KVM: arm: enable to use the ARM_DSCR_MDBGEN macro from KVM assembly code Zhichao Huang
2015-06-30 13:20 ` Christoffer Dall
2015-06-22 10:41 ` [PATCH v3 04/11] KVM: arm: common infrastructure for handling AArch32 CP14/CP15 Zhichao Huang
2015-06-29 19:43 ` Christoffer Dall
2015-07-01 7:09 ` zichao
2015-07-01 9:00 ` Christoffer Dall
2015-06-22 10:41 ` [PATCH v3 05/11] KVM: arm: check ordering of all system register tables Zhichao Huang
2015-06-30 13:20 ` Christoffer Dall
2015-06-22 10:41 ` [PATCH v3 06/11] KVM: arm: add trap handlers for 32-bit debug registers Zhichao Huang
2015-06-29 21:16 ` Christoffer Dall
2015-07-01 7:14 ` zichao
2015-06-22 10:41 ` [PATCH v3 07/11] KVM: arm: add trap handlers for 64-bit " Zhichao Huang
2015-06-30 13:20 ` Christoffer Dall
2015-07-01 7:43 ` Zhichao Huang
2015-06-22 10:41 ` [PATCH v3 08/11] KVM: arm: implement dirty bit mechanism for " Zhichao Huang
2015-06-30 9:20 ` Christoffer Dall [this message]
2015-07-03 9:54 ` Zhichao Huang
2015-07-03 11:56 ` Christoffer Dall
2015-07-07 10:06 ` Zhichao Huang
2015-07-07 10:24 ` Will Deacon
2015-07-08 10:50 ` Zhichao Huang
2015-07-08 17:08 ` Will Deacon
2015-07-09 12:54 ` Zhichao Huang
2015-07-09 11:50 ` Christoffer Dall
2015-07-13 12:12 ` zichao
2015-06-22 10:41 ` [PATCH v3 09/11] KVM: arm: implement lazy world switch " Zhichao Huang
2015-06-30 13:15 ` Christoffer Dall
2015-07-03 10:06 ` Zhichao Huang
2015-07-03 21:05 ` Christoffer Dall
2015-06-22 10:41 ` [PATCH v3 10/11] KVM: arm: add a trace event for cp14 traps Zhichao Huang
2015-06-30 13:20 ` Christoffer Dall
2015-06-22 10:41 ` [PATCH v3 11/11] KVM: arm: enable trapping of all debug registers Zhichao Huang
2015-06-30 13:19 ` Christoffer Dall
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150630092020.GP11332@cbox \
--to=christoffer.dall@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).