diff options
| author | cvs2svn <cvs2svn@FreeBSD.org> | 2007-12-22 06:32:46 +0000 |
|---|---|---|
| committer | cvs2svn <cvs2svn@FreeBSD.org> | 2007-12-22 06:32:46 +0000 |
| commit | ca0202a548c669f45a9e0a63fce138303da6fc65 (patch) | |
| tree | d2e3b3331009b65497a28406543d489372f03151 /sys/powerpc | |
| parent | 6b0086231aa03c59acb964c0c94a023019f2bd5b (diff) | |
| parent | 0f36dbfe3db4f983de562e87103d20899cbfb655 (diff) | |
Notes
Diffstat (limited to 'sys/powerpc')
145 files changed, 26404 insertions, 0 deletions
diff --git a/sys/powerpc/compile/.cvsignore b/sys/powerpc/compile/.cvsignore new file mode 100644 index 000000000000..232298edb15f --- /dev/null +++ b/sys/powerpc/compile/.cvsignore @@ -0,0 +1 @@ +[A-Za-z0-9]* diff --git a/sys/powerpc/conf/.cvsignore b/sys/powerpc/conf/.cvsignore new file mode 100644 index 000000000000..232298edb15f --- /dev/null +++ b/sys/powerpc/conf/.cvsignore @@ -0,0 +1 @@ +[A-Za-z0-9]* diff --git a/sys/powerpc/conf/DEFAULTS b/sys/powerpc/conf/DEFAULTS new file mode 100644 index 000000000000..7204e8b23279 --- /dev/null +++ b/sys/powerpc/conf/DEFAULTS @@ -0,0 +1,19 @@ +# +# DEFAULTS -- Default kernel configuration file for FreeBSD/powerpc +# +# $FreeBSD$ + +machine powerpc + +# Pseudo devices. +device mem # Memory and kernel memory devices + +# UART chips on this platform +device uart_ns8250 +device uart_z8530 + +options GEOM_PART_APM +options GEOM_PART_MBR + +# KSE support went from being default to a kernel option +options KSE diff --git a/sys/powerpc/conf/GENERIC b/sys/powerpc/conf/GENERIC new file mode 100644 index 000000000000..ddeec38a6805 --- /dev/null +++ b/sys/powerpc/conf/GENERIC @@ -0,0 +1,147 @@ +# +# GENERIC -- Generic kernel configuration file for FreeBSD/powerpc +# +# For more information on this file, please read the handbook section on +# Kernel Configuration Files: +# +# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html +# +# The handbook is also available locally in /usr/share/doc/handbook +# if you've installed the doc distribution, otherwise always see the +# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the +# latest information. +# +# An exhaustive list of options and more detailed explanations of the +# device lines is also present in the ../../conf/NOTES and NOTES files. +# If you are in doubt as to the purpose or necessity of a line, check first +# in NOTES. +# +# $FreeBSD$ + +cpu OEA +ident GENERIC + +#To statically compile in device wiring instead of /boot/device.hints +#hints "GENERIC.hints" + +makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols + +# Platform support +options POWERMAC #NewWorld Apple PowerMacs +options PSIM #GDB PSIM ppc simulator + +options SCHED_4BSD #4BSD scheduler +options INET #InterNETworking +options INET6 #IPv6 communications protocols +options SCTP #Stream Control Transmission Protocol +options FFS #Berkeley Fast Filesystem +options SOFTUPDATES #Enable FFS soft updates support +options UFS_ACL #Support for access control lists +options UFS_DIRHASH #Improve performance on big directories +options UFS_GJOURNAL #Enable gjournal-based UFS journaling +options MD_ROOT #MD is a potential root device +options NFSCLIENT #Network Filesystem Client +options NFSSERVER #Network Filesystem Server +options NFS_ROOT #NFS usable as root device +options MSDOSFS #MSDOS Filesystem +options CD9660 #ISO 9660 Filesystem +options PROCFS #Process filesystem (requires PSEUDOFS) +options PSEUDOFS #Pseudo-filesystem framework +options GEOM_PART_GPT #GUID Partition Tables. +options GEOM_LABEL #Provides labelization +options COMPAT_43TTY #BSD 4.3 TTY compat [KEEP THIS!] +options COMPAT_FREEBSD4 #Keep this for a while +options COMPAT_FREEBSD5 #Compatible with FreeBSD5 +options COMPAT_FREEBSD6 #Compatible with FreeBSD6 +options SCSI_DELAY=5000 #Delay (in ms) before probing SCSI +options KTRACE #ktrace(1) syscall trace support +options SYSVSHM #SYSV-style shared memory +options SYSVMSG #SYSV-style message queues +options SYSVSEM #SYSV-style semaphores +options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions +options AUDIT # Security event auditing + +# To make an SMP kernel, the next line is needed +#options SMP # Symmetric MultiProcessor Kernel + +# Standard busses +device pci + +# ATA and ATAPI devices +device ata +device atadisk # ATA disk drives +device atapicd # ATAPI CDROM drives +#device atapifd # ATAPI floppy drives +#device atapist # ATAPI tape drives + +# SCSI peripherals +device scbus # SCSI bus (required for SCSI) +device da # Direct Access (disks) +device sa # Sequential Access (tape etc) +device cd # CD +device pass # Passthrough device (direct SCSI access) + +# syscons is the default console driver, resembling an SCO console +device sc +device kbdmux +options SC_OFWFB # OFW frame buffer +options SC_DFLT_FONT # compile font in +makeoptions SC_DFLT_FONT=cp437 + +# Serial (COM) ports +device scc +device uart + +# PCI Ethernet NICs that use the common MII bus controller code. +device miibus # MII bus support +device bge # Broadcom BCM570xx Gigabit Ethernet +device gem # Sun GEM/Sun ERI/Apple GMAC +device dc # DEC/Intel 21143 and various workalikes +device fxp # Intel EtherExpress PRO/100B (82557, 82558) + +# Pseudo devices. +device loop # Network loopback +device random # Entropy device +device ether # Ethernet support +device sl # Kernel SLIP +device ppp # Kernel PPP +device tun # Packet tunnel. +device pty # Pseudo-ttys (telnet etc) +device md # Memory "disks" +device ofwd # Open Firmware disks +device gif # IPv6 and IPv4 tunneling +device faith # IPv6-to-IPv4 relaying/(translation) + +# The `bpf' device enables the Berkeley Packet Filter. +# Be aware of the administrative consequences of enabling this! +# Note that 'bpf' is required for DHCP. +device bpf #Berkeley packet filter + +# USB support +device uhci # UHCI PCI->USB interface +device ohci # OHCI PCI->USB interface +device ehci # EHCI PCI->USB interface +device usb # USB Bus (required) +device ugen # Generic +device uhid # "Human Interface Devices" +device ukbd # Keyboard +options KBD_INSTALL_CDEV # install a CDEV entry in /dev +device ulpt # Printer +device umass # Disks/Mass storage - Requires scbus and da0 +device ums # Mouse +device urio # Diamond Rio 500 MP3 player +device uscanner # Scanners +# USB Ethernet +device aue # ADMtek USB Ethernet +device axe # ASIX Electronics USB Ethernet +device cdce # Generic USB over Ethernet +device cue # CATC USB Ethernet +device kue # Kawasaki LSI USB Ethernet + +# FireWire support +device firewire # FireWire bus code +device sbp # SCSI over FireWire (Requires scbus and da) +device fwe # Ethernet over FireWire (non-standard!) + +# Misc +device powermac_nvram # Open Firmware configuration NVRAM diff --git a/sys/powerpc/conf/GENERIC.hints b/sys/powerpc/conf/GENERIC.hints new file mode 100644 index 000000000000..e8c0da7a1d7e --- /dev/null +++ b/sys/powerpc/conf/GENERIC.hints @@ -0,0 +1 @@ +# $FreeBSD$ diff --git a/sys/powerpc/conf/MAC b/sys/powerpc/conf/MAC new file mode 100644 index 000000000000..862638397da7 --- /dev/null +++ b/sys/powerpc/conf/MAC @@ -0,0 +1,28 @@ +# MAC -- Generic kernel configuration file for FreeBSD/powerpc MAC +# +# The Mandatory Access Control, or MAC, framework allows administrators to +# finely control system security by providing for a loadable security pol- +# icy architecture. +# +# For more information see: +# +# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/mac.html +# +# $FreeBSD$ + +include GENERIC +ident MAC + +options MAC + +#options MAC_BIBA # BIBA data integrity policy +#options MAC_BSDEXTENDED # File system firewall policy +#options MAC_IFOFF # Network interface silencing policy +#options MAC_LOMAC # Low-watermark data integrity policy +#options MAC_MLS # Multi-level confidentiality policy +#options MAC_NONE # NULL policy +#options MAC_PARTITION # Process partition policy +#options MAC_PORTACL # Network port access control policy +#options MAC_SEEOTHERUIDS # UID visibility policy +#options MAC_STUB # Stub policy +#options MAC_TEST # Testing policy for the MAC framework diff --git a/sys/powerpc/conf/Makefile b/sys/powerpc/conf/Makefile new file mode 100644 index 000000000000..2c006e9c2c80 --- /dev/null +++ b/sys/powerpc/conf/Makefile @@ -0,0 +1,3 @@ +# $FreeBSD$ + +.include "${.CURDIR}/../../conf/makeLINT.mk" diff --git a/sys/powerpc/conf/NOTES b/sys/powerpc/conf/NOTES new file mode 100644 index 000000000000..176e66134153 --- /dev/null +++ b/sys/powerpc/conf/NOTES @@ -0,0 +1,64 @@ +# $FreeBSD$ +# +# This file contains machine dependent kernel configuration notes. For +# machine independent notes, look in /sys/conf/NOTES. + + + +##################################################################### +# CPU OPTIONS + +# +# You must specify at least one CPU (the one you intend to run on). +cpu OEA + +options POWERMAC #NewWorld Apple PowerMacs +options PSIM #GDB PSIM ppc simulator + +options SC_OFWFB # OFW frame buffer + +# Standard busses +device pci + +device ofwd # Open Firmware disks + + +##################################################################### +# Devices we don't want to deal with + +nodevice fdc +nodevice ppc +nodevice splash +# when splash works enable *_saver +nodevice blank_saver +nodevice daemon_saver +nodevice dragon_saver +nodevice fade_saver +nodevice fire_saver +nodevice green_saver +nodevice logo_saver +nodevice rain_saver +nodevice snake_saver +nodevice star_saver +nodevice warp_saver +nodevice daemon_saver +nodevice star_saver +nodevice snake_saver +# isa +nodevice pcii +nodevice tnt4882 +# wants gdb_cur +nodevice dcons +nodevice dcons_crom + + +##################################################################### +# Options we don't want to deal with + +nooption SMP +nooption ADAPTIVE_SX +nooption GDB +nooption PPC_DEBUG +nooption PPC_PROBE_CHIPSET +nooption SC_NO_MODE_CHANGE +nooption UKBD_DFLT_KEYMAP diff --git a/sys/powerpc/include/_bus.h b/sys/powerpc/include/_bus.h new file mode 100644 index 000000000000..5561ce734127 --- /dev/null +++ b/sys/powerpc/include/_bus.h @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2005 M. Warner Losh. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef POWERPC_INCLUDE__BUS_H +#define POWERPC_INCLUDE__BUS_H + +/* + * Bus address and size types + */ +typedef u_int32_t bus_addr_t; +typedef u_int32_t bus_size_t; + +/* + * Access methods for bus resources and address space. + */ +typedef u_int32_t bus_space_tag_t; +typedef u_int32_t bus_space_handle_t; + +#endif /* POWERPC_INCLUDE__BUS_H */ diff --git a/sys/powerpc/include/_inttypes.h b/sys/powerpc/include/_inttypes.h new file mode 100644 index 000000000000..7da589d8a771 --- /dev/null +++ b/sys/powerpc/include/_inttypes.h @@ -0,0 +1,220 @@ +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Klaus Klein. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * From: $NetBSD: int_fmtio.h,v 1.2 2001/04/26 16:25:21 kleink Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_INTTYPES_H_ +#define _MACHINE_INTTYPES_H_ + +/* + * Macros for format specifiers. + */ + +/* fprintf(3) macros for signed integers. */ + +#define PRId8 "d" /* int8_t */ +#define PRId16 "d" /* int16_t */ +#define PRId32 "d" /* int32_t */ +#define PRId64 "lld" /* int64_t */ +#define PRIdLEAST8 "d" /* int_least8_t */ +#define PRIdLEAST16 "d" /* int_least16_t */ +#define PRIdLEAST32 "d" /* int_least32_t */ +#define PRIdLEAST64 "lld" /* int_least64_t */ +#define PRIdFAST8 "d" /* int_fast8_t */ +#define PRIdFAST16 "d" /* int_fast16_t */ +#define PRIdFAST32 "d" /* int_fast32_t */ +#define PRIdFAST64 "lld" /* int_fast64_t */ +#define PRIdMAX "jd" /* intmax_t */ +#define PRIdPTR "d" /* intptr_t */ + +#define PRIi8 "i" /* int8_t */ +#define PRIi16 "i" /* int16_t */ +#define PRIi32 "i" /* int32_t */ +#define PRIi64 "lli" /* int64_t */ +#define PRIiLEAST8 "i" /* int_least8_t */ +#define PRIiLEAST16 "i" /* int_least16_t */ +#define PRIiLEAST32 "i" /* int_least32_t */ +#define PRIiLEAST64 "lli" /* int_least64_t */ +#define PRIiFAST8 "i" /* int_fast8_t */ +#define PRIiFAST16 "i" /* int_fast16_t */ +#define PRIiFAST32 "i" /* int_fast32_t */ +#define PRIiFAST64 "lli" /* int_fast64_t */ +#define PRIiMAX "ji" /* intmax_t */ +#define PRIiPTR "i" /* intptr_t */ + +/* fprintf(3) macros for unsigned integers. */ + +#define PRIo8 "o" /* uint8_t */ +#define PRIo16 "o" /* uint16_t */ +#define PRIo32 "o" /* uint32_t */ +#define PRIo64 "llo" /* uint64_t */ +#define PRIoLEAST8 "o" /* uint_least8_t */ +#define PRIoLEAST16 "o" /* uint_least16_t */ +#define PRIoLEAST32 "o" /* uint_least32_t */ +#define PRIoLEAST64 "llo" /* uint_least64_t */ +#define PRIoFAST8 "o" /* uint_fast8_t */ +#define PRIoFAST16 "o" /* uint_fast16_t */ +#define PRIoFAST32 "o" /* uint_fast32_t */ +#define PRIoFAST64 "llo" /* uint_fast64_t */ +#define PRIoMAX "jo" /* uintmax_t */ +#define PRIoPTR "o" /* uintptr_t */ + +#define PRIu8 "u" /* uint8_t */ +#define PRIu16 "u" /* uint16_t */ +#define PRIu32 "u" /* uint32_t */ +#define PRIu64 "llu" /* uint64_t */ +#define PRIuLEAST8 "u" /* uint_least8_t */ +#define PRIuLEAST16 "u" /* uint_least16_t */ +#define PRIuLEAST32 "u" /* uint_least32_t */ +#define PRIuLEAST64 "llu" /* uint_least64_t */ +#define PRIuFAST8 "u" /* uint_fast8_t */ +#define PRIuFAST16 "u" /* uint_fast16_t */ +#define PRIuFAST32 "u" /* uint_fast32_t */ +#define PRIuFAST64 "llu" /* uint_fast64_t */ +#define PRIuMAX "ju" /* uintmax_t */ +#define PRIuPTR "u" /* uintptr_t */ + +#define PRIx8 "x" /* uint8_t */ +#define PRIx16 "x" /* uint16_t */ +#define PRIx32 "x" /* uint32_t */ +#define PRIx64 "llx" /* uint64_t */ +#define PRIxLEAST8 "x" /* uint_least8_t */ +#define PRIxLEAST16 "x" /* uint_least16_t */ +#define PRIxLEAST32 "x" /* uint_least32_t */ +#define PRIxLEAST64 "llx" /* uint_least64_t */ +#define PRIxFAST8 "x" /* uint_fast8_t */ +#define PRIxFAST16 "x" /* uint_fast16_t */ +#define PRIxFAST32 "x" /* uint_fast32_t */ +#define PRIxFAST64 "llx" /* uint_fast64_t */ +#define PRIxMAX "jx" /* uintmax_t */ +#define PRIxPTR "x" /* uintptr_t */ + +#define PRIX8 "X" /* uint8_t */ +#define PRIX16 "X" /* uint16_t */ +#define PRIX32 "X" /* uint32_t */ +#define PRIX64 "llX" /* uint64_t */ +#define PRIXLEAST8 "X" /* uint_least8_t */ +#define PRIXLEAST16 "X" /* uint_least16_t */ +#define PRIXLEAST32 "X" /* uint_least32_t */ +#define PRIXLEAST64 "llX" /* uint_least64_t */ +#define PRIXFAST8 "X" /* uint_fast8_t */ +#define PRIXFAST16 "X" /* uint_fast16_t */ +#define PRIXFAST32 "X" /* uint_fast32_t */ +#define PRIXFAST64 "llX" /* uint_fast64_t */ +#define PRIXMAX "jX" /* uintmax_t */ +#define PRIXPTR "X" /* uintptr_t */ + +/* fscanf(3) macros for signed integers. */ + +#define SCNd8 "hhd" /* int8_t */ +#define SCNd16 "hd" /* int16_t */ +#define SCNd32 "d" /* int32_t */ +#define SCNd64 "lld" /* int64_t */ +#define SCNdLEAST8 "hhd" /* int_least8_t */ +#define SCNdLEAST16 "hd" /* int_least16_t */ +#define SCNdLEAST32 "d" /* int_least32_t */ +#define SCNdLEAST64 "lld" /* int_least64_t */ +#define SCNdFAST8 "d" /* int_fast8_t */ +#define SCNdFAST16 "d" /* int_fast16_t */ +#define SCNdFAST32 "d" /* int_fast32_t */ +#define SCNdFAST64 "lld" /* int_fast64_t */ +#define SCNdMAX "jd" /* intmax_t */ +#define SCNdPTR "d" /* intptr_t */ + +#define SCNi8 "hhi" /* int8_t */ +#define SCNi16 "hi" /* int16_t */ +#define SCNi32 "i" /* int32_t */ +#define SCNi64 "lli" /* int64_t */ +#define SCNiLEAST8 "hhi" /* int_least8_t */ +#define SCNiLEAST16 "hi" /* int_least16_t */ +#define SCNiLEAST32 "i" /* int_least32_t */ +#define SCNiLEAST64 "lli" /* int_least64_t */ +#define SCNiFAST8 "i" /* int_fast8_t */ +#define SCNiFAST16 "i" /* int_fast16_t */ +#define SCNiFAST32 "i" /* int_fast32_t */ +#define SCNiFAST64 "lli" /* int_fast64_t */ +#define SCNiMAX "ji" /* intmax_t */ +#define SCNiPTR "i" /* intptr_t */ + +/* fscanf(3) macros for unsigned integers. */ + +#define SCNo8 "hho" /* uint8_t */ +#define SCNo16 "ho" /* uint16_t */ +#define SCNo32 "o" /* uint32_t */ +#define SCNo64 "llo" /* uint64_t */ +#define SCNoLEAST8 "hho" /* uint_least8_t */ +#define SCNoLEAST16 "ho" /* uint_least16_t */ +#define SCNoLEAST32 "o" /* uint_least32_t */ +#define SCNoLEAST64 "llo" /* uint_least64_t */ +#define SCNoFAST8 "o" /* uint_fast8_t */ +#define SCNoFAST16 "o" /* uint_fast16_t */ +#define SCNoFAST32 "o" /* uint_fast32_t */ +#define SCNoFAST64 "llo" /* uint_fast64_t */ +#define SCNoMAX "jo" /* uintmax_t */ +#define SCNoPTR "o" /* uintptr_t */ + +#define SCNu8 "hhu" /* uint8_t */ +#define SCNu16 "hu" /* uint16_t */ +#define SCNu32 "u" /* uint32_t */ +#define SCNu64 "llu" /* uint64_t */ +#define SCNuLEAST8 "hhu" /* uint_least8_t */ +#define SCNuLEAST16 "hu" /* uint_least16_t */ +#define SCNuLEAST32 "u" /* uint_least32_t */ +#define SCNuLEAST64 "llu" /* uint_least64_t */ +#define SCNuFAST8 "u" /* uint_fast8_t */ +#define SCNuFAST16 "u" /* uint_fast16_t */ +#define SCNuFAST32 "u" /* uint_fast32_t */ +#define SCNuFAST64 "llu" /* uint_fast64_t */ +#define SCNuMAX "ju" /* uintmax_t */ +#define SCNuPTR "u" /* uintptr_t */ + +#define SCNx8 "hhx" /* uint8_t */ +#define SCNx16 "hx" /* uint16_t */ +#define SCNx32 "x" /* uint32_t */ +#define SCNx64 "llx" /* uint64_t */ +#define SCNxLEAST8 "hhx" /* uint_least8_t */ +#define SCNxLEAST16 "hx" /* uint_least16_t */ +#define SCNxLEAST32 "x" /* uint_least32_t */ +#define SCNxLEAST64 "llx" /* uint_least64_t */ +#define SCNxFAST8 "x" /* uint_fast8_t */ +#define SCNxFAST16 "x" /* uint_fast16_t */ +#define SCNxFAST32 "x" /* uint_fast32_t */ +#define SCNxFAST64 "llx" /* uint_fast64_t */ +#define SCNxMAX "jx" /* uintmax_t */ +#define SCNxPTR "x" /* uintptr_t */ + +#endif /* !_MACHINE_INTTYPES_H_ */ diff --git a/sys/powerpc/include/_limits.h b/sys/powerpc/include/_limits.h new file mode 100644 index 000000000000..76e73544de64 --- /dev/null +++ b/sys/powerpc/include/_limits.h @@ -0,0 +1,99 @@ +/*- + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)limits.h 8.3 (Berkeley) 1/4/94 + * $FreeBSD$ + */ + +#ifndef _MACHINE__LIMITS_H_ +#define _MACHINE__LIMITS_H_ + +/* + * According to ANSI (section 2.2.4.2), the values below must be usable by + * #if preprocessing directives. Additionally, the expression must have the + * same type as would an expression that is an object of the corresponding + * type converted according to the integral promotions. The subtraction for + * INT_MIN, etc., is so the value is not unsigned; e.g., 0x80000000 is an + * unsigned int for 32-bit two's complement ANSI compilers (section 3.1.3.2). + * These numbers are for the default configuration of gcc. They work for + * some other compilers as well, but this should not be depended on. + */ + +#define __CHAR_BIT 8 /* number of bits in a char */ + +#define __SCHAR_MAX 0x7f /* max value for a signed char */ +#define __SCHAR_MIN (-0x7f - 1) /* min value for a signed char */ + +#define __UCHAR_MAX 0xff /* max value for an unsigned char */ + +#define __USHRT_MAX 0xffff /* max value for an unsigned short */ +#define __SHRT_MAX 0x7fff /* max value for a short */ +#define __SHRT_MIN (-0x7fff - 1) /* min value for a short */ + +#define __UINT_MAX 0xffffffffU /* max value for an unsigned int */ +#define __INT_MAX 0x7fffffff /* max value for an int */ +#define __INT_MIN (-0x7fffffff - 1) /* min value for an int */ + +/* Bad hack for gcc configured to give 64-bit longs. */ +#ifdef _LARGE_LONG +#define __ULONG_MAX 0xffffffffffffffffUL +#define __LONG_MAX 0x7fffffffffffffffL +#define __LONG_MIN (-0x7fffffffffffffffL - 1) +#else +#define __ULONG_MAX 0xffffffffUL /* max value for an unsigned long */ +#define __LONG_MAX 0x7fffffffL /* max value for a long */ +#define __LONG_MIN (-0x7fffffffL - 1) /* min value for a long */ +#endif + +#define __ULLONG_MAX 0xffffffffffffffffULL +#define __LLONG_MAX 0x7fffffffffffffffLL /* max value for a long long */ +#define __LLONG_MIN (-0x7fffffffffffffffLL - 1) /* min for a long long */ + +#define __SSIZE_MAX __INT_MAX /* max value for a ssize_t */ + +#define __SIZE_T_MAX __UINT_MAX /* max value for a size_t */ + +#define __OFF_MAX __LLONG_MAX /* max value for an off_t */ +#define __OFF_MIN __LLONG_MIN /* min value for an off_t */ + +/* Quads and long longs are the same size. Ensure they stay in sync. */ +#define __UQUAD_MAX __ULLONG_MAX /* max value for a uquad_t */ +#define __QUAD_MAX __LLONG_MAX /* max value for a quad_t */ +#define __QUAD_MIN __LLONG_MIN /* min value for a quad_t */ + +#ifdef _LARGE_LONG +#define __LONG_BIT 64 +#else +#define __LONG_BIT 32 +#endif +#define __WORD_BIT 32 + +/* Minimum signal stack size. */ +#define __MINSIGSTKSZ (512 * 4) + +#endif /* !_MACHINE__LIMITS_H_ */ diff --git a/sys/powerpc/include/_stdint.h b/sys/powerpc/include/_stdint.h new file mode 100644 index 000000000000..0d8aedfff5d6 --- /dev/null +++ b/sys/powerpc/include/_stdint.h @@ -0,0 +1,171 @@ +/*- + * Copyright (c) 2001, 2002 Mike Barcroft <mike@FreeBSD.org> + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Klaus Klein. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE__STDINT_H_ +#define _MACHINE__STDINT_H_ + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) + +#define INT8_C(c) (c) +#define INT16_C(c) (c) +#define INT32_C(c) (c) +#define INT64_C(c) (c ## LL) + +#define UINT8_C(c) (c) +#define UINT16_C(c) (c) +#define UINT32_C(c) (c ## U) +#define UINT64_C(c) (c ## ULL) + +#define INTMAX_C(c) (c ## LL) +#define UINTMAX_C(c) (c ## ULL) + +#endif /* !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) */ + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) + +/* + * ISO/IEC 9899:1999 + * 7.18.2.1 Limits of exact-width integer types + */ +/* Minimum values of exact-width signed integer types. */ +#define INT8_MIN (-0x7f-1) +#define INT16_MIN (-0x7fff-1) +#define INT32_MIN (-0x7fffffff-1) +#define INT64_MIN (-0x7fffffffffffffffLL-1) + +/* Maximum values of exact-width signed integer types. */ +#define INT8_MAX 0x7f +#define INT16_MAX 0x7fff +#define INT32_MAX 0x7fffffff +#define INT64_MAX 0x7fffffffffffffffLL + +/* Maximum values of exact-width unsigned integer types. */ +#define UINT8_MAX 0xff +#define UINT16_MAX 0xffff +#define UINT32_MAX 0xffffffffU +#define UINT64_MAX 0xffffffffffffffffULL + +/* + * ISO/IEC 9899:1999 + * 7.18.2.2 Limits of minimum-width integer types + */ +/* Minimum values of minimum-width signed integer types. */ +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +/* Maximum values of minimum-width signed integer types. */ +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +/* Maximum values of minimum-width unsigned integer types. */ +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +/* + * ISO/IEC 9899:1999 + * 7.18.2.3 Limits of fastest minimum-width integer types + */ +/* Minimum values of fastest minimum-width signed integer types. */ +#define INT_FAST8_MIN INT32_MIN +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST64_MIN INT64_MIN + +/* Maximum values of fastest minimum-width signed integer types. */ +#define INT_FAST8_MAX INT32_MAX +#define INT_FAST16_MAX INT32_MAX +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MAX INT64_MAX + +/* Maximum values of fastest minimum-width unsigned integer types. */ +#define UINT_FAST8_MAX UINT32_MAX +#define UINT_FAST16_MAX UINT32_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +/* + * ISO/IEC 9899:1999 + * 7.18.2.4 Limits of integer types capable of holding object pointers + */ +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX + +/* + * ISO/IEC 9899:1999 + * 7.18.2.5 Limits of greatest-width integer types + */ +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +/* + * ISO/IEC 9899:1999 + * 7.18.3 Limits of other integer types + */ +/* Limits of ptrdiff_t. */ +#define PTRDIFF_MIN INT32_MIN +#define PTRDIFF_MAX INT32_MAX + +/* Limits of sig_atomic_t. */ +#define SIG_ATOMIC_MIN INT32_MIN +#define SIG_ATOMIC_MAX INT32_MAX + +/* Limit of size_t. */ +#define SIZE_MAX UINT32_MAX + +#ifndef WCHAR_MIN /* Also possibly defined in <wchar.h> */ +/* Limits of wchar_t. */ +#define WCHAR_MIN INT32_MIN +#define WCHAR_MAX INT32_MAX +#endif + +/* Limits of wint_t. */ +#define WINT_MIN INT32_MIN +#define WINT_MAX INT32_MAX + +#endif /* !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) */ + +#endif /* !_MACHINE__STDINT_H_ */ diff --git a/sys/powerpc/include/_types.h b/sys/powerpc/include/_types.h new file mode 100644 index 000000000000..c6babcf4a108 --- /dev/null +++ b/sys/powerpc/include/_types.h @@ -0,0 +1,134 @@ +/*- + * Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org> + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * From: @(#)ansi.h 8.2 (Berkeley) 1/4/94 + * From: @(#)types.h 8.3 (Berkeley) 1/5/94 + * $FreeBSD$ + */ + +#ifndef _MACHINE__TYPES_H_ +#define _MACHINE__TYPES_H_ + +#ifndef _SYS_CDEFS_H_ +#error this file needs sys/cdefs.h as a prerequisite +#endif + +/* + * Basic types upon which most other types are built. + */ +typedef __signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; + +#if defined(lint) +/* LONGLONG */ +typedef long long __int64_t; +/* LONGLONG */ +typedef unsigned long long __uint64_t; +#elif defined(__GNUCLIKE_ATTRIBUTE_MODE_DI) +typedef int __attribute__((__mode__(__DI__))) __int64_t; +typedef unsigned int __attribute__((__mode__(__DI__))) __uint64_t; +#else +/* LONGLONG */ +typedef long long __int64_t; +/* LONGLONG */ +typedef unsigned long long __uint64_t; +#endif + +/* + * Standard type definitions. + */ +typedef __uint32_t __clock_t; /* clock()... */ +typedef unsigned int __cpumask_t; +typedef __int32_t __critical_t; +typedef double __double_t; +typedef double __float_t; +typedef __int32_t __intfptr_t; +typedef __int64_t __intmax_t; +typedef __int32_t __intptr_t; +typedef __int32_t __int_fast8_t; +typedef __int32_t __int_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __int8_t __int_least8_t; +typedef __int16_t __int_least16_t; +typedef __int32_t __int_least32_t; +typedef __int64_t __int_least64_t; +typedef __int32_t __ptrdiff_t; /* ptr1 - ptr2 */ +typedef __int32_t __register_t; +typedef __int32_t __segsz_t; /* segment size (in pages) */ +typedef __uint32_t __size_t; /* sizeof() */ +typedef __int32_t __ssize_t; /* byte count or error */ +typedef __int32_t __time_t; /* time()... */ +typedef __uint32_t __uintfptr_t; +typedef __uint64_t __uintmax_t; +typedef __uint32_t __uintptr_t; +typedef __uint32_t __uint_fast8_t; +typedef __uint32_t __uint_fast16_t; +typedef __uint32_t __uint_fast32_t; +typedef __uint64_t __uint_fast64_t; +typedef __uint8_t __uint_least8_t; +typedef __uint16_t __uint_least16_t; +typedef __uint32_t __uint_least32_t; +typedef __uint64_t __uint_least64_t; +typedef __uint32_t __u_register_t; +typedef __uint32_t __vm_offset_t; +typedef __int64_t __vm_ooffset_t; +typedef __uint32_t __vm_paddr_t; +typedef __uint64_t __vm_pindex_t; +typedef __uint32_t __vm_size_t; + +/* + * Unusual type definitions. + */ +#if defined(__GNUCLIKE_BUILTIN_VARARGS) +typedef __builtin_va_list __va_list; /* internally known to gcc */ +#else +typedef struct { + char __gpr; + char __fpr; + char __pad[2]; + char *__stack; + char *__base; +} __va_list; +#endif /* post GCC 2.95 */ +#if defined(__GNUC_VA_LIST_COMPATIBILITY) && !defined(__GNUC_VA_LIST) \ + && !defined(__NO_GNUC_VA_LIST) +#define __GNUC_VA_LIST +typedef __va_list __gnuc_va_list; /* compatibility w/GNU headers*/ +#endif + +#endif /* !_MACHINE__TYPES_H_ */ diff --git a/sys/powerpc/include/asm.h b/sys/powerpc/include/asm.h new file mode 100644 index 000000000000..34d8ad65e8d7 --- /dev/null +++ b/sys/powerpc/include/asm.h @@ -0,0 +1,99 @@ +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: asm.h,v 1.6.18.1 2000/07/25 08:37:14 kleink Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_ASM_H_ +#define _MACHINE_ASM_H_ + +#include <sys/cdefs.h> + +#ifdef PIC +#define PIC_PROLOGUE XXX +#define PIC_EPILOGUE XXX +#define PIC_PLT(x) x@plt +#ifdef __STDC__ +#define PIC_GOT(x) XXX +#else /* not __STDC__ */ +#define PIC_GOT(x) XXX +#endif /* __STDC__ */ +#else +#define PIC_PROLOGUE +#define PIC_EPILOGUE +#define PIC_PLT(x) x +#define PIC_GOT(x) x +#endif + +#define CNAME(csym) csym +#define ASMNAME(asmsym) asmsym +#define HIDENAME(asmsym) __CONCAT(.,asmsym) + +#define _GLOBAL(x) \ + .data; .align 2; .globl x; x: + +#define _ENTRY(x) \ + .text; .align 2; .globl x; .type x,@function; x: + +#ifdef GPROF +# define _PROF_PROLOGUE mflr 0; stw 0,4(1); bl _mcount +#else +# define _PROF_PROLOGUE +#endif + +#define ENTRY(y) _ENTRY(CNAME(y)); _PROF_PROLOGUE +#define ASENTRY(y) _ENTRY(ASMNAME(y)); _PROF_PROLOGUE +#define GLOBAL(y) _GLOBAL(CNAME(y)) + +#define ASMSTR .asciz + +#define RCSID(x) .text; .asciz x + +#undef __FBSDID +#if !defined(lint) && !defined(STRIP_FBSDID) +#define __FBSDID(s) .ident s +#else +#define __FBSDID(s) /* nothing */ +#endif /* not lint and not STRIP_FBSDID */ + +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym + +#ifdef __STDC__ +#define WARN_REFERENCES(_sym,_msg) \ + .section .gnu.warning. ## _sym ; .ascii _msg ; .text +#else +#define WARN_REFERENCES(_sym,_msg) \ + .section .gnu.warning./**/_sym ; .ascii _msg ; .text +#endif /* __STDC__ */ + +#endif /* !_MACHINE_ASM_H_ */ diff --git a/sys/powerpc/include/atomic.h b/sys/powerpc/include/atomic.h new file mode 100644 index 000000000000..9bbf3bf30564 --- /dev/null +++ b/sys/powerpc/include/atomic.h @@ -0,0 +1,465 @@ +/*- + * Copyright (c) 2001 Benno Rice + * Copyright (c) 2001 David E. O'Brien + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_ATOMIC_H_ +#define _MACHINE_ATOMIC_H_ + +#include <machine/cpufunc.h> + +#ifndef _SYS_CDEFS_H_ +#error this file needs sys/cdefs.h as a prerequisite +#endif + +/* + * Various simple arithmetic on memory which is atomic in the presence + * of interrupts and SMP safe. + */ + +void atomic_set_8(volatile uint8_t *, uint8_t); +void atomic_clear_8(volatile uint8_t *, uint8_t); +void atomic_add_8(volatile uint8_t *, uint8_t); +void atomic_subtract_8(volatile uint8_t *, uint8_t); + +void atomic_set_16(volatile uint16_t *, uint16_t); +void atomic_clear_16(volatile uint16_t *, uint16_t); +void atomic_add_16(volatile uint16_t *, uint16_t); +void atomic_subtract_16(volatile uint16_t *, uint16_t); + +static __inline void +atomic_set_32(volatile uint32_t *p, uint32_t v) +{ + uint32_t temp; + +#ifdef __GNUCLIKE_ASM + __asm __volatile ( + "1:\tlwarx %0, 0, %2\n\t" /* load old value */ + "or %0, %3, %0\n\t" /* calculate new value */ + "stwcx. %0, 0, %2\n\t" /* attempt to store */ + "bne- 1b\n\t" /* spin if failed */ + : "=&r" (temp), "=m" (*p) + : "r" (p), "r" (v), "m" (*p) + : "cc", "memory"); +#endif +} + +static __inline void +atomic_clear_32(volatile uint32_t *p, uint32_t v) +{ + uint32_t temp; + +#ifdef __GNUCLIKE_ASM + __asm __volatile ( + "1:\tlwarx %0, 0, %2\n\t" /* load old value */ + "andc %0, %0, %3\n\t" /* calculate new value */ + "stwcx. %0, 0, %2\n\t" /* attempt to store */ + "bne- 1b\n\t" /* spin if failed */ + : "=&r" (temp), "=m" (*p) + : "r" (p), "r" (v), "m" (*p) + : "cc", "memory"); +#endif +} + +static __inline void +atomic_add_32(volatile uint32_t *p, uint32_t v) +{ + uint32_t temp; + +#ifdef __GNUCLIKE_ASM + __asm __volatile ( + "1:\tlwarx %0, 0, %2\n\t" /* load old value */ + "add %0, %3, %0\n\t" /* calculate new value */ + "stwcx. %0, 0, %2\n\t" /* attempt to store */ + "bne- 1b\n\t" /* spin if failed */ + : "=&r" (temp), "=m" (*p) + : "r" (p), "r" (v), "m" (*p) + : "cc", "memory"); +#endif +} + +static __inline void +atomic_subtract_32(volatile uint32_t *p, uint32_t v) +{ + uint32_t temp; + +#ifdef __GNUCLIKE_ASM + __asm __volatile ( + "1:\tlwarx %0, 0, %2\n\t" /* load old value */ + "subf %0, %3, %0\n\t" /* calculate new value */ + "stwcx. %0, 0, %2\n\t" /* attempt to store */ + "bne- 1b\n\t" /* spin if failed */ + : "=&r" (temp), "=m" (*p) + : "r" (p), "r" (v), "m" (*p) + : "cc", "memory"); +#endif +} + +static __inline uint32_t +atomic_readandclear_32(volatile uint32_t *addr) +{ + uint32_t result,temp; + +#ifdef __GNUCLIKE_ASM + __asm __volatile ( + "\tsync\n" /* drain writes */ + "1:\tlwarx %0, 0, %3\n\t" /* load old value */ + "li %1, 0\n\t" /* load new value */ + "stwcx. %1, 0, %3\n\t" /* attempt to store */ + "bne- 1b\n\t" /* spin if failed */ + : "=&r"(result), "=&r"(temp), "=m" (*addr) + : "r" (addr), "m" (*addr) + : "cc", "memory"); +#endif + + return (result); +} + +#if 0 + +/* + * So far I haven't found a way to implement atomic 64-bit ops on the + * 32-bit PowerPC without involving major headaches. If anyone has + * any ideas, please let me know. =) + * - benno@FreeBSD.org + */ + +static __inline void +atomic_set_64(volatile u_int64_t *p, u_int64_t v) +{ + u_int64_t temp; + + __asm __volatile ( + : "=&r" (temp), "=r" (*p) + : "r" (*p), "r" (v) + : "memory"); +} + +static __inline void +atomic_clear_64(volatile u_int64_t *p, u_int64_t v) +{ + u_int64_t temp; + + __asm __volatile ( + : "=&r" (temp), "=r" (*p) + : "r" (*p), "r" (v) + : "memory"); +} + +static __inline void +atomic_add_64(volatile u_int64_t *p, u_int64_t v) +{ + u_int64_t temp; + + __asm __volatile ( + : "=&r" (temp), "=r" (*p) + : "r" (*p), "r" (v) + : "memory"); +} + +static __inline void +atomic_subtract_64(volatile u_int64_t *p, u_int64_t v) +{ + u_int64_t temp; + + __asm __volatile ( + : "=&r" (temp), "=r" (*p) + : "r" (*p), "r" (v) + : "memory"); +} + +static __inline u_int64_t +atomic_readandclear_64(volatile u_int64_t *addr) +{ + u_int64_t result,temp; + + __asm __volatile ( + : "=&r"(result), "=&r"(temp), "=r" (*addr) + : "r"(*addr) + : "memory"); + + return result; +} + +#endif /* 0 */ + +#define atomic_set_char atomic_set_8 +#define atomic_clear_char atomic_clear_8 +#define atomic_add_char atomic_add_8 +#define atomic_subtract_char atomic_subtract_8 + +#define atomic_set_short atomic_set_16 +#define atomic_clear_short atomic_clear_16 +#define atomic_add_short atomic_add_16 +#define atomic_subtract_short atomic_subtract_16 + +#define atomic_set_int atomic_set_32 +#define atomic_clear_int atomic_clear_32 +#define atomic_add_int atomic_add_32 +#define atomic_subtract_int atomic_subtract_32 +#define atomic_readandclear_int atomic_readandclear_32 + +#define atomic_set_long atomic_set_32 +#define atomic_clear_long atomic_clear_32 +#define atomic_add_long(p, v) atomic_add_32((uint32_t *)p, (uint32_t)v) +#define atomic_subtract_long(p, v) atomic_subtract_32((uint32_t *)p, (uint32_t)v) +#define atomic_readandclear_long atomic_readandclear_32 + +#define atomic_set_ptr atomic_set_32 +#define atomic_clear_ptr atomic_clear_32 +#define atomic_add_ptr atomic_add_32 +#define atomic_subtract_ptr atomic_subtract_32 + +#if 0 + +/* See above. */ + +#define atomic_set_long_long atomic_set_64 +#define atomic_clear_long_long atomic_clear_64 +#define atomic_add_long_long atomic_add_64 +#define atomic_subtract_long_long atomic_subtract_64 +#define atomic_readandclear_long_long atomic_readandclear_64 + +#endif /* 0 */ + +#define ATOMIC_ACQ_REL(NAME, WIDTH, TYPE) \ +static __inline void \ +atomic_##NAME##_acq_##WIDTH(volatile u_int##WIDTH##_t *p, u_int##WIDTH##_t v) \ +{ \ + atomic_##NAME##_##WIDTH(p, v); \ + powerpc_mb(); \ +} \ + \ +static __inline void \ +atomic_##NAME##_rel_##WIDTH(volatile u_int##WIDTH##_t *p, u_int##WIDTH##_t v) \ +{ \ + powerpc_mb(); \ + atomic_##NAME##_##WIDTH(p, v); \ +} \ + \ +static __inline void \ +atomic_##NAME##_acq_##TYPE(volatile u_int##WIDTH##_t *p, u_int##WIDTH##_t v) \ +{ \ + atomic_##NAME##_##WIDTH(p, v); \ + powerpc_mb(); \ +} \ + \ +static __inline void \ +atomic_##NAME##_rel_##TYPE(volatile u_int##WIDTH##_t *p, u_int##WIDTH##_t v) \ +{ \ + powerpc_mb(); \ + atomic_##NAME##_##WIDTH(p, v); \ +} + +ATOMIC_ACQ_REL(set, 8, char) +ATOMIC_ACQ_REL(clear, 8, char) +ATOMIC_ACQ_REL(add, 8, char) +ATOMIC_ACQ_REL(subtract, 8, char) +ATOMIC_ACQ_REL(set, 16, short) +ATOMIC_ACQ_REL(clear, 16, short) +ATOMIC_ACQ_REL(add, 16, short) +ATOMIC_ACQ_REL(subtract, 16, short) +ATOMIC_ACQ_REL(set, 32, int) +ATOMIC_ACQ_REL(clear, 32, int) +ATOMIC_ACQ_REL(add, 32, int) +ATOMIC_ACQ_REL(subtract, 32, int) + +#define atomic_set_acq_long atomic_set_acq_32 +#define atomic_set_rel_long atomic_set_rel_32 +#define atomic_clear_acq_long atomic_clear_acq_32 +#define atomic_clear_rel_long atomic_clear_rel_32 +#define atomic_add_acq_long atomic_add_acq_32 +#define atomic_add_rel_long atomic_add_rel_32 +#define atomic_subtract_acq_long atomic_subtract_acq_32 +#define atomic_subtract_rel_long atomic_subtract_rel_32 + +#define atomic_set_acq_ptr atomic_set_acq_32 +#define atomic_set_rel_ptr atomic_set_rel_32 +#define atomic_clear_acq_ptr atomic_clear_acq_32 +#define atomic_clear_rel_ptr atomic_clear_rel_32 +#define atomic_add_acq_ptr atomic_add_acq_32 +#define atomic_add_rel_ptr atomic_add_rel_32 +#define atomic_subtract_acq_ptr atomic_subtract_acq_32 +#define atomic_subtract_rel_ptr atomic_subtract_rel_32 + +#undef ATOMIC_ACQ_REL + +/* + * We assume that a = b will do atomic loads and stores. + */ +#define ATOMIC_STORE_LOAD(TYPE, WIDTH) \ +static __inline u_##TYPE \ +atomic_load_acq_##WIDTH(volatile u_##TYPE *p) \ +{ \ + u_##TYPE v; \ + \ + v = *p; \ + powerpc_mb(); \ + return (v); \ +} \ + \ +static __inline void \ +atomic_store_rel_##WIDTH(volatile u_##TYPE *p, u_##TYPE v) \ +{ \ + powerpc_mb(); \ + *p = v; \ +} \ + \ +static __inline u_##TYPE \ +atomic_load_acq_##TYPE(volatile u_##TYPE *p) \ +{ \ + u_##TYPE v; \ + \ + v = *p; \ + powerpc_mb(); \ + return (v); \ +} \ + \ +static __inline void \ +atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v) \ +{ \ + powerpc_mb(); \ + *p = v; \ +} + +ATOMIC_STORE_LOAD(char, 8) +ATOMIC_STORE_LOAD(short, 16) +ATOMIC_STORE_LOAD(int, 32) + +#define atomic_load_acq_long atomic_load_acq_32 +#define atomic_store_rel_long atomic_store_rel_32 + +#define atomic_load_acq_ptr atomic_load_acq_32 +#define atomic_store_rel_ptr atomic_store_rel_32 + +#undef ATOMIC_STORE_LOAD + +/* + * Atomically compare the value stored at *p with cmpval and if the + * two values are equal, update the value of *p with newval. Returns + * zero if the compare failed, nonzero otherwise. + */ +static __inline uint32_t +atomic_cmpset_32(volatile uint32_t* p, uint32_t cmpval, uint32_t newval) +{ + uint32_t ret; + +#ifdef __GNUCLIKE_ASM + __asm __volatile ( + "1:\tlwarx %0, 0, %2\n\t" /* load old value */ + "cmplw %3, %0\n\t" /* compare */ + "bne 2f\n\t" /* exit if not equal */ + "stwcx. %4, 0, %2\n\t" /* attempt to store */ + "bne- 1b\n\t" /* spin if failed */ + "li %0, 1\n\t" /* success - retval = 1 */ + "b 3f\n\t" /* we've succeeded */ + "2:\n\t" + "stwcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ + "li %0, 0\n\t" /* failure - retval = 0 */ + "3:\n\t" + : "=&r" (ret), "=m" (*p) + : "r" (p), "r" (cmpval), "r" (newval), "m" (*p) + : "cc", "memory"); +#endif + + return (ret); +} + +#if 0 + +/* + * Atomically compare the value stored at *p with cmpval and if the + * two values are equal, update the value of *p with newval. Returns + * zero if the compare failed, nonzero otherwise. + */ +static __inline u_int64_t +atomic_cmpset_64(volatile u_int64_t* p, u_int64_t cmpval, u_int64_t newval) +{ + u_int64_t ret; + + __asm __volatile ( + : "=&r" (ret), "=r" (*p) + : "r" (cmpval), "r" (newval), "r" (*p) + : "memory"); + + return ret; +} + +#endif /* 0 */ + +#define atomic_cmpset_int atomic_cmpset_32 +#define atomic_cmpset_long atomic_cmpset_32 + +#define atomic_cmpset_ptr(dst, old, new) \ + atomic_cmpset_32((volatile u_int *)(dst), (u_int)(old), (u_int)(new)) + +#if 0 +#define atomic_cmpset_long_long atomic_cmpset_64 +#endif /* 0 */ + +static __inline uint32_t +atomic_cmpset_acq_32(volatile uint32_t *p, uint32_t cmpval, uint32_t newval) +{ + int retval; + + retval = atomic_cmpset_32(p, cmpval, newval); + powerpc_mb(); + return (retval); +} + +static __inline uint32_t +atomic_cmpset_rel_32(volatile uint32_t *p, uint32_t cmpval, uint32_t newval) +{ + powerpc_mb(); + return (atomic_cmpset_32(p, cmpval, newval)); +} + +#define atomic_cmpset_acq_int atomic_cmpset_acq_32 +#define atomic_cmpset_rel_int atomic_cmpset_rel_32 +#define atomic_cmpset_acq_long atomic_cmpset_acq_32 +#define atomic_cmpset_rel_long atomic_cmpset_rel_32 + +#define atomic_cmpset_acq_ptr(dst, old, new) \ + atomic_cmpset_acq_32((volatile u_int *)(dst), (u_int)(old), (u_int)(new)) +#define atomic_cmpset_rel_ptr(dst, old, new) \ + atomic_cmpset_rel_32((volatile u_int *)(dst), (u_int)(old), (u_int)(new)) + +static __inline uint32_t +atomic_fetchadd_32(volatile uint32_t *p, uint32_t v) +{ + uint32_t value; + + do { + value = *p; + } while (!atomic_cmpset_32(p, value, value + v)); + return (value); +} + +#define atomic_fetchadd_int atomic_fetchadd_32 + +#endif /* ! _MACHINE_ATOMIC_H_ */ diff --git a/sys/powerpc/include/bat.h b/sys/powerpc/include/bat.h new file mode 100644 index 000000000000..27c6d5a895f6 --- /dev/null +++ b/sys/powerpc/include/bat.h @@ -0,0 +1,172 @@ +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: bat.h,v 1.2 1999/12/18 01:36:06 thorpej Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_BAT_H_ +#define _MACHINE_BAT_H_ + +struct bat { + u_int32_t batu; + u_int32_t batl; +}; + +/* Lower BAT bits (all but PowerPC 601): */ +#define BAT_PBS 0xfffe0000 /* physical block start */ +#define BAT_W 0x00000040 /* 1 = write-through, 0 = write-back */ +#define BAT_I 0x00000020 /* cache inhibit */ +#define BAT_M 0x00000010 /* memory coherency enable */ +#define BAT_G 0x00000008 /* guarded region */ + +#define BAT_PP_NONE 0x00000000 /* no access permission */ +#define BAT_PP_RO_S 0x00000001 /* read-only (soft) */ +#define BAT_PP_RW 0x00000002 /* read/write */ +#define BAT_PP_RO 0x00000003 /* read-only */ + +/* Upper BAT bits (all but PowerPC 601): */ +#define BAT_EBS 0xfffe0000 /* effective block start */ +#define BAT_BL 0x00001ffc /* block length */ +#define BAT_Vs 0x00000002 /* valid in supervisor mode */ +#define BAT_Vu 0x00000001 /* valid in user mode */ + +#define BAT_V (BAT_Vs|BAT_Vu) + +/* Block Length encoding (all but PowerPC 601): */ +#define BAT_BL_128K 0x00000000 +#define BAT_BL_256K 0x00000004 +#define BAT_BL_512K 0x0000000c +#define BAT_BL_1M 0x0000001c +#define BAT_BL_2M 0x0000003c +#define BAT_BL_4M 0x0000007c +#define BAT_BL_8M 0x000000fc +#define BAT_BL_16M 0x000001fc +#define BAT_BL_32M 0x000003fc +#define BAT_BL_64M 0x000007fc +#define BAT_BL_128M 0x00000ffc +#define BAT_BL_256M 0x00001ffc + +#define BATU(va, len, v) \ + (((va) & BAT_EBS) | ((len) & BAT_BL) | ((v) & BAT_V)) + +#define BATL(pa, wimg, pp) \ + (((pa) & BAT_PBS) | (wimg) | (pp)) + + +/* Lower BAT bits (PowerPC 601): */ +#define BAT601_PBN 0xfffe0000 /* physical block number */ +#define BAT601_V 0x00000040 /* valid */ +#define BAT601_BSM 0x0000003f /* block size mask */ + +/* Upper BAT bits (PowerPC 601): */ +#define BAT601_BLPI 0xfffe0000 /* block logical page index */ +#define BAT601_W 0x00000040 /* 1 = write-through, 0 = write-back */ +#define BAT601_I 0x00000020 /* cache inhibit */ +#define BAT601_M 0x00000010 /* memory coherency enable */ +#define BAT601_Ks 0x00000008 /* key-supervisor */ +#define BAT601_Ku 0x00000004 /* key-user */ + +/* + * Permission bits on the PowerPC 601 are modified by the appropriate + * Key bit: + * + * Key PP Access + * 0 NONE read/write + * 0 RO_S read/write + * 0 RW read/write + * 0 RO read-only + * + * 1 NONE none + * 1 RO_S read-only + * 1 RW read/write + * 1 RO read-only + */ +#define BAT601_PP_NONE 0x00000000 /* no access permission */ +#define BAT601_PP_RO_S 0x00000001 /* read-only (soft) */ +#define BAT601_PP_RW 0x00000002 /* read/write */ +#define BAT601_PP_RO 0x00000003 /* read-only */ + +/* Block Size Mask encoding (PowerPC 601): */ +#define BAT601_BSM_128K 0x00000000 +#define BAT601_BSM_256K 0x00000001 +#define BAT601_BSM_512K 0x00000003 +#define BAT601_BSM_1M 0x00000007 +#define BAT601_BSM_2M 0x0000000f +#define BAT601_BSM_4M 0x0000001f +#define BAT601_BSM_8M 0x0000003f + +#define BATU601(va, wim, key, pp) \ + (((va) & BAT601_BLPI) | (wim) | (key) | (pp)) + +#define BATL601(pa, size, v) \ + (((pa) & BAT601_PBN) | (v) | (size)) + +#ifdef _KERNEL +extern struct bat battable[16]; +#endif + +#endif /* _MACHINE_BAT_H_ */ diff --git a/sys/powerpc/include/bootinfo.h b/sys/powerpc/include/bootinfo.h new file mode 100644 index 000000000000..aa967ac59689 --- /dev/null +++ b/sys/powerpc/include/bootinfo.h @@ -0,0 +1,87 @@ +/*- + * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + * + * $FreeBSD$ + */ + +/* + * The boot program passes a pointer (in the boot environment virtual + * address address space; "BEVA") to a bootinfo to the kernel using + * the following convention: + * + * a0 contains first free page frame number + * a1 contains page number of current level 1 page table + * if a2 contains BOOTINFO_MAGIC and a4 is nonzero: + * a3 contains pointer (BEVA) to bootinfo + * a4 contains bootinfo version number + * if a2 contains BOOTINFO_MAGIC and a4 contains 0 (backward compat): + * a3 contains pointer (BEVA) to bootinfo version + * (u_long), then the bootinfo + */ + +#define BOOTINFO_MAGIC 0xdeadbeeffeedface + +struct bootinfo_v1 { + u_long ssym; /* 0: start of kernel sym table */ + u_long esym; /* 8: end of kernel sym table */ + char boot_flags[64]; /* 16: boot flags */ + char booted_kernel[64]; /* 80: name of booted kernel */ + void *hwrpb; /* 144: hwrpb pointer (BEVA) */ + u_long hwrpbsize; /* 152: size of hwrpb data */ + int (*cngetc)(void); /* 160: console getc pointer */ + void (*cnputc)(int); /* 168: console putc pointer */ + void (*cnpollc)(int); /* 176: console pollc pointer */ + u_long pad[6]; /* 184: rsvd for future use */ + char *envp; /* 232: start of environment */ + u_long kernend; /* 240: end of kernel */ + u_long modptr; /* 248: FreeBSD module base */ + /* 256: total size */ +}; + +/* + * Kernel-internal structure used to hold important bits of boot + * information. NOT to be used by boot blocks. + * + * Note that not all of the fields from the bootinfo struct(s) + * passed by the boot blocks aren't here (because they're not currently + * used by the kernel!). Fields here which aren't supplied by the + * bootinfo structure passed by the boot blocks are supposed to be + * filled in at startup with sane contents. + */ +struct bootinfo_kernel { + u_long ssym; /* start of syms */ + u_long esym; /* end of syms */ + u_long modptr; /* FreeBSD module pointer */ + u_long kernend; /* "end of kernel" from boot code */ + char *envp; /* "end of kernel" from boot code */ + u_long hwrpb_phys; /* hwrpb physical address */ + u_long hwrpb_size; /* size of hwrpb data */ + char boot_flags[64]; /* boot flags */ + char booted_kernel[64]; /* name of booted kernel */ + char booted_dev[64]; /* name of booted device */ +}; + +extern struct bootinfo_kernel bootinfo; diff --git a/sys/powerpc/include/bus.h b/sys/powerpc/include/bus.h new file mode 100644 index 000000000000..7460d130f70e --- /dev/null +++ b/sys/powerpc/include/bus.h @@ -0,0 +1,741 @@ +/*- + * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1996 Charles M. Hannum. All rights reserved. + * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: bus.h,v 1.9.4.1 2000/06/30 16:27:30 simonb Exp $ + * $FreeBSD$ + */ + +#ifndef _MACPPC_BUS_H_ +#define _MACPPC_BUS_H_ + +#include <machine/_bus.h> +#include <machine/pio.h> + +#define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF +#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF +#define BUS_SPACE_MAXSIZE 0xFFFFFFFF +#define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF +#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF +#define BUS_SPACE_MAXADDR 0xFFFFFFFF + +#define BUS_SPACE_UNRESTRICTED (~0) + +/* + * Values for the macppc bus space tag, not to be used directly by MI code. + */ + +#define __BUS_SPACE_HAS_STREAM_METHODS 1 + +/* + * Define the PPC tag values + */ +#define PPC_BUS_SPACE_MEM 1 /* space is mem space */ +#define PPC_BUS_SPACE_IO 2 /* space is io space */ + +static __inline void * +__ppc_ba(bus_space_tag_t tag __unused, bus_space_handle_t handle, + bus_size_t offset) +{ + return ((void *)(handle + offset)); +} + +/* + * int bus_space_map(bus_space_tag_t t, bus_addr_t addr, + * bus_size_t size, int flags, bus_space_handle_t *bshp)); + * + * Map a region of bus space. + */ + +static __inline int +bus_space_map(bus_space_tag_t t __unused, bus_addr_t addr, + bus_size_t size __unused, int flags __unused, + bus_space_handle_t *bshp) +{ + + *bshp = addr; + return (0); +} + +/* + * int bus_space_unmap(bus_space_tag_t t, + * bus_space_handle_t bsh, bus_size_t size)); + * + * Unmap a region of bus space. + */ + +static __inline void +bus_space_unmap(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused, + bus_size_t size __unused) +{ +} + +/* + * int bus_space_subregion(bus_space_tag_t t, + * bus_space_handle_t bsh, bus_size_t offset, bus_size_t size, + * bus_space_handle_t *nbshp)); + * + * Get a new handle for a subregion of an already-mapped area of bus space. + */ + +static __inline int +bus_space_subregion(bus_space_tag_t t __unused, bus_space_handle_t bsh, + bus_size_t offset, bus_size_t size __unused, bus_space_handle_t *nbshp) +{ + *nbshp = bsh + offset; + return (0); +} + +/* + * int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, + * bus_addr_t rend, bus_size_t size, bus_size_t align, + * bus_size_t boundary, int flags, bus_addr_t *addrp, + * bus_space_handle_t *bshp)); + * + * Allocate a region of bus space. + */ + +#if 0 +#define bus_space_alloc(t, rs, re, s, a, b, f, ap, hp) !!! unimplemented !!! +#endif + +/* + * int bus_space_free(bus_space_tag_t t, + * bus_space_handle_t bsh, bus_size_t size)); + * + * Free a region of bus space. + */ +#if 0 +#define bus_space_free(t, h, s) !!! unimplemented !!! +#endif + +/* + * u_intN_t bus_space_read_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset)); + * + * Read a 1, 2, 4, or 8 byte quantity from bus space + * described by tag/handle/offset. + */ + +static __inline u_int8_t +bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +{ + return (in8(__ppc_ba(t, h, o))); +} + +static __inline u_int16_t +bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +{ + return (in16rb(__ppc_ba(t, h, o))); +} + +static __inline u_int32_t +bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +{ + return (in32rb(__ppc_ba(t, h, o))); +} + +#if 0 /* Cause a link error for bus_space_read_8 */ +#define bus_space_read_8(t, h, o) !!! unimplemented !!! +#endif + +static __inline u_int8_t +bus_space_read_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +{ + return (in8(__ppc_ba(t, h, o))); +} + +static __inline u_int16_t +bus_space_read_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +{ + return (in16(__ppc_ba(t, h, o))); +} + +static __inline u_int32_t +bus_space_read_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) +{ + return (in32(__ppc_ba(t, h, o))); +} + +#if 0 /* Cause a link error for bus_space_read_stream_8 */ +#define bus_space_read_stream_8(t, h, o) !!! unimplemented !!! +#endif + +/* + * void bus_space_read_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count)); + * + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle/offset and copy into buffer provided. + */ + +static __inline void +bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + u_int8_t *a, size_t c) +{ + ins8(__ppc_ba(t, h, o), a, c); +} + +static __inline void +bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + u_int16_t *a, size_t c) +{ + ins16rb(__ppc_ba(t, h, o), a, c); +} + +static __inline void +bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + u_int32_t *a, size_t c) +{ + ins32rb(__ppc_ba(t, h, o), a, c); +} + +#if 0 /* Cause a link error for bus_space_read_multi_8 */ +#define bus_space_read_multi_8 !!! unimplemented !!! +#endif + +static __inline void +bus_space_read_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t o, u_int8_t *a, size_t c) +{ + ins8(__ppc_ba(t, h, o), a, c); +} + +static __inline void +bus_space_read_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t o, u_int16_t *a, size_t c) +{ + ins16(__ppc_ba(t, h, o), a, c); +} + +static __inline void +bus_space_read_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t o, u_int32_t *a, size_t c) +{ + ins32(__ppc_ba(t, h, o), a, c); +} + +#if 0 /* Cause a link error for bus_space_read_multi_stream_8 */ +#define bus_space_read_multi_stream_8 !!! unimplemented !!! +#endif + +/* + * void bus_space_read_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t *addr, size_t count)); + * + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle and starting at `offset' and copy into + * buffer provided. + */ + +static __inline void +bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t *addr, size_t count) +{ + volatile u_int8_t *s = __ppc_ba(tag, bsh, offset); + + while (count--) + *addr++ = *s++; + __asm __volatile("eieio; sync"); +} + +static __inline void +bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t *addr, size_t count) +{ + volatile u_int16_t *s = __ppc_ba(tag, bsh, offset); + + while (count--) + __asm __volatile("lhbrx %0, 0, %1" : + "=r"(*addr++) : "r"(s++)); + __asm __volatile("eieio; sync"); +} + +static __inline void +bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int32_t *addr, size_t count) +{ + volatile u_int32_t *s = __ppc_ba(tag, bsh, offset); + + while (count--) + __asm __volatile("lwbrx %0, 0, %1" : + "=r"(*addr++) : "r"(s++)); + __asm __volatile("eieio; sync"); +} + +#if 0 /* Cause a link error for bus_space_read_region_8 */ +#define bus_space_read_region_8 !!! unimplemented !!! +#endif + +static __inline void +bus_space_read_region_stream_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t *addr, size_t count) +{ + volatile u_int16_t *s = __ppc_ba(tag, bsh, offset); + + while (count--) + *addr++ = *s++; + __asm __volatile("eieio; sync"); +} + +static __inline void +bus_space_read_region_stream_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int32_t *addr, size_t count) +{ + volatile u_int32_t *s = __ppc_ba(tag, bsh, offset); + + while (count--) + *addr++ = *s++; + __asm __volatile("eieio; sync"); +} + +#if 0 /* Cause a link error */ +#define bus_space_read_region_stream_8 !!! unimplemented !!! +#endif + +/* + * void bus_space_write_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * u_intN_t value)); + * + * Write the 1, 2, 4, or 8 byte value `value' to bus space + * described by tag/handle/offset. + */ + +static __inline void +bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + uint8_t v) +{ + out8(__ppc_ba(t, h, o), v); +} + +static __inline void +bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + uint16_t v) +{ + out16rb(__ppc_ba(t, h, o), v); +} + +static __inline void +bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + uint32_t v) +{ + out32rb(__ppc_ba(t, h, o), v); +} + +#if 0 /* Cause a link error for bus_space_write_8 */ +#define bus_space_write_8 !!! unimplemented !!! +#endif + +static __inline void +bus_space_write_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + uint8_t v) +{ + out8(__ppc_ba(t, h, o), v); +} + +static __inline void +bus_space_write_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + uint16_t v) +{ + out16(__ppc_ba(t, h, o), v); +} + +static __inline void +bus_space_write_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + uint32_t v) +{ + out32(__ppc_ba(t, h, o), v); +} + +#if 0 /* Cause a link error for bus_space_write_stream_8 */ +#define bus_space_write_stream_8 !!! unimplemented !!! +#endif + + +/* + * void bus_space_write_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count)); + * + * Write `count' 1, 2, 4, or 8 byte quantities from the buffer + * provided to bus space described by tag/handle/offset. + */ + +static __inline void +bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + uint8_t *a, size_t c) +{ + outsb(__ppc_ba(t, h, o), a, c); +} + +static __inline void +bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + uint16_t *a, size_t c) +{ + outsw(__ppc_ba(t, h, o), a, c); +} + +static __inline void +bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, + uint32_t *a, size_t c) +{ + outsl(__ppc_ba(t, h, o), a, c); +} + +#if 0 +#define bus_space_write_multi_8 !!! unimplemented !!! +#endif + +static __inline void +bus_space_write_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t o, const u_int8_t *a, size_t c) +{ + outsb(__ppc_ba(t, h, o), a, c); +} + +static __inline void +bus_space_write_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t o, const u_int16_t *a, size_t c) +{ + outsw(__ppc_ba(t, h, o), a, c); +} + +static __inline void +bus_space_write_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t o, const u_int32_t *a, size_t c) +{ + outsl(__ppc_ba(t, h, o), a, c); +} + +#if 0 +#define bus_space_write_multi_stream_8 !!! unimplemented !!! +#endif + +/* + * void bus_space_write_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * const u_intN_t *addr, size_t count)); + * + * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided + * to bus space described by tag/handle starting at `offset'. + */ + +static __inline void +bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int8_t *addr, size_t count) +{ + volatile u_int8_t *d = __ppc_ba(tag, bsh, offset); + + while (count--) + *d++ = *addr++; + __asm __volatile("eieio; sync"); +} + +static __inline void +bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int16_t *addr, size_t count) +{ + volatile u_int16_t *d = __ppc_ba(tag, bsh, offset); + + while (count--) + __asm __volatile("sthbrx %0, 0, %1" :: + "r"(*addr++), "r"(d++)); + __asm __volatile("eieio; sync"); +} + +static __inline void +bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int32_t *addr, size_t count) +{ + volatile u_int32_t *d = __ppc_ba(tag, bsh, offset); + + while (count--) + __asm __volatile("stwbrx %0, 0, %1" :: + "r"(*addr++), "r"(d++)); + __asm __volatile("eieio; sync"); +} + +#if 0 +#define bus_space_write_region_8 !!! bus_space_write_region_8 unimplemented !!! +#endif + +static __inline void +bus_space_write_region_stream_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int16_t *addr, size_t count) +{ + volatile u_int16_t *d = __ppc_ba(tag, bsh, offset); + + while (count--) + *d++ = *addr++; + __asm __volatile("eieio; sync"); +} + +static __inline void +bus_space_write_region_stream_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, const u_int32_t *addr, size_t count) +{ + volatile u_int32_t *d = __ppc_ba(tag, bsh, offset); + + while (count--) + *d++ = *addr++; + __asm __volatile("eieio; sync"); +} + +#if 0 +#define bus_space_write_region_stream_8 !!! unimplemented !!! +#endif + +/* + * void bus_space_set_multi_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, u_intN_t val, + * size_t count)); + * + * Write the 1, 2, 4, or 8 byte value `val' to bus space described + * by tag/handle/offset `count' times. + */ + +static __inline void +bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t val, size_t count) +{ + volatile u_int8_t *d = __ppc_ba(tag, bsh, offset); + + while (count--) + *d = val; + __asm __volatile("eieio; sync"); +} + +static __inline void +bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t val, size_t count) +{ + volatile u_int16_t *d = __ppc_ba(tag, bsh, offset); + + while (count--) + __asm __volatile("sthbrx %0, 0, %1" :: + "r"(val), "r"(d)); + __asm __volatile("eieio; sync"); +} + +static __inline void +bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int32_t val, size_t count) +{ + volatile u_int32_t *d = __ppc_ba(tag, bsh, offset); + + while (count--) + __asm __volatile("stwbrx %0, 0, %1" :: + "r"(val), "r"(d)); + __asm __volatile("eieio; sync"); +} + +#if 0 +#define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!! +#endif + +static __inline void +bus_space_set_multi_stream_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t val, size_t count) +{ + volatile u_int16_t *d = __ppc_ba(tag, bsh, offset); + + while (count--) + *d = val; + __asm __volatile("eieio; sync"); +} + +static __inline void +bus_space_set_multi_stream_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int32_t val, size_t count) +{ + volatile u_int32_t *d = __ppc_ba(tag, bsh, offset); + + while (count--) + *d = val; + __asm __volatile("eieio; sync"); +} + +#if 0 +#define bus_space_set_multi_stream_8 !!! unimplemented !!! +#endif + +/* + * void bus_space_set_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, u_intN_t val, + * size_t count)); + * + * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described + * by tag/handle starting at `offset'. + */ + +static __inline void +bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t val, size_t count) +{ + volatile u_int8_t *d = __ppc_ba(tag, bsh, offset); + + while (count--) + *d++ = val; + __asm __volatile("eieio; sync"); +} + +static __inline void +bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t val, size_t count) +{ + volatile u_int16_t *d = __ppc_ba(tag, bsh, offset); + + while (count--) + __asm __volatile("sthbrx %0, 0, %1" :: + "r"(val), "r"(d++)); + __asm __volatile("eieio; sync"); +} + +static __inline void +bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int32_t val, size_t count) +{ + volatile u_int32_t *d = __ppc_ba(tag, bsh, offset); + + while (count--) + __asm __volatile("stwbrx %0, 0, %1" :: + "r"(val), "r"(d++)); + __asm __volatile("eieio; sync"); +} + +#if 0 +#define bus_space_set_region_8 !!! bus_space_set_region_8 unimplemented !!! +#endif + +static __inline void +bus_space_set_region_stream_2(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t val, size_t count) +{ + volatile u_int16_t *d = __ppc_ba(tag, bsh, offset); + + while (count--) + *d++ = val; + __asm __volatile("eieio; sync"); +} + +static __inline void +bus_space_set_region_stream_4(bus_space_tag_t tag, bus_space_handle_t bsh, + bus_size_t offset, u_int32_t val, size_t count) +{ + volatile u_int32_t *d = __ppc_ba(tag, bsh, offset); + + while (count--) + *d++ = val; + __asm __volatile("eieio; sync"); +} + +#if 0 +#define bus_space_set_region_stream_8 !!! unimplemented !!! +#endif + +/* + * void bus_space_copy_region_N(bus_space_tag_t tag, + * bus_space_handle_t bsh1, bus_size_t off1, + * bus_space_handle_t bsh2, bus_size_t off2, + * size_t count)); + * + * Copy `count' 1, 2, 4, or 8 byte values from bus space starting + * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. + */ + + /* XXX IMPLEMENT bus_space_copy_N() XXX */ + +/* + * Bus read/write barrier methods. + * + * void bus_space_barrier(bus_space_tag_t tag, + * bus_space_handle_t bsh, bus_size_t offset, + * bus_size_t len, int flags)); + * + * Note: the macppc does not currently require barriers, but we must + * provide the flags to MI code. + */ + +#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ +#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ + +static __inline void +bus_space_barrier(bus_space_tag_t tag __unused, + bus_space_handle_t bsh __unused, bus_size_t offset __unused, + bus_size_t len __unused, int flags __unused) +{ + __asm __volatile("" : : : "memory"); +} + + +#define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t) + +#include <machine/bus_dma.h> + +#endif /* _MACPPC_BUS_H_ */ diff --git a/sys/powerpc/include/bus_dma.h b/sys/powerpc/include/bus_dma.h new file mode 100644 index 000000000000..d10a0557bc6b --- /dev/null +++ b/sys/powerpc/include/bus_dma.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 2005 Scott Long + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* $FreeBSD$ */ + +#ifndef _POWERPC_BUS_DMA_H_ +#define _POWERPC_BUS_DMA_H_ + +#include <sys/bus_dma.h> + +#endif /* _POWERPC_BUS_DMA_H_ */ diff --git a/sys/powerpc/include/clock.h b/sys/powerpc/include/clock.h new file mode 100644 index 000000000000..ead37ac149ab --- /dev/null +++ b/sys/powerpc/include/clock.h @@ -0,0 +1,24 @@ +/*- + * Kernel interface to machine-dependent clock driver. + * Garrett Wollman, September 1994. + * This file is in the public domain. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_CLOCK_H_ +#define _MACHINE_CLOCK_H_ + +#ifdef _KERNEL + +struct trapframe; + +int sysbeep(int pitch, int period); +int acquire_timer2(int mode); +int release_timer2(void); + +void decr_intr(struct trapframe *); + +#endif + +#endif /* !_MACHINE_CLOCK_H_ */ diff --git a/sys/powerpc/include/cpu.h b/sys/powerpc/include/cpu.h new file mode 100644 index 000000000000..a8fea27d3dca --- /dev/null +++ b/sys/powerpc/include/cpu.h @@ -0,0 +1,81 @@ +/*- + * Copyright (C) 1995-1997 Wolfgang Solfrank. + * Copyright (C) 1995-1997 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: cpu.h,v 1.11 2000/05/26 21:19:53 thorpej Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_CPU_H_ +#define _MACHINE_CPU_H_ + +#include <machine/frame.h> +#include <machine/pcb.h> +#include <machine/psl.h> + +#define TRAPF_USERMODE(frame) (((frame)->srr1 & PSL_PR) != 0) +#define TRAPF_PC(frame) ((frame)->srr0) + +#define cpu_swapout(p) +#define cpu_number() 0 + +/* + * CTL_MACHDEP definitions. + */ +#define CPU_CACHELINE 1 + +static __inline u_int64_t +get_cyclecount(void) +{ + u_int32_t _upper, _lower; + u_int64_t _time; + + __asm __volatile( + "mftb %0\n" + "mftbu %1" + : "=r" (_lower), "=r" (_upper)); + + _time = (u_int64_t)_upper; + _time = (_time << 32) + _lower; + return (_time); +} + +#define cpu_getstack(td) ((td)->td_frame->fixreg[1]) +#define cpu_spinwait() /* nothing */ + +void cpu_halt(void); +void cpu_reset(void); +void fork_trampoline(void); +void swi_vm(void *); + +/* XXX the following should not be here. */ +void savectx(struct pcb *); +int kcopy(const void *, void *, size_t); + +#endif /* _MACHINE_CPU_H_ */ diff --git a/sys/powerpc/include/cpufunc.h b/sys/powerpc/include/cpufunc.h new file mode 100644 index 000000000000..f02ff3bd55a3 --- /dev/null +++ b/sys/powerpc/include/cpufunc.h @@ -0,0 +1,175 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_CPUFUNC_H_ +#define _MACHINE_CPUFUNC_H_ + +/* + * Required for user-space atomic.h includes + */ +static __inline void +powerpc_mb(void) +{ + + __asm __volatile("eieio; sync" : : : "memory"); +} + +#ifdef _KERNEL + +#include <sys/types.h> + +#include <machine/psl.h> + +struct thread; + +#ifdef KDB +void ppc_db_trap(void); +#endif + +static __inline void +breakpoint(void) +{ +#ifdef KDB + ppc_db_trap(); +#endif +} + +/* CPU register mangling inlines */ + +static __inline void +mtmsr(register_t value) +{ + + __asm __volatile ("mtmsr %0; isync" :: "r"(value)); +} + +static __inline register_t +mfmsr(void) +{ + register_t value; + + __asm __volatile ("mfmsr %0" : "=r"(value)); + + return (value); +} + +static __inline void +mtsrin(vm_offset_t va, register_t value) +{ + + __asm __volatile ("mtsrin %0,%1" :: "r"(value), "r"(va)); +} + +static __inline register_t +mfsrin(vm_offset_t va) +{ + register_t value; + + __asm __volatile ("mfsrin %0,%1" : "=r"(value) : "r"(va)); + + return (value); +} + +static __inline void +mtdec(register_t value) +{ + + __asm __volatile ("mtdec %0" :: "r"(value)); +} + +static __inline register_t +mfdec(void) +{ + register_t value; + + __asm __volatile ("mfdec %0" : "=r"(value)); + + return (value); +} + +static __inline register_t +mfpvr(void) +{ + register_t value; + + __asm __volatile ("mfpvr %0" : "=r"(value)); + + return (value); +} + +static __inline void +eieio(void) +{ + + __asm __volatile ("eieio"); +} + +static __inline void +isync(void) +{ + + __asm __volatile ("isync"); +} + +static __inline register_t +intr_disable(void) +{ + register_t msr; + + msr = mfmsr(); + mtmsr(msr & ~PSL_EE); + return (msr); +} + +static __inline void +intr_restore(register_t msr) +{ + + mtmsr(msr); +} + +static __inline void +restore_intr(unsigned int msr) +{ + + mtmsr(msr); +} + +static __inline struct pcpu * +powerpc_get_pcpup(void) +{ + struct pcpu *ret; + + __asm ("mfsprg %0, 0" : "=r"(ret)); + + return(ret); +} + +#endif /* _KERNEL */ + +#endif /* !_MACHINE_CPUFUNC_H_ */ diff --git a/sys/powerpc/include/db_machdep.h b/sys/powerpc/include/db_machdep.h new file mode 100644 index 000000000000..8873d43ac8bd --- /dev/null +++ b/sys/powerpc/include/db_machdep.h @@ -0,0 +1,92 @@ +/*- + * Mach Operating System + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + * + * $OpenBSD: db_machdep.h,v 1.2 1997/03/21 00:48:48 niklas Exp $ + * $NetBSD: db_machdep.h,v 1.4.22.1 2000/08/05 11:10:43 wiz Exp $ + * $FreeBSD$ + */ + +/* + * Machine-dependent defines for new kernel debugger. + */ +#ifndef _POWERPC_DB_MACHDEP_H_ +#define _POWERPC_DB_MACHDEP_H_ + +#include <vm/vm_param.h> + +#define DB_ELF_SYMBOLS +#define DB_ELFSIZE 32 + +#define BYTE_MSF (1) + +typedef vm_offset_t db_addr_t; /* address - unsigned */ +typedef int db_expr_t; /* expression - signed */ + +#define PC_REGS(regs) ((db_addr_t)kdb_thrctx->pcb_lr) + +#define BKPT_INST 0x7C810808 /* breakpoint instruction */ + +#define BKPT_SIZE (4) /* size of breakpoint inst */ +#define BKPT_SET(inst) (BKPT_INST) + +#define db_clear_single_step kdb_cpu_clear_singlestep +#define db_set_single_step kdb_cpu_set_singlestep + +#if 0 +#define SR_SINGLESTEP 0x400 +#define db_clear_single_step(regs) ((regs)->msr &= ~SR_SINGLESTEP) +#define db_set_single_step(regs) ((regs)->msr |= SR_SINGLESTEP) +#endif + +#define T_BREAKPOINT 0xffff +#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BREAKPOINT) + +#define T_WATCHPOINT 0xeeee +#ifdef T_WATCHPOINT +#define IS_WATCHPOINT_TRAP(type, code) ((type) == T_WATCHPOINT) +#else +#define IS_WATCHPOINT_TRAP(type, code) 0 +#endif + +#define M_RTS 0xfc0007fe +#define I_RTS 0x4c000020 +#define M_BC 0xfc000000 +#define I_BC 0x40000000 +#define M_B 0xfc000000 +#define I_B 0x50000000 +#define M_RFI 0xfc0007fe +#define I_RFI 0x4c000064 + +#define inst_trap_return(ins) (((ins)&M_RFI) == I_RFI) +#define inst_return(ins) (((ins)&M_RTS) == I_RTS) +#define inst_call(ins) (((ins)&M_BC ) == I_BC || \ + ((ins)&M_B ) == I_B ) +#define inst_load(ins) 0 +#define inst_store(ins) 0 + +#define DB_SMALL_VALUE_MAX (0x7fffffff) +#define DB_SMALL_VALUE_MIN (-0x40001) + +#endif /* _POWERPC_DB_MACHDEP_H_ */ diff --git a/sys/powerpc/include/elf.h b/sys/powerpc/include/elf.h new file mode 100644 index 000000000000..d2b8e12107d8 --- /dev/null +++ b/sys/powerpc/include/elf.h @@ -0,0 +1,101 @@ +/*- + * Copyright (c) 2001 David E. O'Brien + * Copyright (c) 1996-1997 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_ELF_H_ +#define _MACHINE_ELF_H_ 1 + +/* + * EABI ELF definitions for the PowerPC architecture. + * See "PowerPC Embedded Application Binary Interface, 32-Bit Impliementation" + * [ppc-eabi-1995-01.pdf] for details. + */ + +#include <sys/elf32.h> /* Definitions common to all 32 bit architectures. */ + +#define __ELF_WORD_SIZE 32 /* Used by <sys/elf_generic.h> */ +#include <sys/elf_generic.h> + +#define ELF_ARCH EM_PPC + +#define ELF_MACHINE_OK(x) ((x) == EM_PPC) + +/* + * Auxiliary vector entries for passing information to the interpreter. + * + * The PowerPC supplement to the SVR4 ABI specification names this "auxv_t", + * but POSIX lays claim to all symbols ending with "_t". + */ + +typedef struct { /* Auxiliary vector entry on initial stack */ + int a_type; /* Entry type. */ + union { + long a_val; /* Integer value. */ + void *a_ptr; /* Address. */ + void (*a_fcn)(void); /* Function pointer (not used). */ + } a_un; +} Elf32_Auxinfo; + +__ElfType(Auxinfo); + +/* Values for a_type. */ +#define AT_NULL 0 /* Terminates the vector. */ +#define AT_IGNORE 1 /* Ignored entry. */ +#define AT_EXECFD 2 /* File descriptor of program to load. */ +#define AT_PHDR 3 /* Program header of program already loaded. */ +#define AT_PHENT 4 /* Size of each program header entry. */ +#define AT_PHNUM 5 /* Number of program header entries. */ +#define AT_PAGESZ 6 /* Page size in bytes. */ +#define AT_BASE 7 /* Interpreter's base address. */ +#define AT_FLAGS 8 /* Flags (unused for PowerPC). */ +#define AT_ENTRY 9 /* Where interpreter should transfer control. */ +#define AT_DCACHEBSIZE 10 /* Data cache block size for the processor. */ +#define AT_ICACHEBSIZE 11 /* Instruction cache block size for the uP. */ +#define AT_UCACHEBSIZE 12 /* Cache block size, or `0' if cache not unified. */ + +#define AT_COUNT 13 /* Count of defined aux entry types. */ + +/* Used in John Polstra's testbed stuff. */ +#define AT_DEBUG 14 /* Debugging level. */ + +/* + * Relocation types. + */ + +#define R_PPC_COUNT 37 /* Count of defined relocation types. */ + + /* Count of defined relocation types. */ +#define R_PPC_EMB_COUNT (R_PPC_EMB_RELSDA - R_PPC_EMB_NADDR32 + 1) + +/* Define "machine" characteristics */ +#define ELF_TARG_CLASS ELFCLASS32 +#define ELF_TARG_DATA ELFDATA2MSB +#define ELF_TARG_MACH EM_PPC +#define ELF_TARG_VER 1 + +#endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/powerpc/include/endian.h b/sys/powerpc/include/endian.h new file mode 100644 index 000000000000..bc96b9e4fc81 --- /dev/null +++ b/sys/powerpc/include/endian.h @@ -0,0 +1,111 @@ +/*- + * Copyright (c) 1987, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)endian.h 8.1 (Berkeley) 6/10/93 + * $NetBSD: endian.h,v 1.7 1999/08/21 05:53:51 simonb Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_ENDIAN_H_ +#define _MACHINE_ENDIAN_H_ + +#include <sys/cdefs.h> +#include <sys/_types.h> + +/* + * Define the order of 32-bit words in 64-bit words. + */ +#define _QUAD_HIGHWORD 0 +#define _QUAD_LOWWORD 1 + +/* + * Definitions for byte order, according to byte significance from low + * address to high. + */ +#undef _BIG_ENDIAN /* GCC annoyingly defines this for PowerPC */ +#define _LITTLE_ENDIAN 1234 /* LSB first: i386, vax */ +#define _BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */ +#define _PDP_ENDIAN 3412 /* LSB first in word, MSW first in long */ + +#define _BYTE_ORDER _BIG_ENDIAN + +/* + * Deprecated variants that don't have enough underscores to be useful in more + * strict namespaces. + */ +#if __BSD_VISIBLE +#define LITTLE_ENDIAN _LITTLE_ENDIAN +#define BIG_ENDIAN _BIG_ENDIAN +#define PDP_ENDIAN _PDP_ENDIAN +#define BYTE_ORDER _BYTE_ORDER +#endif + +#ifdef __CC_SUPPORTS___INLINE + +static __inline __uint16_t +__bswap16(__uint16_t _x) +{ + + return ((_x >> 8) | ((_x << 8) & 0xff00)); +} + +static __inline __uint32_t +__bswap32(__uint32_t _x) +{ + + return ((_x >> 24) | ((_x >> 8) & 0xff00) | ((_x << 8) & 0xff0000) | + ((_x << 24) & 0xff000000)); +} + +static __inline __uint64_t +__bswap64(__uint64_t _x) +{ + + return ((_x >> 56) | ((_x >> 40) & 0xff00) | ((_x >> 24) & 0xff0000) | + ((_x >> 8) & 0xff000000) | ((_x << 8) & ((__uint64_t)0xff << 32)) | + ((_x << 24) & ((__uint64_t)0xff << 40)) | + ((_x << 40) & ((__uint64_t)0xff << 48)) | ((_x << 56))); +} + +#define __htonl(x) ((__uint32_t)(x)) +#define __htons(x) ((__uint16_t)(x)) +#define __ntohl(x) ((__uint32_t)(x)) +#define __ntohs(x) ((__uint16_t)(x)) + +#else /* !__CC_SUPPORTS___INLINE */ + +/* + * No optimizations are available for this compiler. Fall back to + * non-optimized functions by defining the constant usually used to prevent + * redefinition. + */ +#define _BYTEORDER_FUNC_DEFINED + +#endif /* __CC_SUPPORTS___INLINE */ + +#endif /* !_MACHINE_ENDIAN_H_ */ diff --git a/sys/powerpc/include/exec.h b/sys/powerpc/include/exec.h new file mode 100644 index 000000000000..f5a2bb26f61f --- /dev/null +++ b/sys/powerpc/include/exec.h @@ -0,0 +1,37 @@ +/*- + * Copyright (c) 2001 David E. O'Brien + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_EXEC_H_ +#define _MACHINE_EXEC_H_ + +#define __LDPGSZ 4096 + +#endif /* !_MACHINE_EXEC_H_ */ diff --git a/sys/powerpc/include/float.h b/sys/powerpc/include/float.h new file mode 100644 index 000000000000..5ac715a04180 --- /dev/null +++ b/sys/powerpc/include/float.h @@ -0,0 +1,80 @@ +/*- + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)float.h 7.1 (Berkeley) 5/8/90 + * from: FreeBSD: src/sys/i386/include/float.h,v 1.8 1999/08/28 00:44:11 + * $FreeBSD$ + */ + +#ifndef _MACHINE_FLOAT_H_ +#define _MACHINE_FLOAT_H_ 1 + +#include <sys/cdefs.h> + +__BEGIN_DECLS +extern int __flt_rounds(void); +__END_DECLS + +#define FLT_RADIX 2 /* b */ +#define FLT_ROUNDS __flt_rounds() +#if __ISO_C_VISIBLE >= 1999 +#define FLT_EVAL_METHOD 1 /* operands promoted to double */ +#define DECIMAL_DIG 35 /* max precision in decimal digits */ +#endif + +#define FLT_MANT_DIG 24 /* p */ +#define FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define FLT_MIN_EXP (-125) /* emin */ +#define FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define FLT_MAX_EXP 128 /* emax */ +#define FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ +#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define DBL_MANT_DIG 53 +#define DBL_EPSILON 2.2204460492503131E-16 +#define DBL_DIG 15 +#define DBL_MIN_EXP (-1021) +#define DBL_MIN 2.2250738585072014E-308 +#define DBL_MIN_10_EXP (-307) +#define DBL_MAX_EXP 1024 +#define DBL_MAX 1.7976931348623157E+308 +#define DBL_MAX_10_EXP 308 + +#define LDBL_MANT_DIG DBL_MANT_DIG +#define LDBL_EPSILON DBL_EPSILON +#define LDBL_DIG DBL_DIG +#define LDBL_MIN_EXP DBL_MIN_EXP +#define LDBL_MIN DBL_MIN +#define LDBL_MIN_10_EXP DBL_MIN_10_EXP +#define LDBL_MAX_EXP DBL_MAX_EXP +#define LDBL_MAX DBL_MAX +#define LDBL_MAX_10_EXP DBL_MAX_10_EXP + +#endif /* _MACHINE_FLOAT_H_ */ diff --git a/sys/powerpc/include/floatingpoint.h b/sys/powerpc/include/floatingpoint.h new file mode 100644 index 000000000000..e62e47415a74 --- /dev/null +++ b/sys/powerpc/include/floatingpoint.h @@ -0,0 +1,37 @@ +/*- + * Copyright (c) 2004 Suleiman Souhlal <refugee@segfaulted.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY DAVID O'BRIEN AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _FLOATINGPOINT_H_ +#define _FLOATINGPOINT_H_ + +#include <machine/ieeefp.h> + +#endif /* !_FLOATINGPOINT_H_ */ diff --git a/sys/powerpc/include/fpu.h b/sys/powerpc/include/fpu.h new file mode 100644 index 000000000000..d712b9458903 --- /dev/null +++ b/sys/powerpc/include/fpu.h @@ -0,0 +1,82 @@ +/*- + * Copyright (C) 1996 Wolfgang Solfrank. + * Copyright (C) 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: fpu.h,v 1.2 1999/12/07 15:14:56 danw Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_FPU_H_ +#define _MACHINE_FPU_H_ + +#define FPSCR_FX 0x80000000 +#define FPSCR_FEX 0x40000000 +#define FPSCR_VX 0x20000000 +#define FPSCR_OX 0x10000000 +#define FPSCR_UX 0x08000000 +#define FPSCR_ZX 0x04000000 +#define FPSCR_XX 0x02000000 +#define FPSCR_VXSNAN 0x01000000 +#define FPSCR_VXISI 0x00800000 +#define FPSCR_VXIDI 0x00400000 +#define FPSCR_VXZDZ 0x00200000 +#define FPSCR_VXIMZ 0x00100000 +#define FPSCR_VXVC 0x00080000 +#define FPSCR_FR 0x00040000 +#define FPSCR_FI 0x00020000 +#define FPSCR_FPRF 0x0001f000 +#define FPSCR_C 0x00010000 +#define FPSCR_FPCC 0x0000f000 +#define FPSCR_FL 0x00008000 +#define FPSCR_FG 0x00004000 +#define FPSCR_FE 0x00002000 +#define FPSCR_FU 0x00001000 +#define FPSCR_VXSOFT 0x00000400 +#define FPSCR_VXSQRT 0x00000200 +#define FPSCR_VXCVI 0x00000100 +#define FPSCR_VE 0x00000080 +#define FPSCR_OE 0x00000040 +#define FPSCR_UE 0x00000020 +#define FPSCR_ZE 0x00000010 +#define FPSCR_XE 0x00000008 +#define FPSCR_NI 0x00000004 +#define FPSCR_RN 0x00000003 + +#ifdef _KERNEL + +/* List of PowerPC architectures that support FPUs. */ +#if defined(OEA) +#define PPC_HAVE_FPU + +void enable_fpu(struct thread *); +void save_fpu(struct thread *); +#endif /* PPC_HAVE_FPU */ +#endif /* _KERNEL */ + +#endif /* _MACHINE_FPU_H_ */ diff --git a/sys/powerpc/include/frame.h b/sys/powerpc/include/frame.h new file mode 100644 index 000000000000..09b7a9517771 --- /dev/null +++ b/sys/powerpc/include/frame.h @@ -0,0 +1,84 @@ +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: frame.h,v 1.2 1999/01/10 10:13:15 tsubai Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_FRAME_H_ +#define _MACHINE_FRAME_H_ + +#include <sys/types.h> + +/* + * We have to save all registers on every trap, because + * 1. user could attach this process every time + * 2. we must be able to restore all user registers in case of fork + * Actually, we do not save the fp registers on trap, since + * these are not used by the kernel. They are saved only when switching + * between processes using the FPU. + * + * Change ordering to cluster together these register_t's. XXX + */ +struct trapframe { + register_t fixreg[32]; + register_t lr; + int cr; + int xer; + register_t ctr; + register_t srr0; + register_t srr1; + register_t dar; /* dar & dsisr are only filled on a DSI trap */ + int dsisr; + int exc; +}; +/* + * This is to ensure alignment of the stackpointer + */ +#define FRAMELEN roundup(sizeof(struct trapframe) + 8, 16) +#define trapframe(td) ((td)->td_frame) + +/* + * Call frame for PowerPC used during fork. + */ +struct callframe { + register_t cf_dummy_fp; /* dummy frame pointer */ + register_t cf_lr; /* space for link register save */ + register_t cf_func; + register_t cf_arg0; + register_t cf_arg1; +}; + +/* Definitions for syscalls */ +#define FIRSTARG 3 /* first arg in reg 3 */ +#define NARGREG 8 /* 8 args in regs */ +#define MOREARGS(sp) ((caddr_t)((int)(sp) + 8)) /* more args go here */ + +#endif /* _MACHINE_FRAME_H_ */ diff --git a/sys/powerpc/include/gdb_machdep.h b/sys/powerpc/include/gdb_machdep.h new file mode 100644 index 000000000000..e8c5055fdf5a --- /dev/null +++ b/sys/powerpc/include/gdb_machdep.h @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 2006 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_GDB_MACHDEP_H_ +#define _MACHINE_GDB_MACHDEP_H_ + +#define GDB_NREGS 153 +#define GDB_REG_PC 64 + +#define GDB_BUFSZ (GDB_NREGS*4) + +static __inline size_t +gdb_cpu_regsz(int regnum) +{ + return (sizeof(int)); +} + +static __inline int +gdb_cpu_query(void) +{ + return (0); +} + +void *gdb_cpu_getreg(int, size_t *); +void gdb_cpu_setreg(int, void *); +int gdb_cpu_signal(int, int); + +#endif /* !_MACHINE_GDB_MACHDEP_H_ */ diff --git a/sys/powerpc/include/hid.h b/sys/powerpc/include/hid.h new file mode 100644 index 000000000000..3739839af252 --- /dev/null +++ b/sys/powerpc/include/hid.h @@ -0,0 +1,137 @@ +/*- + * Copyright (c) 2000 Tsubai Masanari. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: hid.h,v 1.2 2001/08/22 21:05:25 matt Exp $ + * $FreeBSD$ + */ + +#ifndef _POWERPC_HID_H_ +#define _POWERPC_HID_H_ + +/* Hardware Implementation Dependent registers for the PowerPC */ + +#define HID0_EMCP 0x80000000 /* Enable MCP */ +#define HID0_DBP 0x40000000 /* Disable 60x bus parity generation */ +#define HID0_EBA 0x20000000 /* Enable 60x bus address parity checking */ +#define HID0_EBD 0x10000000 /* Enable 60x bus data parity checking */ +#define HID0_BCLK 0x08000000 /* CLK_OUT clock type selection */ +#define HID0_EICE 0x04000000 /* Enable ICE output */ +#define HID0_TBEN 0x04000000 /* Time base enable (7450) */ +#define HID0_ECLK 0x02000000 /* CLK_OUT clock type selection */ +#define HID0_PAR 0x01000000 /* Disable precharge of ARTRY */ +#define HID0_STEN 0x01000000 /* Software table search enable (7450) */ +#define HID0_HBATEN 0x00800000 /* High BAT enable (74[45][578]) */ +#define HID0_DOZE 0x00800000 /* Enable doze mode */ +#define HID0_NAP 0x00400000 /* Enable nap mode */ +#define HID0_SLEEP 0x00200000 /* Enable sleep mode */ +#define HID0_DPM 0x00100000 /* Enable Dynamic power management */ +#define HID0_RISEG 0x00080000 /* Read I-SEG */ +#define HID0_BHTCLR 0x00040000 /* Clear branch history table (7450) */ +#define HID0_EIEC 0x00040000 /* Enable internal error checking */ +#define HID0_XAEN 0x00020000 /* Enable eXtended Addressing (7450) */ +#define HID0_NHR 0x00010000 /* Not hard reset */ +#define HID0_ICE 0x00008000 /* Enable i-cache */ +#define HID0_DCE 0x00004000 /* Enable d-cache */ +#define HID0_ILOCK 0x00002000 /* i-cache lock */ +#define HID0_DLOCK 0x00001000 /* d-cache lock */ +#define HID0_ICFI 0x00000800 /* i-cache flush invalidate */ +#define HID0_DCFI 0x00000400 /* d-cache flush invalidate */ +#define HID0_SPD 0x00000200 /* Disable speculative cache access */ +#define HID0_XBSEN 0x00000100 /* Extended BAT block-size enable (7457) */ +#define HID0_IFEM 0x00000100 /* Enable M-bit for I-fetch */ +#define HID0_XBSEN 0x00000100 /* Extended BAT block size enable (7455+)*/ +#define HID0_SGE 0x00000080 /* Enable store gathering */ +#define HID0_DCFA 0x00000040 /* Data cache flush assist */ +#define HID0_BTIC 0x00000020 /* Enable BTIC */ +#define HID0_LRSTK 0x00000010 /* Link register stack enable (7450) */ +#define HID0_ABE 0x00000008 /* Enable address broadcast */ +#define HID0_FOLD 0x00000008 /* Branch folding enable (7450) */ +#define HID0_BHT 0x00000004 /* Enable branch history table */ +#define HID0_NOPTI 0x00000001 /* No-op the dcbt(st) */ + +#define HID0_BITMASK \ + "\20" \ + "\040EMCP\037DBP\036EBA\035EBD\034BCLK\033EICE\032ECLK\031PAR" \ + "\030DOZE\027NAP\026SLEEP\025DPM\024RISEG\023EIEC\022res\021NHR" \ + "\020ICE\017DCE\016ILOCK\015DLOCK\014ICFI\013DCFI\012SPD\011IFEM" \ + "\010SGE\007DCFA\006BTIC\005FBIOB\004ABE\003BHT\002NOPDST\001NOPTI" + +#define HID0_7450_BITMASK \ + "\20" \ + "\040EMCP\037b1\036b2\035b3\034b4\033TBEN\032b6\031STEN" \ + "\030HBATEN\027NAP\026SLEEP\025DPM\024b12\023BHTCLR\022XAEN\021NHR" \ + "\020ICE\017DCE\016ILOCK\015DLOCK\014ICFI\013DCFI\012SPD\011XBSEN" \ + "\010SGE\007b25\006BTIC\005LRSTK\004FOLD\003BHT\002NOPDST\001NOPTI" + +/* + * HID0 bit definitions per cpu model + * + * bit 603 604 750 7400 7410 7450 7457 + * 0 EMCP EMCP EMCP EMCP EMCP - - + * 1 - ECP DBP - - - - + * 2 EBA EBA EBA EBA EDA - - + * 3 EBD EBD EBD EBD EBD - - + * 4 SBCLK - BCLK BCKL BCLK - - + * 5 EICE - - - - TBEN TBEN + * 6 ECLK - ECLK ECLK ECLK - - + * 7 PAR PAR PAR PAR PAR STEN STEN + * 8 DOZE - DOZE DOZE DOZE - HBATEN + * 9 NAP - NAP NAP NAP NAP NAP + * 10 SLEEP - SLEEP SLEEP SLEEP SLEEP SLEEP + * 11 DPM - DPM DPM DPM DPM DPM + * 12 RISEG - - RISEG - - - + * 13 - - - EIEC EIEC BHTCLR BHTCLR + * 14 - - - - - XAEN XAEN + * 15 - NHR NHR NHR NHR NHR NHR + * 16 ICE ICE ICE ICE ICE ICE ICE + * 17 DCE DCE DCE DCE DCE DCE DCE + * 18 ILOCK ILOCK ILOCK ILOCK ILOCK ILOCK ILOCK + * 19 DLOCK DLOCK DLOCK DLOCK DLOCK DLOCK DLOCK + * 20 ICFI ICFI ICFI ICFI ICFI ICFI ICFI + * 21 DCFI DCFI DCFI DCFI DCFI DCFI DCFI + * 22 - - SPD SPD SPG SPD SPD + * 23 - - IFEM IFTT IFTT - XBSEN + * 24 - SIE SGE SGE SGE SGE SGE + * 25 - - DCFA DCFA DCFA - - + * 26 - - BTIC BTIC BTIC BTIC BTIC + * 27 FBIOB - - - - LRSTK LRSTK + * 28 - - ABE - - FOLD FOLD + * 29 - BHT BHT BHT BHT BHT BHT + * 30 - - - NOPDST NOPDST NOPDST NOPDST + * 31 NOOPTI - NOOPTI NOPTI NOPTI NOPTI NOPTI + * + * 604: ECP = Enable cache parity checking + * 604: SIE = Serial instruction execution disable + * 7450: TBEN = Time Base Enable + * 7450: STEN = Software table lookup enable + * 7450: BHTCLR = Branch history clear + * 7450: XAEN = Extended Addressing Enabled + * 7450: LRSTK = Link Register Stack Enable + * 7450: FOLD = Branch folding enable + * 7457: HBATEN = High BAT Enable + * 7457: XBSEN = Extended BAT Block Size Enable + */ + +#endif /* _POWERPC_HID_H_ */ diff --git a/sys/powerpc/include/ieee.h b/sys/powerpc/include/ieee.h new file mode 100644 index 000000000000..793012de4435 --- /dev/null +++ b/sys/powerpc/include/ieee.h @@ -0,0 +1,142 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + * from: NetBSD: ieee.h,v 1.1.1.1 1998/06/20 04:58:51 eeh Exp + * $FreeBSD$ + */ + +#ifndef _MACHINE_IEEE_H_ +#define _MACHINE_IEEE_H_ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACBITS 52 + +#ifdef notyet +#define E80_EXPBITS 15 +#define E80_FRACBITS 64 +#endif + +#define EXT_EXPBITS 15 +#define EXT_FRACBITS 112 + +struct ieee_single { + u_int sng_sign:1; + u_int sng_exp:8; + u_int sng_frac:23; +}; + +struct ieee_double { + u_int dbl_sign:1; + u_int dbl_exp:11; + u_int dbl_frach:20; + u_int dbl_fracl; +}; + +struct ieee_ext { + u_int ext_sign:1; + u_int ext_exp:15; + u_int ext_frach:16; + u_int ext_frachm; + u_int ext_fraclm; + u_int ext_fracl; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define EXT_EXP_BIAS 16383 + +#endif diff --git a/sys/powerpc/include/ieeefp.h b/sys/powerpc/include/ieeefp.h new file mode 100644 index 000000000000..820fffe1cd9c --- /dev/null +++ b/sys/powerpc/include/ieeefp.h @@ -0,0 +1,25 @@ +/* - + * Written by J.T. Conklin, Apr 6, 1995 + * Public domain. + * $NetBSD: ieeefp.h,v 1.2 1999/07/07 01:52:26 danw Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_IEEEFP_H_ +#define _MACHINE_IEEEFP_H_ + +typedef int fp_except_t; +#define FP_X_IMP 0x01 /* imprecise (loss of precision) */ +#define FP_X_DZ 0x02 /* divide-by-zero exception */ +#define FP_X_UFL 0x04 /* underflow exception */ +#define FP_X_OFL 0x08 /* overflow exception */ +#define FP_X_INV 0x10 /* invalid operation exception */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RZ=1, /* round to zero (truncate) */ + FP_RP=2, /* round toward positive infinity */ + FP_RM=3 /* round toward negative infinity */ +} fp_rnd_t; + +#endif /* _MACHINE_IEEEFP_H_ */ diff --git a/sys/powerpc/include/in_cksum.h b/sys/powerpc/include/in_cksum.h new file mode 100644 index 000000000000..09920062a0ae --- /dev/null +++ b/sys/powerpc/include/in_cksum.h @@ -0,0 +1,76 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from tahoe: in_cksum.c 1.2 86/01/05 + * from: @(#)in_cksum.c 1.3 (Berkeley) 1/19/91 + * from: Id: in_cksum.c,v 1.8 1995/12/03 18:35:19 bde Exp + * $FreeBSD$ + */ + +#ifndef _MACHINE_IN_CKSUM_H_ +#define _MACHINE_IN_CKSUM_H_ 1 + +#include <sys/cdefs.h> + +#define in_cksum(m, len) in_cksum_skip(m, len, 0) + +/* + * It it useful to have an Internet checksum routine which is inlineable + * and optimized specifically for the task of computing IP header checksums + * in the normal case (where there are no options and the header length is + * therefore always exactly five 32-bit words. + */ +#ifdef __CC_SUPPORTS___INLINE + +static __inline void +in_cksum_update(struct ip *ip) +{ + int __tmpsum; + __tmpsum = (int)ntohs(ip->ip_sum) + 256; + ip->ip_sum = htons(__tmpsum + (__tmpsum >> 16)); +} + +#else + +#define in_cksum_update(ip) \ + do { \ + int __tmpsum; \ + __tmpsum = (int)ntohs(ip->ip_sum) + 256; \ + ip->ip_sum = htons(__tmpsum + (__tmpsum >> 16)); \ + } while(0) + +#endif + +#ifdef _KERNEL +u_int in_cksum_hdr(const struct ip *ip); +u_short in_addword(u_short sum, u_short b); +u_short in_pseudo(u_int sum, u_int b, u_int c); +u_short in_cksum_skip(struct mbuf *m, int len, int skip); +#endif + +#endif /* _MACHINE_IN_CKSUM_H_ */ diff --git a/sys/powerpc/include/intr.h b/sys/powerpc/include/intr.h new file mode 100644 index 000000000000..8bc417c6a9bd --- /dev/null +++ b/sys/powerpc/include/intr.h @@ -0,0 +1,164 @@ +/*- + * 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. + * + * $NetBSD: intr.h,v 1.6 2000/02/11 13:15:44 tsubai Exp $ + * $FreeBSD$ + */ + +#ifndef _MACPPC_INTR_H_ +#define _MACPPC_INTR_H_ + +/* Interrupt priority `levels'. */ +#define IPL_NONE 9 /* nothing */ +#define IPL_SOFTCLOCK 8 /* timeouts */ +#define IPL_SOFTNET 7 /* protocol stacks */ +#define IPL_BIO 6 /* block I/O */ +#define IPL_NET 5 /* network */ +#define IPL_SOFTSERIAL 4 /* serial */ +#define IPL_TTY 3 /* terminal */ +#define IPL_IMP 3 /* memory allocation */ +#define IPL_AUDIO 2 /* audio */ +#define IPL_CLOCK 1 /* clock */ +#define IPL_HIGH 1 /* everything */ +#define IPL_SERIAL 0 /* serial */ +#define NIPL 10 + +/* Interrupt sharing types. */ +#define IST_NONE 0 /* none */ +#define IST_PULSE 1 /* pulsed */ +#define IST_EDGE 2 /* edge-triggered */ +#define IST_LEVEL 3 /* level-triggered */ + +#ifndef LOCORE + +#if 0 +/* + * Interrupt handler chains. intr_establish() inserts a handler into + * the list. The handler is called with its (single) argument. + */ +struct intrhand { + int (*ih_fun)(void *); + void *ih_arg; + u_long ih_count; + struct intrhand *ih_next; + int ih_level; + int ih_irq; +}; +#endif + +void setsoftclock(void); +void clearsoftclock(void); +void setsoftnet(void); +void clearsoftnet(void); + +void do_pending_int(void); + +static __inline void softintr(int); + +extern u_int cpl, ipending, tickspending; +extern int imask[]; + +/* Following code should be implemented with lwarx/stwcx to avoid + * the disable/enable. i need to read the manual once more.... */ +static __inline void +softintr(int ipl) +{ + unsigned int msrsave; + + msrsave = mfmsr(); + mtmsr(msrsave & ~PSL_EE); + + ipending |= 1 << ipl; + + mtmsr(msrsave); +} + +#define ICU_LEN 64 + +/* Soft interrupt masks. */ +#define SIR_CLOCK 28 +#define SIR_NET 29 +#define SIR_SERIAL 30 +#define SPL_CLOCK 31 + +#if 0 + +/* + * Hardware interrupt masks + */ + +#define splbio() splraise(imask[IPL_BIO]) +#define splnet() splraise(imask[IPL_NET]) +#define spltty() splraise(imask[IPL_TTY]) +#define splaudio() splraise(imask[IPL_AUDIO]) +#define splclock() splraise(imask[IPL_CLOCK]) +#define splstatclock() splclock() +#define splserial() splraise(imask[IPL_SERIAL]) + +#define spllpt() spltty() + +/* + * Software interrupt masks + * + * NOTE: splsoftclock() is used by hardclock() to lower the priority from + * clock to softclock before it calls softclock(). + */ +#define spllowersoftclock() spllower(imask[IPL_SOFTCLOCK]) +#define splsoftclock() splraise(imask[IPL_SOFTCLOCK]) +#define splsoftnet() splraise(imask[IPL_SOFTNET]) +#define splsoftserial() splraise(imask[IPL_SOFTSERIAL]) + +/* + * Miscellaneous + */ +#define splimp() splraise(imask[IPL_IMP]) +#define splhigh() splraise(imask[IPL_HIGH]) +#define spl0() spllower(0) + +#endif /* 0 */ + +#define setsoftclock() softintr(SIR_CLOCK) +#define setsoftnet() softintr(SIR_NET) +#define setsoftserial() softintr(SIR_SERIAL) + +#define CNT_IRQ0 0 +#define CNT_CLOCK 64 +#define CNT_SOFTCLOCK 65 +#define CNT_SOFTNET 66 +#define CNT_SOFTSERIAL 67 + +#endif /* !LOCORE */ + +#endif /* !_MACPPC_INTR_H_ */ diff --git a/sys/powerpc/include/intr_machdep.h b/sys/powerpc/include/intr_machdep.h new file mode 100644 index 000000000000..25f47f0301c8 --- /dev/null +++ b/sys/powerpc/include/intr_machdep.h @@ -0,0 +1,45 @@ +/*- + * Copyright (C) 2002 Benno Rice. + * 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 Benno Rice ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_INTR_MACHDEP_H_ +#define _MACHINE_INTR_MACHDEP_H_ + +#define INTR_VECTORS 256 + +extern device_t pic; + +struct trapframe; + +void powerpc_register_pic(device_t); + +void powerpc_dispatch_intr(u_int, struct trapframe *); +int powerpc_enable_intr(void); +int powerpc_setup_intr(const char *, u_int, driver_filter_t, + driver_intr_t, void *, enum intr_type, void **); +int powerpc_teardown_intr(void *); + +#endif /* _MACHINE_INTR_MACHDEP_H_ */ diff --git a/sys/powerpc/include/kdb.h b/sys/powerpc/include/kdb.h new file mode 100644 index 000000000000..2cb49a801b08 --- /dev/null +++ b/sys/powerpc/include/kdb.h @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2004 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_KDB_H_ +#define _MACHINE_KDB_H_ + +#include <machine/cpufunc.h> +#include <machine/frame.h> +#include <machine/md_var.h> +#include <machine/psl.h> + +static __inline void +kdb_cpu_clear_singlestep(void) +{ + kdb_frame->srr1 &= ~PSL_SE; +} + +static __inline void +kdb_cpu_set_singlestep(void) +{ + kdb_frame->srr1 |= PSL_SE; +} + +static __inline void +kdb_cpu_sync_icache(unsigned char *addr, size_t size) +{ + __syncicache(addr, size); +} + +static __inline void +kdb_cpu_trap(int vector, int _) +{ +} + +#endif /* _MACHINE_KDB_H_ */ diff --git a/sys/powerpc/include/limits.h b/sys/powerpc/include/limits.h new file mode 100644 index 000000000000..35eea1f619de --- /dev/null +++ b/sys/powerpc/include/limits.h @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)limits.h 8.3 (Berkeley) 1/4/94 + * $FreeBSD$ + */ + +#ifndef _MACHINE_LIMITS_H_ +#define _MACHINE_LIMITS_H_ + +#include <sys/cdefs.h> + +#ifdef __CC_SUPPORTS_WARNING +#warning "machine/limits.h is deprecated. Include sys/limits.h instead." +#endif + +#include <sys/limits.h> + +#endif /* !_MACHINE_LIMITS_H_ */ diff --git a/sys/powerpc/include/md_var.h b/sys/powerpc/include/md_var.h new file mode 100644 index 000000000000..567b190876b8 --- /dev/null +++ b/sys/powerpc/include/md_var.h @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_MD_VAR_H_ +#define _MACHINE_MD_VAR_H_ + +/* + * Miscellaneous machine-dependent declarations. + */ + +extern char sigcode[]; +extern char esigcode[]; +extern int szsigcode; +extern long Maxmem; +extern int busdma_swi_pending; + +extern vm_offset_t kstack0; +extern vm_offset_t kstack0_phys; + +extern u_long ns_per_tick; + +#if defined(_KERNEL) || defined(_STANDALONE) +#define CACHELINESIZE 32 +#endif + +void __syncicache(void *, int); + +void busdma_swi(void); +int is_physical_memory(vm_offset_t addr); +int mem_valid(vm_offset_t addr, int len); + +void decr_init(void); +void decr_tc_init(void); + +void cpu_setup(u_int); + +struct trapframe; +void powerpc_interrupt(struct trapframe *); + +#endif /* !_MACHINE_MD_VAR_H_ */ diff --git a/sys/powerpc/include/memdev.h b/sys/powerpc/include/memdev.h new file mode 100644 index 000000000000..69072d9889ca --- /dev/null +++ b/sys/powerpc/include/memdev.h @@ -0,0 +1,40 @@ +/*- + * Copyright (c) 2004 Mark R V Murray + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#define CDEV_MAJOR 2 +#define CDEV_MINOR_MEM 0 +#define CDEV_MINOR_KMEM 1 + +d_open_t memopen; +d_read_t memrw; +#define memioctl (d_ioctl_t *)NULL +d_mmap_t memmmap; + +void dev_mem_md_init(void); + +MALLOC_DECLARE(M_MEMDEV); diff --git a/sys/powerpc/include/metadata.h b/sys/powerpc/include/metadata.h new file mode 100644 index 000000000000..124d46b1b551 --- /dev/null +++ b/sys/powerpc/include/metadata.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2001 Jake Burkholder. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_METADATA_H_ +#define _MACHINE_METADATA_H_ + +#define MODINFOMD_ENVP 0x1001 +#define MODINFOMD_HOWTO 0x1002 +#define MODINFOMD_KERNEND 0x1003 + +#endif /* !_MACHINE_METADATA_H_ */ diff --git a/sys/powerpc/include/mmuvar.h b/sys/powerpc/include/mmuvar.h new file mode 100644 index 000000000000..fc2f8d5c9ca5 --- /dev/null +++ b/sys/powerpc/include/mmuvar.h @@ -0,0 +1,96 @@ +/*- + * Copyright (c) 2005 Peter Grehan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_MMUVAR_H_ +#define _MACHINE_MMUVAR_H_ + +/* + * A PowerPC MMU implementation is declared with a kernel object and + * an associated method table, similar to a device driver. + * + * e.g. + * + * static mmu_method_t ppc8xx_methods[] = { + * MMUMETHOD(mmu_change_wiring, ppc8xx_mmu_change_wiring), + * MMUMETHOD(mmu_clear_modify, ppc8xx_mmu_clear_modify), + * MMUMETHOD(mmu_clear_reference, ppc8xx_mmu_clear_reference), + * ... + * MMUMETHOD(mmu_dev_direct_mapped, ppc8xx_mmu_dev_direct_mapped), + * { 0, 0 } + * }; + * + * static mmu_def_t ppc8xx_mmu = { + * "ppc8xx", + * ppc8xx_methods, + * sizeof(ppc8xx_mmu_softc), // or 0 if no softc + * }; + * + * MMU_DEF(ppc8xx_mmu); + */ + +#include <sys/kobj.h> + +struct mmu_kobj { + /* + * An MMU instance is a kernel object + */ + KOBJ_FIELDS; + + /* + * Utility elements that an instance may use + */ + struct mtx mmu_mtx; /* available for instance use */ + void *mmu_iptr; /* instance data pointer */ + + /* + * Opaque data that can be overlaid with an instance-private + * structure. MMU code can test that this is large enough at + * compile time with a sizeof() test againt it's softc. There + * is also a run-time test when the MMU kernel object is + * registered. + */ +#define MMU_OPAQUESZ 64 + u_int mmu_opaque[MMU_OPAQUESZ]; +}; + +typedef struct mmu_kobj *mmu_t; +typedef struct kobj_class mmu_def_t; +#define mmu_method_t kobj_method_t + +#define MMUMETHOD KOBJMETHOD + +#define MMU_DEF(name) DATA_SET(mmu_set, name) + +/* + * Known MMU names + */ +#define MMU_TYPE_OEA "mmu_oea" /* 32-bit OEA */ +#define MMU_TYPE_G5 "mmu_g5" /* 64-bit bridge (ibm 970) */ +#define MMU_TYPE_8xx "mmu_8xx" /* 8xx quicc TLB */ + +#endif /* _MACHINE_MMUVAR_H_ */ diff --git a/sys/powerpc/include/mutex.h b/sys/powerpc/include/mutex.h new file mode 100644 index 000000000000..0b7fe2633e26 --- /dev/null +++ b/sys/powerpc/include/mutex.h @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 1997 Berkeley Software Design, Inc. 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. Berkeley Software Design Inc's name may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from BSDI $Id: mutex.h,v 2.7.2.35 2000/04/27 03:10:26 cp Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_MUTEX_H_ +#define _MACHINE_MUTEX_H_ + +#ifdef LOCORE + +/* + * Simple assembly macros to get and release non-recursive spin locks + */ +#define MTX_ENTER(lck) \ + mfmsr r10; \ /* disable interrupts */ + rlwinm r0, r10, 0, 17, 15; \ + mtmsr r0; \ +1: li r11, MTX_LOCK; \ /* MTX_LOCK offset */ + lwarx r0, r11, lck; \ /* load current lock value */ + cmplwi r0, r1, MTX_UNOWNED; \ /* compare with unowned */ + beq 1; \ /* if owned, loop */ + lwz r0, PC_CURPROC(pcpup); \ /* load curproc */ + stwcx. r0, r11, lck; \ /* attempt to store */ + beq 1; \ /* loop if failed */ + sync; \ /* sync */ + eieio; \ /* sync */ + stw r10, MTX_SAVEINTR(lck) /* save flags */ + +#define MTX_EXIT(lck) \ + sync; \ /* sync */ + eieio; \ /* sync */ + li r0, MTX_UNOWNED; \ /* load in unowned */ + stw r0, MTX_LOCK(lck); \ /* store to lock */ + lwz r0, MTX_SAVEINTR(lck); \ /* load saved flags */ + mtmsr r0 /* enable interrupts */ + +#endif /* !LOCORE */ + +#endif /* __MACHINE_MUTEX_H */ diff --git a/sys/powerpc/include/nexusvar.h b/sys/powerpc/include/nexusvar.h new file mode 100644 index 000000000000..df8a0f69b92c --- /dev/null +++ b/sys/powerpc/include/nexusvar.h @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2001 by Thomas Moestl <tmm@FreeBSD.org>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_NEXUSVAR_H_ +#define _MACHINE_NEXUSVAR_H_ + +enum nexus_ivars { + NEXUS_IVAR_NODE, + NEXUS_IVAR_NAME, + NEXUS_IVAR_DEVICE_TYPE, + NEXUS_IVAR_COMPATIBLE, +}; + +/* + * Simplified accessors for nexus devices + * XXX: These should be made specializations of generic bus accessor macros + * instead of having multiple implementations around. + */ +#define NEXUS_ACCESSOR(var, ivar, type) \ + __BUS_ACCESSOR(nexus, var, NEXUS, ivar, type) + +NEXUS_ACCESSOR(node, NODE, phandle_t) +NEXUS_ACCESSOR(name, NAME, char *) +NEXUS_ACCESSOR(device_type, DEVICE_TYPE, char *) +NEXUS_ACCESSOR(compatible, COMPATIBLE, char *) + +#undef NEXUS_ACCESSOR + +/* + * Install the interrupt controller device + */ +int nexus_install_intcntlr(device_t); + +#endif /* _MACHINE_NEXUSVAR_H_ */ diff --git a/sys/powerpc/include/ofw_machdep.h b/sys/powerpc/include/ofw_machdep.h new file mode 100644 index 000000000000..a4b601e5499e --- /dev/null +++ b/sys/powerpc/include/ofw_machdep.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2001 by Thomas Moestl <tmm@FreeBSD.org>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_OFW_MACHDEP_H_ +#define _MACHINE_OFW_MACHDEP_H_ + +#include <sys/bus.h> + +int OF_decode_addr(phandle_t, int, bus_space_tag_t *, bus_space_handle_t *); +void OF_getetheraddr(device_t dev, u_char *addr); + +#endif /* _MACHINE_OFW_MACHDEP_H_ */ diff --git a/sys/powerpc/include/openpicreg.h b/sys/powerpc/include/openpicreg.h new file mode 100644 index 000000000000..2fa393d20fd2 --- /dev/null +++ b/sys/powerpc/include/openpicreg.h @@ -0,0 +1,109 @@ +/*- + * Copyright (c) 2000 Tsubai Masanari. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from NetBSD: openpicreg.h,v 1.3 2001/08/30 03:08:52 briggs Exp + * $FreeBSD$ + */ + +/* + * Size of OpenPIC register space + */ +#define OPENPIC_SIZE 0x40000 + +/* + * GLOBAL/TIMER register (IDU base + 0x1000) + */ + +/* feature reporting reg 0 */ +#define OPENPIC_FEATURE 0x1000 +#define OPENPIC_FEATURE_VERSION_MASK 0x000000ff +#define OPENPIC_FEATURE_LAST_CPU_MASK 0x00001f00 +#define OPENPIC_FEATURE_LAST_CPU_SHIFT 8 +#define OPENPIC_FEATURE_LAST_IRQ_MASK 0x07ff0000 +#define OPENPIC_FEATURE_LAST_IRQ_SHIFT 16 + +/* global config reg 0 */ +#define OPENPIC_CONFIG 0x1020 +#define OPENPIC_CONFIG_RESET 0x80000000 +#define OPENPIC_CONFIG_8259_PASSTHRU_DISABLE 0x20000000 + +/* interrupt configuration mode (direct or serial) */ +#define OPENPIC_ICR 0x1030 +#define OPENPIC_ICR_SERIAL_MODE (1 << 27) +#define OPENPIC_ICR_SERIAL_RATIO_MASK (0x7 << 28) +#define OPENPIC_ICR_SERIAL_RATIO_SHIFT 28 + +/* vendor ID */ +#define OPENPIC_VENDOR_ID 0x1080 + +/* processor initialization reg */ +#define OPENPIC_PROC_INIT 0x1090 + +/* IPI vector/priority reg */ +#define OPENPIC_IPI_VECTOR(ipi) (0x10a0 + (ipi) * 0x10) + +/* spurious intr. vector */ +#define OPENPIC_SPURIOUS_VECTOR 0x10e0 + + +/* + * INTERRUPT SOURCE register (IDU base + 0x10000) + */ + +/* interrupt vector/priority reg */ +#ifndef OPENPIC_SRC_VECTOR +#define OPENPIC_SRC_VECTOR(irq) (0x10000 + (irq) * 0x20) +#endif +#define OPENPIC_SENSE_LEVEL 0x00400000 +#define OPENPIC_SENSE_EDGE 0x00000000 +#define OPENPIC_POLARITY_POSITIVE 0x00800000 +#define OPENPIC_POLARITY_NEGATIVE 0x00000000 +#define OPENPIC_IMASK 0x80000000 +#define OPENPIC_ACTIVITY 0x40000000 +#define OPENPIC_PRIORITY_MASK 0x000f0000 +#define OPENPIC_PRIORITY_SHIFT 16 +#define OPENPIC_VECTOR_MASK 0x000000ff + +/* interrupt destination cpu */ +#ifndef OPENPIC_IDEST +#define OPENPIC_IDEST(irq) (0x10010 + (irq) * 0x20) +#endif + +/* + * PROCESSOR register (IDU base + 0x20000) + */ + +/* IPI command reg */ +#define OPENPIC_IPI(cpu, ipi) (0x20040 + (cpu) * 0x1000 + (ipi)) + +/* current task priority reg */ +#define OPENPIC_CPU_PRIORITY(cpu) (0x20080 + (cpu) * 0x1000) +#define OPENPIC_CPU_PRIORITY_MASK 0x0000000f + +/* interrupt acknowledge reg */ +#define OPENPIC_IACK(cpu) (0x200a0 + (cpu) * 0x1000) + +/* end of interrupt reg */ +#define OPENPIC_EOI(cpu) (0x200b0 + (cpu) * 0x1000) diff --git a/sys/powerpc/include/openpicvar.h b/sys/powerpc/include/openpicvar.h new file mode 100644 index 000000000000..081cf7aecfcf --- /dev/null +++ b/sys/powerpc/include/openpicvar.h @@ -0,0 +1,63 @@ +/*- + * Copyright (C) 2002 Benno Rice. + * 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 Benno Rice ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _POWERPC_OPENPICVAR_H_ +#define _POWERPC_OPENPICVAR_H_ + +#define OPENPIC_DEVSTR "OpenPIC Interrupt Controller" + +#define OPENPIC_IRQMAX 256 /* h/w allows more */ + +struct openpic_softc { + device_t sc_dev; + struct resource *sc_memr; + bus_space_tag_t sc_bt; + bus_space_handle_t sc_bh; + char *sc_version; + int sc_rid; + u_int sc_ncpu; + u_int sc_nirq; + int sc_psim; +}; + +extern devclass_t openpic_devclass; + +/* + * Bus-independent attach i/f + */ +int openpic_attach(device_t); + +/* + * PIC interface. + */ +void openpic_dispatch(device_t, struct trapframe *); +void openpic_enable(device_t, u_int, u_int); +void openpic_eoi(device_t, u_int); +void openpic_mask(device_t, u_int); +void openpic_unmask(device_t, u_int); + +#endif /* _POWERPC_OPENPICVAR_H_ */ diff --git a/sys/powerpc/include/param.h b/sys/powerpc/include/param.h new file mode 100644 index 000000000000..6a2018eab0d8 --- /dev/null +++ b/sys/powerpc/include/param.h @@ -0,0 +1,107 @@ +/*- + * Copyright (c) 2001 David E. O'Brien + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)param.h 5.8 (Berkeley) 6/28/91 + * $FreeBSD$ + */ + +/* + * Machine dependent constants for PowerPC (32-bit only currently) + */ + +/* + * Round p (pointer or byte index) up to a correctly-aligned value + * for all data types (int, long, ...). The result is unsigned int + * and must be cast to any desired pointer type. + */ +#ifndef _ALIGNBYTES +#define _ALIGNBYTES (sizeof(int) - 1) +#endif +#ifndef _ALIGN +#define _ALIGN(p) (((unsigned)(p) + _ALIGNBYTES) & ~_ALIGNBYTES) +#endif + +#ifndef _NO_NAMESPACE_POLLUTION + +#ifndef _MACHINE_PARAM_H_ +#define _MACHINE_PARAM_H_ + +#ifndef MACHINE +#define MACHINE "powerpc" +#endif +#ifndef MACHINE_ARCH +#define MACHINE_ARCH "powerpc" +#endif +#define MID_MACHINE MID_POWERPC + +#ifdef SMP +#define MAXCPU 2 +#else +#define MAXCPU 1 +#endif /* SMP */ + +#define ALIGNBYTES _ALIGNBYTES +#define ALIGN(p) _ALIGN(p) + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) /* Page size */ +#define PAGE_MASK (PAGE_SIZE - 1) +#define NPTEPG (PAGE_SIZE/(sizeof (pt_entry_t))) + +#ifndef KSTACK_PAGES +#define KSTACK_PAGES 4 /* includes pcb */ +#endif +#define KSTACK_GUARD_PAGES 1 /* pages of kstack guard; 0 disables */ +#define USPACE (KSTACK_PAGES * PAGE_SIZE) /* total size of pcb */ + +/* + * Mach derived conversion macros + */ +#define trunc_page(x) ((unsigned long)(x) & ~(PAGE_MASK)) +#define round_page(x) (((x) + PAGE_MASK) & ~PAGE_MASK) +#define trunc_4mpage(x) ((unsigned)(x) & ~PDRMASK) +#define round_4mpage(x) ((((unsigned)(x)) + PDRMASK) & ~PDRMASK) + +#define atop(x) ((unsigned long)(x) >> PAGE_SHIFT) +#define ptoa(x) ((unsigned long)(x) << PAGE_SHIFT) + +#define powerpc_btop(x) ((unsigned)(x) >> PAGE_SHIFT) +#define powerpc_ptob(x) ((unsigned)(x) << PAGE_SHIFT) + +#define pgtok(x) ((x) * (PAGE_SIZE / 1024)) + +#endif /* !_MACHINE_PARAM_H_ */ +#endif /* !_NO_NAMESPACE_POLLUTION */ diff --git a/sys/powerpc/include/pcb.h b/sys/powerpc/include/pcb.h new file mode 100644 index 000000000000..3c31441d9b21 --- /dev/null +++ b/sys/powerpc/include/pcb.h @@ -0,0 +1,74 @@ +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: pcb.h,v 1.4 2000/06/04 11:57:17 tsubai Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_PCB_H_ +#define _MACHINE_PCB_H_ + +typedef int faultbuf[23]; + +struct pcb { + register_t pcb_context[20]; /* non-volatile r14-r31 */ + register_t pcb_cr; /* Condition register */ + register_t pcb_sp; /* stack pointer */ + register_t pcb_lr; /* link register */ + register_t pcb_usr; /* USER_SR segment register */ + struct pmap *pcb_pm; /* pmap of our vmspace */ + struct pmap *pcb_pmreal; /* real address of above */ + faultbuf *pcb_onfault; /* For use during + copyin/copyout */ + int pcb_flags; +#define PCB_FPU 1 /* Process had FPU initialized */ + struct fpu { + double fpr[32]; + double fpscr; /* FPSCR stored as double for easier access */ + } pcb_fpu; /* Floating point processor */ + unsigned int pcb_fpcpu; /* which CPU had our FPU + stuff. */ +}; + +#ifdef _KERNEL + +struct trapframe; + +#ifndef curpcb +extern struct pcb *curpcb; +#endif + +extern struct pmap *curpm; +extern struct proc *fpuproc; + +void makectx(struct trapframe *, struct pcb *); + +#endif +#endif /* _MACHINE_PCB_H_ */ diff --git a/sys/powerpc/include/pcpu.h b/sys/powerpc/include/pcpu.h new file mode 100644 index 000000000000..6e9507630126 --- /dev/null +++ b/sys/powerpc/include/pcpu.h @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 1999 Luoqi Chen <luoqi@freebsd.org> + * Copyright (c) Peter Wemm <peter@netplex.com.au> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_PCPU_H_ +#define _MACHINE_PCPU_H_ + +#ifdef _KERNEL +#include <machine/cpufunc.h> + +struct pmap; +#define CPUSAVE_LEN 8 + +#define PCPU_MD_FIELDS \ + int pc_inside_intr; \ + struct pmap *pc_curpmap; /* current pmap */ \ + struct thread *pc_fputhread; /* current fpu user */ \ + register_t pc_tempsave[CPUSAVE_LEN]; \ + register_t pc_disisave[CPUSAVE_LEN]; \ + register_t pc_dbsave[CPUSAVE_LEN]; + +/* Definitions for register offsets within the exception tmp save areas */ +#define CPUSAVE_R28 0 /* where r28 gets saved */ +#define CPUSAVE_R29 1 /* where r29 gets saved */ +#define CPUSAVE_R30 2 /* where r30 gets saved */ +#define CPUSAVE_R31 3 /* where r31 gets saved */ +#define CPUSAVE_DAR 4 /* where SPR_DAR gets saved */ +#define CPUSAVE_DSISR 5 /* where SPR_DSISR gets saved */ +#define CPUSAVE_SRR0 6 /* where SRR0 gets saved */ +#define CPUSAVE_SRR1 7 /* where SRR1 gets saved */ + +#define PCPUP ((struct pcpu *) powerpc_get_pcpup()) + +#define PCPU_GET(member) (PCPUP->pc_ ## member) + +/* + * XXX The implementation of this operation should be made atomic + * with respect to preemption. + */ +#define PCPU_ADD(member, value) (PCPUP->pc_ ## member += (value)) +#define PCPU_INC(member) PCPU_ADD(member, 1) +#define PCPU_PTR(member) (&PCPUP->pc_ ## member) +#define PCPU_SET(member,value) (PCPUP->pc_ ## member = (value)) + +#endif /* _KERNEL */ + +#endif /* !_MACHINE_PCPU_H_ */ diff --git a/sys/powerpc/include/pio.h b/sys/powerpc/include/pio.h new file mode 100644 index 000000000000..bf2cb5b67fcc --- /dev/null +++ b/sys/powerpc/include/pio.h @@ -0,0 +1,256 @@ +/*- + * Copyright (c) 1997 Per Fogelstrom, Opsycon AB and RTMX Inc, USA. + * + * 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 under OpenBSD by + * Per Fogelstrom Opsycon AB for RTMX Inc, North Carolina, USA. + * 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. + * + * $NetBSD: pio.h,v 1.1 1998/05/15 10:15:54 tsubai Exp $ + * $OpenBSD: pio.h,v 1.1 1997/10/13 10:53:47 pefo Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_PIO_H_ +#define _MACHINE_PIO_H_ +/* + * I/O macros. + */ + +static __inline void +__outb(volatile u_int8_t *a, u_int8_t v) +{ + *a = v; + __asm__ volatile("eieio; sync"); +} + +static __inline void +__outw(volatile u_int16_t *a, u_int16_t v) +{ + *a = v; + __asm__ volatile("eieio; sync"); +} + +static __inline void +__outl(volatile u_int32_t *a, u_int32_t v) +{ + *a = v; + __asm__ volatile("eieio; sync"); +} + +static __inline void +__outwrb(volatile u_int16_t *a, u_int16_t v) +{ + __asm__ volatile("sthbrx %0, 0, %1" :: "r"(v), "r"(a)); + __asm__ volatile("eieio; sync"); +} + +static __inline void +__outlrb(volatile u_int32_t *a, u_int32_t v) +{ + __asm__ volatile("stwbrx %0, 0, %1" :: "r"(v), "r"(a)); + __asm__ volatile("eieio; sync"); +} + +static __inline u_int8_t +__inb(volatile u_int8_t *a) +{ + u_int8_t _v_; + + _v_ = *a; + __asm__ volatile("eieio; sync"); + return _v_; +} + +static __inline u_int16_t +__inw(volatile u_int16_t *a) +{ + u_int16_t _v_; + + _v_ = *a; + __asm__ volatile("eieio; sync"); + return _v_; +} + +static __inline u_int32_t +__inl(volatile u_int32_t *a) +{ + u_int32_t _v_; + + _v_ = *a; + __asm__ volatile("eieio; sync"); + return _v_; +} + +static __inline u_int16_t +__inwrb(volatile u_int16_t *a) +{ + u_int16_t _v_; + + __asm__ volatile("lhbrx %0, 0, %1" : "=r"(_v_) : "r"(a)); + __asm__ volatile("eieio; sync"); + return _v_; +} + +static __inline u_int32_t +__inlrb(volatile u_int32_t *a) +{ + u_int32_t _v_; + + __asm__ volatile("lwbrx %0, 0, %1" : "=r"(_v_) : "r"(a)); + __asm__ volatile("eieio; sync"); + return _v_; +} + +#define outb(a,v) (__outb((volatile u_int8_t *)(a), v)) +#define out8(a,v) outb(a,v) +#define outw(a,v) (__outw((volatile u_int16_t *)(a), v)) +#define out16(a,v) outw(a,v) +#define outl(a,v) (__outl((volatile u_int32_t *)(a), v)) +#define out32(a,v) outl(a,v) +#define inb(a) (__inb((volatile u_int8_t *)(a))) +#define in8(a) inb(a) +#define inw(a) (__inw((volatile u_int16_t *)(a))) +#define in16(a) inw(a) +#define inl(a) (__inl((volatile u_int32_t *)(a))) +#define in32(a) inl(a) + +#define out8rb(a,v) outb(a,v) +#define outwrb(a,v) (__outwrb((volatile u_int16_t *)(a), v)) +#define out16rb(a,v) outwrb(a,v) +#define outlrb(a,v) (__outlrb((volatile u_int32_t *)(a), v)) +#define out32rb(a,v) outlrb(a,v) +#define in8rb(a) inb(a) +#define inwrb(a) (__inwrb((volatile u_int16_t *)(a))) +#define in16rb(a) inwrb(a) +#define inlrb(a) (__inlrb((volatile u_int32_t *)(a))) +#define in32rb(a) inlrb(a) + + +static __inline void +__outsb(volatile u_int8_t *a, const u_int8_t *s, size_t c) +{ + while (c--) + *a = *s++; + __asm__ volatile("eieio; sync"); +} + +static __inline void +__outsw(volatile u_int16_t *a, const u_int16_t *s, size_t c) +{ + while (c--) + *a = *s++; + __asm__ volatile("eieio; sync"); +} + +static __inline void +__outsl(volatile u_int32_t *a, const u_int32_t *s, size_t c) +{ + while (c--) + *a = *s++; + __asm__ volatile("eieio; sync"); +} + +static __inline void +__outswrb(volatile u_int16_t *a, const u_int16_t *s, size_t c) +{ + while (c--) + __asm__ volatile("sthbrx %0, 0, %1" :: "r"(*s++), "r"(a)); + __asm__ volatile("eieio; sync"); +} + +static __inline void +__outslrb(volatile u_int32_t *a, const u_int32_t *s, size_t c) +{ + while (c--) + __asm__ volatile("stwbrx %0, 0, %1" :: "r"(*s++), "r"(a)); + __asm__ volatile("eieio; sync"); +} + +static __inline void +__insb(volatile u_int8_t *a, u_int8_t *d, size_t c) +{ + while (c--) + *d++ = *a; + __asm__ volatile("eieio; sync"); +} + +static __inline void +__insw(volatile u_int16_t *a, u_int16_t *d, size_t c) +{ + while (c--) + *d++ = *a; + __asm__ volatile("eieio; sync"); +} + +static __inline void +__insl(volatile u_int32_t *a, u_int32_t *d, size_t c) +{ + while (c--) + *d++ = *a; + __asm__ volatile("eieio; sync"); +} + +static __inline void +__inswrb(volatile u_int16_t *a, u_int16_t *d, size_t c) +{ + while (c--) + __asm__ volatile("lhbrx %0, 0, %1" : "=r"(*d++) : "r"(a)); + __asm__ volatile("eieio; sync"); +} + +static __inline void +__inslrb(volatile u_int32_t *a, u_int32_t *d, size_t c) +{ + while (c--) + __asm__ volatile("lwbrx %0, 0, %1" : "=r"(*d++) : "r"(a)); + __asm__ volatile("eieio; sync"); +} + +#define outsb(a,s,c) (__outsb((volatile u_int8_t *)(a), s, c)) +#define outs8(a,s,c) outsb(a,s,c) +#define outsw(a,s,c) (__outsw((volatile u_int16_t *)(a), s, c)) +#define outs16(a,s,c) outsw(a,s,c) +#define outsl(a,s,c) (__outsl((volatile u_int32_t *)(a), s, c)) +#define outs32(a,s,c) outsl(a,s,c) +#define insb(a,d,c) (__insb((volatile u_int8_t *)(a), d, c)) +#define ins8(a,d,c) insb(a,d,c) +#define insw(a,d,c) (__insw((volatile u_int16_t *)(a), d, c)) +#define ins16(a,d,c) insw(a,d,c) +#define insl(a,d,c) (__insl((volatile u_int32_t *)(a), d, c)) +#define ins32(a,d,c) insl(a,d,c) + +#define outs8rb(a,s,c) outsb(a,s,c) +#define outswrb(a,s,c) (__outswrb((volatile u_int16_t *)(a), s, c)) +#define outs16rb(a,s,c) outswrb(a,s,c) +#define outslrb(a,s,c) (__outslrb((volatile u_int32_t *)(a), s, c)) +#define outs32rb(a,s,c) outslrb(a,s,c) +#define ins8rb(a,d,c) insb(a,d,c) +#define inswrb(a,d,c) (__inswrb((volatile u_int16_t *)(a), d, c)) +#define ins16rb(a,d,c) inswrb(a,d,c) +#define inslrb(a,d,c) (__inslrb((volatile u_int32_t *)(a), d, c)) +#define ins32rb(a,d,c) inslrb(a,d,c) + +#endif /*_MACHINE_PIO_H_*/ diff --git a/sys/powerpc/include/pmap.h b/sys/powerpc/include/pmap.h new file mode 100644 index 000000000000..d02f8d646c06 --- /dev/null +++ b/sys/powerpc/include/pmap.h @@ -0,0 +1,114 @@ +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: pmap.h,v 1.17 2000/03/30 16:18:24 jdolecek Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_PMAP_H_ +#define _MACHINE_PMAP_H_ + +#include <sys/queue.h> +#include <sys/_lock.h> +#include <sys/_mutex.h> +#include <machine/sr.h> +#include <machine/pte.h> + +#if !defined(NPMAPS) +#define NPMAPS 32768 +#endif /* !defined(NPMAPS) */ + +struct pmap { + struct mtx pm_mtx; + u_int pm_sr[16]; + u_int pm_active; + u_int pm_context; + struct pmap_statistics pm_stats; +}; + +typedef struct pmap *pmap_t; + +struct pvo_entry { + LIST_ENTRY(pvo_entry) pvo_vlink; /* Link to common virt page */ + LIST_ENTRY(pvo_entry) pvo_olink; /* Link to overflow entry */ + struct pte pvo_pte; /* PTE */ + pmap_t pvo_pmap; /* Owning pmap */ + vm_offset_t pvo_vaddr; /* VA of entry */ +}; +LIST_HEAD(pvo_head, pvo_entry); + +struct md_page { + u_int mdpg_attrs; + struct pvo_head mdpg_pvoh; +}; + +extern struct pmap kernel_pmap_store; +#define kernel_pmap (&kernel_pmap_store) + +#define pmap_page_is_mapped(m) (!LIST_EMPTY(&(m)->md.mdpg_pvoh)) + +#ifdef _KERNEL + +#define PMAP_LOCK(pmap) mtx_lock(&(pmap)->pm_mtx) +#define PMAP_LOCK_ASSERT(pmap, type) \ + mtx_assert(&(pmap)->pm_mtx, (type)) +#define PMAP_LOCK_DESTROY(pmap) mtx_destroy(&(pmap)->pm_mtx) +#define PMAP_LOCK_INIT(pmap) mtx_init(&(pmap)->pm_mtx, "pmap", \ + NULL, MTX_DEF) +#define PMAP_LOCKED(pmap) mtx_owned(&(pmap)->pm_mtx) +#define PMAP_MTX(pmap) (&(pmap)->pm_mtx) +#define PMAP_TRYLOCK(pmap) mtx_trylock(&(pmap)->pm_mtx) +#define PMAP_UNLOCK(pmap) mtx_unlock(&(pmap)->pm_mtx) + +void pmap_bootstrap(vm_offset_t, vm_offset_t); +void pmap_kenter(vm_offset_t va, vm_offset_t pa); +void pmap_kremove(vm_offset_t); +void *pmap_mapdev(vm_offset_t, vm_size_t); +void pmap_unmapdev(vm_offset_t, vm_size_t); +void pmap_deactivate(struct thread *); +vm_offset_t pmap_kextract(vm_offset_t); +int pmap_dev_direct_mapped(vm_offset_t, vm_size_t); +boolean_t pmap_page_executable(vm_page_t); +boolean_t pmap_mmu_install(char *name, int prio); + +#define vtophys(va) pmap_kextract((vm_offset_t)(va)) + +#define PHYS_AVAIL_SZ 128 +extern vm_offset_t phys_avail[PHYS_AVAIL_SZ]; +extern vm_offset_t virtual_avail; +extern vm_offset_t virtual_end; + +extern vm_offset_t msgbuf_phys; + +extern int pmap_bootstrapped; + +#endif + +#endif /* !_MACHINE_PMAP_H_ */ diff --git a/sys/powerpc/include/pmc_mdep.h b/sys/powerpc/include/pmc_mdep.h new file mode 100644 index 000000000000..d5417c3cedb6 --- /dev/null +++ b/sys/powerpc/include/pmc_mdep.h @@ -0,0 +1,25 @@ +/*- + * This file is in the public domain. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_PMC_MDEP_H_ +#define _MACHINE_PMC_MDEP_H_ + +union pmc_md_op_pmcallocate { + uint64_t __pad[4]; +}; + +/* Logging */ +#define PMCLOG_READADDR PMCLOG_READ32 +#define PMCLOG_EMITADDR PMCLOG_EMIT32 + +#if _KERNEL + +union pmc_md_pmc { +}; + +#endif + +#endif /* !_MACHINE_PMC_MDEP_H_ */ diff --git a/sys/powerpc/include/powerpc.h b/sys/powerpc/include/powerpc.h new file mode 100644 index 000000000000..3de078899dd3 --- /dev/null +++ b/sys/powerpc/include/powerpc.h @@ -0,0 +1,59 @@ +/*- + * Copyright (C) 1996 Wolfgang Solfrank. + * Copyright (C) 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: powerpc.h,v 1.3 2000/06/01 00:49:59 matt Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_POWERPC_H_ +#define _MACHINE_POWERPC_H_ + +struct mem_region { + vm_offset_t mr_start; + vm_size_t mr_size; +}; + +void mem_regions(struct mem_region **, int *, struct mem_region **, int *); + +/* + * These two functions get used solely in boot() in machdep.c. + * + * Not sure whether boot itself should be implementation dependent instead. XXX + */ +void OF_halt(void); +void OF_reboot(void); + +int dk_match(char *name); + +void ofrootfound(void); + +extern int booted_partition; + +#endif /* _MACHINE_POWERPC_H_ */ diff --git a/sys/powerpc/include/proc.h b/sys/powerpc/include/proc.h new file mode 100644 index 000000000000..c958fb76f0fb --- /dev/null +++ b/sys/powerpc/include/proc.h @@ -0,0 +1,49 @@ +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: proc.h,v 1.2 1997/04/16 22:57:48 thorpej Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_PROC_H_ +#define _MACHINE_PROC_H_ + +/* + * Machine-dependent part of the proc structure + */ +struct mdthread { + int md_spinlock_count; /* (k) */ + register_t md_saved_msr; /* (k) */ +}; + +struct mdproc { +}; + +#endif /* !_MACHINE_PROC_H_ */ diff --git a/sys/powerpc/include/profile.h b/sys/powerpc/include/profile.h new file mode 100644 index 000000000000..96f3825e1dc4 --- /dev/null +++ b/sys/powerpc/include/profile.h @@ -0,0 +1,146 @@ +/*- + * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + * + * from: NetBSD: profile.h,v 1.9 1997/04/06 08:47:37 cgd Exp + * from: FreeBSD: src/sys/alpha/include/profile.h,v 1.4 1999/12/29 + * $FreeBSD$ + */ + +#ifndef _MACHINE_PROFILE_H_ +#define _MACHINE_PROFILE_H_ + +#define _MCOUNT_DECL void __mcount + +#define FUNCTION_ALIGNMENT 16 + +typedef u_int fptrdiff_t; + +/* + * The mcount trampoline macro, expanded in libc/gmon/mcount.c + * + * For PowerPC SVR4 ABI profiling, the compiler will insert + * a data declaration and code sequence at the start of a routine of the form + * + * .function_mc: .data + * .align 2 + * .long 0 + * .text + * + * function: mflr %r0 + * addis %r11,%r0, .function_mc@ha + * stw %r0,4(%r1) + * addi %r0,%r11, .function_mc@l + * bl _mcount + * + * The link register is saved in the LR save word in the caller's + * stack frame, r0 is set up to point to the allocated longword, + * and control is transferred to _mcount. + * + * On return from _mcount, the routine should function as it would + * with no profiling so _mcount must restore register state to that upon + * entry. Any routine called by the _mcount trampoline will save + * callee-save registers, so _mcount must make sure it saves volatile + * registers that may have state after it returns i.e. parameter registers. + * + * The FreeBSD libc mcount routine ignores the r0 longword pointer, but + * instead requires as parameters the current PC and called PC. The current + * PC is obtained from the link register, as a result of "bl _mcount" in + * the stub, while the caller's PC is obtained from the LR save word. + * + * On return from libc mcount, the return is done indirectly with the + * ctr register rather than the link register, to allow the link register + * to be restored to what it was on entry to the profiled routine. + */ + +#ifdef PIC +#define _PLT "@plt" +#else +#define _PLT +#endif + +#define MCOUNT \ +__asm(" .globl _mcount \n" \ +" .type _mcount,@function \n" \ +"_mcount: \n" \ +" stwu %r1,-64(%r1) /* alloca for reg save space */ \n" \ +" stw %r3,16(%r1) /* save parameter registers, */ \n" \ +" stw %r4,20(%r1) /* r3-10 */ \n" \ +" stw %r5,24(%r1) \n" \ +" stw %r6,28(%r1) \n" \ +" stw %r7,32(%r1) \n" \ +" stw %r8,36(%r1) \n" \ +" stw %r9,40(%r1) \n" \ +" stw %r10,44(%r1) \n" \ +" \n" \ +" mflr %r4 /* link register is 'selfpc' */ \n" \ +" stw %r4,48(%r1) /* save since bl will scrub */ \n" \ +" lwz %r3,68(%r1) /* get 'frompc' from LR-save */ \n" \ +" bl __mcount" _PLT " /* __mcount(frompc, selfpc)*/ \n" \ +" lwz %r3,68(%r1) \n" \ +" mtlr %r3 /* restore caller's lr */ \n" \ +" lwz %r4,48(%r1) \n" \ +" mtctr %r4 /* set up ctr for call back */ \n" \ +" /* note that blr is not used!*/ \n" \ +" lwz %r3,16(%r1) /* restore r3-10 parameters */ \n" \ +" lwz %r4,20(%r1) \n" \ +" lwz %r5,24(%r1) \n" \ +" lwz %r6,28(%r1) \n" \ +" lwz %r7,32(%r1) \n" \ +" lwz %r8,36(%r1) \n" \ +" lwz %r9,40(%r1) \n" \ +" lwz %r10,44(%r1) \n" \ +" addi %r1,%r1,64 /* blow away alloca save area */ \n" \ +" bctr /* return with indirect call */ \n" \ +"_mcount_end: \n" \ +" .size _mcount,_mcount_end-_mcount"); + + +#ifdef _KERNEL +#define MCOUNT_ENTER(s) s = intr_disable(); +#define MCOUNT_EXIT(s) intr_restore(s); +#define MCOUNT_DECL(s) register_t s + +void bintr(void); +void btrap(void); +void eintr(void); +void user(void); + +#define MCOUNT_FROMPC_USER(pc) \ + ((pc < (uintfptr_t)VM_MAXUSER_ADDRESS) ? (uintfptr_t)user : pc) + +#define MCOUNT_FROMPC_INTR(pc) \ + ((pc >= (uintfptr_t)btrap && pc < (uintfptr_t)eintr) ? \ + ((pc >= (uintfptr_t)bintr) ? (uintfptr_t)bintr : \ + (uintfptr_t)btrap) : ~0U) + + +#else /* !_KERNEL */ + +typedef u_int uintfptr_t; + +#endif /* _KERNEL */ + +#endif /* !_MACHINE_PROFILE_H_ */ diff --git a/sys/powerpc/include/psl.h b/sys/powerpc/include/psl.h new file mode 100644 index 000000000000..a7ab6f1354b3 --- /dev/null +++ b/sys/powerpc/include/psl.h @@ -0,0 +1,86 @@ +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: psl.h,v 1.5 2000/11/19 19:52:37 matt Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_PSL_H_ +#define _MACHINE_PSL_H_ + +/* + * Machine State Register (MSR) + * + * The PowerPC 601 does not implement the following bits: + * + * VEC, POW, ILE, BE, RI, LE[*] + * + * [*] Little-endian mode on the 601 is implemented in the HID0 register. + */ +#define PSL_VEC 0x02000000 /* AltiVec vector unit available */ +#define PSL_POW 0x00040000 /* power management */ +#define PSL_ILE 0x00010000 /* interrupt endian mode (1 == le) */ +#define PSL_EE 0x00008000 /* external interrupt enable */ +#define PSL_PR 0x00004000 /* privilege mode (1 == user) */ +#define PSL_FP 0x00002000 /* floating point enable */ +#define PSL_ME 0x00001000 /* machine check enable */ +#define PSL_FE0 0x00000800 /* floating point interrupt mode 0 */ +#define PSL_SE 0x00000400 /* single-step trace enable */ +#define PSL_BE 0x00000200 /* branch trace enable */ +#define PSL_FE1 0x00000100 /* floating point interrupt mode 1 */ +#define PSL_IP 0x00000040 /* interrupt prefix */ +#define PSL_IR 0x00000020 /* instruction address relocation */ +#define PSL_DR 0x00000010 /* data address relocation */ +#define PSL_RI 0x00000002 /* recoverable interrupt */ +#define PSL_LE 0x00000001 /* endian mode (1 == le) */ + +#define PSL_601_MASK ~(PSL_POW|PSL_ILE|PSL_BE|PSL_RI|PSL_LE) + +/* + * Floating-point exception modes: + */ +#define PSL_FE_DIS 0 /* none */ +#define PSL_FE_NONREC PSL_FE1 /* imprecise non-recoverable */ +#define PSL_FE_REC PSL_FE0 /* imprecise recoverable */ +#define PSL_FE_PREC (PSL_FE0 | PSL_FE1) /* precise */ +#define PSL_FE_DFLT PSL_FE_DIS /* default == none */ + +/* + * Note that PSL_POW and PSL_ILE are not in the saved copy of the MSR + */ +#define PSL_MBO 0 +#define PSL_MBZ 0 + +#define PSL_KERNSET (PSL_EE | PSL_ME | PSL_IR | PSL_DR | PSL_RI) +#define PSL_USERSET (PSL_KERNSET | PSL_PR) + +#define PSL_USERSTATIC (PSL_USERSET | PSL_IP | 0x87c0008c) + +#endif /* _MACHINE_PSL_H_ */ diff --git a/sys/powerpc/include/pte.h b/sys/powerpc/include/pte.h new file mode 100644 index 000000000000..391c82e45951 --- /dev/null +++ b/sys/powerpc/include/pte.h @@ -0,0 +1,159 @@ +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: pte.h,v 1.2 1998/08/31 14:43:40 tsubai Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_PTE_H_ +#define _MACHINE_PTE_H_ + +/* + * Page Table Entries + */ +#ifndef LOCORE + +/* 32-bit PTE */ +struct pte { + u_int32_t pte_hi; + u_int32_t pte_lo; +}; + +struct pteg { + struct pte pt[8]; +}; + +/* 64-bit (long) PTE */ +struct lpte { + u_int64_t pte_hi; + u_int64_t pte_lo; +}; + +struct lpteg { + struct lpte pt[8]; +}; + +#endif /* LOCORE */ + +/* 32-bit PTE definitions */ + +/* High word: */ +#define PTE_VALID 0x80000000 +#define PTE_VSID_SHFT 7 +#define PTE_HID 0x00000040 +#define PTE_API 0x0000003f +/* Low word: */ +#define PTE_RPGN 0xfffff000 +#define PTE_REF 0x00000100 +#define PTE_CHG 0x00000080 +#define PTE_WIMG 0x00000078 +#define PTE_W 0x00000040 +#define PTE_I 0x00000020 +#define PTE_M 0x00000010 +#define PTE_G 0x00000008 +#define PTE_PP 0x00000003 +#define PTE_SO 0x00000000 /* Super. Only (U: XX, S: RW) */ +#define PTE_SW 0x00000001 /* Super. Write-Only (U: RO, S: RW) */ +#define PTE_BW 0x00000002 /* Supervisor (U: RW, S: RW) */ +#define PTE_BR 0x00000003 /* Both Read Only (U: RO, S: RO) */ +#define PTE_RW PTE_BW +#define PTE_RO PTE_BR + +#define PTE_EXEC 0x00000200 /* pseudo bit in attrs; page is exec */ + +/* 64-bit PTE definitions */ + +/* High quadword: */ +#define LPTE_VSID_SHIFT 12 +#define LPTE_API 0x0000000000000F80ULL +#define LPTE_BIG 0x0000000000000004ULL /* 4kb/16Mb page */ +#define LPTE_HID 0x0000000000000002ULL +#define LPTE_VALID 0x0000000000000001ULL + +/* Low quadword: */ +#define EXTEND_PTE(x) UINT64_C(x) /* make constants 64-bit */ +#define LPTE_RPGN 0xfffffffffffff000ULL +#define LPTE_REF EXTEND_PTE( PTE_REF ) +#define LPTE_CHG EXTEND_PTE( PTE_CHG ) +#define LPTE_WIMG EXTEND_PTE( PTE_WIMG ) +#define LPTE_W EXTEND_PTE( PTE_W ) +#define LPTE_I EXTEND_PTE( PTE_I ) +#define LPTE_M EXTEND_PTE( PTE_M ) +#define LPTE_G EXTEND_PTE( PTE_G ) +#define LPTE_NOEXEC 0x0000000000000004ULL +#define LPTE_PP EXTEND_PTE( PTE_PP ) + +#define LPTE_SO EXTEND_PTE( PTE_SO ) /* Super. Only */ +#define LPTE_SW EXTEND_PTE( PTE_SW ) /* Super. Write-Only */ +#define LPTE_BW EXTEND_PTE( PTE_BW ) /* Supervisor */ +#define LPTE_BR EXTEND_PTE( PTE_BR ) /* Both Read Only */ +#define LPTE_RW LPTE_BW +#define LPTE_RO LPTE_BR + +#ifndef LOCORE +typedef struct pte pte_t; +typedef struct lpte lpte_t; +#endif /* LOCORE */ + +/* + * Extract bits from address + */ +#define ADDR_SR_SHFT 28 +#define ADDR_PIDX 0x0ffff000 +#define ADDR_PIDX_SHFT 12 +#define ADDR_API_SHFT 22 +#define ADDR_POFF 0x00000fff + +/* + * Bits in DSISR: + */ +#define DSISR_DIRECT 0x80000000 +#define DSISR_NOTFOUND 0x40000000 +#define DSISR_PROTECT 0x08000000 +#define DSISR_INVRX 0x04000000 +#define DSISR_STORE 0x02000000 +#define DSISR_DABR 0x00400000 +#define DSISR_SEGMENT 0x00200000 +#define DSISR_EAR 0x00100000 + +/* + * Bits in SRR1 on ISI: + */ +#define ISSRR1_NOTFOUND 0x40000000 +#define ISSRR1_DIRECT 0x10000000 +#define ISSRR1_PROTECT 0x08000000 +#define ISSRR1_SEGMENT 0x00200000 + +#ifdef _KERNEL +#ifndef LOCORE +extern u_int dsisr(void); +#endif /* _KERNEL */ +#endif /* LOCORE */ +#endif /* _MACHINE_PTE_H_ */ diff --git a/sys/powerpc/include/ptrace.h b/sys/powerpc/include/ptrace.h new file mode 100644 index 000000000000..eef24f829b48 --- /dev/null +++ b/sys/powerpc/include/ptrace.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ptrace.h 8.1 (Berkeley) 6/11/93 + * $FreeBSD$ + */ + +#ifndef _MACHINE_PTRACE_H_ +#define _MACHINE_PTRACE_H_ + +#endif diff --git a/sys/powerpc/include/reg.h b/sys/powerpc/include/reg.h new file mode 100644 index 000000000000..640365546e7c --- /dev/null +++ b/sys/powerpc/include/reg.h @@ -0,0 +1,39 @@ +/* $NetBSD: reg.h,v 1.4 2000/06/04 09:30:44 tsubai Exp $ */ +/* $FreeBSD$ */ + +#ifndef _POWERPC_REG_H_ +#define _POWERPC_REG_H_ + +/* Must match struct trapframe */ +struct reg { + register_t fixreg[32]; + register_t lr; + int cr; + int xer; + register_t ctr; + register_t pc; +}; + +/* Must match pcb.pcb_fpu */ +struct fpreg { + double fpreg[32]; + double fpscr; +}; + +struct dbreg { + unsigned long junk; +}; + +#ifdef _KERNEL +/* + * XXX these interfaces are MI, so they should be declared in a MI place. + */ +int fill_regs(struct thread *, struct reg *); +int set_regs(struct thread *, struct reg *); +int fill_fpregs(struct thread *, struct fpreg *); +int set_fpregs(struct thread *, struct fpreg *); +int fill_dbregs(struct thread *, struct dbreg *); +int set_dbregs(struct thread *, struct dbreg *); +#endif + +#endif /* _POWERPC_REG_H_ */ diff --git a/sys/powerpc/include/reloc.h b/sys/powerpc/include/reloc.h new file mode 100644 index 000000000000..0e4155dac4cf --- /dev/null +++ b/sys/powerpc/include/reloc.h @@ -0,0 +1,30 @@ +/*- + * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ diff --git a/sys/powerpc/include/resource.h b/sys/powerpc/include/resource.h new file mode 100644 index 000000000000..edde5eb29908 --- /dev/null +++ b/sys/powerpc/include/resource.h @@ -0,0 +1,44 @@ +/* $FreeBSD$ */ +/*- + * Copyright 1998 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MACHINE_RESOURCE_H_ +#define _MACHINE_RESOURCE_H_ 1 + +/* + * Definitions of resource types for Intel Architecture machines + * with support for legacy ISA devices and drivers. + */ + +#define SYS_RES_IRQ 1 /* interrupt lines */ +#define SYS_RES_DRQ 2 /* isa dma lines */ +#define SYS_RES_MEMORY 3 /* i/o memory */ +#define SYS_RES_IOPORT 4 /* i/o ports */ + +#endif /* !_MACHINE_RESOURCE_H_ */ diff --git a/sys/powerpc/include/runq.h b/sys/powerpc/include/runq.h new file mode 100644 index 000000000000..e906fa192c6c --- /dev/null +++ b/sys/powerpc/include/runq.h @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2001 Jake Burkholder <jake@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_RUNQ_H_ +#define _MACHINE_RUNQ_H_ + +#define RQB_LEN (2) /* Number of priority status words. */ +#define RQB_L2BPW (5) /* Log2(sizeof(rqb_word_t) * NBBY)). */ +#define RQB_BPW (1<<RQB_L2BPW) /* Bits in an rqb_word_t. */ + +#define RQB_BIT(pri) (1 << ((pri) & (RQB_BPW - 1))) +#define RQB_WORD(pri) ((pri) >> RQB_L2BPW) + +#define RQB_FFS(word) (ffs(word) - 1) + +/* + * Type of run queue status word. + */ +typedef u_int32_t rqb_word_t; + +#endif diff --git a/sys/powerpc/include/sc_machdep.h b/sys/powerpc/include/sc_machdep.h new file mode 100644 index 000000000000..4f3526fabcf0 --- /dev/null +++ b/sys/powerpc/include/sc_machdep.h @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 2003 Jake Burkholder. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_SC_MACHDEP_H_ +#define _MACHINE_SC_MACHDEP_H_ + +/* Color attributes for foreground text */ + +#define FG_BLACK 0x0 +#define FG_BLUE 0x1 +#define FG_GREEN 0x2 +#define FG_CYAN 0x3 +#define FG_RED 0x4 +#define FG_MAGENTA 0x5 +#define FG_BROWN 0x6 +#define FG_LIGHTGREY 0x7 /* aka white */ +#define FG_DARKGREY 0x8 +#define FG_LIGHTBLUE 0x9 +#define FG_LIGHTGREEN 0xa +#define FG_LIGHTCYAN 0xb +#define FG_LIGHTRED 0xc +#define FG_LIGHTMAGENTA 0xd +#define FG_YELLOW 0xe +#define FG_WHITE 0xf /* aka bright white */ +#define FG_BLINK 0x80 + +/* Color attributes for text background */ + +#define BG_BLACK 0x00 +#define BG_BLUE 0x10 +#define BG_GREEN 0x20 +#define BG_CYAN 0x30 +#define BG_RED 0x40 +#define BG_MAGENTA 0x50 +#define BG_BROWN 0x60 +#define BG_LIGHTGREY 0x70 +#define BG_DARKGREY 0x80 +#define BG_LIGHTBLUE 0x90 +#define BG_LIGHTGREEN 0xa0 +#define BG_LIGHTCYAN 0xb0 +#define BG_LIGHTRED 0xc0 +#define BG_LIGHTMAGENTA 0xd0 +#define BG_YELLOW 0xe0 +#define BG_WHITE 0xf0 + +#endif /* !_MACHINE_SC_MACHDEP_H_ */ diff --git a/sys/powerpc/include/setjmp.h b/sys/powerpc/include/setjmp.h new file mode 100644 index 000000000000..e453044dbf3b --- /dev/null +++ b/sys/powerpc/include/setjmp.h @@ -0,0 +1,24 @@ +/*- + * $NetBSD: setjmp.h,v 1.3 1998/09/16 23:51:27 thorpej Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_SETJMP_H_ +#define _MACHINE_SETJMP_H_ + +#include <sys/cdefs.h> + +#define _JBLEN 100 + +/* + * jmp_buf and sigjmp_buf are encapsulated in different structs to force + * compile-time diagnostics for mismatches. The structs are the same + * internally to avoid some run-time errors for mismatches. + */ +#if __BSD_VISIBLE || __POSIX_VISIBLE || __XSI_VISIBLE +typedef struct _sigjmp_buf { long _sjb[_JBLEN + 1]; } sigjmp_buf[1]; +#endif + +typedef struct _jmp_buf { long _jb[_JBLEN + 1]; } jmp_buf[1]; + +#endif /* !_MACHINE_SETJMP_H_ */ diff --git a/sys/powerpc/include/sf_buf.h b/sys/powerpc/include/sf_buf.h new file mode 100644 index 000000000000..6997419c6423 --- /dev/null +++ b/sys/powerpc/include/sf_buf.h @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2003 Alan L. Cox <alc@cs.rice.edu> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_SF_BUF_H_ +#define _MACHINE_SF_BUF_H_ + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/vm_page.h> + +/* + * On this machine, the only purpose for which sf_buf is used is to implement + * an opaque pointer required by the machine-independent parts of the kernel. + * That pointer references the vm_page that is "mapped" by the sf_buf. The + * actual mapping is provided by the direct virtual-to-physical mapping. + */ +struct sf_buf; + +static __inline vm_offset_t +sf_buf_kva(struct sf_buf *sf) +{ + + return (VM_PAGE_TO_PHYS((vm_page_t)sf)); +} + +static __inline vm_page_t +sf_buf_page(struct sf_buf *sf) +{ + + return ((vm_page_t)sf); +} + +#endif /* !_MACHINE_SF_BUF_H_ */ diff --git a/sys/powerpc/include/sigframe.h b/sys/powerpc/include/sigframe.h new file mode 100644 index 000000000000..d0e886e9bc90 --- /dev/null +++ b/sys/powerpc/include/sigframe.h @@ -0,0 +1,39 @@ +/*- + * Copyright (c) 1999 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_SIGFRAME_H_ +#define _MACHINE_SIGFRAME_H_ 1 + +struct sigframe { + ucontext_t sf_uc; + siginfo_t sf_si; +}; + +#endif /* _MACHINE_SIGFRAME_H_ */ diff --git a/sys/powerpc/include/signal.h b/sys/powerpc/include/signal.h new file mode 100644 index 000000000000..ba0bee2b7797 --- /dev/null +++ b/sys/powerpc/include/signal.h @@ -0,0 +1,53 @@ +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: signal.h,v 1.4 1998/09/14 02:48:34 thorpej Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_SIGNAL_H_ +#define _MACHINE_SIGNAL_H_ + +#include <sys/cdefs.h> + +typedef int sig_atomic_t; + +#if __BSD_VISIBLE +#include <machine/frame.h> + +struct sigcontext { + int sc_onstack; /* saved onstack flag */ + int __sc_mask13; /* saved signal mask (old style) */ + struct trapframe sc_frame; /* saved registers */ + struct __sigset sc_mask; /* saved signal mask (new style) */ +}; +#endif + +#endif /* !_MACHINE_SIGNAL_H_ */ diff --git a/sys/powerpc/include/smp.h b/sys/powerpc/include/smp.h new file mode 100644 index 000000000000..15ec74ce8f80 --- /dev/null +++ b/sys/powerpc/include/smp.h @@ -0,0 +1,7 @@ +/* $FreeBSD$ */ + +/* + * An empty file now, + * Although in the times to come, + * More may be found here. + */ diff --git a/sys/powerpc/include/spr.h b/sys/powerpc/include/spr.h new file mode 100644 index 000000000000..f3919f1a550f --- /dev/null +++ b/sys/powerpc/include/spr.h @@ -0,0 +1,481 @@ +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the 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. + * + * $NetBSD: spr.h,v 1.25 2002/08/14 15:38:40 matt Exp $ + * $FreeBSD$ + */ +#ifndef _POWERPC_SPR_H_ +#define _POWERPC_SPR_H_ + +#ifndef _LOCORE +#define mtspr(reg, val) \ + __asm __volatile("mtspr %0,%1" : : "K"(reg), "r"(val)) +#define mfspr(reg) \ + ( { register_t val; \ + __asm __volatile("mfspr %0,%1" : "=r"(val) : "K"(reg)); \ + val; } ) +#endif /* _LOCORE */ + +/* + * Special Purpose Register declarations. + * + * The first column in the comments indicates which PowerPC + * architectures the SPR is valid on - 4 for 4xx series, + * 6 for 6xx/7xx series and 8 for 8xx and 8xxx series. + */ + +#define SPR_MQ 0x000 /* .6. 601 MQ register */ +#define SPR_XER 0x001 /* 468 Fixed Point Exception Register */ +#define SPR_RTCU_R 0x004 /* .6. 601 RTC Upper - Read */ +#define SPR_RTCL_R 0x005 /* .6. 601 RTC Lower - Read */ +#define SPR_LR 0x008 /* 468 Link Register */ +#define SPR_CTR 0x009 /* 468 Count Register */ +#define SPR_DSISR 0x012 /* .68 DSI exception source */ +#define DSISR_DIRECT 0x80000000 /* Direct-store error exception */ +#define DSISR_NOTFOUND 0x40000000 /* Translation not found */ +#define DSISR_PROTECT 0x08000000 /* Memory access not permitted */ +#define DSISR_INVRX 0x04000000 /* Reserve-indexed insn direct-store access */ +#define DSISR_STORE 0x02000000 /* Store operation */ +#define DSISR_DABR 0x00400000 /* DABR match */ +#define DSISR_SEGMENT 0x00200000 /* XXX; not in 6xx PEM */ +#define DSISR_EAR 0x00100000 /* eciwx/ecowx && EAR[E] == 0 */ +#define SPR_DAR 0x013 /* .68 Data Address Register */ +#define SPR_RTCU_W 0x014 /* .6. 601 RTC Upper - Write */ +#define SPR_RTCL_W 0x015 /* .6. 601 RTC Lower - Write */ +#define SPR_DEC 0x016 /* .68 DECrementer register */ +#define SPR_SDR1 0x019 /* .68 Page table base address register */ +#define SPR_SRR0 0x01a /* 468 Save/Restore Register 0 */ +#define SPR_SRR1 0x01b /* 468 Save/Restore Register 1 */ +#define SPR_EIE 0x050 /* ..8 Exception Interrupt ??? */ +#define SPR_EID 0x051 /* ..8 Exception Interrupt ??? */ +#define SPR_NRI 0x052 /* ..8 Exception Interrupt ??? */ +#define SPR_USPRG0 0x100 /* 4.. User SPR General 0 */ +#define SPR_VRSAVE 0x100 /* .6. AltiVec VRSAVE */ +#define SPR_SPRG0 0x110 /* 468 SPR General 0 */ +#define SPR_SPRG1 0x111 /* 468 SPR General 1 */ +#define SPR_SPRG2 0x112 /* 468 SPR General 2 */ +#define SPR_SPRG3 0x113 /* 468 SPR General 3 */ +#define SPR_SPRG4 0x114 /* 4.. SPR General 4 */ +#define SPR_SPRG5 0x115 /* 4.. SPR General 5 */ +#define SPR_SPRG6 0x116 /* 4.. SPR General 6 */ +#define SPR_SPRG7 0x117 /* 4.. SPR General 7 */ +#define SPR_ASR 0x118 /* ... Address Space Register (PPC64) */ +#define SPR_EAR 0x11a /* .68 External Access Register */ +#define SPR_TBL 0x11c /* 468 Time Base Lower */ +#define SPR_TBU 0x11d /* 468 Time Base Upper */ +#define SPR_PVR 0x11f /* 468 Processor Version Register */ +#define MPC601 0x0001 +#define MPC603 0x0003 +#define MPC604 0x0004 +#define MPC602 0x0005 +#define MPC603e 0x0006 +#define MPC603ev 0x0007 +#define MPC750 0x0008 +#define MPC604ev 0x0009 +#define MPC7400 0x000c +#define MPC620 0x0014 +#define IBM403 0x0020 +#define IBM401A1 0x0021 +#define IBM401B2 0x0022 +#define IBM401C2 0x0023 +#define IBM401D2 0x0024 +#define IBM401E2 0x0025 +#define IBM401F2 0x0026 +#define IBM401G2 0x0027 +#define IBMPOWER3 0x0041 +#define MPC860 0x0050 +#define MPC8240 0x0081 +#define IBM405GP 0x4011 +#define IBM405L 0x4161 +#define IBM750FX 0x7000 +#define MPC745X_P(v) ((v & 0xFFF8) == 0x8000) +#define MPC7450 0x8000 +#define MPC7455 0x8001 +#define MPC7457 0x8002 +#define MPC7447A 0x8003 +#define MPC7448 0x8004 +#define MPC7410 0x800c +#define MPC8245 0x8081 + +#define SPR_IBAT0U 0x210 /* .68 Instruction BAT Reg 0 Upper */ +#define SPR_IBAT0U 0x210 /* .6. Instruction BAT Reg 0 Upper */ +#define SPR_IBAT0L 0x211 /* .6. Instruction BAT Reg 0 Lower */ +#define SPR_IBAT1U 0x212 /* .6. Instruction BAT Reg 1 Upper */ +#define SPR_IBAT1L 0x213 /* .6. Instruction BAT Reg 1 Lower */ +#define SPR_IBAT2U 0x214 /* .6. Instruction BAT Reg 2 Upper */ +#define SPR_IBAT2L 0x215 /* .6. Instruction BAT Reg 2 Lower */ +#define SPR_IBAT3U 0x216 /* .6. Instruction BAT Reg 3 Upper */ +#define SPR_IBAT3L 0x217 /* .6. Instruction BAT Reg 3 Lower */ +#define SPR_DBAT0U 0x218 /* .6. Data BAT Reg 0 Upper */ +#define SPR_DBAT0L 0x219 /* .6. Data BAT Reg 0 Lower */ +#define SPR_DBAT1U 0x21a /* .6. Data BAT Reg 1 Upper */ +#define SPR_DBAT1L 0x21b /* .6. Data BAT Reg 1 Lower */ +#define SPR_DBAT2U 0x21c /* .6. Data BAT Reg 2 Upper */ +#define SPR_DBAT2L 0x21d /* .6. Data BAT Reg 2 Lower */ +#define SPR_DBAT3U 0x21e /* .6. Data BAT Reg 3 Upper */ +#define SPR_DBAT3L 0x21f /* .6. Data BAT Reg 3 Lower */ +#define SPR_IC_CST 0x230 /* ..8 Instruction Cache CSR */ +#define IC_CST_IEN 0x80000000 /* I cache is ENabled (RO) */ +#define IC_CST_CMD_INVALL 0x0c000000 /* I cache invalidate all */ +#define IC_CST_CMD_UNLOCKALL 0x0a000000 /* I cache unlock all */ +#define IC_CST_CMD_UNLOCK 0x08000000 /* I cache unlock block */ +#define IC_CST_CMD_LOADLOCK 0x06000000 /* I cache load & lock block */ +#define IC_CST_CMD_DISABLE 0x04000000 /* I cache disable */ +#define IC_CST_CMD_ENABLE 0x02000000 /* I cache enable */ +#define IC_CST_CCER1 0x00200000 /* I cache error type 1 (RO) */ +#define IC_CST_CCER2 0x00100000 /* I cache error type 2 (RO) */ +#define IC_CST_CCER3 0x00080000 /* I cache error type 3 (RO) */ +#define SPR_IBAT4U 0x230 /* .6. Instruction BAT Reg 4 Upper */ +#define SPR_IC_ADR 0x231 /* ..8 Instruction Cache Address */ +#define SPR_IBAT4L 0x231 /* .6. Instruction BAT Reg 4 Lower */ +#define SPR_IC_DAT 0x232 /* ..8 Instruction Cache Data */ +#define SPR_IBAT5U 0x232 /* .6. Instruction BAT Reg 5 Upper */ +#define SPR_IBAT5L 0x233 /* .6. Instruction BAT Reg 5 Lower */ +#define SPR_IBAT6U 0x234 /* .6. Instruction BAT Reg 6 Upper */ +#define SPR_IBAT6L 0x235 /* .6. Instruction BAT Reg 6 Lower */ +#define SPR_IBAT7U 0x236 /* .6. Instruction BAT Reg 7 Upper */ +#define SPR_IBAT7L 0x237 /* .6. Instruction BAT Reg 7 Lower */ +#define SPR_DC_CST 0x230 /* ..8 Data Cache CSR */ +#define DC_CST_DEN 0x80000000 /* D cache ENabled (RO) */ +#define DC_CST_DFWT 0x40000000 /* D cache Force Write-Thru (RO) */ +#define DC_CST_LES 0x20000000 /* D cache Little Endian Swap (RO) */ +#define DC_CST_CMD_FLUSH 0x0e000000 /* D cache invalidate all */ +#define DC_CST_CMD_INVALL 0x0c000000 /* D cache invalidate all */ +#define DC_CST_CMD_UNLOCKALL 0x0a000000 /* D cache unlock all */ +#define DC_CST_CMD_UNLOCK 0x08000000 /* D cache unlock block */ +#define DC_CST_CMD_CLRLESWAP 0x07000000 /* D cache clr little-endian swap */ +#define DC_CST_CMD_LOADLOCK 0x06000000 /* D cache load & lock block */ +#define DC_CST_CMD_SETLESWAP 0x05000000 /* D cache set little-endian swap */ +#define DC_CST_CMD_DISABLE 0x04000000 /* D cache disable */ +#define DC_CST_CMD_CLRFWT 0x03000000 /* D cache clear forced write-thru */ +#define DC_CST_CMD_ENABLE 0x02000000 /* D cache enable */ +#define DC_CST_CMD_SETFWT 0x01000000 /* D cache set forced write-thru */ +#define DC_CST_CCER1 0x00200000 /* D cache error type 1 (RO) */ +#define DC_CST_CCER2 0x00100000 /* D cache error type 2 (RO) */ +#define DC_CST_CCER3 0x00080000 /* D cache error type 3 (RO) */ +#define SPR_DBAT4U 0x238 /* .6. Data BAT Reg 4 Upper */ +#define SPR_DC_ADR 0x231 /* ..8 Data Cache Address */ +#define SPR_DBAT4L 0x239 /* .6. Data BAT Reg 4 Lower */ +#define SPR_DC_DAT 0x232 /* ..8 Data Cache Data */ +#define SPR_DBAT5U 0x23a /* .6. Data BAT Reg 5 Upper */ +#define SPR_DBAT5L 0x23b /* .6. Data BAT Reg 5 Lower */ +#define SPR_DBAT6U 0x23c /* .6. Data BAT Reg 6 Upper */ +#define SPR_DBAT6L 0x23d /* .6. Data BAT Reg 6 Lower */ +#define SPR_DBAT7U 0x23e /* .6. Data BAT Reg 7 Upper */ +#define SPR_DBAT7L 0x23f /* .6. Data BAT Reg 7 Lower */ +#define SPR_MI_CTR 0x310 /* ..8 IMMU control */ +#define Mx_CTR_GPM 0x80000000 /* Group Protection Mode */ +#define Mx_CTR_PPM 0x40000000 /* Page Protection Mode */ +#define Mx_CTR_CIDEF 0x20000000 /* Cache-Inhibit DEFault */ +#define MD_CTR_WTDEF 0x20000000 /* Write-Through DEFault */ +#define Mx_CTR_RSV4 0x08000000 /* Reserve 4 TLB entries */ +#define MD_CTR_TWAM 0x04000000 /* TableWalk Assist Mode */ +#define Mx_CTR_PPCS 0x02000000 /* Priv/user state compare mode */ +#define Mx_CTR_TLB_INDX 0x000001f0 /* TLB index mask */ +#define Mx_CTR_TLB_INDX_BITPOS 8 /* TLB index shift */ +#define SPR_MI_AP 0x312 /* ..8 IMMU access protection */ +#define Mx_GP_SUPER(n) (0 << (2*(15-(n)))) /* access is supervisor */ +#define Mx_GP_PAGE (1 << (2*(15-(n)))) /* access is page protect */ +#define Mx_GP_SWAPPED (2 << (2*(15-(n)))) /* access is swapped */ +#define Mx_GP_USER (3 << (2*(15-(n)))) /* access is user */ +#define SPR_MI_EPN 0x313 /* ..8 IMMU effective number */ +#define Mx_EPN_EPN 0xfffff000 /* Effective Page Number mask */ +#define Mx_EPN_EV 0x00000020 /* Entry Valid */ +#define Mx_EPN_ASID 0x0000000f /* Address Space ID */ +#define SPR_MI_TWC 0x315 /* ..8 IMMU tablewalk control */ +#define MD_TWC_L2TB 0xfffff000 /* Level-2 Tablewalk Base */ +#define Mx_TWC_APG 0x000001e0 /* Access Protection Group */ +#define Mx_TWC_G 0x00000010 /* Guarded memory */ +#define Mx_TWC_PS 0x0000000c /* Page Size (L1) */ +#define MD_TWC_WT 0x00000002 /* Write-Through */ +#define Mx_TWC_V 0x00000001 /* Entry Valid */ +#define SPR_MI_RPN 0x316 /* ..8 IMMU real (phys) page number */ +#define Mx_RPN_RPN 0xfffff000 /* Real Page Number */ +#define Mx_RPN_PP 0x00000ff0 /* Page Protection */ +#define Mx_RPN_SPS 0x00000008 /* Small Page Size */ +#define Mx_RPN_SH 0x00000004 /* SHared page */ +#define Mx_RPN_CI 0x00000002 /* Cache Inhibit */ +#define Mx_RPN_V 0x00000001 /* Valid */ +#define SPR_MD_CTR 0x318 /* ..8 DMMU control */ +#define SPR_M_CASID 0x319 /* ..8 CASID */ +#define M_CASID 0x0000000f /* Current AS Id */ +#define SPR_MD_AP 0x31a /* ..8 DMMU access protection */ +#define SPR_MD_EPN 0x31b /* ..8 DMMU effective number */ +#define SPR_M_TWB 0x31c /* ..8 MMU tablewalk base */ +#define M_TWB_L1TB 0xfffff000 /* level-1 translation base */ +#define M_TWB_L1INDX 0x00000ffc /* level-1 index */ +#define SPR_MD_TWC 0x31d /* ..8 DMMU tablewalk control */ +#define SPR_MD_RPN 0x31e /* ..8 DMMU real (phys) page number */ +#define SPR_MD_TW 0x31f /* ..8 MMU tablewalk scratch */ +#define SPR_MI_CAM 0x330 /* ..8 IMMU CAM entry read */ +#define SPR_MI_RAM0 0x331 /* ..8 IMMU RAM entry read reg 0 */ +#define SPR_MI_RAM1 0x332 /* ..8 IMMU RAM entry read reg 1 */ +#define SPR_MD_CAM 0x338 /* ..8 IMMU CAM entry read */ +#define SPR_MD_RAM0 0x339 /* ..8 IMMU RAM entry read reg 0 */ +#define SPR_MD_RAM1 0x33a /* ..8 IMMU RAM entry read reg 1 */ +#define SPR_UMMCR2 0x3a0 /* .6. User Monitor Mode Control Register 2 */ +#define SPR_UMMCR0 0x3a8 /* .6. User Monitor Mode Control Register 0 */ +#define SPR_USIA 0x3ab /* .6. User Sampled Instruction Address */ +#define SPR_UMMCR1 0x3ac /* .6. User Monitor Mode Control Register 1 */ +#define SPR_ZPR 0x3b0 /* 4.. Zone Protection Register */ +#define SPR_MMCR2 0x3b0 /* .6. Monitor Mode Control Register 2 */ +#define SPR_MMCR2_THRESHMULT_32 0x80000000 /* Multiply MMCR0 threshold by 32 */ +#define SPR_MMCR2_THRESHMULT_2 0x00000000 /* Multiply MMCR0 threshold by 2 */ +#define SPR_PID 0x3b1 /* 4.. Process ID */ +#define SPR_PMC5 0x3b1 /* .6. Performance Counter Register 5 */ +#define SPR_PMC6 0x3b2 /* .6. Performance Counter Register 6 */ +#define SPR_CCR0 0x3b3 /* 4.. Core Configuration Register 0 */ +#define SPR_IAC3 0x3b4 /* 4.. Instruction Address Compare 3 */ +#define SPR_IAC4 0x3b5 /* 4.. Instruction Address Compare 4 */ +#define SPR_DVC1 0x3b6 /* 4.. Data Value Compare 1 */ +#define SPR_DVC2 0x3b7 /* 4.. Data Value Compare 2 */ +#define SPR_MMCR0 0x3b8 /* .6. Monitor Mode Control Register 0 */ +#define SPR_MMCR0_FC 0x80000000 /* Freeze counters */ +#define SPR_MMCR0_FCS 0x40000000 /* Freeze counters in supervisor mode */ +#define SPR_MMCR0_FCP 0x20000000 /* Freeze counters in user mode */ +#define SPR_MMCR0_FCM1 0x10000000 /* Freeze counters when mark=1 */ +#define SPR_MMCR0_FCM0 0x08000000 /* Freeze counters when mark=0 */ +#define SPR_MMCR0_PMXE 0x04000000 /* Enable PM interrupt */ +#define SPR_MMCR0_FCECE 0x02000000 /* Freeze counters after event */ +#define SPR_MMCR0_TBSEL_15 0x01800000 /* Count bit 15 of TBL */ +#define SPR_MMCR0_TBSEL_19 0x01000000 /* Count bit 19 of TBL */ +#define SPR_MMCR0_TBSEL_23 0x00800000 /* Count bit 23 of TBL */ +#define SPR_MMCR0_TBSEL_31 0x00000000 /* Count bit 31 of TBL */ +#define SPR_MMCR0_TBEE 0x00400000 /* Time-base event enable */ +#define SPR_MMCRO_THRESHOLD(x) ((x) << 16) /* Threshold value */ +#define SPR_MMCR0_PMC1CE 0x00008000 /* PMC1 condition enable */ +#define SPR_MMCR0_PMCNCE 0x00004000 /* PMCn condition enable */ +#define SPR_MMCR0_TRIGGER 0x00002000 /* Trigger */ +#define SPR_MMCR0_PMC1SEL(x) ((x) << 6) /* PMC1 selector */ +#define SPR_MMCR0_PMC2SEL(x) ((x) << 0) /* PMC2 selector */ +#define SPR_SGR 0x3b9 /* 4.. Storage Guarded Register */ +#define SPR_PMC1 0x3b9 /* .6. Performance Counter Register 1 */ +#define SPR_DCWR 0x3ba /* 4.. Data Cache Write-through Register */ +#define SPR_PMC2 0x3ba /* .6. Performance Counter Register 2 */ +#define SPR_SLER 0x3bb /* 4.. Storage Little Endian Register */ +#define SPR_SIA 0x3bb /* .6. Sampled Instruction Address */ +#define SPR_MMCR1 0x3bc /* .6. Monitor Mode Control Register 2 */ +#define SPR_MMCR1_PMC3SEL(x) ((x) << 27) /* PMC 3 selector */ +#define SPR_MMCR1_PMC4SEL(x) ((x) << 22) /* PMC 4 selector */ +#define SPR_MMCR1_PMC5SEL(x) ((x) << 17) /* PMC 5 selector */ +#define SPR_MMCR1_PMC6SEL(x) ((x) << 11) /* PMC 6 selector */ + +#define SPR_SU0R 0x3bc /* 4.. Storage User-defined 0 Register */ +#define SPR_DBCR1 0x3bd /* 4.. Debug Control Register 1 */ +#define SPR_PMC3 0x3bd /* .6. Performance Counter Register 3 */ +#define SPR_PMC4 0x3be /* .6. Performance Counter Register 4 */ +#define SPR_DMISS 0x3d0 /* .68 Data TLB Miss Address Register */ +#define SPR_DCMP 0x3d1 /* .68 Data TLB Compare Register */ +#define SPR_HASH1 0x3d2 /* .68 Primary Hash Address Register */ +#define SPR_ICDBDR 0x3d3 /* 4.. Instruction Cache Debug Data Register */ +#define SPR_HASH2 0x3d3 /* .68 Secondary Hash Address Register */ +#define SPR_ESR 0x3d4 /* 4.. Exception Syndrome Register */ +#define ESR_MCI 0x80000000 /* Machine check - instruction */ +#define ESR_PIL 0x08000000 /* Program interrupt - illegal */ +#define ESR_PPR 0x04000000 /* Program interrupt - privileged */ +#define ESR_PTR 0x02000000 /* Program interrupt - trap */ +#define ESR_DST 0x00800000 /* Data storage interrupt - store fault */ +#define ESR_DIZ 0x00800000 /* Data/instruction storage interrupt - zone fault */ +#define ESR_U0F 0x00008000 /* Data storage interrupt - U0 fault */ +#define SPR_IMISS 0x3d4 /* .68 Instruction TLB Miss Address Register */ +#define SPR_TLBMISS 0x3d4 /* .6. TLB Miss Address Register */ +#define SPR_DEAR 0x3d5 /* 4.. Data Error Address Register */ +#define SPR_ICMP 0x3d5 /* .68 Instruction TLB Compare Register */ +#define SPR_PTEHI 0x3d5 /* .6. Instruction TLB Compare Register */ +#define SPR_EVPR 0x3d6 /* 4.. Exception Vector Prefix Register */ +#define SPR_RPA 0x3d6 /* .68 Required Physical Address Register */ +#define SPR_PTELO 0x3d6 /* .6. Required Physical Address Register */ +#define SPR_TSR 0x3d8 /* 4.. Timer Status Register */ +#define TSR_ENW 0x80000000 /* Enable Next Watchdog */ +#define TSR_WIS 0x40000000 /* Watchdog Interrupt Status */ +#define TSR_WRS_MASK 0x30000000 /* Watchdog Reset Status */ +#define TSR_WRS_NONE 0x00000000 /* No watchdog reset has occurred */ +#define TSR_WRS_CORE 0x10000000 /* Core reset was forced by the watchdog */ +#define TSR_WRS_CHIP 0x20000000 /* Chip reset was forced by the watchdog */ +#define TSR_WRS_SYSTEM 0x30000000 /* System reset was forced by the watchdog */ +#define TSR_PIS 0x08000000 /* PIT Interrupt Status */ +#define TSR_FIS 0x04000000 /* FIT Interrupt Status */ +#define SPR_TCR 0x3da /* 4.. Timer Control Register */ +#define TCR_WP_MASK 0xc0000000 /* Watchdog Period mask */ +#define TCR_WP_2_17 0x00000000 /* 2**17 clocks */ +#define TCR_WP_2_21 0x40000000 /* 2**21 clocks */ +#define TCR_WP_2_25 0x80000000 /* 2**25 clocks */ +#define TCR_WP_2_29 0xc0000000 /* 2**29 clocks */ +#define TCR_WRC_MASK 0x30000000 /* Watchdog Reset Control mask */ +#define TCR_WRC_NONE 0x00000000 /* No watchdog reset */ +#define TCR_WRC_CORE 0x10000000 /* Core reset */ +#define TCR_WRC_CHIP 0x20000000 /* Chip reset */ +#define TCR_WRC_SYSTEM 0x30000000 /* System reset */ +#define TCR_WIE 0x08000000 /* Watchdog Interrupt Enable */ +#define TCR_PIE 0x04000000 /* PIT Interrupt Enable */ +#define TCR_FP_MASK 0x03000000 /* FIT Period */ +#define TCR_FP_2_9 0x00000000 /* 2**9 clocks */ +#define TCR_FP_2_13 0x01000000 /* 2**13 clocks */ +#define TCR_FP_2_17 0x02000000 /* 2**17 clocks */ +#define TCR_FP_2_21 0x03000000 /* 2**21 clocks */ +#define TCR_FIE 0x00800000 /* FIT Interrupt Enable */ +#define TCR_ARE 0x00400000 /* Auto Reload Enable */ +#define SPR_PIT 0x3db /* 4.. Programmable Interval Timer */ +#define SPR_SRR2 0x3de /* 4.. Save/Restore Register 2 */ +#define SPR_SRR3 0x3df /* 4.. Save/Restore Register 3 */ +#define SPR_DBSR 0x3f0 /* 4.. Debug Status Register */ +#define DBSR_IC 0x80000000 /* Instruction completion debug event */ +#define DBSR_BT 0x40000000 /* Branch Taken debug event */ +#define DBSR_EDE 0x20000000 /* Exception debug event */ +#define DBSR_TIE 0x10000000 /* Trap Instruction debug event */ +#define DBSR_UDE 0x08000000 /* Unconditional debug event */ +#define DBSR_IA1 0x04000000 /* IAC1 debug event */ +#define DBSR_IA2 0x02000000 /* IAC2 debug event */ +#define DBSR_DR1 0x01000000 /* DAC1 Read debug event */ +#define DBSR_DW1 0x00800000 /* DAC1 Write debug event */ +#define DBSR_DR2 0x00400000 /* DAC2 Read debug event */ +#define DBSR_DW2 0x00200000 /* DAC2 Write debug event */ +#define DBSR_IDE 0x00100000 /* Imprecise debug event */ +#define DBSR_IA3 0x00080000 /* IAC3 debug event */ +#define DBSR_IA4 0x00040000 /* IAC4 debug event */ +#define DBSR_MRR 0x00000300 /* Most recent reset */ +#define SPR_HID0 0x3f0 /* ..8 Hardware Implementation Register 0 */ +#define SPR_HID1 0x3f1 /* ..8 Hardware Implementation Register 1 */ +#define SPR_DBCR0 0x3f2 /* 4.. Debug Control Register 0 */ +#define DBCR0_EDM 0x80000000 /* External Debug Mode */ +#define DBCR0_IDM 0x40000000 /* Internal Debug Mode */ +#define DBCR0_RST_MASK 0x30000000 /* ReSeT */ +#define DBCR0_RST_NONE 0x00000000 /* No action */ +#define DBCR0_RST_CORE 0x10000000 /* Core reset */ +#define DBCR0_RST_CHIP 0x20000000 /* Chip reset */ +#define DBCR0_RST_SYSTEM 0x30000000 /* System reset */ +#define DBCR0_IC 0x08000000 /* Instruction Completion debug event */ +#define DBCR0_BT 0x04000000 /* Branch Taken debug event */ +#define DBCR0_EDE 0x02000000 /* Exception Debug Event */ +#define DBCR0_TDE 0x01000000 /* Trap Debug Event */ +#define DBCR0_IA1 0x00800000 /* IAC (Instruction Address Compare) 1 debug event */ +#define DBCR0_IA2 0x00400000 /* IAC 2 debug event */ +#define DBCR0_IA12 0x00200000 /* Instruction Address Range Compare 1-2 */ +#define DBCR0_IA12X 0x00100000 /* IA12 eXclusive */ +#define DBCR0_IA3 0x00080000 /* IAC 3 debug event */ +#define DBCR0_IA4 0x00040000 /* IAC 4 debug event */ +#define DBCR0_IA34 0x00020000 /* Instruction Address Range Compare 3-4 */ +#define DBCR0_IA34X 0x00010000 /* IA34 eXclusive */ +#define DBCR0_IA12T 0x00008000 /* Instruction Address Range Compare 1-2 range Toggle */ +#define DBCR0_IA34T 0x00004000 /* Instruction Address Range Compare 3-4 range Toggle */ +#define DBCR0_FT 0x00000001 /* Freeze Timers on debug event */ +#define SPR_IABR 0x3f2 /* ..8 Instruction Address Breakpoint Register 0 */ +#define SPR_HID2 0x3f3 /* ..8 Hardware Implementation Register 2 */ +#define SPR_IAC1 0x3f4 /* 4.. Instruction Address Compare 1 */ +#define SPR_IAC2 0x3f5 /* 4.. Instruction Address Compare 2 */ +#define SPR_DABR 0x3f5 /* .6. Data Address Breakpoint Register */ +#define SPR_DAC1 0x3f6 /* 4.. Data Address Compare 1 */ +#define SPR_MSSCR0 0x3f6 /* .6. Memory SubSystem Control Register */ +#define MSSCR0_SHDEN 0x80000000 /* 0: Shared-state enable */ +#define MSSCR0_SHDPEN3 0x40000000 /* 1: ~SHD[01] signal enable in MEI mode */ +#define MSSCR0_L1INTVEN 0x38000000 /* 2-4: L1 data cache ~HIT intervention enable */ +#define MSSCR0_L2INTVEN 0x07000000 /* 5-7: L2 data cache ~HIT intervention enable*/ +#define MSSCR0_DL1HWF 0x00800000 /* 8: L1 data cache hardware flush */ +#define MSSCR0_MBO 0x00400000 /* 9: must be one */ +#define MSSCR0_EMODE 0x00200000 /* 10: MPX bus mode (read-only) */ +#define MSSCR0_ABD 0x00100000 /* 11: address bus driven (read-only) */ +#define MSSCR0_MBZ 0x000fffff /* 12-31: must be zero */ +#define SPR_DAC2 0x3f7 /* 4.. Data Address Compare 2 */ +#define SPR_L2PM 0x3f8 /* .6. L2 Private Memory Control Register */ +#define SPR_L2CR 0x3f9 /* .6. L2 Control Register */ +#define L2CR_L2E 0x80000000 /* 0: L2 enable */ +#define L2CR_L2PE 0x40000000 /* 1: L2 data parity enable */ +#define L2CR_L2SIZ 0x30000000 /* 2-3: L2 size */ +#define L2SIZ_2M 0x00000000 +#define L2SIZ_256K 0x10000000 +#define L2SIZ_512K 0x20000000 +#define L2SIZ_1M 0x30000000 +#define L2CR_L2CLK 0x0e000000 /* 4-6: L2 clock ratio */ +#define L2CLK_DIS 0x00000000 /* disable L2 clock */ +#define L2CLK_10 0x02000000 /* core clock / 1 */ +#define L2CLK_15 0x04000000 /* / 1.5 */ +#define L2CLK_20 0x08000000 /* / 2 */ +#define L2CLK_25 0x0a000000 /* / 2.5 */ +#define L2CLK_30 0x0c000000 /* / 3 */ +#define L2CR_L2RAM 0x01800000 /* 7-8: L2 RAM type */ +#define L2RAM_FLOWTHRU_BURST 0x00000000 +#define L2RAM_PIPELINE_BURST 0x01000000 +#define L2RAM_PIPELINE_LATE 0x01800000 +#define L2CR_L2DO 0x00400000 /* 9: L2 data-only. + Setting this bit disables instruction + caching. */ +#define L2CR_L2I 0x00200000 /* 10: L2 global invalidate. */ +#define L2CR_L2CTL 0x00100000 /* 11: L2 RAM control (ZZ enable). + Enables automatic operation of the + L2ZZ (low-power mode) signal. */ +#define L2CR_L2WT 0x00080000 /* 12: L2 write-through. */ +#define L2CR_L2TS 0x00040000 /* 13: L2 test support. */ +#define L2CR_L2OH 0x00030000 /* 14-15: L2 output hold. */ +#define L2CR_L2SL 0x00008000 /* 16: L2 DLL slow. */ +#define L2CR_L2DF 0x00004000 /* 17: L2 differential clock. */ +#define L2CR_L2BYP 0x00002000 /* 18: L2 DLL bypass. */ +#define L2CR_L2FA 0x00001000 /* 19: L2 flush assist (for software flush). */ +#define L2CR_L2HWF 0x00000800 /* 20: L2 hardware flush. */ +#define L2CR_L2IO 0x00000400 /* 21: L2 instruction-only. */ +#define L2CR_L2CLKSTP 0x00000200 /* 22: L2 clock stop. */ +#define L2CR_L2DRO 0x00000100 /* 23: L2DLL rollover checkstop enable. */ +#define L2CR_L2IP 0x00000001 /* 31: L2 global invalidate in */ + /* progress (read only). */ +#define SPR_L3CR 0x3fa /* .6. L3 Control Register */ +#define L3CR_L3E 0x80000000 /* 0: L3 enable */ +#define L3CR_L3SIZ 0x10000000 /* 3: L3 size (0=1MB, 1=2MB) */ +#define SPR_DCCR 0x3fa /* 4.. Data Cache Cachability Register */ +#define SPR_ICCR 0x3fb /* 4.. Instruction Cache Cachability Register */ +#define SPR_THRM1 0x3fc /* .6. Thermal Management Register */ +#define SPR_THRM2 0x3fd /* .6. Thermal Management Register */ +#define SPR_THRM_TIN 0x80000000 /* Thermal interrupt bit (RO) */ +#define SPR_THRM_TIV 0x40000000 /* Thermal interrupt valid (RO) */ +#define SPR_THRM_THRESHOLD(x) ((x) << 23) /* Thermal sensor threshold */ +#define SPR_THRM_TID 0x00000004 /* Thermal interrupt direction */ +#define SPR_THRM_TIE 0x00000002 /* Thermal interrupt enable */ +#define SPR_THRM_VALID 0x00000001 /* Valid bit */ +#define SPR_THRM3 0x3fe /* .6. Thermal Management Register */ +#define SPR_THRM_TIMER(x) ((x) << 1) /* Sampling interval timer */ +#define SPR_THRM_ENABLE 0x00000001 /* TAU Enable */ +#define SPR_FPECR 0x3fe /* .6. Floating-Point Exception Cause Register */ +#define SPR_PIR 0x3ff /* .6. Processor Identification Register */ + +/* Time Base Register declarations */ +#define TBR_TBL 0x10c /* 468 Time Base Lower */ +#define TBR_TBU 0x10d /* 468 Time Base Upper */ + +/* Performance counter declarations */ +#define PMC_OVERFLOW 0x80000000 /* Counter has overflowed */ + +/* The first five countable [non-]events are common to all the PMC's */ +#define PMCN_NONE 0 /* Count nothing */ +#define PMCN_CYCLES 1 /* Processor cycles */ +#define PMCN_ICOMP 2 /* Instructions completed */ +#define PMCN_TBLTRANS 3 /* TBL bit transitions */ +#define PCMN_IDISPATCH 4 /* Instructions dispatched */ + +#endif /* !_POWERPC_SPR_H_ */ diff --git a/sys/powerpc/include/sr.h b/sys/powerpc/include/sr.h new file mode 100644 index 000000000000..2ef7b3585076 --- /dev/null +++ b/sys/powerpc/include/sr.h @@ -0,0 +1,56 @@ +/*- + * Copyright (C) 2002 Benno Rice. + * 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 Benno Rice ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_SR_H_ +#define _MACHINE_SR_H_ + +/* + * Bit definitions for segment registers. + * + * PowerPC Microprocessor Family: The Programming Environments for 32-bit + * Microprocessors, section 2.3.5 + */ + +#define SR_TYPE 0x80000000 /* Type selector */ +#define SR_KS 0x40000000 /* Supervisor-state protection key */ +#define SR_KP 0x20000000 /* User-state protection key */ +#define SR_N 0x10000000 /* No-execute protection */ +#define SR_VSID_MASK 0x00ffffff /* Virtual Segment ID mask */ + +/* Kernel segment register usage */ +#define USER_SR 12 +#define KERNEL_SR 13 +#define KERNEL2_SR 14 +#define KERNEL_VSIDBITS 0xfffff +#define KERNEL_SEGMENT (0xfffff0 + KERNEL_SR) +#define KERNEL2_SEGMENT (0xfffff0 + KERNEL2_SR) +#define EMPTY_SEGMENT 0xfffff0 +#define USER_ADDR ((void *)(USER_SR << ADDR_SR_SHFT)) +#define SEGMENT_LENGTH 0x10000000 +#define SEGMENT_MASK 0xf0000000 + +#endif /* !_MACHINE_SR_H_ */ diff --git a/sys/powerpc/include/stdarg.h b/sys/powerpc/include/stdarg.h new file mode 100644 index 000000000000..e81aab30b5c0 --- /dev/null +++ b/sys/powerpc/include/stdarg.h @@ -0,0 +1,150 @@ +/*- + * Copyright (c) 2002 David E. O'Brien. All rights reserved. + * Copyright (c) 2000 Tsubai Masanari. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: stdarg.h,v 1.5 2000/02/27 17:50:21 tsubai Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_STDARG_H_ +#define _MACHINE_STDARG_H_ + +#include <sys/cdefs.h> +#include <sys/_types.h> + +#ifndef _VA_LIST_DECLARED +#define _VA_LIST_DECLARED +typedef __va_list va_list; +#endif + +#if defined(__GNUCLIKE_BUILTIN_STDARG) + +#define va_start(ap, last) \ + __builtin_va_start((ap), (last)) + +#define va_arg(ap, type) \ + __builtin_va_arg((ap), type) + +#if __ISO_C_VISIBLE >= 1999 +#define va_copy(dest, src) \ + __builtin_va_copy((dest), (src)) + +#define __va_copy(dest, src) \ + va_copy((dest), (src)) +#endif + +#define va_end(ap) \ + __builtin_va_end(ap) + +#else /* !__GNUCLIKE_BUILTIN_STDARG */ + +#ifdef __lint__ + +#define va_start(ap, last) ((ap) = *(va_list *)0) +#define va_arg(ap, type) (*(type *)(void *)&(ap)) + +#else + +#if defined(__GNUC_VA_LIST_COMPATIBILITY) +#define va_start(ap, last) \ + (__builtin_next_arg(last), \ + __builtin_memcpy((void *)&(ap), __builtin_saveregs (), \ + sizeof(__gnuc_va_list))) +#else +#define va_start(ap, last) \ + (__builtin_next_arg(last), \ + (ap).__stack = __va_stack_args, \ + (ap).__base = __va_reg_args, \ + (ap).__gpr = __va_first_gpr, \ + (ap).__fpr = __va_first_fpr) +#endif + +#define __va_first_gpr (__builtin_args_info(0)) +#define __va_first_fpr (__builtin_args_info(1) - 32 - 1) +#define __va_stack_args \ + ((char *)__builtin_saveregs() + \ + (__va_first_gpr >= 8 ? __va_first_gpr - 8 : 0) * sizeof(int)) +#define __va_reg_args \ + ((char *)__builtin_frame_address(0) + __builtin_args_info(4)) + +#define __INTEGER_TYPE_CLASS 1 +#define __REAL_TYPE_CLASS 8 +#define __RECORD_TYPE_CLASS 12 + +#define __va_longlong(type) \ + (__builtin_classify_type(*(type *)0) == __INTEGER_TYPE_CLASS && \ + sizeof(type) == 8) + +#define __va_double(type) \ + (__builtin_classify_type(*(type *)0) == __REAL_TYPE_CLASS) + +#define __va_struct(type) \ + (__builtin_classify_type(*(type *)0) >= __RECORD_TYPE_CLASS) + +#define __va_size(type) \ + ((sizeof(type) + sizeof(int) - 1) / sizeof(int) * sizeof(int)) + +#define __va_savedgpr(ap, type) \ + ((ap).__base + (ap).__gpr * sizeof(int) - sizeof(type)) + +#define __va_savedfpr(ap, type) \ + ((ap).__base + 8 * sizeof(int) + (ap).__fpr * sizeof(double) - \ + sizeof(type)) + +#define __va_stack(ap, type) \ + ((ap).__stack += __va_size(type) + \ + (__va_longlong(type) ? (int)(ap).__stack & 4 : 0), \ + (ap).__stack - sizeof(type)) + +#define __va_gpr(ap, type) \ + ((ap).__gpr += __va_size(type) / sizeof(int) + \ + (__va_longlong(type) ? (ap).__gpr & 1 : 0), \ + (ap).__gpr <= 8 ? __va_savedgpr(ap, type) : __va_stack(ap, type)) + +#define __va_fpr(ap, type) \ + ((ap).__fpr++, \ + (ap).__fpr <= 8 ? __va_savedfpr(ap, type) : __va_stack(ap, type)) + +#define va_arg(ap, type) \ + (*(type *)(__va_struct(type) ? (*(void **)__va_gpr(ap, void *)) : \ + __va_double(type) ? __va_fpr(ap, type) : \ + __va_gpr(ap, type))) + +#endif /* __lint__ */ + +#define va_end(ap) + +#if __ISO_C_VISIBLE >= 1999 +#if !defined(_ANSI_SOURCE) && \ + (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE) || \ + defined(_ISOC99_SOURCE) || (__STDC_VERSION__ - 0) >= 199901L) +#define va_copy(dest, src) \ + ((dest) = (src)) +#endif +#endif + +#endif /* __GNUCLIKE_BUILTIN_STDARG */ + +#endif /* _MACHINE_STDARG_H_ */ diff --git a/sys/powerpc/include/trap.h b/sys/powerpc/include/trap.h new file mode 100644 index 000000000000..18778a84cf8c --- /dev/null +++ b/sys/powerpc/include/trap.h @@ -0,0 +1,113 @@ +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: trap.h,v 1.7 2002/02/22 13:51:40 kleink Exp $ + * $FreeBSD$ + */ + +#ifndef _POWERPC_TRAP_H_ +#define _POWERPC_TRAP_H_ + +#define EXC_RSVD 0x0000 /* Reserved */ +#define EXC_RST 0x0100 /* Reset; all but IBM4xx */ +#define EXC_MCHK 0x0200 /* Machine Check */ +#define EXC_DSI 0x0300 /* Data Storage Interrupt */ +#define EXC_ISI 0x0400 /* Instruction Storage Interrupt */ +#define EXC_EXI 0x0500 /* External Interrupt */ +#define EXC_ALI 0x0600 /* Alignment Interrupt */ +#define EXC_PGM 0x0700 /* Program Interrupt */ +#define EXC_FPU 0x0800 /* Floating-point Unavailable */ +#define EXC_DECR 0x0900 /* Decrementer Interrupt */ +#define EXC_SC 0x0c00 /* System Call */ +#define EXC_TRC 0x0d00 /* Trace */ +#define EXC_FPA 0x0e00 /* Floating-point Assist */ + +/* The following is only available on the 601: */ +#define EXC_RUNMODETRC 0x2000 /* Run Mode/Trace Exception */ + +/* The following are only available on 7400(G4): */ +#define EXC_VEC 0x0f20 /* AltiVec Unavailable */ +#define EXC_VECAST 0x1600 /* AltiVec Assist */ + +/* The following are only available on 604/750/7400: */ +#define EXC_PERF 0x0f00 /* Performance Monitoring */ +#define EXC_BPT 0x1300 /* Instruction Breakpoint */ +#define EXC_SMI 0x1400 /* System Managment Interrupt */ + +/* The following are only available on 750/7400: */ +#define EXC_THRM 0x1700 /* Thermal Management Interrupt */ + +/* And these are only on the 603: */ +#define EXC_IMISS 0x1000 /* Instruction translation miss */ +#define EXC_DLMISS 0x1100 /* Data load translation miss */ +#define EXC_DSMISS 0x1200 /* Data store translation miss */ + +/* The following are only available on 405 (and 403?) */ +#define EXC_CII 0x0100 /* Critical Input Interrupt */ +#define EXC_PIT 0x1000 /* Programmable Interval Timer */ +#define EXC_FIT 0x1010 /* Fixed Interval Timer */ +#define EXC_WDOG 0x1020 /* Watchdog Timer */ +#define EXC_DTMISS 0x1100 /* Data TLB Miss */ +#define EXC_ITMISS 0x1200 /* Instruction TLB Miss */ +#define EXC_DEBUG 0x2000 /* Debug trap */ + +#define EXC_LAST 0x2f00 /* Last possible exception vector */ + +#define EXC_AST 0x3000 /* Fake AST vector */ + +/* Trap was in user mode */ +#define EXC_USER 0x10000 + + +/* + * EXC_ALI sets bits in the DSISR and DAR to provide enough + * information to recover from the unaligned access without needing to + * parse the offending instruction. This includes certain bits of the + * opcode, and information about what registers are used. The opcode + * indicator values below come from Appendix F of Book III of "The + * PowerPC Architecture". + */ + +#define EXC_ALI_OPCODE_INDICATOR(dsisr) ((dsisr >> 10) & 0x7f) +#define EXC_ALI_LFD 0x09 +#define EXC_ALI_STFD 0x0b + +/* Macros to extract register information */ +#define EXC_ALI_RST(dsisr) ((dsisr >> 5) & 0x1f) /* source or target */ +#define EXC_ALI_RA(dsisr) (dsisr & 0x1f) + +#ifndef LOCORE + +struct trapframe; +void trap(struct trapframe *); + +#endif + +#endif /* _POWERPC_TRAP_H_ */ diff --git a/sys/powerpc/include/ucontext.h b/sys/powerpc/include/ucontext.h new file mode 100644 index 000000000000..58b6a80bd2ac --- /dev/null +++ b/sys/powerpc/include/ucontext.h @@ -0,0 +1,73 @@ +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: signal.h,v 1.4 1998/09/14 02:48:34 thorpej Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_UCONTEXT_H_ +#define _MACHINE_UCONTEXT_H_ + +typedef struct __mcontext { + int mc_vers; + int mc_flags; +#define _MC_FP_VALID 0x01 +#define _MC_AV_VALID 0x02 + int mc_onstack; /* saved onstack flag */ + int mc_len; /* sizeof(__mcontext) */ + uint64_t mc_avec[32*2]; /* vector register file */ + uint32_t mc_av[2]; + uint32_t mc_frame[41]; + uint64_t mc_fpreg[33]; +} mcontext_t __aligned(16); + +/* GPRs and supervisor-level regs */ +#define mc_gpr mc_frame +#define mc_lr mc_frame[32] +#define mc_cr mc_frame[33] +#define mc_xer mc_frame[34] +#define mc_ctr mc_frame[35] +#define mc_srr0 mc_frame[36] +#define mc_srr1 mc_frame[37] +#define mc_dar mc_frame[38] +#define mc_dsisr mc_frame[39] +#define mc_exc mc_frame[40] + +/* floating-point state */ +#define mc_fpscr mc_fpreg[32] + +/* altivec state */ +#define mc_vscr mc_av[0] +#define mc_vrsave mc_av[1] + +#define _MC_VERSION 0x1 +#define _MC_VERSION_KSE 0xee /* partial ucontext for libpthread */ + +#endif /* !_MACHINE_UCONTEXT_H_ */ diff --git a/sys/powerpc/include/varargs.h b/sys/powerpc/include/varargs.h new file mode 100644 index 000000000000..fed04c9463ed --- /dev/null +++ b/sys/powerpc/include/varargs.h @@ -0,0 +1,80 @@ +/*- + * Copyright (c) 2002 David E. O'Brien. All rights reserved. + * Copyright (c) 2000 Tsubai Masanari. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + * $NetBSD: varargs.h,v 1.5 2000/02/27 17:50:22 tsubai Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_VARARGS_H_ +#define _MACHINE_VARARGS_H_ + +#ifndef _SYS_CDEFS_H_ +#error this file needs sys/cdefs.h as a prerequisite +#endif + +#if defined(__GNUCLIKE_BUILTIN_VARARGS) + +#include <sys/_types.h> + +#ifndef _VA_LIST_DECLARED +#define _VA_LIST_DECLARED +typedef __va_list va_list; +#endif + +typedef int __builtin_va_alist_t __attribute__((__mode__(__word__))); + +#define va_alist __builtin_va_alist +#define va_dcl __builtin_va_alist_t __builtin_va_alist; ... +#define va_start(ap) __builtin_varargs_start(ap) +#define va_arg(ap, type) __builtin_va_arg((ap), type) +#define va_end(ap) __builtin_va_end(ap) + +#else /* ! __GNUCLIKE_BUILTIN_VARARGS */ + +#include <machine/stdarg.h> + +#ifdef __GNUCLIKE_BUILTIN_VAALIST +#define va_alist __builtin_va_alist +#define va_dcl int __builtin_va_alist; ... +#else +#error this file needs to be ported to your compiler +#endif + +#undef va_start + +#ifdef __lint__ +#define va_start(ap) ((ap) = *(va_list *)0) +#else +#define va_start(ap) \ + ((ap).__stack = __va_stack_args, \ + (ap).__base = __va_reg_args, \ + (ap).__gpr = __va_first_gpr, \ + (ap).__fpr = __va_first_fpr) +#endif + +#endif /* __GNUCLIKE_BUILTIN_VARARGS */ + +#endif /* _MACHINE_VARARGS_H_ */ diff --git a/sys/powerpc/include/vmparam.h b/sys/powerpc/include/vmparam.h new file mode 100644 index 000000000000..0f8298e05c55 --- /dev/null +++ b/sys/powerpc/include/vmparam.h @@ -0,0 +1,146 @@ +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: vmparam.h,v 1.11 2000/02/11 19:25:16 thorpej Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_VMPARAM_H_ +#define _MACHINE_VMPARAM_H_ + +#define USRSTACK VM_MAXUSER_ADDRESS + +#ifndef MAXTSIZ +#define MAXTSIZ (16*1024*1024) /* max text size */ +#endif + +#ifndef DFLDSIZ +#define DFLDSIZ (32*1024*1024) /* default data size */ +#endif + +#ifndef MAXDSIZ +#define MAXDSIZ (512*1024*1024) /* max data size */ +#endif + +#ifndef DFLSSIZ +#define DFLSSIZ (1*1024*1024) /* default stack size */ +#endif + +#ifndef MAXSSIZ +#define MAXSSIZ (32*1024*1024) /* max stack size */ +#endif + +/* + * Size of shared memory map + */ +#ifndef SHMMAXPGS +#define SHMMAXPGS 1024 +#endif + +/* + * The time for a process to be blocked before being very swappable. + * This is a number of seconds which the system takes as being a non-trivial + * amount of real time. You probably shouldn't change this; + * it is used in subtle ways (fractions and multiples of it are, that is, like + * half of a ``long time'', almost a long time, etc.) + * It is related to human patience and other factors which don't really + * change over time. + */ +#define MAXSLP 20 + +/* + * Use the direct-mapped BAT registers for UMA small allocs. This + * takes pressure off the small amount of available KVA. + */ +#define UMA_MD_SMALL_ALLOC + +/* + * Would like to have MAX addresses = 0, but this doesn't (currently) work + */ +#define VM_MIN_ADDRESS ((vm_offset_t)0) +#define VM_MAXUSER_ADDRESS ((vm_offset_t)0x7ffff000) +#define VM_MAX_ADDRESS VM_MAXUSER_ADDRESS +#define VM_MIN_KERNEL_ADDRESS ((vm_offset_t)(KERNEL_SR << ADDR_SR_SHFT)) +#define VM_MAX_KERNEL_ADDRESS (VM_MIN_KERNEL_ADDRESS + 2*SEGMENT_LENGTH - 1) + +#define KERNBASE 0x100000 /* start of kernel virtual */ + +/* XXX max. amount of KVM to be used by buffers. */ +#ifndef VM_MAX_KERNEL_BUF +#define VM_MAX_KERNEL_BUF (SEGMENT_LENGTH * 7 / 10) +#endif + +struct pmap_physseg { + struct pv_entry *pvent; + char *attrs; +}; + +#define VM_PHYSSEG_MAX 16 /* 1? */ + +/* + * The physical address space is densely populated. + */ +#define VM_PHYSSEG_DENSE + +/* + * Create three free page pools: VM_FREEPOOL_DEFAULT is the default pool + * from which physical pages are allocated and VM_FREEPOOL_DIRECT is + * the pool from which physical pages for small UMA objects are + * allocated. + */ +#define VM_NFREEPOOL 3 +#define VM_FREEPOOL_CACHE 2 +#define VM_FREEPOOL_DEFAULT 0 +#define VM_FREEPOOL_DIRECT 1 + +/* + * Create one free page list. + */ +#define VM_NFREELIST 1 +#define VM_FREELIST_DEFAULT 0 + +/* + * The largest allocation size is 4MB. + */ +#define VM_NFREEORDER 11 + +#ifndef VM_INITIAL_PAGEIN +#define VM_INITIAL_PAGEIN 16 +#endif + +#ifndef SGROWSIZ +#define SGROWSIZ (128UL*1024) /* amount to grow stack */ +#endif + +#ifndef VM_KMEM_SIZE +#define VM_KMEM_SIZE (12 * 1024 * 1024) +#endif + +#endif /* _MACHINE_VMPARAM_H_ */ diff --git a/sys/powerpc/ofw/ofw_pci.c b/sys/powerpc/ofw/ofw_pci.c new file mode 100644 index 000000000000..ca4b36eb0456 --- /dev/null +++ b/sys/powerpc/ofw/ofw_pci.c @@ -0,0 +1,229 @@ +/*- + * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. + * Copyright (c) 1994 Charles M. Hannum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles M. Hannum. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from NetBSD: pci_machdep.c,v 1.18 2001/07/22 11:29:48 wiz Exp + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> + +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_pci.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> + +#include <powerpc/ofw/ofw_pci.h> + +#include "pcib_if.h" + +static void fixup_node(device_t, phandle_t); +static int find_node_intr(phandle_t, u_int32_t *, u_int32_t *); + +phandle_t +ofw_pci_find_node(device_t dev) +{ + phandle_t node, nextnode; + struct ofw_pci_register pcir; + int l, b, s, f; + + for (node = OF_peer(0); node; node = nextnode) { + l = OF_getprop(node, "reg", &pcir, sizeof(pcir)); + if (l > 4) { + b = OFW_PCI_PHYS_HI_BUS(pcir.phys_hi); + s = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi); + f = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi); + + if (b == pci_get_bus(dev) && s == pci_get_slot(dev) && + f == pci_get_function(dev)) + return (node); + } + + if ((nextnode = OF_child(node))) + continue; + while (node) { + if ((nextnode = OF_peer(node)) != 0) + break; + node = OF_parent(node); + } + } + + return (0); +} + +void +ofw_pci_fixup(device_t dev, u_int bus, phandle_t parentnode) +{ + phandle_t node; + + for (node = OF_child(parentnode); node; node = OF_peer(node)) { + fixup_node(dev, node); + } +} + +static void +fixup_node(device_t dev, phandle_t node) +{ + u_int32_t csr, intr, irqs[4], npintr, paddr[4]; + struct ofw_pci_register addr[8]; + int len, i; + + len = OF_getprop(node, "assigned-addresses", addr, sizeof(addr)); + if (len < (int)sizeof(struct ofw_pci_register)) { + return; + } + + csr = PCIB_READ_CONFIG(dev, OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi), + OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi), + OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_COMMAND, 4); + csr &= ~(PCIM_CMD_PORTEN | PCIM_CMD_MEMEN); + + for (i = 0; i < len / sizeof(struct ofw_pci_register); i++) { + switch (addr[i].phys_hi & OFW_PCI_PHYS_HI_SPACEMASK) { + case OFW_PCI_PHYS_HI_SPACE_IO: + csr |= PCIM_CMD_PORTEN; + break; + case OFW_PCI_PHYS_HI_SPACE_MEM32: + csr |= PCIM_CMD_MEMEN; + break; + } + } + + PCIB_WRITE_CONFIG(dev, OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi), + OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi), + OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_COMMAND, csr, 4); + + /* + * Create PCI interrupt-map array element. pci-mid/pci-lo + * aren't required, but the 'interrupts' property needs + * to be appended + */ + npintr = 0; + OF_getprop(node, "interrupts", &npintr, 4); + paddr[0] = addr[0].phys_hi; + paddr[1] = 0; + paddr[2] = 0; + paddr[3] = npintr; + + if (find_node_intr(node, paddr, irqs) != -1) { + intr = PCIB_READ_CONFIG(dev, + OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi), + OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi), + OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_INTLINE, 2); + intr &= ~(0xff); + intr |= irqs[0] & 0xff; + PCIB_WRITE_CONFIG(dev, + OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi), + OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi), + OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_INTLINE, + intr, 2); + } + +} + +static int +find_node_intr(phandle_t node, u_int32_t *addr, u_int32_t *intr) +{ + phandle_t parent, iparent; + int len, mlen, match, i; + u_int32_t map[160], *mp, imask[8], maskedaddr[8], icells; + char name[32]; + + len = OF_getprop(node, "AAPL,interrupts", intr, 4); + if (len == 4) { + return (len); + } + + parent = OF_parent(node); + len = OF_getprop(parent, "interrupt-map", map, sizeof(map)); + mlen = OF_getprop(parent, "interrupt-map-mask", imask, sizeof(imask)); + + if (len == -1 || mlen == -1) + goto nomap; + + memcpy(maskedaddr, addr, mlen); + for (i = 0; i < mlen/4; i++) + maskedaddr[i] &= imask[i]; + + mp = map; + while (len > mlen) { + match = bcmp(maskedaddr, mp, mlen); + mp += mlen / 4; + len -= mlen; + + /* + * We must read "#interrupt-cells" for each time because + * interrupt-parent may be different. + */ + iparent = *mp++; + len -= 4; + if (OF_getprop(iparent, "#interrupt-cells", &icells, 4) != 4) + goto nomap; + + /* Found. */ + if (match == 0) { + bcopy(mp, intr, icells * 4); + return (icells * 4); + } + + mp += icells; + len -= icells * 4; + } + +nomap: + /* + * If the node has no interrupt property and the parent is a PCI + * bridge, use the parent's interrupt. This occurs on a PCI slot. + */ + bzero(name, sizeof(name)); + OF_getprop(parent, "name", name, sizeof(name)); + if (strcmp(name, "pci-bridge") == 0) { + len = OF_getprop(parent, "AAPL,interrupts", intr, 4); + if (len == 4) { + return (len); + } + + /* + * XXX I don't know what is the correct local address. + * XXX Use the first entry for now. + */ + len = OF_getprop(parent, "interrupt-map", map, sizeof(map)); + if (len >= 36) { + addr = &map[5]; + /* XXX Use 0 for 'interrupts' for compat */ + return (find_node_intr(parent, addr, intr)); + } + } + + return (-1); +} diff --git a/sys/powerpc/ofw/ofw_pci.h b/sys/powerpc/ofw/ofw_pci.h new file mode 100644 index 000000000000..8d78f9189e80 --- /dev/null +++ b/sys/powerpc/ofw/ofw_pci.h @@ -0,0 +1,34 @@ +/*- + * Copyright (C) 2002 Benno Rice. + * 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 Benno Rice ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _POWERPC_OFW_PCI_H_ +#define _POWERPC_OFW_PCI_H_ + +phandle_t ofw_pci_find_node(device_t); +void ofw_pci_fixup(device_t, u_int, phandle_t); + +#endif /* _POWERPC_OFW_PCI_H_ */ diff --git a/sys/powerpc/ofw/ofw_pcib_pci.c b/sys/powerpc/ofw/ofw_pcib_pci.c new file mode 100644 index 000000000000..4cc73c4be34b --- /dev/null +++ b/sys/powerpc/ofw/ofw_pcib_pci.c @@ -0,0 +1,117 @@ +/*- + * Copyright (c) 2000 Michael Smith + * Copyright (c) 2000 BSDi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/malloc.h> +#include <sys/kernel.h> + +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_pci.h> + +#include <powerpc/ofw/ofw_pci.h> + +#include <dev/pci/pcivar.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pcib_private.h> + +#include "pcib_if.h" + +static int ofw_pcib_pci_probe(device_t bus); +static int ofw_pcib_pci_attach(device_t bus); + +static device_method_t ofw_pcib_pci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ofw_pcib_pci_probe), + DEVMETHOD(device_attach, ofw_pcib_pci_attach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_read_ivar, pcib_read_ivar), + DEVMETHOD(bus_write_ivar, pcib_write_ivar), + DEVMETHOD(bus_alloc_resource, pcib_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + /* pcib interface */ + DEVMETHOD(pcib_maxslots, pcib_maxslots), + DEVMETHOD(pcib_read_config, pcib_read_config), + DEVMETHOD(pcib_write_config, pcib_write_config), + DEVMETHOD(pcib_route_interrupt, pcib_route_interrupt), + + {0, 0} +}; + +static devclass_t pcib_devclass; + +DEFINE_CLASS_0(pcib, ofw_pcib_pci_driver, ofw_pcib_pci_methods, + sizeof(struct pcib_softc)); +DRIVER_MODULE(ofw_pcib, pci, ofw_pcib_pci_driver, pcib_devclass, 0, 0); + +static int +ofw_pcib_pci_probe(device_t dev) +{ + + if ((pci_get_class(dev) != PCIC_BRIDGE) || + (pci_get_subclass(dev) != PCIS_BRIDGE_PCI)) { + return (ENXIO); + } + if (ofw_pci_find_node(dev) == 0) { + return (ENXIO); + } + + device_set_desc(dev, "Open Firmware PCI-PCI bridge"); + return (-1000); +} + +static int +ofw_pcib_pci_attach(device_t dev) +{ + phandle_t node; + uint32_t busrange[2]; + + node = ofw_pci_find_node(dev); + if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8) + return (ENXIO); + + pcib_attach_common(dev); + + ofw_pci_fixup(dev, busrange[0], node); + + device_add_child(dev, "pci", -1); + + return (bus_generic_attach(dev)); +} diff --git a/sys/powerpc/ofw/ofw_syscons.c b/sys/powerpc/ofw/ofw_syscons.c new file mode 100644 index 000000000000..1296ea6be578 --- /dev/null +++ b/sys/powerpc/ofw/ofw_syscons.c @@ -0,0 +1,932 @@ +/*- + * Copyright (c) 2003 Peter Grehan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/sysctl.h> +#include <sys/limits.h> +#include <sys/conf.h> +#include <sys/cons.h> +#include <sys/proc.h> +#include <sys/fcntl.h> +#include <sys/malloc.h> +#include <sys/fbio.h> +#include <sys/consio.h> + +#include <machine/bus.h> +#include <machine/sc_machdep.h> + +#include <sys/rman.h> + +#include <dev/fb/fbreg.h> +#include <dev/syscons/syscons.h> + +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_pci.h> +#include <powerpc/ofw/ofw_syscons.h> +#include <machine/nexusvar.h> + +static int ofwfb_ignore_mmap_checks; +SYSCTL_NODE(_hw, OID_AUTO, ofwfb, CTLFLAG_RD, 0, "ofwfb"); +SYSCTL_INT(_hw_ofwfb, OID_AUTO, relax_mmap, CTLFLAG_RW, + &ofwfb_ignore_mmap_checks, 0, "relax mmap bounds checking"); + +extern u_char dflt_font_16[]; +extern u_char dflt_font_14[]; +extern u_char dflt_font_8[]; + +static int ofwfb_configure(int flags); + +static vi_probe_t ofwfb_probe; +static vi_init_t ofwfb_init; +static vi_get_info_t ofwfb_get_info; +static vi_query_mode_t ofwfb_query_mode; +static vi_set_mode_t ofwfb_set_mode; +static vi_save_font_t ofwfb_save_font; +static vi_load_font_t ofwfb_load_font; +static vi_show_font_t ofwfb_show_font; +static vi_save_palette_t ofwfb_save_palette; +static vi_load_palette_t ofwfb_load_palette; +static vi_set_border_t ofwfb_set_border; +static vi_save_state_t ofwfb_save_state; +static vi_load_state_t ofwfb_load_state; +static vi_set_win_org_t ofwfb_set_win_org; +static vi_read_hw_cursor_t ofwfb_read_hw_cursor; +static vi_set_hw_cursor_t ofwfb_set_hw_cursor; +static vi_set_hw_cursor_shape_t ofwfb_set_hw_cursor_shape; +static vi_blank_display_t ofwfb_blank_display; +static vi_mmap_t ofwfb_mmap; +static vi_ioctl_t ofwfb_ioctl; +static vi_clear_t ofwfb_clear; +static vi_fill_rect_t ofwfb_fill_rect; +static vi_bitblt_t ofwfb_bitblt; +static vi_diag_t ofwfb_diag; +static vi_save_cursor_palette_t ofwfb_save_cursor_palette; +static vi_load_cursor_palette_t ofwfb_load_cursor_palette; +static vi_copy_t ofwfb_copy; +static vi_putp_t ofwfb_putp; +static vi_putc_t ofwfb_putc; +static vi_puts_t ofwfb_puts; +static vi_putm_t ofwfb_putm; + +static video_switch_t ofwfbvidsw = { + .probe = ofwfb_probe, + .init = ofwfb_init, + .get_info = ofwfb_get_info, + .query_mode = ofwfb_query_mode, + .set_mode = ofwfb_set_mode, + .save_font = ofwfb_save_font, + .load_font = ofwfb_load_font, + .show_font = ofwfb_show_font, + .save_palette = ofwfb_save_palette, + .load_palette = ofwfb_load_palette, + .set_border = ofwfb_set_border, + .save_state = ofwfb_save_state, + .load_state = ofwfb_load_state, + .set_win_org = ofwfb_set_win_org, + .read_hw_cursor = ofwfb_read_hw_cursor, + .set_hw_cursor = ofwfb_set_hw_cursor, + .set_hw_cursor_shape = ofwfb_set_hw_cursor_shape, + .blank_display = ofwfb_blank_display, + .mmap = ofwfb_mmap, + .ioctl = ofwfb_ioctl, + .clear = ofwfb_clear, + .fill_rect = ofwfb_fill_rect, + .bitblt = ofwfb_bitblt, + .diag = ofwfb_diag, + .save_cursor_palette = ofwfb_save_cursor_palette, + .load_cursor_palette = ofwfb_load_cursor_palette, + .copy = ofwfb_copy, + .putp = ofwfb_putp, + .putc = ofwfb_putc, + .puts = ofwfb_puts, + .putm = ofwfb_putm, +}; + +/* + * bitmap depth-specific routines + */ +static vi_blank_display_t ofwfb_blank_display8; +static vi_putc_t ofwfb_putc8; +static vi_set_border_t ofwfb_set_border8; + +static vi_blank_display_t ofwfb_blank_display32; +static vi_putc_t ofwfb_putc32; +static vi_set_border_t ofwfb_set_border32; + +VIDEO_DRIVER(ofwfb, ofwfbvidsw, ofwfb_configure); + +extern sc_rndr_sw_t txtrndrsw; +RENDERER(ofwfb, 0, txtrndrsw, gfb_set); + +RENDERER_MODULE(ofwfb, gfb_set); + +/* + * Define the iso6429-1983 colormap + */ +static struct { + uint8_t red; + uint8_t green; + uint8_t blue; +} ofwfb_cmap[16] = { /* # R G B Color */ + /* - - - - ----- */ + { 0x00, 0x00, 0x00 }, /* 0 0 0 0 Black */ + { 0x00, 0x00, 0xaa }, /* 1 0 0 2/3 Blue */ + { 0x00, 0xaa, 0x00 }, /* 2 0 2/3 0 Green */ + { 0x00, 0xaa, 0xaa }, /* 3 0 2/3 2/3 Cyan */ + { 0xaa, 0x00, 0x00 }, /* 4 2/3 0 0 Red */ + { 0xaa, 0x00, 0xaa }, /* 5 2/3 0 2/3 Magenta */ + { 0xaa, 0x55, 0x00 }, /* 6 2/3 1/3 0 Brown */ + { 0xaa, 0xaa, 0xaa }, /* 7 2/3 2/3 2/3 White */ + { 0x55, 0x55, 0x55 }, /* 8 1/3 1/3 1/3 Gray */ + { 0x55, 0x55, 0xff }, /* 9 1/3 1/3 1 Bright Blue */ + { 0x55, 0xff, 0x55 }, /* 10 1/3 1 1/3 Bright Green */ + { 0x55, 0xff, 0xff }, /* 11 1/3 1 1 Bright Cyan */ + { 0xff, 0x55, 0x55 }, /* 12 1 1/3 1/3 Bright Red */ + { 0xff, 0x55, 0xff }, /* 13 1 1/3 1 Bright Magenta */ + { 0xff, 0xff, 0x80 }, /* 14 1 1 1/3 Bright Yellow */ + { 0xff, 0xff, 0xff } /* 15 1 1 1 Bright White */ +}; + +#define TODO printf("%s: unimplemented\n", __func__) + +static u_int16_t ofwfb_static_window[ROW*COL]; + +static struct ofwfb_softc ofwfb_softc; + +static __inline int +ofwfb_background(uint8_t attr) +{ + return (attr >> 4); +} + +static __inline int +ofwfb_foreground(uint8_t attr) +{ + return (attr & 0x0f); +} + +static u_int +ofwfb_pix32(int attr) +{ + u_int retval; + + retval = (ofwfb_cmap[attr].blue << 16) | + (ofwfb_cmap[attr].green << 8) | + ofwfb_cmap[attr].red; + + return (retval); +} + +static int +ofwfb_configure(int flags) +{ + struct ofwfb_softc *sc; + phandle_t chosen; + ihandle_t stdout; + phandle_t node; + int depth; + int disable; + int len; + char type[16]; + static int done = 0; + + disable = 0; + TUNABLE_INT_FETCH("hw.syscons.disable", &disable); + if (disable != 0) + return (0); + + if (done != 0) + return (0); + done = 1; + + sc = &ofwfb_softc; + + chosen = OF_finddevice("/chosen"); + OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)); + node = OF_instance_to_package(stdout); + OF_getprop(node, "device_type", type, sizeof(type)); + if (strcmp(type, "display") != 0) + return (0); + + /* Only support 8 and 32-bit framebuffers */ + OF_getprop(node, "depth", &depth, sizeof(depth)); + if (depth == 8) { + sc->sc_blank = ofwfb_blank_display8; + sc->sc_putc = ofwfb_putc8; + sc->sc_set_border = ofwfb_set_border8; + } else if (depth == 32) { + sc->sc_blank = ofwfb_blank_display32; + sc->sc_putc = ofwfb_putc32; + sc->sc_set_border = ofwfb_set_border32; + } else + return (0); + + sc->sc_depth = depth; + sc->sc_node = node; + sc->sc_console = 1; + OF_getprop(node, "height", &sc->sc_height, sizeof(sc->sc_height)); + OF_getprop(node, "width", &sc->sc_width, sizeof(sc->sc_width)); + OF_getprop(node, "linebytes", &sc->sc_stride, sizeof(sc->sc_stride)); + + /* + * XXX the physical address of the frame buffer is assumed to be + * BAT-mapped so it can be accessed directly + */ + OF_getprop(node, "address", &sc->sc_addr, sizeof(sc->sc_addr)); + + /* + * Get the PCI addresses of the adapter. The node may be the + * child of the PCI device: in that case, try the parent for + * the assigned-addresses property. + */ + len = OF_getprop(node, "assigned-addresses", sc->sc_pciaddrs, + sizeof(sc->sc_pciaddrs)); + if (len == -1) { + len = OF_getprop(OF_parent(node), "assigned-addresses", sc->sc_pciaddrs, + sizeof(sc->sc_pciaddrs)); + } + + if (len != -1) { + sc->sc_num_pciaddrs = len / sizeof(struct ofw_pci_register); + } + + ofwfb_init(0, &sc->sc_va, 0); + + return (0); +} + +static int +ofwfb_probe(int unit, video_adapter_t **adp, void *arg, int flags) +{ + TODO; + return (0); +} + +static int +ofwfb_init(int unit, video_adapter_t *adp, int flags) +{ + struct ofwfb_softc *sc; + video_info_t *vi; + char name[64]; + ihandle_t ih; + int i; + int cborder; + int font_height; + int retval; + + sc = (struct ofwfb_softc *)adp; + vi = &adp->va_info; + + vid_init_struct(adp, "ofwfb", -1, unit); + + if (sc->sc_depth == 8) { + /* + * Install the ISO6429 colormap - older OFW systems + * don't do this by default + */ + memset(name, 0, sizeof(name)); + OF_package_to_path(sc->sc_node, name, sizeof(name)); + ih = OF_open(name); + for (i = 0; i < 16; i++) { + OF_call_method("color!", ih, 4, 1, + ofwfb_cmap[i].red, + ofwfb_cmap[i].green, + ofwfb_cmap[i].blue, + i, + &retval); + } + } + + /* The default font size can be overridden by loader */ + font_height = 16; + TUNABLE_INT_FETCH("hw.syscons.fsize", &font_height); + if (font_height == 8) { + sc->sc_font = dflt_font_8; + sc->sc_font_height = 8; + } else if (font_height == 14) { + sc->sc_font = dflt_font_14; + sc->sc_font_height = 14; + } else { + /* default is 8x16 */ + sc->sc_font = dflt_font_16; + sc->sc_font_height = 16; + } + + /* The user can set a border in chars - default is 1 char width */ + cborder = 1; + TUNABLE_INT_FETCH("hw.syscons.border", &cborder); + + vi->vi_cheight = sc->sc_font_height; + vi->vi_width = sc->sc_width/8 - 2*cborder; + vi->vi_height = sc->sc_height/sc->sc_font_height - 2*cborder; + vi->vi_cwidth = 8; + + /* + * Clamp width/height to syscons maximums + */ + if (vi->vi_width > COL) + vi->vi_width = COL; + if (vi->vi_height > ROW) + vi->vi_height = ROW; + + sc->sc_xmargin = (sc->sc_width - (vi->vi_width * vi->vi_cwidth)) / 2; + sc->sc_ymargin = (sc->sc_height - (vi->vi_height * vi->vi_cheight))/2; + + /* + * Avoid huge amounts of conditional code in syscons by + * defining a dummy h/w text display buffer. + */ + adp->va_window = (vm_offset_t) ofwfb_static_window; + + /* Enable future font-loading and flag color support */ + adp->va_flags |= V_ADP_FONT | V_ADP_COLOR; + + ofwfb_blank_display(&sc->sc_va, V_DISPLAY_ON); + + ofwfb_set_mode(&sc->sc_va, 0); + + vid_register(&sc->sc_va); + + return (0); +} + +static int +ofwfb_get_info(video_adapter_t *adp, int mode, video_info_t *info) +{ + bcopy(&adp->va_info, info, sizeof(*info)); + return (0); +} + +static int +ofwfb_query_mode(video_adapter_t *adp, video_info_t *info) +{ + TODO; + return (0); +} + +static int +ofwfb_set_mode(video_adapter_t *adp, int mode) +{ + + return (0); +} + +static int +ofwfb_save_font(video_adapter_t *adp, int page, int size, int width, + u_char *data, int c, int count) +{ + TODO; + return (0); +} + +static int +ofwfb_load_font(video_adapter_t *adp, int page, int size, int width, + u_char *data, int c, int count) +{ + struct ofwfb_softc *sc; + + sc = (struct ofwfb_softc *)adp; + + /* + * syscons code has already determined that current width/height + * are unchanged for this new font + */ + sc->sc_font = data; + return (0); +} + +static int +ofwfb_show_font(video_adapter_t *adp, int page) +{ + + return (0); +} + +static int +ofwfb_save_palette(video_adapter_t *adp, u_char *palette) +{ + /* TODO; */ + return (0); +} + +static int +ofwfb_load_palette(video_adapter_t *adp, u_char *palette) +{ + /* TODO; */ + return (0); +} + +static int +ofwfb_set_border8(video_adapter_t *adp, int border) +{ + struct ofwfb_softc *sc; + int i, j; + uint8_t *addr; + uint8_t bground; + + sc = (struct ofwfb_softc *)adp; + + bground = ofwfb_background(border); + + /* Set top margin */ + addr = (uint8_t *) sc->sc_addr; + for (i = 0; i < sc->sc_ymargin; i++) { + for (j = 0; j < sc->sc_width; j++) { + *(addr + j) = bground; + } + addr += sc->sc_stride; + } + + /* bottom margin */ + addr = (uint8_t *) sc->sc_addr + (sc->sc_height - sc->sc_ymargin)*sc->sc_stride; + for (i = 0; i < sc->sc_ymargin; i++) { + for (j = 0; j < sc->sc_width; j++) { + *(addr + j) = bground; + } + addr += sc->sc_stride; + } + + /* remaining left and right borders */ + addr = (uint8_t *) sc->sc_addr + sc->sc_ymargin*sc->sc_stride; + for (i = 0; i < sc->sc_height - 2*sc->sc_xmargin; i++) { + for (j = 0; j < sc->sc_xmargin; j++) { + *(addr + j) = bground; + *(addr + j + sc->sc_width - sc->sc_xmargin) = bground; + } + addr += sc->sc_stride; + } + + return (0); +} + +static int +ofwfb_set_border32(video_adapter_t *adp, int border) +{ + /* XXX Be lazy for now and blank entire screen */ + return (ofwfb_blank_display32(adp, border)); +} + +static int +ofwfb_set_border(video_adapter_t *adp, int border) +{ + struct ofwfb_softc *sc; + + sc = (struct ofwfb_softc *)adp; + + return ((*sc->sc_set_border)(adp, border)); +} + +static int +ofwfb_save_state(video_adapter_t *adp, void *p, size_t size) +{ + TODO; + return (0); +} + +static int +ofwfb_load_state(video_adapter_t *adp, void *p) +{ + TODO; + return (0); +} + +static int +ofwfb_set_win_org(video_adapter_t *adp, off_t offset) +{ + TODO; + return (0); +} + +static int +ofwfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row) +{ + *col = 0; + *row = 0; + + return (0); +} + +static int +ofwfb_set_hw_cursor(video_adapter_t *adp, int col, int row) +{ + + return (0); +} + +static int +ofwfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, + int celsize, int blink) +{ + return (0); +} + +static int +ofwfb_blank_display8(video_adapter_t *adp, int mode) +{ + struct ofwfb_softc *sc; + int i; + uint8_t *addr; + + sc = (struct ofwfb_softc *)adp; + addr = (uint8_t *) sc->sc_addr; + + /* Could be done a lot faster e.g. 32-bits, or Altivec'd */ + for (i = 0; i < sc->sc_stride*sc->sc_height; i++) + *(addr + i) = ofwfb_background(SC_NORM_ATTR); + + return (0); +} + +static int +ofwfb_blank_display32(video_adapter_t *adp, int mode) +{ + struct ofwfb_softc *sc; + int i; + uint32_t *addr; + + sc = (struct ofwfb_softc *)adp; + addr = (uint32_t *) sc->sc_addr; + + for (i = 0; i < (sc->sc_stride/4)*sc->sc_height; i++) + *(addr + i) = ofwfb_pix32(ofwfb_background(SC_NORM_ATTR)); + + return (0); +} + +static int +ofwfb_blank_display(video_adapter_t *adp, int mode) +{ + struct ofwfb_softc *sc; + + sc = (struct ofwfb_softc *)adp; + + return ((*sc->sc_blank)(adp, mode)); +} + +static int +ofwfb_mmap(video_adapter_t *adp, vm_offset_t offset, vm_paddr_t *paddr, + int prot) +{ + struct ofwfb_softc *sc; + int i; + + sc = (struct ofwfb_softc *)adp; + + if (sc->sc_num_pciaddrs == 0) + return (ENOMEM); + + /* + * Hack for Radeon... + */ + if (ofwfb_ignore_mmap_checks) { + *paddr = offset; + return (0); + } + + /* + * Make sure the requested address lies within the PCI device's assigned addrs + */ + for (i = 0; i < sc->sc_num_pciaddrs; i++) + if (offset >= sc->sc_pciaddrs[i].phys_lo && + offset < (sc->sc_pciaddrs[i].phys_lo + sc->sc_pciaddrs[i].size_lo)) { + *paddr = offset; + return (0); + } + + /* + * This might be a legacy VGA mem request: if so, just point it at the + * framebuffer, since it shouldn't be touched + */ + if (offset < sc->sc_stride*sc->sc_height) { + *paddr = sc->sc_addr + offset; + return (0); + } + + return (EINVAL); +} + +static int +ofwfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data) +{ + + return (0); +} + +static int +ofwfb_clear(video_adapter_t *adp) +{ + TODO; + return (0); +} + +static int +ofwfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) +{ + TODO; + return (0); +} + +static int +ofwfb_bitblt(video_adapter_t *adp, ...) +{ + TODO; + return (0); +} + +static int +ofwfb_diag(video_adapter_t *adp, int level) +{ + TODO; + return (0); +} + +static int +ofwfb_save_cursor_palette(video_adapter_t *adp, u_char *palette) +{ + TODO; + return (0); +} + +static int +ofwfb_load_cursor_palette(video_adapter_t *adp, u_char *palette) +{ + TODO; + return (0); +} + +static int +ofwfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n) +{ + TODO; + return (0); +} + +static int +ofwfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a, + int size, int bpp, int bit_ltor, int byte_ltor) +{ + TODO; + return (0); +} + +static int +ofwfb_putc8(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) +{ + struct ofwfb_softc *sc; + int row; + int col; + int i; + uint32_t *addr; + u_char *p, fg, bg; + union { + uint32_t l; + uint8_t c[4]; + } ch1, ch2; + + + sc = (struct ofwfb_softc *)adp; + row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; + col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; + p = sc->sc_font + c*sc->sc_font_height; + addr = (u_int32_t *)((int)sc->sc_addr + + (row + sc->sc_ymargin)*sc->sc_stride + + col + sc->sc_xmargin); + + fg = ofwfb_foreground(a); + bg = ofwfb_background(a); + + for (i = 0; i < sc->sc_font_height; i++) { + u_char fline = p[i]; + + /* + * Assume that there is more background than foreground + * in characters and init accordingly + */ + ch1.l = ch2.l = (bg << 24) | (bg << 16) | (bg << 8) | bg; + + /* + * Calculate 2 x 4-chars at a time, and then + * write these out. + */ + if (fline & 0x80) ch1.c[0] = fg; + if (fline & 0x40) ch1.c[1] = fg; + if (fline & 0x20) ch1.c[2] = fg; + if (fline & 0x10) ch1.c[3] = fg; + + if (fline & 0x08) ch2.c[0] = fg; + if (fline & 0x04) ch2.c[1] = fg; + if (fline & 0x02) ch2.c[2] = fg; + if (fline & 0x01) ch2.c[3] = fg; + + addr[0] = ch1.l; + addr[1] = ch2.l; + addr += (sc->sc_stride / sizeof(u_int32_t)); + } + + return (0); +} + +static int +ofwfb_putc32(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) +{ + struct ofwfb_softc *sc; + int row; + int col; + int i, j, k; + uint32_t *addr; + u_char *p; + + sc = (struct ofwfb_softc *)adp; + row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight; + col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth; + p = sc->sc_font + c*sc->sc_font_height; + addr = (uint32_t *)sc->sc_addr + + (row + sc->sc_ymargin)*(sc->sc_stride/4) + + col + sc->sc_xmargin; + + for (i = 0; i < sc->sc_font_height; i++) { + for (j = 0, k = 7; j < 8; j++, k--) { + if ((p[i] & (1 << k)) == 0) + *(addr + j) = ofwfb_pix32(ofwfb_background(a)); + else + *(addr + j) = ofwfb_pix32(ofwfb_foreground(a)); + } + addr += (sc->sc_stride/4); + } + + return (0); +} + +static int +ofwfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a) +{ + struct ofwfb_softc *sc; + + sc = (struct ofwfb_softc *)adp; + + return ((*sc->sc_putc)(adp, off, c, a)); +} + +static int +ofwfb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len) +{ + int i; + + for (i = 0; i < len; i++) { + ofwfb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8); + } + return (0); +} + +static int +ofwfb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image, + uint32_t pixel_mask, int size, int width) +{ + struct ofwfb_softc *sc; + + sc = (struct ofwfb_softc *)adp; + + /* put mouse */ + + return (0); +} + +/* + * Define the syscons nexus device attachment + */ +static void +ofwfb_scidentify(driver_t *driver, device_t parent) +{ + device_t child; + + /* + * Add with a priority guaranteed to make it last on + * the device list + */ + child = BUS_ADD_CHILD(parent, INT_MAX, SC_DRIVER_NAME, 0); + if (child != NULL) + nexus_set_device_type(child, "syscons"); +} + +static int +ofwfb_scprobe(device_t dev) +{ + char *name; + + name = nexus_get_name(dev); + if (strcmp(SC_DRIVER_NAME, name) != 0) + return (ENXIO); + + device_set_desc(dev, "System console"); + return (sc_probe_unit(device_get_unit(dev), + device_get_flags(dev) | SC_AUTODETECT_KBD)); +} + +static int +ofwfb_scattach(device_t dev) +{ + return (sc_attach_unit(device_get_unit(dev), + device_get_flags(dev) | SC_AUTODETECT_KBD)); +} + +static device_method_t ofwfb_sc_methods[] = { + DEVMETHOD(device_identify, ofwfb_scidentify), + DEVMETHOD(device_probe, ofwfb_scprobe), + DEVMETHOD(device_attach, ofwfb_scattach), + { 0, 0 } +}; + +static driver_t ofwfb_sc_driver = { + SC_DRIVER_NAME, + ofwfb_sc_methods, + sizeof(sc_softc_t), +}; + +static devclass_t sc_devclass; + +DRIVER_MODULE(sc, nexus, ofwfb_sc_driver, sc_devclass, 0, 0); + +/* + * Define a stub keyboard driver in case one hasn't been + * compiled into the kernel + */ +#include <sys/kbio.h> +#include <dev/kbd/kbdreg.h> + +static int dummy_kbd_configure(int flags); + +keyboard_switch_t dummysw; + +static int +dummy_kbd_configure(int flags) +{ + + return (0); +} +KEYBOARD_DRIVER(dummy, dummysw, dummy_kbd_configure); + +/* + * Utility routines from <dev/fb/fbreg.h> + */ +void +ofwfb_bcopy(const void *s, void *d, size_t c) +{ + bcopy(s, d, c); +} + +void +ofwfb_bzero(void *d, size_t c) +{ + bzero(d, c); +} + +void +ofwfb_fillw(int pat, void *base, size_t cnt) +{ + u_int16_t *bptr = base; + + while (cnt--) + *bptr++ = pat; +} + +u_int16_t +ofwfb_readw(u_int16_t *addr) +{ + return (*addr); +} + +void +ofwfb_writew(u_int16_t *addr, u_int16_t val) +{ + *addr = val; +} diff --git a/sys/powerpc/ofw/ofw_syscons.h b/sys/powerpc/ofw/ofw_syscons.h new file mode 100644 index 000000000000..af33c52d6d81 --- /dev/null +++ b/sys/powerpc/ofw/ofw_syscons.h @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 2003 Peter Grehan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _OFW_SYSCONS_H_ +#define _OFW_SYSCONS_H_ + +struct ofwfb_softc { + video_adapter_t sc_va; + struct cdev *sc_si; + phandle_t sc_node; + int sc_console; + + intptr_t sc_addr; + int sc_depth; + int sc_height; + int sc_width; + int sc_stride; + int sc_ncol; + int sc_nrow; + + int sc_xmargin; + int sc_ymargin; + + u_char *sc_font; + int sc_font_height; + + vi_blank_display_t *sc_blank; + vi_putc_t *sc_putc; + vi_set_border_t *sc_set_border; + +#define OFWSC_MAXADDR 8 + int sc_num_pciaddrs; + struct ofw_pci_register sc_pciaddrs[OFWSC_MAXADDR]; +}; + +#endif diff --git a/sys/powerpc/powermac/ata_kauai.c b/sys/powerpc/powermac/ata_kauai.c new file mode 100644 index 000000000000..141f56ec7071 --- /dev/null +++ b/sys/powerpc/powermac/ata_kauai.c @@ -0,0 +1,198 @@ +/*- + * Copyright 2004 by Peter Grehan. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * Mac 'Kauai' PCI ATA controller + */ +#include "opt_ata.h" +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/malloc.h> +#include <sys/sema.h> +#include <sys/taskqueue.h> +#include <vm/uma.h> +#include <machine/stdarg.h> +#include <machine/resource.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <sys/ata.h> +#include <dev/ata/ata-all.h> +#include <ata_if.h> + +#include <dev/ofw/openfirm.h> + +#include <dev/pci/pcivar.h> +#include <dev/pci/pcireg.h> + +#define ATA_KAUAI_REGOFFSET 0x2000 + +/* + * Offset to alt-control register from base + */ +#define ATA_KAUAI_ALTOFFSET (ATA_KAUAI_REGOFFSET + 0x160) + +/* + * Define the gap between registers + */ +#define ATA_KAUAI_REGGAP 16 + +/* + * Define the kauai pci bus attachment. + */ +static int ata_kauai_probe(device_t dev); +static void ata_kauai_setmode(device_t parent, device_t dev); + +static device_method_t ata_kauai_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ata_kauai_probe), + DEVMETHOD(device_attach, ata_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* ATA interface */ + DEVMETHOD(ata_setmode, ata_kauai_setmode), + { 0, 0 } +}; + +static driver_t ata_kauai_driver = { + "ata", + ata_kauai_methods, + sizeof(struct ata_channel), +}; + +DRIVER_MODULE(ata, pci, ata_kauai_driver, ata_devclass, 0, 0); +MODULE_DEPEND(ata, ata, 1, 1, 1); + +/* + * PCI ID search table + */ +static struct kauai_pci_dev { + u_int32_t kpd_devid; + char *kpd_desc; +} kauai_pci_devlist[] = { + { 0x0033106b, "Uninorth2 Kauai ATA Controller" }, + { 0x003b106b, "Intrepid Kauai ATA Controller" }, + { 0x0043106b, "K2 Kauai ATA Controller" }, + { 0, NULL } +}; + +static int +ata_kauai_probe(device_t dev) +{ + struct ata_channel *ch; + struct resource *mem; + u_long startp, countp; + u_int32_t devid; + int i, found, rid, status; + + found = 0; + devid = pci_get_devid(dev); + for (i = 0; kauai_pci_devlist[i].kpd_desc != NULL; i++) { + if (devid == kauai_pci_devlist[i].kpd_devid) { + found = 1; + device_set_desc(dev, kauai_pci_devlist[i].kpd_desc); + } + } + + if (!found) + return (ENXIO); + + /* + * This device seems to ignore writes to the interrupt + * config register, resulting in interrupt resources + * not being attached. If this is the case, use + * Open Firmware to determine the irq, and then attach + * the resource. This allows the ATA common code to + * allocate the irq. + */ + status = bus_get_resource(dev, SYS_RES_IRQ, 0, &startp, &countp); + if (status == ENOENT) { + int irq; + + /* + * Aargh, hideous hack until ofw pci intr routine is + * exported + */ + irq = 39; /* XXX */ + bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1); + + /* + * Sanity check... + */ + status = bus_get_resource(dev, SYS_RES_IRQ, 0, &startp, + &countp); + if (status == ENOENT || + startp != 39) { + printf("kauai irq not set!\n"); + return (ENXIO); + } + } + + ch = device_get_softc(dev); + bzero(ch, sizeof(struct ata_channel)); + + rid = PCIR_BARS; + mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); + if (mem == NULL) { + device_printf(dev, "could not allocate memory\n"); + return (ENXIO); + } + + /* + * Set up the resource vectors + */ + for (i = ATA_DATA; i <= ATA_COMMAND; i++) { + ch->r_io[i].res = mem; + ch->r_io[i].offset = i*ATA_KAUAI_REGGAP + ATA_KAUAI_REGOFFSET; + } + ch->r_io[ATA_CONTROL].res = mem; + ch->r_io[ATA_CONTROL].offset = ATA_KAUAI_ALTOFFSET; + ata_default_registers(dev); + + ch->unit = 0; + ch->flags |= ATA_USE_16BIT; + ata_generic_hw(dev); + + return (ata_probe(dev)); +} + +static void +ata_kauai_setmode(device_t parent, device_t dev) +{ + struct ata_device *atadev = device_get_softc(dev); + + /* TODO bang kauai speed register */ + atadev->mode = ATA_PIO; +} diff --git a/sys/powerpc/powermac/ata_macio.c b/sys/powerpc/powermac/ata_macio.c new file mode 100644 index 000000000000..f582a5ceef88 --- /dev/null +++ b/sys/powerpc/powermac/ata_macio.c @@ -0,0 +1,136 @@ +/*- + * Copyright 2002 by Peter Grehan. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * Mac-io ATA controller + */ +#include "opt_ata.h" +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/malloc.h> +#include <sys/sema.h> +#include <sys/taskqueue.h> +#include <vm/uma.h> +#include <machine/stdarg.h> +#include <machine/resource.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <sys/ata.h> +#include <dev/ata/ata-all.h> +#include <ata_if.h> + +#include <dev/ofw/ofw_bus.h> + +/* + * Offset to control registers from base + */ +#define ATA_MACIO_ALTOFFSET 0x160 + +/* + * Define the gap between registers + */ +#define ATA_MACIO_REGGAP 16 + +/* + * Define the macio ata bus attachment. + */ +static int ata_macio_probe(device_t dev); +static void ata_macio_setmode(device_t parent, device_t dev); + +static device_method_t ata_macio_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ata_macio_probe), + DEVMETHOD(device_attach, ata_attach), + + /* ATA interface */ + DEVMETHOD(ata_setmode, ata_macio_setmode), + { 0, 0 } +}; + +static driver_t ata_macio_driver = { + "ata", + ata_macio_methods, + sizeof(struct ata_channel), +}; + +DRIVER_MODULE(ata, macio, ata_macio_driver, ata_devclass, 0, 0); +MODULE_DEPEND(ata, ata, 1, 1, 1); + +static int +ata_macio_probe(device_t dev) +{ + const char *type = ofw_bus_get_type(dev); + struct ata_channel *ch; + struct resource *mem; + int rid, i; + + if (strcmp(type, "ata") != 0 && + strcmp(type, "ide") != 0) + return (ENXIO); + + ch = device_get_softc(dev); + bzero(ch, sizeof(struct ata_channel)); + + rid = 0; + mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); + if (mem == NULL) { + device_printf(dev, "could not allocate memory\n"); + return (ENXIO); + } + + /* + * Set up the resource vectors + */ + for (i = ATA_DATA; i <= ATA_COMMAND; i++) { + ch->r_io[i].res = mem; + ch->r_io[i].offset = i * ATA_MACIO_REGGAP; + } + ch->r_io[ATA_CONTROL].res = mem; + ch->r_io[ATA_CONTROL].offset = ATA_MACIO_ALTOFFSET; + ata_default_registers(dev); + + ch->unit = 0; + ch->flags |= ATA_USE_16BIT; + ata_generic_hw(dev); + + return (ata_probe(dev)); +} + +static void +ata_macio_setmode(device_t parent, device_t dev) +{ + struct ata_device *atadev = device_get_softc(dev); + + /* TODO bang macio speed register */ + atadev->mode = ATA_PIO; +} + diff --git a/sys/powerpc/powermac/grackle.c b/sys/powerpc/powermac/grackle.c new file mode 100644 index 000000000000..f606b655582d --- /dev/null +++ b/sys/powerpc/powermac/grackle.c @@ -0,0 +1,556 @@ +/*- + * Copyright 2003 by Peter Grehan. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> + +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_pci.h> + +#include <dev/pci/pcivar.h> +#include <dev/pci/pcireg.h> + +#include <machine/bus.h> +#include <machine/md_var.h> +#include <machine/nexusvar.h> +#include <machine/resource.h> + +#include <sys/rman.h> + +#include <powerpc/ofw/ofw_pci.h> +#include <powerpc/powermac/gracklevar.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include "pcib_if.h" + +int badaddr(void *, size_t); /* XXX */ + +/* + * Device interface. + */ +static int grackle_probe(device_t); +static int grackle_attach(device_t); + +/* + * Bus interface. + */ +static int grackle_read_ivar(device_t, device_t, int, + uintptr_t *); +static struct resource * grackle_alloc_resource(device_t bus, + device_t child, int type, int *rid, u_long start, + u_long end, u_long count, u_int flags); +static int grackle_release_resource(device_t bus, device_t child, + int type, int rid, struct resource *res); +static int grackle_activate_resource(device_t bus, device_t child, + int type, int rid, struct resource *res); +static int grackle_deactivate_resource(device_t bus, + device_t child, int type, int rid, + struct resource *res); + + +/* + * pcib interface. + */ +static int grackle_maxslots(device_t); +static u_int32_t grackle_read_config(device_t, u_int, u_int, u_int, + u_int, int); +static void grackle_write_config(device_t, u_int, u_int, u_int, + u_int, u_int32_t, int); +static int grackle_route_interrupt(device_t, device_t, int); + +/* + * Local routines. + */ +static int grackle_enable_config(struct grackle_softc *, u_int, + u_int, u_int, u_int); +static void grackle_disable_config(struct grackle_softc *); + +/* + * Driver methods. + */ +static device_method_t grackle_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, grackle_probe), + DEVMETHOD(device_attach, grackle_attach), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_read_ivar, grackle_read_ivar), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(bus_alloc_resource, grackle_alloc_resource), + DEVMETHOD(bus_release_resource, grackle_release_resource), + DEVMETHOD(bus_activate_resource, grackle_activate_resource), + DEVMETHOD(bus_deactivate_resource, grackle_deactivate_resource), + + /* pcib interface */ + DEVMETHOD(pcib_maxslots, grackle_maxslots), + DEVMETHOD(pcib_read_config, grackle_read_config), + DEVMETHOD(pcib_write_config, grackle_write_config), + DEVMETHOD(pcib_route_interrupt, grackle_route_interrupt), + + { 0, 0 } +}; + +static driver_t grackle_driver = { + "pcib", + grackle_methods, + sizeof(struct grackle_softc) +}; + +static devclass_t grackle_devclass; + +DRIVER_MODULE(grackle, nexus, grackle_driver, grackle_devclass, 0, 0); + +static int +grackle_probe(device_t dev) +{ + char *type, *compatible; + + type = nexus_get_device_type(dev); + compatible = nexus_get_compatible(dev); + + if (type == NULL || compatible == NULL) + return (ENXIO); + + if (strcmp(type, "pci") != 0 || strcmp(compatible, "grackle") != 0) + return (ENXIO); + + device_set_desc(dev, "MPC106 (Grackle) Host-PCI bridge"); + return (0); +} + +static int +grackle_attach(device_t dev) +{ + struct grackle_softc *sc; + phandle_t node; + u_int32_t busrange[2]; + struct grackle_range *rp, *io, *mem[2]; + int nmem, i; + + node = nexus_get_node(dev); + sc = device_get_softc(dev); + + if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8) + return (ENXIO); + + sc->sc_dev = dev; + sc->sc_node = node; + sc->sc_bus = busrange[0]; + + /* + * The Grackle PCI config addr/data registers are actually in + * PCI space, but since they are needed to actually probe the + * PCI bus, use the fact that they are also available directly + * on the processor bus and map them + */ + sc->sc_addr = (vm_offset_t)pmap_mapdev(GRACKLE_ADDR, PAGE_SIZE); + sc->sc_data = (vm_offset_t)pmap_mapdev(GRACKLE_DATA, PAGE_SIZE); + + bzero(sc->sc_range, sizeof(sc->sc_range)); + sc->sc_nrange = OF_getprop(node, "ranges", sc->sc_range, + sizeof(sc->sc_range)); + + if (sc->sc_nrange == -1) { + device_printf(dev, "could not get ranges\n"); + return (ENXIO); + } + + sc->sc_range[6].pci_hi = 0; + io = NULL; + nmem = 0; + + for (rp = sc->sc_range; rp->pci_hi != 0; rp++) { + switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { + case OFW_PCI_PHYS_HI_SPACE_CONFIG: + break; + case OFW_PCI_PHYS_HI_SPACE_IO: + io = rp; + break; + case OFW_PCI_PHYS_HI_SPACE_MEM32: + mem[nmem] = rp; + nmem++; + break; + case OFW_PCI_PHYS_HI_SPACE_MEM64: + break; + } + } + + if (io == NULL) { + device_printf(dev, "can't find io range\n"); + return (ENXIO); + } + sc->sc_io_rman.rm_type = RMAN_ARRAY; + sc->sc_io_rman.rm_descr = "Grackle PCI I/O Ports"; + sc->sc_iostart = io->pci_iospace; + if (rman_init(&sc->sc_io_rman) != 0 || + rman_manage_region(&sc->sc_io_rman, io->pci_lo, + io->pci_lo + io->size_lo) != 0) { + device_printf(dev, "failed to set up io range management\n"); + return (ENXIO); + } + + if (nmem == 0) { + device_printf(dev, "can't find mem ranges\n"); + return (ENXIO); + } + sc->sc_mem_rman.rm_type = RMAN_ARRAY; + sc->sc_mem_rman.rm_descr = "Grackle PCI Memory"; + if (rman_init(&sc->sc_mem_rman) != 0) { + device_printf(dev, + "failed to init mem range resources\n"); + return (ENXIO); + } + for (i = 0; i < nmem; i++) { + if (rman_manage_region(&sc->sc_mem_rman, mem[i]->pci_lo, + mem[i]->pci_lo + mem[i]->size_lo) != 0) { + device_printf(dev, + "failed to set up memory range management\n"); + return (ENXIO); + } + } + + /* + * Write out the correct PIC interrupt values to config space + * of all devices on the bus. + */ + ofw_pci_fixup(dev, sc->sc_bus, sc->sc_node); + + device_add_child(dev, "pci", device_get_unit(dev)); + return (bus_generic_attach(dev)); +} + +static int +grackle_maxslots(device_t dev) +{ + + return (PCI_SLOTMAX); +} + +static u_int32_t +grackle_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, + int width) +{ + struct grackle_softc *sc; + vm_offset_t caoff; + u_int32_t retval = 0xffffffff; + + sc = device_get_softc(dev); + caoff = sc->sc_data + (reg & 0x03); + + if (grackle_enable_config(sc, bus, slot, func, reg) != 0) { + + /* + * Config probes to non-existent devices on the + * secondary bus generates machine checks. Be sure + * to catch these. + */ + if (bus > 0) { + if (badaddr((void *)sc->sc_data, 4)) { + return (retval); + } + } + + switch (width) { + case 1: + retval = (in8rb(caoff)); + break; + case 2: + retval = (in16rb(caoff)); + break; + case 4: + retval = (in32rb(caoff)); + break; + } + } + grackle_disable_config(sc); + + return (retval); +} + +static void +grackle_write_config(device_t dev, u_int bus, u_int slot, u_int func, + u_int reg, u_int32_t val, int width) +{ + struct grackle_softc *sc; + vm_offset_t caoff; + + sc = device_get_softc(dev); + caoff = sc->sc_data + (reg & 0x03); + + if (grackle_enable_config(sc, bus, slot, func, reg)) { + switch (width) { + case 1: + out8rb(caoff, val); + (void)in8rb(caoff); + break; + case 2: + out16rb(caoff, val); + (void)in16rb(caoff); + break; + case 4: + out32rb(caoff, val); + (void)in32rb(caoff); + break; + } + } + grackle_disable_config(sc); +} + +static int +grackle_route_interrupt(device_t bus, device_t dev, int pin) +{ + + return (0); +} + +static int +grackle_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct grackle_softc *sc; + + sc = device_get_softc(dev); + + switch (which) { + case PCIB_IVAR_DOMAIN: + *result = 0; + return (0); + case PCIB_IVAR_BUS: + *result = sc->sc_bus; + return (0); + } + + return (ENOENT); +} + +static struct resource * +grackle_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct grackle_softc *sc; + struct resource *rv; + struct rman *rm; + bus_space_tag_t bt; + int needactivate; + + needactivate = flags & RF_ACTIVE; + flags &= ~RF_ACTIVE; + + sc = device_get_softc(bus); + + switch (type) { + case SYS_RES_MEMORY: + rm = &sc->sc_mem_rman; + bt = PPC_BUS_SPACE_MEM; + break; + + case SYS_RES_IOPORT: + rm = &sc->sc_io_rman; + bt = PPC_BUS_SPACE_IO; + break; + + case SYS_RES_IRQ: + return (bus_alloc_resource(bus, type, rid, start, end, count, + flags)); + break; + + default: + device_printf(bus, "unknown resource request from %s\n", + device_get_nameunit(child)); + return (NULL); + } + + rv = rman_reserve_resource(rm, start, end, count, flags, child); + if (rv == NULL) { + device_printf(bus, "failed to reserve resource for %s\n", + device_get_nameunit(child)); + return (NULL); + } + + rman_set_rid(rv, *rid); + rman_set_bustag(rv, bt); + rman_set_bushandle(rv, rman_get_start(rv)); + + if (needactivate) { + if (bus_activate_resource(child, type, *rid, rv) != 0) { + device_printf(bus, + "failed to activate resource for %s\n", + device_get_nameunit(child)); + rman_release_resource(rv); + return (NULL); + } + } + + return (rv); +} + +static int +grackle_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + if (rman_get_flags(res) & RF_ACTIVE) { + int error = bus_deactivate_resource(child, type, rid, res); + if (error) + return error; + } + + return (rman_release_resource(res)); +} + +static int +grackle_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + struct grackle_softc *sc; + void *p; + + sc = device_get_softc(bus); + + if (type == SYS_RES_IRQ) { + return (bus_activate_resource(bus, type, rid, res)); + } + if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { + vm_offset_t start; + + start = (vm_offset_t)rman_get_start(res); + /* + * For i/o-ports, convert the start address to the + * MPC106 PCI i/o window + */ + if (type == SYS_RES_IOPORT) + start += sc->sc_iostart; + + if (bootverbose) + printf("grackle mapdev: start %x, len %ld\n", start, + rman_get_size(res)); + + p = pmap_mapdev(start, (vm_size_t)rman_get_size(res)); + if (p == NULL) + return (ENOMEM); + + rman_set_virtual(res, p); + rman_set_bushandle(res, (u_long)p); + } + + return (rman_activate_resource(res)); +} + +static int +grackle_deactivate_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + /* + * If this is a memory resource, unmap it. + */ + if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { + u_int32_t psize; + + psize = rman_get_size(res); + pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize); + } + + return (rman_deactivate_resource(res)); +} + + +static int +grackle_enable_config(struct grackle_softc *sc, u_int bus, u_int slot, + u_int func, u_int reg) +{ + u_int32_t cfgval; + + /* + * Unlike UniNorth, the format of the config word is the same + * for local (0) and remote busses. + */ + cfgval = (bus << 16) | (slot << 11) | (func << 8) | (reg & 0xFC) + | GRACKLE_CFG_ENABLE; + + out32rb(sc->sc_addr, cfgval); + (void) in32rb(sc->sc_addr); + + return (1); +} + +static void +grackle_disable_config(struct grackle_softc *sc) +{ + /* + * Clear the GRACKLE_CFG_ENABLE bit to prevent stray + * accesses from causing config cycles + */ + out32rb(sc->sc_addr, 0); +} + +/* + * Driver to swallow Grackle host bridges from the PCI bus side. + */ +static int +grackle_hb_probe(device_t dev) +{ + + if (pci_get_devid(dev) == 0x00021057) { + device_set_desc(dev, "Grackle Host to PCI bridge"); + device_quiet(dev); + return (0); + } + + return (ENXIO); +} + +static int +grackle_hb_attach(device_t dev) +{ + + return (0); +} + +static device_method_t grackle_hb_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, grackle_hb_probe), + DEVMETHOD(device_attach, grackle_hb_attach), + + { 0, 0 } +}; + +static driver_t grackle_hb_driver = { + "grackle_hb", + grackle_hb_methods, + 1, +}; +static devclass_t grackle_hb_devclass; + +DRIVER_MODULE(grackle_hb, pci, grackle_hb_driver, grackle_hb_devclass, 0, 0); diff --git a/sys/powerpc/powermac/gracklevar.h b/sys/powerpc/powermac/gracklevar.h new file mode 100644 index 000000000000..bb5b150e074a --- /dev/null +++ b/sys/powerpc/powermac/gracklevar.h @@ -0,0 +1,69 @@ +/*- + * Copyright 2003 by Peter Grehan. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _POWERPC_POWERMAC_GRACKLEVAR_H_ +#define _POWERPC_POWERMAC_GRACKLEVAR_H_ + +struct grackle_range { + u_int32_t pci_hi; + u_int32_t pci_mid; + u_int32_t pci_lo; + u_int32_t pci_iospace; + u_int32_t size_hi; + u_int32_t size_lo; +}; + +struct grackle_softc { + device_t sc_dev; + phandle_t sc_node; + vm_offset_t sc_addr; + vm_offset_t sc_data; + int sc_bus; + struct grackle_range sc_range[6]; + int sc_nrange; + int sc_iostart; + struct rman sc_io_rman; + struct rman sc_mem_rman; + bus_space_tag_t sc_memt; + bus_dma_tag_t sc_dmat; +}; + +/* + * Apple uses address map B for the MPC106 + */ +#define GRACKLE_ADDR 0xFEC00000 +#define GRACKLE_DATA 0xFEE00000 + +/* + * The high bit of the config word is 'Enable'. This should always be + * set. + */ +#define GRACKLE_CFG_ENABLE 0x80000000 + +#endif /* _POWERPC_POWERMAC_GRACKLEVAR_H_ */ diff --git a/sys/powerpc/powermac/hrowpic.c b/sys/powerpc/powermac/hrowpic.c new file mode 100644 index 000000000000..cf8a4624b58f --- /dev/null +++ b/sys/powerpc/powermac/hrowpic.c @@ -0,0 +1,271 @@ +/*- + * Copyright 2003 by Peter Grehan. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * A driver for the PIC found in the Heathrow/Paddington MacIO chips. + * This was superseded by an OpenPIC in the Keylargo and beyond + * MacIO versions. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/rman.h> + +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/openfirm.h> + +#include <machine/bus.h> +#include <machine/intr.h> +#include <machine/intr_machdep.h> +#include <machine/md_var.h> +#include <machine/nexusvar.h> +#include <machine/pio.h> +#include <machine/resource.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <powerpc/powermac/hrowpicvar.h> + +#include "pic_if.h" + +/* + * MacIO interface + */ +static int hrowpic_probe(device_t); +static int hrowpic_attach(device_t); + +static void hrowpic_dispatch(device_t, struct trapframe *); +static void hrowpic_enable(device_t, u_int, u_int); +static void hrowpic_eoi(device_t, u_int); +static void hrowpic_mask(device_t, u_int); +static void hrowpic_unmask(device_t, u_int); + +static device_method_t hrowpic_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, hrowpic_probe), + DEVMETHOD(device_attach, hrowpic_attach), + + /* PIC interface */ + DEVMETHOD(pic_dispatch, hrowpic_dispatch), + DEVMETHOD(pic_enable, hrowpic_enable), + DEVMETHOD(pic_eoi, hrowpic_eoi), + DEVMETHOD(pic_mask, hrowpic_mask), + DEVMETHOD(pic_unmask, hrowpic_unmask), + + { 0, 0 }, +}; + +static driver_t hrowpic_driver = { + "hrowpic", + hrowpic_methods, + sizeof(struct hrowpic_softc) +}; + +static devclass_t hrowpic_devclass; + +DRIVER_MODULE(hrowpic, macio, hrowpic_driver, hrowpic_devclass, 0, 0); + +static uint32_t +hrowpic_read_reg(struct hrowpic_softc *sc, u_int reg, u_int bank) +{ + if (bank == HPIC_PRIMARY) + reg += HPIC_1ST_OFFSET; + + return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg)); +} + +static void +hrowpic_write_reg(struct hrowpic_softc *sc, u_int reg, u_int bank, + uint32_t val) +{ + + if (bank == HPIC_PRIMARY) + reg += HPIC_1ST_OFFSET; + + bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val); + + /* XXX Issue a read to force the write to complete. */ + bus_space_read_4(sc->sc_bt, sc->sc_bh, reg); +} + +static int +hrowpic_probe(device_t dev) +{ + const char *type = ofw_bus_get_type(dev); + + /* + * OpenPIC cells have a type of "open-pic", so this + * is sufficient to identify a Heathrow cell + */ + if (strcmp(type, "interrupt-controller") != 0) + return (ENXIO); + + /* + * The description was already printed out in the nexus + * probe, so don't do it again here + */ + device_set_desc(dev, "Heathrow MacIO interrupt controller"); + return (0); +} + +static int +hrowpic_attach(device_t dev) +{ + struct hrowpic_softc *sc; + + sc = device_get_softc(dev); + sc->sc_dev = dev; + + sc->sc_rrid = 0; + sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rrid, + RF_ACTIVE); + + if (sc->sc_rres == NULL) { + device_printf(dev, "Could not alloc mem resource!\n"); + return (ENXIO); + } + + sc->sc_bt = rman_get_bustag(sc->sc_rres); + sc->sc_bh = rman_get_bushandle(sc->sc_rres); + + /* + * Disable all interrupt sources and clear outstanding interrupts + */ + hrowpic_write_reg(sc, HPIC_ENABLE, HPIC_PRIMARY, 0); + hrowpic_write_reg(sc, HPIC_CLEAR, HPIC_PRIMARY, 0xffffffff); + hrowpic_write_reg(sc, HPIC_ENABLE, HPIC_SECONDARY, 0); + hrowpic_write_reg(sc, HPIC_CLEAR, HPIC_SECONDARY, 0xffffffff); + + powerpc_register_pic(dev); + return (0); +} + +/* + * Local routines + */ + +static void +hrowpic_toggle_irq(struct hrowpic_softc *sc, int irq, int enable) +{ + u_int roffset; + u_int rbit; + + KASSERT((irq > 0) && (irq < HROWPIC_IRQMAX), ("en irq out of range")); + + /* + * Calculate prim/sec register bank for the IRQ, update soft copy, + * and enable the IRQ as an interrupt source + */ + roffset = HPIC_INT_TO_BANK(irq); + rbit = HPIC_INT_TO_REGBIT(irq); + + if (enable) + sc->sc_softreg[roffset] |= (1 << rbit); + else + sc->sc_softreg[roffset] &= ~(1 << rbit); + + hrowpic_write_reg(sc, HPIC_ENABLE, roffset, sc->sc_softreg[roffset]); +} + +/* + * PIC I/F methods. + */ + +static void +hrowpic_dispatch(device_t dev, struct trapframe *tf) +{ + struct hrowpic_softc *sc; + uint64_t mask; + uint32_t reg; + u_int irq; + + sc = device_get_softc(dev); + while (1) { + mask = hrowpic_read_reg(sc, HPIC_STATUS, HPIC_SECONDARY); + reg = hrowpic_read_reg(sc, HPIC_STATUS, HPIC_PRIMARY); + mask = (mask << 32) | reg; + if (mask == 0) + break; + + irq = 0; + while (irq < HROWPIC_IRQMAX) { + if (mask & 1) + powerpc_dispatch_intr(sc->sc_vector[irq], tf); + mask >>= 1; + irq++; + } + } +} + +static void +hrowpic_enable(device_t dev, u_int irq, u_int vector) +{ + struct hrowpic_softc *sc; + + sc = device_get_softc(dev); + sc->sc_vector[irq] = vector; + hrowpic_toggle_irq(sc, irq, 1); +} + +static void +hrowpic_eoi(device_t dev __unused, u_int irq __unused) +{ + struct hrowpic_softc *sc; + int bank; + + sc = device_get_softc(dev); + bank = (irq >= 32) ? HPIC_SECONDARY : HPIC_PRIMARY ; + hrowpic_write_reg(sc, HPIC_CLEAR, bank, 1U << (irq & 0x1f)); +} + +static void +hrowpic_mask(device_t dev, u_int irq) +{ + struct hrowpic_softc *sc; + int bank; + + sc = device_get_softc(dev); + hrowpic_toggle_irq(sc, irq, 0); + bank = (irq >= 32) ? HPIC_SECONDARY : HPIC_PRIMARY ; + hrowpic_write_reg(sc, HPIC_CLEAR, bank, 1U << (irq & 0x1f)); +} + +static void +hrowpic_unmask(device_t dev, u_int irq) +{ + struct hrowpic_softc *sc; + + sc = device_get_softc(dev); + hrowpic_toggle_irq(sc, irq, 1); +} diff --git a/sys/powerpc/powermac/hrowpicvar.h b/sys/powerpc/powermac/hrowpicvar.h new file mode 100644 index 000000000000..ac643f574d48 --- /dev/null +++ b/sys/powerpc/powermac/hrowpicvar.h @@ -0,0 +1,75 @@ +/*- + * Copyright 2003 by Peter Grehan. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _POWERPC_POWERMAC_HROWPICVAR_H_ +#define _POWERPC_POWERMAC_HROWPICVAR_H_ + +#define HROWPIC_IRQMAX 64 +#define HROWPIC_IRQ_REGNUM 32 /* irqs per register */ +#define HROWPIC_IRQ_SHIFT 5 /* high or low irq word */ +#define HROWPIC_IRQ_MASK ((HROWPIC_IRQMAX-1) >> 1) /* irq bit pos in word */ + +/* + * Register offsets within bank. There are two identical banks, + * separated by 16 bytes. Interrupts 0->31 are processed in the + * second bank, and 32->63 in the first bank. + */ +#define HPIC_STATUS 0x00 /* active interrupt sources */ +#define HPIC_ENABLE 0x04 /* interrupt asserts ppc EXTINT */ +#define HPIC_CLEAR 0x08 /* clear int source */ +#define HPIC_TRIGGER 0x0c /* edge/level int trigger */ + +#define HPIC_PRIMARY 1 /* primary register bank */ +#define HPIC_SECONDARY 0 /* secondary register bank */ + +/* + * Convert an interrupt into a prim/sec bank number + */ +#define HPIC_INT_TO_BANK(x) \ + (((x) >> HROWPIC_IRQ_SHIFT) ^ 1) + +/* + * Convert an interrupt into the bit number within a bank register + */ +#define HPIC_INT_TO_REGBIT(x) \ + ((x) & HROWPIC_IRQ_MASK) + +#define HPIC_1ST_OFFSET 0x10 /* offset to primary reg bank */ + +struct hrowpic_softc { + device_t sc_dev; /* macio device */ + struct resource *sc_rres; /* macio bus resource */ + bus_space_tag_t sc_bt; /* macio bus tag/handle */ + bus_space_handle_t sc_bh; + int sc_rrid; + uint32_t sc_softreg[2]; /* ENABLE reg copy */ + u_int sc_vector[HROWPIC_IRQMAX]; +}; + +#endif /* _POWERPC_POWERMAC_HROWPICVAR_H_ */ diff --git a/sys/powerpc/powermac/macio.c b/sys/powerpc/powermac/macio.c new file mode 100644 index 000000000000..d3d3dd4a43fd --- /dev/null +++ b/sys/powerpc/powermac/macio.c @@ -0,0 +1,542 @@ +/*- + * Copyright 2002 by Peter Grehan. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * Driver for KeyLargo/Pangea, the MacPPC south bridge ASIC. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <machine/bus.h> +#include <sys/rman.h> + +#include <machine/vmparam.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <machine/pmap.h> + +#include <machine/resource.h> + +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> +#include <dev/ofw/openfirm.h> + +#include <powerpc/powermac/maciovar.h> + +#include <dev/pci/pcivar.h> +#include <dev/pci/pcireg.h> + +/* + * Macio softc + */ +struct macio_softc { + phandle_t sc_node; + vm_offset_t sc_base; + vm_offset_t sc_size; + struct rman sc_mem_rman; +}; + +static MALLOC_DEFINE(M_MACIO, "macio", "macio device information"); + +static int macio_probe(device_t); +static int macio_attach(device_t); +static int macio_print_child(device_t dev, device_t child); +static void macio_probe_nomatch(device_t, device_t); +static struct resource *macio_alloc_resource(device_t, device_t, int, int *, + u_long, u_long, u_long, u_int); +static int macio_activate_resource(device_t, device_t, int, int, + struct resource *); +static int macio_deactivate_resource(device_t, device_t, int, int, + struct resource *); +static int macio_release_resource(device_t, device_t, int, int, + struct resource *); +static struct resource_list *macio_get_resource_list (device_t, device_t); +static ofw_bus_get_devinfo_t macio_get_devinfo; + +/* + * Bus interface definition + */ +static device_method_t macio_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, macio_probe), + DEVMETHOD(device_attach, macio_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* Bus interface */ + DEVMETHOD(bus_print_child, macio_print_child), + DEVMETHOD(bus_probe_nomatch, macio_probe_nomatch), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + DEVMETHOD(bus_alloc_resource, macio_alloc_resource), + DEVMETHOD(bus_release_resource, macio_release_resource), + DEVMETHOD(bus_activate_resource, macio_activate_resource), + DEVMETHOD(bus_deactivate_resource, macio_deactivate_resource), + DEVMETHOD(bus_get_resource_list, macio_get_resource_list), + + /* ofw_bus interface */ + DEVMETHOD(ofw_bus_get_devinfo, macio_get_devinfo), + DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat), + DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model), + DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), + DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), + DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), + + { 0, 0 } +}; + +static driver_t macio_pci_driver = { + "macio", + macio_methods, + sizeof(struct macio_softc) +}; + +devclass_t macio_devclass; + +DRIVER_MODULE(macio, pci, macio_pci_driver, macio_devclass, 0, 0); + +/* + * PCI ID search table + */ +static struct macio_pci_dev { + u_int32_t mpd_devid; + char *mpd_desc; +} macio_pci_devlist[] = { + { 0x0017106b, "Paddington I/O Controller" }, + { 0x0022106b, "KeyLargo I/O Controller" }, + { 0x0025106b, "Pangea I/O Controller" }, + { 0x003e106b, "Intrepid I/O Controller" }, + { 0, NULL } +}; + +/* + * Devices to exclude from the probe + * XXX some of these may be required in the future... + */ +#define MACIO_QUIRK_IGNORE 0x00000001 +#define MACIO_QUIRK_CHILD_HAS_INTR 0x00000002 + +struct macio_quirk_entry { + const char *mq_name; + int mq_quirks; +}; + +static struct macio_quirk_entry macio_quirks[] = { + { "escc-legacy", MACIO_QUIRK_IGNORE }, + { "timer", MACIO_QUIRK_IGNORE }, + { "escc", MACIO_QUIRK_CHILD_HAS_INTR }, + { NULL, 0 } +}; + +static int +macio_get_quirks(const char *name) +{ + struct macio_quirk_entry *mqe; + + for (mqe = macio_quirks; mqe->mq_name != NULL; mqe++) + if (strcmp(name, mqe->mq_name) == 0) + return (mqe->mq_quirks); + return (0); +} + + +/* + * Add an interrupt to the dev's resource list if present + */ +static void +macio_add_intr(phandle_t devnode, struct macio_devinfo *dinfo) +{ + int intr; + + if (dinfo->mdi_ninterrupts >= 5) { + printf("macio: device has more than 5 interrupts\n"); + return; + } + + if (OF_getprop(devnode, "interrupts", &intr, sizeof(intr)) == -1) { + if (OF_getprop(devnode, "AAPL,interrupts", &intr, + sizeof(intr)) == -1) + return; + } + + if (intr == -1) + return; + + resource_list_add(&dinfo->mdi_resources, SYS_RES_IRQ, + dinfo->mdi_ninterrupts, intr, intr, 1); + + dinfo->mdi_interrupts[dinfo->mdi_ninterrupts] = intr; + dinfo->mdi_ninterrupts++; +} + + +static void +macio_add_reg(phandle_t devnode, struct macio_devinfo *dinfo) +{ + struct macio_reg *reg; + int i, nreg; + + nreg = OF_getprop_alloc(devnode, "reg", sizeof(*reg), (void **)®); + if (nreg == -1) + return; + + for (i = 0; i < nreg; i++) { + resource_list_add(&dinfo->mdi_resources, SYS_RES_MEMORY, i, + reg[i].mr_base, reg[i].mr_base + reg[i].mr_size, + reg[i].mr_size); + } +} + +/* + * PCI probe + */ +static int +macio_probe(device_t dev) +{ + int i; + u_int32_t devid; + + devid = pci_get_devid(dev); + for (i = 0; macio_pci_devlist[i].mpd_desc != NULL; i++) { + if (devid == macio_pci_devlist[i].mpd_devid) { + device_set_desc(dev, macio_pci_devlist[i].mpd_desc); + return (0); + } + } + + return (ENXIO); +} + +/* + * PCI attach: scan Open Firmware child nodes, and attach these as children + * of the macio bus + */ +static int +macio_attach(device_t dev) +{ + struct macio_softc *sc; + struct macio_devinfo *dinfo; + phandle_t root; + phandle_t child; + phandle_t subchild; + device_t cdev; + u_int reg[3]; + int quirks; + + sc = device_get_softc(dev); + root = sc->sc_node = OF_finddevice("mac-io"); + + /* + * Locate the device node and it's base address + */ + if (OF_getprop(root, "assigned-addresses", + reg, sizeof(reg)) < sizeof(reg)) { + return (ENXIO); + } + + sc->sc_base = reg[2]; + sc->sc_size = MACIO_REG_SIZE; + + sc->sc_mem_rman.rm_type = RMAN_ARRAY; + sc->sc_mem_rman.rm_descr = "MacIO Device Memory"; + if (rman_init(&sc->sc_mem_rman) != 0) { + device_printf(dev, + "failed to init mem range resources\n"); + return (ENXIO); + } + rman_manage_region(&sc->sc_mem_rman, 0, sc->sc_size); + + /* + * Iterate through the sub-devices + */ + for (child = OF_child(root); child != 0; child = OF_peer(child)) { + dinfo = malloc(sizeof(*dinfo), M_MACIO, M_WAITOK | M_ZERO); + if (ofw_bus_gen_setup_devinfo(&dinfo->mdi_obdinfo, child) != + 0) { + free(dinfo, M_MACIO); + continue; + } + quirks = macio_get_quirks(dinfo->mdi_obdinfo.obd_name); + if ((quirks & MACIO_QUIRK_IGNORE) != 0) { + ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo); + free(dinfo, M_MACIO); + continue; + } + resource_list_init(&dinfo->mdi_resources); + dinfo->mdi_ninterrupts = 0; + macio_add_intr(child, dinfo); + macio_add_reg(child, dinfo); + if ((quirks & MACIO_QUIRK_CHILD_HAS_INTR) != 0) + for (subchild = OF_child(child); subchild != 0; + subchild = OF_peer(subchild)) + macio_add_intr(subchild, dinfo); + cdev = device_add_child(dev, NULL, -1); + if (cdev == NULL) { + device_printf(dev, "<%s>: device_add_child failed\n", + dinfo->mdi_obdinfo.obd_name); + resource_list_free(&dinfo->mdi_resources); + ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo); + free(dinfo, M_MACIO); + continue; + } + device_set_ivars(cdev, dinfo); + } + + return (bus_generic_attach(dev)); +} + + +static int +macio_print_child(device_t dev, device_t child) +{ + struct macio_devinfo *dinfo; + struct resource_list *rl; + int retval = 0; + + dinfo = device_get_ivars(child); + rl = &dinfo->mdi_resources; + + retval += bus_print_child_header(dev, child); + + retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx"); + retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); + + retval += bus_print_child_footer(dev, child); + + return (retval); +} + + +static void +macio_probe_nomatch(device_t dev, device_t child) +{ + struct macio_devinfo *dinfo; + struct resource_list *rl; + const char *type; + + if (bootverbose) { + dinfo = device_get_ivars(child); + rl = &dinfo->mdi_resources; + + if ((type = ofw_bus_get_type(child)) == NULL) + type = "(unknown)"; + device_printf(dev, "<%s, %s>", type, ofw_bus_get_name(child)); + resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx"); + resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); + printf(" (no driver attached)\n"); + } +} + + +static struct resource * +macio_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct macio_softc *sc; + int needactivate; + struct resource *rv; + struct rman *rm; + bus_space_tag_t tagval; + u_long adjstart, adjend, adjcount; + struct macio_devinfo *dinfo; + struct resource_list_entry *rle; + + sc = device_get_softc(bus); + dinfo = device_get_ivars(child); + + needactivate = flags & RF_ACTIVE; + flags &= ~RF_ACTIVE; + + switch (type) { + case SYS_RES_MEMORY: + case SYS_RES_IOPORT: + rle = resource_list_find(&dinfo->mdi_resources, SYS_RES_MEMORY, + *rid); + if (rle == NULL) { + device_printf(bus, "no rle for %s memory %d\n", + device_get_nameunit(child), *rid); + return (NULL); + } + + if (start < rle->start) + adjstart = rle->start; + else if (start > rle->end) + adjstart = rle->end; + else + adjstart = start; + + if (end < rle->start) + adjend = rle->start; + else if (end > rle->end) + adjend = rle->end; + else + adjend = end; + + adjcount = adjend - adjstart; + + rm = &sc->sc_mem_rman; + + tagval = PPC_BUS_SPACE_MEM; + break; + + case SYS_RES_IRQ: + rle = resource_list_find(&dinfo->mdi_resources, SYS_RES_IRQ, + *rid); + if (rle == NULL) { + if (dinfo->mdi_ninterrupts >= 5) { + device_printf(bus, + "%s has more than 5 interrupts\n", + device_get_nameunit(child)); + return (NULL); + } + resource_list_add(&dinfo->mdi_resources, SYS_RES_IRQ, + dinfo->mdi_ninterrupts, start, start, 1); + + dinfo->mdi_interrupts[dinfo->mdi_ninterrupts] = start; + dinfo->mdi_ninterrupts++; + } + + return (resource_list_alloc(&dinfo->mdi_resources, bus, child, + type, rid, start, end, count, flags)); + break; + + default: + device_printf(bus, "unknown resource request from %s\n", + device_get_nameunit(child)); + return (NULL); + } + + rv = rman_reserve_resource(rm, adjstart, adjend, adjcount, flags, + child); + if (rv == NULL) { + device_printf(bus, + "failed to reserve resource %#lx - %#lx (%#lx) for %s\n", + adjstart, adjend, adjcount, device_get_nameunit(child)); + return (NULL); + } + + rman_set_rid(rv, *rid); + rman_set_bustag(rv, tagval); + rman_set_bushandle(rv, rman_get_start(rv)); + + if (needactivate) { + if (bus_activate_resource(child, type, *rid, rv) != 0) { + device_printf(bus, + "failed to activate resource for %s\n", + device_get_nameunit(child)); + rman_release_resource(rv); + return (NULL); + } + } + + return (rv); +} + + +static int +macio_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + if (rman_get_flags(res) & RF_ACTIVE) { + int error = bus_deactivate_resource(child, type, rid, res); + if (error) + return error; + } + + return (rman_release_resource(res)); +} + + +static int +macio_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + struct macio_softc *sc; + void *p; + + sc = device_get_softc(bus); + + if (type == SYS_RES_IRQ) + return (bus_activate_resource(bus, type, rid, res)); + + if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { + p = pmap_mapdev((vm_offset_t)rman_get_start(res) + sc->sc_base, + (vm_size_t)rman_get_size(res)); + if (p == NULL) + return (ENOMEM); + rman_set_virtual(res, p); + rman_set_bushandle(res, (u_long)p); + } + + return (rman_activate_resource(res)); +} + + +static int +macio_deactivate_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + /* + * If this is a memory resource, unmap it. + */ + if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { + u_int32_t psize; + + psize = rman_get_size(res); + pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize); + } + + return (rman_deactivate_resource(res)); +} + + +static struct resource_list * +macio_get_resource_list (device_t dev, device_t child) +{ + struct macio_devinfo *dinfo; + + dinfo = device_get_ivars(child); + return (&dinfo->mdi_resources); +} + +static const struct ofw_bus_devinfo * +macio_get_devinfo(device_t dev, device_t child) +{ + struct macio_devinfo *dinfo; + + dinfo = device_get_ivars(child); + return (&dinfo->mdi_obdinfo); +} diff --git a/sys/powerpc/powermac/maciovar.h b/sys/powerpc/powermac/maciovar.h new file mode 100644 index 000000000000..e2891022ea23 --- /dev/null +++ b/sys/powerpc/powermac/maciovar.h @@ -0,0 +1,59 @@ +/*- + * Copyright 2002 by Peter Grehan. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACIO_MACIOVAR_H_ +#define _MACIO_MACIOVAR_H_ + +/* + * The addr space size + * XXX it would be better if this could be determined by querying the + * PCI device, but there isn't an access method for this + */ +#define MACIO_REG_SIZE 0x7ffff + +/* + * Format of a macio reg property entry. + */ +struct macio_reg { + u_int32_t mr_base; + u_int32_t mr_size; +}; + +/* + * Per macio device structure. + */ +struct macio_devinfo { + int mdi_interrupts[5]; + int mdi_ninterrupts; + int mdi_base; + struct ofw_bus_devinfo mdi_obdinfo; + struct resource_list mdi_resources; +}; + +#endif /* _MACIO_MACIOVAR_H_ */ diff --git a/sys/powerpc/powermac/openpic_macio.c b/sys/powerpc/powermac/openpic_macio.c new file mode 100644 index 000000000000..822804e1c2ce --- /dev/null +++ b/sys/powerpc/powermac/openpic_macio.c @@ -0,0 +1,97 @@ +/*- + * Copyright 2003 by Peter Grehan. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> + +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/openfirm.h> + +#include <machine/bus.h> +#include <machine/intr.h> +#include <machine/intr_machdep.h> +#include <machine/md_var.h> +#include <machine/nexusvar.h> +#include <machine/pio.h> +#include <machine/resource.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <sys/rman.h> + +#include <machine/openpicvar.h> + +#include "pic_if.h" + +/* + * MacIO interface + */ +static int openpic_macio_probe(device_t); + +static device_method_t openpic_macio_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, openpic_macio_probe), + DEVMETHOD(device_attach, openpic_attach), + + /* PIC interface */ + DEVMETHOD(pic_dispatch, openpic_dispatch), + DEVMETHOD(pic_enable, openpic_enable), + DEVMETHOD(pic_eoi, openpic_eoi), + DEVMETHOD(pic_mask, openpic_mask), + DEVMETHOD(pic_unmask, openpic_unmask), + + { 0, 0 }, +}; + +static driver_t openpic_macio_driver = { + "openpic", + openpic_macio_methods, + sizeof(struct openpic_softc), +}; + +DRIVER_MODULE(openpic, macio, openpic_macio_driver, openpic_devclass, 0, 0); + +static int +openpic_macio_probe(device_t dev) +{ + const char *type = ofw_bus_get_type(dev); + + if (strcmp(type, "open-pic") != 0) + return (ENXIO); + + device_set_desc(dev, OPENPIC_DEVSTR); + return (0); +} diff --git a/sys/powerpc/powermac/pswitch.c b/sys/powerpc/powermac/pswitch.c new file mode 100644 index 000000000000..62777eb33748 --- /dev/null +++ b/sys/powerpc/powermac/pswitch.c @@ -0,0 +1,144 @@ +/*- + * Copyright (C) 2002 Benno Rice. + * 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 Benno Rice ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "opt_ddb.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kdb.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/malloc.h> +#include <sys/bus.h> +#include <machine/bus.h> +#include <sys/rman.h> + +#include <machine/resource.h> + +#include <dev/ofw/openfirm.h> + +#include <powerpc/powermac/maciovar.h> + +struct pswitch_softc { + int sc_irqrid; + struct resource *sc_irq; + void *sc_ih; +}; + +static int pswitch_probe(device_t); +static int pswitch_attach(device_t); + +static int pswitch_intr(void *); + +static device_method_t pswitch_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, pswitch_probe), + DEVMETHOD(device_attach, pswitch_attach), + + { 0, 0 } +}; + +static driver_t pswitch_driver = { + "pswitch", + pswitch_methods, + sizeof(struct pswitch_softc) +}; + +static devclass_t pswitch_devclass; + +DRIVER_MODULE(pswitch, macio, pswitch_driver, pswitch_devclass, 0, 0); + +static int +pswitch_probe(device_t dev) +{ + char *type = macio_get_devtype(dev); + + if (strcmp(type, "gpio") != 0) + return (ENXIO); + + device_set_desc(dev, "GPIO Programmer's Switch"); + return (0); +} + +static int +pswitch_attach(device_t dev) +{ + struct pswitch_softc *sc; + phandle_t node, child; + char type[32]; + u_int irq[2]; + + sc = device_get_softc(dev); + node = macio_get_node(dev); + + for (child = OF_child(node); child != 0; child = OF_peer(child)) { + if (OF_getprop(child, "device_type", type, 32) == -1) + continue; + + if (strcmp(type, "programmer-switch") == 0) + break; + } + + if (child == 0) { + device_printf(dev, "could not find correct node\n"); + return (ENXIO); + } + + if (OF_getprop(child, "interrupts", irq, sizeof(irq)) == -1) { + device_printf(dev, "could not get interrupt\n"); + return (ENXIO); + } + + sc->sc_irqrid = 0; + sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_irqrid, + irq[0], irq[0], 1, RF_ACTIVE); + if (sc->sc_irq == NULL) { + device_printf(dev, "could not allocate interrupt\n"); + return (ENXIO); + } + + if (bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC, + pswitch_intr, NULL, dev, &sc->sc_ih) != 0) { + device_printf(dev, "could not setup interrupt\n"); + bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqrid, + sc->sc_irq); + return (ENXIO); + } + + return (0); +} + +static int +pswitch_intr(void *arg) +{ + device_t dev; + + dev = (device_t)arg; + + kdb_enter(device_get_nameunit(dev)); + return (FILTER_HANDLED); +} diff --git a/sys/powerpc/powermac/uninorth.c b/sys/powerpc/powermac/uninorth.c new file mode 100644 index 000000000000..f3b0996e5ea0 --- /dev/null +++ b/sys/powerpc/powermac/uninorth.c @@ -0,0 +1,600 @@ +/*- + * Copyright (C) 2002 Benno Rice. + * 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 Benno Rice ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> + +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_pci.h> + +#include <dev/pci/pcivar.h> +#include <dev/pci/pcireg.h> + +#include <machine/bus.h> +#include <machine/md_var.h> +#include <machine/nexusvar.h> +#include <machine/resource.h> + +#include <sys/rman.h> + +#include <powerpc/ofw/ofw_pci.h> +#include <powerpc/powermac/uninorthvar.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include "pcib_if.h" + +#define UNINORTH_DEBUG 0 + +/* + * Device interface. + */ +static int uninorth_probe(device_t); +static int uninorth_attach(device_t); + +/* + * Bus interface. + */ +static int uninorth_read_ivar(device_t, device_t, int, + uintptr_t *); +static struct resource * uninorth_alloc_resource(device_t bus, + device_t child, int type, int *rid, u_long start, + u_long end, u_long count, u_int flags); +static int uninorth_activate_resource(device_t bus, device_t child, + int type, int rid, struct resource *res); + +/* + * pcib interface. + */ +static int uninorth_maxslots(device_t); +static u_int32_t uninorth_read_config(device_t, u_int, u_int, u_int, + u_int, int); +static void uninorth_write_config(device_t, u_int, u_int, u_int, + u_int, u_int32_t, int); +static int uninorth_route_interrupt(device_t, device_t, int); + +/* + * Local routines. + */ +static int uninorth_enable_config(struct uninorth_softc *, u_int, + u_int, u_int, u_int); +static void unin_enable_gmac(void); + +/* + * Driver methods. + */ +static device_method_t uninorth_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, uninorth_probe), + DEVMETHOD(device_attach, uninorth_attach), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_read_ivar, uninorth_read_ivar), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(bus_alloc_resource, uninorth_alloc_resource), + DEVMETHOD(bus_activate_resource, uninorth_activate_resource), + + /* pcib interface */ + DEVMETHOD(pcib_maxslots, uninorth_maxslots), + DEVMETHOD(pcib_read_config, uninorth_read_config), + DEVMETHOD(pcib_write_config, uninorth_write_config), + DEVMETHOD(pcib_route_interrupt, uninorth_route_interrupt), + + { 0, 0 } +}; + +static driver_t uninorth_driver = { + "pcib", + uninorth_methods, + sizeof(struct uninorth_softc) +}; + +static devclass_t uninorth_devclass; + +DRIVER_MODULE(uninorth, nexus, uninorth_driver, uninorth_devclass, 0, 0); + +static int +uninorth_probe(device_t dev) +{ + char *type, *compatible; + + type = nexus_get_device_type(dev); + compatible = nexus_get_compatible(dev); + + if (type == NULL || compatible == NULL) + return (ENXIO); + + if (strcmp(type, "pci") != 0 || strcmp(compatible, "uni-north") != 0) + return (ENXIO); + + device_set_desc(dev, "Apple UniNorth Host-PCI bridge"); + return (0); +} + +static int +uninorth_attach(device_t dev) +{ + struct uninorth_softc *sc; + phandle_t node; + phandle_t child; + u_int32_t reg[2], busrange[2]; + struct uninorth_range *rp, *io, *mem[2]; + int nmem, i; + + node = nexus_get_node(dev); + sc = device_get_softc(dev); + + if (OF_getprop(node, "reg", reg, sizeof(reg)) < 8) + return (ENXIO); + + if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8) + return (ENXIO); + + sc->sc_dev = dev; + sc->sc_node = node; + sc->sc_addr = (vm_offset_t)pmap_mapdev(reg[0] + 0x800000, PAGE_SIZE); + sc->sc_data = (vm_offset_t)pmap_mapdev(reg[0] + 0xc00000, PAGE_SIZE); + sc->sc_bus = busrange[0]; + + bzero(sc->sc_range, sizeof(sc->sc_range)); + sc->sc_nrange = OF_getprop(node, "ranges", sc->sc_range, + sizeof(sc->sc_range)); + + if (sc->sc_nrange == -1) { + device_printf(dev, "could not get ranges\n"); + return (ENXIO); + } + + sc->sc_range[6].pci_hi = 0; + io = NULL; + nmem = 0; + + for (rp = sc->sc_range; rp->pci_hi != 0; rp++) { + switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { + case OFW_PCI_PHYS_HI_SPACE_CONFIG: + break; + case OFW_PCI_PHYS_HI_SPACE_IO: + io = rp; + break; + case OFW_PCI_PHYS_HI_SPACE_MEM32: + mem[nmem] = rp; + nmem++; + break; + case OFW_PCI_PHYS_HI_SPACE_MEM64: + break; + } + } + + if (io == NULL) { + device_printf(dev, "can't find io range\n"); + return (ENXIO); + } + sc->sc_io_rman.rm_type = RMAN_ARRAY; + sc->sc_io_rman.rm_descr = "UniNorth PCI I/O Ports"; + sc->sc_iostart = io->host; + if (rman_init(&sc->sc_io_rman) != 0 || + rman_manage_region(&sc->sc_io_rman, io->pci_lo, + io->pci_lo + io->size_lo - 1) != 0) { + device_printf(dev, "failed to set up io range management\n"); + return (ENXIO); + } + + if (nmem == 0) { + device_printf(dev, "can't find mem ranges\n"); + return (ENXIO); + } + sc->sc_mem_rman.rm_type = RMAN_ARRAY; + sc->sc_mem_rman.rm_descr = "UniNorth PCI Memory"; + if (rman_init(&sc->sc_mem_rman) != 0) { + device_printf(dev, + "failed to init mem range resources\n"); + return (ENXIO); + } + for (i = 0; i < nmem; i++) { + if (rman_manage_region(&sc->sc_mem_rman, mem[i]->pci_lo, + mem[i]->pci_lo + mem[i]->size_lo - 1) != 0) { + device_printf(dev, + "failed to set up memory range management\n"); + return (ENXIO); + } + } + + /* + * Enable the GMAC Ethernet cell if Open Firmware says it is + * used. + */ + for (child = OF_child(node); child; child = OF_peer(child)) { + char compat[32]; + + memset(compat, 0, sizeof(compat)); + OF_getprop(child, "compatible", compat, sizeof(compat)); + if (strcmp(compat, "gmac") == 0) { + unin_enable_gmac(); + } + } + + /* + * Write out the correct PIC interrupt values to config space + * of all devices on the bus. This has to be done after the GEM + * cell is enabled above. + */ + ofw_pci_fixup(dev, sc->sc_bus, node); + + device_add_child(dev, "pci", device_get_unit(dev)); + return (bus_generic_attach(dev)); +} + +static int +uninorth_maxslots(device_t dev) +{ + + return (PCI_SLOTMAX); +} + +static u_int32_t +uninorth_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, + int width) +{ + struct uninorth_softc *sc; + vm_offset_t caoff; + + sc = device_get_softc(dev); + caoff = sc->sc_data + (reg & 0x07); + + if (uninorth_enable_config(sc, bus, slot, func, reg) != 0) { + switch (width) { + case 1: + return (in8rb(caoff)); + break; + case 2: + return (in16rb(caoff)); + break; + case 4: + return (in32rb(caoff)); + break; + } + } + + return (0xffffffff); +} + +static void +uninorth_write_config(device_t dev, u_int bus, u_int slot, u_int func, + u_int reg, u_int32_t val, int width) +{ + struct uninorth_softc *sc; + vm_offset_t caoff; + + sc = device_get_softc(dev); + caoff = sc->sc_data + (reg & 0x07); + + if (uninorth_enable_config(sc, bus, slot, func, reg)) { + switch (width) { + case 1: + out8rb(caoff, val); + break; + case 2: + out16rb(caoff, val); + break; + case 4: + out32rb(caoff, val); + break; + } + } +} + +static int +uninorth_route_interrupt(device_t bus, device_t dev, int pin) +{ + + return (0); +} + +static int +uninorth_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct uninorth_softc *sc; + + sc = device_get_softc(dev); + + switch (which) { + case PCIB_IVAR_DOMAIN: + *result = device_get_unit(dev); + return (0); + case PCIB_IVAR_BUS: + *result = sc->sc_bus; + return (0); + } + + return (ENOENT); +} + +static struct resource * +uninorth_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct uninorth_softc *sc; + struct resource *rv; + struct rman *rm; + bus_space_tag_t bt; + int needactivate; + + needactivate = flags & RF_ACTIVE; + flags &= ~RF_ACTIVE; + + sc = device_get_softc(bus); + + switch (type) { + case SYS_RES_MEMORY: + rm = &sc->sc_mem_rman; + bt = PPC_BUS_SPACE_MEM; + break; + + case SYS_RES_IOPORT: + rm = &sc->sc_io_rman; + bt = PPC_BUS_SPACE_IO; + break; + + case SYS_RES_IRQ: + return (bus_alloc_resource(bus, type, rid, start, end, count, + flags)); + break; + default: + device_printf(bus, "unknown resource request from %s\n", + device_get_nameunit(child)); + return (NULL); + } + + rv = rman_reserve_resource(rm, start, end, count, flags, child); + if (rv == NULL) { + device_printf(bus, "failed to reserve resource for %s\n", + device_get_nameunit(child)); + return (NULL); + } + + rman_set_rid(rv, *rid); + rman_set_bustag(rv, bt); + rman_set_bushandle(rv, rman_get_start(rv)); + + if (needactivate) { + if (bus_activate_resource(child, type, *rid, rv) != 0) { + device_printf(bus, + "failed to activate resource for %s\n", + device_get_nameunit(child)); + rman_release_resource(rv); + return (NULL); + } + } + + return (rv); +} + +static int +uninorth_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + void *p; + struct uninorth_softc *sc; + + sc = device_get_softc(bus); + + if (type == SYS_RES_IRQ) + return (bus_activate_resource(bus, type, rid, res)); + + if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { + vm_offset_t start; + + start = (vm_offset_t)rman_get_start(res); + /* + * For i/o-ports, convert the start address to the + * uninorth PCI i/o window + */ + if (type == SYS_RES_IOPORT) + start += sc->sc_iostart; + + if (bootverbose) + printf("uninorth mapdev: start %x, len %ld\n", start, + rman_get_size(res)); + + p = pmap_mapdev(start, (vm_size_t)rman_get_size(res)); + if (p == NULL) + return (ENOMEM); + rman_set_virtual(res, p); + rman_set_bushandle(res, (u_long)p); + } + + return (rman_activate_resource(res)); +} + +static int +uninorth_enable_config(struct uninorth_softc *sc, u_int bus, u_int slot, + u_int func, u_int reg) +{ + uint32_t cfgval; + uint32_t pass; + + if (resource_int_value(device_get_name(sc->sc_dev), + device_get_unit(sc->sc_dev), "skipslot", &pass) == 0) { + if (pass == slot) + return (0); + } + + if (sc->sc_bus == bus) { + /* + * No slots less than 11 on the primary bus + */ + if (slot < 11) + return (0); + + cfgval = (1 << slot) | (func << 8) | (reg & 0xfc); + } else { + cfgval = (bus << 16) | (slot << 11) | (func << 8) | + (reg & 0xfc) | 1; + } + + do { + out32rb(sc->sc_addr, cfgval); + } while (in32rb(sc->sc_addr) != cfgval); + + return (1); +} + +/* + * Driver to swallow UniNorth host bridges from the PCI bus side. + */ +static int +unhb_probe(device_t dev) +{ + + if (pci_get_class(dev) == PCIC_BRIDGE && + pci_get_subclass(dev) == PCIS_BRIDGE_HOST) { + device_set_desc(dev, "Host to PCI bridge"); + device_quiet(dev); + return (-10000); + } + + return (ENXIO); +} + +static int +unhb_attach(device_t dev) +{ + + return (0); +} + +static device_method_t unhb_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, unhb_probe), + DEVMETHOD(device_attach, unhb_attach), + + { 0, 0 } +}; + +static driver_t unhb_driver = { + "unhb", + unhb_methods, + 1, +}; +static devclass_t unhb_devclass; + +DRIVER_MODULE(unhb, pci, unhb_driver, unhb_devclass, 0, 0); + + +/* + * Small stub driver for the Uninorth chip itself, to allow setting + * of various parameters and cell enables + */ +static struct unin_chip_softc *uncsc; + +static void +unin_enable_gmac(void) +{ + volatile u_int *clkreg; + u_int32_t tmpl; + + if (uncsc == NULL) + panic("unin_enable_gmac: device not found"); + + clkreg = (void *)(uncsc->sc_addr + UNIN_CLOCKCNTL); + tmpl = inl(clkreg); + tmpl |= UNIN_CLOCKCNTL_GMAC; + outl(clkreg, tmpl); +} + +static int +unin_chip_probe(device_t dev) +{ + char *name; + + name = nexus_get_name(dev); + + if (name == NULL) + return (ENXIO); + + if (strcmp(name, "uni-n") != 0) + return (ENXIO); + + device_set_desc(dev, "Apple UniNorth System Controller"); + return (0); +} + +static int +unin_chip_attach(device_t dev) +{ + phandle_t node; + u_int reg[2]; + + uncsc = device_get_softc(dev); + node = nexus_get_node(dev); + + if (OF_getprop(node, "reg", reg, sizeof(reg)) < 8) + return (ENXIO); + + uncsc->sc_physaddr = reg[0]; + uncsc->sc_size = reg[1]; + + /* + * Only map the first page, since that is where the registers + * of interest lie. + */ + uncsc->sc_addr = (vm_offset_t) pmap_mapdev(reg[0], PAGE_SIZE); + + uncsc->sc_version = *(u_int *)uncsc->sc_addr; + device_printf(dev, "Version %d\n", uncsc->sc_version); + + return (0); +} + +static device_method_t unin_chip_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, unin_chip_probe), + DEVMETHOD(device_attach, unin_chip_attach), + + { 0, 0 } +}; + +static driver_t unin_chip_driver = { + "unin", + unin_chip_methods, + sizeof(struct unin_chip_softc) +}; + +static devclass_t unin_chip_devclass; + +DRIVER_MODULE(unin, nexus, unin_chip_driver, unin_chip_devclass, 0, 0); + + + + diff --git a/sys/powerpc/powermac/uninorthvar.h b/sys/powerpc/powermac/uninorthvar.h new file mode 100644 index 000000000000..d2ee8d793e3c --- /dev/null +++ b/sys/powerpc/powermac/uninorthvar.h @@ -0,0 +1,74 @@ +/*- + * Copyright (C) 2002 Benno Rice. + * 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 Benno Rice ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _POWERPC_POWERMAC_UNINORTHVAR_H_ +#define _POWERPC_POWERMAC_UNINORTHVAR_H_ + +struct uninorth_range { + u_int32_t pci_hi; + u_int32_t pci_mid; + u_int32_t pci_lo; + u_int32_t host; + u_int32_t size_hi; + u_int32_t size_lo; +}; + +struct uninorth_softc { + device_t sc_dev; + phandle_t sc_node; + vm_offset_t sc_addr; + vm_offset_t sc_data; + int sc_bus; + struct uninorth_range sc_range[6]; + int sc_nrange; + int sc_iostart; + struct rman sc_io_rman; + struct rman sc_mem_rman; + bus_space_tag_t sc_iot; + bus_space_tag_t sc_memt; + bus_dma_tag_t sc_dmat; +}; + +struct unin_chip_softc { + vm_offset_t sc_physaddr; + vm_offset_t sc_addr; + u_int sc_size; + int sc_version; +}; + +/* + * Version register + */ +#define UNIN_VERS 0x0 + +/* + * Clock-control register + */ +#define UNIN_CLOCKCNTL 0x20 +#define UNIN_CLOCKCNTL_GMAC 0x2 + +#endif /* _POWERPC_POWERMAC_UNINORTHVAR_H_ */ diff --git a/sys/powerpc/powerpc/atomic.S b/sys/powerpc/powerpc/atomic.S new file mode 100644 index 000000000000..c6f669a6670b --- /dev/null +++ b/sys/powerpc/powerpc/atomic.S @@ -0,0 +1,137 @@ +/*- + * Copyright (c) 2000, 2001 Benno Rice + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <machine/asm.h> + + .text + +ASENTRY(atomic_set_8) +0: lwarx 0, 0, 3 /* load old value */ + slwi 4, 4, 24 /* shift the byte so it's in the right place */ + or 0, 0, 4 /* generate new value */ + stwcx. 0, 0, 3 /* attempt to store */ + bne- 0 /* loop if failed */ + eieio /* synchronise */ + sync + blr /* return */ + +ASENTRY(atomic_clear_8) +0: lwarx 0, 0, 3 /* load old value */ + slwi 4, 4, 24 /* shift the byte so it's in the right place */ + andc 0, 0, 4 /* generate new value */ + stwcx. 0, 0, 3 /* attempt to store */ + bne- 0 /* loop if failed */ + eieio /* synchronise */ + sync + blr /* return */ + +ASENTRY(atomic_add_8) +0: lwarx 9, 0, 3 /* load old value */ + srwi 0, 9, 24 /* byte alignment */ + add 0, 4, 0 /* calculate new value */ + slwi 0, 9, 24 /* byte alignment */ + clrlwi 9, 9, 8 /* clear the byte in the original word */ + or 9, 9, 0 /* copy back in to the original word */ + stwcx. 9, 0, 3 /* attempt to store */ + bne- 0 /* loop if failed */ + eieio /* synchronise */ + sync + blr /* return */ + +ASENTRY(atomic_subtract_8) +0: lwarx 9, 0, 3 /* load old value */ + srwi 0, 9, 24 /* byte alignment */ + subf 0, 4, 0 /* calculate new value */ + slwi 0, 9, 24 /* byte alignment */ + clrlwi 9, 9, 8 /* clear the byte in the original word */ + or 9, 9, 0 /* copy back in to the original word */ + stwcx. 9, 0, 3 /* attempt to store */ + bne- 0 /* loop if failed */ + eieio /* synchronise */ + sync + blr /* return */ + +ASENTRY(atomic_set_16) + li 11, 3 /* mask to test for alignment */ + andc. 11, 3, 11 /* force address to be word-aligned */ +0: lwarx 12, 0, 11 /* load old value */ + bne 1f /* no realignment needed if it's aligned */ + slwi 4, 4, 16 /* realign operand */ +1: or 12, 12, 4 /* calculate new value */ + stwcx. 12, 0, 11 /* attempt to store */ + bne- 0b /* loop if failed */ + eieio /* synchronise */ + sync + blr /* return */ + +ASENTRY(atomic_clear_16) + li 11, 3 /* mask to test for alignment */ + andc. 11, 3, 11 /* force address to be word-aligned */ +0: lwarx 12, 0, 11 /* load old value */ + bne 1f /* no realignment needed if it's aligned */ + slwi 4, 4, 16 /* realign operand */ +1: andc 12, 12, 4 /* calculate new value */ + stwcx. 12, 0, 11 /* attempt to store */ + bne- 0b /* loop if failed */ + eieio /* synchronise */ + sync + blr /* return */ + +ASENTRY(atomic_add_16) + li 11, 3 /* mask to test for alignment */ + andc. 11, 3, 11 /* force address to be word-aligned */ +0: lwarx 12, 0, 11 /* load old value */ + bne 1f /* no realignment needed if it's aligned */ + srwi 12, 9, 16 /* realign */ +1: add 12, 4, 12 /* calculate new value */ + bne 2f /* no realignment needed if it's aligned */ + slwi 12, 12, 16 /* realign */ +2: clrlwi 9, 9, 16 /* clear old value */ + or 9, 9, 12 /* copy in new value */ + stwcx. 12, 0, 11 /* attempt to store */ + bne- 0b /* loop if failed */ + eieio /* synchronise */ + sync + blr /* return */ + +ASENTRY(atomic_subtract_16) + li 11, 3 /* mask to test for alignment */ + andc. 11, 3, 11 /* force address to be word-aligned */ +0: lwarx 12, 0, 11 /* load old value */ + bne 1f /* no realignment needed if it's aligned */ + srwi 12, 9, 16 /* realign */ +1: subf 12, 4, 12 /* calculate new value */ + bne 2f /* no realignment needed if it's aligned */ + slwi 12, 12, 16 /* realign */ +2: clrlwi 9, 9, 16 /* clear old value */ + or 9, 9, 12 /* copy in new value */ + stwcx. 12, 0, 11 /* attempt to store */ + bne- 0 /* loop if failed */ + eieio /* synchronise */ + sync + blr /* return */ diff --git a/sys/powerpc/powerpc/autoconf.c b/sys/powerpc/powerpc/autoconf.c new file mode 100644 index 000000000000..644932304182 --- /dev/null +++ b/sys/powerpc/powerpc/autoconf.c @@ -0,0 +1,84 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/cons.h> +#include <sys/kernel.h> + +#include <machine/intr_machdep.h> + +static device_t nexusdev; + +static void configure_first(void *); +static void configure(void *); +static void configure_final(void *); + +SYSINIT(configure1, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure_first, NULL); +/* SI_ORDER_SECOND is hookable */ +SYSINIT(configure2, SI_SUB_CONFIGURE, SI_ORDER_THIRD, configure, NULL); +/* SI_ORDER_MIDDLE is hookable */ +SYSINIT(configure3, SI_SUB_CONFIGURE, SI_ORDER_ANY, configure_final, NULL); + +/* + * Determine i/o configuration for a machine. + */ +static void +configure_first(void *dummy) +{ + + nexusdev = device_add_child(root_bus, "nexus", 0); +} + +static void +configure(void *dummy) +{ + + root_bus_configure(); +} + +static void +configure_final(void *dummy) +{ + + /* + * Now that we're guaranteed to have a PIC driver (or we'll never + * have one), program it with all the previously setup interrupts. + */ + powerpc_enable_intr(); + + /* Enable external interrupts. */ + mtmsr(mfmsr() | PSL_EE | PSL_RI); + + cninit_finish(); + cold = 0; +} + + diff --git a/sys/powerpc/powerpc/bcopy.c b/sys/powerpc/powerpc/bcopy.c new file mode 100644 index 000000000000..af9e3bfd82db --- /dev/null +++ b/sys/powerpc/powerpc/bcopy.c @@ -0,0 +1,149 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char *sccsid = "from: @(#)bcopy.c 5.11 (Berkeley) 6/21/91"; +#endif +#if 0 +static char *rcsid = "$NetBSD: bcopy.c,v 1.2 1997/04/16 22:09:41 thorpej Exp $"; +#endif +#endif /* LIBC_SCCS and not lint */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#ifdef _KERNEL +#include <sys/systm.h> +#else +#include <string.h> +#endif + +/* + * sizeof(word) MUST BE A POWER OF TWO + * SO THAT wmask BELOW IS ALL ONES + */ +typedef int word; /* "word" used for optimal copy speed */ + +#define wsize sizeof(word) +#define wmask (wsize - 1) + +/* + * Copy a block of memory, handling overlap. + * This is the routine that actually implements + * (the portable versions of) bcopy, memcpy, and memmove. + */ +void * +memcpy(void *dst0, const void *src0, size_t length) +{ + char *dst; + const char *src; + size_t t; + + dst = dst0; + src = src0; + + if (length == 0 || dst == src) { /* nothing to do */ + goto done; + } + + /* + * Macros: loop-t-times; and loop-t-times, t>0 + */ +#define TLOOP(s) if (t) TLOOP1(s) +#define TLOOP1(s) do { s; } while (--t) + + if ((unsigned long)dst < (unsigned long)src) { + /* + * Copy forward. + */ + t = (int)src; /* only need low bits */ + + if ((t | (int)dst) & wmask) { + /* + * Try to align operands. This cannot be done + * unless the low bits match. + */ + if ((t ^ (int)dst) & wmask || length < wsize) { + t = length; + } else { + t = wsize - (t & wmask); + } + + length -= t; + TLOOP1(*dst++ = *src++); + } + /* + * Copy whole words, then mop up any trailing bytes. + */ + t = length / wsize; + TLOOP(*(word *)dst = *(const word *)src; src += wsize; + dst += wsize); + t = length & wmask; + TLOOP(*dst++ = *src++); + } else { + /* + * Copy backwards. Otherwise essentially the same. + * Alignment works as before, except that it takes + * (t&wmask) bytes to align, not wsize-(t&wmask). + */ + src += length; + dst += length; + t = (int)src; + + if ((t | (int)dst) & wmask) { + if ((t ^ (int)dst) & wmask || length <= wsize) { + t = length; + } else { + t &= wmask; + } + + length -= t; + TLOOP1(*--dst = *--src); + } + t = length / wsize; + TLOOP(src -= wsize; dst -= wsize; + *(word *)dst = *(const word *)src); + t = length & wmask; + TLOOP(*--dst = *--src); + } +done: + return (dst0); +} + +void +bcopy(const void *src0, void *dst0, size_t length) +{ + + memcpy(dst0, src0, length); +} + diff --git a/sys/powerpc/powerpc/busdma_machdep.c b/sys/powerpc/powerpc/busdma_machdep.c new file mode 100644 index 000000000000..5f4ad44c37bd --- /dev/null +++ b/sys/powerpc/powerpc/busdma_machdep.c @@ -0,0 +1,589 @@ +/*- + * Copyright (c) 2002 Peter Grehan + * Copyright (c) 1997, 1998 Justin T. Gibbs. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * From i386/busdma_machdep.c,v 1.26 2002/04/19 22:58:09 alfred + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * MacPPC bus dma support routines + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/malloc.h> +#include <sys/bus.h> +#include <sys/interrupt.h> +#include <sys/lock.h> +#include <sys/proc.h> +#include <sys/mutex.h> +#include <sys/mbuf.h> +#include <sys/uio.h> + +#include <vm/vm.h> +#include <vm/vm_page.h> +#include <vm/vm_map.h> + +#include <machine/atomic.h> +#include <machine/bus.h> +#include <machine/cpufunc.h> + +struct bus_dma_tag { + bus_dma_tag_t parent; + bus_size_t alignment; + bus_size_t boundary; + bus_addr_t lowaddr; + bus_addr_t highaddr; + bus_dma_filter_t *filter; + void *filterarg; + bus_size_t maxsize; + u_int nsegments; + bus_size_t maxsegsz; + int flags; + int ref_count; + int map_count; + bus_dma_lock_t *lockfunc; + void *lockfuncarg; +}; + +struct bus_dmamap { + bus_dma_tag_t dmat; + void *buf; /* unmapped buffer pointer */ + bus_size_t buflen; /* unmapped buffer length */ + bus_dmamap_callback_t *callback; + void *callback_arg; +}; + +/* + * Convenience function for manipulating driver locks from busdma (during + * busdma_swi, for example). Drivers that don't provide their own locks + * should specify &Giant to dmat->lockfuncarg. Drivers that use their own + * non-mutex locking scheme don't have to use this at all. + */ +void +busdma_lock_mutex(void *arg, bus_dma_lock_op_t op) +{ + struct mtx *dmtx; + + dmtx = (struct mtx *)arg; + switch (op) { + case BUS_DMA_LOCK: + mtx_lock(dmtx); + break; + case BUS_DMA_UNLOCK: + mtx_unlock(dmtx); + break; + default: + panic("Unknown operation 0x%x for busdma_lock_mutex!", op); + } +} + +/* + * dflt_lock should never get called. It gets put into the dma tag when + * lockfunc == NULL, which is only valid if the maps that are associated + * with the tag are meant to never be defered. + * XXX Should have a way to identify which driver is responsible here. + */ +static void +dflt_lock(void *arg, bus_dma_lock_op_t op) +{ +#ifdef INVARIANTS + panic("driver error: busdma dflt_lock called"); +#else + printf("DRIVER_ERROR: busdma dflt_lock called\n"); +#endif +} + +/* + * Allocate a device specific dma_tag. + */ +int +bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, + bus_size_t boundary, bus_addr_t lowaddr, + bus_addr_t highaddr, bus_dma_filter_t *filter, + void *filterarg, bus_size_t maxsize, int nsegments, + bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc, + void *lockfuncarg, bus_dma_tag_t *dmat) +{ + bus_dma_tag_t newtag; + int error = 0; + + /* Return a NULL tag on failure */ + *dmat = NULL; + + newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF, M_NOWAIT); + if (newtag == NULL) + return (ENOMEM); + + newtag->parent = parent; + newtag->alignment = alignment; + newtag->boundary = boundary; + newtag->lowaddr = trunc_page((vm_offset_t)lowaddr) + (PAGE_SIZE - 1); + newtag->highaddr = trunc_page((vm_offset_t)highaddr) + (PAGE_SIZE - 1); + newtag->filter = filter; + newtag->filterarg = filterarg; + newtag->maxsize = maxsize; + newtag->nsegments = nsegments; + newtag->maxsegsz = maxsegsz; + newtag->flags = flags; + newtag->ref_count = 1; /* Count ourself */ + newtag->map_count = 0; + if (lockfunc != NULL) { + newtag->lockfunc = lockfunc; + newtag->lockfuncarg = lockfuncarg; + } else { + newtag->lockfunc = dflt_lock; + newtag->lockfuncarg = NULL; + } + + /* + * Take into account any restrictions imposed by our parent tag + */ + if (parent != NULL) { + newtag->lowaddr = min(parent->lowaddr, newtag->lowaddr); + newtag->highaddr = max(parent->highaddr, newtag->highaddr); + if (newtag->boundary == 0) + newtag->boundary = parent->boundary; + else if (parent->boundary != 0) + newtag->boundary = MIN(parent->boundary, + newtag->boundary); + if (newtag->filter == NULL) { + /* + * Short circuit looking at our parent directly + * since we have encapsulated all of its information + */ + newtag->filter = parent->filter; + newtag->filterarg = parent->filterarg; + newtag->parent = parent->parent; + } + if (newtag->parent != NULL) + atomic_add_int(&parent->ref_count, 1); + } + + *dmat = newtag; + return (error); +} + +int +bus_dma_tag_destroy(bus_dma_tag_t dmat) +{ + if (dmat != NULL) { + + if (dmat->map_count != 0) + return (EBUSY); + + while (dmat != NULL) { + bus_dma_tag_t parent; + + parent = dmat->parent; + atomic_subtract_int(&dmat->ref_count, 1); + if (dmat->ref_count == 0) { + free(dmat, M_DEVBUF); + /* + * Last reference count, so + * release our reference + * count on our parent. + */ + dmat = parent; + } else + dmat = NULL; + } + } + return (0); +} + +/* + * Allocate a handle for mapping from kva/uva/physical + * address space into bus device space. + */ +int +bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) +{ + *mapp = NULL; + dmat->map_count++; + + return (0); +} + +/* + * Destroy a handle for mapping from kva/uva/physical + * address space into bus device space. + */ +int +bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) +{ + if (map != NULL) { + panic("dmamap_destroy: NULL?\n"); + } + dmat->map_count--; + return (0); +} + +/* + * Allocate a piece of memory that can be efficiently mapped into + * bus device space based on the constraints lited in the dma tag. + * A dmamap to for use with dmamap_load is also allocated. + */ +int +bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, + bus_dmamap_t *mapp) +{ + int mflags; + + if (flags & BUS_DMA_NOWAIT) + mflags = M_NOWAIT; + else + mflags = M_WAITOK; + if (flags & BUS_DMA_ZERO) + mflags |= M_ZERO; + + *mapp = NULL; + + /* + * XXX: + * (dmat->alignment < dmat->maxsize) is just a quick hack; the exact + * alignment guarantees of malloc need to be nailed down, and the + * code below should be rewritten to take that into account. + * + * In the meantime, we'll return an error if malloc gets it wrong. + */ + if (dmat->maxsize <= PAGE_SIZE && + dmat->alignment < dmat->maxsize) { + *vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags); + } else { + /* + * XXX Use Contigmalloc until it is merged into this facility + * and handles multi-seg allocations. Nobody is doing + * multi-seg allocations yet though. + */ + *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags, + 0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul, + dmat->boundary); + } + + if (*vaddr == NULL) + return (ENOMEM); + + if ((uintptr_t)*vaddr % dmat->alignment) + printf("XXX: %s: alignment not respected!\n", __func__); + + return (0); +} + +/* + * Free a piece of memory and it's allocated dmamap, that was allocated + * via bus_dmamem_alloc. Make the same choice for free/contigfree. + */ +void +bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) +{ + if (map != NULL) + panic("bus_dmamem_free: Invalid map freed\n"); + if (dmat->maxsize <= PAGE_SIZE && + dmat->alignment < dmat->maxsize) + free(vaddr, M_DEVBUF); + else + contigfree(vaddr, dmat->maxsize, M_DEVBUF); +} + +/* + * Utility function to load a linear buffer. lastaddrp holds state + * between invocations (for multiple-buffer loads). segp contains + * the starting segment on entrance, and the ending segment on exit. + * first indicates if this is the first invocation of this function. + */ +static int +bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dma_segment_t segs[], + void *buf, bus_size_t buflen, struct thread *td, + int flags, vm_offset_t *lastaddrp, int *segp, + int first) +{ + bus_size_t sgsize; + bus_addr_t curaddr, lastaddr, baddr, bmask; + vm_offset_t vaddr = (vm_offset_t)buf; + int seg; + pmap_t pmap; + + if (td != NULL) + pmap = vmspace_pmap(td->td_proc->p_vmspace); + else + pmap = NULL; + + lastaddr = *lastaddrp; + bmask = ~(dmat->boundary - 1); + + for (seg = *segp; buflen > 0 ; ) { + /* + * Get the physical address for this segment. + */ + if (pmap) + curaddr = pmap_extract(pmap, vaddr); + else + curaddr = pmap_kextract(vaddr); + + /* + * Compute the segment size, and adjust counts. + */ + sgsize = PAGE_SIZE - ((u_long)curaddr & PAGE_MASK); + if (sgsize > dmat->maxsegsz) + sgsize = dmat->maxsegsz; + if (buflen < sgsize) + sgsize = buflen; + + /* + * Make sure we don't cross any boundaries. + */ + if (dmat->boundary > 0) { + baddr = (curaddr + dmat->boundary) & bmask; + if (sgsize > (baddr - curaddr)) + sgsize = (baddr - curaddr); + } + + /* + * Insert chunk into a segment, coalescing with + * the previous segment if possible. + */ + if (first) { + segs[seg].ds_addr = curaddr; + segs[seg].ds_len = sgsize; + first = 0; + } else { + if (curaddr == lastaddr && + (segs[seg].ds_len + sgsize) <= dmat->maxsegsz && + (dmat->boundary == 0 || + (segs[seg].ds_addr & bmask) == (curaddr & bmask))) + segs[seg].ds_len += sgsize; + else { + if (++seg >= dmat->nsegments) + break; + segs[seg].ds_addr = curaddr; + segs[seg].ds_len = sgsize; + } + } + + lastaddr = curaddr + sgsize; + vaddr += sgsize; + buflen -= sgsize; + } + + *segp = seg; + *lastaddrp = lastaddr; + + /* + * Did we fit? + */ + return (buflen != 0 ? EFBIG : 0); /* XXX better return value here? */ +} + +/* + * Map the buffer buf into bus space using the dmamap map. + */ +int +bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, + bus_size_t buflen, bus_dmamap_callback_t *callback, + void *callback_arg, int flags) +{ +#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT + bus_dma_segment_t dm_segments[dmat->nsegments]; +#else + bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS]; +#endif + vm_offset_t lastaddr; + int error, nsegs; + + if (map != NULL) + panic("bus_dmamap_load: Invalid map\n"); + + lastaddr = (vm_offset_t)0; + nsegs = 0; + error = bus_dmamap_load_buffer(dmat, dm_segments, buf, buflen, + NULL, flags, &lastaddr, &nsegs, 1); + + if (error == 0) + (*callback)(callback_arg, dm_segments, nsegs + 1, 0); + else + (*callback)(callback_arg, NULL, 0, error); + + return (0); +} + +/* + * Like bus_dmamap_load(), but for mbufs. + */ +int +bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, + bus_dmamap_callback2_t *callback, void *callback_arg, + int flags) +{ +#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT + bus_dma_segment_t dm_segments[dmat->nsegments]; +#else + bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS]; +#endif + int nsegs = 0, error = 0; + + M_ASSERTPKTHDR(m0); + + if (m0->m_pkthdr.len <= dmat->maxsize) { + int first = 1; + vm_offset_t lastaddr = 0; + struct mbuf *m; + + for (m = m0; m != NULL && error == 0; m = m->m_next) { + if (m->m_len > 0) { + error = bus_dmamap_load_buffer(dmat, + dm_segments, m->m_data, m->m_len, NULL, + flags, &lastaddr, &nsegs, first); + first = 0; + } + } + } else { + error = EINVAL; + } + + if (error) { + /* + * force "no valid mappings" on error in callback. + */ + (*callback)(callback_arg, dm_segments, 0, 0, error); + } else { + (*callback)(callback_arg, dm_segments, nsegs+1, + m0->m_pkthdr.len, error); + } + return (error); +} + +int +bus_dmamap_load_mbuf_sg(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m0, + bus_dma_segment_t *segs, int *nsegs, int flags) +{ + int error = 0; + + M_ASSERTPKTHDR(m0); + + *nsegs = 0; + + if (m0->m_pkthdr.len <= dmat->maxsize) { + int first = 1; + vm_offset_t lastaddr = 0; + struct mbuf *m; + + for (m = m0; m != NULL && error == 0; m = m->m_next) { + if (m->m_len > 0) { + error = bus_dmamap_load_buffer(dmat, + segs, m->m_data, m->m_len, NULL, + flags, &lastaddr, nsegs, first); + first = 0; + } + } + ++*nsegs; + } else { + error = EINVAL; + } + + return (error); +} + +/* + * Like bus_dmamap_load(), but for uios. + */ +int +bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *uio, + bus_dmamap_callback2_t *callback, void *callback_arg, + int flags) +{ + vm_offset_t lastaddr; +#ifdef __CC_SUPPORTS_DYNAMIC_ARRAY_INIT + bus_dma_segment_t dm_segments[dmat->nsegments]; +#else + bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS]; +#endif + int nsegs, i, error, first; + bus_size_t resid; + struct iovec *iov; + struct thread *td = NULL; + + resid = uio->uio_resid; + iov = uio->uio_iov; + + if (uio->uio_segflg == UIO_USERSPACE) { + td = uio->uio_td; + KASSERT(td != NULL, + ("bus_dmamap_load_uio: USERSPACE but no proc")); + } + + first = 1; + nsegs = error = 0; + for (i = 0; i < uio->uio_iovcnt && resid != 0 && !error; i++) { + /* + * Now at the first iovec to load. Load each iovec + * until we have exhausted the residual count. + */ + bus_size_t minlen = + resid < iov[i].iov_len ? resid : iov[i].iov_len; + caddr_t addr = (caddr_t) iov[i].iov_base; + + if (minlen > 0) { + error = bus_dmamap_load_buffer(dmat, dm_segments, addr, + minlen, td, flags, &lastaddr, &nsegs, first); + + first = 0; + + resid -= minlen; + } + } + + if (error) { + /* + * force "no valid mappings" on error in callback. + */ + (*callback)(callback_arg, dm_segments, 0, 0, error); + } else { + (*callback)(callback_arg, dm_segments, nsegs+1, + uio->uio_resid, error); + } + + return (error); +} + +/* + * Release the mapping held by map. A no-op on PowerPC. + */ +void +_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map) +{ + + return; +} + +void +_bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) +{ + + return; +} diff --git a/sys/powerpc/powerpc/clock.c b/sys/powerpc/powerpc/clock.c new file mode 100644 index 000000000000..0c01cf048911 --- /dev/null +++ b/sys/powerpc/powerpc/clock.c @@ -0,0 +1,318 @@ +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: clock.c,v 1.9 2000/01/19 02:52:19 msaitoh Exp $ + */ +/* + * Copyright (C) 2001 Benno Rice. + * 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 Benno Rice ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/sysctl.h> +#include <sys/bus.h> +#include <sys/clock.h> +#include <sys/timetc.h> +#include <sys/interrupt.h> + +#include <dev/ofw/openfirm.h> + +#include <machine/clock.h> +#include <machine/cpu.h> +#include <machine/intr.h> +#include <machine/md_var.h> + +/* + * Initially we assume a processor with a bus frequency of 12.5 MHz. + */ +u_int tickspending; +u_long ns_per_tick = 80; +static u_long ticks_per_sec = 12500000; +static long ticks_per_intr; +static volatile u_long lasttb; + +#define DIFF19041970 2082844800 + +static int clockinitted = 0; + +static timecounter_get_t decr_get_timecount; + +static struct timecounter decr_timecounter = { + decr_get_timecount, /* get_timecount */ + 0, /* no poll_pps */ + ~0u, /* counter_mask */ + 0, /* frequency */ + "decrementer" /* name */ +}; + +void +inittodr(time_t base) +{ + time_t deltat; + u_int rtc_time; + struct timespec ts; + phandle_t phandle; + ihandle_t ihandle; + char rtcpath[128]; + u_int rtcsecs; + + /* + * If we can't read from RTC, use the fs time. + */ + phandle = OF_finddevice("rtc"); + if (phandle != -1) { + OF_package_to_path(phandle, rtcpath, sizeof(rtcpath)); + ihandle = OF_open(rtcpath); + if (ihandle != -1) { + if (OF_call_method("read-rtc", ihandle, + 0, 1, &rtcsecs)) + printf("RTC call method error\n"); + else { + ts.tv_sec = rtcsecs - DIFF19041970; + ts.tv_nsec = 0; + tc_setclock(&ts); + return; + } + } + } + + { + ts.tv_sec = base; + ts.tv_nsec = 0; + tc_setclock(&ts); + return; + } + clockinitted = 1; + ts.tv_sec = rtc_time - DIFF19041970; + + deltat = ts.tv_sec - base; + if (deltat < 0) { + deltat = -deltat; + } + if (deltat < 2 * SECDAY) { + tc_setclock(&ts); + return; + } + + printf("WARNING: clock %s %d days", + ts.tv_sec < base ? "lost" : "gained", (int)(deltat / SECDAY)); + + printf(" -- CHECK AND RESET THE DATE!\n"); +} + +/* + * Similar to the above + */ +void +resettodr() +{ + +} + +void +decr_intr(struct trapframe *frame) +{ + u_long tb; + long tick; + int nticks; + + /* + * Check whether we are initialized. + */ + if (!ticks_per_intr) + return; + + /* + * Based on the actual time delay since the last decrementer reload, + * we arrange for earlier interrupt next time. + */ + __asm ("mftb %0; mfdec %1" : "=r"(tb), "=r"(tick)); + for (nticks = 0; tick < 0; nticks++) + tick += ticks_per_intr; + mtdec(tick); + /* + * lasttb is used during microtime. Set it to the virtual + * start of this tick interval. + */ + lasttb = tb + tick - ticks_per_intr; + + nticks += tickspending; + tickspending = 0; + + /* + * Reenable interrupts + */ +#if 0 + msr = mfmsr(); + mtmsr(msr | PSL_EE | PSL_RI); +#endif + /* + * Do standard timer interrupt stuff. + * Do softclock stuff only on the last iteration. + */ +#if 0 + while (--nticks > 0) { + hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); + } +#endif + hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); +} + +void +decr_init(void) +{ + int qhandle, phandle; + char name[32]; + unsigned int msr; + + phandle = 0; + + /* + * Get this info during autoconf? XXX + */ + for (qhandle = OF_peer(0); qhandle; qhandle = phandle) { + if (OF_getprop(qhandle, "device_type", name, sizeof name) >= 0 + && !strcmp(name, "cpu") + && OF_getprop(qhandle, "timebase-frequency", + &ticks_per_sec, sizeof ticks_per_sec) >= 0) { + /* + * Should check for correct CPU here? XXX + */ + msr = mfmsr(); + mtmsr(msr & ~(PSL_EE|PSL_RI)); + + ns_per_tick = 1000000000 / ticks_per_sec; + ticks_per_intr = ticks_per_sec / hz; + __asm __volatile ("mftb %0" : "=r"(lasttb)); + mtdec(ticks_per_intr); + + mtmsr(msr); + + break; + } + if ((phandle = OF_child(qhandle))) + continue; + while (qhandle) { + if ((phandle = OF_peer(qhandle))) + break; + qhandle = OF_parent(qhandle); + } + } + if (!phandle) + panic("no cpu node"); +} + +void +decr_tc_init(void) +{ + decr_timecounter.tc_frequency = ticks_per_sec; + tc_init(&decr_timecounter); +} + +static __inline u_quad_t +mftb(void) +{ + u_long scratch; + u_quad_t tb; + + __asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw 0,%0,%1; bne 1b" + : "=r"(tb), "=r"(scratch)); + return tb; +} + +static unsigned +decr_get_timecount(struct timecounter *tc) +{ + return mftb(); +} + +/* + * Wait for about n microseconds (at least!). + */ +void +DELAY(int n) +{ + u_quad_t tb, ttb; + + tb = mftb(); + ttb = tb + (n * 1000 + ns_per_tick - 1) / ns_per_tick; + while (tb < ttb) + tb = mftb(); +} + +/* + * Nothing to do. + */ +void +cpu_startprofclock(void) +{ + + /* Do nothing */ +} + +void +cpu_stopprofclock(void) +{ +} + +/* + * XXX Needed by syscons + */ +int +sysbeep(int pitch, int period) +{ + + return (0); +} diff --git a/sys/powerpc/powerpc/copyinout.c b/sys/powerpc/powerpc/copyinout.c new file mode 100644 index 000000000000..4e9f77746f1a --- /dev/null +++ b/sys/powerpc/powerpc/copyinout.c @@ -0,0 +1,356 @@ +/*- + * Copyright (C) 2002 Benno Rice + * 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 Benno Rice ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*- + * Copyright (C) 1993 Wolfgang Solfrank. + * Copyright (C) 1993 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> + +#include <machine/pcb.h> +#include <machine/sr.h> + +int setfault(faultbuf); /* defined in locore.S */ + +/* + * Makes sure that the right segment of userspace is mapped in. + */ +static __inline void +set_user_sr(register_t vsid) +{ + + isync(); + __asm __volatile ("mtsr %0,%1" :: "n"(USER_SR), "r"(vsid)); + isync(); +} + +int +copyout(const void *kaddr, void *udaddr, size_t len) +{ + struct thread *td; + pmap_t pm; + faultbuf env; + const char *kp; + char *up, *p; + size_t l; + + td = PCPU_GET(curthread); + pm = &td->td_proc->p_vmspace->vm_pmap; + + if (setfault(env)) { + td->td_pcb->pcb_onfault = NULL; + return (EFAULT); + } + + kp = kaddr; + up = udaddr; + + while (len > 0) { + p = (char *)USER_ADDR + ((u_int)up & ~SEGMENT_MASK); + + l = ((char *)USER_ADDR + SEGMENT_LENGTH) - p; + if (l > len) + l = len; + + set_user_sr(pm->pm_sr[(u_int)up >> ADDR_SR_SHFT]); + + bcopy(kp, p, l); + + up += l; + kp += l; + len -= l; + } + + td->td_pcb->pcb_onfault = NULL; + return (0); +} + +int +copyin(const void *udaddr, void *kaddr, size_t len) +{ + struct thread *td; + pmap_t pm; + faultbuf env; + const char *up; + char *kp, *p; + size_t l; + + td = PCPU_GET(curthread); + pm = &td->td_proc->p_vmspace->vm_pmap; + + if (setfault(env)) { + td->td_pcb->pcb_onfault = NULL; + return (EFAULT); + } + + kp = kaddr; + up = udaddr; + + while (len > 0) { + p = (char *)USER_ADDR + ((u_int)up & ~SEGMENT_MASK); + + l = ((char *)USER_ADDR + SEGMENT_LENGTH) - p; + if (l > len) + l = len; + + set_user_sr(pm->pm_sr[(u_int)up >> ADDR_SR_SHFT]); + + bcopy(p, kp, l); + + up += l; + kp += l; + len -= l; + } + + td->td_pcb->pcb_onfault = NULL; + return (0); +} + +int +copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done) +{ + struct thread *td; + pmap_t pm; + faultbuf env; + const char *up; + char *kp; + size_t l; + int rv, c; + + td = PCPU_GET(curthread); + pm = &td->td_proc->p_vmspace->vm_pmap; + + if (setfault(env)) { + td->td_pcb->pcb_onfault = NULL; + return (EFAULT); + } + + kp = kaddr; + up = udaddr; + + rv = ENAMETOOLONG; + + for (l = 0; len-- > 0; l++) { + if ((c = fubyte(up++)) < 0) { + rv = EFAULT; + break; + } + + if (!(*kp++ = c)) { + l++; + rv = 0; + break; + } + } + + if (done != NULL) { + *done = l; + } + + td->td_pcb->pcb_onfault = NULL; + return (rv); +} + +int +subyte(void *addr, int byte) +{ + struct thread *td; + pmap_t pm; + faultbuf env; + char *p; + + td = PCPU_GET(curthread); + pm = &td->td_proc->p_vmspace->vm_pmap; + p = (char *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK)); + + if (setfault(env)) { + td->td_pcb->pcb_onfault = NULL; + return (-1); + } + + set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]); + + *p = (char)byte; + + td->td_pcb->pcb_onfault = NULL; + return (0); +} + +int +suword(void *addr, long word) +{ + struct thread *td; + pmap_t pm; + faultbuf env; + long *p; + + td = PCPU_GET(curthread); + pm = &td->td_proc->p_vmspace->vm_pmap; + p = (long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK)); + + if (setfault(env)) { + td->td_pcb->pcb_onfault = NULL; + return (-1); + } + + set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]); + + *p = word; + + td->td_pcb->pcb_onfault = NULL; + return (0); +} + +int +suword32(void *addr, int32_t word) +{ + return (suword(addr, (long)word)); +} + + +int +fubyte(const void *addr) +{ + struct thread *td; + pmap_t pm; + faultbuf env; + u_char *p; + int val; + + td = PCPU_GET(curthread); + pm = &td->td_proc->p_vmspace->vm_pmap; + p = (u_char *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK)); + + if (setfault(env)) { + td->td_pcb->pcb_onfault = NULL; + return (-1); + } + + set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]); + + val = *p; + + td->td_pcb->pcb_onfault = NULL; + return (val); +} + +long +fuword(const void *addr) +{ + struct thread *td; + pmap_t pm; + faultbuf env; + long *p, val; + + td = PCPU_GET(curthread); + pm = &td->td_proc->p_vmspace->vm_pmap; + p = (long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK)); + + if (setfault(env)) { + td->td_pcb->pcb_onfault = NULL; + return (-1); + } + + set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]); + + val = *p; + + td->td_pcb->pcb_onfault = NULL; + return (val); +} + +int32_t +fuword32(const void *addr) +{ + return ((int32_t)fuword(addr)); +} + +uint32_t +casuword32(volatile uint32_t *base, uint32_t oldval, uint32_t newval) +{ + return (casuword((volatile u_long *)base, oldval, newval)); +} + +u_long +casuword(volatile u_long *addr, u_long old, u_long new) +{ + struct thread *td; + pmap_t pm; + faultbuf env; + u_long *p, val; + + td = PCPU_GET(curthread); + pm = &td->td_proc->p_vmspace->vm_pmap; + p = (u_long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK)); + + set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]); + + if (setfault(env)) { + td->td_pcb->pcb_onfault = NULL; + return (-1); + } + + val = *p; + (void) atomic_cmpset_32((volatile uint32_t *)p, old, new); + + td->td_pcb->pcb_onfault = NULL; + + return (val); +} diff --git a/sys/powerpc/powerpc/copystr.c b/sys/powerpc/powerpc/copystr.c new file mode 100644 index 000000000000..1a159d87185b --- /dev/null +++ b/sys/powerpc/powerpc/copystr.c @@ -0,0 +1,68 @@ +/*- + * Copyright (C) 1995 Wolfgang Solfrank. + * Copyright (C) 1995 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: copystr.c,v 1.3 2000/06/08 06:47:17 kleink Exp $ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/systm.h> + +/* + * Emulate copyinstr. + */ +int +copystr(kfaddr, kdaddr, len, done) + const void *kfaddr; + void *kdaddr; + size_t len; + size_t *done; +{ + const u_char *kfp = kfaddr; + u_char *kdp = kdaddr; + size_t l; + int rv; + + rv = ENAMETOOLONG; + for (l = 0; len-- > 0; l++) { + if (!(*kdp++ = *kfp++)) { + l++; + rv = 0; + break; + } + } + if (done != NULL) { + *done = l; + } + return rv; +} diff --git a/sys/powerpc/powerpc/cpu.c b/sys/powerpc/powerpc/cpu.c new file mode 100644 index 000000000000..d942af6d4279 --- /dev/null +++ b/sys/powerpc/powerpc/cpu.c @@ -0,0 +1,385 @@ +/*- + * Copyright (c) 2001 Matt Thomas. + * Copyright (c) 2001 Tsubai Masanari. + * Copyright (c) 1998, 1999, 2001 Internet Research Institute, Inc. + * 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 + * Internet Research Institute, Inc. + * 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) 2003 Benno Rice. + * 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 Benno Rice ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * from $NetBSD: cpu_subr.c,v 1.1 2003/02/03 17:10:09 matt Exp $ + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/sysctl.h> + +#include <machine/bus.h> +#include <machine/hid.h> +#include <machine/md_var.h> +#include <machine/spr.h> + +struct cputab { + const char *name; + uint16_t version; + uint16_t revfmt; +}; +#define REVFMT_MAJMIN 1 /* %u.%u */ +#define REVFMT_HEX 2 /* 0x%04x */ +#define REVFMT_DEC 3 /* %u */ +static const struct cputab models[] = { + { "Motorola PowerPC 601", MPC601, REVFMT_DEC }, + { "Motorola PowerPC 602", MPC602, REVFMT_DEC }, + { "Motorola PowerPC 603", MPC603, REVFMT_MAJMIN }, + { "Motorola PowerPC 603e", MPC603e, REVFMT_MAJMIN }, + { "Motorola PowerPC 603ev", MPC603ev, REVFMT_MAJMIN }, + { "Motorola PowerPC 604", MPC604, REVFMT_MAJMIN }, + { "Motorola PowerPC 604ev", MPC604ev, REVFMT_MAJMIN }, + { "Motorola PowerPC 620", MPC620, REVFMT_HEX }, + { "Motorola PowerPC 750", MPC750, REVFMT_MAJMIN }, + { "IBM PowerPC 750FX", IBM750FX, REVFMT_MAJMIN }, + { "Motorola PowerPC 7400", MPC7400, REVFMT_MAJMIN }, + { "Motorola PowerPC 7410", MPC7410, REVFMT_MAJMIN }, + { "Motorola PowerPC 7450", MPC7450, REVFMT_MAJMIN }, + { "Motorola PowerPC 7455", MPC7455, REVFMT_MAJMIN }, + { "Motorola PowerPC 7457", MPC7457, REVFMT_MAJMIN }, + { "Motorola PowerPC 7447A", MPC7447A, REVFMT_MAJMIN }, + { "Motorola PowerPC 7448", MPC7448, REVFMT_MAJMIN }, + { "Motorola PowerPC 8240", MPC8240, REVFMT_MAJMIN }, + { "Unknown PowerPC CPU", 0, REVFMT_HEX } +}; + +static char model[64]; +SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, model, 0, ""); + +static register_t l2cr_config = 0; + +static void cpu_print_speed(void); +static void cpu_config_l2cr(u_int, uint16_t); + +void +cpu_setup(u_int cpuid) +{ + u_int pvr, maj, min, hid0; + uint16_t vers, rev, revfmt; + const struct cputab *cp; + const char *name; + char *bitmask; + + pvr = mfpvr(); + vers = pvr >> 16; + rev = pvr; + switch (vers) { + case MPC7410: + min = (pvr >> 0) & 0xff; + maj = min <= 4 ? 1 : 2; + break; + default: + maj = (pvr >> 8) & 0xf; + min = (pvr >> 0) & 0xf; + } + + for (cp = models; cp->version != 0; cp++) { + if (cp->version == vers) + break; + } + + revfmt = cp->revfmt; + name = cp->name; + if (rev == MPC750 && pvr == 15) { + name = "Motorola MPC755"; + revfmt = REVFMT_HEX; + } + strncpy(model, name, sizeof(model) - 1); + + printf("cpu%d: %s revision ", cpuid, name); + + switch (revfmt) { + case REVFMT_MAJMIN: + printf("%u.%u", maj, min); + break; + case REVFMT_HEX: + printf("0x%04x", rev); + break; + case REVFMT_DEC: + printf("%u", rev); + break; + } + + hid0 = mfspr(SPR_HID0); + + /* + * Configure power-saving mode. + */ + switch (vers) { + case MPC603: + case MPC603e: + case MPC603ev: + case MPC604ev: + case MPC750: + case IBM750FX: + case MPC7400: + case MPC7410: + case MPC8240: + case MPC8245: + /* Select DOZE mode. */ + hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); + hid0 |= HID0_DOZE | HID0_DPM; +#ifdef notyet + powersave = 1; +#endif + break; + + case MPC7448: + case MPC7447A: + case MPC7457: + case MPC7455: + case MPC7450: + /* Enable the 7450 branch caches */ + hid0 |= HID0_SGE | HID0_BTIC; + hid0 |= HID0_LRSTK | HID0_FOLD | HID0_BHT; + /* Disable BTIC on 7450 Rev 2.0 or earlier and on 7457 */ + if (((pvr >> 16) == MPC7450 && (pvr & 0xFFFF) <= 0x0200) + || (pvr >> 16) == MPC7457) + hid0 &= ~HID0_BTIC; + /* Select NAP mode. */ + hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); + hid0 |= HID0_NAP | HID0_DPM; +#ifdef notyet + powersave = 0; /* but don't use it */ +#endif + break; + + default: + /* No power-saving mode is available. */ ; + } + + switch (vers) { + case IBM750FX: + case MPC750: + hid0 &= ~HID0_DBP; /* XXX correct? */ + hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT; + break; + + case MPC7400: + case MPC7410: + hid0 &= ~HID0_SPD; + hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT; + hid0 |= HID0_EIEC; + break; + } + + mtspr(SPR_HID0, hid0); + + switch (vers) { + case MPC7447A: + case MPC7448: + case MPC7450: + case MPC7455: + case MPC7457: + bitmask = HID0_7450_BITMASK; + break; + default: + bitmask = HID0_BITMASK; + break; + } + + switch (vers) { + case MPC750: + case IBM750FX: + case MPC7400: + case MPC7410: + case MPC7447A: + case MPC7448: + case MPC7450: + case MPC7455: + case MPC7457: + cpu_print_speed(); + printf("\n"); + cpu_config_l2cr(cpuid, vers); + break; + + default: + printf("\n"); + break; + } + + printf("cpu%d: HID0 %b\n", cpuid, hid0, bitmask); +} + +void +cpu_print_speed(void) +{ + uint64_t cps; + + mtspr(SPR_MMCR0, SPR_MMCR0_FC); + mtspr(SPR_PMC1, 0); + mtspr(SPR_MMCR0, SPR_MMCR0_PMC1SEL(PMCN_CYCLES)); + DELAY(100000); + cps = (mfspr(SPR_PMC1) * 10) + 4999; + printf(", %lld.%02lld MHz", cps / 1000000, (cps / 10000) % 100); +} + +void +cpu_config_l2cr(u_int cpuid, uint16_t vers) +{ + u_int l2cr, x, msr; + + l2cr = mfspr(SPR_L2CR); + + /* + * For MP systems, the firmware may only configure the L2 cache + * on the first CPU. In this case, assume that the other CPUs + * should use the same value for L2CR. + */ + if ((l2cr & L2CR_L2E) != 0 && l2cr_config == 0) { + l2cr_config = l2cr; + } + + /* + * Configure L2 cache if not enabled. + */ + if ((l2cr & L2CR_L2E) == 0 && l2cr_config != 0) { + l2cr = l2cr_config; + + /* Disable interrupts and set the cache config bits. */ + msr = mfmsr(); + mtmsr(msr & ~PSL_EE); +#ifdef ALTIVEC + if (cpu_altivec) + __asm __volatile("dssall"); +#endif + __asm __volatile("sync"); + mtspr(SPR_L2CR, l2cr & ~L2CR_L2E); + __asm __volatile("sync"); + + /* Wait for L2 clock to be stable (640 L2 clocks). */ + DELAY(100); + + /* Invalidate all L2 contents. */ + mtspr(SPR_L2CR, l2cr | L2CR_L2I); + do { + x = mfspr(SPR_L2CR); + } while (x & L2CR_L2IP); + + /* Enable L2 cache. */ + l2cr |= L2CR_L2E; + mtspr(SPR_L2CR, l2cr); + mtmsr(msr); + } + + if (!bootverbose) + return; + + printf("cpu%d: ", cpuid); + + if (l2cr & L2CR_L2E) { + if (vers == MPC7450 || + vers == MPC7455 || + vers == MPC7457) { + u_int l3cr; + + printf("256KB L2 cache"); + + l3cr = mfspr(SPR_L3CR); + if (l3cr & L3CR_L3E) + printf(", %cMB L3 backside cache", + l3cr & L3CR_L3SIZ ? '2' : '1'); + printf("\n"); + return; + } + if (vers == IBM750FX) { + printf("512KB L2 cache\n"); + return; + } + switch (l2cr & L2CR_L2SIZ) { + case L2SIZ_256K: + printf("256KB"); + break; + case L2SIZ_512K: + printf("512KB"); + break; + case L2SIZ_1M: + printf("1MB"); + break; + default: + printf("unknown size"); + } + if (l2cr & L2CR_L2WT) { + printf(" write-through"); + } else { + printf(" write-back"); + } + switch (l2cr & L2CR_L2RAM) { + case L2RAM_FLOWTHRU_BURST: + printf(" flow-through synchronous burst SRAM"); + break; + case L2RAM_PIPELINE_BURST: + printf(" pipelined synchronous burst SRAM"); + break; + case L2RAM_PIPELINE_LATE: + printf(" pipelined synchronous late-write SRAM"); + break; + default: + printf(" unknown type"); + } + + if (l2cr & L2CR_L2PE) + printf(" with parity"); + printf(" backside cache"); + } else + printf("L2 cache not enabled"); + + printf("\n"); +} diff --git a/sys/powerpc/powerpc/db_disasm.c b/sys/powerpc/powerpc/db_disasm.c new file mode 100644 index 000000000000..67f90d254401 --- /dev/null +++ b/sys/powerpc/powerpc/db_disasm.c @@ -0,0 +1,962 @@ +/* $FreeBSD$ */ +/* $NetBSD: db_disasm.c,v 1.12 2002/01/05 22:07:26 jhawk Exp $ */ +/* $OpenBSD: db_disasm.c,v 1.2 1996/12/28 06:21:48 rahnds Exp $ */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/systm.h> + +#include <machine/db_machdep.h> +#include <machine/trap.h> + +#include <ddb/ddb.h> +#include <ddb/db_access.h> +#include <ddb/db_sym.h> +#include <ddb/db_variables.h> +#include <ddb/db_output.h> + +enum function_mask { + Op_A = 0x00000001, + Op_B = 0x00000002, + Op_BI = 0x00000004, + Op_BO = 0x00000008, + Op_CRM = 0x00000010, + Op_D = 0x00000020, /* yes, Op_S and Op_D are the same */ + Op_S = 0x00000020, + Op_FM = 0x00000040, + Op_IMM = 0x00000080, + Op_LK = 0x00000100, + Op_Rc = 0x00000200, + Op_AA = Op_LK | Op_Rc, /* kludge (reduce Op_s) */ + Op_LKM = Op_AA, + Op_RcM = Op_AA, + Op_OE = 0x00000400, + Op_SR = 0x00000800, + Op_TO = 0x00001000, + Op_sign = 0x00002000, + Op_const = 0x00004000, + Op_SIMM = Op_const | Op_sign, + Op_UIMM = Op_const, + Op_d = Op_const | Op_sign, + Op_crbA = 0x00008000, + Op_crbB = 0x00010000, + Op_WS = Op_crbB, /* kludge, same field as crbB */ + Op_crbD = 0x00020000, + Op_crfD = 0x00040000, + Op_crfS = 0x00080000, + Op_ds = 0x00100000, + Op_me = 0x00200000, + Op_spr = 0x00400000, + Op_dcr = Op_spr, /* out of bits - cheat with Op_spr */ + Op_tbr = 0x00800000, + + Op_L = 0x01000000, + Op_BD = 0x02000000, + Op_LI = 0x04000000, + Op_C = 0x08000000, + + Op_NB = 0x10000000, + + Op_sh_mb_sh = 0x20000000, + Op_sh = 0x40000000, + Op_SH = Op_sh | Op_sh_mb_sh, + Op_mb = 0x80000000, + Op_MB = Op_mb | Op_sh_mb_sh, + Op_ME = Op_MB, + +}; + +struct opcode { + char *name; + u_int32_t mask; + u_int32_t code; + enum function_mask func; +}; + +typedef u_int32_t instr_t; +typedef void (op_class_func) (instr_t, vm_offset_t); + +u_int32_t extract_field(u_int32_t value, u_int32_t base, u_int32_t width); +void disasm_fields(const struct opcode *popcode, instr_t instr, vm_offset_t loc, + char *disasm_str); +void dis_ppc(const struct opcode *opcodeset, instr_t instr, vm_offset_t loc); + +op_class_func op_ill, op_base; +op_class_func op_cl_x13, op_cl_x1e, op_cl_x1f; +op_class_func op_cl_x3a, op_cl_x3b; +op_class_func op_cl_x3e, op_cl_x3f; + +op_class_func *opcodes_base[] = { +/*x00*/ op_ill, op_ill, op_base, op_ill, +/*x04*/ op_ill, op_ill, op_ill, op_base, +/*x08*/ op_base, op_base, op_ill, op_base, +/*x0C*/ op_base, op_base, op_base/*XXX*/, op_base/*XXX*/, +/*x10*/ op_base, op_base, op_base, op_cl_x13, +/*x14*/ op_base, op_base, op_ill, op_base, +/*x18*/ op_base, op_base, op_base, op_base, +/*x1C*/ op_base, op_base, op_cl_x1e, op_cl_x1f, +/*x20*/ op_base, op_base, op_base, op_base, +/*x24*/ op_base, op_base, op_base, op_base, +/*x28*/ op_base, op_base, op_base, op_base, +/*x2C*/ op_base, op_base, op_base, op_base, +/*x30*/ op_base, op_base, op_base, op_base, +/*x34*/ op_base, op_base, op_base, op_base, +/*x38*/ op_ill, op_ill, op_cl_x3a, op_cl_x3b, +/*x3C*/ op_ill, op_ill, op_cl_x3e, op_cl_x3f +}; + + +/* This table could be modified to make significant the "reserved" fields + * of the opcodes, But I didn't feel like it when typing in the table, + * I would recommend that this table be looked over for errors, + * This was derived from the table in Appendix A.2 of (Mot part # MPCFPE/AD) + * PowerPC Microprocessor Family: The Programming Environments + */ + +const struct opcode opcodes[] = { + { "tdi", 0xfc000000, 0x08000000, Op_TO | Op_A | Op_SIMM }, + { "twi", 0xfc000000, 0x0c000000, Op_TO | Op_A | Op_SIMM }, + { "mulli", 0xfc000000, 0x1c000000, Op_D | Op_A | Op_SIMM }, + { "subfic", 0xfc000000, 0x20000000, Op_D | Op_A | Op_SIMM }, + { "cmpli", 0xfc000000, 0x28000000, Op_crfD | Op_L | Op_A | Op_SIMM }, + { "cmpi", 0xfc000000, 0x2c000000, Op_crfD | Op_L | Op_A | Op_SIMM }, + { "addic", 0xfc000000, 0x30000000, Op_D | Op_A | Op_SIMM }, + { "addic.", 0xfc000000, 0x34000000, Op_D | Op_A | Op_SIMM }, + { "addi", 0xfc000000, 0x38000000, Op_D | Op_A | Op_SIMM }, + { "addis", 0xfc000000, 0x3c000000, Op_D | Op_A | Op_SIMM }, + { "bc", 0xfc000000, 0x40000000, Op_BO | Op_BI | Op_BD | Op_AA | Op_LK }, + { "sc", 0xffffffff, 0x44000002, Op_BO | Op_BI | Op_BD | Op_AA | Op_LK }, + { "b", 0xfc000000, 0x48000000, Op_LI | Op_AA | Op_LK }, + + { "rlwimi", 0xfc000000, 0x50000000, Op_S | Op_A | Op_SH | Op_MB | Op_ME | Op_Rc }, + { "rlwinm", 0xfc000000, 0x54000000, Op_S | Op_A | Op_SH | Op_MB | Op_ME | Op_Rc }, + { "rlwnm", 0xfc000000, 0x5c000000, Op_S | Op_A | Op_SH | Op_MB | Op_ME | Op_Rc }, + + { "ori", 0xfc000000, 0x60000000, Op_S | Op_A | Op_UIMM }, + { "oris", 0xfc000000, 0x64000000, Op_S | Op_A | Op_UIMM }, + { "xori", 0xfc000000, 0x68000000, Op_S | Op_A | Op_UIMM }, + { "xoris", 0xfc000000, 0x6c000000, Op_S | Op_A | Op_UIMM }, + + { "andi.", 0xfc000000, 0x70000000, Op_S | Op_A | Op_UIMM }, + { "andis.", 0xfc000000, 0x74000000, Op_S | Op_A | Op_UIMM }, + + { "lwz", 0xfc000000, 0x80000000, Op_D | Op_A | Op_d }, + { "lwzu", 0xfc000000, 0x84000000, Op_D | Op_A | Op_d }, + { "lbz", 0xfc000000, 0x88000000, Op_D | Op_A | Op_d }, + { "lbzu", 0xfc000000, 0x8c000000, Op_D | Op_A | Op_d }, + { "stw", 0xfc000000, 0x90000000, Op_S | Op_A | Op_d }, + { "stwu", 0xfc000000, 0x94000000, Op_S | Op_A | Op_d }, + { "stb", 0xfc000000, 0x98000000, Op_S | Op_A | Op_d }, + { "stbu", 0xfc000000, 0x9c000000, Op_S | Op_A | Op_d }, + + { "lhz", 0xfc000000, 0xa0000000, Op_D | Op_A | Op_d }, + { "lhzu", 0xfc000000, 0xa4000000, Op_D | Op_A | Op_d }, + { "lha", 0xfc000000, 0xa8000000, Op_D | Op_A | Op_d }, + { "lhau", 0xfc000000, 0xac000000, Op_D | Op_A | Op_d }, + { "sth", 0xfc000000, 0xb0000000, Op_S | Op_A | Op_d }, + { "sthu", 0xfc000000, 0xb4000000, Op_S | Op_A | Op_d }, + { "lmw", 0xfc000000, 0xb8000000, Op_D | Op_A | Op_d }, + { "stmw", 0xfc000000, 0xbc000000, Op_S | Op_A | Op_d }, + + { "lfs", 0xfc000000, 0xc0000000, Op_D | Op_A | Op_d }, + { "lfsu", 0xfc000000, 0xc4000000, Op_D | Op_A | Op_d }, + { "lfd", 0xfc000000, 0xc8000000, Op_D | Op_A | Op_d }, + { "lfdu", 0xfc000000, 0xcc000000, Op_D | Op_A | Op_d }, + + { "stfs", 0xfc000000, 0xd0000000, Op_S | Op_A | Op_d }, + { "stfsu", 0xfc000000, 0xd4000000, Op_S | Op_A | Op_d }, + { "stfd", 0xfc000000, 0xd8000000, Op_S | Op_A | Op_d }, + { "stfdu", 0xfc000000, 0xdc000000, Op_S | Op_A | Op_d }, + { "", 0x0, 0x0, 0 } + +}; +/* 13 * 4 = 4c */ +const struct opcode opcodes_13[] = { +/* 0x13 << 2 */ + { "mcrf", 0xfc0007fe, 0x4c000000, Op_crfD | Op_crfS }, + { "bclr", 0xfc0007fe, 0x4c000020, Op_BO | Op_BI | Op_LK }, + { "crnor", 0xfc0007fe, 0x4c000042, Op_crbD | Op_crbA | Op_crbB }, + { "rfi", 0xfc0007fe, 0x4c000064, 0 }, + { "crandc", 0xfc0007fe, 0x4c000102, Op_BO | Op_BI | Op_LK }, + { "isync", 0xfc0007fe, 0x4c00012c, 0 }, + { "crxor", 0xfc0007fe, 0x4c000182, Op_crbD | Op_crbA | Op_crbB }, + { "crnand", 0xfc0007fe, 0x4c0001c2, Op_crbD | Op_crbA | Op_crbB }, + { "crand", 0xfc0007fe, 0x4c000202, Op_crbD | Op_crbA | Op_crbB }, + { "creqv", 0xfc0007fe, 0x4c000242, Op_crbD | Op_crbA | Op_crbB }, + { "crorc", 0xfc0007fe, 0x4c000342, Op_crbD | Op_crbA | Op_crbB }, + { "cror", 0xfc0007fe, 0x4c000382, Op_crbD | Op_crbA | Op_crbB }, + { "bcctr", 0xfc0007fe, 0x4c000420, Op_BO | Op_BI | Op_LK }, + { "", 0x0, 0x0, 0 } +}; + +/* 1e * 4 = 78 */ +const struct opcode opcodes_1e[] = { + { "rldicl", 0xfc00001c, 0x78000000, Op_S | Op_A | Op_sh | Op_mb | Op_Rc }, + { "rldicr", 0xfc00001c, 0x78000004, Op_S | Op_A | Op_sh | Op_me | Op_Rc }, + { "rldic", 0xfc00001c, 0x78000008, Op_S | Op_A | Op_sh | Op_mb | Op_Rc }, + { "rldimi", 0xfc00001c, 0x7800000c, Op_S | Op_A | Op_sh | Op_mb | Op_Rc }, + { "rldcl", 0xfc00003e, 0x78000010, Op_S | Op_A | Op_B | Op_mb | Op_Rc }, + { "rldcr", 0xfc00003e, 0x78000012, Op_S | Op_A | Op_B | Op_me | Op_Rc }, + { "", 0x0, 0x0, 0 } +}; + +/* 1f * 4 = 7c */ +const struct opcode opcodes_1f[] = { +/* 1f << 2 */ + { "cmp", 0xfc0007fe, 0x7c000000, Op_S | Op_A | Op_B | Op_me | Op_Rc }, + { "tw", 0xfc0007fe, 0x7c000008, Op_TO | Op_A | Op_B }, + { "subfc", 0xfc0003fe, 0x7c000010, Op_D | Op_A | Op_B | Op_OE | Op_Rc }, + { "mulhdu", 0xfc0007fe, 0x7c000012, Op_D | Op_A | Op_B | Op_Rc }, + { "addc", 0xfc0003fe, 0x7c000014, Op_D | Op_A | Op_B | Op_OE | Op_Rc }, + { "mulhwu", 0xfc0007fe, 0x7c000016, Op_D | Op_A | Op_B | Op_Rc }, + + { "mfcr", 0xfc0007fe, 0x7c000026, Op_D }, + { "lwarx", 0xfc0007fe, 0x7c000028, Op_D | Op_A | Op_B }, + { "ldx", 0xfc0007fe, 0x7c00002a, Op_D | Op_A | Op_B }, + { "lwzx", 0xfc0007fe, 0x7c00002e, Op_D | Op_A | Op_B }, + { "slw", 0xfc0007fe, 0x7c000030, Op_D | Op_A | Op_B | Op_Rc }, + { "cntlzw", 0xfc0007fe, 0x7c000034, Op_D | Op_A | Op_Rc }, + { "sld", 0xfc0007fe, 0x7c000036, Op_D | Op_A | Op_B | Op_Rc }, + { "and", 0xfc0007fe, 0x7c000038, Op_D | Op_A | Op_B | Op_Rc }, + { "cmpl", 0xfc0007fe, 0x7c000040, Op_crfD | Op_L | Op_A | Op_B }, + { "subf", 0xfc0003fe, 0x7c000050, Op_D | Op_A | Op_B | Op_OE | Op_Rc }, + { "ldux", 0xfc0007fe, 0x7c00006a, Op_D | Op_A | Op_B }, + { "dcbst", 0xfc0007fe, 0x7c00006c, Op_A | Op_B }, + { "lwzux", 0xfc0007fe, 0x7c00006e, Op_D | Op_A | Op_B }, + { "cntlzd", 0xfc0007fe, 0x7c000074, Op_S | Op_A | Op_Rc }, + { "andc", 0xfc0007fe, 0x7c000078, Op_S | Op_A | Op_B | Op_Rc }, + { "td", 0xfc0007fe, 0x7c000088, Op_TO | Op_A | Op_B }, + { "mulhd", 0xfc0007fe, 0x7c000092, Op_D | Op_A | Op_B | Op_Rc }, + { "mulhw", 0xfc0007fe, 0x7c000096, Op_D | Op_A | Op_B | Op_Rc }, + { "mfmsr", 0xfc0007fe, 0x7c0000a6, Op_D }, + { "ldarx", 0xfc0007fe, 0x7c0000a8, Op_D | Op_A | Op_B }, + { "dcbf", 0xfc0007fe, 0x7c0000ac, Op_A | Op_B }, + { "lbzx", 0xfc0007fe, 0x7c0000ae, Op_D | Op_A | Op_B }, + { "neg", 0xfc0003fe, 0x7c0000d0, Op_D | Op_A | Op_OE | Op_Rc }, + { "lbzux", 0xfc0007fe, 0x7c0000ee, Op_D | Op_A | Op_B }, + { "nor", 0xfc0007fe, 0x7c0000f8, Op_S | Op_A | Op_B | Op_Rc }, + { "wrtee", 0xfc0003ff, 0x7c000106, Op_S }, + { "subfe", 0xfc0003fe, 0x7c000110, Op_D | Op_A | Op_B | Op_OE | Op_Rc }, + { "adde", 0xfc0003fe, 0x7c000114, Op_D | Op_A | Op_B | Op_OE | Op_Rc }, + { "mtcrf", 0xfc0007fe, 0x7c000120, Op_S | Op_CRM }, + { "mtmsr", 0xfc0007fe, 0x7c000124, Op_S }, + { "stdx", 0xfc0007fe, 0x7c00012a, Op_S | Op_A | Op_B }, + { "stwcx.", 0xfc0007ff, 0x7c00012d, Op_S | Op_A | Op_B }, + { "stwx", 0xfc0007fe, 0x7c00012e, Op_S | Op_A | Op_B }, + { "wrteei", 0xfc0003fe, 0x7c000146 }, /* XXX: out of flags! */ + { "stdux", 0xfc0007fe, 0x7c00016a, Op_S | Op_A | Op_B }, + { "stwux", 0xfc0007fe, 0x7c00016e, Op_S | Op_A | Op_B }, + { "subfze", 0xfc0003fe, 0x7c000190, Op_D | Op_A | Op_OE | Op_Rc }, + { "addze", 0xfc0003fe, 0x7c000194, Op_D | Op_A | Op_OE | Op_Rc }, + { "mtsr", 0xfc0007fe, 0x7c0001a4, Op_S | Op_SR }, + { "stdcx.", 0xfc0007ff, 0x7c0001ad, Op_S | Op_A | Op_B }, + { "stbx", 0xfc0007fe, 0x7c0001ae, Op_S | Op_A | Op_B }, + { "subfme", 0xfc0003fe, 0x7c0001d0, Op_D | Op_A | Op_OE | Op_Rc }, + { "mulld", 0xfc0003fe, 0x7c0001d2, Op_D | Op_A | Op_B | Op_OE | Op_Rc }, + { "addme", 0xfc0003fe, 0x7c0001d4, Op_D | Op_A | Op_OE | Op_Rc }, + { "mullw", 0xfc0003fe, 0x7c0001d6, Op_D | Op_A | Op_B | Op_OE | Op_Rc }, + { "mtsrin", 0xfc0007fe, 0x7c0001e4, Op_S | Op_B }, + { "dcbtst", 0xfc0007fe, 0x7c0001ec, Op_A | Op_B }, + { "stbux", 0xfc0007fe, 0x7c0001ee, Op_S | Op_A | Op_B }, + { "add", 0xfc0003fe, 0x7c000214, Op_D | Op_A | Op_B | Op_OE | Op_Rc }, + { "dcbt", 0xfc0007fe, 0x7c00022c, Op_A | Op_B }, + { "lhzx", 0xfc0007ff, 0x7c00022e, Op_D | Op_A | Op_B }, + { "eqv", 0xfc0007fe, 0x7c000238, Op_S | Op_A | Op_B | Op_Rc }, + { "tlbie", 0xfc0007fe, 0x7c000264, Op_B }, + { "eciwx", 0xfc0007fe, 0x7c00026c, Op_D | Op_A | Op_B }, + { "lhzux", 0xfc0007fe, 0x7c00026e, Op_D | Op_A | Op_B }, + { "xor", 0xfc0007fe, 0x7c000278, Op_S | Op_A | Op_B | Op_Rc }, + { "mfdcr", 0xfc0007fe, 0x7c000286, Op_D | Op_dcr }, + { "mfspr", 0xfc0007fe, 0x7c0002a6, Op_D | Op_spr }, + { "lwax", 0xfc0007fe, 0x7c0002aa, Op_D | Op_A | Op_B }, + { "lhax", 0xfc0007fe, 0x7c0002ae, Op_D | Op_A | Op_B }, + { "tlbia", 0xfc0007fe, 0x7c0002e4, 0 }, + { "mftb", 0xfc0007fe, 0x7c0002e6, Op_D | Op_tbr }, + { "lwaux", 0xfc0007fe, 0x7c0002ea, Op_D | Op_A | Op_B }, + { "lhaux", 0xfc0007fe, 0x7c0002ee, Op_D | Op_A | Op_B }, + { "sthx", 0xfc0007fe, 0x7c00032e, Op_S | Op_A | Op_B }, + { "orc", 0xfc0007fe, 0x7c000338, Op_S | Op_A | Op_B | Op_Rc }, + { "ecowx", 0xfc0007fe, 0x7c00036c, Op_S | Op_A | Op_B | Op_Rc }, + { "slbie", 0xfc0007fc, 0x7c000364, Op_B }, + { "sthux", 0xfc0007fe, 0x7c00036e, Op_S | Op_A | Op_B }, + { "or", 0xfc0007fe, 0x7c000378, Op_S | Op_A | Op_B | Op_Rc }, + { "mtdcr", 0xfc0007fe, 0x7c000386, Op_S | Op_dcr }, + { "divdu", 0xfc0003fe, 0x7c000392, Op_D | Op_A | Op_B | Op_OE | Op_Rc }, + { "divwu", 0xfc0003fe, 0x7c000396, Op_D | Op_A | Op_B | Op_OE | Op_Rc }, + { "mtspr", 0xfc0007fe, 0x7c0003a6, Op_S | Op_spr }, + { "dcbi", 0xfc0007fe, 0x7c0003ac, Op_A | Op_B }, + { "nand", 0xfc0007fe, 0x7c0003b8, Op_S | Op_A | Op_B | Op_Rc }, + { "dcread", 0xfc0007fe, 0x7c0003cc, Op_D | Op_A | Op_B }, + { "divd", 0xfc0003fe, 0x7c0003d2, Op_S | Op_A | Op_B | Op_OE | Op_Rc }, + { "divw", 0xfc0003fe, 0x7c0003d6, Op_S | Op_A | Op_B | Op_OE | Op_Rc }, + { "slbia", 0xfc0003fe, 0x7c0003e4, Op_S | Op_A | Op_B | Op_OE | Op_Rc }, + { "mcrxr", 0xfc0007fe, 0x7c000400, Op_crfD }, + { "lswx", 0xfc0007fe, 0x7c00042a, Op_D | Op_A | Op_B }, + { "lwbrx", 0xfc0007fe, 0x7c00042c, Op_D | Op_A | Op_B }, + { "lfsx", 0xfc0007fe, 0x7c00042e, Op_D | Op_A | Op_B }, + { "srw", 0xfc0007fe, 0x7c000430, Op_S | Op_A | Op_B | Op_Rc }, + { "srd", 0xfc0007fe, 0x7c000436, Op_S | Op_A | Op_B | Op_Rc }, + { "tlbsync", 0xfc0007fe, 0x7c00046c, 0 }, + { "lfsux", 0xfc0007fe, 0x7c00046e, Op_D | Op_A | Op_B }, + { "mfsr", 0xfc0007fe, 0x7c0004a6, Op_D | Op_SR }, + { "lswi", 0xfc0007fe, 0x7c0004aa, Op_D | Op_A | Op_NB }, + { "sync", 0xfc0007fe, 0x7c0004ac, 0 }, + { "lfdx", 0xfc0007fe, 0x7c0004ae, Op_D | Op_A | Op_B }, + { "lfdux", 0xfc0007fe, 0x7c0004ee, Op_D | Op_A | Op_B }, + { "mfsrin", 0xfc0007fe, 0x7c000526, Op_D | Op_B }, + { "stswx", 0xfc0007fe, 0x7c00052a, Op_S | Op_A | Op_B }, + { "stwbrx", 0xfc0007fe, 0x7c00052c, Op_S | Op_A | Op_B }, + { "stfsx", 0xfc0007fe, 0x7c00052e, Op_S | Op_A | Op_B }, + { "stfsux", 0xfc0007fe, 0x7c00056e, Op_S | Op_A | Op_B }, + { "stswi", 0xfc0007fe, 0x7c0005aa, Op_S | Op_A | Op_NB }, + { "stfdx", 0xfc0007fe, 0x7c0005ae, Op_S | Op_A | Op_B }, + { "stfdux", 0xfc0007fe, 0x7c0005ee, Op_S | Op_A | Op_B }, + { "lhbrx", 0xfc0007fe, 0x7c00062c, Op_D | Op_A | Op_B }, + { "sraw", 0xfc0007fe, 0x7c000630, Op_S | Op_A | Op_B }, + { "srad", 0xfc0007fe, 0x7c000634, Op_S | Op_A | Op_B | Op_Rc }, + { "srawi", 0xfc0007fe, 0x7c000670, Op_S | Op_A | Op_B | Op_Rc }, + { "sradi", 0xfc0007fc, 0x7c000674, Op_S | Op_A | Op_sh }, + { "eieio", 0xfc0007fe, 0x7c0006ac, 0 }, + { "tlbsx", 0xfc0007fe, 0x7c000724, Op_S | Op_A | Op_B | Op_Rc }, + { "sthbrx", 0xfc0007fe, 0x7c00072c, Op_S | Op_A | Op_B }, + { "extsh", 0xfc0007fe, 0x7c000734, Op_S | Op_A | Op_B | Op_Rc }, + { "tlbre", 0xfc0007fe, 0x7c000764, Op_D | Op_A | Op_WS }, + { "extsb", 0xfc0007fe, 0x7c000774, Op_S | Op_A | Op_Rc }, + { "icbi", 0xfc0007fe, 0x7c0007ac, Op_A | Op_B }, + { "tlbwe", 0xfc0007fe, 0x7c0007a4, Op_S | Op_A | Op_WS }, + { "stfiwx", 0xfc0007fe, 0x7c0007ae, Op_S | Op_A | Op_B }, + { "extsw", 0xfc0007fe, 0x7c0007b4, Op_S | Op_A | Op_Rc }, + { "dcbz", 0xfc0007fe, 0x7c0007ec, Op_A | Op_B }, + { "", 0x0, 0x0, 0 } +}; + +/* 3a * 4 = e8 */ +const struct opcode opcodes_3a[] = { + { "ld", 0xfc000003, 0xe8000000, Op_D | Op_A | Op_ds }, + { "ldu", 0xfc000003, 0xe8000001, Op_D | Op_A | Op_ds }, + { "lwa", 0xfc000003, 0xe8000002, Op_D | Op_A | Op_ds }, + { "", 0x0, 0x0, 0 } +}; +/* 3b * 4 = ec */ +const struct opcode opcodes_3b[] = { + { "fdivs", 0xfc00003e, 0xec000024, Op_D | Op_A | Op_B | Op_Rc }, + { "fsubs", 0xfc00003e, 0xec000028, Op_D | Op_A | Op_B | Op_Rc }, + + { "fadds", 0xfc00003e, 0xec00002a, Op_D | Op_A | Op_B | Op_Rc }, + { "fsqrts", 0xfc00003e, 0xec00002c, Op_D | Op_B | Op_Rc }, + { "fres", 0xfc00003e, 0xec000030, Op_D | Op_B | Op_Rc }, + { "fmuls", 0xfc00003e, 0xec000032, Op_D | Op_A | Op_C | Op_Rc }, + { "fmsubs", 0xfc00003e, 0xec000038, Op_D | Op_A | Op_B | Op_C | Op_Rc }, + { "fmadds", 0xfc00003e, 0xec00003a, Op_D | Op_A | Op_B | Op_C | Op_Rc }, + { "fnmsubs", 0xfc00003e, 0xec00003c, Op_D | Op_A | Op_B | Op_C | Op_Rc }, + { "fnmadds", 0xfc00003e, 0xec00003e, Op_D | Op_A | Op_B | Op_C | Op_Rc }, + { "", 0x0, 0x0, 0 } +}; +/* 3e * 4 = f8 */ +const struct opcode opcodes_3e[] = { + { "std", 0xfc000003, 0xf8000000, Op_S | Op_A | Op_ds }, + { "stdu", 0xfc000003, 0xf8000001, Op_S | Op_A | Op_ds }, + { "", 0x0, 0x0, 0 } +}; + +/* 3f * 4 = fc */ +const struct opcode opcodes_3f[] = { + { "fcmpu", 0xfc0007fe, 0xfc000000, Op_crfD | Op_A | Op_B }, + { "frsp", 0xfc0007fe, 0xfc000018, Op_D | Op_B | Op_Rc }, + { "fctiw", 0xfc0007fe, 0xfc00001c, Op_D | Op_B | Op_Rc }, + { "fctiwz", 0xfc0007fe, 0xfc00001e, Op_D | Op_B | Op_Rc }, + + { "fdiv", 0xfc00003e, 0xfc000024, Op_D | Op_A | Op_B | Op_Rc }, + { "fsub", 0xfc00003e, 0xfc000028, Op_D | Op_A | Op_B | Op_Rc }, + { "fadd", 0xfc00003e, 0xfc00002a, Op_D | Op_A | Op_B | Op_Rc }, + { "fsqrt", 0xfc00003e, 0xfc00002c, Op_D | Op_B | Op_Rc }, + { "fsel", 0xfc00003e, 0xfc00002e, Op_D | Op_A | Op_B | Op_C | Op_Rc }, + { "fmul", 0xfc00003e, 0xfc000032, Op_D | Op_A | Op_C | Op_Rc }, + { "frsqrte", 0xfc00003e, 0xfc000034, Op_D | Op_B | Op_Rc }, + { "fmsub", 0xfc00003e, 0xfc000038, Op_D | Op_A | Op_B | Op_C | Op_Rc }, + { "fmadd", 0xfc00003e, 0xfc00003a, Op_D | Op_A | Op_B | Op_C | Op_Rc }, + { "fnmsub", 0xfc00003e, 0xfc00003c, Op_D | Op_A | Op_B | Op_C | Op_Rc }, + { "fnmadd", 0xfc00003e, 0xfc00003e, Op_D | Op_A | Op_B | Op_C | Op_Rc }, + + { "fcmpo", 0xfc0007fe, 0xfc000040, Op_crfD | Op_A | Op_B }, + { "mtfsb1", 0xfc0007fe, 0xfc00004c, Op_crfD | Op_Rc }, + { "fneg", 0xfc0007fe, 0xfc000050, Op_D | Op_B | Op_Rc }, + { "mcrfs", 0xfc0007fe, 0xfc000080, Op_D | Op_B | Op_Rc }, + { "mtfsb0", 0xfc0007fe, 0xfc00008c, Op_crfD | Op_Rc }, + { "fmr", 0xfc0007fe, 0xfc000090, Op_D | Op_B | Op_Rc }, + { "mtfsfi", 0xfc0007fe, 0xfc00010c, Op_crfD | Op_IMM | Op_Rc }, + + { "fnabs", 0xfc0007fe, 0xfc000110, Op_D | Op_B | Op_Rc }, + { "fabs", 0xfc0007fe, 0xfc000210, Op_D | Op_B | Op_Rc }, + { "mffs", 0xfc0007fe, 0xfc00048e, Op_D | Op_B | Op_Rc }, + { "mtfsf", 0xfc0007fe, 0xfc00058e, Op_FM | Op_B | Op_Rc }, + { "fctid", 0xfc0007fe, 0xfc00065c, Op_D | Op_B | Op_Rc }, + { "fctidz", 0xfc0007fe, 0xfc00065e, Op_D | Op_B | Op_Rc }, + { "fcfid", 0xfc0007fe, 0xfc00069c, Op_D | Op_B | Op_Rc }, + { "", 0x0, 0x0, 0 } +}; + + +struct specialreg { + int reg; + char *name; +}; + +const struct specialreg sprregs[] = { + { 0x001, "xer" }, + { 0x008, "lr" }, + { 0x009, "ctr" }, + { 0x012, "dsisr" }, + { 0x013, "dar" }, + { 0x016, "dec" }, + { 0x019, "sdr1" }, + { 0x01a, "srr0" }, + { 0x01b, "srr1" }, + { 0x100, "usprg0" }, + { 0x110, "sprg0" }, + { 0x111, "sprg1" }, + { 0x112, "sprg2" }, + { 0x113, "sprg3" }, + { 0x114, "sprg4" }, + { 0x115, "sprg5" }, + { 0x116, "sprg6" }, + { 0x117, "sprg7" }, + { 0x118, "asr" }, + { 0x11a, "aer" }, + { 0x11c, "tbl" }, + { 0x11d, "tbu" }, + { 0x11f, "pvr" }, + { 0x210, "ibat0u" }, + { 0x211, "ibat0l" }, + { 0x212, "ibat1u" }, + { 0x213, "ibat1l" }, + { 0x214, "ibat2u" }, + { 0x215, "ibat2l" }, + { 0x216, "ibat3u" }, + { 0x217, "ibat3l" }, + { 0x218, "dbat0u" }, + { 0x219, "dbat0l" }, + { 0x21a, "dbat1u" }, + { 0x21b, "dbat1l" }, + { 0x21c, "dbat2u" }, + { 0x21d, "dbat2l" }, + { 0x21e, "dbat3u" }, + { 0x21f, "dbat3l" }, + { 0x3b0, "zpr" }, + { 0x3b1, "pid" }, + { 0x3b3, "ccr0" }, + { 0x3b4, "iac3" }, + { 0x3b5, "iac4" }, + { 0x3b6, "dvc1" }, + { 0x3b7, "dvc2" }, + { 0x3b9, "sgr" }, + { 0x3ba, "dcwr" }, + { 0x3bb, "sler" }, + { 0x3bc, "su0r" }, + { 0x3bd, "dbcr1" }, + { 0x3d3, "icdbdr" }, + { 0x3d4, "esr" }, + { 0x3d5, "dear" }, + { 0x3d6, "evpr" }, + { 0x3d8, "tsr" }, + { 0x3da, "tcr" }, + { 0x3db, "pit" }, + { 0x3de, "srr2" }, + { 0x3df, "srr3" }, + { 0x3f0, "dbsr" }, + { 0x3f2, "dbcr0" }, + { 0x3f4, "iac1" }, + { 0x3f5, "iac2" }, + { 0x3f6, "dac1" }, + { 0x3f7, "dac2" }, + { 0x3f9, "l2cr" }, + { 0x3fa, "dccr" }, + { 0x3fb, "iccr" }, + { 0x3ff, "pir" }, + { 0, NULL } +}; + +const struct specialreg dcrregs[] = { + { 0x010, "sdram0_cfgaddr" }, + { 0x011, "sdram0_cfgdata" }, + { 0x012, "ebc0_cfgaddr" }, + { 0x013, "ebc0_cfgdata" }, + { 0x014, "dcp0_cfgaddr" }, + { 0x015, "dcp0_cfgdata" }, + { 0x018, "ocm0_isarc" }, + { 0x019, "ocm0_iscntl" }, + { 0x01a, "ocm0_dsarc" }, + { 0x01b, "ocm0_dscntl" }, + { 0x084, "plb0_besr" }, + { 0x086, "plb0_bear" }, + { 0x087, "plb0_acr" }, + { 0x0a0, "pob0_besr0" }, + { 0x0a2, "pob0_bear" }, + { 0x0a4, "pob0_besr1" }, + { 0x0b0, "cpc0_pllmr" }, + { 0x0b1, "cpc0_cr0" }, + { 0x0b2, "cpc0_cr1" }, + { 0x0b4, "cpc0_psr" }, + { 0x0b5, "cpc0_jtagid" }, + { 0x0b8, "cpc0_sr" }, + { 0x0b9, "cpc0_er" }, + { 0x0ba, "cpc0_fr" }, + { 0x0c0, "uic0_sr" }, + { 0x0c2, "uic0_er" }, + { 0x0c3, "uic0_cr" }, + { 0x0c4, "uic0_pr" }, + { 0x0c5, "uic0_tr" }, + { 0x0c6, "uic0_msr" }, + { 0x0c7, "uic0_vr" }, + { 0x0c8, "uic0_vcr" }, + { 0x100, "dma0_cr0" }, + { 0x101, "dma0_ct0" }, + { 0x102, "dma0_da0" }, + { 0x103, "dma0_sa0" }, + { 0x104, "dma0_sg0" }, + { 0x108, "dma0_cr1" }, + { 0x109, "dma0_ct1" }, + { 0x10a, "dma0_da1" }, + { 0x10b, "dma0_sa1" }, + { 0x10c, "dma0_sg1" }, + { 0x110, "dma0_cr2" }, + { 0x111, "dma0_ct2" }, + { 0x112, "dma0_da2" }, + { 0x113, "dma0_sa2" }, + { 0x114, "dma0_sg2" }, + { 0x118, "dma0_cr3" }, + { 0x119, "dma0_ct3" }, + { 0x11a, "dma0_da3" }, + { 0x11b, "dma0_sa3" }, + { 0x11c, "dma0_sg3" }, + { 0x120, "dma0_sr" }, + { 0x123, "dma0_sgc" }, + { 0x125, "dma0_slp" }, + { 0x126, "dma0_pol" }, + { 0x180, "mal0_cfg" }, + { 0x181, "mal0_esr" }, + { 0x182, "mal0_ier" }, + { 0x184, "mal0_txcasr" }, + { 0x185, "mal0_txcarr" }, + { 0x186, "mal0_txeobisr" }, + { 0x187, "mal0_txdeir" }, + { 0x190, "mal0_rxcasr" }, + { 0x191, "mal0_rxcarr" }, + { 0x192, "mal0_rxeobisr" }, + { 0x193, "mal0_rxdeir" }, + { 0x1a0, "mal0_txctp0r" }, + { 0x1a1, "mal0_txctp1r" }, + { 0x1a2, "mal0_txctp2r" }, + { 0x1a3, "mal0_txctp3r" }, + { 0x1c0, "mal0_rxctp0r" }, + { 0x1e0, "mal0_rcbs0" }, + { 0, NULL } +}; + +void +op_ill(instr_t instr, vm_offset_t loc) +{ + db_printf("illegal instruction %x\n", instr); +} + +u_int32_t +extract_field(u_int32_t value, u_int32_t base, u_int32_t width) +{ + u_int32_t mask = (1 << width) - 1; + return ((value >> base) & mask); +} + +const struct opcode * search_op(const struct opcode *); + +void +disasm_fields(const struct opcode *popcode, instr_t instr, vm_offset_t loc, + char *disasm_str) +{ + char * pstr; + enum function_mask func; + + pstr = disasm_str; + + func = popcode->func; + if (func & Op_OE) { + u_int OE; + /* also for Op_S (they are the same) */ + OE = extract_field(instr, 31 - 21, 1); + if (OE) { + pstr += sprintf(pstr, "o"); + } + func &= ~Op_OE; + } + switch (func & Op_LKM) { + case Op_Rc: + if (instr & 0x1) { + pstr += sprintf(pstr, "."); + } + break; + case Op_AA: + if (instr & 0x2) { + pstr += sprintf(pstr, "a"); + loc = 0; /* Absolute address */ + } + case Op_LK: + if (instr & 0x1) { + pstr += sprintf(pstr, "l"); + } + break; + default: + func &= ~Op_LKM; + } + pstr += sprintf(pstr, "\t"); + + /* XXX: special cases here, out of flags in a 32bit word. */ + if (strcmp(popcode->name, "wrteei") == 0) { + int E; + E = extract_field(instr, 31 - 16, 5); + pstr += sprintf(pstr, "%d", E); + return; + } + /* XXX: end of special cases here. */ + + if (func & Op_D) { + u_int D; + /* also for Op_S (they are the same) */ + D = extract_field(instr, 31 - 10, 5); + pstr += sprintf(pstr, "r%d, ", D); + func &= ~Op_D; + } + if (func & Op_crbD) { + u_int crbD; + crbD = extract_field(instr, 31 - 10, 5); + pstr += sprintf(pstr, "crb%d, ", crbD); + func &= ~Op_crbD; + } + if (func & Op_crfD) { + u_int crfD; + crfD = extract_field(instr, 31 - 8, 3); + pstr += sprintf(pstr, "crf%d, ", crfD); + func &= ~Op_crfD; + } + if (func & Op_L) { + u_int L; + L = extract_field(instr, 31 - 10, 1); + if (L) { + pstr += sprintf(pstr, "L, "); + } + func &= ~Op_L; + } + if (func & Op_FM) { + u_int FM; + FM = extract_field(instr, 31 - 10, 8); + pstr += sprintf(pstr, "%d, ", FM); + func &= ~Op_FM; + } + if (func & Op_TO) { + u_int TO; + TO = extract_field(instr, 31 - 10, 1); + pstr += sprintf(pstr, "%d, ", TO); + func &= ~Op_TO; + } + if (func & Op_crfS) { + u_int crfS; + crfS = extract_field(instr, 31 - 13, 3); + pstr += sprintf(pstr, "%d, ", crfS); + func &= ~Op_crfS; + } + if (func & Op_BO) { + u_int BO; + BO = extract_field(instr, 31 - 10, 5); + pstr += sprintf(pstr, "%d, ", BO); + func &= ~Op_BO; + } + if (func & Op_A) { + u_int A; + A = extract_field(instr, 31 - 15, 5); + pstr += sprintf(pstr, "r%d, ", A); + func &= ~Op_A; + } + if (func & Op_B) { + u_int B; + B = extract_field(instr, 31 - 20, 5); + pstr += sprintf(pstr, "r%d, ", B); + func &= ~Op_B; + } + if (func & Op_C) { + u_int C; + C = extract_field(instr, 31 - 25, 5); + pstr += sprintf(pstr, "r%d, ", C); + func &= ~Op_C; + } + if (func & Op_BI) { + u_int BI; + BI = extract_field(instr, 31 - 10, 5); + pstr += sprintf(pstr, "%d, ", BI); + func &= ~Op_BI; + } + if (func & Op_crbA) { + u_int crbA; + crbA = extract_field(instr, 31 - 15, 5); + pstr += sprintf(pstr, "%d, ", crbA); + func &= ~Op_crbA; + } + if (func & Op_crbB) { + u_int crbB; + crbB = extract_field(instr, 31 - 20, 5); + pstr += sprintf(pstr, "%d, ", crbB); + func &= ~Op_crbB; + } + if (func & Op_CRM) { + u_int CRM; + CRM = extract_field(instr, 31 - 19, 8); + pstr += sprintf(pstr, "0x%x, ", CRM); + func &= ~Op_CRM; + } + if (func & Op_LI) { + int LI; + LI = extract_field(instr, 31 - 29, 24); + /* Need to sign extend and shift up 2, then add addr */ + LI = LI << 8; + LI = LI >> 6; + LI += loc; + pstr += sprintf (pstr, "0x%x, ", LI); + func &= ~Op_LI; + } + switch (func & Op_SIMM) { + u_int IMM; + case Op_SIMM: /* same as Op_d */ + IMM = extract_field(instr, 31 - 31, 16); + if (IMM & 0x8000) { + pstr += sprintf(pstr, "-"); + IMM = 0x10000-IMM; + } + func &= ~Op_SIMM; + goto common; + case Op_UIMM: + IMM = extract_field(instr, 31 - 31, 16); + func &= ~Op_UIMM; + goto common; + common: + pstr += sprintf(pstr, "0x%x", IMM); + break; + default: + break; + } + if (func & Op_BD) { + u_int BD; + BD = extract_field(instr, 31 - 29, 14); + pstr += sprintf(pstr, "0x%x, ", BD); + func &= ~Op_BD; + } + if (func & Op_ds) { + u_int ds; + ds = extract_field(instr, 31 - 29, 14) << 2; + pstr += sprintf(pstr, "0x%x, ", ds); + func &= ~Op_ds; + } + if (func & Op_spr) { + u_int spr; + u_int sprl; + u_int sprh; + const struct specialreg *regs; + int i; + sprl = extract_field(instr, 31 - 15, 5); + sprh = extract_field(instr, 31 - 20, 5); + spr = sprh << 5 | sprl; + + /* ugly hack - out of bitfields in the function mask */ + if (popcode->name[2] == 'd') /* m.Dcr */ + regs = dcrregs; + else + regs = sprregs; + for (i = 0; regs[i].name != NULL; i++) + if (spr == regs[i].reg) + break; + if (regs[i].reg == 0) + pstr += sprintf(pstr, "[unknown special reg (%d)]", spr); + else + pstr += sprintf(pstr, "%s", regs[i].name); + func &= ~Op_spr; + } + + if (func & Op_me) { + u_int me, mel, meh; + mel = extract_field(instr, 31 - 25, 4); + meh = extract_field(instr, 31 - 26, 1); + me = meh << 4 | mel; + pstr += sprintf(pstr, ", 0x%x", me); + func &= ~Op_me; + } + if ((func & Op_MB) && (func & Op_sh_mb_sh)) { + u_int MB; + u_int ME; + MB = extract_field(instr, 31 - 20, 5); + pstr += sprintf(pstr, ", %d", MB); + ME = extract_field(instr, 31 - 25, 5); + pstr += sprintf(pstr, ", %d", ME); + } + if ((func & Op_SH) && (func & Op_sh_mb_sh)) { + u_int SH; + SH = extract_field(instr, 31 - 20, 5); + pstr += sprintf(pstr, ", %d", SH); + } + if ((func & Op_sh) && ! (func & Op_sh_mb_sh)) { + u_int sh, shl, shh; + shl = extract_field(instr, 31 - 19, 4); + shh = extract_field(instr, 31 - 20, 1); + sh = shh << 4 | shl; + pstr += sprintf(pstr, ", %d", sh); + } + if ((func & Op_mb) && ! (func & Op_sh_mb_sh)) { + u_int mb, mbl, mbh; + mbl = extract_field(instr, 31 - 25, 4); + mbh = extract_field(instr, 31 - 26, 1); + mb = mbh << 4 | mbl; + pstr += sprintf(pstr, ", %d", mb); + } + if ((func & Op_me) && ! (func & Op_sh_mb_sh)) { + u_int me, mel, meh; + mel = extract_field(instr, 31 - 25, 4); + meh = extract_field(instr, 31 - 26, 1); + me = meh << 4 | mel; + pstr += sprintf(pstr, ", %d", me); + } + if (func & Op_tbr) { + u_int tbr; + u_int tbrl; + u_int tbrh; + char *reg; + tbrl = extract_field(instr, 31 - 15, 5); + tbrh = extract_field(instr, 31 - 20, 5); + tbr = tbrh << 5 | tbrl; + + switch (tbr) { + case 268: + reg = "tbl"; + break; + case 269: + reg = "tbu"; + break; + default: + reg = 0; + } + if (reg == 0) + pstr += sprintf(pstr, ", [unknown tbr %d ]", tbr); + else + pstr += sprintf(pstr, ", %s", reg); + func &= ~Op_tbr; + } + if (func & Op_SR) { + u_int SR; + SR = extract_field(instr, 31 - 15, 3); + pstr += sprintf(pstr, ", sr%d", SR); + func &= ~Op_SR; + } + if (func & Op_NB) { + u_int NB; + NB = extract_field(instr, 31 - 20, 5); + if (NB == 0) + NB = 32; + pstr += sprintf(pstr, ", %d", NB); + func &= ~Op_SR; + } + if (func & Op_IMM) { + u_int IMM; + IMM = extract_field(instr, 31 - 19, 4); + pstr += sprintf(pstr, ", %d", IMM); + func &= ~Op_SR; + } +} + +void +op_base(instr_t instr, vm_offset_t loc) +{ + dis_ppc(opcodes, instr, loc); +} + +void +op_cl_x13(instr_t instr, vm_offset_t loc) +{ + dis_ppc(opcodes_13, instr, loc); +} + +void +op_cl_x1e(instr_t instr, vm_offset_t loc) +{ + dis_ppc(opcodes_1e, instr, loc); +} + +void +op_cl_x1f(instr_t instr, vm_offset_t loc) +{ + dis_ppc(opcodes_1f, instr, loc); +} + +void +op_cl_x3a(instr_t instr, vm_offset_t loc) +{ + dis_ppc(opcodes_3a, instr, loc); +} + +void +op_cl_x3b(instr_t instr, vm_offset_t loc) +{ + dis_ppc(opcodes_3b, instr, loc); +} + +void +op_cl_x3e(instr_t instr, vm_offset_t loc) +{ + dis_ppc(opcodes_3e, instr, loc); +} + +void +op_cl_x3f(instr_t instr, vm_offset_t loc) +{ + dis_ppc(opcodes_3f, instr, loc); +} + +void +dis_ppc(const struct opcode *opcodeset, instr_t instr, vm_offset_t loc) +{ + const struct opcode *op; + int found = 0; + int i; + char disasm_str[30]; + + for (i = 0, op = &opcodeset[0]; + found == 0 && op->mask != 0; + i++, op = &opcodeset[i]) { + if ((instr & op->mask) == op->code) { + found = 1; + disasm_fields(op, instr, loc, disasm_str); + db_printf("%s%s\n", op->name, disasm_str); + return; + } + } + op_ill(instr, loc); +} + +db_addr_t +db_disasm(db_addr_t loc, boolean_t extended) +{ + int class; + instr_t opcode; + opcode = *(instr_t *)(loc); + class = opcode >> 26; + (opcodes_base[class])(opcode, loc); + + return (loc + 4); +} + +vm_offset_t opc_disasm(vm_offset_t loc, int); + +vm_offset_t +opc_disasm(vm_offset_t loc, int xin) +{ + int class; + instr_t opcode; + opcode = xin; + class = opcode >> 26; + (opcodes_base[class])(opcode, loc); + + return (loc + 4); +} diff --git a/sys/powerpc/powerpc/db_hwwatch.c b/sys/powerpc/powerpc/db_hwwatch.c new file mode 100644 index 000000000000..a5b0a69f5a91 --- /dev/null +++ b/sys/powerpc/powerpc/db_hwwatch.c @@ -0,0 +1,54 @@ +/*- + * Copyright (C) 2002 Benno Rice. + * 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 Benno Rice ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include <sys/param.h> + +#include <vm/vm.h> + +#include <ddb/ddb.h> +#include <ddb/db_access.h> +#include <ddb/db_sym.h> +#include <ddb/db_variables.h> +#include <ddb/db_watch.h> + +int +db_md_set_watchpoint(db_expr_t addr, db_expr_t size) +{ + + return (0); +} + +int +db_md_clr_watchpoint(db_expr_t addr, db_expr_t size) +{ + + return (0); +} + +void +db_md_list_watchpoints(void) +{ +} diff --git a/sys/powerpc/powerpc/db_interface.c b/sys/powerpc/powerpc/db_interface.c new file mode 100644 index 000000000000..3dae648d05fe --- /dev/null +++ b/sys/powerpc/powerpc/db_interface.c @@ -0,0 +1,81 @@ +/* $FreeBSD$ */ +/* $NetBSD: db_interface.c,v 1.20 2002/05/13 20:30:09 matt Exp $ */ +/* $OpenBSD: db_interface.c,v 1.2 1996/12/28 06:21:50 rahnds Exp $ */ + + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/cons.h> +#include <sys/kdb.h> +#include <sys/ktr.h> +#include <sys/lock.h> +#include <sys/pcpu.h> +#include <sys/proc.h> +#include <sys/smp.h> + +#include <machine/kdb.h> +#include <machine/md_var.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <ddb/ddb.h> +#include <ddb/db_sym.h> +#include <ddb/db_command.h> +#include <ddb/db_access.h> +#include <ddb/db_output.h> + +#include <dev/ofw/openfirm.h> + +int +db_read_bytes(vm_offset_t addr, size_t size, char *data) +{ + jmp_buf jb; + void *prev_jb; + char *src; + int ret; + + prev_jb = kdb_jmpbuf(jb); + ret = setjmp(jb); + if (ret == 0) { + src = (char *)addr; + + if (size == 4) + *((int *)data) = *((int *)src); + else if (size == 2) + *((short *)data) = *((short *)src); + else + while (size-- > 0) + *data++ = *src++; + } + (void)kdb_jmpbuf(prev_jb); + return (ret); +} + +int +db_write_bytes(vm_offset_t addr, size_t size, char *data) +{ + jmp_buf jb; + void *prev_jb; + char *dst; + size_t cnt; + int ret; + + prev_jb = kdb_jmpbuf(jb); + ret = setjmp(jb); + if (ret == 0) { + dst = (char *)addr; + cnt = size; + + while (cnt-- > 0) + *dst++ = *data++; + kdb_cpu_sync_icache((void *)addr, size); + } + (void)kdb_jmpbuf(prev_jb); + return (ret); +} + +void +db_show_mdpcpu(struct pcpu *pc) +{ +} diff --git a/sys/powerpc/powerpc/db_memrw.c b/sys/powerpc/powerpc/db_memrw.c new file mode 100644 index 000000000000..e27bc67fafe5 --- /dev/null +++ b/sys/powerpc/powerpc/db_memrw.c @@ -0,0 +1,110 @@ +/* $FreeBSD$ */ +/* $NetBSD: db_memrw.c,v 1.5 2001/12/27 10:25:41 dbj Exp $ */ +/* $OpenBSD: db_memrw.c,v 1.2 1996/12/28 06:21:52 rahnds Exp $ */ + +/*- + * Mach Operating System + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +/* + * Interface to the debugger for virtual memory read/write. + * This is a simple version for kernels with writable text. + * For an example of read-only kernel text, see the file: + * sys/arch/sun3/sun3/db_memrw.c + * + * ALERT! If you want to access device registers with a + * specific size, then the read/write functions have to + * make sure to do the correct sized pointer access. + */ + +#include <sys/param.h> +#include <sys/proc.h> + +#include <vm/vm.h> +#include <vm/vm_extern.h> + +#include <machine/cpu.h> +#include <machine/db_machdep.h> + +#include <ddb/ddb.h> + +/* + * Read bytes from kernel address space for debugger. + */ +void +db_read_bytes(addr, size, data) + vm_offset_t addr; + register size_t size; + register char *data; +{ + register char *src = (char*)addr; + + if (size == 4) { + *((int*)data) = *((int*)src); + return; + } + + if (size == 2) { + *((short*)data) = *((short*)src); + return; + } + + while (size > 0) { + --size; + *data++ = *src++; + } +} + +/* + * Write bytes to kernel address space for debugger. + */ +void +db_write_bytes(addr, size, data) + vm_offset_t addr; + register size_t size; + register char *data; +{ + register char *dst = (char *)addr; + + if (size == 4) { + + *((int*)dst) = *((int*)data); + + } else if (size == 2) { + + *((short*)dst) = *((short*)data); + + } else { + + while (size > 0) { + --size; + *dst++ = *data++; + } + + } + + __syncicache((void *)addr, size); +} + diff --git a/sys/powerpc/powerpc/db_trace.c b/sys/powerpc/powerpc/db_trace.c new file mode 100644 index 000000000000..188e0287aab2 --- /dev/null +++ b/sys/powerpc/powerpc/db_trace.c @@ -0,0 +1,323 @@ +/* $FreeBSD$ */ +/* $NetBSD: db_trace.c,v 1.20 2002/05/13 20:30:09 matt Exp $ */ +/* $OpenBSD: db_trace.c,v 1.3 1997/03/21 02:10:48 niklas Exp $ */ + +/*- + * Mach Operating System + * Copyright (c) 1992 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kdb.h> +#include <sys/proc.h> +#include <sys/stack.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_extern.h> + +#include <machine/db_machdep.h> +#include <machine/pcb.h> +#include <machine/spr.h> +#include <machine/trap.h> + +#include <ddb/ddb.h> +#include <ddb/db_access.h> +#include <ddb/db_sym.h> +#include <ddb/db_variables.h> + +static db_varfcn_t db_frame; + +#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x) + +struct db_variable db_regs[] = { + { "r0", DB_OFFSET(fixreg[0]), db_frame }, + { "r1", DB_OFFSET(fixreg[1]), db_frame }, + { "r2", DB_OFFSET(fixreg[2]), db_frame }, + { "r3", DB_OFFSET(fixreg[3]), db_frame }, + { "r4", DB_OFFSET(fixreg[4]), db_frame }, + { "r5", DB_OFFSET(fixreg[5]), db_frame }, + { "r6", DB_OFFSET(fixreg[6]), db_frame }, + { "r7", DB_OFFSET(fixreg[7]), db_frame }, + { "r8", DB_OFFSET(fixreg[8]), db_frame }, + { "r9", DB_OFFSET(fixreg[9]), db_frame }, + { "r10", DB_OFFSET(fixreg[10]), db_frame }, + { "r11", DB_OFFSET(fixreg[11]), db_frame }, + { "r12", DB_OFFSET(fixreg[12]), db_frame }, + { "r13", DB_OFFSET(fixreg[13]), db_frame }, + { "r14", DB_OFFSET(fixreg[14]), db_frame }, + { "r15", DB_OFFSET(fixreg[15]), db_frame }, + { "r16", DB_OFFSET(fixreg[16]), db_frame }, + { "r17", DB_OFFSET(fixreg[17]), db_frame }, + { "r18", DB_OFFSET(fixreg[18]), db_frame }, + { "r19", DB_OFFSET(fixreg[19]), db_frame }, + { "r20", DB_OFFSET(fixreg[20]), db_frame }, + { "r21", DB_OFFSET(fixreg[21]), db_frame }, + { "r22", DB_OFFSET(fixreg[22]), db_frame }, + { "r23", DB_OFFSET(fixreg[23]), db_frame }, + { "r24", DB_OFFSET(fixreg[24]), db_frame }, + { "r25", DB_OFFSET(fixreg[25]), db_frame }, + { "r26", DB_OFFSET(fixreg[26]), db_frame }, + { "r27", DB_OFFSET(fixreg[27]), db_frame }, + { "r28", DB_OFFSET(fixreg[28]), db_frame }, + { "r29", DB_OFFSET(fixreg[29]), db_frame }, + { "r30", DB_OFFSET(fixreg[30]), db_frame }, + { "r31", DB_OFFSET(fixreg[31]), db_frame }, + { "srr0", DB_OFFSET(srr0), db_frame }, + { "srr1", DB_OFFSET(srr1), db_frame }, + { "lr", DB_OFFSET(lr), db_frame }, + { "ctr", DB_OFFSET(ctr), db_frame }, + { "cr", DB_OFFSET(cr), db_frame }, + { "xer", DB_OFFSET(xer), db_frame }, + { "dar", DB_OFFSET(dar), db_frame }, + { "dsisr", DB_OFFSET(dsisr), db_frame }, +}; +struct db_variable *db_eregs = db_regs + sizeof (db_regs)/sizeof (db_regs[0]); + +extern int trapexit[]; +extern int asttrapexit[]; +extern int end[]; + +/* + * register variable handling + */ +static int +db_frame(struct db_variable *vp, db_expr_t *valuep, int op) +{ + uint32_t *reg; + + if (kdb_frame == NULL) + return (0); + reg = (uint32_t*)((uintptr_t)kdb_frame + (uintptr_t)vp->valuep); + if (op == DB_VAR_GET) + *valuep = *reg; + else + *reg = *valuep; + return (1); +} + + +/* + * Frame tracing. + */ +static int +db_backtrace(struct thread *td, db_addr_t fp, int count) +{ + db_addr_t stackframe, lr, *args; + db_expr_t diff; + c_db_sym_t sym; + const char *symname; + boolean_t kernel_only = TRUE; + boolean_t full = FALSE; + +#if 0 + { + register char *cp = modif; + register char c; + + while ((c = *cp++) != 0) { + if (c == 't') + trace_thread = TRUE; + if (c == 'u') + kernel_only = FALSE; + if (c == 'f') + full = TRUE; + } + } +#endif + + stackframe = fp; + + while (!db_pager_quit) { + if (stackframe < PAGE_SIZE) + break; + + /* + * Locate the next frame by grabbing the backchain ptr + * from frame[0] + */ + stackframe = *(db_addr_t *)stackframe; + + next_frame: + /* The saved arg values start at frame[2] */ + args = (db_addr_t *)(stackframe + 8); + + if (stackframe < PAGE_SIZE) + break; + + if (count-- == 0) + break; + + /* + * Extract link register from frame and subtract + * 4 to convert into calling address (as opposed to + * return address) + */ + lr = *(db_addr_t *)(stackframe + 4) - 4; + if ((lr & 3) || (lr < 0x100)) { + db_printf("saved LR(0x%x) is invalid.", lr); + break; + } + + db_printf("0x%08x: ", stackframe); + + /* + * The trap code labels the return addresses from the + * call to C code as 'trapexit' and 'asttrapexit. Use this + * to determine if the callframe has to traverse a saved + * trap context + */ + if ((lr + 4 == (db_addr_t) &trapexit) || + (lr + 4 == (db_addr_t) &asttrapexit)) { + const char *trapstr; + struct trapframe *tf = (struct trapframe *) + (stackframe+8); + db_printf("%s ", tf->srr1 & PSL_PR ? "user" : "kernel"); + switch (tf->exc) { + case EXC_DSI: + db_printf("DSI %s trap @ %#x by ", + tf->dsisr & DSISR_STORE ? "write" : "read", + tf->dar); + goto print_trap; + case EXC_ALI: + db_printf("ALI trap @ %#x (DSISR %#x) ", + tf->dar, tf->dsisr); + goto print_trap; + case EXC_ISI: trapstr = "ISI"; break; + case EXC_PGM: trapstr = "PGM"; break; + case EXC_SC: trapstr = "SC"; break; + case EXC_EXI: trapstr = "EXI"; break; + case EXC_MCHK: trapstr = "MCHK"; break; + case EXC_VEC: trapstr = "VEC"; break; + case EXC_FPU: trapstr = "FPU"; break; + case EXC_FPA: trapstr = "FPA"; break; + case EXC_DECR: trapstr = "DECR"; break; + case EXC_BPT: trapstr = "BPT"; break; + case EXC_TRC: trapstr = "TRC"; break; + case EXC_RUNMODETRC: trapstr = "RUNMODETRC"; break; + case EXC_PERF: trapstr = "PERF"; break; + case EXC_SMI: trapstr = "SMI"; break; + case EXC_RST: trapstr = "RST"; break; + default: trapstr = NULL; break; + } + if (trapstr != NULL) { + db_printf("%s trap by ", trapstr); + } else { + db_printf("trap %#x by ", tf->exc); + } + + print_trap: + lr = (db_addr_t) tf->srr0; + diff = 0; + symname = NULL; + sym = db_search_symbol(lr, DB_STGY_ANY, &diff); + db_symbol_values(sym, &symname, 0); + if (symname == NULL || !strcmp(symname, "end")) { + db_printf("%#x: srr1=%#x\n", lr, tf->srr1); + } else { + db_printf("%s+%#x: srr1=%#x\n", symname, diff, + tf->srr1); + } + db_printf("%-10s r1=%#x cr=%#x xer=%#x ctr=%#x", + "", tf->fixreg[1], tf->cr, tf->xer, tf->ctr); + if (tf->exc == EXC_DSI) + db_printf(" dsisr=%#x", tf->dsisr); + db_printf("\n"); + stackframe = (db_addr_t) tf->fixreg[1]; + if (kernel_only && (tf->srr1 & PSL_PR)) + break; + goto next_frame; + } + + diff = 0; + symname = NULL; + sym = db_search_symbol(lr, DB_STGY_ANY, &diff); + db_symbol_values(sym, &symname, 0); + if (symname == NULL || !strcmp(symname, "end")) + db_printf("at %x", lr); + else + db_printf("at %s+%#x", symname, diff); + if (full) + /* Print all the args stored in that stackframe. */ + db_printf("(%x, %x, %x, %x, %x, %x, %x, %x)", + args[0], args[1], args[2], args[3], + args[4], args[5], args[6], args[7]); + db_printf("\n"); + } + + return (0); +} + +void +db_trace_self(void) +{ + db_addr_t addr; + + addr = (db_addr_t)__builtin_frame_address(1); + db_backtrace(curthread, addr, -1); +} + +int +db_trace_thread(struct thread *td, int count) +{ + struct pcb *ctx; + + ctx = kdb_thr_ctx(td); + return (db_backtrace(td, (db_addr_t)ctx->pcb_sp, count)); +} + +void +stack_save(struct stack *st) +{ + vm_offset_t callpc; + db_addr_t stackframe; + + stack_zero(st); + stackframe = (db_addr_t)__builtin_frame_address(1); + if (stackframe < PAGE_SIZE) + return; + while (1) { + stackframe = *(db_addr_t *)stackframe; + if (stackframe < PAGE_SIZE) + break; + callpc = *(vm_offset_t *)(stackframe + 4) - 4; + if ((callpc & 3) || (callpc < 0x100)) + break; + + /* + * Don't bother traversing trap-frames - there should + * be enough info down to the frame to work out where + * things are going wrong. Plus, prevents this shortened + * version of code from accessing user-space frames + */ + if (callpc + 4 == (db_addr_t) &trapexit || + callpc + 4 == (db_addr_t) &asttrapexit) + break; + + if (stack_put(st, callpc) == -1) + break; + } +} + diff --git a/sys/powerpc/powerpc/elf_machdep.c b/sys/powerpc/powerpc/elf_machdep.c new file mode 100644 index 000000000000..ff017e13e936 --- /dev/null +++ b/sys/powerpc/powerpc/elf_machdep.c @@ -0,0 +1,234 @@ +/*- + * Copyright 1996-1998 John D. Polstra. + * 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. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/exec.h> +#include <sys/imgact.h> +#include <sys/malloc.h> +#include <sys/proc.h> +#include <sys/namei.h> +#include <sys/fcntl.h> +#include <sys/sysent.h> +#include <sys/imgact_elf.h> +#include <sys/syscall.h> +#include <sys/signalvar.h> +#include <sys/vnode.h> +#include <sys/linker.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> + +#include <machine/cpu.h> +#include <machine/elf.h> +#include <machine/md_var.h> + +struct sysentvec elf32_freebsd_sysvec = { + SYS_MAXSYSCALL, + sysent, + 0, + 0, + NULL, + 0, + NULL, + NULL, + __elfN(freebsd_fixup), + sendsig, + sigcode, + &szsigcode, + NULL, + "FreeBSD ELF32", + __elfN(coredump), + NULL, + MINSIGSTKSZ, + PAGE_SIZE, + VM_MIN_ADDRESS, + VM_MAXUSER_ADDRESS, + USRSTACK, + PS_STRINGS, + VM_PROT_ALL, + exec_copyout_strings, + exec_setregs, + NULL +}; + +static Elf32_Brandinfo freebsd_brand_info = { + ELFOSABI_FREEBSD, + EM_PPC, + "FreeBSD", + NULL, + "/libexec/ld-elf.so.1", + &elf32_freebsd_sysvec, + NULL, + BI_CAN_EXEC_DYN, + }; + +SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY, + (sysinit_cfunc_t) elf32_insert_brand_entry, + &freebsd_brand_info); + +static Elf32_Brandinfo freebsd_brand_oinfo = { + ELFOSABI_FREEBSD, + EM_PPC, + "FreeBSD", + NULL, + "/usr/libexec/ld-elf.so.1", + &elf32_freebsd_sysvec, + NULL, + BI_CAN_EXEC_DYN, + }; + +SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY, + (sysinit_cfunc_t) elf32_insert_brand_entry, + &freebsd_brand_oinfo); + + +void +elf32_dump_thread(struct thread *td __unused, void *dst __unused, + size_t *off __unused) +{ +} + + +/* Process one elf relocation with addend. */ +static int +elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, + int type, int local, elf_lookup_fn lookup) +{ + Elf_Addr *where; + Elf_Half *hwhere; + Elf_Addr addr; + Elf_Addr addend; + Elf_Word rtype, symidx; + const Elf_Rela *rela; + + switch (type) { + case ELF_RELOC_REL: + panic("PPC only supports RELA relocations"); + break; + case ELF_RELOC_RELA: + rela = (const Elf_Rela *)data; + where = (Elf_Addr *) (relocbase + rela->r_offset); + hwhere = (Elf_Half *) (relocbase + rela->r_offset); + addend = rela->r_addend; + rtype = ELF_R_TYPE(rela->r_info); + symidx = ELF_R_SYM(rela->r_info); + break; + default: + panic("elf_reloc: unknown relocation mode %d\n", type); + } + + switch (rtype) { + + case R_PPC_NONE: + break; + + case R_PPC_ADDR32: /* word32 S + A */ + addr = lookup(lf, symidx, 1); + if (addr == 0) + return -1; + addr += addend; + *where = addr; + break; + + case R_PPC_ADDR16_LO: /* #lo(S) */ + addr = lookup(lf, symidx, 1); + if (addr == 0) + return -1; + /* + * addend values are sometimes relative to sections + * (i.e. .rodata) in rela, where in reality they + * are relative to relocbase. Detect this condition. + */ + if (addr > relocbase && addr <= (relocbase + addend)) + addr = relocbase + addend; + else + addr += addend; + *hwhere = addr & 0xffff; + break; + + case R_PPC_ADDR16_HA: /* #ha(S) */ + addr = lookup(lf, symidx, 1); + if (addr == 0) + return -1; + /* + * addend values are sometimes relative to sections + * (i.e. .rodata) in rela, where in reality they + * are relative to relocbase. Detect this condition. + */ + if (addr > relocbase && addr <= (relocbase + addend)) + addr = relocbase + addend; + else + addr += addend; + *hwhere = ((addr >> 16) + ((addr & 0x8000) ? 1 : 0)) + & 0xffff; + break; + + case R_PPC_RELATIVE: /* word32 B + A */ + *where = relocbase + addend; + break; + + default: + printf("kldload: unexpected relocation type %d\n", + (int) rtype); + return -1; + } + return(0); +} + +int +elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, + elf_lookup_fn lookup) +{ + + return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup)); +} + +int +elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, + int type, elf_lookup_fn lookup) +{ + + return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup)); +} + +int +elf_cpu_load_file(linker_file_t lf) +{ + /* Only sync the cache for non-kernel modules */ + if (lf->id != 1) + __syncicache(lf->address, lf->size); + return (0); +} + +int +elf_cpu_unload_file(linker_file_t lf __unused) +{ + + return (0); +} diff --git a/sys/powerpc/powerpc/fpu.c b/sys/powerpc/powerpc/fpu.c new file mode 100644 index 000000000000..c4cc326da431 --- /dev/null +++ b/sys/powerpc/powerpc/fpu.c @@ -0,0 +1,151 @@ +/*- + * Copyright (C) 1996 Wolfgang Solfrank. + * Copyright (C) 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: fpu.c,v 1.5 2001/07/22 11:29:46 wiz Exp $ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/limits.h> + +#include <machine/fpu.h> +#include <machine/pcb.h> +#include <machine/psl.h> + +void +enable_fpu(struct thread *td) +{ + int msr; + struct pcb *pcb; + struct trapframe *tf; + + pcb = td->td_pcb; + tf = trapframe(td); + + /* + * Save the thread's FPU CPU number, and set the CPU's current + * FPU thread + */ + td->td_pcb->pcb_fpcpu = PCPU_GET(cpuid); + PCPU_SET(fputhread, td); + + /* + * Enable the FPU for when the thread returns from the exception. + * If this is the first time the FPU has been used by the thread, + * initialise the FPU registers and FPSCR to 0, and set the flag + * to indicate that the FPU is in use. + */ + tf->srr1 |= PSL_FP; + if (!(pcb->pcb_flags & PCB_FPU)) { + memset(&pcb->pcb_fpu, 0, sizeof pcb->pcb_fpu); + pcb->pcb_flags |= PCB_FPU; + } + + /* + * Temporarily enable floating-point so the registers + * can be restored. + */ + msr = mfmsr(); + mtmsr(msr | PSL_FP); + isync(); + + /* + * Load the floating point registers and FPSCR from the PCB. + * (A value of 0xff for mtfsf specifies that all 8 4-bit fields + * of the saved FPSCR are to be loaded from the FPU reg). + */ + __asm __volatile ("lfd 0,0(%0); mtfsf 0xff,0" + :: "b"(&pcb->pcb_fpu.fpscr)); + +#define LFP(n) __asm ("lfd " #n ", 0(%0)" \ + :: "b"(&pcb->pcb_fpu.fpr[n])); + LFP(0); LFP(1); LFP(2); LFP(3); + LFP(4); LFP(5); LFP(6); LFP(7); + LFP(8); LFP(9); LFP(10); LFP(11); + LFP(12); LFP(13); LFP(14); LFP(15); + LFP(16); LFP(17); LFP(18); LFP(19); + LFP(20); LFP(21); LFP(22); LFP(23); + LFP(24); LFP(25); LFP(26); LFP(27); + LFP(28); LFP(29); LFP(30); LFP(31); +#undef LFP + + isync(); + mtmsr(msr); +} + +void +save_fpu(struct thread *td) +{ + int msr; + struct pcb *pcb; + + pcb = td->td_pcb; + + /* + * Temporarily re-enable floating-point during the save + */ + msr = mfmsr(); + mtmsr(msr | PSL_FP); + isync(); + + /* + * Save the floating-point registers and FPSCR to the PCB + */ +#define SFP(n) __asm ("stfd " #n ", 0(%0)" \ + :: "b"(&pcb->pcb_fpu.fpr[n])); + SFP(0); SFP(1); SFP(2); SFP(3); + SFP(4); SFP(5); SFP(6); SFP(7); + SFP(8); SFP(9); SFP(10); SFP(11); + SFP(12); SFP(13); SFP(14); SFP(15); + SFP(16); SFP(17); SFP(18); SFP(19); + SFP(20); SFP(21); SFP(22); SFP(23); + SFP(24); SFP(25); SFP(26); SFP(27); + SFP(28); SFP(29); SFP(30); SFP(31); +#undef SFP + __asm __volatile ("mffs 0; stfd 0,0(%0)" :: "b"(&pcb->pcb_fpu.fpscr)); + + /* + * Disable floating-point again + */ + isync(); + mtmsr(msr); + + /* + * Clear the current fp thread and pcb's CPU id + * XXX should this be left clear to allow lazy save/restore ? + */ + pcb->pcb_fpcpu = INT_MAX; + PCPU_SET(fputhread, NULL); +} + diff --git a/sys/powerpc/powerpc/fuswintr.c b/sys/powerpc/powerpc/fuswintr.c new file mode 100644 index 000000000000..cb5abb7b9a18 --- /dev/null +++ b/sys/powerpc/powerpc/fuswintr.c @@ -0,0 +1,51 @@ +/*- + * Copyright (C) 1994 Wolfgang Solfrank. + * Copyright (C) 1994 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: fuswintr.c,v 1.2 2000/06/08 07:29:54 kleink Exp $ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/resourcevar.h> + +/* + * Emulate fuswintr + * + * Simply return fault for all cases + */ +int +fuswintr(void *addr) +{ + + return -1; +} diff --git a/sys/powerpc/powerpc/gdb_machdep.c b/sys/powerpc/powerpc/gdb_machdep.c new file mode 100644 index 000000000000..5fbb74427391 --- /dev/null +++ b/sys/powerpc/powerpc/gdb_machdep.c @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 2006 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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 AUTHORS ``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 AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kdb.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/signal.h> + +#include <machine/gdb_machdep.h> +#include <machine/pcb.h> +#include <machine/reg.h> +#include <machine/trap.h> + +#include <gdb/gdb.h> +#include <gdb/gdb_int.h> + +void * +gdb_cpu_getreg(int regnum, size_t *regsz) +{ + + *regsz = gdb_cpu_regsz(regnum); + switch (regnum) { + } + return (NULL); +} + +void +gdb_cpu_setreg(int regnum, void *val) +{ + + switch (regnum) { + case GDB_REG_PC: + break; + } +} + +int +gdb_cpu_signal(int vector, int dummy __unused) +{ + + if (vector == EXC_TRC || vector == EXC_RUNMODETRC) + return (SIGTRAP); + return (vector); +} diff --git a/sys/powerpc/powerpc/genassym.c b/sys/powerpc/powerpc/genassym.c new file mode 100644 index 000000000000..63719cc12d20 --- /dev/null +++ b/sys/powerpc/powerpc/genassym.c @@ -0,0 +1,154 @@ +/*- + * Copyright (c) 1982, 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)genassym.c 5.11 (Berkeley) 5/10/91 + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/assym.h> +#include <sys/errno.h> +#include <sys/ktr.h> +#include <sys/proc.h> +#include <sys/queue.h> +#include <sys/signal.h> +#include <sys/smp.h> +#include <sys/systm.h> +#include <sys/ucontext.h> +#include <sys/ucontext.h> +#include <sys/vmmeter.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> + +#include <machine/pcb.h> +#include <machine/pmap.h> +#include <machine/sigframe.h> + +ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread)); +ASSYM(PC_CURPCB, offsetof(struct pcpu, pc_curpcb)); +ASSYM(PC_CURPMAP, offsetof(struct pcpu, pc_curpmap)); +ASSYM(PC_TEMPSAVE, offsetof(struct pcpu, pc_tempsave)); +ASSYM(PC_DISISAVE, offsetof(struct pcpu, pc_disisave)); +ASSYM(PC_DBSAVE, offsetof(struct pcpu, pc_dbsave)); + +ASSYM(CPUSAVE_R28,CPUSAVE_R28*4); +ASSYM(CPUSAVE_R29,CPUSAVE_R29*4); +ASSYM(CPUSAVE_R30,CPUSAVE_R30*4); +ASSYM(CPUSAVE_R31,CPUSAVE_R31*4); +ASSYM(CPUSAVE_DAR,CPUSAVE_DAR*4); +ASSYM(CPUSAVE_DSISR,CPUSAVE_DSISR*4); +ASSYM(CPUSAVE_SRR0,CPUSAVE_SRR0*4); +ASSYM(CPUSAVE_SRR1,CPUSAVE_SRR1*4); + +ASSYM(MTX_LOCK, offsetof(struct mtx, mtx_lock)); +ASSYM(MTX_RECURSECNT, offsetof(struct mtx, mtx_recurse)); + +ASSYM(PM_KERNELSR, offsetof(struct pmap, pm_sr[KERNEL_SR])); +ASSYM(PM_USRSR, offsetof(struct pmap, pm_sr[USER_SR])); +ASSYM(PM_SR, offsetof(struct pmap, pm_sr)); + +ASSYM(FSP, 8); +ASSYM(FRAMELEN, FRAMELEN); +ASSYM(FRAME_0, offsetof(struct trapframe, fixreg[0])); +ASSYM(FRAME_1, offsetof(struct trapframe, fixreg[1])); +ASSYM(FRAME_2, offsetof(struct trapframe, fixreg[2])); +ASSYM(FRAME_3, offsetof(struct trapframe, fixreg[3])); +ASSYM(FRAME_4, offsetof(struct trapframe, fixreg[4])); +ASSYM(FRAME_5, offsetof(struct trapframe, fixreg[5])); +ASSYM(FRAME_6, offsetof(struct trapframe, fixreg[6])); +ASSYM(FRAME_7, offsetof(struct trapframe, fixreg[7])); +ASSYM(FRAME_8, offsetof(struct trapframe, fixreg[8])); +ASSYM(FRAME_9, offsetof(struct trapframe, fixreg[9])); +ASSYM(FRAME_10, offsetof(struct trapframe, fixreg[10])); +ASSYM(FRAME_11, offsetof(struct trapframe, fixreg[11])); +ASSYM(FRAME_12, offsetof(struct trapframe, fixreg[12])); +ASSYM(FRAME_13, offsetof(struct trapframe, fixreg[13])); +ASSYM(FRAME_14, offsetof(struct trapframe, fixreg[14])); +ASSYM(FRAME_15, offsetof(struct trapframe, fixreg[15])); +ASSYM(FRAME_16, offsetof(struct trapframe, fixreg[16])); +ASSYM(FRAME_17, offsetof(struct trapframe, fixreg[17])); +ASSYM(FRAME_18, offsetof(struct trapframe, fixreg[18])); +ASSYM(FRAME_19, offsetof(struct trapframe, fixreg[19])); +ASSYM(FRAME_20, offsetof(struct trapframe, fixreg[20])); +ASSYM(FRAME_21, offsetof(struct trapframe, fixreg[21])); +ASSYM(FRAME_22, offsetof(struct trapframe, fixreg[22])); +ASSYM(FRAME_23, offsetof(struct trapframe, fixreg[23])); +ASSYM(FRAME_24, offsetof(struct trapframe, fixreg[24])); +ASSYM(FRAME_25, offsetof(struct trapframe, fixreg[25])); +ASSYM(FRAME_26, offsetof(struct trapframe, fixreg[26])); +ASSYM(FRAME_27, offsetof(struct trapframe, fixreg[27])); +ASSYM(FRAME_28, offsetof(struct trapframe, fixreg[28])); +ASSYM(FRAME_29, offsetof(struct trapframe, fixreg[29])); +ASSYM(FRAME_30, offsetof(struct trapframe, fixreg[30])); +ASSYM(FRAME_31, offsetof(struct trapframe, fixreg[31])); +ASSYM(FRAME_LR, offsetof(struct trapframe, lr)); +ASSYM(FRAME_CR, offsetof(struct trapframe, cr)); +ASSYM(FRAME_CTR, offsetof(struct trapframe, ctr)); +ASSYM(FRAME_XER, offsetof(struct trapframe, xer)); +ASSYM(FRAME_SRR0, offsetof(struct trapframe, srr0)); +ASSYM(FRAME_SRR1, offsetof(struct trapframe, srr1)); +ASSYM(FRAME_DAR, offsetof(struct trapframe, dar)); +ASSYM(FRAME_DSISR, offsetof(struct trapframe, dsisr)); +ASSYM(FRAME_EXC, offsetof(struct trapframe, exc)); + +ASSYM(CF_FUNC, offsetof(struct callframe, cf_func)); +ASSYM(CF_ARG0, offsetof(struct callframe, cf_arg0)); +ASSYM(CF_ARG1, offsetof(struct callframe, cf_arg1)); +ASSYM(CF_SIZE, sizeof(struct callframe)); + +ASSYM(PCB_CONTEXT, offsetof(struct pcb, pcb_context)); +ASSYM(PCB_CR, offsetof(struct pcb, pcb_cr)); +ASSYM(PCB_PMR, offsetof(struct pcb, pcb_pmreal)); +ASSYM(PCB_SP, offsetof(struct pcb, pcb_sp)); +ASSYM(PCB_LR, offsetof(struct pcb, pcb_lr)); +ASSYM(PCB_USR, offsetof(struct pcb, pcb_usr)); +ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault)); +ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags)); +ASSYM(PCB_FPU, PCB_FPU); + +ASSYM(TD_PROC, offsetof(struct thread, td_proc)); +ASSYM(TD_PCB, offsetof(struct thread, td_pcb)); + +ASSYM(P_VMSPACE, offsetof(struct proc, p_vmspace)); + +ASSYM(VM_PMAP, offsetof(struct vmspace, vm_pmap)); + +ASSYM(TD_FLAGS, offsetof(struct thread, td_flags)); + +ASSYM(TDF_ASTPENDING, TDF_ASTPENDING); +ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED); + +ASSYM(SF_UC, offsetof(struct sigframe, sf_uc)); + +ASSYM(MAXCOMLEN, MAXCOMLEN); diff --git a/sys/powerpc/powerpc/in_cksum.c b/sys/powerpc/powerpc/in_cksum.c new file mode 100644 index 000000000000..a65ed7dddfbe --- /dev/null +++ b/sys/powerpc/powerpc/in_cksum.c @@ -0,0 +1,250 @@ +/* $FreeBSD$ */ +/* $NetBSD: in_cksum.c,v 1.7 1997/09/02 13:18:15 thorpej Exp $ */ + +/*- + * Copyright (c) 1988, 1992, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1996 + * Matt Thomas <matt@3am-software.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +#include <sys/param.h> +#include <sys/mbuf.h> +#include <sys/systm.h> +#include <netinet/in_systm.h> +#include <netinet/in.h> +#include <netinet/ip.h> +#include <machine/in_cksum.h> + +/* + * Checksum routine for Internet Protocol family headers + * (Portable Alpha version). + * + * This routine is very heavily used in the network + * code and should be modified for each CPU to be as fast as possible. + */ + +#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) +#define REDUCE32 \ + { \ + q_util.q = sum; \ + sum = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \ + } +#define REDUCE16 \ + { \ + q_util.q = sum; \ + l_util.l = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \ + sum = l_util.s[0] + l_util.s[1]; \ + ADDCARRY(sum); \ + } + +static const u_int32_t in_masks[] = { +#if 0 + /*0 bytes*/ /*1 byte*/ /*2 bytes*/ /*3 bytes*/ + 0x00000000, 0x000000FF, 0x0000FFFF, 0x00FFFFFF, /* offset 0 */ + 0x00000000, 0x0000FF00, 0x00FFFF00, 0xFFFFFF00, /* offset 1 */ + 0x00000000, 0x00FF0000, 0xFFFF0000, 0xFFFF0000, /* offset 2 */ + 0x00000000, 0xFF000000, 0xFF000000, 0xFF000000, /* offset 3 */ +#else + /*0 bytes*/ /*1 byte*/ /*2 bytes*/ /*3 bytes*/ + 0x00000000, 0xFF000000, 0xFFFF0000, 0xFFFFFF00, /* offset 0 */ + 0x00000000, 0x00FF0000, 0x00FFFF00, 0x00FFFFFF, /* offset 1 */ + 0x00000000, 0x0000FF00, 0x0000FFFF, 0x0000FFFF, /* offset 2 */ + 0x00000000, 0x000000FF, 0x000000FF, 0x000000FF, /* offset 3 */ +#endif +}; + +union l_util { + u_int16_t s[2]; + u_int32_t l; +}; +union q_util { + u_int16_t s[4]; + u_int32_t l[2]; + u_int64_t q; +}; + +static u_int64_t +in_cksumdata(const void *buf, int len) +{ + const u_int32_t *lw = (const u_int32_t *) buf; + u_int64_t sum = 0; + u_int64_t prefilled; + int offset; + union q_util q_util; + + if ((3 & (long) lw) == 0 && len == 20) { + sum = (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3] + lw[4]; + REDUCE32; + return sum; + } + + if ((offset = 3 & (long) lw) != 0) { + const u_int32_t *masks = in_masks + (offset << 2); + lw = (u_int32_t *) (((long) lw) - offset); + sum = *lw++ & masks[len >= 3 ? 3 : len]; + len -= 4 - offset; + if (len <= 0) { + REDUCE32; + return sum; + } + } +#if 0 + /* + * Force to cache line boundary. + */ + offset = 32 - (0x1f & (long) lw); + if (offset < 32 && len > offset) { + len -= offset; + if (4 & offset) { + sum += (u_int64_t) lw[0]; + lw += 1; + } + if (8 & offset) { + sum += (u_int64_t) lw[0] + lw[1]; + lw += 2; + } + if (16 & offset) { + sum += (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3]; + lw += 4; + } + } +#endif + /* + * access prefilling to start load of next cache line. + * then add current cache line + * save result of prefilling for loop iteration. + */ + prefilled = lw[0]; + while ((len -= 32) >= 4) { + u_int64_t prefilling = lw[8]; + sum += prefilled + lw[1] + lw[2] + lw[3] + + lw[4] + lw[5] + lw[6] + lw[7]; + lw += 8; + prefilled = prefilling; + } + if (len >= 0) { + sum += prefilled + lw[1] + lw[2] + lw[3] + + lw[4] + lw[5] + lw[6] + lw[7]; + lw += 8; + } else { + len += 32; + } + while ((len -= 16) >= 0) { + sum += (u_int64_t) lw[0] + lw[1] + lw[2] + lw[3]; + lw += 4; + } + len += 16; + while ((len -= 4) >= 0) { + sum += (u_int64_t) *lw++; + } + len += 4; + if (len > 0) + sum += (u_int64_t) (in_masks[len] & *lw); + REDUCE32; + return sum; +} + +u_short +in_addword(u_short a, u_short b) +{ + u_int64_t sum = a + b; + + ADDCARRY(sum); + return (sum); +} + +u_short +in_pseudo(u_int32_t a, u_int32_t b, u_int32_t c) +{ + u_int64_t sum; + union q_util q_util; + union l_util l_util; + + sum = (u_int64_t) a + b + c; + REDUCE16; + return (sum); +} + +u_short +in_cksum_skip(struct mbuf *m, int len, int skip) +{ + u_int64_t sum = 0; + int mlen = 0; + int clen = 0; + caddr_t addr; + union q_util q_util; + union l_util l_util; + + len -= skip; + for (; skip && m; m = m->m_next) { + if (m->m_len > skip) { + mlen = m->m_len - skip; + addr = mtod(m, caddr_t) + skip; + goto skip_start; + } else { + skip -= m->m_len; + } + } + + for (; m && len; m = m->m_next) { + if (m->m_len == 0) + continue; + mlen = m->m_len; + addr = mtod(m, caddr_t); +skip_start: + if (len < mlen) + mlen = len; + + if ((clen ^ (int) addr) & 1) + sum += in_cksumdata(addr, mlen) << 8; + else + sum += in_cksumdata(addr, mlen); + + clen += mlen; + len -= mlen; + } + REDUCE16; + return (~sum & 0xffff); +} + +u_int in_cksum_hdr(const struct ip *ip) +{ + u_int64_t sum = in_cksumdata(ip, sizeof(struct ip)); + union q_util q_util; + union l_util l_util; + REDUCE16; + return (~sum & 0xffff); +} diff --git a/sys/powerpc/powerpc/interrupt.c b/sys/powerpc/powerpc/interrupt.c new file mode 100644 index 000000000000..ff77fc8dc074 --- /dev/null +++ b/sys/powerpc/powerpc/interrupt.c @@ -0,0 +1,101 @@ +/*- + * Copyright 2002 by Peter Grehan. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * Interrupts are dispatched to here from locore asm + */ + +#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/interrupt.h> +#include <sys/kernel.h> +#include <sys/kthread.h> +#include <sys/ktr.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/smp.h> +#include <sys/unistd.h> +#include <sys/vmmeter.h> + +#include <machine/cpu.h> +#include <machine/clock.h> +#include <machine/db_machdep.h> +#include <machine/fpu.h> +#include <machine/frame.h> +#include <machine/intr_machdep.h> +#include <machine/md_var.h> +#include <machine/pcb.h> +#include <machine/psl.h> +#include <machine/trap.h> +#include <machine/spr.h> +#include <machine/sr.h> + +#include "pic_if.h" + +/* + * A very short dispatch, to try and maximise assembler code use + * between all exception types. Maybe 'true' interrupts should go + * here, and the trap code can come in separately + */ +void +powerpc_interrupt(struct trapframe *framep) +{ + struct thread *td; + register_t ee; + + td = curthread; + + switch (framep->exc) { + case EXC_EXI: + atomic_add_int(&td->td_intr_nesting_level, 1); + PIC_DISPATCH(pic, framep); + atomic_subtract_int(&td->td_intr_nesting_level, 1); + break; + + case EXC_DECR: + atomic_add_int(&td->td_intr_nesting_level, 1); + decr_intr(framep); + atomic_subtract_int(&td->td_intr_nesting_level, 1); + break; + + default: + /* Re-enable interrupts if applicable. */ + ee = framep->srr1 & PSL_EE; + if (ee != 0) { + mtmsr(mfmsr() | ee); + isync(); + } + trap(framep); + } +} diff --git a/sys/powerpc/powerpc/intr_machdep.c b/sys/powerpc/powerpc/intr_machdep.c new file mode 100644 index 000000000000..7653347579f3 --- /dev/null +++ b/sys/powerpc/powerpc/intr_machdep.c @@ -0,0 +1,306 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/*- + * Copyright (c) 2002 Benno Rice. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 + * form: src/sys/i386/isa/intr_machdep.c,v 1.57 2001/07/20 + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/queue.h> +#include <sys/bus.h> +#include <sys/interrupt.h> +#include <sys/ktr.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/pcpu.h> +#include <sys/syslog.h> +#include <sys/vmmeter.h> +#include <sys/proc.h> + +#include <machine/frame.h> +#include <machine/intr_machdep.h> +#include <machine/md_var.h> +#include <machine/trap.h> + +#include "pic_if.h" + +#define MAX_STRAY_LOG 5 + +MALLOC_DEFINE(M_INTR, "intr", "interrupt handler data"); + +struct powerpc_intr { + struct intr_event *event; + long *cntp; + u_int irq; +}; + +static struct powerpc_intr *powerpc_intrs[INTR_VECTORS]; +static u_int nvectors; /* Allocated vectors */ +static u_int stray_count; + +device_t pic; + +static void +intrcnt_setname(const char *name, int index) +{ + snprintf(intrnames + (MAXCOMLEN + 1) * index, MAXCOMLEN + 1, "%-*s", + MAXCOMLEN, name); +} + +#ifdef INTR_FILTER +static void +powerpc_intr_eoi(void *arg) +{ + u_int irq = (uintptr_t)arg; + + PIC_EOI(pic, irq); +} + +static void +powerpc_intr_mask(void *arg) +{ + u_int irq = (uintptr_t)arg; + + PIC_MASK(pic, irq); +} +#endif + +static void +powerpc_intr_unmask(void *arg) +{ + u_int irq = (uintptr_t)arg; + + PIC_UNMASK(pic, irq); +} + +void +powerpc_register_pic(device_t dev) +{ + + pic = dev; +} + +int +powerpc_enable_intr(void) +{ + struct powerpc_intr *i; + int vector; + + for (vector = 0; vector < nvectors; vector++) { + i = powerpc_intrs[vector]; + if (i == NULL) + continue; + + PIC_ENABLE(pic, i->irq, vector); + } + + return (0); +} + +int +powerpc_setup_intr(const char *name, u_int irq, driver_filter_t filter, + driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep) +{ + struct powerpc_intr *i; + u_int vector; + int error; + + /* XXX lock */ + + i = NULL; + for (vector = 0; vector < nvectors; vector++) { + i = powerpc_intrs[vector]; + if (i == NULL) + continue; + if (i->irq == irq) + break; + i = NULL; + } + + if (i == NULL) { + if (nvectors >= INTR_VECTORS) { + /* XXX unlock */ + return (ENOENT); + } + + i = malloc(sizeof(*i), M_INTR, M_NOWAIT); + if (i == NULL) { + /* XXX unlock */ + return (ENOMEM); + } + error = intr_event_create(&i->event, (void *)irq, 0, + powerpc_intr_unmask, +#ifdef INTR_FILTER + powerpc_intr_eoi, powerpc_intr_mask, +#endif + "irq%u:", irq); + if (error) { + /* XXX unlock */ + free(i, M_INTR); + return (error); + } + + vector = nvectors++; + powerpc_intrs[vector] = i; + + i->irq = irq; + + /* XXX unlock */ + + i->cntp = &intrcnt[vector]; + intrcnt_setname(i->event->ie_fullname, vector); + + if (!cold) + PIC_ENABLE(pic, i->irq, vector); + } else { + /* XXX unlock */ + } + + error = intr_event_add_handler(i->event, name, filter, handler, arg, + intr_priority(flags), flags, cookiep); + if (!error) + intrcnt_setname(i->event->ie_fullname, vector); + return (error); +} + +int +powerpc_teardown_intr(void *cookie) +{ + + return (intr_event_remove_handler(cookie)); +} + +void +powerpc_dispatch_intr(u_int vector, struct trapframe *tf) +{ + struct powerpc_intr *i; + struct intr_event *ie; +#ifndef INTR_FILTER + struct intr_handler *ih; + int error, sched, ret; +#endif + + i = powerpc_intrs[vector]; + if (i == NULL) + goto stray; + + (*i->cntp)++; + + ie = i->event; + KASSERT(ie != NULL, ("%s: interrupt without an event", __func__)); + +#ifdef INTR_FILTER + if (intr_event_handle(ie, tf) != 0) { + PIC_MASK(pic, i->irq); + log(LOG_ERR, "stray irq%u\n", i->irq); + } +#else + if (TAILQ_EMPTY(&ie->ie_handlers)) + goto stray; + + /* + * Execute all fast interrupt handlers directly without Giant. Note + * that this means that any fast interrupt handler must be MP safe. + */ + ret = 0; + sched = 0; + critical_enter(); + TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) { + if (ih->ih_filter == NULL) { + sched = 1; + continue; + } + CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__, + ih->ih_filter, ih->ih_argument, ih->ih_name); + ret = ih->ih_filter(ih->ih_argument); + /* + * Wrapper handler special case: see + * i386/intr_machdep.c::intr_execute_handlers() + */ + if (!sched) { + if (ret == FILTER_SCHEDULE_THREAD) + sched = 1; + } + } + + if (sched) { + PIC_MASK(pic, i->irq); + error = intr_event_schedule_thread(ie); + KASSERT(error == 0, ("%s: impossible stray interrupt", + __func__)); + } else + PIC_EOI(pic, i->irq); + critical_exit(); +#endif + return; + +stray: + stray_count++; + if (stray_count <= MAX_STRAY_LOG) { + printf("stray irq %d\n", i->irq); + if (stray_count >= MAX_STRAY_LOG) { + printf("got %d stray interrupts, not logging anymore\n", + MAX_STRAY_LOG); + } + } + if (i != NULL) + PIC_MASK(pic, i->irq); +} diff --git a/sys/powerpc/powerpc/locore.S b/sys/powerpc/powerpc/locore.S new file mode 100644 index 000000000000..1a3c0bbaceeb --- /dev/null +++ b/sys/powerpc/powerpc/locore.S @@ -0,0 +1,208 @@ +/* $FreeBSD$ */ +/* $NetBSD: locore.S,v 1.24 2000/05/31 05:09:17 thorpej Exp $ */ + +/*- + * Copyright (C) 2001 Benno Rice + * 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 Benno Rice ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "assym.s" + +#include <sys/syscall.h> + +#include <machine/trap.h> +#include <machine/param.h> +#include <machine/sr.h> +#include <machine/spr.h> +#include <machine/psl.h> +#include <machine/asm.h> + +/* Locate the per-CPU data structure */ +#define GET_CPUINFO(r) \ + mfsprg0 r + +/* + * Globals + */ + .data +GLOBAL(tmpstk) + .space 8208 +GLOBAL(esym) + .long 0 /* end of symbol table */ + +GLOBAL(ofmsr) + .long 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */ + +GLOBAL(powersave) + .long 0 + +#define INTSTK 16384 /* 16K interrupt stack */ +#define INTRCNT_COUNT 256 /* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */ +GLOBAL(intrnames) + .space INTRCNT_COUNT * (MAXCOMLEN + 1) * 2 +GLOBAL(eintrnames) + .align 4 +GLOBAL(intrcnt) + .space INTRCNT_COUNT * 4 * 2 +GLOBAL(eintrcnt) + +/* + * File-scope for locore.S + */ +idle_u: + .long 0 /* fake uarea during idle after exit */ +openfirmware_entry: + .long 0 /* Open Firmware entry point */ +srsave: + .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + +/* + * This symbol is here for the benefit of kvm_mkdb, and is supposed to + * mark the start of kernel text. + */ + .text + .globl kernel_text +kernel_text: + +/* + * Startup entry. Note, this must be the first thing in the text + * segment! + */ + .text + .globl __start +__start: +#ifdef FIRMWORKSBUGS + mfmsr 0 + andi. 0,0,PSL_IR|PSL_DR + beq 1f + + bl ofwr_init +1: +#endif + li 8,0 + li 9,0x100 + mtctr 9 +1: + dcbf 0,8 + icbi 0,8 + addi 8,8,0x20 + bdnz 1b + sync + isync + + /* Save the argument pointer and length */ + mr 20,6 + mr 21,7 + + lis 8,openfirmware_entry@ha + stw 5,openfirmware_entry@l(8) /* save client interface handler */ + mr 3,5 + + lis 1,tmpstk@ha + addi 1,1,tmpstk@l + addi 1,1,8192 + + mfmsr 0 + lis 9,ofmsr@ha + stwu 0,ofmsr@l(9) + + mfsprg0 0 /* save SPRG0-3 */ + stw 0,4(9) /* ofmsr[1] = sprg0 */ + mfsprg1 0 + stw 0,8(9) /* ofmsr[2] = sprg1 */ + mfsprg2 0 + stw 0,12(9) /* ofmsr[3] = sprg2 */ + mfsprg3 0 + stw 0,16(9) /* ofmsr[4] = sprg3 */ + + bl OF_init + + lis 4,end@ha + addi 4,4,end@l + mr 5,4 + + lis 3,kernel_text@ha + addi 3,3,kernel_text@l + + /* Restore the argument pointer and length */ + mr 6,20 + mr 7,21 + + bl powerpc_init + bl mi_startup + b OF_exit + +/* + * int setfault() + * + * Similar to setjmp to setup for handling faults on accesses to user memory. + * Any routine using this may only call bcopy, either the form below, + * or the (currently used) C code optimized, so it doesn't use any non-volatile + * registers. + */ + .globl setfault +setfault: + mflr 0 + mfcr 12 + mfsprg 4,0 + lwz 4,PC_CURTHREAD(4) + lwz 4,TD_PCB(4) + stw 3,PCB_ONFAULT(4) + stw 0,0(3) + stw 1,4(3) + stw 2,8(3) + stmw 12,12(3) + xor 3,3,3 + blr + +#include <powerpc/powerpc/trap_subr.S> diff --git a/sys/powerpc/powerpc/machdep.c b/sys/powerpc/powerpc/machdep.c new file mode 100644 index 000000000000..ed0ff8339abc --- /dev/null +++ b/sys/powerpc/powerpc/machdep.c @@ -0,0 +1,995 @@ +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*- + * Copyright (C) 2001 Benno Rice + * 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 Benno Rice ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * $NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "opt_compat.h" +#include "opt_ddb.h" +#include "opt_kstack_pages.h" +#include "opt_msgbuf.h" + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/bio.h> +#include <sys/buf.h> +#include <sys/bus.h> +#include <sys/cons.h> +#include <sys/cpu.h> +#include <sys/eventhandler.h> +#include <sys/exec.h> +#include <sys/imgact.h> +#include <sys/kdb.h> +#include <sys/kernel.h> +#include <sys/ktr.h> +#include <sys/linker.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/msgbuf.h> +#include <sys/mutex.h> +#include <sys/ptrace.h> +#include <sys/reboot.h> +#include <sys/signalvar.h> +#include <sys/sysctl.h> +#include <sys/sysent.h> +#include <sys/sysproto.h> +#include <sys/ucontext.h> +#include <sys/uio.h> +#include <sys/vmmeter.h> +#include <sys/vnode.h> + +#include <net/netisr.h> + +#include <vm/vm.h> +#include <vm/vm_extern.h> +#include <vm/vm_kern.h> +#include <vm/vm_page.h> +#include <vm/vm_map.h> +#include <vm/vm_object.h> +#include <vm/vm_pager.h> + +#include <machine/bat.h> +#include <machine/cpu.h> +#include <machine/elf.h> +#include <machine/fpu.h> +#include <machine/md_var.h> +#include <machine/metadata.h> +#include <machine/mmuvar.h> +#include <machine/pcb.h> +#include <machine/powerpc.h> +#include <machine/reg.h> +#include <machine/sigframe.h> +#include <machine/trap.h> +#include <machine/vmparam.h> + +#include <ddb/ddb.h> + +#include <dev/ofw/openfirm.h> + +#ifdef DDB +extern vm_offset_t ksym_start, ksym_end; +#endif + +int cold = 1; + +struct pcpu __pcpu[MAXCPU]; +struct trapframe frame0; + +vm_offset_t kstack0; +vm_offset_t kstack0_phys; + +char machine[] = "powerpc"; +SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); + +static int cacheline_size = CACHELINESIZE; +SYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size, + CTLFLAG_RD, &cacheline_size, 0, ""); + +static void cpu_startup(void *); +SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) + +void powerpc_init(u_int, u_int, u_int, void *); + +int save_ofw_mapping(void); +int restore_ofw_mapping(void); + +void install_extint(void (*)(void)); + +int setfault(faultbuf); /* defined in locore.S */ + +static int grab_mcontext(struct thread *, mcontext_t *, int); + +void asm_panic(char *); + +long Maxmem = 0; +long realmem = 0; + +struct pmap ofw_pmap; +extern int ofmsr; + +struct bat battable[16]; + +struct kva_md_info kmi; + +void setPQL2(int *const size, int *const ways); + +void +setPQL2(int *const size, int *const ways) +{ + return; +} + +static void +powerpc_ofw_shutdown(void *junk, int howto) +{ + if (howto & RB_HALT) { + OF_halt(); + } + OF_reboot(); +} + +static void +cpu_startup(void *dummy) +{ + + /* + * Initialise the decrementer-based clock. + */ + decr_init(); + + /* + * Good {morning,afternoon,evening,night}. + */ + cpu_setup(PCPU_GET(cpuid)); + + /* startrtclock(); */ +#ifdef PERFMON + perfmon_init(); +#endif + printf("real memory = %ld (%ld MB)\n", ptoa(physmem), + ptoa(physmem) / 1048576); + realmem = physmem; + + /* + * Display any holes after the first chunk of extended memory. + */ + if (bootverbose) { + int indx; + + printf("Physical memory chunk(s):\n"); + for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { + int size1 = phys_avail[indx + 1] - phys_avail[indx]; + + printf("0x%08x - 0x%08x, %d bytes (%d pages)\n", + phys_avail[indx], phys_avail[indx + 1] - 1, size1, + size1 / PAGE_SIZE); + } + } + + vm_ksubmap_init(&kmi); + + printf("avail memory = %ld (%ld MB)\n", ptoa(cnt.v_free_count), + ptoa(cnt.v_free_count) / 1048576); + + /* + * Set up buffers, so they can be used to read disk labels. + */ + bufinit(); + vm_pager_bufferinit(); + + EVENTHANDLER_REGISTER(shutdown_final, powerpc_ofw_shutdown, 0, + SHUTDOWN_PRI_LAST); + +#ifdef SMP + /* + * OK, enough kmem_alloc/malloc state should be up, lets get on with it! + */ + mp_start(); /* fire up the secondaries */ + mp_announce(); +#endif /* SMP */ +} + +extern char kernel_text[], _end[]; + +extern void *trapcode, *trapsize; +extern void *alitrap, *alisize; +extern void *dsitrap, *dsisize; +extern void *decrint, *decrsize; +extern void *extint, *extsize; +extern void *dblow, *dbsize; +extern void *vectrap, *vectrapsize; + +void +powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp) +{ + struct pcpu *pc; + vm_offset_t end, off; + void *kmdp; + char *env; + + end = 0; + kmdp = NULL; + + /* + * Parse metadata if present and fetch parameters. Must be done + * before console is inited so cninit gets the right value of + * boothowto. + */ + if (mdp != NULL) { + preload_metadata = mdp; + kmdp = preload_search_by_type("elf kernel"); + if (kmdp != NULL) { + boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); + kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); + end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); +#ifdef DDB + ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t); + ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t); +#endif + } + } + + /* + * Init params/tunables that can be overridden by the loader + */ + init_param1(); + + /* + * Start initializing proc0 and thread0. + */ + proc_linkup(&proc0, &thread0); + thread0.td_frame = &frame0; + + /* + * Set up per-cpu data. + */ + pc = &__pcpu[0]; + pcpu_init(pc, 0, sizeof(struct pcpu)); + pc->pc_curthread = &thread0; + pc->pc_curpcb = thread0.td_pcb; + pc->pc_cpuid = 0; + + __asm __volatile("mtsprg 0, %0" :: "r"(pc)); + + mutex_init(); + + /* + * Initialize the console before printing anything. + */ + cninit(); + + /* + * Complain if there is no metadata. + */ + if (mdp == NULL || kmdp == NULL) { + printf("powerpc_init: no loader metadata.\n"); + } + + kdb_init(); + + kobj_machdep_init(); + + /* + * XXX: Initialize the interrupt tables. + * Disable translation in case the vector area + * hasn't been mapped (G5) + */ + mtmsr(mfmsr() & ~(PSL_IR | PSL_DR)); + isync(); + bcopy(&trapcode, (void *)EXC_RST, (size_t)&trapsize); + bcopy(&trapcode, (void *)EXC_MCHK, (size_t)&trapsize); + bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize); + bcopy(&trapcode, (void *)EXC_ISI, (size_t)&trapsize); + bcopy(&trapcode, (void *)EXC_EXI, (size_t)&trapsize); + bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize); + bcopy(&trapcode, (void *)EXC_PGM, (size_t)&trapsize); + bcopy(&trapcode, (void *)EXC_FPU, (size_t)&trapsize); + bcopy(&trapcode, (void *)EXC_DECR, (size_t)&trapsize); + bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize); + bcopy(&trapcode, (void *)EXC_TRC, (size_t)&trapsize); + bcopy(&trapcode, (void *)EXC_FPA, (size_t)&trapsize); + bcopy(&vectrap, (void *)EXC_VEC, (size_t)&vectrapsize); + bcopy(&trapcode, (void *)EXC_VECAST, (size_t)&trapsize); + bcopy(&trapcode, (void *)EXC_THRM, (size_t)&trapsize); + bcopy(&trapcode, (void *)EXC_BPT, (size_t)&trapsize); +#ifdef KDB + bcopy(&dblow, (void *)EXC_RST, (size_t)&dbsize); + bcopy(&dblow, (void *)EXC_MCHK, (size_t)&dbsize); + bcopy(&dblow, (void *)EXC_PGM, (size_t)&dbsize); + bcopy(&dblow, (void *)EXC_TRC, (size_t)&dbsize); + bcopy(&dblow, (void *)EXC_BPT, (size_t)&dbsize); +#endif + __syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD); + + /* + * Make sure translation has been enabled + */ + mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI); + isync(); + + /* + * Initialise virtual memory. + */ + pmap_mmu_install(MMU_TYPE_OEA, 0); /* XXX temporary */ + pmap_bootstrap(startkernel, endkernel); + + /* + * Initialize params/tunables that are derived from memsize + */ + init_param2(physmem); + + /* + * Grab booted kernel's name + */ + env = getenv("kernelname"); + if (env != NULL) { + strlcpy(kernelname, env, sizeof(kernelname)); + freeenv(env); + } + + /* + * Finish setting up thread0. + */ + thread0.td_kstack = kstack0; + thread0.td_pcb = (struct pcb *) + (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; + + /* + * Map and initialise the message buffer. + */ + for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE) + pmap_kenter((vm_offset_t)msgbufp + off, msgbuf_phys + off); + msgbufinit(msgbufp, MSGBUF_SIZE); + +#ifdef KDB + if (boothowto & RB_KDB) + kdb_enter("Boot flags requested debugger"); +#endif +} + +void +bzero(void *buf, size_t len) +{ + caddr_t p; + + p = buf; + + while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) { + *p++ = 0; + len--; + } + + while (len >= sizeof(u_long) * 8) { + *(u_long*) p = 0; + *((u_long*) p + 1) = 0; + *((u_long*) p + 2) = 0; + *((u_long*) p + 3) = 0; + len -= sizeof(u_long) * 8; + *((u_long*) p + 4) = 0; + *((u_long*) p + 5) = 0; + *((u_long*) p + 6) = 0; + *((u_long*) p + 7) = 0; + p += sizeof(u_long) * 8; + } + + while (len >= sizeof(u_long)) { + *(u_long*) p = 0; + len -= sizeof(u_long); + p += sizeof(u_long); + } + + while (len) { + *p++ = 0; + len--; + } +} + +void +sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) +{ + struct trapframe *tf; + struct sigframe *sfp; + struct sigacts *psp; + struct sigframe sf; + struct thread *td; + struct proc *p; + int oonstack, rndfsize; + int sig; + int code; + + td = curthread; + p = td->td_proc; + PROC_LOCK_ASSERT(p, MA_OWNED); + sig = ksi->ksi_signo; + code = ksi->ksi_code; + psp = p->p_sigacts; + mtx_assert(&psp->ps_mtx, MA_OWNED); + tf = td->td_frame; + oonstack = sigonstack(tf->fixreg[1]); + + rndfsize = ((sizeof(sf) + 15) / 16) * 16; + + CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, + catcher, sig); + + /* + * Save user context + */ + memset(&sf, 0, sizeof(sf)); + grab_mcontext(td, &sf.sf_uc.uc_mcontext, 0); + sf.sf_uc.uc_sigmask = *mask; + sf.sf_uc.uc_stack = td->td_sigstk; + sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) + ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; + + sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; + + /* + * Allocate and validate space for the signal handler context. + */ + if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && + SIGISMEMBER(psp->ps_sigonstack, sig)) { + sfp = (struct sigframe *)(td->td_sigstk.ss_sp + + td->td_sigstk.ss_size - rndfsize); + } else { + sfp = (struct sigframe *)(tf->fixreg[1] - rndfsize); + } + + /* + * Translate the signal if appropriate (Linux emu ?) + */ + if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) + sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; + + /* + * Save the floating-point state, if necessary, then copy it. + */ + /* XXX */ + + /* + * Set up the registers to return to sigcode. + * + * r1/sp - sigframe ptr + * lr - sig function, dispatched to by blrl in trampoline + * r3 - sig number + * r4 - SIGINFO ? &siginfo : exception code + * r5 - user context + * srr0 - trampoline function addr + */ + tf->lr = (register_t)catcher; + tf->fixreg[1] = (register_t)sfp; + tf->fixreg[FIRSTARG] = sig; + tf->fixreg[FIRSTARG+2] = (register_t)&sfp->sf_uc; + if (SIGISMEMBER(psp->ps_siginfo, sig)) { + /* + * Signal handler installed with SA_SIGINFO. + */ + tf->fixreg[FIRSTARG+1] = (register_t)&sfp->sf_si; + + /* + * Fill siginfo structure. + */ + sf.sf_si = ksi->ksi_info; + sf.sf_si.si_signo = sig; + sf.sf_si.si_addr = (void *) ((tf->exc == EXC_DSI) ? + tf->dar : tf->srr0); + } else { + /* Old FreeBSD-style arguments. */ + tf->fixreg[FIRSTARG+1] = code; + tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ? + tf->dar : tf->srr0; + } + mtx_unlock(&psp->ps_mtx); + PROC_UNLOCK(p); + + tf->srr0 = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode)); + + /* + * copy the frame out to userland. + */ + if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { + /* + * Process has trashed its stack. Kill it. + */ + CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); + PROC_LOCK(p); + sigexit(td, SIGILL); + } + + CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, + tf->srr0, tf->fixreg[1]); + + PROC_LOCK(p); + mtx_lock(&psp->ps_mtx); +} + +int +sigreturn(struct thread *td, struct sigreturn_args *uap) +{ + struct proc *p; + ucontext_t uc; + int error; + + CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); + + if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { + CTR1(KTR_SIG, "sigreturn: efault td=%p", td); + return (EFAULT); + } + + error = set_mcontext(td, &uc.uc_mcontext); + if (error != 0) + return (error); + + p = td->td_proc; + PROC_LOCK(p); + td->td_sigmask = uc.uc_sigmask; + SIG_CANTMASK(td->td_sigmask); + signotify(td); + PROC_UNLOCK(p); + + CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x", + td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]); + + return (EJUSTRETURN); +} + +#ifdef COMPAT_FREEBSD4 +int +freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) +{ + + return sigreturn(td, (struct sigreturn_args *)uap); +} +#endif + +/* + * Construct a PCB from a trapframe. This is called from kdb_trap() where + * we want to start a backtrace from the function that caused us to enter + * the debugger. We have the context in the trapframe, but base the trace + * on the PCB. The PCB doesn't have to be perfect, as long as it contains + * enough for a backtrace. + */ +void +makectx(struct trapframe *tf, struct pcb *pcb) +{ + + pcb->pcb_lr = tf->srr0; + pcb->pcb_sp = tf->fixreg[1]; +} + +/* + * get_mcontext/sendsig helper routine that doesn't touch the + * proc lock + */ +static int +grab_mcontext(struct thread *td, mcontext_t *mcp, int flags) +{ + struct pcb *pcb; + + pcb = td->td_pcb; + + memset(mcp, 0, sizeof(mcontext_t)); + + mcp->mc_vers = _MC_VERSION; + mcp->mc_flags = 0; + memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe)); + if (flags & GET_MC_CLEAR_RET) { + mcp->mc_gpr[3] = 0; + mcp->mc_gpr[4] = 0; + } + + /* + * This assumes that floating-point context is *not* lazy, + * so if the thread has used FP there would have been a + * FP-unavailable exception that would have set things up + * correctly. + */ + if (pcb->pcb_flags & PCB_FPU) { + KASSERT(td == curthread, + ("get_mcontext: fp save not curthread")); + critical_enter(); + save_fpu(td); + critical_exit(); + mcp->mc_flags |= _MC_FP_VALID; + memcpy(&mcp->mc_fpscr, &pcb->pcb_fpu.fpscr, sizeof(double)); + memcpy(mcp->mc_fpreg, pcb->pcb_fpu.fpr, 32*sizeof(double)); + } + + /* XXX Altivec context ? */ + + mcp->mc_len = sizeof(*mcp); + + return (0); +} + +int +get_mcontext(struct thread *td, mcontext_t *mcp, int flags) +{ + int error; + + error = grab_mcontext(td, mcp, flags); + if (error == 0) { + PROC_LOCK(curthread->td_proc); + mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]); + PROC_UNLOCK(curthread->td_proc); + } + + return (error); +} + +int +set_mcontext(struct thread *td, const mcontext_t *mcp) +{ + struct pcb *pcb; + struct trapframe *tf; + + pcb = td->td_pcb; + tf = td->td_frame; + + if (mcp->mc_vers != _MC_VERSION || + mcp->mc_len != sizeof(*mcp)) + return (EINVAL); + + /* + * Don't let the user set privileged MSR bits + */ + if ((mcp->mc_srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) { + return (EINVAL); + } + + memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame)); + + if (mcp->mc_flags & _MC_FP_VALID) { + if ((pcb->pcb_flags & PCB_FPU) != PCB_FPU) { + critical_enter(); + enable_fpu(td); + critical_exit(); + } + memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double)); + memcpy(pcb->pcb_fpu.fpr, mcp->mc_fpreg, 32*sizeof(double)); + } + + /* XXX Altivec context? */ + + return (0); +} + +void +cpu_boot(int howto) +{ +} + +void +cpu_initclocks(void) +{ + + decr_tc_init(); +} + +/* Get current clock frequency for the given cpu id. */ +int +cpu_est_clockrate(int cpu_id, uint64_t *rate) +{ + + return (ENXIO); +} + +/* + * Shutdown the CPU as much as possible. + */ +void +cpu_halt(void) +{ + + OF_exit(); +} + +void +cpu_idle(void) +{ + /* TODO: Insert code to halt (until next interrupt) */ + +#ifdef INVARIANTS + if ((mfmsr() & PSL_EE) != PSL_EE) { + struct thread *td = curthread; + printf("td msr %x\n", td->td_md.md_saved_msr); + panic("ints disabled in idleproc!"); + } +#endif +} + +/* + * Set set up registers on exec. + */ +void +exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) +{ + struct trapframe *tf; + struct ps_strings arginfo; + + tf = trapframe(td); + bzero(tf, sizeof *tf); + tf->fixreg[1] = -roundup(-stack + 8, 16); + + /* + * XXX Machine-independent code has already copied arguments and + * XXX environment to userland. Get them back here. + */ + (void)copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo)); + + /* + * Set up arguments for _start(): + * _start(argc, argv, envp, obj, cleanup, ps_strings); + * + * Notes: + * - obj and cleanup are the auxilliary and termination + * vectors. They are fixed up by ld.elf_so. + * - ps_strings is a NetBSD extention, and will be + * ignored by executables which are strictly + * compliant with the SVR4 ABI. + * + * XXX We have to set both regs and retval here due to different + * XXX calling convention in trap.c and init_main.c. + */ + /* + * XXX PG: these get overwritten in the syscall return code. + * execve() should return EJUSTRETURN, like it does on NetBSD. + * Emulate by setting the syscall return value cells. The + * registers still have to be set for init's fork trampoline. + */ + td->td_retval[0] = arginfo.ps_nargvstr; + td->td_retval[1] = (register_t)arginfo.ps_argvstr; + tf->fixreg[3] = arginfo.ps_nargvstr; + tf->fixreg[4] = (register_t)arginfo.ps_argvstr; + tf->fixreg[5] = (register_t)arginfo.ps_envstr; + tf->fixreg[6] = 0; /* auxillary vector */ + tf->fixreg[7] = 0; /* termination vector */ + tf->fixreg[8] = (register_t)PS_STRINGS; /* NetBSD extension */ + + tf->srr0 = entry; + tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT; + td->td_pcb->pcb_flags = 0; +} + +int +fill_regs(struct thread *td, struct reg *regs) +{ + struct trapframe *tf; + + tf = td->td_frame; + memcpy(regs, tf, sizeof(struct reg)); + + return (0); +} + +int +fill_dbregs(struct thread *td, struct dbreg *dbregs) +{ + /* No debug registers on PowerPC */ + return (ENOSYS); +} + +int +fill_fpregs(struct thread *td, struct fpreg *fpregs) +{ + struct pcb *pcb; + + pcb = td->td_pcb; + + if ((pcb->pcb_flags & PCB_FPU) == 0) + memset(fpregs, 0, sizeof(struct fpreg)); + else + memcpy(fpregs, &pcb->pcb_fpu, sizeof(struct fpreg)); + + return (0); +} + +int +set_regs(struct thread *td, struct reg *regs) +{ + struct trapframe *tf; + + tf = td->td_frame; + memcpy(tf, regs, sizeof(struct reg)); + + return (0); +} + +int +set_dbregs(struct thread *td, struct dbreg *dbregs) +{ + /* No debug registers on PowerPC */ + return (ENOSYS); +} + +int +set_fpregs(struct thread *td, struct fpreg *fpregs) +{ + struct pcb *pcb; + + pcb = td->td_pcb; + if ((pcb->pcb_flags & PCB_FPU) == 0) + enable_fpu(td); + memcpy(&pcb->pcb_fpu, fpregs, sizeof(struct fpreg)); + + return (0); +} + +int +ptrace_set_pc(struct thread *td, unsigned long addr) +{ + struct trapframe *tf; + + tf = td->td_frame; + tf->srr0 = (register_t)addr; + + return (0); +} + +int +ptrace_single_step(struct thread *td) +{ + struct trapframe *tf; + + tf = td->td_frame; + tf->srr1 |= PSL_SE; + + return (0); +} + +int +ptrace_clear_single_step(struct thread *td) +{ + struct trapframe *tf; + + tf = td->td_frame; + tf->srr1 &= ~PSL_SE; + + return (0); +} + +/* + * Initialise a struct pcpu. + */ +void +cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz) +{ + +} + +void +spinlock_enter(void) +{ + struct thread *td; + + td = curthread; + if (td->td_md.md_spinlock_count == 0) + td->td_md.md_saved_msr = intr_disable(); + td->td_md.md_spinlock_count++; + critical_enter(); +} + +void +spinlock_exit(void) +{ + struct thread *td; + + td = curthread; + critical_exit(); + td->td_md.md_spinlock_count--; + if (td->td_md.md_spinlock_count == 0) + intr_restore(td->td_md.md_saved_msr); +} + +/* + * kcopy(const void *src, void *dst, size_t len); + * + * Copy len bytes from src to dst, aborting if we encounter a fatal + * page fault. + * + * kcopy() _must_ save and restore the old fault handler since it is + * called by uiomove(), which may be in the path of servicing a non-fatal + * page fault. + */ +int +kcopy(const void *src, void *dst, size_t len) +{ + struct thread *td; + faultbuf env, *oldfault; + int rv; + + td = PCPU_GET(curthread); + oldfault = td->td_pcb->pcb_onfault; + if ((rv = setfault(env)) != 0) { + td->td_pcb->pcb_onfault = oldfault; + return rv; + } + + memcpy(dst, src, len); + + td->td_pcb->pcb_onfault = oldfault; + return (0); +} + +void +asm_panic(char *pstr) +{ + panic(pstr); +} + +int db_trap_glue(struct trapframe *); /* Called from trap_subr.S */ + +int +db_trap_glue(struct trapframe *frame) +{ + if (!(frame->srr1 & PSL_PR) + && (frame->exc == EXC_TRC || frame->exc == EXC_RUNMODETRC + || (frame->exc == EXC_PGM + && (frame->srr1 & 0x20000)) + || frame->exc == EXC_BPT + || frame->exc == EXC_DSI)) { + int type = frame->exc; + if (type == EXC_PGM && (frame->srr1 & 0x20000)) { + type = T_BREAKPOINT; + } + return (kdb_trap(type, 0, frame)); + } + + return (0); +} diff --git a/sys/powerpc/powerpc/mem.c b/sys/powerpc/powerpc/mem.c new file mode 100644 index 000000000000..340fa82a8eb5 --- /dev/null +++ b/sys/powerpc/powerpc/mem.c @@ -0,0 +1,181 @@ +/*- + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department, and code derived from software contributed to + * Berkeley by William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: Utah $Hdr: mem.c 1.13 89/10/08$ + * from: @(#)mem.c 7.2 (Berkeley) 5/9/91 + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * Memory special file + */ + +#include <sys/param.h> +#include <sys/conf.h> +#include <sys/fcntl.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/memrange.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/msgbuf.h> +#include <sys/systm.h> +#include <sys/signalvar.h> +#include <sys/uio.h> + +#include <machine/md_var.h> +#include <machine/vmparam.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_extern.h> + +#include <machine/memdev.h> + +struct mem_range_softc mem_range_softc; + +/* ARGSUSED */ +int +memrw(struct cdev *dev, struct uio *uio, int flags) +{ + struct iovec *iov; + int error = 0; + vm_offset_t va, eva, off, v; + vm_prot_t prot; + vm_size_t cnt; + + cnt = 0; + error = 0; + + GIANT_REQUIRED; + + while (uio->uio_resid > 0 && !error) { + iov = uio->uio_iov; + if (iov->iov_len == 0) { + uio->uio_iov++; + uio->uio_iovcnt--; + if (uio->uio_iovcnt < 0) + panic("memrw"); + continue; + } + if (minor(dev) == CDEV_MINOR_MEM) { +kmem_direct_mapped: v = uio->uio_offset; + + off = uio->uio_offset & PAGE_MASK; + cnt = PAGE_SIZE - ((vm_offset_t)iov->iov_base & + PAGE_MASK); + cnt = min(cnt, PAGE_SIZE - off); + cnt = min(cnt, iov->iov_len); + + if (mem_valid(v, cnt) + && pmap_dev_direct_mapped(v, cnt)) { + error = EFAULT; + break; + } + + uiomove((void *)v, cnt, uio); + break; + } + else if (minor(dev) == CDEV_MINOR_KMEM) { + va = uio->uio_offset; + + if ((va < VM_MIN_KERNEL_ADDRESS) + || (va > VM_MAX_KERNEL_ADDRESS)) + goto kmem_direct_mapped; + + va = trunc_page(uio->uio_offset); + eva = round_page(uio->uio_offset + + iov->iov_len); + + /* + * Make sure that all the pages are currently resident + * so that we don't create any zero-fill pages. + */ + + for (; va < eva; va += PAGE_SIZE) + if (pmap_extract(kernel_pmap, va) + == 0) + return (EFAULT); + + prot = (uio->uio_rw == UIO_READ) + ? VM_PROT_READ : VM_PROT_WRITE; + + va = uio->uio_offset; + if (kernacc((void *) va, iov->iov_len, prot) + == FALSE) + return (EFAULT); + + error = uiomove((void *)va, iov->iov_len, uio); + + continue; + } + } + + return (error); +} + +/* + * allow user processes to MMAP some memory sections + * instead of going through read/write + */ +int +memmmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int prot) +{ + /* + * /dev/mem is the only one that makes sense through this + * interface. For /dev/kmem any physaddr we return here + * could be transient and hence incorrect or invalid at + * a later time. + */ + if (minor(dev) != CDEV_MINOR_MEM) + return (-1); + + /* Only direct-mapped addresses. */ + if (mem_valid(offset, 0) + && pmap_dev_direct_mapped(offset, 0)) + return (EFAULT); + + *paddr = offset; + + return (0); +} + +void +dev_mem_md_init(void) +{ +} diff --git a/sys/powerpc/powerpc/mmu_if.m b/sys/powerpc/powerpc/mmu_if.m new file mode 100644 index 000000000000..0fc546fb14b2 --- /dev/null +++ b/sys/powerpc/powerpc/mmu_if.m @@ -0,0 +1,768 @@ +#- +# Copyright (c) 2005 Peter Grehan +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +#include <sys/param.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/systm.h> + +#include <vm/vm.h> +#include <vm/vm_page.h> + +#include <machine/mmuvar.h> + +/** + * @defgroup MMU mmu - KObj methods for PowerPC MMU implementations + * @brief A set of methods required by all MMU implementations. These + * are basically direct call-thru's from the pmap machine-dependent + * code. + * Thanks to Bruce M Simpson's pmap man pages for routine descriptions. + *@{ + */ + +INTERFACE mmu; + +# +# Default implementations of some methods +# +CODE { + static void mmu_null_copy(mmu_t mmu, pmap_t dst_pmap, pmap_t src_pmap, + vm_offset_t dst_addr, vm_size_t len, vm_offset_t src_addr) + { + return; + } + + static void mmu_null_growkernel(mmu_t mmu, vm_offset_t addr) + { + return; + } + + static void mmu_null_init(mmu_t mmu) + { + return; + } + + static boolean_t mmu_null_is_prefaultable(mmu_t mmu, pmap_t pmap, + vm_offset_t va) + { + return (FALSE); + } + + static void mmu_null_object_init_pt(mmu_t mmu, pmap_t pmap, + vm_offset_t addr, vm_object_t object, vm_pindex_t index, + vm_size_t size) + { + return; + } + + static void mmu_null_page_init(mmu_t mmu, vm_page_t m) + { + return; + } + + static void mmu_null_remove_pages(mmu_t mmu, pmap_t pmap) + { + return; + } + + static int mmu_null_mincore(mmu_t mmu, pmap_t pmap, vm_offset_t addr) + { + return (0); + } + + static void mmu_null_deactivate(struct thread *td) + { + return; + } + + static vm_offset_t mmu_null_addr_hint(mmu_t mmu, vm_object_t object, + vm_offset_t va, vm_size_t size) + { + return (va); + } +}; + + +/** + * @brief Change the wiring attribute for the page in the given physical + * map and virtual address. + * + * @param _pmap physical map of page + * @param _va page virtual address + * @param _wired TRUE to increment wired count, FALSE to decrement + */ +METHOD void change_wiring { + mmu_t _mmu; + pmap_t _pmap; + vm_offset_t _va; + boolean_t _wired; +}; + + +/** + * @brief Clear the 'modified' bit on the given physical page + * + * @param _pg physical page + */ +METHOD void clear_modify { + mmu_t _mmu; + vm_page_t _pg; +}; + + +/** + * @brief Clear the 'referenced' bit on the given physical page + * + * @param _pg physical page + */ +METHOD void clear_reference { + mmu_t _mmu; + vm_page_t _pg; +}; + + +/** + * @brief Clear the write and modified bits in each of the given + * physical page's mappings + * + * @param _pg physical page + */ +METHOD void remove_write { + mmu_t _mmu; + vm_page_t _pg; +}; + + +/** + * @brief Copy the address range given by the source physical map, virtual + * address and length to the destination physical map and virtual address. + * This routine is optional (xxx default null implementation ?) + * + * @param _dst_pmap destination physical map + * @param _src_pmap source physical map + * @param _dst_addr destination virtual address + * @param _len size of range + * @param _src_addr source virtual address + */ +METHOD void copy { + mmu_t _mmu; + pmap_t _dst_pmap; + pmap_t _src_pmap; + vm_offset_t _dst_addr; + vm_size_t _len; + vm_offset_t _src_addr; +} DEFAULT mmu_null_copy; + + +/** + * @brief Copy the source physical page to the destination physical page + * + * @param _src source physical page + * @param _dst destination physical page + */ +METHOD void copy_page { + mmu_t _mmu; + vm_page_t _src; + vm_page_t _dst; +}; + + +/** + * @brief Create a mapping between a virtual/physical address pair in the + * passed physical map with the specified protection and wiring + * + * @param _pmap physical map + * @param _va mapping virtual address + * @param _p mapping physical page + * @param _prot mapping page protection + * @param _wired TRUE if page will be wired + */ +METHOD void enter { + mmu_t _mmu; + pmap_t _pmap; + vm_offset_t _va; + vm_page_t _p; + vm_prot_t _prot; + boolean_t _wired; +}; + + +/** + * @brief Maps a sequence of resident pages belonging to the same object. + * + * @param _pmap physical map + * @param _start virtual range start + * @param _end virtual range end + * @param _m_start physical page mapped at start + * @param _prot mapping page protection + */ +METHOD void enter_object { + mmu_t _mmu; + pmap_t _pmap; + vm_offset_t _start; + vm_offset_t _end; + vm_page_t _m_start; + vm_prot_t _prot; +}; + + +/** + * @brief A faster entry point for page mapping where it is possible + * to short-circuit some of the tests in pmap_enter. + * + * @param _pmap physical map (and also currently active pmap) + * @param _va mapping virtual address + * @param _pg mapping physical page + * @param _prot new page protection - used to see if page is exec. + */ +METHOD void enter_quick { + mmu_t _mmu; + pmap_t _pmap; + vm_offset_t _va; + vm_page_t _pg; + vm_prot_t _prot; +}; + + +/** + * @brief Reverse map the given virtual address, returning the physical + * page associated with the address if a mapping exists. + * + * @param _pmap physical map + * @param _va mapping virtual address + * + * @retval 0 No mapping found + * @retval addr The mapping physical address + */ +METHOD vm_paddr_t extract { + mmu_t _mmu; + pmap_t _pmap; + vm_offset_t _va; +}; + + +/** + * @brief Reverse map the given virtual address, returning the + * physical page if found. The page must be held (by calling + * vm_page_hold) if the page protection matches the given protection + * + * @param _pmap physical map + * @param _va mapping virtual address + * @param _prot protection used to determine if physical page + * should be locked + * + * @retval NULL No mapping found + * @retval page Pointer to physical page. Held if protections match + */ +METHOD vm_page_t extract_and_hold { + mmu_t _mmu; + pmap_t _pmap; + vm_offset_t _va; + vm_prot_t _prot; +}; + + +/** + * @brief Increase kernel virtual address space to the given virtual address. + * Not really required for PowerPC, so optional unless the MMU implementation + * can use it. + * + * @param _va new upper limit for kernel virtual address space + */ +METHOD void growkernel { + mmu_t _mmu; + vm_offset_t _va; +} DEFAULT mmu_null_growkernel; + + +/** + * @brief Called from vm_mem_init. Zone allocation is available at + * this stage so a convenient time to create zones. This routine is + * for MMU-implementation convenience and is optional. + */ +METHOD void init { + mmu_t _mmu; +} DEFAULT mmu_null_init; + + +/** + * @brief Return if the page has been marked by MMU hardware to have been + * modified + * + * @param _pg physical page to test + * + * @retval boolean TRUE if page has been modified + */ +METHOD boolean_t is_modified { + mmu_t _mmu; + vm_page_t _pg; +}; + + +/** + * @brief Return whether the specified virtual address is a candidate to be + * prefaulted in. This routine is optional. + * + * @param _pmap physical map + * @param _va virtual address to test + * + * @retval boolean TRUE if the address is a candidate. + */ +METHOD boolean_t is_prefaultable { + mmu_t _mmu; + pmap_t _pmap; + vm_offset_t _va; +} DEFAULT mmu_null_is_prefaultable; + + +/** + * @brief Return a count of referenced bits for a page, clearing those bits. + * Not all referenced bits need to be cleared, but it is necessary that 0 + * only be returned when there are none set. + * + * @params _m physical page + * + * @retval int count of referenced bits + */ +METHOD boolean_t ts_referenced { + mmu_t _mmu; + vm_page_t _pg; +}; + + +/** + * @brief Map the requested physical address range into kernel virtual + * address space. The value in _virt is taken as a hint. The virtual + * address of the range is returned, or NULL if the mapping could not + * be created. The range can be direct-mapped if that is supported. + * + * @param *_virt Hint for start virtual address, and also return + * value + * @param _start physical address range start + * @param _end physical address range end + * @param _prot protection of range (currently ignored) + * + * @retval NULL could not map the area + * @retval addr, *_virt mapping start virtual address + */ +METHOD vm_offset_t map { + mmu_t _mmu; + vm_offset_t *_virt; + vm_paddr_t _start; + vm_paddr_t _end; + int _prot; +}; + + +/** + * @brief Used to create a contiguous set of read-only mappings for a + * given object to try and eliminate a cascade of on-demand faults as + * the object is accessed sequentially. This routine is optional. + * + * @param _pmap physical map + * @param _addr mapping start virtual address + * @param _object device-backed V.M. object to be mapped + * @param _pindex page-index within object of mapping start + * @param _size size in bytes of mapping + */ +METHOD void object_init_pt { + mmu_t _mmu; + pmap_t _pmap; + vm_offset_t _addr; + vm_object_t _object; + vm_pindex_t _pindex; + vm_size_t _size; +} DEFAULT mmu_null_object_init_pt; + + +/** + * @brief Used to determine if the specified page has a mapping for the + * given physical map, by scanning the list of reverse-mappings from the + * page. The list is scanned to a maximum of 16 entries. + * + * @param _pmap physical map + * @param _pg physical page + * + * @retval bool TRUE if the physical map was found in the first 16 + * reverse-map list entries off the physical page. + */ +METHOD boolean_t page_exists_quick { + mmu_t _mmu; + pmap_t _pmap; + vm_page_t _pg; +}; + + +/** + * @brief Initialise the machine-dependent section of the physical page + * data structure. This routine is optional. + * + * @param _pg physical page + */ +METHOD void page_init { + mmu_t _mmu; + vm_page_t _pg; +} DEFAULT mmu_null_page_init; + + +/** + * @brief Initialise a physical map data structure + * + * @param _pmap physical map + */ +METHOD void pinit { + mmu_t _mmu; + pmap_t _pmap; +}; + + +/** + * @brief Initialise the physical map for process 0, the initial process + * in the system. + * XXX default to pinit ? + * + * @param _pmap physical map + */ +METHOD void pinit0 { + mmu_t _mmu; + pmap_t _pmap; +}; + + +/** + * @brief Set the protection for physical pages in the given virtual address + * range to the given value. + * + * @param _pmap physical map + * @param _start virtual range start + * @param _end virtual range end + * @param _prot new page protection + */ +METHOD void protect { + mmu_t _mmu; + pmap_t _pmap; + vm_offset_t _start; + vm_offset_t _end; + vm_prot_t _prot; +}; + + +/** + * @brief Create a mapping in kernel virtual address space for the given array + * of wired physical pages. + * + * @param _start mapping virtual address start + * @param *_m array of physical page pointers + * @param _count array elements + */ +METHOD void qenter { + mmu_t _mmu; + vm_offset_t _start; + vm_page_t *_pg; + int _count; +}; + + +/** + * @brief Remove the temporary mappings created by qenter. + * + * @param _start mapping virtual address start + * @param _count number of pages in mapping + */ +METHOD void qremove { + mmu_t _mmu; + vm_offset_t _start; + int _count; +}; + + +/** + * @brief Release per-pmap resources, e.g. mutexes, allocated memory etc. There + * should be no existing mappings for the physical map at this point + * + * @param _pmap physical map + */ +METHOD void release { + mmu_t _mmu; + pmap_t _pmap; +}; + + +/** + * @brief Remove all mappings in the given physical map for the start/end + * virtual address range. The range will be page-aligned. + * + * @param _pmap physical map + * @param _start mapping virtual address start + * @param _end mapping virtual address end + */ +METHOD void remove { + mmu_t _mmu; + pmap_t _pmap; + vm_offset_t _start; + vm_offset_t _end; +}; + + +/** + * @brief Traverse the reverse-map list off the given physical page and + * remove all mappings. Clear the PG_WRITEABLE attribute from the page. + * + * @param _pg physical page + */ +METHOD void remove_all { + mmu_t _mmu; + vm_page_t _pg; +}; + + +/** + * @brief Remove all mappings in the given start/end virtual address range + * for the given physical map. Similar to the remove method, but it used + * when tearing down all mappings in an address space. This method is + * optional, since pmap_remove will be called for each valid vm_map in + * the address space later. + * + * @param _pmap physical map + * @param _start mapping virtual address start + * @param _end mapping virtual address end + */ +METHOD void remove_pages { + mmu_t _mmu; + pmap_t _pmap; +} DEFAULT mmu_null_remove_pages; + + +/** + * @brief Zero a physical page. It is not assumed that the page is mapped, + * so a temporary (or direct) mapping may need to be used. + * + * @param _pg physical page + */ +METHOD void zero_page { + mmu_t _mmu; + vm_page_t _pg; +}; + + +/** + * @brief Zero a portion of a physical page, starting at a given offset and + * for a given size (multiples of 512 bytes for 4k pages). + * + * @param _pg physical page + * @param _off byte offset from start of page + * @param _size size of area to zero + */ +METHOD void zero_page_area { + mmu_t _mmu; + vm_page_t _pg; + int _off; + int _size; +}; + + +/** + * @brief Called from the idle loop to zero pages. XXX I think locking + * constraints might be different here compared to zero_page. + * + * @param _pg physical page + */ +METHOD void zero_page_idle { + mmu_t _mmu; + vm_page_t _pg; +}; + + +/** + * @brief Extract mincore(2) information from a mapping. This routine is + * optional and is an optimisation: the mincore code will call is_modified + * and ts_referenced if no result is returned. + * + * @param _pmap physical map + * @param _addr page virtual address + * + * @retval 0 no result + * @retval non-zero mincore(2) flag values + */ +METHOD int mincore { + mmu_t _mmu; + pmap_t _pmap; + vm_offset_t _addr; +} DEFAULT mmu_null_mincore; + + +/** + * @brief Perform any operations required to allow a physical map to be used + * before it's address space is accessed. + * + * @param _td thread associated with physical map + */ +METHOD void activate { + mmu_t _mmu; + struct thread *_td; +}; + +/** + * @brief Perform any operations required to deactivate a physical map, + * for instance as it is context-switched out. + * + * @param _td thread associated with physical map + */ +METHOD void deactivate { + mmu_t _mmu; + struct thread *_td; +} DEFAULT mmu_null_deactivate; + +/** + * @brief Return a hint for the best virtual address to map a tentative + * virtual address range in a given VM object. The default is to just + * return the given tentative start address. + * + * @param _obj VM backing object + * @param _addr initial guess at virtual address + * @param _size size of virtual address range + */ +METHOD vm_offset_t addr_hint { + mmu_t _mmu; + vm_object_t _obj; + vm_offset_t _addr; + vm_size_t _size; +} DEFAULT mmu_null_addr_hint; + + + + +/** + * INTERNAL INTERFACES + */ + +/** + * @brief Bootstrap the VM system. At the completion of this routine, the + * kernel will be running in it's own address space with full control over + * paging. + * + * @param _start start of reserved memory (obsolete ???) + * @param _end end of reserved memory (obsolete ???) + * XXX I think the intent of these was to allow + * the memory used by kernel text+data+bss and + * loader variables/load-time kld's to be carved out + * of available physical mem. + * + */ +METHOD void bootstrap { + mmu_t _mmu; + vm_offset_t _start; + vm_offset_t _end; +}; + + +/** + * @brief Create a kernel mapping for a given physical address range. + * Called by bus code on behalf of device drivers. The mapping does not + * have to be a virtual address: it can be a direct-mapped physical address + * if that is supported by the MMU. + * + * @param _pa start physical address + * @param _size size in bytes of mapping + * + * @retval addr address of mapping. + */ +METHOD void * mapdev { + mmu_t _mmu; + vm_offset_t _pa; + vm_size_t _size; +}; + + +/** + * @brief Remove the mapping created by mapdev. Called when a driver + * is unloaded. + * + * @param _va Mapping address returned from mapdev + * @param _size size in bytes of mapping + */ +METHOD void unmapdev { + mmu_t _mmu; + vm_offset_t _va; + vm_size_t _size; +}; + + +/** + * @brief Reverse-map a kernel virtual address + * + * @param _va kernel virtual address to reverse-map + * + * @retval pa physical address corresponding to mapping + */ +METHOD vm_offset_t kextract { + mmu_t _mmu; + vm_offset_t _va; +}; + + +/** + * @brief Map a wired page into kernel virtual address space + * + * @param _va mapping virtual address + * @param _pa mapping physical address + */ +METHOD void kenter { + mmu_t _mmu; + vm_offset_t _va; + vm_offset_t _pa; +}; + + +/** + * @brief Determine if the given physical address range has been direct-mapped. + * + * @param _pa physical address start + * @param _size physical address range size + * + * @retval bool TRUE if the range is direct-mapped. + */ +METHOD boolean_t dev_direct_mapped { + mmu_t _mmu; + vm_offset_t _pa; + vm_size_t _size; +}; + + +/** + * @brief Evaluate if a physical page has an executable mapping + * + * @param _pg physical page + * + * @retval bool TRUE if a physical mapping exists for the given page. + */ +METHOD boolean_t page_executable { + mmu_t _mmu; + vm_page_t _pg; +}; + diff --git a/sys/powerpc/powerpc/mmu_oea.c b/sys/powerpc/powerpc/mmu_oea.c new file mode 100644 index 000000000000..d1a0faa9d50f --- /dev/null +++ b/sys/powerpc/powerpc/mmu_oea.c @@ -0,0 +1,2522 @@ +/*- + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matt Thomas <matt@3am-software.com> of Allegro Networks, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: pmap.c,v 1.28 2000/03/26 20:42:36 kleink Exp $ + */ +/*- + * Copyright (C) 2001 Benno Rice. + * 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 Benno Rice ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * Manages physical address maps. + * + * In addition to hardware address maps, this module is called upon to + * provide software-use-only maps which may or may not be stored in the + * same form as hardware maps. These pseudo-maps are used to store + * intermediate results from copy operations to and from address spaces. + * + * Since the information managed by this module is also stored by the + * logical address mapping module, this module may throw away valid virtual + * to physical mappings at almost any time. However, invalidations of + * mappings must be done as requested. + * + * In order to cope with hardware architectures which make virtual to + * physical map invalidates expensive, this module may delay invalidate + * reduced protection operations until such time as they are actually + * necessary. This module is given full information as to which processors + * are currently using which maps, and to when physical maps must be made + * correct. + */ + +#include "opt_kstack_pages.h" + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/ktr.h> +#include <sys/lock.h> +#include <sys/msgbuf.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/sysctl.h> +#include <sys/systm.h> +#include <sys/vmmeter.h> + +#include <dev/ofw/openfirm.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/vm_kern.h> +#include <vm/vm_page.h> +#include <vm/vm_map.h> +#include <vm/vm_object.h> +#include <vm/vm_extern.h> +#include <vm/vm_pageout.h> +#include <vm/vm_pager.h> +#include <vm/uma.h> + +#include <machine/cpu.h> +#include <machine/powerpc.h> +#include <machine/bat.h> +#include <machine/frame.h> +#include <machine/md_var.h> +#include <machine/psl.h> +#include <machine/pte.h> +#include <machine/sr.h> +#include <machine/mmuvar.h> + +#include "mmu_if.h" + +#define MOEA_DEBUG + +#define TODO panic("%s: not implemented", __func__); + +#define TLBIE(va) __asm __volatile("tlbie %0" :: "r"(va)) +#define TLBSYNC() __asm __volatile("tlbsync"); +#define SYNC() __asm __volatile("sync"); +#define EIEIO() __asm __volatile("eieio"); + +#define VSID_MAKE(sr, hash) ((sr) | (((hash) & 0xfffff) << 4)) +#define VSID_TO_SR(vsid) ((vsid) & 0xf) +#define VSID_TO_HASH(vsid) (((vsid) >> 4) & 0xfffff) + +#define PVO_PTEGIDX_MASK 0x007 /* which PTEG slot */ +#define PVO_PTEGIDX_VALID 0x008 /* slot is valid */ +#define PVO_WIRED 0x010 /* PVO entry is wired */ +#define PVO_MANAGED 0x020 /* PVO entry is managed */ +#define PVO_EXECUTABLE 0x040 /* PVO entry is executable */ +#define PVO_BOOTSTRAP 0x080 /* PVO entry allocated during + bootstrap */ +#define PVO_FAKE 0x100 /* fictitious phys page */ +#define PVO_VADDR(pvo) ((pvo)->pvo_vaddr & ~ADDR_POFF) +#define PVO_ISEXECUTABLE(pvo) ((pvo)->pvo_vaddr & PVO_EXECUTABLE) +#define PVO_ISFAKE(pvo) ((pvo)->pvo_vaddr & PVO_FAKE) +#define PVO_PTEGIDX_GET(pvo) ((pvo)->pvo_vaddr & PVO_PTEGIDX_MASK) +#define PVO_PTEGIDX_ISSET(pvo) ((pvo)->pvo_vaddr & PVO_PTEGIDX_VALID) +#define PVO_PTEGIDX_CLR(pvo) \ + ((void)((pvo)->pvo_vaddr &= ~(PVO_PTEGIDX_VALID|PVO_PTEGIDX_MASK))) +#define PVO_PTEGIDX_SET(pvo, i) \ + ((void)((pvo)->pvo_vaddr |= (i)|PVO_PTEGIDX_VALID)) + +#define MOEA_PVO_CHECK(pvo) + +struct ofw_map { + vm_offset_t om_va; + vm_size_t om_len; + vm_offset_t om_pa; + u_int om_mode; +}; + +/* + * Map of physical memory regions. + */ +static struct mem_region *regions; +static struct mem_region *pregions; +u_int phys_avail_count; +int regions_sz, pregions_sz; +static struct ofw_map *translations; + +extern struct pmap ofw_pmap; + + + +/* + * Lock for the pteg and pvo tables. + */ +struct mtx moea_table_mutex; + +/* + * PTEG data. + */ +static struct pteg *moea_pteg_table; +u_int moea_pteg_count; +u_int moea_pteg_mask; + +/* + * PVO data. + */ +struct pvo_head *moea_pvo_table; /* pvo entries by pteg index */ +struct pvo_head moea_pvo_kunmanaged = + LIST_HEAD_INITIALIZER(moea_pvo_kunmanaged); /* list of unmanaged pages */ +struct pvo_head moea_pvo_unmanaged = + LIST_HEAD_INITIALIZER(moea_pvo_unmanaged); /* list of unmanaged pages */ + +uma_zone_t moea_upvo_zone; /* zone for pvo entries for unmanaged pages */ +uma_zone_t moea_mpvo_zone; /* zone for pvo entries for managed pages */ + +#define BPVO_POOL_SIZE 32768 +static struct pvo_entry *moea_bpvo_pool; +static int moea_bpvo_pool_index = 0; + +#define VSID_NBPW (sizeof(u_int32_t) * 8) +static u_int moea_vsid_bitmap[NPMAPS / VSID_NBPW]; + +static boolean_t moea_initialized = FALSE; + +/* + * Statistics. + */ +u_int moea_pte_valid = 0; +u_int moea_pte_overflow = 0; +u_int moea_pte_replacements = 0; +u_int moea_pvo_entries = 0; +u_int moea_pvo_enter_calls = 0; +u_int moea_pvo_remove_calls = 0; +u_int moea_pte_spills = 0; +SYSCTL_INT(_machdep, OID_AUTO, moea_pte_valid, CTLFLAG_RD, &moea_pte_valid, + 0, ""); +SYSCTL_INT(_machdep, OID_AUTO, moea_pte_overflow, CTLFLAG_RD, + &moea_pte_overflow, 0, ""); +SYSCTL_INT(_machdep, OID_AUTO, moea_pte_replacements, CTLFLAG_RD, + &moea_pte_replacements, 0, ""); +SYSCTL_INT(_machdep, OID_AUTO, moea_pvo_entries, CTLFLAG_RD, &moea_pvo_entries, + 0, ""); +SYSCTL_INT(_machdep, OID_AUTO, moea_pvo_enter_calls, CTLFLAG_RD, + &moea_pvo_enter_calls, 0, ""); +SYSCTL_INT(_machdep, OID_AUTO, moea_pvo_remove_calls, CTLFLAG_RD, + &moea_pvo_remove_calls, 0, ""); +SYSCTL_INT(_machdep, OID_AUTO, moea_pte_spills, CTLFLAG_RD, + &moea_pte_spills, 0, ""); + +struct pvo_entry *moea_pvo_zeropage; +struct mtx moea_pvo_zeropage_mtx; + +vm_offset_t moea_rkva_start = VM_MIN_KERNEL_ADDRESS; +u_int moea_rkva_count = 4; + +/* + * Allocate physical memory for use in moea_bootstrap. + */ +static vm_offset_t moea_bootstrap_alloc(vm_size_t, u_int); + +/* + * PTE calls. + */ +static int moea_pte_insert(u_int, struct pte *); + +/* + * PVO calls. + */ +static int moea_pvo_enter(pmap_t, uma_zone_t, struct pvo_head *, + vm_offset_t, vm_offset_t, u_int, int); +static void moea_pvo_remove(struct pvo_entry *, int); +static struct pvo_entry *moea_pvo_find_va(pmap_t, vm_offset_t, int *); +static struct pte *moea_pvo_to_pte(const struct pvo_entry *, int); + +/* + * Utility routines. + */ +static void moea_enter_locked(pmap_t, vm_offset_t, vm_page_t, + vm_prot_t, boolean_t); +static struct pvo_entry *moea_rkva_alloc(mmu_t); +static void moea_pa_map(struct pvo_entry *, vm_offset_t, + struct pte *, int *); +static void moea_pa_unmap(struct pvo_entry *, struct pte *, int *); +static void moea_syncicache(vm_offset_t, vm_size_t); +static boolean_t moea_query_bit(vm_page_t, int); +static u_int moea_clear_bit(vm_page_t, int, int *); +static void moea_kremove(mmu_t, vm_offset_t); +static void tlbia(void); +int moea_pte_spill(vm_offset_t); + +/* + * Kernel MMU interface + */ +void moea_change_wiring(mmu_t, pmap_t, vm_offset_t, boolean_t); +void moea_clear_modify(mmu_t, vm_page_t); +void moea_clear_reference(mmu_t, vm_page_t); +void moea_copy_page(mmu_t, vm_page_t, vm_page_t); +void moea_enter(mmu_t, pmap_t, vm_offset_t, vm_page_t, vm_prot_t, boolean_t); +void moea_enter_object(mmu_t, pmap_t, vm_offset_t, vm_offset_t, vm_page_t, + vm_prot_t); +void moea_enter_quick(mmu_t, pmap_t, vm_offset_t, vm_page_t, vm_prot_t); +vm_paddr_t moea_extract(mmu_t, pmap_t, vm_offset_t); +vm_page_t moea_extract_and_hold(mmu_t, pmap_t, vm_offset_t, vm_prot_t); +void moea_init(mmu_t); +boolean_t moea_is_modified(mmu_t, vm_page_t); +boolean_t moea_ts_referenced(mmu_t, vm_page_t); +vm_offset_t moea_map(mmu_t, vm_offset_t *, vm_offset_t, vm_offset_t, int); +boolean_t moea_page_exists_quick(mmu_t, pmap_t, vm_page_t); +void moea_pinit(mmu_t, pmap_t); +void moea_pinit0(mmu_t, pmap_t); +void moea_protect(mmu_t, pmap_t, vm_offset_t, vm_offset_t, vm_prot_t); +void moea_qenter(mmu_t, vm_offset_t, vm_page_t *, int); +void moea_qremove(mmu_t, vm_offset_t, int); +void moea_release(mmu_t, pmap_t); +void moea_remove(mmu_t, pmap_t, vm_offset_t, vm_offset_t); +void moea_remove_all(mmu_t, vm_page_t); +void moea_remove_write(mmu_t, vm_page_t); +void moea_zero_page(mmu_t, vm_page_t); +void moea_zero_page_area(mmu_t, vm_page_t, int, int); +void moea_zero_page_idle(mmu_t, vm_page_t); +void moea_activate(mmu_t, struct thread *); +void moea_deactivate(mmu_t, struct thread *); +void moea_bootstrap(mmu_t, vm_offset_t, vm_offset_t); +void *moea_mapdev(mmu_t, vm_offset_t, vm_size_t); +void moea_unmapdev(mmu_t, vm_offset_t, vm_size_t); +vm_offset_t moea_kextract(mmu_t, vm_offset_t); +void moea_kenter(mmu_t, vm_offset_t, vm_offset_t); +boolean_t moea_dev_direct_mapped(mmu_t, vm_offset_t, vm_size_t); +boolean_t moea_page_executable(mmu_t, vm_page_t); + +static mmu_method_t moea_methods[] = { + MMUMETHOD(mmu_change_wiring, moea_change_wiring), + MMUMETHOD(mmu_clear_modify, moea_clear_modify), + MMUMETHOD(mmu_clear_reference, moea_clear_reference), + MMUMETHOD(mmu_copy_page, moea_copy_page), + MMUMETHOD(mmu_enter, moea_enter), + MMUMETHOD(mmu_enter_object, moea_enter_object), + MMUMETHOD(mmu_enter_quick, moea_enter_quick), + MMUMETHOD(mmu_extract, moea_extract), + MMUMETHOD(mmu_extract_and_hold, moea_extract_and_hold), + MMUMETHOD(mmu_init, moea_init), + MMUMETHOD(mmu_is_modified, moea_is_modified), + MMUMETHOD(mmu_ts_referenced, moea_ts_referenced), + MMUMETHOD(mmu_map, moea_map), + MMUMETHOD(mmu_page_exists_quick,moea_page_exists_quick), + MMUMETHOD(mmu_pinit, moea_pinit), + MMUMETHOD(mmu_pinit0, moea_pinit0), + MMUMETHOD(mmu_protect, moea_protect), + MMUMETHOD(mmu_qenter, moea_qenter), + MMUMETHOD(mmu_qremove, moea_qremove), + MMUMETHOD(mmu_release, moea_release), + MMUMETHOD(mmu_remove, moea_remove), + MMUMETHOD(mmu_remove_all, moea_remove_all), + MMUMETHOD(mmu_remove_write, moea_remove_write), + MMUMETHOD(mmu_zero_page, moea_zero_page), + MMUMETHOD(mmu_zero_page_area, moea_zero_page_area), + MMUMETHOD(mmu_zero_page_idle, moea_zero_page_idle), + MMUMETHOD(mmu_activate, moea_activate), + MMUMETHOD(mmu_deactivate, moea_deactivate), + + /* Internal interfaces */ + MMUMETHOD(mmu_bootstrap, moea_bootstrap), + MMUMETHOD(mmu_mapdev, moea_mapdev), + MMUMETHOD(mmu_unmapdev, moea_unmapdev), + MMUMETHOD(mmu_kextract, moea_kextract), + MMUMETHOD(mmu_kenter, moea_kenter), + MMUMETHOD(mmu_dev_direct_mapped,moea_dev_direct_mapped), + MMUMETHOD(mmu_page_executable, moea_page_executable), + + { 0, 0 } +}; + +static mmu_def_t oea_mmu = { + MMU_TYPE_OEA, + moea_methods, + 0 +}; +MMU_DEF(oea_mmu); + + +static __inline int +va_to_sr(u_int *sr, vm_offset_t va) +{ + return (sr[(uintptr_t)va >> ADDR_SR_SHFT]); +} + +static __inline u_int +va_to_pteg(u_int sr, vm_offset_t addr) +{ + u_int hash; + + hash = (sr & SR_VSID_MASK) ^ (((u_int)addr & ADDR_PIDX) >> + ADDR_PIDX_SHFT); + return (hash & moea_pteg_mask); +} + +static __inline struct pvo_head * +pa_to_pvoh(vm_offset_t pa, vm_page_t *pg_p) +{ + struct vm_page *pg; + + pg = PHYS_TO_VM_PAGE(pa); + + if (pg_p != NULL) + *pg_p = pg; + + if (pg == NULL) + return (&moea_pvo_unmanaged); + + return (&pg->md.mdpg_pvoh); +} + +static __inline struct pvo_head * +vm_page_to_pvoh(vm_page_t m) +{ + + return (&m->md.mdpg_pvoh); +} + +static __inline void +moea_attr_clear(vm_page_t m, int ptebit) +{ + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + m->md.mdpg_attrs &= ~ptebit; +} + +static __inline int +moea_attr_fetch(vm_page_t m) +{ + + return (m->md.mdpg_attrs); +} + +static __inline void +moea_attr_save(vm_page_t m, int ptebit) +{ + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + m->md.mdpg_attrs |= ptebit; +} + +static __inline int +moea_pte_compare(const struct pte *pt, const struct pte *pvo_pt) +{ + if (pt->pte_hi == pvo_pt->pte_hi) + return (1); + + return (0); +} + +static __inline int +moea_pte_match(struct pte *pt, u_int sr, vm_offset_t va, int which) +{ + return (pt->pte_hi & ~PTE_VALID) == + (((sr & SR_VSID_MASK) << PTE_VSID_SHFT) | + ((va >> ADDR_API_SHFT) & PTE_API) | which); +} + +static __inline void +moea_pte_create(struct pte *pt, u_int sr, vm_offset_t va, u_int pte_lo) +{ + + mtx_assert(&moea_table_mutex, MA_OWNED); + + /* + * Construct a PTE. Default to IMB initially. Valid bit only gets + * set when the real pte is set in memory. + * + * Note: Don't set the valid bit for correct operation of tlb update. + */ + pt->pte_hi = ((sr & SR_VSID_MASK) << PTE_VSID_SHFT) | + (((va & ADDR_PIDX) >> ADDR_API_SHFT) & PTE_API); + pt->pte_lo = pte_lo; +} + +static __inline void +moea_pte_synch(struct pte *pt, struct pte *pvo_pt) +{ + + mtx_assert(&moea_table_mutex, MA_OWNED); + pvo_pt->pte_lo |= pt->pte_lo & (PTE_REF | PTE_CHG); +} + +static __inline void +moea_pte_clear(struct pte *pt, vm_offset_t va, int ptebit) +{ + + mtx_assert(&moea_table_mutex, MA_OWNED); + + /* + * As shown in Section 7.6.3.2.3 + */ + pt->pte_lo &= ~ptebit; + TLBIE(va); + EIEIO(); + TLBSYNC(); + SYNC(); +} + +static __inline void +moea_pte_set(struct pte *pt, struct pte *pvo_pt) +{ + + mtx_assert(&moea_table_mutex, MA_OWNED); + pvo_pt->pte_hi |= PTE_VALID; + + /* + * Update the PTE as defined in section 7.6.3.1. + * Note that the REF/CHG bits are from pvo_pt and thus should havce + * been saved so this routine can restore them (if desired). + */ + pt->pte_lo = pvo_pt->pte_lo; + EIEIO(); + pt->pte_hi = pvo_pt->pte_hi; + SYNC(); + moea_pte_valid++; +} + +static __inline void +moea_pte_unset(struct pte *pt, struct pte *pvo_pt, vm_offset_t va) +{ + + mtx_assert(&moea_table_mutex, MA_OWNED); + pvo_pt->pte_hi &= ~PTE_VALID; + + /* + * Force the reg & chg bits back into the PTEs. + */ + SYNC(); + + /* + * Invalidate the pte. + */ + pt->pte_hi &= ~PTE_VALID; + + SYNC(); + TLBIE(va); + EIEIO(); + TLBSYNC(); + SYNC(); + + /* + * Save the reg & chg bits. + */ + moea_pte_synch(pt, pvo_pt); + moea_pte_valid--; +} + +static __inline void +moea_pte_change(struct pte *pt, struct pte *pvo_pt, vm_offset_t va) +{ + + /* + * Invalidate the PTE + */ + moea_pte_unset(pt, pvo_pt, va); + moea_pte_set(pt, pvo_pt); +} + +/* + * Quick sort callout for comparing memory regions. + */ +static int mr_cmp(const void *a, const void *b); +static int om_cmp(const void *a, const void *b); + +static int +mr_cmp(const void *a, const void *b) +{ + const struct mem_region *regiona; + const struct mem_region *regionb; + + regiona = a; + regionb = b; + if (regiona->mr_start < regionb->mr_start) + return (-1); + else if (regiona->mr_start > regionb->mr_start) + return (1); + else + return (0); +} + +static int +om_cmp(const void *a, const void *b) +{ + const struct ofw_map *mapa; + const struct ofw_map *mapb; + + mapa = a; + mapb = b; + if (mapa->om_pa < mapb->om_pa) + return (-1); + else if (mapa->om_pa > mapb->om_pa) + return (1); + else + return (0); +} + +void +moea_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend) +{ + ihandle_t mmui; + phandle_t chosen, mmu; + int sz; + int i, j; + int ofw_mappings; + vm_size_t size, physsz, hwphyssz; + vm_offset_t pa, va, off; + u_int batl, batu; + + /* + * Set up BAT0 to map the lowest 256 MB area + */ + battable[0x0].batl = BATL(0x00000000, BAT_M, BAT_PP_RW); + battable[0x0].batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs); + + /* + * Map PCI memory space. + */ + battable[0x8].batl = BATL(0x80000000, BAT_I|BAT_G, BAT_PP_RW); + battable[0x8].batu = BATU(0x80000000, BAT_BL_256M, BAT_Vs); + + battable[0x9].batl = BATL(0x90000000, BAT_I|BAT_G, BAT_PP_RW); + battable[0x9].batu = BATU(0x90000000, BAT_BL_256M, BAT_Vs); + + battable[0xa].batl = BATL(0xa0000000, BAT_I|BAT_G, BAT_PP_RW); + battable[0xa].batu = BATU(0xa0000000, BAT_BL_256M, BAT_Vs); + + battable[0xb].batl = BATL(0xb0000000, BAT_I|BAT_G, BAT_PP_RW); + battable[0xb].batu = BATU(0xb0000000, BAT_BL_256M, BAT_Vs); + + /* + * Map obio devices. + */ + battable[0xf].batl = BATL(0xf0000000, BAT_I|BAT_G, BAT_PP_RW); + battable[0xf].batu = BATU(0xf0000000, BAT_BL_256M, BAT_Vs); + + /* + * Use an IBAT and a DBAT to map the bottom segment of memory + * where we are. + */ + batu = BATU(0x00000000, BAT_BL_256M, BAT_Vs); + batl = BATL(0x00000000, BAT_M, BAT_PP_RW); + __asm (".balign 32; \n" + "mtibatu 0,%0; mtibatl 0,%1; isync; \n" + "mtdbatu 0,%0; mtdbatl 0,%1; isync" + :: "r"(batu), "r"(batl)); + +#if 0 + /* map frame buffer */ + batu = BATU(0x90000000, BAT_BL_256M, BAT_Vs); + batl = BATL(0x90000000, BAT_I|BAT_G, BAT_PP_RW); + __asm ("mtdbatu 1,%0; mtdbatl 1,%1; isync" + :: "r"(batu), "r"(batl)); +#endif + +#if 1 + /* map pci space */ + batu = BATU(0x80000000, BAT_BL_256M, BAT_Vs); + batl = BATL(0x80000000, BAT_I|BAT_G, BAT_PP_RW); + __asm ("mtdbatu 1,%0; mtdbatl 1,%1; isync" + :: "r"(batu), "r"(batl)); +#endif + + /* + * Set the start and end of kva. + */ + virtual_avail = VM_MIN_KERNEL_ADDRESS; + virtual_end = VM_MAX_KERNEL_ADDRESS; + + mem_regions(&pregions, &pregions_sz, ®ions, ®ions_sz); + CTR0(KTR_PMAP, "moea_bootstrap: physical memory"); + + qsort(pregions, pregions_sz, sizeof(*pregions), mr_cmp); + for (i = 0; i < pregions_sz; i++) { + vm_offset_t pa; + vm_offset_t end; + + CTR3(KTR_PMAP, "physregion: %#x - %#x (%#x)", + pregions[i].mr_start, + pregions[i].mr_start + pregions[i].mr_size, + pregions[i].mr_size); + /* + * Install entries into the BAT table to allow all + * of physmem to be convered by on-demand BAT entries. + * The loop will sometimes set the same battable element + * twice, but that's fine since they won't be used for + * a while yet. + */ + pa = pregions[i].mr_start & 0xf0000000; + end = pregions[i].mr_start + pregions[i].mr_size; + do { + u_int n = pa >> ADDR_SR_SHFT; + + battable[n].batl = BATL(pa, BAT_M, BAT_PP_RW); + battable[n].batu = BATU(pa, BAT_BL_256M, BAT_Vs); + pa += SEGMENT_LENGTH; + } while (pa < end); + } + + if (sizeof(phys_avail)/sizeof(phys_avail[0]) < regions_sz) + panic("moea_bootstrap: phys_avail too small"); + qsort(regions, regions_sz, sizeof(*regions), mr_cmp); + phys_avail_count = 0; + physsz = 0; + hwphyssz = 0; + TUNABLE_ULONG_FETCH("hw.physmem", (u_long *) &hwphyssz); + for (i = 0, j = 0; i < regions_sz; i++, j += 2) { + CTR3(KTR_PMAP, "region: %#x - %#x (%#x)", regions[i].mr_start, + regions[i].mr_start + regions[i].mr_size, + regions[i].mr_size); + if (hwphyssz != 0 && + (physsz + regions[i].mr_size) >= hwphyssz) { + if (physsz < hwphyssz) { + phys_avail[j] = regions[i].mr_start; + phys_avail[j + 1] = regions[i].mr_start + + hwphyssz - physsz; + physsz = hwphyssz; + phys_avail_count++; + } + break; + } + phys_avail[j] = regions[i].mr_start; + phys_avail[j + 1] = regions[i].mr_start + regions[i].mr_size; + phys_avail_count++; + physsz += regions[i].mr_size; + } + physmem = btoc(physsz); + + /* + * Allocate PTEG table. + */ +#ifdef PTEGCOUNT + moea_pteg_count = PTEGCOUNT; +#else + moea_pteg_count = 0x1000; + + while (moea_pteg_count < physmem) + moea_pteg_count <<= 1; + + moea_pteg_count >>= 1; +#endif /* PTEGCOUNT */ + + size = moea_pteg_count * sizeof(struct pteg); + CTR2(KTR_PMAP, "moea_bootstrap: %d PTEGs, %d bytes", moea_pteg_count, + size); + moea_pteg_table = (struct pteg *)moea_bootstrap_alloc(size, size); + CTR1(KTR_PMAP, "moea_bootstrap: PTEG table at %p", moea_pteg_table); + bzero((void *)moea_pteg_table, moea_pteg_count * sizeof(struct pteg)); + moea_pteg_mask = moea_pteg_count - 1; + + /* + * Allocate pv/overflow lists. + */ + size = sizeof(struct pvo_head) * moea_pteg_count; + moea_pvo_table = (struct pvo_head *)moea_bootstrap_alloc(size, + PAGE_SIZE); + CTR1(KTR_PMAP, "moea_bootstrap: PVO table at %p", moea_pvo_table); + for (i = 0; i < moea_pteg_count; i++) + LIST_INIT(&moea_pvo_table[i]); + + /* + * Initialize the lock that synchronizes access to the pteg and pvo + * tables. + */ + mtx_init(&moea_table_mutex, "pmap table", NULL, MTX_DEF | + MTX_RECURSE); + + /* + * Allocate the message buffer. + */ + msgbuf_phys = moea_bootstrap_alloc(MSGBUF_SIZE, 0); + + /* + * Initialise the unmanaged pvo pool. + */ + moea_bpvo_pool = (struct pvo_entry *)moea_bootstrap_alloc( + BPVO_POOL_SIZE*sizeof(struct pvo_entry), 0); + moea_bpvo_pool_index = 0; + + /* + * Make sure kernel vsid is allocated as well as VSID 0. + */ + moea_vsid_bitmap[(KERNEL_VSIDBITS & (NPMAPS - 1)) / VSID_NBPW] + |= 1 << (KERNEL_VSIDBITS % VSID_NBPW); + moea_vsid_bitmap[0] |= 1; + + /* + * Set up the Open Firmware pmap and add it's mappings. + */ + moea_pinit(mmup, &ofw_pmap); + ofw_pmap.pm_sr[KERNEL_SR] = KERNEL_SEGMENT; + ofw_pmap.pm_sr[KERNEL2_SR] = KERNEL2_SEGMENT; + if ((chosen = OF_finddevice("/chosen")) == -1) + panic("moea_bootstrap: can't find /chosen"); + OF_getprop(chosen, "mmu", &mmui, 4); + if ((mmu = OF_instance_to_package(mmui)) == -1) + panic("moea_bootstrap: can't get mmu package"); + if ((sz = OF_getproplen(mmu, "translations")) == -1) + panic("moea_bootstrap: can't get ofw translation count"); + translations = NULL; + for (i = 0; phys_avail[i] != 0; i += 2) { + if (phys_avail[i + 1] >= sz) { + translations = (struct ofw_map *)phys_avail[i]; + break; + } + } + if (translations == NULL) + panic("moea_bootstrap: no space to copy translations"); + bzero(translations, sz); + if (OF_getprop(mmu, "translations", translations, sz) == -1) + panic("moea_bootstrap: can't get ofw translations"); + CTR0(KTR_PMAP, "moea_bootstrap: translations"); + sz /= sizeof(*translations); + qsort(translations, sz, sizeof (*translations), om_cmp); + for (i = 0, ofw_mappings = 0; i < sz; i++) { + CTR3(KTR_PMAP, "translation: pa=%#x va=%#x len=%#x", + translations[i].om_pa, translations[i].om_va, + translations[i].om_len); + + /* + * If the mapping is 1:1, let the RAM and device on-demand + * BAT tables take care of the translation. + */ + if (translations[i].om_va == translations[i].om_pa) + continue; + + /* Enter the pages */ + for (off = 0; off < translations[i].om_len; off += PAGE_SIZE) { + struct vm_page m; + + m.phys_addr = translations[i].om_pa + off; + PMAP_LOCK(&ofw_pmap); + moea_enter_locked(&ofw_pmap, + translations[i].om_va + off, &m, + VM_PROT_ALL, 1); + PMAP_UNLOCK(&ofw_pmap); + ofw_mappings++; + } + } +#ifdef SMP + TLBSYNC(); +#endif + + /* + * Initialize the kernel pmap (which is statically allocated). + */ + PMAP_LOCK_INIT(kernel_pmap); + for (i = 0; i < 16; i++) { + kernel_pmap->pm_sr[i] = EMPTY_SEGMENT; + } + kernel_pmap->pm_sr[KERNEL_SR] = KERNEL_SEGMENT; + kernel_pmap->pm_sr[KERNEL2_SR] = KERNEL2_SEGMENT; + kernel_pmap->pm_active = ~0; + + /* + * Allocate a kernel stack with a guard page for thread0 and map it + * into the kernel page map. + */ + pa = moea_bootstrap_alloc(KSTACK_PAGES * PAGE_SIZE, 0); + kstack0_phys = pa; + kstack0 = virtual_avail + (KSTACK_GUARD_PAGES * PAGE_SIZE); + CTR2(KTR_PMAP, "moea_bootstrap: kstack0 at %#x (%#x)", kstack0_phys, + kstack0); + virtual_avail += (KSTACK_PAGES + KSTACK_GUARD_PAGES) * PAGE_SIZE; + for (i = 0; i < KSTACK_PAGES; i++) { + pa = kstack0_phys + i * PAGE_SIZE; + va = kstack0 + i * PAGE_SIZE; + moea_kenter(mmup, va, pa); + TLBIE(va); + } + + /* + * Calculate the last available physical address. + */ + for (i = 0; phys_avail[i + 2] != 0; i += 2) + ; + Maxmem = powerpc_btop(phys_avail[i + 1]); + + /* + * Allocate virtual address space for the message buffer. + */ + msgbufp = (struct msgbuf *)virtual_avail; + virtual_avail += round_page(MSGBUF_SIZE); + + /* + * Initialize hardware. + */ + for (i = 0; i < 16; i++) { + mtsrin(i << ADDR_SR_SHFT, EMPTY_SEGMENT); + } + __asm __volatile ("mtsr %0,%1" + :: "n"(KERNEL_SR), "r"(KERNEL_SEGMENT)); + __asm __volatile ("mtsr %0,%1" + :: "n"(KERNEL2_SR), "r"(KERNEL2_SEGMENT)); + __asm __volatile ("sync; mtsdr1 %0; isync" + :: "r"((u_int)moea_pteg_table | (moea_pteg_mask >> 10))); + tlbia(); + + pmap_bootstrapped++; +} + +/* + * Activate a user pmap. The pmap must be activated before it's address + * space can be accessed in any way. + */ +void +moea_activate(mmu_t mmu, struct thread *td) +{ + pmap_t pm, pmr; + + /* + * Load all the data we need up front to encourage the compiler to + * not issue any loads while we have interrupts disabled below. + */ + pm = &td->td_proc->p_vmspace->vm_pmap; + + if ((pmr = (pmap_t)moea_kextract(mmu, (vm_offset_t)pm)) == NULL) + pmr = pm; + + pm->pm_active |= PCPU_GET(cpumask); + PCPU_SET(curpmap, pmr); +} + +void +moea_deactivate(mmu_t mmu, struct thread *td) +{ + pmap_t pm; + + pm = &td->td_proc->p_vmspace->vm_pmap; + pm->pm_active &= ~(PCPU_GET(cpumask)); + PCPU_SET(curpmap, NULL); +} + +void +moea_change_wiring(mmu_t mmu, pmap_t pm, vm_offset_t va, boolean_t wired) +{ + struct pvo_entry *pvo; + + PMAP_LOCK(pm); + pvo = moea_pvo_find_va(pm, va & ~ADDR_POFF, NULL); + + if (pvo != NULL) { + if (wired) { + if ((pvo->pvo_vaddr & PVO_WIRED) == 0) + pm->pm_stats.wired_count++; + pvo->pvo_vaddr |= PVO_WIRED; + } else { + if ((pvo->pvo_vaddr & PVO_WIRED) != 0) + pm->pm_stats.wired_count--; + pvo->pvo_vaddr &= ~PVO_WIRED; + } + } + PMAP_UNLOCK(pm); +} + +void +moea_copy_page(mmu_t mmu, vm_page_t msrc, vm_page_t mdst) +{ + vm_offset_t dst; + vm_offset_t src; + + dst = VM_PAGE_TO_PHYS(mdst); + src = VM_PAGE_TO_PHYS(msrc); + + kcopy((void *)src, (void *)dst, PAGE_SIZE); +} + +/* + * Zero a page of physical memory by temporarily mapping it into the tlb. + */ +void +moea_zero_page(mmu_t mmu, vm_page_t m) +{ + vm_offset_t pa = VM_PAGE_TO_PHYS(m); + caddr_t va; + + if (pa < SEGMENT_LENGTH) { + va = (caddr_t) pa; + } else if (moea_initialized) { + if (moea_pvo_zeropage == NULL) { + moea_pvo_zeropage = moea_rkva_alloc(mmu); + mtx_init(&moea_pvo_zeropage_mtx, "pvo zero page", + NULL, MTX_DEF); + } + mtx_lock(&moea_pvo_zeropage_mtx); + moea_pa_map(moea_pvo_zeropage, pa, NULL, NULL); + va = (caddr_t)PVO_VADDR(moea_pvo_zeropage); + } else { + panic("moea_zero_page: can't zero pa %#x", pa); + } + + bzero(va, PAGE_SIZE); + + if (pa >= SEGMENT_LENGTH) { + moea_pa_unmap(moea_pvo_zeropage, NULL, NULL); + mtx_unlock(&moea_pvo_zeropage_mtx); + } +} + +void +moea_zero_page_area(mmu_t mmu, vm_page_t m, int off, int size) +{ + vm_offset_t pa = VM_PAGE_TO_PHYS(m); + caddr_t va; + + if (pa < SEGMENT_LENGTH) { + va = (caddr_t) pa; + } else if (moea_initialized) { + if (moea_pvo_zeropage == NULL) { + moea_pvo_zeropage = moea_rkva_alloc(mmu); + mtx_init(&moea_pvo_zeropage_mtx, "pvo zero page", + NULL, MTX_DEF); + } + mtx_lock(&moea_pvo_zeropage_mtx); + moea_pa_map(moea_pvo_zeropage, pa, NULL, NULL); + va = (caddr_t)PVO_VADDR(moea_pvo_zeropage); + } else { + panic("moea_zero_page: can't zero pa %#x", pa); + } + + bzero(va + off, size); + + if (pa >= SEGMENT_LENGTH) { + moea_pa_unmap(moea_pvo_zeropage, NULL, NULL); + mtx_unlock(&moea_pvo_zeropage_mtx); + } +} + +void +moea_zero_page_idle(mmu_t mmu, vm_page_t m) +{ + + moea_zero_page(mmu, m); +} + +/* + * Map the given physical page at the specified virtual address in the + * target pmap with the protection requested. If specified the page + * will be wired down. + */ +void +moea_enter(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, + boolean_t wired) +{ + + vm_page_lock_queues(); + PMAP_LOCK(pmap); + moea_enter_locked(pmap, va, m, prot, wired); + vm_page_unlock_queues(); + PMAP_UNLOCK(pmap); +} + +/* + * Map the given physical page at the specified virtual address in the + * target pmap with the protection requested. If specified the page + * will be wired down. + * + * The page queues and pmap must be locked. + */ +static void +moea_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot, + boolean_t wired) +{ + struct pvo_head *pvo_head; + uma_zone_t zone; + vm_page_t pg; + u_int pte_lo, pvo_flags, was_exec, i; + int error; + + if (!moea_initialized) { + pvo_head = &moea_pvo_kunmanaged; + zone = moea_upvo_zone; + pvo_flags = 0; + pg = NULL; + was_exec = PTE_EXEC; + } else { + pvo_head = vm_page_to_pvoh(m); + pg = m; + zone = moea_mpvo_zone; + pvo_flags = PVO_MANAGED; + was_exec = 0; + } + if (pmap_bootstrapped) + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + PMAP_LOCK_ASSERT(pmap, MA_OWNED); + + /* XXX change the pvo head for fake pages */ + if ((m->flags & PG_FICTITIOUS) == PG_FICTITIOUS) + pvo_head = &moea_pvo_kunmanaged; + + /* + * If this is a managed page, and it's the first reference to the page, + * clear the execness of the page. Otherwise fetch the execness. + */ + if ((pg != NULL) && ((m->flags & PG_FICTITIOUS) == 0)) { + if (LIST_EMPTY(pvo_head)) { + moea_attr_clear(pg, PTE_EXEC); + } else { + was_exec = moea_attr_fetch(pg) & PTE_EXEC; + } + } + + /* + * Assume the page is cache inhibited and access is guarded unless + * it's in our available memory array. + */ + pte_lo = PTE_I | PTE_G; + for (i = 0; i < pregions_sz; i++) { + if ((VM_PAGE_TO_PHYS(m) >= pregions[i].mr_start) && + (VM_PAGE_TO_PHYS(m) < + (pregions[i].mr_start + pregions[i].mr_size))) { + pte_lo &= ~(PTE_I | PTE_G); + break; + } + } + + if (prot & VM_PROT_WRITE) { + pte_lo |= PTE_BW; + if (pmap_bootstrapped) + vm_page_flag_set(m, PG_WRITEABLE); + } else + pte_lo |= PTE_BR; + + if (prot & VM_PROT_EXECUTE) + pvo_flags |= PVO_EXECUTABLE; + + if (wired) + pvo_flags |= PVO_WIRED; + + if ((m->flags & PG_FICTITIOUS) != 0) + pvo_flags |= PVO_FAKE; + + error = moea_pvo_enter(pmap, zone, pvo_head, va, VM_PAGE_TO_PHYS(m), + pte_lo, pvo_flags); + + /* + * Flush the real page from the instruction cache if this page is + * mapped executable and cacheable and was not previously mapped (or + * was not mapped executable). + */ + if (error == 0 && (pvo_flags & PVO_EXECUTABLE) && + (pte_lo & PTE_I) == 0 && was_exec == 0) { + /* + * Flush the real memory from the cache. + */ + moea_syncicache(VM_PAGE_TO_PHYS(m), PAGE_SIZE); + if (pg != NULL) + moea_attr_save(pg, PTE_EXEC); + } + + /* XXX syncicache always until problems are sorted */ + moea_syncicache(VM_PAGE_TO_PHYS(m), PAGE_SIZE); +} + +/* + * Maps a sequence of resident pages belonging to the same object. + * The sequence begins with the given page m_start. This page is + * mapped at the given virtual address start. Each subsequent page is + * mapped at a virtual address that is offset from start by the same + * amount as the page is offset from m_start within the object. The + * last page in the sequence is the page with the largest offset from + * m_start that can be mapped at a virtual address less than the given + * virtual address end. Not every virtual page between start and end + * is mapped; only those for which a resident page exists with the + * corresponding offset from m_start are mapped. + */ +void +moea_enter_object(mmu_t mmu, pmap_t pm, vm_offset_t start, vm_offset_t end, + vm_page_t m_start, vm_prot_t prot) +{ + vm_page_t m; + vm_pindex_t diff, psize; + + psize = atop(end - start); + m = m_start; + PMAP_LOCK(pm); + while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) { + moea_enter_locked(pm, start + ptoa(diff), m, prot & + (VM_PROT_READ | VM_PROT_EXECUTE), FALSE); + m = TAILQ_NEXT(m, listq); + } + PMAP_UNLOCK(pm); +} + +void +moea_enter_quick(mmu_t mmu, pmap_t pm, vm_offset_t va, vm_page_t m, + vm_prot_t prot) +{ + + PMAP_LOCK(pm); + moea_enter_locked(pm, va, m, prot & (VM_PROT_READ | VM_PROT_EXECUTE), + FALSE); + PMAP_UNLOCK(pm); + +} + +vm_paddr_t +moea_extract(mmu_t mmu, pmap_t pm, vm_offset_t va) +{ + struct pvo_entry *pvo; + vm_paddr_t pa; + + PMAP_LOCK(pm); + pvo = moea_pvo_find_va(pm, va & ~ADDR_POFF, NULL); + if (pvo == NULL) + pa = 0; + else + pa = (pvo->pvo_pte.pte_lo & PTE_RPGN) | (va & ADDR_POFF); + PMAP_UNLOCK(pm); + return (pa); +} + +/* + * Atomically extract and hold the physical page with the given + * pmap and virtual address pair if that mapping permits the given + * protection. + */ +vm_page_t +moea_extract_and_hold(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_prot_t prot) +{ + struct pvo_entry *pvo; + vm_page_t m; + + m = NULL; + vm_page_lock_queues(); + PMAP_LOCK(pmap); + pvo = moea_pvo_find_va(pmap, va & ~ADDR_POFF, NULL); + if (pvo != NULL && (pvo->pvo_pte.pte_hi & PTE_VALID) && + ((pvo->pvo_pte.pte_lo & PTE_PP) == PTE_RW || + (prot & VM_PROT_WRITE) == 0)) { + m = PHYS_TO_VM_PAGE(pvo->pvo_pte.pte_lo & PTE_RPGN); + vm_page_hold(m); + } + vm_page_unlock_queues(); + PMAP_UNLOCK(pmap); + return (m); +} + +void +moea_init(mmu_t mmu) +{ + + CTR0(KTR_PMAP, "moea_init"); + + moea_upvo_zone = uma_zcreate("UPVO entry", sizeof (struct pvo_entry), + NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, + UMA_ZONE_VM | UMA_ZONE_NOFREE); + moea_mpvo_zone = uma_zcreate("MPVO entry", sizeof(struct pvo_entry), + NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, + UMA_ZONE_VM | UMA_ZONE_NOFREE); + moea_initialized = TRUE; +} + +boolean_t +moea_is_modified(mmu_t mmu, vm_page_t m) +{ + + if ((m->flags & (PG_FICTITIOUS |PG_UNMANAGED)) != 0) + return (FALSE); + + return (moea_query_bit(m, PTE_CHG)); +} + +void +moea_clear_reference(mmu_t mmu, vm_page_t m) +{ + + if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0) + return; + moea_clear_bit(m, PTE_REF, NULL); +} + +void +moea_clear_modify(mmu_t mmu, vm_page_t m) +{ + + if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0) + return; + moea_clear_bit(m, PTE_CHG, NULL); +} + +/* + * Clear the write and modified bits in each of the given page's mappings. + */ +void +moea_remove_write(mmu_t mmu, vm_page_t m) +{ + struct pvo_entry *pvo; + struct pte *pt; + pmap_t pmap; + u_int lo; + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0 || + (m->flags & PG_WRITEABLE) == 0) + return; + lo = moea_attr_fetch(m); + SYNC(); + LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) { + pmap = pvo->pvo_pmap; + PMAP_LOCK(pmap); + if ((pvo->pvo_pte.pte_lo & PTE_PP) != PTE_BR) { + pt = moea_pvo_to_pte(pvo, -1); + pvo->pvo_pte.pte_lo &= ~PTE_PP; + pvo->pvo_pte.pte_lo |= PTE_BR; + if (pt != NULL) { + moea_pte_synch(pt, &pvo->pvo_pte); + lo |= pvo->pvo_pte.pte_lo; + pvo->pvo_pte.pte_lo &= ~PTE_CHG; + moea_pte_change(pt, &pvo->pvo_pte, + pvo->pvo_vaddr); + mtx_unlock(&moea_table_mutex); + } + } + PMAP_UNLOCK(pmap); + } + if ((lo & PTE_CHG) != 0) { + moea_attr_clear(m, PTE_CHG); + vm_page_dirty(m); + } + vm_page_flag_clear(m, PG_WRITEABLE); +} + +/* + * moea_ts_referenced: + * + * Return a count of reference bits for a page, clearing those bits. + * It is not necessary for every reference bit to be cleared, but it + * is necessary that 0 only be returned when there are truly no + * reference bits set. + * + * XXX: The exact number of bits to check and clear is a matter that + * should be tested and standardized at some point in the future for + * optimal aging of shared pages. + */ +boolean_t +moea_ts_referenced(mmu_t mmu, vm_page_t m) +{ + int count; + + if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0) + return (0); + + count = moea_clear_bit(m, PTE_REF, NULL); + + return (count); +} + +/* + * Map a wired page into kernel virtual address space. + */ +void +moea_kenter(mmu_t mmu, vm_offset_t va, vm_offset_t pa) +{ + u_int pte_lo; + int error; + int i; + +#if 0 + if (va < VM_MIN_KERNEL_ADDRESS) + panic("moea_kenter: attempt to enter non-kernel address %#x", + va); +#endif + + pte_lo = PTE_I | PTE_G; + for (i = 0; i < pregions_sz; i++) { + if ((pa >= pregions[i].mr_start) && + (pa < (pregions[i].mr_start + pregions[i].mr_size))) { + pte_lo &= ~(PTE_I | PTE_G); + break; + } + } + + PMAP_LOCK(kernel_pmap); + error = moea_pvo_enter(kernel_pmap, moea_upvo_zone, + &moea_pvo_kunmanaged, va, pa, pte_lo, PVO_WIRED); + + if (error != 0 && error != ENOENT) + panic("moea_kenter: failed to enter va %#x pa %#x: %d", va, + pa, error); + + /* + * Flush the real memory from the instruction cache. + */ + if ((pte_lo & (PTE_I | PTE_G)) == 0) { + moea_syncicache(pa, PAGE_SIZE); + } + PMAP_UNLOCK(kernel_pmap); +} + +/* + * Extract the physical page address associated with the given kernel virtual + * address. + */ +vm_offset_t +moea_kextract(mmu_t mmu, vm_offset_t va) +{ + struct pvo_entry *pvo; + vm_paddr_t pa; + +#ifdef UMA_MD_SMALL_ALLOC + /* + * Allow direct mappings + */ + if (va < VM_MIN_KERNEL_ADDRESS) { + return (va); + } +#endif + + PMAP_LOCK(kernel_pmap); + pvo = moea_pvo_find_va(kernel_pmap, va & ~ADDR_POFF, NULL); + KASSERT(pvo != NULL, ("moea_kextract: no addr found")); + pa = (pvo->pvo_pte.pte_lo & PTE_RPGN) | (va & ADDR_POFF); + PMAP_UNLOCK(kernel_pmap); + return (pa); +} + +/* + * Remove a wired page from kernel virtual address space. + */ +void +moea_kremove(mmu_t mmu, vm_offset_t va) +{ + + moea_remove(mmu, kernel_pmap, va, va + PAGE_SIZE); +} + +/* + * Map a range of physical addresses into kernel virtual address space. + * + * The value passed in *virt is a suggested virtual address for the mapping. + * Architectures which can support a direct-mapped physical to virtual region + * can return the appropriate address within that region, leaving '*virt' + * unchanged. We cannot and therefore do not; *virt is updated with the + * first usable address after the mapped region. + */ +vm_offset_t +moea_map(mmu_t mmu, vm_offset_t *virt, vm_offset_t pa_start, + vm_offset_t pa_end, int prot) +{ + vm_offset_t sva, va; + + sva = *virt; + va = sva; + for (; pa_start < pa_end; pa_start += PAGE_SIZE, va += PAGE_SIZE) + moea_kenter(mmu, va, pa_start); + *virt = va; + return (sva); +} + +/* + * Returns true if the pmap's pv is one of the first + * 16 pvs linked to from this page. This count may + * be changed upwards or downwards in the future; it + * is only necessary that true be returned for a small + * subset of pmaps for proper page aging. + */ +boolean_t +moea_page_exists_quick(mmu_t mmu, pmap_t pmap, vm_page_t m) +{ + int loops; + struct pvo_entry *pvo; + + if (!moea_initialized || (m->flags & PG_FICTITIOUS)) + return FALSE; + + loops = 0; + LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) { + if (pvo->pvo_pmap == pmap) + return (TRUE); + if (++loops >= 16) + break; + } + + return (FALSE); +} + +static u_int moea_vsidcontext; + +void +moea_pinit(mmu_t mmu, pmap_t pmap) +{ + int i, mask; + u_int entropy; + + KASSERT((int)pmap < VM_MIN_KERNEL_ADDRESS, ("moea_pinit: virt pmap")); + PMAP_LOCK_INIT(pmap); + + entropy = 0; + __asm __volatile("mftb %0" : "=r"(entropy)); + + /* + * Allocate some segment registers for this pmap. + */ + for (i = 0; i < NPMAPS; i += VSID_NBPW) { + u_int hash, n; + + /* + * Create a new value by mutiplying by a prime and adding in + * entropy from the timebase register. This is to make the + * VSID more random so that the PT hash function collides + * less often. (Note that the prime casues gcc to do shifts + * instead of a multiply.) + */ + moea_vsidcontext = (moea_vsidcontext * 0x1105) + entropy; + hash = moea_vsidcontext & (NPMAPS - 1); + if (hash == 0) /* 0 is special, avoid it */ + continue; + n = hash >> 5; + mask = 1 << (hash & (VSID_NBPW - 1)); + hash = (moea_vsidcontext & 0xfffff); + if (moea_vsid_bitmap[n] & mask) { /* collision? */ + /* anything free in this bucket? */ + if (moea_vsid_bitmap[n] == 0xffffffff) { + entropy = (moea_vsidcontext >> 20); + continue; + } + i = ffs(~moea_vsid_bitmap[i]) - 1; + mask = 1 << i; + hash &= 0xfffff & ~(VSID_NBPW - 1); + hash |= i; + } + moea_vsid_bitmap[n] |= mask; + for (i = 0; i < 16; i++) + pmap->pm_sr[i] = VSID_MAKE(i, hash); + return; + } + + panic("moea_pinit: out of segments"); +} + +/* + * Initialize the pmap associated with process 0. + */ +void +moea_pinit0(mmu_t mmu, pmap_t pm) +{ + + moea_pinit(mmu, pm); + bzero(&pm->pm_stats, sizeof(pm->pm_stats)); +} + +/* + * Set the physical protection on the specified range of this map as requested. + */ +void +moea_protect(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva, + vm_prot_t prot) +{ + struct pvo_entry *pvo; + struct pte *pt; + int pteidx; + + CTR4(KTR_PMAP, "moea_protect: pm=%p sva=%#x eva=%#x prot=%#x", pm, sva, + eva, prot); + + + KASSERT(pm == &curproc->p_vmspace->vm_pmap || pm == kernel_pmap, + ("moea_protect: non current pmap")); + + if ((prot & VM_PROT_READ) == VM_PROT_NONE) { + moea_remove(mmu, pm, sva, eva); + return; + } + + vm_page_lock_queues(); + PMAP_LOCK(pm); + for (; sva < eva; sva += PAGE_SIZE) { + pvo = moea_pvo_find_va(pm, sva, &pteidx); + if (pvo == NULL) + continue; + + if ((prot & VM_PROT_EXECUTE) == 0) + pvo->pvo_vaddr &= ~PVO_EXECUTABLE; + + /* + * Grab the PTE pointer before we diddle with the cached PTE + * copy. + */ + pt = moea_pvo_to_pte(pvo, pteidx); + /* + * Change the protection of the page. + */ + pvo->pvo_pte.pte_lo &= ~PTE_PP; + pvo->pvo_pte.pte_lo |= PTE_BR; + + /* + * If the PVO is in the page table, update that pte as well. + */ + if (pt != NULL) { + moea_pte_change(pt, &pvo->pvo_pte, pvo->pvo_vaddr); + mtx_unlock(&moea_table_mutex); + } + } + vm_page_unlock_queues(); + PMAP_UNLOCK(pm); +} + +/* + * Map a list of wired pages into kernel virtual address space. This is + * intended for temporary mappings which do not need page modification or + * references recorded. Existing mappings in the region are overwritten. + */ +void +moea_qenter(mmu_t mmu, vm_offset_t sva, vm_page_t *m, int count) +{ + vm_offset_t va; + + va = sva; + while (count-- > 0) { + moea_kenter(mmu, va, VM_PAGE_TO_PHYS(*m)); + va += PAGE_SIZE; + m++; + } +} + +/* + * Remove page mappings from kernel virtual address space. Intended for + * temporary mappings entered by moea_qenter. + */ +void +moea_qremove(mmu_t mmu, vm_offset_t sva, int count) +{ + vm_offset_t va; + + va = sva; + while (count-- > 0) { + moea_kremove(mmu, va); + va += PAGE_SIZE; + } +} + +void +moea_release(mmu_t mmu, pmap_t pmap) +{ + int idx, mask; + + /* + * Free segment register's VSID + */ + if (pmap->pm_sr[0] == 0) + panic("moea_release"); + + idx = VSID_TO_HASH(pmap->pm_sr[0]) & (NPMAPS-1); + mask = 1 << (idx % VSID_NBPW); + idx /= VSID_NBPW; + moea_vsid_bitmap[idx] &= ~mask; + PMAP_LOCK_DESTROY(pmap); +} + +/* + * Remove the given range of addresses from the specified map. + */ +void +moea_remove(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva) +{ + struct pvo_entry *pvo; + int pteidx; + + vm_page_lock_queues(); + PMAP_LOCK(pm); + for (; sva < eva; sva += PAGE_SIZE) { + pvo = moea_pvo_find_va(pm, sva, &pteidx); + if (pvo != NULL) { + moea_pvo_remove(pvo, pteidx); + } + } + PMAP_UNLOCK(pm); + vm_page_unlock_queues(); +} + +/* + * Remove physical page from all pmaps in which it resides. moea_pvo_remove() + * will reflect changes in pte's back to the vm_page. + */ +void +moea_remove_all(mmu_t mmu, vm_page_t m) +{ + struct pvo_head *pvo_head; + struct pvo_entry *pvo, *next_pvo; + pmap_t pmap; + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + + pvo_head = vm_page_to_pvoh(m); + for (pvo = LIST_FIRST(pvo_head); pvo != NULL; pvo = next_pvo) { + next_pvo = LIST_NEXT(pvo, pvo_vlink); + + MOEA_PVO_CHECK(pvo); /* sanity check */ + pmap = pvo->pvo_pmap; + PMAP_LOCK(pmap); + moea_pvo_remove(pvo, -1); + PMAP_UNLOCK(pmap); + } + vm_page_flag_clear(m, PG_WRITEABLE); +} + +/* + * Allocate a physical page of memory directly from the phys_avail map. + * Can only be called from moea_bootstrap before avail start and end are + * calculated. + */ +static vm_offset_t +moea_bootstrap_alloc(vm_size_t size, u_int align) +{ + vm_offset_t s, e; + int i, j; + + size = round_page(size); + for (i = 0; phys_avail[i + 1] != 0; i += 2) { + if (align != 0) + s = (phys_avail[i] + align - 1) & ~(align - 1); + else + s = phys_avail[i]; + e = s + size; + + if (s < phys_avail[i] || e > phys_avail[i + 1]) + continue; + + if (s == phys_avail[i]) { + phys_avail[i] += size; + } else if (e == phys_avail[i + 1]) { + phys_avail[i + 1] -= size; + } else { + for (j = phys_avail_count * 2; j > i; j -= 2) { + phys_avail[j] = phys_avail[j - 2]; + phys_avail[j + 1] = phys_avail[j - 1]; + } + + phys_avail[i + 3] = phys_avail[i + 1]; + phys_avail[i + 1] = s; + phys_avail[i + 2] = e; + phys_avail_count++; + } + + return (s); + } + panic("moea_bootstrap_alloc: could not allocate memory"); +} + +/* + * Return an unmapped pvo for a kernel virtual address. + * Used by pmap functions that operate on physical pages. + */ +static struct pvo_entry * +moea_rkva_alloc(mmu_t mmu) +{ + struct pvo_entry *pvo; + struct pte *pt; + vm_offset_t kva; + int pteidx; + + if (moea_rkva_count == 0) + panic("moea_rkva_alloc: no more reserved KVAs"); + + kva = moea_rkva_start + (PAGE_SIZE * --moea_rkva_count); + moea_kenter(mmu, kva, 0); + + pvo = moea_pvo_find_va(kernel_pmap, kva, &pteidx); + + if (pvo == NULL) + panic("moea_kva_alloc: moea_pvo_find_va failed"); + + pt = moea_pvo_to_pte(pvo, pteidx); + + if (pt == NULL) + panic("moea_kva_alloc: moea_pvo_to_pte failed"); + + moea_pte_unset(pt, &pvo->pvo_pte, pvo->pvo_vaddr); + mtx_unlock(&moea_table_mutex); + PVO_PTEGIDX_CLR(pvo); + + moea_pte_overflow++; + + return (pvo); +} + +static void +moea_pa_map(struct pvo_entry *pvo, vm_offset_t pa, struct pte *saved_pt, + int *depth_p) +{ + struct pte *pt; + + /* + * If this pvo already has a valid pte, we need to save it so it can + * be restored later. We then just reload the new PTE over the old + * slot. + */ + if (saved_pt != NULL) { + pt = moea_pvo_to_pte(pvo, -1); + + if (pt != NULL) { + moea_pte_unset(pt, &pvo->pvo_pte, pvo->pvo_vaddr); + mtx_unlock(&moea_table_mutex); + PVO_PTEGIDX_CLR(pvo); + moea_pte_overflow++; + } + + *saved_pt = pvo->pvo_pte; + + pvo->pvo_pte.pte_lo &= ~PTE_RPGN; + } + + pvo->pvo_pte.pte_lo |= pa; + + if (!moea_pte_spill(pvo->pvo_vaddr)) + panic("moea_pa_map: could not spill pvo %p", pvo); + + if (depth_p != NULL) + (*depth_p)++; +} + +static void +moea_pa_unmap(struct pvo_entry *pvo, struct pte *saved_pt, int *depth_p) +{ + struct pte *pt; + + pt = moea_pvo_to_pte(pvo, -1); + + if (pt != NULL) { + moea_pte_unset(pt, &pvo->pvo_pte, pvo->pvo_vaddr); + mtx_unlock(&moea_table_mutex); + PVO_PTEGIDX_CLR(pvo); + moea_pte_overflow++; + } + + pvo->pvo_pte.pte_lo &= ~PTE_RPGN; + + /* + * If there is a saved PTE and it's valid, restore it and return. + */ + if (saved_pt != NULL && (saved_pt->pte_lo & PTE_RPGN) != 0) { + if (depth_p != NULL && --(*depth_p) == 0) + panic("moea_pa_unmap: restoring but depth == 0"); + + pvo->pvo_pte = *saved_pt; + + if (!moea_pte_spill(pvo->pvo_vaddr)) + panic("moea_pa_unmap: could not spill pvo %p", pvo); + } +} + +static void +moea_syncicache(vm_offset_t pa, vm_size_t len) +{ + __syncicache((void *)pa, len); +} + +static void +tlbia(void) +{ + caddr_t i; + + SYNC(); + for (i = 0; i < (caddr_t)0x00040000; i += 0x00001000) { + TLBIE(i); + EIEIO(); + } + TLBSYNC(); + SYNC(); +} + +static int +moea_pvo_enter(pmap_t pm, uma_zone_t zone, struct pvo_head *pvo_head, + vm_offset_t va, vm_offset_t pa, u_int pte_lo, int flags) +{ + struct pvo_entry *pvo; + u_int sr; + int first; + u_int ptegidx; + int i; + int bootstrap; + + moea_pvo_enter_calls++; + first = 0; + bootstrap = 0; + + /* + * Compute the PTE Group index. + */ + va &= ~ADDR_POFF; + sr = va_to_sr(pm->pm_sr, va); + ptegidx = va_to_pteg(sr, va); + + /* + * Remove any existing mapping for this page. Reuse the pvo entry if + * there is a mapping. + */ + mtx_lock(&moea_table_mutex); + LIST_FOREACH(pvo, &moea_pvo_table[ptegidx], pvo_olink) { + if (pvo->pvo_pmap == pm && PVO_VADDR(pvo) == va) { + if ((pvo->pvo_pte.pte_lo & PTE_RPGN) == pa && + (pvo->pvo_pte.pte_lo & PTE_PP) == + (pte_lo & PTE_PP)) { + mtx_unlock(&moea_table_mutex); + return (0); + } + moea_pvo_remove(pvo, -1); + break; + } + } + + /* + * If we aren't overwriting a mapping, try to allocate. + */ + if (moea_initialized) { + pvo = uma_zalloc(zone, M_NOWAIT); + } else { + if (moea_bpvo_pool_index >= BPVO_POOL_SIZE) { + panic("moea_enter: bpvo pool exhausted, %d, %d, %d", + moea_bpvo_pool_index, BPVO_POOL_SIZE, + BPVO_POOL_SIZE * sizeof(struct pvo_entry)); + } + pvo = &moea_bpvo_pool[moea_bpvo_pool_index]; + moea_bpvo_pool_index++; + bootstrap = 1; + } + + if (pvo == NULL) { + mtx_unlock(&moea_table_mutex); + return (ENOMEM); + } + + moea_pvo_entries++; + pvo->pvo_vaddr = va; + pvo->pvo_pmap = pm; + LIST_INSERT_HEAD(&moea_pvo_table[ptegidx], pvo, pvo_olink); + pvo->pvo_vaddr &= ~ADDR_POFF; + if (flags & VM_PROT_EXECUTE) + pvo->pvo_vaddr |= PVO_EXECUTABLE; + if (flags & PVO_WIRED) + pvo->pvo_vaddr |= PVO_WIRED; + if (pvo_head != &moea_pvo_kunmanaged) + pvo->pvo_vaddr |= PVO_MANAGED; + if (bootstrap) + pvo->pvo_vaddr |= PVO_BOOTSTRAP; + if (flags & PVO_FAKE) + pvo->pvo_vaddr |= PVO_FAKE; + + moea_pte_create(&pvo->pvo_pte, sr, va, pa | pte_lo); + + /* + * Remember if the list was empty and therefore will be the first + * item. + */ + if (LIST_FIRST(pvo_head) == NULL) + first = 1; + LIST_INSERT_HEAD(pvo_head, pvo, pvo_vlink); + + if (pvo->pvo_pte.pte_lo & PVO_WIRED) + pm->pm_stats.wired_count++; + pm->pm_stats.resident_count++; + + /* + * We hope this succeeds but it isn't required. + */ + i = moea_pte_insert(ptegidx, &pvo->pvo_pte); + if (i >= 0) { + PVO_PTEGIDX_SET(pvo, i); + } else { + panic("moea_pvo_enter: overflow"); + moea_pte_overflow++; + } + mtx_unlock(&moea_table_mutex); + + return (first ? ENOENT : 0); +} + +static void +moea_pvo_remove(struct pvo_entry *pvo, int pteidx) +{ + struct pte *pt; + + /* + * If there is an active pte entry, we need to deactivate it (and + * save the ref & cfg bits). + */ + pt = moea_pvo_to_pte(pvo, pteidx); + if (pt != NULL) { + moea_pte_unset(pt, &pvo->pvo_pte, pvo->pvo_vaddr); + mtx_unlock(&moea_table_mutex); + PVO_PTEGIDX_CLR(pvo); + } else { + moea_pte_overflow--; + } + + /* + * Update our statistics. + */ + pvo->pvo_pmap->pm_stats.resident_count--; + if (pvo->pvo_pte.pte_lo & PVO_WIRED) + pvo->pvo_pmap->pm_stats.wired_count--; + + /* + * Save the REF/CHG bits into their cache if the page is managed. + */ + if ((pvo->pvo_vaddr & (PVO_MANAGED|PVO_FAKE)) == PVO_MANAGED) { + struct vm_page *pg; + + pg = PHYS_TO_VM_PAGE(pvo->pvo_pte.pte_lo & PTE_RPGN); + if (pg != NULL) { + moea_attr_save(pg, pvo->pvo_pte.pte_lo & + (PTE_REF | PTE_CHG)); + } + } + + /* + * Remove this PVO from the PV list. + */ + LIST_REMOVE(pvo, pvo_vlink); + + /* + * Remove this from the overflow list and return it to the pool + * if we aren't going to reuse it. + */ + LIST_REMOVE(pvo, pvo_olink); + if (!(pvo->pvo_vaddr & PVO_BOOTSTRAP)) + uma_zfree(pvo->pvo_vaddr & PVO_MANAGED ? moea_mpvo_zone : + moea_upvo_zone, pvo); + moea_pvo_entries--; + moea_pvo_remove_calls++; +} + +static __inline int +moea_pvo_pte_index(const struct pvo_entry *pvo, int ptegidx) +{ + int pteidx; + + /* + * We can find the actual pte entry without searching by grabbing + * the PTEG index from 3 unused bits in pte_lo[11:9] and by + * noticing the HID bit. + */ + pteidx = ptegidx * 8 + PVO_PTEGIDX_GET(pvo); + if (pvo->pvo_pte.pte_hi & PTE_HID) + pteidx ^= moea_pteg_mask * 8; + + return (pteidx); +} + +static struct pvo_entry * +moea_pvo_find_va(pmap_t pm, vm_offset_t va, int *pteidx_p) +{ + struct pvo_entry *pvo; + int ptegidx; + u_int sr; + + va &= ~ADDR_POFF; + sr = va_to_sr(pm->pm_sr, va); + ptegidx = va_to_pteg(sr, va); + + mtx_lock(&moea_table_mutex); + LIST_FOREACH(pvo, &moea_pvo_table[ptegidx], pvo_olink) { + if (pvo->pvo_pmap == pm && PVO_VADDR(pvo) == va) { + if (pteidx_p) + *pteidx_p = moea_pvo_pte_index(pvo, ptegidx); + break; + } + } + mtx_unlock(&moea_table_mutex); + + return (pvo); +} + +static struct pte * +moea_pvo_to_pte(const struct pvo_entry *pvo, int pteidx) +{ + struct pte *pt; + + /* + * If we haven't been supplied the ptegidx, calculate it. + */ + if (pteidx == -1) { + int ptegidx; + u_int sr; + + sr = va_to_sr(pvo->pvo_pmap->pm_sr, pvo->pvo_vaddr); + ptegidx = va_to_pteg(sr, pvo->pvo_vaddr); + pteidx = moea_pvo_pte_index(pvo, ptegidx); + } + + pt = &moea_pteg_table[pteidx >> 3].pt[pteidx & 7]; + mtx_lock(&moea_table_mutex); + + if ((pvo->pvo_pte.pte_hi & PTE_VALID) && !PVO_PTEGIDX_ISSET(pvo)) { + panic("moea_pvo_to_pte: pvo %p has valid pte in pvo but no " + "valid pte index", pvo); + } + + if ((pvo->pvo_pte.pte_hi & PTE_VALID) == 0 && PVO_PTEGIDX_ISSET(pvo)) { + panic("moea_pvo_to_pte: pvo %p has valid pte index in pvo " + "pvo but no valid pte", pvo); + } + + if ((pt->pte_hi ^ (pvo->pvo_pte.pte_hi & ~PTE_VALID)) == PTE_VALID) { + if ((pvo->pvo_pte.pte_hi & PTE_VALID) == 0) { + panic("moea_pvo_to_pte: pvo %p has valid pte in " + "moea_pteg_table %p but invalid in pvo", pvo, pt); + } + + if (((pt->pte_lo ^ pvo->pvo_pte.pte_lo) & ~(PTE_CHG|PTE_REF)) + != 0) { + panic("moea_pvo_to_pte: pvo %p pte does not match " + "pte %p in moea_pteg_table", pvo, pt); + } + + mtx_assert(&moea_table_mutex, MA_OWNED); + return (pt); + } + + if (pvo->pvo_pte.pte_hi & PTE_VALID) { + panic("moea_pvo_to_pte: pvo %p has invalid pte %p in " + "moea_pteg_table but valid in pvo", pvo, pt); + } + + mtx_unlock(&moea_table_mutex); + return (NULL); +} + +/* + * XXX: THIS STUFF SHOULD BE IN pte.c? + */ +int +moea_pte_spill(vm_offset_t addr) +{ + struct pvo_entry *source_pvo, *victim_pvo; + struct pvo_entry *pvo; + int ptegidx, i, j; + u_int sr; + struct pteg *pteg; + struct pte *pt; + + moea_pte_spills++; + + sr = mfsrin(addr); + ptegidx = va_to_pteg(sr, addr); + + /* + * Have to substitute some entry. Use the primary hash for this. + * Use low bits of timebase as random generator. + */ + pteg = &moea_pteg_table[ptegidx]; + mtx_lock(&moea_table_mutex); + __asm __volatile("mftb %0" : "=r"(i)); + i &= 7; + pt = &pteg->pt[i]; + + source_pvo = NULL; + victim_pvo = NULL; + LIST_FOREACH(pvo, &moea_pvo_table[ptegidx], pvo_olink) { + /* + * We need to find a pvo entry for this address. + */ + MOEA_PVO_CHECK(pvo); + if (source_pvo == NULL && + moea_pte_match(&pvo->pvo_pte, sr, addr, + pvo->pvo_pte.pte_hi & PTE_HID)) { + /* + * Now found an entry to be spilled into the pteg. + * The PTE is now valid, so we know it's active. + */ + j = moea_pte_insert(ptegidx, &pvo->pvo_pte); + + if (j >= 0) { + PVO_PTEGIDX_SET(pvo, j); + moea_pte_overflow--; + MOEA_PVO_CHECK(pvo); + mtx_unlock(&moea_table_mutex); + return (1); + } + + source_pvo = pvo; + + if (victim_pvo != NULL) + break; + } + + /* + * We also need the pvo entry of the victim we are replacing + * so save the R & C bits of the PTE. + */ + if ((pt->pte_hi & PTE_HID) == 0 && victim_pvo == NULL && + moea_pte_compare(pt, &pvo->pvo_pte)) { + victim_pvo = pvo; + if (source_pvo != NULL) + break; + } + } + + if (source_pvo == NULL) { + mtx_unlock(&moea_table_mutex); + return (0); + } + + if (victim_pvo == NULL) { + if ((pt->pte_hi & PTE_HID) == 0) + panic("moea_pte_spill: victim p-pte (%p) has no pvo" + "entry", pt); + + /* + * If this is a secondary PTE, we need to search it's primary + * pvo bucket for the matching PVO. + */ + LIST_FOREACH(pvo, &moea_pvo_table[ptegidx ^ moea_pteg_mask], + pvo_olink) { + MOEA_PVO_CHECK(pvo); + /* + * We also need the pvo entry of the victim we are + * replacing so save the R & C bits of the PTE. + */ + if (moea_pte_compare(pt, &pvo->pvo_pte)) { + victim_pvo = pvo; + break; + } + } + + if (victim_pvo == NULL) + panic("moea_pte_spill: victim s-pte (%p) has no pvo" + "entry", pt); + } + + /* + * We are invalidating the TLB entry for the EA we are replacing even + * though it's valid. If we don't, we lose any ref/chg bit changes + * contained in the TLB entry. + */ + source_pvo->pvo_pte.pte_hi &= ~PTE_HID; + + moea_pte_unset(pt, &victim_pvo->pvo_pte, victim_pvo->pvo_vaddr); + moea_pte_set(pt, &source_pvo->pvo_pte); + + PVO_PTEGIDX_CLR(victim_pvo); + PVO_PTEGIDX_SET(source_pvo, i); + moea_pte_replacements++; + + MOEA_PVO_CHECK(victim_pvo); + MOEA_PVO_CHECK(source_pvo); + + mtx_unlock(&moea_table_mutex); + return (1); +} + +static int +moea_pte_insert(u_int ptegidx, struct pte *pvo_pt) +{ + struct pte *pt; + int i; + + mtx_assert(&moea_table_mutex, MA_OWNED); + + /* + * First try primary hash. + */ + for (pt = moea_pteg_table[ptegidx].pt, i = 0; i < 8; i++, pt++) { + if ((pt->pte_hi & PTE_VALID) == 0) { + pvo_pt->pte_hi &= ~PTE_HID; + moea_pte_set(pt, pvo_pt); + return (i); + } + } + + /* + * Now try secondary hash. + */ + ptegidx ^= moea_pteg_mask; + + for (pt = moea_pteg_table[ptegidx].pt, i = 0; i < 8; i++, pt++) { + if ((pt->pte_hi & PTE_VALID) == 0) { + pvo_pt->pte_hi |= PTE_HID; + moea_pte_set(pt, pvo_pt); + return (i); + } + } + + panic("moea_pte_insert: overflow"); + return (-1); +} + +static boolean_t +moea_query_bit(vm_page_t m, int ptebit) +{ + struct pvo_entry *pvo; + struct pte *pt; + +#if 0 + if (moea_attr_fetch(m) & ptebit) + return (TRUE); +#endif + + LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) { + MOEA_PVO_CHECK(pvo); /* sanity check */ + + /* + * See if we saved the bit off. If so, cache it and return + * success. + */ + if (pvo->pvo_pte.pte_lo & ptebit) { + moea_attr_save(m, ptebit); + MOEA_PVO_CHECK(pvo); /* sanity check */ + return (TRUE); + } + } + + /* + * No luck, now go through the hard part of looking at the PTEs + * themselves. Sync so that any pending REF/CHG bits are flushed to + * the PTEs. + */ + SYNC(); + LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) { + MOEA_PVO_CHECK(pvo); /* sanity check */ + + /* + * See if this pvo has a valid PTE. if so, fetch the + * REF/CHG bits from the valid PTE. If the appropriate + * ptebit is set, cache it and return success. + */ + pt = moea_pvo_to_pte(pvo, -1); + if (pt != NULL) { + moea_pte_synch(pt, &pvo->pvo_pte); + mtx_unlock(&moea_table_mutex); + if (pvo->pvo_pte.pte_lo & ptebit) { + moea_attr_save(m, ptebit); + MOEA_PVO_CHECK(pvo); /* sanity check */ + return (TRUE); + } + } + } + + return (FALSE); +} + +static u_int +moea_clear_bit(vm_page_t m, int ptebit, int *origbit) +{ + u_int count; + struct pvo_entry *pvo; + struct pte *pt; + int rv; + + /* + * Clear the cached value. + */ + rv = moea_attr_fetch(m); + moea_attr_clear(m, ptebit); + + /* + * Sync so that any pending REF/CHG bits are flushed to the PTEs (so + * we can reset the right ones). note that since the pvo entries and + * list heads are accessed via BAT0 and are never placed in the page + * table, we don't have to worry about further accesses setting the + * REF/CHG bits. + */ + SYNC(); + + /* + * For each pvo entry, clear the pvo's ptebit. If this pvo has a + * valid pte clear the ptebit from the valid pte. + */ + count = 0; + LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) { + MOEA_PVO_CHECK(pvo); /* sanity check */ + pt = moea_pvo_to_pte(pvo, -1); + if (pt != NULL) { + moea_pte_synch(pt, &pvo->pvo_pte); + if (pvo->pvo_pte.pte_lo & ptebit) { + count++; + moea_pte_clear(pt, PVO_VADDR(pvo), ptebit); + } + mtx_unlock(&moea_table_mutex); + } + rv |= pvo->pvo_pte.pte_lo; + pvo->pvo_pte.pte_lo &= ~ptebit; + MOEA_PVO_CHECK(pvo); /* sanity check */ + } + + if (origbit != NULL) { + *origbit = rv; + } + + return (count); +} + +/* + * Return true if the physical range is encompassed by the battable[idx] + */ +static int +moea_bat_mapped(int idx, vm_offset_t pa, vm_size_t size) +{ + u_int prot; + u_int32_t start; + u_int32_t end; + u_int32_t bat_ble; + + /* + * Return immediately if not a valid mapping + */ + if (!battable[idx].batu & BAT_Vs) + return (EINVAL); + + /* + * The BAT entry must be cache-inhibited, guarded, and r/w + * so it can function as an i/o page + */ + prot = battable[idx].batl & (BAT_I|BAT_G|BAT_PP_RW); + if (prot != (BAT_I|BAT_G|BAT_PP_RW)) + return (EPERM); + + /* + * The address should be within the BAT range. Assume that the + * start address in the BAT has the correct alignment (thus + * not requiring masking) + */ + start = battable[idx].batl & BAT_PBS; + bat_ble = (battable[idx].batu & ~(BAT_EBS)) | 0x03; + end = start | (bat_ble << 15) | 0x7fff; + + if ((pa < start) || ((pa + size) > end)) + return (ERANGE); + + return (0); +} + +boolean_t +moea_dev_direct_mapped(mmu_t mmu, vm_offset_t pa, vm_size_t size) +{ + int i; + + /* + * This currently does not work for entries that + * overlap 256M BAT segments. + */ + + for(i = 0; i < 16; i++) + if (moea_bat_mapped(i, pa, size) == 0) + return (0); + + return (EFAULT); +} + +boolean_t +moea_page_executable(mmu_t mmu, vm_page_t pg) +{ + return ((moea_attr_fetch(pg) & PTE_EXEC) == PTE_EXEC); +} + +/* + * Map a set of physical memory pages into the kernel virtual + * address space. Return a pointer to where it is mapped. This + * routine is intended to be used for mapping device memory, + * NOT real memory. + */ +void * +moea_mapdev(mmu_t mmu, vm_offset_t pa, vm_size_t size) +{ + vm_offset_t va, tmpva, ppa, offset; + int i; + + ppa = trunc_page(pa); + offset = pa & PAGE_MASK; + size = roundup(offset + size, PAGE_SIZE); + + GIANT_REQUIRED; + + /* + * If the physical address lies within a valid BAT table entry, + * return the 1:1 mapping. This currently doesn't work + * for regions that overlap 256M BAT segments. + */ + for (i = 0; i < 16; i++) { + if (moea_bat_mapped(i, pa, size) == 0) + return ((void *) pa); + } + + va = kmem_alloc_nofault(kernel_map, size); + if (!va) + panic("moea_mapdev: Couldn't alloc kernel virtual memory"); + + for (tmpva = va; size > 0;) { + moea_kenter(mmu, tmpva, ppa); + TLBIE(tmpva); /* XXX or should it be invalidate-all ? */ + size -= PAGE_SIZE; + tmpva += PAGE_SIZE; + ppa += PAGE_SIZE; + } + + return ((void *)(va + offset)); +} + +void +moea_unmapdev(mmu_t mmu, vm_offset_t va, vm_size_t size) +{ + vm_offset_t base, offset; + + /* + * If this is outside kernel virtual space, then it's a + * battable entry and doesn't require unmapping + */ + if ((va >= VM_MIN_KERNEL_ADDRESS) && (va <= VM_MAX_KERNEL_ADDRESS)) { + base = trunc_page(va); + offset = va & PAGE_MASK; + size = roundup(offset + size, PAGE_SIZE); + kmem_free(kernel_map, base, size); + } +} diff --git a/sys/powerpc/powerpc/mp_machdep.c b/sys/powerpc/powerpc/mp_machdep.c new file mode 100644 index 000000000000..f76eedf58e3a --- /dev/null +++ b/sys/powerpc/powerpc/mp_machdep.c @@ -0,0 +1,68 @@ +/*- + * Copyright (c) 2000 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/ktr.h> +#include <sys/proc.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/kernel.h> +#include <sys/smp.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_map.h> + +#include <machine/atomic.h> +#include <machine/pmap.h> + +int boot_cpu_id; + +void +cpu_mp_setmaxid(void) +{ +} + +int +cpu_mp_probe(void) +{ + all_cpus = 1; /* needed for MB init code */ + return 0; +} + +void +cpu_mp_start(void) +{ +} + +void +cpu_mp_announce(void) +{ +} diff --git a/sys/powerpc/powerpc/nexus.c b/sys/powerpc/powerpc/nexus.c new file mode 100644 index 000000000000..e31ef61a813c --- /dev/null +++ b/sys/powerpc/powerpc/nexus.c @@ -0,0 +1,487 @@ +/*- + * Copyright 1998 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/*- + * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: FreeBSD: src/sys/i386/i386/nexus.c,v 1.43 2001/02/09 + * + * $FreeBSD$ + */ +#include "opt_psim.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/cons.h> +#include <sys/kernel.h> +#include <sys/malloc.h> + +#include <dev/ofw/openfirm.h> + +#include <machine/bus.h> +#include <machine/frame.h> +#include <machine/intr_machdep.h> +#include <machine/nexusvar.h> +#include <machine/resource.h> + +#include <sys/rman.h> + +#include "ofw_bus_if.h" +#include "pic_if.h" + +/* + * The nexus (which is a pseudo-bus actually) iterates over the nodes that + * exist in Open Firmware and adds them as devices to this bus so that drivers + * can be attached to them. + * + * Maybe this code should get into dev/ofw to some extent, as some of it should + * work for all Open Firmware based machines... + */ + +static MALLOC_DEFINE(M_NEXUS, "nexus", "nexus device information"); + +struct nexus_devinfo { + phandle_t ndi_node; + /* Some common properties. */ + const char *ndi_name; + const char *ndi_device_type; + const char *ndi_compatible; +}; + +struct nexus_softc { + struct rman sc_rman; +}; + +/* + * Device interface + */ +static int nexus_probe(device_t); +static void nexus_probe_nomatch(device_t, device_t); + +/* + * Bus interface + */ +static device_t nexus_add_child(device_t, int, const char *, int); +static int nexus_read_ivar(device_t, device_t, int, uintptr_t *); +static int nexus_write_ivar(device_t, device_t, int, uintptr_t); +static int nexus_setup_intr(device_t, device_t, struct resource *, int, + driver_filter_t *, driver_intr_t *, void *, void **); +static int nexus_teardown_intr(device_t, device_t, struct resource *, + void *); +static struct resource *nexus_alloc_resource(device_t, device_t, int, int *, + u_long, u_long, u_long, u_int); +static int nexus_activate_resource(device_t, device_t, int, int, + struct resource *); +static int nexus_deactivate_resource(device_t, device_t, int, int, + struct resource *); +static int nexus_release_resource(device_t, device_t, int, int, + struct resource *); + +static phandle_t nexus_ofw_get_node(device_t, device_t); +static const char *nexus_ofw_get_name(device_t, device_t); +static const char *nexus_ofw_get_type(device_t, device_t); +static const char *nexus_ofw_get_compat(device_t, device_t); + +/* + * Local routines + */ +static device_t nexus_device_from_node(device_t, phandle_t); + +static device_method_t nexus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, nexus_probe), + DEVMETHOD(device_attach, bus_generic_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* Bus interface. Resource management is business of the children... */ + DEVMETHOD(bus_add_child, nexus_add_child), + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_probe_nomatch, nexus_probe_nomatch), + DEVMETHOD(bus_read_ivar, nexus_read_ivar), + DEVMETHOD(bus_write_ivar, nexus_write_ivar), + DEVMETHOD(bus_setup_intr, nexus_setup_intr), + DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), + DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), + DEVMETHOD(bus_activate_resource, nexus_activate_resource), + DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), + DEVMETHOD(bus_release_resource, nexus_release_resource), + + /* OFW bus interface */ + DEVMETHOD(ofw_bus_get_node, nexus_ofw_get_node), + DEVMETHOD(ofw_bus_get_name, nexus_ofw_get_name), + DEVMETHOD(ofw_bus_get_type, nexus_ofw_get_type), + DEVMETHOD(ofw_bus_get_compat, nexus_ofw_get_compat), + + { 0, 0 } +}; + +static driver_t nexus_driver = { + "nexus", + nexus_methods, + sizeof(struct nexus_softc), +}; + +static devclass_t nexus_devclass; + +DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0); + +static int +nexus_probe(device_t dev) +{ + phandle_t root; + phandle_t child; + struct nexus_softc *sc; + u_long start, end; + + if ((root = OF_peer(0)) == -1) + panic("nexus_probe: OF_peer failed."); + + sc = device_get_softc(dev); + + start = 0; + end = INTR_VECTORS - 1; + + sc->sc_rman.rm_start = start; + sc->sc_rman.rm_end = end; + sc->sc_rman.rm_type = RMAN_ARRAY; + sc->sc_rman.rm_descr = "Interrupt request lines"; + if (rman_init(&sc->sc_rman) || + rman_manage_region(&sc->sc_rman, start, end)) + panic("nexus_probe IRQ rman"); + + /* + * Allow devices to identify + */ + bus_generic_probe(dev); + + /* + * Now walk the OFW tree to locate top-level devices + */ + for (child = OF_child(root); child != 0; child = OF_peer(child)) { + if (child == -1) + panic("nexus_probe(): OF_child failed."); + (void)nexus_device_from_node(dev, child); + + } + device_set_desc(dev, "Open Firmware Nexus device"); + return (0); +} + +static void +nexus_probe_nomatch(device_t dev, device_t child) +{ + char *name, *type; + + if (BUS_READ_IVAR(dev, child, NEXUS_IVAR_NAME, + (uintptr_t *)&name) != 0 || + BUS_READ_IVAR(dev, child, NEXUS_IVAR_DEVICE_TYPE, + (uintptr_t *)&type) != 0) + return; + + if (type == NULL) + type = "(unknown)"; + + if (bootverbose) + device_printf(dev, "<%s>, type %s (no driver attached)\n", + name, type); +} + +static device_t +nexus_add_child(device_t dev, int order, const char *name, int unit) +{ + device_t child; + struct nexus_devinfo *dinfo; + + child = device_add_child_ordered(dev, order, name, unit); + if (child == NULL) + return (NULL); + + dinfo = malloc(sizeof(struct nexus_devinfo), M_NEXUS, M_NOWAIT|M_ZERO); + if (dinfo == NULL) + return (NULL); + + dinfo->ndi_node = -1; + dinfo->ndi_name = name; + device_set_ivars(child, dinfo); + + return (child); +} + + +static int +nexus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct nexus_devinfo *dinfo; + + if ((dinfo = device_get_ivars(child)) == 0) + return (ENOENT); + switch (which) { + case NEXUS_IVAR_NODE: + *result = dinfo->ndi_node; + break; + case NEXUS_IVAR_NAME: + *result = (uintptr_t)dinfo->ndi_name; + break; + case NEXUS_IVAR_DEVICE_TYPE: + *result = (uintptr_t)dinfo->ndi_device_type; + break; + case NEXUS_IVAR_COMPATIBLE: + *result = (uintptr_t)dinfo->ndi_compatible; + break; + default: + return (ENOENT); + } + return 0; +} + +static int +nexus_write_ivar(device_t dev, device_t child, int which, uintptr_t value) +{ + struct nexus_devinfo *dinfo; + + if ((dinfo = device_get_ivars(child)) == 0) + return (ENOENT); + + switch (which) { + case NEXUS_IVAR_NAME: + return (EINVAL); + + /* Identified devices may want to set these */ + case NEXUS_IVAR_NODE: + dinfo->ndi_node = (phandle_t)value; + break; + + case NEXUS_IVAR_DEVICE_TYPE: + dinfo->ndi_device_type = (char *)value; + break; + + default: + return (ENOENT); + } + return 0; +} + +static int +nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, + driver_filter_t *filter, driver_intr_t *ihand, void *arg, void **cookiep) +{ + driver_t *driver; + int error; + + /* somebody tried to setup an irq that failed to allocate! */ + if (res == NULL) + panic("nexus_setup_intr: NULL irq resource!"); + + *cookiep = 0; + if ((rman_get_flags(res) & RF_SHAREABLE) == 0) + flags |= INTR_EXCL; + + driver = device_get_driver(child); + + /* + * We depend here on rman_activate_resource() being idempotent. + */ + error = rman_activate_resource(res); + if (error) + return (error); + + error = powerpc_setup_intr(device_get_nameunit(child), + rman_get_start(res), filter, ihand, arg, flags, cookiep); + + return (error); +} + +static int +nexus_teardown_intr(device_t dev, device_t child, struct resource *res, + void *cookie) +{ + + return (powerpc_teardown_intr(cookie)); +} + +/* + * Allocate resources at the behest of a child. This only handles interrupts, + * since I/O resources are handled by child busses. + */ +static struct resource * +nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct nexus_softc *sc; + struct resource *rv; + + if (type != SYS_RES_IRQ) { + device_printf(bus, "unknown resource request from %s\n", + device_get_nameunit(child)); + return (NULL); + } + + if (count == 0 || start + count - 1 != end) { + device_printf(bus, "invalid IRQ allocation from %s\n", + device_get_nameunit(child)); + return (NULL); + } + + sc = device_get_softc(bus); + + rv = rman_reserve_resource(&sc->sc_rman, start, end, count, + flags, child); + if (rv == NULL) { + device_printf(bus, "IRQ allocation failed for %s\n", + device_get_nameunit(child)); + } else + rman_set_rid(rv, *rid); + + return (rv); +} + +static int +nexus_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + + /* Not much to be done yet... */ + return (rman_activate_resource(res)); +} + +static int +nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + + /* Not much to be done yet... */ + return (rman_deactivate_resource(res)); +} + +static int +nexus_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + + if (type != SYS_RES_IRQ) { + device_printf(bus, "unknown resource request from %s\n", + device_get_nameunit(child)); + return (EINVAL); + } + + return (rman_release_resource(res)); +} + +static device_t +nexus_device_from_node(device_t parent, phandle_t node) +{ + device_t cdev; + struct nexus_devinfo *dinfo; + char *name, *type, *compatible; + + OF_getprop_alloc(node, "name", 1, (void **)&name); + OF_getprop_alloc(node, "device_type", 1, (void **)&type); + OF_getprop_alloc(node, "compatible", 1, (void **)&compatible); + cdev = device_add_child(parent, NULL, -1); + if (cdev != NULL) { + dinfo = malloc(sizeof(*dinfo), M_NEXUS, M_WAITOK); + dinfo->ndi_node = node; + dinfo->ndi_name = name; + dinfo->ndi_device_type = type; + dinfo->ndi_compatible = compatible; + device_set_ivars(cdev, dinfo); + } else + free(name, M_OFWPROP); + + return (cdev); +} + +static const char * +nexus_ofw_get_name(device_t bus, device_t dev) +{ + struct nexus_devinfo *dinfo; + + if ((dinfo = device_get_ivars(dev)) == NULL) + return (NULL); + + return (dinfo->ndi_name); +} + +static phandle_t +nexus_ofw_get_node(device_t bus, device_t dev) +{ + struct nexus_devinfo *dinfo; + + if ((dinfo = device_get_ivars(dev)) == NULL) + return (0); + + return (dinfo->ndi_node); +} + +static const char * +nexus_ofw_get_type(device_t bus, device_t dev) +{ + struct nexus_devinfo *dinfo; + + if ((dinfo = device_get_ivars(dev)) == NULL) + return (NULL); + + return (dinfo->ndi_device_type); +} + +static const char * +nexus_ofw_get_compat(device_t bus, device_t dev) +{ + struct nexus_devinfo *dinfo; + + if ((dinfo = device_get_ivars(dev)) == NULL) + return (NULL); + + return (dinfo->ndi_compatible); +} diff --git a/sys/powerpc/powerpc/ofw_machdep.c b/sys/powerpc/powerpc/ofw_machdep.c new file mode 100644 index 000000000000..d63236f9bda8 --- /dev/null +++ b/sys/powerpc/powerpc/ofw_machdep.c @@ -0,0 +1,436 @@ +/*- + * Copyright (C) 1996 Wolfgang Solfrank. + * Copyright (C) 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: ofw_machdep.c,v 1.5 2000/05/23 13:25:43 tsubai Exp $ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/disk.h> +#include <sys/fcntl.h> +#include <sys/malloc.h> +#include <sys/stat.h> + +#include <net/ethernet.h> + +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_pci.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/vm_page.h> + +#include <machine/bus.h> +#include <machine/md_var.h> +#include <machine/powerpc.h> +#include <machine/ofw_machdep.h> +#include <powerpc/ofw/ofw_pci.h> + +#define OFMEM_REGIONS 32 +static struct mem_region OFmem[OFMEM_REGIONS + 1], OFavail[OFMEM_REGIONS + 3]; +static struct mem_region OFfree[OFMEM_REGIONS + 3]; + +extern register_t ofmsr[5]; +extern struct pcpu __pcpu[MAXCPU]; +extern struct pmap ofw_pmap; +static int (*ofwcall)(void *); + +/* + * Saved SPRG0-3 from OpenFirmware. Will be restored prior to the callback. + */ +register_t ofw_sprg0_save; + +static __inline void +ofw_sprg_prepare(void) +{ + /* + * Assume that interrupt are disabled at this point, or + * SPRG1-3 could be trashed + */ + __asm __volatile("mfsprg0 %0\n\t" + "mtsprg0 %1\n\t" + "mtsprg1 %2\n\t" + "mtsprg2 %3\n\t" + "mtsprg3 %4\n\t" + : "=&r"(ofw_sprg0_save) + : "r"(ofmsr[1]), + "r"(ofmsr[2]), + "r"(ofmsr[3]), + "r"(ofmsr[4])); +} + +static __inline void +ofw_sprg_restore(void) +{ + /* + * Note that SPRG1-3 contents are irrelevant. They are scratch + * registers used in the early portion of trap handling when + * interrupts are disabled. + * + * PCPU data cannot be used until this routine is called ! + */ + __asm __volatile("mtsprg0 %0" :: "r"(ofw_sprg0_save)); +} + +/* + * Memory region utilities: determine if two regions overlap, + * and merge two overlapping regions into one + */ +static int +memr_overlap(struct mem_region *r1, struct mem_region *r2) +{ + if ((r1->mr_start + r1->mr_size) < r2->mr_start || + (r2->mr_start + r2->mr_size) < r1->mr_start) + return (FALSE); + + return (TRUE); +} + +static void +memr_merge(struct mem_region *from, struct mem_region *to) +{ + int end; + end = imax(to->mr_start + to->mr_size, from->mr_start + from->mr_size); + to->mr_start = imin(from->mr_start, to->mr_start); + to->mr_size = end - to->mr_start; +} + +/* + * This is called during powerpc_init, before the system is really initialized. + * It shall provide the total and the available regions of RAM. + * Both lists must have a zero-size entry as terminator. + * The available regions need not take the kernel into account, but needs + * to provide space for two additional entry beyond the terminating one. + */ +void +mem_regions(struct mem_region **memp, int *memsz, + struct mem_region **availp, int *availsz) +{ + int phandle; + int asz, msz, fsz; + int i, j; + int still_merging; + + /* + * Get memory. + */ + if ((phandle = OF_finddevice("/memory")) == -1 + || (msz = OF_getprop(phandle, "reg", + OFmem, sizeof OFmem[0] * OFMEM_REGIONS)) + <= 0 + || (asz = OF_getprop(phandle, "available", + OFavail, sizeof OFavail[0] * OFMEM_REGIONS)) + <= 0) + panic("no memory?"); + *memp = OFmem; + *memsz = msz / sizeof(struct mem_region); + + /* + * OFavail may have overlapping regions - collapse these + * and copy out remaining regions to OFfree + */ + asz /= sizeof(struct mem_region); + do { + still_merging = FALSE; + for (i = 0; i < asz; i++) { + if (OFavail[i].mr_size == 0) + continue; + for (j = i+1; j < asz; j++) { + if (OFavail[j].mr_size == 0) + continue; + if (memr_overlap(&OFavail[j], &OFavail[i])) { + memr_merge(&OFavail[j], &OFavail[i]); + /* mark inactive */ + OFavail[j].mr_size = 0; + still_merging = TRUE; + } + } + } + } while (still_merging == TRUE); + + /* evict inactive ranges */ + for (i = 0, fsz = 0; i < asz; i++) { + if (OFavail[i].mr_size != 0) { + OFfree[fsz] = OFavail[i]; + fsz++; + } + } + + *availp = OFfree; + *availsz = fsz; +} + +void +set_openfirm_callback(int (*openfirm)(void *)) +{ + + ofwcall = openfirm; +} + +int +openfirmware(void *args) +{ + long oldmsr; + int result; + u_int srsave[16]; + u_int i; + + __asm __volatile( "\t" + "sync\n\t" + "mfmsr %0\n\t" + "mtmsr %1\n\t" + "isync\n" + : "=r" (oldmsr) + : "r" (ofmsr[0]) + ); + + ofw_sprg_prepare(); + + if (pmap_bootstrapped) { + /* + * Swap the kernel's address space with Open Firmware's + */ + for (i = 0; i < 16; i++) { + srsave[i] = mfsrin(i << ADDR_SR_SHFT); + mtsrin(i << ADDR_SR_SHFT, ofw_pmap.pm_sr[i]); + } + + /* + * Clear battable[] translations + */ + __asm __volatile("mtdbatu 2, %0\n" + "mtdbatu 3, %0" : : "r" (0)); + isync(); + } + + result = ofwcall(args); + + if (pmap_bootstrapped) { + /* + * Restore the kernel's addr space. The isync() doesn;t + * work outside the loop unless mtsrin() is open-coded + * in an asm statement :( + */ + for (i = 0; i < 16; i++) { + mtsrin(i << ADDR_SR_SHFT, srsave[i]); + isync(); + } + } + + ofw_sprg_restore(); + + __asm( "\t" + "mtmsr %0\n\t" + "isync\n" + : : "r" (oldmsr) + ); + + return (result); +} + +void +OF_halt() +{ + int retval; /* dummy, this may not be needed */ + + OF_interpret("shut-down", 1, &retval); + for (;;); /* just in case */ +} + +void +OF_reboot() +{ + int retval; /* dummy, this may not be needed */ + + OF_interpret("reset-all", 1, &retval); + for (;;); /* just in case */ +} + +void +OF_getetheraddr(device_t dev, u_char *addr) +{ + phandle_t node; + + node = ofw_pci_find_node(dev); + OF_getprop(node, "local-mac-address", addr, ETHER_ADDR_LEN); +} + +/* + * Return a bus handle and bus tag that corresponds to the register + * numbered regno for the device referenced by the package handle + * dev. This function is intended to be used by console drivers in + * early boot only. It works by mapping the address of the device's + * register in the address space of its parent and recursively walk + * the device tree upward this way. + */ +static void +OF_get_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep, int *pcip) +{ + char name[16]; + uint32_t addr, size; + int pci, res; + + res = OF_getprop(node, "#address-cells", &addr, sizeof(addr)); + if (res == -1) + addr = 2; + res = OF_getprop(node, "#size-cells", &size, sizeof(size)); + if (res == -1) + size = 1; + pci = 0; + if (addr == 3 && size == 2) { + res = OF_getprop(node, "name", name, sizeof(name)); + if (res != -1) { + name[sizeof(name) - 1] = '\0'; + pci = (strcmp(name, "pci") == 0) ? 1 : 0; + } + } + if (addrp != NULL) + *addrp = addr; + if (sizep != NULL) + *sizep = size; + if (pcip != NULL) + *pcip = pci; +} + +int +OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag, + bus_space_handle_t *handle) +{ + uint32_t cell[32]; + bus_addr_t addr, raddr, baddr; + bus_size_t size, rsize; + uint32_t c, nbridge, naddr, nsize; + phandle_t bridge, parent; + u_int spc, rspc; + int pci, pcib, res; + + /* Sanity checking. */ + if (dev == 0) + return (EINVAL); + bridge = OF_parent(dev); + if (bridge == 0) + return (EINVAL); + if (regno < 0) + return (EINVAL); + if (tag == NULL || handle == NULL) + return (EINVAL); + + /* Get the requested register. */ + OF_get_addr_props(bridge, &naddr, &nsize, &pci); + res = OF_getprop(dev, (pci) ? "assigned-addresses" : "reg", + cell, sizeof(cell)); + if (res == -1) + return (ENXIO); + if (res % sizeof(cell[0])) + return (ENXIO); + res /= sizeof(cell[0]); + regno *= naddr + nsize; + if (regno + naddr + nsize > res) + return (EINVAL); + spc = (pci) ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK : ~0; + addr = 0; + for (c = 0; c < naddr; c++) + addr = ((uint64_t)addr << 32) | cell[regno++]; + size = 0; + for (c = 0; c < nsize; c++) + size = ((uint64_t)size << 32) | cell[regno++]; + + /* + * Map the address range in the bridge's decoding window as given + * by the "ranges" property. If a node doesn't have such property + * then no mapping is done. + */ + parent = OF_parent(bridge); + while (parent != 0) { + OF_get_addr_props(parent, &nbridge, NULL, &pcib); + res = OF_getprop(bridge, "ranges", cell, sizeof(cell)); + if (res == -1) + goto next; + if (res % sizeof(cell[0])) + return (ENXIO); + res /= sizeof(cell[0]); + regno = 0; + while (regno < res) { + rspc = (pci) + ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK + : ~0; + if (rspc != spc) { + regno += naddr + nbridge + nsize; + continue; + } + raddr = 0; + for (c = 0; c < naddr; c++) + raddr = ((uint64_t)raddr << 32) | cell[regno++]; + rspc = (pcib) + ? cell[regno] & OFW_PCI_PHYS_HI_SPACEMASK + : ~0; + baddr = 0; + for (c = 0; c < nbridge; c++) + baddr = ((uint64_t)baddr << 32) | cell[regno++]; + rsize = 0; + for (c = 0; c < nsize; c++) + rsize = ((uint64_t)rsize << 32) | cell[regno++]; + if (addr < raddr || addr >= raddr + rsize) + continue; + addr = addr - raddr + baddr; + if (rspc != ~0) + spc = rspc; + } + + next: + bridge = parent; + parent = OF_parent(bridge); + OF_get_addr_props(bridge, &naddr, &nsize, &pci); + } + + /* Default to memory mapped I/O. */ + *tag = PPC_BUS_SPACE_MEM; + if (spc == OFW_PCI_PHYS_HI_SPACE_IO) + *tag = PPC_BUS_SPACE_IO; + return (bus_space_map(*tag, addr, size, 0, handle)); +} + +int +mem_valid(vm_offset_t addr, int len) +{ + int i; + + for (i = 0; i < OFMEM_REGIONS; i++) + if ((addr >= OFmem[i].mr_start) + && (addr + len < OFmem[i].mr_start + OFmem[i].mr_size)) + return (0); + + return (EFAULT); +} diff --git a/sys/powerpc/powerpc/ofwmagic.S b/sys/powerpc/powerpc/ofwmagic.S new file mode 100644 index 000000000000..55af6d254440 --- /dev/null +++ b/sys/powerpc/powerpc/ofwmagic.S @@ -0,0 +1,75 @@ +/* $FreeBSD$ */ +/* $NetBSD: ofwmagic.S,v 1.2 1997/10/09 08:38:18 jtc Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Magic note section used by Open Firmware. + */ + + .section ".note" + + /*# note header */ + + /*# length of name */ + .long 8 + + /*# note descriptor size */ + .long 20 + + /*# note type (IEEE 1275) */ + .long 0x1275 + + /*# name of owner */ + .asciz "PowerPC" + .balign 4 + + + /*# note descriptor */ + + /*# real mode (-1) or virtual mode (0) */ + .long 0 + + /*# real-base */ + .long -1 + /*# real-size */ + .long -1 + + /*# virt-base */ + .long -1 + /*# virt-size */ + .long -1 diff --git a/sys/powerpc/powerpc/openpic.c b/sys/powerpc/powerpc/openpic.c new file mode 100644 index 000000000000..c6a086380eb9 --- /dev/null +++ b/sys/powerpc/powerpc/openpic.c @@ -0,0 +1,238 @@ +/*- + * Copyright (C) 2002 Benno Rice. + * 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 Benno Rice ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/rman.h> + +#include <machine/bus.h> +#include <machine/intr.h> +#include <machine/intr_machdep.h> +#include <machine/md_var.h> +#include <machine/pio.h> +#include <machine/resource.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <machine/openpicreg.h> +#include <machine/openpicvar.h> + +#include "pic_if.h" + +devclass_t openpic_devclass; + +/* + * Local routines + */ + +static __inline uint32_t +openpic_read(struct openpic_softc *sc, u_int reg) +{ + return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg)); +} + +static __inline void +openpic_write(struct openpic_softc *sc, u_int reg, uint32_t val) +{ + bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val); +} + +static __inline void +openpic_set_priority(struct openpic_softc *sc, int cpu, int pri) +{ + uint32_t x; + + x = openpic_read(sc, OPENPIC_CPU_PRIORITY(cpu)); + x &= ~OPENPIC_CPU_PRIORITY_MASK; + x |= pri; + openpic_write(sc, OPENPIC_CPU_PRIORITY(cpu), x); +} + +int +openpic_attach(device_t dev) +{ + struct openpic_softc *sc; + u_int irq; + u_int32_t x; + + sc = device_get_softc(dev); + sc->sc_dev = dev; + + sc->sc_rid = 0; + sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid, + RF_ACTIVE); + + if (sc->sc_memr == NULL) { + device_printf(dev, "Could not alloc mem resource!\n"); + return (ENXIO); + } + + sc->sc_bt = rman_get_bustag(sc->sc_memr); + sc->sc_bh = rman_get_bushandle(sc->sc_memr); + + x = openpic_read(sc, OPENPIC_FEATURE); + switch (x & OPENPIC_FEATURE_VERSION_MASK) { + case 1: + sc->sc_version = "1.0"; + break; + case 2: + sc->sc_version = "1.2"; + break; + case 3: + sc->sc_version = "1.3"; + break; + default: + sc->sc_version = "unknown"; + break; + } + + sc->sc_ncpu = ((x & OPENPIC_FEATURE_LAST_CPU_MASK) >> + OPENPIC_FEATURE_LAST_CPU_SHIFT) + 1; + sc->sc_nirq = ((x & OPENPIC_FEATURE_LAST_IRQ_MASK) >> + OPENPIC_FEATURE_LAST_IRQ_SHIFT) + 1; + + /* + * PSIM seems to report 1 too many IRQs + */ + if (sc->sc_psim) + sc->sc_nirq--; + + if (bootverbose) + device_printf(dev, + "Version %s, supports %d CPUs and %d irqs\n", + sc->sc_version, sc->sc_ncpu, sc->sc_nirq); + + /* disable all interrupts */ + for (irq = 0; irq < sc->sc_nirq; irq++) + openpic_write(sc, OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK); + + openpic_set_priority(sc, 0, 15); + + /* we don't need 8259 passthrough mode */ + x = openpic_read(sc, OPENPIC_CONFIG); + x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE; + openpic_write(sc, OPENPIC_CONFIG, x); + + /* send all interrupts to cpu 0 */ + for (irq = 0; irq < sc->sc_nirq; irq++) + openpic_write(sc, OPENPIC_IDEST(irq), 1 << 0); + + for (irq = 0; irq < sc->sc_nirq; irq++) { + x = irq; /* irq == vector. */ + x |= OPENPIC_IMASK; + x |= OPENPIC_POLARITY_POSITIVE; + x |= OPENPIC_SENSE_LEVEL; + x |= 8 << OPENPIC_PRIORITY_SHIFT; + openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); + } + + /* XXX IPI */ + /* XXX set spurious intr vector */ + + openpic_set_priority(sc, 0, 0); + + /* clear all pending interrupts */ + for (irq = 0; irq < sc->sc_nirq; irq++) { + (void)openpic_read(sc, OPENPIC_IACK(0)); + openpic_write(sc, OPENPIC_EOI(0), 0); + } + + powerpc_register_pic(dev); + + return (0); +} + +/* + * PIC I/F methods + */ + +void +openpic_dispatch(device_t dev, struct trapframe *tf) +{ + struct openpic_softc *sc; + u_int vector; + + sc = device_get_softc(dev); + while (1) { + vector = openpic_read(sc, OPENPIC_IACK(0)); + vector &= OPENPIC_VECTOR_MASK; + if (vector == 255) + break; + powerpc_dispatch_intr(vector, tf); + } +} + +void +openpic_enable(device_t dev, u_int irq, u_int vector) +{ + struct openpic_softc *sc; + uint32_t x; + + sc = device_get_softc(dev); + x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq)); + x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK); + x |= vector; + openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); +} + +void +openpic_eoi(device_t dev, u_int irq __unused) +{ + struct openpic_softc *sc; + + sc = device_get_softc(dev); + openpic_write(sc, OPENPIC_EOI(0), 0); +} + +void +openpic_mask(device_t dev, u_int irq) +{ + struct openpic_softc *sc; + uint32_t x; + + sc = device_get_softc(dev); + x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq)); + x |= OPENPIC_IMASK; + openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); + openpic_write(sc, OPENPIC_EOI(0), 0); +} + +void +openpic_unmask(device_t dev, u_int irq) +{ + struct openpic_softc *sc; + uint32_t x; + + sc = device_get_softc(dev); + x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq)); + x &= ~OPENPIC_IMASK; + openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); +} diff --git a/sys/powerpc/powerpc/pic_if.m b/sys/powerpc/powerpc/pic_if.m new file mode 100644 index 000000000000..9db9c1667a12 --- /dev/null +++ b/sys/powerpc/powerpc/pic_if.m @@ -0,0 +1,59 @@ +#- +# Copyright (c) 1998 Doug Rabson +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# from: src/sys/kern/bus_if.m,v 1.21 2002/04/21 11:16:10 markm Exp +# $FreeBSD$ +# + +#include <sys/bus.h> +#include <machine/frame.h> + +INTERFACE pic; + +METHOD void dispatch { + device_t dev; + struct trapframe *tf; +}; + +METHOD void enable { + device_t dev; + u_int irq; + u_int vector; +}; + +METHOD void eoi { + device_t dev; + u_int irq; +}; + +METHOD void mask { + device_t dev; + u_int irq; +}; + +METHOD void unmask { + device_t dev; + u_int irq; +}; diff --git a/sys/powerpc/powerpc/pmap_dispatch.c b/sys/powerpc/powerpc/pmap_dispatch.c new file mode 100644 index 000000000000..92ac5148a404 --- /dev/null +++ b/sys/powerpc/powerpc/pmap_dispatch.c @@ -0,0 +1,382 @@ +/*- + * Copyright (c) 2005 Peter Grehan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +/* + * Dispatch MI pmap calls to the appropriate MMU implementation + * through a previously registered kernel object. + * + * Before pmap_bootstrap() can be called, a CPU module must have + * called pmap_mmu_install(). This may be called multiple times: + * the highest priority call will be installed as the default + * MMU handler when pmap_bootstrap() is called. + * + * It is required that kobj_machdep_init() be called before + * pmap_bootstrap() to allow the kobj subsystem to initialise. This + * in turn requires that mutex_init() has been called. + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/systm.h> + +#include <vm/vm.h> +#include <vm/vm_page.h> + +#include <machine/mmuvar.h> + +#include "mmu_if.h" + +static mmu_def_t *mmu_def_impl; +static mmu_t mmu_obj; +static struct mmu_kobj mmu_kernel_obj; +static struct kobj_ops mmu_kernel_kops; + +/* + * pmap globals + */ +struct pmap kernel_pmap_store; + +struct msgbuf *msgbufp; +vm_offset_t msgbuf_phys; + +vm_offset_t kernel_vm_end; +vm_offset_t phys_avail[PHYS_AVAIL_SZ]; +vm_offset_t virtual_avail; +vm_offset_t virtual_end; + +int pmap_bootstrapped; + +void +pmap_change_wiring(pmap_t pmap, vm_offset_t va, boolean_t wired) +{ + MMU_CHANGE_WIRING(mmu_obj, pmap, va, wired); +} + +void +pmap_clear_modify(vm_page_t m) +{ + MMU_CLEAR_MODIFY(mmu_obj, m); +} + +void +pmap_clear_reference(vm_page_t m) +{ + MMU_CLEAR_REFERENCE(mmu_obj, m); +} + +void +pmap_copy(pmap_t dst_pmap, pmap_t src_pmap, vm_offset_t dst_addr, + vm_size_t len, vm_offset_t src_addr) +{ + MMU_COPY(mmu_obj, dst_pmap, src_pmap, dst_addr, len, src_addr); +} + +void +pmap_copy_page(vm_page_t src, vm_page_t dst) +{ + MMU_COPY_PAGE(mmu_obj, src, dst); +} + +void +pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t p, vm_prot_t prot, + boolean_t wired) +{ + MMU_ENTER(mmu_obj, pmap, va, p, prot, wired); +} + +void +pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end, + vm_page_t m_start, vm_prot_t prot) +{ + MMU_ENTER_OBJECT(mmu_obj, pmap, start, end, m_start, prot); +} + +void +pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot) +{ + MMU_ENTER_QUICK(mmu_obj, pmap, va, m, prot); +} + +vm_paddr_t +pmap_extract(pmap_t pmap, vm_offset_t va) +{ + return (MMU_EXTRACT(mmu_obj, pmap, va)); +} + +vm_page_t +pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot) +{ + return (MMU_EXTRACT_AND_HOLD(mmu_obj, pmap, va, prot)); +} + +void +pmap_growkernel(vm_offset_t va) +{ + MMU_GROWKERNEL(mmu_obj, va); +} + +void +pmap_init(void) +{ + MMU_INIT(mmu_obj); +} + +boolean_t +pmap_is_modified(vm_page_t m) +{ + return (MMU_IS_MODIFIED(mmu_obj, m)); +} + +boolean_t +pmap_is_prefaultable(pmap_t pmap, vm_offset_t va) +{ + return (MMU_IS_PREFAULTABLE(mmu_obj, pmap, va)); +} + +boolean_t +pmap_ts_referenced(vm_page_t m) +{ + return (MMU_TS_REFERENCED(mmu_obj, m)); +} + +vm_offset_t +pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, int prot) +{ + return (MMU_MAP(mmu_obj, virt, start, end, prot)); +} + +void +pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, + vm_pindex_t pindex, vm_size_t size) +{ + MMU_OBJECT_INIT_PT(mmu_obj, pmap, addr, object, pindex, size); +} + +boolean_t +pmap_page_exists_quick(pmap_t pmap, vm_page_t m) +{ + return (MMU_PAGE_EXISTS_QUICK(mmu_obj, pmap, m)); +} + +void +pmap_page_init(vm_page_t m) +{ + MMU_PAGE_INIT(mmu_obj, m); +} + +void +pmap_pinit(pmap_t pmap) +{ + MMU_PINIT(mmu_obj, pmap); +} + +void +pmap_pinit0(pmap_t pmap) +{ + MMU_PINIT0(mmu_obj, pmap); +} + +void +pmap_protect(pmap_t pmap, vm_offset_t start, vm_offset_t end, vm_prot_t prot) +{ + MMU_PROTECT(mmu_obj, pmap, start, end, prot); +} + +void +pmap_qenter(vm_offset_t start, vm_page_t *m, int count) +{ + MMU_QENTER(mmu_obj, start, m, count); +} + +void +pmap_qremove(vm_offset_t start, int count) +{ + MMU_QREMOVE(mmu_obj, start, count); +} + +void +pmap_release(pmap_t pmap) +{ + MMU_RELEASE(mmu_obj, pmap); +} + +void +pmap_remove(pmap_t pmap, vm_offset_t start, vm_offset_t end) +{ + MMU_REMOVE(mmu_obj, pmap, start, end); +} + +void +pmap_remove_all(vm_page_t m) +{ + MMU_REMOVE_ALL(mmu_obj, m); +} + +void +pmap_remove_pages(pmap_t pmap) +{ + MMU_REMOVE_PAGES(mmu_obj, pmap); +} + +void +pmap_remove_write(vm_page_t m) +{ + MMU_REMOVE_WRITE(mmu_obj, m); +} + +void +pmap_zero_page(vm_page_t m) +{ + MMU_ZERO_PAGE(mmu_obj, m); +} + +void +pmap_zero_page_area(vm_page_t m, int off, int size) +{ + MMU_ZERO_PAGE_AREA(mmu_obj, m, off, size); +} + +void +pmap_zero_page_idle(vm_page_t m) +{ + MMU_ZERO_PAGE_IDLE(mmu_obj, m); +} + +int +pmap_mincore(pmap_t pmap, vm_offset_t addr) +{ + return (MMU_MINCORE(mmu_obj, pmap, addr)); +} + +void +pmap_activate(struct thread *td) +{ + MMU_ACTIVATE(mmu_obj, td); +} + +void +pmap_deactivate(struct thread *td) +{ + MMU_DEACTIVATE(mmu_obj, td); +} + +vm_offset_t +pmap_addr_hint(vm_object_t obj, vm_offset_t addr, vm_size_t size) +{ + return (MMU_ADDR_HINT(mmu_obj, obj, addr, size)); +} + + + +/* + * Routines used in machine-dependent code + */ +void +pmap_bootstrap(vm_offset_t start, vm_offset_t end) +{ + mmu_obj = &mmu_kernel_obj; + + /* + * Take care of compiling the selected class, and + * then statically initialise the MMU object + */ + kobj_class_compile_static(mmu_def_impl, &mmu_kernel_kops); + kobj_init((kobj_t)mmu_obj, mmu_def_impl); + + MMU_BOOTSTRAP(mmu_obj, start, end); +} + +void * +pmap_mapdev(vm_offset_t pa, vm_size_t size) +{ + return (MMU_MAPDEV(mmu_obj, pa, size)); +} + +void +pmap_unmapdev(vm_offset_t va, vm_size_t size) +{ + MMU_UNMAPDEV(mmu_obj, va, size); +} + +vm_offset_t +pmap_kextract(vm_offset_t va) +{ + return (MMU_KEXTRACT(mmu_obj, va)); +} + +void +pmap_kenter(vm_offset_t va, vm_offset_t pa) +{ + MMU_KENTER(mmu_obj, va, pa); +} + +boolean_t +pmap_dev_direct_mapped(vm_offset_t pa, vm_size_t size) +{ + return (MMU_DEV_DIRECT_MAPPED(mmu_obj, pa, size)); +} + +boolean_t +pmap_page_executable(vm_page_t pg) +{ + return (MMU_PAGE_EXECUTABLE(mmu_obj, pg)); +} + +/* + * MMU install routines. Highest priority wins, equal priority also + * overrides allowing last-set to win. + */ +SET_DECLARE(mmu_set, mmu_def_t); + +boolean_t +pmap_mmu_install(char *name, int prio) +{ + mmu_def_t **mmupp, *mmup; + static int curr_prio = 0; + + /* + * Try and locate the MMU kobj corresponding to the name + */ + SET_FOREACH(mmupp, mmu_set) { + mmup = *mmupp; + + if (mmup->name && + !strcmp(mmup->name, name) && + prio >= curr_prio) { + curr_prio = prio; + mmu_def_impl = mmup; + return (TRUE); + } + } + + return (FALSE); +} diff --git a/sys/powerpc/powerpc/sc_machdep.c b/sys/powerpc/powerpc/sc_machdep.c new file mode 100644 index 000000000000..a81ffddbb211 --- /dev/null +++ b/sys/powerpc/powerpc/sc_machdep.c @@ -0,0 +1,90 @@ +/*- + * Copyright (c) 2003 Jake Burkholder. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/cons.h> +#include <sys/kbio.h> +#include <sys/consio.h> +#include <sys/sysctl.h> + +#include <dev/syscons/syscons.h> + +static sc_softc_t sc_softcs[8]; + +int +sc_get_cons_priority(int *unit, int *flags) +{ + + *unit = 0; + *flags = 0; + return (CN_INTERNAL); +} + +int +sc_max_unit(void) +{ + return (1); +} + +sc_softc_t * +sc_get_softc(int unit, int flags) +{ + sc_softc_t *sc; + + if (unit < 0) + return (NULL); + sc = &sc_softcs[unit]; + sc->unit = unit; + if ((sc->flags & SC_INIT_DONE) == 0) { + sc->keyboard = -1; + sc->adapter = -1; + sc->cursor_char = SC_CURSOR_CHAR; + sc->mouse_char = SC_MOUSE_CHAR; + } + return (sc); +} + +void +sc_get_bios_values(bios_values_t *values) +{ + values->cursor_start = 0; + values->cursor_end = 32; + values->shift_state = 0; +} + +int +sc_tone(int hz) +{ + return (0); +} diff --git a/sys/powerpc/powerpc/setjmp.S b/sys/powerpc/powerpc/setjmp.S new file mode 100644 index 000000000000..b372e40e3ff0 --- /dev/null +++ b/sys/powerpc/powerpc/setjmp.S @@ -0,0 +1,103 @@ +/* $FreeBSD$ */ +/* from: NetBSD: setjmp.S,v 1.1 1998/01/27 15:13:12 sakamoto Exp $ */ +/* from: OpenBSD: setjmp.S,v 1.2 1996/12/28 06:22:18 rahnds Exp */ +/* kernel version of this file, does not have signal goop */ +/* int setjmp(jmp_buf env) */ + +#define JMP_r1 0x04 +#define JMP_r14 0x08 +#define JMP_r15 0x0c +#define JMP_r16 0x10 +#define JMP_r17 0x14 +#define JMP_r18 0x18 +#define JMP_r19 0x1c +#define JMP_r20 0x20 +#define JMP_r21 0x24 +#define JMP_r22 0x28 +#define JMP_r23 0x2c +#define JMP_r24 0x30 +#define JMP_r25 0x34 +#define JMP_r26 0x38 +#define JMP_r27 0x3c +#define JMP_r28 0x40 +#define JMP_r29 0x44 +#define JMP_r30 0x48 +#define JMP_r31 0x4c +#define JMP_lr 0x50 +#define JMP_cr 0x54 +#define JMP_ctr 0x58 +#define JMP_xer 0x5c +#define JMP_sig 0x60 + + +.globl setjmp +setjmp: + stw 31, JMP_r31(3) + /* r1, r14-r30 */ + stw 1, JMP_r1 (3) + stw 14, JMP_r14(3) + stw 15, JMP_r15(3) + stw 16, JMP_r16(3) + stw 17, JMP_r17(3) + stw 18, JMP_r18(3) + stw 19, JMP_r19(3) + stw 20, JMP_r20(3) + stw 21, JMP_r21(3) + stw 22, JMP_r22(3) + stw 23, JMP_r23(3) + stw 24, JMP_r24(3) + stw 25, JMP_r25(3) + stw 26, JMP_r26(3) + stw 27, JMP_r27(3) + stw 28, JMP_r28(3) + stw 29, JMP_r29(3) + stw 30, JMP_r30(3) + /* cr, lr, ctr, xer */ + mfcr 0 + stw 0, JMP_cr(3) + mflr 0 + stw 0, JMP_lr(3) + mfctr 0 + stw 0, JMP_ctr(3) + mfxer 0 + stw 0, JMP_xer(3) + /* f14-f31, fpscr */ + li 3, 0 + blr + + +.extern sigsetmask +.globl longjmp +longjmp: + lwz 31, JMP_r31(3) + /* r1, r14-r30 */ + lwz 1, JMP_r1 (3) + lwz 14, JMP_r14(3) + lwz 15, JMP_r15(3) + lwz 16, JMP_r16(3) + lwz 17, JMP_r17(3) + lwz 18, JMP_r18(3) + lwz 19, JMP_r19(3) + lwz 20, JMP_r20(3) + lwz 21, JMP_r21(3) + lwz 22, JMP_r22(3) + lwz 23, JMP_r23(3) + lwz 24, JMP_r24(3) + lwz 25, JMP_r25(3) + lwz 26, JMP_r26(3) + lwz 27, JMP_r27(3) + lwz 28, JMP_r28(3) + lwz 29, JMP_r29(3) + lwz 30, JMP_r30(3) + /* cr, lr, ctr, xer */ + lwz 0, JMP_cr(3) + mtcr 0 + lwz 0, JMP_lr(3) + mtlr 0 + lwz 0, JMP_ctr(3) + mtctr 0 + lwz 0, JMP_xer(3) + mtxer 0 + /* f14-f31, fpscr */ + mr 3, 4 + blr diff --git a/sys/powerpc/powerpc/sigcode.S b/sys/powerpc/powerpc/sigcode.S new file mode 100644 index 000000000000..af0ed49e153b --- /dev/null +++ b/sys/powerpc/powerpc/sigcode.S @@ -0,0 +1,59 @@ +/* $FreeBSD$ */ +/* $NetBSD: sigcode.S,v 1.1 1999/11/17 14:56:11 kleink Exp $ */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <machine/asm.h> +#include <sys/syscall.h> +#include "assym.s" + +/* + * The following code gets copied to the top of the user stack on process + * execution. It does signal trampolining on signal delivery. + * + * On entry r1 points to a struct sigframe at bottom of current stack. + * All other registers are unchanged. + */ + .globl CNAME(sigcode),CNAME(szsigcode) +CNAME(sigcode): + addi 1,1,-16 /* reserved space for callee */ + blrl + addi 3,1,16+SF_UC /* restore sp, and get &frame->sf_uc */ + li 0,SYS_sigreturn + sc /* sigreturn(scp) */ + li 0,SYS_exit + sc /* exit(errno) */ +endsigcode: + + .data +CNAME(szsigcode): + .long endsigcode - CNAME(sigcode) diff --git a/sys/powerpc/powerpc/suswintr.c b/sys/powerpc/powerpc/suswintr.c new file mode 100644 index 000000000000..0252201e8a4b --- /dev/null +++ b/sys/powerpc/powerpc/suswintr.c @@ -0,0 +1,51 @@ +/*- + * Copyright (C) 1994 Wolfgang Solfrank. + * Copyright (C) 1994 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: suswintr.c,v 1.2 2000/06/09 14:05:48 kleink Exp $ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/resourcevar.h> + +/* + * Emulate suswintr + * + * Simply return fault for all cases + */ +int +suswintr(void *addr, int s) +{ + + return -1; +} diff --git a/sys/powerpc/powerpc/swtch.S b/sys/powerpc/powerpc/swtch.S new file mode 100644 index 000000000000..038e788b9175 --- /dev/null +++ b/sys/powerpc/powerpc/swtch.S @@ -0,0 +1,154 @@ +/* $FreeBSD$ */ +/* $NetBSD: locore.S,v 1.24 2000/05/31 05:09:17 thorpej Exp $ */ + +/*- + * Copyright (C) 2001 Benno Rice + * 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 Benno Rice ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "assym.s" + +#include <sys/syscall.h> + +#include <machine/trap.h> +#include <machine/param.h> +#include <machine/sr.h> +#include <machine/psl.h> +#include <machine/asm.h> + +/* + * void cpu_switch(struct thread *old, struct thread *new) + * + * Switch to a new thread saving the current state in the old thread. + */ +ENTRY(cpu_switch) + lwz %r5,TD_PCB(%r3) /* Get the old thread's PCB ptr */ + + mr %r12,%r2 + stmw %r12,PCB_CONTEXT(%r5) /* Save the non-volatile GP regs. + These can now be used for scratch */ + + mfcr %r16 /* Save the condition register */ + stw %r16,PCB_CR(%r5) + mflr %r16 /* Save the link register */ + stw %r16,PCB_LR(%r5) + mfsr %r16,USER_SR /* Save USER_SR for copyin/out */ + isync + stw %r16,PCB_USR(%r5) + stw %r1,PCB_SP(%r5) /* Save the stack pointer */ + + mr %r14,%r3 /* Copy the old thread ptr... */ + mr %r15,%r4 /* and the new thread ptr in scratch */ + + lwz %r6,PCB_FLAGS(%r5) /* Save FPU context if needed */ + andi. %r6, %r6, PCB_FPU + beq .L1 + bl save_fpu + mr %r3,%r14 /* restore old thread ptr */ +.L1: + bl pmap_deactivate /* Deactivate the current pmap */ + + mr %r3,%r15 /* Get new thread ptr */ + bl pmap_activate /* Activate the new address space */ + + mfsprg %r7,0 /* Get the pcpu pointer */ + stw %r15,PC_CURTHREAD(%r7) /* Store new current thread */ + lwz %r17,TD_PCB(%r15) /* Store new current PCB */ + stw %r17,PC_CURPCB(%r7) + + lwz %r6, PCB_FLAGS(%r17) /* Restore FPU context if needed */ + andi. %r6, %r6, PCB_FPU + beq .L2 + mr %r3,%r15 /* Pass curthread to enable_fpu */ + bl enable_fpu + + /* thread to restore is in r3 */ +.L2: + mr %r3,%r17 /* Recover PCB ptr */ + lmw %r12,PCB_CONTEXT(%r3) /* Load the non-volatile GP regs */ + mr %r2,%r12 + lwz %r5,PCB_CR(%r3) /* Load the condition register */ + mtcr %r5 + lwz %r5,PCB_LR(%r3) /* Load the link register */ + mtlr %r5 + lwz %r5,PCB_USR(%r3) /* Load the USER_SR segment reg */ + mtsr USER_SR,%r5 + isync + lwz %r1,PCB_SP(%r3) /* Load the stack pointer */ + blr + +/* + * savectx(pcb) + * Update pcb, saving current processor state + */ +ENTRY(savectx) + mr %r12,%r2 + stmw %r12,PCB_CONTEXT(%r3) /* Save the non-volatile GP regs */ + mfcr %r4 /* Save the condition register */ + stw %r4,PCB_CONTEXT(%r3) + blr + +/* + * fork_trampoline() + * Set up the return from cpu_fork() + */ +ENTRY(fork_trampoline) + lwz %r3,CF_FUNC(%r1) + lwz %r4,CF_ARG0(%r1) + lwz %r5,CF_ARG1(%r1) + bl fork_exit + addi %r1,%r1,CF_SIZE-FSP /* Allow 8 bytes in front of + trapframe to simulate FRAME_SETUP + does when allocating space for + a frame pointer/saved LR */ + b trapexit diff --git a/sys/powerpc/powerpc/syncicache.c b/sys/powerpc/powerpc/syncicache.c new file mode 100644 index 000000000000..3d4f732e72bf --- /dev/null +++ b/sys/powerpc/powerpc/syncicache.c @@ -0,0 +1,96 @@ +/*- + * Copyright (C) 1995-1997, 1999 Wolfgang Solfrank. + * Copyright (C) 1995-1997, 1999 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: syncicache.c,v 1.2 1999/05/05 12:36:40 tsubai Exp $ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#if defined(_KERNEL) || defined(_STANDALONE) +#include <sys/time.h> +#include <sys/proc.h> +#include <vm/vm.h> +#endif +#include <sys/sysctl.h> + +#include <machine/md_var.h> + +#if defined(_KERNEL) || defined(_STANDALONE) +#ifndef CACHELINESIZE +#error "Must know the size of a cache line" +#endif +#else +static void getcachelinesize(void); + +static int _cachelinesize; +#define CACHELINESIZE _cachelinesize + +static void +getcachelinesize() +{ + static int cachemib[] = { CTL_MACHDEP, CPU_CACHELINE }; + int clen; + + clen = sizeof(_cachelinesize); + + if (sysctl(cachemib, sizeof(cachemib) / sizeof(cachemib[0]), + &_cachelinesize, &clen, NULL, 0) < 0 || !_cachelinesize) { + abort(); + } +} +#endif + +void +__syncicache(void *from, int len) +{ + int l, off; + char *p; + +#if !defined(_KERNEL) && !defined(_STANDALONE) + if (!_cachelinesize) + getcachelinesize(); +#endif + off = (u_int)from & (CACHELINESIZE - 1); + l = len += off; + p = (char *)from - off; + do { + __asm __volatile ("dcbst 0,%0" :: "r"(p)); + p += CACHELINESIZE; + } while ((l -= CACHELINESIZE) > 0); + __asm __volatile ("sync"); + p = (char *)from - off; + do { + __asm __volatile ("icbi 0,%0" :: "r"(p)); + p += CACHELINESIZE; + } while ((len -= CACHELINESIZE) > 0); + __asm __volatile ("sync; isync"); +} diff --git a/sys/powerpc/powerpc/sys_machdep.c b/sys/powerpc/powerpc/sys_machdep.c new file mode 100644 index 000000000000..86e6e077c3f4 --- /dev/null +++ b/sys/powerpc/powerpc/sys_machdep.c @@ -0,0 +1,39 @@ +/*- + * Copyright (C) 2001 Benno Rice. + * 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 Benno Rice ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/errno.h> +#include <sys/sysproto.h> + +int +sysarch(struct thread *td, struct sysarch_args *uap) +{ + + return (EINVAL); +} diff --git a/sys/powerpc/powerpc/trap.c b/sys/powerpc/powerpc/trap.c new file mode 100644 index 000000000000..a5ab7ebbffb2 --- /dev/null +++ b/sys/powerpc/powerpc/trap.c @@ -0,0 +1,681 @@ +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: trap.c,v 1.58 2002/03/04 04:07:35 dbj Exp $ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "opt_ktrace.h" + +#include <sys/param.h> +#include <sys/kdb.h> +#include <sys/proc.h> +#include <sys/ktr.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/pioctl.h> +#include <sys/ptrace.h> +#include <sys/reboot.h> +#include <sys/syscall.h> +#include <sys/sysent.h> +#include <sys/systm.h> +#include <sys/uio.h> +#include <sys/signalvar.h> +#ifdef KTRACE +#include <sys/ktrace.h> +#endif +#include <sys/vmmeter.h> + +#include <security/audit/audit.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_extern.h> +#include <vm/vm_param.h> +#include <vm/vm_kern.h> +#include <vm/vm_map.h> +#include <vm/vm_page.h> + +#include <machine/cpu.h> +#include <machine/db_machdep.h> +#include <machine/fpu.h> +#include <machine/frame.h> +#include <machine/pcb.h> +#include <machine/pmap.h> +#include <machine/psl.h> +#include <machine/trap.h> +#include <machine/spr.h> +#include <machine/sr.h> + +static void trap_fatal(struct trapframe *frame); +static void printtrap(u_int vector, struct trapframe *frame, int isfatal, + int user); +static int trap_pfault(struct trapframe *frame, int user); +static int fix_unaligned(struct thread *td, struct trapframe *frame); +static int handle_onfault(struct trapframe *frame); +static void syscall(struct trapframe *frame); + +static __inline void setusr(u_int); + +int setfault(faultbuf); /* defined in locore.S */ + +/* Why are these not defined in a header? */ +int badaddr(void *, size_t); +int badaddr_read(void *, size_t, int *); + +extern char *syscallnames[]; + +struct powerpc_exception { + u_int vector; + char *name; +}; + +static struct powerpc_exception powerpc_exceptions[] = { + { 0x0100, "system reset" }, + { 0x0200, "machine check" }, + { 0x0300, "data storage interrupt" }, + { 0x0400, "instruction storage interrupt" }, + { 0x0500, "external interrupt" }, + { 0x0600, "alignment" }, + { 0x0700, "program" }, + { 0x0800, "floating-point unavailable" }, + { 0x0900, "decrementer" }, + { 0x0c00, "system call" }, + { 0x0d00, "trace" }, + { 0x0e00, "floating-point assist" }, + { 0x0f00, "performance monitoring" }, + { 0x0f20, "altivec unavailable" }, + { 0x1000, "instruction tlb miss" }, + { 0x1100, "data load tlb miss" }, + { 0x1200, "data store tlb miss" }, + { 0x1300, "instruction breakpoint" }, + { 0x1400, "system management" }, + { 0x1600, "altivec assist" }, + { 0x1700, "thermal management" }, + { 0x2000, "run mode/trace" }, + { 0x3000, NULL } +}; + +static const char * +trapname(u_int vector) +{ + struct powerpc_exception *pe; + + for (pe = powerpc_exceptions; pe->vector != 0x3000; pe++) { + if (pe->vector == vector) + return (pe->name); + } + + return ("unknown"); +} + +void +trap(struct trapframe *frame) +{ + struct thread *td; + struct proc *p; + int sig, type, user; + u_int ucode; + ksiginfo_t ksi; + + PCPU_INC(cnt.v_trap); + + td = PCPU_GET(curthread); + p = td->td_proc; + + type = ucode = frame->exc; + sig = 0; + user = frame->srr1 & PSL_PR; + + CTR3(KTR_TRAP, "trap: %s type=%s (%s)", p->p_comm, + trapname(type), user ? "user" : "kernel"); + + if (user) { + td->td_pticks = 0; + td->td_frame = frame; + if (td->td_ucred != p->p_ucred) + cred_update_thread(td); + + /* User Mode Traps */ + switch (type) { + case EXC_RUNMODETRC: + case EXC_TRC: + frame->srr1 &= ~PSL_SE; + sig = SIGTRAP; + break; + + case EXC_DSI: + case EXC_ISI: + sig = trap_pfault(frame, 1); + break; + + case EXC_SC: + syscall(frame); + break; + + case EXC_FPU: + KASSERT((td->td_pcb->pcb_flags & PCB_FPU) != PCB_FPU, + ("FPU already enabled for thread")); + enable_fpu(td); + break; + +#ifdef ALTIVEC + case EXC_VEC: + if ((vecthread = PCPU_GET(vecthread)) != NULL) { + KASSERT(vecthread != td, + ("altivec already enabled")); + save_vec(vecthread); + } + PCPU_SET(vecthread, td); + td->td_pcb->pcb_veccpu = PCPU_GET(cpuid); + enable_vec(td); + frame->srr1 |= PSL_VEC; + break; +#else + case EXC_VEC: + case EXC_VECAST: + sig = SIGILL; + break; +#endif /* ALTIVEC */ + + case EXC_ALI: + if (fix_unaligned(td, frame) != 0) + sig = SIGBUS; + else + frame->srr0 += 4; + break; + + case EXC_PGM: + /* XXX temporarily */ + /* XXX: Magic Number? */ + if (frame->srr1 & 0x0002000) + sig = SIGTRAP; + else + sig = SIGILL; + break; + + default: + trap_fatal(frame); + } + } else { + /* Kernel Mode Traps */ + + KASSERT(cold || td->td_ucred != NULL, + ("kernel trap doesn't have ucred")); + switch (type) { + case EXC_DSI: + if (trap_pfault(frame, 0) == 0) + return; + break; + case EXC_MCHK: + if (handle_onfault(frame)) + return; + break; + default: + break; + } + trap_fatal(frame); + } + +#ifdef ALTIVEC + if (td != PCPU_GET(vecthread) || + td->td_pcb->pcb_veccpu != PCPU_GET(cpuid)) + frame->srr1 &= ~PSL_VEC; +#endif /* ALTIVEC */ + + if (sig != 0) { + if (p->p_sysent->sv_transtrap != NULL) + sig = (p->p_sysent->sv_transtrap)(sig, type); + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = sig; + ksi.ksi_code = (int) ucode; /* XXX, not POSIX */ + /* ksi.ksi_addr = ? */ + ksi.ksi_trapno = type; + trapsignal(td, &ksi); + } + + userret(td, frame); + mtx_assert(&Giant, MA_NOTOWNED); +} + +static void +trap_fatal(struct trapframe *frame) +{ + + printtrap(frame->exc, frame, 1, (frame->srr1 & PSL_PR)); +#ifdef KDB + if ((debugger_on_panic || kdb_active) && + kdb_trap(frame->exc, 0, frame)) + return; +#endif + panic("%s trap", trapname(frame->exc)); +} + +static void +printtrap(u_int vector, struct trapframe *frame, int isfatal, int user) +{ + + printf("\n"); + printf("%s %s trap:\n", isfatal ? "fatal" : "handled", + user ? "user" : "kernel"); + printf("\n"); + printf(" exception = 0x%x (%s)\n", vector >> 8, + trapname(vector)); + switch (vector) { + case EXC_DSI: + printf(" virtual address = 0x%x\n", frame->dar); + break; + case EXC_ISI: + printf(" virtual address = 0x%x\n", frame->srr0); + break; + } + printf(" srr0 = 0x%x\n", frame->srr0); + printf(" srr1 = 0x%x\n", frame->srr1); + printf(" curthread = %p\n", curthread); + if (curthread != NULL) + printf(" pid = %d, comm = %s\n", + curthread->td_proc->p_pid, curthread->td_proc->p_comm); + printf("\n"); +} + +/* + * Handles a fatal fault when we have onfault state to recover. Returns + * non-zero if there was onfault recovery state available. + */ +static int +handle_onfault(struct trapframe *frame) +{ + struct thread *td; + faultbuf *fb; + + td = curthread; + fb = td->td_pcb->pcb_onfault; + if (fb != NULL) { + frame->srr0 = (*fb)[0]; + frame->fixreg[1] = (*fb)[1]; + frame->fixreg[2] = (*fb)[2]; + frame->fixreg[3] = 1; + frame->cr = (*fb)[3]; + bcopy(&(*fb)[4], &frame->fixreg[13], + 19 * sizeof(register_t)); + return (1); + } + return (0); +} + +void +syscall(struct trapframe *frame) +{ + caddr_t params; + struct sysent *callp; + struct thread *td; + struct proc *p; + int error, n; + size_t narg; + register_t args[10]; + u_int code; + + td = PCPU_GET(curthread); + p = td->td_proc; + + PCPU_INC(cnt.v_syscall); + +#ifdef KSE + if (p->p_flag & P_SA) + thread_user_enter(td); +#endif + + code = frame->fixreg[0]; + params = (caddr_t)(frame->fixreg + FIRSTARG); + n = NARGREG; + + if (p->p_sysent->sv_prepsyscall) { + /* + * The prep code is MP aware. + */ + (*p->p_sysent->sv_prepsyscall)(frame, args, &code, ¶ms); + } else if (code == SYS_syscall) { + /* + * code is first argument, + * followed by actual args. + */ + code = *(u_int *) params; + params += sizeof(register_t); + n -= 1; + } else if (code == SYS___syscall) { + /* + * Like syscall, but code is a quad, + * so as to maintain quad alignment + * for the rest of the args. + */ + params += sizeof(register_t); + code = *(u_int *) params; + params += sizeof(register_t); + n -= 2; + } + + if (p->p_sysent->sv_mask) + code &= p->p_sysent->sv_mask; + + if (code >= p->p_sysent->sv_size) + callp = &p->p_sysent->sv_table[0]; + else + callp = &p->p_sysent->sv_table[code]; + + narg = callp->sy_narg; + + if (narg > n) { + bcopy(params, args, n * sizeof(register_t)); + error = copyin(MOREARGS(frame->fixreg[1]), args + n, + (narg - n) * sizeof(register_t)); + params = (caddr_t)args; + } else + error = 0; + + CTR5(KTR_SYSC, "syscall: p=%s %s(%x %x %x)", p->p_comm, + syscallnames[code], + frame->fixreg[FIRSTARG], + frame->fixreg[FIRSTARG+1], + frame->fixreg[FIRSTARG+2]); + +#ifdef KTRACE + if (KTRPOINT(td, KTR_SYSCALL)) + ktrsyscall(code, narg, (register_t *)params); +#endif + + td->td_syscalls++; + + if (error == 0) { + td->td_retval[0] = 0; + td->td_retval[1] = frame->fixreg[FIRSTARG + 1]; + + STOPEVENT(p, S_SCE, narg); + + PTRACESTOP_SC(p, td, S_PT_SCE); + + AUDIT_SYSCALL_ENTER(code, td); + error = (*callp->sy_call)(td, params); + AUDIT_SYSCALL_EXIT(error, td); + + CTR3(KTR_SYSC, "syscall: p=%s %s ret=%x", p->p_comm, + syscallnames[code], td->td_retval[0]); + } + switch (error) { + case 0: + if (frame->fixreg[0] == SYS___syscall && + code != SYS_freebsd6_lseek && code != SYS_lseek) { + /* + * 64-bit return, 32-bit syscall. Fixup byte order + */ + frame->fixreg[FIRSTARG] = 0; + frame->fixreg[FIRSTARG + 1] = td->td_retval[0]; + } else { + frame->fixreg[FIRSTARG] = td->td_retval[0]; + frame->fixreg[FIRSTARG + 1] = td->td_retval[1]; + } + /* XXX: Magic number */ + frame->cr &= ~0x10000000; + break; + case ERESTART: + /* + * Set user's pc back to redo the system call. + */ + frame->srr0 -= 4; + break; + case EJUSTRETURN: + /* nothing to do */ + break; + default: + if (p->p_sysent->sv_errsize) { + if (error >= p->p_sysent->sv_errsize) + error = -1; /* XXX */ + else + error = p->p_sysent->sv_errtbl[error]; + } + frame->fixreg[FIRSTARG] = error; + /* XXX: Magic number: Carry Flag Equivalent? */ + frame->cr |= 0x10000000; + break; + } + + /* + * Check for misbehavior. + */ + WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???"); + KASSERT(td->td_critnest == 0, + ("System call %s returning in a critical section", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???")); + KASSERT(td->td_locks == 0, + ("System call %s returning with %d locks held", + (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???", + td->td_locks)); + +#ifdef KTRACE + if (KTRPOINT(td, KTR_SYSRET)) + ktrsysret(code, error, td->td_retval[0]); +#endif + + /* + * Does the comment in the i386 code about errno apply here? + */ + STOPEVENT(p, S_SCX, code); + + PTRACESTOP_SC(p, td, S_PT_SCX); +} + +static int +trap_pfault(struct trapframe *frame, int user) +{ + vm_offset_t eva, va; + struct thread *td; + struct proc *p; + vm_map_t map; + vm_prot_t ftype; + int rv; + u_int user_sr; + + td = curthread; + p = td->td_proc; + if (frame->exc == EXC_ISI) { + eva = frame->srr0; + ftype = VM_PROT_READ | VM_PROT_EXECUTE; + } else { + eva = frame->dar; + if (frame->dsisr & DSISR_STORE) + ftype = VM_PROT_WRITE; + else + ftype = VM_PROT_READ; + } + + if (user) { + map = &p->p_vmspace->vm_map; + } else { + if ((eva >> ADDR_SR_SHFT) == USER_SR) { + if (p->p_vmspace == NULL) + return (SIGSEGV); + + __asm ("mfsr %0, %1" + : "=r"(user_sr) + : "K"(USER_SR)); + eva &= ADDR_PIDX | ADDR_POFF; + eva |= user_sr << ADDR_SR_SHFT; + map = &p->p_vmspace->vm_map; + } else { + map = kernel_map; + } + } + va = trunc_page(eva); + + if (map != kernel_map) { + /* + * Keep swapout from messing with us during this + * critical time. + */ + PROC_LOCK(p); + ++p->p_lock; + PROC_UNLOCK(p); + + /* Fault in the user page: */ + rv = vm_fault(map, va, ftype, + (ftype & VM_PROT_WRITE) ? VM_FAULT_DIRTY + : VM_FAULT_NORMAL); + + PROC_LOCK(p); + --p->p_lock; + PROC_UNLOCK(p); + } else { + /* + * Don't have to worry about process locking or stacks in the + * kernel. + */ + rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL); + } + + if (rv == KERN_SUCCESS) + return (0); + + if (!user && handle_onfault(frame)) + return (0); + + return (SIGSEGV); +} + +static __inline void +setusr(u_int content) +{ + __asm __volatile ("isync; mtsr %0,%1; isync" + :: "n"(USER_SR), "r"(content)); +} + +int +badaddr(void *addr, size_t size) +{ + return (badaddr_read(addr, size, NULL)); +} + +int +badaddr_read(void *addr, size_t size, int *rptr) +{ + struct thread *td; + faultbuf env; + int x; + + /* Get rid of any stale machine checks that have been waiting. */ + __asm __volatile ("sync; isync"); + + td = PCPU_GET(curthread); + + if (setfault(env)) { + td->td_pcb->pcb_onfault = 0; + __asm __volatile ("sync"); + return 1; + } + + __asm __volatile ("sync"); + + switch (size) { + case 1: + x = *(volatile int8_t *)addr; + break; + case 2: + x = *(volatile int16_t *)addr; + break; + case 4: + x = *(volatile int32_t *)addr; + break; + default: + panic("badaddr: invalid size (%d)", size); + } + + /* Make sure we took the machine check, if we caused one. */ + __asm __volatile ("sync; isync"); + + td->td_pcb->pcb_onfault = 0; + __asm __volatile ("sync"); /* To be sure. */ + + /* Use the value to avoid reorder. */ + if (rptr) + *rptr = x; + + return (0); +} + +/* + * For now, this only deals with the particular unaligned access case + * that gcc tends to generate. Eventually it should handle all of the + * possibilities that can happen on a 32-bit PowerPC in big-endian mode. + */ + +static int +fix_unaligned(struct thread *td, struct trapframe *frame) +{ + struct thread *fputhread; + int indicator, reg; + double *fpr; + + indicator = EXC_ALI_OPCODE_INDICATOR(frame->dsisr); + + switch (indicator) { + case EXC_ALI_LFD: + case EXC_ALI_STFD: + reg = EXC_ALI_RST(frame->dsisr); + fpr = &td->td_pcb->pcb_fpu.fpr[reg]; + fputhread = PCPU_GET(fputhread); + + /* Juggle the FPU to ensure that we've initialized + * the FPRs, and that their current state is in + * the PCB. + */ + if (fputhread != td) { + if (fputhread) + save_fpu(fputhread); + enable_fpu(td); + } + save_fpu(td); + + if (indicator == EXC_ALI_LFD) { + if (copyin((void *)frame->dar, fpr, + sizeof(double)) != 0) + return -1; + enable_fpu(td); + } else { + if (copyout(fpr, (void *)frame->dar, + sizeof(double)) != 0) + return -1; + } + return 0; + break; + } + + return -1; +} diff --git a/sys/powerpc/powerpc/trap_subr.S b/sys/powerpc/powerpc/trap_subr.S new file mode 100644 index 000000000000..06ed891406f9 --- /dev/null +++ b/sys/powerpc/powerpc/trap_subr.S @@ -0,0 +1,540 @@ +/* $FreeBSD$ */ +/* $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink Exp $ */ + +/*- + * Copyright (C) 1995, 1996 Wolfgang Solfrank. + * Copyright (C) 1995, 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * NOTICE: This is not a standalone file. to use it, #include it in + * your port's locore.S, like so: + * + * #include <powerpc/powerpc/trap_subr.S> + */ + +/* + * Save/restore segment registers + */ +#define RESTORE_SRS(pmap,sr) mtsr 0,sr; \ + lwz sr,1*4(pmap); mtsr 1,sr; \ + lwz sr,2*4(pmap); mtsr 2,sr; \ + lwz sr,3*4(pmap); mtsr 3,sr; \ + lwz sr,4*4(pmap); mtsr 4,sr; \ + lwz sr,5*4(pmap); mtsr 5,sr; \ + lwz sr,6*4(pmap); mtsr 6,sr; \ + lwz sr,7*4(pmap); mtsr 7,sr; \ + lwz sr,8*4(pmap); mtsr 8,sr; \ + lwz sr,9*4(pmap); mtsr 9,sr; \ + lwz sr,10*4(pmap); mtsr 10,sr; \ + lwz sr,11*4(pmap); mtsr 11,sr; \ + lwz sr,12*4(pmap); mtsr 12,sr; \ + lwz sr,13*4(pmap); mtsr 13,sr; \ + lwz sr,14*4(pmap); mtsr 14,sr; \ + lwz sr,15*4(pmap); mtsr 15,sr; isync; + +/* + * User SRs are loaded through a pointer to the current pmap. + */ +#define RESTORE_USER_SRS(pmap,sr) \ + GET_CPUINFO(pmap); \ + lwz pmap,PC_CURPMAP(pmap); \ + lwzu sr,PM_SR(pmap); \ + RESTORE_SRS(pmap,sr) + +/* + * Kernel SRs are loaded directly from kernel_pmap_ + */ +#define RESTORE_KERN_SRS(pmap,sr) \ + lis pmap,CNAME(kernel_pmap_store)@ha; \ + lwzu sr,CNAME(kernel_pmap_store)+PM_SR@l(pmap); \ + RESTORE_SRS(pmap,sr) + +/* + * FRAME_SETUP assumes: + * SPRG1 SP (1) + * savearea r28-r31,DAR,DSISR (DAR & DSISR only for DSI traps) + * r28 LR + * r29 CR + * r30 scratch + * r31 scratch + * r1 kernel stack + * LR trap type (from calling address, mask with 0xff00) + * SRR0/1 as at start of trap + */ +#define FRAME_SETUP(savearea) \ +/* Have to enable translation to allow access of kernel stack: */ \ + GET_CPUINFO(%r31); \ + mfsrr0 %r30; \ + stw %r30,(savearea+CPUSAVE_SRR0)(%r31); /* save SRR0 */ \ + mfsrr1 %r30; \ + stw %r30,(savearea+CPUSAVE_SRR1)(%r31); /* save SRR1 */ \ + mfmsr %r30; \ + ori %r30,%r30,(PSL_DR|PSL_IR|PSL_RI)@l; /* relocation on */ \ + mtmsr %r30; /* stack can now be accessed */ \ + isync; \ + mfsprg1 %r31; /* get saved SP */ \ + stwu %r31,-FRAMELEN(%r1); /* save it in the callframe */ \ + stw %r0, FRAME_0+8(%r1); /* save r0 in the trapframe */ \ + stw %r31,FRAME_1+8(%r1); /* save SP " " */ \ + stw %r2, FRAME_2+8(%r1); /* save r2 " " */ \ + stw %r28,FRAME_LR+8(%r1); /* save LR " " */ \ + stw %r29,FRAME_CR+8(%r1); /* save CR " " */ \ + GET_CPUINFO(%r2); \ + lwz %r28,(savearea+CPUSAVE_R28)(%r2); /* get saved r28 */ \ + lwz %r29,(savearea+CPUSAVE_R29)(%r2); /* get saved r29 */ \ + lwz %r30,(savearea+CPUSAVE_R30)(%r2); /* get saved r30 */ \ + lwz %r31,(savearea+CPUSAVE_R31)(%r2); /* get saved r31 */ \ + stw %r3, FRAME_3+8(%r1); /* save r3-r31 */ \ + stw %r4, FRAME_4+8(%r1); \ + stw %r5, FRAME_5+8(%r1); \ + stw %r6, FRAME_6+8(%r1); \ + stw %r7, FRAME_7+8(%r1); \ + stw %r8, FRAME_8+8(%r1); \ + stw %r9, FRAME_9+8(%r1); \ + stw %r10, FRAME_10+8(%r1); \ + stw %r11, FRAME_11+8(%r1); \ + stw %r12, FRAME_12+8(%r1); \ + stw %r13, FRAME_13+8(%r1); \ + stw %r14, FRAME_14+8(%r1); \ + stw %r15, FRAME_15+8(%r1); \ + stw %r16, FRAME_16+8(%r1); \ + stw %r17, FRAME_17+8(%r1); \ + stw %r18, FRAME_18+8(%r1); \ + stw %r19, FRAME_19+8(%r1); \ + stw %r20, FRAME_20+8(%r1); \ + stw %r21, FRAME_21+8(%r1); \ + stw %r22, FRAME_22+8(%r1); \ + stw %r23, FRAME_23+8(%r1); \ + stw %r24, FRAME_24+8(%r1); \ + stw %r25, FRAME_25+8(%r1); \ + stw %r26, FRAME_26+8(%r1); \ + stw %r27, FRAME_27+8(%r1); \ + stw %r28, FRAME_28+8(%r1); \ + stw %r29, FRAME_29+8(%r1); \ + stw %r30, FRAME_30+8(%r1); \ + stw %r31, FRAME_31+8(%r1); \ + lwz %r28,(savearea+CPUSAVE_DAR)(%r2); /* saved DAR */ \ + lwz %r29,(savearea+CPUSAVE_DSISR)(%r2);/* saved DSISR */ \ + lwz %r30,(savearea+CPUSAVE_SRR0)(%r2); /* saved SRR0 */ \ + lwz %r31,(savearea+CPUSAVE_SRR1)(%r2); /* saved SRR1 */ \ + mfxer %r3; \ + mfctr %r4; \ + mflr %r5; \ + andi. %r5,%r5,0xff00; /* convert LR to exc # */ \ + stw %r3, FRAME_XER+8(1); /* save xer/ctr/exc */ \ + stw %r4, FRAME_CTR+8(1); \ + stw %r5, FRAME_EXC+8(1); \ + stw %r28,FRAME_DAR+8(1); \ + stw %r29,FRAME_DSISR+8(1); /* save dsisr/srr0/srr1 */ \ + stw %r30,FRAME_SRR0+8(1); \ + stw %r31,FRAME_SRR1+8(1) + +#define FRAME_LEAVE(savearea) \ +/* Now restore regs: */ \ + lwz %r2,FRAME_SRR0+8(%r1); \ + lwz %r3,FRAME_SRR1+8(%r1); \ + lwz %r4,FRAME_CTR+8(%r1); \ + lwz %r5,FRAME_XER+8(%r1); \ + lwz %r6,FRAME_LR+8(%r1); \ + GET_CPUINFO(%r7); \ + stw %r2,(savearea+CPUSAVE_SRR0)(%r7); /* save SRR0 */ \ + stw %r3,(savearea+CPUSAVE_SRR1)(%r7); /* save SRR1 */ \ + lwz %r7,FRAME_CR+8(%r1); \ + mtctr %r4; \ + mtxer %r5; \ + mtlr %r6; \ + mtsprg1 %r7; /* save cr */ \ + lwz %r31,FRAME_31+8(%r1); /* restore r0-31 */ \ + lwz %r30,FRAME_30+8(%r1); \ + lwz %r29,FRAME_29+8(%r1); \ + lwz %r28,FRAME_28+8(%r1); \ + lwz %r27,FRAME_27+8(%r1); \ + lwz %r26,FRAME_26+8(%r1); \ + lwz %r25,FRAME_25+8(%r1); \ + lwz %r24,FRAME_24+8(%r1); \ + lwz %r23,FRAME_23+8(%r1); \ + lwz %r22,FRAME_22+8(%r1); \ + lwz %r21,FRAME_21+8(%r1); \ + lwz %r20,FRAME_20+8(%r1); \ + lwz %r19,FRAME_19+8(%r1); \ + lwz %r18,FRAME_18+8(%r1); \ + lwz %r17,FRAME_17+8(%r1); \ + lwz %r16,FRAME_16+8(%r1); \ + lwz %r15,FRAME_15+8(%r1); \ + lwz %r14,FRAME_14+8(%r1); \ + lwz %r13,FRAME_13+8(%r1); \ + lwz %r12,FRAME_12+8(%r1); \ + lwz %r11,FRAME_11+8(%r1); \ + lwz %r10,FRAME_10+8(%r1); \ + lwz %r9, FRAME_9+8(%r1); \ + lwz %r8, FRAME_8+8(%r1); \ + lwz %r7, FRAME_7+8(%r1); \ + lwz %r6, FRAME_6+8(%r1); \ + lwz %r5, FRAME_5+8(%r1); \ + lwz %r4, FRAME_4+8(%r1); \ + lwz %r3, FRAME_3+8(%r1); \ + lwz %r2, FRAME_2+8(%r1); \ + lwz %r0, FRAME_0+8(%r1); \ + lwz %r1, FRAME_1+8(%r1); \ +/* Can't touch %r1 from here on */ \ + mtsprg2 %r2; /* save r2 & r3 */ \ + mtsprg3 %r3; \ +/* Disable translation, machine check and recoverability: */ \ + mfmsr %r2; \ + andi. %r2,%r2,~(PSL_DR|PSL_IR|PSL_EE|PSL_ME|PSL_RI)@l; \ + mtmsr %r2; \ + isync; \ +/* Decide whether we return to user mode: */ \ + GET_CPUINFO(%r2); \ + lwz %r3,(savearea+CPUSAVE_SRR1)(%r2); \ + mtcr %r3; \ + bf 17,1f; /* branch if PSL_PR is false */ \ +/* Restore user SRs */ \ + RESTORE_USER_SRS(%r2,%r3); \ +1: mfsprg1 %r2; /* restore cr */ \ + mtcr %r2; \ + GET_CPUINFO(%r2); \ + lwz %r3,(savearea+CPUSAVE_SRR0)(%r2); /* restore srr0 */ \ + mtsrr0 %r3; \ + lwz %r3,(savearea+CPUSAVE_SRR1)(%r2); /* restore srr1 */ \ + mtsrr1 %r3; \ + mfsprg2 %r2; /* restore r2 & r3 */ \ + mfsprg3 %r3 + +#ifdef KDB +/* + * Define the kdb debugger stack + */ + .data +GLOBAL(dbstk) + .space INTSTK+8 /* kdb stack */ +#endif + +/* + * This code gets copied to all the trap vectors + * (except ISI/DSI, ALI, and the interrupts) + */ + .text + .globl CNAME(trapcode),CNAME(trapsize) +CNAME(trapcode): + mtsprg1 %r1 /* save SP */ + GET_CPUINFO(%r1) + stw %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) /* free r28-r31 */ + stw %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) + stw %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) + stw %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) + mfsprg1 %r1 /* restore SP, in case of branch */ + mflr %r28 /* save LR */ + mfcr %r29 /* save CR */ +/* Test whether we already had PR set */ + mfsrr1 %r31 + mtcr %r31 + bla s_trap /* LR & 0xff00 is exception # */ +CNAME(trapsize) = .-CNAME(trapcode) + +/* + * For ALI: has to save DSISR and DAR + */ + .globl CNAME(alitrap),CNAME(alisize) +CNAME(alitrap): + mtsprg1 %r1 /* save SP */ + GET_CPUINFO(%r1) + stw %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) /* free r28-r31 */ + stw %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) + stw %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) + stw %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) + mfdar %r30 + mfdsisr %r31 + stw %r30,(PC_TEMPSAVE+CPUSAVE_DAR)(%r1) + stw %r31,(PC_TEMPSAVE+CPUSAVE_DSISR)(%r1) + mfsprg1 %r1 /* restore SP, in case of branch */ + mflr %r28 /* save LR */ + mfcr %r29 /* save CR */ +/* Test whether we already had PR set */ + mfsrr1 %r31 + mtcr %r31 + bla s_trap /* LR & 0xff00 is exception # */ +CNAME(alisize) = .-CNAME(alitrap) + +/* + * Similar to the above for DSI + * Has to handle BAT spills + * and standard pagetable spills + */ + .globl CNAME(dsitrap),CNAME(dsisize) +CNAME(dsitrap): + mtsprg1 %r1 /* save SP */ + GET_CPUINFO(%r1) + stw %r28,(PC_DISISAVE+CPUSAVE_R28)(%r1) /* free r28-r31 */ + stw %r29,(PC_DISISAVE+CPUSAVE_R29)(%r1) + stw %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) + stw %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) + mfsprg1 %r1 /* restore SP */ + mfcr %r29 /* save CR */ + mfxer %r30 /* save XER */ + mtsprg2 %r30 /* in SPRG2 */ + mfsrr1 %r31 /* test kernel mode */ + mtcr %r31 + bt 17,1f /* branch if PSL_PR is set */ + mfdar %r31 /* get fault address */ + rlwinm %r31,%r31,7,25,28 /* get segment * 8 */ + + /* get batu */ + addis %r31,%r31,CNAME(battable)@ha + lwz %r30,CNAME(battable)@l(31) + mtcr %r30 + bf 30,1f /* branch if supervisor valid is + false */ + /* get batl */ + lwz %r31,CNAME(battable)+4@l(31) +/* We randomly use the highest two bat registers here */ + mftb %r28 + andi. %r28,%r28,1 + bne 2f + mtdbatu 2,%r30 + mtdbatl 2,%r31 + b 3f +2: + mtdbatu 3,%r30 + mtdbatl 3,%r31 +3: + mfsprg2 %r30 /* restore XER */ + mtxer %r30 + mtcr %r29 /* restore CR */ + mtsprg1 %r1 + GET_CPUINFO(%r1) + lwz %r28,(PC_DISISAVE+CPUSAVE_R28)(%r1) /* restore r28-r31 */ + lwz %r29,(PC_DISISAVE+CPUSAVE_R29)(%r1) + lwz %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) + lwz %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) + mfsprg1 %r1 + rfi /* return to trapped code */ +1: + mflr %r28 /* save LR (SP already saved) */ + bla disitrap +CNAME(dsisize) = .-CNAME(dsitrap) + +/* + * Preamble code for DSI/ISI traps + */ +disitrap: + GET_CPUINFO(%r1) + lwz %r30,(PC_DISISAVE+CPUSAVE_R28)(%r1) + stw %r30,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) + lwz %r31,(PC_DISISAVE+CPUSAVE_R29)(%r1) + stw %r31,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) + lwz %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) + stw %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) + lwz %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) + stw %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) + mfdar %r30 + mfdsisr %r31 + stw %r30,(PC_TEMPSAVE+CPUSAVE_DAR)(%r1) + stw %r31,(PC_TEMPSAVE+CPUSAVE_DSISR)(%r1) + +#ifdef KDB + /* Try and detect a kernel stack overflow */ + mfsrr1 %r31 + mtcr %r31 + bt 17,realtrap /* branch is user mode */ + mfsprg1 %r31 /* get old SP */ + sub. %r30,%r31,%r30 /* SP - DAR */ + bge 1f + neg %r30,%r30 /* modulo value */ +1: cmplwi %cr0,%r30,4096 /* is DAR within a page of SP? */ + bge %cr0,realtrap /* no, too far away. */ + + /* Now convert this DSI into a DDB trap. */ + GET_CPUINFO(%r1) + lwz %r30,(PC_TEMPSAVE+CPUSAVE_DAR)(%r1) /* get DAR */ + stw %r30,(PC_DBSAVE +CPUSAVE_DAR)(%r1) /* save DAR */ + lwz %r30,(PC_TEMPSAVE+CPUSAVE_DSISR)(%r1) /* get DSISR */ + lwz %r30,(PC_DBSAVE +CPUSAVE_DSISR)(%r1) /* save DSISR */ + lwz %r30,(PC_DISISAVE+CPUSAVE_R28)(%r1) /* get r28 */ + stw %r30,(PC_DBSAVE +CPUSAVE_R28)(%r1) /* save r28 */ + lwz %r31,(PC_DISISAVE+CPUSAVE_R29)(%r1) /* get r29 */ + stw %r31,(PC_DBSAVE +CPUSAVE_R29)(%r1) /* save r29 */ + lwz %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) /* get r30 */ + stw %r30,(PC_DBSAVE +CPUSAVE_R30)(%r1) /* save r30 */ + lwz %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) /* get r31 */ + stw %r31,(PC_DBSAVE +CPUSAVE_R31)(%r1) /* save r31 */ + lis %r1,dbstk+INTSTK@ha /* get new SP */ + addi %r1,%r1,dbstk+INTSTK@l + b dbtrap +#endif + + /* XXX need stack probe here */ +realtrap: +/* Test whether we already had PR set */ + mfsrr1 %r1 + mtcr %r1 + mfsprg1 %r1 /* restore SP (might have been + overwritten) */ +s_trap: + bf 17,k_trap /* branch if PSL_PR is false */ + GET_CPUINFO(%r1) +u_trap: + lwz %r1,PC_CURPCB(%r1) + RESTORE_KERN_SRS(%r30,%r31) /* enable kernel mapping */ + +/* + * Now the common trap catching code. + */ +k_trap: + FRAME_SETUP(PC_TEMPSAVE) +/* Call C interrupt dispatcher: */ +trapagain: + addi %r3,%r1,8 + bl CNAME(powerpc_interrupt) + .globl CNAME(trapexit) /* backtrace code sentinel */ +CNAME(trapexit): + +/* Disable interrupts: */ + mfmsr %r3 + andi. %r3,%r3,~PSL_EE@l + mtmsr %r3 +/* Test AST pending: */ + lwz %r5,FRAME_SRR1+8(%r1) + mtcr %r5 + bf 17,1f /* branch if PSL_PR is false */ + + GET_CPUINFO(%r3) /* get per-CPU pointer */ + lwz %r4, PC_CURTHREAD(%r3) /* deref to get curthread */ + lwz %r4, TD_FLAGS(%r4) /* get thread flags value */ + lis %r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@h + ori %r5,%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@l + and. %r4,%r4,%r5 + beq 1f + mfmsr %r3 /* re-enable interrupts */ + ori %r3,%r3,PSL_EE@l + mtmsr %r3 + isync + addi %r3,%r1,8 + bl CNAME(ast) + .globl CNAME(asttrapexit) /* backtrace code sentinel #2 */ +CNAME(asttrapexit): + b trapexit /* test ast ret value ? */ +1: + FRAME_LEAVE(PC_TEMPSAVE) + rfi + +/* + * Temporary: vector-unavailable traps are directed to vector-assist traps + */ + .globl CNAME(vectrap),CNAME(vectrapsize) +CNAME(vectrap): + ba EXC_VECAST +CNAME(vectrapsize) = .-CNAME(vectrap) + +#if defined(KDB) +/* + * Deliberate entry to dbtrap + */ + .globl CNAME(ppc_db_trap) +CNAME(ppc_db_trap): + mtsprg1 %r1 + mfmsr %r3 + mtsrr1 %r3 + andi. %r3,%r3,~(PSL_EE|PSL_ME)@l + mtmsr %r3 /* disable interrupts */ + isync + GET_CPUINFO(%r3) + stw %r28,(PC_DBSAVE+CPUSAVE_R28)(%r3) + stw %r29,(PC_DBSAVE+CPUSAVE_R29)(%r3) + stw %r30,(PC_DBSAVE+CPUSAVE_R30)(%r3) + stw %r31,(PC_DBSAVE+CPUSAVE_R31)(%r3) + mflr %r28 + li %r29,EXC_BPT + mtlr %r29 + mfcr %r29 + mtsrr0 %r28 + +/* + * Now the kdb trap catching code. + */ +dbtrap: + FRAME_SETUP(PC_DBSAVE) +/* Call C trap code: */ + addi %r3,%r1,8 + bl CNAME(db_trap_glue) + or. %r3,%r3,%r3 + bne dbleave +/* This wasn't for KDB, so switch to real trap: */ + lwz %r3,FRAME_EXC+8(%r1) /* save exception */ + GET_CPUINFO(%r4) + stw %r3,(PC_DBSAVE+CPUSAVE_R31)(%r4) + FRAME_LEAVE(PC_DBSAVE) + mtsprg1 %r1 /* prepare for entrance to realtrap */ + GET_CPUINFO(%r1) + stw %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) + stw %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) + stw %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) + stw %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) + mflr %r28 + mfcr %r29 + lwz %r31,(PC_DBSAVE+CPUSAVE_R31)(%r1) + mtlr %r31 + mfsprg1 %r1 + b realtrap +dbleave: + FRAME_LEAVE(PC_DBSAVE) + rfi + +/* + * In case of KDB we want a separate trap catcher for it + */ + .globl CNAME(dblow),CNAME(dbsize) +CNAME(dblow): + mtsprg1 %r1 /* save SP */ + mtsprg2 %r29 /* save r29 */ + mfcr %r29 /* save CR in r29 */ + mfsrr1 %r1 + mtcr %r1 + GET_CPUINFO(%r1) + bf 17,1f /* branch if privileged */ + stw %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1) /* free r28 */ + mfsprg2 %r28 /* r29 holds cr ... */ + stw %r28,(PC_TEMPSAVE+CPUSAVE_R29)(%r1) /* free r29 */ + stw %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1) /* free r30 */ + stw %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1) /* free r31 */ + mflr %r28 /* save LR */ + bla u_trap +1: + stw %r28,(PC_DBSAVE+CPUSAVE_R28)(%r1) /* free r28 */ + mfsprg2 %r28 /* r29 holds cr... */ + stw %r28,(PC_DBSAVE+CPUSAVE_R29)(%r1) /* free r29 */ + stw %r30,(PC_DBSAVE+CPUSAVE_R30)(%r1) /* free r30 */ + stw %r31,(PC_DBSAVE+CPUSAVE_R31)(%r1) /* free r31 */ + mflr %r28 /* save LR */ + lis %r1,dbstk+INTSTK@ha /* get new SP */ + addi %r1,%r1,dbstk+INTSTK@l + bla dbtrap +CNAME(dbsize) = .-CNAME(dblow) +#endif /* KDB */ diff --git a/sys/powerpc/powerpc/uio_machdep.c b/sys/powerpc/powerpc/uio_machdep.c new file mode 100644 index 000000000000..070ad9871c5d --- /dev/null +++ b/sys/powerpc/powerpc/uio_machdep.c @@ -0,0 +1,124 @@ +/*- + * Copyright (c) 2004 Alan L. Cox <alc@cs.rice.edu> + * Copyright (c) 1982, 1986, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/systm.h> +#include <sys/uio.h> + +#include <vm/vm.h> +#include <vm/vm_page.h> + +#include <machine/md_var.h> +#include <machine/vmparam.h> + +/* + * Implement uiomove(9) from physical memory using the direct map to + * avoid the creation and destruction of ephemeral mappings. + */ +int +uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio) +{ + struct thread *td = curthread; + struct iovec *iov; + void *cp; + vm_offset_t page_offset; + size_t cnt; + int error = 0; + int save = 0; + + KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, + ("uiomove_fromphys: mode")); + KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, + ("uiomove_fromphys proc")); + save = td->td_pflags & TDP_DEADLKTREAT; + td->td_pflags |= TDP_DEADLKTREAT; + while (n > 0 && uio->uio_resid) { + iov = uio->uio_iov; + cnt = iov->iov_len; + if (cnt == 0) { + uio->uio_iov++; + uio->uio_iovcnt--; + continue; + } + if (cnt > n) + cnt = n; + page_offset = offset & PAGE_MASK; + cnt = min(cnt, PAGE_SIZE - page_offset); + cp = (char *)VM_PAGE_TO_PHYS(ma[offset >> PAGE_SHIFT]) + + page_offset; + switch (uio->uio_segflg) { + case UIO_USERSPACE: + if (ticks - PCPU_GET(switchticks) >= hogticks) + uio_yield(); + if (uio->uio_rw == UIO_READ) + error = copyout(cp, iov->iov_base, cnt); + else + error = copyin(iov->iov_base, cp, cnt); + if (error) + goto out; + if (uio->uio_rw == UIO_WRITE && + pmap_page_executable(ma[offset >> PAGE_SHIFT])) + __syncicache(cp, cnt); + break; + case UIO_SYSSPACE: + if (uio->uio_rw == UIO_READ) + bcopy(cp, iov->iov_base, cnt); + else + bcopy(iov->iov_base, cp, cnt); + break; + case UIO_NOCOPY: + break; + } + iov->iov_base = (char *)iov->iov_base + cnt; + iov->iov_len -= cnt; + uio->uio_resid -= cnt; + uio->uio_offset += cnt; + offset += cnt; + n -= cnt; + } +out: + if (save == 0) + td->td_pflags &= ~TDP_DEADLKTREAT; + return (error); +} diff --git a/sys/powerpc/powerpc/uma_machdep.c b/sys/powerpc/powerpc/uma_machdep.c new file mode 100644 index 000000000000..89d092a00843 --- /dev/null +++ b/sys/powerpc/powerpc/uma_machdep.c @@ -0,0 +1,91 @@ +/*- + * Copyright (c) 2003 The FreeBSD Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 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> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/systm.h> +#include <sys/sysctl.h> +#include <vm/vm.h> +#include <vm/vm_page.h> +#include <vm/vm_pageout.h> +#include <vm/uma.h> +#include <vm/uma_int.h> +#include <machine/vmparam.h> + +static int hw_uma_mdpages; +SYSCTL_INT(_hw, OID_AUTO, uma_mdpages, CTLFLAG_RD, &hw_uma_mdpages, 0, + "UMA MD pages in use"); + +void * +uma_small_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait) +{ + static vm_pindex_t color; + void *va; + vm_page_t m; + int pflags; + + *flags = UMA_SLAB_PRIV; + if ((wait & (M_NOWAIT|M_USE_RESERVE)) == M_NOWAIT) + pflags = VM_ALLOC_INTERRUPT | VM_ALLOC_WIRED; + else + pflags = VM_ALLOC_SYSTEM | VM_ALLOC_WIRED; + if (wait & M_ZERO) + pflags |= VM_ALLOC_ZERO; + + for (;;) { + m = vm_page_alloc(NULL, color++, pflags | VM_ALLOC_NOOBJ); + if (m == NULL) { + if (wait & M_NOWAIT) + return (NULL); + VM_WAIT; + } else + break; + } + + va = (void *) VM_PAGE_TO_PHYS(m); + if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0) + bzero(va, PAGE_SIZE); + atomic_add_int(&hw_uma_mdpages, 1); + + return (va); +} + +void +uma_small_free(void *mem, int size, u_int8_t flags) +{ + vm_page_t m; + + m = PHYS_TO_VM_PAGE((u_int32_t)mem); + m->wire_count--; + vm_page_free(m); + atomic_subtract_int(&cnt.v_wire_count, 1); + atomic_subtract_int(&hw_uma_mdpages, 1); +} diff --git a/sys/powerpc/powerpc/vm_machdep.c b/sys/powerpc/powerpc/vm_machdep.c new file mode 100644 index 000000000000..1b58c1ec6b1d --- /dev/null +++ b/sys/powerpc/powerpc/vm_machdep.c @@ -0,0 +1,364 @@ +/*- + * Copyright (c) 1982, 1986 The Regents of the University of California. + * Copyright (c) 1989, 1990 William Jolitz + * Copyright (c) 1994 John Dyson + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Systems Programming Group of the University of Utah Computer + * Science Department, and William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 + * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ + * $FreeBSD$ + */ +/*- + * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/malloc.h> +#include <sys/bio.h> +#include <sys/buf.h> +#include <sys/ktr.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/vnode.h> +#include <sys/vmmeter.h> +#include <sys/kernel.h> +#include <sys/mbuf.h> +#include <sys/sf_buf.h> +#include <sys/sysctl.h> +#include <sys/unistd.h> + +#include <machine/cpu.h> +#include <machine/fpu.h> +#include <machine/frame.h> +#include <machine/md_var.h> +#include <machine/pcb.h> +#include <machine/powerpc.h> + +#include <dev/ofw/openfirm.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/vm_kern.h> +#include <vm/vm_page.h> +#include <vm/vm_map.h> +#include <vm/vm_extern.h> + +/* + * Finish a fork operation, with process p2 nearly set up. + * Copy and update the pcb, set up the stack so that the child + * ready to run and return to user mode. + */ +void +cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags) +{ + struct proc *p1; + struct trapframe *tf; + struct callframe *cf; + struct pcb *pcb; + + KASSERT(td1 == curthread || td1 == &thread0, + ("cpu_fork: p1 not curproc and not proc0")); + CTR3(KTR_PROC, "cpu_fork: called td1=%08x p2=%08x flags=%x", (u_int)td1, (u_int)p2, flags); + + if ((flags & RFPROC) == 0) + return; + + p1 = td1->td_proc; + + pcb = (struct pcb *)((td2->td_kstack + + td2->td_kstack_pages * PAGE_SIZE - sizeof(struct pcb)) & ~0x2fU); + td2->td_pcb = pcb; + + /* Copy the pcb */ + bcopy(td1->td_pcb, pcb, sizeof(struct pcb)); + + /* + * Create a fresh stack for the new process. + * Copy the trap frame for the return to user mode as if from a + * syscall. This copies most of the user mode register values. + */ + tf = (struct trapframe *)pcb - 1; + bcopy(td1->td_frame, tf, sizeof(*tf)); + + /* Set up trap frame. */ + tf->fixreg[FIRSTARG] = 0; + tf->fixreg[FIRSTARG + 1] = 0; + tf->cr &= ~0x10000000; + + td2->td_frame = tf; + + cf = (struct callframe *)tf - 1; + memset(cf, 0, sizeof(struct callframe)); + cf->cf_func = (register_t)fork_return; + cf->cf_arg0 = (register_t)td2; + cf->cf_arg1 = (register_t)tf; + + pcb->pcb_sp = (register_t)cf; + pcb->pcb_lr = (register_t)fork_trampoline; + pcb->pcb_usr = kernel_pmap->pm_sr[USER_SR]; + + /* Setup to release spin count in fork_exit(). */ + td2->td_md.md_spinlock_count = 1; + td2->td_md.md_saved_msr = PSL_KERNSET; + + /* + * Now cpu_switch() can schedule the new process. + */ +} + +/* + * Intercept the return address from a freshly forked process that has NOT + * been scheduled yet. + * + * This is needed to make kernel threads stay in kernel mode. + */ +void +cpu_set_fork_handler(td, func, arg) + struct thread *td; + void (*func)(void *); + void *arg; +{ + struct callframe *cf; + + CTR3(KTR_PROC, "cpu_set_fork_handler: called with td=%08x func=%08x arg=%08x", + (u_int)td, (u_int)func, (u_int)arg); + + cf = (struct callframe *)td->td_pcb->pcb_sp; + + cf->cf_func = (register_t)func; + cf->cf_arg0 = (register_t)arg; +} + +void +cpu_exit(td) + register struct thread *td; +{ +} + +/* Temporary helper */ +void +cpu_throw(struct thread *old, struct thread *new) +{ + + cpu_switch(old, new, NULL); + panic("cpu_throw() didn't"); +} + +/* + * Reset back to firmware. + */ +void +cpu_reset() +{ + OF_reboot(); +} + +/* + * Allocate an sf_buf for the given vm_page. On this machine, however, there + * is no sf_buf object. Instead, an opaque pointer to the given vm_page is + * returned. + */ +struct sf_buf * +sf_buf_alloc(struct vm_page *m, int pri) +{ + + return ((struct sf_buf *)m); +} + +/* + * Free the sf_buf. In fact, do nothing because there are no resources + * associated with the sf_buf. + */ +void +sf_buf_free(struct sf_buf *sf) +{ +} + +/* + * Software interrupt handler for queued VM system processing. + */ +void +swi_vm(void *dummy) +{ +#if 0 /* XXX: Don't have busdma stuff yet */ + if (busdma_swi_pending != 0) + busdma_swi(); +#endif +} + +/* + * Tell whether this address is in some physical memory region. + * Currently used by the kernel coredump code in order to avoid + * dumping the ``ISA memory hole'' which could cause indefinite hangs, + * or other unpredictable behaviour. + */ + + +int +is_physical_memory(addr) + vm_offset_t addr; +{ + /* + * stuff other tests for known memory-mapped devices (PCI?) + * here + */ + + return 1; +} + +/* + * KSE functions + */ +void +cpu_thread_exit(struct thread *td) +{ +} + +void +cpu_thread_clean(struct thread *td) +{ +} + +void +cpu_thread_setup(struct thread *td) +{ + struct pcb *pcb; + + pcb = (struct pcb *)((td->td_kstack + td->td_kstack_pages * PAGE_SIZE - + sizeof(struct pcb)) & ~0x2fU); + td->td_pcb = pcb; + td->td_frame = (struct trapframe *)pcb - 1; +} + +void +cpu_thread_swapin(struct thread *td) +{ +} + +void +cpu_thread_swapout(struct thread *td) +{ +} + +void +cpu_set_upcall(struct thread *td, struct thread *td0) +{ + struct pcb *pcb2; + struct trapframe *tf; + struct callframe *cf; + + pcb2 = td->td_pcb; + + /* Copy the upcall pcb */ + bcopy(td0->td_pcb, pcb2, sizeof(*pcb2)); + + /* Create a stack for the new thread */ + tf = td->td_frame; + bcopy(td0->td_frame, tf, sizeof(struct trapframe)); + tf->fixreg[FIRSTARG] = 0; + tf->fixreg[FIRSTARG + 1] = 0; + tf->cr &= ~0x10000000; + + /* Set registers for trampoline to user mode. */ + cf = (struct callframe *)tf - 1; + memset(cf, 0, sizeof(struct callframe)); + cf->cf_func = (register_t)fork_return; + cf->cf_arg0 = (register_t)td; + cf->cf_arg1 = (register_t)tf; + + pcb2->pcb_sp = (register_t)cf; + pcb2->pcb_lr = (register_t)fork_trampoline; + pcb2->pcb_usr = kernel_pmap->pm_sr[USER_SR]; + + /* Setup to release spin count in fork_exit(). */ + td->td_md.md_spinlock_count = 1; + td->td_md.md_saved_msr = PSL_KERNSET; +} + +void +cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg, + stack_t *stack) +{ + struct trapframe *tf; + uint32_t sp; + + tf = td->td_frame; + /* align stack and alloc space for frame ptr and saved LR */ + sp = ((uint32_t)stack->ss_sp + stack->ss_size + - 2*sizeof(u_int32_t)) & ~0x1f; + bzero(tf, sizeof(struct trapframe)); + + tf->fixreg[1] = (register_t)sp; + tf->fixreg[3] = (register_t)arg; + tf->srr0 = (register_t)entry; + tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT; + td->td_pcb->pcb_flags = 0; + + td->td_retval[0] = (register_t)entry; + td->td_retval[1] = 0; +} + +int +cpu_set_user_tls(struct thread *td, void *tls_base) +{ + + td->td_frame->fixreg[2] = (register_t)tls_base + 0x7008; + return (0); +} diff --git a/sys/powerpc/psim/ata_iobus.c b/sys/powerpc/psim/ata_iobus.c new file mode 100644 index 000000000000..f9b4a56ba361 --- /dev/null +++ b/sys/powerpc/psim/ata_iobus.c @@ -0,0 +1,257 @@ +/*- + * Copyright 2002 by Peter Grehan. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * PSIM local bus ATA controller + */ +#include "opt_ata.h" +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/malloc.h> +#include <sys/sema.h> +#include <sys/taskqueue.h> +#include <machine/stdarg.h> +#include <vm/uma.h> +#include <machine/resource.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <sys/ata.h> +#include <dev/ata/ata-all.h> +#include <ata_if.h> + +#include <dev/ofw/openfirm.h> +#include <powerpc/psim/iobusvar.h> + +/* + * Define the iobus ata bus attachment. This creates a pseudo-bus that + * the ATA device can be attached to + */ +static int ata_iobus_attach(device_t dev); +static int ata_iobus_probe(device_t dev); +static int ata_iobus_print_child(device_t dev, device_t child); +struct resource *ata_iobus_alloc_resource(device_t, device_t, int, int *, + u_long, u_long, u_long, u_int); +static int ata_iobus_release_resource(device_t, device_t, int, int, + struct resource *); + +static device_method_t ata_iobus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ata_iobus_probe), + DEVMETHOD(device_attach, ata_iobus_attach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* Bus methods */ + DEVMETHOD(bus_print_child, ata_iobus_print_child), + DEVMETHOD(bus_alloc_resource, ata_iobus_alloc_resource), + DEVMETHOD(bus_release_resource, ata_iobus_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t ata_iobus_driver = { + "ataiobus", + ata_iobus_methods, + 0, +}; + +static devclass_t ata_iobus_devclass; + +DRIVER_MODULE(ataiobus, iobus, ata_iobus_driver, ata_iobus_devclass, 0, 0); +MODULE_DEPEND(ata, ata, 1, 1, 1); + +static int +ata_iobus_probe(device_t dev) +{ + char *type = iobus_get_name(dev); + + if (strncmp(type, "ata", 3) != 0) + return (ENXIO); + + device_set_desc(dev, "PSIM ATA Controller"); + return (0); +} + + +static int +ata_iobus_attach(device_t dev) +{ + /* + * Add a single child per controller. Should be able + * to add two + */ + device_add_child(dev, "ata", + devclass_find_free_unit(ata_devclass, 0)); + + return (bus_generic_attach(dev)); +} + + +static int +ata_iobus_print_child(device_t dev, device_t child) +{ + int retval = 0; + + retval += bus_print_child_header(dev, child); + /* irq ? */ + retval += bus_print_child_footer(dev, child); + + return (retval); +} + + +struct resource * +ata_iobus_alloc_resource(device_t dev, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct resource *res = NULL; + int myrid; + u_int *ofw_regs; + + ofw_regs = iobus_get_regs(dev); + + /* + * The reg array for the PSIM ata device has 6 start/size entries: + * 0 - unused + * 1/2/3 - unused + * 4/5/6 - primary command + * 7/8/9 - secondary command + * 10/11/12 - primary control + * 13/14/15 - secondary control + * 16/17/18 - primary/secondary dma registers, unimplemented + * + * The resource values are calculated from these registers + */ + if (type == SYS_RES_IOPORT) { + switch (*rid) { + case ATA_IOADDR_RID: + myrid = 0; + start = ofw_regs[4]; + end = start + ATA_IOSIZE - 1; + count = ATA_IOSIZE; + res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, + SYS_RES_MEMORY, &myrid, + start, end, count, flags); + break; + + case ATA_CTLADDR_RID: + myrid = 0; + start = ofw_regs[10]; + end = start + ATA_CTLIOSIZE - 1; + count = ATA_CTLIOSIZE; + res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, + SYS_RES_MEMORY, &myrid, + start, end, count, flags); + break; + + case ATA_BMADDR_RID: + /* DMA not properly supported by psim */ + break; + } + return (res); + + } else if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) { + /* + * Pass this on to the parent + */ + return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, + SYS_RES_IRQ, rid, 0, ~0, 1, flags)); + + } else { + return (NULL); + } +} + + +static int +ata_iobus_release_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + /* no hotplug... */ + return (0); +} + + +/* + * Define the actual ATA device. This is a sub-bus to the ata-iobus layer + * to allow the higher layer bus to massage the resource allocation. + */ + +static int ata_iobus_sub_probe(device_t dev); +static void ata_iobus_sub_setmode(device_t parent, device_t dev); + +static device_method_t ata_iobus_sub_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ata_iobus_sub_probe), + DEVMETHOD(device_attach, ata_attach), + DEVMETHOD(device_detach, ata_detach), + DEVMETHOD(device_resume, ata_resume), + + /* ATA interface */ + DEVMETHOD(ata_setmode, ata_iobus_sub_setmode), + { 0, 0 } +}; + +static driver_t ata_iobus_sub_driver = { + "ata", + ata_iobus_sub_methods, + sizeof(struct ata_channel), +}; + +DRIVER_MODULE(ata, ataiobus, ata_iobus_sub_driver, ata_devclass, 0, 0); + +static int +ata_iobus_sub_probe(device_t dev) +{ + struct ata_channel *ch = device_get_softc(dev); + + /* Only a single unit per controller thus far */ + ch->unit = 0; + ch->flags = (ATA_USE_16BIT|ATA_NO_SLAVE); + ata_generic_hw(dev); + + return ata_probe(dev); +} + +static void +ata_iobus_sub_setmode(device_t parent, device_t dev) +{ + struct ata_device *atadev = device_get_softc(dev); + + /* Only ever PIO mode here... */ + atadev->mode = ATA_PIO; +} diff --git a/sys/powerpc/psim/iobus.c b/sys/powerpc/psim/iobus.c new file mode 100644 index 000000000000..30cbeed7cedf --- /dev/null +++ b/sys/powerpc/psim/iobus.c @@ -0,0 +1,416 @@ +/*- + * Copyright 2002 by Peter Grehan. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * PSIM 'iobus' local bus. Should be set up in the device tree like: + * + * /iobus@0x80000000/name psim-iobus + * + * Code borrowed from various nexus.c and uninorth.c :-) + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <machine/bus.h> +#include <sys/rman.h> + +#include <dev/ofw/openfirm.h> + +#include <machine/vmparam.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <machine/pmap.h> + +#include <machine/resource.h> +#include <machine/nexusvar.h> + +#include <powerpc/psim/iobusvar.h> + +struct iobus_softc { + phandle_t sc_node; + vm_offset_t sc_addr; + vm_offset_t sc_size; + struct rman sc_mem_rman; +}; + +static MALLOC_DEFINE(M_IOBUS, "iobus", "iobus device information"); + +static int iobus_probe(device_t); +static int iobus_attach(device_t); +static int iobus_print_child(device_t dev, device_t child); +static void iobus_probe_nomatch(device_t, device_t); +static int iobus_read_ivar(device_t, device_t, int, uintptr_t *); +static int iobus_write_ivar(device_t, device_t, int, uintptr_t); +static struct resource *iobus_alloc_resource(device_t, device_t, int, int *, + u_long, u_long, u_long, u_int); +static int iobus_activate_resource(device_t, device_t, int, int, + struct resource *); +static int iobus_deactivate_resource(device_t, device_t, int, int, + struct resource *); +static int iobus_release_resource(device_t, device_t, int, int, + struct resource *); + +/* + * Bus interface definition + */ +static device_method_t iobus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, iobus_probe), + DEVMETHOD(device_attach, iobus_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* Bus interface */ + DEVMETHOD(bus_print_child, iobus_print_child), + DEVMETHOD(bus_probe_nomatch, iobus_probe_nomatch), + DEVMETHOD(bus_read_ivar, iobus_read_ivar), + DEVMETHOD(bus_write_ivar, iobus_write_ivar), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + DEVMETHOD(bus_alloc_resource, iobus_alloc_resource), + DEVMETHOD(bus_release_resource, iobus_release_resource), + DEVMETHOD(bus_activate_resource, iobus_activate_resource), + DEVMETHOD(bus_deactivate_resource, iobus_deactivate_resource), + + { 0, 0 } +}; + +static driver_t iobus_driver = { + "iobus", + iobus_methods, + sizeof(struct iobus_softc) +}; + +devclass_t iobus_devclass; + +DRIVER_MODULE(iobus, nexus, iobus_driver, iobus_devclass, 0, 0); + +static int +iobus_probe(device_t dev) +{ + char *type = nexus_get_name(dev); + + if (strcmp(type, "psim-iobus") != 0) + return (ENXIO); + + device_set_desc(dev, "PSIM local bus"); + return (0); +} + +/* + * Add interrupt/addr range to the dev's resource list if present + */ +static void +iobus_add_intr(phandle_t devnode, struct iobus_devinfo *dinfo) +{ + u_int intr = -1; + + if (OF_getprop(devnode, "interrupt", &intr, sizeof(intr)) != -1) { + resource_list_add(&dinfo->id_resources, + SYS_RES_IRQ, 0, intr, intr, 1); + } + dinfo->id_interrupt = intr; +} + + +static void +iobus_add_reg(phandle_t devnode, struct iobus_devinfo *dinfo, + vm_offset_t iobus_off) +{ + u_int size; + int i; + + size = OF_getprop(devnode, "reg", dinfo->id_reg,sizeof(dinfo->id_reg)); + + if (size != -1) { + dinfo->id_nregs = size / (sizeof(dinfo->id_reg[0])); + + for (i = 0; i < dinfo->id_nregs; i+= 3) { + /* + * Scale the absolute addresses back to iobus + * relative offsets. This is to better simulate + * macio + */ + dinfo->id_reg[i+1] -= iobus_off; + + resource_list_add(&dinfo->id_resources, + SYS_RES_MEMORY, 0, + dinfo->id_reg[i+1], + dinfo->id_reg[i+1] + + dinfo->id_reg[i+2], + dinfo->id_reg[i+2]); + } + } +} + + +static int +iobus_attach(device_t dev) +{ + struct iobus_softc *sc; + struct iobus_devinfo *dinfo; + phandle_t root; + phandle_t child; + device_t cdev; + char *name; + u_int reg[2]; + int size; + + sc = device_get_softc(dev); + sc->sc_node = nexus_get_node(dev); + + /* + * Find the base addr/size of the iobus, and initialize the + * resource manager + */ + size = OF_getprop(sc->sc_node, "reg", reg, sizeof(reg)); + if (size == sizeof(reg)) { + sc->sc_addr = reg[0]; + sc->sc_size = reg[1]; + } else { + return (ENXIO); + } + + sc->sc_mem_rman.rm_type = RMAN_ARRAY; + sc->sc_mem_rman.rm_descr = "IOBus Device Memory"; + if (rman_init(&sc->sc_mem_rman) != 0) { + device_printf(dev, + "failed to init mem range resources\n"); + return (ENXIO); + } + rman_manage_region(&sc->sc_mem_rman, 0, sc->sc_size); + + /* + * Iterate through the sub-devices + */ + root = sc->sc_node; + + for (child = OF_child(root); child != 0; child = OF_peer(child)) { + OF_getprop_alloc(child, "name", 1, (void **)&name); + + cdev = device_add_child(dev, NULL, -1); + if (cdev != NULL) { + dinfo = malloc(sizeof(*dinfo), M_IOBUS, M_WAITOK); + memset(dinfo, 0, sizeof(*dinfo)); + resource_list_init(&dinfo->id_resources); + dinfo->id_node = child; + dinfo->id_name = name; + iobus_add_intr(child, dinfo); + iobus_add_reg(child, dinfo, sc->sc_addr); + device_set_ivars(cdev, dinfo); + } else { + free(name, M_OFWPROP); + } + } + + return (bus_generic_attach(dev)); +} + + +static int +iobus_print_child(device_t dev, device_t child) +{ + struct iobus_devinfo *dinfo; + struct resource_list *rl; + int retval = 0; + + dinfo = device_get_ivars(child); + rl = &dinfo->id_resources; + + retval += bus_print_child_header(dev, child); + + retval += printf(" offset 0x%x", dinfo->id_reg[1]); + retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld"); + + retval += bus_print_child_footer(dev, child); + + return (retval); +} + + +static void +iobus_probe_nomatch(device_t dev, device_t child) +{ +} + + +static int +iobus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct iobus_devinfo *dinfo; + + if ((dinfo = device_get_ivars(child)) == 0) + return (ENOENT); + + switch (which) { + case IOBUS_IVAR_NODE: + *result = dinfo->id_node; + break; + case IOBUS_IVAR_NAME: + *result = (uintptr_t)dinfo->id_name; + break; + case IOBUS_IVAR_NREGS: + *result = dinfo->id_nregs; + break; + case IOBUS_IVAR_REGS: + *result = (uintptr_t)dinfo->id_reg; + break; + default: + return (ENOENT); + } + + return (0); +} + + +static int +iobus_write_ivar(device_t dev, device_t child, int which, uintptr_t value) +{ + return (EINVAL); +} + + +static struct resource * +iobus_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct iobus_softc *sc; + int needactivate; + struct resource *rv; + struct rman *rm; + bus_space_tag_t tagval; + + sc = device_get_softc(bus); + + needactivate = flags & RF_ACTIVE; + flags &= ~RF_ACTIVE; + + switch (type) { + case SYS_RES_MEMORY: + case SYS_RES_IOPORT: + rm = &sc->sc_mem_rman; + tagval = PPC_BUS_SPACE_MEM; + break; + case SYS_RES_IRQ: + return (bus_alloc_resource(bus, type, rid, start, end, count, + flags)); + break; + default: + device_printf(bus, "unknown resource request from %s\n", + device_get_nameunit(child)); + return (NULL); + } + + rv = rman_reserve_resource(rm, start, end, count, flags, child); + if (rv == NULL) { + device_printf(bus, "failed to reserve resource for %s\n", + device_get_nameunit(child)); + return (NULL); + } + + rman_set_rid(rv, *rid); + rman_set_bustag(rv, tagval); + rman_set_bushandle(rv, rman_get_start(rv)); + + if (needactivate) { + if (bus_activate_resource(child, type, *rid, rv) != 0) { + device_printf(bus, + "failed to activate resource for %s\n", + device_get_nameunit(child)); + rman_release_resource(rv); + return (NULL); + } + } + + return (rv); +} + + +static int +iobus_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + if (rman_get_flags(res) & RF_ACTIVE) { + int error = bus_deactivate_resource(child, type, rid, res); + if (error) + return error; + } + + return (rman_release_resource(res)); +} + + +static int +iobus_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + struct iobus_softc *sc; + void *p; + + sc = device_get_softc(bus); + + if (type == SYS_RES_IRQ) + return (bus_activate_resource(bus, type, rid, res)); + + if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { + p = pmap_mapdev((vm_offset_t)rman_get_start(res) + sc->sc_addr, + (vm_size_t)rman_get_size(res)); + if (p == NULL) + return (ENOMEM); + rman_set_virtual(res, p); + rman_set_bushandle(res, (u_long)p); + } + + return (rman_activate_resource(res)); +} + + +static int +iobus_deactivate_resource(device_t bus, device_t child, int type, int rid, + struct resource *res) +{ + /* + * If this is a memory resource, unmap it. + */ + if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { + u_int32_t psize; + + psize = rman_get_size(res); + pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize); + } + + return (rman_deactivate_resource(res)); +} diff --git a/sys/powerpc/psim/iobusvar.h b/sys/powerpc/psim/iobusvar.h new file mode 100644 index 000000000000..1ab7f7eaed90 --- /dev/null +++ b/sys/powerpc/psim/iobusvar.h @@ -0,0 +1,66 @@ +/*- + * Copyright 2002 by Peter Grehan. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _PSIM_IOBUSVAR_H_ +#define _PSIM_IOBUSVAR_H_ + +/* + * Accessors for iobus devices + */ + +enum iobus_ivars { + IOBUS_IVAR_NODE, + IOBUS_IVAR_NAME, + IOBUS_IVAR_NREGS, + IOBUS_IVAR_REGS, +}; + +#define IOBUS_ACCESSOR(var, ivar, type) \ + __BUS_ACCESSOR(iobus, var, IOBUS, ivar, type) + +IOBUS_ACCESSOR(node, NODE, phandle_t) +IOBUS_ACCESSOR(name, NAME, char *) +IOBUS_ACCESSOR(nregs, NREGS, u_int) +IOBUS_ACCESSOR(regs, REGS, u_int *) + +#undef IOBUS_ACCESSOR + +/* + * Per-device structure. + */ +struct iobus_devinfo { + phandle_t id_node; + char *id_name; + int id_interrupt; + u_int id_nregs; + u_int id_reg[24]; + struct resource_list id_resources; +}; + +#endif /* _PSIM_IOBUSVAR_H_ */ diff --git a/sys/powerpc/psim/openpic_iobus.c b/sys/powerpc/psim/openpic_iobus.c new file mode 100644 index 000000000000..a3a69d318c2d --- /dev/null +++ b/sys/powerpc/psim/openpic_iobus.c @@ -0,0 +1,106 @@ +/*- + * Copyright 2003 by Peter Grehan. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * The psim iobus attachment for the OpenPIC interrupt controller. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> + +#include <dev/ofw/openfirm.h> + +#include <machine/bus.h> +#include <machine/intr.h> +#include <machine/intr_machdep.h> +#include <machine/md_var.h> +#include <machine/nexusvar.h> +#include <machine/pio.h> +#include <machine/resource.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <sys/rman.h> + +#include <machine/openpicvar.h> +#include <powerpc/psim/iobusvar.h> + +#include "pic_if.h" + +/* + * PSIM IOBus interface + */ +static int openpic_iobus_probe(device_t); + +static device_method_t openpic_iobus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, openpic_iobus_probe), + DEVMETHOD(device_attach, openpic_attach), + + /* PIC interface */ + DEVMETHOD(pic_dispatch, openpic_dispatch), + DEVMETHOD(pic_enable, openpic_enable), + DEVMETHOD(pic_eoi, openpic_eoi), + DEVMETHOD(pic_mask, openpic_mask), + DEVMETHOD(pic_unmask, openpic_unmask), + + { 0, 0 } +}; + +static driver_t openpic_iobus_driver = { + "openpic", + openpic_iobus_methods, + sizeof(struct openpic_softc) +}; + +DRIVER_MODULE(openpic, iobus, openpic_iobus_driver, openpic_devclass, 0, 0); + +static int +openpic_iobus_probe(device_t dev) +{ + char *name; + + name = iobus_get_name(dev); + if (strcmp(name, "interrupt-controller") != 0) + return (ENXIO); + + /* + * The description was already printed out in the nexus + * probe, so don't do it again here + */ + device_set_desc(dev, OPENPIC_DEVSTR); + return (0); +} diff --git a/sys/powerpc/psim/psim-tree b/sys/powerpc/psim/psim-tree new file mode 100644 index 000000000000..62391c5ed950 --- /dev/null +++ b/sys/powerpc/psim/psim-tree @@ -0,0 +1,90 @@ +# $FreeBSD$ +# +# Simple psim h/w description +# +# The .gdbinit should contain something like: +# +# target sim -e chirp -r 33554432 -f psim-tree +# load +# +# (The -r option is the amount of physical RAM the simulator has) +# + +/#address-cells 1 +/openprom/options/use-stdio? false +#/openprom/options/strict-alignment? true + +/options + ./output-device "psim-stdout + +# +# Define the disk device alias so ofwd can identify it +# +/aliases + ./ofwdisk "/phb@0x70000000/ide@1/disk@0 + +# +# CPU definition. The phandle property is to help nexus.c locate the +# interrupt controller. +# +/cpus/cpu@0 + +# +# disk file, done via phb. maybe there's a simpler way. +# +/phb@0x70000000 + ./device_type "pci + ./name "pci + ./#address-cells 3 + ./#size-cells 2 + ./ranges ni0,0,0,0 0xc0000000 0x10000 + +/phb@0x70000000/ide@1 + ./device_type "ide + ./name "ide + ./assigned-addresses \ + ni0,0,10,1f0 8 \ + ni0,0,14,3f8 8 \ + ni0,0,18,170 8 \ + ni0,0,1c,378 8 \ + ni0,0,20,200 8 + ./reg \ + 1 0 \ + i0,0,10,0 8 \ + i0,0,18,0 8 \ + i0,0,14,6 1 \ + i0,0,1c,6 1 \ + i0,0,20,0 8 + ./ready-delay 1000 + +/phb@0x70000000/ide@1/disk@0/file "../image.iso + +# +# I/O Bus +# +/iobus@0x90000000 + ./name psim-iobus + ./reg 0x90000000 0x20000000 + +# +# OpenPIC +# +/iobus@0x90000000/opic@0x90000000 + ./name interrupt-controller + ./device_type open-pic + ./compatible psim,open-pic + ./reg 0x90000000 0x40000 + ./interrupt-ranges 0 256 + +/iobus/opic > intr0 int /cpus/cpu@0x0 + +# +# IDE1 +# +#/iobus@0x90000000/ide@0x90052000 +# ./name ata-4 +# ./ioport 1 +# ./device_type ata +# ./interrupt 12 +# ./reg 0x90052000 8 0x90052010 8 0x90052020 8 0x90052030 1 0x90052040 1 0x90052050 8 +#/iobus@0x90000000/ide@0x90052000 > a irq12 /iobus/opic diff --git a/sys/powerpc/psim/uart_iobus.c b/sys/powerpc/psim/uart_iobus.c new file mode 100644 index 000000000000..1768338b9952 --- /dev/null +++ b/sys/powerpc/psim/uart_iobus.c @@ -0,0 +1,87 @@ +/*- + * Copyright 2002 by Peter Grehan. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * PSIM local bus 16550 + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/module.h> +#include <sys/tty.h> +#include <machine/bus.h> +#include <sys/timepps.h> + +#include <dev/ofw/openfirm.h> +#include <powerpc/psim/iobusvar.h> + +#include <dev/uart/uart.h> +#include <dev/uart/uart_bus.h> + +static int uart_iobus_probe(device_t dev); + +static device_method_t uart_iobus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, uart_iobus_probe), + DEVMETHOD(device_attach, uart_bus_attach), + DEVMETHOD(device_detach, uart_bus_detach), + + { 0, 0 } +}; + +static driver_t uart_iobus_driver = { + uart_driver_name, + uart_iobus_methods, + sizeof(struct uart_softc), +}; + +static int +uart_iobus_probe(device_t dev) +{ + struct uart_softc *sc; + char *type; + + type = iobus_get_name(dev); + if (strncmp(type, "com", 3) != 0) + return (ENXIO); + + sc = device_get_softc(dev); + sc->sc_class = &uart_ns8250_class; + + device_set_desc(dev, "PSIM serial port"); + return (uart_bus_probe(dev, 0, 0, 0, 0)); +} + +DRIVER_MODULE(uart, iobus, uart_iobus_driver, uart_devclass, 0, 0); |
