Merge remote branch 'crater/master' into vkernel64
authorMatthew Dillon <dillon@apollo.backplane.com>
Wed, 24 Mar 2010 18:25:37 +0000 (11:25 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Wed, 24 Mar 2010 18:25:37 +0000 (11:25 -0700)
88 files changed:
include/strings.h
sys/conf/files
sys/config/VKERNEL64 [new file with mode: 0644]
sys/cpu/x86_64/include/cpufunc.h
sys/cpu/x86_64/include/frame.h
sys/cpu/x86_64/include/npx.h
sys/cpu/x86_64/include/param.h
sys/cpu/x86_64/include/tls.h
sys/cpu/x86_64/include/trap.h
sys/cpu/x86_64/include/types.h
sys/cpu/x86_64/misc/atomic.c [moved from sys/platform/pc64/x86_64/atomic.c with 100% similarity]
sys/cpu/x86_64/misc/db_disasm.c [moved from sys/platform/pc64/x86_64/db_disasm.c with 99% similarity]
sys/cpu/x86_64/misc/elf_machdep.c [moved from sys/platform/pc64/x86_64/elf_machdep.c with 100% similarity]
sys/cpu/x86_64/misc/in_cksum2.s [copied from sys/platform/pc64/x86_64/in_cksum2.s with 97% similarity]
sys/cpu/x86_64/misc/ktr.c [copied from sys/platform/pc64/x86_64/ktr.c with 98% similarity]
sys/kern/init_main.c
sys/kern/kern_shutdown.c
sys/kern/link_elf.c
sys/kern/subr_log.c
sys/net/altq/altq_subr.c
sys/platform/pc64/conf/files
sys/platform/pc64/include/md_var.h
sys/platform/pc64/x86_64/exception.S
sys/platform/pc64/x86_64/machdep.c
sys/platform/pc64/x86_64/pmap.c
sys/platform/pc64/x86_64/trap.c
sys/platform/vkernel/include/pmap.h
sys/platform/vkernel/platform/pmap.c
sys/platform/vkernel/platform/pmap_inval.c
sys/platform/vkernel64/Makefile.inc [new file with mode: 0644]
sys/platform/vkernel64/conf/Makefile [new file with mode: 0644]
sys/platform/vkernel64/conf/files [new file with mode: 0644]
sys/platform/vkernel64/conf/kern.mk [new file with mode: 0644]
sys/platform/vkernel64/conf/ldscript.x86_64 [new file with mode: 0644]
sys/platform/vkernel64/conf/options [new file with mode: 0644]
sys/platform/vkernel64/include/clock.h [new file with mode: 0644]
sys/platform/vkernel64/include/cothread.h [copied from sys/platform/pc64/x86_64/in_cksum2.s with 56% similarity]
sys/platform/vkernel64/include/cpu.h [copied from sys/platform/pc64/x86_64/ktr.c with 56% similarity]
sys/platform/vkernel64/include/cpufunc.h [copied from sys/platform/pc64/x86_64/ktr.c with 57% similarity]
sys/platform/vkernel64/include/globaldata.h [new file with mode: 0644]
sys/platform/vkernel64/include/lock.h [copied from sys/platform/pc64/x86_64/in_cksum2.s with 56% similarity]
sys/platform/vkernel64/include/md_var.h [new file with mode: 0644]
sys/platform/vkernel64/include/param.h [new file with mode: 0644]
sys/platform/vkernel64/include/pcb.h [copied from sys/cpu/x86_64/include/types.h with 53% similarity]
sys/platform/vkernel64/include/pcb_ext.h [copied from include/strings.h with 57% similarity]
sys/platform/vkernel64/include/pmap.h [copied from sys/platform/vkernel/include/pmap.h with 80% similarity]
sys/platform/vkernel64/include/pmap_inval.h [copied from sys/platform/pc64/x86_64/ktr.c with 54% similarity]
sys/platform/vkernel64/include/proc.h [copied from sys/platform/pc64/x86_64/ktr.c with 56% similarity]
sys/platform/vkernel64/include/ptrace.h [copied from sys/cpu/x86_64/include/types.h with 53% similarity]
sys/platform/vkernel64/include/smp.h [new file with mode: 0644]
sys/platform/vkernel64/include/thread.h [new file with mode: 0644]
sys/platform/vkernel64/include/types.h [copied from sys/platform/pc64/x86_64/in_cksum2.s with 56% similarity]
sys/platform/vkernel64/include/vmparam.h [new file with mode: 0644]
sys/platform/vkernel64/platform/busdma_machdep.c [new file with mode: 0644]
sys/platform/vkernel64/platform/console.c [new file with mode: 0644]
sys/platform/vkernel64/platform/copyio.c [new file with mode: 0644]
sys/platform/vkernel64/platform/cothread.c [new file with mode: 0644]
sys/platform/vkernel64/platform/globaldata.c [copied from sys/platform/pc64/x86_64/ktr.c with 55% similarity]
sys/platform/vkernel64/platform/init.c [new file with mode: 0644]
sys/platform/vkernel64/platform/ipl_funcs.c [new file with mode: 0644]
sys/platform/vkernel64/platform/kqueue.c [new file with mode: 0644]
sys/platform/vkernel64/platform/machintr.c [new file with mode: 0644]
sys/platform/vkernel64/platform/pmap.c [copied from sys/platform/pc64/x86_64/pmap.c with 58% similarity]
sys/platform/vkernel64/platform/pmap_inval.c [copied from sys/platform/vkernel/platform/pmap_inval.c with 94% similarity]
sys/platform/vkernel64/platform/shutdown.c [copied from sys/platform/pc64/x86_64/ktr.c with 54% similarity]
sys/platform/vkernel64/platform/sysarch.c [copied from sys/platform/pc64/x86_64/ktr.c with 57% similarity]
sys/platform/vkernel64/platform/systimer.c [new file with mode: 0644]
sys/platform/vkernel64/x86_64/autoconf.c [new file with mode: 0644]
sys/platform/vkernel64/x86_64/cpu_regs.c [new file with mode: 0644]
sys/platform/vkernel64/x86_64/db_interface.c [new file with mode: 0644]
sys/platform/vkernel64/x86_64/db_trace.c [new file with mode: 0644]
sys/platform/vkernel64/x86_64/exception.c [new file with mode: 0644]
sys/platform/vkernel64/x86_64/fork_tramp.s [new file with mode: 0644]
sys/platform/vkernel64/x86_64/genassym.c [new file with mode: 0644]
sys/platform/vkernel64/x86_64/global.s [new file with mode: 0644]
sys/platform/vkernel64/x86_64/locore.s [moved from sys/platform/pc64/x86_64/in_cksum2.s with 54% similarity]
sys/platform/vkernel64/x86_64/mp.c [new file with mode: 0644]
sys/platform/vkernel64/x86_64/npx.c [new file with mode: 0644]
sys/platform/vkernel64/x86_64/procfs_machdep.c [new file with mode: 0644]
sys/platform/vkernel64/x86_64/swtch.s [new file with mode: 0644]
sys/platform/vkernel64/x86_64/tls.c [new file with mode: 0644]
sys/platform/vkernel64/x86_64/trap.c [copied from sys/platform/pc64/x86_64/trap.c with 56% similarity]
sys/platform/vkernel64/x86_64/userldt.c [moved from sys/platform/pc64/x86_64/ktr.c with 57% similarity]
sys/platform/vkernel64/x86_64/vm_machdep.c [new file with mode: 0644]
sys/sys/vkernel.h
sys/vm/vm_fault.c
sys/vm/vm_page.c
test/vkernel/Makefile

index 7c90b89..0c218e3 100644 (file)
@@ -45,9 +45,9 @@ void   bzero(void *, size_t);                                 /* LEGACY */
 int     ffs(int) __pure2;
 #endif
 #ifdef __BSD_VISIBLE
-int     ffsl(long) __pure2;
 int     ffsll(long long) __pure2;
 #if !defined(_KERNEL_VIRTUAL)
+int     ffsl(long) __pure2;
 int     fls(int) __pure2;
 int     flsl(long) __pure2;
 #endif
index 015d07a..8054c9b 100644 (file)
@@ -630,7 +630,7 @@ kern/imgact_resident.c      standard
 kern/imgact_gzip.c     optional gzip
 kern/imgact_shell.c    standard
 kern/inflate.c         optional gzip
-kern/init_main.c       standard
+kern/init_main.c       standard nowerror
 kern/init_sysent.c     standard
 kern/kern_checkpoint.c standard
 kern/kern_sysref.c     standard
diff --git a/sys/config/VKERNEL64 b/sys/config/VKERNEL64
new file mode 100644 (file)
index 0000000..a4215bd
--- /dev/null
@@ -0,0 +1,110 @@
+# VKERNEL - configuration for a virtual kernel
+#
+# $DragonFly: src/sys/config/VKERNEL,v 1.14 2008/11/09 18:57:17 dillon Exp $
+
+platform       vkernel64       # platform architecture (i386, vkernel, etc)
+machine                x86_64
+machine_arch   x86_64          # cpu architecture (i386, etc)
+ident          VKERNEL64
+maxusers       0
+
+makeoptions    DEBUG=-g
+
+cpu            HAMMER_CPU
+
+options                DEBUG_PCTRACK
+
+##options              KTR
+##options              KTR_GIANT_CONTENTION
+##options              KTR_SPIN_CONTENTION
+#options       DEBUG_CRIT_SECTIONS
+
+options                QUOTA
+options                DUMMYNET
+options         IPFIREWALL              #firewall
+options                IPFIREWALL_FORWARD      #enable transparent proxy support
+options                IPFIREWALL_DEFAULT_TO_ACCEPT    #allow everything by default
+
+# ALTQ
+options         ALTQ            #alternate queueing
+options         ALTQ_CBQ        #class based queueing
+options         ALTQ_RED        #random early detection
+options         ALTQ_RIO        #triple red for diffserv (needs RED)
+options         ALTQ_HFSC       #hierarchical fair service curve
+options         ALTQ_PRIQ       #priority queue
+options                ALTQ_FAIRQ      #fair queue
+#options        ALTQ_NOPCC      #don't use processor cycle counter
+options         ALTQ_DEBUG      #for debugging
+
+##options              IPSEC                   #IP security
+##options              IPSEC_ESP               #IP security (crypto; define w/ IPSEC)
+##options              IPSEC_DEBUG             #debug for IP security
+
+options                HAMMER
+options                EXT2FS
+options        INET                    #InterNETworking
+options        INET6                   #IPv6 communications protocols
+options        FFS                     #Berkeley Fast Filesystem
+options        FFS_ROOT                #FFS usable as root device [keep this!]
+options        SOFTUPDATES             #Enable FFS soft updates support
+options        UFS_DIRHASH             #Improve performance on big directories
+options        MFS                     #Memory Filesystem
+options        MD_ROOT                 #MD is a potential root device
+options        NFS                     #Network Filesystem
+options        NFS_ROOT                #NFS usable as root device, NFS required
+options        MSDOSFS                 #MSDOS Filesystem
+options        CD9660                  #ISO 9660 Filesystem
+options        PROCFS                  #Process filesystem
+options        COMPAT_43               #Compatible with BSD 4.3 [KEEP THIS!]
+options                COMPAT_DF12             #Compatible with DragonFly 1.2 and earlier
+options                DEVICE_POLLING          # Support mixed interrupt-polling
+                                       # handling of network device drivers
+options        UCONSOLE                #Allow users to grab the console
+options        KTRACE                  #ktrace(1) support
+options        SYSVSHM                 #SYSV-style shared memory
+options        SYSVMSG                 #SYSV-style message queues
+options        SYSVSEM                 #SYSV-style semaphores
+options        P1003_1B                #Posix P1003_1B real-time extensions
+options        _KPOSIX_PRIORITY_SCHEDULING
+options        ICMP_BANDLIM            #Rate limit bad replies
+
+options        SMP                     # Symmetric MultiProcessor Kernel
+
+# Debugging for Development
+options        DDB
+options        DDB_TRACE
+options        INVARIANTS
+
+#options       CARP
+
+# Pseudo devices - the number indicates how many units to allocate.
+pseudo-device  loop            # Network loopback
+pseudo-device  ether           # Ethernet support
+pseudo-device  sl      1       # Kernel SLIP
+pseudo-device  ppp     1       # Kernel PPP
+pseudo-device  tun             # Packet tunnel.
+pseudo-device  pty             # Pseudo-ttys (telnet etc)
+pseudo-device  md              # Memory "disks"
+pseudo-device  gif             # IPv6 and IPv4 tunneling
+pseudo-device  faith   1       # IPv6-to-IPv4 relaying (translation)
+
+#pseudo-device carp
+
+# SCSI peripherals
+device          scbus           # SCSI bus (required)
+device          da              # Direct Access (disks)
+device          sa              # Sequential Access (tape etc)
+device          cd              # CD
+device          pass            # Passthrough device (direct SCSI access)
+
+# The `bpf' pseudo-device enables the Berkeley Packet Filter.
+# Be aware of the administrative consequences of enabling this!
+pseudo-device  bpf             #Berkeley packet filter
+
+# VIRTUAL DEVICES
+#
+device         vn
+device         vkd
+device         vke
+
+device         vcd
index 6b08fa9..8b1305a 100644 (file)
@@ -115,12 +115,6 @@ bsrq(u_long mask)
        return (result);
 }
 
-static __inline void
-cpu_disable_intr(void)
-{
-       __asm __volatile("cli" : : : "memory");
-}
-
 static __inline void
 do_cpuid(u_int ax, u_int *p)
 {
@@ -137,12 +131,26 @@ cpuid_count(u_int ax, u_int cx, u_int *p)
                         :  "0" (ax), "c" (cx));
 }
 
+#ifndef _CPU_DISABLE_INTR_DEFINED
+
+static __inline void
+cpu_disable_intr(void)
+{
+       __asm __volatile("cli" : : : "memory");
+}
+
+#endif
+
+#ifndef _CPU_ENABLE_INTR_DEFINED
+
 static __inline void
 cpu_enable_intr(void)
 {
        __asm __volatile("sti");
 }
 
+#endif
+
 /*
  * Cpu and compiler memory ordering fence.  mfence ensures strong read and
  * write ordering.
@@ -591,16 +599,22 @@ rcr4(void)
        return (data);
 }
 
+#ifndef _CPU_INVLTLB_DEFINED
+
 /*
- * Global TLB flush (except for thise for pages marked PG_G)
+ * Invalidate the TLB on this cpu only
  */
 static __inline void
 cpu_invltlb(void)
 {
-
        load_cr3(rcr3());
+#if defined(SWTCH_OPTIM_STATS)
+       ++tlb_flush_count;
+#endif
 }
 
+#endif
+
 /*
  * TLB flush for an individual page (even if it has PG_G).
  * Only works on 486+ CPUs (i386 does not have PG_G).
index a063049..263e169 100644 (file)
@@ -108,7 +108,7 @@ struct intrframe {
        register_t      if_r13;
        register_t      if_r14;
        register_t      if_r15;
-       register_t      :64;            /* compat with trap frame - xflags */
+       register_t      if_xflags;      /* compat with trap frame - xflags */
        register_t      :64;            /* compat with trap frame - trapno */
        register_t      :64;            /* compat with trap frame - addr */
        register_t      :64;            /* compat with trap frame - flags */
index 02f124a..186682c 100644 (file)
@@ -161,7 +161,6 @@ struct trapframe;
 void   npxexit (void);
 void   npxinit (u_short control);
 void   npxsave (union savefpu *addr);
-int    npxdna(void);
 #endif
 
 #endif /* !_CPU_NPX_H_ */
index f8cd471..7fe73c7 100644 (file)
 #define PML4MASK       (NPML4-1)
 #define NPML4EPG       (PAGE_SIZE/(sizeof (pml4_entry_t)))
 
+/* for vkernel */
+#define SEG_SHIFT      21
+#define SEG_SIZE       (1<<SEG_SHIFT)  /* bytes per mmu segment (level 1) */
+#define SEG_MASK       (SEG_SIZE-1)
+
 #define DEV_BSHIFT     9               /* log2(DEV_BSIZE) */
 #define DEV_BSIZE      (1<<DEV_BSHIFT)
 #define DEV_BMASK      (DEV_BSIZE - 1)
index 3771dfa..7badc6d 100644 (file)
@@ -67,8 +67,6 @@ struct tls_dtv {
 #define        RTLD_STATIC_TLS_EXTRA           256
 #define RTLD_STATIC_TLS_VARIANT_II
 
-#ifndef _KERNEL
-
 /* Get the current TCB. */
 static __inline struct tls_tcb *
 tls_get_tcb(void)
@@ -107,6 +105,20 @@ tls_set_tcb(struct tls_tcb *tcb)
        /*__asm __volatile("movl %0, %%fs" : : "r" (seg));*/
 }
 
+static __inline void
+tls_set_gs(void *base, size_t bytes)
+{
+       struct tls_info info;
+       int seg;
+
+       info.base = base;
+       info.size = bytes;
+       seg = set_tls_area(1, &info, sizeof(info));
+       /*__asm __volatile("mov %0, %%fs" : : "g" (seg));*/
+}
+
+#ifndef _KERNEL
+
 struct tls_tcb *_rtld_allocate_tls(void);
 struct tls_tcb *_libc_allocate_tls(void);
 void            _rtld_free_tls(struct tls_tcb *);
index c2a49d0..728f355 100644 (file)
@@ -95,6 +95,7 @@
 
 /* Trap's coming from user mode */
 #define T_SYSCALL80    0x080
+#define T_FAST_SYSCALL 0x081
 #define        T_USER  0x100
 
 #endif /* !_CPU_TRAP_H_ */
index bfb6c13..0843757 100644 (file)
 #ifndef _CPU_TYPES_H_
 #define        _CPU_TYPES_H_
 
+#ifndef _MACHINE_STDINT_H_
+#include <machine/stdint.h>
+#endif
+
 #if defined(__x86_64__)
 typedef        __int64_t       __segsz_t;      /* segment size */
 typedef        __int64_t       register_t;
similarity index 99%
rename from sys/platform/pc64/x86_64/db_disasm.c
rename to sys/cpu/x86_64/misc/db_disasm.c
index 4fb3a53..4a3ce4a 100644 (file)
@@ -1,10 +1,10 @@
 /*
  * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -14,7 +14,7 @@
  * 3. Neither the name of The DragonFly Project nor the names of its
  *    contributors may be used to endorse or promote products derived
  *    from this software without specific, prior written permission.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
similarity index 97%
copy from sys/platform/pc64/x86_64/in_cksum2.s
copy to sys/cpu/x86_64/misc/in_cksum2.s
index bf249cc..fd414d8 100644 (file)
@@ -1,13 +1,13 @@
 /*
  * Copyright (c) 2003,2004,2008 The DragonFly Project.  All rights reserved.
- * 
+ *
  * This code is derived from software contributed to The DragonFly Project
  * by Matthew Dillon <dillon@backplane.com>
- * 
+ *
  * 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
@@ -17,7 +17,7 @@
  * 3. Neither the name of The DragonFly Project nor the names of its
  *    contributors may be used to endorse or promote products derived
  *    from this software without specific, prior written permission.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
@@ -41,9 +41,9 @@
        /*
         * asm_ones32(32bitalignedbuffer, numberof32bitwords)
         *
-        * Returns the 32 bit one complement partial checksum.  This is 
+        * Returns the 32 bit one complement partial checksum.  This is
         * basically a 1's complement checksum without the inversion (~)
-        * at the end.  A 32 bit value is returned.  If the caller is 
+        * at the end.  A 32 bit value is returned.  If the caller is
         * calculating a 16 bit 1's complement checksum the caller must
         * collapse the 32 bit return value via:
         *
similarity index 98%
copy from sys/platform/pc64/x86_64/ktr.c
copy to sys/cpu/x86_64/misc/ktr.c
index a85a71c..cbb76b4 100644 (file)
@@ -1,13 +1,13 @@
 /*
  * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
- * 
+ *
  * This code is derived from software contributed to The DragonFly Project
  * by Matthew Dillon <dillon@backplane.com>
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -17,7 +17,7 @@
  * 3. Neither the name of The DragonFly Project nor the names of its
  *    contributors may be used to endorse or promote products derived
  *    from this software without specific, prior written permission.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
@@ -58,7 +58,7 @@
  * sp ->[junk]
  */
 
-static __inline 
+static __inline
 void **
 FRAMEUP(void **frameptr)
 {
@@ -84,4 +84,3 @@ cpu_ktr_caller(struct ktr_entry *_ktr)
     frameptr = FRAMEUP(frameptr);      /* frame, caller2 of caller1 */
     ktr->ktr_caller2 = frameptr[1];
 }
-
index 52b864f..3db8165 100644 (file)
@@ -200,8 +200,22 @@ mi_startup(void)
 
        if (sysinit == NULL) {
                sysinit = SET_BEGIN(sysinit_set);
+#if defined(__amd64__) && defined(_KERNEL_VIRTUAL)
+               /*
+                * XXX For whatever reason, on 64-bit vkernels
+                * the value of sysinit obtained from the
+                * linker set is wrong.
+                */
+               if ((long)sysinit % 8 != 0) {
+                       kprintf("Fixing sysinit value...\n");
+                       sysinit = (long)sysinit + 4;
+               }
+#endif
                sysinit_end = SET_LIMIT(sysinit_set);
        }
+#if defined(__amd64__) && defined(_KERNEL_VIRTUAL)
+       KKASSERT((long)sysinit % 8 == 0);
+#endif
 
 restart:
        /*
index b50869f..199eed0 100644 (file)
@@ -426,10 +426,10 @@ shutdown_busycount2(struct buf *bp, void *info)
                }
 #if defined(SHOW_BUSYBUFS) || defined(DIAGNOSTIC)
                kprintf(
-           "%p dev:?, flags:%08x, loffset:%lld, doffset:%lld\n",
+           "%p dev:?, flags:%08x, loffset:%jd, doffset:%jd\n",
                    bp, 
-                   bp->b_flags, bp->b_loffset,
-                   bp->b_bio2.bio_offset);
+                   bp->b_flags, (intmax_t)bp->b_loffset,
+                   (intmax_t)bp->b_bio2.bio_offset);
 #endif
                return(1);
        }
index 9029368..e2716f1 100644 (file)
 #include <vm/pmap.h>
 #include <vm/vm_map.h>
 
+#if defined(__amd64__) && defined(_KERNEL_VIRTUAL)
+#include <stdio.h>
+#endif
+
 static int     link_elf_preload_file(const char *, linker_file_t *);
 static int     link_elf_preload_finish(linker_file_t);
 static int     link_elf_load_file(const char*, linker_file_t*);
@@ -161,6 +165,9 @@ link_elf_init(void* arg)
        if (linker_kernel_file == NULL)
            panic("link_elf_init: Can't create linker structures for kernel");
        parse_dynamic(linker_kernel_file);
+#if defined(__amd64__) && defined(_KERNEL_VIRTUAL)
+       fprintf(stderr, "WARNING: KERNBASE being used\n");
+#endif
        linker_kernel_file->address = (caddr_t) KERNBASE;
        linker_kernel_file->size = -(intptr_t)linker_kernel_file->address;
 
index 4e68248..e6b4fa5 100644 (file)
@@ -143,7 +143,7 @@ logread(struct dev_read_args *ap)
        logsoftc.sc_state &= ~LOG_RDWAIT;
 
        while (uio->uio_resid > 0) {
-               l = mbp->msg_bufx - mbp->msg_bufr;
+               l = (long)mbp->msg_bufx - (long)mbp->msg_bufr;
                if (l < 0)
                        l = mbp->msg_size - mbp->msg_bufr;
                l = (long)szmin(l, uio->uio_resid);
index 1383d94..67e124a 100644 (file)
@@ -817,7 +817,7 @@ init_machclk(void)
                machclk_freq = 1000000LLU << MACHCLK_SHIFT;
                machclk_per_tick = machclk_freq / hz;
 #ifdef ALTQ_DEBUG
-               kprintf("altq: emulate %lluHz cpu clock\n", machclk_freq);
+               kprintf("altq: emulate %juHz cpu clock\n", (uintmax_t)machclk_freq);
 #endif
                return;
        }
@@ -855,7 +855,7 @@ init_machclk(void)
        machclk_per_tick = machclk_freq / hz;
 
 #ifdef ALTQ_DEBUG
-       kprintf("altq: CPU clock: %lluHz\n", machclk_freq);
+       kprintf("altq: CPU clock: %juHz\n", (uintmax_t)machclk_freq);
 #endif
 }
 
index 49e7150..a57dd69 100644 (file)
@@ -88,18 +88,18 @@ vfs/smbfs/smbfs_subr.c              optional        smbfs
 vfs/smbfs/smbfs_vfsops.c       optional        smbfs
 vfs/smbfs/smbfs_vnops.c                optional        smbfs
 
-platform/pc64/x86_64/atomic.c                  standard                        \
+cpu/x86_64/misc/atomic.c               standard                        \
         compile-with    "${CC} -c ${CFLAGS} ${WERROR} ${DEFINED_PROF:S/^$/-fomit-frame-pointer/} ${.IMPSRC}"
 platform/pc64/x86_64/autoconf.c        standard
 platform/pc64/x86_64/mpboot.S          optional        smp
 
 # DDB XXX
-cpu/x86_64/misc/x86_64-gdbstub.c               optional        ddb
-cpu/x86_64/misc/lwbuf.c                                standard
-platform/pc64/x86_64/elf_machdep.c             standard
-platform/pc64/x86_64/in_cksum2.s                       optional        inet
-platform/pc64/x86_64/ktr.c                     optional        ktr
-platform/pc64/x86_64/db_disasm.c                       optional        ddb
+cpu/x86_64/misc/x86_64-gdbstub.c       optional        ddb
+cpu/x86_64/misc/lwbuf.c                        standard
+cpu/x86_64/misc/elf_machdep.c          standard
+cpu/x86_64/misc/in_cksum2.s            optional        inet
+cpu/x86_64/misc/ktr.c                  optional        ktr
+cpu/x86_64/misc/db_disasm.c            optional        ddb
 #
 # DOS mbr and gpt
 kern/subr_diskmbr.c                    standard
index 3edc80b..562e21b 100644 (file)
@@ -86,6 +86,7 @@ void  setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int ist);
 int    user_dbreg_trap(void);
 void   fpstate_drop(struct thread *td);
 
+int     npxdna(void);
 void npxpush(struct __mcontext *mctx);
 void npxpop(struct __mcontext *mctx);
 
index b9ca27e..4efea94 100644 (file)
@@ -285,6 +285,7 @@ IDTVEC(fast_syscall)
        movq    $KUDSEL,TF_SS(%rsp)
        movq    $KUCSEL,TF_CS(%rsp)
        movq    $2,TF_ERR(%rsp)
+       movq    $T_FAST_SYSCALL,TF_TRAPNO(%rsp) /* for the vkernel */
        movq    $0,TF_XFLAGS(%rsp)      /* note: used in signal frame */
        movq    %rdi,TF_RDI(%rsp)       /* arg 1 */
        movq    %rsi,TF_RSI(%rsp)       /* arg 2 */
index 1f7b676..eabe97f 100644 (file)
@@ -460,13 +460,13 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
                 * action(signo, siginfo, ucontext)
                 */
                regs->tf_rsi = (register_t)&sfp->sf_si; /* argument 2 */
-               regs->tf_rcx = (register_t)regs->tf_err; /* argument 4 */
+               regs->tf_rcx = (register_t)regs->tf_addr; /* argument 4 */
                sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
 
                /* fill siginfo structure */
                sf.sf_si.si_signo = sig;
                sf.sf_si.si_code = code;
-               sf.sf_si.si_addr = (void *)regs->tf_err;
+               sf.sf_si.si_addr = (void *)regs->tf_addr;
        } else {
                /*
                 * Old FreeBSD-style arguments.
@@ -474,7 +474,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
                 * handler (signo, code, [uc], addr)
                 */
                regs->tf_rsi = (register_t)code;        /* argument 2 */
-               regs->tf_rcx = (register_t)regs->tf_err; /* argument 4 */
+               regs->tf_rcx = (register_t)regs->tf_addr; /* argument 4 */
                sf.sf_ahu.sf_handler = catcher;
        }
 
index cd343db..7c45c0d 100644 (file)
@@ -3764,6 +3764,7 @@ pmap_setlwpvm(struct lwp *lp, struct vmspace *newvm)
                        tlb_flush_count++;
 #endif
                        curthread->td_pcb->pcb_cr3 = vtophys(pmap->pm_pml4);
+                       curthread->td_pcb->pcb_cr3 |= PG_RW | PG_U | PG_V;
                        load_cr3(curthread->td_pcb->pcb_cr3);
                        pmap = vmspace_pmap(oldvm);
 #if defined(SMP)
index 08afdee..b394da5 100644 (file)
@@ -895,8 +895,10 @@ nogo:
         * kludge is needed to pass the fault address to signal handlers.
         */
        struct proc *p = td->td_proc;
-       kprintf("seg-fault accessing address %p rip=%p pid=%d p_comm=%s\n",
-               (void *)va, (void *)frame->tf_rip, p->p_pid, p->p_comm);
+       if (td->td_lwp->lwp_vkernel == NULL) {
+               kprintf("seg-fault accessing address %p rip=%p pid=%d p_comm=%s\n",
+                       (void *)va, (void *)frame->tf_rip, p->p_pid, p->p_comm);
+       }
        /* Debugger("seg-fault"); */
 
        return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
@@ -1320,7 +1322,15 @@ generic_lwp_return(struct lwp *lp, struct trapframe *frame)
 void
 set_vkernel_fp(struct trapframe *frame)
 {
-       /* JGXXX */
+       struct thread *td = curthread;
+
+       if (frame->tf_xflags & PGEX_FPFAULT) {
+               td->td_pcb->pcb_flags |= FP_VIRTFP;
+               if (mdcpu->gd_npxthread == td)
+                       npxexit();
+       } else {
+               td->td_pcb->pcb_flags &= ~FP_VIRTFP;
+       }
 }
 
 /*
index 40e3487..d6d9aa3 100644 (file)
@@ -120,7 +120,7 @@ struct pmap_statistics {
 typedef struct pmap_statistics *pmap_statistics_t;
 
 struct pmap {
-       pd_entry_t              *pm_pdir;       /* KVA of page directory */
+       vpte_t                  *pm_pdir;       /* KVA of page directory */
        vpte_t                  pm_pdirpte;     /* pte mapping phys page */
        struct vm_object        *pm_pteobj;     /* Container for pte's */
        cpumask_t               pm_cpucachemask;/* Invalidate cpu mappings */
index 1ef6682..2f6c8a7 100644 (file)
@@ -192,7 +192,7 @@ pmap_pinit(struct pmap *pmap)
         */
        if (pmap->pm_pdir == NULL) {
                pmap->pm_pdir =
-                   (pd_entry_t *)kmem_alloc_pageable(&kernel_map, PAGE_SIZE);
+                   (vpte_t *)kmem_alloc_pageable(&kernel_map, PAGE_SIZE);
        }
 
        /*
@@ -1706,7 +1706,7 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
                                if (pbits & VPTE_A) {
                                        m = PHYS_TO_VM_PAGE(pbits);
                                        vm_page_flag_set(m, PG_REFERENCED);
-                                       atomic_clear_int(ptep, VPTE_A);
+                                       atomic_clear_long(ptep, VPTE_A);
                                }
                                if (pbits & VPTE_M) {
                                        if (pmap_track_modified(pmap, i386_ptob(sindex))) {
@@ -1743,7 +1743,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
        vm_paddr_t pa;
        vpte_t *pte;
        vm_paddr_t opa;
-       vm_offset_t origpte, newpte;
+       vpte_t origpte, newpte;
        vm_page_t mpte;
 
        if (pmap == NULL)
@@ -2153,9 +2153,9 @@ pmap_change_wiring(pmap_t pmap, vm_offset_t va, boolean_t wired)
         * wiring changes.
         */
        if (wired)
-               atomic_set_int(pte, VPTE_WIRED);
+               atomic_set_long(pte, VPTE_WIRED);
        else
-               atomic_clear_int(pte, VPTE_WIRED);
+               atomic_clear_long(pte, VPTE_WIRED);
 }
 
 /*
@@ -2229,7 +2229,7 @@ pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr,
                        
                if (srcptepaddr & VPTE_PS) {
                        if (dst_pmap->pm_pdir[ptepindex] == 0) {
-                               dst_pmap->pm_pdir[ptepindex] = (pd_entry_t) srcptepaddr;
+                               dst_pmap->pm_pdir[ptepindex] = (vpte_t)srcptepaddr;
                                dst_pmap->pm_stats.resident_count += NBPDR / PAGE_SIZE;
                        }
                        continue;
@@ -2517,7 +2517,7 @@ pmap_remove_pages(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
                m = PHYS_TO_VM_PAGE(tpte);
 
                KASSERT(m < &vm_page_array[vm_page_array_size],
-                       ("pmap_remove_pages: bad tpte %x", tpte));
+                       ("pmap_remove_pages: bad tpte %lx", tpte));
 
                KKASSERT(pmap->pm_stats.resident_count > 0);
                --pmap->pm_stats.resident_count;
@@ -2668,7 +2668,7 @@ pmap_clearbit(vm_page_t m, int bit)
                                 * handle the write fault without forwarding
                                 * the fault to us.
                                 */
-                               atomic_clear_int(pte, VPTE_M);
+                               atomic_clear_long(pte, VPTE_M);
                        } else if ((bit & (VPTE_W|VPTE_M)) == (VPTE_W|VPTE_M)) {
                                /*
                                 * We've been asked to clear W & M, I guess
@@ -2681,7 +2681,7 @@ pmap_clearbit(vm_page_t m, int bit)
                                 * We've been asked to clear bits that do
                                 * not interact with hardware.
                                 */
-                               atomic_clear_int(pte, bit);
+                               atomic_clear_long(pte, bit);
                        }
                }
        }
@@ -2754,9 +2754,9 @@ pmap_ts_referenced(vm_page_t m)
 
                        if (pte && (*pte & VPTE_A)) {
 #ifdef SMP
-                               atomic_clear_int(pte, VPTE_A);
+                               atomic_clear_long(pte, VPTE_A);
 #else
-                               atomic_clear_int_nonlocked(pte, VPTE_A);
+                               atomic_clear_long_nonlocked(pte, VPTE_A);
 #endif
                                rtval++;
                                if (rtval > 4) {
@@ -2891,7 +2891,7 @@ pmap_mincore(pmap_t pmap, vm_offset_t addr)
        }
 
        if ((pte = *ptep) != 0) {
-               vm_offset_t pa;
+               vm_paddr_t pa;
 
                val = MINCORE_INCORE;
                if ((pte & VPTE_MANAGED) == 0)
@@ -3010,8 +3010,8 @@ pads(pmap_t pm)
 
        if (pm == &kernel_pmap)
                return;
-       for (i = 0; i < 1024; i++)
-               if (pm->pm_pdir[i])
+       for (i = 0; i < 1024; i++) {
+               if (pm->pm_pdir[i]) {
                        for (j = 0; j < 1024; j++) {
                                va = (i << PDRSHIFT) + (j << PAGE_SHIFT);
                                if (pm == &kernel_pmap && va < KERNBASE)
@@ -3024,7 +3024,8 @@ pads(pmap_t pm)
                                                (void *)va, (unsigned)*ptep);
                                }
                        };
-
+               }
+       }
 }
 
 void
index b054e07..02634f4 100644 (file)
@@ -154,10 +154,10 @@ pmap_clean_pte(volatile vpte_t *ptep, struct pmap *pmap, vm_offset_t va)
 
        pte = *ptep;
        if (pte & VPTE_V) {
-               atomic_clear_int(ptep, VPTE_W);
+               atomic_clear_long(ptep, VPTE_W);
                pmap_inval_cpu(pmap, va, PAGE_SIZE);
                pte = *ptep;
-               atomic_clear_int(ptep, VPTE_W|VPTE_M);
+               atomic_clear_long(ptep, VPTE_W|VPTE_M);
        }
        return(pte);
 }
@@ -169,10 +169,10 @@ pmap_clean_pde(volatile vpte_t *ptep, struct pmap *pmap, vm_offset_t va)
 
        pte = *ptep;
        if (pte & VPTE_V) {
-               atomic_clear_int(ptep, VPTE_W);
+               atomic_clear_long(ptep, VPTE_W);
                pmap_inval_cpu(pmap, va, SEG_SIZE);
                pte = *ptep;
-               atomic_clear_int(ptep, VPTE_W|VPTE_M);
+               atomic_clear_long(ptep, VPTE_W|VPTE_M);
                pmap->pm_cpucachemask = 0;
        }
        return(pte);
@@ -192,7 +192,7 @@ pmap_setro_pte(volatile vpte_t *ptep, struct pmap *pmap, vm_offset_t va)
        pte = *ptep;
        if (pte & VPTE_V) {
                pte = *ptep;
-               atomic_clear_int(ptep, VPTE_W);
+               atomic_clear_long(ptep, VPTE_W);
                pmap_inval_cpu(pmap, va, PAGE_SIZE);
                pte |= *ptep & VPTE_M;
        }
@@ -214,7 +214,7 @@ pmap_inval_loadandclear(volatile vpte_t *ptep, struct pmap *pmap,
        pte = *ptep;
        if (pte & VPTE_V) {
                pte = *ptep;
-               atomic_clear_int(ptep, VPTE_R|VPTE_W);
+               atomic_clear_long(ptep, VPTE_R|VPTE_W);
                pmap_inval_cpu(pmap, va, PAGE_SIZE);
                pte |= *ptep & (VPTE_A | VPTE_M);
        }
diff --git a/sys/platform/vkernel64/Makefile.inc b/sys/platform/vkernel64/Makefile.inc
new file mode 100644 (file)
index 0000000..669994c
--- /dev/null
@@ -0,0 +1,4 @@
+# Used by the device build to check for device support
+#
+
+DEV_SUPPORT=   virtual disk/ccd disk/md disk/vn
diff --git a/sys/platform/vkernel64/conf/Makefile b/sys/platform/vkernel64/conf/Makefile
new file mode 100644 (file)
index 0000000..8ac1446
--- /dev/null
@@ -0,0 +1,36 @@
+# $DragonFly: src/sys/platform/vkernel/conf/Makefile,v 1.7 2007/07/01 02:51:41 dillon Exp $
+#
+# Which version of config(8) is required.
+%VERSREQ=      400026
+
+.if !defined(S)
+.if exists(./@/.)
+S=     ./@
+.else
+S=     ../..
+.endif
+.endif
+
+.include "$S/conf/kern.pre.mk"
+
+# Override the normal kernel link and link as a normal user program
+#
+SYSTEM_LD= @${CC} -g -export-dynamic -o ${.TARGET} ${SYSTEM_OBJS} vers.o -pthread
+
+%BEFORE_DEPEND
+
+%OBJS
+
+%CFILES
+
+%SFILES
+
+%MFILES
+
+%CLEAN
+
+.include "$S/conf/kern.post.mk"
+
+%RULES
+
+# DO NOT DELETE THIS LINE -- make depend uses it
diff --git a/sys/platform/vkernel64/conf/files b/sys/platform/vkernel64/conf/files
new file mode 100644 (file)
index 0000000..69ab38a
--- /dev/null
@@ -0,0 +1,66 @@
+# This file tells config what files go into building a kernel,
+# files marked standard are always included.
+#
+# $DragonFly: src/sys/platform/vkernel/conf/files,v 1.21 2008/03/20 02:14:52 dillon Exp $
+#
+emulation/dragonfly12/dfbsd12_getdirentries.c  nonoptional     compat_df12
+emulation/dragonfly12/dfbsd12_stat.c           nonoptional     compat_df12
+vfs/smbfs/smbfs_io.c           optional        smbfs
+vfs/smbfs/smbfs_node.c         optional        smbfs
+vfs/smbfs/smbfs_smb.c          optional        smbfs
+vfs/smbfs/smbfs_subr.c         optional        smbfs
+vfs/smbfs/smbfs_vfsops.c       optional        smbfs
+vfs/smbfs/smbfs_vnops.c                optional        smbfs
+cpu/x86_64/misc/atomic.c       standard                                \
+       compile-with    "${CC} -c ${CFLAGS} ${DEFINED_PROF:S/^$/-fomit-frame-pointer/} ${.IMPSRC}"
+platform/vkernel64/x86_64/autoconf.c   standard
+platform/vkernel64/x86_64/mp.c         optional        smp             \
+       compile-with    "${CC} -c -pthread ${CFLAGS} -I/usr/include ${.IMPSRC}"
+#
+# DDB XXX
+cpu/x86_64/misc/elf_machdep.c          standard
+cpu/x86_64/misc/lwbuf.c                        standard
+cpu/x86_64/misc/in_cksum2.s            optional        inet
+cpu/x86_64/misc/ktr.c                  optional        ktr
+cpu/x86_64/misc/db_disasm.c            optional        ddb
+cpu/x86_64/misc/x86_64-gdbstub.c       optional        ddb
+#
+# DOS mbr and gpt
+kern/subr_diskmbr.c                    standard
+kern/subr_diskgpt.c                    standard
+
+# DEVICES
+#
+dev/virtual/cdrom/vcd.c                        optional        vcd
+dev/virtual/disk/vdisk.c               optional        vkd
+dev/virtual/net/if_vke.c               optional        vke
+
+# PLATFORM FILES
+#
+platform/vkernel64/x86_64/global.s             standard
+platform/vkernel64/x86_64/swtch.s              standard
+platform/vkernel64/x86_64/npx.c                standard
+platform/vkernel64/x86_64/db_interface.c       optional        ddb
+platform/vkernel64/x86_64/db_trace.c   optional        ddb
+platform/vkernel64/x86_64/vm_machdep.c standard
+platform/vkernel64/x86_64/cpu_regs.c   standard
+platform/vkernel64/x86_64/userldt.c            standard
+platform/vkernel64/x86_64/tls.c                standard
+platform/vkernel64/x86_64/trap.c       standard
+platform/vkernel64/x86_64/exception.c  standard
+platform/vkernel64/x86_64/procfs_machdep.c     standard
+platform/vkernel64/x86_64/fork_tramp.s standard
+platform/vkernel64/platform/init.c     standard nowerror
+platform/vkernel64/platform/globaldata.c       standard
+platform/vkernel64/platform/kqueue.c   standard
+platform/vkernel64/platform/shutdown.c standard
+platform/vkernel64/platform/machintr.c standard
+platform/vkernel64/platform/copyio.c   standard
+platform/vkernel64/platform/pmap.c     standard nowerror
+platform/vkernel64/platform/pmap_inval.c       standard
+platform/vkernel64/platform/busdma_machdep.c standard
+platform/vkernel64/platform/sysarch.c  standard
+platform/vkernel64/platform/systimer.c standard
+platform/vkernel64/platform/console.c  standard
+platform/vkernel64/platform/ipl_funcs.c        standard
+platform/vkernel64/platform/cothread.c standard
diff --git a/sys/platform/vkernel64/conf/kern.mk b/sys/platform/vkernel64/conf/kern.mk
new file mode 100644 (file)
index 0000000..39af0c8
--- /dev/null
@@ -0,0 +1,18 @@
+# $DragonFly: src/sys/platform/vkernel/conf/kern.mk,v 1.3 2007/01/06 08:57:30 dillon Exp $
+#
+#
+# Prohibit the use of FP registers in the kernel.  The user FP state is
+# only saved and restored under strictly managed conditions and mainline
+# kernel code cannot safely use the FP system.
+#
+CFLAGS+=       -mpreferred-stack-boundary=4
+CFLAGS+=       -fno-stack-protector
+CFLAGS+=       -mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3
+CFLAGS+=       -D_KERNEL_VIRTUAL
+CFLAGS+=       -fno-omit-frame-pointer
+
+# Remove the dynamic library hack for now
+#
+SYSTEM_OBJS:= ${SYSTEM_OBJS:Nhack.So}
+
+INLINE_LIMIT=  8000
diff --git a/sys/platform/vkernel64/conf/ldscript.x86_64 b/sys/platform/vkernel64/conf/ldscript.x86_64
new file mode 100644 (file)
index 0000000..ce05503
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * $FreeBSD: src/sys/conf/ldscript.amd64,v 1.9 2004/05/29 01:09:00 tjr Exp $
+ * $DragonFly: src/sys/platform/pc64/conf/ldscript.amd64,v 1.1 2007/09/23 04:29:31 yanyh Exp $
+ */
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(btext)
+SEARCH_DIR("/usr/lib");
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = kernbase + 0x00100000 + SIZEOF_HEADERS;
+  .interp         : { *(.interp) }
+  .hash           : { *(.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+  .rel.init       : { *(.rel.init) }
+  .rela.init      : { *(.rela.init) }
+  .rel.text       : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
+  .rela.text      : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
+  .rel.fini       : { *(.rel.fini) }
+  .rela.fini      : { *(.rela.fini) }
+  .rel.rodata     : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
+  .rela.rodata    : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
+  .rel.data       : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
+  .rela.data      : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
+  .rel.tdata     : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
+  .rela.tdata    : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
+  .rel.tbss      : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
+  .rela.tbss     : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
+  .rel.ctors      : { *(.rel.ctors) }
+  .rela.ctors     : { *(.rela.ctors) }
+  .rel.dtors      : { *(.rel.dtors) }
+  .rela.dtors     : { *(.rela.dtors) }
+  .rel.got        : { *(.rel.got) }
+  .rela.got       : { *(.rela.got) }
+  .rel.bss        : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
+  .rela.bss       : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
+  .rel.plt        : { *(.rel.plt) }
+  .rela.plt       : { *(.rela.plt) }
+  .init           :
+  {
+    KEEP (*(.init))
+  } =0x90909090
+  .plt            : { *(.plt) }
+  .text           :
+  {
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0x90909090
+  .fini           :
+  {
+    KEEP (*(.fini))
+  } =0x90909090
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+  .rodata1        : { *(.rodata1) }
+  .eh_frame_hdr : { *(.eh_frame_hdr) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = DATA_SEGMENT_ALIGN(0x100000, 0x1000);
+  /* Ensure the __preinit_array_start label is properly aligned.  We
+     could instead move the label definition inside the section, but
+     the linker would then create the section even if it turns out to
+     be empty, which isn't pretty.  */
+  . = ALIGN(64 / 8);
+  PROVIDE (__preinit_array_start = .);
+  .preinit_array     : { *(.preinit_array) }
+  PROVIDE (__preinit_array_end = .);
+  PROVIDE (__init_array_start = .);
+  .init_array     : { *(.init_array) }
+  PROVIDE (__init_array_end = .);
+  PROVIDE (__fini_array_start = .);
+  .fini_array     : { *(.fini_array) }
+  PROVIDE (__fini_array_end = .);
+  .data           :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  .tdata         : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss                  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+  .eh_frame       : { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : { *(.gcc_except_table) }
+  .dynamic        : { *(.dynamic) }
+  _start_ctors = .;
+  PROVIDE (start_ctors = .);
+  .ctors          :
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin.o(.ctors))
+    /* We don't want to include the .ctor section from
+       from the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  _stop_ctors = .;
+  PROVIDE (stop_ctors = .);
+  .dtors          :
+  {
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .jcr            : { KEEP (*(.jcr)) }
+  .got            : { *(.got.plt) *(.got) }
+  _edata = .;
+  PROVIDE (edata = .);
+  __bss_start = .;
+  .bss            :
+  {
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.  */
+   . = ALIGN(64 / 8);
+  }
+  . = ALIGN(64 / 8);
+  _end = .;
+  PROVIDE (end = .);
+  . = DATA_SEGMENT_END (.);
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+}
diff --git a/sys/platform/vkernel64/conf/options b/sys/platform/vkernel64/conf/options
new file mode 100644 (file)
index 0000000..d695377
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# $DragonFly: src/sys/platform/vkernel/conf/options,v 1.2 2006/10/25 20:55:51 dillon Exp $
+#
+
+# The cpu type
+#
+HAMMER_CPU              opt_global.h
+
+#
+#
+SHOW_BUSYBUFS
+PANIC_REBOOT_WAIT_TIME  opt_panic.h
diff --git a/sys/platform/vkernel64/include/clock.h b/sys/platform/vkernel64/include/clock.h
new file mode 100644 (file)
index 0000000..6465b61
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Kernel interface to machine-dependent clock driver.
+ * Garrett Wollman, September 1994.
+ * This file is in the public domain.
+ *
+ * $FreeBSD: src/sys/i386/include/clock.h,v 1.38.2.1 2002/11/02 04:41:50 iwasaki Exp $
+ * $DragonFly: src/sys/platform/vkernel/include/clock.h,v 1.2 2008/05/10 17:24:11 dillon Exp $
+ */
+
+#ifndef _MACHINE_CLOCK_H_
+#define        _MACHINE_CLOCK_H_
+
+#ifdef _KERNEL
+
+#ifndef _SYS_TYPES_H_
+#include <sys/types.h>
+#endif
+
+/*
+ * i386 to clock driver interface.
+ * XXX large parts of the driver and its interface are misplaced.
+ */
+extern int     adjkerntz;
+extern int     disable_rtc_set;
+extern int     statclock_disable;
+extern u_int   timer_freq;
+extern int     timer0_max_count;
+extern int     tsc_present;
+extern int64_t tsc_frequency;
+extern int     tsc_is_broken;
+extern int     wall_cmos_clock;
+#ifdef APIC_IO
+extern int     apic_8254_intr;
+#endif
+
+/*
+ * Driver to clock driver interface.
+ */
+
+int    rtcin (int val);
+int    acquire_timer2 (int mode);
+int    release_timer2 (void);
+int    sysbeep (int pitch, int period);
+void   timer_restore (void);
+
+#endif /* _KERNEL */
+
+#endif /* !_MACHINE_CLOCK_H_ */
similarity index 56%
copy from sys/platform/pc64/x86_64/in_cksum2.s
copy to sys/platform/vkernel64/include/cothread.h
index bf249cc..7fd72a2 100644 (file)
@@ -1,13 +1,13 @@
 /*
- * Copyright (c) 2003,2004,2008 The DragonFly Project.  All rights reserved.
- * 
+ * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
+ *
  * This code is derived from software contributed to The DragonFly Project
  * by Matthew Dillon <dillon@backplane.com>
- * 
+ *
  * 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
@@ -17,7 +17,7 @@
  * 3. Neither the name of The DragonFly Project nor the names of its
  *    contributors may be used to endorse or promote products derived
  *    from this software without specific, prior written permission.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
+ *
+ * $DragonFly: src/sys/platform/vkernel/include/cothread.h,v 1.2 2008/03/27 04:28:07 dillon Exp $
  */
 
-#include <machine/asmacros.h>          /* miscellaneous asm macros */
+#ifndef _MACHINE_COTHREAD_H_
+#define _MACHINE_COTHREAD_H_
 
-#include "assym.s"
+#include <pthread.h>
 
-       .text
+struct cothread {
+       pthread_t       pthr;
+       pthread_t       pintr;
+       void            *arg;
+       void            (*thr_func)(struct cothread *);
+       void            (*thr_intr)(struct cothread *);
+       void            *intr_id;
+       pthread_mutex_t mutex;
+       pthread_cond_t  cond;
+};
 
-       /*
-        * asm_ones32(32bitalignedbuffer, numberof32bitwords)
-        *
-        * Returns the 32 bit one complement partial checksum.  This is 
-        * basically a 1's complement checksum without the inversion (~)
-        * at the end.  A 32 bit value is returned.  If the caller is 
-        * calculating a 16 bit 1's complement checksum the caller must
-        * collapse the 32 bit return value via:
-        *
-        *      result = (result >> 16) + (result & 0xFFFF)
-        *      if (result > 0xFFFF)
-        *          result -= 0xFFFF;   <<< same as (result + 1) & 0xFFFF
-        *                                  within the range of result.
-        * Note that worst case 0xFFFFFFFF + 0xFFFFFFFF = 0xFFFFFFFE + CARRY,
-        * so no double-carry ever occurs.
-        */
-       .p2align 4
-ENTRY(asm_ones32)
-       movq    %rdi,%rdx       /* %rdx = buffer pointer */
-       movl    %esi,%ecx       /* %ecx = counter */
-       xorl    %eax,%eax       /* %eax = checksum */
-       cmpl    $5,%ecx
-       jl      2f
-1:
-       subl    $5,%ecx
-       addl    (%rdx),%eax
-       adcl    4(%rdx),%eax
-       adcl    8(%rdx),%eax
-       adcl    12(%rdx),%eax
-       adcl    16(%rdx),%eax
-       adcl    $0,%eax
-       addq    $20,%rdx
-       cmpl    $5,%ecx
-       jge     1b
-2:
-       testl   %ecx,%ecx
-       je      4f
-3:
-       addl    (%rdx),%eax
-       adcl    $0,%eax
-       addq    $4,%rdx
-       decl    %ecx
-       jnz     3b
-4:
-       ret
+typedef struct cothread *cothread_t;
+
+cothread_t cothread_create(void (*thr_func)(cothread_t cotd),
+                          void (*thr_intr)(cothread_t cotd),
+                          void *arg, const  char *name);
+void cothread_delete(cothread_t *cotdp);
+void cothread_intr(cothread_t cotd);
+void cothread_signal(cothread_t cotd);
+void cothread_wait(cothread_t cotd);
+void cothread_lock(cothread_t cotd, int is_cotd);
+void cothread_unlock(cothread_t cotd, int is_cotd);
+
+#endif
similarity index 56%
copy from sys/platform/pc64/x86_64/ktr.c
copy to sys/platform/vkernel64/include/cpu.h
index a85a71c..c1d1373 100644 (file)
@@ -1,13 +1,13 @@
 /*
- * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
- * 
+ * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
+ *
  * This code is derived from software contributed to The DragonFly Project
  * by Matthew Dillon <dillon@backplane.com>
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -17,7 +17,7 @@
  * 3. Neither the name of The DragonFly Project nor the names of its
  *    contributors may be used to endorse or promote products derived
  *    from this software without specific, prior written permission.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  * 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.
- */
-/*
- * Kernel tracepoint facility.
+ *
+ * $DragonFly: src/sys/platform/vkernel/include/cpu.h,v 1.3 2008/05/19 10:29:58 corecode Exp $
  */
 
-#include "opt_ddb.h"
-#include "opt_ktr.h"
+#ifndef _MACHINE_CPU_H_
+#define _MACHINE_CPU_H_
 
-#include <sys/param.h>
-#include <sys/cons.h>
-#include <sys/kernel.h>
-#include <sys/libkern.h>
-#include <sys/proc.h>
-#include <sys/sysctl.h>
-#include <sys/ktr.h>
+#include <cpu/cpu.h>
 
-/*
- * This routine fills in the ktr_caller1 and ktr_caller2 fields by
- * tracing back through the kernel stack to locate the stack frames
- * and return addresses.
- *
- *
- *     [first argument]
- *     [retpc]
- *     [frameptr]              -> points to caller's frame pointer
- * sp ->[junk]
- */
+#define CLKF_USERMODE(framep) ((framep)->if_xflags & PGEX_U)
+
+/* globals used in vkernel CPU to kernel CPU locking */
+#if defined(_KERNEL)
+
+extern int lwp_cpu_lock;
+extern int next_cpu;
+extern int real_ncpus;
+void setrealcpu(void);
+void identcpu(void);
 
-static __inline 
-void **
-FRAMEUP(void **frameptr)
-{
-    void **newframeptr;
+#endif
 
-    newframeptr = (void **)frameptr[0];
-    if (((uintptr_t)newframeptr ^ (uintptr_t)frameptr) & ~16383)
-       newframeptr = frameptr;
-    return(newframeptr);
-}
+#if defined(_KERNEL) || defined(_KERNEL_STRUCTURES)
 
-void
-cpu_ktr_caller(struct ktr_entry *_ktr)
-{
-    struct ktr_entry *ktr;
-    void **frameptr;
+#define LCL_NONE        0
+#define LCL_PER_CPU     1
+#define LCL_SINGLE_CPU  2
 
-    frameptr = (void **)&_ktr - 2;     /* frame, retpc to ktr_log */
-    ktr = _ktr;
-    frameptr = FRAMEUP(frameptr);      /* frame, retpc to traced function */
-    frameptr = FRAMEUP(frameptr);      /* frame, caller1 of traced function */
-    ktr->ktr_caller1 = frameptr[1];
-    frameptr = FRAMEUP(frameptr);      /* frame, caller2 of caller1 */
-    ktr->ktr_caller2 = frameptr[1];
-}
+#endif
 
+#endif
similarity index 57%
copy from sys/platform/pc64/x86_64/ktr.c
copy to sys/platform/vkernel64/include/cpufunc.h
index a85a71c..4418245 100644 (file)
@@ -1,13 +1,13 @@
 /*
- * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
- * 
+ * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
+ *
  * This code is derived from software contributed to The DragonFly Project
  * by Matthew Dillon <dillon@backplane.com>
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -17,7 +17,7 @@
  * 3. Neither the name of The DragonFly Project nor the names of its
  *    contributors may be used to endorse or promote products derived
  *    from this software without specific, prior written permission.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
+ *
+ * $DragonFly: src/sys/platform/vkernel/include/cpufunc.h,v 1.2 2007/02/18 14:28:18 corecode Exp $
  */
-/*
- * Kernel tracepoint facility.
- */
+#ifndef _MACHINE_CPUFUNC_H_
+#define        _MACHINE_CPUFUNC_H_
 
-#include "opt_ddb.h"
-#include "opt_ktr.h"
-
-#include <sys/param.h>
-#include <sys/cons.h>
-#include <sys/kernel.h>
-#include <sys/libkern.h>
-#include <sys/proc.h>
-#include <sys/sysctl.h>
-#include <sys/ktr.h>
+#ifdef _KERNEL
 
 /*
- * This routine fills in the ktr_caller1 and ktr_caller2 fields by
- * tracing back through the kernel stack to locate the stack frames
- * and return addresses.
- *
+ * First declare our overriding functions.  We have to do this to prevent
+ * cpu/cpufunc.h to define inline assembler versions.  However, we need
+ * cpu/cpufunc.h to define other functions like ``ffs'', which will otherwise
+ * be defined by libkern (via sys/systm.h).  This is why the order needs to be:
  *
- *     [first argument]
- *     [retpc]
- *     [frameptr]              -> points to caller's frame pointer
- * sp ->[junk]
+ * 1. Declare our overrides
+ * 2. include cpu/cpufunc.h
+ * 3. include the remaining needed headers for our overrides
  */
 
-static __inline 
-void **
-FRAMEUP(void **frameptr)
-{
-    void **newframeptr;
+#define _CPU_ENABLE_INTR_DEFINED
+#define _CPU_DISABLE_INTR_DEFINED
+#define _CPU_INVLPG_DEFINED
+#define _CPU_INVLTLB_DEFINED
+
+void cpu_disable_intr(void);
+void cpu_enable_intr(void);
+void cpu_invlpg(void *addr);
+void cpu_invltlb(void);
+
+#endif
 
-    newframeptr = (void **)frameptr[0];
-    if (((uintptr_t)newframeptr ^ (uintptr_t)frameptr) & ~16383)
-       newframeptr = frameptr;
-    return(newframeptr);
-}
+#include <cpu/cpufunc.h>
+
+#ifdef _KERNEL
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <vm/pmap.h>
 
-void
-cpu_ktr_caller(struct ktr_entry *_ktr)
-{
-    struct ktr_entry *ktr;
-    void **frameptr;
+#include <sys/mman.h>
+#include <signal.h>
 
-    frameptr = (void **)&_ktr - 2;     /* frame, retpc to ktr_log */
-    ktr = _ktr;
-    frameptr = FRAMEUP(frameptr);      /* frame, retpc to traced function */
-    frameptr = FRAMEUP(frameptr);      /* frame, caller1 of traced function */
-    ktr->ktr_caller1 = frameptr[1];
-    frameptr = FRAMEUP(frameptr);      /* frame, caller2 of caller1 */
-    ktr->ktr_caller2 = frameptr[1];
-}
+#endif /* _KERNEL */
 
+#endif /* !_MACHINE_CPUFUNC_H_ */
diff --git a/sys/platform/vkernel64/include/globaldata.h b/sys/platform/vkernel64/include/globaldata.h
new file mode 100644 (file)
index 0000000..770eed2
--- /dev/null
@@ -0,0 +1,132 @@
+/*-
+ * Copyright (c) Peter Wemm <peter@netplex.com.au>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     Only machine-dependant code should ever include this file.  MI
+ *     code and header files do NOT include this file.  e.g. sys/globaldata.h
+ *     should not include this file.
+ *
+ * $FreeBSD: src/sys/i386/include/globaldata.h,v 1.11.2.1 2000/05/16 06:58:10 dillon Exp $
+ * $DragonFly: src/sys/platform/vkernel/include/globaldata.h,v 1.8 2008/04/28 07:05:07 dillon Exp $
+ */
+
+#ifndef _MACHINE_GLOBALDATA_H_
+#define _MACHINE_GLOBALDATA_H_
+
+#if defined(_KERNEL) || defined(_KERNEL_STRUCTURES)
+
+#ifndef _SYS_GLOBALDATA_H_
+#include <sys/globaldata.h>    /* struct globaldata */
+#endif
+#ifndef _SYS_THREAD_H_
+#include <sys/thread.h>                /* struct thread */
+#endif
+#ifndef _SYS_VKERNEL_H_
+#include <sys/vkernel.h>       /* vpte_t */
+#endif
+#ifndef _MACHINE_SEGMENTS_H_
+#include <machine/segments.h>  /* struct segment_descriptor */
+#endif
+#ifndef _MACHINE_TSS_H_
+#include <machine/tss.h>       /* struct i386tss */
+#endif
+#ifndef _MACHINE_NPX_H_
+#include <machine/npx.h>
+#endif
+
+/*
+ * Note on interrupt control.  Pending interrupts not yet dispatched are
+ * marked in gd_fpending, gd_ipending, or gd_spending.  Once dispatched
+ * the interrupt's pending bit is cleared and the interrupt is masked.
+ * Upon completion the interrupt is unmasked.
+ *
+ * For edge triggered interrupts interrupts may be enabled again at this
+ * point and if they occur before the interrupt service routine is complete
+ * the service routine will loop.
+ *
+ * The current thread's cpl is stored in the thread structure.
+ *
+ * Note: the embedded globaldata and/or the mdglobaldata structure
+ * may exceed the size of a page.
+ */
+struct mdglobaldata {
+       struct globaldata mi;
+       struct user_segment_descriptor gd_common_tssd;
+       struct user_segment_descriptor *gd_tss_gdt;
+       struct thread   *gd_npxthread;
+       struct x86_64tss gd_common_tss;
+       union savefpu   gd_savefpu;     /* fast bcopy/zero temp fpu save area */
+       int             gd_fpu_lock;    /* fast bcopy/zero cpu lock */
+       int             gd_fpending;    /* fast interrupt pending */
+       int             gd_ipending;    /* normal interrupt pending */
+       int             gd_spending;    /* software interrupt pending */
+       int             gd_sdelayed;    /* delayed software ints */
+       int             gd_currentldt;
+       int             unused003;
+       int             unused002;
+       u_int           unused001;
+       u_int           gd_other_cpus;
+       u_int           gd_ss_eflags;
+};
+
+#define MDGLOBALDATA_BASEALLOC_SIZE    \
+       ((sizeof(struct mdglobaldata) + PAGE_MASK) & ~PAGE_MASK)
+#define MDGLOBALDATA_BASEALLOC_PAGES   \
+       (MDGLOBALDATA_BASEALLOC_SIZE / PAGE_SIZE)
+#define MDGLOBALDATA_PAD               \
+       (MDGLOBALDATA_BASEALLOC_SIZE - sizeof(struct mdglobaldata))
+
+/*
+ * This is the upper (0xff800000) address space layout that is per-cpu.
+ * It is setup in locore.s and pmap.c for the BSP and in mp_machdep.c for
+ * each AP.  genassym helps export this to the assembler code.
+ *
+ * WARNING!  This structure must be segment-aligned and portions within the
+ *           structure must also be segment-aligned.  The structure typically
+ *          takes 3 segments per cpu (12MB).
+ */
+#define PRIVATESPACE_SEGPAD    \
+       (SEG_SIZE -             \
+       ((sizeof(struct mdglobaldata) + MDGLOBALDATA_PAD + PAGE_SIZE * 4 +  \
+       UPAGES * PAGE_SIZE) % SEG_SIZE))                                    \
+
+struct privatespace {
+       /* main data page */
+       struct mdglobaldata mdglobaldata;
+       char            __filler0[MDGLOBALDATA_PAD];
+
+       /* idle stack (UPAGES pages) */
+       char            idlestack[UPAGES * PAGE_SIZE];
+};
+#define mdcpu                  ((struct mdglobaldata *)_get_mycpu())
+
+#endif
+
+#ifdef _KERNEL
+
+extern struct privatespace *CPU_prvspace;
+
+#endif
+
+#endif
similarity index 56%
copy from sys/platform/pc64/x86_64/in_cksum2.s
copy to sys/platform/vkernel64/include/lock.h
index bf249cc..7c365f0 100644 (file)
@@ -1,13 +1,13 @@
 /*
- * Copyright (c) 2003,2004,2008 The DragonFly Project.  All rights reserved.
- * 
+ * Copyright (c) 2003-2006 The DragonFly Project.  All rights reserved.
+ *
  * This code is derived from software contributed to The DragonFly Project
  * by Matthew Dillon <dillon@backplane.com>
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -17,7 +17,7 @@
  * 3. Neither the name of The DragonFly Project nor the names of its
  *    contributors may be used to endorse or promote products derived
  *    from this software without specific, prior written permission.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/i386/include/lock.h,v 1.11.2.2 2000/09/30 02:49:34 ps Exp $
+ * $DragonFly: src/sys/platform/vkernel/include/lock.h,v 1.2 2008/06/19 21:32:55 aggelos Exp $
  */
 
-#include <machine/asmacros.h>          /* miscellaneous asm macros */
+#ifndef _MACHINE_LOCK_H_
+#define _MACHINE_LOCK_H_
 
-#include "assym.s"
+#ifndef _CPU_PSL_H_
+#include <machine/psl.h>
+#endif
 
-       .text
+#ifndef LOCORE
 
-       /*
-        * asm_ones32(32bitalignedbuffer, numberof32bitwords)
-        *
-        * Returns the 32 bit one complement partial checksum.  This is 
-        * basically a 1's complement checksum without the inversion (~)
-        * at the end.  A 32 bit value is returned.  If the caller is 
-        * calculating a 16 bit 1's complement checksum the caller must
-        * collapse the 32 bit return value via:
-        *
-        *      result = (result >> 16) + (result & 0xFFFF)
-        *      if (result > 0xFFFF)
-        *          result -= 0xFFFF;   <<< same as (result + 1) & 0xFFFF
-        *                                  within the range of result.
-        * Note that worst case 0xFFFFFFFF + 0xFFFFFFFF = 0xFFFFFFFE + CARRY,
-        * so no double-carry ever occurs.
-        */
-       .p2align 4
-ENTRY(asm_ones32)
-       movq    %rdi,%rdx       /* %rdx = buffer pointer */
-       movl    %esi,%ecx       /* %ecx = counter */
-       xorl    %eax,%eax       /* %eax = checksum */
-       cmpl    $5,%ecx
-       jl      2f
-1:
-       subl    $5,%ecx
-       addl    (%rdx),%eax
-       adcl    4(%rdx),%eax
-       adcl    8(%rdx),%eax
-       adcl    12(%rdx),%eax
-       adcl    16(%rdx),%eax
-       adcl    $0,%eax
-       addq    $20,%rdx
-       cmpl    $5,%ecx
-       jge     1b
-2:
-       testl   %ecx,%ecx
-       je      4f
-3:
-       addl    (%rdx),%eax
-       adcl    $0,%eax
-       addq    $4,%rdx
-       decl    %ecx
-       jnz     3b
-4:
-       ret
+#endif /* LOCORE */
+#endif /* !_MACHINE_LOCK_H_ */
diff --git a/sys/platform/vkernel64/include/md_var.h b/sys/platform/vkernel64/include/md_var.h
new file mode 100644 (file)
index 0000000..cfa8d4a
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon@backplane.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $DragonFly: src/sys/platform/vkernel/include/md_var.h,v 1.24 2008/03/20 02:14:54 dillon Exp $
+ */
+
+#ifndef _MACHINE_MD_VAR_H_
+#define _MACHINE_MD_VAR_H_
+
+#ifndef _SYS_TYPES_H_
+#include <sys/types.h>
+#endif
+#ifndef _SYS_VKERNEL_H_
+#include <sys/vkernel.h>
+#endif
+
+#define VKNETIF_MAX    16
+#define VKDISK_MAX     16
+
+struct vknetif_info {
+       int             tap_fd;
+       int             tap_unit;
+       in_addr_t       netif_addr;
+       in_addr_t       netif_mask;
+};
+
+struct vkdisk_info {
+        int fd;
+        int unit;
+       enum vkdisk_type { VKD_EMPTY, VKD_DISK, VKD_CD } type;
+        char fname[MAXPATHLEN];
+};
+
+extern char    sigcode[];
+extern int     szsigcode;
+extern vpte_t  *KernelPTA;     /* NOTE: Offset for direct VA translation */
+extern vpte_t  *KernelPTD;
+extern vm_offset_t crashdumpmap;
+extern  int    cpu_fxsr;
+
+extern  char    cpu_vendor[];  /* XXX belongs in i386 */
+extern  u_int   cpu_id;                /* XXX belongs in i386 */
+
+extern struct vkdisk_info DiskInfo[VKDISK_MAX];
+extern int     DiskNum;
+extern int     MemImageFd;
+extern struct vknetif_info NetifInfo[VKNETIF_MAX];
+extern int     NetifNum;
+extern int     _ucodesel, _udatasel;
+
+extern int     via_feature_xcrypt;
+extern int     via_feature_rng;
+
+struct mdglobaldata;
+struct __mcontext;
+
+vpte_t *pmap_kpte(vm_offset_t va);
+void cpu_gdinit (struct mdglobaldata *gd, int cpu);
+
+void cpu_heavy_restore(void);  /* cannot be called from C */
+void cpu_lwkt_restore(void);    /* cannot be called from C */
+void cpu_idle_restore(void);    /* cannot be called from C */
+void cpu_kthread_restore(void);        /* cannot be called from C */
+void cpu_exit_switch (struct thread *next);
+void cpu_setregs (void);
+void cpu_idle (void);
+void cpu_mask_all_signals (void);
+void cpu_unmask_all_signals (void);
+void go_user (struct intrframe *frame);
+
+void init_exceptions(void);
+void init_kqueue(void);
+void init_fpu(int supports_sse);
+void kern_trap(struct trapframe *);
+void user_trap(struct trapframe *);
+void syscall2 (struct trapframe *);
+void vcons_set_mode(int);
+int npxdna(struct trapframe *);
+void npxpush(struct __mcontext *mctx);
+void npxpop(struct __mcontext *mctx);
+
+void signalintr(int intr);
+
+struct kqueue_info;
+struct kqueue_info *kqueue_add(int, void (*)(void *, struct intrframe *), void *);
+void kqueue_del(struct kqueue_info *);
+struct kqueue_info *kqueue_add_timer(void (*func)(void *, struct intrframe *), void *data);
+void kqueue_reload_timer(struct kqueue_info *info, int ms);
+
+
+#endif
diff --git a/sys/platform/vkernel64/include/param.h b/sys/platform/vkernel64/include/param.h
new file mode 100644 (file)
index 0000000..d500d32
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * $DragonFly: src/sys/platform/vkernel/include/param.h,v 1.4 2008/05/06 18:37:58 dillon Exp $
+ */
+
+#ifndef _MACHINE_PARAM_H_
+
+#ifndef _NO_NAMESPACE_POLLUTION
+#define _MACHINE_PARAM_H_
+#endif
+
+#ifndef _MACHINE_PLATFORM
+#define _MACHINE_PLATFORM      vkernel64
+#endif
+
+#ifndef _NO_NAMESPACE_POLLUTION
+
+#ifndef MACHINE_PLATFORM
+#define MACHINE_PLATFORM       "vkernel64"
+#endif
+
+#endif
+
+#if 0
+/*
+ * This is kinda silly but why not?  We use a 32 bit bitmask so 31 is
+ * the most we can have.  We use the msb bit for other purposes in the
+ * spinlock code so we can't have 32.
+ *
+ * XXX just use the cpu default (16) so buildworld binaries are compatible.
+ */
+#ifndef SMP_MAXCPU
+#define SMP_MAXCPU     31
+#endif
+#endif
+
+/*
+ * Set the default HZ to the likely resolution of the kqueue timer
+ * the vkernel uses, otherwise our ticks will be seriously off and
+ * while date/time will be correct, sleep intervals will not.
+ */
+#ifdef _KERNEL
+#ifndef HZ
+#define HZ     20
+#endif
+#endif
+
+#include <cpu/param.h>
+
+#endif
similarity index 53%
copy from sys/cpu/x86_64/include/types.h
copy to sys/platform/vkernel64/include/pcb.h
index bfb6c13..d799876 100644 (file)
@@ -1,7 +1,11 @@
 /*-
- * Copyright (c) 1990, 1993
- *     The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1990 The Regents of the University of California.
+ * Copyright (c) 2003 Peter Wemm.
  * Copyright (c) 2008 The DragonFly Project.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)types.h     8.3 (Berkeley) 1/5/94
- * $FreeBSD: src/sys/i386/include/types.h,v 1.19.2.1 2001/03/21 10:50:58 peter Exp $
+ *     from: @(#)pcb.h 5.10 (Berkeley) 5/12/91
+ * $FreeBSD: src/sys/i386/include/pcb.h,v 1.32.2.1 2001/08/15 01:23:52 peter Exp $
+ * $DragonFly: src/sys/platform/vkernel/include/pcb.h,v 1.3 2007/01/09 23:34:05 dillon Exp $
  */
 
-#ifndef _CPU_TYPES_H_
-#define        _CPU_TYPES_H_
+#ifndef _MACHINE_PCB_H_
+#define _MACHINE_PCB_H_
 
-#if defined(__x86_64__)
-typedef        __int64_t       __segsz_t;      /* segment size */
-typedef        __int64_t       register_t;
-typedef        __uint64_t      u_register_t;
-#elif defined(__i386__)
-typedef        __int32_t       __segsz_t;      /* segment size */
-typedef        __int32_t       register_t;
-typedef        __uint32_t      u_register_t;
-#endif
+/*
+ * AMD64 process control block
+ */
+#include <machine/npx.h>
 
-typedef unsigned long  vm_offset_t;    /* address space bounded offset */
-typedef unsigned long  vm_size_t;      /* address space bounded size */
+struct pcb {
+       register_t      padxx[8];
+       register_t      pcb_unused01;
+       register_t      pcb_r15;
+       register_t      pcb_r14;
+       register_t      pcb_r13;
+       register_t      pcb_r12;
+       register_t      pcb_rbp;
+       register_t      pcb_rsp;
+       register_t      pcb_rbx;
+       register_t      pcb_rip;
+       register_t      pcb_rsi;
+       register_t      pcb_rdi;
+       register_t      pcb_rflags;
+       register_t      pcb_fsbase;
+       register_t      pcb_gsbase;
+       u_long          pcb_flags;
+       u_int32_t       pcb_ds;
+       u_int32_t       pcb_es;
+       u_int32_t       pcb_fs;
+       u_int32_t       pcb_gs;
+       u_int64_t       pcb_dr0;
+       u_int64_t       pcb_dr1;
+       u_int64_t       pcb_dr2;
+       u_int64_t       pcb_dr3;
+       u_int64_t       pcb_dr6;
+       u_int64_t       pcb_dr7;
 
-typedef __uint64_t     vm_pindex_t;    /* physical page index */
-typedef        __int64_t       vm_ooffset_t;   /* VM object bounded offset */
-typedef __uint64_t     vm_poff_t;      /* physical offset */
-typedef __uint64_t     vm_paddr_t;     /* physical addr (same as vm_poff_t) */
+       struct pcb_ldt *pcb_ldt;
+       union savefpu   pcb_save;
+#define        PCB_DBREGS      0x02    /* process using debug registers */
+#define        PCB_FPUINITDONE 0x08    /* fpu state is initialized */
+#define FP_SOFTFP       0x01    /* process using software fltng pnt emulator */
+#define        FP_VIRTFP       0x04    /* virtual kernel wants exception */
+       caddr_t pcb_onfault;    /* copyin/out fault recovery */
+       int     pcb_unused;
+       struct  pcb_ext *pcb_ext;       /* optional pcb extension */
+};
 
 #ifdef _KERNEL
-typedef        __int64_t       intfptr_t;
-typedef        __uint64_t      uintfptr_t;
-#endif
-
-/*
- * MMU page tables
- */
-#ifndef JG_defined_pml4_entry_t
-#define JG_defined_pml4_entry_t
-typedef __uint64_t     pml4_entry_t;
-typedef __uint64_t     pdp_entry_t;
-typedef __uint64_t     pd_entry_t;
-typedef __uint64_t     pt_entry_t;
+void   savectx(struct pcb *);
 #endif
-typedef __uint32_t      cpumask_t;      /* mask representing a set of cpus */
-
-#define PML4SIZE       sizeof(pml4_entry_t) /* for assembly files */
-#define PDPSIZE                sizeof(pdp_entry_t) /* for assembly files */
-#define PDESIZE         sizeof(pd_entry_t) /* for assembly files */
-#define PTESIZE         sizeof(pt_entry_t) /* for assembly files */
-
-#endif /* !_CPU_TYPES_H_ */
 
+#endif /* _MACHINE_PCB_H_ */
similarity index 57%
copy from include/strings.h
copy to sys/platform/vkernel64/include/pcb_ext.h
index 7c90b89..4f12f83 100644 (file)
@@ -1,5 +1,6 @@
 /*-
- * Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org>
+ * Copyright (c) 1997 Jonathan Lemon
+ * Copyright (c) 2008 The DragonFly Project.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/include/strings.h,v 1.7 2008/11/03 10:22:19 kib Exp $
+ * $FreeBSD: src/sys/i386/include/pcb_ext.h,v 1.4 1999/12/29 04:33:04 peter Exp $
+ * $DragonFly: src/sys/platform/pc64/include/pcb_ext.h,v 1.3 2008/08/29 17:07:17 dillon Exp $
  */
 
-#ifndef _STRINGS_H_
-#define        _STRINGS_H_
+#ifndef _MACHINE_PCB_EXT_H_
+#define _MACHINE_PCB_EXT_H_
 
-#include <sys/cdefs.h>
+#ifndef _SYS_TYPES_H_
 #include <sys/types.h>
-
-#ifndef _SIZE_T_DECLARED
-typedef        __size_t        size_t;
-#define        _SIZE_T_DECLARED
 #endif
 
-__BEGIN_DECLS
-#if !defined(_KERNEL_VIRTUAL)
-int     bcmp(const void *, const void *, size_t) __pure;       /* LEGACY */
-void    bcopy(const void *, void *, size_t);                   /* LEGACY */
-void    bzero(void *, size_t);                                 /* LEGACY */
-int     ffs(int) __pure2;
-#endif
-#ifdef __BSD_VISIBLE
-int     ffsl(long) __pure2;
-int     ffsll(long long) __pure2;
-#if !defined(_KERNEL_VIRTUAL)
-int     fls(int) __pure2;
-int     flsl(long) __pure2;
+/*
+ * Extension to the 386 process control block
+ */
+#ifndef _MACHINE_TSS_H_
+#include <machine/tss.h>
 #endif
-int     flsll(long long) __pure2;
+#ifndef _MACHINE_SEGMENTS_H_
+#include <machine/segments.h>
 #endif
-#if !defined(_KERNEL_VIRTUAL)
-char   *index(const char *, int) __pure;                       /* LEGACY */
-char   *rindex(const char *, int) __pure;                      /* LEGACY */
+
+struct pcb_ext {
+       struct  user_segment_descriptor ext_tssd;       /* tss descriptor */
+       struct  x86_64tss       ext_tss;        /* per-process amd64tss */
+       caddr_t ext_iomap;              /* i/o permission bitmap */
+};
+
+/* JG remove this structure? */
+struct pcb_ldt {
+       caddr_t ldt_base;
+       int     ldt_len;
+       int     ldt_refcnt;
+       u_long  ldt_active;
+       struct  user_segment_descriptor ldt_sd;
+};
+
+#ifdef _KERNEL
+
+struct pcb;
+
+void set_user_ldt (struct pcb *);
+struct pcb_ldt *user_ldt_alloc (struct pcb *, int);
+void user_ldt_free (struct pcb *);
+
 #endif
-int     strcasecmp(const char *, const char *) __pure;
-int     strncasecmp(const char *, const char *, size_t) __pure;
-__END_DECLS
 
-#endif /* _STRINGS_H_ */
+#endif /* _MACHINE_PCB_EXT_H_ */
similarity index 80%
copy from sys/platform/vkernel/include/pmap.h
copy to sys/platform/vkernel64/include/pmap.h
index 40e3487..4a0691b 100644 (file)
 #include <cpu/pmap.h>
 
 /*
- * Size of Kernel address space.  This is the number of page table pages
- * (4MB each) to use for the kernel.  256 pages == 1 Gigabyte.
- * This **MUST** be a multiple of 4 (eg: 252, 256, 260, etc).
+ * Pte related macros
  */
-#ifndef KVA_PAGES
-#define KVA_PAGES      256
+#define KVADDR(l4, l3, l2, l1) ( \
+       ((unsigned long)-1 << 47) | \
+       ((unsigned long)(l4) << PML4SHIFT) | \
+       ((unsigned long)(l3) << PDPSHIFT) | \
+       ((unsigned long)(l2) << PDRSHIFT) | \
+       ((unsigned long)(l1) << PAGE_SHIFT))
+
+#define UVADDR(l4, l3, l2, l1) ( \
+       ((unsigned long)(l4) << PML4SHIFT) | \
+       ((unsigned long)(l3) << PDPSHIFT) | \
+       ((unsigned long)(l2) << PDRSHIFT) | \
+       ((unsigned long)(l1) << PAGE_SHIFT))
+
+/* Initial number of kernel page tables. */
+#ifndef NKPT
+#define        NKPT            32
 #endif
 
+#define NKPML4E                1               /* number of kernel PML4 slots */
+#define NKPDPE         howmany(NKPT, NPDEPG)/* number of kernel PDP slots */
+
+#define        NUPML4E         (NPML4EPG/2)    /* number of userland PML4 pages */
+#define        NUPDPE          (NUPML4E*NPDPEPG)/* number of userland PDP pages */
+#define        NUPDE           (NUPDPE*NPDEPG) /* number of userland PD entries */
+
+#define        NDMPML4E        1               /* number of dmap PML4 slots */
+
 /*
- * Pte related macros
+ * The *PML4I values control the layout of virtual memory
  */
-#define VADDR(pdi, pti) ((vm_offset_t)(((pdi)<<PDRSHIFT)|((pti)<<PAGE_SHIFT)))
+#define        PML4PML4I       (NPML4EPG/2)    /* Index of recursive pml4 mapping */
+
 
 #ifndef LOCORE
 
@@ -95,6 +117,8 @@ vm_paddr_t pmap_kextract(vm_offset_t);
 
 #endif
 
+#define        pte_load_clear(pte)     atomic_readandclear_long(pte)
+
 /*
  * Pmap stuff
  */
@@ -120,22 +144,20 @@ struct pmap_statistics {
 typedef struct pmap_statistics *pmap_statistics_t;
 
 struct pmap {
-       pd_entry_t              *pm_pdir;       /* KVA of page directory */
+       pml4_entry_t            *pm_pml4;       /* KVA of level 4 page table */
+       struct vm_page          *pm_pdirm;      /* VM page for pg directory */
        vpte_t                  pm_pdirpte;     /* pte mapping phys page */
        struct vm_object        *pm_pteobj;     /* Container for pte's */
-       cpumask_t               pm_cpucachemask;/* Invalidate cpu mappings */
        TAILQ_ENTRY(pmap)       pm_pmnode;      /* list of pmaps */
        TAILQ_HEAD(,pv_entry)   pm_pvlist;      /* list of mappings in pmap */
        int                     pm_count;       /* reference count */
        cpumask_t               pm_active;      /* active on cpus */
-       int                     pm_pdindex;     /* page dir page in obj */
+       vm_pindex_t             pm_pdindex;     /* page dir page in obj */
        struct pmap_statistics  pm_stats;       /* pmap statistics */
        struct  vm_page         *pm_ptphint;    /* pmap ptp hint */
        int                     pm_generation;  /* detect pvlist deletions */
 };
 
-#define CPUMASK_LOCK            (1 << SMP_MAXCPU)
-
 #define pmap_resident_count(pmap) (pmap)->pm_stats.resident_count
 
 typedef struct pmap    *pmap_t;
@@ -164,13 +186,10 @@ extern char *ptvmmap;             /* poor name! */
 extern vm_offset_t clean_sva;
 extern vm_offset_t clean_eva;
 
-void   pmap_bootstrap (void);
+void   pmap_bootstrap(vm_paddr_t *, int64_t);
 void   *pmap_mapdev (vm_paddr_t, vm_size_t);
 void   pmap_unmapdev (vm_offset_t, vm_size_t);
 struct vm_page *pmap_use_pt (pmap_t, vm_offset_t);
-#ifdef SMP
-void   pmap_set_opt (void);
-#endif
 
 #endif /* _KERNEL */
 
similarity index 54%
copy from sys/platform/pc64/x86_64/ktr.c
copy to sys/platform/vkernel64/include/pmap_inval.h
index a85a71c..f99fe3f 100644 (file)
@@ -1,13 +1,13 @@
 /*
- * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
- * 
+ * Copyright (c) 2003,2004 The DragonFly Project.  All rights reserved.
+ *
  * This code is derived from software contributed to The DragonFly Project
  * by Matthew Dillon <dillon@backplane.com>
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -17,7 +17,7 @@
  * 3. Neither the name of The DragonFly Project nor the names of its
  *    contributors may be used to endorse or promote products derived
  *    from this software without specific, prior written permission.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  * 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.
- */
-/*
- * Kernel tracepoint facility.
+ *
+ * $DragonFly: src/sys/platform/vkernel/include/pmap_inval.h,v 1.3 2007/07/02 02:22:57 dillon Exp $
  */
 
-#include "opt_ddb.h"
-#include "opt_ktr.h"
+#ifndef _MACHINE_PMAP_INVAL_H_
+#define        _MACHINE_PMAP_INVAL_H_
 
-#include <sys/param.h>
-#include <sys/cons.h>
-#include <sys/kernel.h>
-#include <sys/libkern.h>
-#include <sys/proc.h>
-#include <sys/sysctl.h>
-#include <sys/ktr.h>
+#ifndef _SYS_THREAD_H_
+#include <sys/thread.h>
+#endif
 
-/*
- * This routine fills in the ktr_caller1 and ktr_caller2 fields by
- * tracing back through the kernel stack to locate the stack frames
- * and return addresses.
- *
- *
- *     [first argument]
- *     [retpc]
- *     [frameptr]              -> points to caller's frame pointer
- * sp ->[junk]
- */
+typedef struct pmap_inval_info {
+    int                        pir_flags;
+    struct lwkt_cpusync        pir_cpusync;
+} pmap_inval_info;
+
+typedef pmap_inval_info *pmap_inval_info_t;
+
+#define PIRF_INVLTLB   0x0001  /* request invalidation of whole table */
+#define PIRF_INVL1PG   0x0002  /* else request invalidation of one page */
+#define PIRF_CPUSYNC   0x0004  /* cpusync is currently active */
 
-static __inline 
-void **
-FRAMEUP(void **frameptr)
-{
-    void **newframeptr;
+#ifdef _KERNEL
 
-    newframeptr = (void **)frameptr[0];
-    if (((uintptr_t)newframeptr ^ (uintptr_t)frameptr) & ~16383)
-       newframeptr = frameptr;
-    return(newframeptr);
-}
+#ifndef _MACHINE_PMAP_H_
+#include <machine/pmap.h>
+#endif
 
-void
-cpu_ktr_caller(struct ktr_entry *_ktr)
-{
-    struct ktr_entry *ktr;
-    void **frameptr;
+void pmap_inval_pte(volatile vpte_t *ptep, struct pmap *pmap, vm_offset_t va);
+void pmap_inval_pte_quick(volatile vpte_t *ptep, struct pmap *pmap, vm_offset_t va);
+void pmap_inval_pde(volatile vpte_t *ptep, struct pmap *pmap, vm_offset_t va);
+void pmap_inval_pde_quick(volatile vpte_t *ptep, struct pmap *pmap, vm_offset_t va);
+vpte_t pmap_clean_pte(volatile vpte_t *ptep, struct pmap *pmap, vm_offset_t va);
+vpte_t pmap_clean_pde(volatile vpte_t *ptep, struct pmap *pmap, vm_offset_t va);
+vpte_t pmap_setro_pte(volatile vpte_t *ptep, struct pmap *pmap, vm_offset_t va);
+vpte_t pmap_inval_loadandclear(volatile vpte_t *ptep, struct pmap *pmap, vm_offset_t va);
 
-    frameptr = (void **)&_ktr - 2;     /* frame, retpc to ktr_log */
-    ktr = _ktr;
-    frameptr = FRAMEUP(frameptr);      /* frame, retpc to traced function */
-    frameptr = FRAMEUP(frameptr);      /* frame, caller1 of traced function */
-    ktr->ktr_caller1 = frameptr[1];
-    frameptr = FRAMEUP(frameptr);      /* frame, caller2 of caller1 */
-    ktr->ktr_caller2 = frameptr[1];
-}
+#endif
 
+#endif
similarity index 56%
copy from sys/platform/pc64/x86_64/ktr.c
copy to sys/platform/vkernel64/include/proc.h
index a85a71c..34a3473 100644 (file)
@@ -1,13 +1,13 @@
 /*
- * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
- * 
+ * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
+ *
  * This code is derived from software contributed to The DragonFly Project
  * by Matthew Dillon <dillon@backplane.com>
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -17,7 +17,7 @@
  * 3. Neither the name of The DragonFly Project nor the names of its
  *    contributors may be used to endorse or promote products derived
  *    from this software without specific, prior written permission.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
+ *
+ * $DragonFly: src/sys/platform/vkernel/include/proc.h,v 1.1 2006/11/07 18:50:07 dillon Exp $
  */
-/*
- * Kernel tracepoint facility.
- */
-
-#include "opt_ddb.h"
-#include "opt_ktr.h"
 
-#include <sys/param.h>
-#include <sys/cons.h>
-#include <sys/kernel.h>
-#include <sys/libkern.h>
-#include <sys/proc.h>
-#include <sys/sysctl.h>
-#include <sys/ktr.h>
+#ifndef _MACHINE_PROC_H_
+#define        _MACHINE_PROC_H_
 
 /*
- * This routine fills in the ktr_caller1 and ktr_caller2 fields by
- * tracing back through the kernel stack to locate the stack frames
- * and return addresses.
- *
- *
- *     [first argument]
- *     [retpc]
- *     [frameptr]              -> points to caller's frame pointer
- * sp ->[junk]
+ * When a trap or exception occurs the trap code stores the frame pointer
+ * in md_regs so emulation and other code can modify it for the return.
  */
+struct trapframe;
 
-static __inline 
-void **
-FRAMEUP(void **frameptr)
-{
-    void **newframeptr;
-
-    newframeptr = (void **)frameptr[0];
-    if (((uintptr_t)newframeptr ^ (uintptr_t)frameptr) & ~16383)
-       newframeptr = frameptr;
-    return(newframeptr);
-}
-
-void
-cpu_ktr_caller(struct ktr_entry *_ktr)
-{
-    struct ktr_entry *ktr;
-    void **frameptr;
+struct mdproc {
+       struct trapframe *md_regs;      /* registers on current frame */
+};
 
-    frameptr = (void **)&_ktr - 2;     /* frame, retpc to ktr_log */
-    ktr = _ktr;
-    frameptr = FRAMEUP(frameptr);      /* frame, retpc to traced function */
-    frameptr = FRAMEUP(frameptr);      /* frame, caller1 of traced function */
-    ktr->ktr_caller1 = frameptr[1];
-    frameptr = FRAMEUP(frameptr);      /* frame, caller2 of caller1 */
-    ktr->ktr_caller2 = frameptr[1];
-}
+int grow_stack(struct proc *p, u_long sp); /* XXX swildner */
 
+#endif /* !_MACHINE_PROC_H_ */
similarity index 53%
copy from sys/cpu/x86_64/include/types.h
copy to sys/platform/vkernel64/include/ptrace.h
index bfb6c13..0467f85 100644 (file)
@@ -1,7 +1,6 @@
-/*-
- * Copyright (c) 1990, 1993
+/*
+ * Copyright (c) 1992, 1993
  *     The Regents of the University of California.  All rights reserved.
- * Copyright (c) 2008 The DragonFly Project.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)types.h     8.3 (Berkeley) 1/5/94
- * $FreeBSD: src/sys/i386/include/types.h,v 1.19.2.1 2001/03/21 10:50:58 peter Exp $
+ *     @(#)ptrace.h    8.1 (Berkeley) 6/11/93
+ * $FreeBSD: src/sys/i386/include/ptrace.h,v 1.9 1999/12/29 04:33:06 peter Exp $
+ * $DragonFly: src/sys/platform/vkernel/include/ptrace.h,v 1.1 2006/11/08 16:40:00 dillon Exp $
  */
 
-#ifndef _CPU_TYPES_H_
-#define        _CPU_TYPES_H_
-
-#if defined(__x86_64__)
-typedef        __int64_t       __segsz_t;      /* segment size */
-typedef        __int64_t       register_t;
-typedef        __uint64_t      u_register_t;
-#elif defined(__i386__)
-typedef        __int32_t       __segsz_t;      /* segment size */
-typedef        __int32_t       register_t;
-typedef        __uint32_t      u_register_t;
-#endif
-
-typedef unsigned long  vm_offset_t;    /* address space bounded offset */
-typedef unsigned long  vm_size_t;      /* address space bounded size */
-
-typedef __uint64_t     vm_pindex_t;    /* physical page index */
-typedef        __int64_t       vm_ooffset_t;   /* VM object bounded offset */
-typedef __uint64_t     vm_poff_t;      /* physical offset */
-typedef __uint64_t     vm_paddr_t;     /* physical addr (same as vm_poff_t) */
-
-#ifdef _KERNEL
-typedef        __int64_t       intfptr_t;
-typedef        __uint64_t      uintfptr_t;
-#endif
+#ifndef _MACHINE_PTRACE_H_
+#define _MACHINE_PTRACE_H_
 
 /*
- * MMU page tables
+ * Machine dependent trace commands.
  */
-#ifndef JG_defined_pml4_entry_t
-#define JG_defined_pml4_entry_t
-typedef __uint64_t     pml4_entry_t;
-typedef __uint64_t     pdp_entry_t;
-typedef __uint64_t     pd_entry_t;
-typedef __uint64_t     pt_entry_t;
-#endif
-typedef __uint32_t      cpumask_t;      /* mask representing a set of cpus */
-
-#define PML4SIZE       sizeof(pml4_entry_t) /* for assembly files */
-#define PDPSIZE                sizeof(pdp_entry_t) /* for assembly files */
-#define PDESIZE         sizeof(pd_entry_t) /* for assembly files */
-#define PTESIZE         sizeof(pt_entry_t) /* for assembly files */
-
-#endif /* !_CPU_TYPES_H_ */
+#define PT_GETREGS      (PT_FIRSTMACH + 1)
+#define PT_SETREGS      (PT_FIRSTMACH + 2)
+#define PT_GETFPREGS    (PT_FIRSTMACH + 3)
+#define PT_SETFPREGS    (PT_FIRSTMACH + 4)
+#define PT_GETDBREGS    (PT_FIRSTMACH + 5)
+#define PT_SETDBREGS    (PT_FIRSTMACH + 6)
 
+#endif
diff --git a/sys/platform/vkernel64/include/smp.h b/sys/platform/vkernel64/include/smp.h
new file mode 100644 (file)
index 0000000..b956d28
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ *
+ * $FreeBSD: src/sys/i386/include/smp.h,v 1.50.2.5 2001/02/13 22:32:45 tegge Exp $
+ * $DragonFly: src/sys/platform/vkernel/include/smp.h,v 1.3 2007/07/02 02:37:04 dillon Exp $
+ *
+ */
+
+#ifndef _MACHINE_SMP_H_
+#define _MACHINE_SMP_H_
+
+#ifdef _KERNEL
+
+#if defined(SMP)
+
+#ifndef LOCORE
+
+#if 0
+
+/*
+ * For sending values to POST displays.
+ * XXX FIXME: where does this really belong, isa.h/isa.c perhaps?
+ */
+extern int current_postcode;  /** XXX currently in mp_machdep.c */
+#define POSTCODE(X)    current_postcode = (X), \
+                       outb(0x80, current_postcode)
+#define POSTCODE_LO(X) current_postcode &= 0xf0, \
+                       current_postcode |= ((X) & 0x0f), \
+                       outb(0x80, current_postcode)
+#define POSTCODE_HI(X) current_postcode &= 0x0f, \
+                       current_postcode |= (((X) << 4) & 0xf0), \
+                       outb(0x80, current_postcode)
+
+
+#include <machine_base/apic/apicreg.h>
+#include <machine/pcb.h>
+
+/* global data in mpboot.s */
+extern int                     bootMP_size;
+
+/* functions in mpboot.s */
+void   bootMP                  (void);
+
+#endif
+
+/* global data in apic_vector.s */
+extern volatile u_int          stopped_cpus;
+extern int                     optcpus;        /* from main() */
+
+#if 0
+extern volatile u_int          started_cpus;
+
+extern volatile u_int          checkstate_probed_cpus;
+extern void (*cpustop_restartfunc) (void);
+
+/* functions in apic_ipl.s */
+void   apic_eoi                (void);
+u_int  io_apic_read            (int, int);
+void   io_apic_write           (int, int, u_int);
+
+#endif
+
+#if 0
+/* global data in mp_machdep.c */
+extern int                     bsp_apic_ready;
+extern int                     mp_naps;
+extern int                     mp_nbusses;
+extern int                     mp_napics;
+extern int                     boot_cpu_id;
+extern vm_offset_t             cpu_apic_address;
+extern vm_offset_t             io_apic_address[];
+extern u_int32_t               cpu_apic_versions[];
+extern u_int32_t               *io_apic_versions;
+extern int                     cpu_num_to_apic_id[];
+extern int                     io_num_to_apic_id[];
+extern int                     apic_id_to_logical[];
+#endif
+
+#if 0
+#define APIC_INTMAPSIZE 24
+struct apic_intmapinfo {
+       int ioapic;
+       int int_pin;
+       volatile void *apic_address;
+       int redirindex;
+};
+extern struct apic_intmapinfo  int_to_apicintpin[];
+extern struct pcb              stoppcbs[];
+
+#endif
+
+#if 0
+/* functions in mp_machdep.c */
+void   *permanent_io_mapping(vm_paddr_t);
+u_int  mp_bootaddress          (u_int);
+int    mp_probe                (void);
+#endif
+void   mp_start                (void);
+void   mp_announce             (void);
+#if 0
+u_int  isa_apic_mask           (u_int);
+int    isa_apic_irq            (int);
+int    pci_apic_irq            (int, int, int);
+int    apic_irq                (int, int);
+int    next_apic_irq           (int);
+int    undirect_isa_irq        (int);
+int    undirect_pci_irq        (int);
+int    apic_bus_type           (int);
+int    apic_src_bus_id         (int, int);
+int    apic_src_bus_irq        (int, int);
+int    apic_int_type           (int, int);
+int    apic_trigger            (int, int);
+int    apic_polarity           (int, int);
+void   assign_apic_irq         (int apic, int intpin, int irq);
+void   revoke_apic_irq         (int irq);
+void   init_secondary          (void);
+#endif
+int    stop_cpus               (u_int);
+void   ap_init                 (void);
+int    restart_cpus            (u_int);
+#if 0
+void   forward_signal          (struct proc *);
+
+#endif
+
+#if 0
+/* global data in mpapic.c */
+extern volatile lapic_t                lapic;
+extern volatile ioapic_t       **ioapic;
+#endif
+
+/* functions in mpapic.c */
+#if 0
+void   apic_dump               (char*);
+void   apic_initialize         (void);
+void   imen_dump               (void);
+int    apic_ipi                (int, int, int);
+void   selected_apic_ipi       (u_int, int, int);
+void   single_apic_ipi(int cpu, int vector, int delivery_mode);
+int    single_apic_ipi_passive(int cpu, int vector, int delivery_mode);
+int    io_apic_setup           (int);
+void   io_apic_setup_intpin    (int, int);
+void   io_apic_set_id          (int, int);
+int    io_apic_get_id          (int);
+int    ext_int_setup           (int, int);
+#endif
+
+#if 0
+void   clr_io_apic_mask24      (int, u_int32_t);
+void   set_io_apic_mask24      (int, u_int32_t);
+#endif
+
+#if 0
+void   set_apic_timer          (int);
+int    read_apic_timer         (void);
+void   u_sleep                 (int);
+#endif
+void   cpu_send_ipiq           (int);
+int    cpu_send_ipiq_passive   (int);
+
+/* global data in init_smp.c */
+extern cpumask_t               smp_active_mask;
+
+#endif /* !LOCORE */
+#else  /* !SMP */
+
+#define        smp_active_mask 1       /* smp_active_mask always 1 on UP machines */
+
+#endif
+
+#endif /* _KERNEL */
+#endif /* _MACHINE_SMP_H_ */
diff --git a/sys/platform/vkernel64/include/thread.h b/sys/platform/vkernel64/include/thread.h
new file mode 100644 (file)
index 0000000..90ed090
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon@backplane.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $DragonFly: src/sys/platform/vkernel/include/thread.h,v 1.2 2007/01/08 03:33:43 dillon Exp $
+ */
+
+#ifndef        _MACHINE_THREAD_H_
+#define        _MACHINE_THREAD_H_
+
+#ifndef _MACHINE_VFRAME_H_
+#include <machine/vframe.h>
+#endif
+#ifndef _MACHINE_NPX_H_
+#include <machine/npx.h>
+#endif
+
+struct md_thread {
+    unsigned int       mtd_unused;     /* used to be mtd_cpl */
+    union savefpu      *mtd_savefpu;   /* pointer to current fpu context */
+    struct vextframe   mtd_savevext;
+};
+
+#ifdef _KERNEL
+
+#define td_savefpu     td_mach.mtd_savefpu
+#define td_tls         td_mach.mtd_savevext.vx_tls
+#define td_savevext    td_mach.mtd_savevext
+
+/*
+ * mycpu() retrieves the base of the current cpu's globaldata structure.
+ * Note that it is *NOT* volatile, meaning that the value may be cached by
+ * GCC.  We have to force a dummy memory reference so gcc does not cache
+ * the gd pointer across a procedure call (which might block and cause us
+ * to wakeup on a different cpu).
+ *
+ * Also note that in DragonFly a thread can be preempted, but only by an
+ * interrupt thread and the original thread will resume after the
+ * interrupt thread finishes or blocks.  A thread cannot move to another
+ * cpu preemptively or at all, in fact, while you are in the kernel, even
+ * if you block.
+ */
+
+struct globaldata;
+
+extern int __mycpu__dummy;
+
+static __inline
+struct globaldata *
+_get_mycpu(void)
+{
+    struct globaldata *gd;
+
+    __asm ("movq %%gs:globaldata,%0" : "=r" (gd) : "m"(__mycpu__dummy));
+    return(gd);
+}
+
+#define mycpu          _get_mycpu()
+
+#ifdef SMP
+#define        mycpuid (_get_mycpu()->gd_cpuid)
+#else
+#define        mycpuid 0
+#endif
+
+/*
+ * note: curthread is never NULL, but curproc can be.  Also note that
+ * that only processes really use the PCB.  Threads fill in some fields
+ * but mostly store contextual data on the stack and do not use (much of)
+ * the PCB.
+ */
+#define curthread      mycpu->gd_curthread
+#define        curproc         curthread->td_proc
+
+#endif /* _KERNEL */
+
+#endif /* !_MACHINE_THREAD_H_ */
similarity index 56%
copy from sys/platform/pc64/x86_64/in_cksum2.s
copy to sys/platform/vkernel64/include/types.h
index bf249cc..d76854f 100644 (file)
@@ -1,13 +1,13 @@
 /*
- * Copyright (c) 2003,2004,2008 The DragonFly Project.  All rights reserved.
- * 
+ * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
+ *
  * This code is derived from software contributed to The DragonFly Project
  * by Matthew Dillon <dillon@backplane.com>
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -17,7 +17,7 @@
  * 3. Neither the name of The DragonFly Project nor the names of its
  *    contributors may be used to endorse or promote products derived
  *    from this software without specific, prior written permission.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  * 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_TYPES_H_
+#define        _MACHINE_TYPES_H_
 
-#include <machine/asmacros.h>          /* miscellaneous asm macros */
+#include <cpu/types.h>
 
-#include "assym.s"
+typedef __uint32_t     intrmask_t;
 
-       .text
-
-       /*
-        * asm_ones32(32bitalignedbuffer, numberof32bitwords)
-        *
-        * Returns the 32 bit one complement partial checksum.  This is 
-        * basically a 1's complement checksum without the inversion (~)
-        * at the end.  A 32 bit value is returned.  If the caller is 
-        * calculating a 16 bit 1's complement checksum the caller must
-        * collapse the 32 bit return value via:
-        *
-        *      result = (result >> 16) + (result & 0xFFFF)
-        *      if (result > 0xFFFF)
-        *          result -= 0xFFFF;   <<< same as (result + 1) & 0xFFFF
-        *                                  within the range of result.
-        * Note that worst case 0xFFFFFFFF + 0xFFFFFFFF = 0xFFFFFFFE + CARRY,
-        * so no double-carry ever occurs.
-        */
-       .p2align 4
-ENTRY(asm_ones32)
-       movq    %rdi,%rdx       /* %rdx = buffer pointer */
-       movl    %esi,%ecx       /* %ecx = counter */
-       xorl    %eax,%eax       /* %eax = checksum */
-       cmpl    $5,%ecx
-       jl      2f
-1:
-       subl    $5,%ecx
-       addl    (%rdx),%eax
-       adcl    4(%rdx),%eax
-       adcl    8(%rdx),%eax
-       adcl    12(%rdx),%eax
-       adcl    16(%rdx),%eax
-       adcl    $0,%eax
-       addq    $20,%rdx
-       cmpl    $5,%ecx
-       jge     1b
-2:
-       testl   %ecx,%ecx
-       je      4f
-3:
-       addl    (%rdx),%eax
-       adcl    $0,%eax
-       addq    $4,%rdx
-       decl    %ecx
-       jnz     3b
-4:
-       ret
+#endif /* !_MACHINE_TYPES_H_ */
diff --git a/sys/platform/vkernel64/include/vmparam.h b/sys/platform/vkernel64/include/vmparam.h
new file mode 100644 (file)
index 0000000..112f732
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon@backplane.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $DragonFly: src/sys/platform/vkernel/include/vmparam.h,v 1.5 2007/01/14 00:01:07 dillon Exp $
+ */
+
+#ifndef _MACHINE_VMPARAM_H_
+#define _MACHINE_VMPARAM_H_
+
+/*
+ * Indicate that read access also means execution access (XXX newer PCs
+ * have a separate bit).
+ */
+#define VM_PROT_READ_IS_EXEC
+
+/*
+ * Virtual memory related constants, all in bytes
+ */
+#define        MAXTSIZ         (128UL*1024*1024)       /* max text size */
+#ifndef DFLDSIZ
+#define        DFLDSIZ         (128UL*1024*1024)       /* initial data size limit */
+#endif
+#ifndef MAXDSIZ
+#define        MAXDSIZ         (32768UL*1024*1024)     /* max data size */
+#endif
+#ifndef        DFLSSIZ
+#define        DFLSSIZ         (8UL*1024*1024)         /* initial stack size limit */
+#endif
+#ifndef        MAXSSIZ
+#define        MAXSSIZ         (512UL*1024*1024)       /* max stack size */
+#endif
+#ifndef SGROWSIZ
+#define        SGROWSIZ        (128UL*1024)            /* amount to grow stack */
+#endif
+
+/*
+ * After this period of time allow a process to become swappable.  This
+ * parameter is mostly obsolete now.
+ */
+#define        MAXSLP          20
+
+/*
+ * For virtual kernels running as userland processes the user and kernel
+ * address spaces exist in different VM spaces and can overlap.
+ */
+#define KERNEL_KVA_SIZE                (2UL * 1024 * 1024 * 1024)
+
+#define VM_MIN_USER_ADDRESS    ((vm_offset_t)0)
+#define VM_MAX_USER_ADDRESS    UVADDR(NUPML4E, 0, 0, 0)
+
+#define DMAP_SIZE              (512UL * 1024 * 1024 * 1024)
+
+#define KERNBASE               0xC0000000      /* XXX totally wrong */
+
+#define USRSTACK               VM_MAX_USER_ADDRESS
+
+extern void *dmap_min_address;
+#define        PHYS_TO_DMAP(x)         ((uint64_t)(x) + (uint64_t)dmap_min_address)
+#define        DMAP_TO_PHYS(x)         ((uint64_t)(x) - (uint64_t)dmap_min_address)
+
+/*
+ * Initial memory map preload
+ */
+#ifndef VM_INITIAL_PAGEIN
+#define        VM_INITIAL_PAGEIN       16
+#endif
+
+#endif /* _MACHINE_VMPARAM_H_ */
diff --git a/sys/platform/vkernel64/platform/busdma_machdep.c b/sys/platform/vkernel64/platform/busdma_machdep.c
new file mode 100644 (file)
index 0000000..986ba9a
--- /dev/null
@@ -0,0 +1,1287 @@
+/*
+ * Copyright (c) 1997, 1998 Justin T. Gibbs.
+ * 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,
+ *    without modification, immediately at the beginning of the file.
+ * 2. 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 AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/i386/i386/busdma_machdep.c,v 1.94 2008/08/15 20:51:31 kmacy Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/busdma_machdep.c,v 1.23 2008/06/05 18:06:32 swildner Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/uio.h>
+#include <sys/thread2.h>
+#include <sys/bus_dma.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/lock.h>
+#include <sys/spinlock2.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+
+/* XXX needed for to access pmap to convert per-proc virtual to physical */
+#include <sys/proc.h>
+#include <sys/lock.h>
+#include <vm/vm_map.h>
+
+#include <machine/md_var.h>
+
+#define MAX_BPAGES     1024
+
+struct bounce_zone;
+struct bus_dmamap;
+
+struct bus_dma_tag {
+       bus_dma_tag_t   parent;
+       bus_size_t      alignment;
+       bus_size_t      boundary;
+       bus_addr_t      lowaddr;
+       bus_addr_t      highaddr;
+       bus_dma_filter_t *filter;
+       void            *filterarg;
+       bus_size_t      maxsize;
+       u_int           nsegments;
+       bus_size_t      maxsegsz;
+       int             flags;
+       int             ref_count;
+       int             map_count;
+       bus_dma_segment_t *segments;
+       struct bounce_zone *bounce_zone;
+};
+
+/*
+ * bus_dma_tag private flags
+ */
+#define BUS_DMA_BOUNCE_ALIGN   BUS_DMA_BUS2
+#define BUS_DMA_BOUNCE_LOWADDR BUS_DMA_BUS3
+#define BUS_DMA_MIN_ALLOC_COMP BUS_DMA_BUS4
+
+#define BUS_DMA_COULD_BOUNCE   (BUS_DMA_BOUNCE_LOWADDR | BUS_DMA_BOUNCE_ALIGN)
+
+#define BUS_DMAMEM_KMALLOC(dmat) \
+       ((dmat)->maxsize <= PAGE_SIZE && \
+        (dmat)->alignment <= PAGE_SIZE && \
+        (dmat)->lowaddr >= ptoa(Maxmem))
+
+struct bounce_page {
+       vm_offset_t     vaddr;          /* kva of bounce buffer */
+       bus_addr_t      busaddr;        /* Physical address */
+       vm_offset_t     datavaddr;      /* kva of client data */
+       bus_size_t      datacount;      /* client data count */
+       STAILQ_ENTRY(bounce_page) links;
+};
+
+struct bounce_zone {
+       STAILQ_ENTRY(bounce_zone) links;
+       STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
+       STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist;
+#ifdef SMP
+       struct spinlock spin;
+#else
+       int             unused0;
+#endif
+       int             total_bpages;
+       int             free_bpages;
+       int             reserved_bpages;
+       int             active_bpages;
+       int             total_bounced;
+       int             total_deferred;
+       int             reserve_failed;
+       bus_size_t      alignment;
+       bus_addr_t      lowaddr;
+       char            zoneid[8];
+       char            lowaddrid[20];
+       struct sysctl_ctx_list sysctl_ctx;
+       struct sysctl_oid *sysctl_tree;
+};
+
+#ifdef SMP
+#define BZ_LOCK(bz)    spin_lock_wr(&(bz)->spin)
+#define BZ_UNLOCK(bz)  spin_unlock_wr(&(bz)->spin)
+#else
+#define BZ_LOCK(bz)    crit_enter()
+#define BZ_UNLOCK(bz)  crit_exit()
+#endif
+
+static struct lwkt_token bounce_zone_tok =
+       LWKT_TOKEN_INITIALIZER(bounce_zone_tok);
+static int busdma_zonecount;
+static STAILQ_HEAD(, bounce_zone) bounce_zone_list =
+       STAILQ_HEAD_INITIALIZER(bounce_zone_list);
+
+int busdma_swi_pending;
+static int total_bounce_pages;
+static int max_bounce_pages = MAX_BPAGES;
+static int bounce_alignment = 1; /* XXX temporary */
+
+TUNABLE_INT("hw.busdma.max_bpages", &max_bounce_pages);
+TUNABLE_INT("hw.busdma.bounce_alignment", &bounce_alignment);
+
+struct bus_dmamap {
+       struct bp_list  bpages;
+       int             pagesneeded;
+       int             pagesreserved;
+       bus_dma_tag_t   dmat;
+       void            *buf;           /* unmapped buffer pointer */
+       bus_size_t      buflen;         /* unmapped buffer length */
+       bus_dmamap_callback_t *callback;
+       void            *callback_arg;
+       STAILQ_ENTRY(bus_dmamap) links;
+};
+
+static STAILQ_HEAD(, bus_dmamap) bounce_map_callbacklist =
+       STAILQ_HEAD_INITIALIZER(bounce_map_callbacklist);
+
+static struct bus_dmamap nobounce_dmamap;
+
+static int             alloc_bounce_zone(bus_dma_tag_t);
+static int             alloc_bounce_pages(bus_dma_tag_t, u_int, int);
+static int             reserve_bounce_pages(bus_dma_tag_t, bus_dmamap_t, int);
+static void            return_bounce_pages(bus_dma_tag_t, bus_dmamap_t);
+static bus_addr_t      add_bounce_page(bus_dma_tag_t, bus_dmamap_t,
+                           vm_offset_t, bus_size_t);
+static void            free_bounce_page(bus_dma_tag_t, struct bounce_page *);
+
+static bus_dmamap_t    get_map_waiting(bus_dma_tag_t);
+static void            add_map_callback(bus_dmamap_t);
+
+SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD, 0, "Busdma parameters");
+SYSCTL_INT(_hw_busdma, OID_AUTO, total_bpages, CTLFLAG_RD, &total_bounce_pages,
+          0, "Total bounce pages");
+SYSCTL_INT(_hw_busdma, OID_AUTO, max_bpages, CTLFLAG_RD, &max_bounce_pages,
+          0, "Max bounce pages per bounce zone");
+SYSCTL_INT(_hw_busdma, OID_AUTO, bounce_alignment, CTLFLAG_RD,
+          &bounce_alignment, 0, "Obey alignment constraint");
+
+static __inline int
+run_filter(bus_dma_tag_t dmat, bus_addr_t paddr)
+{
+       int retval;
+
+       retval = 0;
+       do {
+               if (((paddr > dmat->lowaddr && paddr <= dmat->highaddr) ||
+                    (bounce_alignment && (paddr & (dmat->alignment - 1)) != 0))
+                && (dmat->filter == NULL ||
+                    dmat->filter(dmat->filterarg, paddr) != 0))
+                       retval = 1;
+
+               dmat = dmat->parent;
+       } while (retval == 0 && dmat != NULL);
+       return (retval);
+}
+
+/*
+ * Allocate a device specific dma_tag.
+ */
+int
+bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
+                  bus_size_t boundary, bus_addr_t lowaddr,
+                  bus_addr_t highaddr, bus_dma_filter_t *filter,
+                  void *filterarg, bus_size_t maxsize, int nsegments,
+                  bus_size_t maxsegsz, int flags, bus_dma_tag_t *dmat)
+{
+       bus_dma_tag_t newtag;
+       int error = 0;
+
+       /*
+        * Sanity checks
+        */
+
+       if (alignment == 0)
+               alignment = 1;
+       if (alignment & (alignment - 1))
+               panic("alignment must be power of 2\n");
+
+       if (boundary != 0) {
+               if (boundary & (boundary - 1))
+                       panic("boundary must be power of 2\n");
+               if (boundary < maxsegsz) {
+                       kprintf("boundary < maxsegsz:\n");
+                       print_backtrace();
+                       maxsegsz = boundary;
+               }
+       }
+
+       /* Return a NULL tag on failure */
+       *dmat = NULL;
+
+       newtag = kmalloc(sizeof(*newtag), M_DEVBUF, M_INTWAIT);
+
+       newtag->parent = parent;
+       newtag->alignment = alignment;
+       newtag->boundary = boundary;
+       newtag->lowaddr = trunc_page((vm_paddr_t)lowaddr) + (PAGE_SIZE - 1);
+       newtag->highaddr = trunc_page((vm_paddr_t)highaddr) + (PAGE_SIZE - 1);
+       newtag->filter = filter;
+       newtag->filterarg = filterarg;
+       newtag->maxsize = maxsize;
+       newtag->nsegments = nsegments;
+       newtag->maxsegsz = maxsegsz;
+       newtag->flags = flags;
+       newtag->ref_count = 1; /* Count ourself */
+       newtag->map_count = 0;
+       newtag->segments = NULL;
+       newtag->bounce_zone = NULL;
+
+       /* Take into account any restrictions imposed by our parent tag */
+       if (parent != NULL) {
+               newtag->lowaddr = MIN(parent->lowaddr, newtag->lowaddr);
+               newtag->highaddr = MAX(parent->highaddr, newtag->highaddr);
+
+               if (newtag->boundary == 0) {
+                       newtag->boundary = parent->boundary;
+               } else if (parent->boundary != 0) {
+                       newtag->boundary = MIN(parent->boundary,
+                                              newtag->boundary);
+               }
+
+#ifdef notyet
+               newtag->alignment = MAX(parent->alignment, newtag->alignment);
+#endif
+
+               if (newtag->filter == NULL) {
+                       /*
+                        * Short circuit looking at our parent directly
+                        * since we have encapsulated all of its information
+                        */
+                       newtag->filter = parent->filter;
+                       newtag->filterarg = parent->filterarg;
+                       newtag->parent = parent->parent;
+               }
+               if (newtag->parent != NULL)
+                       parent->ref_count++;
+       }
+
+       if (newtag->lowaddr < ptoa(Maxmem))
+               newtag->flags |= BUS_DMA_BOUNCE_LOWADDR;
+       if (bounce_alignment && newtag->alignment > 1 &&
+           !(newtag->flags & BUS_DMA_ALIGNED))
+               newtag->flags |= BUS_DMA_BOUNCE_ALIGN;
+
+       if ((newtag->flags & BUS_DMA_COULD_BOUNCE) &&
+           (flags & BUS_DMA_ALLOCNOW) != 0) {
+               struct bounce_zone *bz;
+
+               /* Must bounce */
+
+               error = alloc_bounce_zone(newtag);
+               if (error)
+                       goto back;
+               bz = newtag->bounce_zone;
+
+               if (ptoa(bz->total_bpages) < maxsize) {
+                       int pages;
+
+                       if (flags & BUS_DMA_ONEBPAGE) {
+                               pages = 1;
+                       } else {
+                               pages = atop(round_page(maxsize)) -
+                                       bz->total_bpages;
+                               pages = MAX(pages, 1);
+                       }
+
+                       /* Add pages to our bounce pool */
+                       if (alloc_bounce_pages(newtag, pages, flags) < pages)
+                               error = ENOMEM;
+
+                       /* Performed initial allocation */
+                       newtag->flags |= BUS_DMA_MIN_ALLOC_COMP;
+               }
+       }
+back:
+       if (error)
+               kfree(newtag, M_DEVBUF);
+       else
+               *dmat = newtag;
+       return error;
+}
+
+int
+bus_dma_tag_destroy(bus_dma_tag_t dmat)
+{
+       if (dmat != NULL) {
+               if (dmat->map_count != 0)
+                       return (EBUSY);
+
+               while (dmat != NULL) {
+                       bus_dma_tag_t parent;
+
+                       parent = dmat->parent;
+                       dmat->ref_count--;
+                       if (dmat->ref_count == 0) {
+                               if (dmat->segments != NULL)
+                                       kfree(dmat->segments, M_DEVBUF);
+                               kfree(dmat, M_DEVBUF);
+                               /*
+                                * Last reference count, so
+                                * release our reference
+                                * count on our parent.
+                                */
+                               dmat = parent;
+                       } else
+                               dmat = NULL;
+               }
+       }
+       return (0);
+}
+
+/*
+ * Allocate a handle for mapping from kva/uva/physical
+ * address space into bus device space.
+ */
+int
+bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)
+{
+       int error;
+
+       error = 0;
+
+       if (dmat->segments == NULL) {
+               KKASSERT(dmat->nsegments && dmat->nsegments < 16384);
+               dmat->segments = kmalloc(sizeof(bus_dma_segment_t) *
+                                       dmat->nsegments, M_DEVBUF, M_INTWAIT);
+       }
+
+       if (dmat->flags & BUS_DMA_COULD_BOUNCE) {
+               struct bounce_zone *bz;
+               int maxpages;
+
+               /* Must bounce */
+
+               if (dmat->bounce_zone == NULL) {
+                       error = alloc_bounce_zone(dmat);
+                       if (error)
+                               return error;
+               }
+               bz = dmat->bounce_zone;
+
+               *mapp = kmalloc(sizeof(**mapp), M_DEVBUF, M_INTWAIT | M_ZERO);
+
+               /* Initialize the new map */
+               STAILQ_INIT(&((*mapp)->bpages));
+
+               /*
+                * Attempt to add pages to our pool on a per-instance
+                * basis up to a sane limit.
+                */
+               if (dmat->flags & BUS_DMA_BOUNCE_ALIGN) {
+                       maxpages = max_bounce_pages;
+               } else {
+                       maxpages = MIN(max_bounce_pages,
+                                      Maxmem - atop(dmat->lowaddr));
+               }
+               if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0
+                || (dmat->map_count > 0
+                 && bz->total_bpages < maxpages)) {
+                       int pages;
+
+                       if (flags & BUS_DMA_ONEBPAGE) {
+                               pages = 1;
+                       } else {
+                               pages = atop(round_page(dmat->maxsize));
+                               pages = MIN(maxpages - bz->total_bpages, pages);
+                               pages = MAX(pages, 1);
+                       }
+                       if (alloc_bounce_pages(dmat, pages, flags) < pages)
+                               error = ENOMEM;
+
+                       if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0) {
+                               if (!error)
+                                       dmat->flags |= BUS_DMA_MIN_ALLOC_COMP;
+                       } else {
+                               error = 0;
+                       }
+               }
+       } else {
+               *mapp = NULL;
+       }
+       if (!error)
+               dmat->map_count++;
+       return error;
+}
+
+/*
+ * Destroy a handle for mapping from kva/uva/physical
+ * address space into bus device space.
+ */
+int
+bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)
+{
+       if (map != NULL) {
+               if (STAILQ_FIRST(&map->bpages) != NULL)
+                       return (EBUSY);
+               kfree(map, M_DEVBUF);
+       }
+       dmat->map_count--;
+       return (0);
+}
+
+static __inline bus_size_t
+check_kmalloc(bus_dma_tag_t dmat, const void *vaddr0, int verify)
+{
+       bus_size_t maxsize = 0;
+       uintptr_t vaddr = (uintptr_t)vaddr0;
+
+       if ((vaddr ^ (vaddr + dmat->maxsize - 1)) & ~PAGE_MASK) {
+               kprintf("boundary check failed\n");
+               if (verify)
+                       print_backtrace(); /* XXX panic */
+               maxsize = dmat->maxsize;
+       }
+       if (vaddr & (dmat->alignment - 1)) {
+               kprintf("alignment check failed\n");
+               if (verify)
+                       print_backtrace(); /* XXX panic */
+               if (dmat->maxsize < dmat->alignment)
+                       maxsize = dmat->alignment;
+               else
+                       maxsize = dmat->maxsize;
+       }
+       return maxsize;
+}
+
+/*
+ * Allocate a piece of memory that can be efficiently mapped into
+ * bus device space based on the constraints lited in the dma tag.
+ *
+ * mapp is degenerate.  By definition this allocation should not require
+ * bounce buffers so do not allocate a dma map.
+ */
+int
+bus_dmamem_alloc(bus_dma_tag_t dmat, void **vaddr, int flags,
+                bus_dmamap_t *mapp)
+{
+       int mflags;
+
+       /* If we succeed, no mapping/bouncing will be required */
+       *mapp = NULL;
+
+       if (dmat->segments == NULL) {
+               KKASSERT(dmat->nsegments < 16384);
+               dmat->segments = kmalloc(sizeof(bus_dma_segment_t) *
+                                       dmat->nsegments, M_DEVBUF, M_INTWAIT);
+       }
+
+       if (flags & BUS_DMA_NOWAIT)
+               mflags = M_NOWAIT;
+       else
+               mflags = M_WAITOK;
+       if (flags & BUS_DMA_ZERO)
+               mflags |= M_ZERO;
+
+       if (BUS_DMAMEM_KMALLOC(dmat)) {
+               bus_size_t maxsize;
+
+               *vaddr = kmalloc(dmat->maxsize, M_DEVBUF, mflags);
+
+               /*
+                * XXX
+                * Check whether the allocation
+                * - crossed a page boundary
+                * - was not aligned
+                * Retry with power-of-2 alignment in the above cases.
+                */
+               maxsize = check_kmalloc(dmat, *vaddr, 0);
+               if (maxsize) {
+                       size_t size;
+
+                       kfree(*vaddr, M_DEVBUF);
+                       /* XXX check for overflow? */
+                       for (size = 1; size <= maxsize; size <<= 1)
+                               ;
+                       *vaddr = kmalloc(size, M_DEVBUF, mflags);
+                       check_kmalloc(dmat, *vaddr, 1);
+               }
+       } else {
+               /*
+                * XXX Use Contigmalloc until it is merged into this facility
+                *     and handles multi-seg allocations.  Nobody is doing
+                *     multi-seg allocations yet though.
+                */
+               *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags,
+                   0ul, dmat->lowaddr, dmat->alignment, dmat->boundary);
+       }
+       if (*vaddr == NULL)
+               return (ENOMEM);
+       return (0);
+}
+
+/*
+ * Free a piece of memory and it's allociated dmamap, that was allocated
+ * via bus_dmamem_alloc.  Make the same choice for free/contigfree.
+ */
+void
+bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)
+{
+       /*
+        * dmamem does not need to be bounced, so the map should be
+        * NULL
+        */
+       if (map != NULL)
+               panic("bus_dmamem_free: Invalid map freed\n");
+       if (BUS_DMAMEM_KMALLOC(dmat))
+               kfree(vaddr, M_DEVBUF);
+       else
+               contigfree(vaddr, dmat->maxsize, M_DEVBUF);
+}
+
+static __inline vm_paddr_t
+_bus_dma_extract(pmap_t pmap, vm_offset_t vaddr)
+{
+       if (pmap)
+               return pmap_extract(pmap, vaddr);
+       else
+               return pmap_kextract(vaddr);
+}
+
+/*
+ * Utility function to load a linear buffer.  lastaddrp holds state
+ * between invocations (for multiple-buffer loads).  segp contains
+ * the segment following the starting one on entrace, and the ending
+ * segment on exit.  first indicates if this is the first invocation
+ * of this function.
+ */
+static int
+_bus_dmamap_load_buffer(bus_dma_tag_t dmat,
+                       bus_dmamap_t map,
+                       void *buf, bus_size_t buflen,
+                       bus_dma_segment_t *segments,
+                       int nsegments,
+                       pmap_t pmap,
+                       int flags,
+                       vm_paddr_t *lastpaddrp,
+                       int *segp,
+                       int first)
+{
+       vm_offset_t vaddr;
+       vm_paddr_t paddr, nextpaddr;
+       bus_dma_segment_t *sg;
+       bus_addr_t bmask;
+       int seg, error = 0;
+
+       if (map == NULL)
+               map = &nobounce_dmamap;
+
+#ifdef INVARIANTS
+       if (dmat->flags & BUS_DMA_ALIGNED)
+               KKASSERT(((uintptr_t)buf & (dmat->alignment - 1)) == 0);
+#endif
+
+       /*
+        * If we are being called during a callback, pagesneeded will
+        * be non-zero, so we can avoid doing the work twice.
+        */
+       if ((dmat->flags & BUS_DMA_COULD_BOUNCE) &&
+           map != &nobounce_dmamap && map->pagesneeded == 0) {
+               vm_offset_t vendaddr;
+
+               /*
+                * Count the number of bounce pages
+                * needed in order to complete this transfer
+                */
+               vaddr = (vm_offset_t)buf;
+               vendaddr = (vm_offset_t)buf + buflen;
+
+               while (vaddr < vendaddr) {
+                       paddr = _bus_dma_extract(pmap, vaddr);
+                       if (run_filter(dmat, paddr) != 0)
+                               map->pagesneeded++;
+                       vaddr += (PAGE_SIZE - ((vm_offset_t)vaddr & PAGE_MASK));
+               }
+       }
+
+       /* Reserve Necessary Bounce Pages */
+       if (map->pagesneeded != 0) {
+               struct bounce_zone *bz;
+
+               bz = dmat->bounce_zone;
+               BZ_LOCK(bz);
+               if (flags & BUS_DMA_NOWAIT) {
+                       if (reserve_bounce_pages(dmat, map, 0) != 0) {
+                               BZ_UNLOCK(bz);
+                               error = ENOMEM;
+                               goto free_bounce;
+                       }
+               } else {
+                       if (reserve_bounce_pages(dmat, map, 1) != 0) {
+                               /* Queue us for resources */
+                               map->dmat = dmat;
+                               map->buf = buf;
+                               map->buflen = buflen;
+
+                               STAILQ_INSERT_TAIL(
+                                   &dmat->bounce_zone->bounce_map_waitinglist,
+                                   map, links);
+                               BZ_UNLOCK(bz);
+
+                               return (EINPROGRESS);
+                       }
+               }
+               BZ_UNLOCK(bz);
+       }
+
+       KKASSERT(*segp >= 1 && *segp <= nsegments);
+       seg = *segp;
+       sg = &segments[seg - 1];
+
+       vaddr = (vm_offset_t)buf;
+       nextpaddr = *lastpaddrp;
+       bmask = ~(dmat->boundary - 1);  /* note: will be 0 if boundary is 0 */
+
+       /* force at least one segment */
+       do {
+               bus_size_t size;
+
+               /*
+                * Per-page main loop
+                */
+               paddr = _bus_dma_extract(pmap, vaddr);
+               size = PAGE_SIZE - (paddr & PAGE_MASK);
+               if (size > buflen)
+                       size = buflen;
+               if (map->pagesneeded != 0 && run_filter(dmat, paddr)) {
+                       /*
+                        * note: this paddr has the same in-page offset
+                        * as vaddr and thus the paddr above, so the
+                        * size does not have to be recalculated
+                        */
+                       paddr = add_bounce_page(dmat, map, vaddr, size);
+               }
+
+               /*
+                * Fill in the bus_dma_segment
+                */
+               if (first) {
+                       sg->ds_addr = paddr;
+                       sg->ds_len = size;
+                       first = 0;
+               } else if (paddr == nextpaddr) {
+                       sg->ds_len += size;
+               } else {
+                       sg++;
+                       seg++;
+                       if (seg > nsegments)
+                               break;
+                       sg->ds_addr = paddr;
+                       sg->ds_len = size;
+               }
+               nextpaddr = paddr + size;
+
+               /*
+                * Handle maxsegsz and boundary issues with a nested loop
+                */
+               for (;;) {
+                       bus_size_t tmpsize;
+
+                       /*
+                        * Limit to the boundary and maximum segment size
+                        */
+                       if (((nextpaddr - 1) ^ sg->ds_addr) & bmask) {
+                               tmpsize = dmat->boundary -
+                                         (sg->ds_addr & ~bmask);
+                               if (tmpsize > dmat->maxsegsz)
+                                       tmpsize = dmat->maxsegsz;
+                               KKASSERT(tmpsize < sg->ds_len);
+                       } else if (sg->ds_len > dmat->maxsegsz) {
+                               tmpsize = dmat->maxsegsz;
+                       } else {
+                               break;
+                       }
+
+                       /*
+                        * Futz, split the data into a new segment.
+                        */
+                       if (seg >= nsegments)
+                               goto fail;
+                       sg[1].ds_len = sg[0].ds_len - tmpsize;
+                       sg[1].ds_addr = sg[0].ds_addr + tmpsize;
+                       sg[0].ds_len = tmpsize;
+                       sg++;
+                       seg++;
+               }
+
+               /*
+                * Adjust for loop
+                */
+               buflen -= size;
+               vaddr += size;
+       } while (buflen > 0);
+fail:
+       if (buflen != 0)
+               error = EFBIG;
+
+       *segp = seg;
+       *lastpaddrp = nextpaddr;
+
+free_bounce:
+       if (error && (dmat->flags & BUS_DMA_COULD_BOUNCE) &&
+           map != &nobounce_dmamap) {
+               _bus_dmamap_unload(dmat, map);
+               return_bounce_pages(dmat, map);
+       }
+       return error;
+}
+
+/*
+ * Map the buffer buf into bus space using the dmamap map.
+ */
+int
+bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
+               bus_size_t buflen, bus_dmamap_callback_t *callback,
+               void *callback_arg, int flags)
+{
+       vm_paddr_t lastaddr = 0;
+       int error, nsegs = 1;
+
+       if (map != NULL) {
+               /*
+                * XXX
+                * Follow old semantics.  Once all of the callers are fixed,
+                * we should get rid of these internal flag "adjustment".
+                */
+               flags &= ~BUS_DMA_NOWAIT;
+               flags |= BUS_DMA_WAITOK;
+
+               map->callback = callback;
+               map->callback_arg = callback_arg;
+       }
+
+       error = _bus_dmamap_load_buffer(dmat, map, buf, buflen,
+                       dmat->segments, dmat->nsegments,
+                       NULL, flags, &lastaddr, &nsegs, 1);
+       if (error == EINPROGRESS)
+               return error;
+
+       callback(callback_arg, dmat->segments, nsegs, error);
+       return 0;
+}
+
+/*
+ * Like _bus_dmamap_load(), but for mbufs.
+ */
+int
+bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map,
+                    struct mbuf *m0,
+                    bus_dmamap_callback2_t *callback, void *callback_arg,
+                    int flags)
+{
+       int nsegs, error;
+
+       /*
+        * XXX
+        * Follow old semantics.  Once all of the callers are fixed,
+        * we should get rid of these internal flag "adjustment".
+        */
+       flags &= ~BUS_DMA_WAITOK;
+       flags |= BUS_DMA_NOWAIT;
+
+       error = bus_dmamap_load_mbuf_segment(dmat, map, m0,
+                       dmat->segments, dmat->nsegments, &nsegs, flags);
+       if (error) {
+               /* force "no valid mappings" in callback */
+               callback(callback_arg, dmat->segments, 0, 0, error);
+       } else {
+               callback(callback_arg, dmat->segments, nsegs,
+                        m0->m_pkthdr.len, error);
+       }
+       return error;
+}
+
+int
+bus_dmamap_load_mbuf_segment(bus_dma_tag_t dmat, bus_dmamap_t map,
+                            struct mbuf *m0,
+                            bus_dma_segment_t *segs, int maxsegs,
+                            int *nsegs, int flags)
+{
+       int error;
+
+       M_ASSERTPKTHDR(m0);
+
+       KASSERT(maxsegs >= 1, ("invalid maxsegs %d\n", maxsegs));
+       KASSERT(maxsegs <= dmat->nsegments,
+               ("%d too many segments, dmat only support %d segments\n",
+                maxsegs, dmat->nsegments));
+       KASSERT(flags & BUS_DMA_NOWAIT,
+               ("only BUS_DMA_NOWAIT is supported\n"));
+
+       if (m0->m_pkthdr.len <= dmat->maxsize) {
+               int first = 1;
+               vm_paddr_t lastaddr = 0;
+               struct mbuf *m;
+
+               *nsegs = 1;
+               error = 0;
+               for (m = m0; m != NULL && error == 0; m = m->m_next) {
+                       if (m->m_len == 0)
+                               continue;
+
+                       error = _bus_dmamap_load_buffer(dmat, map,
+                                       m->m_data, m->m_len,
+                                       segs, maxsegs,
+                                       NULL, flags, &lastaddr,
+                                       nsegs, first);
+                       if (error == ENOMEM && !first) {
+                               /*
+                                * Out of bounce pages due to too many
+                                * fragments in the mbuf chain; return
+                                * EFBIG instead.
+                                */
+                               error = EFBIG;
+                       }
+                       first = 0;
+               }
+#ifdef INVARIANTS
+               if (!error)
+                       KKASSERT(*nsegs <= maxsegs && *nsegs >= 1);
+#endif
+       } else {
+               *nsegs = 0;
+               error = EINVAL;
+       }
+       KKASSERT(error != EINPROGRESS);
+       return error;
+}
+
+/*
+ * Like _bus_dmamap_load(), but for uios.
+ */
+int
+bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map,
+                   struct uio *uio,
+                   bus_dmamap_callback2_t *callback, void *callback_arg,
+                   int flags)
+{
+       vm_paddr_t lastaddr;
+       int nsegs, error, first, i;
+       bus_size_t resid;
+       struct iovec *iov;
+       pmap_t pmap;
+
+       /*
+        * XXX
+        * Follow old semantics.  Once all of the callers are fixed,
+        * we should get rid of these internal flag "adjustment".
+        */
+       flags &= ~BUS_DMA_WAITOK;
+       flags |= BUS_DMA_NOWAIT;
+
+       resid = (bus_size_t)uio->uio_resid;
+       iov = uio->uio_iov;
+
+       if (uio->uio_segflg == UIO_USERSPACE) {
+               struct thread *td;
+
+               td = uio->uio_td;
+               KASSERT(td != NULL && td->td_proc != NULL,
+                       ("bus_dmamap_load_uio: USERSPACE but no proc"));
+               pmap = vmspace_pmap(td->td_proc->p_vmspace);
+       } else {
+               pmap = NULL;
+       }
+
+       error = 0;
+       nsegs = 1;
+       first = 1;
+       lastaddr = 0;
+       for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) {
+               /*
+                * Now at the first iovec to load.  Load each iovec
+                * until we have exhausted the residual count.
+                */
+               bus_size_t minlen =
+                       resid < iov[i].iov_len ? resid : iov[i].iov_len;
+               caddr_t addr = (caddr_t) iov[i].iov_base;
+
+               error = _bus_dmamap_load_buffer(dmat, map, addr, minlen,
+                               dmat->segments, dmat->nsegments,
+                               pmap, flags, &lastaddr, &nsegs, first);
+               first = 0;
+
+               resid -= minlen;
+       }
+
+       if (error) {
+               /* force "no valid mappings" in callback */
+               callback(callback_arg, dmat->segments, 0, 0, error);
+       } else {
+               callback(callback_arg, dmat->segments, nsegs,
+                        (bus_size_t)uio->uio_resid, error);
+       }
+       return error;
+}
+
+/*
+ * Release the mapping held by map.
+ */
+void
+_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
+{
+       struct bounce_page *bpage;
+
+       while ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
+               STAILQ_REMOVE_HEAD(&map->bpages, links);
+               free_bounce_page(dmat, bpage);
+       }
+}
+
+void
+_bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
+{
+       struct bounce_page *bpage;
+
+       if ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
+               /*
+                * Handle data bouncing.  We might also
+                * want to add support for invalidating
+                * the caches on broken hardware
+                */
+               switch (op) {
+               case BUS_DMASYNC_PREWRITE:
+                       while (bpage != NULL) {
+                               bcopy((void *)bpage->datavaddr,
+                                     (void *)bpage->vaddr,
+                                     bpage->datacount);
+                               bpage = STAILQ_NEXT(bpage, links);
+                       }
+                       dmat->bounce_zone->total_bounced++;
+                       break;
+
+               case BUS_DMASYNC_POSTREAD:
+                       while (bpage != NULL) {
+                               bcopy((void *)bpage->vaddr,
+                                     (void *)bpage->datavaddr,
+                                     bpage->datacount);
+                               bpage = STAILQ_NEXT(bpage, links);
+                       }
+                       dmat->bounce_zone->total_bounced++;
+                       break;
+
+               case BUS_DMASYNC_PREREAD:
+               case BUS_DMASYNC_POSTWRITE:
+                       /* No-ops */
+                       break;
+               }
+       }
+}
+
+static int
+alloc_bounce_zone(bus_dma_tag_t dmat)
+{
+       struct bounce_zone *bz, *new_bz;
+       lwkt_tokref ref;
+
+       KASSERT(dmat->bounce_zone == NULL,
+               ("bounce zone was already assigned\n"));
+
+       new_bz = kmalloc(sizeof(*new_bz), M_DEVBUF, M_INTWAIT | M_ZERO);
+
+       lwkt_gettoken(&ref, &bounce_zone_tok);
+
+       /* Check to see if we already have a suitable zone */
+       STAILQ_FOREACH(bz, &bounce_zone_list, links) {
+               if (dmat->alignment <= bz->alignment &&
+                   dmat->lowaddr >= bz->lowaddr) {
+                       lwkt_reltoken(&ref);
+
+                       dmat->bounce_zone = bz;
+                       kfree(new_bz, M_DEVBUF);
+                       return 0;
+               }
+       }
+       bz = new_bz;
+
+#ifdef SMP
+       spin_init(&bz->spin);
+#endif
+       STAILQ_INIT(&bz->bounce_page_list);
+       STAILQ_INIT(&bz->bounce_map_waitinglist);
+       bz->free_bpages = 0;
+       bz->reserved_bpages = 0;
+       bz->active_bpages = 0;
+       bz->lowaddr = dmat->lowaddr;
+       bz->alignment = round_page(dmat->alignment);
+       ksnprintf(bz->zoneid, 8, "zone%d", busdma_zonecount);
+       busdma_zonecount++;
+       ksnprintf(bz->lowaddrid, 18, "%#jx", (uintmax_t)bz->lowaddr);
+       STAILQ_INSERT_TAIL(&bounce_zone_list, bz, links);
+
+       lwkt_reltoken(&ref);
+
+       dmat->bounce_zone = bz;
+
+       sysctl_ctx_init(&bz->sysctl_ctx);
+       bz->sysctl_tree = SYSCTL_ADD_NODE(&bz->sysctl_ctx,
+           SYSCTL_STATIC_CHILDREN(_hw_busdma), OID_AUTO, bz->zoneid,
+           CTLFLAG_RD, 0, "");
+       if (bz->sysctl_tree == NULL) {
+               sysctl_ctx_free(&bz->sysctl_ctx);
+               return 0;       /* XXX error code? */
+       }
+
+       SYSCTL_ADD_INT(&bz->sysctl_ctx,
+           SYSCTL_CHILDREN(bz->sysctl_tree), OID_AUTO,
+           "total_bpages", CTLFLAG_RD, &bz->total_bpages, 0,
+           "Total bounce pages");
+       SYSCTL_ADD_INT(&bz->sysctl_ctx,
+           SYSCTL_CHILDREN(bz->sysctl_tree), OID_AUTO,
+           "free_bpages", CTLFLAG_RD, &bz->free_bpages, 0,
+           "Free bounce pages");
+       SYSCTL_ADD_INT(&bz->sysctl_ctx,
+           SYSCTL_CHILDREN(bz->sysctl_tree), OID_AUTO,
+           "reserved_bpages", CTLFLAG_RD, &bz->reserved_bpages, 0,
+           "Reserved bounce pages");
+       SYSCTL_ADD_INT(&bz->sysctl_ctx,
+           SYSCTL_CHILDREN(bz->sysctl_tree), OID_AUTO,
+           "active_bpages", CTLFLAG_RD, &bz->active_bpages, 0,
+           "Active bounce pages");
+       SYSCTL_ADD_INT(&bz->sysctl_ctx,
+           SYSCTL_CHILDREN(bz->sysctl_tree), OID_AUTO,
+           "total_bounced", CTLFLAG_RD, &bz->total_bounced, 0,
+           "Total bounce requests");
+       SYSCTL_ADD_INT(&bz->sysctl_ctx,
+           SYSCTL_CHILDREN(bz->sysctl_tree), OID_AUTO,
+           "total_deferred", CTLFLAG_RD, &bz->total_deferred, 0,
+           "Total bounce requests that were deferred");
+       SYSCTL_ADD_INT(&bz->sysctl_ctx,
+           SYSCTL_CHILDREN(bz->sysctl_tree), OID_AUTO,
+           "reserve_failed", CTLFLAG_RD, &bz->reserve_failed, 0,
+           "Total bounce page reservations that were failed");
+       SYSCTL_ADD_STRING(&bz->sysctl_ctx,
+           SYSCTL_CHILDREN(bz->sysctl_tree), OID_AUTO,
+           "lowaddr", CTLFLAG_RD, bz->lowaddrid, 0, "");
+       SYSCTL_ADD_INT(&bz->sysctl_ctx,
+           SYSCTL_CHILDREN(bz->sysctl_tree), OID_AUTO,
+           "alignment", CTLFLAG_RD, &bz->alignment, 0, "");
+
+       return 0;
+}
+
+static int
+alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages, int flags)
+{
+       struct bounce_zone *bz = dmat->bounce_zone;
+       int count = 0, mflags;
+
+       if (flags & BUS_DMA_NOWAIT)
+               mflags = M_NOWAIT;
+       else
+               mflags = M_WAITOK;
+
+       while (numpages > 0) {
+               struct bounce_page *bpage;
+
+               bpage = kmalloc(sizeof(*bpage), M_DEVBUF, M_INTWAIT | M_ZERO);
+
+               bpage->vaddr = (vm_offset_t)contigmalloc(PAGE_SIZE, M_DEVBUF,
+                                                        mflags, 0ul,
+                                                        bz->lowaddr,
+                                                        bz->alignment, 0);
+               if (bpage->vaddr == 0) {
+                       kfree(bpage, M_DEVBUF);
+                       break;
+               }
+               bpage->busaddr = pmap_kextract(bpage->vaddr);
+
+               BZ_LOCK(bz);
+               STAILQ_INSERT_TAIL(&bz->bounce_page_list, bpage, links);
+               total_bounce_pages++;
+               bz->total_bpages++;
+               bz->free_bpages++;
+               BZ_UNLOCK(bz);
+
+               count++;
+               numpages--;
+       }
+       return count;
+}
+
+/* Assume caller holds bounce zone spinlock */
+static int
+reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map, int commit)
+{
+       struct bounce_zone *bz = dmat->bounce_zone;
+       int pages;
+
+       pages = MIN(bz->free_bpages, map->pagesneeded - map->pagesreserved);
+       if (!commit && map->pagesneeded > (map->pagesreserved + pages)) {
+               bz->reserve_failed++;
+               return (map->pagesneeded - (map->pagesreserved + pages));
+       }
+
+       bz->free_bpages -= pages;
+
+       bz->reserved_bpages += pages;
+       KKASSERT(bz->reserved_bpages <= bz->total_bpages);
+
+       map->pagesreserved += pages;
+       pages = map->pagesneeded - map->pagesreserved;
+
+       return pages;
+}
+
+static void
+return_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map)
+{
+       struct bounce_zone *bz = dmat->bounce_zone;
+       int reserved = map->pagesreserved;
+       bus_dmamap_t wait_map;
+
+       map->pagesreserved = 0;
+       map->pagesneeded = 0;
+
+       if (reserved == 0)
+               return;
+
+       BZ_LOCK(bz);
+
+       bz->free_bpages += reserved;
+       KKASSERT(bz->free_bpages <= bz->total_bpages);
+
+       KKASSERT(bz->reserved_bpages >= reserved);
+       bz->reserved_bpages -= reserved;
+
+       wait_map = get_map_waiting(dmat);
+
+       BZ_UNLOCK(bz);
+
+       if (wait_map != NULL)
+               add_map_callback(map);
+}
+
+static bus_addr_t
+add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map, vm_offset_t vaddr,
+               bus_size_t size)
+{
+       struct bounce_zone *bz = dmat->bounce_zone;
+       struct bounce_page *bpage;
+
+       KASSERT(map->pagesneeded > 0, ("map doesn't need any pages"));
+       map->pagesneeded--;
+
+       KASSERT(map->pagesreserved > 0, ("map doesn't reserve any pages"));
+       map->pagesreserved--;
+
+       BZ_LOCK(bz);
+
+       bpage = STAILQ_FIRST(&bz->bounce_page_list);
+       KASSERT(bpage != NULL, ("free page list is empty"));
+       STAILQ_REMOVE_HEAD(&bz->bounce_page_list, links);
+
+       KKASSERT(bz->reserved_bpages > 0);
+       bz->reserved_bpages--;
+
+       bz->active_bpages++;
+       KKASSERT(bz->active_bpages <= bz->total_bpages);
+
+       BZ_UNLOCK(bz);
+
+       bpage->datavaddr = vaddr;
+       bpage->datacount = size;
+       STAILQ_INSERT_TAIL(&map->bpages, bpage, links);
+       return bpage->busaddr;
+}
+
+static void
+free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage)
+{
+       struct bounce_zone *bz = dmat->bounce_zone;
+       bus_dmamap_t map;
+
+       bpage->datavaddr = 0;
+       bpage->datacount = 0;
+
+       BZ_LOCK(bz);
+
+       STAILQ_INSERT_HEAD(&bz->bounce_page_list, bpage, links);
+
+       bz->free_bpages++;
+       KKASSERT(bz->free_bpages <= bz->total_bpages);
+
+       KKASSERT(bz->active_bpages > 0);
+       bz->active_bpages--;
+
+       map = get_map_waiting(dmat);
+
+       BZ_UNLOCK(bz);
+
+       if (map != NULL)
+               add_map_callback(map);
+}
+
+/* Assume caller holds bounce zone spinlock */
+static bus_dmamap_t
+get_map_waiting(bus_dma_tag_t dmat)
+{
+       struct bounce_zone *bz = dmat->bounce_zone;
+       bus_dmamap_t map;
+
+       map = STAILQ_FIRST(&bz->bounce_map_waitinglist);
+       if (map != NULL) {
+               if (reserve_bounce_pages(map->dmat, map, 1) == 0) {
+                       STAILQ_REMOVE_HEAD(&bz->bounce_map_waitinglist, links);
+                       bz->total_deferred++;
+               } else {
+                       map = NULL;
+               }
+       }
+       return map;
+}
+
+static void
+add_map_callback(bus_dmamap_t map)
+{
+#ifdef notyet
+       /* XXX callbacklist is not MPSAFE */
+       crit_enter();
+       get_mplock();
+       STAILQ_INSERT_TAIL(&bounce_map_callbacklist, map, links);
+       busdma_swi_pending = 1;
+       setsoftvm();
+       rel_mplock();
+       crit_exit();
+#else
+       panic("%s uncoded\n", __func__);
+#endif
+}
+
+#ifdef notyet
+void
+busdma_swi(void)
+{
+       bus_dmamap_t map;
+
+       crit_enter();
+       while ((map = STAILQ_FIRST(&bounce_map_callbacklist)) != NULL) {
+               STAILQ_REMOVE_HEAD(&bounce_map_callbacklist, links);
+               crit_exit();
+               bus_dmamap_load(map->dmat, map, map->buf, map->buflen,
+                               map->callback, map->callback_arg, /*flags*/0);
+               crit_enter();
+       }
+       crit_exit();
+}
+#endif
diff --git a/sys/platform/vkernel64/platform/console.c b/sys/platform/vkernel64/platform/console.c
new file mode 100644 (file)
index 0000000..db99c5a
--- /dev/null
@@ -0,0 +1,426 @@
+/*
+ * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon@backplane.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $DragonFly: src/sys/platform/vkernel/platform/console.c,v 1.17 2007/07/02 04:19:14 dillon Exp $
+ */
+
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/tty.h>
+#include <sys/termios.h>
+#include <sys/fcntl.h>
+#include <sys/signalvar.h>
+#include <sys/eventhandler.h>
+#include <sys/interrupt.h>
+#include <machine/md_var.h>
+#include <unistd.h>
+#include <termios.h>
+#include <stdlib.h>
+
+static int console_stolen_by_kernel;
+static struct kqueue_info *kqueue_console_info;
+
+/*
+ * Global console locking functions
+ */
+void
+cons_lock(void)
+{
+}
+
+void
+cons_unlock(void)
+{
+}
+
+/************************************************************************
+ *                         CONSOLE DEVICE                              *
+ ************************************************************************
+ *
+ */
+
+#define CDEV_MAJOR     12      /* steal the same major as /dev/ttyv* */
+
+static int vcons_tty_param(struct tty *tp, struct termios *tio);
+static void vcons_tty_start(struct tty *tp);
+static void vcons_intr(void *tpx, struct intrframe *frame __unused);
+
+static d_open_t         vcons_open;
+static d_close_t        vcons_close;
+static d_ioctl_t        vcons_ioctl;
+
+static struct dev_ops vcons_ops = {
+       { "vcons", CDEV_MAJOR, D_TTY },
+       .d_open =       vcons_open,
+       .d_close =      vcons_close,
+       .d_read =       ttyread,
+       .d_write =      ttywrite,
+       .d_ioctl =      vcons_ioctl,
+       .d_poll =       ttypoll,
+};
+
+static int
+vcons_open(struct dev_open_args *ap)
+{
+       cdev_t dev = ap->a_head.a_dev;
+       struct tty *tp;
+       int error;
+
+       tp = dev->si_tty = ttymalloc(dev->si_tty);
+
+#define        ISSET(t, f)     ((t) & (f))
+
+       if ((tp->t_state & TS_ISOPEN) == 0) {
+               tp->t_oproc = vcons_tty_start;
+               tp->t_param = vcons_tty_param;
+               tp->t_stop = nottystop;
+               tp->t_dev = dev;
+
+               tp->t_state |= TS_CARR_ON | TS_CONNECTED;
+               ttychars(tp);
+               tp->t_iflag = TTYDEF_IFLAG;
+               tp->t_oflag = TTYDEF_OFLAG;
+               tp->t_cflag = TTYDEF_CFLAG;
+               tp->t_lflag = TTYDEF_LFLAG;
+               tp->t_ispeed = TTYDEF_SPEED;
+               tp->t_ospeed = TTYDEF_SPEED;
+               ttsetwater(tp);
+       }
+       if (minor(dev) == 0) {
+               error = (*linesw[tp->t_line].l_open)(dev, tp);
+               ioctl(0, TIOCGWINSZ, &tp->t_winsize);
+
+               if (kqueue_console_info == NULL)
+                       kqueue_console_info = kqueue_add(0, vcons_intr, tp);
+       } else {
+               /* dummy up other minors so the installer will run */
+               error = 0;
+       }
+       return(error);
+}
+
+static int
+vcons_close(struct dev_close_args *ap)
+{
+       cdev_t dev = ap->a_head.a_dev;
+       struct tty *tp;
+
+       tp = dev->si_tty;
+       (*linesw[tp->t_line].l_close)(tp, ap->a_fflag);
+       ttyclose(tp);
+       return(0);
+}
+
+static int
+vcons_ioctl(struct dev_ioctl_args *ap)
+{
+       cdev_t dev = ap->a_head.a_dev;
+       struct tty *tp;
+       int error;
+
+       tp = dev->si_tty;
+       error = (*linesw[tp->t_line].l_ioctl)(tp, ap->a_cmd, ap->a_data,
+                                             ap->a_fflag, ap->a_cred);
+       if (error != ENOIOCTL)
+               return (error);
+       error = ttioctl(tp, ap->a_cmd, ap->a_data, ap->a_fflag);
+       if (error != ENOIOCTL)
+               return (error);
+       return (ENOTTY);
+}
+
+static int
+vcons_tty_param(struct tty *tp, struct termios *tio)
+{
+       tp->t_ispeed = tio->c_ispeed;
+       tp->t_ospeed = tio->c_ospeed;
+       tp->t_cflag = tio->c_cflag;
+       return(0);
+}
+
+static void
+vcons_tty_start(struct tty *tp)
+{
+       int n;
+       char buf[64];
+
+       if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
+               ttwwakeup(tp);
+               return;
+       }
+       tp->t_state |= TS_BUSY;
+       while ((n = q_to_b(&tp->t_outq, buf, sizeof(buf))) > 0) {
+               /*
+                * Dummy up ttyv1, etc.
+                */
+               if (minor(tp->t_dev) == 0) {
+                       pwrite(1, buf, n, -1);
+               }
+       }
+       tp->t_state &= ~TS_BUSY;
+       ttwwakeup(tp);
+}
+
+static
+void
+vcons_intr(void *tpx, struct intrframe *frame __unused)
+{
+       struct tty *tp = tpx;
+       unsigned char buf[32];
+       int i;
+       int n;
+
+       /*
+        * If we aren't open we only have synchronous traffic via the
+        * debugger and do not need to poll.
+        */
+       if ((tp->t_state & TS_ISOPEN) == 0)
+               return;
+
+       /*
+        * Only poll if we are open and haven't been stolen by the debugger.
+        */
+       if (console_stolen_by_kernel == 0 && (tp->t_state & TS_ISOPEN)) {
+               do {
+                       n = extpread(0, buf, sizeof(buf), O_FNONBLOCKING, -1LL);
+                       for (i = 0; i < n; ++i)
+                               (*linesw[tp->t_line].l_rint)(buf[i], tp);
+               } while (n > 0);
+       }
+}
+
+/************************************************************************
+ *                     KERNEL CONSOLE INTERFACE                        *
+ ************************************************************************
+ *
+ * Kernel direct-call interface console driver
+ */
+static cn_probe_t      vconsprobe;
+static cn_init_t       vconsinit;
+static cn_init_fini_t  vconsinit_fini;
+static cn_term_t       vconsterm;
+static cn_getc_t       vconsgetc;
+static cn_checkc_t     vconscheckc;
+static cn_putc_t       vconsputc;
+
+CONS_DRIVER(vcons, vconsprobe, vconsinit, vconsinit_fini, vconsterm, vconsgetc,
+               vconscheckc, vconsputc, NULL);
+
+static struct termios init_tio;
+static struct consdev *vconsole;
+
+static void
+vconsprobe(struct consdev *cp)
+{
+       cp->cn_pri = CN_NORMAL;
+       cp->cn_probegood = 1;
+}
+
+/*
+ * This is a little bulky handler to set proper terminal
+ * settings in the case of a signal which might lead to
+ * termination or suspension.
+ */
+static void
+vconssignal(int sig)
+{
+       struct termios curtio;
+       struct sigaction sa, osa;
+       sigset_t ss, oss;
+
+       tcgetattr(0, &curtio);
+       tcsetattr(0, TCSAFLUSH, &init_tio);
+       bzero(&sa, sizeof(sa));
+       sigemptyset(&sa.sa_mask);
+       sa.sa_handler = SIG_DFL;
+       sigaction(sig, &sa, &osa);
+       sigemptyset(&ss);
+       sigaddset(&ss, sig);
+       sigprocmask(SIG_UNBLOCK, &ss, &oss);
+       raise(sig);     /* now hand down the sig */
+       sigprocmask(SIG_SETMASK, &oss, NULL);
+       sigaction(sig, &osa, NULL);
+       tcsetattr(0, TCSAFLUSH, &curtio);
+}
+
+static void
+vconswinchsig(int __unused sig)
+{
+       signalintr(3);
+}
+
+static void
+vconswinch_intr(void *arg __unused, void *frame __unused)
+{
+       struct winsize newsize;
+
+       if (vconsole != NULL && vconsole->cn_dev->si_tty != NULL) {
+               ioctl(0, TIOCGWINSZ, &newsize);
+               /*
+                * ttioctl(vconsole->cn_dev->si_tty, TIOCSWINSZ, &newsize, 0);
+                * I wished.  Unfortunately this needs a curproc, so do it
+                * manually.
+                */
+               if (bcmp(&newsize, &vconsole->cn_dev->si_tty->t_winsize,
+                        sizeof(newsize)) != 0) {
+                       vconsole->cn_dev->si_tty->t_winsize = newsize;
+                       pgsignal(vconsole->cn_dev->si_tty->t_pgrp, SIGWINCH, 1);
+               }
+       }
+}
+
+static void
+vconscleanup(void)
+{
+       /*
+        * We might catch stray SIGIOs, so try hard.
+        */
+       while (tcsetattr(0, TCSAFLUSH, &init_tio) != 0 && errno == EINTR)
+               /* NOTHING */;
+}
+
+static void
+vconsinit(struct consdev *cp)
+{
+       struct sigaction sa;
+
+       vconsole = cp;
+
+       tcgetattr(0, &init_tio);
+       bzero(&sa, sizeof(sa));
+       sigemptyset(&sa.sa_mask);
+       sa.sa_handler = vconssignal;
+       sigaction(SIGTSTP, &sa, NULL);
+       sigaction(SIGINT, &sa, NULL);
+       sigaction(SIGTERM, &sa, NULL);
+       atexit(vconscleanup);
+       vcons_set_mode(0);
+}
+
+static void
+vconsinit_fini(struct consdev *cp)
+{
+       struct sigaction sa;
+       cdev_t dev;
+       int i;
+
+       /*
+        * We have to do this here rather then in early boot to be able
+        * to use the interrupt subsystem.
+        */
+       register_int(3, vconswinch_intr, NULL, "swinch", NULL, 0);
+       bzero(&sa, sizeof(sa));
+       sigemptyset(&sa.sa_mask);
+       sa.sa_handler = vconswinchsig;
+       sigaction(SIGWINCH, &sa, NULL);
+
+       /*
+        * Implement ttyv0-ttyv7.  At the moment ttyv1-7 are sink nulls.
+        */
+       for (i = 0; i < 8; ++i) {
+               dev = make_dev(&vcons_ops, i,
+                              UID_ROOT, GID_WHEEL, 0600, "ttyv%d", i);
+               if (i == 0) {
+                       cp->cn_dev = dev;
+               }
+       }
+       EVENTHANDLER_REGISTER(shutdown_final, vconscleanup, NULL, SHUTDOWN_PRI_LAST);
+}
+
+static void
+vconsterm(struct consdev *vp)
+{
+       vconsole = NULL;
+       vconscleanup();
+}
+
+static int
+vconsgetc(void *private)
+{
+       unsigned char c;
+       ssize_t n;
+
+       console_stolen_by_kernel = 1;
+       for (;;) {
+               n = pread(0, &c, 1, -1);
+               if (n == 1)
+                       break;
+               if (n < 0 && errno == EINTR)
+                       continue;
+               panic("vconsgetc: EOF on console %jd %d", (intmax_t)n, errno);
+       }
+       console_stolen_by_kernel = 0;
+       return((int)c);
+}
+
+static int
+vconscheckc(void *private)
+{
+       unsigned char c;
+
+       if (extpread(0, &c, 1, O_FNONBLOCKING, -1LL) == 1)
+               return((int)c);
+       return(-1);
+}
+
+static void
+vconsputc(void *private, int c)
+{
+       char cc = c;
+
+       pwrite(1, &cc, 1, -1);
+}
+
+void
+vcons_set_mode(int in_debugger)
+{
+       struct termios tio;
+
+       if (tcgetattr(0, &tio) < 0)
+               return;
+       cfmakeraw(&tio);
+       tio.c_oflag |= OPOST | ONLCR;
+       tio.c_lflag |= ISIG;
+       if (in_debugger) {
+               tio.c_cc[VINTR] = init_tio.c_cc[VINTR];
+               tio.c_cc[VSUSP] = init_tio.c_cc[VSUSP];
+               tio.c_cc[VSTATUS] = init_tio.c_cc[VSTATUS];
+       } else {
+               tio.c_cc[VINTR] = _POSIX_VDISABLE;
+               tio.c_cc[VSUSP] = _POSIX_VDISABLE;
+               tio.c_cc[VSTATUS] = _POSIX_VDISABLE;
+       }
+       tcsetattr(0, TCSAFLUSH, &tio);
+}
diff --git a/sys/platform/vkernel64/platform/copyio.c b/sys/platform/vkernel64/platform/copyio.c
new file mode 100644 (file)
index 0000000..d7d7155
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon@backplane.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $DragonFly: src/sys/platform/vkernel/platform/copyio.c,v 1.9 2008/05/09 07:24:47 dillon Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <cpu/lwbuf.h>
+#include <vm/vm_page.h>
+#include <vm/vm_extern.h>
+#include <assert.h>
+
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include <sys/mplock2.h>
+
+/*
+ * A bcopy that works dring low level boot, before FP is working
+ */
+void
+ovbcopy(const void *src, void *dst, size_t len)
+{
+       bcopy(src, dst, len);
+}
+
+void
+bcopyi(const void *src, void *dst, size_t len)
+{
+       bcopy(src, dst, len);
+}
+
+int
+copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *lencopied)
+{
+       size_t i;
+
+       for (i = 0; i < len; ++i) {
+               if ((((char *)kdaddr)[i] = ((const char *)kfaddr)[i]) == 0) {
+                       if (lencopied)
+                               *lencopied = i + 1;
+                       return(0);
+               }
+       }
+       return (ENAMETOOLONG);
+}
+
+/*
+ * Copies a NUL-terminated string from user space to kernel space.
+ * The number of bytes copied, including the terminator, is returned in
+ * (*res).
+ *
+ * Returns 0 on success, EFAULT or ENAMETOOLONG on failure.
+ */
+int
+copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *res)
+{
+       int error;
+       size_t n;
+       const char *uptr = udaddr;
+       char *kptr = kaddr;
+
+       if (res)
+               *res = 0;
+       while (len) {
+               n = PAGE_SIZE - ((vm_offset_t)uptr & PAGE_MASK);
+               if (n > 32)
+                       n = 32;
+               if (n > len)
+                       n = len;
+               if ((error = copyin(uptr, kptr, n)) != 0)
+                       return(error);
+               while (n) {
+                       if (res)
+                               ++*res;
+                       if (*kptr == 0)
+                               return(0);
+                       ++kptr;
+                       ++uptr;
+                       --n;
+                       --len;
+               }
+
+       }
+       return(ENAMETOOLONG);
+}
+
+/*
+ * Copy a binary buffer from user space to kernel space.
+ *
+ * NOTE: on a real system copyin/copyout are MP safe, but the current
+ * implementation on a vkernel is not so we get the mp lock.
+ *
+ * Returns 0 on success, EFAULT on failure.
+ */
+int
+copyin(const void *udaddr, void *kaddr, size_t len)
+{
+       struct vmspace *vm = curproc->p_vmspace;
+       struct lwbuf *lwb;
+       vm_page_t m;
+       int error;
+       size_t n;
+
+       error = 0;
+       get_mplock();
+       while (len) {
+               m = vm_fault_page(&vm->vm_map, trunc_page((vm_offset_t)udaddr),
+                                 VM_PROT_READ,
+                                 VM_FAULT_NORMAL, &error);
+               if (error)
+                       break;
+               n = PAGE_SIZE - ((vm_offset_t)udaddr & PAGE_MASK);
+               if (n > len)
+                       n = len;
+               lwb = lwbuf_alloc(m);
+               bcopy((char *)lwbuf_kva(lwb)+((vm_offset_t)udaddr & PAGE_MASK),
+                     kaddr, n);
+               len -= n;
+               udaddr = (const char *)udaddr + n;
+               kaddr = (char *)kaddr + n;
+               vm_page_unhold(m);
+               lwbuf_free(lwb);
+       }
+       rel_mplock();
+       return (error);
+}
+
+/*
+ * Copy a binary buffer from kernel space to user space.
+ *
+ * Returns 0 on success, EFAULT on failure.
+ */
+int
+copyout(const void *kaddr, void *udaddr, size_t len)
+{
+       struct vmspace *vm = curproc->p_vmspace;
+       struct lwbuf *lwb;
+       vm_page_t m;
+       int error;
+       size_t n;
+
+       error = 0;
+       get_mplock();
+       while (len) {
+               m = vm_fault_page(&vm->vm_map, trunc_page((vm_offset_t)udaddr),
+                                 VM_PROT_READ|VM_PROT_WRITE,
+                                 VM_FAULT_NORMAL, &error);
+               if (error)
+                       break;
+               n = PAGE_SIZE - ((vm_offset_t)udaddr & PAGE_MASK);
+               if (n > len)
+                       n = len;
+               lwb = lwbuf_alloc(m);
+               bcopy(kaddr, (char *)lwbuf_kva(lwb) +
+                            ((vm_offset_t)udaddr & PAGE_MASK), n);
+               len -= n;
+               udaddr = (char *)udaddr + n;
+               kaddr = (const char *)kaddr + n;
+               vm_page_dirty(m);
+               vm_page_unhold(m);
+               lwbuf_free(lwb);
+       }
+       rel_mplock();
+       return (error);
+}
+
+/*
+ * Fetch the byte at the specified user address.  Returns -1 on failure.
+ */
+int
+fubyte(const void *base)
+{
+       unsigned char c;
+       int error;
+
+       if ((error = copyin(base, &c, 1)) == 0)
+               return((int)c);
+       return(-1);
+}
+
+/*
+ * Store a byte at the specified user address.  Returns -1 on failure.
+ */
+int
+subyte (void *base, int byte)
+{
+       unsigned char c = byte;
+       int error;
+
+       if ((error = copyout(&c, base, 1)) == 0)
+               return(0);
+       return(-1);
+}
+
+/*
+ * Fetch a word (integer, 32 bits) from user space
+ */
+long
+fuword(const void *base)
+{
+       long v;
+       int error;
+
+       if ((error = copyin(base, &v, sizeof(v))) == 0)
+               return((long)v);
+       return(-1);
+}
+
+/*
+ * Store a word (integer, 32 bits) to user space
+ */
+int
+suword(void *base, long word)
+{
+       int error;
+
+       if ((error = copyout(&word, base, sizeof(word))) == 0)
+               return(0);
+       return(-1);
+}
+
+/*
+ * Fetch an short word (16 bits) from user space
+ */
+int
+fusword(void *base)
+{
+       unsigned short sword;
+       int error;
+
+       if ((error = copyin(base, &sword, sizeof(sword))) == 0)
+               return((int)sword);
+       return(-1);
+}
+
+/*
+ * Store a short word (16 bits) to user space
+ */
+int
+susword (void *base, int word)
+{
+       unsigned short sword = word;
+       int error;
+
+       if ((error = copyout(&sword, base, sizeof(sword))) == 0)
+               return(0);
+       return(-1);
+}
diff --git a/sys/platform/vkernel64/platform/cothread.c b/sys/platform/vkernel64/platform/cothread.c
new file mode 100644 (file)
index 0000000..dc81faa
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon@backplane.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $DragonFly: src/sys/platform/vkernel/platform/cothread.c,v 1.3 2008/05/07 17:19:47 dillon Exp $
+ */
+/*
+ * Provides the vkernel with an asynchronous I/O mechanism using pthreads
+ * which operates outside the cpu abstraction.  Cothreads are intended to
+ * operate like DMA engines and may ONLY make libc and cothread_*() calls.
+ * The cothread may NOT call into the vkernel since abstractions like
+ * 'mycpu' do not exist for it.
+ */
+
+#include <sys/interrupt.h>
+#include <sys/kernel.h>
+#include <sys/memrange.h>
+#include <sys/tls.h>
+#include <sys/types.h>
+
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_object.h>
+#include <vm/vm_page.h>
+
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/globaldata.h>
+#include <machine/md_var.h>
+#include <machine/pmap.h>
+#include <machine/smp.h>
+#include <machine/tls.h>
+#include <machine/cothread.h>
+
+#include <unistd.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+
+static void cothread_thread(void *arg);
+
+/*
+ * Create a co-processor thread for a virtual kernel.  This thread operates
+ * outside of the virtual kernel cpu abstraction and may only make direct
+ * cothread and libc calls.
+ */
+cothread_t
+cothread_create(void (*thr_func)(cothread_t cotd),
+               void (*thr_intr)(cothread_t cotd),
+               void *arg, const char *name)
+{
+       cothread_t cotd;
+
+       cotd = kmalloc(sizeof(*cotd), M_DEVBUF, M_WAITOK|M_ZERO);
+       cotd->thr_intr = thr_intr;
+       cotd->thr_func = thr_func;
+       cotd->arg = arg;
+       crit_enter();
+       pthread_mutex_init(&cotd->mutex, NULL);
+       pthread_cond_init(&cotd->cond, NULL);
+       crit_exit();
+
+       cotd->pintr = pthread_self();
+
+       cotd->intr_id = register_int(1, (void *)thr_intr, cotd, name, NULL, 0);
+
+       /*
+        * The vkernel's cpu_disable_intr() masks signals.  We don't want
+        * our coprocessor thread taking any unix signals :-)
+        */
+       crit_enter();
+       cpu_mask_all_signals();
+       pthread_create(&cotd->pthr, NULL, (void *)cothread_thread, cotd);
+       cpu_unmask_all_signals();
+       crit_exit();
+       return(cotd);
+}
+
+/*
+ * Wait for the target thread to terminate and then destroy the cothread
+ * structure.
+ */
+void
+cothread_delete(cothread_t *cotdp)
+{
+       cothread_t cotd;
+
+       if ((cotd = *cotdp) != NULL) {
+               unregister_int(cotd->intr_id);
+               crit_enter();
+               pthread_join(cotd->pthr, NULL);
+               crit_exit();
+               kfree(cotd, M_DEVBUF);
+               *cotdp = NULL;
+       }
+}
+
+static void
+cothread_thread(void *arg)
+{
+       cothread_t cotd = arg;
+
+       cpu_mask_all_signals(); /* XXX remove me? should already be masked */
+       /*
+        * %gs (aka mycpu) is illegal in cothreads.   Note that %fs is used
+        * by pthreads.
+        */
+       /* JG try another approach? */
+       tls_set_gs(0, sizeof(struct privatespace));
+       cotd->thr_func(cotd);
+}
+
+/*
+ * Called by the cothread to generate an interrupt back to the vkernel.
+ */
+void
+cothread_intr(cothread_t cotd)
+{
+       pthread_kill(cotd->pintr, SIGIO);
+}
+
+/*
+ * Called by the vkernel to wakeup a cothread.
+ */
+void
+cothread_signal(cothread_t cotd)
+{
+       crit_enter();
+       pthread_cond_signal(&cotd->cond);
+       crit_exit();
+}
+
+/*
+ * Called by the cothread to wait for the vkernel to call cothread_signal().
+ */
+void
+cothread_wait(cothread_t cotd)
+{
+       pthread_cond_wait(&cotd->cond, &cotd->mutex);
+}
+
+/*
+ * Typically called by kernel thread or cothread
+ */
+void
+cothread_lock(cothread_t cotd, int is_cotd)
+{
+       if (is_cotd) {
+               pthread_mutex_lock(&cotd->mutex);
+       } else {
+               crit_enter();
+               pthread_mutex_lock(&cotd->mutex);
+               crit_exit();
+       }
+}
+
+void
+cothread_unlock(cothread_t cotd, int is_cotd)
+{
+       if (is_cotd) {
+               pthread_mutex_unlock(&cotd->mutex);
+       } else {
+               crit_enter();
+               pthread_mutex_unlock(&cotd->mutex);
+               crit_exit();
+       }
+}
similarity index 55%
copy from sys/platform/pc64/x86_64/ktr.c
copy to sys/platform/vkernel64/platform/globaldata.c
index a85a71c..cd7da82 100644 (file)
@@ -1,13 +1,13 @@
 /*
- * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
- * 
+ * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
+ *
  * This code is derived from software contributed to The DragonFly Project
  * by Matthew Dillon <dillon@backplane.com>
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -17,7 +17,7 @@
  * 3. Neither the name of The DragonFly Project nor the names of its
  *    contributors may be used to endorse or promote products derived
  *    from this software without specific, prior written permission.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
+ *
+ * $DragonFly: src/sys/platform/vkernel/platform/globaldata.c,v 1.5 2008/04/28 07:05:08 dillon Exp $
  */
-/*
- * Kernel tracepoint facility.
- */
-
-#include "opt_ddb.h"
-#include "opt_ktr.h"
 
-#include <sys/param.h>
-#include <sys/cons.h>
-#include <sys/kernel.h>
-#include <sys/libkern.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/tls.h>
 #include <sys/proc.h>
-#include <sys/sysctl.h>
-#include <sys/ktr.h>
+#include <vm/vm_page.h>
 
-/*
- * This routine fills in the ktr_caller1 and ktr_caller2 fields by
- * tracing back through the kernel stack to locate the stack frames
- * and return addresses.
- *
- *
- *     [first argument]
- *     [retpc]
- *     [frameptr]              -> points to caller's frame pointer
- * sp ->[junk]
- */
+#include <machine/md_var.h>
+#include <machine/globaldata.h>
+#include <machine/vmparam.h>
 
-static __inline 
-void **
-FRAMEUP(void **frameptr)
-{
-    void **newframeptr;
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <err.h>
+#include <errno.h>
+#include <assert.h>
 
-    newframeptr = (void **)frameptr[0];
-    if (((uintptr_t)newframeptr ^ (uintptr_t)frameptr) & ~16383)
-       newframeptr = frameptr;
-    return(newframeptr);
+struct globaldata *
+globaldata_find(int cpu)
+{
+       KKASSERT(cpu >= 0 && cpu < ncpus);
+       return (&CPU_prvspace[cpu].mdglobaldata.mi);
 }
 
 void
-cpu_ktr_caller(struct ktr_entry *_ktr)
+cpu_gdinit(struct mdglobaldata *gd, int cpu)
 {
-    struct ktr_entry *ktr;
-    void **frameptr;
+       if (cpu)
+               gd->mi.gd_curthread = &gd->mi.gd_idlethread;
 
-    frameptr = (void **)&_ktr - 2;     /* frame, retpc to ktr_log */
-    ktr = _ktr;
-    frameptr = FRAMEUP(frameptr);      /* frame, retpc to traced function */
-    frameptr = FRAMEUP(frameptr);      /* frame, caller1 of traced function */
-    ktr->ktr_caller1 = frameptr[1];
-    frameptr = FRAMEUP(frameptr);      /* frame, caller2 of caller1 */
-    ktr->ktr_caller2 = frameptr[1];
+       lwkt_init_thread(&gd->mi.gd_idlethread,
+                       gd->mi.gd_prvspace->idlestack,
+                       sizeof(gd->mi.gd_prvspace->idlestack),
+                       TDF_MPSAFE, &gd->mi);
+       lwkt_set_comm(&gd->mi.gd_idlethread, "idle_%d", cpu);
+       gd->mi.gd_idlethread.td_switch = cpu_lwkt_switch;
+       gd->mi.gd_idlethread.td_sp -= sizeof(void *);
+       *(void **)gd->mi.gd_idlethread.td_sp = cpu_idle_restore;
 }
 
+int
+is_globaldata_space(vm_offset_t saddr, vm_offset_t eaddr)
+{
+       if (saddr >= (vm_offset_t)&CPU_prvspace[0] &&
+           eaddr <= (vm_offset_t)&CPU_prvspace[MAXCPU]) {
+               return (TRUE);
+       }
+       return (FALSE);
+}
diff --git a/sys/platform/vkernel64/platform/init.c b/sys/platform/vkernel64/platform/init.c
new file mode 100644 (file)
index 0000000..ad2fd1f
--- /dev/null
@@ -0,0 +1,1262 @@
+/*
+ * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon@backplane.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $DragonFly: src/sys/platform/vkernel/platform/init.c,v 1.56 2008/05/27 07:48:00 dillon Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/cons.h>
+#include <sys/random.h>
+#include <sys/vkernel.h>
+#include <sys/tls.h>
+#include <sys/reboot.h>
+#include <sys/proc.h>
+#include <sys/msgbuf.h>
+#include <sys/vmspace.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/un.h>
+#include <vm/vm_page.h>
+
+#include <machine/cpu.h>
+#include <machine/globaldata.h>
+#include <machine/tls.h>
+#include <machine/md_var.h>
+#include <machine/vmparam.h>
+#include <cpu/specialreg.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/bridge/if_bridgevar.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <err.h>
+#include <errno.h>
+#include <assert.h>
+
+vm_paddr_t phys_avail[16];
+vm_paddr_t Maxmem;
+vm_paddr_t Maxmem_bytes;
+int MemImageFd = -1;
+struct vkdisk_info DiskInfo[VKDISK_MAX];
+int DiskNum;
+struct vknetif_info NetifInfo[VKNETIF_MAX];
+int NetifNum;
+char *pid_file;
+vm_offset_t KvaStart;
+vm_offset_t KvaEnd;
+vm_offset_t KvaSize;
+vm_offset_t virtual_start;
+vm_offset_t virtual_end;
+vm_offset_t virtual2_start;
+vm_offset_t virtual2_end;
+vm_offset_t kernel_vm_end;
+vm_offset_t crashdumpmap;
+vm_offset_t clean_sva;
+vm_offset_t clean_eva;
+struct msgbuf *msgbufp;
+caddr_t ptvmmap;
+vpte_t *KernelPTD;
+vpte_t *KernelPTA;     /* Warning: Offset for direct VA translation */
+void *dmap_min_address;
+u_int cpu_feature;     /* XXX */
+int tsc_present;
+int64_t tsc_frequency;
+int optcpus;           /* number of cpus - see mp_start() */
+int lwp_cpu_lock;      /* if/how to lock virtual CPUs to real CPUs */
+int real_ncpus;                /* number of real CPUs */
+int next_cpu;          /* next real CPU to lock a virtual CPU to */
+
+struct privatespace *CPU_prvspace;
+
+static struct trapframe proc0_tf;
+static void *proc0paddr;
+
+static void init_sys_memory(char *imageFile);
+static void init_kern_memory(void);
+static void init_globaldata(void);
+static void init_vkernel(void);
+static void init_disk(char *diskExp[], int diskFileNum, enum vkdisk_type type);
+static void init_netif(char *netifExp[], int netifFileNum);
+static void writepid( void );
+static void cleanpid( void );
+static int unix_connect(const char *path);
+static void usage(const char *ctl, ...);
+
+static int save_ac;
+static char **save_av;
+
+/*
+ * Kernel startup for virtual kernels - standard main()
+ */
+int
+main(int ac, char **av)
+{
+       char *memImageFile = NULL;
+       char *netifFile[VKNETIF_MAX];
+       char *diskFile[VKDISK_MAX];
+       char *cdFile[VKDISK_MAX];
+       char *suffix;
+       char *endp;
+       int netifFileNum = 0;
+       int diskFileNum = 0;
+       int cdFileNum = 0;
+       int bootOnDisk = -1;    /* set below to vcd (0) or vkd (1) */
+       int c;
+       int i;
+       int j;
+       int n;
+       int isq;
+       int real_vkernel_enable;
+       int supports_sse;
+       size_t vsize;
+
+       save_ac = ac;
+       save_av = av;
+
+       /*
+        * Process options
+        */
+       kernel_mem_readonly = 1;
+#ifdef SMP
+       optcpus = 2;
+#endif
+       lwp_cpu_lock = LCL_NONE;
+
+       real_vkernel_enable = 0;
+       vsize = sizeof(real_vkernel_enable);
+       sysctlbyname("vm.vkernel_enable", &real_vkernel_enable, &vsize, NULL,0);
+
+       if (real_vkernel_enable == 0) {
+               errx(1, "vm.vkernel_enable is 0, must be set "
+                       "to 1 to execute a vkernel!");
+       }
+
+       real_ncpus = 1;
+       vsize = sizeof(real_ncpus);
+       sysctlbyname("hw.ncpu", &real_ncpus, &vsize, NULL, 0);
+
+       while ((c = getopt(ac, av, "c:svl:m:n:r:e:i:p:I:U")) != -1) {
+               switch(c) {
+               case 'e':
+                       /*
+                        * name=value:name=value:name=value...
+                        * name="value"...
+                        *
+                        * Allow values to be quoted but note that shells
+                        * may remove the quotes, so using this feature
+                        * to embed colons may require a backslash.
+                        */
+                       n = strlen(optarg);
+                       isq = 0;
+                       kern_envp = malloc(n + 2);
+                       for (i = j = 0; i < n; ++i) {
+                               if (optarg[i] == '"')
+                                       isq ^= 1;
+                               else if (optarg[i] == '\'')
+                                       isq ^= 2;
+                               else if (isq == 0 && optarg[i] == ':')
+                                       kern_envp[j++] = 0;
+                               else
+                                       kern_envp[j++] = optarg[i];
+                       }
+                       kern_envp[j++] = 0;
+                       kern_envp[j++] = 0;
+                       break;
+               case 's':
+                       boothowto |= RB_SINGLE;
+                       break;
+               case 'v':
+                       bootverbose = 1;
+                       break;
+               case 'i':
+                       memImageFile = optarg;
+                       break;
+               case 'I':
+                       if (netifFileNum < VKNETIF_MAX)
+                               netifFile[netifFileNum++] = strdup(optarg);
+                       break;
+               case 'r':
+                       if (bootOnDisk < 0)
+                               bootOnDisk = 1;
+                       if (diskFileNum + cdFileNum < VKDISK_MAX)
+                               diskFile[diskFileNum++] = strdup(optarg);
+                       break;
+               case 'c':
+                       if (bootOnDisk < 0)
+                               bootOnDisk = 0;
+                       if (diskFileNum + cdFileNum < VKDISK_MAX)
+                               cdFile[cdFileNum++] = strdup(optarg);
+                       break;
+               case 'm':
+                       Maxmem_bytes = strtoull(optarg, &suffix, 0);
+                       if (suffix) {
+                               switch(*suffix) {
+                               case 'g':
+                               case 'G':
+                                       Maxmem_bytes <<= 30;
+                                       break;
+                               case 'm':
+                               case 'M':
+                                       Maxmem_bytes <<= 20;
+                                       break;
+                               case 'k':
+                               case 'K':
+                                       Maxmem_bytes <<= 10;
+                                       break;
+                               default:
+                                       Maxmem_bytes = 0;
+                                       usage("Bad maxmem option");
+                                       /* NOT REACHED */
+                                       break;
+                               }
+                       }
+                       break;
+               case 'l':
+                       next_cpu = -1;
+                       if (strncmp("map", optarg, 3) == 0) {
+                               lwp_cpu_lock = LCL_PER_CPU;
+                               if (optarg[3] == ',') {
+                                       next_cpu = strtol(optarg+4, &endp, 0);
+                                       if (*endp != '\0')
+                                               usage("Bad target CPU number at '%s'", endp);
+                               } else {
+                                       next_cpu = 0;
+                               }
+                               if (next_cpu < 0 || next_cpu > real_ncpus - 1)
+                                       usage("Bad target CPU, valid range is 0-%d", real_ncpus - 1);
+                       } else if (strncmp("any", optarg, 3) == 0) {
+                               lwp_cpu_lock = LCL_NONE;
+                       } else {
+                               lwp_cpu_lock = LCL_SINGLE_CPU;
+                               next_cpu = strtol(optarg, &endp, 0);
+                               if (*endp != '\0')
+                                       usage("Bad target CPU number at '%s'", endp);
+                               if (next_cpu < 0 || next_cpu > real_ncpus - 1)
+                                       usage("Bad target CPU, valid range is 0-%d", real_ncpus - 1);
+                       }
+                       break;
+               case 'n':
+                       /*
+                        * This value is set up by mp_start(), don't just
+                        * set ncpus here.
+                        */
+#ifdef SMP
+                       optcpus = strtol(optarg, NULL, 0);
+                       if (optcpus < 1 || optcpus > MAXCPU)
+                               usage("Bad ncpus, valid range is 1-%d", MAXCPU);
+#else
+                       if (strtol(optarg, NULL, 0) != 1) {
+                               usage("You built a UP vkernel, only 1 cpu!");
+                       }
+#endif
+
+                       break;
+               case 'p':
+                       pid_file = optarg;
+                       break;
+               case 'U':
+                       kernel_mem_readonly = 0;
+                       break;
+               }
+       }
+
+       writepid();
+       cpu_disable_intr();
+       init_sys_memory(memImageFile);
+       init_kern_memory();
+       init_globaldata();
+       init_vkernel();
+       setrealcpu();
+       init_kqueue();
+
+       /*
+        * Check TSC
+        */
+       vsize = sizeof(tsc_present);
+       sysctlbyname("hw.tsc_present", &tsc_present, &vsize, NULL, 0);
+       vsize = sizeof(tsc_frequency);
+       sysctlbyname("hw.tsc_frequency", &tsc_frequency, &vsize, NULL, 0);
+       if (tsc_present)
+               cpu_feature |= CPUID_TSC;
+
+       /*
+        * Check SSE
+        */
+       vsize = sizeof(supports_sse);
+       supports_sse = 0;
+       sysctlbyname("hw.instruction_sse", &supports_sse, &vsize, NULL, 0);
+       init_fpu(supports_sse);
+       if (supports_sse)
+               cpu_feature |= CPUID_SSE | CPUID_FXSR;
+
+       /*
+        * We boot from the first installed disk.
+        */
+       if (bootOnDisk == 1) {
+               init_disk(diskFile, diskFileNum, VKD_DISK);
+               init_disk(cdFile, cdFileNum, VKD_CD);
+       } else {
+               init_disk(cdFile, cdFileNum, VKD_CD);
+               init_disk(diskFile, diskFileNum, VKD_DISK);
+       }
+       init_netif(netifFile, netifFileNum);
+       init_exceptions();
+       mi_startup();
+       /* NOT REACHED */
+       exit(1);
+}
+
+/*
+ * Initialize system memory.  This is the virtual kernel's 'RAM'.
+ */
+static
+void
+init_sys_memory(char *imageFile)
+{
+       struct stat st;
+       int i;
+       int fd;
+
+       /*
+        * Figure out the system memory image size.  If an image file was
+        * specified and -m was not specified, use the image file's size.
+        */
+
+       if (imageFile && stat(imageFile, &st) == 0 && Maxmem_bytes == 0)
+               Maxmem_bytes = (vm_paddr_t)st.st_size;
+       if ((imageFile == NULL || stat(imageFile, &st) < 0) &&
+           Maxmem_bytes == 0) {
+               err(1, "Cannot create new memory file %s unless "
+                      "system memory size is specified with -m",
+                      imageFile);
+               /* NOT REACHED */
+       }
+
+       /*
+        * Maxmem must be known at this time
+        */
+       if (Maxmem_bytes < 32 * 1024 * 1024 || (Maxmem_bytes & SEG_MASK)) {
+               err(1, "Bad maxmem specification: 32MB minimum, "
+                      "multiples of %dMB only",
+                      SEG_SIZE / 1024 / 1024);
+               /* NOT REACHED */
+       }
+
+       /*
+        * Generate an image file name if necessary, then open/create the
+        * file exclusively locked.  Do not allow multiple virtual kernels
+        * to use the same image file.
+        */
+       if (imageFile == NULL) {
+               for (i = 0; i < 1000000; ++i) {
+                       asprintf(&imageFile, "/var/vkernel/memimg.%06d", i);
+                       fd = open(imageFile,
+                                 O_RDWR|O_CREAT|O_EXLOCK|O_NONBLOCK, 0644);
+                       if (fd < 0 && errno == EWOULDBLOCK) {
+                               free(imageFile);
+                               continue;
+                       }
+                       break;
+               }
+       } else {
+               fd = open(imageFile, O_RDWR|O_CREAT|O_EXLOCK|O_NONBLOCK, 0644);
+       }
+       fprintf(stderr, "Using memory file: %s\n", imageFile);
+       if (fd < 0 || fstat(fd, &st) < 0) {
+               err(1, "Unable to open/create %s", imageFile);
+               /* NOT REACHED */
+       }
+
+       /*
+        * Truncate or extend the file as necessary.
+        */
+       if (st.st_size > Maxmem_bytes) {
+               ftruncate(fd, Maxmem_bytes);
+       } else if (st.st_size < Maxmem_bytes) {
+               char *zmem;
+               off_t off = st.st_size & ~SEG_MASK;
+
+               kprintf("%s: Reserving blocks for memory image\n", imageFile);
+               zmem = malloc(SEG_SIZE);
+               bzero(zmem, SEG_SIZE);
+               lseek(fd, off, SEEK_SET);
+               while (off < Maxmem_bytes) {
+                       if (write(fd, zmem, SEG_SIZE) != SEG_SIZE) {
+                               err(1, "Unable to reserve blocks for memory image");
+                               /* NOT REACHED */
+                       }
+                       off += SEG_SIZE;
+               }
+               if (fsync(fd) < 0)
+                       err(1, "Unable to reserve blocks for memory image");
+               free(zmem);
+       }
+       MemImageFd = fd;
+       Maxmem = Maxmem_bytes >> PAGE_SHIFT;
+}
+
+/*
+ * Initialize kernel memory.  This reserves kernel virtual memory by using
+ * MAP_VPAGETABLE
+ */
+
+static
+void
+init_kern_memory(void)
+{
+       void *base;
+       void *try;
+       char *zero;
+       char dummy;
+       char *topofstack = &dummy;
+       vpte_t pte;
+       int i;
+       void *firstfree;
+
+       /*
+        * Memory map our kernel virtual memory space.  Note that the
+        * kernel image itself is not made part of this memory for the
+        * moment.
+        *
+        * The memory map must be segment-aligned so we can properly
+        * offset KernelPTD.
+        *
+        * If the system kernel has a different MAXDSIZ, it might not
+        * be possible to map kernel memory in its prefered location.
+        * Try a number of different locations.
+        */
+       try = (void *)(512UL << 30);
+       base = NULL;
+       while ((char *)try + KERNEL_KVA_SIZE < topofstack) {
+               base = mmap(try, KERNEL_KVA_SIZE, PROT_READ|PROT_WRITE,
+                           MAP_FILE|MAP_SHARED|MAP_VPAGETABLE,
+                           MemImageFd, try);
+               if (base == try)
+                       break;
+               if (base != MAP_FAILED)
+                       munmap(base, KERNEL_KVA_SIZE);
+               try = (char *)try + (512UL << 30);
+       }
+       if (base != try) {
+               err(1, "Unable to mmap() kernel virtual memory!");
+               /* NOT REACHED */
+       }
+       madvise(base, KERNEL_KVA_SIZE, MADV_NOSYNC);
+       KvaStart = (vm_offset_t)base;
+       KvaSize = KERNEL_KVA_SIZE;
+       KvaEnd = KvaStart + KvaSize;
+       printf("KVM mapped at %p-%p\n", (void *)KvaStart, (void *)KvaEnd);
+
+       /* MAP_FILE? */
+       dmap_min_address = mmap(0, DMAP_SIZE, PROT_READ|PROT_WRITE,
+                               MAP_NOCORE|MAP_NOSYNC|MAP_SHARED,
+                               MemImageFd, 0);
+       if (dmap_min_address == MAP_FAILED) {
+               err(1, "Unable to mmap() kernel DMAP region!");
+               /* NOT REACHED */
+       }
+
+       firstfree = 0;
+       pmap_bootstrap(&firstfree, base);
+
+       mcontrol(base, KERNEL_KVA_SIZE, MADV_SETMAP,
+                0 | VPTE_R | VPTE_W | VPTE_V);
+
+       /*
+        * phys_avail[] represents unallocated physical memory.  MI code
+        * will use phys_avail[] to create the vm_page array.
+        */
+       phys_avail[0] = firstfree;
+       phys_avail[0] = (phys_avail[0] + PAGE_MASK) & ~(vm_paddr_t)PAGE_MASK;
+       phys_avail[1] = Maxmem_bytes;
+
+#if JGV
+       /*
+        * (virtual_start, virtual_end) represent unallocated kernel virtual
+        * memory.  MI code will create kernel_map using these parameters.
+        */
+       virtual_start = KvaStart + (long)firstfree;
+       virtual_start = (virtual_start + PAGE_MASK) & ~(vm_offset_t)PAGE_MASK;
+       virtual_end = KvaStart + KERNEL_KVA_SIZE;
+#endif
+
+       /*
+        * pmap_growkernel() will set the correct value.
+        */
+       kernel_vm_end = 0;
+
+       /*
+        * Allocate space for process 0's UAREA.
+        */
+       proc0paddr = (void *)virtual_start;
+       for (i = 0; i < UPAGES; ++i) {
+               pmap_kenter_quick(virtual_start, phys_avail[0]);
+               virtual_start += PAGE_SIZE;
+               phys_avail[0] += PAGE_SIZE;
+       }
+
+       /*
+        * crashdumpmap
+        */
+       crashdumpmap = virtual_start;
+       virtual_start += MAXDUMPPGS * PAGE_SIZE;
+
+       /*
+        * msgbufp maps the system message buffer
+        */
+       assert((MSGBUF_SIZE & PAGE_MASK) == 0);
+       msgbufp = (void *)virtual_start;
+       for (i = 0; i < (MSGBUF_SIZE >> PAGE_SHIFT); ++i) {
+               pmap_kenter_quick(virtual_start, phys_avail[0]);
+               virtual_start += PAGE_SIZE;
+               phys_avail[0] += PAGE_SIZE;
+       }
+       msgbufinit(msgbufp, MSGBUF_SIZE);
+
+       /*
+        * used by kern_memio for /dev/mem access
+        */
+       ptvmmap = (caddr_t)virtual_start;
+       virtual_start += PAGE_SIZE;
+
+       /*
+        * Bootstrap the kernel_pmap
+        */
+#if JGV
+       pmap_bootstrap();
+#endif
+}
+
+/*
+ * Map the per-cpu globaldata for cpu #0.  Allocate the space using
+ * virtual_start and phys_avail[0]
+ */
+static
+void
+init_globaldata(void)
+{
+       int i;
+       vm_paddr_t pa;
+       vm_offset_t va;
+
+       /*
+        * Reserve enough KVA to cover possible cpus.  This is a considerable
+        * amount of KVA since the privatespace structure includes two
+        * whole page table mappings.
+        */
+       virtual_start = (virtual_start + SEG_MASK) & ~(vm_offset_t)SEG_MASK;
+       CPU_prvspace = (void *)virtual_start;
+       virtual_start += sizeof(struct privatespace) * SMP_MAXCPU;
+
+       /*
+        * Allocate enough physical memory to cover the mdglobaldata
+        * portion of the space and the idle stack and map the pages
+        * into KVA.  For cpu #0 only.
+        */
+       for (i = 0; i < sizeof(struct mdglobaldata); i += PAGE_SIZE) {
+               pa = phys_avail[0];
+               va = (vm_offset_t)&CPU_prvspace[0].mdglobaldata + i;
+               pmap_kenter_quick(va, pa);
+               phys_avail[0] += PAGE_SIZE;
+       }
+       for (i = 0; i < sizeof(CPU_prvspace[0].idlestack); i += PAGE_SIZE) {
+               pa = phys_avail[0];
+               va = (vm_offset_t)&CPU_prvspace[0].idlestack + i;
+               pmap_kenter_quick(va, pa);
+               phys_avail[0] += PAGE_SIZE;
+       }
+
+       /*
+        * Setup the %gs for cpu #0.  The mycpu macro works after this
+        * point.  Note that %fs is used by pthreads.
+        */
+       tls_set_gs(&CPU_prvspace[0], sizeof(struct privatespace));
+}
+
+/*
+ * Initialize very low level systems including thread0, proc0, etc.
+ */
+static
+void
+init_vkernel(void)
+{
+       struct mdglobaldata *gd;
+
+       gd = &CPU_prvspace[0].mdglobaldata;
+       bzero(gd, sizeof(*gd));
+
+       gd->mi.gd_curthread = &thread0;
+       thread0.td_gd = &gd->mi;
+       ncpus = 1;
+       ncpus2 = 1;     /* rounded down power of 2 */
+       ncpus_fit = 1;  /* rounded up power of 2 */
+       /* ncpus2_mask and ncpus_fit_mask are 0 */
+       init_param1();
+       gd->mi.gd_prvspace = &CPU_prvspace[0];
+       mi_gdinit(&gd->mi, 0);
+       cpu_gdinit(gd, 0);
+       mi_proc0init(&gd->mi, proc0paddr);
+       lwp0.lwp_md.md_regs = &proc0_tf;
+
+       /*init_locks();*/
+       cninit();
+       rand_initialize();
+#if 0  /* #ifdef DDB */
+       kdb_init();
+       if (boothowto & RB_KDB)
+               Debugger("Boot flags requested debugger");
+#endif
+       identcpu();
+#if 0
+       initializecpu();        /* Initialize CPU registers */
+#endif
+       init_param2((phys_avail[1] - phys_avail[0]) / PAGE_SIZE);
+
+#if 0
+       /*
+        * Map the message buffer
+        */
+       for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE)
+               pmap_kenter((vm_offset_t)msgbufp + off, avail_end + off);
+       msgbufinit(msgbufp, MSGBUF_SIZE);
+#endif
+#if 0
+       thread0.td_pcb_cr3 ... MMU
+       lwp0.lwp_md.md_regs = &proc0_tf;
+#endif
+}
+
+/*
+ * Filesystem image paths for the virtual kernel are optional.
+ * If specified they each should point to a disk image,
+ * the first of which will become the root disk.
+ *
+ * The virtual kernel caches data from our 'disk' just like a normal kernel,
+ * so we do not really want the real kernel to cache the data too.  Use
+ * O_DIRECT to remove the duplication.
+ */
+static
+void
+init_disk(char *diskExp[], int diskFileNum, enum vkdisk_type type)
+{
+       int i;
+
+        if (diskFileNum == 0)
+                return;
+
+       for(i=0; i < diskFileNum; i++){
+               char *fname;
+               fname = diskExp[i];
+
+               if (fname == NULL) {
+                        warnx("Invalid argument to '-r'");
+                        continue;
+                }
+
+               if (DiskNum < VKDISK_MAX) {
+                       struct stat st;
+                       struct vkdisk_info* info = NULL;
+                       int fd;
+                       size_t l = 0;
+
+                       if (type == VKD_DISK)
+                           fd = open(fname, O_RDWR|O_DIRECT|O_EXLOCK|O_NONBLOCK, 0644);
+                       else
+                           fd = open(fname, O_RDONLY|O_DIRECT, 0644);
+                       if (fd < 0 || fstat(fd, &st) < 0) {
+                               if (errno == EAGAIN)
+                                       fprintf(stderr, "You may already have a vkernel using this disk image!\n");
+                               err(1, "Unable to open/create %s", fname);
+                               /* NOT REACHED */
+                       }
+                       /* get rid of O_NONBLOCK, keep O_DIRECT */
+                       if (type == VKD_DISK)
+                               fcntl(fd, F_SETFL, O_DIRECT);
+
+                       info = &DiskInfo[DiskNum];
+                       l = strlen(fname);
+
+                       info->unit = i;
+                       info->fd = fd;
+                       info->type = type;
+                       memcpy(info->fname, fname, l);
+
+                       if (DiskNum == 0) {
+                               if (type == VKD_CD) {
+                                   rootdevnames[0] = "cd9660:vcd0a";
+                               } else if (type == VKD_DISK) {
+                                   rootdevnames[0] = "ufs:vkd0s0a";
+                                   rootdevnames[1] = "ufs:vkd0s1a";
+                               }
+                       }
+
+                       DiskNum++;
+               } else {
+                        warnx("vkd%d (%s) > VKDISK_MAX", DiskNum, fname);
+                        continue;
+               }
+       }
+}
+
+static
+int
+netif_set_tapflags(int tap_unit, int f, int s)
+{
+       struct ifreq ifr;
+       int flags;
+
+       bzero(&ifr, sizeof(ifr));
+
+       snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tap%d", tap_unit);
+       if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) {
+               warn("tap%d: ioctl(SIOCGIFFLAGS) failed", tap_unit);
+               return -1;
+       }
+
+       /*
+        * Adjust if_flags
+        *
+        * If the flags are already set/cleared, then we return
+        * immediately to avoid extra syscalls
+        */
+       flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
+       if (f < 0) {
+               /* Turn off flags */
+               f = -f;
+               if ((flags & f) == 0)
+                       return 0;
+               flags &= ~f;
+       } else {
+               /* Turn on flags */
+               if (flags & f)
+                       return 0;
+               flags |= f;
+       }
+
+       /*
+        * Fix up ifreq.ifr_name, since it may be trashed
+        * in previous ioctl(SIOCGIFFLAGS)
+        */
+       snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tap%d", tap_unit);
+
+       ifr.ifr_flags = flags & 0xffff;
+       ifr.ifr_flagshigh = flags >> 16;
+       if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) {
+               warn("tap%d: ioctl(SIOCSIFFLAGS) failed", tap_unit);
+               return -1;
+       }
+       return 0;
+}
+
+static
+int
+netif_set_tapaddr(int tap_unit, in_addr_t addr, in_addr_t mask, int s)
+{
+       struct ifaliasreq ifra;
+       struct sockaddr_in *in;
+
+       bzero(&ifra, sizeof(ifra));
+       snprintf(ifra.ifra_name, sizeof(ifra.ifra_name), "tap%d", tap_unit);
+
+       /* Setup address */
+       in = (struct sockaddr_in *)&ifra.ifra_addr;
+       in->sin_family = AF_INET;
+       in->sin_len = sizeof(*in);
+       in->sin_addr.s_addr = addr;
+
+       if (mask != 0) {
+               /* Setup netmask */
+               in = (struct sockaddr_in *)&ifra.ifra_mask;
+               in->sin_len = sizeof(*in);
+               in->sin_addr.s_addr = mask;
+       }
+
+       if (ioctl(s, SIOCAIFADDR, &ifra) < 0) {
+               warn("tap%d: ioctl(SIOCAIFADDR) failed", tap_unit);
+               return -1;
+       }
+       return 0;
+}
+
+static
+int
+netif_add_tap2brg(int tap_unit, const char *ifbridge, int s)
+{
+       struct ifbreq ifbr;
+       struct ifdrv ifd;
+
+       bzero(&ifbr, sizeof(ifbr));
+       snprintf(ifbr.ifbr_ifsname, sizeof(ifbr.ifbr_ifsname),
+                "tap%d", tap_unit);
+
+       bzero(&ifd, sizeof(ifd));
+       strlcpy(ifd.ifd_name, ifbridge, sizeof(ifd.ifd_name));
+       ifd.ifd_cmd = BRDGADD;
+       ifd.ifd_len = sizeof(ifbr);
+       ifd.ifd_data = &ifbr;
+
+       if (ioctl(s, SIOCSDRVSPEC, &ifd) < 0) {
+               /*
+                * 'errno == EEXIST' means that the tap(4) is already
+                * a member of the bridge(4)
+                */
+               if (errno != EEXIST) {
+                       warn("ioctl(%s, SIOCSDRVSPEC) failed", ifbridge);
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+#define TAPDEV_OFLAGS  (O_RDWR | O_NONBLOCK)
+
+/*
+ * Locate the first unused tap(4) device file if auto mode is requested,
+ * or open the user supplied device file, and bring up the corresponding
+ * tap(4) interface.
+ *
+ * NOTE: Only tap(4) device file is supported currently
+ */
+static
+int
+netif_open_tap(const char *netif, int *tap_unit, int s)
+{
+       char tap_dev[MAXPATHLEN];
+       int tap_fd, failed;
+       struct stat st;
+       char *dname;
+
+       *tap_unit = -1;
+
+       if (strcmp(netif, "auto") == 0) {
+               /*
+                * Find first unused tap(4) device file
+                */
+               tap_fd = open("/dev/tap", TAPDEV_OFLAGS);
+               if (tap_fd < 0) {
+                       warnc(errno, "Unable to find a free tap(4)");
+                       return -1;
+               }
+       } else {
+               /*
+                * User supplied tap(4) device file or unix socket.
+                */
+               if (netif[0] == '/')    /* Absolute path */
+                       strlcpy(tap_dev, netif, sizeof(tap_dev));
+               else
+                       snprintf(tap_dev, sizeof(tap_dev), "/dev/%s", netif);
+
+               tap_fd = open(tap_dev, TAPDEV_OFLAGS);
+
+               /*
+                * If we cannot open normally try to connect to it.
+                */
+               if (tap_fd < 0)
+                       tap_fd = unix_connect(tap_dev);
+
+               if (tap_fd < 0) {
+                       warn("Unable to open %s", tap_dev);
+                       return -1;
+               }
+       }
+
+       /*
+        * Check whether the device file is a tap(4)
+        */
+       if (fstat(tap_fd, &st) < 0) {
+               failed = 1;
+       } else if (S_ISCHR(st.st_mode)) {
+               dname = fdevname(tap_fd);
+               if (dname)
+                       dname = strstr(dname, "tap");
+               if (dname) {
+                       /*
+                        * Bring up the corresponding tap(4) interface
+                        */
+                       *tap_unit = strtol(dname + 3, NULL, 10);
+                       printf("TAP UNIT %d\n", *tap_unit);
+                       if (netif_set_tapflags(*tap_unit, IFF_UP, s) == 0)
+                               failed = 0;
+                       failed = 0;
+               } else {
+                       failed = 1;
+               }
+       } else if (S_ISSOCK(st.st_mode)) {
+               /*
+                * Special socket connection (typically to vknet).  We
+                * do not have to do anything.
+                */
+               failed = 0;
+       } else {
+               failed = 1;
+       }
+
+       if (failed) {
+               warnx("%s is not a tap(4) device or socket", tap_dev);
+               close(tap_fd);
+               tap_fd = -1;
+               *tap_unit = -1;
+       }
+       return tap_fd;
+}
+
+static int
+unix_connect(const char *path)
+{
+       struct sockaddr_un sunx;
+       int len;
+       int net_fd;
+       int sndbuf = 262144;
+       struct stat st;
+
+       snprintf(sunx.sun_path, sizeof(sunx.sun_path), "%s", path);
+       len = offsetof(struct sockaddr_un, sun_path[strlen(sunx.sun_path)]);
+       ++len;  /* include nul */
+       sunx.sun_family = AF_UNIX;
+       sunx.sun_len = len;
+
+       net_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
+       if (net_fd < 0)
+               return(-1);
+       if (connect(net_fd, (void *)&sunx, len) < 0) {
+               close(net_fd);
+               return(-1);
+       }
+       setsockopt(net_fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
+       if (fstat(net_fd, &st) == 0)
+               printf("Network socket buffer: %d bytes\n", st.st_blksize);
+       fcntl(net_fd, F_SETFL, O_NONBLOCK);
+       return(net_fd);
+}
+
+#undef TAPDEV_MAJOR
+#undef TAPDEV_MINOR
+#undef TAPDEV_OFLAGS
+
+/*
+ * Following syntax is supported,
+ * 1) x.x.x.x             tap(4)'s address is x.x.x.x
+ *
+ * 2) x.x.x.x/z           tap(4)'s address is x.x.x.x
+ *                        tap(4)'s netmask len is z
+ *
+ * 3) x.x.x.x:y.y.y.y     tap(4)'s address is x.x.x.x
+ *                        pseudo netif's address is y.y.y.y
+ *
+ * 4) x.x.x.x:y.y.y.y/z   tap(4)'s address is x.x.x.x
+ *                        pseudo netif's address is y.y.y.y
+ *                        tap(4) and pseudo netif's netmask len are z
+ *
+ * 5) bridgeX             tap(4) will be added to bridgeX
+ *
+ * 6) bridgeX:y.y.y.y     tap(4) will be added to bridgeX
+ *                        pseudo netif's address is y.y.y.y
+ *
+ * 7) bridgeX:y.y.y.y/z   tap(4) will be added to bridgeX
+ *                        pseudo netif's address is y.y.y.y
+ *                        pseudo netif's netmask len is z
+ */
+static
+int
+netif_init_tap(int tap_unit, in_addr_t *addr, in_addr_t *mask, int s)
+{
+       in_addr_t tap_addr, netmask, netif_addr;
+       int next_netif_addr;
+       char *tok, *masklen_str, *ifbridge;
+
+       *addr = 0;
+       *mask = 0;
+
+       tok = strtok(NULL, ":/");
+       if (tok == NULL) {
+               /*
+                * Nothing special, simply use tap(4) as backend
+                */
+               return 0;
+       }
+
+       if (inet_pton(AF_INET, tok, &tap_addr) > 0) {
+               /*
+                * tap(4)'s address is supplied
+                */
+               ifbridge = NULL;
+
+               /*
+                * If there is next token, then it may be pseudo
+                * netif's address or netmask len for tap(4)
+                */
+               next_netif_addr = 0;
+       } else {
+               /*
+                * Not tap(4)'s address, assume it as a bridge(4)
+                * iface name
+                */
+               tap_addr = 0;
+               ifbridge = tok;
+
+               /*
+                * If there is next token, then it must be pseudo
+                * netif's address
+                */
+               next_netif_addr = 1;
+       }
+
+       netmask = netif_addr = 0;
+
+       tok = strtok(NULL, ":/");
+       if (tok == NULL)
+               goto back;
+
+       if (inet_pton(AF_INET, tok, &netif_addr) <= 0) {
+               if (next_netif_addr) {
+                       warnx("Invalid pseudo netif address: %s", tok);
+                       return -1;
+               }
+               netif_addr = 0;
+
+               /*
+                * Current token is not address, then it must be netmask len
+                */
+               masklen_str = tok;
+       } else {
+               /*
+                * Current token is pseudo netif address, if there is next token
+                * it must be netmask len
+                */
+               masklen_str = strtok(NULL, "/");
+       }
+
+       /* Calculate netmask */
+       if (masklen_str != NULL) {
+               u_long masklen;
+
+               masklen = strtoul(masklen_str, NULL, 10);
+               if (masklen < 32 && masklen > 0) {
+                       netmask = htonl(~((1LL << (32 - masklen)) - 1)
+                                       & 0xffffffff);
+               } else {
+                       warnx("Invalid netmask len: %lu", masklen);
+                       return -1;
+               }
+       }
+
+       /* Make sure there is no more token left */
+       if (strtok(NULL, ":/") != NULL) {
+               warnx("Invalid argument to '-I'");
+               return -1;
+       }
+
+back:
+       if (tap_unit < 0) {
+               /* Do nothing */
+       } else if (ifbridge == NULL) {
+               /* Set tap(4) address/netmask */
+               if (netif_set_tapaddr(tap_unit, tap_addr, netmask, s) < 0)
+                       return -1;
+       } else {
+               /* Tie tap(4) to bridge(4) */
+               if (netif_add_tap2brg(tap_unit, ifbridge, s) < 0)
+                       return -1;
+       }
+
+       *addr = netif_addr;
+       *mask = netmask;
+       return 0;
+}
+
+/*
+ * NetifInfo[] will be filled for pseudo netif initialization.
+ * NetifNum will be bumped to reflect the number of valid entries
+ * in NetifInfo[].
+ */
+static
+void
+init_netif(char *netifExp[], int netifExpNum)
+{
+       int i, s;
+
+       if (netifExpNum == 0)
+               return;
+
+       s = socket(AF_INET, SOCK_DGRAM, 0);     /* for ioctl(SIOC) */
+       if (s < 0)
+               return;
+
+       for (i = 0; i < netifExpNum; ++i) {
+               struct vknetif_info *info;
+               in_addr_t netif_addr, netif_mask;
+               int tap_fd, tap_unit;
+               char *netif;
+
+               netif = strtok(netifExp[i], ":");
+               if (netif == NULL) {
+                       warnx("Invalid argument to '-I'");
+                       continue;
+               }
+
+               /*
+                * Open tap(4) device file and bring up the
+                * corresponding interface
+                */
+               tap_fd = netif_open_tap(netif, &tap_unit, s);
+               if (tap_fd < 0)
+                       continue;
+
+               /*
+                * Initialize tap(4) and get address/netmask
+                * for pseudo netif
+                *
+                * NB: Rest part of netifExp[i] is passed
+                *     to netif_init_tap() implicitly.
+                */
+               if (netif_init_tap(tap_unit, &netif_addr, &netif_mask, s) < 0) {
+                       /*
+                        * NB: Closing tap(4) device file will bring
+                        *     down the corresponding interface
+                        */
+                       close(tap_fd);
+                       continue;
+               }
+
+               info = &NetifInfo[NetifNum];
+               info->tap_fd = tap_fd;
+               info->tap_unit = tap_unit;
+               info->netif_addr = netif_addr;
+               info->netif_mask = netif_mask;
+
+               NetifNum++;
+               if (NetifNum >= VKNETIF_MAX)    /* XXX will this happen? */
+                       break;
+       }
+       close(s);
+}
+
+static
+void
+writepid( void )
+{
+       pid_t self;
+       FILE *fp;
+
+       if (pid_file != NULL) {
+               self = getpid();
+               fp = fopen(pid_file, "w");
+
+               if (fp != NULL) {
+                       fprintf(fp, "%ld\n", (long)self);
+                       fclose(fp);
+               }
+               else {
+                       perror("Warning: couldn't open pidfile");
+               }
+       }
+}
+
+static
+void
+cleanpid( void )
+{
+       if (pid_file != NULL) {
+               if ( unlink(pid_file) != 0 )
+                       perror("Warning: couldn't remove pidfile");
+       }
+}
+
+static
+void
+usage(const char *ctl, ...)
+{
+       va_list va;
+
+       va_start(va, ctl);
+       vfprintf(stderr, ctl, va);
+       va_end(va);
+       fprintf(stderr, "\n");
+       exit(1);
+}
+
+void
+cpu_reset(void)
+{
+       kprintf("cpu reset, rebooting vkernel\n");
+       closefrom(3);
+       cleanpid();
+       execv(save_av[0], save_av);
+}
+
+void
+cpu_halt(void)
+{
+       kprintf("cpu halt, exiting vkernel\n");
+       cleanpid();
+       exit(0);
+}
+
+void
+setrealcpu(void)
+{
+       switch(lwp_cpu_lock) {
+       case LCL_PER_CPU:
+               if (bootverbose)
+                       kprintf("Locking CPU%d to real cpu %d\n",
+                               mycpuid, next_cpu);
+               usched_set(getpid(), USCHED_SET_CPU, &next_cpu, sizeof(next_cpu));
+               next_cpu++;
+               if (next_cpu >= real_ncpus)
+                       next_cpu = 0;
+               break;
+       case LCL_SINGLE_CPU:
+               if (bootverbose)
+                       kprintf("Locking CPU%d to real cpu %d\n",
+                               mycpuid, next_cpu);
+               usched_set(getpid(), USCHED_SET_CPU, &next_cpu, sizeof(next_cpu));
+               break;
+       default:
+               /* do not map virtual cpus to real cpus */
+               break;
+       }
+}
diff --git a/sys/platform/vkernel64/platform/ipl_funcs.c b/sys/platform/vkernel64/platform/ipl_funcs.c
new file mode 100644 (file)
index 0000000..2649e4f
--- /dev/null
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 1997 Bruce Evans.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/i386/isa/ipl_funcs.c,v 1.32.2.5 2002/12/17 18:04:02 sam Exp $
+ * $DragonFly: src/sys/platform/vkernel/platform/ipl_funcs.c,v 1.2 2007/01/11 23:23:56 dillon Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/interrupt.h>
+#include <machine/globaldata.h>
+
+/*
+ * Bits in the ipending bitmap variable must be set atomically because
+ * ipending may be manipulated by interrupts or other cpu's without holding
+ * any locks.
+ *
+ * Note: setbits uses a locked or, making simple cases MP safe.
+ */
+#define DO_SETBITS(name, var, bits)                                    \
+void                                                                   \
+name(void)                                                             \
+{                                                                      \
+       struct mdglobaldata *gd = mdcpu;                                \
+       atomic_set_int_nonlocked(var, bits);                            \
+       atomic_set_int_nonlocked(&gd->mi.gd_reqflags, RQF_INTPEND);     \
+}                                                                      \
+
+DO_SETBITS(setdelayed,   &gd->gd_spending, loadandclear(&gd->gd_sdelayed))
+
+DO_SETBITS(setsoftcamnet,&gd->gd_spending, SWI_CAMNET_PENDING)
+DO_SETBITS(setsoftcambio,&gd->gd_spending, SWI_CAMBIO_PENDING)
+/*DO_SETBITS(setsoftunused02, &gd->gd_spending, SWI_UNUSED02_PENDING)*/
+/*DO_SETBITS(setsoftunused01,   &gd->gd_spending, SWI_UNUSED01_PENDING)*/
+DO_SETBITS(setsofttty,   &gd->gd_spending, SWI_TTY_PENDING)
+DO_SETBITS(setsoftvm,   &gd->gd_spending, SWI_VM_PENDING)
+DO_SETBITS(setsofttq,   &gd->gd_spending, SWI_TQ_PENDING)
+DO_SETBITS(setsoftcrypto,&gd->gd_spending, SWI_CRYPTO_PENDING)
+
+/*DO_SETBITS(schedsoftcamnet, &gd->gd_sdelayed, SWI_CAMNET_PENDING)*/
+/*DO_SETBITS(schedsoftcambio, &gd->gd_sdelayed, SWI_CAMBIO_PENDING)*/
+/*DO_SETBITS(schedsoftunused01, &gd->gd_sdelayed, SWI_UNUSED01_PENDING)*/
+DO_SETBITS(schedsofttty, &gd->gd_sdelayed, SWI_TTY_PENDING)
+/*DO_SETBITS(schedsoftvm, &gd->gd_sdelayed, SWI_VM_PENDING)*/
+/*DO_SETBITS(schedsofttq, &gd->gd_sdelayed, SWI_TQ_PENDING)*/
+/* YYY schedsoft what? */
diff --git a/sys/platform/vkernel64/platform/kqueue.c b/sys/platform/vkernel64/platform/kqueue.c
new file mode 100644 (file)
index 0000000..c40c0d7
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon@backplane.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $DragonFly: src/sys/platform/vkernel/platform/kqueue.c,v 1.6 2007/07/02 03:44:12 dillon Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/systimer.h>
+#include <sys/sysctl.h>
+#include <sys/signal.h>
+#include <sys/interrupt.h>
+#include <sys/bus.h>
+#include <sys/time.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#include <machine/cpu.h>
+#include <machine/globaldata.h>
+#include <machine/md_var.h>
+
+#include <sys/thread2.h>
+
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+struct kqueue_info {
+       void (*func)(void *, struct intrframe *);
+       void *data;
+       int fd;
+};
+
+static void kqueuesig(int signo);
+static void kqueue_intr(void *arg __unused, void *frame __unused);
+
+static int KQueueFd = -1;
+static void *VIntr1;
+
+/*
+ * Initialize kqueue based I/O
+ *
+ * Use SIGIO to get an immediate event when the kqueue has something waiting
+ * for us.  Setup the SIGIO signal as a mailbox signal for efficiency.
+ *
+ * Currently only read events are supported.
+ */
+void
+init_kqueue(void)
+{
+       struct sigaction sa;
+
+       bzero(&sa, sizeof(sa));
+       /*sa.sa_mailbox = &mdcpu->gd_mailbox;*/
+       sa.sa_flags = SA_NODEFER;
+       sa.sa_handler = kqueuesig;
+       sigemptyset(&sa.sa_mask);
+       sigaction(SIGIO, &sa, NULL);
+       KQueueFd = kqueue();
+       if (fcntl(KQueueFd, F_SETOWN, getpid()) < 0)
+               panic("Cannot configure kqueue for SIGIO, update your kernel");
+       if (fcntl(KQueueFd, F_SETFL, O_ASYNC) < 0)
+               panic("Cannot configure kqueue for SIGIO, update your kernel");
+}
+
+/*
+ * Signal handler dispatches interrupt thread.  Use interrupt #1
+ */
+static void
+kqueuesig(int signo)
+{
+       signalintr(1);
+}
+
+/*
+ * Generic I/O event support
+ */
+struct kqueue_info *
+kqueue_add(int fd, void (*func)(void *, struct intrframe *), void *data)
+{
+       struct timespec ts = { 0, 0 };
+       struct kqueue_info *info;
+       struct kevent kev;
+
+       if (VIntr1 == NULL)
+               VIntr1 = register_int(1, kqueue_intr, NULL, "kqueue", NULL, 0);
+
+       info = kmalloc(sizeof(*info), M_DEVBUF, M_ZERO|M_INTWAIT);
+       info->func = func;
+       info->data = data;
+       info->fd = fd;
+       EV_SET(&kev, fd, EVFILT_READ, EV_ADD|EV_ENABLE|EV_CLEAR, 0, 0, info);
+       if (kevent(KQueueFd, &kev, 1, NULL, 0, &ts) < 0)
+               panic("kqueue: kevent() call could not add descriptor");
+       return(info);
+}
+
+/*
+ * Medium resolution timer support
+ */
+struct kqueue_info *
+kqueue_add_timer(void (*func)(void *, struct intrframe *), void *data)
+{
+       struct kqueue_info *info;
+
+       if (VIntr1 == NULL)
+               VIntr1 = register_int(1, kqueue_intr, NULL, "kqueue", NULL, 0);
+
+       info = kmalloc(sizeof(*info), M_DEVBUF, M_ZERO|M_INTWAIT);
+       info->func = func;
+       info->data = data;
+       info->fd = (uintptr_t)info;
+       return(info);
+}
+
+void
+kqueue_reload_timer(struct kqueue_info *info, int ms)
+{
+       struct timespec ts = { 0, 0 };
+       struct kevent kev;
+
+       KKASSERT(ms > 0);
+
+       EV_SET(&kev, info->fd, EVFILT_TIMER,
+               EV_ADD|EV_ENABLE|EV_ONESHOT|EV_CLEAR, 0, (uintptr_t)ms, info);
+       if (kevent(KQueueFd, &kev, 1, NULL, 0, &ts) < 0)
+               panic("kqueue_reload_timer: Failed");
+}
+
+/*
+ * Destroy a previously added kqueue event
+ */
+void
+kqueue_del(struct kqueue_info *info)
+{
+       struct timespec ts = { 0, 0 };
+       struct kevent kev;
+
+       KKASSERT(info->fd >= 0);
+       EV_SET(&kev, info->fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
+       if (kevent(KQueueFd, &kev, 1, NULL, 0, &ts) < 0)
+               panic("kevent: failed to delete descriptor %d", info->fd);
+       info->fd = -1;
+       kfree(info, M_DEVBUF);
+}
+
+/*
+ * Safely called via DragonFly's normal interrupt handling mechanism.
+ *
+ * Calleld with the MP lock held.  Note that this is still an interrupt
+ * thread context.
+ */
+static
+void
+kqueue_intr(void *arg __unused, void *frame __unused)
+{
+       struct timespec ts;
+       struct kevent kevary[8];
+       int n;
+       int i;
+
+       ts.tv_sec = 0;
+       ts.tv_nsec = 0;
+       do {
+               n = kevent(KQueueFd, NULL, 0, kevary, 8, &ts);
+               for (i = 0; i < n; ++i) {
+                       struct kevent *kev = &kevary[i];
+                       struct kqueue_info *info = (void *)kev->udata;
+
+                       info->func(info->data, frame);
+               }
+       } while (n == 8);
+}
diff --git a/sys/platform/vkernel64/platform/machintr.c b/sys/platform/vkernel64/platform/machintr.c
new file mode 100644 (file)
index 0000000..7aa99ab
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2006 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon@backplane.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $DragonFly: src/sys/platform/vkernel/platform/machintr.c,v 1.17 2008/04/30 16:59:45 dillon Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/machintr.h>
+#include <sys/errno.h>
+#include <sys/mman.h>
+#include <sys/globaldata.h>
+#include <sys/interrupt.h>
+#include <stdio.h>
+#include <signal.h>
+#include <machine/globaldata.h>
+#include <machine/md_var.h>
+#include <sys/thread2.h>
+
+/*
+ * Interrupt Subsystem ABI
+ */
+
+static void dummy_intrdis(int);
+static void dummy_intren(int);
+static int dummy_vectorctl(int, int, int);
+static int dummy_setvar(int, const void *);
+static int dummy_getvar(int, void *);
+static void dummy_finalize(void);
+static void dummy_intrcleanup(void);
+
+struct machintr_abi MachIntrABI = {
+       MACHINTR_GENERIC,
+       .intrdis =      dummy_intrdis,
+       .intren =       dummy_intren,
+       .vectorctl =    dummy_vectorctl,
+       .setvar =       dummy_setvar,
+       .getvar =       dummy_getvar,
+       .finalize =     dummy_finalize,
+       .cleanup =      dummy_intrcleanup
+};
+
+static void
+dummy_intrdis(int intr)
+{
+}
+
+static void
+dummy_intren(int intr)
+{
+}
+
+static int
+dummy_vectorctl(int op, int intr, int flags)
+{
+       return (0);
+       /* return (EOPNOTSUPP); */
+}
+
+static int
+dummy_setvar(int varid, const void *buf)
+{
+       return (ENOENT);
+}
+
+static int
+dummy_getvar(int varid, void *buf)
+{
+       return (ENOENT);
+}
+
+static void
+dummy_finalize(void)
+{
+}
+
+static void
+dummy_intrcleanup(void)
+{
+}
+
+/*
+ * Process pending interrupts
+ */
+void
+splz(void)
+{
+       struct mdglobaldata *gd = mdcpu;
+       thread_t td = gd->mi.gd_curthread;
+       int irq;
+
+       while (gd->mi.gd_reqflags & (RQF_IPIQ|RQF_INTPEND)) {
+               crit_enter_quick(td);
+#ifdef SMP
+               if (gd->mi.gd_reqflags & RQF_IPIQ) {
+                       atomic_clear_int_nonlocked(&gd->mi.gd_reqflags,
+                                                  RQF_IPIQ);
+                       lwkt_process_ipiq();
+               }
+#endif
+               if (gd->mi.gd_reqflags & RQF_INTPEND) {
+                       atomic_clear_int_nonlocked(&gd->mi.gd_reqflags,
+                                                  RQF_INTPEND);
+                       while ((irq = ffs(gd->gd_spending)) != 0) {
+                               --irq;
+                               atomic_clear_int(&gd->gd_spending, 1 << irq);
+                               irq += FIRST_SOFTINT;
+                               sched_ithd(irq);
+                       }
+                       while ((irq = ffs(gd->gd_fpending)) != 0) {
+                               --irq;
+                               atomic_clear_int(&gd->gd_fpending, 1 << irq);
+                               sched_ithd(irq);
+                       }
+               }
+               crit_exit_noyield(td);
+       }
+}
+
+/*
+ * Allows an unprotected signal handler or mailbox to signal an interrupt
+ *
+ * For sched_ithd() to properly preempt via lwkt_schedule() we cannot
+ * enter a critical section here.  We use td_nest_count instead.
+ */
+void
+signalintr(int intr)
+{
+       struct mdglobaldata *gd = mdcpu;
+       thread_t td = gd->mi.gd_curthread;
+
+       if (td->td_pri >= TDPRI_CRIT || td->td_nest_count) {
+               atomic_set_int_nonlocked(&gd->gd_fpending, 1 << intr);
+               atomic_set_int_nonlocked(&gd->mi.gd_reqflags, RQF_INTPEND);
+       } else {
+               ++td->td_nest_count;
+               atomic_clear_int(&gd->gd_fpending, 1 << intr);
+               sched_ithd(intr);
+               --td->td_nest_count;
+       }
+}
+
+void
+cpu_disable_intr(void)
+{
+       sigblock(sigmask(SIGALRM)|sigmask(SIGIO));
+}
+
+void
+cpu_enable_intr(void)
+{
+       sigsetmask(0);
+}
+
+void
+cpu_mask_all_signals(void)
+{
+       sigblock(sigmask(SIGALRM)|sigmask(SIGIO)|sigmask(SIGQUIT)|
+                sigmask(SIGUSR1)|sigmask(SIGTERM)|sigmask(SIGWINCH)|
+                sigmask(SIGUSR2));
+}
+
+void
+cpu_unmask_all_signals(void)
+{
+       sigsetmask(0);
+}
+
+void
+cpu_invlpg(void *addr)
+{
+       madvise(addr, PAGE_SIZE, MADV_INVAL);
+}
+
+void
+cpu_invltlb(void)
+{
+       madvise((void *)KvaStart, KvaEnd - KvaStart, MADV_INVAL);
+}
similarity index 58%
copy from sys/platform/pc64/x86_64/pmap.c
copy to sys/platform/vkernel64/platform/pmap.c
index cd343db..c656218 100644 (file)
@@ -42,6 +42,7 @@
  *
  *     from:   @(#)pmap.c      7.7 (Berkeley)  5/12/91
  * $FreeBSD: src/sys/i386/i386/pmap.c,v 1.250.2.18 2002/03/06 22:48:53 silby Exp $
+ * $DragonFly: src/sys/platform/pc64/amd64/pmap.c,v 1.3 2008/08/29 17:07:10 dillon Exp $
  */
 
 /*
@@ -71,7 +72,6 @@
  */
 
 #if JG
-#include "opt_disable_pse.h"
 #include "opt_pmap.h"
 #endif
 #include "opt_msgbuf.h"
@@ -83,6 +83,7 @@
 #include <sys/msgbuf.h>
 #include <sys/vmmeter.h>
 #include <sys/mman.h>
+#include <sys/vmspace.h>
 
 #include <vm/vm.h>
 #include <vm/vm_param.h>
 #include <machine/md_var.h>
 #include <machine/specialreg.h>
 #include <machine/smp.h>
-#include <machine_base/apic/apicreg.h>
 #include <machine/globaldata.h>
 #include <machine/pmap.h>
 #include <machine/pmap_inval.h>
 
 #include <ddb/ddb.h>
 
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+
 #define PMAP_KEEP_PDIRS
 #ifndef PMAP_SHPGPERPROC
 #define PMAP_SHPGPERPROC 200
 
 #define MINPV 2048
 
+#if !defined(PMAP_DIAGNOSTIC)
+#define PMAP_INLINE __inline
+#else
+#define PMAP_INLINE
+#endif
+
 /*
  * Get PDEs and PTEs for user/kernel address space
  */
 static pd_entry_t *pmap_pde(pmap_t pmap, vm_offset_t va);
 #define pdir_pde(m, v) (m[(vm_offset_t)(v) >> PDRSHIFT])
 
-#define pmap_pde_v(pte)                ((*(pd_entry_t *)pte & PG_V) != 0)
-#define pmap_pte_w(pte)                ((*(pt_entry_t *)pte & PG_W) != 0)
-#define pmap_pte_m(pte)                ((*(pt_entry_t *)pte & PG_M) != 0)
-#define pmap_pte_u(pte)                ((*(pt_entry_t *)pte & PG_A) != 0)
-#define pmap_pte_v(pte)                ((*(pt_entry_t *)pte & PG_V) != 0)
-
+#define pmap_pde_v(pte)                ((*(pd_entry_t *)pte & VPTE_V) != 0)
+#define pmap_pte_w(pte)                ((*(pt_entry_t *)pte & VPTE_WIRED) != 0)
+#define pmap_pte_m(pte)                ((*(pt_entry_t *)pte & VPTE_M) != 0)
+#define pmap_pte_u(pte)                ((*(pt_entry_t *)pte & VPTE_A) != 0)
+#define pmap_pte_v(pte)                ((*(pt_entry_t *)pte & VPTE_V) != 0)
 
 /*
  * Given a map and a machine independent protection code,
@@ -147,35 +156,16 @@ static int protection_codes[8];
 struct pmap kernel_pmap;
 static TAILQ_HEAD(,pmap)       pmap_list = TAILQ_HEAD_INITIALIZER(pmap_list);
 
-vm_paddr_t avail_start;                /* PA of first available physical page */
-vm_paddr_t avail_end;          /* PA of last available physical page */
-vm_offset_t virtual2_start;    /* cutout free area prior to kernel start */
-vm_offset_t virtual2_end;
-vm_offset_t virtual_start;     /* VA of first avail page (after kernel bss) */
-vm_offset_t virtual_end;       /* VA of last avail page (end of kernel AS) */
-vm_offset_t KvaStart;          /* VA start of KVA space */
-vm_offset_t KvaEnd;            /* VA end of KVA space (non-inclusive) */
-vm_offset_t KvaSize;           /* max size of kernel virtual address space */
 static boolean_t pmap_initialized = FALSE;     /* Has pmap_init completed? */
-static int pgeflag;            /* PG_G or-in */
-static int pseflag;            /* PG_PS or-in */
 
 static vm_object_t kptobj;
 
-static int ndmpdp;
-static vm_paddr_t dmaplimit;
 static int nkpt;
-vm_offset_t kernel_vm_end = VM_MIN_KERNEL_ADDRESS;
 
-static uint64_t KPTbase;
-static uint64_t KPTphys;
 static uint64_t        KPDphys;        /* phys addr of kernel level 2 */
-static uint64_t        KPDbase;        /* phys addr of kernel level 2 @ KERNBASE */
-uint64_t KPDPphys;     /* phys addr of kernel level 3 */
-uint64_t KPML4phys;    /* phys addr of kernel level 4 */
+uint64_t               KPDPphys;       /* phys addr of kernel level 3 */
+uint64_t               KPML4phys;      /* phys addr of kernel level 4 */
 
-static uint64_t        DMPDphys;       /* phys addr of direct mapped level 2 */
-static uint64_t        DMPDPphys;      /* phys addr of direct mapped level 3 */
 
 /*
  * Data for the pv entry allocation mechanism
@@ -191,34 +181,25 @@ static struct pv_entry *pvinit;
  * All those kernel PT submaps that BSD is so fond of
  */
 pt_entry_t *CMAP1 = 0, *ptmmap;
-caddr_t CADDR1 = 0, ptvmmap = 0;
+caddr_t CADDR1 = 0;
 static pt_entry_t *msgbufmap;
-struct msgbuf *msgbufp=0;
 
-/*
- * Crashdump maps.
- */
-static pt_entry_t *pt_crashdumpmap;
-static caddr_t crashdumpmap;
-
-extern pt_entry_t *SMPpt;
-extern uint64_t SMPptpa;
-
-#define DISABLE_PSE
+uint64_t KPTphys;
 
+static PMAP_INLINE void        free_pv_entry (pv_entry_t pv);
 static pv_entry_t get_pv_entry (void);
-static void i386_protection_init (void);
-static void create_pagetables(vm_paddr_t *firstaddr);
-static void pmap_remove_all (vm_page_t m);
-static int  pmap_remove_pte (struct pmap *pmap, pt_entry_t *ptq,
-                               vm_offset_t sva, pmap_inval_info_t info);
-static void pmap_remove_page (struct pmap *pmap, 
-                               vm_offset_t va, pmap_inval_info_t info);
-static int  pmap_remove_entry (struct pmap *pmap, vm_page_t m,
-                               vm_offset_t va, pmap_inval_info_t info);
+static void    i386_protection_init (void);
+static __inline void   pmap_clearbit (vm_page_t m, int bit);
+
+static void    pmap_remove_all (vm_page_t m);
+static int pmap_remove_pte (struct pmap *pmap, pt_entry_t *ptq,
+                               vm_offset_t sva);
+static void pmap_remove_page (struct pmap *pmap, vm_offset_t va);
+static int pmap_remove_entry (struct pmap *pmap, vm_page_t m,
+                               vm_offset_t va);
 static boolean_t pmap_testbit (vm_page_t m, int bit);
 static void pmap_insert_entry (pmap_t pmap, vm_offset_t va,
-                               vm_page_t mpte, vm_page_t m);
+               vm_page_t mpte, vm_page_t m);
 
 static vm_page_t pmap_allocpte (pmap_t pmap, vm_offset_t va);
 
@@ -226,28 +207,8 @@ static int pmap_release_free_page (pmap_t pmap, vm_page_t p);
 static vm_page_t _pmap_allocpte (pmap_t pmap, vm_pindex_t ptepindex);
 static pt_entry_t * pmap_pte_quick (pmap_t pmap, vm_offset_t va);
 static vm_page_t pmap_page_lookup (vm_object_t object, vm_pindex_t pindex);
-static int _pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m,
-                               pmap_inval_info_t info);
-static int pmap_unuse_pt (pmap_t, vm_offset_t, vm_page_t, pmap_inval_info_t);
-static vm_offset_t pmap_kmem_choose(vm_offset_t addr);
-
-static unsigned pdir4mb;
-
-/*
- * Move the kernel virtual free pointer to the next
- * 2MB.  This is used to help improve performance
- * by using a large (2MB) page for much of the kernel
- * (.text, .data, .bss)
- */
-static
-vm_offset_t
-pmap_kmem_choose(vm_offset_t addr)
-{
-       vm_offset_t newaddr = addr;
-
-       newaddr = (addr + (NBPDR - 1)) & ~(NBPDR - 1);
-       return newaddr;
-}
+static int pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m);
+static int pmap_unuse_pt (pmap_t, vm_offset_t, vm_page_t);
 
 /*
  * pmap_pte_quick:
@@ -261,48 +222,42 @@ pmap_kmem_choose(vm_offset_t addr)
  */
 static __inline pt_entry_t *pmap_pte(pmap_t pmap, vm_offset_t va);
 
-static
-pt_entry_t *
+static pt_entry_t *
 pmap_pte_quick(pmap_t pmap, vm_offset_t va)
 {
        return pmap_pte(pmap, va);
 }
 
 /* Return a non-clipped PD index for a given VA */
-static __inline
-vm_pindex_t
+static __inline vm_pindex_t
 pmap_pde_pindex(vm_offset_t va)
 {
        return va >> PDRSHIFT;
 }
 
 /* Return various clipped indexes for a given VA */
-static __inline
-vm_pindex_t
+static __inline vm_pindex_t
 pmap_pte_index(vm_offset_t va)
 {
 
        return ((va >> PAGE_SHIFT) & ((1ul << NPTEPGSHIFT) - 1));
 }
 
-static __inline
-vm_pindex_t
+static __inline vm_pindex_t
 pmap_pde_index(vm_offset_t va)
 {
 
        return ((va >> PDRSHIFT) & ((1ul << NPDEPGSHIFT) - 1));
 }
 
-static __inline
-vm_pindex_t
+static __inline vm_pindex_t
 pmap_pdpe_index(vm_offset_t va)
 {
 
        return ((va >> PDPSHIFT) & ((1ul << NPDPEPGSHIFT) - 1));
 }
 
-static __inline
-vm_pindex_t
+static __inline vm_pindex_t
 pmap_pml4e_index(vm_offset_t va)
 {
 
@@ -310,8 +265,7 @@ pmap_pml4e_index(vm_offset_t va)
 }
 
 /* Return a pointer to the PML4 slot that corresponds to a VA */
-static __inline
-pml4_entry_t *
+static __inline pml4_entry_t *
 pmap_pml4e(pmap_t pmap, vm_offset_t va)
 {
 
@@ -319,81 +273,76 @@ pmap_pml4e(pmap_t pmap, vm_offset_t va)
 }
 
 /* Return a pointer to the PDP slot that corresponds to a VA */
-static __inline
-pdp_entry_t *
+static __inline pdp_entry_t *
 pmap_pml4e_to_pdpe(pml4_entry_t *pml4e, vm_offset_t va)
 {
        pdp_entry_t *pdpe;
 
-       pdpe = (pdp_entry_t *)PHYS_TO_DMAP(*pml4e & PG_FRAME);
+       pdpe = (pdp_entry_t *)PHYS_TO_DMAP(*pml4e & VPTE_FRAME);
        return (&pdpe[pmap_pdpe_index(va)]);
 }
 
 /* Return a pointer to the PDP slot that corresponds to a VA */
-static __inline
-pdp_entry_t *
+static __inline pdp_entry_t *
 pmap_pdpe(pmap_t pmap, vm_offset_t va)
 {
        pml4_entry_t *pml4e;
 
        pml4e = pmap_pml4e(pmap, va);
-       if ((*pml4e & PG_V) == 0)
+       if ((*pml4e & VPTE_V) == 0)
                return NULL;
        return (pmap_pml4e_to_pdpe(pml4e, va));
 }
 
 /* Return a pointer to the PD slot that corresponds to a VA */
-static __inline
-pd_entry_t *
+static __inline pd_entry_t *
 pmap_pdpe_to_pde(pdp_entry_t *pdpe, vm_offset_t va)
 {
        pd_entry_t *pde;
 
-       pde = (pd_entry_t *)PHYS_TO_DMAP(*pdpe & PG_FRAME);
+       pde = (pd_entry_t *)PHYS_TO_DMAP(*pdpe & VPTE_FRAME);
        return (&pde[pmap_pde_index(va)]);
 }
 
 /* Return a pointer to the PD slot that corresponds to a VA */
-static __inline
-pd_entry_t *
+static __inline pd_entry_t *
 pmap_pde(pmap_t pmap, vm_offset_t va)
 {
        pdp_entry_t *pdpe;
 
        pdpe = pmap_pdpe(pmap, va);
-       if (pdpe == NULL || (*pdpe & PG_V) == 0)
+       if (pdpe == NULL || (*pdpe & VPTE_V) == 0)
                 return NULL;
        return (pmap_pdpe_to_pde(pdpe, va));
 }
 
 /* Return a pointer to the PT slot that corresponds to a VA */
-static __inline
-pt_entry_t *
+static __inline pt_entry_t *
 pmap_pde_to_pte(pd_entry_t *pde, vm_offset_t va)
 {
        pt_entry_t *pte;
 
-       pte = (pt_entry_t *)PHYS_TO_DMAP(*pde & PG_FRAME);
+       pte = (pt_entry_t *)PHYS_TO_DMAP(*pde & VPTE_FRAME);
        return (&pte[pmap_pte_index(va)]);
 }
 
 /* Return a pointer to the PT slot that corresponds to a VA */
-static __inline
-pt_entry_t *
+static __inline pt_entry_t *
 pmap_pte(pmap_t pmap, vm_offset_t va)
 {
        pd_entry_t *pde;
 
        pde = pmap_pde(pmap, va);
-       if (pde == NULL || (*pde & PG_V) == 0)
+       if (pde == NULL || (*pde & VPTE_V) == 0)
                return NULL;
-       if ((*pde & PG_PS) != 0)        /* compat with i386 pmap_pte() */
+       if ((*pde & VPTE_PS) != 0)      /* compat with i386 pmap_pte() */
                return ((pt_entry_t *)pde);
        return (pmap_pde_to_pte(pde, va));
 }
 
-static __inline
-pt_entry_t *
+
+#if JGV
+PMAP_INLINE pt_entry_t *
 vtopte(vm_offset_t va)
 {
        uint64_t mask = ((1ul << (NPTEPGSHIFT + NPDEPGSHIFT + NPDPEPGSHIFT + NPML4EPGSHIFT)) - 1);
@@ -401,14 +350,32 @@ vtopte(vm_offset_t va)
        return (PTmap + ((va >> PAGE_SHIFT) & mask));
 }
 
-static __inline
-pd_entry_t *
+static __inline pd_entry_t *
 vtopde(vm_offset_t va)
 {
        uint64_t mask = ((1ul << (NPDEPGSHIFT + NPDPEPGSHIFT + NPML4EPGSHIFT)) - 1);
 
        return (PDmap + ((va >> PDRSHIFT) & mask));
 }
+#else
+PMAP_INLINE pt_entry_t *
+vtopte(vm_offset_t va)
+{
+       pt_entry_t *x;
+       x = pmap_pte(&kernel_pmap, va);
+       assert(x != NULL);
+       return x;
+}
+
+static __inline pd_entry_t *
+vtopde(vm_offset_t va)
+{
+       pd_entry_t *x;
+       x = pmap_pde(&kernel_pmap, va);
+       assert(x != NULL);
+       return x;
+}
+#endif
 
 static uint64_t
 allocpages(vm_paddr_t *firstaddr, int n)
@@ -416,129 +383,60 @@ allocpages(vm_paddr_t *firstaddr, int n)
        uint64_t ret;
 
        ret = *firstaddr;
+#if JGV
        bzero((void *)ret, n * PAGE_SIZE);
+#endif
        *firstaddr += n * PAGE_SIZE;
        return (ret);
 }
 
-static
 void
-create_pagetables(vm_paddr_t *firstaddr)
+create_pagetables(vm_paddr_t *firstaddr, int64_t ptov_offset)
 {
        int i;
+       pml4_entry_t *KPML4virt;
+       pdp_entry_t *KPDPvirt;
+       pd_entry_t *KPDvirt;
+       pt_entry_t *KPTvirt;
+       int kpml4i = pmap_pml4e_index(ptov_offset);
+       int kpdpi = pmap_pdpe_index(ptov_offset);
 
-       /* we are running (mostly) V=P at this point */
 
        /* Allocate pages */
-       KPTbase = allocpages(firstaddr, NKPT);
-       KPTphys = allocpages(firstaddr, NKPT);
        KPML4phys = allocpages(firstaddr, 1);
        KPDPphys = allocpages(firstaddr, NKPML4E);
-
-       /*
-        * Calculate the page directory base for KERNBASE,
-        * that is where we start populating the page table pages.
-        * Basically this is the end - 2.
-        */
        KPDphys = allocpages(firstaddr, NKPDPE);
-       KPDbase = KPDphys + ((NKPDPE - (NPDPEPG - KPDPI)) << PAGE_SHIFT);
+       KPTphys = allocpages(firstaddr, NKPT);
 
-       ndmpdp = (ptoa(Maxmem) + NBPDP - 1) >> PDPSHIFT;
-       if (ndmpdp < 4)         /* Minimum 4GB of dirmap */
-               ndmpdp = 4;
-       DMPDPphys = allocpages(firstaddr, NDMPML4E);
-       if ((amd_feature & AMDID_PAGE1GB) == 0)
-               DMPDphys = allocpages(firstaddr, ndmpdp);
-       dmaplimit = (vm_paddr_t)ndmpdp << PDPSHIFT;
+       KPML4virt = (pml4_entry_t *)PHYS_TO_DMAP(KPML4phys);
+       KPDPvirt = (pdp_entry_t *)PHYS_TO_DMAP(KPDPphys);
+       KPDvirt = (pd_entry_t *)PHYS_TO_DMAP(KPDphys);
+       KPTvirt = (pt_entry_t *)PHYS_TO_DMAP(KPTphys);
 
-       /*
-        * Fill in the underlying page table pages for the area around
-        * KERNBASE.  This remaps low physical memory to KERNBASE.
-        *
-        * Read-only from zero to physfree
-        * XXX not fully used, underneath 2M pages
-        */
-       for (i = 0; (i << PAGE_SHIFT) < *firstaddr; i++) {
-               ((pt_entry_t *)KPTbase)[i] = i << PAGE_SHIFT;
-               ((pt_entry_t *)KPTbase)[i] |= PG_RW | PG_V | PG_G;
-       }
+       bzero(KPML4virt, 1 * PAGE_SIZE);
+       bzero(KPDPvirt, NKPML4E * PAGE_SIZE);
+       bzero(KPDvirt, NKPDPE * PAGE_SIZE);
+       bzero(KPTvirt, NKPT * PAGE_SIZE);
 
-       /*
-        * Now map the initial kernel page tables.  One block of page
-        * tables is placed at the beginning of kernel virtual memory,
-        * and another block is placed at KERNBASE to map the kernel binary,
-        * data, bss, and initial pre-allocations.
-        */
+       /* Now map the page tables at their location within PTmap */
        for (i = 0; i < NKPT; i++) {
-               ((pd_entry_t *)KPDbase)[i] = KPTbase + (i << PAGE_SHIFT);
-               ((pd_entry_t *)KPDbase)[i] |= PG_RW | PG_V;
-       }
-       for (i = 0; i < NKPT; i++) {
-               ((pd_entry_t *)KPDphys)[i] = KPTphys + (i << PAGE_SHIFT);
-               ((pd_entry_t *)KPDphys)[i] |= PG_RW | PG_V;
-       }
-
-       /*
-        * Map from zero to end of allocations using 2M pages as an
-        * optimization.  This will bypass some of the KPTBase pages
-        * above in the KERNBASE area.
-        */
-       for (i = 0; (i << PDRSHIFT) < *firstaddr; i++) {
-               ((pd_entry_t *)KPDbase)[i] = i << PDRSHIFT;
-               ((pd_entry_t *)KPDbase)[i] |= PG_RW | PG_V | PG_PS | PG_G;
+               KPDvirt[i] = KPTphys + (i << PAGE_SHIFT);
+               KPDvirt[i] |= VPTE_R | VPTE_W | VPTE_V;
        }
 
-       /*
-        * And connect up the PD to the PDP.  The kernel pmap is expected
-        * to pre-populate all of its PDs.  See NKPDPE in vmparam.h.
-        */
+       /* And connect up the PD to the PDP */
        for (i = 0; i < NKPDPE; i++) {
-               ((pdp_entry_t *)KPDPphys)[NPDPEPG - NKPDPE + i] =
-                               KPDphys + (i << PAGE_SHIFT);
-               ((pdp_entry_t *)KPDPphys)[NPDPEPG - NKPDPE + i] |=
-                               PG_RW | PG_V | PG_U;
-       }
-
-       /* Now set up the direct map space using either 2MB or 1GB pages */
-       /* Preset PG_M and PG_A because demotion expects it */
-       if ((amd_feature & AMDID_PAGE1GB) == 0) {
-               for (i = 0; i < NPDEPG * ndmpdp; i++) {
-                       ((pd_entry_t *)DMPDphys)[i] = (vm_paddr_t)i << PDRSHIFT;
-                       ((pd_entry_t *)DMPDphys)[i] |= PG_RW | PG_V | PG_PS |
-                           PG_G | PG_M | PG_A;
-               }
-               /* And the direct map space's PDP */
-               for (i = 0; i < ndmpdp; i++) {
-                       ((pdp_entry_t *)DMPDPphys)[i] = DMPDphys +
-                           (i << PAGE_SHIFT);
-                       ((pdp_entry_t *)DMPDPphys)[i] |= PG_RW | PG_V | PG_U;
-               }
-       } else {
-               for (i = 0; i < ndmpdp; i++) {
-                       ((pdp_entry_t *)DMPDPphys)[i] =
-                           (vm_paddr_t)i << PDPSHIFT;
-                       ((pdp_entry_t *)DMPDPphys)[i] |= PG_RW | PG_V | PG_PS |
-                           PG_G | PG_M | PG_A;
-               }
+               KPDPvirt[i + kpdpi] = KPDphys + (i << PAGE_SHIFT);
+               KPDPvirt[i + kpdpi] |= VPTE_R | VPTE_W | VPTE_V;
        }
 
        /* And recursively map PML4 to itself in order to get PTmap */
-       ((pdp_entry_t *)KPML4phys)[PML4PML4I] = KPML4phys;
-       ((pdp_entry_t *)KPML4phys)[PML4PML4I] |= PG_RW | PG_V | PG_U;
-
-       /* Connect the Direct Map slot up to the PML4 */
-       ((pdp_entry_t *)KPML4phys)[DMPML4I] = DMPDPphys;
-       ((pdp_entry_t *)KPML4phys)[DMPML4I] |= PG_RW | PG_V | PG_U;
+       KPML4virt[PML4PML4I] = KPML4phys;
+       KPML4virt[PML4PML4I] |= VPTE_R | VPTE_W | VPTE_V;
 
        /* Connect the KVA slot up to the PML4 */
-       ((pdp_entry_t *)KPML4phys)[KPML4I] = KPDPphys;
-       ((pdp_entry_t *)KPML4phys)[KPML4I] |= PG_RW | PG_V | PG_U;
-}
-
-void
-init_paging(vm_paddr_t *firstaddr)
-{
-       create_pagetables(firstaddr);
+       KPML4virt[kpml4i] = KPDPphys;
+       KPML4virt[kpml4i] |= VPTE_R | VPTE_W | VPTE_V;
 }
 
 /*
@@ -552,35 +450,18 @@ init_paging(vm_paddr_t *firstaddr)
  *     (physical) address starting relative to 0]
  */
 void
-pmap_bootstrap(vm_paddr_t *firstaddr)
+pmap_bootstrap(vm_paddr_t *firstaddr, int64_t ptov_offset)
 {
        vm_offset_t va;
        pt_entry_t *pte;
-       struct mdglobaldata *gd;
-       int pg;
-
-       KvaStart = VM_MIN_KERNEL_ADDRESS;
-       KvaEnd = VM_MAX_KERNEL_ADDRESS;
-       KvaSize = KvaEnd - KvaStart;
-
-       avail_start = *firstaddr;
 
        /*
         * Create an initial set of page tables to run the kernel in.
         */
-       create_pagetables(firstaddr);
-
-       virtual2_start = KvaStart;
-       virtual2_end = PTOV_OFFSET;
-
-       virtual_start = (vm_offset_t) PTOV_OFFSET + *firstaddr;
-       virtual_start = pmap_kmem_choose(virtual_start);
-
-       virtual_end = VM_MAX_KERNEL_ADDRESS;
+       create_pagetables(firstaddr, ptov_offset);
 
-       /* XXX do %cr0 as well */
-       load_cr4(rcr4() | CR4_PGE | CR4_PSE);
-       load_cr3(KPML4phys);
+       virtual_start = KvaStart + *firstaddr;
+       virtual_end = KvaEnd;
 
        /*
         * Initialize protection array.
@@ -592,9 +473,9 @@ pmap_bootstrap(vm_paddr_t *firstaddr)
         * pmap_create, which is unlikely to work correctly at this part of
         * the boot sequence (XXX and which no longer exists).
         */
-       kernel_pmap.pm_pml4 = (pdp_entry_t *) (PTOV_OFFSET + KPML4phys);
+       kernel_pmap.pm_pml4 = (pml4_entry_t *)PHYS_TO_DMAP(KPML4phys);
        kernel_pmap.pm_count = 1;
-       kernel_pmap.pm_active = (cpumask_t)-1 & ~CPUMASK_LOCK;
+       kernel_pmap.pm_active = (cpumask_t)-1;  /* don't allow deactivation */
        TAILQ_INIT(&kernel_pmap.pm_pvlist);
        nkpt = NKPT;
 
@@ -606,21 +487,19 @@ pmap_bootstrap(vm_paddr_t *firstaddr)
        v = (c)va; va += ((n)*PAGE_SIZE); p = pte; pte += (n);
 
        va = virtual_start;
-#ifdef JG
-       pte = (pt_entry_t *) pmap_pte(&kernel_pmap, va);
-#else
-       pte = vtopte(va);
-#endif
+       pte = pmap_pte(&kernel_pmap, va);
 
        /*
         * CMAP1/CMAP2 are used for zeroing and copying pages.
         */
        SYSMAP(caddr_t, CMAP1, CADDR1, 1)
 
+#if JGV
        /*
         * Crashdump maps.
         */
        SYSMAP(caddr_t, pt_crashdumpmap, crashdumpmap, MAXDUMPPGS);
+#endif
 
        /*
         * ptvmmap is used for reading arbitrary physical pages via
@@ -639,102 +518,9 @@ pmap_bootstrap(vm_paddr_t *firstaddr)
 
        *CMAP1 = 0;
 
-       /*
-        * PG_G is terribly broken on SMP because we IPI invltlb's in some
-        * cases rather then invl1pg.  Actually, I don't even know why it
-        * works under UP because self-referential page table mappings
-        */
-#ifdef SMP
-       pgeflag = 0;
-#else
-       if (cpu_feature & CPUID_PGE)
-               pgeflag = PG_G;
-#endif
-       
-/*
- * Initialize the 4MB page size flag
- */
-       pseflag = 0;
-/*
- * The 4MB page version of the initial
- * kernel page mapping.
- */
-       pdir4mb = 0;
-
-#if !defined(DISABLE_PSE)
-       if (cpu_feature & CPUID_PSE) {
-               pt_entry_t ptditmp;
-               /*
-                * Note that we have enabled PSE mode
-                */
-               pseflag = PG_PS;
-               ptditmp = *(PTmap + x86_64_btop(KERNBASE));
-               ptditmp &= ~(NBPDR - 1);
-               ptditmp |= PG_V | PG_RW | PG_PS | PG_U | pgeflag;
-               pdir4mb = ptditmp;
-
-#ifndef SMP
-               /*
-                * Enable the PSE mode.  If we are SMP we can't do this
-                * now because the APs will not be able to use it when
-                * they boot up.
-                */
-               load_cr4(rcr4() | CR4_PSE);
-
-               /*
-                * We can do the mapping here for the single processor
-                * case.  We simply ignore the old page table page from
-                * now on.
-                */
-               /*
-                * For SMP, we still need 4K pages to bootstrap APs,
-                * PSE will be enabled as soon as all APs are up.
-                */
-               PTD[KPTDI] = (pd_entry_t)ptditmp;
-               cpu_invltlb();
-#endif
-       }
-#endif
-#ifdef SMP
-       if (cpu_apic_address == 0)
-               panic("pmap_bootstrap: no local apic!");
-#endif
-
-       /*
-        * We need to finish setting up the globaldata page for the BSP.
-        * locore has already populated the page table for the mdglobaldata
-        * portion.
-        */
-       pg = MDGLOBALDATA_BASEALLOC_PAGES;
-       gd = &CPU_prvspace[0].mdglobaldata;
-       gd->gd_CMAP1 = &SMPpt[pg + 0];
-       gd->gd_CMAP2 = &SMPpt[pg + 1];
-       gd->gd_CMAP3 = &SMPpt[pg + 2];
-       gd->gd_PMAP1 = &SMPpt[pg + 3];
-       gd->gd_CADDR1 = CPU_prvspace[0].CPAGE1;
-       gd->gd_CADDR2 = CPU_prvspace[0].CPAGE2;
-       gd->gd_CADDR3 = CPU_prvspace[0].CPAGE3;
-       gd->gd_PADDR1 = (pt_entry_t *)CPU_prvspace[0].PPAGE1;
-
        cpu_invltlb();
 }
 
-#ifdef SMP
-/*
- * Set 4mb pdir for mp startup
- */
-void
-pmap_set_opt(void)
-{
-       if (pseflag && (cpu_feature & CPUID_PSE)) {
-               load_cr4(rcr4() | CR4_PSE);
-               if (pdir4mb && mycpu->gd_cpuid == 0) {  /* only on BSP */
-                       cpu_invltlb();
-               }
-       }
-}
-#endif
-
 /*
  *     Initialize the pmap module.
  *     Called by vm_init, to initialize any structures that the pmap
@@ -783,9 +569,6 @@ pmap_init(void)
         * Now it is safe to enable pv_table recording.
         */
        pmap_initialized = TRUE;
-#ifdef SMP
-       lapic = pmap_mapdev_uncacheable(cpu_apic_address, sizeof(struct LAPIC));
-#endif
 }
 
 /*
@@ -810,33 +593,20 @@ pmap_init2(void)
  * Low level helper routines.....
  ***************************************************/
 
-#if defined(PMAP_DIAGNOSTIC)
-
 /*
- * This code checks for non-writeable/modified pages.
- * This should be an invalid condition.
+ * The modification bit is not tracked for any pages in this range. XXX
+ * such pages in this maps should always use pmap_k*() functions and not
+ * be managed anyhow.
+ *
+ * XXX User and kernel address spaces are independant for virtual kernels,
+ * this function only applies to the kernel pmap.
  */
-static
-int
-pmap_nw_modified(pt_entry_t pte)
+static int
+pmap_track_modified(pmap_t pmap, vm_offset_t va)
 {
-       if ((pte & (PG_M|PG_RW)) == PG_M)
+       if (pmap != &kernel_pmap)
                return 1;
-       else
-               return 0;
-}
-#endif
-
-
-/*
- * this routine defines the region(s) of memory that should
- * not be tested for the modified bit.
- */
-static __inline
-int
-pmap_track_modified(vm_offset_t va)
-{
-       if ((va < clean_sva) || (va >= clean_eva)) 
+       if ((va < clean_sva) || (va >= clean_eva))
                return 1;
        else
                return 0;
@@ -846,11 +616,8 @@ pmap_track_modified(vm_offset_t va)
  * pmap_extract:
  *
  *     Extract the physical page address associated with the map/VA pair.
- *
- *     This function may not be called from an interrupt if the pmap is
- *     not kernel_pmap.
  */
-vm_paddr_t 
+vm_paddr_t
 pmap_extract(pmap_t pmap, vm_offset_t va)
 {
        vm_paddr_t rtval;
@@ -862,11 +629,12 @@ pmap_extract(pmap_t pmap, vm_offset_t va)
        if (pdep != NULL) {
                pde = *pdep;
                if (pde) {
-                       if ((pde & PG_PS) != 0) {
+                       if ((pde & VPTE_PS) != 0) {
+                               /* JGV */
                                rtval = (pde & PG_PS_FRAME) | (va & PDRMASK);
                        } else {
                                pte = pmap_pde_to_pte(pdep, va);
-                               rtval = (*pte & PG_FRAME) | (va & PAGE_MASK);
+                               rtval = (*pte & VPTE_FRAME) | (va & PAGE_MASK);
                        }
                }
        }
@@ -885,11 +653,19 @@ pmap_kextract(vm_offset_t va)
        pd_entry_t pde;
        vm_paddr_t pa;
 
+       KKASSERT(va >= KvaStart && va < KvaEnd);
+
+       /*
+        * The DMAP region is not included in [KvaStart, KvaEnd)
+        */
+#if 0
        if (va >= DMAP_MIN_ADDRESS && va < DMAP_MAX_ADDRESS) {
                pa = DMAP_TO_PHYS(va);
        } else {
+#endif
                pde = *vtopde(va);
-               if (pde & PG_PS) {
+               if (pde & VPTE_PS) {
+                       /* JGV */
                        pa = (pde & PG_PS_FRAME) | (va & PDRMASK);
                } else {
                        /*
@@ -901,9 +677,11 @@ pmap_kextract(vm_offset_t va)
                         * promotion.
                         */
                        pa = *pmap_pde_to_pte(&pde, va);
-                       pa = (pa & PG_FRAME) | (va & PAGE_MASK);
+                       pa = (pa & VPTE_FRAME) | (va & PAGE_MASK);
                }
+#if 0
        }
+#endif
        return pa;
 }
 
@@ -912,33 +690,33 @@ pmap_kextract(vm_offset_t va)
  ***************************************************/
 
 /*
- * Routine: pmap_kenter
- * Function:
- *     Add a wired page to the KVA
- *     NOTE! note that in order for the mapping to take effect -- you
- *     should do an invltlb after doing the pmap_kenter().
+ * Enter a mapping into kernel_pmap.  Mappings created in this fashion
+ * are not managed.  Mappings must be immediately accessible on all cpus.
+ *
+ * Call pmap_inval_pte() to invalidate the virtual pte and clean out the
+ * real pmap and handle related races before storing the new vpte.
  */
-void 
+void
 pmap_kenter(vm_offset_t va, vm_paddr_t pa)
 {
        pt_entry_t *pte;
        pt_entry_t npte;
-       pmap_inval_info info;
 
-       pmap_inval_init(&info);
-       npte = pa | PG_RW | PG_V | pgeflag;
+