AMD64 - Sync AMD64 support from Jordan Gordeev's svn repository and
authorMatthew Dillon <dillon@dragonflybsd.org>
Fri, 29 Aug 2008 17:07:21 +0000 (17:07 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Fri, 29 Aug 2008 17:07:21 +0000 (17:07 +0000)
Google SOC project.  This work is still continuing but represents
substantial progress in the effort.

With this commit the world builds and installs, the loader is able to
boot the kernel, and the kernel is able to initialize, probe devices, and
exec the init program.  The init program is then able to run until it hits
its first fork().  For the purposes of the GSOC the project is being
considered a big success!

The code has been adapted from multiple sources, most notably Peter Wemm
and other peoples work from FreeBSD, with many modifications to make it
work with DragonFly.  Also thanks go to Simon Schubert for working on gdb
and compiler issues, and to Noah Yan for a good chunk of precursor work
in 2007.

While Jordan wishes to be modest on his contribution, frankly we would
not have been able to make this much progress without the large number
of man-hours Jordan has dedicated to his GSOC project painstakingly gluing
code together, tracking down issues, and progressing the boot sequence.

Submitted-by: Jordan Gordeev <jgordeev@dir.bg>
101 files changed:
sys/cpu/amd64/include/asmacros.h
sys/cpu/amd64/include/atomic.h
sys/cpu/amd64/include/cpufunc.h
sys/cpu/amd64/include/frame.h
sys/cpu/amd64/include/npx.h
sys/cpu/amd64/include/param.h
sys/cpu/amd64/include/pmap.h
sys/cpu/amd64/include/segments.h
sys/cpu/amd64/include/signal.h
sys/cpu/amd64/include/specialreg.h
sys/cpu/amd64/include/tls.h
sys/cpu/amd64/include/tss.h
sys/cpu/amd64/include/types.h
sys/cpu/amd64/include/ucontext.h
sys/cpu/amd64/misc/amd64-gdbstub.c [new file with mode: 0644]
sys/platform/pc64/amd64/autoconf.c
sys/platform/pc64/amd64/console.c
sys/platform/pc64/amd64/cpu_regs.c [deleted file]
sys/platform/pc64/amd64/db_disasm.c
sys/platform/pc64/amd64/db_interface.c
sys/platform/pc64/amd64/db_trace.c
sys/platform/pc64/amd64/exception.S [new file with mode: 0644]
sys/platform/pc64/amd64/exception.c [deleted file]
sys/platform/pc64/amd64/fork_tramp.s [deleted file]
sys/platform/pc64/amd64/genassym.c
sys/platform/pc64/amd64/global.s
sys/platform/pc64/amd64/globaldata.c
sys/platform/pc64/amd64/identcpu.c [new file with mode: 0644]
sys/platform/pc64/amd64/in_cksum2.s
sys/platform/pc64/amd64/init.c
sys/platform/pc64/amd64/initcpu.c [new file with mode: 0644]
sys/platform/pc64/amd64/ipl.s [new file with mode: 0644]
sys/platform/pc64/amd64/locore.s
sys/platform/pc64/amd64/machdep.c [new file with mode: 0644]
sys/platform/pc64/amd64/machintr.c [deleted file]
sys/platform/pc64/amd64/nexus.c [new file with mode: 0644]
sys/platform/pc64/amd64/npx.c
sys/platform/pc64/amd64/pmap.c
sys/platform/pc64/amd64/pmap_inval.c [new file with mode: 0644]
sys/platform/pc64/amd64/spinlock.s [new file with mode: 0644]
sys/platform/pc64/amd64/support.s
sys/platform/pc64/amd64/swtch.s
sys/platform/pc64/amd64/systimer.c
sys/platform/pc64/amd64/tls.c
sys/platform/pc64/amd64/trap.c
sys/platform/pc64/amd64/vm_machdep.c
sys/platform/pc64/apic/apic_abi.c [new file with mode: 0644]
sys/platform/pc64/apic/apic_ipl.h [new file with mode: 0644]
sys/platform/pc64/apic/apic_ipl.s [new file with mode: 0644]
sys/platform/pc64/apic/apic_vector.s [new file with mode: 0644]
sys/platform/pc64/apic/apicreg.h [new file with mode: 0644]
sys/platform/pc64/apic/apicvar.h [new file with mode: 0644]
sys/platform/pc64/apic/mpapic.c [new file with mode: 0644]
sys/platform/pc64/apic/mpapic.h [new file with mode: 0644]
sys/platform/pc64/conf/files
sys/platform/pc64/conf/kern.mk
sys/platform/pc64/conf/options
sys/platform/pc64/icu/icu.h [copied from sys/cpu/amd64/include/tss.h with 59% similarity]
sys/platform/pc64/icu/icu_abi.c [new file with mode: 0644]
sys/platform/pc64/icu/icu_ipl.h [copied from sys/platform/pc64/include/pcb_ext.h with 56% similarity]
sys/platform/pc64/icu/icu_ipl.s [new file with mode: 0644]
sys/platform/pc64/icu/icu_vector.s [new file with mode: 0644]
sys/platform/pc64/include/globaldata.h
sys/platform/pc64/include/intr_machdep.h
sys/platform/pc64/include/ipl.h [copied from sys/platform/pc64/amd64/console.c with 84% similarity]
sys/platform/pc64/include/lock.h
sys/platform/pc64/include/md_var.h
sys/platform/pc64/include/metadata.h [copied from sys/platform/pc64/include/pcb_ext.h with 55% similarity]
sys/platform/pc64/include/nexusvar.h [copied from sys/platform/pc64/include/pcb_ext.h with 56% similarity]
sys/platform/pc64/include/param.h
sys/platform/pc64/include/pc/bios.h [new file with mode: 0644]
sys/platform/pc64/include/pc/display.h [new file with mode: 0644]
sys/platform/pc64/include/pcb.h
sys/platform/pc64/include/pcb_ext.h
sys/platform/pc64/include/pmap.h [copied from sys/cpu/amd64/include/pmap.h with 54% similarity]
sys/platform/pc64/include/thread.h
sys/platform/pc64/include/vmparam.h
sys/platform/pc64/isa/README.le [new file with mode: 0644]
sys/platform/pc64/isa/README.stl [new file with mode: 0644]
sys/platform/pc64/isa/asc.c [new file with mode: 0644]
sys/platform/pc64/isa/ascreg.h [new file with mode: 0644]
sys/platform/pc64/isa/clock.c [new file with mode: 0644]
sys/platform/pc64/isa/ic/Am7990.h [new file with mode: 0644]
sys/platform/pc64/isa/ic/am7990.h [new file with mode: 0644]
sys/platform/pc64/isa/ic/cd1400.h [new file with mode: 0644]
sys/platform/pc64/isa/ic/cd180.h [new file with mode: 0644]
sys/platform/pc64/isa/ic/hd64570.h [new file with mode: 0644]
sys/platform/pc64/isa/ic/i8237.h [new file with mode: 0644]
sys/platform/pc64/isa/ic/i82586.h [new file with mode: 0644]
sys/platform/pc64/isa/ic/lemac.h [new file with mode: 0644]
sys/platform/pc64/isa/ic/mb86960.h [new file with mode: 0644]
sys/platform/pc64/isa/ic/sc26198.h [new file with mode: 0644]
sys/platform/pc64/isa/ic/scd1400.h [new file with mode: 0644]
sys/platform/pc64/isa/intr_machdep.c [new file with mode: 0644]
sys/platform/pc64/isa/intr_machdep.h [new file with mode: 0644]
sys/platform/pc64/isa/lptreg.h [new file with mode: 0644]
sys/platform/pc64/isa/npx.c [copied from sys/platform/pc64/amd64/npx.c with 54% similarity]
sys/platform/pc64/isa/pmtimer.c [new file with mode: 0644]
sys/platform/pc64/isa/prof_machdep.c [new file with mode: 0644]
sys/platform/pc64/isa/timerreg.h [new file with mode: 0644]
sys/sys/tls.h

index 6d9f476..c5aa487 100644 (file)
@@ -1,5 +1,6 @@
-/*-
+/*
  * Copyright (c) 1993 The Regents of the University of California.
+ * Copyright (c) 2008 The DragonFly Project.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -27,7 +28,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/amd64/include/asmacros.h,v 1.32 2006/10/28 06:04:29 bde Exp $
- * $DragonFly: src/sys/cpu/amd64/include/asmacros.h,v 1.1 2007/09/23 04:29:30 yanyh Exp $
+ * $DragonFly: src/sys/cpu/amd64/include/asmacros.h,v 1.2 2008/08/29 17:07:06 dillon Exp $
  */
 
 #ifndef _CPU_ASMACROS_H_
  * Macros to create and destroy a trap frame.
  */
 #define PUSH_FRAME                                                     \
-       subq    $TF_RIP,%rsp ;  /* skip dummy tf_err and tf_trapno */   \
+       subq    $TF_RIP,%rsp ;  /* extend hardware frame to trapframe */ \
        testb   $SEL_RPL_MASK,TF_CS(%rsp) ; /* come from kernel? */     \
        jz      1f ;            /* Yes, dont swapgs again */            \
        swapgs ;                                                        \
index 33a6367..8e344c3 100644 (file)
@@ -1,5 +1,6 @@
 /*-
- * Copyright (c) 1998 Doug Rabson
+ * Copyright (c) 1998 Doug Rabson.
+ * Copyright (c) 2008 The DragonFly Project.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -24,7 +25,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/amd64/include/atomic.h,v 1.32 2003/11/21 03:02:00 peter Exp $
- * $DragonFly: src/sys/cpu/amd64/include/atomic.h,v 1.2 2007/09/23 04:29:30 yanyh Exp $
+ * $DragonFly: src/sys/cpu/amd64/include/atomic.h,v 1.3 2008/08/29 17:07:06 dillon Exp $
  */
 #ifndef _CPU_ATOMIC_H_
 #define _CPU_ATOMIC_H_
 #endif
 
 /*
- * Various simple arithmetic on memory which is atomic in the presence
- * of interrupts and multiple processors.
+ * Various simple operations on memory, each of which is atomic in the
+ * presence of interrupts and multiple processors.
  *
- * atomic_set_char(P, V)       (*(u_char*)(P) |= (V))
- * atomic_clear_char(P, V)     (*(u_char*)(P) &= ~(V))
- * atomic_add_char(P, V)       (*(u_char*)(P) += (V))
- * atomic_subtract_char(P, V)  (*(u_char*)(P) -= (V))
+ * atomic_set_char(P, V)       (*(u_char *)(P) |= (V))
+ * atomic_clear_char(P, V)     (*(u_char *)(P) &= ~(V))
+ * atomic_add_char(P, V)       (*(u_char *)(P) += (V))
+ * atomic_subtract_char(P, V)  (*(u_char *)(P) -= (V))
  *
- * atomic_set_short(P, V)      (*(u_short*)(P) |= (V))
- * atomic_clear_short(P, V)    (*(u_short*)(P) &= ~(V))
- * atomic_add_short(P, V)      (*(u_short*)(P) += (V))
- * atomic_subtract_short(P, V) (*(u_short*)(P) -= (V))
+ * atomic_set_short(P, V)      (*(u_short *)(P) |= (V))
+ * atomic_clear_short(P, V)    (*(u_short *)(P) &= ~(V))
+ * atomic_add_short(P, V)      (*(u_short *)(P) += (V))
+ * atomic_subtract_short(P, V) (*(u_short *)(P) -= (V))
  *
- * atomic_set_int(P, V)                (*(u_int*)(P) |= (V))
- * atomic_clear_int(P, V)      (*(u_int*)(P) &= ~(V))
- * atomic_add_int(P, V)                (*(u_int*)(P) += (V))
- * atomic_subtract_int(P, V)   (*(u_int*)(P) -= (V))
- * atomic_readandclear_int(P)  (return  *(u_int*)P; *(u_int*)P = 0;)
+ * atomic_set_int(P, V)                (*(u_int *)(P) |= (V))
+ * atomic_clear_int(P, V)      (*(u_int *)(P) &= ~(V))
+ * atomic_add_int(P, V)                (*(u_int *)(P) += (V))
+ * atomic_subtract_int(P, V)   (*(u_int *)(P) -= (V))
+ * atomic_readandclear_int(P)  (return (*(u_int *)(P)); *(u_int *)(P) = 0;)
  *
- * atomic_set_long(P, V)       (*(u_long*)(P) |= (V))
- * atomic_clear_long(P, V)     (*(u_long*)(P) &= ~(V))
- * atomic_add_long(P, V)       (*(u_long*)(P) += (V))
- * atomic_subtract_long(P, V)  (*(u_long*)(P) -= (V))
- * atomic_readandclear_long(P) (return  *(u_long*)P; *(u_long*)P = 0;)
+ * atomic_set_long(P, V)       (*(u_long *)(P) |= (V))
+ * atomic_clear_long(P, V)     (*(u_long *)(P) &= ~(V))
+ * atomic_add_long(P, V)       (*(u_long *)(P) += (V))
+ * atomic_subtract_long(P, V)  (*(u_long *)(P) -= (V))
+ * atomic_readandclear_long(P) (return (*(u_long *)(P)); *(u_long *)(P) = 0;)
  */
 
 /*
  * This allows kernel modules to be portable between UP and SMP systems.
  */
 #if defined(KLD_MODULE)
-#define ATOMIC_ASM(NAME, TYPE, OP, CONS, V)                    \
+#define        ATOMIC_ASM(NAME, TYPE, OP, CONS, V)                     \
 void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v); \
 void atomic_##NAME##_##TYPE##_nonlocked(volatile u_##TYPE *p, u_##TYPE v);
 
-int atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src);
-int atomic_cmpset_long(volatile u_long *dst, u_long exp, u_long src);
+int    atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src);
+int    atomic_cmpset_long(volatile u_long *dst, u_long exp, u_long src);
+u_int  atomic_fetchadd_int(volatile u_int *p, u_int v);
+u_long atomic_fetchadd_long(volatile u_long *p, u_long v);
 
 #define        ATOMIC_STORE_LOAD(TYPE, LOP, SOP)                       \
 u_##TYPE       atomic_load_acq_##TYPE(volatile u_##TYPE *p);   \
@@ -85,20 +88,20 @@ void                atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)
 #ifdef __GNUC__
 
 /*
- * For userland, assume the SMP case and use lock prefixes so that
- * the binaries will run on both types of systems.
+ * For userland, always use lock prefixes so that the binaries will run
+ * on both SMP and !SMP systems.
  */
 #if defined(SMP) || !defined(_KERNEL)
-#define MPLOCKED       "lock ; "
+#define        MPLOCKED        "lock ; "
 #else
-#define MPLOCKED
+#define        MPLOCKED
 #endif
 
 /*
  * The assembly is volatilized to demark potential before-and-after side
  * effects if an interrupt or SMP collision were to occur.
  */
-#define ATOMIC_ASM(NAME, TYPE, OP, CONS, V)            \
+#define        ATOMIC_ASM(NAME, TYPE, OP, CONS, V)             \
 static __inline void                                   \
 atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
 {                                                      \
@@ -244,6 +247,43 @@ atomic_intr_cond_enter(atomic_intr_t *p, void (*func)(void *), void *arg)
                         : "ax", "cx", "dx", "di");     /* XXX clobbers more regs */
 }
 
+/*
+ * Atomically add the value of v to the integer pointed to by p and return
+ * the previous value of *p.
+ */
+static __inline u_int
+atomic_fetchadd_int(volatile u_int *p, u_int v)
+{
+
+       __asm __volatile(
+       "       " MPLOCKED "            "
+       "       xaddl   %0, %1 ;        "
+       "# atomic_fetchadd_int"
+       : "+r" (v),                     /* 0 (result) */
+         "=m" (*p)                     /* 1 */
+       : "m" (*p));                    /* 2 */
+
+       return (v);
+}
+
+/*
+ * Atomically add the value of v to the long integer pointed to by p and return
+ * the previous value of *p.
+ */
+static __inline u_long
+atomic_fetchadd_long(volatile u_long *p, u_long v)
+{
+
+       __asm __volatile(
+       "       " MPLOCKED "            "
+       "       xaddq   %0, %1 ;        "
+       "# atomic_fetchadd_long"
+       : "+r" (v),                     /* 0 (result) */
+         "=m" (*p)                     /* 1 */
+       : "m" (*p));                    /* 2 */
+
+       return (v);
+}
 /*
  * Attempt to enter the interrupt condition variable.  Returns zero on
  * success, 1 on failure.
@@ -343,7 +383,7 @@ atomic_cmpset_long(volatile u_long *dst, u_long exp, u_long src)
 
 #if defined(__GNUC__)
 
-#define ATOMIC_STORE_LOAD(TYPE, LOP, SOP)              \
+#define        ATOMIC_STORE_LOAD(TYPE, LOP, SOP)               \
 static __inline u_##TYPE                               \
 atomic_load_acq_##TYPE(volatile u_##TYPE *p)           \
 {                                                      \
@@ -410,8 +450,6 @@ ATOMIC_STORE_LOAD(long,     "cmpxchgq %0,%1",  "xchgq %1,%0");
 
 #define        atomic_cmpset_32        atomic_cmpset_int
 
-#if 0
-
 #undef ATOMIC_ASM
 #undef ATOMIC_STORE_LOAD
 
@@ -441,8 +479,8 @@ ATOMIC_STORE_LOAD(long,     "cmpxchgq %0,%1",  "xchgq %1,%0");
 #define        atomic_add_rel_int              atomic_add_int
 #define        atomic_subtract_acq_int         atomic_subtract_int
 #define        atomic_subtract_rel_int         atomic_subtract_int
-#define atomic_cmpset_acq_int          atomic_cmpset_int
-#define atomic_cmpset_rel_int          atomic_cmpset_int
+#define        atomic_cmpset_acq_int           atomic_cmpset_int
+#define        atomic_cmpset_rel_int           atomic_cmpset_int
 
 #define        atomic_set_acq_long             atomic_set_long
 #define        atomic_set_rel_long             atomic_set_long
@@ -453,9 +491,6 @@ ATOMIC_STORE_LOAD(long,     "cmpxchgq %0,%1",  "xchgq %1,%0");
 #define        atomic_subtract_acq_long        atomic_subtract_long
 #define        atomic_subtract_rel_long        atomic_subtract_long
 
-#define atomic_cmpset_acq_ptr          atomic_cmpset_ptr
-#define atomic_cmpset_rel_ptr          atomic_cmpset_ptr
-
 #define        atomic_set_8            atomic_set_char
 #define        atomic_set_acq_8        atomic_set_acq_char
 #define        atomic_set_rel_8        atomic_set_rel_char
@@ -471,6 +506,7 @@ ATOMIC_STORE_LOAD(long,     "cmpxchgq %0,%1",  "xchgq %1,%0");
 #define        atomic_load_acq_8       atomic_load_acq_char
 #define        atomic_store_rel_8      atomic_store_rel_char
 
+/* Operations on 16-bit words. */
 #define        atomic_set_16           atomic_set_short
 #define        atomic_set_acq_16       atomic_set_acq_short
 #define        atomic_set_rel_16       atomic_set_rel_short
@@ -486,6 +522,7 @@ ATOMIC_STORE_LOAD(long,     "cmpxchgq %0,%1",  "xchgq %1,%0");
 #define        atomic_load_acq_16      atomic_load_acq_short
 #define        atomic_store_rel_16     atomic_store_rel_short
 
+/* Operations on 32-bit double words. */
 #define        atomic_set_32           atomic_set_int
 #define        atomic_set_acq_32       atomic_set_acq_int
 #define        atomic_set_rel_32       atomic_set_rel_int
@@ -500,63 +537,38 @@ ATOMIC_STORE_LOAD(long,   "cmpxchgq %0,%1",  "xchgq %1,%0");
 #define        atomic_subtract_rel_32  atomic_subtract_rel_int
 #define        atomic_load_acq_32      atomic_load_acq_int
 #define        atomic_store_rel_32     atomic_store_rel_int
+#define        atomic_cmpset_32        atomic_cmpset_int
 #define        atomic_cmpset_acq_32    atomic_cmpset_acq_int
 #define        atomic_cmpset_rel_32    atomic_cmpset_rel_int
 #define        atomic_readandclear_32  atomic_readandclear_int
-
-#if !defined(WANT_FUNCTIONS)
-static __inline int
-atomic_cmpset_ptr(volatile void *dst, void *exp, void *src)
-{
-
-       return (atomic_cmpset_long((volatile u_long *)dst,
-           (u_long)exp, (u_long)src));
-}
-
-static __inline void *
-atomic_load_acq_ptr(volatile void *p)
-{
-       /*
-        * The apparently-bogus cast to intptr_t in the following is to
-        * avoid a warning from "gcc -Wbad-function-cast".
-        */
-       return ((void *)(intptr_t)atomic_load_acq_long((volatile u_long *)p));
-}
-
-static __inline void
-atomic_store_rel_ptr(volatile void *p, void *v)
-{
-       atomic_store_rel_long((volatile u_long *)p, (u_long)v);
-}
-
-#define ATOMIC_PTR(NAME)                               \
-static __inline void                                   \
-atomic_##NAME##_ptr(volatile void *p, uintptr_t v)     \
-{                                                      \
-       atomic_##NAME##_long((volatile u_long *)p, v);  \
-}                                                      \
-                                                       \
-static __inline void                                   \
-atomic_##NAME##_acq_ptr(volatile void *p, uintptr_t v) \
-{                                                      \
-       atomic_##NAME##_acq_long((volatile u_long *)p, v);\
-}                                                      \
-                                                       \
-static __inline void                                   \
-atomic_##NAME##_rel_ptr(volatile void *p, uintptr_t v) \
-{                                                      \
-       atomic_##NAME##_rel_long((volatile u_long *)p, v);\
-}
-
-ATOMIC_PTR(set)
-ATOMIC_PTR(clear)
-ATOMIC_PTR(add)
-ATOMIC_PTR(subtract)
-
-#undef ATOMIC_PTR
+#define        atomic_fetchadd_32      atomic_fetchadd_int
+
+/* Operations on pointers. */
+#define        atomic_set_ptr          atomic_set_long
+#define        atomic_set_acq_ptr      atomic_set_acq_long
+#define        atomic_set_rel_ptr      atomic_set_rel_long
+#define        atomic_clear_ptr        atomic_clear_long
+#define        atomic_clear_acq_ptr    atomic_clear_acq_long
+#define        atomic_clear_rel_ptr    atomic_clear_rel_long
+#define        atomic_add_ptr          atomic_add_long
+#define        atomic_add_acq_ptr      atomic_add_acq_long
+#define        atomic_add_rel_ptr      atomic_add_rel_long
+#define        atomic_subtract_ptr     atomic_subtract_long
+#define        atomic_subtract_acq_ptr atomic_subtract_acq_long
+#define        atomic_subtract_rel_ptr atomic_subtract_rel_long
+#define        atomic_load_acq_ptr     atomic_load_acq_long
+#define        atomic_store_rel_ptr    atomic_store_rel_long
+#define        atomic_cmpset_ptr       atomic_cmpset_long
+#define        atomic_cmpset_acq_ptr   atomic_cmpset_acq_long
+#define        atomic_cmpset_rel_ptr   atomic_cmpset_rel_long
+#define        atomic_readandclear_ptr atomic_readandclear_long
 
 #if defined(__GNUC__)
 
+#if defined(KLD_MODULE)
+extern u_int atomic_readandclear_int(volatile u_int *addr);
+extern u_long atomic_readandclear_long(volatile u_long *addr);
+#else /* !KLD_MODULE */
 static __inline u_int
 atomic_readandclear_int(volatile u_int *addr)
 {
@@ -586,6 +598,7 @@ atomic_readandclear_long(volatile u_long *addr)
 
        return (result);
 }
+#endif /* KLD_MODULE */
 
 #else /* !defined(__GNUC__) */
 
@@ -594,7 +607,4 @@ extern u_int        atomic_readandclear_int(volatile u_int *);
 
 #endif /* defined(__GNUC__) */
 
-#endif /* !defined(WANT_FUNCTIONS) */
-#endif /* 0 */
-
 #endif /* ! _CPU_ATOMIC_H_ */
index a0d21f8..6359332 100644 (file)
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 2003 Peter Wemm.
  * Copyright (c) 1993 The Regents of the University of California.
+ * Copyright (c) 2008 The DragonFly Project.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -32,7 +33,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/amd64/include/cpufunc.h,v 1.139 2004/01/28 23:53:04 peter Exp $
- * $DragonFly: src/sys/cpu/amd64/include/cpufunc.h,v 1.2 2007/09/23 04:29:30 yanyh Exp $
+ * $DragonFly: src/sys/cpu/amd64/include/cpufunc.h,v 1.3 2008/08/29 17:07:06 dillon Exp $
  */
 
 /*
@@ -112,7 +113,7 @@ bsrq(u_long mask)
 }
 
 static __inline void
-disable_intr(void)
+cpu_disable_intr(void)
 {
        __asm __volatile("cli" : : : "memory");
 }
@@ -125,6 +126,14 @@ do_cpuid(u_int ax, u_int *p)
                         :  "0" (ax));
 }
 
+static __inline void
+cpuid_count(u_int ax, u_int cx, u_int *p)
+{
+       __asm __volatile("cpuid"
+                        : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
+                        :  "0" (ax), "c" (cx));
+}
+
 static __inline void
 cpu_enable_intr(void)
 {
@@ -345,6 +354,34 @@ invd(void)
        __asm __volatile("invd");
 }
 
+#if defined(_KERNEL)
+
+/*
+ * If we are not a true-SMP box then smp_invltlb() is a NOP.  Note that this
+ * will cause the invl*() functions to be equivalent to the cpu_invl*()
+ * functions.
+ */
+#ifdef SMP
+void smp_invltlb(void);
+#else
+#define smp_invltlb()
+#endif
+
+#ifndef _CPU_INVLPG_DEFINED
+
+/*
+ * Invalidate a patricular VA on this cpu only
+ */
+static __inline void
+cpu_invlpg(void *addr)
+{
+       __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
+}
+
+#endif
+
+#endif /* _KERNEL */
+
 static __inline u_short
 inw(u_int port)
 {
@@ -543,7 +580,7 @@ rcr4(void)
  * Global TLB flush (except for thise for pages marked PG_G)
  */
 static __inline void
-invltlb(void)
+cpu_invltlb(void)
 {
 
        load_cr3(rcr3());
@@ -618,7 +655,7 @@ load_gs(u_int sel)
         * being trashed happens to be the kernel gsbase at the time.
         */
        gsbase = MSR_GSBASE;
-        __asm __volatile("pushfq; cli; rdmsr; movl %0,%%gs; wrmsr; popfq"
+        __asm __volatile("pushfq; cli; rdmsr; movw %0,%%gs; wrmsr; popfq"
             : : "rm" (sel), "c" (gsbase) : "eax", "edx");
 }
 #else
@@ -775,7 +812,7 @@ intr_disable(void)
        register_t rflags;
 
        rflags = read_rflags();
-       disable_intr();
+       cpu_disable_intr();
        return (rflags);
 }
 
@@ -791,11 +828,11 @@ int       breakpoint(void);
 void   cpu_pause(void);
 u_int  bsfl(u_int mask);
 u_int  bsrl(u_int mask);
+void   cpu_disable_intr(void);
+void   cpu_enable_intr(void);
 void   cpu_invlpg(u_long addr);
 void   cpu_invlpg_range(u_long start, u_long end);
-void   disable_intr(void);
 void   do_cpuid(u_int ax, u_int *p);
-void   enable_intr(void);
 void   halt(void);
 u_char inb(u_int port);
 u_int  inl(u_int port);
@@ -805,7 +842,7 @@ void        insw(u_int port, void *addr, size_t cnt);
 void   invd(void);
 void   invlpg(u_int addr);
 void   invlpg_range(u_int start, u_int end);
-void   invltlb(void);
+void   cpu_invltlb(void);
 u_short        inw(u_int port);
 void   load_cr0(u_int cr0);
 void   load_cr3(u_int cr3);
index 825e68a..ee389dd 100644 (file)
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 2003 Peter Wemm.
  * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 2008 The DragonFly Project.
  * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  *
  *     from: @(#)frame.h       5.2 (Berkeley) 1/18/91
  * $FreeBSD: src/sys/amd64/include/frame.h,v 1.26 2003/11/08 04:39:22 peter Exp $
- * $DragonFly: src/sys/cpu/amd64/include/frame.h,v 1.2 2007/09/23 04:29:30 yanyh Exp $
+ * $DragonFly: src/sys/cpu/amd64/include/frame.h,v 1.3 2008/08/29 17:07:06 dillon Exp $
  */
 
 #ifndef _CPU_FRAME_H_
 #define _CPU_FRAME_H_
 
+/* JG? */
+#include <sys/types.h>
+
 /*
  * System stack frames.
  */
@@ -88,7 +92,6 @@ struct trapframe {
 
 struct intrframe {
        register_t      if_vec; /* vec */
-       /* ppl */
        /* fs XXX */
        /* es XXX */
        /* ds XXX */
index d698eb9..4d74a9c 100644 (file)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 2008 The DragonFly Project.
  * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
@@ -35,7 +36,7 @@
  *
  *     from: @(#)npx.h 5.3 (Berkeley) 1/18/91
  * $FreeBSD: src/sys/i386/include/npx.h,v 1.18.2.1 2001/08/15 01:23:52 peter Exp $
- * $DragonFly: src/sys/cpu/amd64/include/npx.h,v 1.2 2007/09/23 04:29:30 yanyh Exp $
+ * $DragonFly: src/sys/cpu/amd64/include/npx.h,v 1.3 2008/08/29 17:07:06 dillon Exp $
  */
 
 /*
@@ -156,7 +157,7 @@ struct trapframe;
 void   npxexit (void);
 void   npxinit (u_short control);
 void   npxsave (union savefpu *addr);
-int    npxdna(struct trapframe *);
+int    npxdna(void);
 #endif
 
 #endif /* !_CPU_NPX_H_ */
index ee4da86..a640d84 100644 (file)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 2008 The DragonFly Project.
  * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
@@ -35,7 +36,7 @@
  *
  *     from: @(#)param.h       5.8 (Berkeley) 6/28/91
  * $FreeBSD: src/sys/i386/include/param.h,v 1.54.2.8 2002/08/31 21:15:55 dillon Exp $
- * $DragonFly: src/sys/cpu/amd64/include/param.h,v 1.3 2007/09/23 04:29:30 yanyh Exp $
+ * $DragonFly: src/sys/cpu/amd64/include/param.h,v 1.4 2008/08/29 17:07:06 dillon Exp $
  */
 
 #ifndef _CPU_PARAM_H_
 #define ALIGNBYTES     _ALIGNBYTES
 #define ALIGN(p)       _ALIGN(p)
 
+/* JG license? from fbsd/src/sys/amd64/include/param.h */
 /* level 1 == page table */
+#define        NPTEPGSHIFT     9               /* LOG2(NPTEPG) */
 #define PAGE_SHIFT     12              /* LOG2(PAGE_SIZE) */
 #define PAGE_SIZE      (1<<PAGE_SHIFT) /* bytes/page */
 #define PAGE_MASK      (PAGE_SIZE-1)
 #define NPTEPG         (PAGE_SIZE/(sizeof (pt_entry_t)))
 
 /* level 2 == page directory */
+#define        NPDEPGSHIFT     9               /* LOG2(NPDEPG) */
 #define PDRSHIFT       21              /* LOG2(NBPDR) */
 #define NBPDR          (1<<PDRSHIFT)   /* bytes/page dir */
 #define PDRMASK                (NBPDR-1)
 #define NPDEPG         (PAGE_SIZE/(sizeof (pd_entry_t)))
 
 /* level 3 == page directory pointer table */
+#define        NPDPEPGSHIFT    9               /* LOG2(NPDPEPG) */
 #define PDPSHIFT       30              /* LOG2(NBPDP) */
 #define NBPDP          (1<<PDPSHIFT)   /* bytes/page dir ptr table */
 #define PDPMASK                (NBPDP-1)
 #define NPDPEPG                (PAGE_SIZE/(sizeof (pdp_entry_t)))
 
 /* level 4 */
+#define        NPML4EPGSHIFT   9               /* LOG2(NPML4EPG) */
 #define PML4SHIFT      39              /* LOG2(NPML4) */
 #define NPML4          (1UL<<PML4SHIFT)/* bytes/page map level4 table */
+#define        NBPML4          (1ul<<PML4SHIFT)/* bytes/page map lev4 table */
 #define PML4MASK       (NPML4-1)
 #define NPML4EPG       (PAGE_SIZE/(sizeof (pml4_entry_t)))
 
  * of the hardware page size.
  */
 #ifndef        MSIZE
-#define MSIZE          256             /* size of an mbuf */
+#define MSIZE          512             /* size of an mbuf */
 #endif /* MSIZE */
 
 #ifndef        MCLSHIFT
 /*
  * Mach derived conversion macros
  */
-#define trunc_page(x)          ((x) & ~PAGE_MASK)
-#define round_page(x)          (((x) + PAGE_MASK) & ~PAGE_MASK)
-#define trunc_4mpage(x)                ((x) & ~PDRMASK)
-#define round_4mpage(x)                ((((x)) + PDRMASK) & ~PDRMASK)
+#define        round_page(x)   ((((unsigned long)(x)) + PAGE_MASK) & ~(PAGE_MASK))
+#define        trunc_page(x)   ((unsigned long)(x) & ~(PAGE_MASK))
+#define trunc_2mpage(x)        ((unsigned long)(x) & ~PDRMASK)
+#define round_2mpage(x)        ((((unsigned long)(x)) + PDRMASK) & ~PDRMASK)
 
 #if defined(_KERNEL) || defined(_KERNEL_STRUCTURES)
-#define atop(x)                        ((x) >> PAGE_SHIFT)
+#define        atop(x)         ((vm_pindex_t)((x) >> PAGE_SHIFT))
 #endif
-#define ptoa(x)                        ((x) << PAGE_SHIFT)
+#define        ptoa(x)         ((vm_paddr_t)(x) << PAGE_SHIFT)
 
-#define i386_btop(x)           ((x) >> PAGE_SHIFT)
-#define i386_ptob(x)           ((x) << PAGE_SHIFT)
+#define        amd64_btop(x)   ((vm_pindex_t)((x) >> PAGE_SHIFT))
+#define        amd64_ptob(x)   ((vm_paddr_t)(x) << PAGE_SHIFT)
 
 #define        pgtok(x)                ((x) * (PAGE_SIZE / 1024))
 
index 5946d82..cbed116 100644 (file)
@@ -1,7 +1,13 @@
-/*
- * Copyright (c) 2003 Matthew Dillon <dillon@backplane.com>
+/*-
+ * Copyright (c) 1991 Regents of the University of California.
+ * Copyright (c) 2003 Peter Wemm.
+ * Copyright (c) 2008 The DragonFly Project.
  * All rights reserved.
  *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department and William Jolitz of UUNET Technologies Inc.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/cpu/amd64/include/pmap.h,v 1.2 2007/09/23 04:29:30 yanyh Exp $
+ * Derived from hp300 version by Mike Hibler, this version by William
+ * Jolitz uses a recursive map [a pde points to the page directory] to
+ * map the page tables using the pagetables themselves. This is done to
+ * reduce the impact on kernel virtual memory for lots of sparse address
+ * space, and to reduce the cost of memory to each process.
+ *
+ * from: hp300: @(#)pmap.h     7.2 (Berkeley) 12/16/90
+ * from: @(#)pmap.h    7.4 (Berkeley) 5/12/91
+ * $FreeBSD$
+ * $DragonFly: src/sys/cpu/amd64/include/pmap.h,v 1.3 2008/08/29 17:07:06 dillon Exp $
  */
+
 #ifndef _CPU_PMAP_H_
-#define        _CPU_PMAP_H_
+#define _CPU_PMAP_H_
 
 /*
- * A four level page table is implemented by the amd64 hardware.  Each
- * page table represents 9 address bits and eats 4KB of space.  There are
- * 512 8-byte entries in each table.  The last page table contains PTE's
- * representing 4K pages (12 bits of address space).
- *
- * The page tables are named:
- *     PML4    Represents 512GB per entry (256TB total)        LEVEL4
- *     PDP     Represents 1GB per entry                        LEVEL3
- *     PDE     Represents 2MB per entry                        LEVEL2
- *     PTE     Represents 4KB per entry                        LEVEL1
- *
- * PG_PAE      PAE 2MB extension.  In the PDE.  If 0 there is another level
- *             of page table and PG_D and PG_G are ignored.  If 1 this is
- *             the terminating page table and PG_D and PG_G apply.
- *
- * PG_PWT      Page write through.  If 1 caching is disabled for data
- *             represented by the page.
- * PG_PCD      Page Cache Disable.  If 1 the page table entry will not
- *             be cached in the data cache.
- *
- * Each entry in the PML4 table represents a 512GB VA space.  We use a fixed
- * PML4 and adjust entries within it to switch user spaces.
+ * Page-directory and page-table entries follow this format, with a few
+ * of the fields not present here and there, depending on a lot of things.
  */
-
-#define PG_V           0x0001LL                /* P    Present         */
-#define PG_RW          0x0002LL                /* R/W  Writable        */
-#define PG_U           0x0004LL                /* U/S  User            */
-#define PG_PWT         0x0008LL                /* PWT  Page Write Through */
-#define PG_PCD         0x0010LL                /* PCD  Page Cache Disable */
-#define PG_A           0x0020LL                /* A    Accessed        */
-#define PG_D           0x0040LL                /* D    Dirty   (pte only) */
-#define PG_PS          0x0080LL                /* PAT          (pte only) */
-#define PG_G           0x0100LL                /* G    Global  (pte only) */
-#define PG_USR0                0x0200LL                /* available to os */
-#define PG_USR1                0x0400LL                /* available to os */
-#define PG_USR2                0x0800LL                /* available to os */
-#define PG_PTE_PAT     PG_PAE                  /* PAT bit for 4K pages */
-#define PG_PDE_PAT     0x1000LL                /* PAT bit for 2M pages */
-#define PG_FRAME       0x000000FFFFFF0000LL    /* 40 bit phys address */
-#define PG_PHYSRESERVED        0x000FFF0000000000LL    /* reserved for future PA */
-#define PG_USR3                0x0010000000000000LL    /* avilable to os */
+                               /* ---- Intel Nomenclature ---- */
+#define        PG_V            0x001   /* P    Valid                   */
+#define PG_RW          0x002   /* R/W  Read/Write              */
+#define PG_U           0x004   /* U/S  User/Supervisor         */
+#define        PG_NC_PWT       0x008   /* PWT  Write through           */
+#define        PG_NC_PCD       0x010   /* PCD  Cache disable           */
+#define PG_A           0x020   /* A    Accessed                */
+#define        PG_M            0x040   /* D    Dirty                   */
+#define        PG_PS           0x080   /* PS   Page size (0=4k,1=2M)   */
+#define        PG_PTE_PAT      0x080   /* PAT  PAT index               */
+#define        PG_G            0x100   /* G    Global                  */
+#define        PG_AVAIL1       0x200   /*    / Available for system    */
+#define        PG_AVAIL2       0x400   /*   <  programmers use         */
+#define        PG_AVAIL3       0x800   /*    \                         */
+#define        PG_PDE_PAT      0x1000  /* PAT  PAT index               */
+#define        PG_NX           (1ul<<63) /* No-execute */
+
+
+/* Our various interpretations of the above */
+#define PG_W           PG_AVAIL1       /* "Wired" pseudoflag */
+#define        PG_MANAGED      PG_AVAIL2
+#define        PG_FRAME        (0x000ffffffffff000ul)
+#define        PG_PS_FRAME     (0x000fffffffe00000ul)
+#define        PG_PROT         (PG_RW|PG_U)    /* all protection bits . */
+#define PG_N           (PG_NC_PWT|PG_NC_PCD)   /* Non-cacheable */
 
 /*
- * OS assignments
+ * Promotion to a 2MB (PDE) page mapping requires that the corresponding 4KB
+ * (PTE) page mappings have identical settings for the following fields:
  */
-#define PG_W           PG_USR0                 /* Wired        */
-#define        PG_MANAGED      PG_USR1                 /* Managed      */
-#define        PG_PROT         (PG_RW|PG_U)            /* all protection bits . */
-#define PG_N           (PG_PWT|PG_PCD)         /* Non-cacheable */
+#define        PG_PTE_PROMOTE  (PG_NX | PG_MANAGED | PG_W | PG_G | PG_PTE_PAT | \
+           PG_M | PG_A | PG_NC_PCD | PG_NC_PWT | PG_U | PG_RW | PG_V)
 
 /*
  * Page Protection Exception bits
 #define PGEX_P         0x01    /* Protection violation vs. not present */
 #define PGEX_W         0x02    /* during a Write cycle */
 #define PGEX_U         0x04    /* access from User mode (UPL) */
-
-#define PGEX_MAILBOX   0x40
-#define PGEX_FPFAULT   0x80
-
-/*
- * User space is limited to one PML4 entry (512GB).  Kernel space is also
- * limited to one PML4 entry.  Other PML4 entries are used to map foreign
- * user spaces into KVM.  Typically each cpu in the system reserves two
- * PML4 entries for private use.
- */
-#define UVA_MAXMEM     (512LL*1024*1024*1024)
-#define KVA_MAXMEM     (512LL*1024*1024*1024)
-
-/*
- * Pte related macros.  This is complicated by having to deal with
- * the sign extension of the 48th bit.
- */
-#define KVADDR(l4, l3, l2, l1) ( \
-       ((unsigned long)-1 << 47) | \
-       ((unsigned long)(l4) << PML4SHIFT) | \
-       ((unsigned long)(l3) << PDPSHIFT) | \
-       ((unsigned long)(l2) << PDRSHIFT) | \
-       ((unsigned long)(l1) << PAGE_SHIFT))
-
-#define UVADDR(l4, l3, l2, l1) ( \
-       ((unsigned long)(l4) << PML4SHIFT) | \
-       ((unsigned long)(l3) << PDPSHIFT) | \
-       ((unsigned long)(l2) << PDRSHIFT) | \
-       ((unsigned long)(l1) << PAGE_SHIFT))
-
-
-#define NKPML4E                1
-#define NKPDPE         1
-#define NKPDE          (NKPDPE*NPDEPG)
-
-#define NUPML4E                (NPML4EPG/2)
-#define NUPDPE         (NUPML4E*NPDPEPG)
-#define NUPDE          (NUPDPE*NPDEPG)
-
-
-/*
- * The *PTDI values control the layout of virtual memory
- *
- * XXX This works for now, but I am not real happy with it, I'll fix it
- * right after I fix locore.s and the magic 28K hole
- *
- * SMP_PRIVPAGES: The per-cpu address space is 0xff80000 -> 0xffbfffff
- */
-#define        APTDPTDI        (NPDEPG-1)      /* alt ptd entry that points to APTD */
-#define MPPTDI         (APTDPTDI-1)    /* per cpu ptd entry */
-#define        KPTDI           (MPPTDI-NKPDE)  /* start of kernel virtual pde's */
-#define        PTDPTDI         (KPTDI-1)       /* ptd entry that points to ptd! */
-#define        UMAXPTDI        (PTDPTDI-1)     /* ptd entry for user space end */
-#define        UMAXPTEOFF      (NPTEPG)        /* pte entry for user space end */
-
-#define KPML4I         (NPML4EPG-1)
-
-#define KPDPI          (NPDPEPG-2)
-
-/*
- * XXX doesn't really belong here I guess...
- */
-#define ISA_HOLE_START    0xa0000
-#define ISA_HOLE_LENGTH (0x100000-ISA_HOLE_START)
-
-#ifndef LOCORE
-
-#include <sys/queue.h>
-
-/*
- * Address of current and alternate address space page table maps
- * and directories.
- */
-#ifdef _KERNEL
-extern pt_entry_t PTmap[], APTmap[], Upte;
-extern pd_entry_t PTD[], APTD[], PTDpde, APTDpde, Upde;
-
-extern pd_entry_t IdlePTD;     /* physical address of "Idle" state directory */
-#endif
-
-#ifdef _KERNEL
-/*
- * virtual address to page table entry and
- * to physical address. Likewise for alternate address space.
- * Note: these work recursively, thus vtopte of a pte will give
- * the corresponding pde that in turn maps it.
- */
-#define        vtopte(va)      (PTmap + i386_btop(va))
-
-#define        avtopte(va)     (APTmap + i386_btop(va))
-
-/*
- *     Routine:        pmap_kextract
- *     Function:
- *             Extract the physical page address associated
- *             kernel virtual address.
- */
-static __inline vm_paddr_t
-pmap_kextract(vm_offset_t va)
-{
-       vm_paddr_t pa;
-
-       if ((pa = (vm_offset_t) PTD[va >> PDRSHIFT]) & PG_PS) {
-               pa = (pa & ~(NBPDR - 1)) | (va & (NBPDR - 1));
-       } else {
-               pa = *(vm_offset_t *)vtopte(va);
-               pa = (pa & PG_FRAME) | (va & PAGE_MASK);
-       }
-       return pa;
-}
-
-/*
- * XXX
- */
-#define        vtophys(va)     pmap_kextract(((vm_offset_t)(va)))
-#define        vtophys_pte(va) ((pt_entry_t)pmap_kextract(((vm_offset_t)(va))))
-
-#define        avtophys(va)    (((vm_offset_t) (*avtopte(va))&PG_FRAME) | ((vm_offset_t)(va) & PAGE_MASK))
-
-#endif
-
-/*
- * Pmap stuff
- */
-struct pv_entry;
-
-struct md_page {
-       int pv_list_count;
-       TAILQ_HEAD(,pv_entry)   pv_list;
-};
-
-/*
- * Each machine dependent implementation is expected to
- * keep certain statistics.  They may do this anyway they
- * so choose, but are expected to return the statistics
- * in the following structure.
- */
-struct pmap_statistics {
-       long resident_count;    /* # of pages mapped (total) */
-       long wired_count;       /* # of pages wired */
-};
-typedef struct pmap_statistics *pmap_statistics_t;
-
-struct vm_object;
-struct vm_page;
-
-struct pmap {
-       pd_entry_t              *pm_pdir;       /* KVA of page directory */
-       struct vm_object        *pm_pteobj;     /* Container for pte's */
-       TAILQ_HEAD(,pv_entry)   pm_pvlist;      /* list of mappings in pmap */
-       int                     pm_count;       /* reference count */
-       cpumask_t               pm_active;      /* active on cpus */
-       struct pmap_statistics  pm_stats;       /* pmap statistics */
-       struct  vm_page         *pm_ptphint;    /* pmap ptp hint */
-};
-
-#define pmap_resident_count(pmap) (pmap)->pm_stats.resident_count
-
-typedef struct pmap    *pmap_t;
-
-#ifdef _KERNEL
-extern struct pmap             kernel_pmap;
-#endif
-
-/*
- * For each vm_page_t, there is a list of all currently valid virtual
- * mappings of that page.  An entry is a pv_entry_t, the list is pv_list
- */
-typedef struct pv_entry {
-       pmap_t          pv_pmap;        /* pmap where mapping lies */
-       vm_offset_t     pv_va;          /* virtual address for mapping */
-       TAILQ_ENTRY(pv_entry)   pv_list;
-       TAILQ_ENTRY(pv_entry)   pv_plist;
-       struct vm_page  *pv_ptem;       /* VM page for pte */
-} *pv_entry_t;
-
-#ifdef _KERNEL
-
-#define NPPROVMTRR             8
-#define PPRO_VMTRRphysBase0    0x200
-#define PPRO_VMTRRphysMask0    0x201
-struct ppro_vmtrr {
-       u_int64_t base, mask;
-};
-extern struct ppro_vmtrr PPro_vmtrr[NPPROVMTRR];
-
-extern caddr_t CADDR1;
-extern pt_entry_t *CMAP1;
-extern vm_paddr_t avail_end;
-extern vm_paddr_t avail_start;
-extern vm_offset_t clean_eva;
-extern vm_offset_t clean_sva;
-extern char *ptvmmap;          /* poor name! */
-extern vm_offset_t virtual_avail;
-
-void   pmap_bootstrap ( vm_paddr_t, vm_paddr_t);
-pmap_t pmap_kernel (void);
-void   *pmap_mapdev (vm_paddr_t, vm_size_t);
-void   pmap_unmapdev (vm_offset_t, vm_size_t);
-unsigned *pmap_pte (pmap_t, vm_offset_t) __pure2;
-struct vm_page *pmap_use_pt (pmap_t, vm_offset_t);
-#ifdef SMP
-void   pmap_set_opt (void);
-#endif
-
-#endif /* _KERNEL */
-
-#endif /* !LOCORE */
+#define PGEX_RSV       0x08    /* reserved PTE field is non-zero */
+#define PGEX_I         0x10    /* during an instruction fetch */
 
 #endif /* !_CPU_PMAP_H_ */
index c1cdfc8..86eae43 100644 (file)
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 1989, 1990 William F. Jolitz
  * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 2008 The DragonFly Project.
  * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  *
  *     from: @(#)segments.h    7.1 (Berkeley) 5/9/91
  * $FreeBSD: src/sys/i386/include/segments.h,v 1.24 1999/12/29 04:33:07 peter Exp $
- * $DragonFly: src/sys/cpu/amd64/include/segments.h,v 1.2 2007/09/23 04:29:30 yanyh Exp $
+ * $DragonFly: src/sys/cpu/amd64/include/segments.h,v 1.3 2008/08/29 17:07:06 dillon Exp $
  */
 
 #ifndef _CPU_SEGMENTS_H_
 #define        _CPU_SEGMENTS_H_
 
 /*
- * 386 Segmentation Data Structures and definitions
- *     William F. Jolitz (william@ernie.berkeley.edu) 6/20/1989
+ * AMD64 Segmentation Data Structures and definitions
  */
 
 /*
  * Selectors
  */
 
-#define        ISPL(s) ((s)&3)         /* what is the priority level of a selector */
-#define        SEL_KPL 0               /* kernel priority level */
-#define        SEL_UPL 3               /* user priority level */
+#define        SEL_RPL_MASK    3       /* requester priv level */
+#define        ISPL(s) ((s)&3)         /* what is the privilege level of a selector */
+#define        SEL_KPL 0               /* kernel privilege level */
+#define        SEL_UPL 3               /* user privilege level */
 #define        ISLDT(s)        ((s)&SEL_LDT)   /* is it local or global */
 #define        SEL_LDT 4               /* local descriptor table */
 #define        IDXSEL(s)       (((s)>>3) & 0x1fff)             /* index of selector */
 #ifndef LOCORE
 
 /*
- * Memory and System segment descriptors
+ * User segment descriptors (%cs, %ds etc for compatability apps. 64 bit wide)
+ * For long-mode apps, %cs only has the conforming bit in sd_type, the sd_dpl,
+ * sd_p, sd_l and sd_def32 which must be zero).  %ds only has sd_p.
  */
-struct segment_descriptor      {
-       unsigned sd_lolimit:16 ;        /* segment extent (lsb) */
-       unsigned sd_lobase:24 __attribute__ ((packed));
-                                       /* segment base address (lsb) */
-       unsigned sd_type:5 ;            /* segment type */
-       unsigned sd_dpl:2 ;             /* segment descriptor priority level */
-       unsigned sd_p:1 ;               /* segment descriptor present */
-       unsigned sd_hilimit:4 ;         /* segment extent (msb) */
-       unsigned sd_xx:2 ;              /* unused */
-       unsigned sd_def32:1 ;           /* default 32 vs 16 bit size */
-       unsigned sd_gran:1 ;            /* limit granularity (byte/page units)*/
-       unsigned sd_hibase:8 ;          /* segment base address  (msb) */
-} ;
+struct user_segment_descriptor {
+       u_int64_t sd_lolimit:16;        /* segment extent (lsb) */
+       u_int64_t sd_lobase:24;         /* segment base address (lsb) */
+       u_int64_t sd_type:5;            /* segment type */
+       u_int64_t sd_dpl:2;             /* segment descriptor priority level */
+       u_int64_t sd_p:1;               /* segment descriptor present */
+       u_int64_t sd_hilimit:4;         /* segment extent (msb) */
+       u_int64_t sd_xx:1;              /* unused */
+       u_int64_t sd_long:1;            /* long mode (cs only) */
+       u_int64_t sd_def32:1;           /* default 32 vs 16 bit size */
+       u_int64_t sd_gran:1;            /* limit granularity (byte/page units)*/
+       u_int64_t sd_hibase:8;          /* segment base address  (msb) */
+} __packed;
 
 /*
- * Gate descriptors (e.g. indirect descriptors)
+ * System segment descriptors (128 bit wide)
  */
-struct gate_descriptor {
-       unsigned gd_looffset:16 ;       /* gate offset (lsb) */
-       unsigned gd_selector:16 ;       /* gate segment selector */
-       unsigned gd_stkcpy:5 ;          /* number of stack wds to cpy */
-       unsigned gd_xx:3 ;              /* unused */
-       unsigned gd_type:5 ;            /* segment type */
-       unsigned gd_dpl:2 ;             /* segment descriptor priority level */
-       unsigned gd_p:1 ;               /* segment descriptor present */
-       unsigned gd_hioffset:16 ;       /* gate offset (msb) */
-} ;
+struct system_segment_descriptor {
+       u_int64_t sd_lolimit:16;        /* segment extent (lsb) */
+       u_int64_t sd_lobase:24;         /* segment base address (lsb) */
+       u_int64_t sd_type:5;            /* segment type */
+       u_int64_t sd_dpl:2;             /* segment descriptor priority level */
+       u_int64_t sd_p:1;               /* segment descriptor present */
+       u_int64_t sd_hilimit:4;         /* segment extent (msb) */
+       u_int64_t sd_xx0:3;             /* unused */
+       u_int64_t sd_gran:1;            /* limit granularity (byte/page units)*/
+       u_int64_t sd_hibase:40 __packed;/* segment base address  (msb) */
+       u_int64_t sd_xx1:8;
+       u_int64_t sd_mbz:5;             /* MUST be zero */
+       u_int64_t sd_xx2:19;
+} __packed;
 
 /*
- * Generic descriptor
+ * Gate descriptors (e.g. indirect descriptors, trap, interrupt etc. 128 bit)
+ * Only interrupt and trap gates have gd_ist.
  */
-union  descriptor      {
-       struct  segment_descriptor sd;
-       struct  gate_descriptor gd;
-};
+struct gate_descriptor {
+       u_int64_t gd_looffset:16;       /* gate offset (lsb) */
+       u_int64_t gd_selector:16;       /* gate segment selector */
+       u_int64_t gd_ist:3;             /* IST table index */
+       u_int64_t gd_xx:5;              /* unused */
+       u_int64_t gd_type:5;            /* segment type */
+       u_int64_t gd_dpl:2;             /* segment descriptor priority level */
+       u_int64_t gd_p:1;               /* segment descriptor present */
+       u_int64_t gd_hioffset:48 __packed;      /* gate offset (msb) */
+       u_int64_t sd_xx1:32;
+} __packed;
 
 #endif /* LOCORE */
 
 /* system segments and gate types */
 #define        SDT_SYSNULL      0      /* system null */
-#define        SDT_SYS286TSS    1      /* system 286 TSS available */
-#define        SDT_SYSLDT       2      /* system local descriptor table */
-#define        SDT_SYS286BSY    3      /* system 286 TSS busy */
-#define        SDT_SYS286CGT    4      /* system 286 call gate */
-#define        SDT_SYSTASKGT    5      /* system task gate */
-#define        SDT_SYS286IGT    6      /* system 286 interrupt gate */
-#define        SDT_SYS286TGT    7      /* system 286 trap gate */
-#define        SDT_SYSNULL2     8      /* system null again */
-#define        SDT_SYS386TSS    9      /* system 386 TSS available */
-#define        SDT_SYSNULL3    10      /* system null again */
-#define        SDT_SYS386BSY   11      /* system 386 TSS busy */
-#define        SDT_SYS386CGT   12      /* system 386 call gate */
-#define        SDT_SYSNULL4    13      /* system null again */
-#define        SDT_SYS386IGT   14      /* system 386 interrupt gate */
-#define        SDT_SYS386TGT   15      /* system 386 trap gate */
+#define        SDT_SYSLDT       2      /* system 64-bit local descriptor table */
+#define        SDT_SYSTSS       9      /* system available 64-bit TSS */
+#define        SDT_SYSBSY      11      /* system busy 64-bit TSS */
+#define        SDT_SYSCGT      12      /* system 64-bit call gate */
+#define        SDT_SYSIGT      14      /* system 64-bit interrupt gate */
+#define        SDT_SYSTGT      15      /* system 64-bit trap gate */
 
        /* memory segment types */
 #define        SDT_MEMRO       16      /* memory read only */
@@ -142,6 +148,14 @@ union      descriptor      {
 
 #ifndef LOCORE
 
+#ifndef _SYS_TLS_H_
+#include <sys/tls.h>
+#endif
+
+struct savetls {
+       struct tls_info info[2];
+};
+
 /* is memory segment descriptor pointer ? */
 #define ISMEMSDP(s)    ((s->d_type) >= SDT_MEMRO && (s->d_type) <= SDT_MEMERAC)
 
@@ -168,28 +182,24 @@ union     descriptor      {
  * when needed to be used by the 386 hardware
  */
 
-#if 0
-
-struct soft_segment_descriptor {
-       unsigned ssd_base ;             /* segment base address  */
-       unsigned ssd_limit ;            /* segment extent */
-       unsigned ssd_type:5 ;           /* segment type */
-       unsigned ssd_dpl:2 ;            /* segment descriptor priority level */
-       unsigned ssd_p:1 ;              /* segment descriptor present */
-       unsigned ssd_xx:4 ;             /* unused */
-       unsigned ssd_xx1:2 ;            /* unused */
-       unsigned ssd_def32:1 ;          /* default 32 vs 16 bit size */
-       unsigned ssd_gran:1 ;           /* limit granularity (byte/page units)*/
-};
-#endif /* 0 */
+struct soft_segment_descriptor {
+       uint64_t ssd_base;              /* segment base address  */
+       uint64_t ssd_limit;     /* segment extent */
+       uint64_t ssd_type:5;    /* segment type */
+       uint64_t ssd_dpl:2;     /* segment descriptor priority level */
+       uint64_t ssd_p:1;               /* segment descriptor present */
+       uint64_t ssd_long:1;    /* long mode (for %cs) */
+       uint64_t ssd_def32:1;   /* default 32 vs 16 bit size */
+       uint64_t ssd_gran:1;    /* limit granularity (byte/page units)*/
+} __packed;
 
 /*
  * region descriptors, used to load gdt/idt tables before segments yet exist.
  */
 struct region_descriptor {
-       unsigned rd_limit:16;                           /* segment extent */
-       unsigned rd_base:32 __attribute__ ((packed));   /* base address  */
-};
+       uint64_t rd_limit:16;           /* segment extent */
+       uint64_t rd_base:64 __packed;   /* base address  */
+} __packed;
 
 #endif /* LOCORE */
 
@@ -209,6 +219,30 @@ struct region_descriptor {
  * as well just use all of them.
  */
 #define        NIDT    256             /* we use them all */
+/*
+ * Entries in the Interrupt Descriptor Table (IDT)
+ */
+#define        IDT_DE          0       /* #DE: Divide Error */
+#define        IDT_DB          1       /* #DB: Debug */
+#define        IDT_NMI         2       /* Nonmaskable External Interrupt */
+#define        IDT_BP          3       /* #BP: Breakpoint */
+#define        IDT_OF          4       /* #OF: Overflow */
+#define        IDT_BR          5       /* #BR: Bound Range Exceeded */
+#define        IDT_UD          6       /* #UD: Undefined/Invalid Opcode */
+#define        IDT_NM          7       /* #NM: No Math Coprocessor */
+#define        IDT_DF          8       /* #DF: Double Fault */
+#define        IDT_FPUGP       9       /* Coprocessor Segment Overrun */
+#define        IDT_TS          10      /* #TS: Invalid TSS */
+#define        IDT_NP          11      /* #NP: Segment Not Present */
+#define        IDT_SS          12      /* #SS: Stack Segment Fault */
+#define        IDT_GP          13      /* #GP: General Protection Fault */
+#define        IDT_PF          14      /* #PF: Page Fault */
+#define        IDT_MF          16      /* #MF: FPU Floating-Point Error */
+#define        IDT_AC          17      /* #AC: Alignment Check */
+#define        IDT_MC          18      /* #MC: Machine Check */
+#define        IDT_XF          19      /* #XF: SIMD Floating-Point Exception */
+#define        IDT_IO_INTS     NRSVIDT /* Base of IDT entries for I/O interrupts. */
+#define        IDT_SYSCALL     0x80    /* System Call Interrupt Vector */
 
 /*
  * Entries in the Global Descriptor Table (GDT)
@@ -216,59 +250,28 @@ struct region_descriptor {
 #define        GNULL_SEL       0       /* Null Descriptor */
 #define        GCODE_SEL       1       /* Kernel Code Descriptor */
 #define        GDATA_SEL       2       /* Kernel Data Descriptor */
-#define        GPRIV_SEL       3       /* SMP Per-Processor Private Data */
-#define        GPROC0_SEL      4       /* Task state process slot zero and up */
-#define        GLDT_SEL        5       /* LDT - eventually one per process */
-#define        GUSERLDT_SEL    6       /* User LDT */
-#define        GTGATE_SEL      7       /* Process task switch gate */
-#define        GBIOSLOWMEM_SEL 8       /* BIOS low memory access (must be entry 8) */
-#define        GPANIC_SEL      9       /* Task state to consider panic from */
-#define GBIOSCODE32_SEL        10      /* BIOS interface (32bit Code) */
-#define GBIOSCODE16_SEL        11      /* BIOS interface (16bit Code) */
-#define GBIOSDATA_SEL  12      /* BIOS interface (Data) */
-#define GBIOSUTIL_SEL  13      /* BIOS interface (Utility) */
-#define GBIOSARGS_SEL  14      /* BIOS interface (Arguments) */
-#define GTLS_START     15      /* Thread TLS Descriptor */
-#define GTLS_END       17      /* Thread TLS Descriptor */
-
-#define NGTLS                  (GTLS_END - GTLS_START + 1)
-#ifdef BDE_DEBUGGER
-#define        NGDT            18      /* some of 11-17 are reserved for debugger */
-#else
-#define NGDT           15
-#endif
-
-/*
- * Entries in the Local Descriptor Table (LDT)
- */
-#define        LSYS5CALLS_SEL  0       /* forced by intel BCS */
-#define        LSYS5SIGR_SEL   1
-#define        L43BSDCALLS_SEL 2       /* notyet */
-#define        LUCODE_SEL      3
-#define LSOL26CALLS_SEL        4       /* Solaris >= 2.6 system call gate */
-#define        LUDATA_SEL      5
-/* separate stack, es,fs,gs sels ? */
-/* #define     LPOSIXCALLS_SEL 5*/     /* notyet */
-#define LBSDICALLS_SEL 16      /* BSDI system call gate */
-#define NLDT           (LBSDICALLS_SEL + 1)
+#define        GUCODE32_SEL    3       /* User 32 bit code Descriptor */
+#define        GUDATA_SEL      4       /* User 32/64 bit Data Descriptor */
+#define        GUCODE_SEL      5       /* User 64 bit Code Descriptor */
+#define        GPROC0_SEL      6       /* TSS for entering kernel etc */
+/* slot 7 is second half of GPROC0_SEL */
+#define        GUGS32_SEL      8       /* User 32 bit GS Descriptor */
+#define        NGDT            9
 
 #ifndef LOCORE
-struct savetls {
-       struct segment_descriptor tls[NGTLS];
-};
 
 #ifdef _KERNEL
-extern int     _default_ldt;
-extern union descriptor gdt[];
+extern struct user_segment_descriptor gdt[];
 extern struct soft_segment_descriptor gdt_segs[];
 extern struct gate_descriptor *idt;
-extern union descriptor ldt[NLDT];
 
-void   lgdt            (struct region_descriptor *rdp);
-void   sdtossd         (struct segment_descriptor *sdp,
-                            struct soft_segment_descriptor *ssdp);
-void   ssdtosd         (struct soft_segment_descriptor *ssdp,
-                            struct segment_descriptor *sdp);
+void   lgdt(struct region_descriptor *rdp);
+void   sdtossd(struct user_segment_descriptor *sdp,
+           struct soft_segment_descriptor *ssdp);
+void   ssdtosd(struct soft_segment_descriptor *ssdp,
+           struct user_segment_descriptor *sdp);
+void   ssdtosyssd(struct soft_segment_descriptor *ssdp,
+           struct system_segment_descriptor *sdp);
 #endif /* _KERNEL */
 #endif /* LOCORE */
 
index 4956269..5dbc973 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * Copyright (c) 1986, 1989, 1991, 1993
- *     The Regents of the University of California.  All rights reserved.
+ *     The Regents of the University of California.
+ * Copyright (c) 2008 The DragonFly Project.
+ * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -32,7 +34,7 @@
  *
  *     @(#)signal.h    8.1 (Berkeley) 6/11/93
  * $FreeBSD: src/sys/i386/include/signal.h,v 1.12 1999/11/12 13:52:11 marcel Exp $
- * $DragonFly: src/sys/cpu/amd64/include/signal.h,v 1.2 2008/08/25 23:34:31 dillon Exp $
+ * $DragonFly: src/sys/cpu/amd64/include/signal.h,v 1.3 2008/08/29 17:07:06 dillon Exp $
  */
 
 #ifndef _CPU_SIGNAL_H_
@@ -99,12 +101,6 @@ typedef int sig_atomic_t;
 
 #if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE)
 
-/*
- * XXX temporarily use a <machine/bla.h> path instead of "bla.h" so the
- * XFree86-4-clients port, which uses -I-, builds.  Use of -I- should
- * be banned, or the option should be fixed to not screw up relative-path
- * includes.
- */
 #include <machine/trap.h>      /* codes for SIGILL, SIGFPE */
 
 /*
@@ -118,40 +114,45 @@ typedef int sig_atomic_t;
  * those in mcontext_t.
  */
 struct sigcontext {
-       sigset_t sc_mask;               /* signal mask to restore */
-       long    sc_onstack;             /* sigstack state to restore */
-       long    sc_rdi;
-       long    sc_rsi;
-       long    sc_rdx;
-       long    sc_rcx;
-       long    sc_r8;
-       long    sc_r9;
-       long    sc_rax;
-       long    sc_rbx;
-       long    sc_rbp;
-       long    sc_r10;
-       long    sc_r11;
-       long    sc_r12;
-       long    sc_r13;
-       long    sc_r14;
-       long    sc_r15;
-       long    sc_trapno;
-       long    sc_addr;
-       long    sc_flags;
-       long    sc_err;
-       long    sc_rip;
-       long    sc_cs;
-       long    sc_rflags;
-       long    sc_rsp;
-       long    sc_ss;
-       long    sc_len;
-       /*
-        * XXX - taken from freebsd
-        */
-       long    sc_fpformat;
-       long    sc_ownedfp;
-       long    sc_fpstate[64] __aligned(16);
-       long    sc_spare[9];
+       sigset_t        sc_mask;        /* signal mask to restore */
+
+       long            sc_onstack;     /* sigstack state to restore */
+       long            sc_rdi;
+       long            sc_rsi;
+       long            sc_rdx;
+       long            sc_rcx;
+       long            sc_r8;
+       long            sc_r9;
+       long            sc_rax;
+       long            sc_rbx;
+       long            sc_rbp;
+       long            sc_r10;
+       long            sc_r11;
+       long            sc_r12;
+       long            sc_r13;
+       long            sc_r14;
+       long            sc_r15;
+       long            sc_trapno;
+       long            sc_addr;
+       long            sc_flags;
+       long            sc_err;
+       long            sc_rip;
+       long            sc_cs;
+       long            sc_rflags;
+       long            sc_rsp;
+       long            sc_ss;
+
+       unsigned int    sc_len;
+       unsigned int    sc_fpformat;
+       unsigned int    sc_ownedfp;
+       unsigned int    sc_reserved;
+       unsigned int    sc_unused01;
+       unsigned int    sc_unused02;
+
+       /* 16 byte aligned */
+
+       int             sc_fpregs[128];
+       int             __spare__[16];
 };
 
 #endif /* !_ANSI_SOURCE && !_POSIX_SOURCE */
index e949e6b..92a9bec 100644 (file)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 1991 The Regents of the University of California.
+ * Copyright (c) 2008 The DragonFly Project.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -28,7 +29,7 @@
  *
  *     from: @(#)specialreg.h  7.1 (Berkeley) 5/9/91
  * $FreeBSD: src/sys/amd64/include/specialreg.h,v 1.39 2007/05/31 11:26:44 des Exp $
- * $DragonFly: src/sys/cpu/amd64/include/specialreg.h,v 1.1 2007/09/23 04:29:30 yanyh Exp $
+ * $DragonFly: src/sys/cpu/amd64/include/specialreg.h,v 1.2 2008/08/29 17:07:06 dillon Exp $
  */
 
 #ifndef _CPU_SPECIALREG_H_
 #define        AMDID_NX        0x00100000
 #define        AMDID_EXT_MMX   0x00400000
 #define        AMDID_FFXSR     0x01000000
+#define        AMDID_PAGE1GB   0x04000000
 #define        AMDID_RDTSCP    0x08000000
 #define        AMDID_LM        0x20000000
 #define        AMDID_EXT_3DNOW 0x40000000
index 9d1d565..7f17f32 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
+ * Copyright (c) 2005,2008 The DragonFly Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,7 +28,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/cpu/amd64/include/tls.h,v 1.1 2007/08/21 19:40:24 corecode Exp $
+ * $DragonFly: src/sys/cpu/amd64/include/tls.h,v 1.2 2008/08/29 17:07:06 dillon Exp $
  */
 
 #ifndef        _CPU_TLS_H_
@@ -106,7 +106,7 @@ tls_set_tcb(struct tls_tcb *tcb)
        info.base = tcb;
        info.size = -1;
        seg = set_tls_area(0, &info, sizeof(info));
-       __asm __volatile("movl %0, %%fs" : : "r" (seg));
+       /*__asm __volatile("movl %0, %%fs" : : "r" (seg));*/
 }
 
 struct tls_tcb *_rtld_allocate_tls(void);
index 7053eb7..eefafdf 100644 (file)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 2008 The DragonFly Project.
  * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
@@ -35,7 +36,7 @@
  *
  *     from: @(#)tss.h 5.4 (Berkeley) 1/18/91
  * $FreeBSD: src/sys/amd64/include/tss.h,v 1.15 2003/11/17 08:58:14 peter Exp $
- * $DragonFly: src/sys/cpu/amd64/include/tss.h,v 1.1 2007/08/21 19:40:24 corecode Exp $
+ * $DragonFly: src/sys/cpu/amd64/include/tss.h,v 1.2 2008/08/29 17:07:06 dillon Exp $
  */
 
 #ifndef _CPU_TSS_H_
@@ -55,7 +56,6 @@ struct amd64tss {
        u_int64_t       tss_rsp2 __packed;      /* kernel stack pointer ring 2 */
        u_int32_t       tss_rsvd1;
        u_int32_t       tss_rsvd2;
-       u_int32_t       tss_rsvd3;
        u_int64_t       tss_ist1 __packed;      /* Interrupt stack table 1 */
        u_int64_t       tss_ist2 __packed;      /* Interrupt stack table 2 */
        u_int64_t       tss_ist3 __packed;      /* Interrupt stack table 3 */
@@ -63,9 +63,9 @@ struct amd64tss {
        u_int64_t       tss_ist5 __packed;      /* Interrupt stack table 5 */
        u_int64_t       tss_ist6 __packed;      /* Interrupt stack table 6 */
        u_int64_t       tss_ist7 __packed;      /* Interrupt stack table 7 */
+       u_int32_t       tss_rsvd3;
        u_int32_t       tss_rsvd4;
-       u_int32_t       tss_rsvd5;
-       u_int16_t       tss_rsvd6;
+       u_int16_t       tss_rsvd5;
        u_int16_t       tss_iobase;     /* io bitmap offset */
 };
 
index 11f7ae6..e234fe9 100644 (file)
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 1990, 1993
  *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 2008 The DragonFly Project.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -32,7 +33,7 @@
  *
  *     @(#)types.h     8.3 (Berkeley) 1/5/94
  * $FreeBSD: src/sys/i386/include/types.h,v 1.19.2.1 2001/03/21 10:50:58 peter Exp $
- * $DragonFly: src/sys/cpu/amd64/include/types.h,v 1.1 2007/08/21 19:40:24 corecode Exp $
+ * $DragonFly: src/sys/cpu/amd64/include/types.h,v 1.2 2008/08/29 17:07:06 dillon Exp $
  */
 
 #ifndef _CPU_TYPES_H_
@@ -66,10 +67,13 @@ typedef     __uint64_t      uintfptr_t;
 /*
  * MMU page tables
  */
+#ifndef JG_defined_pml4_entry_t
+#define JG_defined_pml4_entry_t
 typedef __uint64_t     pml4_entry_t;
 typedef __uint64_t     pdp_entry_t;
 typedef __uint64_t     pd_entry_t;
 typedef __uint64_t     pt_entry_t;
+#endif
 typedef __uint32_t      cpumask_t;      /* mask representing a set of cpus */
 
 #define PML4SIZE       sizeof(pml4_entry_t) /* for assembly files */
index 139f794..b53c769 100644 (file)
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 2003 Peter Wemm
  * Copyright (c) 1999 Marcel Moolenaar
+ * Copyright (c) 2008 The DragonFly Project.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -27,7 +28,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/amd64/include/ucontext.h,v 1.18 2003/11/08 04:39:22 peter Exp $
- * $DragonFly: src/sys/cpu/amd64/include/ucontext.h,v 1.1 2007/08/21 19:40:24 corecode Exp $
+ * $DragonFly: src/sys/cpu/amd64/include/ucontext.h,v 1.2 2008/08/29 17:07:06 dillon Exp $
  */
 
 #ifndef _CPU_UCONTEXT_H_
@@ -39,8 +40,8 @@ typedef struct __mcontext {
         * sigcontext. So that we can support sigcontext
         * and ucontext_t at the same time.
         */
-       __register_t    mc_onstack;             /* XXX - sigcontext compat. */
-       __register_t    mc_rdi;                 /* machine state (struct trapframe) */
+       __register_t    mc_onstack;     /* XXX - sigcontext compat. */
+       __register_t    mc_rdi;
        __register_t    mc_rsi;
        __register_t    mc_rdx;
        __register_t    mc_rcx;
@@ -62,22 +63,28 @@ typedef struct __mcontext {
        __register_t    mc_rip;
        __register_t    mc_cs;
        __register_t    mc_rflags;
-       __register_t    mc_rsp;
+       __register_t    mc_rsp;         /* machine state */
        __register_t    mc_ss;
 
-       long    mc_len;                 /* sizeof(mcontext_t) */
-#define        _MC_FPFMT_NODEV         0x10000 /* device not present or configured */
-#define        _MC_FPFMT_XMM           0x10002
-       long    mc_fpformat;
-#define        _MC_FPOWNED_NONE        0x20000 /* FP state not used */
-#define        _MC_FPOWNED_FPU         0x20001 /* FP state came from FPU */
-#define        _MC_FPOWNED_PCB         0x20002 /* FP state came from PCB */
-       long    mc_ownedfp;
-       /*
-        * See <machine/fpu.h> for the internals of mc_fpstate[].
-        */
-       long    mc_fpstate[64] __aligned(16);
-       long    mc_spare[8];
+       unsigned int    mc_len;         /* sizeof(mcontext_t) */
+       unsigned int    mc_fpformat;
+       unsigned int    mc_ownedfp;
+       unsigned int    mc_reserved;
+       unsigned int    mc_unused01;
+       unsigned int    mc_unused02;
+
+       /* 16 byte aligned */
+
+       int             mc_fpregs[128];
+       int             __spare__[16];
 } mcontext_t;
 
+#define _MC_FPFMT_NODEV                0x10000 /* device not present or configured */
+#define _MC_FPFMT_387          0x10001
+#define _MC_FPFMT_XMM          0x10002
+
+#define _MC_FPOWNED_NONE       0x20000 /* FP state not used */
+#define _MC_FPOWNED_FPU                0x20001 /* FP state came from FPU */
+#define _MC_FPOWNED_PCB                0x20002 /* FP state came from PCB */
+
 #endif /* !_CPU_UCONTEXT_H_ */
diff --git a/sys/cpu/amd64/misc/amd64-gdbstub.c b/sys/cpu/amd64/misc/amd64-gdbstub.c
new file mode 100644 (file)
index 0000000..06ba3c1
--- /dev/null
@@ -0,0 +1,666 @@
+/****************************************************************************
+
+               THIS SOFTWARE IS NOT COPYRIGHTED
+
+   HP offers the following for use in the public domain.  HP makes no
+   warranty with regard to the software or its performance and the
+   user accepts the software "AS IS" with all faults.
+
+   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+****************************************************************************/
+
+/****************************************************************************
+ *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
+ *
+ *  Module name: remcom.c $
+ *  Revision: 1.34 $
+ *  Date: 91/03/09 12:29:49 $
+ *  Contributor:     Lake Stevens Instrument Division$
+ *
+ *  Description:     low level support for gdb debugger. $
+ *
+ *  Considerations:  only works on target hardware $
+ *
+ *  Written by:      Glenn Engel $
+ *  ModuleState:     Experimental $
+ *
+ *  NOTES:           See Below $
+ *
+ *  Modified for FreeBSD by Stu Grossman.
+ *
+ *  To enable debugger support, two things need to happen.  One, a
+ *  call to set_debug_traps() is necessary in order to allow any breakpoints
+ *  or error conditions to be properly intercepted and reported to gdb.
+ *  Two, a breakpoint needs to be generated to begin communication.  This
+ *  is most easily accomplished by a call to breakpoint().  Breakpoint()
+ *  simulates a breakpoint by executing a trap #1.
+ *
+ *  The external function exceptionHandler() is
+ *  used to attach a specific handler to a specific 386 vector number.
+ *  It should use the same privilege level it runs at.  It should
+ *  install it as an interrupt gate so that interrupts are masked
+ *  while the handler runs.
+ *  Also, need to assign exceptionHook and oldExceptionHook.
+ *
+ *  Because gdb will sometimes write to the stack area to execute function
+ *  calls, this program cannot rely on using the supervisor stack so it
+ *  uses its own stack area reserved in the int array remcomStack.
+ *
+ *************
+ *
+ *    The following gdb commands are supported:
+ *
+ * command          function                               Return value
+ *
+ *    g             return the value of the CPU registers  hex data or ENN
+ *    G             set the value of the CPU registers     OK or ENN
+ *
+ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
+ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
+ *
+ *    c             Resume at current address              SNN   ( signal NN)
+ *    cAA..AA       Continue at address AA..AA             SNN
+ *
+ *    s             Step one instruction                   SNN
+ *    sAA..AA       Step one instruction from AA..AA       SNN
+ *
+ *    k             kill
+ *
+ *    ?             What was the last sigval ?             SNN   (signal NN)
+ *
+ *    D             detach                                 OK
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum.  A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer.  '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host:                  Reply:
+ * $m0,10#2a               +$00010203040506070809101112131415#42
+ *
+ ****************************************************************************/
+/*
+ * $FreeBSD: src/sys/i386/i386/i386-gdbstub.c,v 1.13.2.1 2000/08/03 00:54:41 peter Exp $
+ * $DragonFly: src/sys/cpu/amd64/misc/amd64-gdbstub.c,v 1.1 2008/08/29 17:07:09 dillon Exp $
+ */
+
+#include "opt_ddb.h"
+
+#include <sys/param.h>
+#include <sys/reboot.h>
+#include <sys/systm.h>
+#include <sys/cons.h>
+
+#include <ddb/ddb.h>
+
+#include <setjmp.h>
+
+void           gdb_handle_exception (db_regs_t *, int, int);
+
+/************************************************************************/
+
+extern jmp_buf db_jmpbuf;
+
+/************************************************************************/
+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
+/* at least NUMREGBYTES*2 are needed for register packets */
+#define BUFMAX 400
+
+/* Create private copies of common functions used by the stub.  This prevents
+   nasty interactions between app code and the stub (for instance if user steps
+   into strlen, etc..) */
+
+#define strlen gdb_strlen
+#define strcpy gdb_strcpy
+
+static int
+strlen (const char *s)
+{
+  const char *s1 = s;
+
+  while (*s1++ != '\000');
+
+  return s1 - s;
+}
+
+static char *
+strcpy (char *dst, const char *src)
+{
+  char *retval = dst;
+
+  while ((*dst++ = *src++) != '\000');
+
+  return retval;
+}
+
+static int
+putDebugChar (int c)           /* write a single character      */
+{
+  if (gdb_tab == NULL)
+       return 0;
+  gdb_tab->cn_putc(gdb_tab->cn_gdbprivate, c);
+  return 1;
+}
+
+static int
+getDebugChar (void)            /* read and return a single char */
+{
+  if (gdb_tab == NULL)
+       return -1;
+  return gdb_tab->cn_getc(gdb_tab->cn_gdbprivate);
+}
+
+static const char hexchars[]="0123456789abcdef";
+
+static int
+hex(char ch)
+{
+  if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
+  if ((ch >= '0') && (ch <= '9')) return (ch-'0');
+  if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
+  return (-1);
+}
+
+/* scan for the sequence $<data>#<checksum>     */
+static void
+getpacket (char *buffer)
+{
+  unsigned char checksum;
+  unsigned char xmitcsum;
+  int i;
+  int count;
+  unsigned char ch;
+
+  do
+    {
+      /* wait around for the start character, ignore all other characters */
+
+      while ((ch = (getDebugChar () & 0x7f)) != '$');
+
+      checksum = 0;
+      xmitcsum = -1;
+
+      count = 0;
+
+      /* now, read until a # or end of buffer is found */
+
+      while (count < BUFMAX)
+       {
+         ch = getDebugChar () & 0x7f;
+         if (ch == '#')
+           break;
+         checksum = checksum + ch;
+         buffer[count] = ch;
+         count = count + 1;
+       }
+      buffer[count] = 0;
+
+      if (ch == '#')
+       {
+         xmitcsum = hex (getDebugChar () & 0x7f) << 4;
+         xmitcsum += hex (getDebugChar () & 0x7f);
+
+         if (checksum != xmitcsum)
+           putDebugChar ('-');  /* failed checksum */
+         else
+           {
+             putDebugChar ('+'); /* successful transfer */
+             /* if a sequence char is present, reply the sequence ID */
+             if (buffer[2] == ':')
+               {
+                 putDebugChar (buffer[0]);
+                 putDebugChar (buffer[1]);
+
+                 /* remove sequence chars from buffer */
+
+                 count = strlen (buffer);
+                 for (i=3; i <= count; i++)
+                   buffer[i-3] = buffer[i];
+               }
+           }
+       }
+    }
+  while (checksum != xmitcsum);
+}
+
+/* send the packet in buffer.  */
+
+static void
+putpacket (char *buffer)
+{
+  unsigned char checksum;
+  int count;
+  unsigned char ch;
+
+  /*  $<packet info>#<checksum>. */
+  do
+    {
+/*
+ * This is a non-standard hack to allow use of the serial console for
+ * operation as well as debugging.  Simply turn on 'remotechat' in gdb.
+ *
+ * This extension is not part of the Cygnus protocol, is kinda gross,
+ * but gets the job done.
+ */
+#ifdef GDB_REMOTE_CHAT
+      putDebugChar ('|');
+      putDebugChar ('|');
+      putDebugChar ('|');
+      putDebugChar ('|');
+#endif
+      putDebugChar ('$');
+      checksum = 0;
+      count = 0;
+
+      while ((ch=buffer[count]) != 0)
+       {
+         putDebugChar (ch);
+         checksum += ch;
+         count += 1;
+       }
+
+      putDebugChar ('#');
+      putDebugChar (hexchars[checksum >> 4]);
+      putDebugChar (hexchars[checksum & 0xf]);
+    }
+  while ((getDebugChar () & 0x7f) != '+');
+}
+
+static char  remcomInBuffer[BUFMAX];
+static char  remcomOutBuffer[BUFMAX];
+
+static int
+get_char (vm_offset_t addr)
+{
+  char data;
+
+  if (setjmp (db_jmpbuf))
+    return -1;
+
+  db_read_bytes (addr, 1, &data);
+
+  return data & 0xff;
+}
+
+static int
+set_char (vm_offset_t addr, int val)
+{
+  char data;
+
+  if (setjmp (db_jmpbuf))
+    return -1;
+
+  data = val;
+
+  db_write_bytes (addr, 1, &data);
+  return 0;
+}
+
+/* convert the memory pointed to by mem into hex, placing result in buf */
+/* return a pointer to the last char put in buf (null) */
+
+static char *
+mem2hex (vm_offset_t mem, char *buf, int count)
+{
+      int i;
+      int ch;
+
+      for (i=0;i<count;i++) {
+          ch = get_char (mem++);
+         if (ch == -1)
+           return NULL;
+          *buf++ = hexchars[ch >> 4];
+          *buf++ = hexchars[ch % 16];
+      }
+      *buf = 0;
+      return(buf);
+}
+
+/* convert the hex array pointed to by buf into binary to be placed in mem */
+/* return a pointer to the character AFTER the last byte written */
+static char *
+hex2mem (char *buf, vm_offset_t mem, int count)
+{
+      int i;
+      int ch;
+      int rv;
+
+      for (i=0;i<count;i++) {
+          ch = hex(*buf++) << 4;
+          ch = ch + hex(*buf++);
+          rv = set_char (mem++, ch);
+         if (rv == -1)
+           return NULL;
+      }
+      return(buf);
+}
+
+/* this function takes the 386 exception vector and attempts to
+   translate this number into a unix compatible signal value */
+static int
+computeSignal (int exceptionVector)
+{
+  int sigval;
+  switch (exceptionVector & ~T_USER)
+    {
+    case 0: sigval = 8; break; /* divide by zero */
+    case 1: sigval = 5; break; /* debug exception */
+    case 3: sigval = 5; break; /* breakpoint */
+    case 4: sigval = 16; break; /* into instruction (overflow) */
+    case 5: sigval = 16; break; /* bound instruction */
+    case 6: sigval = 4; break; /* Invalid opcode */
+    case 7: sigval = 8; break; /* coprocessor not available */
+    case 8: sigval = 7; break; /* double fault */
+    case 9: sigval = 11; break; /* coprocessor segment overrun */
+    case 10: sigval = 5; break; /* Invalid TSS (also single-step) */
+    case 11: sigval = 11; break; /* Segment not present */
+    case 12: sigval = 11; break; /* stack exception */
+    case 13: sigval = 11; break; /* general protection */
+    case 14: sigval = 11; break; /* page fault */
+    case 16: sigval = 7; break; /* coprocessor error */
+    default:
+      sigval = 7;         /* "software generated"*/
+    }
+  return (sigval);
+}
+
+/*
+ * While we find nice hex chars, build an int.
+ * Return number of chars processed.
+ */
+
+static int
+hexToInt(char **ptr, int *intValue)
+{
+    int numChars = 0;
+    int hexValue;
+
+    *intValue = 0;
+
+    while (**ptr)
+    {
+        hexValue = hex(**ptr);
+        if (hexValue >=0)
+        {
+            *intValue = (*intValue <<4) | hexValue;
+            numChars ++;
+        }
+        else
+            break;
+
+        (*ptr)++;
+    }
+
+    return (numChars);
+}
+
+/*
+ * While we find nice hex chars, build a long.
+ * Return number of chars processed.
+ */
+
+static long
+hexToLong(char **ptr, long *longValue)
+{
+    int numChars = 0;
+    int hexValue;
+
+    *longValue = 0;
+
+    while (**ptr)
+    {
+        hexValue = hex(**ptr);
+        if (hexValue >=0)
+        {
+            *longValue = (*longValue <<4) | hexValue;
+            numChars ++;
+        }
+        else
+            break;
+
+        (*ptr)++;
+    }
+
+    return (numChars);
+}
+
+#define NUMREGBYTES (sizeof registers)
+#define PC 16
+#define SP 7
+#define FP 6
+#define NUM_REGS 22
+
+/*
+ * This function does all command procesing for interfacing to gdb.
+ */
+void
+gdb_handle_exception (db_regs_t *raw_regs, int type, int code)
+{
+  int    sigval;
+  long   addr;
+  int length;
+  char * ptr;
+  struct amd64regs {
+    unsigned long rax;
+    unsigned long rcx;
+    unsigned long rdx;
+    unsigned long rbx;
+    unsigned long rsi;
+    unsigned long rdi;
+    unsigned long rbp;
+    unsigned long rsp;
+    unsigned long r8;
+    unsigned long r9;
+    unsigned long r10;
+    unsigned long r11;
+    unsigned long r12;
+    unsigned long r13;
+    unsigned long r14;
+    unsigned long r15;
+    unsigned long rip;
+    unsigned long rflags;
+    unsigned int cs;
+    unsigned int ss;
+  };
+  struct amd64regs registers;
+
+  registers.rax = raw_regs->tf_rax;
+  registers.rbx = raw_regs->tf_rbx;
+  registers.rcx = raw_regs->tf_rcx;
+  registers.rdx = raw_regs->tf_rdx;
+
+  registers.rsp = raw_regs->tf_rsp;
+  registers.rbp = raw_regs->tf_rbp;
+  registers.rsi = raw_regs->tf_rsi;
+  registers.rdi = raw_regs->tf_rdi;
+
+  registers.r8  = raw_regs->tf_r8;
+  registers.r9  = raw_regs->tf_r9;
+  registers.r10 = raw_regs->tf_r10;
+  registers.r11 = raw_regs->tf_r11;
+  registers.r12 = raw_regs->tf_r12;
+  registers.r13 = raw_regs->tf_r13;
+  registers.r14 = raw_regs->tf_r14;
+  registers.r15 = raw_regs->tf_r15;
+
+  registers.rip = raw_regs->tf_rip;
+  registers.rflags = raw_regs->tf_rflags;
+
+  registers.cs = raw_regs->tf_cs;
+  registers.ss = raw_regs->tf_ss;
+
+  /* reply to host that an exception has occurred */
+  sigval = computeSignal (type);
+  ptr = remcomOutBuffer;
+
+  *ptr++ = 'T';
+  *ptr++ = hexchars[sigval >> 4];
+  *ptr++ = hexchars[sigval & 0xf];
+
+  *ptr++ = hexchars[PC >> 4];
+  *ptr++ = hexchars[PC & 0xf];
+  *ptr++ = ':';
+  ptr = mem2hex ((vm_offset_t)&registers.rip, ptr, 8);
+  *ptr++ = ';';
+
+  *ptr++ = hexchars[FP >> 4];
+  *ptr++ = hexchars[FP & 0xf];
+  *ptr++ = ':';
+  ptr = mem2hex ((vm_offset_t)&registers.rbp, ptr, 8);
+  *ptr++ = ';';
+
+  *ptr++ = hexchars[SP >> 4];
+  *ptr++ = hexchars[SP & 0xf];
+  *ptr++ = ':';
+  ptr = mem2hex ((vm_offset_t)&registers.rsp, ptr, 8);
+  *ptr++ = ';';
+
+  *ptr++ = 0;
+
+  putpacket (remcomOutBuffer);
+
+  while (1)
+    {
+      remcomOutBuffer[0] = 0;
+
+      getpacket (remcomInBuffer);
+      switch (remcomInBuffer[0]) 
+       {
+       case '?':
+         remcomOutBuffer[0] = 'S';
+         remcomOutBuffer[1] = hexchars[sigval >> 4];
+         remcomOutBuffer[2] = hexchars[sigval % 16];
+         remcomOutBuffer[3] = 0;
+         break;
+
+       case 'D':               /* detach; say OK and turn off gdb */
+         putpacket(remcomOutBuffer);
+         boothowto &= ~RB_GDB;
+         return;
+
+       case 'g':               /* return the value of the CPU registers */
+         mem2hex ((vm_offset_t)&registers, remcomOutBuffer, NUMREGBYTES);
+         break;
+
+       case 'G':               /* set the value of the CPU registers - return OK */
+         hex2mem (&remcomInBuffer[1], (vm_offset_t)&registers, NUMREGBYTES);
+         strcpy (remcomOutBuffer, "OK");
+         break;
+
+       case 'P':               /* Set the value of one register */
+         {
+           int regno;
+
+           ptr = &remcomInBuffer[1];
+
+           if (hexToInt (&ptr, &regno)
+               && *ptr++ == '='
+               && regno < NUM_REGS)
+             {
+               /* JG */
+               hex2mem (ptr, (vm_offset_t)&registers + regno * 8, 8);
+               strcpy(remcomOutBuffer,"OK");
+             }
+           else
+             strcpy (remcomOutBuffer, "P01");
+           break;
+         }
+       case 'm':       /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
+         /* Try to read %x,%x.  */
+
+         ptr = &remcomInBuffer[1];
+
+         if (hexToLong (&ptr, &addr)
+             && *(ptr++) == ','
+             && hexToInt (&ptr, &length))
+           {
+             if (mem2hex((vm_offset_t) addr, remcomOutBuffer, length) == NULL)
+               strcpy (remcomOutBuffer, "E03");
+             break;
+           }
+         else
+           strcpy (remcomOutBuffer, "E01");
+         break;
+
+       case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+
+         /* Try to read '%x,%x:'.  */
+
+         ptr = &remcomInBuffer[1];
+
+         if (hexToLong(&ptr,&addr)
+             && *(ptr++) == ','
+             && hexToInt(&ptr, &length)
+             && *(ptr++) == ':')
+           {
+             if (hex2mem(ptr, (vm_offset_t) addr, length) == NULL)
+               strcpy (remcomOutBuffer, "E03");
+             else
+               strcpy (remcomOutBuffer, "OK");
+           }
+         else
+           strcpy (remcomOutBuffer, "E02");
+         break;
+
+         /* cAA..AA    Continue at address AA..AA(optional) */
+         /* sAA..AA   Step one instruction from AA..AA(optional) */
+       case 'c' :
+       case 's' :
+         /* try to read optional parameter, pc unchanged if no parm */
+
+         ptr = &remcomInBuffer[1];
+         if (hexToLong(&ptr,&addr))
+           registers.rip = addr;
+
+
+         /* set the trace bit if we're stepping */
+         if (remcomInBuffer[0] == 's')
+           registers.rflags |= PSL_T;
+         else
+           registers.rflags &= ~PSL_T;
+
+         raw_regs->tf_rax = registers.rax;
+         raw_regs->tf_rbx = registers.rbx;
+         raw_regs->tf_rcx = registers.rcx;
+         raw_regs->tf_rdx = registers.rdx;
+
+         raw_regs->tf_rsp = registers.rsp;
+         raw_regs->tf_rbp = registers.rbp;
+         raw_regs->tf_rsi = registers.rsi;
+         raw_regs->tf_rdi = registers.rdi;
+
+         raw_regs->tf_r8  = registers.r8;
+         raw_regs->tf_r9  = registers.r9;
+         raw_regs->tf_r10  = registers.r10;
+         raw_regs->tf_r11  = registers.r11;
+         raw_regs->tf_r12  = registers.r12;
+         raw_regs->tf_r13  = registers.r13;
+         raw_regs->tf_r14  = registers.r14;
+         raw_regs->tf_r15  = registers.r15;
+
+         raw_regs->tf_rip = registers.rip;
+         raw_regs->tf_rflags = registers.rflags;
+
+         raw_regs->tf_cs = registers.cs;
+         raw_regs->tf_ss = registers.ss;
+         return;
+
+       } /* switch */
+
+      /* reply to the request */
+      putpacket (remcomOutBuffer);
+    }
+}
+
index 7a51aa7..504ac81 100644 (file)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 2008 The DragonFly Project.
  * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
@@ -35,7 +36,7 @@
  *
  *     from: @(#)autoconf.c    7.1 (Berkeley) 5/9/91
  * $FreeBSD: src/sys/i386/i386/autoconf.c,v 1.146.2.2 2001/06/07 06:05:58 dd Exp $
- * $DragonFly: src/sys/platform/pc64/amd64/autoconf.c,v 1.2 2008/03/08 07:50:49 sephe Exp $
+ * $DragonFly: src/sys/platform/pc64/amd64/autoconf.c,v 1.3 2008/08/29 17:07:10 dillon Exp $
  */
 
 /*
@@ -60,7 +61,6 @@
 #include <sys/systm.h>
 #include <sys/bootmaj.h>
 #include <sys/bus.h>
-#include <sys/buf.h>
 #include <sys/conf.h>
 #include <sys/diskslice.h>
 #include <sys/reboot.h>
 #include <sys/device.h>
 #include <sys/machintr.h>
 
-#include <vm/pmap.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_pager.h>
+#include <machine/bootinfo.h>
+#include <machine/md_var.h>
+#include <machine/smp.h>
+#include <machine_base/icu/icu.h>
 
-#if 0
 #include <machine/pcb.h>
 #include <machine/pcb_ext.h>
-#include <machine/vm86.h>
-#endif
-#include <machine/smp.h>
 #include <machine/globaldata.h>
-#include <machine/md_var.h>
 
 #if NISA > 0
 #include <bus/isa/isavar.h>
 device_t isa_bus_device = 0;
 #endif
 
-static void cpu_startup (void *);
-static void configure_first (void *);
-static void configure (void *);
-static void configure_final (void *);
+static void    configure_first (void *);
+static void    configure (void *);
+static void    configure_final (void *);
 
 #if defined(FFS) && defined(FFS_ROOT)
 static void    setroot (void);
@@ -107,7 +101,6 @@ static void pxe_setup_nfsdiskless(void);
 #endif
 #endif
 
-SYSINIT(cpu, SI_BOOT2_SMP, SI_ORDER_FIRST, cpu_startup, NULL);
 SYSINIT(configure1, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure_first, NULL);
 /* SI_ORDER_SECOND is hookable */
 SYSINIT(configure2, SI_SUB_CONFIGURE, SI_ORDER_THIRD, configure, NULL);
@@ -117,77 +110,6 @@ SYSINIT(configure3, SI_SUB_CONFIGURE, SI_ORDER_ANY, configure_final, NULL);
 cdev_t rootdev = NULL;
 cdev_t dumpdev = NULL;
 
-/*
- * 
- */
-static void
-cpu_startup(void *dummy)
-{
-       vm_offset_t buffer_sva;
-       vm_offset_t buffer_eva;
-       vm_offset_t pager_sva;
-       vm_offset_t pager_eva;
-
-       kprintf("%s", version);
-       kprintf("real memory = %llu (%lluK bytes)\n",
-               ptoa(Maxmem), ptoa(Maxmem) / 1024);
-
-       if (nbuf == 0) {
-               int factor = 4 * BKVASIZE / 1024;
-               int kbytes = Maxmem * (PAGE_SIZE / 1024);
-
-               nbuf = 50;
-               if (kbytes > 4096)
-                       nbuf += min((kbytes - 4096) / factor, 65536 / factor);
-               if (kbytes > 65536)
-                       nbuf += (kbytes - 65536) * 2 / (factor * 5);
-               if (maxbcache && nbuf > maxbcache / BKVASIZE)
-                       nbuf = maxbcache / BKVASIZE;
-       }
-       if (nbuf > (virtual_end - virtual_start) / (BKVASIZE * 2)) {
-               nbuf = (virtual_end - virtual_start) / (BKVASIZE * 2);
-               kprintf("Warning: nbufs capped at %d\n", nbuf);
-       }
-
-       nswbuf = max(min(nbuf/4, 256), 16);
-#ifdef NSWBUF_MIN
-       if (nswbuf < NSWBUF_MIN)
-               nswbuf = NSWBUF_MIN;
-#endif
-
-       /*
-        * Allocate memory for the buffer cache
-        */
-       buf = (void *)kmem_alloc(&kernel_map, nbuf * sizeof(struct buf));
-       swbuf = (void *)kmem_alloc(&kernel_map, nswbuf * sizeof(struct buf));
-
-
-#ifdef DIRECTIO
-        ffs_rawread_setup();
-#endif
-       kmem_suballoc(&kernel_map, &clean_map, &clean_sva, &clean_eva,
-                     (nbuf*BKVASIZE) + (nswbuf*MAXPHYS) + pager_map_size);
-       kmem_suballoc(&clean_map, &buffer_map, &buffer_sva, &buffer_eva,
-                     (nbuf*BKVASIZE));
-       buffer_map.system_map = 1;
-       kmem_suballoc(&clean_map, &pager_map, &pager_sva, &pager_eva,
-                     (nswbuf*MAXPHYS) + pager_map_size);
-       pager_map.system_map = 1;
-#if defined(USERCONFIG)
-        userconfig();
-       cninit();               /* the preferred console may have changed */
-#endif
-       kprintf("avail memory = %u (%uK bytes)\n", ptoa(vmstats.v_free_count),
-               ptoa(vmstats.v_free_count) / 1024);
-       bufinit();
-       vm_pager_bufferinit();
-#ifdef SMP
-       mp_start();
-       mp_announce();
-#endif
-       cpu_setregs();
-}
-
 /*
  * Determine i/o configuration for a machine.
  */
@@ -199,12 +121,6 @@ configure_first(void *dummy)
 static void
 configure(void *dummy)
 {
-        /*
-        * Final interrupt support acviation, then enable hardware interrupts.
-        */
-       MachIntrABI.finalize();
-       cpu_enable_intr();
-
        /*
         * This will configure all devices, generally starting with the
         * nexus (i386/i386/nexus.c).  The nexus ISA code explicitly
@@ -235,10 +151,49 @@ configure(void *dummy)
 static void
 configure_final(void *dummy)
 {
+       int i;
+
        cninit_finish();
 
-       if (bootverbose)
+       if (bootverbose) {
+#ifdef APIC_IO
+               imen_dump();
+#endif /* APIC_IO */
+
+#if JG
+               /*
+                * Print out the BIOS's idea of the disk geometries.
+                */
+               kprintf("BIOS Geometries:\n");
+               for (i = 0; i < N_BIOS_GEOM; i++) {
+                       unsigned long bios_geom;
+                       int max_cylinder, max_head, max_sector;
+
+                       bios_geom = bootinfo.bi_bios_geom[i];
+
+                       /*
+                        * XXX the bootstrap punts a 1200K floppy geometry
+                        * when the get-disk-geometry interrupt fails.  Skip
+                        * drives that have this geometry.
+                        */
+                       if (bios_geom == 0x4f010f)
+                               continue;
+
+                       kprintf(" %x:%08lx ", i, bios_geom);
+                       max_cylinder = bios_geom >> 16;
+                       max_head = (bios_geom >> 8) & 0xff;
+                       max_sector = bios_geom & 0xff;
+                       kprintf(
+               "0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n",
+                              max_cylinder, max_cylinder + 1,
+                              max_head, max_head + 1,
+                              max_sector, max_sector);
+               }
+               kprintf(" %d accounted for\n", bootinfo.bi_n_bios_used);
+
                kprintf("Device configuration finished.\n");
+#endif
+       }
 }
 
 #ifdef BOOTP
@@ -270,6 +225,8 @@ SYSINIT(cpu_rootconf, SI_SUB_ROOT_CONF, SI_ORDER_FIRST, cpu_rootconf, NULL)
 u_long bootdev = 0;            /* not a cdev_t - encoding is different */
 
 #if defined(FFS) && defined(FFS_ROOT)
+#define FDMAJOR        2
+#define FDUNITSHIFT     6
 
 /*
  * The boot code uses old block device major numbers to pass bootdev to
@@ -465,7 +422,6 @@ pxe_setup_nfsdiskless(void)
 {
        struct nfs_diskless     *nd = &nfs_diskless;
        struct ifnet            *ifp;
-       struct ifaddr           *ifa;
        struct sockaddr_dl      *sdl, ourdl;
        struct sockaddr_in      myaddr, netmask;
        char                    *cp;
@@ -487,13 +443,12 @@ pxe_setup_nfsdiskless(void)
                kprintf("PXE: no hardware address\n");
                return;
        }
-       ifa = NULL;
        ifp = TAILQ_FIRST(&ifnet);
        TAILQ_FOREACH(ifp, &ifnet, if_link) {
                struct ifaddr_container *ifac;
 
                TAILQ_FOREACH(ifac, &ifp->if_addrheads[mycpuid], ifa_link) {
-                       ifa = ifac->ifa;
+                       struct ifaddr *ifa = ifac->ifa;
 
                        if ((ifa->ifa_addr->sa_family == AF_LINK) &&
                            (sdl = ((struct sockaddr_dl *)ifa->ifa_addr))) {
index 6d194c3..3b5813f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
+ * Copyright (c) 2006-2008 The DragonFly Project.  All rights reserved.
  * 
  * This code is derived from software contributed to The DragonFly Project
  * by Matthew Dillon <dillon@backplane.com>
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/platform/pc64/amd64/console.c,v 1.2 2007/09/24 03:24:45 yanyh Exp $
+ * $DragonFly: src/sys/platform/pc64/amd64/console.c,v 1.3 2008/08/29 17:07:10 dillon Exp $
  */
 
 #include <sys/systm.h>
 
+#if JG
 /*
  * Global console locking functions
  */
@@ -48,3 +49,4 @@ void
 cons_unlock(void)
 {
 }
+#endif
diff --git a/sys/platform/pc64/amd64/cpu_regs.c b/sys/platform/pc64/amd64/cpu_regs.c
deleted file mode 100644 (file)
index 676a565..0000000
+++ /dev/null
@@ -1,1264 +0,0 @@
-/*-
- * Copyright (c) 1992 Terrence R. Lambert.
- * Copyright (C) 1994, David Greenman
- * Copyright (c) 1982, 1987, 1990, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * William Jolitz.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *     from: @(#)machdep.c     7.4 (Berkeley) 6/3/91
- * $FreeBSD: src/sys/i386/i386/machdep.c,v 1.385.2.30 2003/05/31 08:48:05 alc Exp $
- * $DragonFly: src/sys/platform/pc64/amd64/Attic/cpu_regs.c,v 1.6 2008/04/21 15:47:56 dillon Exp $
- */
-
-#include "use_ether.h"
-#include "use_npx.h"
-#include "use_isa.h"
-#include "opt_atalk.h"
-#include "opt_compat.h"
-#include "opt_ddb.h"
-#include "opt_directio.h"
-#include "opt_inet.h"
-#include "opt_ipx.h"
-#include "opt_msgbuf.h"
-#include "opt_swap.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/sysproto.h>
-#include <sys/signalvar.h>
-#include <sys/kernel.h>
-#include <sys/linker.h>
-#include <sys/malloc.h>
-#include <sys/proc.h>
-#include <sys/buf.h>
-#include <sys/reboot.h>
-#include <sys/mbuf.h>
-#include <sys/msgbuf.h>
-#include <sys/sysent.h>
-#include <sys/sysctl.h>
-#include <sys/vmmeter.h>
-#include <sys/bus.h>
-#include <sys/upcall.h>
-#include <sys/usched.h>
-#include <sys/reg.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <sys/lock.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_object.h>
-#include <vm/vm_page.h>
-#include <vm/vm_map.h>
-#include <vm/vm_pager.h>
-#include <vm/vm_extern.h>
-
-#include <sys/thread2.h>
-
-#include <sys/user.h>
-#include <sys/exec.h>
-#include <sys/cons.h>
-
-#include <ddb/ddb.h>
-
-#include <machine/cpu.h>
-#include <machine/clock.h>
-#include <machine/specialreg.h>
-#include <machine/md_var.h>
-#include <machine/pcb_ext.h>           /* pcb.h included via sys/user.h */
-#include <machine/globaldata.h>                /* CPU_prvspace */
-#include <machine/smp.h>
-#ifdef PERFMON
-#include <machine/perfmon.h>
-#endif
-#include <machine/cputypes.h>
-
-#include <bus/isa/rtc.h>
-/* #include <machine/vm86.h> */
-#include <sys/random.h>
-#include <sys/ptrace.h>
-#include <machine/sigframe.h>
-#include <unistd.h>            /* umtx_* functions */
-
-extern void dblfault_handler (void);
-
-#ifndef CPU_DISABLE_SSE
-static void set_fpregs_xmm (struct save87 *, struct savexmm *);
-static void fill_fpregs_xmm (struct savexmm *, struct save87 *);
-#endif /* CPU_DISABLE_SSE */
-#ifdef DIRECTIO
-extern void ffs_rawread_setup(void);
-#endif /* DIRECTIO */
-
-#ifdef SMP
-int64_t tsc_offsets[MAXCPU];
-#else
-int64_t tsc_offsets[1];
-#endif
-
-#if defined(SWTCH_OPTIM_STATS)
-extern int swtch_optim_stats;
-SYSCTL_INT(_debug, OID_AUTO, swtch_optim_stats,
-       CTLFLAG_RD, &swtch_optim_stats, 0, "");
-SYSCTL_INT(_debug, OID_AUTO, tlb_flush_count,
-       CTLFLAG_RD, &tlb_flush_count, 0, "");
-#endif
-
-static int
-sysctl_hw_physmem(SYSCTL_HANDLER_ARGS)
-{
-       int error = sysctl_handle_int(oidp, 0, ctob((int)Maxmem), req);
-       return (error);
-}
-
-SYSCTL_PROC(_hw, HW_PHYSMEM, physmem, CTLTYPE_INT|CTLFLAG_RD,
-       0, 0, sysctl_hw_physmem, "IU", "");
-
-static int
-sysctl_hw_usermem(SYSCTL_HANDLER_ARGS)
-{
-       int error = sysctl_handle_int(oidp, 0,
-               ctob((int)Maxmem - vmstats.v_wire_count), req);
-       return (error);
-}
-
-SYSCTL_PROC(_hw, HW_USERMEM, usermem, CTLTYPE_INT|CTLFLAG_RD,
-       0, 0, sysctl_hw_usermem, "IU", "");
-
-SYSCTL_ULONG(_hw, OID_AUTO, availpages, CTLFLAG_RD, &Maxmem, NULL, "");
-
-#if 0
-
-static int
-sysctl_machdep_msgbuf(SYSCTL_HANDLER_ARGS)
-{
-       int error;
-
-       /* Unwind the buffer, so that it's linear (possibly starting with
-        * some initial nulls).
-        */
-       error=sysctl_handle_opaque(oidp,msgbufp->msg_ptr+msgbufp->msg_bufr,
-               msgbufp->msg_size-msgbufp->msg_bufr,req);
-       if(error) return(error);
-       if(msgbufp->msg_bufr>0) {
-               error=sysctl_handle_opaque(oidp,msgbufp->msg_ptr,
-                       msgbufp->msg_bufr,req);
-       }
-       return(error);
-}
-
-SYSCTL_PROC(_machdep, OID_AUTO, msgbuf, CTLTYPE_STRING|CTLFLAG_RD,
-       0, 0, sysctl_machdep_msgbuf, "A","Contents of kernel message buffer");
-
-static int msgbuf_clear;
-
-static int
-sysctl_machdep_msgbuf_clear(SYSCTL_HANDLER_ARGS)
-{
-       int error;
-       error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2,
-               req);
-       if (!error && req->newptr) {
-               /* Clear the buffer and reset write pointer */
-               bzero(msgbufp->msg_ptr,msgbufp->msg_size);
-               msgbufp->msg_bufr=msgbufp->msg_bufx=0;
-               msgbuf_clear=0;
-       }
-       return (error);
-}
-
-SYSCTL_PROC(_machdep, OID_AUTO, msgbuf_clear, CTLTYPE_INT|CTLFLAG_RW,
-       &msgbuf_clear, 0, sysctl_machdep_msgbuf_clear, "I",
-       "Clear kernel message buffer");
-
-#endif
-
-/*
- * Send an interrupt to process.
- *
- * Stack is set up to allow sigcode stored
- * at top to call routine, followed by kcall
- * to sigreturn routine below.  After sigreturn
- * resets the signal mask, the stack, and the
- * frame pointer, it returns to the user
- * specified pc, psl.
- */
-
-extern int _ucodesel, _udatasel;
-void
-sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
-{
-       struct lwp *lp = curthread->td_lwp;
-       struct proc *p = lp->lwp_proc;
-       struct trapframe *regs;
-       struct sigacts *psp = p->p_sigacts;
-       struct sigframe sf, *sfp;
-       int oonstack;
-
-       regs = lp->lwp_md.md_regs;
-       oonstack = (lp->lwp_sigstk.ss_flags & SS_ONSTACK) ? 1 : 0;
-
-       /* save user context */
-       bzero(&sf, sizeof(struct sigframe));
-       sf.sf_uc.uc_sigmask = *mask;
-       sf.sf_uc.uc_stack = lp->lwp_sigstk;
-       sf.sf_uc.uc_mcontext.mc_onstack = oonstack;
-       /* bcopy(regs, &sf.sf_uc.uc_mcontext.mc_gs, sizeof(struct trapframe)); */
-
-       /* make the size of the saved context visible to userland */
-       sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); 
-
-       /* save mailbox pending state for syscall interlock semantics */
-       if (p->p_flag & P_MAILBOX)
-               sf.sf_uc.uc_mcontext.mc_flags |= PGEX_MAILBOX;
-
-
-       /* Allocate and validate space for the signal handler context. */
-        if ((lp->lwp_flag & LWP_ALTSTACK) != 0 && !oonstack &&
-           SIGISMEMBER(psp->ps_sigonstack, sig)) {
-               sfp = (struct sigframe *)(lp->lwp_sigstk.ss_sp +
-                   lp->lwp_sigstk.ss_size - sizeof(struct sigframe));
-               lp->lwp_sigstk.ss_flags |= SS_ONSTACK;
-       }
-       else
-               sfp = (struct sigframe *)regs->tf_rsp - 1;
-
-       /* Translate the signal is appropriate */
-       if (p->p_sysent->sv_sigtbl) {
-               if (sig <= p->p_sysent->sv_sigsize)
-                       sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
-       }
-
-       /* Build the argument list for the signal handler. */
-       sf.sf_signum = sig;
-       sf.sf_ucontext = (register_t)&sfp->sf_uc;
-       if (SIGISMEMBER(psp->ps_siginfo, sig)) {
-               /* Signal handler installed with SA_SIGINFO. */
-               sf.sf_siginfo = (register_t)&sfp->sf_si;
-               sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
-
-               /* fill siginfo structure */
-               sf.sf_si.si_signo = sig;
-               sf.sf_si.si_code = code;
-               sf.sf_si.si_addr = (void*)regs->tf_err;
-       }
-       else {
-               /* Old FreeBSD-style arguments. */
-               sf.sf_siginfo = code;
-               sf.sf_addr = regs->tf_err;
-               sf.sf_ahu.sf_handler = catcher;
-       }
-
-#if 0
-       /*
-        * If we're a vm86 process, we want to save the segment registers.
-        * We also change eflags to be our emulated eflags, not the actual
-        * eflags.
-        */
-       if (regs->tf_rflags & PSL_VM) {
-               struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
-               struct vm86_kernel *vm86 = &lp->lwp_thread->td_pcb->pcb_ext->ext_vm86;
-
-               sf.sf_uc.uc_mcontext.mc_gs = tf->tf_vm86_gs;
-               sf.sf_uc.uc_mcontext.mc_fs = tf->tf_vm86_fs;
-               sf.sf_uc.uc_mcontext.mc_es = tf->tf_vm86_es;
-               sf.sf_uc.uc_mcontext.mc_ds = tf->tf_vm86_ds;
-
-               if (vm86->vm86_has_vme == 0)
-                       sf.sf_uc.uc_mcontext.mc_eflags =
-                           (tf->tf_rflags & ~(PSL_VIF | PSL_VIP)) |
-                           (vm86->vm86_eflags & (PSL_VIF | PSL_VIP));
-
-               /*
-                * Clear PSL_NT to inhibit T_TSSFLT faults on return from
-                * syscalls made by the signal handler.  This just avoids
-                * wasting time for our lazy fixup of such faults.  PSL_NT
-                * does nothing in vm86 mode, but vm86 programs can set it
-                * almost legitimately in probes for old cpu types.
-                */
-               tf->tf_rflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP);
-       }
-#endif
-
-       /*
-        * Save the FPU state and reinit the FP unit
-        */
-       npxpush(&sf.sf_uc.uc_mcontext);
-
-       /*
-        * Copy the sigframe out to the user's stack.
-        */
-       if (copyout(&sf, sfp, sizeof(struct sigframe)) != 0) {
-               /*
-                * Something is wrong with the stack pointer.
-                * ...Kill the process.
-                */
-               sigexit(lp, SIGILL);
-       }
-
-       regs->tf_rsp = (int)sfp;
-       regs->tf_rip = PS_STRINGS - *(p->p_sysent->sv_szsigcode);
-
-       /*
-        * amd64 abi specifies that the direction flag must be cleared
-        * on function entry
-        */
-       regs->tf_rflags &= ~(PSL_T|PSL_D);
-
-       regs->tf_cs = _ucodesel;
-       /* regs->tf_ds = _udatasel;
-       regs->tf_es = _udatasel; */
-       if (regs->tf_trapno == T_PROTFLT) {
-               /* regs->tf_fs = _udatasel;
-               regs->tf_gs = _udatasel; */
-       }
-       regs->tf_ss = _udatasel;
-}
-
-/*
- * Sanitize the trapframe for a virtual kernel passing control to a custom
- * VM context.
- *
- * Allow userland to set or maintain PSL_RF, the resume flag.  This flag
- * basically controls whether the return PC should skip the first instruction
- * (as in an explicit system call) or re-execute it (as in an exception).
- */
-int
-cpu_sanitize_frame(struct trapframe *frame)
-{
-       frame->tf_cs = _ucodesel;
-#if 0
-       frame->tf_ds = _udatasel;
-       frame->tf_es = _udatasel;
-       frame->tf_fs = _udatasel;
-       frame->tf_gs = _udatasel;
-#endif
-       frame->tf_ss = _udatasel;
-       frame->tf_rflags &= (PSL_RF | PSL_USERCHANGE);
-       frame->tf_rflags |= PSL_RESERVED_DEFAULT | PSL_I;
-       return(0);
-}
-
-int
-cpu_sanitize_tls(struct savetls *tls)
-{
-        struct segment_descriptor *desc;
-        int i;
-
-        for (i = 0; i < NGTLS; ++i) {
-               desc = &tls->tls[i];
-               if (desc->sd_dpl == 0 && desc->sd_type == 0)
-                       continue;
-               if (desc->sd_def32 == 0)
-                       return(ENXIO);
-               if (desc->sd_type != SDT_MEMRWA)
-                       return(ENXIO);
-               if (desc->sd_dpl != SEL_UPL)
-                       return(ENXIO);
-               if (desc->sd_xx != 0 || desc->sd_p != 1)
-                       return(ENXIO);
-        }
-        return(0);
-}
-
-/*
- * sigreturn(ucontext_t *sigcntxp)
- *
- * System call to cleanup state after a signal
- * has been taken.  Reset signal mask and
- * stack state from context left by sendsig (above).
- * Return to previous pc and psl as specified by
- * context left by sendsig. Check carefully to
- * make sure that the user has not modified the
- * state to gain improper privileges.
- */
-#define        EFL_SECURE(ef, oef)     ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
-#define        CS_SECURE(cs)           (ISPL(cs) == SEL_UPL)
-
-int
-sys_sigreturn(struct sigreturn_args *uap)
-{
-       struct lwp *lp = curthread->td_lwp;
-       struct proc *p = lp->lwp_proc;
-       struct trapframe *regs;
-       ucontext_t ucp;
-       int cs;
-       int rflags;
-       int error;
-
-       error = copyin(uap->sigcntxp, &ucp, sizeof(ucp));
-       if (error)
-               return (error);
-
-       regs = lp->lwp_md.md_regs;
-       rflags = ucp.uc_mcontext.mc_rflags;
-
-#if 0
-       if (eflags & PSL_VM) {
-               struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
-               struct vm86_kernel *vm86;
-
-               /*
-                * if pcb_ext == 0 or vm86_inited == 0, the user hasn't
-                * set up the vm86 area, and we can't enter vm86 mode.
-                */
-               if (lp->lwp_thread->td_pcb->pcb_ext == 0)
-                       return (EINVAL);
-               vm86 = &lp->lwp_thread->td_pcb->pcb_ext->ext_vm86;
-               if (vm86->vm86_inited == 0)
-                       return (EINVAL);
-
-               /* go back to user mode if both flags are set */
-               if ((eflags & PSL_VIP) && (eflags & PSL_VIF))
-                       trapsignal(lp->lwp_proc, SIGBUS, 0);
-
-               if (vm86->vm86_has_vme) {
-                       eflags = (tf->tf_eflags & ~VME_USERCHANGE) |
-                           (eflags & VME_USERCHANGE) | PSL_VM;
-               } else {
-                       vm86->vm86_eflags = eflags;     /* save VIF, VIP */
-                       eflags = (tf->tf_eflags & ~VM_USERCHANGE) |                                         (eflags & VM_USERCHANGE) | PSL_VM;
-               }
-               bcopy(&ucp.uc_mcontext.mc_gs, tf, sizeof(struct trapframe));
-               tf->tf_eflags = eflags;
-               tf->tf_vm86_ds = tf->tf_ds;
-               tf->tf_vm86_es = tf->tf_es;
-               tf->tf_vm86_fs = tf->tf_fs;
-               tf->tf_vm86_gs = tf->tf_gs;
-               tf->tf_ds = _udatasel;
-               tf->tf_es = _udatasel;
-#if 0
-               tf->tf_fs = _udatasel;
-               tf->tf_gs = _udatasel;
-#endif
-       } else 
-#endif
-       {
-               /*
-                * Don't allow users to change privileged or reserved flags.
-                */
-               /*
-                * XXX do allow users to change the privileged flag PSL_RF.
-                * The cpu sets PSL_RF in tf_eflags for faults.  Debuggers
-                * should sometimes set it there too.  tf_eflags is kept in
-                * the signal context during signal handling and there is no
-                * other place to remember it, so the PSL_RF bit may be
-                * corrupted by the signal handler without us knowing.
-                * Corruption of the PSL_RF bit at worst causes one more or
-                * one less debugger trap, so allowing it is fairly harmless.
-                */
-               if (!EFL_SECURE(rflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
-                       kprintf("sigreturn: eflags = 0x%x\n", rflags);
-                       return(EINVAL);
-               }
-
-               /*
-                * Don't allow users to load a valid privileged %cs.  Let the
-                * hardware check for invalid selectors, excess privilege in
-                * other selectors, invalid %eip's and invalid %esp's.
-                */
-               cs = ucp.uc_mcontext.mc_cs;
-               if (!CS_SECURE(cs)) {
-                       kprintf("sigreturn: cs = 0x%x\n", cs);
-                       trapsignal(lp, SIGBUS, T_PROTFLT);
-                       return(EINVAL);
-               }
-               /* bcopy(&ucp.uc_mcontext.mc_gs, regs, sizeof(struct trapframe)); */
-       }
-
-       /*
-        * Restore the FPU state from the frame
-        */
-       npxpop(&ucp.uc_mcontext);
-
-       /*
-        * Merge saved signal mailbox pending flag to maintain interlock
-        * semantics against system calls.
-        */
-       if (ucp.uc_mcontext.mc_flags & PGEX_MAILBOX)
-               p->p_flag |= P_MAILBOX;
-
-       if (ucp.uc_mcontext.mc_onstack & 1)
-               lp->lwp_sigstk.ss_flags |= SS_ONSTACK;
-       else
-               lp->lwp_sigstk.ss_flags &= ~SS_ONSTACK;
-
-       lp->lwp_sigmask = ucp.uc_sigmask;
-       SIG_CANTMASK(lp->lwp_sigmask);
-       return(EJUSTRETURN);
-}
-
-/*
- * Stack frame on entry to function.  %eax will contain the function vector,
- * %ecx will contain the function data.  flags, ecx, and eax will have 
- * already been pushed on the stack.
- */
-struct upc_frame {
-       register_t      eax;
-       register_t      ecx;
-       register_t      edx;
-       register_t      flags;
-       register_t      oldip;
-};
-
-void
-sendupcall(struct vmupcall *vu, int morepending)
-{
-       struct lwp *lp = curthread->td_lwp;
-       struct trapframe *regs;
-       struct upcall upcall;
-       struct upc_frame upc_frame;
-       int     crit_count = 0;
-
-       /*
-        * If we are a virtual kernel running an emulated user process
-        * context, switch back to the virtual kernel context before
-        * trying to post the signal.
-        */
-       if (lp->lwp_vkernel && lp->lwp_vkernel->ve) {
-               lp->lwp_md.md_regs->tf_trapno = 0;
-               vkernel_trap(lp, lp->lwp_md.md_regs);
-       }
-
-       /*
-        * Get the upcall data structure
-        */
-       if (copyin(lp->lwp_upcall, &upcall, sizeof(upcall)) ||
-           copyin((char *)upcall.upc_uthread + upcall.upc_critoff, &crit_count, sizeof(int))
-       ) {
-               vu->vu_pending = 0;
-               kprintf("bad upcall address\n");
-               return;
-       }
-
-       /*
-        * If the data structure is already marked pending or has a critical
-        * section count, mark the data structure as pending and return 
-        * without doing an upcall.  vu_pending is left set.
-        */
-       if (upcall.upc_pending || crit_count >= vu->vu_pending) {
-               if (upcall.upc_pending < vu->vu_pending) {
-                       upcall.upc_pending = vu->vu_pending;
-                       copyout(&upcall.upc_pending, &lp->lwp_upcall->upc_pending,
-                               sizeof(upcall.upc_pending));
-               }
-               return;
-       }
-
-       /*
-        * We can run this upcall now, clear vu_pending.
-        *
-        * Bump our critical section count and set or clear the
-        * user pending flag depending on whether more upcalls are
-        * pending.  The user will be responsible for calling 
-        * upc_dispatch(-1) to process remaining upcalls.
-        */
-       vu->vu_pending = 0;
-       upcall.upc_pending = morepending;
-       crit_count += TDPRI_CRIT;
-       copyout(&upcall.upc_pending, &lp->lwp_upcall->upc_pending, 
-               sizeof(upcall.upc_pending));
-       copyout(&crit_count, (char *)upcall.upc_uthread + upcall.upc_critoff,
-               sizeof(int));
-
-       /*
-        * Construct a stack frame and issue the upcall
-        */
-       regs = lp->lwp_md.md_regs;
-       upc_frame.eax = regs->tf_rax;
-       upc_frame.ecx = regs->tf_rcx;
-       upc_frame.edx = regs->tf_rdx;
-       upc_frame.flags = regs->tf_rflags;
-       upc_frame.oldip = regs->tf_rip;
-       if (copyout(&upc_frame, (void *)(regs->tf_rsp - sizeof(upc_frame)),
-           sizeof(upc_frame)) != 0) {
-               kprintf("bad stack on upcall\n");
-       } else {
-               regs->tf_rax = (register_t)vu->vu_func;
-               regs->tf_rcx = (register_t)vu->vu_data;
-               regs->tf_rdx = (register_t)lp->lwp_upcall;
-               regs->tf_rip = (register_t)vu->vu_ctx;
-               regs->tf_rsp -= sizeof(upc_frame);
-       }
-}
-
-/*
- * fetchupcall occurs in the context of a system call, which means that
- * we have to return EJUSTRETURN in order to prevent eax and edx from
- * being overwritten by the syscall return value.
- *
- * if vu is not NULL we return the new context in %edx, the new data in %ecx,
- * and the function pointer in %eax.  
- */
-int
-fetchupcall (struct vmupcall *vu, int morepending, void *rsp)
-{
-       struct upc_frame upc_frame;
-       struct lwp *lp = curthread->td_lwp;
-       struct trapframe *regs;
-       int error;
-       struct upcall upcall;
-       int crit_count;
-
-       regs = lp->lwp_md.md_regs;
-
-       error = copyout(&morepending, &lp->lwp_upcall->upc_pending, sizeof(int));
-       if (error == 0) {
-           if (vu) {
-               /*
-                * This jumps us to the next ready context.
-                */
-               vu->vu_pending = 0;
-               error = copyin(lp->lwp_upcall, &upcall, sizeof(upcall));
-               crit_count = 0;
-               if (error == 0)
-                       error = copyin((char *)upcall.upc_uthread + upcall.upc_critoff, &crit_count, sizeof(int));
-               crit_count += TDPRI_CRIT;
-               if (error == 0)
-                       error = copyout(&crit_count, (char *)upcall.upc_uthread + upcall.upc_critoff, sizeof(int));
-               regs->tf_rax = (register_t)vu->vu_func;
-               regs->tf_rcx = (register_t)vu->vu_data;
-               regs->tf_rdx = (register_t)lp->lwp_upcall;
-               regs->tf_rip = (register_t)vu->vu_ctx;
-               regs->tf_rsp = (register_t)rsp;
-           } else {
-               /*
-                * This returns us to the originally interrupted code.
-                */
-               error = copyin(rsp, &upc_frame, sizeof(upc_frame));
-               regs->tf_rax = upc_frame.eax;
-               regs->tf_rcx = upc_frame.ecx;
-               regs->tf_rdx = upc_frame.edx;
-               regs->tf_rflags = (regs->tf_rflags & ~PSL_USERCHANGE) |
-                               (upc_frame.flags & PSL_USERCHANGE);
-               regs->tf_rip = upc_frame.oldip;
-               regs->tf_rsp = (register_t)((char *)rsp + sizeof(upc_frame));
-           }
-       }
-       if (error == 0)
-               error = EJUSTRETURN;
-       return(error);
-}
-
-/*
- * cpu_idle() represents the idle LWKT.  You cannot return from this function
- * (unless you want to blow things up!).  Instead we look for runnable threads
- * and loop or halt as appropriate.  Giant is not held on entry to the thread.
- *
- * The main loop is entered with a critical section held, we must release
- * the critical section before doing anything else.  lwkt_switch() will
- * check for pending interrupts due to entering and exiting its own 
- * critical section.
- *
- * Note on cpu_idle_hlt:  On an SMP system we rely on a scheduler IPI
- * to wake a HLTed cpu up.  However, there are cases where the idlethread
- * will be entered with the possibility that no IPI will occur and in such
- * cases lwkt_switch() sets TDF_IDLE_NOHLT.
- */
-static int     cpu_idle_hlt = 1;
-static int     cpu_idle_hltcnt;
-static int     cpu_idle_spincnt;
-SYSCTL_INT(_machdep, OID_AUTO, cpu_idle_hlt, CTLFLAG_RW,
-    &cpu_idle_hlt, 0, "Idle loop HLT enable");
-SYSCTL_INT(_machdep, OID_AUTO, cpu_idle_hltcnt, CTLFLAG_RW,
-    &cpu_idle_hltcnt, 0, "Idle loop entry halts");
-SYSCTL_INT(_machdep, OID_AUTO, cpu_idle_spincnt, CTLFLAG_RW,
-    &cpu_idle_spincnt, 0, "Idle loop entry spins");
-
-void
-cpu_idle(void)
-{
-       struct thread *td = curthread;
-       struct mdglobaldata *gd = mdcpu;
-
-       crit_exit();
-       KKASSERT(td->td_pri < TDPRI_CRIT);
-       for (;;) {
-               /*
-                * See if there are any LWKTs ready to go.
-                */
-               lwkt_switch();
-
-               /*
-                * The idle loop halts only if no threads are scheduleable
-                * and no signals have occured.
-                */
-               if (cpu_idle_hlt && !lwkt_runnable() &&
-                   (td->td_flags & TDF_IDLE_NOHLT) == 0) {
-                       splz();
-                       if (!lwkt_runnable()) {
-#ifdef DEBUGIDLE
-                               struct timeval tv1, tv2;
-                               gettimeofday(&tv1, NULL);
-#endif
-                               /* umtx_sleep(&gd->mi.gd_runqmask, 0, 1000000); */
-#ifdef DEBUGIDLE
-                               gettimeofday(&tv2, NULL);
-                               if (tv2.tv_usec - tv1.tv_usec +
-                                   (tv2.tv_sec - tv1.tv_sec) * 1000000 
-                                   > 500000) {
-                                       kprintf("cpu %d idlelock %08x %08x\n",
-                                               gd->mi.gd_cpuid,
-                                               gd->mi.gd_runqmask,
-                                               gd->gd_fpending);
-                               }
-#endif
-                       }
-#ifdef SMP
-                       else {
-                           __asm __volatile("pause");
-                       }
-#endif
-                       ++cpu_idle_hltcnt;
-               } else {
-                       td->td_flags &= ~TDF_IDLE_NOHLT;
-                       splz();
-#ifdef SMP
-                       /*__asm __volatile("sti; pause");*/
-                       __asm __volatile("pause");
-#else
-                       /*__asm __volatile("sti");*/
-#endif
-                       ++cpu_idle_spincnt;
-               }
-       }
-}
-
-#ifdef SMP
-
-/*
- * Called by the LWKT switch core with a critical section held if the only
- * schedulable thread needs the MP lock and we couldn't get it.  On
- * a real cpu we just spin in the scheduler.  In the virtual kernel
- * we sleep for a bit.
- */
-void
-cpu_mplock_contested(void)
-{
-       usleep(1000);
-}
-
-/*
- * Called by the spinlock code with or without a critical section held
- * when a spinlock is found to be seriously constested.
- */
-void
-cpu_spinlock_contested(void)
-{
-       usleep(1000);
-}
-
-#endif
-
-/*
- * Clear registers on exec
- */
-void
-exec_setregs(u_long entry, u_long stack, u_long ps_strings)
-{
-       struct thread *td = curthread;
-       struct lwp *lp = td->td_lwp;
-       struct trapframe *regs = lp->lwp_md.md_regs;
-       struct pcb *pcb = lp->lwp_thread->td_pcb;
-
-       /* was i386_user_cleanup() in NetBSD */
-       user_ldt_free(pcb);
-  
-       bzero((char *)regs, sizeof(struct trapframe));
-       regs->tf_rip = entry;
-       regs->tf_rsp = stack;
-       regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T);
-       regs->tf_ss = 0;
-       /* regs->tf_ds = 0;
-       regs->tf_es = 0;
-       regs->tf_fs = 0;
-       regs->tf_gs = 0; */
-       regs->tf_cs = 0;
-
-       /* PS_STRINGS value for BSD/OS binaries.  It is 0 for non-BSD/OS. */
-       regs->tf_rbx = ps_strings;
-
-        /*
-         * Reset the hardware debug registers if they were in use.
-         * They won't have any meaning for the newly exec'd process.  
-         */
-        if (pcb->pcb_flags & PCB_DBREGS) {
-                pcb->pcb_dr0 = 0;
-                pcb->pcb_dr1 = 0;
-                pcb->pcb_dr2 = 0;
-                pcb->pcb_dr3 = 0;
-                pcb->pcb_dr6 = 0;
-                pcb->pcb_dr7 = 0;
-                if (pcb == td->td_pcb) {
-                       /*
-                        * Clear the debug registers on the running
-                        * CPU, otherwise they will end up affecting
-                        * the next process we switch to.
-                        */
-                       reset_dbregs();
-                }
-                pcb->pcb_flags &= ~PCB_DBREGS;
-        }
-
-       /*
-        * Initialize the math emulator (if any) for the current process.
-        * Actually, just clear the bit that says that the emulator has
-        * been initialized.  Initialization is delayed until the process
-        * traps to the emulator (if it is done at all) mainly because
-        * emulators don't provide an entry point for initialization.
-        */
-       /* pcb->pcb_flags &= ~FP_SOFTFP; */
-
-       /*
-        * note: do not set CR0_TS here.  npxinit() must do it after clearing
-        * gd_npxthread.  Otherwise a preemptive interrupt thread may panic
-        * in npxdna().
-        */
-       crit_enter();
-#if 0
-       load_cr0(rcr0() | CR0_MP);
-#endif
-
-#if NNPX > 0
-       /* Initialize the npx (if any) for the current process. */
-       npxinit(__INITIAL_NPXCW__);
-#endif
-       crit_exit();
-
-       /*
-        * note: linux emulator needs edx to be 0x0 on entry, which is
-        * handled in execve simply by setting the 64 bit syscall
-        * return value to 0.
-        */
-}
-
-void
-cpu_setregs(void)
-{
-#if 0
-       unsigned int cr0;
-
-       cr0 = rcr0();
-       cr0 |= CR0_NE;                  /* Done by npxinit() */
-       cr0 |= CR0_MP | CR0_TS;         /* Done at every execve() too. */
-       cr0 |= CR0_WP | CR0_AM;
-       load_cr0(cr0);
-       load_gs(_udatasel);
-#endif
-}
-
-static int
-sysctl_machdep_adjkerntz(SYSCTL_HANDLER_ARGS)
-{
-       int error;
-       error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2,
-               req);
-       if (!error && req->newptr)
-               resettodr();
-       return (error);
-}
-
-SYSCTL_PROC(_machdep, CPU_ADJKERNTZ, adjkerntz, CTLTYPE_INT|CTLFLAG_RW,
-       &adjkerntz, 0, sysctl_machdep_adjkerntz, "I", "");
-
-extern u_long bootdev;         /* not a cdev_t - encoding is different */
-SYSCTL_ULONG(_machdep, OID_AUTO, guessed_bootdev,
-       CTLFLAG_RD, &bootdev, 0, "Boot device (not in cdev_t format)");
-
-/*
- * Initialize 386 and configure to run kernel
- */
-
-/*
- * Initialize segments & interrupt table
- */
-
-extern  struct user *proc0paddr;
-
-#if 0
-
-extern inthand_t
-       IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
-       IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(fpusegm),
-       IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
-       IDTVEC(page), IDTVEC(mchk), IDTVEC(fpu), IDTVEC(align),
-       IDTVEC(xmm), IDTVEC(syscall),
-       IDTVEC(rsvd0);
-extern inthand_t
-       IDTVEC(int0x80_syscall);
-
-#endif
-
-#ifdef DEBUG_INTERRUPTS
-extern inthand_t *Xrsvdary[256];
-#endif
-
-int
-ptrace_set_pc(struct lwp *lp, unsigned long addr)
-{
-       lp->lwp_md.md_regs->tf_rip = addr;
-       return (0);
-}
-
-int
-ptrace_single_step(struct lwp *lp)
-{
-       lp->lwp_md.md_regs->tf_rflags |= PSL_T;
-       return (0);
-}
-
-int
-fill_regs(struct lwp *lp, struct reg *regs)
-{
-       struct trapframe *tp;
-
-       tp = lp->lwp_md.md_regs;
-       /* regs->r_gs = tp->tf_gs;
-       regs->r_fs = tp->tf_fs;
-       regs->r_es = tp->tf_es;
-       regs->r_ds = tp->tf_ds; */
-       regs->r_rdi = tp->tf_rdi;
-       regs->r_rsi = tp->tf_rsi;
-       regs->r_rbp = tp->tf_rbp;
-       regs->r_rbx = tp->tf_rbx;
-       regs->r_rdx = tp->tf_rdx;
-       regs->r_rcx = tp->tf_rcx;
-       regs->r_rax = tp->tf_rax;
-       regs->r_rip = tp->tf_rip;
-       regs->r_cs = tp->tf_cs;
-       regs->r_rflags = tp->tf_rflags;
-       regs->r_rsp = tp->tf_rsp;
-       regs->r_ss = tp->tf_ss;
-       return (0);
-}
-
-int
-set_regs(struct lwp *lp, struct reg *regs)
-{
-       struct trapframe *tp;
-
-       tp = lp->lwp_md.md_regs;
-       if (!EFL_SECURE(regs->r_rflags, tp->tf_rflags) ||
-           !CS_SECURE(regs->r_cs))
-               return (EINVAL);
-       /* tp->tf_gs = regs->r_gs;
-       tp->tf_fs = regs->r_fs;
-       tp->tf_es = regs->r_es;
-       tp->tf_ds = regs->r_ds; */
-       tp->tf_rdi = regs->r_rdi;
-       tp->tf_rsi = regs->r_rsi;
-       tp->tf_rbp = regs->r_rbp;
-       tp->tf_rbx = regs->r_rbx;
-       tp->tf_rdx = regs->r_rdx;
-       tp->tf_rcx = regs->r_rcx;
-       tp->tf_rax = regs->r_rax;
-       tp->tf_rip = regs->r_rip;
-       tp->tf_cs = regs->r_cs;
-       tp->tf_rflags = regs->r_rflags;
-       tp->tf_rsp = regs->r_rsp;
-       tp->tf_ss = regs->r_ss;
-       return (0);
-}
-
-#ifndef CPU_DISABLE_SSE
-static void
-fill_fpregs_xmm(struct savexmm *sv_xmm, struct save87 *sv_87)
-{
-       struct env87 *penv_87 = &sv_87->sv_env;
-       struct envxmm *penv_xmm = &sv_xmm->sv_env;
-       int i;
-
-       /* FPU control/status */
-       penv_87->en_cw = penv_xmm->en_cw;
-       penv_87->en_sw = penv_xmm->en_sw;
-       penv_87->en_tw = penv_xmm->en_tw;
-       penv_87->en_fip = penv_xmm->en_fip;
-       penv_87->en_fcs = penv_xmm->en_fcs;
-       penv_87->en_opcode = penv_xmm->en_opcode;
-       penv_87->en_foo = penv_xmm->en_foo;
-       penv_87->en_fos = penv_xmm->en_fos;
-
-       /* FPU registers */
-       for (i = 0; i < 8; ++i)
-               sv_87->sv_ac[i] = sv_xmm->sv_fp[i].fp_acc;
-
-       sv_87->sv_ex_sw = sv_xmm->sv_ex_sw;
-}
-
-static void
-set_fpregs_xmm(struct save87 *sv_87, struct savexmm *sv_xmm)
-{
-       struct env87 *penv_87 = &sv_87->sv_env;
-       struct envxmm *penv_xmm = &sv_xmm->sv_env;
-       int i;
-
-       /* FPU control/status */
-       penv_xmm->en_cw = penv_87->en_cw;
-       penv_xmm->en_sw = penv_87->en_sw;
-       penv_xmm->en_tw = penv_87->en_tw;
-       penv_xmm->en_fip = penv_87->en_fip;
-       penv_xmm->en_fcs = penv_87->en_fcs;
-       penv_xmm->en_opcode = penv_87->en_opcode;
-       penv_xmm->en_foo = penv_87->en_foo;
-       penv_xmm->en_fos = penv_87->en_fos;
-
-       /* FPU registers */
-       for (i = 0; i < 8; ++i)
-               sv_xmm->sv_fp[i].fp_acc = sv_87->sv_ac[i];
-
-       sv_xmm->sv_ex_sw = sv_87->sv_ex_sw;
-}
-#endif /* CPU_DISABLE_SSE */
-
-int
-fill_fpregs(struct lwp *lp, struct fpreg *fpregs)
-{
-#ifndef CPU_DISABLE_SSE
-       if (cpu_fxsr) {
-               fill_fpregs_xmm(&lp->lwp_thread->td_pcb->pcb_save.sv_xmm,
-                               (struct save87 *)fpregs);
-               return (0);
-       }
-#endif /* CPU_DISABLE_SSE */
-       bcopy(&lp->lwp_thread->td_pcb->pcb_save.sv_87, fpregs, sizeof *fpregs);
-       return (0);
-}
-
-int
-set_fpregs(struct lwp *lp, struct fpreg *fpregs)
-{
-#ifndef CPU_DISABLE_SSE
-       if (cpu_fxsr) {
-               set_fpregs_xmm((struct save87 *)fpregs,
-                              &lp->lwp_thread->td_pcb->pcb_save.sv_xmm);
-               return (0);
-       }
-#endif /* CPU_DISABLE_SSE */
-       bcopy(fpregs, &lp->lwp_thread->td_pcb->pcb_save.sv_87, sizeof *fpregs);
-       return (0);
-}
-
-int
-fill_dbregs(struct lwp *lp, struct dbreg *dbregs)
-{
-        if (lp == NULL) {
-                dbregs->dr[0] = rdr0();
-                dbregs->dr[1] = rdr1();
-                dbregs->dr[2] = rdr2();
-                dbregs->dr[3] = rdr3();
-                dbregs->dr[4] = rdr4();
-                dbregs->dr[5] = rdr5();
-                dbregs->dr[6] = rdr6();
-                dbregs->dr[7] = rdr7();
-        } else {
-               struct pcb *pcb;
-
-                pcb = lp->lwp_thread->td_pcb;
-                dbregs->dr[0] = pcb->pcb_dr0;
-                dbregs->dr[1] = pcb->pcb_dr1;
-                dbregs->dr[2] = pcb->pcb_dr2;
-                dbregs->dr[3] = pcb->pcb_dr3;
-                dbregs->dr[4] = 0;
-                dbregs->dr[5] = 0;
-                dbregs->dr[6] = pcb->pcb_dr6;
-                dbregs->dr[7] = pcb->pcb_dr7;
-        }
-       return (0);
-}
-
-int
-set_dbregs(struct lwp *lp, struct dbreg *dbregs)
-{
-       if (lp == NULL) {
-               load_dr0(dbregs->dr[0]);
-               load_dr1(dbregs->dr[1]);
-               load_dr2(dbregs->dr[2]);
-               load_dr3(dbregs->dr[3]);
-               load_dr4(dbregs->dr[4]);
-               load_dr5(dbregs->dr[5]);
-               load_dr6(dbregs->dr[6]);
-               load_dr7(dbregs->dr[7]);
-       } else {
-               struct pcb *pcb;
-               struct ucred *ucred;
-               int i;
-               uint32_t mask1, mask2;
-
-               /*
-                * Don't let an illegal value for dr7 get set.  Specifically,
-                * check for undefined settings.  Setting these bit patterns
-                * result in undefined behaviour and can lead to an unexpected
-                * TRCTRAP.
-                */
-               for (i = 0, mask1 = 0x3<<16, mask2 = 0x2<<16; i < 8; 
-                    i++, mask1 <<= 2, mask2 <<= 2)
-                       if ((dbregs->dr[7] & mask1) == mask2)
-                               return (EINVAL);
-               
-               pcb = lp->lwp_thread->td_pcb;
-               ucred = lp->lwp_proc->p_ucred;
-
-               /*
-                * Don't let a process set a breakpoint that is not within the
-                * process's address space.  If a process could do this, it
-                * could halt the system by setting a breakpoint in the kernel
-                * (if ddb was enabled).  Thus, we need to check to make sure
-                * that no breakpoints are being enabled for addresses outside
-                * process's address space, unless, perhaps, we were called by
-                * uid 0.
-                *
-                * XXX - what about when the watched area of the user's
-                * address space is written into from within the kernel
-                * ... wouldn't that still cause a breakpoint to be generated
-                * from within kernel mode?
-                */
-
-               if (suser_cred(ucred, 0) != 0) {
-                       if (dbregs->dr[7] & 0x3) {
-                               /* dr0 is enabled */
-                               if (dbregs->dr[0] >= VM_MAX_USER_ADDRESS)
-                                       return (EINVAL);
-                       }
-
-                       if (dbregs->dr[7] & (0x3<<2)) {
-                               /* dr1 is enabled */
-                               if (dbregs->dr[1] >= VM_MAX_USER_ADDRESS)
-                                       return (EINVAL);
-                       }
-
-                       if (dbregs->dr[7] & (0x3<<4)) {
-                               /* dr2 is enabled */
-                               if (dbregs->dr[2] >= VM_MAX_USER_ADDRESS)
-                                       return (EINVAL);
-                       }
-
-                       if (dbregs->dr[7] & (0x3<<6)) {
-                               /* dr3 is enabled */
-                               if (dbregs->dr[3] >= VM_MAX_USER_ADDRESS)
-                                       return (EINVAL);
-                       }
-               }
-
-               pcb->pcb_dr0 = dbregs->dr[0];
-               pcb->pcb_dr1 = dbregs->dr[1];
-               pcb->pcb_dr2 = dbregs->dr[2];
-               pcb->pcb_dr3 = dbregs->dr[3];
-               pcb->pcb_dr6 = dbregs->dr[6];
-               pcb->pcb_dr7 = dbregs->dr[7];
-
-               pcb->pcb_flags |= PCB_DBREGS;
-       }
-
-       return (0);
-}
-
-#if 0
-/*
- * Return > 0 if a hardware breakpoint has been hit, and the
- * breakpoint was in user space.  Return 0, otherwise.
- */
-int
-user_dbreg_trap(void)
-{
-        u_int32_t dr7, dr6; /* debug registers dr6 and dr7 */
-        u_int32_t bp;       /* breakpoint bits extracted from dr6 */
-        int nbp;            /* number of breakpoints that triggered */
-        caddr_t addr[4];    /* breakpoint addresses */
-        int i;
-        
-        dr7 = rdr7();
-        if ((dr7 & 0x000000ff) == 0) {
-                /*
-                 * all GE and LE bits in the dr7 register are zero,
-                 * thus the trap couldn't have been caused by the
-                 * hardware debug registers
-                 */
-                return 0;
-        }
-
-        nbp = 0;
-        dr6 = rdr6();
-        bp = dr6 & 0x0000000f;
-
-        if (!bp) {
-                /*
-                 * None of the breakpoint bits are set meaning this
-                 * trap was not caused by any of the debug registers
-                 */
-                return 0;
-        }
-
-        /*
-         * at least one of the breakpoints were hit, check to see
-         * which ones and if any of them are user space addresses
-         */
-
-        if (bp & 0x01) {
-                addr[nbp++] = (caddr_t)rdr0();
-        }
-        if (bp & 0x02) {
-                addr[nbp++] = (caddr_t)rdr1();
-        }
-        if (bp & 0x04) {
-                addr[nbp++] = (caddr_t)rdr2();
-        }
-        if (bp & 0x08) {
-                addr[nbp++] = (caddr_t)rdr3();
-        }
-
-        for (i=0; i<nbp; i++) {
-                if (addr[i] <
-                    (caddr_t)VM_MAX_USER_ADDRESS) {
-                        /*
-                         * addr[i] is in user space
-                         */
-                        return nbp;
-                }
-        }
-
-        /*
-         * None of the breakpoints are in user space.
-         */
-        return 0;
-}
-
-#endif
-
-
-#ifndef DDB
-void
-Debugger(const char *msg)
-{
-       kprintf("Debugger(\"%s\") called.\n", msg);
-}
-#endif /* no DDB */
-
index 73d4a91..9b9794d 100644 (file)
@@ -1,4 +1,35 @@
 /*
+ * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * --
+ *
  * Mach Operating System
  * Copyright (c) 1991,1990 Carnegie Mellon University
  * All Rights Reserved.
@@ -23,8 +54,7 @@
  * any improvements or extensions that they make and grant Carnegie the
  * rights to redistribute these changes.
  *
- * $FreeBSD: src/sys/i386/i386/db_disasm.c,v 1.23.2.1 2001/07/29 22:48:37 kris Exp $
- * $DragonFly: src/sys/platform/pc64/amd64/db_disasm.c,v 1.2 2007/09/24 03:24:45 yanyh Exp $
+ * $DragonFly: src/sys/platform/pc64/amd64/db_disasm.c,v 1.3 2008/08/29 17:07:10 dillon Exp $
  */
 
 /*
 #define        SDEP    7
 #define        NONE    8
 
+/*
+ * REX prefix and bits
+ */
+#define REX_B  1
+#define REX_X  2
+#define REX_R  4
+#define REX_W  8
+#define REX    0x40
+
 /*
  * Addressing modes
  */
 #define        Ib      21                      /* byte immediate, unsigned */
 #define        Ibs     22                      /* byte immediate, signed */
 #define        Iw      23                      /* word immediate, unsigned */
+#define        Ilq     24                      /* long/quad immediate, unsigned */
 #define        O       25                      /* direct address */
 #define        Db      26                      /* byte displacement from EIP */
 #define        Dl      27                      /* long displacement from EIP */
 #define        STI     32                      /* FP stack */
 #define        X       33                      /* extended FP op */
 #define        XA      34                      /* for 'fstcw %ax' */
-#define        El      35                      /* address, long size */
+#define        El      35                      /* address, long/quad size */
 #define        Ril     36                      /* long register in instruction */
 #define        Iba     37                      /* byte immediate, don't print if 0xa */
+#define        EL      38                      /* address, explicitly long size */
 
 struct inst {
        const char *    i_name;         /* name */
@@ -213,6 +254,26 @@ static const struct inst db_inst_0f3x[] = {
 /*3f*/ { "",      FALSE, NONE,  0,           0 },
 };
 
+static const struct inst db_inst_0f4x[] = {
+/*40*/ { "cmovo",  TRUE, NONE,  op2(E, R),   0 },
+/*41*/ { "cmovno", TRUE, NONE,  op2(E, R),   0 },
+/*42*/ { "cmovb",  TRUE, NONE,  op2(E, R),   0 },
+/*43*/ { "cmovnb", TRUE, NONE,  op2(E, R),   0 },
+/*44*/ { "cmovz",  TRUE, NONE,  op2(E, R),   0 },
+/*45*/ { "cmovnz", TRUE, NONE,  op2(E, R),   0 },
+/*46*/ { "cmovbe", TRUE, NONE,  op2(E, R),   0 },
+/*47*/ { "cmovnbe",TRUE, NONE,  op2(E, R),   0 },
+
+/*48*/ { "cmovs",  TRUE, NONE,  op2(E, R),   0 },
+/*49*/ { "cmovns", TRUE, NONE,  op2(E, R),   0 },
+/*4a*/ { "cmovp",  TRUE, NONE,  op2(E, R),   0 },
+/*4b*/ { "cmovnp", TRUE, NONE,  op2(E, R),   0 },
+/*4c*/ { "cmovl",  TRUE, NONE,  op2(E, R),   0 },
+/*4d*/ { "cmovnl", TRUE, NONE,  op2(E, R),   0 },
+/*4e*/ { "cmovle", TRUE, NONE,  op2(E, R),   0 },
+/*4f*/ { "cmovnle",TRUE, NONE,  op2(E, R),   0 },
+};
+
 static const struct inst db_inst_0f8x[] = {
 /*80*/ { "jo",    FALSE, NONE,  op1(Dl),     0 },
 /*81*/ { "jno",   FALSE, NONE,  op1(Dl),     0 },
@@ -317,7 +378,7 @@ static const struct inst * const db_inst_0f[] = {
        0,
        db_inst_0f2x,
        db_inst_0f3x,
-       0,
+       db_inst_0f4x,
        0,
        0,
        0,
@@ -585,23 +646,23 @@ static const struct inst db_inst_table[256] = {
 /*3e*/ { "",      FALSE, NONE,  0,          0 },
 /*3f*/ { "aas",   FALSE, NONE,  0,          0 },
 
-/*40*/ { "inc",   FALSE, LONG,  op1(Ri),    0 },
-/*41*/ { "inc",   FALSE, LONG,  op1(Ri),    0 },
-/*42*/ { "inc",   FALSE, LONG,  op1(Ri),    0 },
-/*43*/ { "inc",   FALSE, LONG,  op1(Ri),    0 },
-/*44*/ { "inc",   FALSE, LONG,  op1(Ri),    0 },
-/*45*/ { "inc",   FALSE, LONG,  op1(Ri),    0 },
-/*46*/ { "inc",   FALSE, LONG,  op1(Ri),    0 },
-/*47*/ { "inc",   FALSE, LONG,  op1(Ri),    0 },
-
-/*48*/ { "dec",   FALSE, LONG,  op1(Ri),    0 },
-/*49*/ { "dec",   FALSE, LONG,  op1(Ri),    0 },
-/*4a*/ { "dec",   FALSE, LONG,  op1(Ri),    0 },
-/*4b*/ { "dec",   FALSE, LONG,  op1(Ri),    0 },
-/*4c*/ { "dec",   FALSE, LONG,  op1(Ri),    0 },
-/*4d*/ { "dec",   FALSE, LONG,  op1(Ri),    0 },
-/*4e*/ { "dec",   FALSE, LONG,  op1(Ri),    0 },
-/*4f*/ { "dec",   FALSE, LONG,  op1(Ri),    0 },
+/*40*/ { "rex",   FALSE, NONE,  0,          0 },
+/*41*/ { "rex.b", FALSE, NONE,  0,          0 },
+/*42*/ { "rex.x", FALSE, NONE,  0,          0 },
+/*43*/ { "rex.xb", FALSE, NONE, 0,          0 },
+/*44*/ { "rex.r", FALSE, NONE,  0,          0 },
+/*45*/ { "rex.rb", FALSE, NONE, 0,          0 },
+/*46*/ { "rex.rx", FALSE, NONE, 0,          0 },
+/*47*/ { "rex.rxb", FALSE, NONE, 0,         0 },
+
+/*48*/ { "rex.w", FALSE, NONE,  0,          0 },
+/*49*/ { "rex.wb", FALSE, NONE, 0,          0 },
+/*4a*/ { "rex.wx", FALSE, NONE, 0,          0 },
+/*4b*/ { "rex.wxb", FALSE, NONE, 0,         0 },
+/*4c*/ { "rex.wr", FALSE, NONE, 0,          0 },
+/*4d*/ { "rex.wrb", FALSE, NONE, 0,         0 },
+/*4e*/ { "rex.wrx", FALSE, NONE, 0,         0 },
+/*4f*/ { "rex.wrxb", FALSE, NONE, 0,        0 },
 
 /*50*/ { "push",  FALSE, LONG,  op1(Ri),    0 },
 /*51*/ { "push",  FALSE, LONG,  op1(Ri),    0 },
@@ -624,7 +685,7 @@ static const struct inst db_inst_table[256] = {
 /*60*/ { "pusha", FALSE, LONG,  0,          0 },
 /*61*/ { "popa",  FALSE, LONG,  0,          0 },
 /*62*/  { "bound", TRUE,  LONG,  op2(E, R),  0 },
-/*63*/ { "arpl",  TRUE,  NONE,  op2(Rw,Ew), 0 },
+/*63*/ { "movslq",  TRUE,  NONE,  op2(EL,R), 0 },
 
 /*64*/ { "",      FALSE, NONE,  0,          0 },
 /*65*/ { "",      FALSE, NONE,  0,          0 },
@@ -721,14 +782,14 @@ static const struct inst db_inst_table[256] = {
 /*b6*/ { "mov",   FALSE, BYTE,  op2(I, Ri),  0 },
 /*b7*/ { "mov",   FALSE, BYTE,  op2(I, Ri),  0 },
 
-/*b8*/ { "mov",   FALSE, LONG,  op2(I, Ri),  0 },
-/*b9*/ { "mov",   FALSE, LONG,  op2(I, Ri),  0 },
-/*ba*/ { "mov",   FALSE, LONG,  op2(I, Ri),  0 },
-/*bb*/ { "mov",   FALSE, LONG,  op2(I, Ri),  0 },
-/*bc*/ { "mov",   FALSE, LONG,  op2(I, Ri),  0 },
-/*bd*/ { "mov",   FALSE, LONG,  op2(I, Ri),  0 },
-/*be*/ { "mov",   FALSE, LONG,  op2(I, Ri),  0 },
-/*bf*/ { "mov",   FALSE, LONG,  op2(I, Ri),  0 },
+/*b8*/ { "mov",   FALSE, LONG,  op2(Ilq, Ri),  0 },
+/*b9*/ { "mov",   FALSE, LONG,  op2(Ilq, Ri),  0 },
+/*ba*/ { "mov",   FALSE, LONG,  op2(Ilq, Ri),  0 },
+/*bb*/ { "mov",   FALSE, LONG,  op2(Ilq, Ri),  0 },
+/*bc*/ { "mov",   FALSE, LONG,  op2(Ilq, Ri),  0 },
+/*bd*/ { "mov",   FALSE, LONG,  op2(Ilq, Ri),  0 },
+/*be*/ { "mov",   FALSE, LONG,  op2(Ilq, Ri),  0 },
+/*bf*/ { "mov",   FALSE, LONG,  op2(Ilq, Ri),  0 },
 
 /*c0*/ { "",      TRUE,  BYTE,  op2(Ib, E),  db_Grp2 },
 /*c1*/ { "",      TRUE,  LONG,  op2(Ib, E),  db_Grp2 },
@@ -807,13 +868,13 @@ static const struct inst db_bad_inst =
        { "???",   FALSE, NONE,  0,           0 }
 ;
 
-#define        f_mod(byte)     ((byte)>>6)
-#define        f_reg(byte)     (((byte)>>3)&0x7)
-#define        f_rm(byte)      ((byte)&0x7)
+#define        f_mod(rex, byte)        ((byte)>>6)
+#define        f_reg(rex, byte)        ((((byte)>>3)&0x7) | (rex & REX_R ? 0x8 : 0x0))
+#define        f_rm(rex, byte)         (((byte)&0x7) | (rex & REX_B ? 0x8 : 0x0))
 
-#define        sib_ss(byte)    ((byte)>>6)
-#define        sib_index(byte) (((byte)>>3)&0x7)
-#define        sib_base(byte)  ((byte)&0x7)
+#define        sib_ss(rex, byte)       ((byte)>>6)
+#define        sib_index(rex, byte)    ((((byte)>>3)&0x7) | (rex & REX_X ? 0x8 : 0x0))
+#define        sib_base(rex, byte)     (((byte)&0x7) | (rex & REX_B ? 0x8 : 0x0))
 
 struct i_addr {
        int             is_reg; /* if reg, reg number is in 'disp' */
@@ -821,24 +882,27 @@ struct i_addr {
        const char *    base;
        const char *    index;
        int             ss;
-       int             defss;  /* default stack segment */
-};
-
-static const char * const db_index_reg_16[8] = {
-       "%bx,%si",
-       "%bx,%di",
-       "%bp,%si",
-       "%bp,%di",
-       "%si",
-       "%di",
-       "%bp",
-       "%bx"
 };
 
-static const char * const db_reg[3][8] = {
-       { "%al",  "%cl",  "%dl",  "%bl",  "%ah",  "%ch",  "%dh",  "%bh" },
-       { "%ax",  "%cx",  "%dx",  "%bx",  "%sp",  "%bp",  "%si",  "%di" },
-       { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi" }
+static const char * const db_reg[2][4][16] = {
+
+       {{"%al",  "%cl",  "%dl",  "%bl",  "%ah",  "%ch",  "%dh",  "%bh",
+         "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" },
+       { "%ax",  "%cx",  "%dx",  "%bx",  "%sp",  "%bp",  "%si",  "%di",
+         "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" },
+       { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
+         "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" },
+       { "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
+         "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" }},
+
+       {{"%al",  "%cl",  "%dl",  "%bl",  "%spl",  "%bpl",  "%sil",  "%dil",
+         "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" },
+       { "%ax",  "%cx",  "%dx",  "%bx",  "%sp",  "%bp",  "%si",  "%di",
+         "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" },
+       { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
+         "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" },
+       { "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
+         "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" }}
 };
 
 static const char * const db_seg_reg[8] = {
@@ -863,25 +927,29 @@ static const int db_lengths[] = {
        (loc) += (size);
 
 static db_addr_t
-               db_disasm_esc (db_addr_t loc, int inst, int short_addr,
-                                  int size, const char *seg);
-static void    db_print_address (const char *seg, int size,
-                                     struct i_addr *addrp);
+               db_disasm_esc(db_addr_t loc, int inst, int rex, int short_addr,
+                   int size, const char *seg);
+static void    db_print_address(const char *seg, int size, int rex,
+                   struct i_addr *addrp);
 static db_addr_t
-               db_read_address (db_addr_t loc, int short_addr,
-                                    int regmodrm, struct i_addr *addrp);
+               db_read_address(db_addr_t loc, int short_addr, int rex, int regmodrm,
+                   struct i_addr *addrp);
 
 /*
  * Read address at location and return updated location.
  */
 static db_addr_t
-db_read_address(db_addr_t loc, int short_addr, int regmodrm,
-               struct i_addr *addrp)
+db_read_address(loc, short_addr, rex, regmodrm, addrp)
+       db_addr_t       loc;
+       int             short_addr;
+       int             rex;
+       int             regmodrm;
+       struct i_addr * addrp;          /* out */
 {
-       int             mod, rm, sib, index, disp;
+       int             mod, rm, sib, index, disp, size, have_sib;
 
-       mod = f_mod(regmodrm);
-       rm  = f_rm(regmodrm);
+       mod = f_mod(rex, regmodrm);
+       rm  = f_rm(rex, regmodrm);
 
        if (mod == 3) {
            addrp->is_reg = TRUE;
@@ -890,104 +958,72 @@ db_read_address(db_addr_t loc, int short_addr, int regmodrm,
        }
        addrp->is_reg = FALSE;
        addrp->index = 0;
-       addrp->ss = 0;
-       addrp->defss = 0;
-
-       if (short_addr) {
-           if (mod != 3) {
-               switch(rm) {
-               case 0:
-               case 1:
-                   addrp->index = "%bx";
-                   break;
-               case 2:
-               case 3:
-                   addrp->index = "%bp";
-                   addrp->defss = 1;
-                   break;
-               case 6:
-                   if (mod == 1 || mod == 2)
-                       addrp->defss = 1;
-                   break;
-               }
-           }
-           switch (mod) {
-               case 0:
-                   if (rm == 6) {
-                       get_value_inc(disp, loc, 2, FALSE);
-                       addrp->disp = disp;
-                       addrp->base = 0;
-                   }
-                   else {
-                       addrp->disp = 0;
-                       addrp->base = db_index_reg_16[rm];
-                   }
-                   break;
-               case 1:
-                   get_value_inc(disp, loc, 1, TRUE);
-                   disp &= 0xFFFF;
-                   addrp->disp = disp;
-                   addrp->base = db_index_reg_16[rm];
-                   break;
-               case 2:
-                   get_value_inc(disp, loc, 2, FALSE);
-                   addrp->disp = disp;
-                   addrp->base = db_index_reg_16[rm];
-                   break;
-           }
-       } else {
-           if (mod != 3 && rm == 4) {
-               get_value_inc(sib, loc, 1, FALSE);
-               rm = sib_base(sib);
-               index = sib_index(sib);
-               if (index != 4)
-                   addrp->index = db_reg[LONG][index];
-               addrp->ss = sib_ss(sib);
-           }
-
-           switch (mod) {
-               case 0:
-                   if (rm == 5) {
-                       get_value_inc(addrp->disp, loc, 4, FALSE);
-                       addrp->base = 0;
-                   }
-                   else {
-                       addrp->disp = 0;
-                       addrp->base = db_reg[LONG][rm];
-                   }
-                   break;
 
-               case 1:
-                   get_value_inc(disp, loc, 1, TRUE);
-                   addrp->disp = disp;
-                   addrp->base = db_reg[LONG][rm];
-                   break;
+       if (short_addr)
+           size = LONG;
+       else
+           size = QUAD;
+
+       if ((rm & 0x7) == 4) {
+           get_value_inc(sib, loc, 1, FALSE);
+           rm = sib_base(rex, sib);
+           index = sib_index(rex, sib);
+           if (index != 4)
+               addrp->index = db_reg[1][size][index];
+           addrp->ss = sib_ss(rex, sib);
+           have_sib = 1;
+       } else
+           have_sib = 0;
 
-               case 2:
-                   get_value_inc(disp, loc, 4, FALSE);
-                   addrp->disp = disp;
-                   addrp->base = db_reg[LONG][rm];
-                   break;
-           }
+       switch (mod) {
+           case 0:
+               if (rm == 5) {
+                   get_value_inc(addrp->disp, loc, 4, FALSE);
+                   if (have_sib)
+                       addrp->base = 0;
+                   else if (short_addr)
+                       addrp->base = "%eip";
+                   else
+                       addrp->base = "%rip";
+               } else {
+                   addrp->disp = 0;
+                   addrp->base = db_reg[1][size][rm];
+               }
+               break;
+
+           case 1:
+               get_value_inc(disp, loc, 1, TRUE);
+               addrp->disp = disp;
+               addrp->base = db_reg[1][size][rm];
+               break;
+
+           case 2:
+               get_value_inc(disp, loc, 4, FALSE);
+               addrp->disp = disp;
+               addrp->base = db_reg[1][size][rm];
+               break;
        }
        return (loc);
 }
 
 static void
-db_print_address(const char *seg, int size, struct i_addr *addrp)
+db_print_address(seg, size, rex, addrp)
+       const char *    seg;
+       int             size;
+       int             rex;
+       struct i_addr * addrp;
 {
        if (addrp->is_reg) {
-           db_printf("%s", db_reg[size][addrp->disp]);
+           db_printf("%s", db_reg[rex != 0 ? 1 : 0][(size == LONG && (rex & REX_W)) ? QUAD : size][addrp->disp]);
            return;
        }
 
        if (seg) {
            db_printf("%s:", seg);
-       } else if (addrp->defss) {
-           db_printf("%%ss:");
        }
 
-       db_printsym((db_addr_t)addrp->disp, DB_STGY_ANY);
+       if (addrp->disp != 0 || (addrp->base == 0 && addrp->index == 0))
+               db_printsym((db_addr_t)addrp->disp, DB_STGY_ANY);
        if (addrp->base != 0 || addrp->index != 0) {
            db_printf("(");
            if (addrp->base)
@@ -1003,8 +1039,13 @@ db_print_address(const char *seg, int size, struct i_addr *addrp)
  * and return updated location.
  */
 static db_addr_t
-db_disasm_esc(db_addr_t loc, int inst, int short_addr, int size,
-             const char *seg)
+db_disasm_esc(loc, inst, rex, short_addr, size, seg)
+       db_addr_t       loc;
+       int             inst;
+       int             rex;
+       int             short_addr;
+       int             size;
+       const char *    seg;
 {
        int             regmodrm;
        const struct finst *    fp;
@@ -1013,8 +1054,8 @@ db_disasm_esc(db_addr_t loc, int inst, int short_addr, int size,
        const char *    name;
 
        get_value_inc(regmodrm, loc, 1, FALSE);
-       fp = &db_Esc_inst[inst - 0xd8][f_reg(regmodrm)];
-       mod = f_mod(regmodrm);
+       fp = &db_Esc_inst[inst - 0xd8][f_reg(rex, regmodrm)];
+       mod = f_mod(rex, regmodrm);
        if (mod != 3) {
            if (*fp->f_name == '\0') {
                db_printf("<bad instruction>");
@@ -1023,7 +1064,7 @@ db_disasm_esc(db_addr_t loc, int inst, int short_addr, int size,
            /*
             * Normal address modes.
             */
-           loc = db_read_address(loc, short_addr, regmodrm, &address);
+           loc = db_read_address(loc, short_addr, rex, regmodrm, &address);
            db_printf("%s", fp->f_name);
            switch(fp->f_size) {
                case SNGL:
@@ -1048,7 +1089,7 @@ db_disasm_esc(db_addr_t loc, int inst, int short_addr, int size,
                    break;
            }
            db_printf("\t");
-           db_print_address(seg, BYTE, &address);
+           db_print_address(seg, BYTE, rex, &address);
        }
        else {
            /*
@@ -1057,24 +1098,24 @@ db_disasm_esc(db_addr_t loc, int inst, int short_addr, int size,
            switch (fp->f_rrmode) {
                case op2(ST,STI):
                    name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
-                   db_printf("%s\t%%st,%%st(%d)",name,f_rm(regmodrm));
+                   db_printf("%s\t%%st,%%st(%d)",name,f_rm(rex, regmodrm));
                    break;
                case op2(STI,ST):
                    name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
-                   db_printf("%s\t%%st(%d),%%st",name, f_rm(regmodrm));
+                   db_printf("%s\t%%st(%d),%%st",name, f_rm(rex, regmodrm));
                    break;
                case op1(STI):
                    name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
-                   db_printf("%s\t%%st(%d)",name, f_rm(regmodrm));
+                   db_printf("%s\t%%st(%d)",name, f_rm(rex, regmodrm));
                    break;
                case op1(X):
-                   name = ((const char * const *)fp->f_rrname)[f_rm(regmodrm)];
+                   name = ((const char * const *)fp->f_rrname)[f_rm(rex, regmodrm)];
                    if (*name == '\0')
                        goto bad;
                    db_printf("%s", name);
                    break;
                case op1(XA):
-                   name = ((const char * const *)fp->f_rrname)[f_rm(regmodrm)];
+                   name = ((const char * const *)fp->f_rrname)[f_rm(rex, regmodrm)];
                    if (*name == '\0')
                        goto bad;
                    db_printf("%s\t%%ax", name);
@@ -1091,14 +1132,14 @@ db_disasm_esc(db_addr_t loc, int inst, int short_addr, int size,
 
 /*
  * Disassemble instruction at 'loc'.  'altfmt' specifies an
- * (optional) alternate format.  Return the address of the
- * start of the next instruction.
- *
- * If regs is non-null it may be used to obtain context, such as
- * whether we are in word or long mode.
+ * (optional) alternate format.  Return address of start of
+ * next instruction.
  */
 db_addr_t
-db_disasm(db_addr_t loc, boolean_t altfmt, db_regs_t *regs)
+db_disasm(loc, altfmt, dummy)
+       db_addr_t       loc;
+       boolean_t       altfmt;
+       db_regs_t       *dummy;
 {
        int     inst;
        int     size;
@@ -1108,29 +1149,22 @@ db_disasm(db_addr_t loc, boolean_t altfmt, db_regs_t *regs)
        const char *    i_name;
        int     i_size;
        int     i_mode;
+       int     rex = 0;
        int     regmodrm = 0;
        boolean_t       first;
        int     displ;
        int     prefix;
        int     imm;
        int     imm2;
+       long    imm64;
        int     len;
        struct i_addr   address;
 
        get_value_inc(inst, loc, 1, FALSE);
+       short_addr = FALSE;
+       size = LONG;
        seg = 0;
 
-#ifdef _GDT_ARRAY_PRESENT
-       if (regs && gdt[mycpu->gd_cpuid * NGDT + IDXSEL(regs->tf_cs & 0xFFFF)].sd.sd_def32 == 0) {
-               size = WORD;
-               short_addr = TRUE;
-       } else
-#endif
-       {
-               size = LONG;
-               short_addr = FALSE;
-       }
-
        /*
         * Get prefixes
         */
@@ -1174,13 +1208,17 @@ db_disasm(db_addr_t loc, boolean_t altfmt, db_regs_t *regs)
                    prefix = FALSE;
                    break;
            }
+           if (inst >= 0x40 && inst < 0x50) {
+               rex = inst;
+               prefix = TRUE;
+           }
            if (prefix) {
                get_value_inc(inst, loc, 1, FALSE);
            }
        } while (prefix);
 
        if (inst >= 0xd8 && inst <= 0xdf) {
-           loc = db_disasm_esc(loc, inst, short_addr, size, seg);
+           loc = db_disasm_esc(loc, inst, rex, short_addr, size, seg);
            db_printf("\n");
            return (loc);
        }
@@ -1200,7 +1238,7 @@ db_disasm(db_addr_t loc, boolean_t altfmt, db_regs_t *regs)
 
        if (ip->i_has_modrm) {
            get_value_inc(regmodrm, loc, 1, FALSE);
-           loc = db_read_address(loc, short_addr, regmodrm, &address);
+           loc = db_read_address(loc, short_addr, rex, regmodrm, &address);
        }
 
        i_name = ip->i_name;
@@ -1210,17 +1248,17 @@ db_disasm(db_addr_t loc, boolean_t altfmt, db_regs_t *regs)
        if (ip->i_extra == db_Grp1 || ip->i_extra == db_Grp2 ||
            ip->i_extra == db_Grp6 || ip->i_extra == db_Grp7 ||
            ip->i_extra == db_Grp8 || ip->i_extra == db_Grp9) {
-           i_name = ((const char * const *)ip->i_extra)[f_reg(regmodrm)];
+           i_name = ((const char * const *)ip->i_extra)[f_reg(rex, regmodrm)];
        }
        else if (ip->i_extra == db_Grp3) {
            ip = ip->i_extra;
-           ip = &ip[f_reg(regmodrm)];
+           ip = &ip[f_reg(rex, regmodrm)];
            i_name = ip->i_name;
            i_mode = ip->i_mode;
        }
        else if (ip->i_extra == db_Grp4 || ip->i_extra == db_Grp5) {
            ip = ip->i_extra;
-           ip = &ip[f_reg(regmodrm)];
+           ip = &ip[f_reg(rex, regmodrm)];
            i_name = ip->i_name;
            i_mode = ip->i_mode;
            i_size = ip->i_size;
@@ -1234,6 +1272,10 @@ db_disasm(db_addr_t loc, boolean_t altfmt, db_regs_t *regs)
        }
        else {
            db_printf("%s", i_name);
+           if ((inst >= 0x50 && inst <= 0x5f) || inst == 0x68 || inst == 0x6a) {
+               i_size = NONE;
+               db_printf("q");
+           }
            if (i_size != NONE) {
                if (i_size == BYTE) {
                    db_printf("b");
@@ -1245,8 +1287,12 @@ db_disasm(db_addr_t loc, boolean_t altfmt, db_regs_t *regs)
                }
                else if (size == WORD)
                    db_printf("w");
-               else
-                   db_printf("l");
+               else {
+                   if (rex & REX_W)
+                       db_printf("q");
+                   else
+                       db_printf("l");
+               }
            }
        }
        db_printf("\t");
@@ -1260,52 +1306,56 @@ db_disasm(db_addr_t loc, boolean_t altfmt, db_regs_t *regs)
            switch (i_mode & 0xFF) {
 
                case E:
-                   db_print_address(seg, size, &address);
+                   db_print_address(seg, size, rex, &address);
                    break;
 
                case Eind:
                    db_printf("*");
-                   db_print_address(seg, size, &address);
+                   db_print_address(seg, size, rex, &address);
                    break;
 
                case El:
-                   db_print_address(seg, LONG, &address);
+                   db_print_address(seg, (rex & REX_W) ? QUAD : LONG, rex, &address);
+                   break;
+
+               case EL:
+                   db_print_address(seg, LONG, 0, &address);
                    break;
 
                case Ew:
-                   db_print_address(seg, WORD, &address);
+                   db_print_address(seg, WORD, rex, &address);
                    break;
 
                case Eb:
-                   db_print_address(seg, BYTE, &address);
+                   db_print_address(seg, BYTE, rex, &address);
                    break;
 
                case R:
-                   db_printf("%s", db_reg[size][f_reg(regmodrm)]);
+                   db_printf("%s", db_reg[rex != 0 ? 1 : 0][(size == LONG && (rex & REX_W)) ? QUAD : size][f_reg(rex, regmodrm)]);
                    break;
 
                case Rw:
-                   db_printf("%s", db_reg[WORD][f_reg(regmodrm)]);
+                   db_printf("%s", db_reg[rex != 0 ? 1 : 0][WORD][f_reg(rex, regmodrm)]);
                    break;
 
                case Ri:
-                   db_printf("%s", db_reg[size][f_rm(inst)]);
+                   db_printf("%s", db_reg[0][QUAD][f_rm(rex, inst)]);
                    break;
 
                case Ril:
-                   db_printf("%s", db_reg[LONG][f_rm(inst)]);
+                   db_printf("%s", db_reg[rex != 0 ? 1 : 0][(rex & REX_R) ? QUAD : LONG][f_rm(rex, inst)]);
                    break;
 
                case S:
-                   db_printf("%s", db_seg_reg[f_reg(regmodrm)]);
+                   db_printf("%s", db_seg_reg[f_reg(rex, regmodrm)]);
                    break;
 
                case Si:
-                   db_printf("%s", db_seg_reg[f_reg(inst)]);
+                   db_printf("%s", db_seg_reg[f_reg(rex, inst)]);
                    break;
 
                case A:
-                   db_printf("%s", db_reg[size][0]);   /* acc */
+                   db_printf("%s", db_reg[rex != 0 ? 1 : 0][size][0]); /* acc */
                    break;
 
                case BX:
@@ -1325,23 +1375,23 @@ db_disasm(db_addr_t loc, boolean_t altfmt, db_regs_t *regs)
                case SI:
                    if (seg)
                        db_printf("%s:", seg);
-                   db_printf("(%s)", short_addr ? "%si" : "%esi");
+                   db_printf("(%s)", short_addr ? "%si" : "%rsi");
                    break;
 
                case DI:
-                   db_printf("%%es:(%s)", short_addr ? "%di" : "%edi");
+                   db_printf("%%es:(%s)", short_addr ? "%di" : "%rdi");
                    break;
 
                case CR:
-                   db_printf("%%cr%d", f_reg(regmodrm));
+                   db_printf("%%cr%d", f_reg(rex, regmodrm));
                    break;
 
                case DR:
-                   db_printf("%%dr%d", f_reg(regmodrm));
+                   db_printf("%%dr%d", f_reg(rex, regmodrm));
                    break;
 
                case TR:
-                   db_printf("%%tr%d", f_reg(regmodrm));
+                   db_printf("%%tr%d", f_reg(rex, regmodrm));
                    break;
 
                case I:
@@ -1351,7 +1401,7 @@ db_disasm(db_addr_t loc, boolean_t altfmt, db_regs_t *regs)
                    break;
 
                case Is:
-                   len = db_lengths[size];
+                   len = db_lengths[(size == LONG && (rex & REX_W)) ? QUAD : size];
                    get_value_inc(imm, loc, len, FALSE);
                    db_printf("$%+#r", imm);
                    break;
@@ -1379,6 +1429,12 @@ db_disasm(db_addr_t loc, boolean_t altfmt, db_regs_t *regs)
                    db_printf("$%#r", imm);
                    break;
 
+               case Ilq:
+                   len = db_lengths[rex & REX_W ? QUAD : LONG];
+                   get_value_inc(imm64, loc, len, FALSE);
+                   db_printf("$%#lr", imm64);
+                   break;
+
                case O:
                    len = (short_addr ? 2 : 4);
                    get_value_inc(displ, loc, len, FALSE);
@@ -1397,7 +1453,7 @@ db_disasm(db_addr_t loc, boolean_t altfmt, db_regs_t *regs)
                    break;
 
                case Dl:
-                   len = db_lengths[size];
+                   len = db_lengths[(size == LONG && (rex & REX_W)) ? QUAD : size];
                    get_value_inc(displ, loc, len, FALSE);
                    displ += loc;
                    if (size == WORD)
index c9dde76..c8dde74 100644 (file)
@@ -1,4 +1,35 @@
 /*
+ * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * --
+ *
  * Mach Operating System
  * Copyright (c) 1991,1990 Carnegie Mellon University
  * All Rights Reserved.
@@ -24,7 +55,7 @@
  * rights to redistribute these changes.
  *
  * $FreeBSD: src/sys/i386/i386/db_interface.c,v 1.48.2.1 2000/07/07 00:38:46 obrien Exp $
- * $DragonFly: src/sys/platform/pc64/amd64/db_interface.c,v 1.2 2007/09/24 03:24:45 yanyh Exp $
+ * $DragonFly: src/sys/platform/pc64/amd64/db_interface.c,v 1.3 2008/08/29 17:07:10 dillon Exp $
  */
 
 /*
@@ -50,6 +81,8 @@
 static jmp_buf *db_nofault = 0;
 extern jmp_buf db_jmpbuf;
 
+extern void    gdb_handle_exception (db_regs_t *, int, int);
+
 int    db_active;
 db_regs_t ddb_regs;
 
@@ -121,14 +154,6 @@ kdb_trap(int type, int code, struct amd64_saved_state *regs)
         */
        ddb_regs = *regs;
 
-       /*
-        * If in kernel mode, esp and ss are not saved, so dummy them up.
-        */
-       if (ISPL(regs->tf_cs) == 0) {
-           ddb_regs.tf_rsp = (int)&regs->tf_rsp;
-           ddb_regs.tf_ss = rss();
-       }
-
 #ifdef SMP
        db_printf("\nCPU%d stopping CPUs: 0x%08x\n", 
            mycpu->gd_cpuid, mycpu->gd_other_cpus);
@@ -148,7 +173,7 @@ kdb_trap(int type, int code, struct amd64_saved_state *regs)
            db_trap(type, code);
            cndbctl(FALSE);
        } else
-           /* gdb_handle_exception(&ddb_regs, type, code); */
+           gdb_handle_exception(&ddb_regs, type, code);
        db_active--;
        /* vcons_set_mode(0); */
        db_global_jmpbuf_valid = FALSE;
@@ -175,17 +200,22 @@ kdb_trap(int type, int code, struct amd64_saved_state *regs)
        regs->tf_rdx    = ddb_regs.tf_rdx;
        regs->tf_rbx    = ddb_regs.tf_rbx;
 
-       /*
-        * If in user mode, the saved ESP and SS were valid, restore them.
-        */
-       if (ISPL(regs->tf_cs)) {
-           regs->tf_rsp = ddb_regs.tf_rsp;
-           regs->tf_ss  = ddb_regs.tf_ss & 0xffff;
-       }
+       regs->tf_rsp    = ddb_regs.tf_rsp;
+       regs->tf_ss     = ddb_regs.tf_ss & 0xffff;
 
        regs->tf_rbp    = ddb_regs.tf_rbp;
        regs->tf_rsi    = ddb_regs.tf_rsi;
        regs->tf_rdi    = ddb_regs.tf_rdi;
+
+       regs->tf_r8     = ddb_regs.tf_r8;
+       regs->tf_r9     = ddb_regs.tf_r9;
+       regs->tf_r10    = ddb_regs.tf_r10;
+       regs->tf_r11    = ddb_regs.tf_r11;
+       regs->tf_r12    = ddb_regs.tf_r12;
+       regs->tf_r13    = ddb_regs.tf_r13;
+       regs->tf_r14    = ddb_regs.tf_r14;
+       regs->tf_r15    = ddb_regs.tf_r15;
+
        /* regs->tf_es     = ddb_regs.tf_es & 0xffff; */
        /* regs->tf_fs     = ddb_regs.tf_fs & 0xffff; */
        /* regs->tf_gs     = ddb_regs.tf_gs & 0xffff; */
index 77ece5d..d1077f2 100644 (file)
@@ -1,4 +1,35 @@
 /*
+ * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * --
+ *
  * Mach Operating System
  * Copyright (c) 1991,1990 Carnegie Mellon University
  * All Rights Reserved.
@@ -24,7 +55,7 @@
  * rights to redistribute these changes.
  *
  * $FreeBSD: src/sys/i386/i386/db_trace.c,v 1.35.2.3 2002/02/21 22:31:25 silby Exp $
- * $DragonFly: src/sys/platform/pc64/amd64/db_trace.c,v 1.2 2007/09/24 03:24:45 yanyh Exp $ 
+ * $DragonFly: src/sys/platform/pc64/amd64/db_trace.c,v 1.3 2008/08/29 17:07:10 dillon Exp $ 
  */
 
 #include <sys/param.h>
@@ -79,6 +110,14 @@ struct db_variable db_regs[] = {
        { "rdi",        &ddb_regs.tf_rdi,    FCN_NULL },
        { "rip",        &ddb_regs.tf_rip,    FCN_NULL },
        { "rfl",        &ddb_regs.tf_rflags, FCN_NULL },
+       { "r8",         &ddb_regs.tf_r8,     FCN_NULL },
+       { "r9",         &ddb_regs.tf_r9,     FCN_NULL },
+       { "r10",        &ddb_regs.tf_r10,    FCN_NULL },
+       { "r11",        &ddb_regs.tf_r11,    FCN_NULL },
+       { "r12",        &ddb_regs.tf_r12,    FCN_NULL },
+       { "r13",        &ddb_regs.tf_r13,    FCN_NULL },
+       { "r14",        &ddb_regs.tf_r14,    FCN_NULL },
+       { "r15",        &ddb_regs.tf_r15,    FCN_NULL },
        { "dr0",        NULL,                db_dr0 },
        { "dr1",        NULL,                db_dr1 },
        { "dr2",        NULL,                db_dr2 },
@@ -108,8 +147,8 @@ struct amd64_frame {
 
 static void    db_nextframe(struct amd64_frame **, db_addr_t *);
 static int     db_numargs(struct amd64_frame *);
-static void    db_print_stack_entry(const char *, int, char **, int *, db_addr_t);
-static void    dl_symbol_values(int callpc, const char **name);
+static void    db_print_stack_entry(const char *, int, char **, long *, db_addr_t);
+static void    dl_symbol_values(long callpc, const char **name);
 
 
 static char    *watchtype_str(int type);
@@ -127,6 +166,9 @@ void                db_md_list_watchpoints(void);
 static int
 db_numargs(struct amd64_frame *fp)
 {
+#if 1
+       return (0);     /* regparm, needs dwarf2 info */
+#else
        int     args;
 #if 0
        int     *argp;
@@ -152,21 +194,22 @@ db_numargs(struct amd64_frame *fp)
 #endif
        args = 5;
        return(args);
+#endif
 }
 
 static void
-db_print_stack_entry(const char *name, int narg, char **argnp, int *argp,
+db_print_stack_entry(const char *name, int narg, char **argnp, long *argp,
                     db_addr_t callpc)
 {
        db_printf("%s(", name);
        while (narg) {
                if (argnp)
                        db_printf("%s=", *argnp++);
-               db_printf("%r", db_get_value((int)argp, 4, FALSE));
+               db_printf("%r", db_get_value((long)argp, 8, FALSE));
                argp++;
                if (--narg != 0)
                        db_printf(",");
-       }
+       }
        db_printf(") at ");
        db_printsym(callpc, DB_STGY_PROC);
        db_printf("\n");
@@ -180,12 +223,12 @@ db_nextframe(struct amd64_frame **fp, db_addr_t *ip)
 {
        struct trapframe *tf;
        int frame_type;
-       int eip, esp, ebp;
+       long rip, rsp, rbp;
        db_expr_t offset;
        const char *sym, *name;
 
-       eip = db_get_value((int) &(*fp)->f_retaddr, 4, FALSE);
-       ebp = db_get_value((int) &(*fp)->f_frame, 4, FALSE);
+       rip = db_get_value((long) &(*fp)->f_retaddr, 8, FALSE);
+       rbp = db_get_value((long) &(*fp)->f_frame, 8, FALSE);
 
        /*
         * Figure out frame type.
@@ -193,9 +236,9 @@ db_nextframe(struct amd64_frame **fp, db_addr_t *ip)
 
        frame_type = NORMAL;
 
-       sym = db_search_symbol(eip, DB_STGY_ANY, &offset);
+       sym = db_search_symbol(rip, DB_STGY_ANY, &offset);
        db_symbol_values(sym, &name, NULL);
-       dl_symbol_values(eip, &name);
+       dl_symbol_values(rip, &name);
        if (name != NULL) {
                if (!strcmp(name, "calltrap")) {
                        frame_type = TRAP;
@@ -210,59 +253,59 @@ db_nextframe(struct amd64_frame **fp, db_addr_t *ip)
         * Normal frames need no special processing.
         */
        if (frame_type == NORMAL) {
-               *ip = (db_addr_t) eip;
-               *fp = (struct amd64_frame *) ebp;
+               *ip = (db_addr_t) rip;
+               *fp = (struct amd64_frame *) rbp;
                return;
        }
 
-       db_print_stack_entry(name, 0, 0, 0, eip);
+       db_print_stack_entry(name, 0, 0, 0, rip);
 
        /*
         * Point to base of trapframe which is just above the
         * current frame.
         */
-       tf = (struct trapframe *) ((int)*fp + 8);
+       tf = (struct trapframe *)((long)*fp + 16);
 
 #if 0
-       esp = (ISPL(tf->tf_cs) == SEL_UPL) ?  tf->tf_rsp : (int)&tf->tf_rsp;
+       rsp = (ISPL(tf->tf_cs) == SEL_UPL) ?  tf->tf_rsp : (long)&tf->tf_rsp;
 #endif
-       esp = (int)&tf->tf_rsp;
+       rsp = (long)&tf->tf_rsp;
 
        switch (frame_type) {
        case TRAP:
                {
-                       eip = tf->tf_rip;
-                       ebp = tf->tf_rbp;
+                       rip = tf->tf_rip;
+                       rbp = tf->tf_rbp;
                        db_printf(
-                   "--- trap %#r, eip = %#r, esp = %#r, ebp = %#r ---\n",
-                           tf->tf_trapno, eip, esp, ebp);
+                   "--- trap %#r, rip = %#r, rsp = %#r, rbp = %#r ---\n",
+                           tf->tf_trapno, rip, rsp, rbp);
                }
                break;
        case SYSCALL:
                {
-                       eip = tf->tf_rip;
-                       ebp = tf->tf_rbp;
+                       rip = tf->tf_rip;
+                       rbp = tf->tf_rbp;
                        db_printf(
-                   "--- syscall %#r, eip = %#r, esp = %#r, ebp = %#r ---\n",
-                           tf->tf_rax, eip, esp, ebp);
+                   "--- syscall %#r, rip = %#r, rsp = %#r, rbp = %#r ---\n",
+                           tf->tf_rax, rip, rsp, rbp);
                }
                break;
        case INTERRUPT:
-               tf = (struct trapframe *)((int)*fp + 16);
+               tf = (struct trapframe *)((long)*fp + 16);
                {
-                       eip = tf->tf_rip;
-                       ebp = tf->tf_rbp;
+                       rip = tf->tf_rip;
+                       rbp = tf->tf_rbp;
                        db_printf(
-                   "--- interrupt, eip = %#r, esp = %#r, ebp = %#r ---\n",
-                           eip, esp, ebp);
+                   "--- interrupt, rip = %#r, rsp = %#r, rbp = %#r ---\n",
+                           rip, rsp, rbp);
                }
                break;
        default:
                break;
        }
 
-       *ip = (db_addr_t) eip;
-       *fp = (struct amd64_frame *) ebp;
+       *ip = (db_addr_t) rip;
+       *fp = (struct amd64_frame *) rbp;
 }
 
 void
@@ -281,7 +324,7 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
        if (!have_addr) {
                frame = (struct amd64_frame *)BP_REGS(&ddb_regs);
                if (frame == NULL)
-                       frame = (struct amd64_frame *)(SP_REGS(&ddb_regs) - 4);
+                       frame = (struct amd64_frame *)(SP_REGS(&ddb_regs) - 8);
                callpc = PC_REGS(&ddb_regs);
        } else {
                /*
@@ -289,10 +332,10 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
                 * a convenience.
                 */
                frame = (struct amd64_frame *)addr;
-               for (i = 0; i < 4096; i += 4) {
+               for (i = 0; i < 4096; i += 8) {
                        struct amd64_frame *check;
 
-                       check = (struct amd64_frame *)db_get_value((int)((char *)&frame->f_frame + i), 4, FALSE);
+                       check = (struct amd64_frame *)db_get_value((long)((char *)&frame->f_frame + i), 8, FALSE);
                        if ((char *)check - (char *)frame >= 0 &&
                            (char *)check - (char *)frame < 4096
                        ) {
@@ -306,7 +349,7 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
                }
                frame = (void *)((char *)frame + i);
                db_printf("Trace beginning at frame %p\n", frame);
-               callpc = (db_addr_t)db_get_value((int)&frame->f_retaddr, 4, FALSE);
+               callpc = (db_addr_t)db_get_value((long)&frame->f_retaddr, 8, FALSE);
        }
 
        first = TRUE;
@@ -340,26 +383,26 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
                                int instr;
 
                                instr = db_get_value(callpc, 4, FALSE);
-                               if ((instr & 0x00ffffff) == 0x00e58955) {
-                                       /* pushl %ebp; movl %esp, %ebp */
+                               if ((instr & 0xffffffff) == 0xe5894855) {
+                                       /* pushq %rbp; movq %rsp, %rbp */
                                        actframe = (struct amd64_frame *)
-                                           (SP_REGS(&ddb_regs) - 4);
-                               } else if ((instr & 0x0000ffff) == 0x0000e589) {
-                                       /* movl %esp, %ebp */
+                                           (SP_REGS(&ddb_regs) - 8);
+                               } else if ((instr & 0xffffff) == 0xe58948) {
+                                       /* movq %rsp, %rbp */
                                        actframe = (struct amd64_frame *)
                                            SP_REGS(&ddb_regs);
                                        if (ddb_regs.tf_rbp == 0) {
                                                /* Fake caller's frame better. */
                                                frame = actframe;
                                        }
-                               } else if ((instr & 0x000000ff) == 0x000000c3) {
+                               } else if ((instr & 0xff) == 0xc3) {
                                        /* ret */
                                        actframe = (struct amd64_frame *)
-                                           (SP_REGS(&ddb_regs) - 4);
+                                           (SP_REGS(&ddb_regs) - 8);
                                } else if (offset == 0) {
                                        /* Probably a symbol in assembler code. */
                                        actframe = (struct amd64_frame *)
-                                           (SP_REGS(&ddb_regs) - 4);
+                                           (SP_REGS(&ddb_regs) - 8);
                                }
                        } else if (name != NULL &&
                                   strcmp(name, "fork_trampoline") == 0) {
@@ -386,7 +429,7 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
                if (actframe != frame) {
                        /* `frame' belongs to caller. */
                        callpc = (db_addr_t)
-                           db_get_value((int)&actframe->f_retaddr, 4, FALSE);
+                           db_get_value((long)&actframe->f_retaddr, 8, FALSE);
                        continue;
                }
 
@@ -399,10 +442,10 @@ db_stack_trace_cmd(db_expr_t addr, boolean_t have_addr, db_expr_t count,
 void
 db_print_backtrace(void)
 {
-       register_t  ebp;
+       register_t  rbp;
 
-       /* __asm __volatile("movl %%ebp, %0" : "=r" (ebp)); */
-       db_stack_trace_cmd(ebp, 1, -1, NULL);
+       __asm __volatile("movq %%rbp, %0" : "=r" (rbp));
+       db_stack_trace_cmd(rbp, 1, -1, NULL);
 }
 
 #define DB_DRX_FUNC(reg)                                               \
@@ -442,7 +485,7 @@ kamd64_set_watch(int watchnum, unsigned int watchaddr, int size, int access,
                else
                        return(-1);
        }
-       
+
        switch (access) {
        case DBREG_DR7_EXEC:
                size = 1; /* size must be 1 for an execution breakpoint */
@@ -455,7 +498,7 @@ kamd64_set_watch(int watchnum, unsigned int watchaddr, int size, int access,
        }
 
        /*
-        * we can watch a 1, 2, or 4 byte sized location
+        * we can watch a 1, 2, 4, or 8 byte sized location
         */
        switch (size) {
        case 1:
@@ -466,6 +509,8 @@ kamd64_set_watch(int watchnum, unsigned int watchaddr, int size, int access,
                break;
        case 4:
                mask = 0x03 << 2;
+       case 8:
+               mask = 0x02 << 2;
                break;
        default:
                return(-1);
@@ -491,10 +536,10 @@ kamd64_clr_watch(int watchnum, struct dbreg *d)
 {
        if (watchnum < 0 || watchnum >= 4)
                return(-1);
-       
+
        d->dr[7] &= ~((0x3 << (watchnum * 2)) | (0x0f << (watchnum * 4 + 16)));
        DBREG_DRX(d, watchnum) = 0;
-       
+
        return(0);
 }
 
@@ -507,19 +552,21 @@ db_md_set_watchpoint(db_expr_t addr, db_expr_t size)
        struct dbreg d;
        
        fill_dbregs(NULL, &d);
-       
+
        avail = 0;
-       for(i=0; i < 4; i++) {
+       for (i = 0; i < 4; i++) {
                if ((d.dr[7] & (3 << (i * 2))) == 0)
                        avail++;
        }
-       
-       if (avail * 4 < size)
+
+       if (avail * 8 < size)
                return(-1);
-       
+
        for (i=0; i < 4 && (size != 0); i++) {
                if ((d.dr[7] & (3 << (i * 2))) == 0) {
-                       if (size > 4)
+                       if (size >= 8 || (avail == 1 && size > 4))
+                               wsize = 8;
+                       else if (size > 2)
                                wsize = 4;
                        else
                                wsize = size;
@@ -539,12 +586,12 @@ db_md_set_watchpoint(db_expr_t addr, db_expr_t size)
 int
 db_md_clr_watchpoint(db_expr_t addr, db_expr_t size)
 {
-       int i;
        struct dbreg d;
+       int i;
 
        fill_dbregs(NULL, &d);
 
-       for(i=0; i<4; i++) {
+       for(i = 0; i < 4; i++) {
                if (d.dr[7] & (3 << (i * 2))) {
                        if ((DBREG_DRX((&d), i) >= addr) && 
                            (DBREG_DRX((&d), i) < addr + size))
@@ -583,7 +630,7 @@ db_md_list_watchpoints(void)
        db_printf("\nhardware watchpoints:\n");
        db_printf("  watch    status        type  len     address\n"
                  "  -----  --------  ----------  ---  ----------\n");
-       for (i=0; i < 4; i++) {
+       for (i = 0; i < 4; i++) {
                if (d.dr[7] & (0x03 << (i * 2))) {
                        unsigned type, len;
                        type = (d.dr[7] >> (16 + (i * 4))) & 3;
@@ -597,7 +644,7 @@ db_md_list_watchpoints(void)
        }
 
        db_printf("\ndebug register values:\n");
-       for (i=0; i < 8; i++)
+       for (i = 0; i < 8; i++)
                db_printf("  dr%d 0x%08x\n", i, DBREG_DRX((&d),i));
        db_printf("\n");
 }
@@ -607,7 +654,7 @@ db_md_list_watchpoints(void)
  */
 static
 void
-dl_symbol_values(int callpc, const char **name)
+dl_symbol_values(long callpc, const char **name)
 {
        Dl_info info;
 
diff --git a/sys/platform/pc64/amd64/exception.S b/sys/platform/pc64/amd64/exception.S
new file mode 100644 (file)
index 0000000..ae9c540
--- /dev/null
@@ -0,0 +1,512 @@
+/*-
+ * Copyright (c) 1989, 1990 William F. Jolitz.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 2007 The FreeBSD Foundation
+ * Copyright (c) 2008 The DragonFly Project.
+ * Copyright (c) 2008 Jordan Gordeev.
+ * All rights reserved.
+ *
+ * Portions of this software were developed by A. Joseph Koshy under
+ * sponsorship from the FreeBSD Foundation and Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ * $DragonFly: src/sys/platform/pc64/amd64/exception.S,v 1.1 2008/08/29 17:07:10 dillon Exp $
+ */
+
+#if JG
+#include "opt_atpic.h"
+#endif
+#include "opt_compat.h"
+
+#include <machine/asmacros.h>
+#include <machine/psl.h>
+#include <machine/trap.h>
+
+#include "assym.s"
+
+       .text
+
+/*****************************************************************************/
+/* Trap handling                                                             */
+/*****************************************************************************/
+/*
+ * Trap and fault vector routines.
+ *
+ * All traps are 'interrupt gates', SDT_SYSIGT.  An interrupt gate pushes
+ * state on the stack but also disables interrupts.  This is important for
+ * us for the use of the swapgs instruction.  We cannot be interrupted
+ * until the GS.base value is correct.  For most traps, we automatically
+ * then enable interrupts if the interrupted context had them enabled.
+ * This is equivalent to the i386 port's use of SDT_SYS386TGT.
+ *
+ * The cpu will push a certain amount of state onto the kernel stack for
+ * the current process.  See amd64/include/frame.h.  
+ * This includes the current RFLAGS (status register, which includes 
+ * the interrupt disable state prior to the trap), the code segment register,
+ * and the return instruction pointer are pushed by the cpu.  The cpu 
+ * will also push an 'error' code for certain traps.  We push a dummy 
+ * error code for those traps where the cpu doesn't in order to maintain 
+ * a consistent frame.  We also push a contrived 'trap number'.
+ *
+ * The cpu does not push the general registers, we must do that, and we 
+ * must restore them prior to calling 'iret'.  The cpu adjusts the %cs and
+ * %ss segment registers, but does not mess with %ds, %es, or %fs.  Thus we
+ * must load them with appropriate values for supervisor mode operation.
+ */
+
+MCOUNT_LABEL(user)
+MCOUNT_LABEL(btrap)
+
+/* Traps that we leave interrupts disabled for.. */
+#define        TRAP_NOEN(a)    \
+       subq $TF_RIP,%rsp; \
+       movq $(a),TF_TRAPNO(%rsp) ; \
+       movq $0,TF_ADDR(%rsp) ; \
+       movq $0,TF_ERR(%rsp) ; \
+       jmp alltraps_noen
+IDTVEC(dbg)
+       TRAP_NOEN(T_TRCTRAP)
+IDTVEC(bpt)
+       TRAP_NOEN(T_BPTFLT)
+
+/* Regular traps; The cpu does not supply tf_err for these. */
+#define        TRAP(a)  \
+       subq $TF_RIP,%rsp; \
+       movq $(a),TF_TRAPNO(%rsp) ; \
+       movq $0,TF_ADDR(%rsp) ; \
+       movq $0,TF_ERR(%rsp) ; \
+       jmp alltraps
+IDTVEC(div)
+       TRAP(T_DIVIDE)
+IDTVEC(ofl)
+       TRAP(T_OFLOW)
+IDTVEC(bnd)
+       TRAP(T_BOUND)
+IDTVEC(ill)
+       TRAP(T_PRIVINFLT)
+IDTVEC(dna)
+       TRAP(T_DNA)
+IDTVEC(fpusegm)
+       TRAP(T_FPOPFLT)
+IDTVEC(mchk)
+       TRAP(T_MCHK)
+IDTVEC(rsvd)
+       TRAP(T_RESERVED)
+IDTVEC(fpu)
+       TRAP(T_ARITHTRAP)
+IDTVEC(xmm)
+       TRAP(T_XMMFLT)
+
+/* This group of traps have tf_err already pushed by the cpu */
+#define        TRAP_ERR(a)     \
+       subq $TF_ERR,%rsp; \
+       movq $(a),TF_TRAPNO(%rsp) ; \
+       movq $0,TF_ADDR(%rsp) ; \
+       jmp alltraps
+IDTVEC(tss)
+       TRAP_ERR(T_TSSFLT)
+IDTVEC(missing)
+       TRAP_ERR(T_SEGNPFLT)
+IDTVEC(stk)
+       TRAP_ERR(T_STKFLT)
+IDTVEC(align)
+       TRAP_ERR(T_ALIGNFLT)
+
+       /*
+        * alltraps entry point.  Use swapgs if this is the first time in the
+        * kernel from userland.  Reenable interrupts if they were enabled
+        * before the trap.  This approximates SDT_SYS386TGT on the i386 port.
+        */
+
+       SUPERALIGN_TEXT
+       .globl  alltraps
+       .type   alltraps,@function
+alltraps:
+       testb   $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
+       jz      alltraps_testi          /* already running with kernel GS.base */
+       swapgs
+alltraps_testi:
+       testq   $PSL_I,TF_RFLAGS(%rsp)
+       jz      alltraps_pushregs
+       sti
+alltraps_pushregs:
+       movq    %rdi,TF_RDI(%rsp)
+alltraps_pushregs_no_rdi:
+       movq    %rsi,TF_RSI(%rsp)
+       movq    %rdx,TF_RDX(%rsp)
+       movq    %rcx,TF_RCX(%rsp)
+       movq    %r8,TF_R8(%rsp)
+       movq    %r9,TF_R9(%rsp)
+       movq    %rax,TF_RAX(%rsp)
+       movq    %rbx,TF_RBX(%rsp)
+       movq    %rbp,TF_RBP(%rsp)
+       movq    %r10,TF_R10(%rsp)
+       movq    %r11,TF_R11(%rsp)
+       movq    %r12,TF_R12(%rsp)
+       movq    %r13,TF_R13(%rsp)
+       movq    %r14,TF_R14(%rsp)
+       movq    %r15,TF_R15(%rsp)
+       FAKE_MCOUNT(TF_RIP(%rsp))
+       .globl  calltrap
+       .type   calltrap,@function
+calltrap:
+       movq    %rsp, %rdi
+       call    trap
+       MEXITCOUNT
+       jmp     doreti                  /* Handle any pending ASTs */
+
+       /*
+        * alltraps_noen entry point.  Unlike alltraps above, we want to
+        * leave the interrupts disabled.  This corresponds to
+        * SDT_SYS386IGT on the i386 port.
+        */
+       SUPERALIGN_TEXT
+       .globl  alltraps_noen
+       .type   alltraps_noen,@function
+alltraps_noen:
+       testb   $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
+       jz      alltraps_pushregs       /* already running with kernel GS.base */
+       swapgs
+       jmp     alltraps_pushregs
+
+IDTVEC(dblfault)
+       subq    $TF_ERR,%rsp
+       movq    $T_DOUBLEFLT,TF_TRAPNO(%rsp)
+       movq    $0,TF_ADDR(%rsp)
+       movq    $0,TF_ERR(%rsp)
+       movq    %rdi,TF_RDI(%rsp)
+       movq    %rsi,TF_RSI(%rsp)
+       movq    %rdx,TF_RDX(%rsp)
+       movq    %rcx,TF_RCX(%rsp)
+       movq    %r8,TF_R8(%rsp)
+       movq    %r9,TF_R9(%rsp)
+       movq    %rax,TF_RAX(%rsp)
+       movq    %rbx,TF_RBX(%rsp)
+       movq    %rbp,TF_RBP(%rsp)
+       movq    %r10,TF_R10(%rsp)
+       movq    %r11,TF_R11(%rsp)
+       movq    %r12,TF_R12(%rsp)
+       movq    %r13,TF_R13(%rsp)
+       movq    %r14,TF_R14(%rsp)
+       movq    %r15,TF_R15(%rsp)
+       testb   $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
+       jz      1f                      /* already running with kernel GS.base */
+       swapgs
+1:     movq    %rsp, %rdi
+       call    dblfault_handler
+2:     hlt
+       jmp     2b
+
+IDTVEC(page)
+       subq    $TF_ERR,%rsp
+       movq    $T_PAGEFLT,TF_TRAPNO(%rsp)
+       testb   $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
+       jz      1f                      /* already running with kernel GS.base */
+       swapgs
+1:
+       movq    %rdi,TF_RDI(%rsp)       /* free up a GP register */
+       movq    %cr2,%rdi               /* preserve %cr2 before ..  */
+       movq    %rdi,TF_ADDR(%rsp)      /* enabling interrupts. */
+       testq   $PSL_I,TF_RFLAGS(%rsp)
+       jz      alltraps_pushregs_no_rdi
+       sti
+       jmp     alltraps_pushregs_no_rdi
+
+       /*
+        * We have to special-case this one.  If we get a trap in doreti() at
+        * the iretq stage, we'll reenter with the wrong gs state.  We'll have
+        * to do a special the swapgs in this case even coming from the kernel.
+        * XXX linux has a trap handler for their equivalent of load_gs().
+        */
+IDTVEC(prot)
+       subq    $TF_ERR,%rsp
+       movq    $T_PROTFLT,TF_TRAPNO(%rsp)
+       movq    $0,TF_ADDR(%rsp)
+       movq    %rdi,TF_RDI(%rsp)       /* free up a GP register */
+       leaq    doreti_iret(%rip),%rdi
+       cmpq    %rdi,TF_RIP(%rsp)
+       je      2f                      /* kernel but with user gsbase!! */
+       testb   $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
+       jz      1f                      /* already running with kernel GS.base */
+2:
+       swapgs
+1:
+       testq   $PSL_I,TF_RFLAGS(%rsp)
+       jz      alltraps_pushregs_no_rdi
+       sti
+       jmp     alltraps_pushregs_no_rdi
+
+/*
+ * Fast syscall entry point.  We enter here with just our new %cs/%ss set,
+ * and the new privilige level.  We are still running on the old user stack
+ * pointer.  We have to juggle a few things around to find our stack etc.
+ * swapgs gives us access to our PCPU space only.
+ */
+IDTVEC(fast_syscall)
+       swapgs
+       movq    %rsp,PCPU(scratch_rsp)
+       movq    PCPU(rsp0),%rsp
+       /* Now emulate a trapframe. Make the 8 byte alignment odd for call. */
+       subq    $TF_SIZE,%rsp
+       /* defer TF_RSP till we have a spare register */
+       movq    %r11,TF_RFLAGS(%rsp)
+       movq    %rcx,TF_RIP(%rsp)       /* %rcx original value is in %r10 */
+       movq    PCPU(scratch_rsp),%r11  /* %r11 already saved */
+       movq    %r11,TF_RSP(%rsp)       /* user stack pointer */
+       sti
+       movq    $KUDSEL,TF_SS(%rsp)
+       movq    $KUCSEL,TF_CS(%rsp)
+       movq    $2,TF_ERR(%rsp)
+       movq    %rdi,TF_RDI(%rsp)       /* arg 1 */
+       movq    %rsi,TF_RSI(%rsp)       /* arg 2 */
+       movq    %rdx,TF_RDX(%rsp)       /* arg 3 */
+       movq    %r10,TF_RCX(%rsp)       /* arg 4 */
+       movq    %r8,TF_R8(%rsp)         /* arg 5 */
+       movq    %r9,TF_R9(%rsp)         /* arg 6 */
+       movq    %rax,TF_RAX(%rsp)       /* syscall number */
+       movq    %rbx,TF_RBX(%rsp)       /* C preserved */
+       movq    %rbp,TF_RBP(%rsp)       /* C preserved */
+       movq    %r12,TF_R12(%rsp)       /* C preserved */
+       movq    %r13,TF_R13(%rsp)       /* C preserved */
+       movq    %r14,TF_R14(%rsp)       /* C preserved */
+       movq    %r15,TF_R15(%rsp)       /* C preserved */
+       FAKE_MCOUNT(TF_RIP(%rsp))
+       movq    %rsp, %rdi
+       call    syscall2
+       /* JGXXX handle AST's? */
+       /* restore preserved registers */
+       MEXITCOUNT
+       movq    TF_RDI(%rsp),%rdi       /* bonus; preserve arg 1 */
+       movq    TF_RSI(%rsp),%rsi       /* bonus: preserve arg 2 */
+       movq    TF_RDX(%rsp),%rdx       /* return value 2 */
+       movq    TF_RAX(%rsp),%rax       /* return value 1 */
+       movq    TF_RBX(%rsp),%rbx       /* C preserved */
+       movq    TF_RBP(%rsp),%rbp       /* C preserved */
+       movq    TF_R12(%rsp),%r12       /* C preserved */
+       movq    TF_R13(%rsp),%r13       /* C preserved */
+       movq    TF_R14(%rsp),%r14       /* C preserved */
+       movq    TF_R15(%rsp),%r15       /* C preserved */
+       movq    TF_RFLAGS(%rsp),%r11    /* original %rflags */
+       movq    TF_RIP(%rsp),%rcx       /* original %rip */
+       movq    TF_RSP(%rsp),%r9        /* user stack pointer */
+       movq    %r9,%rsp                /* original %rsp */
+       swapgs
+       sysretq
+       MEXITCOUNT
+       jmp     doreti
+
+/*
+ * Here for CYA insurance, in case a "syscall" instruction gets
+ * issued from 32 bit compatability mode. MSR_CSTAR has to point
+ * to *something* if EFER_SCE is enabled.
+ */
+IDTVEC(fast_syscall32)
+       sysret
+
+/*
+ * NMI handling is special.
+ *
+ * First, NMIs do not respect the state of the processor's RFLAGS.IF
+ * bit and the NMI handler may be invoked at any time, including when
+ * the processor is in a critical section with RFLAGS.IF == 0.  In
+ * particular, this means that the processor's GS.base values could be
+ * inconsistent on entry to the handler, and so we need to read
+ * MSR_GSBASE to determine if a 'swapgs' is needed.  We use '%ebx', a
+ * C-preserved register, to remember whether to swap GS back on the
+ * exit path.
+ *
+ * Second, the processor treats NMIs specially, blocking further NMIs
+ * until an 'iretq' instruction is executed.  We therefore need to
+ * execute the NMI handler with interrupts disabled to prevent a
+ * nested interrupt from executing an 'iretq' instruction and
+ * inadvertently taking the processor out of NMI mode.
+ *
+ * Third, the NMI handler runs on its own stack (tss_ist1), shared
+ * with the double fault handler.
+ */
+
+IDTVEC(nmi)
+       subq    $TF_RIP,%rsp
+       movq    $(T_NMI),TF_TRAPNO(%rsp)
+       movq    $0,TF_ADDR(%rsp)
+       movq    $0,TF_ERR(%rsp)
+       movq    %rdi,TF_RDI(%rsp)
+       movq    %rsi,TF_RSI(%rsp)
+       movq    %rdx,TF_RDX(%rsp)
+       movq    %rcx,TF_RCX(%rsp)
+       movq    %r8,TF_R8(%rsp)
+       movq    %r9,TF_R9(%rsp)
+       movq    %rax,TF_RAX(%rsp)
+       movq    %rbx,TF_RBX(%rsp)
+       movq    %rbp,TF_RBP(%rsp)
+       movq    %r10,TF_R10(%rsp)
+       movq    %r11,TF_R11(%rsp)
+       movq    %r12,TF_R12(%rsp)
+       movq    %r13,TF_R13(%rsp)
+       movq    %r14,TF_R14(%rsp)
+       movq    %r15,TF_R15(%rsp)
+       xorl    %ebx,%ebx
+       testb   $SEL_RPL_MASK,TF_CS(%rsp)
+       jnz     nmi_needswapgs          /* we came from userland */
+       movl    $MSR_GSBASE,%ecx
+       rdmsr
+       cmpl    $VM_MAXUSER_ADDRESS >> 32,%edx
+       jae     nmi_calltrap            /* GS.base holds a kernel VA */
+nmi_needswapgs:
+       incl    %ebx
+       swapgs
+/* Note: this label is also used by ddb and gdb: */
+nmi_calltrap:
+       FAKE_MCOUNT(TF_RIP(%rsp))
+       movq    %rsp, %rdi
+       call    trap
+       MEXITCOUNT
+       testl   %ebx,%ebx
+       jz      nmi_restoreregs
+       swapgs
+nmi_restoreregs:
+       movq    TF_RDI(%rsp),%rdi
+       movq    TF_RSI(%rsp),%rsi
+       movq    TF_RDX(%rsp),%rdx
+       movq    TF_RCX(%rsp),%rcx
+       movq    TF_R8(%rsp),%r8
+       movq    TF_R9(%rsp),%r9
+       movq    TF_RAX(%rsp),%rax
+       movq    TF_RBX(%rsp),%rbx
+       movq    TF_RBP(%rsp),%rbp
+       movq    TF_R10(%rsp),%r10
+       movq    TF_R11(%rsp),%r11
+       movq    TF_R12(%rsp),%r12
+       movq    TF_R13(%rsp),%r13
+       movq    TF_R14(%rsp),%r14
+       movq    TF_R15(%rsp),%r15
+       addq    $TF_RIP,%rsp
+       iretq
+
+/*
+ * This function is what cpu_heavy_restore jumps to after a new process
+ * is created.  The LWKT subsystem switches while holding a critical
+ * section and we maintain that abstraction here (e.g. because 
+ * cpu_heavy_restore needs it due to PCB_*() manipulation), then get out of
+ * it before calling the initial function (typically fork_return()) and/or
+ * returning to user mode.
+ *
+ * The MP lock is held on entry, but for processes fork_return(esi)
+ * releases it.  'doreti' always runs without the MP lock.
+ */
+ENTRY(fork_trampoline)
+       movq    PCPU(curthread),%rax
+       subl    $TDPRI_CRIT,TD_PRI(%rax)
+
+       /*
+        * cpu_set_fork_handler intercepts this function call to
+        * have this call a non-return function to stay in kernel mode.
+        *
+        * initproc has its own fork handler, start_init(), which DOES
+        * return.
+        *
+        * %rbx - chaining function (typically fork_return)
+        * %r12 -> %rdi (argument)
+        * frame-> %rsi (trap frame)
+        *
+        *   void (func:rbx)(arg:rdi, trapframe:rsi)
+        */
+       movq    %rsp, %rsi              /* pass trapframe by reference */
+       movq    %r12, %rdi              /* arg1 */
+       call    *%rbx                   /* function */
+
+       /* cut from syscall */
+
+       sti
+       call    splz
+
+#if defined(INVARIANTS) && defined(SMP)
+       movq    PCPU(curthread),%rax
+       cmpl    $0,TD_MPCOUNT(%rax)
+       je      1f
+       movq    $pmsg4, %rdi
+       movl    TD_MPCOUNT(%rax), %rsi
+       movq    %rbx, %rdx
+       xorl    %eax, %eax
+       call    panic
+pmsg4:  .asciz "fork_trampoline mpcount %d after calling %p"
+       /* JG what's the purpose of this alignment and is it enough on amd64? */
+       .p2align 2
+1:
+#endif
+       /*
+        * Return via doreti to handle ASTs.
+        *
+        * trapframe is at the top of the stack.
+        */
+#if JG
+       pushl   $0                      /* cpl to restore */
+#endif
+       MEXITCOUNT
+       jmp     doreti
+
+/*
+ * To efficiently implement classification of trap and interrupt handlers
+ * for profiling, there must be only trap handlers between the labels btrap
+ * and bintr, and only interrupt handlers between the labels bintr and
+ * eintr.  This is implemented (partly) by including files that contain
+ * some of the handlers.  Before including the files, set up a normal asm
+ * environment so that the included files doen't need to know that they are
+ * included.
+ */
+
+#ifdef COMPAT_IA32
+       .data
+       .p2align 4
+       .text
+       SUPERALIGN_TEXT
+
+#include <amd64/ia32/ia32_exception.S>
+#endif
+
+       .data
+       .p2align 4
+       .text
+       SUPERALIGN_TEXT
+MCOUNT_LABEL(bintr)
+
+#if JG
+#include <amd64/amd64/apic_vector.S>
+#endif
+
+#ifdef DEV_ATPIC
+       .data
+       .p2align 4
+       .text
+       SUPERALIGN_TEXT
+
+#include <amd64/isa/atpic_vector.S>
+#endif
+
+       .text
+MCOUNT_LABEL(eintr)
+
diff --git a/sys/platform/pc64/amd64/exception.c b/sys/platform/pc64/amd64/exception.c
deleted file mode 100644 (file)
index fbe8865..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-
-/*
- * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
- * 
- * This code is derived from software contributed to The DragonFly Project
- * by Matthew Dillon <dillon@backplane.com>
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- * 3. Neither the name of The DragonFly Project nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific, prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
- * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * 
- * $DragonFly: src/sys/platform/pc64/amd64/Attic/exception.c,v 1.2 2007/09/24 03:24:45 yanyh Exp $
- */
-
-#include "opt_ddb.h"
-#include <sys/types.h>
-#include <sys/systm.h>
-#include <sys/reboot.h>
-#include <sys/kernel.h>
-#include <sys/kthread.h>
-#include <sys/reboot.h>
-#include <sys/signal.h>
-#include <ddb/ddb.h>
-
-#include <sys/thread2.h>
-
-#include <machine/trap.h>
-#include <machine/md_var.h>
-#include <machine/segments.h>
-#include <machine/cpu.h>
-
-int _ucodesel = LSEL(LUCODE_SEL, SEL_UPL);
-int _udatasel = LSEL(LUDATA_SEL, SEL_UPL);
-
-static void exc_segfault(int signo, siginfo_t *info, void *ctx);
-#ifdef DDB
-static void exc_debugger(int signo, siginfo_t *info, void *ctx);
-#endif
-
-/*
- * IPIs are 'fast' interrupts, so we deal with them directly from our
- * signal handler.
- */
-
-#ifdef SMP
-
-static
-void
-ipisig(int nada, siginfo_t *info, void *ctxp)
-{
-       ++mycpu->gd_intr_nesting_level;
-       if (curthread->td_pri < TDPRI_CRIT) {
-               curthread->td_pri += TDPRI_CRIT;
-               lwkt_process_ipiq();
-               curthread->td_pri -= TDPRI_CRIT;
-       } else {
-               need_ipiq();
-       }
-       --mycpu->gd_intr_nesting_level;
-}
-
-#endif
-
-void
-init_exceptions(void)
-{
-}
-
-/*
- * This function handles a segmentation fault.  
- *
- * XXX We assume that trapframe is a subset of ucontext.  It is as of
- *     this writing.
- */
-static void
-exc_segfault(int signo, siginfo_t *info, void *ctxp)
-{
-       ucontext_t *ctx = ctxp;
-
-#if 0
-       kprintf("CAUGHT SEGFAULT EIP %08x ERR %08x TRAPNO %d err %d\n",
-               ctx->uc_mcontext.mc_eip,
-               ctx->uc_mcontext.mc_err,
-               ctx->uc_mcontext.mc_trapno & 0xFFFF,
-               ctx->uc_mcontext.mc_trapno >> 16);
-       kern_trap((struct trapframe *)&ctx->uc_mcontext.mc_gs);
-#endif
-       splz();
-}
-
-#ifdef DDB
-
-static void
-exc_debugger(int signo, siginfo_t *info, void *ctx)
-{
-       Debugger("interrupt from console");
-}
-
-#endif
diff --git a/sys/platform/pc64/amd64/fork_tramp.s b/sys/platform/pc64/amd64/fork_tramp.s
deleted file mode 100644 (file)
index cdf93d2..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*-
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD: src/sys/i386/i386/exception.s,v 1.65.2.3 2001/08/15 01:23:49 peter Exp $
- * $DragonFly: src/sys/platform/pc64/amd64/Attic/fork_tramp.s,v 1.2 2007/09/24 03:24:45 yanyh Exp $
- */
-
-#include "use_npx.h"
-
-#include <machine/asmacros.h>
-#include <machine/segments.h>
-#include <machine/lock.h>
-#include <machine/psl.h>
-#include <machine/trap.h>
-
-#include "assym.s"
-
-       .text
-
-/*
- * This function is what cpu_heavy_restore jumps to after a new process
- * is created.  The LWKT subsystem switches while holding a critical
- * section and we maintain that abstraction here (e.g. because 
- * cpu_heavy_restore needs it due to PCB_*() manipulation), then get out of
- * it before calling the initial function (typically fork_return()) and/or
- * returning to user mode.
- *
- * The MP lock is held on entry, but for processes fork_return(esi)
- * releases it.  'doreti' always runs without the MP lock.
- */
-ENTRY(fork_trampoline)
-       movl    PCPU(curthread),%eax
-       subl    $TDPRI_CRIT,TD_PRI(%eax)
-
-       /*
-        * cpu_set_fork_handler intercepts this function call to
-        * have this call a non-return function to stay in kernel mode.
-        *
-        * initproc has its own fork handler, start_init(), which DOES
-        * return.
-        *
-        * The function (set in pcb_esi) gets passed two arguments,
-        * the primary parameter set in pcb_ebx and a pointer to the
-        * trapframe.
-        *   void (func)(int arg, struct trapframe *frame);
-        */
-#if 0
-       pushl   %esp                    /* pass frame by reference */
-       pushl   %ebx                    /* arg1 */
-       call    *%esi                   /* function */
-       addl    $8,%esp
-       /* cut from syscall */
-#endif
-       call    splz
-
-#if defined(INVARIANTS) && defined(SMP)
-       movl    PCPU(curthread),%eax
-       cmpl    $0,TD_MPCOUNT(%eax)
-       je      1f
-       pushl   %esi
-       pushl   TD_MPCOUNT(%eax)
-       pushl   $pmsg4
-       call    panic
-pmsg4:  .asciz "fork_trampoline mpcount %d after calling %p"
-       .p2align 2
-1:
-#endif
-       /*
-        * Return via doreti to handle ASTs.
-        */
-#if 0
-       MEXITCOUNT
-       pushl   $0              /* if_ppl */
-       pushl   $0              /* if_vec */
-       pushl   %esp            /* pass by reference */
-       call    go_user
-       /* NOT REACHED */
-#endif
-
index 1fe5005..64303b4 100644 (file)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 1982, 1990 The Regents of the University of California.
+ * Copyright (c) 2008 The DragonFly Project.
  * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
@@ -35,7 +36,7 @@
  *
  *     from: @(#)genassym.c    5.11 (Berkeley) 5/10/91
  * $FreeBSD: src/sys/i386/i386/genassym.c,v 1.86.2.3 2002/03/03 05:42:49 nyan Exp $
- * $DragonFly: src/sys/platform/pc64/amd64/genassym.c,v 1.1 2007/09/23 04:29:31 yanyh Exp $ 
+ * $DragonFly: src/sys/platform/pc64/amd64/genassym.c,v 1.2 2008/08/29 17:07:10 dillon Exp $ 
  */
 
 #include <sys/param.h>
 #include <machine/segments.h>
 #include <machine/sigframe.h>
 #include <machine/globaldata.h>
+#include <machine/specialreg.h>
 #include <machine/pcb.h>
 
 ASSYM(P_VMSPACE, offsetof(struct proc, p_vmspace));
 ASSYM(VM_PMAP, offsetof(struct vmspace, vm_pmap));
 ASSYM(PM_ACTIVE, offsetof(struct pmap, pm_active));
 
+ASSYM(LWP_VMSPACE, offsetof(struct lwp, lwp_vmspace));
 ASSYM(UPAGES, UPAGES);
 ASSYM(PAGE_SIZE, PAGE_SIZE);
 ASSYM(NPTEPG, NPTEPG);
@@ -86,20 +89,131 @@ ASSYM(PDRSHIFT, PDRSHIFT);
 ASSYM(USRSTACK, USRSTACK);
 ASSYM(KERNBASE,        KERNBASE);
 
+ASSYM(V_TRAP, offsetof(struct vmmeter, v_trap));
+ASSYM(V_SYSCALL, offsetof(struct vmmeter, v_syscall));
+ASSYM(V_SENDSYS, offsetof(struct vmmeter, v_sendsys));
+ASSYM(V_WAITSYS, offsetof(struct vmmeter, v_waitsys));
+ASSYM(V_INTR, offsetof(struct vmmeter, v_intr));
+ASSYM(V_FORWARDED_INTS, offsetof(struct vmmeter, v_forwarded_ints));
+ASSYM(V_FORWARDED_HITS, offsetof(struct vmmeter, v_forwarded_hits));
+ASSYM(V_FORWARDED_MISSES, offsetof(struct vmmeter, v_forwarded_misses));
+
 ASSYM(MAXCOMLEN, MAXCOMLEN);
 ASSYM(EFAULT, EFAULT);
 ASSYM(ENAMETOOLONG, ENAMETOOLONG);
 ASSYM(VM_MAXUSER_ADDRESS, VM_MAXUSER_ADDRESS);
+
 ASSYM(GD_CURTHREAD, offsetof(struct mdglobaldata, mi.gd_curthread));
+ASSYM(GD_CNT, offsetof(struct mdglobaldata, mi.gd_cnt));
+ASSYM(GD_CPUID, offsetof(struct mdglobaldata, mi.gd_cpuid));
+
+ASSYM(PCB_CR3, offsetof(struct pcb, pcb_cr3));
+ASSYM(PCB_R15, offsetof(struct pcb, pcb_r15));
+ASSYM(PCB_R14, offsetof(struct pcb, pcb_r14));
+ASSYM(PCB_R13, offsetof(struct pcb, pcb_r13));
+ASSYM(PCB_R12, offsetof(struct pcb, pcb_r12));
+ASSYM(PCB_RSI, offsetof(struct pcb, pcb_rsi));
+ASSYM(PCB_RBP, offsetof(struct pcb, pcb_rbp));
+ASSYM(PCB_RSP, offsetof(struct pcb, pcb_rsp));
+ASSYM(PCB_RBX, offsetof(struct pcb, pcb_rbx));
+ASSYM(PCB_RIP, offsetof(struct pcb, pcb_rip));
+ASSYM(PCB_EXT, offsetof(struct pcb, pcb_ext));
+ASSYM(PCB_FULLCTX, PCB_FULLCTX);
+ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
 ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
+ASSYM(PCB_FSBASE, offsetof(struct pcb, pcb_fsbase));
+ASSYM(PCB_GSBASE, offsetof(struct pcb, pcb_gsbase));
+
+ASSYM(TF_R15, offsetof(struct trapframe, tf_r15));
+ASSYM(TF_R14, offsetof(struct trapframe, tf_r14));
+ASSYM(TF_R13, offsetof(struct trapframe, tf_r13));
+ASSYM(TF_R12, offsetof(struct trapframe, tf_r12));
+ASSYM(TF_R11, offsetof(struct trapframe, tf_r11));
+ASSYM(TF_R10, offsetof(struct trapframe, tf_r10));
+ASSYM(TF_R9, offsetof(struct trapframe, tf_r9));
+ASSYM(TF_R8, offsetof(struct trapframe, tf_r8));
+ASSYM(TF_RDI, offsetof(struct trapframe, tf_rdi));
+ASSYM(TF_RSI, offsetof(struct trapframe, tf_rsi));
+ASSYM(TF_RBP, offsetof(struct trapframe, tf_rbp));
+ASSYM(TF_RBX, offsetof(struct trapframe, tf_rbx));
+ASSYM(TF_RDX, offsetof(struct trapframe, tf_rdx));
+ASSYM(TF_RCX, offsetof(struct trapframe, tf_rcx));
+ASSYM(TF_RAX, offsetof(struct trapframe, tf_rax));
+
+ASSYM(TF_TRAPNO, offsetof(struct trapframe, tf_trapno));
+ASSYM(TF_ADDR, offsetof(struct trapframe, tf_addr));
+ASSYM(TF_ERR, offsetof(struct trapframe, tf_err));
+ASSYM(TF_FLAGS, offsetof(struct trapframe, tf_flags));
+
+ASSYM(TF_RIP, offsetof(struct trapframe, tf_rip));
+ASSYM(TF_CS, offsetof(struct trapframe, tf_cs));
+ASSYM(TF_RFLAGS, offsetof(struct trapframe, tf_rflags));
+ASSYM(TF_RSP, offsetof(struct trapframe, tf_rsp));
+ASSYM(TF_SS, offsetof(struct trapframe, tf_ss));
+ASSYM(TF_SIZE, sizeof(struct trapframe));
 
 ASSYM(SIGF_HANDLER, offsetof(struct sigframe, sf_ahu.sf_handler));
 ASSYM(SIGF_UC, offsetof(struct sigframe, sf_uc));
 
+ASSYM(TD_PROC, offsetof(struct thread, td_proc));
+ASSYM(TD_LWP, offsetof(struct thread, td_lwp));
+ASSYM(TD_PCB, offsetof(struct thread, td_pcb));
+ASSYM(TD_SP, offsetof(struct thread, td_sp));
+ASSYM(TD_PRI, offsetof(struct thread, td_pri));
+ASSYM(TD_MACH, offsetof(struct thread, td_mach));
+ASSYM(TD_WCHAN, offsetof(struct thread, td_wchan));
+ASSYM(TD_NEST_COUNT, offsetof(struct thread, td_nest_count));
+#ifdef SMP
+ASSYM(TD_MPCOUNT, offsetof(struct thread, td_mpcount));
+#endif
+ASSYM(TD_FLAGS, offsetof(struct thread, td_flags));
+ASSYM(TDF_RUNNING, TDF_RUNNING);
+ASSYM(TDF_USINGFP, TDF_USINGFP);
+ASSYM(TDF_KERNELFP, TDF_KERNELFP);
+
+ASSYM(FIRST_SOFTINT, FIRST_SOFTINT);
+ASSYM(MDGLOBALDATA_BASEALLOC_PAGES, MDGLOBALDATA_BASEALLOC_PAGES);
+
+ASSYM(GD_PRIVATE_TSS, offsetof(struct mdglobaldata, gd_private_tss));
+ASSYM(GD_SCRATCH_RSP, offsetof(struct mdglobaldata, gd_scratch_rsp));
+ASSYM(GD_RSP0, offsetof(struct mdglobaldata, gd_rsp0));
+ASSYM(GD_USER_FS, offsetof(struct mdglobaldata, gd_user_fs));
+ASSYM(GD_USER_GS, offsetof(struct mdglobaldata, gd_user_gs));
+ASSYM(GD_INTR_NESTING_LEVEL, offsetof(struct mdglobaldata, mi.gd_intr_nesting_level));
+
+ASSYM(GD_FPENDING, offsetof(struct mdglobaldata, gd_fpending));
+ASSYM(GD_IPENDING, offsetof(struct mdglobaldata, gd_ipending));
+ASSYM(GD_SPENDING, offsetof(struct mdglobaldata, gd_spending));
+ASSYM(GD_COMMON_TSS, offsetof(struct mdglobaldata, gd_common_tss));
+ASSYM(GD_COMMON_TSSD, offsetof(struct mdglobaldata, gd_common_tssd));
+ASSYM(GD_TSS_GDT, offsetof(struct mdglobaldata, gd_tss_gdt));
+ASSYM(GD_NPXTHREAD, offsetof(struct mdglobaldata, gd_npxthread));
+ASSYM(GD_FPU_LOCK, offsetof(struct mdglobaldata, gd_fpu_lock));
+ASSYM(GD_SAVEFPU, offsetof(struct mdglobaldata, gd_savefpu));
+ASSYM(GD_OTHER_CPUS, offsetof(struct mdglobaldata, gd_other_cpus));
+ASSYM(GD_SS_EFLAGS, offsetof(struct mdglobaldata, gd_ss_eflags));
+ASSYM(GD_REQFLAGS, offsetof(struct mdglobaldata, mi.gd_reqflags));
+
+ASSYM(RQF_IPIQ, RQF_IPIQ);
+ASSYM(RQF_INTPEND, RQF_INTPEND);
+ASSYM(RQF_AST_OWEUPC, RQF_AST_OWEUPC);
+ASSYM(RQF_AST_SIGNAL, RQF_AST_SIGNAL);
+ASSYM(RQF_AST_USER_RESCHED, RQF_AST_USER_RESCHED);
+ASSYM(RQF_AST_LWKT_RESCHED, RQF_AST_LWKT_RESCHED);
+ASSYM(RQF_AST_UPCALL, RQF_AST_UPCALL);
+ASSYM(RQF_AST_MASK, RQF_AST_MASK);
+
 ASSYM(KCSEL, GSEL(GCODE_SEL, SEL_KPL));
 ASSYM(KDSEL, GSEL(GDATA_SEL, SEL_KPL));
+ASSYM(KUCSEL, GSEL(GUCODE_SEL, SEL_UPL));
+ASSYM(KUDSEL, GSEL(GUDATA_SEL, SEL_UPL));
+ASSYM(SEL_RPL_MASK, SEL_RPL_MASK);
 
-ASSYM(TD_PRI, offsetof(struct thread, td_pri));
+ASSYM(MSR_GSBASE, MSR_GSBASE);
+ASSYM(MSR_KGSBASE, MSR_KGSBASE);
+ASSYM(MSR_FSBASE, MSR_FSBASE);
+
+ASSYM(MACHINTR_INTREN, offsetof(struct machintr_abi, intren));
 
 ASSYM(TDPRI_CRIT, TDPRI_CRIT);
 ASSYM(TDPRI_INT_SUPPORT, TDPRI_INT_SUPPORT);
index 2e9583a..a6d594e 100644 (file)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) Peter Wemm <peter@netplex.com.au>
+ * Copyright (c) 2008 The DragonFly Project.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -24,7 +25,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/i386/globals.s,v 1.13.2.1 2000/05/16 06:58:06 dillon Exp $
- * $DragonFly: src/sys/platform/pc64/amd64/global.s,v 1.2 2007/09/24 03:24:45 yanyh Exp $
+ * $DragonFly: src/sys/platform/pc64/amd64/global.s,v 1.3 2008/08/29 17:07:10 dillon Exp $
  */
 
 #include <machine/asmacros.h>
@@ -41,6 +42,9 @@
         * segment.
         */
        .data
+       .globl  CPU_prvspace, lapic
+       .set    CPU_prvspace,(MPPTDI << PDRSHIFT)
+       .set    lapic,CPU_prvspace + (NPTEPG-1) * PAGE_SIZE
 
        .globl  globaldata
        .set    globaldata,0
        .globl  gd_CMAP1, gd_CMAP2, gd_CMAP3, gd_PMAP1
        .globl  gd_CADDR1, gd_CADDR2, gd_CADDR3, gd_PADDR1
        .globl  gd_spending, gd_ipending, gd_fpending
-       .globl  gd_cnt
+       .globl  gd_cnt, gd_private_tss
+       .globl  gd_scratch_rsp, gd_rsp0
+       .globl  gd_user_fs, gd_user_gs
 
        .set    gd_cpuid,globaldata + GD_CPUID
+       .set    gd_private_tss,globaldata + GD_PRIVATE_TSS
        .set    gd_other_cpus,globaldata + GD_OTHER_CPUS
        .set    gd_ss_eflags,globaldata + GD_SS_EFLAGS
        .set    gd_intr_nesting_level,globaldata + GD_INTR_NESTING_LEVEL
        .set    gd_ipending,globaldata + GD_IPENDING
        .set    gd_spending,globaldata + GD_SPENDING
        .set    gd_cnt,globaldata + GD_CNT
+       .set    gd_scratch_rsp,globaldata + GD_SCRATCH_RSP
+       .set    gd_rsp0,globaldata + GD_RSP0
+       .set    gd_user_fs,globaldata + GD_USER_FS
+       .set    gd_user_gs,globaldata + GD_USER_GS
 
index 5a63261..71a06ce 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
+ * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
  * 
  * This code is derived from software contributed to The DragonFly Project
  * by Matthew Dillon <dillon@backplane.com>
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/platform/pc64/amd64/globaldata.c,v 1.2 2007/09/24 03:24:45 yanyh Exp $
+ * $DragonFly: src/sys/platform/pc64/amd64/globaldata.c,v 1.3 2008/08/29 17:07:10 dillon Exp $
  */
 
 #include <sys/types.h>
@@ -46,6 +46,7 @@
 #include <machine/globaldata.h>
 #include <machine/vmparam.h>
 
+#if JG
 struct globaldata *
 globaldata_find(int cpu)
 {
@@ -60,4 +61,5 @@ int
 is_globaldata_space(vm_offset_t saddr, vm_offset_t eaddr)
 {
 }
+#endif
 
diff --git a/sys/platform/pc64/amd64/identcpu.c b/sys/platform/pc64/amd64/identcpu.c
new file mode 100644 (file)
index 0000000..22d953e
--- /dev/null
@@ -0,0 +1,557 @@
+/*-
+ * Copyright (c) 1992 Terrence R. Lambert.
+ * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
+ * Copyright (c) 1997 KATO Takenori.
+ * Copyright (c) 2008 The DragonFly Project.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp
+ * $DragonFly: src/sys/platform/pc64/amd64/identcpu.c,v 1.1 2008/08/29 17:07:10 dillon Exp $
+ */
+
+#include "opt_cpu.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#if JG
+#include <sys/cpu.h>
+#endif
+#include <sys/eventhandler.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/power.h>
+
+#include <machine/asmacros.h>
+#include <machine/clock.h>
+#include <machine/cputypes.h>
+#include <machine/frame.h>
+#include <machine/intr_machdep.h>
+#include <machine/segments.h>
+#include <machine/specialreg.h>
+#include <machine/md_var.h>
+
+#if JG
+#include <amd64/isa/icu.h>
+#endif
+
+/* XXX - should be in header file: */
+void printcpuinfo(void);
+void identify_cpu(void);
+void earlysetcpuclass(void);
+void panicifcpuunsupported(void);
+
+static void print_AMD_info(void);
+static void print_AMD_assoc(int i);
+
+int    cpu_class;
+char machine[] = "amd64";
+SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, 
+    machine, 0, "Machine class");
+
+static char cpu_model[128];
+SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, 
+    cpu_model, 0, "Machine model");
+
+static int hw_clockrate;
+SYSCTL_INT(_hw, OID_AUTO, clockrate, CTLFLAG_RD, 
+    &hw_clockrate, 0, "CPU instruction clock rate");
+
+static char cpu_brand[48];
+
+static struct {
+       char    *cpu_name;
+       int     cpu_class;
+} amd64_cpus[] = {
+       { "Clawhammer",         CPUCLASS_K8 },          /* CPU_CLAWHAMMER */
+       { "Sledgehammer",       CPUCLASS_K8 },          /* CPU_SLEDGEHAMMER */
+};
+
+int cpu_cores;
+int cpu_logical;
+
+
+extern int pq_l2size;
+extern int pq_l2nways;
+
+void
+printcpuinfo(void)
+{
+       u_int regs[4], i;
+       char *brand;
+
+       cpu_class = amd64_cpus[cpu].cpu_class;
+       kprintf("CPU: ");
+       strncpy(cpu_model, amd64_cpus[cpu].cpu_name, sizeof (cpu_model));
+
+       /* Check for extended CPUID information and a processor name. */
+       if (cpu_exthigh >= 0x80000004) {
+               brand = cpu_brand;
+               for (i = 0x80000002; i < 0x80000005; i++) {
+                       do_cpuid(i, regs);
+                       memcpy(brand, regs, sizeof(regs));
+                       brand += sizeof(regs);
+               }
+       }
+
+       if (strcmp(cpu_vendor, "GenuineIntel") == 0) {
+               /* Please make up your mind folks! */
+               strcat(cpu_model, "EM64T");
+       } else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
+               /*
+                * Values taken from AMD Processor Recognition
+                * http://www.amd.com/K6/k6docs/pdf/20734g.pdf
+                * (also describes ``Features'' encodings.
+                */
+               strcpy(cpu_model, "AMD ");
+               switch (cpu_id & 0xF00) {
+               case 0xf00:
+                       strcat(cpu_model, "AMD64 Processor");
+                       break;
+               default:
+                       strcat(cpu_model, "Unknown");
+                       break;
+               }
+       }
+
+       /*
+        * Replace cpu_model with cpu_brand minus leading spaces if
+        * we have one.
+        */
+       brand = cpu_brand;
+       while (*brand == ' ')
+               ++brand;
+       if (*brand != '\0')
+               strcpy(cpu_model, brand);
+
+       kprintf("%s (", cpu_model);
+       switch(cpu_class) {
+       case CPUCLASS_K8:
+#if JG
+               hw_clockrate = (tsc_freq + 5000) / 1000000;
+               kprintf("%jd.%02d-MHz ",
+                      (intmax_t)(tsc_freq + 4999) / 1000000,
+                      (u_int)((tsc_freq + 4999) / 10000) % 100);
+#endif
+               kprintf("K8");
+               break;
+       default:
+               kprintf("Unknown");     /* will panic below... */
+       }
+       kprintf("-class CPU)\n");
+       if(*cpu_vendor)
+               kprintf("  Origin = \"%s\"",cpu_vendor);
+       if(cpu_id)
+               kprintf("  Id = 0x%x", cpu_id);
+
+       if (strcmp(cpu_vendor, "GenuineIntel") == 0 ||
+           strcmp(cpu_vendor, "AuthenticAMD") == 0) {
+               kprintf("  Stepping = %u", cpu_id & 0xf);
+               if (cpu_high > 0) {
+                       u_int cmp = 1, htt = 1;
+
+                       /*
+                        * Here we should probably set up flags indicating
+                        * whether or not various features are available.
+                        * The interesting ones are probably VME, PSE, PAE,
+                        * and PGE.  The code already assumes without bothering
+                        * to check that all CPUs >= Pentium have a TSC and
+                        * MSRs.
+                        */
+                       kprintf("\n  Features=0x%b", cpu_feature,
+                       "\020"
+                       "\001FPU"       /* Integral FPU */
+                       "\002VME"       /* Extended VM86 mode support */
+                       "\003DE"        /* Debugging Extensions (CR4.DE) */
+                       "\004PSE"       /* 4MByte page tables */
+                       "\005TSC"       /* Timestamp counter */
+                       "\006MSR"       /* Machine specific registers */
+                       "\007PAE"       /* Physical address extension */
+                       "\010MCE"       /* Machine Check support */
+                       "\011CX8"       /* CMPEXCH8 instruction */
+                       "\012APIC"      /* SMP local APIC */
+                       "\013oldMTRR"   /* Previous implementation of MTRR */
+                       "\014SEP"       /* Fast System Call */
+                       "\015MTRR"      /* Memory Type Range Registers */
+                       "\016PGE"       /* PG_G (global bit) support */
+                       "\017MCA"       /* Machine Check Architecture */
+                       "\020CMOV"      /* CMOV instruction */
+                       "\021PAT"       /* Page attributes table */
+                       "\022PSE36"     /* 36 bit address space support */
+                       "\023PN"        /* Processor Serial number */
+                       "\024CLFLUSH"   /* Has the CLFLUSH instruction */
+                       "\025<b20>"
+                       "\026DTS"       /* Debug Trace Store */
+                       "\027ACPI"      /* ACPI support */
+                       "\030MMX"       /* MMX instructions */
+                       "\031FXSR"      /* FXSAVE/FXRSTOR */
+                       "\032SSE"       /* Streaming SIMD Extensions */
+                       "\033SSE2"      /* Streaming SIMD Extensions #2 */
+                       "\034SS"        /* Self snoop */
+                       "\035HTT"       /* Hyperthreading (see EBX bit 16-23) */
+                       "\036TM"        /* Thermal Monitor clock slowdown */
+                       "\037IA64"      /* CPU can execute IA64 instructions */
+                       "\040PBE"       /* Pending Break Enable */
+                       );
+
+                       if (cpu_feature2 != 0) {
+                               kprintf("\n  Features2=0x%b", cpu_feature2,
+                               "\020"
+                               "\001SSE3"      /* SSE3 */
+                               "\002<b1>"
+                               "\003DTES64"    /* 64-bit Debug Trace */
+                               "\004MON"       /* MONITOR/MWAIT Instructions */
+                               "\005DS_CPL"    /* CPL Qualified Debug Store */
+                               "\006VMX"       /* Virtual Machine Extensions */
+                               "\007SMX"       /* Safer Mode Extensions */
+                               "\010EST"       /* Enhanced SpeedStep */
+                               "\011TM2"       /* Thermal Monitor 2 */
+                               "\012SSSE3"     /* SSSE3 */
+                               "\013CNXT-ID"   /* L1 context ID available */
+                               "\014<b11>"
+                               "\015<b12>"
+                               "\016CX16"      /* CMPXCHG16B Instruction */
+                               "\017xTPR"      /* Send Task Priority Messages*/
+                               "\020PDCM"      /* Perf/Debug Capability MSR */
+                               "\021<b16>"
+                               "\022<b17>"
+                               "\023DCA"       /* Direct Cache Access */
+                               "\024SSE4.1"
+                               "\025SSE4.2"
+                               "\026x2APIC"    /* xAPIC Extensions */
+                               "\027<b22>"
+                               "\030POPCNT"
+                               "\031<b24>"
+                               "\032<b25>"
+                               "\033<b26>"
+                               "\034<b27>"
+                               "\035<b28>"
+                               "\036<b29>"
+                               "\037<b30>"
+                               "\040<b31>"
+                               );
+                       }
+
+                       /*
+                        * AMD64 Architecture Programmer's Manual Volume 3:
+                        * General-Purpose and System Instructions
+                        * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/24594.pdf
+                        *
+                        * IA-32 Intel Architecture Software Developer's Manual,
+                        * Volume 2A: Instruction Set Reference, A-M
+                        * ftp://download.intel.com/design/Pentium4/manuals/25366617.pdf
+                        */
+                       if (amd_feature != 0) {
+                               kprintf("\n  AMD Features=0x%b", amd_feature,
+                               "\020"          /* in hex */
+                               "\001<s0>"      /* Same */
+                               "\002<s1>"      /* Same */
+                               "\003<s2>"      /* Same */
+                               "\004<s3>"      /* Same */
+                               "\005<s4>"      /* Same */
+                               "\006<s5>"      /* Same */
+                               "\007<s6>"      /* Same */
+                               "\010<s7>"      /* Same */
+                               "\011<s8>"      /* Same */
+                               "\012<s9>"      /* Same */
+                               "\013<b10>"     /* Undefined */
+                               "\014SYSCALL"   /* Have SYSCALL/SYSRET */
+                               "\015<s12>"     /* Same */
+                               "\016<s13>"     /* Same */
+                               "\017<s14>"     /* Same */
+                               "\020<s15>"     /* Same */
+                               "\021<s16>"     /* Same */
+                               "\022<s17>"     /* Same */
+                               "\023<b18>"     /* Reserved, unknown */
+                               "\024MP"        /* Multiprocessor Capable */
+                               "\025NX"        /* Has EFER.NXE, NX */
+                               "\026<b21>"     /* Undefined */
+                               "\027MMX+"      /* AMD MMX Extensions */
+                               "\030<s23>"     /* Same */
+                               "\031<s24>"     /* Same */
+                               "\032FFXSR"     /* Fast FXSAVE/FXRSTOR */
+                               "\033Page1GB"   /* 1-GB large page support */
+                               "\034RDTSCP"    /* RDTSCP */
+                               "\035<b28>"     /* Undefined */
+                               "\036LM"        /* 64 bit long mode */
+                               "\0373DNow!+"   /* AMD 3DNow! Extensions */
+                               "\0403DNow!"    /* AMD 3DNow! */
+                               );
+                       }
+
+                       if (amd_feature2 != 0) {
+                               kprintf("\n  AMD Features2=0x%b", amd_feature2,
+                               "\020"
+                               "\001LAHF"      /* LAHF/SAHF in long mode */
+                               "\002CMP"       /* CMP legacy */
+                               "\003SVM"       /* Secure Virtual Mode */
+                               "\004ExtAPIC"   /* Extended APIC register */
+                               "\005CR8"       /* CR8 in legacy mode */
+                               "\006<b5>"
+                               "\007<b6>"
+                               "\010<b7>"
+                               "\011Prefetch"  /* 3DNow! Prefetch/PrefetchW */
+                               "\012<b9>"
+                               "\013<b10>"
+                               "\014<b11>"
+                               "\015<b12>"
+                               "\016<b13>"
+                               "\017<b14>"
+                               "\020<b15>"
+                               "\021<b16>"
+                               "\022<b17>"
+                               "\023<b18>"
+                               "\024<b19>"
+                               "\025<b20>"
+                               "\026<b21>"
+                               "\027<b22>"
+                               "\030<b23>"
+                               "\031<b24>"
+                               "\032<b25>"
+                               "\033<b26>"
+                               "\034<b27>"
+                               "\035<b28>"
+                               "\036<b29>"
+                               "\037<b30>"
+                               "\040<b31>"
+                               );
+                       }
+
+                       if (cpu_feature & CPUID_HTT && strcmp(cpu_vendor,
+                           "AuthenticAMD") == 0)
+                               cpu_feature &= ~CPUID_HTT;
+
+                       /*
+                        * If this CPU supports HTT or CMP then mention the
+                        * number of physical/logical cores it contains.
+                        */
+                       if (cpu_feature & CPUID_HTT)
+                               htt = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
+                       if (strcmp(cpu_vendor, "AuthenticAMD") == 0 &&
+                           (amd_feature2 & AMDID2_CMP))
+                               cmp = (cpu_procinfo2 & AMDID_CMP_CORES) + 1;
+                       else if (strcmp(cpu_vendor, "GenuineIntel") == 0 &&
+                           (cpu_high >= 4)) {
+                               cpuid_count(4, 0, regs);
+                               if ((regs[0] & 0x1f) != 0)
+                                       cmp = ((regs[0] >> 26) & 0x3f) + 1;
+                       }
+                       cpu_cores = cmp;
+                       cpu_logical = htt / cmp;
+                       if (cmp > 1)
+                               kprintf("\n  Cores per package: %d", cmp);
+                       if ((htt / cmp) > 1)
+                               kprintf("\n  Logical CPUs per core: %d",
+                                   cpu_logical);
+               }
+       }
+       /* Avoid ugly blank lines: only print newline when we have to. */
+       if (*cpu_vendor || cpu_id)
+               kprintf("\n");
+
+       if (!bootverbose)
+               return;
+
+       if (strcmp(cpu_vendor, "AuthenticAMD") == 0)
+               print_AMD_info();
+}
+
+void
+panicifcpuunsupported(void)
+{
+
+#ifndef HAMMER_CPU
+#error "You need to specify a cpu type"
+#endif
+       /*
+        * Now that we have told the user what they have,
+        * let them know if that machine type isn't configured.
+        */
+       switch (cpu_class) {
+       case CPUCLASS_X86:
+#ifndef HAMMER_CPU
+       case CPUCLASS_K8:
+#endif
+               panic("CPU class not configured");
+       default:
+               break;
+       }
+}
+
+
+#if JG
+/* Update TSC freq with the value indicated by the caller. */
+static void
+tsc_freq_changed(void *arg, const struct cf_level *level, int status)
+{
+       /* If there was an error during the transition, don't do anything. */
+       if (status != 0)
+               return;
+
+       /* Total setting for this level gives the new frequency in MHz. */
+       hw_clockrate = level->total_set.freq;
+}
+
+EVENTHANDLER_DEFINE(cpufreq_post_change, tsc_freq_changed, NULL,
+    EVENTHANDLER_PRI_ANY);
+#endif
+
+/*
+ * Final stage of CPU identification. -- Should I check TI?
+ */
+void
+identify_cpu(void)
+{
+       u_int regs[4];
+
+       do_cpuid(0, regs);
+       cpu_high = regs[0];
+       ((u_int *)&cpu_vendor)[0] = regs[1];
+       ((u_int *)&cpu_vendor)[1] = regs[3];
+       ((u_int *)&cpu_vendor)[2] = regs[2];
+       cpu_vendor[12] = '\0';
+
+       do_cpuid(1, regs);
+       cpu_id = regs[0];
+       cpu_procinfo = regs[1];
+       cpu_feature = regs[3];
+       cpu_feature2 = regs[2];
+
+       if (strcmp(cpu_vendor, "GenuineIntel") == 0 ||
+           strcmp(cpu_vendor, "AuthenticAMD") == 0) {
+               do_cpuid(0x80000000, regs);
+               cpu_exthigh = regs[0];
+       }
+       if (cpu_exthigh >= 0x80000001) {
+               do_cpuid(0x80000001, regs);
+               amd_feature = regs[3] & ~(cpu_feature & 0x0183f3ff);
+               amd_feature2 = regs[2];
+       }
+       if (cpu_exthigh >= 0x80000008) {
+               do_cpuid(0x80000008, regs);
+               cpu_procinfo2 = regs[2];
+       }
+
+       /* XXX */
+       cpu = CPU_CLAWHAMMER;
+}
+
+static void
+print_AMD_assoc(int i)
+{
+       if (i == 255)
+               kprintf(", fully associative\n");
+       else
+               kprintf(", %d-way associative\n", i);
+}
+
+static void
+print_AMD_l2_assoc(int i)
+{
+       switch (i & 0x0f) {
+       case 0: kprintf(", disabled/not present\n"); break;
+       case 1: kprintf(", direct mapped\n"); break;
+       case 2: kprintf(", 2-way associative\n"); break;
+       case 4: kprintf(", 4-way associative\n"); break;
+       case 6: kprintf(", 8-way associative\n"); break;
+       case 8: kprintf(", 16-way associative\n"); break;
+       case 15: kprintf(", fully associative\n"); break;
+       default: kprintf(", reserved configuration\n"); break;
+       }
+}
+
+static void
+print_AMD_info(void)
+{
+       u_int regs[4];
+
+       if (cpu_exthigh < 0x80000005)
+               return;
+
+       do_cpuid(0x80000005, regs);
+       kprintf("L1 2MB data TLB: %d entries", (regs[0] >> 16) & 0xff);
+       print_AMD_assoc(regs[0] >> 24);
+
+       kprintf("L1 2MB instruction TLB: %d entries", regs[0] & 0xff);
+       print_AMD_assoc((regs[0] >> 8) & 0xff);
+
+       kprintf("L1 4KB data TLB: %d entries", (regs[1] >> 16) & 0xff);
+       print_AMD_assoc(regs[1] >> 24);
+
+       kprintf("L1 4KB instruction TLB: %d entries", regs[1] & 0xff);
+       print_AMD_assoc((regs[1] >> 8) & 0xff);
+
+       kprintf("L1 data cache: %d kbytes", regs[2] >> 24);
+       kprintf(", %d bytes/line", regs[2] & 0xff);
+       kprintf(", %d lines/tag", (regs[2] >> 8) & 0xff);
+       print_AMD_assoc((regs[2] >> 16) & 0xff);
+
+       kprintf("L1 instruction cache: %d kbytes", regs[3] >> 24);
+       kprintf(", %d bytes/line", regs[3] & 0xff);
+       kprintf(", %d lines/tag", (regs[3] >> 8) & 0xff);
+       print_AMD_assoc((regs[3] >> 16) & 0xff);
+
+       if (cpu_exthigh >= 0x80000006) {
+               do_cpuid(0x80000006, regs);
+               if ((regs[0] >> 16) != 0) {
+                       kprintf("L2 2MB data TLB: %d entries",
+                           (regs[0] >> 16) & 0xfff);
+                       print_AMD_l2_assoc(regs[0] >> 28);
+                       kprintf("L2 2MB instruction TLB: %d entries",
+                           regs[0] & 0xfff);
+                       print_AMD_l2_assoc((regs[0] >> 28) & 0xf);
+               } else {
+                       kprintf("L2 2MB unified TLB: %d entries",
+                           regs[0] & 0xfff);
+                       print_AMD_l2_assoc((regs[0] >> 28) & 0xf);
+               }
+               if ((regs[1] >> 16) != 0) {
+                       kprintf("L2 4KB data TLB: %d entries",
+                           (regs[1] >> 16) & 0xfff);
+                       print_AMD_l2_assoc(regs[1] >> 28);
+
+                       kprintf("L2 4KB instruction TLB: %d entries",
+                           (regs[1] >> 16) & 0xfff);
+                       print_AMD_l2_assoc((regs[1] >> 28) & 0xf);
+               } else {
+                       kprintf("L2 4KB unified TLB: %d entries",
+                           (regs[1] >> 16) & 0xfff);
+                       print_AMD_l2_assoc((regs[1] >> 28) & 0xf);
+               }
+               kprintf("L2 unified cache: %d kbytes", regs[2] >> 16);
+               kprintf(", %d bytes/line", regs[2] & 0xff);
+               kprintf(", %d lines/tag", (regs[2] >> 8) & 0x0f);
+               print_AMD_l2_assoc((regs[2] >> 12) & 0x0f);     
+       }
+}
index d7492cc..2378b07 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003,2004 The DragonFly Project.  All rights reserved.
+ * Copyright (c) 2003,2004,2008 The DragonFly Project.  All rights reserved.
  * 
  * This code is derived from software contributed to The DragonFly Project
  * by Matthew Dillon <dillon@backplane.com>
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/platform/pc64/amd64/in_cksum2.s,v 1.2 2007/09/24 03:24:45 yanyh Exp $
+ * $DragonFly: src/sys/platform/pc64/amd64/in_cksum2.s,v 1.3 2008/08/29 17:07:10 dillon Exp $
  */
 
 #include <machine/asmacros.h>          /* miscellaneous asm macros */
         */
        .p2align 4
 ENTRY(asm_ones32)
-       movl    4(%esp),%edx    /* %edx = buffer pointer */
-       movl    8(%esp),%ecx    /* %ecx = counter */
-       subl    %eax,%eax       /* %eax = checksum */
+       movq    %rdi,%rdx       /* %rdx = buffer pointer */
+       movl    %esi,%ecx       /* %ecx = counter */
+       xorl    %eax,%eax       /* %eax = checksum */
        cmpl    $5,%ecx
        jl      2f
 1:
        subl    $5,%ecx
-       addl    (%edx),%eax
-       adcl    4(%edx),%eax
-       adcl    8(%edx),%eax
-       adcl    12(%edx),%eax
-       adcl    16(%edx),%eax
+       addl    (%rdx),%eax
+       adcl    4(%rdx),%eax
+       adcl    8(%rdx),%eax
+       adcl    12(%rdx),%eax
+       adcl    16(%rdx),%eax
        adcl    $0,%eax
-       addl    $20,%edx
+       addq    $20,%rdx
        cmpl    $5,%ecx
        jge     1b
 2:
        testl   %ecx,%ecx
        je      4f
 3:
-       addl    (%edx),%eax
+       addl    (%rdx),%eax
        adcl    $0,%eax
-       addl    $4,%edx
+       addq    $4,%rdx
        decl    %ecx
        jnz     3b
 4:
index 9ce29ab..89d78da 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
+ * Copyright (c) 2006-2008 The DragonFly Project.  All rights reserved.
  * 
  * This code is derived from software contributed to The DragonFly Project
  * by Matthew Dillon <dillon@backplane.com>
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/platform/pc64/amd64/init.c,v 1.2 2007/09/24 03:24:45 yanyh Exp $
+ * $DragonFly: src/sys/platform/pc64/amd64/init.c,v 1.3 2008/08/29 17:07:10 dillon Exp $
  */
 
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#if JG
 struct privatespace CPU_prvspace[];
+#endif
 
-vm_paddr_t phys_avail[16];
-vm_paddr_t Maxmem;
+extern vm_paddr_t phys_avail[16];
+extern vm_paddr_t Maxmem;
 vm_paddr_t Maxmem_bytes;
 int MemImageFd = -1;
 int DiskNum;
 int NetifNum;
 char *pid_file;
-struct msgbuf *msgbufp;
-caddr_t ptvmmap;
+extern struct msgbuf *msgbufp;
+extern caddr_t ptvmmap;
+#if JG
 u_int tsc_present; 
 vm_offset_t KvaStart;
 vm_offset_t KvaEnd;
 vm_offset_t KvaSize;
 vm_offset_t virtual_start;
-vm_offset_t virtual_end;
-vm_offset_t kernel_vm_end;
+#endif
+extern vm_offset_t virtual_end;
+extern vm_offset_t kernel_vm_end;
 vm_offset_t crashdumpmap;
-vm_offset_t clean_sva;
-vm_offset_t clean_eva;
+extern vm_offset_t clean_sva;
+extern vm_offset_t clean_eva;
 
 static void init_sys_memory(char *imageFile);
 static void init_kern_memory(void);
@@ -166,6 +170,7 @@ usage(const char *ctl, ...)
 {
 }
 
+#if JG
 void
 cpu_reset(void)
 {
@@ -175,3 +180,4 @@ void
 cpu_halt(void)
 {
 }
+#endif
diff --git a/sys/platform/pc64/amd64/initcpu.c b/sys/platform/pc64/amd64/initcpu.c
new file mode 100644 (file)
index 0000000..1c4ce0b
--- /dev/null
@@ -0,0 +1,84 @@
+/*-
+ * Copyright (c) KATO Takenori, 1997, 1998.
+ * Copyright (c) 2008 The DragonFly Project.
+ * 
+ * All rights reserved.  Unpublished rights reserved under the copyright
+ * laws of Japan.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer as
+ *    the first lines of this file unmodified.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $DragonFly: src/sys/platform/pc64/amd64/initcpu.c,v 1.1 2008/08/29 17:07:10 dillon Exp $
+ */
+
+#include "opt_cpu.h"
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+
+#include <machine/cputypes.h>
+#include <machine/md_var.h>
+#include <machine/specialreg.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+static int     hw_instruction_sse;
+SYSCTL_INT(_hw, OID_AUTO, instruction_sse, CTLFLAG_RD,
+    &hw_instruction_sse, 0, "SIMD/MMX2 instructions available in CPU");
+
+int    cpu;                    /* Are we 386, 386sx, 486, etc? */
+u_int  cpu_feature;            /* Feature flags */
+u_int  cpu_feature2;           /* Feature flags */
+u_int  amd_feature;            /* AMD feature flags */
+u_int  amd_feature2;           /* AMD feature flags */
+u_int  cpu_high;               /* Highest arg to CPUID */
+u_int  cpu_exthigh;            /* Highest arg to extended CPUID */
+u_int  cpu_id;                 /* Stepping ID */
+u_int  cpu_procinfo;           /* HyperThreading Info / Brand Index / CLFUSH */
+u_int  cpu_procinfo2;          /* Multicore info */
+char   cpu_vendor[20];         /* CPU Origin code */
+u_int  cpu_fxsr;               /* SSE enabled */
+u_int  cpu_mxcsr_mask;         /* Valid bits in mxcsr */
+
+/*
+ * Initialize CPU control registers
+ */
+void
+initializecpu(void)
+{
+       uint64_t msr;
+
+       if ((cpu_feature & CPUID_XMM) && (cpu_feature & CPUID_FXSR)) {
+               load_cr4(rcr4() | CR4_FXSR | CR4_XMM);
+               cpu_fxsr = hw_instruction_sse = 1;
+       }
+       if ((amd_feature & AMDID_NX) != 0) {
+               msr = rdmsr(MSR_EFER) | EFER_NXE;
+               wrmsr(MSR_EFER, msr);
+#if JG
+               pg_nx = PG_NX;
+#endif
+       }
+}
diff --git a/sys/platform/pc64/amd64/ipl.s b/sys/platform/pc64/amd64/ipl.s
new file mode 100644 (file)
index 0000000..839dbf1
--- /dev/null
@@ -0,0 +1,534 @@
+/*
+ * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
+ * 
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon@backplane.com>
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * ---
+ *
+ * Copyright (c) 1989, 1990 William F. Jolitz.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)ipl.s
+ *
+ * $FreeBSD: src/sys/i386/isa/ipl.s,v 1.32.2.3 2002/05/16 16:03:56 bde Exp $
+ * $DragonFly: src/sys/platform/pc64/amd64/ipl.s,v 1.1 2008/08/29 17:07:10 dillon Exp $
+ */
+
+#include <machine/asmacros.h>
+#include <machine/segments.h>
+#include <machine/ipl.h>
+#include <machine/lock.h>
+#include <machine/psl.h>
+#include <machine/trap.h>
+#include "assym.s"
+
+/*
+ * AT/386
+ * Vector interrupt control section
+ *
+ *  ipending   - Pending interrupts (set when a masked interrupt occurs)
+ *  spending   - Pending software interrupts
+ */
+       .data
+       ALIGN_DATA
+
+       .globl          fastunpend_count
+fastunpend_count:      .long   0
+
+       .text
+       SUPERALIGN_TEXT
+
+       /*
+        * GENERAL NOTES
+        *
+        *      - fast interrupts are always called with a critical section
+        *        held
+        *
+        *      - we release our critical section when scheduling interrupt
+        *        or softinterrupt threads in order so they can preempt
+        *        (unless we are called manually from a critical section, in
+        *        which case there will still be a critical section and
+        *        they won't preempt anyway).
+        *
+        *      - TD_NEST_COUNT prevents splz from nesting too deeply within
+        *        itself.  It is *not* actually an interrupt nesting count.
+        *        PCPU(intr_nesting_level) is an interrupt nesting count.
+        *
+        *      - We have to be careful in regards to local interrupts
+        *        occuring simultaniously with our doreti and splz 
+        *        processing.
+        */
+
+       /*
+        * DORETI
+        *
+        * Handle return from interrupts, traps and syscalls.  This function
+        * checks the cpl for unmasked pending interrupts (fast, normal, or
+        * soft) and schedules them if appropriate, then irets.
+        *
+        * If we are in a critical section we cannot run any pending ints
+        * nor can be play with mp_lock.
+        *
+        * The stack contains a trapframe at the start of doreti.
+        */
+       SUPERALIGN_TEXT
+       .globl  doreti
+       .type   doreti,@function
+doreti:
+       FAKE_MCOUNT(bintr)              /* init "from" bintr -> doreti */
+       movq    $0,%rax                 /* irq mask unavailable due to BGL */
+       movq    PCPU(curthread),%rbx
+       cli                             /* interlock with TDPRI_CRIT */
+       cmpl    $0,PCPU(reqflags)       /* short cut if nothing to do */
+       je      5f
+       cmpl    $TDPRI_CRIT,TD_PRI(%rbx) /* can't unpend if in critical sec */
+       jge     5f
+       addl    $TDPRI_CRIT,TD_PRI(%rbx) /* force all ints to pending */
+doreti_next:
+       sti                             /* allow new interrupts */
+       movl    %eax,%ecx               /* irq mask unavailable due to BGL */
+       notl    %ecx
+       cli                             /* disallow YYY remove */
+#ifdef SMP
+       testl   $RQF_IPIQ,PCPU(reqflags)
+       jnz     doreti_ipiq
+#endif
+       testl   PCPU(fpending),%ecx     /* check for an unmasked fast int */
+       jnz     doreti_fast
+
+       testl   PCPU(ipending),%ecx     /* check for an unmasked slow int */
+       jnz     doreti_intr
+
+       movl    PCPU(spending),%ecx     /* check for a pending software int */
+       cmpl    $0,%ecx
+       jnz     doreti_soft
+
+       testl   $RQF_AST_MASK,PCPU(reqflags) /* any pending ASTs? */
+       jz      2f
+
+       /* ASTs are only applicable when returning to userland */
+       testb   $SEL_RPL_MASK,TF_CS(%rsp)
+       jnz     doreti_ast
+2:
+       /*
+        * Nothing left to do, finish up.  Interrupts are still disabled.
+        * %eax contains the mask of IRQ's that are not available due to
+        * BGL requirements.  We can only clear RQF_INTPEND if *ALL* pending
+        * interrupts have been processed.
+        */
+       subl    $TDPRI_CRIT,TD_PRI(%rbx)        /* interlocked with cli */
+       testl   %eax,%eax
+       jnz     5f
+       andl    $~RQF_INTPEND,PCPU(reqflags)
+5:
+       MEXITCOUNT
+
+       /*
+        * Restore register and iret.  iret can fault on %rip (which is
+        * really stupid).  If this occurs we re-fault and vector to
+        * doreti_iret_fault().
+        *
+        * ...
+        * can be set from user mode, this can result in a kernel mode
+        * exception.  The trap code will revector to the *_fault code
+        * which then sets up a T_PROTFLT signal.  If the signal is
+        * sent to userland, sendsig() will automatically clean up all
+        * the segment registers to avoid a loop.
+        */
+       .globl  doreti_iret
+       .globl  doreti_syscall_ret
+doreti_syscall_ret:
+       POP_FRAME               /* registers and %gs (+cli) */
+       /* special global also used by exception.S */
+doreti_iret:
+       iretq
+
+       /*
+        * doreti_iret_fault.  Alternative return code for
+        * the case where we get a fault in the doreti_exit code
+        * above.  trap() (sys/platform/pc64/amd64/trap.c) catches this specific
+        * case, sends the process a signal and continues in the
+        * corresponding place in the code below.
+        */
+       ALIGN_TEXT
+       .globl  doreti_iret_fault
+doreti_iret_fault:
+       PUSH_FRAME
+       testq   $PSL_I,TF_RFLAGS(%rsp)
+       jz      2f
+       sti
+2:
+       movq    $T_PROTFLT,TF_TRAPNO(%rsp)
+       movq    $0,TF_ERR(%rsp) /* XXX should be the error code */
+       movq    $0,TF_ADDR(%rsp)
+       FAKE_MCOUNT(TF_RIP(%rsp))
+       jmp     calltrap
+
+       /*
+        * FAST interrupt pending.  NOTE: stack context holds frame structure
+        * for fast interrupt procedure, do not do random pushes or pops!
+        */
+       ALIGN_TEXT
+doreti_fast:
+       andl    PCPU(fpending),%ecx     /* only check fast ints */
+       bsfl    %ecx, %ecx              /* locate the next dispatchable int */
+       btrl    %ecx, PCPU(fpending)    /* is it really still pending? */
+       jnc     doreti_next
+       pushq   %rax                    /* save IRQ mask unavailable for BGL */
+                                       /* NOTE: is also CPL in frame */
+#if 0
+#ifdef SMP
+       pushq   %rcx                    /* save ecx */
+       call    try_mplock
+       popq    %rcx
+       testl   %eax,%eax
+       jz      1f
+       /* MP lock successful */
+#endif
+#endif
+       incl    PCPU(intr_nesting_level)
+       call    dofastunpend            /* unpend fast intr %ecx */
+       decl    PCPU(intr_nesting_level)
+#if 0
+#ifdef SMP
+       call    rel_mplock
+#endif
+#endif
+       popq    %rax
+       jmp     doreti_next
+1:
+       btsl    %ecx, PCPU(fpending)    /* oops, couldn't get the MP lock */
+       popq    %rax                    /* add to temp. cpl mask to ignore */
+       orl     PCPU(fpending),%eax
+       jmp     doreti_next
+
+       /*
+        *  INTR interrupt pending
+        *
+        *  Temporarily back-out our critical section to allow an interrupt
+        *  preempt us when we schedule it.  Bump intr_nesting_level to
+        *  prevent the switch code from recursing via splz too deeply.
+        */
+       ALIGN_TEXT
+doreti_intr:
+       andl    PCPU(ipending),%ecx     /* only check normal ints */
+       bsfl    %ecx, %ecx              /* locate the next dispatchable int */
+       btrl    %ecx, PCPU(ipending)    /* is it really still pending? */
+       jnc     doreti_next
+       pushq   %rax
+       movl    %ecx,%edi               /* argument to C function */
+       incl    TD_NEST_COUNT(%rbx)     /* prevent doreti/splz nesting */
+       subl    $TDPRI_CRIT,TD_PRI(%rbx) /* so we can preempt */
+       call    sched_ithd              /* YYY must pull in imasks */
+       addl    $TDPRI_CRIT,TD_PRI(%rbx)
+       decl    TD_NEST_COUNT(%rbx)
+       popq    %rax
+       jmp     doreti_next
+
+       /*
+        *  SOFT interrupt pending
+        *
+        *  Temporarily back-out our critical section to allow an interrupt
+        *  preempt us when we schedule it.  Bump intr_nesting_level to
+        *  prevent the switch code from recursing via splz too deeply.
+        */
+       ALIGN_TEXT
+doreti_soft:
+       bsfl    %ecx,%ecx               /* locate the next pending softint */
+       btrl    %ecx,PCPU(spending)     /* make sure its still pending */
+       jnc     doreti_next
+       addl    $FIRST_SOFTINT,%ecx     /* actual intr number */
+       pushq   %rax
+       movl    %ecx,%edi               /* argument to C call */
+       incl    TD_NEST_COUNT(%rbx)     /* prevent doreti/splz nesting */
+       subl    $TDPRI_CRIT,TD_PRI(%rbx) /* so we can preempt */
+       call    sched_ithd              /* YYY must pull in imasks */
+       addl    $TDPRI_CRIT,TD_PRI(%rbx)
+       decl    TD_NEST_COUNT(%rbx)
+       popq    %rax
+       jmp     doreti_next
+
+       /*
+        * AST pending.  We clear RQF_AST_SIGNAL automatically, the others
+        * are cleared by the trap as they are processed.
+        *
+        * Temporarily back-out our critical section because trap() can be
+        * a long-winded call, and we want to be more syscall-like.  
+        *
+        * YYY theoretically we can call lwkt_switch directly if all we need
+        * to do is a reschedule.
+        */
+doreti_ast:
+       andl    $~(RQF_AST_SIGNAL|RQF_AST_UPCALL),PCPU(reqflags)
+       sti
+       movl    %eax,%esi               /* save cpl (can't use stack) */
+       movl    $T_ASTFLT,TF_TRAPNO(%rsp)
+       movq    %rsp,%rdi               /* pass frame by ref (%edi = C arg) */
+       subl    $TDPRI_CRIT,TD_PRI(%rbx)
+       call    trap
+       addl    $TDPRI_CRIT,TD_PRI(%rbx)
+       movl    %esi,%eax               /* restore cpl for loop */
+       jmp     doreti_next
+
+#ifdef SMP
+       /*
+        * IPIQ message pending.  We clear RQF_IPIQ automatically.
+        */
+doreti_ipiq:
+       movl    %eax,%esi               /* save cpl (can't use stack) */
+       incl    PCPU(intr_nesting_level)
+       andl    $~RQF_IPIQ,PCPU(reqflags)
+       subl    $16,%rsp                /* add dummy vec and ppl */
+       movq    %rsp,%rdi               /* pass frame by ref (C arg) */
+       call    lwkt_process_ipiq_frame
+       addl    $16,%rsp
+       decl    PCPU(intr_nesting_level)
+       movl    %esi,%eax               /* restore cpl for loop */
+       jmp     doreti_next
+
+#endif
+
+       /*
+        * SPLZ() a C callable procedure to dispatch any unmasked pending
+        *        interrupts regardless of critical section nesting.  ASTs
+        *        are not dispatched.
+        *
+        *        Use %eax to track those IRQs that could not be processed
+        *        due to BGL requirements.
+        */
+       SUPERALIGN_TEXT
+
+ENTRY(splz)
+       pushfq
+       pushq   %rbx
+       movq    PCPU(curthread),%rbx
+       addl    $TDPRI_CRIT,TD_PRI(%rbx)
+       movl    $0,%eax
+
+splz_next:
+       cli
+       movl    %eax,%ecx               /* ecx = ~CPL */
+       notl    %ecx
+#ifdef SMP
+       testl   $RQF_IPIQ,PCPU(reqflags)
+       jnz     splz_ipiq
+#endif
+       testl   PCPU(fpending),%ecx     /* check for an unmasked fast int */
+       jnz     splz_fast
+
+       testl   PCPU(ipending),%ecx
+       jnz     splz_intr
+
+       movl    PCPU(spending),%ecx
+       cmpl    $0,%ecx
+       jnz     splz_soft
+
+       subl    $TDPRI_CRIT,TD_PRI(%rbx)
+
+       /*
+        * Nothing left to do, finish up.  Interrupts are still disabled.
+        * If our mask of IRQs we couldn't process due to BGL requirements
+        * is 0 then there are no pending interrupt sources left and we
+        * can clear RQF_INTPEND.
+        */
+       testl   %eax,%eax
+       jnz     5f
+       andl    $~RQF_INTPEND,PCPU(reqflags)
+5:
+       popq    %rbx
+       popfq
+       ret
+
+       /*
+        * FAST interrupt pending
+        */
+       ALIGN_TEXT
+splz_fast:
+       andl    PCPU(fpending),%ecx     /* only check fast ints */
+       bsfl    %ecx, %ecx              /* locate the next dispatchable int */
+       btrl    %ecx, PCPU(fpending)    /* is it really still pending? */
+       jnc     splz_next
+       pushq   %rax
+#if 0
+#ifdef SMP
+       movl    %ecx,%edi               /* argument to try_mplock */
+       call    try_mplock
+       testl   %eax,%eax
+       jz      1f
+#endif
+#endif
+       incl    PCPU(intr_nesting_level)
+       call    dofastunpend            /* unpend fast intr %ecx */
+       decl    PCPU(intr_nesting_level)
+#if 0
+#ifdef SMP
+       call    rel_mplock
+#endif
+#endif
+       popq    %rax
+       jmp     splz_next
+1:
+       btsl    %ecx, PCPU(fpending)    /* oops, couldn't get the MP lock */
+       popq    %rax
+       orl     PCPU(fpending),%eax
+       jmp     splz_next
+
+       /*
+        *  INTR interrupt pending
+        *
+        *  Temporarily back-out our critical section to allow the interrupt
+        *  preempt us.
+        */
+       ALIGN_TEXT
+splz_intr:
+       andl    PCPU(ipending),%ecx     /* only check normal ints */
+       bsfl    %ecx, %ecx              /* locate the next dispatchable int */
+       btrl    %ecx, PCPU(ipending)    /* is it really still pending? */
+       jnc     splz_next
+       sti
+       pushq   %rax
+       movl    %ecx,%edi               /* C argument */
+       subl    $TDPRI_CRIT,TD_PRI(%rbx)
+       incl    TD_NEST_COUNT(%rbx)     /* prevent doreti/splz nesting */
+       call    sched_ithd              /* YYY must pull in imasks */
+       addl    $TDPRI_CRIT,TD_PRI(%rbx)
+       decl    TD_NEST_COUNT(%rbx)     /* prevent doreti/splz nesting */
+       popq    %rax
+   &n