|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen master] x86/PVH: actually show Dom0's register state from debug key '0'
commit 1578322ac6bc4d66800a5a3caf6685f556b64054
Author: Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Tue Sep 28 16:03:38 2021 +0200
Commit: Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Tue Sep 28 16:03:38 2021 +0200
x86/PVH: actually show Dom0's register state from debug key '0'
vcpu_show_registers() didn't do anything for HVM so far. Note though
that some extra hackery is needed for VMX - see the code comment.
Note further that the show_guest_stack() invocation is left alone here:
While strictly speaking guest_kernel_mode() should be predicated by a
PV / !HVM check, show_guest_stack() itself will bail immediately for
HVM.
While there and despite not being PVH-specific, take the opportunity and
filter offline vCPU-s: There's not really any register state associated
with them, so avoid spamming the log with useless information while
still leaving an indication of the fact.
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
Reviewed-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
---
xen/arch/x86/traps.c | 26 +++++++++++++
xen/arch/x86/x86_64/traps.c | 95 ++++++++++++++++++++++++++++-----------------
2 files changed, 86 insertions(+), 35 deletions(-)
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 0cc1ee95cb..c2e2603c39 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -632,6 +632,12 @@ void vcpu_show_execution_state(struct vcpu *v)
{
unsigned long flags;
+ if ( test_bit(_VPF_down, &v->pause_flags) )
+ {
+ printk("*** %pv is offline ***\n", v);
+ return;
+ }
+
printk("*** Dumping Dom%d vcpu#%d state: ***\n",
v->domain->domain_id, v->vcpu_id);
@@ -643,6 +649,21 @@ void vcpu_show_execution_state(struct vcpu *v)
vcpu_pause(v); /* acceptably dangerous */
+#ifdef CONFIG_HVM
+ /*
+ * For VMX special care is needed: Reading some of the register state will
+ * require VMCS accesses. Engaging foreign VMCSes involves acquiring of a
+ * lock, which check_lock() would object to when done from an IRQs-disabled
+ * region. Despite this being a layering violation, engage the VMCS right
+ * here. This then also avoids doing so several times in close succession.
+ */
+ if ( cpu_has_vmx && is_hvm_vcpu(v) )
+ {
+ ASSERT(!in_irq());
+ vmx_vmcs_enter(v);
+ }
+#endif
+
/* Prevent interleaving of output. */
flags = console_lock_recursive_irqsave();
@@ -652,6 +673,11 @@ void vcpu_show_execution_state(struct vcpu *v)
console_unlock_recursive_irqrestore(flags);
+#ifdef CONFIG_HVM
+ if ( cpu_has_vmx && is_hvm_vcpu(v) )
+ vmx_vmcs_exit(v);
+#endif
+
vcpu_unpause(v);
}
diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c
index 4116ecb9c0..d661d7ffca 100644
--- a/xen/arch/x86/x86_64/traps.c
+++ b/xen/arch/x86/x86_64/traps.c
@@ -49,6 +49,39 @@ static void read_registers(struct cpu_user_regs *regs,
unsigned long crs[8])
crs[7] = read_gs_shadow();
}
+static void get_hvm_registers(struct vcpu *v, struct cpu_user_regs *regs,
+ unsigned long crs[8])
+{
+ struct segment_register sreg;
+
+ crs[0] = v->arch.hvm.guest_cr[0];
+ crs[2] = v->arch.hvm.guest_cr[2];
+ crs[3] = v->arch.hvm.guest_cr[3];
+ crs[4] = v->arch.hvm.guest_cr[4];
+
+ hvm_get_segment_register(v, x86_seg_cs, &sreg);
+ regs->cs = sreg.sel;
+
+ hvm_get_segment_register(v, x86_seg_ds, &sreg);
+ regs->ds = sreg.sel;
+
+ hvm_get_segment_register(v, x86_seg_es, &sreg);
+ regs->es = sreg.sel;
+
+ hvm_get_segment_register(v, x86_seg_fs, &sreg);
+ regs->fs = sreg.sel;
+ crs[5] = sreg.base;
+
+ hvm_get_segment_register(v, x86_seg_gs, &sreg);
+ regs->gs = sreg.sel;
+ crs[6] = sreg.base;
+
+ hvm_get_segment_register(v, x86_seg_ss, &sreg);
+ regs->ss = sreg.sel;
+
+ crs[7] = hvm_get_shadow_gs_base(v);
+}
+
static void _show_registers(
const struct cpu_user_regs *regs, unsigned long crs[8],
enum context context, const struct vcpu *v)
@@ -99,27 +132,8 @@ void show_registers(const struct cpu_user_regs *regs)
if ( guest_mode(regs) && is_hvm_vcpu(v) )
{
- struct segment_register sreg;
+ get_hvm_registers(v, &fault_regs, fault_crs);
context = CTXT_hvm_guest;
- fault_crs[0] = v->arch.hvm.guest_cr[0];
- fault_crs[2] = v->arch.hvm.guest_cr[2];
- fault_crs[3] = v->arch.hvm.guest_cr[3];
- fault_crs[4] = v->arch.hvm.guest_cr[4];
- hvm_get_segment_register(v, x86_seg_cs, &sreg);
- fault_regs.cs = sreg.sel;
- hvm_get_segment_register(v, x86_seg_ds, &sreg);
- fault_regs.ds = sreg.sel;
- hvm_get_segment_register(v, x86_seg_es, &sreg);
- fault_regs.es = sreg.sel;
- hvm_get_segment_register(v, x86_seg_fs, &sreg);
- fault_regs.fs = sreg.sel;
- fault_crs[5] = sreg.base;
- hvm_get_segment_register(v, x86_seg_gs, &sreg);
- fault_regs.gs = sreg.sel;
- fault_crs[6] = sreg.base;
- hvm_get_segment_register(v, x86_seg_ss, &sreg);
- fault_regs.ss = sreg.sel;
- fault_crs[7] = hvm_get_shadow_gs_base(v);
}
else
{
@@ -159,24 +173,35 @@ void show_registers(const struct cpu_user_regs *regs)
void vcpu_show_registers(const struct vcpu *v)
{
const struct cpu_user_regs *regs = &v->arch.user_regs;
- bool kernel = guest_kernel_mode(v, regs);
+ struct cpu_user_regs aux_regs;
+ enum context context;
unsigned long crs[8];
- /* Only handle PV guests for now */
- if ( !is_pv_vcpu(v) )
- return;
+ if ( is_hvm_vcpu(v) )
+ {
+ aux_regs = *regs;
+ get_hvm_registers(v->domain->vcpu[v->vcpu_id], &aux_regs, crs);
+ regs = &aux_regs;
+ context = CTXT_hvm_guest;
+ }
+ else
+ {
+ bool kernel = guest_kernel_mode(v, regs);
+
+ crs[0] = v->arch.pv.ctrlreg[0];
+ crs[2] = arch_get_cr2(v);
+ crs[3] = pagetable_get_paddr(kernel ?
+ v->arch.guest_table :
+ v->arch.guest_table_user);
+ crs[4] = v->arch.pv.ctrlreg[4];
+ crs[5] = v->arch.pv.fs_base;
+ crs[6 + !kernel] = v->arch.pv.gs_base_kernel;
+ crs[7 - !kernel] = v->arch.pv.gs_base_user;
+
+ context = CTXT_pv_guest;
+ }
- crs[0] = v->arch.pv.ctrlreg[0];
- crs[2] = arch_get_cr2(v);
- crs[3] = pagetable_get_paddr(kernel ?
- v->arch.guest_table :
- v->arch.guest_table_user);
- crs[4] = v->arch.pv.ctrlreg[4];
- crs[5] = v->arch.pv.fs_base;
- crs[6 + !kernel] = v->arch.pv.gs_base_kernel;
- crs[7 - !kernel] = v->arch.pv.gs_base_user;
-
- _show_registers(regs, crs, CTXT_pv_guest, v);
+ _show_registers(regs, crs, context, v);
}
void show_page_walk(unsigned long addr)
--
generated by git-patchbot for /home/xen/git/xen.git#master
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |