mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
bitkeeper revision 1.1159.72.2 (413cb4b0nYQ7KFQbxIn6g-4lsRAgbQ)
Add sparse tree for NetBSD.
This commit is contained in:
1 parent
2a632d88f7
commit
3ebb973d50
28 files changed
+20378
No files matched your search
@@ -263,6 +263,33 @@
|
||||
413cb1e5c_Mkxf_X0zimEhTKI_l4DA netbsd-2.0-xen-sparse/mkbuildtree
|
||||
413cb1e5kY_Zil7-b0kI6hvCIxBEYg netbsd-2.0-xen-sparse/nbconfig-xen
|
||||
413cb1e5-58q5doPifcE1Q8ZAgm-JQ netbsd-2.0-xen-sparse/nbmake-xen
|
||||
413cb3b3Cmp02Gj87f3wwu2W9y0gBg netbsd-2.0-xen-sparse/sys/arch/xen/conf/XEN
|
||||
413cb3b3aUP9GmUWqHWQ2SRp1qXnqQ netbsd-2.0-xen-sparse/sys/arch/xen/conf/files.xen
|
||||
413cb3b3pZuLKElEpQwX1C-3hLW4qA netbsd-2.0-xen-sparse/sys/arch/xen/i386/autoconf.c
|
||||
413cb3b34ui1cCGaSqIeLiBgMp-PDw netbsd-2.0-xen-sparse/sys/arch/xen/i386/gdt.c
|
||||
413cb3b3i11i2GVGn0YGlRbM3ifbPQ netbsd-2.0-xen-sparse/sys/arch/xen/i386/hypervisor_machdep.c
|
||||
413cb3b3FgMboWw-Pm3XdbBFSlZl_g netbsd-2.0-xen-sparse/sys/arch/xen/i386/locore.S
|
||||
413cb3b4ABCSfkHRmbsWfnZNG28nBA netbsd-2.0-xen-sparse/sys/arch/xen/i386/machdep.c
|
||||
413cb3b4bvVJ7UlliMSH60J4uIb9kA netbsd-2.0-xen-sparse/sys/arch/xen/i386/pmap.c
|
||||
413cb3b4aKd9SUY-OzUiTF0Gb9ve9w netbsd-2.0-xen-sparse/sys/arch/xen/i386/sys_machdep.c
|
||||
413cb3b4jUtWl-sP493PvB27o-Iltw netbsd-2.0-xen-sparse/sys/arch/xen/i386/vector.S
|
||||
413cb3b4ElwwoJEmmzflV0HgK5Qxcg netbsd-2.0-xen-sparse/sys/arch/xen/i386/xen_machdep.c
|
||||
413cb3b4k9OVRCxuSdhKt-2baTp_Yg netbsd-2.0-xen-sparse/sys/arch/xen/include/frameasm.h
|
||||
413cb3b4bRsqiHQLTKEZk4-zOksf8A netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h
|
||||
413cb3b4OqY83qI8GztIZGADpvrpSw netbsd-2.0-xen-sparse/sys/arch/xen/include/if_xennetvar.h
|
||||
413cb3b42GG0LffraTnpZKlSUq57wg netbsd-2.0-xen-sparse/sys/arch/xen/include/pmap.h
|
||||
413cb3b4F0ArkWVBRyspkw7ivfXihg netbsd-2.0-xen-sparse/sys/arch/xen/include/xen.h
|
||||
413cb3b4ullQud70n4JClwoEEUBh8Q netbsd-2.0-xen-sparse/sys/arch/xen/include/xenfunc.h
|
||||
413cb3b4y1Ffq8BOhbdSpn-fGmKuEg netbsd-2.0-xen-sparse/sys/arch/xen/include/xenpmap.h
|
||||
413cb3b4uXOFcT56QuLt1fcDrB-4Zg netbsd-2.0-xen-sparse/sys/arch/xen/x86/bus_space.c
|
||||
413cb3b4hIffjrKn3zhVqJmH6ueB3Q netbsd-2.0-xen-sparse/sys/arch/xen/xen/clock.c
|
||||
413cb3b4eNdRIasCoQIuX4Nu39Dlqw netbsd-2.0-xen-sparse/sys/arch/xen/xen/hypervisor.c
|
||||
413cb3b40DLJLbX_ZUIULB0JFjBuaw netbsd-2.0-xen-sparse/sys/arch/xen/xen/if_xennet.c
|
||||
413cb3b46JnvK1UurZAubeQoFg1W-w netbsd-2.0-xen-sparse/sys/arch/xen/xen/xbd.c
|
||||
413cb3b5rIKB3TbyhK3pbNyVkYysqA netbsd-2.0-xen-sparse/sys/arch/xen/xen/xen_debug.c
|
||||
413cb3b5eKxnzoodEqaWn2wrPnHWnA netbsd-2.0-xen-sparse/sys/arch/xen/xen/xencons.c
|
||||
413cb3b5F56TvQWAmO5TsuzhtzLFPQ netbsd-2.0-xen-sparse/sys/arch/xen/xen/xenkbc.c
|
||||
413cb3b53nyOv1OIeDSsCXhBFDXvJA netbsd-2.0-xen-sparse/sys/nfs/files.nfs
|
||||
40e1b09db5mN69Ijj0X_Eol-S7dXiw tools/Make.defs
|
||||
3f776bd1Hy9rn69ntXBhPReUFw9IEA tools/Makefile
|
||||
4124b307nRyK3dhn1hAsvrY76NuV3g tools/check/Makefile
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
# $NetBSD: XEN,v 1.1.2.2 2004/07/15 20:19:34 he Exp $
|
||||
|
||||
include "arch/xen/conf/std.xen"
|
||||
|
||||
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
|
||||
|
||||
#options UVMHIST
|
||||
#options UVMHIST_PRINT
|
||||
#options SYSCALL_DEBUG
|
||||
|
||||
maxusers 32 # estimated number of users
|
||||
|
||||
#
|
||||
options XEN
|
||||
#options DOM0OPS
|
||||
options HZ=50
|
||||
|
||||
#options I586_CPU
|
||||
options I686_CPU
|
||||
|
||||
#options VM86 # virtual 8086 emulation
|
||||
#options USER_LDT # user-settable LDT; used by WINE
|
||||
|
||||
#options MTRR # memory-type range register syscall support
|
||||
|
||||
#options CONSDEVNAME="\"xencons\""
|
||||
#options CONS_OVERRIDE
|
||||
|
||||
options INSECURE # disable kernel security levels - X needs this
|
||||
|
||||
options RTC_OFFSET=0 # hardware clock is this many mins. west of GMT
|
||||
#options NTP # NTP phase/frequency locked loop
|
||||
|
||||
options KTRACE # system call tracing via ktrace(1)
|
||||
#options SYSTRACE # system call vetting via systrace(1)
|
||||
|
||||
options SYSVMSG # System V-like message queues
|
||||
options SYSVSEM # System V-like semaphores
|
||||
#options SEMMNI=10 # number of semaphore identifiers
|
||||
#options SEMMNS=60 # number of semaphores in system
|
||||
#options SEMUME=10 # max number of undo entries per process
|
||||
#options SEMMNU=30 # number of undo structures in system
|
||||
options SYSVSHM # System V-like memory sharing
|
||||
#options SHMMAXPGS=2048 # 2048 pages is the default
|
||||
options P1003_1B_SEMAPHORE # p1003.1b semaphore support
|
||||
|
||||
options LKM # loadable kernel modules
|
||||
|
||||
options USERCONF # userconf(4) support
|
||||
options SYSCTL_INCLUDE_DESCR # Include sysctl descriptions in kernel
|
||||
|
||||
# Diagnostic/debugging support options
|
||||
options DIAGNOSTIC # expensive kernel consistency checks
|
||||
options DEBUG # expensive debugging checks/support
|
||||
options KMEMSTATS # kernel memory statistics (vmstat -m)
|
||||
options DDB # in-kernel debugger
|
||||
options DDB_ONPANIC=1 # see also sysctl(8): `ddb.onpanic'
|
||||
options DDB_HISTORY_SIZE=512 # enable history editing in DDB
|
||||
#options KGDB # remote debugger
|
||||
#options KGDB_DEVNAME="\"com\"",KGDB_DEVADDR=0x2f8,KGDB_DEVRATE=57600
|
||||
makeoptions DEBUG="-g" # compile full symbol table
|
||||
|
||||
#options COMPAT_14 # NetBSD 1.4
|
||||
#options COMPAT_15 # NetBSD 1.5
|
||||
options COMPAT_16 # NetBSD 1.6
|
||||
|
||||
##options COMPAT_LINUX # binary compatibility with Linux
|
||||
#options COMPAT_FREEBSD # binary compatibility with FreeBSD
|
||||
#options COMPAT_MACH # binary compatibility with Mach binaries
|
||||
#options COMPAT_DARWIN # binary compatibility with Darwin binaries
|
||||
#options EXEC_MACHO # exec MACH-O binaries
|
||||
#options COMPAT_PECOFF # kernel support to run Win32 apps
|
||||
|
||||
file-system FFS # UFS
|
||||
file-system EXT2FS # second extended file system (linux)
|
||||
#file-system LFS # log-structured file system
|
||||
#file-system MFS # memory file system
|
||||
file-system NFS # Network File System client
|
||||
#file-system NTFS # Windows/NT file system (experimental)
|
||||
#file-system CD9660 # ISO 9660 + Rock Ridge file system
|
||||
#file-system MSDOSFS # MS-DOS file system
|
||||
file-system FDESC # /dev/fd
|
||||
file-system KERNFS # /kern
|
||||
file-system NULLFS # loopback file system
|
||||
#file-system OVERLAY # overlay file system
|
||||
#file-system PORTAL # portal filesystem (still experimental)
|
||||
file-system PROCFS # /proc
|
||||
#file-system UMAPFS # NULLFS + uid and gid remapping
|
||||
#file-system UNION # union file system
|
||||
#file-system SMBFS # experimental - CIFS; also needs nsmb (below)
|
||||
|
||||
#options QUOTA # UFS quotas
|
||||
#options SOFTDEP # FFS soft updates support.
|
||||
#options NFSSERVER # Network File System server
|
||||
|
||||
options GATEWAY # packet forwarding
|
||||
options INET # IP + ICMP + TCP + UDP
|
||||
options INET6 # IPV6
|
||||
options IPSEC # IP security
|
||||
options IPSEC_ESP # IP security (encryption part; define w/IPSEC)
|
||||
options MROUTING # IP multicast routing
|
||||
options PFIL_HOOKS # pfil(9) packet filter hooks
|
||||
options IPFILTER_LOG # ipmon(8) log support
|
||||
|
||||
options NFS_BOOT_DHCP,NFS_BOOT_BOOTPARAM,NFS_BOOT_BOOTSTATIC
|
||||
#options NFS_BOOTSTATIC_MYIP="\"169.254.1.2\""
|
||||
#options NFS_BOOTSTATIC_GWIP="\"169.254.1.1\""
|
||||
#options NFS_BOOTSTATIC_MASK="\"255.255.255.0\""
|
||||
#options NFS_BOOTSTATIC_SERVADDR="\"169.254.1.1\""
|
||||
#options NFS_BOOTSTATIC_SERVER="\"server:/path/to/root\""
|
||||
|
||||
options WSEMUL_VT100 # VT100 / VT220 emulation
|
||||
options WS_KERNEL_FG=WSCOL_GREEN
|
||||
options WSDISPLAY_COMPAT_PCVT # emulate some ioctls
|
||||
options WSDISPLAY_COMPAT_SYSCONS # emulate some ioctls
|
||||
options WSDISPLAY_COMPAT_USL # VT handling
|
||||
options WSDISPLAY_COMPAT_RAWKBD # can get raw scancodes
|
||||
options WSDISPLAY_DEFAULTSCREENS=4
|
||||
options PCDISPLAY_SOFTCURSOR
|
||||
|
||||
config netbsd root on ? type ?
|
||||
#config netbsd root on wd0a type ffs
|
||||
#config netbsd root on xennet0 type nfs
|
||||
|
||||
mainbus0 at root
|
||||
|
||||
cpu* at mainbus?
|
||||
|
||||
hypervisor* at mainbus? # Xen hypervisor
|
||||
|
||||
npx0 at hypervisor? # x86 math coprocessor
|
||||
|
||||
xencons* at hypervisor? # Xen virtual console
|
||||
xennet* at hypervisor? # Xen virtual network interface
|
||||
|
||||
#xbd* at hypervisor? # Xen virtual block device
|
||||
#wd* at hypervisor? # Xen vbd (wd identity)
|
||||
#sd* at hypervisor? # Xen vbd (sd identity)
|
||||
#cd* at hypervisor? # Xen vbd (cd identity)
|
||||
|
||||
#xenkbc* at hypervisor? # Xen Keyboard/Mouse Interface
|
||||
#pckbd* at xenkbc? # Keyboard
|
||||
#vga* at hypervisor? # Xen VGA display
|
||||
#pms* at xenkbc? # PS/2 Mouse for wsmouse
|
||||
|
||||
#wskbd* at pckbd? console ?
|
||||
#wsdisplay* at vga? console ?
|
||||
#wsmouse* at pms? mux 0
|
||||
|
||||
|
||||
include "arch/xen/conf/GENERIC.local"
|
||||
|
||||
|
||||
pseudo-device ccd 4 # concatenated/striped disk devices
|
||||
#pseudo-device cgd 4 # cryptographic disk devices
|
||||
#pseudo-device md 1 # memory disk device (ramdisk)
|
||||
#pseudo-device vnd 4 # disk-like interface to files
|
||||
|
||||
pseudo-device bpfilter 8 # Berkeley packet filter
|
||||
pseudo-device ipfilter # IP filter (firewall) and NAT
|
||||
pseudo-device loop # network loopback
|
||||
#pseudo-device tun 2 # network tunneling over tty
|
||||
#pseudo-device gre 2 # generic L3 over IP tunnel
|
||||
#pseudo-device gif 4 # IPv[46] over IPv[46] tunnel (RFC1933)
|
||||
#pseudo-device faith 1 # IPv[46] tcp relay translation i/f
|
||||
#pseudo-device stf 1 # 6to4 IPv6 over IPv4 encapsulation
|
||||
#pseudo-device vlan # IEEE 802.1q encapsulation
|
||||
#pseudo-device bridge # simple inter-network bridging
|
||||
|
||||
pseudo-device pty # pseudo-terminals
|
||||
pseudo-device rnd # /dev/random and in-kernel generator
|
||||
pseudo-device clockctl # user control of clock subsystem
|
||||
|
||||
pseudo-device wsmux # mouse & keyboard multiplexor
|
||||
pseudo-device wsfont
|
||||
pseudo-device ksyms # /dev/ksyms
|
||||
@@ -0,0 +1,232 @@
|
||||
# $NetBSD: files.xen,v 1.3.2.1 2004/05/22 15:59:02 he Exp $
|
||||
# NetBSD: files.x86,v 1.10 2003/10/08 17:30:00 bouyer Exp
|
||||
# NetBSD: files.i386,v 1.254 2004/03/25 23:32:10 jmc Exp
|
||||
|
||||
maxpartitions 8
|
||||
|
||||
maxusers 2 16 128
|
||||
|
||||
# Processor type options.
|
||||
defflag opt_cputype.h I686_CPU
|
||||
|
||||
# delay before cpu_reset() for reboot.
|
||||
defparam CPURESET_DELAY
|
||||
|
||||
# No unmapped page below kernel stack
|
||||
defflag NOREDZONE
|
||||
|
||||
# Beep on halt
|
||||
defflag opt_beep.h BEEP_ONHALT
|
||||
defparam opt_beep.h BEEP_ONHALT_COUNT
|
||||
defparam opt_beep.h BEEP_ONHALT_PITCH BEEP_ONHALT_PERIOD
|
||||
|
||||
file arch/xen/i386/autoconf.c
|
||||
file arch/i386/i386/db_dbgreg.S ddb | kstack_check_dr0
|
||||
file arch/i386/i386/db_disasm.c ddb
|
||||
file arch/i386/i386/db_interface.c ddb
|
||||
file arch/i386/i386/db_memrw.c ddb | kgdb
|
||||
file arch/i386/i386/db_trace.c ddb
|
||||
file kern/subr_disk_mbr.c disk
|
||||
file arch/xen/i386/gdt.c
|
||||
file arch/xen/i386/hypervisor_machdep.c
|
||||
file arch/i386/i386/in_cksum.S inet | inet6
|
||||
file arch/i386/i386/ipkdb_glue.c ipkdb
|
||||
file arch/i386/i386/kgdb_machdep.c kgdb
|
||||
file arch/xen/i386/machdep.c
|
||||
file arch/xen/i386/identcpu.c
|
||||
file arch/i386/i386/math_emulate.c math_emulate
|
||||
file arch/i386/i386/mem.c
|
||||
file kern/kern_microtime.c i586_cpu | i686_cpu
|
||||
file arch/i386/i386/mtrr_k6.c mtrr
|
||||
file netns/ns_cksum.c ns
|
||||
file arch/xen/i386/pmap.c
|
||||
file arch/i386/i386/process_machdep.c
|
||||
file arch/i386/i386/procfs_machdep.c procfs
|
||||
file arch/xen/i386/sys_machdep.c
|
||||
file arch/i386/i386/syscall.c
|
||||
file arch/xen/i386/trap.c
|
||||
file arch/i386/i386/vm_machdep.c
|
||||
file arch/xen/i386/xen_machdep.c
|
||||
|
||||
file arch/xen/xen/xen_debug.c
|
||||
|
||||
file arch/xen/xen/clock.c
|
||||
file arch/xen/xen/evtchn.c
|
||||
file arch/xen/xen/ctrl_if.c
|
||||
|
||||
file dev/cons.c
|
||||
|
||||
file arch/i386/i386/mptramp.S multiprocessor
|
||||
file arch/i386/i386/ipifuncs.c multiprocessor
|
||||
|
||||
file arch/i386/i386/pmc.c perfctrs
|
||||
|
||||
file crypto/des/arch/i386/des_enc.S des
|
||||
file crypto/des/arch/i386/des_cbc.S des
|
||||
|
||||
file crypto/blowfish/arch/i386/bf_enc.S blowfish
|
||||
file crypto/blowfish/arch/i386/bf_cbc.S blowfish & !i386_cpu
|
||||
|
||||
#
|
||||
# Machine-independent SCSI drivers
|
||||
#
|
||||
|
||||
#xxx include "dev/scsipi/files.scsipi"
|
||||
|
||||
#
|
||||
# Machine-independent ATA drivers
|
||||
#
|
||||
|
||||
#xxx include "dev/ata/files.ata"
|
||||
|
||||
# Memory Disk for install floppy
|
||||
file dev/md_root.c memory_disk_hooks
|
||||
|
||||
#
|
||||
define mainbus { [apid = -1] }
|
||||
|
||||
file arch/x86/x86/bus_dma.c
|
||||
file arch/xen/x86/bus_space.c
|
||||
file arch/x86/x86/cacheinfo.c
|
||||
file arch/xen/x86/consinit.c
|
||||
file arch/xen/x86/intr.c
|
||||
file arch/x86/x86/ipi.c multiprocessor
|
||||
file arch/x86/x86/lock_machdep.c lockdebug
|
||||
file arch/x86/x86/softintr.c
|
||||
|
||||
include "arch/xen/conf/files.compat"
|
||||
|
||||
#
|
||||
# System bus types
|
||||
#
|
||||
|
||||
device mainbus: mainbus
|
||||
attach mainbus at root
|
||||
file arch/xen/i386/mainbus.c mainbus
|
||||
|
||||
# Xen hypervisor
|
||||
device hypervisor { }
|
||||
attach hypervisor at mainbus
|
||||
file arch/xen/xen/hypervisor.c hypervisor needs-flag
|
||||
|
||||
# Numeric Processing Extension; Math Co-processor
|
||||
device npx
|
||||
file arch/xen/i386/npx.c npx needs-flag
|
||||
|
||||
attach npx at hypervisor with npx_hv
|
||||
file arch/xen/i386/npx_hv.c npx_hv
|
||||
|
||||
# Xen console support
|
||||
device xencons: tty
|
||||
attach xencons at hypervisor
|
||||
file arch/xen/xen/xencons.c xencons needs-flag
|
||||
|
||||
include "dev/wscons/files.wscons"
|
||||
include "dev/wsfont/files.wsfont"
|
||||
|
||||
include "dev/pckbport/files.pckbport"
|
||||
|
||||
# CPUS
|
||||
|
||||
define cpu { [apid = -1] }
|
||||
device cpu
|
||||
attach cpu at mainbus
|
||||
file arch/xen/i386/cpu.c cpu
|
||||
|
||||
#
|
||||
# Compatibility modules
|
||||
#
|
||||
|
||||
# VM86 mode
|
||||
file arch/i386/i386/vm86.c vm86
|
||||
|
||||
# VM86 in kernel
|
||||
file arch/i386/i386/kvm86.c kvm86
|
||||
file arch/i386/i386/kvm86call.S kvm86
|
||||
|
||||
# Binary compatibility with previous NetBSD releases (COMPAT_XX)
|
||||
file arch/i386/i386/compat_13_machdep.c compat_13 | compat_aout
|
||||
file arch/i386/i386/compat_16_machdep.c compat_16 | compat_ibcs2
|
||||
|
||||
# SVR4 binary compatibility (COMPAT_SVR4)
|
||||
include "compat/svr4/files.svr4"
|
||||
file arch/i386/i386/svr4_machdep.c compat_svr4
|
||||
file arch/i386/i386/svr4_sigcode.S compat_svr4
|
||||
file arch/i386/i386/svr4_syscall.c compat_svr4
|
||||
|
||||
# MACH binary compatibility (COMPAT_MACH)
|
||||
include "compat/mach/files.mach"
|
||||
file arch/i386/i386/mach_machdep.c compat_mach | compat_darwin
|
||||
file arch/i386/i386/mach_sigcode.S compat_mach | compat_darwin
|
||||
file arch/i386/i386/mach_syscall.c compat_mach | compat_darwin
|
||||
file arch/i386/i386/macho_machdep.c exec_macho
|
||||
|
||||
# DARWIN binary compatibility (COMPAT_DARWIN)
|
||||
include "compat/darwin/files.darwin"
|
||||
file arch/i386/i386/darwin_machdep.c compat_darwin
|
||||
|
||||
# iBCS-2 binary compatibility (COMPAT_IBCS2)
|
||||
include "compat/ibcs2/files.ibcs2"
|
||||
file arch/i386/i386/ibcs2_machdep.c compat_ibcs2
|
||||
file arch/i386/i386/ibcs2_sigcode.S compat_ibcs2
|
||||
file arch/i386/i386/ibcs2_syscall.c compat_ibcs2
|
||||
|
||||
# Linux binary compatibility (COMPAT_LINUX)
|
||||
include "compat/linux/files.linux"
|
||||
include "compat/linux/arch/i386/files.linux_i386"
|
||||
file arch/i386/i386/linux_sigcode.S compat_linux
|
||||
file arch/i386/i386/linux_syscall.c compat_linux
|
||||
file arch/i386/i386/linux_trap.c compat_linux
|
||||
|
||||
# FreeBSD binary compatibility (COMPAT_FREEBSD)
|
||||
include "compat/freebsd/files.freebsd"
|
||||
file arch/i386/i386/freebsd_machdep.c compat_freebsd
|
||||
file arch/i386/i386/freebsd_sigcode.S compat_freebsd
|
||||
file arch/i386/i386/freebsd_syscall.c compat_freebsd
|
||||
|
||||
# a.out binary compatibility (COMPAT_AOUT)
|
||||
include "compat/aout/files.aout"
|
||||
|
||||
# Win32 binary compatibility (COMPAT_PECOFF)
|
||||
include "compat/pecoff/files.pecoff"
|
||||
|
||||
# OSS audio driver compatibility
|
||||
include "compat/ossaudio/files.ossaudio"
|
||||
|
||||
# Xen devices
|
||||
|
||||
# Network driver
|
||||
device xennet: arp, ether, ifnet
|
||||
attach xennet at hypervisor
|
||||
file arch/xen/xen/if_xennet.c xennet needs-flag
|
||||
|
||||
# Block device driver and wd/sd/cd identities
|
||||
device xbd: disk
|
||||
attach xbd at hypervisor
|
||||
file arch/xen/xen/xbd.c xbd | wd | sd | cd needs-flag
|
||||
|
||||
device wd: disk
|
||||
attach wd at hypervisor
|
||||
|
||||
device sd: disk
|
||||
attach sd at hypervisor
|
||||
|
||||
device cd: disk
|
||||
attach cd at hypervisor
|
||||
|
||||
# Keyboard
|
||||
device xenkbc: pckbport
|
||||
attach xenkbc at hypervisor
|
||||
file arch/xen/xen/xenkbc.c xenkbc needs-flag
|
||||
|
||||
# Generic VGA
|
||||
attach vga at hypervisor with vga_xen
|
||||
file arch/xen/xen/vga_xen.c vga_xen needs-flag
|
||||
|
||||
# Domain-0 operations
|
||||
defflag opt_xen.h DOM0OPS
|
||||
file arch/xen/xen/machmem.c dom0ops
|
||||
file arch/xen/xen/privcmd.c dom0ops
|
||||
file arch/xen/xen/vfr.c dom0ops
|
||||
|
||||
include "arch/xen/conf/majors.i386"
|
||||
@@ -0,0 +1,630 @@
|
||||
/* $NetBSD: autoconf.c,v 1.1.2.1 2004/05/22 15:57:33 he Exp $ */
|
||||
/* NetBSD: autoconf.c,v 1.75 2003/12/30 12:33:22 pk Exp */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* William Jolitz.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)autoconf.c 7.1 (Berkeley) 5/9/91
|
||||
*/
|
||||
|
||||
/*
|
||||
* Setup the system to run on the current machine.
|
||||
*
|
||||
* Configure() is called at boot time and initializes the vba
|
||||
* device tables and the memory controller monitoring. Available
|
||||
* devices are determined (from possibilities mentioned in ioconf.c),
|
||||
* and the drivers are initialized.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.1.2.1 2004/05/22 15:57:33 he Exp $");
|
||||
|
||||
#include "opt_compat_oldboot.h"
|
||||
#include "opt_multiprocessor.h"
|
||||
#include "opt_nfs_boot.h"
|
||||
#include "xennet.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/conf.h>
|
||||
#ifdef COMPAT_OLDBOOT
|
||||
#include <sys/reboot.h>
|
||||
#endif
|
||||
#include <sys/device.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/dkio.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#ifdef NFS_BOOT_BOOTSTATIC
|
||||
#include <net/if.h>
|
||||
#include <net/if_ether.h>
|
||||
#include <netinet/in.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#include <nfs/nfsproto.h>
|
||||
#include <nfs/nfs.h>
|
||||
#include <nfs/nfsmount.h>
|
||||
#include <nfs/nfsdiskless.h>
|
||||
#include <machine/if_xennetvar.h>
|
||||
#endif
|
||||
|
||||
#include <machine/pte.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/gdt.h>
|
||||
#include <machine/pcb.h>
|
||||
#include <machine/bootinfo.h>
|
||||
|
||||
#include "ioapic.h"
|
||||
#include "lapic.h"
|
||||
|
||||
#if NIOAPIC > 0
|
||||
#include <machine/i82093var.h>
|
||||
#endif
|
||||
|
||||
#if NLAPIC > 0
|
||||
#include <machine/i82489var.h>
|
||||
#endif
|
||||
|
||||
static int match_harddisk(struct device *, struct btinfo_bootdisk *);
|
||||
static void matchbiosdisks(void);
|
||||
static void findroot(void);
|
||||
static int is_valid_disk(struct device *);
|
||||
|
||||
extern struct disklist *i386_alldisks;
|
||||
extern int i386_ndisks;
|
||||
|
||||
#include "bios32.h"
|
||||
#if NBIOS32 > 0
|
||||
#include <machine/bios32.h>
|
||||
#endif
|
||||
|
||||
#include "opt_pcibios.h"
|
||||
#ifdef PCIBIOS
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <i386/pci/pcibios.h>
|
||||
#endif
|
||||
|
||||
#include "opt_kvm86.h"
|
||||
#ifdef KVM86
|
||||
#include <machine/kvm86.h>
|
||||
#endif
|
||||
|
||||
#include "opt_xen.h"
|
||||
|
||||
struct device *booted_device;
|
||||
int booted_partition;
|
||||
|
||||
/*
|
||||
* Determine i/o configuration for a machine.
|
||||
*/
|
||||
void
|
||||
cpu_configure(void)
|
||||
{
|
||||
|
||||
startrtclock();
|
||||
|
||||
#if NBIOS32 > 0
|
||||
bios32_init();
|
||||
#endif
|
||||
#ifdef PCIBIOS
|
||||
pcibios_init();
|
||||
#endif
|
||||
|
||||
/* kvm86 needs a TSS */
|
||||
i386_proc0_tss_ldt_init();
|
||||
#ifdef KVM86
|
||||
kvm86_init();
|
||||
#endif
|
||||
|
||||
if (config_rootfound("mainbus", NULL) == NULL)
|
||||
panic("configure: mainbus not configured");
|
||||
|
||||
#ifdef INTRDEBUG
|
||||
intr_printconfig();
|
||||
#endif
|
||||
|
||||
#if NIOAPIC > 0
|
||||
lapic_set_lvt();
|
||||
ioapic_enable();
|
||||
#endif
|
||||
/* resync cr0 after FPU configuration */
|
||||
lwp0.l_addr->u_pcb.pcb_cr0 = rcr0();
|
||||
#ifdef MULTIPROCESSOR
|
||||
/* propagate this to the idle pcb's. */
|
||||
cpu_init_idle_pcbs();
|
||||
#endif
|
||||
|
||||
spl0();
|
||||
#if NLAPIC > 0
|
||||
lapic_tpr = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
cpu_rootconf(void)
|
||||
{
|
||||
findroot();
|
||||
matchbiosdisks();
|
||||
|
||||
printf("boot device: %s\n",
|
||||
booted_device ? booted_device->dv_xname : "<unknown>");
|
||||
|
||||
setroot(booted_device, booted_partition);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX ugly bit of code. But, this is the only safe time that the
|
||||
* match between BIOS disks and native disks can be done.
|
||||
*/
|
||||
static void
|
||||
matchbiosdisks(void)
|
||||
{
|
||||
struct btinfo_biosgeom *big;
|
||||
struct bi_biosgeom_entry *be;
|
||||
struct device *dv;
|
||||
int i, ck, error, m, n;
|
||||
struct vnode *tv;
|
||||
char mbr[DEV_BSIZE];
|
||||
int dklist_size;
|
||||
int bmajor;
|
||||
|
||||
big = lookup_bootinfo(BTINFO_BIOSGEOM);
|
||||
|
||||
if (big == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* First, count all native disks
|
||||
*/
|
||||
for (dv = alldevs.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next)
|
||||
if (is_valid_disk(dv))
|
||||
i386_ndisks++;
|
||||
|
||||
if (i386_ndisks == 0)
|
||||
return;
|
||||
|
||||
dklist_size = sizeof (struct disklist) + (i386_ndisks - 1) *
|
||||
sizeof (struct nativedisk_info);
|
||||
|
||||
/* XXX M_TEMP is wrong */
|
||||
i386_alldisks = malloc(dklist_size, M_TEMP, M_NOWAIT);
|
||||
if (i386_alldisks == NULL)
|
||||
return;
|
||||
|
||||
memset(i386_alldisks, 0, dklist_size);
|
||||
|
||||
i386_alldisks->dl_nnativedisks = i386_ndisks;
|
||||
i386_alldisks->dl_nbiosdisks = big->num;
|
||||
for (i = 0; i < big->num; i++) {
|
||||
i386_alldisks->dl_biosdisks[i].bi_dev = big->disk[i].dev;
|
||||
i386_alldisks->dl_biosdisks[i].bi_sec = big->disk[i].sec;
|
||||
i386_alldisks->dl_biosdisks[i].bi_head = big->disk[i].head;
|
||||
i386_alldisks->dl_biosdisks[i].bi_cyl = big->disk[i].cyl;
|
||||
i386_alldisks->dl_biosdisks[i].bi_lbasecs = big->disk[i].totsec;
|
||||
i386_alldisks->dl_biosdisks[i].bi_flags = big->disk[i].flags;
|
||||
#ifdef GEOM_DEBUG
|
||||
#ifdef NOTYET
|
||||
printf("disk %x: flags %x, interface %x, device %llx\n",
|
||||
big->disk[i].dev, big->disk[i].flags,
|
||||
big->disk[i].interface_path, big->disk[i].device_path);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX code duplication from findroot()
|
||||
*/
|
||||
n = -1;
|
||||
for (dv = alldevs.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next) {
|
||||
if (dv->dv_class != DV_DISK)
|
||||
continue;
|
||||
#ifdef GEOM_DEBUG
|
||||
printf("matchbiosdisks: trying to match (%s) %s\n",
|
||||
dv->dv_xname, dv->dv_cfdata->cf_name);
|
||||
#endif
|
||||
if (is_valid_disk(dv)) {
|
||||
n++;
|
||||
sprintf(i386_alldisks->dl_nativedisks[n].ni_devname,
|
||||
"%s%d", dv->dv_cfdata->cf_name,
|
||||
dv->dv_unit);
|
||||
|
||||
bmajor = devsw_name2blk(dv->dv_xname, NULL, 0);
|
||||
if (bmajor == -1)
|
||||
return;
|
||||
|
||||
if (bdevvp(MAKEDISKDEV(bmajor, dv->dv_unit, RAW_PART),
|
||||
&tv))
|
||||
panic("matchbiosdisks: can't alloc vnode");
|
||||
|
||||
error = VOP_OPEN(tv, FREAD, NOCRED, 0);
|
||||
if (error) {
|
||||
vput(tv);
|
||||
continue;
|
||||
}
|
||||
error = vn_rdwr(UIO_READ, tv, mbr, DEV_BSIZE, 0,
|
||||
UIO_SYSSPACE, 0, NOCRED, NULL, 0);
|
||||
VOP_CLOSE(tv, FREAD, NOCRED, 0);
|
||||
if (error) {
|
||||
#ifdef GEOM_DEBUG
|
||||
printf("matchbiosdisks: %s: MBR read failure\n",
|
||||
dv->dv_xname);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
for (ck = i = 0; i < DEV_BSIZE; i++)
|
||||
ck += mbr[i];
|
||||
for (m = i = 0; i < big->num; i++) {
|
||||
be = &big->disk[i];
|
||||
#ifdef GEOM_DEBUG
|
||||
printf("match %s with %d ", dv->dv_xname, i);
|
||||
printf("dev ck %x bios ck %x\n", ck, be->cksum);
|
||||
#endif
|
||||
if (be->flags & BI_GEOM_INVALID)
|
||||
continue;
|
||||
if (be->cksum == ck &&
|
||||
!memcmp(&mbr[MBR_PART_OFFSET], be->dosparts,
|
||||
MBR_PART_COUNT *
|
||||
sizeof (struct mbr_partition))) {
|
||||
#ifdef GEOM_DEBUG
|
||||
printf("matched bios disk %x with %s\n",
|
||||
be->dev, dv->dv_xname);
|
||||
#endif
|
||||
i386_alldisks->dl_nativedisks[n].
|
||||
ni_biosmatches[m++] = i;
|
||||
}
|
||||
}
|
||||
i386_alldisks->dl_nativedisks[n].ni_nmatches = m;
|
||||
vput(tv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef COMPAT_OLDBOOT
|
||||
u_long bootdev = 0; /* should be dev_t, but not until 32 bits */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* helper function for "findroot()":
|
||||
* return nonzero if disk device matches bootinfo
|
||||
*/
|
||||
static int
|
||||
match_harddisk(struct device *dv, struct btinfo_bootdisk *bid)
|
||||
{
|
||||
struct vnode *tmpvn;
|
||||
int error;
|
||||
struct disklabel label;
|
||||
int found = 0;
|
||||
int bmajor;
|
||||
|
||||
/*
|
||||
* A disklabel is required here. The
|
||||
* bootblocks don't refuse to boot from
|
||||
* a disk without a label, but this is
|
||||
* normally not wanted.
|
||||
*/
|
||||
if (bid->labelsector == -1)
|
||||
return(0);
|
||||
|
||||
/*
|
||||
* lookup major number for disk block device
|
||||
*/
|
||||
bmajor = devsw_name2blk(dv->dv_xname, NULL, 0);
|
||||
if (bmajor == -1)
|
||||
return(0); /* XXX panic() ??? */
|
||||
|
||||
/*
|
||||
* Fake a temporary vnode for the disk, open
|
||||
* it, and read the disklabel for comparison.
|
||||
*/
|
||||
if (bdevvp(MAKEDISKDEV(bmajor, dv->dv_unit, bid->partition), &tmpvn))
|
||||
panic("findroot can't alloc vnode");
|
||||
error = VOP_OPEN(tmpvn, FREAD, NOCRED, 0);
|
||||
if (error) {
|
||||
#ifndef DEBUG
|
||||
/*
|
||||
* Ignore errors caused by missing
|
||||
* device, partition or medium.
|
||||
*/
|
||||
if (error != ENXIO && error != ENODEV)
|
||||
#endif
|
||||
printf("findroot: can't open dev %s%c (%d)\n",
|
||||
dv->dv_xname, 'a' + bid->partition, error);
|
||||
vput(tmpvn);
|
||||
return(0);
|
||||
}
|
||||
error = VOP_IOCTL(tmpvn, DIOCGDINFO, &label, FREAD, NOCRED, 0);
|
||||
if (error) {
|
||||
/*
|
||||
* XXX can't happen - open() would
|
||||
* have errored out (or faked up one)
|
||||
*/
|
||||
printf("can't get label for dev %s%c (%d)\n",
|
||||
dv->dv_xname, 'a' + bid->partition, error);
|
||||
goto closeout;
|
||||
}
|
||||
|
||||
/* compare with our data */
|
||||
if (label.d_type == bid->label.type &&
|
||||
label.d_checksum == bid->label.checksum &&
|
||||
!strncmp(label.d_packname, bid->label.packname, 16))
|
||||
found = 1;
|
||||
|
||||
closeout:
|
||||
VOP_CLOSE(tmpvn, FREAD, NOCRED, 0);
|
||||
vput(tmpvn);
|
||||
return(found);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to find the device from which we were booted.
|
||||
* If we can do so, and not instructed not to do so,
|
||||
* change rootdev to correspond to the load device.
|
||||
*/
|
||||
void
|
||||
findroot(void)
|
||||
{
|
||||
struct btinfo_bootdisk *bid;
|
||||
struct device *dv;
|
||||
union xen_cmdline_parseinfo xcp;
|
||||
#ifdef COMPAT_OLDBOOT
|
||||
int i, majdev, unit, part;
|
||||
char buf[32];
|
||||
#endif
|
||||
|
||||
if (booted_device)
|
||||
return;
|
||||
|
||||
if (lookup_bootinfo(BTINFO_NETIF)) {
|
||||
/*
|
||||
* We got netboot interface information, but
|
||||
* "device_register()" couldn't match it to a configured
|
||||
* device. Bootdisk information cannot be present at the
|
||||
* same time, so give up.
|
||||
*/
|
||||
printf("findroot: netboot interface not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bid = lookup_bootinfo(BTINFO_BOOTDISK);
|
||||
if (bid) {
|
||||
/*
|
||||
* Scan all disk devices for ones that match the passed data.
|
||||
* Don't break if one is found, to get possible multiple
|
||||
* matches - for problem tracking. Use the first match anyway
|
||||
* because lower device numbers are more likely to be the
|
||||
* boot device.
|
||||
*/
|
||||
for (dv = alldevs.tqh_first; dv != NULL;
|
||||
dv = dv->dv_list.tqe_next) {
|
||||
if (dv->dv_class != DV_DISK)
|
||||
continue;
|
||||
|
||||
if (!strcmp(dv->dv_cfdata->cf_name, "fd")) {
|
||||
/*
|
||||
* Assume the configured unit number matches
|
||||
* the BIOS device number. (This is the old
|
||||
* behaviour.) Needs some ideas how to handle
|
||||
* BIOS's "swap floppy drive" options.
|
||||
*/
|
||||
if ((bid->biosdev & 0x80) ||
|
||||
dv->dv_unit != bid->biosdev)
|
||||
continue;
|
||||
|
||||
goto found;
|
||||
}
|
||||
|
||||
if (is_valid_disk(dv)) {
|
||||
/*
|
||||
* Don't trust BIOS device numbers, try
|
||||
* to match the information passed by the
|
||||
* bootloader instead.
|
||||
*/
|
||||
if ((bid->biosdev & 0x80) == 0 ||
|
||||
!match_harddisk(dv, bid))
|
||||
continue;
|
||||
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* no "fd", "wd", "sd", "ld", "ed" */
|
||||
continue;
|
||||
|
||||
found:
|
||||
if (booted_device) {
|
||||
printf("warning: double match for boot "
|
||||
"device (%s, %s)\n",
|
||||
booted_device->dv_xname, dv->dv_xname);
|
||||
continue;
|
||||
}
|
||||
booted_device = dv;
|
||||
booted_partition = bid->partition;
|
||||
}
|
||||
|
||||
if (booted_device)
|
||||
return;
|
||||
}
|
||||
|
||||
xen_parse_cmdline(XEN_PARSE_BOOTDEV, &xcp);
|
||||
|
||||
for (dv = alldevs.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next) {
|
||||
if (is_valid_disk(dv) == 0)
|
||||
continue;
|
||||
|
||||
if (xcp.xcp_bootdev[0] == 0) {
|
||||
booted_device = dv;
|
||||
break;
|
||||
}
|
||||
|
||||
if (strncmp(xcp.xcp_bootdev, dv->dv_xname,
|
||||
strlen(dv->dv_xname)))
|
||||
continue;
|
||||
|
||||
if (strlen(xcp.xcp_bootdev) > strlen(dv->dv_xname)) {
|
||||
booted_partition = toupper(
|
||||
xcp.xcp_bootdev[strlen(dv->dv_xname)]) - 'A';
|
||||
}
|
||||
|
||||
booted_device = dv;
|
||||
break;
|
||||
}
|
||||
|
||||
if (booted_device)
|
||||
return;
|
||||
|
||||
#ifdef COMPAT_OLDBOOT
|
||||
#if 0
|
||||
printf("howto %x bootdev %x ", boothowto, bootdev);
|
||||
#endif
|
||||
|
||||
if ((bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
|
||||
return;
|
||||
|
||||
majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
|
||||
name = devsw_blk2name(majdev);
|
||||
if (name == NULL)
|
||||
return;
|
||||
|
||||
part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
|
||||
unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
|
||||
|
||||
sprintf(buf, "%s%d", name, unit);
|
||||
for (dv = alldevs.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next) {
|
||||
if (strcmp(buf, dv->dv_xname) == 0) {
|
||||
booted_device = dv;
|
||||
booted_partition = part;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "pci.h"
|
||||
|
||||
#include <dev/isa/isavar.h>
|
||||
#if NPCI > 0
|
||||
#include <dev/pci/pcivar.h>
|
||||
#endif
|
||||
|
||||
void
|
||||
device_register(struct device *dev, void *aux)
|
||||
{
|
||||
/*
|
||||
* Handle network interfaces here, the attachment information is
|
||||
* not available driver independantly later.
|
||||
* For disks, there is nothing useful available at attach time.
|
||||
*/
|
||||
#if NXENNET > 0
|
||||
if (dev->dv_class == DV_IFNET) {
|
||||
union xen_cmdline_parseinfo xcp;
|
||||
|
||||
xen_parse_cmdline(XEN_PARSE_BOOTDEV, &xcp);
|
||||
if (strncmp(xcp.xcp_bootdev, dev->dv_xname, 16) == 0) {
|
||||
#ifdef NFS_BOOT_BOOTSTATIC
|
||||
nfs_bootstatic_callback = xennet_bootstatic_callback;
|
||||
#endif
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (dev->dv_class == DV_IFNET) {
|
||||
struct btinfo_netif *bin = lookup_bootinfo(BTINFO_NETIF);
|
||||
if (bin == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* We don't check the driver name against the device name
|
||||
* passed by the boot ROM. The ROM should stay usable
|
||||
* if the driver gets obsoleted.
|
||||
* The physical attachment information (checked below)
|
||||
* must be sufficient to identify the device.
|
||||
*/
|
||||
|
||||
if (bin->bus == BI_BUS_ISA &&
|
||||
!strcmp(dev->dv_parent->dv_cfdata->cf_name, "isa")) {
|
||||
struct isa_attach_args *iaa = aux;
|
||||
|
||||
/* compare IO base address */
|
||||
/* XXXJRT what about multiple I/O addrs? */
|
||||
if (iaa->ia_nio > 0 &&
|
||||
bin->addr.iobase == iaa->ia_io[0].ir_addr)
|
||||
goto found;
|
||||
}
|
||||
#if NPCI > 0
|
||||
if (bin->bus == BI_BUS_PCI &&
|
||||
!strcmp(dev->dv_parent->dv_cfdata->cf_name, "pci")) {
|
||||
struct pci_attach_args *paa = aux;
|
||||
int b, d, f;
|
||||
|
||||
/*
|
||||
* Calculate BIOS representation of:
|
||||
*
|
||||
* <bus,device,function>
|
||||
*
|
||||
* and compare.
|
||||
*/
|
||||
pci_decompose_tag(paa->pa_pc, paa->pa_tag, &b, &d, &f);
|
||||
if (bin->addr.tag == ((b << 8) | (d << 3) | f))
|
||||
goto found;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
|
||||
found:
|
||||
if (booted_device) {
|
||||
/* XXX should be a "panic()" */
|
||||
printf("warning: double match for boot device (%s, %s)\n",
|
||||
booted_device->dv_xname, dev->dv_xname);
|
||||
return;
|
||||
}
|
||||
booted_device = dev;
|
||||
}
|
||||
|
||||
static int
|
||||
is_valid_disk(struct device *dv)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
if (dv->dv_class != DV_DISK)
|
||||
return (0);
|
||||
|
||||
name = dv->dv_cfdata->cf_name;
|
||||
|
||||
return (strcmp(name, "sd") == 0 || strcmp(name, "wd") == 0 ||
|
||||
strcmp(name, "ld") == 0 || strcmp(name, "ed") == 0 ||
|
||||
strcmp(name, "xbd") == 0);
|
||||
}
|
||||
@@ -0,0 +1,408 @@
|
||||
/* $NetBSD: gdt.c,v 1.1 2004/03/11 21:44:08 cl Exp $ */
|
||||
/* NetBSD: gdt.c,v 1.32 2004/02/13 11:36:13 wiz Exp */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by John T. Kohl and Charles M. Hannum.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: gdt.c,v 1.1 2004/03/11 21:44:08 cl Exp $");
|
||||
|
||||
#include "opt_multiprocessor.h"
|
||||
#include "opt_xen.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <uvm/uvm.h>
|
||||
|
||||
#include <machine/gdt.h>
|
||||
|
||||
int gdt_size[2]; /* total number of GDT entries */
|
||||
int gdt_count[2]; /* number of GDT entries in use */
|
||||
int gdt_next[2]; /* next available slot for sweeping */
|
||||
int gdt_free[2]; /* next free slot; terminated with GNULL_SEL */
|
||||
|
||||
struct lock gdt_lock_store;
|
||||
|
||||
static __inline void gdt_lock(void);
|
||||
static __inline void gdt_unlock(void);
|
||||
void gdt_init(void);
|
||||
void gdt_grow(int);
|
||||
int gdt_get_slot(void);
|
||||
int gdt_get_slot1(int);
|
||||
void gdt_put_slot(int);
|
||||
void gdt_put_slot1(int, int);
|
||||
|
||||
/*
|
||||
* Lock and unlock the GDT, to avoid races in case gdt_{ge,pu}t_slot() sleep
|
||||
* waiting for memory.
|
||||
*
|
||||
* Note that the locking done here is not sufficient for multiprocessor
|
||||
* systems. A freshly allocated slot will still be of type SDT_SYSNULL for
|
||||
* some time after the GDT is unlocked, so gdt_compact() could attempt to
|
||||
* reclaim it.
|
||||
*/
|
||||
static __inline void
|
||||
gdt_lock()
|
||||
{
|
||||
|
||||
(void) lockmgr(&gdt_lock_store, LK_EXCLUSIVE, NULL);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
gdt_unlock()
|
||||
{
|
||||
|
||||
(void) lockmgr(&gdt_lock_store, LK_RELEASE, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
setgdt(int sel, void *base, size_t limit,
|
||||
int type, int dpl, int def32, int gran)
|
||||
{
|
||||
struct segment_descriptor sd;
|
||||
CPU_INFO_ITERATOR cii;
|
||||
struct cpu_info *ci;
|
||||
|
||||
if (type == SDT_SYS386TSS) {
|
||||
/* printk("XXX TSS descriptor not supported in GDT\n"); */
|
||||
return;
|
||||
}
|
||||
|
||||
setsegment(&sd, base, limit, type, dpl, def32, gran);
|
||||
for (CPU_INFO_FOREACH(cii, ci)) {
|
||||
if (ci->ci_gdt != NULL) {
|
||||
#ifndef XEN
|
||||
ci->ci_gdt[sel].sd = sd;
|
||||
#else
|
||||
xen_update_descriptor(&ci->ci_gdt[sel],
|
||||
(union descriptor *)&sd);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the GDT subsystem. Called from autoconf().
|
||||
*/
|
||||
void
|
||||
gdt_init()
|
||||
{
|
||||
size_t max_len, min_len;
|
||||
union descriptor *old_gdt;
|
||||
struct vm_page *pg;
|
||||
vaddr_t va;
|
||||
struct cpu_info *ci = &cpu_info_primary;
|
||||
|
||||
lockinit(&gdt_lock_store, PZERO, "gdtlck", 0, 0);
|
||||
|
||||
max_len = MAXGDTSIZ * sizeof(gdt[0]);
|
||||
min_len = MINGDTSIZ * sizeof(gdt[0]);
|
||||
|
||||
gdt_size[0] = MINGDTSIZ;
|
||||
gdt_count[0] = NGDT;
|
||||
gdt_next[0] = NGDT;
|
||||
gdt_free[0] = GNULL_SEL;
|
||||
|
||||
gdt_size[1] = 0;
|
||||
gdt_count[1] = MAXGDTSIZ;
|
||||
gdt_next[1] = MAXGDTSIZ;
|
||||
gdt_free[1] = GNULL_SEL;
|
||||
|
||||
old_gdt = gdt;
|
||||
gdt = (union descriptor *)uvm_km_valloc(kernel_map, max_len + max_len);
|
||||
for (va = (vaddr_t)gdt; va < (vaddr_t)gdt + min_len; va += PAGE_SIZE) {
|
||||
pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO);
|
||||
if (pg == NULL) {
|
||||
panic("gdt_init: no pages");
|
||||
}
|
||||
pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg),
|
||||
VM_PROT_READ | VM_PROT_WRITE);
|
||||
}
|
||||
memcpy(gdt, old_gdt, NGDT * sizeof(gdt[0]));
|
||||
ci->ci_gdt = gdt;
|
||||
setsegment(&ci->ci_gdt[GCPU_SEL].sd, ci, sizeof(struct cpu_info)-1,
|
||||
SDT_MEMRWA, SEL_KPL, 1, 1);
|
||||
|
||||
gdt_init_cpu(ci);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate shadow GDT for a slave CPU.
|
||||
*/
|
||||
void
|
||||
gdt_alloc_cpu(struct cpu_info *ci)
|
||||
{
|
||||
int max_len = MAXGDTSIZ * sizeof(gdt[0]);
|
||||
int min_len = MINGDTSIZ * sizeof(gdt[0]);
|
||||
struct vm_page *pg;
|
||||
vaddr_t va;
|
||||
|
||||
ci->ci_gdt = (union descriptor *)uvm_km_valloc(kernel_map, max_len);
|
||||
for (va = (vaddr_t)ci->ci_gdt; va < (vaddr_t)ci->ci_gdt + min_len;
|
||||
va += PAGE_SIZE) {
|
||||
while ((pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO))
|
||||
== NULL) {
|
||||
uvm_wait("gdt_alloc_cpu");
|
||||
}
|
||||
pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg),
|
||||
VM_PROT_READ | VM_PROT_WRITE);
|
||||
}
|
||||
memset(ci->ci_gdt, 0, min_len);
|
||||
memcpy(ci->ci_gdt, gdt, gdt_count[0] * sizeof(gdt[0]));
|
||||
setsegment(&ci->ci_gdt[GCPU_SEL].sd, ci, sizeof(struct cpu_info)-1,
|
||||
SDT_MEMRWA, SEL_KPL, 1, 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Load appropriate gdt descriptor; we better be running on *ci
|
||||
* (for the most part, this is how a CPU knows who it is).
|
||||
*/
|
||||
void
|
||||
gdt_init_cpu(struct cpu_info *ci)
|
||||
{
|
||||
#ifndef XEN
|
||||
struct region_descriptor region;
|
||||
size_t max_len;
|
||||
|
||||
max_len = MAXGDTSIZ * sizeof(gdt[0]);
|
||||
setregion(®ion, ci->ci_gdt, max_len - 1);
|
||||
lgdt(®ion);
|
||||
#else
|
||||
size_t len = gdt_size[0] * sizeof(gdt[0]);
|
||||
unsigned long frames[len >> PAGE_SHIFT];
|
||||
vaddr_t va;
|
||||
pt_entry_t *ptp;
|
||||
pt_entry_t *maptp;
|
||||
int f;
|
||||
|
||||
for (va = (vaddr_t)ci->ci_gdt, f = 0;
|
||||
va < (vaddr_t)ci->ci_gdt + len;
|
||||
va += PAGE_SIZE, f++) {
|
||||
KASSERT(va >= VM_MIN_KERNEL_ADDRESS);
|
||||
ptp = kvtopte(va);
|
||||
frames[f] = *ptp >> PAGE_SHIFT;
|
||||
maptp = (pt_entry_t *)vtomach((vaddr_t)ptp);
|
||||
PTE_CLEARBITS(ptp, maptp, PG_RW);
|
||||
}
|
||||
PTE_UPDATES_FLUSH();
|
||||
/* printk("loading gdt %x, %d entries, %d pages", */
|
||||
/* frames[0] << PAGE_SHIFT, gdt_size[0], len >> PAGE_SHIFT); */
|
||||
if (HYPERVISOR_set_gdt(frames, gdt_size[0]))
|
||||
panic("HYPERVISOR_set_gdt failed!\n");
|
||||
lgdt_finish();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MULTIPROCESSOR
|
||||
|
||||
void
|
||||
gdt_reload_cpu(struct cpu_info *ci)
|
||||
{
|
||||
struct region_descriptor region;
|
||||
size_t max_len;
|
||||
|
||||
max_len = MAXGDTSIZ * sizeof(gdt[0]);
|
||||
setregion(®ion, ci->ci_gdt, max_len - 1);
|
||||
lgdt(®ion);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Grow the GDT.
|
||||
*/
|
||||
void
|
||||
gdt_grow(int which)
|
||||
{
|
||||
size_t old_len, new_len, max_len;
|
||||
CPU_INFO_ITERATOR cii;
|
||||
struct cpu_info *ci;
|
||||
struct vm_page *pg;
|
||||
vaddr_t va;
|
||||
|
||||
old_len = gdt_size[which] * sizeof(gdt[0]);
|
||||
gdt_size[which] <<= 1;
|
||||
new_len = old_len << 1;
|
||||
|
||||
if (which != 0) {
|
||||
max_len = MAXGDTSIZ * sizeof(gdt[0]);
|
||||
if (old_len == 0) {
|
||||
gdt_size[which] = MINGDTSIZ;
|
||||
new_len = gdt_size[which] * sizeof(gdt[0]);
|
||||
}
|
||||
for (va = (vaddr_t)(cpu_info_primary.ci_gdt) + old_len + max_len;
|
||||
va < (vaddr_t)(cpu_info_primary.ci_gdt) + new_len + max_len;
|
||||
va += PAGE_SIZE) {
|
||||
while ((pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO)) ==
|
||||
NULL) {
|
||||
uvm_wait("gdt_grow");
|
||||
}
|
||||
pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg),
|
||||
VM_PROT_READ | VM_PROT_WRITE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (CPU_INFO_FOREACH(cii, ci)) {
|
||||
for (va = (vaddr_t)(ci->ci_gdt) + old_len;
|
||||
va < (vaddr_t)(ci->ci_gdt) + new_len;
|
||||
va += PAGE_SIZE) {
|
||||
while ((pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO)) ==
|
||||
NULL) {
|
||||
uvm_wait("gdt_grow");
|
||||
}
|
||||
pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg),
|
||||
VM_PROT_READ | VM_PROT_WRITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a GDT slot as follows:
|
||||
* 1) If there are entries on the free list, use those.
|
||||
* 2) If there are fewer than gdt_size entries in use, there are free slots
|
||||
* near the end that we can sweep through.
|
||||
* 3) As a last resort, we increase the size of the GDT, and sweep through
|
||||
* the new slots.
|
||||
*/
|
||||
int
|
||||
gdt_get_slot()
|
||||
{
|
||||
return gdt_get_slot1(0);
|
||||
}
|
||||
|
||||
int
|
||||
gdt_get_slot1(int which)
|
||||
{
|
||||
size_t offset;
|
||||
int slot;
|
||||
|
||||
gdt_lock();
|
||||
|
||||
if (gdt_free[which] != GNULL_SEL) {
|
||||
slot = gdt_free[which];
|
||||
gdt_free[which] = gdt[slot].gd.gd_selector;
|
||||
} else {
|
||||
offset = which * MAXGDTSIZ * sizeof(gdt[0]);
|
||||
if (gdt_next[which] != gdt_count[which] + offset)
|
||||
panic("gdt_get_slot botch 1");
|
||||
if (gdt_next[which] - offset >= gdt_size[which]) {
|
||||
if (gdt_size[which] >= MAXGDTSIZ)
|
||||
panic("gdt_get_slot botch 2");
|
||||
gdt_grow(which);
|
||||
}
|
||||
slot = gdt_next[which]++;
|
||||
}
|
||||
|
||||
gdt_count[which]++;
|
||||
gdt_unlock();
|
||||
return (slot);
|
||||
}
|
||||
|
||||
/*
|
||||
* Deallocate a GDT slot, putting it on the free list.
|
||||
*/
|
||||
void
|
||||
gdt_put_slot(int slot)
|
||||
{
|
||||
gdt_put_slot1(slot, 0);
|
||||
}
|
||||
|
||||
void
|
||||
gdt_put_slot1(int slot, int which)
|
||||
{
|
||||
|
||||
gdt_lock();
|
||||
gdt_count[which]--;
|
||||
|
||||
gdt[slot].gd.gd_type = SDT_SYSNULL;
|
||||
gdt[slot].gd.gd_selector = gdt_free[which];
|
||||
gdt_free[which] = slot;
|
||||
|
||||
gdt_unlock();
|
||||
}
|
||||
|
||||
int
|
||||
tss_alloc(struct pcb *pcb)
|
||||
{
|
||||
int slot;
|
||||
|
||||
slot = gdt_get_slot();
|
||||
setgdt(slot, &pcb->pcb_tss, sizeof(struct pcb) - 1,
|
||||
SDT_SYS386TSS, SEL_KPL, 0, 0);
|
||||
return GSEL(slot, SEL_KPL);
|
||||
}
|
||||
|
||||
void
|
||||
tss_free(int sel)
|
||||
{
|
||||
|
||||
gdt_put_slot(IDXSEL(sel));
|
||||
}
|
||||
|
||||
/*
|
||||
* Caller must have pmap locked for both of these functions.
|
||||
*/
|
||||
void
|
||||
ldt_alloc(struct pmap *pmap, union descriptor *ldt, size_t len)
|
||||
{
|
||||
int slot;
|
||||
|
||||
slot = gdt_get_slot1(1);
|
||||
#ifndef XEN
|
||||
setgdt(slot, ldt, len - 1, SDT_SYSLDT, SEL_KPL, 0, 0);
|
||||
#else
|
||||
cpu_info_primary.ci_gdt[slot].ld.ld_base = (uint32_t)ldt;
|
||||
cpu_info_primary.ci_gdt[slot].ld.ld_entries =
|
||||
len / sizeof(union descriptor);
|
||||
#endif
|
||||
pmap->pm_ldt_sel = GSEL(slot, SEL_KPL);
|
||||
}
|
||||
|
||||
void
|
||||
ldt_free(struct pmap *pmap)
|
||||
{
|
||||
int slot;
|
||||
|
||||
slot = IDXSEL(pmap->pm_ldt_sel);
|
||||
|
||||
gdt_put_slot1(slot, 1);
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
/* $NetBSD: hypervisor_machdep.c,v 1.2.2.2 2004/06/17 09:23:13 tron Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2004 Christian Limpach.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Christian Limpach.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* hypervisor.c
|
||||
*
|
||||
* Communication to/from hypervisor.
|
||||
*
|
||||
* Copyright (c) 2002-2004, K A Fraser
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: hypervisor_machdep.c,v 1.2.2.2 2004/06/17 09:23:13 tron Exp $");
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/xen.h>
|
||||
#include <machine/hypervisor.h>
|
||||
#include <machine/evtchn.h>
|
||||
|
||||
/*
|
||||
* Force a proper event-channel callback from Xen after clearing the
|
||||
* callback mask. We do this in a very simple manner, by making a call
|
||||
* down into Xen. The pending flag will be checked by Xen on return.
|
||||
*/
|
||||
void
|
||||
hypervisor_force_callback(void)
|
||||
{
|
||||
|
||||
(void)HYPERVISOR_xen_version(0);
|
||||
}
|
||||
|
||||
int stipending(void);
|
||||
int
|
||||
stipending()
|
||||
{
|
||||
uint32_t l1;
|
||||
unsigned long l2;
|
||||
unsigned int l1i, l2i, port;
|
||||
int irq;
|
||||
shared_info_t *s = HYPERVISOR_shared_info;
|
||||
struct cpu_info *ci;
|
||||
int ret;
|
||||
|
||||
ret = 0;
|
||||
ci = curcpu();
|
||||
|
||||
#if 0
|
||||
if (HYPERVISOR_shared_info->events)
|
||||
printf("stipending events %08lx mask %08lx ilevel %d\n",
|
||||
HYPERVISOR_shared_info->events,
|
||||
HYPERVISOR_shared_info->events_mask, ci->ci_ilevel);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* we're only called after STIC, so we know that we'll have to
|
||||
* STI at the end
|
||||
*/
|
||||
cli();
|
||||
while (s->vcpu_data[0].evtchn_upcall_pending) {
|
||||
s->vcpu_data[0].evtchn_upcall_pending = 0;
|
||||
/* NB. No need for a barrier here -- XCHG is a barrier
|
||||
* on x86. */
|
||||
l1 = x86_atomic_xchg(&s->evtchn_pending_sel, 0);
|
||||
while ((l1i = ffs(l1)) != 0) {
|
||||
l1i--;
|
||||
l1 &= ~(1 << l1i);
|
||||
|
||||
l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i];
|
||||
while ((l2i = ffs(l2)) != 0) {
|
||||
l2i--;
|
||||
l2 &= ~(1 << l2i);
|
||||
|
||||
port = (l1i << 5) + l2i;
|
||||
if ((irq = evtchn_to_irq[port]) != -1) {
|
||||
hypervisor_acknowledge_irq(irq);
|
||||
ci->ci_ipending |= (1 << irq);
|
||||
if (ret == 0 && ci->ci_ilevel <
|
||||
ci->ci_isources[irq]->is_handlers
|
||||
->ih_level)
|
||||
ret = 1;
|
||||
}
|
||||
#if 0 /* XXXcl dev/evtchn */
|
||||
else
|
||||
evtchn_device_upcall(port);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
sti();
|
||||
|
||||
#if 0
|
||||
if (ci->ci_ipending & 0x1)
|
||||
printf("stipending events %08lx mask %08lx ilevel %d ipending %08x\n",
|
||||
HYPERVISOR_shared_info->events,
|
||||
HYPERVISOR_shared_info->events_mask, ci->ci_ilevel,
|
||||
ci->ci_ipending);
|
||||
#endif
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void do_hypervisor_callback(struct trapframe *regs)
|
||||
{
|
||||
uint32_t l1;
|
||||
unsigned long l2;
|
||||
unsigned int l1i, l2i, port;
|
||||
int irq;
|
||||
shared_info_t *s = HYPERVISOR_shared_info;
|
||||
struct cpu_info *ci;
|
||||
int level;
|
||||
|
||||
ci = curcpu();
|
||||
level = ci->ci_ilevel;
|
||||
|
||||
while (s->vcpu_data[0].evtchn_upcall_pending) {
|
||||
s->vcpu_data[0].evtchn_upcall_pending = 0;
|
||||
/* NB. No need for a barrier here -- XCHG is a barrier
|
||||
* on x86. */
|
||||
l1 = x86_atomic_xchg(&s->evtchn_pending_sel, 0);
|
||||
while ((l1i = ffs(l1)) != 0) {
|
||||
l1i--;
|
||||
l1 &= ~(1 << l1i);
|
||||
|
||||
l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i];
|
||||
while ((l2i = ffs(l2)) != 0) {
|
||||
l2i--;
|
||||
l2 &= ~(1 << l2i);
|
||||
|
||||
port = (l1i << 5) + l2i;
|
||||
if ((irq = evtchn_to_irq[port]) != -1)
|
||||
do_event(irq, regs);
|
||||
#if 0 /* XXXcl dev/evtchn */
|
||||
else
|
||||
evtchn_device_upcall(port);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (level != ci->ci_ilevel)
|
||||
printf("hypervisor done %08x level %d/%d ipending %08x\n",
|
||||
HYPERVISOR_shared_info->evtchn_pending_sel, level,
|
||||
ci->ci_ilevel, ci->ci_ipending);
|
||||
#endif
|
||||
}
|
||||
|
||||
void hypervisor_unmask_event(unsigned int ev)
|
||||
{
|
||||
shared_info_t *s = HYPERVISOR_shared_info;
|
||||
|
||||
x86_atomic_clear_bit(&s->evtchn_mask[0], ev);
|
||||
/*
|
||||
* The following is basically the equivalent of
|
||||
* 'hw_resend_irq'. Just like a real IO-APIC we 'lose the
|
||||
* interrupt edge' if the channel is masked.
|
||||
*/
|
||||
if (x86_atomic_test_bit(&s->evtchn_pending[0], ev) &&
|
||||
!x86_atomic_test_and_set_bit(&s->evtchn_pending_sel, ev>>5)) {
|
||||
s->vcpu_data[0].evtchn_upcall_pending = 1;
|
||||
if (!s->vcpu_data[0].evtchn_upcall_mask)
|
||||
hypervisor_force_callback();
|
||||
}
|
||||
}
|
||||
|
||||
void hypervisor_mask_event(unsigned int ev)
|
||||
{
|
||||
shared_info_t *s = HYPERVISOR_shared_info;
|
||||
|
||||
x86_atomic_set_bit(&s->evtchn_mask[0], ev);
|
||||
}
|
||||
|
||||
void hypervisor_clear_event(unsigned int ev)
|
||||
{
|
||||
shared_info_t *s = HYPERVISOR_shared_info;
|
||||
|
||||
x86_atomic_clear_bit(&s->evtchn_pending[0], ev);
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,550 @@
|
||||
/* $NetBSD: sys_machdep.c,v 1.1.2.1 2004/05/22 15:59:21 he Exp $ */
|
||||
/* NetBSD: sys_machdep.c,v 1.70 2003/10/27 14:11:47 junyoung Exp */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Charles M. Hannum.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sys_machdep.c,v 1.1.2.1 2004/05/22 15:59:21 he Exp $");
|
||||
|
||||
#include "opt_compat_netbsd.h"
|
||||
#include "opt_mtrr.h"
|
||||
#include "opt_perfctrs.h"
|
||||
#include "opt_user_ldt.h"
|
||||
#include "opt_vm86.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#include <sys/mount.h>
|
||||
#include <sys/sa.h>
|
||||
#include <sys/syscallargs.h>
|
||||
|
||||
#include <uvm/uvm_extern.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/gdt.h>
|
||||
#include <machine/psl.h>
|
||||
#include <machine/reg.h>
|
||||
#include <machine/sysarch.h>
|
||||
#include <machine/mtrr.h>
|
||||
|
||||
#ifdef VM86
|
||||
#include <machine/vm86.h>
|
||||
#endif
|
||||
|
||||
#ifdef PERFCTRS
|
||||
#include <machine/pmc.h>
|
||||
#endif
|
||||
|
||||
extern struct vm_map *kernel_map;
|
||||
|
||||
int i386_iopl(struct lwp *, void *, register_t *);
|
||||
int i386_get_ioperm(struct lwp *, void *, register_t *);
|
||||
int i386_set_ioperm(struct lwp *, void *, register_t *);
|
||||
int i386_get_mtrr(struct lwp *, void *, register_t *);
|
||||
int i386_set_mtrr(struct lwp *, void *, register_t *);
|
||||
|
||||
#ifdef USER_LDT
|
||||
|
||||
#ifdef LDT_DEBUG
|
||||
static void i386_print_ldt(int, const struct segment_descriptor *);
|
||||
|
||||
static void
|
||||
i386_print_ldt(i, d)
|
||||
int i;
|
||||
const struct segment_descriptor *d;
|
||||
{
|
||||
printf("[%d] lolimit=0x%x, lobase=0x%x, type=%u, dpl=%u, p=%u, "
|
||||
"hilimit=0x%x, xx=%x, def32=%u, gran=%u, hibase=0x%x\n",
|
||||
i, d->sd_lolimit, d->sd_lobase, d->sd_type, d->sd_dpl, d->sd_p,
|
||||
d->sd_hilimit, d->sd_xx, d->sd_def32, d->sd_gran, d->sd_hibase);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
i386_get_ldt(l, args, retval)
|
||||
struct lwp *l;
|
||||
void *args;
|
||||
register_t *retval;
|
||||
{
|
||||
int error;
|
||||
struct proc *p = l->l_proc;
|
||||
pmap_t pmap = p->p_vmspace->vm_map.pmap;
|
||||
int nldt, num;
|
||||
union descriptor *lp, *cp;
|
||||
struct i386_get_ldt_args ua;
|
||||
|
||||
if ((error = copyin(args, &ua, sizeof(ua))) != 0)
|
||||
return (error);
|
||||
|
||||
#ifdef LDT_DEBUG
|
||||
printf("i386_get_ldt: start=%d num=%d descs=%p\n", ua.start,
|
||||
ua.num, ua.desc);
|
||||
#endif
|
||||
|
||||
if (ua.start < 0 || ua.num < 0 || ua.start > 8192 || ua.num > 8192 ||
|
||||
ua.start + ua.num > 8192)
|
||||
return (EINVAL);
|
||||
|
||||
cp = malloc(ua.num * sizeof(union descriptor), M_TEMP, M_WAITOK);
|
||||
if (cp == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
simple_lock(&pmap->pm_lock);
|
||||
|
||||
if (pmap->pm_flags & PMF_USER_LDT) {
|
||||
nldt = pmap->pm_ldt_len;
|
||||
lp = pmap->pm_ldt;
|
||||
} else {
|
||||
nldt = NLDT;
|
||||
lp = ldt;
|
||||
}
|
||||
|
||||
if (ua.start > nldt) {
|
||||
simple_unlock(&pmap->pm_lock);
|
||||
free(cp, M_TEMP);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
lp += ua.start;
|
||||
num = min(ua.num, nldt - ua.start);
|
||||
#ifdef LDT_DEBUG
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < num; i++)
|
||||
i386_print_ldt(i, &lp[i].sd);
|
||||
}
|
||||
#endif
|
||||
|
||||
memcpy(cp, lp, num * sizeof(union descriptor));
|
||||
simple_unlock(&pmap->pm_lock);
|
||||
|
||||
error = copyout(cp, ua.desc, num * sizeof(union descriptor));
|
||||
if (error == 0)
|
||||
*retval = num;
|
||||
|
||||
free(cp, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
i386_set_ldt(l, args, retval)
|
||||
struct lwp *l;
|
||||
void *args;
|
||||
register_t *retval;
|
||||
{
|
||||
int error, i, n;
|
||||
struct proc *p = l->l_proc;
|
||||
struct pcb *pcb = &l->l_addr->u_pcb;
|
||||
pmap_t pmap = p->p_vmspace->vm_map.pmap;
|
||||
struct i386_set_ldt_args ua;
|
||||
union descriptor *descv;
|
||||
size_t old_len, new_len, ldt_len;
|
||||
union descriptor *old_ldt, *new_ldt;
|
||||
|
||||
if ((error = copyin(args, &ua, sizeof(ua))) != 0)
|
||||
return (error);
|
||||
|
||||
if (ua.start < 0 || ua.num < 0 || ua.start > 8192 || ua.num > 8192 ||
|
||||
ua.start + ua.num > 8192)
|
||||
return (EINVAL);
|
||||
|
||||
descv = malloc(sizeof (*descv) * ua.num, M_TEMP, M_NOWAIT);
|
||||
if (descv == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
if ((error = copyin(ua.desc, descv, sizeof (*descv) * ua.num)) != 0)
|
||||
goto out;
|
||||
|
||||
/* Check descriptors for access violations. */
|
||||
for (i = 0; i < ua.num; i++) {
|
||||
union descriptor *desc = &descv[i];
|
||||
|
||||
switch (desc->sd.sd_type) {
|
||||
case SDT_SYSNULL:
|
||||
desc->sd.sd_p = 0;
|
||||
break;
|
||||
case SDT_SYS286CGT:
|
||||
case SDT_SYS386CGT:
|
||||
/*
|
||||
* Only allow call gates targeting a segment
|
||||
* in the LDT or a user segment in the fixed
|
||||
* part of the gdt. Segments in the LDT are
|
||||
* constrained (below) to be user segments.
|
||||
*/
|
||||
if (desc->gd.gd_p != 0 &&
|
||||
!ISLDT(desc->gd.gd_selector) &&
|
||||
((IDXSEL(desc->gd.gd_selector) >= NGDT) ||
|
||||
(gdt[IDXSEL(desc->gd.gd_selector)].sd.sd_dpl !=
|
||||
SEL_UPL))) {
|
||||
error = EACCES;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case SDT_MEMEC:
|
||||
case SDT_MEMEAC:
|
||||
case SDT_MEMERC:
|
||||
case SDT_MEMERAC:
|
||||
/* Must be "present" if executable and conforming. */
|
||||
if (desc->sd.sd_p == 0) {
|
||||
error = EACCES;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case SDT_MEMRO:
|
||||
case SDT_MEMROA:
|
||||
case SDT_MEMRW:
|
||||
case SDT_MEMRWA:
|
||||
case SDT_MEMROD:
|
||||
case SDT_MEMRODA:
|
||||
case SDT_MEMRWD:
|
||||
case SDT_MEMRWDA:
|
||||
case SDT_MEME:
|
||||
case SDT_MEMEA:
|
||||
case SDT_MEMER:
|
||||
case SDT_MEMERA:
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* Make sure that unknown descriptor types are
|
||||
* not marked present.
|
||||
*/
|
||||
if (desc->sd.sd_p != 0) {
|
||||
error = EACCES;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (desc->sd.sd_p != 0) {
|
||||
/* Only user (ring-3) descriptors may be present. */
|
||||
if (desc->sd.sd_dpl != SEL_UPL) {
|
||||
error = EACCES;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* allocate user ldt */
|
||||
simple_lock(&pmap->pm_lock);
|
||||
if (pmap->pm_ldt == 0 || (ua.start + ua.num) > pmap->pm_ldt_len) {
|
||||
if (pmap->pm_flags & PMF_USER_LDT)
|
||||
ldt_len = pmap->pm_ldt_len;
|
||||
else
|
||||
ldt_len = 512;
|
||||
while ((ua.start + ua.num) > ldt_len)
|
||||
ldt_len *= 2;
|
||||
new_len = ldt_len * sizeof(union descriptor);
|
||||
|
||||
simple_unlock(&pmap->pm_lock);
|
||||
new_ldt = (union descriptor *)uvm_km_alloc(kernel_map,
|
||||
new_len);
|
||||
simple_lock(&pmap->pm_lock);
|
||||
|
||||
if (pmap->pm_ldt != NULL && ldt_len <= pmap->pm_ldt_len) {
|
||||
/*
|
||||
* Another thread (re)allocated the LDT to
|
||||
* sufficient size while we were blocked in
|
||||
* uvm_km_alloc. Oh well. The new entries
|
||||
* will quite probably not be right, but
|
||||
* hey.. not our problem if user applications
|
||||
* have race conditions like that.
|
||||
*/
|
||||
uvm_km_free(kernel_map, (vaddr_t)new_ldt, new_len);
|
||||
goto copy;
|
||||
}
|
||||
|
||||
old_ldt = pmap->pm_ldt;
|
||||
|
||||
if (old_ldt != NULL) {
|
||||
old_len = pmap->pm_ldt_len * sizeof(union descriptor);
|
||||
} else {
|
||||
old_len = NLDT * sizeof(union descriptor);
|
||||
old_ldt = ldt;
|
||||
}
|
||||
|
||||
memcpy(new_ldt, old_ldt, old_len);
|
||||
memset((caddr_t)new_ldt + old_len, 0, new_len - old_len);
|
||||
|
||||
if (old_ldt != ldt)
|
||||
uvm_km_free(kernel_map, (vaddr_t)old_ldt, old_len);
|
||||
|
||||
pmap->pm_ldt = new_ldt;
|
||||
pmap->pm_ldt_len = ldt_len;
|
||||
|
||||
if (pmap->pm_flags & PMF_USER_LDT)
|
||||
ldt_free(pmap);
|
||||
else
|
||||
pmap->pm_flags |= PMF_USER_LDT;
|
||||
ldt_alloc(pmap, new_ldt, new_len);
|
||||
pcb->pcb_ldt_sel = pmap->pm_ldt_sel;
|
||||
if (pcb == curpcb)
|
||||
lldt(pcb->pcb_ldt_sel);
|
||||
|
||||
}
|
||||
copy:
|
||||
/* Now actually replace the descriptors. */
|
||||
for (i = 0, n = ua.start; i < ua.num; i++, n++)
|
||||
pmap->pm_ldt[n] = descv[i];
|
||||
|
||||
simple_unlock(&pmap->pm_lock);
|
||||
|
||||
*retval = ua.start;
|
||||
|
||||
out:
|
||||
free(descv, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
#endif /* USER_LDT */
|
||||
|
||||
int
|
||||
i386_iopl(l, args, retval)
|
||||
struct lwp *l;
|
||||
void *args;
|
||||
register_t *retval;
|
||||
{
|
||||
int error;
|
||||
struct proc *p = l->l_proc;
|
||||
struct pcb *pcb = &l->l_addr->u_pcb;
|
||||
struct i386_iopl_args ua;
|
||||
dom0_op_t op;
|
||||
|
||||
if ((xen_start_info.flags & SIF_PRIVILEGED) == 0)
|
||||
return EPERM;
|
||||
|
||||
if (securelevel > 1)
|
||||
return EPERM;
|
||||
|
||||
if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
|
||||
return error;
|
||||
|
||||
if ((error = copyin(args, &ua, sizeof(ua))) != 0)
|
||||
return error;
|
||||
|
||||
pcb->pcb_tss.tss_ioopt &= ~SEL_RPL;
|
||||
if (ua.iopl)
|
||||
pcb->pcb_tss.tss_ioopt |= SEL_UPL; /* i/o pl */
|
||||
else
|
||||
pcb->pcb_tss.tss_ioopt |= SEL_KPL; /* i/o pl */
|
||||
|
||||
/* Force the change at ring 0. */
|
||||
op.cmd = DOM0_IOPL;
|
||||
op.u.iopl.domain = DOMID_SELF;
|
||||
op.u.iopl.iopl = pcb->pcb_tss.tss_ioopt & SEL_RPL; /* i/o pl */
|
||||
HYPERVISOR_dom0_op(&op);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
i386_get_ioperm(l, args, retval)
|
||||
struct lwp *l;
|
||||
void *args;
|
||||
register_t *retval;
|
||||
{
|
||||
int error;
|
||||
struct pcb *pcb = &l->l_addr->u_pcb;
|
||||
struct i386_get_ioperm_args ua;
|
||||
|
||||
if ((error = copyin(args, &ua, sizeof(ua))) != 0)
|
||||
return (error);
|
||||
|
||||
return copyout(pcb->pcb_iomap, ua.iomap, sizeof(pcb->pcb_iomap));
|
||||
}
|
||||
|
||||
int
|
||||
i386_set_ioperm(l, args, retval)
|
||||
struct lwp *l;
|
||||
void *args;
|
||||
register_t *retval;
|
||||
{
|
||||
int error;
|
||||
struct proc *p = l->l_proc;
|
||||
struct pcb *pcb = &l->l_addr->u_pcb;
|
||||
struct i386_set_ioperm_args ua;
|
||||
|
||||
if (securelevel > 1)
|
||||
return EPERM;
|
||||
|
||||
if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
|
||||
return error;
|
||||
|
||||
if ((error = copyin(args, &ua, sizeof(ua))) != 0)
|
||||
return (error);
|
||||
|
||||
return copyin(ua.iomap, pcb->pcb_iomap, sizeof(pcb->pcb_iomap));
|
||||
}
|
||||
|
||||
#ifdef MTRR
|
||||
int
|
||||
i386_get_mtrr(struct lwp *l, void *args, register_t *retval)
|
||||
{
|
||||
struct i386_get_mtrr_args ua;
|
||||
int error, n;
|
||||
struct proc *p = l->l_proc;
|
||||
|
||||
if (mtrr_funcs == NULL)
|
||||
return ENOSYS;
|
||||
|
||||
error = copyin(args, &ua, sizeof ua);
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
||||
error = copyin(ua.n, &n, sizeof n);
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
||||
error = mtrr_get(ua.mtrrp, &n, p, MTRR_GETSET_USER);
|
||||
|
||||
copyout(&n, ua.n, sizeof (int));
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
i386_set_mtrr(struct lwp *l, void *args, register_t *retval)
|
||||
{
|
||||
int error, n;
|
||||
struct i386_set_mtrr_args ua;
|
||||
struct proc *p = l->l_proc;
|
||||
|
||||
if (mtrr_funcs == NULL)
|
||||
return ENOSYS;
|
||||
|
||||
error = suser(p->p_ucred, &p->p_acflag);
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
||||
error = copyin(args, &ua, sizeof ua);
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
||||
error = copyin(ua.n, &n, sizeof n);
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
||||
error = mtrr_set(ua.mtrrp, &n, p, MTRR_GETSET_USER);
|
||||
if (n != 0)
|
||||
mtrr_commit();
|
||||
|
||||
copyout(&n, ua.n, sizeof n);
|
||||
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
sys_sysarch(struct lwp *l, void *v, register_t *retval)
|
||||
{
|
||||
struct sys_sysarch_args /* {
|
||||
syscallarg(int) op;
|
||||
syscallarg(void *) parms;
|
||||
} */ *uap = v;
|
||||
int error = 0;
|
||||
|
||||
switch(SCARG(uap, op)) {
|
||||
#ifdef USER_LDT
|
||||
case I386_GET_LDT:
|
||||
error = i386_get_ldt(l, SCARG(uap, parms), retval);
|
||||
break;
|
||||
|
||||
case I386_SET_LDT:
|
||||
error = i386_set_ldt(l, SCARG(uap, parms), retval);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case I386_IOPL:
|
||||
error = i386_iopl(l, SCARG(uap, parms), retval);
|
||||
break;
|
||||
|
||||
case I386_GET_IOPERM:
|
||||
error = i386_get_ioperm(l, SCARG(uap, parms), retval);
|
||||
break;
|
||||
|
||||
case I386_SET_IOPERM:
|
||||
error = i386_set_ioperm(l, SCARG(uap, parms), retval);
|
||||
break;
|
||||
|
||||
#ifdef VM86
|
||||
case I386_VM86:
|
||||
error = i386_vm86(l, SCARG(uap, parms), retval);
|
||||
break;
|
||||
#ifdef COMPAT_16
|
||||
case I386_OLD_VM86:
|
||||
error = compat_16_i386_vm86(l, SCARG(uap, parms), retval);
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef MTRR
|
||||
case I386_GET_MTRR:
|
||||
error = i386_get_mtrr(l, SCARG(uap, parms), retval);
|
||||
break;
|
||||
case I386_SET_MTRR:
|
||||
error = i386_set_mtrr(l, SCARG(uap, parms), retval);
|
||||
break;
|
||||
#endif
|
||||
#ifdef PERFCTRS
|
||||
case I386_PMC_INFO:
|
||||
error = pmc_info(l, SCARG(uap, parms), retval);
|
||||
break;
|
||||
|
||||
case I386_PMC_STARTSTOP:
|
||||
error = pmc_startstop(l, SCARG(uap, parms), retval);
|
||||
break;
|
||||
|
||||
case I386_PMC_READ:
|
||||
error = pmc_read(l, SCARG(uap, parms), retval);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,680 @@
|
||||
/* $NetBSD: xen_machdep.c,v 1.1.2.1 2004/05/22 15:57:33 he Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2004 Christian Limpach.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Christian Limpach.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: xen_machdep.c,v 1.1.2.1 2004/05/22 15:57:33 he Exp $");
|
||||
|
||||
#include "opt_xen.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include <uvm/uvm.h>
|
||||
|
||||
#include <machine/gdt.h>
|
||||
#include <machine/xenfunc.h>
|
||||
#include <machine/xenpmap.h>
|
||||
|
||||
/* #define XENDEBUG */
|
||||
/* #define XENDEBUG_LOW */
|
||||
|
||||
#ifdef XENDEBUG
|
||||
#define XENPRINTF(x) printf x
|
||||
#define XENPRINTK(x) printk x
|
||||
#define XENPRINTK2(x) /* printk x */
|
||||
|
||||
static char XBUF[256];
|
||||
#else
|
||||
#define XENPRINTF(x)
|
||||
#define XENPRINTK(x)
|
||||
#define XENPRINTK2(x)
|
||||
#endif
|
||||
void printk(char *, ...);
|
||||
#define PRINTF(x) printf x
|
||||
#define PRINTK(x) printk x
|
||||
|
||||
shared_info_t *HYPERVISOR_shared_info;
|
||||
union start_info_union start_info_union;
|
||||
|
||||
void xen_failsafe_handler(void);
|
||||
|
||||
void
|
||||
xen_failsafe_handler(void)
|
||||
{
|
||||
|
||||
panic("xen_failsafe_handler called!\n");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
xen_update_descriptor(union descriptor *table, union descriptor *entry)
|
||||
{
|
||||
paddr_t pa;
|
||||
pt_entry_t *ptp;
|
||||
|
||||
ptp = kvtopte((vaddr_t)table);
|
||||
pa = (*ptp & PG_FRAME) | ((vaddr_t)table & ~PG_FRAME);
|
||||
if (HYPERVISOR_update_descriptor(pa, entry->raw[0], entry->raw[1]))
|
||||
panic("HYPERVISOR_update_descriptor failed\n");
|
||||
}
|
||||
|
||||
void
|
||||
xen_set_ldt(vaddr_t base, uint32_t entries)
|
||||
{
|
||||
vaddr_t va;
|
||||
pt_entry_t *ptp, *maptp;
|
||||
|
||||
for (va = base; va < base + entries * sizeof(union descriptor);
|
||||
va += PAGE_SIZE) {
|
||||
KASSERT(va >= VM_MIN_KERNEL_ADDRESS);
|
||||
ptp = kvtopte(va);
|
||||
maptp = (pt_entry_t *)vtomach((vaddr_t)ptp);
|
||||
XENPRINTF(("xen_set_ldt %p %d %p %p\n", (void *)base,
|
||||
entries, ptp, maptp));
|
||||
PTE_CLEARBITS(ptp, maptp, PG_RW);
|
||||
}
|
||||
PTE_UPDATES_FLUSH();
|
||||
|
||||
xpq_queue_set_ldt(base, entries);
|
||||
xpq_flush_queue();
|
||||
}
|
||||
|
||||
void
|
||||
lgdt(struct region_descriptor *rdp)
|
||||
{
|
||||
|
||||
panic("lgdt %p %08x\n", (void *)rdp->rd_base, rdp->rd_limit);
|
||||
}
|
||||
|
||||
void
|
||||
xen_parse_cmdline(int what, union xen_cmdline_parseinfo *xcp)
|
||||
{
|
||||
char *cmd_line, *opt, *s;
|
||||
int b, i, ipidx = 0;
|
||||
uint32_t xi_ip[5];
|
||||
|
||||
cmd_line = xen_start_info.cmd_line;
|
||||
|
||||
switch (what) {
|
||||
case XEN_PARSE_BOOTDEV:
|
||||
xcp->xcp_bootdev[0] = 0;
|
||||
break;
|
||||
case XEN_PARSE_CONSOLE:
|
||||
xcp->xcp_console[0] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
while (cmd_line && *cmd_line) {
|
||||
opt = cmd_line;
|
||||
cmd_line = strchr(opt, ' ');
|
||||
if (cmd_line)
|
||||
*cmd_line = 0;
|
||||
|
||||
switch (what) {
|
||||
case XEN_PARSE_BOOTDEV:
|
||||
if (strncasecmp(opt, "bootdev=", 8) == 0)
|
||||
strncpy(xcp->xcp_bootdev, opt + 8,
|
||||
sizeof(xcp->xcp_console));
|
||||
break;
|
||||
|
||||
case XEN_PARSE_NETINFO:
|
||||
if (xcp->xcp_netinfo.xi_root &&
|
||||
strncasecmp(opt, "nfsroot=", 8) == 0)
|
||||
strncpy(xcp->xcp_netinfo.xi_root, opt + 8,
|
||||
MNAMELEN);
|
||||
|
||||
if (strncasecmp(opt, "ip=", 3) == 0) {
|
||||
memset(xi_ip, 0, sizeof(xi_ip));
|
||||
opt += 3;
|
||||
ipidx = 0;
|
||||
while (opt && *opt) {
|
||||
s = opt;
|
||||
opt = strchr(opt, ':');
|
||||
if (opt)
|
||||
*opt = 0;
|
||||
|
||||
switch (ipidx) {
|
||||
case 0: /* ip */
|
||||
case 1: /* nfs server */
|
||||
case 2: /* gw */
|
||||
case 3: /* mask */
|
||||
case 4: /* host */
|
||||
if (*s == 0)
|
||||
break;
|
||||
for (i = 0; i < 4; i++) {
|
||||
b = strtoul(s, &s, 10);
|
||||
xi_ip[ipidx] = b + 256
|
||||
* xi_ip[ipidx];
|
||||
if (*s != '.')
|
||||
break;
|
||||
s++;
|
||||
}
|
||||
if (i < 3)
|
||||
xi_ip[ipidx] = 0;
|
||||
break;
|
||||
case 5: /* interface */
|
||||
if (!strncmp(s, "xennet", 6))
|
||||
s += 6;
|
||||
else if (!strncmp(s, "eth", 3))
|
||||
s += 3;
|
||||
else
|
||||
break;
|
||||
if (xcp->xcp_netinfo.xi_ifno
|
||||
== strtoul(s, NULL, 10))
|
||||
memcpy(xcp->
|
||||
xcp_netinfo.xi_ip,
|
||||
xi_ip,
|
||||
sizeof(xi_ip));
|
||||
break;
|
||||
}
|
||||
ipidx++;
|
||||
|
||||
if (opt)
|
||||
*opt++ = ':';
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case XEN_PARSE_CONSOLE:
|
||||
if (strncasecmp(opt, "console=", 8) == 0)
|
||||
strncpy(xcp->xcp_console, opt + 8,
|
||||
sizeof(xcp->xcp_console));
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (cmd_line)
|
||||
*cmd_line++ = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define XEN_PAGE_OFFSET 0xC0100000
|
||||
|
||||
static pd_entry_t
|
||||
xpmap_get_bootpde(paddr_t va)
|
||||
{
|
||||
|
||||
return ((pd_entry_t *)xen_start_info.pt_base)[va >> PDSHIFT];
|
||||
}
|
||||
|
||||
static pd_entry_t
|
||||
xpmap_get_vbootpde(paddr_t va)
|
||||
{
|
||||
pd_entry_t pde;
|
||||
|
||||
pde = xpmap_get_bootpde(va);
|
||||
if ((pde & PG_V) == 0)
|
||||
return (pde & ~PG_FRAME);
|
||||
return (pde & ~PG_FRAME) |
|
||||
(xpmap_mtop(pde & PG_FRAME) + KERNBASE);
|
||||
}
|
||||
|
||||
static pt_entry_t *
|
||||
xpmap_get_bootptep(paddr_t va)
|
||||
{
|
||||
pd_entry_t pde;
|
||||
|
||||
pde = xpmap_get_vbootpde(va);
|
||||
if ((pde & PG_V) == 0)
|
||||
return (void *)-1;
|
||||
return &(((pt_entry_t *)(pde & PG_FRAME))[(va & PT_MASK) >> PAGE_SHIFT]);
|
||||
}
|
||||
|
||||
static pt_entry_t
|
||||
xpmap_get_bootpte(paddr_t va)
|
||||
{
|
||||
|
||||
return xpmap_get_bootptep(va)[0];
|
||||
}
|
||||
|
||||
#if defined(XENDEBUG)
|
||||
static void
|
||||
xpmap_dump_pt(pt_entry_t *ptp, int p)
|
||||
{
|
||||
pt_entry_t pte;
|
||||
int j;
|
||||
int bufpos;
|
||||
|
||||
pte = xpmap_ptom((uint32_t)ptp - KERNBASE);
|
||||
PRINTK(("%03x: %p(%p) %08x\n", p, ptp, (void *)pte, p << PDSHIFT));
|
||||
|
||||
bufpos = 0;
|
||||
for (j = 0; j < PTES_PER_PTP; j++) {
|
||||
if ((ptp[j] & PG_V) == 0)
|
||||
continue;
|
||||
pte = ptp[j] /* & PG_FRAME */;
|
||||
bufpos += sprintf(XBUF + bufpos, "%x:%03x:%08x ",
|
||||
p, j, pte);
|
||||
if (bufpos > 70) {
|
||||
int k;
|
||||
sprintf(XBUF + bufpos, "\n");
|
||||
PRINTK((XBUF));
|
||||
bufpos = 0;
|
||||
for (k = 0; k < 1000000; k++);
|
||||
}
|
||||
}
|
||||
if (bufpos) {
|
||||
PRINTK((XBUF));
|
||||
PRINTK(("\n"));
|
||||
bufpos = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
xpmap_init(void)
|
||||
{
|
||||
pd_entry_t *xen_pdp;
|
||||
pt_entry_t *ptp, *sysptp;
|
||||
pt_entry_t pte;
|
||||
uint32_t i, j;
|
||||
int bufpos;
|
||||
#if defined(XENDEBUG_LOW)
|
||||
extern char kernel_text, _etext, __bss_start, end, *esym;
|
||||
#endif
|
||||
|
||||
xpmap_phys_to_machine_mapping = (void *)xen_start_info.mfn_list;
|
||||
|
||||
xen_pdp = (pd_entry_t *)xen_start_info.pt_base;
|
||||
|
||||
XENPRINTK(("text %p data %p bss %p end %p esym %p\n", &kernel_text,
|
||||
&_etext, &__bss_start, &end, esym));
|
||||
XENPRINTK(("xpmap_init PTD %p nkpde %d upages %d xen_PTD %p p2m-map %p\n",
|
||||
(void *)PTDpaddr, nkpde, UPAGES, xen_pdp,
|
||||
xpmap_phys_to_machine_mapping));
|
||||
|
||||
bufpos = 0;
|
||||
|
||||
XENPRINTK(("shared_inf %08x\n", (paddr_t)xen_start_info.shared_info));
|
||||
XENPRINTK(("c0100000: %08x\n",
|
||||
xpmap_get_bootpte(0xc0100000)));
|
||||
|
||||
/* Map kernel. */
|
||||
|
||||
/* Map kernel data/bss/tables. */
|
||||
|
||||
/* Map ISA I/O memory. */
|
||||
|
||||
/* Map kernel PDEs. */
|
||||
|
||||
/* Install a PDE recursively mapping page directory as a page table! */
|
||||
|
||||
sysptp = (pt_entry_t *)(PTDpaddr + ((1 + UPAGES) << PAGE_SHIFT));
|
||||
|
||||
/* make xen's PDE and PTE pages read-only in our pagetable */
|
||||
for (i = 0; i < xen_start_info.nr_pt_frames; i++) {
|
||||
/* mark PTE page read-only in our table */
|
||||
sysptp[((xen_start_info.pt_base +
|
||||
(i << PAGE_SHIFT) - KERNBASE_LOCORE) &
|
||||
(PD_MASK | PT_MASK)) >> PAGE_SHIFT] &= ~PG_RW;
|
||||
}
|
||||
|
||||
xpq_flush_queue();
|
||||
|
||||
for (i = 0; i < 1 + UPAGES + nkpde; i++) {
|
||||
/* mark PTE page read-only in xen's table */
|
||||
ptp = xpmap_get_bootptep(PTDpaddr + (i << PAGE_SHIFT));
|
||||
xpq_queue_pte_update(
|
||||
(void *)xpmap_ptom((unsigned long)ptp - KERNBASE), *ptp & ~PG_RW);
|
||||
XENPRINTK(("%03x: %p(%p) -> %08x\n", i, ptp,
|
||||
(unsigned long)ptp - KERNTEXTOFF, *ptp));
|
||||
|
||||
/* mark PTE page read-only in our table */
|
||||
sysptp[((PTDpaddr + (i << PAGE_SHIFT) - KERNBASE_LOCORE) &
|
||||
(PD_MASK | PT_MASK)) >> PAGE_SHIFT] &= ~PG_RW;
|
||||
|
||||
/* update our pte's */
|
||||
ptp = (pt_entry_t *)(PTDpaddr + (i << PAGE_SHIFT));
|
||||
#if 0
|
||||
pte = xpmap_ptom((uint32_t)ptp - KERNBASE);
|
||||
XENPRINTK(("%03x: %p(%p) %08x\n", i, ptp, pte, i << PDSHIFT));
|
||||
#endif
|
||||
for (j = 0; j < PTES_PER_PTP; j++) {
|
||||
if ((ptp[j] & PG_V) == 0)
|
||||
continue;
|
||||
if (ptp[j] == 0xffffffff)
|
||||
ptp[j] = xen_start_info.shared_info |
|
||||
(PG_V|PG_RW);
|
||||
if (ptp[j] >= KERNTEXTOFF) {
|
||||
pte = ptp[j];
|
||||
ptp[j] = (pte & ~PG_FRAME) |
|
||||
(xpmap_get_bootpte(pte & PG_FRAME) &
|
||||
PG_FRAME);
|
||||
}
|
||||
#if defined(XENDEBUG) && 0
|
||||
pte = ptp[j] /* & PG_FRAME */;
|
||||
bufpos += sprintf(XBUF + bufpos, "%x:%03x:%08x ",
|
||||
i, j, pte);
|
||||
if (bufpos > 70) {
|
||||
int k;
|
||||
sprintf(XBUF + bufpos, "\n");
|
||||
XENPRINTK((XBUF));
|
||||
bufpos = 0;
|
||||
for (k = 0; k < 1000000; k++);
|
||||
}
|
||||
}
|
||||
if (bufpos) {
|
||||
XENPRINTK((XBUF));
|
||||
bufpos = 0;
|
||||
#endif
|
||||
}
|
||||
if (i == 0)
|
||||
i = 1 + UPAGES - 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (i = 0x300; i < 0x305; i++)
|
||||
if (((pt_entry_t *)xen_start_info.pt_base)[i] & PG_V)
|
||||
xpmap_dump_pt((pt_entry_t *)
|
||||
(xpmap_mtop(((pt_entry_t *)xen_start_info.pt_base)[i] &
|
||||
PG_FRAME) + KERNBASE), i);
|
||||
xpmap_dump_pt((pt_entry_t *)xen_start_info.pt_base, 0);
|
||||
#endif
|
||||
|
||||
XENPRINTK(("switching pdp: %p, %08lx, %p, %p, %p\n", (void *)PTDpaddr,
|
||||
PTDpaddr - KERNBASE,
|
||||
(void *)xpmap_ptom(PTDpaddr - KERNBASE),
|
||||
(void *)xpmap_get_bootpte(PTDpaddr),
|
||||
(void *)xpmap_mtop(xpmap_ptom(PTDpaddr - KERNBASE))));
|
||||
|
||||
#if defined(XENDEBUG)
|
||||
xpmap_dump_pt((pt_entry_t *)PTDpaddr, 0);
|
||||
#endif
|
||||
|
||||
xpq_flush_queue();
|
||||
|
||||
xpq_queue_pin_table(xpmap_get_bootpte(PTDpaddr) & PG_FRAME,
|
||||
XPQ_PIN_L2_TABLE);
|
||||
xpq_queue_pt_switch(xpmap_get_bootpte(PTDpaddr) & PG_FRAME);
|
||||
xpq_queue_unpin_table(
|
||||
xpmap_get_bootpte(xen_start_info.pt_base) & PG_FRAME);
|
||||
|
||||
/* make xen's PDE and PTE pages writable in our pagetable */
|
||||
for (i = 0; i < xen_start_info.nr_pt_frames; i++) {
|
||||
/* mark PTE page writable in our table */
|
||||
ptp = &sysptp[((xen_start_info.pt_base +
|
||||
(i << PAGE_SHIFT) - KERNBASE_LOCORE) &
|
||||
(PD_MASK | PT_MASK)) >> PAGE_SHIFT];
|
||||
xpq_queue_pte_update(
|
||||
(void *)xpmap_ptom((unsigned long)ptp - KERNBASE), *ptp |
|
||||
PG_RW);
|
||||
}
|
||||
|
||||
xpq_flush_queue();
|
||||
XENPRINTK(("pt_switch done!\n"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a binary search to find out where physical memory ends on the
|
||||
* real hardware. Xen will fail our updates if they are beyond the
|
||||
* last available page (max_page in xen/common/memory.c).
|
||||
*/
|
||||
paddr_t
|
||||
find_pmap_mem_end(vaddr_t va)
|
||||
{
|
||||
mmu_update_t r;
|
||||
int start, end, ok;
|
||||
pt_entry_t old;
|
||||
|
||||
start = xen_start_info.nr_pages;
|
||||
end = HYPERVISOR_VIRT_START >> PAGE_SHIFT;
|
||||
|
||||
r.ptr = (unsigned long)&PTE_BASE[x86_btop(va)];
|
||||
old = PTE_BASE[x86_btop(va)];
|
||||
|
||||
while (start + 1 < end) {
|
||||
r.val = (((start + end) / 2) << PAGE_SHIFT) | PG_V;
|
||||
|
||||
if (HYPERVISOR_mmu_update(&r, 1, &ok) < 0)
|
||||
end = (start + end) / 2;
|
||||
else
|
||||
start = (start + end) / 2;
|
||||
}
|
||||
r.val = old;
|
||||
if (HYPERVISOR_mmu_update(&r, 1, &ok) < 0)
|
||||
printf("pmap_mem_end find: old update failed %08x\n",
|
||||
old);
|
||||
|
||||
return end << PAGE_SHIFT;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
void xpmap_find_memory(paddr_t);
|
||||
void
|
||||
xpmap_find_memory(paddr_t first_avail)
|
||||
{
|
||||
char buf[256];
|
||||
uint32_t i;
|
||||
int bufpos;
|
||||
paddr_t p;
|
||||
|
||||
bufpos = 0;
|
||||
for (i = ((first_avail - KERNTEXTOFF) >> PAGE_SHIFT);
|
||||
i < xen_start_info.nr_pages; i++) {
|
||||
/* if (xpmap_phys_to_machine_mapping[i] */
|
||||
bufpos += sprintf(buf + bufpos, "%03x:%08x:%08x ",
|
||||
i, (uint32_t)xpmap_phys_to_machine_mapping[i],
|
||||
(uint32_t)xpmap_mtop(xpmap_phys_to_machine_mapping[i] <<
|
||||
PAGE_SHIFT));
|
||||
p = xpmap_phys_to_machine_mapping[i];
|
||||
uvm_page_physload(p, p + 1, p, p + 1, VM_FREELIST_DEFAULT);
|
||||
|
||||
if (bufpos > 70) {
|
||||
int k;
|
||||
sprintf(buf + bufpos, "\n");
|
||||
XENPRINTK((buf));
|
||||
bufpos = 0;
|
||||
for (k = 0; k < 1000000; k++);
|
||||
}
|
||||
}
|
||||
if (bufpos) {
|
||||
XENPRINTK((buf));
|
||||
bufpos = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef XENDEBUG
|
||||
void xpq_debug_dump(void);
|
||||
#endif
|
||||
|
||||
#define XPQUEUE_SIZE 2048
|
||||
typedef union xpq_queue {
|
||||
struct {
|
||||
pd_entry_t *ptr;
|
||||
pd_entry_t val;
|
||||
} pde;
|
||||
struct {
|
||||
pt_entry_t *ptr;
|
||||
pt_entry_t val;
|
||||
} pte;
|
||||
struct {
|
||||
paddr_t ptr;
|
||||
uint32_t val;
|
||||
} pa;
|
||||
} xpq_queue_t;
|
||||
static xpq_queue_t xpq_queue[XPQUEUE_SIZE];
|
||||
static int xpq_idx = 0;
|
||||
|
||||
void
|
||||
xpq_flush_queue()
|
||||
{
|
||||
int i, ok;
|
||||
|
||||
XENPRINTK2(("flush queue %p entries %d\n", xpq_queue, xpq_idx));
|
||||
for (i = 0; i < xpq_idx; i++)
|
||||
XENPRINTK2(("%d: %p %08x\n", i, xpq_queue[i].pde.ptr,
|
||||
xpq_queue[i].pde.val));
|
||||
if (xpq_idx != 0 &&
|
||||
HYPERVISOR_mmu_update((mmu_update_t *)xpq_queue, xpq_idx, &ok) < 0)
|
||||
panic("HYPERVISOR_mmu_update failed\n");
|
||||
xpq_idx = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
xpq_increment_idx(void)
|
||||
{
|
||||
|
||||
xpq_idx++;
|
||||
if (__predict_false(xpq_idx == XPQUEUE_SIZE))
|
||||
xpq_flush_queue();
|
||||
}
|
||||
|
||||
void
|
||||
xpq_queue_invlpg(vaddr_t va)
|
||||
{
|
||||
|
||||
XENPRINTK2(("xpq_queue_invlpg %p\n", (void *)va));
|
||||
xpq_queue[xpq_idx].pa.ptr = (va & PG_FRAME) | MMU_EXTENDED_COMMAND;
|
||||
xpq_queue[xpq_idx].pa.val = MMUEXT_INVLPG;
|
||||
xpq_increment_idx();
|
||||
}
|
||||
|
||||
void
|
||||
xpq_queue_pde_update(pd_entry_t *ptr, pd_entry_t val)
|
||||
{
|
||||
|
||||
xpq_queue[xpq_idx].pde.ptr = ptr;
|
||||
xpq_queue[xpq_idx].pde.val = val;
|
||||
xpq_increment_idx();
|
||||
}
|
||||
|
||||
void
|
||||
xpq_queue_pte_update(pt_entry_t *ptr, pt_entry_t val)
|
||||
{
|
||||
|
||||
xpq_queue[xpq_idx].pte.ptr = ptr;
|
||||
xpq_queue[xpq_idx].pte.val = val;
|
||||
xpq_increment_idx();
|
||||
}
|
||||
|
||||
void
|
||||
xpq_queue_unchecked_pte_update(pt_entry_t *ptr, pt_entry_t val)
|
||||
{
|
||||
|
||||
xpq_queue[xpq_idx].pa.ptr = (paddr_t)ptr | MMU_NORMAL_PT_UPDATE;
|
||||
/* XXXcl UNCHECKED_PT_UPDATE */
|
||||
xpq_queue[xpq_idx].pa.val = val;
|
||||
xpq_increment_idx();
|
||||
}
|
||||
|
||||
void
|
||||
xpq_queue_pt_switch(paddr_t pa)
|
||||
{
|
||||
|
||||
XENPRINTK2(("xpq_queue_pt_switch: %p %p\n", (void *)pa, (void *)pa));
|
||||
xpq_queue[xpq_idx].pa.ptr = pa | MMU_EXTENDED_COMMAND;
|
||||
xpq_queue[xpq_idx].pa.val = MMUEXT_NEW_BASEPTR;
|
||||
xpq_increment_idx();
|
||||
}
|
||||
|
||||
void
|
||||
xpq_queue_pin_table(paddr_t pa, int type)
|
||||
{
|
||||
|
||||
XENPRINTK2(("xpq_queue_pin_table: %p %p\n", (void *)pa, (void *)pa));
|
||||
xpq_queue[xpq_idx].pa.ptr = pa | MMU_EXTENDED_COMMAND;
|
||||
switch (type) {
|
||||
case XPQ_PIN_L1_TABLE:
|
||||
xpq_queue[xpq_idx].pa.val = MMUEXT_PIN_L1_TABLE;
|
||||
break;
|
||||
case XPQ_PIN_L2_TABLE:
|
||||
xpq_queue[xpq_idx].pa.val = MMUEXT_PIN_L2_TABLE;
|
||||
break;
|
||||
}
|
||||
xpq_increment_idx();
|
||||
}
|
||||
|
||||
void
|
||||
xpq_queue_unpin_table(paddr_t pa)
|
||||
{
|
||||
|
||||
XENPRINTK2(("xpq_queue_unpin_table: %p %p\n", (void *)pa, (void *)pa));
|
||||
xpq_queue[xpq_idx].pa.ptr = pa | MMU_EXTENDED_COMMAND;
|
||||
xpq_queue[xpq_idx].pa.val = MMUEXT_UNPIN_TABLE;
|
||||
xpq_increment_idx();
|
||||
}
|
||||
|
||||
void
|
||||
xpq_queue_set_ldt(vaddr_t va, uint32_t entries)
|
||||
{
|
||||
|
||||
XENPRINTK2(("xpq_queue_set_ldt\n"));
|
||||
KASSERT(va == (va & PG_FRAME));
|
||||
xpq_queue[xpq_idx].pa.ptr = MMU_EXTENDED_COMMAND | va;
|
||||
xpq_queue[xpq_idx].pa.val = MMUEXT_SET_LDT |
|
||||
(entries << MMUEXT_CMD_SHIFT);
|
||||
xpq_increment_idx();
|
||||
}
|
||||
|
||||
void
|
||||
xpq_queue_tlb_flush()
|
||||
{
|
||||
|
||||
XENPRINTK2(("xpq_queue_tlb_flush\n"));
|
||||
xpq_queue[xpq_idx].pa.ptr = MMU_EXTENDED_COMMAND;
|
||||
xpq_queue[xpq_idx].pa.val = MMUEXT_TLB_FLUSH;
|
||||
xpq_increment_idx();
|
||||
}
|
||||
|
||||
#ifdef XENDEBUG
|
||||
void
|
||||
xpq_debug_dump()
|
||||
{
|
||||
int i;
|
||||
|
||||
XENPRINTK2(("idx: %d\n", xpq_idx));
|
||||
for (i = 0; i < xpq_idx; i++) {
|
||||
sprintf(XBUF, "%p %08x ", xpq_queue[i].pte.ptr,
|
||||
xpq_queue[i].pte.val);
|
||||
if (++i < xpq_idx)
|
||||
sprintf(XBUF + strlen(XBUF), "%p %08x ",
|
||||
xpq_queue[i].pte.ptr, xpq_queue[i].pte.val);
|
||||
if (++i < xpq_idx)
|
||||
sprintf(XBUF + strlen(XBUF), "%p %08x ",
|
||||
xpq_queue[i].pte.ptr, xpq_queue[i].pte.val);
|
||||
if (++i < xpq_idx)
|
||||
sprintf(XBUF + strlen(XBUF), "%p %08x ",
|
||||
xpq_queue[i].pte.ptr, xpq_queue[i].pte.val);
|
||||
XENPRINTK2(("%d: %s\n", xpq_idx, XBUF));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,130 @@
|
||||
/* $NetBSD: frameasm.h,v 1.1 2004/03/11 21:44:08 cl Exp $ */
|
||||
/* NetBSD: frameasm.h,v 1.4 2004/02/20 17:35:01 yamt Exp */
|
||||
|
||||
#ifndef _I386_FRAMEASM_H_
|
||||
#define _I386_FRAMEASM_H_
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_multiprocessor.h"
|
||||
#endif
|
||||
|
||||
/* XXX assym.h */
|
||||
#define TRAP_INSTR int $0x82
|
||||
#define __HYPERVISOR_stack_switch 4
|
||||
#define __HYPERVISOR_fpu_taskswitch 7
|
||||
|
||||
#ifndef TRAPLOG
|
||||
#define TLOG /**/
|
||||
#else
|
||||
/*
|
||||
* Fill in trap record
|
||||
*/
|
||||
#define TLOG \
|
||||
9: \
|
||||
movl %fs:CPU_TLOG_OFFSET, %eax; \
|
||||
movl %fs:CPU_TLOG_BASE, %ebx; \
|
||||
addl $SIZEOF_TREC,%eax; \
|
||||
andl $SIZEOF_TLOG-1,%eax; \
|
||||
addl %eax,%ebx; \
|
||||
movl %eax,%fs:CPU_TLOG_OFFSET; \
|
||||
movl %esp,TREC_SP(%ebx); \
|
||||
movl $9b,TREC_HPC(%ebx); \
|
||||
movl TF_EIP(%esp),%eax; \
|
||||
movl %eax,TREC_IPC(%ebx); \
|
||||
rdtsc ; \
|
||||
movl %eax,TREC_TSC(%ebx); \
|
||||
movl $MSR_LASTBRANCHFROMIP,%ecx; \
|
||||
rdmsr ; \
|
||||
movl %eax,TREC_LBF(%ebx); \
|
||||
incl %ecx ; \
|
||||
rdmsr ; \
|
||||
movl %eax,TREC_LBT(%ebx); \
|
||||
incl %ecx ; \
|
||||
rdmsr ; \
|
||||
movl %eax,TREC_IBF(%ebx); \
|
||||
incl %ecx ; \
|
||||
rdmsr ; \
|
||||
movl %eax,TREC_IBT(%ebx)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These are used on interrupt or trap entry or exit.
|
||||
*/
|
||||
#define INTRENTRY \
|
||||
cld; \
|
||||
subl $TF_PUSHSIZE,%esp ; \
|
||||
movl %gs,TF_GS(%esp) ; \
|
||||
movl %fs,TF_FS(%esp) ; \
|
||||
movl %eax,TF_EAX(%esp) ; \
|
||||
movl %es,TF_ES(%esp) ; \
|
||||
movl %ds,TF_DS(%esp) ; \
|
||||
movl $GSEL(GDATA_SEL, SEL_KPL),%eax ; \
|
||||
movl %edi,TF_EDI(%esp) ; \
|
||||
movl %esi,TF_ESI(%esp) ; \
|
||||
movl %eax,%ds ; \
|
||||
movl %ebp,TF_EBP(%esp) ; \
|
||||
movl %eax,%es ; \
|
||||
movl %ebx,TF_EBX(%esp) ; \
|
||||
movl %eax,%gs ; \
|
||||
movl %edx,TF_EDX(%esp) ; \
|
||||
movl $GSEL(GCPU_SEL, SEL_KPL),%eax ; \
|
||||
movl %ecx,TF_ECX(%esp) ; \
|
||||
movl %eax,%fs ; \
|
||||
TLOG
|
||||
|
||||
#define INTRFASTEXIT \
|
||||
movl TF_GS(%esp),%gs ; \
|
||||
movl TF_FS(%esp),%fs ; \
|
||||
movl TF_ES(%esp),%es ; \
|
||||
movl TF_DS(%esp),%ds ; \
|
||||
movl TF_EDI(%esp),%edi ; \
|
||||
movl TF_ESI(%esp),%esi ; \
|
||||
movl TF_EBP(%esp),%ebp ; \
|
||||
movl TF_EBX(%esp),%ebx ; \
|
||||
movl TF_EDX(%esp),%edx ; \
|
||||
movl TF_ECX(%esp),%ecx ; \
|
||||
movl TF_EAX(%esp),%eax ; \
|
||||
addl $(TF_PUSHSIZE+8),%esp ; \
|
||||
iret
|
||||
|
||||
#define DO_DEFERRED_SWITCH(reg) \
|
||||
cmpl $0, CPUVAR(WANT_PMAPLOAD) ; \
|
||||
jz 1f ; \
|
||||
call _C_LABEL(pmap_load) ; \
|
||||
1:
|
||||
|
||||
#define CHECK_DEFERRED_SWITCH(reg) \
|
||||
cmpl $0, CPUVAR(WANT_PMAPLOAD)
|
||||
|
||||
#define CHECK_ASTPENDING(reg) movl CPUVAR(CURLWP),reg ; \
|
||||
cmpl $0, reg ; \
|
||||
je 1f ; \
|
||||
movl L_PROC(reg),reg ; \
|
||||
cmpl $0, P_MD_ASTPENDING(reg); \
|
||||
1:
|
||||
#define CLEAR_ASTPENDING(reg) movl $0, P_MD_ASTPENDING(reg)
|
||||
|
||||
#if !defined(XEN)
|
||||
#define CLI(reg) cli
|
||||
#define STI(reg) sti
|
||||
#else
|
||||
/* XXX assym.h */
|
||||
#define EVENTS_MASK 136
|
||||
/* Offsets into shared_info_t. */
|
||||
#define evtchn_upcall_pending /* 0 */
|
||||
#define evtchn_upcall_mask 1
|
||||
|
||||
#define XEN_BLOCK_EVENTS(reg) movb $1,evtchn_upcall_mask(reg)
|
||||
#define XEN_UNBLOCK_EVENTS(reg) movb $0,evtchn_upcall_mask(reg)
|
||||
#define XEN_TEST_PENDING(reg) testb $0xFF,evtchn_upcall_pending(%reg)
|
||||
|
||||
#define CLI(reg) movl _C_LABEL(HYPERVISOR_shared_info),reg ; \
|
||||
XEN_BLOCK_EVENTS(reg)
|
||||
#define STI(reg) movl _C_LABEL(HYPERVISOR_shared_info),reg ; \
|
||||
XEN_UNBLOCK_EVENTS(reg)
|
||||
#define STIC(reg) movl _C_LABEL(HYPERVISOR_shared_info),reg ; \
|
||||
XEN_UNBLOCK_EVENTS(reg) ; \
|
||||
testb $1,evtchn_upcall_pending(reg)
|
||||
#endif
|
||||
|
||||
#endif /* _I386_FRAMEASM_H_ */
|
||||
@@ -0,0 +1,423 @@
|
||||
/* $NetBSD: hypervisor.h,v 1.1.2.2 2004/06/17 09:23:19 tron Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
* Communication to/from hypervisor.
|
||||
*
|
||||
* Copyright (c) 2002-2003, K A Fraser
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _XEN_HYPERVISOR_H_
|
||||
#define _XEN_HYPERVISOR_H_
|
||||
|
||||
|
||||
struct hypervisor_attach_args {
|
||||
const char *haa_busname;
|
||||
};
|
||||
|
||||
struct xencons_attach_args {
|
||||
const char *xa_device;
|
||||
};
|
||||
|
||||
struct xen_npx_attach_args {
|
||||
const char *xa_device;
|
||||
};
|
||||
|
||||
|
||||
#define u8 uint8_t
|
||||
#define u16 uint16_t
|
||||
#define u32 uint32_t
|
||||
#define u64 uint64_t
|
||||
#define s8 int8_t
|
||||
#define s16 int16_t
|
||||
#define s32 int32_t
|
||||
#define s64 int64_t
|
||||
|
||||
/* include the hypervisor interface */
|
||||
#include <sys/systm.h>
|
||||
#include <machine/hypervisor-ifs/hypervisor-if.h>
|
||||
#include <machine/hypervisor-ifs/dom0_ops.h>
|
||||
#include <machine/hypervisor-ifs/event_channel.h>
|
||||
#include <machine/hypervisor-ifs/io/domain_controller.h>
|
||||
#include <machine/hypervisor-ifs/io/netif.h>
|
||||
|
||||
#undef u8
|
||||
#undef u16
|
||||
#undef u32
|
||||
#undef u64
|
||||
#undef s8
|
||||
#undef s16
|
||||
#undef s32
|
||||
#undef s64
|
||||
|
||||
|
||||
/*
|
||||
* a placeholder for the start of day information passed up from the hypervisor
|
||||
*/
|
||||
union start_info_union
|
||||
{
|
||||
start_info_t start_info;
|
||||
char padding[512];
|
||||
};
|
||||
extern union start_info_union start_info_union;
|
||||
#define xen_start_info (start_info_union.start_info)
|
||||
|
||||
|
||||
/* hypervisor.c */
|
||||
void do_hypervisor_callback(struct trapframe *regs);
|
||||
void hypervisor_notify_via_evtchn(unsigned int);
|
||||
void hypervisor_enable_irq(unsigned int);
|
||||
void hypervisor_disable_irq(unsigned int);
|
||||
void hypervisor_acknowledge_irq(unsigned int);
|
||||
|
||||
/* hypervisor_machdep.c */
|
||||
void hypervisor_unmask_event(unsigned int);
|
||||
void hypervisor_mask_event(unsigned int);
|
||||
void hypervisor_clear_event(unsigned int);
|
||||
void hypervisor_force_callback(void);
|
||||
|
||||
/*
|
||||
* Assembler stubs for hyper-calls.
|
||||
*/
|
||||
|
||||
static inline int HYPERVISOR_set_trap_table(trap_info_t *table)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_set_trap_table),
|
||||
"b" (table) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_mmu_update(mmu_update_t *req, int count,
|
||||
int *success_count)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_mmu_update),
|
||||
"b" (req), "c" (count), "d" (success_count) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_set_gdt),
|
||||
"b" (frame_list), "c" (entries) : "memory" );
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_stack_switch),
|
||||
"b" (ss), "c" (esp) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_set_callbacks(
|
||||
unsigned long event_selector, unsigned long event_address,
|
||||
unsigned long failsafe_selector, unsigned long failsafe_address)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_set_callbacks),
|
||||
"b" (event_selector), "c" (event_address),
|
||||
"d" (failsafe_selector), "S" (failsafe_address) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_fpu_taskswitch(void)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_fpu_taskswitch) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_yield(void)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_sched_op),
|
||||
"b" (SCHEDOP_yield) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_block(void)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_sched_op),
|
||||
"b" (SCHEDOP_block) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_shutdown(void)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_sched_op),
|
||||
"b" (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift))
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_reboot(void)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_sched_op),
|
||||
"b" (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift))
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_suspend(unsigned long srec)
|
||||
{
|
||||
int ret;
|
||||
/* NB. On suspend, control software expects a suspend record in %esi. */
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_sched_op),
|
||||
"b" (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)),
|
||||
"S" (srec) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline long HYPERVISOR_set_timer_op(uint64_t timeout)
|
||||
{
|
||||
int ret;
|
||||
unsigned long timeout_hi = (unsigned long)(timeout>>32);
|
||||
unsigned long timeout_lo = (unsigned long)timeout;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_set_timer_op),
|
||||
"b" (timeout_hi), "c" (timeout_lo) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_dom0_op(dom0_op_t *dom0_op)
|
||||
{
|
||||
int ret;
|
||||
dom0_op->interface_version = DOM0_INTERFACE_VERSION;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_dom0_op),
|
||||
"b" (dom0_op) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_set_debugreg(int reg, unsigned long value)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_set_debugreg),
|
||||
"b" (reg), "c" (value) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned long HYPERVISOR_get_debugreg(int reg)
|
||||
{
|
||||
unsigned long ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_get_debugreg),
|
||||
"b" (reg) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_update_descriptor(
|
||||
unsigned long pa, unsigned long word1, unsigned long word2)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_update_descriptor),
|
||||
"b" (pa), "c" (word1), "d" (word2) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_set_fast_trap(int idx)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_set_fast_trap),
|
||||
"b" (idx) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_dom_mem_op(unsigned int op,
|
||||
unsigned long *extent_list,
|
||||
unsigned long nr_extents,
|
||||
unsigned int extent_order)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_dom_mem_op),
|
||||
"b" (op), "c" (extent_list), "d" (nr_extents), "S" (extent_order),
|
||||
"D" (DOMID_SELF)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_multicall(void *call_list, int nr_calls)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_multicall),
|
||||
"b" (call_list), "c" (nr_calls) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_update_va_mapping(
|
||||
unsigned long page_nr, unsigned long new_val, unsigned long flags)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_update_va_mapping),
|
||||
"b" (page_nr), "c" (new_val), "d" (flags) : "memory" );
|
||||
|
||||
if (__predict_false(ret < 0))
|
||||
panic("Failed update VA mapping: %08lx, %08lx, %08lx",
|
||||
page_nr, new_val, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_event_channel_op(void *op)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_event_channel_op),
|
||||
"b" (op) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_xen_version(int cmd)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_xen_version),
|
||||
"b" (cmd) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_console_io(int cmd, int count, char *str)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_console_io),
|
||||
"b" (cmd), "c" (count), "d" (str) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_physdev_op(void *physdev_op)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_physdev_op),
|
||||
"b" (physdev_op) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_grant_table_op(void *gnttab_op)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_grant_table_op),
|
||||
"b" (gnttab_op) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_update_va_mapping_otherdomain(
|
||||
unsigned long page_nr, unsigned long new_val, unsigned long flags, domid_t domid)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_update_va_mapping_otherdomain),
|
||||
"b" (page_nr), "c" (new_val), "d" (flags), "S" (domid) :
|
||||
"memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_vm_assist),
|
||||
"b" (cmd), "c" (type) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* _XEN_HYPERVISOR_H_ */
|
||||
@@ -0,0 +1,110 @@
|
||||
/* $NetBSD: if_xennetvar.h,v 1.1.2.1 2004/05/22 15:59:31 he Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2004 Christian Limpach.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Christian Limpach.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _XEN_IF_XENNETVAR_H_
|
||||
#define _XEN_IF_XENNETVAR_H_
|
||||
|
||||
#include <machine/xen.h>
|
||||
|
||||
union xennet_bufarray {
|
||||
struct {
|
||||
struct mbuf *xbtx_m;
|
||||
} xb_tx;
|
||||
struct {
|
||||
vaddr_t xbrx_va;
|
||||
paddr_t xbrx_pa;
|
||||
struct xennet_softc *xbrx_sc;
|
||||
} xb_rx;
|
||||
int xb_next;
|
||||
};
|
||||
|
||||
struct xennet_txbuf {
|
||||
SLIST_ENTRY(xennet_txbuf) xt_next;
|
||||
struct xennet_softc *xt_sc;
|
||||
paddr_t xt_pa;
|
||||
u_char xt_buf[0];
|
||||
};
|
||||
#define TXBUF_PER_PAGE 2
|
||||
#define TXBUF_BUFSIZE (PAGE_SIZE / TXBUF_PER_PAGE) - sizeof(struct xennet_txbuf)
|
||||
|
||||
struct xennet_softc {
|
||||
struct device sc_dev; /* base device glue */
|
||||
struct ethercom sc_ethercom; /* Ethernet common part */
|
||||
|
||||
int sc_ifno;
|
||||
|
||||
uint8_t sc_enaddr[6];
|
||||
|
||||
#ifdef mediacode
|
||||
struct ifmedia sc_media;
|
||||
#endif
|
||||
|
||||
/* What is the status of our connection to the remote backend? */
|
||||
#define BEST_CLOSED 0
|
||||
#define BEST_DISCONNECTED 1
|
||||
#define BEST_CONNECTED 2
|
||||
unsigned int sc_backend_state;
|
||||
|
||||
unsigned int sc_evtchn;
|
||||
unsigned int sc_irq;
|
||||
|
||||
netif_tx_interface_t *sc_tx;
|
||||
netif_rx_interface_t *sc_rx;
|
||||
|
||||
uint32_t sc_tx_entries;
|
||||
uint32_t sc_tx_resp_cons;
|
||||
|
||||
uint32_t sc_rx_resp_cons;
|
||||
uint32_t sc_rx_bufs_to_notify;
|
||||
|
||||
union xennet_bufarray sc_tx_bufa[NETIF_TX_RING_SIZE];
|
||||
union xennet_bufarray sc_rx_bufa[NETIF_TX_RING_SIZE];
|
||||
|
||||
SLIST_HEAD(, xennet_txbuf) sc_tx_bufs;
|
||||
};
|
||||
|
||||
struct xennet_attach_args {
|
||||
const char *xa_device;
|
||||
int xa_handle;
|
||||
};
|
||||
|
||||
struct nfs_diskless;
|
||||
|
||||
int xennet_scan(struct device *, struct xennet_attach_args *, cfprint_t);
|
||||
void xennet_start(struct ifnet *);
|
||||
int xennet_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
|
||||
void xennet_watchdog(struct ifnet *ifp);
|
||||
int xennet_bootstatic_callback(struct nfs_diskless *);
|
||||
|
||||
#endif /* _XEN_IF_XENNETVAR_H_ */
|
||||
@@ -0,0 +1,533 @@
|
||||
/* $NetBSD: pmap.h,v 1.1.2.1 2004/05/22 15:59:58 he Exp $ */
|
||||
/* NetBSD: pmap.h,v 1.79 2004/02/20 17:35:01 yamt Exp */
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1997 Charles D. Cranor and Washington University.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgment:
|
||||
* This product includes software developed by Charles D. Cranor and
|
||||
* Washington University.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* pmap.h: see pmap.c for the history of this pmap module.
|
||||
*/
|
||||
|
||||
#ifndef _I386_PMAP_H_
|
||||
#define _I386_PMAP_H_
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_user_ldt.h"
|
||||
#include "opt_largepages.h"
|
||||
#endif
|
||||
|
||||
#include "opt_xen.h"
|
||||
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/pte.h>
|
||||
#include <machine/xenfunc.h>
|
||||
#include <machine/xenpmap.h>
|
||||
#include <machine/segments.h>
|
||||
#include <uvm/uvm_object.h>
|
||||
|
||||
/*
|
||||
* see pte.h for a description of i386 MMU terminology and hardware
|
||||
* interface.
|
||||
*
|
||||
* a pmap describes a processes' 4GB virtual address space. this
|
||||
* virtual address space can be broken up into 1024 4MB regions which
|
||||
* are described by PDEs in the PDP. the PDEs are defined as follows:
|
||||
*
|
||||
* (ranges are inclusive -> exclusive, just like vm_map_entry start/end)
|
||||
* (the following assumes that KERNBASE is 0xc0000000)
|
||||
*
|
||||
* PDE#s VA range usage
|
||||
* 0->766 0x0 -> 0xbfc00000 user address space
|
||||
* 767 0xbfc00000-> recursive mapping of PDP (used for
|
||||
* 0xc0000000 linear mapping of PTPs)
|
||||
* 768->1023 0xc0000000-> kernel address space (constant
|
||||
* 0xffc00000 across all pmap's/processes)
|
||||
* 1023 0xffc00000-> "alternate" recursive PDP mapping
|
||||
* <end> (for other pmaps)
|
||||
*
|
||||
*
|
||||
* note: a recursive PDP mapping provides a way to map all the PTEs for
|
||||
* a 4GB address space into a linear chunk of virtual memory. in other
|
||||
* words, the PTE for page 0 is the first int mapped into the 4MB recursive
|
||||
* area. the PTE for page 1 is the second int. the very last int in the
|
||||
* 4MB range is the PTE that maps VA 0xffffe000 (the last page in a 4GB
|
||||
* address).
|
||||
*
|
||||
* all pmap's PD's must have the same values in slots 768->1023 so that
|
||||
* the kernel is always mapped in every process. these values are loaded
|
||||
* into the PD at pmap creation time.
|
||||
*
|
||||
* at any one time only one pmap can be active on a processor. this is
|
||||
* the pmap whose PDP is pointed to by processor register %cr3. this pmap
|
||||
* will have all its PTEs mapped into memory at the recursive mapping
|
||||
* point (slot #767 as show above). when the pmap code wants to find the
|
||||
* PTE for a virtual address, all it has to do is the following:
|
||||
*
|
||||
* address of PTE = (767 * 4MB) + (VA / PAGE_SIZE) * sizeof(pt_entry_t)
|
||||
* = 0xbfc00000 + (VA / 4096) * 4
|
||||
*
|
||||
* what happens if the pmap layer is asked to perform an operation
|
||||
* on a pmap that is not the one which is currently active? in that
|
||||
* case we take the PA of the PDP of non-active pmap and put it in
|
||||
* slot 1023 of the active pmap. this causes the non-active pmap's
|
||||
* PTEs to get mapped in the final 4MB of the 4GB address space
|
||||
* (e.g. starting at 0xffc00000).
|
||||
*
|
||||
* the following figure shows the effects of the recursive PDP mapping:
|
||||
*
|
||||
* PDP (%cr3)
|
||||
* +----+
|
||||
* | 0| -> PTP#0 that maps VA 0x0 -> 0x400000
|
||||
* | |
|
||||
* | |
|
||||
* | 767| -> points back to PDP (%cr3) mapping VA 0xbfc00000 -> 0xc0000000
|
||||
* | 768| -> first kernel PTP (maps 0xc0000000 -> 0xf0400000)
|
||||
* | |
|
||||
* |1023| -> points to alternate pmap's PDP (maps 0xffc00000 -> end)
|
||||
* +----+
|
||||
*
|
||||
* note that the PDE#767 VA (0xbfc00000) is defined as "PTE_BASE"
|
||||
* note that the PDE#1023 VA (0xffc00000) is defined as "APTE_BASE"
|
||||
*
|
||||
* starting at VA 0xbfc00000 the current active PDP (%cr3) acts as a
|
||||
* PTP:
|
||||
*
|
||||
* PTP#767 == PDP(%cr3) => maps VA 0xbfc00000 -> 0xc0000000
|
||||
* +----+
|
||||
* | 0| -> maps the contents of PTP#0 at VA 0xbfc00000->0xbfc01000
|
||||
* | |
|
||||
* | |
|
||||
* | 767| -> maps contents of PTP#767 (the PDP) at VA 0xbffbf000
|
||||
* | 768| -> maps contents of first kernel PTP
|
||||
* | |
|
||||
* |1023|
|
||||
* +----+
|
||||
*
|
||||
* note that mapping of the PDP at PTP#767's VA (0xbffbf000) is
|
||||
* defined as "PDP_BASE".... within that mapping there are two
|
||||
* defines:
|
||||
* "PDP_PDE" (0xbfeffbfc) is the VA of the PDE in the PDP
|
||||
* which points back to itself.
|
||||
* "APDP_PDE" (0xbfeffffc) is the VA of the PDE in the PDP which
|
||||
* establishes the recursive mapping of the alternate pmap.
|
||||
* to set the alternate PDP, one just has to put the correct
|
||||
* PA info in *APDP_PDE.
|
||||
*
|
||||
* note that in the APTE_BASE space, the APDP appears at VA
|
||||
* "APDP_BASE" (0xfffff000).
|
||||
*/
|
||||
/* XXX MP should we allocate one APDP_PDE per processor?? */
|
||||
|
||||
/*
|
||||
* the following defines identify the slots used as described above.
|
||||
*/
|
||||
|
||||
#define PDSLOT_PTE ((KERNBASE/NBPD)-1) /* 767: for recursive PDP map */
|
||||
#define PDSLOT_KERN (KERNBASE/NBPD) /* 768: start of kernel space */
|
||||
#define PDSLOT_APTE ((unsigned)1023-16) /* 1023: alternative recursive slot */
|
||||
|
||||
/*
|
||||
* the following defines give the virtual addresses of various MMU
|
||||
* data structures:
|
||||
* PTE_BASE and APTE_BASE: the base VA of the linear PTE mappings
|
||||
* PTD_BASE and APTD_BASE: the base VA of the recursive mapping of the PTD
|
||||
* PDP_PDE and APDP_PDE: the VA of the PDE that points back to the PDP/APDP
|
||||
*/
|
||||
|
||||
#define PTE_BASE ((pt_entry_t *) (PDSLOT_PTE * NBPD) )
|
||||
#define APTE_BASE ((pt_entry_t *) (PDSLOT_APTE * NBPD) )
|
||||
#define PDP_BASE ((pd_entry_t *)(((char *)PTE_BASE) + (PDSLOT_PTE * PAGE_SIZE)))
|
||||
#define APDP_BASE ((pd_entry_t *)(((char *)APTE_BASE) + (PDSLOT_APTE * PAGE_SIZE)))
|
||||
#define PDP_PDE (PDP_BASE + PDSLOT_PTE)
|
||||
#define APDP_PDE (PDP_BASE + PDSLOT_APTE)
|
||||
|
||||
/*
|
||||
* the follow define determines how many PTPs should be set up for the
|
||||
* kernel by locore.s at boot time. this should be large enough to
|
||||
* get the VM system running. once the VM system is running, the
|
||||
* pmap module can add more PTPs to the kernel area on demand.
|
||||
*/
|
||||
|
||||
#ifndef NKPTP
|
||||
#define NKPTP 4 /* 16MB to start */
|
||||
#endif
|
||||
#define NKPTP_MIN 4 /* smallest value we allow */
|
||||
#define NKPTP_MAX (1024 - (KERNBASE/NBPD) - 1)
|
||||
/* largest value (-1 for APTP space) */
|
||||
|
||||
/*
|
||||
* pdei/ptei: generate index into PDP/PTP from a VA
|
||||
*/
|
||||
#define pdei(VA) (((VA) & PD_MASK) >> PDSHIFT)
|
||||
#define ptei(VA) (((VA) & PT_MASK) >> PGSHIFT)
|
||||
|
||||
/*
|
||||
* PTP macros:
|
||||
* a PTP's index is the PD index of the PDE that points to it
|
||||
* a PTP's offset is the byte-offset in the PTE space that this PTP is at
|
||||
* a PTP's VA is the first VA mapped by that PTP
|
||||
*
|
||||
* note that PAGE_SIZE == number of bytes in a PTP (4096 bytes == 1024 entries)
|
||||
* NBPD == number of bytes a PTP can map (4MB)
|
||||
*/
|
||||
|
||||
#define ptp_i2o(I) ((I) * PAGE_SIZE) /* index => offset */
|
||||
#define ptp_o2i(O) ((O) / PAGE_SIZE) /* offset => index */
|
||||
#define ptp_i2v(I) ((I) * NBPD) /* index => VA */
|
||||
#define ptp_v2i(V) ((V) / NBPD) /* VA => index (same as pdei) */
|
||||
|
||||
/*
|
||||
* PG_AVAIL usage: we make use of the ignored bits of the PTE
|
||||
*/
|
||||
|
||||
#define PG_W PG_AVAIL1 /* "wired" mapping */
|
||||
#define PG_PVLIST PG_AVAIL2 /* mapping has entry on pvlist */
|
||||
#define PG_X PG_AVAIL3 /* executable mapping */
|
||||
|
||||
/*
|
||||
* Number of PTE's per cache line. 4 byte pte, 32-byte cache line
|
||||
* Used to avoid false sharing of cache lines.
|
||||
*/
|
||||
#define NPTECL 8
|
||||
|
||||
#ifdef _KERNEL
|
||||
/*
|
||||
* pmap data structures: see pmap.c for details of locking.
|
||||
*/
|
||||
|
||||
struct pmap;
|
||||
typedef struct pmap *pmap_t;
|
||||
|
||||
/*
|
||||
* we maintain a list of all non-kernel pmaps
|
||||
*/
|
||||
|
||||
LIST_HEAD(pmap_head, pmap); /* struct pmap_head: head of a pmap list */
|
||||
|
||||
/*
|
||||
* the pmap structure
|
||||
*
|
||||
* note that the pm_obj contains the simple_lock, the reference count,
|
||||
* page list, and number of PTPs within the pmap.
|
||||
*
|
||||
* XXX If we ever support processor numbers higher than 31, we'll have
|
||||
* XXX to rethink the CPU mask.
|
||||
*/
|
||||
|
||||
struct pmap {
|
||||
struct uvm_object pm_obj; /* object (lck by object lock) */
|
||||
#define pm_lock pm_obj.vmobjlock
|
||||
LIST_ENTRY(pmap) pm_list; /* list (lck by pm_list lock) */
|
||||
pd_entry_t *pm_pdir; /* VA of PD (lck by object lock) */
|
||||
u_int32_t pm_pdirpa; /* PA of PD (read-only after create) */
|
||||
struct vm_page *pm_ptphint; /* pointer to a PTP in our pmap */
|
||||
struct pmap_statistics pm_stats; /* pmap stats (lck by object lock) */
|
||||
|
||||
vaddr_t pm_hiexec; /* highest executable mapping */
|
||||
int pm_flags; /* see below */
|
||||
|
||||
union descriptor *pm_ldt; /* user-set LDT */
|
||||
int pm_ldt_len; /* number of LDT entries */
|
||||
int pm_ldt_sel; /* LDT selector */
|
||||
u_int32_t pm_cpus; /* mask of CPUs using pmap */
|
||||
};
|
||||
|
||||
/* pm_flags */
|
||||
#define PMF_USER_LDT 0x01 /* pmap has user-set LDT */
|
||||
|
||||
/*
|
||||
* for each managed physical page we maintain a list of <PMAP,VA>'s
|
||||
* which it is mapped at. the list is headed by a pv_head structure.
|
||||
* there is one pv_head per managed phys page (allocated at boot time).
|
||||
* the pv_head structure points to a list of pv_entry structures (each
|
||||
* describes one mapping).
|
||||
*/
|
||||
|
||||
struct pv_entry { /* locked by its list's pvh_lock */
|
||||
SPLAY_ENTRY(pv_entry) pv_node; /* splay-tree node */
|
||||
struct pmap *pv_pmap; /* the pmap */
|
||||
vaddr_t pv_va; /* the virtual address */
|
||||
struct vm_page *pv_ptp; /* the vm_page of the PTP */
|
||||
};
|
||||
|
||||
/*
|
||||
* pv_entrys are dynamically allocated in chunks from a single page.
|
||||
* we keep track of how many pv_entrys are in use for each page and
|
||||
* we can free pv_entry pages if needed. there is one lock for the
|
||||
* entire allocation system.
|
||||
*/
|
||||
|
||||
struct pv_page_info {
|
||||
TAILQ_ENTRY(pv_page) pvpi_list;
|
||||
struct pv_entry *pvpi_pvfree;
|
||||
int pvpi_nfree;
|
||||
};
|
||||
|
||||
/*
|
||||
* number of pv_entry's in a pv_page
|
||||
* (note: won't work on systems where NPBG isn't a constant)
|
||||
*/
|
||||
|
||||
#define PVE_PER_PVPAGE ((PAGE_SIZE - sizeof(struct pv_page_info)) / \
|
||||
sizeof(struct pv_entry))
|
||||
|
||||
/*
|
||||
* a pv_page: where pv_entrys are allocated from
|
||||
*/
|
||||
|
||||
struct pv_page {
|
||||
struct pv_page_info pvinfo;
|
||||
struct pv_entry pvents[PVE_PER_PVPAGE];
|
||||
};
|
||||
|
||||
/*
|
||||
* global kernel variables
|
||||
*/
|
||||
|
||||
/* PTDpaddr: is the physical address of the kernel's PDP */
|
||||
extern u_long PTDpaddr;
|
||||
|
||||
extern struct pmap kernel_pmap_store; /* kernel pmap */
|
||||
extern int nkpde; /* current # of PDEs for kernel */
|
||||
extern int pmap_pg_g; /* do we support PG_G? */
|
||||
|
||||
/*
|
||||
* macros
|
||||
*/
|
||||
|
||||
#define pmap_kernel() (&kernel_pmap_store)
|
||||
#define pmap_resident_count(pmap) ((pmap)->pm_stats.resident_count)
|
||||
#define pmap_wired_count(pmap) ((pmap)->pm_stats.wired_count)
|
||||
#define pmap_update(pmap) /* nothing (yet) */
|
||||
|
||||
#define pmap_clear_modify(pg) pmap_clear_attrs(pg, PG_M)
|
||||
#define pmap_clear_reference(pg) pmap_clear_attrs(pg, PG_U)
|
||||
#define pmap_copy(DP,SP,D,L,S)
|
||||
#define pmap_is_modified(pg) pmap_test_attrs(pg, PG_M)
|
||||
#define pmap_is_referenced(pg) pmap_test_attrs(pg, PG_U)
|
||||
#define pmap_move(DP,SP,D,L,S)
|
||||
#define pmap_phys_address(ppn) x86_ptob(ppn)
|
||||
#define pmap_valid_entry(E) ((E) & PG_V) /* is PDE or PTE valid? */
|
||||
|
||||
|
||||
/*
|
||||
* prototypes
|
||||
*/
|
||||
|
||||
void pmap_activate(struct lwp *);
|
||||
void pmap_bootstrap(vaddr_t);
|
||||
boolean_t pmap_clear_attrs(struct vm_page *, int);
|
||||
void pmap_deactivate(struct lwp *);
|
||||
void pmap_deactivate2(struct lwp *);
|
||||
void pmap_page_remove (struct vm_page *);
|
||||
void pmap_remove(struct pmap *, vaddr_t, vaddr_t);
|
||||
boolean_t pmap_test_attrs(struct vm_page *, int);
|
||||
void pmap_write_protect(struct pmap *, vaddr_t, vaddr_t, vm_prot_t);
|
||||
int pmap_exec_fixup(struct vm_map *, struct trapframe *,
|
||||
struct pcb *);
|
||||
void pmap_load(void);
|
||||
int pmap_enter_ma(struct pmap *, vaddr_t, paddr_t, vm_prot_t,
|
||||
int);
|
||||
|
||||
vaddr_t reserve_dumppages(vaddr_t); /* XXX: not a pmap fn */
|
||||
|
||||
void pmap_tlb_shootdown(pmap_t, vaddr_t, pt_entry_t, int32_t *);
|
||||
void pmap_tlb_shootnow(int32_t);
|
||||
void pmap_do_tlb_shootdown(struct cpu_info *);
|
||||
|
||||
#define PMAP_GROWKERNEL /* turn on pmap_growkernel interface */
|
||||
|
||||
/*
|
||||
* Do idle page zero'ing uncached to avoid polluting the cache.
|
||||
*/
|
||||
boolean_t pmap_pageidlezero(paddr_t);
|
||||
#define PMAP_PAGEIDLEZERO(pa) pmap_pageidlezero((pa))
|
||||
|
||||
/*
|
||||
* inline functions
|
||||
*/
|
||||
|
||||
/*ARGSUSED*/
|
||||
static __inline void
|
||||
pmap_remove_all(struct pmap *pmap)
|
||||
{
|
||||
/* Nothing. */
|
||||
}
|
||||
|
||||
/*
|
||||
* pmap_update_pg: flush one page from the TLB (or flush the whole thing
|
||||
* if hardware doesn't support one-page flushing)
|
||||
*/
|
||||
|
||||
__inline static void __attribute__((__unused__))
|
||||
pmap_update_pg(vaddr_t va)
|
||||
{
|
||||
#if defined(I386_CPU)
|
||||
if (cpu_class == CPUCLASS_386)
|
||||
tlbflush();
|
||||
else
|
||||
#endif
|
||||
invlpg((u_int) va);
|
||||
}
|
||||
|
||||
/*
|
||||
* pmap_update_2pg: flush two pages from the TLB
|
||||
*/
|
||||
|
||||
__inline static void __attribute__((__unused__))
|
||||
pmap_update_2pg(vaddr_t va, vaddr_t vb)
|
||||
{
|
||||
#if defined(I386_CPU)
|
||||
if (cpu_class == CPUCLASS_386)
|
||||
tlbflush();
|
||||
else
|
||||
#endif
|
||||
{
|
||||
invlpg((u_int) va);
|
||||
invlpg((u_int) vb);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* pmap_page_protect: change the protection of all recorded mappings
|
||||
* of a managed page
|
||||
*
|
||||
* => this function is a frontend for pmap_page_remove/pmap_clear_attrs
|
||||
* => we only have to worry about making the page more protected.
|
||||
* unprotecting a page is done on-demand at fault time.
|
||||
*/
|
||||
|
||||
__inline static void __attribute__((__unused__))
|
||||
pmap_page_protect(struct vm_page *pg, vm_prot_t prot)
|
||||
{
|
||||
if ((prot & VM_PROT_WRITE) == 0) {
|
||||
if (prot & (VM_PROT_READ|VM_PROT_EXECUTE)) {
|
||||
(void) pmap_clear_attrs(pg, PG_RW);
|
||||
} else {
|
||||
pmap_page_remove(pg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* pmap_protect: change the protection of pages in a pmap
|
||||
*
|
||||
* => this function is a frontend for pmap_remove/pmap_write_protect
|
||||
* => we only have to worry about making the page more protected.
|
||||
* unprotecting a page is done on-demand at fault time.
|
||||
*/
|
||||
|
||||
__inline static void __attribute__((__unused__))
|
||||
pmap_protect(struct pmap *pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
|
||||
{
|
||||
if ((prot & VM_PROT_WRITE) == 0) {
|
||||
if (prot & (VM_PROT_READ|VM_PROT_EXECUTE)) {
|
||||
pmap_write_protect(pmap, sva, eva, prot);
|
||||
} else {
|
||||
pmap_remove(pmap, sva, eva);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* various address inlines
|
||||
*
|
||||
* vtopte: return a pointer to the PTE mapping a VA, works only for
|
||||
* user and PT addresses
|
||||
*
|
||||
* kvtopte: return a pointer to the PTE mapping a kernel VA
|
||||
*/
|
||||
|
||||
#include <lib/libkern/libkern.h>
|
||||
|
||||
static __inline pt_entry_t * __attribute__((__unused__))
|
||||
vtopte(vaddr_t va)
|
||||
{
|
||||
|
||||
KASSERT(va < (PDSLOT_KERN << PDSHIFT));
|
||||
|
||||
return (PTE_BASE + x86_btop(va));
|
||||
}
|
||||
|
||||
static __inline pt_entry_t * __attribute__((__unused__))
|
||||
kvtopte(vaddr_t va)
|
||||
{
|
||||
|
||||
KASSERT(va >= (PDSLOT_KERN << PDSHIFT));
|
||||
|
||||
#ifdef LARGEPAGES
|
||||
{
|
||||
pd_entry_t *pde;
|
||||
|
||||
pde = PDP_BASE + pdei(va);
|
||||
if (*pde & PG_PS)
|
||||
return ((pt_entry_t *)pde);
|
||||
}
|
||||
#endif
|
||||
|
||||
return (PTE_BASE + x86_btop(va));
|
||||
}
|
||||
|
||||
/*
|
||||
* vtomach: virtual address to machine address. For use by
|
||||
* machine-dependent code only.
|
||||
*/
|
||||
|
||||
static inline paddr_t __attribute__((__unused__))
|
||||
vtomach(vaddr_t va)
|
||||
{
|
||||
pt_entry_t pte;
|
||||
|
||||
pte = PTE_GET(&PTE_BASE[x86_btop(va)]);
|
||||
return xpmap_ptom((pte & PG_FRAME) | (va & ~PG_FRAME));
|
||||
}
|
||||
|
||||
#define pmap_cpu_has_pg_n() (cpu_class != CPUCLASS_386)
|
||||
#define pmap_cpu_has_invlpg() (cpu_class != CPUCLASS_386)
|
||||
|
||||
paddr_t vtophys(vaddr_t);
|
||||
vaddr_t pmap_map(vaddr_t, paddr_t, paddr_t, vm_prot_t);
|
||||
|
||||
void pmap_kenter_ma(vaddr_t, paddr_t, vm_prot_t);
|
||||
|
||||
#if defined(USER_LDT)
|
||||
void pmap_ldt_cleanup(struct lwp *);
|
||||
#define PMAP_FORK
|
||||
#endif /* USER_LDT */
|
||||
|
||||
/*
|
||||
* Hooks for the pool allocator.
|
||||
*/
|
||||
#define POOL_VTOPHYS(va) vtophys((vaddr_t) (va))
|
||||
|
||||
#endif /* _KERNEL */
|
||||
#endif /* _I386_PMAP_H_ */
|
||||
@@ -0,0 +1,247 @@
|
||||
/* $NetBSD: xen.h,v 1.1.2.2 2004/06/17 09:23:19 tron Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2003, 2004 Keir Fraser (on behalf of the Xen team)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _XEN_H
|
||||
#define _XEN_H
|
||||
|
||||
#ifndef _LOCORE
|
||||
|
||||
struct xen_netinfo {
|
||||
uint32_t xi_ifno;
|
||||
char *xi_root;
|
||||
uint32_t xi_ip[5];
|
||||
};
|
||||
|
||||
union xen_cmdline_parseinfo {
|
||||
char xcp_bootdev[16]; /* sizeof(dv_xname) */
|
||||
struct xen_netinfo xcp_netinfo;
|
||||
char xcp_console[16];
|
||||
};
|
||||
|
||||
#define XEN_PARSE_BOOTDEV 0
|
||||
#define XEN_PARSE_NETINFO 1
|
||||
#define XEN_PARSE_CONSOLE 2
|
||||
|
||||
void xen_parse_cmdline(int, union xen_cmdline_parseinfo *);
|
||||
|
||||
void xenconscn_attach(void);
|
||||
|
||||
void xenmachmem_init(void);
|
||||
void xenprivcmd_init(void);
|
||||
void xenvfr_init(void);
|
||||
|
||||
#ifdef XENDEBUG
|
||||
void printk(const char *, ...);
|
||||
void vprintk(const char *, va_list);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _XEN_H */
|
||||
|
||||
/******************************************************************************
|
||||
* os.h
|
||||
*
|
||||
* random collection of macros and definition
|
||||
*/
|
||||
|
||||
#ifndef _OS_H_
|
||||
#define _OS_H_
|
||||
|
||||
/*
|
||||
* These are the segment descriptors provided for us by the hypervisor.
|
||||
* For now, these are hardwired -- guest OSes cannot update the GDT
|
||||
* or LDT.
|
||||
*
|
||||
* It shouldn't be hard to support descriptor-table frobbing -- let me
|
||||
* know if the BSD or XP ports require flexibility here.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* these are also defined in hypervisor-if.h but can't be pulled in as
|
||||
* they are used in start of day assembly. Need to clean up the .h files
|
||||
* a bit more...
|
||||
*/
|
||||
|
||||
#ifndef FLAT_RING1_CS
|
||||
#define FLAT_RING1_CS 0x0819
|
||||
#define FLAT_RING1_DS 0x0821
|
||||
#define FLAT_RING3_CS 0x082b
|
||||
#define FLAT_RING3_DS 0x0833
|
||||
#endif
|
||||
|
||||
#define __KERNEL_CS FLAT_RING1_CS
|
||||
#define __KERNEL_DS FLAT_RING1_DS
|
||||
|
||||
/* Everything below this point is not included by assembler (.S) files. */
|
||||
#ifndef _LOCORE
|
||||
|
||||
/* some function prototypes */
|
||||
void trap_init(void);
|
||||
|
||||
|
||||
/*
|
||||
* STI/CLI equivalents. These basically set and clear the virtual
|
||||
* event_enable flag in the shared_info structure. Note that when
|
||||
* the enable bit is set, there may be pending events to be handled.
|
||||
* We may therefore call into do_hypervisor_callback() directly.
|
||||
*/
|
||||
|
||||
#define __save_flags(x) \
|
||||
do { \
|
||||
(x) = HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask; \
|
||||
} while (0)
|
||||
|
||||
#define __restore_flags(x) \
|
||||
do { \
|
||||
shared_info_t *_shared = HYPERVISOR_shared_info; \
|
||||
__insn_barrier(); \
|
||||
if ((_shared->vcpu_data[0].evtchn_upcall_mask = (x)) == 0) { \
|
||||
__insn_barrier(); \
|
||||
if (__predict_false(_shared->vcpu_data[0].evtchn_upcall_pending)) \
|
||||
hypervisor_force_callback(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define __cli() \
|
||||
do { \
|
||||
HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask = 1; \
|
||||
__insn_barrier(); \
|
||||
} while (0)
|
||||
|
||||
#define __sti() \
|
||||
do { \
|
||||
shared_info_t *_shared = HYPERVISOR_shared_info; \
|
||||
__insn_barrier(); \
|
||||
_shared->vcpu_data[0].evtchn_upcall_mask = 0; \
|
||||
__insn_barrier(); /* unmask then check (avoid races) */ \
|
||||
if (__predict_false(_shared->vcpu_data[0].evtchn_upcall_pending)) \
|
||||
hypervisor_force_callback(); \
|
||||
} while (0)
|
||||
|
||||
#define cli() __cli()
|
||||
#define sti() __sti()
|
||||
#define save_flags(x) __save_flags(x)
|
||||
#define restore_flags(x) __restore_flags(x)
|
||||
#define save_and_cli(x) do { \
|
||||
__save_flags(x); \
|
||||
__cli(); \
|
||||
} while (/* CONSTCOND */ 0)
|
||||
#define save_and_sti(x) __save_and_sti(x)
|
||||
|
||||
#ifdef MULTIPROCESSOR
|
||||
#define __LOCK_PREFIX "lock; "
|
||||
#else
|
||||
#define __LOCK_PREFIX ""
|
||||
#endif
|
||||
|
||||
static __inline__ uint32_t
|
||||
x86_atomic_xchg(uint32_t *ptr, unsigned long val)
|
||||
{
|
||||
unsigned long result;
|
||||
|
||||
__asm __volatile("xchgl %0,%1"
|
||||
:"=r" (result)
|
||||
:"m" (*ptr), "0" (val)
|
||||
:"memory");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
x86_atomic_test_and_clear_bit(volatile void *ptr, int bitno)
|
||||
{
|
||||
int result;
|
||||
|
||||
__asm __volatile(__LOCK_PREFIX
|
||||
"btrl %2,%1 ;"
|
||||
"sbbl %0,%0"
|
||||
:"=r" (result), "=m" (*(volatile uint32_t *)(ptr))
|
||||
:"Ir" (bitno) : "memory");
|
||||
return result;
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
x86_atomic_test_and_set_bit(volatile void *ptr, int bitno)
|
||||
{
|
||||
int result;
|
||||
|
||||
__asm __volatile(__LOCK_PREFIX
|
||||
"btsl %2,%1 ;"
|
||||
"sbbl %0,%0"
|
||||
:"=r" (result), "=m" (*(volatile uint32_t *)(ptr))
|
||||
:"Ir" (bitno) : "memory");
|
||||
return result;
|
||||
}
|
||||
|
||||
static __inline int
|
||||
x86_constant_test_bit(const volatile void *ptr, int bitno)
|
||||
{
|
||||
return ((1UL << (bitno & 31)) &
|
||||
(((const volatile uint32_t *) ptr)[bitno >> 5])) != 0;
|
||||
}
|
||||
|
||||
static __inline int
|
||||
x86_variable_test_bit(const volatile void *ptr, int bitno)
|
||||
{
|
||||
int result;
|
||||
|
||||
__asm __volatile(
|
||||
"btl %2,%1 ;"
|
||||
"sbbl %0,%0"
|
||||
:"=r" (result)
|
||||
:"m" (*(volatile uint32_t *)(ptr)), "Ir" (bitno));
|
||||
return result;
|
||||
}
|
||||
|
||||
#define x86_atomic_test_bit(ptr, bitno) \
|
||||
(__builtin_constant_p(bitno) ? \
|
||||
x86_constant_test_bit((ptr),(bitno)) : \
|
||||
x86_variable_test_bit((ptr),(bitno)))
|
||||
|
||||
static __inline void
|
||||
x86_atomic_set_bit(volatile void *ptr, int bitno)
|
||||
{
|
||||
__asm __volatile(__LOCK_PREFIX
|
||||
"btsl %1,%0"
|
||||
:"=m" (*(volatile uint32_t *)(ptr))
|
||||
:"Ir" (bitno));
|
||||
}
|
||||
|
||||
static __inline void
|
||||
x86_atomic_clear_bit(volatile void *ptr, int bitno)
|
||||
{
|
||||
__asm __volatile(__LOCK_PREFIX
|
||||
"btrl %1,%0"
|
||||
:"=m" (*(volatile uint32_t *)(ptr))
|
||||
:"Ir" (bitno));
|
||||
}
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* _OS_H_ */
|
||||
@@ -0,0 +1,135 @@
|
||||
/* $NetBSD: xenfunc.h,v 1.1.2.1 2004/05/22 15:59:31 he Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2004 Christian Limpach.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Christian Limpach.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _XEN_XENFUNC_H_
|
||||
#define _XEN_XENFUNC_H_
|
||||
|
||||
#include <machine/xen.h>
|
||||
#include <machine/hypervisor.h>
|
||||
#include <machine/evtchn.h>
|
||||
#include <machine/xenpmap.h>
|
||||
#include <machine/pte.h>
|
||||
|
||||
#ifdef XENDEBUG_LOW
|
||||
#define __PRINTK(x) printk x
|
||||
#else
|
||||
#define __PRINTK(x)
|
||||
#endif
|
||||
|
||||
void xen_set_ldt(vaddr_t, uint32_t);
|
||||
void xen_update_descriptor(union descriptor *, union descriptor *);
|
||||
|
||||
static __inline void
|
||||
invlpg(u_int addr)
|
||||
{
|
||||
xpq_queue_invlpg(addr);
|
||||
xpq_flush_queue();
|
||||
}
|
||||
|
||||
static __inline void
|
||||
lldt(u_short sel)
|
||||
{
|
||||
|
||||
/* __PRINTK(("ldt %x\n", IDXSELN(sel))); */
|
||||
if (sel == GSEL(GLDT_SEL, SEL_KPL))
|
||||
xen_set_ldt((vaddr_t)ldt, NLDT);
|
||||
else
|
||||
xen_set_ldt(cpu_info_primary.ci_gdt[IDXSELN(sel)].ld.ld_base,
|
||||
cpu_info_primary.ci_gdt[IDXSELN(sel)].ld.ld_entries);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
ltr(u_short sel)
|
||||
{
|
||||
__PRINTK(("XXX ltr not supported\n"));
|
||||
}
|
||||
|
||||
static __inline void
|
||||
lcr0(u_int val)
|
||||
{
|
||||
__PRINTK(("XXX lcr0 not supported\n"));
|
||||
}
|
||||
|
||||
static __inline u_int
|
||||
rcr0(void)
|
||||
{
|
||||
__PRINTK(("XXX rcr0 not supported\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define lcr3(_v) _lcr3((_v), __FILE__, __LINE__)
|
||||
static __inline void
|
||||
_lcr3(u_int val, char *file, int line)
|
||||
{
|
||||
/* __PRINTK(("lcr3 %08x at %s:%d\n", val, file, line)); */
|
||||
xpq_queue_pt_switch(xpmap_ptom(val) & PG_FRAME);
|
||||
xpq_flush_queue();
|
||||
}
|
||||
|
||||
static __inline void
|
||||
tlbflush(void)
|
||||
{
|
||||
xpq_queue_tlb_flush();
|
||||
xpq_flush_queue();
|
||||
}
|
||||
|
||||
static __inline u_int
|
||||
rdr6(void)
|
||||
{
|
||||
u_int val;
|
||||
|
||||
val = HYPERVISOR_get_debugreg(6);
|
||||
return val;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
ldr6(u_int val)
|
||||
{
|
||||
|
||||
HYPERVISOR_set_debugreg(6, val);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
disable_intr(void)
|
||||
{
|
||||
__cli();
|
||||
}
|
||||
|
||||
static __inline void
|
||||
enable_intr(void)
|
||||
{
|
||||
__sti();
|
||||
}
|
||||
|
||||
#endif /* _XEN_XENFUNC_H_ */
|
||||
@@ -0,0 +1,193 @@
|
||||
/* $NetBSD: xenpmap.h,v 1.1.2.1 2004/05/22 15:59:58 he Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2004 Christian Limpach.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Christian Limpach.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _XEN_XENPMAP_H_
|
||||
#define _XEN_XENPMAP_H_
|
||||
|
||||
#define INVALID_P2M_ENTRY (~0UL)
|
||||
|
||||
void xpq_queue_invlpg(vaddr_t);
|
||||
void xpq_queue_pde_update(pd_entry_t *, pd_entry_t);
|
||||
void xpq_queue_pte_update(pt_entry_t *, pt_entry_t);
|
||||
void xpq_queue_unchecked_pte_update(pt_entry_t *, pt_entry_t);
|
||||
void xpq_queue_pt_switch(paddr_t);
|
||||
void xpq_flush_queue(void);
|
||||
void xpq_queue_set_ldt(vaddr_t, uint32_t);
|
||||
void xpq_queue_tlb_flush(void);
|
||||
void xpq_queue_pin_table(paddr_t, int);
|
||||
void xpq_queue_unpin_table(paddr_t);
|
||||
|
||||
extern paddr_t *xpmap_phys_to_machine_mapping;
|
||||
|
||||
#define XPQ_PIN_L1_TABLE 1
|
||||
#define XPQ_PIN_L2_TABLE 2
|
||||
|
||||
#ifndef XEN
|
||||
#define PDE_GET(_pdp) \
|
||||
*(_pdp)
|
||||
#define PDE_SET(_pdp,_mapdp,_npde) \
|
||||
*(_mapdp) = (_npde)
|
||||
#define PDE_CLEAR(_pdp,_mapdp) \
|
||||
*(_mapdp) = 0
|
||||
#define PTE_SET(_ptp,_maptp,_npte) \
|
||||
*(_maptp) = (_npte)
|
||||
#define PTE_CLEAR(_ptp,_maptp) \
|
||||
*(_maptp) = 0
|
||||
#define PTE_ATOMIC_SET(_ptp,_maptp,_npte,_opte) \
|
||||
(_opte) = x86_atomic_testset_ul((_maptp), (_npte))
|
||||
#define PTE_ATOMIC_CLEAR(_ptp,_maptp,_opte) \
|
||||
(_opte) = x86_atomic_testset_ul((_maptp), 0)
|
||||
#define PDE_CLEARBITS(_pdp,_mapdp,_bits) \
|
||||
*(_mapdp) &= ~(_bits)
|
||||
#define PTE_ATOMIC_CLEARBITS(_ptp,_maptp,_bits) \
|
||||
x86_atomic_clearbits_l((_maptp), (_bits))
|
||||
#define PTE_SETBITS(_ptp,_maptp,_bits) \
|
||||
*(_maptp) |= (_bits)
|
||||
#define PTE_ATOMIC_SETBITS(_ptp,_maptp,_bits) \
|
||||
x86_atomic_setbits_l((_maptp), (_bits))
|
||||
#else
|
||||
paddr_t *xpmap_phys_to_machine_mapping;
|
||||
|
||||
#define PDE_GET(_pdp) \
|
||||
(pmap_valid_entry(*(_pdp)) ? xpmap_mtop(*(_pdp)) : *(_pdp))
|
||||
#define PDE_SET(_pdp,_mapdp,_npde) do { \
|
||||
xpq_queue_pde_update((_mapdp), xpmap_ptom((_npde))); \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define PDE_CLEAR(_pdp,_mapdp) do { \
|
||||
xpq_queue_pde_update((_mapdp), 0); \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define PTE_GET(_ptp) \
|
||||
(pmap_valid_entry(*(_ptp)) ? xpmap_mtop(*(_ptp)) : *(_ptp))
|
||||
#define PTE_GET_MA(_ptp) \
|
||||
*(_ptp)
|
||||
#define PTE_SET(_ptp,_maptp,_npte) do { \
|
||||
xpq_queue_pte_update((_maptp), xpmap_ptom((_npte))); \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define PTE_SET_MA(_ptp,_maptp,_npte) do { \
|
||||
xpq_queue_pte_update((_maptp), (_npte)); \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define PTE_SET_MA_UNCHECKED(_ptp,_maptp,_npte) do { \
|
||||
xpq_queue_unchecked_pte_update((_maptp), (_npte)); \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define PTE_CLEAR(_ptp,_maptp) do { \
|
||||
xpq_queue_pte_update((_maptp), 0); \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define PTE_ATOMIC_SET(_ptp,_maptp,_npte,_opte) do { \
|
||||
(_opte) = PTE_GET(_ptp); \
|
||||
xpq_queue_pte_update((_maptp), xpmap_ptom((_npte))); \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define PTE_ATOMIC_SET_MA(_ptp,_maptp,_npte,_opte) do { \
|
||||
(_opte) = *(_ptp); \
|
||||
xpq_queue_pte_update((_maptp), (_npte)); \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define PTE_ATOMIC_CLEAR(_ptp,_maptp,_opte) do { \
|
||||
(_opte) = PTE_GET(_ptp); \
|
||||
xpq_queue_pte_update((_maptp), 0); \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define PTE_ATOMIC_CLEAR_MA(_ptp,_maptp,_opte) do { \
|
||||
(_opte) = *(_ptp); \
|
||||
xpq_queue_pte_update((_maptp), 0); \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define PDE_CLEARBITS(_pdp,_mapdp,_bits) do { \
|
||||
xpq_queue_pte_update((_mapdp), *(_pdp) & ~((_bits) & ~PG_FRAME)); \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define PTE_CLEARBITS(_ptp,_maptp,_bits) do { \
|
||||
xpq_queue_pte_update((_maptp), *(_ptp) & ~((_bits) & ~PG_FRAME)); \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define PDE_ATOMIC_CLEARBITS(_pdp,_mapdp,_bits) do { \
|
||||
xpq_queue_pde_update((_mapdp), *(_pdp) & ~((_bits) & ~PG_FRAME)); \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define PTE_ATOMIC_CLEARBITS(_ptp,_maptp,_bits) do { \
|
||||
xpq_queue_pte_update((_maptp), *(_ptp) & ~((_bits) & ~PG_FRAME)); \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define PTE_SETBITS(_ptp,_maptp,_bits) do { \
|
||||
xpq_queue_pte_update((_maptp), *(_ptp) | ((_bits) & ~PG_FRAME)); \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define PDE_ATOMIC_SETBITS(_pdp,_mapdp,_bits) do { \
|
||||
xpq_queue_pde_update((_mapdp), *(_pdp) | ((_bits) & ~PG_FRAME)); \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define PTE_ATOMIC_SETBITS(_ptp,_maptp,_bits) do { \
|
||||
xpq_queue_pte_update((_maptp), *(_ptp) | ((_bits) & ~PG_FRAME)); \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define PDE_COPY(_dpdp,_madpdp,_spdp) do { \
|
||||
xpq_queue_pde_update((_madpdp), *(_spdp)); \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
#define PTE_UPDATES_FLUSH() do { \
|
||||
xpq_flush_queue(); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#endif
|
||||
|
||||
#define XPMAP_OFFSET (KERNTEXTOFF - KERNBASE_LOCORE)
|
||||
static __inline paddr_t
|
||||
xpmap_mtop(paddr_t mpa)
|
||||
{
|
||||
return ((machine_to_phys_mapping[mpa >> PAGE_SHIFT] << PAGE_SHIFT) +
|
||||
XPMAP_OFFSET) | (mpa & ~PG_FRAME);
|
||||
}
|
||||
|
||||
static __inline paddr_t
|
||||
xpmap_ptom(paddr_t ppa)
|
||||
{
|
||||
return (xpmap_phys_to_machine_mapping[(ppa -
|
||||
XPMAP_OFFSET) >> PAGE_SHIFT] << PAGE_SHIFT)
|
||||
| (ppa & ~PG_FRAME);
|
||||
}
|
||||
|
||||
static __inline paddr_t
|
||||
xpmap_ptom_masked(paddr_t ppa)
|
||||
{
|
||||
return (xpmap_phys_to_machine_mapping[(ppa -
|
||||
XPMAP_OFFSET) >> PAGE_SHIFT] << PAGE_SHIFT);
|
||||
}
|
||||
|
||||
#endif /* _XEN_XENPMAP_H_ */
|
||||
@@ -0,0 +1,505 @@
|
||||
/* $NetBSD: bus_space.c,v 1.2.2.1 2004/05/22 15:57:25 he Exp $ */
|
||||
/* NetBSD: bus_space.c,v 1.2 2003/03/14 18:47:53 christos Exp */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
|
||||
* Simulation Facility, NASA Ames Research Center.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: bus_space.c,v 1.2.2.1 2004/05/22 15:57:25 he Exp $");
|
||||
|
||||
#include "opt_xen.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/extent.h>
|
||||
|
||||
#include <uvm/uvm_extern.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/isa/isareg.h>
|
||||
#include <machine/isa_machdep.h>
|
||||
|
||||
#include <machine/hypervisor.h>
|
||||
#include <machine/xenpmap.h>
|
||||
|
||||
/*
|
||||
* Extent maps to manage I/O and memory space. Allocate
|
||||
* storage for 8 regions in each, initially. Later, ioport_malloc_safe
|
||||
* will indicate that it's safe to use malloc() to dynamically allocate
|
||||
* region descriptors.
|
||||
*
|
||||
* N.B. At least two regions are _always_ allocated from the iomem
|
||||
* extent map; (0 -> ISA hole) and (end of ISA hole -> end of RAM).
|
||||
*
|
||||
* The extent maps are not static! Machine-dependent ISA and EISA
|
||||
* routines need access to them for bus address space allocation.
|
||||
*/
|
||||
static long ioport_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
|
||||
static long iomem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
|
||||
struct extent *ioport_ex;
|
||||
struct extent *iomem_ex;
|
||||
static int ioport_malloc_safe;
|
||||
|
||||
int x86_mem_add_mapping __P((bus_addr_t, bus_size_t,
|
||||
int, bus_space_handle_t *));
|
||||
|
||||
void
|
||||
x86_bus_space_init()
|
||||
{
|
||||
/*
|
||||
* Initialize the I/O port and I/O mem extent maps.
|
||||
* Note: we don't have to check the return value since
|
||||
* creation of a fixed extent map will never fail (since
|
||||
* descriptor storage has already been allocated).
|
||||
*
|
||||
* N.B. The iomem extent manages _all_ physical addresses
|
||||
* on the machine. When the amount of RAM is found, the two
|
||||
* extents of RAM are allocated from the map (0 -> ISA hole
|
||||
* and end of ISA hole -> end of RAM).
|
||||
*/
|
||||
ioport_ex = extent_create("ioport", 0x0, 0xffff, M_DEVBUF,
|
||||
(caddr_t)ioport_ex_storage, sizeof(ioport_ex_storage),
|
||||
EX_NOCOALESCE|EX_NOWAIT);
|
||||
iomem_ex = extent_create("iomem", 0x0, 0xffffffff, M_DEVBUF,
|
||||
(caddr_t)iomem_ex_storage, sizeof(iomem_ex_storage),
|
||||
EX_NOCOALESCE|EX_NOWAIT);
|
||||
|
||||
/* We are privileged guest os - should have IO privileges. */
|
||||
if (xen_start_info.flags & SIF_PRIVILEGED) {
|
||||
dom0_op_t op;
|
||||
op.cmd = DOM0_IOPL;
|
||||
op.u.iopl.domain = DOMID_SELF;
|
||||
op.u.iopl.iopl = 1;
|
||||
if (HYPERVISOR_dom0_op(&op) != 0)
|
||||
panic("Unable to obtain IOPL, "
|
||||
"despite being SIF_PRIVILEGED");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
x86_bus_space_mallocok()
|
||||
{
|
||||
|
||||
ioport_malloc_safe = 1;
|
||||
}
|
||||
|
||||
int
|
||||
x86_memio_map(t, bpa, size, flags, bshp)
|
||||
bus_space_tag_t t;
|
||||
bus_addr_t bpa;
|
||||
bus_size_t size;
|
||||
int flags;
|
||||
bus_space_handle_t *bshp;
|
||||
{
|
||||
int error;
|
||||
struct extent *ex;
|
||||
|
||||
/*
|
||||
* Pick the appropriate extent map.
|
||||
*/
|
||||
if (t == X86_BUS_SPACE_IO) {
|
||||
if (flags & BUS_SPACE_MAP_LINEAR)
|
||||
return (EOPNOTSUPP);
|
||||
ex = ioport_ex;
|
||||
} else if (t == X86_BUS_SPACE_MEM)
|
||||
ex = iomem_ex;
|
||||
else
|
||||
panic("x86_memio_map: bad bus space tag");
|
||||
|
||||
/*
|
||||
* Before we go any further, let's make sure that this
|
||||
* region is available.
|
||||
*/
|
||||
error = extent_alloc_region(ex, bpa, size,
|
||||
EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0));
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/*
|
||||
* For I/O space, that's all she wrote.
|
||||
*/
|
||||
if (t == X86_BUS_SPACE_IO) {
|
||||
*bshp = bpa;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* For memory space, map the bus physical address to
|
||||
* a kernel virtual address.
|
||||
*/
|
||||
error = x86_mem_add_mapping(bpa, size,
|
||||
(flags & BUS_SPACE_MAP_CACHEABLE) != 0, bshp);
|
||||
if (error) {
|
||||
if (extent_free(ex, bpa, size, EX_NOWAIT |
|
||||
(ioport_malloc_safe ? EX_MALLOCOK : 0))) {
|
||||
printf("x86_memio_map: pa 0x%lx, size 0x%lx\n",
|
||||
bpa, size);
|
||||
printf("x86_memio_map: can't free region\n");
|
||||
}
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
_x86_memio_map(t, bpa, size, flags, bshp)
|
||||
bus_space_tag_t t;
|
||||
bus_addr_t bpa;
|
||||
bus_size_t size;
|
||||
int flags;
|
||||
bus_space_handle_t *bshp;
|
||||
{
|
||||
|
||||
/*
|
||||
* For I/O space, just fill in the handle.
|
||||
*/
|
||||
if (t == X86_BUS_SPACE_IO) {
|
||||
if (flags & BUS_SPACE_MAP_LINEAR)
|
||||
return (EOPNOTSUPP);
|
||||
*bshp = bpa;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* For memory space, map the bus physical address to
|
||||
* a kernel virtual address.
|
||||
*/
|
||||
return (x86_mem_add_mapping(bpa, size,
|
||||
(flags & BUS_SPACE_MAP_CACHEABLE) != 0, bshp));
|
||||
}
|
||||
|
||||
int
|
||||
x86_memio_alloc(t, rstart, rend, size, alignment, boundary, flags,
|
||||
bpap, bshp)
|
||||
bus_space_tag_t t;
|
||||
bus_addr_t rstart, rend;
|
||||
bus_size_t size, alignment, boundary;
|
||||
int flags;
|
||||
bus_addr_t *bpap;
|
||||
bus_space_handle_t *bshp;
|
||||
{
|
||||
struct extent *ex;
|
||||
u_long bpa;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Pick the appropriate extent map.
|
||||
*/
|
||||
if (t == X86_BUS_SPACE_IO) {
|
||||
if (flags & BUS_SPACE_MAP_LINEAR)
|
||||
return (EOPNOTSUPP);
|
||||
ex = ioport_ex;
|
||||
} else if (t == X86_BUS_SPACE_MEM)
|
||||
ex = iomem_ex;
|
||||
else
|
||||
panic("x86_memio_alloc: bad bus space tag");
|
||||
|
||||
/*
|
||||
* Sanity check the allocation against the extent's boundaries.
|
||||
*/
|
||||
if (rstart < ex->ex_start || rend > ex->ex_end)
|
||||
panic("x86_memio_alloc: bad region start/end");
|
||||
|
||||
/*
|
||||
* Do the requested allocation.
|
||||
*/
|
||||
error = extent_alloc_subregion(ex, rstart, rend, size, alignment,
|
||||
boundary,
|
||||
EX_FAST | EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0),
|
||||
&bpa);
|
||||
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/*
|
||||
* For I/O space, that's all she wrote.
|
||||
*/
|
||||
if (t == X86_BUS_SPACE_IO) {
|
||||
*bshp = *bpap = bpa;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* For memory space, map the bus physical address to
|
||||
* a kernel virtual address.
|
||||
*/
|
||||
error = x86_mem_add_mapping(bpa, size,
|
||||
(flags & BUS_SPACE_MAP_CACHEABLE) != 0, bshp);
|
||||
if (error) {
|
||||
if (extent_free(iomem_ex, bpa, size, EX_NOWAIT |
|
||||
(ioport_malloc_safe ? EX_MALLOCOK : 0))) {
|
||||
printf("x86_memio_alloc: pa 0x%lx, size 0x%lx\n",
|
||||
bpa, size);
|
||||
printf("x86_memio_alloc: can't free region\n");
|
||||
}
|
||||
}
|
||||
|
||||
*bpap = bpa;
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
x86_mem_add_mapping(bpa, size, cacheable, bshp)
|
||||
bus_addr_t bpa;
|
||||
bus_size_t size;
|
||||
int cacheable;
|
||||
bus_space_handle_t *bshp;
|
||||
{
|
||||
u_long pa, endpa;
|
||||
vaddr_t va;
|
||||
pt_entry_t *pte;
|
||||
pt_entry_t *maptp;
|
||||
int32_t cpumask = 0;
|
||||
|
||||
pa = x86_trunc_page(bpa);
|
||||
endpa = x86_round_page(bpa + size);
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (endpa <= pa)
|
||||
panic("x86_mem_add_mapping: overflow");
|
||||
#endif
|
||||
|
||||
if (bpa >= IOM_BEGIN && (bpa + size) <= IOM_END) {
|
||||
va = (vaddr_t)ISA_HOLE_VADDR(pa);
|
||||
} else {
|
||||
va = uvm_km_valloc(kernel_map, endpa - pa);
|
||||
if (va == 0)
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
*bshp = (bus_space_handle_t)(va + (bpa & PGOFSET));
|
||||
|
||||
for (; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) {
|
||||
pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE);
|
||||
|
||||
/*
|
||||
* PG_N doesn't exist on 386's, so we assume that
|
||||
* the mainboard has wired up device space non-cacheable
|
||||
* on those machines.
|
||||
*
|
||||
* Note that it's not necessary to use atomic ops to
|
||||
* fiddle with the PTE here, because we don't care
|
||||
* about mod/ref information.
|
||||
*
|
||||
* XXX should hand this bit to pmap_kenter_pa to
|
||||
* save the extra invalidate!
|
||||
*
|
||||
* XXX extreme paranoia suggests tlb shootdown belongs here.
|
||||
*/
|
||||
if (pmap_cpu_has_pg_n()) {
|
||||
pte = kvtopte(va);
|
||||
maptp = (pt_entry_t *)vtomach((vaddr_t)pte);
|
||||
if (cacheable)
|
||||
PTE_CLEARBITS(pte, maptp, PG_N);
|
||||
else
|
||||
PTE_SETBITS(pte, maptp, PG_N);
|
||||
pmap_tlb_shootdown(pmap_kernel(), va, *pte,
|
||||
&cpumask);
|
||||
}
|
||||
}
|
||||
|
||||
pmap_tlb_shootnow(cpumask);
|
||||
pmap_update(pmap_kernel());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* void _x86_memio_unmap(bus_space_tag bst, bus_space_handle bsh,
|
||||
* bus_size_t size, bus_addr_t *adrp)
|
||||
*
|
||||
* This function unmaps memory- or io-space mapped by the function
|
||||
* _x86_memio_map(). This function works nearly as same as
|
||||
* x86_memio_unmap(), but this function does not ask kernel
|
||||
* built-in extents and returns physical address of the bus space,
|
||||
* for the convenience of the extra extent manager.
|
||||
*/
|
||||
void
|
||||
_x86_memio_unmap(t, bsh, size, adrp)
|
||||
bus_space_tag_t t;
|
||||
bus_space_handle_t bsh;
|
||||
bus_size_t size;
|
||||
bus_addr_t *adrp;
|
||||
{
|
||||
u_long va, endva;
|
||||
bus_addr_t bpa;
|
||||
|
||||
/*
|
||||
* Find the correct extent and bus physical address.
|
||||
*/
|
||||
if (t == X86_BUS_SPACE_IO) {
|
||||
bpa = bsh;
|
||||
} else if (t == X86_BUS_SPACE_MEM) {
|
||||
if (bsh >= atdevbase && (bsh + size) <= (atdevbase + IOM_SIZE)) {
|
||||
bpa = (bus_addr_t)ISA_PHYSADDR(bsh);
|
||||
} else {
|
||||
|
||||
va = x86_trunc_page(bsh);
|
||||
endva = x86_round_page(bsh + size);
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (endva <= va) {
|
||||
panic("_x86_memio_unmap: overflow");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __NetBSD_Version__ > 104050000
|
||||
if (pmap_extract(pmap_kernel(), va, &bpa) == FALSE) {
|
||||
panic("_x86_memio_unmap:"
|
||||
" wrong virtual address");
|
||||
}
|
||||
bpa += (bsh & PGOFSET);
|
||||
#else
|
||||
bpa = pmap_extract(pmap_kernel(), va) + (bsh & PGOFSET);
|
||||
#endif
|
||||
|
||||
pmap_kremove(va, endva - va);
|
||||
/*
|
||||
* Free the kernel virtual mapping.
|
||||
*/
|
||||
uvm_km_free(kernel_map, va, endva - va);
|
||||
}
|
||||
} else {
|
||||
panic("_x86_memio_unmap: bad bus space tag");
|
||||
}
|
||||
|
||||
if (adrp != NULL) {
|
||||
*adrp = bpa;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
x86_memio_unmap(t, bsh, size)
|
||||
bus_space_tag_t t;
|
||||
bus_space_handle_t bsh;
|
||||
bus_size_t size;
|
||||
{
|
||||
struct extent *ex;
|
||||
u_long va, endva;
|
||||
bus_addr_t bpa;
|
||||
|
||||
/*
|
||||
* Find the correct extent and bus physical address.
|
||||
*/
|
||||
if (t == X86_BUS_SPACE_IO) {
|
||||
ex = ioport_ex;
|
||||
bpa = bsh;
|
||||
} else if (t == X86_BUS_SPACE_MEM) {
|
||||
ex = iomem_ex;
|
||||
|
||||
if (bsh >= atdevbase &&
|
||||
(bsh + size) <= (atdevbase + IOM_SIZE)) {
|
||||
bpa = (bus_addr_t)ISA_PHYSADDR(bsh);
|
||||
goto ok;
|
||||
}
|
||||
|
||||
va = x86_trunc_page(bsh);
|
||||
endva = x86_round_page(bsh + size);
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (endva <= va)
|
||||
panic("x86_memio_unmap: overflow");
|
||||
#endif
|
||||
|
||||
(void) pmap_extract(pmap_kernel(), va, &bpa);
|
||||
bpa += (bsh & PGOFSET);
|
||||
|
||||
pmap_kremove(va, endva - va);
|
||||
/*
|
||||
* Free the kernel virtual mapping.
|
||||
*/
|
||||
uvm_km_free(kernel_map, va, endva - va);
|
||||
} else
|
||||
panic("x86_memio_unmap: bad bus space tag");
|
||||
|
||||
ok:
|
||||
if (extent_free(ex, bpa, size,
|
||||
EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
|
||||
printf("x86_memio_unmap: %s 0x%lx, size 0x%lx\n",
|
||||
(t == X86_BUS_SPACE_IO) ? "port" : "pa", bpa, size);
|
||||
printf("x86_memio_unmap: can't free region\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
x86_memio_free(t, bsh, size)
|
||||
bus_space_tag_t t;
|
||||
bus_space_handle_t bsh;
|
||||
bus_size_t size;
|
||||
{
|
||||
|
||||
/* x86_memio_unmap() does all that we need to do. */
|
||||
x86_memio_unmap(t, bsh, size);
|
||||
}
|
||||
|
||||
int
|
||||
x86_memio_subregion(t, bsh, offset, size, nbshp)
|
||||
bus_space_tag_t t;
|
||||
bus_space_handle_t bsh;
|
||||
bus_size_t offset, size;
|
||||
bus_space_handle_t *nbshp;
|
||||
{
|
||||
|
||||
*nbshp = bsh + offset;
|
||||
return (0);
|
||||
}
|
||||
|
||||
paddr_t
|
||||
x86_memio_mmap(t, addr, off, prot, flags)
|
||||
bus_space_tag_t t;
|
||||
bus_addr_t addr;
|
||||
off_t off;
|
||||
int prot;
|
||||
int flags;
|
||||
{
|
||||
|
||||
/* Can't mmap I/O space. */
|
||||
if (t == X86_BUS_SPACE_IO)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* "addr" is the base address of the device we're mapping.
|
||||
* "off" is the offset into that device.
|
||||
*
|
||||
* Note we are called for each "page" in the device that
|
||||
* the upper layers want to map.
|
||||
*/
|
||||
return (x86_btop(addr + off));
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
/* $NetBSD: clock.c,v 1.1.2.2 2004/07/17 16:43:56 he Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2004 Christian Limpach.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Christian Limpach.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opt_xen.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.1.2.2 2004/07/17 16:43:56 he Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <machine/xen.h>
|
||||
#include <machine/hypervisor.h>
|
||||
#include <machine/evtchn.h>
|
||||
#include <machine/cpu_counter.h>
|
||||
|
||||
#include <dev/clock_subr.h>
|
||||
|
||||
#include "config_time.h" /* for CONFIG_TIME */
|
||||
|
||||
static int xen_timer_handler(void *, struct trapframe *);
|
||||
|
||||
/* These are peridically updated in shared_info, and then copied here. */
|
||||
static unsigned long shadow_tsc_stamp;
|
||||
static u_int64_t shadow_system_time;
|
||||
static unsigned long shadow_time_version;
|
||||
static struct timeval shadow_tv;
|
||||
|
||||
static int timeset;
|
||||
|
||||
/*
|
||||
* Reads a consistent set of time-base values from Xen, into a shadow data
|
||||
* area. Must be called at splclock.
|
||||
*/
|
||||
static void
|
||||
get_time_values_from_xen(void)
|
||||
{
|
||||
do {
|
||||
shadow_time_version = HYPERVISOR_shared_info->time_version2;
|
||||
__insn_barrier();
|
||||
shadow_tv.tv_sec = HYPERVISOR_shared_info->wc_sec;
|
||||
shadow_tv.tv_usec = HYPERVISOR_shared_info->wc_usec;
|
||||
shadow_tsc_stamp = HYPERVISOR_shared_info->tsc_timestamp;
|
||||
shadow_system_time = HYPERVISOR_shared_info->system_time;
|
||||
__insn_barrier();
|
||||
} while (shadow_time_version != HYPERVISOR_shared_info->time_version1);
|
||||
}
|
||||
|
||||
void
|
||||
inittodr(time_t base)
|
||||
{
|
||||
int s;
|
||||
|
||||
/*
|
||||
* if the file system time is more than a year older than the
|
||||
* kernel, warn and then set the base time to the CONFIG_TIME.
|
||||
*/
|
||||
if (base && base < (CONFIG_TIME-SECYR)) {
|
||||
printf("WARNING: preposterous time in file system\n");
|
||||
base = CONFIG_TIME;
|
||||
}
|
||||
|
||||
s = splclock();
|
||||
get_time_values_from_xen();
|
||||
splx(s);
|
||||
|
||||
time.tv_usec = shadow_tv.tv_usec;
|
||||
time.tv_sec = shadow_tv.tv_sec + rtc_offset * 60;
|
||||
#ifdef DEBUG_CLOCK
|
||||
printf("readclock: %ld (%ld)\n", time.tv_sec, base);
|
||||
#endif
|
||||
if (base != 0 && base < time.tv_sec - 5*SECYR)
|
||||
printf("WARNING: file system time much less than clock time\n");
|
||||
else if (base > time.tv_sec + 5*SECYR) {
|
||||
printf("WARNING: clock time much less than file system time\n");
|
||||
printf("WARNING: using file system time\n");
|
||||
goto fstime;
|
||||
}
|
||||
|
||||
timeset = 1;
|
||||
return;
|
||||
|
||||
fstime:
|
||||
timeset = 1;
|
||||
time.tv_sec = base;
|
||||
printf("WARNING: CHECK AND RESET THE DATE!\n");
|
||||
}
|
||||
|
||||
void
|
||||
resettodr()
|
||||
{
|
||||
#ifdef DOM0OPS
|
||||
dom0_op_t op;
|
||||
int s;
|
||||
#endif
|
||||
#ifdef DEBUG_CLOCK
|
||||
struct clock_ymdhms dt;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We might have been called by boot() due to a crash early
|
||||
* on. Don't reset the clock chip in this case.
|
||||
*/
|
||||
if (!timeset)
|
||||
return;
|
||||
|
||||
#ifdef DEBUG_CLOCK
|
||||
clock_secs_to_ymdhms(time.tv_sec - rtc_offset * 60, &dt);
|
||||
|
||||
printf("setclock: %d/%d/%d %02d:%02d:%02d\n", dt.dt_year,
|
||||
dt.dt_mon, dt.dt_day, dt.dt_hour, dt.dt_min, dt.dt_sec);
|
||||
#endif
|
||||
#ifdef DOM0OPS
|
||||
if (xen_start_info.dom_id == 0) {
|
||||
s = splclock();
|
||||
|
||||
op.cmd = DOM0_SETTIME;
|
||||
op.u.settime.secs = time.tv_sec - rtc_offset * 60;
|
||||
op.u.settime.usecs = time.tv_usec;
|
||||
op.u.settime.system_time = shadow_system_time;
|
||||
HYPERVISOR_dom0_op(&op);
|
||||
|
||||
splx(s);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
startrtclock()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait approximately `n' microseconds.
|
||||
*/
|
||||
void
|
||||
xen_delay(int n)
|
||||
{
|
||||
u_int64_t when;
|
||||
|
||||
get_time_values_from_xen();
|
||||
when = shadow_system_time + n * 1000;
|
||||
while (shadow_system_time < when)
|
||||
get_time_values_from_xen();
|
||||
}
|
||||
|
||||
void
|
||||
xen_microtime(struct timeval *tv)
|
||||
{
|
||||
|
||||
*tv = time;
|
||||
}
|
||||
|
||||
void
|
||||
xen_initclocks()
|
||||
{
|
||||
int irq = bind_virq_to_irq(VIRQ_TIMER);
|
||||
|
||||
event_set_handler(irq, (int (*)(void *))xen_timer_handler,
|
||||
NULL, IPL_CLOCK);
|
||||
hypervisor_enable_irq(irq);
|
||||
}
|
||||
|
||||
static int
|
||||
xen_timer_handler(void *arg, struct trapframe *regs)
|
||||
{
|
||||
#if defined(I586_CPU) || defined(I686_CPU)
|
||||
static int microset_iter; /* call cc_microset once/sec */
|
||||
struct cpu_info *ci = curcpu();
|
||||
|
||||
/*
|
||||
* If we have a cycle counter, do the microset thing.
|
||||
*/
|
||||
if (ci->ci_feature_flags & CPUID_TSC) {
|
||||
if (
|
||||
#if defined(MULTIPROCESSOR)
|
||||
CPU_IS_PRIMARY(ci) &&
|
||||
#endif
|
||||
(microset_iter--) == 0) {
|
||||
microset_iter = hz - 1;
|
||||
#if defined(MULTIPROCESSOR)
|
||||
x86_broadcast_ipi(X86_IPI_MICROSET);
|
||||
#endif
|
||||
cc_microset_time = time;
|
||||
cc_microset(ci);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
get_time_values_from_xen();
|
||||
|
||||
hardclock((struct clockframe *)regs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
setstatclockrate(int arg)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
/* $NetBSD: hypervisor.c,v 1.7.2.1 2004/05/22 15:58:54 he Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2004 Christian Limpach.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Christian Limpach.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: hypervisor.c,v 1.7.2.1 2004/05/22 15:58:54 he Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include "xencons.h"
|
||||
#include "xennet.h"
|
||||
#include "xbd.h"
|
||||
#include "xenkbc.h"
|
||||
#include "vga_xen.h"
|
||||
#include "npx.h"
|
||||
|
||||
#include "opt_xen.h"
|
||||
|
||||
#include <machine/xen.h>
|
||||
#include <machine/hypervisor.h>
|
||||
#include <machine/evtchn.h>
|
||||
|
||||
#ifdef DOM0OPS
|
||||
#include <sys/dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/tree.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <miscfs/specfs/specdev.h>
|
||||
#include <miscfs/kernfs/kernfs.h>
|
||||
#include <machine/kernfs_machdep.h>
|
||||
#endif
|
||||
|
||||
#if NXENNET > 0
|
||||
#include <net/if.h>
|
||||
#include <net/if_ether.h>
|
||||
#include <net/if_media.h>
|
||||
#include <machine/if_xennetvar.h>
|
||||
#endif
|
||||
|
||||
#if NXBD > 0
|
||||
#include <sys/buf.h>
|
||||
#include <sys/disk.h>
|
||||
#include <dev/dkvar.h>
|
||||
#include <machine/xbdvar.h>
|
||||
#endif
|
||||
|
||||
#if NXENKBC > 0
|
||||
#include <dev/pckbport/pckbportvar.h>
|
||||
#include <machine/xenkbcvar.h>
|
||||
#endif
|
||||
|
||||
#if NVGA_XEN > 0
|
||||
#include <machine/bus.h>
|
||||
#include <machine/vga_xenvar.h>
|
||||
#endif
|
||||
|
||||
int hypervisor_match(struct device *, struct cfdata *, void *);
|
||||
void hypervisor_attach(struct device *, struct device *, void *);
|
||||
|
||||
CFATTACH_DECL(hypervisor, sizeof(struct device),
|
||||
hypervisor_match, hypervisor_attach, NULL, NULL);
|
||||
|
||||
int hypervisor_print(void *, const char *);
|
||||
|
||||
union hypervisor_attach_cookie {
|
||||
const char *hac_device; /* first elem of all */
|
||||
#if NXENKBC > 0
|
||||
struct xenkbc_attach_args hac_xenkbc;
|
||||
#endif
|
||||
#if NVGA_XEN > 0
|
||||
struct xen_vga_attach_args hac_vga_xen;
|
||||
#endif
|
||||
#if NXENCONS > 0
|
||||
struct xencons_attach_args hac_xencons;
|
||||
#endif
|
||||
#if NXENNET > 0
|
||||
struct xennet_attach_args hac_xennet;
|
||||
#endif
|
||||
#if NXBD > 0
|
||||
struct xbd_attach_args hac_xbd;
|
||||
#endif
|
||||
#if NNPX > 0
|
||||
struct xen_npx_attach_args hac_xennpx;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Probe for the hypervisor; always succeeds.
|
||||
*/
|
||||
int
|
||||
hypervisor_match(parent, match, aux)
|
||||
struct device *parent;
|
||||
struct cfdata *match;
|
||||
void *aux;
|
||||
{
|
||||
struct hypervisor_attach_args *haa = aux;
|
||||
|
||||
if (strcmp(haa->haa_busname, "hypervisor") == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach the hypervisor.
|
||||
*/
|
||||
void
|
||||
hypervisor_attach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
union hypervisor_attach_cookie hac;
|
||||
|
||||
printf("\n");
|
||||
|
||||
init_events();
|
||||
|
||||
#if NXENKBC > 0
|
||||
hac.hac_xenkbc.xa_device = "xenkbc";
|
||||
config_found(self, &hac.hac_xenkbc, hypervisor_print);
|
||||
#endif
|
||||
|
||||
#if NVGA_XEN > 0
|
||||
hac.hac_vga_xen.xa_device = "vga_xen";
|
||||
hac.hac_vga_xen.xa_iot = X86_BUS_SPACE_IO;
|
||||
hac.hac_vga_xen.xa_memt = X86_BUS_SPACE_MEM;
|
||||
config_found(self, &hac.hac_vga_xen, hypervisor_print);
|
||||
#endif
|
||||
|
||||
#if NXENCONS > 0
|
||||
hac.hac_xencons.xa_device = "xencons";
|
||||
config_found(self, &hac.hac_xencons, hypervisor_print);
|
||||
#endif
|
||||
#if NXENNET > 0
|
||||
hac.hac_xennet.xa_device = "xennet";
|
||||
xennet_scan(self, &hac.hac_xennet, hypervisor_print);
|
||||
#endif
|
||||
#if NXBD > 0
|
||||
hac.hac_xbd.xa_device = "xbd";
|
||||
xbd_scan(self, &hac.hac_xbd, hypervisor_print);
|
||||
#endif
|
||||
#if NNPX > 0
|
||||
hac.hac_xennpx.xa_device = "npx";
|
||||
config_found(self, &hac.hac_xennpx, hypervisor_print);
|
||||
#endif
|
||||
#ifdef DOM0OPS
|
||||
if (xen_start_info.flags & SIF_PRIVILEGED) {
|
||||
xenkernfs_init();
|
||||
xenprivcmd_init();
|
||||
xenmachmem_init();
|
||||
xenvfr_init();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
hypervisor_print(aux, parent)
|
||||
void *aux;
|
||||
const char *parent;
|
||||
{
|
||||
union hypervisor_attach_cookie *hac = aux;
|
||||
|
||||
if (parent)
|
||||
aprint_normal("%s at %s", hac->hac_device, parent);
|
||||
return (UNCONF);
|
||||
}
|
||||
|
||||
void
|
||||
hypervisor_notify_via_evtchn(unsigned int port)
|
||||
{
|
||||
evtchn_op_t op;
|
||||
|
||||
op.cmd = EVTCHNOP_send;
|
||||
op.u.send.local_port = port;
|
||||
(void)HYPERVISOR_event_channel_op(&op);
|
||||
}
|
||||
|
||||
#ifdef DOM0OPS
|
||||
|
||||
#define DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
|
||||
|
||||
kernfs_parentdir_t *kernxen_pkt;
|
||||
|
||||
void
|
||||
xenkernfs_init()
|
||||
{
|
||||
kernfs_entry_t *dkt;
|
||||
|
||||
KERNFS_ALLOCENTRY(dkt, M_TEMP, M_WAITOK);
|
||||
KERNFS_INITENTRY(dkt, DT_DIR, "xen", NULL, KFSsubdir, VDIR, DIR_MODE);
|
||||
kernfs_addentry(NULL, dkt);
|
||||
kernxen_pkt = KERNFS_ENTOPARENTDIR(dkt);
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,444 @@
|
||||
/* $NetBSD: xen_debug.c,v 1.1.2.1 2004/05/22 15:59:31 he Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2004 Christian Limpach.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Christian Limpach.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2002-2003, K A Fraser & R Neugebauer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: xen_debug.c,v 1.1.2.1 2004/05/22 15:59:31 he Exp $");
|
||||
|
||||
#define XENDEBUG
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/stdarg.h>
|
||||
#include <machine/xen.h>
|
||||
#include <machine/hypervisor.h>
|
||||
|
||||
#ifdef XENDEBUG
|
||||
|
||||
#define PRINTK_BUFSIZE 1024
|
||||
void
|
||||
printk(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
static char buf[PRINTK_BUFSIZE];
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = vsnprintf(buf, PRINTK_BUFSIZE - 1, fmt, ap);
|
||||
va_end(ap);
|
||||
buf[ret] = 0;
|
||||
(void)HYPERVISOR_console_io(CONSOLEIO_write, ret, buf);
|
||||
}
|
||||
|
||||
void
|
||||
vprintk(const char *fmt, va_list ap)
|
||||
{
|
||||
int ret;
|
||||
static char buf[PRINTK_BUFSIZE];
|
||||
|
||||
ret = vsnprintf(buf, PRINTK_BUFSIZE - 1, fmt, ap);
|
||||
buf[ret] = 0;
|
||||
(void)HYPERVISOR_console_io(CONSOLEIO_write, ret, buf);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef XENDEBUG_LOW
|
||||
|
||||
int xen_once = 0;
|
||||
|
||||
void hypervisor_callback(void);
|
||||
void failsafe_callback(void);
|
||||
|
||||
void xen_dbglow_init(void);
|
||||
void
|
||||
xen_dbglow_init()
|
||||
{
|
||||
start_info_t *si;
|
||||
#if 0
|
||||
int i;
|
||||
#endif
|
||||
|
||||
si = &xen_start_info;
|
||||
|
||||
HYPERVISOR_set_callbacks(
|
||||
__KERNEL_CS, (unsigned long)hypervisor_callback,
|
||||
__KERNEL_CS, (unsigned long)failsafe_callback);
|
||||
|
||||
trap_init();
|
||||
|
||||
/* __sti(); */
|
||||
|
||||
/* print out some useful information */
|
||||
printk(version);
|
||||
printk("start_info: %p\n", si);
|
||||
printk(" nr_pages: %lu", si->nr_pages);
|
||||
printk(" shared_inf: %p (was %p)\n", HYPERVISOR_shared_info,
|
||||
si->shared_info);
|
||||
printk(" pt_base: %p", (void *)si->pt_base);
|
||||
printk(" mod_start: 0x%lx\n", si->mod_start);
|
||||
printk(" mod_len: %lu\n", si->mod_len);
|
||||
#if 0
|
||||
printk(" net_rings: ");
|
||||
for (i = 0; i < MAX_DOMAIN_VIFS; i++) {
|
||||
if (si->net_rings[i] == 0)
|
||||
break;
|
||||
printk(" %lx", si->net_rings[i]);
|
||||
};
|
||||
printk("\n");
|
||||
printk(" blk_ring: 0x%lx\n", si->blk_ring);
|
||||
#endif
|
||||
printk(" dom_id: %d\n", si->dom_id);
|
||||
printk(" flags: 0x%lx\n", si->flags);
|
||||
printk(" cmd_line: %s\n", si->cmd_line ?
|
||||
(const char *)si->cmd_line : "NULL");
|
||||
}
|
||||
|
||||
|
||||
void xen_dbg0(char *);
|
||||
void
|
||||
xen_dbg0(char *end)
|
||||
{
|
||||
struct cpu_info *ci;
|
||||
|
||||
ci = &cpu_info_primary;
|
||||
if (xen_once)
|
||||
printk("xencpu level %d ipending %08x master %08x\n",
|
||||
ci->ci_ilevel, ci->ci_ipending,
|
||||
HYPERVISOR_shared_info->events_mask);
|
||||
/* ipending %08x imask %08x iunmask %08x */
|
||||
/* ci->ci_imask[IPL_NET], ci->ci_iunmask[IPL_NET]); */
|
||||
}
|
||||
|
||||
void xen_dbg1(void *esp, int ss);
|
||||
void
|
||||
xen_dbg1(void *esp, int ss)
|
||||
{
|
||||
#if 1
|
||||
struct cpu_info *ci;
|
||||
|
||||
ci = &cpu_info_primary;
|
||||
if (xen_once)
|
||||
printk("xenhighlevel %d ipending %08x master %08x events %08x\n",
|
||||
ci->ci_ilevel, ci->ci_ipending,
|
||||
HYPERVISOR_shared_info->events_mask, HYPERVISOR_shared_info->events);
|
||||
#else
|
||||
printk("stack switch %p %d/%d, sp %p\n", esp, ss, IDXSEL(ss), &ss);
|
||||
#endif
|
||||
}
|
||||
|
||||
void xen_dbg2(void);
|
||||
void
|
||||
xen_dbg2(void)
|
||||
{
|
||||
if (xen_once)
|
||||
printk("xen_dbg2\n");
|
||||
}
|
||||
|
||||
void xen_dbg3(void *, void *);
|
||||
void
|
||||
xen_dbg3(void *ss, void *esp)
|
||||
{
|
||||
if (xen_once)
|
||||
printk("xen_dbg3 %p %p\n", ss, esp);
|
||||
}
|
||||
|
||||
void xen_dbg4(void *);
|
||||
void
|
||||
xen_dbg4(void *esi)
|
||||
{
|
||||
|
||||
printk("xen_dbg4 %p\n", esi);
|
||||
for(;;);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void do_exit(void);
|
||||
|
||||
/*
|
||||
* These are assembler stubs in vector.S.
|
||||
* They are the actual entry points for virtual exceptions.
|
||||
*/
|
||||
void divide_error(void);
|
||||
void debug(void);
|
||||
void int3(void);
|
||||
void overflow(void);
|
||||
void bounds(void);
|
||||
void invalid_op(void);
|
||||
void device_not_available(void);
|
||||
void double_fault(void);
|
||||
void coprocessor_segment_overrun(void);
|
||||
void invalid_TSS(void);
|
||||
void segment_not_present(void);
|
||||
void stack_segment(void);
|
||||
void general_protection(void);
|
||||
void page_fault(void);
|
||||
void coprocessor_error(void);
|
||||
void simd_coprocessor_error(void);
|
||||
void alignment_check(void);
|
||||
void spurious_interrupt_bug(void);
|
||||
void machine_check(void);
|
||||
|
||||
static void
|
||||
dump_regs(struct pt_regs *regs)
|
||||
{
|
||||
int in_kernel = 1;
|
||||
unsigned long esp;
|
||||
unsigned short ss;
|
||||
|
||||
esp = (unsigned long) (®s->esp);
|
||||
ss = __KERNEL_DS;
|
||||
if (regs->xcs & 2) {
|
||||
in_kernel = 0;
|
||||
esp = regs->esp;
|
||||
ss = regs->xss & 0xffff;
|
||||
}
|
||||
printf("EIP: %04x:[<%08lx>]\n",
|
||||
0xffff & regs->xcs, regs->eip);
|
||||
printf("EFLAGS: %08lx\n",regs->eflags);
|
||||
printf("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
|
||||
regs->eax, regs->ebx, regs->ecx, regs->edx);
|
||||
printf("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
|
||||
regs->esi, regs->edi, regs->ebp, esp);
|
||||
printf("ds: %04x es: %04x ss: %04x\n",
|
||||
regs->xds & 0xffff, regs->xes & 0xffff, ss);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
dump_code(unsigned eip)
|
||||
{
|
||||
unsigned *ptr = (unsigned *)eip;
|
||||
int x;
|
||||
|
||||
printk("Bytes at eip:\n");
|
||||
for (x = -4; x < 5; x++)
|
||||
printf("%x", ptr[x]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* C handlers here have their parameter-list constructed by the
|
||||
* assembler stubs above. Each one gets a pointer to a list
|
||||
* of register values (to be restored at end of exception).
|
||||
* Some will also receive an error code -- this is the code that
|
||||
* was generated by the processor for the underlying real exception.
|
||||
*
|
||||
* Note that the page-fault exception is special. It also receives
|
||||
* the faulting linear address. Normally this would be found in
|
||||
* register CR2, but that is not accessible in a virtualised OS.
|
||||
*/
|
||||
|
||||
static void inline
|
||||
do_trap(int trapnr, char *str, struct pt_regs *regs, long error_code)
|
||||
{
|
||||
|
||||
printk("FATAL: Unhandled Trap (see mini-os:traps.c)");
|
||||
printf("%d %s", trapnr, str);
|
||||
dump_regs(regs);
|
||||
dump_code(regs->eip);
|
||||
|
||||
do_exit();
|
||||
}
|
||||
|
||||
#define DO_ERROR(trapnr, str, name) \
|
||||
void do_##name(struct pt_regs *regs, long error_code); \
|
||||
void do_##name(struct pt_regs *regs, long error_code) \
|
||||
{ \
|
||||
do_trap(trapnr, str, regs, error_code); \
|
||||
}
|
||||
|
||||
#define DO_ERROR_INFO(trapnr, str, name, sicode, siaddr) \
|
||||
void do_##name(struct pt_regs *regs, long error_code); \
|
||||
void do_##name(struct pt_regs *regs, long error_code) \
|
||||
{ \
|
||||
do_trap(trapnr, str, regs, error_code); \
|
||||
}
|
||||
|
||||
DO_ERROR_INFO( 0, "divide error", divide_error, FPE_INTDIV, regs->eip)
|
||||
DO_ERROR( 3, "int3", int3)
|
||||
DO_ERROR( 4, "overflow", overflow)
|
||||
DO_ERROR( 5, "bounds", bounds)
|
||||
DO_ERROR_INFO( 6, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
|
||||
DO_ERROR( 7, "device not available", device_not_available)
|
||||
DO_ERROR( 8, "double fault", double_fault)
|
||||
DO_ERROR( 9, "coprocessor segment overrun", coprocessor_segment_overrun)
|
||||
DO_ERROR(10, "invalid TSS", invalid_TSS)
|
||||
DO_ERROR(11, "segment not present", segment_not_present)
|
||||
DO_ERROR(12, "stack segment", stack_segment)
|
||||
DO_ERROR_INFO(17, "alignment check", alignment_check, BUS_ADRALN, 0)
|
||||
DO_ERROR(18, "machine check", machine_check)
|
||||
|
||||
void do_page_fault(struct pt_regs *, long, unsigned long);
|
||||
void
|
||||
do_page_fault(struct pt_regs *regs, long error_code, unsigned long address)
|
||||
{
|
||||
|
||||
printk("Page fault\n");
|
||||
printk("Address: 0x%lx", address);
|
||||
printk("Error Code: 0x%lx", error_code);
|
||||
printk("eip: \t 0x%lx", regs->eip);
|
||||
do_exit();
|
||||
}
|
||||
|
||||
void do_general_protection(struct pt_regs *, long);
|
||||
void
|
||||
do_general_protection(struct pt_regs *regs, long error_code)
|
||||
{
|
||||
|
||||
HYPERVISOR_shared_info->events_mask = 0;
|
||||
printk("GPF\n");
|
||||
printk("Error Code: 0x%lx", error_code);
|
||||
dump_regs(regs);
|
||||
dump_code(regs->eip);
|
||||
do_exit();
|
||||
}
|
||||
|
||||
|
||||
void do_debug(struct pt_regs *, long);
|
||||
void
|
||||
do_debug(struct pt_regs *regs, long error_code)
|
||||
{
|
||||
|
||||
printk("Debug exception\n");
|
||||
#define TF_MASK 0x100
|
||||
regs->eflags &= ~TF_MASK;
|
||||
dump_regs(regs);
|
||||
do_exit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void do_coprocessor_error(struct pt_regs *, long);
|
||||
void
|
||||
do_coprocessor_error(struct pt_regs *regs, long error_code)
|
||||
{
|
||||
|
||||
printk("Copro error\n");
|
||||
dump_regs(regs);
|
||||
dump_code(regs->eip);
|
||||
do_exit();
|
||||
}
|
||||
|
||||
void simd_math_error(void *);
|
||||
void
|
||||
simd_math_error(void *eip)
|
||||
{
|
||||
|
||||
printk("SIMD error\n");
|
||||
}
|
||||
|
||||
void do_simd_coprocessor_error(struct pt_regs *, long);
|
||||
void
|
||||
do_simd_coprocessor_error(struct pt_regs *regs, long error_code)
|
||||
{
|
||||
|
||||
printk("SIMD copro error\n");
|
||||
}
|
||||
|
||||
void do_spurious_interrupt_bug(struct pt_regs *, long);
|
||||
void
|
||||
do_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
do_exit(void)
|
||||
{
|
||||
|
||||
HYPERVISOR_exit();
|
||||
}
|
||||
|
||||
/*
|
||||
* Submit a virtual IDT to teh hypervisor. This consists of tuples
|
||||
* (interrupt vector, privilege ring, CS:EIP of handler).
|
||||
* The 'privilege ring' field specifies the least-privileged ring that
|
||||
* can trap to that vector using a software-interrupt instruction (INT).
|
||||
*/
|
||||
static trap_info_t trap_table[] = {
|
||||
{ 0, 0, __KERNEL_CS, (unsigned long)divide_error },
|
||||
{ 1, 0, __KERNEL_CS, (unsigned long)debug },
|
||||
{ 3, 3, __KERNEL_CS, (unsigned long)int3 },
|
||||
{ 4, 3, __KERNEL_CS, (unsigned long)overflow },
|
||||
{ 5, 3, __KERNEL_CS, (unsigned long)bounds },
|
||||
{ 6, 0, __KERNEL_CS, (unsigned long)invalid_op },
|
||||
{ 7, 0, __KERNEL_CS, (unsigned long)device_not_available },
|
||||
{ 8, 0, __KERNEL_CS, (unsigned long)double_fault },
|
||||
{ 9, 0, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun },
|
||||
{ 10, 0, __KERNEL_CS, (unsigned long)invalid_TSS },
|
||||
{ 11, 0, __KERNEL_CS, (unsigned long)segment_not_present },
|
||||
{ 12, 0, __KERNEL_CS, (unsigned long)stack_segment },
|
||||
{ 13, 0, __KERNEL_CS, (unsigned long)general_protection },
|
||||
{ 14, 0, __KERNEL_CS, (unsigned long)page_fault },
|
||||
{ 15, 0, __KERNEL_CS, (unsigned long)spurious_interrupt_bug },
|
||||
{ 16, 0, __KERNEL_CS, (unsigned long)coprocessor_error },
|
||||
{ 17, 0, __KERNEL_CS, (unsigned long)alignment_check },
|
||||
{ 18, 0, __KERNEL_CS, (unsigned long)machine_check },
|
||||
{ 19, 0, __KERNEL_CS, (unsigned long)simd_coprocessor_error },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
void
|
||||
trap_init(void)
|
||||
{
|
||||
|
||||
HYPERVISOR_set_trap_table(trap_table);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,352 @@
|
||||
/* $NetBSD: xencons.c,v 1.1.2.1 2004/05/22 15:59:21 he Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2004 Christian Limpach.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Christian Limpach.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: xencons.c,v 1.1.2.1 2004/05/22 15:59:21 he Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/tty.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/conf.h>
|
||||
|
||||
#include <machine/stdarg.h>
|
||||
#include <machine/xen.h>
|
||||
#include <machine/hypervisor.h>
|
||||
|
||||
#include <dev/cons.h>
|
||||
|
||||
#include <ddb/db_output.h> /* XXX for db_max_line */
|
||||
|
||||
static int xencons_isconsole = 0;
|
||||
|
||||
#define XENCONS_UNIT(x) (minor(x))
|
||||
#define XENCONS_BURST 128
|
||||
|
||||
int xencons_match (struct device *, struct cfdata *, void *);
|
||||
void xencons_attach (struct device *, struct device *, void *);
|
||||
/* int xencons_intr (void *); */
|
||||
void xencons_init (void);
|
||||
|
||||
struct xencons_softc {
|
||||
struct device sc_dev;
|
||||
struct tty *sc_tty;
|
||||
};
|
||||
|
||||
CFATTACH_DECL(xencons, sizeof(struct xencons_softc),
|
||||
xencons_match, xencons_attach, NULL, NULL);
|
||||
|
||||
extern struct cfdriver xencons_cd;
|
||||
|
||||
dev_type_open(xencons_open);
|
||||
dev_type_close(xencons_close);
|
||||
dev_type_read(xencons_read);
|
||||
dev_type_write(xencons_write);
|
||||
dev_type_ioctl(xencons_ioctl);
|
||||
dev_type_stop(xencons_stop);
|
||||
dev_type_tty(xencons_tty);
|
||||
dev_type_poll(xencons_poll);
|
||||
|
||||
const struct cdevsw xencons_cdevsw = {
|
||||
xencons_open, xencons_close, xencons_read, xencons_write,
|
||||
xencons_ioctl, xencons_stop, xencons_tty, xencons_poll,
|
||||
NULL, ttykqfilter, D_TTY
|
||||
};
|
||||
|
||||
|
||||
void xenconscn_attach(void);
|
||||
int xenconscn_getc(dev_t);
|
||||
void xenconscn_putc(dev_t, int);
|
||||
void xenconscn_pollc(dev_t, int);
|
||||
|
||||
static struct consdev xencons = {
|
||||
NULL, NULL, xenconscn_getc, xenconscn_putc, xenconscn_pollc,
|
||||
NULL, NULL, NULL, NODEV, CN_NORMAL
|
||||
};
|
||||
|
||||
void xencons_start (struct tty *);
|
||||
int xencons_param (struct tty *, struct termios *);
|
||||
|
||||
int
|
||||
xencons_match(struct device *parent, struct cfdata *match, void *aux)
|
||||
{
|
||||
struct xencons_attach_args *xa = (struct xencons_attach_args *)aux;
|
||||
|
||||
if (strcmp(xa->xa_device, "xencons") == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
xencons_attach(struct device *parent, struct device *self, void *aux)
|
||||
{
|
||||
struct xencons_softc *sc = (void *)self;
|
||||
|
||||
aprint_normal(": Xen Virtual Console Driver\n");
|
||||
|
||||
if (xencons_isconsole) {
|
||||
int maj;
|
||||
|
||||
/* Locate the major number. */
|
||||
maj = cdevsw_lookup_major(&xencons_cdevsw);
|
||||
|
||||
/* There can be only one, but it can have any unit number. */
|
||||
cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit);
|
||||
|
||||
aprint_verbose("%s: console major %d, unit %d\n",
|
||||
sc->sc_dev.dv_xname, maj, sc->sc_dev.dv_unit);
|
||||
|
||||
/* Set db_max_line to avoid paging. */
|
||||
db_max_line = 0x7fffffff;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
xencons_open(dev_t dev, int flag, int mode, struct proc *p)
|
||||
{
|
||||
struct xencons_softc *sc;
|
||||
int unit = XENCONS_UNIT(dev);
|
||||
struct tty *tp;
|
||||
|
||||
sc = device_lookup(&xencons_cd, unit);
|
||||
if (sc == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
if (!sc->sc_tty) {
|
||||
tp = sc->sc_tty = ttymalloc();
|
||||
tty_attach(tp);
|
||||
} else
|
||||
tp = sc->sc_tty;
|
||||
|
||||
tp->t_oproc = xencons_start;
|
||||
tp->t_param = xencons_param;
|
||||
tp->t_dev = dev;
|
||||
if ((tp->t_state & TS_ISOPEN) == 0) {
|
||||
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 = tp->t_ospeed = TTYDEF_SPEED;
|
||||
xencons_param(tp, &tp->t_termios);
|
||||
ttsetwater(tp);
|
||||
} else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
|
||||
return (EBUSY);
|
||||
tp->t_state |= TS_CARR_ON;
|
||||
|
||||
return ((*tp->t_linesw->l_open)(dev, tp));
|
||||
}
|
||||
|
||||
int
|
||||
xencons_close(dev_t dev, int flag, int mode, struct proc *p)
|
||||
{
|
||||
struct xencons_softc *sc = device_lookup(&xencons_cd,
|
||||
XENCONS_UNIT(dev));
|
||||
struct tty *tp = sc->sc_tty;
|
||||
|
||||
if (tp == NULL)
|
||||
return (0);
|
||||
(*tp->t_linesw->l_close)(tp, flag);
|
||||
ttyclose(tp);
|
||||
#ifdef notyet /* XXX */
|
||||
ttyfree(tp);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
xencons_read(dev_t dev, struct uio *uio, int flag)
|
||||
{
|
||||
struct xencons_softc *sc = device_lookup(&xencons_cd,
|
||||
XENCONS_UNIT(dev));
|
||||
struct tty *tp = sc->sc_tty;
|
||||
|
||||
return ((*tp->t_linesw->l_read)(tp, uio, flag));
|
||||
}
|
||||
|
||||
int
|
||||
xencons_write(dev_t dev, struct uio *uio, int flag)
|
||||
{
|
||||
struct xencons_softc *sc = device_lookup(&xencons_cd,
|
||||
XENCONS_UNIT(dev));
|
||||
struct tty *tp = sc->sc_tty;
|
||||
|
||||
return ((*tp->t_linesw->l_write)(tp, uio, flag));
|
||||
}
|
||||
|
||||
int
|
||||
xencons_poll(dev_t dev, int events, struct proc *p)
|
||||
{
|
||||
struct xencons_softc *sc = device_lookup(&xencons_cd,
|
||||
XENCONS_UNIT(dev));
|
||||
struct tty *tp = sc->sc_tty;
|
||||
|
||||
return ((*tp->t_linesw->l_poll)(tp, events, p));
|
||||
}
|
||||
|
||||
struct tty *
|
||||
xencons_tty(dev_t dev)
|
||||
{
|
||||
struct xencons_softc *sc = device_lookup(&xencons_cd,
|
||||
XENCONS_UNIT(dev));
|
||||
struct tty *tp = sc->sc_tty;
|
||||
|
||||
return (tp);
|
||||
}
|
||||
|
||||
int
|
||||
xencons_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
|
||||
{
|
||||
struct xencons_softc *sc = device_lookup(&xencons_cd,
|
||||
XENCONS_UNIT(dev));
|
||||
struct tty *tp = sc->sc_tty;
|
||||
int error;
|
||||
|
||||
error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p);
|
||||
if (error != EPASSTHROUGH)
|
||||
return (error);
|
||||
|
||||
error = ttioctl(tp, cmd, data, flag, p);
|
||||
if (error != EPASSTHROUGH)
|
||||
return (error);
|
||||
|
||||
switch (cmd) {
|
||||
default:
|
||||
return (EPASSTHROUGH);
|
||||
}
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
panic("xencons_ioctl: impossible");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
xencons_start(struct tty *tp)
|
||||
{
|
||||
struct clist *cl;
|
||||
int s, len;
|
||||
u_char buf[XENCONS_BURST+1];
|
||||
|
||||
s = spltty();
|
||||
if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
|
||||
goto out;
|
||||
tp->t_state |= TS_BUSY;
|
||||
splx(s);
|
||||
|
||||
/*
|
||||
* We need to do this outside spl since it could be fairly
|
||||
* expensive and we don't want our serial ports to overflow.
|
||||
*/
|
||||
cl = &tp->t_outq;
|
||||
len = q_to_b(cl, buf, XENCONS_BURST);
|
||||
(void)HYPERVISOR_console_io(CONSOLEIO_write, len, buf);
|
||||
|
||||
s = spltty();
|
||||
tp->t_state &= ~TS_BUSY;
|
||||
if (cl->c_cc) {
|
||||
tp->t_state |= TS_TIMEOUT;
|
||||
callout_reset(&tp->t_rstrt_ch, 1, ttrstrt, tp);
|
||||
}
|
||||
if (cl->c_cc <= tp->t_lowat) {
|
||||
if (tp->t_state & TS_ASLEEP) {
|
||||
tp->t_state &= ~TS_ASLEEP;
|
||||
wakeup(cl);
|
||||
}
|
||||
selwakeup(&tp->t_wsel);
|
||||
}
|
||||
out:
|
||||
splx(s);
|
||||
}
|
||||
|
||||
void
|
||||
xencons_stop(struct tty *tp, int flag)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
xenconscn_attach()
|
||||
{
|
||||
|
||||
cn_tab = &xencons;
|
||||
|
||||
xencons_isconsole = 1;
|
||||
}
|
||||
|
||||
int
|
||||
xenconscn_getc(dev_t dev)
|
||||
{
|
||||
|
||||
printf("\n");
|
||||
for (;;);
|
||||
}
|
||||
|
||||
#define MAXLINELEN 1024
|
||||
void
|
||||
xenconscn_putc(dev_t dev, int c)
|
||||
{
|
||||
static char buf[1024+1];
|
||||
static int bufpos = 0;
|
||||
|
||||
buf[bufpos++] = c;
|
||||
if (c == '\n') {
|
||||
buf[bufpos] = 0;
|
||||
(void)HYPERVISOR_console_io(CONSOLEIO_write, bufpos, buf);
|
||||
bufpos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xenconscn_pollc(dev_t dev, int on)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Set line parameters.
|
||||
*/
|
||||
int
|
||||
xencons_param(struct tty *tp, struct termios *t)
|
||||
{
|
||||
|
||||
tp->t_ispeed = t->c_ispeed;
|
||||
tp->t_ospeed = t->c_ospeed;
|
||||
tp->t_cflag = t->c_cflag;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,600 @@
|
||||
/* $NetBSD: xenkbc.c,v 1.3.2.1 2004/05/22 15:57:43 he Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2004 Christian Limpach.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Christian Limpach.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004 Ben Harris.
|
||||
* Copyright (c) 1998
|
||||
* Matthias Drochner. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: xenkbc.c,v 1.3.2.1 2004/05/22 15:57:43 he Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <dev/pckbport/pckbportvar.h>
|
||||
#include <dev/ic/i8042reg.h>
|
||||
|
||||
#include <machine/intr.h>
|
||||
|
||||
#include <machine/xenkbcvar.h>
|
||||
#include <machine/xen.h>
|
||||
#include <machine/hypervisor.h>
|
||||
#include <machine/hypervisor-ifs/kbd.h>
|
||||
#include <machine/evtchn.h>
|
||||
|
||||
#define KBC_DELAY DELAY(1000)
|
||||
#define KBC_TIMEOUT 250
|
||||
|
||||
#define XENKBC_NSLOTS 2
|
||||
|
||||
/* data per slave device */
|
||||
struct xenkbc_slotdata {
|
||||
int xsd_polling; /* don't process data in interrupt handler */
|
||||
int xsd_poll_data; /* data read from inr handler if polling */
|
||||
int xsd_poll_stat; /* status read from inr handler if polling */
|
||||
#if NRND > 0
|
||||
rndsource_element_t xsd_rnd_source;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct xenkbc_internal {
|
||||
struct xenkbc_softc *xi_sc;
|
||||
struct pckbport_tag *xi_pt;
|
||||
struct xenkbc_slotdata *xi_slotdata[XENKBC_NSLOTS];
|
||||
int xi_flags;
|
||||
int xi_data;
|
||||
int xi_8042cmdbyte;
|
||||
};
|
||||
|
||||
#define XI_CONSOLE_FLAG 0x01
|
||||
#define XI_HASAUX_FLAG 0x02
|
||||
|
||||
#define XI_CONSOLE(xi) ((xi)->xi_flags & XI_CONSOLE_FLAG)
|
||||
#define XI_HASAUX(xi) ((xi)->xi_flags & XI_HASAUX_FLAG)
|
||||
|
||||
#define XI_SETCONSOLE(xi,on) \
|
||||
((on) ? ((xi)->xi_flags |= XI_CONSOLE_FLAG) : \
|
||||
((xi)->xi_flags &= ~XI_CONSOLE_FLAG))
|
||||
#define XI_SETHASAUX(xi,on) \
|
||||
((on) ? ((xi)->xi_flags |= XI_HASAUX_FLAG) : \
|
||||
((xi)->xi_flags &= ~XI_HASAUX_FLAG))
|
||||
|
||||
static int xenkbc_match(struct device *, struct cfdata *, void *);
|
||||
static void xenkbc_attach(struct device *, struct device *, void *);
|
||||
|
||||
static int xenkbc_xt_translation(void *, pckbport_slot_t, int);
|
||||
static void xenkbc_init_slotdata(struct xenkbc_slotdata *);
|
||||
|
||||
static int xenkbc_get8042cmd (struct xenkbc_internal *);
|
||||
static int xenkbc_put8042cmd (struct xenkbc_internal *);
|
||||
static int xenkbc_send_devcmd(void *, pckbport_slot_t, u_char);
|
||||
static int xenkbc_send_cmd(void *, u_char);
|
||||
static int xenkbc_send_data(void *, u_char);
|
||||
static int xenkbc_poll_data1(void *, pckbport_slot_t);
|
||||
|
||||
static void xenkbc_slot_enable(void *, pckbport_slot_t, int);
|
||||
static void xenkbc_intr_establish(void *, pckbport_slot_t);
|
||||
static void xenkbc_set_poll(void *, pckbport_slot_t, int);
|
||||
|
||||
static int xenkbc_intr(void *);
|
||||
|
||||
CFATTACH_DECL(xenkbc, sizeof(struct xenkbc_softc),
|
||||
xenkbc_match, xenkbc_attach, NULL, NULL);
|
||||
|
||||
static struct pckbport_accessops const xenkbc_ops = {
|
||||
xenkbc_xt_translation,
|
||||
xenkbc_send_devcmd,
|
||||
xenkbc_poll_data1,
|
||||
xenkbc_slot_enable,
|
||||
xenkbc_intr_establish,
|
||||
xenkbc_set_poll
|
||||
};
|
||||
|
||||
static struct xenkbc_internal xenkbc_consdata;
|
||||
static struct xenkbc_slotdata xenkbc_cons_slotdata;
|
||||
|
||||
/* #define XENKBCDEBUG */
|
||||
#ifdef XENKBCDEBUG
|
||||
#define DPRINTF(x) printf x
|
||||
#else
|
||||
#define DPRINTF(x)
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
xenkbc_getstatus(struct xenkbc_internal *xi)
|
||||
{
|
||||
long res;
|
||||
|
||||
res = HYPERVISOR_kbd_op(KBD_OP_READ, 0);
|
||||
if (res < 0) {
|
||||
xi->xi_data = 0;
|
||||
return 0;
|
||||
}
|
||||
xi->xi_data = KBD_CODE_SCANCODE(res);
|
||||
return KBD_CODE_STATUS(res);
|
||||
}
|
||||
|
||||
static int
|
||||
xenkbc_wait_output(struct xenkbc_internal *xi)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = KBC_TIMEOUT; i; i--) {
|
||||
if ((xenkbc_getstatus(xi) & KBS_IBF) == 0)
|
||||
return (1);
|
||||
KBC_DELAY;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
xenkbc_match(struct device *parent, struct cfdata *cf, void *aux)
|
||||
{
|
||||
struct xenkbc_attach_args *xa = aux;
|
||||
|
||||
if ((xen_start_info.flags & SIF_PRIVILEGED) == 0)
|
||||
return 0;
|
||||
|
||||
if (strcmp(xa->xa_device, "xenkbc"))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
xenkbc_attach_slot(struct xenkbc_softc *xs, pckbport_slot_t slot)
|
||||
{
|
||||
struct xenkbc_internal *xi = xs->sc_xi;
|
||||
struct device *child;
|
||||
int alloced = 0;
|
||||
|
||||
if (xi->xi_slotdata[slot] == NULL) {
|
||||
xi->xi_slotdata[slot] = malloc(sizeof(struct xenkbc_slotdata),
|
||||
M_DEVBUF, M_NOWAIT);
|
||||
if (xi->xi_slotdata[slot] == NULL) {
|
||||
printf("%s: no memory\n", xs->sc_dev.dv_xname);
|
||||
return 0;
|
||||
}
|
||||
xenkbc_init_slotdata(xi->xi_slotdata[slot]);
|
||||
alloced++;
|
||||
}
|
||||
|
||||
child = pckbport_attach_slot(&xs->sc_dev, xi->xi_pt, slot);
|
||||
|
||||
if (child == NULL && alloced) {
|
||||
free(xi->xi_slotdata[slot], M_DEVBUF);
|
||||
xi->xi_slotdata[slot] = NULL;
|
||||
}
|
||||
|
||||
#if NRND > 0
|
||||
if (child != NULL && xi->xi_slotdata[slot] != NULL)
|
||||
rnd_attach_source(&xi->xi_slotdata[slot]->xsd_rnd_source,
|
||||
child->dv_xname, RND_TYPE_TTY, 0);
|
||||
#endif
|
||||
|
||||
return child != NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
xenkbc_attach(struct device *parent, struct device *self, void *aux)
|
||||
{
|
||||
/* struct xenkbc_attach_args *xa = aux; */
|
||||
struct xenkbc_softc *xs = (struct xenkbc_softc *)self;
|
||||
struct xenkbc_internal *xi;
|
||||
int res;
|
||||
u_char cmdbits = 0;
|
||||
|
||||
if (XI_CONSOLE(&xenkbc_consdata))
|
||||
xi = &xenkbc_consdata;
|
||||
else {
|
||||
xi = malloc(sizeof(struct xenkbc_internal), M_DEVBUF,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (xi == NULL) {
|
||||
aprint_error(": no memory\n");
|
||||
return;
|
||||
}
|
||||
xi->xi_8042cmdbyte = KC8_CPU;
|
||||
}
|
||||
|
||||
aprint_normal(": Xen Keyboard/Mouse Device\n");
|
||||
|
||||
xs->sc_xi = xi;
|
||||
xi->xi_sc = xs;
|
||||
|
||||
event_set_handler(_EVENT_PS2, &xenkbc_intr, xi, IPL_TTY);
|
||||
hypervisor_enable_event(_EVENT_PS2);
|
||||
|
||||
xi->xi_pt = pckbport_attach(xi, &xenkbc_ops);
|
||||
|
||||
/* flush */
|
||||
xenkbc_poll_data1(xi, PCKBPORT_KBD_SLOT);
|
||||
|
||||
/* set initial cmd byte */
|
||||
if (!xenkbc_put8042cmd(xi)) {
|
||||
printf("kbc: cmd word write error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (xenkbc_attach_slot(xs, PCKBPORT_KBD_SLOT))
|
||||
cmdbits |= KC8_KENABLE;
|
||||
|
||||
/*
|
||||
* Check aux port ok.
|
||||
*/
|
||||
if (!xenkbc_send_cmd(xi, KBC_AUXECHO)) {
|
||||
printf("kbc: aux echo error 1\n");
|
||||
goto nomouse;
|
||||
}
|
||||
if (!xenkbc_wait_output(xi)) {
|
||||
printf("kbc: aux echo error 2\n");
|
||||
goto nomouse;
|
||||
}
|
||||
XI_SETHASAUX(xi, 1);
|
||||
xenkbc_send_data(xi, 0x5a); /* a random value */
|
||||
res = xenkbc_poll_data1(xi, PCKBPORT_AUX_SLOT);
|
||||
if (res != -1) {
|
||||
/*
|
||||
* In most cases, the 0x5a gets echoed.
|
||||
* Some older controllers (Gateway 2000 circa 1993)
|
||||
* return 0xfe here.
|
||||
* We are satisfied if there is anything in the
|
||||
* aux output buffer.
|
||||
*/
|
||||
if (xenkbc_attach_slot(xs, PCKBPORT_AUX_SLOT))
|
||||
cmdbits |= KC8_MENABLE;
|
||||
} else {
|
||||
#ifdef XENKBCDEBUG
|
||||
printf("kbc: aux echo test failed\n");
|
||||
#endif
|
||||
XI_SETHASAUX(xi, 0);
|
||||
}
|
||||
|
||||
nomouse:
|
||||
/* enable needed interrupts */
|
||||
xi->xi_8042cmdbyte |= cmdbits;
|
||||
if (!xenkbc_put8042cmd(xi))
|
||||
printf("kbc: cmd word write error\n");
|
||||
}
|
||||
|
||||
static void
|
||||
xenkbc_init_slotdata(struct xenkbc_slotdata *xsd)
|
||||
{
|
||||
|
||||
xsd->xsd_polling = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current command byte.
|
||||
*/
|
||||
static int
|
||||
xenkbc_get8042cmd(struct xenkbc_internal *xi)
|
||||
{
|
||||
int data;
|
||||
|
||||
if (!xenkbc_send_cmd(xi, K_RDCMDBYTE))
|
||||
return 0;
|
||||
data = xenkbc_poll_data1(xi, PCKBPORT_KBD_SLOT);
|
||||
if (data == -1)
|
||||
return 0;
|
||||
xi->xi_8042cmdbyte = data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass command byte to keyboard controller (8042).
|
||||
*/
|
||||
static int
|
||||
xenkbc_put8042cmd(struct xenkbc_internal *xi)
|
||||
{
|
||||
|
||||
if (!xenkbc_send_cmd(xi, K_LDCMDBYTE))
|
||||
return 0;
|
||||
if (!xenkbc_wait_output(xi))
|
||||
return 0;
|
||||
return xenkbc_send_data(xi, xi->xi_8042cmdbyte);
|
||||
}
|
||||
|
||||
static int
|
||||
xenkbc_send_devcmd(void *cookie, pckbport_slot_t slot, u_char devcmd)
|
||||
{
|
||||
|
||||
DPRINTF(("send_devcmd %x\n", devcmd));
|
||||
|
||||
if (slot == PCKBPORT_AUX_SLOT) {
|
||||
if (!xenkbc_send_cmd(cookie, KBC_AUXWRITE)) {
|
||||
DPRINTF(("xenkbc_send_devcmd: KBC_AUXWRITE failed\n"));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!xenkbc_wait_output(cookie)) {
|
||||
DPRINTF(("xenkbc_send_devcmd: wait_output failed\n"));
|
||||
return 0;
|
||||
}
|
||||
return xenkbc_send_data(cookie, devcmd);
|
||||
}
|
||||
|
||||
static int
|
||||
xenkbc_send_cmd(void *cookie, u_char cmd)
|
||||
{
|
||||
struct xenkbc_internal *xi = cookie;
|
||||
|
||||
DPRINTF(("send_cmd %x\n", cmd));
|
||||
xenkbc_wait_output(xi);
|
||||
return !HYPERVISOR_kbd_op(KBD_OP_WRITECOMMAND, cmd);
|
||||
}
|
||||
|
||||
static int
|
||||
xenkbc_send_data(void *cookie, u_char output)
|
||||
{
|
||||
struct xenkbc_internal *xi = cookie;
|
||||
|
||||
DPRINTF(("send_data %x\n", output));
|
||||
xenkbc_wait_output(xi);
|
||||
return !HYPERVISOR_kbd_op(KBD_OP_WRITEOUTPUT, output);
|
||||
}
|
||||
|
||||
static int
|
||||
xenkbc_poll_data1(void *cookie, pckbport_slot_t slot)
|
||||
{
|
||||
struct xenkbc_internal *xi = cookie;
|
||||
struct xenkbc_slotdata *xsd = xi->xi_slotdata[slot];
|
||||
int s;
|
||||
u_char stat, c;
|
||||
int i = 1000;
|
||||
|
||||
s = splhigh();
|
||||
|
||||
if (xsd && xsd->xsd_polling && xsd->xsd_poll_data != -1 &&
|
||||
xsd->xsd_poll_stat != -1) {
|
||||
stat = xsd->xsd_poll_stat;
|
||||
c = xsd->xsd_poll_data;
|
||||
xsd->xsd_poll_data = -1;
|
||||
xsd->xsd_poll_stat = -1;
|
||||
goto process;
|
||||
}
|
||||
|
||||
DELAY(10);
|
||||
for (; i; i--) {
|
||||
stat = xenkbc_getstatus(xi);
|
||||
if (stat & KBS_DIB) {
|
||||
c = xi->xi_data;
|
||||
DELAY(10);
|
||||
process:
|
||||
if (XI_HASAUX(xi) && (stat & 0x20)) { /* aux data */
|
||||
if (slot != PCKBPORT_AUX_SLOT) {
|
||||
#ifdef XENKBCDEBUG
|
||||
printf("lost aux 0x%x\n", c);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (slot == PCKBPORT_AUX_SLOT) {
|
||||
#ifdef XENKBCDEBUG
|
||||
printf("lost kbd 0x%x\n", c);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
}
|
||||
splx(s);
|
||||
DPRINTF(("poll -> %x stat %x\n", c, stat));
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
DPRINTF(("poll failed -> -1\n"));
|
||||
splx(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* switch scancode translation on / off
|
||||
* return nonzero on success
|
||||
*/
|
||||
static int
|
||||
xenkbc_xt_translation(void *cookie, pckbport_slot_t slot, int on)
|
||||
{
|
||||
struct xenkbc_internal *xi = cookie;
|
||||
int ison;
|
||||
|
||||
if (slot != PCKBPORT_KBD_SLOT) {
|
||||
/* translation only for kbd slot */
|
||||
if (on)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
ison = xi->xi_8042cmdbyte & KC8_TRANS;
|
||||
if ((on && ison) || (!on && !ison))
|
||||
return 1;
|
||||
|
||||
xi->xi_8042cmdbyte ^= KC8_TRANS;
|
||||
if (!xenkbc_put8042cmd(xi))
|
||||
return 0;
|
||||
|
||||
/* read back to be sure */
|
||||
if (!xenkbc_get8042cmd(xi))
|
||||
return 0;
|
||||
|
||||
ison = xi->xi_8042cmdbyte & KC8_TRANS;
|
||||
if ((on && ison) || (!on && !ison))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct xenkbc_portcmd {
|
||||
u_char cmd_en, cmd_dis;
|
||||
} xenkbc_portcmd[2] = {
|
||||
{
|
||||
KBC_KBDENABLE, KBC_KBDDISABLE,
|
||||
}, {
|
||||
KBC_AUXENABLE, KBC_AUXDISABLE,
|
||||
}
|
||||
};
|
||||
|
||||
static void
|
||||
xenkbc_slot_enable(void *cookie, pckbport_slot_t slot, int on)
|
||||
{
|
||||
struct xenkbc_internal *xi = cookie;
|
||||
const struct xenkbc_portcmd *cmd;
|
||||
|
||||
cmd = &xenkbc_portcmd[slot];
|
||||
|
||||
DPRINTF(("slot enable %d -> %d\n", slot, on));
|
||||
xenkbc_send_cmd(xi, on ? cmd->cmd_en : cmd->cmd_dis);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
xenkbc_intr_establish(void *cookie, pckbport_slot_t slot)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
xenkbc_set_poll(void *cookie, pckbport_slot_t slot, int on)
|
||||
{
|
||||
struct xenkbc_internal *xi = cookie;
|
||||
|
||||
DPRINTF(("xenkbc_set_poll %d -> %d\n", slot, on));
|
||||
|
||||
xi->xi_slotdata[slot]->xsd_polling = on;
|
||||
|
||||
if (on) {
|
||||
xi->xi_slotdata[slot]->xsd_poll_data = -1;
|
||||
xi->xi_slotdata[slot]->xsd_poll_stat = -1;
|
||||
} else {
|
||||
int s;
|
||||
|
||||
/*
|
||||
* If disabling polling on a device that's been configured,
|
||||
* make sure there are no bytes left in the FIFO, holding up
|
||||
* the interrupt line. Otherwise we won't get any further
|
||||
* interrupts.
|
||||
*/
|
||||
s = spltty();
|
||||
xenkbc_intr(xi);
|
||||
splx(s);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
xenkbc_intr(void *self)
|
||||
{
|
||||
struct xenkbc_internal *xi = self;
|
||||
u_char stat;
|
||||
pckbport_slot_t slot;
|
||||
struct xenkbc_slotdata *xsd;
|
||||
int served = 0;
|
||||
|
||||
for (;;) {
|
||||
stat = xenkbc_getstatus(xi);
|
||||
if (!(stat & KBS_DIB))
|
||||
break;
|
||||
|
||||
served = 1;
|
||||
|
||||
slot = (XI_HASAUX(xi) && (stat & 0x20)) ?
|
||||
PCKBPORT_AUX_SLOT : PCKBPORT_KBD_SLOT;
|
||||
xsd = xi->xi_slotdata[slot];
|
||||
|
||||
if (xsd == NULL)
|
||||
continue;
|
||||
|
||||
#if NRND > 0
|
||||
rnd_add_uint32(&xsd->xsd_rnd_source,
|
||||
(stat << 8) | xi->xi_data);
|
||||
#endif
|
||||
|
||||
if (xsd->xsd_polling) {
|
||||
xsd->xsd_poll_data = xi->xi_data;
|
||||
xsd->xsd_poll_stat = stat;
|
||||
break; /* xenkbc_poll_data() will get it */
|
||||
}
|
||||
|
||||
pckbportintr(xi->xi_pt, slot, xi->xi_data);
|
||||
}
|
||||
|
||||
return served;
|
||||
}
|
||||
|
||||
int
|
||||
xenkbc_cnattach(pckbport_slot_t slot)
|
||||
{
|
||||
struct xenkbc_internal *xi = &xenkbc_consdata;
|
||||
int ret;
|
||||
|
||||
/* flush */
|
||||
(void) xenkbc_poll_data1(xi, PCKBPORT_KBD_SLOT);
|
||||
|
||||
/* init cmd byte, enable ports */
|
||||
xenkbc_consdata.xi_8042cmdbyte = KC8_CPU;
|
||||
if (!xenkbc_put8042cmd(xi)) {
|
||||
printf("kbc: cmd word write error\n");
|
||||
return EIO;
|
||||
}
|
||||
|
||||
ret = pckbport_cnattach(xi, &xenkbc_ops, slot);
|
||||
|
||||
xi->xi_slotdata[slot] = &xenkbc_cons_slotdata;
|
||||
xenkbc_init_slotdata(xi->xi_slotdata[slot]);
|
||||
XI_SETCONSOLE(xi, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
# $NetBSD: files.nfs,v 1.3 2004/03/11 21:48:43 cl Exp $
|
||||
|
||||
deffs fs_nfs.h NFS
|
||||
|
||||
defflag opt_nfs_boot.h NFS_BOOT_BOOTP NFS_BOOT_BOOTPARAM NFS_BOOT_DHCP
|
||||
NFS_BOOT_GATEWAY NFS_BOOT_TCP
|
||||
NFS_BOOT_BOOTSTATIC
|
||||
|
||||
defparam opt_nfs_boot.h NFS_BOOT_BOOTP_REQFILE NFS_BOOT_OPTIONS
|
||||
NFS_BOOT_RWSIZE
|
||||
NFS_BOOTSTATIC_MYIP NFS_BOOTSTATIC_GWIP
|
||||
NFS_BOOTSTATIC_MASK NFS_BOOTSTATIC_SERVADDR
|
||||
NFS_BOOTSTATIC_SERVER
|
||||
|
||||
defflag opt_nfs.h NFS_V2_ONLY
|
||||
|
||||
defflag NFSSERVER
|
||||
|
||||
file nfs/krpc_subr.c nfs
|
||||
file nfs/nfs_bio.c nfs
|
||||
file nfs/nfs_boot.c nfs
|
||||
file nfs/nfs_bootdhcp.c nfs & (nfs_boot_bootp | nfs_boot_dhcp)
|
||||
file nfs/nfs_bootparam.c nfs & nfs_boot_bootparam
|
||||
file nfs/nfs_bootstatic.c nfs & nfs_boot_bootstatic
|
||||
file nfs/nfs_kq.c nfs
|
||||
file nfs/nfs_node.c nfs
|
||||
file nfs/nfs_nqlease.c nfsserver | nfs
|
||||
file nfs/nfs_serv.c nfsserver
|
||||
file nfs/nfs_socket.c nfsserver | nfs
|
||||
file nfs/nfs_srvcache.c nfsserver
|
||||
file nfs/nfs_subs.c nfsserver | nfs
|
||||
file nfs/nfs_syscalls.c nfsserver | nfs
|
||||
file nfs/nfs_vfsops.c nfs
|
||||
file nfs/nfs_vnops.c nfs
|
||||