summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/amd64/Makefile10
-rw-r--r--sys/arch/amd64/amd64/Locore.c88
-rw-r--r--sys/arch/amd64/amd64/autoconf.c606
-rw-r--r--sys/arch/amd64/amd64/bus_dma.c709
-rw-r--r--sys/arch/amd64/amd64/bus_space.c473
-rw-r--r--sys/arch/amd64/amd64/cacheinfo.c237
-rw-r--r--sys/arch/amd64/amd64/conf.c455
-rw-r--r--sys/arch/amd64/amd64/consinit.c61
-rw-r--r--sys/arch/amd64/amd64/copy.S321
-rw-r--r--sys/arch/amd64/amd64/cpu.c699
-rw-r--r--sys/arch/amd64/amd64/db_disasm.c56
-rw-r--r--sys/arch/amd64/amd64/db_interface.c303
-rw-r--r--sys/arch/amd64/amd64/db_memrw.c211
-rw-r--r--sys/arch/amd64/amd64/db_trace.c412
-rw-r--r--sys/arch/amd64/amd64/disksubr.c550
-rw-r--r--sys/arch/amd64/amd64/fpu.c309
-rw-r--r--sys/arch/amd64/amd64/gdt.c374
-rw-r--r--sys/arch/amd64/amd64/genassym.cf122
-rw-r--r--sys/arch/amd64/amd64/i8259.c255
-rw-r--r--sys/arch/amd64/amd64/identcpu.c105
-rw-r--r--sys/arch/amd64/amd64/intr.c707
-rw-r--r--sys/arch/amd64/amd64/locore.S1243
-rw-r--r--sys/arch/amd64/amd64/machdep.c1874
-rw-r--r--sys/arch/amd64/amd64/mainbus.c190
-rw-r--r--sys/arch/amd64/amd64/mem.c266
-rw-r--r--sys/arch/amd64/amd64/microtime.S111
-rw-r--r--sys/arch/amd64/amd64/pmap.c3835
-rw-r--r--sys/arch/amd64/amd64/process_machdep.c193
-rw-r--r--sys/arch/amd64/amd64/softintr.c168
-rw-r--r--sys/arch/amd64/amd64/spl.S184
-rw-r--r--sys/arch/amd64/amd64/swapgeneric.c57
-rw-r--r--sys/arch/amd64/amd64/sys_machdep.c466
-rw-r--r--sys/arch/amd64/amd64/syscall.c341
-rw-r--r--sys/arch/amd64/amd64/trap.c579
-rw-r--r--sys/arch/amd64/amd64/vector.S821
-rw-r--r--sys/arch/amd64/amd64/vm_machdep.c379
-rw-r--r--sys/arch/amd64/amd64/wscons_machdep.c169
-rw-r--r--sys/arch/amd64/compile/.cvsignore1
-rw-r--r--sys/arch/amd64/conf/GENERIC73
-rw-r--r--sys/arch/amd64/conf/Makefile.amd64214
-rw-r--r--sys/arch/amd64/conf/files.amd64145
-rw-r--r--sys/arch/amd64/include/ansi.h87
-rw-r--r--sys/arch/amd64/include/apicvar.h58
-rw-r--r--sys/arch/amd64/include/apmvar.h300
-rw-r--r--sys/arch/amd64/include/asm.h122
-rw-r--r--sys/arch/amd64/include/atomic.h96
-rw-r--r--sys/arch/amd64/include/biosvar.h259
-rw-r--r--sys/arch/amd64/include/bootinfo.h159
-rw-r--r--sys/arch/amd64/include/bus.h1158
-rw-r--r--sys/arch/amd64/include/cacheinfo.h111
-rw-r--r--sys/arch/amd64/include/cdefs.h23
-rw-r--r--sys/arch/amd64/include/conf.h45
-rw-r--r--sys/arch/amd64/include/cpu.h376
-rw-r--r--sys/arch/amd64/include/cpufunc.h280
-rw-r--r--sys/arch/amd64/include/cpuvar.h109
-rw-r--r--sys/arch/amd64/include/db_machdep.h141
-rw-r--r--sys/arch/amd64/include/disklabel.h118
-rw-r--r--sys/arch/amd64/include/endian.h67
-rw-r--r--sys/arch/amd64/include/exec.h22
-rw-r--r--sys/arch/amd64/include/float.h77
-rw-r--r--sys/arch/amd64/include/fpu.h84
-rw-r--r--sys/arch/amd64/include/frame.h175
-rw-r--r--sys/arch/amd64/include/frameasm.h94
-rw-r--r--sys/arch/amd64/include/gdt.h62
-rw-r--r--sys/arch/amd64/include/i82093reg.h121
-rw-r--r--sys/arch/amd64/include/i82093var.h104
-rw-r--r--sys/arch/amd64/include/i82489reg.h150
-rw-r--r--sys/arch/amd64/include/i8259.h152
-rw-r--r--sys/arch/amd64/include/ieee.h133
-rw-r--r--sys/arch/amd64/include/ieeefp.h26
-rw-r--r--sys/arch/amd64/include/internal_types.h10
-rw-r--r--sys/arch/amd64/include/intr.h356
-rw-r--r--sys/arch/amd64/include/intrdefs.h93
-rw-r--r--sys/arch/amd64/include/isa_machdep.h237
-rw-r--r--sys/arch/amd64/include/kcore.h49
-rw-r--r--sys/arch/amd64/include/limits.h57
-rw-r--r--sys/arch/amd64/include/loadfile_machdep.h60
-rw-r--r--sys/arch/amd64/include/mcontext.h108
-rw-r--r--sys/arch/amd64/include/mpbiosreg.h138
-rw-r--r--sys/arch/amd64/include/mpbiosvar.h62
-rw-r--r--sys/arch/amd64/include/mpconfig.h65
-rw-r--r--sys/arch/amd64/include/mtrr.h160
-rw-r--r--sys/arch/amd64/include/param.h173
-rw-r--r--sys/arch/amd64/include/pcb.h130
-rw-r--r--sys/arch/amd64/include/pci_machdep.h110
-rw-r--r--sys/arch/amd64/include/pic.h40
-rw-r--r--sys/arch/amd64/include/pio.h232
-rw-r--r--sys/arch/amd64/include/pmap.h592
-rw-r--r--sys/arch/amd64/include/proc.h63
-rw-r--r--sys/arch/amd64/include/profile.h65
-rw-r--r--sys/arch/amd64/include/psl.h87
-rw-r--r--sys/arch/amd64/include/pte.h137
-rw-r--r--sys/arch/amd64/include/ptrace.h41
-rw-r--r--sys/arch/amd64/include/reg.h102
-rw-r--r--sys/arch/amd64/include/segments.h305
-rw-r--r--sys/arch/amd64/include/setjmp.h21
-rw-r--r--sys/arch/amd64/include/signal.h88
-rw-r--r--sys/arch/amd64/include/specialreg.h604
-rw-r--r--sys/arch/amd64/include/spinlock.h10
-rw-r--r--sys/arch/amd64/include/stdarg.h57
-rw-r--r--sys/arch/amd64/include/sysarch.h120
-rw-r--r--sys/arch/amd64/include/trap.h74
-rw-r--r--sys/arch/amd64/include/tss.h62
-rw-r--r--sys/arch/amd64/include/types.h81
-rw-r--r--sys/arch/amd64/include/userret.h99
-rw-r--r--sys/arch/amd64/include/vmparam.h132
-rw-r--r--sys/arch/amd64/isa/clock.c765
-rw-r--r--sys/arch/amd64/isa/isa_machdep.c1026
-rw-r--r--sys/arch/amd64/pci/pchb.c130
-rw-r--r--sys/arch/amd64/pci/pchbvar.h61
-rw-r--r--sys/arch/amd64/pci/pci_machdep.c693
-rw-r--r--sys/arch/amd64/pci/pciide_machdep.c76
-rw-r--r--sys/compat/common/Makefile5
-rw-r--r--sys/dev/isa/isavar.h7
-rw-r--r--sys/dev/pci/pcivar.h7
-rw-r--r--sys/lib/libkern/arch/amd64/Makefile.inc14
-rw-r--r--sys/lib/libkern/arch/amd64/bcmp.S24
-rw-r--r--sys/lib/libkern/arch/amd64/bcopy.S101
-rw-r--r--sys/lib/libkern/arch/amd64/byte_swap_2.S52
-rw-r--r--sys/lib/libkern/arch/amd64/byte_swap_4.S52
-rw-r--r--sys/lib/libkern/arch/amd64/bzero.S44
-rw-r--r--sys/lib/libkern/arch/amd64/ffs.S21
-rw-r--r--sys/lib/libkern/arch/amd64/index.S29
-rw-r--r--sys/lib/libkern/arch/amd64/memchr.S25
-rw-r--r--sys/lib/libkern/arch/amd64/memcmp.S40
-rw-r--r--sys/lib/libkern/arch/amd64/memcpy.S4
-rw-r--r--sys/lib/libkern/arch/amd64/memmove.S4
-rw-r--r--sys/lib/libkern/arch/amd64/memset.S58
-rw-r--r--sys/lib/libkern/arch/amd64/ovbcopy.S4
-rw-r--r--sys/lib/libkern/arch/amd64/rindex.S29
-rw-r--r--sys/lib/libkern/arch/amd64/scanc.S62
-rw-r--r--sys/lib/libkern/arch/amd64/skpc.S56
-rw-r--r--sys/lib/libkern/arch/amd64/strcat.S65
-rw-r--r--sys/lib/libkern/arch/amd64/strchr.S4
-rw-r--r--sys/lib/libkern/arch/amd64/strcmp.S88
-rw-r--r--sys/lib/libkern/arch/amd64/strcpy.S57
-rw-r--r--sys/lib/libkern/arch/amd64/strlen.S21
-rw-r--r--sys/lib/libkern/arch/amd64/strrchr.S4
-rw-r--r--sys/lib/libkern/arch/x86_64/Makefile.inc14
-rw-r--r--sys/lib/libkern/arch/x86_64/bcmp.S24
-rw-r--r--sys/lib/libkern/arch/x86_64/bcopy.S101
-rw-r--r--sys/lib/libkern/arch/x86_64/byte_swap_2.S52
-rw-r--r--sys/lib/libkern/arch/x86_64/byte_swap_4.S52
-rw-r--r--sys/lib/libkern/arch/x86_64/bzero.S44
-rw-r--r--sys/lib/libkern/arch/x86_64/ffs.S21
-rw-r--r--sys/lib/libkern/arch/x86_64/index.S29
-rw-r--r--sys/lib/libkern/arch/x86_64/memchr.S25
-rw-r--r--sys/lib/libkern/arch/x86_64/memcmp.S40
-rw-r--r--sys/lib/libkern/arch/x86_64/memcpy.S4
-rw-r--r--sys/lib/libkern/arch/x86_64/memmove.S4
-rw-r--r--sys/lib/libkern/arch/x86_64/memset.S58
-rw-r--r--sys/lib/libkern/arch/x86_64/ovbcopy.S4
-rw-r--r--sys/lib/libkern/arch/x86_64/rindex.S29
-rw-r--r--sys/lib/libkern/arch/x86_64/scanc.S62
-rw-r--r--sys/lib/libkern/arch/x86_64/skpc.S56
-rw-r--r--sys/lib/libkern/arch/x86_64/strcat.S65
-rw-r--r--sys/lib/libkern/arch/x86_64/strchr.S4
-rw-r--r--sys/lib/libkern/arch/x86_64/strcmp.S88
-rw-r--r--sys/lib/libkern/arch/x86_64/strcpy.S57
-rw-r--r--sys/lib/libkern/arch/x86_64/strlen.S21
-rw-r--r--sys/lib/libkern/arch/x86_64/strrchr.S4
-rw-r--r--sys/sys/exec_aout.h3
-rw-r--r--sys/sys/exec_elf.h3
163 files changed, 32385 insertions, 8 deletions
diff --git a/sys/arch/amd64/Makefile b/sys/arch/amd64/Makefile
new file mode 100644
index 00000000000..8cc23453486
--- /dev/null
+++ b/sys/arch/amd64/Makefile
@@ -0,0 +1,10 @@
+# $OpenBSD: Makefile,v 1.1 2004/01/28 01:39:38 mickey Exp $
+
+NOPROG= noprog
+NOMAN= noman
+
+SUBDIR= stand
+
+obj: _SUBDIRUSE
+
+.include <bsd.prog.mk>
diff --git a/sys/arch/amd64/amd64/Locore.c b/sys/arch/amd64/amd64/Locore.c
new file mode 100644
index 00000000000..91ea15b55ea
--- /dev/null
+++ b/sys/arch/amd64/amd64/Locore.c
@@ -0,0 +1,88 @@
+/* $OpenBSD: Locore.c,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996 Wolfgang Solfrank.
+ * Copyright (C) 1995, 1996 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
+ */
+
+/*
+ * Some additional routines that happened to be in locore.S traditionally,
+ * but have no need to be coded in assembly.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+
+/*
+ * Put process p on the run queue, given by its priority.
+ * Calls should be made at splstatclock(), and p->p_stat should be SRUN.
+ */
+void
+setrunqueue(p)
+ struct proc *p;
+{
+ struct prochd *q;
+ struct proc *oldlast;
+ int which = p->p_priority >> 2;
+
+#ifdef DIAGNOSTIC
+ if (p->p_back)
+ panic("setrunqueue");
+#endif
+ q = &qs[which];
+ whichqs |= 1 << which;
+ p->p_forw = (struct proc *)q;
+ p->p_back = oldlast = q->ph_rlink;
+ q->ph_rlink = p;
+ oldlast->p_forw = p;
+}
+
+/*
+ * Remove process p from its run queue, given by its priority.
+ * Calls should be made at splstatclock().
+ */
+void
+remrunqueue(p)
+ struct proc *p;
+{
+ int which = p->p_priority >> 2;
+ struct prochd *q;
+
+#ifdef DIAGNOSTIC
+ if (!(whichqs & (1 << which)))
+ panic("remrunqueue");
+#endif
+ p->p_forw->p_back = p->p_back;
+ p->p_back->p_forw = p->p_forw;
+ p->p_back = NULL;
+ q = &qs[which];
+ if (q->ph_link == (struct proc *)q)
+ whichqs &= ~(1 << which);
+}
diff --git a/sys/arch/amd64/amd64/autoconf.c b/sys/arch/amd64/amd64/autoconf.c
new file mode 100644
index 00000000000..d4eed4a1134
--- /dev/null
+++ b/sys/arch/amd64/amd64/autoconf.c
@@ -0,0 +1,606 @@
+/* $OpenBSD: autoconf.c,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+/* $NetBSD: autoconf.c,v 1.1 2003/04/26 18:39:26 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)autoconf.c 7.1 (Berkeley) 5/9/91
+ */
+
+/*
+ * Setup the system to run on the current machine.
+ *
+ * Configure() is called at boot time and initializes the vba
+ * device tables and the memory controller monitoring. Available
+ * devices are determined (from possibilities mentioned in ioconf.c),
+ * and the drivers are initialized.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/dkstat.h>
+#include <sys/disklabel.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/fcntl.h>
+#include <sys/dkio.h>
+#include <sys/reboot.h>
+
+#include <machine/pte.h>
+#include <machine/cpu.h>
+#include <machine/bootinfo.h>
+
+#include <dev/cons.h>
+
+#include "ioapic.h"
+#include "lapic.h"
+
+#if NIOAPIC > 0
+#include <machine/i82093var.h>
+#endif
+
+#if NLAPIC > 0
+#include <machine/i82489var.h>
+#endif
+
+void setroot(void);
+void swapconf(void);
+void diskconf(void);
+int findblkmajor(struct device *);
+char *findblkname(int);
+static struct device *getdisk(char *, int, int, dev_t *);
+struct device * parsedisk(char *, int, int, dev_t *);
+static int getstr(char *, int);
+
+extern struct disklist *x86_64_alldisks;
+extern int x86_64_ndisks;
+
+#if 0
+#include "bios32.h"
+#if NBIOS32 > 0
+#include <machine/bios32.h>
+#endif
+#endif
+
+int cold = 1; /* if 1, still working on cold-start */
+struct device *booted_device;
+int booted_partition;
+
+/*
+ * Determine i/o configuration for a machine.
+ */
+void
+cpu_configure(void)
+{
+#if NBIOS32 > 0
+ bios32_init();
+#endif
+
+ x86_64_proc0_tss_ldt_init();
+
+ if (config_rootfound("mainbus", NULL) == NULL)
+ panic("configure: mainbus not configured");
+
+ startrtclock();
+
+ intr_printconfig();
+
+#if NIOAPIC > 0
+ lapic_set_lvt();
+ ioapic_enable();
+#endif
+
+#ifdef MULTIPROCESSOR
+ cpu_init_idle_pcbs();
+#endif
+
+ lcr8(0);
+ spl0();
+ cold = 0;
+
+ md_diskconf = diskconf;
+}
+
+void
+diskconf(void)
+{
+printf("setroot\n");
+ setroot();
+printf("swapconf\n");
+ swapconf();
+printf("dumpconf\n");
+ dumpconf();
+}
+
+void
+setroot()
+{
+ struct swdevt *swp;
+ struct device *dv;
+ int len, majdev, unit, part;
+ dev_t nrootdev, nswapdev = NODEV;
+ char buf[128];
+ dev_t temp;
+ struct device *bootdv;
+ struct bootpath *bp;
+#if defined(NFSCLIENT)
+ extern char *nfsbootdevname;
+#endif
+
+#ifdef RAMDISK_HOOKS
+ bootdv = &fakerdrootdev;
+#else
+ bootdv = booted_device;
+#endif
+
+ /*
+ * (raid) device auto-configuration could have returned
+ * the root device's id in rootdev. Check this case.
+ */
+ if (rootdev != NODEV) {
+ majdev = major(rootdev);
+ unit = DISKUNIT(rootdev);
+ part = DISKPART(rootdev);
+
+ len = snprintf(buf, sizeof buf, "%s%d", findblkname(majdev),
+ unit);
+ if (len >= sizeof(buf))
+ panic("setroot: device name too long");
+
+ bootdv = getdisk(buf, len, part, &rootdev);
+ }
+
+ /*
+ * If `swap generic' and we couldn't determine boot device,
+ * ask the user.
+ */
+ if (mountroot == NULL && bootdv == NULL)
+ boothowto |= RB_ASKNAME;
+
+ if (boothowto & RB_ASKNAME) {
+ for (;;) {
+ printf("root device ");
+ if (bootdv != NULL)
+ printf("(default %s%c)",
+ bootdv->dv_xname,
+ bootdv->dv_class == DV_DISK
+ ? booted_partition + 'a' : ' ');
+ printf(": ");
+ len = getstr(buf, sizeof(buf));
+ if (len == 0 && bootdv != NULL) {
+ strlcpy(buf, bootdv->dv_xname, sizeof buf);
+ len = strlen(buf);
+ }
+ if (len > 0 && buf[len - 1] == '*') {
+ buf[--len] = '\0';
+ dv = getdisk(buf, len, 1, &nrootdev);
+ if (dv != NULL) {
+ bootdv = dv;
+ nswapdev = nrootdev;
+ goto gotswap;
+ }
+ }
+ if (len == 4 && strncmp(buf, "exit", 4) == 0)
+ boot(RB_HALT);
+ dv = getdisk(buf, len, bp ? booted_partition : 0,
+ &nrootdev);
+ if (dv != NULL) {
+ bootdv = dv;
+ break;
+ }
+ }
+
+ /*
+ * because swap must be on same device as root, for
+ * network devices this is easy.
+ */
+ if (bootdv->dv_class == DV_IFNET) {
+ goto gotswap;
+ }
+ for (;;) {
+ printf("swap device ");
+ if (bootdv != NULL)
+ printf("(default %s%c)",
+ bootdv->dv_xname,
+ bootdv->dv_class == DV_DISK?'b':' ');
+ printf(": ");
+ len = getstr(buf, sizeof(buf));
+ if (len == 0 && bootdv != NULL) {
+ switch (bootdv->dv_class) {
+ case DV_IFNET:
+ nswapdev = NODEV;
+ break;
+ case DV_DISK:
+ nswapdev = MAKEDISKDEV(major(nrootdev),
+ DISKUNIT(nrootdev), 1);
+ break;
+ case DV_TAPE:
+ case DV_TTY:
+ case DV_DULL:
+ case DV_CPU:
+ break;
+ }
+ break;
+ }
+ if (len == 4 && strncmp(buf, "exit", 4) == 0)
+ boot(RB_HALT);
+ dv = getdisk(buf, len, 1, &nswapdev);
+ if (dv) {
+ if (dv->dv_class == DV_IFNET)
+ nswapdev = NODEV;
+ break;
+ }
+ }
+gotswap:
+ rootdev = nrootdev;
+ dumpdev = nswapdev;
+ swdevt[0].sw_dev = nswapdev;
+ swdevt[1].sw_dev = NODEV;
+
+ } else if (mountroot == NULL) {
+
+ /*
+ * `swap generic': Use the device the ROM told us to use.
+ */
+ majdev = findblkmajor(bootdv);
+ if (majdev >= 0) {
+ /*
+ * Root and swap are on a disk.
+ * val[2] of the boot device is the partition number.
+ * Assume swap is on partition b.
+ */
+ part = booted_partition;
+ unit = bootdv->dv_unit;
+ rootdev = MAKEDISKDEV(majdev, unit, part);
+ nswapdev = dumpdev = MAKEDISKDEV(major(rootdev),
+ DISKUNIT(rootdev), 1);
+ } else {
+ /*
+ * Root and swap are on a net.
+ */
+ nswapdev = dumpdev = NODEV;
+ }
+ swdevt[0].sw_dev = nswapdev;
+ /* swdevt[1].sw_dev = NODEV; */
+
+ } else {
+
+ /*
+ * `root DEV swap DEV': honour rootdev/swdevt.
+ * rootdev/swdevt/mountroot already properly set.
+ */
+ if (bootdv->dv_class == DV_DISK)
+ printf("root on %s%c\n", bootdv->dv_xname,
+ part + 'a');
+ majdev = major(rootdev);
+ unit = DISKUNIT(rootdev);
+ part = DISKPART(rootdev);
+ return;
+ }
+
+ switch (bootdv->dv_class) {
+#if defined(NFSCLIENT)
+ case DV_IFNET:
+ mountroot = nfs_mountroot;
+ nfsbootdevname = bootdv->dv_xname;
+ return;
+#endif
+ case DV_DISK:
+ mountroot = dk_mountroot;
+ majdev = major(rootdev);
+ unit = DISKUNIT(rootdev);
+ part = DISKPART(rootdev);
+ printf("root on %s%c\n", bootdv->dv_xname,
+ part + 'a');
+ break;
+ default:
+ printf("can't figure root, hope your kernel is right\n");
+ return;
+ }
+
+ /*
+ * Make the swap partition on the root drive the primary swap.
+ */
+ temp = NODEV;
+ for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
+ if (majdev == major(swp->sw_dev) &&
+ unit == DISKUNIT(swp->sw_dev)) {
+ temp = swdevt[0].sw_dev;
+ swdevt[0].sw_dev = swp->sw_dev;
+ swp->sw_dev = temp;
+ break;
+ }
+ }
+ if (swp->sw_dev != NODEV) {
+ /*
+ * If dumpdev was the same as the old primary swap device,
+ * move it to the new primary swap device.
+ */
+ if (temp == dumpdev)
+ dumpdev = swdevt[0].sw_dev;
+ }
+}
+
+void
+swapconf(void)
+{
+ struct swdevt *swp;
+ int nblks;
+
+ for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
+ if (bdevsw[major(swp->sw_dev)].d_psize) {
+ nblks =
+ (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev);
+ if (nblks != -1 &&
+ (swp->sw_nblks == 0 || swp->sw_nblks > nblks))
+ swp->sw_nblks = nblks;
+ swp->sw_nblks = ctod(dtoc(swp->sw_nblks));
+ }
+ }
+}
+
+static struct device *
+getdisk(str, len, defpart, devp)
+ char *str;
+ int len, defpart;
+ dev_t *devp;
+{
+ struct device *dv;
+
+ if ((dv = parsedisk(str, len, defpart, devp)) == NULL) {
+ printf("use one of: exit");
+#ifdef RAMDISK_HOOKS
+ printf(" %s[a-p]", fakerdrootdev.dv_xname);
+#endif
+ for (dv = alldevs.tqh_first; dv != NULL;
+ dv = dv->dv_list.tqe_next) {
+ if (dv->dv_class == DV_DISK)
+ printf(" %s[a-p]", dv->dv_xname);
+#ifdef NFSCLIENT
+ if (dv->dv_class == DV_IFNET)
+ printf(" %s", dv->dv_xname);
+#endif
+ }
+ printf("\n");
+ }
+ return (dv);
+}
+
+struct device *
+parsedisk(str, len, defpart, devp)
+ char *str;
+ int len, defpart;
+ dev_t *devp;
+{
+ struct device *dv;
+ char *cp, c;
+ int majdev, unit, part;
+
+ if (len == 0)
+ return (NULL);
+ cp = str + len - 1;
+ c = *cp;
+ if (c >= 'a' && (c - 'a') < MAXPARTITIONS) {
+ part = c - 'a';
+ *cp = '\0';
+ } else
+ part = defpart;
+
+#ifdef RAMDISK_HOOKS
+ if (strcmp(str, fakerdrootdev.dv_xname) == 0) {
+ dv = &fakerdrootdev;
+ goto gotdisk;
+ }
+#endif
+
+ for (dv = alldevs.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next) {
+ if (dv->dv_class == DV_DISK &&
+ strcmp(str, dv->dv_xname) == 0) {
+#ifdef RAMDISK_HOOKS
+gotdisk:
+#endif
+ majdev = findblkmajor(dv);
+ unit = dv->dv_unit;
+ if (majdev < 0)
+ panic("parsedisk");
+ *devp = MAKEDISKDEV(majdev, unit, part);
+ break;
+ }
+#ifdef NFSCLIENT
+ if (dv->dv_class == DV_IFNET &&
+ strcmp(str, dv->dv_xname) == 0) {
+ *devp = NODEV;
+ break;
+ }
+#endif
+ }
+
+ *cp = c;
+ return (dv);
+}
+
+static int
+getstr(cp, size)
+ char *cp;
+ int size;
+{
+ char *lp;
+ int c;
+ int len;
+
+ lp = cp;
+ len = 0;
+ for (;;) {
+ c = cngetc();
+ switch (c) {
+ case '\n':
+ case '\r':
+ printf("\n");
+ *lp++ = '\0';
+ return (len);
+ case '\b':
+ case '\177':
+ case '#':
+ if (len) {
+ --len;
+ --lp;
+ printf("\b \b");
+ }
+ continue;
+ case '@':
+ case 'u'&037:
+ len = 0;
+ lp = cp;
+ printf("\n");
+ continue;
+ default:
+ if (len + 1 >= size || c < ' ') {
+ printf("\007");
+ continue;
+ }
+ printf("%c", c);
+ ++len;
+ *lp++ = c;
+ }
+ }
+}
+
+#include "pci.h"
+
+#include <dev/isa/isavar.h>
+#if NPCI > 0
+#include <dev/pci/pcivar.h>
+#endif
+
+void
+device_register(struct device *dev, void *aux)
+{
+ /*
+ * Handle network interfaces here, the attachment information is
+ * not available driver independantly later.
+ * For disks, there is nothing useful available at attach time.
+ */
+ if (dev->dv_class == DV_IFNET) {
+ struct btinfo_netif *bin = lookup_bootinfo(BTINFO_NETIF);
+ if (bin == NULL)
+ return;
+
+ /*
+ * We don't check the driver name against the device name
+ * passed by the boot ROM. The ROM should stay usable
+ * if the driver gets obsoleted.
+ * The physical attachment information (checked below)
+ * must be sufficient to identify the device.
+ */
+
+ if (bin->bus == BI_BUS_ISA &&
+ !strcmp(dev->dv_parent->dv_cfdata->cf_driver->cd_name,
+ "isa")) {
+ struct isa_attach_args *iaa = aux;
+
+ /* compare IO base address */
+ /* XXXJRT what about multiple I/O addrs? */
+ if (iaa->ipa_nio > 0 &&
+ bin->addr.iobase == iaa->ipa_io[0].base)
+ goto found;
+ }
+#if NPCI > 0
+ if (bin->bus == BI_BUS_PCI &&
+ !strcmp(dev->dv_parent->dv_cfdata->cf_driver->cd_name,
+ "pci")) {
+ struct pci_attach_args *paa = aux;
+ int b, d, f;
+
+ /*
+ * Calculate BIOS representation of:
+ *
+ * <bus,device,function>
+ *
+ * and compare.
+ */
+ pci_decompose_tag(paa->pa_pc, paa->pa_tag, &b, &d, &f);
+ if (bin->addr.tag == ((b << 8) | (d << 3) | f))
+ goto found;
+ }
+#endif
+ }
+ return;
+
+found:
+ if (booted_device) {
+ /* XXX should be a "panic()" */
+ printf("warning: double match for boot device (%s, %s)\n",
+ booted_device->dv_xname, dev->dv_xname);
+ return;
+ }
+ booted_device = dev;
+}
+
+/* XXX */
+static struct nam2blk {
+ char *name;
+ int maj;
+} nam2blk[] = {
+ { "wd", 0 }, /* 0 = wd */
+ { "sd", 4 }, /* 2 = sd */
+ { "raid", 19 }, /* 19 = raid */
+};
+
+int
+findblkmajor(struct device *dv)
+{
+ char *name = dv->dv_xname;
+ int i;
+
+ for (i = 0; i < sizeof(nam2blk)/sizeof(nam2blk[0]); ++i)
+ if (strncmp(name, nam2blk[i].name, strlen(nam2blk[i].name)) == 0)
+ return (nam2blk[i].maj);
+ return (-1);
+}
+
+char *
+findblkname(maj)
+ int maj;
+{
+ int i;
+
+ for (i = 0; i < sizeof(nam2blk)/sizeof(nam2blk[0]); i++)
+ if (nam2blk[i].maj == maj)
+ return (nam2blk[i].name);
+ return (NULL);
+}
diff --git a/sys/arch/amd64/amd64/bus_dma.c b/sys/arch/amd64/amd64/bus_dma.c
new file mode 100644
index 00000000000..17863c33031
--- /dev/null
+++ b/sys/arch/amd64/amd64/bus_dma.c
@@ -0,0 +1,709 @@
+/* $NetBSD: bus_dma.c,v 1.3 2003/05/07 21:33:58 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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>
+
+/*
+ * The following is included because _bus_dma_uiomove is derived from
+ * uiomove() in kern_subr.c.
+ */
+
+/*
+ * Copyright (c) 1982, 1986, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/proc.h>
+
+#define _X86_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+
+#include <uvm/uvm_extern.h>
+
+#include "ioapic.h"
+
+#if NIOAPIC > 0
+#include <machine/i82093var.h>
+#include <machine/mpbiosvar.h>
+#endif
+
+extern paddr_t avail_end;
+
+int _bus_dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t,
+ struct proc *, int, paddr_t *, int *, int);
+
+#define IDTVEC(name) __CONCAT(X,name)
+typedef void (vector)(void);
+extern vector *IDTVEC(intr)[];
+
+/*
+ * Common function for DMA map creation. May be called by bus-specific
+ * DMA map creation functions.
+ */
+int
+_bus_dmamap_create(t, size, nsegments, maxsegsz, boundary, flags, dmamp)
+ bus_dma_tag_t t;
+ bus_size_t size;
+ int nsegments;
+ bus_size_t maxsegsz;
+ bus_size_t boundary;
+ int flags;
+ bus_dmamap_t *dmamp;
+{
+ struct x86_bus_dmamap *map;
+ void *mapstore;
+ size_t mapsize;
+
+ /*
+ * Allocate and initialize the DMA map. The end of the map
+ * is a variable-sized array of segments, so we allocate enough
+ * room for them in one shot.
+ *
+ * Note we don't preserve the WAITOK or NOWAIT flags. Preservation
+ * of ALLOCNOW notifies others that we've reserved these resources,
+ * and they are not to be freed.
+ *
+ * The bus_dmamap_t includes one bus_dma_segment_t, hence
+ * the (nsegments - 1).
+ */
+ mapsize = sizeof(struct x86_bus_dmamap) +
+ (sizeof(bus_dma_segment_t) * (nsegments - 1));
+ if ((mapstore = malloc(mapsize, M_DEVBUF,
+ (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL)
+ return (ENOMEM);
+
+ bzero(mapstore, mapsize);
+ map = (struct x86_bus_dmamap *)mapstore;
+ map->_dm_size = size;
+ map->_dm_segcnt = nsegments;
+ map->_dm_maxsegsz = maxsegsz;
+ map->_dm_boundary = boundary;
+ map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT);
+ map->dm_mapsize = 0; /* no valid mappings */
+ map->dm_nsegs = 0;
+
+ *dmamp = map;
+ return (0);
+}
+
+/*
+ * Common function for DMA map destruction. May be called by bus-specific
+ * DMA map destruction functions.
+ */
+void
+_bus_dmamap_destroy(t, map)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+{
+
+ free(map, M_DEVBUF);
+}
+
+/*
+ * Common function for loading a DMA map with a linear buffer. May
+ * be called by bus-specific DMA map load functions.
+ */
+int
+_bus_dmamap_load(t, map, buf, buflen, p, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ void *buf;
+ bus_size_t buflen;
+ struct proc *p;
+ int flags;
+{
+ bus_addr_t lastaddr;
+ int seg, error;
+
+ /*
+ * Make sure that on error condition we return "no valid mappings".
+ */
+ map->dm_mapsize = 0;
+ map->dm_nsegs = 0;
+
+ if (buflen > map->_dm_size)
+ return (EINVAL);
+
+ seg = 0;
+ error = _bus_dmamap_load_buffer(t, map, buf, buflen, p, flags,
+ &lastaddr, &seg, 1);
+ if (error == 0) {
+ map->dm_mapsize = buflen;
+ map->dm_nsegs = seg + 1;
+ }
+ return (error);
+}
+
+/*
+ * Like _bus_dmamap_load(), but for mbufs.
+ */
+int
+_bus_dmamap_load_mbuf(t, map, m0, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ struct mbuf *m0;
+ int flags;
+{
+ paddr_t lastaddr;
+ int seg, error, first;
+ struct mbuf *m;
+
+ /*
+ * Make sure that on error condition we return "no valid mappings".
+ */
+ map->dm_mapsize = 0;
+ map->dm_nsegs = 0;
+
+#ifdef DIAGNOSTIC
+ if ((m0->m_flags & M_PKTHDR) == 0)
+ panic("_bus_dmamap_load_mbuf: no packet header");
+#endif
+
+ if (m0->m_pkthdr.len > map->_dm_size)
+ return (EINVAL);
+
+ first = 1;
+ seg = 0;
+ error = 0;
+ for (m = m0; m != NULL && error == 0; m = m->m_next) {
+ error = _bus_dmamap_load_buffer(t, map, m->m_data, m->m_len,
+ NULL, flags, &lastaddr, &seg, first);
+ first = 0;
+ }
+ if (error == 0) {
+ map->dm_mapsize = m0->m_pkthdr.len;
+ map->dm_nsegs = seg + 1;
+ }
+ return (error);
+}
+
+/*
+ * Like _bus_dmamap_load(), but for uios.
+ */
+int
+_bus_dmamap_load_uio(t, map, uio, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ struct uio *uio;
+ int flags;
+{
+ paddr_t lastaddr;
+ int seg, i, error, first;
+ bus_size_t minlen, resid;
+ struct proc *p = NULL;
+ struct iovec *iov;
+ caddr_t addr;
+
+ /*
+ * Make sure that on error condition we return "no valid mappings".
+ */
+ map->dm_mapsize = 0;
+ map->dm_nsegs = 0;
+
+ resid = uio->uio_resid;
+ iov = uio->uio_iov;
+
+ if (uio->uio_segflg == UIO_USERSPACE) {
+ p = uio->uio_procp;
+#ifdef DIAGNOSTIC
+ if (p == NULL)
+ panic("_bus_dmamap_load_uio: USERSPACE but no proc");
+#endif
+ }
+
+ first = 1;
+ seg = 0;
+ error = 0;
+ for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) {
+ /*
+ * Now at the first iovec to load. Load each iovec
+ * until we have exhausted the residual count.
+ */
+ minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len;
+ addr = (caddr_t)iov[i].iov_base;
+
+ error = _bus_dmamap_load_buffer(t, map, addr, minlen,
+ p, flags, &lastaddr, &seg, first);
+ first = 0;
+
+ resid -= minlen;
+ }
+ if (error == 0) {
+ map->dm_mapsize = uio->uio_resid;
+ map->dm_nsegs = seg + 1;
+ }
+ return (error);
+}
+
+/*
+ * Like _bus_dmamap_load(), but for raw memory allocated with
+ * bus_dmamem_alloc().
+ */
+int
+_bus_dmamap_load_raw(t, map, segs, nsegs, size, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ bus_size_t size;
+ int flags;
+{
+ if (nsegs > map->_dm_segcnt || size > map->_dm_size)
+ return (EINVAL);
+
+ /*
+ * Make sure we don't cross any boundaries.
+ */
+ if (map->_dm_boundary) {
+ bus_addr_t bmask = ~(map->_dm_boundary - 1);
+ int i;
+
+ for (i = 0; i < nsegs; i++) {
+ if (segs[i].ds_len > map->_dm_maxsegsz)
+ return (EINVAL);
+ if ((segs[i].ds_addr & bmask) !=
+ ((segs[i].ds_addr + segs[i].ds_len - 1) & bmask))
+ return (EINVAL);
+ }
+ }
+
+ bcopy(segs, map->dm_segs, nsegs * sizeof(*segs));
+ map->dm_nsegs = nsegs;
+ return (0);
+}
+
+/*
+ * Common function for unloading a DMA map. May be called by
+ * bus-specific DMA map unload functions.
+ */
+void
+_bus_dmamap_unload(t, map)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+{
+
+ /*
+ * No resources to free; just mark the mappings as
+ * invalid.
+ */
+ map->dm_mapsize = 0;
+ map->dm_nsegs = 0;
+}
+
+/*
+ * Common function for DMA map synchronization. May be called
+ * by bus-specific DMA map synchronization functions.
+ */
+void
+_bus_dmamap_sync(t, map, addr, size, op)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ bus_addr_t addr;
+ bus_size_t size;
+ int op;
+{
+
+ /* Nothing to do here. */
+}
+
+/*
+ * Common function for DMA-safe memory allocation. May be called
+ * by bus-specific DMA memory allocation functions.
+ */
+int
+_bus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags)
+ bus_dma_tag_t t;
+ bus_size_t size, alignment, boundary;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ int *rsegs;
+ int flags;
+{
+
+ return (_bus_dmamem_alloc_range(t, size, alignment, boundary,
+ segs, nsegs, rsegs, flags, 0, trunc_page(avail_end)));
+}
+
+/*
+ * Common function for freeing DMA-safe memory. May be called by
+ * bus-specific DMA memory free functions.
+ */
+void
+_bus_dmamem_free(t, segs, nsegs)
+ bus_dma_tag_t t;
+ bus_dma_segment_t *segs;
+ int nsegs;
+{
+ struct vm_page *m;
+ bus_addr_t addr;
+ struct pglist mlist;
+ int curseg;
+
+ /*
+ * Build a list of pages to free back to the VM system.
+ */
+ TAILQ_INIT(&mlist);
+ for (curseg = 0; curseg < nsegs; curseg++) {
+ for (addr = segs[curseg].ds_addr;
+ addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
+ addr += PAGE_SIZE) {
+ m = PHYS_TO_VM_PAGE(addr);
+ TAILQ_INSERT_TAIL(&mlist, m, pageq);
+ }
+ }
+
+ uvm_pglistfree(&mlist);
+}
+
+/*
+ * Common function for mapping DMA-safe memory. May be called by
+ * bus-specific DMA memory map functions.
+ */
+int
+_bus_dmamem_map(t, segs, nsegs, size, kvap, flags)
+ bus_dma_tag_t t;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ size_t size;
+ caddr_t *kvap;
+ int flags;
+{
+ vaddr_t va;
+ bus_addr_t addr;
+ int curseg;
+
+ size = round_page(size);
+ va = uvm_km_valloc(kernel_map, size);
+ if (va == 0)
+ return (ENOMEM);
+
+ *kvap = (caddr_t)va;
+
+ for (curseg = 0; curseg < nsegs; curseg++) {
+ for (addr = segs[curseg].ds_addr;
+ addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
+ addr += PAGE_SIZE, va += PAGE_SIZE, size -= PAGE_SIZE) {
+ if (size == 0)
+ panic("_bus_dmamem_map: size botch");
+ pmap_enter(pmap_kernel(), va, addr,
+ VM_PROT_READ | VM_PROT_WRITE,
+ VM_PROT_READ | VM_PROT_WRITE | PMAP_WIRED);
+ }
+ }
+ pmap_update(pmap_kernel());
+
+ return (0);
+}
+
+/*
+ * Common function for unmapping DMA-safe memory. May be called by
+ * bus-specific DMA memory unmapping functions.
+ */
+void
+_bus_dmamem_unmap(t, kva, size)
+ bus_dma_tag_t t;
+ caddr_t kva;
+ size_t size;
+{
+
+#ifdef DIAGNOSTIC
+ if ((u_long)kva & PGOFSET)
+ panic("_bus_dmamem_unmap");
+#endif
+
+ size = round_page(size);
+ uvm_km_free(kernel_map, (vaddr_t)kva, size);
+}
+
+/*
+ * Common functin for mmap(2)'ing DMA-safe memory. May be called by
+ * bus-specific DMA mmap(2)'ing functions.
+ */
+paddr_t
+_bus_dmamem_mmap(t, segs, nsegs, off, prot, flags)
+ bus_dma_tag_t t;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ off_t off;
+ int prot, flags;
+{
+ int i;
+
+ for (i = 0; i < nsegs; i++) {
+#ifdef DIAGNOSTIC
+ if (off & PGOFSET)
+ panic("_bus_dmamem_mmap: offset unaligned");
+ if (segs[i].ds_addr & PGOFSET)
+ panic("_bus_dmamem_mmap: segment unaligned");
+ if (segs[i].ds_len & PGOFSET)
+ panic("_bus_dmamem_mmap: segment size not multiple"
+ " of page size");
+#endif
+ if (off >= segs[i].ds_len) {
+ off -= segs[i].ds_len;
+ continue;
+ }
+
+ return (x86_btop((caddr_t)segs[i].ds_addr + off));
+ }
+
+ /* Page not found. */
+ return (-1);
+}
+
+/**********************************************************************
+ * DMA utility functions
+ **********************************************************************/
+/*
+ * Utility function to load a linear buffer. lastaddrp holds state
+ * between invocations (for multiple-buffer loads). segp contains
+ * the starting segment on entrace, and the ending segment on exit.
+ * first indicates if this is the first invocation of this function.
+ */
+int
+_bus_dmamap_load_buffer(t, map, buf, buflen, p, flags, lastaddrp, segp, first)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ void *buf;
+ bus_size_t buflen;
+ struct proc *p;
+ int flags;
+ paddr_t *lastaddrp;
+ int *segp;
+ int first;
+{
+ bus_size_t sgsize;
+ bus_addr_t curaddr, lastaddr, baddr, bmask;
+ vaddr_t vaddr = (vaddr_t)buf;
+ int seg;
+ pmap_t pmap;
+
+ if (p != NULL)
+ pmap = p->p_vmspace->vm_map.pmap;
+ else
+ pmap = pmap_kernel();
+
+ lastaddr = *lastaddrp;
+ bmask = ~(map->_dm_boundary - 1);
+
+ for (seg = *segp; buflen > 0 ; ) {
+ /*
+ * Get the physical address for this segment.
+ */
+ pmap_extract(pmap, vaddr, (paddr_t *)&curaddr);
+
+ /*
+ * Compute the segment size, and adjust counts.
+ */
+ sgsize = PAGE_SIZE - ((u_long)vaddr & PGOFSET);
+ if (buflen < sgsize)
+ sgsize = buflen;
+
+ /*
+ * Make sure we don't cross any boundaries.
+ */
+ if (map->_dm_boundary > 0) {
+ baddr = (curaddr + map->_dm_boundary) & bmask;
+ if (sgsize > (baddr - curaddr))
+ sgsize = (baddr - curaddr);
+ }
+
+ /*
+ * Insert chunk into a segment, coalescing with
+ * previous segment if possible.
+ */
+ if (first) {
+ map->dm_segs[seg].ds_addr = curaddr;
+ map->dm_segs[seg].ds_len = sgsize;
+ first = 0;
+ } else {
+ if (curaddr == lastaddr &&
+ (map->dm_segs[seg].ds_len + sgsize) <=
+ map->_dm_maxsegsz &&
+ (map->_dm_boundary == 0 ||
+ (map->dm_segs[seg].ds_addr & bmask) ==
+ (curaddr & bmask)))
+ map->dm_segs[seg].ds_len += sgsize;
+ else {
+ if (++seg >= map->_dm_segcnt)
+ break;
+ map->dm_segs[seg].ds_addr = curaddr;
+ map->dm_segs[seg].ds_len = sgsize;
+ }
+ }
+
+ lastaddr = curaddr + sgsize;
+ vaddr += sgsize;
+ buflen -= sgsize;
+ }
+
+ *segp = seg;
+ *lastaddrp = lastaddr;
+
+ /*
+ * Did we fit?
+ */
+ if (buflen != 0)
+ return (EFBIG); /* XXX better return value here? */
+ return (0);
+}
+
+/*
+ * Allocate physical memory from the given physical address range.
+ * Called by DMA-safe memory allocation methods.
+ */
+int
+_bus_dmamem_alloc_range(t, size, alignment, boundary, segs, nsegs, rsegs,
+ flags, low, high)
+ bus_dma_tag_t t;
+ bus_size_t size, alignment, boundary;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ int *rsegs;
+ int flags;
+ paddr_t low;
+ paddr_t high;
+{
+ paddr_t curaddr, lastaddr;
+ struct vm_page *m;
+ struct pglist mlist;
+ int curseg, error;
+
+ /* Always round the size. */
+ size = round_page(size);
+
+ /*
+ * Allocate pages from the VM system.
+ */
+ TAILQ_INIT(&mlist);
+ error = uvm_pglistalloc(size, low, high,
+ alignment, boundary, &mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0);
+ if (error)
+ return (error);
+
+ /*
+ * Compute the location, size, and number of segments actually
+ * returned by the VM code.
+ */
+ m = TAILQ_FIRST(&mlist);
+ curseg = 0;
+ lastaddr = segs[curseg].ds_addr = VM_PAGE_TO_PHYS(m);
+ segs[curseg].ds_len = PAGE_SIZE;
+
+ for (m = TAILQ_NEXT(m, pageq); m != NULL; m = TAILQ_NEXT(m, pageq)) {
+ curaddr = VM_PAGE_TO_PHYS(m);
+#ifdef DIAGNOSTIC
+ if (curseg == nsegs) {
+ printf("uvm_pglistalloc returned too many\n");
+ panic("_bus_dmamem_alloc_range");
+ }
+ if (curaddr < low || curaddr >= high) {
+ printf("uvm_pglistalloc returned non-sensical"
+ " address 0x%lx\n", curaddr);
+ panic("_bus_dmamem_alloc_range");
+ }
+#endif
+ if (curaddr == (lastaddr + PAGE_SIZE))
+ segs[curseg].ds_len += PAGE_SIZE;
+ else {
+ curseg++;
+ segs[curseg].ds_addr = curaddr;
+ segs[curseg].ds_len = PAGE_SIZE;
+ }
+ lastaddr = curaddr;
+ }
+
+ *rsegs = curseg + 1;
+
+ return (0);
+}
+
diff --git a/sys/arch/amd64/amd64/bus_space.c b/sys/arch/amd64/amd64/bus_space.c
new file mode 100644
index 00000000000..a99b33dcd7c
--- /dev/null
+++ b/sys/arch/amd64/amd64/bus_space.c
@@ -0,0 +1,473 @@
+/* $OpenBSD: bus_space.c,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+/* $NetBSD: bus_space.c,v 1.2 2003/03/14 18:47:53 christos Exp $ */
+
+/*-
+ * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/extent.h>
+
+#include <uvm/uvm_extern.h>
+
+#define _X86_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+
+#include <dev/isa/isareg.h>
+#include <machine/isa_machdep.h>
+
+/*
+ * Extent maps to manage I/O and memory space. Allocate
+ * storage for 8 regions in each, initially. Later, ioport_malloc_safe
+ * will indicate that it's safe to use malloc() to dynamically allocate
+ * region descriptors.
+ *
+ * N.B. At least two regions are _always_ allocated from the iomem
+ * extent map; (0 -> ISA hole) and (end of ISA hole -> end of RAM).
+ *
+ * The extent maps are not static! Machine-dependent ISA and EISA
+ * routines need access to them for bus address space allocation.
+ */
+static long ioport_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
+static long iomem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
+struct extent *ioport_ex;
+struct extent *iomem_ex;
+static int ioport_malloc_safe;
+
+int x86_mem_add_mapping(bus_addr_t, bus_size_t,
+ int, bus_space_handle_t *);
+
+void
+x86_bus_space_init()
+{
+ /*
+ * Initialize the I/O port and I/O mem extent maps.
+ * Note: we don't have to check the return value since
+ * creation of a fixed extent map will never fail (since
+ * descriptor storage has already been allocated).
+ *
+ * N.B. The iomem extent manages _all_ physical addresses
+ * on the machine. When the amount of RAM is found, the two
+ * extents of RAM are allocated from the map (0 -> ISA hole
+ * and end of ISA hole -> end of RAM).
+ */
+ ioport_ex = extent_create("ioport", 0x0, 0xffff, M_DEVBUF,
+ (caddr_t)ioport_ex_storage, sizeof(ioport_ex_storage),
+ EX_NOCOALESCE|EX_NOWAIT);
+ iomem_ex = extent_create("iomem", 0x0, 0xffffffff, M_DEVBUF,
+ (caddr_t)iomem_ex_storage, sizeof(iomem_ex_storage),
+ EX_NOCOALESCE|EX_NOWAIT);
+}
+
+void
+x86_bus_space_mallocok()
+{
+
+ ioport_malloc_safe = 1;
+}
+
+int
+x86_memio_map(t, bpa, size, flags, bshp)
+ bus_space_tag_t t;
+ bus_addr_t bpa;
+ bus_size_t size;
+ int flags;
+ bus_space_handle_t *bshp;
+{
+ int error;
+ struct extent *ex;
+
+ /*
+ * Pick the appropriate extent map.
+ */
+ if (t == X86_BUS_SPACE_IO) {
+ ex = ioport_ex;
+ } else if (t == X86_BUS_SPACE_MEM)
+ ex = iomem_ex;
+ else
+ panic("x86_memio_map: bad bus space tag");
+
+ /*
+ * Before we go any further, let's make sure that this
+ * region is available.
+ */
+ error = extent_alloc_region(ex, bpa, size,
+ EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0));
+ if (error)
+ return (error);
+
+ /*
+ * For I/O space, that's all she wrote.
+ */
+ if (t == X86_BUS_SPACE_IO) {
+ *bshp = bpa;
+ return (0);
+ }
+
+ if (bpa >= IOM_BEGIN && (bpa + size) <= IOM_END) {
+ *bshp = (bus_space_handle_t)ISA_HOLE_VADDR(bpa);
+ return(0);
+ }
+
+ /*
+ * For memory space, map the bus physical address to
+ * a kernel virtual address.
+ */
+ error = x86_mem_add_mapping(bpa, size, 0, bshp);
+ if (error) {
+ if (extent_free(ex, bpa, size, EX_NOWAIT |
+ (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
+ printf("x86_memio_map: pa 0x%lx, size 0x%lx\n",
+ bpa, size);
+ printf("x86_memio_map: can't free region\n");
+ }
+ }
+
+ return (error);
+}
+
+int
+_x86_memio_map(t, bpa, size, flags, bshp)
+ bus_space_tag_t t;
+ bus_addr_t bpa;
+ bus_size_t size;
+ int flags;
+ bus_space_handle_t *bshp;
+{
+
+ /*
+ * For I/O space, just fill in the handle.
+ */
+ if (t == X86_BUS_SPACE_IO) {
+ *bshp = bpa;
+ return (0);
+ }
+
+ /*
+ * For memory space, map the bus physical address to
+ * a kernel virtual address.
+ */
+ return (x86_mem_add_mapping(bpa, size, 0, bshp));
+}
+
+int
+x86_memio_alloc(t, rstart, rend, size, alignment, boundary, flags,
+ bpap, bshp)
+ bus_space_tag_t t;
+ bus_addr_t rstart, rend;
+ bus_size_t size, alignment, boundary;
+ int flags;
+ bus_addr_t *bpap;
+ bus_space_handle_t *bshp;
+{
+ struct extent *ex;
+ u_long bpa;
+ int error;
+
+ /*
+ * Pick the appropriate extent map.
+ */
+ if (t == X86_BUS_SPACE_IO) {
+ ex = ioport_ex;
+ } else if (t == X86_BUS_SPACE_MEM)
+ ex = iomem_ex;
+ else
+ panic("x86_memio_alloc: bad bus space tag");
+
+ /*
+ * Sanity check the allocation against the extent's boundaries.
+ */
+ if (rstart < ex->ex_start || rend > ex->ex_end)
+ panic("x86_memio_alloc: bad region start/end");
+
+ /*
+ * Do the requested allocation.
+ */
+ error = extent_alloc_subregion(ex, rstart, rend, size, alignment,
+ 0, boundary,
+ EX_FAST | EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0),
+ &bpa);
+
+ if (error)
+ return (error);
+
+ /*
+ * For I/O space, that's all she wrote.
+ */
+ if (t == X86_BUS_SPACE_IO) {
+ *bshp = *bpap = bpa;
+ return (0);
+ }
+
+ /*
+ * For memory space, map the bus physical address to
+ * a kernel virtual address.
+ */
+ error = x86_mem_add_mapping(bpa, size, 0, bshp);
+ if (error) {
+ if (extent_free(iomem_ex, bpa, size, EX_NOWAIT |
+ (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
+ printf("x86_memio_alloc: pa 0x%lx, size 0x%lx\n",
+ bpa, size);
+ printf("x86_memio_alloc: can't free region\n");
+ }
+ }
+
+ *bpap = bpa;
+
+ return (error);
+}
+
+int
+x86_mem_add_mapping(bpa, size, cacheable, bshp)
+ bus_addr_t bpa;
+ bus_size_t size;
+ int cacheable;
+ bus_space_handle_t *bshp;
+{
+ u_long pa, endpa;
+ vaddr_t va;
+ pt_entry_t *pte;
+ int32_t cpumask = 0;
+
+ pa = x86_trunc_page(bpa);
+ endpa = x86_round_page(bpa + size);
+
+#ifdef DIAGNOSTIC
+ if (endpa <= pa)
+ panic("x86_mem_add_mapping: overflow");
+#endif
+
+ va = uvm_km_valloc(kernel_map, endpa - pa);
+ if (va == 0)
+ return (ENOMEM);
+
+ *bshp = (bus_space_handle_t)(va + (bpa & PGOFSET));
+
+ for (; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) {
+ pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE);
+
+ /*
+ * PG_N doesn't exist on 386's, so we assume that
+ * the mainboard has wired up device space non-cacheable
+ * on those machines.
+ *
+ * Note that it's not necessary to use atomic ops to
+ * fiddle with the PTE here, because we don't care
+ * about mod/ref information.
+ *
+ * XXX should hand this bit to pmap_kenter_pa to
+ * save the extra invalidate!
+ *
+ * XXX extreme paranoia suggests tlb shootdown belongs here.
+ */
+ if (pmap_cpu_has_pg_n()) {
+ pte = kvtopte(va);
+ if (cacheable)
+ *pte &= ~PG_N;
+ else
+ *pte |= PG_N;
+ pmap_tlb_shootdown(pmap_kernel(), va, *pte,
+ &cpumask);
+ }
+ }
+
+ pmap_tlb_shootnow(cpumask);
+ pmap_update(pmap_kernel());
+
+ return 0;
+}
+
+/*
+ * void _x86_memio_unmap(bus_space_tag bst, bus_space_handle bsh,
+ * bus_size_t size, bus_addr_t *adrp)
+ *
+ * This function unmaps memory- or io-space mapped by the function
+ * _x86_memio_map(). This function works nearly as same as
+ * x86_memio_unmap(), but this function does not ask kernel
+ * built-in extents and returns physical address of the bus space,
+ * for the convenience of the extra extent manager.
+ */
+void
+_x86_memio_unmap(t, bsh, size, adrp)
+ bus_space_tag_t t;
+ bus_space_handle_t bsh;
+ bus_size_t size;
+ bus_addr_t *adrp;
+{
+ u_long va, endva;
+ bus_addr_t bpa;
+
+ /*
+ * Find the correct extent and bus physical address.
+ */
+ if (t == X86_BUS_SPACE_IO) {
+ bpa = bsh;
+ } else if (t == X86_BUS_SPACE_MEM) {
+ if (bsh >= atdevbase && (bsh + size) <= (atdevbase + IOM_SIZE)) {
+ bpa = (bus_addr_t)ISA_PHYSADDR(bsh);
+ } else {
+
+ va = x86_trunc_page(bsh);
+ endva = x86_round_page(bsh + size);
+
+#ifdef DIAGNOSTIC
+ if (endva <= va) {
+ panic("_x86_memio_unmap: overflow");
+ }
+#endif
+
+ if (pmap_extract(pmap_kernel(), va, &bpa) == FALSE) {
+ panic("_x86_memio_unmap:"
+ " wrong virtual address");
+ }
+ bpa += (bsh & PGOFSET);
+
+ pmap_kremove(va, endva - va);
+ /*
+ * Free the kernel virtual mapping.
+ */
+ uvm_km_free(kernel_map, va, endva - va);
+ }
+ } else {
+ panic("_x86_memio_unmap: bad bus space tag");
+ }
+
+ if (adrp != NULL) {
+ *adrp = bpa;
+ }
+}
+
+void
+x86_memio_unmap(t, bsh, size)
+ bus_space_tag_t t;
+ bus_space_handle_t bsh;
+ bus_size_t size;
+{
+ struct extent *ex;
+ u_long va, endva;
+ bus_addr_t bpa;
+
+ /*
+ * Find the correct extent and bus physical address.
+ */
+ if (t == X86_BUS_SPACE_IO) {
+ ex = ioport_ex;
+ bpa = bsh;
+ } else if (t == X86_BUS_SPACE_MEM) {
+ ex = iomem_ex;
+
+ if (bsh >= atdevbase &&
+ (bsh + size) <= (atdevbase + IOM_SIZE)) {
+ bpa = (bus_addr_t)ISA_PHYSADDR(bsh);
+ goto ok;
+ }
+
+ va = x86_trunc_page(bsh);
+ endva = x86_round_page(bsh + size);
+
+#ifdef DIAGNOSTIC
+ if (endva <= va)
+ panic("x86_memio_unmap: overflow");
+#endif
+
+ (void) pmap_extract(pmap_kernel(), va, &bpa);
+ bpa += (bsh & PGOFSET);
+
+ pmap_kremove(va, endva - va);
+ /*
+ * Free the kernel virtual mapping.
+ */
+ uvm_km_free(kernel_map, va, endva - va);
+ } else
+ panic("x86_memio_unmap: bad bus space tag");
+
+ok:
+ if (extent_free(ex, bpa, size,
+ EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
+ printf("x86_memio_unmap: %s 0x%lx, size 0x%lx\n",
+ (t == X86_BUS_SPACE_IO) ? "port" : "pa", bpa, size);
+ printf("x86_memio_unmap: can't free region\n");
+ }
+}
+
+void
+x86_memio_free(t, bsh, size)
+ bus_space_tag_t t;
+ bus_space_handle_t bsh;
+ bus_size_t size;
+{
+
+ /* x86_memio_unmap() does all that we need to do. */
+ x86_memio_unmap(t, bsh, size);
+}
+
+int
+x86_memio_subregion(t, bsh, offset, size, nbshp)
+ bus_space_tag_t t;
+ bus_space_handle_t bsh;
+ bus_size_t offset, size;
+ bus_space_handle_t *nbshp;
+{
+
+ *nbshp = bsh + offset;
+ return (0);
+}
+
+paddr_t
+x86_memio_mmap(t, addr, off, prot, flags)
+ bus_space_tag_t t;
+ bus_addr_t addr;
+ off_t off;
+ int prot;
+ int flags;
+{
+
+ /* Can't mmap I/O space. */
+ if (t == X86_BUS_SPACE_IO)
+ return (-1);
+
+ /*
+ * "addr" is the base address of the device we're mapping.
+ * "off" is the offset into that device.
+ *
+ * Note we are called for each "page" in the device that
+ * the upper layers want to map.
+ */
+ return (x86_btop(addr + off));
+}
diff --git a/sys/arch/amd64/amd64/cacheinfo.c b/sys/arch/amd64/amd64/cacheinfo.c
new file mode 100644
index 00000000000..813825c4d44
--- /dev/null
+++ b/sys/arch/amd64/amd64/cacheinfo.c
@@ -0,0 +1,237 @@
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/cpu.h>
+#include <machine/specialreg.h>
+
+static char *print_cache_config(struct cpu_info *, int, char *, char *);
+static char *print_tlb_config(struct cpu_info *, int, char *, char *);
+
+static char *
+print_cache_config(struct cpu_info *ci, int cache_tag, char *name, char *sep)
+{
+ struct x86_cache_info *cai = &ci->ci_cinfo[cache_tag];
+
+ if (cai->cai_totalsize == 0)
+ return sep;
+
+ if (sep == NULL)
+ printf("%s: ", ci->ci_dev->dv_xname);
+ else
+ printf("%s", sep);
+ if (name != NULL)
+ printf("%s ", name);
+
+ if (cai->cai_string != NULL) {
+ printf("%s ", cai->cai_string);
+ } else {
+ printf("%d %db/line ", cai->cai_totalsize, cai->cai_linesize);
+ }
+ switch (cai->cai_associativity) {
+ case 0:
+ printf("disabled");
+ break;
+ case 1:
+ printf("direct-mapped");
+ break;
+ case 0xff:
+ printf("fully associative");
+ break;
+ default:
+ printf("%d-way", cai->cai_associativity);
+ break;
+ }
+ return ", ";
+}
+
+static char *
+print_tlb_config(struct cpu_info *ci, int cache_tag, char *name, char *sep)
+{
+ struct x86_cache_info *cai = &ci->ci_cinfo[cache_tag];
+
+ if (cai->cai_totalsize == 0)
+ return sep;
+
+ if (sep == NULL)
+ printf("%s: ", ci->ci_dev->dv_xname);
+ else
+ printf("%s", sep);
+ if (name != NULL)
+ printf("%s ", name);
+
+ if (cai->cai_string != NULL) {
+ printf("%s", cai->cai_string);
+ } else {
+ printf("%d %d entries ", cai->cai_totalsize, cai->cai_linesize);
+ switch (cai->cai_associativity) {
+ case 0:
+ printf("disabled");
+ break;
+ case 1:
+ printf("direct-mapped");
+ break;
+ case 0xff:
+ printf("fully associative");
+ break;
+ default:
+ printf("%d-way", cai->cai_associativity);
+ break;
+ }
+ }
+ return ", ";
+}
+
+const struct x86_cache_info *
+cache_info_lookup(const struct x86_cache_info *cai, u_int8_t desc)
+{
+ int i;
+
+ for (i = 0; cai[i].cai_desc != 0; i++) {
+ if (cai[i].cai_desc == desc)
+ return (&cai[i]);
+ }
+
+ return (NULL);
+}
+
+
+static const struct x86_cache_info amd_cpuid_l2cache_assoc_info[] = {
+ { 0, 0x01, 1 },
+ { 0, 0x02, 2 },
+ { 0, 0x04, 4 },
+ { 0, 0x06, 8 },
+ { 0, 0x08, 16 },
+ { 0, 0x0f, 0xff },
+ { 0, 0x00, 0 },
+};
+
+void
+amd_cpu_cacheinfo(struct cpu_info *ci)
+{
+ const struct x86_cache_info *cp;
+ struct x86_cache_info *cai;
+ int family, model;
+ u_int descs[4];
+ u_int lfunc;
+
+ family = (ci->ci_signature >> 8) & 15;
+ model = CPUID2MODEL(ci->ci_signature);
+
+ /*
+ * K5 model 0 has none of this info.
+ */
+ if (family == 5 && model == 0)
+ return;
+
+ /*
+ * Get extended values for K8 and up.
+ */
+ if (family == 0xf) {
+ family += (ci->ci_signature >> 20) & 0xff;
+ model += (ci->ci_signature >> 16) & 0xf;
+ }
+
+ /*
+ * Determine the largest extended function value.
+ */
+ CPUID(0x80000000, descs[0], descs[1], descs[2], descs[3]);
+ lfunc = descs[0];
+
+ /*
+ * Determine L1 cache/TLB info.
+ */
+ if (lfunc < 0x80000005) {
+ /* No L1 cache info available. */
+ return;
+ }
+
+ CPUID(0x80000005, descs[0], descs[1], descs[2], descs[3]);
+
+ /*
+ * K6-III and higher have large page TLBs.
+ */
+ if ((family == 5 && model >= 9) || family >= 6) {
+ cai = &ci->ci_cinfo[CAI_ITLB2];
+ cai->cai_totalsize = AMD_L1_EAX_ITLB_ENTRIES(descs[0]);
+ cai->cai_associativity = AMD_L1_EAX_ITLB_ASSOC(descs[0]);
+ cai->cai_linesize = (4 * 1024 * 1024);
+
+ cai = &ci->ci_cinfo[CAI_DTLB2];
+ cai->cai_totalsize = AMD_L1_EAX_DTLB_ENTRIES(descs[0]);
+ cai->cai_associativity = AMD_L1_EAX_DTLB_ASSOC(descs[0]);
+ cai->cai_linesize = (4 * 1024 * 1024);
+ }
+
+ cai = &ci->ci_cinfo[CAI_ITLB];
+ cai->cai_totalsize = AMD_L1_EBX_ITLB_ENTRIES(descs[1]);
+ cai->cai_associativity = AMD_L1_EBX_ITLB_ASSOC(descs[1]);
+ cai->cai_linesize = (4 * 1024);
+
+ cai = &ci->ci_cinfo[CAI_DTLB];
+ cai->cai_totalsize = AMD_L1_EBX_DTLB_ENTRIES(descs[1]);
+ cai->cai_associativity = AMD_L1_EBX_DTLB_ASSOC(descs[1]);
+ cai->cai_linesize = (4 * 1024);
+
+ cai = &ci->ci_cinfo[CAI_DCACHE];
+ cai->cai_totalsize = AMD_L1_ECX_DC_SIZE(descs[2]);
+ cai->cai_associativity = AMD_L1_ECX_DC_ASSOC(descs[2]);
+ cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[2]);
+
+ cai = &ci->ci_cinfo[CAI_ICACHE];
+ cai->cai_totalsize = AMD_L1_EDX_IC_SIZE(descs[3]);
+ cai->cai_associativity = AMD_L1_EDX_IC_ASSOC(descs[3]);
+ cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[3]);
+
+ /*
+ * Determine L2 cache/TLB info.
+ */
+ if (lfunc < 0x80000006) {
+ /* No L2 cache info available. */
+ return;
+ }
+
+ CPUID(0x80000006, descs[0], descs[1], descs[2], descs[3]);
+
+ cai = &ci->ci_cinfo[CAI_L2CACHE];
+ cai->cai_totalsize = AMD_L2_ECX_C_SIZE(descs[2]);
+ cai->cai_associativity = AMD_L2_ECX_C_ASSOC(descs[2]);
+ cai->cai_linesize = AMD_L2_ECX_C_LS(descs[2]);
+
+ cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
+ cai->cai_associativity);
+ if (cp != NULL)
+ cai->cai_associativity = cp->cai_associativity;
+ else
+ cai->cai_associativity = 0; /* XXX Unknown/reserved */
+}
+
+void
+x86_print_cacheinfo(struct cpu_info *ci)
+{
+ char *sep;
+
+ if (ci->ci_cinfo[CAI_ICACHE].cai_totalsize != 0 ||
+ ci->ci_cinfo[CAI_DCACHE].cai_totalsize != 0) {
+ sep = print_cache_config(ci, CAI_ICACHE, "I-cache", NULL);
+ sep = print_cache_config(ci, CAI_DCACHE, "D-cache", sep);
+ if (sep != NULL)
+ printf("\n");
+ }
+ if (ci->ci_cinfo[CAI_L2CACHE].cai_totalsize != 0) {
+ sep = print_cache_config(ci, CAI_L2CACHE, "L2 cache", NULL);
+ if (sep != NULL)
+ printf("\n");
+ }
+ if (ci->ci_cinfo[CAI_ITLB].cai_totalsize != 0) {
+ sep = print_tlb_config(ci, CAI_ITLB, "ITLB", NULL);
+ sep = print_tlb_config(ci, CAI_ITLB2, NULL, sep);
+ if (sep != NULL)
+ printf("\n");
+ }
+ if (ci->ci_cinfo[CAI_DTLB].cai_totalsize != 0) {
+ sep = print_tlb_config(ci, CAI_DTLB, "DTLB", NULL);
+ sep = print_tlb_config(ci, CAI_DTLB2, NULL, sep);
+ if (sep != NULL)
+ printf("\n");
+ }
+}
diff --git a/sys/arch/amd64/amd64/conf.c b/sys/arch/amd64/amd64/conf.c
new file mode 100644
index 00000000000..cb6c91516c1
--- /dev/null
+++ b/sys/arch/amd64/amd64/conf.c
@@ -0,0 +1,455 @@
+/* $OpenBSD: conf.c,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Charles Hannum.
+ * 4. 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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/device.h>
+#include <sys/disklabel.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/vnode.h>
+
+#include <machine/conf.h>
+
+#include "inet.h"
+
+#include "wd.h"
+bdev_decl(wd);
+#include "fdc.h"
+#include "fd.h"
+bdev_decl(fd);
+#include "wt.h"
+bdev_decl(wt);
+#include "sd.h"
+#include "ses.h"
+#include "st.h"
+#include "cd.h"
+#include "uk.h"
+#include "mcd.h"
+bdev_decl(mcd);
+#include "vnd.h"
+#include "ccd.h"
+#include "raid.h"
+#include "rd.h"
+
+struct bdevsw bdevsw[] =
+{
+ bdev_disk_init(NWD,wd), /* 0: ST506/ESDI/IDE disk */
+ bdev_swap_init(1,sw), /* 1: swap pseudo-device */
+ bdev_disk_init(NFD,fd), /* 2: floppy diskette */
+ bdev_tape_init(NWT,wt), /* 3: QIC-02/QIC-36 tape */
+ bdev_disk_init(NSD,sd), /* 4: SCSI disk */
+ bdev_tape_init(NST,st), /* 5: SCSI tape */
+ bdev_disk_init(NCD,cd), /* 6: SCSI CD-ROM */
+ bdev_disk_init(NMCD,mcd), /* 7: Mitsumi CD-ROM */
+ bdev_lkm_dummy(), /* 8 */
+ bdev_lkm_dummy(), /* 9 */
+ bdev_lkm_dummy(), /* 10 */
+ bdev_lkm_dummy(), /* 11 */
+ bdev_lkm_dummy(), /* 12 */
+ bdev_lkm_dummy(), /* 13 */
+ bdev_disk_init(NVND,vnd), /* 14: vnode disk driver */
+ bdev_lkm_dummy(), /* 15: Sony CD-ROM */
+ bdev_disk_init(NCCD,ccd), /* 16: concatenated disk driver */
+ bdev_disk_init(NRD,rd), /* 17: ram disk driver */
+ bdev_lkm_dummy(), /* 18 */
+ bdev_disk_init(NRAID,raid), /* 19: RAIDframe disk driver */
+};
+int nblkdev = sizeof(bdevsw) / sizeof(bdevsw[0]);
+
+/* open, close, read, write, ioctl, tty, mmap */
+#define cdev_pc_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+ dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \
+ dev_init(c,n,tty), ttselect, dev_init(c,n,mmap), D_TTY }
+
+/* open, close, read, ioctl */
+#define cdev_joy_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, 0, seltrue, \
+ (dev_type_mmap((*))) enodev }
+
+/* open, close, ioctl -- XXX should be a generic device */
+#define cdev_oci_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, 0, seltrue, \
+ (dev_type_mmap((*))) enodev, 0 }
+
+/* open, close, ioctl, select -- XXX should be a generic device */
+#define cdev_ocis_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, 0, dev_init(c,n,select), \
+ (dev_type_mmap((*))) enodev, 0 }
+
+/* open, close, read, ioctl */
+#define cdev_wdt_init(c, n) { \
+ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, 0, seltrue, (dev_type_mmap((*))) enodev }
+
+
+#define mmread mmrw
+#define mmwrite mmrw
+cdev_decl(mm);
+cdev_decl(wd);
+#include "systrace.h"
+#include "bio.h"
+#include "pty.h"
+#include "com.h"
+cdev_decl(com);
+cdev_decl(fd);
+cdev_decl(wt);
+cdev_decl(scd);
+#include "ss.h"
+#include "lpt.h"
+cdev_decl(lpt);
+#include "ch.h"
+#include "bpfilter.h"
+#if 0
+#include "pcmcia.h"
+cdev_decl(pcmcia);
+#endif
+#include "spkr.h"
+cdev_decl(spkr);
+#if 0 /* old (non-wsmouse) drivers */
+#include "mms.h"
+cdev_decl(mms);
+#include "lms.h"
+cdev_decl(lms);
+#include "opms.h"
+cdev_decl(pms);
+#endif
+#include "cy.h"
+cdev_decl(cy);
+cdev_decl(mcd);
+#include "tun.h"
+#include "audio.h"
+#include "midi.h"
+#include "sequencer.h"
+cdev_decl(music);
+#include "iop.h"
+#ifdef XFS
+#include <xfs/nxfs.h>
+cdev_decl(xfs_dev);
+#endif
+#include "bktr.h"
+#include "wdt.h"
+cdev_decl(wdt);
+#include "ksyms.h"
+#include "usb.h"
+#include "uhid.h"
+#include "ugen.h"
+#include "ulpt.h"
+#include "urio.h"
+#include "ucom.h"
+#include "uscanner.h"
+#include "cz.h"
+cdev_decl(cztty);
+#include "radio.h"
+
+#include "wsdisplay.h"
+#include "wskbd.h"
+#include "wsmouse.h"
+#include "wsmux.h"
+
+#ifdef USER_PCICONF
+#include "pci.h"
+cdev_decl(pci);
+#endif
+
+#include "pf.h"
+
+struct cdevsw cdevsw[] =
+{
+ cdev_cn_init(1,cn), /* 0: virtual console */
+ cdev_ctty_init(1,ctty), /* 1: controlling terminal */
+ cdev_mm_init(1,mm), /* 2: /dev/{null,mem,kmem,...} */
+ cdev_disk_init(NWD,wd), /* 3: ST506/ESDI/IDE disk */
+ cdev_swap_init(1,sw), /* 4: /dev/drum (swap pseudo-device) */
+ cdev_tty_init(NPTY,pts), /* 5: pseudo-tty slave */
+ cdev_ptc_init(NPTY,ptc), /* 6: pseudo-tty master */
+ cdev_log_init(1,log), /* 7: /dev/klog */
+ cdev_tty_init(NCOM,com), /* 8: serial port */
+ cdev_disk_init(NFD,fd), /* 9: floppy disk */
+ cdev_tape_init(NWT,wt), /* 10: QIC-02/QIC-36 tape */
+ cdev_lkm_dummy(), /* 11: Sony CD-ROM */
+ cdev_wsdisplay_init(NWSDISPLAY, /* 12: frame buffers, etc. */
+ wsdisplay),
+ cdev_disk_init(NSD,sd), /* 13: SCSI disk */
+ cdev_tape_init(NST,st), /* 14: SCSI tape */
+ cdev_disk_init(NCD,cd), /* 15: SCSI CD-ROM */
+ cdev_lpt_init(NLPT,lpt), /* 16: parallel printer */
+ cdev_ch_init(NCH,ch), /* 17: SCSI autochanger */
+ cdev_disk_init(NCCD,ccd), /* 18: concatenated disk driver */
+ cdev_ss_init(NSS,ss), /* 19: SCSI scanner */
+ cdev_uk_init(NUK,uk), /* 20: unknown SCSI */
+ cdev_notdef(), /* 21 */
+ cdev_fd_init(1,filedesc), /* 22: file descriptor pseudo-device */
+ cdev_bpftun_init(NBPFILTER,bpf),/* 23: Berkeley packet filter */
+ cdev_ses_init(NSES,ses), /* 24: SES/SAF-TE SCSI */
+#if 0
+ cdev_ocis_init(NPCMCIA,pcmcia), /* 25: PCMCIA Bus */
+#else
+ cdev_notdef(), /* 25 */
+#endif
+ cdev_notdef(), /* 26 */
+ cdev_spkr_init(NSPKR,spkr), /* 27: PC speaker */
+ cdev_lkm_init(NLKM,lkm), /* 28: loadable module driver */
+ cdev_lkm_dummy(), /* 29 */
+ cdev_lkm_dummy(), /* 30 */
+ cdev_lkm_dummy(), /* 31 */
+ cdev_lkm_dummy(), /* 32 */
+ cdev_lkm_dummy(), /* 33 */
+ cdev_lkm_dummy(), /* 34 */
+ cdev_notdef(), /* 35: Microsoft mouse */
+ cdev_notdef(), /* 36: Logitech mouse */
+ cdev_notdef(), /* 37: Extended PS/2 mouse */
+ cdev_tty_init(NCY,cy), /* 38: Cyclom serial port */
+ cdev_disk_init(NMCD,mcd), /* 39: Mitsumi CD-ROM */
+ cdev_bpftun_init(NTUN,tun), /* 40: network tunnel */
+ cdev_disk_init(NVND,vnd), /* 41: vnode disk driver */
+ cdev_audio_init(NAUDIO,audio), /* 42: generic audio I/O */
+#ifdef COMPAT_SVR4
+ cdev_svr4_net_init(1,svr4_net), /* 43: svr4 net pseudo-device */
+#else
+ cdev_notdef(), /* 43 */
+#endif
+ cdev_notdef(), /* 44 */
+ cdev_random_init(1,random), /* 45: random data source */
+ cdev_notdef(), /* 46 */
+ cdev_disk_init(NRD,rd), /* 47: ram disk driver */
+ cdev_notdef(), /* 48 */
+ cdev_bktr_init(NBKTR,bktr), /* 49: Bt848 video capture device */
+ cdev_ksyms_init(NKSYMS,ksyms), /* 50: Kernel symbols device */
+#ifdef XFS
+ cdev_xfs_init(NXFS,xfs_dev), /* 51: xfs communication device */
+#else
+ cdev_notdef(), /* 51 */
+#endif
+ cdev_midi_init(NMIDI,midi), /* 52: MIDI I/O */
+ cdev_midi_init(NSEQUENCER,sequencer), /* 53: sequencer I/O */
+ cdev_disk_init(NRAID,raid), /* 54: RAIDframe disk driver */
+ cdev_wdt_init(NWDT,wdt), /* 55: WDT50x watchdog timer */
+ /* The following slots are reserved for isdn4bsd. */
+ cdev_notdef(), /* 56: i4b main device */
+ cdev_notdef(), /* 57: i4b control device */
+ cdev_notdef(), /* 58: i4b raw b-channel access */
+ cdev_notdef(), /* 59: i4b trace device */
+ cdev_notdef(), /* 60: i4b phone device */
+ /* End of reserved slots for isdn4bsd. */
+ cdev_usb_init(NUSB,usb), /* 61: USB controller */
+ cdev_usbdev_init(NUHID,uhid), /* 62: USB generic HID */
+ cdev_usbdev_init(NUGEN,ugen), /* 63: USB generic driver */
+ cdev_ulpt_init(NULPT,ulpt), /* 64: USB printers */
+ cdev_usbdev_init(NURIO,urio), /* 65: USB Diamond Rio 500 */
+ cdev_tty_init(NUCOM,ucom), /* 66: USB tty */
+ cdev_mouse_init(NWSKBD, wskbd), /* 67: keyboards */
+ cdev_mouse_init(NWSMOUSE, /* 68: mice */
+ wsmouse),
+ cdev_mouse_init(NWSMUX, wsmux), /* 69: ws multiplexor */
+ cdev_crypto_init(NCRYPTO,crypto), /* 70: /dev/crypto */
+ cdev_tty_init(NCZ,cztty), /* 71: Cyclades-Z serial port */
+#ifdef USER_PCICONF
+ cdev_pci_init(NPCI,pci), /* 72: PCI user */
+#else
+ cdev_notdef(),
+#endif
+ cdev_pf_init(NPF,pf), /* 73: packet filter */
+ cdev_notdef(), /* 74: ALTQ (deprecated) */
+ cdev_iop_init(NIOP,iop), /* 75: I2O IOP control interface */
+ cdev_radio_init(NRADIO, radio), /* 76: generic radio I/O */
+ cdev_usbdev_init(NUSCANNER,uscanner), /* 77: USB scanners */
+ cdev_systrace_init(NSYSTRACE,systrace), /* 78: system call tracing */
+ cdev_oci_init(NBIO,bio), /* 79: ioctl tunnel */
+};
+int nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);
+
+int mem_no = 2; /* major device number of memory special file */
+
+/*
+ * Swapdev is a fake device implemented
+ * in sw.c used only internally to get to swstrategy.
+ * It cannot be provided to the users, because the
+ * swstrategy routine munches the b_dev and b_blkno entries
+ * before calling the appropriate driver. This would horribly
+ * confuse, e.g. the hashing routines. Instead, /dev/drum is
+ * provided as a character (raw) device.
+ */
+dev_t swapdev = makedev(1, 0);
+
+/*
+ * Returns true if dev is /dev/mem or /dev/kmem.
+ */
+int
+iskmemdev(dev)
+ dev_t dev;
+{
+
+ return (major(dev) == mem_no && (minor(dev) < 2 || minor(dev) == 14));
+}
+
+/*
+ * Returns true if dev is /dev/zero.
+ */
+int
+iszerodev(dev)
+ dev_t dev;
+{
+
+ return (major(dev) == mem_no && minor(dev) == 12);
+}
+
+dev_t
+getnulldev()
+{
+ return makedev(mem_no, 2);
+}
+
+int chrtoblktbl[] = {
+ /* XXXX This needs to be dynamic for LKMs. */
+ /*VCHR*/ /*VBLK*/
+ /* 0 */ NODEV,
+ /* 1 */ NODEV,
+ /* 2 */ NODEV,
+ /* 3 */ 0,
+ /* 4 */ NODEV,
+ /* 5 */ NODEV,
+ /* 6 */ NODEV,
+ /* 7 */ NODEV,
+ /* 8 */ NODEV,
+ /* 9 */ 2,
+ /* 10 */ 3,
+ /* 11 */ 15,
+ /* 12 */ NODEV,
+ /* 13 */ 4,
+ /* 14 */ 5,
+ /* 15 */ 6,
+ /* 16 */ NODEV,
+ /* 17 */ NODEV,
+ /* 18 */ 16,
+ /* 19 */ NODEV,
+ /* 20 */ NODEV,
+ /* 21 */ NODEV,
+ /* 22 */ NODEV,
+ /* 23 */ NODEV,
+ /* 24 */ 18,
+ /* 25 */ NODEV,
+ /* 26 */ NODEV,
+ /* 27 */ NODEV,
+ /* 28 */ NODEV,
+ /* 29 */ NODEV,
+ /* 30 */ NODEV,
+ /* 31 */ NODEV,
+ /* 32 */ NODEV,
+ /* 33 */ NODEV,
+ /* 34 */ NODEV,
+ /* 35 */ NODEV,
+ /* 36 */ NODEV,
+ /* 37 */ NODEV,
+ /* 38 */ NODEV,
+ /* 39 */ 7,
+ /* 40 */ NODEV,
+ /* 41 */ 14,
+ /* 42 */ NODEV,
+ /* 43 */ NODEV,
+ /* 44 */ NODEV,
+ /* 45 */ NODEV,
+ /* 46 */ NODEV,
+ /* 47 */ 17,
+ /* 48 */ NODEV,
+ /* 49 */ NODEV,
+ /* 50 */ NODEV,
+ /* 51 */ NODEV,
+ /* 52 */ NODEV,
+ /* 53 */ NODEV,
+ /* 54 */ 19,
+};
+
+int nchrtoblktbl = sizeof(chrtoblktbl) / sizeof(chrtoblktbl[0]);
+
+/*
+ * In order to map BSD bdev numbers of disks to their BIOS equivalents
+ * we use several heuristics, one being using checksums of the first
+ * few blocks of a disk to get a signature we can match with /boot's
+ * computed signatures. To know where from to read, we must provide a
+ * disk driver name -> bdev major number table, which follows.
+ * Note: floppies are not included as those are differentiated by the BIOS.
+ */
+int findblkmajor(struct device *dv);
+dev_t dev_rawpart(struct device *); /* XXX */
+
+dev_t
+dev_rawpart(dv)
+ struct device *dv;
+{
+ int majdev;
+
+ majdev = findblkmajor(dv);
+
+ switch (majdev) {
+ /* add here any device you want to be checksummed on boot */
+ case 0: /* wd */
+ case 4: /* sd */
+ return (MAKEDISKDEV(majdev, dv->dv_unit, RAW_PART));
+ break;
+ default:
+ ;
+ }
+
+ return (NODEV);
+}
+
+/*
+ * This entire table could be autoconfig()ed but that would mean that
+ * the kernel's idea of the console would be out of sync with that of
+ * the standalone boot. I think it best that they both use the same
+ * known algorithm unless we see a pressing need otherwise.
+ */
+#include <dev/cons.h>
+
+cons_decl(pc);
+cons_decl(com);
+cons_decl(ws);
+
+struct consdev constab[] = {
+#if 1 || NWSDISPLAY > 0
+ cons_init(ws),
+#endif
+#if 0 && NCOM > 0
+ cons_init(com),
+#endif
+ { 0 },
+};
+
diff --git a/sys/arch/amd64/amd64/consinit.c b/sys/arch/amd64/amd64/consinit.c
new file mode 100644
index 00000000000..2a167480017
--- /dev/null
+++ b/sys/arch/amd64/amd64/consinit.c
@@ -0,0 +1,61 @@
+/* $OpenBSD: consinit.c,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+/* $NetBSD: consinit.c,v 1.2 2003/03/02 18:27:14 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1998
+ * Matthias Drochner. 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 ``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.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <machine/bus.h>
+#include <machine/bootinfo.h>
+
+#include <dev/cons.h>
+
+void
+consinit()
+{
+ static int initted;
+
+ if (initted)
+ return;
+ initted = 1;
+ cninit();
+}
+
+#if (NPCKBC > 0) && (NPCKBD == 0)
+/*
+ * glue code to support old console code with the
+ * mi keyboard controller driver
+ */
+int
+pckbc_machdep_cnattach(kbctag, kbcslot)
+ pckbc_tag_t kbctag;
+ pckbc_slot_t kbcslot;
+{
+ return (ENXIO);
+}
+#endif
diff --git a/sys/arch/amd64/amd64/copy.S b/sys/arch/amd64/amd64/copy.S
new file mode 100644
index 00000000000..6a8a1b3d2cd
--- /dev/null
+++ b/sys/arch/amd64/amd64/copy.S
@@ -0,0 +1,321 @@
+/* $OpenBSD: copy.S,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+/* $NetBSD: copy.S,v 1.1 2003/04/26 18:39:26 fvdl Exp $ */
+
+/*
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Frank van der Linden for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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 "assym.h"
+
+#include <sys/errno.h>
+#include <sys/syscall.h>
+
+#include <machine/asm.h>
+
+/*
+ * Copy routines from and to userland, plus a few more. See the
+ * section 9 manpages for info. Some cases can be optimized more.
+ *
+ * I wonder if it's worthwhile to make these use SSE2 registers.
+ */
+
+/*
+ * XXXfvdl appears only to be used by pccons.
+ *
+ * fillw(short pattern, caddr_t addr, size_t len);
+ * Write len copies of pattern at addr.
+ * appears to be used by pccons.
+ */
+ENTRY(fillw)
+ movl %edi,%eax
+ movq %rsi,%rdi
+ movw %ax,%cx
+ rorl $16,%eax
+ movw %cx,%ax
+ cld
+ movq %rdx,%rcx
+ shrq %rcx
+ rep
+ stosl
+ movq %rdx,%rcx
+ andq $1,%rcx
+ rep
+ stosw
+ ret
+
+ENTRY(kcopy)
+ movq CPUVAR(CURPCB),%rax
+ pushq PCB_ONFAULT(%rax)
+ leaq _C_LABEL(copy_fault)(%rip),%r11
+ movq %r11, PCB_ONFAULT(%rax)
+
+ xchgq %rdi,%rsi
+ movq %rdx,%rcx
+
+ movq %rdi,%rax
+ subq %rsi,%rax
+ cmpq %rcx,%rax # overlapping?
+ jb 1f
+ cld # nope, copy forward
+ shrq $3,%rcx # copy by 64-bit words
+ rep
+ movsq
+
+ movq %rdx,%rcx
+ andl $7,%ecx # any bytes left?
+ rep
+ movsb
+
+ movq CPUVAR(CURPCB),%rdx
+ popq PCB_ONFAULT(%rdx)
+ xorq %rax,%rax
+ ret
+
+1: addq %rcx,%rdi # copy backward
+ addq %rcx,%rsi
+ std
+ andq $7,%rcx # any fractional bytes?
+ decq %rdi
+ decq %rsi
+ rep
+ movsb
+ movq %rdx,%rcx # copy remainder by 64-bit words
+ shrq $3,%rcx
+ subq $7,%rsi
+ subq $7,%rdi
+ rep
+ movsq
+ cld
+
+ movq CPUVAR(CURPCB),%rdx
+ popq PCB_ONFAULT(%rdx)
+ xorq %rax,%rax
+ ret
+
+ENTRY(copyout)
+ pushq $0
+
+ xchgq %rdi,%rsi
+ movq %rdx,%rax
+
+ movq %rdi,%rdx
+ addq %rax,%rdx
+ jc _C_LABEL(copy_efault)
+ movq $VM_MAXUSER_ADDRESS,%r8
+ cmpq %r8,%rdx
+ ja _C_LABEL(copy_efault)
+
+ movq CPUVAR(CURPCB),%rdx
+ leaq _C_LABEL(copy_fault)(%rip),%r11
+ movq %r11,PCB_ONFAULT(%rdx)
+
+ cld
+ movq %rax,%rcx
+ shrq $3,%rcx
+ rep
+ movsq
+ movb %al,%cl
+ andb $7,%cl
+ rep
+ movsb
+
+ popq PCB_ONFAULT(%rdx)
+ xorl %eax,%eax
+ ret
+
+ENTRY(copyin)
+ movq CPUVAR(CURPCB),%rax
+ pushq $0
+ leaq _C_LABEL(copy_fault)(%rip),%r11
+ movq %r11,PCB_ONFAULT(%rax)
+
+ xchgq %rdi,%rsi
+ movq %rdx,%rax
+
+ movq %rsi,%rdx
+ addq %rax,%rdx
+ jc _C_LABEL(copy_efault)
+ movq $VM_MAXUSER_ADDRESS,%r8
+ cmpq %r8,%rdx
+ ja _C_LABEL(copy_efault)
+
+3: /* bcopy(%rsi, %rdi, %rax); */
+ cld
+ movq %rax,%rcx
+ shrq $3,%rcx
+ rep
+ movsq
+ movb %al,%cl
+ andb $7,%cl
+ rep
+ movsb
+
+ movq CPUVAR(CURPCB),%rdx
+ popq PCB_ONFAULT(%rdx)
+ xorl %eax,%eax
+ ret
+
+NENTRY(copy_efault)
+ movq $EFAULT,%rax
+
+NENTRY(copy_fault)
+ movq CPUVAR(CURPCB),%rdx
+ popq PCB_ONFAULT(%rdx)
+ ret
+
+ENTRY(copyoutstr)
+ xchgq %rdi,%rsi
+ movq %rdx,%r8
+ movq %rcx,%r9
+
+5: movq CPUVAR(CURPCB),%rax
+ leaq _C_LABEL(copystr_fault)(%rip),%r11
+ movq %r11,PCB_ONFAULT(%rax)
+ /*
+ * Get min(%rdx, VM_MAXUSER_ADDRESS-%rdi).
+ */
+ movq $VM_MAXUSER_ADDRESS,%rax
+ subq %rdi,%rax
+ cmpq %rdx,%rax
+ jae 1f
+ movq %rax,%rdx
+ movq %rax,%r8
+
+1: incq %rdx
+ cld
+
+1: decq %rdx
+ jz 2f
+ lodsb
+ stosb
+ testb %al,%al
+ jnz 1b
+
+ /* Success -- 0 byte reached. */
+ decq %rdx
+ xorq %rax,%rax
+ jmp copystr_return
+
+2: /* rdx is zero -- return EFAULT or ENAMETOOLONG. */
+ movq $VM_MAXUSER_ADDRESS,%r11
+ cmpq %r11,%rdi
+ jae _C_LABEL(copystr_efault)
+ movq $ENAMETOOLONG,%rax
+ jmp copystr_return
+
+ENTRY(copyinstr)
+ xchgq %rdi,%rsi
+ movq %rdx,%r8
+ movq %rcx,%r9
+
+ movq CPUVAR(CURPCB),%rcx
+ leaq _C_LABEL(copystr_fault)(%rip),%r11
+ movq %r11,PCB_ONFAULT(%rcx)
+
+ /*
+ * Get min(%rdx, VM_MAXUSER_ADDRESS-%rsi).
+ */
+ movq $VM_MAXUSER_ADDRESS,%rax
+ subq %rsi,%rax
+ cmpq %rdx,%rax
+ jae 1f
+ movq %rax,%rdx
+ movq %rax,%r8
+
+1: incq %rdx
+ cld
+
+1: decq %rdx
+ jz 2f
+ lodsb
+ stosb
+ testb %al,%al
+ jnz 1b
+
+ /* Success -- 0 byte reached. */
+ decq %rdx
+ xorq %rax,%rax
+ jmp copystr_return
+
+2: /* edx is zero -- return EFAULT or ENAMETOOLONG. */
+ movq $VM_MAXUSER_ADDRESS,%r11
+ cmpq %r11,%rsi
+ jae _C_LABEL(copystr_efault)
+ movq $ENAMETOOLONG,%rax
+ jmp copystr_return
+
+ENTRY(copystr_efault)
+ movl $EFAULT,%eax
+
+ENTRY(copystr_fault)
+copystr_return:
+ /* Set *lencopied and return %eax. */
+ movq CPUVAR(CURPCB),%rcx
+ movq $0,PCB_ONFAULT(%rcx)
+ testq %r9,%r9
+ jz 8f
+ subq %rdx,%r8
+ movq %r8,(%r9)
+
+8: ret
+
+ENTRY(copystr)
+ xchgq %rdi,%rsi
+ movq %rdx,%r8
+
+ incq %rdx
+ cld
+
+1: decq %rdx
+ jz 4f
+ lodsb
+ stosb
+ testb %al,%al
+ jnz 1b
+
+ /* Success -- 0 byte reached. */
+ decq %rdx
+ xorl %eax,%eax
+ jmp 6f
+
+4: /* edx is zero -- return ENAMETOOLONG. */
+ movl $ENAMETOOLONG,%eax
+
+6: /* Set *lencopied and return %eax. */
+ testq %rcx,%rcx
+ jz 7f
+ subq %rdx,%r8
+ movq %r8,(%rcx)
+
+7: ret
diff --git a/sys/arch/amd64/amd64/cpu.c b/sys/arch/amd64/amd64/cpu.c
new file mode 100644
index 00000000000..d58a8acb3ce
--- /dev/null
+++ b/sys/arch/amd64/amd64/cpu.c
@@ -0,0 +1,699 @@
+/* $OpenBSD: cpu.c,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+/* $NetBSD: cpu.c,v 1.1 2003/04/26 18:39:26 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by RedBack Networks Inc.
+ *
+ * Author: Bill Sommerfeld
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999 Stefan Grefen
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 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 AND 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 "lapic.h"
+#include "ioapic.h"
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/cpuvar.h>
+#include <machine/pmap.h>
+#include <machine/vmparam.h>
+#include <machine/mpbiosvar.h>
+#include <machine/pcb.h>
+#include <machine/specialreg.h>
+#include <machine/segments.h>
+#include <machine/gdt.h>
+#include <machine/mtrr.h>
+#include <machine/pio.h>
+
+#if NLAPIC > 0
+#include <machine/apicvar.h>
+#include <machine/i82489reg.h>
+#include <machine/i82489var.h>
+#endif
+
+#if NIOAPIC > 0
+#include <machine/i82093var.h>
+#endif
+
+#include <dev/ic/mc146818reg.h>
+#include <i386/isa/nvram.h>
+#include <dev/isa/isareg.h>
+
+int cpu_match(struct device *, void *, void *);
+void cpu_attach(struct device *, struct device *, void *);
+
+struct cpu_softc {
+ struct device sc_dev; /* device tree glue */
+ struct cpu_info *sc_info; /* pointer to CPU info */
+};
+
+int mp_cpu_start(struct cpu_info *);
+void mp_cpu_start_cleanup(struct cpu_info *);
+struct cpu_functions mp_cpu_funcs = { mp_cpu_start, NULL,
+ mp_cpu_start_cleanup };
+
+struct cfattach cpu_ca = {
+ sizeof(struct cpu_softc), cpu_match, cpu_attach
+};
+
+struct cfdriver cpu_cd = {
+ NULL, "cpu", DV_DULL
+};
+
+/*
+ * Statically-allocated CPU info for the primary CPU (or the only
+ * CPU, on uniprocessors). The CPU info list is initialized to
+ * point at it.
+ */
+struct cpu_info cpu_info_primary = { 0, &cpu_info_primary };
+
+struct cpu_info *cpu_info_list = &cpu_info_primary;
+
+u_int32_t cpus_attached = 0;
+
+#ifdef MULTIPROCESSOR
+/*
+ * Array of CPU info structures. Must be statically-allocated because
+ * curproc, etc. are used early.
+ */
+struct cpu_info *cpu_info[X86_MAXPROCS] = { &cpu_info_primary };
+
+u_int32_t cpus_running = 0;
+
+void cpu_hatch(void *);
+static void cpu_boot_secondary(struct cpu_info *ci);
+static void cpu_start_secondary(struct cpu_info *ci);
+static void cpu_copy_trampoline(void);
+
+/*
+ * Runs once per boot once multiprocessor goo has been detected and
+ * the local APIC on the boot processor has been mapped.
+ *
+ * Called from lapic_boot_init() (from mpbios_scan()).
+ */
+void
+cpu_init_first()
+{
+ int cpunum = lapic_cpu_number();
+
+ if (cpunum != 0) {
+ cpu_info[0] = NULL;
+ cpu_info[cpunum] = &cpu_info_primary;
+ }
+
+ cpu_copy_trampoline();
+}
+#endif
+
+int
+cpu_match(struct device *parent, void *match, void *aux)
+{
+ struct cfdata *cf = match;
+ struct cpu_attach_args *caa = aux;
+
+ if (strcmp(caa->caa_name, cf->cf_driver->cd_name) == 0)
+ return 1;
+ return 0;
+}
+
+static void
+cpu_vm_init(struct cpu_info *ci)
+{
+ int ncolors = 2, i;
+
+ for (i = CAI_ICACHE; i <= CAI_L2CACHE; i++) {
+ struct x86_cache_info *cai;
+ int tcolors;
+
+ cai = &ci->ci_cinfo[i];
+
+ tcolors = atop(cai->cai_totalsize);
+ switch(cai->cai_associativity) {
+ case 0xff:
+ tcolors = 1; /* fully associative */
+ break;
+ case 0:
+ case 1:
+ break;
+ default:
+ tcolors /= cai->cai_associativity;
+ }
+ ncolors = max(ncolors, tcolors);
+ }
+
+#ifdef notyet
+ /*
+ * Knowing the size of the largest cache on this CPU, re-color
+ * our pages.
+ */
+ if (ncolors <= uvmexp.ncolors)
+ return;
+ printf("%s: %d page colors\n", ci->ci_dev->dv_xname, ncolors);
+ uvm_page_recolor(ncolors);
+#endif
+}
+
+
+void
+cpu_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct cpu_softc *sc = (void *) self;
+ struct cpu_attach_args *caa = aux;
+ struct cpu_info *ci;
+#if defined(MULTIPROCESSOR)
+ int cpunum = caa->cpu_number;
+ vaddr_t kstack;
+ struct pcb *pcb;
+#endif
+
+ /*
+ * If we're an Application Processor, allocate a cpu_info
+ * structure, otherwise use the primary's.
+ */
+ if (caa->cpu_role == CPU_ROLE_AP) {
+ ci = malloc(sizeof(*ci), M_DEVBUF, M_WAITOK);
+ memset(ci, 0, sizeof(*ci));
+#if defined(MULTIPROCESSOR)
+ if (cpu_info[cpunum] != NULL)
+ panic("cpu at apic id %d already attached?", cpunum);
+ cpu_info[cpunum] = ci;
+#endif
+#ifdef TRAPLOG
+ ci->ci_tlog_base = malloc(sizeof(struct tlog),
+ M_DEVBUF, M_WAITOK);
+#endif
+ } else {
+ ci = &cpu_info_primary;
+#if defined(MULTIPROCESSOR)
+ if (cpunum != lapic_cpu_number()) {
+ panic("%s: running cpu is at apic %d"
+ " instead of at expected %d",
+ sc->sc_dev.dv_xname, lapic_cpu_number(), cpunum);
+ }
+#endif
+ }
+
+ ci->ci_self = ci;
+ sc->sc_info = ci;
+
+ ci->ci_dev = self;
+ ci->ci_apicid = caa->cpu_number;
+#ifdef MULTIPROCESSOR
+ ci->ci_cpuid = ci->ci_apicid;
+#else
+ ci->ci_cpuid = 0; /* False for APs, but they're not used anyway */
+#endif
+ ci->ci_func = caa->cpu_func;
+
+ simple_lock_init(&ci->ci_slock);
+
+#if defined(MULTIPROCESSOR)
+ /*
+ * Allocate UPAGES contiguous pages for the idle PCB and stack.
+ */
+ kstack = uvm_km_alloc (kernel_map, USPACE);
+ if (kstack == 0) {
+ if (caa->cpu_role != CPU_ROLE_AP) {
+ panic("cpu_attach: unable to allocate idle stack for"
+ " primary");
+ }
+ printf("%s: unable to allocate idle stack\n",
+ sc->sc_dev.dv_xname);
+ return;
+ }
+ pcb = ci->ci_idle_pcb = (struct pcb *) kstack;
+ memset(pcb, 0, USPACE);
+
+ pcb->pcb_tss.tss_rsp0 = kstack + USPACE - 16;
+ pcb->pcb_rbp = pcb->pcb_rsp = kstack + USPACE - 16;
+ pcb->pcb_tss.tss_ist[0] = kstack + PAGE_SIZE - 16;
+ pcb->pcb_pmap = pmap_kernel();
+ pcb->pcb_cr0 = rcr0();
+ pcb->pcb_cr3 = pcb->pcb_pmap->pm_pdirpa;
+#endif
+
+ /* further PCB init done later. */
+
+ printf(": ");
+
+ switch (caa->cpu_role) {
+ case CPU_ROLE_SP:
+ printf("(uniprocessor)\n");
+ ci->ci_flags |= CPUF_PRESENT | CPUF_SP | CPUF_PRIMARY;
+ cpu_intr_init(ci);
+ identifycpu(ci);
+ cpu_init(ci);
+ break;
+
+ case CPU_ROLE_BP:
+ printf("apid %d (boot processor)\n", caa->cpu_number);
+ ci->ci_flags |= CPUF_PRESENT | CPUF_BSP | CPUF_PRIMARY;
+ cpu_intr_init(ci);
+ identifycpu(ci);
+ cpu_init(ci);
+
+#if NLAPIC > 0
+ /*
+ * Enable local apic
+ */
+ lapic_enable();
+ lapic_calibrate_timer(ci);
+#endif
+#if NIOAPIC > 0
+ ioapic_bsp_id = caa->cpu_number;
+#endif
+ break;
+
+ case CPU_ROLE_AP:
+ /*
+ * report on an AP
+ */
+ printf("apid %d (application processor)\n", caa->cpu_number);
+
+#if defined(MULTIPROCESSOR)
+ cpu_intr_init(ci);
+ gdt_alloc_cpu(ci);
+ cpu_start_secondary(ci);
+ if (ci->ci_flags & CPUF_PRESENT) {
+ identifycpu(ci);
+ ci->ci_next = cpu_info_list->ci_next;
+ cpu_info_list->ci_next = ci;
+ }
+#else
+ printf("%s: not started\n", sc->sc_dev.dv_xname);
+#endif
+ break;
+
+ default:
+ panic("unknown processor type??\n");
+ }
+ cpu_vm_init(ci);
+
+ cpus_attached |= (1 << ci->ci_cpuid);
+
+#if defined(MULTIPROCESSOR)
+ if (mp_verbose) {
+ printf("%s: kstack at 0x%lx for %d bytes\n",
+ sc->sc_dev.dv_xname, kstack, USPACE);
+ printf("%s: idle pcb at %p, idle sp at 0x%lx\n",
+ sc->sc_dev.dv_xname, pcb, pcb->pcb_rsp);
+ }
+#endif
+}
+
+/*
+ * Initialize the processor appropriately.
+ */
+
+void
+cpu_init(ci)
+ struct cpu_info *ci;
+{
+ /* configure the CPU if needed */
+ if (ci->cpu_setup != NULL)
+ (*ci->cpu_setup)(ci);
+
+ lcr0(rcr0() | CR0_WP);
+ lcr4(rcr4() | CR4_PGE | CR4_OSFXSR | CR4_OSXMMEXCPT);
+
+#ifdef MTRR
+ if ((ci->ci_flags & CPUF_AP) == 0)
+ i686_mtrr_init_first();
+ mtrr_init_cpu(ci);
+#endif
+
+#ifdef MULTIPROCESSOR
+ ci->ci_flags |= CPUF_RUNNING;
+ cpus_running |= 1 << ci->ci_cpuid;
+#endif
+}
+
+
+#ifdef MULTIPROCESSOR
+void
+cpu_boot_secondary_processors()
+{
+ struct cpu_info *ci;
+ u_long i;
+
+ for (i=0; i < X86_MAXPROCS; i++) {
+ ci = cpu_info[i];
+ if (ci == NULL)
+ continue;
+ if (ci->ci_idle_pcb == NULL)
+ continue;
+ if ((ci->ci_flags & CPUF_PRESENT) == 0)
+ continue;
+ if (ci->ci_flags & (CPUF_BSP|CPUF_SP|CPUF_PRIMARY))
+ continue;
+ cpu_boot_secondary(ci);
+ }
+}
+
+void
+cpu_init_idle_pcbs()
+{
+ struct cpu_info *ci;
+ u_long i;
+
+ for (i=0; i < X86_MAXPROCS; i++) {
+ ci = cpu_info[i];
+ if (ci == NULL)
+ continue;
+ if (ci->ci_idle_pcb == NULL)
+ continue;
+ if ((ci->ci_flags & CPUF_PRESENT) == 0)
+ continue;
+ x86_64_init_pcb_tss_ldt(ci);
+ }
+}
+
+void
+cpu_start_secondary (ci)
+ struct cpu_info *ci;
+{
+ struct pcb *pcb;
+ int i;
+ struct pmap *kmp = pmap_kernel();
+ extern u_int64_t mp_pdirpa;
+ extern vaddr_t lo32_vaddr;
+ extern paddr_t lo32_paddr;
+
+ /*
+ * The initial PML4 pointer must be below 4G, so if the
+ * current one isn't, use a "bounce buffer"
+ */
+ if (kmp->pm_pdirpa > 0xffffffff) {
+ memcpy((void *)lo32_vaddr, kmp->pm_pdir, PAGE_SIZE);
+ mp_pdirpa = lo32_paddr;
+ } else
+ mp_pdirpa = kmp->pm_pdirpa;
+
+ pcb = ci->ci_idle_pcb;
+
+ ci->ci_flags |= CPUF_AP;
+
+ printf("%s: starting\n", ci->ci_dev->dv_xname);
+
+ CPU_STARTUP(ci);
+
+ /*
+ * wait for it to become ready
+ */
+ for (i = 100000; (!(ci->ci_flags & CPUF_PRESENT)) && i>0;i--) {
+ delay(10);
+ }
+ if (! (ci->ci_flags & CPUF_PRESENT)) {
+ printf("%s: failed to become ready\n", ci->ci_dev->dv_xname);
+#if defined(MPDEBUG) && defined(DDB)
+ printf("dropping into debugger; continue from here to resume boot\n");
+ Debugger();
+#endif
+ }
+
+ CPU_START_CLEANUP(ci);
+}
+
+void
+cpu_boot_secondary(ci)
+ struct cpu_info *ci;
+{
+ int i;
+
+ ci->ci_flags |= CPUF_GO; /* XXX atomic */
+
+ for (i = 100000; (!(ci->ci_flags & CPUF_RUNNING)) && i>0;i--) {
+ delay(10);
+ }
+ if (! (ci->ci_flags & CPUF_RUNNING)) {
+ printf("cpu failed to start\n");
+#if defined(MPDEBUG) && defined(DDB)
+ printf("dropping into debugger; continue from here to resume boot\n");
+ Debugger();
+#endif
+ }
+}
+
+/*
+ * The CPU ends up here when its ready to run
+ * This is called from code in mptramp.s; at this point, we are running
+ * in the idle pcb/idle stack of the new cpu. When this function returns,
+ * this processor will enter the idle loop and start looking for work.
+ *
+ * XXX should share some of this with init386 in machdep.c
+ */
+void
+cpu_hatch(void *v)
+{
+ struct cpu_info *ci = (struct cpu_info *)v;
+ int s;
+
+ cpu_init_msrs(ci);
+
+ cpu_probe_features(ci);
+ cpu_feature &= ci->ci_feature_flags;
+
+#ifdef DEBUG
+ if (ci->ci_flags & CPUF_PRESENT)
+ panic("%s: already running!?", ci->ci_dev->dv_xname);
+#endif
+
+ ci->ci_flags |= CPUF_PRESENT;
+
+ lapic_enable();
+ lapic_initclocks();
+
+ while ((ci->ci_flags & CPUF_GO) == 0)
+ delay(10);
+#ifdef DEBUG
+ if (ci->ci_flags & CPUF_RUNNING)
+ panic("%s: already running!?", ci->ci_dev->dv_xname);
+#endif
+
+ lcr0(ci->ci_idle_pcb->pcb_cr0);
+ cpu_init_idt();
+ lapic_set_lvt();
+ gdt_init_cpu(ci);
+ fpuinit(ci);
+
+ lldt(GSYSSEL(GLDT_SEL, SEL_KPL));
+
+ cpu_init(ci);
+
+ s = splhigh();
+ lcr8(0);
+ enable_intr();
+
+ printf("%s: CPU %u running\n",ci->ci_dev->dv_xname, ci->ci_cpuid);
+#if defined(I586_CPU) || defined(I686_CPU)
+ if (ci->ci_feature_flags & CPUID_TSC)
+ cc_microset(ci);
+#endif
+ microtime(&ci->ci_schedstate.spc_runtime);
+ splx(s);
+}
+
+#if defined(DDB)
+
+#include <ddb/db_output.h>
+#include <machine/db_machdep.h>
+
+/*
+ * Dump cpu information from ddb.
+ */
+void
+cpu_debug_dump(void)
+{
+ struct cpu_info *ci;
+ CPU_INFO_ITERATOR cii;
+
+ db_printf("addr dev id flags ipis curproc fpcurproc\n");
+ for (CPU_INFO_FOREACH(cii, ci)) {
+ db_printf("%p %s %u %x %x %10p %10p\n",
+ ci,
+ ci->ci_dev == NULL ? "BOOT" : ci->ci_dev->dv_xname,
+ ci->ci_cpuid,
+ ci->ci_flags, ci->ci_ipis,
+ ci->ci_curproc,
+ ci->ci_fpcurproc);
+ }
+}
+#endif
+
+static void
+cpu_copy_trampoline()
+{
+ /*
+ * Copy boot code.
+ */
+ extern u_char cpu_spinup_trampoline[];
+ extern u_char cpu_spinup_trampoline_end[];
+ pmap_kenter_pa((vaddr_t)MP_TRAMPOLINE, /* virtual */
+ (paddr_t)MP_TRAMPOLINE, /* physical */
+ VM_PROT_ALL); /* protection */
+ memcpy((caddr_t)MP_TRAMPOLINE,
+ cpu_spinup_trampoline,
+ cpu_spinup_trampoline_end-cpu_spinup_trampoline);
+}
+
+#endif
+
+
+int
+mp_cpu_start(struct cpu_info *ci)
+{
+#if NLAPIC > 0
+ int error;
+#endif
+ unsigned short dwordptr[2];
+
+ /*
+ * "The BSP must initialize CMOS shutdown code to 0Ah ..."
+ */
+
+ outb(IO_RTC, NVRAM_RESET);
+ outb(IO_RTC+1, NVRAM_RESET_SOFT);
+
+ /*
+ * "and the warm reset vector (DWORD based at 40:67) to point
+ * to the AP startup code ..."
+ */
+
+ dwordptr[0] = 0;
+ dwordptr[1] = MP_TRAMPOLINE >> 4;
+
+ pmap_kenter_pa (0, 0, VM_PROT_READ|VM_PROT_WRITE);
+ memcpy ((u_int8_t *) 0x467, dwordptr, 4);
+ pmap_kremove (0, PAGE_SIZE);
+
+#if NLAPIC > 0
+ /*
+ * ... prior to executing the following sequence:"
+ */
+
+ if (ci->ci_flags & CPUF_AP) {
+ if ((error = x86_ipi_init(ci->ci_apicid)) != 0)
+ return error;
+
+ delay(10000);
+
+ if (cpu_feature & CPUID_APIC) {
+
+ if ((error = x86_ipi(MP_TRAMPOLINE/PAGE_SIZE,
+ ci->ci_apicid,
+ LAPIC_DLMODE_STARTUP)) != 0)
+ return error;
+ delay(200);
+
+ if ((error = x86_ipi(MP_TRAMPOLINE/PAGE_SIZE,
+ ci->ci_apicid,
+ LAPIC_DLMODE_STARTUP)) != 0)
+ return error;
+ delay(200);
+ }
+ }
+#endif
+ return 0;
+}
+
+void
+mp_cpu_start_cleanup(struct cpu_info *ci)
+{
+ /*
+ * Ensure the NVRAM reset byte contains something vaguely sane.
+ */
+
+ outb(IO_RTC, NVRAM_RESET);
+ outb(IO_RTC+1, NVRAM_RESET_RST);
+}
+
+typedef void (vector)(void);
+extern vector Xsyscall, Xsyscall32;
+
+void
+cpu_init_msrs(struct cpu_info *ci)
+{
+ wrmsr(MSR_STAR,
+ ((uint64_t)GSEL(GCODE_SEL, SEL_KPL) << 32) |
+ ((uint64_t)LSEL(LSYSRETBASE_SEL, SEL_UPL) << 48));
+ wrmsr(MSR_LSTAR, (uint64_t)Xsyscall);
+ wrmsr(MSR_CSTAR, (uint64_t)Xsyscall32);
+ wrmsr(MSR_SFMASK, PSL_NT|PSL_T|PSL_I|PSL_C);
+
+ wrmsr(MSR_FSBASE, 0);
+ wrmsr(MSR_GSBASE, (u_int64_t)ci);
+ wrmsr(MSR_KERNELGSBASE, 0);
+}
diff --git a/sys/arch/amd64/amd64/db_disasm.c b/sys/arch/amd64/amd64/db_disasm.c
new file mode 100644
index 00000000000..431afcc2551
--- /dev/null
+++ b/sys/arch/amd64/amd64/db_disasm.c
@@ -0,0 +1,56 @@
+/* $OpenBSD: db_disasm.c,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+/* $NetBSD: db_disasm.c,v 1.1 2003/04/26 18:39:27 fvdl Exp $ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ *
+ * Id: db_disasm.c,v 2.3 91/02/05 17:11:03 mrt (CMU)
+ */
+
+/*
+ * Instruction disassembler.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <machine/db_machdep.h>
+
+#include <ddb/db_access.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_output.h>
+#include <ddb/db_interface.h>
+
+/*
+ * Disassemble instruction at 'loc'. 'altfmt' specifies an
+ * (optional) alternate format. Return address of start of
+ * next instruction.
+ */
+db_addr_t
+db_disasm(loc, altfmt)
+ db_addr_t loc;
+ boolean_t altfmt;
+{
+ return loc;
+}
diff --git a/sys/arch/amd64/amd64/db_interface.c b/sys/arch/amd64/amd64/db_interface.c
new file mode 100644
index 00000000000..56c3dd5ce22
--- /dev/null
+++ b/sys/arch/amd64/amd64/db_interface.c
@@ -0,0 +1,303 @@
+/* $OpenBSD: db_interface.c,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+/* $NetBSD: db_interface.c,v 1.1 2003/04/26 18:39:27 fvdl Exp $ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ *
+ * db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU)
+ */
+
+/*
+ * Interface to new debugger.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/systm.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <dev/cons.h>
+
+#include <machine/cpufunc.h>
+#include <machine/db_machdep.h>
+#include <machine/cpuvar.h>
+#include <machine/i82093var.h>
+#include <machine/i82489reg.h>
+#include <machine/atomic.h>
+
+#include <ddb/db_sym.h>
+#include <ddb/db_command.h>
+#include <ddb/db_extern.h>
+#include <ddb/db_access.h>
+#include <ddb/db_output.h>
+#include <ddb/db_var.h>
+
+extern label_t *db_recover;
+extern char *trap_type[];
+extern int trap_types;
+
+int db_active;
+db_regs_t ddb_regs; /* register state */
+db_regs_t *ddb_regp;
+
+void db_mach_cpu (db_expr_t, int, db_expr_t, char *);
+
+const struct db_command db_machine_command_table[] = {
+#ifdef MULTIPROCESSOR
+ { "cpu", db_mach_cpu, 0, 0 },
+#endif
+ { (char *)0, },
+};
+
+void kdbprinttrap(int, int);
+#ifdef MULTIPROCESSOR
+extern void ddb_ipi(struct trapframe);
+static void ddb_suspend(struct trapframe *);
+int ddb_vec;
+#endif
+
+#define NOCPU -1
+
+int ddb_cpu = NOCPU;
+
+typedef void (vector)(void);
+extern vector Xintrddb;
+
+void
+db_machine_init()
+{
+
+#ifdef MULTIPROCESSOR
+ ddb_vec = idt_vec_alloc(0xf0, 0xff);
+ setgate((struct gate_descriptor *)&idt[ddb_vec], &Xintrddb, 1,
+ SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+#endif
+}
+
+#ifdef MULTIPROCESSOR
+
+__cpu_simple_lock_t db_lock;
+
+static int
+db_suspend_others(void)
+{
+ int cpu_me = cpu_number();
+ int win;
+
+ if (ddb_vec == 0)
+ return 1;
+
+ __cpu_simple_lock(&db_lock);
+ if (ddb_cpu == NOCPU)
+ ddb_cpu = cpu_me;
+ win = (ddb_cpu == cpu_me);
+ __cpu_simple_unlock(&db_lock);
+ if (win) {
+ x86_ipi(ddb_vec, LAPIC_DEST_ALLEXCL, LAPIC_DLMODE_FIXED);
+ }
+ return win;
+}
+
+static void
+db_resume_others(void)
+{
+ int i;
+
+ __cpu_simple_lock(&db_lock);
+ ddb_cpu = NOCPU;
+ __cpu_simple_unlock(&db_lock);
+
+ for (i=0; i < X86_MAXPROCS; i++) {
+ struct cpu_info *ci = cpu_info[i];
+ if (ci == NULL)
+ continue;
+ if (ci->ci_flags & CPUF_PAUSE)
+ x86_atomic_clearbits_l(&ci->ci_flags, CPUF_PAUSE);
+ }
+
+}
+
+#endif
+
+/*
+ * Print trap reason.
+ */
+void
+kdbprinttrap(type, code)
+ int type, code;
+{
+ db_printf("kernel: ");
+ if (type >= trap_types || type < 0)
+ db_printf("type %d", type);
+ else
+ db_printf("%s", trap_type[type]);
+ db_printf(" trap, code=%x\n", code);
+}
+
+/*
+ * kdb_trap - field a TRACE or BPT trap
+ */
+int
+kdb_trap(type, code, regs)
+ int type, code;
+ db_regs_t *regs;
+{
+ int s;
+ db_regs_t dbreg;
+
+ switch (type) {
+ case T_BPTFLT: /* breakpoint */
+ case T_TRCTRAP: /* single_step */
+ case T_NMI: /* NMI */
+ case -1: /* keyboard interrupt */
+ break;
+ default:
+ if (!db_panic)
+ return (0);
+
+ kdbprinttrap(type, code);
+ if (db_recover != 0) {
+ db_error("Faulted in DDB; continuing...\n");
+ /*NOTREACHED*/
+ }
+ }
+
+#ifdef MULTIPROCESSOR
+ if (!db_suspend_others()) {
+ ddb_suspend(regs);
+ } else {
+ curcpu()->ci_ddb_regs = &dbreg;
+ ddb_regp = &dbreg;
+#endif
+
+ ddb_regs = *regs;
+
+ ddb_regs.tf_cs &= 0xffff;
+ ddb_regs.tf_ds &= 0xffff;
+ ddb_regs.tf_es &= 0xffff;
+ ddb_regs.tf_fs &= 0xffff;
+ ddb_regs.tf_gs &= 0xffff;
+ ddb_regs.tf_ss &= 0xffff;
+
+ s = splhigh();
+ db_active++;
+ cnpollc(TRUE);
+ db_trap(type, code);
+ cnpollc(FALSE);
+ db_active--;
+ splx(s);
+#ifdef MULTIPROCESSOR
+ db_resume_others();
+ }
+#endif
+ ddb_regp = &dbreg;
+
+ *regs = ddb_regs;
+
+ return (1);
+}
+
+void
+Debugger()
+{
+ breakpoint();
+}
+
+#ifdef MULTIPROCESSOR
+
+/*
+ * Called when we receive a debugger IPI (inter-processor interrupt).
+ * As with trap() in trap.c, this function is called from an assembly
+ * language IDT gate entry routine which prepares a suitable stack frame,
+ * and restores this frame after the exception has been processed. Note
+ * that the effect is as if the arguments were passed call by reference.
+ */
+
+void
+ddb_ipi(struct trapframe frame)
+{
+
+ ddb_suspend(&frame);
+}
+
+static void
+ddb_suspend(struct trapframe *frame)
+{
+ volatile struct cpu_info *ci = curcpu();
+ db_regs_t regs;
+
+ regs = *frame;
+
+ ci->ci_ddb_regs = &regs;
+
+ x86_atomic_setbits_l(&ci->ci_flags, CPUF_PAUSE);
+
+ while (ci->ci_flags & CPUF_PAUSE)
+ ;
+ ci->ci_ddb_regs = 0;
+}
+
+
+extern void cpu_debug_dump(void); /* XXX */
+
+void
+db_mach_cpu(addr, have_addr, count, modif)
+ db_expr_t addr;
+ int have_addr;
+ db_expr_t count;
+ char * modif;
+{
+ struct cpu_info *ci;
+ if (!have_addr) {
+ cpu_debug_dump();
+ return;
+ }
+
+ if ((addr < 0) || (addr >= X86_MAXPROCS)) {
+ db_printf("%ld: cpu out of range\n", addr);
+ return;
+ }
+ ci = cpu_info[addr];
+ if (ci == NULL) {
+ db_printf("cpu %ld not configured\n", addr);
+ return;
+ }
+ if (ci != curcpu()) {
+ if (!(ci->ci_flags & CPUF_PAUSE)) {
+ db_printf("cpu %ld not paused\n", addr);
+ return;
+ }
+ }
+ if (ci->ci_ddb_regs == 0) {
+ db_printf("cpu %ld has no saved regs\n", addr);
+ return;
+ }
+ db_printf("using cpu %ld", addr);
+ ddb_regp = ci->ci_ddb_regs;
+}
+
+#endif
diff --git a/sys/arch/amd64/amd64/db_memrw.c b/sys/arch/amd64/amd64/db_memrw.c
new file mode 100644
index 00000000000..9b26b5d99fb
--- /dev/null
+++ b/sys/arch/amd64/amd64/db_memrw.c
@@ -0,0 +1,211 @@
+/* $OpenBSD: db_memrw.c,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+/* $NetBSD: db_memrw.c,v 1.1 2003/04/26 18:39:27 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1996, 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Gordon W. Ross and Jason R. Thorpe.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * Interface to the debugger for virtual memory read/write.
+ * This file is shared by DDB and KGDB, and must work even
+ * when only KGDB is included (thus no db_printf calls).
+ *
+ * To write in the text segment, we have to first make
+ * the page writable, do the write, then restore the PTE.
+ * For writes outside the text segment, and all reads,
+ * just do the access -- if it causes a fault, the debugger
+ * will recover with a longjmp to an appropriate place.
+ *
+ * ALERT! If you want to access device registers with a
+ * specific size, then the read/write functions have to
+ * make sure to do the correct sized pointer access.
+ *
+ * Modified for i386 from hp300 version by
+ * Jason R. Thorpe <thorpej@zembu.com>.
+ *
+ * Basic copy to amd64 by fvdl.
+ */
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/db_machdep.h>
+
+#include <ddb/db_access.h>
+
+/*
+ * Read bytes from kernel address space for debugger.
+ */
+void
+db_read_bytes(vaddr_t addr, size_t size, char *data)
+{
+ char *src;
+
+ src = (char *)addr;
+
+ if (size == 8) {
+ *((long *)data) = *((long *)src);
+ return;
+ }
+
+ if (size == 4) {
+ *((int *)data) = *((int *)src);
+ return;
+ }
+
+ if (size == 2) {
+ *((short *)data) = *((short *)src);
+ return;
+ }
+
+ while (size-- > 0)
+ *data++ = *src++;
+}
+
+/*
+ * Write bytes somewhere in the kernel text. Make the text
+ * pages writable temporarily.
+ */
+static void
+db_write_text(vaddr_t addr, size_t size, char *data)
+{
+ pt_entry_t *pte, oldpte, tmppte;
+ vaddr_t pgva;
+ size_t limit;
+ char *dst;
+
+ if (size == 0)
+ return;
+
+ dst = (char *)addr;
+
+ do {
+ /*
+ * Get the PTE for the page.
+ */
+ pte = kvtopte(addr);
+ oldpte = *pte;
+
+ if ((oldpte & PG_V) == 0) {
+ printf(" address %p not a valid page\n", dst);
+ return;
+ }
+
+ /*
+ * Get the VA for the page.
+ */
+#ifdef LARGEPAGES
+ if (oldpte & PG_PS)
+ pgva = (vaddr_t)dst & PG_LGFRAME;
+ else
+#endif
+ pgva = x86_trunc_page(dst);
+
+ /*
+ * Compute number of bytes that can be written
+ * with this mapping and subtract it from the
+ * total size.
+ */
+#ifdef LARGEPAGES
+ if (oldpte & PG_PS)
+ limit = NBPD - ((vaddr_t)dst & (NBPD - 1));
+ else
+#endif
+ limit = PAGE_SIZE - ((vaddr_t)dst & PGOFSET);
+ if (limit > size)
+ limit = size;
+ size -= limit;
+
+ tmppte = (oldpte & ~PG_KR) | PG_KW;
+ *pte = tmppte;
+ pmap_update_pg(pgva);
+
+ /*
+ * Page is now writable. Do as much access as we
+ * can in this page.
+ */
+ for (; limit > 0; limit--)
+ *dst++ = *data++;
+
+ /*
+ * Restore the old PTE.
+ */
+ *pte = oldpte;
+
+ pmap_update_pg(pgva);
+
+ } while (size != 0);
+}
+
+/*
+ * Write bytes to kernel address space for debugger.
+ */
+void
+db_write_bytes(vaddr_t addr, size_t size, char *data)
+{
+ extern char etext;
+ char *dst;
+
+ dst = (char *)addr;
+
+ /* If any part is in kernel text, use db_write_text() */
+ if (addr >= KERNBASE && addr < (vaddr_t)&etext) {
+ db_write_text(addr, size, data);
+ return;
+ }
+
+ dst = (char *)addr;
+
+ if (size == 8) {
+ *((long *)dst) = *((long *)data);
+ return;
+ }
+
+ if (size == 4) {
+ *((int *)dst) = *((int *)data);
+ return;
+ }
+
+ if (size == 2) {
+ *((short *)dst) = *((short *)data);
+ return;
+ }
+
+ while (size-- > 0)
+ *dst++ = *data++;
+}
diff --git a/sys/arch/amd64/amd64/db_trace.c b/sys/arch/amd64/amd64/db_trace.c
new file mode 100644
index 00000000000..223498c59f6
--- /dev/null
+++ b/sys/arch/amd64/amd64/db_trace.c
@@ -0,0 +1,412 @@
+/* $OpenBSD: db_trace.c,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+/* $NetBSD: db_trace.c,v 1.1 2003/04/26 18:39:27 fvdl Exp $ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+
+#include <machine/db_machdep.h>
+#include <machine/frame.h>
+#include <machine/trap.h>
+
+#include <ddb/db_sym.h>
+#include <ddb/db_access.h>
+#include <ddb/db_variables.h>
+#include <ddb/db_output.h>
+#include <ddb/db_interface.h>
+
+#if 1
+#define dbreg(xx) (long *)offsetof(db_regs_t, tf_ ## xx)
+#else
+#define dbreg(xx) (long *)&ddb_regs.tf_ ## xx
+#endif
+
+static int db_x86_64_regop(struct db_variable *, db_expr_t *, int);
+
+/*
+ * Machine register set.
+ */
+struct db_variable db_regs[] = {
+ { "ds", dbreg(ds), db_x86_64_regop },
+ { "es", dbreg(es), db_x86_64_regop },
+ { "fs", dbreg(fs), db_x86_64_regop },
+ { "gs", dbreg(gs), db_x86_64_regop },
+ { "rdi", dbreg(rdi), db_x86_64_regop },
+ { "rsi", dbreg(rsi), db_x86_64_regop },
+ { "rbp", dbreg(rbp), db_x86_64_regop },
+ { "rbx", dbreg(rbx), db_x86_64_regop },
+ { "rdx", dbreg(rdx), db_x86_64_regop },
+ { "rcx", dbreg(rcx), db_x86_64_regop },
+ { "rax", dbreg(rax), db_x86_64_regop },
+ { "r8", dbreg(r8), db_x86_64_regop },
+ { "r9", dbreg(r9), db_x86_64_regop },
+ { "r10", dbreg(r10), db_x86_64_regop },
+ { "r11", dbreg(r11), db_x86_64_regop },
+ { "r12", dbreg(r12), db_x86_64_regop },
+ { "r13", dbreg(r13), db_x86_64_regop },
+ { "r14", dbreg(r14), db_x86_64_regop },
+ { "r15", dbreg(r15), db_x86_64_regop },
+ { "rip", dbreg(rip), db_x86_64_regop },
+ { "cs", dbreg(cs), db_x86_64_regop },
+ { "rflags", dbreg(rflags), db_x86_64_regop },
+ { "rsp", dbreg(rsp), db_x86_64_regop },
+ { "ss", dbreg(ss), db_x86_64_regop },
+};
+struct db_variable * db_eregs =
+ db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
+
+static int
+db_x86_64_regop(struct db_variable *vp, db_expr_t *val, int opcode)
+{
+ db_expr_t *regaddr =
+ (db_expr_t *)(((uint8_t *)DDB_REGS) + ((size_t)vp->valuep));
+
+ switch (opcode) {
+ case DB_VAR_GET:
+ *val = *regaddr;
+ break;
+ case DB_VAR_SET:
+ *regaddr = *val;
+ break;
+ default:
+ panic("db_x86_64_regop: unknown op %d", opcode);
+ }
+ return 0;
+}
+
+/*
+ * Stack trace.
+ */
+#define INKERNEL(va) (((vaddr_t)(va)) >= VM_MIN_KERNEL_ADDRESS)
+
+struct x86_64_frame {
+ struct x86_64_frame *f_frame;
+ long f_retaddr;
+ long f_arg0;
+};
+
+#define NONE 0
+#define TRAP 1
+#define SYSCALL 2
+#define INTERRUPT 3
+
+db_addr_t db_trap_symbol_value = 0;
+db_addr_t db_syscall_symbol_value = 0;
+db_addr_t db_kdintr_symbol_value = 0;
+boolean_t db_trace_symbols_found = FALSE;
+
+void db_find_trace_symbols(void);
+int db_numargs(struct x86_64_frame *);
+void db_nextframe(struct x86_64_frame **, db_addr_t *, long *, int,
+ int (*) (const char *, ...));
+
+void
+db_find_trace_symbols()
+{
+ db_expr_t value;
+
+ if (db_value_of_name("_trap", &value))
+ db_trap_symbol_value = (db_addr_t) value;
+ if (db_value_of_name("_kdintr", &value))
+ db_kdintr_symbol_value = (db_addr_t) value;
+ if (db_value_of_name("_syscall", &value))
+ db_syscall_symbol_value = (db_addr_t) value;
+ db_trace_symbols_found = TRUE;
+}
+
+/*
+ * Figure out how many arguments were passed into the frame at "fp".
+ * We can probably figure out how many arguments where passed above
+ * the first 6 (which are in registers), but since we can't
+ * reliably determine the values currently, just return 0.
+ */
+int
+db_numargs(fp)
+ struct x86_64_frame *fp;
+{
+ return 0;
+}
+
+/*
+ * Figure out the next frame up in the call stack.
+ * For trap(), we print the address of the faulting instruction and
+ * proceed with the calling frame. We return the ip that faulted.
+ * If the trap was caused by jumping through a bogus pointer, then
+ * the next line in the backtrace will list some random function as
+ * being called. It should get the argument list correct, though.
+ * It might be possible to dig out from the next frame up the name
+ * of the function that faulted, but that could get hairy.
+ */
+void
+db_nextframe(fp, ip, argp, is_trap, pr)
+ struct x86_64_frame **fp; /* in/out */
+ db_addr_t *ip; /* out */
+ long *argp; /* in */
+ int is_trap; /* in */
+ int (*pr)(const char *, ...); /* in */
+{
+
+ switch (is_trap) {
+ case NONE:
+ *ip = (db_addr_t)
+ db_get_value((db_addr_t)&(*fp)->f_retaddr, 8, FALSE);
+ *fp = (struct x86_64_frame *)
+ db_get_value((db_addr_t)&(*fp)->f_frame, 8, FALSE);
+ break;
+
+ default: {
+ struct trapframe *tf;
+
+ /* The only argument to trap() or syscall() is the trapframe. */
+ tf = (struct trapframe *)argp;
+ switch (is_trap) {
+ case TRAP:
+ (*pr)("--- trap (number %d) ---\n", tf->tf_trapno);
+ break;
+ case SYSCALL:
+ (*pr)("--- syscall (number %ld) ---\n", tf->tf_rax);
+ break;
+ case INTERRUPT:
+ (*pr)("--- interrupt ---\n");
+ break;
+ }
+ *fp = (struct x86_64_frame *)tf->tf_rbp;
+ *ip = (db_addr_t)tf->tf_rip;
+ break;
+ }
+ }
+}
+
+void
+db_stack_trace_print(addr, have_addr, count, modif, pr)
+ db_expr_t addr;
+ boolean_t have_addr;
+ db_expr_t count;
+ char *modif;
+ int (*pr)(const char *, ...);
+{
+ struct x86_64_frame *frame, *lastframe;
+ long *argp;
+ db_addr_t callpc;
+ int is_trap = 0;
+ boolean_t kernel_only = TRUE;
+ boolean_t trace_thread = FALSE;
+
+#if 0
+ if (!db_trace_symbols_found)
+ db_find_trace_symbols();
+#endif
+
+ {
+ register char *cp = modif;
+ register char c;
+
+ while ((c = *cp++) != 0) {
+ if (c == 't')
+ trace_thread = TRUE;
+ if (c == 'u')
+ kernel_only = FALSE;
+ }
+ }
+
+ if (!have_addr) {
+ frame = (struct x86_64_frame *)ddb_regs.tf_rbp;
+ callpc = (db_addr_t)ddb_regs.tf_rip;
+ } else {
+#if 0
+ if (trace_thread) {
+ struct proc *p;
+ struct user *u;
+ struct lwp *l;
+ (*pr)("trace: pid %d ", (int)addr);
+ p = pfind(addr);
+ if (p == NULL) {
+ (*pr)("not found\n");
+ return;
+ }
+ l = proc_representative_lwp(p);
+ if (!(l->l_flag&L_INMEM)) {
+ (*pr)("swapped out\n");
+ return;
+ }
+ u = l->l_addr;
+ frame = (struct x86_64_frame *) u->u_pcb.pcb_rbp;
+ (*pr)("at %p\n", frame);
+ } else
+#endif
+ frame = (struct x86_64_frame *)addr;
+ callpc = (db_addr_t)
+ db_get_value((db_addr_t)&frame->f_retaddr, 8, FALSE);
+ frame = (struct x86_64_frame *)frame->f_frame;
+ }
+
+ lastframe = 0;
+ while (count && frame != 0) {
+ int narg;
+ char * name;
+ db_expr_t offset;
+ db_sym_t sym;
+#define MAXNARG 16
+ char *argnames[MAXNARG], **argnp = NULL;
+
+ sym = db_search_symbol(callpc, DB_STGY_ANY, &offset);
+ db_symbol_values(sym, &name, NULL);
+
+ if (lastframe == 0 && sym == NULL) {
+ /* Symbol not found, peek at code */
+ long instr = db_get_value(callpc, 8, FALSE);
+
+ offset = 1;
+ if ((instr & 0x00ffffff) == 0x00e58955 ||
+ /* enter: pushl %ebp, movl %esp, %ebp */
+ (instr & 0x0000ffff) == 0x0000e589
+ /* enter+1: movl %esp, %ebp */) {
+ offset = 0;
+ }
+ }
+ if (INKERNEL(frame) && name) {
+#ifdef __ELF__
+ if (!strcmp(name, "trap")) {
+ is_trap = TRAP;
+ } else if (!strcmp(name, "syscall")) {
+ is_trap = SYSCALL;
+ } else if (name[0] == 'X') {
+ if (!strncmp(name, "Xintr", 5) ||
+ !strncmp(name, "Xresume", 7) ||
+ !strncmp(name, "Xstray", 6) ||
+ !strncmp(name, "Xhold", 5) ||
+ !strncmp(name, "Xrecurse", 8) ||
+ !strcmp(name, "Xdoreti") ||
+ !strncmp(name, "Xsoft", 5)) {
+ is_trap = INTERRUPT;
+ } else
+ goto normal;
+ } else
+ goto normal;
+ narg = 0;
+#else
+ if (!strcmp(name, "_trap")) {
+ is_trap = TRAP;
+ } else if (!strcmp(name, "_syscall")) {
+ is_trap = SYSCALL;
+ } else if (name[0] == '_' && name[1] == 'X') {
+ if (!strncmp(name, "_Xintr", 6) ||
+ !strncmp(name, "_Xresume", 8) ||
+ !strncmp(name, "_Xstray", 7) ||
+ !strncmp(name, "_Xhold", 6) ||
+ !strncmp(name, "_Xrecurse", 9) ||
+ !strcmp(name, "_Xdoreti") ||
+ !strncmp(name, "_Xsoft", 6)) {
+ is_trap = INTERRUPT;
+ } else
+ goto normal;
+ } else
+ goto normal;
+ narg = 0;
+#endif /* __ELF__ */
+ } else {
+ normal:
+ is_trap = NONE;
+ narg = MAXNARG;
+ if (db_sym_numargs(sym, &narg, argnames))
+ argnp = argnames;
+ else
+ narg = db_numargs(frame);
+ }
+
+ (*pr)("%s(", name);
+
+ if (lastframe == 0 && offset == 0 && !have_addr) {
+ /*
+ * We have a breakpoint before the frame is set up
+ * Use %esp instead
+ */
+ argp = &((struct x86_64_frame *)(ddb_regs.tf_rsp-8))->f_arg0;
+ } else {
+ argp = &frame->f_arg0;
+ }
+
+ while (narg) {
+ if (argnp)
+ (*pr)("%s=", *argnp++);
+ (*pr)("%lx", db_get_value((db_addr_t)argp, 8, FALSE));
+ argp++;
+ if (--narg != 0)
+ (*pr)(",");
+ }
+ (*pr)(") at ");
+ db_printsym(callpc, DB_STGY_PROC, pr);
+ (*pr)("\n");
+
+ if (lastframe == 0 && offset == 0 && !have_addr) {
+ /* Frame really belongs to next callpc */
+ lastframe = (struct x86_64_frame *)(ddb_regs.tf_rsp-8);
+ callpc = (db_addr_t)
+ db_get_value((db_addr_t)&lastframe->f_retaddr,
+ 8, FALSE);
+ continue;
+ }
+
+ lastframe = frame;
+ db_nextframe(&frame, &callpc, &frame->f_arg0, is_trap, pr);
+
+ if (frame == 0) {
+ /* end of chain */
+ break;
+ }
+ if (INKERNEL(frame)) {
+ /* staying in kernel */
+ if (frame <= lastframe) {
+ (*pr)("Bad frame pointer: %p\n", frame);
+ break;
+ }
+ } else if (INKERNEL(lastframe)) {
+ /* switch from user to kernel */
+ if (kernel_only) {
+ (*pr)("end of kernel\n");
+ break; /* kernel stack only */
+ }
+ } else {
+ /* in user */
+ if (frame <= lastframe) {
+ (*pr)("Bad user frame pointer: %p\n",
+ frame);
+ break;
+ }
+ }
+ --count;
+ }
+ (*pr)("end trace frame: 0x%lx, count: %d\n", frame, count);
+
+ if (count && is_trap != NONE) {
+ db_printsym(callpc, DB_STGY_XTRN, pr);
+ (*pr)(":\n");
+ }
+}
diff --git a/sys/arch/amd64/amd64/disksubr.c b/sys/arch/amd64/amd64/disksubr.c
new file mode 100644
index 00000000000..c44f592be57
--- /dev/null
+++ b/sys/arch/amd64/amd64/disksubr.c
@@ -0,0 +1,550 @@
+/* $OpenBSD: disksubr.c,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+/* $NetBSD: disksubr.c,v 1.21 1996/05/03 19:42:03 christos Exp $ */
+
+/*
+ * Copyright (c) 1996 Theo de Raadt
+ * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/device.h>
+#include <sys/disklabel.h>
+#include <sys/syslog.h>
+#include <sys/disk.h>
+
+void
+dk_establish(dk, dev)
+ struct disk *dk;
+ struct device *dev;
+{
+}
+
+/*
+ * Attempt to read a disk label from a device
+ * using the indicated strategy routine.
+ * The label must be partly set up before this:
+ * secpercyl, secsize and anything required for a block i/o read
+ * operation in the driver's strategy/start routines
+ * must be filled in before calling us.
+ *
+ * If dos partition table requested, attempt to load it and
+ * find disklabel inside a DOS partition. Also, if bad block
+ * table needed, attempt to extract it as well. Return buffer
+ * for use in signalling errors if requested.
+ *
+ * We would like to check if each MBR has a valid DOSMBR_SIGNATURE, but
+ * we cannot because it doesn't always exist. So.. we assume the
+ * MBR is valid.
+ *
+ * Returns null on success and an error string on failure.
+ */
+char *
+readdisklabel(dev, strat, lp, osdep, spoofonly)
+ dev_t dev;
+ void (*strat)(struct buf *);
+ register struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+ int spoofonly;
+{
+ struct dos_partition *dp = osdep->dosparts, *dp2;
+ struct dkbad *bdp = &DKBAD(osdep);
+ struct buf *bp = NULL;
+ struct disklabel *dlp;
+ char *msg = NULL, *cp;
+ int dospartoff, cyl, i, ourpart = -1;
+
+ /* minimal requirements for archtypal disk label */
+ if (lp->d_secsize == 0)
+ lp->d_secsize = DEV_BSIZE;
+ if (lp->d_secpercyl == 0) {
+ msg = "invalid geometry";
+ goto done;
+ }
+ if (lp->d_secperunit == 0)
+ lp->d_secperunit = 0x1fffffff;
+ lp->d_npartitions = RAW_PART + 1;
+ for (i = 0; i < RAW_PART; i++) {
+ lp->d_partitions[i].p_size = 0;
+ lp->d_partitions[i].p_offset = 0;
+ }
+ if (lp->d_partitions[i].p_size == 0)
+ lp->d_partitions[i].p_size = 0x1fffffff;
+ lp->d_partitions[i].p_offset = 0;
+
+ /* get a buffer and initialize it */
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = dev;
+
+ /* do dos partitions in the process of getting disklabel? */
+ dospartoff = 0;
+ cyl = LABELSECTOR / lp->d_secpercyl;
+ if (dp) {
+ daddr_t part_blkno = DOSBBSECTOR;
+ unsigned long extoff = 0;
+ int wander = 1, n = 0, loop = 0;
+
+ /*
+ * Read dos partition table, follow extended partitions.
+ * Map the partitions to disklabel entries i-p
+ */
+ while (wander && n < 8 && loop < 8) {
+ loop++;
+ wander = 0;
+ if (part_blkno < extoff)
+ part_blkno = extoff;
+
+ /* read boot record */
+ bp->b_blkno = part_blkno;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ bp->b_cylinder = part_blkno / lp->d_secpercyl;
+ (*strat)(bp);
+
+ /* if successful, wander through dos partition table */
+ if (biowait(bp)) {
+ msg = "dos partition I/O error";
+ goto done;
+ }
+ bcopy(bp->b_data + DOSPARTOFF, dp, NDOSPART * sizeof(*dp));
+
+ if (ourpart == -1) {
+ /* Search for our MBR partition */
+ for (dp2=dp, i=0; i < NDOSPART && ourpart == -1;
+ i++, dp2++)
+ if (get_le(&dp2->dp_size) &&
+ dp2->dp_typ == DOSPTYP_OPENBSD)
+ ourpart = i;
+ for (dp2=dp, i=0; i < NDOSPART && ourpart == -1;
+ i++, dp2++)
+ if (get_le(&dp2->dp_size) &&
+ dp2->dp_typ == DOSPTYP_FREEBSD)
+ ourpart = i;
+ for (dp2=dp, i=0; i < NDOSPART && ourpart == -1;
+ i++, dp2++)
+ if (get_le(&dp2->dp_size) &&
+ dp2->dp_typ == DOSPTYP_NETBSD)
+ ourpart = i;
+ if (ourpart == -1)
+ goto donot;
+ /*
+ * This is our MBR partition. need sector address
+ * for SCSI/IDE, cylinder for ESDI/ST506/RLL
+ */
+ dp2 = &dp[ourpart];
+ dospartoff = get_le(&dp2->dp_start) + part_blkno;
+ cyl = DPCYL(dp2->dp_scyl, dp2->dp_ssect);
+
+ /* XXX build a temporary disklabel */
+ lp->d_partitions[0].p_size = get_le(&dp2->dp_size);
+ lp->d_partitions[0].p_offset =
+ get_le(&dp2->dp_start) + part_blkno;
+ if (lp->d_ntracks == 0)
+ lp->d_ntracks = dp2->dp_ehd + 1;
+ if (lp->d_nsectors == 0)
+ lp->d_nsectors = DPSECT(dp2->dp_esect);
+ if (lp->d_secpercyl == 0)
+ lp->d_secpercyl = lp->d_ntracks *
+ lp->d_nsectors;
+ }
+donot:
+ /*
+ * In case the disklabel read below fails, we want to
+ * provide a fake label in i-p.
+ */
+ for (dp2=dp, i=0; i < NDOSPART && n < 8; i++, dp2++) {
+ struct partition *pp = &lp->d_partitions[8+n];
+
+ if (dp2->dp_typ == DOSPTYP_OPENBSD)
+ continue;
+ if (get_le(&dp2->dp_size) > lp->d_secperunit)
+ continue;
+ if (get_le(&dp2->dp_size))
+ pp->p_size = get_le(&dp2->dp_size);
+ if (get_le(&dp2->dp_start))
+ pp->p_offset =
+ get_le(&dp2->dp_start) + part_blkno;
+
+ switch (dp2->dp_typ) {
+ case DOSPTYP_UNUSED:
+ for (cp = (char *)dp2;
+ cp < (char *)(dp2 + 1); cp++)
+ if (*cp)
+ break;
+ /*
+ * Was it all zeroes? If so, it is
+ * an unused entry that we don't
+ * want to show.
+ */
+ if (cp == (char *)(dp2 + 1))
+ continue;
+ lp->d_partitions[8 + n++].p_fstype =
+ FS_UNUSED;
+ break;
+
+ case DOSPTYP_LINUX:
+ pp->p_fstype = FS_EXT2FS;
+ n++;
+ break;
+
+ case DOSPTYP_FAT12:
+ case DOSPTYP_FAT16S:
+ case DOSPTYP_FAT16B:
+ case DOSPTYP_FAT32:
+ case DOSPTYP_FAT32L:
+ case DOSPTYP_FAT16L:
+ pp->p_fstype = FS_MSDOS;
+ n++;
+ break;
+ case DOSPTYP_EXTEND:
+ case DOSPTYP_EXTENDL:
+ part_blkno = get_le(&dp2->dp_start) + extoff;
+ if (!extoff) {
+ extoff = get_le(&dp2->dp_start);
+ part_blkno = 0;
+ }
+ wander = 1;
+ break;
+ default:
+ pp->p_fstype = FS_OTHER;
+ n++;
+ break;
+ }
+ }
+ }
+ lp->d_bbsize = 8192;
+ lp->d_sbsize = 64*1024; /* XXX ? */
+ lp->d_npartitions = MAXPARTITIONS;
+ }
+
+ /* don't read the on-disk label if we are in spoofed-only mode */
+ if (spoofonly)
+ goto done;
+
+ /* next, dig out disk label */
+ bp->b_blkno = dospartoff + LABELSECTOR;
+ bp->b_cylinder = cyl;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ (*strat)(bp);
+
+ /* if successful, locate disk label within block and validate */
+ if (biowait(bp)) {
+ /* XXX we return the faked label built so far */
+ msg = "disk label I/O error";
+ goto done;
+ }
+ for (dlp = (struct disklabel *)bp->b_data;
+ dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - sizeof(*dlp));
+ dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
+ if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
+ if (msg == NULL)
+ msg = "no disk label";
+ } else if (dlp->d_npartitions > MAXPARTITIONS ||
+ dkcksum(dlp) != 0)
+ msg = "disk label corrupted";
+ else {
+ *lp = *dlp;
+ msg = NULL;
+ break;
+ }
+ }
+
+ if (msg) {
+#if defined(CD9660)
+ if (iso_disklabelspoof(dev, strat, lp) == 0)
+ msg = NULL;
+#endif
+ goto done;
+ }
+
+ /* obtain bad sector table if requested and present */
+ if (bdp && (lp->d_flags & D_BADSECT)) {
+ struct dkbad *db;
+
+ i = 0;
+ do {
+ /* read a bad sector table */
+ bp->b_flags = B_BUSY | B_READ;
+ bp->b_blkno = lp->d_secperunit - lp->d_nsectors + i;
+ if (lp->d_secsize > DEV_BSIZE)
+ bp->b_blkno *= lp->d_secsize / DEV_BSIZE;
+ else
+ bp->b_blkno /= DEV_BSIZE / lp->d_secsize;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_cylinder = lp->d_ncylinders - 1;
+ (*strat)(bp);
+
+ /* if successful, validate, otherwise try another */
+ if (biowait(bp)) {
+ msg = "bad sector table I/O error";
+ } else {
+ db = (struct dkbad *)(bp->b_data);
+#define DKBAD_MAGIC 0x4321
+ if (db->bt_mbz == 0
+ && db->bt_flag == DKBAD_MAGIC) {
+ msg = NULL;
+ *bdp = *db;
+ break;
+ } else
+ msg = "bad sector table corrupted";
+ }
+ } while ((bp->b_flags & B_ERROR) && (i += 2) < 10 &&
+ i < lp->d_nsectors);
+ }
+
+done:
+ if (bp) {
+ bp->b_flags |= B_INVAL;
+ brelse(bp);
+ }
+ return (msg);
+}
+
+/*
+ * Check new disk label for sensibility
+ * before setting it.
+ */
+int
+setdisklabel(olp, nlp, openmask, osdep)
+ register struct disklabel *olp, *nlp;
+ u_long openmask;
+ struct cpu_disklabel *osdep;
+{
+ register int i;
+ register struct partition *opp, *npp;
+
+ /* sanity clause */
+ if (nlp->d_secpercyl == 0 || nlp->d_secsize == 0 ||
+ (nlp->d_secsize % DEV_BSIZE) != 0)
+ return(EINVAL);
+
+ /* special case to allow disklabel to be invalidated */
+ if (nlp->d_magic == 0xffffffff) {
+ *olp = *nlp;
+ return (0);
+ }
+
+ if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC ||
+ dkcksum(nlp) != 0)
+ return (EINVAL);
+
+ /* XXX missing check if other dos partitions will be overwritten */
+
+ while (openmask != 0) {
+ i = ffs(openmask) - 1;
+ openmask &= ~(1 << i);
+ if (nlp->d_npartitions <= i)
+ return (EBUSY);
+ opp = &olp->d_partitions[i];
+ npp = &nlp->d_partitions[i];
+ if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size)
+ return (EBUSY);
+ /*
+ * Copy internally-set partition information
+ * if new label doesn't include it. XXX
+ */
+ if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) {
+ npp->p_fstype = opp->p_fstype;
+ npp->p_fsize = opp->p_fsize;
+ npp->p_frag = opp->p_frag;
+ npp->p_cpg = opp->p_cpg;
+ }
+ }
+ nlp->d_checksum = 0;
+ nlp->d_checksum = dkcksum(nlp);
+ *olp = *nlp;
+ return (0);
+}
+
+
+/*
+ * Write disk label back to device after modification.
+ * XXX cannot handle OpenBSD partitions in extended partitions!
+ */
+int
+writedisklabel(dev, strat, lp, osdep)
+ dev_t dev;
+ void (*strat)(struct buf *);
+ register struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+{
+ struct dos_partition *dp = osdep->dosparts, *dp2;
+ struct buf *bp;
+ struct disklabel *dlp;
+ int error, dospartoff, cyl, i;
+ int ourpart = -1;
+
+ /* get a buffer and initialize it */
+ bp = geteblk((int)lp->d_secsize);
+ bp->b_dev = dev;
+
+ /* do dos partitions in the process of getting disklabel? */
+ dospartoff = 0;
+ cyl = LABELSECTOR / lp->d_secpercyl;
+ if (dp) {
+ /* read master boot record */
+ bp->b_blkno = DOSBBSECTOR;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ bp->b_cylinder = DOSBBSECTOR / lp->d_secpercyl;
+ (*strat)(bp);
+
+ if ((error = biowait(bp)) != 0)
+ goto done;
+
+ /* XXX how do we check veracity/bounds of this? */
+ bcopy(bp->b_data + DOSPARTOFF, dp,
+ NDOSPART * sizeof(*dp));
+
+ for (dp2=dp, i=0; i < NDOSPART && ourpart == -1; i++, dp2++)
+ if (get_le(&dp2->dp_size) && dp2->dp_typ == DOSPTYP_OPENBSD)
+ ourpart = i;
+ for (dp2=dp, i=0; i < NDOSPART && ourpart == -1; i++, dp2++)
+ if (get_le(&dp2->dp_size) && dp2->dp_typ == DOSPTYP_FREEBSD)
+ ourpart = i;
+ for (dp2=dp, i=0; i < NDOSPART && ourpart == -1; i++, dp2++)
+ if (get_le(&dp2->dp_size) && dp2->dp_typ == DOSPTYP_NETBSD)
+ ourpart = i;
+
+ if (ourpart != -1) {
+ dp2 = &dp[ourpart];
+
+ /*
+ * need sector address for SCSI/IDE,
+ * cylinder for ESDI/ST506/RLL
+ */
+ dospartoff = get_le(&dp2->dp_start);
+ cyl = DPCYL(dp2->dp_scyl, dp2->dp_ssect);
+ }
+ }
+
+ /* next, dig out disk label */
+ bp->b_blkno = dospartoff + LABELSECTOR;
+ bp->b_cylinder = cyl;
+ bp->b_bcount = lp->d_secsize;
+ bp->b_flags = B_BUSY | B_READ;
+ (*strat)(bp);
+
+ /* if successful, locate disk label within block and validate */
+ if ((error = biowait(bp)) != 0)
+ goto done;
+ for (dlp = (struct disklabel *)bp->b_data;
+ dlp <= (struct disklabel *)(bp->b_data + lp->d_secsize - sizeof(*dlp));
+ dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
+ if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
+ dkcksum(dlp) == 0) {
+ *dlp = *lp;
+ bp->b_flags = B_BUSY | B_WRITE;
+ (*strat)(bp);
+ error = biowait(bp);
+ goto done;
+ }
+ }
+
+ /* Write it in the regular place. */
+ *(struct disklabel *)bp->b_data = *lp;
+ bp->b_flags = B_BUSY | B_WRITE;
+ (*strat)(bp);
+ error = biowait(bp);
+ goto done;
+
+done:
+ bp->b_flags |= B_INVAL;
+ brelse(bp);
+ return (error);
+}
+
+/*
+ * Determine the size of the transfer, and make sure it is
+ * within the boundaries of the partition. Adjust transfer
+ * if needed, and signal errors or early completion.
+ */
+int
+bounds_check_with_label(bp, lp, osdep, wlabel)
+ struct buf *bp;
+ struct disklabel *lp;
+ struct cpu_disklabel *osdep;
+ int wlabel;
+{
+#define blockpersec(count, lp) ((count) * (((lp)->d_secsize) / DEV_BSIZE))
+ struct partition *p = lp->d_partitions + DISKPART(bp->b_dev);
+ int labelsector = blockpersec(lp->d_partitions[RAW_PART].p_offset, lp) +
+ LABELSECTOR;
+ int sz = howmany(bp->b_bcount, DEV_BSIZE);
+
+ /* avoid division by zero */
+ if (lp->d_secpercyl == 0) {
+ bp->b_error = EINVAL;
+ goto bad;
+ }
+
+ /* beyond partition? */
+ if (bp->b_blkno + sz > blockpersec(p->p_size, lp)) {
+ sz = blockpersec(p->p_size, lp) - bp->b_blkno;
+ if (sz == 0) {
+ /* If exactly at end of disk, return EOF. */
+ bp->b_resid = bp->b_bcount;
+ goto done;
+ }
+ if (sz < 0) {
+ /* If past end of disk, return EINVAL. */
+ bp->b_error = EINVAL;
+ goto bad;
+ }
+ /* Otherwise, truncate request. */
+ bp->b_bcount = sz << DEV_BSHIFT;
+ }
+
+ /* Overwriting disk label? */
+ if (bp->b_blkno + blockpersec(p->p_offset, lp) <= labelsector &&
+#if LABELSECTOR != 0
+ bp->b_blkno + blockpersec(p->p_offset, lp) + sz > labelsector &&
+#endif
+ (bp->b_flags & B_READ) == 0 && !wlabel) {
+ bp->b_error = EROFS;
+ goto bad;
+ }
+
+ /* calculate cylinder for disksort to order transfers with */
+ bp->b_cylinder = (bp->b_blkno + blockpersec(p->p_offset, lp)) /
+ lp->d_secpercyl;
+ return (1);
+
+bad:
+ bp->b_flags |= B_ERROR;
+done:
+ return (0);
+}
diff --git a/sys/arch/amd64/amd64/fpu.c b/sys/arch/amd64/amd64/fpu.c
new file mode 100644
index 00000000000..9b874b9b251
--- /dev/null
+++ b/sys/arch/amd64/amd64/fpu.c
@@ -0,0 +1,309 @@
+/* $OpenBSD: fpu.c,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+/* $NetBSD: fpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1994, 1995, 1998 Charles M. Hannum. All rights reserved.
+ * Copyright (c) 1990 William Jolitz.
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)npx.c 7.2 (Berkeley) 5/12/91
+ */
+
+/*
+ * XXXfvdl update copyright notice. this started out as a stripped isa/npx.c
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <sys/device.h>
+#include <sys/vmmeter.h>
+#include <sys/signalvar.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/cpufunc.h>
+#include <machine/pcb.h>
+#include <machine/trap.h>
+#include <machine/specialreg.h>
+#include <machine/fpu.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+
+/*
+ * We do lazy initialization and switching using the TS bit in cr0 and the
+ * MDP_USEDFPU bit in mdproc.
+ *
+ * DNA exceptions are handled like this:
+ *
+ * 1) If there is no FPU, return and go to the emulator.
+ * 2) If someone else has used the FPU, save its state into that process' PCB.
+ * 3a) If MDP_USEDFPU is not set, set it and initialize the FPU.
+ * 3b) Otherwise, reload the process' previous FPU state.
+ *
+ * When a process is created or exec()s, its saved cr0 image has the TS bit
+ * set and the MDP_USEDFPU bit clear. The MDP_USEDFPU bit is set when the
+ * process first gets a DNA and the FPU is initialized. The TS bit is turned
+ * off when the FPU is used, and turned on again later when the process' FPU
+ * state is saved.
+ */
+
+#define fninit() __asm("fninit")
+#define fwait() __asm("fwait")
+#define fxsave(addr) __asm("fxsave %0" : "=m" (*addr))
+#define fxrstor(addr) __asm("fxrstor %0" : : "m" (*addr))
+#define fldcw(addr) __asm("fldcw %0" : : "m" (*addr))
+#define clts() __asm("clts")
+#define stts() lcr0(rcr0() | CR0_TS)
+
+void fpudna(struct cpu_info *);
+
+/*
+ * Init the FPU.
+ */
+void
+fpuinit(struct cpu_info *ci)
+{
+ lcr0(rcr0() & ~(CR0_EM|CR0_TS));
+ fninit();
+ lcr0(rcr0() | (CR0_TS));
+}
+
+/*
+ * Record the FPU state and reinitialize it all except for the control word.
+ * Then generate a SIGFPE.
+ *
+ * Reinitializing the state allows naive SIGFPE handlers to longjmp without
+ * doing any fixups.
+ */
+
+void
+fputrap(struct trapframe *frame)
+{
+ struct proc *p = curcpu()->ci_fpcurproc;
+ struct savefpu *sfp = &p->p_addr->u_pcb.pcb_savefpu;
+ u_int16_t cw;
+ union sigval sv;
+
+printf("fputrap\n");
+#ifdef DIAGNOSTIC
+ /*
+ * At this point, fpcurproc should be curproc. If it wasn't,
+ * the TS bit should be set, and we should have gotten a DNA exception.
+ */
+ if (p != curproc)
+ panic("fputrap: wrong proc");
+#endif
+
+ fxsave(sfp);
+ if (frame->tf_trapno == T_XMM) {
+ } else {
+ fninit();
+ fwait();
+ cw = sfp->fp_fxsave.fx_fcw;
+ fldcw(&cw);
+ fwait();
+ }
+ sfp->fp_ex_tw = sfp->fp_fxsave.fx_ftw;
+ sfp->fp_ex_sw = sfp->fp_fxsave.fx_fsw;
+ sv.sival_ptr = (void *)frame->tf_rip; /* XXX - ? */
+ KERNEL_PROC_LOCK(p);
+ trapsignal(p, SIGFPE, frame->tf_err, 0 /* XXX */, sv);
+ KERNEL_PROC_UNLOCK(p);
+}
+
+/*
+ * Implement device not available (DNA) exception
+ *
+ * If we were the last process to use the FPU, we can simply return.
+ * Otherwise, we save the previous state, if necessary, and restore our last
+ * saved state.
+ */
+void
+fpudna(struct cpu_info *ci)
+{
+ u_int16_t cw;
+ struct proc *p;
+ int s;
+
+ if (ci->ci_fpsaving) {
+ printf("recursive fpu trap; cr0=%x\n", rcr0());
+ return;
+ }
+
+ s = splipi();
+
+#ifdef MULTIPROCESSOR
+ p = ci->ci_curproc;
+#else
+ p = curproc;
+#endif
+
+ /*
+ * Initialize the FPU state to clear any exceptions. If someone else
+ * was using the FPU, save their state.
+ */
+ if (ci->ci_fpcurproc != NULL && ci->ci_fpcurproc != p)
+ fpusave_cpu(ci, 1);
+ else {
+ clts();
+ fninit();
+ fwait();
+ stts();
+ }
+ splx(s);
+
+ if (p == NULL) {
+ clts();
+ return;
+ }
+
+ KDASSERT(ci->ci_fpcurproc == NULL);
+#ifndef MULTIPROCESSOR
+ KDASSERT(p->p_addr->u_pcb.pcb_fpcpu == NULL);
+#else
+ if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
+ fpusave_proc(p, 1);
+#endif
+
+ p->p_addr->u_pcb.pcb_cr0 &= ~CR0_TS;
+ clts();
+
+ s = splipi();
+ ci->ci_fpcurproc = p;
+ p->p_addr->u_pcb.pcb_fpcpu = ci;
+ splx(s);
+
+ if ((p->p_md.md_flags & MDP_USEDFPU) == 0) {
+ cw = p->p_addr->u_pcb.pcb_savefpu.fp_fxsave.fx_fcw;
+ fldcw(&cw);
+ p->p_md.md_flags |= MDP_USEDFPU;
+ } else
+ fxrstor(&p->p_addr->u_pcb.pcb_savefpu);
+}
+
+
+void
+fpusave_cpu(struct cpu_info *ci, int save)
+{
+ struct proc *p;
+ int s;
+
+ KDASSERT(ci == curcpu());
+
+ p = ci->ci_fpcurproc;
+ if (p == NULL)
+ return;
+
+ if (save) {
+#ifdef DIAGNOSTIC
+ if (ci->ci_fpsaving != 0)
+ panic("fpusave_cpu: recursive save!");
+#endif
+ /*
+ * Set ci->ci_fpsaving, so that any pending exception will be
+ * thrown away. (It will be caught again if/when the FPU
+ * state is restored.)
+ */
+ clts();
+ ci->ci_fpsaving = 1;
+ fxsave(&p->p_addr->u_pcb.pcb_savefpu);
+ ci->ci_fpsaving = 0;
+ }
+
+ stts();
+ p->p_addr->u_pcb.pcb_cr0 |= CR0_TS;
+
+ s = splipi();
+ p->p_addr->u_pcb.pcb_fpcpu = NULL;
+ ci->ci_fpcurproc = NULL;
+ splx(s);
+}
+
+/*
+ * Save l's FPU state, which may be on this processor or another processor.
+ */
+void
+fpusave_proc(struct proc *p, int save)
+{
+ struct cpu_info *ci = curcpu();
+ struct cpu_info *oci;
+
+ KDASSERT(p->p_addr != NULL);
+ KDASSERT(p->p_flag & P_INMEM);
+
+ oci = p->p_addr->u_pcb.pcb_fpcpu;
+ if (oci == NULL)
+ return;
+
+#if defined(MULTIPROCESSOR)
+ if (oci == ci) {
+ int s = splipi();
+ fpusave_cpu(ci, save);
+ splx(s);
+ } else {
+#ifdef DIAGNOSTIC
+ int spincount;
+#endif
+
+ x86_send_ipi(oci,
+ save ? X86_IPI_SYNCH_FPU : X86_IPI_FLUSH_FPU);
+
+#ifdef DIAGNOSTIC
+ spincount = 0;
+#endif
+ while (p->dpl_addr->u_pcb.pcb_fpcpu != NULL)
+#ifdef DIAGNOSTIC
+ {
+ spincount++;
+ if (spincount > 10000000) {
+ panic("fp_save ipi didn't");
+ }
+ }
+#else
+ __splbarrier(); /* XXX replace by generic barrier */
+ ;
+#endif
+ }
+#else
+ KASSERT(ci->ci_fpcurproc == p);
+ fpusave_cpu(ci, save);
+#endif
+}
diff --git a/sys/arch/amd64/amd64/gdt.c b/sys/arch/amd64/amd64/gdt.c
new file mode 100644
index 00000000000..4790b079614
--- /dev/null
+++ b/sys/arch/amd64/amd64/gdt.c
@@ -0,0 +1,374 @@
+/* $OpenBSD: gdt.c,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+/* $NetBSD: gdt.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by John T. Kohl and Charles M. Hannum.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * Modified to deal with variable-length entries for NetBSD/x86_64 by
+ * fvdl@wasabisystems.com, may 2001
+ * XXX this file should be shared with the i386 code, the difference
+ * can be hidden in macros.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/lock.h>
+#include <sys/user.h>
+
+#include <uvm/uvm.h>
+
+#include <machine/gdt.h>
+
+#define MINGDTSIZ 2048
+#define MAXGDTSIZ 65536
+
+int gdt_size; /* size of GDT in bytes */
+int gdt_dyncount; /* number of dyn. allocated GDT entries in use */
+int gdt_dynavail;
+int gdt_next; /* next available slot for sweeping */
+int gdt_free; /* next free slot; terminated with GNULL_SEL */
+
+struct lock gdt_lock_store;
+
+static __inline void gdt_lock(void);
+static __inline void gdt_unlock(void);
+void gdt_init(void);
+void gdt_grow(void);
+int gdt_get_slot(void);
+void gdt_put_slot(int);
+
+/*
+ * Lock and unlock the GDT, to avoid races in case gdt_{ge,pu}t_slot() sleep
+ * waiting for memory.
+ *
+ * Note that the locking done here is not sufficient for multiprocessor
+ * systems. A freshly allocated slot will still be of type SDT_SYSNULL for
+ * some time after the GDT is unlocked, so gdt_compact() could attempt to
+ * reclaim it.
+ */
+static __inline void
+gdt_lock()
+{
+
+ (void) lockmgr(&gdt_lock_store, LK_EXCLUSIVE, NULL, curproc);
+}
+
+static __inline void
+gdt_unlock()
+{
+
+ (void) lockmgr(&gdt_lock_store, LK_RELEASE, NULL, curproc);
+}
+
+void
+set_mem_gdt(sd, base, limit, type, dpl, gran, def32, is64)
+ struct mem_segment_descriptor *sd;
+ void *base;
+ size_t limit;
+ int type, dpl, gran, def32, is64;
+{
+ CPU_INFO_ITERATOR cii;
+ struct cpu_info *ci;
+ int off;
+
+ set_mem_segment(sd, base, limit, type, dpl, gran, def32, is64);
+ off = (char *)sd - gdtstore;
+ for (CPU_INFO_FOREACH(cii, ci)) {
+ if (ci->ci_gdt != NULL)
+ *(struct mem_segment_descriptor *)(ci->ci_gdt + off) =
+ *sd;
+ }
+}
+
+void
+set_sys_gdt(sd, base, limit, type, dpl, gran)
+ struct sys_segment_descriptor *sd;
+ void *base;
+ size_t limit;
+ int type, dpl, gran;
+{
+ CPU_INFO_ITERATOR cii;
+ struct cpu_info *ci;
+ int off;
+
+ set_sys_segment(sd, base, limit, type, dpl, gran);
+ off = (char *)sd - gdtstore;
+ for (CPU_INFO_FOREACH(cii, ci)) {
+ if (ci->ci_gdt != NULL)
+ *(struct sys_segment_descriptor *)(ci->ci_gdt + off) =
+ *sd;
+ }
+}
+
+
+/*
+ * Initialize the GDT.
+ */
+void
+gdt_init()
+{
+ char *old_gdt;
+ struct vm_page *pg;
+ vaddr_t va;
+ struct cpu_info *ci = &cpu_info_primary;
+
+ lockinit(&gdt_lock_store, PZERO, "gdtlck", 0, 0);
+
+ gdt_size = MINGDTSIZ;
+ gdt_dyncount = 0;
+ gdt_next = 0;
+ gdt_free = GNULL_SEL;
+ gdt_dynavail =
+ (gdt_size - DYNSEL_START) / sizeof (struct sys_segment_descriptor);
+
+ old_gdt = gdtstore;
+ gdtstore = (char *)uvm_km_valloc(kernel_map, MAXGDTSIZ);
+ for (va = (vaddr_t)gdtstore; va < (vaddr_t)gdtstore + MINGDTSIZ;
+ va += PAGE_SIZE) {
+ pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO);
+ if (pg == NULL) {
+ panic("gdt_init: no pages");
+ }
+ pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg),
+ VM_PROT_READ | VM_PROT_WRITE);
+ }
+ memcpy(gdtstore, old_gdt, DYNSEL_START);
+ ci->ci_gdt = gdtstore;
+ set_sys_segment(GDT_ADDR_SYS(gdtstore, GLDT_SEL), ldtstore,
+ LDT_SIZE - 1, SDT_SYSLDT, SEL_KPL, 0);
+
+ gdt_init_cpu(ci);
+}
+
+/*
+ * Allocate shadow GDT for a slave cpu.
+ */
+void
+gdt_alloc_cpu(struct cpu_info *ci)
+{
+ ci->ci_gdt = (char *)uvm_km_valloc(kernel_map, MAXGDTSIZ);
+ uvm_map_pageable(kernel_map, (vaddr_t)ci->ci_gdt,
+ (vaddr_t)ci->ci_gdt + MINGDTSIZ, FALSE, FALSE);
+ memset(ci->ci_gdt, 0, MINGDTSIZ);
+ memcpy(ci->ci_gdt, gdtstore,
+ DYNSEL_START + gdt_dyncount * sizeof(struct sys_segment_descriptor));
+}
+
+
+/*
+ * Load appropriate gdt descriptor; we better be running on *ci
+ * (for the most part, this is how a cpu knows who it is).
+ */
+void
+gdt_init_cpu(struct cpu_info *ci)
+{
+ struct region_descriptor region;
+
+ setregion(&region, ci->ci_gdt, (u_int16_t)(MAXGDTSIZ - 1));
+ lgdt(&region);
+}
+
+#ifdef MULTIPROCESSOR
+
+void
+gdt_reload_cpu(struct cpu_info *ci)
+{
+ struct region_descriptor region;
+
+ setregion(&region, ci->ci_gdt, MAXGDTSIZ - 1);
+ lgdt(&region);
+}
+#endif
+
+
+/*
+ * Grow or shrink the GDT.
+ */
+void
+gdt_grow()
+{
+ size_t old_len, new_len;
+ struct vm_page *pg;
+ vaddr_t va;
+
+ old_len = gdt_size;
+ gdt_size <<= 1;
+ new_len = old_len << 1;
+ gdt_dynavail =
+ (gdt_size - DYNSEL_START) / sizeof (struct sys_segment_descriptor);
+
+ for (va = (vaddr_t)gdtstore + old_len; va < (vaddr_t)gdtstore + new_len;
+ va += PAGE_SIZE) {
+ while ((pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO)) ==
+ NULL) {
+ uvm_wait("gdt_grow");
+ }
+ pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg),
+ VM_PROT_READ | VM_PROT_WRITE);
+ }
+}
+
+/*
+ * Allocate a GDT slot as follows:
+ * 1) If there are entries on the free list, use those.
+ * 2) If there are fewer than gdt_dynavail entries in use, there are free slots
+ * near the end that we can sweep through.
+ * 3) As a last resort, we increase the size of the GDT, and sweep through
+ * the new slots.
+ */
+int
+gdt_get_slot()
+{
+ int slot;
+ struct sys_segment_descriptor *gdt;
+
+ gdt = (struct sys_segment_descriptor *)&gdtstore[DYNSEL_START];
+
+ gdt_lock();
+
+ if (gdt_free != GNULL_SEL) {
+ slot = gdt_free;
+ gdt_free = gdt[slot].sd_xx3; /* XXXfvdl res. field abuse */
+ } else {
+#ifdef DIAGNOSTIC
+ if (gdt_next != gdt_dyncount)
+ panic("gdt_get_slot botch 1");
+#endif
+ if (gdt_next >= gdt_dynavail) {
+#ifdef DIAGNOSTIC
+ if (gdt_size >= MAXGDTSIZ)
+ panic("gdt_get_slot botch 2");
+#endif
+ gdt_grow();
+ }
+ slot = gdt_next++;
+ }
+
+ gdt_dyncount++;
+ gdt_unlock();
+ return (slot);
+}
+
+/*
+ * Deallocate a GDT slot, putting it on the free list.
+ */
+void
+gdt_put_slot(slot)
+ int slot;
+{
+ struct sys_segment_descriptor *gdt;
+
+ gdt = (struct sys_segment_descriptor *)&gdtstore[DYNSEL_START];
+
+ gdt_lock();
+ gdt_dyncount--;
+
+ gdt[slot].sd_type = SDT_SYSNULL;
+ gdt[slot].sd_xx3 = gdt_free;
+ gdt_free = slot;
+
+ gdt_unlock();
+}
+
+int
+tss_alloc(pcb)
+ struct pcb *pcb;
+{
+ int slot;
+ struct sys_segment_descriptor *gdt;
+
+ gdt = (struct sys_segment_descriptor *)&gdtstore[DYNSEL_START];
+
+ slot = gdt_get_slot();
+#if 0
+ printf("tss_alloc: slot %d addr %p\n", slot, &gdt[slot]);
+#endif
+ set_sys_gdt(&gdt[slot], &pcb->pcb_tss, sizeof (struct x86_64_tss)-1,
+ SDT_SYS386TSS, SEL_KPL, 0);
+#if 0
+ printf("lolimit %lx lobase %lx type %lx dpl %lx p %lx hilimit %lx\n"
+ "xx1 %lx gran %lx hibase %lx xx2 %lx zero %lx xx3 %lx pad %lx\n",
+ (unsigned long)gdt[slot].sd_lolimit,
+ (unsigned long)gdt[slot].sd_lobase,
+ (unsigned long)gdt[slot].sd_type,
+ (unsigned long)gdt[slot].sd_dpl,
+ (unsigned long)gdt[slot].sd_p,
+ (unsigned long)gdt[slot].sd_hilimit,
+ (unsigned long)gdt[slot].sd_xx1,
+ (unsigned long)gdt[slot].sd_gran,
+ (unsigned long)gdt[slot].sd_hibase,
+ (unsigned long)gdt[slot].sd_xx2,
+ (unsigned long)gdt[slot].sd_zero,
+ (unsigned long)gdt[slot].sd_xx3);
+#endif
+ return GDYNSEL(slot, SEL_KPL);
+}
+
+void
+tss_free(int sel)
+{
+
+ gdt_put_slot(IDXDYNSEL(sel));
+}
+
+void
+ldt_alloc(pmap, ldt, len)
+ struct pmap *pmap;
+ char *ldt;
+ size_t len;
+{
+ int slot;
+ struct sys_segment_descriptor *gdt;
+
+ gdt = (struct sys_segment_descriptor *)&gdtstore[DYNSEL_START];
+
+ slot = gdt_get_slot();
+ set_sys_gdt(&gdt[slot], ldt, len - 1, SDT_SYSLDT, SEL_KPL, 0);
+ pmap->pm_ldt_sel = GSEL(slot, SEL_KPL);
+}
+
+void
+ldt_free(pmap)
+ struct pmap *pmap;
+{
+ int slot;
+
+ slot = IDXDYNSEL(pmap->pm_ldt_sel);
+
+ gdt_put_slot(slot);
+}
diff --git a/sys/arch/amd64/amd64/genassym.cf b/sys/arch/amd64/amd64/genassym.cf
new file mode 100644
index 00000000000..da5462ebd46
--- /dev/null
+++ b/sys/arch/amd64/amd64/genassym.cf
@@ -0,0 +1,122 @@
+# $OpenBSD: genassym.cf,v 1.1 2004/01/28 01:39:38 mickey Exp $
+
+# Written by Artur Grabowski art@openbsd.org, Public Domain
+
+include <sys/param.h>
+include <sys/proc.h>
+include <sys/resourcevar.h>
+include <sys/device.h>
+include <sys/user.h>
+
+include <uvm/uvm.h>
+
+include <machine/trap.h>
+include <machine/pmap.h>
+include <machine/vmparam.h>
+include <machine/intr.h>
+
+export SRUN
+
+define L3_SLOT_KERNBASE pl3_pi(KERNBASE)
+define L2_SLOT_KERNBASE pl2_pi(KERNBASE)
+define L1_SLOT_KERNBASE pl1_pi(KERNBASE)
+
+export VM_MAXUSER_ADDRESS
+export VM_MIN_KERNEL_ADDRESS
+
+define UVM_PAGE_IDLE_ZERO offsetof(struct uvm, page_idle_zero)
+
+struct proc
+member p_addr
+member p_back
+member p_forw
+member p_priority
+member p_stat
+member p_wchan
+member P_MD_TSS_SEL p_md.md_tss_sel
+member P_MD_REGS p_md.md_regs
+member P_MD_FLAGS p_md.md_flags
+member P_MD_SYSCALL p_md.md_syscall
+member P_MD_ASTPENDING p_md.md_astpending
+member p_flag
+
+export P_SYSTEM
+
+export MDP_IRET
+
+struct uvmexp V_
+member INTR intrs
+
+struct trapframe
+member tf_rdi
+member tf_rsi
+member tf_rdx
+member tf_rcx
+member tf_r8
+member tf_r9
+member tf_r10
+member tf_r11
+member tf_r12
+member tf_r13
+member tf_r14
+member tf_r15
+member tf_rbp
+member tf_rbx
+member tf_rax
+member tf_gs
+member tf_fs
+member tf_es
+member tf_ds
+member tf_trapno
+member tf_err
+member tf_rip
+member tf_cs
+member tf_rflags
+member tf_rsp
+member tf_ss
+
+define FRAMESIZE sizeof(struct trapframe)
+
+struct pcb
+member pcb_cr3
+member pcb_rbp
+member pcb_rsp
+member pcb_usersp
+member PCB_RSP0 pcb_tss.tss_rsp0
+member pcb_cr0
+member pcb_ldt_sel
+member pcb_onfault
+member pcb_fpcpu
+
+struct cpu_info
+member CPU_INFO_SCRATCH ci_scratch
+member CPU_INFO_SELF ci_self
+member CPU_INFO_RESCHED ci_want_resched
+member CPU_INFO_CURPROC ci_curproc
+member CPU_INFO_CURPCB ci_curpcb
+member CPU_INFO_IDLE_PCB ci_idle_pcb
+member CPU_INFO_IDLE_TSS_SEL ci_idle_tss_sel
+member CPU_INFO_ASTPENDING ci_astpending
+member CPU_INFO_ILEVEL ci_ilevel
+member CPU_INFO_IDEPTH ci_idepth
+member CPU_INFO_ISOURCES ci_isources
+member CPU_INFO_IPENDING ci_ipending
+member CPU_INFO_IUNMASK ci_iunmask
+
+struct intrsource
+member is_recurse
+member is_resume
+member is_evcnt
+member is_handlers
+member is_pic
+member is_flags
+member is_pin
+member is_type
+member is_maxlevel
+
+struct intrhand
+member ih_fun
+member ih_arg
+member ih_next
+member ih_level
+
diff --git a/sys/arch/amd64/amd64/i8259.c b/sys/arch/amd64/amd64/i8259.c
new file mode 100644
index 00000000000..12b04b2a40b
--- /dev/null
+++ b/sys/arch/amd64/amd64/i8259.c
@@ -0,0 +1,255 @@
+/* $OpenBSD: i8259.c,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+/* $NetBSD: i8259.c,v 1.2 2003/03/02 18:27:15 fvdl Exp $ */
+
+/*
+ * Copyright 2002 (c) Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Frank van der Linden for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 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.
+ * 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.
+ *
+ * @(#)isa.c 7.2 (Berkeley) 5/13/91
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+
+#include <dev/isa/isareg.h>
+
+#include <machine/pio.h>
+#include <machine/cpufunc.h>
+#include <machine/cpu.h>
+#include <machine/pic.h>
+#include <machine/i8259.h>
+
+
+#ifndef __x86_64__
+#include "mca.h"
+#if NMCA > 0
+#include <machine/mca_machdep.h> /* for MCA_system */
+#endif
+#endif
+
+static void i8259_hwmask(struct pic *, int);
+static void i8259_hwunmask(struct pic *, int);
+static void i8259_setup(struct pic *, struct cpu_info *, int, int, int);
+static void i8259_reinit_irqs(void);
+
+unsigned i8259_imen;
+
+/*
+ * Perhaps this should be made into a real device.
+ */
+struct pic i8259_pic = {
+ {0, {NULL}, NULL, 0, "pic0", NULL, 0, 0},
+ PIC_I8259,
+#ifdef MULTIPROCESSOR
+ __SIMPLELOCK_UNLOCKED,
+#else
+ 0,
+#endif
+ i8259_hwmask,
+ i8259_hwunmask,
+ i8259_setup,
+ i8259_setup,
+ i8259_stubs,
+ i8259_stubs,
+};
+
+void
+i8259_default_setup(void)
+{
+#if NMCA > 0
+ /* level-triggered interrupts on MCA PS/2s */
+ if (MCA_system)
+ outb(IO_ICU1, 0x19); /* reset; program device, four bytes */
+ else
+#endif
+ outb(IO_ICU1, 0x11); /* reset; program device, four bytes */
+
+ outb(IO_ICU1+1, ICU_OFFSET); /* starting at this vector index */
+ outb(IO_ICU1+1, 1 << IRQ_SLAVE); /* slave on line 2 */
+#ifdef AUTO_EOI_1
+ outb(IO_ICU1+1, 2 | 1); /* auto EOI, 8086 mode */
+#else
+ outb(IO_ICU1+1, 1); /* 8086 mode */
+#endif
+ outb(IO_ICU1+1, 0xff); /* leave interrupts masked */
+ outb(IO_ICU1, 0x68); /* special mask mode (if available) */
+ outb(IO_ICU1, 0x0a); /* Read IRR by default. */
+#ifdef REORDER_IRQ
+ outb(IO_ICU1, 0xc0 | (3 - 1)); /* pri order 3-7, 0-2 (com2 first) */
+#endif
+
+#if NMCA > 0
+ /* level-triggered interrupts on MCA PS/2s */
+ if (MCA_system)
+ outb(IO_ICU2, 0x19); /* reset; program device, four bytes */
+ else
+#endif
+ outb(IO_ICU2, 0x11); /* reset; program device, four bytes */
+
+ outb(IO_ICU2+1, ICU_OFFSET+8); /* staring at this vector index */
+ outb(IO_ICU2+1, IRQ_SLAVE);
+#ifdef AUTO_EOI_2
+ outb(IO_ICU2+1, 2 | 1); /* auto EOI, 8086 mode */
+#else
+ outb(IO_ICU2+1, 1); /* 8086 mode */
+#endif
+ outb(IO_ICU2+1, 0xff); /* leave interrupts masked */
+ outb(IO_ICU2, 0x68); /* special mask mode (if available) */
+ outb(IO_ICU2, 0x0a); /* Read IRR by default. */
+}
+
+static void
+i8259_hwmask(struct pic *pic, int pin)
+{
+ unsigned port;
+ u_int8_t byte;
+
+ i8259_imen |= (1 << pin);
+#ifdef PIC_MASKDELAY
+ delay(10);
+#endif
+ if (pin > 7) {
+ port = IO_ICU2 + 1;
+ byte = i8259_imen >> 8;
+ } else {
+ port = IO_ICU1 + 1;
+ byte = i8259_imen & 0xff;
+ }
+ outb(port, byte);
+}
+
+static void
+i8259_hwunmask(struct pic *pic, int pin)
+{
+ unsigned port;
+ u_int8_t byte;
+
+ disable_intr(); /* XXX */
+ i8259_imen &= ~(1 << pin);
+#ifdef PIC_MASKDELAY
+ delay(10);
+#endif
+ if (pin > 7) {
+ port = IO_ICU2 + 1;
+ byte = i8259_imen >> 8;
+ } else {
+ port = IO_ICU1 + 1;
+ byte = i8259_imen & 0xff;
+ }
+ outb(port, byte);
+ enable_intr();
+}
+
+static void
+i8259_reinit_irqs(void)
+{
+ int irqs, irq;
+ struct cpu_info *ci = &cpu_info_primary;
+
+ irqs = 0;
+ for (irq = 0; irq < NUM_LEGACY_IRQS; irq++)
+ if (ci->ci_isources[irq] != NULL)
+ irqs |= 1 << irq;
+ if (irqs >= 0x100) /* any IRQs >= 8 in use */
+ irqs |= 1 << IRQ_SLAVE;
+ i8259_imen = ~irqs;
+
+ outb(IO_ICU1 + 1, i8259_imen);
+ outb(IO_ICU2 + 1, i8259_imen >> 8);
+}
+
+static void
+i8259_setup(struct pic *pic, struct cpu_info *ci, int pin, int idtvec, int type)
+{
+ if (CPU_IS_PRIMARY(ci))
+ i8259_reinit_irqs();
+}
+
+void
+i8259_reinit(void)
+{
+ i8259_default_setup();
+ i8259_reinit_irqs();
+}
+
+unsigned
+i8259_setmask(unsigned mask)
+{
+ unsigned old = i8259_imen;
+
+ i8259_imen = mask;
+ outb(IO_ICU1 + 1, i8259_imen);
+ outb(IO_ICU2 + 1, i8259_imen >> 8);
+ return old;
+}
diff --git a/sys/arch/amd64/amd64/identcpu.c b/sys/arch/amd64/amd64/identcpu.c
new file mode 100644
index 00000000000..6535b5e768c
--- /dev/null
+++ b/sys/arch/amd64/amd64/identcpu.c
@@ -0,0 +1,105 @@
+/* $OpenBSD: identcpu.c,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+/* $NetBSD: identcpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */
+
+/*
+ * Copyright (c) 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Frank van der Linden for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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/types.h>
+#include <sys/systm.h>
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+
+/* sysctl wants this. */
+char cpu_model[48];
+
+void
+identifycpu(struct cpu_info *ci)
+{
+ u_int64_t last_tsc;
+ u_int32_t dummy, val;
+ u_int32_t brand[12];
+
+ CPUID(1, ci->ci_signature, val, dummy, ci->ci_feature_flags);
+ CPUID(0x80000001, dummy, dummy, dummy, val);
+ ci->ci_feature_flags |= val;
+
+ CPUID(0x80000002, brand[0], brand[1], brand[2], brand[3]);
+ CPUID(0x80000003, brand[4], brand[5], brand[6], brand[7]);
+ CPUID(0x80000004, brand[8], brand[9], brand[10], brand[11]);
+
+ strlcpy(cpu_model, (char *)brand, sizeof(cpu_model));
+ if (cpu_model[0] == 0)
+ strlcpy(cpu_model, "Opteron or Athlon 64", sizeof(cpu_model));
+
+ last_tsc = rdtsc();
+ delay(100000);
+ ci->ci_tsc_freq = (rdtsc() - last_tsc) * 10;
+
+ amd_cpu_cacheinfo(ci);
+
+ printf("%s: %s", ci->ci_dev->dv_xname, cpu_model);
+
+ if (ci->ci_tsc_freq != 0)
+ printf(", %lu.%02lu MHz", (ci->ci_tsc_freq + 4999) / 1000000,
+ ((ci->ci_tsc_freq + 4999) / 10000) % 100);
+ printf("\n");
+
+ if ((ci->ci_feature_flags & CPUID_MASK1) != 0) {
+ printf("%s: features: %b\n", ci->ci_dev->dv_xname,
+ ci->ci_feature_flags, CPUID_FLAGS1);
+ }
+ if ((ci->ci_feature_flags & CPUID_MASK2) != 0) {
+ printf("%s: features: %b\n", ci->ci_dev->dv_xname,
+ ci->ci_feature_flags, CPUID_EXT_FLAGS2);
+ }
+ if ((ci->ci_feature_flags & CPUID_MASK3) != 0) {
+ printf("%s: features: %b\n", ci->ci_dev->dv_xname,
+ ci->ci_feature_flags, CPUID_EXT_FLAGS3);
+ }
+
+ x86_print_cacheinfo(ci);
+
+ return; /* TODO - warning to fix this ifdef later */
+#ifdef notyet
+ microtime_func = cc_microtime;
+#endif
+}
+
+void
+cpu_probe_features(struct cpu_info *ci)
+{
+ ci->ci_feature_flags = cpu_feature;
+ ci->ci_signature = 0;
+}
diff --git a/sys/arch/amd64/amd64/intr.c b/sys/arch/amd64/amd64/intr.c
new file mode 100644
index 00000000000..a80798e3a44
--- /dev/null
+++ b/sys/arch/amd64/amd64/intr.c
@@ -0,0 +1,707 @@
+/* $OpenBSD: intr.c,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+/* $NetBSD: intr.c,v 1.3 2003/03/03 22:16:20 fvdl Exp $ */
+
+/*
+ * Copyright 2002 (c) Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Frank van der Linden for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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.
+ */
+
+/* #define INTRDEBUG */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/errno.h>
+
+#include <machine/atomic.h>
+#include <machine/i8259.h>
+#include <machine/cpu.h>
+#include <machine/pio.h>
+
+#include "ioapic.h"
+#include "lapic.h"
+
+#if NIOAPIC > 0
+#include <machine/i82093var.h>
+#include <machine/mpbiosvar.h>
+#endif
+
+#if NLAPIC > 0
+#include <machine/i82489var.h>
+#endif
+
+struct pic softintr_pic = {
+ {0, {NULL}, NULL, 0, "softintr_fakepic", NULL, 0, 0},
+ PIC_SOFT,
+#ifdef MULTIPROCESSOR
+ __SIMPLELOCK_UNLOCKED,
+#else
+ 0,
+#endif
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+/*
+ * Fill in default interrupt table (in case of spurious interrupt
+ * during configuration of kernel), setup interrupt control unit
+ */
+void
+intr_default_setup(void)
+{
+ int i;
+
+ /* icu vectors */
+ for (i = 0; i < NUM_LEGACY_IRQS; i++) {
+ idt_allocmap[ICU_OFFSET + i] = 1;
+ setgate(&idt[ICU_OFFSET + i],
+ i8259_stubs[i].ist_entry, 0, SDT_SYS386IGT,
+ SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ }
+
+ /*
+ * Eventually might want to check if it's actually there.
+ */
+ i8259_default_setup();
+}
+
+/*
+ * Handle a NMI, possibly a machine check.
+ * return true to panic system, false to ignore.
+ */
+int
+x86_nmi(void)
+{
+ log(LOG_CRIT, "NMI port 61 %x, port 70 %x\n", inb(0x61), inb(0x70));
+ return(0);
+}
+
+/*
+ * Recalculate the interrupt masks from scratch.
+ */
+void
+intr_calculatemasks(struct cpu_info *ci)
+{
+ int irq, level, unusedirqs, intrlevel[MAX_INTR_SOURCES];
+ struct intrhand *q;
+
+ /* First, figure out which levels each IRQ uses. */
+ unusedirqs = 0xffffffff;
+ for (irq = 0; irq < MAX_INTR_SOURCES; irq++) {
+ int levels = 0;
+
+ if (ci->ci_isources[irq] == NULL) {
+ intrlevel[irq] = 0;
+ continue;
+ }
+ for (q = ci->ci_isources[irq]->is_handlers; q; q = q->ih_next)
+ levels |= 1 << q->ih_level;
+ intrlevel[irq] = levels;
+ if (levels)
+ unusedirqs &= ~(1 << irq);
+ }
+
+ /* Then figure out which IRQs use each level. */
+ for (level = 0; level < NIPL; level++) {
+ int irqs = 0;
+ for (irq = 0; irq < MAX_INTR_SOURCES; irq++)
+ if (intrlevel[irq] & (1 << level))
+ irqs |= 1 << irq;
+ ci->ci_imask[level] = irqs | unusedirqs;
+ }
+
+ for (level = 0; level<(NIPL-1); level++)
+ ci->ci_imask[level+1] |= ci->ci_imask[level];
+
+ for (irq = 0; irq < MAX_INTR_SOURCES; irq++) {
+ int maxlevel = IPL_NONE;
+ int minlevel = IPL_HIGH;
+
+ if (ci->ci_isources[irq] == NULL)
+ continue;
+ for (q = ci->ci_isources[irq]->is_handlers; q;
+ q = q->ih_next) {
+ if (q->ih_level < minlevel)
+ minlevel = q->ih_level;
+ if (q->ih_level > maxlevel)
+ maxlevel = q->ih_level;
+ }
+ ci->ci_isources[irq]->is_maxlevel = maxlevel;
+ ci->ci_isources[irq]->is_minlevel = minlevel;
+ }
+
+ for (level = 0; level < NIPL; level++)
+ ci->ci_iunmask[level] = ~ci->ci_imask[level];
+}
+
+
+/*
+ * XXX if defined(MULTIPROCESSOR) && .. ?
+ */
+#if NIOAPIC > 0
+int
+intr_find_mpmapping(int bus, int pin, int *handle)
+{
+ struct mp_intr_map *mip;
+
+ if (bus == -1 || mp_busses[bus].mb_intrs == NULL)
+ return ENOENT;
+
+ for (mip = mp_busses[bus].mb_intrs; mip != NULL; mip=mip->next) {
+ if (mip->bus_pin == pin) {
+ *handle = mip->ioapic_ih;
+ return 0;
+ }
+ }
+ return ENOENT;
+}
+#endif
+
+int
+intr_allocate_slot_cpu(struct cpu_info *ci, struct pic *pic, int pin,
+ int *index)
+{
+ int start, slot, i;
+ struct intrsource *isp;
+
+ start = CPU_IS_PRIMARY(ci) ? NUM_LEGACY_IRQS : 0;
+ slot = -1;
+
+ simple_lock(&ci->ci_slock);
+ for (i = start; i < MAX_INTR_SOURCES ; i++) {
+ isp = ci->ci_isources[i];
+ if (isp != NULL && isp->is_pic == pic && isp->is_pin == pin) {
+ slot = i;
+ break;
+ }
+ if (isp == NULL && slot == -1) {
+ slot = i;
+ continue;
+ }
+ }
+ if (slot == -1) {
+ simple_unlock(&ci->ci_slock);
+ return EBUSY;
+ }
+
+ isp = ci->ci_isources[slot];
+ if (isp == NULL) {
+ MALLOC(isp, struct intrsource *, sizeof (struct intrsource),
+ M_DEVBUF, M_NOWAIT);
+ memset(isp, 0, sizeof(struct intrsource));
+ if (isp == NULL) {
+ simple_unlock(&ci->ci_slock);
+ return ENOMEM;
+ }
+ snprintf(isp->is_evname, sizeof (isp->is_evname),
+ "pin %d", pin);
+#if notyet
+ evcnt_attach_dynamic(&isp->is_evcnt, EVCNT_TYPE_INTR, NULL,
+ pic->pic_dev.dv_xname, isp->is_evname);
+#endif
+ ci->ci_isources[slot] = isp;
+ }
+ simple_unlock(&ci->ci_slock);
+
+ *index = slot;
+ return 0;
+}
+
+/*
+ * A simple round-robin allocator to assign interrupts to CPUs.
+ */
+int
+intr_allocate_slot(struct pic *pic, int legacy_irq, int pin, int level,
+ struct cpu_info **cip, int *index, int *idt_slot)
+{
+ CPU_INFO_ITERATOR cii;
+ struct cpu_info *ci;
+ struct intrsource *isp;
+ int slot, idtvec, error;
+
+ /*
+ * If a legacy IRQ is wanted, try to use a fixed slot pointing
+ * at the primary CPU. In the case of IO APICs, multiple pins
+ * may map to one legacy IRQ, but they should not be shared
+ * in that case, so the first one gets the legacy slot, but
+ * a subsequent allocation with a different pin will get
+ * a different slot.
+ */
+ if (legacy_irq != -1) {
+ ci = &cpu_info_primary;
+ slot = legacy_irq;
+ isp = ci->ci_isources[slot];
+ if (isp == NULL) {
+ MALLOC(isp, struct intrsource *,
+ sizeof (struct intrsource), M_DEVBUF,
+ M_NOWAIT);
+ memset(isp, 0, sizeof(struct intrsource));
+ if (isp == NULL)
+ return ENOMEM;
+ snprintf(isp->is_evname, sizeof (isp->is_evname),
+ "pin %d", pin);
+
+#if notyet
+ evcnt_attach_dynamic(&isp->is_evcnt, EVCNT_TYPE_INTR,
+ NULL, pic->pic_dev.dv_xname, isp->is_evname);
+#endif
+ simple_lock(&ci->ci_slock);
+ ci->ci_isources[slot] = isp;
+ simple_unlock(&ci->ci_slock);
+ } else {
+ if (isp->is_pin != pin) {
+ if (pic == &i8259_pic)
+ return EINVAL;
+ goto other;
+ }
+ }
+
+ if (pic == &i8259_pic)
+ idtvec = ICU_OFFSET + legacy_irq;
+ else {
+#ifdef IOAPIC_HWMASK
+ if (level > isp->is_maxlevel) {
+#else
+ if (isp->is_minlevel == 0 || level < isp->is_minlevel) {
+#endif
+ idtvec = idt_vec_alloc(APIC_LEVEL(level),
+ IDT_INTR_HIGH);
+ if (idtvec == 0)
+ return EBUSY;
+ } else
+ idtvec = isp->is_idtvec;
+ }
+ } else {
+other:
+ /*
+ * Otherwise, look for a free slot elsewhere. Do the primary
+ * CPU first.
+ */
+ ci = &cpu_info_primary;
+ error = intr_allocate_slot_cpu(ci, pic, pin, &slot);
+ if (error == 0)
+ goto found;
+
+ /*
+ * ..now try the others.
+ */
+ for (CPU_INFO_FOREACH(cii, ci)) {
+ if (CPU_IS_PRIMARY(ci))
+ continue;
+ error = intr_allocate_slot_cpu(ci, pic, pin, &slot);
+ if (error == 0)
+ goto found;
+ }
+ return EBUSY;
+found:
+ idtvec = idt_vec_alloc(APIC_LEVEL(level), IDT_INTR_HIGH);
+ if (idtvec == 0) {
+ simple_lock(&ci->ci_slock);
+ FREE(ci->ci_isources[slot], M_DEVBUF);
+ ci->ci_isources[slot] = NULL;
+ simple_unlock(&ci->ci_slock);
+ return EBUSY;
+ }
+ }
+ *idt_slot = idtvec;
+ *index = slot;
+ *cip = ci;
+ return 0;
+}
+
+void *
+intr_establish(int legacy_irq, struct pic *pic, int pin, int type, int level,
+ int (*handler)(void *), void *arg)
+{
+ struct intrhand **p, *q, *ih;
+ struct cpu_info *ci;
+ int slot, error, idt_vec;
+ struct intrsource *source;
+ struct intrstub *stubp;
+
+#ifdef DIAGNOSTIC
+ if (legacy_irq != -1 && (legacy_irq < 0 || legacy_irq > 15))
+ panic("intr_establish: bad legacy IRQ value");
+
+ if (legacy_irq == -1 && pic == &i8259_pic)
+ panic("intr_establish: non-legacy IRQ on i8259");
+#endif
+
+ error = intr_allocate_slot(pic, legacy_irq, pin, level, &ci, &slot,
+ &idt_vec);
+ if (error != 0) {
+ printf("failed to allocate interrupt slot for PIC %s pin %d\n",
+ pic->pic_dev.dv_xname, pin);
+ return NULL;
+ }
+
+ /* no point in sleeping unless someone can free memory. */
+ ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
+ if (ih == NULL) {
+ printf("intr_establish: can't allocate handler info\n");
+ return NULL;
+ }
+
+ source = ci->ci_isources[slot];
+
+ if (source->is_handlers != NULL &&
+ source->is_pic->pic_type != pic->pic_type) {
+ free(ih, M_DEVBUF);
+ printf("intr_establish: can't share intr source between "
+ "different PIC types (legacy_irq %d pin %d slot %d)\n",
+ legacy_irq, pin, slot);
+ return NULL;
+ }
+
+ simple_lock(&ci->ci_slock);
+
+ source->is_pin = pin;
+ source->is_pic = pic;
+
+ switch (source->is_type) {
+ case IST_NONE:
+ source->is_type = type;
+ break;
+ case IST_EDGE:
+ case IST_LEVEL:
+ if (source->is_type == type)
+ break;
+ case IST_PULSE:
+ if (type != IST_NONE) {
+ simple_unlock(&ci->ci_slock);
+ printf("intr_establish: pic %s pin %d: can't share "
+ "type %d with %d\n", pic->pic_name, pin,
+ source->is_type, type);
+ free(ih, M_DEVBUF);
+ return NULL;
+ }
+ break;
+ default:
+ simple_unlock(&ci->ci_slock);
+ panic("intr_establish: bad intr type %d for pic %s pin %d\n",
+ source->is_type, pic->pic_dev.dv_xname, pin);
+ }
+
+ if (!cold)
+ pic->pic_hwmask(pic, pin);
+
+ /*
+ * Figure out where to put the handler.
+ * This is O(N^2), but we want to preserve the order, and N is
+ * generally small.
+ */
+ for (p = &ci->ci_isources[slot]->is_handlers;
+ (q = *p) != NULL && q->ih_level > level;
+ p = &q->ih_next)
+ ;
+
+ ih->ih_fun = handler;
+ ih->ih_arg = arg;
+ ih->ih_next = *p;
+ ih->ih_level = level;
+ ih->ih_pin = pin;
+ ih->ih_cpu = ci;
+ ih->ih_slot = slot;
+ *p = ih;
+
+ intr_calculatemasks(ci);
+
+ simple_unlock(&ci->ci_slock);
+
+ if (ci->ci_isources[slot]->is_resume == NULL ||
+ source->is_idtvec != idt_vec) {
+ if (source->is_idtvec != 0 && source->is_idtvec != idt_vec)
+ idt_vec_free(source->is_idtvec);
+ source->is_idtvec = idt_vec;
+ stubp = type == IST_LEVEL ?
+ &pic->pic_level_stubs[slot] : &pic->pic_edge_stubs[slot];
+ ci->ci_isources[slot]->is_resume = stubp->ist_resume;
+ ci->ci_isources[slot]->is_recurse = stubp->ist_recurse;
+ setgate(&idt[idt_vec], stubp->ist_entry, 0, SDT_SYS386IGT,
+ SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
+ }
+
+ pic->pic_addroute(pic, ci, pin, idt_vec, type);
+
+ if (!cold)
+ pic->pic_hwunmask(pic, pin);
+
+#ifdef INTRDEBUG
+ printf("allocated pic %s type %s pin %d level %d to cpu%u slot %d idt entry %d\n",
+ pic->pic_name, type == IST_EDGE ? "edge" : "level", pin, level,
+ ci->ci_apicid, slot, idt_vec);
+#endif
+
+ return (ih);
+}
+
+/*
+ * Deregister an interrupt handler.
+ */
+void
+intr_disestablish(struct intrhand *ih)
+{
+ struct intrhand **p, *q;
+ struct cpu_info *ci;
+ struct pic *pic;
+ struct intrsource *source;
+ int idtvec;
+
+ ci = ih->ih_cpu;
+ pic = ci->ci_isources[ih->ih_slot]->is_pic;
+ source = ci->ci_isources[ih->ih_slot];
+ idtvec = source->is_idtvec;
+
+ simple_lock(&ci->ci_slock);
+ pic->pic_hwmask(pic, ih->ih_pin);
+ x86_atomic_clearbits_l(&ci->ci_ipending, (1 << ih->ih_slot));
+
+ /*
+ * Remove the handler from the chain.
+ */
+ for (p = &source->is_handlers; (q = *p) != NULL && q != ih;
+ p = &q->ih_next)
+ ;
+ if (q == NULL) {
+ simple_unlock(&ci->ci_slock);
+ panic("intr_disestablish: handler not registered");
+ }
+
+ *p = q->ih_next;
+
+ intr_calculatemasks(ci);
+ pic->pic_delroute(pic, ci, ih->ih_pin, idtvec, source->is_type);
+ pic->pic_hwunmask(pic, ih->ih_pin);
+
+#ifdef INTRDEBUG
+ printf("cpu%u: remove slot %d (pic %s pin %d vec %d)\n",
+ ci->ci_apicid, ih->ih_slot, pic->pic_dev.dv_xname, ih->ih_pin,
+ idtvec);
+#endif
+
+ if (source->is_handlers == NULL) {
+#if notyet
+ evcnt_detach(&source->is_evcnt);
+#endif
+ FREE(source, M_DEVBUF);
+ ci->ci_isources[ih->ih_slot] = NULL;
+ if (pic != &i8259_pic)
+ idt_vec_free(idtvec);
+ }
+
+ free(ih, M_DEVBUF);
+
+ simple_unlock(&ci->ci_slock);
+}
+
+#define CONCAT(x,y) __CONCAT(x,y)
+
+/*
+ * Fake interrupt handler structures for the benefit of symmetry with
+ * other interrupt sources, and the benefit of intr_calculatemasks()
+ */
+struct intrhand fake_softclock_intrhand;
+struct intrhand fake_softnet_intrhand;
+struct intrhand fake_softserial_intrhand;
+struct intrhand fake_timer_intrhand;
+struct intrhand fake_ipi_intrhand;
+
+#if NLAPIC > 0 && defined(MULTIPROCESSOR)
+static char *x86_ipi_names[X86_NIPI] = X86_IPI_NAMES;
+#endif
+
+/*
+ * Initialize all handlers that aren't dynamically allocated, and exist
+ * for each CPU.
+ */
+void
+cpu_intr_init(struct cpu_info *ci)
+{
+ struct intrsource *isp;
+#if NLAPIC > 0 && defined(MULTIPROCESSOR)
+ int i;
+#endif
+
+ MALLOC(isp, struct intrsource *, sizeof (struct intrsource), M_DEVBUF,
+ M_WAITOK);
+ memset(isp, 0, sizeof(struct intrsource));
+ if (isp == NULL)
+ panic("can't allocate fixed interrupt source");
+ isp->is_recurse = Xsoftclock;
+ isp->is_resume = Xsoftclock;
+ fake_softclock_intrhand.ih_level = IPL_SOFTCLOCK;
+ isp->is_handlers = &fake_softclock_intrhand;
+ isp->is_pic = &softintr_pic;
+ ci->ci_isources[SIR_CLOCK] = isp;
+#if notyet
+ evcnt_attach_dynamic(&isp->is_evcnt, EVCNT_TYPE_INTR, NULL,
+ ci->ci_dev->dv_xname, "softclock");
+#endif
+ MALLOC(isp, struct intrsource *, sizeof (struct intrsource), M_DEVBUF,
+ M_WAITOK);
+ memset(isp, 0, sizeof(struct intrsource));
+ if (isp == NULL)
+ panic("can't allocate fixed interrupt source");
+ isp->is_recurse = Xsoftnet;
+ isp->is_resume = Xsoftnet;
+ fake_softnet_intrhand.ih_level = IPL_SOFTNET;
+ isp->is_handlers = &fake_softnet_intrhand;
+ isp->is_pic = &softintr_pic;
+ ci->ci_isources[SIR_NET] = isp;
+#if notyet
+ evcnt_attach_dynamic(&isp->is_evcnt, EVCNT_TYPE_INTR, NULL,
+ ci->ci_dev->dv_xname, "softnet");
+#endif
+ MALLOC(isp, struct intrsource *, sizeof (struct intrsource), M_DEVBUF,
+ M_WAITOK);
+ memset(isp, 0, sizeof(struct intrsource));
+ if (isp == NULL)
+ panic("can't allocate fixed interrupt source");
+ isp->is_recurse = Xsoftserial;
+ isp->is_resume = Xsoftserial;
+ fake_softserial_intrhand.ih_level = IPL_SOFTSERIAL;
+ isp->is_handlers = &fake_softserial_intrhand;
+ isp->is_pic = &softintr_pic;
+ ci->ci_isources[SIR_SERIAL] = isp;
+#if notyet
+ evcnt_attach_dynamic(&isp->is_evcnt, EVCNT_TYPE_INTR, NULL,
+ ci->ci_dev->dv_xname, "softserial");
+#endif
+#if NLAPIC > 0
+ MALLOC(isp, struct intrsource *, sizeof (struct intrsource), M_DEVBUF,
+ M_WAITOK);
+ memset(isp, 0, sizeof(struct intrsource));
+ if (isp == NULL)
+ panic("can't allocate fixed interrupt source");
+ isp->is_recurse = Xrecurse_lapic_ltimer;
+ isp->is_resume = Xresume_lapic_ltimer;
+ fake_timer_intrhand.ih_level = IPL_CLOCK;
+ isp->is_handlers = &fake_timer_intrhand;
+ isp->is_pic = &local_pic;
+ ci->ci_isources[LIR_TIMER] = isp;
+#if notyet
+ evcnt_attach_dynamic(&isp->is_evcnt, EVCNT_TYPE_INTR, NULL,
+ ci->ci_dev->dv_xname, "timer");
+#endif
+#ifdef MULTIPROCESSOR
+ MALLOC(isp, struct intrsource *, sizeof (struct intrsource), M_DEVBUF,
+ M_WAITOK);
+ memset(isp, 0, sizeof(struct intrsource));
+ if (isp == NULL)
+ panic("can't allocate fixed interrupt source");
+ isp->is_recurse = Xrecurse_lapic_ipi;
+ isp->is_resume = Xresume_lapic_ipi;
+ fake_ipi_intrhand.ih_level = IPL_IPI;
+ isp->is_handlers = &fake_ipi_intrhand;
+ isp->is_pic = &local_pic;
+ ci->ci_isources[LIR_IPI] = isp;
+
+ for (i = 0; i < X86_NIPI; i++)
+ evcnt_attach_dynamic(&ci->ci_ipi_events[i], EVCNT_TYPE_INTR,
+ NULL, ci->ci_dev->dv_xname, x86_ipi_names[i]);
+#endif
+#endif
+
+ intr_calculatemasks(ci);
+
+}
+
+#ifdef MULTIPROCESSOR
+void
+x86_intlock(struct intrframe iframe)
+{
+ if (iframe.if_ppl < IPL_SCHED)
+ spinlockmgr(&kernel_lock, LK_EXCLUSIVE|LK_CANRECURSE, 0);
+}
+
+void
+x86_intunlock(struct intrframe iframe)
+{
+ if (iframe.if_ppl < IPL_SCHED)
+ spinlockmgr(&kernel_lock, LK_RELEASE, 0);
+}
+
+void
+x86_softintlock(void)
+{
+ spinlockmgr(&kernel_lock, LK_EXCLUSIVE|LK_CANRECURSE, 0);
+}
+
+void
+x86_softintunlock(void)
+{
+ spinlockmgr(&kernel_lock, LK_RELEASE, 0);
+}
+#endif
+
+void
+intr_printconfig(void)
+{
+#ifdef INTRDEBUG
+ int i;
+ struct intrhand *ih;
+ struct intrsource *isp;
+ struct cpu_info *ci;
+ CPU_INFO_ITERATOR cii;
+
+ for (CPU_INFO_FOREACH(cii, ci)) {
+ printf("cpu%d: interrupt masks:\n", ci->ci_apicid);
+ for (i = 0; i < NIPL; i++)
+ printf("IPL %d mask %lx unmask %lx\n", i,
+ (u_long)ci->ci_imask[i], (u_long)ci->ci_iunmask[i]);
+ simple_lock(&ci->ci_slock);
+ for (i = 0; i < MAX_INTR_SOURCES; i++) {
+ isp = ci->ci_isources[i];
+ if (isp == NULL)
+ continue;
+ printf("cpu%u source %d is pin %d from pic %s maxlevel %d\n",
+ ci->ci_apicid, i, isp->is_pin,
+ isp->is_pic->pic_name, isp->is_maxlevel);
+ for (ih = isp->is_handlers; ih != NULL;
+ ih = ih->ih_next)
+ printf("\thandler %p level %d\n",
+ ih->ih_fun, ih->ih_level);
+
+ }
+ simple_unlock(&ci->ci_slock);
+ }
+#endif
+}
diff --git a/sys/arch/amd64/amd64/locore.S b/sys/arch/amd64/amd64/locore.S
new file mode 100644
index 00000000000..2ec08feec31
--- /dev/null
+++ b/sys/arch/amd64/amd64/locore.S
@@ -0,0 +1,1243 @@
+/* $OpenBSD: locore.S,v 1.1 2004/01/28 01:39:38 mickey Exp $ */
+/* $NetBSD: locore.S,v 1.2 2003/04/26 19:34:45 fvdl Exp $ */
+
+/*
+ * Copyright-o-rama!
+ */
+
+/*
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Frank van der Linden for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*-
+ * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 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.
+ *
+ * @(#)locore.s 7.3 (Berkeley) 5/13/91
+ */
+
+#include "assym.h"
+#include "lapic.h"
+#include "ioapic.h"
+#include "ksyms.h"
+
+#include <sys/errno.h>
+#include <sys/syscall.h>
+
+#include <machine/param.h>
+#include <machine/pte.h>
+#include <machine/pmap.h>
+#include <machine/segments.h>
+#include <machine/specialreg.h>
+#include <machine/trap.h>
+#include <machine/bootinfo.h>
+#include <machine/frameasm.h>
+
+#if NLAPIC > 0
+#include <machine/i82489reg.h>
+#endif
+
+/*
+ * override user-land alignment before including asm.h
+ */
+#define ALIGN_DATA .align 8
+#define ALIGN_TEXT .align 16,0x90
+#define _ALIGN_TEXT ALIGN_TEXT
+
+#include <machine/asm.h>
+
+#if defined(MULTIPROCESSOR)
+
+#define SET_CURPROC(proc,cpu) \
+ movq CPUVAR(SELF),cpu ; \
+ movq proc,CPUVAR(CURPROC) ; \
+ movq cpu,P_CPU(proc)
+
+#else
+
+#define SET_CURPROC(proc,tcpu) movq proc,CPUVAR(CURPROC)
+#define GET_CURPROC(reg) movq CPUVAR(CURPROC),reg
+
+#endif
+
+#define GET_CURPCB(reg) movq CPUVAR(CURPCB),reg
+#define SET_CURPCB(reg) movq reg,CPUVAR(CURPCB)
+
+
+/* XXX temporary kluge; these should not be here */
+/* Get definitions for IOM_BEGIN, IOM_END, and IOM_SIZE */
+#include <dev/isa/isareg.h>
+
+
+/*
+ * Initialization
+ */
+ .data
+
+#if NLAPIC > 0
+ .align NBPG
+ .globl _C_LABEL(local_apic), _C_LABEL(lapic_id), _C_LABEL(lapic_tpr)
+_C_LABEL(local_apic):
+ .space LAPIC_ID
+_C_LABEL(lapic_id):
+ .long 0x00000000
+ .space LAPIC_TPRI-(LAPIC_ID+4)
+_C_LABEL(lapic_tpr):
+ .space LAPIC_PPRI-LAPIC_TPRI
+_C_LABEL(lapic_ppr):
+ .space LAPIC_ISR-LAPIC_PPRI
+_C_LABEL(lapic_isr):
+ .space NBPG-LAPIC_ISR
+#endif
+
+ .globl _C_LABEL(cpu_id),_C_LABEL(cpu_vendor), _C_LABEL(cpu_brand_id)
+ .globl _C_LABEL(cpuid_level),_C_LABEL(cpu_feature)
+ .globl _C_LABEL(esym),_C_LABEL(boothowto)
+ .globl _C_LABEL(bootinfo),_C_LABEL(atdevbase)
+ .globl _C_LABEL(proc0paddr),_C_LABEL(PTDpaddr)
+ .globl _C_LABEL(biosbasemem),_C_LABEL(biosextmem)
+ .globl _C_LABEL(gdtstore)
+_C_LABEL(cpu): .long 0 # are we 386, 386sx, or 486,
+ # or Pentium, or..
+_C_LABEL(cpu_id): .long 0 # saved from `cpuid' instruction
+_C_LABEL(cpu_feature): .long 0 # feature flags from 'cpuid'
+ # instruction
+_C_LABEL(cpuid_level): .long -1 # max. level accepted by 'cpuid'
+ # instruction
+_C_LABEL(cpu_vendor): .space 16 # vendor string returned by `cpuid'
+ # instruction
+_C_LABEL(cpu_brand_id): .long 0 # brand ID from 'cpuid' instruction
+_C_LABEL(esym): .quad 0 # ptr to end of syms
+_C_LABEL(atdevbase): .quad 0 # location of start of iomem in virtual
+_C_LABEL(proc0paddr): .quad 0
+_C_LABEL(PTDpaddr): .quad 0 # paddr of PTD, for libkvm
+#ifndef REALBASEMEM
+_C_LABEL(biosbasemem): .long 0 # base memory reported by BIOS
+#else
+_C_LABEL(biosbasemem): .long REALBASEMEM
+#endif
+#ifndef REALEXTMEM
+_C_LABEL(biosextmem): .long 0 # extended memory reported by BIOS
+#else
+_C_LABEL(biosextmem): .long REALEXTMEM
+#endif
+
+#define _RELOC(x) ((x) - KERNBASE)
+#define RELOC(x) _RELOC(_C_LABEL(x))
+
+ .globl gdt64
+
+gdt64:
+ .word gdt64_end-gdt64_start
+ .quad _RELOC(gdt64_start)
+.align 64
+
+gdt64_start:
+ .quad 0x0000000000000000 /* always empty */
+ .quad 0x00af9a000000ffff /* kernel CS */
+ .quad 0x00cf92000000ffff /* kernel DS */
+gdt64_end:
+
+farjmp64:
+ .long longmode-KERNBASE
+ .word GSEL(GCODE_SEL, SEL_KPL)
+
+ .space 512
+tmpstk:
+
+ .globl _C_LABEL(cpu_private)
+ .comm _C_LABEL(cpu_private),NBPG,NBPG
+
+/*
+ * Some hackage to deal with 64bit symbols in 32 bit mode.
+ * This may not be needed it things are cleaned up a little.
+ */
+
+
+ .text
+ .globl _C_LABEL(kernel_text)
+ .set _C_LABEL(kernel_text),KERNTEXTOFF
+
+.code32
+
+ .globl start
+start: movw $0x1234,0x472 # warm boot
+
+ /*
+ * Load parameters from stack
+ * (howto, [bootdev], bootinfo, esym, basemem, extmem).
+ */
+ movl 4(%esp),%eax
+ movl %eax,RELOC(boothowto)
+ movl 12(%esp),%eax
+ testl %eax, %eax
+ jz 1f
+ movl (%eax), %ebx /* number of entries */
+ movl $RELOC(bootinfo),%ebp
+ movl %ebp, %edx
+ addl $BOOTINFO_MAXSIZE,%ebp
+ movl %ebx, (%edx)
+ addl $4, %edx
+2:
+ testl %ebx, %ebx
+ jz 1f
+ addl $4, %eax
+ movl (%eax), %ecx /* address of entry */
+ pushl %edi
+ pushl %esi
+ pushl %eax
+
+ movl (%ecx),%eax /* len */
+ movl %edx,%edi
+ addl (%ecx), %edx /* update dest pointer */
+ cmpl %ebp, %edx
+ jg 2f
+ movl %ecx,%esi
+ movl %eax,%ecx
+ rep
+ movsb
+ popl %eax
+ popl %esi
+ popl %edi
+ subl $1, %ebx
+ jmp 2b
+2: /* cleanup for overflow case */
+ popl %eax
+ popl %esi
+ popl %edi
+ movl $RELOC(bootinfo),%ebp
+ movl %ebp, %edx
+ subl %ebx, (%edx) /* correct number of entries */
+1:
+
+ movl 16(%esp),%eax
+ testl %eax,%eax
+ jz 1f
+ addl $KERNBASE_LO,%eax
+1: movl $RELOC(esym),%ebp
+ movl %eax,(%ebp)
+ movl $KERNBASE_HI,4(%ebp)
+
+ movl $RELOC(biosextmem),%ebp
+ movl (%ebp),%eax
+ testl %eax,%eax
+ jnz 1f
+ movl 20(%esp),%eax
+ movl %eax,(%ebp)
+1:
+ movl $RELOC(biosbasemem),%ebp
+ movl (%ebp),%eax
+ testl %eax,%eax
+ jnz 1f
+ movl 24(%esp),%eax
+ movl %eax,(%ebp)
+1:
+
+ /* First, reset the PSL. */
+ pushl $PSL_MBO
+ popfl
+
+ xorl %eax,%eax
+ cpuid
+ movl %eax,RELOC(cpuid_level)
+ movl $RELOC(cpu_vendor),%ebp
+ movl %ebx,(%ebp)
+ movl %edx,4(%ebp)
+ movl %ecx,8(%ebp)
+ movl $0, 12(%ebp)
+
+ movl $1,%eax
+ cpuid
+ movl %eax,RELOC(cpu_id)
+ movl %edx,RELOC(cpu_feature)
+
+ /* Brand ID is bits 0-7 of %ebx */
+ andl $255,%ebx
+ movl %ebx,RELOC(cpu_brand_id)
+
+ /*
+ * Finished with old stack; load new %esp now instead of later so we
+ * can trace this code without having to worry about the trace trap
+ * clobbering the memory test or the zeroing of the bss+bootstrap page
+ * tables.
+ *
+ * The boot program should check:
+ * text+data <= &stack_variable - more_space_for_stack
+ * text+data+bss+pad+space_for_page_tables <= end_of_memory
+ * Oops, the gdt is in the carcass of the boot program so clearing
+ * the rest of memory is still not possible.
+ */
+ movl $RELOC(tmpstk),%esp
+
+/*
+ * Virtual address space of kernel:
+ *
+ * text | data | bss | [syms] | page dir | proc0 kstack | L1 ptp | L2 ptp | L3
+ * 0 1 2 3
+ */
+
+#if L2_SLOT_KERNBASE > 0
+#define TABLE_L2_ENTRIES (2 * (NKL2_KIMG_ENTRIES + 1))
+#else
+#define TABLE_L2_ENTRIES (NKL2_KIMG_ENTRIES + 1)
+#endif
+
+#if L3_SLOT_KERNBASE > 0
+#define TABLE_L3_ENTRIES (2 * NKL3_KIMG_ENTRIES)
+#else
+#define TABLE_L3_ENTRIES NKL3_KIMG_ENTRIES
+#endif
+
+
+#define PROC0_PML4_OFF 0
+#define PROC0_STK_OFF (PROC0_PML4_OFF + NBPG)
+#define PROC0_PTP3_OFF (PROC0_STK_OFF + UPAGES * NBPG)
+#define PROC0_PTP2_OFF (PROC0_PTP3_OFF + NKL4_KIMG_ENTRIES * NBPG)
+#define PROC0_PTP1_OFF (PROC0_PTP2_OFF + TABLE_L3_ENTRIES * NBPG)
+#define TABLESIZE \
+ ((NKL4_KIMG_ENTRIES + TABLE_L3_ENTRIES + TABLE_L2_ENTRIES + 1 + UPAGES) \
+ * NBPG)
+
+#define fillkpt \
+1: movl %eax,(%ebx) ; /* store phys addr */ \
+ movl $0,4(%ebx) ; /* upper 32 bits 0 */ \
+ addl $8,%ebx ; /* next pte/pde */ \
+ addl $NBPG,%eax ; /* next phys page */ \
+ loop 1b ; \
+
+
+ /* Find end of kernel image. */
+ movl $RELOC(end),%edi
+#if (NKSYMS || defined(DDB) || defined(LKM)) && !defined(SYMTAB_SPACE)
+ /* Save the symbols (if loaded). */
+ movl RELOC(esym),%eax
+ testl %eax,%eax
+ jz 1f
+ subl $KERNBASE_LO,%eax /* XXX */
+ movl %eax,%edi
+1:
+#endif
+ /* Clear tables */
+ movl %edi,%esi
+ addl $PGOFSET,%esi
+ andl $~PGOFSET,%esi
+
+ movl %esi,%edi
+ xorl %eax,%eax
+ cld
+ movl $TABLESIZE,%ecx
+ shrl $2,%ecx
+ rep
+ stosl
+
+ leal (PROC0_PTP1_OFF)(%esi), %ebx
+
+ /*
+ * Compute etext - KERNBASE. This can't be > 4G, or we can't deal
+ * with it anyway, since we can't load it in 32 bit mode. So use
+ * the bottom 32 bits.
+ */
+ movl $RELOC(etext),%edx
+ addl $PGOFSET,%edx
+ andl $~PGOFSET,%edx
+
+ /*
+ * Skip the first MB.
+ */
+ movl $(KERNTEXTOFF_LO - KERNBASE_LO),%eax
+ movl %eax,%ecx
+ shrl $(PGSHIFT-3),%ecx /* ((n >> PGSHIFT) << 3) for # pdes */
+ addl %ecx,%ebx
+
+ /* Map kernel text read-only */
+ movl %edx,%ecx
+ subl %eax,%ecx
+ shrl $PGSHIFT,%ecx
+ orl $(PG_V|PG_KR),%eax
+ fillkpt
+
+ /* Map the data, BSS, and bootstrap tables read-write. */
+ leal (PG_V|PG_KW)(%edx),%eax
+ movl $TABLESIZE,%ecx
+ addl %esi,%ecx /* %ecx = &end[TABLESIZE] */
+ subl %edx,%ecx /* %ecx = %ecx - etext */
+ shrl $PGSHIFT,%ecx
+ fillkpt
+
+ /* Map ISA I/O mem (later atdevbase) */
+ movl $(IOM_BEGIN|PG_V|PG_KW/*|PG_N*/),%eax
+ movl $(IOM_SIZE>>PGSHIFT),%ecx
+ fillkpt
+
+ /* Set up level 2 pages */
+ leal (PROC0_PTP2_OFF)(%esi),%ebx
+ leal (PROC0_PTP1_OFF)(%esi),%eax
+ orl $(PG_V|PG_KW), %eax
+ movl $(NKL2_KIMG_ENTRIES+1),%ecx
+ fillkpt
+
+#if L2_SLOT_KERNBASE > 0
+ /* If needed, set up level 2 entries for actual kernel mapping */
+ leal (PROC0_PTP2_OFF+ L2_SLOT_KERNBASE*8)(%esi),%ebx
+ leal (PROC0_PTP1_OFF)(%esi),%eax
+ orl $(PG_V|PG_KW), %eax
+ movl $(NKL2_KIMG_ENTRIES+1),%ecx
+ fillkpt
+#endif
+
+ /* Set up level 3 pages */
+ leal (PROC0_PTP3_OFF)(%esi),%ebx
+ leal (PROC0_PTP2_OFF)(%esi),%eax
+ orl $(PG_V|PG_KW), %eax
+ movl $NKL3_KIMG_ENTRIES,%ecx
+ fillkpt
+
+#if L3_SLOT_KERNBASE > 0
+ /* If needed, set up level 3 entries for actual kernel mapping */
+ leal (PROC0_PTP3_OFF+ L3_SLOT_KERNBASE*8)(%esi),%ebx
+ leal (PROC0_PTP2_OFF)(%esi),%eax
+ orl $(PG_V|PG_KW), %eax
+ movl $NKL3_KIMG_ENTRIES,%ecx
+ fillkpt
+#endif
+
+ /* Set up top level entries for identity mapping */
+ leal (PROC0_PML4_OFF)(%esi),%ebx
+ leal (PROC0_PTP3_OFF)(%esi),%eax
+ orl $(PG_V|PG_KW), %eax
+ movl $NKL4_KIMG_ENTRIES,%ecx
+ fillkpt
+
+ /* Set up top level entries for actual kernel mapping */
+ leal (PROC0_PML4_OFF + L4_SLOT_KERNBASE*8)(%esi),%ebx
+ leal (PROC0_PTP3_OFF)(%esi),%eax
+ orl $(PG_V|PG_KW), %eax
+ movl $NKL4_KIMG_ENTRIES,%ecx
+ fillkpt
+
+ /* Install recursive top level PDE */
+ leal (PROC0_PML4_OFF + PDIR_SLOT_PTE*8)(%esi),%ebx
+ leal (PROC0_PML4_OFF)(%esi),%eax
+ orl $(PG_V|PG_KW),%eax
+ movl %eax,(%ebx)
+ movl $0, 4(%ebx)
+
+
+ /* Save phys. addr of PTD, for libkvm. */
+ movl $RELOC(PTDpaddr),%ebp
+ movl %esi,(%ebp)
+ movl $0,4(%ebp)
+
+ /*
+ * Startup checklist:
+ * 1. Enable PAE (and SSE while here).
+ */
+ movl %cr4,%eax
+ orl $(CR4_PAE|CR4_OSFXSR|CR4_OSXMMEXCPT),%eax
+ movl %eax,%cr4
+
+ /*
+ * 2. Set Long Mode Enable in EFER. Also enable the
+ * syscall extensions.
+ */
+ movl $MSR_EFER,%ecx
+ rdmsr
+ xorl %eax,%eax /* XXX */
+ orl $(EFER_LME|EFER_SCE),%eax
+ wrmsr
+
+ /*
+ * 3. Load %cr3 with pointer to PML4.
+ */
+ movl %esi,%eax
+ movl %eax,%cr3
+
+ /*
+ * 4. Enable paging and the rest of it.
+ */
+ movl %cr0,%eax
+ orl $(CR0_PE|CR0_PG|CR0_NE|CR0_TS|CR0_MP|CR0_WP),%eax
+ movl %eax,%cr0
+ jmp compat
+compat:
+
+ /*
+ * 5.
+ * Not quite done yet, we're now in a compatibility segment,
+ * in legacy mode. We must jump to a long mode segment.
+ * Need to set up a temporary GDT with a long mode segment
+ * in it to do that.
+ */
+
+ movl $RELOC(gdt64),%eax
+ lgdt (%eax)
+ movl $RELOC(farjmp64),%eax
+ ljmp *(%eax)
+
+.code64
+longmode:
+ /*
+ * 6.
+ * Finally, we're in long mode. However, we're still
+ * in the identity mapped area (could not jump out
+ * of that earlier because it would have been a > 32bit
+ * jump). We can do that now, so here we go.
+ */
+ movabsq $longmode_hi,%rax
+ jmp *%rax
+longmode_hi:
+ /*
+ * We have arrived.
+ * There's no need anymore for the identity mapping in low
+ * memory, remove it.
+ */
+ movq $KERNBASE,%r8
+
+#if L2_SLOT_KERNBASE > 0
+ movq $(NKL2_KIMG_ENTRIES+1),%rcx
+ leaq (PROC0_PTP2_OFF)(%rsi),%rbx
+ addq %r8, %rbx
+1: movq $0,(%rbx)
+ addq $8,%rbx
+ loop 1b
+#endif
+
+#if L3_SLOT_KERNBASE > 0
+ movq $NKL3_KIMG_ENTRIES,%rcx
+ leaq (PROC0_PTP3_OFF)(%rsi),%rbx
+ addq %r8, %rbx
+1: movq $0,(%rbx)
+ addq $8,%rbx
+ loop 1b
+#endif
+
+ movq $NKL4_KIMG_ENTRIES,%rcx
+ leaq (PROC0_PML4_OFF)(%rsi),%rbx # old, phys address of PML4
+ addq %r8, %rbx # new, virtual adress of PML4
+1: movq $0,(%rbx)
+ addq $8,%rbx
+ loop 1b
+
+ /* Relocate atdevbase. */
+ movq $(TABLESIZE+KERNBASE),%rdx
+ addq %rsi,%rdx
+ movq %rdx,_C_LABEL(atdevbase)(%rip)
+
+ /* Set up bootstrap stack. */
+ leaq (PROC0_STK_OFF)(%rsi),%rax
+ addq %r8,%rax
+ movq %rax,_C_LABEL(proc0paddr)(%rip)
+ leaq (USPACE-FRAMESIZE)(%rax),%rsp
+ movq %rsi,PCB_CR3(%rax) # pcb->pcb_cr3
+ xorq %rbp,%rbp # mark end of frames
+
+ xorw %ax,%ax
+ movw %ax,%gs
+ movw %ax,%fs
+
+ /* XXX merge these */
+ leaq TABLESIZE(%rsi),%rdi
+ call _C_LABEL(init_x86_64)
+
+ call _C_LABEL(main)
+
+/*****************************************************************************/
+
+/*
+ * Signal trampoline; copied to top of user stack.
+ */
+NENTRY(sigcode)
+ call *%rax
+
+ movq %rsp,%rdi
+ pushq %rdi /* fake return address */
+ movq $SYS_sigreturn,%rax
+ syscall
+ movq $SYS_exit,%rax
+ syscall
+ .globl _C_LABEL(esigcode)
+_C_LABEL(esigcode):
+
+/*
+ * void lgdt(struct region_descriptor *rdp);
+ * Change the global descriptor table.
+ */
+NENTRY(lgdt)
+ /* Reload the descriptor table. */
+ movq %rdi,%rax
+ lgdt (%rax)
+ /* Flush the prefetch q. */
+ jmp 1f
+ nop
+1: /* Reload "stale" selectors. */
+ movl $GSEL(GDATA_SEL, SEL_KPL),%eax
+ movl %eax,%ds
+ movl %eax,%es
+ movl %eax,%ss
+ /* Reload code selector by doing intersegment return. */
+ popq %rax
+ pushq $GSEL(GCODE_SEL, SEL_KPL)
+ pushq %rax
+ lretq
+
+ENTRY(setjmp)
+ /*
+ * Only save registers that must be preserved across function
+ * calls according to the ABI (%rbx, %rsp, %rbp, %r12-%r15)
+ * and %rip.
+ */
+ movq %rdi,%rax
+ movq %rbx,(%rax)
+ movq %rsp,8(%rax)
+ movq %rbp,16(%rax)
+ movq %r12,24(%rax)
+ movq %r13,32(%rax)
+ movq %r14,40(%rax)
+ movq %r15,48(%rax)
+ movq (%rsp),%rdx
+ movq %rdx,56(%rax)
+ xorl %eax,%eax
+ ret
+
+ENTRY(longjmp)
+ movq %rdi,%rax
+ movq (%rax),%rbx
+ movq 8(%rax),%rsp
+ movq 16(%rax),%rbp
+ movq 24(%rax),%r12
+ movq 32(%rax),%r13
+ movq 40(%rax),%r14
+ movq 48(%rax),%r15
+ movq 56(%rax),%rdx
+ movq %rdx,(%rsp)
+ xorl %eax,%eax
+ incl %eax
+ ret
+
+/*****************************************************************************/
+
+/*
+ * The following primitives manipulate the run queues.
+ * _whichqs tells which of the 32 queues _qs
+ * have processes in them. Setrq puts processes into queues, Remrq
+ * removes them from queues. The running process is on no queue,
+ * other processes are on a queue related to p->p_pri, divided by 4
+ * actually to shrink the 0-127 range of priorities into the 32 available
+ * queues.
+ */
+ .globl _C_LABEL(whichqs),_C_LABEL(qs)
+ .globl _C_LABEL(uvmexp),_C_LABEL(panic)
+
+#if NAPM > 0
+ .globl _C_LABEL(apm_cpu_idle),_C_LABEL(apm_cpu_busy)
+#endif
+
+#ifdef DIAGNOSTIC
+NENTRY(switch_error1)
+ movabsq $1f,%rdi
+ call _C_LABEL(panic)
+ /* NOTREACHED */
+1: .asciz "cpu_switch 1"
+NENTRY(switch_error2)
+ movabsq $1f,%rdi
+ call _C_LABEL(panic)
+ /* NOTREACHED */
+1: .asciz "cpu_switch 2"
+NENTRY(switch_error3)
+ movabsq $1f,%rdi
+ call _C_LABEL(panic)
+ /* NOTREACHED */
+1: .asciz "cpu_switch 3"
+#endif /* DIAGNOSTIC */
+
+/*
+ * When no processes are on the runq, cpu_switch() branches to here to wait for
+ * something to come ready.
+ */
+ENTRY(idle)
+#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
+ call _C_LABEL(sched_unlock_idle)
+#endif
+ jmp idle_start
+idle_zero:
+ sti
+ call _C_LABEL(uvm_pageidlezero)
+ jmp idle_start
+idle_loop:
+ /* Try to zero some pages. */
+ movl _C_LABEL(uvm)+UVM_PAGE_IDLE_ZERO(%rip),%ecx
+ testl %ecx,%ecx
+ jnz idle_zero
+ sti
+ hlt
+NENTRY(mpidle)
+idle_start:
+ cli
+ movl _C_LABEL(whichqs)(%rip),%ecx
+ testl %ecx, %ecx
+ jz idle_loop
+#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
+ call _C_LABEL(sched_lock_idle)
+#endif
+ jmp sw1
+
+/*
+ * void cpu_switch(struct proc *)
+ * Find a runnable process and switch to it. Wait if necessary. If the new
+ * proc is the same as the old one, we short-circuit the context save and
+ * restore.
+ */
+ENTRY(cpu_switch)
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ movl CPUVAR(ILEVEL), %ebx
+ pushq %rbx
+
+ movq %rdi,%r13
+
+ /*
+ * Clear curproc so that we don't accumulate system time while idle.
+ * This also insures that schedcpu() will move the old proc to
+ * the correct queue if it happens to get called from the spllower()
+ * below and changes the priority. (See corresponding comment in
+ * userret()).
+ */
+ movq $0, CPUVAR(CURPROC)
+
+ movl $IPL_NONE, %edi
+ call _C_LABEL(Xspllower)
+
+ /*
+ * First phase: find new proc.
+ *
+ * Registers:
+ * %rax - queue head, scratch, then zero
+ * %r8 - queue number
+ * %ecx - cached value of whichqs
+ * %rdx - next process in queue
+ * %r13 - old proc
+ * %r12 - new proc
+ */
+
+switch_search:
+ /* Look for new proc. */
+ cli # splhigh doesn't do a cli
+ movl _C_LABEL(whichqs)(%rip),%ecx
+
+sw1: bsfl %ecx,%r8d # find a full q
+ jz _C_LABEL(idle)
+
+switch_dequeue:
+ movq %r8,%r9
+
+ shlq $4, %r9
+ leaq _C_LABEL(qs)(%rip),%rax
+ addq %r9,%rax
+ /* movq (%rax),%rax */
+
+ movq P_FORW(%rax),%r12 # unlink from front of process q
+#ifdef DIAGNOSTIC
+ cmpq %r12,%rax # linked to self (i.e. nothing queued)?
+ je _C_LABEL(switch_error1) # not possible
+#endif /* DIAGNOSTIC */
+ movq P_FORW(%r12),%rdx
+ movq %rdx,P_FORW(%rax)
+ movq %rax,P_BACK(%rdx)
+
+ cmpq %rdx,%rax # q empty?
+ jne 3f
+
+ btrl %r8d,%ecx # yes, clear to indicate empty
+ movl %ecx,_C_LABEL(whichqs)(%rip) # update q status
+
+3: /* We just did it. */
+ xorq %rax,%rax
+ movl %eax,CPUVAR(RESCHED)
+switch_resume:
+#ifdef DIAGNOSTIC
+ cmpq %rax,P_WCHAN(%r12)
+ jne _C_LABEL(switch_error2)
+ cmpb $SRUN,P_STAT(%r12)
+ jne _C_LABEL(switch_error3)
+#endif
+
+ /* Isolate proc. XXX Is this necessary? */
+ movq %rax,P_BACK(%r12)
+
+ /* Record new proc. */
+#ifdef MULTIPROCESSOR
+ movb $SONPROC,P_STAT(%r12) # l->l_stat = SONPROC
+#endif
+ SET_CURPROC(%r12,%rcx)
+
+ sti
+
+ /* Skip context switch if same proc. */
+ movl $1,%eax
+ cmpq %r12,%r13
+ je switch_return
+
+ /* If old proc exited, don't bother. */
+ testq %r13,%r13
+ jz switch_exited
+
+ /*
+ * Second phase: save old context.
+ *
+ * Registers:
+ * %rax, %rcx - scratch
+ * %r13 - old proc, then old pcb
+ * %r12 - new proc
+ */
+
+ movq P_ADDR(%r13),%r13
+
+ /* Save stack pointers. */
+ movq %rsp,PCB_RSP(%r13)
+ movq %rbp,PCB_RBP(%r13)
+
+switch_exited:
+ /*
+ * Third phase: restore saved context.
+ *
+ * Registers:
+ * %rax, %rcx, %rdx - scratch
+ * %r13 - new pcb
+ * %r12 - new process
+ */
+
+ /* No interrupts while loading new state. */
+ cli
+ movq P_ADDR(%r12),%r13
+
+ /* Restore stack pointers. */
+ movq PCB_RSP(%r13),%rsp
+ movq PCB_RBP(%r13),%rbp
+
+#if 0
+ /* Don't bother with the rest if switching to a system process. */
+ testl $P_SYSTEM,P_FLAG(%r12)
+ jnz switch_restored
+#endif
+
+ /* Load TSS info. */
+#ifdef MULTIPROCESSOR
+ movq CPUVAR(GDT),%rax
+#else
+ movq _C_LABEL(gdtstore)(%rip),%rax
+#endif
+ movl P_MD_TSS_SEL(%r12),%edx
+
+ /* Switch address space. */
+ movq PCB_CR3(%r13),%rcx
+ movq %rcx,%cr3
+
+ /* Switch TSS. Reset "task busy" flag before */
+ andl $~0x0200,4(%rax,%rdx, 1)
+ ltr %dx
+
+ movq PCB_LDT_SEL(%r13),%rcx
+ lldt %cx
+#if 0
+switch_restored:
+#endif
+ /* Restore cr0 (including FPU state). */
+ movl PCB_CR0(%r13),%ecx
+#ifdef MULTIPROCESSOR
+ movq PCB_FPCPU(%r13),%r8
+ cmpq CPUVAR(SELF),%r8
+ jz 1f
+ orl $CR0_TS,%ecx
+1:
+#endif
+ movq %rcx,%cr0
+
+ SET_CURPCB(%r13)
+
+ /* Interrupts are okay again. */
+ sti
+
+switch_return:
+#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
+ call _C_LABEL(sched_unlock_idle)
+#endif
+ /*
+ * Restore old cpl from stack. Note that this is always an increase,
+ * due to the spl0() on entry.
+ */
+ popq %rbx
+ movl %ebx, CPUVAR(ILEVEL)
+
+ popq %r15
+ popq %r14
+ popq %r13
+ popq %r12
+ popq %rbp
+ popq %rbx
+ ret
+
+ENTRY(cpu_switchto)
+ pushq %rbx
+ pushq %rbp
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+
+ movq %rdi,%r13
+ movq %rsi,%r12
+
+ movq $0,CPUVAR(CURPROC)
+
+ xorq %rax,%rax
+ jmp switch_resume
+
+
+/*
+ * void switch_exit(struct proc *l, void (*exit)(struct proc *));
+ * Switch to proc0's saved context and deallocate the address space and kernel
+ * stack for p. Then jump into cpu_switch(), as if we were in proc0 all along.
+ */
+ .globl _C_LABEL(proc0),_C_LABEL(uvmspace_free),_C_LABEL(kernel_map)
+ .globl _C_LABEL(uvm_km_free),_C_LABEL(tss_free)
+ENTRY(switch_exit)
+#ifdef MULTIPROCESSOR
+ movq CPUVAR(IDLE_PCB),%r8
+ movl CPUVAR(IDLE_TSS_SEL),%edx
+#else
+ leaq _C_LABEL(proc0)(%rip),%r9
+ movq P_ADDR(%r9),%r8
+ movl P_MD_TSS_SEL(%r9),%edx
+#endif
+
+ /* In case we fault... */
+ movq $0,CPUVAR(CURPROC)
+
+ cli
+
+ /* Restore stack pointers. */
+ movq PCB_RSP(%r8),%rsp
+ movq PCB_RBP(%r8),%rbp
+
+ /* Load TSS info. */
+#ifdef MULTIPROCESSOR
+ movq CPUVAR(GDT),%rax
+#else
+ movq _C_LABEL(gdtstore)(%rip),%rax
+#endif
+
+ /* Switch address space. */
+ movq PCB_CR3(%r8),%rcx
+ movq %rcx,%cr3
+
+ /* Switch TSS. */
+ andl $~0x0200,4-SEL_KPL(%rax,%rdx,1)
+ ltr %dx
+
+ /* We're always in the kernel, so we don't need the LDT. */
+
+ /* Restore cr0 (including FPU state). */
+ movl PCB_CR0(%r8),%ecx
+ movq %rcx,%cr0
+
+ /* Record new pcb. */
+ SET_CURPCB(%r8)
+
+ /* Interrupts are okay again. */
+ sti
+
+ /*
+ * Schedule the dead process's vmspace and stack to be freed.
+ * {lpw_}exit2(l). Function still in %rsi (2nd arg), proc in
+ * %rdi (first arg).
+ */
+
+ call *%rsi
+
+ /* Jump into cpu_switch() with the right state. */
+ movq %r9, %r13
+ movq $0, CPUVAR(CURPROC)
+ jmp switch_search
+
+/*
+ * savectx(struct pcb *pcb);
+ * Update pcb, saving current processor state.
+ */
+ENTRY(savectx)
+ /* Save stack pointers. */
+ movq %rsp,PCB_RSP(%rdi)
+ movq %rbp,PCB_RBP(%rdi)
+
+ ret
+
+IDTVEC(syscall32)
+ sysret /* go away please */
+
+/*
+ * syscall insn entry. This currently isn't much faster, but
+ * it can be made faster in the future.
+ */
+IDTVEC(syscall)
+ swapgs
+ movq %r15,CPUVAR(SCRATCH)
+ movq CPUVAR(CURPCB),%r15
+ movq PCB_RSP0(%r15),%r15
+ xchgq %r15,%rsp
+ sti
+
+ /*
+ * XXX don't need this whole frame, split of the
+ * syscall frame and trapframe is needed.
+ * First, leave some room for the trapno, error,
+ * ss:rsp, etc, so that all GP registers can be
+ * saved. Then, fill in the rest.
+ */
+ pushq $(LSEL(LUDATA_SEL, SEL_UPL))
+ pushq %r15
+ subq $(TF_RSP-TF_TRAPNO),%rsp
+ movq CPUVAR(SCRATCH),%r15
+ subq $32,%rsp
+ INTR_SAVE_GPRS
+ movw %fs,TF_FS(%rsp)
+ movw %gs,TF_GS(%rsp)
+ movw %es,TF_ES(%rsp)
+ movw $(LSEL(LUDATA_SEL, SEL_UPL)),TF_DS(%rsp)
+ movq %r11, TF_RFLAGS(%rsp) /* old rflags from syscall insn */
+ movq $(LSEL(LUCODE_SEL, SEL_UPL)), TF_CS(%rsp)
+ movq %rcx,TF_RIP(%rsp)
+ movq $2,TF_ERR(%rsp)
+ movq $T_ASTFLT, TF_TRAPNO(%rsp)
+
+ movq CPUVAR(CURPROC),%r14
+ movq %rsp,P_MD_REGS(%r14) # save pointer to frame
+ andl $~MDP_IRET,P_MD_FLAGS(%r14)
+ call *P_MD_SYSCALL(%r14)
+1: /* Check for ASTs on exit to user mode. */
+ cli
+ CHECK_ASTPENDING(%r11)
+ je 2f
+ /* Always returning to user mode here. */
+ CLEAR_ASTPENDING(%r11)
+ sti
+ /* Pushed T_ASTFLT into tf_trapno on entry. */
+ call _C_LABEL(trap)
+ jmp 1b
+2:
+ sti
+ testl $MDP_IRET, P_MD_FLAGS(%r14)
+ jne iret_return;
+syscall_return:
+#ifdef DIAGNOSTIC
+ movl CPUVAR(ILEVEL), %r8d
+ testl %r8d, %r8d
+ jne 3f
+#endif
+ /*
+ * XXX interrupts off longer than they should be here.
+ */
+ cli
+ swapgs
+ movw TF_GS(%rsp),%gs
+ movw TF_FS(%rsp),%fs
+ movw TF_ES(%rsp),%es
+ INTR_RESTORE_GPRS
+ addq $48,%rsp
+ popq %rcx /* return rip */
+ addq $8,%rsp
+ popq %r11 /* flags as set by sysret insn */
+ movq (%rsp),%rsp
+ sysretq
+
+#ifdef DIAGNOSTIC
+3: movabsq $4f, %rdi
+ movl TF_RAX(%rsp),%esi
+ movl TF_RDI(%rsp),%edx
+ movl %ebx,%ecx
+ xorq %rax,%rax
+ call _C_LABEL(printf)
+#ifdef DDB
+ int $3
+#endif /* DDB */
+ movl $IPL_NONE,CPUVAR(ILEVEL)
+ jmp 1b
+4: .asciz "WARNING: SPL NOT LOWERED ON SYSCALL %d %d EXIT %x %x\n"
+#endif
+
+
+NENTRY(proc_trampoline)
+#ifdef MULTIPROCESSOR
+ call _C_LABEL(proc_trampoline_mp)
+#endif
+ movl $IPL_NONE,CPUVAR(ILEVEL)
+ movq %r13,%rdi
+ call *%r12
+ INTRFASTEXIT
+ /* NOTREACHED */
+
+NENTRY(child_trampoline)
+#ifdef MULTIPROCESSOR
+ call _C_LABEL(proc_trampoline_mp)
+#endif
+ movl $IPL_NONE,CPUVAR(ILEVEL)
+ movq %r13,%rdi
+ call *%r12
+ jmp syscall_return
+
+ .globl _C_LABEL(osyscall_return)
+
+/*
+ * Old call gate entry for syscall. XXXfvdl: only needed if we're
+ * going to support running old NetBSD or ibcs2 binaries, etc,
+ * on NetBSD/amd64.
+ */
+IDTVEC(oosyscall)
+ /* Set rflags in trap frame. */
+ pushfq
+ popq 8(%rsp)
+ pushq $7 # size of instruction for restart
+ jmp osyscall1
+
+/*
+ * Trap gate entry for int $80 syscall, also used by sigreturn.
+ */
+IDTVEC(osyscall)
+ pushq $2 # size of instruction for restart
+osyscall1:
+ pushq $T_ASTFLT # trap # for doing ASTs
+ INTRENTRY
+ sti
+ movq CPUVAR(CURPROC),%rdx
+ movq %rsp,P_MD_REGS(%rdx) # save pointer to frame
+ call *P_MD_SYSCALL(%rdx)
+_C_LABEL(osyscall_return):
+2: /* Check for ASTs on exit to user mode. */
+ cli
+ CHECK_ASTPENDING(%r11)
+ je 1f
+ /* Always returning to user mode here. */
+ CLEAR_ASTPENDING(%r11)
+ sti
+ /* Pushed T_ASTFLT into tf_trapno on entry. */
+ call _C_LABEL(trap)
+ jmp 2b
+iret_return:
+#ifndef DIAGNOSTIC
+1: INTRFASTEXIT
+#else /* DIAGNOSTIC */
+1: cmpl $IPL_NONE,CPUVAR(ILEVEL)
+ jne 3f
+ INTRFASTEXIT
+3: sti
+ movabsq $4f, %rdi
+ xorq %rax,%rax
+ call _C_LABEL(printf)
+#ifdef DDB
+ int $3
+#endif /* DDB */
+ movl $IPL_NONE,CPUVAR(ILEVEL)
+ jmp 2b
+4: .asciz "WARNING: SPL NOT LOWERED ON SYSCALL EXIT\n"
+#endif /* DIAGNOSTIC */
diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c
new file mode 100644
index 00000000000..bd4cd513785
--- /dev/null
+++ b/sys/arch/amd64/amd64/machdep.c
@@ -0,0 +1,1874 @@
+/* $OpenBSD: machdep.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1996, 1997, 1998, 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 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.
+ *
+ * @(#)machdep.c 7.4 (Berkeley) 6/3/91
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/signal.h>
+#include <sys/signalvar.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/exec.h>
+#include <sys/buf.h>
+#include <sys/reboot.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/msgbuf.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/extent.h>
+#include <sys/core.h>
+#include <sys/kcore.h>
+#include <sys/syscallargs.h>
+
+#ifdef SYSVMSG
+#include <sys/msg.h>
+#endif
+
+#ifdef KGDB
+#include <sys/kgdb.h>
+#endif
+
+#include <dev/cons.h>
+
+#include <uvm/uvm_extern.h>
+#include <uvm/uvm_page.h>
+
+#include <sys/sysctl.h>
+
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/gdt.h>
+#include <machine/pio.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
+#include <machine/specialreg.h>
+#include <machine/bootinfo.h>
+#include <machine/fpu.h>
+#include <machine/mtrr.h>
+#include <machine/mpbiosvar.h>
+
+#include <dev/isa/isareg.h>
+#include <machine/isa_machdep.h>
+#include <dev/ic/i8042reg.h>
+
+#ifdef DDB
+#include <machine/db_machdep.h>
+#include <ddb/db_extern.h>
+#endif
+
+#include "isa.h"
+#include "isadma.h"
+#include "ksyms.h"
+
+/* the following is used externally (sysctl_hw) */
+char machine[] = "amd64"; /* cpu "architecture" */
+char machine_arch[] = "x86_64"; /* machine == machine_arch */
+
+char bootinfo[BOOTINFO_MAXSIZE];
+
+struct bi_devmatch *x86_64_alldisks = NULL;
+int x86_64_ndisks = 0;
+
+#ifdef CPURESET_DELAY
+int cpureset_delay = CPURESET_DELAY;
+#else
+int cpureset_delay = 2000; /* default to 2s */
+#endif
+
+int physmem;
+u_int64_t dumpmem_low;
+u_int64_t dumpmem_high;
+extern int boothowto;
+int cpu_class;
+
+char *ssym = NULL;
+
+#define CPUID2MODEL(cpuid) (((cpuid) >> 4) & 15)
+
+vaddr_t msgbuf_vaddr;
+paddr_t msgbuf_paddr;
+
+vaddr_t idt_vaddr;
+paddr_t idt_paddr;
+
+vaddr_t lo32_vaddr;
+paddr_t lo32_paddr;
+
+struct vm_map *exec_map = NULL;
+struct vm_map *phys_map = NULL;
+
+#ifdef NBUF
+int nbuf = NUF;
+#else
+int nbuf = 0;
+#endif
+
+#ifndef BUFCACHEPERCENT
+#define BUFCACHEPERCENT 5
+#endif
+
+#ifdef BUFPAGES
+int bufpages = BUFPAGES;
+#else
+int bufpages = 0;
+#endif
+int bufcachepercent = BUFCACHEPERCENT;
+
+#ifdef DEBUG
+int sigdebug = 0;
+pid_t sigpid = 0;
+#define SDB_FOLLOW 0x01
+#endif
+
+extern paddr_t avail_start, avail_end;
+
+void (*delay_func)(int) = i8254_delay;
+void (*microtime_func)(struct timeval *) = i8254_microtime;
+void (*initclock_func)(void) = i8254_initclocks;
+
+struct mtrr_funcs *mtrr_funcs;
+
+/*
+ * Size of memory segments, before any memory is stolen.
+ */
+phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
+int mem_cluster_cnt;
+
+vaddr_t allocsys(vaddr_t);
+void setup_buffers(vaddr_t *);
+int cpu_dump(void);
+int cpu_dumpsize(void);
+u_long cpu_dump_mempagecnt(void);
+void dumpsys(void);
+void init_x86_64(paddr_t);
+void syscall_intern(struct proc *p);
+
+/*
+ * Machine-dependent startup code
+ */
+void
+cpu_startup(void)
+{
+ vaddr_t v;
+ vsize_t sz;
+ int x;
+ vaddr_t minaddr, maxaddr;
+
+ /*
+ * Initialize error message buffer (et end of core).
+ */
+ msgbuf_vaddr = uvm_km_valloc(kernel_map, x86_round_page(MSGBUFSIZE));
+ if (msgbuf_vaddr == 0)
+ panic("failed to valloc msgbuf_vaddr");
+
+ /* msgbuf_paddr was init'd in pmap */
+ for (x = 0; x < btoc(MSGBUFSIZE); x++)
+ pmap_kenter_pa((vaddr_t)msgbuf_vaddr + x * PAGE_SIZE,
+ msgbuf_paddr + x * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE);
+ pmap_update(pmap_kenel());
+
+ initmsgbuf((caddr_t)msgbuf_vaddr, round_page(MSGBUFSIZE));
+
+ printf("%s", version);
+
+ printf("real mem = %u (%uK)\n", ctob(physmem), ctob(physmem)/1024);
+
+ /*
+ * Find out how much space we need, allocate it,
+ * and then give everything true virtual addresses.
+ */
+ sz = allocsys(0);
+ if ((v = uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
+ panic("startup: no room for tables");
+ if (allocsys(v) - v != sz)
+ panic("startup: table size inconsistency");
+
+ /*
+ * Now allocate buffers proper. They are different than the above
+ * in that they usually occupy more virtual memory than physical.
+ */
+ setup_buffers(&maxaddr);
+
+ /*
+ * Allocate a submap for exec arguments. This map effectively
+ * limits the number of processes exec'ing at any time.
+ */
+ minaddr = vm_map_min(kernel_map);
+ exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
+ 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
+
+ /*
+ * Allocate a submap for physio
+ */
+ minaddr = vm_map_min(kernel_map);
+ phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
+ VM_PHYS_SIZE, 0, FALSE, NULL);
+
+ printf("avail mem = %lu (%luK)\n", ptoa(uvmexp.free),
+ ptoa(uvmexp.free)/1024);
+ printf("using %u buffers containing %u bytes (%uK) of memory\n",
+ nbuf, bufpages * PAGE_SIZE, bufpages * PAGE_SIZE / 1024);
+
+ bufinit();
+
+ if (boothowto & RB_CONFIG) {
+#ifdef BOOT_CONFIG
+ user_config();
+#else
+ printf("kernel does not support - c; continuing..\n");
+#endif
+ }
+
+ /* Safe for i/o port / memory space allocation to use malloc now. */
+ x86_bus_space_mallocok();
+}
+
+
+/*
+ * The following defines are for the code in setup_buffers that tries to
+ * ensure that enough ISA DMAable memory is still left after the buffercache
+ * has been allocated.
+ */
+#define CHUNKSZ (3 * 1024 * 1024)
+#define ISADMA_LIMIT (16 * 1024 * 1024) /* XXX wrong place */
+#define ALLOC_PGS(sz, limit, pgs) \
+ uvm_pglistalloc((sz), 0, (limit), PAGE_SIZE, 0, &(pgs), 1, 0)
+#define FREE_PGS(pgs) uvm_pglistfree(&(pgs))
+
+/*
+ * Allocate space for system data structures. We are given
+ * a starting virtual address and we return a final virtual
+ * address; along the way we set each data structure pointer.
+ *
+ * We call allocsys() with 0 to find out how much space we want,
+ * allocate that much and fill it with zeroes, and then call
+ * allocsys() again with the correct base virtual address.
+ */
+vaddr_t
+allocsys(vaddr_t v)
+{
+
+#define valloc(name, type, num) \
+ v = (vaddr_t)(((name) = (type *)v) + (num))
+
+#ifdef SYSVMSG
+ valloc(msgpool, char, msginfo.msgmax);
+ valloc(msgmaps, struct msgmap, msginfo.msgseg);
+ valloc(msghdrs, struct msg, msginfo.msgtql);
+ valloc(msqids, struct msqid_ds, msginfo.msgmni);
+#endif
+
+ /*
+ * Determine how many buffers to allocate. We use 10% of the
+ * first 2MB of memory, and 5% of the rest, with a minimum of 16
+ * buffers. We allocate 1/2 as many swap buffer headers as file
+ * i/o buffers.
+ */
+ if (bufpages == 0) {
+ if (physmem < btoc(2 * 1024 * 1024))
+ bufpages = physmem / 10;
+ else
+ bufpages = (btoc(2 * 1024 * 1024) + physmem) *
+ bufcachepercent / 100;
+ }
+ if (nbuf == 0) {
+ nbuf = bufpages;
+ if (nbuf < 16)
+ nbuf = 16;
+ }
+
+ /* Restrict to at most 35% filled kvm */
+ /* XXX - This needs UBC... */
+ if (nbuf >
+ (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / MAXBSIZE * 35 / 100)
+ nbuf = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
+ MAXBSIZE * 35 / 100;
+
+ /* More buffer pages than fits into the buffers is senseless. */
+ if (bufpages > nbuf * MAXBSIZE / PAGE_SIZE)
+ bufpages = nbuf * MAXBSIZE / PAGE_SIZE;
+
+ valloc(buf, struct buf, nbuf);
+ return v;
+}
+
+void
+setup_buffers(vaddr_t *maxaddr)
+{
+ vsize_t size;
+ vaddr_t addr;
+ int base, residual, left, chunk, i;
+ struct pglist pgs, saved_pgs;
+ struct vm_page *pg;
+ int rv;
+
+ size = MAXBSIZE * nbuf;
+ addr = vm_map_min(kernel_map);
+ if ((rv = uvm_map(kernel_map, &addr, round_page(size),
+ NULL, UVM_UNKNOWN_OFFSET, 0,
+ UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
+ UVM_ADV_NORMAL, 0))))
+ panic("cpu_startup: cannot allocate VM for buffers %d", rv);
+ buffers = (char *)addr;
+
+ base = bufpages / nbuf;
+ residual = bufpages % nbuf;
+ if (base >= MAXBSIZE / PAGE_SIZE) {
+ /* don't want to alloc more physical mem than needed */
+ base = MAXBSIZE / PAGE_SIZE;
+ residual = 0;
+ }
+
+ /*
+ * In case we might need DMA bouncing we have to make sure there
+ * is some memory below 16MB available. On machines with many
+ * pages reserved for the buffer cache we risk filling all of that
+ * area with buffer pages. We still want much of the buffers
+ * reside there as that lowers the probability of them needing to
+ * bounce, but we have to set aside some space for DMA buffers too.
+ *
+ * The current strategy is to grab hold of one 3MB chunk below 16MB
+ * first, which we are saving for DMA buffers, then try to get
+ * one chunk at a time for fs buffers, until that is not possible
+ * anymore, at which point we get the rest wherever we may find it.
+ * After that we give our saved area back. That will guarantee at
+ * least 3MB below 16MB left for drivers' attach routines, among
+ * them isadma. However we still have a potential problem of PCI
+ * devices attached earlier snatching that memory. This can be
+ * solved by making the PCI DMA memory allocation routines go for
+ * memory above 16MB first.
+ */
+
+ left = bufpages;
+
+ /*
+ * First, save ISA DMA bounce buffer area so we won't lose that
+ * capability.
+ */
+ TAILQ_INIT(&saved_pgs);
+ TAILQ_INIT(&pgs);
+ if (!ALLOC_PGS(CHUNKSZ, ISADMA_LIMIT, saved_pgs)) {
+ /*
+ * Then, grab as much ISA DMAable memory as possible
+ * for the buffer cache as it is nice to not need to
+ * bounce all buffer I/O.
+ */
+ for (left = bufpages; left > 0; left -= chunk) {
+ chunk = min(left, CHUNKSZ / PAGE_SIZE);
+ if (ALLOC_PGS(chunk * PAGE_SIZE, ISADMA_LIMIT, pgs))
+ break;
+ }
+ }
+
+ /*
+ * If we need more pages for the buffer cache, get them from anywhere.
+ */
+ if (left > 0 && ALLOC_PGS(left * PAGE_SIZE, avail_end, pgs))
+ panic("cannot get physical memory for buffer cache");
+
+ /*
+ * Finally, give back the ISA DMA bounce buffer area, so it can be
+ * allocated by the isadma driver later.
+ */
+ if (!TAILQ_EMPTY(&saved_pgs))
+ FREE_PGS(saved_pgs);
+
+ pg = TAILQ_FIRST(&pgs);
+ for (i = 0; i < nbuf; i++) {
+ /*
+ * First <residual> buffers get (base+1) physical pages
+ * allocated for them. The rest get (base) physical pages.
+ *
+ * The rest of each buffer occupies virtual space,
+ * but has no physical memory allocated for it.
+ */
+ addr = (vaddr_t)buffers + i * MAXBSIZE;
+ for (size = PAGE_SIZE * (i < residual ? base + 1 : base);
+ size > 0; size -= PAGE_SIZE, addr += PAGE_SIZE) {
+ pmap_kenter_pa(addr, VM_PAGE_TO_PHYS(pg),
+ VM_PROT_READ|VM_PROT_WRITE);
+ pg = TAILQ_NEXT(pg, pageq);
+ }
+ }
+ pmap_update(pmap_kernel());
+}
+
+/*
+ * Set up proc0's TSS and LDT.
+ */
+void
+x86_64_proc0_tss_ldt_init(void)
+{
+ struct pcb *pcb;
+ int x;
+
+ gdt_init();
+
+ cpu_info_primary.ci_curpcb = pcb = &proc0.p_addr->u_pcb;
+
+ pcb->pcb_flags = 0;
+ pcb->pcb_tss.tss_iobase =
+ (u_int16_t)((caddr_t)pcb->pcb_iomap - (caddr_t)&pcb->pcb_tss);
+ for (x = 0; x < sizeof(pcb->pcb_iomap) / 4; x++)
+ pcb->pcb_iomap[x] = 0xffffffff;
+
+ pcb->pcb_ldt_sel = pmap_kernel()->pm_ldt_sel =
+ GSYSSEL(GLDT_SEL, SEL_KPL);
+ pcb->pcb_cr0 = rcr0();
+ pcb->pcb_tss.tss_rsp0 = (u_int64_t)proc0.p_addr + USPACE - 16;
+ pcb->pcb_tss.tss_ist[0] = (u_int64_t)proc0.p_addr + PAGE_SIZE;
+ proc0.p_md.md_regs = (struct trapframe *)pcb->pcb_tss.tss_rsp0 - 1;
+ proc0.p_md.md_tss_sel = tss_alloc(pcb);
+
+ ltr(proc0.p_md.md_tss_sel);
+ lldt(pcb->pcb_ldt_sel);
+}
+
+/*
+ * Set up TSS and LDT for a new PCB.
+ */
+
+void
+x86_64_init_pcb_tss_ldt(ci)
+ struct cpu_info *ci;
+{
+ int x;
+ struct pcb *pcb = ci->ci_idle_pcb;
+
+ pcb->pcb_tss.tss_iobase =
+ (u_int16_t)((caddr_t)pcb->pcb_iomap - (caddr_t)&pcb->pcb_tss);
+ for (x = 0; x < sizeof(pcb->pcb_iomap) / 4; x++)
+ pcb->pcb_iomap[x] = 0xffffffff;
+
+ /* XXXfvdl pmap_kernel not needed */
+ pcb->pcb_ldt_sel = pmap_kernel()->pm_ldt_sel =
+ GSYSSEL(GLDT_SEL, SEL_KPL);
+ pcb->pcb_cr0 = rcr0();
+
+ ci->ci_idle_tss_sel = tss_alloc(pcb);
+}
+
+/*
+ * machine dependent system variables.
+ */
+int
+cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
+ int *name;
+ u_int namelen;
+ void *oldp;
+ size_t *oldlenp;
+ void *newp;
+ size_t newlen;
+ struct proc *p;
+{
+ dev_t consdev;
+ struct btinfo_bootpath *bibp;
+
+ /* all sysctl names at this level are terminal */
+ if (namelen != 1)
+ return (ENOTDIR); /* overloaded */
+
+ switch (name[0]) {
+ case CPU_CONSDEV:
+ if (cn_tab != NULL)
+ consdev = cn_tab->cn_dev;
+ else
+ consdev = NODEV;
+ return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
+ sizeof consdev));
+
+ case CPU_BOOTED_KERNEL:
+ bibp = lookup_bootinfo(BTINFO_BOOTPATH);
+ if(!bibp)
+ return(ENOENT); /* ??? */
+ return (sysctl_rdstring(oldp, oldlenp, newp, bibp->bootpath));
+ case CPU_DISKINFO:
+ if (x86_64_alldisks == NULL)
+ return (ENOENT);
+ return (sysctl_rdstruct(oldp, oldlenp, newp, x86_64_alldisks,
+ sizeof (struct disklist) +
+ (x86_64_ndisks - 1) * sizeof (struct nativedisk_info)));
+ default:
+ return (EOPNOTSUPP);
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * 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.
+ */
+void
+sendsig(sig_t catcher, int sig, int mask, u_long code, int type,
+ union sigval val)
+{
+ struct proc *p = curproc;
+ struct trapframe *tf = p->p_md.md_regs;
+ struct sigacts * psp = p->p_sigacts;
+ struct sigcontext ksc;
+ siginfo_t ksi;
+ register_t sp, scp, sip;
+ u_long sss;
+
+#ifdef DEBUG
+ if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
+ printf("sendsig: %s[%d] sig %d catcher %p\n",
+ p->p_comm, p->p_pid, sig, catcher);
+#endif
+
+ if (p->p_md.md_flags & MDP_USEDFPU)
+ fpusave_proc(p, 1);
+
+ bcopy(tf, &ksc, sizeof(*tf));
+ ksc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
+ ksc.sc_mask = mask;
+
+ /* Allocate space for the signal handler context. */
+ if ((psp->ps_flags & SAS_ALTSTACK) && !ksc.sc_onstack &&
+ (psp->ps_sigonstack & sigmask(sig))) {
+ sp = (register_t)psp->ps_sigstk.ss_sp + psp->ps_sigstk.ss_size;
+ psp->ps_sigstk.ss_flags |= SS_ONSTACK;
+ } else
+ sp = tf->tf_rsp;
+
+ sp &= ~15ULL; /* just in case */
+ sss = (sizeof(ksc) + 15) & ~15;
+ sip = 0;
+ if (psp->ps_siginfo & sigmask(sig)) {
+ sip = sp - ((sizeof(ksi) + 15) & ~15);
+ sss += (sizeof(ksi) + 15) & ~15;
+
+ initsiginfo(&ksi, sig, code, type, val);
+ if (copyout(&ksi, (void *)sip, sizeof(ksi)))
+ sigexit(p, SIGILL);
+ }
+ scp = sp - sss;
+
+ if (copyout(&ksc, (void *)scp, sizeof(ksc)))
+ sigexit(p, SIGILL);
+
+ /*
+ * Build context to run handler in.
+ */
+ tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
+ tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
+ tf->tf_fs = LSEL(LUDATA_SEL, SEL_UPL);
+ tf->tf_gs = LSEL(LUDATA_SEL, SEL_UPL);
+
+ tf->tf_rax = (u_int64_t)catcher;
+ tf->tf_rdi = sig;
+ tf->tf_rsi = sip;
+ tf->tf_rdx = scp;
+
+ tf->tf_rip = (u_int64_t)p->p_sigcode;
+ tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
+ tf->tf_rflags &= ~(PSL_T|PSL_VM|PSL_AC);
+ tf->tf_rsp = sp - sss;
+ tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
+
+#ifdef DEBUG
+ if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
+ printf("sendsig(%d): pc 0x%x, catcher 0x%x\n", p->p_pid,
+ tf->tf_rip, tf->tf_rax);
+#endif
+}
+
+/*
+ * 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
+sys_sigreturn(struct proc *p, void *v, register_t *retval)
+{
+ struct sys_sigreturn_args /* {
+ syscallarg(struct sigcontext *) sigcntxp;
+ } */ *uap = v;
+ struct sigcontext *scp, ksc;
+ struct trapframe *tf = p->p_md.md_regs;
+ int error;
+
+ scp = SCARG(uap, sigcntxp);
+#ifdef DEBUG
+ if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
+ printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
+#endif
+
+ if (copyin((caddr_t)scp, &ksc, sizeof ksc))
+ return (error);
+
+ ksc.sc_trapno = tf->tf_trapno;
+ ksc.sc_err = tf->tf_err;
+ bcopy(&ksc, tf, sizeof(*tf));
+
+ /* Restore signal stack. */
+ if (ksc.sc_onstack)
+ p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
+ else
+ p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
+ p->p_sigmask = ksc.sc_mask & ~sigcantmask;
+
+ return (EJUSTRETURN);
+}
+
+int waittime = -1;
+struct pcb dumppcb;
+
+void
+boot(int howto)
+{
+
+ if (cold) {
+ howto |= RB_HALT;
+ goto haltsys;
+ }
+
+ boothowto = howto;
+ if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
+ waittime = 0;
+
+ if (curproc == NULL)
+ curproc = &proc0; /* XXX */
+ vfs_shutdown();
+ /*
+ * If we've been adjusting the clock, the todr
+ * will be out of synch; adjust it now.
+ */
+ if ((howto & RB_TIMEBAD) == 0) {
+ resettodr();
+ } else {
+ printf("WARNING: not updating battery clock\n");
+ }
+ }
+
+ /* Disable interrupts. */
+ splhigh();
+
+ /* Do a dump if requested. */
+ if (howto & RB_DUMP)
+ dumpsys();
+
+haltsys:
+ doshutdownhooks();
+
+#ifdef MULTIPROCESSOR
+ x86_broadcast_ipi(X86_IPI_HALT);
+#endif
+
+ if (howto & RB_HALT) {
+ if (howto & RB_POWERDOWN) {
+#if NACPI > 0
+ delay(500000);
+ acpi_enter_sleep_state(acpi_softc, ACPI_STATE_S5);
+ printf("WARNING: powerdown failed!\n");
+#endif
+ }
+
+ printf("\n");
+ printf("The operating system has halted.\n");
+ printf("Please press any key to reboot.\n\n");
+ cnpollc(1); /* for proper keyboard command handling */
+ cngetc();
+ cnpollc(0);
+ }
+
+ printf("rebooting...\n");
+ if (cpureset_delay > 0)
+ delay(cpureset_delay * 1000);
+ cpu_reset();
+ for(;;) ;
+ /*NOTREACHED*/
+}
+
+/*
+ * XXXfvdl share dumpcode.
+ */
+
+/*
+ * These variables are needed by /sbin/savecore
+ */
+u_int32_t dumpmag = 0x8fca0101; /* magic number */
+int dumpsize = 0; /* pages */
+long dumplo = 0; /* blocks */
+
+/*
+ * cpu_dump: dump the machine-dependent kernel core dump headers.
+ */
+int
+cpu_dump()
+{
+ int (*dump)(dev_t, daddr_t, caddr_t, size_t);
+ char buf[dbtob(1)];
+ kcore_seg_t *segp;
+
+ dump = bdevsw[major(dumpdev)].d_dump;
+
+ memset(buf, 0, sizeof buf);
+ segp = (kcore_seg_t *)buf;
+
+ /*
+ * Generate a segment header.
+ */
+ CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
+ segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
+
+ return (dump(dumpdev, dumplo, (caddr_t)buf, dbtob(1)));
+}
+
+/*
+ * This is called by main to set dumplo and dumpsize.
+ * Dumps always skip the first PAGE_SIZE of disk space
+ * in case there might be a disk label stored there.
+ * If there is extra space, put dump at the end to
+ * reduce the chance that swapping trashes it.
+ */
+void
+dumpconf()
+{
+ const struct bdevsw *bdev;
+ int nblks, dumpblks; /* size of dump area */
+
+ if (dumpdev == NODEV)
+ goto bad;
+ bdev = &bdevsw[major(dumpdev)];
+
+ if (bdev == NULL)
+ panic("dumpconf: bad dumpdev=0x%x", dumpdev);
+ if (bdev->d_psize == NULL)
+ goto bad;
+ nblks = (*bdev->d_psize)(dumpdev);
+ if (nblks <= ctod(1))
+ goto bad;
+
+ dumpblks = cpu_dumpsize();
+ if (dumpblks < 0)
+ goto bad;
+ dumpblks += ctod(cpu_dump_mempagecnt());
+
+ /* If dump won't fit (incl. room for possible label), punt. */
+ if (dumpblks > (nblks - ctod(1)))
+ goto bad;
+
+ /* Put dump at end of partition */
+ dumplo = nblks - dumpblks;
+
+ /* dumpsize is in page units, and doesn't include headers. */
+ dumpsize = cpu_dump_mempagecnt();
+ return;
+
+ bad:
+ dumpsize = 0;
+}
+
+/*
+ * Doadump comes here after turning off memory management and
+ * getting on the dump stack, either when called above, or by
+ * the auto-restart code.
+ */
+#define BYTES_PER_DUMP PAGE_SIZE /* must be a multiple of pagesize XXX small */
+static vaddr_t dumpspace;
+
+vaddr_t
+reserve_dumppages(vaddr_t p)
+{
+
+ dumpspace = p;
+ return (p + BYTES_PER_DUMP);
+}
+
+void
+dumpsys()
+{
+ u_long totalbytesleft, bytes, i, n, memseg;
+ u_long maddr;
+ int psize;
+ daddr_t blkno;
+ int (*dump)(dev_t, daddr_t, caddr_t, size_t);
+ int error;
+
+ /* Save registers. */
+ savectx(&dumppcb);
+
+ if (dumpdev == NODEV)
+ return;
+
+ /*
+ * For dumps during autoconfiguration,
+ * if dump device has already configured...
+ */
+ if (dumpsize == 0)
+ dumpconf();
+ if (dumplo <= 0 || dumpsize == 0) {
+ printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
+ minor(dumpdev));
+ return;
+ }
+ printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
+ minor(dumpdev), dumplo);
+
+ error = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
+ printf("dump ");
+ if (psize == -1) {
+ printf("area unavailable\n");
+ return;
+ }
+
+ if ((error = cpu_dump()) != 0)
+ goto err;
+
+ totalbytesleft = ptoa(cpu_dump_mempagecnt());
+ blkno = dumplo + cpu_dumpsize();
+ dump = bdevsw[major(dumpdev)].d_dump;
+ error = 0;
+
+ for (memseg = 0; memseg < mem_cluster_cnt; memseg++) {
+ maddr = mem_clusters[memseg].start;
+ bytes = mem_clusters[memseg].size;
+
+ for (i = 0; i < bytes; i += n, totalbytesleft -= n) {
+ /* Print out how many MBs we have left to go. */
+ if ((totalbytesleft % (1024*1024)) == 0)
+ printf("%ld ", totalbytesleft / (1024 * 1024));
+
+ /* Limit size for next transfer. */
+ n = bytes - i;
+ if (n > BYTES_PER_DUMP)
+ n = BYTES_PER_DUMP;
+
+ (void) pmap_map(dumpspace, maddr, maddr + n,
+ VM_PROT_READ);
+
+ error = (*dump)(dumpdev, blkno, (caddr_t)dumpspace, n);
+ if (error)
+ goto err;
+ maddr += n;
+ blkno += btodb(n); /* XXX? */
+
+#if 0 /* XXX this doesn't work. grr. */
+ /* operator aborting dump? */
+ if (sget() != NULL) {
+ error = EINTR;
+ break;
+ }
+#endif
+ }
+ }
+
+ err:
+ switch (error) {
+
+ case ENXIO:
+ printf("device bad\n");
+ break;
+
+ case EFAULT:
+ printf("device not ready\n");
+ break;
+
+ case EINVAL:
+ printf("area improper\n");
+ break;
+
+ case EIO:
+ printf("i/o error\n");
+ break;
+
+ case EINTR:
+ printf("aborted from console\n");
+ break;
+
+ case 0:
+ printf("succeeded\n");
+ break;
+
+ default:
+ printf("error %d\n", error);
+ break;
+ }
+ printf("\n\n");
+ delay(5000000); /* 5 seconds */
+}
+
+/*
+ * Clear registers on exec
+ */
+void
+setregs(struct proc *p, struct exec_package *pack, u_long stack,
+ register_t *retval)
+{
+ struct pcb *pcb = &p->p_addr->u_pcb;
+ struct trapframe *tf;
+
+ /* If we were using the FPU, forget about it. */
+ if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
+ fpusave_proc(p, 0);
+
+#ifdef USER_LDT
+ pmap_ldt_cleanup(p);
+#endif
+
+ syscall_intern(p);
+
+ p->p_md.md_flags &= ~MDP_USEDFPU;
+ pcb->pcb_flags = 0;
+ pcb->pcb_savefpu.fp_fxsave.fx_fcw = __NetBSD_NPXCW__;
+ pcb->pcb_savefpu.fp_fxsave.fx_mxcsr = __INITIAL_MXCSR__;
+ pcb->pcb_savefpu.fp_fxsave.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__;
+
+ tf = p->p_md.md_regs;
+ tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
+ tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
+ tf->tf_fs = LSEL(LUDATA_SEL, SEL_UPL);
+ tf->tf_gs = LSEL(LUDATA_SEL, SEL_UPL);
+ tf->tf_rdi = 0;
+ tf->tf_rsi = 0;
+ tf->tf_rbp = 0;
+ tf->tf_rbx = 0;
+ tf->tf_rdx = 0;
+ tf->tf_rcx = 0;
+ tf->tf_rax = 0;
+ tf->tf_rip = pack->ep_entry;
+ tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
+ tf->tf_rflags = PSL_USERSET;
+ tf->tf_rsp = stack;
+ tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
+
+ retval[1] = 0;
+}
+
+/*
+ * Initialize segments and descriptor tables
+ */
+
+struct gate_descriptor *idt;
+char idt_allocmap[NIDT];
+struct simplelock idt_lock;
+char *ldtstore;
+char *gdtstore;
+extern struct user *proc0paddr;
+
+void
+setgate(gd, func, ist, type, dpl, sel)
+ struct gate_descriptor *gd;
+ void *func;
+ int ist, type, dpl, sel;
+{
+ gd->gd_looffset = (u_int64_t)func & 0xffff;
+ gd->gd_selector = sel;
+ gd->gd_ist = ist;
+ gd->gd_type = type;
+ gd->gd_dpl = dpl;
+ gd->gd_p = 1;
+ gd->gd_hioffset = (u_int64_t)func >> 16;
+ gd->gd_zero = 0;
+ gd->gd_xx1 = 0;
+ gd->gd_xx2 = 0;
+ gd->gd_xx3 = 0;
+}
+
+void
+unsetgate(gd)
+ struct gate_descriptor *gd;
+{
+ memset(gd, 0, sizeof (*gd));
+}
+
+void
+setregion(rd, base, limit)
+ struct region_descriptor *rd;
+ void *base;
+ u_int16_t limit;
+{
+ rd->rd_limit = limit;
+ rd->rd_base = (u_int64_t)base;
+}
+
+/*
+ * Note that the base and limit fields are ignored in long mode.
+ */
+void
+set_mem_segment(sd, base, limit, type, dpl, gran, def32, is64)
+ struct mem_segment_descriptor *sd;
+ void *base;
+ size_t limit;
+ int type, dpl, gran, is64;
+{
+ sd->sd_lolimit = (unsigned)limit;
+ sd->sd_lobase = (unsigned long)base;
+ sd->sd_type = type;
+ sd->sd_dpl = dpl;
+ sd->sd_p = 1;
+ sd->sd_hilimit = (unsigned)limit >> 16;
+ sd->sd_avl = 0;
+ sd->sd_long = is64;
+ sd->sd_def32 = def32;
+ sd->sd_gran = gran;
+ sd->sd_hibase = (unsigned long)base >> 24;
+}
+
+void
+set_sys_segment(sd, base, limit, type, dpl, gran)
+ struct sys_segment_descriptor *sd;
+ void *base;
+ size_t limit;
+ int type, dpl, gran;
+{
+ memset(sd, 0, sizeof *sd);
+ sd->sd_lolimit = (unsigned)limit;
+ sd->sd_lobase = (u_int64_t)base;
+ sd->sd_type = type;
+ sd->sd_dpl = dpl;
+ sd->sd_p = 1;
+ sd->sd_hilimit = (unsigned)limit >> 16;
+ sd->sd_gran = gran;
+ sd->sd_hibase = (u_int64_t)base >> 24;
+}
+
+void cpu_init_idt()
+{
+ struct region_descriptor region;
+
+ setregion(&region, idt, NIDT * sizeof(idt[0]) - 1);
+ lidt(&region);
+}
+
+
+#define IDTVEC(name) __CONCAT(X, name)
+typedef void (vector)(void);
+extern vector IDTVEC(syscall);
+extern vector IDTVEC(syscall32);
+extern vector IDTVEC(osyscall);
+extern vector IDTVEC(oosyscall);
+extern vector *IDTVEC(exceptions)[];
+
+#define KBTOB(x) ((size_t)(x) * 1024UL)
+
+#if 0
+void
+beepme(int pitch, int duration)
+{
+#define IO_TIMER1 0x040
+#define IO_PPI 0x061
+#define TIMER_SEL2 0x80
+#define TIMER_16BIT 0x30
+#define TIMER_SQWAVE 0x06
+#define TIMER_CNTR2 (IO_TIMER1 + 2)
+#define TIMER_MODE (IO_TIMER1 + 3)
+#define TIMER_FREQ 1193182
+#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x))
+
+#define PIT_ENABLETMR2 0x01
+#define PIT_SPKRDATA 0x02
+#define PIT_SPKR (PIT_ENABLETMR2|PIT_SPKRDATA)
+
+#define PITCH 440
+
+ outb(IO_TIMER1 + TIMER_MODE, TIMER_SEL2 | TIMER_16BIT | TIMER_SQWAVE);
+ outb(IO_TIMER1 + TIMER_CNTR2, TIMER_DIV(pitch) % 256);
+ outb(IO_TIMER1 + TIMER_CNTR2, TIMER_DIV(pitch) / 256);
+ outb(IO_PPI, inb(IO_PPI) | PIT_SPKR);
+ delay(duration / 2);
+ outb(IO_PPI, inb(IO_PPI) & ~PIT_SPKR);
+ delay(duration / 2);
+}
+#endif
+
+void
+init_x86_64(first_avail)
+ paddr_t first_avail;
+{
+ extern void consinit(void);
+ extern struct extent *iomem_ex;
+ struct region_descriptor region;
+ struct mem_segment_descriptor *ldt_segp;
+ int x, first16q, ist;
+ u_int64_t seg_start, seg_end;
+ u_int64_t seg_start1, seg_end1;
+#if !defined(REALEXTMEM) && !defined(REALBASEMEM)
+ struct btinfo_memmap *bim;
+ u_int64_t addr, size, io_end;
+#endif
+
+ cpu_init_msrs(&cpu_info_primary);
+
+ proc0.p_addr = proc0paddr;
+ cpu_info_primary.ci_curpcb = &proc0.p_addr->u_pcb;
+
+ x86_bus_space_init();
+
+ consinit(); /* XXX SHOULD NOT BE DONE HERE */
+
+ /*
+ * Initailize PAGE_SIZE-dependent variables.
+ */
+ uvm_setpagesize();
+
+#if 0
+ uvmexp.ncolors = 2;
+#endif
+
+ avail_start = PAGE_SIZE; /* BIOS leaves data in low memory */
+ /* and VM system doesn't work with phys 0 */
+#ifdef MULTIPROCESSOR
+ if (avail_start < MP_TRAMPOLINE + PAGE_SIZE)
+ avail_start = MP_TRAMPOLINE + PAGE_SIZE;
+#endif
+
+ /*
+ * Call pmap initialization to make new kernel address space.
+ * We must do this before loading pages into the VM system.
+ */
+ pmap_bootstrap(VM_MIN_KERNEL_ADDRESS);
+
+ if (avail_start != PAGE_SIZE)
+ pmap_prealloc_lowmem_ptps();
+
+#if !defined(REALBASEMEM) && !defined(REALEXTMEM)
+
+ /*
+ * Check to see if we have a memory map from the BIOS (passed
+ * to us by the boot program.
+ */
+ bim = lookup_bootinfo(BTINFO_MEMMAP);
+ if (bim != NULL && bim->num > 0) {
+#if DEBUG_MEMLOAD
+ printf("BIOS MEMORY MAP (%d ENTRIES):\n", bim->num);
+#endif
+ for (x = 0; x < bim->num; x++) {
+ addr = bim->entry[x].addr;
+ size = bim->entry[x].size;
+#if DEBUG_MEMLOAD
+ printf(" addr 0x%lx size 0x%lx type 0x%x\n",
+ addr, size, bim->entry[x].type);
+#endif
+
+ /*
+ * If the segment is not memory, skip it.
+ */
+ switch (bim->entry[x].type) {
+ case BIM_Memory:
+ case BIM_ACPI:
+ case BIM_NVS:
+ break;
+ default:
+ continue;
+ }
+
+ seg_start = addr;
+ seg_end = addr + size;
+
+ if (seg_end > 0x100000000000ULL) {
+ printf("WARNING: skipping large "
+ "memory map entry: "
+ "0x%lx/0x%lx/0x%x\n",
+ addr, size,
+ bim->entry[x].type);
+ continue;
+ }
+
+ /*
+ * Allocate the physical addresses used by RAM
+ * from the iomem extent map. This is done before
+ * the addresses are page rounded just to make
+ * sure we get them all.
+ */
+ if (seg_start < 0x100000000UL) {
+ if (seg_end > 0x100000000UL)
+ io_end = 0x100000000UL;
+ else
+ io_end = seg_end;
+ if (extent_alloc_region(iomem_ex, seg_start,
+ io_end - seg_start, EX_NOWAIT)) {
+ /* XXX What should we do? */
+ printf("WARNING: CAN'T ALLOCATE "
+ "MEMORY SEGMENT %d "
+ "(0x%lx/0x%lx/0l%x) FROM "
+ "IOMEM EXTENT MAP!\n",
+ x, seg_start, io_end - seg_start,
+ bim->entry[x].type);
+ }
+ }
+
+ /*
+ * If it's not free memory, skip it.
+ */
+ if (bim->entry[x].type != BIM_Memory)
+ continue;
+
+ /* XXX XXX XXX */
+ if (mem_cluster_cnt >= VM_PHYSSEG_MAX)
+ panic("init386: too many memory segments");
+
+ seg_start = round_page(seg_start);
+ seg_end = trunc_page(seg_end);
+
+ if (seg_start == seg_end)
+ continue;
+
+ mem_clusters[mem_cluster_cnt].start = seg_start;
+ mem_clusters[mem_cluster_cnt].size =
+ seg_end - seg_start;
+
+ if (avail_end < seg_end)
+ avail_end = seg_end;
+ physmem += atop(mem_clusters[mem_cluster_cnt].size);
+ mem_cluster_cnt++;
+ }
+ }
+#endif /* ! REALBASEMEM && ! REALEXTMEM */
+
+ /*
+ * If the loop above didn't find any valid segment, fall back to
+ * former code.
+ */
+ if (mem_cluster_cnt == 0) {
+ /*
+ * Allocate the physical addresses used by RAM from the iomem
+ * extent map. This is done before the addresses are
+ * page rounded just to make sure we get them all.
+ */
+ if (extent_alloc_region(iomem_ex, 0, KBTOB(biosbasemem),
+ EX_NOWAIT)) {
+ /* XXX What should we do? */
+ printf("WARNING: CAN'T ALLOCATE BASE MEMORY FROM "
+ "IOMEM EXTENT MAP!\n");
+ }
+ mem_clusters[0].start = 0;
+ mem_clusters[0].size = trunc_page(KBTOB(biosbasemem));
+ physmem += atop(mem_clusters[0].size);
+ if (extent_alloc_region(iomem_ex, IOM_END, KBTOB(biosextmem),
+ EX_NOWAIT)) {
+ /* XXX What should we do? */
+ printf("WARNING: CAN'T ALLOCATE EXTENDED MEMORY FROM "
+ "IOMEM EXTENT MAP!\n");
+ }
+#if NISADMA > 0
+ /*
+ * Some motherboards/BIOSes remap the 384K of RAM that would
+ * normally be covered by the ISA hole to the end of memory
+ * so that it can be used. However, on a 16M system, this
+ * would cause bounce buffers to be allocated and used.
+ * This is not desirable behaviour, as more than 384K of
+ * bounce buffers might be allocated. As a work-around,
+ * we round memory down to the nearest 1M boundary if
+ * we're using any isadma devices and the remapped memory
+ * is what puts us over 16M.
+ */
+ if (biosextmem > (15*1024) && biosextmem < (16*1024)) {
+ char pbuf[9];
+
+ format_bytes(pbuf, sizeof(pbuf),
+ biosextmem - (15*1024));
+ printf("Warning: ignoring %s of remapped memory\n",
+ pbuf);
+ biosextmem = (15*1024);
+ }
+#endif
+ mem_clusters[1].start = IOM_END;
+ mem_clusters[1].size = trunc_page(KBTOB(biosextmem));
+ physmem += atop(mem_clusters[1].size);
+
+ mem_cluster_cnt = 2;
+
+ avail_end = IOM_END + trunc_page(KBTOB(biosextmem));
+ }
+
+ /*
+ * If we have 16M of RAM or less, just put it all on
+ * the default free list. Otherwise, put the first
+ * 16M of RAM on a lower priority free list (so that
+ * all of the ISA DMA'able memory won't be eaten up
+ * first-off).
+ */
+ if (avail_end <= (16 * 1024 * 1024))
+ first16q = VM_FREELIST_DEFAULT;
+ else
+ first16q = VM_FREELIST_FIRST16;
+
+ /* Make sure the end of the space used by the kernel is rounded. */
+ first_avail = round_page(first_avail);
+
+ /*
+ * Now, load the memory clusters (which have already been
+ * rounded and truncated) into the VM system.
+ *
+ * NOTE: WE ASSUME THAT MEMORY STARTS AT 0 AND THAT THE KERNEL
+ * IS LOADED AT IOM_END (1M).
+ */
+ for (x = 0; x < mem_cluster_cnt; x++) {
+ seg_start = mem_clusters[x].start;
+ seg_end = mem_clusters[x].start + mem_clusters[x].size;
+ seg_start1 = 0;
+ seg_end1 = 0;
+
+ if (seg_start > 0xffffffffULL) {
+ printf("skipping %lld bytes of memory above 4GB\n",
+ seg_end - seg_start);
+ continue;
+ }
+ if (seg_end > 0x100000000ULL) {
+ printf("skipping %lld bytes of memory above 4GB\n",
+ seg_end - 0x100000000ULL);
+ seg_end = 0x100000000ULL;
+ }
+
+ /*
+ * Skip memory before our available starting point.
+ */
+ if (seg_end <= avail_start)
+ continue;
+
+ if (avail_start >= seg_start && avail_start < seg_end) {
+ if (seg_start != 0)
+ panic("init_x86_64: memory doesn't start at 0");
+ seg_start = avail_start;
+ if (seg_start == seg_end)
+ continue;
+ }
+
+ /*
+ * If this segment contains the kernel, split it
+ * in two, around the kernel.
+ */
+ if (seg_start <= IOM_END && first_avail <= seg_end) {
+ seg_start1 = first_avail;
+ seg_end1 = seg_end;
+ seg_end = IOM_END;
+ }
+
+ /* First hunk */
+ if (seg_start != seg_end) {
+ if (seg_start <= (16 * 1024 * 1024) &&
+ first16q != VM_FREELIST_DEFAULT) {
+ u_int64_t tmp;
+
+ if (seg_end > (16 * 1024 * 1024))
+ tmp = (16 * 1024 * 1024);
+ else
+ tmp = seg_end;
+#if DEBUG_MEMLOAD
+ printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
+ (unsigned long long)seg_start,
+ (unsigned long long)tmp,
+ atop(seg_start), atop(tmp));
+#endif
+ uvm_page_physload(atop(seg_start),
+ atop(tmp), atop(seg_start),
+ atop(tmp), first16q);
+ seg_start = tmp;
+ }
+
+ if (seg_start != seg_end) {
+#if DEBUG_MEMLOAD
+ printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
+ (unsigned long long)seg_start,
+ (unsigned long long)seg_end,
+ atop(seg_start), atop(seg_end));
+#endif
+ uvm_page_physload(atop(seg_start),
+ atop(seg_end), atop(seg_start),
+ atop(seg_end), VM_FREELIST_DEFAULT);
+ }
+ }
+
+ /* Second hunk */
+ if (seg_start1 != seg_end1) {
+ if (seg_start1 <= (16 * 1024 * 1024) &&
+ first16q != VM_FREELIST_DEFAULT) {
+ u_int64_t tmp;
+
+ if (seg_end1 > (16 * 1024 * 1024))
+ tmp = (16 * 1024 * 1024);
+ else
+ tmp = seg_end1;
+#if DEBUG_MEMLOAD
+ printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
+ (unsigned long long)seg_start1,
+ (unsigned long long)tmp,
+ atop(seg_start1), atop(tmp));
+#endif
+ uvm_page_physload(atop(seg_start1),
+ atop(tmp), atop(seg_start1),
+ atop(tmp), first16q);
+ seg_start1 = tmp;
+ }
+
+ if (seg_start1 != seg_end1) {
+#if DEBUG_MEMLOAD
+ printf("loading 0x%qx-0x%qx (0x%lx-0x%lx)\n",
+ (unsigned long long)seg_start1,
+ (unsigned long long)seg_end1,
+ atop(seg_start1), atop(seg_end1));
+#endif
+ uvm_page_physload(atop(seg_start1),
+ atop(seg_end1), atop(seg_start1),
+ atop(seg_end1), VM_FREELIST_DEFAULT);
+ }
+ }
+ }
+
+ /*
+ * Steal memory for the message buffer (at end of core).
+ */
+ {
+ struct vm_physseg *vps = NULL;
+ psize_t sz = round_page(MSGBUFSIZE);
+ psize_t reqsz = sz;
+
+ for (x = 0; x < vm_nphysseg; x++) {
+ vps = &vm_physmem[x];
+ if (ptoa(vps->avail_end) == avail_end)
+ break;
+ }
+ if (x == vm_nphysseg)
+ panic("init_x86_64: can't find end of memory");
+
+ /* Shrink so it'll fit in the last segment. */
+ if ((vps->avail_end - vps->avail_start) < atop(sz))
+ sz = ptoa(vps->avail_end - vps->avail_start);
+
+ vps->avail_end -= atop(sz);
+ vps->end -= atop(sz);
+ msgbuf_paddr = ptoa(vps->avail_end);
+
+ /* Remove the last segment if it now has no pages. */
+ if (vps->start == vps->end) {
+ for (vm_nphysseg--; x < vm_nphysseg; x++)
+ vm_physmem[x] = vm_physmem[x + 1];
+ }
+
+ /* Now find where the new avail_end is. */
+ for (avail_end = 0, x = 0; x < vm_nphysseg; x++)
+ if (vm_physmem[x].avail_end > avail_end)
+ avail_end = vm_physmem[x].avail_end;
+ avail_end = ptoa(avail_end);
+
+ /* Warn if the message buffer had to be shrunk. */
+ if (sz != reqsz)
+ printf("WARNING: %ld bytes not available for msgbuf "
+ "in last cluster (%ld used)\n", reqsz, sz);
+ }
+
+ /*
+ * XXXfvdl todo: acpi wakeup code.
+ */
+
+ pmap_growkernel(VM_MIN_KERNEL_ADDRESS + 32 * 1024 * 1024);
+
+ pmap_kenter_pa(idt_vaddr, idt_paddr, VM_PROT_READ|VM_PROT_WRITE);
+ pmap_kenter_pa(idt_vaddr + PAGE_SIZE, idt_paddr + PAGE_SIZE,
+ VM_PROT_READ|VM_PROT_WRITE);
+
+ pmap_kenter_pa(lo32_vaddr, lo32_paddr, VM_PROT_READ|VM_PROT_WRITE);
+
+ idt = (struct gate_descriptor *)idt_vaddr;
+ gdtstore = (char *)(idt + NIDT);
+ ldtstore = gdtstore + DYNSEL_START;
+
+ /* make gdt gates and memory segments */
+ set_mem_segment(GDT_ADDR_MEM(gdtstore, GCODE_SEL), 0, 0xfffff, SDT_MEMERA,
+ SEL_KPL, 1, 0, 1);
+
+ set_mem_segment(GDT_ADDR_MEM(gdtstore, GDATA_SEL), 0, 0xfffff, SDT_MEMRWA,
+ SEL_KPL, 1, 0, 1);
+
+ set_sys_segment(GDT_ADDR_SYS(gdtstore, GLDT_SEL), ldtstore, LDT_SIZE - 1,
+ SDT_SYSLDT, SEL_KPL, 0);
+
+ set_mem_segment(GDT_ADDR_MEM(gdtstore, GUCODE_SEL), 0,
+ x86_btop(VM_MAXUSER_ADDRESS) - 1, SDT_MEMERA, SEL_UPL, 1, 0, 1);
+
+ set_mem_segment(GDT_ADDR_MEM(gdtstore, GUDATA_SEL), 0,
+ x86_btop(VM_MAXUSER_ADDRESS) - 1, SDT_MEMRWA, SEL_UPL, 1, 0, 1);
+
+ /* make ldt gates and memory segments */
+ setgate((struct gate_descriptor *)(ldtstore + LSYS5CALLS_SEL),
+ &IDTVEC(oosyscall), 0, SDT_SYS386CGT, SEL_UPL,
+ GSEL(GCODE_SEL, SEL_KPL));
+
+ *(struct mem_segment_descriptor *)(ldtstore + LUCODE_SEL) =
+ *GDT_ADDR_MEM(gdtstore, GUCODE_SEL);
+ *(struct mem_segment_descriptor *)(ldtstore + LUDATA_SEL) =
+ *GDT_ADDR_MEM(gdtstore, GUDATA_SEL);
+
+ /*
+ * 32 bit GDT entries.
+ */
+
+ set_mem_segment(GDT_ADDR_MEM(gdtstore, GUCODE32_SEL), 0,
+ x86_btop(VM_MAXUSER_ADDRESS) - 1, SDT_MEMERA, SEL_UPL, 1, 1, 0);
+
+ set_mem_segment(GDT_ADDR_MEM(gdtstore, GUDATA32_SEL), 0,
+ x86_btop(VM_MAXUSER_ADDRESS) - 1, SDT_MEMRWA, SEL_UPL, 1, 1, 0);
+
+ /*
+ * 32 bit LDT entries.
+ */
+ ldt_segp = (struct mem_segment_descriptor *)(ldtstore + LUCODE32_SEL);
+ set_mem_segment(ldt_segp, 0, x86_btop(VM_MAXUSER_ADDRESS32) - 1,
+ SDT_MEMERA, SEL_UPL, 1, 1, 0);
+ ldt_segp = (struct mem_segment_descriptor *)(ldtstore + LUDATA32_SEL);
+ set_mem_segment(ldt_segp, 0, x86_btop(VM_MAXUSER_ADDRESS32) - 1,
+ SDT_MEMRWA, SEL_UPL, 1, 1, 0);
+
+ /*
+ * Other entries.
+ */
+ memcpy((struct gate_descriptor *)(ldtstore + LSOL26CALLS_SEL),
+ (struct gate_descriptor *)(ldtstore + LSYS5CALLS_SEL),
+ sizeof (struct gate_descriptor));
+ memcpy((struct gate_descriptor *)(ldtstore + LBSDICALLS_SEL),
+ (struct gate_descriptor *)(ldtstore + LSYS5CALLS_SEL),
+ sizeof (struct gate_descriptor));
+
+ /* exceptions */
+ for (x = 0; x < 32; x++) {
+ ist = (x == 8 || x == 3) ? 1 : 0;
+ setgate(&idt[x], IDTVEC(exceptions)[x], ist, SDT_SYS386IGT,
+ (x == 3 || x == 4) ? SEL_UPL : SEL_KPL,
+ GSEL(GCODE_SEL, SEL_KPL));
+ idt_allocmap[x] = 1;
+ }
+
+ /* new-style interrupt gate for syscalls */
+ setgate(&idt[128], &IDTVEC(osyscall), 0, SDT_SYS386IGT, SEL_UPL,
+ GSEL(GCODE_SEL, SEL_KPL));
+ idt_allocmap[128] = 1;
+
+ setregion(&region, gdtstore, DYNSEL_START - 1);
+ lgdt(&region);
+
+ cpu_init_idt();
+
+#ifdef DDB
+ {
+ extern caddr_t esym;
+ struct btinfo_symtab *symtab;
+
+ symtab = lookup_bootinfo(BTINFO_SYMTAB);
+ if (symtab) {
+ ssym = (char *)((vaddr_t)symtab->ssym + KERNBASE);
+ esym = (caddr_t)((vaddr_t)symtab->esym + KERNBASE);
+ }
+
+ db_machine_init();
+ ddb_init();
+ }
+
+ if (boothowto & RB_KDB)
+ Debugger();
+#endif
+#ifdef KGDB
+ kgdb_port_init();
+ if (boothowto & RB_KDB) {
+ kgdb_debug_init = 1;
+ kgdb_connect(1);
+ }
+#endif
+
+ intr_default_setup();
+
+ softintr_init();
+ splraise(IPL_IPI);
+ enable_intr();
+
+ /* Make sure maxproc is sane */
+ if (maxproc > cpu_maxproc())
+ maxproc = cpu_maxproc();
+}
+
+void *
+lookup_bootinfo(type)
+ int type;
+{
+ struct btinfo_common *help;
+ int n = *(int*)bootinfo;
+ help = (struct btinfo_common *)(bootinfo + sizeof(int));
+ while(n--) {
+ if(help->type == type) {
+#if 0
+ if (type == BTINFO_CONSOLE) {
+ struct btinfo_console *consinfo = (struct btinfo_console *)help;
+ snprintf(consinfo->devname, 16, "com");
+ consinfo->speed = 9600;
+ consinfo->addr = 0x3f8;
+ }
+#endif
+ return(help);
+ }
+ help = (struct btinfo_common *)((char*)help + help->len);
+ }
+ return(0);
+}
+
+void
+cpu_reset()
+{
+
+ disable_intr();
+
+ /*
+ * The keyboard controller has 4 random output pins, one of which is
+ * connected to the RESET pin on the CPU in many PCs. We tell the
+ * keyboard controller to pulse this line a couple of times.
+ */
+ outb(IO_KBD + KBCMDP, KBC_PULSE0);
+ delay(100000);
+ outb(IO_KBD + KBCMDP, KBC_PULSE0);
+ delay(100000);
+
+ /*
+ * Try to cause a triple fault and watchdog reset by making the IDT
+ * invalid and causing a fault.
+ */
+ memset((caddr_t)idt, 0, NIDT * sizeof(idt[0]));
+ __asm __volatile("divl %0,%1" : : "q" (0), "a" (0));
+
+#if 0
+ /*
+ * Try to cause a triple fault and watchdog reset by unmapping the
+ * entire address space and doing a TLB flush.
+ */
+ memset((caddr_t)PTD, 0, PAGE_SIZE);
+ tlbflush();
+#endif
+
+ for (;;);
+}
+
+/*
+ * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
+ */
+int
+cpu_dumpsize()
+{
+ int size;
+
+ size = ALIGN(sizeof(kcore_seg_t)) +
+ ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t));
+ if (roundup(size, dbtob(1)) != dbtob(1))
+ return (-1);
+
+ return (1);
+}
+
+/*
+ * cpu_dump_mempagecnt: calculate the size of RAM (in pages) to be dumped.
+ */
+u_long
+cpu_dump_mempagecnt()
+{
+ u_long i, n;
+
+ n = 0;
+ for (i = 0; i < mem_cluster_cnt; i++)
+ n += atop(mem_clusters[i].size);
+ return (n);
+}
+
+#if 0
+extern void i8254_microtime(struct timeval *tv);
+
+/*
+ * XXXXXXX
+ * the simulator's 8254 seems to travel backward in time sometimes?
+ * work around this with this hideous code. Unacceptable for
+ * real hardware, but this is just a patch to stop the weird
+ * effects. SMP unsafe, etc.
+ */
+void
+microtime(struct timeval *tv)
+{
+ static struct timeval mtv;
+
+ i8254_microtime(tv);
+ if (tv->tv_sec <= mtv.tv_sec && tv->tv_usec < mtv.tv_usec) {
+ mtv.tv_usec++;
+ if (mtv.tv_usec > 1000000) {
+ mtv.tv_sec++;
+ mtv.tv_usec = 0;
+ }
+ *tv = mtv;
+ } else
+ mtv = *tv;
+}
+#endif
+
+void
+cpu_initclocks()
+{
+ (*initclock_func)();
+}
+
+#ifdef MULTIPROCESSOR
+void
+need_resched(struct cpu_info *ci)
+{
+ ci->ci_want_resched = 1;
+ if ((ci)->ci_curproc != NULL)
+ aston((ci)->ci_curproc);
+}
+#endif
+
+/*
+ * Allocate an IDT vector slot within the given range.
+ * XXX needs locking to avoid MP allocation races.
+ * XXXfvdl share idt code
+ */
+
+int
+idt_vec_alloc(low, high)
+ int low;
+ int high;
+{
+ int vec;
+
+ simple_lock(&idt_lock);
+ for (vec = low; vec <= high; vec++) {
+ if (idt_allocmap[vec] == 0) {
+ idt_allocmap[vec] = 1;
+ simple_unlock(&idt_lock);
+ return vec;
+ }
+ }
+ simple_unlock(&idt_lock);
+ return 0;
+}
+
+void
+idt_vec_set(vec, function)
+ int vec;
+ void (*function)(void);
+{
+ /*
+ * Vector should be allocated, so no locking needed.
+ */
+ KASSERT(idt_allocmap[vec] == 1);
+ setgate(&idt[vec], function, 0, SDT_SYS386IGT, SEL_KPL,
+ GSEL(GCODE_SEL, SEL_KPL));
+}
+
+void
+idt_vec_free(vec)
+ int vec;
+{
+ simple_lock(&idt_lock);
+ unsetgate(&idt[vec]);
+ idt_allocmap[vec] = 0;
+ simple_unlock(&idt_lock);
+}
+
+/*
+ * Number of processes is limited by number of available GDT slots.
+ */
+int
+cpu_maxproc(void)
+{
+#ifdef USER_LDT
+ return ((MAXGDTSIZ - DYNSEL_START) / 32);
+#else
+ return (MAXGDTSIZ - DYNSEL_START) / 16;
+#endif
+}
+
+#ifdef DIAGNOSTIC
+void
+splassert_check(int wantipl, const char *func)
+{
+ int cpl = curcpu()->ci_ilevel;
+
+ if (cpl < wantipl) {
+ splassert_fail(wantipl, cpl, func);
+ }
+}
+#endif
+
diff --git a/sys/arch/amd64/amd64/mainbus.c b/sys/arch/amd64/amd64/mainbus.c
new file mode 100644
index 00000000000..e4c5e6d32fd
--- /dev/null
+++ b/sys/arch/amd64/amd64/mainbus.c
@@ -0,0 +1,190 @@
+/* $OpenBSD: mainbus.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: mainbus.c,v 1.1 2003/04/26 18:39:29 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. 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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+
+#include <dev/isa/isavar.h>
+#include <dev/pci/pcivar.h>
+
+#include <dev/isa/isareg.h>
+
+#include "pci.h"
+#include "isa.h"
+
+#include <machine/cpuvar.h>
+#include <machine/i82093var.h>
+#include <machine/mpbiosvar.h>
+
+/*
+ * XXXfvdl ACPI
+ */
+
+int mainbus_match(struct device *, void *, void *);
+void mainbus_attach(struct device *, struct device *, void *);
+
+struct cfattach mainbus_ca = {
+ sizeof(struct device), mainbus_match, mainbus_attach
+};
+
+struct cfdriver mainbus_cd = {
+ NULL, "mainbus", DV_DULL
+};
+
+int mainbus_print(void *, const char *);
+
+union mainbus_attach_args {
+ const char *mba_busname; /* first elem of all */
+ struct pcibus_attach_args mba_pba;
+ struct isabus_attach_args mba_iba;
+ struct cpu_attach_args mba_caa;
+ struct apic_attach_args aaa_caa;
+};
+
+/*
+ * This is set when the ISA bus is attached. If it's not set by the
+ * time it's checked below, then mainbus attempts to attach an ISA.
+ */
+int isa_has_been_seen;
+#if NISA > 0
+struct isabus_attach_args mba_iba = {
+ "isa",
+ X86_BUS_SPACE_IO, X86_BUS_SPACE_MEM,
+ NULL,
+};
+#endif
+
+#if defined(MPBIOS) || defined(MPACPI)
+struct mp_bus *mp_busses;
+int mp_nbus;
+struct mp_intr_map *mp_intrs;
+int mp_nintr;
+
+int mp_isa_bus = -1;
+int mp_eisa_bus = -1;
+
+#ifdef MPVERBOSE
+int mp_verbose = 1;
+#else
+int mp_verbose = 0;
+#endif
+#endif
+
+
+/*
+ * Probe for the mainbus; always succeeds.
+ */
+int
+mainbus_match(struct device *parent, void *match, void *aux)
+{
+
+ return 1;
+}
+
+/*
+ * Attach the mainbus.
+ */
+void
+mainbus_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+#if NPCI > 0
+ union mainbus_attach_args mba;
+#endif
+#ifdef MPBIOS
+ int mpbios_present = 0;
+#endif
+
+ printf("\n");
+
+#ifdef MPBIOS
+ mpbios_present = mpbios_probe(self);
+#endif
+
+#if NPCI > 0
+ pci_mode = pci_mode_detect();
+#endif
+
+#ifdef MPBIOS
+ if (mpbios_present)
+ mpbios_scan(self);
+ else
+#endif
+ {
+ struct cpu_attach_args caa;
+
+ memset(&caa, 0, sizeof(caa));
+ caa.caa_name = "cpu";
+ caa.cpu_number = 0;
+ caa.cpu_role = CPU_ROLE_SP;
+ caa.cpu_func = 0;
+
+ config_found(self, &caa, mainbus_print);
+ }
+
+#if NPCI > 0
+ if (pci_mode != 0) {
+ mba.mba_pba.pba_busname = "pci";
+ mba.mba_pba.pba_iot = X86_BUS_SPACE_IO;
+ mba.mba_pba.pba_memt = X86_BUS_SPACE_MEM;
+ mba.mba_pba.pba_dmat = &pci_bus_dma_tag;
+ mba.mba_pba.pba_bus = 0;
+ mba.mba_pba.pba_pc = NULL;
+ config_found(self, &mba.mba_pba, mainbus_print);
+ }
+#endif
+
+#if NISA > 0
+ if (isa_has_been_seen == 0)
+ config_found(self, &mba_iba, mainbus_print);
+#endif
+
+}
+
+int
+mainbus_print(aux, pnp)
+ void *aux;
+ const char *pnp;
+{
+ union mainbus_attach_args *mba = aux;
+
+ if (pnp)
+ printf("%s at %s", mba->mba_busname, pnp);
+ if (strcmp(mba->mba_busname, "pci") == 0)
+ printf(" bus %d", mba->mba_pba.pba_bus);
+ return (UNCONF);
+}
diff --git a/sys/arch/amd64/amd64/mem.c b/sys/arch/amd64/amd64/mem.c
new file mode 100644
index 00000000000..7bb187717c3
--- /dev/null
+++ b/sys/arch/amd64/amd64/mem.c
@@ -0,0 +1,266 @@
+/* $OpenBSD: mem.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * 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.
+ *
+ * @(#)mem.c 8.3 (Berkeley) 1/12/94
+ */
+
+/*
+ * Memory special file
+ */
+
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+#include <sys/ioccom.h>
+#include <sys/malloc.h>
+#include <sys/memrange.h>
+#include <sys/proc.h>
+#include <sys/fcntl.h>
+
+#include <machine/cpu.h>
+#include <machine/conf.h>
+
+#include <uvm/uvm_extern.h>
+
+extern char *vmmap; /* poor name! */
+caddr_t zeropage;
+
+/* open counter for aperture */
+#ifdef APERTURE
+static int ap_open_count = 0;
+extern int allowaperture;
+
+#define VGA_START 0xA0000
+#define BIOS_END 0xFFFFF
+#endif
+
+/*ARGSUSED*/
+int
+mmopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+
+ switch (minor(dev)) {
+ case 0:
+ case 1:
+ case 2:
+ case 12:
+ break;
+#ifdef APERTURE
+ case 4:
+ if (suser(p, 0) != 0 || !allowaperture)
+ return (EPERM);
+
+ /* authorize only one simultaneous open() */
+ if (ap_open_count > 0)
+ return(EPERM);
+ ap_open_count++;
+ break;
+#endif
+ default:
+ return (ENXIO);
+ }
+ return (0);
+}
+
+/*ARGSUSED*/
+int
+mmclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+#ifdef APERTURE
+ if (minor(dev) == 4)
+ ap_open_count--;
+#endif
+ return (0);
+}
+
+/*ARGSUSED*/
+int
+mmrw(dev_t dev, struct uio *uio, int flags)
+{
+ vaddr_t o, v;
+ int c;
+ struct iovec *iov;
+ int error = 0;
+ static int physlock;
+
+ if (minor(dev) == 0) {
+ /* lock against other uses of shared vmmap */
+ while (physlock > 0) {
+ physlock++;
+ error = tsleep((caddr_t)&physlock, PZERO | PCATCH,
+ "mmrw", 0);
+ if (error)
+ return (error);
+ }
+ physlock = 1;
+ }
+ while (uio->uio_resid > 0 && error == 0) {
+ iov = uio->uio_iov;
+ if (iov->iov_len == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ if (uio->uio_iovcnt < 0)
+ panic("mmrw");
+ continue;
+ }
+ switch (minor(dev)) {
+
+/* minor device 0 is physical memory */
+ case 0:
+ v = uio->uio_offset;
+ pmap_enter(pmap_kernel(), (vaddr_t)vmmap,
+ trunc_page(v), uio->uio_rw == UIO_READ ?
+ VM_PROT_READ : VM_PROT_WRITE, PMAP_WIRED);
+ pmap_update(pmap_kernel());
+ o = uio->uio_offset & PGOFSET;
+ c = min(uio->uio_resid, (int)(NBPG - o));
+ error = uiomove((caddr_t)vmmap + o, c, uio);
+ pmap_remove(pmap_kernel(), (vaddr_t)vmmap,
+ (vaddr_t)vmmap + NBPG);
+ pmap_update(pmap_kernel());
+ continue;
+
+/* minor device 1 is kernel memory */
+ case 1:
+ v = uio->uio_offset;
+ c = min(iov->iov_len, MAXPHYS);
+ if (!uvm_kernacc((caddr_t)v, c,
+ uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
+ return (EFAULT);
+ error = uiomove((caddr_t)v, c, uio);
+ continue;
+
+/* minor device 2 is EOF/RATHOLE */
+ case 2:
+ if (uio->uio_rw == UIO_WRITE)
+ uio->uio_resid = 0;
+ return (0);
+
+/* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */
+ case 12:
+ if (uio->uio_rw == UIO_WRITE) {
+ c = iov->iov_len;
+ break;
+ }
+ if (zeropage == NULL) {
+ zeropage = (caddr_t)
+ malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
+ bzero(zeropage, PAGE_SIZE);
+ }
+ c = min(iov->iov_len, PAGE_SIZE);
+ error = uiomove(zeropage, c, uio);
+ continue;
+
+ default:
+ return (ENXIO);
+ }
+ iov->iov_base += c;
+ iov->iov_len -= c;
+ uio->uio_offset += c;
+ uio->uio_resid -= c;
+ }
+ if (minor(dev) == 0) {
+ if (physlock > 1)
+ wakeup((caddr_t)&physlock);
+ physlock = 0;
+ }
+ return (error);
+}
+
+paddr_t
+mmmmap(dev, off, prot)
+ dev_t dev;
+ off_t off;
+ int prot;
+{
+ struct proc *p = curproc; /* XXX */
+
+ switch (minor(dev)) {
+/* minor device 0 is physical memory */
+ case 0:
+ if ((paddr_t)off > (paddr_t)ctob(physmem) && suser(p, 0) != 0)
+ return -1;
+ return btop((paddr_t)off);
+
+#ifdef APERTURE
+/* minor device 4 is aperture driver */
+ case 4:
+ switch (allowaperture) {
+ case 1:
+ /* Allow mapping of the VGA framebuffer & BIOS only */
+ if ((off >= VGA_START && off <= BIOS_END) ||
+ (unsigned)off > (unsigned)ctob(physmem))
+ return btop((paddr_t)off);
+ else
+ return -1;
+ case 2:
+ /* Allow mapping of the whole 1st megabyte
+ for x86emu */
+ if (off <= BIOS_END ||
+ (unsigned)off > (unsigned)ctob(physmem))
+ return btop((paddr_t)off);
+ else
+ return -1;
+ default:
+ return -1;
+ }
+
+#endif
+ default:
+ return -1;
+ }
+}
+
+int
+mmioctl(dev, cmd, data, flags, p)
+ dev_t dev;
+ u_long cmd;
+ caddr_t data;
+ int flags;
+ struct proc *p;
+{
+ return (ENODEV);
+}
+
diff --git a/sys/arch/amd64/amd64/microtime.S b/sys/arch/amd64/amd64/microtime.S
new file mode 100644
index 00000000000..2e64a7e585a
--- /dev/null
+++ b/sys/arch/amd64/amd64/microtime.S
@@ -0,0 +1,111 @@
+/* $OpenBSD: microtime.S,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: microtime.S,v 1.1 2003/04/26 18:39:30 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1993 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+#include <dev/isa/isareg.h>
+#include <dev/ic/i8253reg.h>
+
+#include "assym.h"
+
+#define IRQ_BIT(irq_num) (1 << ((irq_num) & 7))
+#define IRQ_BYTE(irq_num) ((irq_num) >> 3)
+
+ENTRY(i8254_microtime)
+ # clear registers and do whatever we can up front
+ xorl %edx,%edx
+ movl $(TIMER_SEL0|TIMER_LATCH),%eax
+
+ cli # disable interrupts
+
+ # select timer 0 and latch its counter
+ outb %al,$IO_TIMER1+TIMER_MODE
+ inb $IO_ICU1,%al # as close to timer latch as possible
+ movb %al,%ch # %ch is current ICU mask
+
+ # Read counter value into [%al %dl], LSB first
+ inb $IO_TIMER1+TIMER_CNTR0,%al
+ movb %al,%dl # %dl has LSB
+ inb $IO_TIMER1+TIMER_CNTR0,%al # %al has MSB
+
+ # save state of IIR in ICU, and of ipending, for later perusal
+ movb CPUVAR(IPENDING) + IRQ_BYTE(0),%cl
+
+ # save the current value of _time
+ movq _C_LABEL(time)(%rip),%r8 # get time.tv_sec
+ movq (_C_LABEL(time)+8)(%rip),%r9 # and time.tv_usec
+
+ sti # enable interrupts, we're done
+
+ # At this point we've collected all the state we need to
+ # compute the time. First figure out if we've got a pending
+ # interrupt. If the IRQ0 bit is set in ipending we've taken
+ # a clock interrupt without incrementing time, so we bump
+ # time.tv_usec by a tick. Otherwise if the ICU shows a pending
+ # interrupt for IRQ0 we (or the caller) may have blocked an interrupt
+ # with the cli. If the counter is not a very small value (3 as
+ # a heuristic), i.e. in pre-interrupt state, we add a tick to
+ # time.tv_usec
+
+ testb $IRQ_BIT(0),%cl # pending interrupt?
+ jnz 1f # yes, increment count
+
+ testb $IRQ_BIT(0),%ch # hardware interrupt pending?
+ jz 2f # no, continue
+ testb %al,%al # MSB zero?
+ jnz 1f # no, add a tick
+ cmpb $3,%dl # is this small number?
+ jbe 2f # yes, continue
+1: addq _C_LABEL(isa_timer_tick)(%rip),%r9 # add a tick
+
+ # We've corrected for pending interrupts. Now do a table lookup
+ # based on each of the high and low order counter bytes to increment
+ # time.tv_usec
+2: leaq _C_LABEL(isa_timer_msb_table)(%rip),%rsi
+ movw (%rsi,%rax,2),%ax
+ subw (%rsi,%rdx,2),%ax
+ addq %rax,%r9 # add msb increment
+
+ # Normalize the struct timeval. We know the previous increments
+ # will be less than a second, so we'll only need to adjust accordingly
+ cmpq $1000000,%r9 # carry in timeval?
+ jb 3f
+ subq $1000000,%r9 # adjust usec
+ incq %r8 # bump sec
+
+3: movq %r8,(%rdi) # tvp->tv_sec = sec
+ movq %r9,8(%rdi) # tvp->tv_usec = usec
+
+ ret
diff --git a/sys/arch/amd64/amd64/pmap.c b/sys/arch/amd64/amd64/pmap.c
new file mode 100644
index 00000000000..09ac35327c5
--- /dev/null
+++ b/sys/arch/amd64/amd64/pmap.c
@@ -0,0 +1,3835 @@
+/* $OpenBSD: pmap.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: pmap.c,v 1.3 2003/05/08 18:13:13 thorpej Exp $ */
+
+/*
+ *
+ * Copyright (c) 1997 Charles D. Cranor and Washington University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Charles D. Cranor and
+ * Washington University.
+ * 4. 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.
+ */
+
+/*
+ * Copyright 2001 (c) Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Frank van der Linden for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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.
+ */
+
+/*
+ * This is the i386 pmap modified and generalized to support x86-64
+ * as well. The idea is to hide the upper N levels of the page tables
+ * inside pmap_get_ptp, pmap_free_ptp and pmap_growkernel. The rest
+ * is mostly untouched, except that it uses some more generalized
+ * macros and interfaces.
+ *
+ * This pmap has been tested on the i386 as well, and it can be easily
+ * adapted to PAE.
+ *
+ * fvdl@wasabisystems.com 18-Jun-2001
+ */
+
+/*
+ * pmap.c: i386 pmap module rewrite
+ * Chuck Cranor <chuck@ccrc.wustl.edu>
+ * 11-Aug-97
+ *
+ * history of this pmap module: in addition to my own input, i used
+ * the following references for this rewrite of the i386 pmap:
+ *
+ * [1] the NetBSD i386 pmap. this pmap appears to be based on the
+ * BSD hp300 pmap done by Mike Hibler at University of Utah.
+ * it was then ported to the i386 by William Jolitz of UUNET
+ * Technologies, Inc. Then Charles M. Hannum of the NetBSD
+ * project fixed some bugs and provided some speed ups.
+ *
+ * [2] the FreeBSD i386 pmap. this pmap seems to be the
+ * Hibler/Jolitz pmap, as modified for FreeBSD by John S. Dyson
+ * and David Greenman.
+ *
+ * [3] the Mach pmap. this pmap, from CMU, seems to have migrated
+ * between several processors. the VAX version was done by
+ * Avadis Tevanian, Jr., and Michael Wayne Young. the i386
+ * version was done by Lance Berc, Mike Kupfer, Bob Baron,
+ * David Golub, and Richard Draves. the alpha version was
+ * done by Alessandro Forin (CMU/Mach) and Chris Demetriou
+ * (NetBSD/alpha).
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/pool.h>
+#include <sys/user.h>
+#include <sys/kernel.h>
+
+#include <uvm/uvm.h>
+
+#include <machine/atomic.h>
+#include <machine/cpu.h>
+#include <machine/specialreg.h>
+#include <machine/gdt.h>
+
+#include <dev/isa/isareg.h>
+#include <machine/isa_machdep.h>
+
+/*
+ * general info:
+ *
+ * - for an explanation of how the i386 MMU hardware works see
+ * the comments in <machine/pte.h>.
+ *
+ * - for an explanation of the general memory structure used by
+ * this pmap (including the recursive mapping), see the comments
+ * in <machine/pmap.h>.
+ *
+ * this file contains the code for the "pmap module." the module's
+ * job is to manage the hardware's virtual to physical address mappings.
+ * note that there are two levels of mapping in the VM system:
+ *
+ * [1] the upper layer of the VM system uses vm_map's and vm_map_entry's
+ * to map ranges of virtual address space to objects/files. for
+ * example, the vm_map may say: "map VA 0x1000 to 0x22000 read-only
+ * to the file /bin/ls starting at offset zero." note that
+ * the upper layer mapping is not concerned with how individual
+ * vm_pages are mapped.
+ *
+ * [2] the lower layer of the VM system (the pmap) maintains the mappings
+ * from virtual addresses. it is concerned with which vm_page is
+ * mapped where. for example, when you run /bin/ls and start
+ * at page 0x1000 the fault routine may lookup the correct page
+ * of the /bin/ls file and then ask the pmap layer to establish
+ * a mapping for it.
+ *
+ * note that information in the lower layer of the VM system can be
+ * thrown away since it can easily be reconstructed from the info
+ * in the upper layer.
+ *
+ * data structures we use include:
+ *
+ * - struct pmap: describes the address space of one thread
+ * - struct pv_entry: describes one <PMAP,VA> mapping of a PA
+ * - struct pv_head: there is one pv_head per managed page of
+ * physical memory. the pv_head points to a list of pv_entry
+ * structures which describe all the <PMAP,VA> pairs that this
+ * page is mapped in. this is critical for page based operations
+ * such as pmap_page_protect() [change protection on _all_ mappings
+ * of a page]
+ * - pv_page/pv_page_info: pv_entry's are allocated out of pv_page's.
+ * if we run out of pv_entry's we allocate a new pv_page and free
+ * its pv_entrys.
+ * - pmap_remove_record: a list of virtual addresses whose mappings
+ * have been changed. used for TLB flushing.
+ */
+
+/*
+ * memory allocation
+ *
+ * - there are three data structures that we must dynamically allocate:
+ *
+ * [A] new process' page directory page (PDP)
+ * - plan 1: done at pmap_create() we use
+ * uvm_km_alloc(kernel_map, PAGE_SIZE) [fka kmem_alloc] to do this
+ * allocation.
+ *
+ * if we are low in free physical memory then we sleep in
+ * uvm_km_alloc -- in this case this is ok since we are creating
+ * a new pmap and should not be holding any locks.
+ *
+ * if the kernel is totally out of virtual space
+ * (i.e. uvm_km_alloc returns NULL), then we panic.
+ *
+ * XXX: the fork code currently has no way to return an "out of
+ * memory, try again" error code since uvm_fork [fka vm_fork]
+ * is a void function.
+ *
+ * [B] new page tables pages (PTP)
+ * call uvm_pagealloc()
+ * => success: zero page, add to pm_pdir
+ * => failure: we are out of free vm_pages, let pmap_enter()
+ * tell UVM about it.
+ *
+ * note: for kernel PTPs, we start with NKPTP of them. as we map
+ * kernel memory (at uvm_map time) we check to see if we've grown
+ * the kernel pmap. if so, we call the optional function
+ * pmap_growkernel() to grow the kernel PTPs in advance.
+ *
+ * [C] pv_entry structures
+ * - plan 1: try to allocate one off the free list
+ * => success: done!
+ * => failure: no more free pv_entrys on the list
+ * - plan 2: try to allocate a new pv_page to add a chunk of
+ * pv_entrys to the free list
+ * [a] obtain a free, unmapped, VA in kmem_map. either
+ * we have one saved from a previous call, or we allocate
+ * one now using a "vm_map_lock_try" in uvm_map
+ * => success: we have an unmapped VA, continue to [b]
+ * => failure: unable to lock kmem_map or out of VA in it.
+ * move on to plan 3.
+ * [b] allocate a page for the VA
+ * => success: map it in, free the pv_entry's, DONE!
+ * => failure: no free vm_pages, etc.
+ * save VA for later call to [a], go to plan 3.
+ * If we fail, we simply let pmap_enter() tell UVM about it.
+ */
+
+/*
+ * locking
+ *
+ * we have the following locks that we must contend with:
+ *
+ * "normal" locks:
+ *
+ * - pmap_main_lock
+ * this lock is used to prevent deadlock and/or provide mutex
+ * access to the pmap system. most operations lock the pmap
+ * structure first, then they lock the pv_lists (if needed).
+ * however, some operations such as pmap_page_protect lock
+ * the pv_lists and then lock pmaps. in order to prevent a
+ * cycle, we require a mutex lock when locking the pv_lists
+ * first. thus, the "pmap = >pv_list" lockers must gain a
+ * read-lock on pmap_main_lock before locking the pmap. and
+ * the "pv_list => pmap" lockers must gain a write-lock on
+ * pmap_main_lock before locking. since only one thread
+ * can write-lock a lock at a time, this provides mutex.
+ *
+ * "simple" locks:
+ *
+ * - pmap lock (per pmap, part of uvm_object)
+ * this lock protects the fields in the pmap structure including
+ * the non-kernel PDEs in the PDP, and the PTEs. it also locks
+ * in the alternate PTE space (since that is determined by the
+ * entry in the PDP).
+ *
+ * - pvh_lock (per pv_head)
+ * this lock protects the pv_entry list which is chained off the
+ * pv_head structure for a specific managed PA. it is locked
+ * when traversing the list (e.g. adding/removing mappings,
+ * syncing R/M bits, etc.)
+ *
+ * - pvalloc_lock
+ * this lock protects the data structures which are used to manage
+ * the free list of pv_entry structures.
+ *
+ * - pmaps_lock
+ * this lock protects the list of active pmaps (headed by "pmaps").
+ * we lock it when adding or removing pmaps from this list.
+ *
+ * XXX: would be nice to have per-CPU VAs for the above 4
+ */
+
+/*
+ * locking data structures
+ */
+
+vaddr_t ptp_masks[] = PTP_MASK_INITIALIZER;
+int ptp_shifts[] = PTP_SHIFT_INITIALIZER;
+long nkptp[] = NKPTP_INITIALIZER;
+long nkptpmax[] = NKPTPMAX_INITIALIZER;
+long nbpd[] = NBPD_INITIALIZER;
+pd_entry_t *normal_pdes[] = PDES_INITIALIZER;
+pd_entry_t *alternate_pdes[] = APDES_INITIALIZER;
+
+/* int nkpde = NKPTP; */
+
+struct simplelock pvalloc_lock;
+struct simplelock pmaps_lock;
+
+#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
+struct lock pmap_main_lock;
+#define PMAP_MAP_TO_HEAD_LOCK() \
+ (void) spinlockmgr(&pmap_main_lock, LK_SHARED, NULL)
+#define PMAP_MAP_TO_HEAD_UNLOCK() \
+ (void) spinlockmgr(&pmap_main_lock, LK_RELEASE, NULL)
+
+#define PMAP_HEAD_TO_MAP_LOCK() \
+ (void) spinlockmgr(&pmap_main_lock, LK_EXCLUSIVE, NULL)
+#define PMAP_HEAD_TO_MAP_UNLOCK() \
+ (void) spinlockmgr(&pmap_main_lock, LK_RELEASE, NULL)
+
+#else
+
+#define PMAP_MAP_TO_HEAD_LOCK() /* null */
+#define PMAP_MAP_TO_HEAD_UNLOCK() /* null */
+
+#define PMAP_HEAD_TO_MAP_LOCK() /* null */
+#define PMAP_HEAD_TO_MAP_UNLOCK() /* null */
+
+#endif
+
+#define COUNT(x) /* nothing */
+
+/*
+ * TLB Shootdown:
+ *
+ * When a mapping is changed in a pmap, the TLB entry corresponding to
+ * the virtual address must be invalidated on all processors. In order
+ * to accomplish this on systems with multiple processors, messages are
+ * sent from the processor which performs the mapping change to all
+ * processors on which the pmap is active. For other processors, the
+ * ASN generation numbers for that processor is invalidated, so that
+ * the next time the pmap is activated on that processor, a new ASN
+ * will be allocated (which implicitly invalidates all TLB entries).
+ *
+ * Shootdown job queue entries are allocated using a simple special-
+ * purpose allocator for speed.
+ */
+struct pmap_tlb_shootdown_job {
+ TAILQ_ENTRY(pmap_tlb_shootdown_job) pj_list;
+ vaddr_t pj_va; /* virtual address */
+ pmap_t pj_pmap; /* the pmap which maps the address */
+ pt_entry_t pj_pte; /* the PTE bits */
+ struct pmap_tlb_shootdown_job *pj_nextfree;
+};
+
+#define PMAP_TLB_SHOOTDOWN_JOB_ALIGN 64
+union pmap_tlb_shootdown_job_al {
+ struct pmap_tlb_shootdown_job pja_job;
+ char pja_align[PMAP_TLB_SHOOTDOWN_JOB_ALIGN];
+};
+
+struct pmap_tlb_shootdown_q {
+ TAILQ_HEAD(, pmap_tlb_shootdown_job) pq_head;
+ int pq_pte; /* aggregate PTE bits */
+ int pq_count; /* number of pending requests */
+ struct simplelock pq_slock; /* spin lock on queue */
+ int pq_flushg; /* pending flush global */
+ int pq_flushu; /* pending flush user */
+} pmap_tlb_shootdown_q[X86_MAXPROCS];
+
+#define PMAP_TLB_MAXJOBS 16
+
+void pmap_tlb_shootdown_q_drain(struct pmap_tlb_shootdown_q *);
+struct pmap_tlb_shootdown_job *pmap_tlb_shootdown_job_get
+ (struct pmap_tlb_shootdown_q *);
+void pmap_tlb_shootdown_job_put(struct pmap_tlb_shootdown_q *,
+ struct pmap_tlb_shootdown_job *);
+
+struct simplelock pmap_tlb_shootdown_job_lock;
+union pmap_tlb_shootdown_job_al *pj_page, *pj_free;
+
+/*
+ * global data structures
+ */
+
+struct pmap kernel_pmap_store; /* the kernel's pmap (proc0) */
+
+/*
+ * pmap_pg_g: if our processor supports PG_G in the PTE then we
+ * set pmap_pg_g to PG_G (otherwise it is zero).
+ */
+
+int pmap_pg_g = 0;
+
+#ifdef LARGEPAGES
+/*
+ * pmap_largepages: if our processor supports PG_PS and we are
+ * using it, this is set to TRUE.
+ */
+
+int pmap_largepages;
+#endif
+
+/*
+ * i386 physical memory comes in a big contig chunk with a small
+ * hole toward the front of it... the following 4 paddr_t's
+ * (shared with machdep.c) describe the physical address space
+ * of this machine.
+ */
+paddr_t avail_start; /* PA of first available physical page */
+paddr_t avail_end; /* PA of last available physical page */
+
+/*
+ * other data structures
+ */
+
+pt_entry_t protection_codes[8]; /* maps MI prot to i386 prot code */
+boolean_t pmap_initialized = FALSE; /* pmap_init done yet? */
+
+/*
+ * pv_page management structures: locked by pvalloc_lock
+ */
+
+TAILQ_HEAD(pv_pagelist, pv_page);
+struct pv_pagelist pv_freepages; /* list of pv_pages with free entrys */
+struct pv_pagelist pv_unusedpgs; /* list of unused pv_pages */
+unsigned int pv_nfpvents; /* # of free pv entries */
+struct pv_page *pv_initpage; /* bootstrap page from kernel_map */
+vaddr_t pv_cachedva; /* cached VA for later use */
+
+#define PVE_LOWAT (PVE_PER_PVPAGE / 2) /* free pv_entry low water mark */
+#define PVE_HIWAT (PVE_LOWAT + (PVE_PER_PVPAGE * 2))
+ /* high water mark */
+
+/*
+ * linked list of all non-kernel pmaps
+ */
+
+struct pmap_head pmaps;
+
+/*
+ * pool that pmap structures are allocated from
+ */
+
+struct pool pmap_pmap_pool;
+
+
+/*
+ * MULTIPROCESSOR: special VA's/ PTE's are actually allocated inside a
+ * X86_MAXPROCS*NPTECL array of PTE's, to avoid cache line thrashing
+ * due to false sharing.
+ */
+
+#ifdef MULTIPROCESSOR
+#define PTESLEW(pte, id) ((pte)+(id)*NPTECL)
+#define VASLEW(va,id) ((va)+(id)*NPTECL*PAGE_SIZE)
+#else
+#define PTESLEW(pte, id) (pte)
+#define VASLEW(va,id) (va)
+#endif
+
+/*
+ * special VAs and the PTEs that map them
+ */
+pt_entry_t *csrc_pte, *cdst_pte, *zero_pte, *ptp_pte, *early_zero_pte;
+caddr_t csrcp, cdstp, zerop, ptpp, early_zerop;
+
+/*
+ * pool and cache that PDPs are allocated from
+ */
+
+struct pool pmap_pdp_pool;
+struct pool_cache pmap_pdp_cache;
+u_int pmap_pdp_cache_generation;
+
+int pmap_pdp_ctor(void *, void *, int);
+
+caddr_t vmmap; /* XXX: used by mem.c... it should really uvm_map_reserve it */
+
+extern vaddr_t msgbuf_vaddr;
+extern paddr_t msgbuf_paddr;
+
+extern vaddr_t idt_vaddr; /* we allocate IDT early */
+extern paddr_t idt_paddr;
+
+#ifdef _LP64
+extern vaddr_t lo32_vaddr;
+extern vaddr_t lo32_paddr;
+#endif
+
+vaddr_t virtual_avail;
+extern int end;
+
+#if defined(I586_CPU)
+/* stuff to fix the pentium f00f bug */
+extern vaddr_t pentium_idt_vaddr;
+#endif
+
+/*
+ * local prototypes
+ */
+
+static struct pv_entry *pmap_add_pvpage(struct pv_page *, boolean_t);
+static struct pv_entry *pmap_alloc_pv(struct pmap *, int); /* see codes below */
+#define ALLOCPV_NEED 0 /* need PV now */
+#define ALLOCPV_TRY 1 /* just try to allocate, don't steal */
+#define ALLOCPV_NONEED 2 /* don't need PV, just growing cache */
+struct pv_entry *pmap_alloc_pvpage(struct pmap *, int);
+static void pmap_enter_pv(struct pv_head *,
+ struct pv_entry *, struct pmap *, vaddr_t, struct vm_page *);
+static void pmap_free_pv(struct pmap *, struct pv_entry *);
+static void pmap_free_pvs(struct pmap *, struct pv_entry *);
+static void pmap_free_pv_doit(struct pv_entry *);
+void pmap_free_pvpage(void);
+struct vm_page *pmap_get_ptp(struct pmap *, vaddr_t, pd_entry_t **);
+static struct vm_page *pmap_find_ptp(struct pmap *, vaddr_t, paddr_t, int);
+void pmap_free_ptp(struct pmap *, struct vm_page *,
+ vaddr_t, pt_entry_t *, pd_entry_t **, int32_t *);
+static void pmap_freepage(struct pmap *, struct vm_page *, int);
+static boolean_t pmap_is_curpmap(struct pmap *);
+static boolean_t pmap_is_active(struct pmap *, int);
+static void pmap_map_ptes(struct pmap *, pt_entry_t **, pd_entry_t ***);
+static struct pv_entry *pmap_remove_pv(struct pv_head *, struct pmap *, vaddr_t);
+void pmap_do_remove(struct pmap *, vaddr_t, vaddr_t, int);
+boolean_t pmap_remove_pte(struct pmap *, struct vm_page *, pt_entry_t *,
+ vaddr_t, int32_t *, int);
+void pmap_remove_ptes(struct pmap *, struct vm_page *, vaddr_t,
+ vaddr_t, vaddr_t, int32_t *, int);
+#define PMAP_REMOVE_ALL 0 /* remove all mappings */
+#define PMAP_REMOVE_SKIPWIRED 1 /* skip wired mappings */
+
+static vaddr_t pmap_tmpmap_pa(paddr_t);
+static pt_entry_t *pmap_tmpmap_pvepte(struct pv_entry *);
+static void pmap_tmpunmap_pa(void);
+static void pmap_tmpunmap_pvepte(struct pv_entry *);
+static void pmap_unmap_ptes(struct pmap *);
+boolean_t pmap_get_physpage(vaddr_t, int, paddr_t *);
+boolean_t pmap_pdes_valid(vaddr_t, pd_entry_t **, pd_entry_t *);
+void pmap_alloc_level(pd_entry_t **, vaddr_t, int, long *);
+
+/*
+ * p m a p i n l i n e h e l p e r f u n c t i o n s
+ */
+
+/*
+ * pmap_is_curpmap: is this pmap the one currently loaded [in %cr3]?
+ * of course the kernel is always loaded
+ */
+
+__inline static boolean_t
+pmap_is_curpmap(pmap)
+ struct pmap *pmap;
+{
+ return((pmap == pmap_kernel()) ||
+ (pmap->pm_pdirpa == (paddr_t) rcr3()));
+}
+
+/*
+ * pmap_is_active: is this pmap loaded into the specified processor's %cr3?
+ */
+
+__inline static boolean_t
+pmap_is_active(pmap, cpu_id)
+ struct pmap *pmap;
+ int cpu_id;
+{
+
+ return (pmap == pmap_kernel() ||
+ (pmap->pm_cpus & (1U << cpu_id)) != 0);
+}
+
+/*
+ * pmap_tmpmap_pa: map a page in for tmp usage
+ */
+
+__inline static vaddr_t
+pmap_tmpmap_pa(pa)
+ paddr_t pa;
+{
+#ifdef MULTIPROCESSOR
+ int id = cpu_number();
+#endif
+ pt_entry_t *ptpte = PTESLEW(ptp_pte, id);
+ caddr_t ptpva = VASLEW(ptpp, id);
+#if defined(DIAGNOSTIC)
+ if (*ptpte)
+ panic("pmap_tmpmap_pa: ptp_pte in use?");
+#endif
+ *ptpte = PG_V | PG_RW | pa; /* always a new mapping */
+ return((vaddr_t)ptpva);
+}
+
+/*
+ * pmap_tmpunmap_pa: unmap a tmp use page (undoes pmap_tmpmap_pa)
+ */
+
+__inline static void
+pmap_tmpunmap_pa()
+{
+#ifdef MULTIPROCESSOR
+ int id = cpu_number();
+#endif
+ pt_entry_t *ptpte = PTESLEW(ptp_pte, id);
+ caddr_t ptpva = VASLEW(ptpp, id);
+#if defined(DIAGNOSTIC)
+ if (!pmap_valid_entry(*ptp_pte))
+ panic("pmap_tmpunmap_pa: our pte invalid?");
+#endif
+ *ptpte = 0; /* zap! */
+ pmap_update_pg((vaddr_t)ptpva);
+#ifdef MULTIPROCESSOR
+ /*
+ * No need for tlb shootdown here, since ptp_pte is per-CPU.
+ */
+#endif
+}
+
+/*
+ * pmap_tmpmap_pvepte: get a quick mapping of a PTE for a pv_entry
+ *
+ * => do NOT use this on kernel mappings [why? because pv_ptp may be NULL]
+ */
+
+__inline static pt_entry_t *
+pmap_tmpmap_pvepte(pve)
+ struct pv_entry *pve;
+{
+#ifdef DIAGNOSTIC
+ if (pve->pv_pmap == pmap_kernel())
+ panic("pmap_tmpmap_pvepte: attempt to map kernel");
+#endif
+
+ /* is it current pmap? use direct mapping... */
+ if (pmap_is_curpmap(pve->pv_pmap))
+ return(vtopte(pve->pv_va));
+
+ return(((pt_entry_t *)pmap_tmpmap_pa(VM_PAGE_TO_PHYS(pve->pv_ptp)))
+ + ptei((unsigned long)pve->pv_va));
+}
+
+/*
+ * pmap_tmpunmap_pvepte: release a mapping obtained with pmap_tmpmap_pvepte
+ */
+
+__inline static void
+pmap_tmpunmap_pvepte(pve)
+ struct pv_entry *pve;
+{
+ /* was it current pmap? if so, return */
+ if (pmap_is_curpmap(pve->pv_pmap))
+ return;
+
+ pmap_tmpunmap_pa();
+}
+
+__inline static void
+pmap_apte_flush(struct pmap *pmap)
+{
+#if defined(MULTIPROCESSOR)
+ struct pmap_tlb_shootdown_q *pq;
+ struct cpu_info *ci, *self = curcpu();
+ CPU_INFO_ITERATOR cii;
+ int s;
+#endif
+
+ tlbflush(); /* flush TLB on current processor */
+#if defined(MULTIPROCESSOR)
+ /*
+ * Flush the APTE mapping from all other CPUs that
+ * are using the pmap we are using (who's APTE space
+ * is the one we've just modified).
+ *
+ * XXXthorpej -- find a way to defer the IPI.
+ */
+ for (CPU_INFO_FOREACH(cii, ci)) {
+ if (ci == self)
+ continue;
+ if (pmap_is_active(pmap, ci->ci_cpuid)) {
+ pq = &pmap_tlb_shootdown_q[ci->ci_cpuid];
+ s = splipi();
+#ifdef MULTIPROCESSOR
+ __cpu_simple_lock(&pq->pq_slock);
+#endif
+ pq->pq_flushu++;
+#ifdef MULTIPROCESSOR
+ __cpu_simple_unlock(&pq->pq_slock);
+#endif
+ splx(s);
+ x86_send_ipi(ci, X86_IPI_TLB);
+ }
+ }
+#endif
+}
+
+/*
+ * pmap_map_ptes: map a pmap's PTEs into KVM and lock them in
+ *
+ * => we lock enough pmaps to keep things locked in
+ * => must be undone with pmap_unmap_ptes before returning
+ */
+
+__inline static void
+pmap_map_ptes(pmap, ptepp, pdeppp)
+ struct pmap *pmap;
+ pt_entry_t **ptepp;
+ pd_entry_t ***pdeppp;
+{
+ pd_entry_t opde, npde;
+
+ /* the kernel's pmap is always accessible */
+ if (pmap == pmap_kernel()) {
+ *ptepp = PTE_BASE;
+ *pdeppp = normal_pdes;
+ return;
+ }
+
+ /* if curpmap then we are always mapped */
+ if (pmap_is_curpmap(pmap)) {
+ simple_lock(&pmap->pm_lock);
+ *ptepp = PTE_BASE;
+ *pdeppp = normal_pdes;
+ return;
+ }
+
+ /* need to lock both curpmap and pmap: use ordered locking */
+ if ((unsigned long) pmap < (unsigned long) curpcb->pcb_pmap) {
+ simple_lock(&pmap->pm_lock);
+ simple_lock(&curpcb->pcb_pmap->pm_lock);
+ } else {
+ simple_lock(&curpcb->pcb_pmap->pm_lock);
+ simple_lock(&pmap->pm_lock);
+ }
+
+ /* need to load a new alternate pt space into curpmap? */
+ opde = *APDP_PDE;
+ if (!pmap_valid_entry(opde) || (opde & PG_FRAME) != pmap->pm_pdirpa) {
+ npde = (pd_entry_t) (pmap->pm_pdirpa | PG_RW | PG_V);
+ *APDP_PDE = npde;
+ if (pmap_valid_entry(opde))
+ pmap_apte_flush(curpcb->pcb_pmap);
+ }
+ *ptepp = APTE_BASE;
+ *pdeppp = alternate_pdes;
+}
+
+/*
+ * pmap_unmap_ptes: unlock the PTE mapping of "pmap"
+ */
+
+__inline static void
+pmap_unmap_ptes(pmap)
+ struct pmap *pmap;
+{
+ if (pmap == pmap_kernel()) {
+ return;
+ }
+ if (pmap_is_curpmap(pmap)) {
+ simple_unlock(&pmap->pm_lock);
+ } else {
+#if defined(MULTIPROCESSOR)
+ *APDP_PDE = 0;
+ pmap_apte_flush(curpcb->pcb_pmap);
+#endif
+ COUNT(apdp_pde_unmap);
+ simple_unlock(&pmap->pm_lock);
+ simple_unlock(&curpcb->pcb_pmap->pm_lock);
+ }
+}
+
+/*
+ * p m a p k e n t e r f u n c t i o n s
+ *
+ * functions to quickly enter/remove pages from the kernel address
+ * space. pmap_kremove is exported to MI kernel. we make use of
+ * the recursive PTE mappings.
+ */
+
+/*
+ * pmap_kenter_pa: enter a kernel mapping without R/M (pv_entry) tracking
+ *
+ * => no need to lock anything, assume va is already allocated
+ * => should be faster than normal pmap enter function
+ */
+
+void
+pmap_kenter_pa(va, pa, prot)
+ vaddr_t va;
+ paddr_t pa;
+ vm_prot_t prot;
+{
+ pt_entry_t *pte, opte, npte;
+
+ if (va < VM_MIN_KERNEL_ADDRESS)
+ pte = vtopte(va);
+ else
+ pte = kvtopte(va);
+
+ npte = pa | ((prot & VM_PROT_WRITE) ? PG_RW : PG_RO) |
+ PG_V | pmap_pg_g;
+ opte = pmap_pte_set(pte, npte); /* zap! */
+#ifdef LARGEPAGES
+ /* XXX For now... */
+ if (opte & PG_PS)
+ panic("pmap_kenter_pa: PG_PS");
+#endif
+ if (pmap_valid_entry(opte)) {
+#if defined(MULTIPROCESSOR)
+ int32_t cpumask = 0;
+
+ pmap_tlb_shootdown(pmap_kernel(), va, opte, &cpumask);
+ pmap_tlb_shootnow(cpumask);
+#else
+ /* Don't bother deferring in the single CPU case. */
+ pmap_update_pg(va);
+#endif
+ }
+}
+
+/*
+ * pmap_kremove: remove a kernel mapping(s) without R/M (pv_entry) tracking
+ *
+ * => no need to lock anything
+ * => caller must dispose of any vm_page mapped in the va range
+ * => note: not an inline function
+ * => we assume the va is page aligned and the len is a multiple of PAGE_SIZE
+ * => we assume kernel only unmaps valid addresses and thus don't bother
+ * checking the valid bit before doing TLB flushing
+ */
+
+void
+pmap_kremove(va, len)
+ vaddr_t va;
+ vsize_t len;
+{
+ pt_entry_t *pte, opte;
+ int32_t cpumask = 0;
+
+ len >>= PAGE_SHIFT;
+ for ( /* null */ ; len ; len--, va += PAGE_SIZE) {
+ if (va < VM_MIN_KERNEL_ADDRESS)
+ pte = vtopte(va);
+ else
+ pte = kvtopte(va);
+ opte = pmap_pte_set(pte, 0); /* zap! */
+#ifdef LARGEPAGES
+ /* XXX For now... */
+ if (opte & PG_PS)
+ panic("pmap_kremove: PG_PS");
+#endif
+#ifdef DIAGNOSTIC
+ if (opte & PG_PVLIST)
+ panic("pmap_kremove: PG_PVLIST mapping for 0x%lx",
+ va);
+#endif
+ pmap_tlb_shootdown(pmap_kernel(), va, opte, &cpumask);
+ }
+ pmap_tlb_shootnow(cpumask);
+}
+
+/*
+ * p m a p i n i t f u n c t i o n s
+ *
+ * pmap_bootstrap and pmap_init are called during system startup
+ * to init the pmap module. pmap_bootstrap() does a low level
+ * init just to get things rolling. pmap_init() finishes the job.
+ */
+
+/*
+ * pmap_bootstrap: get the system in a state where it can run with VM
+ * properly enabled (called before main()). the VM system is
+ * fully init'd later...
+ *
+ * => on i386, locore.s has already enabled the MMU by allocating
+ * a PDP for the kernel, and nkpde PTP's for the kernel.
+ * => kva_start is the first free virtual address in kernel space
+ */
+
+void
+pmap_bootstrap(kva_start)
+ vaddr_t kva_start;
+{
+ vaddr_t kva, kva_end;
+ struct pmap *kpm;
+ pt_entry_t *pte;
+ int i;
+ unsigned long p1i;
+
+ /*
+ * define the voundaries of the managed kernel virtual address
+ * space.
+ */
+
+ virtual_avail = kva_start; /* first free KVA */
+
+ /*
+ * set up protection_codes: we need to be able to convert from
+ * a MI protection code (some combo of VM_PROT...) to something
+ * we can jam into a i386 PTE.
+ */
+
+ protection_codes[VM_PROT_NONE] = 0; /* --- */
+ protection_codes[VM_PROT_EXECUTE] = PG_RO; /* --x */
+ protection_codes[VM_PROT_READ] = PG_RO; /* -r- */
+ protection_codes[VM_PROT_READ|VM_PROT_EXECUTE] = PG_RO; /* -rx */
+ protection_codes[VM_PROT_WRITE] = PG_RW; /* w-- */
+ protection_codes[VM_PROT_WRITE|VM_PROT_EXECUTE] = PG_RW;/* w-x */
+ protection_codes[VM_PROT_WRITE|VM_PROT_READ] = PG_RW; /* wr- */
+ protection_codes[VM_PROT_ALL] = PG_RW; /* wrx */
+
+ /*
+ * now we init the kernel's pmap
+ *
+ * the kernel pmap's pm_obj is not used for much. however, in
+ * user pmaps the pm_obj contains the list of active PTPs.
+ * the pm_obj currently does not have a pager. it might be possible
+ * to add a pager that would allow a process to read-only mmap its
+ * own page tables (fast user level vtophys?). this may or may not
+ * be useful.
+ */
+
+ kpm = pmap_kernel();
+ for (i = 0; i < PTP_LEVELS - 1; i++) {
+ simple_lock_init(&kpm->pm_obj[i].vmobjlock);
+ kpm->pm_obj[i].pgops = NULL;
+ TAILQ_INIT(&kpm->pm_obj[i].memq);
+ kpm->pm_obj[i].uo_npages = 0;
+ kpm->pm_obj[i].uo_refs = 1;
+ kpm->pm_ptphint[i] = NULL;
+ }
+ memset(&kpm->pm_list, 0, sizeof(kpm->pm_list)); /* pm_list not used */
+ kpm->pm_pdir = (pd_entry_t *)(proc0.p_addr->u_pcb.pcb_cr3 + KERNBASE);
+ kpm->pm_pdirpa = (u_int32_t) proc0.p_addr->u_pcb.pcb_cr3;
+ kpm->pm_stats.wired_count = kpm->pm_stats.resident_count =
+ btop(kva_start - VM_MIN_KERNEL_ADDRESS);
+
+ /*
+ * the above is just a rough estimate and not critical to the proper
+ * operation of the system.
+ */
+
+ curpcb->pcb_pmap = kpm; /* proc0's pcb */
+
+ /*
+ * enable global TLB entries if they are supported
+ */
+
+ if (cpu_feature & CPUID_PGE) {
+ lcr4(rcr4() | CR4_PGE); /* enable hardware (via %cr4) */
+ pmap_pg_g = PG_G; /* enable software */
+
+ /* add PG_G attribute to already mapped kernel pages */
+#if KERNBASE == VM_MIN_KERNEL_ADDRESS
+ for (kva = VM_MIN_KERNEL_ADDRESS ; kva < virtual_avail ;
+#else
+ kva_end = roundup((vaddr_t)&end, PAGE_SIZE);
+ for (kva = KERNBASE; kva < kva_end ;
+#endif
+ kva += PAGE_SIZE) {
+ p1i = pl1_i(kva);
+ if (pmap_valid_entry(PTE_BASE[p1i]))
+ PTE_BASE[p1i] |= PG_G;
+ }
+ }
+
+#if defined(LARGEPAGES) && 0 /* XXX non-functional right now */
+ /*
+ * enable large pages of they are supported.
+ */
+
+ if (cpu_feature & CPUID_PSE) {
+ paddr_t pa;
+ pd_entry_t *pde;
+ extern char _etext;
+
+ lcr4(rcr4() | CR4_PSE); /* enable hardware (via %cr4) */
+ pmap_largepages = 1; /* enable software */
+
+ /*
+ * the TLB must be flushed after enabling large pages
+ * on Pentium CPUs, according to section 3.6.2.2 of
+ * "Intel Architecture Software Developer's Manual,
+ * Volume 3: System Programming".
+ */
+ tlbflush();
+
+ /*
+ * now, remap the kernel text using large pages. we
+ * assume that the linker has properly aligned the
+ * .data segment to a 4MB boundary.
+ */
+ kva_end = roundup((vaddr_t)&_etext, NBPD);
+ for (pa = 0, kva = KERNBASE; kva < kva_end;
+ kva += NBPD, pa += NBPD) {
+ pde = &kpm->pm_pdir[pdei(kva)];
+ *pde = pa | pmap_pg_g | PG_PS |
+ PG_KR | PG_V; /* zap! */
+ tlbflush();
+ }
+ }
+#endif /* LARGEPAGES */
+
+#if VM_MIN_KERNEL_ADDRESS != KERNBASE
+ /*
+ * zero_pte is stuck at the end of mapped space for the kernel
+ * image (disjunct from kva space). This is done so that it
+ * can safely be used in pmap_growkernel (pmap_get_physpage),
+ * when it's called for the first time.
+ * XXXfvdl fix this for MULTIPROCESSOR later.
+ */
+
+ early_zerop = (caddr_t)(KERNBASE + NKL2_KIMG_ENTRIES * NBPD_L2);
+ early_zero_pte = PTE_BASE + pl1_i((unsigned long)early_zerop);
+#endif
+
+ /*
+ * now we allocate the "special" VAs which are used for tmp mappings
+ * by the pmap (and other modules). we allocate the VAs by advancing
+ * virtual_avail (note that there are no pages mapped at these VAs).
+ * we find the PTE that maps the allocated VA via the linear PTE
+ * mapping.
+ */
+
+ pte = PTE_BASE + pl1_i(virtual_avail);
+
+#ifdef MULTIPROCESSOR
+ /*
+ * Waste some VA space to avoid false sharing of cache lines
+ * for page table pages: Give each possible CPU a cache line
+ * of PTE's (8) to play with, though we only need 4. We could
+ * recycle some of this waste by putting the idle stacks here
+ * as well; we could waste less space if we knew the largest
+ * CPU ID beforehand.
+ */
+ csrcp = (caddr_t) virtual_avail; csrc_pte = pte;
+
+ cdstp = (caddr_t) virtual_avail+PAGE_SIZE; cdst_pte = pte+1;
+
+ zerop = (caddr_t) virtual_avail+PAGE_SIZE*2; zero_pte = pte+2;
+
+ ptpp = (caddr_t) virtual_avail+PAGE_SIZE*3; ptp_pte = pte+3;
+
+ virtual_avail += PAGE_SIZE * X86_MAXPROCS * NPTECL;
+ pte += X86_MAXPROCS * NPTECL;
+#else
+ csrcp = (caddr_t) virtual_avail; csrc_pte = pte; /* allocate */
+ virtual_avail += PAGE_SIZE; pte++; /* advance */
+
+ cdstp = (caddr_t) virtual_avail; cdst_pte = pte;
+ virtual_avail += PAGE_SIZE; pte++;
+
+ zerop = (caddr_t) virtual_avail; zero_pte = pte;
+ virtual_avail += PAGE_SIZE; pte++;
+
+ ptpp = (caddr_t) virtual_avail; ptp_pte = pte;
+ virtual_avail += PAGE_SIZE; pte++;
+#endif
+
+#if VM_MIN_KERNEL_ADDRESS == KERNBASE
+ early_zerop = zerop;
+ early_zero_pte = zero_pte;
+#endif
+
+ pte = (void *)0xdeadbeef;
+
+ /* XXX: vmmap used by mem.c... should be uvm_map_reserve */
+ /* XXXfvdl PTEs not needed here */
+ vmmap = (char *)virtual_avail; /* don't need pte */
+ virtual_avail += PAGE_SIZE; pte++;
+
+ msgbuf_vaddr = virtual_avail; /* don't need pte */
+ virtual_avail += round_page(MSGBUFSIZE);
+ pte += x86_btop(round_page(MSGBUFSIZE));
+
+ idt_vaddr = virtual_avail; /* don't need pte */
+ virtual_avail += 2 * PAGE_SIZE; pte += 2;
+ idt_paddr = avail_start; /* steal a page */
+ avail_start += 2 * PAGE_SIZE;
+
+#if defined(I586_CPU)
+ /* pentium f00f bug stuff */
+ pentium_idt_vaddr = virtual_avail; /* don't need pte */
+ virtual_avail += PAGE_SIZE; pte++;
+#endif
+
+#ifdef _LP64
+ /*
+ * Grab a page below 4G for things that need it (i.e.
+ * having an initial %cr3 for the MP trampoline).
+ */
+ lo32_vaddr = virtual_avail;
+ virtual_avail += PAGE_SIZE; pte++;
+ lo32_paddr = avail_start;
+ avail_start += PAGE_SIZE;
+#endif
+
+ /*
+ * now we reserve some VM for mapping pages when doing a crash dump
+ */
+
+ virtual_avail = reserve_dumppages(virtual_avail);
+
+ /*
+ * init the static-global locks and global lists.
+ */
+
+#if defined(MULTIPROCESSOR) || defined(LOCKDEBUG)
+ spinlockinit(&pmap_main_lock, "pmaplk", 0);
+#endif
+ simple_lock_init(&pvalloc_lock);
+ simple_lock_init(&pmaps_lock);
+ LIST_INIT(&pmaps);
+ TAILQ_INIT(&pv_freepages);
+ TAILQ_INIT(&pv_unusedpgs);
+
+ /*
+ * initialize the pmap pool.
+ */
+
+ pool_init(&pmap_pmap_pool, sizeof(struct pmap), 0, 0, 0, "pmappl",
+ &pool_allocator_nointr);
+
+ /*
+ * Initialize the TLB shootdown queues.
+ */
+
+ simple_lock_init(&pmap_tlb_shootdown_job_lock);
+
+ for (i = 0; i < X86_MAXPROCS; i++) {
+ TAILQ_INIT(&pmap_tlb_shootdown_q[i].pq_head);
+ simple_lock_init(&pmap_tlb_shootdown_q[i].pq_slock);
+ }
+
+ /*
+ * initialize the PDE pool and cache.
+ */
+
+ pool_init(&pmap_pdp_pool, PAGE_SIZE, 0, 0, 0, "pdppl",
+ &pool_allocator_nointr);
+ pool_cache_init(&pmap_pdp_cache, &pmap_pdp_pool,
+ pmap_pdp_ctor, NULL, NULL);
+
+ /*
+ * ensure the TLB is sync'd with reality by flushing it...
+ */
+
+ tlbflush();
+}
+
+/*
+ * Pre-allocate PTPs for low memory, so that 1:1 mappings for various
+ * trampoline code can be entered.
+ */
+void
+pmap_prealloc_lowmem_ptps(void)
+{
+ pd_entry_t *pdes;
+ int level;
+ paddr_t newp;
+
+ pdes = pmap_kernel()->pm_pdir;
+ level = PTP_LEVELS;
+ for (;;) {
+ newp = avail_start;
+ avail_start += PAGE_SIZE;
+ *early_zero_pte = (newp & PG_FRAME) | PG_V | PG_RW;
+ pmap_update_pg((vaddr_t)early_zerop);
+ memset(early_zerop, 0, PAGE_SIZE);
+ pdes[pl_i(0, level)] = (newp & PG_FRAME) | PG_V | PG_RW;
+ level--;
+ if (level <= 1)
+ break;
+ pdes = normal_pdes[level - 2];
+ }
+}
+
+/*
+ * pmap_init: called from uvm_init, our job is to get the pmap
+ * system ready to manage mappings... this mainly means initing
+ * the pv_entry stuff.
+ */
+
+void
+pmap_init()
+{
+ int lcv;
+ unsigned int npages, i;
+ vaddr_t addr;
+ vsize_t s;
+
+ /*
+ * compute the number of pages we have and then allocate RAM
+ * for each pages' pv_head and saved attributes.
+ */
+
+ npages = 0;
+ for (lcv = 0 ; lcv < vm_nphysseg ; lcv++)
+ npages += (vm_physmem[lcv].end - vm_physmem[lcv].start);
+ s = (vsize_t) (sizeof(struct pv_head) * npages +
+ sizeof(char) * npages);
+ s = round_page(s);
+ addr = (vaddr_t) uvm_km_zalloc(kernel_map, s);
+ if (addr == 0)
+ panic("pmap_init: unable to allocate pv_heads");
+
+ /*
+ * init all pv_head's and attrs in one memset
+ */
+
+ /* allocate pv_head stuff first */
+ for (lcv = 0 ; lcv < vm_nphysseg ; lcv++) {
+ vm_physmem[lcv].pmseg.pvhead = (struct pv_head *) addr;
+ addr = (vaddr_t)(vm_physmem[lcv].pmseg.pvhead +
+ (vm_physmem[lcv].end - vm_physmem[lcv].start));
+ for (i = 0;
+ i < (vm_physmem[lcv].end - vm_physmem[lcv].start); i++) {
+ simple_lock_init(
+ &vm_physmem[lcv].pmseg.pvhead[i].pvh_lock);
+ }
+ }
+
+ /* now allocate attrs */
+ for (lcv = 0 ; lcv < vm_nphysseg ; lcv++) {
+ vm_physmem[lcv].pmseg.attrs = (unsigned char *)addr;
+ addr = (vaddr_t)(vm_physmem[lcv].pmseg.attrs +
+ (vm_physmem[lcv].end - vm_physmem[lcv].start));
+ }
+
+#ifdef LOCKDEBUG
+ /*
+ * Now, initialize all the pv_head locks.
+ * We only do this if LOCKDEBUG because we know that initialized locks
+ * are always all-zero if !LOCKDEBUG.
+ */
+ for (lcv = 0; lcv < vm_nphysseg ; lcv++) {
+ int off, npages;
+ struct pmap_physseg *pmsegp;
+
+ npages = vm_physmem[lcv].end - vm_physmem[lcv].start;
+ pmsegp = &vm_physmem[lcv].pmseg;
+
+ for (off = 0; off <npages; off++)
+ simple_lock_init(&pmsegp->pvhead[off].pvh_lock);
+
+ }
+#endif
+
+ /*
+ * now we need to free enough pv_entry structures to allow us to get
+ * the kmem_map allocated and inited (done after this
+ * function is finished). to do this we allocate one bootstrap page out
+ * of kernel_map and use it to provide an initial pool of pv_entry
+ * structures. we never free this page.
+ */
+
+ pv_initpage = (struct pv_page *) uvm_km_alloc(kernel_map, PAGE_SIZE);
+ if (pv_initpage == NULL)
+ panic("pmap_init: pv_initpage");
+ pv_cachedva = 0; /* a VA we have allocated but not used yet */
+ pv_nfpvents = 0;
+ (void) pmap_add_pvpage(pv_initpage, FALSE);
+
+ pj_page = (void *)uvm_km_alloc(kernel_map, PAGE_SIZE);
+ if (pj_page == NULL)
+ panic("pmap_init: pj_page");
+
+ for (i = 0;
+ i < (PAGE_SIZE / sizeof (union pmap_tlb_shootdown_job_al) - 1);
+ i++)
+ pj_page[i].pja_job.pj_nextfree = &pj_page[i + 1].pja_job;
+ pj_page[i].pja_job.pj_nextfree = NULL;
+ pj_free = &pj_page[0];
+
+ /*
+ * done: pmap module is up (and ready for business)
+ */
+
+ pmap_initialized = TRUE;
+}
+
+/*
+ * p v _ e n t r y f u n c t i o n s
+ */
+
+/*
+ * pv_entry allocation functions:
+ * the main pv_entry allocation functions are:
+ * pmap_alloc_pv: allocate a pv_entry structure
+ * pmap_free_pv: free one pv_entry
+ * pmap_free_pvs: free a list of pv_entrys
+ *
+ * the rest are helper functions
+ */
+
+/*
+ * pmap_alloc_pv: inline function to allocate a pv_entry structure
+ * => we lock pvalloc_lock
+ * => if we fail, we call out to pmap_alloc_pvpage
+ * => 3 modes:
+ * ALLOCPV_NEED = we really need a pv_entry, even if we have to steal it
+ * ALLOCPV_TRY = we want a pv_entry, but not enough to steal
+ * ALLOCPV_NONEED = we are trying to grow our free list, don't really need
+ * one now
+ *
+ * "try" is for optional functions like pmap_copy().
+ */
+
+__inline static struct pv_entry *
+pmap_alloc_pv(pmap, mode)
+ struct pmap *pmap;
+ int mode;
+{
+ struct pv_page *pvpage;
+ struct pv_entry *pv;
+
+ simple_lock(&pvalloc_lock);
+
+ pvpage = TAILQ_FIRST(&pv_freepages);
+ if (pvpage != NULL) {
+ pvpage->pvinfo.pvpi_nfree--;
+ if (pvpage->pvinfo.pvpi_nfree == 0) {
+ /* nothing left in this one? */
+ TAILQ_REMOVE(&pv_freepages, pvpage, pvinfo.pvpi_list);
+ }
+ pv = pvpage->pvinfo.pvpi_pvfree;
+ KASSERT(pv);
+ pvpage->pvinfo.pvpi_pvfree = pv->pv_next;
+ pv_nfpvents--; /* took one from pool */
+ } else {
+ pv = NULL; /* need more of them */
+ }
+
+ /*
+ * if below low water mark or we didn't get a pv_entry we try and
+ * create more pv_entrys ...
+ */
+
+ if (pv_nfpvents < PVE_LOWAT || pv == NULL) {
+ if (pv == NULL)
+ pv = pmap_alloc_pvpage(pmap, (mode == ALLOCPV_TRY) ?
+ mode : ALLOCPV_NEED);
+ else
+ (void) pmap_alloc_pvpage(pmap, ALLOCPV_NONEED);
+ }
+
+ simple_unlock(&pvalloc_lock);
+ return(pv);
+}
+
+/*
+ * pmap_alloc_pvpage: maybe allocate a new pvpage
+ *
+ * if need_entry is false: try and allocate a new pv_page
+ * if need_entry is true: try and allocate a new pv_page and return a
+ * new pv_entry from it. if we are unable to allocate a pv_page
+ * we make a last ditch effort to steal a pv_page from some other
+ * mapping. if that fails, we panic...
+ *
+ * => we assume that the caller holds pvalloc_lock
+ */
+
+struct pv_entry *
+pmap_alloc_pvpage(pmap, mode)
+ struct pmap *pmap;
+ int mode;
+{
+ struct vm_page *pg;
+ struct pv_page *pvpage;
+ struct pv_entry *pv;
+ int s;
+
+ /*
+ * if we need_entry and we've got unused pv_pages, allocate from there
+ */
+
+ pvpage = TAILQ_FIRST(&pv_unusedpgs);
+ if (mode != ALLOCPV_NONEED && pvpage != NULL) {
+
+ /* move it to pv_freepages list */
+ TAILQ_REMOVE(&pv_unusedpgs, pvpage, pvinfo.pvpi_list);
+ TAILQ_INSERT_HEAD(&pv_freepages, pvpage, pvinfo.pvpi_list);
+
+ /* allocate a pv_entry */
+ pvpage->pvinfo.pvpi_nfree--; /* can't go to zero */
+ pv = pvpage->pvinfo.pvpi_pvfree;
+ KASSERT(pv);
+ pvpage->pvinfo.pvpi_pvfree = pv->pv_next;
+ pv_nfpvents--; /* took one from pool */
+ return(pv);
+ }
+
+ /*
+ * see if we've got a cached unmapped VA that we can map a page in.
+ * if not, try to allocate one.
+ */
+
+ s = splvm(); /* must protect kmem_map with splvm! */
+ if (pv_cachedva == 0) {
+ pv_cachedva = uvm_km_kmemalloc(kmem_map, uvmexp.kmem_object,
+ PAGE_SIZE, UVM_KMF_TRYLOCK|UVM_KMF_VALLOC);
+ if (pv_cachedva == 0) {
+ splx(s);
+ return (NULL);
+ }
+ }
+
+ /*
+ * we have a VA, now let's try and allocate a page.
+ */
+ if (!simple_lock_try(&uvmexp.kmem_object->vmobjlock)) {
+ splx(s);
+ return (NULL);
+ }
+
+ pg = uvm_pagealloc(uvmexp.kmem_object, pv_cachedva -
+ vm_map_min(kernel_map), NULL, UVM_PGA_USERESERVE);
+ if (pg)
+ pg->flags &= ~PG_BUSY; /* never busy */
+
+ simple_unlock(&uvmexp.kmem_object->vmobjlock);
+ splx(s);
+
+ if (pg == NULL)
+ return (NULL);
+
+ /*
+ * add a mapping for our new pv_page and free its entrys (save one!)
+ *
+ * NOTE: If we are allocating a PV page for the kernel pmap, the
+ * pmap is already locked! (...but entering the mapping is safe...)
+ */
+
+ pmap_kenter_pa(pv_cachedva, VM_PAGE_TO_PHYS(pg),
+ VM_PROT_READ | VM_PROT_WRITE);
+ pmap_update(pmap_kernel());
+ pvpage = (struct pv_page *) pv_cachedva;
+ pv_cachedva = 0;
+ return (pmap_add_pvpage(pvpage, mode != ALLOCPV_NONEED));
+}
+
+/*
+ * pmap_add_pvpage: add a pv_page's pv_entrys to the free list
+ *
+ * => caller must hold pvalloc_lock
+ * => if need_entry is true, we allocate and return one pv_entry
+ */
+
+static struct pv_entry *
+pmap_add_pvpage(pvp, need_entry)
+ struct pv_page *pvp;
+ boolean_t need_entry;
+{
+ int tofree, lcv;
+
+ /* do we need to return one? */
+ tofree = (need_entry) ? PVE_PER_PVPAGE - 1 : PVE_PER_PVPAGE;
+
+ pvp->pvinfo.pvpi_pvfree = NULL;
+ pvp->pvinfo.pvpi_nfree = tofree;
+ for (lcv = 0 ; lcv < tofree ; lcv++) {
+ pvp->pvents[lcv].pv_next = pvp->pvinfo.pvpi_pvfree;
+ pvp->pvinfo.pvpi_pvfree = &pvp->pvents[lcv];
+ }
+ if (need_entry)
+ TAILQ_INSERT_TAIL(&pv_freepages, pvp, pvinfo.pvpi_list);
+ else
+ TAILQ_INSERT_TAIL(&pv_unusedpgs, pvp, pvinfo.pvpi_list);
+ pv_nfpvents += tofree;
+ return((need_entry) ? &pvp->pvents[lcv] : NULL);
+}
+
+/*
+ * pmap_free_pv_doit: actually free a pv_entry
+ *
+ * => do not call this directly! instead use either
+ * 1. pmap_free_pv ==> free a single pv_entry
+ * 2. pmap_free_pvs => free a list of pv_entrys
+ * => we must be holding pvalloc_lock
+ */
+
+__inline static void
+pmap_free_pv_doit(pv)
+ struct pv_entry *pv;
+{
+ struct pv_page *pvp;
+
+ pvp = (struct pv_page *) x86_trunc_page(pv);
+ pv_nfpvents++;
+ pvp->pvinfo.pvpi_nfree++;
+
+ /* nfree == 1 => fully allocated page just became partly allocated */
+ if (pvp->pvinfo.pvpi_nfree == 1) {
+ TAILQ_INSERT_HEAD(&pv_freepages, pvp, pvinfo.pvpi_list);
+ }
+
+ /* free it */
+ pv->pv_next = pvp->pvinfo.pvpi_pvfree;
+ pvp->pvinfo.pvpi_pvfree = pv;
+
+ /*
+ * are all pv_page's pv_entry's free? move it to unused queue.
+ */
+
+ if (pvp->pvinfo.pvpi_nfree == PVE_PER_PVPAGE) {
+ TAILQ_REMOVE(&pv_freepages, pvp, pvinfo.pvpi_list);
+ TAILQ_INSERT_HEAD(&pv_unusedpgs, pvp, pvinfo.pvpi_list);
+ }
+}
+
+/*
+ * pmap_free_pv: free a single pv_entry
+ *
+ * => we gain the pvalloc_lock
+ */
+
+__inline static void
+pmap_free_pv(pmap, pv)
+ struct pmap *pmap;
+ struct pv_entry *pv;
+{
+ simple_lock(&pvalloc_lock);
+ pmap_free_pv_doit(pv);
+
+ /*
+ * Can't free the PV page if the PV entries were associated with
+ * the kernel pmap; the pmap is already locked.
+ */
+ if (pv_nfpvents > PVE_HIWAT && TAILQ_FIRST(&pv_unusedpgs) != NULL &&
+ pmap != pmap_kernel())
+ pmap_free_pvpage();
+
+ simple_unlock(&pvalloc_lock);
+}
+
+/*
+ * pmap_free_pvs: free a list of pv_entrys
+ *
+ * => we gain the pvalloc_lock
+ */
+
+__inline static void
+pmap_free_pvs(pmap, pvs)
+ struct pmap *pmap;
+ struct pv_entry *pvs;
+{
+ struct pv_entry *nextpv;
+
+ simple_lock(&pvalloc_lock);
+
+ for ( /* null */ ; pvs != NULL ; pvs = nextpv) {
+ nextpv = pvs->pv_next;
+ pmap_free_pv_doit(pvs);
+ }
+
+ /*
+ * Can't free the PV page if the PV entries were associated with
+ * the kernel pmap; the pmap is already locked.
+ */
+ if (pv_nfpvents > PVE_HIWAT && TAILQ_FIRST(&pv_unusedpgs) != NULL &&
+ pmap != pmap_kernel())
+ pmap_free_pvpage();
+
+ simple_unlock(&pvalloc_lock);
+}
+
+
+/*
+ * pmap_free_pvpage: try and free an unused pv_page structure
+ *
+ * => assume caller is holding the pvalloc_lock and that
+ * there is a page on the pv_unusedpgs list
+ * => if we can't get a lock on the kmem_map we try again later
+ */
+
+void
+pmap_free_pvpage()
+{
+ int s;
+ struct vm_map *map;
+ struct vm_map_entry *dead_entries;
+ struct pv_page *pvp;
+
+ s = splvm(); /* protect kmem_map */
+
+ pvp = TAILQ_FIRST(&pv_unusedpgs);
+
+ /*
+ * note: watch out for pv_initpage which is allocated out of
+ * kernel_map rather than kmem_map.
+ */
+
+ if (pvp == pv_initpage)
+ map = kernel_map;
+ else
+ map = kmem_map;
+ if (vm_map_lock_try(map)) {
+
+ /* remove pvp from pv_unusedpgs */
+ TAILQ_REMOVE(&pv_unusedpgs, pvp, pvinfo.pvpi_list);
+
+ /* unmap the page */
+ dead_entries = NULL;
+ uvm_unmap_remove(map, (vaddr_t)pvp, ((vaddr_t)pvp) + PAGE_SIZE,
+ &dead_entries);
+ vm_map_unlock(map);
+
+ if (dead_entries != NULL)
+ uvm_unmap_detach(dead_entries, 0);
+
+ pv_nfpvents -= PVE_PER_PVPAGE; /* update free count */
+ }
+ if (pvp == pv_initpage)
+ /* no more initpage, we've freed it */
+ pv_initpage = NULL;
+
+ splx(s);
+}
+
+/*
+ * main pv_entry manipulation functions:
+ * pmap_enter_pv: enter a mapping onto a pv_head list
+ * pmap_remove_pv: remove a mappiing from a pv_head list
+ *
+ * NOTE: pmap_enter_pv expects to lock the pvh itself
+ * pmap_remove_pv expects te caller to lock the pvh before calling
+ */
+
+/*
+ * pmap_enter_pv: enter a mapping onto a pv_head lst
+ *
+ * => caller should hold the proper lock on pmap_main_lock
+ * => caller should have pmap locked
+ * => we will gain the lock on the pv_head and allocate the new pv_entry
+ * => caller should adjust ptp's wire_count before calling
+ */
+
+__inline static void
+pmap_enter_pv(pvh, pve, pmap, va, ptp)
+ struct pv_head *pvh;
+ struct pv_entry *pve; /* preallocated pve for us to use */
+ struct pmap *pmap;
+ vaddr_t va;
+ struct vm_page *ptp; /* PTP in pmap that maps this VA */
+{
+ pve->pv_pmap = pmap;
+ pve->pv_va = va;
+ pve->pv_ptp = ptp; /* NULL for kernel pmap */
+ simple_lock(&pvh->pvh_lock); /* lock pv_head */
+ pve->pv_next = pvh->pvh_list; /* add to ... */
+ pvh->pvh_list = pve; /* ... locked list */
+ simple_unlock(&pvh->pvh_lock); /* unlock, done! */
+}
+
+/*
+ * pmap_remove_pv: try to remove a mapping from a pv_list
+ *
+ * => caller should hold proper lock on pmap_main_lock
+ * => pmap should be locked
+ * => caller should hold lock on pv_head [so that attrs can be adjusted]
+ * => caller should adjust ptp's wire_count and free PTP if needed
+ * => we return the removed pve
+ */
+
+__inline static struct pv_entry *
+pmap_remove_pv(pvh, pmap, va)
+ struct pv_head *pvh;
+ struct pmap *pmap;
+ vaddr_t va;
+{
+ struct pv_entry *pve, **prevptr;
+
+ prevptr = &pvh->pvh_list; /* previous pv_entry pointer */
+ pve = *prevptr;
+ while (pve) {
+ if (pve->pv_pmap == pmap && pve->pv_va == va) { /* match? */
+ *prevptr = pve->pv_next; /* remove it! */
+ break;
+ }
+ prevptr = &pve->pv_next; /* previous pointer */
+ pve = pve->pv_next; /* advance */
+ }
+ return(pve); /* return removed pve */
+}
+
+/*
+ * p t p f u n c t i o n s
+ */
+
+static __inline struct vm_page *
+pmap_find_ptp(struct pmap *pmap, vaddr_t va, paddr_t pa, int level)
+{
+ int lidx = level - 1;
+ struct vm_page *pg;
+
+ if (pa != (paddr_t)-1 && pmap->pm_ptphint[lidx] &&
+ pa == VM_PAGE_TO_PHYS(pmap->pm_ptphint[lidx])) {
+ return (pmap->pm_ptphint[lidx]);
+ }
+ if (lidx == 0)
+ pg = uvm_pagelookup(&pmap->pm_obj[lidx], ptp_va2o(va, level));
+ else {
+ simple_lock(&pmap->pm_obj[lidx].vmobjlock);
+ pg = uvm_pagelookup(&pmap->pm_obj[lidx], ptp_va2o(va, level));
+ simple_unlock(&pmap->pm_obj[lidx].vmobjlock);
+ }
+ return pg;
+}
+
+static __inline void
+pmap_freepage(struct pmap *pmap, struct vm_page *ptp, int level)
+{
+ int lidx;
+ struct uvm_object *obj;
+
+ lidx = level - 1;
+
+ obj = &pmap->pm_obj[lidx];
+ pmap->pm_stats.resident_count--;
+ if (lidx != 0)
+ simple_lock(&obj->vmobjlock);
+ if (pmap->pm_ptphint[lidx] == ptp)
+ pmap->pm_ptphint[lidx] = TAILQ_FIRST(&obj->memq);
+ ptp->wire_count = 0;
+ uvm_pagefree(ptp);
+ if (lidx != 0)
+ simple_unlock(&obj->vmobjlock);
+}
+
+void
+pmap_free_ptp(struct pmap *pmap, struct vm_page *ptp, vaddr_t va,
+ pt_entry_t *ptes, pd_entry_t **pdes, int32_t *cpumaskp)
+{
+ unsigned long index;
+ int level;
+ vaddr_t invaladdr;
+ pd_entry_t opde;
+
+ level = 1;
+ do {
+ pmap_freepage(pmap, ptp, level);
+ index = pl_i(va, level + 1);
+ opde = pmap_pte_set(&pdes[level - 1][index], 0);
+ invaladdr = level == 1 ? (vaddr_t)ptes :
+ (vaddr_t)pdes[level - 2];
+ pmap_tlb_shootdown(curpcb->pcb_pmap,
+ invaladdr + index * PAGE_SIZE,
+ opde, cpumaskp);
+#if defined(MULTIPROCESSOR)
+ invaladdr = level == 1 ? (vaddr_t)PTE_BASE :
+ (vaddr_t)normal_pdes[level - 2];
+ pmap_tlb_shootdown(pmap, invaladdr + index * PAGE_SIZE, opde,
+ cpumaskp);
+#endif
+ if (level < PTP_LEVELS - 1) {
+ ptp = pmap_find_ptp(pmap, va, (paddr_t)-1, level + 1);
+ ptp->wire_count--;
+ if (ptp->wire_count > 1)
+ break;
+ }
+ } while (++level < PTP_LEVELS);
+}
+
+/*
+ * pmap_get_ptp: get a PTP (if there isn't one, allocate a new one)
+ *
+ * => pmap should NOT be pmap_kernel()
+ * => pmap should be locked
+ */
+
+
+struct vm_page *
+pmap_get_ptp(struct pmap *pmap, vaddr_t va, pd_entry_t **pdes)
+{
+ struct vm_page *ptp, *pptp;
+ int i;
+ unsigned long index;
+ pd_entry_t *pva;
+ paddr_t ppa, pa;
+ struct uvm_object *obj;
+
+ ptp = NULL;
+ pa = (paddr_t)-1;
+
+ /*
+ * Loop through all page table levels seeing if we need to
+ * add a new page to that level.
+ */
+ for (i = PTP_LEVELS; i > 1; i--) {
+ /*
+ * Save values from previous round.
+ */
+ pptp = ptp;
+ ppa = pa;
+
+ index = pl_i(va, i);
+ pva = pdes[i - 2];
+
+ if (pmap_valid_entry(pva[index])) {
+ ppa = pva[index] & PG_FRAME;
+ ptp = NULL;
+ continue;
+ }
+
+ obj = &pmap->pm_obj[i-2];
+ /*
+ * XXX pm_obj[0] is pm_lock, which is already locked.
+ */
+ if (i != 2)
+ simple_lock(&obj->vmobjlock);
+ ptp = uvm_pagealloc(obj, ptp_va2o(va, i - 1), NULL,
+ UVM_PGA_USERESERVE|UVM_PGA_ZERO);
+ if (i != 2)
+ simple_unlock(&obj->vmobjlock);
+
+ if (ptp == NULL)
+ return NULL;
+
+ ptp->flags &= ~PG_BUSY; /* never busy */
+ ptp->wire_count = 1;
+ pmap->pm_ptphint[i - 2] = ptp;
+ pa = VM_PAGE_TO_PHYS(ptp);
+ pva[index] = (pd_entry_t) (pa | PG_u | PG_RW | PG_V);
+ pmap->pm_stats.resident_count++;
+ /*
+ * If we're not in the top level, increase the
+ * wire count of the parent page.
+ */
+ if (i < PTP_LEVELS) {
+ if (pptp == NULL)
+ pptp = pmap_find_ptp(pmap, va, ppa, i);
+#ifdef DIAGNOSTIC
+ if (pptp == NULL)
+ panic("pde page disappeared");
+#endif
+ pptp->wire_count++;
+ }
+ }
+
+ /*
+ * ptp is not NULL if we just allocated a new ptp. If it's
+ * still NULL, we must look up the existing one.
+ */
+ if (ptp == NULL) {
+ ptp = pmap_find_ptp(pmap, va, ppa, 1);
+#ifdef DIAGNOSTIC
+ if (ptp == NULL) {
+ printf("va %lx ppa %lx\n", (unsigned long)va,
+ (unsigned long)ppa);
+ panic("pmap_get_ptp: unmanaged user PTP");
+ }
+#endif
+ }
+
+ pmap->pm_ptphint[0] = ptp;
+ return(ptp);
+}
+
+/*
+ * p m a p l i f e c y c l e f u n c t i o n s
+ */
+
+/*
+ * pmap_pdp_ctor: constructor for the PDP cache.
+ */
+
+int
+pmap_pdp_ctor(void *arg, void *object, int flags)
+{
+ pd_entry_t *pdir = object;
+ paddr_t pdirpa;
+ int npde;
+
+ /*
+ * NOTE: The `pmap_lock' is held when the PDP is allocated.
+ * WE MUST NOT BLOCK!
+ */
+
+ /* fetch the physical address of the page directory. */
+ (void) pmap_extract(pmap_kernel(), (vaddr_t) pdir, &pdirpa);
+
+ /* zero init area */
+ memset(pdir, 0, PDIR_SLOT_PTE * sizeof(pd_entry_t));
+
+ /* put in recursibve PDE to map the PTEs */
+ pdir[PDIR_SLOT_PTE] = pdirpa | PG_V | PG_KW;
+
+ npde = nkptp[PTP_LEVELS - 1];
+
+ /* put in kernel VM PDEs */
+ memcpy(&pdir[PDIR_SLOT_KERN], &PDP_BASE[PDIR_SLOT_KERN],
+ npde * sizeof(pd_entry_t));
+
+ /* zero the rest */
+ memset(&pdir[PDIR_SLOT_KERN + npde], 0,
+ (NTOPLEVEL_PDES - (PDIR_SLOT_KERN + npde)) * sizeof(pd_entry_t));
+
+#if VM_MIN_KERNEL_ADDRESS != KERNBASE
+ pdir[pl4_pi(KERNBASE)] = PDP_BASE[pl4_pi(KERNBASE)];
+#endif
+
+ return (0);
+}
+
+/*
+ * pmap_create: create a pmap
+ *
+ * => note: old pmap interface took a "size" args which allowed for
+ * the creation of "software only" pmaps (not in bsd).
+ */
+
+struct pmap *
+pmap_create()
+{
+ struct pmap *pmap;
+ int i;
+ u_int gen;
+
+ pmap = pool_get(&pmap_pmap_pool, PR_WAITOK);
+
+ /* init uvm_object */
+ for (i = 0; i < PTP_LEVELS - 1; i++) {
+ simple_lock_init(&pmap->pm_obj[i].vmobjlock);
+ pmap->pm_obj[i].pgops = NULL; /* not a mappable object */
+ TAILQ_INIT(&pmap->pm_obj[i].memq);
+ pmap->pm_obj[i].uo_npages = 0;
+ pmap->pm_obj[i].uo_refs = 1;
+ pmap->pm_ptphint[i] = NULL;
+ }
+ pmap->pm_stats.wired_count = 0;
+ pmap->pm_stats.resident_count = 1; /* count the PDP allocd below */
+ pmap->pm_flags = 0;
+
+ /* init the LDT */
+ pmap->pm_ldt = NULL;
+ pmap->pm_ldt_len = 0;
+ pmap->pm_ldt_sel = GSYSSEL(GLDT_SEL, SEL_KPL);
+
+ /* allocate PDP */
+
+ /*
+ * we need to lock pmaps_lock to prevent nkpde from changing on
+ * us. note that there is no need to splvm to protect us from
+ * malloc since malloc allocates out of a submap and we should
+ * have already allocated kernel PTPs to cover the range...
+ *
+ * NOTE: WE MUST NOT BLOCK WHILE HOLDING THE `pmap_lock', nor
+ * ust we call pmap_growkernel() while holding it!
+ */
+
+try_again:
+ gen = pmap_pdp_cache_generation;
+ pmap->pm_pdir = pool_cache_get(&pmap_pdp_cache, PR_WAITOK);
+
+ simple_lock(&pmaps_lock);
+
+ if (gen != pmap_pdp_cache_generation) {
+ simple_unlock(&pmaps_lock);
+ pool_cache_destruct_object(&pmap_pdp_cache, pmap->pm_pdir);
+ goto try_again;
+ }
+
+ pmap->pm_pdirpa = pmap->pm_pdir[PDIR_SLOT_PTE] & PG_FRAME;
+
+ LIST_INSERT_HEAD(&pmaps, pmap, pm_list);
+
+ simple_unlock(&pmaps_lock);
+
+ return (pmap);
+}
+
+/*
+ * pmap_destroy: drop reference count on pmap. free pmap if
+ * reference count goes to zero.
+ */
+
+void
+pmap_destroy(pmap)
+ struct pmap *pmap;
+{
+ struct vm_page *pg;
+ int refs;
+ int i;
+
+ /*
+ * drop reference count
+ */
+
+ simple_lock(&pmap->pm_lock);
+ refs = --pmap->pm_obj[0].uo_refs;
+ simple_unlock(&pmap->pm_lock);
+ if (refs > 0) {
+ return;
+ }
+
+ /*
+ * reference count is zero, free pmap resources and then free pmap.
+ */
+
+ /*
+ * remove it from global list of pmaps
+ */
+
+ simple_lock(&pmaps_lock);
+ LIST_REMOVE(pmap, pm_list);
+ simple_unlock(&pmaps_lock);
+
+ /*
+ * free any remaining PTPs
+ */
+
+ for (i = 0; i < PTP_LEVELS - 1; i++) {
+ while ((pg = TAILQ_FIRST(&pmap->pm_obj[i].memq)) != NULL) {
+ KASSERT((pg->flags & PG_BUSY) == 0);
+
+ pg->wire_count = 0;
+ uvm_pagefree(pg);
+ }
+ }
+
+ /*
+ * MULTIPROCESSOR -- no need to flush out of other processors'
+ * APTE space because we do that in pmap_unmap_ptes().
+ */
+ /* XXX: need to flush it out of other processor's APTE space? */
+ pool_cache_put(&pmap_pdp_cache, pmap->pm_pdir);
+
+#ifdef USER_LDT
+ if (pmap->pm_flags & PMF_USER_LDT) {
+ /*
+ * no need to switch the LDT; this address space is gone,
+ * nothing is using it.
+ *
+ * No need to lock the pmap for ldt_free (or anything else),
+ * we're the last one to use it.
+ */
+ ldt_free(pmap);
+ uvm_km_free(kernel_map, (vaddr_t)pmap->pm_ldt,
+ pmap->pm_ldt_len);
+ }
+#endif
+
+ pool_put(&pmap_pmap_pool, pmap);
+}
+
+/*
+ * Add a reference to the specified pmap.
+ */
+
+void
+pmap_reference(pmap)
+ struct pmap *pmap;
+{
+ simple_lock(&pmap->pm_lock);
+ pmap->pm_obj[0].uo_refs++;
+ simple_unlock(&pmap->pm_lock);
+}
+
+#if defined(PMAP_FORK)
+/*
+ * pmap_fork: perform any necessary data structure manipulation when
+ * a VM space is forked.
+ */
+
+void
+pmap_fork(pmap1, pmap2)
+ struct pmap *pmap1, *pmap2;
+{
+ simple_lock(&pmap1->pm_lock);
+ simple_lock(&pmap2->pm_lock);
+
+#ifdef USER_LDT
+ /* Copy the LDT, if necessary. */
+ if (pmap1->pm_flags & PMF_USER_LDT) {
+ char *new_ldt;
+ size_t len;
+
+ len = pmap1->pm_ldt_len;
+ new_ldt = (char *)uvm_km_alloc(kernel_map, len);
+ memcpy(new_ldt, pmap1->pm_ldt, len);
+ pmap2->pm_ldt = new_ldt;
+ pmap2->pm_ldt_len = pmap1->pm_ldt_len;
+ pmap2->pm_flags |= PMF_USER_LDT;
+ ldt_alloc(pmap2, new_ldt, len);
+ }
+#endif /* USER_LDT */
+
+ simple_unlock(&pmap2->pm_lock);
+ simple_unlock(&pmap1->pm_lock);
+}
+#endif /* PMAP_FORK */
+
+#ifdef USER_LDT
+/*
+ * pmap_ldt_cleanup: if the pmap has a local LDT, deallocate it, and
+ * restore the default.
+ */
+
+void
+pmap_ldt_cleanup(struct proc *p)
+{
+ struct pcb *pcb = &p->p_addr->u_pcb;
+ pmap_t pmap = p->->p_vmspace->vm_map.pmap;
+ char *old_ldt = NULL;
+ size_t len = 0;
+
+ simple_lock(&pmap->pm_lock);
+
+ if (pmap->pm_flags & PMF_USER_LDT) {
+ ldt_free(pmap);
+ pmap->pm_ldt_sel = GSYSSEL(GLDT_SEL, SEL_KPL);
+ pcb->pcb_ldt_sel = pmap->pm_ldt_sel;
+ if (pcb == curpcb)
+ lldt(pcb->pcb_ldt_sel);
+ old_ldt = pmap->pm_ldt;
+ len = pmap->pm_ldt_len;
+ pmap->pm_ldt = NULL;
+ pmap->pm_ldt_len = 0;
+ pmap->pm_flags &= ~PMF_USER_LDT;
+ }
+
+ simple_unlock(&pmap->pm_lock);
+
+ if (old_ldt != NULL)
+ uvm_km_free(kernel_map, (vaddr_t)old_ldt, len);
+}
+#endif /* USER_LDT */
+
+/*
+ * pmap_activate: activate a process' pmap (fill in %cr3 and LDT info)
+ *
+ * => called from cpu_switch()
+ * => if p is the curproc, then load it into the MMU
+ */
+
+void
+pmap_activate(struct proc *p)
+{
+ struct pcb *pcb = &p->p_addr->u_pcb;
+ struct pmap *pmap = p->p_vmspace->vm_map.pmap;
+
+ pcb->pcb_pmap = pmap;
+ pcb->pcb_ldt_sel = pmap->pm_ldt_sel;
+ pcb->pcb_cr3 = pmap->pm_pdirpa;
+ if (p == curproc)
+ lcr3(pcb->pcb_cr3);
+ if (pcb == curpcb)
+ lldt(pcb->pcb_ldt_sel);
+
+ /*
+ * mark the pmap in use by this processor.
+ */
+ x86_atomic_setbits_ul(&pmap->pm_cpus, (1U << cpu_number()));
+}
+
+/*
+ * pmap_deactivate: deactivate a process' pmap
+ */
+
+void
+pmap_deactivate(struct proc *p)
+{
+ struct pmap *pmap = p->p_vmspace->vm_map.pmap;
+
+ /*
+ * mark the pmap no longer in use by this processor.
+ */
+ x86_atomic_clearbits_ul(&pmap->pm_cpus, (1U << cpu_number()));
+
+}
+
+/*
+ * end of lifecycle functions
+ */
+
+/*
+ * some misc. functions
+ */
+
+boolean_t
+pmap_pdes_valid(vaddr_t va, pd_entry_t **pdes, pd_entry_t *lastpde)
+{
+ int i;
+ unsigned long index;
+ pd_entry_t pde;
+
+ for (i = PTP_LEVELS; i > 1; i--) {
+ index = pl_i(va, i);
+ pde = pdes[i - 2][index];
+ if ((pde & PG_V) == 0)
+ return FALSE;
+ }
+ if (lastpde != NULL)
+ *lastpde = pde;
+ return TRUE;
+}
+
+/*
+ * pmap_extract: extract a PA for the given VA
+ */
+
+boolean_t
+pmap_extract(pmap, va, pap)
+ struct pmap *pmap;
+ vaddr_t va;
+ paddr_t *pap;
+{
+ pt_entry_t *ptes, pte;
+ pd_entry_t pde, **pdes;
+
+ pmap_map_ptes(pmap, &ptes, &pdes);
+ if (pmap_pdes_valid(va, pdes, &pde) == FALSE) {
+ pmap_unmap_ptes(pmap);
+ return FALSE;
+ }
+ pte = ptes[pl1_i(va)];
+ pmap_unmap_ptes(pmap);
+
+#ifdef LARGEPAGES
+ if (pde & PG_PS) {
+ if (pap != NULL)
+ *pap = (pde & PG_LGFRAME) | (va & ~PG_LGFRAME);
+ return (TRUE);
+ }
+#endif
+
+
+ if (__predict_true((pte & PG_V) != 0)) {
+ if (pap != NULL)
+ *pap = (pte & PG_FRAME) | (va & ~PG_FRAME);
+ return (TRUE);
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * vtophys: virtual address to physical address. For use by
+ * machine-dependent code only.
+ */
+
+paddr_t
+vtophys(va)
+ vaddr_t va;
+{
+ paddr_t pa;
+
+ if (pmap_extract(pmap_kernel(), va, &pa) == TRUE)
+ return (pa);
+ return (0);
+}
+
+
+/*
+ * pmap_map: map a range of PAs into kvm
+ *
+ * => used during crash dump
+ * => XXX: pmap_map() should be phased out?
+ */
+
+vaddr_t
+pmap_map(va, spa, epa, prot)
+ vaddr_t va;
+ paddr_t spa, epa;
+ vm_prot_t prot;
+{
+ while (spa < epa) {
+ pmap_enter(pmap_kernel(), va, spa, prot, 0);
+ va += PAGE_SIZE;
+ spa += PAGE_SIZE;
+ }
+ pmap_update(pmap_kernel());
+ return va;
+}
+
+
+/*
+ * pmap_zero_page: zero a page
+ */
+
+void
+pmap_zero_page(struct vm_page *pg)
+{
+ paddr_t pa = VM_PAGE_TO_PHYS(pg);
+
+#ifdef MULTIPROCESSOR
+ int id = cpu_number();
+#endif
+ pt_entry_t *zpte = PTESLEW(zero_pte, id);
+ caddr_t zerova = VASLEW(zerop, id);
+
+#ifdef DIAGNOSTIC
+ if (*zpte)
+ panic("pmap_zero_page: lock botch");
+#endif
+
+ *zpte = (pa & PG_FRAME) | PG_V | PG_RW; /* map in */
+ pmap_update_pg((vaddr_t)zerova); /* flush TLB */
+
+ memset(zerova, 0, PAGE_SIZE); /* zero */
+#ifdef DIAGNOSTIC
+ *zpte = 0; /* zap! */
+#endif
+}
+
+/*
+ * pmap_pagezeroidle: the same, for the idle loop page zero'er.
+ * Returns TRUE if the page was zero'd, FALSE if we aborted for
+ * some reason.
+ */
+
+boolean_t
+pmap_pageidlezero(struct vm_page *pg)
+{
+ paddr_t pa = VM_PAGE_TO_PHYS(pg);
+#ifdef MULTIPROCESSOR
+ int id = cpu_number();
+#endif
+ pt_entry_t *zpte = PTESLEW(zero_pte, id);
+ caddr_t zerova = VASLEW(zerop, id);
+ boolean_t rv = TRUE;
+ int *ptr;
+ unsigned int i;
+
+printf("pmap_pageidlezero()\n");
+#ifdef DIAGNOSTIC
+ if (*zpte)
+ panic("pmap_zero_page_uncached: lock botch");
+#endif
+ *zpte = (pa & PG_FRAME) | PG_V | PG_RW | PG_N; /* map in */
+ pmap_update_pg((vaddr_t)zerova); /* flush TLB */
+ for (i = 0, ptr = (int *) zerova; i < PAGE_SIZE / sizeof(int); i++) {
+ if (whichqs != 0) {
+
+ /*
+ * A process has become ready. Abort now,
+ * so we don't keep it waiting while we
+ * do slow memory access to finish this
+ * page.
+ */
+
+ rv = FALSE;
+ break;
+ }
+ *ptr++ = 0;
+ }
+
+#ifdef DIAGNOSTIC
+ *zpte = 0; /* zap! */
+#endif
+ return (rv);
+}
+
+/*
+ * pmap_copy_page: copy a page
+ */
+
+void
+pmap_copy_page(struct vm_page *srcpg, struct vm_page *dstpg)
+{
+ paddr_t srcpa = VM_PAGE_TO_PHYS(srcpg);
+ paddr_t dstpa = VM_PAGE_TO_PHYS(dstpg);
+#ifdef MULTIPROCESSOR
+ int id = cpu_number();
+#endif
+ pt_entry_t *spte = PTESLEW(csrc_pte,id);
+ pt_entry_t *dpte = PTESLEW(cdst_pte,id);
+ caddr_t csrcva = VASLEW(csrcp, id);
+ caddr_t cdstva = VASLEW(cdstp, id);
+
+#ifdef DIAGNOSTIC
+ if (*spte || *dpte)
+ panic("pmap_copy_page: lock botch");
+#endif
+
+ *spte = (srcpa & PG_FRAME) | PG_V | PG_RW;
+ *dpte = (dstpa & PG_FRAME) | PG_V | PG_RW;
+ pmap_update_2pg((vaddr_t)csrcva, (vaddr_t)cdstva);
+ memcpy(cdstva, csrcva, PAGE_SIZE);
+#ifdef DIAGNOSTIC
+ *spte = *dpte = 0; /* zap! */
+#endif
+}
+
+/*
+ * p m a p r e m o v e f u n c t i o n s
+ *
+ * functions that remove mappings
+ */
+
+/*
+ * pmap_remove_ptes: remove PTEs from a PTP
+ *
+ * => must have proper locking on pmap_master_lock
+ * => caller must hold pmap's lock
+ * => PTP must be mapped into KVA
+ * => PTP should be null if pmap == pmap_kernel()
+ */
+
+void
+pmap_remove_ptes(pmap, ptp, ptpva, startva, endva, cpumaskp, flags)
+ struct pmap *pmap;
+ struct vm_page *ptp;
+ vaddr_t ptpva;
+ vaddr_t startva, endva;
+ int32_t *cpumaskp;
+ int flags;
+{
+ struct pv_entry *pv_tofree = NULL; /* list of pv_entrys to free */
+ struct pv_entry *pve;
+ pt_entry_t *pte = (pt_entry_t *) ptpva;
+ pt_entry_t opte;
+ int bank, off;
+
+ /*
+ * note that ptpva points to the PTE that maps startva. this may
+ * or may not be the first PTE in the PTP.
+ *
+ * we loop through the PTP while there are still PTEs to look at
+ * and the wire_count is greater than 1 (because we use the wire_count
+ * to keep track of the number of real PTEs in the PTP).
+ */
+
+ for (/*null*/; startva < endva && (ptp == NULL || ptp->wire_count > 1)
+ ; pte++, startva += PAGE_SIZE) {
+ if (!pmap_valid_entry(*pte))
+ continue; /* VA not mapped */
+ if ((flags & PMAP_REMOVE_SKIPWIRED) && (*pte & PG_W)) {
+ continue;
+ }
+
+ /* atomically save the old PTE and zap! it */
+ opte = pmap_pte_set(pte, 0);
+
+ if (opte & PG_W)
+ pmap->pm_stats.wired_count--;
+ pmap->pm_stats.resident_count--;
+
+ pmap_tlb_shootdown(pmap, startva, opte, cpumaskp);
+
+ if (ptp)
+ ptp->wire_count--; /* dropping a PTE */
+
+ /*
+ * if we are not on a pv_head list we are done.
+ */
+
+ if ((opte & PG_PVLIST) == 0) {
+#ifdef DIAGNOSTIC
+ if (vm_physseg_find(btop(opte & PG_FRAME), &off)
+ != -1)
+ panic("pmap_remove_ptes: managed page without "
+ "PG_PVLIST for 0x%lx", startva);
+#endif
+ continue;
+ }
+
+ bank = vm_physseg_find(btop(opte & PG_FRAME), &off);
+#ifdef DIAGNOSTIC
+ if (bank == -1)
+ panic("pmap_remove_ptes: unmanaged page marked "
+ "PG_PVLIST, va = 0x%lx, pa = 0x%lx",
+ startva, (u_long)(opte & PG_FRAME));
+#endif
+
+ /* sync R/M bits */
+ simple_lock(&vm_physmem[bank].pmseg.pvhead[off].pvh_lock);
+ vm_physmem[bank].pmseg.attrs[off] |= (opte & (PG_U|PG_M));
+ pve = pmap_remove_pv(&vm_physmem[bank].pmseg.pvhead[off], pmap,
+ startva);
+ simple_unlock(&vm_physmem[bank].pmseg.pvhead[off].pvh_lock);
+
+ if (pve) {
+ pve->pv_next = pv_tofree;
+ pv_tofree = pve;
+ }
+
+ /* end of "for" loop: time for next pte */
+ }
+ if (pv_tofree)
+ pmap_free_pvs(pmap, pv_tofree);
+}
+
+
+/*
+ * pmap_remove_pte: remove a single PTE from a PTP
+ *
+ * => must have proper locking on pmap_master_lock
+ * => caller must hold pmap's lock
+ * => PTP must be mapped into KVA
+ * => PTP should be null if pmap == pmap_kernel()
+ * => returns true if we removed a mapping
+ */
+
+boolean_t
+pmap_remove_pte(pmap, ptp, pte, va, cpumaskp, flags)
+ struct pmap *pmap;
+ struct vm_page *ptp;
+ pt_entry_t *pte;
+ vaddr_t va;
+ int32_t *cpumaskp;
+ int flags;
+{
+ pt_entry_t opte;
+ int bank, off;
+ struct pv_entry *pve;
+
+ if (!pmap_valid_entry(*pte))
+ return(FALSE); /* VA not mapped */
+ if ((flags & PMAP_REMOVE_SKIPWIRED) && (*pte & PG_W)) {
+ return(FALSE);
+ }
+
+ /* atomically save the old PTE and zap! it */
+ opte = pmap_pte_set(pte, 0);
+
+ if (opte & PG_W)
+ pmap->pm_stats.wired_count--;
+ pmap->pm_stats.resident_count--;
+
+ if (ptp)
+ ptp->wire_count--; /* dropping a PTE */
+
+ pmap_tlb_shootdown(pmap, va, opte, cpumaskp);
+
+ /*
+ * if we are not on a pv_head list we are done.
+ */
+
+ if ((opte & PG_PVLIST) == 0) {
+#ifdef DIAGNOSTIC
+ if (vm_physseg_find(btop(opte & PG_FRAME), &off) != -1) {
+ printf("pmap_remove_pte: managed page without "
+ "PG_PVLIST for 0x%lx\n", va);
+ Debugger();
+ }
+#endif
+ return(TRUE);
+ }
+
+ bank = vm_physseg_find(btop(opte & PG_FRAME), &off);
+#ifdef DIAGNOSTIC
+ if (bank == -1)
+ panic("pmap_remove_pte: unmanaged page marked "
+ "PG_PVLIST, va = 0x%lx, pa = 0x%lx", va,
+ (u_long)(opte & PG_FRAME));
+#endif
+
+ /* sync R/M bits */
+ simple_lock(&vm_physmem[bank].pmseg.pvhead[off].pvh_lock);
+ vm_physmem[bank].pmseg.attrs[off] |= (opte & (PG_U|PG_M));
+ pve = pmap_remove_pv(&vm_physmem[bank].pmseg.pvhead[off], pmap, va);
+ simple_unlock(&vm_physmem[bank].pmseg.pvhead[off].pvh_lock);
+
+ if (pve)
+ pmap_free_pv(pmap, pve);
+ return(TRUE);
+}
+
+/*
+ * pmap_remove: top level mapping removal function
+ *
+ * => caller should not be holding any pmap locks
+ */
+
+void
+pmap_remove(pmap, sva, eva)
+ struct pmap *pmap;
+ vaddr_t sva, eva;
+{
+ pmap_do_remove(pmap, sva, eva, PMAP_REMOVE_ALL);
+}
+
+/*
+ * pmap_do_remove: mapping removal guts
+ *
+ * => caller should not be holding any pmap locks
+ */
+
+void
+pmap_do_remove(pmap, sva, eva, flags)
+ struct pmap *pmap;
+ vaddr_t sva, eva;
+ int flags;
+{
+ pt_entry_t *ptes;
+ pd_entry_t **pdes, pde;
+ boolean_t result;
+ paddr_t ptppa;
+ vaddr_t blkendva;
+ struct vm_page *ptp;
+ int32_t cpumask = 0;
+
+ /*
+ * we lock in the pmap => pv_head direction
+ */
+
+ PMAP_MAP_TO_HEAD_LOCK();
+ pmap_map_ptes(pmap, &ptes, &pdes); /* locks pmap */
+
+ /*
+ * removing one page? take shortcut function.
+ */
+
+ if (sva + PAGE_SIZE == eva) {
+ if (pmap_pdes_valid(sva, pdes, &pde)) {
+
+ /* PA of the PTP */
+ ptppa = pde & PG_FRAME;
+
+ /* get PTP if non-kernel mapping */
+
+ if (pmap == pmap_kernel()) {
+ /* we never free kernel PTPs */
+ ptp = NULL;
+ } else {
+ ptp = pmap_find_ptp(pmap, sva, ptppa, 1);
+#ifdef DIAGNOSTIC
+ if (ptp == NULL)
+ panic("pmap_remove: unmanaged "
+ "PTP detected");
+#endif
+ }
+
+ /* do it! */
+ result = pmap_remove_pte(pmap, ptp,
+ &ptes[pl1_i(sva)], sva, &cpumask, flags);
+
+ /*
+ * if mapping removed and the PTP is no longer
+ * being used, free it!
+ */
+
+ if (result && ptp && ptp->wire_count <= 1)
+ pmap_free_ptp(pmap, ptp, sva, ptes, pdes,
+ &cpumask);
+ }
+
+ pmap_tlb_shootnow(cpumask);
+ pmap_unmap_ptes(pmap); /* unlock pmap */
+ PMAP_MAP_TO_HEAD_UNLOCK();
+ return;
+ }
+
+ cpumask = 0;
+
+ for (/* null */ ; sva < eva ; sva = blkendva) {
+
+ /* determine range of block */
+ blkendva = x86_round_pdr(sva+1);
+ if (blkendva > eva)
+ blkendva = eva;
+
+ /*
+ * XXXCDC: our PTE mappings should never be removed
+ * with pmap_remove! if we allow this (and why would
+ * we?) then we end up freeing the pmap's page
+ * directory page (PDP) before we are finished using
+ * it when we hit in in the recursive mapping. this
+ * is BAD.
+ *
+ * long term solution is to move the PTEs out of user
+ * address space. and into kernel address space (up
+ * with APTE). then we can set VM_MAXUSER_ADDRESS to
+ * be VM_MAX_ADDRESS.
+ */
+
+ if (pl_i(sva, PTP_LEVELS) == PDIR_SLOT_PTE)
+ /* XXXCDC: ugly hack to avoid freeing PDP here */
+ continue;
+
+ if (!pmap_pdes_valid(sva, pdes, &pde))
+ continue;
+
+ /* PA of the PTP */
+ ptppa = pde & PG_FRAME;
+
+ /* get PTP if non-kernel mapping */
+ if (pmap == pmap_kernel()) {
+ /* we never free kernel PTPs */
+ ptp = NULL;
+ } else {
+ ptp = pmap_find_ptp(pmap, sva, ptppa, 1);
+#ifdef DIAGNOSTIC
+ if (ptp == NULL)
+ panic("pmap_remove: unmanaged PTP "
+ "detected");
+#endif
+ }
+ pmap_remove_ptes(pmap, ptp,
+ (vaddr_t)&ptes[pl1_i(sva)], sva, blkendva, &cpumask, flags);
+
+ /* if PTP is no longer being used, free it! */
+ if (ptp && ptp->wire_count <= 1) {
+ pmap_free_ptp(pmap, ptp, sva, ptes,pdes,
+ &cpumask);
+ }
+ }
+
+ pmap_tlb_shootnow(cpumask);
+ pmap_unmap_ptes(pmap);
+ PMAP_MAP_TO_HEAD_UNLOCK();
+}
+
+/*
+ * pmap_page_remove: remove a managed vm_page from all pmaps that map it
+ *
+ * => we set pv_head => pmap locking
+ * => R/M bits are sync'd back to attrs
+ */
+
+void
+pmap_page_remove(pg)
+ struct vm_page *pg;
+{
+ int bank, off;
+ struct pv_head *pvh;
+ struct pv_entry *pve, *npve, **prevptr, *killlist = NULL;
+ pt_entry_t *ptes, opte;
+ pd_entry_t **pdes;
+#ifdef DIAGNOSTIC
+ pd_entry_t pde;
+#endif
+ int32_t cpumask = 0;
+
+ /* XXX: vm_page should either contain pv_head or have a pointer to it */
+ bank = vm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), &off);
+ if (bank == -1) {
+ printf("pmap_page_remove: unmanaged page?\n");
+ return;
+ }
+
+ pvh = &vm_physmem[bank].pmseg.pvhead[off];
+ if (pvh->pvh_list == NULL) {
+ return;
+ }
+
+ /* set pv_head => pmap locking */
+ PMAP_HEAD_TO_MAP_LOCK();
+
+ /* XXX: needed if we hold head->map lock? */
+ simple_lock(&pvh->pvh_lock);
+
+ for (prevptr = &pvh->pvh_list, pve = pvh->pvh_list;
+ pve != NULL; pve = npve) {
+ npve = pve->pv_next;
+ pmap_map_ptes(pve->pv_pmap, &ptes, &pdes); /* locks pmap */
+
+#ifdef DIAGNOSTIC
+ if (pve->pv_ptp && pmap_pdes_valid(pve->pv_va, pdes, &pde) &&
+ (pde & PG_FRAME) != VM_PAGE_TO_PHYS(pve->pv_ptp)) {
+ printf("pmap_page_remove: pg=%p: va=%lx, pv_ptp=%p\n",
+ pg, pve->pv_va, pve->pv_ptp);
+ printf("pmap_page_remove: PTP's phys addr: "
+ "actual=%lx, recorded=%lx\n",
+ (unsigned long)(pde & PG_FRAME),
+ VM_PAGE_TO_PHYS(pve->pv_ptp));
+ panic("pmap_page_remove: mapped managed page has "
+ "invalid pv_ptp field");
+ }
+#endif
+
+ /* atomically save the old PTE and zap! it */
+ opte = pmap_pte_set(&ptes[pl1_i(pve->pv_va)], 0);
+
+ if (opte & PG_W)
+ pve->pv_pmap->pm_stats.wired_count--;
+ pve->pv_pmap->pm_stats.resident_count--;
+
+ pmap_tlb_shootdown(pve->pv_pmap, pve->pv_va, opte, &cpumask);
+
+ /* sync R/M bits */
+ vm_physmem[bank].pmseg.attrs[off] |= (opte & (PG_U|PG_M));
+
+ /* update the PTP reference count. free if last reference. */
+ if (pve->pv_ptp) {
+ pve->pv_ptp->wire_count--;
+ if (pve->pv_ptp->wire_count <= 1) {
+ pmap_free_ptp(pve->pv_pmap, pve->pv_ptp,
+ pve->pv_va, ptes, pdes, &cpumask);
+ }
+ }
+ pmap_unmap_ptes(pve->pv_pmap); /* unlocks pmap */
+ *prevptr = npve; /* remove it */
+ pve->pv_next = killlist; /* mark it for death */
+ killlist = pve;
+ }
+ pmap_free_pvs(NULL, killlist);
+ pvh->pvh_list = NULL;
+ simple_unlock(&pvh->pvh_lock);
+ PMAP_HEAD_TO_MAP_UNLOCK();
+ pmap_tlb_shootnow(cpumask);
+}
+
+/*
+ * p m a p a t t r i b u t e f u n c t i o n s
+ * functions that test/change managed page's attributes
+ * since a page can be mapped multiple times we must check each PTE that
+ * maps it by going down the pv lists.
+ */
+
+/*
+ * pmap_test_attrs: test a page's attributes
+ *
+ * => we set pv_head => pmap locking
+ */
+
+boolean_t
+pmap_test_attrs(pg, testbits)
+ struct vm_page *pg;
+ unsigned testbits;
+{
+ int bank, off;
+ unsigned char *myattrs;
+ struct pv_head *pvh;
+ struct pv_entry *pve;
+ pt_entry_t *ptes, pte;
+ pd_entry_t **pdes;
+
+ /* XXX: vm_page should either contain pv_head or have a pointer to it */
+ bank = vm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), &off);
+ if (bank == -1) {
+ printf("pmap_test_attrs: unmanaged page?\n");
+ return(FALSE);
+ }
+
+ /*
+ * before locking: see if attributes are already set and if so,
+ * return!
+ */
+
+ myattrs = &vm_physmem[bank].pmseg.attrs[off];
+ if (*myattrs & testbits)
+ return(TRUE);
+
+ /* test to see if there is a list before bothering to lock */
+ pvh = &vm_physmem[bank].pmseg.pvhead[off];
+ if (pvh->pvh_list == NULL) {
+ return(FALSE);
+ }
+
+ /* nope, gonna have to do it the hard way */
+ PMAP_HEAD_TO_MAP_LOCK();
+ /* XXX: needed if we hold head->map lock? */
+ simple_lock(&pvh->pvh_lock);
+
+ for (pve = pvh->pvh_list; pve != NULL && (*myattrs & testbits) == 0;
+ pve = pve->pv_next) {
+ pmap_map_ptes(pve->pv_pmap, &ptes, &pdes);
+ pte = ptes[pl1_i(pve->pv_va)];
+ pmap_unmap_ptes(pve->pv_pmap);
+ *myattrs |= pte;
+ }
+
+ /*
+ * note that we will exit the for loop with a non-null pve if
+ * we have found the bits we are testing for.
+ */
+
+ simple_unlock(&pvh->pvh_lock);
+ PMAP_HEAD_TO_MAP_UNLOCK();
+ return((*myattrs & testbits) != 0);
+}
+
+/*
+ * pmap_clear_attrs: change a page's attributes
+ *
+ * => we set pv_head => pmap locking
+ * => we return TRUE if we cleared one of the bits we were asked to
+ */
+
+boolean_t
+pmap_clear_attrs(pg, clearbits)
+ struct vm_page *pg;
+ unsigned clearbits;
+{
+ int bank, off;
+ unsigned result;
+ struct pv_head *pvh;
+ struct pv_entry *pve;
+ pt_entry_t *ptes, opte;
+ pd_entry_t **pdes;
+ unsigned char *myattrs;
+ int32_t cpumask = 0;
+
+ /* XXX: vm_page should either contain pv_head or have a pointer to it */
+ bank = vm_physseg_find(atop(VM_PAGE_TO_PHYS(pg)), &off);
+ if (bank == -1) {
+ printf("pmap_change_attrs: unmanaged page?\n");
+ return(FALSE);
+ }
+
+ PMAP_HEAD_TO_MAP_LOCK();
+ pvh = &vm_physmem[bank].pmseg.pvhead[off];
+ /* XXX: needed if we hold head->map lock? */
+ simple_lock(&pvh->pvh_lock);
+
+ myattrs = &vm_physmem[bank].pmseg.attrs[off];
+ result = *myattrs & clearbits;
+ *myattrs &= ~clearbits;
+
+ for (pve = pvh->pvh_list; pve != NULL; pve = pve->pv_next) {
+ pmap_map_ptes(pve->pv_pmap, &ptes, &pdes); /* locks pmap */
+#ifdef DIAGNOSTIC
+ if (!pmap_pdes_valid(pve->pv_va, pdes, NULL))
+ panic("pmap_change_attrs: mapping without PTP "
+ "detected");
+#endif
+
+ opte = ptes[pl1_i(pve->pv_va)];
+ if (opte & clearbits) {
+ result |= (opte & clearbits);
+ pmap_pte_clearbits(&ptes[pl1_i(pve->pv_va)],
+ (opte & clearbits));
+ pmap_tlb_shootdown(pve->pv_pmap, pve->pv_va, opte,
+ &cpumask);
+ }
+ pmap_unmap_ptes(pve->pv_pmap); /* unlocks pmap */
+ }
+
+ simple_unlock(&pvh->pvh_lock);
+ PMAP_HEAD_TO_MAP_UNLOCK();
+
+ pmap_tlb_shootnow(cpumask);
+
+ return(result != 0);
+}
+
+/*
+ * p m a p p r o t e c t i o n f u n c t i o n s
+ */
+
+/*
+ * pmap_page_protect: change the protection of all recorded mappings
+ * of a managed page
+ *
+ * => NOTE: this is an inline function in pmap.h
+ */
+
+/* see pmap.h */
+
+/*
+ * pmap_protect: set the protection in of the pages in a pmap
+ *
+ * => NOTE: this is an inline function in pmap.h
+ */
+
+/* see pmap.h */
+
+/*
+ * pmap_write_protect: write-protect pages in a pmap
+ */
+
+void
+pmap_write_protect(pmap, sva, eva, prot)
+ struct pmap *pmap;
+ vaddr_t sva, eva;
+ vm_prot_t prot;
+{
+ pt_entry_t *ptes, *spte, *epte;
+ pd_entry_t **pdes;
+ vaddr_t blockend;
+ int32_t cpumask = 0;
+
+ pmap_map_ptes(pmap, &ptes, &pdes); /* locks pmap */
+
+ /* should be ok, but just in case ... */
+ sva &= PG_FRAME;
+ eva &= PG_FRAME;
+
+ for (/* null */ ; sva < eva ; sva = blockend) {
+
+ blockend = (sva & L2_FRAME) + NBPD_L2;
+ if (blockend > eva)
+ blockend = eva;
+
+ /*
+ * XXXCDC: our PTE mappings should never be write-protected!
+ *
+ * long term solution is to move the PTEs out of user
+ * address space. and into kernel address space (up
+ * with APTE). then we can set VM_MAXUSER_ADDRESS to
+ * be VM_MAX_ADDRESS.
+ */
+
+ /* XXXCDC: ugly hack to avoid freeing PDP here */
+ if (pl_i(sva, PTP_LEVELS) == PDIR_SLOT_PTE)
+ continue;
+
+ /* empty block? */
+ if (!pmap_pdes_valid(sva, pdes, NULL))
+ continue;
+
+#ifdef DIAGNOSTIC
+ if (sva >= VM_MAXUSER_ADDRESS &&
+ sva < VM_MAX_ADDRESS)
+ panic("pmap_write_protect: PTE space");
+#endif
+
+ spte = &ptes[pl1_i(sva)];
+ epte = &ptes[pl1_i(blockend)];
+
+ for (/*null */; spte < epte ; spte++) {
+ if ((*spte & (PG_RW|PG_V)) == (PG_RW|PG_V)) {
+ pmap_pte_clearbits(spte, PG_RW);
+ pmap_tlb_shootdown(pmap, ptob(spte - ptes),
+ *spte, &cpumask);
+ }
+ }
+ }
+
+ pmap_tlb_shootnow(cpumask);
+ pmap_unmap_ptes(pmap); /* unlocks pmap */
+}
+
+/*
+ * end of protection functions
+ */
+
+/*
+ * pmap_unwire: clear the wired bit in the PTE
+ *
+ * => mapping should already be in map
+ */
+
+void
+pmap_unwire(pmap, va)
+ struct pmap *pmap;
+ vaddr_t va;
+{
+ pt_entry_t *ptes;
+ pd_entry_t **pdes;
+
+ pmap_map_ptes(pmap, &ptes, &pdes); /* locks pmap */
+
+ if (pmap_pdes_valid(va, pdes, NULL)) {
+
+#ifdef DIAGNOSTIC
+ if (!pmap_valid_entry(ptes[pl1_i(va)]))
+ panic("pmap_unwire: invalid (unmapped) va 0x%lx", va);
+#endif
+ if ((ptes[pl1_i(va)] & PG_W) != 0) {
+ ptes[pl1_i(va)] &= ~PG_W;
+ pmap->pm_stats.wired_count--;
+ }
+#ifdef DIAGNOSTIC
+ else {
+ printf("pmap_unwire: wiring for pmap %p va 0x%lx "
+ "didn't change!\n", pmap, va);
+ }
+#endif
+ pmap_unmap_ptes(pmap); /* unlocks map */
+ }
+#ifdef DIAGNOSTIC
+ else {
+ panic("pmap_unwire: invalid PDE");
+ }
+#endif
+}
+
+/*
+ * pmap_collect: free resources held by a pmap
+ *
+ * => optional function.
+ * => called when a process is swapped out to free memory.
+ */
+
+void
+pmap_collect(pmap)
+ struct pmap *pmap;
+{
+ /*
+ * free all of the pt pages by removing the physical mappings
+ * for its entire address space.
+ */
+
+/* pmap_do_remove(pmap, VM_MIN_ADDRESS, VM_MAX_ADDRESS,
+ PMAP_REMOVE_SKIPWIRED);
+*/
+}
+
+/*
+ * pmap_copy: copy mappings from one pmap to another
+ *
+ * => optional function
+ * void pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr)
+ */
+
+/*
+ * defined as macro in pmap.h
+ */
+
+/*
+ * pmap_enter: enter a mapping into a pmap
+ *
+ * => must be done "now" ... no lazy-evaluation
+ * => we set pmap => pv_head locking
+ */
+
+int
+pmap_enter(pmap, va, pa, prot, flags)
+ struct pmap *pmap;
+ vaddr_t va;
+ paddr_t pa;
+ vm_prot_t prot;
+ int flags;
+{
+ pt_entry_t *ptes, opte, npte;
+ pd_entry_t **pdes;
+ struct vm_page *ptp;
+ struct pv_head *pvh;
+ struct pv_entry *pve;
+ int bank, off, error;
+ int ptpdelta, wireddelta, resdelta;
+ boolean_t wired = (flags & PMAP_WIRED) != 0;
+
+#ifdef DIAGNOSTIC
+ /* sanity check: totally out of range? */
+ if (va >= VM_MAX_KERNEL_ADDRESS)
+ panic("pmap_enter: too big");
+
+ if (va == (vaddr_t) PDP_BASE || va == (vaddr_t) APDP_BASE)
+ panic("pmap_enter: trying to map over PDP/APDP!");
+
+ /* sanity check: kernel PTPs should already have been pre-allocated */
+ if (va >= VM_MIN_KERNEL_ADDRESS &&
+ !pmap_valid_entry(pmap->pm_pdir[pl_i(va, PTP_LEVELS)]))
+ panic("pmap_enter: missing kernel PTP for va %lx!", va);
+
+#endif
+
+ /* get lock */
+ PMAP_MAP_TO_HEAD_LOCK();
+
+ /*
+ * map in ptes and get a pointer to our PTP (unless we are the kernel)
+ */
+
+ pmap_map_ptes(pmap, &ptes, &pdes); /* locks pmap */
+ if (pmap == pmap_kernel()) {
+ ptp = NULL;
+ } else {
+ ptp = pmap_get_ptp(pmap, va, pdes);
+ if (ptp == NULL) {
+ if (flags & PMAP_CANFAIL) {
+ error = ENOMEM;
+ goto out;
+ }
+ panic("pmap_enter: get ptp failed");
+ }
+ }
+ opte = ptes[pl1_i(va)]; /* old PTE */
+
+ /*
+ * is there currently a valid mapping at our VA?
+ */
+
+ if (pmap_valid_entry(opte)) {
+ /*
+ * first, calculate pm_stats updates. resident count will not
+ * change since we are replacing/changing a valid mapping.
+ * wired count might change...
+ */
+
+ resdelta = 0;
+ if (wired && (opte & PG_W) == 0)
+ wireddelta = 1;
+ else if (!wired && (opte & PG_W) != 0)
+ wireddelta = -1;
+ else
+ wireddelta = 0;
+ ptpdelta = 0;
+
+ /*
+ * is the currently mapped PA the same as the one we
+ * want to map?
+ */
+
+ if ((opte & PG_FRAME) == pa) {
+
+ /* if this is on the PVLIST, sync R/M bit */
+ if (opte & PG_PVLIST) {
+ bank = vm_physseg_find(atop(pa), &off);
+#ifdef DIAGNOSTIC
+ if (bank == -1)
+ panic("pmap_enter: same pa PG_PVLIST "
+ "mapping with unmanaged page "
+ "pa = 0x%lx (0x%lx)", pa,
+ atop(pa));
+#endif
+ pvh = &vm_physmem[bank].pmseg.pvhead[off];
+ simple_lock(&pvh->pvh_lock);
+ vm_physmem[bank].pmseg.attrs[off] |= opte;
+ simple_unlock(&pvh->pvh_lock);
+ } else {
+ pvh = NULL; /* ensure !PG_PVLIST */
+ }
+ goto enter_now;
+ }
+
+ /*
+ * changing PAs: we must remove the old one first
+ */
+
+ /*
+ * if current mapping is on a pvlist,
+ * remove it (sync R/M bits)
+ */
+
+ if (opte & PG_PVLIST) {
+ bank = vm_physseg_find(atop(opte & PG_FRAME), &off);
+#ifdef DIAGNOSTIC
+ if (bank == -1)
+ panic("pmap_enter: PG_PVLIST mapping with "
+ "unmanaged page "
+ "pa = 0x%lx (0x%lx)", pa, atop(pa));
+#endif
+ pvh = &vm_physmem[bank].pmseg.pvhead[off];
+ simple_lock(&pvh->pvh_lock);
+ pve = pmap_remove_pv(pvh, pmap, va);
+ vm_physmem[bank].pmseg.attrs[off] |= opte;
+ simple_unlock(&pvh->pvh_lock);
+ } else {
+ pve = NULL;
+ }
+ } else { /* opte not valid */
+ pve = NULL;
+ resdelta = 1;
+ if (wired)
+ wireddelta = 1;
+ else
+ wireddelta = 0;
+ if (ptp)
+ ptpdelta = 1;
+ else
+ ptpdelta = 0;
+ }
+
+ /*
+ * pve is either NULL or points to a now-free pv_entry structure
+ * (the latter case is if we called pmap_remove_pv above).
+ *
+ * if this entry is to be on a pvlist, enter it now.
+ */
+
+ bank = vm_physseg_find(atop(pa), &off);
+ if (pmap_initialized && bank != -1) {
+ pvh = &vm_physmem[bank].pmseg.pvhead[off];
+ if (pve == NULL) {
+ pve = pmap_alloc_pv(pmap, ALLOCPV_NEED);
+ if (pve == NULL) {
+ if (flags & PMAP_CANFAIL) {
+ error = ENOMEM;
+ goto out;
+ }
+ panic("pmap_enter: no pv entries available");
+ }
+ }
+ /* lock pvh when adding */
+ pmap_enter_pv(pvh, pve, pmap, va, ptp);
+ } else {
+
+ /* new mapping is not PG_PVLIST. free pve if we've got one */
+ pvh = NULL; /* ensure !PG_PVLIST */
+ if (pve)
+ pmap_free_pv(pmap, pve);
+ }
+
+enter_now:
+ /*
+ * at this point pvh is !NULL if we want the PG_PVLIST bit set
+ */
+
+ pmap->pm_stats.resident_count += resdelta;
+ pmap->pm_stats.wired_count += wireddelta;
+ if (ptp)
+ ptp->wire_count += ptpdelta;
+ npte = pa | protection_codes[prot] | PG_V;
+ if (pvh)
+ npte |= PG_PVLIST;
+ if (wired)
+ npte |= PG_W;
+ if (va < VM_MAXUSER_ADDRESS)
+ npte |= PG_u;
+ else if (va < VM_MAX_ADDRESS)
+ npte |= (PG_u | PG_RW); /* XXXCDC: no longer needed? */
+ if (pmap == pmap_kernel())
+ npte |= pmap_pg_g;
+
+ ptes[pl1_i(va)] = npte; /* zap! */
+
+ /*
+ * If we changed anything other than modified/used bits,
+ * flush the TLB. (is this overkill?)
+ */
+ if ((opte & ~(PG_M|PG_U)) != npte) {
+#if defined(MULTIPROCESSOR)
+ int32_t cpumask = 0;
+
+ pmap_tlb_shootdown(pmap, va, opte, &cpumask);
+ pmap_tlb_shootnow(cpumask);
+#else
+ /* Don't bother deferring in the single CPU case. */
+ if (pmap_is_curpmap(pmap))
+ pmap_update_pg(va);
+#endif
+ }
+
+ error = 0;
+
+out:
+ pmap_unmap_ptes(pmap);
+ PMAP_MAP_TO_HEAD_UNLOCK();
+
+ return error;
+}
+
+boolean_t
+pmap_get_physpage(va, level, paddrp)
+ vaddr_t va;
+ int level;
+ paddr_t *paddrp;
+{
+ struct vm_page *ptp;
+ struct pmap *kpm = pmap_kernel();
+
+ if (uvm.page_init_done == FALSE) {
+ /*
+ * we're growing the kernel pmap early (from
+ * uvm_pageboot_alloc()). this case must be
+ * handled a little differently.
+ */
+
+ if (uvm_page_physget(paddrp) == FALSE)
+ panic("pmap_get_physpage: out of memory");
+ *early_zero_pte = (*paddrp & PG_FRAME) | PG_V | PG_RW;
+ pmap_update_pg((vaddr_t)early_zerop);
+ memset(early_zerop, 0, PAGE_SIZE);
+ } else {
+ ptp = uvm_pagealloc(&kpm->pm_obj[level - 1],
+ ptp_va2o(va, level), NULL,
+ UVM_PGA_USERESERVE|UVM_PGA_ZERO);
+ if (ptp == NULL)
+ panic("pmap_get_physpage: out of memory");
+ ptp->flags &= ~PG_BUSY;
+ ptp->wire_count = 1;
+ *paddrp = VM_PAGE_TO_PHYS(ptp);
+ }
+ kpm->pm_stats.resident_count++;
+ return TRUE;
+}
+
+/*
+ * Allocate the amount of specified ptps for a ptp level, and populate
+ * all levels below accordingly, mapping virtual addresses starting at
+ * kva.
+ *
+ * Used by pmap_growkernel.
+ */
+void
+pmap_alloc_level(pdes, kva, lvl, needed_ptps)
+ pd_entry_t **pdes;
+ vaddr_t kva;
+ int lvl;
+ long *needed_ptps;
+{
+ unsigned long i;
+ vaddr_t va;
+ paddr_t pa;
+ unsigned long index, endindex;
+ int level;
+ pd_entry_t *pdep;
+
+ for (level = lvl; level > 1; level--) {
+ if (level == PTP_LEVELS)
+ pdep = pmap_kernel()->pm_pdir;
+ else
+ pdep = pdes[level - 2];
+ va = kva;
+ index = pl_i(kva, level);
+ endindex = index + needed_ptps[level - 1];
+ /*
+ * XXX special case for first time call.
+ */
+ if (nkptp[level - 1] != 0)
+ index++;
+ else
+ endindex--;
+
+ for (i = index; i <= endindex; i++) {
+ pmap_get_physpage(va, level - 1, &pa);
+ pdep[i] = pa | PG_RW | PG_V;
+ nkptp[level - 1]++;
+ va += nbpd[level - 1];
+ }
+ }
+}
+
+/*
+ * pmap_growkernel: increase usage of KVM space
+ *
+ * => we allocate new PTPs for the kernel and install them in all
+ * the pmaps on the system.
+ */
+
+static vaddr_t pmap_maxkvaddr = VM_MIN_KERNEL_ADDRESS;
+
+vaddr_t
+pmap_growkernel(maxkvaddr)
+ vaddr_t maxkvaddr;
+{
+ struct pmap *kpm = pmap_kernel(), *pm;
+ int s, i;
+ unsigned newpdes;
+ long needed_kptp[PTP_LEVELS], target_nptp, old;
+
+ if (maxkvaddr <= pmap_maxkvaddr)
+ return pmap_maxkvaddr;
+
+ maxkvaddr = round_pdr(maxkvaddr);
+ old = nkptp[PTP_LEVELS - 1];
+ /*
+ * This loop could be optimized more, but pmap_growkernel()
+ * is called infrequently.
+ */
+ for (i = PTP_LEVELS - 1; i >= 1; i--) {
+ target_nptp = pl_i(maxkvaddr, i + 1) -
+ pl_i(VM_MIN_KERNEL_ADDRESS, i + 1);
+ /*
+ * XXX only need to check toplevel.
+ */
+ if (target_nptp > nkptpmax[i])
+ panic("out of KVA space");
+ needed_kptp[i] = target_nptp - nkptp[i] + 1;
+ }
+
+
+ s = splhigh(); /* to be safe */
+ simple_lock(&kpm->pm_lock);
+ pmap_alloc_level(normal_pdes, pmap_maxkvaddr, PTP_LEVELS,
+ needed_kptp);
+
+ /*
+ * If the number of top level entries changed, update all
+ * pmaps.
+ */
+ if (needed_kptp[PTP_LEVELS - 1] != 0) {
+ newpdes = nkptp[PTP_LEVELS - 1] - old;
+ simple_lock(&pmaps_lock);
+ LIST_FOREACH(pm, &pmaps, pm_list) {
+ memcpy(&pm->pm_pdir[PDIR_SLOT_KERN + old],
+ &kpm->pm_pdir[PDIR_SLOT_KERN + old],
+ newpdes * sizeof (pd_entry_t));
+ }
+
+ /* Invalidate the PDP cache. */
+ pool_cache_invalidate(&pmap_pdp_cache);
+ pmap_pdp_cache_generation++;
+
+ simple_unlock(&pmaps_lock);
+ }
+ pmap_maxkvaddr = maxkvaddr;
+ simple_unlock(&kpm->pm_lock);
+ splx(s);
+
+ return maxkvaddr;
+}
+
+#ifdef DEBUG
+void pmap_dump(struct pmap *, vaddr_t, vaddr_t);
+
+/*
+ * pmap_dump: dump all the mappings from a pmap
+ *
+ * => caller should not be holding any pmap locks
+ */
+
+void
+pmap_dump(pmap, sva, eva)
+ struct pmap *pmap;
+ vaddr_t sva, eva;
+{
+ pt_entry_t *ptes, *pte;
+ pd_entry_t **pdes;
+ vaddr_t blkendva;
+
+ /*
+ * if end is out of range truncate.
+ * if (end == start) update to max.
+ */
+
+ if (eva > VM_MAXUSER_ADDRESS || eva <= sva)
+ eva = VM_MAXUSER_ADDRESS;
+
+ /*
+ * we lock in the pmap => pv_head direction
+ */
+
+ PMAP_MAP_TO_HEAD_LOCK();
+ pmap_map_ptes(pmap, &ptes, &pdes); /* locks pmap */
+
+ /*
+ * dumping a range of pages: we dump in PTP sized blocks (4MB)
+ */
+
+ for (/* null */ ; sva < eva ; sva = blkendva) {
+
+ /* determine range of block */
+ blkendva = round_pdr(sva+1);
+ if (blkendva > eva)
+ blkendva = eva;
+
+ /* valid block? */
+ if (!pmap_pdes_valid(sva, pdes, NULL))
+ continue;
+
+ pte = &ptes[pl1_i(sva)];
+ for (/* null */; sva < blkendva ; sva += PAGE_SIZE, pte++) {
+ if (!pmap_valid_entry(*pte))
+ continue;
+ printf("va %#lx -> pa %#lx (pte=%#lx)\n",
+ sva, *pte, *pte & PG_FRAME);
+ }
+ }
+ pmap_unmap_ptes(pmap);
+ PMAP_MAP_TO_HEAD_UNLOCK();
+}
+#endif
+
+/******************** TLB shootdown code ********************/
+
+
+void
+pmap_tlb_shootnow(int32_t cpumask)
+{
+#ifdef MULTIPROCESSOR
+ struct cpu_info *ci, *self;
+ CPU_INFO_ITERATOR cii;
+ int s;
+#ifdef DIAGNOSTIC
+ int count = 0;
+#endif
+#endif
+
+ if (cpumask == 0)
+ return;
+
+#ifdef MULTIPROCESSOR
+ self = curcpu();
+ s = splipi();
+ self->ci_tlb_ipi_mask = cpumask;
+#endif
+
+ pmap_do_tlb_shootdown(0); /* do *our* work. */
+
+#ifdef MULTIPROCESSOR
+ splx(s);
+
+ /*
+ * Send the TLB IPI to other CPUs pending shootdowns.
+ */
+ for (CPU_INFO_FOREACH(cii, ci)) {
+ if (ci == self)
+ continue;
+ if (cpumask & (1U << ci->ci_cpuid))
+ if (x86_send_ipi(ci, X86_IPI_TLB) != 0)
+ x86_atomic_clearbits_ul(&self->ci_tlb_ipi_mask,
+ (1U << ci->ci_cpuid));
+ }
+
+ while (self->ci_tlb_ipi_mask != 0)
+#ifdef DIAGNOSTIC
+ if (count++ > 10000000)
+ panic("TLB IPI rendezvous failed (mask %x)",
+ self->ci_tlb_ipi_mask);
+#else
+ /* XXX insert pause instruction */
+ ;
+#endif
+#endif
+}
+
+/*
+ * pmap_tlb_shootdown:
+ *
+ * Cause the TLB entry for pmap/va to be shot down.
+ */
+void
+pmap_tlb_shootdown(pmap, va, pte, cpumaskp)
+ pmap_t pmap;
+ vaddr_t va;
+ pt_entry_t pte;
+ int32_t *cpumaskp;
+{
+ struct cpu_info *ci, *self = curcpu();
+ struct pmap_tlb_shootdown_q *pq;
+ struct pmap_tlb_shootdown_job *pj;
+ CPU_INFO_ITERATOR cii;
+ int s;
+
+#ifdef LARGEPAGES
+ if (pte & PG_PS)
+ va &= PG_LGFRAME;
+#endif
+
+ if (pmap_initialized == FALSE || cpus_attached == 0) {
+ pmap_update_pg(va);
+ return;
+ }
+
+ s = splipi();
+#if 0
+ printf("dshootdown %lx\n", va);
+#endif
+
+ for (CPU_INFO_FOREACH(cii, ci)) {
+ /* Note: we queue shootdown events for ourselves here! */
+ if (pmap_is_active(pmap, ci->ci_cpuid) == 0)
+ continue;
+ if (ci != self && !(ci->ci_flags & CPUF_RUNNING))
+ continue;
+ pq = &pmap_tlb_shootdown_q[ci->ci_cpuid];
+#if defined(MULTIPROCESSOR)
+ simple_lock(&pq->pq_slock);
+#endif
+
+ /*
+ * If there's a global flush already queued, or a
+ * non-global flush, and this pte doesn't have the G
+ * bit set, don't bother.
+ */
+ if (pq->pq_flushg > 0 ||
+ (pq->pq_flushu > 0 && (pte & pmap_pg_g) == 0)) {
+#if defined(MULTIPROCESSOR)
+ simple_unlock(&pq->pq_slock);
+#endif
+ continue;
+ }
+
+#ifdef I386_CPU
+ /*
+ * i386 CPUs can't invalidate a single VA, only
+ * flush the entire TLB, so don't bother allocating
+ * jobs for them -- just queue a `flushu'.
+ *
+ * XXX note that this can be executed for non-i386
+ * when called * early (before identifycpu() has set
+ * cpu_class)
+ */
+ if (cpu_class == CPUCLASS_386) {
+ pq->pq_flushu++;
+ *cpumaskp |= 1U << ci->ci_cpuid;
+ continue;
+ }
+#endif
+
+ pj = pmap_tlb_shootdown_job_get(pq);
+ pq->pq_pte |= pte;
+ if (pj == NULL) {
+ /*
+ * Couldn't allocate a job entry.
+ * Kill it now for this cpu, unless the failure
+ * was due to too many pending flushes; otherwise,
+ * tell other cpus to kill everything..
+ */
+ if (ci == self && pq->pq_count < PMAP_TLB_MAXJOBS) {
+ pmap_update_pg(va);
+#if defined(MULTIPROCESSOR)
+ simple_unlock(&pq->pq_slock);
+#endif
+ continue;
+ } else {
+ if (pq->pq_pte & pmap_pg_g)
+ pq->pq_flushg++;
+ else
+ pq->pq_flushu++;
+ /*
+ * Since we've nailed the whole thing,
+ * drain the job entries pending for that
+ * processor.
+ */
+ pmap_tlb_shootdown_q_drain(pq);
+ *cpumaskp |= 1U << ci->ci_cpuid;
+ }
+ } else {
+ pj->pj_pmap = pmap;
+ pj->pj_va = va;
+ pj->pj_pte = pte;
+ TAILQ_INSERT_TAIL(&pq->pq_head, pj, pj_list);
+ *cpumaskp |= 1U << ci->ci_cpuid;
+ }
+#if defined(MULTIPROCESSOR)
+ simple_unlock(&pq->pq_slock);
+#endif
+ }
+ splx(s);
+}
+
+/*
+ * pmap_do_tlb_shootdown:
+ *
+ * Process pending TLB shootdown operations for this processor.
+ */
+void
+pmap_do_tlb_shootdown(struct cpu_info *self)
+{
+ u_long cpu_id = cpu_number();
+ struct pmap_tlb_shootdown_q *pq = &pmap_tlb_shootdown_q[cpu_id];
+ struct pmap_tlb_shootdown_job *pj;
+ int s;
+#ifdef MULTIPROCESSOR
+ struct cpu_info *ci;
+ CPU_INFO_ITERATOR cii;
+#endif
+
+ s = splipi();
+
+#ifdef MULTIPROCESSOR
+ simple_lock(&pq->pq_slock);
+#endif
+
+ if (pq->pq_flushg) {
+ COUNT(flushg);
+ tlbflushg();
+ pq->pq_flushg = 0;
+ pq->pq_flushu = 0;
+ pmap_tlb_shootdown_q_drain(pq);
+ } else {
+ /*
+ * TLB flushes for PTEs with PG_G set may be in the queue
+ * after a flushu, they need to be dealt with.
+ */
+ if (pq->pq_flushu) {
+ COUNT(flushu);
+ tlbflush();
+ }
+ while ((pj = TAILQ_FIRST(&pq->pq_head)) != NULL) {
+ TAILQ_REMOVE(&pq->pq_head, pj, pj_list);
+
+ if ((!pq->pq_flushu && pmap_is_curpmap(pj->pj_pmap)) ||
+ (pj->pj_pte & pmap_pg_g))
+ pmap_update_pg(pj->pj_va);
+
+ pmap_tlb_shootdown_job_put(pq, pj);
+ }
+
+ pq->pq_flushu = pq->pq_pte = 0;
+ }
+
+#ifdef MULTIPROCESSOR
+ for (CPU_INFO_FOREACH(cii, ci))
+ x86_atomic_clearbits_ul(&ci->ci_tlb_ipi_mask,
+ (1U << cpu_id));
+ simple_unlock(&pq->pq_slock);
+#endif
+
+ splx(s);
+}
+
+
+/*
+ * pmap_tlb_shootdown_q_drain:
+ *
+ * Drain a processor's TLB shootdown queue. We do not perform
+ * the shootdown operations. This is merely a convenience
+ * function.
+ *
+ * Note: We expect the queue to be locked.
+ */
+void
+pmap_tlb_shootdown_q_drain(pq)
+ struct pmap_tlb_shootdown_q *pq;
+{
+ struct pmap_tlb_shootdown_job *pj;
+
+ while ((pj = TAILQ_FIRST(&pq->pq_head)) != NULL) {
+ TAILQ_REMOVE(&pq->pq_head, pj, pj_list);
+ pmap_tlb_shootdown_job_put(pq, pj);
+ }
+ pq->pq_pte = 0;
+}
+
+/*
+ * pmap_tlb_shootdown_job_get:
+ *
+ * Get a TLB shootdown job queue entry. This places a limit on
+ * the number of outstanding jobs a processor may have.
+ *
+ * Note: We expect the queue to be locked.
+ */
+struct pmap_tlb_shootdown_job *
+pmap_tlb_shootdown_job_get(pq)
+ struct pmap_tlb_shootdown_q *pq;
+{
+ struct pmap_tlb_shootdown_job *pj;
+
+ if (pq->pq_count >= PMAP_TLB_MAXJOBS)
+ return (NULL);
+
+#ifdef MULTIPROCESSOR
+ simple_lock(&pmap_tlb_shootdown_job_lock);
+#endif
+ if (pj_free == NULL) {
+#ifdef MULTIPROCESSOR
+ simple_unlock(&pmap_tlb_shootdown_job_lock);
+#endif
+ return NULL;
+ }
+ pj = &pj_free->pja_job;
+ pj_free =
+ (union pmap_tlb_shootdown_job_al *)pj_free->pja_job.pj_nextfree;
+#ifdef MULTIPROCESSOR
+ simple_unlock(&pmap_tlb_shootdown_job_lock);
+#endif
+
+ pq->pq_count++;
+ return (pj);
+}
+
+/*
+ * pmap_tlb_shootdown_job_put:
+ *
+ * Put a TLB shootdown job queue entry onto the free list.
+ *
+ * Note: We expect the queue to be locked.
+ */
+void
+pmap_tlb_shootdown_job_put(pq, pj)
+ struct pmap_tlb_shootdown_q *pq;
+ struct pmap_tlb_shootdown_job *pj;
+{
+
+#ifdef DIAGNOSTIC
+ if (pq->pq_count == 0)
+ panic("pmap_tlb_shootdown_job_put: queue length inconsistency");
+#endif
+#ifdef MULTIPROCESSOR
+ simple_lock(&pmap_tlb_shootdown_job_lock);
+#endif
+ pj->pj_nextfree = &pj_free->pja_job;
+ pj_free = (union pmap_tlb_shootdown_job_al *)pj;
+#ifdef MULTIPROCESSOR
+ simple_unlock(&pmap_tlb_shootdown_job_lock);
+#endif
+
+ pq->pq_count--;
+}
+
+void
+pmap_virtual_space(vaddr_t *vstartp, vaddr_t *vendp)
+{
+ *vstartp = virtual_avail;
+ *vendp = VM_MAX_KERNEL_ADDRESS;
+}
diff --git a/sys/arch/amd64/amd64/process_machdep.c b/sys/arch/amd64/amd64/process_machdep.c
new file mode 100644
index 00000000000..cb8650eb822
--- /dev/null
+++ b/sys/arch/amd64/amd64/process_machdep.c
@@ -0,0 +1,193 @@
+/* $OpenBSD: process_machdep.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: process_machdep.c,v 1.1 2003/04/26 18:39:31 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * This file may seem a bit stylized, but that so that it's easier to port.
+ * Functions to be implemented here are:
+ *
+ * process_read_regs(proc, regs)
+ * Get the current user-visible register set from the process
+ * and copy it into the regs structure (<machine/reg.h>).
+ * The process is stopped at the time read_regs is called.
+ *
+ * process_write_regs(proc, regs)
+ * Update the current register set from the passed in regs
+ * structure. Take care to avoid clobbering special CPU
+ * registers or privileged bits in the PSL.
+ * The process is stopped at the time write_regs is called.
+ *
+ * process_sstep(proc)
+ * Arrange for the process to trap after executing a single instruction.
+ *
+ * process_set_pc(proc)
+ * Set the process's program counter.
+ */
+
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/vnode.h>
+#include <sys/ptrace.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/psl.h>
+#include <machine/reg.h>
+#include <machine/segments.h>
+#include <machine/fpu.h>
+
+static __inline struct trapframe *process_frame(struct proc *);
+static __inline struct fxsave64 *process_fpframe(struct proc *);
+#if 0
+static __inline int verr_gdt(struct pmap *, int sel);
+static __inline int verr_ldt(struct pmap *, int sel);
+#endif
+
+static __inline struct trapframe *
+process_frame(struct proc *p)
+{
+
+ return (p->p_md.md_regs);
+}
+
+static __inline struct fxsave64 *
+process_fpframe(struct proc *p)
+{
+
+ return (&p->p_addr->u_pcb.pcb_savefpu.fp_fxsave);
+}
+
+int
+process_read_regs(struct proc *p, struct reg *regs)
+{
+ struct trapframe *tf = process_frame(p);
+
+ memcpy(regs, tf, sizeof (*regs));
+
+ return (0);
+}
+
+int
+process_read_fpregs(struct proc *p, struct fpreg *regs)
+{
+ struct fxsave64 *frame = process_fpframe(p);
+
+ if (p->p_md.md_flags & MDP_USEDFPU) {
+ fpusave_proc(p, 1);
+ } else {
+ u_int16_t cw;
+
+ /*
+ * Fake a FNINIT.
+ * The initial control word was already set by setregs(), so
+ * save it temporarily.
+ */
+ cw = frame->fx_fcw;
+ memset(frame, 0, sizeof(*regs));
+ frame->fx_fcw = cw;
+ frame->fx_fsw = 0x0000;
+ frame->fx_ftw = 0xff;
+ p->p_md.md_flags |= MDP_USEDFPU;
+ }
+
+ memcpy(&regs->fxstate, frame, sizeof(*regs));
+ return (0);
+}
+
+int
+process_write_regs(struct proc *p, struct reg *regp)
+{
+ struct trapframe *tf = process_frame(p);
+ long *regs = regp->regs;
+
+ /*
+ * Check for security violations.
+ */
+ if (((regs[_REG_RFL] ^ tf->tf_rflags) & PSL_USERSTATIC) != 0 ||
+ !USERMODE(regs[_REG_CS], regs[_REG_RFL]))
+ return (EINVAL);
+
+ memcpy(tf, regs, sizeof (*tf));
+
+ return (0);
+}
+
+int
+process_write_fpregs(struct proc *p, struct fpreg *regs)
+{
+ struct fxsave64 *frame = process_fpframe(p);
+
+ if (p->p_md.md_flags & MDP_USEDFPU) {
+ fpusave_proc(p, 0);
+ } else {
+ p->p_md.md_flags |= MDP_USEDFPU;
+ }
+
+ memcpy(frame, &regs->fxstate, sizeof(*regs));
+ return (0);
+}
+
+int
+process_sstep(struct proc *p, int sstep)
+{
+ struct trapframe *tf = process_frame(p);
+
+ if (sstep)
+ tf->tf_rflags |= PSL_T;
+ else
+ tf->tf_rflags &= ~PSL_T;
+
+ return (0);
+}
+
+int
+process_set_pc(struct proc *p, caddr_t addr)
+{
+ struct trapframe *tf = process_frame(p);
+
+ if ((u_int64_t)addr > VM_MAXUSER_ADDRESS)
+ return EINVAL;
+ tf->tf_rip = (u_int64_t)addr;
+
+ return (0);
+}
diff --git a/sys/arch/amd64/amd64/softintr.c b/sys/arch/amd64/amd64/softintr.c
new file mode 100644
index 00000000000..57ce947e086
--- /dev/null
+++ b/sys/arch/amd64/amd64/softintr.c
@@ -0,0 +1,168 @@
+/* $OpenBSD: softintr.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: softintr.c,v 1.1 2003/02/26 21:26:12 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * Generic soft interrupt implementation for NetBSD/x86.
+ */
+
+#include <sys/param.h>
+#include <sys/malloc.h>
+
+#include <machine/intr.h>
+
+#include <uvm/uvm_extern.h>
+
+struct x86_soft_intr x86_soft_intrs[X86_NSOFTINTR];
+
+const int x86_soft_intr_to_ssir[X86_NSOFTINTR] = {
+ SIR_CLOCK,
+ SIR_NET,
+ SIR_SERIAL,
+};
+
+/*
+ * softintr_init:
+ *
+ * Initialize the software interrupt system.
+ */
+void
+softintr_init(void)
+{
+ struct x86_soft_intr *si;
+ int i;
+
+ for (i = 0; i < X86_NSOFTINTR; i++) {
+ si = &x86_soft_intrs[i];
+ TAILQ_INIT(&si->softintr_q);
+ simple_lock_init(&si->softintr_slock);
+ si->softintr_ssir = x86_soft_intr_to_ssir[i];
+ }
+}
+
+/*
+ * softintr_dispatch:
+ *
+ * Process pending software interrupts.
+ */
+void
+softintr_dispatch(int which)
+{
+ struct x86_soft_intr *si = &x86_soft_intrs[which];
+ struct x86_soft_intrhand *sih;
+ int s;
+
+ for (;;) {
+ x86_softintr_lock(si, s);
+ sih = TAILQ_FIRST(&si->softintr_q);
+ if (sih == NULL) {
+ x86_softintr_unlock(si, s);
+ break;
+ }
+ TAILQ_REMOVE(&si->softintr_q, sih, sih_q);
+ sih->sih_pending = 0;
+ x86_softintr_unlock(si, s);
+
+ uvmexp.softs++;
+ (*sih->sih_fn)(sih->sih_arg);
+ }
+}
+
+/*
+ * softintr_establish: [interface]
+ *
+ * Register a software interrupt handler.
+ */
+void *
+softintr_establish(int ipl, void (*func)(void *), void *arg)
+{
+ struct x86_soft_intr *si;
+ struct x86_soft_intrhand *sih;
+ int which;
+
+ switch (ipl) {
+ case IPL_SOFTCLOCK:
+ which = X86_SOFTINTR_SOFTCLOCK;
+ break;
+
+ case IPL_SOFTNET:
+ which = X86_SOFTINTR_SOFTNET;
+ break;
+
+ case IPL_TTY:
+ case IPL_SOFTSERIAL:
+ which = X86_SOFTINTR_SOFTSERIAL;
+ break;
+
+ default:
+ panic("softintr_establish");
+ }
+
+ si = &x86_soft_intrs[which];
+
+ sih = malloc(sizeof(*sih), M_DEVBUF, M_NOWAIT);
+ if (__predict_true(sih != NULL)) {
+ sih->sih_intrhead = si;
+ sih->sih_fn = func;
+ sih->sih_arg = arg;
+ sih->sih_pending = 0;
+ }
+ return (sih);
+}
+
+/*
+ * softintr_disestablish: [interface]
+ *
+ * Unregister a software interrupt handler.
+ */
+void
+softintr_disestablish(void *arg)
+{
+ struct x86_soft_intrhand *sih = arg;
+ struct x86_soft_intr *si = sih->sih_intrhead;
+ int s;
+
+ x86_softintr_lock(si, s);
+ if (sih->sih_pending) {
+ TAILQ_REMOVE(&si->softintr_q, sih, sih_q);
+ sih->sih_pending = 0;
+ }
+ x86_softintr_unlock(si, s);
+
+ free(sih, M_DEVBUF);
+}
diff --git a/sys/arch/amd64/amd64/spl.S b/sys/arch/amd64/amd64/spl.S
new file mode 100644
index 00000000000..c9b674ff648
--- /dev/null
+++ b/sys/arch/amd64/amd64/spl.S
@@ -0,0 +1,184 @@
+/* $NetBSD: spl.S,v 1.1 2003/04/26 18:39:32 fvdl Exp $ */
+
+/*
+ * Copyright (c) 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Frank van der Linden for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#define ALIGN_TEXT .align 16,0x90
+
+#include <machine/asm.h>
+#include <machine/psl.h>
+#include <machine/trap.h>
+#include <machine/segments.h>
+#include <machine/frameasm.h>
+
+#include "assym.h"
+
+ .text
+
+#if 0
+#if defined(PROF) || defined(GPROF)
+/*
+ * XXXX TODO
+ */
+ .globl _C_LABEL(splhigh), _C_LABEL(splx)
+
+ ALIGN_TEXT
+_C_LABEL(splhigh):
+ movl $IPL_HIGH,%eax
+ xchgl %eax,CPUVAR(ILEVEL)
+ ret
+
+ ALIGN_TEXT
+_C_LABEL(splx):
+ movl 4(%esp),%eax
+ movl %eax,CPUVAR(ILEVEL)
+ testl %eax,%eax
+ jnz _C_LABEL(Xspllower)
+ ret
+#endif /* PROF || GPROF */
+#endif
+
+/*
+ * Process pending interrupts.
+ *
+ * Important registers:
+ * ebx - cpl
+ * r13 - address to resume loop at
+ *
+ * It is important that the bit scan instruction is bsr, it will get
+ * the highest 2 bits (currently the IPI and clock handlers) first,
+ * to avoid deadlocks where one CPU sends an IPI, another one is at
+ * splipi() and defers it, lands in here via splx(), and handles
+ * a lower-prio one first, which needs to take the kernel lock -->
+ * the sending CPU will never see the that CPU accept the IPI
+ * (see pmap_tlb_shootnow).
+ */
+IDTVEC(spllower)
+ pushq %rbx
+ pushq %r13
+ pushq %r12
+ movl %edi,%ebx
+ leaq 1f(%rip),%r13 # address to resume loop at
+1: movl %ebx,%eax # get cpl
+ movl CPUVAR(IUNMASK)(,%rax,4),%eax
+ cli
+ andl CPUVAR(IPENDING),%eax # any non-masked bits left?
+ jz 2f
+ sti
+ bsrl %eax,%eax
+ btrl %eax,CPUVAR(IPENDING)
+ jnc 1b
+ movq CPUVAR(ISOURCES)(,%rax,8),%rax
+ jmp *IS_RECURSE(%rax)
+2:
+ movl %ebx,CPUVAR(ILEVEL)
+ sti
+ popq %r12
+ popq %r13
+ popq %rbx
+ ret
+
+/*
+ * Handle return from interrupt after device handler finishes.
+ *
+ * Important registers:
+ * ebx - cpl to restore
+ * r13 - address to resume loop at
+ */
+IDTVEC(doreti)
+ popq %rbx # get previous priority
+ decl CPUVAR(IDEPTH)
+ leaq 1f(%rip),%r13
+1: movl %ebx,%eax
+ movl CPUVAR(IUNMASK)(,%rax,4),%eax
+ cli
+ andl CPUVAR(IPENDING),%eax
+ jz 2f
+ sti
+ bsrl %eax,%eax # slow, but not worth optimizing
+ btrl %eax,CPUVAR(IPENDING)
+ jnc 1b # some intr cleared the in-memory bit
+ movq CPUVAR(ISOURCES)(,%rax, 8),%rax
+ jmp *IS_RESUME(%rax)
+2: /* Check for ASTs on exit to user mode. */
+ movl %ebx,CPUVAR(ILEVEL)
+5: CHECK_ASTPENDING(%r11)
+ je 3f
+ testb $SEL_RPL,TF_CS(%rsp)
+ jz 3f
+4: CLEAR_ASTPENDING(%r11)
+ sti
+ movl $T_ASTFLT,TF_TRAPNO(%rsp) /* XXX undo later.. */
+ /* Pushed T_ASTFLT into tf_trapno on entry. */
+ call _C_LABEL(trap)
+ cli
+ jmp 5b
+3: INTRFASTEXIT
diff --git a/sys/arch/amd64/amd64/swapgeneric.c b/sys/arch/amd64/amd64/swapgeneric.c
new file mode 100644
index 00000000000..cf0a65e8f0a
--- /dev/null
+++ b/sys/arch/amd64/amd64/swapgeneric.c
@@ -0,0 +1,57 @@
+/* $OpenBSD: swapgeneric.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: swapgeneric.c,v 1.12 1996/05/03 19:42:28 christos Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)swapgeneric.c 5.5 (Berkeley) 5/9/91
+ */
+
+/*
+ * fake swapgeneric.c -- should do this differently.
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+
+int (*mountroot)(void) = NULL;
+
+dev_t rootdev = NODEV;
+dev_t dumpdev = NODEV;
+
+struct swdevt swdevt[] = {
+ { NODEV, 0, 0 }, /* to be filled in */
+ { NODEV, 0, 0 }
+};
diff --git a/sys/arch/amd64/amd64/sys_machdep.c b/sys/arch/amd64/amd64/sys_machdep.c
new file mode 100644
index 00000000000..098c523ea68
--- /dev/null
+++ b/sys/arch/amd64/amd64/sys_machdep.c
@@ -0,0 +1,466 @@
+/* $OpenBSD: sys_machdep.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: sys_machdep.c,v 1.1 2003/04/26 18:39:32 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * XXXfvdl check USER_LDT
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/uio.h>
+#include <sys/kernel.h>
+#include <sys/buf.h>
+#include <sys/signal.h>
+
+#include <sys/mount.h>
+#include <sys/syscallargs.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/gdt.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
+#include <machine/sysarch.h>
+#include <machine/mtrr.h>
+
+#if defined(PERFCTRS) && 0
+#include <machine/pmc.h>
+#endif
+
+extern struct vm_map *kernel_map;
+
+#if 0
+int x86_64_get_ioperm(struct proc *, void *, register_t *);
+int x86_64_set_ioperm(struct proc *, void *, register_t *);
+#endif
+int x86_64_iopl(struct proc *, void *, register_t *);
+int x86_64_get_mtrr(struct proc *, void *, register_t *);
+int x86_64_set_mtrr(struct proc *, void *, register_t *);
+
+/* XXXfvdl disabled USER_LDT stuff until I check this stuff */
+
+#if defined(USER_LDT) && 0
+int
+x86_64_get_ldt(p, args, retval)
+ struct proc *p;
+ void *args;
+ register_t *retval;
+{
+ int error;
+ pmap_t pmap = p->p_vmspace->vm_map.pmap;
+ int nldt, num;
+ union descriptor *lp;
+ struct x86_64_get_ldt_args ua;
+
+ if ((error = copyin(args, &ua, sizeof(ua))) != 0)
+ return (error);
+
+#ifdef LDT_DEBUG
+ printf("x86_64_get_ldt: start=%d num=%d descs=%p\n", ua.start,
+ ua.num, ua.desc);
+#endif
+
+ if (ua.start < 0 || ua.num < 0)
+ return (EINVAL);
+
+ /*
+ * XXX LOCKING.
+ */
+
+ if (pmap->pm_flags & PMF_USER_LDT) {
+ nldt = pmap->pm_ldt_len;
+ lp = pmap->pm_ldt;
+ } else {
+ nldt = NLDT;
+ lp = ldt;
+ }
+
+ if (ua.start > nldt)
+ return (EINVAL);
+
+ lp += ua.start;
+ num = min(ua.num, nldt - ua.start);
+
+ error = copyout(lp, ua.desc, num * sizeof(union descriptor));
+ if (error)
+ return (error);
+
+ *retval = num;
+ return (0);
+}
+
+int
+x86_64_set_ldt(p, args, retval)
+ struct proc *p;
+ void *args;
+ register_t *retval;
+{
+ int error, i, n;
+ struct pcb *pcb = &p->p_addr->u_pcb;
+ pmap_t pmap = p->p_vmspace->vm_map.pmap;
+ struct x86_64_set_ldt_args ua;
+ union descriptor desc;
+
+ if ((error = copyin(args, &ua, sizeof(ua))) != 0)
+ return (error);
+
+#ifdef LDT_DEBUG
+ printf("x86_64_set_ldt: start=%d num=%d descs=%p\n", ua.start,
+ ua.num, ua.desc);
+#endif
+
+ if (ua.start < 0 || ua.num < 0)
+ return (EINVAL);
+ if (ua.start > 8192 || (ua.start + ua.num) > 8192)
+ return (EINVAL);
+
+ /*
+ * XXX LOCKING
+ */
+
+ /* allocate user ldt */
+ if (pmap->pm_ldt == 0 || (ua.start + ua.num) > pmap->pm_ldt_len) {
+ size_t old_len, new_len;
+ union descriptor *old_ldt, *new_ldt;
+
+ if (pmap->pm_flags & PMF_USER_LDT) {
+ old_len = pmap->pm_ldt_len * sizeof(union descriptor);
+ old_ldt = pmap->pm_ldt;
+ } else {
+ old_len = NLDT * sizeof(union descriptor);
+ old_ldt = ldt;
+ pmap->pm_ldt_len = 512;
+ }
+ while ((ua.start + ua.num) > pmap->pm_ldt_len)
+ pmap->pm_ldt_len *= 2;
+ new_len = pmap->pm_ldt_len * sizeof(union descriptor);
+ new_ldt = (union descriptor *)uvm_km_alloc(kernel_map, new_len);
+ memcpy(new_ldt, old_ldt, old_len);
+ memset((caddr_t)new_ldt + old_len, 0, new_len - old_len);
+ pmap->pm_ldt = new_ldt;
+
+ if (pmap->pm_flags & PCB_USER_LDT)
+ ldt_free(pmap);
+ else
+ pmap->pm_flags |= PCB_USER_LDT;
+ ldt_alloc(pmap, new_ldt, new_len);
+ pcb->pcb_ldt_sel = pmap->pm_ldt_sel;
+ if (pcb == curpcb)
+ lldt(pcb->pcb_ldt_sel);
+
+ /*
+ * XXX Need to notify other processors which may be
+ * XXX currently using this pmap that they need to
+ * XXX re-load the LDT.
+ */
+
+ if (old_ldt != ldt)
+ uvm_km_free(kernel_map, (vaddr_t)old_ldt, old_len);
+#ifdef LDT_DEBUG
+ printf("x86_64_set_ldt(%d): new_ldt=%p\n", p->p_pid, new_ldt);
+#endif
+ }
+
+ if (pcb == curpcb)
+ savectx(curpcb);
+ error = 0;
+
+ /* Check descriptors for access violations. */
+ for (i = 0, n = ua.start; i < ua.num; i++, n++) {
+ if ((error = copyin(&ua.desc[i], &desc, sizeof(desc))) != 0)
+ return (error);
+
+ switch (desc.sd.sd_type) {
+ case SDT_SYSNULL:
+ desc.sd.sd_p = 0;
+ break;
+ case SDT_SYS286CGT:
+ case SDT_SYS386CGT:
+ /*
+ * Only allow call gates targeting a segment
+ * in the LDT or a user segment in the fixed
+ * part of the gdt. Segments in the LDT are
+ * constrained (below) to be user segments.
+ */
+ if (desc.gd.gd_p != 0 && !ISLDT(desc.gd.gd_selector) &&
+ ((IDXSEL(desc.gd.gd_selector) >= NGDT) ||
+ (gdt[IDXSEL(desc.gd.gd_selector)].sd.sd_dpl !=
+ SEL_UPL)))
+ return (EACCES);
+ break;
+ case SDT_MEMEC:
+ case SDT_MEMEAC:
+ case SDT_MEMERC:
+ case SDT_MEMERAC:
+ /* Must be "present" if executable and conforming. */
+ if (desc.sd.sd_p == 0)
+ return (EACCES);
+ break;
+ case SDT_MEMRO:
+ case SDT_MEMROA:
+ case SDT_MEMRW:
+ case SDT_MEMRWA:
+ case SDT_MEMROD:
+ case SDT_MEMRODA:
+ case SDT_MEMRWD:
+ case SDT_MEMRWDA:
+ case SDT_MEME:
+ case SDT_MEMEA:
+ case SDT_MEMER:
+ case SDT_MEMERA:
+ break;
+ default:
+ /* Only care if it's present. */
+ if (desc.sd.sd_p != 0)
+ return (EACCES);
+ break;
+ }
+
+ if (desc.sd.sd_p != 0) {
+ /* Only user (ring-3) descriptors may be present. */
+ if (desc.sd.sd_dpl != SEL_UPL)
+ return (EACCES);
+ }
+ }
+
+ /* Now actually replace the descriptors. */
+ for (i = 0, n = ua.start; i < ua.num; i++, n++) {
+ if ((error = copyin(&ua.desc[i], &desc, sizeof(desc))) != 0)
+ goto out;
+
+ pmap->pm_ldt[n] = desc;
+ }
+
+ *retval = ua.start;
+
+out:
+ return (error);
+}
+#endif /* USER_LDT */
+
+int
+x86_64_iopl(struct proc *p, void *args, register_t *retval)
+{
+ int error;
+ struct trapframe *tf = p->p_md.md_regs;
+ struct x86_64_iopl_args ua;
+
+ if (securelevel > 1)
+ return EPERM;
+
+ if ((error = suser(p, 0)) != 0)
+ return error;
+
+ if ((error = copyin(args, &ua, sizeof(ua))) != 0)
+ return error;
+
+ if (ua.iopl)
+ tf->tf_rflags |= PSL_IOPL;
+ else
+ tf->tf_rflags &= ~PSL_IOPL;
+
+ return 0;
+}
+
+#if 0
+
+int
+x86_64_get_ioperm(p, args, retval)
+ struct proc *p;
+ void *args;
+ register_t *retval;
+{
+ int error;
+ struct pcb *pcb = &p->p_addr->u_pcb;
+ struct x86_64_get_ioperm_args ua;
+
+ if ((error = copyin(args, &ua, sizeof(ua))) != 0)
+ return (error);
+
+ return copyout(pcb->pcb_iomap, ua.iomap, sizeof(pcb->pcb_iomap));
+}
+
+int
+x86_64_set_ioperm(p, args, retval)
+ struct proc *p;
+ void *args;
+ register_t *retval;
+{
+ int error;
+ struct pcb *pcb = &p->p_addr->u_pcb;
+ struct x86_64_set_ioperm_args ua;
+
+ if (securelevel > 1)
+ return EPERM;
+
+ if ((error = suser(p, 0)) != 0)
+ return error;
+
+ if ((error = copyin(args, &ua, sizeof(ua))) != 0)
+ return (error);
+
+ return copyin(ua.iomap, pcb->pcb_iomap, sizeof(pcb->pcb_iomap));
+}
+
+#endif
+
+#ifdef MTRR
+
+int
+x86_64_get_mtrr(struct proc *p, void *args, register_t *retval)
+{
+ struct x86_64_get_mtrr_args ua;
+ int error, n;
+
+ if (mtrr_funcs == NULL)
+ return ENOSYS;
+
+ error = copyin(args, &ua, sizeof ua);
+ if (error != 0)
+ return error;
+
+ error = copyin(ua.n, &n, sizeof n);
+ if (error != 0)
+ return error;
+
+ error = mtrr_get(ua.mtrrp, &n, p, MTRR_GETSET_USER);
+
+ copyout(&n, ua.n, sizeof (int));
+
+ return error;
+}
+
+int
+x86_64_set_mtrr(struct proc *p, void *args, register_t *retval)
+{
+ int error, n;
+ struct x86_64_set_mtrr_args ua;
+
+ if (mtrr_funcs == NULL)
+ return ENOSYS;
+
+ error = suser(p, 0);
+ if (error != 0)
+ return error;
+
+ error = copyin(args, &ua, sizeof ua);
+ if (error != 0)
+ return error;
+
+ error = copyin(ua.n, &n, sizeof n);
+ if (error != 0)
+ return error;
+
+ error = mtrr_set(ua.mtrrp, &n, p, MTRR_GETSET_USER);
+ if (n != 0)
+ mtrr_commit();
+
+ copyout(&n, ua.n, sizeof n);
+
+ return error;
+}
+#endif
+
+int
+sys_sysarch(struct proc *p, void *v, register_t *retval)
+{
+ struct sys_sysarch_args /* {
+ syscallarg(int) op;
+ syscallarg(void *) parms;
+ } */ *uap = v;
+ int error = 0;
+
+ switch(SCARG(uap, op)) {
+#if defined(USER_LDT) && 0
+ case X86_64_GET_LDT:
+ error = x86_64_get_ldt(p, SCARG(uap, parms), retval);
+ break;
+
+ case X86_64_SET_LDT:
+ error = x86_64_set_ldt(p, SCARG(uap, parms), retval);
+ break;
+#endif
+ case X86_64_IOPL:
+ error = x86_64_iopl(p, SCARG(uap, parms), retval);
+ break;
+
+#if 0
+ case X86_64_GET_IOPERM:
+ error = x86_64_get_ioperm(p, SCARG(uap, parms), retval);
+ break;
+
+ case X86_64_SET_IOPERM:
+ error = x86_64_set_ioperm(p, SCARG(uap, parms), retval);
+ break;
+#endif
+#ifdef MTRR
+ case X86_64_GET_MTRR:
+ error = x86_64_get_mtrr(p, SCARG(uap, parms), retval);
+ break;
+ case X86_64_SET_MTRR:
+ error = x86_64_set_mtrr(p, SCARG(uap, parms), retval);
+ break;
+#endif
+
+#if defined(PERFCTRS) && 0
+ case X86_64_PMC_INFO:
+ error = pmc_info(p, SCARG(uap, parms), retval);
+ break;
+
+ case X86_64_PMC_STARTSTOP:
+ error = pmc_startstop(p, SCARG(uap, parms), retval);
+ break;
+
+ case X86_64_PMC_READ:
+ error = pmc_read(p, SCARG(uap, parms), retval);
+ break;
+#endif
+ default:
+ error = EINVAL;
+ break;
+ }
+ return (error);
+}
diff --git a/sys/arch/amd64/amd64/syscall.c b/sys/arch/amd64/amd64/syscall.c
new file mode 100644
index 00000000000..5c134c8f2b4
--- /dev/null
+++ b/sys/arch/amd64/amd64/syscall.c
@@ -0,0 +1,341 @@
+/* $OpenBSD: syscall.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: syscall.c,v 1.1 2003/04/26 18:39:32 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/signal.h>
+#ifdef KTRACE
+#include <sys/ktrace.h>
+#endif
+#ifdef SYSTRACE
+#include <sys/systrace.h>
+#endif
+#include <sys/syscall.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/cpu.h>
+#include <machine/psl.h>
+#include <machine/userret.h>
+
+void syscall_intern(struct proc *);
+void syscall_plain(struct trapframe);
+void syscall_fancy(struct trapframe);
+
+void
+syscall_intern(p)
+ struct proc *p;
+{
+#ifdef KTRACE
+ if (p->p_traceflag & (KTRFAC_SYSCALL | KTRFAC_SYSRET)) {
+ p->p_md.md_syscall = syscall_fancy;
+ return;
+ }
+#endif
+#ifdef SYSTRACE
+ if (ISSET(p->p_flag, P_SYSTRACE)) {
+ p->p_md.md_syscall = syscall_fancy;
+ return;
+ }
+#endif
+ p->p_md.md_syscall = syscall_plain;
+}
+
+/*
+ * syscall(frame):
+ * System call request from POSIX system call gate interface to kernel.
+ * Like trap(), argument is call by reference.
+ */
+void
+syscall_plain(frame)
+ struct trapframe frame;
+{
+ caddr_t params;
+ const struct sysent *callp;
+ struct proc *p;
+ int error;
+ int nsys;
+ size_t argsize, argoff;
+ register_t code, args[9], rval[2], *argp;
+
+
+ uvmexp.syscalls++;
+ p = curproc;
+
+ code = frame.tf_rax;
+ nsys = p->p_emul->e_nsysent;
+ callp = p->p_emul->e_sysent;
+ argoff = 0;
+ argp = &args[0];
+
+ switch (code) {
+ case SYS_syscall:
+ case SYS___syscall:
+ /*
+ * Code is first argument, followed by actual args.
+ */
+ code = frame.tf_rdi;
+ argp = &args[1];
+ argoff = 1;
+ break;
+ default:
+ break;
+ }
+
+ if (code < 0 || code >= nsys)
+ callp += p->p_emul->e_nosys;
+ else
+ callp += code;
+
+ argsize = (callp->sy_argsize >> 3) + argoff;
+ if (argsize) {
+ switch (MIN(argsize, 6)) {
+ case 6:
+ args[5] = frame.tf_r9;
+ case 5:
+ args[4] = frame.tf_r8;
+ case 4:
+ args[3] = frame.tf_r10;
+ case 3:
+ args[2] = frame.tf_rdx;
+ case 2:
+ args[1] = frame.tf_rsi;
+ case 1:
+ args[0] = frame.tf_rdi;
+ break;
+ default:
+ panic("impossible syscall argsize");
+ }
+ if (argsize > 6) {
+ argsize -= 6;
+ params = (caddr_t)frame.tf_rsp + sizeof(register_t);
+ error = copyin(params, (caddr_t)&args[6],
+ argsize << 3);
+ if (error != 0)
+ goto bad;
+ }
+ }
+
+#ifdef SYSCALL_DEBUG
+ scdebug_call(p, code, argp);
+#endif /* SYSCALL_DEBUG */
+
+ rval[0] = 0;
+ rval[1] = 0;
+ KERNEL_PROC_LOCK(p);
+ error = (*callp->sy_call)(p, argp, rval);
+ KERNEL_PROC_UNLOCK(p);
+
+ switch (error) {
+ case 0:
+ frame.tf_rax = rval[0];
+ frame.tf_rdx = rval[1];
+ frame.tf_rflags &= ~PSL_C; /* carry bit */
+ break;
+ case ERESTART:
+ /*
+ * The offset to adjust the PC by depends on whether we entered
+ * the kernel through the trap or call gate. We pushed the
+ * size of the instruction into tf_err on entry.
+ */
+ frame.tf_rip -= frame.tf_err;
+ break;
+ case EJUSTRETURN:
+ /* nothing to do */
+ break;
+ default:
+ bad:
+ frame.tf_rax = error;
+ frame.tf_rflags |= PSL_C; /* carry bit */
+ break;
+ }
+
+#ifdef SYSCALL_DEBUG
+ scdebug_ret(p, code, error, rval);
+#endif /* SYSCALL_DEBUG */
+ userret(p);
+}
+
+void
+syscall_fancy(frame)
+ struct trapframe frame;
+{
+ caddr_t params;
+ const struct sysent *callp;
+ struct proc *p;
+ int error;
+ int nsys;
+ size_t argsize, argoff;
+ register_t code, args[9], rval[2], *argp;
+
+ uvmexp.syscalls++;
+ p = curproc;
+
+ code = frame.tf_rax;
+ callp = p->p_emul->e_sysent;
+ nsys = p->p_emul->e_nsysent;
+ argp = &args[0];
+ argoff = 0;
+
+ switch (code) {
+ case SYS_syscall:
+ case SYS___syscall:
+ /*
+ * Code is first argument, followed by actual args.
+ */
+ code = frame.tf_rdi;
+ argp = &args[1];
+ argoff = 1;
+ break;
+ default:
+ break;
+ }
+
+ if (code < 0 || code >= nsys)
+ callp += p->p_emul->e_nosys;
+ else
+ callp += code;
+
+ argsize = (callp->sy_argsize >> 3) + argoff;
+ if (argsize) {
+ switch (MIN(argsize, 6)) {
+ case 6:
+ args[5] = frame.tf_r9;
+ case 5:
+ args[4] = frame.tf_r8;
+ case 4:
+ args[3] = frame.tf_r10;
+ case 3:
+ args[2] = frame.tf_rdx;
+ case 2:
+ args[1] = frame.tf_rsi;
+ case 1:
+ args[0] = frame.tf_rdi;
+ break;
+ default:
+ panic("impossible syscall argsize");
+ }
+ if (argsize > 6) {
+ argsize -= 6;
+ params = (caddr_t)frame.tf_rsp + sizeof(register_t);
+ error = copyin(params, (caddr_t)&args[6],
+ argsize << 3);
+ if (error != 0)
+ goto bad;
+ }
+ }
+
+ KERNEL_PROC_LOCK(p);
+#ifdef SYSCALL_DEBUG
+ scdebug_call(p, code, args);
+#endif
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSCALL))
+ ktrsyscall(p, code, argsize, args);
+#endif
+
+ rval[0] = 0;
+ rval[1] = 0;
+#if NSYSTRACE > 0
+ if (ISSET(p->p_flag, P_SYSTRACE))
+ error = systrace_redirect(code, p, args, rval);
+#endif
+ error = (*callp->sy_call)(p, argp, rval);
+ KERNEL_PROC_UNLOCK(p);
+ switch (error) {
+ case 0:
+ frame.tf_rax = rval[0];
+ frame.tf_rdx = rval[1];
+ frame.tf_rflags &= ~PSL_C; /* carry bit */
+ break;
+ case ERESTART:
+ /*
+ * The offset to adjust the PC by depends on whether we entered
+ * the kernel through the trap or call gate. We pushed the
+ * size of the instruction into tf_err on entry.
+ */
+ frame.tf_rip -= frame.tf_err;
+ break;
+ case EJUSTRETURN:
+ /* nothing to do */
+ break;
+ default:
+ bad:
+ frame.tf_rax = error;
+ frame.tf_rflags |= PSL_C; /* carry bit */
+ break;
+ }
+
+#ifdef SYSCALL_DEBUG
+ KERNEL_PROC_LOCK(p);
+ scdebug_ret(p, code, error, rval);
+ KERNEL_PROC_UNLOCK(p);
+#endif
+ userret(p);
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSRET)) {
+ KERNEL_PROC_LOCK(p);
+ ktrsysret(p, code, error, rval[0]);
+ KERNEL_PROC_UNLOCK(p);
+ }
+#endif
+}
+
+void
+child_return(void *arg)
+{
+ struct proc *p = arg;
+ struct trapframe *tf = p->p_md.md_regs;
+
+ tf->tf_rax = 0;
+ tf->tf_rflags &= ~PSL_C;
+
+ KERNEL_PROC_UNLOCK(l);
+
+ userret(p);
+#ifdef KTRACE
+ if (KTRPOINT(p, KTR_SYSRET)) {
+ KERNEL_PROC_LOCK(p);
+ ktrsysret(p, SYS_fork, 0, 0);
+ KERNEL_PROC_UNLOCK(p);
+ }
+#endif
+}
diff --git a/sys/arch/amd64/amd64/trap.c b/sys/arch/amd64/amd64/trap.c
new file mode 100644
index 00000000000..82f5623731d
--- /dev/null
+++ b/sys/arch/amd64/amd64/trap.c
@@ -0,0 +1,579 @@
+/* $OpenBSD: trap.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: trap.c,v 1.2 2003/05/04 23:51:56 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the University of Utah, and 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.
+ *
+ * @(#)trap.c 7.4 (Berkeley) 5/13/91
+ */
+
+/*
+ * amd64 Trap and System call handling
+ */
+#define TRAP_SIGDEBUG
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/acct.h>
+#include <sys/kernel.h>
+#include <sys/signal.h>
+#include <sys/syscall.h>
+#include <sys/reboot.h>
+#include <sys/pool.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/fpu.h>
+#include <machine/psl.h>
+#include <machine/reg.h>
+#include <machine/trap.h>
+#include <machine/userret.h>
+#ifdef DDB
+#include <machine/db_machdep.h>
+#endif
+
+#include "isa.h"
+
+#ifdef KGDB
+#include <sys/kgdb.h>
+#endif
+
+void trap(struct trapframe);
+#if defined(I386_CPU)
+int trapwrite(unsigned);
+#endif
+
+const char *trap_type[] = {
+ "privileged instruction fault", /* 0 T_PRIVINFLT */
+ "breakpoint trap", /* 1 T_BPTFLT */
+ "arithmetic trap", /* 2 T_ARITHTRAP */
+ "asynchronous system trap", /* 3 T_ASTFLT */
+ "protection fault", /* 4 T_PROTFLT */
+ "trace trap", /* 5 T_TRCTRAP */
+ "page fault", /* 6 T_PAGEFLT */
+ "alignment fault", /* 7 T_ALIGNFLT */
+ "integer divide fault", /* 8 T_DIVIDE */
+ "non-maskable interrupt", /* 9 T_NMI */
+ "overflow trap", /* 10 T_OFLOW */
+ "bounds check fault", /* 11 T_BOUND */
+ "FPU not available fault", /* 12 T_DNA */
+ "double fault", /* 13 T_DOUBLEFLT */
+ "FPU operand fetch fault", /* 14 T_FPOPFLT */
+ "invalid TSS fault", /* 15 T_TSSFLT */
+ "segment not present fault", /* 16 T_SEGNPFLT */
+ "stack fault", /* 17 T_STKFLT */
+ "machine check", /* 18 T_MCA */
+ "SSE FP exception", /* 19 T_XMM */
+ "reserved trap", /* 20 T_RESERVED */
+};
+int trap_types = sizeof trap_type / sizeof trap_type[0];
+
+#ifdef DEBUG
+int trapdebug = 0;
+#endif
+
+#define IDTVEC(name) __CONCAT(X, name)
+
+#ifdef TRAP_SIGDEBUG
+static void frame_dump(struct trapframe *);
+#endif
+
+/*
+ * trap(frame):
+ * Exception, fault, and trap interface to BSD kernel. This
+ * common code is called from assembly language IDT gate entry
+ * routines that prepare a suitable stack frame, and restore this
+ * frame after the exception has been processed. Note that the
+ * effect is as if the arguments were passed call by reference.
+ */
+/*ARGSUSED*/
+void
+trap(frame)
+ struct trapframe frame;
+{
+ struct proc *p = curproc;
+ int type = (int)frame.tf_trapno;
+ struct pcb *pcb;
+ extern char resume_iret[], IDTVEC(oosyscall)[];
+#if 0
+ extern char resume_pop_ds[], resume_pop_es[];
+#endif
+ struct trapframe *vframe;
+ void *resume;
+ caddr_t onfault;
+ int error;
+ uint64_t cr2;
+ union sigval sv;
+
+ uvmexp.traps++;
+
+ pcb = (p != NULL && p->p_addr != NULL) ? &p->p_addr->u_pcb : NULL;
+
+#ifdef DEBUG
+ if (trapdebug) {
+ printf("trap %d code %lx eip %lx cs %lx rflags %lx cr2 %lx "
+ "cpl %x\n",
+ type, frame.tf_err, frame.tf_rip, frame.tf_cs,
+ frame.tf_rflags, rcr2(), curcpu()->ci_ilevel);
+ printf("curproc %p\n", curproc);
+ if (curproc)
+ printf("pid %d\n", p->p_pid);
+ }
+#endif
+
+ if (!KERNELMODE(frame.tf_cs, frame.tf_rflags)) {
+ type |= T_USER;
+ p->p_md.md_regs = &frame;
+ }
+
+ switch (type) {
+
+ default:
+ we_re_toast:
+#ifdef KGDB
+ if (kgdb_trap(type, &frame))
+ return;
+ else {
+ /*
+ * If this is a breakpoint, don't panic
+ * if we're not connected.
+ */
+ if (type == T_BPTFLT) {
+ printf("kgdb: ignored %s\n", trap_type[type]);
+ return;
+ }
+ }
+#endif
+#ifdef DDB
+ if (kdb_trap(type, 0, &frame))
+ return;
+#endif
+ if (frame.tf_trapno < trap_types)
+ printf("fatal %s", trap_type[frame.tf_trapno]);
+ else
+ printf("unknown trap %ld", (u_long)frame.tf_trapno);
+ printf(" in %s mode\n", (type & T_USER) ? "user" : "supervisor");
+ printf("trap type %d code %lx rip %lx cs %lx rflags %lx cr2 "
+ " %lx cpl %x rsp %lx\n",
+ type, frame.tf_err, (u_long)frame.tf_rip, frame.tf_cs,
+ frame.tf_rflags, rcr2(), curcpu()->ci_ilevel, frame.tf_rsp);
+
+ /* panic("trap"); */
+ boot(RB_HALT);
+ /*NOTREACHED*/
+
+ case T_PROTFLT:
+ case T_SEGNPFLT:
+ case T_ALIGNFLT:
+ case T_TSSFLT:
+ if (p == NULL)
+ goto we_re_toast;
+ /* Check for copyin/copyout fault. */
+ if (pcb->pcb_onfault != 0) {
+ error = EFAULT;
+copyfault:
+ frame.tf_rip = (u_int64_t)pcb->pcb_onfault;
+ frame.tf_rax = error;
+ return;
+ }
+
+ /*
+ * Check for failure during return to user mode.
+ *
+ * XXXfvdl check for rex prefix?
+ *
+ * We do this by looking at the instruction we faulted on. The
+ * specific instructions we recognize only happen when
+ * returning from a trap, syscall, or interrupt.
+ *
+ * XXX
+ * The heuristic used here will currently fail for the case of
+ * one of the 2 pop instructions faulting when returning from a
+ * a fast interrupt. This should not be possible. It can be
+ * fixed by rearranging the trap frame so that the stack format
+ * at this point is the same as on exit from a `slow'
+ * interrupt.
+ */
+ switch (*(u_char *)frame.tf_rip) {
+ case 0xcf: /* iret */
+ vframe = (void *)((u_int64_t)&frame.tf_rsp - 44);
+ resume = resume_iret;
+ break;
+/*
+ * XXXfvdl these are illegal in long mode (not in compat mode, though)
+ * and we do not take back the descriptors from the signal context anyway,
+ * but may do so later for USER_LDT, in which case we need to intercept
+ * other instructions (movl %eax, %Xs).
+ */
+#if 0
+ case 0x1f: /* popl %ds */
+ vframe = (void *)((u_int64_t)&frame.tf_rsp - 4);
+ resume = resume_pop_ds;
+ break;
+ case 0x07: /* popl %es */
+ vframe = (void *)((u_int64_t)&frame.tf_rsp - 0);
+ resume = resume_pop_es;
+ break;
+#endif
+ default:
+ goto we_re_toast;
+ }
+ if (KERNELMODE(vframe->tf_cs, vframe->tf_rflags))
+ goto we_re_toast;
+
+ frame.tf_rip = (u_int64_t)resume;
+ return;
+
+ case T_PROTFLT|T_USER: /* protection fault */
+ case T_TSSFLT|T_USER:
+ case T_SEGNPFLT|T_USER:
+ case T_STKFLT|T_USER:
+ case T_NMI|T_USER:
+#ifdef TRAP_SIGDEBUG
+ printf("pid %d (%s): BUS at rip %lx addr %lx\n",
+ p->p_pid, p->p_comm, frame.tf_rip, rcr2());
+ frame_dump(&frame);
+#endif
+ sv.sival_ptr = (void *)frame.tf_rip;
+ KERNEL_PROC_LOCK(p);
+ trapsignal(p, SIGBUS, type & ~T_USER, BUS_OBJERR, sv);
+ KERNEL_PROC_UNLOCK(p);
+ goto out;
+ case T_ALIGNFLT|T_USER:
+ sv.sival_ptr = (void *)frame.tf_rip;
+ KERNEL_PROC_LOCK(p);
+ trapsignal(p, SIGBUS, type & ~T_USER, BUS_ADRALN, sv);
+ KERNEL_PROC_UNLOCK(p);
+ goto out;
+
+ case T_PRIVINFLT|T_USER: /* privileged instruction fault */
+ sv.sival_ptr = (void *)frame.tf_rip;
+ KERNEL_PROC_LOCK(p);
+ trapsignal(p, SIGILL, type & ~T_USER, ILL_PRVOPC, sv);
+ KERNEL_PROC_UNLOCK(p);
+ goto out;
+ case T_FPOPFLT|T_USER: /* coprocessor operand fault */
+#ifdef TRAP_SIGDEBUG
+ printf("pid %d (%s): ILL at rip %lx addr %lx\n",
+ p->p_pid, p->p_comm, frame.tf_rip, rcr2());
+ frame_dump(&frame);
+#endif
+ sv.sival_ptr = (void *)frame.tf_rip;
+ KERNEL_PROC_LOCK(p);
+ trapsignal(p, SIGILL, type & ~T_USER, ILL_COPROC, sv);
+ KERNEL_PROC_UNLOCK(p);
+ goto out;
+
+ case T_ASTFLT|T_USER: /* Allow process switch */
+ uvmexp.softs++;
+ if (p->p_flag & P_OWEUPC) {
+ p->p_flag &= ~P_OWEUPC;
+ KERNEL_PROC_LOCK(p);
+ ADDUPROF(p);
+ KERNEL_PROC_UNLOCK(p);
+ }
+ /* Allow a forced task switch. */
+ if (curcpu()->ci_want_resched)
+ preempt(NULL);
+ goto out;
+
+ case T_DNA|T_USER: {
+ printf("pid %d killed due to lack of floating point\n",
+ p->p_pid);
+ sv.sival_ptr = (void *)frame.tf_rip;
+ KERNEL_PROC_LOCK(p);
+ trapsignal(p, SIGKILL, type &~ T_USER, FPE_FLTINV, sv);
+ KERNEL_PROC_UNLOCK(p);
+ goto out;
+ }
+
+ case T_BOUND|T_USER:
+ sv.sival_ptr = (void *)frame.tf_rip;
+ KERNEL_PROC_LOCK(p);
+ trapsignal(p, SIGFPE, type &~ T_USER, FPE_FLTSUB, sv);
+ KERNEL_PROC_UNLOCK(p);
+ goto out;
+ case T_OFLOW|T_USER:
+ sv.sival_ptr = (void *)frame.tf_rip;
+ KERNEL_PROC_LOCK(p);
+ trapsignal(p, SIGFPE, type &~ T_USER, FPE_INTOVF, sv);
+ KERNEL_PROC_UNLOCK(p);
+ goto out;
+ case T_DIVIDE|T_USER:
+ sv.sival_ptr = (void *)frame.tf_rip;
+ KERNEL_PROC_LOCK(p);
+ trapsignal(p, SIGFPE, type &~ T_USER, FPE_INTDIV, sv);
+ KERNEL_PROC_UNLOCK(p);
+ goto out;
+
+ case T_ARITHTRAP|T_USER:
+ case T_XMM|T_USER:
+ fputrap(&frame);
+ goto out;
+
+ case T_PAGEFLT: /* allow page faults in kernel mode */
+ if (p == NULL)
+ goto we_re_toast;
+#ifdef LOCKDEBUG
+ if (simple_lock_held(&sched_lock))
+ goto we_re_toast;
+#endif
+#ifdef MULTIPROCESSOR
+ if ((p->p_flag & P_BIGLOCK) == 0)
+ goto we_re_toast;
+#endif
+ cr2 = rcr2();
+ KERNEL_LOCK(LK_CANRECURSE|LK_EXCLUSIVE);
+ goto faultcommon;
+
+ case T_PAGEFLT|T_USER: { /* page fault */
+ vaddr_t va, fa;
+ struct vmspace *vm;
+ struct vm_map *map;
+ vm_prot_t ftype;
+ extern struct vm_map *kernel_map;
+ unsigned long nss;
+
+ cr2 = rcr2();
+ KERNEL_PROC_LOCK(p);
+faultcommon:
+ vm = p->p_vmspace;
+ if (vm == NULL)
+ goto we_re_toast;
+ fa = cr2;
+ va = trunc_page((vaddr_t)cr2);
+ /*
+ * It is only a kernel address space fault iff:
+ * 1. (type & T_USER) == 0 and
+ * 2. pcb_onfault not set or
+ * 3. pcb_onfault set but supervisor space fault
+ * The last can occur during an exec() copyin where the
+ * argument space is lazy-allocated.
+ */
+ if (type == T_PAGEFLT && va >= VM_MIN_KERNEL_ADDRESS)
+ map = kernel_map;
+ else
+ map = &vm->vm_map;
+ if (frame.tf_err & PGEX_W)
+ ftype = VM_PROT_WRITE;
+ else
+ ftype = VM_PROT_READ;
+
+#ifdef DIAGNOSTIC
+ if (map == kernel_map && va == 0) {
+ printf("trap: bad kernel access at %lx\n", va);
+ goto we_re_toast;
+ }
+#endif
+
+ nss = 0;
+ if ((caddr_t)va >= vm->vm_maxsaddr
+ && (caddr_t)va < (caddr_t)VM_MAXUSER_ADDRESS
+ && map != kernel_map) {
+ nss = btoc(USRSTACK-(unsigned long)va);
+ if (nss > (u_long)btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
+ /*
+ * We used to fail here. However, it may
+ * just have been an mmap()ed page low
+ * in the stack, which is legal. If it
+ * wasn't, uvm_fault() will fail below.
+ *
+ * Set nss to 0, since this case is not
+ * a "stack extension".
+ */
+ nss = 0;
+ }
+ }
+
+ /* Fault the original page in. */
+ onfault = pcb->pcb_onfault;
+ pcb->pcb_onfault = NULL;
+ error = uvm_fault(map, va, 0, ftype);
+ pcb->pcb_onfault = onfault;
+ if (error == 0) {
+ if (nss > (u_long)vm->vm_ssize)
+ vm->vm_ssize = nss;
+
+ if (type == T_PAGEFLT) {
+ KERNEL_UNLOCK();
+ return;
+ }
+ KERNEL_PROC_UNLOCK(p);
+ goto out;
+ }
+ if (error == EACCES) {
+ error = EFAULT;
+ }
+
+ if (type == T_PAGEFLT) {
+ if (pcb->pcb_onfault != 0) {
+ KERNEL_UNLOCK();
+ goto copyfault;
+ }
+ printf("uvm_fault(%p, 0x%lx, 0, %d) -> %x\n",
+ map, va, ftype, error);
+ goto we_re_toast;
+ }
+ if (error == ENOMEM) {
+ printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
+ p->p_pid, p->p_comm,
+ p->p_cred && p->p_ucred ?
+ (int)p->p_ucred->cr_uid : -1);
+ sv.sival_ptr = (void *)fa;
+ trapsignal(p, SIGKILL, T_PAGEFLT, SEGV_MAPERR, sv);
+ } else {
+#ifdef TRAP_SIGDEBUG
+ printf("pid %d (%s): SEGV at rip %lx addr %lx\n",
+ p->p_pid, p->p_comm, frame.tf_rip, va);
+ frame_dump(&frame);
+#endif
+ sv.sival_ptr = (void *)fa;
+ trapsignal(p, SIGSEGV, T_PAGEFLT, SEGV_MAPERR, sv);
+ }
+ if (type == T_PAGEFLT)
+ KERNEL_UNLOCK();
+ else
+ KERNEL_PROC_UNLOCK(p);
+ break;
+ }
+
+ case T_TRCTRAP:
+ /* Check whether they single-stepped into a lcall. */
+ if (frame.tf_rip == (int)IDTVEC(oosyscall))
+ return;
+ if (frame.tf_rip == (int)IDTVEC(oosyscall) + 1) {
+ frame.tf_rflags &= ~PSL_T;
+ return;
+ }
+ goto we_re_toast;
+
+ case T_BPTFLT|T_USER: /* bpt instruction fault */
+ case T_TRCTRAP|T_USER: /* trace trap */
+#ifdef MATH_EMULATE
+ trace:
+#endif
+ KERNEL_PROC_LOCK(p);
+ trapsignal(p, SIGTRAP, type &~ T_USER, TRAP_BRKPT, sv);
+ KERNEL_PROC_UNLOCK(p);
+ break;
+
+#if NISA > 0
+ case T_NMI:
+#if defined(KGDB) || defined(DDB)
+ /* NMI can be hooked up to a pushbutton for debugging */
+ printf ("NMI ... going to debugger\n");
+#ifdef KGDB
+
+ if (kgdb_trap(type, &frame))
+ return;
+#endif
+#ifdef DDB
+ if (kdb_trap(type, 0, &frame))
+ return;
+#endif
+#endif /* KGDB || DDB */
+ /* machine/parity/power fail/"kitchen sink" faults */
+
+ if (x86_nmi() != 0)
+ goto we_re_toast;
+ else
+ return;
+#endif /* NISA > 0 */
+ }
+
+ if ((type & T_USER) == 0)
+ return;
+out:
+ userret(p);
+}
+
+#ifdef TRAP_SIGDEBUG
+static void
+frame_dump(struct trapframe *tf)
+{
+ printf("rip %p rsp %p rfl %p\n",
+ (void *)tf->tf_rip, (void *)tf->tf_rsp, (void *)tf->tf_rflags);
+ printf("rdi %p rsi %p rdx %p\n",
+ (void *)tf->tf_rdi, (void *)tf->tf_rsi, (void *)tf->tf_rdx);
+ printf("rcx %p r8 %p r9 %p\n",
+ (void *)tf->tf_rcx, (void *)tf->tf_r8, (void *)tf->tf_r9);
+ printf("r10 %p r11 %p r12 %p\n",
+ (void *)tf->tf_r10, (void *)tf->tf_r11, (void *)tf->tf_r12);
+ printf("r13 %p r14 %p r15 %p\n",
+ (void *)tf->tf_r13, (void *)tf->tf_r14, (void *)tf->tf_r15);
+ printf("rbp %p rbx %p rax %p\n",
+ (void *)tf->tf_rbp, (void *)tf->tf_rbx, (void *)tf->tf_rax);
+}
+#endif
diff --git a/sys/arch/amd64/amd64/vector.S b/sys/arch/amd64/amd64/vector.S
new file mode 100644
index 00000000000..b2c3819dd2d
--- /dev/null
+++ b/sys/arch/amd64/amd64/vector.S
@@ -0,0 +1,821 @@
+/* $OpenBSD: vector.S,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: vector.S,v 1.2 2003/05/04 23:46:41 fvdl Exp $ */
+
+/*
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Frank van der Linden for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#define ALIGN_TEXT .align 16,0x90
+
+#include <machine/i8259.h>
+#include <machine/i82093reg.h>
+#include <machine/i82489reg.h>
+#include <machine/asm.h>
+#include <machine/frameasm.h>
+#include <machine/segments.h>
+#include <machine/trap.h>
+#include <machine/intr.h>
+#include <machine/psl.h>
+
+#include <net/netisr.h>
+
+#include "ioapic.h"
+#include "lapic.h"
+#include "assym.h"
+
+/*****************************************************************************/
+
+/*
+ * Trap and fault vector routines
+ *
+ * On exit from the kernel to user mode, we always need to check for ASTs. In
+ * addition, we need to do this atomically; otherwise an interrupt may occur
+ * which causes an AST, but it won't get processed until the next kernel entry
+ * (possibly the next clock tick). Thus, we disable interrupt before checking,
+ * and only enable them again on the final `iret' or before calling the AST
+ * handler.
+ */
+
+/*****************************************************************************/
+
+#define TRAP(a) pushq $(a) ; jmp _C_LABEL(alltraps)
+#define ZTRAP(a) pushq $0 ; TRAP(a)
+
+#define BPTTRAP(a) ZTRAP(a)
+
+ .text
+IDTVEC(trap00)
+ ZTRAP(T_DIVIDE)
+IDTVEC(trap01)
+ BPTTRAP(T_TRCTRAP)
+IDTVEC(trap02)
+ ZTRAP(T_NMI)
+IDTVEC(trap03)
+ BPTTRAP(T_BPTFLT)
+IDTVEC(trap04)
+ ZTRAP(T_OFLOW)
+IDTVEC(trap05)
+ ZTRAP(T_BOUND)
+IDTVEC(trap06)
+ ZTRAP(T_PRIVINFLT)
+IDTVEC(trap07)
+ pushq $0 # dummy error code
+ pushq $T_DNA
+ INTRENTRY
+ sti
+ movq CPUVAR(SELF),%rdi
+ call _C_LABEL(fpudna)
+ INTRFASTEXIT
+IDTVEC(trap08)
+ ZTRAP(T_DOUBLEFLT)
+IDTVEC(trap09)
+ ZTRAP(T_FPOPFLT)
+IDTVEC(trap0a)
+ TRAP(T_TSSFLT)
+IDTVEC(trap0b)
+ TRAP(T_SEGNPFLT)
+IDTVEC(trap0c)
+ TRAP(T_STKFLT)
+IDTVEC(trap0d)
+ TRAP(T_PROTFLT)
+IDTVEC(trap0e)
+ TRAP(T_PAGEFLT)
+IDTVEC(intrspurious)
+IDTVEC(trap0f)
+ iretq
+IDTVEC(trap10)
+ ZTRAP(T_ARITHTRAP)
+IDTVEC(trap11)
+ ZTRAP(T_ALIGNFLT)
+IDTVEC(trap12)
+ ZTRAP(T_MCA)
+IDTVEC(trap13)
+ ZTRAP(T_XMM)
+IDTVEC(trap14)
+IDTVEC(trap15)
+IDTVEC(trap16)
+IDTVEC(trap17)
+IDTVEC(trap18)
+IDTVEC(trap19)
+IDTVEC(trap1a)
+IDTVEC(trap1b)
+IDTVEC(trap1c)
+IDTVEC(trap1d)
+IDTVEC(trap1e)
+IDTVEC(trap1f)
+ /* 20 - 31 reserved for future exp */
+ ZTRAP(T_RESERVED)
+
+IDTVEC(exceptions)
+ .quad _C_LABEL(Xtrap00), _C_LABEL(Xtrap01)
+ .quad _C_LABEL(Xtrap02), _C_LABEL(Xtrap03)
+ .quad _C_LABEL(Xtrap04), _C_LABEL(Xtrap05)
+ .quad _C_LABEL(Xtrap06), _C_LABEL(Xtrap07)
+ .quad _C_LABEL(Xtrap08), _C_LABEL(Xtrap09)
+ .quad _C_LABEL(Xtrap0a), _C_LABEL(Xtrap0b)
+ .quad _C_LABEL(Xtrap0c), _C_LABEL(Xtrap0d)
+ .quad _C_LABEL(Xtrap0e), _C_LABEL(Xtrap0f)
+ .quad _C_LABEL(Xtrap10), _C_LABEL(Xtrap11)
+ .quad _C_LABEL(Xtrap12), _C_LABEL(Xtrap13)
+ .quad _C_LABEL(Xtrap14), _C_LABEL(Xtrap15)
+ .quad _C_LABEL(Xtrap16), _C_LABEL(Xtrap17)
+ .quad _C_LABEL(Xtrap18), _C_LABEL(Xtrap19)
+ .quad _C_LABEL(Xtrap1a), _C_LABEL(Xtrap1b)
+ .quad _C_LABEL(Xtrap1c), _C_LABEL(Xtrap1d)
+ .quad _C_LABEL(Xtrap1e), _C_LABEL(Xtrap1f)
+
+/*
+ * If an error is detected during trap, syscall, or interrupt exit, trap() will
+ * change %eip to point to one of these labels. We clean up the stack, if
+ * necessary, and resume as if we were handling a general protection fault.
+ * This will cause the process to get a SIGBUS.
+ *
+ * XXXfvdl currently unused, as pop %ds and pop %es are illegal in long
+ * mode. However, if the x86-64 port is going to support USER_LDT, we
+ * may need something like this after all.
+ */
+NENTRY(resume_iret)
+ ZTRAP(T_PROTFLT)
+#if 0
+NENTRY(resume_pop_ds)
+ movl $GSEL(GDATA_SEL, SEL_KPL),%eax
+ movl %eax,%es
+NENTRY(resume_pop_es)
+ movl $T_PROTFLT,TF_TRAPNO(%rsp)
+ jmp calltrap
+#endif
+
+/*
+ * All traps go through here. Call the generic trap handler, and
+ * check for ASTs afterwards.
+ */
+NENTRY(alltraps)
+ INTRENTRY
+ sti
+calltrap:
+#ifdef DIAGNOSTIC
+ movl CPUVAR(ILEVEL),%ebx
+#endif /* DIAGNOSTIC */
+ call _C_LABEL(trap)
+2: /* Check for ASTs on exit to user mode. */
+ cli
+ CHECK_ASTPENDING(%r11)
+ je 1f
+ testb $SEL_RPL,TF_CS(%rsp)
+ jz 1f
+5: CLEAR_ASTPENDING(%r11)
+ sti
+ movl $T_ASTFLT,TF_TRAPNO(%rsp)
+ call _C_LABEL(trap)
+ jmp 2b
+#ifndef DIAGNOSTIC
+1: INTRFASTEXIT
+#else /* DIAGNOSTIC */
+1: cmpl CPUVAR(ILEVEL),%ebx
+ jne 3f
+ INTRFASTEXIT
+3: sti
+ movabsq $4f,%rdi
+ movl CPUVAR(ILEVEL),%esi
+ movl %ebx,%edx
+ xorq %rax,%rax
+ call _C_LABEL(printf)
+#ifdef DDB
+ int $3
+#endif /* DDB */
+ movl %ebx,CPUVAR(ILEVEL)
+ jmp 2b
+4: .asciz "WARNING: SPL NOT LOWERED ON TRAP EXIT %x %x\n"
+#endif /* DIAGNOSTIC */
+
+
+#define __HAVE_GENERIC_SOFT_INTERRUPTS /* XXX */
+
+
+/*
+ * Macros for interrupt entry, call to handler, and exit.
+ *
+ * XXX
+ * The interrupt frame is set up to look like a trap frame. This may be a
+ * waste. The only handler which needs a frame is the clock handler, and it
+ * only needs a few bits. Xdoreti() needs a trap frame for handling ASTs, but
+ * it could easily convert the frame on demand.
+ *
+ * The direct costs of setting up a trap frame are two pushq's (error code and
+ * trap number), an addl to get rid of these, and pushing and popping the
+ * callee-saved registers %esi, %edi, %ebx, and %ebp twice.
+ *
+ * If the interrupt frame is made more flexible, INTR can push %eax first and
+ * decide the ipending case with less overhead, e.g., by avoiding loading the
+ * segment registers.
+ *
+ */
+
+#define MY_COUNT _C_LABEL(uvmexp)
+
+/* XXX See comment in locore.s */
+#ifdef __ELF__
+#define XINTR(name,num) Xintr_/**/name/**/num
+#else
+#define XINTR(name,num) _Xintr_/**/name/**/num
+#endif
+
+#if NLAPIC > 0
+#ifdef MULTIPROCESSOR
+IDTVEC(recurse_lapic_ipi)
+ INTR_RECURSE_HWFRAME
+ pushq $0
+ pushq $T_ASTFLT
+ INTRENTRY
+IDTVEC(resume_lapic_ipi)
+ cli
+ jmp 1f
+IDTVEC(intr_lapic_ipi)
+ pushq $0
+ pushq $T_ASTFLT
+ INTRENTRY
+ movl $0,_C_LABEL(local_apic)+LAPIC_EOI
+ movl CPUVAR(ILEVEL),%ebx
+ cmpl $IPL_IPI,%ebx
+ jae 2f
+1:
+ incl CPUVAR(IDEPTH)
+ movl $IPL_IPI,CPUVAR(ILEVEL)
+ sti
+ pushq %rbx
+ call _C_LABEL(x86_ipi_handler)
+ jmp _C_LABEL(Xdoreti)
+2:
+ orl $(1 << LIR_IPI),CPUVAR(IPENDING)
+ sti
+ INTRFASTEXIT
+
+#if defined(DDB)
+IDTVEC(intrddb)
+1:
+ pushq $0
+ pushq $T_BPTFLT
+ INTRENTRY
+ movl $0xf,%eax
+ movq %rax,%cr8
+ movl $0,_C_LABEL(local_apic)+LAPIC_EOI
+ sti
+ call _C_LABEL(ddb_ipi)
+ xorl %eax,%eax
+ movq %rax,%cr8
+ INTRFASTEXIT
+#endif /* DDB */
+#endif /* MULTIPROCESSOR */
+
+ /*
+ * Interrupt from the local APIC timer.
+ */
+IDTVEC(recurse_lapic_ltimer)
+ INTR_RECURSE_HWFRAME
+ pushq $0
+ pushq $T_ASTFLT
+ INTRENTRY
+IDTVEC(resume_lapic_ltimer)
+ cli
+ jmp 1f
+IDTVEC(intr_lapic_ltimer)
+ pushq $0
+ pushq $T_ASTFLT
+ INTRENTRY
+ movl $0,_C_LABEL(local_apic)+LAPIC_EOI
+ movl CPUVAR(ILEVEL),%ebx
+ cmpl $IPL_CLOCK,%ebx
+ jae 2f
+1:
+ incl CPUVAR(IDEPTH)
+ movl $IPL_CLOCK,CPUVAR(ILEVEL)
+ sti
+ pushq %rbx
+ xorq %rdi,%rdi
+ call _C_LABEL(lapic_clockintr)
+ jmp _C_LABEL(Xdoreti)
+2:
+ orl $(1 << LIR_TIMER),CPUVAR(IPENDING)
+ sti
+ INTRFASTEXIT
+#endif /* NLAPIC > 0 */
+
+#ifdef MULTIPROCESSOR
+#define LOCK_KERNEL call _C_LABEL(x86_intlock)
+#define UNLOCK_KERNEL call _C_LABEL(x86_intunlock)
+#else
+#define LOCK_KERNEL
+#define UNLOCK_KERNEL
+#endif
+
+#define voidop(num)
+
+
+/*
+ * This macro defines the generic stub code. Its arguments modifiy it
+ * for specific PICs.
+ */
+
+#define INTRSTUB(name, num, early_ack, late_ack, mask, unmask, level_mask) \
+IDTVEC(recurse_/**/name/**/num) ;\
+ INTR_RECURSE_HWFRAME ;\
+ subq $8,%rsp ;\
+ pushq $T_ASTFLT /* trap # for doing ASTs */ ;\
+ INTRENTRY ;\
+IDTVEC(resume_/**/name/**/num) \
+ movq $IREENT_MAGIC,TF_ERR(%rsp) ;\
+ movl %ebx,%r13d ;\
+ movq CPUVAR(ISOURCES) + (num) * 8, %r14 ;\
+ movl IS_MAXLEVEL(%r14),%ebx ;\
+ jmp 1f ;\
+IDTVEC(intr_/**/name/**/num) ;\
+ pushq $0 /* dummy error code */ ;\
+ pushq $T_ASTFLT /* trap # for doing ASTs */ ;\
+ INTRENTRY ;\
+ movq CPUVAR(ISOURCES) + (num) * 8, %r14 ;\
+ mask(num) /* mask it in hardware */ ;\
+ early_ack(num) /* and allow other intrs */ ;\
+ testq %r14,%r14 ;\
+ jz 9f /* stray */ ;\
+ movl IS_MAXLEVEL(%r14),%ebx ;\
+ movl CPUVAR(ILEVEL),%r13d ;\
+ cmpl %ebx,%r13d ;\
+ jae 10f /* currently masked; hold it */ ;\
+ incl MY_COUNT+V_INTR /* statistical info */ ;\
+ incq IS_EVCNT(%r14) ;\
+1: \
+ pushq %r13 ;\
+ movl %ebx,CPUVAR(ILEVEL) ;\
+ sti ;\
+ incl CPUVAR(IDEPTH) ;\
+ movq IS_HANDLERS(%r14),%rbx ;\
+ LOCK_KERNEL ;\
+6: \
+ movl IH_LEVEL(%rbx),%r12d ;\
+ cmpl %r13d,%r12d ;\
+ jle 7f ;\
+ movq IH_ARG(%rbx),%rdi ;\
+ testq %rdi, %rdi ;\
+ jnz 8f ;\
+ movq %rsp, %rdi ;\
+8: movl %r12d,CPUVAR(ILEVEL) ;\
+ call *IH_FUN(%rbx) /* call it */ ;\
+ movq IH_NEXT(%rbx),%rbx /* next handler in chain */ ;\
+ testq %rbx,%rbx ;\
+ jnz 6b ;\
+5: \
+ UNLOCK_KERNEL ;\
+ cli ;\
+ unmask(num) /* unmask it in hardware */ ;\
+ late_ack(num) ;\
+ sti ;\
+ jmp _C_LABEL(Xdoreti) /* lower spl and do ASTs */ ;\
+7: \
+ UNLOCK_KERNEL ;\
+ cli ;\
+ orl $(1 << num),CPUVAR(IPENDING) ;\
+ level_mask(num) ;\
+ late_ack(num) ;\
+ sti ;\
+ jmp _C_LABEL(Xdoreti) /* lower spl and do ASTs */ ;\
+10: \
+ cli ;\
+ orl $(1 << num),CPUVAR(IPENDING) ;\
+ level_mask(num) ;\
+ late_ack(num) ;\
+ sti ;\
+ INTRFASTEXIT ;\
+9: \
+ unmask(num) ;\
+ late_ack(num) ;\
+ sti ;\
+ INTRFASTEXIT
+
+#define ICUADDR IO_ICU1
+
+INTRSTUB(legacy,0,i8259_asm_ack1,voidop,i8259_asm_mask,i8259_asm_unmask,
+ voidop)
+INTRSTUB(legacy,1,i8259_asm_ack1,voidop,i8259_asm_mask,i8259_asm_unmask,
+ voidop)
+INTRSTUB(legacy,2,i8259_asm_ack1,voidop,i8259_asm_mask,i8259_asm_unmask,
+ voidop)
+INTRSTUB(legacy,3,i8259_asm_ack1,voidop,i8259_asm_mask,i8259_asm_unmask,
+ voidop)
+INTRSTUB(legacy,4,i8259_asm_ack1,voidop,i8259_asm_mask,i8259_asm_unmask,
+ voidop)
+INTRSTUB(legacy,5,i8259_asm_ack1,voidop,i8259_asm_mask,i8259_asm_unmask,
+ voidop)
+INTRSTUB(legacy,6,i8259_asm_ack1,voidop,i8259_asm_mask,i8259_asm_unmask,
+ voidop)
+INTRSTUB(legacy,7,i8259_asm_ack1,voidop,i8259_asm_mask,i8259_asm_unmask,
+ voidop)
+#undef ICUADDR
+#define ICUADDR IO_ICU2
+
+INTRSTUB(legacy,8,i8259_asm_ack2,voidop,i8259_asm_mask,i8259_asm_unmask,
+ voidop)
+INTRSTUB(legacy,9,i8259_asm_ack2,voidop,i8259_asm_mask,i8259_asm_unmask,
+ voidop)
+INTRSTUB(legacy,10,i8259_asm_ack2,voidop,i8259_asm_mask,i8259_asm_unmask,
+ voidop)
+INTRSTUB(legacy,11,i8259_asm_ack2,voidop,i8259_asm_mask,i8259_asm_unmask,
+ voidop)
+INTRSTUB(legacy,12,i8259_asm_ack2,voidop,i8259_asm_mask,i8259_asm_unmask,
+ voidop)
+INTRSTUB(legacy,13,i8259_asm_ack2,voidop,i8259_asm_mask,i8259_asm_unmask,
+ voidop)
+INTRSTUB(legacy,14,i8259_asm_ack2,voidop,i8259_asm_mask,i8259_asm_unmask,
+ voidop)
+INTRSTUB(legacy,15,i8259_asm_ack2,voidop,i8259_asm_mask,i8259_asm_unmask,
+ voidop)
+
+#if NIOAPIC > 0
+
+INTRSTUB(ioapic_edge,0,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,1,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,2,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,3,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,4,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,5,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,6,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,7,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,8,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,9,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,10,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,11,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,12,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,13,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,14,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,15,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,16,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,17,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,18,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,19,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,20,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,21,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,22,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,23,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,24,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,25,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,26,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,27,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,28,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,29,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,30,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+INTRSTUB(ioapic_edge,31,voidop,ioapic_asm_ack,voidop,voidop,voidop)
+
+INTRSTUB(ioapic_level,0,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,1,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,2,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,3,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,4,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,5,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,6,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,7,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,8,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,9,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,10,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,11,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,12,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,13,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,14,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,15,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,16,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,17,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,18,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,19,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,20,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,21,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,22,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,23,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,24,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,25,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,26,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,27,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,28,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,29,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,30,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+INTRSTUB(ioapic_level,31,voidop,ioapic_asm_ack,voidop,ioapic_unmask,ioapic_mask)
+
+#endif
+
+ .globl _C_LABEL(i8259_stubs)
+_C_LABEL(i8259_stubs):
+ .quad _C_LABEL(Xintr_legacy0), _C_LABEL(Xrecurse_legacy0)
+ .quad _C_LABEL(Xresume_legacy0)
+ .quad _C_LABEL(Xintr_legacy1), _C_LABEL(Xrecurse_legacy1)
+ .quad _C_LABEL(Xresume_legacy1)
+ .quad _C_LABEL(Xintr_legacy2), _C_LABEL(Xrecurse_legacy2)
+ .quad _C_LABEL(Xresume_legacy2)
+ .quad _C_LABEL(Xintr_legacy3), _C_LABEL(Xrecurse_legacy3)
+ .quad _C_LABEL(Xresume_legacy3)
+ .quad _C_LABEL(Xintr_legacy4), _C_LABEL(Xrecurse_legacy4)
+ .quad _C_LABEL(Xresume_legacy4)
+ .quad _C_LABEL(Xintr_legacy5), _C_LABEL(Xrecurse_legacy5)
+ .quad _C_LABEL(Xresume_legacy5)
+ .quad _C_LABEL(Xintr_legacy6), _C_LABEL(Xrecurse_legacy6)
+ .quad _C_LABEL(Xresume_legacy6)
+ .quad _C_LABEL(Xintr_legacy7), _C_LABEL(Xrecurse_legacy7)
+ .quad _C_LABEL(Xresume_legacy7)
+ .quad _C_LABEL(Xintr_legacy8), _C_LABEL(Xrecurse_legacy8)
+ .quad _C_LABEL(Xresume_legacy8)
+ .quad _C_LABEL(Xintr_legacy9), _C_LABEL(Xrecurse_legacy9)
+ .quad _C_LABEL(Xresume_legacy9)
+ .quad _C_LABEL(Xintr_legacy10), _C_LABEL(Xrecurse_legacy10)
+ .quad _C_LABEL(Xresume_legacy10)
+ .quad _C_LABEL(Xintr_legacy11), _C_LABEL(Xrecurse_legacy11)
+ .quad _C_LABEL(Xresume_legacy11)
+ .quad _C_LABEL(Xintr_legacy12), _C_LABEL(Xrecurse_legacy12)
+ .quad _C_LABEL(Xresume_legacy12)
+ .quad _C_LABEL(Xintr_legacy13), _C_LABEL(Xrecurse_legacy13)
+ .quad _C_LABEL(Xresume_legacy13)
+ .quad _C_LABEL(Xintr_legacy14), _C_LABEL(Xrecurse_legacy14)
+ .quad _C_LABEL(Xresume_legacy14)
+ .quad _C_LABEL(Xintr_legacy15), _C_LABEL(Xrecurse_legacy15)
+ .quad _C_LABEL(Xresume_legacy15)
+
+#if NIOAPIC > 0
+ .globl _C_LABEL(ioapic_edge_stubs)
+_C_LABEL(ioapic_edge_stubs):
+ .quad _C_LABEL(Xintr_ioapic_edge0), _C_LABEL(Xrecurse_ioapic_edge0)
+ .quad _C_LABEL(Xresume_ioapic_edge0)
+ .quad _C_LABEL(Xintr_ioapic_edge1), _C_LABEL(Xrecurse_ioapic_edge1)
+ .quad _C_LABEL(Xresume_ioapic_edge1)
+ .quad _C_LABEL(Xintr_ioapic_edge2), _C_LABEL(Xrecurse_ioapic_edge2)
+ .quad _C_LABEL(Xresume_ioapic_edge2)
+ .quad _C_LABEL(Xintr_ioapic_edge3), _C_LABEL(Xrecurse_ioapic_edge3)
+ .quad _C_LABEL(Xresume_ioapic_edge3)
+ .quad _C_LABEL(Xintr_ioapic_edge4), _C_LABEL(Xrecurse_ioapic_edge4)
+ .quad _C_LABEL(Xresume_ioapic_edge4)
+ .quad _C_LABEL(Xintr_ioapic_edge5), _C_LABEL(Xrecurse_ioapic_edge5)
+ .quad _C_LABEL(Xresume_ioapic_edge5)
+ .quad _C_LABEL(Xintr_ioapic_edge6), _C_LABEL(Xrecurse_ioapic_edge6)
+ .quad _C_LABEL(Xresume_ioapic_edge6)
+ .quad _C_LABEL(Xintr_ioapic_edge7), _C_LABEL(Xrecurse_ioapic_edge7)
+ .quad _C_LABEL(Xresume_ioapic_edge7)
+ .quad _C_LABEL(Xintr_ioapic_edge8), _C_LABEL(Xrecurse_ioapic_edge8)
+ .quad _C_LABEL(Xresume_ioapic_edge8)
+ .quad _C_LABEL(Xintr_ioapic_edge9), _C_LABEL(Xrecurse_ioapic_edge9)
+ .quad _C_LABEL(Xresume_ioapic_edge9)
+ .quad _C_LABEL(Xintr_ioapic_edge10), _C_LABEL(Xrecurse_ioapic_edge10)
+ .quad _C_LABEL(Xresume_ioapic_edge10)
+ .quad _C_LABEL(Xintr_ioapic_edge11), _C_LABEL(Xrecurse_ioapic_edge11)
+ .quad _C_LABEL(Xresume_ioapic_edge11)
+ .quad _C_LABEL(Xintr_ioapic_edge12), _C_LABEL(Xrecurse_ioapic_edge12)
+ .quad _C_LABEL(Xresume_ioapic_edge12)
+ .quad _C_LABEL(Xintr_ioapic_edge13), _C_LABEL(Xrecurse_ioapic_edge13)
+ .quad _C_LABEL(Xresume_ioapic_edge13)
+ .quad _C_LABEL(Xintr_ioapic_edge14), _C_LABEL(Xrecurse_ioapic_edge14)
+ .quad _C_LABEL(Xresume_ioapic_edge14)
+ .quad _C_LABEL(Xintr_ioapic_edge15), _C_LABEL(Xrecurse_ioapic_edge15)
+ .quad _C_LABEL(Xresume_ioapic_edge15)
+ .quad _C_LABEL(Xintr_ioapic_edge16), _C_LABEL(Xrecurse_ioapic_edge16)
+ .quad _C_LABEL(Xresume_ioapic_edge16)
+ .quad _C_LABEL(Xintr_ioapic_edge17), _C_LABEL(Xrecurse_ioapic_edge17)
+ .quad _C_LABEL(Xresume_ioapic_edge17)
+ .quad _C_LABEL(Xintr_ioapic_edge18), _C_LABEL(Xrecurse_ioapic_edge18)
+ .quad _C_LABEL(Xresume_ioapic_edge18)
+ .quad _C_LABEL(Xintr_ioapic_edge19), _C_LABEL(Xrecurse_ioapic_edge19)
+ .quad _C_LABEL(Xresume_ioapic_edge19)
+ .quad _C_LABEL(Xintr_ioapic_edge20), _C_LABEL(Xrecurse_ioapic_edge20)
+ .quad _C_LABEL(Xresume_ioapic_edge20)
+ .quad _C_LABEL(Xintr_ioapic_edge21), _C_LABEL(Xrecurse_ioapic_edge21)
+ .quad _C_LABEL(Xresume_ioapic_edge21)
+ .quad _C_LABEL(Xintr_ioapic_edge22), _C_LABEL(Xrecurse_ioapic_edge22)
+ .quad _C_LABEL(Xresume_ioapic_edge22)
+ .quad _C_LABEL(Xintr_ioapic_edge23), _C_LABEL(Xrecurse_ioapic_edge23)
+ .quad _C_LABEL(Xresume_ioapic_edge23)
+ .quad _C_LABEL(Xintr_ioapic_edge24), _C_LABEL(Xrecurse_ioapic_edge24)
+ .quad _C_LABEL(Xresume_ioapic_edge24)
+ .quad _C_LABEL(Xintr_ioapic_edge25), _C_LABEL(Xrecurse_ioapic_edge25)
+ .quad _C_LABEL(Xresume_ioapic_edge25)
+ .quad _C_LABEL(Xintr_ioapic_edge26), _C_LABEL(Xrecurse_ioapic_edge26)
+ .quad _C_LABEL(Xresume_ioapic_edge26)
+ .quad _C_LABEL(Xintr_ioapic_edge27), _C_LABEL(Xrecurse_ioapic_edge27)
+ .quad _C_LABEL(Xresume_ioapic_edge27)
+ .quad _C_LABEL(Xintr_ioapic_edge28), _C_LABEL(Xrecurse_ioapic_edge28)
+ .quad _C_LABEL(Xresume_ioapic_edge28)
+ .quad _C_LABEL(Xintr_ioapic_edge29), _C_LABEL(Xrecurse_ioapic_edge29)
+ .quad _C_LABEL(Xresume_ioapic_edge29)
+ .quad _C_LABEL(Xintr_ioapic_edge30), _C_LABEL(Xrecurse_ioapic_edge30)
+ .quad _C_LABEL(Xresume_ioapic_edge30)
+ .quad _C_LABEL(Xintr_ioapic_edge31), _C_LABEL(Xrecurse_ioapic_edge31)
+ .quad _C_LABEL(Xresume_ioapic_edge31)
+
+ .globl _C_LABEL(ioapic_level_stubs)
+_C_LABEL(ioapic_level_stubs):
+ .quad _C_LABEL(Xintr_ioapic_level0), _C_LABEL(Xrecurse_ioapic_level0)
+ .quad _C_LABEL(Xresume_ioapic_level0)
+ .quad _C_LABEL(Xintr_ioapic_level1), _C_LABEL(Xrecurse_ioapic_level1)
+ .quad _C_LABEL(Xresume_ioapic_level1)
+ .quad _C_LABEL(Xintr_ioapic_level2), _C_LABEL(Xrecurse_ioapic_level2)
+ .quad _C_LABEL(Xresume_ioapic_level2)
+ .quad _C_LABEL(Xintr_ioapic_level3), _C_LABEL(Xrecurse_ioapic_level3)
+ .quad _C_LABEL(Xresume_ioapic_level3)
+ .quad _C_LABEL(Xintr_ioapic_level4), _C_LABEL(Xrecurse_ioapic_level4)
+ .quad _C_LABEL(Xresume_ioapic_level4)
+ .quad _C_LABEL(Xintr_ioapic_level5), _C_LABEL(Xrecurse_ioapic_level5)
+ .quad _C_LABEL(Xresume_ioapic_level5)
+ .quad _C_LABEL(Xintr_ioapic_level6), _C_LABEL(Xrecurse_ioapic_level6)
+ .quad _C_LABEL(Xresume_ioapic_level6)
+ .quad _C_LABEL(Xintr_ioapic_level7), _C_LABEL(Xrecurse_ioapic_level7)
+ .quad _C_LABEL(Xresume_ioapic_level7)
+ .quad _C_LABEL(Xintr_ioapic_level8), _C_LABEL(Xrecurse_ioapic_level8)
+ .quad _C_LABEL(Xresume_ioapic_level8)
+ .quad _C_LABEL(Xintr_ioapic_level9), _C_LABEL(Xrecurse_ioapic_level9)
+ .quad _C_LABEL(Xresume_ioapic_level9)
+ .quad _C_LABEL(Xintr_ioapic_level10), _C_LABEL(Xrecurse_ioapic_level10)
+ .quad _C_LABEL(Xresume_ioapic_level10)
+ .quad _C_LABEL(Xintr_ioapic_level11), _C_LABEL(Xrecurse_ioapic_level11)
+ .quad _C_LABEL(Xresume_ioapic_level11)
+ .quad _C_LABEL(Xintr_ioapic_level12), _C_LABEL(Xrecurse_ioapic_level12)
+ .quad _C_LABEL(Xresume_ioapic_level12)
+ .quad _C_LABEL(Xintr_ioapic_level13), _C_LABEL(Xrecurse_ioapic_level13)
+ .quad _C_LABEL(Xresume_ioapic_level13)
+ .quad _C_LABEL(Xintr_ioapic_level14), _C_LABEL(Xrecurse_ioapic_level14)
+ .quad _C_LABEL(Xresume_ioapic_level14)
+ .quad _C_LABEL(Xintr_ioapic_level15), _C_LABEL(Xrecurse_ioapic_level15)
+ .quad _C_LABEL(Xresume_ioapic_level15)
+ .quad _C_LABEL(Xintr_ioapic_level16), _C_LABEL(Xrecurse_ioapic_level16)
+ .quad _C_LABEL(Xresume_ioapic_level16)
+ .quad _C_LABEL(Xintr_ioapic_level17), _C_LABEL(Xrecurse_ioapic_level17)
+ .quad _C_LABEL(Xresume_ioapic_level17)
+ .quad _C_LABEL(Xintr_ioapic_level18), _C_LABEL(Xrecurse_ioapic_level18)
+ .quad _C_LABEL(Xresume_ioapic_level18)
+ .quad _C_LABEL(Xintr_ioapic_level19), _C_LABEL(Xrecurse_ioapic_level19)
+ .quad _C_LABEL(Xresume_ioapic_level19)
+ .quad _C_LABEL(Xintr_ioapic_level20), _C_LABEL(Xrecurse_ioapic_level20)
+ .quad _C_LABEL(Xresume_ioapic_level20)
+ .quad _C_LABEL(Xintr_ioapic_level21), _C_LABEL(Xrecurse_ioapic_level21)
+ .quad _C_LABEL(Xresume_ioapic_level21)
+ .quad _C_LABEL(Xintr_ioapic_level22), _C_LABEL(Xrecurse_ioapic_level22)
+ .quad _C_LABEL(Xresume_ioapic_level22)
+ .quad _C_LABEL(Xintr_ioapic_level23), _C_LABEL(Xrecurse_ioapic_level23)
+ .quad _C_LABEL(Xresume_ioapic_level23)
+ .quad _C_LABEL(Xintr_ioapic_level24), _C_LABEL(Xrecurse_ioapic_level24)
+ .quad _C_LABEL(Xresume_ioapic_level24)
+ .quad _C_LABEL(Xintr_ioapic_level25), _C_LABEL(Xrecurse_ioapic_level25)
+ .quad _C_LABEL(Xresume_ioapic_level25)
+ .quad _C_LABEL(Xintr_ioapic_level26), _C_LABEL(Xrecurse_ioapic_level26)
+ .quad _C_LABEL(Xresume_ioapic_level26)
+ .quad _C_LABEL(Xintr_ioapic_level27), _C_LABEL(Xrecurse_ioapic_level27)
+ .quad _C_LABEL(Xresume_ioapic_level27)
+ .quad _C_LABEL(Xintr_ioapic_level28), _C_LABEL(Xrecurse_ioapic_level28)
+ .quad _C_LABEL(Xresume_ioapic_level28)
+ .quad _C_LABEL(Xintr_ioapic_level29), _C_LABEL(Xrecurse_ioapic_level29)
+ .quad _C_LABEL(Xresume_ioapic_level29)
+ .quad _C_LABEL(Xintr_ioapic_level30), _C_LABEL(Xrecurse_ioapic_level30)
+ .quad _C_LABEL(Xresume_ioapic_level30)
+ .quad _C_LABEL(Xintr_ioapic_level31), _C_LABEL(Xrecurse_ioapic_level31)
+ .quad _C_LABEL(Xresume_ioapic_level31)
+#endif
+
+ .data
+/*
+ * Symbols that vmstat -i wants, even though they're not used.
+ */
+ .globl _C_LABEL(intrnames)
+_C_LABEL(intrnames):
+ .globl _C_LABEL(eintrnames)
+_C_LABEL(eintrnames):
+
+ .globl _C_LABEL(intrcnt)
+_C_LABEL(intrcnt):
+ .globl _C_LABEL(eintrcnt)
+_C_LABEL(eintrcnt):
+
+/*
+ * Soft interrupt handlers
+ */
+ .globl _C_LABEL(netisr)
+_C_LABEL(netisr):
+ .word 0
+
+IDTVEC(softserial)
+ movl $IPL_SOFTSERIAL, CPUVAR(ILEVEL)
+ incl CPUVAR(IDEPTH)
+#ifdef MULTIPROCESSOR
+ call _C_LABEL(x86_softintlock)
+#endif
+ movq CPUVAR(ISOURCES) + SIR_SERIAL * 8, %r12
+ incq IS_EVCNT(%r12)
+ movl $X86_SOFTINTR_SOFTSERIAL,%edi
+ call _C_LABEL(softintr_dispatch)
+#ifdef MULTIPROCESSOR
+ call _C_LABEL(x86_softintunlock)
+#endif
+ decl CPUVAR(IDEPTH)
+ jmp *%r13
+
+IDTVEC(softnet)
+ movl $IPL_SOFTNET, CPUVAR(ILEVEL)
+ incl CPUVAR(IDEPTH)
+#ifdef MULTIPROCESSOR
+ call _C_LABEL(x86_softintlock)
+#endif
+ movq CPUVAR(ISOURCES) + SIR_NET * 8, %r12
+ incq IS_EVCNT(%r12)
+
+ xorq %r12,%r12
+ xchgl _C_LABEL(netisr),%r12d
+
+ /* XXX Do the legacy netisrs here for now. */
+#define DONETISR(s, c) \
+ .globl _C_LABEL(c) ;\
+ testl $(1 << s),%r12d ;\
+ jz 1f ;\
+ call _C_LABEL(c) ;\
+1:
+#include <net/netisr_dispatch.h>
+
+ movl $X86_SOFTINTR_SOFTNET,%edi
+ call _C_LABEL(softintr_dispatch)
+#ifdef MULTIPROCESSOR
+ call _C_LABEL(x86_softintunlock)
+#endif
+ decl CPUVAR(IDEPTH)
+ jmp *%r13
+
+IDTVEC(softclock)
+ movl $IPL_SOFTCLOCK, CPUVAR(ILEVEL)
+ incl CPUVAR(IDEPTH)
+#ifdef MULTIPROCESSOR
+ call _C_LABEL(x86_softintlock)
+#endif
+ movq CPUVAR(ISOURCES) + SIR_CLOCK * 8, %r12
+ incq IS_EVCNT(%r12)
+
+ movl $X86_SOFTINTR_SOFTCLOCK,%edi
+ call _C_LABEL(softintr_dispatch)
+#ifdef MULTIPROCESSOR
+ call _C_LABEL(x86_softintunlock)
+#endif
+ decl CPUVAR(IDEPTH)
+ jmp *%r13
diff --git a/sys/arch/amd64/amd64/vm_machdep.c b/sys/arch/amd64/amd64/vm_machdep.c
new file mode 100644
index 00000000000..40d41ee2bf3
--- /dev/null
+++ b/sys/arch/amd64/amd64/vm_machdep.c
@@ -0,0 +1,379 @@
+/* $OpenBSD: vm_machdep.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: vm_machdep.c,v 1.1 2003/04/26 18:39:33 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1995 Charles M. Hannum. All rights reserved.
+ * Copyright (c) 1982, 1986 The Regents of the University of California.
+ * Copyright (c) 1989, 1990 William Jolitz
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department, and William Jolitz.
+ *
+ * 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.
+ *
+ * @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91
+ */
+
+/*
+ * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+#include <sys/buf.h>
+#include <sys/user.h>
+#include <sys/core.h>
+#include <sys/exec.h>
+#include <sys/ptrace.h>
+#include <sys/signalvar.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/cpu.h>
+#include <machine/gdt.h>
+#include <machine/reg.h>
+#include <machine/specialreg.h>
+#include <machine/fpu.h>
+#include <machine/mtrr.h>
+
+void setredzone(struct proc *);
+void syscall_intern(struct proc *p); /* syscall.c */
+
+/*
+ * Finish a fork operation, with process p2 nearly set up.
+ * Copy and update the kernel stack and pcb, making the child
+ * ready to run, and marking it so that it can return differently
+ * than the parent. Returns 1 in the child process, 0 in the parent.
+ * We currently double-map the user area so that the stack is at the same
+ * address in each process; in the future we will probably relocate
+ * the frame pointers on the stack after copying.
+ */
+void
+cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
+ void (*func)(void *), void *arg)
+{
+ struct pcb *pcb = &p2->p_addr->u_pcb;
+ struct trapframe *tf;
+ struct switchframe *sf;
+
+ /*
+ * If fpuproc != p1, then the fpu h/w state is irrelevant and the
+ * state had better already be in the pcb. This is true for forks
+ * but not for dumps.
+ *
+ * If fpuproc == p1, then we have to save the fpu h/w state to
+ * p1's pcb so that we can copy it.
+ */
+ if (p1->p_addr->u_pcb.pcb_fpcpu != NULL)
+ fpusave_proc(p1, 1);
+
+ p2->p_md.md_flags = p1->p_md.md_flags;
+ syscall_intern(p2);
+
+ /* Copy pcb from proc p1 to p2. */
+ if (p1 == curproc) {
+ /* Sync the PCB before we copy it. */
+ savectx(curpcb);
+ }
+#ifdef DIAGNOSTIC
+ else if (p1 != &proc0)
+ panic("cpu_fork: curproc");
+#endif
+ *pcb = p1->p_addr->u_pcb;
+
+ /*
+ * Preset these so that gdt_compact() doesn't get confused if called
+ * during the allocations below.
+ *
+ * Note: pcb_ldt_sel is handled in the pmap_activate() call when
+ * we run the new process.
+ */
+ p2->p_md.md_tss_sel = GSEL(GNULL_SEL, SEL_KPL);
+
+ /*
+ * Activate the addres space. Note this will refresh pcb_ldt_sel.
+ */
+ pmap_activate(p2);
+
+ /* Fix up the TSS. */
+ pcb->pcb_tss.tss_rsp0 = (u_int64_t)p2->p_addr + USPACE - 16;
+ pcb->pcb_tss.tss_ist[0] = (u_int64_t)p2->p_addr + PAGE_SIZE - 16;
+ p2->p_md.md_tss_sel = tss_alloc(pcb);
+
+ /*
+ * Copy the trapframe.
+ */
+ p2->p_md.md_regs = tf = (struct trapframe *)pcb->pcb_tss.tss_rsp0 - 1;
+ *tf = *p1->p_md.md_regs;
+
+ setredzone(p2);
+
+ /*
+ * If specified, give the child a different stack.
+ */
+ if (stack != NULL)
+ tf->tf_rsp = (u_int64_t)stack + stacksize;
+
+ sf = (struct switchframe *)tf - 1;
+ sf->sf_ppl = IPL_NONE;
+ sf->sf_r12 = (u_int64_t)func;
+ sf->sf_r13 = (u_int64_t)arg;
+ if (func == child_return)
+ sf->sf_rip = (u_int64_t)child_trampoline;
+ else
+ sf->sf_rip = (u_int64_t)proc_trampoline;
+ pcb->pcb_rsp = (u_int64_t)sf;
+ pcb->pcb_rbp = 0;
+}
+
+void
+cpu_swapin(struct proc *p)
+{
+ setredzone(p);
+}
+
+void
+cpu_swapout(struct proc *p)
+{
+
+ /*
+ * Make sure we save the FP state before the user area vanishes.
+ */
+ fpusave_proc(p, 1);
+}
+
+/*
+ * cpu_exit is called as the last action during exit.
+ *
+ * We clean up a little and then call switch_exit() with the old proc as an
+ * argument. switch_exit() first switches to proc0's context, and finally
+ * jumps into switch() to wait for another process to wake up.
+ */
+void
+cpu_exit(struct proc *p)
+{
+
+ /* If we were using the FPU, forget about it. */
+ if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
+ fpusave_proc(p, 0);
+
+ if (p->p_md.md_flags & MDP_USEDMTRR)
+ mtrr_clean(p);
+
+ /*
+ * No need to do user LDT cleanup here; it's handled in
+ * pmap_destroy().
+ */
+
+ uvmexp.swtch++;
+ switch_exit(p, exit2);
+}
+
+/*
+ * cpu_wait is called from reaper() to let machine-dependent
+ * code free machine-dependent resources that couldn't be freed
+ * in cpu_exit().
+ */
+void
+cpu_wait(struct proc *p)
+{
+ /* Nuke the TSS. */
+ tss_free(p->p_md.md_tss_sel);
+}
+
+/*
+ * Dump the machine specific segment at the start of a core dump.
+ */
+struct md_core {
+ struct reg intreg;
+ struct fpreg freg;
+};
+
+int
+cpu_coredump(struct proc *p, struct vnode *vp, struct ucred *cred,
+ struct core *chdr)
+{
+ struct md_core md_core;
+ struct coreseg cseg;
+ int error;
+
+ CORE_SETMAGIC(*chdr, COREMAGIC, MID_MACHINE, 0);
+ chdr->c_hdrsize = ALIGN(sizeof(*chdr));
+ chdr->c_seghdrsize = ALIGN(sizeof(cseg));
+ chdr->c_cpusize = sizeof(md_core);
+
+ /* Save integer registers. */
+ error = process_read_regs(p, &md_core.intreg);
+ if (error)
+ return error;
+
+ /* Save floating point registers. */
+ error = process_read_fpregs(p, &md_core.freg);
+ if (error)
+ return error;
+
+ CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_MACHINE, CORE_CPU);
+ cseg.c_addr = 0;
+ cseg.c_size = chdr->c_cpusize;
+
+ error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&cseg, chdr->c_seghdrsize,
+ (off_t)chdr->c_hdrsize, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred,
+ NULL, p);
+ if (error)
+ return error;
+
+ error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&md_core, sizeof(md_core),
+ (off_t)(chdr->c_hdrsize + chdr->c_seghdrsize), UIO_SYSSPACE,
+ IO_NODELOCKED|IO_UNIT, cred, NULL, p);
+ if (error)
+ return error;
+
+ chdr->c_nseg++;
+ return 0;
+}
+
+/*
+ * Set a red zone in the kernel stack after the u. area.
+ */
+void
+setredzone(struct proc *p)
+{
+#if 0
+ pmap_remove(pmap_kernel(), (vaddr_t)p->p_addr + PAGE_SIZE,
+ (vaddr_t)p->p_addr + 2 * PAGE_SIZE);
+ pmap_update(pmap_kernel());
+#endif
+}
+
+
+/*
+ * Move pages from one kernel virtual address to another.
+ * Both addresses are assumed to reside in the Sysmap.
+ */
+void
+pagemove(caddr_t from, caddr_t to, size_t size)
+{
+ pt_entry_t *fpte, *tpte, ofpte, otpte;
+ int32_t cpumask = 0;
+
+#ifdef DIAGNOSTIC
+ if ((size & PAGE_MASK) != 0)
+ panic("pagemove");
+#endif
+ fpte = kvtopte((vaddr_t)from);
+ tpte = kvtopte((vaddr_t)to);
+#ifdef LARGEPAGES
+ /* XXX For now... */
+ if (*fpte & PG_PS)
+ panic("pagemove: fpte PG_PS");
+ if (*tpte & PG_PS)
+ panic("pagemove: tpte PG_PS");
+#endif
+ while (size > 0) {
+ otpte = *tpte;
+ ofpte = *fpte;
+ *tpte++ = *fpte;
+ *fpte++ = 0;
+ if (otpte & PG_V)
+ pmap_tlb_shootdown(pmap_kernel(),
+ (vaddr_t)to, otpte, &cpumask);
+ if (ofpte & PG_V)
+ pmap_tlb_shootdown(pmap_kernel(),
+ (vaddr_t)from, ofpte, &cpumask);
+ from += PAGE_SIZE;
+ to += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+ pmap_tlb_shootnow(cpumask);
+}
+
+/*
+ * Map a user I/O request into kernel virtual address space.
+ * Note: the pages are already locked by uvm_vslock(), so we
+ * do not need to pass an access_type to pmap_enter().
+ */
+void
+vmapbuf(struct buf *bp, vsize_t len)
+{
+ vaddr_t faddr, taddr, off;
+ paddr_t fpa;
+
+ if ((bp->b_flags & B_PHYS) == 0)
+ panic("vmapbuf");
+ faddr = trunc_page((vaddr_t)bp->b_saveaddr = bp->b_data);
+ off = (vaddr_t)bp->b_data - faddr;
+ len = round_page(off + len);
+ taddr= uvm_km_valloc_wait(phys_map, len);
+ bp->b_data = (caddr_t)(taddr + off);
+ /*
+ * The region is locked, so we expect that pmap_pte() will return
+ * non-NULL.
+ * XXX: unwise to expect this in a multithreaded environment.
+ * anything can happen to a pmap between the time we lock a
+ * region, release the pmap lock, and then relock it for
+ * the pmap_extract().
+ *
+ * no need to flush TLB since we expect nothing to be mapped
+ * where we we just allocated (TLB will be flushed when our
+ * mapping is removed).
+ */
+ while (len) {
+ (void) pmap_extract(vm_map_pmap(&bp->b_proc->p_vmspace->vm_map),
+ faddr, &fpa);
+ pmap_kenter_pa(taddr, fpa, VM_PROT_READ|VM_PROT_WRITE);
+ faddr += PAGE_SIZE;
+ taddr += PAGE_SIZE;
+ len -= PAGE_SIZE;
+ }
+}
+
+/*
+ * Unmap a previously-mapped user I/O request.
+ */
+void
+vunmapbuf(struct buf *bp, vsize_t len)
+{
+ vaddr_t addr, off;
+
+ if ((bp->b_flags & B_PHYS) == 0)
+ panic("vunmapbuf");
+ addr = trunc_page((vaddr_t)bp->b_data);
+ off = (vaddr_t)bp->b_data - addr;
+ len = round_page(off + len);
+ pmap_kremove(addr, len);
+ pmap_update(pmap_kernel());
+ uvm_km_free_wakeup(phys_map, addr, len);
+ bp->b_data = bp->b_saveaddr;
+ bp->b_saveaddr = 0;
+}
diff --git a/sys/arch/amd64/amd64/wscons_machdep.c b/sys/arch/amd64/amd64/wscons_machdep.c
new file mode 100644
index 00000000000..47d05e7e942
--- /dev/null
+++ b/sys/arch/amd64/amd64/wscons_machdep.c
@@ -0,0 +1,169 @@
+/* $OpenBSD: wscons_machdep.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+
+/*
+ * Copyright (c) 2001 Aaron Campbell
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Aaron Campbell.
+ * 4. 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 OR HIS RELATIVES 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 MIND, 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/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/extent.h>
+
+#include <machine/bus.h>
+
+#include <dev/cons.h>
+
+#include "vga.h"
+#include "ega.h"
+#include "pcdisplay.h"
+#if (NVGA > 0) || (NEGA > 0) || (NPCDISPLAY > 0)
+#include <dev/ic/mc6845reg.h>
+#include <dev/ic/pcdisplayvar.h>
+#if (NVGA > 0)
+#include <dev/ic/vgareg.h>
+#include <dev/ic/vgavar.h>
+#endif
+#if (NEGA > 0)
+#include <dev/isa/egavar.h>
+#endif
+#if (NPCDISPLAY > 0)
+#include <dev/isa/pcdisplayvar.h>
+#endif
+#endif
+
+#include "wsdisplay.h"
+#if NWSDISPLAY > 0
+#include <dev/wscons/wsdisplayvar.h>
+#endif
+
+#include "pckbc.h"
+#if (NPCKBC > 0)
+#include <dev/isa/isareg.h>
+#include <dev/ic/i8042reg.h>
+#include <dev/ic/pckbcvar.h>
+#endif
+#include "pckbd.h" /* for pckbc_machdep_cnattach */
+#include "ukbd.h"
+#if (NPCKBD > 0) || (NUKBD > 0)
+#include <dev/wscons/wskbdvar.h>
+#endif
+#if (NUKBD > 0)
+#include <dev/usb/ukbdvar.h>
+#endif
+
+void wscnprobe(struct consdev *);
+void wscninit(struct consdev *);
+void wscnputc(dev_t, char);
+int wscngetc(dev_t);
+void wscnpollc(dev_t, int);
+
+void
+wscnprobe(cp)
+ struct consdev *cp;
+{
+ int maj;
+
+ /* locate the major number */
+ for (maj = 0; maj < nchrdev; maj++) {
+ if (cdevsw[maj].d_open == wsdisplayopen)
+ break;
+ }
+
+ if (maj == nchrdev) {
+ /* we are not in cdevsw[], give up */
+ panic("wsdisplay is not in cdevsw[]");
+ }
+
+ cp->cn_dev = makedev(maj, 0);
+ cp->cn_pri = CN_INTERNAL;
+}
+
+void
+wscninit(cp)
+ struct consdev *cp;
+{
+ static int initted;
+
+ if (initted)
+ return;
+
+ initted = 1;
+
+#if (NVGA > 0) || (NEGA > 0) || (NPCDISPLAY > 0)
+#if (NVGA > 0)
+ if (!vga_cnattach(X86_BUS_SPACE_IO, X86_BUS_SPACE_MEM, -1, 1))
+ goto dokbd;
+#endif
+#if (NEGA > 0)
+ if (!ega_cnattach(X86_BUS_SPACE_IO, X86_BUS_SPACE_MEM))
+ goto dokbd;
+#endif
+#if (NPCDISPLAY > 0)
+ if (!pcdisplay_cnattach(X86_BUS_SPACE_IO, X86_BUS_SPACE_MEM))
+ goto dokbd;
+#endif
+ if (0) goto dokbd; /* XXX stupid gcc */
+dokbd:
+#if (NPCKBC > 0)
+ if (!pckbc_cnattach(X86_BUS_SPACE_IO, IO_KBD, KBCMDP, PCKBC_KBD_SLOT))
+ return;
+#endif
+#if (NUKBD > 0)
+ if (!ukbd_cnattach())
+ return;
+#endif
+#endif /* VGA | EGA | PCDISPLAY */
+ return;
+}
+
+void
+wscnputc(dev, i)
+ dev_t dev;
+ char i;
+{
+ wsdisplay_cnputc(dev, (int)i);
+}
+
+int
+wscngetc(dev)
+ dev_t dev;
+{
+ return (wskbd_cngetc(dev));
+}
+
+void
+wscnpollc(dev, on)
+ dev_t dev;
+ int on;
+{
+ wskbd_cnpollc(dev, on);
+}
diff --git a/sys/arch/amd64/compile/.cvsignore b/sys/arch/amd64/compile/.cvsignore
new file mode 100644
index 00000000000..db5b0e04a3a
--- /dev/null
+++ b/sys/arch/amd64/compile/.cvsignore
@@ -0,0 +1 @@
+GENERIC
diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC
new file mode 100644
index 00000000000..0cd955cdf85
--- /dev/null
+++ b/sys/arch/amd64/conf/GENERIC
@@ -0,0 +1,73 @@
+# $OpenBSD: GENERIC,v 1.1 2004/01/28 01:39:39 mickey Exp $
+
+machine amd64
+
+include "../../../conf/GENERIC"
+
+maxusers 32
+
+config bsd swap generic
+option DEBUG
+option SYSCALL_DEBUG
+
+mainbus0 at root
+cpu* at mainbus?
+
+isa0 at mainbus0
+pci* at mainbus0 bus ?
+
+option PCIVERBOSE
+pchb* at pci? dev ? function ?
+ppb* at pci? dev ? function ?
+pci* at ppb? bus ?
+pci* at pchb? bus ?
+
+pckbc0 at isa?
+pckbd* at pckbc?
+
+com0 at isa? port 0x3f8 irq 4 # standard PC serial ports
+com1 at isa? port 0x2f8 irq 3
+
+#vga0 at isa?
+vga* at pci? dev ? function ?
+wsdisplay* at vga? console ?
+wskbd* at pckbd? console ?
+
+skc* at pci? dev ? function ?
+sk* at skc?
+fxp* at pci? dev ? function ?
+eephy* at mii? phy ?
+inphy* at mii? phy ?
+iophy* at mii? phy ?
+nsphy* at mii? phy ?
+ukphy* at mii? phy ?
+
+ahc* at pci? dev ? function ? # Adaptec 2940 SCSI controllers
+scsibus* at ahc?
+
+pciide* at pci? dev ? function ?
+wd* at pciide? channel ? drive ? flags 0x0000
+
+# PCI USB Controllers
+uhci* at pci? # Universal Host Controller (Intel)
+ohci* at pci? # Open Host Controller
+
+# USB bus support
+usb* at uhci?
+usb* at ohci?
+
+uhub* at usb? # USB Hubs
+uhub* at uhub? port ? configuration ? # USB Hubs
+ums* at uhidev? reportid ?
+wsmouse* at ums? mux 0
+uhidev* at uhub? port ? configuration ? interface ?
+ukbd* at uhidev? reportid ?
+wskbd* at ukbd? console ? mux 1
+uhid* at uhidev? reportid ?
+
+sd* at scsibus? target ? lun ? # SCSI disk drives
+cd* at scsibus? target ? lun ? # SCSI CD-ROM drives
+
+# mouse & keyboard multiplexor pseudo-devices
+pseudo-device wsmux 2
+pseudo-device crypto 1
diff --git a/sys/arch/amd64/conf/Makefile.amd64 b/sys/arch/amd64/conf/Makefile.amd64
new file mode 100644
index 00000000000..4909063e7dc
--- /dev/null
+++ b/sys/arch/amd64/conf/Makefile.amd64
@@ -0,0 +1,214 @@
+# $OpenBSD: Makefile.amd64,v 1.1 2004/01/28 01:39:39 mickey Exp $
+
+# Makefile for OpenBSD
+#
+# This makefile is constructed from a machine description:
+# config machineid
+# Most changes should be made in the machine description
+# /sys/arch/amd64/conf/``machineid''
+# after which you should do
+# config machineid
+# Machine generic makefile changes should be made in
+# /sys/arch/amd64/conf/Makefile.amd64
+# after which config should be rerun for all machines of that type.
+#
+# N.B.: NO DEPENDENCIES ON FOLLOWING FLAGS ARE VISIBLE TO MAKEFILE
+# IF YOU CHANGE THE DEFINITION OF ANY OF THESE RECOMPILE EVERYTHING
+#
+# -DTRACE compile in kernel tracing hooks
+# -DQUOTA compile in file system quotas
+
+# DEBUG is set to -g if debugging.
+# PROF is set to -pg if profiling.
+
+.include <bsd.own.mk>
+
+MKDEP?= mkdep
+SIZE?= size
+STRIP?= strip
+
+# source tree is located via $S relative to the compilation directory
+.ifndef S
+S!= cd ../../../..; pwd
+.endif
+AMD64= $S/arch/amd64
+
+INCLUDES= -nostdinc -I. -I$S/arch -I$S
+CPPFLAGS= ${INCLUDES} ${IDENT} -D_KERNEL -U__NetBSD__ -D__OpenBSD__ \
+ -Damd64 -Dx86_64
+CDIAGFLAGS= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \
+ -Wno-uninitialized -Wno-format -Wno-main -Wno-sign-compare
+
+CMACHFLAGS+= -mcmodel=kernel -mno-red-zone -fno-strict-aliasing \
+ -mno-sse2 -mno-sse -mno-3dnow -mno-mmx -msoft-float \
+ -fno-builtin-printf -fno-builtin-log
+# -fno-stack-protector
+
+COPTS?= -O2
+CFLAGS= ${DEBUG} ${CDIAGFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE}
+AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE
+LINKFLAGS= -Ttext 0xffffffff80100000 -e start -X
+STRIPFLAGS= -g -x
+
+HOSTCC= ${CC}
+HOSTED_CPPFLAGS=${CPPFLAGS:S/^-nostdinc$//}
+HOSTED_CFLAGS= ${CFLAGS}
+
+### find out what to use for libkern
+.include "$S/lib/libkern/Makefile.inc"
+.ifndef PROF
+LIBKERN= ${KERNLIB}
+.else
+LIBKERN= ${KERNLIB_PROF}
+.endif
+
+### find out what to use for libcompat
+.include "$S/compat/common/Makefile.inc"
+.ifndef PROF
+LIBCOMPAT= ${COMPATLIB}
+.else
+LIBCOMPAT= ${COMPATLIB_PROF}
+.endif
+
+# compile rules: rules are named ${TYPE}_${SUFFIX}${CONFIG_DEP}
+# where TYPE is NORMAL, DRIVER, or PROFILE; SUFFIX is the file suffix,
+# capitalized (e.g. C for a .c file), and CONFIG_DEP is _C if the file
+# is marked as config-dependent.
+
+NORMAL_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
+NORMAL_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $<
+
+DRIVER_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c $<
+DRIVER_C_C= ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} ${PARAM} -c $<
+
+NORMAL_S= ${CC} ${AFLAGS} ${CPPFLAGS} -c $<
+NORMAL_S_C= ${CC} ${AFLAGS} ${CPPFLAGS} ${PARAM} -c $<
+
+HOSTED_C= ${HOSTCC} ${HOSTED_CFLAGS} ${HOSTED_CPPFLAGS} -c $<
+
+%OBJS
+
+%CFILES
+
+%SFILES
+
+# load lines for config "xxx" will be emitted as:
+# xxx: ${SYSTEM_DEP} swapxxx.o
+# ${SYSTEM_LD_HEAD}
+# ${SYSTEM_LD} swapxxx.o
+# ${SYSTEM_LD_TAIL}
+SYSTEM_OBJ= locore.o vector.o copy.o microtime.o spl.o \
+ param.o ioconf.o ${OBJS} ${LIBKERN} ${LIBCOMPAT}
+SYSTEM_DEP= Makefile ${SYSTEM_OBJ}
+SYSTEM_LD_HEAD= rm -f $@
+SYSTEM_LD= @echo ${LD} ${LINKFLAGS} -o $@ '$${SYSTEM_OBJ}' vers.o; \
+ ${LD} ${LINKFLAGS} -o $@ ${SYSTEM_OBJ} vers.o
+SYSTEM_LD_TAIL= @${SIZE} $@; chmod 755 $@
+
+DEBUG?=
+.if ${DEBUG} == "-g"
+LINKFLAGS+= -X
+SYSTEM_LD_TAIL+=; \
+ echo cp $@ $@.gdb; rm -f $@.gdb; cp $@ $@.gdb; \
+ echo ${STRIP} ${STRIPFLAGS} $@; ${STRIP} ${STRIPFLAGS} $@
+.else
+LINKFLAGS+= -x
+.endif
+
+%LOAD
+
+assym.h: $S/kern/genassym.sh ${AMD64}/amd64/genassym.cf Makefile
+ sh $S/kern/genassym.sh ${CC} ${CFLAGS} ${CPPFLAGS} \
+ ${PARAM} < ${AMD64}/amd64/genassym.cf > assym.h.tmp && \
+ mv -f assym.h.tmp assym.h
+
+param.c: $S/conf/param.c
+ rm -f param.c
+ cp $S/conf/param.c .
+
+param.o: param.c Makefile
+ ${NORMAL_C_C}
+
+ioconf.o: ioconf.c
+ ${NORMAL_C}
+
+newvers: ${SYSTEM_DEP} ${SYSTEM_SWAP_DEP}
+ sh $S/conf/newvers.sh
+ ${CC} ${CFLAGS} ${CPPFLAGS} ${PROF} -c vers.c
+
+
+clean::
+ rm -f eddep *bsd bsd.gdb tags *.[io] [a-z]*.s \
+ [Ee]rrs linterrs makelinks assym.h
+
+lint:
+ @lint -hbxncez -Dvolatile= ${CPPFLAGS} ${PARAM} -UKGDB \
+ ${CFILES} ${AMD64}/amd64/swapgeneric.c ioconf.c param.c | \
+ grep -v 'static function .* unused'
+
+tags:
+ @echo "see $S/kern/Makefile for tags"
+
+links:
+ egrep '#if' ${CFILES} | sed -f $S/conf/defines | \
+ sed -e 's/:.*//' -e 's/\.c/.o/' | sort -u > dontlink
+ echo ${CFILES} | tr -s ' ' '\12' | sed 's/\.c/.o/' | \
+ sort -u | comm -23 - dontlink | \
+ sed 's,.*/\(.*.o\),rm -f \1; ln -s ../GENERIC/\1 \1,' > makelinks
+ sh makelinks && rm -f dontlink makelinks
+
+AFILES= ${AMD64}/amd64/locore.S ${AMD64}/amd64/vector.S ${AMD64}/amd64/copy.S \
+ ${AMD64}/amd64/microtime.S ${AMD64}/amd64/spl.S
+SRCS= param.c ioconf.c ${AFILES} ${CFILES} ${SFILES}
+depend:: .depend
+.depend: ${SRCS} assym.h param.c ${APMINC}
+ ${MKDEP} ${AFLAGS} ${CPPFLAGS} ${AFILES}
+ ${MKDEP} -a ${CFLAGS} ${CPPFLAGS} param.c ioconf.c ${CFILES}
+# ${MKDEP} -a ${AFLAGS} ${CPPFLAGS} ${SFILES}
+
+
+# depend on root or device configuration
+autoconf.o conf.o: Makefile
+
+# depend on network or filesystem configuration
+uipc_domain.o uipc_proto.o vfs_conf.o: Makefile
+if.o if_tun.o if_loop.o if_ethersubr.o: Makefile
+if_arp.o if_ether.o: Makefile
+ip_input.o ip_output.o in_pcb.o in_proto.o: Makefile
+tcp_subr.o tcp_timer.o tcp_output.o: Makefile
+
+# depend on maxusers
+machdep.o: Makefile
+
+# depend on CPU configuration
+locore.o machdep.o: Makefile
+
+
+locore.o: ${AMD64}/amd64/locore.S assym.h
+ ${NORMAL_S}
+
+vector.o: ${AMD64}/amd64/vector.S assym.h
+ ${NORMAL_S}
+
+copy.o: ${AMD64}/amd64/copy.S assym.h
+ ${NORMAL_S}
+
+microtime.o: ${AMD64}/amd64/microtime.S assym.h
+ ${NORMAL_S}
+
+spl.o: ${AMD64}/amd64/spl.S assym.h
+ ${NORMAL_S}
+
+# The install target can be redefined by putting a
+# install-kernel-${MACHINE_NAME} target into /etc/mk.conf
+MACHINE_NAME!= uname -n
+install: install-kernel-${MACHINE_NAME}
+.if !target(install-kernel-${MACHINE_NAME}})
+install-kernel-${MACHINE_NAME}:
+ rm -f /obsd
+ ln /bsd /obsd
+ cp bsd /nbsd
+ mv /nbsd /bsd
+.endif
+
+%RULES
diff --git a/sys/arch/amd64/conf/files.amd64 b/sys/arch/amd64/conf/files.amd64
new file mode 100644
index 00000000000..608a9f4ac38
--- /dev/null
+++ b/sys/arch/amd64/conf/files.amd64
@@ -0,0 +1,145 @@
+# $OpenBSD: files.amd64,v 1.1 2004/01/28 01:39:39 mickey Exp $
+
+maxpartitions 16
+maxusers 2 16 128
+
+file arch/amd64/amd64/autoconf.c
+file arch/amd64/amd64/conf.c
+file arch/amd64/amd64/disksubr.c disk
+file arch/amd64/amd64/gdt.c
+file arch/amd64/amd64/machdep.c
+file arch/amd64/amd64/identcpu.c
+file arch/amd64/amd64/mem.c
+file arch/amd64/amd64/pmap.c
+file arch/amd64/amd64/process_machdep.c
+file arch/amd64/amd64/sys_machdep.c
+file arch/amd64/amd64/syscall.c
+file arch/amd64/amd64/trap.c
+file arch/amd64/amd64/vm_machdep.c
+file arch/amd64/amd64/fpu.c
+file arch/amd64/amd64/Locore.c
+file arch/amd64/amd64/softintr.c
+file arch/amd64/amd64/i8259.c
+file arch/amd64/amd64/cacheinfo.c
+
+file arch/amd64/amd64/intr.c
+file arch/amd64/amd64/bus_space.c
+file arch/amd64/amd64/bus_dma.c
+
+file arch/amd64/amd64/consinit.c
+file dev/cons.c
+file dev/cninit.c
+
+file arch/amd64/amd64/db_disasm.c ddb
+file arch/amd64/amd64/db_interface.c ddb
+file arch/amd64/amd64/db_memrw.c ddb
+file arch/amd64/amd64/db_trace.c ddb
+
+file netinet/in_cksum.c inet
+
+# Basic clock - required
+file arch/amd64/isa/clock.c
+file dev/clock_subr.c
+
+
+include "dev/mii/files.mii"
+
+include "scsi/files.scsi"
+
+include "dev/i2o/files.i2o"
+
+include "dev/atapiscsi/files.atapiscsi"
+include "dev/ata/files.ata"
+
+define mainbus { }
+device mainbus: isabus, pcibus, mainbus
+attach mainbus at root
+file arch/amd64/amd64/mainbus.c mainbus
+
+define cpu { [apid = -1] }
+device cpu
+attach cpu at mainbus
+file arch/amd64/amd64/cpu.c cpu
+
+
+define lapic
+file arch/amd64/amd64/lapic.c lapic needs-flag
+
+device ioapic: lapic
+attach ioapic at mainbus
+file arch/amd64/amd64/ioapic.c ioapic needs-flag
+
+#
+# PCI drivers
+#
+
+include "dev/pci/files.pci"
+file arch/amd64/pci/pci_machdep.c pci
+file arch/amd64/pci/pciide_machdep.c pciide
+
+# PCI Host bridge chipsets
+device pchb: pcibus
+attach pchb at pci
+file arch/amd64/pci/pchb.c pchb
+
+# PCI-ISA bridges
+device pcib: isabus
+attach pcib at pci
+file arch/amd64/pci/pcib.c pcib
+
+device aapic
+attach aapic at pci
+file arch/amd64/pci/aapic.c aapic
+
+#
+# ISA drivers
+#
+
+include "dev/isa/files.isa"
+include "dev/isa/files.isapnp"
+file arch/amd64/isa/isa_machdep.c isa
+
+# attribute used to represent the "keyboard controller"
+# XXX should be a real device
+define pckbcport { [irq = -1], [port = -1] }
+
+include "dev/wscons/files.wscons"
+include "dev/pckbc/files.pckbc"
+
+file arch/amd64/amd64/wscons_machdep.c wsdisplay
+
+device sysbeep
+attach sysbeep at pcppi
+
+# Floppy disk controller
+device fdc { drive = - 1 }
+attach fdc at isa
+file dev/isa/fdc.c fdc needs-flag
+
+device fd: disk, isa_dma
+attach fd at fdc
+file dev/isa/fd.c fd needs-flag
+
+#
+# USB
+#
+include "dev/usb/files.usb"
+
+#
+# FireWire
+#
+include "dev/ieee1394/files.ieee1394"
+
+#
+# device major numbers
+#
+
+major {ccd = 16}
+major {vnd = 14}
+major {sd = 4}
+major {st = 5}
+major {cd = 6}
+major {rd = 17}
+major {wd = 0}
+major {wt = 3}
+major {fd = 2}
diff --git a/sys/arch/amd64/include/ansi.h b/sys/arch/amd64/include/ansi.h
new file mode 100644
index 00000000000..eba619188a4
--- /dev/null
+++ b/sys/arch/amd64/include/ansi.h
@@ -0,0 +1,87 @@
+/* $NetBSD: ansi.h,v 1.1 2003/04/26 18:39:36 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ansi.h 8.2 (Berkeley) 1/4/94
+ */
+
+#ifndef _ANSI_H_
+#define _ANSI_H_
+
+/*
+ * Types which are fundamental to the implementation and may appear in
+ * more than one standard header are defined here. Standard headers
+ * then use:
+ * #ifdef _BSD_SIZE_T_
+ * typedef _BSD_SIZE_T_ size_t;
+ * #undef _BSD_SIZE_T_
+ * #endif
+ */
+#define _BSD_CLOCK_T_ unsigned int /* clock() */
+#define _BSD_PTRDIFF_T_ long /* ptr1 - ptr2 */
+#define _BSD_SIZE_T_ unsigned long /* sizeof() */
+#define _BSD_SSIZE_T_ long /* byte count or error */
+#define _BSD_TIME_T_ int /* time() */
+#ifdef __GNUC__
+#define _BSD_VA_LIST_ __builtin_va_list /* GCC built-in type */
+#else
+#define _BSD_VA_LIST_ char * /* XXXfvdl should be ok? */
+#endif
+#define _BSD_CLOCKID_T_ int /* clockid_t */
+#define _BSD_TIMER_T_ int /* timer_t */
+
+/*
+ * Runes (wchar_t) is declared to be an ``int'' instead of the more natural
+ * ``unsigned long'' or ``long''. Two things are happening here. It is not
+ * unsigned so that EOF (-1) can be naturally assigned to it and used. Also,
+ * it looks like 10646 will be a 31 bit standard. This means that if your
+ * ints cannot hold 32 bits, you will be in trouble. The reason an int was
+ * chosen over a long is that the is*() and to*() routines take ints (says
+ * ANSI C), but they use _RUNE_T_ instead of int. By changing it here, you
+ * lose a bit of ANSI conformance, but your programs will still work.
+ *
+ * Note that _WCHAR_T_ and _RUNE_T_ must be of the same type. When wchar_t
+ * and rune_t are typedef'd, _WCHAR_T_ will be undef'd, but _RUNE_T remains
+ * defined for ctype.h.
+ */
+#define _BSD_WCHAR_T_ int /* wchar_t */
+#define _BSD_WINT_T_ int /* wint_t */
+#define _BSD_RUNE_T_ int /* rune_t */
+
+/*
+ * We describe off_t here so its declaration can be visible to
+ * stdio without pulling in all of <sys/type.h>, thus appeasing ANSI.
+ */
+#define _BSD_OFF_T_ long long /* file offset */
+
+#endif /* _ANSI_H_ */
diff --git a/sys/arch/amd64/include/apicvar.h b/sys/arch/amd64/include/apicvar.h
new file mode 100644
index 00000000000..e40b9552c18
--- /dev/null
+++ b/sys/arch/amd64/include/apicvar.h
@@ -0,0 +1,58 @@
+/* $OpenBSD: apicvar.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: apicvar.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by RedBack Networks Inc.
+ *
+ * Author: Bill Sommerfeld
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef _X86_APICVAR_H_
+#define _X86_APICVAR_H_
+
+struct apic_attach_args {
+ const char *aaa_name;
+ int apic_id;
+ int apic_version;
+ int flags;
+#define IOAPIC_PICMODE 0x01
+#define IOAPIC_VWIRE 0x02
+ paddr_t apic_address;
+ int apic_vecbase;
+};
+
+void apic_format_redir(char *, char *, int, u_int32_t, u_int32_t);
+
+#endif /* !_X86_APICVAR_H_ */
diff --git a/sys/arch/amd64/include/apmvar.h b/sys/arch/amd64/include/apmvar.h
new file mode 100644
index 00000000000..7be38bb9db4
--- /dev/null
+++ b/sys/arch/amd64/include/apmvar.h
@@ -0,0 +1,300 @@
+/* XXX - DSR */
+/* $OpenBSD: apmvar.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+
+/*
+ * Copyright (c) 1995 John T. Kohl
+ * 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. 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.
+ *
+ */
+#ifndef _I386_APMVAR_H_
+#define _I386_APMVAR_H_
+
+#include <sys/ioccom.h>
+
+/* Advanced Power Management (v1.0 and v1.1 specification)
+ * functions/defines/etc.
+ */
+
+#define APM_VERSION 0x0102
+
+/*
+ * APM info word from boot loader
+ */
+#define APM_16BIT_SUPPORTED 0x00010000
+#define APM_32BIT_SUPPORTED 0x00020000
+#define APM_IDLE_SLOWS 0x00040000
+#define APM_BIOS_PM_DISABLED 0x00080000
+#define APM_BIOS_PM_DISENGAGED 0x00100000
+#define APM_MAJOR(f) (((f) >> 8) & 0xff)
+#define APM_MINOR(f) ((f) & 0xff)
+#define APM_VERMASK 0x0000ffff
+#define APM_NOCLI 0x00010000
+#define APM_BEBATT 0x00020000
+
+/* APM error codes */
+#define APM_ERR_CODE(regs) (((regs)->ax & 0xff00) >> 8)
+#define APM_ERR_PM_DISABLED 0x01
+#define APM_ERR_REALALREADY 0x02
+#define APM_ERR_NOTCONN 0x03
+#define APM_ERR_16ALREADY 0x05
+#define APM_ERR_16NOTSUPP 0x06
+#define APM_ERR_32ALREADY 0x07
+#define APM_ERR_32NOTSUPP 0x08
+#define APM_ERR_UNRECOG_DEV 0x09
+#define APM_ERR_ERANGE 0x0A
+#define APM_ERR_NOTENGAGED 0x0B
+#define APM_ERR_EOPNOSUPP 0x0C
+#define APM_ERR_RTIMER_DISABLED 0x0D
+#define APM_ERR_UNABLE 0x60
+#define APM_ERR_NOEVENTS 0x80
+#define APM_ERR_NOT_PRESENT 0x86
+
+#define APM_DEV_APM_BIOS 0x0000
+#define APM_DEV_ALLDEVS 0x0001
+/* device classes are high byte; device IDs go in low byte */
+#define APM_DEV_DISPLAY(x) (0x0100|((x)&0xff))
+#define APM_DEV_DISK(x) (0x0200|((x)&0xff))
+#define APM_DEV_PARALLEL(x) (0x0300|((x)&0xff))
+#define APM_DEV_SERIAL(x) (0x0400|((x)&0xff))
+#define APM_DEV_NETWORK(x) (0x0500|((x)&0xff))
+#define APM_DEV_PCMCIA(x) (0x0600|((x)&0xff))
+#define APM_DEV_BATTERIES(x) (0x8000|((x)&0xff))
+#define APM_DEV_ALLUNITS 0xff
+/* 0x8100-0xDFFF - reserved */
+/* 0xE000-0xEFFF - OEM-defined */
+/* 0xF000-0xFFFF - reserved */
+
+#define APM_INSTCHECK 0x5300 /* int15 only */
+#define APM_16BIT_SUPPORT 0x01
+#define APM_32BIT_SUPPORT 0x02
+#define APM_CPUIDLE_SLOW 0x04
+#define APM_DISABLED 0x08
+#define APM_DISENGAGED 0x10
+
+#define APM_REAL_CONNECT 0x5301 /* int15 only */
+#define APM_PROT16_CONNECT 0x5302 /* int15 only */
+#define APM_PROT32_CONNECT 0x5303 /* int15 only */
+#define APM_DISCONNECT 0x5304 /* %bx = APM_DEV_APM_BIOS */
+
+#define APM_CPU_IDLE 0x5305
+#define APM_CPU_BUSY 0x5306
+
+#define APM_SET_PWR_STATE 0x5307
+#define APM_SYS_READY 0x0000 /* %cx */
+#define APM_SYS_STANDBY 0x0001
+#define APM_SYS_SUSPEND 0x0002
+#define APM_SYS_OFF 0x0003
+#define APM_LASTREQ_INPROG 0x0004
+#define APM_LASTREQ_REJECTED 0x0005
+/* 0x0006 - 0x001f Reserved system states */
+/* 0x0020 - 0x003f OEM-defined system states */
+/* 0x0040 - 0x007f OEM-defined device states */
+/* 0x0080 - 0xffff Reserved device states */
+
+/* system standby is device ID (%bx) 0x0001, APM_SYS_STANDBY */
+/* system suspend is device ID (%bx) 0x0001, APM_SYS_SUSPEND */
+
+#define APM_PWR_MGT_ENABLE 0x5308
+#define APM_MGT_ALL 0xffff /* %bx */
+#define APM_MGT_DISABLE 0x0 /* %cx */
+#define APM_MGT_ENABLE 0x1
+
+#define APM_SYSTEM_DEFAULTS 0x5309
+#define APM_DEFAULTS_ALL 0xffff /* %bx */
+
+#define APM_POWER_STATUS 0x530a
+#define APM_AC_OFF 0x00
+#define APM_AC_ON 0x01
+#define APM_AC_BACKUP 0x02
+#define APM_AC_UNKNOWN 0xff
+#define APM_BATT_HIGH 0x00
+#define APM_BATT_LOW 0x01
+#define APM_BATT_CRITICAL 0x02
+#define APM_BATT_CHARGING 0x03
+#define APM_BATT_UNKNOWN 0xff
+#define APM_BATT_FLAG_HIGH 0x01
+#define APM_BATT_FLAG_LOW 0x02
+#define APM_BATT_FLAG_CRITICAL 0x04
+#define APM_BATT_FLAG_CHARGING 0x08
+#define APM_BATT_FLAG_NOBATTERY 0x10
+#define APM_BATT_FLAG_NOSYSBATT 0x80
+#define APM_BATT_LIFE_UNKNOWN 0xff
+#define BATT_STATE(regp) ((regp)->bx & 0xff)
+#define BATT_FLAGS(regp) (((regp)->cx & 0xff00) >> 8)
+#define AC_STATE(regp) (((regp)->bx & 0xff00) >> 8)
+#define BATT_LIFE(regp) ((regp)->cx & 0xff) /* in % */
+/* Return time in minutes. According to the APM 1.2 spec:
+ DX = Remaining battery life -- time units
+ Bit 15 = 0 Time units are seconds
+ = 1 Time units are minutes
+ Bits 14-0 = Number of seconds or minutes */
+#define BATT_REMAINING(regp) (((regp)->dx & 0x8000) ? \
+ ((regp)->dx & 0x7fff) : \
+ ((regp)->dx & 0x7fff)/60)
+#define BATT_REM_VALID(regp) (((regp)->dx & 0xffff) != 0xffff)
+#define BATT_COUNT(regp) ((regp)->si)
+
+#define APM_GET_PM_EVENT 0x530b
+#define APM_NOEVENT 0x0000
+#define APM_STANDBY_REQ 0x0001 /* %bx on return */
+#define APM_SUSPEND_REQ 0x0002
+#define APM_NORMAL_RESUME 0x0003
+#define APM_CRIT_RESUME 0x0004 /* suspend/resume happened
+ without us */
+#define APM_BATTERY_LOW 0x0005
+#define APM_POWER_CHANGE 0x0006
+#define APM_UPDATE_TIME 0x0007
+#define APM_CRIT_SUSPEND_REQ 0x0008
+#define APM_USER_STANDBY_REQ 0x0009
+#define APM_USER_SUSPEND_REQ 0x000A
+#define APM_SYS_STANDBY_RESUME 0x000B
+#define APM_CAPABILITY_CHANGE 0x000C /* apm v1.2 */
+/* 0x000d - 0x00ff Reserved system events */
+/* 0x0100 - 0x01ff Reserved device events */
+/* 0x0200 - 0x02ff OEM-defined APM events */
+/* 0x0300 - 0xffff Reserved */
+#define APM_EVENT_MASK 0xffff
+
+#define APM_EVENT_COMPOSE(t,i) ((((i) & 0x7fff) << 16)|((t) & APM_EVENT_MASK))
+#define APM_EVENT_TYPE(e) ((e) & APM_EVENT_MASK)
+#define APM_EVENT_INDEX(e) ((e) >> 16)
+
+#define APM_GET_POWER_STATE 0x530c
+#define APM_DEVICE_MGMT_ENABLE 0x530d
+
+#define APM_DRIVER_VERSION 0x530e
+/* %bx should be DEV value (APM_DEV_APM_BIOS)
+ %ch = driver major vno
+ %cl = driver minor vno
+ return: %ah = conn major; %al = conn minor
+ */
+#define APM_CONN_MINOR(regp) ((regp)->ax & 0xff)
+#define APM_CONN_MAJOR(regp) (((regp)->ax & 0xff00) >> 8)
+
+#define APM_PWR_MGT_ENGAGE 0x530F
+#define APM_MGT_DISENGAGE 0x0 /* %cx */
+#define APM_MGT_ENGAGE 0x1
+
+/* %bx - APM_DEV_APM_BIOS
+ * %bl - number of batteries
+ * %cx - capabilities
+ */
+#define APM_GET_CAPABILITIES 0x5310
+#define APM_NBATTERIES(regp) ((regp)->bx)
+#define APM_GLOBAL_STANDBY 0x0001
+#define APM_GLOBAL_SUSPEND 0x0002
+#define APM_RTIMER_STANDBY 0x0004 /* resume time wakes up */
+#define APM_RTIMER_SUSPEND 0x0008
+#define APM_IRRING_STANDBY 0x0010 /* internal ring wakes up */
+#define APM_IRRING_SUSPEND 0x0020
+#define APM_PCCARD_STANDBY 0x0040 /* pccard wakes up */
+#define APM_PCCARD_SUSPEND 0x0080
+
+/* %bx - APM_DEV_APM_BIOS
+ * %cl - function
+ * for %cl=2 (set resume timer)
+ * %ch - seconds in BCD
+ * %dh - hours in BCD
+ * %dl - minutes in BCD
+ * %si - month in BCD (high), day in BCD (low)
+ * %di - year in BCD
+ */
+#define APM_RESUME_TIMER 0x5311
+#define APM_RT_DISABLE 0x0
+#define APM_RT_GET 0x1
+#define APM_RT_SET 0x2
+
+/* %bx - APM_DEV_APM_BIOS
+ * %cx - function
+ */
+#define APM_RESUME_ON_RING 0x5312
+#define APM_ROR_DISABLE 0x0
+#define APM_ROR_ENABLE 0x1
+#define APM_ROR_STATUS 0x2
+
+/* %bx - APM_EDV_APM_BIOS
+ * %cx - function
+ */
+#define APM_INACTIVITY_TIMER 0x5313
+#define APM_IT_DISABLE 0x0
+#define APM_IT_ENABLE 0x1
+#define APM_IT_STATUS 0x2
+
+/* %bh - function */
+#define APM_OEM 0x5380
+#define APM_OEM_INSTCHECK 0x7f /* %bx - OEM ID */
+
+/*
+ * LP (Laptop Package)
+ *
+ * Copyright (C) 1994 by HOSOKAWA Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ *
+ * This software may be used, modified, copied, and distributed, in
+ * both source and binary form provided that the above copyright and
+ * these terms are retained. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its
+ * use.
+ *
+ * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+ */
+
+#define APM_BATTERY_ABSENT 4
+
+struct apm_power_info {
+ u_char battery_state;
+ u_char ac_state;
+ u_char battery_life;
+ u_char spare1;
+ u_int minutes_left; /* estimate */
+ u_int spare2[6];
+};
+
+struct apm_ctl {
+ u_int dev;
+ u_int mode;
+};
+
+#define APM_IOC_REJECT _IOW('A', 0, struct apm_event_info) /* reject request # */
+#define APM_IOC_STANDBY _IO('A', 1) /* put system into standby */
+#define APM_IOC_SUSPEND _IO('A', 2) /* put system into suspend */
+#define APM_IOC_GETPOWER _IOR('A', 3, struct apm_power_info) /* fetch battery state */
+#define APM_IOC_DEV_CTL _IOW('A', 5, struct apm_ctl) /* put device into mode */
+#define APM_IOC_PRN_CTL _IOW('A', 6, int ) /* driver power status msg */
+#define APM_PRINT_ON 0 /* driver power status displayed */
+#define APM_PRINT_OFF 1 /* driver power status not displayed */
+#define APM_PRINT_PCT 2 /* driver power status only displayed
+ if the percentage changes */
+
+#ifdef _KERNEL
+extern void apm_cpu_busy(void);
+extern void apm_cpu_idle(void);
+extern void apminit(void);
+int apm_set_powstate(u_int devid, u_int powstate);
+int apm_kqfilter(dev_t dev, struct knote *kn);
+#endif /* _KERNEL */
+
+#endif /* _I386_APMVAR_H_ */
diff --git a/sys/arch/amd64/include/asm.h b/sys/arch/amd64/include/asm.h
new file mode 100644
index 00000000000..4dc7f0facac
--- /dev/null
+++ b/sys/arch/amd64/include/asm.h
@@ -0,0 +1,122 @@
+/* $OpenBSD: asm.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: asm.h,v 1.2 2003/05/02 18:05:47 yamt Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)asm.h 5.5 (Berkeley) 5/7/91
+ */
+
+#ifndef _AMD64_ASM_H_
+#define _AMD64_ASM_H_
+
+#ifdef PIC
+#define PIC_PLT(x) x@PLT
+#define PIC_GOT(x) x@GOTPCREL(%rip)
+#else
+#define PIC_PLT(x) x
+#define PIC_GOT(x) x
+#endif
+
+# define _C_LABEL(x) x
+#define _ASM_LABEL(x) x
+
+#define CVAROFF(x,y) (_C_LABEL(x)+y)(%rip)
+
+#ifdef __STDC__
+# define __CONCAT(x,y) x ## y
+# define __STRING(x) #x
+#else
+# define __CONCAT(x,y) x/**/y
+# define __STRING(x) "x"
+#endif
+
+/* let kernels and others override entrypoint alignment */
+#ifndef _ALIGN_TEXT
+#define _ALIGN_TEXT .align 16, 0x90
+#endif
+
+#define _ENTRY(x) \
+ .text; _ALIGN_TEXT; .globl x; .type x,@function; x:
+
+#ifdef _KERNEL
+/* XXX Can't use __CONCAT() here, as it would be evaluated incorrectly. */
+#ifdef __STDC__
+#define IDTVEC(name) \
+ .text; ALIGN_TEXT; .globl X ## name; .type X ## name,@function; X ## name:
+#else
+#define IDTVEC(name) \
+ .text; ALIGN_TEXT; .globl X/**/name; .type X/**/name,@function; X/**/name:
+#endif /* __STDC__ */
+#endif /* _KERNEL */
+
+#ifdef __STDC__
+#define CPUVAR(off) %gs:CPU_INFO_ ## off
+#else
+#define CPUVAR(off) %gs:CPU_INFO_/**/off
+#endif
+
+
+#ifdef GPROF
+# define _PROF_PROLOGUE \
+ pushq %rbp; leaq (%rsp),%rbp; call PIC_PLT(__mcount); popq %rbp
+#else
+# define _PROF_PROLOGUE
+#endif
+
+#define ENTRY(y) _ENTRY(_C_LABEL(y)); _PROF_PROLOGUE
+#define NENTRY(y) _ENTRY(_C_LABEL(y))
+#define ASENTRY(y) _ENTRY(_ASM_LABEL(y)); _PROF_PROLOGUE
+
+#define ASMSTR .asciz
+
+#define RCSID(x) .text; .asciz x
+
+#define WEAK_ALIAS(alias,sym) \
+ .weak alias; \
+ alias = sym
+
+/* XXXfvdl do not use stabs here */
+#ifdef __STDC__
+#define WARN_REFERENCES(sym,msg) \
+ .stabs msg ## ,30,0,0,0 ; \
+ .stabs __STRING(_C_LABEL(sym)) ## ,1,0,0,0
+#else
+#define WARN_REFERENCES(sym,msg) \
+ .stabs msg,30,0,0,0 ; \
+ .stabs __STRING(sym),1,0,0,0
+#endif /* __STDC__ */
+
+#endif /* !_AMD64_ASM_H_ */
diff --git a/sys/arch/amd64/include/atomic.h b/sys/arch/amd64/include/atomic.h
new file mode 100644
index 00000000000..027415b18c2
--- /dev/null
+++ b/sys/arch/amd64/include/atomic.h
@@ -0,0 +1,96 @@
+/* $OpenBSD: atomic.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: atomic.h,v 1.1 2003/04/26 18:39:37 fvdl Exp $ */
+
+/*
+ * Copyright 2002 (c) Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Frank van der Linden for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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.
+ */
+
+#ifndef _ATOMIC_H
+#define _ATOMIC_H
+
+#ifndef _LOCORE
+
+static __inline u_int64_t
+x86_atomic_testset_u64(volatile u_int64_t *ptr, u_int64_t val) {
+ __asm__ volatile ("xchgq %0,(%2)" :"=r" (val):"0" (val),"r" (ptr));
+ return val;
+}
+
+static __inline u_int32_t
+x86_atomic_testset_u32(volatile u_int32_t *ptr, u_int32_t val) {
+ __asm__ volatile ("xchgl %0,(%2)" :"=r" (val):"0" (val),"r" (ptr));
+ return val;
+}
+
+
+
+static __inline int32_t
+x86_atomic_testset_i32(volatile int32_t *ptr, int32_t val) {
+ __asm__ volatile ("xchgl %0,(%2)" :"=r" (val):"0" (val),"r" (ptr));
+ return val;
+}
+
+
+
+static __inline void
+x86_atomic_setbits_u32(volatile u_int32_t *ptr, u_int32_t bits) {
+ __asm __volatile("lock ; orl %1,%0" : "=m" (*ptr) : "ir" (bits));
+}
+
+static __inline void
+x86_atomic_clearbits_u32(volatile u_int32_t *ptr, u_int32_t bits) {
+ __asm __volatile("lock ; andl %1,%0" : "=m" (*ptr) : "ir" (~bits));
+}
+
+
+
+static __inline void
+x86_atomic_setbits_u64(volatile u_int64_t *ptr, u_int64_t bits) {
+ __asm __volatile("lock ; orq %1,%0" : "=m" (*ptr) : "ir" (~bits));
+}
+
+static __inline void
+x86_atomic_clearbits_u64(volatile u_int64_t *ptr, u_int64_t bits) {
+ __asm __volatile("lock ; andq %1,%0" : "=m" (*ptr) : "ir" (~bits));
+}
+
+#define x86_atomic_testset_ul x86_atomic_testset_u32
+#define x86_atomic_testset_i x86_atomic_testset_i32
+#define x86_atomic_setbits_l x86_atomic_setbits_u32
+#define x86_atomic_setbits_ul x86_atomic_setbits_u32
+#define x86_atomic_clearbits_l x86_atomic_clearbits_u32
+#define x86_atomic_clearbits_ul x86_atomic_clearbits_u32
+
+#endif
+#endif
diff --git a/sys/arch/amd64/include/biosvar.h b/sys/arch/amd64/include/biosvar.h
new file mode 100644
index 00000000000..55922d4e002
--- /dev/null
+++ b/sys/arch/amd64/include/biosvar.h
@@ -0,0 +1,259 @@
+/* XXX - DSR */
+/* $OpenBSD: biosvar.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+
+/*
+ * Copyright (c) 1997-1999 Michael Shalayeff
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Michael Shalayeff.
+ * 4. 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 OR HIS RELATIVES 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 MIND, 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.
+ */
+
+#ifndef _I386_BIOSVAR_H_
+#define _I386_BIOSVAR_H_
+#pragma pack(1)
+
+ /* some boxes put apm data seg in the 2nd page */
+#define BOOTARG_OFF (NBPG*2)
+#define BOOTARG_LEN (NBPG*1)
+#define BOOTBIOS_ADDR (0x7c00)
+
+ /* BIOS configure flags */
+#define BIOSF_BIOS32 0x0001
+#define BIOSF_PCIBIOS 0x0002
+#define BIOSF_PROMSCAN 0x0004
+
+/* BIOS media ID */
+#define BIOSM_F320K 0xff /* floppy ds/sd 8 spt */
+#define BIOSM_F160K 0xfe /* floppy ss/sd 8 spt */
+#define BIOSM_F360K 0xfd /* floppy ds/sd 9 spt */
+#define BIOSM_F180K 0xfc /* floppy ss/sd 9 spt */
+#define BIOSM_ROMD 0xfa /* ROM disk */
+#define BIOSM_F120M 0xf9 /* floppy ds/hd 15 spt 5.25" */
+#define BIOSM_F720K 0xf9 /* floppy ds/dd 9 spt 3.50" */
+#define BIOSM_HD 0xf8 /* hard drive */
+#define BIOSM_F144K 0xf0 /* floppy ds/hd 18 spt 3.50" */
+#define BIOSM_OTHER 0xf0 /* any other */
+
+/*
+ * BIOS memory maps
+ */
+#define BIOS_MAP_END 0x00 /* End of array XXX - special */
+#define BIOS_MAP_FREE 0x01 /* Usable memory */
+#define BIOS_MAP_RES 0x02 /* Reserved memory */
+#define BIOS_MAP_ACPI 0x03 /* ACPI Reclaim memory */
+#define BIOS_MAP_NVS 0x04 /* ACPI NVS memory */
+
+/*
+ * Optional ROM header
+ */
+typedef
+struct bios_romheader {
+ u_int16_t signature; /* 0xaa55 */
+ u_int8_t len; /* length in pages (512 bytes) */
+ u_int32_t entry; /* initialization entry point */
+ u_int8_t reserved[19];
+ u_int16_t pnpheader; /* offset to PnP expansion header */
+} *bios_romheader_t;
+
+/*
+ * BIOS32
+ */
+typedef
+struct bios32_header {
+ u_int32_t signature; /* 00: signature "_32_" */
+ u_int32_t entry; /* 04: entry point */
+ u_int8_t rev; /* 08: revision */
+ u_int8_t length; /* 09: header length */
+ u_int8_t cksum; /* 0a: modulo 256 checksum */
+ u_int8_t reserved[5];
+} *bios32_header_t;
+
+typedef
+struct bios32_entry_info {
+ paddr_t bei_base;
+ psize_t bei_size;
+ paddr_t bei_entry;
+} *bios32_entry_info_t;
+
+typedef
+struct bios32_entry {
+ u_int32_t offset;
+ u_int16_t segment;
+} *bios32_entry_t;
+
+#define BIOS32_START 0xe0000
+#define BIOS32_SIZE 0x20000
+#define BIOS32_END (BIOS32_START + BIOS32_SIZE - 0x10)
+
+#define BIOS32_MAKESIG(a, b, c, d) \
+ ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
+#define BIOS32_SIGNATURE BIOS32_MAKESIG('_', '3', '2', '_')
+#define PCIBIOS_SIGNATURE BIOS32_MAKESIG('$', 'P', 'C', 'I')
+
+/*
+ * CTL_BIOS definitions.
+ */
+#define BIOS_DEV 1 /* int: BIOS boot device */
+#define BIOS_DISKINFO 2 /* struct: BIOS boot device info */
+#define BIOS_CKSUMLEN 3 /* int: disk cksum block count */
+#define BIOS_MAXID 4 /* number of valid machdep ids */
+
+#define CTL_BIOS_NAMES { \
+ { 0, 0 }, \
+ { "biosdev", CTLTYPE_INT }, \
+ { "diskinfo", CTLTYPE_STRUCT }, \
+ { "cksumlen", CTLTYPE_INT }, \
+}
+
+#define BOOTARG_MEMMAP 0
+typedef struct _bios_memmap {
+ u_int64_t addr; /* Beginning of block */
+ u_int64_t size; /* Size of block */
+ u_int32_t type; /* Type of block */
+} bios_memmap_t;
+
+/* Info about disk from the bios, plus the mapping from
+ * BIOS numbers to BSD major (driver?) number.
+ *
+ * Also, do not bother with BIOSN*() macros, just parcel
+ * the info out, and use it like this. This makes for less
+ * of a dependance on BIOSN*() macros having to be the same
+ * across /boot, /bsd, and userland.
+ */
+#define BOOTARG_DISKINFO 1
+typedef struct _bios_diskinfo {
+ /* BIOS section */
+ int bios_number; /* BIOS number of drive (or -1) */
+ u_int bios_cylinders; /* BIOS cylinders */
+ u_int bios_heads; /* BIOS heads */
+ u_int bios_sectors; /* BIOS sectors */
+ int bios_edd; /* EDD support */
+
+ /* BSD section */
+ dev_t bsd_dev; /* BSD device */
+
+ /* Checksum section */
+ u_int32_t checksum; /* Checksum for drive */
+
+ /* Misc. flags */
+ u_int32_t flags;
+#define BDI_INVALID 0x00000001 /* I/O error during checksumming */
+#define BDI_GOODLABEL 0x00000002 /* Had SCSI or ST506/ESDI disklabel */
+#define BDI_BADLABEL 0x00000004 /* Had another disklabel */
+#define BDI_PICKED 0x80000000 /* kernel-only: cksum matched */
+
+} bios_diskinfo_t;
+
+#define BOOTARG_APMINFO 2
+typedef struct _bios_apminfo {
+ /* APM_CONNECT returned values */
+ u_int apm_detail;
+ u_int apm_code32_base;
+ u_int apm_code16_base;
+ u_int apm_code_len;
+ u_int apm_data_base;
+ u_int apm_data_len;
+ u_int apm_entry;
+ u_int apm_code16_len;
+} bios_apminfo_t;
+
+#define BOOTARG_CKSUMLEN 3 /* u_int32_t */
+
+#define BOOTARG_PCIINFO 4
+typedef struct _bios_pciinfo {
+ /* PCI BIOS v2.0+ - Installation check values */
+ u_int32_t pci_chars; /* Characteristics (%eax) */
+ u_int32_t pci_rev; /* BCD Revision (%ebx) */
+ u_int32_t pci_entry32; /* PM entry point for PCI BIOS */
+ u_int32_t pci_lastbus; /* Number of last PCI bus */
+} bios_pciinfo_t;
+
+#define BOOTARG_CONSDEV 5
+typedef struct _bios_consdev {
+ dev_t consdev;
+ int conspeed;
+} bios_consdev_t;
+
+#if defined(_KERNEL) || defined (_STANDALONE)
+
+#ifdef _LOCORE
+#define DOINT(n) int $0x20+(n)
+#else
+#define DOINT(n) "int $0x20+(" #n ")"
+
+extern struct BIOS_regs {
+ u_int32_t biosr_ax;
+ u_int32_t biosr_cx;
+ u_int32_t biosr_dx;
+ u_int32_t biosr_bx;
+ u_int32_t biosr_bp;
+ u_int32_t biosr_si;
+ u_int32_t biosr_di;
+ u_int32_t biosr_ds;
+ u_int32_t biosr_es;
+} BIOS_regs;
+
+#ifdef _KERNEL
+#include <machine/bus.h>
+
+struct bios_attach_args {
+ char *bios_dev;
+ u_int bios_func;
+ bus_space_tag_t bios_iot;
+ bus_space_tag_t bios_memt;
+ union {
+ void *_p;
+ bios_apminfo_t *_bios_apmp;
+ } _;
+};
+
+#define bios_apmp _._bios_apmp
+
+struct consdev;
+struct proc;
+
+int bios_sysctl(int *, u_int, void *, size_t *, void *, size_t, struct proc *);
+
+void bioscnprobe(struct consdev *);
+void bioscninit(struct consdev *);
+void bioscnputc(dev_t, int);
+int bioscngetc(dev_t);
+void bioscnpollc(dev_t, int);
+void bios_getopt(void);
+
+/* bios32.c */
+int bios32_service(u_int32_t, bios32_entry_t, bios32_entry_info_t);
+
+extern u_int bootapiver;
+extern bios_memmap_t *bios_memmap;
+
+#endif /* _KERNEL */
+#endif /* _LOCORE */
+#endif /* _KERNEL || _STANDALONE */
+
+#pragma pack()
+#endif /* _I386_BIOSVAR_H_ */
diff --git a/sys/arch/amd64/include/bootinfo.h b/sys/arch/amd64/include/bootinfo.h
new file mode 100644
index 00000000000..8751e66a3be
--- /dev/null
+++ b/sys/arch/amd64/include/bootinfo.h
@@ -0,0 +1,159 @@
+/* $OpenBSD: bootinfo.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: bootinfo.h,v 1.2 2003/04/16 19:16:42 dsl Exp $ */
+
+/*
+ * Copyright (c) 1997
+ * Matthias Drochner. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project
+ * by Matthias Drochner.
+ * 4. 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.
+ *
+ */
+
+#ifndef _LOCORE
+
+struct btinfo_common {
+ int len;
+ int type;
+};
+
+#define BTINFO_BOOTPATH 0
+#define BTINFO_BOOTDISK 3
+#define BTINFO_NETIF 4
+#define BTINFO_CONSOLE 6
+#define BTINFO_BIOSGEOM 7
+#define BTINFO_SYMTAB 8
+#define BTINFO_MEMMAP 9
+
+struct btinfo_bootpath {
+ struct btinfo_common common;
+ char bootpath[80];
+};
+
+struct btinfo_bootdisk {
+ struct btinfo_common common;
+ int labelsector; /* label valid if != -1 */
+ struct {
+ u_int16_t type, checksum;
+ char packname[16];
+ } label;
+ int biosdev;
+ int partition;
+};
+
+struct btinfo_netif {
+ struct btinfo_common common;
+ char ifname[16];
+ int bus;
+#define BI_BUS_ISA 0
+#define BI_BUS_PCI 1
+ union {
+ unsigned int iobase; /* ISA */
+ unsigned int tag; /* PCI, BIOS format */
+ } addr;
+};
+
+struct btinfo_console {
+ struct btinfo_common common;
+ char devname[16];
+ int addr;
+ int speed;
+};
+
+struct btinfo_symtab {
+ struct btinfo_common common;
+ int nsym;
+ int ssym;
+ int esym;
+};
+
+struct bi_memmap_entry {
+ u_int64_t addr; /* beginning of block */ /* 8 */
+ u_int64_t size; /* size of block */ /* 8 */
+ u_int32_t type; /* type of block */ /* 4 */
+} __attribute__((packed)); /* == 20 */
+
+#define BIM_Memory 1 /* available RAM usable by OS */
+#define BIM_Reserved 2 /* in use or reserved by the system */
+#define BIM_ACPI 3 /* ACPI Reclaim memory */
+#define BIM_NVS 4 /* ACPI NVS memory */
+
+struct btinfo_memmap {
+ struct btinfo_common common;
+ int num;
+ struct bi_memmap_entry entry[1]; /* var len */
+};
+
+#include <machine/disklabel.h>
+
+/*
+ * Structure describing disk info as seen by the BIOS.
+ */
+struct bi_biosgeom_entry {
+ int sec, head, cyl; /* geometry */
+ u_int64_t totsec; /* LBA sectors from ext int13 */
+ int flags, dev; /* flags, BIOS device # */
+#define BI_GEOM_INVALID 0x000001
+#define BI_GEOM_EXTINT13 0x000002
+#ifdef BIOSDISK_EXT13INFO_V3
+#define BI_GEOM_BADCKSUM 0x000004 /* v3.x checksum invalid */
+#define BI_GEOM_BUS_MASK 0x00ff00 /* connecting bus type */
+#define BI_GEOM_BUS_ISA 0x000100
+#define BI_GEOM_BUS_PCI 0x000200
+#define BI_GEOM_BUS_OTHER 0x00ff00
+#define BI_GEOM_IFACE_MASK 0xff0000 /* interface type */
+#define BI_GEOM_IFACE_ATA 0x010000
+#define BI_GEOM_IFACE_ATAPI 0x020000
+#define BI_GEOM_IFACE_SCSI 0x030000
+#define BI_GEOM_IFACE_USB 0x040000
+#define BI_GEOM_IFACE_1394 0x050000 /* Firewire */
+#define BI_GEOM_IFACE_FIBRE 0x060000 /* Fibre channel */
+#define BI_GEOM_IFACE_OTHER 0xff0000
+ unsigned int cksum; /* MBR checksum */
+ u_int interface_path; /* ISA iobase PCI bus/dev/fun */
+ u_int64_t device_path;
+ int res0; /* future expansion; 0 now */
+#else
+ unsigned int cksum; /* MBR checksum */
+ int res0, res1, res2, res3; /* future expansion; 0 now */
+#endif
+ struct dos_partition dosparts[NDOSPART]; /* MBR itself */
+} __attribute__((packed));
+
+struct btinfo_biosgeom {
+ struct btinfo_common common;
+ int num;
+ struct bi_biosgeom_entry disk[1]; /* var len */
+};
+
+#ifdef _KERNEL
+void *lookup_bootinfo __P((int));
+#endif
+#endif /* _LOCORE */
+
+#ifdef _KERNEL
+#define BOOTINFO_MAXSIZE 4096
+#endif
diff --git a/sys/arch/amd64/include/bus.h b/sys/arch/amd64/include/bus.h
new file mode 100644
index 00000000000..4a1c326b8fc
--- /dev/null
+++ b/sys/arch/amd64/include/bus.h
@@ -0,0 +1,1158 @@
+/* $OpenBSD: bus.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: bus.h,v 1.6 1996/11/10 03:19:25 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1996 Charles M. Hannum. All rights reserved.
+ * Copyright (c) 1996 Jason R. Thorpe. All rights reserved.
+ * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. 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.
+ */
+
+#ifndef _X86_BUS_H_
+#define _X86_BUS_H_
+
+#include <machine/pio.h>
+
+/*
+ * Values for the x86 bus space tag, not to be used directly by MI code.
+ */
+#define X86_BUS_SPACE_IO 0 /* space is i/o space */
+#define X86_BUS_SPACE_MEM 1 /* space is mem space */
+
+/*
+ * Bus address and size types
+ */
+typedef u_long bus_addr_t;
+typedef u_long bus_size_t;
+
+/*
+ * Access methods for bus resources and address space.
+ */
+typedef int bus_space_tag_t;
+typedef u_long bus_space_handle_t;
+
+#define bus_space_map(t, a, s, f, hp) x86_memio_map((t),(a),(s),(f),(hp))
+#define bus_space_unmap(t, h, s) x86_memio_unmap((t),(h),(s))
+#define bus_space_subregion(t, h, o, s, nhp) \
+ x86_memio_subregion((t), (h), (o), (s), (nhp))
+
+int x86_memio_map(bus_space_tag_t t, bus_addr_t addr,
+ bus_size_t size, int flags, bus_space_handle_t *bshp);
+/* like map, but without extent map checking/allocation */
+int _x86_memio_map(bus_space_tag_t t, bus_addr_t addr,
+ bus_size_t size, int flags, bus_space_handle_t *bshp);
+
+/*
+ * int bus_space_unmap(bus_space_tag_t t,
+ * bus_space_handle_t bsh, bus_size_t size);
+ *
+ * Unmap a region of bus space.
+ */
+
+void x86_memio_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
+ bus_size_t size);
+void _x86_memio_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
+ bus_size_t size, bus_addr_t *);
+
+/* like bus_space_map(), but without extent map checking/allocation */
+int _bus_space_map(bus_space_tag_t t, bus_addr_t addr,
+ bus_size_t size, int cacheable, bus_space_handle_t *bshp);
+
+int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
+ bus_addr_t rend, bus_size_t size, bus_size_t align,
+ bus_size_t boundary, int cacheable, bus_addr_t *addrp,
+ bus_space_handle_t *bshp);
+void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
+ bus_size_t size);
+
+/*
+ * int bus_space_subregion(bus_space_tag_t t,
+ * bus_space_handle_t bsh, bus_size_t offset, bus_size_t size,
+ * bus_space_handle_t *nbshp);
+ *
+ * Get a new handle for a subregion of an already-mapped area of bus space.
+ */
+
+int x86_memio_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
+ bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp);
+
+/*
+ * u_intN_t bus_space_read_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset);
+ *
+ * Read a 1, 2, 4, or 8 byte quantity from bus space
+ * described by tag/handle/offset.
+ */
+
+#define bus_space_read_1(t, h, o) \
+ ((t) == X86_BUS_SPACE_IO ? (inb((h) + (o))) : \
+ (*(volatile u_int8_t *)((h) + (o))))
+
+#define bus_space_read_2(t, h, o) \
+ ((t) == X86_BUS_SPACE_IO ? (inw((h) + (o))) : \
+ (*(volatile u_int16_t *)((h) + (o))))
+
+#define bus_space_read_4(t, h, o) \
+ ((t) == X86_BUS_SPACE_IO ? (inl((h) + (o))) : \
+ (*(volatile u_int32_t *)((h) + (o))))
+
+#if 0 /* Cause a link error for bus_space_read_8 */
+#define bus_space_read_8(t, h, o) !!! bus_space_read_8 unimplemented !!!
+#endif
+
+/*
+ * void bus_space_read_multi_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * u_intN_t *addr, size_t count);
+ *
+ * Read `count' 1, 2, 4, or 8 byte quantities from bus space
+ * described by tag/handle/offset and copy into buffer provided.
+ */
+
+#define bus_space_read_multi_1(t, h, o, ptr, cnt) \
+do { \
+ if ((t) == X86_BUS_SPACE_IO) { \
+ insb((h) + (o), (ptr), (cnt)); \
+ } else { \
+ void *dummy1; \
+ int dummy2; \
+ void *dummy3; \
+ int __x; \
+ __asm __volatile(" \
+ cld ; \
+ 1: movb (%2),%%al ; \
+ stosb ; \
+ loop 1b" : \
+ "=D" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) : \
+ "0" ((ptr)), "1" ((cnt)), "2" ((h) + (o)) : \
+ "memory"); \
+ } \
+} while (/* CONSTCOND */ 0)
+
+#define bus_space_read_multi_2(t, h, o, ptr, cnt) \
+do { \
+ if ((t) == X86_BUS_SPACE_IO) { \
+ insw((h) + (o), (ptr), (cnt)); \
+ } else { \
+ void *dummy1; \
+ int dummy2; \
+ void *dummy3; \
+ int __x; \
+ __asm __volatile(" \
+ cld ; \
+ 1: movw (%2),%%ax ; \
+ stosw ; \
+ loop 1b" : \
+ "=D" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) : \
+ "0" ((ptr)), "1" ((cnt)), "2" ((h) + (o)) : \
+ "memory"); \
+ } \
+} while (/* CONSTCOND */ 0)
+
+#define bus_space_read_multi_4(t, h, o, ptr, cnt) \
+do { \
+ if ((t) == X86_BUS_SPACE_IO) { \
+ insl((h) + (o), (ptr), (cnt)); \
+ } else { \
+ void *dummy1; \
+ int dummy2; \
+ void *dummy3; \
+ int __x; \
+ __asm __volatile(" \
+ cld ; \
+ 1: movl (%2),%%eax ; \
+ stosl ; \
+ loop 1b" : \
+ "=D" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) : \
+ "0" ((ptr)), "1" ((cnt)), "2" ((h) + (o)) : \
+ "memory"); \
+ } \
+} while (/* CONSTCOND */ 0)
+
+#if 0 /* Cause a link error for bus_space_read_multi_8 */
+#define bus_space_read_multi_8 !!! bus_space_read_multi_8 unimplemented !!!
+#endif
+
+/*
+ * void bus_space_read_raw_multi_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * u_int8_t *addr, size_t count);
+ *
+ * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space
+ * described by tag/handle/offset and copy into buffer provided. The buffer
+ * must have proper alignment for the N byte wide entities. Furthermore
+ * possible byte-swapping should be done by these functions.
+ */
+
+#define bus_space_read_raw_multi_2(t, h, o, a, c) \
+ bus_space_read_multi_2((t), (h), (o), (u_int16_t *)(a), (c) >> 1)
+#define bus_space_read_raw_multi_4(t, h, o, a, c) \
+ bus_space_read_multi_4((t), (h), (o), (u_int32_t *)(a), (c) >> 2)
+
+#if 0 /* Cause a link error for bus_space_read_raw_multi_8 */
+#define bus_space_read_raw_multi_8 \
+ !!! bus_space_read_raw_multi_8 unimplemented !!!
+#endif
+
+/*
+ * void bus_space_read_region_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * u_intN_t *addr, size_t count);
+ *
+ * Read `count' 1, 2, 4, or 8 byte quantities from bus space
+ * described by tag/handle and starting at `offset' and copy into
+ * buffer provided.
+ */
+
+#define bus_space_read_region_1(t, h, o, ptr, cnt) \
+do { \
+ if ((t) == X86_BUS_SPACE_IO) { \
+ int dummy1; \
+ void *dummy2; \
+ int dummy3; \
+ int __x; \
+ __asm __volatile(" \
+ cld ; \
+ 1: inb %w1,%%al ; \
+ stosb ; \
+ incl %1 ; \
+ loop 1b" : \
+ "=&a" (__x), "=d" (dummy1), "=D" (dummy2), \
+ "=c" (dummy3) : \
+ "1" ((h) + (o)), "2" ((ptr)), "3" ((cnt)) : \
+ "memory"); \
+ } else { \
+ int dummy1; \
+ void *dummy2; \
+ int dummy3; \
+ __asm __volatile(" \
+ cld ; \
+ repne ; \
+ movsb" : \
+ "=S" (dummy1), "=D" (dummy2), "=c" (dummy3) : \
+ "0" ((h) + (o)), "1" ((ptr)), "2" ((cnt)) : \
+ "memory"); \
+ } \
+} while (/* CONSTCOND */ 0)
+
+#define bus_space_read_region_2(t, h, o, ptr, cnt) \
+do { \
+ if ((t) == X86_BUS_SPACE_IO) { \
+ int dummy1; \
+ void *dummy2; \
+ int dummy3; \
+ int __x; \
+ __asm __volatile(" \
+ cld ; \
+ 1: inw %w1,%%ax ; \
+ stosw ; \
+ addl $2,%1 ; \
+ loop 1b" : \
+ "=&a" (__x), "=d" (dummy1), "=D" (dummy2), \
+ "=c" (dummy3) : \
+ "1" ((h) + (o)), "2" ((ptr)), "3" ((cnt)) : \
+ "memory"); \
+ } else { \
+ int dummy1; \
+ void *dummy2; \
+ int dummy3; \
+ __asm __volatile(" \
+ cld ; \
+ repne ; \
+ movsw" : \
+ "=S" (dummy1), "=D" (dummy2), "=c" (dummy3) : \
+ "0" ((h) + (o)), "1" ((ptr)), "2" ((cnt)) : \
+ "memory"); \
+ } \
+} while (/* CONSTCOND */ 0)
+
+#define bus_space_read_region_4(t, h, o, ptr, cnt) \
+do { \
+ if ((t) == X86_BUS_SPACE_IO) { \
+ int dummy1; \
+ void *dummy2; \
+ int dummy3; \
+ int __x; \
+ __asm __volatile(" \
+ cld ; \
+ 1: inl %w1,%%eax ; \
+ stosl ; \
+ addl $4,%1 ; \
+ loop 1b" : \
+ "=&a" (__x), "=d" (dummy1), "=D" (dummy2), \
+ "=c" (dummy3) : \
+ "1" ((h) + (o)), "2" ((ptr)), "3" ((cnt)) : \
+ "memory"); \
+ } else { \
+ int dummy1; \
+ void *dummy2; \
+ int dummy3; \
+ __asm __volatile(" \
+ cld ; \
+ repne ; \
+ movsl" : \
+ "=S" (dummy1), "=D" (dummy2), "=c" (dummy3) : \
+ "0" ((h) + (o)), "1" ((ptr)), "2" ((cnt)) : \
+ "memory"); \
+ } \
+} while (/* CONSTCOND */ 0)
+
+#define bus_space_read_region_stream_1 bus_space_read_region_1
+#if 0 /* Cause a link error for bus_space_read_region_8 */
+#define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!!
+#endif
+
+/*
+ * void bus_space_read_raw_region_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * u_int8_t *addr, size_t count);
+ *
+ * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space
+ * described by tag/handle and starting at `offset' and copy into
+ * buffer provided. The buffer must have proper alignment for the N byte
+ * wide entities. Furthermore possible byte-swapping should be done by
+ * these functions.
+ */
+
+#define bus_space_read_raw_region_2(t, h, o, a, c) \
+ bus_space_read_region_2((t), (h), (o), (u_int16_t *)(a), (c) >> 1)
+#define bus_space_read_raw_region_4(t, h, o, a, c) \
+ bus_space_read_region_4((t), (h), (o), (u_int32_t *)(a), (c) >> 2)
+
+#if 0 /* Cause a link error for bus_space_read_raw_region_8 */
+#define bus_space_read_raw_region_8 \
+ !!! bus_space_read_raw_region_8 unimplemented !!!
+#endif
+
+/*
+ * void bus_space_write_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * u_intN_t value);
+ *
+ * Write the 1, 2, 4, or 8 byte value `value' to bus space
+ * described by tag/handle/offset.
+ */
+
+#define bus_space_write_1(t, h, o, v) do { \
+ if ((t) == X86_BUS_SPACE_IO) \
+ outb((h) + (o), (v)); \
+ else \
+ ((void)(*(volatile u_int8_t *)((h) + (o)) = (v))); \
+} while (0)
+
+#define bus_space_write_2(t, h, o, v) do { \
+ if ((t) == X86_BUS_SPACE_IO) \
+ outw((h) + (o), (v)); \
+ else \
+ ((void)(*(volatile u_int16_t *)((h) + (o)) = (v))); \
+} while (0)
+
+#define bus_space_write_4(t, h, o, v) do { \
+ if ((t) == X86_BUS_SPACE_IO) \
+ outl((h) + (o), (v)); \
+ else \
+ ((void)(*(volatile u_int32_t *)((h) + (o)) = (v))); \
+} while (0)
+
+#if 0 /* Cause a link error for bus_space_write_8 */
+#define bus_space_write_8 !!! bus_space_write_8 not implemented !!!
+#endif
+
+/*
+ * void bus_space_write_multi_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * const u_intN_t *addr, size_t count);
+ *
+ * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
+ * provided to bus space described by tag/handle/offset.
+ */
+
+#define bus_space_write_multi_1(t, h, o, ptr, cnt) \
+do { \
+ if ((t) == X86_BUS_SPACE_IO) { \
+ outsb((h) + (o), (ptr), (cnt)); \
+ } else { \
+ void *dummy1; \
+ int dummy2; \
+ void *dummy3; \
+ int __x; \
+ __asm __volatile(" \
+ cld ; \
+ 1: lodsb ; \
+ movb %%al,(%2) ; \
+ loop 1b" : \
+ "=S" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) : \
+ "0" ((ptr)), "1" ((cnt)), "2" ((h) + (o))); \
+ } \
+} while (/* CONSTCOND */ 0)
+
+#define bus_space_write_multi_2(t, h, o, ptr, cnt) \
+do { \
+ if ((t) == X86_BUS_SPACE_IO) { \
+ outsw((h) + (o), (ptr), (cnt)); \
+ } else { \
+ void *dummy1; \
+ int dummy2; \
+ void *dummy3; \
+ int __x; \
+ __asm __volatile(" \
+ cld ; \
+ 1: lodsw ; \
+ movw %%ax,(%2) ; \
+ loop 1b" : \
+ "=S" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) : \
+ "0" ((ptr)), "1" ((cnt)), "2" ((h) + (o))); \
+ } \
+} while (/* CONSTCOND */ 0)
+
+#define bus_space_write_multi_4(t, h, o, ptr, cnt) \
+do { \
+ if ((t) == X86_BUS_SPACE_IO) { \
+ outsl((h) + (o), (ptr), (cnt)); \
+ } else { \
+ void *dummy1; \
+ int dummy2; \
+ void *dummy3; \
+ int __x; \
+ __asm __volatile(" \
+ cld ; \
+ 1: lodsl ; \
+ movl %%eax,(%2) ; \
+ loop 1b" : \
+ "=S" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) : \
+ "0" ((ptr)), "1" ((cnt)), "2" ((h) + (o))); \
+ } \
+} while (/* CONSTCOND */ 0)
+
+#if 0 /* Cause a link error for bus_space_write_multi_8 */
+#define bus_space_write_multi_8(t, h, o, a, c) \
+ !!! bus_space_write_multi_8 unimplemented !!!
+#endif
+
+/*
+ * void bus_space_write_raw_multi_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * const u_int8_t *addr, size_t count);
+ *
+ * Write `count' bytes in 2, 4 or 8 byte wide quantities from the buffer
+ * provided to bus space described by tag/handle/offset. The buffer
+ * must have proper alignment for the N byte wide entities. Furthermore
+ * possible byte-swapping should be done by these functions.
+ */
+
+#define bus_space_write_raw_multi_2(t, h, o, a, c) \
+ bus_space_write_multi_2((t), (h), (o), (const u_int16_t *)(a), (c) >> 1)
+#define bus_space_write_raw_multi_4(t, h, o, a, c) \
+ bus_space_write_multi_4((t), (h), (o), (const u_int32_t *)(a), (c) >> 2)
+
+#if 0 /* Cause a link error for bus_space_write_raw_multi_8 */
+#define bus_space_write_raw_multi_8 \
+ !!! bus_space_write_raw_multi_8 unimplemented !!!
+#endif
+
+/*
+ * void bus_space_write_region_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * const u_intN_t *addr, size_t count);
+ *
+ * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
+ * to bus space described by tag/handle starting at `offset'.
+ */
+
+#define bus_space_write_region_1(t, h, o, ptr, cnt) \
+do { \
+ if ((t) == X86_BUS_SPACE_IO) { \
+ int dummy1; \
+ void *dummy2; \
+ int dummy3; \
+ int __x; \
+ __asm __volatile(" \
+ cld ; \
+ 1: lodsb ; \
+ outb %%al,%w1 ; \
+ incl %1 ; \
+ loop 1b" : \
+ "=&a" (__x), "=d" (dummy1), "=S" (dummy2), \
+ "=c" (dummy3) : \
+ "1" ((h) + (o)), "2" ((ptr)), "3" ((cnt)) : \
+ "memory"); \
+ } else { \
+ int dummy1; \
+ void *dummy2; \
+ int dummy3; \
+ __asm __volatile(" \
+ cld ; \
+ repne ; \
+ movsb" : \
+ "=D" (dummy1), "=S" (dummy2), "=c" (dummy3) : \
+ "0" ((h) + (o)), "1" ((ptr)), "2" ((cnt)) : \
+ "memory"); \
+ } \
+} while (/* CONSTCOND */ 0)
+
+#define bus_space_write_region_2(t, h, o, ptr, cnt) \
+do { \
+ if ((t) == X86_BUS_SPACE_IO) { \
+ int dummy1; \
+ void *dummy2; \
+ int dummy3; \
+ int __x; \
+ __asm __volatile(" \
+ cld ; \
+ 1: lodsw ; \
+ outw %%ax,%w1 ; \
+ addl $2,%1 ; \
+ loop 1b" : \
+ "=&a" (__x), "=d" (dummy1), "=S" (dummy2), \
+ "=c" (dummy3) : \
+ "1" ((h) + (o)), "2" ((ptr)), "3" ((cnt)) : \
+ "memory"); \
+ } else { \
+ int dummy1; \
+ void *dummy2; \
+ int dummy3; \
+ __asm __volatile(" \
+ cld ; \
+ repne ; \
+ movsw" : \
+ "=D" (dummy1), "=S" (dummy2), "=c" (dummy3) : \
+ "0" ((h) + (o)), "1" ((ptr)), "2" ((cnt)) : \
+ "memory"); \
+ } \
+} while (/* CONSTCOND */ 0)
+
+#define bus_space_write_region_4(t, h, o, ptr, cnt) \
+do { \
+ if ((t) == X86_BUS_SPACE_IO) { \
+ int dummy1; \
+ void *dummy2; \
+ int dummy3; \
+ int __x; \
+ __asm __volatile(" \
+ cld ; \
+ 1: lodsl ; \
+ outl %%eax,%w1 ; \
+ addl $4,%1 ; \
+ loop 1b" : \
+ "=&a" (__x), "=d" (dummy1), "=S" (dummy2), \
+ "=c" (dummy3) : \
+ "1" ((h) + (o)), "2" ((ptr)), "3" ((cnt)) : \
+ "memory"); \
+ } else { \
+ int dummy1; \
+ void *dummy2; \
+ int dummy3; \
+ __asm __volatile(" \
+ cld ; \
+ repne ; \
+ movsl" : \
+ "=D" (dummy1), "=S" (dummy2), "=c" (dummy3) : \
+ "0" ((h) + (o)), "1" ((ptr)), "2" ((cnt)) : \
+ "memory"); \
+ } \
+} while (/* CONSTCOND */ 0)
+
+#if 0 /* Cause a link error for bus_space_write_region_8 */
+#define bus_space_write_region_8 \
+ !!! bus_space_write_region_8 unimplemented !!!
+#endif
+
+/*
+ * void bus_space_write_raw_region_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * const u_int8_t *addr, size_t count);
+ *
+ * Write `count' bytes in 2, 4 or 8 byte wide quantities to bus space
+ * described by tag/handle and starting at `offset' from the
+ * buffer provided. The buffer must have proper alignment for the N byte
+ * wide entities. Furthermore possible byte-swapping should be done by
+ * these functions.
+ */
+
+#define bus_space_write_raw_region_2(t, h, o, a, c) \
+ bus_space_write_region_2((t), (h), (o), (const u_int16_t *)(a), (c) >> 1)
+#define bus_space_write_raw_region_4(t, h, o, a, c) \
+ bus_space_write_region_4((t), (h), (o), (const u_int32_t *)(a), (c) >> 2)
+
+#if 0 /* Cause a link error for bus_space_write_raw_region_8 */
+#define bus_space_write_raw_region_8 \
+ !!! bus_space_write_raw_region_8 unimplemented !!!
+#endif
+
+/*
+ * void bus_space_set_multi_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * u_intN_t val, size_t count);
+ *
+ * Write the 1, 2, 4, or 8 byte value `val' to bus space described
+ * by tag/handle/offset `count' times.
+ */
+
+static __inline void x86_memio_set_multi_1(bus_space_tag_t,
+ bus_space_handle_t, bus_size_t, u_int8_t, size_t);
+static __inline void x86_memio_set_multi_2(bus_space_tag_t,
+ bus_space_handle_t, bus_size_t, u_int16_t, size_t);
+static __inline void x86_memio_set_multi_4(bus_space_tag_t,
+ bus_space_handle_t, bus_size_t, u_int32_t, size_t);
+
+#define bus_space_set_multi_1(t, h, o, v, c) \
+ x86_memio_set_multi_1((t), (h), (o), (v), (c))
+
+#define bus_space_set_multi_2(t, h, o, v, c) \
+ x86_memio_set_multi_2((t), (h), (o), (v), (c))
+
+#define bus_space_set_multi_4(t, h, o, v, c) \
+ x86_memio_set_multi_4((t), (h), (o), (v), (c))
+
+static __inline void
+x86_memio_set_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ u_int8_t v, size_t c)
+{
+ bus_addr_t addr = h + o;
+
+ if (t == X86_BUS_SPACE_IO)
+ while (c--)
+ outb(addr, v);
+ else
+ while (c--)
+ *(volatile u_int8_t *)(addr) = v;
+}
+
+static __inline void
+x86_memio_set_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ u_int16_t v, size_t c)
+{
+ bus_addr_t addr = h + o;
+
+ if (t == X86_BUS_SPACE_IO)
+ while (c--)
+ outw(addr, v);
+ else
+ while (c--)
+ *(volatile u_int16_t *)(addr) = v;
+}
+
+static __inline void
+x86_memio_set_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ u_int32_t v, size_t c)
+{
+ bus_addr_t addr = h + o;
+
+ if (t == X86_BUS_SPACE_IO)
+ while (c--)
+ outl(addr, v);
+ else
+ while (c--)
+ *(volatile u_int32_t *)(addr) = v;
+}
+
+#if 0 /* Cause a link error for bus_space_set_multi_8 */
+#define bus_space_set_multi_8 \
+ !!! bus_space_set_multi_8 unimplemented !!!
+#endif
+
+/*
+ * void bus_space_set_region_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * u_intN_t val, size_t count);
+ *
+ * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
+ * by tag/handle starting at `offset'.
+ */
+
+static __inline void x86_memio_set_region_1(bus_space_tag_t,
+ bus_space_handle_t, bus_size_t, u_int8_t, size_t);
+static __inline void x86_memio_set_region_2(bus_space_tag_t,
+ bus_space_handle_t, bus_size_t, u_int16_t, size_t);
+static __inline void x86_memio_set_region_4(bus_space_tag_t,
+ bus_space_handle_t, bus_size_t, u_int32_t, size_t);
+
+#define bus_space_set_region_1(t, h, o, v, c) \
+ x86_memio_set_region_1((t), (h), (o), (v), (c))
+
+#define bus_space_set_region_2(t, h, o, v, c) \
+ x86_memio_set_region_2((t), (h), (o), (v), (c))
+
+#define bus_space_set_region_4(t, h, o, v, c) \
+ x86_memio_set_region_4((t), (h), (o), (v), (c))
+
+static __inline void
+x86_memio_set_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ u_int8_t v, size_t c)
+{
+ bus_addr_t addr = h + o;
+
+ if (t == X86_BUS_SPACE_IO)
+ for (; c != 0; c--, addr++)
+ outb(addr, v);
+ else
+ for (; c != 0; c--, addr++)
+ *(volatile u_int8_t *)(addr) = v;
+}
+
+static __inline void
+x86_memio_set_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ u_int16_t v, size_t c)
+{
+ bus_addr_t addr = h + o;
+
+ if (t == X86_BUS_SPACE_IO)
+ for (; c != 0; c--, addr += 2)
+ outw(addr, v);
+ else
+ for (; c != 0; c--, addr += 2)
+ *(volatile u_int16_t *)(addr) = v;
+}
+
+static __inline void
+x86_memio_set_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ u_int32_t v, size_t c)
+{
+ bus_addr_t addr = h + o;
+
+ if (t == X86_BUS_SPACE_IO)
+ for (; c != 0; c--, addr += 4)
+ outl(addr, v);
+ else
+ for (; c != 0; c--, addr += 4)
+ *(volatile u_int32_t *)(addr) = v;
+}
+
+#if 0 /* Cause a link error for bus_space_set_region_8 */
+#define bus_space_set_region_8 \
+ !!! bus_space_set_region_8 unimplemented !!!
+#endif
+
+/*
+ * void bus_space_copy_N(bus_space_tag_t tag,
+ * bus_space_handle_t bsh1, bus_size_t off1,
+ * bus_space_handle_t bsh2, bus_size_t off2,
+ * size_t count);
+ *
+ * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
+ * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
+ */
+
+#define bus_space_copy_1 bus_space_copy_region_1
+#define bus_space_copy_2 bus_space_copy_region_2
+#define bus_space_copy_4 bus_space_copy_region_4
+#define bus_space_copy_8 bus_space_copy_region_8
+
+static __inline void x86_memio_copy_region_1(bus_space_tag_t,
+ bus_space_handle_t, bus_size_t, bus_space_handle_t,
+ bus_size_t, size_t);
+static __inline void x86_memio_copy_region_2(bus_space_tag_t,
+ bus_space_handle_t, bus_size_t, bus_space_handle_t,
+ bus_size_t, size_t);
+static __inline void x86_memio_copy_region_4(bus_space_tag_t,
+ bus_space_handle_t, bus_size_t, bus_space_handle_t,
+ bus_size_t, size_t);
+
+#define bus_space_copy_region_1(t, h1, o1, h2, o2, c) \
+ x86_memio_copy_region_1((t), (h1), (o1), (h2), (o2), (c))
+
+#define bus_space_copy_region_2(t, h1, o1, h2, o2, c) \
+ x86_memio_copy_region_2((t), (h1), (o1), (h2), (o2), (c))
+
+#define bus_space_copy_region_4(t, h1, o1, h2, o2, c) \
+ x86_memio_copy_region_4((t), (h1), (o1), (h2), (o2), (c))
+
+static __inline void
+x86_memio_copy_region_1(bus_space_tag_t t,
+ bus_space_handle_t h1, bus_size_t o1,
+ bus_space_handle_t h2, bus_size_t o2, size_t c)
+{
+ bus_addr_t addr1 = h1 + o1;
+ bus_addr_t addr2 = h2 + o2;
+
+ if (t == X86_BUS_SPACE_IO) {
+ if (addr1 >= addr2) {
+ /* src after dest: copy forward */
+ for (; c != 0; c--, addr1++, addr2++)
+ outb(addr2, inb(addr1));
+ } else {
+ /* dest after src: copy backwards */
+ for (addr1 += (c - 1), addr2 += (c - 1);
+ c != 0; c--, addr1--, addr2--)
+ outb(addr2, inb(addr1));
+ }
+ } else {
+ if (addr1 >= addr2) {
+ /* src after dest: copy forward */
+ for (; c != 0; c--, addr1++, addr2++)
+ *(volatile u_int8_t *)(addr2) =
+ *(volatile u_int8_t *)(addr1);
+ } else {
+ /* dest after src: copy backwards */
+ for (addr1 += (c - 1), addr2 += (c - 1);
+ c != 0; c--, addr1--, addr2--)
+ *(volatile u_int8_t *)(addr2) =
+ *(volatile u_int8_t *)(addr1);
+ }
+ }
+}
+
+static __inline void
+x86_memio_copy_region_2(bus_space_tag_t t,
+ bus_space_handle_t h1, bus_size_t o1,
+ bus_space_handle_t h2, bus_size_t o2, size_t c)
+{
+ bus_addr_t addr1 = h1 + o1;
+ bus_addr_t addr2 = h2 + o2;
+
+ if (t == X86_BUS_SPACE_IO) {
+ if (addr1 >= addr2) {
+ /* src after dest: copy forward */
+ for (; c != 0; c--, addr1 += 2, addr2 += 2)
+ outw(addr2, inw(addr1));
+ } else {
+ /* dest after src: copy backwards */
+ for (addr1 += 2 * (c - 1), addr2 += 2 * (c - 1);
+ c != 0; c--, addr1 -= 2, addr2 -= 2)
+ outw(addr2, inw(addr1));
+ }
+ } else {
+ if (addr1 >= addr2) {
+ /* src after dest: copy forward */
+ for (; c != 0; c--, addr1 += 2, addr2 += 2)
+ *(volatile u_int16_t *)(addr2) =
+ *(volatile u_int16_t *)(addr1);
+ } else {
+ /* dest after src: copy backwards */
+ for (addr1 += 2 * (c - 1), addr2 += 2 * (c - 1);
+ c != 0; c--, addr1 -= 2, addr2 -= 2)
+ *(volatile u_int16_t *)(addr2) =
+ *(volatile u_int16_t *)(addr1);
+ }
+ }
+}
+
+static __inline void
+x86_memio_copy_region_4(bus_space_tag_t t,
+ bus_space_handle_t h1, bus_size_t o1,
+ bus_space_handle_t h2, bus_size_t o2, size_t c)
+{
+ bus_addr_t addr1 = h1 + o1;
+ bus_addr_t addr2 = h2 + o2;
+
+ if (t == X86_BUS_SPACE_IO) {
+ if (addr1 >= addr2) {
+ /* src after dest: copy forward */
+ for (; c != 0; c--, addr1 += 4, addr2 += 4)
+ outl(addr2, inl(addr1));
+ } else {
+ /* dest after src: copy backwards */
+ for (addr1 += 4 * (c - 1), addr2 += 4 * (c - 1);
+ c != 0; c--, addr1 -= 4, addr2 -= 4)
+ outl(addr2, inl(addr1));
+ }
+ } else {
+ if (addr1 >= addr2) {
+ /* src after dest: copy forward */
+ for (; c != 0; c--, addr1 += 4, addr2 += 4)
+ *(volatile u_int32_t *)(addr2) =
+ *(volatile u_int32_t *)(addr1);
+ } else {
+ /* dest after src: copy backwards */
+ for (addr1 += 4 * (c - 1), addr2 += 4 * (c - 1);
+ c != 0; c--, addr1 -= 4, addr2 -= 4)
+ *(volatile u_int32_t *)(addr2) =
+ *(volatile u_int32_t *)(addr1);
+ }
+ }
+}
+
+#if 0 /* Cause a link error for bus_space_copy_8 */
+#define bus_space_copy_8 \
+ !!! bus_space_copy_8 unimplemented !!!
+#endif
+
+/*
+ * Bus read/write barrier methods.
+ *
+ * void bus_space_barrier(bus_space_tag_t tag,
+ * bus_space_handle_t bsh, bus_size_t offset,
+ * bus_size_t len, int flags);
+ *
+ * Note: the x86 does not currently require barriers, but we must
+ * provide the flags to MI code.
+ */
+#define bus_space_barrier(t, h, o, l, f) \
+ ((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)))
+#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */
+#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */
+/* Compatibility defines */
+#define BUS_BARRIER_READ BUS_SPACE_BARRIER_READ
+#define BUS_BARRIER_WRITE BUS_SPACE_BARRIER_WRITE
+
+/*
+ * Flags used in various bus DMA methods.
+ */
+#define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */
+#define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */
+#define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */
+#define BUS_DMA_COHERENT 0x004 /* hint: map memory DMA coherent */
+#define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */
+#define BUS_DMA_BUS2 0x020
+#define BUS_DMA_BUS3 0x040
+#define BUS_DMA_BUS4 0x080
+#define BUS_DMA_STREAMING 0x100 /* hint: sequential, unidirectional */
+#define BUS_DMA_READ 0x200 /* mapping is device -> memory only */
+#define BUS_DMA_WRITE 0x400 /* mapping is memory -> device only */
+
+/* Forwards needed by prototypes below. */
+struct mbuf;
+struct proc;
+struct uio;
+
+/*
+ * Operations performed by bus_dmamap_sync().
+ */
+#define BUS_DMASYNC_PREREAD 0x01
+#define BUS_DMASYNC_POSTREAD 0x02
+#define BUS_DMASYNC_PREWRITE 0x04
+#define BUS_DMASYNC_POSTWRITE 0x08
+
+typedef struct x86_bus_dma_tag *bus_dma_tag_t;
+typedef struct x86_bus_dmamap *bus_dmamap_t;
+
+/*
+ * bus_dma_segment_t
+ *
+ * Describes a single contiguous DMA transaction. Values
+ * are suitable for programming into DMA registers.
+ */
+struct x86_bus_dma_segment {
+ bus_addr_t ds_addr; /* DMA address */
+ bus_size_t ds_len; /* length of transfer */
+};
+typedef struct x86_bus_dma_segment bus_dma_segment_t;
+
+/*
+ * bus_dma_tag_t
+ *
+ * A machine-dependent opaque type describing the implementation of
+ * DMA for a given bus.
+ */
+
+struct x86_bus_dma_tag {
+ void *_cookie; /* cookie used in the guts */
+
+ /*
+ * DMA mapping methods.
+ */
+ int (*_dmamap_create)(bus_dma_tag_t, bus_size_t, int,
+ bus_size_t, bus_size_t, int, bus_dmamap_t *);
+ void (*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t);
+ int (*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *,
+ bus_size_t, struct proc *, int);
+ int (*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t,
+ struct mbuf *, int);
+ int (*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t,
+ struct uio *, int);
+ int (*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t,
+ bus_dma_segment_t *, int, bus_size_t, int);
+ void (*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t);
+ void (*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t,
+ bus_addr_t, bus_size_t, int);
+
+ /*
+ * DMA memory utility functions.
+ */
+ int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t,
+ bus_size_t, bus_dma_segment_t *, int, int *, int);
+ void (*_dmamem_free)(bus_dma_tag_t,
+ bus_dma_segment_t *, int);
+ int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *,
+ int, size_t, caddr_t *, int);
+ void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t);
+ paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *,
+ int, off_t, int, int);
+};
+
+#define bus_dmamap_create(t, s, n, m, b, f, p) \
+ (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
+#define bus_dmamap_destroy(t, p) \
+ (*(t)->_dmamap_destroy)((t), (p))
+#define bus_dmamap_load(t, m, b, s, p, f) \
+ (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
+#define bus_dmamap_load_mbuf(t, m, b, f) \
+ (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
+#define bus_dmamap_load_uio(t, m, u, f) \
+ (*(t)->_dmamap_load_uio)((t), (m), (u), (f))
+#define bus_dmamap_load_raw(t, m, sg, n, s, f) \
+ (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
+#define bus_dmamap_unload(t, p) \
+ (*(t)->_dmamap_unload)((t), (p))
+#define bus_dmamap_sync(t, p, o, l, ops) \
+ (void)((t)->_dmamap_sync ? \
+ (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) : (void)0)
+
+#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \
+ (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f))
+#define bus_dmamem_free(t, sg, n) \
+ (*(t)->_dmamem_free)((t), (sg), (n))
+#define bus_dmamem_map(t, sg, n, s, k, f) \
+ (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f))
+#define bus_dmamem_unmap(t, k, s) \
+ (*(t)->_dmamem_unmap)((t), (k), (s))
+#define bus_dmamem_mmap(t, sg, n, o, p, f) \
+ (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))
+
+/*
+ * bus_dmamap_t
+ *
+ * Describes a DMA mapping.
+ */
+struct x86_bus_dmamap {
+ /*
+ * PRIVATE MEMBERS: not for use my machine-independent code.
+ */
+ bus_size_t _dm_size; /* largest DMA transfer mappable */
+ int _dm_segcnt; /* number of segs this map can map */
+ bus_size_t _dm_maxsegsz; /* largest possible segment */
+ bus_size_t _dm_boundary; /* don't cross this */
+ int _dm_flags; /* misc. flags */
+
+ void *_dm_cookie; /* cookie for bus-specific functions */
+
+ /*
+ * PUBLIC MEMBERS: these are used by machine-independent code.
+ */
+ bus_size_t dm_mapsize; /* size of the mapping */
+ int dm_nsegs; /* # valid segments in mapping */
+ bus_dma_segment_t dm_segs[1]; /* segments; variable length */
+};
+
+#ifdef _X86_BUS_DMA_PRIVATE
+int _bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
+ bus_size_t, int, bus_dmamap_t *);
+void _bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
+int _bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *,
+ bus_size_t, struct proc *, int);
+int _bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t,
+ struct mbuf *, int);
+int _bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t,
+ struct uio *, int);
+int _bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
+ bus_dma_segment_t *, int, bus_size_t, int);
+void _bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
+void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
+ bus_size_t, int);
+
+int _bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size,
+ bus_size_t alignment, bus_size_t boundary,
+ bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);
+void _bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs,
+ int nsegs);
+int _bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs,
+ int nsegs, size_t size, caddr_t *kvap, int flags);
+void _bus_dmamem_unmap(bus_dma_tag_t tag, caddr_t kva,
+ size_t size);
+paddr_t _bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs,
+ int nsegs, off_t off, int prot, int flags);
+
+int _bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size,
+ bus_size_t alignment, bus_size_t boundary,
+ bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
+ paddr_t low, paddr_t high);
+
+/*
+ * int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
+ * bus_addr_t rend, bus_size_t size, bus_size_t align,
+ * bus_size_t boundary, int flags, bus_addr_t *addrp,
+ * bus_space_handle_t *bshp);
+ *
+ * Allocate a region of bus space.
+ */
+
+int x86_memio_alloc(bus_space_tag_t t, bus_addr_t rstart,
+ bus_addr_t rend, bus_size_t size, bus_size_t align,
+ bus_size_t boundary, int flags, bus_addr_t *addrp,
+ bus_space_handle_t *bshp);
+
+/*
+ * int bus_space_free(bus_space_tag_t t,
+ * bus_space_handle_t bsh, bus_size_t size);
+ *
+ * Free a region of bus space.
+ */
+
+void x86_memio_free(bus_space_tag_t t, bus_space_handle_t bsh,
+ bus_size_t size);
+
+/*
+ * paddr_t bus_space_mmap(bus_space_tag_t t, bus_addr_t base,
+ * off_t offset, int prot, int flags);
+ *
+ * Mmap an area of bus space.
+ */
+
+paddr_t x86_memio_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int);
+
+
+#endif /* _X86_BUS_DMA_PRIVATE */
+
+#endif /* _X86_BUS_H_ */
diff --git a/sys/arch/amd64/include/cacheinfo.h b/sys/arch/amd64/include/cacheinfo.h
new file mode 100644
index 00000000000..ea0d7837029
--- /dev/null
+++ b/sys/arch/amd64/include/cacheinfo.h
@@ -0,0 +1,111 @@
+/* $OpenBSD: cacheinfo.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: cacheinfo.h,v 1.1 2003/04/25 21:54:30 fvdl Exp $ */
+
+#ifndef _X86_CACHEINFO_H
+#define _X86_CACHEINFO_H
+
+struct x86_cache_info {
+ uint8_t cai_index;
+ uint8_t cai_desc;
+ uint8_t cai_associativity;
+ u_int cai_totalsize; /* #entries for TLB, bytes for cache */
+ u_int cai_linesize; /* or page size for TLB */
+ const char *cai_string;
+};
+
+#define CAI_ITLB 0 /* Instruction TLB (4K pages) */
+#define CAI_ITLB2 1 /* Instruction TLB (2/4M pages) */
+#define CAI_DTLB 2 /* Data TLB (4K pages) */
+#define CAI_DTLB2 3 /* Data TLB (2/4M pages) */
+#define CAI_ICACHE 4 /* Instruction cache */
+#define CAI_DCACHE 5 /* Data cache */
+#define CAI_L2CACHE 6 /* Level 2 cache */
+
+#define CAI_COUNT 7
+
+struct cpu_info;
+
+const struct x86_cache_info *cache_info_lookup(const struct x86_cache_info *,
+ u_int8_t);
+void amd_cpu_cacheinfo(struct cpu_info *);
+void x86_print_cacheinfo(struct cpu_info *);
+
+/*
+ * AMD Cache Info:
+ *
+ * Athlon, Duron:
+ *
+ * Function 8000.0005 L1 TLB/Cache Information
+ * EAX -- L1 TLB 2/4MB pages
+ * EBX -- L1 TLB 4K pages
+ * ECX -- L1 D-cache
+ * EDX -- L1 I-cache
+ *
+ * Function 8000.0006 L2 TLB/Cache Information
+ * EAX -- L2 TLB 2/4MB pages
+ * EBX -- L2 TLB 4K pages
+ * ECX -- L2 Unified cache
+ * EDX -- reserved
+ *
+ * K5, K6:
+ *
+ * Function 8000.0005 L1 TLB/Cache Information
+ * EAX -- reserved
+ * EBX -- TLB 4K pages
+ * ECX -- L1 D-cache
+ * EDX -- L1 I-cache
+ *
+ * K6-III:
+ *
+ * Function 8000.0006 L2 Cache Information
+ * EAX -- reserved
+ * EBX -- reserved
+ * ECX -- L2 Unified cache
+ * EDX -- reserved
+ */
+
+/* L1 TLB 2/4MB pages */
+#define AMD_L1_EAX_DTLB_ASSOC(x) (((x) >> 24) & 0xff)
+#define AMD_L1_EAX_DTLB_ENTRIES(x) (((x) >> 16) & 0xff)
+#define AMD_L1_EAX_ITLB_ASSOC(x) (((x) >> 8) & 0xff)
+#define AMD_L1_EAX_ITLB_ENTRIES(x) ( (x) & 0xff)
+
+/* L1 TLB 4K pages */
+#define AMD_L1_EBX_DTLB_ASSOC(x) (((x) >> 24) & 0xff)
+#define AMD_L1_EBX_DTLB_ENTRIES(x) (((x) >> 16) & 0xff)
+#define AMD_L1_EBX_ITLB_ASSOC(x) (((x) >> 8) & 0xff)
+#define AMD_L1_EBX_ITLB_ENTRIES(x) ( (x) & 0xff)
+
+/* L1 Data Cache */
+#define AMD_L1_ECX_DC_SIZE(x) ((((x) >> 24) & 0xff) * 1024)
+#define AMD_L1_ECX_DC_ASSOC(x) (((x) >> 16) & 0xff)
+#define AMD_L1_ECX_DC_LPT(x) (((x) >> 8) & 0xff)
+#define AMD_L1_ECX_DC_LS(x) ( (x) & 0xff)
+
+/* L1 Instruction Cache */
+#define AMD_L1_EDX_IC_SIZE(x) ((((x) >> 24) & 0xff) * 1024)
+#define AMD_L1_EDX_IC_ASSOC(x) (((x) >> 16) & 0xff)
+#define AMD_L1_EDX_IC_LPT(x) (((x) >> 8) & 0xff)
+#define AMD_L1_EDX_IC_LS(x) ( (x) & 0xff)
+
+/* Note for L2 TLB -- if the upper 16 bits are 0, it is a unified TLB */
+
+/* L2 TLB 2/4MB pages */
+#define AMD_L2_EAX_DTLB_ASSOC(x) (((x) >> 28) & 0xf)
+#define AMD_L2_EAX_DTLB_ENTRIES(x) (((x) >> 16) & 0xfff)
+#define AMD_L2_EAX_IUTLB_ASSOC(x) (((x) >> 12) & 0xf)
+#define AMD_L2_EAX_IUTLB_ENTRIES(x) ( (x) & 0xfff)
+
+/* L2 TLB 4K pages */
+#define AMD_L2_EBX_DTLB_ASSOC(x) (((x) >> 28) & 0xf)
+#define AMD_L2_EBX_DTLB_ENTRIES(x) (((x) >> 16) & 0xfff)
+#define AMD_L2_EBX_IUTLB_ASSOC(x) (((x) >> 12) & 0xf)
+#define AMD_L2_EBX_IUTLB_ENTRIES(x) ( (x) & 0xfff)
+
+/* L2 Cache */
+#define AMD_L2_ECX_C_SIZE(x) ((((x) >> 16) & 0xffff) * 1024)
+#define AMD_L2_ECX_C_ASSOC(x) (((x) >> 12) & 0xf)
+#define AMD_L2_ECX_C_LPT(x) (((x) >> 8) & 0xf)
+#define AMD_L2_ECX_C_LS(x) ( (x) & 0xff)
+
+#endif /* _X86_CACHEINFO_H */
diff --git a/sys/arch/amd64/include/cdefs.h b/sys/arch/amd64/include/cdefs.h
new file mode 100644
index 00000000000..26606d3e377
--- /dev/null
+++ b/sys/arch/amd64/include/cdefs.h
@@ -0,0 +1,23 @@
+/* $OpenBSD: cdefs.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: cdefs.h,v 1.2 1995/03/23 20:10:26 jtc Exp $ */
+
+/*
+ * Written by J.T. Conklin <jtc@wimsey.com> 01/17/95.
+ * Public domain.
+ */
+
+#ifndef _MACHINE_CDEFS_H_
+#define _MACHINE_CDEFS_H_
+
+#if defined(__GNUC__) && defined(__STDC__)
+#define __weak_alias(alias,sym) \
+ __asm__(".weak " __STRING(alias) " ; " __STRING(alias) " = " __STRING(sym))
+#define __warn_references(sym,msg) \
+ __asm__(".section .gnu.warning." __STRING(sym) " ; .ascii \"" msg "\" ; .text")
+#else
+#define __indr_reference(sym,alias)
+#define __warn_references(sym,msg)
+#define __weak_alias(alias,sym)
+#endif
+
+#endif /* !_MACHINE_CDEFS_H_ */
diff --git a/sys/arch/amd64/include/conf.h b/sys/arch/amd64/include/conf.h
new file mode 100644
index 00000000000..0eeee30a029
--- /dev/null
+++ b/sys/arch/amd64/include/conf.h
@@ -0,0 +1,45 @@
+/* $OpenBSD: conf.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */
+
+/*
+ * Copyright (c) 1996 Christos Zoulas. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christos Zoulas.
+ * 4. 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.
+ */
+
+#include <sys/conf.h>
+
+#define mmread mmrw
+#define mmwrite mmrw
+cdev_decl(mm);
+
+bdev_decl(fd);
+cdev_decl(fd);
+
+cdev_decl(spkr);
+
+#define biosselect seltrue
+cdev_decl(bios);
diff --git a/sys/arch/amd64/include/cpu.h b/sys/arch/amd64/include/cpu.h
new file mode 100644
index 00000000000..44e4a446ccb
--- /dev/null
+++ b/sys/arch/amd64/include/cpu.h
@@ -0,0 +1,376 @@
+/* $OpenBSD: cpu.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)cpu.h 5.4 (Berkeley) 5/9/91
+ */
+
+#ifndef _AMD64_CPU_H_
+#define _AMD64_CPU_H_
+
+/*
+ * Definitions unique to x86-64 cpu support.
+ */
+#include <machine/frame.h>
+#include <machine/segments.h>
+#include <machine/tss.h>
+#include <machine/intrdefs.h>
+#include <machine/cacheinfo.h>
+
+#include <sys/device.h>
+#include <sys/lock.h>
+
+struct cpu_info {
+ struct device *ci_dev;
+ struct cpu_info *ci_self;
+#if 0
+ struct schedstate_percpu ci_schedstate; /* scheduler state */
+#endif
+ struct cpu_info *ci_next;
+
+ struct proc *ci_curproc;
+ struct simplelock ci_slock;
+ u_int ci_cpuid;
+ u_int ci_apicid;
+ u_long ci_spin_locks;
+ u_long ci_simple_locks;
+
+ u_int64_t ci_scratch;
+
+ struct proc *ci_fpcurproc;
+ int ci_fpsaving;
+
+ volatile u_int32_t ci_tlb_ipi_mask;
+
+ struct pcb *ci_curpcb;
+ struct pcb *ci_idle_pcb;
+ int ci_idle_tss_sel;
+
+ struct intrsource *ci_isources[MAX_INTR_SOURCES];
+ u_int32_t ci_ipending;
+ int ci_ilevel;
+ int ci_idepth;
+ u_int32_t ci_imask[NIPL];
+ u_int32_t ci_iunmask[NIPL];
+
+ paddr_t ci_idle_pcb_paddr;
+ u_int ci_flags;
+ u_int32_t ci_ipis;
+
+ u_int32_t ci_feature_flags;
+ u_int32_t ci_signature;
+ u_int64_t ci_tsc_freq;
+
+ struct cpu_functions *ci_func;
+ void (*cpu_setup)(struct cpu_info *);
+ void (*ci_info)(struct cpu_info *);
+
+ int ci_want_resched;
+ int ci_astpending;
+ struct trapframe *ci_ddb_regs;
+
+ struct x86_cache_info ci_cinfo[CAI_COUNT];
+
+ struct timeval ci_cc_time;
+ int64_t ci_cc_cc;
+ int64_t ci_cc_ms_delta;
+ int64_t ci_cc_denom;
+
+ char *ci_gdt;
+
+ struct x86_64_tss ci_doubleflt_tss;
+ struct x86_64_tss ci_ddbipi_tss;
+
+ char *ci_doubleflt_stack;
+ char *ci_ddbipi_stack;
+
+ struct evcnt ci_ipi_events[X86_NIPI];
+};
+
+#define CPUF_BSP 0x0001 /* CPU is the original BSP */
+#define CPUF_AP 0x0002 /* CPU is an AP */
+#define CPUF_SP 0x0004 /* CPU is only processor */
+#define CPUF_PRIMARY 0x0008 /* CPU is active primary processor */
+
+#define CPUF_PRESENT 0x1000 /* CPU is present */
+#define CPUF_RUNNING 0x2000 /* CPU is running */
+#define CPUF_PAUSE 0x4000 /* CPU is paused in DDB */
+#define CPUF_GO 0x8000 /* CPU should start running */
+
+#define PROC_PC(p) ((p)->p_md.md_regs->tf_rip)
+
+extern struct cpu_info cpu_info_primary;
+extern struct cpu_info *cpu_info_list;
+
+#define CPU_INFO_ITERATOR int
+#define CPU_INFO_FOREACH(cii, ci) cii = 0, ci = cpu_info_list; \
+ ci != NULL; ci = ci->ci_next
+
+#if defined(MULTIPROCESSOR)
+
+#define X86_MAXPROCS 32 /* bitmask; can be bumped to 64 */
+
+#define CPU_STARTUP(_ci) ((_ci)->ci_func->start(_ci))
+#define CPU_STOP(_ci) ((_ci)->ci_func->stop(_ci))
+#define CPU_START_CLEANUP(_ci) ((_ci)->ci_func->cleanup(_ci))
+
+#define curcpu() ({struct cpu_info *__ci; \
+ asm volatile("movq %%gs:8,%0" : "=r" (__ci)); \
+ __ci;})
+#define cpu_number() (curcpu()->ci_cpuid)
+
+#define CPU_IS_PRIMARY(ci) ((ci)->ci_flags & CPUF_PRIMARY)
+
+extern struct cpu_info *cpu_info[X86_MAXPROCS];
+
+void cpu_boot_secondary_processors(void);
+void cpu_init_idle_pcbs(void);
+
+
+/*
+ * Preempt the current process if in interrupt from user mode,
+ * or after the current trap/syscall if in system mode.
+ */
+extern void need_resched(struct cpu_info *);
+
+#else /* !MULTIPROCESSOR */
+
+#define X86_MAXPROCS 1
+
+#ifdef _KERNEL
+extern struct cpu_info cpu_info_primary;
+
+#define curcpu() (&cpu_info_primary)
+
+#endif
+
+/*
+ * definitions of cpu-dependent requirements
+ * referenced in generic code
+ */
+#define cpu_number() 0
+#define CPU_IS_PRIMARY(ci) 1
+
+/*
+ * Preempt the current process if in interrupt from user mode,
+ * or after the current trap/syscall if in system mode.
+ */
+
+#ifdef MULTIPROCESSOR
+#define need_resched(ci) \
+do { \
+ struct cpu_info *__ci = (ci); \
+ __ci->ci_want_resched = 1; \
+ if (__ci->ci_curproc != NULL) \
+ aston(__ci->ci_curproc); \
+} while (/*CONSTCOND*/0)
+#else
+#define need_resched() \
+do { \
+ struct cpu_info *__ci = curcpu(); \
+ __ci->ci_want_resched = 1; \
+ if (__ci->ci_curproc != NULL) \
+ aston(__ci->ci_curproc); \
+} while (/*CONSTCOND*/0)
+#endif
+
+#endif
+
+#define aston(p) ((p)->p_md.md_astpending = 1)
+
+extern u_int32_t cpus_attached;
+
+#define curpcb curcpu()->ci_curpcb
+#define curproc curcpu()->ci_curproc
+
+/*
+ * Arguments to hardclock, softclock and statclock
+ * encapsulate the previous machine state in an opaque
+ * clockframe; for now, use generic intrframe.
+ */
+#define clockframe intrframe
+
+#define CLKF_USERMODE(frame) USERMODE((frame)->if_cs, (frame)->if_rflags)
+#define CLKF_BASEPRI(frame) (0)
+#define CLKF_PC(frame) ((frame)->if_rip)
+#define CLKF_INTR(frame) (curcpu()->ci_idepth > 1)
+
+/*
+ * Give a profiling tick to the current process when the user profiling
+ * buffer pages are invalid. On the i386, request an ast to send us
+ * through trap(), marking the proc as needing a profiling tick.
+ */
+#define need_proftick(p) ((p)->p_flag |= P_OWEUPC, aston(p))
+
+/*
+ * Notify the current process (p) that it has a signal pending,
+ * process as soon as possible.
+ */
+#define signotify(p) aston(p)
+
+/*
+ * We need a machine-independent name for this.
+ */
+extern void (*delay_func)(int);
+struct timeval;
+extern void (*microtime_func)(struct timeval *);
+
+#define DELAY(x) (*delay_func)(x)
+#define delay(x) (*delay_func)(x)
+#define microtime(tv) (*microtime_func)(tv)
+
+
+/*
+ * pull in #defines for kinds of processors
+ */
+
+#ifdef _KERNEL
+extern int biosbasemem;
+extern int biosextmem;
+extern int cpu;
+extern int cpu_feature;
+extern int cpu_id;
+extern char cpu_vendor[];
+extern int cpuid_level;
+
+/* kern_microtime.c */
+
+extern struct timeval cc_microset_time;
+void cc_microtime(struct timeval *);
+void cc_microset(struct cpu_info *);
+
+/* identcpu.c */
+
+void identifycpu(struct cpu_info *);
+void cpu_probe_features(struct cpu_info *);
+
+/* machdep.c */
+void delay(int);
+void dumpconf(void);
+int cpu_maxproc(void);
+void cpu_reset(void);
+void x86_64_proc0_tss_ldt_init(void);
+void x86_64_bufinit(void);
+void x86_64_init_pcb_tss_ldt(struct cpu_info *);
+void cpu_proc_fork(struct proc *, struct proc *);
+
+struct region_descriptor;
+void lgdt(struct region_descriptor *);
+void fillw(short, void *, size_t);
+
+struct pcb;
+void savectx(struct pcb *);
+void switch_exit(struct proc *, void (*)(struct proc *));
+void proc_trampoline(void);
+void child_trampoline(void);
+
+/* clock.c */
+void initrtclock(void);
+void startrtclock(void);
+void i8254_delay(int);
+void i8254_microtime(struct timeval *);
+void i8254_initclocks(void);
+
+void cpu_init_msrs(struct cpu_info *);
+
+
+/* trap.c */
+void child_return(void *);
+
+/* consinit.c */
+void kgdb_port_init(void);
+
+/* bus_machdep.c */
+void x86_bus_space_init(void);
+void x86_bus_space_mallocok(void);
+
+#endif /* _KERNEL */
+
+#include <machine/psl.h>
+
+/*
+ * CTL_MACHDEP definitions.
+ */
+#define CPU_CONSDEV 1 /* dev_t: console terminal device */
+#define CPU_BIOSBASEMEM 2 /* int: bios-reported base mem (K) */
+#define CPU_BIOSEXTMEM 3 /* int: bios-reported ext. mem (K) */
+#define CPU_NKPDE 4 /* int: number of kernel PDEs */
+#define CPU_BOOTED_KERNEL 5 /* string: booted kernel name */
+#define CPU_DISKINFO 6 /* disk geometry information */
+#define CPU_FPU_PRESENT 7 /* FPU is present */
+#define CPU_MAXID 8 /* number of valid machdep ids */
+
+#define CTL_MACHDEP_NAMES { \
+ { 0, 0 }, \
+ { "console_device", CTLTYPE_STRUCT }, \
+ { "biosbasemem", CTLTYPE_INT }, \
+ { "biosextmem", CTLTYPE_INT }, \
+ { "nkpde", CTLTYPE_INT }, \
+ { "booted_kernel", CTLTYPE_STRING }, \
+ { "diskinfo", CTLTYPE_STRUCT }, \
+ { "fpu_present", CTLTYPE_INT }, \
+}
+
+
+/*
+ * Structure for CPU_DISKINFO sysctl call.
+ * XXX this should be somewhere else.
+ */
+#define MAX_BIOSDISKS 16
+
+struct disklist {
+ int dl_nbiosdisks; /* number of bios disks */
+ struct biosdisk_info {
+ int bi_dev; /* BIOS device # (0x80 ..) */
+ int bi_cyl; /* cylinders on disk */
+ int bi_head; /* heads per track */
+ int bi_sec; /* sectors per track */
+ u_int64_t bi_lbasecs; /* total sec. (iff ext13) */
+#define BIFLAG_INVALID 0x01
+#define BIFLAG_EXTINT13 0x02
+ int bi_flags;
+ } dl_biosdisks[MAX_BIOSDISKS];
+
+ int dl_nnativedisks; /* number of native disks */
+ struct nativedisk_info {
+ char ni_devname[16]; /* native device name */
+ int ni_nmatches; /* # of matches w/ BIOS */
+ int ni_biosmatches[MAX_BIOSDISKS]; /* indices in dl_biosdisks */
+ } dl_nativedisks[1]; /* actually longer */
+};
+
+#endif /* !_AMD64_CPU_H_ */
diff --git a/sys/arch/amd64/include/cpufunc.h b/sys/arch/amd64/include/cpufunc.h
new file mode 100644
index 00000000000..085a658a23e
--- /dev/null
+++ b/sys/arch/amd64/include/cpufunc.h
@@ -0,0 +1,280 @@
+/* $OpenBSD: cpufunc.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: cpufunc.h,v 1.3 2003/05/08 10:27:43 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef _AMD64_CPUFUNC_H_
+#define _AMD64_CPUFUNC_H_
+
+/*
+ * Functions to provide access to i386-specific instructions.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <machine/specialreg.h>
+
+static __inline void
+x86_pause(void)
+{
+ /* nothing */
+}
+
+#ifdef _KERNEL
+
+extern int cpu_feature;
+
+static __inline void
+invlpg(u_int64_t addr)
+{
+ __asm __volatile("invlpg (%0)" : : "r" (addr) : "memory");
+}
+
+static __inline void
+lidt(void *p)
+{
+ __asm __volatile("lidt (%0)" : : "r" (p));
+}
+
+static __inline void
+lldt(u_short sel)
+{
+ __asm __volatile("lldt %0" : : "r" (sel));
+}
+
+static __inline void
+ltr(u_short sel)
+{
+ __asm __volatile("ltr %0" : : "r" (sel));
+}
+
+static __inline void
+lcr8(u_int val)
+{
+ u_int64_t val64 = val;
+ __asm __volatile("movq %0,%%cr8" : : "r" (val64));
+}
+
+/*
+ * Upper 32 bits are reserved anyway, so just keep this 32bits.
+ */
+static __inline void
+lcr0(u_int val)
+{
+ u_int64_t val64 = val;
+ __asm __volatile("movq %0,%%cr0" : : "r" (val64));
+}
+
+static __inline u_int
+rcr0(void)
+{
+ u_int64_t val64;
+ u_int val;
+ __asm __volatile("movq %%cr0,%0" : "=r" (val64));
+ val = val64;
+ return val;
+}
+
+static __inline u_int64_t
+rcr2(void)
+{
+ u_int64_t val;
+ __asm __volatile("movq %%cr2,%0" : "=r" (val));
+ return val;
+}
+
+static __inline void
+lcr3(u_int64_t val)
+{
+ __asm __volatile("movq %0,%%cr3" : : "r" (val));
+}
+
+static __inline u_int64_t
+rcr3(void)
+{
+ u_int64_t val;
+ __asm __volatile("movq %%cr3,%0" : "=r" (val));
+ return val;
+}
+
+/*
+ * Same as for cr0. Don't touch upper 32 bits.
+ */
+static __inline void
+lcr4(u_int val)
+{
+ u_int64_t val64 = val;
+
+ __asm __volatile("movq %0,%%cr4" : : "r" (val64));
+}
+
+static __inline u_int
+rcr4(void)
+{
+ u_int val;
+ u_int64_t val64;
+ __asm __volatile("movq %%cr4,%0" : "=r" (val64));
+ val = val64;
+ return val;
+}
+
+static __inline void
+tlbflush(void)
+{
+ u_int64_t val;
+ __asm __volatile("movq %%cr3,%0" : "=r" (val));
+ __asm __volatile("movq %0,%%cr3" : : "r" (val));
+}
+
+static __inline void
+tlbflushg(void)
+{
+ /*
+ * Big hammer: flush all TLB entries, including ones from PTE's
+ * with the G bit set. This should only be necessary if TLB
+ * shootdown falls far behind.
+ *
+ * Intel Architecture Software Developer's Manual, Volume 3,
+ * System Programming, section 9.10, "Invalidating the
+ * Translation Lookaside Buffers (TLBS)":
+ * "The following operations invalidate all TLB entries, irrespective
+ * of the setting of the G flag:
+ * ...
+ * "(P6 family processors only): Writing to control register CR4 to
+ * modify the PSE, PGE, or PAE flag."
+ *
+ * (the alternatives not quoted above are not an option here.)
+ *
+ * If PGE is not in use, we reload CR3 for the benefit of
+ * pre-P6-family processors.
+ */
+
+ if (cpu_feature & CPUID_PGE) {
+ u_int cr4 = rcr4();
+ lcr4(cr4 & ~CR4_PGE);
+ lcr4(cr4);
+ } else
+ tlbflush();
+}
+
+#ifdef notyet
+void setidt(int idx, /*XXX*/caddr_t func, int typ, int dpl);
+#endif
+
+
+/* XXXX ought to be in psl.h with spl() functions */
+
+static __inline void
+disable_intr(void)
+{
+ __asm __volatile("cli");
+}
+
+static __inline void
+enable_intr(void)
+{
+ __asm __volatile("sti");
+}
+
+static __inline u_long
+read_rflags(void)
+{
+ u_long ef;
+
+ __asm __volatile("pushfq; popq %0" : "=r" (ef));
+ return (ef);
+}
+
+static __inline void
+write_rflags(u_long ef)
+{
+ __asm __volatile("pushq %0; popfq" : : "r" (ef));
+}
+
+static __inline u_int64_t
+rdmsr(u_int msr)
+{
+ uint32_t hi, lo;
+ __asm __volatile("rdmsr" : "=d" (hi), "=a" (lo) : "c" (msr));
+ return (((uint64_t)hi << 32) | (uint64_t) lo);
+}
+
+static __inline void
+wrmsr(u_int msr, u_int64_t newval)
+{
+ __asm __volatile("wrmsr" :
+ : "a" (newval & 0xffffffff), "d" (newval >> 32), "c" (msr));
+}
+
+static __inline void
+wbinvd(void)
+{
+ __asm __volatile("wbinvd");
+}
+
+static __inline u_int64_t
+rdtsc(void)
+{
+ uint32_t hi, lo;
+
+ __asm __volatile("rdtsc" : "=d" (hi), "=a" (lo));
+ return (((uint64_t)hi << 32) | (uint64_t) lo);
+}
+
+static __inline u_int64_t
+rdpmc(u_int pmc)
+{
+ uint32_t hi, lo;
+
+ __asm __volatile("rdpmc" : "=d" (hi), "=a" (lo) : "c" (pmc));
+ return (((uint64_t)hi << 32) | (uint64_t) lo);
+}
+
+/* Break into DDB/KGDB. */
+static __inline void
+breakpoint(void)
+{
+ __asm __volatile("int $3");
+}
+
+#define read_psl() read_rflags()
+#define write_psl(x) write_rflags(x)
+
+#endif /* _KERNEL */
+
+#endif /* !_AMD64_CPUFUNC_H_ */
diff --git a/sys/arch/amd64/include/cpuvar.h b/sys/arch/amd64/include/cpuvar.h
new file mode 100644
index 00000000000..b821592e1b8
--- /dev/null
+++ b/sys/arch/amd64/include/cpuvar.h
@@ -0,0 +1,109 @@
+/* $OpenBSD: cpuvar.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: cpuvar.h,v 1.1 2003/03/01 18:29:28 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by RedBack Networks Inc.
+ *
+ * Author: Bill Sommerfeld
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1999 Stefan Grefen
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 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 AND 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.
+ */
+
+struct cpu_functions {
+ int (*start)(struct cpu_info *);
+ int (*stop)(struct cpu_info *);
+ void (*cleanup)(struct cpu_info *);
+};
+
+extern struct cpu_functions mp_cpu_funcs;
+
+#define CPU_ROLE_SP 0
+#define CPU_ROLE_BP 1
+#define CPU_ROLE_AP 2
+
+struct cpu_attach_args {
+ const char *caa_name;
+ int cpu_number;
+ int cpu_role;
+ struct cpu_functions *cpu_func;
+};
+
+#define MP_PICMODE 0x00000001 /* System booted in picmode */
+
+#ifdef _KERNEL
+
+#ifdef MULTIPROCESSOR
+extern u_int32_t cpus_running;
+#endif
+
+int x86_ipi(int,int,int);
+void x86_self_ipi(int);
+int x86_ipi_init(int);
+
+void identifycpu(struct cpu_info *);
+void cpu_init(struct cpu_info *);
+void cpu_init_first(void);
+
+#endif
diff --git a/sys/arch/amd64/include/db_machdep.h b/sys/arch/amd64/include/db_machdep.h
new file mode 100644
index 00000000000..c2569ee9379
--- /dev/null
+++ b/sys/arch/amd64/include/db_machdep.h
@@ -0,0 +1,141 @@
+/* $OpenBSD: db_machdep.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: db_machdep.h,v 1.2 2003/04/29 17:06:04 scw Exp $ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+#ifndef _I386_DB_MACHDEP_H_
+#define _I386_DB_MACHDEP_H_
+
+/*
+ * Machine-dependent defines for new kernel debugger.
+ */
+
+#include <sys/param.h>
+#include <uvm/uvm_extern.h>
+#include <machine/trap.h>
+
+typedef vaddr_t db_addr_t; /* address - unsigned */
+typedef long db_expr_t; /* expression - signed */
+
+typedef struct trapframe db_regs_t;
+#ifndef MULTIPROCESSOR
+extern db_regs_t ddb_regs; /* register state */
+#define DDB_REGS (&ddb_regs)
+#else
+extern db_regs_t *ddb_regp;
+#define DDB_REGS (ddb_regp)
+#define ddb_regs (*ddb_regp)
+#endif
+
+#if defined(lint)
+#define PC_REGS(regs) ((regs)->tf_rip)
+#else
+#define PC_REGS(regs) ((db_addr_t)(regs)->tf_rip)
+#endif
+
+#define BKPT_ADDR(addr) (addr) /* breakpoint address */
+#define BKPT_INST 0xcc /* breakpoint instruction */
+#define BKPT_SIZE (1) /* size of breakpoint inst */
+#define BKPT_SET(inst) (BKPT_INST)
+
+#define FIXUP_PC_AFTER_BREAK(regs) ((regs)->tf_rip -= BKPT_SIZE)
+
+#define db_clear_single_step(regs) ((regs)->tf_rflags &= ~PSL_T)
+#define db_set_single_step(regs) ((regs)->tf_rflags |= PSL_T)
+
+#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BPTFLT)
+#define IS_WATCHPOINT_TRAP(type, code) ((type) == T_TRCTRAP && (code) & 15)
+
+#define I_CALL 0xe8
+#define I_CALLI 0xff
+#define I_RET 0xc3
+#define I_IRET 0xcf
+
+#define inst_trap_return(ins) (((ins)&0xff) == I_IRET)
+#define inst_return(ins) (((ins)&0xff) == I_RET)
+#define inst_call(ins) (((ins)&0xff) == I_CALL || \
+ (((ins)&0xff) == I_CALLI && \
+ ((ins)&0x3800) == 0x1000))
+#define inst_load(ins) 0
+#define inst_store(ins) 0
+
+/* access capability and access macros */
+
+#define DB_ACCESS_LEVEL 2 /* access any space */
+#define DB_CHECK_ACCESS(addr,size,task) \
+ db_check_access(addr,size,task)
+#define DB_PHYS_EQ(task1,addr1,task2,addr2) \
+ db_phys_eq(task1,addr1,task2,addr2)
+#define DB_VALID_KERN_ADDR(addr) \
+ ((addr) >= VM_MIN_KERNEL_ADDRESS && \
+ (addr) < VM_MAX_KERNEL_ADDRESS)
+#define DB_VALID_ADDRESS(addr,user) \
+ ((!(user) && DB_VALID_KERN_ADDR(addr)) || \
+ ((user) && (addr) < VM_MAX_ADDRESS))
+
+#if 0
+boolean_t db_check_access(vaddr_t, int, task_t);
+boolean_t db_phys_eq(task_t, vaddr_t, task_t, vaddr_t);
+#endif
+
+/* macros for printing OS server dependent task name */
+
+#define DB_TASK_NAME(task) db_task_name(task)
+#define DB_TASK_NAME_TITLE "COMMAND "
+#define DB_TASK_NAME_LEN 23
+#define DB_NULL_TASK_NAME "? "
+
+/*
+ * Constants for KGDB.
+ */
+typedef long kgdb_reg_t;
+#define KGDB_NUMREGS 16
+#define KGDB_BUFLEN 512
+
+#if 0
+void db_task_name(/* task_t */);
+#endif
+
+/* macro for checking if a thread has used floating-point */
+
+#define db_thread_fp_used(thread) ((thread)->pcb->ims.ifps != 0)
+
+int kdb_trap(int, int, db_regs_t *);
+
+/*
+ * We define some of our own commands
+ */
+#define DB_MACHINE_COMMANDS
+
+#define DB_ELF_SYMBOLS
+#define DB_ELFSIZE 64
+
+extern void db_machine_init(void);
+
+extern void cpu_debug_dump(void);
+
+#endif /* _I386_DB_MACHDEP_H_ */
diff --git a/sys/arch/amd64/include/disklabel.h b/sys/arch/amd64/include/disklabel.h
new file mode 100644
index 00000000000..8b2ef5f335c
--- /dev/null
+++ b/sys/arch/amd64/include/disklabel.h
@@ -0,0 +1,118 @@
+/* $OpenBSD: disklabel.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: disklabel.h,v 1.3 1996/03/09 20:52:54 ghudson Exp $ */
+
+/*
+ * Copyright (c) 1994 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou.
+ * 4. 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.
+ */
+
+#ifndef _MACHINE_DISKLABEL_H_
+#define _MACHINE_DISKLABEL_H_
+
+#define LABELSECTOR 1 /* sector containing label */
+#define LABELOFFSET 0 /* offset of label in sector */
+#define MAXPARTITIONS 16 /* number of partitions */
+#define RAW_PART 2 /* raw partition: ie. rsd0c */
+
+/* DOS partition table -- located in boot block */
+#define DOSBBSECTOR 0 /* DOS boot block relative sector # */
+#define DOSPARTOFF 446
+#define DOSDISKOFF 444
+#define NDOSPART 4
+#define DOSACTIVE 0x80 /* active partition */
+
+struct dos_partition {
+ u_int8_t dp_flag; /* bootstrap flags */
+ u_int8_t dp_shd; /* starting head */
+ u_int8_t dp_ssect; /* starting sector */
+ u_int8_t dp_scyl; /* starting cylinder */
+ u_int8_t dp_typ; /* partition type (see below) */
+ u_int8_t dp_ehd; /* end head */
+ u_int8_t dp_esect; /* end sector */
+ u_int8_t dp_ecyl; /* end cylinder */
+ u_int32_t dp_start; /* absolute starting sector number */
+ u_int32_t dp_size; /* partition size in sectors */
+};
+
+/* Known DOS partition types. */
+#define DOSPTYP_UNUSED 0x00 /* Unused partition */
+#define DOSPTYP_FAT12 0x01 /* 12-bit FAT */
+#define DOSPTYP_FAT16S 0x04 /* 16-bit FAT, less than 32M */
+#define DOSPTYP_EXTEND 0x05 /* Extended; contains sub-partitions */
+#define DOSPTYP_FAT16B 0x06 /* 16-bit FAT, more than 32M */
+#define DOSPTYP_FAT32 0x0b /* 32-bit FAT */
+#define DOSPTYP_FAT32L 0x0c /* 32-bit FAT, LBA-mapped */
+#define DOSPTYP_FAT16L 0x0e /* 16-bit FAT, LBA-mapped */
+#define DOSPTYP_EXTENDL 0x0f /* Extended, LBA-mapped; contains sub-partitions */
+#define DOSPTYP_ONTRACK 0x54
+#define DOSPTYP_LINUX 0x83 /* That other thing */
+#define DOSPTYP_FREEBSD 0xa5 /* FreeBSD partition type */
+#define DOSPTYP_OPENBSD 0xa6 /* OpenBSD partition type */
+#define DOSPTYP_NETBSD 0xa9 /* NetBSD partition type */
+
+struct dos_mbr {
+ u_int8_t dmbr_boot[DOSPARTOFF];
+ struct dos_partition dmbr_parts[NDOSPART];
+ u_int16_t dmbr_sign;
+} __attribute__((__packed__));
+
+#define DOSMBR_SIGNATURE (0xaa55)
+#define DOSMBR_SIGNATURE_OFF (0x1fe)
+
+#include <sys/dkbad.h>
+struct cpu_disklabel {
+ struct dos_partition dosparts[NDOSPART];
+ struct dkbad bad;
+};
+
+#define DKBAD(x) ((x)->bad)
+
+/* Isolate the relevant bits to get sector and cylinder. */
+#define DPSECT(s) ((s) & 0x3f)
+#define DPCYL(c, s) ((c) + (((s) & 0xc0) << 2))
+
+static __inline u_int32_t get_le(void *);
+
+static __inline u_int32_t
+#ifdef __cplusplus
+get_le(void *p)
+#else
+get_le(p)
+ void *p;
+#endif
+{
+ u_int8_t *_p = (u_int8_t *)p;
+ u_int32_t x;
+ x = _p[0];
+ x |= _p[1] << 8;
+ x |= _p[2] << 16;
+ x |= _p[3] << 24;
+ return x;
+}
+
+#endif /* _MACHINE_DISKLABEL_H_ */
diff --git a/sys/arch/amd64/include/endian.h b/sys/arch/amd64/include/endian.h
new file mode 100644
index 00000000000..a8ee99504de
--- /dev/null
+++ b/sys/arch/amd64/include/endian.h
@@ -0,0 +1,67 @@
+/* $OpenBSD: endian.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+
+/*-
+ * Copyright (c) 1997 Niklas Hallqvist. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Niklas Hallqvist.
+ * 4. 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.
+ */
+
+#ifndef _I386_ENDIAN_H_
+#define _I386_ENDIAN_H_
+
+#ifdef __GNUC__
+
+#define __swap32md(x) ({ \
+ u_int32_t __swap32md_x = (x); \
+ \
+ __asm ("bswap %1" : "+r" (__swap32md_x)); \
+ __swap32md_x; \
+})
+
+/* XXX - I'm sure there is a better way on this cpu. */
+#define __swap64md(x) ({ \
+ u_int64_t __swap64md_x = (x); \
+ \
+ (u_int64_t)__swap32md(__swap64md_x >> 32) | \
+ (u_int64_t)__swap32md(__swap64md_x & 0xffffffff) << 32; \
+})
+
+#define __swap16md(x) ({ \
+ u_int16_t __swap16md_x = (x); \
+ \
+ __asm ("rorw $8, %w1" : "+r" (__swap16md_x)); \
+ __swap16md_x; \
+})
+
+/* Tell sys/endian.h we have MD variants of the swap macros. */
+#define MD_SWAP
+
+#endif /* __GNUC__ */
+
+#define BYTE_ORDER LITTLE_ENDIAN
+#include <sys/endian.h>
+
+#endif /* _I386_ENDIAN_H_ */
diff --git a/sys/arch/amd64/include/exec.h b/sys/arch/amd64/include/exec.h
new file mode 100644
index 00000000000..45290aafa7d
--- /dev/null
+++ b/sys/arch/amd64/include/exec.h
@@ -0,0 +1,22 @@
+/* $OpenBSD: exec.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/*
+ * Written by Artur Grabowski <art@openbsd.org> Public Domain
+ */
+
+#ifndef _AMD64_EXEC_H_
+#define _AMD64_EXEC_H_
+
+#define __LDPGSZ 4096
+
+#define NATIVE_EXEC_ELF
+
+#define ARCH_ELFSIZE 64
+
+#define ELF_TARG_CLASS ELFCLASS64
+#define ELF_TARG_DATA ELFDATA2LSB
+#define ELF_TARG_MACH EM_X86_64
+
+#define _NLIST_DO_ELF
+#define _KERN_DO_ELF64
+
+#endif
diff --git a/sys/arch/amd64/include/float.h b/sys/arch/amd64/include/float.h
new file mode 100644
index 00000000000..7c315a0e10d
--- /dev/null
+++ b/sys/arch/amd64/include/float.h
@@ -0,0 +1,77 @@
+/* $OpenBSD: float.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: float.h,v 1.8 1995/06/20 20:45:37 jtc Exp $ */
+
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. 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.
+ *
+ * @(#)float.h 7.1 (Berkeley) 5/8/90
+ */
+
+#ifndef _I386_FLOAT_H_
+#define _I386_FLOAT_H_
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+int __flt_rounds(void);
+__END_DECLS
+
+#define FLT_RADIX 2 /* b */
+#define FLT_ROUNDS __flt_rounds()
+
+#define FLT_MANT_DIG 24 /* p */
+#define FLT_EPSILON 1.19209290E-07F /* b**(1-p) */
+#define FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */
+#define FLT_MIN_EXP (-125) /* emin */
+#define FLT_MIN 1.17549435E-38F /* b**(emin-1) */
+#define FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */
+#define FLT_MAX_EXP 128 /* emax */
+#define FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */
+#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */
+
+#define DBL_MANT_DIG 53
+#define DBL_EPSILON 2.2204460492503131E-16
+#define DBL_DIG 15
+#define DBL_MIN_EXP (-1021)
+#define DBL_MIN 2.2250738585072014E-308
+#define DBL_MIN_10_EXP (-307)
+#define DBL_MAX_EXP 1024
+#define DBL_MAX 1.7976931348623157E+308
+#define DBL_MAX_10_EXP 308
+
+#define LDBL_MANT_DIG DBL_MANT_DIG
+#define LDBL_EPSILON DBL_EPSILON
+#define LDBL_DIG DBL_DIG
+#define LDBL_MIN_EXP DBL_MIN_EXP
+#define LDBL_MIN DBL_MIN
+#define LDBL_MIN_10_EXP DBL_MIN_10_EXP
+#define LDBL_MAX_EXP DBL_MAX_EXP
+#define LDBL_MAX DBL_MAX
+#define LDBL_MAX_10_EXP DBL_MAX_10_EXP
+
+#endif /* _I386_FLOAT_H_ */
diff --git a/sys/arch/amd64/include/fpu.h b/sys/arch/amd64/include/fpu.h
new file mode 100644
index 00000000000..a7952df5d54
--- /dev/null
+++ b/sys/arch/amd64/include/fpu.h
@@ -0,0 +1,84 @@
+/* $OpenBSD: fpu.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: fpu.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */
+
+#ifndef _AMD64_FPU_H_
+#define _AMD64_FPU_H_
+
+#include <sys/types.h>
+
+/*
+ * NetBSD/amd64 only uses the extended save/restore format used
+ * by fxsave/fsrestore, to always deal with the SSE registers,
+ * which are part of the ABI to pass floating point values.
+ * Must be stored in memory on a 16-byte boundary.
+ */
+
+struct fxsave64 {
+ u_int16_t fx_fcw;
+ u_int16_t fx_fsw;
+ u_int8_t fx_ftw;
+ u_int8_t fx_unused1;
+ u_int16_t fx_fop;
+ u_int64_t fx_rip;
+ u_int64_t fx_rdp;
+ u_int32_t fx_mxcsr;
+ u_int32_t fx_mxcsr_mask;
+ u_int64_t fx_st[8][2]; /* 8 normal FP regs */
+ u_int64_t fx_xmm[16][2]; /* 16 SSE2 registers */
+ u_int8_t fx_unused3[96];
+} __attribute__((packed));
+
+struct savefpu {
+ struct fxsave64 fp_fxsave; /* see above */
+ u_int16_t fp_ex_sw; /* saved status from last exception */
+ u_int16_t fp_ex_tw; /* saved tag from last exception */
+};
+
+/*
+ * The i387 defaults to Intel extended precision mode and round to nearest,
+ * with all exceptions masked.
+ */
+#define __INITIAL_NPXCW__ 0x037f
+#define __INITIAL_MXCSR__ 0x1f80
+#define __INITIAL_MXCSR_MASK__ 0xffbf
+
+/* NetBSD uses IEEE double precision. */
+#define __NetBSD_NPXCW__ 0x127f
+/* Linux just uses the default control word. */
+#define __Linux_NPXCW__ 0x037f
+
+/*
+ * The standard control word from finit is 0x37F, giving:
+ * round to nearest
+ * 64-bit precision
+ * all exceptions masked.
+ *
+ * Now we want:
+ * affine mode (if we decide to support 287's)
+ * round to nearest
+ * 53-bit precision
+ * all exceptions masked.
+ *
+ * 64-bit precision often gives bad results with high level languages
+ * because it makes the results of calculations depend on whether
+ * intermediate values are stored in memory or in FPU registers.
+ */
+
+#ifdef _KERNEL
+/*
+ * XXX
+ */
+struct trapframe;
+struct cpu_info;
+
+void fpuinit(struct cpu_info *);
+void fpudrop(void);
+void fpusave(struct proc *);
+void fpudiscard(struct proc *);
+void fputrap(struct trapframe *);
+void fpusave_proc(struct proc *, int);
+void fpusave_cpu(struct cpu_info *, int);
+
+#endif
+
+#endif /* _AMD64_FPU_H_ */
diff --git a/sys/arch/amd64/include/frame.h b/sys/arch/amd64/include/frame.h
new file mode 100644
index 00000000000..d0fb538ceeb
--- /dev/null
+++ b/sys/arch/amd64/include/frame.h
@@ -0,0 +1,175 @@
+/* $OpenBSD: frame.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: frame.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 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.
+ *
+ * @(#)frame.h 5.2 (Berkeley) 1/18/91
+ */
+
+/*
+ * Adapted for NetBSD/amd64 by fvdl@wasabisystems.com
+ */
+
+#ifndef _AMD64_FRAME_H_
+#define _AMD64_FRAME_H_
+
+#include <sys/signal.h>
+#include <machine/fpu.h>
+
+/*
+ * System stack frames.
+ */
+
+/*
+ * Exception/Trap Stack Frame
+ */
+struct trapframe {
+ int64_t tf_rdi;
+ int64_t tf_rsi;
+ int64_t tf_rdx;
+ int64_t tf_rcx;
+ int64_t tf_r8;
+ int64_t tf_r9;
+ int64_t tf_r10;
+ int64_t tf_r11;
+ int64_t tf_r12;
+ int64_t tf_r13;
+ int64_t tf_r14;
+ int64_t tf_r15;
+ int64_t tf_rbp;
+ int64_t tf_rbx;
+ int64_t tf_rax;
+ int64_t tf_gs;
+ int64_t tf_fs;
+ int64_t tf_es;
+ int64_t tf_ds;
+ int64_t tf_trapno;
+ /* below portion defined in hardware */
+ int64_t tf_err;
+ int64_t tf_rip;
+ int64_t tf_cs;
+ int64_t tf_rflags;
+ /* These are pushed unconditionally on the x86-64 */
+ int64_t tf_rsp;
+ int64_t tf_ss;
+};
+
+/*
+ * Interrupt stack frame
+ */
+struct intrframe {
+ int64_t if_ppl;
+ int64_t if_rdi;
+ int64_t if_rsi;
+ int64_t if_rdx;
+ int64_t if_rcx;
+ int64_t if_r8;
+ int64_t if_r9;
+ int64_t if_r10;
+ int64_t if_r11;
+ int64_t if_r12;
+ int64_t if_r13;
+ int64_t if_r14;
+ int64_t if_r15;
+ int64_t if_rbp;
+ int64_t if_rbx;
+ int64_t if_rax;
+ int64_t tf_gs;
+ int64_t tf_fs;
+ int64_t tf_es;
+ int64_t tf_ds;
+ u_int64_t __if_trapno; /* for compat with trap frame - trapno */
+ u_int64_t __if_err; /* for compat with trap frame - err */
+ /* below portion defined in hardware */
+ int64_t if_rip;
+ int64_t if_cs;
+ int64_t if_rflags;
+ /* These are pushed unconditionally on the x86-64 */
+ int64_t if_rsp;
+ int64_t if_ss;
+};
+
+/*
+ * Stack frame inside cpu_switch()
+ */
+struct switchframe {
+ int64_t sf_ppl;
+ int64_t sf_r15;
+ int64_t sf_r14;
+ int64_t sf_r13;
+ int64_t sf_r12;
+ int64_t sf_rbp;
+ int64_t sf_rbx;
+ int64_t sf_rip;
+};
+
+#endif /* _AMD64_FRAME_H_ */
diff --git a/sys/arch/amd64/include/frameasm.h b/sys/arch/amd64/include/frameasm.h
new file mode 100644
index 00000000000..c23b0e65a4d
--- /dev/null
+++ b/sys/arch/amd64/include/frameasm.h
@@ -0,0 +1,94 @@
+/* $OpenBSD: frameasm.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: frameasm.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */
+
+#ifndef _AMD64_MACHINE_FRAMEASM_H
+#define _AMD64_MACHINE_FRAMEASM_H
+
+/*
+ * Macros to define pushing/popping frames for interrupts, traps
+ * and system calls. Currently all the same; will diverge later.
+ */
+
+/*
+ * These are used on interrupt or trap entry or exit.
+ */
+#define INTR_SAVE_GPRS \
+ subq $120,%rsp ; \
+ movq %r15,TF_R15(%rsp) ; \
+ movq %r14,TF_R14(%rsp) ; \
+ movq %r13,TF_R13(%rsp) ; \
+ movq %r12,TF_R12(%rsp) ; \
+ movq %r11,TF_R11(%rsp) ; \
+ movq %r10,TF_R10(%rsp) ; \
+ movq %r9,TF_R9(%rsp) ; \
+ movq %r8,TF_R8(%rsp) ; \
+ movq %rdi,TF_RDI(%rsp) ; \
+ movq %rsi,TF_RSI(%rsp) ; \
+ movq %rbp,TF_RBP(%rsp) ; \
+ movq %rbx,TF_RBX(%rsp) ; \
+ movq %rdx,TF_RDX(%rsp) ; \
+ movq %rcx,TF_RCX(%rsp) ; \
+ movq %rax,TF_RAX(%rsp)
+
+#define INTR_RESTORE_GPRS \
+ movq TF_R15(%rsp),%r15 ; \
+ movq TF_R14(%rsp),%r14 ; \
+ movq TF_R13(%rsp),%r13 ; \
+ movq TF_R12(%rsp),%r12 ; \
+ movq TF_R11(%rsp),%r11 ; \
+ movq TF_R10(%rsp),%r10 ; \
+ movq TF_R9(%rsp),%r9 ; \
+ movq TF_R8(%rsp),%r8 ; \
+ movq TF_RDI(%rsp),%rdi ; \
+ movq TF_RSI(%rsp),%rsi ; \
+ movq TF_RBP(%rsp),%rbp ; \
+ movq TF_RBX(%rsp),%rbx ; \
+ movq TF_RDX(%rsp),%rdx ; \
+ movq TF_RCX(%rsp),%rcx ; \
+ movq TF_RAX(%rsp),%rax ; \
+ addq $120,%rsp
+
+#define INTRENTRY \
+ subq $32,%rsp ; \
+ testq $SEL_UPL,56(%rsp) ; \
+ je 98f ; \
+ swapgs ; \
+ movw %gs,0(%rsp) ; \
+ movw %fs,8(%rsp) ; \
+ movw %es,16(%rsp) ; \
+ movw %ds,24(%rsp) ; \
+98: INTR_SAVE_GPRS
+
+#define INTRFASTEXIT \
+ INTR_RESTORE_GPRS ; \
+ testq $SEL_UPL,56(%rsp) ; \
+ je 99f ; \
+ cli ; \
+ swapgs ; \
+ movw 0(%rsp),%gs ; \
+ movw 8(%rsp),%fs ; \
+ movw 16(%rsp),%es ; \
+ movw 24(%rsp),%ds ; \
+99: addq $48,%rsp ; \
+ iretq
+
+#define INTR_RECURSE_HWFRAME \
+ movq %rsp,%r10 ; \
+ movl %ss,%r11d ; \
+ pushq %r11 ; \
+ pushq %r10 ; \
+ pushfq ; \
+ movl %cs,%r11d ; \
+ pushq %r11 ; \
+ pushq %r13 ;
+
+
+#define CHECK_ASTPENDING(reg) movq CPUVAR(CURPROC),reg ; \
+ cmpq $0, reg ; \
+ je 99f ; \
+ cmpl $0, P_MD_ASTPENDING(reg) ; \
+ 99:
+
+#define CLEAR_ASTPENDING(reg) movl $0, P_MD_ASTPENDING(reg)
+
+#endif /* _AMD64_MACHINE_FRAMEASM_H */
diff --git a/sys/arch/amd64/include/gdt.h b/sys/arch/amd64/include/gdt.h
new file mode 100644
index 00000000000..a26608a78e8
--- /dev/null
+++ b/sys/arch/amd64/include/gdt.h
@@ -0,0 +1,62 @@
+/* $OpenBSD: gdt.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: gdt.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by John T. Kohl and Charles M. Hannum.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef _LOCORE
+struct proc;
+struct pmap;
+
+void gdt_init(void);
+void gdt_init_cpu(struct cpu_info *);
+void gdt_reload_cpu(struct cpu_info *);
+void gdt_alloc_cpu(struct cpu_info *);
+
+int tss_alloc(struct pcb *);
+void tss_free(int);
+
+void ldt_alloc(struct pmap *, char *, size_t);
+void ldt_free(struct pmap *);
+
+void set_mem_gdt(struct mem_segment_descriptor *, void *, size_t,
+ int, int, int, int, int);
+void set_sys_gdt(struct sys_segment_descriptor *, void *, size_t, int, int,
+ int);
+#endif
+
+#define MINGDTSIZ 2048
+#define MAXGDTSIZ 65536
diff --git a/sys/arch/amd64/include/i82093reg.h b/sys/arch/amd64/include/i82093reg.h
new file mode 100644
index 00000000000..91dc73bb1df
--- /dev/null
+++ b/sys/arch/amd64/include/i82093reg.h
@@ -0,0 +1,121 @@
+/* $OpenBSD: i82093reg.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: i82093reg.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by RedBack Networks Inc.
+ *
+ * Author: Bill Sommerfeld
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * Typically, the first apic lives here.
+ */
+#define IOAPIC_BASE_DEFAULT 0xfec00000
+
+/*
+ * Memory-space registers.
+ */
+
+/*
+ * The externally visible registers are all 32 bits wide;
+ * store the register number of interest in IOAPIC_REG, and store/fetch
+ * the real value in IOAPIC_DATA.
+ */
+
+
+
+#define IOAPIC_REG 0x0000
+#define IOAPIC_DATA 0x0010
+
+/*
+ * Internal I/O APIC registers.
+ */
+
+#define IOAPIC_ID 0x00
+
+#define IOAPIC_ID_SHIFT 24
+#define IOAPIC_ID_MASK 0x0f000000
+
+/* Version, and maximum interrupt pin number. */
+
+#define IOAPIC_VER 0x01
+
+#define IOAPIC_VER_SHIFT 0
+#define IOAPIC_VER_MASK 0x000000ff
+
+#define IOAPIC_MAX_SHIFT 16
+#define IOAPIC_MAX_MASK 0x00ff0000
+
+/*
+ * Arbitration ID. Same format as IOAPIC_ID register.
+ */
+#define IOAPIC_ARB 0x02
+
+/*
+ * Redirection table registers.
+ */
+
+#define IOAPIC_REDHI(pin) (0x11 + ((pin)<<1))
+#define IOAPIC_REDLO(pin) (0x10 + ((pin)<<1))
+
+#define IOAPIC_REDHI_DEST_SHIFT 24 /* destination. */
+#define IOAPIC_REDHI_DEST_MASK 0xff000000
+
+#define IOAPIC_REDLO_MASK 0x00010000 /* 0=enabled; 1=masked */
+
+#define IOAPIC_REDLO_LEVEL 0x00008000 /* 0=edge, 1=level */
+#define IOAPIC_REDLO_RIRR 0x00004000 /* remote IRR; read only */
+#define IOAPIC_REDLO_ACTLO 0x00002000 /* 0=act. hi; 1=act. lo */
+#define IOAPIC_REDLO_DELSTS 0x00001000 /* 0=idle; 1=send pending */
+#define IOAPIC_REDLO_DSTMOD 0x00000800 /* 0=physical; 1=logical */
+
+#define IOAPIC_REDLO_DEL_MASK 0x00000700 /* del. mode mask */
+#define IOAPIC_REDLO_DEL_SHIFT 8
+
+#define IOAPIC_REDLO_DEL_FIXED 0
+#define IOAPIC_REDLO_DEL_LOPRI 1
+#define IOAPIC_REDLO_DEL_SMI 2
+#define IOAPIC_REDLO_DEL_NMI 4
+#define IOAPIC_REDLO_DEL_INIT 5
+#define IOAPIC_REDLO_DEL_EXTINT 7
+
+#define IOAPIC_REDLO_VECTOR_MASK 0x000000ff /* delivery vector */
+
+#define IMCR_ADDR 0x22
+#define IMCR_DATA 0x23
+
+#define IMCR_REGISTER 0x70
+#define IMCR_PIC 0x00
+#define IMCR_APIC 0x01
diff --git a/sys/arch/amd64/include/i82093var.h b/sys/arch/amd64/include/i82093var.h
new file mode 100644
index 00000000000..78f1358bb63
--- /dev/null
+++ b/sys/arch/amd64/include/i82093var.h
@@ -0,0 +1,104 @@
+/* $OpenBSD: i82093var.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: i82093var.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by RedBack Networks Inc.
+ *
+ * Author: Bill Sommerfeld
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef _X86_I82093VAR_H_
+#define _X86_I82093VAR_H_
+
+#include <machine/apicvar.h>
+
+struct ioapic_pin
+{
+ struct ioapic_pin *ip_next; /* next pin on this vector */
+ struct mp_intr_map *ip_map;
+ int ip_vector; /* IDT vector */
+ int ip_type;
+ struct cpu_info *ip_cpu; /* target CPU */
+};
+
+struct ioapic_softc {
+ struct pic sc_pic;
+ struct ioapic_softc *sc_next;
+ int sc_apicid;
+ int sc_apic_vers;
+ int sc_apic_vecbase; /* global int base if ACPI */
+ int sc_apic_sz; /* apic size*/
+ int sc_flags;
+ paddr_t sc_pa; /* PA of ioapic */
+ volatile u_int32_t *sc_reg; /* KVA of ioapic addr */
+ volatile u_int32_t *sc_data; /* KVA of ioapic data */
+ struct ioapic_pin *sc_pins; /* sc_apic_sz entries */
+};
+
+/*
+ * MP: intr_handle_t is bitfielded.
+ * ih&0xff -> legacy irq number.
+ * ih&0x10000000 -> if 0, old-style isa irq; if 1, routed via ioapic.
+ * (ih&0xff0000)>>16 -> ioapic id.
+ * (ih&0x00ff00)>>8 -> ioapic pin.
+ */
+
+#define APIC_INT_VIA_APIC 0x10000000
+#define APIC_INT_APIC_MASK 0x00ff0000
+#define APIC_INT_APIC_SHIFT 16
+#define APIC_INT_PIN_MASK 0x0000ff00
+#define APIC_INT_PIN_SHIFT 8
+
+#define APIC_IRQ_APIC(x) ((x & APIC_INT_APIC_MASK) >> APIC_INT_APIC_SHIFT)
+#define APIC_IRQ_PIN(x) ((x & APIC_INT_PIN_MASK) >> APIC_INT_PIN_SHIFT)
+#define APIC_IRQ_ISLEGACY(x) (!((x) & APIC_INT_VIA_APIC))
+#define APIC_IRQ_LEGACY_IRQ(x) ((x) & 0xff)
+
+void *apic_intr_establish(int, int, int, int (*)(void *), void *);
+void apic_intr_disestablish(void *);
+
+void ioapic_print_redir(struct ioapic_softc *, char *, int);
+void ioapic_format_redir(char *, char *, int, u_int32_t, u_int32_t);
+struct ioapic_softc *ioapic_find(int);
+struct ioapic_softc *ioapic_find_bybase(int);
+
+void ioapic_enable(void);
+void lapic_vectorset(void); /* XXX */
+
+extern int ioapic_bsp_id;
+extern int nioapics;
+extern struct ioapic_softc *ioapics;
+
+#endif /* !_X86_I82093VAR_H_ */
diff --git a/sys/arch/amd64/include/i82489reg.h b/sys/arch/amd64/include/i82489reg.h
new file mode 100644
index 00000000000..fb1bb6217b4
--- /dev/null
+++ b/sys/arch/amd64/include/i82489reg.h
@@ -0,0 +1,150 @@
+/* $OpenBSD: i82489reg.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: i82489reg.h,v 1.1 2003/02/26 21:26:10 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Frank van der Linden.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+
+/*
+ * Registers and constants for the 82489DX and Pentium (and up) integrated
+ * "local" APIC.
+ */
+
+#define LAPIC_ID 0x020 /* ID. RW */
+# define LAPIC_ID_MASK 0x0f000000
+# define LAPIC_ID_SHIFT 24
+
+#define LAPIC_VERS 0x030 /* Version. R */
+# define LAPIC_VERSION_MASK 0x000000ff
+# define LAPIC_VERSION_LVT_MASK 0x00ff0000
+# define LAPIC_VERSION_LVT_SHIFT 16
+
+#define LAPIC_TPRI 0x080 /* Task Prio. RW */
+# define LAPIC_TPRI_MASK 0x000000ff
+# define LAPIC_TPRI_INT_MASK 0x000000f0
+# define LAPIC_TPRI_SUB_MASK 0x0000000f
+
+#define LAPIC_APRI 0x090 /* Arbitration prio R */
+# define LAPIC_APRI_MASK 0x000000ff
+
+#define LAPIC_PPRI 0x0a0 /* Processor prio. R */
+#define LAPIC_EOI 0x0b0 /* End Int. W */
+#define LAPIC_RRR 0x0c0 /* Remote read R */
+#define LAPIC_LDR 0x0d0 /* Logical dest. RW */
+#define LAPIC_DFR 0x0e0 /* Dest. format RW */
+
+#define LAPIC_SVR 0x0f0 /* Spurious intvec RW */
+# define LAPIC_SVR_VECTOR_MASK 0x000000ff
+# define LAPIC_SVR_VEC_FIX 0x0000000f
+# define LAPIC_SVR_VEC_PROG 0x000000f0
+# define LAPIC_SVR_ENABLE 0x00000100
+# define LAPIC_SVR_SWEN 0x00000100
+# define LAPIC_SVR_FOCUS 0x00000200
+# define LAPIC_SVR_FDIS 0x00000200
+
+#define LAPIC_ISR 0x100 /* Int. status. R */
+#define LAPIC_TMR 0x180
+#define LAPIC_IRR 0x200
+#define LAPIC_ESR 0x280 /* Err status. R */
+
+#define LAPIC_ICRLO 0x300 /* Int. cmd. RW */
+# define LAPIC_DLMODE_MASK 0x00000700
+# define LAPIC_DLMODE_FIXED 0x00000000
+# define LAPIC_DLMODE_LOW 0x00000100
+# define LAPIC_DLMODE_SMI 0x00000200
+# define LAPIC_DLMODE_RR 0x00000300
+# define LAPIC_DLMODE_NMI 0x00000400
+# define LAPIC_DLMODE_INIT 0x00000500
+# define LAPIC_DLMODE_STARTUP 0x00000600
+
+# define LAPIC_DSTMODE_LOG 0x00000800
+
+# define LAPIC_DLSTAT_BUSY 0x00001000
+
+# define LAPIC_LVL_ASSERT 0x00004000
+# define LAPIC_LVL_DEASSERT 0x00000000
+
+# define LAPIC_LVL_TRIG 0x00008000
+
+# define LAPIC_RRSTAT_MASK 0x00030000
+# define LAPIC_RRSTAT_INPROG 0x00010000
+# define LAPIC_RRSTAT_VALID 0x00020000
+
+# define LAPIC_DEST_MASK 0x000c0000
+# define LAPIC_DEST_SELF 0x00040000
+# define LAPIC_DEST_ALLINCL 0x00080000
+# define LAPIC_DEST_ALLEXCL 0x000c0000
+
+# define LAPIC_RESV2_MASK 0xfff00000
+
+
+#define LAPIC_ICRHI 0x310 /* Int. cmd. RW */
+# define LAPIC_ID_MASK 0x0f000000
+# define LAPIC_ID_SHIFT 24
+
+#define LAPIC_LVTT 0x320 /* Loc.vec.(timer) RW */
+# define LAPIC_LVTT_VEC_MASK 0x000000ff
+# define LAPIC_LVTT_DS 0x00001000
+# define LAPIC_LVTT_M 0x00010000
+# define LAPIC_LVTT_TM 0x00020000
+
+#define LAPIC_PCINT 0x340
+#define LAPIC_LVINT0 0x350 /* Loc.vec (LINT0) RW */
+# define LAPIC_LVT_PERIODIC 0x00020000
+# define LAPIC_LVT_MASKED 0x00010000
+# define LAPIC_LVT_LEVTRIG 0x00008000
+# define LAPIC_LVT_REMOTE_IRR 0x00004000
+# define LAPIC_INP_POL 0x00002000
+# define LAPIC_PEND_SEND 0x00001000
+
+#define LAPIC_LVINT1 0x360 /* Loc.vec (LINT1) RW */
+#define LAPIC_LVERR 0x370 /* Loc.vec (ERROR) RW */
+#define LAPIC_ICR_TIMER 0x380 /* Initial count RW */
+#define LAPIC_CCR_TIMER 0x390 /* Current count RO */
+
+#define LAPIC_DCR_TIMER 0x3e0 /* Divisor config register */
+# define LAPIC_DCRT_DIV1 0x0b
+# define LAPIC_DCRT_DIV2 0x00
+# define LAPIC_DCRT_DIV4 0x01
+# define LAPIC_DCRT_DIV8 0x02
+# define LAPIC_DCRT_DIV16 0x03
+# define LAPIC_DCRT_DIV32 0x08
+# define LAPIC_DCRT_DIV64 0x09
+# define LAPIC_DCRT_DIV128 0x0a
+
+#define LAPIC_BASE 0xfee00000
+
+#define LAPIC_IRQ_MASK(i) (1 << ((i) + 1))
diff --git a/sys/arch/amd64/include/i8259.h b/sys/arch/amd64/include/i8259.h
new file mode 100644
index 00000000000..e89f77f4164
--- /dev/null
+++ b/sys/arch/amd64/include/i8259.h
@@ -0,0 +1,152 @@
+/* $OpenBSD: i8259.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: i8259.h,v 1.3 2003/05/04 22:01:56 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)icu.h 5.6 (Berkeley) 5/9/91
+ */
+
+#ifndef _X86_I8259_H_
+#define _X86_I8259_H_
+
+#include <dev/isa/isareg.h>
+
+#ifndef _LOCORE
+
+/*
+ * Interrupt "level" mechanism variables, masks, and macros
+ */
+extern unsigned i8259_imen; /* interrupt mask enable */
+extern unsigned i8259_setmask(unsigned);
+
+#define SET_ICUS() (outb(IO_ICU1 + 1, imen), outb(IO_ICU2 + 1, imen >> 8))
+
+extern void i8259_default_setup(void);
+extern void i8259_reinit(void);
+
+#endif /* !_LOCORE */
+
+/*
+ * Interrupt enable bits -- in order of priority
+ */
+#define IRQ_SLAVE 2
+
+/*
+ * Interrupt Control offset into Interrupt descriptor table (IDT)
+ */
+#define ICU_OFFSET 32 /* 0-31 are processor exceptions */
+#define ICU_LEN 16 /* 32-47 are ISA interrupts */
+
+
+#define ICU_HARDWARE_MASK
+
+/*
+ * These macros are fairly self explanatory. If ICU_SPECIAL_MASK_MODE is
+ * defined, we try to take advantage of the ICU's `special mask mode' by only
+ * EOIing the interrupts on return. This avoids the requirement of masking and
+ * unmasking. We can't do this without special mask mode, because the ICU
+ * would also hold interrupts that it thinks are of lower priority.
+ *
+ * Many machines do not support special mask mode, so by default we don't try
+ * to use it.
+ */
+
+#define IRQ_BIT(num) (1 << ((num) % 8))
+#define IRQ_BYTE(num) ((num) >> 3)
+
+#define i8259_late_ack(num)
+
+#ifdef ICU_SPECIAL_MASK_MODE
+
+#define i8259_asm_ack1(num)
+#define i8259_asm_ack2(num) \
+ movb $(0x60|IRQ_SLAVE),%al /* specific EOI for IRQ2 */ ;\
+ outb %al,$IO_ICU1
+#define i8259_asm_mask(num)
+#define i8259_asm_unmask(num) \
+ movb $(0x60|(num%8)),%al /* specific EOI */ ;\
+ outb %al,$ICUADDR
+
+#else /* ICU_SPECIAL_MASK_MODE */
+
+#ifndef AUTO_EOI_1
+#define i8259_asm_ack1(num) \
+ movb $(0x60|(num%8)),%al /* specific EOI */ ;\
+ outb %al,$IO_ICU1
+#else
+#define i8259_asm_ack1(num)
+#endif
+
+#ifndef AUTO_EOI_2
+#define i8259_asm_ack2(num) \
+ movb $(0x60|(num%8)),%al /* specific EOI */ ;\
+ outb %al,$IO_ICU2 /* do the second ICU first */ ;\
+ movb $(0x60|IRQ_SLAVE),%al /* specific EOI for IRQ2 */ ;\
+ outb %al,$IO_ICU1
+#else
+#define i8259_asm_ack2(num)
+#endif
+
+#ifdef PIC_MASKDELAY
+#define MASKDELAY pushl %eax ; inb $0x84,%al ; popl %eax
+#else
+#define MASKDELAY
+#endif
+
+#ifdef ICU_HARDWARE_MASK
+
+#define i8259_asm_mask(num) \
+ movb CVAROFF(i8259_imen, IRQ_BYTE(num)),%al ;\
+ orb $IRQ_BIT(num),%al ;\
+ movb %al,CVAROFF(i8259_imen, IRQ_BYTE(num)) ;\
+ MASKDELAY ;\
+ outb %al,$(ICUADDR+1)
+#define i8259_asm_unmask(num) \
+ movb CVAROFF(i8259_imen, IRQ_BYTE(num)),%al ;\
+ andb $~IRQ_BIT(num),%al ;\
+ movb %al,CVAROFF(i8259_imen, IRQ_BYTE(num)) ;\
+ MASKDELAY ;\
+ outb %al,$(ICUADDR+1)
+
+#else /* ICU_HARDWARE_MASK */
+
+#define i8259_asm_mask(num)
+#define i8259_asm_unmask(num)
+
+#endif /* ICU_HARDWARE_MASK */
+#endif /* ICU_SPECIAL_MASK_MODE */
+
+#endif /* !_X86_I8259_H_ */
diff --git a/sys/arch/amd64/include/ieee.h b/sys/arch/amd64/include/ieee.h
new file mode 100644
index 00000000000..5a34355d223
--- /dev/null
+++ b/sys/arch/amd64/include/ieee.h
@@ -0,0 +1,133 @@
+/* $OpenBSD: ieee.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: ieee.h,v 1.1 1996/09/30 16:34:25 ws Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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, Lawrence Berkeley Laboratory.
+ *
+ * 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 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.
+ *
+ * @(#)ieee.h 8.1 (Berkeley) 6/11/93
+ */
+
+/*
+ * ieee.h defines the machine-dependent layout of the machine's IEEE
+ * floating point. It does *not* define (yet?) any of the rounding
+ * mode bits, exceptions, and so forth.
+ */
+
+/*
+ * Define the number of bits in each fraction and exponent.
+ *
+ * k k+1
+ * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented
+ *
+ * (-exp_bias+1)
+ * as fractions that look like 0.fffff x 2 . This means that
+ *
+ * -126
+ * the number 0.10000 x 2 , for instance, is the same as the normalized
+ *
+ * -127 -128
+ * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero
+ *
+ * -129
+ * in the fraction; to represent 2 , we need two, and so on. This
+ *
+ * (-exp_bias-fracbits+1)
+ * implies that the smallest denormalized number is 2
+ *
+ * for whichever format we are talking about: for single precision, for
+ *
+ * -126 -149
+ * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and
+ *
+ * -149 == -127 - 23 + 1.
+ */
+#define SNG_EXPBITS 8
+#define SNG_FRACBITS 23
+
+#define DBL_EXPBITS 11
+#define DBL_FRACBITS 52
+
+#define EXT_EXPBITS 15
+#define EXT_FRACBITS 112
+
+struct ieee_single {
+ u_int sng_frac:23;
+ u_int sng_exp:8;
+ u_int sng_sign:1;
+};
+
+struct ieee_double {
+ u_int dbl_fracl;
+ u_int dbl_frach:20;
+ u_int dbl_exp:11;
+ u_int dbl_sign:1;
+};
+
+struct ieee_ext {
+ u_int ext_fracl;
+ u_int ext_fraclm;
+ u_int ext_frachm;
+ u_int ext_frach:16;
+ u_int ext_exp:15;
+ u_int ext_sign:1;
+};
+
+/*
+ * Floats whose exponent is in [1..INFNAN) (of whatever type) are
+ * `normal'. Floats whose exponent is INFNAN are either Inf or NaN.
+ * Floats whose exponent is zero are either zero (iff all fraction
+ * bits are zero) or subnormal values.
+ *
+ * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its
+ * high fraction; if the bit is set, it is a `quiet NaN'.
+ */
+#define SNG_EXP_INFNAN 255
+#define DBL_EXP_INFNAN 2047
+#define EXT_EXP_INFNAN 32767
+
+#if 0
+#define SNG_QUIETNAN (1 << 22)
+#define DBL_QUIETNAN (1 << 19)
+#define EXT_QUIETNAN (1 << 15)
+#endif
+
+/*
+ * Exponent biases.
+ */
+#define SNG_EXP_BIAS 127
+#define DBL_EXP_BIAS 1023
+#define EXT_EXP_BIAS 16383
diff --git a/sys/arch/amd64/include/ieeefp.h b/sys/arch/amd64/include/ieeefp.h
new file mode 100644
index 00000000000..774ee8d6adc
--- /dev/null
+++ b/sys/arch/amd64/include/ieeefp.h
@@ -0,0 +1,26 @@
+/* $OpenBSD: ieeefp.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+
+/*
+ * Written by J.T. Conklin, Apr 6, 1995
+ * Public domain.
+ */
+
+#ifndef _I386_IEEEFP_H_
+#define _I386_IEEEFP_H_
+
+typedef int fp_except;
+#define FP_X_INV 0x01 /* invalid operation exception */
+#define FP_X_DNML 0x02 /* denormalization exception */
+#define FP_X_DZ 0x04 /* divide-by-zero exception */
+#define FP_X_OFL 0x08 /* overflow exception */
+#define FP_X_UFL 0x10 /* underflow exception */
+#define FP_X_IMP 0x20 /* imprecise (loss of precision) */
+
+typedef enum {
+ FP_RN=0, /* round to nearest representable number */
+ FP_RM=1, /* round toward negative infinity */
+ FP_RP=2, /* round toward positive infinity */
+ FP_RZ=3 /* round to zero (truncate) */
+} fp_rnd;
+
+#endif /* _I386_IEEEFP_H_ */
diff --git a/sys/arch/amd64/include/internal_types.h b/sys/arch/amd64/include/internal_types.h
new file mode 100644
index 00000000000..8237a6b4cef
--- /dev/null
+++ b/sys/arch/amd64/include/internal_types.h
@@ -0,0 +1,10 @@
+/* $OpenBSD: internal_types.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* Public domain */
+#ifndef _MACHINE_INTERNAL_TYPES_H_
+#define _MACHINE_INTERNAL_TYPES_H_
+
+#ifdef __x86_64__
+#define __machine_is_64_bits
+#endif
+
+#endif
diff --git a/sys/arch/amd64/include/intr.h b/sys/arch/amd64/include/intr.h
new file mode 100644
index 00000000000..1b3390d7b17
--- /dev/null
+++ b/sys/arch/amd64/include/intr.h
@@ -0,0 +1,356 @@
+/* $OpenBSD: intr.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: intr.h,v 1.2 2003/05/04 22:01:56 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum, and by Jason R. Thorpe.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef _X86_INTR_H_
+#define _X86_INTR_H_
+
+#include <machine/intrdefs.h>
+
+#ifndef _LOCORE
+#include <machine/cpu.h>
+#include <machine/pic.h>
+
+/*
+ * Struct describing an interrupt source for a CPU. struct cpu_info
+ * has an array of MAX_INTR_SOURCES of these. The index in the array
+ * is equal to the stub number of the stubcode as present in vector.s
+ *
+ * The primary CPU's array of interrupt sources has its first 16
+ * entries reserved for legacy ISA irq handlers. This means that
+ * they have a 1:1 mapping for arrayindex:irq_num. This is not
+ * true for interrupts that come in through IO APICs, to find
+ * their source, go through ci->ci_isources[index].is_pic
+ *
+ * It's possible to always maintain a 1:1 mapping, but that means
+ * limiting the total number of interrupt sources to MAX_INTR_SOURCES
+ * (32), instead of 32 per CPU. It also would mean that having multiple
+ * IO APICs which deliver interrupts from an equal pin number would
+ * overlap if they were to be sent to the same CPU.
+ */
+
+struct intrstub {
+ void *ist_entry;
+ void *ist_recurse;
+ void *ist_resume;
+};
+
+struct intrsource {
+ int is_maxlevel; /* max. IPL for this source */
+ int is_pin; /* IRQ for legacy; pin for IO APIC */
+ struct intrhand *is_handlers; /* handler chain */
+ struct pic *is_pic; /* originating PIC */
+ void *is_recurse; /* entry for spllower */
+ void *is_resume; /* entry for doreti */
+ struct evcnt is_evcnt; /* interrupt counter */
+ char is_evname[32]; /* event counter name */
+ int is_flags; /* see below */
+ int is_type; /* level, edge */
+ int is_idtvec;
+ int is_minlevel;
+};
+
+#define IS_LEGACY 0x0001 /* legacy ISA irq source */
+#define IS_IPI 0x0002
+#define IS_LOG 0x0004
+
+
+/*
+ * Interrupt handler chains. *_intr_establish() insert a handler into
+ * the list. The handler is called with its (single) argument.
+ */
+
+struct intrhand {
+ int (*ih_fun)(void *);
+ void *ih_arg;
+ int ih_level;
+ struct intrhand *ih_next;
+ int ih_pin;
+ int ih_slot;
+ struct cpu_info *ih_cpu;
+ int ih_irq;
+ char *ih_what;
+};
+
+#define IMASK(ci,level) (ci)->ci_imask[(level)]
+#define IUNMASK(ci,level) (ci)->ci_iunmask[(level)]
+
+extern void Xspllower(int);
+
+static __inline int splraise(int);
+static __inline void spllower(int);
+static __inline void softintr(int);
+
+/*
+ * Convert spl level to local APIC level
+ */
+#define APIC_LEVEL(l) ((l) << 4)
+
+/*
+ * compiler barrier: prevent reordering of instructions.
+ * XXX something similar will move to <sys/cdefs.h>
+ * or thereabouts.
+ * This prevents the compiler from reordering code around
+ * this "instruction", acting as a sequence point for code generation.
+ */
+
+#define __splbarrier() __asm __volatile("":::"memory")
+
+/*
+ * Add a mask to cpl, and return the old value of cpl.
+ */
+static __inline int
+splraise(int nlevel)
+{
+ int olevel;
+ struct cpu_info *ci = curcpu();
+
+ olevel = ci->ci_ilevel;
+ if (nlevel > olevel)
+ ci->ci_ilevel = nlevel;
+ __splbarrier();
+ return (olevel);
+}
+
+/*
+ * Restore a value to cpl (unmasking interrupts). If any unmasked
+ * interrupts are pending, call Xspllower() to process them.
+ */
+static __inline void
+spllower(int nlevel)
+{
+ struct cpu_info *ci = curcpu();
+
+ __splbarrier();
+ /*
+ * Since this should only lower the interrupt level,
+ * the XOR below should only show interrupts that
+ * are being unmasked.
+ */
+ if (ci->ci_ipending & IUNMASK(ci,nlevel))
+ Xspllower(nlevel);
+ else
+ ci->ci_ilevel = nlevel;
+}
+
+/*
+ * Hardware interrupt masks
+ */
+#define splbio() splraise(IPL_BIO)
+#define splnet() splraise(IPL_NET)
+#define spltty() splraise(IPL_TTY)
+#define splaudio() splraise(IPL_AUDIO)
+#define splclock() splraise(IPL_CLOCK)
+#define splstatclock() splclock()
+#define splserial() splraise(IPL_SERIAL)
+#define splipi() splraise(IPL_IPI)
+
+#define spllpt() spltty()
+
+#define spllpt() spltty()
+
+/*
+ * Software interrupt masks
+ *
+ * NOTE: spllowersoftclock() is used by hardclock() to lower the priority from
+ * clock to softclock before it calls softclock().
+ */
+#define spllowersoftclock() spllower(IPL_SOFTCLOCK)
+
+#define splsoftclock() splraise(IPL_SOFTCLOCK)
+#define splsoftnet() splraise(IPL_SOFTNET)
+#define splsoftserial() splraise(IPL_SOFTSERIAL)
+
+/*
+ * Miscellaneous
+ */
+#define splimp() splraise(IPL_IMP)
+#define splvm() splraise(IPL_IMP)
+#define splhigh() splraise(IPL_HIGH)
+#define spl0() spllower(IPL_NONE)
+#define splsched() splraise(IPL_SCHED)
+#define spllock() splhigh()
+#define splx(x) spllower(x)
+
+/* SPL asserts */
+#ifdef DIAGNOSTIC
+/*
+ * Although this function is implemented in MI code, it must be in this MD
+ * header because we don't want this header to include MI includes.
+ */
+void splassert_fail(int, int, const char *);
+extern int splassert_ctl;
+void splassert_check(int, const char *);
+#define splassert(__wantipl) do { \
+ if (__predict_false(splassert_ctl > 0)) { \
+ splassert_check(__wantipl, __func__); \
+ } \
+} while (0)
+#else
+#define splassert(wantipl) do { /* nada */ } while (0)
+#endif
+
+/*
+ * Software interrupt registration
+ *
+ * We hand-code this to ensure that it's atomic.
+ *
+ * XXX always scheduled on the current CPU.
+ */
+static __inline void
+softintr(int sir)
+{
+ struct cpu_info *ci = curcpu();
+
+ __asm __volatile("lock ; orl %1, %0" :
+ "=m"(ci->ci_ipending) : "ir" (1 << sir));
+}
+
+/*
+ * XXX
+ */
+#define setsoftnet() softintr(SIR_NET)
+
+#define IPLSHIFT 4 /* The upper nibble of vectors is the IPL. */
+#define IPL(level) ((level) >> IPLSHIFT) /* Extract the IPL. */
+
+/*
+ * Stub declarations.
+ */
+
+extern void Xsoftclock(void);
+extern void Xsoftnet(void);
+extern void Xsoftserial(void);
+
+extern struct intrstub i8259_stubs[];
+extern struct intrstub ioapic_edge_stubs[];
+extern struct intrstub ioapic_level_stubs[];
+
+struct cpu_info;
+
+extern char idt_allocmap[];
+
+void intr_default_setup(void);
+int x86_nmi(void);
+void intr_calculatemasks(struct cpu_info *);
+int intr_allocate_slot_cpu(struct cpu_info *, struct pic *, int, int *);
+int intr_allocate_slot(struct pic *, int, int, int, struct cpu_info **, int *,
+ int *);
+void *intr_establish(int, struct pic *, int, int, int, int (*)(void *), void *);
+void intr_disestablish(struct intrhand *);
+void cpu_intr_init(struct cpu_info *);
+int intr_find_mpmapping(int bus, int pin, int *handle);
+void intr_printconfig(void);
+
+#ifdef MULTIPROCESSOR
+int x86_send_ipi(struct cpu_info *, int);
+void x86_broadcast_ipi(int);
+void x86_multicast_ipi(int, int);
+void x86_ipi_handler(void);
+void x86_intlock(struct intrframe);
+void x86_intunlock(struct intrframe);
+void x86_softintlock(void);
+void x86_softintunlock(void);
+
+extern void (*ipifunc[X86_NIPI])(struct cpu_info *);
+#endif
+
+#endif /* !_LOCORE */
+
+/*
+ * Generic software interrupt support.
+ */
+
+#define X86_SOFTINTR_SOFTCLOCK 0
+#define X86_SOFTINTR_SOFTNET 1
+#define X86_SOFTINTR_SOFTSERIAL 2
+#define X86_NSOFTINTR 3
+
+#ifndef _LOCORE
+#include <sys/queue.h>
+
+struct x86_soft_intrhand {
+ TAILQ_ENTRY(x86_soft_intrhand)
+ sih_q;
+ struct x86_soft_intr *sih_intrhead;
+ void (*sih_fn)(void *);
+ void *sih_arg;
+ int sih_pending;
+};
+
+struct x86_soft_intr {
+ TAILQ_HEAD(, x86_soft_intrhand)
+ softintr_q;
+ int softintr_ssir;
+ struct simplelock softintr_slock;
+};
+
+#define x86_softintr_lock(si, s) \
+do { \
+ (s) = splhigh(); \
+ simple_lock(&si->softintr_slock); \
+} while (/*CONSTCOND*/ 0)
+
+#define x86_softintr_unlock(si, s) \
+do { \
+ simple_unlock(&si->softintr_slock); \
+ splx((s)); \
+} while (/*CONSTCOND*/ 0)
+
+void *softintr_establish(int, void (*)(void *), void *);
+void softintr_disestablish(void *);
+void softintr_init(void);
+void softintr_dispatch(int);
+
+#define softintr_schedule(arg) \
+do { \
+ struct x86_soft_intrhand *__sih = (arg); \
+ struct x86_soft_intr *__si = __sih->sih_intrhead; \
+ int __s; \
+ \
+ x86_softintr_lock(__si, __s); \
+ if (__sih->sih_pending == 0) { \
+ TAILQ_INSERT_TAIL(&__si->softintr_q, __sih, sih_q); \
+ __sih->sih_pending = 1; \
+ softintr(__si->softintr_ssir); \
+ } \
+ x86_softintr_unlock(__si, __s); \
+} while (/*CONSTCOND*/ 0)
+#endif /* _LOCORE */
+
+#endif /* !_X86_INTR_H_ */
diff --git a/sys/arch/amd64/include/intrdefs.h b/sys/arch/amd64/include/intrdefs.h
new file mode 100644
index 00000000000..d1b46308c38
--- /dev/null
+++ b/sys/arch/amd64/include/intrdefs.h
@@ -0,0 +1,93 @@
+/* $OpenBSD: intrdefs.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: intrdefs.h,v 1.2 2003/05/04 22:01:56 fvdl Exp $ */
+
+#ifndef _i386_INTRDEFS_H
+#define _i386_INTRDEFS_H
+
+/*
+ * Interrupt priority levels.
+ *
+ * There are tty, network and disk drivers that use free() at interrupt
+ * time, so imp > (tty | net | bio).
+ *
+ * Since run queues may be manipulated by both the statclock and tty,
+ * network, and disk drivers, clock > imp.
+ *
+ * IPL_HIGH must block everything that can manipulate a run queue.
+ *
+ * We need serial drivers to run at the absolute highest priority to
+ * avoid overruns, so serial > high.
+ *
+ * The level numbers are picked to fit into APIC vector priorities.
+ *
+ */
+#define IPL_NONE 0x0 /* nothing */
+#define IPL_SOFTCLOCK 0x4 /* timeouts */
+#define IPL_SOFTNET 0x5 /* protocol stacks */
+#define IPL_BIO 0x6 /* block I/O */
+#define IPL_NET 0x7 /* network */
+#define IPL_SOFTSERIAL 0x8 /* serial */
+#define IPL_TTY 0x9 /* terminal */
+#define IPL_VM 0xa /* memory allocation */
+#define IPL_IMP IPL_VM
+#define IPL_AUDIO 0xb /* audio */
+#define IPL_CLOCK 0xc /* clock */
+#define IPL_SCHED IPL_CLOCK
+#define IPL_STATCLOCK IPL_CLOCK
+#define IPL_HIGH 0xd /* everything */
+#define IPL_SERIAL 0xd /* serial */
+#define IPL_IPI 0xe /* inter-processor interrupts */
+#define NIPL 16
+
+/* Interrupt sharing types. */
+#define IST_NONE 0 /* none */
+#define IST_PULSE 1 /* pulsed */
+#define IST_EDGE 2 /* edge-triggered */
+#define IST_LEVEL 3 /* level-triggered */
+
+/*
+ * Local APIC masks. Must not conflict with SIR_* above, and must
+ * be >= NUM_LEGACY_IRQs. Note that LIR_IPI must be first.
+ */
+#define LIR_IPI 31
+#define LIR_TIMER 30
+
+/* Soft interrupt masks. */
+#define SIR_CLOCK 29
+#define SIR_NET 28
+#define SIR_SERIAL 27
+
+
+/*
+ * Maximum # of interrupt sources per CPU. 32 to fit in one word.
+ * ioapics can theoretically produce more, but it's not likely to
+ * happen. For multiple ioapics, things can be routed to different
+ * CPUs.
+ */
+#define MAX_INTR_SOURCES 32
+#define NUM_LEGACY_IRQS 16
+
+/*
+ * Low and high boundaries between which interrupt gates will
+ * be allocated in the IDT.
+ */
+#define IDT_INTR_LOW (0x20 + NUM_LEGACY_IRQS)
+#define IDT_INTR_HIGH 0xef
+
+#define X86_IPI_HALT 0x00000001
+#define X86_IPI_MICROSET 0x00000002
+#define X86_IPI_FLUSH_FPU 0x00000004
+#define X86_IPI_SYNCH_FPU 0x00000008
+#define X86_IPI_TLB 0x00000010
+#define X86_IPI_MTRR 0x00000020
+#define X86_IPI_GDT 0x00000040
+
+#define X86_NIPI 7
+
+#define X86_IPI_NAMES { "halt IPI", "timeset IPI", "FPU flush IPI", \
+ "FPU synch IPI", "TLB shootdown IPI", \
+ "MTRR update IPI", "GDT update IPI" }
+
+#define IREENT_MAGIC 0x18041969
+
+#endif /* _X86_INTRDEFS_H */
diff --git a/sys/arch/amd64/include/isa_machdep.h b/sys/arch/amd64/include/isa_machdep.h
new file mode 100644
index 00000000000..306eed9ef8e
--- /dev/null
+++ b/sys/arch/amd64/include/isa_machdep.h
@@ -0,0 +1,237 @@
+/* $OpenBSD: isa_machdep.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: isa_machdep.h,v 1.2 2003/05/09 23:51:28 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 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.
+ *
+ * @(#)isa.h 5.7 (Berkeley) 5/9/91
+ */
+
+/*
+ * Various pieces of the i386 port want to include this file without
+ * or in spite of using isavar.h, and should be fixed.
+ */
+
+#ifndef _I386_ISA_MACHDEP_H_ /* XXX */
+#define _I386_ISA_MACHDEP_H_ /* XXX */
+
+#include <machine/bus.h>
+#include <dev/isa/isadmavar.h>
+
+/*
+ * XXX THIS FILE IS A MESS. copyright: berkeley's probably.
+ * contents from isavar.h and isareg.h, mostly the latter.
+ * perhaps charles's?
+ *
+ * copyright from berkeley's isa.h which is now dev/isa/isareg.h.
+ */
+
+/*
+ * Types provided to machine-independent ISA code.
+ */
+
+typedef void *isa_chipset_tag_t;
+
+struct device; /* XXX */
+struct isabus_attach_args; /* XXX */
+
+/*
+ * Functions provided to machine-independent ISA code.
+ */
+void isa_attach_hook(struct device *, struct device *,
+ struct isabus_attach_args *);
+int isa_intr_alloc(isa_chipset_tag_t, int, int, int *);
+const struct evcnt *isa_intr_evcnt(isa_chipset_tag_t ic, int irq);
+void *isa_intr_establish(isa_chipset_tag_t ic, int irq, int type,
+ int level, int (*ih_fun)(void *), void *ih_arg, char *);
+void isa_intr_disestablish(isa_chipset_tag_t ic, void *handler);
+int isa_mem_alloc(bus_space_tag_t, bus_size_t, bus_size_t,
+ bus_addr_t, int, bus_addr_t *, bus_space_handle_t *);
+void isa_mem_free(bus_space_tag_t, bus_space_handle_t, bus_size_t);
+
+#define isa_dmainit(ic, bst, dmat, d) \
+ _isa_dmainit(&(ic)->ic_dmastate, (bst), (dmat), (d))
+#define isa_dmacascade(ic, c) \
+ _isa_dmacascade(&(ic)->ic_dmastate, (c))
+#define isa_dmamaxsize(ic, c) \
+ _isa_dmamaxsize(&(ic)->ic_dmastate, (c))
+#define isa_dmamap_create(ic, c, s, f) \
+ _isa_dmamap_create(&(ic)->ic_dmastate, (c), (s), (f))
+#define isa_dmamap_destroy(ic, c) \
+ _isa_dmamap_destroy(&(ic)->ic_dmastate, (c))
+#define isa_dmastart(ic, c, a, n, p, f, bf) \
+ _isa_dmastart(&(ic)->ic_dmastate, (c), (a), (n), (p), (f), (bf))
+#define isa_dmaabort(ic, c) \
+ _isa_dmaabort(&(ic)->ic_dmastate, (c))
+#define isa_dmacount(ic, c) \
+ _isa_dmacount(&(ic)->ic_dmastate, (c))
+#define isa_dmafinished(ic, c) \
+ _isa_dmafinished(&(ic)->ic_dmastate, (c))
+#define isa_dmadone(ic, c) \
+ _isa_dmadone(&(ic)->ic_dmastate, (c))
+#define isa_dmafreeze(ic) \
+ _isa_dmafreeze(&(ic)->ic_dmastate)
+#define isa_dmathaw(ic) \
+ _isa_dmathaw(&(ic)->ic_dmastate)
+#define isa_dmamem_alloc(ic, c, s, ap, f) \
+ _isa_dmamem_alloc(&(ic)->ic_dmastate, (c), (s), (ap), (f))
+#define isa_dmamem_free(ic, c, a, s) \
+ _isa_dmamem_free(&(ic)->ic_dmastate, (c), (a), (s))
+#define isa_dmamem_map(ic, c, a, s, kp, f) \
+ _isa_dmamem_map(&(ic)->ic_dmastate, (c), (a), (s), (kp), (f))
+#define isa_dmamem_unmap(ic, c, k, s) \
+ _isa_dmamem_unmap(&(ic)->ic_dmastate, (c), (k), (s))
+#define isa_dmamem_mmap(ic, c, a, s, o, p, f) \
+ _isa_dmamem_mmap(&(ic)->ic_dmastate, (c), (a), (s), (o), (p), (f))
+#define isa_drq_alloc(ic, c) \
+ _isa_drq_alloc(&(ic)->ic_dmastate, c)
+#define isa_drq_free(ic, c) \
+ _isa_drq_free(&(ic)->ic_dmastate, c)
+#define isa_drq_isfree(ic, c) \
+ _isa_drq_isfree(&(ic)->ic_dmastate, (c))
+#define isa_malloc(ic, c, s, p, f) \
+ _isa_malloc(&(ic)->ic_dmastate, (c), (s), (p), (f))
+#define isa_free(a, p) \
+ _isa_free((a), (p))
+#define isa_mappage(m, o, p) \
+ _isa_mappage((m), (o), (p))
+
+int isa_intr_check(isa_chipset_tag_t, int, int);
+
+/*
+ * for ACPI code
+ */
+
+void isa_reinit_irq(void);
+
+/*
+ * ALL OF THE FOLLOWING ARE MACHINE-DEPENDENT, AND SHOULD NOT BE USED
+ * BY PORTABLE CODE.
+ */
+
+extern struct x86_bus_dma_tag isa_bus_dma_tag;
+
+/*
+ * XXX Various seemingly PC-specific constants, some of which may be
+ * unnecessary anyway.
+ */
+
+/*
+ * RAM Physical Address Space (ignoring the above mentioned "hole")
+ */
+#define RAM_BEGIN 0x0000000 /* Start of RAM Memory */
+#define RAM_END 0x1000000 /* End of RAM Memory */
+#define RAM_SIZE (RAM_END - RAM_BEGIN)
+
+/*
+ * Oddball Physical Memory Addresses
+ */
+#define COMPAQ_RAMRELOC 0x80c00000 /* Compaq RAM relocation/diag */
+#define COMPAQ_RAMSETUP 0x80c00002 /* Compaq RAM setup */
+#define WEITEK_FPU 0xC0000000 /* WTL 2167 */
+#define CYRIX_EMC 0xC0000000 /* Cyrix EMC */
+
+/*
+ * stuff that used to be in pccons.c
+ */
+#define MONO_BASE 0x3B4
+#define MONO_BUF 0xB0000
+#define CGA_BASE 0x3D4
+#define CGA_BUF 0xB8000
+
+/*
+ * Variables and macros to deal with the ISA I/O hole.
+ * XXX These should be converted to machine- and bus-mapping-independent
+ * function definitions, invoked through the softc.
+ */
+
+extern u_long atdevbase; /* kernel virtual address of "hole" */
+
+/*
+ * Given a kernel virtual address for some location
+ * in the "hole" I/O space, return a physical address.
+ */
+#define ISA_PHYSADDR(v) ((void *) ((u_long)(v) - atdevbase + IOM_BEGIN))
+
+/*
+ * Given a physical address in the "hole",
+ * return a kernel virtual address.
+ */
+#define ISA_HOLE_VADDR(p) ((void *) ((u_long)(p) - IOM_BEGIN + atdevbase))
+
+
+/*
+ * Miscellanous functions.
+ */
+void sysbeep(int, int); /* beep with the system speaker */
+
+#endif /* _I386_ISA_MACHDEP_H_ XXX */
diff --git a/sys/arch/amd64/include/kcore.h b/sys/arch/amd64/include/kcore.h
new file mode 100644
index 00000000000..ddb4d1d7a85
--- /dev/null
+++ b/sys/arch/amd64/include/kcore.h
@@ -0,0 +1,49 @@
+/* $NetBSD: kcore.h,v 1.1 2003/04/26 18:39:43 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/*
+ * Modified for NetBSD/i386 by Jason R. Thorpe, Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center.
+ *
+ * And once again modified for x86-64 by Frank van der Linden of
+ * Wasabi Systems, Inc.
+ */
+
+#ifndef _AMD64KCORE_H_
+#define _AMD64_KCORE_H_
+
+typedef struct cpu_kcore_hdr {
+ u_int64_t ptdpaddr; /* PA of PML4 */
+ u_int64_t nmemsegs; /* Number of RAM segments */
+#if 0
+ phys_ram_seg_t memsegs[]; /* RAM segments */
+#endif
+} cpu_kcore_hdr_t;
+
+#endif /* _AMD64_KCORE_H_ */
diff --git a/sys/arch/amd64/include/limits.h b/sys/arch/amd64/include/limits.h
new file mode 100644
index 00000000000..8cde663caa5
--- /dev/null
+++ b/sys/arch/amd64/include/limits.h
@@ -0,0 +1,57 @@
+/* $OpenBSD: limits.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+
+/*
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)limits.h 7.2 (Berkeley) 6/28/90
+ */
+
+#ifndef _MACHINE_LIMITS_H_
+#define _MACHINE_LIMITS_H_
+
+#define MB_LEN_MAX 1 /* no multibyte characters */
+
+#if !defined(_ANSI_SOURCE)
+#define SIZE_MAX ULONG_MAX /* max value for a size_t */
+#define SSIZE_MAX LONG_MAX /* max value for a ssize_t */
+
+#if !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)
+#define SIZE_T_MAX ULONG_MAX /* max value for a size_t */
+
+#define UQUAD_MAX 0xffffffffffffffffULL /* max unsigned quad */
+#define QUAD_MAX 0x7fffffffffffffffLL /* max signed quad */
+#define QUAD_MIN (-0x7fffffffffffffffLL-1) /* min signed quad */
+
+#endif /* !_POSIX_C_SOURCE && !_XOPEN_SOURCE */
+#endif /* !_ANSI_SOURCE */
+
+#endif /* _MACHINE_LIMITS_H_ */
diff --git a/sys/arch/amd64/include/loadfile_machdep.h b/sys/arch/amd64/include/loadfile_machdep.h
new file mode 100644
index 00000000000..7de50b522ee
--- /dev/null
+++ b/sys/arch/amd64/include/loadfile_machdep.h
@@ -0,0 +1,60 @@
+/* XXX - DSR */
+/* $OpenBSD: loadfile_machdep.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: loadfile_machdep.h,v 1.1 1999/04/29 03:17:12 tsubai Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#define BOOT_ELF
+#define ELFSIZE 64
+
+#define LOAD_KERNEL (LOAD_ALL & ~LOAD_TEXTA)
+#define COUNT_KERNEL (COUNT_ALL & ~COUNT_TEXTA)
+
+#define LOADADDR(a) ((((u_long)(a)) + offset)&0xfffffff)
+#define ALIGNENTRY(a) ((u_long)(a))
+#define READ(f, b, c) read((f), (void *)LOADADDR(b), (c))
+#define BCOPY(s, d, c) memcpy((void *)LOADADDR(d), (void *)(s), (c))
+#define BZERO(d, c) memset((void *)LOADADDR(d), 0, (c))
+#define WARN(a) (void)(printf a, \
+ printf((errno ? ": %s\n" : "\n"), \
+ strerror(errno)))
+#define PROGRESS(a) (void) printf a
+#define ALLOC(a) alloc(a)
+#define FREE(a, b) free(a, b)
+#define OKMAGIC(a) ((a) == OMAGIC)
+
+void run_loadfile(u_long *, int);
diff --git a/sys/arch/amd64/include/mcontext.h b/sys/arch/amd64/include/mcontext.h
new file mode 100644
index 00000000000..ec1ed5f816c
--- /dev/null
+++ b/sys/arch/amd64/include/mcontext.h
@@ -0,0 +1,108 @@
+/* $OpenBSD: mcontext.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: mcontext.h,v 1.1 2003/04/26 18:39:44 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Klaus Klein.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef _AMD64_MCONTEXT_H_
+#define _AMD64_MCONTEXT_H_
+
+/*
+ * Layout of mcontext_t according to the System V Application Binary Interface,
+ * Intel386(tm) Architecture Processor Supplement, Fourth Edition.
+ */
+
+/*
+ * General register state
+ */
+#define _NGREG 26
+typedef long __greg_t;
+typedef __greg_t __gregset_t[_NGREG];
+
+/*
+ * This is laid out to match trapframe and intrframe (see <machine/frame.h>).
+ * Hence, memcpy between gregs and a trapframe is possible.
+ */
+#define _REG_RDI 0
+#define _REG_RSI 1
+#define _REG_RDX 2
+#define _REG_RCX 3
+#define _REG_R8 4
+#define _REG_R9 5
+#define _REG_R10 6
+#define _REG_R11 7
+#define _REG_R12 8
+#define _REG_R13 9
+#define _REG_R14 10
+#define _REG_R15 11
+#define _REG_RBP 12
+#define _REG_RBX 13
+#define _REG_RAX 14
+#define _REG_GS 15
+#define _REG_FS 16
+#define _REG_ES 17
+#define _REG_DS 18
+#define _REG_TRAPNO 19
+#define _REG_ERR 20
+#define _REG_RIP 21
+#define _REG_CS 22
+#define _REG_RFL 23
+#define _REG_URSP 24
+#define _REG_SS 25
+
+/*
+ * Floating point register state
+ */
+typedef char __fpregset_t[512];
+
+/*
+ * The padding below is to make __fpregs have a 16-byte aligned offset
+ * within ucontext_t.
+ */
+
+typedef struct {
+ __gregset_t __gregs;
+ long __pad;
+ __fpregset_t __fpregs;
+} mcontext_t;
+
+#define _UC_UCONTEXT_ALIGN (~0xf)
+
+#ifdef _KERNEL
+#define _UC_MACHINE_SP(uc) ((uc)->uc_mcontext.__gregs[_REG_URSP])
+#endif
+
+#endif /* !_AMD64_MCONTEXT_H_ */
diff --git a/sys/arch/amd64/include/mpbiosreg.h b/sys/arch/amd64/include/mpbiosreg.h
new file mode 100644
index 00000000000..8041f5bb930
--- /dev/null
+++ b/sys/arch/amd64/include/mpbiosreg.h
@@ -0,0 +1,138 @@
+/* $OpenBSD: mpbiosreg.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: mpbiosreg.h,v 1.3 2003/03/04 23:27:32 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by RedBack Networks Inc.
+ *
+ * Author: Bill Sommerfeld
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef _X86_MPBIOSREG_H_
+#define _X86_MPBIOSREG_H_
+
+#define BIOS_BASE (0xf0000)
+#define BIOS_SIZE (0x10000)
+#define BIOS_COUNT (BIOS_SIZE)
+
+/*
+ * Multiprocessor config table entry types.
+ */
+
+#define MPS_MCT_CPU 0
+#define MPS_MCT_BUS 1
+#define MPS_MCT_IOAPIC 2
+#define MPS_MCT_IOINT 3
+#define MPS_MCT_LINT 4
+
+#define MPS_MCT_NTYPES 5
+
+/* MP Floating Pointer Structure */
+struct mpbios_fps {
+ u_int32_t signature;
+/* string defined by the Intel MP Spec as identifying the MP table */
+#define MP_FP_SIG 0x5f504d5f /* _MP_ */
+
+ u_int32_t pap;
+ u_int8_t length;
+ u_int8_t spec_rev;
+ u_int8_t checksum;
+ u_int8_t mpfb1; /* system configuration */
+ u_int8_t mpfb2; /* flags */
+#define MPFPS_FLAG_IMCR 0x80 /* IMCR present */
+ u_int8_t mpfb3; /* unused */
+ u_int8_t mpfb4; /* unused */
+ u_int8_t mpfb5; /* unused */
+};
+
+/* MP Configuration Table Header */
+struct mpbios_cth {
+ u_int32_t signature;
+#define MP_CT_SIG 0x504d4350 /* PCMP */
+
+ u_int16_t base_len;
+ u_int8_t spec_rev;
+ u_int8_t checksum;
+ u_int8_t oem_id[8];
+ u_int8_t product_id[12];
+ u_int32_t oem_table_pointer;
+ u_int16_t oem_table_size;
+ u_int16_t entry_count;
+ u_int32_t apic_address;
+ u_int16_t ext_len;
+ u_int8_t ext_cksum;
+ u_int8_t reserved;
+};
+
+struct mpbios_proc {
+ u_int8_t type;
+ u_int8_t apic_id;
+ u_int8_t apic_version;
+ u_int8_t cpu_flags;
+#define PROCENTRY_FLAG_EN 0x01
+#define PROCENTRY_FLAG_BP 0x02
+ u_int32_t cpu_signature;
+ u_int32_t feature_flags;
+ u_int32_t reserved1;
+ u_int32_t reserved2;
+};
+
+struct mpbios_bus {
+ u_int8_t type;
+ u_int8_t bus_id;
+ char bus_type[6];
+};
+
+struct mpbios_ioapic {
+ u_int8_t type;
+ u_int8_t apic_id;
+ u_int8_t apic_version;
+ u_int8_t apic_flags;
+#define IOAPICENTRY_FLAG_EN 0x01
+ u_int32_t apic_address;
+};
+
+struct mpbios_int {
+ u_int8_t type;
+ u_int8_t int_type;
+ u_int16_t int_flags;
+ u_int8_t src_bus_id;
+ u_int8_t src_bus_irq;
+ u_int8_t dst_apic_id;
+#define MPS_ALL_APICS 0xff
+ u_int8_t dst_apic_int;
+};
+
+
+#endif /* !_X86_MPBIOSREG_H_ */
diff --git a/sys/arch/amd64/include/mpbiosvar.h b/sys/arch/amd64/include/mpbiosvar.h
new file mode 100644
index 00000000000..b10bbe44fc7
--- /dev/null
+++ b/sys/arch/amd64/include/mpbiosvar.h
@@ -0,0 +1,62 @@
+/* $OpenBSD: mpbiosvar.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: mpbiosvar.h,v 1.2 2003/04/02 07:53:57 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by RedBack Networks Inc.
+ *
+ * Author: Bill Sommerfeld
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+
+#ifndef _X86_MPBIOSVAR_H_
+#define _X86_MPBIOSVAR_H_
+
+#define MP_TRAMPOLINE (2 * PAGE_SIZE)
+
+#if !defined(_LOCORE)
+
+#include <machine/mpbiosreg.h>
+#include <machine/mpconfig.h>
+
+#if defined(_KERNEL)
+void mpbios_scan(struct device *);
+int mpbios_probe(struct device *);
+
+extern int mpbios_scanned;
+#endif
+
+#endif
+
+#endif /* !_X86_MPBIOSVAR_H_ */
diff --git a/sys/arch/amd64/include/mpconfig.h b/sys/arch/amd64/include/mpconfig.h
new file mode 100644
index 00000000000..7c12822824c
--- /dev/null
+++ b/sys/arch/amd64/include/mpconfig.h
@@ -0,0 +1,65 @@
+/* $NetBSD: mpconfig.h,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */
+
+/*
+ * Definitions originally from the mpbios code, but now used for ACPI
+ * MP config as well.
+ */
+
+#ifndef _X86_MPCONFIG_H
+#define _X86_MPCONFIG_H
+
+/*
+ * Interrupt typess
+ */
+#define MPS_INTTYPE_INT 0
+#define MPS_INTTYPE_NMI 1
+#define MPS_INTTYPE_SMI 2
+#define MPS_INTTYPE_ExtINT 3
+
+#define MPS_INTPO_DEF 0
+#define MPS_INTPO_ACTHI 1
+#define MPS_INTPO_ACTLO 3
+
+#define MPS_INTTR_DEF 0
+#define MPS_INTTR_EDGE 1
+#define MPS_INTTR_LEVEL 3
+
+#ifndef _LOCORE
+
+struct mpbios_int;
+
+struct mp_bus
+{
+ char *mb_name; /* XXX bus name */
+ int mb_idx; /* XXX bus index */
+ void (*mb_intr_print)(int);
+ void (*mb_intr_cfg)(const struct mpbios_int *, u_int32_t *);
+ struct mp_intr_map *mb_intrs;
+ u_int32_t mb_data; /* random bus-specific datum. */
+};
+
+struct mp_intr_map
+{
+ struct mp_intr_map *next;
+ struct mp_bus *bus;
+ int bus_pin;
+ struct ioapic_softc *ioapic;
+ int ioapic_pin;
+ int ioapic_ih; /* int handle, for apic_intr_est */
+ int type; /* from mp spec intr record */
+ int flags; /* from mp spec intr record */
+ u_int32_t redir;
+ int cpu_id;
+};
+
+#if defined(_KERNEL)
+extern int mp_verbose;
+extern struct mp_bus *mp_busses;
+extern struct mp_intr_map *mp_intrs;
+extern int mp_nintr;
+extern int mp_isa_bus, mp_eisa_bus;
+extern int mp_nbus;
+#endif
+#endif
+
+#endif /* _X86_MPCONFIG_H */
diff --git a/sys/arch/amd64/include/mtrr.h b/sys/arch/amd64/include/mtrr.h
new file mode 100644
index 00000000000..ab17926ecf5
--- /dev/null
+++ b/sys/arch/amd64/include/mtrr.h
@@ -0,0 +1,160 @@
+/* $OpenBSD: mtrr.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: mtrr.h,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Bill Sommerfeld
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef _X86_MTRR_H_
+#define _X86_MTRR_H_
+
+#define MTRR_I686_FIXED_IDX64K 0
+#define MTRR_I686_FIXED_IDX16K 1
+#define MTRR_I686_FIXED_IDX4K 3
+
+#define MTRR_I686_NVAR 8
+
+#define MTRR_I686_64K_START 0x00000
+#define MTRR_I686_16K_START 0x80000
+#define MTRR_I686_4K_START 0xc0000
+
+#define MTRR_I686_NFIXED_64K 1
+#define MTRR_I686_NFIXED_16K 2
+#define MTRR_I686_NFIXED_4K 8
+#define MTRR_I686_NFIXED 11
+#define MTRR_I686_NFIXED_SOFT_64K (MTRR_I686_NFIXED_64K * 8)
+#define MTRR_I686_NFIXED_SOFT_16K (MTRR_I686_NFIXED_16K * 8)
+#define MTRR_I686_NFIXED_SOFT_4K (MTRR_I686_NFIXED_4K * 8)
+#define MTRR_I686_NFIXED_SOFT (MTRR_I686_NFIXED * 8)
+
+#define MTRR_I686_ENABLE_MASK 0x0800
+#define MTRR_I686_FIXED_ENABLE_MASK 0x0400
+
+#define MTRR_I686_CAP_VCNT_MASK 0x00ff
+#define MTRR_I686_CAP_FIX_MASK 0x0100
+#define MTRR_I686_CAP_WC_MASK 0x0400
+
+#define MTRR_TYPE_UC 0
+#define MTRR_TYPE_WC 1
+#define MTRR_TYPE_UNDEF1 2
+#define MTRR_TYPE_UNDEF2 3
+#define MTRR_TYPE_WT 4
+#define MTRR_TYPE_WP 5
+#define MTRR_TYPE_WB 6
+
+struct mtrr_state {
+ uint32_t msraddr;
+ uint64_t msrval;
+};
+
+#define MTRR_PRIVATE 0x0001 /* 'own' range, reset at exit */
+#define MTRR_FIXED 0x0002 /* use fixed range mtrr */
+#define MTRR_VALID 0x0004 /* entry is valid */
+
+#define MTRR_CANTSET MTRR_FIXED
+
+#define MTRR_I686_MASK_VALID (1 << 11)
+
+/*
+ * AMD K6 MTRRs.
+ *
+ * There are two of these MTRR-like registers in the UWCRR.
+ */
+
+#define MTRR_K6_ADDR_SHIFT 17
+#define MTRR_K6_ADDR (0x7fffU << MTRR_K6_ADDR_SHIFT)
+#define MTRR_K6_MASK_SHIFT 2
+#define MTRR_K6_MASK (0x7fffU << MTRR_K6_MASK_SHIFT)
+#define MTRR_K6_WC (1U << 1) /* write-combine */
+#define MTRR_K6_UC (1U << 0) /* uncached */
+
+#define MTRR_K6_NVAR 2
+
+#ifdef _KERNEL
+
+#define mtrr_base_value(mtrrp) \
+ (((uint64_t)(mtrrp)->base) | ((uint64_t)(mtrrp)->type))
+#define mtrr_mask_value(mtrrp) \
+ ((~((mtrrp)->len - 1) & 0x0000000ffffff000))
+
+
+#define mtrr_len(val) \
+ ((~((val) & 0x0000000ffffff000)+1) & 0x0000000ffffff000)
+#define mtrr_base(val) ((val) & 0x0000000ffffff000)
+#define mtrr_type(val) ((uint8_t)((val) & 0x00000000000000ff))
+#define mtrr_valid(val) (((val) & MTRR_I686_MASK_VALID) != 0)
+
+struct proc;
+struct mtrr;
+
+void i686_mtrr_init_first(void);
+void k6_mtrr_init_first(void);
+
+struct mtrr_funcs {
+ void (*init_cpu)(struct cpu_info *ci);
+ void (*reload_cpu)(struct cpu_info *ci);
+ void (*clean)(struct proc *p);
+ int (*set)(struct mtrr *, int *n, struct proc *p, int flags);
+ int (*get)(struct mtrr *, int *n, struct proc *p, int flags);
+ void (*commit)(void);
+ void (*dump)(const char *tag);
+};
+
+extern struct mtrr_funcs i686_mtrr_funcs;
+extern struct mtrr_funcs k6_mtrr_funcs;
+extern struct mtrr_funcs *mtrr_funcs;
+
+#define mtrr_init_cpu(ci) mtrr_funcs->init_cpu(ci)
+#define mtrr_reload_cpu(ci) mtrr_funcs->reload_cpu(ci)
+#define mtrr_clean(p) mtrr_funcs->clean(p)
+#define mtrr_set(mp,n,p,f) mtrr_funcs->set(mp,n,p,f)
+#define mtrr_get(mp,n,p,f) mtrr_funcs->get(mp,n,p,f)
+#define mtrr_dump(s) mtrr_funcs->dump(s)
+#define mtrr_commit() mtrr_funcs->commit()
+
+#define MTRR_GETSET_USER 0x0001
+#define MTRR_GETSET_KERNEL 0x0002
+
+#endif /* _KERNEL */
+
+struct mtrr {
+ uint64_t base; /* physical base address */
+ uint64_t len;
+ uint8_t type;
+ int flags;
+ pid_t owner; /* valid if MTRR_PRIVATE set in flags */
+};
+
+#endif /* _X86_MTRR_H_ */
diff --git a/sys/arch/amd64/include/param.h b/sys/arch/amd64/include/param.h
new file mode 100644
index 00000000000..7e3f512977f
--- /dev/null
+++ b/sys/arch/amd64/include/param.h
@@ -0,0 +1,173 @@
+/* $OpenBSD: param.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)param.h 5.8 (Berkeley) 6/28/91
+ */
+
+#ifdef _KERNEL
+#ifdef _LOCORE
+#include <machine/psl.h>
+#else
+#include <machine/cpu.h>
+#endif
+#endif
+
+#define _MACHINE amd64
+#define MACHINE "amd64"
+#define _MACHINE_ARCH x86_64
+#define MACHINE_ARCH "x86_64"
+#define MID_MACHINE MID_X86_64
+
+/*
+ * Round p (pointer or byte index) up to a correctly-aligned value
+ * for all data types (int, long, ...). The result is u_long and
+ * must be cast to any desired pointer type.
+ *
+ * ALIGNED_POINTER is a boolean macro that checks whether an address
+ * is valid to fetch data elements of type t from on this architecture.
+ * This does not reflect the optimal alignment, just the possibility
+ * (within reasonable limits).
+ *
+ */
+#define ALIGNBYTES (sizeof(long) - 1)
+#define ALIGN(p) (((u_long)(p) + ALIGNBYTES) &~ALIGNBYTES)
+#define ALIGNED_POINTER(p,t) 1
+
+#define PGSHIFT 12 /* LOG2(NBPG) */
+#define NBPG (1 << PGSHIFT) /* bytes/page */
+#define PGOFSET (NBPG-1) /* byte offset into page */
+
+#define PAGE_SHIFT 12
+#define PAGE_SIZE (1 << PAGE_SHIFT)
+#define PAGE_MASK (PAGE_SIZE - 1)
+
+#define NPTEPG (NBPG/(sizeof (pt_entry_t)))
+
+#define KERNBASE 0xffffffff80000000 /* start of kernel virtual space */
+#define KERNTEXTOFF (KERNBASE+0x100000) /* start of kernel text */
+#define BTOPKERNBASE ((u_long)KERNBASE >> PGSHIFT)
+
+#define KERNTEXTOFF_HI 0xffffffff
+#define KERNTEXTOFF_LO 0x80100000
+
+#define KERNBASE_HI 0xffffffff
+#define KERNBASE_LO 0x80000000
+
+#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */
+#define DEV_BSIZE (1 << DEV_BSHIFT)
+#define BLKDEV_IOSIZE 2048
+#ifndef MAXPHYS
+#define MAXPHYS (64 * 1024) /* max raw I/O transfer size */
+#endif
+
+#define SSIZE 1 /* initial stack size/NBPG */
+#define SINCR 1 /* increment of stack/NBPG */
+#define UPAGES 5 /* pages of u-area */
+#define USPACE (UPAGES * NBPG) /* total size of u-area */
+
+#ifndef MSGBUFSIZE
+#define MSGBUFSIZE 4*NBPG /* default message buffer size */
+#endif
+
+/*
+ * Constants related to network buffer management.
+ * MCLBYTES must be no larger than NBPG (the software page size), and,
+ * on machines that exchange pages of input or output buffers with mbuf
+ * clusters (MAPPED_MBUFS), MCLBYTES must also be an integral multiple
+ * of the hardware page size.
+ */
+#define MSIZE 256 /* size of an mbuf */
+#define MCLSHIFT 11 /* convert bytes to m_buf clusters */
+#define MCLBYTES (1 << MCLSHIFT) /* size of a m_buf cluster */
+#define MCLOFSET (MCLBYTES - 1) /* offset within a m_buf cluster */
+
+#ifndef NMBCLUSTERS
+#define NMBCLUSTERS 2048 /* map size, max cluster allocation */
+#endif
+
+/*
+ * Minimum and maximum sizes of the kernel malloc arena in PAGE_SIZE-sized
+ * logical pages.
+ */
+#define NKMEMPAGES_MIN_DEFAULT ((8 * 1024 * 1024) >> PAGE_SHIFT)
+#define NKMEMPAGES_MAX_DEFAULT ((128 * 1024 * 1024) >> PAGE_SHIFT)
+
+/* pages ("clicks") to disk blocks */
+#define ctod(x) ((x) << (PGSHIFT - DEV_BSHIFT))
+#define dtoc(x) ((x) >> (PGSHIFT - DEV_BSHIFT))
+
+/* bytes to pages */
+#define ctob(x) ((x) << PGSHIFT)
+#define btoc(x) (((x) + PGOFSET) >> PGSHIFT)
+
+/* bytes to disk blocks */
+#define dbtob(x) ((x) << DEV_BSHIFT)
+#define btodb(x) ((x) >> DEV_BSHIFT)
+
+/*
+ * Map a ``block device block'' to a file system block.
+ * This should be device dependent, and should use the bsize
+ * field from the disk label.
+ * For now though just use DEV_BSIZE.
+ */
+#define bdbtofsb(bn) ((bn) / (BLKDEV_IOSIZE / DEV_BSIZE))
+
+/*
+ * XXXfvdl the PD* stuff is different from i386.
+ */
+/*
+ * Mach derived conversion macros
+ */
+#define x86_round_pdr(x) \
+ ((((unsigned long)(x)) + (NBPD_L2 - 1)) & ~(NBPD_L2 - 1))
+#define x86_trunc_pdr(x) ((unsigned long)(x) & ~(NBPD_L2 - 1))
+#define x86_btod(x) ((unsigned long)(x) >> L2_SHIFT)
+#define x86_dtob(x) ((unsigned long)(x) << L2_SHIFT)
+#define x86_round_page(x) ((((unsigned long)(x)) + PGOFSET) & ~PGOFSET)
+#define x86_trunc_page(x) ((unsigned long)(x) & ~PGOFSET)
+#define x86_btop(x) ((unsigned long)(x) >> PGSHIFT)
+#define x86_ptob(x) ((unsigned long)(x) << PGSHIFT)
+
+#define btop(x) x86_btop(x)
+#define ptob(x) x86_ptob(x)
+#define round_pdr(x) x86_round_pdr(x)
+
+/* XXX - oh, the horror.. Just for now. */
+#define KERNEL_PROC_LOCK(p)
+#define KERNEL_PROC_UNLOCK(p)
+#define KERNEL_LOCK(i)
+#define KERNEL_UNLOCK()
diff --git a/sys/arch/amd64/include/pcb.h b/sys/arch/amd64/include/pcb.h
new file mode 100644
index 00000000000..af95ea5aa9b
--- /dev/null
+++ b/sys/arch/amd64/include/pcb.h
@@ -0,0 +1,130 @@
+/* $NetBSD: pcb.h,v 1.1 2003/04/26 18:39:45 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 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.
+ *
+ * @(#)pcb.h 5.10 (Berkeley) 5/12/91
+ */
+
+/*
+ * XXXfvdl these copyrights don't really match anymore
+ */
+
+#ifndef _AMD64_PCB_H_
+#define _AMD64_PCB_H_
+
+#include <sys/signal.h>
+
+#include <machine/segments.h>
+#include <machine/tss.h>
+#include <machine/fpu.h>
+#include <machine/sysarch.h>
+
+#define NIOPORTS 1024 /* # of ports we allow to be mapped */
+
+/*
+ * Please note that the pcb_savefpu field in struct below must be
+ * on a 16-byte boundary.
+ */
+struct pcb {
+ /*
+ * XXXfvdl
+ * It's overkill to have a TSS here, as it's only needed
+ * for compatibility processes who use an I/O permission map.
+ * The pcb fields below are not in the TSS anymore (and there's
+ * not enough room in the TSS to store them all)
+ * Should just make this a pointer and allocate.
+ */
+ struct x86_64_tss pcb_tss;
+ u_int64_t pcb_cr3;
+ u_int64_t pcb_rsp;
+ u_int64_t pcb_rbp;
+ u_int64_t pcb_usersp;
+ u_int64_t pcb_ldt_sel;
+ struct savefpu pcb_savefpu; /* floating point state */
+ int pcb_cr0; /* saved image of CR0 */
+ int pcb_flags;
+#define PCB_USER_LDT 0x01 /* has user-set LDT */
+ caddr_t pcb_onfault; /* copyin/out fault recovery */
+ struct cpu_info *pcb_fpcpu; /* cpu holding our fp state. */
+ unsigned pcb_iomap[NIOPORTS/32]; /* I/O bitmap */
+ struct pmap *pcb_pmap; /* back pointer to our pmap */
+};
+
+/*
+ * The pcb is augmented with machine-dependent additional data for
+ * core dumps. For the i386, there is nothing to add.
+ */
+struct md_coredump {
+ long md_pad[8];
+};
+
+#endif /* _AMD64_PCB_H_ */
diff --git a/sys/arch/amd64/include/pci_machdep.h b/sys/arch/amd64/include/pci_machdep.h
new file mode 100644
index 00000000000..e7852418297
--- /dev/null
+++ b/sys/arch/amd64/include/pci_machdep.h
@@ -0,0 +1,110 @@
+/* $OpenBSD: pci_machdep.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: pci_machdep.h,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
+ * Copyright (c) 1994 Charles M. Hannum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Charles M. Hannum.
+ * 4. 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.
+ */
+
+/*
+ * Machine-specific definitions for PCI autoconfiguration.
+ */
+
+/*
+ * i386-specific PCI structure and type definitions.
+ * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE.
+ *
+ * Configuration tag; created from a {bus,device,function} triplet by
+ * pci_make_tag(), and passed to pci_conf_read() and pci_conf_write().
+ * We could instead always pass the {bus,device,function} triplet to
+ * the read and write routines, but this would cause extra overhead.
+ *
+ * Mode 2 is historical and deprecated by the Revision 2.0 specification.
+ */
+union x86_pci_tag_u {
+ u_int32_t mode1;
+ struct {
+ u_int16_t port;
+ u_int8_t enable;
+ u_int8_t forward;
+ } mode2;
+};
+
+extern struct x86_bus_dma_tag pci_bus_dma_tag;
+
+/*
+ * Types provided to machine-independent PCI code
+ */
+typedef void *pci_chipset_tag_t;
+typedef union x86_pci_tag_u pcitag_t;
+typedef int pci_intr_handle_t;
+
+/*
+ * i386-specific PCI variables and functions.
+ * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE.
+ */
+extern int pci_mode;
+int pci_mode_detect(void);
+int pci_bus_flags(void);
+struct pci_attach_args;
+
+/*
+ * Functions provided to machine-independent PCI code.
+ */
+void pci_attach_hook(struct device *, struct device *,
+ struct pcibus_attach_args *);
+int pci_bus_maxdevs(pci_chipset_tag_t, int);
+pcitag_t pci_make_tag(pci_chipset_tag_t, int, int, int);
+void pci_decompose_tag(pci_chipset_tag_t, pcitag_t,
+ int *, int *, int *);
+pcireg_t pci_conf_read(pci_chipset_tag_t, pcitag_t, int);
+void pci_conf_write(pci_chipset_tag_t, pcitag_t, int,
+ pcireg_t);
+int pci_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
+const char *pci_intr_string(pci_chipset_tag_t, pci_intr_handle_t);
+const struct evcnt *pci_intr_evcnt(pci_chipset_tag_t, pci_intr_handle_t);
+void *pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t,
+ int, int (*)(void *), void *, char *);
+void pci_intr_disestablish(pci_chipset_tag_t, void *);
+void pci_decompose_tag(pci_chipset_tag_t, pcitag_t,
+ int *, int *, int *);
+
+#define pci_enumerate_bus(sc, m, p) \
+ pci_enumerate_bus_generic((sc), (m), (p))
+
+/*
+ * ALL OF THE FOLLOWING ARE MACHINE-DEPENDENT, AND SHOULD NOT BE USED
+ * BY PORTABLE CODE.
+ */
+
+/*
+ * Section 6.2.4, `Miscellaneous Functions' of the PCI Specification,
+ * says that 255 means `unknown' or `no connection' to the interrupt
+ * controller on a PC.
+ */
+#define X86_PCI_INTERRUPT_LINE_NO_CONNECTION 0xff
diff --git a/sys/arch/amd64/include/pic.h b/sys/arch/amd64/include/pic.h
new file mode 100644
index 00000000000..c9d9a5082a6
--- /dev/null
+++ b/sys/arch/amd64/include/pic.h
@@ -0,0 +1,40 @@
+/* $OpenBSD: pic.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: pic.h,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */
+
+#ifndef _X86_PIC_H
+#define _X86_PIC_H
+
+#include <sys/device.h>
+#include <sys/lock.h>
+
+struct cpu_info;
+
+/*
+ * Structure common to all PIC softcs
+ */
+struct pic {
+ struct device pic_dev;
+ int pic_type;
+ simple_lock_t pic_lock;
+ void (*pic_hwmask)(struct pic *, int);
+ void (*pic_hwunmask)(struct pic *, int);
+ void (*pic_addroute)(struct pic *, struct cpu_info *, int, int, int);
+ void (*pic_delroute)(struct pic *, struct cpu_info *, int, int, int);
+ struct intrstub *pic_level_stubs;
+ struct intrstub *pic_edge_stubs;
+};
+
+#define pic_name pic_dev.dv_xname
+
+/*
+ * PIC types.
+ */
+#define PIC_I8259 0
+#define PIC_IOAPIC 1
+#define PIC_LAPIC 2
+#define PIC_SOFT 3
+
+extern struct pic i8259_pic;
+extern struct pic local_pic;
+extern struct pic softintr_pic;
+#endif
diff --git a/sys/arch/amd64/include/pio.h b/sys/arch/amd64/include/pio.h
new file mode 100644
index 00000000000..9d54de16fc5
--- /dev/null
+++ b/sys/arch/amd64/include/pio.h
@@ -0,0 +1,232 @@
+/* $OpenBSD: pio.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: pio.h,v 1.2 2003/02/27 11:22:46 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef _X86_PIO_H_
+#define _X86_PIO_H_
+
+/*
+ * Functions to provide access to x86 programmed I/O instructions.
+ *
+ * The in[bwl]() and out[bwl]() functions are split into two varieties: one to
+ * use a small, constant, 8-bit port number, and another to use a large or
+ * variable port number. The former can be compiled as a smaller instruction.
+ */
+
+
+#ifdef __OPTIMIZE__
+
+#define __use_immediate_port(port) \
+ (__builtin_constant_p((port)) && (port) < 0x100)
+
+#else
+
+#define __use_immediate_port(port) 0
+
+#endif
+
+
+#define inb(port) \
+ (/* CONSTCOND */ __use_immediate_port(port) ? __inbc(port) : __inb(port))
+
+static __inline u_int8_t
+__inbc(unsigned port)
+{
+ u_int8_t data;
+ __asm __volatile("inb %w1,%0" : "=a" (data) : "id" (port));
+ return data;
+}
+
+static __inline u_int8_t
+__inb(unsigned port)
+{
+ u_int8_t data;
+ __asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port));
+ return data;
+}
+
+static __inline void
+insb(unsigned port, void *addr, int cnt)
+{
+ void *dummy1;
+ int dummy2;
+ __asm __volatile("cld\n\trepne\n\tinsb" :
+ "=D" (dummy1), "=c" (dummy2) :
+ "d" (port), "0" (addr), "1" (cnt) :
+ "memory");
+}
+
+#define inw(port) \
+ (/* CONSTCOND */ __use_immediate_port(port) ? __inwc(port) : __inw(port))
+
+static __inline u_int16_t
+__inwc(unsigned port)
+{
+ u_int16_t data;
+ __asm __volatile("inw %w1,%0" : "=a" (data) : "id" (port));
+ return data;
+}
+
+static __inline u_int16_t
+__inw(unsigned port)
+{
+ u_int16_t data;
+ __asm __volatile("inw %w1,%0" : "=a" (data) : "d" (port));
+ return data;
+}
+
+static __inline void
+insw(unsigned port, void *addr, int cnt)
+{
+ void *dummy1;
+ int dummy2;
+ __asm __volatile("cld\n\trepne\n\tinsw" :
+ "=D" (dummy1), "=c" (dummy2) :
+ "d" (port), "0" (addr), "1" (cnt) :
+ "memory");
+}
+
+#define inl(port) \
+ (/* CONSTCOND */ __use_immediate_port(port) ? __inlc(port) : __inl(port))
+
+static __inline u_int32_t
+__inlc(unsigned port)
+{
+ u_int32_t data;
+ __asm __volatile("inl %w1,%0" : "=a" (data) : "id" (port));
+ return data;
+}
+
+static __inline u_int32_t
+__inl(unsigned port)
+{
+ u_int32_t data;
+ __asm __volatile("inl %w1,%0" : "=a" (data) : "d" (port));
+ return data;
+}
+
+static __inline void
+insl(unsigned port, void *addr, int cnt)
+{
+ void *dummy1;
+ int dummy2;
+ __asm __volatile("cld\n\trepne\n\tinsl" :
+ "=D" (dummy1), "=c" (dummy2) :
+ "d" (port), "0" (addr), "1" (cnt) :
+ "memory");
+}
+
+#define outb(port, data) \
+ (/* CONSTCOND */__use_immediate_port(port) ? __outbc(port, data) : \
+ __outb(port, data))
+
+static __inline void
+__outbc(unsigned port, u_int8_t data)
+{
+ __asm __volatile("outb %0,%w1" : : "a" (data), "id" (port));
+}
+
+static __inline void
+__outb(unsigned port, u_int8_t data)
+{
+ __asm __volatile("outb %0,%w1" : : "a" (data), "d" (port));
+}
+
+static __inline void
+outsb(unsigned port, const void *addr, int cnt)
+{
+ void *dummy1;
+ int dummy2;
+ __asm __volatile("cld\n\trepne\n\toutsb" :
+ "=S" (dummy1), "=c" (dummy2) :
+ "d" (port), "0" (addr), "1" (cnt));
+}
+
+#define outw(port, data) \
+ (/* CONSTCOND */ __use_immediate_port(port) ? __outwc(port, data) : \
+ __outw(port, data))
+
+static __inline void
+__outwc(unsigned port, u_int16_t data)
+{
+ __asm __volatile("outw %0,%w1" : : "a" (data), "id" (port));
+}
+
+static __inline void
+__outw(unsigned port, u_int16_t data)
+{
+ __asm __volatile("outw %0,%w1" : : "a" (data), "d" (port));
+}
+
+static __inline void
+outsw(unsigned port, const void *addr, int cnt)
+{
+ void *dummy1;
+ int dummy2;
+ __asm __volatile("cld\n\trepne\n\toutsw" :
+ "=S" (dummy1), "=c" (dummy2) :
+ "d" (port), "0" (addr), "1" (cnt));
+}
+
+#define outl(port, data) \
+ (/* CONSTCOND */ __use_immediate_port(port) ? __outlc(port, data) : \
+ __outl(port, data))
+
+static __inline void
+__outlc(unsigned port, u_int32_t data)
+{
+ __asm __volatile("outl %0,%w1" : : "a" (data), "id" (port));
+}
+
+static __inline void
+__outl(unsigned port, u_int32_t data)
+{
+ __asm __volatile("outl %0,%w1" : : "a" (data), "d" (port));
+}
+
+static __inline void
+outsl(unsigned port, const void *addr, int cnt)
+{
+ void *dummy1;
+ int dummy2;
+ __asm __volatile("cld\n\trepne\n\toutsl" :
+ "=S" (dummy1), "=c" (dummy2) :
+ "d" (port), "0" (addr), "1" (cnt));
+}
+
+#endif /* _X86_PIO_H_ */
diff --git a/sys/arch/amd64/include/pmap.h b/sys/arch/amd64/include/pmap.h
new file mode 100644
index 00000000000..a9366187930
--- /dev/null
+++ b/sys/arch/amd64/include/pmap.h
@@ -0,0 +1,592 @@
+/* $OpenBSD: pmap.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: pmap.h,v 1.1 2003/04/26 18:39:46 fvdl Exp $ */
+
+/*
+ *
+ * Copyright (c) 1997 Charles D. Cranor and Washington University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgment:
+ * This product includes software developed by Charles D. Cranor and
+ * Washington University.
+ * 4. 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.
+ */
+
+/*
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Frank van der Linden for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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.
+ */
+
+/*
+ * pmap.h: see pmap.c for the history of this pmap module.
+ */
+
+#ifndef _AMD64_PMAP_H_
+#define _AMD64_PMAP_H_
+
+#ifndef _LOCORE
+#include <machine/cpufunc.h>
+#include <machine/pte.h>
+#include <machine/segments.h>
+#include <uvm/uvm_object.h>
+#endif
+
+/*
+ * The x86_64 pmap module closely resembles the i386 one. It uses
+ * the same recursive entry scheme, and the same alternate area
+ * trick for accessing non-current pmaps. See the i386 pmap.h
+ * for a description. The obvious difference is that 3 extra
+ * levels of page table need to be dealt with. The level 1 page
+ * table pages are at:
+ *
+ * l1: 0x00007f8000000000 - 0x00007fffffffffff (39 bits, needs PML4 entry)
+ *
+ * The alternate space is at:
+ *
+ * l1: 0xffffff8000000000 - 0xffffffffffffffff (39 bits, needs PML4 entry)
+ *
+ * The rest is kept as physical pages in 3 UVM objects, and is
+ * temporarily mapped for virtual access when needed.
+ *
+ * Note that address space is signed, so the layout for 48 bits is:
+ *
+ * +---------------------------------+ 0xffffffffffffffff
+ * | |
+ * | alt.L1 table (PTE pages) |
+ * | |
+ * +---------------------------------+ 0xffffff8000000000
+ * ~ ~
+ * | |
+ * | Kernel Space |
+ * | |
+ * | |
+ * +---------------------------------+ 0xffff800000000000 = 0x0000008000000000
+ * | |
+ * | alt.L1 table (PTE pages) |
+ * | |
+ * +---------------------------------+ 0x00007f8000000000
+ * ~ ~
+ * | |
+ * | User Space |
+ * | |
+ * | |
+ * +---------------------------------+ 0x0000000000000000
+ *
+ * In other words, there is a 'VA hole' at 0x0000008000000000 -
+ * 0xffff800000000000 which will trap, just as on, for example,
+ * sparcv9.
+ *
+ * The unused space can be used if needed, but it adds a little more
+ * complexity to the calculations.
+ */
+
+/*
+ * The first generation of Hammer processors can use 48 bits of
+ * virtual memory, and 40 bits of physical memory. This will be
+ * more for later generations. These defines can be changed to
+ * variable names containing the # of bits, extracted from an
+ * extended cpuid instruction (variables are harder to use during
+ * bootstrap, though)
+ */
+#define VIRT_BITS 48
+#define PHYS_BITS 40
+
+/*
+ * Mask to get rid of the sign-extended part of addresses.
+ */
+#define VA_SIGN_MASK 0xffff000000000000
+#define VA_SIGN_NEG(va) ((va) | VA_SIGN_MASK)
+/*
+ * XXXfvdl this one's not right.
+ */
+#define VA_SIGN_POS(va) ((va) & ~VA_SIGN_MASK)
+
+#define L4_SLOT_PTE 255
+#define L4_SLOT_KERN 256
+#define L4_SLOT_KERNBASE 511
+#define L4_SLOT_APTE 510
+
+#define PDIR_SLOT_KERN L4_SLOT_KERN
+#define PDIR_SLOT_PTE L4_SLOT_PTE
+#define PDIR_SLOT_APTE L4_SLOT_APTE
+
+/*
+ * the following defines give the virtual addresses of various MMU
+ * data structures:
+ * PTE_BASE and APTE_BASE: the base VA of the linear PTE mappings
+ * PTD_BASE and APTD_BASE: the base VA of the recursive mapping of the PTD
+ * PDP_PDE and APDP_PDE: the VA of the PDE that points back to the PDP/APDP
+ *
+ */
+
+#define PTE_BASE ((pt_entry_t *) (L4_SLOT_PTE * NBPD_L4))
+#define APTE_BASE ((pt_entry_t *) (VA_SIGN_NEG((L4_SLOT_APTE * NBPD_L4))))
+
+#define L1_BASE PTE_BASE
+#define AL1_BASE APTE_BASE
+
+#define L2_BASE ((pd_entry_t *)((char *)L1_BASE + L4_SLOT_PTE * NBPD_L3))
+#define L3_BASE ((pd_entry_t *)((char *)L2_BASE + L4_SLOT_PTE * NBPD_L2))
+#define L4_BASE ((pd_entry_t *)((char *)L3_BASE + L4_SLOT_PTE * NBPD_L1))
+
+#define AL2_BASE ((pd_entry_t *)((char *)AL1_BASE + L4_SLOT_PTE * NBPD_L3))
+#define AL3_BASE ((pd_entry_t *)((char *)AL2_BASE + L4_SLOT_PTE * NBPD_L2))
+#define AL4_BASE ((pd_entry_t *)((char *)AL3_BASE + L4_SLOT_PTE * NBPD_L1))
+
+#define PDP_PDE (L4_BASE + PDIR_SLOT_PTE)
+#define APDP_PDE (L4_BASE + PDIR_SLOT_APTE)
+
+#define PDP_BASE L4_BASE
+#define APDP_BASE AL4_BASE
+
+#define NKL4_MAX_ENTRIES (unsigned long)1
+#define NKL3_MAX_ENTRIES (unsigned long)(NKL4_MAX_ENTRIES * 512)
+#define NKL2_MAX_ENTRIES (unsigned long)(NKL3_MAX_ENTRIES * 512)
+#define NKL1_MAX_ENTRIES (unsigned long)(NKL2_MAX_ENTRIES * 512)
+
+#define NKL4_KIMG_ENTRIES 1
+#define NKL3_KIMG_ENTRIES 1
+#define NKL2_KIMG_ENTRIES 8
+
+/*
+ * Since kva space is below the kernel in its entirety, we start off
+ * with zero entries on each level.
+ */
+#define NKL4_START_ENTRIES 0
+#define NKL3_START_ENTRIES 0
+#define NKL2_START_ENTRIES 0
+#define NKL1_START_ENTRIES 0 /* XXX */
+
+#define NTOPLEVEL_PDES (PAGE_SIZE / (sizeof (pd_entry_t)))
+
+#define KERNSPACE (NKL4_ENTRIES * NBPD_L4)
+
+#define NPDPG (PAGE_SIZE / sizeof (pd_entry_t))
+
+#define ptei(VA) (((VA_SIGN_POS(VA)) & L1_MASK) >> L1_SHIFT)
+
+/*
+ * pl*_pi: index in the ptp page for a pde mapping a VA.
+ * (pl*_i below is the index in the virtual array of all pdes per level)
+ */
+#define pl1_pi(VA) (((VA_SIGN_POS(VA)) & L1_MASK) >> L1_SHIFT)
+#define pl2_pi(VA) (((VA_SIGN_POS(VA)) & L2_MASK) >> L2_SHIFT)
+#define pl3_pi(VA) (((VA_SIGN_POS(VA)) & L3_MASK) >> L3_SHIFT)
+#define pl4_pi(VA) (((VA_SIGN_POS(VA)) & L4_MASK) >> L4_SHIFT)
+
+/*
+ * pl*_i: generate index into pde/pte arrays in virtual space
+ */
+#define pl1_i(VA) (((VA_SIGN_POS(VA)) & L1_FRAME) >> L1_SHIFT)
+#define pl2_i(VA) (((VA_SIGN_POS(VA)) & L2_FRAME) >> L2_SHIFT)
+#define pl3_i(VA) (((VA_SIGN_POS(VA)) & L3_FRAME) >> L3_SHIFT)
+#define pl4_i(VA) (((VA_SIGN_POS(VA)) & L4_FRAME) >> L4_SHIFT)
+#define pl_i(va, lvl) \
+ (((VA_SIGN_POS(va)) & ptp_masks[(lvl)-1]) >> ptp_shifts[(lvl)-1])
+
+#define PTP_MASK_INITIALIZER { L1_FRAME, L2_FRAME, L3_FRAME, L4_FRAME }
+#define PTP_SHIFT_INITIALIZER { L1_SHIFT, L2_SHIFT, L3_SHIFT, L4_SHIFT }
+#define NKPTP_INITIALIZER { NKL1_START_ENTRIES, NKL2_START_ENTRIES, \
+ NKL3_START_ENTRIES, NKL4_START_ENTRIES }
+#define NKPTPMAX_INITIALIZER { NKL1_MAX_ENTRIES, NKL2_MAX_ENTRIES, \
+ NKL3_MAX_ENTRIES, NKL4_MAX_ENTRIES }
+#define NBPD_INITIALIZER { NBPD_L1, NBPD_L2, NBPD_L3, NBPD_L4 }
+#define PDES_INITIALIZER { L2_BASE, L3_BASE, L4_BASE }
+#define APDES_INITIALIZER { AL2_BASE, AL3_BASE, AL4_BASE }
+
+/*
+ * PTP macros:
+ * a PTP's index is the PD index of the PDE that points to it
+ * a PTP's offset is the byte-offset in the PTE space that this PTP is at
+ * a PTP's VA is the first VA mapped by that PTP
+ *
+ * note that PAGE_SIZE == number of bytes in a PTP (4096 bytes == 1024 entries)
+ * NBPD == number of bytes a PTP can map (4MB)
+ */
+
+#define ptp_va2o(va, lvl) (pl_i(va, (lvl)+1) * PAGE_SIZE)
+
+#define PTP_LEVELS 4
+
+/*
+ * PG_AVAIL usage: we make use of the ignored bits of the PTE
+ */
+
+#define PG_W PG_AVAIL1 /* "wired" mapping */
+#define PG_PVLIST PG_AVAIL2 /* mapping has entry on pvlist */
+/* PG_AVAIL3 not used */
+
+/*
+ * Number of PTE's per cache line. 8 byte pte, 64-byte cache line
+ * Used to avoid false sharing of cache lines.
+ */
+#define NPTECL 8
+
+
+#if defined(_KERNEL) && !defined(_LOCORE)
+/*
+ * pmap data structures: see pmap.c for details of locking.
+ */
+
+struct pmap;
+typedef struct pmap *pmap_t;
+
+/*
+ * we maintain a list of all non-kernel pmaps
+ */
+
+LIST_HEAD(pmap_head, pmap); /* struct pmap_head: head of a pmap list */
+
+/*
+ * the pmap structure
+ *
+ * note that the pm_obj contains the simple_lock, the reference count,
+ * page list, and number of PTPs within the pmap.
+ *
+ * pm_lock is the same as the spinlock for vm object 0. Changes to
+ * the other objects may only be made if that lock has been taken
+ * (the other object locks are only used when uvm_pagealloc is called)
+ */
+
+struct pmap {
+ struct uvm_object pm_obj[PTP_LEVELS-1]; /* objects for lvl >= 1) */
+#define pm_lock pm_obj[0].vmobjlock
+#define pm_obj_l1 pm_obj[0]
+#define pm_obj_l2 pm_obj[1]
+#define pm_obj_l3 pm_obj[2]
+ LIST_ENTRY(pmap) pm_list; /* list (lck by pm_list lock) */
+ pd_entry_t *pm_pdir; /* VA of PD (lck by object lock) */
+ paddr_t pm_pdirpa; /* PA of PD (read-only after create) */
+ struct vm_page *pm_ptphint[PTP_LEVELS-1];
+ /* pointer to a PTP in our pmap */
+ struct pmap_statistics pm_stats; /* pmap stats (lck by object lock) */
+
+ int pm_flags; /* see below */
+
+ union descriptor *pm_ldt; /* user-set LDT */
+ int pm_ldt_len; /* number of LDT entries */
+ int pm_ldt_sel; /* LDT selector */
+ u_int32_t pm_cpus; /* mask of CPUs using pmap */
+};
+
+/* pm_flags */
+#define PMF_USER_LDT 0x01 /* pmap has user-set LDT */
+
+/*
+ * for each managed physical page we maintain a list of <PMAP,VA>'s
+ * which it is mapped at. the list is headed by a pv_head structure.
+ * there is one pv_head per managed phys page (allocated at boot time).
+ * the pv_head structure points to a list of pv_entry structures (each
+ * describes one mapping).
+ */
+
+struct pv_entry;
+
+struct pv_head {
+ struct simplelock pvh_lock; /* locks every pv on this list */
+ struct pv_entry *pvh_list; /* head of list (locked by pvh_lock) */
+};
+
+struct pv_entry { /* locked by its list's pvh_lock */
+ struct pv_entry *pv_next; /* next entry */
+ struct pmap *pv_pmap; /* the pmap */
+ vaddr_t pv_va; /* the virtual address */
+ struct vm_page *pv_ptp; /* the vm_page of the PTP */
+};
+
+/*
+ * pv_entrys are dynamically allocated in chunks from a single page.
+ * we keep track of how many pv_entrys are in use for each page and
+ * we can free pv_entry pages if needed. there is one lock for the
+ * entire allocation system.
+ */
+
+struct pv_page_info {
+ TAILQ_ENTRY(pv_page) pvpi_list;
+ struct pv_entry *pvpi_pvfree;
+ int pvpi_nfree;
+};
+
+/*
+ * number of pv_entry's in a pv_page
+ * (note: won't work on systems where NPBG isn't a constant)
+ */
+
+#define PVE_PER_PVPAGE ((PAGE_SIZE - sizeof(struct pv_page_info)) / \
+ sizeof(struct pv_entry))
+
+/*
+ * a pv_page: where pv_entrys are allocated from
+ */
+
+struct pv_page {
+ struct pv_page_info pvinfo;
+ struct pv_entry pvents[PVE_PER_PVPAGE];
+};
+
+/*
+ * pmap_remove_record: a record of VAs that have been unmapped, used to
+ * flush TLB. if we have more than PMAP_RR_MAX then we stop recording.
+ */
+
+#define PMAP_RR_MAX 16 /* max of 16 pages (64K) */
+
+struct pmap_remove_record {
+ int prr_npages;
+ vaddr_t prr_vas[PMAP_RR_MAX];
+};
+
+/*
+ * global kernel variables
+ */
+
+/* PTDpaddr: is the physical address of the kernel's PDP */
+extern u_long PTDpaddr;
+
+extern struct pmap kernel_pmap_store; /* kernel pmap */
+extern int pmap_pg_g; /* do we support PG_G? */
+
+extern paddr_t ptp_masks[];
+extern int ptp_shifts[];
+extern long nkptp[], nbpd[], nkptpmax[];
+extern pd_entry_t *pdes[];
+
+/*
+ * macros
+ */
+
+#define pmap_kernel() (&kernel_pmap_store)
+#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count)
+#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count)
+#define pmap_update(pmap) /* nothing (yet) */
+
+#define pmap_clear_modify(pg) pmap_clear_attrs(pg, PG_M)
+#define pmap_clear_reference(pg) pmap_clear_attrs(pg, PG_U)
+#define pmap_copy(DP,SP,D,L,S)
+#define pmap_is_modified(pg) pmap_test_attrs(pg, PG_M)
+#define pmap_is_referenced(pg) pmap_test_attrs(pg, PG_U)
+#define pmap_move(DP,SP,D,L,S)
+#define pmap_phys_address(ppn) ptob(ppn)
+#define pmap_valid_entry(E) ((E) & PG_V) /* is PDE or PTE valid? */
+
+
+/*
+ * prototypes
+ */
+
+void pmap_bootstrap(vaddr_t);
+boolean_t pmap_clear_attrs(struct vm_page *, unsigned);
+static void pmap_page_protect(struct vm_page *, vm_prot_t);
+void pmap_page_remove (struct vm_page *);
+static void pmap_protect(struct pmap *, vaddr_t,
+ vaddr_t, vm_prot_t);
+void pmap_remove(struct pmap *, vaddr_t, vaddr_t);
+boolean_t pmap_test_attrs(struct vm_page *, unsigned);
+static void pmap_update_pg(vaddr_t);
+static void pmap_update_2pg(vaddr_t,vaddr_t);
+void pmap_write_protect(struct pmap *, vaddr_t,
+ vaddr_t, vm_prot_t);
+
+vaddr_t reserve_dumppages(vaddr_t); /* XXX: not a pmap fn */
+
+void pmap_tlb_shootdown(pmap_t, vaddr_t, pt_entry_t, int32_t *);
+void pmap_tlb_shootnow(int32_t);
+void pmap_do_tlb_shootdown(struct cpu_info *);
+void pmap_prealloc_lowmem_ptps(void);
+
+#define PMAP_GROWKERNEL /* turn on pmap_growkernel interface */
+
+/*
+ * Do idle page zero'ing uncached to avoid polluting the cache.
+ */
+boolean_t pmap_pageidlezero(struct vm_page *);
+#define PMAP_PAGEIDLEZERO(pg) pmap_pageidlezero((pg))
+
+/*
+ * inline functions
+ */
+
+static __inline void
+pmap_remove_all(struct pmap *pmap)
+{
+ /* Nothing. */
+}
+
+/*
+ * pmap_update_pg: flush one page from the TLB (or flush the whole thing
+ * if hardware doesn't support one-page flushing)
+ */
+
+__inline static void
+pmap_update_pg(va)
+ vaddr_t va;
+{
+ invlpg(va);
+}
+
+/*
+ * pmap_update_2pg: flush two pages from the TLB
+ */
+
+__inline static void
+pmap_update_2pg(va, vb)
+ vaddr_t va, vb;
+{
+ invlpg(va);
+ invlpg(vb);
+}
+
+/*
+ * pmap_page_protect: change the protection of all recorded mappings
+ * of a managed page
+ *
+ * => this function is a frontend for pmap_page_remove/pmap_clear_attrs
+ * => we only have to worry about making the page more protected.
+ * unprotecting a page is done on-demand at fault time.
+ */
+
+__inline static void
+pmap_page_protect(struct vm_page *pg, vm_prot_t prot)
+{
+ if ((prot & VM_PROT_WRITE) == 0) {
+ if (prot & (VM_PROT_READ|VM_PROT_EXECUTE)) {
+ (void) pmap_clear_attrs(pg, PG_RW);
+ } else {
+ pmap_page_remove(pg);
+ }
+ }
+}
+
+/*
+ * pmap_protect: change the protection of pages in a pmap
+ *
+ * => this function is a frontend for pmap_remove/pmap_write_protect
+ * => we only have to worry about making the page more protected.
+ * unprotecting a page is done on-demand at fault time.
+ */
+
+__inline static void
+pmap_protect(pmap, sva, eva, prot)
+ struct pmap *pmap;
+ vaddr_t sva, eva;
+ vm_prot_t prot;
+{
+ if ((prot & VM_PROT_WRITE) == 0) {
+ if (prot & (VM_PROT_READ|VM_PROT_EXECUTE)) {
+ pmap_write_protect(pmap, sva, eva, prot);
+ } else {
+ pmap_remove(pmap, sva, eva);
+ }
+ }
+}
+
+/*
+ * various address inlines
+ *
+ * vtopte: return a pointer to the PTE mapping a VA, works only for
+ * user and PT addresses
+ *
+ * kvtopte: return a pointer to the PTE mapping a kernel VA
+ */
+
+#include <lib/libkern/libkern.h>
+
+static __inline pt_entry_t *
+vtopte(vaddr_t va)
+{
+
+ KASSERT(va < (L4_SLOT_KERN * NBPD_L4));
+
+ return (PTE_BASE + pl1_i(va));
+}
+
+static __inline pt_entry_t *
+kvtopte(vaddr_t va)
+{
+
+ KASSERT(va >= (L4_SLOT_KERN * NBPD_L4));
+
+#ifdef LARGEPAGES
+ {
+ pd_entry_t *pde;
+
+ pde = L1_BASE + pl2_i(va);
+ if (*pde & PG_PS)
+ return ((pt_entry_t *)pde);
+ }
+#endif
+
+ return (PTE_BASE + pl1_i(va));
+}
+
+#define pmap_pte_set(p, n) x86_atomic_testset_u64(p, n)
+#define pmap_pte_clearbits(p, b) x86_atomic_clearbits_u64(p, b)
+#define pmap_cpu_has_pg_n() (1)
+#define pmap_cpu_has_invlpg (1)
+
+paddr_t vtophys(vaddr_t);
+vaddr_t pmap_map(vaddr_t, paddr_t, paddr_t, vm_prot_t);
+
+#if 0 /* XXXfvdl was USER_LDT, need to check if that can be supported */
+void pmap_ldt_cleanup(struct proc *);
+#define PMAP_FORK
+#endif /* USER_LDT */
+
+/*
+ * Hooks for the pool allocator.
+ */
+/* #define POOL_VTOPHYS(va) vtophys((vaddr_t) (va)) */
+
+#endif /* _KERNEL && !_LOCORE */
+#endif /* _AMD64_PMAP_H_ */
diff --git a/sys/arch/amd64/include/proc.h b/sys/arch/amd64/include/proc.h
new file mode 100644
index 00000000000..89e8360b954
--- /dev/null
+++ b/sys/arch/amd64/include/proc.h
@@ -0,0 +1,63 @@
+/* $OpenBSD: proc.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: proc.h,v 1.1 2003/04/26 18:39:46 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1991 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)proc.h 7.1 (Berkeley) 5/15/91
+ */
+
+#ifndef _AMD64_PROC_H
+#define _AMD64_PROC_H
+
+#include <machine/frame.h>
+
+/*
+ * Machine-dependent part of the proc structure for amd64.
+ */
+struct mdproc {
+ struct trapframe *md_regs; /* registers on current frame */
+ int md_tss_sel; /* TSS selector */
+ int md_flags;
+ /* Syscall handling function */
+ void (*md_syscall)(struct trapframe);
+ __volatile int md_astpending;
+};
+
+/* md_flags */
+#define MDP_USEDFPU 0x0001 /* has used the FPU */
+#define MDP_COMPAT 0x0002 /* x86 compatibility process */
+#define MDP_SYSCALL 0x0004 /* entered kernel via syscall ins */
+#define MDP_USEDMTRR 0x0008 /* has set volatile MTRRs */
+#define MDP_IRET 0x0010 /* return via iret, not sysret */
+
+#endif /* _AMD64_PROC_H */
diff --git a/sys/arch/amd64/include/profile.h b/sys/arch/amd64/include/profile.h
new file mode 100644
index 00000000000..5d928249a31
--- /dev/null
+++ b/sys/arch/amd64/include/profile.h
@@ -0,0 +1,65 @@
+/* $OpenBSD: profile.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: profile.h,v 1.1 2003/04/26 18:39:46 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)profile.h 8.1 (Berkeley) 6/11/93
+ */
+
+#define _MCOUNT_DECL static __inline void _mcount
+
+#define MCOUNT_ENTRY "mcount"
+
+/*
+ * XXXfvdl this is screwed by -fomit-frame-pointer being included in
+ * -O.
+ */
+#define MCOUNT \
+extern void mcount __P((void)) __asm__(MCOUNT_ENTRY); \
+void \
+mcount() \
+{ \
+ _mcount((u_long)__builtin_return_address(1), \
+ (u_long)__builtin_return_address(0)); \
+}
+
+
+#ifdef _KERNEL
+/*
+ * Note that we assume splhigh() and splx() cannot call mcount()
+ * recursively.
+ */
+#define MCOUNT_ENTER s = splhigh()
+#define MCOUNT_EXIT splx(s)
+#endif /* _KERNEL */
+
diff --git a/sys/arch/amd64/include/psl.h b/sys/arch/amd64/include/psl.h
new file mode 100644
index 00000000000..689c507c487
--- /dev/null
+++ b/sys/arch/amd64/include/psl.h
@@ -0,0 +1,87 @@
+/* $OpenBSD: psl.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: psl.h,v 1.1 2003/02/26 21:26:11 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)psl.h 5.2 (Berkeley) 1/18/91
+ */
+
+#ifndef _X86_PSL_H_
+#define _X86_PSL_H_
+
+/*
+ * 386 processor status longword.
+ */
+#define PSL_C 0x00000001 /* carry flag */
+#define PSL_PF 0x00000004 /* parity flag */
+#define PSL_AF 0x00000010 /* auxiliary carry flag */
+#define PSL_Z 0x00000040 /* zero flag */
+#define PSL_N 0x00000080 /* sign flag */
+#define PSL_T 0x00000100 /* trap flag */
+#define PSL_I 0x00000200 /* interrupt enable flag */
+#define PSL_D 0x00000400 /* direction flag */
+#define PSL_V 0x00000800 /* overflow flag */
+#define PSL_IOPL 0x00003000 /* i/o privilege level */
+#define PSL_NT 0x00004000 /* nested task */
+#define PSL_RF 0x00010000 /* resume flag */
+#define PSL_VM 0x00020000 /* virtual 8086 mode */
+#define PSL_AC 0x00040000 /* alignment check flag */
+#define PSL_VIF 0x00080000 /* virtual interrupt enable flag */
+#define PSL_VIP 0x00100000 /* virtual interrupt pending flag */
+#define PSL_ID 0x00200000 /* identification flag */
+
+#define PSL_MBO 0x00000002 /* must be one bits */
+#define PSL_MBZ 0xffc08028 /* must be zero bits */
+
+#define PSL_USERSET (PSL_MBO | PSL_I)
+#if defined(_KERNEL_OPT)
+#include "opt_vm86.h"
+#endif
+#ifdef VM86
+#define PSL_USERSTATIC (PSL_MBO | PSL_MBZ | PSL_I | PSL_IOPL | PSL_NT | PSL_VIF | PSL_VIP)
+#else
+#define PSL_USERSTATIC (PSL_MBO | PSL_MBZ | PSL_I | PSL_IOPL | PSL_NT | PSL_VM | PSL_VIF | PSL_VIP)
+#endif
+#define PSL_USER (PSL_C | PSL_MBO | PSL_PF | PSL_AF | PSL_Z | PSL_N | PSL_V)
+
+/*
+ * ???
+ */
+#ifdef _KERNEL
+#include <machine/intr.h>
+#endif
+
+#endif /* !_X86_PSL_H_ */
diff --git a/sys/arch/amd64/include/pte.h b/sys/arch/amd64/include/pte.h
new file mode 100644
index 00000000000..eaa883d3f6f
--- /dev/null
+++ b/sys/arch/amd64/include/pte.h
@@ -0,0 +1,137 @@
+/* $OpenBSD: pte.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: pte.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */
+
+/*
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Frank van der Linden for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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.
+ */
+
+#ifndef _AMD64_PTE_H_
+#define _AMD64_PTE_H_
+
+/*
+ * amd64 MMU hardware structure:
+ *
+ * the (first generation) amd64 MMU is a 4-level MMU which maps 2^48 bytes
+ * of virtual memory. The pagesize we use is is 4K (4096 [0x1000] bytes),
+ * although 2M and 4M can be used as well. The indexes in the levels
+ * are 9 bits wide (512 64bit entries per level), dividing the bits
+ * 9-9-9-9-12.
+ *
+ * The top level table, called PML4, contains 512 64bit entries pointing
+ * to 3rd level table. The 3rd level table is called the 'page directory
+ * pointers directory' and has 512 entries pointing to page directories.
+ * The 2nd level is the page directory, containing 512 pointers to
+ * page table pages. Lastly, level 1 consists of pages containing 512
+ * PTEs.
+ *
+ * Simply put, levels 4-1 all consist of pages containing 512
+ * entries pointing to the next level. Level 0 is the actual PTEs
+ * themselves.
+ *
+ * For a description on the other bits, which are i386 compatible,
+ * see the i386 pte.h
+ */
+
+#if !defined(_LOCORE)
+
+/*
+ * here we define the data types for PDEs and PTEs
+ */
+
+typedef u_int64_t pd_entry_t; /* PDE */
+typedef u_int64_t pt_entry_t; /* PTE */
+
+#endif
+
+/*
+ * now we define various for playing with virtual addresses
+ */
+
+#define L1_SHIFT 12
+#define L2_SHIFT 21
+#define L3_SHIFT 30
+#define L4_SHIFT 39
+#define NBPD_L1 (1ULL << L1_SHIFT) /* # bytes mapped by L1 ent (4K) */
+#define NBPD_L2 (1ULL << L2_SHIFT) /* # bytes mapped by L2 ent (2MB) */
+#define NBPD_L3 (1ULL << L3_SHIFT) /* # bytes mapped by L3 ent (1G) */
+#define NBPD_L4 (1ULL << L4_SHIFT) /* # bytes mapped by L4 ent (512G) */
+
+#define L4_MASK 0x0000ff8000000000
+#define L3_MASK 0x0000007fc0000000
+#define L2_MASK 0x000000003fe00000
+#define L1_MASK 0x00000000001ff000
+
+#define L4_FRAME L4_MASK
+#define L3_FRAME (L4_FRAME|L3_MASK)
+#define L2_FRAME (L3_FRAME|L2_MASK)
+#define L1_FRAME (L2_FRAME|L1_MASK)
+
+/*
+ * PDE/PTE bits. These are no different from their i386 counterparts.
+ */
+
+#define PG_V 0x0000000000000001 /* valid */
+#define PG_RO 0x0000000000000000 /* read-only */
+#define PG_RW 0x0000000000000002 /* read-write */
+#define PG_u 0x0000000000000004 /* user accessible */
+#define PG_PROT 0x0000000000000006
+#define PG_N 0x0000000000000018 /* non-cacheable */
+#define PG_U 0x0000000000000020 /* used */
+#define PG_M 0x0000000000000040 /* modified */
+#define PG_PS 0x0000000000000080 /* 2MB page size */
+#define PG_G 0x0000000000000100 /* not flushed */
+#define PG_AVAIL1 0x0000000000000200
+#define PG_AVAIL2 0x0000000000000400
+#define PG_AVAIL3 0x0000000000000800
+#define PG_NX 0x8000000000000000 /* non-executable */
+#define PG_FRAME 0xfffffffffffff000
+
+#define PG_LGFRAME 0xffffffffffc00000 /* large (2M) page frame mask */
+
+/*
+ * short forms of protection codes
+ */
+
+#define PG_KR 0x0000000000000000 /* kernel read-only */
+#define PG_KW 0x0000000000000002 /* kernel read-write */
+
+/*
+ * page protection exception bits
+ */
+
+#define PGEX_P 0x01 /* protection violation (vs. no mapping) */
+#define PGEX_W 0x02 /* exception during a write cycle */
+#define PGEX_U 0x04 /* exception while in user mode (upl) */
+
+#endif /* _AMD64_PTE_H_ */
diff --git a/sys/arch/amd64/include/ptrace.h b/sys/arch/amd64/include/ptrace.h
new file mode 100644
index 00000000000..27c0bf29c1d
--- /dev/null
+++ b/sys/arch/amd64/include/ptrace.h
@@ -0,0 +1,41 @@
+/* $OpenBSD: ptrace.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: ptrace.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1993 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou.
+ * 4. 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.
+ */
+
+/*
+ * i386-dependent ptrace definitions
+ */
+#define PT_STEP (PT_FIRSTMACH + 0)
+#define PT_GETREGS (PT_FIRSTMACH + 1)
+#define PT_SETREGS (PT_FIRSTMACH + 2)
+#define PT_GETFPREGS (PT_FIRSTMACH + 3)
+#define PT_SETFPREGS (PT_FIRSTMACH + 4)
diff --git a/sys/arch/amd64/include/reg.h b/sys/arch/amd64/include/reg.h
new file mode 100644
index 00000000000..f594a44c6fc
--- /dev/null
+++ b/sys/arch/amd64/include/reg.h
@@ -0,0 +1,102 @@
+/* $OpenBSD: reg.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: reg.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)reg.h 5.5 (Berkeley) 1/18/91
+ */
+
+#ifndef _AMD64_REG_H_
+#define _AMD64_REG_H_
+
+#include <machine/mcontext.h>
+#include <machine/fpu.h>
+
+/*
+ * XXX
+ * The #defines aren't used in the kernel, but some user-level code still
+ * expects them.
+ */
+
+/* When referenced during a trap/exception, registers are at these offsets */
+
+#define tR15 0
+#define tR14 1
+#define tR13 2
+#define tR12 3
+#define tR11 4
+#define tR10 5
+#define tR9 6
+#define tR8 7
+#define tRDI 8
+#define tRSI 9
+#define tRBP 10
+#define tRBX 11
+#define tRDX 12
+#define tRCX 13
+#define tRAX 14
+
+#define tRIP 17
+#define tCS 18
+#define tRFLAGS 19
+#define tRSP 20
+#define tSS 21
+
+/*
+ * Registers accessible to ptrace(2) syscall for debugger use.
+ * Same as mcontext.__gregs and struct trapframe, they must
+ * remain synced (XXX should use common structure).
+ */
+struct reg {
+ long regs[_NGREG];
+};
+
+struct fpreg {
+ struct fxsave64 fxstate;
+};
+
+#define fp_fcw fxstate.fx_fcw
+#define fp_fsw fxstate.fx_fsw
+#define fp_ftw fxstate.fx_ftw
+#define fp_fop fxstate.fx_fop
+#define fp_rip fxstate.fx_rip
+#define fp_rdp fxstate.fx_rdp
+#define fp_mxcsr fxstate.fx_mxcsr
+#define fp_mxcsr_mask fxstate.fx_mxcsr_mask
+#define fp_st fxstate.fx_st
+#define fp_xmm fxstate.fx_xmm
+
+#endif /* !_AMD64_REG_H_ */
diff --git a/sys/arch/amd64/include/segments.h b/sys/arch/amd64/include/segments.h
new file mode 100644
index 00000000000..636f3a38fee
--- /dev/null
+++ b/sys/arch/amd64/include/segments.h
@@ -0,0 +1,305 @@
+/* $OpenBSD: segments.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: segments.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1995, 1997
+ * Charles M. Hannum. All rights reserved.
+ * Copyright (c) 1989, 1990 William F. Jolitz
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)segments.h 7.1 (Berkeley) 5/9/91
+ */
+
+/*
+ * Adapted for NetBSD/amd64 by fvdl@wasabisystems.com.
+ */
+
+/*
+ * 386 Segmentation Data Structures and definitions
+ * William F. Jolitz (william@ernie.berkeley.edu) 6/20/1989
+ */
+
+#ifndef _AMD64_SEGMENTS_H_
+#define _AMD64_SEGMENTS_H_
+
+/*
+ * Selectors
+ */
+
+#define ISPL(s) ((s) & SEL_RPL) /* what is the priority level of a selector */
+#define SEL_KPL 0 /* kernel privilege level */
+#define SEL_UPL 3 /* user privilege level */
+#define SEL_RPL 3 /* requester's privilege level mask */
+#define ISLDT(s) ((s) & SEL_LDT) /* is it local or global */
+#define SEL_LDT 4 /* local descriptor table */
+
+/* Dynamically allocated TSSs and LDTs start (byte offset) */
+#define SYSSEL_START (NGDT_MEM << 3)
+#define DYNSEL_START (SYSSEL_START + (NGDT_SYS << 4))
+
+/*
+ * These define the index not from the start of the GDT, but from
+ * the part of the GDT that they're allocated from.
+ * First NGDT_MEM entries are 8-byte descriptors for CS and DS.
+ * Next NGDT_SYS entries are 16-byte descriptors defining LDTs.
+ *
+ * The rest is 16-byte descriptors for TSS and LDT.
+ */
+
+#define IDXSEL(s) (((s) >> 3) & 0x1fff)
+#define IDXDYNSEL(s) ((((s) & ~SEL_RPL) - DYNSEL_START) >> 4)
+
+#define GSEL(s,r) (((s) << 3) | r)
+#define GSYSSEL(s,r) ((((s) << 4) + SYSSEL_START) | r)
+#define GDYNSEL(s,r) ((((s) << 4) + DYNSEL_START) | r | SEL_KPL)
+
+#define LSEL(s,r) ((s) | r | SEL_LDT)
+
+#define USERMODE(c, f) (ISPL(c) == SEL_UPL)
+#define KERNELMODE(c, f) (ISPL(c) == SEL_KPL)
+
+#ifndef _LOCORE
+
+/*
+ * Memory and System segment descriptors
+ */
+
+/*
+ * Below is used for TSS and LDT.
+ */
+struct sys_segment_descriptor {
+/*BITFIELDTYPE*/ u_int64_t sd_lolimit:16;/* segment extent (lsb) */
+/*BITFIELDTYPE*/ u_int64_t sd_lobase:24;/* segment base address (lsb) */
+/*BITFIELDTYPE*/ u_int64_t sd_type:5; /* segment type */
+/*BITFIELDTYPE*/ u_int64_t sd_dpl:2; /* segment descriptor priority level */
+/*BITFIELDTYPE*/ u_int64_t sd_p:1; /* segment descriptor present */
+/*BITFIELDTYPE*/ u_int64_t sd_hilimit:4;/* segment extent (msb) */
+/*BITFIELDTYPE*/ u_int64_t sd_xx1:3; /* avl, long and def32 (not used) */
+/*BITFIELDTYPE*/ u_int64_t sd_gran:1; /* limit granularity (byte/page) */
+/*BITFIELDTYPE*/ u_int64_t sd_hibase:40;/* segment base address (msb) */
+/*BITFIELDTYPE*/ u_int64_t sd_xx2:8; /* reserved */
+/*BITFIELDTYPE*/ u_int64_t sd_zero:5; /* must be zero */
+/*BITFIELDTYPE*/ u_int64_t sd_xx3:19; /* reserved */
+} __attribute__((packed));
+
+/*
+ * Below is used for cs, ds, etc.
+ */
+struct mem_segment_descriptor {
+ unsigned sd_lolimit:16; /* segment extent (lsb) */
+ unsigned sd_lobase:24; /* 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_avl:1; /* available */
+ unsigned sd_long:1; /* long mode */
+ unsigned sd_def32:1; /* default 32 vs 16 bit size */
+ unsigned sd_gran:1; /* limit granularity (byte/page) */
+ unsigned sd_hibase:8; /* segment base address (msb) */
+} __attribute__((packed));
+
+/*
+ * Gate descriptors (e.g. indirect descriptors)
+ */
+struct gate_descriptor {
+/*BITFIELDTYPE*/ u_int64_t gd_looffset:16;/* gate offset (lsb) */
+/*BITFIELDTYPE*/ u_int64_t gd_selector:16;/* gate segment selector */
+/*BITFIELDTYPE*/ u_int64_t gd_ist:3; /* IST select */
+/*BITFIELDTYPE*/ u_int64_t gd_xx1:5; /* reserved */
+/*BITFIELDTYPE*/ u_int64_t gd_type:5; /* segment type */
+/*BITFIELDTYPE*/ u_int64_t gd_dpl:2; /* segment descriptor priority level */
+/*BITFIELDTYPE*/ u_int64_t gd_p:1; /* segment descriptor present */
+/*BITFIELDTYPE*/ u_int64_t gd_hioffset:48;/* gate offset (msb) */
+/*BITFIELDTYPE*/ u_int64_t gd_xx2:8; /* reserved */
+/*BITFIELDTYPE*/ u_int64_t gd_zero:5; /* must be zero */
+/*BITFIELDTYPE*/ u_int64_t gd_xx3:19; /* reserved */
+} __attribute__((packed));
+
+/*
+ * region descriptors, used to load gdt/idt tables before segments yet exist.
+ */
+struct region_descriptor {
+ u_int16_t rd_limit; /* segment extent */
+ u_int64_t rd_base; /* base address */
+} __attribute__((packed));
+
+#ifdef _KERNEL
+#if 0
+extern struct sys_segment_descriptor *ldt;
+#endif
+extern struct gate_descriptor *idt;
+extern char *gdtstore;
+extern char *ldtstore;
+
+void setgate(struct gate_descriptor *, void *, int, int, int, int);
+void unsetgate(struct gate_descriptor *);
+void setregion(struct region_descriptor *, void *, u_int16_t);
+void set_sys_segment(struct sys_segment_descriptor *, void *, size_t,
+ int, int, int);
+void set_mem_segment(struct mem_segment_descriptor *, void *, size_t,
+ int, int, int, int, int);
+int idt_vec_alloc(int, int);
+void idt_vec_set(int, void (*)(void));
+void idt_vec_free(int);
+void cpu_init_idt(void);
+
+#endif /* _KERNEL */
+
+#endif /* !_LOCORE */
+
+/* system segments and gate types */
+#define SDT_SYSNULL 0 /* system null */
+#define SDT_SYS286TSS 1 /* system 286 TSS available */
+#define SDT_SYSLDT 2 /* system local descriptor table */
+#define SDT_SYS286BSY 3 /* system 286 TSS busy */
+#define SDT_SYS286CGT 4 /* system 286 call gate */
+#define SDT_SYSTASKGT 5 /* system task gate */
+#define SDT_SYS286IGT 6 /* system 286 interrupt gate */
+#define SDT_SYS286TGT 7 /* system 286 trap gate */
+#define SDT_SYSNULL2 8 /* system null again */
+#define SDT_SYS386TSS 9 /* system 386 TSS available */
+#define SDT_SYSNULL3 10 /* system null again */
+#define SDT_SYS386BSY 11 /* system 386 TSS busy */
+#define SDT_SYS386CGT 12 /* system 386 call gate */
+#define SDT_SYSNULL4 13 /* system null again */
+#define SDT_SYS386IGT 14 /* system 386 interrupt gate */
+#define SDT_SYS386TGT 15 /* system 386 trap gate */
+
+/* memory segment types */
+#define SDT_MEMRO 16 /* memory read only */
+#define SDT_MEMROA 17 /* memory read only accessed */
+#define SDT_MEMRW 18 /* memory read write */
+#define SDT_MEMRWA 19 /* memory read write accessed */
+#define SDT_MEMROD 20 /* memory read only expand dwn limit */
+#define SDT_MEMRODA 21 /* memory read only expand dwn limit accessed */
+#define SDT_MEMRWD 22 /* memory read write expand dwn limit */
+#define SDT_MEMRWDA 23 /* memory read write expand dwn limit acessed */
+#define SDT_MEME 24 /* memory execute only */
+#define SDT_MEMEA 25 /* memory execute only accessed */
+#define SDT_MEMER 26 /* memory execute read */
+#define SDT_MEMERA 27 /* memory execute read accessed */
+#define SDT_MEMEC 28 /* memory execute only conforming */
+#define SDT_MEMEAC 29 /* memory execute only accessed conforming */
+#define SDT_MEMERC 30 /* memory execute read conforming */
+#define SDT_MEMERAC 31 /* memory execute read accessed conforming */
+
+/* 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))
+
+/*
+ * 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 */
+
+/*
+ * Entries in the Interrupt Descriptor Table (IDT)
+ */
+#define NIDT 256
+#define NRSVIDT 32 /* reserved entries for cpu exceptions */
+
+/*
+ * Entries in the Global Descriptor Table (GDT)
+ * The code and data descriptors must come first. There
+ * are NGDT_MEM of them.
+ *
+ * Then come the predefined LDT (and possibly TSS) descriptors.
+ * There are NGDT_SYS of them.
+ */
+#define GNULL_SEL 0 /* Null descriptor */
+#define GCODE_SEL 1 /* Kernel code descriptor */
+#define GDATA_SEL 2 /* Kernel data descriptor */
+#define GUCODE_SEL 3 /* User code descriptor */
+#define GUDATA_SEL 4 /* User data descriptor */
+#define GAPM32CODE_SEL 5
+#define GAPM16CODE_SEL 6
+#define GAPMDATA_SEL 7
+#define GBIOSCODE_SEL 8
+#define GBIOSDATA_SEL 9
+#define GPNPBIOSCODE_SEL 10
+#define GPNPBIOSDATA_SEL 11
+#define GPNPBIOSSCRATCH_SEL 12
+#define GPNPBIOSTRAMP_SEL 13
+#define GUCODE32_SEL 14
+#define GUDATA32_SEL 15
+#define NGDT_MEM 16
+
+#define GLDT_SEL 0 /* Default LDT descriptor */
+#define NGDT_SYS 1
+
+#define GDT_SYS_OFFSET (NGDT_MEM << 3)
+
+#define GDT_ADDR_MEM(s,i) \
+ ((struct mem_segment_descriptor *)((s) + ((i) << 3)))
+#define GDT_ADDR_SYS(s,i) \
+ ((struct sys_segment_descriptor *)((s) + (((i) << 4) + SYSSEL_START)))
+
+/*
+ * Byte offsets in the Local Descriptor Table (LDT)
+ * Strange order because of syscall/sysret insns
+ */
+#define LSYS5CALLS_SEL 0 /* iBCS system call gate */
+#define LUCODE32_SEL 8 /* 32 bit user code descriptor */
+#define LUDATA_SEL 16 /* User data descriptor */
+#define LUCODE_SEL 24 /* User code descriptor */
+#define LSOL26CALLS_SEL 32 /* Solaris 2.6 system call gate */
+#define LUDATA32_SEL 56 /* 32 bit user data descriptor (needed?)*/
+#define LBSDICALLS_SEL 128 /* BSDI system call gate */
+
+#define LDT_SIZE 144
+
+#define LSYSRETBASE_SEL LUCODE32_SEL
+
+#endif /* _AMD64_SEGMENTS_H_ */
diff --git a/sys/arch/amd64/include/setjmp.h b/sys/arch/amd64/include/setjmp.h
new file mode 100644
index 00000000000..01d6066450f
--- /dev/null
+++ b/sys/arch/amd64/include/setjmp.h
@@ -0,0 +1,21 @@
+/* $OpenBSD: setjmp.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: setjmp.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */
+
+/*
+ * machine/setjmp.h: machine dependent setjmp-related information.
+ * These are only the callee-saved registers, code calling setjmp
+ * will expect the rest to be clobbered anyway.
+ */
+
+#define _JB_RBX 0
+#define _JB_RBP 1
+#define _JB_R12 2
+#define _JB_R13 3
+#define _JB_R14 4
+#define _JB_R15 5
+#define _JB_RSP 6
+#define _JB_PC 7
+#define _JB_SIGFLAG 8
+#define _JB_SIGMASK 9
+
+#define _JBLEN 11 /* size, in longs, of a jmp_buf */
diff --git a/sys/arch/amd64/include/signal.h b/sys/arch/amd64/include/signal.h
new file mode 100644
index 00000000000..79227ad5f6e
--- /dev/null
+++ b/sys/arch/amd64/include/signal.h
@@ -0,0 +1,88 @@
+/* $NetBSD: signal.h,v 1.2 2003/04/28 23:16:17 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)signal.h 7.16 (Berkeley) 3/17/91
+ */
+
+#ifndef _AMD64_SIGNAL_H_
+#define _AMD64_SIGNAL_H_
+
+typedef int sig_atomic_t;
+
+#ifndef _ANSI_SOURCE
+#include <machine/trap.h>
+
+/*
+ * Information pushed on stack when a signal is delivered.
+ * This is used by the kernel to restore state following
+ * execution of the signal handler. It is also made available
+ * to the handler to allow it to restore state properly if
+ * a non-standard exit is performed.
+ */
+struct sigcontext {
+ /* plain match trapframe */
+ long sc_rdi;
+ long sc_rsi;
+ long sc_rdx;
+ long sc_rcx;
+ long sc_r8;
+ long sc_r9;
+ long sc_r10;
+ long sc_r11;
+ long sc_r12;
+ long sc_r13;
+ long sc_r14;
+ long sc_r15;
+ long sc_rbp;
+ long sc_rbx;
+ long sc_rax;
+ long sc_gs;
+ long sc_fs;
+ long sc_es;
+ long sc_ds;
+ long sc_trapno;
+ long sc_err;
+ long sc_rip;
+ long sc_cs;
+ long sc_rflags;
+ long sc_rsp;
+ long sc_ss;
+
+ int sc_onstack;
+ int sc_mask;
+};
+
+#endif /* !_ANSI_SOURCE */
+#endif /* !_AMD64_SIGNAL_H_ */
+
diff --git a/sys/arch/amd64/include/specialreg.h b/sys/arch/amd64/include/specialreg.h
new file mode 100644
index 00000000000..ef6db41a1fc
--- /dev/null
+++ b/sys/arch/amd64/include/specialreg.h
@@ -0,0 +1,604 @@
+/* $OpenBSD: specialreg.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: specialreg.h,v 1.1 2003/04/26 18:39:48 fvdl Exp $ */
+/* $NetBSD: x86/specialreg.h,v 1.2 2003/04/25 21:54:30 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)specialreg.h 7.1 (Berkeley) 5/9/91
+ */
+
+/*
+ * Bits in 386 special registers:
+ */
+#define CR0_PE 0x00000001 /* Protected mode Enable */
+#define CR0_MP 0x00000002 /* "Math" Present (NPX or NPX emulator) */
+#define CR0_EM 0x00000004 /* EMulate non-NPX coproc. (trap ESC only) */
+#define CR0_TS 0x00000008 /* Task Switched (if MP, trap ESC and WAIT) */
+#define CR0_ET 0x00000010 /* Extension Type (387 (if set) vs 287) */
+#define CR0_PG 0x80000000 /* PaGing enable */
+
+/*
+ * Bits in 486 special registers:
+ */
+#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */
+#define CR0_WP 0x00010000 /* Write Protect (honor PG_RW in all modes) */
+#define CR0_AM 0x00040000 /* Alignment Mask (set to enable AC flag) */
+#define CR0_NW 0x20000000 /* Not Write-through */
+#define CR0_CD 0x40000000 /* Cache Disable */
+
+/*
+ * Cyrix 486 DLC special registers, accessible as IO ports.
+ */
+#define CCR0 0xc0 /* configuration control register 0 */
+#define CCR0_NC0 0x01 /* first 64K of each 1M memory region is non-cacheable */
+#define CCR0_NC1 0x02 /* 640K-1M region is non-cacheable */
+#define CCR0_A20M 0x04 /* enables A20M# input pin */
+#define CCR0_KEN 0x08 /* enables KEN# input pin */
+#define CCR0_FLUSH 0x10 /* enables FLUSH# input pin */
+#define CCR0_BARB 0x20 /* flushes internal cache when entering hold state */
+#define CCR0_CO 0x40 /* cache org: 1=direct mapped, 0=2x set assoc */
+#define CCR0_SUSPEND 0x80 /* enables SUSP# and SUSPA# pins */
+
+#define CCR1 0xc1 /* configuration control register 1 */
+#define CCR1_RPL 0x01 /* enables RPLSET and RPLVAL# pins */
+/* the remaining 7 bits of this register are reserved */
+
+/*
+ * bits in the pentiums %cr4 register:
+ */
+
+#define CR4_VME 0x00000001 /* virtual 8086 mode extension enable */
+#define CR4_PVI 0x00000002 /* protected mode virtual interrupt enable */
+#define CR4_TSD 0x00000004 /* restrict RDTSC instruction to cpl 0 only */
+#define CR4_DE 0x00000008 /* debugging extension */
+#define CR4_PSE 0x00000010 /* large (4MB) page size enable */
+#define CR4_PAE 0x00000020 /* physical address extension enable */
+#define CR4_MCE 0x00000040 /* machine check enable */
+#define CR4_PGE 0x00000080 /* page global enable */
+#define CR4_PCE 0x00000100 /* enable RDPMC instruction for all cpls */
+#define CR4_OSFXSR 0x00000200 /* enable fxsave/fxrestor and SSE */
+#define CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */
+
+/*
+ * CPUID "features" bits:
+ */
+
+#define CPUID_FPU 0x00000001 /* processor has an FPU? */
+#define CPUID_VME 0x00000002 /* has virtual mode (%cr4's VME/PVI) */
+#define CPUID_DE 0x00000004 /* has debugging extension */
+#define CPUID_PSE 0x00000008 /* has page 4MB page size extension */
+#define CPUID_TSC 0x00000010 /* has time stamp counter */
+#define CPUID_MSR 0x00000020 /* has mode specific registers */
+#define CPUID_PAE 0x00000040 /* has phys address extension */
+#define CPUID_MCE 0x00000080 /* has machine check exception */
+#define CPUID_CX8 0x00000100 /* has CMPXCHG8B instruction */
+#define CPUID_APIC 0x00000200 /* has enabled APIC */
+#define CPUID_B10 0x00000400 /* reserved, MTRR */
+#define CPUID_SEP 0x00000800 /* has SYSENTER/SYSEXIT extension */
+#define CPUID_MTRR 0x00001000 /* has memory type range register */
+#define CPUID_PGE 0x00002000 /* has page global extension */
+#define CPUID_MCA 0x00004000 /* has machine check architecture */
+#define CPUID_CMOV 0x00008000 /* has CMOVcc instruction */
+#define CPUID_PAT 0x00010000 /* Page Attribute Table */
+#define CPUID_PSE36 0x00020000 /* 36-bit PSE */
+#define CPUID_PN 0x00040000 /* processor serial number */
+#define CPUID_CFLUSH 0x00080000 /* CFLUSH insn supported */
+#define CPUID_B20 0x00100000 /* reserved */
+#define CPUID_DS 0x00200000 /* Debug Store */
+#define CPUID_ACPI 0x00400000 /* ACPI performance modulation regs */
+#define CPUID_MMX 0x00800000 /* MMX supported */
+#define CPUID_FXSR 0x01000000 /* fast FP/MMX save/restore */
+#define CPUID_SSE 0x02000000 /* streaming SIMD extensions */
+#define CPUID_SSE2 0x04000000 /* streaming SIMD extensions #2 */
+#define CPUID_SS 0x08000000 /* self-snoop */
+#define CPUID_HTT 0x10000000 /* Hyper-Threading Technology */
+#define CPUID_TM 0x20000000 /* thermal monitor (TCC) */
+#define CPUID_IA64 0x40000000 /* IA-64 architecture */
+#define CPUID_SBF 0x80000000 /* signal break on FERR */
+
+#define CPUID_FLAGS1 "\20\1FPU\2VME\3DE\4PSE\5TSC\6MSR\7PAE" \
+ "\10MCE\11CX8\12APIC\13B10\14SEP\15MTRR"
+#define CPUID_MASK1 0x00001fff
+#define CPUID_FLAGS2 "\20\16PGE\17MCA\20CMOV\21PAT\22PSE36\23PN\24CFLUSH" \
+ "\25B20\26DS\27ACPI\30MMX"
+#define CPUID_MASK2 0x00ffe000
+#define CPUID_FLAGS3 "\20\31FXSR\32SSE\33SSE2\34SS\35HTT\36TM\37IA64\40SBF"
+#define CPUID_MASK3 0xff000000
+
+/*
+ * AMD/VIA processor specific flags.
+ */
+
+#define CPUID_MPC 0x00080000 /* Multiprocessing Capable */
+#define CPUID_NXE 0x00100000 /* No-Execute Extension */
+#define CPUID_MMXX 0x00400000 /* AMD MMX Extensions */
+#define CPUID_3DNOW2 0x40000000 /* 3DNow! Instruction Extension */
+#define CPUID_3DNOW 0x80000000 /* 3DNow! Instructions */
+
+#define CPUID_EXT_FLAGS2 "\20\16PGE\17MCA\20CMOV\21PAT\22PSE36\23PN" \
+ "\24MPC\25NXE\26B21\27MMXX\30MMX"
+#define CPUID_EXT_FLAGS3 "\20\31FXSR\32SSE\33SSE2\34B27\35B28\36LONG" \
+ "\0373DNOW2\0403DNOW"
+
+#define CPUID2FAMILY(cpuid) (((cpuid) >> 8) & 15)
+#define CPUID2MODEL(cpuid) (((cpuid) >> 4) & 15)
+#define CPUID2STEPPING(cpuid) ((cpuid) & 15)
+
+#define CPUID(code, eax, ebx, ecx, edx) \
+ __asm("cpuid" \
+ : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \
+ : "a" (code));
+
+
+/*
+ * Model-specific registers for the i386 family
+ */
+#define MSR_P5_MC_ADDR 0x000 /* P5 only */
+#define MSR_P5_MC_TYPE 0x001 /* P5 only */
+#define MSR_TSC 0x010
+#define MSR_CESR 0x011 /* P5 only (trap on P6) */
+#define MSR_CTR0 0x012 /* P5 only (trap on P6) */
+#define MSR_CTR1 0x013 /* P5 only (trap on P6) */
+#define MSR_APICBASE 0x01b
+#define MSR_EBL_CR_POWERON 0x02a
+#define MSR_TEST_CTL 0x033
+#define MSR_BIOS_UPDT_TRIG 0x079
+#define MSR_BBL_CR_D0 0x088 /* PII+ only */
+#define MSR_BBL_CR_D1 0x089 /* PII+ only */
+#define MSR_BBL_CR_D2 0x08a /* PII+ only */
+#define MSR_BIOS_SIGN 0x08b
+#define MSR_PERFCTR0 0x0c1
+#define MSR_PERFCTR1 0x0c2
+#define MSR_MTRRcap 0x0fe
+#define MSR_BBL_CR_ADDR 0x116 /* PII+ only */
+#define MSR_BBL_CR_DECC 0x118 /* PII+ only */
+#define MSR_BBL_CR_CTL 0x119 /* PII+ only */
+#define MSR_BBL_CR_TRIG 0x11a /* PII+ only */
+#define MSR_BBL_CR_BUSY 0x11b /* PII+ only */
+#define MSR_BBL_CR_CTR3 0x11e /* PII+ only */
+#define MSR_SYSENTER_CS 0x174 /* PII+ only */
+#define MSR_SYSENTER_ESP 0x175 /* PII+ only */
+#define MSR_SYSENTER_EIP 0x176 /* PII+ only */
+#define MSR_MCG_CAP 0x179
+#define MSR_MCG_STATUS 0x17a
+#define MSR_MCG_CTL 0x17b
+#define MSR_EVNTSEL0 0x186
+#define MSR_EVNTSEL1 0x187
+#define MSR_DEBUGCTLMSR 0x1d9
+#define MSR_LASTBRANCHFROMIP 0x1db
+#define MSR_LASTBRANCHTOIP 0x1dc
+#define MSR_LASTINTFROMIP 0x1dd
+#define MSR_LASTINTTOIP 0x1de
+#define MSR_ROB_CR_BKUPTMPDR6 0x1e0
+#define MSR_MTRRphysBase0 0x200
+#define MSR_MTRRphysMask0 0x201
+#define MSR_MTRRphysBase1 0x202
+#define MSR_MTRRphysMask1 0x203
+#define MSR_MTRRphysBase2 0x204
+#define MSR_MTRRphysMask2 0x205
+#define MSR_MTRRphysBase3 0x206
+#define MSR_MTRRphysMask3 0x207
+#define MSR_MTRRphysBase4 0x208
+#define MSR_MTRRphysMask4 0x209
+#define MSR_MTRRphysBase5 0x20a
+#define MSR_MTRRphysMask5 0x20b
+#define MSR_MTRRphysBase6 0x20c
+#define MSR_MTRRphysMask6 0x20d
+#define MSR_MTRRphysBase7 0x20e
+#define MSR_MTRRphysMask7 0x20f
+#define MSR_MTRRfix64K_00000 0x250
+#define MSR_MTRRfix16K_80000 0x258
+#define MSR_MTRRfix16K_A0000 0x259
+#define MSR_MTRRfix4K_C0000 0x268
+#define MSR_MTRRfix4K_C8000 0x269
+#define MSR_MTRRfix4K_D0000 0x26a
+#define MSR_MTRRfix4K_D8000 0x26b
+#define MSR_MTRRfix4K_E0000 0x26c
+#define MSR_MTRRfix4K_E8000 0x26d
+#define MSR_MTRRfix4K_F0000 0x26e
+#define MSR_MTRRfix4K_F8000 0x26f
+#define MSR_MTRRdefType 0x2ff
+#define MSR_MC0_CTL 0x400
+#define MSR_MC0_STATUS 0x401
+#define MSR_MC0_ADDR 0x402
+#define MSR_MC0_MISC 0x403
+#define MSR_MC1_CTL 0x404
+#define MSR_MC1_STATUS 0x405
+#define MSR_MC1_ADDR 0x406
+#define MSR_MC1_MISC 0x407
+#define MSR_MC2_CTL 0x408
+#define MSR_MC2_STATUS 0x409
+#define MSR_MC2_ADDR 0x40a
+#define MSR_MC2_MISC 0x40b
+#define MSR_MC4_CTL 0x40c
+#define MSR_MC4_STATUS 0x40d
+#define MSR_MC4_ADDR 0x40e
+#define MSR_MC4_MISC 0x40f
+#define MSR_MC3_CTL 0x410
+#define MSR_MC3_STATUS 0x411
+#define MSR_MC3_ADDR 0x412
+#define MSR_MC3_MISC 0x413
+
+/*
+ * AMD K6/K7 MSRs.
+ */
+#define MSR_K6_UWCCR 0xc0000085
+#define MSR_K7_EVNTSEL0 0xc0010000
+#define MSR_K7_EVNTSEL1 0xc0010001
+#define MSR_K7_EVNTSEL2 0xc0010002
+#define MSR_K7_EVNTSEL3 0xc0010003
+#define MSR_K7_PERFCTR0 0xc0010004
+#define MSR_K7_PERFCTR1 0xc0010005
+#define MSR_K7_PERFCTR2 0xc0010006
+#define MSR_K7_PERFCTR3 0xc0010007
+
+/*
+ * Constants related to MTRRs
+ */
+#define MTRR_N64K 8 /* numbers of fixed-size entries */
+#define MTRR_N16K 16
+#define MTRR_N4K 64
+
+/*
+ * the following four 3-byte registers control the non-cacheable regions.
+ * These registers must be written as three separate bytes.
+ *
+ * NCRx+0: A31-A24 of starting address
+ * NCRx+1: A23-A16 of starting address
+ * NCRx+2: A15-A12 of starting address | NCR_SIZE_xx.
+ *
+ * The non-cacheable region's starting address must be aligned to the
+ * size indicated by the NCR_SIZE_xx field.
+ */
+#define NCR1 0xc4
+#define NCR2 0xc7
+#define NCR3 0xca
+#define NCR4 0xcd
+
+#define NCR_SIZE_0K 0
+#define NCR_SIZE_4K 1
+#define NCR_SIZE_8K 2
+#define NCR_SIZE_16K 3
+#define NCR_SIZE_32K 4
+#define NCR_SIZE_64K 5
+#define NCR_SIZE_128K 6
+#define NCR_SIZE_256K 7
+#define NCR_SIZE_512K 8
+#define NCR_SIZE_1M 9
+#define NCR_SIZE_2M 10
+#define NCR_SIZE_4M 11
+#define NCR_SIZE_8M 12
+#define NCR_SIZE_16M 13
+#define NCR_SIZE_32M 14
+#define NCR_SIZE_4G 15
+
+/*
+ * Performance monitor events.
+ *
+ * Note that 586-class and 686-class CPUs have different performance
+ * monitors available, and they are accessed differently:
+ *
+ * 686-class: `rdpmc' instruction
+ * 586-class: `rdmsr' instruction, CESR MSR
+ *
+ * The descriptions of these events are too lenghy to include here.
+ * See Appendix A of "Intel Architecture Software Developer's
+ * Manual, Volume 3: System Programming" for more information.
+ */
+
+/*
+ * 586-class CESR MSR format. Lower 16 bits is CTR0, upper 16 bits
+ * is CTR1.
+ */
+
+#define PMC5_CESR_EVENT 0x003f
+#define PMC5_CESR_OS 0x0040
+#define PMC5_CESR_USR 0x0080
+#define PMC5_CESR_E 0x0100
+#define PMC5_CESR_P 0x0200
+
+#define PMC5_DATA_READ 0x00
+#define PMC5_DATA_WRITE 0x01
+#define PMC5_DATA_TLB_MISS 0x02
+#define PMC5_DATA_READ_MISS 0x03
+#define PMC5_DATA_WRITE_MISS 0x04
+#define PMC5_WRITE_M_E 0x05
+#define PMC5_DATA_LINES_WBACK 0x06
+#define PMC5_DATA_CACHE_SNOOP 0x07
+#define PMC5_DATA_CACHE_SNOOP_HIT 0x08
+#define PMC5_MEM_ACCESS_BOTH_PIPES 0x09
+#define PMC5_BANK_CONFLICTS 0x0a
+#define PMC5_MISALIGNED_DATA 0x0b
+#define PMC5_INST_READ 0x0c
+#define PMC5_INST_TLB_MISS 0x0d
+#define PMC5_INST_CACHE_MISS 0x0e
+#define PMC5_SEGMENT_REG_LOAD 0x0f
+#define PMC5_BRANCHES 0x12
+#define PMC5_BTB_HITS 0x13
+#define PMC5_BRANCH_TAKEN 0x14
+#define PMC5_PIPELINE_FLUSH 0x15
+#define PMC5_INST_EXECUTED 0x16
+#define PMC5_INST_EXECUTED_V_PIPE 0x17
+#define PMC5_BUS_UTILIZATION 0x18
+#define PMC5_WRITE_BACKUP_STALL 0x19
+#define PMC5_DATA_READ_STALL 0x1a
+#define PMC5_WRITE_E_M_STALL 0x1b
+#define PMC5_LOCKED_BUS 0x1c
+#define PMC5_IO_CYCLE 0x1d
+#define PMC5_NONCACHE_MEM_READ 0x1e
+#define PMC5_AGI_STALL 0x1f
+#define PMC5_FLOPS 0x22
+#define PMC5_BP0_MATCH 0x23
+#define PMC5_BP1_MATCH 0x24
+#define PMC5_BP2_MATCH 0x25
+#define PMC5_BP3_MATCH 0x26
+#define PMC5_HARDWARE_INTR 0x27
+#define PMC5_DATA_RW 0x28
+#define PMC5_DATA_RW_MISS 0x29
+
+/*
+ * 686-class Event Selector MSR format.
+ */
+
+#define PMC6_EVTSEL_EVENT 0x000000ff
+#define PMC6_EVTSEL_UNIT 0x0000ff00
+#define PMC6_EVTSEL_UNIT_SHIFT 8
+#define PMC6_EVTSEL_USR (1 << 16)
+#define PMC6_EVTSEL_OS (1 << 17)
+#define PMC6_EVTSEL_E (1 << 18)
+#define PMC6_EVTSEL_PC (1 << 19)
+#define PMC6_EVTSEL_INT (1 << 20)
+#define PMC6_EVTSEL_EN (1 << 22) /* PerfEvtSel0 only */
+#define PMC6_EVTSEL_INV (1 << 23)
+#define PMC6_EVTSEL_COUNTER_MASK 0xff000000
+#define PMC6_EVTSEL_COUNTER_MASK_SHIFT 24
+
+/* Data Cache Unit */
+#define PMC6_DATA_MEM_REFS 0x43
+#define PMC6_DCU_LINES_IN 0x45
+#define PMC6_DCU_M_LINES_IN 0x46
+#define PMC6_DCU_M_LINES_OUT 0x47
+#define PMC6_DCU_MISS_OUTSTANDING 0x48
+
+/* Instruction Fetch Unit */
+#define PMC6_IFU_IFETCH 0x80
+#define PMC6_IFU_IFETCH_MISS 0x81
+#define PMC6_ITLB_MISS 0x85
+#define PMC6_IFU_MEM_STALL 0x86
+#define PMC6_ILD_STALL 0x87
+
+/* L2 Cache */
+#define PMC6_L2_IFETCH 0x28
+#define PMC6_L2_LD 0x29
+#define PMC6_L2_ST 0x2a
+#define PMC6_L2_LINES_IN 0x24
+#define PMC6_L2_LINES_OUT 0x26
+#define PMC6_L2_M_LINES_INM 0x25
+#define PMC6_L2_M_LINES_OUTM 0x27
+#define PMC6_L2_RQSTS 0x2e
+#define PMC6_L2_ADS 0x21
+#define PMC6_L2_DBUS_BUSY 0x22
+#define PMC6_L2_DBUS_BUSY_RD 0x23
+
+/* External Bus Logic */
+#define PMC6_BUS_DRDY_CLOCKS 0x62
+#define PMC6_BUS_LOCK_CLOCKS 0x63
+#define PMC6_BUS_REQ_OUTSTANDING 0x60
+#define PMC6_BUS_TRAN_BRD 0x65
+#define PMC6_BUS_TRAN_RFO 0x66
+#define PMC6_BUS_TRANS_WB 0x67
+#define PMC6_BUS_TRAN_IFETCH 0x68
+#define PMC6_BUS_TRAN_INVAL 0x69
+#define PMC6_BUS_TRAN_PWR 0x6a
+#define PMC6_BUS_TRANS_P 0x6b
+#define PMC6_BUS_TRANS_IO 0x6c
+#define PMC6_BUS_TRAN_DEF 0x6d
+#define PMC6_BUS_TRAN_BURST 0x6e
+#define PMC6_BUS_TRAN_ANY 0x70
+#define PMC6_BUS_TRAN_MEM 0x6f
+#define PMC6_BUS_DATA_RCV 0x64
+#define PMC6_BUS_BNR_DRV 0x61
+#define PMC6_BUS_HIT_DRV 0x7a
+#define PMC6_BUS_HITM_DRDV 0x7b
+#define PMC6_BUS_SNOOP_STALL 0x7e
+
+/* Floating Point Unit */
+#define PMC6_FLOPS 0xc1
+#define PMC6_FP_COMP_OPS_EXE 0x10
+#define PMC6_FP_ASSIST 0x11
+#define PMC6_MUL 0x12
+#define PMC6_DIV 0x12
+#define PMC6_CYCLES_DIV_BUSY 0x14
+
+/* Memory Ordering */
+#define PMC6_LD_BLOCKS 0x03
+#define PMC6_SB_DRAINS 0x04
+#define PMC6_MISALIGN_MEM_REF 0x05
+#define PMC6_EMON_KNI_PREF_DISPATCHED 0x07 /* P-III only */
+#define PMC6_EMON_KNI_PREF_MISS 0x4b /* P-III only */
+
+/* Instruction Decoding and Retirement */
+#define PMC6_INST_RETIRED 0xc0
+#define PMC6_UOPS_RETIRED 0xc2
+#define PMC6_INST_DECODED 0xd0
+#define PMC6_EMON_KNI_INST_RETIRED 0xd8
+#define PMC6_EMON_KNI_COMP_INST_RET 0xd9
+
+/* Interrupts */
+#define PMC6_HW_INT_RX 0xc8
+#define PMC6_CYCLES_INT_MASKED 0xc6
+#define PMC6_CYCLES_INT_PENDING_AND_MASKED 0xc7
+
+/* Branches */
+#define PMC6_BR_INST_RETIRED 0xc4
+#define PMC6_BR_MISS_PRED_RETIRED 0xc5
+#define PMC6_BR_TAKEN_RETIRED 0xc9
+#define PMC6_BR_MISS_PRED_TAKEN_RET 0xca
+#define PMC6_BR_INST_DECODED 0xe0
+#define PMC6_BTB_MISSES 0xe2
+#define PMC6_BR_BOGUS 0xe4
+#define PMC6_BACLEARS 0xe6
+
+/* Stalls */
+#define PMC6_RESOURCE_STALLS 0xa2
+#define PMC6_PARTIAL_RAT_STALLS 0xd2
+
+/* Segment Register Loads */
+#define PMC6_SEGMENT_REG_LOADS 0x06
+
+/* Clocks */
+#define PMC6_CPU_CLK_UNHALTED 0x79
+
+/* MMX Unit */
+#define PMC6_MMX_INSTR_EXEC 0xb0 /* Celeron, P-II, P-IIX only */
+#define PMC6_MMX_SAT_INSTR_EXEC 0xb1 /* P-II and P-III only */
+#define PMC6_MMX_UOPS_EXEC 0xb2 /* P-II and P-III only */
+#define PMC6_MMX_INSTR_TYPE_EXEC 0xb3 /* P-II and P-III only */
+#define PMC6_FP_MMX_TRANS 0xcc /* P-II and P-III only */
+#define PMC6_MMX_ASSIST 0xcd /* P-II and P-III only */
+#define PMC6_MMX_INSTR_RET 0xc3 /* P-II only */
+
+/* Segment Register Renaming */
+#define PMC6_SEG_RENAME_STALLS 0xd4 /* P-II and P-III only */
+#define PMC6_SEG_REG_RENAMES 0xd5 /* P-II and P-III only */
+#define PMC6_RET_SEG_RENAMES 0xd6 /* P-II and P-III only */
+
+/*
+ * AMD K7 Event Selector MSR format.
+ */
+
+#define K7_EVTSEL_EVENT 0x000000ff
+#define K7_EVTSEL_UNIT 0x0000ff00
+#define K7_EVTSEL_UNIT_SHIFT 8
+#define K7_EVTSEL_USR (1 << 16)
+#define K7_EVTSEL_OS (1 << 17)
+#define K7_EVTSEL_E (1 << 18)
+#define K7_EVTSEL_PC (1 << 19)
+#define K7_EVTSEL_INT (1 << 20)
+#define K7_EVTSEL_EN (1 << 22)
+#define K7_EVTSEL_INV (1 << 23)
+#define K7_EVTSEL_COUNTER_MASK 0xff000000
+#define K7_EVTSEL_COUNTER_MASK_SHIFT 24
+
+/* Segment Register Loads */
+#define K7_SEGMENT_REG_LOADS 0x20
+
+#define K7_STORES_TO_ACTIVE_INST_STREAM 0x21
+
+/* Data Cache Unit */
+#define K7_DATA_CACHE_ACCESS 0x40
+#define K7_DATA_CACHE_MISS 0x41
+#define K7_DATA_CACHE_REFILL 0x42
+#define K7_DATA_CACHE_REFILL_SYSTEM 0x43
+#define K7_DATA_CACHE_WBACK 0x44
+#define K7_L2_DTLB_HIT 0x45
+#define K7_L2_DTLB_MISS 0x46
+#define K7_MISALIGNED_DATA_REF 0x47
+#define K7_SYSTEM_REQUEST 0x64
+#define K7_SYSTEM_REQUEST_TYPE 0x65
+
+#define K7_SNOOP_HIT 0x73
+#define K7_SINGLE_BIT_ECC_ERROR 0x74
+#define K7_CACHE_LINE_INVAL 0x75
+#define K7_CYCLES_PROCESSOR_IS_RUNNING 0x76
+#define K7_L2_REQUEST 0x79
+#define K7_L2_REQUEST_BUSY 0x7a
+
+/* Instruction Fetch Unit */
+#define K7_IFU_IFETCH 0x80
+#define K7_IFU_IFETCH_MISS 0x81
+#define K7_IFU_REFILL_FROM_L2 0x82
+#define K7_IFU_REFILL_FROM_SYSTEM 0x83
+#define K7_ITLB_L1_MISS 0x84
+#define K7_ITLB_L2_MISS 0x85
+#define K7_SNOOP_RESYNC 0x86
+#define K7_IFU_STALL 0x87
+
+#define K7_RETURN_STACK_HITS 0x88
+#define K7_RETURN_STACK_OVERFLOW 0x89
+
+/* Retired */
+#define K7_RETIRED_INST 0xc0
+#define K7_RETIRED_OPS 0xc1
+#define K7_RETIRED_BRANCHES 0xc2
+#define K7_RETIRED_BRANCH_MISPREDICTED 0xc3
+#define K7_RETIRED_TAKEN_BRANCH 0xc4
+#define K7_RETIRED_TAKEN_BRANCH_MISPREDICTED 0xc5
+#define K7_RETIRED_FAR_CONTROL_TRANSFER 0xc6
+#define K7_RETIRED_RESYNC_BRANCH 0xc7
+#define K7_RETIRED_NEAR_RETURNS 0xc8
+#define K7_RETIRED_NEAR_RETURNS_MISPREDICTED 0xc9
+#define K7_RETIRED_INDIRECT_MISPREDICTED 0xca
+
+/* Interrupts */
+#define K7_CYCLES_INT_MASKED 0xcd
+#define K7_CYCLES_INT_PENDING_AND_MASKED 0xce
+#define K7_HW_INTR_RECV 0xcf
+
+#define K7_INSTRUCTION_DECODER_EMPTY 0xd0
+#define K7_DISPATCH_STALLS 0xd1
+#define K7_BRANCH_ABORTS_TO_RETIRE 0xd2
+#define K7_SERIALIZE 0xd3
+#define K7_SEGMENT_LOAD_STALL 0xd4
+#define K7_ICU_FULL 0xd5
+#define K7_RESERVATION_STATIONS_FULL 0xd6
+#define K7_FPU_FULL 0xd7
+#define K7_LS_FULL 0xd8
+#define K7_ALL_QUIET_STALL 0xd9
+#define K7_FAR_TRANSFER_OR_RESYNC_BRANCH_PENDING 0xda
+
+#define K7_BP0_MATCH 0xdc
+#define K7_BP1_MATCH 0xdd
+#define K7_BP2_MATCH 0xde
+#define K7_BP3_MATCH 0xdf
+
+/*
+ * Extended Feature Enable Register of the x86-64
+ */
+
+#define MSR_EFER 0xc0000080
+
+#define EFER_SCE 0x00000001 /* SYSCALL extension */
+#define EFER_LME 0x00000100 /* Long Mode Enabled */
+#define EFER_LMA 0x00000400 /* Long Mode Active */
+#define EFER_NXE 0x00000800 /* No-Execute Enable */
+#define EFER_FFXSR 0x00004000 /* Fast FXSAVE/FXRSTOR */
+
+#define MSR_STAR 0xc0000081 /* 32 bit syscall gate addr */
+#define MSR_LSTAR 0xc0000082 /* 64 bit syscall gate addr */
+#define MSR_CSTAR 0xc0000083 /* compat syscall gate addr */
+#define MSR_SFMASK 0xc0000084 /* flags to clear on syscall */
+
+#define MSR_FSBASE 0xc0000100 /* 64bit offset for fs: */
+#define MSR_GSBASE 0xc0000101 /* 64bit offset for gs: */
+#define MSR_KERNELGSBASE 0xc0000102 /* storage for swapgs ins */
diff --git a/sys/arch/amd64/include/spinlock.h b/sys/arch/amd64/include/spinlock.h
new file mode 100644
index 00000000000..be9e806ff5e
--- /dev/null
+++ b/sys/arch/amd64/include/spinlock.h
@@ -0,0 +1,10 @@
+/* $OpenBSD: spinlock.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+
+#ifndef _MACHINE_SPINLOCK_H_
+#define _MACHINE_SPINLOCK_H_
+
+#define _SPINLOCK_UNLOCKED (0)
+#define _SPINLOCK_LOCKED (1)
+typedef int _spinlock_lock_t;
+
+#endif
diff --git a/sys/arch/amd64/include/stdarg.h b/sys/arch/amd64/include/stdarg.h
new file mode 100644
index 00000000000..671b1e4d191
--- /dev/null
+++ b/sys/arch/amd64/include/stdarg.h
@@ -0,0 +1,57 @@
+/* $OpenBSD: stdarg.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: stdarg.h,v 1.2 2003/04/28 23:16:17 bjh21 Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)stdarg.h 8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _AMD64_STDARG_H_
+#define _AMD64_STDARG_H_
+
+#include <machine/ansi.h>
+
+typedef _BSD_VA_LIST_ va_list;
+
+#define va_start(ap, last) __builtin_stdarg_start((ap), (last))
+#define va_arg __builtin_va_arg
+#define va_end(ap) __builtin_va_end(ap)
+#define __va_copy(dest, src) __builtin_va_copy((dest), (src))
+
+#if !defined(_ANSI_SOURCE) && \
+ (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE) || \
+ defined(_ISOC99_SOURCE) || (__STDC_VERSION__ - 0) >= 199901L)
+#define va_copy(dest, src) __va_copy((dest), (src))
+#endif
+
+#endif /* !_AMD64_STDARG_H_ */
diff --git a/sys/arch/amd64/include/sysarch.h b/sys/arch/amd64/include/sysarch.h
new file mode 100644
index 00000000000..6ae6d006262
--- /dev/null
+++ b/sys/arch/amd64/include/sysarch.h
@@ -0,0 +1,120 @@
+/* $OpenBSD: sysarch.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: sysarch.h,v 1.1 2003/04/26 18:39:48 fvdl Exp $ */
+
+#ifndef _AMD64_SYSARCH_H_
+#define _AMD64_SYSARCH_H_
+
+/*
+ * Architecture specific syscalls (amd64)
+ */
+#define X86_64_GET_LDT 0
+#define X86_64_SET_LDT 1
+#define X86_64_IOPL 2
+#define X86_64_GET_IOPERM 3
+#define X86_64_SET_IOPERM 4
+#define X86_64_VM86 5
+#define X86_64_PMC_INFO 8
+#define X86_64_PMC_STARTSTOP 9
+#define X86_64_PMC_READ 10
+#define X86_64_GET_MTRR 11
+#define X86_64_SET_MTRR 12
+
+/*
+ * XXXfvdl todo.
+ */
+
+#if 0
+
+struct x86_64_get_ldt_args {
+ int start;
+ union descriptor *desc;
+ int num;
+};
+
+struct x86_64_set_ldt_args {
+ int start;
+ union descriptor *desc;
+ int num;
+};
+
+#endif
+
+struct x86_64_iopl_args {
+ int iopl;
+};
+
+#if 0
+
+struct x86_64_get_ioperm_args {
+ u_long *iomap;
+};
+
+struct x86_64_set_ioperm_args {
+ u_long *iomap;
+};
+
+struct x86_64_pmc_info_args {
+ int type;
+ int flags;
+};
+
+#define PMC_TYPE_NONE 0
+#define PMC_TYPE_I586 1
+#define PMC_TYPE_I686 2
+
+#define PMC_INFO_HASTSC 0x01
+
+#define PMC_NCOUNTERS 2
+
+struct x86_64_pmc_startstop_args {
+ int counter;
+ u_int64_t val;
+ u_int8_t event;
+ u_int8_t unit;
+ u_int8_t compare;
+ u_int8_t flags;
+};
+
+#define PMC_SETUP_KERNEL 0x01
+#define PMC_SETUP_USER 0x02
+#define PMC_SETUP_EDGE 0x04
+#define PMC_SETUP_INV 0x08
+
+struct x86_64_pmc_read_args {
+ int counter;
+ u_int64_t val;
+ u_int64_t time;
+};
+
+#endif /* todo */
+
+struct x86_64_get_mtrr_args {
+ struct mtrr *mtrrp;
+ int *n;
+};
+
+struct x86_64_set_mtrr_args {
+ struct mtrr *mtrrp;
+ int *n;
+};
+
+
+#ifdef _KERNEL
+int x86_64_iopl(struct proc *, void *, register_t *);
+int x86_64_get_mtrr(struct proc *, void *, register_t *);
+int x86_64_set_mtrr(struct proc *, void *, register_t *);
+#else
+int x86_64_get_ldt(int, union descriptor *, int);
+int x86_64_set_ldt(int, union descriptor *, int);
+int x86_64_iopl(int);
+int x86_64_get_ioperm(u_long *);
+int x86_64_set_ioperm(u_long *);
+int x86_64_pmc_info(struct x86_64_pmc_info_args *);
+int x86_64_pmc_startstop(struct x86_64_pmc_startstop_args *);
+int x86_64_pmc_read(struct x86_64_pmc_read_args *);
+int x86_64_set_mtrr(struct mtrr *, int *);
+int x86_64_get_mtrr(struct mtrr *, int *);
+int sysarch(int, void *);
+#endif
+
+#endif /* !_AMD64_SYSARCH_H_ */
diff --git a/sys/arch/amd64/include/trap.h b/sys/arch/amd64/include/trap.h
new file mode 100644
index 00000000000..f3353efc973
--- /dev/null
+++ b/sys/arch/amd64/include/trap.h
@@ -0,0 +1,74 @@
+/* $OpenBSD: trap.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: trap.h,v 1.4 1994/10/27 04:16:30 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)trap.h 5.4 (Berkeley) 5/9/91
+ */
+
+/*
+ * Trap type values
+ * also known in trap.c for name strings
+ */
+
+#define T_PRIVINFLT 0 /* privileged instruction */
+#define T_BPTFLT 1 /* breakpoint trap */
+#define T_ARITHTRAP 2 /* arithmetic trap */
+#define T_ASTFLT 3 /* asynchronous system trap */
+#define T_PROTFLT 4 /* protection fault */
+#define T_TRCTRAP 5 /* trace trap */
+#define T_PAGEFLT 6 /* page fault */
+#define T_ALIGNFLT 7 /* alignment fault */
+#define T_DIVIDE 8 /* integer divide fault */
+#define T_NMI 9 /* non-maskable interrupt */
+#define T_OFLOW 10 /* overflow trap */
+#define T_BOUND 11 /* bounds check fault */
+#define T_DNA 12 /* device not available fault */
+#define T_DOUBLEFLT 13 /* double fault */
+#define T_FPOPFLT 14 /* fp coprocessor operand fetch fault (![P]Pro)*/
+#define T_TSSFLT 15 /* invalid tss fault */
+#define T_SEGNPFLT 16 /* segment not present fault */
+#define T_STKFLT 17 /* stack fault */
+#define T_MCA 18 /* machine check ([P]Pro) */
+#define T_XMM 19 /* SSE FP exception */
+#define T_RESERVED 20 /* reserved fault base */
+
+/* Trap's coming from user mode */
+#define T_USER 0x100
+
+/* Flags kludged into the trap code */
+#define TC_TSS 0x80000000
+#define TC_FLAGMASK (TC_TSS)
diff --git a/sys/arch/amd64/include/tss.h b/sys/arch/amd64/include/tss.h
new file mode 100644
index 00000000000..c674e0952dd
--- /dev/null
+++ b/sys/arch/amd64/include/tss.h
@@ -0,0 +1,62 @@
+/* $OpenBSD: tss.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: tss.h,v 1.1 2003/04/26 18:39:49 fvdl Exp $ */
+
+/*
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Frank van der Linden for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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.
+ */
+
+#ifndef _AMD64_TSS_H_
+#define _AMD64_TSS_H_
+
+/*
+ * TSS structure. Since TSS hw switching is not supported in long
+ * mode, this is mainly there for the I/O permission map in
+ * normal processes.
+ */
+
+struct x86_64_tss {
+ u_int32_t tss_reserved1;
+ u_int64_t tss_rsp0;
+ u_int64_t tss_rsp1;
+ u_int64_t tss_rsp3;
+ u_int32_t tss_reserved2;
+ u_int32_t tss_reserved3;
+ u_int64_t tss_ist[7];
+ u_int32_t tss_reserved4;
+ u_int32_t tss_reserved5;
+ u_int16_t tss_reserved6;
+ u_int16_t tss_iobase;
+} __attribute__((packed));
+
+#endif /* _AMD64_TSS_H_ */
diff --git a/sys/arch/amd64/include/types.h b/sys/arch/amd64/include/types.h
new file mode 100644
index 00000000000..dc95c7e0a4e
--- /dev/null
+++ b/sys/arch/amd64/include/types.h
@@ -0,0 +1,81 @@
+/* $OpenBSD: types.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)types.h 7.5 (Berkeley) 3/9/91
+ */
+
+#ifndef _MACHTYPES_H_
+#define _MACHTYPES_H_
+
+#include <sys/cdefs.h>
+
+#if defined(_KERNEL)
+typedef struct label_t {
+ long val[8];
+} label_t;
+#endif
+
+typedef unsigned long paddr_t;
+typedef unsigned long psize_t;
+typedef unsigned long vaddr_t;
+typedef unsigned long vsize_t;
+
+#define __BIT_TYPES_DEFINED__
+typedef __signed char int8_t;
+typedef unsigned char u_int8_t;
+typedef unsigned char uint8_t;
+typedef short int16_t;
+typedef unsigned short u_int16_t;
+typedef unsigned short uint16_t;
+typedef int int32_t;
+typedef unsigned int u_int32_t;
+typedef unsigned int uint32_t;
+typedef long long int64_t;
+typedef unsigned long long u_int64_t;
+typedef unsigned long long uint64_t;
+
+typedef long register_t;
+
+/* The amd64 does not have strict alignment requirements. */
+#define __NO_STRICT_ALIGNMENT
+
+#define __HAVE_DEVICE_REGISTER
+#define __HAVE_NWSCONS
+#define __HAVE_CPU_COUNTER
+#define __HAVE_SYSCALL_INTERN
+#define __HAVE_MINIMAL_EMUL
+#define __HAVE_GENERIC_SOFT_INTERRUPTS
+#define __HAVE_CPU_MAXPROC
+
+#endif /* _MACHTYPES_H_ */
diff --git a/sys/arch/amd64/include/userret.h b/sys/arch/amd64/include/userret.h
new file mode 100644
index 00000000000..4422d1b25dd
--- /dev/null
+++ b/sys/arch/amd64/include/userret.h
@@ -0,0 +1,99 @@
+/* $OpenBSD: userret.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: userret.h,v 1.1 2003/04/26 18:39:49 fvdl Exp $ */
+
+/*
+ * XXXfvdl same as i386 counterpart, but should probably be independent.
+ */
+
+/*-
+ * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 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.
+ *
+ */
+
+#include <sys/signalvar.h>
+#include <machine/cpu.h>
+
+static __inline void userret(struct proc *);
+
+/*
+ * Define the code needed before returning to user mode, for
+ * trap and syscall.
+ */
+static __inline void
+userret(struct proc *p)
+{
+ int sig;
+
+ while ((sig = CURSIG(p)) != 0)
+ postsig(sig);
+
+ curpriority = p->p_priority = p->p_usrpri;
+}
diff --git a/sys/arch/amd64/include/vmparam.h b/sys/arch/amd64/include/vmparam.h
new file mode 100644
index 00000000000..a7657f1bbff
--- /dev/null
+++ b/sys/arch/amd64/include/vmparam.h
@@ -0,0 +1,132 @@
+/* $OpenBSD: vmparam.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: vmparam.h,v 1.1 2003/04/26 18:39:49 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)vmparam.h 5.9 (Berkeley) 5/12/91
+ */
+
+#ifndef _VMPARAM_H_
+#define _VMPARAM_H_
+
+/*
+ * Machine dependent constants for amd64.
+ */
+
+/*
+ * USRSTACK is the top (end) of the user stack. Immediately above the
+ * user stack resides the user structure, which is UPAGES long and contains
+ * the kernel stack.
+ *
+ * Immediately after the user structure is the page table map, and then
+ * kernal address space.
+ */
+#define USRSTACK VM_MAXUSER_ADDRESS
+
+/*
+ * Virtual memory related constants, all in bytes
+ */
+#define MAXTSIZ (64*1024*1024) /* max text size */
+#ifndef DFLDSIZ
+#define DFLDSIZ (128*1024*1024) /* initial data size limit */
+#endif
+#ifndef MAXDSIZ
+#define MAXDSIZ (1*1024*1024*1024) /* max data size */
+#endif
+#ifndef DFLSSIZ
+#define DFLSSIZ (2*1024*1024) /* initial stack size limit */
+#endif
+#ifndef MAXSSIZ
+#define MAXSSIZ (32*1024*1024) /* max stack size */
+#endif
+
+/*
+ * Size of shared memory map
+ */
+#ifndef SHMMAXPGS
+#define SHMMAXPGS 8192
+#endif
+
+/*
+ * Size of User Raw I/O map
+ */
+#define USRIOSIZE 300
+
+/*
+ * The time for a process to be blocked before being very swappable.
+ * This is a number of seconds which the system takes as being a non-trivial
+ * amount of real time. You probably shouldn't change this;
+ * it is used in subtle ways (fractions and multiples of it are, that is, like
+ * half of a ``long time'', almost a long time, etc.)
+ * It is related to human patience and other factors which don't really
+ * change over time.
+ */
+#define MAXSLP 20
+
+/*
+ * Mach derived constants
+ */
+
+/* user/kernel map constants */
+#define VM_MIN_ADDRESS 0
+#define VM_MAXUSER_ADDRESS 0x00007f7fffffc000
+#define VM_MAX_ADDRESS 0x00007fbfdfeff000
+#define VM_MIN_KERNEL_ADDRESS 0xffff800000000000
+#define VM_MAX_KERNEL_ADDRESS 0xffff800100000000
+
+#define VM_MAXUSER_ADDRESS32 0xffffc000
+
+/* virtual sizes (bytes) for various kernel submaps */
+#define VM_PHYS_SIZE (USRIOSIZE*PAGE_SIZE)
+
+#define VM_PHYSSEG_MAX 5 /* 1 "hole" + 4 free lists */
+#define VM_PHYSSEG_STRAT VM_PSTRAT_BIGFIRST
+#define VM_PHYSSEG_NOADD /* can't add RAM after vm_mem_init */
+
+#define VM_NFREELIST 2
+#define VM_FREELIST_DEFAULT 0
+#define VM_FREELIST_FIRST16 1
+
+/*
+ * pmap specific data stored in the vm_physmem[] array
+ */
+#define __HAVE_PMAP_PHYSSEG
+struct pmap_physseg {
+ struct pv_head *pvhead; /* pv_head array */
+ unsigned char *attrs; /* attrs array */
+};
+
+#endif /* _VMPARAM_H_ */
diff --git a/sys/arch/amd64/isa/clock.c b/sys/arch/amd64/isa/clock.c
new file mode 100644
index 00000000000..524ad712ec3
--- /dev/null
+++ b/sys/arch/amd64/isa/clock.c
@@ -0,0 +1,765 @@
+/* $OpenBSD: clock.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: clock.c,v 1.1 2003/04/26 18:39:50 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1993, 1994 Charles M. Hannum.
+ * 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.
+ * 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.
+ *
+ * @(#)clock.c 7.2 (Berkeley) 5/12/91
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+ * Primitive clock interrupt routines.
+ */
+
+/* #define CLOCKDEBUG */
+/* #define CLOCK_PARANOIA */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/timeout.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/pio.h>
+#include <machine/cpufunc.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+#include <dev/ic/mc146818reg.h>
+#include <dev/ic/i8253reg.h>
+#include <i386/isa/nvram.h>
+#include <dev/clock_subr.h>
+#include <machine/specialreg.h>
+
+#ifndef __x86_64__
+#include "mca.h"
+#endif
+#if NMCA > 0
+#include <machine/mca_machdep.h> /* for MCA_system */
+#endif
+
+#include "pcppi.h"
+#if (NPCPPI > 0)
+#include <dev/isa/pcppivar.h>
+
+#ifdef CLOCKDEBUG
+int clock_debug = 0;
+#define DPRINTF(arg) if (clock_debug) printf arg
+#else
+#define DPRINTF(arg)
+#endif
+
+int sysbeepmatch(struct device *, void *, void *);
+void sysbeepattach(struct device *, struct device *, void *);
+
+struct cfattach sysbeep_ca = {
+ sizeof(struct device), sysbeepmatch, sysbeepattach
+};
+
+struct cfdriver sysbeep_cd = {
+ NULL, "sysbeep", DV_DULL
+};
+
+static int ppi_attached;
+static pcppi_tag_t ppicookie;
+#endif /* PCPPI */
+
+void spinwait(int);
+int clockintr(void *);
+int rtcintr(void *);
+int gettick(void);
+void sysbeep(int, int);
+void rtcdrain(void *v);
+int rtcget(mc_todregs *);
+void rtcput(mc_todregs *);
+int bcdtobin(int);
+int bintobcd(int);
+void findcpuspeed(void);
+
+__inline u_int mc146818_read(void *, u_int);
+__inline void mc146818_write(void *, u_int, u_int);
+
+__inline u_int
+mc146818_read(sc, reg)
+ void *sc; /* XXX use it? */
+ u_int reg;
+{
+
+ outb(IO_RTC, reg);
+ DELAY(1);
+ return (inb(IO_RTC+1));
+}
+
+__inline void
+mc146818_write(sc, reg, datum)
+ void *sc; /* XXX use it? */
+ u_int reg, datum;
+{
+
+ outb(IO_RTC, reg);
+ DELAY(1);
+ outb(IO_RTC+1, datum);
+ DELAY(1);
+}
+
+/* minimal initialization, enough for delay() */
+void
+initrtclock()
+{
+ u_long tval;
+
+ /*
+ * Compute timer_count, the count-down count the timer will be
+ * set to. Also, correctly round
+ * this by carrying an extra bit through the division.
+ */
+ tval = (TIMER_FREQ * 2) / (u_long) hz;
+ tval = (tval / 2) + (tval & 0x1);
+
+ /* initialize 8253 clock */
+ outb(IO_TIMER1+TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT);
+
+ /* Correct rounding will buy us a better precision in timekeeping */
+ outb(IO_TIMER1+TIMER_CNTR0, tval % 256);
+ outb(IO_TIMER1+TIMER_CNTR0, tval / 256);
+}
+
+/*
+ * microtime() makes use of the following globals. Note that isa_timer_tick
+ * may be redundant to the `tick' variable, but is kept here for stability.
+ * isa_timer_count is the countdown count for the timer. timer_msb_table[]
+ * and timer_lsb_table[] are used to compute the microsecond increment
+ * for time.tv_usec in the follow fashion:
+ *
+ * time.tv_usec += isa_timer_msb_table[cnt_msb] - isa_timer_lsb_table[cnt_lsb];
+ */
+#define ISA_TIMER_MSB_TABLE_SIZE 128
+
+u_long isa_timer_tick; /* the number of microseconds in a tick */
+u_short isa_timer_count; /* the countdown count for the timer */
+u_short isa_timer_msb_table[ISA_TIMER_MSB_TABLE_SIZE]; /* timer->usec MSB */
+u_short isa_timer_lsb_table[256]; /* timer->usec conversion for LSB */
+
+void
+startrtclock()
+{
+ int s;
+
+ findcpuspeed(); /* use the clock (while it's free)
+ to find the cpu speed */
+ initrtclock();
+
+ /* Check diagnostic status */
+ if ((s = mc146818_read(NULL, NVRAM_DIAG)) != 0) /* XXX softc */
+ printf("RTC BIOS diagnostic error %b\n", s, NVRAM_DIAG_BITS);
+}
+
+int
+clockintr(void *arg)
+{
+ struct clockframe *frame = arg;
+#if defined(I586_CPU) || defined(I686_CPU)
+ static int microset_iter; /* call cc_microset once/sec */
+ struct cpu_info *ci = curcpu();
+
+ /*
+ * If we have a cycle counter, do the microset thing.
+ */
+ if (ci->ci_feature_flags & CPUID_TSC) {
+ if (
+#if defined(MULTIPROCESSOR)
+ CPU_IS_PRIMARY(ci) &&
+#endif
+ (microset_iter--) == 0) {
+ cc_microset_time = time;
+ microset_iter = hz - 1;
+#if defined(MULTIPROCESSOR)
+ x86_broadcast_ipi(X86_IPI_MICROSET);
+#endif
+ cc_microset(ci);
+ }
+ }
+#endif
+ hardclock(frame);
+
+ return 1;
+}
+
+int
+rtcintr(void *arg)
+{
+ struct clockframe *frame = arg;
+ u_int stat = 0;
+
+ /*
+ * If rtcintr is 'late', next intr may happen immediately.
+ * Get them all. (Also, see comment in cpu_initclocks().)
+ */
+ while (mc146818_read(NULL, MC_REGC) & MC_REGC_PF) {
+ statclock(frame);
+ stat = 1;
+ }
+
+ return (stat);
+}
+
+int
+gettick()
+{
+ u_long ef;
+ u_char lo, hi;
+
+ /* Don't want someone screwing with the counter while we're here. */
+ ef = read_rflags();
+ disable_intr();
+ /* Select counter 0 and latch it. */
+ outb(IO_TIMER1+TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
+ lo = inb(IO_TIMER1+TIMER_CNTR0);
+ hi = inb(IO_TIMER1+TIMER_CNTR0);
+ write_rflags(ef);
+ return ((hi << 8) | lo);
+}
+
+/*
+ * Wait "n" microseconds.
+ * Relies on timer 1 counting down from (TIMER_FREQ / hz) at TIMER_FREQ Hz.
+ * Note: timer had better have been programmed before this is first used!
+ * (Note that we use `rate generator' mode, which counts at 1:1; `square
+ * wave' mode counts at 2:1).
+ */
+void
+i8254_delay(int n)
+{
+ int limit, tick, otick;
+
+ /*
+ * Read the counter first, so that the rest of the setup overhead is
+ * counted.
+ */
+ otick = gettick();
+
+#ifdef __GNUC__
+ /*
+ * Calculate ((n * TIMER_FREQ) / 1e6) using explicit assembler code so
+ * we can take advantage of the intermediate 64-bit quantity to prevent
+ * loss of significance.
+ */
+ n -= 5;
+ if (n < 0)
+ return;
+ __asm __volatile("mul %2\n\tdiv %3"
+ : "=a" (n)
+ : "0" (n), "r" (TIMER_FREQ), "r" (1000000)
+ : "%edx", "cc");
+#else
+ /*
+ * Calculate ((n * TIMER_FREQ) / 1e6) without using floating point and
+ * without any avoidable overflows.
+ */
+ n -= 20;
+ {
+ int sec = n / 1000000,
+ usec = n % 1000000;
+ n = sec * TIMER_FREQ +
+ usec * (TIMER_FREQ / 1000000) +
+ usec * ((TIMER_FREQ % 1000000) / 1000) / 1000 +
+ usec * (TIMER_FREQ % 1000) / 1000000;
+ }
+#endif
+
+ limit = TIMER_FREQ / hz;
+
+ while (n > 0) {
+ tick = gettick();
+ if (tick > otick)
+ n -= limit - (tick - otick);
+ else
+ n -= otick - tick;
+ otick = tick;
+ }
+}
+
+#if (NPCPPI > 0)
+int
+sysbeepmatch(parent, match, aux)
+ struct device *parent;
+ void *match;
+ void *aux;
+{
+ return (!ppi_attached);
+}
+
+void
+sysbeepattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ printf("\n");
+
+ ppicookie = ((struct pcppi_attach_args *)aux)->pa_cookie;
+ ppi_attached = 1;
+}
+#endif
+
+void
+sysbeep(pitch, period)
+ int pitch, period;
+{
+#if (NPCPPI > 0)
+ if (ppi_attached)
+ pcppi_bell(ppicookie, pitch, period, 0);
+#endif
+}
+
+unsigned int delaycount; /* calibrated loop variable (1 millisecond) */
+
+#define FIRST_GUESS 0x2000
+
+void
+findcpuspeed()
+{
+ int i;
+ int remainder;
+
+ /* Put counter in count down mode */
+ outb(TIMER_MODE, TIMER_SEL0 | TIMER_16BIT | TIMER_RATEGEN);
+ outb(TIMER_CNTR0, 0xff);
+ outb(TIMER_CNTR0, 0xff);
+ for (i = FIRST_GUESS; i; i--)
+ ;
+ /* Read the value left in the counter */
+ remainder = gettick();
+ /*
+ * Formula for delaycount is:
+ * (loopcount * timer clock speed) / (counter ticks * 1000)
+ */
+ delaycount = (FIRST_GUESS * TIMER_DIV(1000)) / (0xffff-remainder);
+}
+
+void
+rtcdrain(void *v)
+{
+ struct timeout *to = (struct timeout *)v;
+
+ if (to != NULL)
+ timeout_del(to);
+
+ /*
+ * Drain any un-acknowledged RTC interrupts.
+ * See comment in cpu_initclocks().
+ */
+ while (mc146818_read(NULL, MC_REGC) & MC_REGC_PF)
+ ; /* Nothing. */
+}
+
+void
+i8254_initclocks()
+{
+ static struct timeout rtcdrain_timeout;
+
+ stathz = 128;
+ profhz = 1024;
+
+ /*
+ * XXX If you're doing strange things with multiple clocks, you might
+ * want to keep track of clock handlers.
+ */
+ isa_intr_establish(NULL, 0, IST_PULSE, IPL_CLOCK, clockintr,0,"clock");
+ isa_intr_establish(NULL, 8, IST_PULSE, IPL_CLOCK, rtcintr, 0, "rtc");
+
+ mc146818_write(NULL, MC_REGA, MC_BASE_32_KHz | MC_RATE_128_Hz);
+ mc146818_write(NULL, MC_REGB, MC_REGB_24HR | MC_REGB_PIE);
+
+ /*
+ * On a number of i386 systems, the rtc will fail to start when booting
+ * the system. This is due to us missing to acknowledge an interrupt
+ * during early stages of the boot process. If we do not acknowledge
+ * the interrupt, the rtc clock will not generate further interrupts.
+ * To solve this, once interrupts are enabled, use a timeout (once)
+ * to drain any un-acknowledged rtc interrupt(s).
+ */
+ timeout_set(&rtcdrain_timeout, rtcdrain, (void *)&rtcdrain_timeout);
+ timeout_add(&rtcdrain_timeout, 1);
+}
+
+int
+rtcget(regs)
+ mc_todregs *regs;
+{
+ if ((mc146818_read(NULL, MC_REGD) & MC_REGD_VRT) == 0) /* XXX softc */
+ return (-1);
+ MC146818_GETTOD(NULL, regs); /* XXX softc */
+ return (0);
+}
+
+void
+rtcput(regs)
+ mc_todregs *regs;
+{
+ MC146818_PUTTOD(NULL, regs); /* XXX softc */
+}
+
+int
+bcdtobin(n)
+ int n;
+{
+
+ return (((n >> 4) & 0x0f) * 10 + (n & 0x0f));
+}
+
+int
+bintobcd(n)
+ int n;
+{
+
+ return ((u_char)(((n / 10) << 4) & 0xf0) | ((n % 10) & 0x0f));
+}
+
+static int timeset;
+
+/*
+ * check whether the CMOS layout is "standard"-like (ie, not PS/2-like),
+ * to be called at splclock()
+ */
+static int cmoscheck(void);
+static int
+cmoscheck()
+{
+ int i;
+ unsigned short cksum = 0;
+
+ for (i = 0x10; i <= 0x2d; i++)
+ cksum += mc146818_read(NULL, i); /* XXX softc */
+
+ return (cksum == (mc146818_read(NULL, 0x2e) << 8)
+ + mc146818_read(NULL, 0x2f));
+}
+
+#if NMCA > 0
+/*
+ * Check whether the CMOS layout is PS/2 like, to be called at splclock().
+ */
+static int cmoscheckps2(void);
+static int
+cmoscheckps2()
+{
+#if 0
+ /* Disabled until I find out the CRC checksum algorithm IBM uses */
+ int i;
+ unsigned short cksum = 0;
+
+ for (i = 0x10; i <= 0x31; i++)
+ cksum += mc146818_read(NULL, i); /* XXX softc */
+
+ return (cksum == (mc146818_read(NULL, 0x32) << 8)
+ + mc146818_read(NULL, 0x33));
+#else
+ /* Check 'incorrect checksum' bit of IBM PS/2 Diagnostic Status Byte */
+ return ((mc146818_read(NULL, NVRAM_DIAG) & (1<<6)) == 0);
+#endif
+}
+#endif /* NMCA > 0 */
+
+/*
+ * patchable to control century byte handling:
+ * 1: always update
+ * -1: never touch
+ * 0: try to figure out itself
+ */
+int rtc_update_century = 0;
+
+/*
+ * Expand a two-digit year as read from the clock chip
+ * into full width.
+ * Being here, deal with the CMOS century byte.
+ */
+static int centb = NVRAM_CENTURY;
+static int clock_expandyear(int);
+static int
+clock_expandyear(clockyear)
+ int clockyear;
+{
+ int s, clockcentury, cmoscentury;
+
+ clockcentury = (clockyear < 70) ? 20 : 19;
+ clockyear += 100 * clockcentury;
+
+ if (rtc_update_century < 0)
+ return (clockyear);
+
+ s = splclock();
+ if (cmoscheck())
+ cmoscentury = mc146818_read(NULL, NVRAM_CENTURY);
+#if NMCA > 0
+ else if (MCA_system && cmoscheckps2())
+ cmoscentury = mc146818_read(NULL, (centb = 0x37));
+#endif
+ else
+ cmoscentury = 0;
+ splx(s);
+ if (!cmoscentury) {
+#ifdef DIAGNOSTIC
+ printf("clock: unknown CMOS layout\n");
+#endif
+ return (clockyear);
+ }
+ cmoscentury = bcdtobin(cmoscentury);
+
+ if (cmoscentury != clockcentury) {
+ /* XXX note: saying "century is 20" might confuse the naive. */
+ printf("WARNING: NVRAM century is %d but RTC year is %d\n",
+ cmoscentury, clockyear);
+
+ /* Kludge to roll over century. */
+ if ((rtc_update_century > 0) ||
+ ((cmoscentury == 19) && (clockcentury == 20) &&
+ (clockyear == 2000))) {
+ printf("WARNING: Setting NVRAM century to %d\n",
+ clockcentury);
+ s = splclock();
+ mc146818_write(NULL, centb, bintobcd(clockcentury));
+ splx(s);
+ }
+ } else if (cmoscentury == 19 && rtc_update_century == 0)
+ rtc_update_century = 1; /* will update later in resettodr() */
+
+ return (clockyear);
+}
+
+/*
+ * Initialize the time of day register, based on the time base which is, e.g.
+ * from a filesystem.
+ */
+void
+inittodr(base)
+ time_t base;
+{
+ mc_todregs rtclk;
+ struct clock_ymdhms dt;
+ int s;
+#if defined(I586_CPU) || defined(I686_CPU)
+ struct cpu_info *ci = curcpu();
+#endif
+ /*
+ * We mostly ignore the suggested time (which comes from the
+ * file system) and go for the RTC clock time stored in the
+ * CMOS RAM. If the time can't be obtained from the CMOS, or
+ * if the time obtained from the CMOS is 5 or more years less
+ * than the suggested time, we used the suggested time. (In
+ * the latter case, it's likely that the CMOS battery has
+ * died.)
+ */
+
+ /*
+ * if the file system time is more than a year older than the
+ * kernel, warn and then set the base time to the CONFIG_TIME.
+ */
+ if (base < 30*SECYR) { /* if before 2000, something's odd... */
+ printf("WARNING: preposterous time in file system\n");
+ base = 30*SECYR;
+ }
+
+ s = splclock();
+ if (rtcget(&rtclk)) {
+ splx(s);
+ printf("WARNING: invalid time in clock chip\n");
+ goto fstime;
+ }
+ splx(s);
+#ifdef DEBUG_CLOCK
+ printf("readclock: %x/%x/%x %x:%x:%x\n", rtclk[MC_YEAR],
+ rtclk[MC_MONTH], rtclk[MC_DOM], rtclk[MC_HOUR], rtclk[MC_MIN],
+ rtclk[MC_SEC]);
+#endif
+
+ dt.dt_sec = bcdtobin(rtclk[MC_SEC]);
+ dt.dt_min = bcdtobin(rtclk[MC_MIN]);
+ dt.dt_hour = bcdtobin(rtclk[MC_HOUR]);
+ dt.dt_day = bcdtobin(rtclk[MC_DOM]);
+ dt.dt_mon = bcdtobin(rtclk[MC_MONTH]);
+ dt.dt_year = clock_expandyear(bcdtobin(rtclk[MC_YEAR]));
+
+ /*
+ * If time_t is 32 bits, then the "End of Time" is
+ * Mon Jan 18 22:14:07 2038 (US/Eastern)
+ * This code copes with RTC's past the end of time if time_t
+ * is an int32 or less. Needed because sometimes RTCs screw
+ * up or are badly set, and that would cause the time to go
+ * negative in the calculation below, which causes Very Bad
+ * Mojo. This at least lets the user boot and fix the problem.
+ * Note the code is self eliminating once time_t goes to 64 bits.
+ */
+ if (sizeof(time_t) <= sizeof(int32_t)) {
+ if (dt.dt_year >= 2038) {
+ printf("WARNING: RTC time at or beyond 2038.\n");
+ dt.dt_year = 2037;
+ printf("WARNING: year set back to 2037.\n");
+ printf("WARNING: CHECK AND RESET THE DATE!\n");
+ }
+ }
+
+ time.tv_sec = clock_ymdhms_to_secs(&dt);
+#ifdef DEBUG_CLOCK
+ printf("readclock: %ld (%ld)\n", time.tv_sec, base);
+#endif
+#if defined(I586_CPU) || defined(I686_CPU)
+ if (ci->ci_feature_flags & CPUID_TSC) {
+ cc_microset_time = time;
+ cc_microset(ci);
+ }
+#endif
+
+ if (base != 0 && base < time.tv_sec - 5*SECYR)
+ printf("WARNING: file system time much less than clock time\n");
+ else if (base > time.tv_sec + 5*SECYR) {
+ printf("WARNING: clock time much less than file system time\n");
+ printf("WARNING: using file system time\n");
+ goto fstime;
+ }
+
+ timeset = 1;
+ return;
+
+fstime:
+ timeset = 1;
+ time.tv_sec = base;
+ printf("WARNING: CHECK AND RESET THE DATE!\n");
+}
+
+/*
+ * Reset the clock.
+ */
+void
+resettodr()
+{
+ mc_todregs rtclk;
+ struct clock_ymdhms dt;
+ int century;
+ int s;
+
+ /*
+ * We might have been called by boot() due to a crash early
+ * on. Don't reset the clock chip in this case.
+ */
+ if (!timeset)
+ return;
+
+ s = splclock();
+ if (rtcget(&rtclk))
+ memset(&rtclk, 0, sizeof(rtclk));
+ splx(s);
+
+ clock_secs_to_ymdhms(time.tv_sec, &dt);
+
+ rtclk[MC_SEC] = bintobcd(dt.dt_sec);
+ rtclk[MC_MIN] = bintobcd(dt.dt_min);
+ rtclk[MC_HOUR] = bintobcd(dt.dt_hour);
+ rtclk[MC_DOW] = dt.dt_wday + 1;
+ rtclk[MC_YEAR] = bintobcd(dt.dt_year % 100);
+ rtclk[MC_MONTH] = bintobcd(dt.dt_mon);
+ rtclk[MC_DOM] = bintobcd(dt.dt_day);
+
+#ifdef DEBUG_CLOCK
+ printf("setclock: %x/%x/%x %x:%x:%x\n", rtclk[MC_YEAR], rtclk[MC_MONTH],
+ rtclk[MC_DOM], rtclk[MC_HOUR], rtclk[MC_MIN], rtclk[MC_SEC]);
+#endif
+ s = splclock();
+ rtcput(&rtclk);
+ if (rtc_update_century > 0) {
+ century = bintobcd(dt.dt_year / 100);
+ mc146818_write(NULL, centb, century); /* XXX softc */
+ }
+ splx(s);
+}
+
+void
+setstatclockrate(arg)
+ int arg;
+{
+ if (arg == stathz)
+ mc146818_write(NULL, MC_REGA, MC_BASE_32_KHz | MC_RATE_128_Hz);
+ else
+ mc146818_write(NULL, MC_REGA, MC_BASE_32_KHz | MC_RATE_1024_Hz);
+}
diff --git a/sys/arch/amd64/isa/isa_machdep.c b/sys/arch/amd64/isa/isa_machdep.c
new file mode 100644
index 00000000000..f86a49a00ed
--- /dev/null
+++ b/sys/arch/amd64/isa/isa_machdep.c
@@ -0,0 +1,1026 @@
+/* $OpenBSD: isa_machdep.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: isa_machdep.c,v 1.22 1997/06/12 23:57:32 thorpej Exp $ */
+
+#define ISA_DMA_STATS
+
+/*-
+ * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1993, 1994, 1996, 1997
+ * Charles M. Hannum. All rights reserved.
+ * 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.
+ * 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.
+ *
+ * @(#)isa.c 7.2 (Berkeley) 5/13/91
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+
+#include <uvm/uvm_extern.h>
+
+#define _I386_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+
+#include <machine/intr.h>
+#include <machine/pio.h>
+#include <machine/cpufunc.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+#if 0
+#include <dev/isa/isadmavar.h>
+#endif
+#include <i386/isa/isa_machdep.h>
+#include <i386/isa/icu.h>
+
+#include "isadma.h"
+
+/*
+ * ISA can only DMA to 0-16M.
+ */
+#define ISA_DMA_BOUNCE_THRESHOLD 0x00ffffff
+
+extern paddr_t avail_end;
+
+#define IDTVEC(name) __CONCAT(X,name)
+/* default interrupt vector table entries */
+typedef int (*vector)(void);
+extern vector IDTVEC(intr)[];
+void isa_strayintr(int);
+int fakeintr(void *);
+
+#if NISADMA > 0
+int _isa_bus_dmamap_create(bus_dma_tag_t, bus_size_t, int,
+ bus_size_t, bus_size_t, int, bus_dmamap_t *);
+void _isa_bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
+int _isa_bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *,
+ bus_size_t, struct proc *, int);
+int _isa_bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t,
+ struct mbuf *, int);
+int _isa_bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t,
+ struct uio *, int);
+int _isa_bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
+ bus_dma_segment_t *, int, bus_size_t, int);
+void _isa_bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
+void _isa_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t,
+ bus_addr_t, bus_size_t, int);
+
+int _isa_bus_dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t,
+ bus_size_t, bus_dma_segment_t *, int, int *, int);
+void _isa_bus_dmamem_free(bus_dma_tag_t,
+ bus_dma_segment_t *, int);
+int _isa_bus_dmamem_map(bus_dma_tag_t, bus_dma_segment_t *,
+ int, size_t, caddr_t *, int);
+void _isa_bus_dmamem_unmap(bus_dma_tag_t, caddr_t, size_t);
+paddr_t _isa_bus_dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *,
+ int, off_t, int, int);
+
+int _isa_dma_check_buffer(void *, bus_size_t, int, bus_size_t,
+ struct proc *);
+int _isa_dma_alloc_bouncebuf(bus_dma_tag_t, bus_dmamap_t,
+ bus_size_t, int);
+void _isa_dma_free_bouncebuf(bus_dma_tag_t, bus_dmamap_t);
+
+/*
+ * Entry points for ISA DMA. These are mostly wrappers around
+ * the generic functions that understand how to deal with bounce
+ * buffers, if necessary.
+ */
+struct i386_bus_dma_tag isa_bus_dma_tag = {
+ NULL, /* _cookie */
+ _isa_bus_dmamap_create,
+ _isa_bus_dmamap_destroy,
+ _isa_bus_dmamap_load,
+ _isa_bus_dmamap_load_mbuf,
+ _isa_bus_dmamap_load_uio,
+ _isa_bus_dmamap_load_raw,
+ _isa_bus_dmamap_unload,
+ _isa_bus_dmamap_sync,
+ _isa_bus_dmamem_alloc,
+ _isa_bus_dmamem_free,
+ _isa_bus_dmamem_map,
+ _isa_bus_dmamem_unmap,
+ _isa_bus_dmamem_mmap,
+};
+#endif /* NISADMA > 0 */
+
+#define GICODE_SEL 10
+
+u_long intrstray[ICU_LEN];
+
+/*
+ * Caught a stray interrupt, notify
+ */
+void
+isa_strayintr(irq)
+ int irq;
+{
+ /*
+ * Stray interrupts on irq 7 occur when an interrupt line is raised
+ * and then lowered before the CPU acknowledges it. This generally
+ * means either the device is screwed or something is cli'ing too
+ * long and it's timing out.
+ */
+ if (++intrstray[irq] <= 5)
+ log(LOG_ERR, "stray interrupt %d%s\n", irq,
+ intrstray[irq] >= 5 ? "; stopped logging" : "");
+}
+
+int intrtype[ICU_LEN], intrmask[ICU_LEN], intrlevel[ICU_LEN];
+int iminlevel[ICU_LEN], imaxlevel[ICU_LEN];
+struct intrhand *intrhand[ICU_LEN];
+
+int
+fakeintr(arg)
+ void *arg;
+{
+ return 0;
+}
+
+#define LEGAL_IRQ(x) ((x) >= 0 && (x) < ICU_LEN && (x) != 2)
+
+int
+isa_intr_alloc(ic, mask, type, irq)
+ isa_chipset_tag_t ic;
+ int mask;
+ int type;
+ int *irq;
+{
+ int i, bestirq, count;
+ int tmp;
+ struct intrhand **p, *q;
+
+ if (type == IST_NONE)
+ panic("intr_alloc: bogus type");
+
+ bestirq = -1;
+ count = -1;
+
+ /* some interrupts should never be dynamically allocated */
+ mask &= 0xdef8;
+
+ /*
+ * XXX some interrupts will be used later (6 for fdc, 12 for pms).
+ * the right answer is to do "breadth-first" searching of devices.
+ */
+ mask &= 0xefbf;
+
+ for (i = 0; i < ICU_LEN; i++) {
+ if (LEGAL_IRQ(i) == 0 || (mask & (1<<i)) == 0)
+ continue;
+
+ switch(intrtype[i]) {
+ case IST_NONE:
+ /*
+ * if nothing's using the irq, just return it
+ */
+ *irq = i;
+ return (0);
+
+ case IST_EDGE:
+ case IST_LEVEL:
+ if (type != intrtype[i])
+ continue;
+ /*
+ * if the irq is shareable, count the number of other
+ * handlers, and if it's smaller than the last irq like
+ * this, remember it
+ *
+ * XXX We should probably also consider the
+ * interrupt level and stick IPL_TTY with other
+ * IPL_TTY, etc.
+ */
+ for (p = &intrhand[i], tmp = 0; (q = *p) != NULL;
+ p = &q->ih_next, tmp++)
+ ;
+ if ((bestirq == -1) || (count > tmp)) {
+ bestirq = i;
+ count = tmp;
+ }
+ break;
+
+ case IST_PULSE:
+ /* this just isn't shareable */
+ continue;
+ }
+ }
+
+ if (bestirq == -1)
+ return (1);
+
+ *irq = bestirq;
+
+ return (0);
+}
+
+/*
+ * Just check to see if an IRQ is available/can be shared.
+ * 0 = interrupt not available
+ * 1 = interrupt shareable
+ * 2 = interrupt all to ourself
+ */
+int
+isa_intr_check(ic, irq, type)
+ isa_chipset_tag_t ic; /* Not used. */
+ int irq;
+ int type;
+{
+ if (!LEGAL_IRQ(irq) || type == IST_NONE)
+ return (0);
+
+ switch (intrtype[irq]) {
+ case IST_NONE:
+ return (2);
+ break;
+ case IST_LEVEL:
+ if (type != intrtype[irq])
+ return (0);
+ return (1);
+ break;
+ case IST_EDGE:
+ case IST_PULSE:
+ if (type != IST_NONE)
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Set up an interrupt handler to start being called.
+ * XXX PRONE TO RACE CONDITIONS, UGLY, 'INTERESTING' INSERTION ALGORITHM.
+ */
+void *
+isa_intr_establish(ic, irq, type, level, ih_fun, ih_arg, ih_what)
+ isa_chipset_tag_t ic;
+ int irq;
+ int type;
+ int level;
+ int (*ih_fun)(void *);
+ void *ih_arg;
+ char *ih_what;
+{
+ struct intrhand **p, *q, *ih;
+ static struct intrhand fakehand = {fakeintr};
+
+ return intr_establish(irq, &i8259_pic, irq, type, level, ih_fun, ih_arg);
+
+ /* no point in sleeping unless someone can free memory. */
+ ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
+ if (ih == NULL) {
+ printf("%s: isa_intr_establish: can't malloc handler info\n",
+ ih_what);
+ return NULL;
+ }
+
+ if (!LEGAL_IRQ(irq) || type == IST_NONE) {
+ printf("%s: intr_establish: bogus irq or type\n", ih_what);
+ return NULL;
+ }
+ switch (intrtype[irq]) {
+ case IST_NONE:
+ intrtype[irq] = type;
+ break;
+ case IST_EDGE:
+ case IST_LEVEL:
+ if (type == intrtype[irq])
+ break;
+ case IST_PULSE:
+ if (type != IST_NONE) {
+ /*printf("%s: intr_establish: can't share %s with %s, irq %d\n",
+ ih_what, isa_intr_typename(intrtype[irq]),
+ isa_intr_typename(type), irq);*/
+ return NULL;
+ }
+ break;
+ }
+
+ /*
+ * Figure out where to put the handler.
+ * This is O(N^2), but we want to preserve the order, and N is
+ * generally small.
+ */
+ for (p = &intrhand[irq]; (q = *p) != NULL; p = &q->ih_next)
+ ;
+
+ /*
+ * Actually install a fake handler momentarily, since we might be doing
+ * this with interrupts enabled and don't want the real routine called
+ * until masking is set up.
+ */
+ fakehand.ih_level = level;
+ *p = &fakehand;
+
+ /*
+ * Poke the real handler in now.
+ */
+ ih->ih_fun = ih_fun;
+ ih->ih_arg = ih_arg;
+ ih->ih_next = NULL;
+ ih->ih_level = level;
+ ih->ih_irq = irq;
+ ih->ih_what = ih_what;
+ *p = ih;
+
+ return (ih);
+}
+
+/*
+ * Deregister an interrupt handler.
+ */
+void
+isa_intr_disestablish(ic, arg)
+ isa_chipset_tag_t ic;
+ void *arg;
+{
+ struct intrhand *ih = arg;
+ int irq = ih->ih_irq;
+ struct intrhand **p, *q;
+
+ intr_disestablish(arg);
+ return;
+
+ if (!LEGAL_IRQ(irq))
+ panic("intr_disestablish: bogus irq");
+
+ /*
+ * Remove the handler from the chain.
+ * This is O(n^2), too.
+ */
+ for (p = &intrhand[irq]; (q = *p) != NULL && q != ih; p = &q->ih_next)
+ ;
+ if (q)
+ *p = q->ih_next;
+ else
+ panic("intr_disestablish: handler not registered");
+ free(ih, M_DEVBUF);
+
+ if (intrhand[irq] == NULL)
+ intrtype[irq] = IST_NONE;
+}
+
+void
+isa_attach_hook(parent, self, iba)
+ struct device *parent, *self;
+ struct isabus_attach_args *iba;
+{
+ extern int isa_has_been_seen;
+
+ /*
+ * Notify others that might need to know that the ISA bus
+ * has now been attached.
+ */
+ if (isa_has_been_seen)
+ panic("isaattach: ISA bus already seen!");
+ isa_has_been_seen = 1;
+}
+
+#if NISADMA > 0
+/**********************************************************************
+ * bus.h dma interface entry points
+ **********************************************************************/
+
+#ifdef ISA_DMA_STATS
+#define STAT_INCR(v) (v)++
+#define STAT_DECR(v) do { \
+ if ((v) == 0) \
+ printf("%s:%d -- Already 0!\n", __FILE__, __LINE__); \
+ else \
+ (v)--; \
+ } while (0)
+u_long isa_dma_stats_loads;
+u_long isa_dma_stats_bounces;
+u_long isa_dma_stats_nbouncebufs;
+#else
+#define STAT_INCR(v)
+#define STAT_DECR(v)
+#endif
+
+/*
+ * Create an ISA DMA map.
+ */
+int
+_isa_bus_dmamap_create(t, size, nsegments, maxsegsz, boundary, flags, dmamp)
+ bus_dma_tag_t t;
+ bus_size_t size;
+ int nsegments;
+ bus_size_t maxsegsz;
+ bus_size_t boundary;
+ int flags;
+ bus_dmamap_t *dmamp;
+{
+ struct i386_isa_dma_cookie *cookie;
+ bus_dmamap_t map;
+ int error, cookieflags;
+ void *cookiestore;
+ size_t cookiesize;
+
+ /* Call common function to create the basic map. */
+ error = _bus_dmamap_create(t, size, nsegments, maxsegsz, boundary,
+ flags, dmamp);
+ if (error)
+ return (error);
+
+ map = *dmamp;
+ map->_dm_cookie = NULL;
+
+ cookiesize = sizeof(struct i386_isa_dma_cookie);
+
+ /*
+ * ISA only has 24-bits of address space. This means
+ * we can't DMA to pages over 16M. In order to DMA to
+ * arbitrary buffers, we use "bounce buffers" - pages
+ * in memory below the 16M boundary. On DMA reads,
+ * DMA happens to the bounce buffers, and is copied into
+ * the caller's buffer. On writes, data is copied into
+ * but bounce buffer, and the DMA happens from those
+ * pages. To software using the DMA mapping interface,
+ * this looks simply like a data cache.
+ *
+ * If we have more than 16M of RAM in the system, we may
+ * need bounce buffers. We check and remember that here.
+ *
+ * There are exceptions, however. VLB devices can do
+ * 32-bit DMA, and indicate that here.
+ *
+ * ...or, there is an opposite case. The most segments
+ * a transfer will require is (maxxfer / NBPG) + 1. If
+ * the caller can't handle that many segments (e.g. the
+ * ISA DMA controller), we may have to bounce it as well.
+ */
+ cookieflags = 0;
+ if ((avail_end > ISA_DMA_BOUNCE_THRESHOLD &&
+ (flags & ISABUS_DMA_32BIT) == 0) ||
+ ((map->_dm_size / NBPG) + 1) > map->_dm_segcnt) {
+ cookieflags |= ID_MIGHT_NEED_BOUNCE;
+ cookiesize += (sizeof(bus_dma_segment_t) * map->_dm_segcnt);
+ }
+
+ /*
+ * Allocate our cookie.
+ */
+ if ((cookiestore = malloc(cookiesize, M_DEVBUF,
+ (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+ bzero(cookiestore, cookiesize);
+ cookie = (struct i386_isa_dma_cookie *)cookiestore;
+ cookie->id_flags = cookieflags;
+ map->_dm_cookie = cookie;
+
+ if (cookieflags & ID_MIGHT_NEED_BOUNCE) {
+ /*
+ * Allocate the bounce pages now if the caller
+ * wishes us to do so.
+ */
+ if ((flags & BUS_DMA_ALLOCNOW) == 0)
+ goto out;
+
+ error = _isa_dma_alloc_bouncebuf(t, map, size, flags);
+ }
+
+ out:
+ if (error) {
+ if (map->_dm_cookie != NULL)
+ free(map->_dm_cookie, M_DEVBUF);
+ _bus_dmamap_destroy(t, map);
+ }
+ return (error);
+}
+
+/*
+ * Destroy an ISA DMA map.
+ */
+void
+_isa_bus_dmamap_destroy(t, map)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+{
+ struct i386_isa_dma_cookie *cookie = map->_dm_cookie;
+
+ /*
+ * Free any bounce pages this map might hold.
+ */
+ if (cookie->id_flags & ID_HAS_BOUNCE)
+ _isa_dma_free_bouncebuf(t, map);
+
+ free(cookie, M_DEVBUF);
+ _bus_dmamap_destroy(t, map);
+}
+
+/*
+ * Load an ISA DMA map with a linear buffer.
+ */
+int
+_isa_bus_dmamap_load(t, map, buf, buflen, p, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ void *buf;
+ bus_size_t buflen;
+ struct proc *p;
+ int flags;
+{
+ struct i386_isa_dma_cookie *cookie = map->_dm_cookie;
+ int error;
+
+ STAT_INCR(isa_dma_stats_loads);
+
+ /*
+ * Check to see if we might need to bounce the transfer.
+ */
+ if (cookie->id_flags & ID_MIGHT_NEED_BOUNCE) {
+ /*
+ * Check if all pages are below the bounce
+ * threshold. If they are, don't bother bouncing.
+ */
+ if (_isa_dma_check_buffer(buf, buflen,
+ map->_dm_segcnt, map->_dm_boundary, p) == 0)
+ return (_bus_dmamap_load(t, map, buf, buflen,
+ p, flags));
+
+ STAT_INCR(isa_dma_stats_bounces);
+
+ /*
+ * Allocate bounce pages, if necessary.
+ */
+ if ((cookie->id_flags & ID_HAS_BOUNCE) == 0) {
+ error = _isa_dma_alloc_bouncebuf(t, map, buflen,
+ flags);
+ if (error)
+ return (error);
+ }
+
+ /*
+ * Cache a pointer to the caller's buffer and
+ * load the DMA map with the bounce buffer.
+ */
+ cookie->id_origbuf = buf;
+ cookie->id_origbuflen = buflen;
+ error = _bus_dmamap_load(t, map, cookie->id_bouncebuf,
+ buflen, p, flags);
+
+ if (error) {
+ /*
+ * Free the bounce pages, unless our resources
+ * are reserved for our exclusive use.
+ */
+ if ((map->_dm_flags & BUS_DMA_ALLOCNOW) == 0)
+ _isa_dma_free_bouncebuf(t, map);
+ }
+
+ /* ...so _isa_bus_dmamap_sync() knows we're bouncing */
+ cookie->id_flags |= ID_IS_BOUNCING;
+ } else {
+ /*
+ * Just use the generic load function.
+ */
+ error = _bus_dmamap_load(t, map, buf, buflen, p, flags);
+ }
+
+ return (error);
+}
+
+/*
+ * Like _isa_bus_dmamap_load(), but for mbufs.
+ */
+int
+_isa_bus_dmamap_load_mbuf(t, map, m, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ struct mbuf *m;
+ int flags;
+{
+
+ panic("_isa_bus_dmamap_load_mbuf: not implemented");
+}
+
+/*
+ * Like _isa_bus_dmamap_load(), but for uios.
+ */
+int
+_isa_bus_dmamap_load_uio(t, map, uio, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ struct uio *uio;
+ int flags;
+{
+
+ panic("_isa_bus_dmamap_load_uio: not implemented");
+}
+
+/*
+ * Like _isa_bus_dmamap_load(), but for raw memory allocated with
+ * bus_dmamem_alloc().
+ */
+int
+_isa_bus_dmamap_load_raw(t, map, segs, nsegs, size, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ bus_size_t size;
+ int flags;
+{
+
+ panic("_isa_bus_dmamap_load_raw: not implemented");
+}
+
+/*
+ * Unload an ISA DMA map.
+ */
+void
+_isa_bus_dmamap_unload(t, map)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+{
+ struct i386_isa_dma_cookie *cookie = map->_dm_cookie;
+
+ /*
+ * If we have bounce pages, free them, unless they're
+ * reserved for our exclusive use.
+ */
+ if ((cookie->id_flags & ID_HAS_BOUNCE) &&
+ (map->_dm_flags & BUS_DMA_ALLOCNOW) == 0)
+ _isa_dma_free_bouncebuf(t, map);
+
+ cookie->id_flags &= ~ID_IS_BOUNCING;
+
+ /*
+ * Do the generic bits of the unload.
+ */
+ _bus_dmamap_unload(t, map);
+}
+
+/*
+ * Synchronize an ISA DMA map.
+ */
+void
+_isa_bus_dmamap_sync(t, map, offset, len, op)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ bus_addr_t offset;
+ bus_size_t len;
+ int op;
+{
+ struct i386_isa_dma_cookie *cookie = map->_dm_cookie;
+
+#ifdef DEBUG
+ if ((op & (BUS_DMASYNC_PREWRITE|BUS_DMASYNC_POSTREAD)) != 0) {
+ if (offset >= map->dm_mapsize)
+ panic("_isa_bus_dmamap_sync: bad offset");
+ if (len == 0 || (offset + len) > map->dm_mapsize)
+ panic("_isa_bus_dmamap_sync: bad length");
+ }
+#endif
+
+ switch (op) {
+ case BUS_DMASYNC_PREREAD:
+ /*
+ * Nothing to do for pre-read.
+ */
+ break;
+
+ case BUS_DMASYNC_PREWRITE:
+ /*
+ * If we're bouncing this transfer, copy the
+ * caller's buffer to the bounce buffer.
+ */
+ if (cookie->id_flags & ID_IS_BOUNCING)
+ bcopy(cookie->id_origbuf + offset,
+ cookie->id_bouncebuf + offset,
+ len);
+ break;
+
+ case BUS_DMASYNC_POSTREAD:
+ /*
+ * If we're bouncing this transfer, copy the
+ * bounce buffer to the caller's buffer.
+ */
+ if (cookie->id_flags & ID_IS_BOUNCING)
+ bcopy(cookie->id_bouncebuf + offset,
+ cookie->id_origbuf + offset,
+ len);
+ break;
+
+ case BUS_DMASYNC_POSTWRITE:
+ /*
+ * Nothing to do for post-write.
+ */
+ break;
+ }
+
+#if 0
+ /* This is a noop anyhow, so why bother calling it? */
+ _bus_dmamap_sync(t, map, op);
+#endif
+}
+
+/*
+ * Allocate memory safe for ISA DMA.
+ */
+int
+_isa_bus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags)
+ bus_dma_tag_t t;
+ bus_size_t size, alignment, boundary;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ int *rsegs;
+ int flags;
+{
+ paddr_t high;
+
+ if (avail_end > ISA_DMA_BOUNCE_THRESHOLD)
+ high = trunc_page(ISA_DMA_BOUNCE_THRESHOLD);
+ else
+ high = trunc_page(avail_end);
+
+ return (_bus_dmamem_alloc_range(t, size, alignment, boundary,
+ segs, nsegs, rsegs, flags, 0, high));
+}
+
+/*
+ * Free memory safe for ISA DMA.
+ */
+void
+_isa_bus_dmamem_free(t, segs, nsegs)
+ bus_dma_tag_t t;
+ bus_dma_segment_t *segs;
+ int nsegs;
+{
+
+ _bus_dmamem_free(t, segs, nsegs);
+}
+
+/*
+ * Map ISA DMA-safe memory into kernel virtual address space.
+ */
+int
+_isa_bus_dmamem_map(t, segs, nsegs, size, kvap, flags)
+ bus_dma_tag_t t;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ size_t size;
+ caddr_t *kvap;
+ int flags;
+{
+
+ return (_bus_dmamem_map(t, segs, nsegs, size, kvap, flags));
+}
+
+/*
+ * Unmap ISA DMA-safe memory from kernel virtual address space.
+ */
+void
+_isa_bus_dmamem_unmap(t, kva, size)
+ bus_dma_tag_t t;
+ caddr_t kva;
+ size_t size;
+{
+
+ _bus_dmamem_unmap(t, kva, size);
+}
+
+/*
+ * mmap(2) ISA DMA-safe memory.
+ */
+paddr_t
+_isa_bus_dmamem_mmap(t, segs, nsegs, off, prot, flags)
+ bus_dma_tag_t t;
+ bus_dma_segment_t *segs;
+ int nsegs;
+ off_t off;
+ int prot, flags;
+{
+
+ return (_bus_dmamem_mmap(t, segs, nsegs, off, prot, flags));
+}
+
+/**********************************************************************
+ * ISA DMA utility functions
+ **********************************************************************/
+
+/*
+ * Return 0 if all pages in the passed buffer lie within the DMA'able
+ * range RAM.
+ */
+int
+_isa_dma_check_buffer(buf, buflen, segcnt, boundary, p)
+ void *buf;
+ bus_size_t buflen;
+ int segcnt;
+ bus_size_t boundary;
+ struct proc *p;
+{
+ vaddr_t vaddr = (vaddr_t)buf;
+ vaddr_t endva;
+ paddr_t pa, lastpa;
+ u_long pagemask = ~(boundary - 1);
+ pmap_t pmap;
+ int nsegs;
+
+ endva = round_page(vaddr + buflen);
+
+ nsegs = 1;
+ lastpa = 0;
+
+ if (p != NULL)
+ pmap = p->p_vmspace->vm_map.pmap;
+ else
+ pmap = pmap_kernel();
+
+ for (; vaddr < endva; vaddr += NBPG) {
+ /*
+ * Get physical address for this segment.
+ */
+ pmap_extract(pmap, (vaddr_t)vaddr, &pa);
+ pa = trunc_page(pa);
+
+ /*
+ * Is it below the DMA'able threshold?
+ */
+ if (pa > ISA_DMA_BOUNCE_THRESHOLD)
+ return (EINVAL);
+
+ if (lastpa) {
+ /*
+ * Check excessive segment count.
+ */
+ if (lastpa + NBPG != pa) {
+ if (++nsegs > segcnt)
+ return (EFBIG);
+ }
+
+ /*
+ * Check boundary restriction.
+ */
+ if (boundary) {
+ if ((lastpa ^ pa) & pagemask)
+ return (EINVAL);
+ }
+ }
+ lastpa = pa;
+ }
+
+ return (0);
+}
+
+int
+_isa_dma_alloc_bouncebuf(t, map, size, flags)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+ bus_size_t size;
+ int flags;
+{
+ struct i386_isa_dma_cookie *cookie = map->_dm_cookie;
+ int error = 0;
+
+ cookie->id_bouncebuflen = round_page(size);
+ error = _isa_bus_dmamem_alloc(t, cookie->id_bouncebuflen,
+ NBPG, map->_dm_boundary, cookie->id_bouncesegs,
+ map->_dm_segcnt, &cookie->id_nbouncesegs, flags);
+ if (error)
+ goto out;
+ error = _isa_bus_dmamem_map(t, cookie->id_bouncesegs,
+ cookie->id_nbouncesegs, cookie->id_bouncebuflen,
+ (caddr_t *)&cookie->id_bouncebuf, flags);
+
+ out:
+ if (error) {
+ _isa_bus_dmamem_free(t, cookie->id_bouncesegs,
+ cookie->id_nbouncesegs);
+ cookie->id_bouncebuflen = 0;
+ cookie->id_nbouncesegs = 0;
+ } else {
+ cookie->id_flags |= ID_HAS_BOUNCE;
+ STAT_INCR(isa_dma_stats_nbouncebufs);
+ }
+
+ return (error);
+}
+
+void
+_isa_dma_free_bouncebuf(t, map)
+ bus_dma_tag_t t;
+ bus_dmamap_t map;
+{
+ struct i386_isa_dma_cookie *cookie = map->_dm_cookie;
+
+ STAT_DECR(isa_dma_stats_nbouncebufs);
+
+ _isa_bus_dmamem_unmap(t, cookie->id_bouncebuf,
+ cookie->id_bouncebuflen);
+ _isa_bus_dmamem_free(t, cookie->id_bouncesegs,
+ cookie->id_nbouncesegs);
+ cookie->id_bouncebuflen = 0;
+ cookie->id_nbouncesegs = 0;
+ cookie->id_flags &= ~ID_HAS_BOUNCE;
+}
+#endif /* NISADMA > 0 */
diff --git a/sys/arch/amd64/pci/pchb.c b/sys/arch/amd64/pci/pchb.c
new file mode 100644
index 00000000000..4d1b614d7b3
--- /dev/null
+++ b/sys/arch/amd64/pci/pchb.c
@@ -0,0 +1,130 @@
+/* $OpenBSD: pchb.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: pchb.c,v 1.1 2003/04/26 18:39:50 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1996, 1998, 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <dev/pci/pcidevs.h>
+
+#include <arch/amd64/pci/pchbvar.h>
+
+#define PCISET_BRIDGETYPE_MASK 0x3
+#define PCISET_TYPE_COMPAT 0x1
+#define PCISET_TYPE_AUX 0x2
+
+#define PCISET_BUSCONFIG_REG 0x48
+#define PCISET_BRIDGE_NUMBER(reg) (((reg) >> 8) & 0xff)
+#define PCISET_PCI_BUS_NUMBER(reg) (((reg) >> 16) & 0xff)
+
+/* XXX should be in dev/ic/i82443reg.h */
+#define I82443BX_SDRAMC_REG 0x76
+
+/* XXX should be in dev/ic/i82424{reg.var}.h */
+#define I82424_CPU_BCTL_REG 0x53
+#define I82424_PCI_BCTL_REG 0x54
+
+#define I82424_BCTL_CPUMEM_POSTEN 0x01
+#define I82424_BCTL_CPUPCI_POSTEN 0x02
+#define I82424_BCTL_PCIMEM_BURSTEN 0x01
+#define I82424_BCTL_PCI_BURSTEN 0x02
+
+int pchbmatch __P((struct device *, void *, void *));
+void pchbattach __P((struct device *, struct device *, void *));
+
+int pchb_print __P((void *, const char *));
+
+struct cfattach pchb_ca = {
+ sizeof(struct pchb_softc), pchbmatch, pchbattach,
+};
+
+struct cfdriver pchb_cd = {
+ NULL, "pchb", DV_DULL
+};
+
+int
+pchbmatch(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct pci_attach_args *pa = aux;
+
+ if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
+ PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_HOST) {
+ return (1);
+ }
+
+ return (0);
+}
+
+void
+pchbattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct pci_attach_args *pa = aux;
+
+ printf("\n");
+
+ switch (PCI_VENDOR(pa->pa_id)) {
+ /* Nothing yet */
+ default:
+ break;
+ }
+
+}
+
+int
+pchb_print(aux, pnp)
+ void *aux;
+ const char *pnp;
+{
+ struct pcibus_attach_args *pba = aux;
+
+ if (pnp)
+ printf("%s at %s", pba->pba_busname, pnp);
+ printf(" bus %d", pba->pba_bus);
+ return (UNCONF);
+}
diff --git a/sys/arch/amd64/pci/pchbvar.h b/sys/arch/amd64/pci/pchbvar.h
new file mode 100644
index 00000000000..9e573bb97e3
--- /dev/null
+++ b/sys/arch/amd64/pci/pchbvar.h
@@ -0,0 +1,61 @@
+/* $NetBSD: pchbvar.h,v 1.1 2003/04/26 18:39:51 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef _I386_PCI_PCHBVAR_H_
+#define _I386_PCI_PCHBVAR_H_
+
+#include <sys/timeout.h>
+
+struct pchb_softc {
+ struct device sc_dev;
+
+ bus_space_tag_t sc_st;
+ bus_space_handle_t sc_sh;
+
+#if 0
+ struct callout sc_rnd_ch;
+ rndsource_element_t sc_rnd_source;
+#endif
+
+ int sc_rnd_i;
+ u_int32_t sc_rnd_ax;
+};
+
+void pchb_attach_rnd(struct pchb_softc *, struct pci_attach_args *);
+
+#endif /* _I386_PCI_PCHBVAR_H_ */
diff --git a/sys/arch/amd64/pci/pci_machdep.c b/sys/arch/amd64/pci/pci_machdep.c
new file mode 100644
index 00000000000..138afc1ba23
--- /dev/null
+++ b/sys/arch/amd64/pci/pci_machdep.c
@@ -0,0 +1,693 @@
+/* $OpenBSD: pci_machdep.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: pci_machdep.c,v 1.3 2003/05/07 21:33:58 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
+ * Copyright (c) 1994 Charles M. Hannum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Charles M. Hannum.
+ * 4. 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.
+ */
+
+/*
+ * Machine-specific functions for PCI autoconfiguration.
+ *
+ * On PCs, there are two methods of generating PCI configuration cycles.
+ * We try to detect the appropriate mechanism for this machine and set
+ * up a few function pointers to access the correct method directly.
+ *
+ * The configuration method can be hard-coded in the config file by
+ * using `options PCI_CONF_MODE=N', where `N' is the configuration mode
+ * as defined section 3.6.4.1, `Generating Configuration Cycles'.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/device.h>
+#include <sys/lock.h>
+
+#include <uvm/uvm_extern.h>
+
+#define _X86_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+
+#include <machine/pio.h>
+#include <machine/intr.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcidevs.h>
+
+#include "ioapic.h"
+
+#if NIOAPIC > 0
+#include <machine/i82093var.h>
+#include <machine/mpbiosvar.h>
+#endif
+
+int pci_mode = -1;
+
+#ifdef MULTIPROCESSOR
+struct simplelock pci_conf_slock = SIMPLELOCK_INITIALIZER;
+#else
+struct simplelock pci_conf_slock = { 0 };
+#endif
+
+#define PCI_CONF_LOCK(s) \
+do { \
+ (s) = splhigh(); \
+ simple_lock(&pci_conf_slock); \
+} while (0)
+
+#define PCI_CONF_UNLOCK(s) \
+do { \
+ simple_unlock(&pci_conf_slock); \
+ splx((s)); \
+} while (0)
+
+#define PCI_MODE1_ENABLE 0x80000000UL
+#define PCI_MODE1_ADDRESS_REG 0x0cf8
+#define PCI_MODE1_DATA_REG 0x0cfc
+
+#define PCI_MODE2_ENABLE_REG 0x0cf8
+#define PCI_MODE2_FORWARD_REG 0x0cfa
+
+#define PCI_ID_CODE(vid,pid) \
+ ((((vid) & PCI_VENDOR_MASK) << PCI_VENDOR_SHIFT) | \
+ (((pid) & PCI_PRODUCT_MASK) << PCI_PRODUCT_SHIFT)) \
+
+#define _m1tag(b, d, f) \
+ (PCI_MODE1_ENABLE | ((b) << 16) | ((d) << 11) | ((f) << 8))
+#define _qe(bus, dev, fcn, vend, prod) \
+ {_m1tag(bus, dev, fcn), PCI_ID_CODE(vend, prod)}
+struct {
+ u_int32_t tag;
+ pcireg_t id;
+} pcim1_quirk_tbl[] = {
+ _qe(0, 0, 0, PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX1),
+ /* XXX Triflex2 not tested */
+ _qe(0, 0, 0, PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX2),
+ _qe(0, 0, 0, PCI_VENDOR_COMPAQ, PCI_PRODUCT_COMPAQ_TRIFLEX4),
+ /* Triton needed for Connectix Virtual PC */
+ _qe(0, 0, 0, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82437FX),
+ /* Connectix Virtual PC 5 has a 440BX */
+ _qe(0, 0, 0, PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82443BX_NOAGP),
+ {0, 0xffffffff} /* patchable */
+};
+#undef _m1tag
+#undef _id
+#undef _qe
+
+/*
+ * PCI doesn't have any special needs; just use the generic versions
+ * of these functions.
+ */
+struct x86_bus_dma_tag pci_bus_dma_tag = {
+ NULL, /* _may_bounce */
+ _bus_dmamap_create,
+ _bus_dmamap_destroy,
+ _bus_dmamap_load,
+ _bus_dmamap_load_mbuf,
+ _bus_dmamap_load_uio,
+ _bus_dmamap_load_raw,
+ _bus_dmamap_unload,
+ NULL,
+ _bus_dmamem_alloc,
+ _bus_dmamem_free,
+ _bus_dmamem_map,
+ _bus_dmamem_unmap,
+ _bus_dmamem_mmap,
+};
+
+void
+pci_attach_hook(parent, self, pba)
+ struct device *parent, *self;
+ struct pcibus_attach_args *pba;
+{
+
+ if (pba->pba_bus == 0)
+ printf(": configuration mode %d", pci_mode);
+}
+
+int
+pci_bus_maxdevs(pc, busno)
+ pci_chipset_tag_t pc;
+ int busno;
+{
+
+ /*
+ * Bus number is irrelevant. If Configuration Mechanism 2 is in
+ * use, can only have devices 0-15 on any bus. If Configuration
+ * Mechanism 1 is in use, can have devices 0-32 (i.e. the `normal'
+ * range).
+ */
+ if (pci_mode == 2)
+ return (16);
+ else
+ return (32);
+}
+
+pcitag_t
+pci_make_tag(pc, bus, device, function)
+ pci_chipset_tag_t pc;
+ int bus, device, function;
+{
+ pcitag_t tag;
+
+#ifndef PCI_CONF_MODE
+ switch (pci_mode) {
+ case 1:
+ goto mode1;
+ case 2:
+ goto mode2;
+ default:
+ panic("pci_make_tag: mode not configured");
+ }
+#endif
+
+#if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1)
+#ifndef PCI_CONF_MODE
+mode1:
+#endif
+ if (bus >= 256 || device >= 32 || function >= 8)
+ panic("pci_make_tag: bad request");
+
+ tag.mode1 = PCI_MODE1_ENABLE |
+ (bus << 16) | (device << 11) | (function << 8);
+ return tag;
+#endif
+
+#if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2)
+#ifndef PCI_CONF_MODE
+mode2:
+#endif
+ if (bus >= 256 || device >= 16 || function >= 8)
+ panic("pci_make_tag: bad request");
+
+ tag.mode2.port = 0xc000 | (device << 8);
+ tag.mode2.enable = 0xf0 | (function << 1);
+ tag.mode2.forward = bus;
+ return tag;
+#endif
+}
+
+void
+pci_decompose_tag(pc, tag, bp, dp, fp)
+ pci_chipset_tag_t pc;
+ pcitag_t tag;
+ int *bp, *dp, *fp;
+{
+
+#ifndef PCI_CONF_MODE
+ switch (pci_mode) {
+ case 1:
+ goto mode1;
+ case 2:
+ goto mode2;
+ default:
+ panic("pci_decompose_tag: mode not configured");
+ }
+#endif
+
+#if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1)
+#ifndef PCI_CONF_MODE
+mode1:
+#endif
+ if (bp != NULL)
+ *bp = (tag.mode1 >> 16) & 0xff;
+ if (dp != NULL)
+ *dp = (tag.mode1 >> 11) & 0x1f;
+ if (fp != NULL)
+ *fp = (tag.mode1 >> 8) & 0x7;
+ return;
+#endif
+
+#if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2)
+#ifndef PCI_CONF_MODE
+mode2:
+#endif
+ if (bp != NULL)
+ *bp = tag.mode2.forward & 0xff;
+ if (dp != NULL)
+ *dp = (tag.mode2.port >> 8) & 0xf;
+ if (fp != NULL)
+ *fp = (tag.mode2.enable >> 1) & 0x7;
+#endif
+}
+
+pcireg_t
+pci_conf_read(pc, tag, reg)
+ pci_chipset_tag_t pc;
+ pcitag_t tag;
+ int reg;
+{
+ pcireg_t data;
+ int s;
+
+#ifndef PCI_CONF_MODE
+ switch (pci_mode) {
+ case 1:
+ goto mode1;
+ case 2:
+ goto mode2;
+ default:
+ panic("pci_conf_read: mode not configured");
+ }
+#endif
+
+#if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1)
+#ifndef PCI_CONF_MODE
+mode1:
+#endif
+ PCI_CONF_LOCK(s);
+ outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg);
+ data = inl(PCI_MODE1_DATA_REG);
+ outl(PCI_MODE1_ADDRESS_REG, 0);
+ PCI_CONF_UNLOCK(s);
+ return data;
+#endif
+
+#if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2)
+#ifndef PCI_CONF_MODE
+mode2:
+#endif
+ PCI_CONF_LOCK(s);
+ outb(PCI_MODE2_ENABLE_REG, tag.mode2.enable);
+ outb(PCI_MODE2_FORWARD_REG, tag.mode2.forward);
+ data = inl(tag.mode2.port | reg);
+ outb(PCI_MODE2_ENABLE_REG, 0);
+ PCI_CONF_UNLOCK(s);
+ return data;
+#endif
+}
+
+void
+pci_conf_write(pc, tag, reg, data)
+ pci_chipset_tag_t pc;
+ pcitag_t tag;
+ int reg;
+ pcireg_t data;
+{
+ int s;
+
+#ifndef PCI_CONF_MODE
+ switch (pci_mode) {
+ case 1:
+ goto mode1;
+ case 2:
+ goto mode2;
+ default:
+ panic("pci_conf_write: mode not configured");
+ }
+#endif
+
+#if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 1)
+#ifndef PCI_CONF_MODE
+mode1:
+#endif
+ PCI_CONF_LOCK(s);
+ outl(PCI_MODE1_ADDRESS_REG, tag.mode1 | reg);
+ outl(PCI_MODE1_DATA_REG, data);
+ outl(PCI_MODE1_ADDRESS_REG, 0);
+ PCI_CONF_UNLOCK(s);
+ return;
+#endif
+
+#if !defined(PCI_CONF_MODE) || (PCI_CONF_MODE == 2)
+#ifndef PCI_CONF_MODE
+mode2:
+#endif
+ PCI_CONF_LOCK(s);
+ outb(PCI_MODE2_ENABLE_REG, tag.mode2.enable);
+ outb(PCI_MODE2_FORWARD_REG, tag.mode2.forward);
+ outl(tag.mode2.port | reg, data);
+ outb(PCI_MODE2_ENABLE_REG, 0);
+ PCI_CONF_UNLOCK(s);
+#endif
+}
+
+int
+pci_mode_detect()
+{
+
+#ifdef PCI_CONF_MODE
+#if (PCI_CONF_MODE == 1) || (PCI_CONF_MODE == 2)
+ return (pci_mode = PCI_CONF_MODE);
+#else
+#error Invalid PCI configuration mode.
+#endif
+#else
+ u_int32_t sav, val;
+ int i;
+ pcireg_t idreg;
+
+ if (pci_mode != -1)
+ return pci_mode;
+
+ /*
+ * We try to divine which configuration mode the host bridge wants.
+ */
+
+ sav = inl(PCI_MODE1_ADDRESS_REG);
+
+ pci_mode = 1; /* assume this for now */
+ /*
+ * catch some known buggy implementations of mode 1
+ */
+ for (i = 0; i < sizeof(pcim1_quirk_tbl) / sizeof(pcim1_quirk_tbl[0]);
+ i++) {
+ pcitag_t t;
+
+ if (!pcim1_quirk_tbl[i].tag)
+ break;
+ t.mode1 = pcim1_quirk_tbl[i].tag;
+ idreg = pci_conf_read(0, t, PCI_ID_REG); /* needs "pci_mode" */
+ if (idreg == pcim1_quirk_tbl[i].id) {
+#ifdef DEBUG
+ printf("known mode 1 PCI chipset (%08x)\n",
+ idreg);
+#endif
+ return (pci_mode);
+ }
+ }
+
+ /*
+ * Strong check for standard compliant mode 1:
+ * 1. bit 31 ("enable") can be set
+ * 2. byte/word access does not affect register
+ */
+ outl(PCI_MODE1_ADDRESS_REG, PCI_MODE1_ENABLE);
+ outb(PCI_MODE1_ADDRESS_REG + 3, 0);
+ outw(PCI_MODE1_ADDRESS_REG + 2, 0);
+ val = inl(PCI_MODE1_ADDRESS_REG);
+ if ((val & 0x80fffffc) != PCI_MODE1_ENABLE) {
+#ifdef DEBUG
+ printf("pci_mode_detect: mode 1 enable failed (%x)\n",
+ val);
+#endif
+ goto not1;
+ }
+ outl(PCI_MODE1_ADDRESS_REG, 0);
+ val = inl(PCI_MODE1_ADDRESS_REG);
+ if ((val & 0x80fffffc) != 0)
+ goto not1;
+ return (pci_mode);
+not1:
+ outl(PCI_MODE1_ADDRESS_REG, sav);
+
+ /*
+ * This mode 2 check is quite weak (and known to give false
+ * positives on some Compaq machines).
+ * However, this doesn't matter, because this is the
+ * last test, and simply no PCI devices will be found if
+ * this happens.
+ */
+ outb(PCI_MODE2_ENABLE_REG, 0);
+ outb(PCI_MODE2_FORWARD_REG, 0);
+ if (inb(PCI_MODE2_ENABLE_REG) != 0 ||
+ inb(PCI_MODE2_FORWARD_REG) != 0)
+ goto not2;
+ return (pci_mode = 2);
+not2:
+
+ return (pci_mode = 0);
+#endif
+}
+
+int
+pci_intr_map(pa, ihp)
+ struct pci_attach_args *pa;
+ pci_intr_handle_t *ihp;
+{
+ int pin = pa->pa_intrpin;
+ int line = pa->pa_intrline;
+#if NIOAPIC > 0
+ int rawpin = pa->pa_rawintrpin;
+ pci_chipset_tag_t pc = pa->pa_pc;
+ int bus, dev, func;
+#endif
+
+ if (pin == 0) {
+ /* No IRQ used. */
+ goto bad;
+ }
+
+ if (pin > PCI_INTERRUPT_PIN_MAX) {
+ printf("pci_intr_map: bad interrupt pin %d\n", pin);
+ goto bad;
+ }
+
+#if NIOAPIC > 0
+ pci_decompose_tag(pc, pa->pa_tag, &bus, &dev, &func);
+ if (mp_busses != NULL) {
+ if (intr_find_mpmapping(bus, (dev<<2)|(rawpin-1), ihp) == 0) {
+ *ihp |= line;
+ return 0;
+ }
+ /*
+ * No explicit PCI mapping found. This is not fatal,
+ * we'll try the ISA (or possibly EISA) mappings next.
+ */
+ }
+#endif
+
+ /*
+ * Section 6.2.4, `Miscellaneous Functions', says that 255 means
+ * `unknown' or `no connection' on a PC. We assume that a device with
+ * `no connection' either doesn't have an interrupt (in which case the
+ * pin number should be 0, and would have been noticed above), or
+ * wasn't configured by the BIOS (in which case we punt, since there's
+ * no real way we can know how the interrupt lines are mapped in the
+ * hardware).
+ *
+ * XXX
+ * Since IRQ 0 is only used by the clock, and we can't actually be sure
+ * that the BIOS did its job, we also recognize that as meaning that
+ * the BIOS has not configured the device.
+ */
+ if (line == 0 || line == X86_PCI_INTERRUPT_LINE_NO_CONNECTION) {
+ printf("pci_intr_map: no mapping for pin %c (line=%02x)\n",
+ '@' + pin, line);
+ goto bad;
+ } else {
+ if (line >= NUM_LEGACY_IRQS) {
+ printf("pci_intr_map: bad interrupt line %d\n", line);
+ goto bad;
+ }
+ if (line == 2) {
+ printf("pci_intr_map: changed line 2 to line 9\n");
+ line = 9;
+ }
+ }
+#if NIOAPIC > 0
+ if (mp_busses != NULL) {
+ if (intr_find_mpmapping(mp_isa_bus, line, ihp) == 0) {
+ *ihp |= line;
+ return 0;
+ }
+#if NEISA > 0
+ if (intr_find_mpmapping(mp_eisa_bus, line, ihp) == 0) {
+ *ihp |= line;
+ return 0;
+ }
+#endif
+ printf("pci_intr_map: bus %d dev %d func %d pin %d; line %d\n",
+ bus, dev, func, pin, line);
+ printf("pci_intr_map: no MP mapping found\n");
+ }
+#endif
+
+ *ihp = line;
+ return 0;
+
+bad:
+ *ihp = -1;
+ return 1;
+}
+
+const char *
+pci_intr_string(pc, ih)
+ pci_chipset_tag_t pc;
+ pci_intr_handle_t ih;
+{
+ static char irqstr[64];
+
+ if (ih == 0)
+ panic("pci_intr_string: bogus handle 0x%x", ih);
+
+
+#if NIOAPIC > 0
+ if (ih & APIC_INT_VIA_APIC)
+ snprintf(irqstr, sizeof(irqstr), "apic %d int %d (irq %d)",
+ APIC_IRQ_APIC(ih),
+ APIC_IRQ_PIN(ih),
+ ih&0xff);
+ else
+ snprintf(irqstr, sizeof(irqstr), "irq %d", ih&0xff);
+#else
+
+ snprintf(irqstr, sizeof(irqstr), "irq %d", ih&0xff);
+#endif
+ return (irqstr);
+
+}
+
+const struct evcnt *
+pci_intr_evcnt(pc, ih)
+ pci_chipset_tag_t pc;
+ pci_intr_handle_t ih;
+{
+
+ /* XXX for now, no evcnt parent reported */
+ return NULL;
+}
+
+void *
+pci_intr_establish(pc, ih, level, func, arg, what)
+ pci_chipset_tag_t pc;
+ pci_intr_handle_t ih;
+ int level, (*func)(void *);
+ void *arg;
+ char *what;
+{
+ int pin, irq;
+ struct pic *pic;
+
+ pic = &i8259_pic;
+ pin = irq = ih;
+
+#if NIOAPIC > 0
+ if (ih & APIC_INT_VIA_APIC) {
+ pic = (struct pic *)ioapic_find(APIC_IRQ_APIC(ih));
+ if (pic == NULL) {
+ printf("pci_intr_establish: bad ioapic %d\n",
+ APIC_IRQ_APIC(ih));
+ return NULL;
+ }
+ pin = APIC_IRQ_PIN(ih);
+ irq = APIC_IRQ_LEGACY_IRQ(ih);
+ if (irq < 0 || irq >= NUM_LEGACY_IRQS)
+ irq = -1;
+ }
+#endif
+
+ return intr_establish(irq, pic, pin, IST_LEVEL, level, func, arg);
+}
+
+void
+pci_intr_disestablish(pc, cookie)
+ pci_chipset_tag_t pc;
+ void *cookie;
+{
+
+ intr_disestablish(cookie);
+}
+
+/*
+ * Determine which flags should be passed to the primary PCI bus's
+ * autoconfiguration node. We use this to detect broken chipsets
+ * which cannot safely use memory-mapped device access.
+ */
+int
+pci_bus_flags()
+{
+ int rval = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
+ int device, maxndevs;
+ pcitag_t tag;
+ pcireg_t id;
+
+ maxndevs = pci_bus_maxdevs(NULL, 0);
+
+ for (device = 0; device < maxndevs; device++) {
+ tag = pci_make_tag(NULL, 0, device, 0);
+ id = pci_conf_read(NULL, tag, PCI_ID_REG);
+
+ /* Invalid vendor ID value? */
+ if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
+ continue;
+ /* XXX Not invalid, but we've done this ~forever. */
+ if (PCI_VENDOR(id) == 0)
+ continue;
+
+ switch (PCI_VENDOR(id)) {
+ case PCI_VENDOR_SIS:
+ switch (PCI_PRODUCT(id)) {
+ case PCI_PRODUCT_SIS_85C496:
+ goto disable_mem;
+ }
+ break;
+ }
+ }
+
+ return (rval);
+
+ disable_mem:
+ printf("Warning: broken PCI-Host bridge detected; "
+ "disabling memory-mapped access\n");
+ rval &= ~(PCI_FLAGS_MEM_ENABLED);
+ return (rval);
+}
diff --git a/sys/arch/amd64/pci/pciide_machdep.c b/sys/arch/amd64/pci/pciide_machdep.c
new file mode 100644
index 00000000000..9b24cf40032
--- /dev/null
+++ b/sys/arch/amd64/pci/pciide_machdep.c
@@ -0,0 +1,76 @@
+/* $OpenBSD: pciide_machdep.c,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
+/* $NetBSD: pciide_machdep.c,v 1.2 1999/02/19 18:01:27 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1998 Christopher G. Demetriou. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. 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.
+ */
+
+/*
+ * PCI IDE controller driver (i386 machine-dependent portion).
+ *
+ * Author: Christopher G. Demetriou, March 2, 1998 (derived from NetBSD
+ * sys/dev/pci/ppb.c, revision 1.16).
+ *
+ * See "PCI IDE Controller Specification, Revision 1.0 3/4/94" from the
+ * PCI SIG.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pciidereg.h>
+#include <dev/pci/pciidevar.h>
+
+#include <dev/isa/isavar.h>
+
+void *
+pciide_machdep_compat_intr_establish(dev, pa, chan, func, arg)
+ struct device *dev;
+ struct pci_attach_args *pa;
+ int chan;
+ int (*func)(void *);
+ void *arg;
+{
+ int irq;
+ void *cookie;
+
+ irq = PCIIDE_COMPAT_IRQ(chan);
+ cookie = isa_intr_establish(NULL, irq, IST_EDGE, IPL_BIO, func, arg, dev->dv_xname);
+
+ return (cookie);
+}
+
+void
+pciide_machdep_compat_intr_disestablish(pci_chipset_tag_t pc, void *cookie)
+{
+ isa_intr_disestablish(NULL, cookie);
+}
diff --git a/sys/compat/common/Makefile b/sys/compat/common/Makefile
index 49e3098dc34..2fdb75cea90 100644
--- a/sys/compat/common/Makefile
+++ b/sys/compat/common/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.14 2003/06/24 22:45:33 espie Exp $
+# $OpenBSD: Makefile,v 1.15 2004/01/28 01:39:39 mickey Exp $
# $NetBSD: Makefile,v 1.8 1996/05/18 15:52:19 christos Exp $
LIB= compat
@@ -15,7 +15,8 @@ SRCS= compat_exec.c compat_util.c compat_dir.c compat_vm.c \
vfs_syscalls_25.c vfs_syscalls_43.c vm_43.c
# really, all machines where sizeof(int) != sizeof(long)
-.if (${MACHINE_ARCH} != "alpha") && (${MACHINE_ARCH} != "sparc64")
+.if (${MACHINE_ARCH} != "alpha") && (${MACHINE_ARCH} != "x86_64") && \
+ (${MACHINE_ARCH} != "sparc64")
SRCS+= kern_ipc_10.c
.endif
diff --git a/sys/dev/isa/isavar.h b/sys/dev/isa/isavar.h
index 2289499bdb2..107ee3c3e35 100644
--- a/sys/dev/isa/isavar.h
+++ b/sys/dev/isa/isavar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: isavar.h,v 1.47 2004/01/15 17:51:42 miod Exp $ */
+/* $OpenBSD: isavar.h,v 1.48 2004/01/28 01:39:39 mickey Exp $ */
/* $NetBSD: isavar.h,v 1.26 1997/06/06 23:43:57 thorpej Exp $ */
/*-
@@ -122,7 +122,7 @@
*/
struct isabus_attach_args;
-#if (__alpha__ + amiga + __i386__ + arc + __wgrisc__ + __powerpc__ + __hppa__ != 1)
+#if (__alpha__ + amiga + __i386__ + arc + __wgrisc__ + __powerpc__ + __hppa__ + __amd64__ != 1)
#error "COMPILING ISA FOR UNSUPPORTED MACHINE, OR MORE THAN ONE."
#endif
#ifdef __alpha__
@@ -150,6 +150,9 @@ struct isabus_attach_args;
#ifdef __hppa__
#include <hppa/include/isa_machdep.h>
#endif
+#ifdef __amd64__
+#include <amd64/include/isa_machdep.h>
+#endif
#include "isapnp.h"
diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index 7148650ffad..29cda47f461 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/pci/pcivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcivar.h,v 1.33 2003/12/12 22:56:46 hshoexer Exp $ */
+/* $OpenBSD: pcivar.h,v 1.34 2004/01/28 01:39:40 mickey Exp $ */
/* $NetBSD: pcivar.h,v 1.23 1997/06/06 23:48:05 thorpej Exp $ */
/*
@@ -54,7 +54,7 @@ struct pcibus_attach_args;
/*
* Machine-dependent definitions.
*/
-#if (__alpha__ + __atari__ + __i386__ + __arc__ + __powerpc__ + __galileo__ + __sparc64__ + __hppa__ != 1)
+#if (__alpha__ + __atari__ + __i386__ + __arc__ + __powerpc__ + __galileo__ + __sparc64__ + __hppa__ +__amd64__ != 1)
#error COMPILING FOR UNSUPPORTED MACHINE, OR MORE THAN ONE.
#endif
#if __alpha__
@@ -81,6 +81,9 @@ struct pcibus_attach_args;
#if __sparc64__
#include <sparc64/include/pci_machdep.h>
#endif
+#if __amd64__
+#include <amd64/include/pci_machdep.h>
+#endif
/*
* PCI bus attach arguments.
diff --git a/sys/lib/libkern/arch/amd64/Makefile.inc b/sys/lib/libkern/arch/amd64/Makefile.inc
new file mode 100644
index 00000000000..ed61f7015e9
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/Makefile.inc
@@ -0,0 +1,14 @@
+# $NetBSD: Makefile.inc,v 1.2 2002/11/25 00:55:22 fvdl Exp $
+
+SRCS+= imax.c imin.c lmax.c lmin.c max.c min.c ulmax.c ulmin.c \
+ byte_swap_2.S byte_swap_4.S \
+ bcmp.S bcopy.S bzero.S ffs.S \
+ memchr.S memcmp.S memcpy.S memmove.S memset.S \
+ ovbcopy.S \
+ strcat.S strchr.S strcmp.S \
+ strcpy.S strlcpy.c strlcat.c strlen.S \
+ strncasecmp.c strncmp.c strncpy.c strrchr.S \
+ scanc.S skpc.S random.c
+# bswap64.c strcasecmp.c strncasecmp.c \ strtoul.c \
+
+CFLAGS+=-mcmodel=kernel
diff --git a/sys/lib/libkern/arch/amd64/bcmp.S b/sys/lib/libkern/arch/amd64/bcmp.S
new file mode 100644
index 00000000000..5cee3afe74b
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/bcmp.S
@@ -0,0 +1,24 @@
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: bcmp.S,v 1.1 2001/06/19 00:22:45 fvdl Exp $")
+#endif
+
+ENTRY(bcmp)
+ xorl %eax,%eax /* clear return value */
+ cld /* set compare direction forward */
+
+ movq %rdx,%rcx /* compare by words */
+ shrq $3,%rcx
+ repe
+ cmpsq
+ jne L1
+
+ movq %rdx,%rcx /* compare remainder by bytes */
+ andq $7,%rcx
+ repe
+ cmpsb
+ je L2
+
+L1: incl %eax
+L2: ret
diff --git a/sys/lib/libkern/arch/amd64/bcopy.S b/sys/lib/libkern/arch/amd64/bcopy.S
new file mode 100644
index 00000000000..c741cd66ca1
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/bcopy.S
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from locore.s.
+ *
+ * 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.
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: bcopy.S,v 1.1 2001/06/19 00:22:45 fvdl Exp $")
+#endif
+
+ /*
+ * (ov)bcopy (src,dst,cnt)
+ * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
+ */
+
+#ifdef MEMCOPY
+ENTRY(memcpy)
+#else
+#ifdef MEMMOVE
+ENTRY(memmove)
+#else
+#ifdef OVBCOPY
+ENTRY(ovbcopy)
+#else
+ENTRY(bcopy)
+#endif
+#endif
+#endif
+#if defined(MEMCOPY) || defined(MEMMOVE)
+ movq %rdi,%r11 /* save dest */
+#else
+ xchgq %rdi,%rsi
+#endif
+ movq %rdx,%rcx
+ movq %rdi,%rax
+ subq %rsi,%rax
+ cmpq %rcx,%rax /* overlapping? */
+ jb 1f
+ cld /* nope, copy forwards. */
+ shrq $3,%rcx /* copy by words */
+ rep
+ movsq
+ movq %rdx,%rcx
+ andq $7,%rcx /* any bytes left? */
+ rep
+ movsb
+#if defined(MEMCOPY) || defined(MEMMOVE)
+ movq %r11,%rax
+#endif
+ ret
+1:
+ addq %rcx,%rdi /* copy backwards. */
+ addq %rcx,%rsi
+ std
+ andq $7,%rcx /* any fractional bytes? */
+ decq %rdi
+ decq %rsi
+ rep
+ movsb
+ movq %rdx,%rcx /* copy remainder by words */
+ shrq $3,%rcx
+ subq $7,%rsi
+ subq $7,%rdi
+ rep
+ movsq
+#if defined(MEMCOPY) || defined(MEMMOVE)
+ movq %r11,%rax
+#endif
+ cld
+ ret
diff --git a/sys/lib/libkern/arch/amd64/byte_swap_2.S b/sys/lib/libkern/arch/amd64/byte_swap_2.S
new file mode 100644
index 00000000000..19ed5e27812
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/byte_swap_2.S
@@ -0,0 +1,52 @@
+/* $NetBSD: byte_swap_2.S,v 1.1 2001/06/19 00:22:45 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)htons.s 5.2 (Berkeley) 12/17/90
+ */
+
+#include <machine/asm.h>
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: byte_swap_2.S,v 1.1 2001/06/19 00:22:45 fvdl Exp $")
+#endif
+
+_ENTRY(_C_LABEL(bswap16))
+_ENTRY(_C_LABEL(ntohs))
+_ENTRY(_C_LABEL(htons))
+_PROF_PROLOGUE
+ movl %edi,%eax
+ xchgb %ah,%al
+ ret
diff --git a/sys/lib/libkern/arch/amd64/byte_swap_4.S b/sys/lib/libkern/arch/amd64/byte_swap_4.S
new file mode 100644
index 00000000000..f6a961e38f5
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/byte_swap_4.S
@@ -0,0 +1,52 @@
+/* $NetBSD: byte_swap_4.S,v 1.1 2001/06/19 00:22:45 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)htonl.s 5.3 (Berkeley) 12/17/90
+ */
+
+#include <machine/asm.h>
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: byte_swap_4.S,v 1.1 2001/06/19 00:22:45 fvdl Exp $")
+#endif
+
+_ENTRY(_C_LABEL(bswap32))
+_ENTRY(_C_LABEL(ntohl))
+_ENTRY(_C_LABEL(htonl))
+_PROF_PROLOGUE
+ movl %edi,%eax
+ bswap %eax
+ ret
diff --git a/sys/lib/libkern/arch/amd64/bzero.S b/sys/lib/libkern/arch/amd64/bzero.S
new file mode 100644
index 00000000000..6e4fe834d1a
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/bzero.S
@@ -0,0 +1,44 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: bzero.S,v 1.1 2001/06/19 00:22:45 fvdl Exp $")
+#endif
+
+ENTRY(bzero)
+ movq %rsi,%rdx
+
+ cld /* set fill direction forward */
+ xorq %rax,%rax /* set fill data to 0 */
+
+ /*
+ * if the string is too short, it's really not worth the overhead
+ * of aligning to word boundries, etc. So we jump to a plain
+ * unaligned set.
+ */
+ cmpq $16,%rdx
+ jb L1
+
+ movq %rdi,%rcx /* compute misalignment */
+ negq %rcx
+ andq $7,%rcx
+ subq %rcx,%rdx
+ rep /* zero until word aligned */
+ stosb
+
+ movq %rdx,%rcx /* zero by words */
+ shrq $3,%rcx
+ andq $7,%rdx
+ rep
+ stosq
+
+L1: movq %rdx,%rcx /* zero remainder by bytes */
+ rep
+ stosb
+
+ ret
diff --git a/sys/lib/libkern/arch/amd64/ffs.S b/sys/lib/libkern/arch/amd64/ffs.S
new file mode 100644
index 00000000000..c74c7010f54
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/ffs.S
@@ -0,0 +1,21 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: ffs.S,v 1.1 2001/06/19 00:22:46 fvdl Exp $")
+#endif
+
+ENTRY(ffs)
+ bsfl %edi,%eax
+ jz L1 /* ZF is set if all bits are 0 */
+ incl %eax /* bits numbered from 1, not 0 */
+ ret
+
+ _ALIGN_TEXT
+L1: xorl %eax,%eax /* clear result */
+ ret
diff --git a/sys/lib/libkern/arch/amd64/index.S b/sys/lib/libkern/arch/amd64/index.S
new file mode 100644
index 00000000000..60754f266f0
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/index.S
@@ -0,0 +1,29 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: index.S,v 1.1 2001/06/19 00:22:46 fvdl Exp $")
+#endif
+
+#ifdef STRCHR
+ENTRY(strchr)
+#else
+ENTRY(index)
+#endif
+ movq %rdi,%rax
+ movb %sil,%cl
+L1:
+ movb (%rax),%dl
+ cmpb %dl,%cl /* found char? */
+ je L2
+ incq %rax
+ testb %dl,%dl /* null terminator? */
+ jnz L1
+ xorq %rax,%rax
+L2:
+ ret
diff --git a/sys/lib/libkern/arch/amd64/memchr.S b/sys/lib/libkern/arch/amd64/memchr.S
new file mode 100644
index 00000000000..f978e760220
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/memchr.S
@@ -0,0 +1,25 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: memchr.S,v 1.1 2001/06/19 00:22:46 fvdl Exp $")
+#endif
+
+ENTRY(memchr)
+ movb %sil,%al /* set character to search for */
+ movq %rdx,%rcx /* set length of search */
+ testq %rcx,%rcx /* test for len == 0 */
+ jz L1
+ cld /* set search forward */
+ repne /* search! */
+ scasb
+ jne L1 /* scan failed, return null */
+ leaq -1(%rdi),%rax /* adjust result of scan */
+ ret
+L1: xorq %rax,%rax
+ ret
diff --git a/sys/lib/libkern/arch/amd64/memcmp.S b/sys/lib/libkern/arch/amd64/memcmp.S
new file mode 100644
index 00000000000..722a2a2c304
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/memcmp.S
@@ -0,0 +1,40 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: memcmp.S,v 1.1 2001/06/19 00:22:46 fvdl Exp $")
+#endif
+
+ENTRY(memcmp)
+ cld /* set compare direction forward */
+ movq %rdx,%rcx /* compare by longs */
+ shrq $3,%rcx
+ repe
+ cmpsq
+ jne L5 /* do we match so far? */
+
+ movq %rdx,%rcx /* compare remainder by bytes */
+ andq $7,%rcx
+ repe
+ cmpsb
+ jne L6 /* do we match? */
+
+ xorl %eax,%eax /* we match, return zero */
+ ret
+
+L5: movl $8,%ecx /* We know that one of the next */
+ subq %rcx,%rdi /* eight pairs of bytes do not */
+ subq %rcx,%rsi /* match. */
+ repe
+ cmpsb
+L6: xorl %eax,%eax /* Perform unsigned comparison */
+ movb -1(%rdi),%al
+ xorl %edx,%edx
+ movb -1(%rsi),%dl
+ subl %edx,%eax
+ ret
diff --git a/sys/lib/libkern/arch/amd64/memcpy.S b/sys/lib/libkern/arch/amd64/memcpy.S
new file mode 100644
index 00000000000..c39caa328a3
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/memcpy.S
@@ -0,0 +1,4 @@
+/* $NetBSD: memcpy.S,v 1.1 2001/06/19 00:22:46 fvdl Exp $ */
+
+#define MEMCOPY
+#include "bcopy.S"
diff --git a/sys/lib/libkern/arch/amd64/memmove.S b/sys/lib/libkern/arch/amd64/memmove.S
new file mode 100644
index 00000000000..f5b81357afa
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/memmove.S
@@ -0,0 +1,4 @@
+/* $NetBSD: memmove.S,v 1.1 2001/06/19 00:22:46 fvdl Exp $ */
+
+#define MEMMOVE
+#include "bcopy.S"
diff --git a/sys/lib/libkern/arch/amd64/memset.S b/sys/lib/libkern/arch/amd64/memset.S
new file mode 100644
index 00000000000..2d92dc66534
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/memset.S
@@ -0,0 +1,58 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: memset.S,v 1.1 2001/06/19 00:22:46 fvdl Exp $")
+#endif
+
+ENTRY(memset)
+ movq %rsi,%rax
+ movq %rdx,%rcx
+ movq %rdi,%r11
+
+ cld /* set fill direction forward */
+
+ /*
+ * if the string is too short, it's really not worth the overhead
+ * of aligning to word boundries, etc. So we jump to a plain
+ * unaligned set.
+ */
+ cmpq $0x0f,%rcx
+ jle L1
+
+ movb %al,%ah /* copy char to all bytes in word */
+ movl %eax,%edx
+ sall $16,%eax
+ orl %edx,%eax
+
+ movl %eax,%edx
+ salq $32,%rax
+ orq %rdx,%rax
+
+ movq %rdi,%rdx /* compute misalignment */
+ negq %rdx
+ andq $7,%rdx
+ movq %rcx,%r8
+ subq %rdx,%r8
+
+ movq %rdx,%rcx /* set until word aligned */
+ rep
+ stosb
+
+ movq %r8,%rcx
+ shrq $3,%rcx /* set by words */
+ rep
+ stosq
+
+ movq %r8,%rcx /* set remainder by bytes */
+ andq $7,%rcx
+L1: rep
+ stosb
+ movq %r11,%rax
+
+ ret
diff --git a/sys/lib/libkern/arch/amd64/ovbcopy.S b/sys/lib/libkern/arch/amd64/ovbcopy.S
new file mode 100644
index 00000000000..71f2c9c8ddc
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/ovbcopy.S
@@ -0,0 +1,4 @@
+/* $NetBSD: memmove.S,v 1.1 2001/06/19 00:22:46 fvdl Exp $ */
+
+#define OVBCOPY
+#include "bcopy.S"
diff --git a/sys/lib/libkern/arch/amd64/rindex.S b/sys/lib/libkern/arch/amd64/rindex.S
new file mode 100644
index 00000000000..6ba7c52a11f
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/rindex.S
@@ -0,0 +1,29 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: rindex.S,v 1.1 2001/06/19 00:22:47 fvdl Exp $")
+#endif
+
+#ifdef STRRCHR
+ENTRY(strrchr)
+#else
+ENTRY(rindex)
+#endif
+ movb %sil,%cl
+ xorq %rax,%rax /* init pointer to null */
+L1:
+ movb (%rdi),%dl
+ cmpb %dl,%cl
+ jne L2
+ movq %rdi,%rax
+L2:
+ incq %rdi
+ testb %dl,%dl /* null terminator??? */
+ jnz L1
+ ret
diff --git a/sys/lib/libkern/arch/amd64/scanc.S b/sys/lib/libkern/arch/amd64/scanc.S
new file mode 100644
index 00000000000..fd4fd31e129
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/scanc.S
@@ -0,0 +1,62 @@
+/* $NetBSD: scanc.S,v 1.1 2001/06/19 00:22:47 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+ENTRY(scanc)
+ movq %rdx,%r11
+ movb %cl,%dl
+ movl %edi,%ecx
+ testl %ecx,%ecx
+ jz 2f
+ movq %r11,%rdi
+ xorq %rax,%rax
+ cld
+1:
+ lodsb
+ testb %dl,(%rax,%rdi)
+ jnz 2f
+ decl %ecx
+ jnz 1b
+2:
+ movl %ecx,%eax
+ ret
diff --git a/sys/lib/libkern/arch/amd64/skpc.S b/sys/lib/libkern/arch/amd64/skpc.S
new file mode 100644
index 00000000000..f037d98b66a
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/skpc.S
@@ -0,0 +1,56 @@
+/* $NetBSD: skpc.S,v 1.1 2001/06/19 00:22:47 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+ENTRY(skpc)
+ movl %edi,%eax
+ movq %rsi,%rcx
+ movq %rdx,%rdi
+ cld
+ repe
+ scasb
+ je 1f
+ incq %rcx
+1:
+ movl %ecx,%eax
+ ret
diff --git a/sys/lib/libkern/arch/amd64/strcat.S b/sys/lib/libkern/arch/amd64/strcat.S
new file mode 100644
index 00000000000..7dc71244312
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/strcat.S
@@ -0,0 +1,65 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: strcat.S,v 1.1 2001/06/19 00:22:47 fvdl Exp $")
+#endif
+
+/*
+ * NOTE: I've unrolled the loop eight times: large enough to make a
+ * significant difference, and small enough not to totally trash the
+ * cache.
+ */
+
+ENTRY(strcat)
+ movq %rdi,%r11
+
+ cld /* set search forward */
+ xorl %eax,%eax /* set search for null terminator */
+ movq $-1,%rcx /* set search for lots of characters */
+ repne /* search! */
+ scasb
+
+ decq %rdi
+
+L1: movb (%rsi),%al /* unroll loop, but not too much */
+ movb %al,(%rdi)
+ testb %al,%al
+ jz L2
+ movb 1(%rsi),%al
+ movb %al,1(%rdi)
+ testb %al,%al
+ jz L2
+ movb 2(%rsi),%al
+ movb %al,2(%rdi)
+ testb %al,%al
+ jz L2
+ movb 3(%rsi),%al
+ movb %al,3(%rdi)
+ testb %al,%al
+ jz L2
+ movb 4(%rsi),%al
+ movb %al,4(%rdi)
+ testb %al,%al
+ jz L2
+ movb 5(%rsi),%al
+ movb %al,5(%rdi)
+ testb %al,%al
+ jz L2
+ movb 6(%rsi),%al
+ movb %al,6(%rdi)
+ testb %al,%al
+ jz L2
+ movb 7(%rsi),%al
+ movb %al,7(%rdi)
+ addq $8,%rsi
+ addq $8,%rdi
+ testb %al,%al
+ jnz L1
+L2: movq %r11,%rax
+ ret
diff --git a/sys/lib/libkern/arch/amd64/strchr.S b/sys/lib/libkern/arch/amd64/strchr.S
new file mode 100644
index 00000000000..91fd708891f
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/strchr.S
@@ -0,0 +1,4 @@
+/* $NetBSD: strchr.S,v 1.1 2001/06/19 00:22:47 fvdl Exp $ */
+
+#define STRCHR
+#include "index.S"
diff --git a/sys/lib/libkern/arch/amd64/strcmp.S b/sys/lib/libkern/arch/amd64/strcmp.S
new file mode 100644
index 00000000000..559563666d4
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/strcmp.S
@@ -0,0 +1,88 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: strcmp.S,v 1.1 2001/06/19 00:22:47 fvdl Exp $")
+#endif
+
+/*
+ * NOTE: I've unrolled the loop eight times: large enough to make a
+ * significant difference, and small enough not to totally trash the
+ * cache.
+ */
+
+ENTRY(strcmp)
+ jmp L2 /* Jump into the loop. */
+
+L1: incq %rdi
+ incq %rsi
+L2: movb (%rdi),%cl
+ testb %cl,%cl /* null terminator */
+ jz L3
+ cmpb %cl,(%rsi) /* chars match */
+ jne L3
+
+ incq %rdi
+ incq %rsi
+ movb (%rdi),%cl
+ testb %cl,%cl
+ jz L3
+ cmpb %cl,(%rsi)
+ jne L3
+
+ incq %rdi
+ incq %rsi
+ movb (%rdi),%cl
+ testb %cl,%cl
+ jz L3
+ cmpb %cl,(%rsi)
+ jne L3
+
+ incq %rdi
+ incq %rsi
+ movb (%rdi),%cl
+ testb %cl,%cl
+ jz L3
+ cmpb %cl,(%rsi)
+ jne L3
+
+ incq %rdi
+ incq %rsi
+ movb (%rdi),%cl
+ testb %cl,%cl
+ jz L3
+ cmpb %cl,(%rsi)
+ jne L3
+
+ incq %rdi
+ incq %rsi
+ movb (%rdi),%cl
+ testb %cl,%cl
+ jz L3
+ cmpb %cl,(%rsi)
+ jne L3
+
+ incq %rdi
+ incq %rsi
+ movb (%rdi),%cl
+ testb %cl,%cl
+ jz L3
+ cmpb %cl,(%rsi)
+ jne L3
+
+ incq %rdi
+ incq %rsi
+ movb (%rdi),%cl
+ testb %cl,%cl
+ jz L3
+ cmpb %cl,(%rsi)
+ je L1
+L3: movzbl (%rdi),%eax /* unsigned comparison */
+ movzbl (%rsi),%edx
+ subl %edx,%eax
+ ret
diff --git a/sys/lib/libkern/arch/amd64/strcpy.S b/sys/lib/libkern/arch/amd64/strcpy.S
new file mode 100644
index 00000000000..924dfffd5be
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/strcpy.S
@@ -0,0 +1,57 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: strcpy.S,v 1.1 2001/06/19 00:22:47 fvdl Exp $")
+#endif
+
+/*
+ * NOTE: I've unrolled the loop eight times: large enough to make a
+ * significant difference, and small enough not to totally trash the
+ * cache.
+ */
+
+ENTRY(strcpy)
+ movq %rdi,%r11
+
+L1: movb (%rsi),%al /* unroll loop, but not too much */
+ movb %al,(%rdi)
+ testb %al,%al
+ jz L2
+ movb 1(%rsi),%al
+ movb %al,1(%rdi)
+ testb %al,%al
+ jz L2
+ movb 2(%rsi),%al
+ movb %al,2(%rdi)
+ testb %al,%al
+ jz L2
+ movb 3(%rsi),%al
+ movb %al,3(%rdi)
+ testb %al,%al
+ jz L2
+ movb 4(%rsi),%al
+ movb %al,4(%rdi)
+ testb %al,%al
+ jz L2
+ movb 5(%rsi),%al
+ movb %al,5(%rdi)
+ testb %al,%al
+ jz L2
+ movb 6(%rsi),%al
+ movb %al,6(%rdi)
+ testb %al,%al
+ jz L2
+ movb 7(%rsi),%al
+ movb %al,7(%rdi)
+ addq $8,%rsi
+ addq $8,%rdi
+ testb %al,%al
+ jnz L1
+L2: movq %r11,%rax
+ ret
diff --git a/sys/lib/libkern/arch/amd64/strlen.S b/sys/lib/libkern/arch/amd64/strlen.S
new file mode 100644
index 00000000000..3c85659391a
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/strlen.S
@@ -0,0 +1,21 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: strlen.S,v 1.1 2001/06/19 00:22:47 fvdl Exp $")
+#endif
+
+ENTRY(strlen)
+ cld /* set search forward */
+ xorl %eax,%eax /* set search for null terminator */
+ movq $-1,%rcx /* set search for lots of characters */
+ repne /* search! */
+ scasb
+ notq %rcx /* get length by taking complement */
+ leaq -1(%rcx),%rax /* and subtracting one */
+ ret
diff --git a/sys/lib/libkern/arch/amd64/strrchr.S b/sys/lib/libkern/arch/amd64/strrchr.S
new file mode 100644
index 00000000000..9b23edfb435
--- /dev/null
+++ b/sys/lib/libkern/arch/amd64/strrchr.S
@@ -0,0 +1,4 @@
+/* $NetBSD: strrchr.S,v 1.1 2001/06/19 00:22:47 fvdl Exp $ */
+
+#define STRRCHR
+#include "rindex.S"
diff --git a/sys/lib/libkern/arch/x86_64/Makefile.inc b/sys/lib/libkern/arch/x86_64/Makefile.inc
new file mode 100644
index 00000000000..ed61f7015e9
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/Makefile.inc
@@ -0,0 +1,14 @@
+# $NetBSD: Makefile.inc,v 1.2 2002/11/25 00:55:22 fvdl Exp $
+
+SRCS+= imax.c imin.c lmax.c lmin.c max.c min.c ulmax.c ulmin.c \
+ byte_swap_2.S byte_swap_4.S \
+ bcmp.S bcopy.S bzero.S ffs.S \
+ memchr.S memcmp.S memcpy.S memmove.S memset.S \
+ ovbcopy.S \
+ strcat.S strchr.S strcmp.S \
+ strcpy.S strlcpy.c strlcat.c strlen.S \
+ strncasecmp.c strncmp.c strncpy.c strrchr.S \
+ scanc.S skpc.S random.c
+# bswap64.c strcasecmp.c strncasecmp.c \ strtoul.c \
+
+CFLAGS+=-mcmodel=kernel
diff --git a/sys/lib/libkern/arch/x86_64/bcmp.S b/sys/lib/libkern/arch/x86_64/bcmp.S
new file mode 100644
index 00000000000..5cee3afe74b
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/bcmp.S
@@ -0,0 +1,24 @@
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: bcmp.S,v 1.1 2001/06/19 00:22:45 fvdl Exp $")
+#endif
+
+ENTRY(bcmp)
+ xorl %eax,%eax /* clear return value */
+ cld /* set compare direction forward */
+
+ movq %rdx,%rcx /* compare by words */
+ shrq $3,%rcx
+ repe
+ cmpsq
+ jne L1
+
+ movq %rdx,%rcx /* compare remainder by bytes */
+ andq $7,%rcx
+ repe
+ cmpsb
+ je L2
+
+L1: incl %eax
+L2: ret
diff --git a/sys/lib/libkern/arch/x86_64/bcopy.S b/sys/lib/libkern/arch/x86_64/bcopy.S
new file mode 100644
index 00000000000..c741cd66ca1
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/bcopy.S
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from locore.s.
+ *
+ * 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.
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: bcopy.S,v 1.1 2001/06/19 00:22:45 fvdl Exp $")
+#endif
+
+ /*
+ * (ov)bcopy (src,dst,cnt)
+ * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
+ */
+
+#ifdef MEMCOPY
+ENTRY(memcpy)
+#else
+#ifdef MEMMOVE
+ENTRY(memmove)
+#else
+#ifdef OVBCOPY
+ENTRY(ovbcopy)
+#else
+ENTRY(bcopy)
+#endif
+#endif
+#endif
+#if defined(MEMCOPY) || defined(MEMMOVE)
+ movq %rdi,%r11 /* save dest */
+#else
+ xchgq %rdi,%rsi
+#endif
+ movq %rdx,%rcx
+ movq %rdi,%rax
+ subq %rsi,%rax
+ cmpq %rcx,%rax /* overlapping? */
+ jb 1f
+ cld /* nope, copy forwards. */
+ shrq $3,%rcx /* copy by words */
+ rep
+ movsq
+ movq %rdx,%rcx
+ andq $7,%rcx /* any bytes left? */
+ rep
+ movsb
+#if defined(MEMCOPY) || defined(MEMMOVE)
+ movq %r11,%rax
+#endif
+ ret
+1:
+ addq %rcx,%rdi /* copy backwards. */
+ addq %rcx,%rsi
+ std
+ andq $7,%rcx /* any fractional bytes? */
+ decq %rdi
+ decq %rsi
+ rep
+ movsb
+ movq %rdx,%rcx /* copy remainder by words */
+ shrq $3,%rcx
+ subq $7,%rsi
+ subq $7,%rdi
+ rep
+ movsq
+#if defined(MEMCOPY) || defined(MEMMOVE)
+ movq %r11,%rax
+#endif
+ cld
+ ret
diff --git a/sys/lib/libkern/arch/x86_64/byte_swap_2.S b/sys/lib/libkern/arch/x86_64/byte_swap_2.S
new file mode 100644
index 00000000000..19ed5e27812
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/byte_swap_2.S
@@ -0,0 +1,52 @@
+/* $NetBSD: byte_swap_2.S,v 1.1 2001/06/19 00:22:45 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)htons.s 5.2 (Berkeley) 12/17/90
+ */
+
+#include <machine/asm.h>
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: byte_swap_2.S,v 1.1 2001/06/19 00:22:45 fvdl Exp $")
+#endif
+
+_ENTRY(_C_LABEL(bswap16))
+_ENTRY(_C_LABEL(ntohs))
+_ENTRY(_C_LABEL(htons))
+_PROF_PROLOGUE
+ movl %edi,%eax
+ xchgb %ah,%al
+ ret
diff --git a/sys/lib/libkern/arch/x86_64/byte_swap_4.S b/sys/lib/libkern/arch/x86_64/byte_swap_4.S
new file mode 100644
index 00000000000..f6a961e38f5
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/byte_swap_4.S
@@ -0,0 +1,52 @@
+/* $NetBSD: byte_swap_4.S,v 1.1 2001/06/19 00:22:45 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)htonl.s 5.3 (Berkeley) 12/17/90
+ */
+
+#include <machine/asm.h>
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: byte_swap_4.S,v 1.1 2001/06/19 00:22:45 fvdl Exp $")
+#endif
+
+_ENTRY(_C_LABEL(bswap32))
+_ENTRY(_C_LABEL(ntohl))
+_ENTRY(_C_LABEL(htonl))
+_PROF_PROLOGUE
+ movl %edi,%eax
+ bswap %eax
+ ret
diff --git a/sys/lib/libkern/arch/x86_64/bzero.S b/sys/lib/libkern/arch/x86_64/bzero.S
new file mode 100644
index 00000000000..6e4fe834d1a
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/bzero.S
@@ -0,0 +1,44 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: bzero.S,v 1.1 2001/06/19 00:22:45 fvdl Exp $")
+#endif
+
+ENTRY(bzero)
+ movq %rsi,%rdx
+
+ cld /* set fill direction forward */
+ xorq %rax,%rax /* set fill data to 0 */
+
+ /*
+ * if the string is too short, it's really not worth the overhead
+ * of aligning to word boundries, etc. So we jump to a plain
+ * unaligned set.
+ */
+ cmpq $16,%rdx
+ jb L1
+
+ movq %rdi,%rcx /* compute misalignment */
+ negq %rcx
+ andq $7,%rcx
+ subq %rcx,%rdx
+ rep /* zero until word aligned */
+ stosb
+
+ movq %rdx,%rcx /* zero by words */
+ shrq $3,%rcx
+ andq $7,%rdx
+ rep
+ stosq
+
+L1: movq %rdx,%rcx /* zero remainder by bytes */
+ rep
+ stosb
+
+ ret
diff --git a/sys/lib/libkern/arch/x86_64/ffs.S b/sys/lib/libkern/arch/x86_64/ffs.S
new file mode 100644
index 00000000000..c74c7010f54
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/ffs.S
@@ -0,0 +1,21 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: ffs.S,v 1.1 2001/06/19 00:22:46 fvdl Exp $")
+#endif
+
+ENTRY(ffs)
+ bsfl %edi,%eax
+ jz L1 /* ZF is set if all bits are 0 */
+ incl %eax /* bits numbered from 1, not 0 */
+ ret
+
+ _ALIGN_TEXT
+L1: xorl %eax,%eax /* clear result */
+ ret
diff --git a/sys/lib/libkern/arch/x86_64/index.S b/sys/lib/libkern/arch/x86_64/index.S
new file mode 100644
index 00000000000..60754f266f0
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/index.S
@@ -0,0 +1,29 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: index.S,v 1.1 2001/06/19 00:22:46 fvdl Exp $")
+#endif
+
+#ifdef STRCHR
+ENTRY(strchr)
+#else
+ENTRY(index)
+#endif
+ movq %rdi,%rax
+ movb %sil,%cl
+L1:
+ movb (%rax),%dl
+ cmpb %dl,%cl /* found char? */
+ je L2
+ incq %rax
+ testb %dl,%dl /* null terminator? */
+ jnz L1
+ xorq %rax,%rax
+L2:
+ ret
diff --git a/sys/lib/libkern/arch/x86_64/memchr.S b/sys/lib/libkern/arch/x86_64/memchr.S
new file mode 100644
index 00000000000..f978e760220
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/memchr.S
@@ -0,0 +1,25 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: memchr.S,v 1.1 2001/06/19 00:22:46 fvdl Exp $")
+#endif
+
+ENTRY(memchr)
+ movb %sil,%al /* set character to search for */
+ movq %rdx,%rcx /* set length of search */
+ testq %rcx,%rcx /* test for len == 0 */
+ jz L1
+ cld /* set search forward */
+ repne /* search! */
+ scasb
+ jne L1 /* scan failed, return null */
+ leaq -1(%rdi),%rax /* adjust result of scan */
+ ret
+L1: xorq %rax,%rax
+ ret
diff --git a/sys/lib/libkern/arch/x86_64/memcmp.S b/sys/lib/libkern/arch/x86_64/memcmp.S
new file mode 100644
index 00000000000..722a2a2c304
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/memcmp.S
@@ -0,0 +1,40 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: memcmp.S,v 1.1 2001/06/19 00:22:46 fvdl Exp $")
+#endif
+
+ENTRY(memcmp)
+ cld /* set compare direction forward */
+ movq %rdx,%rcx /* compare by longs */
+ shrq $3,%rcx
+ repe
+ cmpsq
+ jne L5 /* do we match so far? */
+
+ movq %rdx,%rcx /* compare remainder by bytes */
+ andq $7,%rcx
+ repe
+ cmpsb
+ jne L6 /* do we match? */
+
+ xorl %eax,%eax /* we match, return zero */
+ ret
+
+L5: movl $8,%ecx /* We know that one of the next */
+ subq %rcx,%rdi /* eight pairs of bytes do not */
+ subq %rcx,%rsi /* match. */
+ repe
+ cmpsb
+L6: xorl %eax,%eax /* Perform unsigned comparison */
+ movb -1(%rdi),%al
+ xorl %edx,%edx
+ movb -1(%rsi),%dl
+ subl %edx,%eax
+ ret
diff --git a/sys/lib/libkern/arch/x86_64/memcpy.S b/sys/lib/libkern/arch/x86_64/memcpy.S
new file mode 100644
index 00000000000..c39caa328a3
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/memcpy.S
@@ -0,0 +1,4 @@
+/* $NetBSD: memcpy.S,v 1.1 2001/06/19 00:22:46 fvdl Exp $ */
+
+#define MEMCOPY
+#include "bcopy.S"
diff --git a/sys/lib/libkern/arch/x86_64/memmove.S b/sys/lib/libkern/arch/x86_64/memmove.S
new file mode 100644
index 00000000000..f5b81357afa
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/memmove.S
@@ -0,0 +1,4 @@
+/* $NetBSD: memmove.S,v 1.1 2001/06/19 00:22:46 fvdl Exp $ */
+
+#define MEMMOVE
+#include "bcopy.S"
diff --git a/sys/lib/libkern/arch/x86_64/memset.S b/sys/lib/libkern/arch/x86_64/memset.S
new file mode 100644
index 00000000000..2d92dc66534
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/memset.S
@@ -0,0 +1,58 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: memset.S,v 1.1 2001/06/19 00:22:46 fvdl Exp $")
+#endif
+
+ENTRY(memset)
+ movq %rsi,%rax
+ movq %rdx,%rcx
+ movq %rdi,%r11
+
+ cld /* set fill direction forward */
+
+ /*
+ * if the string is too short, it's really not worth the overhead
+ * of aligning to word boundries, etc. So we jump to a plain
+ * unaligned set.
+ */
+ cmpq $0x0f,%rcx
+ jle L1
+
+ movb %al,%ah /* copy char to all bytes in word */
+ movl %eax,%edx
+ sall $16,%eax
+ orl %edx,%eax
+
+ movl %eax,%edx
+ salq $32,%rax
+ orq %rdx,%rax
+
+ movq %rdi,%rdx /* compute misalignment */
+ negq %rdx
+ andq $7,%rdx
+ movq %rcx,%r8
+ subq %rdx,%r8
+
+ movq %rdx,%rcx /* set until word aligned */
+ rep
+ stosb
+
+ movq %r8,%rcx
+ shrq $3,%rcx /* set by words */
+ rep
+ stosq
+
+ movq %r8,%rcx /* set remainder by bytes */
+ andq $7,%rcx
+L1: rep
+ stosb
+ movq %r11,%rax
+
+ ret
diff --git a/sys/lib/libkern/arch/x86_64/ovbcopy.S b/sys/lib/libkern/arch/x86_64/ovbcopy.S
new file mode 100644
index 00000000000..71f2c9c8ddc
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/ovbcopy.S
@@ -0,0 +1,4 @@
+/* $NetBSD: memmove.S,v 1.1 2001/06/19 00:22:46 fvdl Exp $ */
+
+#define OVBCOPY
+#include "bcopy.S"
diff --git a/sys/lib/libkern/arch/x86_64/rindex.S b/sys/lib/libkern/arch/x86_64/rindex.S
new file mode 100644
index 00000000000..6ba7c52a11f
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/rindex.S
@@ -0,0 +1,29 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: rindex.S,v 1.1 2001/06/19 00:22:47 fvdl Exp $")
+#endif
+
+#ifdef STRRCHR
+ENTRY(strrchr)
+#else
+ENTRY(rindex)
+#endif
+ movb %sil,%cl
+ xorq %rax,%rax /* init pointer to null */
+L1:
+ movb (%rdi),%dl
+ cmpb %dl,%cl
+ jne L2
+ movq %rdi,%rax
+L2:
+ incq %rdi
+ testb %dl,%dl /* null terminator??? */
+ jnz L1
+ ret
diff --git a/sys/lib/libkern/arch/x86_64/scanc.S b/sys/lib/libkern/arch/x86_64/scanc.S
new file mode 100644
index 00000000000..fd4fd31e129
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/scanc.S
@@ -0,0 +1,62 @@
+/* $NetBSD: scanc.S,v 1.1 2001/06/19 00:22:47 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+ENTRY(scanc)
+ movq %rdx,%r11
+ movb %cl,%dl
+ movl %edi,%ecx
+ testl %ecx,%ecx
+ jz 2f
+ movq %r11,%rdi
+ xorq %rax,%rax
+ cld
+1:
+ lodsb
+ testb %dl,(%rax,%rdi)
+ jnz 2f
+ decl %ecx
+ jnz 1b
+2:
+ movl %ecx,%eax
+ ret
diff --git a/sys/lib/libkern/arch/x86_64/skpc.S b/sys/lib/libkern/arch/x86_64/skpc.S
new file mode 100644
index 00000000000..f037d98b66a
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/skpc.S
@@ -0,0 +1,56 @@
+/* $NetBSD: skpc.S,v 1.1 2001/06/19 00:22:47 fvdl Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+ENTRY(skpc)
+ movl %edi,%eax
+ movq %rsi,%rcx
+ movq %rdx,%rdi
+ cld
+ repe
+ scasb
+ je 1f
+ incq %rcx
+1:
+ movl %ecx,%eax
+ ret
diff --git a/sys/lib/libkern/arch/x86_64/strcat.S b/sys/lib/libkern/arch/x86_64/strcat.S
new file mode 100644
index 00000000000..7dc71244312
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/strcat.S
@@ -0,0 +1,65 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: strcat.S,v 1.1 2001/06/19 00:22:47 fvdl Exp $")
+#endif
+
+/*
+ * NOTE: I've unrolled the loop eight times: large enough to make a
+ * significant difference, and small enough not to totally trash the
+ * cache.
+ */
+
+ENTRY(strcat)
+ movq %rdi,%r11
+
+ cld /* set search forward */
+ xorl %eax,%eax /* set search for null terminator */
+ movq $-1,%rcx /* set search for lots of characters */
+ repne /* search! */
+ scasb
+
+ decq %rdi
+
+L1: movb (%rsi),%al /* unroll loop, but not too much */
+ movb %al,(%rdi)
+ testb %al,%al
+ jz L2
+ movb 1(%rsi),%al
+ movb %al,1(%rdi)
+ testb %al,%al
+ jz L2
+ movb 2(%rsi),%al
+ movb %al,2(%rdi)
+ testb %al,%al
+ jz L2
+ movb 3(%rsi),%al
+ movb %al,3(%rdi)
+ testb %al,%al
+ jz L2
+ movb 4(%rsi),%al
+ movb %al,4(%rdi)
+ testb %al,%al
+ jz L2
+ movb 5(%rsi),%al
+ movb %al,5(%rdi)
+ testb %al,%al
+ jz L2
+ movb 6(%rsi),%al
+ movb %al,6(%rdi)
+ testb %al,%al
+ jz L2
+ movb 7(%rsi),%al
+ movb %al,7(%rdi)
+ addq $8,%rsi
+ addq $8,%rdi
+ testb %al,%al
+ jnz L1
+L2: movq %r11,%rax
+ ret
diff --git a/sys/lib/libkern/arch/x86_64/strchr.S b/sys/lib/libkern/arch/x86_64/strchr.S
new file mode 100644
index 00000000000..91fd708891f
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/strchr.S
@@ -0,0 +1,4 @@
+/* $NetBSD: strchr.S,v 1.1 2001/06/19 00:22:47 fvdl Exp $ */
+
+#define STRCHR
+#include "index.S"
diff --git a/sys/lib/libkern/arch/x86_64/strcmp.S b/sys/lib/libkern/arch/x86_64/strcmp.S
new file mode 100644
index 00000000000..559563666d4
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/strcmp.S
@@ -0,0 +1,88 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: strcmp.S,v 1.1 2001/06/19 00:22:47 fvdl Exp $")
+#endif
+
+/*
+ * NOTE: I've unrolled the loop eight times: large enough to make a
+ * significant difference, and small enough not to totally trash the
+ * cache.
+ */
+
+ENTRY(strcmp)
+ jmp L2 /* Jump into the loop. */
+
+L1: incq %rdi
+ incq %rsi
+L2: movb (%rdi),%cl
+ testb %cl,%cl /* null terminator */
+ jz L3
+ cmpb %cl,(%rsi) /* chars match */
+ jne L3
+
+ incq %rdi
+ incq %rsi
+ movb (%rdi),%cl
+ testb %cl,%cl
+ jz L3
+ cmpb %cl,(%rsi)
+ jne L3
+
+ incq %rdi
+ incq %rsi
+ movb (%rdi),%cl
+ testb %cl,%cl
+ jz L3
+ cmpb %cl,(%rsi)
+ jne L3
+
+ incq %rdi
+ incq %rsi
+ movb (%rdi),%cl
+ testb %cl,%cl
+ jz L3
+ cmpb %cl,(%rsi)
+ jne L3
+
+ incq %rdi
+ incq %rsi
+ movb (%rdi),%cl
+ testb %cl,%cl
+ jz L3
+ cmpb %cl,(%rsi)
+ jne L3
+
+ incq %rdi
+ incq %rsi
+ movb (%rdi),%cl
+ testb %cl,%cl
+ jz L3
+ cmpb %cl,(%rsi)
+ jne L3
+
+ incq %rdi
+ incq %rsi
+ movb (%rdi),%cl
+ testb %cl,%cl
+ jz L3
+ cmpb %cl,(%rsi)
+ jne L3
+
+ incq %rdi
+ incq %rsi
+ movb (%rdi),%cl
+ testb %cl,%cl
+ jz L3
+ cmpb %cl,(%rsi)
+ je L1
+L3: movzbl (%rdi),%eax /* unsigned comparison */
+ movzbl (%rsi),%edx
+ subl %edx,%eax
+ ret
diff --git a/sys/lib/libkern/arch/x86_64/strcpy.S b/sys/lib/libkern/arch/x86_64/strcpy.S
new file mode 100644
index 00000000000..924dfffd5be
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/strcpy.S
@@ -0,0 +1,57 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: strcpy.S,v 1.1 2001/06/19 00:22:47 fvdl Exp $")
+#endif
+
+/*
+ * NOTE: I've unrolled the loop eight times: large enough to make a
+ * significant difference, and small enough not to totally trash the
+ * cache.
+ */
+
+ENTRY(strcpy)
+ movq %rdi,%r11
+
+L1: movb (%rsi),%al /* unroll loop, but not too much */
+ movb %al,(%rdi)
+ testb %al,%al
+ jz L2
+ movb 1(%rsi),%al
+ movb %al,1(%rdi)
+ testb %al,%al
+ jz L2
+ movb 2(%rsi),%al
+ movb %al,2(%rdi)
+ testb %al,%al
+ jz L2
+ movb 3(%rsi),%al
+ movb %al,3(%rdi)
+ testb %al,%al
+ jz L2
+ movb 4(%rsi),%al
+ movb %al,4(%rdi)
+ testb %al,%al
+ jz L2
+ movb 5(%rsi),%al
+ movb %al,5(%rdi)
+ testb %al,%al
+ jz L2
+ movb 6(%rsi),%al
+ movb %al,6(%rdi)
+ testb %al,%al
+ jz L2
+ movb 7(%rsi),%al
+ movb %al,7(%rdi)
+ addq $8,%rsi
+ addq $8,%rdi
+ testb %al,%al
+ jnz L1
+L2: movq %r11,%rax
+ ret
diff --git a/sys/lib/libkern/arch/x86_64/strlen.S b/sys/lib/libkern/arch/x86_64/strlen.S
new file mode 100644
index 00000000000..3c85659391a
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/strlen.S
@@ -0,0 +1,21 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS)
+ RCSID("$NetBSD: strlen.S,v 1.1 2001/06/19 00:22:47 fvdl Exp $")
+#endif
+
+ENTRY(strlen)
+ cld /* set search forward */
+ xorl %eax,%eax /* set search for null terminator */
+ movq $-1,%rcx /* set search for lots of characters */
+ repne /* search! */
+ scasb
+ notq %rcx /* get length by taking complement */
+ leaq -1(%rcx),%rax /* and subtracting one */
+ ret
diff --git a/sys/lib/libkern/arch/x86_64/strrchr.S b/sys/lib/libkern/arch/x86_64/strrchr.S
new file mode 100644
index 00000000000..9b23edfb435
--- /dev/null
+++ b/sys/lib/libkern/arch/x86_64/strrchr.S
@@ -0,0 +1,4 @@
+/* $NetBSD: strrchr.S,v 1.1 2001/06/19 00:22:47 fvdl Exp $ */
+
+#define STRRCHR
+#include "rindex.S"
diff --git a/sys/sys/exec_aout.h b/sys/sys/exec_aout.h
index 6bddccd3216..11d7d079dac 100644
--- a/sys/sys/exec_aout.h
+++ b/sys/sys/exec_aout.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: exec_aout.h,v 1.16 2002/03/28 07:02:03 deraadt Exp $ */
+/* $OpenBSD: exec_aout.h,v 1.17 2004/01/28 01:39:40 mickey Exp $ */
/* $NetBSD: exec_aout.h,v 1.15 1996/05/18 17:20:54 christos Exp $ */
/*
@@ -79,6 +79,7 @@ struct exec {
#define MID_POWERPC 149 /* big-endian PowerPC */
#define MID_VAX 150 /* vax */
#define MID_SPARC64 151 /* LP64 sparc */
+#define MID_X86_64 152 /* AMD x86-64 */
#define MID_M88K 153 /* m88k BSD binary */
#define MID_HPPA 154 /* hppa */
#define MID_HP200 200 /* hp200 (68010) BSD binary */
diff --git a/sys/sys/exec_elf.h b/sys/sys/exec_elf.h
index 8b8685033a5..2bb7f8323ea 100644
--- a/sys/sys/exec_elf.h
+++ b/sys/sys/exec_elf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: exec_elf.h,v 1.36 2003/09/18 09:58:13 jmc Exp $ */
+/* $OpenBSD: exec_elf.h,v 1.37 2004/01/28 01:39:40 mickey Exp $ */
/*
* Copyright (c) 1995, 1996 Erik Theisen. All rights reserved.
*
@@ -190,6 +190,7 @@ typedef struct {
#define EM_ALPHA 41 /* DEC ALPHA */
#define EM_SPARCV9 43 /* SPARC version 9 */
#define EM_ALPHA_EXP 0x9026 /* DEC ALPHA */
+#define EM_X86_64 62 /* AMD x86-64 architecture */
#define EM_VAX 75 /* DEC VAX */
#define EM_NUM 15 /* number of machine types */