Index: gnu/usr.bin/binutils217/ld/Makefile.amd64
===================================================================
RCS file: /home/dcvs/src/gnu/usr.bin/binutils217/ld/Makefile.amd64,v
retrieving revision 1.1
diff -u -r1.1 Makefile.amd64
--- gnu/usr.bin/binutils217/ld/Makefile.amd64	13 Apr 2007 12:24:32 -0000	1.1
+++ gnu/usr.bin/binutils217/ld/Makefile.amd64	10 Feb 2008 11:48:09 -0000
@@ -30,3 +30,25 @@
 		no \
 		${NATIVE_EMULATION:Q} \
 		${TARGET_TUPLE:Q}
+
+
+NATIVE32_EMULATION=	elf_i386
+EMS+=		${NATIVE32_EMULATION}
+SRCS+=	e${NATIVE32_EMULATION}.c
+CLEANFILES+=	e${NATIVE32_EMULATION}.c
+
+e${NATIVE32_EMULATION}.c: emulparams/${NATIVE32_EMULATION}.sh emultempl/elf32.em \
+    scripttempl/elf.sc genscripts.sh stringify.sed
+	sh ${SRCDIR}/ld/genscripts.sh \
+		${SRCDIR:Q}/ld \
+		${_amd64_path:Q} \
+		"" \
+		"" \
+		${HOST} \
+		${TARGET_TUPLE:Q} \
+		${TARGET_TUPLE:Q} \
+		${NATIVE_EMULATION:Q} \
+		"" \
+		no \
+		${NATIVE32_EMULATION:Q} \
+		${TARGET_TUPLE:Q}
Index: sys/cpu/amd64/include/cpufunc.h
===================================================================
RCS file: /home/dcvs/src/sys/cpu/amd64/include/cpufunc.h,v
retrieving revision 1.2
diff -u -r1.2 cpufunc.h
--- sys/cpu/amd64/include/cpufunc.h	23 Sep 2007 04:29:30 -0000	1.2
+++ sys/cpu/amd64/include/cpufunc.h	10 Feb 2008 11:48:09 -0000
@@ -126,6 +126,14 @@
 }
 
 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)
 {
 	__asm __volatile("sti");
Index: sys/cpu/amd64/include/pmap.h
===================================================================
RCS file: /home/dcvs/src/sys/cpu/amd64/include/pmap.h,v
retrieving revision 1.2
diff -u -r1.2 pmap.h
--- sys/cpu/amd64/include/pmap.h	23 Sep 2007 04:29:30 -0000	1.2
+++ sys/cpu/amd64/include/pmap.h	10 Feb 2008 11:48:09 -0000
@@ -60,22 +60,26 @@
 #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_PAT		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_AVL0		0x0200LL		/* available to os */
+#define PG_AVL1		0x0400LL		/* available to os */
+#define PG_AVL2		0x0800LL		/* available to os */
+
+#define PG_PTE_PAT	PG_PAT			/* PAT bit for 4K pages */
 #define PG_PDE_PAT	0x1000LL		/* PAT bit for 2M pages */
+#define PG_PDPE_PAT	0x1000LL		/* PAT bit for 1G pages */
+
 #define PG_FRAME	0x000000FFFFFF0000LL	/* 40 bit phys address */
 #define PG_PHYSRESERVED	0x000FFF0000000000LL	/* reserved for future PA */
-#define PG_USR3		0x0010000000000000LL	/* avilable to os */
+#define PG_AVLN		0x0010000000000000LL	/* avilable to os, bit 52-62 */
+#define PG_NX		(1ul<<63)		/* No-execute, bit 63*/
 
 /*
  * OS assignments
  */
-#define PG_W		PG_USR0			/* Wired 	*/
-#define	PG_MANAGED	PG_USR1			/* Managed 	*/
+#define PG_W		PG_AVL0			/* Wired 	*/
+#define	PG_MANAGED	PG_AVL1			/* Managed 	*/
 #define	PG_PROT		(PG_RW|PG_U)		/* all protection bits . */
 #define PG_N		(PG_PWT|PG_PCD)		/* Non-cacheable */
 
@@ -91,16 +95,7 @@
 #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
+ * Pte related macros. This is complicated by having to deal with
  * the sign extension of the 48th bit.
  */
 #define KVADDR(l4, l3, l2, l1) ( \
@@ -116,34 +111,50 @@
 	((unsigned long)(l2) << PDRSHIFT) | \
 	((unsigned long)(l1) << PAGE_SHIFT))
 
+/*
+ * The six fields in the long mode virtual address
+ *
+ *  |63    48|47      39|38     30|29    21|20    12|11       0|
+ *  |--------|----------|---------|--------|--------|----------|
+ *  |   Ext  |   PML4   |   PDP   |   PD   |   PT   |  offset  |
+ *  |--------|----------|---------|--------|--------|----------|
+ *  
+ * There are totally 512 entries in each table of PML4, PDP, PD, or PT field.
+ * Each entry takes 64-bit (8 bytes) and a 4-Kb page is able to hold exactly 
+ * the 512 entries. Each PML4 entry covers 512GB (2**39) vm space; each PDP 
+ * entry covers 1GB (2**30) vm space; each PD entry cover 2MB (2**21) vm space
+ * and each PT entry covers 4KB(2**12) vm space, the page size.   
+ *
+ * We allocate the 512 PML4 entries in this way: 
+ * User space: one PML4 entry (512GB);
+ * Kernel space: one PML4 entry; 
+ * Each cpu in the system: one PML4 entry is reserved for private use;
+ * On PML4 entry is used to directly map all the physical space;
+ */
 
-#define NKPML4E		1
-#define NKPDPE		1
-#define NKPDE		(NKPDPE*NPDEPG)
+#define NKPML4E		1	/* number of PML4 entries for kernel map */
+#define NKPDPE		1	/* number of PDP entries for kernel map */
+#define NKPDE		(NKPDPE*NPDEPG)	/* number of PD entries for kernel map */
 
-#define NUPML4E		(NPML4EPG/2)
+#define NUPML4E		1	/* number of PML4 entries for user map */
 #define NUPDPE		(NUPML4E*NPDPEPG)
 #define NUPDE		(NUPDPE*NPDEPG)
 
+#define NDMPML4E	1	/* number of PML4 entries for direct map */
 
 /*
  * 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)	/* pml4 entry for kernel map */
+#define KPDPI		(NPDPEPG-1)	/* pdp entry for kernel map */
+
+#define UPML4I		(NPML4EPG-2)	/* pml4 entry for user map */
 
-#define KPML4I		(NPML4EPG-1)
+#define DMPML4I		(NPML4EPG-3)	/* pml4 entry for direct map */
 
-#define KPDPI		(NPDPEPG-2)
+/* The index for per-cpu PML4 entries, starting from 256 till the end (511).
+ * So we totally have 256 PML4 entries, meaning support up to 256 CPUs  */
+#define MPPML4I		(NPML4EPG/2)    /* pml4 entries per-cpu */
 
 /*
  * XXX doesn't really belong here I guess...
@@ -188,7 +199,7 @@
 {
 	vm_paddr_t pa;
 
-	if ((pa = (vm_offset_t) PTD[va >> PDRSHIFT]) & PG_PS) {
+	if ((pa = (vm_offset_t) PTD[va >> PDRSHIFT]) & PG_PAT) {
 		pa = (pa & ~(NBPDR - 1)) | (va & (NBPDR - 1));
 	} else {
 		pa = *(vm_offset_t *)vtopte(va);
Index: sys/cpu/amd64/include/segments.h
===================================================================
RCS file: /home/dcvs/src/sys/cpu/amd64/include/segments.h,v
retrieving revision 1.2
diff -u -r1.2 segments.h
--- sys/cpu/amd64/include/segments.h	23 Sep 2007 04:29:30 -0000	1.2
+++ sys/cpu/amd64/include/segments.h	10 Feb 2008 11:48:09 -0000
@@ -14,10 +14,6 @@
  * 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.
@@ -35,22 +31,22 @@
  * SUCH DAMAGE.
  *
  *	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 $
+ * $FreeBSD: src/sys/amd64/include/segments.h,v 1.39 2007/03/30 00:06:21 jkim Exp $
+ * $DragonFly $
  */
 
-#ifndef _CPU_SEGMENTS_H_
-#define	_CPU_SEGMENTS_H_
+#ifndef _MACHINE_SEGMENTS_H_
+#define	_MACHINE_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	SEL_RPL_MASK	3	/* requester priv level */
 #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 */
@@ -60,66 +56,67 @@
 #define	LSEL(s,r)	(((s)<<3) | SEL_LDT | r)	/* a local selector */
 #define	GSEL(s,r)	(((s)<<3) | r)			/* a global selector */
 
-#ifndef LOCORE
-
-/*
- * Memory and System segment descriptors
- */
-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) */
-} ;
-
 /*
- * Gate descriptors (e.g. indirect descriptors)
- */
-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) */
-} ;
-
-/*
- * Generic descriptor
- */
-union	descriptor	{
-	struct	segment_descriptor sd;
-	struct	gate_descriptor gd;
-};
+ * 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	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;
+
+/*
+ * System segment descriptors (128 bit wide)
+ */
+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;
+
+/*
+ * Gate descriptors (e.g. indirect descriptors, trap, interrupt etc. 128 bit)
+ * Only interrupt and trap gates have gd_ist.
+ */
+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 */
+	/* 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 */
@@ -139,76 +136,61 @@
 #define	SDT_MEMERC	30	/* memory execute read conforming */
 #define	SDT_MEMERAC	31	/* memory execute read accessed conforming */
 
-
-#ifndef LOCORE
-
-/* is memory segment descriptor pointer ? */
-#define ISMEMSDP(s)	((s->d_type) >= SDT_MEMRO && (s->d_type) <= SDT_MEMERAC)
-
-/* is 286 gate descriptor pointer ? */
-#define IS286GDP(s)	(((s->d_type) >= SDT_SYS286CGT \
-				 && (s->d_type) < SDT_SYS286TGT))
-
-/* is 386 gate descriptor pointer ? */
-#define IS386GDP(s)	(((s->d_type) >= SDT_SYS386CGT \
-				&& (s->d_type) < SDT_SYS386TGT))
-
-/* is gate descriptor pointer ? */
-#define ISGDP(s)	(IS286GDP(s) || IS386GDP(s))
-
-/* is segment descriptor pointer ? */
-#define ISSDP(s)	(ISMEMSDP(s) || !ISGDP(s))
-
-/* is system segment descriptor pointer ? */
-#define ISSYSSDP(s)	(!ISMEMSDP(s) && !ISGDP(s))
-
 /*
  * Software definitions are in this convenient format,
  * which are translated into inconvenient segment descriptors
  * 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 {
+	unsigned long ssd_base;		/* segment base address  */
+	unsigned long ssd_limit;	/* segment extent */
+	unsigned long ssd_type:5;	/* segment type */
+	unsigned long ssd_dpl:2;	/* segment descriptor priority level */
+	unsigned long ssd_p:1;		/* segment descriptor present */
+	unsigned long ssd_long:1;	/* long mode (for %cs) */
+	unsigned long ssd_def32:1;	/* default 32 vs 16 bit size */
+	unsigned long 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  */
-};
-
-#endif /* LOCORE */
-
-/*
- * Segment Protection Exception code bits
- */
-
-#define	SEGEX_EXT	0x01	/* recursive or externally induced */
-#define	SEGEX_IDT	0x02	/* interrupt descriptor table */
-#define	SEGEX_TI	0x04	/* local descriptor table */
-				/* other bits are affected descriptor index */
-#define SEGEX_IDX(s)	((s)>>3)&0x1fff)
-
-/*
- * Size of the IDT table.  Theoretically we only need to cover past 0x81 
- * (NIDT=130) if not running APIC_IO or SMP, but at this point we might
- * as well just use all of them.
- */
-#define	NIDT	256		/* we use them all */
+	unsigned long rd_limit:16;		/* segment extent */
+	unsigned long rd_base:64 __packed;	/* base address  */
+} __packed;
+
+/*
+ * Size of IDT table
+ */
+#define	NIDT	256		/* 32 reserved, 16 h/w, 0 s/w, linux's 0x80 */
+#define	NRSVIDT	32		/* reserved entries for cpu exceptions */
+
+/*
+ * 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,60 +198,27 @@
 #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)
-
-#ifndef LOCORE
-struct savetls {
-	struct segment_descriptor tls[NGTLS];
-};
+#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 6 is second half of GPROC0_SEL */
+#define	GUGS32_SEL	8	/* User 32 bit GS Descriptor */
+#define	NGDT 		9
 
 #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];
+extern struct region_descriptor r_gdt, r_idt;
 
-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 */
 
-#endif /* !_CPU_SEGMENTS_H_ */
+#endif /* !_MACHINE_SEGMENTS_H_ */
Index: sys/emulation/linux/amd64/Makefile
===================================================================
RCS file: sys/emulation/linux/amd64/Makefile
diff -N sys/emulation/linux/amd64/Makefile
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/emulation/linux/amd64/Makefile	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,16 @@
+# Makefile for syscall tables
+#
+# $FreeBSD: src/sys/amd64/linux32/Makefile,v 1.1 2004/08/16 07:55:06 tjr Exp $
+# $DragonFly$
+
+all:
+	@echo "make sysent only"
+
+sysent:  linux32_sysent.c linux32_syscall.h linux32_proto.h
+
+linux32_sysent.c linux32_syscall.h linux32_proto.h: ../../kern/makesyscalls.sh \
+		syscalls.master syscalls.conf
+	-mv -f linux32_sysent.c linux32_sysent.c.bak
+	-mv -f linux32_syscall.h linux32_syscall.h.bak
+	-mv -f linux32_proto.h linux32_proto.h.bak
+	sh ../../kern/makesyscalls.sh syscalls.master syscalls.conf
Index: sys/emulation/linux/amd64/linux.h
===================================================================
RCS file: sys/emulation/linux/amd64/linux.h
diff -N sys/emulation/linux/amd64/linux.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/emulation/linux/amd64/linux.h	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,873 @@
+/*-
+ * Copyright (c) 2004 Tim J. Robbins
+ * Copyright (c) 2001 Doug Rabson
+ * Copyright (c) 1994-1996 Søren Schmidt
+ * 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
+ *    in this position and unchanged.
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * 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.
+ *
+ * $FreeBSD: src/sys/amd64/linux32/linux.h,v 1.15 2007/03/29 02:11:46 julian Exp $
+ * $DragonFly$
+ */
+
+#ifndef _AMD64_LINUX_H_
+#define	_AMD64_LINUX_H_
+
+#include <amd64/linux32/linux32_syscall.h>
+
+/*
+ * debugging support
+ */
+extern u_char linux_debug_map[];
+#define	ldebug(name)	isclr(linux_debug_map, LINUX_SYS_linux_ ## name)
+#define	ARGS(nm, fmt)	"linux(%ld): "#nm"("fmt")\n", (long)td->td_proc->p_pid
+#define	LMSG(fmt)	"linux(%ld): "fmt"\n", (long)td->td_proc->p_pid
+
+#ifdef MALLOC_DECLARE
+MALLOC_DECLARE(M_LINUX);
+#endif
+
+#define	LINUX32_USRSTACK	((1ul << 32) - PAGE_SIZE)
+/* XXX 16 = sizeof(linux32_ps_strings) */
+#define	LINUX32_PS_STRINGS	(LINUX32_USRSTACK - 16)
+#define	LINUX32_MAXDSIZ		(512 * 1024 * 1024)	/* 512MB */
+#define	LINUX32_MAXSSIZ		(64 * 1024 * 1024)	/* 64MB */
+#define	LINUX32_MAXVMEM		0			/* Unlimited */
+
+#define	PTRIN(v)	(void *)(uintptr_t)(v)
+#define	PTROUT(v)	(l_uintptr_t)(uintptr_t)(v)
+
+/*
+ * Provide a separate set of types for the Linux types.
+ */
+typedef int		l_int;
+typedef int32_t		l_long;
+typedef int64_t		l_longlong;
+typedef short		l_short;
+typedef unsigned int	l_uint;
+typedef uint32_t	l_ulong;
+typedef uint64_t	l_ulonglong;
+typedef unsigned short	l_ushort;
+
+typedef l_ulong		l_uintptr_t;
+typedef l_long		l_clock_t;
+typedef l_int		l_daddr_t;
+typedef l_ushort	l_dev_t;
+typedef l_uint		l_gid_t;
+typedef l_ushort	l_gid16_t;
+typedef l_ulong		l_ino_t;
+typedef l_int		l_key_t;
+typedef l_longlong	l_loff_t;
+typedef l_ushort	l_mode_t;
+typedef l_long		l_off_t;
+typedef l_int		l_pid_t;
+typedef l_uint		l_size_t;
+typedef l_long		l_suseconds_t;
+typedef l_long		l_time_t;
+typedef l_uint		l_uid_t;
+typedef l_ushort	l_uid16_t;
+
+typedef struct {
+	l_int		val[2];
+} __packed l_fsid_t;
+
+typedef struct {
+	l_time_t	tv_sec;
+	l_suseconds_t	tv_usec;
+} __packed l_timeval;
+
+#define	l_fd_set	fd_set
+
+/*
+ * Miscellaneous
+ */
+#define	LINUX_NAME_MAX		255
+#define	LINUX_MAX_UTSNAME	65
+
+#define	LINUX_CTL_MAXNAME	10
+
+struct l___sysctl_args
+{
+	l_uintptr_t	name;
+	l_int		nlen;
+	l_uintptr_t	oldval;
+	l_uintptr_t	oldlenp;
+	l_uintptr_t	newval;
+	l_size_t	newlen;
+	l_ulong		__spare[4];
+} __packed;
+
+/* Scheduling policies */
+#define	LINUX_SCHED_OTHER	0
+#define	LINUX_SCHED_FIFO	1
+#define	LINUX_SCHED_RR		2
+
+/* Resource limits */
+#define	LINUX_RLIMIT_CPU	0
+#define	LINUX_RLIMIT_FSIZE	1
+#define	LINUX_RLIMIT_DATA	2
+#define	LINUX_RLIMIT_STACK	3
+#define	LINUX_RLIMIT_CORE	4
+#define	LINUX_RLIMIT_RSS	5
+#define	LINUX_RLIMIT_NPROC	6
+#define	LINUX_RLIMIT_NOFILE	7
+#define	LINUX_RLIMIT_MEMLOCK	8
+#define	LINUX_RLIMIT_AS		9	/* Address space limit */
+
+#define	LINUX_RLIM_NLIMITS	10
+
+struct l_rlimit {
+	l_ulong rlim_cur;
+	l_ulong rlim_max;
+} __packed;
+
+struct l_rusage {
+	l_timeval ru_utime;
+	l_timeval ru_stime;
+	l_long	ru_maxrss;
+	l_long	ru_ixrss;
+	l_long	ru_idrss;
+	l_long	ru_isrss;
+	l_long	ru_minflt;
+	l_long	ru_majflt;
+	l_long	ru_nswap;
+	l_long	ru_inblock;
+	l_long	ru_oublock;
+	l_long	ru_msgsnd;
+	l_long	ru_msgrcv;
+	l_long	ru_nsignals;
+	l_long	ru_nvcsw;
+	l_long	ru_nivcsw;
+} __packed;
+
+/* mmap options */
+#define	LINUX_MAP_SHARED	0x0001
+#define	LINUX_MAP_PRIVATE	0x0002
+#define	LINUX_MAP_FIXED		0x0010
+#define	LINUX_MAP_ANON		0x0020
+#define	LINUX_MAP_GROWSDOWN	0x0100
+
+struct l_mmap_argv {
+	l_uintptr_t	addr;
+	l_size_t	len;
+	l_int		prot;
+	l_int		flags;
+	l_int		fd;
+	l_off_t		pgoff;
+} __packed;
+
+/*
+ * stat family of syscalls
+ */
+struct l_timespec {
+	l_time_t	tv_sec;
+	l_long		tv_nsec;
+} __packed;
+
+struct l_newstat {
+	l_ushort	st_dev;
+	l_ushort	__pad1;
+	l_ulong		st_ino;
+	l_ushort	st_mode;
+	l_ushort	st_nlink;
+	l_ushort	st_uid;
+	l_ushort	st_gid;
+	l_ushort	st_rdev;
+	l_ushort	__pad2;
+	l_ulong		st_size;
+	l_ulong		st_blksize;
+	l_ulong		st_blocks;
+	struct l_timespec	st_atimespec;
+	struct l_timespec	st_mtimespec;
+	struct l_timespec	st_ctimespec;
+	l_ulong		__unused4;
+	l_ulong		__unused5;
+} __packed;
+
+struct l_stat {
+	l_ushort	st_dev;
+	l_ulong		st_ino;
+	l_ushort	st_mode;
+	l_ushort	st_nlink;
+	l_ushort	st_uid;
+	l_ushort	st_gid;
+	l_ushort	st_rdev;
+	l_long		st_size;
+	struct l_timespec	st_atimespec;
+	struct l_timespec	st_mtimespec;
+	struct l_timespec	st_ctimespec;
+	l_long		st_blksize;
+	l_long		st_blocks;
+	l_ulong		st_flags;
+	l_ulong		st_gen;
+};
+
+struct l_stat64 {
+	l_ushort	st_dev;
+	u_char		__pad0[10];
+	l_ulong		__st_ino;
+	l_uint		st_mode;
+	l_uint		st_nlink;
+	l_ulong		st_uid;
+	l_ulong		st_gid;
+	l_ushort	st_rdev;
+	u_char		__pad3[10];
+	l_longlong	st_size;
+	l_ulong		st_blksize;
+	l_ulong		st_blocks;
+	l_ulong		__pad4;
+	struct l_timespec	st_atimespec;
+	struct l_timespec	st_mtimespec;
+	struct l_timespec	st_ctimespec;
+	l_ulonglong	st_ino;
+} __packed;
+
+struct l_new_utsname {
+	char	sysname[LINUX_MAX_UTSNAME];
+	char	nodename[LINUX_MAX_UTSNAME];
+	char	release[LINUX_MAX_UTSNAME];
+	char	version[LINUX_MAX_UTSNAME];
+	char	machine[LINUX_MAX_UTSNAME];
+	char	domainname[LINUX_MAX_UTSNAME];
+} __packed;
+
+/*
+ * Signalling
+ */
+#define	LINUX_SIGHUP		1
+#define	LINUX_SIGINT		2
+#define	LINUX_SIGQUIT		3
+#define	LINUX_SIGILL		4
+#define	LINUX_SIGTRAP		5
+#define	LINUX_SIGABRT		6
+#define	LINUX_SIGIOT		LINUX_SIGABRT
+#define	LINUX_SIGBUS		7
+#define	LINUX_SIGFPE		8
+#define	LINUX_SIGKILL		9
+#define	LINUX_SIGUSR1		10
+#define	LINUX_SIGSEGV		11
+#define	LINUX_SIGUSR2		12
+#define	LINUX_SIGPIPE		13
+#define	LINUX_SIGALRM		14
+#define	LINUX_SIGTERM		15
+#define	LINUX_SIGSTKFLT		16
+#define	LINUX_SIGCHLD		17
+#define	LINUX_SIGCONT		18
+#define	LINUX_SIGSTOP		19
+#define	LINUX_SIGTSTP		20
+#define	LINUX_SIGTTIN		21
+#define	LINUX_SIGTTOU		22
+#define	LINUX_SIGURG		23
+#define	LINUX_SIGXCPU		24
+#define	LINUX_SIGXFSZ		25
+#define	LINUX_SIGVTALRM		26
+#define	LINUX_SIGPROF		27
+#define	LINUX_SIGWINCH		28
+#define	LINUX_SIGIO		29
+#define	LINUX_SIGPOLL		LINUX_SIGIO
+#define	LINUX_SIGPWR		30
+#define	LINUX_SIGSYS		31
+
+#define	LINUX_SIGTBLSZ		31
+#define	LINUX_NSIG_WORDS	2
+#define	LINUX_NBPW		32
+#define	LINUX_NSIG		(LINUX_NBPW * LINUX_NSIG_WORDS)
+
+/* sigaction flags */
+#define	LINUX_SA_NOCLDSTOP	0x00000001
+#define	LINUX_SA_NOCLDWAIT	0x00000002
+#define	LINUX_SA_SIGINFO	0x00000004
+#define	LINUX_SA_RESTORER	0x04000000
+#define	LINUX_SA_ONSTACK	0x08000000
+#define	LINUX_SA_RESTART	0x10000000
+#define	LINUX_SA_INTERRUPT	0x20000000
+#define	LINUX_SA_NOMASK		0x40000000
+#define	LINUX_SA_ONESHOT	0x80000000
+
+/* sigprocmask actions */
+#define	LINUX_SIG_BLOCK		0
+#define	LINUX_SIG_UNBLOCK	1
+#define	LINUX_SIG_SETMASK	2
+
+/* sigset_t macros */
+#define	LINUX_SIGEMPTYSET(set)		(set).__bits[0] = (set).__bits[1] = 0
+#define	LINUX_SIGISMEMBER(set, sig)	SIGISMEMBER(set, sig)
+#define	LINUX_SIGADDSET(set, sig)	SIGADDSET(set, sig)
+
+/* sigaltstack */
+#define	LINUX_MINSIGSTKSZ	2048
+#define	LINUX_SS_ONSTACK	1
+#define	LINUX_SS_DISABLE	2
+
+int linux_to_bsd_sigaltstack(int lsa);
+int bsd_to_linux_sigaltstack(int bsa);
+
+typedef l_uintptr_t l_handler_t;
+typedef l_ulong	l_osigset_t;
+
+typedef struct {
+	l_uint	__bits[LINUX_NSIG_WORDS];
+} __packed l_sigset_t;
+
+typedef struct {
+	l_handler_t	lsa_handler;
+	l_osigset_t	lsa_mask;
+	l_ulong		lsa_flags;
+	l_uintptr_t	lsa_restorer;
+} __packed l_osigaction_t;
+
+typedef struct {
+	l_handler_t	lsa_handler;
+	l_ulong		lsa_flags;
+	l_uintptr_t	lsa_restorer;
+	l_sigset_t	lsa_mask;
+} __packed l_sigaction_t;
+
+typedef struct {
+	l_uintptr_t	ss_sp;
+	l_int		ss_flags;
+	l_size_t	ss_size;
+} __packed l_stack_t;
+
+/* The Linux sigcontext, pretty much a standard 386 trapframe. */
+struct l_sigcontext {
+	l_int		sc_gs;
+	l_int		sc_fs;
+	l_int		sc_es;
+	l_int		sc_ds;
+	l_int		sc_edi;
+	l_int		sc_esi;
+	l_int		sc_ebp;
+	l_int		sc_esp;
+	l_int		sc_ebx;
+	l_int		sc_edx;
+	l_int		sc_ecx;
+	l_int		sc_eax;
+	l_int		sc_trapno;
+	l_int		sc_err;
+	l_int		sc_eip;
+	l_int		sc_cs;
+	l_int		sc_eflags;
+	l_int		sc_esp_at_signal;
+	l_int		sc_ss;
+	l_int		sc_387;
+	l_int		sc_mask;
+	l_int		sc_cr2;
+} __packed;
+
+struct l_ucontext {
+	l_ulong		uc_flags;
+	l_uintptr_t	uc_link;
+	l_stack_t	uc_stack;
+	struct l_sigcontext	uc_mcontext;
+	l_sigset_t	uc_sigmask;
+} __packed;
+
+#define	LINUX_SI_MAX_SIZE	128
+#define	LINUX_SI_PAD_SIZE	((LINUX_SI_MAX_SIZE/sizeof(l_int)) - 3)
+
+union l_sigval {
+	l_int		sival_int;
+	l_uintptr_t	sival_ptr;
+};
+
+typedef struct l_siginfo {
+	l_int		lsi_signo;
+	l_int		lsi_errno;
+	l_int		lsi_code;
+	union {
+		l_int	_pad[LINUX_SI_PAD_SIZE];
+
+		struct {
+			l_pid_t		_pid;
+			l_uid16_t	_uid;
+		} __packed _kill;
+
+		struct {
+			l_uint		_timer1;
+			l_uint		_timer2;
+		} __packed _timer;
+
+		struct {
+			l_pid_t		_pid;		/* sender's pid */
+			l_uid16_t	_uid;		/* sender's uid */
+			union l_sigval _sigval;
+		} __packed _rt;
+
+		struct {
+			l_pid_t		_pid;		/* which child */
+			l_uid16_t	_uid;		/* sender's uid */
+			l_int		_status;	/* exit code */
+			l_clock_t	_utime;
+			l_clock_t	_stime;
+		} __packed _sigchld;
+
+		struct {
+			l_uintptr_t	_addr;	/* Faulting insn/memory ref. */
+		} __packed _sigfault;
+
+		struct {
+			l_int		_band;	/* POLL_IN,POLL_OUT,POLL_MSG */
+			l_int		_fd;
+		} __packed _sigpoll;
+	} _sifields;
+} __packed l_siginfo_t;
+
+#define	lsi_pid		_sifields._kill._pid
+#define	lsi_uid		_sifields._kill._uid
+#define	lsi_status	_sifields._sigchld._status
+#define	lsi_utime	_sifields._sigchld._utime
+#define	lsi_stime	_sifields._sigchld._stime
+#define	lsi_value	_sifields._rt._sigval
+#define	lsi_int		_sifields._rt._sigval.sival_int
+#define	lsi_ptr		_sifields._rt._sigval.sival_ptr
+#define	lsi_addr	_sifields._sigfault._addr
+#define	lsi_band	_sifields._sigpoll._band
+#define	lsi_fd		_sifields._sigpoll._fd
+
+struct l_fpreg {
+	u_int16_t	significand[4];
+	u_int16_t	exponent;
+} __packed;
+
+struct l_fpxreg {
+	u_int16_t	significand[4];
+	u_int16_t	exponent;
+	u_int16_t	padding[3];
+} __packed;
+
+struct l_xmmreg {
+	u_int32_t	element[4];
+} __packed;
+
+struct l_fpstate {
+	/* Regular FPU environment */
+	u_int32_t		cw;
+	u_int32_t		sw;
+	u_int32_t		tag;
+	u_int32_t		ipoff;
+	u_int32_t		cssel;
+	u_int32_t		dataoff;
+	u_int32_t		datasel;
+	struct l_fpreg		_st[8];
+	u_int16_t		status;
+	u_int16_t		magic;		/* 0xffff = regular FPU data */
+
+	/* FXSR FPU environment */
+	u_int32_t		_fxsr_env[6];	/* env is ignored. */
+	u_int32_t		mxcsr;
+	u_int32_t		reserved;
+	struct l_fpxreg		_fxsr_st[8];	/* reg data is ignored. */
+	struct l_xmmreg		_xmm[8];
+	u_int32_t		padding[56];
+} __packed;
+
+/*
+ * We make the stack look like Linux expects it when calling a signal
+ * handler, but use the BSD way of calling the handler and sigreturn().
+ * This means that we need to pass the pointer to the handler too.
+ * It is appended to the frame to not interfere with the rest of it.
+ */
+struct l_sigframe {
+	l_int			sf_sig;
+	struct l_sigcontext	sf_sc;
+	struct l_fpstate	sf_fpstate;
+	l_uint			sf_extramask[LINUX_NSIG_WORDS-1];
+	l_handler_t		sf_handler;
+} __packed;
+
+struct l_rt_sigframe {
+	l_int			sf_sig;
+	l_uintptr_t 		sf_siginfo;
+	l_uintptr_t		sf_ucontext;
+	l_siginfo_t		sf_si;
+	struct l_ucontext 	sf_sc;
+	l_handler_t 		sf_handler;
+} __packed;
+
+extern int bsd_to_linux_signal[];
+extern int linux_to_bsd_signal[];
+extern struct sysentvec elf_linux_sysvec;
+
+/*
+ * Pluggable ioctl handlers
+ */
+struct linux_ioctl_args;
+struct thread;
+
+typedef int linux_ioctl_function_t(struct thread *, struct linux_ioctl_args *);
+
+struct linux_ioctl_handler {
+	linux_ioctl_function_t *func;
+	int	low, high;
+};
+
+int	linux_ioctl_register_handler(struct linux_ioctl_handler *h);
+int	linux_ioctl_unregister_handler(struct linux_ioctl_handler *h);
+
+/*
+ * open/fcntl flags
+ */
+#define	LINUX_O_RDONLY		00000000
+#define	LINUX_O_WRONLY		00000001
+#define	LINUX_O_RDWR		00000002
+#define	LINUX_O_ACCMODE		00000003
+#define	LINUX_O_CREAT		00000100
+#define	LINUX_O_EXCL		00000200
+#define	LINUX_O_NOCTTY		00000400
+#define	LINUX_O_TRUNC		00001000
+#define	LINUX_O_APPEND		00002000
+#define	LINUX_O_NONBLOCK	00004000
+#define	LINUX_O_NDELAY		LINUX_O_NONBLOCK
+#define	LINUX_O_SYNC		00010000
+#define	LINUX_FASYNC		00020000
+#define	LINUX_O_DIRECT		00040000	/* Direct disk access hint */
+#define	LINUX_O_LARGEFILE	00100000
+#define	LINUX_O_DIRECTORY	00200000	/* Must be a directory */
+#define	LINUX_O_NOFOLLOW	00400000	/* Do not follow links */
+#define	LINUX_O_NOATIME		01000000
+
+#define	LINUX_F_DUPFD		0
+#define	LINUX_F_GETFD		1
+#define	LINUX_F_SETFD		2
+#define	LINUX_F_GETFL		3
+#define	LINUX_F_SETFL		4
+#define	LINUX_F_GETLK		5
+#define	LINUX_F_SETLK		6
+#define	LINUX_F_SETLKW		7
+#define	LINUX_F_SETOWN		8
+#define	LINUX_F_GETOWN		9
+
+#define	LINUX_F_GETLK64		12
+#define	LINUX_F_SETLK64		13
+#define	LINUX_F_SETLKW64	14
+
+#define	LINUX_F_RDLCK		0
+#define	LINUX_F_WRLCK		1
+#define	LINUX_F_UNLCK		2
+
+#define	LINUX_AT_FDCWD		-100
+
+/*
+ * mount flags
+ */
+#define	LINUX_MS_RDONLY		0x0001
+#define	LINUX_MS_NOSUID		0x0002
+#define	LINUX_MS_NODEV		0x0004
+#define	LINUX_MS_NOEXEC		0x0008
+#define	LINUX_MS_REMOUNT	0x0020
+
+/*
+ * SystemV IPC defines
+ */
+#define	LINUX_SEMOP		1
+#define	LINUX_SEMGET		2
+#define	LINUX_SEMCTL		3
+#define	LINUX_MSGSND		11
+#define	LINUX_MSGRCV		12
+#define	LINUX_MSGGET		13
+#define	LINUX_MSGCTL		14
+#define	LINUX_SHMAT		21
+#define	LINUX_SHMDT		22
+#define	LINUX_SHMGET		23
+#define	LINUX_SHMCTL		24
+
+#define	LINUX_IPC_RMID		0
+#define	LINUX_IPC_SET		1
+#define	LINUX_IPC_STAT		2
+#define	LINUX_IPC_INFO		3
+
+#define	LINUX_SHM_LOCK		11
+#define	LINUX_SHM_UNLOCK	12
+#define	LINUX_SHM_STAT		13
+#define	LINUX_SHM_INFO		14
+
+#define	LINUX_SHM_RDONLY	0x1000
+#define	LINUX_SHM_RND		0x2000
+#define	LINUX_SHM_REMAP		0x4000
+
+/* semctl commands */
+#define	LINUX_GETPID		11
+#define	LINUX_GETVAL		12
+#define	LINUX_GETALL		13
+#define	LINUX_GETNCNT		14
+#define	LINUX_GETZCNT		15
+#define	LINUX_SETVAL		16
+#define	LINUX_SETALL		17
+#define	LINUX_SEM_STAT		18
+#define	LINUX_SEM_INFO		19
+
+union l_semun {
+	l_int		val;
+	l_uintptr_t	buf;
+	l_uintptr_t	array;
+	l_uintptr_t	__buf;
+	l_uintptr_t	__pad;
+} __packed;
+
+/*
+ * Socket defines
+ */
+#define	LINUX_SOCKET 		1
+#define	LINUX_BIND		2
+#define	LINUX_CONNECT 		3
+#define	LINUX_LISTEN 		4
+#define	LINUX_ACCEPT 		5
+#define	LINUX_GETSOCKNAME	6
+#define	LINUX_GETPEERNAME	7
+#define	LINUX_SOCKETPAIR	8
+#define	LINUX_SEND		9
+#define	LINUX_RECV		10
+#define	LINUX_SENDTO 		11
+#define	LINUX_RECVFROM 		12
+#define	LINUX_SHUTDOWN 		13
+#define	LINUX_SETSOCKOPT	14
+#define	LINUX_GETSOCKOPT	15
+#define	LINUX_SENDMSG		16
+#define	LINUX_RECVMSG		17
+
+#define	LINUX_AF_UNSPEC		0
+#define	LINUX_AF_UNIX		1
+#define	LINUX_AF_INET		2
+#define	LINUX_AF_AX25		3
+#define	LINUX_AF_IPX		4
+#define	LINUX_AF_APPLETALK	5
+#define	LINUX_AF_INET6		10
+
+#define	LINUX_SOL_SOCKET	1
+#define	LINUX_SOL_IP		0
+#define	LINUX_SOL_IPX		256
+#define	LINUX_SOL_AX25		257
+#define	LINUX_SOL_TCP		6
+#define	LINUX_SOL_UDP		17
+
+#define	LINUX_SO_DEBUG		1
+#define	LINUX_SO_REUSEADDR	2
+#define	LINUX_SO_TYPE		3
+#define	LINUX_SO_ERROR		4
+#define	LINUX_SO_DONTROUTE	5
+#define	LINUX_SO_BROADCAST	6
+#define	LINUX_SO_SNDBUF		7
+#define	LINUX_SO_RCVBUF		8
+#define	LINUX_SO_KEEPALIVE	9
+#define	LINUX_SO_OOBINLINE	10
+#define	LINUX_SO_NO_CHECK	11
+#define	LINUX_SO_PRIORITY	12
+#define	LINUX_SO_LINGER		13
+#define	LINUX_SO_PEERCRED	17
+#define	LINUX_SO_RCVLOWAT	18
+#define	LINUX_SO_SNDLOWAT	19
+#define	LINUX_SO_RCVTIMEO	20
+#define	LINUX_SO_SNDTIMEO	21
+#define	LINUX_SO_TIMESTAMP	29
+#define	LINUX_SO_ACCEPTCONN	30
+
+#define	LINUX_IP_TOS		1
+#define	LINUX_IP_TTL		2
+#define	LINUX_IP_HDRINCL	3
+#define	LINUX_IP_OPTIONS	4
+
+#define	LINUX_IP_MULTICAST_IF		32
+#define	LINUX_IP_MULTICAST_TTL		33
+#define	LINUX_IP_MULTICAST_LOOP		34
+#define	LINUX_IP_ADD_MEMBERSHIP		35
+#define	LINUX_IP_DROP_MEMBERSHIP	36
+
+struct l_sockaddr {
+	l_ushort	sa_family;
+	char		sa_data[14];
+} __packed;
+
+struct l_ifmap {
+	l_ulong		mem_start;
+	l_ulong		mem_end;
+	l_ushort	base_addr;
+	u_char		irq;
+	u_char		dma;
+	u_char		port;
+} __packed;
+
+#define	LINUX_IFHWADDRLEN	6
+#define	LINUX_IFNAMSIZ		16
+
+struct l_ifreq {
+	union {
+		char	ifrn_name[LINUX_IFNAMSIZ];
+	} ifr_ifrn;
+
+	union {
+		struct l_sockaddr	ifru_addr;
+		struct l_sockaddr	ifru_dstaddr;
+		struct l_sockaddr	ifru_broadaddr;
+		struct l_sockaddr	ifru_netmask;
+		struct l_sockaddr	ifru_hwaddr;
+		l_short		ifru_flags[1];
+		l_int		ifru_metric;
+		l_int		ifru_mtu;
+		struct l_ifmap	ifru_map;
+		char		ifru_slave[LINUX_IFNAMSIZ];
+		l_uintptr_t	ifru_data;
+	} ifr_ifru;
+} __packed;
+
+#define	ifr_name	ifr_ifrn.ifrn_name	/* Interface name */
+#define	ifr_hwaddr	ifr_ifru.ifru_hwaddr	/* MAC address */
+
+struct l_ifconf {
+	int	ifc_len;
+	union {
+		l_uintptr_t	ifcu_buf;
+		l_uintptr_t	ifcu_req;
+	} ifc_ifcu;
+} __packed;
+
+#define	ifc_buf		ifc_ifcu.ifcu_buf
+#define	ifc_req		ifc_ifcu.ifcu_req
+
+/*
+ * poll()
+ */
+#define	LINUX_POLLIN		0x0001
+#define	LINUX_POLLPRI		0x0002
+#define	LINUX_POLLOUT		0x0004
+#define	LINUX_POLLERR		0x0008
+#define	LINUX_POLLHUP		0x0010
+#define	LINUX_POLLNVAL		0x0020
+#define	LINUX_POLLRDNORM	0x0040
+#define	LINUX_POLLRDBAND	0x0080
+#define	LINUX_POLLWRNORM	0x0100
+#define	LINUX_POLLWRBAND	0x0200
+#define	LINUX_POLLMSG		0x0400
+
+struct l_pollfd {
+	l_int		fd;
+	l_short		events;
+	l_short		revents;
+} __packed;
+
+struct l_user_desc {
+	l_uint		entry_number;
+	l_uint		base_addr;
+	l_uint		limit;
+	l_uint		seg_32bit:1;
+	l_uint		contents:2;
+	l_uint		read_exec_only:1;
+	l_uint		limit_in_pages:1;
+	l_uint		seg_not_present:1;
+	l_uint		useable:1;
+};
+
+#define	LINUX_LOWERWORD	0x0000ffff
+
+/*
+ * Macros which does the same thing as those in Linux include/asm-um/ldt-i386.h.
+ * These convert Linux user space descriptor to machine one.
+ */
+#define	LINUX_LDT_entry_a(info)					\
+	((((info)->base_addr & LINUX_LOWERWORD) << 16) |	\
+	((info)->limit & LINUX_LOWERWORD))
+
+#define	LINUX_ENTRY_B_READ_EXEC_ONLY	9
+#define	LINUX_ENTRY_B_CONTENTS		10
+#define	LINUX_ENTRY_B_SEG_NOT_PRESENT	15
+#define	LINUX_ENTRY_B_BASE_ADDR		16
+#define	LINUX_ENTRY_B_USEABLE		20
+#define	LINUX_ENTRY_B_SEG32BIT		22
+#define	LINUX_ENTRY_B_LIMIT		23
+
+#define	LINUX_LDT_entry_b(info)							\
+	(((info)->base_addr & 0xff000000) |					\
+	((info)->limit & 0xf0000) |						\
+	((info)->contents << LINUX_ENTRY_B_CONTENTS) |				\
+	(((info)->seg_not_present == 0) << LINUX_ENTRY_B_SEG_NOT_PRESENT) |	\
+	(((info)->base_addr & 0x00ff0000) >> LINUX_ENTRY_B_BASE_ADDR) |		\
+	(((info)->read_exec_only == 0) << LINUX_ENTRY_B_READ_EXEC_ONLY) |	\
+	((info)->seg_32bit << LINUX_ENTRY_B_SEG32BIT) |				\
+	((info)->useable << LINUX_ENTRY_B_USEABLE) |				\
+	((info)->limit_in_pages << LINUX_ENTRY_B_LIMIT) | 0x7000)
+
+#define	LINUX_LDT_empty(info)		\
+	((info)->base_addr == 0 &&	\
+	(info)->limit == 0 &&		\
+	(info)->contents == 0 &&	\
+	(info)->seg_not_present == 1 &&	\
+	(info)->read_exec_only == 1 &&	\
+	(info)->seg_32bit == 0 &&	\
+	(info)->limit_in_pages == 0 &&	\
+	(info)->useable == 0)
+
+/*
+ * Macros for converting segments.
+ * They do the same as those in arch/i386/kernel/process.c in Linux.
+ */
+#define	LINUX_GET_BASE(desc)				\
+	((((desc)->a >> 16) & LINUX_LOWERWORD) |	\
+	(((desc)->b << 16) & 0x00ff0000) |		\
+	((desc)->b & 0xff000000))
+
+#define	LINUX_GET_LIMIT(desc)			\
+	(((desc)->a & LINUX_LOWERWORD) |	\
+	((desc)->b & 0xf0000))
+
+#define	LINUX_GET_32BIT(desc)		\
+	(((desc)->b >> LINUX_ENTRY_B_SEG32BIT) & 1)
+#define	LINUX_GET_CONTENTS(desc)	\
+	(((desc)->b >> LINUX_ENTRY_B_CONTENTS) & 3)
+#define	LINUX_GET_WRITABLE(desc)	\
+	(((desc)->b >> LINUX_ENTRY_B_READ_EXEC_ONLY) & 1)
+#define	LINUX_GET_LIMIT_PAGES(desc)	\
+	(((desc)->b >> LINUX_ENTRY_B_LIMIT) & 1)
+#define	LINUX_GET_PRESENT(desc)		\
+	(((desc)->b >> LINUX_ENTRY_B_SEG_NOT_PRESENT) & 1)
+#define	LINUX_GET_USEABLE(desc)		\
+	(((desc)->b >> LINUX_ENTRY_B_USEABLE) & 1)
+
+#define	LINUX_CLOCK_REALTIME		0
+#define	LINUX_CLOCK_MONOTONIC		1
+#define	LINUX_CLOCK_PROCESS_CPUTIME_ID	2
+#define	LINUX_CLOCK_THREAD_CPUTIME_ID	3
+#define	LINUX_CLOCK_REALTIME_HR		4
+#define	LINUX_CLOCK_MONOTONIC_HR	5
+
+typedef int l_timer_t;
+typedef int l_mqd_t;
+
+#define	LINUX_CLONE_VM			0x00000100
+#define	LINUX_CLONE_FS			0x00000200
+#define	LINUX_CLONE_FILES		0x00000400
+#define	LINUX_CLONE_SIGHAND		0x00000800
+#define	LINUX_CLONE_PID			0x00001000	/* No longer exist in Linux */
+#define	LINUX_CLONE_VFORK		0x00004000
+#define	LINUX_CLONE_PARENT		0x00008000
+#define	LINUX_CLONE_THREAD		0x00010000
+#define	LINUX_CLONE_SETTLS		0x00080000
+#define	LINUX_CLONE_PARENT_SETTID	0x00100000
+#define	LINUX_CLONE_CHILD_CLEARTID	0x00200000
+#define	LINUX_CLONE_CHILD_SETTID	0x01000000
+
+#define	LINUX_THREADING_FLAGS					\
+	(LINUX_CLONE_VM | LINUX_CLONE_FS | LINUX_CLONE_FILES |	\
+	LINUX_CLONE_SIGHAND | LINUX_CLONE_THREAD)
+
+#endif /* !_AMD64_LINUX_H_ */
Index: sys/emulation/linux/amd64/linux32_dummy.c
===================================================================
RCS file: sys/emulation/linux/amd64/linux32_dummy.c
diff -N sys/emulation/linux/amd64/linux32_dummy.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/emulation/linux/amd64/linux32_dummy.c	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 1994-1995 Søren Schmidt
+ * 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 
+ *    in this position and unchanged.
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * 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.
+ *
+ * $FreeBSD: src/sys/amd64/linux32/linux32_dummy.c,v 1.9 2007/04/18 18:08:12 jkim Exp $
+ * $DragonFly$
+ */
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+
+#include <amd64/linux32/linux.h>
+#include <amd64/linux32/linux32_proto.h>
+#include <compat/linux/linux_util.h>
+
+DUMMY(stime);
+DUMMY(olduname);
+DUMMY(syslog);
+DUMMY(uname);
+DUMMY(vhangup);
+DUMMY(swapoff);
+DUMMY(adjtimex);
+DUMMY(create_module);
+DUMMY(init_module);
+DUMMY(delete_module);
+DUMMY(get_kernel_syms);
+DUMMY(quotactl);
+DUMMY(bdflush);
+DUMMY(sysfs);
+DUMMY(query_module);
+DUMMY(nfsservctl);
+DUMMY(rt_sigqueueinfo);
+DUMMY(capget);
+DUMMY(capset);
+DUMMY(sendfile);
+DUMMY(truncate64);
+DUMMY(setfsuid);
+DUMMY(setfsgid);
+DUMMY(pivot_root);
+DUMMY(mincore);
+DUMMY(fadvise64);
+DUMMY(ptrace);
+DUMMY(lookup_dcookie);
+DUMMY(epoll_create);
+DUMMY(epoll_ctl);
+DUMMY(epoll_wait);
+DUMMY(remap_file_pages);
+DUMMY(timer_create);
+DUMMY(timer_settime);
+DUMMY(timer_gettime);
+DUMMY(timer_getoverrun);
+DUMMY(timer_delete);
+DUMMY(fstatfs64);
+DUMMY(fadvise64_64);
+DUMMY(mbind);
+DUMMY(get_mempolicy);
+DUMMY(set_mempolicy);
+DUMMY(mq_open);
+DUMMY(mq_unlink);
+DUMMY(mq_timedsend);
+DUMMY(mq_timedreceive);
+DUMMY(mq_notify);
+DUMMY(mq_getsetattr);
+DUMMY(kexec_load);
+DUMMY(waitid);
+DUMMY(add_key);
+DUMMY(request_key);
+DUMMY(keyctl);
+DUMMY(ioprio_set);
+DUMMY(ioprio_get);
+DUMMY(inotify_init);
+DUMMY(inotify_add_watch);
+DUMMY(inotify_rm_watch);
+DUMMY(migrate_pages);
+DUMMY(mkdirat);
+DUMMY(mknodat);
+DUMMY(fchownat);
+DUMMY(futimesat);
+DUMMY(fstatat64);
+DUMMY(unlinkat);
+DUMMY(renameat);
+DUMMY(linkat);
+DUMMY(symlinkat);
+DUMMY(readlinkat);
+DUMMY(fchmodat);
+DUMMY(faccessat);
+DUMMY(pselect6);
+DUMMY(ppoll);
+DUMMY(unshare);
+
+#define DUMMY_XATTR(s)						\
+int								\
+linux_ ## s ## xattr(						\
+    struct thread *td, struct linux_ ## s ## xattr_args *arg)	\
+{								\
+								\
+	return (ENOATTR);					\
+}
+DUMMY_XATTR(set);
+DUMMY_XATTR(lset);
+DUMMY_XATTR(fset);
+DUMMY_XATTR(get);
+DUMMY_XATTR(lget);
+DUMMY_XATTR(fget);
+DUMMY_XATTR(list);
+DUMMY_XATTR(llist);
+DUMMY_XATTR(flist);
+DUMMY_XATTR(remove);
+DUMMY_XATTR(lremove);
+DUMMY_XATTR(fremove);
Index: sys/emulation/linux/amd64/linux32_genassym.c
===================================================================
RCS file: sys/emulation/linux/amd64/linux32_genassym.c
diff -N sys/emulation/linux/amd64/linux32_genassym.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/emulation/linux/amd64/linux32_genassym.c	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,19 @@
+/* 
+ * $FreeBSD: src/sys/amd64/linux32/linux32_genassym.c,v 1.1 2004/08/16 07:55:06 tjr Exp $
+ * $DragonFly$
+ */
+
+#include <sys/param.h>
+#include <sys/assym.h>
+#include <sys/systm.h>
+
+#include <amd64/linux32/linux.h>
+
+ASSYM(LINUX_SIGF_HANDLER, offsetof(struct l_sigframe, sf_handler));
+ASSYM(LINUX_SIGF_SC, offsetof(struct l_sigframe, sf_sc));
+ASSYM(LINUX_SC_GS, offsetof(struct l_sigcontext, sc_gs));
+ASSYM(LINUX_SC_FS, offsetof(struct l_sigcontext, sc_fs));
+ASSYM(LINUX_SC_ES, offsetof(struct l_sigcontext, sc_es));
+ASSYM(LINUX_SC_DS, offsetof(struct l_sigcontext, sc_ds));
+ASSYM(LINUX_RT_SIGF_HANDLER, offsetof(struct l_rt_sigframe, sf_handler));
+ASSYM(LINUX_RT_SIGF_UC, offsetof(struct l_rt_sigframe, sf_sc));
Index: sys/emulation/linux/amd64/linux32_ipc64.h
===================================================================
RCS file: sys/emulation/linux/amd64/linux32_ipc64.h
diff -N sys/emulation/linux/amd64/linux32_ipc64.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/emulation/linux/amd64/linux32_ipc64.h	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,146 @@
+/*-
+ * Copyright (c) 2002 Maxim Sobolev <sobomax@FreeBSD.org>
+ * 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 
+ *    in this position and unchanged.
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * 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.
+ *
+ * $FreeBSD: src/sys/amd64/linux32/linux32_ipc64.h,v 1.1 2004/08/16 07:55:06 tjr Exp $
+ * $DragonFly$
+ */
+
+#ifndef _AMD64_LINUX_LINUX_IPC64_H_
+#define	_AMD64_LINUX_LINUX_IPC64_H_
+
+/*
+ * The ipc64_perm structure for i386 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit mode_t and seq
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct l_ipc64_perm
+{
+	l_key_t		key;
+	l_uid_t		uid;
+	l_gid_t		gid;
+	l_uid_t		cuid;
+	l_gid_t		cgid;
+	l_mode_t	mode;
+	l_ushort	__pad1;
+	l_ushort	seq;
+	l_ushort	__pad2;
+	l_ulong		__unused1;
+	l_ulong		__unused2;
+} __packed;
+
+/*
+ * The msqid64_ds structure for i386 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct l_msqid64_ds {
+	struct l_ipc64_perm msg_perm;
+	l_time_t	msg_stime;	/* last msgsnd time */
+	l_ulong		__unused1;
+	l_time_t	msg_rtime;	/* last msgrcv time */
+	l_ulong		__unused2;
+	l_time_t	msg_ctime;	/* last change time */
+	l_ulong		__unused3;
+	l_ulong		msg_cbytes;	/* current number of bytes on queue */
+	l_ulong		msg_qnum;	/* number of messages in queue */
+	l_ulong		msg_qbytes;	/* max number of bytes on queue */
+	l_pid_t		msg_lspid;	/* pid of last msgsnd */
+	l_pid_t		msg_lrpid;	/* last receive pid */
+	l_ulong		__unused4;
+	l_ulong		__unused5;
+} __packed;
+
+/*
+ * The semid64_ds structure for i386 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct l_semid64_ds {
+	struct l_ipc64_perm sem_perm;	/* permissions */
+	l_time_t	sem_otime;	/* last semop time */
+	l_ulong		__unused1;
+	l_time_t	sem_ctime;	/* last change time */
+	l_ulong		__unused2;
+	l_ulong		sem_nsems;	/* no. of semaphores in array */
+	l_ulong		__unused3;
+	l_ulong		__unused4;
+} __packed;
+
+/*
+ * The shmid64_ds structure for i386 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct l_shmid64_ds {
+	struct l_ipc64_perm shm_perm;	/* operation perms */
+	l_size_t	shm_segsz;	/* size of segment (bytes) */
+	l_time_t	shm_atime;	/* last attach time */
+	l_ulong		__unused1;
+	l_time_t	shm_dtime;	/* last detach time */
+	l_ulong		__unused2;
+	l_time_t	shm_ctime;	/* last change time */
+	l_ulong		__unused3;
+	l_pid_t		shm_cpid;	/* pid of creator */
+	l_pid_t		shm_lpid;	/* pid of last operator */
+	l_ulong		shm_nattch;	/* no. of current attaches */
+	l_ulong		__unused4;
+	l_ulong		__unused5;
+} __packed;
+
+struct l_shminfo64 {
+	l_ulong   	shmmax;
+	l_ulong   	shmmin;
+	l_ulong   	shmmni;
+	l_ulong   	shmseg;
+	l_ulong   	shmall;
+	l_ulong   	__unused1;
+	l_ulong   	__unused2;
+	l_ulong   	__unused3;
+	l_ulong   	__unused4;
+} __packed;
+
+#endif /* !_AMD64_LINUX_LINUX_IPC64_H_ */
Index: sys/emulation/linux/amd64/linux32_locore.s
===================================================================
RCS file: sys/emulation/linux/amd64/linux32_locore.s
diff -N sys/emulation/linux/amd64/linux32_locore.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/emulation/linux/amd64/linux32_locore.s	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,44 @@
+/*
+ * $FreeBSD: src/sys/amd64/linux32/linux32_locore.s,v 1.2 2007/03/30 00:06:21 jkim Exp $
+ * $DragonFly$
+ */
+
+#include "linux32_assym.h"			/* system definitions */
+#include <machine/asmacros.h>			/* miscellaneous asm macros */
+
+#include <amd64/linux32/linux32_syscall.h>	/* system call numbers */
+
+.text
+.code32
+
+NON_GPROF_ENTRY(linux_sigcode)
+	call	*LINUX_SIGF_HANDLER(%esp)
+	leal	LINUX_SIGF_SC(%esp),%ebx	/* linux scp */
+	movl	LINUX_SC_ES(%ebx),%es
+	movl	LINUX_SC_DS(%ebx),%ds
+	movl	%esp, %ebx			/* pass sigframe */
+	push	%eax				/* fake ret addr */
+	movl	$LINUX_SYS_linux_sigreturn,%eax	/* linux_sigreturn() */
+	int	$0x80				/* enter kernel with args */
+0:	jmp	0b
+	ALIGN_TEXT
+/* XXXXX */
+linux_rt_sigcode:
+	call	*LINUX_RT_SIGF_HANDLER(%esp)
+	leal	LINUX_RT_SIGF_UC(%esp),%ebx	/* linux ucp */
+	movl	LINUX_SC_ES(%ebx),%es
+	movl	LINUX_SC_DS(%ebx),%ds
+	push	%eax				/* fake ret addr */
+	movl	$LINUX_SYS_linux_rt_sigreturn,%eax   /* linux_rt_sigreturn() */
+	int	$0x80				/* enter kernel with args */
+0:	jmp	0b
+	ALIGN_TEXT
+/* XXXXX */
+linux_esigcode:
+
+	.data
+	.globl	linux_szsigcode, linux_sznonrtsigcode
+linux_szsigcode:
+	.long	linux_esigcode-linux_sigcode
+linux_sznonrtsigcode:
+	.long	linux_rt_sigcode-linux_sigcode
Index: sys/emulation/linux/amd64/linux32_machdep.c
===================================================================
RCS file: sys/emulation/linux/amd64/linux32_machdep.c
diff -N sys/emulation/linux/amd64/linux32_machdep.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/emulation/linux/amd64/linux32_machdep.c	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,1362 @@
+/*-
+ * Copyright (c) 2004 Tim J. Robbins
+ * Copyright (c) 2002 Doug Rabson
+ * Copyright (c) 2000 Marcel Moolenaar
+ * 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
+ *    in this position and unchanged.
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * 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.
+ * 
+ * $FreeBSD: src/sys/amd64/linux32/linux32_machdep.c,v 1.45 2007/07/04 23:06:43 peter Exp $
+ * $DragonFly$
+ */
+
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/file.h>
+#include <sys/fcntl.h>
+#include <sys/clock.h>
+#include <sys/imgact.h>
+#include <sys/limits.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mman.h>
+#include <sys/mutex.h>
+#include <sys/priv.h>
+#include <sys/proc.h>
+#include <sys/resource.h>
+#include <sys/resourcevar.h>
+#include <sys/sched.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysproto.h>
+#include <sys/unistd.h>
+
+#include <machine/frame.h>
+#include <machine/pcb.h>
+#include <machine/psl.h>
+#include <machine/segments.h>
+#include <machine/specialreg.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_map.h>
+
+#include <amd64/linux32/linux.h>
+#include <amd64/linux32/linux32_proto.h>
+#include <compat/linux/linux_ipc.h>
+#include <compat/linux/linux_signal.h>
+#include <compat/linux/linux_util.h>
+#include <compat/linux/linux_emul.h>
+
+struct l_old_select_argv {
+	l_int		nfds;
+	l_uintptr_t	readfds;
+	l_uintptr_t	writefds;
+	l_uintptr_t	exceptfds;
+	l_uintptr_t	timeout;
+} __packed;
+
+int
+linux_to_bsd_sigaltstack(int lsa)
+{
+	int bsa = 0;
+
+	if (lsa & LINUX_SS_DISABLE)
+		bsa |= SS_DISABLE;
+	if (lsa & LINUX_SS_ONSTACK)
+		bsa |= SS_ONSTACK;
+	return (bsa);
+}
+
+int
+bsd_to_linux_sigaltstack(int bsa)
+{
+	int lsa = 0;
+
+	if (bsa & SS_DISABLE)
+		lsa |= LINUX_SS_DISABLE;
+	if (bsa & SS_ONSTACK)
+		lsa |= LINUX_SS_ONSTACK;
+	return (lsa);
+}
+
+/*
+ * Custom version of exec_copyin_args() so that we can translate
+ * the pointers.
+ */
+static int
+linux_exec_copyin_args(struct image_args *args, char *fname,
+    enum uio_seg segflg, char **argv, char **envv)
+{
+	char *argp, *envp;
+	u_int32_t *p32, arg;
+	size_t length;
+	int error;
+
+	bzero(args, sizeof(*args));
+	if (argv == NULL)
+		return (EFAULT);
+
+	/*
+	 * Allocate temporary demand zeroed space for argument and
+	 *	environment strings
+	 */
+	args->buf = (char *)kmem_alloc_wait(exec_map,
+	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
+	if (args->buf == NULL)
+		return (ENOMEM);
+	args->begin_argv = args->buf;
+	args->endp = args->begin_argv;
+	args->stringspace = ARG_MAX;
+
+	args->fname = args->buf + ARG_MAX;
+
+	/*
+	 * Copy the file name.
+	 */
+	error = (segflg == UIO_SYSSPACE) ?
+	    copystr(fname, args->fname, PATH_MAX, &length) :
+	    copyinstr(fname, args->fname, PATH_MAX, &length);
+	if (error != 0)
+		goto err_exit;
+
+	/*
+	 * extract arguments first
+	 */
+	p32 = (u_int32_t *)argv;
+	for (;;) {
+		error = copyin(p32++, &arg, sizeof(arg));
+		if (error)
+			goto err_exit;
+		if (arg == 0)
+			break;
+		argp = PTRIN(arg);
+		error = copyinstr(argp, args->endp, args->stringspace, &length);
+		if (error) {
+			if (error == ENAMETOOLONG)
+				error = E2BIG;
+
+			goto err_exit;
+		}
+		args->stringspace -= length;
+		args->endp += length;
+		args->argc++;
+	}
+
+	args->begin_envv = args->endp;
+
+	/*
+	 * extract environment strings
+	 */
+	if (envv) {
+		p32 = (u_int32_t *)envv;
+		for (;;) {
+			error = copyin(p32++, &arg, sizeof(arg));
+			if (error)
+				goto err_exit;
+			if (arg == 0)
+				break;
+			envp = PTRIN(arg);
+			error = copyinstr(envp, args->endp, args->stringspace,
+			    &length);
+			if (error) {
+				if (error == ENAMETOOLONG)
+					error = E2BIG;
+				goto err_exit;
+			}
+			args->stringspace -= length;
+			args->endp += length;
+			args->envc++;
+		}
+	}
+
+	return (0);
+
+err_exit:
+	kmem_free_wakeup(exec_map, (vm_offset_t)args->buf,
+	    PATH_MAX + ARG_MAX + MAXSHELLCMDLEN);
+	args->buf = NULL;
+	return (error);
+}
+
+int
+linux_execve(struct thread *td, struct linux_execve_args *args)
+{
+	struct image_args eargs;
+	char *path;
+	int error;
+
+	LCONVPATHEXIST(td, args->path, &path);
+
+#ifdef DEBUG
+	if (ldebug(execve))
+		printf(ARGS(execve, "%s"), path);
+#endif
+
+	error = linux_exec_copyin_args(&eargs, path, UIO_SYSSPACE, args->argp,
+	    args->envp);
+	free(path, M_TEMP);
+	if (error == 0)
+		error = kern_execve(td, &eargs, NULL);
+	if (error == 0)
+		/* Linux process can execute FreeBSD one, do not attempt
+		 * to create emuldata for such process using
+		 * linux_proc_init, this leads to a panic on KASSERT
+		 * because such process has p->p_emuldata == NULL.
+		 */
+	   	if (td->td_proc->p_sysent == &elf_linux_sysvec)
+			error = linux_proc_init(td, 0, 0);
+	return (error);
+}
+
+struct iovec32 {
+	u_int32_t iov_base;
+	int	iov_len;
+};
+
+CTASSERT(sizeof(struct iovec32) == 8);
+
+static int
+linux32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
+{
+	struct iovec32 iov32;
+	struct iovec *iov;
+	struct uio *uio;
+	u_int iovlen;
+	int error, i;
+
+	*uiop = NULL;
+	if (iovcnt > UIO_MAXIOV)
+		return (EINVAL);
+	iovlen = iovcnt * sizeof(struct iovec);
+	uio = malloc(iovlen + sizeof(*uio), M_IOV, M_WAITOK);
+	iov = (struct iovec *)(uio + 1);
+	for (i = 0; i < iovcnt; i++) {
+		error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
+		if (error) {
+			free(uio, M_IOV);
+			return (error);
+		}
+		iov[i].iov_base = PTRIN(iov32.iov_base);
+		iov[i].iov_len = iov32.iov_len;
+	}
+	uio->uio_iov = iov;
+	uio->uio_iovcnt = iovcnt;
+	uio->uio_segflg = UIO_USERSPACE;
+	uio->uio_offset = -1;
+	uio->uio_resid = 0;
+	for (i = 0; i < iovcnt; i++) {
+		if (iov->iov_len > INT_MAX - uio->uio_resid) {
+			free(uio, M_IOV);
+			return (EINVAL);
+		}
+		uio->uio_resid += iov->iov_len;
+		iov++;
+	}
+	*uiop = uio;
+	return (0);
+}
+
+int
+linux_readv(struct thread *td, struct linux_readv_args *uap)
+{
+	struct uio *auio;
+	int error;
+
+	error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio);
+	if (error)
+		return (error);
+	error = kern_readv(td, uap->fd, auio);
+	free(auio, M_IOV);
+	return (error);
+}
+
+int
+linux_writev(struct thread *td, struct linux_writev_args *uap)
+{
+	struct uio *auio;
+	int error;
+
+	error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio);
+	if (error)
+		return (error);
+	error = kern_writev(td, uap->fd, auio);
+	free(auio, M_IOV);
+	return (error);
+}
+
+struct l_ipc_kludge {
+	l_uintptr_t msgp;
+	l_long msgtyp;
+} __packed;
+
+int
+linux_ipc(struct thread *td, struct linux_ipc_args *args)
+{
+
+	switch (args->what & 0xFFFF) {
+	case LINUX_SEMOP: {
+		struct linux_semop_args a;
+
+		a.semid = args->arg1;
+		a.tsops = args->ptr;
+		a.nsops = args->arg2;
+		return (linux_semop(td, &a));
+	}
+	case LINUX_SEMGET: {
+		struct linux_semget_args a;
+
+		a.key = args->arg1;
+		a.nsems = args->arg2;
+		a.semflg = args->arg3;
+		return (linux_semget(td, &a));
+	}
+	case LINUX_SEMCTL: {
+		struct linux_semctl_args a;
+		int error;
+
+		a.semid = args->arg1;
+		a.semnum = args->arg2;
+		a.cmd = args->arg3;
+		error = copyin(args->ptr, &a.arg, sizeof(a.arg));
+		if (error)
+			return (error);
+		return (linux_semctl(td, &a));
+	}
+	case LINUX_MSGSND: {
+		struct linux_msgsnd_args a;
+
+		a.msqid = args->arg1;
+		a.msgp = args->ptr;
+		a.msgsz = args->arg2;
+		a.msgflg = args->arg3;
+		return (linux_msgsnd(td, &a));
+	}
+	case LINUX_MSGRCV: {
+		struct linux_msgrcv_args a;
+
+		a.msqid = args->arg1;
+		a.msgsz = args->arg2;
+		a.msgflg = args->arg3;
+		if ((args->what >> 16) == 0) {
+			struct l_ipc_kludge tmp;
+			int error;
+
+			if (args->ptr == 0)
+				return (EINVAL);
+			error = copyin(args->ptr, &tmp, sizeof(tmp));
+			if (error)
+				return (error);
+			a.msgp = PTRIN(tmp.msgp);
+			a.msgtyp = tmp.msgtyp;
+		} else {
+			a.msgp = args->ptr;
+			a.msgtyp = args->arg5;
+		}
+		return (linux_msgrcv(td, &a));
+	}
+	case LINUX_MSGGET: {
+		struct linux_msgget_args a;
+
+		a.key = args->arg1;
+		a.msgflg = args->arg2;
+		return (linux_msgget(td, &a));
+	}
+	case LINUX_MSGCTL: {
+		struct linux_msgctl_args a;
+
+		a.msqid = args->arg1;
+		a.cmd = args->arg2;
+		a.buf = args->ptr;
+		return (linux_msgctl(td, &a));
+	}
+	case LINUX_SHMAT: {
+		struct linux_shmat_args a;
+
+		a.shmid = args->arg1;
+		a.shmaddr = args->ptr;
+		a.shmflg = args->arg2;
+		a.raddr = PTRIN((l_uint)args->arg3);
+		return (linux_shmat(td, &a));
+	}
+	case LINUX_SHMDT: {
+		struct linux_shmdt_args a;
+
+		a.shmaddr = args->ptr;
+		return (linux_shmdt(td, &a));
+	}
+	case LINUX_SHMGET: {
+		struct linux_shmget_args a;
+
+		a.key = args->arg1;
+		a.size = args->arg2;
+		a.shmflg = args->arg3;
+		return (linux_shmget(td, &a));
+	}
+	case LINUX_SHMCTL: {
+		struct linux_shmctl_args a;
+
+		a.shmid = args->arg1;
+		a.cmd = args->arg2;
+		a.buf = args->ptr;
+		return (linux_shmctl(td, &a));
+	}
+	default:
+		break;
+	}
+
+	return (EINVAL);
+}
+
+int
+linux_old_select(struct thread *td, struct linux_old_select_args *args)
+{
+	struct l_old_select_argv linux_args;
+	struct linux_select_args newsel;
+	int error;
+
+#ifdef DEBUG
+	if (ldebug(old_select))
+		printf(ARGS(old_select, "%p"), args->ptr);
+#endif
+
+	error = copyin(args->ptr, &linux_args, sizeof(linux_args));
+	if (error)
+		return (error);
+
+	newsel.nfds = linux_args.nfds;
+	newsel.readfds = PTRIN(linux_args.readfds);
+	newsel.writefds = PTRIN(linux_args.writefds);
+	newsel.exceptfds = PTRIN(linux_args.exceptfds);
+	newsel.timeout = PTRIN(linux_args.timeout);
+	return (linux_select(td, &newsel));
+}
+
+int
+linux_fork(struct thread *td, struct linux_fork_args *args)
+{
+	int error;
+	struct proc *p2;
+	struct thread *td2;
+
+#ifdef DEBUG
+	if (ldebug(fork))
+		printf(ARGS(fork, ""));
+#endif
+
+	if ((error = fork1(td, RFFDG | RFPROC | RFSTOPPED, 0, &p2)) != 0)
+		return (error);
+
+	if (error == 0) {
+		td->td_retval[0] = p2->p_pid;
+		td->td_retval[1] = 0;
+	}
+
+	if (td->td_retval[1] == 1)
+		td->td_retval[0] = 0;
+	error = linux_proc_init(td, td->td_retval[0], 0);
+	if (error)
+		return (error);
+
+	td2 = FIRST_THREAD_IN_PROC(p2);
+
+	/*
+	 * Make this runnable after we are finished with it.
+	 */
+	thread_lock(td2);
+	TD_SET_CAN_RUN(td2);
+	sched_add(td2, SRQ_BORING);
+	thread_unlock(td2);
+
+	return (0);
+}
+
+int
+linux_vfork(struct thread *td, struct linux_vfork_args *args)
+{
+	int error;
+	struct proc *p2;
+	struct thread *td2;
+
+#ifdef DEBUG
+	if (ldebug(vfork))
+		printf(ARGS(vfork, ""));
+#endif
+
+	/* Exclude RFPPWAIT */
+	if ((error = fork1(td, RFFDG | RFPROC | RFMEM | RFSTOPPED, 0, &p2)) != 0)
+		return (error);
+	if (error == 0) {
+	   	td->td_retval[0] = p2->p_pid;
+		td->td_retval[1] = 0;
+	}
+	/* Are we the child? */
+	if (td->td_retval[1] == 1)
+		td->td_retval[0] = 0;
+	error = linux_proc_init(td, td->td_retval[0], 0);
+	if (error)
+		return (error);
+
+	PROC_LOCK(p2);
+	p2->p_flag |= P_PPWAIT;
+	PROC_UNLOCK(p2);
+
+	td2 = FIRST_THREAD_IN_PROC(p2);
+
+	/*
+	 * Make this runnable after we are finished with it.
+	 */
+	thread_lock(td2);
+	TD_SET_CAN_RUN(td2);
+	sched_add(td2, SRQ_BORING);
+	thread_unlock(td2);
+
+	/* wait for the children to exit, ie. emulate vfork */
+	PROC_LOCK(p2);
+	while (p2->p_flag & P_PPWAIT)
+	   	msleep(td->td_proc, &p2->p_mtx, PWAIT, "ppwait", 0);
+	PROC_UNLOCK(p2);
+
+	return (0);
+}
+
+int
+linux_clone(struct thread *td, struct linux_clone_args *args)
+{
+	int error, ff = RFPROC | RFSTOPPED;
+	struct proc *p2;
+	struct thread *td2;
+	int exit_signal;
+	struct linux_emuldata *em;
+
+#ifdef DEBUG
+	if (ldebug(clone)) {
+		printf(ARGS(clone, "flags %x, stack %p, parent tid: %p, "
+		    "child tid: %p"), (unsigned)args->flags,
+		    args->stack, args->parent_tidptr, args->child_tidptr);
+	}
+#endif
+
+	exit_signal = args->flags & 0x000000ff;
+	if (LINUX_SIG_VALID(exit_signal)) {
+		if (exit_signal <= LINUX_SIGTBLSZ)
+			exit_signal =
+			    linux_to_bsd_signal[_SIG_IDX(exit_signal)];
+	} else if (exit_signal != 0)
+		return (EINVAL);
+
+	if (args->flags & LINUX_CLONE_VM)
+		ff |= RFMEM;
+	if (args->flags & LINUX_CLONE_SIGHAND)
+		ff |= RFSIGSHARE;
+	/*
+	 * XXX: In Linux, sharing of fs info (chroot/cwd/umask)
+	 * and open files is independant.  In FreeBSD, its in one
+	 * structure but in reality it does not cause any problems
+	 * because both of these flags are usually set together.
+	 */
+	if (!(args->flags & (LINUX_CLONE_FILES | LINUX_CLONE_FS)))
+		ff |= RFFDG;
+
+	/*
+	 * Attempt to detect when linux_clone(2) is used for creating
+	 * kernel threads. Unfortunately despite the existence of the
+	 * CLONE_THREAD flag, version of linuxthreads package used in
+	 * most popular distros as of beginning of 2005 doesn't make
+	 * any use of it. Therefore, this detection relies on
+	 * empirical observation that linuxthreads sets certain
+	 * combination of flags, so that we can make more or less
+	 * precise detection and notify the FreeBSD kernel that several
+	 * processes are in fact part of the same threading group, so
+	 * that special treatment is necessary for signal delivery
+	 * between those processes and fd locking.
+	 */
+	if ((args->flags & 0xffffff00) == LINUX_THREADING_FLAGS)
+		ff |= RFTHREAD;
+
+	if (args->flags & LINUX_CLONE_PARENT_SETTID)
+		if (args->parent_tidptr == NULL)
+			return (EINVAL);
+
+	error = fork1(td, ff, 0, &p2);
+	if (error)
+		return (error);
+
+	if (args->flags & (LINUX_CLONE_PARENT | LINUX_CLONE_THREAD)) {
+	   	sx_xlock(&proctree_lock);
+		PROC_LOCK(p2);
+		proc_reparent(p2, td->td_proc->p_pptr);
+		PROC_UNLOCK(p2);
+		sx_xunlock(&proctree_lock);
+	}
+
+	/* create the emuldata */
+	error = linux_proc_init(td, p2->p_pid, args->flags);
+	/* reference it - no need to check this */
+	em = em_find(p2, EMUL_DOLOCK);
+	KASSERT(em != NULL, ("clone: emuldata not found.\n"));
+	/* and adjust it */
+
+	if (args->flags & LINUX_CLONE_THREAD) {
+#ifdef notyet
+	   	PROC_LOCK(p2);
+	   	p2->p_pgrp = td->td_proc->p_pgrp;
+	   	PROC_UNLOCK(p2);
+#endif
+		exit_signal = 0;
+	}
+
+	if (args->flags & LINUX_CLONE_CHILD_SETTID)
+		em->child_set_tid = args->child_tidptr;
+	else
+	   	em->child_set_tid = NULL;
+
+	if (args->flags & LINUX_CLONE_CHILD_CLEARTID)
+		em->child_clear_tid = args->child_tidptr;
+	else
+	   	em->child_clear_tid = NULL;
+
+	EMUL_UNLOCK(&emul_lock);
+
+	if (args->flags & LINUX_CLONE_PARENT_SETTID) {
+		error = copyout(&p2->p_pid, args->parent_tidptr,
+		    sizeof(p2->p_pid));
+		if (error)
+			printf(LMSG("copyout failed!"));
+	}
+
+	PROC_LOCK(p2);
+	p2->p_sigparent = exit_signal;
+	PROC_UNLOCK(p2);
+	td2 = FIRST_THREAD_IN_PROC(p2);
+	/*
+	 * In a case of stack = NULL, we are supposed to COW calling process
+	 * stack. This is what normal fork() does, so we just keep tf_rsp arg
+	 * intact.
+	 */
+	if (args->stack)
+		td2->td_frame->tf_rsp = PTROUT(args->stack);
+
+	if (args->flags & LINUX_CLONE_SETTLS) {
+		struct user_segment_descriptor sd;
+		struct l_user_desc info;
+		int a[2];
+
+		error = copyin((void *)td->td_frame->tf_rsi, &info,
+		    sizeof(struct l_user_desc));
+		if (error) {
+			printf(LMSG("copyin failed!"));
+		} else {
+			/* We might copy out the entry_number as GUGS32_SEL. */
+			info.entry_number = GUGS32_SEL;
+			error = copyout(&info, (void *)td->td_frame->tf_rsi,
+			    sizeof(struct l_user_desc));
+			if (error)
+				printf(LMSG("copyout failed!"));
+
+			a[0] = LINUX_LDT_entry_a(&info);
+			a[1] = LINUX_LDT_entry_b(&info);
+
+			memcpy(&sd, &a, sizeof(a));
+#ifdef DEBUG
+			if (ldebug(clone))
+				printf("Segment created in clone with "
+				    "CLONE_SETTLS: lobase: %x, hibase: %x, "
+				    "lolimit: %x, hilimit: %x, type: %i, "
+				    "dpl: %i, p: %i, xx: %i, long: %i, "
+				    "def32: %i, gran: %i\n", sd.sd_lobase,
+				    sd.sd_hibase, sd.sd_lolimit, sd.sd_hilimit,
+				    sd.sd_type, sd.sd_dpl, sd.sd_p, sd.sd_xx,
+				    sd.sd_long, sd.sd_def32, sd.sd_gran);
+#endif
+			td2->td_pcb->pcb_gsbase = (register_t)info.base_addr;
+			td2->td_pcb->pcb_gs32sd = sd;
+			td2->td_pcb->pcb_gs32p = &gdt[GUGS32_SEL];
+			td2->td_pcb->pcb_gs = GSEL(GUGS32_SEL, SEL_UPL);
+			td2->td_pcb->pcb_flags |= PCB_32BIT;
+		}
+	}
+
+#ifdef DEBUG
+	if (ldebug(clone))
+		printf(LMSG("clone: successful rfork to %d, "
+		    "stack %p sig = %d"), (int)p2->p_pid, args->stack,
+		    exit_signal);
+#endif
+	if (args->flags & LINUX_CLONE_VFORK) {
+	   	PROC_LOCK(p2);
+	   	p2->p_flag |= P_PPWAIT;
+	   	PROC_UNLOCK(p2);
+	}
+
+	/*
+	 * Make this runnable after we are finished with it.
+	 */
+	thread_lock(td2);
+	TD_SET_CAN_RUN(td2);
+	sched_add(td2, SRQ_BORING);
+	thread_unlock(td2);
+
+	td->td_retval[0] = p2->p_pid;
+	td->td_retval[1] = 0;
+
+	if (args->flags & LINUX_CLONE_VFORK) {
+		/* wait for the children to exit, ie. emulate vfork */
+		PROC_LOCK(p2);
+		while (p2->p_flag & P_PPWAIT)
+			msleep(td->td_proc, &p2->p_mtx, PWAIT, "ppwait", 0);
+		PROC_UNLOCK(p2);
+	}
+
+	return (0);
+}
+
+#define STACK_SIZE  (2 * 1024 * 1024)
+#define GUARD_SIZE  (4 * PAGE_SIZE)
+
+static int linux_mmap_common(struct thread *, struct l_mmap_argv *);
+
+int
+linux_mmap2(struct thread *td, struct linux_mmap2_args *args)
+{
+	struct l_mmap_argv linux_args;
+
+#ifdef DEBUG
+	if (ldebug(mmap2))
+		printf(ARGS(mmap2, "0x%08x, %d, %d, 0x%08x, %d, %d"),
+		    args->addr, args->len, args->prot,
+		    args->flags, args->fd, args->pgoff);
+#endif
+
+	linux_args.addr = PTROUT(args->addr);
+	linux_args.len = args->len;
+	linux_args.prot = args->prot;
+	linux_args.flags = args->flags;
+	linux_args.fd = args->fd;
+	linux_args.pgoff = args->pgoff;
+
+	return (linux_mmap_common(td, &linux_args));
+}
+
+int
+linux_mmap(struct thread *td, struct linux_mmap_args *args)
+{
+	int error;
+	struct l_mmap_argv linux_args;
+
+	error = copyin(args->ptr, &linux_args, sizeof(linux_args));
+	if (error)
+		return (error);
+
+#ifdef DEBUG
+	if (ldebug(mmap))
+		printf(ARGS(mmap, "0x%08x, %d, %d, 0x%08x, %d, %d"),
+		    linux_args.addr, linux_args.len, linux_args.prot,
+		    linux_args.flags, linux_args.fd, linux_args.pgoff);
+#endif
+	if ((linux_args.pgoff % PAGE_SIZE) != 0)
+		return (EINVAL);
+	linux_args.pgoff /= PAGE_SIZE;
+
+	return (linux_mmap_common(td, &linux_args));
+}
+
+static int
+linux_mmap_common(struct thread *td, struct l_mmap_argv *linux_args)
+{
+	struct proc *p = td->td_proc;
+	struct mmap_args /* {
+		caddr_t addr;
+		size_t len;
+		int prot;
+		int flags;
+		int fd;
+		long pad;
+		off_t pos;
+	} */ bsd_args;
+	int error;
+	struct file *fp;
+
+	error = 0;
+	bsd_args.flags = 0;
+	fp = NULL;
+
+	/*
+	 * Linux mmap(2):
+	 * You must specify exactly one of MAP_SHARED and MAP_PRIVATE
+	 */
+	if (! ((linux_args->flags & LINUX_MAP_SHARED) ^
+	    (linux_args->flags & LINUX_MAP_PRIVATE)))
+		return (EINVAL);
+
+	if (linux_args->flags & LINUX_MAP_SHARED)
+		bsd_args.flags |= MAP_SHARED;
+	if (linux_args->flags & LINUX_MAP_PRIVATE)
+		bsd_args.flags |= MAP_PRIVATE;
+	if (linux_args->flags & LINUX_MAP_FIXED)
+		bsd_args.flags |= MAP_FIXED;
+	if (linux_args->flags & LINUX_MAP_ANON)
+		bsd_args.flags |= MAP_ANON;
+	else
+		bsd_args.flags |= MAP_NOSYNC;
+	if (linux_args->flags & LINUX_MAP_GROWSDOWN)
+		bsd_args.flags |= MAP_STACK;
+
+	/*
+	 * PROT_READ, PROT_WRITE, or PROT_EXEC implies PROT_READ and PROT_EXEC
+	 * on Linux/i386. We do this to ensure maximum compatibility.
+	 * Linux/ia64 does the same in i386 emulation mode.
+	 */
+	bsd_args.prot = linux_args->prot;
+	if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC))
+		bsd_args.prot |= PROT_READ | PROT_EXEC;
+
+	/* Linux does not check file descriptor when MAP_ANONYMOUS is set. */
+	bsd_args.fd = (bsd_args.flags & MAP_ANON) ? -1 : linux_args->fd;
+	if (bsd_args.fd != -1) {
+		/*
+		 * Linux follows Solaris mmap(2) description:
+		 * The file descriptor fildes is opened with
+		 * read permission, regardless of the
+		 * protection options specified.
+		 */
+
+		if ((error = fget(td, bsd_args.fd, &fp)) != 0)
+			return (error);
+		if (fp->f_type != DTYPE_VNODE) {
+			fdrop(fp, td);
+			return (EINVAL);
+		}
+
+		/* Linux mmap() just fails for O_WRONLY files */
+		if (!(fp->f_flag & FREAD)) {
+			fdrop(fp, td);
+			return (EACCES);
+		}
+
+		fdrop(fp, td);
+	}
+
+	if (linux_args->flags & LINUX_MAP_GROWSDOWN) {
+		/*
+		 * The Linux MAP_GROWSDOWN option does not limit auto
+		 * growth of the region.  Linux mmap with this option
+		 * takes as addr the inital BOS, and as len, the initial
+		 * region size.  It can then grow down from addr without
+		 * limit.  However, Linux threads has an implicit internal
+		 * limit to stack size of STACK_SIZE.  Its just not
+		 * enforced explicitly in Linux.  But, here we impose
+		 * a limit of (STACK_SIZE - GUARD_SIZE) on the stack
+		 * region, since we can do this with our mmap.
+		 *
+		 * Our mmap with MAP_STACK takes addr as the maximum
+		 * downsize limit on BOS, and as len the max size of
+		 * the region.  It then maps the top SGROWSIZ bytes,
+		 * and auto grows the region down, up to the limit
+		 * in addr.
+		 *
+		 * If we don't use the MAP_STACK option, the effect
+		 * of this code is to allocate a stack region of a
+		 * fixed size of (STACK_SIZE - GUARD_SIZE).
+		 */
+
+		if ((caddr_t)PTRIN(linux_args->addr) + linux_args->len >
+		    p->p_vmspace->vm_maxsaddr) {
+			/*
+			 * Some Linux apps will attempt to mmap
+			 * thread stacks near the top of their
+			 * address space.  If their TOS is greater
+			 * than vm_maxsaddr, vm_map_growstack()
+			 * will confuse the thread stack with the
+			 * process stack and deliver a SEGV if they
+			 * attempt to grow the thread stack past their
+			 * current stacksize rlimit.  To avoid this,
+			 * adjust vm_maxsaddr upwards to reflect
+			 * the current stacksize rlimit rather
+			 * than the maximum possible stacksize.
+			 * It would be better to adjust the
+			 * mmap'ed region, but some apps do not check
+			 * mmap's return value.
+			 */
+			PROC_LOCK(p);
+			p->p_vmspace->vm_maxsaddr = (char *)LINUX32_USRSTACK -
+			    lim_cur(p, RLIMIT_STACK);
+			PROC_UNLOCK(p);
+		}
+
+		/* This gives us our maximum stack size */
+		if (linux_args->len > STACK_SIZE - GUARD_SIZE)
+			bsd_args.len = linux_args->len;
+		else
+			bsd_args.len  = STACK_SIZE - GUARD_SIZE;
+
+		/*
+		 * This gives us a new BOS.  If we're using VM_STACK, then
+		 * mmap will just map the top SGROWSIZ bytes, and let
+		 * the stack grow down to the limit at BOS.  If we're
+		 * not using VM_STACK we map the full stack, since we
+		 * don't have a way to autogrow it.
+		 */
+		bsd_args.addr = (caddr_t)PTRIN(linux_args->addr) -
+		    bsd_args.len;
+	} else {
+		bsd_args.addr = (caddr_t)PTRIN(linux_args->addr);
+		bsd_args.len  = linux_args->len;
+	}
+	bsd_args.pos = (off_t)linux_args->pgoff * PAGE_SIZE;
+
+#ifdef DEBUG
+	if (ldebug(mmap))
+		printf("-> %s(%p, %d, %d, 0x%08x, %d, 0x%x)\n",
+		    __func__,
+		    (void *)bsd_args.addr, (int)bsd_args.len, bsd_args.prot,
+		    bsd_args.flags, bsd_args.fd, (int)bsd_args.pos);
+#endif
+	error = mmap(td, &bsd_args);
+#ifdef DEBUG
+	if (ldebug(mmap))
+		printf("-> %s() return: 0x%x (0x%08x)\n",
+			__func__, error, (u_int)td->td_retval[0]);
+#endif
+	return (error);
+}
+
+int
+linux_mprotect(struct thread *td, struct linux_mprotect_args *uap)
+{
+	struct mprotect_args bsd_args;
+
+	bsd_args.addr = uap->addr;
+	bsd_args.len = uap->len;
+	bsd_args.prot = uap->prot;
+	if (bsd_args.prot & (PROT_READ | PROT_WRITE | PROT_EXEC))
+		bsd_args.prot |= PROT_READ | PROT_EXEC;
+	return (mprotect(td, &bsd_args));
+}
+
+int
+linux_iopl(struct thread *td, struct linux_iopl_args *args)
+{
+	int error;
+
+	if (args->level < 0 || args->level > 3)
+		return (EINVAL);
+	if ((error = priv_check(td, PRIV_IO)) != 0)
+		return (error);
+	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
+		return (error);
+	td->td_frame->tf_rflags = (td->td_frame->tf_rflags & ~PSL_IOPL) |
+	    (args->level * (PSL_IOPL / 3));
+
+	return (0);
+}
+
+int
+linux_pipe(struct thread *td, struct linux_pipe_args *args)
+{
+	int pip[2];
+	int error;
+	register_t reg_rdx;
+
+#ifdef DEBUG
+	if (ldebug(pipe))
+		printf(ARGS(pipe, "*"));
+#endif
+
+	reg_rdx = td->td_retval[1];
+	error = pipe(td, 0);
+	if (error) {
+		td->td_retval[1] = reg_rdx;
+		return (error);
+	}
+
+	pip[0] = td->td_retval[0];
+	pip[1] = td->td_retval[1];
+	error = copyout(pip, args->pipefds, 2 * sizeof(int));
+	if (error) {
+		td->td_retval[1] = reg_rdx;
+		return (error);
+	}
+
+	td->td_retval[1] = reg_rdx;
+	td->td_retval[0] = 0;
+	return (0);
+}
+
+int
+linux_sigaction(struct thread *td, struct linux_sigaction_args *args)
+{
+	l_osigaction_t osa;
+	l_sigaction_t act, oact;
+	int error;
+
+#ifdef DEBUG
+	if (ldebug(sigaction))
+		printf(ARGS(sigaction, "%d, %p, %p"),
+		    args->sig, (void *)args->nsa, (void *)args->osa);
+#endif
+
+	if (args->nsa != NULL) {
+		error = copyin(args->nsa, &osa, sizeof(l_osigaction_t));
+		if (error)
+			return (error);
+		act.lsa_handler = osa.lsa_handler;
+		act.lsa_flags = osa.lsa_flags;
+		act.lsa_restorer = osa.lsa_restorer;
+		LINUX_SIGEMPTYSET(act.lsa_mask);
+		act.lsa_mask.__bits[0] = osa.lsa_mask;
+	}
+
+	error = linux_do_sigaction(td, args->sig, args->nsa ? &act : NULL,
+	    args->osa ? &oact : NULL);
+
+	if (args->osa != NULL && !error) {
+		osa.lsa_handler = oact.lsa_handler;
+		osa.lsa_flags = oact.lsa_flags;
+		osa.lsa_restorer = oact.lsa_restorer;
+		osa.lsa_mask = oact.lsa_mask.__bits[0];
+		error = copyout(&osa, args->osa, sizeof(l_osigaction_t));
+	}
+
+	return (error);
+}
+
+/*
+ * Linux has two extra args, restart and oldmask.  We don't use these,
+ * but it seems that "restart" is actually a context pointer that
+ * enables the signal to happen with a different register set.
+ */
+int
+linux_sigsuspend(struct thread *td, struct linux_sigsuspend_args *args)
+{
+	sigset_t sigmask;
+	l_sigset_t mask;
+
+#ifdef DEBUG
+	if (ldebug(sigsuspend))
+		printf(ARGS(sigsuspend, "%08lx"), (unsigned long)args->mask);
+#endif
+
+	LINUX_SIGEMPTYSET(mask);
+	mask.__bits[0] = args->mask;
+	linux_to_bsd_sigset(&mask, &sigmask);
+	return (kern_sigsuspend(td, sigmask));
+}
+
+int
+linux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap)
+{
+	l_sigset_t lmask;
+	sigset_t sigmask;
+	int error;
+
+#ifdef DEBUG
+	if (ldebug(rt_sigsuspend))
+		printf(ARGS(rt_sigsuspend, "%p, %d"),
+		    (void *)uap->newset, uap->sigsetsize);
+#endif
+
+	if (uap->sigsetsize != sizeof(l_sigset_t))
+		return (EINVAL);
+
+	error = copyin(uap->newset, &lmask, sizeof(l_sigset_t));
+	if (error)
+		return (error);
+
+	linux_to_bsd_sigset(&lmask, &sigmask);
+	return (kern_sigsuspend(td, sigmask));
+}
+
+int
+linux_pause(struct thread *td, struct linux_pause_args *args)
+{
+	struct proc *p = td->td_proc;
+	sigset_t sigmask;
+
+#ifdef DEBUG
+	if (ldebug(pause))
+		printf(ARGS(pause, ""));
+#endif
+
+	PROC_LOCK(p);
+	sigmask = td->td_sigmask;
+	PROC_UNLOCK(p);
+	return (kern_sigsuspend(td, sigmask));
+}
+
+int
+linux_sigaltstack(struct thread *td, struct linux_sigaltstack_args *uap)
+{
+	stack_t ss, oss;
+	l_stack_t lss;
+	int error;
+
+#ifdef DEBUG
+	if (ldebug(sigaltstack))
+		printf(ARGS(sigaltstack, "%p, %p"), uap->uss, uap->uoss);
+#endif
+
+	if (uap->uss != NULL) {
+		error = copyin(uap->uss, &lss, sizeof(l_stack_t));
+		if (error)
+			return (error);
+
+		ss.ss_sp = PTRIN(lss.ss_sp);
+		ss.ss_size = lss.ss_size;
+		ss.ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags);
+	}
+	error = kern_sigaltstack(td, (uap->uss != NULL) ? &ss : NULL,
+	    (uap->uoss != NULL) ? &oss : NULL);
+	if (!error && uap->uoss != NULL) {
+		lss.ss_sp = PTROUT(oss.ss_sp);
+		lss.ss_size = oss.ss_size;
+		lss.ss_flags = bsd_to_linux_sigaltstack(oss.ss_flags);
+		error = copyout(&lss, uap->uoss, sizeof(l_stack_t));
+	}
+
+	return (error);
+}
+
+int
+linux_ftruncate64(struct thread *td, struct linux_ftruncate64_args *args)
+{
+	struct ftruncate_args sa;
+
+#ifdef DEBUG
+	if (ldebug(ftruncate64))
+		printf(ARGS(ftruncate64, "%u, %jd"), args->fd,
+		    (intmax_t)args->length);
+#endif
+
+	sa.fd = args->fd;
+	sa.length = args->length;
+	return ftruncate(td, &sa);
+}
+
+int
+linux_gettimeofday(struct thread *td, struct linux_gettimeofday_args *uap)
+{
+	struct timeval atv;
+	l_timeval atv32;
+	struct timezone rtz;
+	int error = 0;
+
+	if (uap->tp) {
+		microtime(&atv);
+		atv32.tv_sec = atv.tv_sec;
+		atv32.tv_usec = atv.tv_usec;
+		error = copyout(&atv32, uap->tp, sizeof(atv32));
+	}
+	if (error == 0 && uap->tzp != NULL) {
+		rtz.tz_minuteswest = tz_minuteswest;
+		rtz.tz_dsttime = tz_dsttime;
+		error = copyout(&rtz, uap->tzp, sizeof(rtz));
+	}
+	return (error);
+}
+
+int
+linux_settimeofday(struct thread *td, struct linux_settimeofday_args *uap)
+{
+	l_timeval atv32;
+	struct timeval atv, *tvp;
+	struct timezone atz, *tzp;
+	int error;
+
+	if (uap->tp) {
+		error = copyin(uap->tp, &atv32, sizeof(atv32));
+		if (error)
+			return (error);
+		atv.tv_sec = atv32.tv_sec;
+		atv.tv_usec = atv32.tv_usec;
+		tvp = &atv;
+	} else
+		tvp = NULL;
+	if (uap->tzp) {
+		error = copyin(uap->tzp, &atz, sizeof(atz));
+		if (error)
+			return (error);
+		tzp = &atz;
+	} else
+		tzp = NULL;
+	return (kern_settimeofday(td, tvp, tzp));
+}
+
+int
+linux_getrusage(struct thread *td, struct linux_getrusage_args *uap)
+{
+	struct l_rusage s32;
+	struct rusage s;
+	int error;
+
+	error = kern_getrusage(td, uap->who, &s);
+	if (error != 0)
+		return (error);
+	if (uap->rusage != NULL) {
+		s32.ru_utime.tv_sec = s.ru_utime.tv_sec;
+		s32.ru_utime.tv_usec = s.ru_utime.tv_usec;
+		s32.ru_stime.tv_sec = s.ru_stime.tv_sec;
+		s32.ru_stime.tv_usec = s.ru_stime.tv_usec;
+		s32.ru_maxrss = s.ru_maxrss;
+		s32.ru_ixrss = s.ru_ixrss;
+		s32.ru_idrss = s.ru_idrss;
+		s32.ru_isrss = s.ru_isrss;
+		s32.ru_minflt = s.ru_minflt;
+		s32.ru_majflt = s.ru_majflt;
+		s32.ru_nswap = s.ru_nswap;
+		s32.ru_inblock = s.ru_inblock;
+		s32.ru_oublock = s.ru_oublock;
+		s32.ru_msgsnd = s.ru_msgsnd;
+		s32.ru_msgrcv = s.ru_msgrcv;
+		s32.ru_nsignals = s.ru_nsignals;
+		s32.ru_nvcsw = s.ru_nvcsw;
+		s32.ru_nivcsw = s.ru_nivcsw;
+		error = copyout(&s32, uap->rusage, sizeof(s32));
+	}
+	return (error);
+}
+
+int
+linux_sched_rr_get_interval(struct thread *td,
+    struct linux_sched_rr_get_interval_args *uap)
+{
+	struct timespec ts;
+	struct l_timespec ts32;
+	int error;
+
+	error = kern_sched_rr_get_interval(td, uap->pid, &ts);
+	if (error != 0)
+		return (error);
+	ts32.tv_sec = ts.tv_sec;
+	ts32.tv_nsec = ts.tv_nsec;
+	return (copyout(&ts32, uap->interval, sizeof(ts32)));
+}
+
+int
+linux_set_thread_area(struct thread *td,
+    struct linux_set_thread_area_args *args)
+{
+	struct l_user_desc info;
+	struct user_segment_descriptor sd;
+	int a[2];
+	int error;
+
+	error = copyin(args->desc, &info, sizeof(struct l_user_desc));
+	if (error)
+		return (error);
+
+#ifdef DEBUG
+	if (ldebug(set_thread_area))
+		printf(ARGS(set_thread_area, "%i, %x, %x, %i, %i, %i, "
+		    "%i, %i, %i"), info.entry_number, info.base_addr,
+		    info.limit, info.seg_32bit, info.contents,
+		    info.read_exec_only, info.limit_in_pages,
+		    info.seg_not_present, info.useable);
+#endif
+
+	/*
+	 * Semantics of Linux version: every thread in the system has array
+	 * of three TLS descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown.
+	 * This syscall loads one of the selected TLS decriptors with a value
+	 * and also loads GDT descriptors 6, 7 and 8 with the content of
+	 * the per-thread descriptors.
+	 *
+	 * Semantics of FreeBSD version: I think we can ignore that Linux has
+	 * three per-thread descriptors and use just the first one.
+	 * The tls_array[] is used only in [gs]et_thread_area() syscalls and
+	 * for loading the GDT descriptors. We use just one GDT descriptor
+	 * for TLS, so we will load just one.
+	 *
+	 * XXX: This doesn't work when a user space process tries to use more
+	 * than one TLS segment. Comment in the Linux source says wine might
+	 * do this.
+	 */
+
+	/*
+	 * GLIBC reads current %gs and call set_thread_area() with it.
+	 * We should let GUDATA_SEL and GUGS32_SEL proceed as well because
+	 * we use these segments.
+	 */
+	switch (info.entry_number) {
+	case GUGS32_SEL:
+	case GUDATA_SEL:
+	case 6:
+	case -1:
+		info.entry_number = GUGS32_SEL;
+		break;
+	default:
+		return (EINVAL);
+	}
+
+	/*
+	 * We have to copy out the GDT entry we use.
+	 *
+	 * XXX: What if a user space program does not check the return value
+	 * and tries to use 6, 7 or 8?
+	 */
+	error = copyout(&info, args->desc, sizeof(struct l_user_desc));
+	if (error)
+		return (error);
+
+	if (LINUX_LDT_empty(&info)) {
+		a[0] = 0;
+		a[1] = 0;
+	} else {
+		a[0] = LINUX_LDT_entry_a(&info);
+		a[1] = LINUX_LDT_entry_b(&info);
+	}
+
+	memcpy(&sd, &a, sizeof(a));
+#ifdef DEBUG
+	if (ldebug(set_thread_area))
+		printf("Segment created in set_thread_area: "
+		    "lobase: %x, hibase: %x, lolimit: %x, hilimit: %x, "
+		    "type: %i, dpl: %i, p: %i, xx: %i, long: %i, "
+		    "def32: %i, gran: %i\n",
+		    sd.sd_lobase,
+		    sd.sd_hibase,
+		    sd.sd_lolimit,
+		    sd.sd_hilimit,
+		    sd.sd_type,
+		    sd.sd_dpl,
+		    sd.sd_p,
+		    sd.sd_xx,
+		    sd.sd_long,
+		    sd.sd_def32,
+		    sd.sd_gran);
+#endif
+
+	critical_enter();
+	td->td_pcb->pcb_gsbase = (register_t)info.base_addr;
+	td->td_pcb->pcb_gs32sd = gdt[GUGS32_SEL] = sd;
+	td->td_pcb->pcb_gs32p = &gdt[GUGS32_SEL];
+	td->td_pcb->pcb_flags |= PCB_32BIT;
+	wrmsr(MSR_KGSBASE, td->td_pcb->pcb_gsbase);
+	critical_exit();
+
+	return (0);
+}
Index: sys/emulation/linux/amd64/linux32_support.s
===================================================================
RCS file: sys/emulation/linux/amd64/linux32_support.s
diff -N sys/emulation/linux/amd64/linux32_support.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/emulation/linux/amd64/linux32_support.s	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,125 @@
+/*-
+ * Copyright (c) 2007 Konstantin Belousov
+ * 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.
+ * 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/amd64/linux32/linux32_support.s,v 1.1 2007/05/23 08:33:05 kib Exp $
+ * $DragonFly$
+ */
+
+#include "linux32_assym.h"		/* system definitions */
+#include <machine/asmacros.h>		/* miscellaneous asm macros */
+
+#include "assym.s"
+
+futex_fault:
+	movq	$0,PCB_ONFAULT(%r8)
+	movl	$-EFAULT,%eax
+	ret
+
+ENTRY(futex_xchgl)
+	movq	PCPU(CURPCB),%r8
+	movq	$futex_fault,PCB_ONFAULT(%r8)
+	movq	$VM_MAXUSER_ADDRESS-4,%rax
+	cmpq	%rax,%rsi
+	ja	futex_fault
+	xchgl	%edi,(%rsi)
+	movl	%edi,(%rdx)
+	xorl	%eax,%eax
+	movq	%rax,PCB_ONFAULT(%r8)
+	ret
+
+ENTRY(futex_addl)
+	movq	PCPU(CURPCB),%r8
+	movq	$futex_fault,PCB_ONFAULT(%r8)
+	movq	$VM_MAXUSER_ADDRESS-4,%rax
+	cmpq	%rax,%rsi
+	ja	futex_fault
+#ifdef SMP
+	lock
+#endif
+	xaddl	%edi,(%rsi)
+	movl	%edi,(%rdx)
+	xorl	%eax,%eax
+	movq	%rax,PCB_ONFAULT(%r8)
+	ret
+
+ENTRY(futex_orl)
+	movq	PCPU(CURPCB),%r8
+	movq	$futex_fault,PCB_ONFAULT(%r8)
+	movq	$VM_MAXUSER_ADDRESS-4,%rax
+	cmpq	%rax,%rsi
+	ja	futex_fault
+	movl	(%rsi),%eax
+1:	movl	%eax,%ecx
+	orl	%edi,%ecx
+#ifdef SMP
+	lock
+#endif
+	cmpxchgl %ecx,(%rsi)
+	jnz	1b
+	movl	%eax,(%rdx)
+	xorl	%eax,%eax
+	movq	%rax,PCB_ONFAULT(%r8)
+	ret
+
+ENTRY(futex_andl)
+	movq	PCPU(CURPCB),%r8
+	movq	$futex_fault,PCB_ONFAULT(%r8)
+	movq	$VM_MAXUSER_ADDRESS-4,%rax
+	cmpq	%rax,%rsi
+	ja	futex_fault
+	movl	(%rsi),%eax
+1:	movl	%eax,%ecx
+	andl	%edi,%ecx
+#ifdef SMP
+	lock
+#endif
+	cmpxchgl %ecx,(%rsi)
+	jnz	1b
+	movl	%eax,(%rdx)
+	xorl	%eax,%eax
+	movq	%rax,PCB_ONFAULT(%r8)
+	ret
+
+ENTRY(futex_xorl)
+	movq	PCPU(CURPCB),%r8
+	movq	$futex_fault,PCB_ONFAULT(%r8)
+	movq	$VM_MAXUSER_ADDRESS-4,%rax
+	cmpq	%rax,%rsi
+	ja	futex_fault
+	movl	(%rsi),%eax
+1:	movl	%eax,%ecx
+	xorl	%edi,%ecx
+#ifdef SMP
+	lock
+#endif
+	cmpxchgl %ecx,(%rsi)
+	jnz	1b
+	movl	%eax,(%rdx)
+	xorl	%eax,%eax
+	movq	%rax,PCB_ONFAULT(%r8)
+	ret
Index: sys/emulation/linux/amd64/linux32_sysvec.c
===================================================================
RCS file: sys/emulation/linux/amd64/linux32_sysvec.c
diff -N sys/emulation/linux/amd64/linux32_sysvec.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/emulation/linux/amd64/linux32_sysvec.c	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,1133 @@
+/*-
+ * Copyright (c) 2004 Tim J. Robbins
+ * Copyright (c) 2003 Peter Wemm
+ * Copyright (c) 2002 Doug Rabson
+ * Copyright (c) 1998-1999 Andrew Gallatin
+ * Copyright (c) 1994-1996 Søren Schmidt
+ * 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
+ *    in this position and unchanged.
+ * 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. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * 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.
+ *
+ * $FreeBSD: src/sys/amd64/linux32/linux32_sysvec.c,v 1.29 2007/05/14 22:40:04 jhb Exp $
+ * $DragonFly$
+ */
+
+#include "opt_compat.h"
+
+#ifndef COMPAT_IA32
+#error "Unable to compile Linux-emulator due to missing COMPAT_IA32 option!"
+#endif
+
+#define	__ELF_WORD_SIZE	32
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/exec.h>
+#include <sys/imgact.h>
+#include <sys/imgact_elf.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/resourcevar.h>
+#include <sys/signalvar.h>
+#include <sys/sysctl.h>
+#include <sys/syscallsubr.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/vnode.h>
+#include <sys/eventhandler.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+#include <vm/vm_param.h>
+
+#include <machine/cpu.h>
+#include <machine/md_var.h>
+#include <machine/pcb.h>
+#include <machine/specialreg.h>
+
+#include <amd64/linux32/linux.h>
+#include <amd64/linux32/linux32_proto.h>
+#include <compat/linux/linux_emul.h>
+#include <compat/linux/linux_mib.h>
+#include <compat/linux/linux_signal.h>
+#include <compat/linux/linux_util.h>
+
+MODULE_VERSION(linux, 1);
+
+MALLOC_DEFINE(M_LINUX, "linux", "Linux mode structures");
+
+#define	AUXARGS_ENTRY_32(pos, id, val)	\
+	do {				\
+		suword32(pos++, id);	\
+		suword32(pos++, val);	\
+	} while (0)
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define SHELLMAGIC      0x2123 /* #! */
+#else
+#define SHELLMAGIC      0x2321
+#endif
+
+/*
+ * Allow the sendsig functions to use the ldebug() facility
+ * even though they are not syscalls themselves. Map them
+ * to syscall 0. This is slightly less bogus than using
+ * ldebug(sigreturn).
+ */
+#define	LINUX_SYS_linux_rt_sendsig	0
+#define	LINUX_SYS_linux_sendsig		0
+
+extern char linux_sigcode[];
+extern int linux_szsigcode;
+
+extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL];
+
+SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler);
+SET_DECLARE(linux_device_handler_set, struct linux_device_handler);
+
+static int	elf_linux_fixup(register_t **stack_base,
+		    struct image_params *iparams);
+static register_t *linux_copyout_strings(struct image_params *imgp);
+static void	linux_prepsyscall(struct trapframe *tf, int *args, u_int *code,
+		    caddr_t *params);
+static void     linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
+static void	exec_linux_setregs(struct thread *td, u_long entry,
+				   u_long stack, u_long ps_strings);
+static void	linux32_fixlimit(struct rlimit *rl, int which);
+
+extern LIST_HEAD(futex_list, futex) futex_list;
+extern struct sx futex_sx;
+
+static eventhandler_tag linux_exit_tag;
+static eventhandler_tag linux_schedtail_tag;
+static eventhandler_tag linux_exec_tag;
+
+/*
+ * Linux syscalls return negative errno's, we do positive and map them
+ * Reference:
+ *   FreeBSD: src/sys/sys/errno.h
+ *   Linux:   linux-2.6.17.8/include/asm-generic/errno-base.h
+ *            linux-2.6.17.8/include/asm-generic/errno.h
+ */
+static int bsd_to_linux_errno[ELAST + 1] = {
+	-0,  -1,  -2,  -3,  -4,  -5,  -6,  -7,  -8,  -9,
+	-10, -35, -12, -13, -14, -15, -16, -17, -18, -19,
+	-20, -21, -22, -23, -24, -25, -26, -27, -28, -29,
+	-30, -31, -32, -33, -34, -11,-115,-114, -88, -89,
+	-90, -91, -92, -93, -94, -95, -96, -97, -98, -99,
+	-100,-101,-102,-103,-104,-105,-106,-107,-108,-109,
+	-110,-111, -40, -36,-112,-113, -39, -11, -87,-122,
+	-116, -66,  -6,  -6,  -6,  -6,  -6, -37, -38,  -9,
+	  -6,  -6, -43, -42, -75,-125, -84, -95, -16, -74,
+	 -72, -67, -71
+};
+
+int bsd_to_linux_signal[LINUX_SIGTBLSZ] = {
+	LINUX_SIGHUP, LINUX_SIGINT, LINUX_SIGQUIT, LINUX_SIGILL,
+	LINUX_SIGTRAP, LINUX_SIGABRT, 0, LINUX_SIGFPE,
+	LINUX_SIGKILL, LINUX_SIGBUS, LINUX_SIGSEGV, LINUX_SIGSYS,
+	LINUX_SIGPIPE, LINUX_SIGALRM, LINUX_SIGTERM, LINUX_SIGURG,
+	LINUX_SIGSTOP, LINUX_SIGTSTP, LINUX_SIGCONT, LINUX_SIGCHLD,
+	LINUX_SIGTTIN, LINUX_SIGTTOU, LINUX_SIGIO, LINUX_SIGXCPU,
+	LINUX_SIGXFSZ, LINUX_SIGVTALRM, LINUX_SIGPROF, LINUX_SIGWINCH,
+	0, LINUX_SIGUSR1, LINUX_SIGUSR2
+};
+
+int linux_to_bsd_signal[LINUX_SIGTBLSZ] = {
+	SIGHUP, SIGINT, SIGQUIT, SIGILL,
+	SIGTRAP, SIGABRT, SIGBUS, SIGFPE,
+	SIGKILL, SIGUSR1, SIGSEGV, SIGUSR2,
+	SIGPIPE, SIGALRM, SIGTERM, SIGBUS,
+	SIGCHLD, SIGCONT, SIGSTOP, SIGTSTP,
+	SIGTTIN, SIGTTOU, SIGURG, SIGXCPU,
+	SIGXFSZ, SIGVTALRM, SIGPROF, SIGWINCH,
+	SIGIO, SIGURG, SIGSYS
+};
+
+#define LINUX_T_UNKNOWN  255
+static int _bsd_to_linux_trapcode[] = {
+	LINUX_T_UNKNOWN,	/* 0 */
+	6,			/* 1  T_PRIVINFLT */
+	LINUX_T_UNKNOWN,	/* 2 */
+	3,			/* 3  T_BPTFLT */
+	LINUX_T_UNKNOWN,	/* 4 */
+	LINUX_T_UNKNOWN,	/* 5 */
+	16,			/* 6  T_ARITHTRAP */
+	254,			/* 7  T_ASTFLT */
+	LINUX_T_UNKNOWN,	/* 8 */
+	13,			/* 9  T_PROTFLT */
+	1,			/* 10 T_TRCTRAP */
+	LINUX_T_UNKNOWN,	/* 11 */
+	14,			/* 12 T_PAGEFLT */
+	LINUX_T_UNKNOWN,	/* 13 */
+	17,			/* 14 T_ALIGNFLT */
+	LINUX_T_UNKNOWN,	/* 15 */
+	LINUX_T_UNKNOWN,	/* 16 */
+	LINUX_T_UNKNOWN,	/* 17 */
+	0,			/* 18 T_DIVIDE */
+	2,			/* 19 T_NMI */
+	4,			/* 20 T_OFLOW */
+	5,			/* 21 T_BOUND */
+	7,			/* 22 T_DNA */
+	8,			/* 23 T_DOUBLEFLT */
+	9,			/* 24 T_FPOPFLT */
+	10,			/* 25 T_TSSFLT */
+	11,			/* 26 T_SEGNPFLT */
+	12,			/* 27 T_STKFLT */
+	18,			/* 28 T_MCHK */
+	19,			/* 29 T_XMMFLT */
+	15			/* 30 T_RESERVED */
+};
+#define bsd_to_linux_trapcode(code) \
+    ((code)<sizeof(_bsd_to_linux_trapcode)/sizeof(*_bsd_to_linux_trapcode)? \
+     _bsd_to_linux_trapcode[(code)]: \
+     LINUX_T_UNKNOWN)
+
+struct linux32_ps_strings {
+	u_int32_t ps_argvstr;	/* first of 0 or more argument strings */
+	u_int ps_nargvstr;	/* the number of argument strings */
+	u_int32_t ps_envstr;	/* first of 0 or more environment strings */
+	u_int ps_nenvstr;	/* the number of environment strings */
+};
+
+/*
+ * If FreeBSD & Linux have a difference of opinion about what a trap
+ * means, deal with it here.
+ *
+ * MPSAFE
+ */
+static int
+translate_traps(int signal, int trap_code)
+{
+	if (signal != SIGBUS)
+		return signal;
+	switch (trap_code) {
+	case T_PROTFLT:
+	case T_TSSFLT:
+	case T_DOUBLEFLT:
+	case T_PAGEFLT:
+		return SIGSEGV;
+	default:
+		return signal;
+	}
+}
+
+static int
+elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
+{
+	Elf32_Auxargs *args;
+	Elf32_Addr *base;
+	Elf32_Addr *pos;
+
+	KASSERT(curthread->td_proc == imgp->proc &&
+	    (curthread->td_proc->p_flag & P_SA) == 0,
+	    ("unsafe elf_linux_fixup(), should be curproc"));
+	base = (Elf32_Addr *)*stack_base;
+	args = (Elf32_Auxargs *)imgp->auxargs;
+	pos = base + (imgp->args->argc + imgp->args->envc + 2);
+
+	if (args->trace)
+		AUXARGS_ENTRY_32(pos, AT_DEBUG, 1);
+	if (args->execfd != -1)
+		AUXARGS_ENTRY_32(pos, AT_EXECFD, args->execfd);
+	AUXARGS_ENTRY_32(pos, AT_PHDR, args->phdr);
+	AUXARGS_ENTRY_32(pos, AT_PHENT, args->phent);
+	AUXARGS_ENTRY_32(pos, AT_PHNUM, args->phnum);
+	AUXARGS_ENTRY_32(pos, AT_PAGESZ, args->pagesz);
+	AUXARGS_ENTRY_32(pos, AT_FLAGS, args->flags);
+	AUXARGS_ENTRY_32(pos, AT_ENTRY, args->entry);
+	AUXARGS_ENTRY_32(pos, AT_BASE, args->base);
+	AUXARGS_ENTRY_32(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
+	AUXARGS_ENTRY_32(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
+	AUXARGS_ENTRY_32(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
+	AUXARGS_ENTRY_32(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
+	AUXARGS_ENTRY_32(pos, AT_NULL, 0);
+
+	free(imgp->auxargs, M_TEMP);
+	imgp->auxargs = NULL;
+
+	base--;
+	suword32(base, (uint32_t)imgp->args->argc);
+	*stack_base = (register_t *)base;
+	return 0;
+}
+
+extern int _ucodesel, _ucode32sel, _udatasel;
+extern unsigned long linux_sznonrtsigcode;
+
+static void
+linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
+{
+	struct thread *td = curthread;
+	struct proc *p = td->td_proc;
+	struct sigacts *psp;
+	struct trapframe *regs;
+	struct l_rt_sigframe *fp, frame;
+	int oonstack;
+	int sig;
+	int code;
+	
+	sig = ksi->ksi_signo;
+	code = ksi->ksi_code;
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+	psp = p->p_sigacts;
+	mtx_assert(&psp->ps_mtx, MA_OWNED);
+	regs = td->td_frame;
+	oonstack = sigonstack(regs->tf_rsp);
+
+#ifdef DEBUG
+	if (ldebug(rt_sendsig))
+		printf(ARGS(rt_sendsig, "%p, %d, %p, %u"),
+		    catcher, sig, (void*)mask, code);
+#endif
+	/*
+	 * Allocate space for the signal handler context.
+	 */
+	if ((td->td_pflags & TDP_ALTSTACK) && !oonstack &&
+	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
+		fp = (struct l_rt_sigframe *)(td->td_sigstk.ss_sp +
+		    td->td_sigstk.ss_size - sizeof(struct l_rt_sigframe));
+	} else
+		fp = (struct l_rt_sigframe *)regs->tf_rsp - 1;
+	mtx_unlock(&psp->ps_mtx);
+
+	/*
+	 * Build the argument list for the signal handler.
+	 */
+	if (p->p_sysent->sv_sigtbl)
+		if (sig <= p->p_sysent->sv_sigsize)
+			sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
+
+	bzero(&frame, sizeof(frame));
+
+	frame.sf_handler = PTROUT(catcher);
+	frame.sf_sig = sig;
+	frame.sf_siginfo = PTROUT(&fp->sf_si);
+	frame.sf_ucontext = PTROUT(&fp->sf_sc);
+
+	/* Fill in POSIX parts */
+	frame.sf_si.lsi_signo = sig;
+	frame.sf_si.lsi_code = code;
+	frame.sf_si.lsi_addr = PTROUT(ksi->ksi_addr);
+
+	/*
+	 * Build the signal context to be used by sigreturn.
+	 */
+	frame.sf_sc.uc_flags = 0;		/* XXX ??? */
+	frame.sf_sc.uc_link = 0;		/* XXX ??? */
+
+	frame.sf_sc.uc_stack.ss_sp = PTROUT(td->td_sigstk.ss_sp);
+	frame.sf_sc.uc_stack.ss_size = td->td_sigstk.ss_size;
+	frame.sf_sc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
+	    ? ((oonstack) ? LINUX_SS_ONSTACK : 0) : LINUX_SS_DISABLE;
+	PROC_UNLOCK(p);
+
+	bsd_to_linux_sigset(mask, &frame.sf_sc.uc_sigmask);
+
+	frame.sf_sc.uc_mcontext.sc_mask   = frame.sf_sc.uc_sigmask.__bits[0];
+        frame.sf_sc.uc_mcontext.sc_gs     = rgs();
+        frame.sf_sc.uc_mcontext.sc_fs     = rfs();
+        __asm __volatile("movl %%es,%0" :
+	    "=rm" (frame.sf_sc.uc_mcontext.sc_es));
+        __asm __volatile("movl %%ds,%0" :
+	    "=rm" (frame.sf_sc.uc_mcontext.sc_ds));
+	frame.sf_sc.uc_mcontext.sc_edi    = regs->tf_rdi;
+	frame.sf_sc.uc_mcontext.sc_esi    = regs->tf_rsi;
+	frame.sf_sc.uc_mcontext.sc_ebp    = regs->tf_rbp;
+	frame.sf_sc.uc_mcontext.sc_ebx    = regs->tf_rbx;
+	frame.sf_sc.uc_mcontext.sc_edx    = regs->tf_rdx;
+	frame.sf_sc.uc_mcontext.sc_ecx    = regs->tf_rcx;
+	frame.sf_sc.uc_mcontext.sc_eax    = regs->tf_rax;
+	frame.sf_sc.uc_mcontext.sc_eip    = regs->tf_rip;
+	frame.sf_sc.uc_mcontext.sc_cs     = regs->tf_cs;
+	frame.sf_sc.uc_mcontext.sc_eflags = regs->tf_rflags;
+	frame.sf_sc.uc_mcontext.sc_esp_at_signal = regs->tf_rsp;
+	frame.sf_sc.uc_mcontext.sc_ss     = regs->tf_ss;
+	frame.sf_sc.uc_mcontext.sc_err    = regs->tf_err;
+	frame.sf_sc.uc_mcontext.sc_trapno = bsd_to_linux_trapcode(code);
+
+#ifdef DEBUG
+	if (ldebug(rt_sendsig))
+		printf(LMSG("rt_sendsig flags: 0x%x, sp: %p, ss: 0x%lx, mask: 0x%x"),
+		    frame.sf_sc.uc_stack.ss_flags, td->td_sigstk.ss_sp,
+		    td->td_sigstk.ss_size, frame.sf_sc.uc_mcontext.sc_mask);
+#endif
+
+	if (copyout(&frame, fp, sizeof(frame)) != 0) {
+		/*
+		 * Process has trashed its stack; give it an illegal
+		 * instruction to halt it in its tracks.
+		 */
+#ifdef DEBUG
+		if (ldebug(rt_sendsig))
+			printf(LMSG("rt_sendsig: bad stack %p, oonstack=%x"),
+			    fp, oonstack);
+#endif
+		PROC_LOCK(p);
+		sigexit(td, SIGILL);
+	}
+
+	/*
+	 * Build context to run handler in.
+	 */
+	regs->tf_rsp = PTROUT(fp);
+	regs->tf_rip = LINUX32_PS_STRINGS - *(p->p_sysent->sv_szsigcode) +
+	    linux_sznonrtsigcode;
+	regs->tf_rflags &= ~PSL_T;
+	regs->tf_cs = _ucode32sel;
+	regs->tf_ss = _udatasel;
+	load_ds(_udatasel);
+	td->td_pcb->pcb_ds = _udatasel;
+	load_es(_udatasel);
+	td->td_pcb->pcb_es = _udatasel;
+	/* leave user %fs and %gs untouched */
+	PROC_LOCK(p);
+	mtx_lock(&psp->ps_mtx);
+}
+
+
+/*
+ * Send an interrupt to process.
+ *
+ * Stack is set up to allow sigcode stored
+ * in u. 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.
+ */
+static void
+linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
+{
+	struct thread *td = curthread;
+	struct proc *p = td->td_proc;
+	struct sigacts *psp;
+	struct trapframe *regs;
+	struct l_sigframe *fp, frame;
+	l_sigset_t lmask;
+	int oonstack, i;
+	int sig, code;
+
+	sig = ksi->ksi_signo;
+	code = ksi->ksi_code;
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+	psp = p->p_sigacts;
+	mtx_assert(&psp->ps_mtx, MA_OWNED);
+	if (SIGISMEMBER(psp->ps_siginfo, sig)) {
+		/* Signal handler installed with SA_SIGINFO. */
+		linux_rt_sendsig(catcher, ksi, mask);
+		return;
+	}
+
+	regs = td->td_frame;
+	oonstack = sigonstack(regs->tf_rsp);
+
+#ifdef DEBUG
+	if (ldebug(sendsig))
+		printf(ARGS(sendsig, "%p, %d, %p, %u"),
+		    catcher, sig, (void*)mask, code);
+#endif
+
+	/*
+	 * Allocate space for the signal handler context.
+	 */
+	if ((td->td_pflags & TDP_ALTSTACK) && !oonstack &&
+	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
+		fp = (struct l_sigframe *)(td->td_sigstk.ss_sp +
+		    td->td_sigstk.ss_size - sizeof(struct l_sigframe));
+	} else
+		fp = (struct l_sigframe *)regs->tf_rsp - 1;
+	mtx_unlock(&psp->ps_mtx);
+	PROC_UNLOCK(p);
+
+	/*
+	 * Build the argument list for the signal handler.
+	 */
+	if (p->p_sysent->sv_sigtbl)
+		if (sig <= p->p_sysent->sv_sigsize)
+			sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
+
+	bzero(&frame, sizeof(frame));
+
+	frame.sf_handler = PTROUT(catcher);
+	frame.sf_sig = sig;
+
+	bsd_to_linux_sigset(mask, &lmask);
+
+	/*
+	 * Build the signal context to be used by sigreturn.
+	 */
+	frame.sf_sc.sc_mask   = lmask.__bits[0];
+        frame.sf_sc.sc_gs     = rgs();
+        frame.sf_sc.sc_fs     = rfs();
+        __asm __volatile("movl %%es,%0" : "=rm" (frame.sf_sc.sc_es));
+        __asm __volatile("movl %%ds,%0" : "=rm" (frame.sf_sc.sc_ds));
+	frame.sf_sc.sc_edi    = regs->tf_rdi;
+	frame.sf_sc.sc_esi    = regs->tf_rsi;
+	frame.sf_sc.sc_ebp    = regs->tf_rbp;
+	frame.sf_sc.sc_ebx    = regs->tf_rbx;
+	frame.sf_sc.sc_edx    = regs->tf_rdx;
+	frame.sf_sc.sc_ecx    = regs->tf_rcx;
+	frame.sf_sc.sc_eax    = regs->tf_rax;
+	frame.sf_sc.sc_eip    = regs->tf_rip;
+	frame.sf_sc.sc_cs     = regs->tf_cs;
+	frame.sf_sc.sc_eflags = regs->tf_rflags;
+	frame.sf_sc.sc_esp_at_signal = regs->tf_rsp;
+	frame.sf_sc.sc_ss     = regs->tf_ss;
+	frame.sf_sc.sc_err    = regs->tf_err;
+	frame.sf_sc.sc_trapno = bsd_to_linux_trapcode(code);
+
+	for (i = 0; i < (LINUX_NSIG_WORDS-1); i++)
+		frame.sf_extramask[i] = lmask.__bits[i+1];
+
+	if (copyout(&frame, fp, sizeof(frame)) != 0) {
+		/*
+		 * Process has trashed its stack; give it an illegal
+		 * instruction to halt it in its tracks.
+		 */
+		PROC_LOCK(p);
+		sigexit(td, SIGILL);
+	}
+
+	/*
+	 * Build context to run handler in.
+	 */
+	regs->tf_rsp = PTROUT(fp);
+	regs->tf_rip = LINUX32_PS_STRINGS - *(p->p_sysent->sv_szsigcode);
+	regs->tf_rflags &= ~PSL_T;
+	regs->tf_cs = _ucode32sel;
+	regs->tf_ss = _udatasel;
+	load_ds(_udatasel);
+	td->td_pcb->pcb_ds = _udatasel;
+	load_es(_udatasel);
+	td->td_pcb->pcb_es = _udatasel;
+	/* leave user %fs and %gs untouched */
+	PROC_LOCK(p);
+	mtx_lock(&psp->ps_mtx);
+}
+
+/*
+ * 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
+ * psl to gain improper privileges or to cause
+ * a machine fault.
+ */
+int
+linux_sigreturn(struct thread *td, struct linux_sigreturn_args *args)
+{
+	struct proc *p = td->td_proc;
+	struct l_sigframe frame;
+	struct trapframe *regs;
+	l_sigset_t lmask;
+	int eflags, i;
+	ksiginfo_t ksi;
+
+	regs = td->td_frame;
+
+#ifdef DEBUG
+	if (ldebug(sigreturn))
+		printf(ARGS(sigreturn, "%p"), (void *)args->sfp);
+#endif
+	/*
+	 * The trampoline code hands us the sigframe.
+	 * It is unsafe to keep track of it ourselves, in the event that a
+	 * program jumps out of a signal handler.
+	 */
+	if (copyin(args->sfp, &frame, sizeof(frame)) != 0)
+		return (EFAULT);
+
+	/*
+	 * Check for security violations.
+	 */
+#define	EFLAGS_SECURE(ef, oef)	((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
+	eflags = frame.sf_sc.sc_eflags;
+	/*
+	 * 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 (!EFLAGS_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF))
+		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.
+	 */
+#define	CS_SECURE(cs)	(ISPL(cs) == SEL_UPL)
+	if (!CS_SECURE(frame.sf_sc.sc_cs)) {
+		ksiginfo_init_trap(&ksi);
+		ksi.ksi_signo = SIGBUS;
+		ksi.ksi_code = BUS_OBJERR;
+		ksi.ksi_trapno = T_PROTFLT;
+		ksi.ksi_addr = (void *)regs->tf_rip;
+		trapsignal(td, &ksi);
+		return(EINVAL);
+	}
+
+	lmask.__bits[0] = frame.sf_sc.sc_mask;
+	for (i = 0; i < (LINUX_NSIG_WORDS-1); i++)
+		lmask.__bits[i+1] = frame.sf_extramask[i];
+	PROC_LOCK(p);
+	linux_to_bsd_sigset(&lmask, &td->td_sigmask);
+	SIG_CANTMASK(td->td_sigmask);
+	signotify(td);
+	PROC_UNLOCK(p);
+
+	/*
+	 * Restore signal context.
+	 */
+	/* Selectors were restored by the trampoline. */
+	regs->tf_rdi    = frame.sf_sc.sc_edi;
+	regs->tf_rsi    = frame.sf_sc.sc_esi;
+	regs->tf_rbp    = frame.sf_sc.sc_ebp;
+	regs->tf_rbx    = frame.sf_sc.sc_ebx;
+	regs->tf_rdx    = frame.sf_sc.sc_edx;
+	regs->tf_rcx    = frame.sf_sc.sc_ecx;
+	regs->tf_rax    = frame.sf_sc.sc_eax;
+	regs->tf_rip    = frame.sf_sc.sc_eip;
+	regs->tf_cs     = frame.sf_sc.sc_cs;
+	regs->tf_rflags = eflags;
+	regs->tf_rsp    = frame.sf_sc.sc_esp_at_signal;
+	regs->tf_ss     = frame.sf_sc.sc_ss;
+
+	return (EJUSTRETURN);
+}
+
+/*
+ * System call to cleanup state after a signal
+ * has been taken.  Reset signal mask and
+ * stack state from context left by rt_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
+ * psl to gain improper privileges or to cause
+ * a machine fault.
+ */
+int
+linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args)
+{
+	struct proc *p = td->td_proc;
+	struct l_ucontext uc;
+	struct l_sigcontext *context;
+	l_stack_t *lss;
+	stack_t ss;
+	struct trapframe *regs;
+	int eflags;
+	ksiginfo_t ksi;
+
+	regs = td->td_frame;
+
+#ifdef DEBUG
+	if (ldebug(rt_sigreturn))
+		printf(ARGS(rt_sigreturn, "%p"), (void *)args->ucp);
+#endif
+	/*
+	 * The trampoline code hands us the ucontext.
+	 * It is unsafe to keep track of it ourselves, in the event that a
+	 * program jumps out of a signal handler.
+	 */
+	if (copyin(args->ucp, &uc, sizeof(uc)) != 0)
+		return (EFAULT);
+
+	context = &uc.uc_mcontext;
+
+	/*
+	 * Check for security violations.
+	 */
+#define	EFLAGS_SECURE(ef, oef)	((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
+	eflags = context->sc_eflags;
+	/*
+	 * 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 (!EFLAGS_SECURE(eflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF))
+		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.
+	 */
+#define	CS_SECURE(cs)	(ISPL(cs) == SEL_UPL)
+	if (!CS_SECURE(context->sc_cs)) {
+		ksiginfo_init_trap(&ksi);
+		ksi.ksi_signo = SIGBUS;
+		ksi.ksi_code = BUS_OBJERR;
+		ksi.ksi_trapno = T_PROTFLT;
+		ksi.ksi_addr = (void *)regs->tf_rip;
+		trapsignal(td, &ksi);
+		return(EINVAL);
+	}
+
+	PROC_LOCK(p);
+	linux_to_bsd_sigset(&uc.uc_sigmask, &td->td_sigmask);
+	SIG_CANTMASK(td->td_sigmask);
+	signotify(td);
+	PROC_UNLOCK(p);
+
+	/*
+	 * Restore signal context
+	 */
+	/* Selectors were restored by the trampoline. */
+	regs->tf_rdi    = context->sc_edi;
+	regs->tf_rsi    = context->sc_esi;
+	regs->tf_rbp    = context->sc_ebp;
+	regs->tf_rbx    = context->sc_ebx;
+	regs->tf_rdx    = context->sc_edx;
+	regs->tf_rcx    = context->sc_ecx;
+	regs->tf_rax    = context->sc_eax;
+	regs->tf_rip    = context->sc_eip;
+	regs->tf_cs     = context->sc_cs;
+	regs->tf_rflags = eflags;
+	regs->tf_rsp    = context->sc_esp_at_signal;
+	regs->tf_ss     = context->sc_ss;
+
+	/*
+	 * call sigaltstack & ignore results..
+	 */
+	lss = &uc.uc_stack;
+	ss.ss_sp = PTRIN(lss->ss_sp);
+	ss.ss_size = lss->ss_size;
+	ss.ss_flags = linux_to_bsd_sigaltstack(lss->ss_flags);
+
+#ifdef DEBUG
+	if (ldebug(rt_sigreturn))
+		printf(LMSG("rt_sigret flags: 0x%x, sp: %p, ss: 0x%lx, mask: 0x%x"),
+		    ss.ss_flags, ss.ss_sp, ss.ss_size, context->sc_mask);
+#endif
+	(void)kern_sigaltstack(td, &ss, NULL);
+
+	return (EJUSTRETURN);
+}
+
+/*
+ * MPSAFE
+ */
+static void
+linux_prepsyscall(struct trapframe *tf, int *args, u_int *code, caddr_t *params)
+{
+	args[0] = tf->tf_rbx;
+	args[1] = tf->tf_rcx;
+	args[2] = tf->tf_rdx;
+	args[3] = tf->tf_rsi;
+	args[4] = tf->tf_rdi;
+	args[5] = tf->tf_rbp;	/* Unconfirmed */
+	*params = NULL;		/* no copyin */
+}
+
+/*
+ * If a linux binary is exec'ing something, try this image activator
+ * first.  We override standard shell script execution in order to
+ * be able to modify the interpreter path.  We only do this if a linux
+ * binary is doing the exec, so we do not create an EXEC module for it.
+ */
+static int	exec_linux_imgact_try(struct image_params *iparams);
+
+static int
+exec_linux_imgact_try(struct image_params *imgp)
+{
+    const char *head = (const char *)imgp->image_header;
+    char *rpath;
+    int error = -1, len;
+
+    /*
+     * The interpreter for shell scripts run from a linux binary needs
+     * to be located in /compat/linux if possible in order to recursively
+     * maintain linux path emulation.
+     */
+    if (((const short *)head)[0] == SHELLMAGIC) {
+	    /*
+	     * Run our normal shell image activator.  If it succeeds attempt
+	     * to use the alternate path for the interpreter.  If an alternate
+	     * path is found, use our stringspace to store it.
+	     */
+	    if ((error = exec_shell_imgact(imgp)) == 0) {
+		    linux_emul_convpath(FIRST_THREAD_IN_PROC(imgp->proc),
+			imgp->interpreter_name, UIO_SYSSPACE, &rpath, 0);
+		    if (rpath != NULL) {
+			    len = strlen(rpath) + 1;
+
+			    if (len <= MAXSHELLCMDLEN) {
+				    memcpy(imgp->interpreter_name, rpath, len);
+			    }
+			    free(rpath, M_TEMP);
+		    }
+	    }
+    }
+    return(error);
+}
+
+/*
+ * Clear registers on exec
+ * XXX copied from ia32_signal.c.
+ */
+static void
+exec_linux_setregs(td, entry, stack, ps_strings)
+	struct thread *td;
+	u_long entry;
+	u_long stack;
+	u_long ps_strings;
+{
+	struct trapframe *regs = td->td_frame;
+	struct pcb *pcb = td->td_pcb;
+
+	critical_enter();
+	wrmsr(MSR_FSBASE, 0);
+	wrmsr(MSR_KGSBASE, 0);	/* User value while we're in the kernel */
+	pcb->pcb_fsbase = 0;
+	pcb->pcb_gsbase = 0;
+	critical_exit();
+	load_ds(_udatasel);
+	load_es(_udatasel);
+	load_fs(_udatasel);
+	load_gs(_udatasel);
+	pcb->pcb_ds = _udatasel;
+	pcb->pcb_es = _udatasel;
+	pcb->pcb_fs = _udatasel;
+	pcb->pcb_gs = _udatasel;
+
+	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 = _udatasel;
+	regs->tf_cs = _ucode32sel;
+	regs->tf_rbx = ps_strings;
+	load_cr0(rcr0() | CR0_MP | CR0_TS);
+	fpstate_drop(td);
+
+	/* Return via doreti so that we can change to a different %cs */
+	pcb->pcb_flags |= PCB_FULLCTX;
+	td->td_retval[1] = 0;
+}
+
+/*
+ * XXX copied from ia32_sysvec.c.
+ */
+static register_t *
+linux_copyout_strings(struct image_params *imgp)
+{
+	int argc, envc;
+	u_int32_t *vectp;
+	char *stringp, *destp;
+	u_int32_t *stack_base;
+	struct linux32_ps_strings *arginfo;
+	int sigcodesz;
+
+	/*
+	 * Calculate string base and vector table pointers.
+	 * Also deal with signal trampoline code for this exec type.
+	 */
+	arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS;
+	sigcodesz = *(imgp->proc->p_sysent->sv_szsigcode);
+	destp =	(caddr_t)arginfo - sigcodesz - SPARE_USRSPACE -
+		roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));
+
+	/*
+	 * install sigcode
+	 */
+	if (sigcodesz)
+		copyout(imgp->proc->p_sysent->sv_sigcode,
+			((caddr_t)arginfo - sigcodesz), sigcodesz);
+
+	/*
+	 * If we have a valid auxargs ptr, prepare some room
+	 * on the stack.
+	 */
+	if (imgp->auxargs) {
+		/*
+		 * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
+		 * lower compatibility.
+		 */
+		imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size
+			: (AT_COUNT * 2);
+		/*
+		 * The '+ 2' is for the null pointers at the end of each of
+		 * the arg and env vector sets,and imgp->auxarg_size is room
+		 * for argument of Runtime loader.
+		 */
+		vectp = (u_int32_t *) (destp - (imgp->args->argc + imgp->args->envc + 2 +
+				       imgp->auxarg_size) * sizeof(u_int32_t));
+
+	} else
+		/*
+		 * The '+ 2' is for the null pointers at the end of each of
+		 * the arg and env vector sets
+		 */
+		vectp = (u_int32_t *)
+			(destp - (imgp->args->argc + imgp->args->envc + 2) * sizeof(u_int32_t));
+
+	/*
+	 * vectp also becomes our initial stack base
+	 */
+	stack_base = vectp;
+
+	stringp = imgp->args->begin_argv;
+	argc = imgp->args->argc;
+	envc = imgp->args->envc;
+	/*
+	 * Copy out strings - arguments and environment.
+	 */
+	copyout(stringp, destp, ARG_MAX - imgp->args->stringspace);
+
+	/*
+	 * Fill in "ps_strings" struct for ps, w, etc.
+	 */
+	suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp);
+	suword32(&arginfo->ps_nargvstr, argc);
+
+	/*
+	 * Fill in argument portion of vector table.
+	 */
+	for (; argc > 0; --argc) {
+		suword32(vectp++, (u_int32_t)(intptr_t)destp);
+		while (*stringp++ != 0)
+			destp++;
+		destp++;
+	}
+
+	/* a null vector table pointer separates the argp's from the envp's */
+	suword32(vectp++, 0);
+
+	suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp);
+	suword32(&arginfo->ps_nenvstr, envc);
+
+	/*
+	 * Fill in environment portion of vector table.
+	 */
+	for (; envc > 0; --envc) {
+		suword32(vectp++, (u_int32_t)(intptr_t)destp);
+		while (*stringp++ != 0)
+			destp++;
+		destp++;
+	}
+
+	/* end of vector table is a null pointer */
+	suword32(vectp, 0);
+
+	return ((register_t *)stack_base);
+}
+
+SYSCTL_NODE(_compat, OID_AUTO, linux32, CTLFLAG_RW, 0,
+    "32-bit Linux emulation");
+
+static u_long	linux32_maxdsiz = LINUX32_MAXDSIZ;
+SYSCTL_ULONG(_compat_linux32, OID_AUTO, maxdsiz, CTLFLAG_RW,
+    &linux32_maxdsiz, 0, "");
+static u_long	linux32_maxssiz = LINUX32_MAXSSIZ;
+SYSCTL_ULONG(_compat_linux32, OID_AUTO, maxssiz, CTLFLAG_RW,
+    &linux32_maxssiz, 0, "");
+static u_long	linux32_maxvmem = LINUX32_MAXVMEM;
+SYSCTL_ULONG(_compat_linux32, OID_AUTO, maxvmem, CTLFLAG_RW,
+    &linux32_maxvmem, 0, "");
+
+static void
+linux32_fixlimit(struct rlimit *rl, int which)
+{
+
+	switch (which) {
+	case RLIMIT_DATA:
+		if (linux32_maxdsiz != 0) {			
+			if (rl->rlim_cur > linux32_maxdsiz)
+				rl->rlim_cur = linux32_maxdsiz;
+			if (rl->rlim_max > linux32_maxdsiz)
+				rl->rlim_max = linux32_maxdsiz;
+		}
+		break;
+	case RLIMIT_STACK:
+		if (linux32_maxssiz != 0) {
+			if (rl->rlim_cur > linux32_maxssiz)
+				rl->rlim_cur = linux32_maxssiz;
+			if (rl->rlim_max > linux32_maxssiz)
+				rl->rlim_max = linux32_maxssiz;
+		}
+		break;
+	case RLIMIT_VMEM:
+		if (linux32_maxvmem != 0) {
+			if (rl->rlim_cur > linux32_maxvmem)
+				rl->rlim_cur = linux32_maxvmem;
+			if (rl->rlim_max > linux32_maxvmem)
+				rl->rlim_max = linux32_maxvmem;
+		}
+		break;
+	}
+}
+
+struct sysentvec elf_linux_sysvec = {
+	LINUX_SYS_MAXSYSCALL,
+	linux_sysent,
+	0,
+	LINUX_SIGTBLSZ,
+	bsd_to_linux_signal,
+	ELAST + 1,
+	bsd_to_linux_errno,
+	translate_traps,
+	elf_linux_fixup,
+	linux_sendsig,
+	linux_sigcode,
+	&linux_szsigcode,
+	linux_prepsyscall,
+	"Linux ELF32",
+	elf32_coredump,
+	exec_linux_imgact_try,
+	LINUX_MINSIGSTKSZ,
+	PAGE_SIZE,
+	VM_MIN_ADDRESS,
+	LINUX32_USRSTACK,
+	LINUX32_USRSTACK,
+	LINUX32_PS_STRINGS,
+	VM_PROT_ALL,
+	linux_copyout_strings,
+	exec_linux_setregs,
+	linux32_fixlimit
+};
+
+static Elf32_Brandinfo linux_brand = {
+					ELFOSABI_LINUX,
+					EM_386,
+					"Linux",
+					"/compat/linux",
+					"/lib/ld-linux.so.1",
+					&elf_linux_sysvec,
+					NULL,
+					BI_CAN_EXEC_DYN,
+				 };
+
+static Elf32_Brandinfo linux_glibc2brand = {
+					ELFOSABI_LINUX,
+					EM_386,
+					"Linux",
+					"/compat/linux",
+					"/lib/ld-linux.so.2",
+					&elf_linux_sysvec,
+					NULL,
+					BI_CAN_EXEC_DYN,
+				 };
+
+Elf32_Brandinfo *linux_brandlist[] = {
+					&linux_brand,
+					&linux_glibc2brand,
+					NULL
+				};
+
+static int
+linux_elf_modevent(module_t mod, int type, void *data)
+{
+	Elf32_Brandinfo **brandinfo;
+	int error;
+	struct linux_ioctl_handler **lihp;
+	struct linux_device_handler **ldhp;
+
+	error = 0;
+
+	switch(type) {
+	case MOD_LOAD:
+		for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL;
+		     ++brandinfo)
+			if (elf32_insert_brand_entry(*brandinfo) < 0)
+				error = EINVAL;
+		if (error == 0) {
+			SET_FOREACH(lihp, linux_ioctl_handler_set)
+				linux_ioctl_register_handler(*lihp);
+			SET_FOREACH(ldhp, linux_device_handler_set)
+				linux_device_register_handler(*ldhp);
+			mtx_init(&emul_lock, "emuldata lock", NULL, MTX_DEF);
+			sx_init(&emul_shared_lock, "emuldata->shared lock");
+			LIST_INIT(&futex_list);
+			sx_init(&futex_sx, "futex protection lock");
+			linux_exit_tag = EVENTHANDLER_REGISTER(process_exit, linux_proc_exit,
+			      NULL, 1000);
+			linux_schedtail_tag = EVENTHANDLER_REGISTER(schedtail, linux_schedtail,
+			      NULL, 1000);
+			linux_exec_tag = EVENTHANDLER_REGISTER(process_exec, linux_proc_exec,
+			      NULL, 1000);
+			if (bootverbose)
+				printf("Linux ELF exec handler installed\n");
+		} else
+			printf("cannot insert Linux ELF brand handler\n");
+		break;
+	case MOD_UNLOAD:
+		for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL;
+		     ++brandinfo)
+			if (elf32_brand_inuse(*brandinfo))
+				error = EBUSY;
+		if (error == 0) {
+			for (brandinfo = &linux_brandlist[0];
+			     *brandinfo != NULL; ++brandinfo)
+				if (elf32_remove_brand_entry(*brandinfo) < 0)
+					error = EINVAL;
+		}
+		if (error == 0) {
+			SET_FOREACH(lihp, linux_ioctl_handler_set)
+				linux_ioctl_unregister_handler(*lihp);
+			SET_FOREACH(ldhp, linux_device_handler_set)
+				linux_device_unregister_handler(*ldhp);
+			mtx_destroy(&emul_lock);
+			sx_destroy(&emul_shared_lock);
+			sx_destroy(&futex_sx);
+			EVENTHANDLER_DEREGISTER(process_exit, linux_exit_tag);
+			EVENTHANDLER_DEREGISTER(schedtail, linux_schedtail_tag);
+			EVENTHANDLER_DEREGISTER(process_exec, linux_exec_tag);
+			if (bootverbose)
+				printf("Linux ELF exec handler removed\n");
+		} else
+			printf("Could not deinstall ELF interpreter entry\n");
+		break;
+	default:
+		return EOPNOTSUPP;
+	}
+	return error;
+}
+
+static moduledata_t linux_elf_mod = {
+	"linuxelf",
+	linux_elf_modevent,
+	0
+};
+
+DECLARE_MODULE(linuxelf, linux_elf_mod, SI_SUB_EXEC, SI_ORDER_ANY);
Index: sys/emulation/linux/amd64/syscalls.conf
===================================================================
RCS file: sys/emulation/linux/amd64/syscalls.conf
diff -N sys/emulation/linux/amd64/syscalls.conf
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/emulation/linux/amd64/syscalls.conf	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,12 @@
+# $FreeBSD: src/sys/amd64/linux32/syscalls.conf,v 1.2 2006/08/15 17:25:54 jhb Exp $
+# $DragonFly$
+sysnames="/dev/null"
+sysproto="linux32_proto.h"
+sysproto_h=_LINUX_SYSPROTO_H_
+syshdr="linux32_syscall.h"
+syssw="linux32_sysent.c"
+sysmk="/dev/null"
+syscallprefix="LINUX_SYS_"
+switchname="linux_sysent"
+namesname="linux_syscallnames"
+systrace="/dev/null"
Index: sys/emulation/linux/amd64/syscalls.master
===================================================================
RCS file: sys/emulation/linux/amd64/syscalls.master
diff -N sys/emulation/linux/amd64/syscalls.master
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/emulation/linux/amd64/syscalls.master	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,483 @@
+ $FreeBSD: src/sys/amd64/linux32/syscalls.master,v 1.28 2007/03/30 00:06:21 jkim Exp $
+ $DragonFly$
+
+;	@(#)syscalls.master	8.1 (Berkeley) 7/19/93
+; System call name/number master file (or rather, slave, from LINUX).
+; Processed to create linux_sysent.c, linux_proto.h and linux_syscall.h.
+
+; Columns: number audit type nargs name alt{name,tag,rtyp}/comments
+;	number	system call number, must be in order
+;	audit	the audit event associated with the system call
+;		A value of AUE_NULL means no auditing, but it also means that
+;		there is no audit event for the call at this time. For the
+;		case where the event exists, but we don't want auditing, the
+;		event should be #defined to AUE_NULL in audit_kevents.h.
+;	type	one of STD, OBSOL, UNIMPL
+;	name	psuedo-prototype of syscall routine
+;		If one of the following alts is different, then all appear:
+;	altname	name of system call if different
+;	alttag	name of args struct tag if different from [o]`name'"_args"
+;	altrtyp	return type if not int (bogus - syscalls always return int)
+;		for UNIMPL/OBSOL, name continues with comments
+
+; types:
+;	STD	always included
+;	OBSOL	obsolete, not included in system, only specifies name
+;	UNIMPL	not implemented, placeholder only
+
+#include "opt_compat.h"
+#include <sys/param.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <compat/linux/linux_sysproto.h>
+#include <amd64/linux32/linux.h>
+#include <amd64/linux32/linux32_proto.h>
+
+; Isn't pretty, but there seems to be no other way to trap nosys
+#define	nosys	linux_nosys
+
+; #ifdef's, etc. may be included, and are copied to the output files.
+
+0	AUE_NULL	UNIMPL	setup
+1	AUE_EXIT	NOPROTO	{ void sys_exit(int rval); } exit \
+				    sys_exit_args void
+2	AUE_FORK	STD	{ int linux_fork(void); }
+3	AUE_NULL	NOPROTO	{ int read(int fd, char *buf, \
+				    u_int nbyte); }
+4	AUE_NULL	NOPROTO	{ int write(int fd, char *buf, \
+				    u_int nbyte); }
+5	AUE_OPEN_RWTC	STD	{ int linux_open(char *path, l_int flags, \
+				    l_int mode); }
+6	AUE_CLOSE	NOPROTO	{ int close(int fd); }
+7	AUE_WAIT4	STD	{ int linux_waitpid(l_pid_t pid, \
+				    l_int *status, l_int options); }
+8	AUE_CREAT	STD	{ int linux_creat(char *path, \
+				    l_int mode); }
+9	AUE_LINK	STD	{ int linux_link(char *path, char *to); }
+10	AUE_UNLINK	STD	{ int linux_unlink(char *path); }
+11	AUE_EXECVE	STD	{ int linux_execve(char *path, char **argp, \
+				    char **envp); }
+12	AUE_CHDIR	STD	{ int linux_chdir(char *path); }
+13	AUE_NULL	STD	{ int linux_time(l_time_t *tm); }
+14	AUE_MKNOD	STD	{ int linux_mknod(char *path, l_int mode, \
+				    l_dev_t dev); }
+15	AUE_CHMOD	STD	{ int linux_chmod(char *path, \
+				    l_mode_t mode); }
+16	AUE_LCHOWN	STD	{ int linux_lchown16(char *path, \
+				    l_uid16_t uid, l_gid16_t gid); }
+17	AUE_NULL	UNIMPL	break
+18	AUE_STAT	STD	{ int linux_stat(char *path, \
+				    struct linux_stat *up); }
+19	AUE_LSEEK	STD	{ int linux_lseek(l_uint fdes, l_off_t off, \
+				    l_int whence); }
+20	AUE_GETPID	STD	{ int linux_getpid(void); }
+21	AUE_MOUNT	STD	{ int linux_mount(char *specialfile, \
+				    char *dir, char *filesystemtype, \
+				    l_ulong rwflag, void *data); }
+22	AUE_UMOUNT	STD	{ int linux_oldumount(char *path); }
+23	AUE_SETUID	STD	{ int linux_setuid16(l_uid16_t uid); }
+24	AUE_GETUID	STD	{ int linux_getuid16(void); }
+25	AUE_SETTIMEOFDAY	STD	{ int linux_stime(void); }
+26	AUE_PTRACE	STD	{ int linux_ptrace(l_long req, l_long pid, \
+				    l_long addr, l_long data); }
+27	AUE_NULL	STD	{ int linux_alarm(l_uint secs); }
+28	AUE_FSTAT	UNIMPL	fstat
+29	AUE_NULL	STD	{ int linux_pause(void); }
+30	AUE_UTIME	STD	{ int linux_utime(char *fname, \
+				    struct l_utimbuf *times); }
+31	AUE_NULL	UNIMPL	stty
+32	AUE_NULL	UNIMPL	gtty
+33	AUE_ACCESS	STD	{ int linux_access(char *path, l_int flags); }
+34	AUE_NICE	STD	{ int linux_nice(l_int inc); }
+35	AUE_NULL	UNIMPL	ftime
+36	AUE_SYNC	NOPROTO	{ int sync(void); }
+37	AUE_KILL	STD	{ int linux_kill(l_int pid, l_int signum); }
+38	AUE_RENAME	STD	{ int linux_rename(char *from, char *to); }
+39	AUE_MKDIR	STD	{ int linux_mkdir(char *path, l_int mode); }
+40	AUE_RMDIR	STD	{ int linux_rmdir(char *path); }
+41	AUE_DUP		NOPROTO	{ int dup(u_int fd); }
+42	AUE_PIPE	STD	{ int linux_pipe(l_ulong *pipefds); }
+43	AUE_NULL	STD	{ int linux_times(struct l_times_argv *buf); }
+44	AUE_NULL	UNIMPL	prof
+45	AUE_NULL	STD	{ int linux_brk(l_ulong dsend); }
+46	AUE_SETGID	STD	{ int linux_setgid16(l_gid16_t gid); }
+47	AUE_GETGID	STD	{ int linux_getgid16(void); }
+48	AUE_NULL	STD	{ int linux_signal(l_int sig, \
+				    l_handler_t handler); }
+49	AUE_GETEUID	STD	{ int linux_geteuid16(void); }
+50	AUE_GETEGID	STD	{ int linux_getegid16(void); }
+51	AUE_ACCT	NOPROTO	{ int acct(char *path); }
+52	AUE_UMOUNT	STD	{ int linux_umount(char *path, l_int flags); }
+53	AUE_NULL	UNIMPL	lock
+54	AUE_IOCTL	STD	{ int linux_ioctl(l_uint fd, l_uint cmd, \
+				    uintptr_t arg); }
+55	AUE_FCNTL	STD	{ int linux_fcntl(l_uint fd, l_uint cmd, \
+				    uintptr_t arg); }
+56	AUE_NULL	UNIMPL	mpx
+57	AUE_SETPGRP	NOPROTO	{ int setpgid(int pid, int pgid); }
+58	AUE_NULL	UNIMPL	ulimit
+59	AUE_NULL	STD	{ int linux_olduname(void); }
+60	AUE_UMASK	NOPROTO	{ int umask(int newmask); }
+61	AUE_CHROOT	NOPROTO	{ int chroot(char *path); }
+62	AUE_NULL	STD	{ int linux_ustat(l_dev_t dev, \
+				    struct l_ustat *ubuf); }
+63	AUE_DUP2	NOPROTO	{ int dup2(u_int from, u_int to); }
+64	AUE_GETPPID	STD	{ int linux_getppid(void); }
+65	AUE_GETPGRP	NOPROTO	{ int getpgrp(void); }
+66	AUE_SETSID	NOPROTO	{ int setsid(void); }
+67	AUE_NULL	STD	{ int linux_sigaction(l_int sig, \
+				    l_osigaction_t *nsa, \
+				    l_osigaction_t *osa); }
+68	AUE_NULL	STD	{ int linux_sgetmask(void); }
+69	AUE_NULL	STD	{ int linux_ssetmask(l_osigset_t mask); }
+70	AUE_SETREUID	STD	{ int linux_setreuid16(l_uid16_t ruid, \
+				    l_uid16_t euid); }
+71	AUE_SETREGID	STD	{ int linux_setregid16(l_gid16_t rgid, \
+				    l_gid16_t egid); }
+72	AUE_NULL	STD	{ int linux_sigsuspend(l_int hist0, \
+				    l_int hist1, l_osigset_t mask); }
+73	AUE_NULL	STD	{ int linux_sigpending(l_osigset_t *mask); }
+74	AUE_SYSCTL	STD	{ int linux_sethostname(char *hostname, \
+				    u_int len); }
+75	AUE_SETRLIMIT	STD	{ int linux_setrlimit(l_uint resource, \
+				    struct l_rlimit *rlim); }
+76	AUE_GETRLIMIT	STD	{ int linux_old_getrlimit(l_uint resource, \
+				    struct l_rlimit *rlim); }
+77	AUE_GETRUSAGE	STD	{ int linux_getrusage(int who, \
+				    struct l_rusage *rusage); }
+78	AUE_NULL	STD	{ int linux_gettimeofday( \
+				    struct l_timeval *tp, \
+				    struct timezone *tzp); }
+79	AUE_SETTIMEOFDAY STD	{ int linux_settimeofday( \
+				    struct l_timeval *tp, \
+				    struct timezone *tzp); }
+80	AUE_GETGROUPS	STD	{ int linux_getgroups16(l_uint gidsetsize, \
+				    l_gid16_t *gidset); }
+81	AUE_SETGROUPS	STD	{ int linux_setgroups16(l_uint gidsetsize, \
+				    l_gid16_t *gidset); }
+82	AUE_SELECT	STD	{ int linux_old_select( \
+				    struct l_old_select_argv *ptr); }
+83	AUE_SYMLINK	STD	{ int linux_symlink(char *path, char *to); }
+84	AUE_LSTAT	STD	{ int linux_lstat(char *path, struct linux_lstat *up); }
+85	AUE_READLINK	STD	{ int linux_readlink(char *name, char *buf, \
+				    l_int count); }
+86	AUE_USELIB	UNIMPL	linux_uselib
+87	AUE_SWAPON	NOPROTO	{ int swapon(char *name); }
+88	AUE_REBOOT	STD	{ int linux_reboot(l_int magic1, \
+				    l_int magic2, l_uint cmd, void *arg); }
+89	AUE_GETDIRENTRIES	STD { int linux_readdir(l_uint fd, \
+				    struct l_dirent *dent, l_uint count); }
+90	AUE_MMAP	STD	{ int linux_mmap(struct l_mmap_argv *ptr); }
+91	AUE_MUNMAP	NOPROTO	{ int munmap(caddr_t addr, int len); }
+92	AUE_TRUNCATE	STD	{ int linux_truncate(char *path, \
+				    l_ulong length); }
+93	AUE_FTRUNCATE	STD	{ int linux_ftruncate(int fd, long length); }
+94	AUE_FCHMOD	NOPROTO	{ int fchmod(int fd, int mode); }
+95	AUE_FCHOWN	NOPROTO	{ int fchown(int fd, int uid, int gid); }
+96	AUE_GETPRIORITY	STD	{ int linux_getpriority(int which, int who); }
+97	AUE_SETPRIORITY	NOPROTO	{ int setpriority(int which, int who, \
+				    int prio); }
+98	AUE_PROFILE	UNIMPL	profil
+99	AUE_STATFS	STD	{ int linux_statfs(char *path, \
+				    struct l_statfs_buf *buf); }
+100	AUE_FSTATFS	STD	{ int linux_fstatfs(l_uint fd, \
+				    struct l_statfs_buf *buf); }
+101	AUE_NULL	UNIMPL	ioperm
+102	AUE_NULL	STD	{ int linux_socketcall(l_int what, \
+				    l_ulong args); }
+103	AUE_NULL	STD	{ int linux_syslog(l_int type, char *buf, \
+				    l_int len); }
+104	AUE_SETITIMER	STD	{ int linux_setitimer(l_int which, \
+				    struct l_itimerval *itv, \
+				    struct l_itimerval *oitv); }
+105	AUE_GETITIMER	STD	{ int linux_getitimer(l_int which, \
+				    struct l_itimerval *itv); }
+106	AUE_STAT	STD	{ int linux_newstat(char *path, \
+				    struct l_newstat *buf); }
+107	AUE_LSTAT	STD	{ int linux_newlstat(char *path, \
+				    struct l_newstat *buf); }
+108	AUE_FSTAT	STD	{ int linux_newfstat(l_uint fd, \
+				    struct l_newstat *buf); }
+109	AUE_NULL	STD	{ int linux_uname(void); }
+110	AUE_NULL	STD	{ int linux_iopl(l_ulong level); }
+111	AUE_NULL	STD	{ int linux_vhangup(void); }
+112	AUE_NULL	UNIMPL	idle
+113	AUE_NULL	UNIMPL	vm86old
+114	AUE_WAIT4	STD	{ int linux_wait4(l_pid_t pid, \
+				    l_uint *status, l_int options, \
+				    struct l_rusage *rusage); }
+115	AUE_SWAPOFF	STD	{ int linux_swapoff(void); }
+116	AUE_NULL	STD	{ int linux_sysinfo(struct l_sysinfo *info); }
+117	AUE_NULL	STD	{ int linux_ipc(l_uint what, l_int arg1, \
+				    l_int arg2, l_int arg3, void *ptr, \
+				    l_long arg5); }
+118	AUE_FSYNC	NOPROTO	{ int fsync(int fd); }
+119	AUE_SIGRETURN	STD	{ int linux_sigreturn( \
+				    struct l_sigframe *sfp); }
+; linux uses some strange calling convention here so we have to use the dummy arg
+120	AUE_RFORK	STD	{ int linux_clone(l_int flags, void *stack, \
+				    void *parent_tidptr, int dummy, void * child_tidptr); }
+121	AUE_SYSCTL	NOPROTO	{ int setdomainname(char *name, \
+				    int len); }
+122	AUE_NULL	STD	{ int linux_newuname( \
+				    struct l_new_utsname *buf); }
+123	AUE_NULL	UNIMPL	modify_ldt
+124	AUE_ADJTIME	STD	{ int linux_adjtimex(void); }
+125	AUE_MPROTECT	STD	{ int linux_mprotect(caddr_t addr, int len, \
+				    int prot); }
+126	AUE_SIGPROCMASK	STD	{ int linux_sigprocmask(l_int how, \
+				    l_osigset_t *mask, l_osigset_t *omask); }
+127	AUE_NULL	STD	{ int linux_create_module(void); }
+128	AUE_NULL	STD	{ int linux_init_module(void); }
+129	AUE_NULL	STD	{ int linux_delete_module(void); }
+130	AUE_NULL	STD	{ int linux_get_kernel_syms(void); }
+131	AUE_QUOTACTL	STD	{ int linux_quotactl(void); }
+132	AUE_GETPGID	NOPROTO	{ int getpgid(int pid); }
+133	AUE_FCHDIR	NOPROTO	{ int fchdir(int fd); }
+134	AUE_BDFLUSH	STD	{ int linux_bdflush(void); }
+135	AUE_NULL	STD	{ int linux_sysfs(l_int option, \
+				    l_ulong arg1, l_ulong arg2); }
+136	AUE_PERSONALITY	STD	{ int linux_personality(l_ulong per); }
+137	AUE_NULL	UNIMPL	afs_syscall
+138	AUE_SETFSUID	STD	{ int linux_setfsuid16(l_uid16_t uid); }
+139	AUE_SETFSGID	STD	{ int linux_setfsgid16(l_gid16_t gid); }
+140	AUE_LSEEK	STD	{ int linux_llseek(l_int fd, l_ulong ohigh, \
+				    l_ulong olow, l_loff_t *res, \
+				    l_uint whence); }
+141	AUE_GETDIRENTRIES	STD { int linux_getdents(l_uint fd, void *dent, \
+				    l_uint count); }
+142	AUE_SELECT	STD	{ int linux_select(l_int nfds, \
+				    l_fd_set *readfds, l_fd_set *writefds, \
+				    l_fd_set *exceptfds, \
+				    struct l_timeval *timeout); }
+143	AUE_FLOCK	NOPROTO	{ int flock(int fd, int how); }
+144	AUE_MSYNC	STD	{ int linux_msync(l_ulong addr, \
+				    l_size_t len, l_int fl); }
+145	AUE_READV	STD { int linux_readv(int fd, struct iovec32 *iovp, \
+				    u_int iovcnt); }
+146	AUE_WRITEV	STD { int linux_writev(int fd, struct iovec32 *iovp, \
+				    u_int iovcnt); }
+147	AUE_GETSID	STD	{ int linux_getsid(l_pid_t pid); }
+148	AUE_NULL	STD	{ int linux_fdatasync(l_uint fd); }
+149	AUE_SYSCTL	STD	{ int linux_sysctl( \
+				    struct l___sysctl_args *args); }
+150	AUE_MLOCK	NOPROTO	{ int mlock(const void *addr, size_t len); }
+151	AUE_MUNLOCK	NOPROTO	{ int munlock(const void *addr, size_t len); }
+152	AUE_MLOCKALL	NOPROTO	{ int mlockall(int how); }
+153	AUE_MUNLOCKALL	NOPROTO	{ int munlockall(void); }
+154	AUE_SCHED_SETPARAM	NOPROTO	{ int sched_setparam(pid_t pid, \
+				    const struct sched_param *param); }
+155	AUE_SCHED_GETPARAM	NOPROTO	{ int sched_getparam(pid_t pid, \
+				    struct sched_param *param); }
+156	AUE_SCHED_SETSCHEDULER	STD { int linux_sched_setscheduler( \
+				    l_pid_t pid, l_int policy, \
+				    struct l_sched_param *param); }
+157	AUE_SCHED_GETSCHEDULER	STD { int linux_sched_getscheduler( \
+				    l_pid_t pid); }
+158	AUE_NULL	NOPROTO	{ int sched_yield(void); }
+159	AUE_SCHED_GET_PRIORITY_MAX	STD { int linux_sched_get_priority_max( \
+				    l_int policy); }
+160	AUE_SCHED_GET_PRIORITY_MIN	STD { int linux_sched_get_priority_min( \
+				    l_int policy); }
+161	AUE_SCHED_RR_GET_INTERVAL	STD { int linux_sched_rr_get_interval(l_pid_t pid, \
+				    struct l_timespec *interval); }
+162	AUE_NULL	STD	{ int linux_nanosleep( \
+				    const struct l_timespec *rqtp, \
+				    struct l_timespec *rmtp); }
+163	AUE_NULL	STD	{ int linux_mremap(l_ulong addr, \
+				    l_ulong old_len, l_ulong new_len, \
+				    l_ulong flags, l_ulong new_addr); }
+164	AUE_SETRESUID	STD	{ int linux_setresuid16(l_uid16_t ruid, \
+				    l_uid16_t euid, l_uid16_t suid); }
+165	AUE_GETRESUID	STD	{ int linux_getresuid16(l_uid16_t *ruid, \
+				    l_uid16_t *euid, l_uid16_t *suid); }
+166	AUE_NULL	UNIMPL	vm86
+167	AUE_NULL	STD	{ int linux_query_module(void); }
+168	AUE_POLL	NOPROTO	{ int poll(struct pollfd*, \
+				    unsigned int nfds, int timeout); }
+169	AUE_NULL	STD	{ int linux_nfsservctl(void); }
+170	AUE_SETRESGID	STD	{ int linux_setresgid16(l_gid16_t rgid, \
+				    l_gid16_t egid, l_gid16_t sgid); }
+171	AUE_GETRESGID	STD	{ int linux_getresgid16(l_gid16_t *rgid, \
+				    l_gid16_t *egid, l_gid16_t *sgid); }
+172	AUE_PRCTL	STD	{ int linux_prctl(l_int option, l_int arg2, l_int arg3, \
+				    l_int arg4, l_int arg5); }
+173	AUE_NULL	STD	{ int linux_rt_sigreturn( \
+				    struct l_ucontext *ucp); }
+174	AUE_NULL	STD	{ int linux_rt_sigaction(l_int sig, \
+				    l_sigaction_t *act, l_sigaction_t *oact, \
+				    l_size_t sigsetsize); }
+175	AUE_NULL	STD	{ int linux_rt_sigprocmask(l_int how, \
+				    l_sigset_t *mask, l_sigset_t *omask, \
+				    l_size_t sigsetsize); }
+176	AUE_NULL	STD	{ int linux_rt_sigpending(l_sigset_t *set, \
+				    l_size_t sigsetsize); }
+177	AUE_NULL	STD	{ int linux_rt_sigtimedwait(l_sigset_t *mask, \
+				    l_siginfo_t *ptr, \
+				    struct l_timeval *timeout, \
+				    l_size_t sigsetsize); }
+178	AUE_NULL	STD	{ int linux_rt_sigqueueinfo(void); }
+179	AUE_NULL	STD	{ int linux_rt_sigsuspend( \
+				    l_sigset_t *newset, \
+				    l_size_t sigsetsize); }
+180	AUE_PREAD	STD	{ int linux_pread(l_uint fd, char *buf, \
+				    l_size_t nbyte, l_loff_t offset); }
+181	AUE_PWRITE	STD	{ int linux_pwrite(l_uint fd, char *buf, \
+				    l_size_t nbyte, l_loff_t offset); }
+182	AUE_CHOWN	STD	{ int linux_chown16(char *path, \
+				    l_uid16_t uid, l_gid16_t gid); }
+183	AUE_GETCWD	STD	{ int linux_getcwd(char *buf, \
+				    l_ulong bufsize); }
+184	AUE_CAPGET	STD	{ int linux_capget(void); }
+185	AUE_CAPSET	STD	{ int linux_capset(void); }
+186	AUE_NULL	STD	{ int linux_sigaltstack(l_stack_t *uss, \
+				    l_stack_t *uoss); }
+187	AUE_SENDFILE	STD	{ int linux_sendfile(void); }
+188	AUE_GETPMSG	UNIMPL	getpmsg
+189	AUE_PUTPMSG	UNIMPL	putpmsg
+190	AUE_VFORK	STD	{ int linux_vfork(void); }
+191	AUE_GETRLIMIT	STD	{ int linux_getrlimit(l_uint resource, \
+				    struct l_rlimit *rlim); }
+192	AUE_MMAP	STD	{ int linux_mmap2(l_ulong addr, l_ulong len, \
+				    l_ulong prot, l_ulong flags, l_ulong fd, \
+				    l_ulong pgoff); }
+193	AUE_TRUNCATE	STD	{ int linux_truncate64(char *path, \
+				    l_loff_t length); }
+194	AUE_FTRUNCATE	STD	{ int linux_ftruncate64(l_uint fd, \
+				    l_loff_t length); }
+195	AUE_STAT	STD	{ int linux_stat64(char *filename, \
+				    struct l_stat64 *statbuf, l_long flags); }
+196	AUE_LSTAT	STD	{ int linux_lstat64(char *filename, \
+				    struct l_stat64 *statbuf, l_long flags); }
+197	AUE_FSTAT	STD	{ int linux_fstat64(l_ulong fd, \
+				    struct l_stat64 *statbuf, l_long flags); }
+198	AUE_LCHOWN	STD	{ int linux_lchown(char *path, l_uid_t uid, \
+				    l_gid_t gid); }
+199	AUE_GETUID	STD	{ int linux_getuid(void); }
+200	AUE_GETGID	STD	{ int linux_getgid(void); }
+201	AUE_GETEUID	NOPROTO	{ int geteuid(void); }
+202	AUE_GETEGID	NOPROTO	{ int getegid(void); }
+203	AUE_SETREUID	NOPROTO	{ int setreuid(uid_t ruid, uid_t euid); }
+204	AUE_SETREGID	NOPROTO	{ int setregid(gid_t rgid, gid_t egid); }
+205	AUE_GETGROUPS	STD	{ int linux_getgroups(l_int gidsetsize, \
+				    l_gid_t *grouplist); }
+206	AUE_SETGROUPS	STD	{ int linux_setgroups(l_int gidsetsize, \
+				    l_gid_t *grouplist); }
+207	AUE_FCHOWN	NODEF	fchown fchown fchown_args int
+208	AUE_SETRESUID	NOPROTO	{ int setresuid(uid_t ruid, uid_t euid, \
+				    uid_t suid); }
+209	AUE_GETRESUID	NOPROTO	{ int getresuid(uid_t *ruid, uid_t *euid, \
+				    uid_t *suid); }
+210	AUE_SETRESGID	NOPROTO	{ int setresgid(gid_t rgid, gid_t egid, \
+				    gid_t sgid); }
+211	AUE_GETRESGID	NOPROTO	{ int getresgid(gid_t *rgid, gid_t *egid, \
+				    gid_t *sgid); }
+212	AUE_CHOWN	STD	{ int linux_chown(char *path, l_uid_t uid, \
+				    l_gid_t gid); }
+213	AUE_SETUID	NOPROTO	{ int setuid(uid_t uid); }
+214	AUE_SETGID	NOPROTO	{ int setgid(gid_t gid); }
+215	AUE_SETFSUID	STD	{ int linux_setfsuid(l_uid_t uid); }
+216	AUE_SETFSGID	STD	{ int linux_setfsgid(l_gid_t gid); }
+217	AUE_PIVOT_ROOT	STD	{ int linux_pivot_root(char *new_root, \
+				    char *put_old); }
+218	AUE_MINCORE	STD	{ int linux_mincore(l_ulong start, \
+				    l_size_t len, u_char *vec); }
+219	AUE_MADVISE	NOPROTO	{ int madvise(void *addr, size_t len, \
+				    int behav); }
+220	AUE_GETDIRENTRIES	STD { int linux_getdents64(l_uint fd, \
+				    void *dirent, l_uint count); }
+221	AUE_FCNTL	STD	{ int linux_fcntl64(l_uint fd, l_uint cmd, \
+				    uintptr_t arg); }
+222	AUE_NULL	UNIMPL
+223	AUE_NULL	UNIMPL
+224	AUE_NULL	STD	{ long linux_gettid(void); }
+225	AUE_NULL	UNIMPL	linux_readahead
+226	AUE_NULL	STD	{ int linux_setxattr(void); }
+227	AUE_NULL	STD	{ int linux_lsetxattr(void); }
+228	AUE_NULL	STD	{ int linux_fsetxattr(void); }
+229	AUE_NULL	STD	{ int linux_getxattr(void); }
+230	AUE_NULL	STD	{ int linux_lgetxattr(void); }
+231	AUE_NULL	STD	{ int linux_fgetxattr(void); }
+232	AUE_NULL	STD	{ int linux_listxattr(void); }
+233	AUE_NULL	STD	{ int linux_llistxattr(void); }
+234	AUE_NULL	STD	{ int linux_flistxattr(void); }
+235	AUE_NULL	STD	{ int linux_removexattr(void); }
+236	AUE_NULL	STD	{ int linux_lremovexattr(void); }
+237	AUE_NULL	STD	{ int linux_fremovexattr(void); }
+238	AUE_NULL	STD	{ int linux_tkill(int tid, int sig); }
+239	AUE_SENDFILE	UNIMPL	linux_sendfile64
+240	AUE_NULL	STD	{ int linux_sys_futex(void *uaddr, int op, int val, \
+					struct l_timespec *timeout, void *uaddr2, int val3); }
+241	AUE_NULL	UNIMPL	linux_sched_setaffinity
+242	AUE_NULL	UNIMPL	linux_sched_getaffinity
+243	AUE_NULL	STD	{ int linux_set_thread_area(struct l_user_desc *desc); }
+244	AUE_NULL	UNIMPL	linux_get_thread_area
+245	AUE_NULL	UNIMPL	linux_io_setup
+246	AUE_NULL	UNIMPL	linux_io_destroy
+247	AUE_NULL	UNIMPL	linux_io_getevents
+248	AUE_NULL	UNIMPL	inux_io_submit
+249	AUE_NULL	UNIMPL	linux_io_cancel
+250	AUE_NULL	STD	{ int linux_fadvise64(void); }
+251	AUE_NULL	UNIMPL
+252	AUE_EXIT	STD	{ int linux_exit_group(int error_code); }
+253	AUE_NULL	STD	{ int linux_lookup_dcookie(void); }
+254	AUE_NULL	STD	{ int linux_epoll_create(void); }
+255	AUE_NULL	STD	{ int linux_epoll_ctl(void); }
+256	AUE_NULL	STD	{ int linux_epoll_wait(void); }
+257	AUE_NULL	STD	{ int linux_remap_file_pages(void); }
+258	AUE_NULL	STD	{ int linux_set_tid_address(int *tidptr); }
+259	AUE_NULL	STD	{ int linux_timer_create(void); }
+260	AUE_NULL	STD	{ int linux_timer_settime(void); }
+261	AUE_NULL	STD	{ int linux_timer_gettime(void); }
+262	AUE_NULL	STD	{ int linux_timer_getoverrun(void); }
+263	AUE_NULL	STD	{ int linux_timer_delete(void); }
+264	AUE_CLOCK_SETTIME	STD	{ int linux_clock_settime(clockid_t which, struct l_timespec *tp); }
+265	AUE_NULL	STD	{ int linux_clock_gettime(clockid_t which, struct l_timespec *tp); }
+266	AUE_NULL	STD	{ int linux_clock_getres(clockid_t which, struct l_timespec *tp); }
+267	AUE_NULL	STD	{ int linux_clock_nanosleep(clockid_t which, int flags, \
+					struct l_timespec *rqtp, struct l_timespec *rmtp); }
+268	AUE_STATFS	STD	{ int linux_statfs64(char *path, struct l_statfs64_buf *buf); }
+269	AUE_FSTATFS	STD	{ int linux_fstatfs64(void); }
+270	AUE_NULL	STD	{ int linux_tgkill(int tgid, int pid, int sig); }
+271	AUE_UTIMES	STD	{ int linux_utimes(char *fname, \
+					struct l_timeval *tptr); }
+272	AUE_NULL	STD	{ int linux_fadvise64_64(void); }
+273	AUE_NULL	UNIMPL
+274	AUE_NULL	STD	{ int linux_mbind(void); }
+275	AUE_NULL	STD	{ int linux_get_mempolicy(void); }
+276	AUE_NULL	STD	{ int linux_set_mempolicy(void); }
+277	AUE_NULL	STD	{ int linux_mq_open(void); }
+278	AUE_NULL	STD	{ int linux_mq_unlink(void); }
+279	AUE_NULL	STD	{ int linux_mq_timedsend(void); }
+280	AUE_NULL	STD	{ int linux_mq_timedreceive(void); }
+281	AUE_NULL	STD	{ int linux_mq_notify(void); }
+282	AUE_NULL	STD	{ int linux_mq_getsetattr(void); }
+283	AUE_NULL	STD	{ int linux_kexec_load(void); }
+284	AUE_NULL	STD	{ int linux_waitid(void); }
+285	AUE_NULL	UNIMPL
+286	AUE_NULL	STD	{ int linux_add_key(void); }
+287	AUE_NULL	STD	{ int linux_request_key(void); }
+288	AUE_NULL	STD	{ int linux_keyctl(void); }
+289	AUE_NULL	STD	{ int linux_ioprio_set(void); }
+290	AUE_NULL	STD	{ int linux_ioprio_get(void); }
+291	AUE_NULL	STD	{ int linux_inotify_init(void); }
+292	AUE_NULL	STD	{ int linux_inotify_add_watch(void); }
+293	AUE_NULL	STD	{ int linux_inotify_rm_watch(void); }
+294	AUE_NULL	STD	{ int linux_migrate_pages(void); }
+295	AUE_OPEN_RWTC	STD	{ int linux_openat(l_int dfd, char *filename, \
+					l_int flags, l_int mode); }
+296	AUE_NULL	STD	{ int linux_mkdirat(void); }
+297	AUE_NULL	STD	{ int linux_mknodat(void); }
+298	AUE_NULL	STD	{ int linux_fchownat(void); }
+299	AUE_NULL	STD	{ int linux_futimesat(void); }
+300	AUE_NULL	STD	{ int linux_fstatat64(void); }
+301	AUE_NULL	STD	{ int linux_unlinkat(void); }
+302	AUE_NULL	STD	{ int linux_renameat(void); }
+303	AUE_NULL	STD	{ int linux_linkat(void); }
+304	AUE_NULL	STD	{ int linux_symlinkat(void); }
+305	AUE_NULL	STD	{ int linux_readlinkat(void); }
+306	AUE_NULL	STD	{ int linux_fchmodat(void); }
+307	AUE_NULL	STD	{ int linux_faccessat(void); }
+308	AUE_NULL	STD	{ int linux_pselect6(void); }
+309	AUE_NULL	STD	{ int linux_ppoll(void); }
+310	AUE_NULL	STD	{ int linux_unshare(void); }
Index: sys/platform/pc32/include/md_var.h
===================================================================
RCS file: /home/dcvs/src/sys/platform/pc32/include/md_var.h,v
retrieving revision 1.26
diff -u -r1.26 md_var.h
--- sys/platform/pc32/include/md_var.h	12 Dec 2007 23:49:20 -0000	1.26
+++ sys/platform/pc32/include/md_var.h	10 Feb 2008 11:48:09 -0000
@@ -52,6 +52,8 @@
 				       size_t len);
 extern	void	(*cpu_idle_hook)(void);
 extern	u_int	cpu_exthigh;
+extern	u_int	cpu_feature;       /* CPUID_* features */
+extern	u_int	cpu_feature2;      /* CPUID2_* features */
 extern	u_int	cpu_fxsr;
 extern	u_int	cpu_high;
 extern	u_int	cpu_id;
Index: sys/platform/pc64/amd64/bios.c
===================================================================
RCS file: sys/platform/pc64/amd64/bios.c
diff -N sys/platform/pc64/amd64/bios.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/platform/pc64/amd64/bios.c	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 1997 Michael Smith
+ * Copyright (c) 1998 Jonathan Lemon
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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
+ * 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/amd64/amd64/bios.c,v 1.73 2005/07/21 09:48:36 phk Exp $
+ */
+
+/*
+ * Subset of the i386 bios support code.  We cannot make bios16 nor bios32
+ * calls, so we can leave that out.  However, searching for bios rom
+ * signatures can be useful for locating tables, eg: powernow settings.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/vmparam.h>
+#include <machine/pc/bios.h>
+
+#define BIOS_START	0xe0000
+#define BIOS_SIZE	0x20000
+
+/*
+ * bios_sigsearch
+ *
+ * Search some or all of the BIOS region for a signature string.
+ *
+ * (start)	Optional offset returned from this function 
+ *		(for searching for multiple matches), or NULL
+ *		to start the search from the base of the BIOS.
+ *		Note that this will be a _physical_ address in
+ *		the range 0xe0000 - 0xfffff.
+ * (sig)	is a pointer to the byte(s) of the signature.
+ * (siglen)	number of bytes in the signature.
+ * (paralen)	signature paragraph (alignment) size.
+ * (sigofs)	offset of the signature within the paragraph.
+ *
+ * Returns the _physical_ address of the found signature, 0 if the
+ * signature was not found.
+ */
+
+u_int32_t
+bios_sigsearch(u_int32_t start, u_char *sig, int siglen, int paralen, int sigofs)
+{
+    u_char	*sp, *end;
+    
+    /* compute the starting address */
+    if ((start >= BIOS_START) && (start <= (BIOS_START + BIOS_SIZE))) {
+	sp = (char *)BIOS_PADDRTOVADDR(start);
+    } else if (start == 0) {
+	sp = (char *)BIOS_PADDRTOVADDR(BIOS_START);
+    } else {
+	return 0;				/* bogus start address */
+    }
+
+    /* compute the end address */
+    end = (u_char *)BIOS_PADDRTOVADDR(BIOS_START + BIOS_SIZE);
+
+    /* loop searching */
+    while ((sp + sigofs + siglen) < end) {
+	
+	/* compare here */
+	if (!bcmp(sp + sigofs, sig, siglen)) {
+	    /* convert back to physical address */
+	    return((u_int32_t)(uintptr_t)BIOS_VADDRTOPADDR(sp));
+	}
+	sp += paralen;
+    }
+    return(0);
+}
Index: sys/platform/pc64/amd64/global.s
===================================================================
RCS file: /home/dcvs/src/sys/platform/pc64/amd64/global.s,v
retrieving revision 1.2
diff -u -r1.2 global.s
--- sys/platform/pc64/amd64/global.s	24 Sep 2007 03:24:45 -0000	1.2
+++ sys/platform/pc64/amd64/global.s	10 Feb 2008 11:48:09 -0000
@@ -1,96 +0,0 @@
-/*-
- * Copyright (c) Peter Wemm <peter@netplex.com.au>
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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
- * 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/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 $
- */
-
-#include <machine/asmacros.h>
-#include <machine/pmap.h>
-
-#include "assym.s"
-
-	/*
-	 * Define the layout of the per-cpu address space.  This is
-	 * "constructed" in locore.s on the BSP and in mp_machdep.c for
-	 * each AP.  DO NOT REORDER THESE WITHOUT UPDATING THE REST!
-	 *
-	 * On UP the per-cpu address space is simply placed in the data
-	 * segment.
-	 */
-	.data
-
-	.globl	globaldata
-	.set	globaldata,0
-
-	/*
-	 * Define layout of the global data.  On SMP this lives in
-	 * the per-cpu address space, otherwise it's in the data segment.
-	 */
-	.globl	gd_curthread, gd_npxthread, gd_reqflags, gd_common_tss
-	.set	gd_curthread,globaldata + GD_CURTHREAD
-	.set	gd_npxthread,globaldata + GD_NPXTHREAD
-	.set	gd_reqflags,globaldata + GD_REQFLAGS
-	.set	gd_common_tss,globaldata + GD_COMMON_TSS
-
-	.globl	gd_common_tssd, gd_tss_gdt
-	.set	gd_common_tssd,globaldata + GD_COMMON_TSSD
-	.set	gd_tss_gdt,globaldata + GD_TSS_GDT
-
-	.globl	gd_currentldt
-	.set	gd_currentldt,globaldata + GD_CURRENTLDT
-
-	.globl	gd_fpu_lock, gd_savefpu
-	.set	gd_fpu_lock, globaldata + GD_FPU_LOCK
-	.set	gd_savefpu, globaldata + GD_SAVEFPU
-
-	/*
-	 * The BSP version of these get setup in locore.s and pmap.c, while
-	 * the AP versions are setup in mp_machdep.c.
-	 */
-	.globl  gd_cpuid, gd_other_cpus
-	.globl	gd_ss_eflags, gd_intr_nesting_level
-	.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
-
-	.set    gd_cpuid,globaldata + GD_CPUID
-	.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_CMAP1,globaldata + GD_PRV_CMAP1
-	.set    gd_CMAP2,globaldata + GD_PRV_CMAP2
-	.set    gd_CMAP3,globaldata + GD_PRV_CMAP3
-	.set    gd_PMAP1,globaldata + GD_PRV_PMAP1
-	.set    gd_CADDR1,globaldata + GD_PRV_CADDR1
-	.set    gd_CADDR2,globaldata + GD_PRV_CADDR2
-	.set    gd_CADDR3,globaldata + GD_PRV_CADDR3
-	.set    gd_PADDR1,globaldata + GD_PRV_PADDR1
-	.set	gd_fpending,globaldata + GD_FPENDING
-	.set	gd_ipending,globaldata + GD_IPENDING
-	.set	gd_spending,globaldata + GD_SPENDING
-	.set	gd_cnt,globaldata + GD_CNT
-
Index: sys/platform/pc64/amd64/globals.s
===================================================================
RCS file: sys/platform/pc64/amd64/globals.s
diff -N sys/platform/pc64/amd64/globals.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/platform/pc64/amd64/globals.s	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,167 @@
+/*-
+ * Copyright (c) Peter Wemm <peter@netplex.com.au>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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
+ * 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/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 $
+ */
+
+#include <machine/asmacros.h>
+#include <machine/pmap.h>
+
+#include "assym.s"
+
+	/*
+	 * Define the layout of the per-cpu address space.  This is
+	 * "constructed" in locore.s on the BSP and in mp_machdep.c for
+	 * each AP.  DO NOT REORDER THESE WITHOUT UPDATING THE REST!
+	 *
+	 * On UP the per-cpu address space is simply placed in the data
+	 * segment.
+	 */
+	.data
+	.globl	CPU_prvspace, lapic
+	.set	CPU_prvspace,(MPPML4I << PML4SHIFT)
+	.set	lapic,CPU_prvspace + (NPTEPG-1) * PAGE_SIZE
+
+	.globl	globaldata
+	.set	globaldata,0
+
+	/*
+	 * Define layout of the global data.  On SMP this lives in
+	 * the per-cpu address space, otherwise it's in the data segment.
+	 */
+	.globl	gd_curthread, gd_npxthread, gd_reqflags, gd_common_tss
+	.set	gd_curthread,globaldata + GD_CURTHREAD
+	.set	gd_npxthread,globaldata + GD_NPXTHREAD
+	.set	gd_reqflags,globaldata + GD_REQFLAGS
+	.set	gd_common_tss,globaldata + GD_COMMON_TSS
+
+	.globl	gd_common_tssd, gd_tss_gdt
+	.set	gd_common_tssd,globaldata + GD_COMMON_TSSD
+	.set	gd_tss_gdt,globaldata + GD_TSS_GDT
+
+	.globl	gd_currentldt
+	.set	gd_currentldt,globaldata + GD_CURRENTLDT
+
+	.globl	gd_fpu_lock, gd_savefpu
+	.set	gd_fpu_lock, globaldata + GD_FPU_LOCK
+	.set	gd_savefpu, globaldata + GD_SAVEFPU
+
+	/*
+	 * The BSP version of these get setup in locore.s and pmap.c, while
+	 * the AP versions are setup in mp_machdep.c.
+	 */
+	.globl  gd_cpuid, gd_other_cpus
+	.globl	gd_ss_eflags, gd_intr_nesting_level
+	.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, gd_private_tss
+
+	.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_CMAP1,globaldata + GD_PRV_CMAP1
+	.set    gd_CMAP2,globaldata + GD_PRV_CMAP2
+	.set    gd_CMAP3,globaldata + GD_PRV_CMAP3
+	.set    gd_PMAP1,globaldata + GD_PRV_PMAP1
+	.set    gd_CADDR1,globaldata + GD_PRV_CADDR1
+	.set    gd_CADDR2,globaldata + GD_PRV_CADDR2
+	.set    gd_CADDR3,globaldata + GD_PRV_CADDR3
+	.set    gd_PADDR1,globaldata + GD_PRV_PADDR1
+	.set	gd_fpending,globaldata + GD_FPENDING
+	.set	gd_ipending,globaldata + GD_IPENDING
+	.set	gd_spending,globaldata + GD_SPENDING
+	.set	gd_cnt,globaldata + GD_CNT
+
+#ifdef SMP
+	.globl	lapic_eoi, lapic_svr, lapic_tpr, lapic_irr1, lapic_ver
+	.globl	lapic_icr_lo,lapic_icr_hi,lapic_isr1
+/*
+ * Do not clutter our namespace with these unless we need them in other
+ * assembler code.  The C code uses different definitions.
+ */
+#if 0
+	.globl	lapic_id,lapic_ver,lapic_tpr,lapic_apr,lapic_ppr,lapic_eoi
+	.globl	lapic_ldr,lapic_dfr,lapic_svr,lapic_isr,lapic_isr0
+	.globl	lapic_isr2,lapic_isr3,lapic_isr4,lapic_isr5,lapic_isr6
+	.globl	lapic_isr7,lapic_tmr,lapic_tmr0,lapic_tmr1,lapic_tmr2
+	.globl	lapic_tmr3,lapic_tmr4,lapic_tmr5,lapic_tmr6,lapic_tmr7
+	.globl	lapic_irr,lapic_irr0,lapic_irr1,lapic_irr2,lapic_irr3
+	.globl	lapic_irr4,lapic_irr5,lapic_irr6,lapic_irr7,lapic_esr
+	.globl	lapic_lvtt,lapic_pcint,lapic_lvt1
+	.globl	lapic_lvt2,lapic_lvt3,lapic_ticr,lapic_tccr,lapic_tdcr
+#endif
+	.set	lapic_id,	lapic + 0x020
+	.set	lapic_ver,	lapic + 0x030
+	.set	lapic_tpr,	lapic + 0x080
+	.set	lapic_apr,	lapic + 0x090
+	.set	lapic_ppr,	lapic + 0x0a0
+	.set	lapic_eoi,	lapic + 0x0b0
+	.set	lapic_ldr,	lapic + 0x0d0
+	.set	lapic_dfr,	lapic + 0x0e0
+	.set	lapic_svr,	lapic + 0x0f0
+	.set	lapic_isr,	lapic + 0x100
+	.set	lapic_isr0,	lapic + 0x100
+	.set	lapic_isr1,	lapic + 0x110
+	.set	lapic_isr2,	lapic + 0x120
+	.set	lapic_isr3,	lapic + 0x130
+	.set	lapic_isr4,	lapic + 0x140
+	.set	lapic_isr5,	lapic + 0x150
+	.set	lapic_isr6,	lapic + 0x160
+	.set	lapic_isr7,	lapic + 0x170
+	.set	lapic_tmr,	lapic + 0x180
+	.set	lapic_tmr0,	lapic + 0x180
+	.set	lapic_tmr1,	lapic + 0x190
+	.set	lapic_tmr2,	lapic + 0x1a0
+	.set	lapic_tmr3,	lapic + 0x1b0
+	.set	lapic_tmr4,	lapic + 0x1c0
+	.set	lapic_tmr5,	lapic + 0x1d0
+	.set	lapic_tmr6,	lapic + 0x1e0
+	.set	lapic_tmr7,	lapic + 0x1f0
+	.set	lapic_irr,	lapic + 0x200
+	.set	lapic_irr0,	lapic + 0x200
+	.set	lapic_irr1,	lapic + 0x210
+	.set	lapic_irr2,	lapic + 0x220
+	.set	lapic_irr3,	lapic + 0x230
+	.set	lapic_irr4,	lapic + 0x240
+	.set	lapic_irr5,	lapic + 0x250
+	.set	lapic_irr6,	lapic + 0x260
+	.set	lapic_irr7,	lapic + 0x270
+	.set	lapic_esr,	lapic + 0x280
+	.set	lapic_icr_lo,	lapic + 0x300
+	.set	lapic_icr_hi,	lapic + 0x310
+	.set	lapic_lvtt,	lapic + 0x320
+	.set	lapic_pcint,	lapic + 0x340
+	.set	lapic_lvt1,	lapic + 0x350
+	.set	lapic_lvt2,	lapic + 0x360
+	.set	lapic_lvt3,	lapic + 0x370
+	.set	lapic_ticr,	lapic + 0x380
+	.set	lapic_tccr,	lapic + 0x390
+	.set	lapic_tdcr,	lapic + 0x3e0
+#endif
+
Index: sys/platform/pc64/amd64/identcpu.c
===================================================================
RCS file: sys/platform/pc64/amd64/identcpu.c
diff -N sys/platform/pc64/amd64/identcpu.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/platform/pc64/amd64/identcpu.c	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,578 @@
+/*-
+ * Copyright (c) 1992 Terrence R. Lambert.
+ * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
+ * Copyright (c) 1997 KATO Takenori.
+ * 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.
+ *
+ * $FreeBSD: src/sys/amd64/amd64/identcpu.c,v 1.154 2007/05/30 14:23:26 des Exp $
+ * $DragonFly $
+ */
+
+#include "opt_cpu.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+/* #include <sys/cpu.h> */
+#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>
+
+#include <machine_base/isa/icu.h>
+
+/* 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);
+void setPQL2(int *const size, int *const ways);
+static void setPQL2_AMD(int *const size, int *const ways);
+
+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 */
+};
+
+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:
+		hw_clockrate = (tsc_freq + 5000) / 1000000;
+		kprintf("%jd.%02d-MHz ",
+		       (intmax_t)(tsc_freq + 4999) / 1000000,
+		       (u_int)((tsc_freq + 4999) / 10000) % 100);
+		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>"
+				"\003RSVD2"	/* "Reserved" bit 2 */
+				"\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 */
+				"\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>"
+				);
+			}
+
+			/*
+			 * 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 */
+				"\033<b26>"	/* Undefined */
+				"\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;
+			}
+			if (cmp > 1)
+				kprintf("\n  Cores per package: %d", cmp);
+			if ((htt / cmp) > 1)
+				kprintf("\n  Logical CPUs per core: %d",
+				    htt / cmp);
+		}
+	}
+	/* 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
+#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
+	case CPUCLASS_K8:
+#endif
+		panic("CPU class not configured");
+	default:
+		break;
+	}
+}
+
+#if 0
+/* XXX do we need this? it relies a sys/cpu.h headers and the macro 
+ * (EVENTHANDLER_DEFINE) is defined in sys/eventhandler.h in the freebsd version
+ * but not in dflybsd yet.
+ */
+
+/* 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);	
+	}
+}
+
+static void             
+setPQL2_AMD(int *const size, int *const ways)
+{
+	if (cpu_exthigh >= 0x80000006) {
+		u_int regs[4];
+
+		do_cpuid(0x80000006, regs);
+		*size = regs[2] >> 16;
+		*ways = (regs[2] >> 12) & 0x0f;
+		switch (*ways) {
+		case 0:				/* disabled/not present */
+		case 15:			/* fully associative */
+		default: *ways = 1; break;	/* reserved configuration */
+		case 4: *ways = 4; break;
+		case 6: *ways = 8; break;
+		case 8: *ways = 16; break;
+		}
+	}
+}
+
+void
+setPQL2(int *const size, int *const ways)
+{
+	if (strcmp(cpu_vendor, "AuthenticAMD") == 0)
+		setPQL2_AMD(size, ways);
+}
Index: sys/platform/pc64/amd64/initcpu.c
===================================================================
RCS file: sys/platform/pc64/amd64/initcpu.c
diff -N sys/platform/pc64/amd64/initcpu.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/platform/pc64/amd64/initcpu.c	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,84 @@
+/*-
+ * Copyright (c) KATO Takenori, 1997, 1998.
+ * 
+ * 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.
+ *
+ * $FreeBSD: src/sys/amd64/amd64/initcpu.c,v 1.50 2006/06/19 22:59:28 davidxu 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 0
+			pg_nx = PG_NX;
+		#endif
+	}
+}
Index: sys/platform/pc64/amd64/locore.s
===================================================================
RCS file: /home/dcvs/src/sys/platform/pc64/amd64/locore.s,v
retrieving revision 1.1
diff -u -r1.1 locore.s
--- sys/platform/pc64/amd64/locore.s	23 Sep 2007 04:29:31 -0000	1.1
+++ sys/platform/pc64/amd64/locore.s	10 Feb 2008 11:48:09 -0000
@@ -85,7 +85,7 @@
 	movq	$bootstack,%rsp
 	xorl	%ebp, %ebp
 
-	/* call	hammer_time*/		/* set up cpu for unix operation */
+	call	hammer_time		/* set up cpu for unix operation */
 	movq	%rax,%rsp		/* set up kstack for mi_startup() */
 	call	mi_startup		/* autoconfiguration, mountroot etc */
 0:	hlt
Index: sys/platform/pc64/amd64/machdep.c
===================================================================
RCS file: sys/platform/pc64/amd64/machdep.c
diff -N sys/platform/pc64/amd64/machdep.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/platform/pc64/amd64/machdep.c	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,1956 @@
+/*-
+ * Copyright (c) 2003 Peter Wemm.
+ * Copyright (c) 1992 Terrence R. Lambert.
+ * Copyright (c) 1982, 1987, 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.
+ *
+ *	from: @(#)machdep.c	7.4 (Berkeley) 6/3/91
+ *
+ * $FreeBSD: src/sys/amd64/amd64/machdep.c,v 1.675 2007/06/06 07:35:07 davidxu Exp $
+ * $DragonFly $
+ */
+
+#include "opt_atalk.h"
+#include "opt_atpic.h"
+#include "opt_compat.h"
+#include "opt_cpu.h"
+#include "opt_ddb.h"
+#include "opt_inet.h"
+#include "opt_ipx.h"
+#include "opt_isa.h"
+#include "opt_kstack_pages.h"
+#include "opt_maxmem.h"
+#include "opt_msgbuf.h"
+#include "opt_perfmon.h"
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/bio.h>
+#include <sys/buf.h>
+#include <sys/bus.h>
+#include <sys/callout.h>
+#include <sys/clock.h>
+#include <sys/cons.h>
+#include <sys/cpu.h>
+#include <sys/eventhandler.h>
+#include <sys/exec.h>
+#include <sys/imgact.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/memrange.h>
+#include <sys/msgbuf.h>
+#include <sys/mutex.h>
+#include <sys/pcpu.h>
+#include <sys/ptrace.h>
+#include <sys/reboot.h>
+#include <sys/sched.h>
+#include <sys/signalvar.h>
+#include <sys/sysctl.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/ucontext.h>
+#include <sys/vmmeter.h>
+
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_pager.h>
+#include <vm/vm_param.h>
+
+#ifdef DDB
+#ifndef KDB
+#error KDB must be enabled in order for DDB to work!
+#endif
+#endif
+#include <ddb/ddb.h>
+
+#include <net/netisr.h>
+
+#include <machine/clock.h>
+#include <machine/cpu.h>
+#include <machine/cputypes.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/metadata.h>
+#include <machine/pc/bios.h>
+#include <machine/pcb.h>
+#include <machine/proc.h>
+#include <machine/reg.h>
+#include <machine/sigframe.h>
+#include <machine/specialreg.h>
+#ifdef PERFMON
+#include <machine/perfmon.h>
+#endif
+#include <machine/tss.h>
+#ifdef SMP
+#include <machine/smp.h>
+#endif
+
+#ifdef DEV_ATPIC
+#include <amd64/isa/icu.h>
+#else
+#include <machine/apicvar.h>
+#endif
+
+#include <isa/isareg.h>
+#include <isa/rtc.h>
+
+/* Sanity check for __curthread() */
+CTASSERT(offsetof(struct pcpu, pc_curthread) == 0);
+
+extern u_int64_t hammer_time(u_int64_t, u_int64_t);
+extern void dblfault_handler(void);
+
+extern void printcpuinfo(void);	/* XXX header file */
+extern void identify_cpu(void);
+extern void panicifcpuunsupported(void);
+
+#define	CS_SECURE(cs)		(ISPL(cs) == SEL_UPL)
+#define	EFL_SECURE(ef, oef)	((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
+
+static void cpu_startup(void *);
+static void get_fpcontext(struct thread *td, mcontext_t *mcp);
+static int  set_fpcontext(struct thread *td, const mcontext_t *mcp);
+SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
+
+#ifdef DDB
+extern vm_offset_t ksym_start, ksym_end;
+#endif
+
+int	_udatasel, _ucodesel, _ucode32sel;
+
+int cold = 1;
+
+long Maxmem = 0;
+long realmem = 0;
+
+/*
+ * The number of PHYSMAP entries must be one less than the number of
+ * PHYSSEG entries because the PHYSMAP entry that spans the largest
+ * physical address that is accessible by ISA DMA is split into two
+ * PHYSSEG entries.
+ */
+#define	PHYSMAP_SIZE	(2 * (VM_PHYSSEG_MAX - 1))
+
+vm_paddr_t phys_avail[PHYSMAP_SIZE + 2];
+vm_paddr_t dump_avail[PHYSMAP_SIZE + 2];
+
+/* must be 2 less so 0 0 can signal end of chunks */
+#define PHYS_AVAIL_ARRAY_END ((sizeof(phys_avail) / sizeof(phys_avail[0])) - 2)
+#define DUMP_AVAIL_ARRAY_END ((sizeof(dump_avail) / sizeof(dump_avail[0])) - 2)
+
+struct kva_md_info kmi;
+
+static struct trapframe proc0_tf;
+struct region_descriptor r_gdt, r_idt;
+
+struct pcpu __pcpu[MAXCPU];
+
+struct mtx icu_lock;
+
+struct mem_range_softc mem_range_softc;
+
+static void
+cpu_startup(dummy)
+	void *dummy;
+{
+	/*
+	 * Good {morning,afternoon,evening,night}.
+	 */
+	startrtclock();
+	printcpuinfo();
+	panicifcpuunsupported();
+#ifdef PERFMON
+	perfmon_init();
+#endif
+	printf("usable memory = %ju (%ju MB)\n", ptoa((uintmax_t)physmem),
+	    ptoa((uintmax_t)physmem) / 1048576);
+	realmem = Maxmem;
+	/*
+	 * Display any holes after the first chunk of extended memory.
+	 */
+	if (bootverbose) {
+		int indx;
+
+		printf("Physical memory chunk(s):\n");
+		for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
+			vm_paddr_t size;
+
+			size = phys_avail[indx + 1] - phys_avail[indx];
+			printf(
+			    "0x%016jx - 0x%016jx, %ju bytes (%ju pages)\n",
+			    (uintmax_t)phys_avail[indx],
+			    (uintmax_t)phys_avail[indx + 1] - 1,
+			    (uintmax_t)size, (uintmax_t)size / PAGE_SIZE);
+		}
+	}
+
+	vm_ksubmap_init(&kmi);
+
+	printf("avail memory  = %ju (%ju MB)\n",
+	    ptoa((uintmax_t)cnt.v_free_count),
+	    ptoa((uintmax_t)cnt.v_free_count) / 1048576);
+
+	/*
+	 * Set up buffers, so they can be used to read disk labels.
+	 */
+	bufinit();
+	vm_pager_bufferinit();
+
+	cpu_setregs();
+}
+
+/*
+ * 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.
+ */
+void
+sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
+{
+	struct sigframe sf, *sfp;
+	struct proc *p;
+	struct thread *td;
+	struct sigacts *psp;
+	char *sp;
+	struct trapframe *regs;
+	int sig;
+	int oonstack;
+
+	td = curthread;
+	p = td->td_proc;
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+	sig = ksi->ksi_signo;
+	psp = p->p_sigacts;
+	mtx_assert(&psp->ps_mtx, MA_OWNED);
+	regs = td->td_frame;
+	oonstack = sigonstack(regs->tf_rsp);
+
+	/* Save user context. */
+	bzero(&sf, sizeof(sf));
+	sf.sf_uc.uc_sigmask = *mask;
+	sf.sf_uc.uc_stack = td->td_sigstk;
+	sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
+	    ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
+	sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
+	bcopy(regs, &sf.sf_uc.uc_mcontext.mc_rdi, sizeof(*regs));
+	sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
+	get_fpcontext(td, &sf.sf_uc.uc_mcontext);
+	fpstate_drop(td);
+
+	/* Allocate space for the signal handler context. */
+	if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
+	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
+		sp = td->td_sigstk.ss_sp +
+		    td->td_sigstk.ss_size - sizeof(struct sigframe);
+#if defined(COMPAT_43)
+		td->td_sigstk.ss_flags |= SS_ONSTACK;
+#endif
+	} else
+		sp = (char *)regs->tf_rsp - sizeof(struct sigframe) - 128;
+	/* Align to 16 bytes. */
+	sfp = (struct sigframe *)((unsigned long)sp & ~0xFul);
+
+	/* Translate the signal if appropriate. */
+	if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
+		sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
+
+	/* Build the argument list for the signal handler. */
+	regs->tf_rdi = sig;			/* arg 1 in %rdi */
+	regs->tf_rdx = (register_t)&sfp->sf_uc;	/* arg 3 in %rdx */
+	if (SIGISMEMBER(psp->ps_siginfo, sig)) {
+		/* Signal handler installed with SA_SIGINFO. */
+		regs->tf_rsi = (register_t)&sfp->sf_si;	/* arg 2 in %rsi */
+		sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
+
+		/* Fill in POSIX parts */
+		sf.sf_si = ksi->ksi_info;
+		sf.sf_si.si_signo = sig; /* maybe a translated signal */
+		regs->tf_rcx = (register_t)ksi->ksi_addr; /* arg 4 in %rcx */
+	} else {
+		/* Old FreeBSD-style arguments. */
+		regs->tf_rsi = ksi->ksi_code;	/* arg 2 in %rsi */
+		regs->tf_rcx = (register_t)ksi->ksi_addr; /* arg 4 in %rcx */
+		sf.sf_ahu.sf_handler = catcher;
+	}
+	mtx_unlock(&psp->ps_mtx);
+	PROC_UNLOCK(p);
+
+	/*
+	 * Copy the sigframe out to the user's stack.
+	 */
+	if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
+#ifdef DEBUG
+		printf("process %ld has trashed its stack\n", (long)p->p_pid);
+#endif
+		PROC_LOCK(p);
+		sigexit(td, SIGILL);
+	}
+
+	regs->tf_rsp = (long)sfp;
+	regs->tf_rip = PS_STRINGS - *(p->p_sysent->sv_szsigcode);
+	regs->tf_rflags &= ~PSL_T;
+	regs->tf_cs = _ucodesel;
+	PROC_LOCK(p);
+	mtx_lock(&psp->ps_mtx);
+}
+
+/*
+ * 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.
+ *
+ * MPSAFE
+ */
+int
+sigreturn(td, uap)
+	struct thread *td;
+	struct sigreturn_args /* {
+		const struct __ucontext *sigcntxp;
+	} */ *uap;
+{
+	ucontext_t uc;
+	struct proc *p = td->td_proc;
+	struct trapframe *regs;
+	const ucontext_t *ucp;
+	long rflags;
+	int cs, error, ret;
+	ksiginfo_t ksi;
+
+	error = copyin(uap->sigcntxp, &uc, sizeof(uc));
+	if (error != 0)
+		return (error);
+	ucp = &uc;
+	regs = td->td_frame;
+	rflags = ucp->uc_mcontext.mc_rflags;
+	/*
+	 * 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_rflags for faults.  Debuggers
+	 * should sometimes set it there too.  tf_rflags 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)) {
+		printf("sigreturn: rflags = 0x%lx\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)) {
+		printf("sigreturn: cs = 0x%x\n", cs);
+		ksiginfo_init_trap(&ksi);
+		ksi.ksi_signo = SIGBUS;
+		ksi.ksi_code = BUS_OBJERR;
+		ksi.ksi_trapno = T_PROTFLT;
+		ksi.ksi_addr = (void *)regs->tf_rip;
+		trapsignal(td, &ksi);
+		return (EINVAL);
+	}
+
+	ret = set_fpcontext(td, &ucp->uc_mcontext);
+	if (ret != 0)
+		return (ret);
+	bcopy(&ucp->uc_mcontext.mc_rdi, regs, sizeof(*regs));
+
+	PROC_LOCK(p);
+#if defined(COMPAT_43)
+	if (ucp->uc_mcontext.mc_onstack & 1)
+		td->td_sigstk.ss_flags |= SS_ONSTACK;
+	else
+		td->td_sigstk.ss_flags &= ~SS_ONSTACK;
+#endif
+
+	td->td_sigmask = ucp->uc_sigmask;
+	SIG_CANTMASK(td->td_sigmask);
+	signotify(td);
+	PROC_UNLOCK(p);
+	td->td_pcb->pcb_flags |= PCB_FULLCTX;
+	return (EJUSTRETURN);
+}
+
+#ifdef COMPAT_FREEBSD4
+int
+freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
+{
+ 
+	return sigreturn(td, (struct sigreturn_args *)uap);
+}
+#endif
+
+
+/*
+ * Machine dependent boot() routine
+ *
+ * I haven't seen anything to put here yet
+ * Possibly some stuff might be grafted back here from boot()
+ */
+void
+cpu_boot(int howto)
+{
+}
+
+/* Get current clock frequency for the given cpu id. */
+int
+cpu_est_clockrate(int cpu_id, uint64_t *rate)
+{
+	register_t reg;
+	uint64_t tsc1, tsc2;
+
+	if (pcpu_find(cpu_id) == NULL || rate == NULL)
+		return (EINVAL);
+
+	/* If we're booting, trust the rate calibrated moments ago. */
+	if (cold) {
+		*rate = tsc_freq;
+		return (0);
+	}
+
+#ifdef SMP
+	/* Schedule ourselves on the indicated cpu. */
+	thread_lock(curthread);
+	sched_bind(curthread, cpu_id);
+	thread_unlock(curthread);
+#endif
+
+	/* Calibrate by measuring a short delay. */
+	reg = intr_disable();
+	tsc1 = rdtsc();
+	DELAY(1000);
+	tsc2 = rdtsc();
+	intr_restore(reg);
+
+#ifdef SMP
+	thread_lock(curthread);
+	sched_unbind(curthread);
+	thread_unlock(curthread);
+#endif
+
+	/*
+	 * Calculate the difference in readings, convert to Mhz, and
+	 * subtract 0.5% of the total.  Empirical testing has shown that
+	 * overhead in DELAY() works out to approximately this value.
+	 */
+	tsc2 -= tsc1;
+	*rate = tsc2 * 1000 - tsc2 * 5;
+	return (0);
+}
+
+/*
+ * Shutdown the CPU as much as possible
+ */
+void
+cpu_halt(void)
+{
+	for (;;)
+		__asm__ ("hlt");
+}
+
+/*
+ * Hook to idle the CPU when possible.  In the SMP case we default to
+ * off because a halted cpu will not currently pick up a new thread in the
+ * run queue until the next timer tick.  If turned on this will result in
+ * approximately a 4.2% loss in real time performance in buildworld tests
+ * (but improves user and sys times oddly enough), and saves approximately
+ * 5% in power consumption on an idle machine (tests w/2xCPU 1.1GHz P3).
+ *
+ * XXX we need to have a cpu mask of idle cpus and generate an IPI or
+ * otherwise generate some sort of interrupt to wake up cpus sitting in HLT.
+ * Then we can have our cake and eat it too.
+ *
+ * XXX I'm turning it on for SMP as well by default for now.  It seems to
+ * help lock contention somewhat, and this is critical for HTT. -Peter
+ */
+static int	cpu_idle_hlt = 1;
+TUNABLE_INT("machdep.cpu_idle_hlt", &cpu_idle_hlt);
+SYSCTL_INT(_machdep, OID_AUTO, cpu_idle_hlt, CTLFLAG_RW,
+    &cpu_idle_hlt, 0, "Idle loop HLT enable");
+
+static void
+cpu_idle_default(void)
+{
+	/*
+	 * we must absolutely guarentee that hlt is the
+	 * absolute next instruction after sti or we
+	 * introduce a timing window.
+	 */
+	__asm __volatile("sti; hlt");
+}
+
+/*
+ * Note that we have to be careful here to avoid a race between checking
+ * sched_runnable() and actually halting.  If we don't do this, we may waste
+ * the time between calling hlt and the next interrupt even though there
+ * is a runnable process.
+ */
+void
+cpu_idle(void)
+{
+
+#ifdef SMP
+	if (mp_grab_cpu_hlt())
+		return;
+#endif
+	if (cpu_idle_hlt) {
+		disable_intr();
+  		if (sched_runnable())
+			enable_intr();
+		else
+			(*cpu_idle_hook)();
+	}
+}
+
+/* Other subsystems (e.g., ACPI) can hook this later. */
+void (*cpu_idle_hook)(void) = cpu_idle_default;
+
+/*
+ * Clear registers on exec
+ */
+void
+exec_setregs(td, entry, stack, ps_strings)
+	struct thread *td;
+	u_long entry;
+	u_long stack;
+	u_long ps_strings;
+{
+	struct trapframe *regs = td->td_frame;
+	struct pcb *pcb = td->td_pcb;
+	
+	critical_enter();
+	wrmsr(MSR_FSBASE, 0);
+	wrmsr(MSR_KGSBASE, 0);	/* User value while we're in the kernel */
+	pcb->pcb_fsbase = 0;
+	pcb->pcb_gsbase = 0;
+	critical_exit();
+	load_ds(_udatasel);
+	load_es(_udatasel);
+	load_fs(_udatasel);
+	load_gs(_udatasel);
+	pcb->pcb_ds = _udatasel;
+	pcb->pcb_es = _udatasel;
+	pcb->pcb_fs = _udatasel;
+	pcb->pcb_gs = _udatasel;
+
+	bzero((char *)regs, sizeof(struct trapframe));
+	regs->tf_rip = entry;
+	regs->tf_rsp = ((stack - 8) & ~0xFul) + 8;
+	regs->tf_rdi = stack;		/* argv */
+	regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T);
+	regs->tf_ss = _udatasel;
+	regs->tf_cs = _ucodesel;
+
+	/*
+	 * 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 == PCPU_GET(curpcb)) {
+			/*
+			 * 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;
+	}
+
+	/*
+	 * Drop the FP state if we hold it, so that the process gets a
+	 * clean FP state if it uses the FPU again.
+	 */
+	fpstate_drop(td);
+}
+
+void
+cpu_setregs(void)
+{
+	register_t cr0;
+
+	cr0 = rcr0();
+	/*
+	 * CR0_MP, CR0_NE and CR0_TS are also set by npx_probe() for the
+	 * BSP.  See the comments there about why we set them.
+	 */
+	cr0 |= CR0_MP | CR0_NE | CR0_TS | CR0_WP | CR0_AM;
+	load_cr0(cr0);
+}
+
+/*
+ * Initialize amd64 and configure to run kernel
+ */
+
+/*
+ * Initialize segments & interrupt table
+ */
+
+struct user_segment_descriptor gdt[NGDT * MAXCPU];/* global descriptor table */
+static struct gate_descriptor idt0[NIDT];
+struct gate_descriptor *idt = &idt0[0];	/* interrupt descriptor table */
+
+static char dblfault_stack[PAGE_SIZE] __aligned(16);
+
+struct amd64tss common_tss[MAXCPU];
+
+/* software prototypes -- in more palatable form */
+struct soft_segment_descriptor gdt_segs[] = {
+/* GNULL_SEL	0 Null Descriptor */
+{	0x0,			/* segment base address  */
+	0x0,			/* length */
+	0,			/* segment type */
+	0,			/* segment descriptor priority level */
+	0,			/* segment descriptor present */
+	0,			/* long */
+	0,			/* default 32 vs 16 bit size */
+	0  			/* limit granularity (byte/page units)*/ },
+/* GCODE_SEL	1 Code Descriptor for kernel */
+{	0x0,			/* segment base address  */
+	0xfffff,		/* length - all address space */
+	SDT_MEMERA,		/* segment type */
+	SEL_KPL,		/* segment descriptor priority level */
+	1,			/* segment descriptor present */
+	1,			/* long */
+	0,			/* default 32 vs 16 bit size */
+	1  			/* limit granularity (byte/page units)*/ },
+/* GDATA_SEL	2 Data Descriptor for kernel */
+{	0x0,			/* segment base address  */
+	0xfffff,		/* length - all address space */
+	SDT_MEMRWA,		/* segment type */
+	SEL_KPL,		/* segment descriptor priority level */
+	1,			/* segment descriptor present */
+	1,			/* long */
+	0,			/* default 32 vs 16 bit size */
+	1  			/* limit granularity (byte/page units)*/ },
+/* GUCODE32_SEL	3 32 bit Code Descriptor for user */
+{	0x0,			/* segment base address  */
+	0xfffff,		/* length - all address space */
+	SDT_MEMERA,		/* segment type */
+	SEL_UPL,		/* segment descriptor priority level */
+	1,			/* segment descriptor present */
+	0,			/* long */
+	1,			/* default 32 vs 16 bit size */
+	1  			/* limit granularity (byte/page units)*/ },
+/* GUDATA_SEL	4 32/64 bit Data Descriptor for user */
+{	0x0,			/* segment base address  */
+	0xfffff,		/* length - all address space */
+	SDT_MEMRWA,		/* segment type */
+	SEL_UPL,		/* segment descriptor priority level */
+	1,			/* segment descriptor present */
+	0,			/* long */
+	1,			/* default 32 vs 16 bit size */
+	1  			/* limit granularity (byte/page units)*/ },
+/* GUCODE_SEL	5 64 bit Code Descriptor for user */
+{	0x0,			/* segment base address  */
+	0xfffff,		/* length - all address space */
+	SDT_MEMERA,		/* segment type */
+	SEL_UPL,		/* segment descriptor priority level */
+	1,			/* segment descriptor present */
+	1,			/* long */
+	0,			/* default 32 vs 16 bit size */
+	1  			/* limit granularity (byte/page units)*/ },
+/* GPROC0_SEL	6 Proc 0 Tss Descriptor */
+{
+	0x0,			/* segment base address */
+	sizeof(struct amd64tss)-1,/* length - all address space */
+	SDT_SYSTSS,		/* segment type */
+	SEL_KPL,		/* segment descriptor priority level */
+	1,			/* segment descriptor present */
+	0,			/* long */
+	0,			/* unused - default 32 vs 16 bit size */
+	0  			/* limit granularity (byte/page units)*/ },
+/* Actually, the TSS is a system descriptor which is double size */
+{	0x0,			/* segment base address  */
+	0x0,			/* length */
+	0,			/* segment type */
+	0,			/* segment descriptor priority level */
+	0,			/* segment descriptor present */
+	0,			/* long */
+	0,			/* default 32 vs 16 bit size */
+	0  			/* limit granularity (byte/page units)*/ },
+/* GUGS32_SEL	8 32 bit GS Descriptor for user */
+{	0x0,			/* segment base address  */
+	0xfffff,		/* length - all address space */
+	SDT_MEMRWA,		/* segment type */
+	SEL_UPL,		/* segment descriptor priority level */
+	1,			/* segment descriptor present */
+	0,			/* long */
+	1,			/* default 32 vs 16 bit size */
+	1  			/* limit granularity (byte/page units)*/ },
+};
+
+void
+setidt(idx, func, typ, dpl, ist)
+	int idx;
+	inthand_t *func;
+	int typ;
+	int dpl;
+	int ist;
+{
+	struct gate_descriptor *ip;
+
+	ip = idt + idx;
+	ip->gd_looffset = (uintptr_t)func;
+	ip->gd_selector = GSEL(GCODE_SEL, SEL_KPL);
+	ip->gd_ist = ist;
+	ip->gd_xx = 0;
+	ip->gd_type = typ;
+	ip->gd_dpl = dpl;
+	ip->gd_p = 1;
+	ip->gd_hioffset = ((uintptr_t)func)>>16 ;
+}
+
+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(rsvd), IDTVEC(fpu), IDTVEC(align),
+	IDTVEC(xmm), IDTVEC(dblfault),
+	IDTVEC(fast_syscall), IDTVEC(fast_syscall32);
+
+void
+sdtossd(sd, ssd)
+	struct user_segment_descriptor *sd;
+	struct soft_segment_descriptor *ssd;
+{
+
+	ssd->ssd_base  = (sd->sd_hibase << 24) | sd->sd_lobase;
+	ssd->ssd_limit = (sd->sd_hilimit << 16) | sd->sd_lolimit;
+	ssd->ssd_type  = sd->sd_type;
+	ssd->ssd_dpl   = sd->sd_dpl;
+	ssd->ssd_p     = sd->sd_p;
+	ssd->ssd_long  = sd->sd_long;
+	ssd->ssd_def32 = sd->sd_def32;
+	ssd->ssd_gran  = sd->sd_gran;
+}
+
+void
+ssdtosd(ssd, sd)
+	struct soft_segment_descriptor *ssd;
+	struct user_segment_descriptor *sd;
+{
+
+	sd->sd_lobase = (ssd->ssd_base) & 0xffffff;
+	sd->sd_hibase = (ssd->ssd_base >> 24) & 0xff;
+	sd->sd_lolimit = (ssd->ssd_limit) & 0xffff;
+	sd->sd_hilimit = (ssd->ssd_limit >> 16) & 0xf;
+	sd->sd_type  = ssd->ssd_type;
+	sd->sd_dpl   = ssd->ssd_dpl;
+	sd->sd_p     = ssd->ssd_p;
+	sd->sd_long  = ssd->ssd_long;
+	sd->sd_def32 = ssd->ssd_def32;
+	sd->sd_gran  = ssd->ssd_gran;
+}
+
+void
+ssdtosyssd(ssd, sd)
+	struct soft_segment_descriptor *ssd;
+	struct system_segment_descriptor *sd;
+{
+
+	sd->sd_lobase = (ssd->ssd_base) & 0xffffff;
+	sd->sd_hibase = (ssd->ssd_base >> 24) & 0xfffffffffful;
+	sd->sd_lolimit = (ssd->ssd_limit) & 0xffff;
+	sd->sd_hilimit = (ssd->ssd_limit >> 16) & 0xf;
+	sd->sd_type  = ssd->ssd_type;
+	sd->sd_dpl   = ssd->ssd_dpl;
+	sd->sd_p     = ssd->ssd_p;
+	sd->sd_gran  = ssd->ssd_gran;
+}
+
+#if !defined(DEV_ATPIC) && defined(DEV_ISA)
+#include <isa/isavar.h>
+u_int
+isa_irq_pending(void)
+{
+
+	return (0);
+}
+#endif
+
+u_int basemem;
+
+/*
+ * Populate the (physmap) array with base/bound pairs describing the
+ * available physical memory in the system, then test this memory and
+ * build the phys_avail array describing the actually-available memory.
+ *
+ * If we cannot accurately determine the physical memory map, then use
+ * value from the 0xE801 call, and failing that, the RTC.
+ *
+ * Total memory size may be set by the kernel environment variable
+ * hw.physmem or the compile-time define MAXMEM.
+ *
+ * XXX first should be vm_paddr_t.
+ */
+static void
+getmemsize(caddr_t kmdp, u_int64_t first)
+{
+	int i, off, physmap_idx, pa_indx, da_indx;
+	vm_paddr_t pa, physmap[PHYSMAP_SIZE];
+	u_long physmem_tunable;
+	pt_entry_t *pte;
+	struct bios_smap *smapbase, *smap, *smapend;
+	u_int32_t smapsize;
+	quad_t dcons_addr, dcons_size;
+
+	bzero(physmap, sizeof(physmap));
+	basemem = 0;
+	physmap_idx = 0;
+
+	/*
+	 * get memory map from INT 15:E820, kindly supplied by the loader.
+	 *
+	 * subr_module.c says:
+	 * "Consumer may safely assume that size value precedes data."
+	 * ie: an int32_t immediately precedes smap.
+	 */
+	smapbase = (struct bios_smap *)preload_search_info(kmdp,
+	    MODINFO_METADATA | MODINFOMD_SMAP);
+	if (smapbase == NULL)
+		panic("No BIOS smap info from loader!");
+
+	smapsize = *((u_int32_t *)smapbase - 1);
+	smapend = (struct bios_smap *)((uintptr_t)smapbase + smapsize);
+
+	for (smap = smapbase; smap < smapend; smap++) {
+		if (boothowto & RB_VERBOSE)
+			printf("SMAP type=%02x base=%016lx len=%016lx\n",
+			    smap->type, smap->base, smap->length);
+
+		if (smap->type != 0x01)
+			continue;
+
+		if (smap->length == 0)
+			continue;
+
+		for (i = 0; i <= physmap_idx; i += 2) {
+			if (smap->base < physmap[i + 1]) {
+				if (boothowto & RB_VERBOSE)
+					printf(
+	"Overlapping or non-monotonic memory region, ignoring second region\n");
+				continue;
+			}
+		}
+
+		if (smap->base == physmap[physmap_idx + 1]) {
+			physmap[physmap_idx + 1] += smap->length;
+			continue;
+		}
+
+		physmap_idx += 2;
+		if (physmap_idx == PHYSMAP_SIZE) {
+			printf(
+		"Too many segments in the physical address map, giving up\n");
+			break;
+		}
+		physmap[physmap_idx] = smap->base;
+		physmap[physmap_idx + 1] = smap->base + smap->length;
+	}
+
+	/*
+	 * Find the 'base memory' segment for SMP
+	 */
+	basemem = 0;
+	for (i = 0; i <= physmap_idx; i += 2) {
+		if (physmap[i] == 0x00000000) {
+			basemem = physmap[i + 1] / 1024;
+			break;
+		}
+	}
+	if (basemem == 0)
+		panic("BIOS smap did not include a basemem segment!");
+
+#ifdef SMP
+	/* make hole for AP bootstrap code */
+	physmap[1] = mp_bootaddress(physmap[1] / 1024);
+#endif
+
+	/*
+	 * Maxmem isn't the "maximum memory", it's one larger than the
+	 * highest page of the physical address space.  It should be
+	 * called something like "Maxphyspage".  We may adjust this
+	 * based on ``hw.physmem'' and the results of the memory test.
+	 */
+	Maxmem = atop(physmap[physmap_idx + 1]);
+
+#ifdef MAXMEM
+	Maxmem = MAXMEM / 4;
+#endif
+
+	if (TUNABLE_ULONG_FETCH("hw.physmem", &physmem_tunable))
+		Maxmem = atop(physmem_tunable);
+
+	/*
+	 * Don't allow MAXMEM or hw.physmem to extend the amount of memory
+	 * in the system.
+	 */
+	if (Maxmem > atop(physmap[physmap_idx + 1]))
+		Maxmem = atop(physmap[physmap_idx + 1]);
+
+	if (atop(physmap[physmap_idx + 1]) != Maxmem &&
+	    (boothowto & RB_VERBOSE))
+		printf("Physical memory use set to %ldK\n", Maxmem * 4);
+
+	/* call pmap initialization to make new kernel address space */
+	pmap_bootstrap(&first);
+
+	/*
+	 * Size up each available chunk of physical memory.
+	 */
+	physmap[0] = PAGE_SIZE;		/* mask off page 0 */
+	pa_indx = 0;
+	da_indx = 1;
+	phys_avail[pa_indx++] = physmap[0];
+	phys_avail[pa_indx] = physmap[0];
+	dump_avail[da_indx] = physmap[0];
+	pte = CMAP1;
+
+	/*
+	 * Get dcons buffer address
+	 */
+	if (getenv_quad("dcons.addr", &dcons_addr) == 0 ||
+	    getenv_quad("dcons.size", &dcons_size) == 0)
+		dcons_addr = 0;
+
+	/*
+	 * physmap is in bytes, so when converting to page boundaries,
+	 * round up the start address and round down the end address.
+	 */
+	for (i = 0; i <= physmap_idx; i += 2) {
+		vm_paddr_t end;
+
+		end = ptoa((vm_paddr_t)Maxmem);
+		if (physmap[i + 1] < end)
+			end = trunc_page(physmap[i + 1]);
+		for (pa = round_page(physmap[i]); pa < end; pa += PAGE_SIZE) {
+			int tmp, page_bad, full;
+			int *ptr = (int *)CADDR1;
+
+			full = FALSE;
+			/*
+			 * block out kernel memory as not available.
+			 */
+			if (pa >= 0x100000 && pa < first)
+				goto do_dump_avail;
+
+			/*
+			 * block out dcons buffer
+			 */
+			if (dcons_addr > 0
+			    && pa >= trunc_page(dcons_addr)
+			    && pa < dcons_addr + dcons_size)
+				goto do_dump_avail;
+
+			page_bad = FALSE;
+
+			/*
+			 * map page into kernel: valid, read/write,non-cacheable
+			 */
+			*pte = pa | PG_V | PG_RW | PG_N;
+			invltlb();
+
+			tmp = *(int *)ptr;
+			/*
+			 * Test for alternating 1's and 0's
+			 */
+			*(volatile int *)ptr = 0xaaaaaaaa;
+			if (*(volatile int *)ptr != 0xaaaaaaaa)
+				page_bad = TRUE;
+			/*
+			 * Test for alternating 0's and 1's
+			 */
+			*(volatile int *)ptr = 0x55555555;
+			if (*(volatile int *)ptr != 0x55555555)
+				page_bad = TRUE;
+			/*
+			 * Test for all 1's
+			 */
+			*(volatile int *)ptr = 0xffffffff;
+			if (*(volatile int *)ptr != 0xffffffff)
+				page_bad = TRUE;
+			/*
+			 * Test for all 0's
+			 */
+			*(volatile int *)ptr = 0x0;
+			if (*(volatile int *)ptr != 0x0)
+				page_bad = TRUE;
+			/*
+			 * Restore original value.
+			 */
+			*(int *)ptr = tmp;
+
+			/*
+			 * Adjust array of valid/good pages.
+			 */
+			if (page_bad == TRUE)
+				continue;
+			/*
+			 * If this good page is a continuation of the
+			 * previous set of good pages, then just increase
+			 * the end pointer. Otherwise start a new chunk.
+			 * Note that "end" points one higher than end,
+			 * making the range >= start and < end.
+			 * If we're also doing a speculative memory
+			 * test and we at or past the end, bump up Maxmem
+			 * so that we keep going. The first bad page
+			 * will terminate the loop.
+			 */
+			if (phys_avail[pa_indx] == pa) {
+				phys_avail[pa_indx] += PAGE_SIZE;
+			} else {
+				pa_indx++;
+				if (pa_indx == PHYS_AVAIL_ARRAY_END) {
+					printf(
+		"Too many holes in the physical address space, giving up\n");
+					pa_indx--;
+					full = TRUE;
+					goto do_dump_avail;
+				}
+				phys_avail[pa_indx++] = pa;	/* start */
+				phys_avail[pa_indx] = pa + PAGE_SIZE; /* end */
+			}
+			physmem++;
+do_dump_avail:
+			if (dump_avail[da_indx] == pa) {
+				dump_avail[da_indx] += PAGE_SIZE;
+			} else {
+				da_indx++;
+				if (da_indx == DUMP_AVAIL_ARRAY_END) {
+					da_indx--;
+					goto do_next;
+				}
+				dump_avail[da_indx++] = pa; /* start */
+				dump_avail[da_indx] = pa + PAGE_SIZE; /* end */
+			}
+do_next:
+			if (full)
+				break;
+		}
+	}
+	*pte = 0;
+	invltlb();
+
+	/*
+	 * XXX
+	 * The last chunk must contain at least one page plus the message
+	 * buffer to avoid complicating other code (message buffer address
+	 * calculation, etc.).
+	 */
+	while (phys_avail[pa_indx - 1] + PAGE_SIZE +
+	    round_page(MSGBUF_SIZE) >= phys_avail[pa_indx]) {
+		physmem -= atop(phys_avail[pa_indx] - phys_avail[pa_indx - 1]);
+		phys_avail[pa_indx--] = 0;
+		phys_avail[pa_indx--] = 0;
+	}
+
+	Maxmem = atop(phys_avail[pa_indx]);
+
+	/* Trim off space for the message buffer. */
+	phys_avail[pa_indx] -= round_page(MSGBUF_SIZE);
+
+	/* Map the message buffer. */
+	for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE)
+		pmap_kenter((vm_offset_t)msgbufp + off, phys_avail[pa_indx] +
+		    off);
+}
+
+u_int64_t
+hammer_time(u_int64_t modulep, u_int64_t physfree)
+{
+	struct mdglobaldata *gd;
+
+	/*
+	 * Prevent lowering of the ipl if we call tsleep() early.
+	 */
+	gd = &CPU_prvspace[0].mdglobaldata;
+	bzero(gd, sizeof(*gd));
+
+	gd->mi.gd_curthread = &thread0;
+	thread0.td_gd = &gd->mi;
+
+	preload_metadata = (caddr_t)(uintptr_t)(modulep + KERNBASE);
+	preload_bootstrap_relocate(KERNBASE);
+	kmdp = preload_search_by_type("elf kernel");
+	if (kmdp == NULL)
+		kmdp = preload_search_by_type("elf64 kernel");
+	boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
+	kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *) + KERNBASE;
+#ifdef DDB
+	ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
+	ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
+#endif
+
+	/*
+	 * start with one cpu.  Note: with one cpu, ncpus2_shift, ncpus2_mask,
+ 	 * and ncpus_fit_mask remain 0.
+	 */
+	ncpus = 1;
+	ncpus2 = 1;
+	ncpus_fit = 1;
+
+	/* Init basic tunables, hz etc */
+	init_param1();
+
+	/*
+	 * make gdt memory segments
+	 */
+	gdt_segs[GPROC0_SEL].ssd_base = (uintptr_t)&common_tss[0];
+
+	for (x = 0; x < NGDT; x++) {
+		if (x != GPROC0_SEL && x != (GPROC0_SEL + 1))
+			ssdtosd(&gdt_segs[x], &gdt[x]);
+	}
+	ssdtosyssd(&gdt_segs[GPROC0_SEL],
+	    (struct system_segment_descriptor *)&gdt[GPROC0_SEL]);
+
+	r_gdt.rd_limit = NGDT * sizeof(gdt[0]) - 1;
+	r_gdt.rd_base =  (long) gdt;
+	lgdt(&r_gdt);
+
+	wrmsr(MSR_FSBASE, 0);		/* User value */
+	wrmsr(MSR_GSBASE, (u_int64_t)pc);
+	wrmsr(MSR_KGSBASE, 0);		/* User value while in the kernel */
+
+	gd->mi.gd_prvspace = &CPU_prvspace[0];
+
+	mi_gdinit(&gd->mi, 0);
+	cpu_gdinit(gd, 0);
+	mi_proc0init(&gd->mi, proc0paddr);
+	safepri = TDPRI_MAX;
+
+	/* spinlocks and the BGL */
+	init_locks();
+	
+	/* exceptions */
+	for (x = 0; x < NIDT; x++)
+		setidt(x, &IDTVEC(rsvd), SDT_SYSIGT, SEL_KPL, 0);
+	setidt(IDT_DE, &IDTVEC(div),  SDT_SYSIGT, SEL_KPL, 0);
+	setidt(IDT_DB, &IDTVEC(dbg),  SDT_SYSIGT, SEL_KPL, 0);
+	setidt(IDT_NMI, &IDTVEC(nmi),  SDT_SYSIGT, SEL_KPL, 1);
+ 	setidt(IDT_BP, &IDTVEC(bpt),  SDT_SYSIGT, SEL_UPL, 0);
+	setidt(IDT_OF, &IDTVEC(ofl),  SDT_SYSIGT, SEL_KPL, 0);
+	setidt(IDT_BR, &IDTVEC(bnd),  SDT_SYSIGT, SEL_KPL, 0);
+	setidt(IDT_UD, &IDTVEC(ill),  SDT_SYSIGT, SEL_KPL, 0);
+	setidt(IDT_NM, &IDTVEC(dna),  SDT_SYSIGT, SEL_KPL, 0);
+	setidt(IDT_DF, &IDTVEC(dblfault), SDT_SYSIGT, SEL_KPL, 1);
+	setidt(IDT_FPUGP, &IDTVEC(fpusegm),  SDT_SYSIGT, SEL_KPL, 0);
+	setidt(IDT_TS, &IDTVEC(tss),  SDT_SYSIGT, SEL_KPL, 0);
+	setidt(IDT_NP, &IDTVEC(missing),  SDT_SYSIGT, SEL_KPL, 0);
+	setidt(IDT_SS, &IDTVEC(stk),  SDT_SYSIGT, SEL_KPL, 0);
+	setidt(IDT_GP, &IDTVEC(prot),  SDT_SYSIGT, SEL_KPL, 0);
+	setidt(IDT_PF, &IDTVEC(page),  SDT_SYSIGT, SEL_KPL, 0);
+	setidt(IDT_MF, &IDTVEC(fpu),  SDT_SYSIGT, SEL_KPL, 0);
+	setidt(IDT_AC, &IDTVEC(align), SDT_SYSIGT, SEL_KPL, 0);
+	setidt(IDT_MC, &IDTVEC(mchk),  SDT_SYSIGT, SEL_KPL, 0);
+	setidt(IDT_XF, &IDTVEC(xmm), SDT_SYSIGT, SEL_KPL, 0);
+
+	r_idt.rd_limit = sizeof(idt0) - 1;
+	r_idt.rd_base = (long) idt;
+	lidt(&r_idt);
+
+	/*
+	 * Initialize the i8254 before the console so that console
+	 * initialization can use DELAY().
+	 */
+	i8254_init();
+
+	/*
+	 * Initialize the console before we print anything out.
+	 */
+	cninit();
+
+#ifdef DEV_ISA
+#ifdef DEV_ATPIC
+	elcr_probe();
+	atpic_startup();
+#else
+	/* Reset and mask the atpics and leave them shut down. */
+	atpic_reset();
+
+	/*
+	 * Point the ICU spurious interrupt vectors at the APIC spurious
+	 * interrupt handler.
+	 */
+	setidt(IDT_IO_INTS + 7, IDTVEC(spuriousint), SDT_SYSIGT, SEL_KPL, 0);
+	setidt(IDT_IO_INTS + 15, IDTVEC(spuriousint), SDT_SYSIGT, SEL_KPL, 0);
+#endif
+#else
+#error "have you forgotten the isa device?";
+#endif
+
+	kdb_init();
+
+#ifdef KDB
+	if (boothowto & RB_KDB)
+		kdb_enter("Boot flags requested debugger");
+#endif
+
+	identify_cpu();		/* Final stage of CPU initialization */
+	initializecpu();	/* Initialize CPU registers */
+
+	/* make an initial tss so cpu can get interrupt stack on syscall! */
+	common_tss[0].tss_rsp0 = thread0.td_kstack + \
+	    KSTACK_PAGES * PAGE_SIZE - sizeof(struct pcb);
+	/* Ensure the stack is aligned to 16 bytes */
+	common_tss[0].tss_rsp0 &= ~0xFul;
+	PCPU_SET(rsp0, common_tss[0].tss_rsp0);
+
+	/* doublefault stack space, runs on ist1 */
+	common_tss[0].tss_ist1 = (long)&dblfault_stack[sizeof(dblfault_stack)];
+
+	/* Set the IO permission bitmap (empty due to tss seg limit) */
+	common_tss[0].tss_iobase = sizeof(struct amd64tss);
+
+	gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
+	ltr(gsel_tss);
+
+	/* Set up the fast syscall stuff */
+	msr = rdmsr(MSR_EFER) | EFER_SCE;
+	wrmsr(MSR_EFER, msr);
+	wrmsr(MSR_LSTAR, (u_int64_t)IDTVEC(fast_syscall));
+	wrmsr(MSR_CSTAR, (u_int64_t)IDTVEC(fast_syscall32));
+	msr = ((u_int64_t)GSEL(GCODE_SEL, SEL_KPL) << 32) |
+	      ((u_int64_t)GSEL(GUCODE32_SEL, SEL_UPL) << 48);
+	wrmsr(MSR_STAR, msr);
+	wrmsr(MSR_SF_MASK, PSL_NT|PSL_T|PSL_I|PSL_C|PSL_D);
+
+	getmemsize(kmdp, physfree);
+	init_param2(physmem);
+
+	/* now running on new page tables, configured,and u/iom is accessible */
+
+	msgbufinit(msgbufp, MSGBUF_SIZE);
+	fpuinit();
+
+	/* transfer to user mode */
+
+	_ucodesel = GSEL(GUCODE_SEL, SEL_UPL);
+	_udatasel = GSEL(GUDATA_SEL, SEL_UPL);
+	_ucode32sel = GSEL(GUCODE32_SEL, SEL_UPL);
+
+	/* setup proc 0's pcb */
+	thread0.td_pcb->pcb_flags = 0; /* XXXKSE */
+	thread0.td_pcb->pcb_cr3 = KPML4phys;
+	thread0.td_frame = &proc0_tf;
+
+        env = getenv("kernelname");
+	if (env != NULL)
+		strlcpy(kernelname, env, sizeof(kernelname));
+
+	/* Location of kernel stack for locore */
+	return ((u_int64_t)thread0.td_pcb);
+}
+
+void
+cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
+{
+
+	pcpu->pc_acpi_id = 0xffffffff;
+}
+
+void
+spinlock_enter(void)
+{
+	struct thread *td;
+
+	td = curthread;
+	if (td->td_md.md_spinlock_count == 0)
+		td->td_md.md_saved_flags = intr_disable();
+	td->td_md.md_spinlock_count++;
+	critical_enter();
+}
+
+void
+spinlock_exit(void)
+{
+	struct thread *td;
+
+	td = curthread;
+	critical_exit();
+	td->td_md.md_spinlock_count--;
+	if (td->td_md.md_spinlock_count == 0)
+		intr_restore(td->td_md.md_saved_flags);
+}
+
+/*
+ * Construct a PCB from a trapframe. This is called from kdb_trap() where
+ * we want to start a backtrace from the function that caused us to enter
+ * the debugger. We have the context in the trapframe, but base the trace
+ * on the PCB. The PCB doesn't have to be perfect, as long as it contains
+ * enough for a backtrace.
+ */
+void
+makectx(struct trapframe *tf, struct pcb *pcb)
+{
+
+	pcb->pcb_r12 = tf->tf_r12;
+	pcb->pcb_r13 = tf->tf_r13;
+	pcb->pcb_r14 = tf->tf_r14;
+	pcb->pcb_r15 = tf->tf_r15;
+	pcb->pcb_rbp = tf->tf_rbp;
+	pcb->pcb_rbx = tf->tf_rbx;
+	pcb->pcb_rip = tf->tf_rip;
+	pcb->pcb_rsp = (ISPL(tf->tf_cs)) ? tf->tf_rsp : (long)(tf + 1) - 8;
+}
+
+int
+ptrace_set_pc(struct thread *td, unsigned long addr)
+{
+	td->td_frame->tf_rip = addr;
+	return (0);
+}
+
+int
+ptrace_single_step(struct thread *td)
+{
+	td->td_frame->tf_rflags |= PSL_T;
+	return (0);
+}
+
+int
+ptrace_clear_single_step(struct thread *td)
+{
+	td->td_frame->tf_rflags &= ~PSL_T;
+	return (0);
+}
+
+int
+fill_regs(struct thread *td, struct reg *regs)
+{
+	struct trapframe *tp;
+
+	tp = td->td_frame;
+	regs->r_r15 = tp->tf_r15;
+	regs->r_r14 = tp->tf_r14;
+	regs->r_r13 = tp->tf_r13;
+	regs->r_r12 = tp->tf_r12;
+	regs->r_r11 = tp->tf_r11;
+	regs->r_r10 = tp->tf_r10;
+	regs->r_r9  = tp->tf_r9;
+	regs->r_r8  = tp->tf_r8;
+	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 thread *td, struct reg *regs)
+{
+	struct trapframe *tp;
+	register_t rflags;
+
+	tp = td->td_frame;
+	rflags = regs->r_rflags & 0xffffffff;
+	if (!EFL_SECURE(rflags, tp->tf_rflags) || !CS_SECURE(regs->r_cs))
+		return (EINVAL);
+	tp->tf_r15 = regs->r_r15;
+	tp->tf_r14 = regs->r_r14;
+	tp->tf_r13 = regs->r_r13;
+	tp->tf_r12 = regs->r_r12;
+	tp->tf_r11 = regs->r_r11;
+	tp->tf_r10 = regs->r_r10;
+	tp->tf_r9  = regs->r_r9;
+	tp->tf_r8  = regs->r_r8;
+	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 = rflags;
+	tp->tf_rsp = regs->r_rsp;
+	tp->tf_ss = regs->r_ss;
+	td->td_pcb->pcb_flags |= PCB_FULLCTX;
+	return (0);
+}
+
+/* XXX check all this stuff! */
+/* externalize from sv_xmm */
+static void
+fill_fpregs_xmm(struct savefpu *sv_xmm, struct fpreg *fpregs)
+{
+	struct envxmm *penv_fpreg = (struct envxmm *)&fpregs->fpr_env;
+	struct envxmm *penv_xmm = &sv_xmm->sv_env;
+	int i;
+
+	/* pcb -> fpregs */
+	bzero(fpregs, sizeof(*fpregs));
+
+	/* FPU control/status */
+	penv_fpreg->en_cw = penv_xmm->en_cw;
+	penv_fpreg->en_sw = penv_xmm->en_sw;
+	penv_fpreg->en_tw = penv_xmm->en_tw;
+	penv_fpreg->en_opcode = penv_xmm->en_opcode;
+	penv_fpreg->en_rip = penv_xmm->en_rip;
+	penv_fpreg->en_rdp = penv_xmm->en_rdp;
+	penv_fpreg->en_mxcsr = penv_xmm->en_mxcsr;
+	penv_fpreg->en_mxcsr_mask = penv_xmm->en_mxcsr_mask;
+
+	/* FPU registers */
+	for (i = 0; i < 8; ++i)
+		bcopy(sv_xmm->sv_fp[i].fp_acc.fp_bytes, fpregs->fpr_acc[i], 10);
+
+	/* SSE registers */
+	for (i = 0; i < 16; ++i)
+		bcopy(sv_xmm->sv_xmm[i].xmm_bytes, fpregs->fpr_xacc[i], 16);
+}
+
+/* internalize from fpregs into sv_xmm */
+static void
+set_fpregs_xmm(struct fpreg *fpregs, struct savefpu *sv_xmm)
+{
+	struct envxmm *penv_xmm = &sv_xmm->sv_env;
+	struct envxmm *penv_fpreg = (struct envxmm *)&fpregs->fpr_env;
+	int i;
+
+	/* fpregs -> pcb */
+	/* FPU control/status */
+	penv_xmm->en_cw = penv_fpreg->en_cw;
+	penv_xmm->en_sw = penv_fpreg->en_sw;
+	penv_xmm->en_tw = penv_fpreg->en_tw;
+	penv_xmm->en_opcode = penv_fpreg->en_opcode;
+	penv_xmm->en_rip = penv_fpreg->en_rip;
+	penv_xmm->en_rdp = penv_fpreg->en_rdp;
+	penv_xmm->en_mxcsr = penv_fpreg->en_mxcsr;
+	penv_xmm->en_mxcsr_mask = penv_fpreg->en_mxcsr_mask & cpu_mxcsr_mask;
+
+	/* FPU registers */
+	for (i = 0; i < 8; ++i)
+		bcopy(fpregs->fpr_acc[i], sv_xmm->sv_fp[i].fp_acc.fp_bytes, 10);
+
+	/* SSE registers */
+	for (i = 0; i < 16; ++i)
+		bcopy(fpregs->fpr_xacc[i], sv_xmm->sv_xmm[i].xmm_bytes, 16);
+}
+
+/* externalize from td->pcb */
+int
+fill_fpregs(struct thread *td, struct fpreg *fpregs)
+{
+
+	fill_fpregs_xmm(&td->td_pcb->pcb_save, fpregs);
+	return (0);
+}
+
+/* internalize to td->pcb */
+int
+set_fpregs(struct thread *td, struct fpreg *fpregs)
+{
+
+	set_fpregs_xmm(fpregs, &td->td_pcb->pcb_save);
+	return (0);
+}
+
+/*
+ * Get machine context.
+ */
+int
+get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
+{
+	struct trapframe *tp;
+
+	tp = td->td_frame;
+	PROC_LOCK(curthread->td_proc);
+	mcp->mc_onstack = sigonstack(tp->tf_rsp);
+	PROC_UNLOCK(curthread->td_proc);
+	mcp->mc_r15 = tp->tf_r15;
+	mcp->mc_r14 = tp->tf_r14;
+	mcp->mc_r13 = tp->tf_r13;
+	mcp->mc_r12 = tp->tf_r12;
+	mcp->mc_r11 = tp->tf_r11;
+	mcp->mc_r10 = tp->tf_r10;
+	mcp->mc_r9  = tp->tf_r9;
+	mcp->mc_r8  = tp->tf_r8;
+	mcp->mc_rdi = tp->tf_rdi;
+	mcp->mc_rsi = tp->tf_rsi;
+	mcp->mc_rbp = tp->tf_rbp;
+	mcp->mc_rbx = tp->tf_rbx;
+	mcp->mc_rcx = tp->tf_rcx;
+	mcp->mc_rflags = tp->tf_rflags;
+	if (flags & GET_MC_CLEAR_RET) {
+		mcp->mc_rax = 0;
+		mcp->mc_rdx = 0;
+		mcp->mc_rflags &= ~PSL_C;
+	} else {
+		mcp->mc_rax = tp->tf_rax;
+		mcp->mc_rdx = tp->tf_rdx;
+	}
+	mcp->mc_rip = tp->tf_rip;
+	mcp->mc_cs = tp->tf_cs;
+	mcp->mc_rsp = tp->tf_rsp;
+	mcp->mc_ss = tp->tf_ss;
+	mcp->mc_len = sizeof(*mcp);
+	get_fpcontext(td, mcp);
+	return (0);
+}
+
+/*
+ * Set machine context.
+ *
+ * However, we don't set any but the user modifiable flags, and we won't
+ * touch the cs selector.
+ */
+int
+set_mcontext(struct thread *td, const mcontext_t *mcp)
+{
+	struct trapframe *tp;
+	long rflags;
+	int ret;
+
+	tp = td->td_frame;
+	if (mcp->mc_len != sizeof(*mcp))
+		return (EINVAL);
+	rflags = (mcp->mc_rflags & PSL_USERCHANGE) |
+	    (tp->tf_rflags & ~PSL_USERCHANGE);
+	ret = set_fpcontext(td, mcp);
+	if (ret != 0)
+		return (ret);
+	tp->tf_r15 = mcp->mc_r15;
+	tp->tf_r14 = mcp->mc_r14;
+	tp->tf_r13 = mcp->mc_r13;
+	tp->tf_r12 = mcp->mc_r12;
+	tp->tf_r11 = mcp->mc_r11;
+	tp->tf_r10 = mcp->mc_r10;
+	tp->tf_r9  = mcp->mc_r9;
+	tp->tf_r8  = mcp->mc_r8;
+	tp->tf_rdi = mcp->mc_rdi;
+	tp->tf_rsi = mcp->mc_rsi;
+	tp->tf_rbp = mcp->mc_rbp;
+	tp->tf_rbx = mcp->mc_rbx;
+	tp->tf_rdx = mcp->mc_rdx;
+	tp->tf_rcx = mcp->mc_rcx;
+	tp->tf_rax = mcp->mc_rax;
+	tp->tf_rip = mcp->mc_rip;
+	tp->tf_rflags = rflags;
+	tp->tf_rsp = mcp->mc_rsp;
+	tp->tf_ss = mcp->mc_ss;
+	td->td_pcb->pcb_flags |= PCB_FULLCTX;
+	return (0);
+}
+
+static void
+get_fpcontext(struct thread *td, mcontext_t *mcp)
+{
+
+	mcp->mc_ownedfp = fpugetregs(td, (struct savefpu *)&mcp->mc_fpstate);
+	mcp->mc_fpformat = fpuformat();
+}
+
+static int
+set_fpcontext(struct thread *td, const mcontext_t *mcp)
+{
+	struct savefpu *fpstate;
+
+	if (mcp->mc_fpformat == _MC_FPFMT_NODEV)
+		return (0);
+	else if (mcp->mc_fpformat != _MC_FPFMT_XMM)
+		return (EINVAL);
+	else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE)
+		/* We don't care what state is left in the FPU or PCB. */
+		fpstate_drop(td);
+	else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
+	    mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
+		/*
+		 * XXX we violate the dubious requirement that fpusetregs()
+		 * be called with interrupts disabled.
+		 * XXX obsolete on trap-16 systems?
+		 */
+		fpstate = (struct savefpu *)&mcp->mc_fpstate;
+		fpstate->sv_env.en_mxcsr &= cpu_mxcsr_mask;
+		fpusetregs(td, fpstate);
+	} else
+		return (EINVAL);
+	return (0);
+}
+
+void
+fpstate_drop(struct thread *td)
+{
+	register_t s;
+
+	s = intr_disable();
+	if (PCPU_GET(fpcurthread) == td)
+		fpudrop();
+	/*
+	 * XXX force a full drop of the fpu.  The above only drops it if we
+	 * owned it.
+	 *
+	 * XXX I don't much like fpugetregs()'s semantics of doing a full
+	 * drop.  Dropping only to the pcb matches fnsave's behaviour.
+	 * We only need to drop to !PCB_INITDONE in sendsig().  But
+	 * sendsig() is the only caller of fpugetregs()... perhaps we just
+	 * have too many layers.
+	 */
+	curthread->td_pcb->pcb_flags &= ~PCB_FPUINITDONE;
+	intr_restore(s);
+}
+
+int
+fill_dbregs(struct thread *td, struct dbreg *dbregs)
+{
+	struct pcb *pcb;
+
+	if (td == NULL) {
+		dbregs->dr[0] = rdr0();
+		dbregs->dr[1] = rdr1();
+		dbregs->dr[2] = rdr2();
+		dbregs->dr[3] = rdr3();
+		dbregs->dr[6] = rdr6();
+		dbregs->dr[7] = rdr7();
+	} else {
+		pcb = td->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[6] = pcb->pcb_dr6;
+		dbregs->dr[7] = pcb->pcb_dr7;
+	}
+	dbregs->dr[4] = 0;
+	dbregs->dr[5] = 0;
+	dbregs->dr[8] = 0;
+	dbregs->dr[9] = 0;
+	dbregs->dr[10] = 0;
+	dbregs->dr[11] = 0;
+	dbregs->dr[12] = 0;
+	dbregs->dr[13] = 0;
+	dbregs->dr[14] = 0;
+	dbregs->dr[15] = 0;
+	return (0);
+}
+
+int
+set_dbregs(struct thread *td, struct dbreg *dbregs)
+{
+	struct pcb *pcb;
+	int i;
+
+	if (td == NULL) {
+		load_dr0(dbregs->dr[0]);
+		load_dr1(dbregs->dr[1]);
+		load_dr2(dbregs->dr[2]);
+		load_dr3(dbregs->dr[3]);
+		load_dr6(dbregs->dr[6]);
+		load_dr7(dbregs->dr[7]);
+	} else {
+		/*
+		 * 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 or a general protection fault right here.
+		 * Upper bits of dr6 and dr7 must not be set
+		 */
+		for (i = 0; i < 4; i++) {
+			if (DBREG_DR7_ACCESS(dbregs->dr[7], i) == 0x02)
+				return (EINVAL);
+			if (td->td_frame->tf_cs == _ucode32sel &&
+			    DBREG_DR7_LEN(dbregs->dr[7], i) == DBREG_DR7_LEN_8)
+				return (EINVAL);
+		}
+		if ((dbregs->dr[6] & 0xffffffff00000000ul) != 0 ||
+		    (dbregs->dr[7] & 0xffffffff00000000ul) != 0)
+			return (EINVAL);
+
+		pcb = td->td_pcb;
+
+		/*
+		 * 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.
+		 *
+		 * 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 (DBREG_DR7_ENABLED(dbregs->dr[7], 0)) {
+			/* dr0 is enabled */
+			if (dbregs->dr[0] >= VM_MAXUSER_ADDRESS)
+				return (EINVAL);
+		}
+		if (DBREG_DR7_ENABLED(dbregs->dr[7], 1)) {
+			/* dr1 is enabled */
+			if (dbregs->dr[1] >= VM_MAXUSER_ADDRESS)
+				return (EINVAL);
+		}
+		if (DBREG_DR7_ENABLED(dbregs->dr[7], 2)) {
+			/* dr2 is enabled */
+			if (dbregs->dr[2] >= VM_MAXUSER_ADDRESS)
+				return (EINVAL);
+		}
+		if (DBREG_DR7_ENABLED(dbregs->dr[7], 3)) {
+			/* dr3 is enabled */
+			if (dbregs->dr[3] >= VM_MAXUSER_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);
+}
+
+void
+reset_dbregs(void)
+{
+
+	load_dr7(0);	/* Turn off the control bits first */
+	load_dr0(0);
+	load_dr1(0);
+	load_dr2(0);
+	load_dr3(0);
+	load_dr6(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_int64_t dr7, dr6; /* debug registers dr6 and dr7 */
+        u_int64_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_MAXUSER_ADDRESS) {
+                        /*
+                         * addr[i] is in user space
+                         */
+                        return nbp;
+                }
+        }
+
+        /*
+         * None of the breakpoints are in user space.
+         */
+        return 0;
+}
+
+#ifdef KDB
+
+/*
+ * Provide inb() and outb() as functions.  They are normally only
+ * available as macros calling inlined functions, thus cannot be
+ * called from the debugger.
+ *
+ * The actual code is stolen from <machine/cpufunc.h>, and de-inlined.
+ */
+
+#undef inb
+#undef outb
+
+/* silence compiler warnings */
+u_char inb(u_int);
+void outb(u_int, u_char);
+
+u_char
+inb(u_int port)
+{
+	u_char	data;
+	/*
+	 * We use %%dx and not %1 here because i/o is done at %dx and not at
+	 * %edx, while gcc generates inferior code (movw instead of movl)
+	 * if we tell it to load (u_short) port.
+	 */
+	__asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
+	return (data);
+}
+
+void
+outb(u_int port, u_char data)
+{
+	u_char	al;
+	/*
+	 * Use an unnecessary assignment to help gcc's register allocator.
+	 * This make a large difference for gcc-1.40 and a tiny difference
+	 * for gcc-2.6.0.  For gcc-1.40, al had to be ``asm("ax")'' for
+	 * best results.  gcc-2.6.0 can't handle this.
+	 */
+	al = data;
+	__asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
+}
+
+
+
+
+
+
+
+
+
+
+/*
+ * Initialize machine-dependant portions of the global data structure.
+ * Note that the global data area and cpu0's idlestack in the private
+ * data space were allocated in locore.
+ *
+ * Note: the idlethread's cpl is 0
+ *
+ * WARNING!  Called from early boot, 'mycpu' may not work yet.
+ */
+void
+cpu_gdinit(struct mdglobaldata *gd, int cpu)
+{
+	if (cpu)
+		gd->mi.gd_curthread = &gd->mi.gd_idlethread;
+
+	lwkt_init_thread(&gd->mi.gd_idlethread,
+			gd->mi.gd_prvspace->idlestack,
+			sizeof(gd->mi.gd_prvspace->idlestack),
+			TDF_MPSAFE, &gd->mi);
+	lwkt_set_comm(&gd->mi.gd_idlethread, "idle_%d", cpu);
+	gd->mi.gd_idlethread.td_switch = cpu_lwkt_switch;
+	gd->mi.gd_idlethread.td_sp -= sizeof(void *);
+	*(void **)gd->mi.gd_idlethread.td_sp = cpu_idle_restore;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif /* KDB */
Index: sys/platform/pc64/conf/files
===================================================================
RCS file: /home/dcvs/src/sys/platform/pc64/conf/files,v
retrieving revision 1.2
diff -u -r1.2 files
--- sys/platform/pc64/conf/files	24 Sep 2007 03:24:45 -0000	1.2
+++ sys/platform/pc64/conf/files	10 Feb 2008 11:48:09 -0000
@@ -67,7 +67,8 @@
 
 # PLATFORM FILES
 #
-platform/pc64/amd64/global.s		standard
+platform/pc64/amd64/globals.s		standard
+platform/pc64/amd64/bios.c		standard
 platform/pc64/amd64/support.s		standard
 platform/pc64/amd64/sigtramp.s		standard
 platform/pc64/amd64/swtch.s		standard
@@ -82,9 +83,17 @@
 platform/pc64/amd64/exception.c		standard
 platform/pc64/amd64/procfs_machdep.c	standard
 platform/pc64/amd64/fork_tramp.s	standard
-#platform/pc64/amd64/machdep.c		standard
-#platform/pc64/amd64/initcpu.c		standard
-#platform/pc64/amd64/identcpu.c		standard
+platform/pc64/amd64/machdep.c		standard
+platform/pc64/amd64/initcpu.c		standard
+platform/pc64/amd64/identcpu.c		standard
+
+platform/pc64/isa/atpic.c               optional        atpic isa
+#platform/pc64/isa/atpic_vector.S       optional        atpic isa
+platform/pc64/isa/clock.c               standard
+platform/pc64/isa/elcr.c                standard
+platform/pc64/isa/isa.c                 standard
+platform/pc64/isa/isa_dma.c             standard
+platform/pc64/isa/nmi.c                 standard
 
 platform/pc64/amd64/init.c		standard
 platform/pc64/amd64/globaldata.c	standard
Index: sys/platform/pc64/include/cpu.h
===================================================================
RCS file: /home/dcvs/src/sys/platform/pc64/include/cpu.h,v
retrieving revision 1.1
diff -u -r1.1 cpu.h
--- sys/platform/pc64/include/cpu.h	23 Sep 2007 04:42:07 -0000	1.1
+++ sys/platform/pc64/include/cpu.h	10 Feb 2008 11:48:09 -0000
@@ -1,6 +1,4 @@
 /* 
- *
- *
  * $DragonFly: src/sys/platform/pc64/include/cpu.h,v 1.1 2007/09/23 04:42:07 yanyh Exp $
  */
 
Index: sys/platform/pc64/include/md_var.h
===================================================================
RCS file: /home/dcvs/src/sys/platform/pc64/include/md_var.h,v
retrieving revision 1.4
diff -u -r1.4 md_var.h
--- sys/platform/pc64/include/md_var.h	12 Dec 2007 23:49:23 -0000	1.4
+++ sys/platform/pc64/include/md_var.h	10 Feb 2008 11:48:09 -0000
@@ -41,10 +41,15 @@
 extern	u_int	basemem;
 extern	int	busdma_swi_pending;
 extern	u_int	cpu_exthigh;
+extern	u_int	cpu_feature;
+extern	u_int	cpu_feature2;
+extern	u_int	amd_feature;
+extern	u_int	amd_feature2;
 extern	u_int	cpu_fxsr;
 extern	u_int	cpu_high;
 extern	u_int	cpu_id;
 extern	u_int	cpu_procinfo;
+extern	u_int	cpu_procinfo2;
 extern	char	cpu_vendor[];
 extern	char	kstack[];
 extern	char	sigcode[];
@@ -72,6 +77,7 @@
 void npxpush(struct __mcontext *mctx);
 void npxpop(struct __mcontext *mctx);
 
+void	initializecpu(void);
 void	cpu_heavy_restore (void);
 void	cpu_kthread_restore (void);/* cannot be called from C */
 
Index: sys/platform/pc64/include/pc/bios.h
===================================================================
RCS file: sys/platform/pc64/include/pc/bios.h
diff -N sys/platform/pc64/include/pc/bios.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/platform/pc64/include/pc/bios.h	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 1997 Michael Smith
+ * Copyright (c) 1998 Jonathan Lemon
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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
+ * 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/amd64/include/pc/bios.h,v 1.19 2005/07/21 09:48:36 phk Exp $
+ */
+
+#ifndef _MACHINE_PC_BIOS_H_
+#define _MACHINE_PC_BIOS_H_
+
+extern u_int32_t	bios_sigsearch(u_int32_t start, u_char *sig, int siglen, 
+					 int paralen, int sigofs);
+
+#define BIOS_PADDRTOVADDR(x)	((x) + KERNBASE)
+#define BIOS_VADDRTOPADDR(x)	((x) - KERNBASE)
+
+/*
+ * Int 15:E820 'SMAP' structure
+ *
+ * XXX add constants for type
+ */
+#define SMAP_SIG	0x534D4150			/* 'SMAP' */
+struct bios_smap {
+    u_int64_t	base;
+    u_int64_t	length;
+    u_int32_t	type;
+} __packed;
+
+struct bios_oem_signature {
+	char * anchor;		/* search anchor string in BIOS memory */
+	size_t offset;		/* offset from anchor (may be negative) */
+	size_t totlen;		/* total length of BIOS string to copy */
+} __packed;
+struct bios_oem_range {
+	u_int from;		/* shouldn't be below 0xe0000 */
+	u_int to;		/* shouldn't be above 0xfffff */
+} __packed;
+struct bios_oem {
+	struct bios_oem_range range;
+	struct bios_oem_signature signature[];
+} __packed;
+
+extern int
+bios_oem_strings(struct bios_oem *oem, u_char *buffer, size_t maxlen);
+
+
+#endif /* _MACHINE_PC_BIOS_H_ */
Index: sys/platform/pc64/include/pc/display.h
===================================================================
RCS file: sys/platform/pc64/include/pc/display.h
diff -N sys/platform/pc64/include/pc/display.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/platform/pc64/include/pc/display.h	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,45 @@
+/*
+ * IBM PC display definitions
+ *
+ * $FreeBSD: src/sys/amd64/include/pc/display.h,v 1.7 2005/01/05 20:11:13 imp Exp $
+ */
+
+/* Color attributes for foreground text */
+
+#define	FG_BLACK		   0
+#define	FG_BLUE			   1
+#define	FG_GREEN		   2
+#define	FG_CYAN			   3
+#define	FG_RED			   4
+#define	FG_MAGENTA		   5
+#define	FG_BROWN		   6
+#define	FG_LIGHTGREY		   7
+#define	FG_DARKGREY		   8
+#define	FG_LIGHTBLUE		   9
+#define	FG_LIGHTGREEN		  10
+#define	FG_LIGHTCYAN		  11
+#define	FG_LIGHTRED		  12
+#define	FG_LIGHTMAGENTA		  13
+#define	FG_YELLOW		  14
+#define	FG_WHITE		  15
+#define	FG_BLINK		0x80
+
+/* Color attributes for text background */
+
+#define	BG_BLACK		0x00
+#define	BG_BLUE			0x10
+#define	BG_GREEN		0x20
+#define	BG_CYAN			0x30
+#define	BG_RED			0x40
+#define	BG_MAGENTA		0x50
+#define	BG_BROWN		0x60
+#define	BG_LIGHTGREY		0x70
+
+/* Monochrome attributes for foreground text */
+
+#define	FG_UNDERLINE		0x01
+#define	FG_INTENSE		0x08
+
+/* Monochrome attributes for text background */
+
+#define	BG_INTENSE		0x10
Index: sys/platform/pc64/isa/atpic.c
===================================================================
RCS file: sys/platform/pc64/isa/atpic.c
diff -N sys/platform/pc64/isa/atpic.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/platform/pc64/isa/atpic.c	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,614 @@
+/*-
+ * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
+ * 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 author nor the names of any co-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
+ * 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
+ * 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.
+ */
+
+/*
+ * PIC driver for the 8259A Master and Slave PICs in PC/AT machines.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/amd64/isa/atpic.c,v 1.22 2007/05/08 21:29:13 jhb Exp $");
+
+#include "opt_auto_eoi.h"
+#include "opt_isa.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/interrupt.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+
+#include <machine/cpufunc.h>
+#include <machine/frame.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/resource.h>
+#include <machine/segments.h>
+
+#include <dev/ic/i8259.h>
+#include <amd64/isa/icu.h>
+#include <amd64/isa/isa.h>
+
+#include <isa/isavar.h>
+
+#define	MASTER	0
+#define	SLAVE	1
+
+/*
+ * PC-AT machines wire the slave PIC to pin 2 on the master PIC.
+ */
+#define	ICU_SLAVEID	2
+
+/*
+ * Determine the base master and slave modes not including auto EOI support.
+ * All machines that FreeBSD supports use 8086 mode.
+ */
+#define	BASE_MASTER_MODE	ICW4_8086
+#define	BASE_SLAVE_MODE		ICW4_8086
+
+/* Enable automatic EOI if requested. */
+#ifdef AUTO_EOI_1
+#define	MASTER_MODE		(BASE_MASTER_MODE | ICW4_AEOI)
+#else
+#define	MASTER_MODE		BASE_MASTER_MODE
+#endif
+#ifdef AUTO_EOI_2
+#define	SLAVE_MODE		(BASE_SLAVE_MODE | ICW4_AEOI)
+#else
+#define	SLAVE_MODE		BASE_SLAVE_MODE
+#endif
+
+#define	IRQ_MASK(irq)		(1 << (irq))
+#define	IMEN_MASK(ai)		(IRQ_MASK((ai)->at_irq))
+
+#define	NUM_ISA_IRQS		16
+
+static void	atpic_init(void *dummy);
+
+unsigned int imen;	/* XXX */
+
+inthand_t
+	IDTVEC(atpic_intr0), IDTVEC(atpic_intr1), IDTVEC(atpic_intr2),
+	IDTVEC(atpic_intr3), IDTVEC(atpic_intr4), IDTVEC(atpic_intr5),
+	IDTVEC(atpic_intr6), IDTVEC(atpic_intr7), IDTVEC(atpic_intr8),
+	IDTVEC(atpic_intr9), IDTVEC(atpic_intr10), IDTVEC(atpic_intr11),
+	IDTVEC(atpic_intr12), IDTVEC(atpic_intr13), IDTVEC(atpic_intr14),
+	IDTVEC(atpic_intr15);
+
+#define	IRQ(ap, ai)	((ap)->at_irqbase + (ai)->at_irq)
+
+#define	ATPIC(io, base, eoi, imenptr)					\
+     	{ { atpic_enable_source, atpic_disable_source, (eoi),		\
+	    atpic_enable_intr, atpic_disable_intr, atpic_vector,	\
+	    atpic_source_pending, NULL,	atpic_resume, atpic_config_intr,\
+	    atpic_assign_cpu }, (io), (base), IDT_IO_INTS + (base),	\
+	    (imenptr) }
+
+#define	INTSRC(irq)							\
+	{ { &atpics[(irq) / 8].at_pic }, IDTVEC(atpic_intr ## irq ),	\
+	    (irq) % 8 }
+
+struct atpic {
+	struct pic at_pic;
+	int	at_ioaddr;
+	int	at_irqbase;
+	uint8_t	at_intbase;
+	uint8_t	*at_imen;
+};
+
+struct atpic_intsrc {
+	struct intsrc at_intsrc;
+	inthand_t *at_intr;
+	int	at_irq;			/* Relative to PIC base. */
+	enum intr_trigger at_trigger;
+	u_long	at_count;
+	u_long	at_straycount;
+};
+
+static void atpic_enable_source(struct intsrc *isrc);
+static void atpic_disable_source(struct intsrc *isrc, int eoi);
+static void atpic_eoi_master(struct intsrc *isrc);
+static void atpic_eoi_slave(struct intsrc *isrc);
+static void atpic_enable_intr(struct intsrc *isrc);
+static void atpic_disable_intr(struct intsrc *isrc);
+static int atpic_vector(struct intsrc *isrc);
+static void atpic_resume(struct pic *pic);
+static int atpic_source_pending(struct intsrc *isrc);
+static int atpic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
+    enum intr_polarity pol);
+static void atpic_assign_cpu(struct intsrc *isrc, u_int apic_id);
+static void i8259_init(struct atpic *pic, int slave);
+
+static struct atpic atpics[] = {
+	ATPIC(IO_ICU1, 0, atpic_eoi_master, (uint8_t *)&imen),
+	ATPIC(IO_ICU2, 8, atpic_eoi_slave, ((uint8_t *)&imen) + 1)
+};
+
+static struct atpic_intsrc atintrs[] = {
+	INTSRC(0),
+	INTSRC(1),
+	INTSRC(2),
+	INTSRC(3),
+	INTSRC(4),
+	INTSRC(5),
+	INTSRC(6),
+	INTSRC(7),
+	INTSRC(8),
+	INTSRC(9),
+	INTSRC(10),
+	INTSRC(11),
+	INTSRC(12),
+	INTSRC(13),
+	INTSRC(14),
+	INTSRC(15),
+};
+
+CTASSERT(sizeof(atintrs) / sizeof(atintrs[0]) == NUM_ISA_IRQS);
+
+static __inline void
+_atpic_eoi_master(struct intsrc *isrc)
+{
+
+	KASSERT(isrc->is_pic == &atpics[MASTER].at_pic,
+	    ("%s: mismatched pic", __func__));
+#ifndef AUTO_EOI_1
+	outb(atpics[MASTER].at_ioaddr, OCW2_EOI);
+#endif
+}
+
+/*
+ * The data sheet says no auto-EOI on slave, but it sometimes works.
+ * So, if AUTO_EOI_2 is enabled, we use it.
+ */
+static __inline void
+_atpic_eoi_slave(struct intsrc *isrc)
+{
+
+	KASSERT(isrc->is_pic == &atpics[SLAVE].at_pic,
+	    ("%s: mismatched pic", __func__));
+#ifndef AUTO_EOI_2
+	outb(atpics[SLAVE].at_ioaddr, OCW2_EOI);
+#ifndef AUTO_EOI_1
+	outb(atpics[MASTER].at_ioaddr, OCW2_EOI);
+#endif
+#endif
+}
+
+static void
+atpic_enable_source(struct intsrc *isrc)
+{
+	struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
+	struct atpic *ap = (struct atpic *)isrc->is_pic;
+
+	mtx_lock_spin(&icu_lock);
+	if (*ap->at_imen & IMEN_MASK(ai)) {
+		*ap->at_imen &= ~IMEN_MASK(ai);
+		outb(ap->at_ioaddr + ICU_IMR_OFFSET, *ap->at_imen);
+	}
+	mtx_unlock_spin(&icu_lock);
+}
+
+static void
+atpic_disable_source(struct intsrc *isrc, int eoi)
+{
+	struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
+	struct atpic *ap = (struct atpic *)isrc->is_pic;
+
+	mtx_lock_spin(&icu_lock);
+	if (ai->at_trigger != INTR_TRIGGER_EDGE) {
+		*ap->at_imen |= IMEN_MASK(ai);
+		outb(ap->at_ioaddr + ICU_IMR_OFFSET, *ap->at_imen);
+	}
+
+	/*
+	 * Take care to call these functions directly instead of through
+	 * a function pointer.  All of the referenced variables should
+	 * still be hot in the cache.
+	 */
+	if (eoi == PIC_EOI) {
+		if (isrc->is_pic == &atpics[MASTER].at_pic)
+			_atpic_eoi_master(isrc);
+		else
+			_atpic_eoi_slave(isrc);
+	}
+
+	mtx_unlock_spin(&icu_lock);
+}
+
+static void
+atpic_eoi_master(struct intsrc *isrc)
+{
+#ifndef AUTO_EOI_1
+	mtx_lock_spin(&icu_lock);
+	_atpic_eoi_master(isrc);
+	mtx_unlock_spin(&icu_lock);
+#endif
+}
+
+static void
+atpic_eoi_slave(struct intsrc *isrc)
+{
+#ifndef AUTO_EOI_2
+	mtx_lock_spin(&icu_lock);
+	_atpic_eoi_slave(isrc);
+	mtx_unlock_spin(&icu_lock);
+#endif
+}
+
+static void
+atpic_enable_intr(struct intsrc *isrc)
+{
+}
+
+static void
+atpic_disable_intr(struct intsrc *isrc)
+{
+}
+
+
+static int
+atpic_vector(struct intsrc *isrc)
+{
+	struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
+	struct atpic *ap = (struct atpic *)isrc->is_pic;
+
+	return (IRQ(ap, ai));
+}
+
+static int
+atpic_source_pending(struct intsrc *isrc)
+{
+	struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
+	struct atpic *ap = (struct atpic *)isrc->is_pic;
+
+	return (inb(ap->at_ioaddr) & IMEN_MASK(ai));
+}
+
+static void
+atpic_resume(struct pic *pic)
+{
+	struct atpic *ap = (struct atpic *)pic;
+
+	i8259_init(ap, ap == &atpics[SLAVE]);
+	if (ap == &atpics[SLAVE] && elcr_found)
+		elcr_resume();
+}
+
+static int
+atpic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
+    enum intr_polarity pol)
+{
+	struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
+	u_int vector;
+
+	/* Map conforming values to edge/hi and sanity check the values. */
+	if (trig == INTR_TRIGGER_CONFORM)
+		trig = INTR_TRIGGER_EDGE;
+	if (pol == INTR_POLARITY_CONFORM)
+		pol = INTR_POLARITY_HIGH;
+	vector = atpic_vector(isrc);
+	if ((trig == INTR_TRIGGER_EDGE && pol == INTR_POLARITY_LOW) ||
+	    (trig == INTR_TRIGGER_LEVEL && pol == INTR_POLARITY_HIGH)) {
+		printf(
+		"atpic: Mismatched config for IRQ%u: trigger %s, polarity %s\n",
+		    vector, trig == INTR_TRIGGER_EDGE ? "edge" : "level",
+		    pol == INTR_POLARITY_HIGH ? "high" : "low");
+		return (EINVAL);
+	}
+
+	/* If there is no change, just return. */
+	if (ai->at_trigger == trig)
+		return (0);
+
+	/*
+	 * Certain IRQs can never be level/lo, so don't try to set them
+	 * that way if asked.  At least some ELCR registers ignore setting
+	 * these bits as well.
+	 */
+	if ((vector == 0 || vector == 1 || vector == 2 || vector == 13) &&
+	    trig == INTR_TRIGGER_LEVEL) {
+		if (bootverbose)
+			printf(
+		"atpic: Ignoring invalid level/low configuration for IRQ%u\n",
+			    vector);
+		return (EINVAL);
+	}
+	if (!elcr_found) {
+		if (bootverbose)
+			printf("atpic: No ELCR to configure IRQ%u as %s\n",
+			    vector, trig == INTR_TRIGGER_EDGE ? "edge/high" :
+			    "level/low");
+		return (ENXIO);
+	}
+	if (bootverbose)
+		printf("atpic: Programming IRQ%u as %s\n", vector,
+		    trig == INTR_TRIGGER_EDGE ? "edge/high" : "level/low");
+	mtx_lock_spin(&icu_lock);
+	elcr_write_trigger(atpic_vector(isrc), trig);
+	ai->at_trigger = trig;
+	mtx_unlock_spin(&icu_lock);
+	return (0);
+}
+
+static void
+atpic_assign_cpu(struct intsrc *isrc, u_int apic_id)
+{
+
+	/*
+	 * 8259A's are only used in UP in which case all interrupts always
+	 * go to the sole CPU and this function shouldn't even be called.
+	 */
+	panic("%s: bad cookie", __func__);
+}
+
+static void
+i8259_init(struct atpic *pic, int slave)
+{
+	int imr_addr;
+
+	/* Reset the PIC and program with next four bytes. */
+	mtx_lock_spin(&icu_lock);
+	outb(pic->at_ioaddr, ICW1_RESET | ICW1_IC4);
+	imr_addr = pic->at_ioaddr + ICU_IMR_OFFSET;
+
+	/* Start vector. */
+	outb(imr_addr, pic->at_intbase);
+
+	/*
+	 * Setup slave links.  For the master pic, indicate what line
+	 * the slave is configured on.  For the slave indicate
+	 * which line on the master we are connected to.
+	 */
+	if (slave)
+		outb(imr_addr, ICU_SLAVEID);
+	else
+		outb(imr_addr, IRQ_MASK(ICU_SLAVEID));
+
+	/* Set mode. */
+	if (slave)
+		outb(imr_addr, SLAVE_MODE);
+	else
+		outb(imr_addr, MASTER_MODE);
+
+	/* Set interrupt enable mask. */
+	outb(imr_addr, *pic->at_imen);
+
+	/* Reset is finished, default to IRR on read. */
+	outb(pic->at_ioaddr, OCW3_SEL | OCW3_RR);
+
+	/* OCW2_L1 sets priority order to 3-7, 0-2 (com2 first). */
+	if (!slave)
+		outb(pic->at_ioaddr, OCW2_R | OCW2_SL | OCW2_L1);
+	mtx_unlock_spin(&icu_lock);
+}
+
+void
+atpic_startup(void)
+{
+	struct atpic_intsrc *ai;
+	int i;
+
+	/* Start off with all interrupts disabled. */
+	imen = 0xffff;
+	i8259_init(&atpics[MASTER], 0);
+	i8259_init(&atpics[SLAVE], 1);
+	atpic_enable_source((struct intsrc *)&atintrs[ICU_SLAVEID]);
+
+	/* Install low-level interrupt handlers for all of our IRQs. */
+	for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) {
+		if (i == ICU_SLAVEID)
+			continue;
+		ai->at_intsrc.is_count = &ai->at_count;
+		ai->at_intsrc.is_straycount = &ai->at_straycount;
+		setidt(((struct atpic *)ai->at_intsrc.is_pic)->at_intbase +
+		    ai->at_irq, ai->at_intr, SDT_SYSIGT, SEL_KPL, 0);
+	}
+
+	/*
+	 * Look for an ELCR.  If we find one, update the trigger modes.
+	 * If we don't find one, assume that IRQs 0, 1, 2, and 13 are
+	 * edge triggered and that everything else is level triggered.
+	 * We only use the trigger information to reprogram the ELCR if
+	 * we have one and as an optimization to avoid masking edge
+	 * triggered interrupts.  For the case that we don't have an ELCR,
+	 * it doesn't hurt to mask an edge triggered interrupt, so we
+	 * assume level trigger for any interrupt that we aren't sure is
+	 * edge triggered.
+	 */
+	if (elcr_found) {
+		for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
+			ai->at_trigger = elcr_read_trigger(i);
+	} else {
+		for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
+			switch (i) {
+			case 0:
+			case 1:
+			case 2:
+			case 8:
+			case 13:
+				ai->at_trigger = INTR_TRIGGER_EDGE;
+				break;
+			default:
+				ai->at_trigger = INTR_TRIGGER_LEVEL;
+				break;
+			}
+	}
+}
+
+static void
+atpic_init(void *dummy __unused)
+{
+	struct atpic_intsrc *ai;
+	int i;
+
+	/*
+	 * Register our PICs, even if we aren't going to use any of their
+	 * pins so that they are suspended and resumed.
+	 */
+	if (intr_register_pic(&atpics[0].at_pic) != 0 ||
+	    intr_register_pic(&atpics[1].at_pic) != 0)
+		panic("Unable to register ATPICs");
+
+	/*
+	 * If any of the ISA IRQs have an interrupt source already, then
+	 * assume that the APICs are being used and don't register any
+	 * of our interrupt sources.  This makes sure we don't accidentally
+	 * use mixed mode.  The "accidental" use could otherwise occur on
+	 * machines that route the ACPI SCI interrupt to a different ISA
+	 * IRQ (at least one machines routes it to IRQ 13) thus disabling
+	 * that APIC ISA routing and allowing the ATPIC source for that IRQ
+	 * to leak through.  We used to depend on this feature for routing
+	 * IRQ0 via mixed mode, but now we don't use mixed mode at all.
+	 */
+	for (i = 0; i < NUM_ISA_IRQS; i++)
+		if (intr_lookup_source(i) != NULL)
+			return;
+
+	/* Loop through all interrupt sources and add them. */
+	for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) {
+		if (i == ICU_SLAVEID)
+			continue;
+		intr_register_source(&ai->at_intsrc);
+	}
+}
+SYSINIT(atpic_init, SI_SUB_INTR, SI_ORDER_SECOND + 1, atpic_init, NULL)
+
+void
+atpic_handle_intr(u_int vector, struct trapframe *frame)
+{
+	struct intsrc *isrc;
+
+	KASSERT(vector < NUM_ISA_IRQS, ("unknown int %u\n", vector));
+	isrc = &atintrs[vector].at_intsrc;
+
+	/*
+	 * If we don't have an event, see if this is a spurious
+	 * interrupt.
+	 */
+	if (isrc->is_event == NULL && (vector == 7 || vector == 15)) {
+		int port, isr;
+
+		/*
+		 * Read the ISR register to see if IRQ 7/15 is really
+		 * pending.  Reset read register back to IRR when done.
+		 */
+		port = ((struct atpic *)isrc->is_pic)->at_ioaddr;
+		mtx_lock_spin(&icu_lock);
+		outb(port, OCW3_SEL | OCW3_RR | OCW3_RIS);
+		isr = inb(port);
+		outb(port, OCW3_SEL | OCW3_RR);
+		mtx_unlock_spin(&icu_lock);
+		if ((isr & IRQ_MASK(7)) == 0)
+			return;
+	}
+	intr_execute_handlers(isrc, frame);
+}
+
+#ifdef DEV_ISA
+/*
+ * Bus attachment for the ISA PIC.
+ */
+static struct isa_pnp_id atpic_ids[] = {
+	{ 0x0000d041 /* PNP0000 */, "AT interrupt controller" },
+	{ 0 }
+};
+
+static int
+atpic_probe(device_t dev)
+{
+	int result;
+	
+	result = ISA_PNP_PROBE(device_get_parent(dev), dev, atpic_ids);
+	if (result <= 0)
+		device_quiet(dev);
+	return (result);
+}
+
+/*
+ * We might be granted IRQ 2, as this is typically consumed by chaining
+ * between the two PIC components.  If we're using the APIC, however,
+ * this may not be the case, and as such we should free the resource.
+ * (XXX untested)
+ *
+ * The generic ISA attachment code will handle allocating any other resources
+ * that we don't explicitly claim here.
+ */
+static int
+atpic_attach(device_t dev)
+{
+	struct resource *res;
+	int rid;
+
+	/* Try to allocate our IRQ and then free it. */
+	rid = 0;
+	res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 0);
+	if (res != NULL)
+		bus_release_resource(dev, SYS_RES_IRQ, rid, res);
+	return (0);
+}
+
+static device_method_t atpic_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		atpic_probe),
+	DEVMETHOD(device_attach,	atpic_attach),
+	DEVMETHOD(device_detach,	bus_generic_detach),
+	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
+	DEVMETHOD(device_suspend,	bus_generic_suspend),
+	DEVMETHOD(device_resume,	bus_generic_resume),
+	{ 0, 0 }
+};
+
+static driver_t atpic_driver = {
+	"atpic",
+	atpic_methods,
+	1,		/* no softc */
+};
+
+static devclass_t atpic_devclass;
+
+DRIVER_MODULE(atpic, isa, atpic_driver, atpic_devclass, 0, 0);
+DRIVER_MODULE(atpic, acpi, atpic_driver, atpic_devclass, 0, 0);
+
+/*
+ * Return a bitmap of the current interrupt requests.  This is 8259-specific
+ * and is only suitable for use at probe time.
+ */
+intrmask_t
+isa_irq_pending(void)
+{
+	u_char irr1;
+	u_char irr2;
+
+	irr1 = inb(IO_ICU1);
+	irr2 = inb(IO_ICU2);
+	return ((irr2 << 8) | irr1);
+}
+#endif /* DEV_ISA */
Index: sys/platform/pc64/isa/atpic_vector.S
===================================================================
RCS file: sys/platform/pc64/isa/atpic_vector.S
diff -N sys/platform/pc64/isa/atpic_vector.S
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/platform/pc64/isa/atpic_vector.S	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,73 @@
+/*-
+ * Copyright (c) 1989, 1990 William F. Jolitz.
+ * 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.
+ * 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: vector.s, 386BSD 0.1 unknown origin
+ * $FreeBSD: src/sys/amd64/isa/atpic_vector.S,v 1.48 2006/12/17 06:48:40 kmacy Exp $
+ */
+
+/*
+ * Interrupt entry points for external interrupts triggered by the 8259A
+ * master and slave interrupt controllers.
+ */
+
+#include <machine/asmacros.h>
+
+#include "assym.s"
+
+/*
+ * Macros for interrupt entry, call to handler, and exit.
+ */
+#define	INTR(irq_num, vec_name) \
+	.text ;								\
+	SUPERALIGN_TEXT ;						\
+IDTVEC(vec_name) ;							\
+	PUSH_FRAME ;							\
+	FAKE_MCOUNT(TF_RIP(%rsp)) ;					\
+	movq	%rsp, %rsi	;                                       \
+	movl	$irq_num, %edi; 	/* pass the IRQ */		\
+	call	atpic_handle_intr ;					\
+	MEXITCOUNT ;							\
+	jmp	doreti
+
+	INTR(0, atpic_intr0)
+	INTR(1, atpic_intr1)
+	INTR(2, atpic_intr2)
+	INTR(3, atpic_intr3)
+	INTR(4, atpic_intr4)
+	INTR(5, atpic_intr5)
+	INTR(6, atpic_intr6)
+	INTR(7, atpic_intr7)
+	INTR(8, atpic_intr8)
+	INTR(9, atpic_intr9)
+	INTR(10, atpic_intr10)
+	INTR(11, atpic_intr11)
+	INTR(12, atpic_intr12)
+	INTR(13, atpic_intr13)
+	INTR(14, atpic_intr14)
+	INTR(15, atpic_intr15)
Index: sys/platform/pc64/isa/clock.c
===================================================================
RCS file: sys/platform/pc64/isa/clock.c
diff -N sys/platform/pc64/isa/clock.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/platform/pc64/isa/clock.c	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,1033 @@
+/*-
+ * 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 and Don Ahn.
+ *
+ * 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.
+ *
+ *	from: @(#)clock.c	7.2 (Berkeley) 5/12/91
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/amd64/isa/clock.c,v 1.232 2007/06/15 22:58:14 peter Exp $");
+
+/*
+ * Routines to handle clock hardware.
+ */
+
+/*
+ * inittodr, settodr and support routines written
+ * by Christoph Robitschko <chmr@edvz.tu-graz.ac.at>
+ *
+ * reintroduced and updated by Chris Stenton <chris@gnome.co.uk> 8/10/94
+ */
+
+#include "opt_clock.h"
+#include "opt_isa.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
+#include <sys/lock.h>
+#include <sys/kdb.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/time.h>
+#include <sys/timetc.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/module.h>
+#include <sys/sched.h>
+#include <sys/sysctl.h>
+#include <sys/cons.h>
+#include <sys/power.h>
+
+#include <machine/clock.h>
+#include <machine/cpu.h>
+#include <machine/frame.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/psl.h>
+#include <machine/apicvar.h>
+#include <machine/specialreg.h>
+#include <machine/ppireg.h>
+#include <machine/timerreg.h>
+
+#include <isa/rtc.h>
+#ifdef DEV_ISA
+#include <isa/isareg.h>
+#include <isa/isavar.h>
+#endif
+
+/*
+ * 32-bit time_t's can't reach leap years before 1904 or after 2036, so we
+ * can use a simple formula for leap years.
+ */
+#define	LEAPYEAR(y) (((u_int)(y) % 4 == 0) ? 1 : 0)
+#define DAYSPERYEAR   (31+28+31+30+31+30+31+31+30+31+30+31)
+
+#define	TIMER_DIV(x) ((timer_freq + (x) / 2) / (x))
+
+int	clkintr_pending;
+int	pscnt = 1;
+int	psdiv = 1;
+int	statclock_disable;
+#ifndef TIMER_FREQ
+#define TIMER_FREQ   1193182
+#endif
+u_int	timer_freq = TIMER_FREQ;
+int	timer0_max_count;
+int	timer0_real_max_count;
+#define	RTC_LOCK	mtx_lock_spin(&clock_lock)
+#define	RTC_UNLOCK	mtx_unlock_spin(&clock_lock)
+
+static	int	beeping = 0;
+static	struct mtx clock_lock;
+static	const u_char daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
+static	struct intsrc *i8254_intsrc;
+static	u_int32_t i8254_lastcount;
+static	u_int32_t i8254_offset;
+static	int	(*i8254_pending)(struct intsrc *);
+static	int	i8254_ticked;
+static	int	using_lapic_timer;
+static	int	rtc_reg = -1;
+static	u_char	rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
+static	u_char	rtc_statusb = RTCSB_24HR;
+
+/* Values for timerX_state: */
+#define	RELEASED	0
+#define	RELEASE_PENDING	1
+#define	ACQUIRED	2
+#define	ACQUIRE_PENDING	3
+
+static	u_char	timer2_state;
+
+static	unsigned i8254_get_timecount(struct timecounter *tc);
+static	unsigned i8254_simple_get_timecount(struct timecounter *tc);
+static	void	set_timer_freq(u_int freq, int intr_freq);
+
+static struct timecounter i8254_timecounter = {
+	i8254_get_timecount,	/* get_timecount */
+	0,			/* no poll_pps */
+	~0u,			/* counter_mask */
+	0,			/* frequency */
+	"i8254",		/* name */
+	0			/* quality */
+};
+
+static int
+clkintr(struct trapframe *frame)
+{
+
+	if (timecounter->tc_get_timecount == i8254_get_timecount) {
+		mtx_lock_spin(&clock_lock);
+		if (i8254_ticked)
+			i8254_ticked = 0;
+		else {
+			i8254_offset += timer0_max_count;
+			i8254_lastcount = 0;
+		}
+		clkintr_pending = 0;
+		mtx_unlock_spin(&clock_lock);
+	}
+	KASSERT(!using_lapic_timer, ("clk interrupt enabled with lapic timer"));
+	hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
+	return (FILTER_HANDLED);
+}
+
+int
+acquire_timer2(int mode)
+{
+
+	if (timer2_state != RELEASED)
+		return (-1);
+	timer2_state = ACQUIRED;
+
+	/*
+	 * This access to the timer registers is as atomic as possible
+	 * because it is a single instruction.  We could do better if we
+	 * knew the rate.  Use of splclock() limits glitches to 10-100us,
+	 * and this is probably good enough for timer2, so we aren't as
+	 * careful with it as with timer0.
+	 */
+	outb(TIMER_MODE, TIMER_SEL2 | (mode & 0x3f));
+
+	return (0);
+}
+
+int
+release_timer2()
+{
+
+	if (timer2_state != ACQUIRED)
+		return (-1);
+	timer2_state = RELEASED;
+	outb(TIMER_MODE, TIMER_SEL2 | TIMER_SQWAVE | TIMER_16BIT);
+	return (0);
+}
+
+/*
+ * This routine receives statistical clock interrupts from the RTC.
+ * As explained above, these occur at 128 interrupts per second.
+ * When profiling, we receive interrupts at a rate of 1024 Hz.
+ *
+ * This does not actually add as much overhead as it sounds, because
+ * when the statistical clock is active, the hardclock driver no longer
+ * needs to keep (inaccurate) statistics on its own.  This decouples
+ * statistics gathering from scheduling interrupts.
+ *
+ * The RTC chip requires that we read status register C (RTC_INTR)
+ * to acknowledge an interrupt, before it will generate the next one.
+ * Under high interrupt load, rtcintr() can be indefinitely delayed and
+ * the clock can tick immediately after the read from RTC_INTR.  In this
+ * case, the mc146818A interrupt signal will not drop for long enough
+ * to register with the 8259 PIC.  If an interrupt is missed, the stat
+ * clock will halt, considerably degrading system performance.  This is
+ * why we use 'while' rather than a more straightforward 'if' below.
+ * Stat clock ticks can still be lost, causing minor loss of accuracy
+ * in the statistics, but the stat clock will no longer stop.
+ */
+static int
+rtcintr(struct trapframe *frame)
+{
+	int flag = 0;
+
+	while (rtcin(RTC_INTR) & RTCIR_PERIOD) {
+		flag = 1;
+		if (profprocs != 0) {
+			if (--pscnt == 0)
+				pscnt = psdiv;
+			profclock(TRAPF_USERMODE(frame), TRAPF_PC(frame));
+		}
+		if (pscnt == psdiv)
+			statclock(TRAPF_USERMODE(frame));
+	}
+	return(flag ? FILTER_HANDLED : FILTER_STRAY);
+}
+
+#include "opt_ddb.h"
+#ifdef DDB
+#include <ddb/ddb.h>
+
+DB_SHOW_COMMAND(rtc, rtc)
+{
+	printf("%02x/%02x/%02x %02x:%02x:%02x, A = %02x, B = %02x, C = %02x\n",
+	       rtcin(RTC_YEAR), rtcin(RTC_MONTH), rtcin(RTC_DAY),
+	       rtcin(RTC_HRS), rtcin(RTC_MIN), rtcin(RTC_SEC),
+	       rtcin(RTC_STATUSA), rtcin(RTC_STATUSB), rtcin(RTC_INTR));
+}
+#endif /* DDB */
+
+static int
+getit(void)
+{
+	int high, low;
+
+	mtx_lock_spin(&clock_lock);
+
+	/* Select timer0 and latch counter value. */
+	outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
+
+	low = inb(TIMER_CNTR0);
+	high = inb(TIMER_CNTR0);
+
+	mtx_unlock_spin(&clock_lock);
+	return ((high << 8) | low);
+}
+
+/*
+ * Wait "n" microseconds.
+ * Relies on timer 1 counting down from (timer_freq / hz)
+ * Note: timer had better have been programmed before this is first used!
+ */
+void
+DELAY(int n)
+{
+	int delta, prev_tick, tick, ticks_left;
+
+#ifdef DELAYDEBUG
+	int getit_calls = 1;
+	int n1;
+	static int state = 0;
+#endif
+
+	if (tsc_freq != 0 && !tsc_is_broken) {
+		uint64_t start, end, now;
+
+		sched_pin();
+		start = rdtsc();
+		end = start + (tsc_freq * n) / 1000000;
+		do {
+			now = rdtsc();
+		} while (now < end || (now > start && end < start));
+		sched_unpin();
+		return;
+	}
+#ifdef DELAYDEBUG
+	if (state == 0) {
+		state = 1;
+		for (n1 = 1; n1 <= 10000000; n1 *= 10)
+			DELAY(n1);
+		state = 2;
+	}
+	if (state == 1)
+		printf("DELAY(%d)...", n);
+#endif
+	/*
+	 * Read the counter first, so that the rest of the setup overhead is
+	 * counted.  Guess the initial overhead is 20 usec (on most systems it
+	 * takes about 1.5 usec for each of the i/o's in getit().  The loop
+	 * takes about 6 usec on a 486/33 and 13 usec on a 386/20.  The
+	 * multiplications and divisions to scale the count take a while).
+	 *
+	 * However, if ddb is active then use a fake counter since reading
+	 * the i8254 counter involves acquiring a lock.  ddb must not do
+	 * locking for many reasons, but it calls here for at least atkbd
+	 * input.
+	 */
+#ifdef KDB
+	if (kdb_active)
+		prev_tick = 1;
+	else
+#endif
+		prev_tick = getit();
+	n -= 0;			/* XXX actually guess no initial overhead */
+	/*
+	 * Calculate (n * (timer_freq / 1e6)) without using floating point
+	 * and without any avoidable overflows.
+	 */
+	if (n <= 0)
+		ticks_left = 0;
+	else if (n < 256)
+		/*
+		 * Use fixed point to avoid a slow division by 1000000.
+		 * 39099 = 1193182 * 2^15 / 10^6 rounded to nearest.
+		 * 2^15 is the first power of 2 that gives exact results
+		 * for n between 0 and 256.
+		 */
+		ticks_left = ((u_int)n * 39099 + (1 << 15) - 1) >> 15;
+	else
+		/*
+		 * Don't bother using fixed point, although gcc-2.7.2
+		 * generates particularly poor code for the long long
+		 * division, since even the slow way will complete long
+		 * before the delay is up (unless we're interrupted).
+		 */
+		ticks_left = ((u_int)n * (long long)timer_freq + 999999)
+			     / 1000000;
+
+	while (ticks_left > 0) {
+#ifdef KDB
+		if (kdb_active) {
+			inb(0x84);
+			tick = prev_tick - 1;
+			if (tick <= 0)
+				tick = timer0_max_count;
+		} else
+#endif
+			tick = getit();
+#ifdef DELAYDEBUG
+		++getit_calls;
+#endif
+		delta = prev_tick - tick;
+		prev_tick = tick;
+		if (delta < 0) {
+			delta += timer0_max_count;
+			/*
+			 * Guard against timer0_max_count being wrong.
+			 * This shouldn't happen in normal operation,
+			 * but it may happen if set_timer_freq() is
+			 * traced.
+			 */
+			if (delta < 0)
+				delta = 0;
+		}
+		ticks_left -= delta;
+	}
+#ifdef DELAYDEBUG
+	if (state == 1)
+		printf(" %d calls to getit() at %d usec each\n",
+		       getit_calls, (n + 5) / getit_calls);
+#endif
+}
+
+static void
+sysbeepstop(void *chan)
+{
+	ppi_spkr_off();		/* disable counter2 output to speaker */
+	timer_spkr_release();
+	beeping = 0;
+}
+
+int
+sysbeep(int pitch, int period)
+{
+	int x = splclock();
+
+	if (timer_spkr_acquire())
+		if (!beeping) {
+			/* Something else owns it. */
+			splx(x);
+			return (-1); /* XXX Should be EBUSY, but nobody cares anyway. */
+		}
+	mtx_lock_spin(&clock_lock);
+	spkr_set_pitch(pitch);
+	mtx_unlock_spin(&clock_lock);
+	if (!beeping) {
+		/* enable counter2 output to speaker */
+		ppi_spkr_on();
+		beeping = period;
+		timeout(sysbeepstop, (void *)NULL, period);
+	}
+	splx(x);
+	return (0);
+}
+
+/*
+ * RTC support routines
+ */
+
+int
+rtcin(reg)
+	int reg;
+{
+	u_char val;
+
+	RTC_LOCK;
+	if (rtc_reg != reg) {
+		inb(0x84);
+		outb(IO_RTC, reg);
+		rtc_reg = reg;
+		inb(0x84);
+	}
+	val = inb(IO_RTC + 1);
+	RTC_UNLOCK;
+	return (val);
+}
+
+static void
+writertc(int reg, u_char val)
+{
+
+	RTC_LOCK;
+	if (rtc_reg != reg) {
+		inb(0x84);
+		outb(IO_RTC, reg);
+		rtc_reg = reg;
+		inb(0x84);
+	}
+	outb(IO_RTC + 1, val);
+	inb(0x84);
+	RTC_UNLOCK;
+}
+
+static __inline int
+readrtc(int port)
+{
+	return(bcd2bin(rtcin(port)));
+}
+
+static u_int
+calibrate_clocks(void)
+{
+	u_int count, prev_count, tot_count;
+	int sec, start_sec, timeout;
+
+	if (bootverbose)
+	        printf("Calibrating clock(s) ... ");
+	if (!(rtcin(RTC_STATUSD) & RTCSD_PWR))
+		goto fail;
+	timeout = 100000000;
+
+	/* Read the mc146818A seconds counter. */
+	for (;;) {
+		if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) {
+			sec = rtcin(RTC_SEC);
+			break;
+		}
+		if (--timeout == 0)
+			goto fail;
+	}
+
+	/* Wait for the mC146818A seconds counter to change. */
+	start_sec = sec;
+	for (;;) {
+		if (!(rtcin(RTC_STATUSA) & RTCSA_TUP)) {
+			sec = rtcin(RTC_SEC);
+			if (sec != start_sec)
+				break;
+		}
+		if (--timeout == 0)
+			goto fail;
+	}
+
+	/* Start keeping track of the i8254 counter. */
+	prev_count = getit();
+	if (prev_count == 0 || prev_count > timer0_max_count)
+		goto fail;
+	tot_count = 0;
+
+	/*
+	 * Wait for the mc146818A seconds counter to change.  Read the i8254
+	 * counter for each iteration since this is convenient and only
+	 * costs a few usec of inaccuracy. The timing of the final reads
+	 * of the counters almost matches the timing of the initial reads,
+	 * so the main cause of inaccuracy is the varying latency from 
+	 * inside getit() or rtcin(RTC_STATUSA) to the beginning of the
+	 * rtcin(RTC_SEC) that returns a changed seconds count.  The
+	 * maximum inaccuracy from this cause is < 10 usec on 486's.
+	 */
+	start_sec = sec;
+	for (;;) {
+		if (!(rtcin(RTC_STATUSA) & RTCSA_TUP))
+			sec = rtcin(RTC_SEC);
+		count = getit();
+		if (count == 0 || count > timer0_max_count)
+			goto fail;
+		if (count > prev_count)
+			tot_count += prev_count - (count - timer0_max_count);
+		else
+			tot_count += prev_count - count;
+		prev_count = count;
+		if (sec != start_sec)
+			break;
+		if (--timeout == 0)
+			goto fail;
+	}
+
+	if (bootverbose) {
+	        printf("i8254 clock: %u Hz\n", tot_count);
+	}
+	return (tot_count);
+
+fail:
+	if (bootverbose)
+	        printf("failed, using default i8254 clock of %u Hz\n",
+		       timer_freq);
+	return (timer_freq);
+}
+
+static void
+set_timer_freq(u_int freq, int intr_freq)
+{
+	int new_timer0_real_max_count;
+
+	i8254_timecounter.tc_frequency = freq;
+	mtx_lock_spin(&clock_lock);
+	timer_freq = freq;
+	if (using_lapic_timer)
+		new_timer0_real_max_count = 0x10000;
+	else
+		new_timer0_real_max_count = TIMER_DIV(intr_freq);
+	if (new_timer0_real_max_count != timer0_real_max_count) {
+		timer0_real_max_count = new_timer0_real_max_count;
+		if (timer0_real_max_count == 0x10000)
+			timer0_max_count = 0xffff;
+		else
+			timer0_max_count = timer0_real_max_count;
+		outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
+		outb(TIMER_CNTR0, timer0_real_max_count & 0xff);
+		outb(TIMER_CNTR0, timer0_real_max_count >> 8);
+	}
+	mtx_unlock_spin(&clock_lock);
+}
+
+/* This is separate from startrtclock() so that it can be called early. */
+void
+i8254_init(void)
+{
+
+	mtx_init(&clock_lock, "clk", NULL, MTX_SPIN);
+	set_timer_freq(timer_freq, hz);
+}
+
+void
+startrtclock()
+{
+	u_int delta, freq;
+
+	writertc(RTC_STATUSA, rtc_statusa);
+	writertc(RTC_STATUSB, RTCSB_24HR);
+
+	freq = calibrate_clocks();
+#ifdef CLK_CALIBRATION_LOOP
+	if (bootverbose) {
+		printf(
+		"Press a key on the console to abort clock calibration\n");
+		while (cncheckc() == -1)
+			calibrate_clocks();
+	}
+#endif
+
+	/*
+	 * Use the calibrated i8254 frequency if it seems reasonable.
+	 * Otherwise use the default, and don't use the calibrated i586
+	 * frequency.
+	 */
+	delta = freq > timer_freq ? freq - timer_freq : timer_freq - freq;
+	if (delta < timer_freq / 100) {
+#ifndef CLK_USE_I8254_CALIBRATION
+		if (bootverbose)
+			printf(
+"CLK_USE_I8254_CALIBRATION not specified - using default frequency\n");
+		freq = timer_freq;
+#endif
+		timer_freq = freq;
+	} else {
+		if (bootverbose)
+			printf(
+		    "%d Hz differs from default of %d Hz by more than 1%%\n",
+			       freq, timer_freq);
+	}
+
+	set_timer_freq(timer_freq, hz);
+	tc_init(&i8254_timecounter);
+
+	init_TSC();
+}
+
+/*
+ * Initialize the time of day register, based on the time base which is, e.g.
+ * from a filesystem.
+ */
+void
+inittodr(time_t base)
+{
+	unsigned long	sec, days;
+	int		year, month;
+	int		y, m, s;
+	struct timespec ts;
+
+	if (base) {
+		s = splclock();
+		ts.tv_sec = base;
+		ts.tv_nsec = 0;
+		tc_setclock(&ts);
+		splx(s);
+	}
+
+	/* Look if we have a RTC present and the time is valid */
+	if (!(rtcin(RTC_STATUSD) & RTCSD_PWR))
+		goto wrong_time;
+
+	/* wait for time update to complete */
+	/* If RTCSA_TUP is zero, we have at least 244us before next update */
+	s = splhigh();
+	while (rtcin(RTC_STATUSA) & RTCSA_TUP) {
+		splx(s);
+		s = splhigh();
+	}
+
+	days = 0;
+#ifdef USE_RTC_CENTURY
+	year = readrtc(RTC_YEAR) + readrtc(RTC_CENTURY) * 100;
+#else
+	year = readrtc(RTC_YEAR) + 1900;
+	if (year < 1970)
+		year += 100;
+#endif
+	if (year < 1970) {
+		splx(s);
+		goto wrong_time;
+	}
+	month = readrtc(RTC_MONTH);
+	for (m = 1; m < month; m++)
+		days += daysinmonth[m-1];
+	if ((month > 2) && LEAPYEAR(year))
+		days ++;
+	days += readrtc(RTC_DAY) - 1;
+	for (y = 1970; y < year; y++)
+		days += DAYSPERYEAR + LEAPYEAR(y);
+	sec = ((( days * 24 +
+		  readrtc(RTC_HRS)) * 60 +
+		  readrtc(RTC_MIN)) * 60 +
+		  readrtc(RTC_SEC));
+	/* sec now contains the number of seconds, since Jan 1 1970,
+	   in the local time zone */
+
+	sec += utc_offset();
+
+	y = time_second - sec;
+	if (y <= -2 || y >= 2) {
+		/* badly off, adjust it */
+		ts.tv_sec = sec;
+		ts.tv_nsec = 0;
+		tc_setclock(&ts);
+	}
+	splx(s);
+	return;
+
+wrong_time:
+	printf("Invalid time in real time clock.\n");
+	printf("Check and reset the date immediately!\n");
+}
+
+/*
+ * Write system time back to RTC
+ */
+void
+resettodr()
+{
+	unsigned long	tm;
+	int		y, m, s;
+
+	if (disable_rtc_set)
+		return;
+
+	s = splclock();
+	tm = time_second;
+	splx(s);
+
+	/* Disable RTC updates and interrupts. */
+	writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR);
+
+	/* Calculate local time to put in RTC */
+
+	tm -= utc_offset();
+
+	writertc(RTC_SEC, bin2bcd(tm%60)); tm /= 60;	/* Write back Seconds */
+	writertc(RTC_MIN, bin2bcd(tm%60)); tm /= 60;	/* Write back Minutes */
+	writertc(RTC_HRS, bin2bcd(tm%24)); tm /= 24;	/* Write back Hours   */
+
+	/* We have now the days since 01-01-1970 in tm */
+	writertc(RTC_WDAY, (tm + 4) % 7 + 1);		/* Write back Weekday */
+	for (y = 1970, m = DAYSPERYEAR + LEAPYEAR(y);
+	     tm >= m;
+	     y++,      m = DAYSPERYEAR + LEAPYEAR(y))
+	     tm -= m;
+
+	/* Now we have the years in y and the day-of-the-year in tm */
+	writertc(RTC_YEAR, bin2bcd(y%100));		/* Write back Year    */
+#ifdef USE_RTC_CENTURY
+	writertc(RTC_CENTURY, bin2bcd(y/100));		/* ... and Century    */
+#endif
+	for (m = 0; ; m++) {
+		int ml;
+
+		ml = daysinmonth[m];
+		if (m == 1 && LEAPYEAR(y))
+			ml++;
+		if (tm < ml)
+			break;
+		tm -= ml;
+	}
+
+	writertc(RTC_MONTH, bin2bcd(m + 1));            /* Write back Month   */
+	writertc(RTC_DAY, bin2bcd(tm + 1));             /* Write back Month Day */
+
+	/* Reenable RTC updates and interrupts. */
+	writertc(RTC_STATUSB, rtc_statusb);
+	rtcin(RTC_INTR);
+}
+
+
+/*
+ * Start both clocks running.
+ */
+void
+cpu_initclocks()
+{
+	int diag;
+
+	using_lapic_timer = lapic_setup_clock();
+	/*
+	 * If we aren't using the local APIC timer to drive the kernel
+	 * clocks, setup the interrupt handler for the 8254 timer 0 so
+	 * that it can drive hardclock().  Otherwise, change the 8254
+	 * timecounter to user a simpler algorithm.
+	 */
+	if (!using_lapic_timer) {
+		intr_add_handler("clk", 0, (driver_filter_t *)clkintr, NULL, NULL,
+		    INTR_TYPE_CLK, NULL);
+		i8254_intsrc = intr_lookup_source(0);
+		if (i8254_intsrc != NULL)
+			i8254_pending =
+			    i8254_intsrc->is_pic->pic_source_pending;
+	} else {
+		i8254_timecounter.tc_get_timecount =
+		    i8254_simple_get_timecount;
+		i8254_timecounter.tc_counter_mask = 0xffff;
+		set_timer_freq(timer_freq, hz);
+	}
+
+	/* Initialize RTC. */
+	writertc(RTC_STATUSA, rtc_statusa);
+	writertc(RTC_STATUSB, RTCSB_24HR);
+
+	/*
+	 * If the separate statistics clock hasn't been explicility disabled
+	 * and we aren't already using the local APIC timer to drive the
+	 * kernel clocks, then setup the RTC to periodically interrupt to
+	 * drive statclock() and profclock().
+	 */
+	if (!statclock_disable && !using_lapic_timer) {
+		diag = rtcin(RTC_DIAG);
+		if (diag != 0)
+			printf("RTC BIOS diagnostic error %b\n", diag, RTCDG_BITS);
+
+	        /* Setting stathz to nonzero early helps avoid races. */
+		stathz = RTC_NOPROFRATE;
+		profhz = RTC_PROFRATE;
+
+		/* Enable periodic interrupts from the RTC. */
+		rtc_statusb |= RTCSB_PINTR;
+		intr_add_handler("rtc", 8, (driver_filter_t *)rtcintr, NULL, NULL,
+		    INTR_TYPE_CLK, NULL);
+
+		writertc(RTC_STATUSB, rtc_statusb);
+		rtcin(RTC_INTR);
+	}
+
+	init_TSC_tc();
+}
+
+void
+cpu_startprofclock(void)
+{
+
+	if (using_lapic_timer)
+		return;
+	rtc_statusa = RTCSA_DIVIDER | RTCSA_PROF;
+	writertc(RTC_STATUSA, rtc_statusa);
+	psdiv = pscnt = psratio;
+}
+
+void
+cpu_stopprofclock(void)
+{
+
+	if (using_lapic_timer)
+		return;
+	rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
+	writertc(RTC_STATUSA, rtc_statusa);
+	psdiv = pscnt = 1;
+}
+
+static int
+sysctl_machdep_i8254_freq(SYSCTL_HANDLER_ARGS)
+{
+	int error;
+	u_int freq;
+
+	/*
+	 * Use `i8254' instead of `timer' in external names because `timer'
+	 * is is too generic.  Should use it everywhere.
+	 */
+	freq = timer_freq;
+	error = sysctl_handle_int(oidp, &freq, 0, req);
+	if (error == 0 && req->newptr != NULL)
+		set_timer_freq(freq, hz);
+	return (error);
+}
+
+SYSCTL_PROC(_machdep, OID_AUTO, i8254_freq, CTLTYPE_INT | CTLFLAG_RW,
+    0, sizeof(u_int), sysctl_machdep_i8254_freq, "IU", "");
+
+static unsigned
+i8254_simple_get_timecount(struct timecounter *tc)
+{
+
+	return (timer0_max_count - getit());
+}
+
+static unsigned
+i8254_get_timecount(struct timecounter *tc)
+{
+	u_int count;
+	u_int high, low;
+	u_long rflags;
+
+	rflags = read_rflags();
+	mtx_lock_spin(&clock_lock);
+
+	/* Select timer0 and latch counter value. */
+	outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
+
+	low = inb(TIMER_CNTR0);
+	high = inb(TIMER_CNTR0);
+	count = timer0_max_count - ((high << 8) | low);
+	if (count < i8254_lastcount ||
+	    (!i8254_ticked && (clkintr_pending ||
+	    ((count < 20 || (!(rflags & PSL_I) && count < timer0_max_count / 2u)) &&
+	    i8254_pending != NULL && i8254_pending(i8254_intsrc))))) {
+		i8254_ticked = 1;
+		i8254_offset += timer0_max_count;
+	}
+	i8254_lastcount = count;
+	count += i8254_offset;
+	mtx_unlock_spin(&clock_lock);
+	return (count);
+}
+
+#ifdef DEV_ISA
+/*
+ * Attach to the ISA PnP descriptors for the timer and realtime clock.
+ */
+static struct isa_pnp_id attimer_ids[] = {
+	{ 0x0001d041 /* PNP0100 */, "AT timer" },
+	{ 0x000bd041 /* PNP0B00 */, "AT realtime clock" },
+	{ 0 }
+};
+
+static int
+attimer_probe(device_t dev)
+{
+	int result;
+	
+	if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, attimer_ids)) <= 0)
+		device_quiet(dev);
+	return(result);
+}
+
+static int
+attimer_attach(device_t dev)
+{
+	return(0);
+}
+
+static device_method_t attimer_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		attimer_probe),
+	DEVMETHOD(device_attach,	attimer_attach),
+	DEVMETHOD(device_detach,	bus_generic_detach),
+	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
+	DEVMETHOD(device_suspend,	bus_generic_suspend),	/* XXX stop statclock? */
+	DEVMETHOD(device_resume,	bus_generic_resume),	/* XXX restart statclock? */
+	{ 0, 0 }
+};
+
+static driver_t attimer_driver = {
+	"attimer",
+	attimer_methods,
+	1,		/* no softc */
+};
+
+static devclass_t attimer_devclass;
+
+DRIVER_MODULE(attimer, isa, attimer_driver, attimer_devclass, 0, 0);
+DRIVER_MODULE(attimer, acpi, attimer_driver, attimer_devclass, 0, 0);
+
+/*
+ * Linux-style /dev/nvram driver
+ *
+ * cmos ram starts at bytes 14 through 128, for a total of 114 bytes.
+ * bytes 16 through 31 are checksummed at byte 32.
+ * Unlike Linux, you have to take care of the checksums yourself.
+ * The driver exposes byte 14 as file offset 0.
+ */
+
+#define NVRAM_FIRST	RTC_DIAG	/* 14 */
+#define NVRAM_LAST	128
+
+static d_open_t		nvram_open;
+static d_read_t		nvram_read;
+static d_write_t	nvram_write;
+
+static struct cdev *nvram_dev;
+
+static struct cdevsw nvram_cdevsw = {
+	.d_version =	D_VERSION,
+	.d_flags =	D_NEEDGIANT,
+	.d_open =	nvram_open,
+	.d_read =	nvram_read,
+	.d_write =	nvram_write,
+	.d_name =	"nvram",
+};
+
+static int
+nvram_open(struct cdev *dev __unused, int flags, int fmt __unused,
+    struct thread *td)
+{
+	int error = 0;
+
+	if (flags & FWRITE)
+		error = securelevel_gt(td->td_ucred, 0);
+
+	return (error);
+}
+
+static int
+nvram_read(struct cdev *dev, struct uio *uio, int flags)
+{
+	int nv_off;
+	u_char v;
+	int error = 0;
+
+	while (uio->uio_resid > 0 && error == 0) {
+		nv_off = uio->uio_offset + NVRAM_FIRST;
+		if (nv_off < NVRAM_FIRST || nv_off >= NVRAM_LAST)
+			return (0);	/* Signal EOF */
+		/* Single byte at a time */
+		v = rtcin(nv_off);
+		error = uiomove(&v, 1, uio);
+	}
+	return (error);
+
+}
+
+static int
+nvram_write(struct cdev *dev, struct uio *uio, int flags)
+{
+	int nv_off;
+	u_char v;
+	int error = 0;
+
+	while (uio->uio_resid > 0 && error == 0) {
+		nv_off = uio->uio_offset + NVRAM_FIRST;
+		if (nv_off < NVRAM_FIRST || nv_off >= NVRAM_LAST)
+			return (0);	/* Signal EOF */
+		/* Single byte at a time */
+		error = uiomove(&v, 1, uio);
+		writertc(nv_off, v);
+	}
+	return (error);
+}
+
+static int
+nvram_modevent(module_t mod __unused, int type, void *data __unused)
+{
+	switch (type) {
+	case MOD_LOAD:
+		nvram_dev = make_dev(&nvram_cdevsw, 0,
+		    UID_ROOT, GID_KMEM, 0640, "nvram");
+		break;
+	case MOD_UNLOAD:
+	case MOD_SHUTDOWN:
+		destroy_dev(nvram_dev);
+		break;
+	default:
+		return (EOPNOTSUPP);
+	}
+	return (0);
+}
+DEV_MODULE(nvram, nvram_modevent, NULL);
+
+#endif /* DEV_ISA */
Index: sys/platform/pc64/isa/elcr.c
===================================================================
RCS file: sys/platform/pc64/isa/elcr.c
diff -N sys/platform/pc64/isa/elcr.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/platform/pc64/isa/elcr.c	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,139 @@
+/*-
+ * Copyright (c) 2004 John Baldwin <jhb@FreeBSD.org>
+ * 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 author nor the names of any co-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
+ * 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
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/amd64/isa/elcr.c,v 1.2 2005/01/21 06:01:20 peter Exp $");
+
+/*
+ * The ELCR is a register that controls the trigger mode and polarity of
+ * EISA and ISA interrupts.  In FreeBSD 3.x and 4.x, the ELCR was only
+ * consulted for determining the appropriate trigger mode of EISA
+ * interrupts when using an APIC.  However, it seems that almost all
+ * systems that include PCI also include an ELCR that manages the ISA
+ * IRQs 0 through 15.  Thus, we check for the presence of an ELCR on
+ * every machine by checking to see if the values found at bootup are
+ * sane.  Note that the polarity of ISA and EISA IRQs are linked to the
+ * trigger mode.  All edge triggered IRQs use active-hi polarity, and
+ * all level triggered interrupts use active-lo polarity.
+ *
+ * The format of the ELCR is simple: it is a 16-bit bitmap where bit 0
+ * controls IRQ 0, bit 1 controls IRQ 1, etc.  If the bit is zero, the
+ * associated IRQ is edge triggered.  If the bit is one, the IRQ is
+ * level triggered.
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/systm.h>
+#include <machine/intr_machdep.h>
+
+#define	ELCR_PORT	0x4d0
+#define	ELCR_MASK(irq)	(1 << (irq))
+
+static int elcr_status;
+int elcr_found;
+
+/*
+ * Check to see if we have what looks like a valid ELCR.  We do this by
+ * verifying that IRQs 0, 1, 2, and 13 are all edge triggered.
+ */
+int
+elcr_probe(void)
+{
+	int i;
+
+	elcr_status = inb(ELCR_PORT) | inb(ELCR_PORT + 1) << 8;
+	if ((elcr_status & (ELCR_MASK(0) | ELCR_MASK(1) | ELCR_MASK(2) |
+	    ELCR_MASK(8) | ELCR_MASK(13))) != 0)
+		return (ENXIO);
+	if (bootverbose) {
+		printf("ELCR Found.  ISA IRQs programmed as:\n");
+		for (i = 0; i < 16; i++)
+			printf(" %2d", i);
+		printf("\n");
+		for (i = 0; i < 16; i++)
+			if (elcr_status & ELCR_MASK(i))
+				printf("  L");
+			else
+				printf("  E");
+		printf("\n");
+	}
+	if (resource_disabled("elcr", 0))
+		return (ENXIO);
+	elcr_found = 1;
+	return (0);
+}
+
+/*
+ * Returns 1 for level trigger, 0 for edge.
+ */
+enum intr_trigger
+elcr_read_trigger(u_int irq)
+{
+
+	KASSERT(elcr_found, ("%s: no ELCR was found!", __func__));
+	KASSERT(irq <= 15, ("%s: invalid IRQ %u", __func__, irq));
+	if (elcr_status & ELCR_MASK(irq))
+		return (INTR_TRIGGER_LEVEL);
+	else
+		return (INTR_TRIGGER_EDGE);
+}
+
+/*
+ * Set the trigger mode for a specified IRQ.  Mode of 0 means edge triggered,
+ * and a mode of 1 means level triggered.
+ */
+void
+elcr_write_trigger(u_int irq, enum intr_trigger trigger)
+{
+	int new_status;
+
+	KASSERT(elcr_found, ("%s: no ELCR was found!", __func__));
+	KASSERT(irq <= 15, ("%s: invalid IRQ %u", __func__, irq));
+	if (trigger == INTR_TRIGGER_LEVEL)
+		new_status = elcr_status | ELCR_MASK(irq);
+	else
+		new_status = elcr_status & ~ELCR_MASK(irq);
+	if (new_status == elcr_status)
+		return;
+	elcr_status = new_status;
+	if (irq >= 8)
+		outb(ELCR_PORT + 1, elcr_status >> 8);
+	else
+		outb(ELCR_PORT, elcr_status & 0xff);
+}
+
+void
+elcr_resume(void)
+{
+
+	KASSERT(elcr_found, ("%s: no ELCR was found!", __func__));
+	outb(ELCR_PORT, elcr_status & 0xff);
+	outb(ELCR_PORT + 1, elcr_status >> 8);
+}
Index: sys/platform/pc64/isa/icu.h
===================================================================
RCS file: sys/platform/pc64/isa/icu.h
diff -N sys/platform/pc64/isa/icu.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/platform/pc64/isa/icu.h	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,49 @@
+/*-
+ * 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.
+ * 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: @(#)icu.h	5.6 (Berkeley) 5/9/91
+ * $FreeBSD: src/sys/amd64/isa/icu.h,v 1.36 2006/12/17 21:51:44 kmacy Exp $
+ */
+
+/*
+ * AT/386 Interrupt Control constants
+ * W. Jolitz 8/89
+ */
+
+#ifndef _AMD64_ISA_ICU_H_
+#define	_AMD64_ISA_ICU_H_
+
+#define	ICU_IMR_OFFSET	1
+
+void	atpic_handle_intr(u_int vector, struct trapframe *frame);
+void	atpic_startup(void);
+
+#endif /* !_AMD64_ISA_ICU_H_ */
Index: sys/platform/pc64/isa/isa.c
===================================================================
RCS file: sys/platform/pc64/isa/isa.c
diff -N sys/platform/pc64/isa/isa.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/platform/pc64/isa/isa.c	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,167 @@
+/*-
+ * Copyright (c) 1998 Doug Rabson
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/amd64/isa/isa.c,v 1.149 2007/02/23 12:18:26 piso Exp $");
+
+/*-
+ * Modifications for Intel architecture by Garrett A. Wollman.
+ * Copyright 1998 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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.
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+
+#include <machine/resource.h>
+
+#include <isa/isavar.h>
+#include <isa/isa_common.h>
+
+void
+isa_init(device_t dev)
+{
+}
+
+/*
+ * This implementation simply passes the request up to the parent
+ * bus, which in our case is the special i386 nexus, substituting any
+ * configured values if the caller defaulted.  We can get away with
+ * this because there is no special mapping for ISA resources on an Intel
+ * platform.  When porting this code to another architecture, it may be
+ * necessary to interpose a mapping layer here.
+ */
+struct resource *
+isa_alloc_resource(device_t bus, device_t child, int type, int *rid,
+		   u_long start, u_long end, u_long count, u_int flags)
+{
+	/*
+	 * Consider adding a resource definition.
+	 */
+	int passthrough = (device_get_parent(child) != bus);
+	int isdefault = (start == 0UL && end == ~0UL);
+	struct isa_device* idev = DEVTOISA(child);
+	struct resource_list *rl = &idev->id_resources;
+	struct resource_list_entry *rle;
+	
+	if (!passthrough && !isdefault) {
+		rle = resource_list_find(rl, type, *rid);
+		if (!rle) {
+			if (*rid < 0)
+				return 0;
+			switch (type) {
+			case SYS_RES_IRQ:
+				if (*rid >= ISA_NIRQ)
+					return 0;
+				break;
+			case SYS_RES_DRQ:
+				if (*rid >= ISA_NDRQ)
+					return 0;
+				break;
+			case SYS_RES_MEMORY:
+				if (*rid >= ISA_NMEM)
+					return 0;
+				break;
+			case SYS_RES_IOPORT:
+				if (*rid >= ISA_NPORT)
+					return 0;
+				break;
+			default:
+				return 0;
+			}
+			resource_list_add(rl, type, *rid, start, end, count);
+		}
+	}
+
+	return resource_list_alloc(rl, bus, child, type, rid,
+				   start, end, count, flags);
+}
+
+int
+isa_release_resource(device_t bus, device_t child, int type, int rid,
+		     struct resource *r)
+{
+	struct isa_device* idev = DEVTOISA(child);
+	struct resource_list *rl = &idev->id_resources;
+
+	return resource_list_release(rl, bus, child, type, rid, r);
+}
+
+/*
+ * We can't use the bus_generic_* versions of these methods because those
+ * methods always pass the bus param as the requesting device, and we need
+ * to pass the child (the i386 nexus knows about this and is prepared to
+ * deal).
+ */
+int
+isa_setup_intr(device_t bus, device_t child, struct resource *r, int flags,
+	       driver_filter_t *filter, void (*ihand)(void *), void *arg, 
+	       void **cookiep)
+{
+	return (BUS_SETUP_INTR(device_get_parent(bus), child, r, flags,
+			       filter, ihand, arg, cookiep));
+}
+
+int
+isa_teardown_intr(device_t bus, device_t child, struct resource *r,
+		  void *cookie)
+{
+	return (BUS_TEARDOWN_INTR(device_get_parent(bus), child, r, cookie));
+}
+
+/*
+ * On this platform, isa can also attach to the legacy bus.
+ */
+DRIVER_MODULE(isa, legacy, isa_driver, isa_devclass, 0, 0);
Index: sys/platform/pc64/isa/isa.h
===================================================================
RCS file: sys/platform/pc64/isa/isa.h
diff -N sys/platform/pc64/isa/isa.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/platform/pc64/isa/isa.h	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,80 @@
+/*-
+ * 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.
+ * 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: @(#)isa.h	5.7 (Berkeley) 5/9/91
+ * $FreeBSD: src/sys/amd64/isa/isa.h,v 1.29 2005/05/14 10:14:56 nyan Exp $
+ */
+
+#ifndef _I386_ISA_ISA_H_
+#define	_I386_ISA_ISA_H_
+
+/* BEWARE:  Included in both assembler and C code */
+
+/*
+ * ISA Bus conventions
+ */
+
+/*
+ * Input / Output Port Assignments
+ */
+#ifndef IO_ISABEGIN
+#define	IO_ISABEGIN	0x000		/* 0x000 - Beginning of I/O Registers */
+
+		/* CPU Board */
+#define	IO_ICU1		0x020		/* 8259A Interrupt Controller #1 */
+#define	IO_PMP1		0x026		/* 82347 Power Management Peripheral */
+#define	IO_KBD		0x060		/* 8042 Keyboard */
+#define	IO_RTC		0x070		/* RTC */
+#define	IO_NMI		IO_RTC		/* NMI Control */
+#define	IO_ICU2		0x0A0		/* 8259A Interrupt Controller #2 */
+
+		/* Cards */
+#define	IO_VGA		0x3C0		/* E/VGA Ports */
+#define	IO_CGA		0x3D0		/* CGA Ports */
+#define	IO_MDA		0x3B0		/* Monochome Adapter */
+
+#define	IO_ISAEND	0x3FF		/* End (actually Max) of I/O Regs */
+#endif /* !IO_ISABEGIN */
+
+/*
+ * Input / Output Port Sizes - these are from several sources, and tend
+ * to be the larger of what was found.
+ */
+#ifndef	IO_ISASIZES
+#define	IO_ISASIZES
+
+#define	IO_CGASIZE	12		/* CGA controllers */
+#define	IO_MDASIZE	12		/* Monochrome display controllers */
+#define	IO_VGASIZE	16		/* VGA controllers */
+
+#endif /* !IO_ISASIZES */
+
+#endif /* !_I386_ISA_ISA_H_ */
Index: sys/platform/pc64/isa/isa_dma.c
===================================================================
RCS file: sys/platform/pc64/isa/isa_dma.c
diff -N sys/platform/pc64/isa/isa_dma.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/platform/pc64/isa/isa_dma.c	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,555 @@
+/*-
+ * Copyright (c) 1991 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.
+ * 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: @(#)isa.c	7.2 (Berkeley) 5/13/91
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/amd64/isa/isa_dma.c,v 1.22 2005/05/14 10:14:56 nyan Exp $");
+
+/*
+ * code to manage AT bus
+ *
+ * 92/08/18  Frank P. MacLachlan (fpm@crash.cts.com):
+ * Fixed uninitialized variable problem and added code to deal
+ * with DMA page boundaries in isa_dmarangecheck().  Fixed word
+ * mode DMA count compution and reorganized DMA setup code in
+ * isa_dmastart()
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+#include <sys/mutex.h>
+#include <sys/module.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <isa/isareg.h>
+#include <isa/isavar.h>
+#include <isa/isa_dmareg.h>
+
+#define ISARAM_END	0x1000000
+
+static int isa_dmarangecheck(caddr_t va, u_int length, int chan);
+
+static caddr_t	dma_bouncebuf[8];
+static u_int	dma_bouncebufsize[8];
+static u_int8_t	dma_bounced = 0;
+static u_int8_t	dma_busy = 0;		/* Used in isa_dmastart() */
+static u_int8_t	dma_inuse = 0;		/* User for acquire/release */
+static u_int8_t dma_auto_mode = 0;
+
+#define VALID_DMA_MASK (7)
+
+/* high byte of address is stored in this port for i-th dma channel */
+static int dmapageport[8] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a };
+
+/*
+ * Setup a DMA channel's bounce buffer.
+ */
+int
+isa_dma_init(int chan, u_int bouncebufsize, int flag)
+{
+	void *buf;
+
+	/*
+	 * If a DMA channel is shared, both drivers have to call isa_dma_init
+	 * since they don't know that the other driver will do it.
+	 * Just return if we're already set up good.
+	 * XXX: this only works if they agree on the bouncebuf size.  This
+	 * XXX: is typically the case since they are multiple instances of
+	 * XXX: the same driver.
+	 */
+	if (dma_bouncebuf[chan] != NULL)
+		return (0);
+
+#ifdef DIAGNOSTIC
+	if (chan & ~VALID_DMA_MASK)
+		panic("isa_dma_init: channel out of range");
+#endif
+
+	dma_bouncebufsize[chan] = bouncebufsize;
+
+	/* Try malloc() first.  It works better if it works. */
+	buf = malloc(bouncebufsize, M_DEVBUF, flag);
+	if (buf != NULL) {
+		if (isa_dmarangecheck(buf, bouncebufsize, chan) == 0) {
+			dma_bouncebuf[chan] = buf;
+			return (0);
+		}
+		free(buf, M_DEVBUF);
+	}
+	buf = contigmalloc(bouncebufsize, M_DEVBUF, flag, 0ul, 0xfffffful,
+			   1ul, chan & 4 ? 0x20000ul : 0x10000ul);
+	if (buf == NULL)
+		return (ENOMEM);
+	dma_bouncebuf[chan] = buf;
+	return (0);
+}
+
+/*
+ * Register a DMA channel's usage.  Usually called from a device driver
+ * in open() or during its initialization.
+ */
+int
+isa_dma_acquire(chan)
+	int chan;
+{
+#ifdef DIAGNOSTIC
+	if (chan & ~VALID_DMA_MASK)
+		panic("isa_dma_acquire: channel out of range");
+#endif
+
+	if (dma_inuse & (1 << chan)) {
+		printf("isa_dma_acquire: channel %d already in use\n", chan);
+		return (EBUSY);
+	}
+	dma_inuse |= (1 << chan);
+	dma_auto_mode &= ~(1 << chan);
+
+	return (0);
+}
+
+/*
+ * Unregister a DMA channel's usage.  Usually called from a device driver
+ * during close() or during its shutdown.
+ */
+void
+isa_dma_release(chan)
+	int chan;
+{
+#ifdef DIAGNOSTIC
+	if (chan & ~VALID_DMA_MASK)
+		panic("isa_dma_release: channel out of range");
+
+	if ((dma_inuse & (1 << chan)) == 0)
+		printf("isa_dma_release: channel %d not in use\n", chan);
+#endif
+
+	if (dma_busy & (1 << chan)) {
+		dma_busy &= ~(1 << chan);
+		/* 
+		 * XXX We should also do "dma_bounced &= (1 << chan);"
+		 * because we are acting on behalf of isa_dmadone() which
+		 * was not called to end the last DMA operation.  This does
+		 * not matter now, but it may in the future.
+		 */
+	}
+
+	dma_inuse &= ~(1 << chan);
+	dma_auto_mode &= ~(1 << chan);
+}
+
+/*
+ * isa_dmacascade(): program 8237 DMA controller channel to accept
+ * external dma control by a board.
+ */
+void
+isa_dmacascade(chan)
+	int chan;
+{
+#ifdef DIAGNOSTIC
+	if (chan & ~VALID_DMA_MASK)
+		panic("isa_dmacascade: channel out of range");
+#endif
+
+	/* set dma channel mode, and set dma channel mode */
+	if ((chan & 4) == 0) {
+		outb(DMA1_MODE, DMA37MD_CASCADE | chan);
+		outb(DMA1_SMSK, chan);
+	} else {
+		outb(DMA2_MODE, DMA37MD_CASCADE | (chan & 3));
+		outb(DMA2_SMSK, chan & 3);
+	}
+}
+
+/*
+ * isa_dmastart(): program 8237 DMA controller channel, avoid page alignment
+ * problems by using a bounce buffer.
+ */
+void
+isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan)
+{
+	vm_paddr_t phys;
+	int waport;
+	caddr_t newaddr;
+
+	GIANT_REQUIRED;
+
+#ifdef DIAGNOSTIC
+	if (chan & ~VALID_DMA_MASK)
+		panic("isa_dmastart: channel out of range");
+
+	if ((chan < 4 && nbytes > (1<<16))
+	    || (chan >= 4 && (nbytes > (1<<17) || (uintptr_t)addr & 1)))
+		panic("isa_dmastart: impossible request");
+
+	if ((dma_inuse & (1 << chan)) == 0)
+		printf("isa_dmastart: channel %d not acquired\n", chan);
+#endif
+
+#if 0
+	/*
+	 * XXX This should be checked, but drivers like ad1848 only call
+	 * isa_dmastart() once because they use Auto DMA mode.  If we
+	 * leave this in, drivers that do this will print this continuously.
+	 */
+	if (dma_busy & (1 << chan))
+		printf("isa_dmastart: channel %d busy\n", chan);
+#endif
+
+	dma_busy |= (1 << chan);
+
+	if (isa_dmarangecheck(addr, nbytes, chan)) {
+		if (dma_bouncebuf[chan] == NULL
+		    || dma_bouncebufsize[chan] < nbytes)
+			panic("isa_dmastart: bad bounce buffer"); 
+		dma_bounced |= (1 << chan);
+		newaddr = dma_bouncebuf[chan];
+
+		/* copy bounce buffer on write */
+		if (!(flags & ISADMA_READ))
+			bcopy(addr, newaddr, nbytes);
+		addr = newaddr;
+	}
+
+	/* translate to physical */
+	phys = pmap_extract(kernel_pmap, (vm_offset_t)addr);
+
+	if (flags & ISADMA_RAW) {
+	    dma_auto_mode |= (1 << chan);
+	} else { 
+	    dma_auto_mode &= ~(1 << chan);
+	}
+
+	if ((chan & 4) == 0) {
+		/*
+		 * Program one of DMA channels 0..3.  These are
+		 * byte mode channels.
+		 */
+		/* set dma channel mode, and reset address ff */
+
+		/* If ISADMA_RAW flag is set, then use autoinitialise mode */
+		if (flags & ISADMA_RAW) {
+		  if (flags & ISADMA_READ)
+			outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_WRITE|chan);
+		  else
+			outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_READ|chan);
+		}
+		else
+		if (flags & ISADMA_READ)
+			outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|chan);
+		else
+			outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_READ|chan);
+		outb(DMA1_FFC, 0);
+
+		/* send start address */
+		waport =  DMA1_CHN(chan);
+		outb(waport, phys);
+		outb(waport, phys>>8);
+		outb(dmapageport[chan], phys>>16);
+
+		/* send count */
+		outb(waport + 1, --nbytes);
+		outb(waport + 1, nbytes>>8);
+
+		/* unmask channel */
+		outb(DMA1_SMSK, chan);
+	} else {
+		/*
+		 * Program one of DMA channels 4..7.  These are
+		 * word mode channels.
+		 */
+		/* set dma channel mode, and reset address ff */
+
+		/* If ISADMA_RAW flag is set, then use autoinitialise mode */
+		if (flags & ISADMA_RAW) {
+		  if (flags & ISADMA_READ)
+			outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_WRITE|(chan&3));
+		  else
+			outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_READ|(chan&3));
+		}
+		else
+		if (flags & ISADMA_READ)
+			outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|(chan&3));
+		else
+			outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_READ|(chan&3));
+		outb(DMA2_FFC, 0);
+
+		/* send start address */
+		waport = DMA2_CHN(chan - 4);
+		outb(waport, phys>>1);
+		outb(waport, phys>>9);
+		outb(dmapageport[chan], phys>>16);
+
+		/* send count */
+		nbytes >>= 1;
+		outb(waport + 2, --nbytes);
+		outb(waport + 2, nbytes>>8);
+
+		/* unmask channel */
+		outb(DMA2_SMSK, chan & 3);
+	}
+}
+
+void
+isa_dmadone(int flags, caddr_t addr, int nbytes, int chan)
+{  
+#ifdef DIAGNOSTIC
+	if (chan & ~VALID_DMA_MASK)
+		panic("isa_dmadone: channel out of range");
+
+	if ((dma_inuse & (1 << chan)) == 0)
+		printf("isa_dmadone: channel %d not acquired\n", chan);
+#endif
+
+	if (((dma_busy & (1 << chan)) == 0) && 
+	    (dma_auto_mode & (1 << chan)) == 0 )
+		printf("isa_dmadone: channel %d not busy\n", chan);
+
+	if ((dma_auto_mode & (1 << chan)) == 0)
+		outb(chan & 4 ? DMA2_SMSK : DMA1_SMSK, (chan & 3) | 4);
+
+	if (dma_bounced & (1 << chan)) {
+		/* copy bounce buffer on read */
+		if (flags & ISADMA_READ)
+			bcopy(dma_bouncebuf[chan], addr, nbytes);
+
+		dma_bounced &= ~(1 << chan);
+	}
+	dma_busy &= ~(1 << chan);
+}
+
+/*
+ * Check for problems with the address range of a DMA transfer
+ * (non-contiguous physical pages, outside of bus address space,
+ * crossing DMA page boundaries).
+ * Return true if special handling needed.
+ */
+
+static int
+isa_dmarangecheck(caddr_t va, u_int length, int chan)
+{
+	vm_paddr_t phys, priorpage = 0;
+	vm_offset_t endva;
+	u_int dma_pgmsk = (chan & 4) ?  ~(128*1024-1) : ~(64*1024-1);
+
+	GIANT_REQUIRED;
+
+	endva = (vm_offset_t)round_page((vm_offset_t)va + length);
+	for (; va < (caddr_t) endva ; va += PAGE_SIZE) {
+		phys = trunc_page(pmap_extract(kernel_pmap, (vm_offset_t)va));
+		if (phys == 0)
+			panic("isa_dmacheck: no physical page present");
+		if (phys >= ISARAM_END)
+			return (1);
+		if (priorpage) {
+			if (priorpage + PAGE_SIZE != phys)
+				return (1);
+			/* check if crossing a DMA page boundary */
+			if (((u_int)priorpage ^ (u_int)phys) & dma_pgmsk)
+				return (1);
+		}
+		priorpage = phys;
+	}
+	return (0);
+}
+
+/*
+ * Query the progress of a transfer on a DMA channel.
+ *
+ * To avoid having to interrupt a transfer in progress, we sample
+ * each of the high and low databytes twice, and apply the following
+ * logic to determine the correct count.
+ *
+ * Reads are performed with interrupts disabled, thus it is to be
+ * expected that the time between reads is very small.  At most
+ * one rollover in the low count byte can be expected within the
+ * four reads that are performed.
+ *
+ * There are three gaps in which a rollover can occur :
+ *
+ * - read low1
+ *              gap1
+ * - read high1
+ *              gap2
+ * - read low2
+ *              gap3
+ * - read high2
+ *
+ * If a rollover occurs in gap1 or gap2, the low2 value will be
+ * greater than the low1 value.  In this case, low2 and high2 are a
+ * corresponding pair. 
+ *
+ * In any other case, low1 and high1 can be considered to be correct.
+ *
+ * The function returns the number of bytes remaining in the transfer,
+ * or -1 if the channel requested is not active.
+ *
+ */
+int
+isa_dmastatus(int chan)
+{
+	u_long	cnt = 0;
+	int	ffport, waport;
+	u_long	low1, high1, low2, high2;
+
+	/* channel active? */
+	if ((dma_inuse & (1 << chan)) == 0) {
+		printf("isa_dmastatus: channel %d not active\n", chan);
+		return(-1);
+	}
+	/* channel busy? */
+
+	if (((dma_busy & (1 << chan)) == 0) &&
+	    (dma_auto_mode & (1 << chan)) == 0 ) {
+	    printf("chan %d not busy\n", chan);
+	    return -2 ;
+	}	
+	if (chan < 4) {			/* low DMA controller */
+		ffport = DMA1_FFC;
+		waport = DMA1_CHN(chan) + 1;
+	} else {			/* high DMA controller */
+		ffport = DMA2_FFC;
+		waport = DMA2_CHN(chan - 4) + 2;
+	}
+
+	disable_intr();			/* no interrupts Mr Jones! */
+	outb(ffport, 0);		/* clear register LSB flipflop */
+	low1 = inb(waport);
+	high1 = inb(waport);
+	outb(ffport, 0);		/* clear again */
+	low2 = inb(waport);
+	high2 = inb(waport);
+	enable_intr();			/* enable interrupts again */
+
+	/* 
+	 * Now decide if a wrap has tried to skew our results.
+	 * Note that after TC, the count will read 0xffff, while we want 
+	 * to return zero, so we add and then mask to compensate.
+	 */
+	if (low1 >= low2) {
+		cnt = (low1 + (high1 << 8) + 1) & 0xffff;
+	} else {
+		cnt = (low2 + (high2 << 8) + 1) & 0xffff;
+	}
+
+	if (chan >= 4)			/* high channels move words */
+		cnt *= 2;
+	return(cnt);
+}
+
+/*
+ * Reached terminal count yet ?
+ */
+int
+isa_dmatc(int chan)
+{
+
+	if (chan < 4)
+		return(inb(DMA1_STATUS) & (1 << chan));
+	else
+		return(inb(DMA2_STATUS) & (1 << (chan & 3)));
+}
+
+/*
+ * Stop a DMA transfer currently in progress.
+ */
+int
+isa_dmastop(int chan) 
+{
+	if ((dma_inuse & (1 << chan)) == 0)
+		printf("isa_dmastop: channel %d not acquired\n", chan);  
+
+	if (((dma_busy & (1 << chan)) == 0) &&
+	    ((dma_auto_mode & (1 << chan)) == 0)) {
+		printf("chan %d not busy\n", chan);
+		return -2 ;
+	}
+    
+	if ((chan & 4) == 0) {
+		outb(DMA1_SMSK, (chan & 3) | 4 /* disable mask */);
+	} else {
+		outb(DMA2_SMSK, (chan & 3) | 4 /* disable mask */);
+	}
+	return(isa_dmastatus(chan));
+}
+
+/*
+ * Attach to the ISA PnP descriptor for the AT DMA controller
+ */
+static struct isa_pnp_id atdma_ids[] = {
+	{ 0x0002d041 /* PNP0200 */, "AT DMA controller" },
+	{ 0 }
+};
+
+static int
+atdma_probe(device_t dev)
+{
+	int result;
+	
+	if ((result = ISA_PNP_PROBE(device_get_parent(dev), dev, atdma_ids)) <= 0)
+		device_quiet(dev);
+	return(result);
+}
+
+static int
+atdma_attach(device_t dev)
+{
+	return(0);
+}
+
+static device_method_t atdma_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		atdma_probe),
+	DEVMETHOD(device_attach,	atdma_attach),
+	DEVMETHOD(device_detach,	bus_generic_detach),
+	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
+	DEVMETHOD(device_suspend,	bus_generic_suspend),
+	DEVMETHOD(device_resume,	bus_generic_resume),
+	{ 0, 0 }
+};
+
+static driver_t atdma_driver = {
+	"atdma",
+	atdma_methods,
+	1,		/* no softc */
+};
+
+static devclass_t atdma_devclass;
+
+DRIVER_MODULE(atdma, isa, atdma_driver, atdma_devclass, 0, 0);
+DRIVER_MODULE(atdma, acpi, atdma_driver, atdma_devclass, 0, 0);
Index: sys/platform/pc64/isa/nmi.c
===================================================================
RCS file: sys/platform/pc64/isa/nmi.c
diff -N sys/platform/pc64/isa/nmi.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/platform/pc64/isa/nmi.c	10 Feb 2008 11:48:09 -0000
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (c) 1991 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.
+ * 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: @(#)isa.c	7.2 (Berkeley) 5/13/91
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/amd64/isa/nmi.c,v 1.80 2004/05/16 20:30:47 peter Exp $");
+
+#include "opt_mca.h"
+
+#include <sys/types.h>
+#include <sys/syslog.h>
+#include <sys/systm.h>
+
+#include <machine/md_var.h>
+
+#define NMI_PARITY (1 << 7)
+#define NMI_IOCHAN (1 << 6)
+#define ENMI_WATCHDOG (1 << 7)
+#define ENMI_BUSTIMER (1 << 6)
+#define ENMI_IOSTATUS (1 << 5)
+
+/*
+ * Handle a NMI, possibly a machine check.
+ * return true to panic system, false to ignore.
+ */
+int
+isa_nmi(int cd)
+{
+	int retval = 0;
+	int isa_port = inb(0x61);
+	int eisa_port = inb(0x461);
+
+	log(LOG_CRIT, "NMI ISA %x, EISA %x\n", isa_port, eisa_port);
+	
+	if (isa_port & NMI_PARITY) {
+		log(LOG_CRIT, "RAM parity error, likely hardware failure.");
+		retval = 1;
+	}
+
+	if (isa_port & NMI_IOCHAN) {
+		log(LOG_CRIT, "I/O channel check, likely hardware failure.");
+		retval = 1;
+	}
+
+	/*
+	 * On a real EISA machine, this will never happen.  However it can
+	 * happen on ISA machines which implement XT style floating point
+	 * error handling (very rare).  Save them from a meaningless panic.
+	 */
+	if (eisa_port == 0xff)
+		return(retval);
+
+	if (eisa_port & ENMI_WATCHDOG) {
+		log(LOG_CRIT, "EISA watchdog timer expired, likely hardware failure.");
+		retval = 1;
+	}
+
+	if (eisa_port & ENMI_BUSTIMER) {
+		log(LOG_CRIT, "EISA bus timeout, likely hardware failure.");
+		retval = 1;
+	}
+
+	if (eisa_port & ENMI_IOSTATUS) {
+		log(LOG_CRIT, "EISA I/O port status error.");
+		retval = 1;
+	}
+
+	return(retval);
+}
Index: sys/sys/imgact_elf.h
===================================================================
RCS file: /home/dcvs/src/sys/sys/imgact_elf.h,v
retrieving revision 1.8
diff -u -r1.8 imgact_elf.h
--- sys/sys/imgact_elf.h	12 Dec 2007 23:29:20 -0000	1.8
+++ sys/sys/imgact_elf.h	10 Feb 2008 11:48:09 -0000
@@ -93,6 +93,7 @@
 typedef struct {
 	int brand;
 	const char *compat_3_brand;	/* pre Binutils 2.10 method (FBSD 3) */
+	int (*match_abi_note)(const Elf_Note *);
 	const char *emul_path;
 	const char *interp_path;
         struct sysentvec *sysvec;
Index: sys/sys/systm.h
===================================================================
RCS file: /home/dcvs/src/sys/sys/systm.h,v
retrieving revision 1.77
diff -u -r1.77 systm.h
--- sys/sys/systm.h	25 Nov 2007 00:13:28 -0000	1.77
+++ sys/sys/systm.h	10 Feb 2008 11:48:09 -0000
@@ -95,10 +95,6 @@
 extern int ncpus_fit_mask;	/* ncpus_fit - 1 */
 extern int clocks_running;	/* timing/timeout subsystem is operational */
 
-/* XXX TGEN these don't belong here, they're MD on i386/amd64 */
-extern u_int cpu_feature;	/* CPUID_* features */
-extern u_int cpu_feature2;	/* CPUID2_* features */
-
 extern int nfs_diskless_valid;	/* NFS diskless params were obtained */
 extern vm_paddr_t Maxmem;	/* Highest physical memory address in system */
 
