WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] x86: improve output resulting from sending '0' over

To: <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH] x86: improve output resulting from sending '0' over serial
From: "Jan Beulich" <JBeulich@xxxxxxxxxx>
Date: Wed, 10 Jun 2009 15:57:26 +0100
Delivery-date: Wed, 10 Jun 2009 07:56:35 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
While the original logic already implied that the kernel part of the
guest's address space is identical on all vCPU-s (i.e. for all guest
processes), it didn't fully leverage the potential here: As long as
the top page table currently active is owned by the subject domain
(currently only Dom0), the stack dump can be done without extra
effort.

For x86-64, additionally add page table traversal so that the stack
can be dumped in all cases (unless it's invalid or user space).

I left the 32-bit variant of do_page_walk() unimplemented for the
moment as I couldn't convince myself using map_domain_page() there is
a good idea, and didn't want to introduce new fixmap entries either.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>

--- 2009-06-10.orig/xen/arch/x86/traps.c        2009-06-10 10:48:29.000000000 
+0200
+++ 2009-06-10/xen/arch/x86/traps.c     2009-06-10 11:15:26.000000000 +0200
@@ -129,18 +129,18 @@ boolean_param("ler", opt_ler);
 #define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)regs->rsp)
 #endif
 
-static void show_guest_stack(struct cpu_user_regs *regs)
+static void show_guest_stack(struct vcpu *v, struct cpu_user_regs *regs)
 {
     int i;
-    struct vcpu *curr = current;
     unsigned long *stack, addr;
+    unsigned long mask = STACK_SIZE;
 
-    if ( is_hvm_vcpu(curr) )
+    if ( is_hvm_vcpu(v) )
         return;
 
-    if ( is_pv_32on64_vcpu(curr) )
+    if ( is_pv_32on64_vcpu(v) )
     {
-        compat_show_guest_stack(regs, debug_stack_lines);
+        compat_show_guest_stack(v, regs, debug_stack_lines);
         return;
     }
 
@@ -156,11 +156,42 @@ static void show_guest_stack(struct cpu_
         printk("Guest stack trace from "__OP"sp=%p:\n  ", stack);
     }
 
+    if ( !access_ok(stack, sizeof(*stack)) )
+    {
+        printk("Guest-inaccessible memory.\n");
+        return;
+    }
+
+    if ( v != current )
+    {
+        struct vcpu *vcpu;
+
+        ASSERT(guest_kernel_mode(v, regs));
+#ifndef __x86_64__
+        addr = read_cr3();
+        for_each_vcpu( v->domain, vcpu )
+            if ( vcpu->arch.cr3 == addr )
+                break;
+#else
+        vcpu = maddr_get_owner(read_cr3()) == v->domain ? v : NULL;
+#endif
+        if ( !vcpu )
+        {
+            stack = do_page_walk(v, (unsigned long)stack);
+            if ( (unsigned long)stack < PAGE_SIZE )
+            {
+                printk("Inaccessible guest memory.\n");
+                return;
+            }
+            mask = PAGE_SIZE;
+        }
+    }
+
     for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ )
     {
-        if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 )
+        if ( (((long)stack - 1) ^ ((long)(stack + 1) - 1)) & mask )
             break;
-        if ( get_user(addr, stack) )
+        if ( __get_user(addr, stack) )
         {
             if ( i != 0 )
                 printk("\n    ");
@@ -264,7 +295,7 @@ void show_stack(struct cpu_user_regs *re
     int i;
 
     if ( guest_mode(regs) )
-        return show_guest_stack(regs);
+        return show_guest_stack(current, regs);
 
     printk("Xen stack trace from "__OP"sp=%p:\n  ", stack);
 
@@ -346,10 +377,8 @@ void vcpu_show_execution_state(struct vc
     vcpu_pause(v); /* acceptably dangerous */
 
     vcpu_show_registers(v);
-    /* Todo: map arbitrary vcpu's top guest stack page here. */
-    if ( (v->domain == current->domain) &&
-         guest_kernel_mode(v, &v->arch.guest_context.user_regs) )
-        show_guest_stack(&v->arch.guest_context.user_regs);
+    if ( guest_kernel_mode(v, &v->arch.guest_context.user_regs) )
+        show_guest_stack(v, &v->arch.guest_context.user_regs);
 
     vcpu_unpause(v);
 }
--- 2009-06-10.orig/xen/arch/x86/x86_32/mm.c    2009-05-20 08:45:59.000000000 
+0200
+++ 2009-06-10/xen/arch/x86/x86_32/mm.c 2009-06-10 11:15:26.000000000 +0200
@@ -63,6 +63,11 @@ l2_pgentry_t *virt_to_xen_l2e(unsigned l
     return &idle_pg_table_l2[l2_linear_offset(v)];
 }
 
+void *do_page_walk(struct vcpu *v, unsigned long addr)
+{
+    return NULL;
+}
+
 void __init paging_init(void)
 {
     unsigned long v;
--- 2009-06-10.orig/xen/arch/x86/x86_64/compat/traps.c  2008-07-18 
16:19:34.000000000 +0200
+++ 2009-06-10/xen/arch/x86/x86_64/compat/traps.c       2009-06-10 
11:15:26.000000000 +0200
@@ -5,18 +5,46 @@
 #include <compat/callback.h>
 #include <compat/arch-x86_32.h>
 
-void compat_show_guest_stack(struct cpu_user_regs *regs, int debug_stack_lines)
+void compat_show_guest_stack(struct vcpu *v, struct cpu_user_regs *regs,
+                             int debug_stack_lines)
 {
-    unsigned int i, *stack, addr;
+    unsigned int i, *stack, addr, mask = STACK_SIZE;
 
     stack = (unsigned int *)(unsigned long)regs->_esp;
     printk("Guest stack trace from esp=%08lx:\n ", (unsigned long)stack);
 
+    if ( !__compat_access_ok(v->domain, stack, sizeof(*stack)) )
+    {
+        printk("Guest-inaccessible memory.\n");
+        return;
+    }
+
+    if ( v != current )
+    {
+        struct vcpu *vcpu;
+
+        ASSERT(guest_kernel_mode(v, regs));
+        addr = read_cr3() >> PAGE_SHIFT;
+        for_each_vcpu( v->domain, vcpu )
+            if ( pagetable_get_pfn(vcpu->arch.guest_table) == addr )
+                break;
+        if ( !vcpu )
+        {
+            stack = do_page_walk(v, (unsigned long)stack);
+            if ( (unsigned long)stack < PAGE_SIZE )
+            {
+                printk("Inaccessible guest memory.\n");
+                return;
+            }
+            mask = PAGE_SIZE;
+        }
+    }
+
     for ( i = 0; i < debug_stack_lines * 8; i++ )
     {
-        if ( (((long)stack + 3) & (STACK_SIZE - 4)) == 0 )
+        if ( (((long)stack - 1) ^ ((long)(stack + 1) - 1)) & mask )
             break;
-        if ( get_user(addr, stack) )
+        if ( __get_user(addr, stack) )
         {
             if ( i != 0 )
                 printk("\n    ");
--- 2009-06-10.orig/xen/arch/x86/x86_64/mm.c    2009-05-20 08:45:59.000000000 
+0200
+++ 2009-06-10/xen/arch/x86/x86_64/mm.c 2009-06-10 11:15:26.000000000 +0200
@@ -103,6 +103,47 @@ l2_pgentry_t *virt_to_xen_l2e(unsigned l
     return l3e_to_l2e(*pl3e) + l2_table_offset(v);
 }
 
+void *do_page_walk(struct vcpu *v, unsigned long addr)
+{
+    unsigned long mfn = pagetable_get_pfn(v->arch.guest_table);
+    l4_pgentry_t l4e, *l4t;
+    l3_pgentry_t l3e, *l3t;
+    l2_pgentry_t l2e, *l2t;
+    l1_pgentry_t l1e, *l1t;
+
+    if ( is_hvm_vcpu(v) )
+        return NULL;
+
+    l4t = mfn_to_virt(mfn);
+    l4e = l4t[l4_table_offset(addr)];
+    mfn = l4e_get_pfn(l4e);
+    if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
+        return NULL;
+
+    l3t = mfn_to_virt(mfn);
+    l3e = l3t[l3_table_offset(addr)];
+    mfn = l3e_get_pfn(l3e);
+    if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) || !mfn_valid(mfn) )
+    if ( (l3e_get_flags(l3e) & _PAGE_PSE) )
+        return mfn_to_virt(mfn) + (addr & ((1UL << L3_PAGETABLE_SHIFT) - 1));
+
+    l2t = mfn_to_virt(mfn);
+    l2e = l2t[l2_table_offset(addr)];
+    mfn = l2e_get_pfn(l2e);
+    if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) || !mfn_valid(mfn) )
+        return NULL;
+    if ( (l2e_get_flags(l2e) & _PAGE_PSE) )
+        return mfn_to_virt(mfn) + (addr & ((1UL << L2_PAGETABLE_SHIFT) - 1));
+
+    l1t = mfn_to_virt(mfn);
+    l1e = l1t[l1_table_offset(addr)];
+    mfn = l1e_get_pfn(l1e);
+    if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) || !mfn_valid(mfn) )
+        return NULL;
+
+    return mfn_to_virt(mfn) + (addr & ~PAGE_MASK);
+}
+
 void __init paging_init(void)
 {
     unsigned long i, mpt_size, va;
--- 2009-06-10.orig/xen/include/asm-x86/mm.h    2009-06-05 11:59:48.000000000 
+0200
+++ 2009-06-10/xen/include/asm-x86/mm.h 2009-06-10 11:15:26.000000000 +0200
@@ -475,6 +475,7 @@ int new_guest_cr3(unsigned long pfn);
 void make_cr3(struct vcpu *v, unsigned long mfn);
 void update_cr3(struct vcpu *v);
 void propagate_page_fault(unsigned long addr, u16 error_code);
+void *do_page_walk(struct vcpu *v, unsigned long addr);
 
 int __sync_lazy_execstate(void);
 
--- 2009-06-10.orig/xen/include/asm-x86/processor.h     2009-03-16 
16:09:07.000000000 +0100
+++ 2009-06-10/xen/include/asm-x86/processor.h  2009-06-10 11:15:26.000000000 
+0200
@@ -536,9 +536,9 @@ void show_page_walk(unsigned long addr);
 asmlinkage void fatal_trap(int trapnr, struct cpu_user_regs *regs);
 
 #ifdef CONFIG_COMPAT
-void compat_show_guest_stack(struct cpu_user_regs *, int lines);
+void compat_show_guest_stack(struct vcpu *, struct cpu_user_regs *, int lines);
 #else
-#define compat_show_guest_stack(regs, lines) ((void)0)
+#define compat_show_guest_stack(vcpu, regs, lines) ((void)0)
 #endif
 
 extern void mtrr_ap_init(void);
--- 2009-06-10.orig/xen/include/asm-x86/x86_64/uaccess.h        2008-06-16 
10:43:34.000000000 +0200
+++ 2009-06-10/xen/include/asm-x86/x86_64/uaccess.h     2009-06-10 
11:15:26.000000000 +0200
@@ -27,11 +27,14 @@ DECLARE_PER_CPU(char, compat_arg_xlat[CO
 #define array_access_ok(addr, count, size) \
     (access_ok(addr, (count)*(size)))
 
-#define __compat_addr_ok(addr) \
-    ((unsigned long)(addr) < HYPERVISOR_COMPAT_VIRT_START(current->domain))
+#define __compat_addr_ok(d, addr) \
+    ((unsigned long)(addr) < HYPERVISOR_COMPAT_VIRT_START(d))
+
+#define __compat_access_ok(d, addr, size) \
+    __compat_addr_ok(d, (unsigned long)(addr) + ((size) ? (size) - 1 : 0))
 
 #define compat_access_ok(addr, size) \
-    __compat_addr_ok((unsigned long)(addr) + ((size) ? (size) - 1 : 0))
+    __compat_access_ok(current->domain, addr, size)
 
 #define compat_array_access_ok(addr,count,size) \
     (likely((count) < (~0U / (size))) && \



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH] x86: improve output resulting from sending '0' over serial, Jan Beulich <=