Page MenuHomeFreeBSD

D44739.id.diff
No OneTemporary

D44739.id.diff

diff --git a/sys/arm64/include/vmm.h b/sys/arm64/include/vmm.h
--- a/sys/arm64/include/vmm.h
+++ b/sys/arm64/include/vmm.h
@@ -295,9 +295,11 @@
*/
enum vm_cap_type {
VM_CAP_HALT_EXIT,
- VM_CAP_MTRAP_EXIT,
VM_CAP_PAUSE_EXIT,
VM_CAP_UNRESTRICTED_GUEST,
+ VM_CAP_BRK_EXIT,
+ VM_CAP_SS_EXIT,
+ VM_CAP_MASK_HWINTR,
VM_CAP_MAX
};
@@ -312,6 +314,8 @@
VM_EXITCODE_PAGING,
VM_EXITCODE_SMCCC,
VM_EXITCODE_DEBUG,
+ VM_EXITCODE_BRK,
+ VM_EXITCODE_SS,
VM_EXITCODE_MAX
};
diff --git a/sys/arm64/vmm/arm64.h b/sys/arm64/vmm/arm64.h
--- a/sys/arm64/vmm/arm64.h
+++ b/sys/arm64/vmm/arm64.h
@@ -39,6 +39,9 @@
struct vgic_v3;
struct vgic_v3_cpu;
+/*
+ * Per-vCPU hypervisor state.
+ */
struct hypctx {
struct trapframe tf;
@@ -104,6 +107,12 @@
struct vtimer_cpu vtimer_cpu;
+ uint64_t setcaps; /* Currently enabled capabilities. */
+
+ /* vCPU state used to handle guest debugging. */
+ uint64_t debug_spsr; /* Saved guest SPSR */
+ uint64_t debug_mdscr; /* Saved guest MDSCR */
+
struct vgic_v3_regs vgic_v3_regs;
struct vgic_v3_cpu *vgic_cpu;
bool has_exception;
diff --git a/sys/arm64/vmm/vmm_arm64.c b/sys/arm64/vmm/vmm_arm64.c
--- a/sys/arm64/vmm/vmm_arm64.c
+++ b/sys/arm64/vmm/vmm_arm64.c
@@ -700,7 +700,14 @@
arm64_gen_reg_emul_data(esr_iss, vme_ret);
vme_ret->exitcode = VM_EXITCODE_REG_EMUL;
break;
-
+ case EXCP_BRK:
+ vmm_stat_incr(hypctx->vcpu, VMEXIT_BRK, 1);
+ vme_ret->exitcode = VM_EXITCODE_BRK;
+ break;
+ case EXCP_SOFTSTP_EL0:
+ vmm_stat_incr(hypctx->vcpu, VMEXIT_SS, 1);
+ vme_ret->exitcode = VM_EXITCODE_SS;
+ break;
case EXCP_INSN_ABORT_L:
case EXCP_DATA_ABORT_L:
vmm_stat_incr(hypctx->vcpu, esr_ec == EXCP_DATA_ABORT_L ?
@@ -1313,6 +1320,7 @@
int
vmmops_getcap(void *vcpui, int num, int *retval)
{
+ struct hypctx *hypctx = vcpui;
int ret;
ret = ENOENT;
@@ -1322,6 +1330,11 @@
*retval = 1;
ret = 0;
break;
+ case VM_CAP_BRK_EXIT:
+ case VM_CAP_SS_EXIT:
+ case VM_CAP_MASK_HWINTR:
+ *retval = (hypctx->setcaps & (1ul << num)) != 0;
+ break;
default:
break;
}
@@ -1332,6 +1345,68 @@
int
vmmops_setcap(void *vcpui, int num, int val)
{
+ struct hypctx *hypctx = vcpui;
+ int ret;
+
+ ret = 0;
- return (ENOENT);
+ switch (num) {
+ case VM_CAP_BRK_EXIT:
+ if ((val != 0) == (hypctx->setcaps & (1ul << num)) != 0)
+ break;
+ if (val != 0)
+ hypctx->mdcr_el2 |= MDCR_EL2_TDE;
+ else
+ hypctx->mdcr_el2 &= ~MDCR_EL2_TDE;
+ break;
+ case VM_CAP_SS_EXIT:
+ if ((val != 0) == (hypctx->setcaps & (1ul << num)) != 0)
+ break;
+
+ if (val != 0) {
+ hypctx->debug_spsr |= (hypctx->tf.tf_spsr & PSR_SS);
+ hypctx->debug_mdscr |= hypctx->mdscr_el1 &
+ (MDSCR_SS | MDSCR_KDE);
+
+ hypctx->tf.tf_spsr |= PSR_SS;
+ hypctx->mdscr_el1 |= MDSCR_SS | MDSCR_KDE;
+ hypctx->mdcr_el2 |= MDCR_EL2_TDE;
+ } else {
+ hypctx->tf.tf_spsr &= ~PSR_SS;
+ hypctx->tf.tf_spsr |= hypctx->debug_spsr;
+ hypctx->debug_spsr &= ~PSR_SS;
+ hypctx->mdscr_el1 &= ~(MDSCR_SS | MDSCR_KDE);
+ hypctx->mdscr_el1 |= hypctx->debug_mdscr;
+ hypctx->debug_mdscr &= ~(MDSCR_SS | MDSCR_KDE);
+ hypctx->mdcr_el2 &= ~MDCR_EL2_TDE;
+ }
+ break;
+ case VM_CAP_MASK_HWINTR:
+ if ((val != 0) == (hypctx->setcaps & (1ul << num)) != 0)
+ break;
+
+ if (val != 0) {
+ hypctx->debug_spsr |= (hypctx->tf.tf_spsr &
+ (PSR_I | PSR_F));
+ hypctx->tf.tf_spsr |= PSR_I | PSR_F;
+ } else {
+ hypctx->tf.tf_spsr &= ~(PSR_I | PSR_F);
+ hypctx->tf.tf_spsr |= (hypctx->debug_spsr &
+ (PSR_I | PSR_F));
+ hypctx->debug_spsr &= ~(PSR_I | PSR_F);
+ }
+ break;
+ default:
+ ret = ENOENT;
+ break;
+ }
+
+ if (ret == 0) {
+ if (val == 0)
+ hypctx->setcaps &= ~(1ul << num);
+ else
+ hypctx->setcaps |= (1ul << num);
+ }
+
+ return (ret);
}
diff --git a/sys/arm64/vmm/vmm_stat.h b/sys/arm64/vmm/vmm_stat.h
--- a/sys/arm64/vmm/vmm_stat.h
+++ b/sys/arm64/vmm/vmm_stat.h
@@ -140,6 +140,8 @@
VMM_STAT_DECLARE(VMEXIT_UNHANDLED_SYNC);
VMM_STAT_DECLARE(VMEXIT_IRQ);
VMM_STAT_DECLARE(VMEXIT_FIQ);
+VMM_STAT_DECLARE(VMEXIT_BRK);
+VMM_STAT_DECLARE(VMEXIT_SS);
VMM_STAT_DECLARE(VMEXIT_UNHANDLED_EL2);
VMM_STAT_DECLARE(VMEXIT_UNHANDLED);
#endif
diff --git a/sys/arm64/vmm/vmm_stat.c b/sys/arm64/vmm/vmm_stat.c
--- a/sys/arm64/vmm/vmm_stat.c
+++ b/sys/arm64/vmm/vmm_stat.c
@@ -161,5 +161,7 @@
VMM_STAT(VMEXIT_UNHANDLED_SYNC, "number of vmexits for an unhandled synchronous exception");
VMM_STAT(VMEXIT_IRQ, "number of vmexits for an irq");
VMM_STAT(VMEXIT_FIQ, "number of vmexits for an interrupt");
+VMM_STAT(VMEXIT_BRK, "number of vmexits for a breakpoint exception");
+VMM_STAT(VMEXIT_SS, "number of vmexits for a single-step exception");
VMM_STAT(VMEXIT_UNHANDLED_EL2, "number of vmexits for an unhandled EL2 exception");
VMM_STAT(VMEXIT_UNHANDLED, "number of vmexits for an unhandled exception");

File Metadata

Mime Type
text/plain
Expires
Sun, Apr 19, 3:02 PM (7 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31778772
Default Alt Text
D44739.id.diff (4 KB)

Event Timeline