Author: bde
Date: Sun Aug 14 16:51:25 2016
New Revision: 304085
URL: https://svnweb.freebsd.org/changeset/base/304085

Log:
  Fix the variables $esp, $ds, $es, $fs, $gs and $ss in vm86 mode.
  
  Fix PC_REGS() so that printing of instructions works in some useful
  cases.  ddb only understands a single flat address space, but this
  macro allows mapping $cs:$eip into vm86's flat address space well
  enough for the MI parts of ddb.  This doesn't work for the MD parts
  that do stack traces, and there are no similar macros for data addresses.
  
  PC_REGS() has to use the trapframe pointer instead of the pcb for this.
  For other CPUs, the trapframe pointer is not available except by tracing
  back to it.  But tracing back through vm86 trapframes is broken even
  starting with one.

Modified:
  head/sys/i386/i386/db_trace.c
  head/sys/i386/include/db_machdep.h

Modified: head/sys/i386/i386/db_trace.c
==============================================================================
--- head/sys/i386/i386/db_trace.c       Sun Aug 14 16:32:23 2016        
(r304084)
+++ head/sys/i386/i386/db_trace.c       Sun Aug 14 16:51:25 2016        
(r304085)
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/sysent.h>
 
 #include <machine/cpu.h>
+#include <machine/frame.h>
 #include <machine/md_var.h>
 #include <machine/pcb.h>
 #include <machine/reg.h>
@@ -81,8 +82,8 @@ struct db_variable *db_eregs = db_regs +
 static __inline int
 get_esp(struct trapframe *tf)
 {
-       return ((ISPL(tf->tf_cs)) ? tf->tf_esp :
-           (db_expr_t)tf + (uintptr_t)DB_OFFSET(tf_esp));
+       return ((ISPL(tf->tf_cs) || kdb_frame->tf_eflags & PSL_VM) ?
+           tf->tf_esp : (intptr_t)&tf->tf_esp);
 }
 
 static int
@@ -104,12 +105,32 @@ db_frame(struct db_variable *vp, db_expr
 static int
 db_frame_seg(struct db_variable *vp, db_expr_t *valuep, int op)
 {
+       struct trapframe_vm86 *tfp;
+       int off;
        uint16_t *reg;
 
        if (kdb_frame == NULL)
                return (0);
 
-       reg = (uint16_t *)((uintptr_t)kdb_frame + (db_expr_t)vp->valuep);
+       off = (intptr_t)vp->valuep;
+       if (kdb_frame->tf_eflags & PSL_VM) {
+               tfp = (void *)kdb_frame;
+               switch ((intptr_t)vp->valuep) {
+               case (intptr_t)DB_OFFSET(tf_cs):
+                       reg = (uint16_t *)&tfp->tf_cs;
+                       break;
+               case (intptr_t)DB_OFFSET(tf_ds):
+                       reg = (uint16_t *)&tfp->tf_vm86_ds;
+                       break;
+               case (intptr_t)DB_OFFSET(tf_es):
+                       reg = (uint16_t *)&tfp->tf_vm86_es;
+                       break;
+               case (intptr_t)DB_OFFSET(tf_fs):
+                       reg = (uint16_t *)&tfp->tf_vm86_fs;
+                       break;
+               }
+       } else
+               reg = (uint16_t *)((uintptr_t)kdb_frame + off);
        if (op == DB_VAR_GET)
                *valuep = *reg;
        else
@@ -134,7 +155,16 @@ db_esp(struct db_variable *vp, db_expr_t
 static int
 db_gs(struct db_variable *vp, db_expr_t *valuep, int op)
 {
+       struct trapframe_vm86 *tfp;
 
+       if (kdb_frame != NULL && kdb_frame->tf_eflags & PSL_VM) {
+               tfp = (void *)kdb_frame;
+               if (op == DB_VAR_GET)
+                       *valuep = tfp->tf_vm86_gs;
+               else
+                       tfp->tf_vm86_gs = *valuep;
+               return (1);
+       }
        if (op == DB_VAR_GET)
                *valuep = rgs();
        else
@@ -150,8 +180,9 @@ db_ss(struct db_variable *vp, db_expr_t 
                return (0);
 
        if (op == DB_VAR_GET)
-               *valuep = (ISPL(kdb_frame->tf_cs)) ? kdb_frame->tf_ss : rss();
-       else if (ISPL(kdb_frame->tf_cs))
+               *valuep = (ISPL(kdb_frame->tf_cs) ||
+                   kdb_frame->tf_eflags & PSL_VM) ? kdb_frame->tf_ss : rss();
+       else if (ISPL(kdb_frame->tf_cs) || kdb_frame->tf_eflags & PSL_VM)
                kdb_frame->tf_ss = *valuep;
        return (1);
 }

Modified: head/sys/i386/include/db_machdep.h
==============================================================================
--- head/sys/i386/include/db_machdep.h  Sun Aug 14 16:32:23 2016        
(r304084)
+++ head/sys/i386/include/db_machdep.h  Sun Aug 14 16:51:25 2016        
(r304085)
@@ -35,7 +35,10 @@
 typedef        vm_offset_t     db_addr_t;      /* address - unsigned */
 typedef        int             db_expr_t;      /* expression - signed */
 
-#define        PC_REGS()       ((db_addr_t)kdb_thrctx->pcb_eip)
+#define        PC_REGS()       ((db_addr_t)(kdb_frame->tf_eflags & PSL_VM ?    
\
+                           (kdb_frame->tf_eip & 0xffff) +              \
+                           ((kdb_frame->tf_cs & 0xffff) << 4) :        \
+                           kdb_frame->tf_eip))
 
 #define        BKPT_INST       0xcc            /* breakpoint instruction */
 #define        BKPT_SIZE       (1)             /* size of breakpoint inst */
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to